Commit bbfbfd08 authored by Alexandre Julliard's avatar Alexandre Julliard

gphoto2.ds: Move libgphoto2 handling to a separate Unix library.

parent 929e2a54
MODULE = gphoto2.ds
UNIXLIB = gphoto2.so
IMPORTS = comctl32 user32 gdi32 advapi32
EXTRALIBS = $(GPHOTO2_LIBS) $(GPHOTO2_PORT_LIBS)
EXTRAINCL = $(GPHOTO2_CFLAGS) $(GPHOTO2_PORT_CFLAGS) $(JPEG_CFLAGS)
......@@ -9,6 +10,7 @@ C_SRCS = \
capability.c \
ds_image.c \
gphoto2_main.c \
ui.c
ui.c \
unixlib.c
RC_SRCS = gphoto2.rc
......@@ -27,6 +27,7 @@
#include "gphoto2_i.h"
#include "wingdi.h"
#include "winuser.h"
#include "unixlib.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(twain);
......@@ -85,6 +86,19 @@ static boolean _jpeg_resync_to_restart(j_decompress_ptr cinfo, int desired) {
}
static void _jpeg_term_source(j_decompress_ptr cinfo) { }
static void close_file( void *handle )
{
struct close_file_params params = { handle };
GPHOTO2_CALL( close_file, &params );
}
static void close_current_file(void)
{
close_file( activeDS.file_handle );
activeDS.file_handle = NULL;
free( activeDS.file_data );
}
/* DG_IMAGE/DAT_CIECOLOR/MSG_GET */
TW_UINT16 GPHOTO2_CIEColorGet (pTW_IDENTITY pOrigin,
TW_MEMREF pData)
......@@ -131,45 +145,52 @@ TW_UINT16 GPHOTO2_ImageFileXferGet (pTW_IDENTITY pOrigin,
}
static TW_UINT16 _get_image_and_startup_jpeg(void) {
const char *folder = NULL, *filename = NULL;
struct gphoto2_file *file;
const unsigned char *filedata;
unsigned long filesize;
#ifdef SONAME_LIBJPEG
unsigned int i;
int ret;
struct open_file_params open_params;
struct get_file_data_params get_data_params;
if (activeDS.file) /* Already loaded. */
if (activeDS.file_handle) /* Already loaded. */
return TWRC_SUCCESS;
if(!libjpeg_handle) {
if(!load_libjpeg()) {
FIXME("Failed reading JPEG because unable to find %s\n", SONAME_LIBJPEG);
filedata = NULL;
return TWRC_FAILURE;
}
}
LIST_FOR_EACH_ENTRY( file, &activeDS.files, struct gphoto2_file, entry ) {
if (strstr(file->filename,".JPG") || strstr(file->filename,".jpg")) {
filename = file->filename;
folder = file->folder;
TRACE("downloading %s/%s\n", folder, filename);
if (file->download) {
file->download = FALSE; /* mark as done */
break;
}
for (i = 0; i < activeDS.file_count; i++)
{
if (activeDS.download_flags[i])
{
activeDS.download_flags[i] = FALSE; /* mark as done */
break;
}
}
gp_file_new (&activeDS.file);
ret = gp_camera_file_get(activeDS.camera, folder, filename, GP_FILE_TYPE_NORMAL,
activeDS.file, activeDS.context);
if (ret < GP_OK) {
FIXME("Failed to get file?\n");
if (i == activeDS.file_count)
{
activeDS.twCC = TWCC_SEQERROR;
return TWRC_FAILURE;
}
open_params.idx = i;
open_params.preview = FALSE;
open_params.handle = &activeDS.file_handle;
open_params.size = &activeDS.file_size;
if (GPHOTO2_CALL( open_file, &open_params ))
{
activeDS.twCC = TWCC_SEQERROR;
return TWRC_FAILURE;
}
ret = gp_file_get_data_and_size (activeDS.file, (const char**)&filedata, &filesize);
if (ret < GP_OK) {
FIXME("Failed to get file data?\n");
activeDS.file_data = malloc( activeDS.file_size );
get_data_params.handle = activeDS.file_handle;
get_data_params.data = activeDS.file_data;
get_data_params.size = activeDS.file_size;
if (GPHOTO2_CALL( get_file_data, &get_data_params ))
{
activeDS.twCC = TWCC_SEQERROR;
return TWRC_FAILURE;
}
......@@ -177,8 +198,8 @@ static TW_UINT16 _get_image_and_startup_jpeg(void) {
/* This is basically so we can use in-memory data for jpeg decompression.
* We need to have all the functions.
*/
activeDS.xjsm.next_input_byte = filedata;
activeDS.xjsm.bytes_in_buffer = filesize;
activeDS.xjsm.next_input_byte = activeDS.file_data;
activeDS.xjsm.bytes_in_buffer = activeDS.file_size;
activeDS.xjsm.init_source = _jpeg_init_source;
activeDS.xjsm.fill_input_buffer = _jpeg_fill_input_buffer;
activeDS.xjsm.skip_input_data = _jpeg_skip_input_data;
......@@ -195,8 +216,7 @@ static TW_UINT16 _get_image_and_startup_jpeg(void) {
pjpeg_start_decompress(&activeDS.jd);
if (ret != JPEG_HEADER_OK) {
ERR("Jpeg image in stream has bad format, read header returned %d.\n",ret);
gp_file_unref (activeDS.file);
activeDS.file = NULL;
close_current_file();
return TWRC_FAILURE;
}
return TWRC_SUCCESS;
......@@ -308,7 +328,7 @@ TW_UINT16 GPHOTO2_ImageMemXferGet (pTW_IDENTITY pOrigin,
activeDS.currentState = 7;
} else {
if (!activeDS.file) {
if (!activeDS.file_handle) {
activeDS.twCC = TWRC_SUCCESS;
return TWRC_XFERDONE;
}
......@@ -347,8 +367,7 @@ TW_UINT16 GPHOTO2_ImageMemXferGet (pTW_IDENTITY pOrigin,
if (activeDS.jd.output_scanline == activeDS.jd.output_height) {
pjpeg_finish_decompress(&activeDS.jd);
pjpeg_destroy_decompress(&activeDS.jd);
gp_file_unref (activeDS.file);
activeDS.file = NULL;
close_current_file();
TRACE("xfer is done!\n");
/*TransferringDialogBox(activeDS.progressWnd, -1);*/
......@@ -413,8 +432,7 @@ TW_UINT16 GPHOTO2_ImageNativeXferGet (pTW_IDENTITY pOrigin,
hDIB = CreateDIBSection (0, &bmpInfo, DIB_RGB_COLORS, (LPVOID)&bits, 0, 0);
if (!hDIB) {
FIXME("Failed creating DIB.\n");
gp_file_unref (activeDS.file);
activeDS.file = NULL;
close_current_file();
activeDS.twCC = TWCC_LOWMEMORY;
return TWRC_FAILURE;
}
......@@ -437,8 +455,7 @@ TW_UINT16 GPHOTO2_ImageNativeXferGet (pTW_IDENTITY pOrigin,
samprow = oldsamprow;
}
HeapFree (GetProcessHeap(), 0, samprow);
gp_file_unref (activeDS.file);
activeDS.file = NULL;
close_current_file();
*pHandle = (UINT_PTR)hDIB;
activeDS.twCC = TWCC_SUCCESS;
activeDS.currentState = 7;
......@@ -537,45 +554,52 @@ TW_UINT16 GPHOTO2_RGBResponseSet (pTW_IDENTITY pOrigin,
}
TW_UINT16
_get_gphoto2_file_as_DIB(
const char *folder, const char *filename, CameraFileType type,
HWND hwnd, HBITMAP *hDIB
) {
const unsigned char *filedata;
unsigned long filesize;
int ret;
CameraFile *file;
_get_gphoto2_file_as_DIB( unsigned int idx, BOOL preview, HWND hwnd, HBITMAP *hDIB )
{
#ifdef SONAME_LIBJPEG
unsigned char *filedata;
int ret;
struct jpeg_source_mgr xjsm;
struct jpeg_decompress_struct jd;
struct jpeg_error_mgr jerr;
BITMAPINFO bmpInfo;
LPBYTE bits;
JSAMPROW samprow, oldsamprow;
struct open_file_params open_params;
struct get_file_data_params get_data_params;
void *file_handle;
unsigned int filesize;
if(!libjpeg_handle) {
if(!load_libjpeg()) {
FIXME("Failed reading JPEG because unable to find %s\n", SONAME_LIBJPEG);
filedata = NULL;
return TWRC_FAILURE;
}
}
gp_file_new (&file);
ret = gp_camera_file_get(activeDS.camera, folder, filename, type, file, activeDS.context);
if (ret < GP_OK) {
FIXME("Failed to get file?\n");
gp_file_unref (file);
open_params.idx = idx;
open_params.preview = preview;
open_params.handle = &file_handle;
open_params.size = &filesize;
if (GPHOTO2_CALL( open_file, &open_params ))
{
FIXME( "Failed to get file %u\n", idx);
return TWRC_FAILURE;
}
ret = gp_file_get_data_and_size (file, (const char**)&filedata, &filesize);
if (ret < GP_OK) {
FIXME("Failed to get file data?\n");
filedata = malloc( filesize );
get_data_params.handle = file_handle;
get_data_params.data = filedata;
get_data_params.size = filesize;
if (GPHOTO2_CALL( get_file_data, &get_data_params ))
{
close_file( file_handle );
free( filedata );
return TWRC_FAILURE;
}
/* FIXME: Actually we might get other types than JPEG ... But only handle JPEG for now */
if (filedata[0] != 0xff) {
ERR("File %s/%s might not be JPEG, cannot decode!\n", folder, filename);
ERR("File %u might not be JPEG, cannot decode!\n", idx);
}
/* This is basically so we can use in-memory data for jpeg decompression.
......@@ -599,7 +623,8 @@ _get_gphoto2_file_as_DIB(
pjpeg_start_decompress(&jd);
if (ret != JPEG_HEADER_OK) {
ERR("Jpeg image in stream has bad format, read header returned %d.\n",ret);
gp_file_unref (file);
close_file( file_handle );
free( filedata );
return TWRC_FAILURE;
}
......@@ -618,7 +643,8 @@ _get_gphoto2_file_as_DIB(
*hDIB = CreateDIBSection(0, &bmpInfo, DIB_RGB_COLORS, (LPVOID)&bits, 0, 0);
if (!*hDIB) {
FIXME("Failed creating DIB.\n");
gp_file_unref (file);
close_file( file_handle );
free( filedata );
return TWRC_FAILURE;
}
samprow = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,jd.output_width*jd.output_components);
......@@ -640,6 +666,7 @@ _get_gphoto2_file_as_DIB(
samprow = oldsamprow;
}
HeapFree (GetProcessHeap(), 0, samprow);
gp_file_unref (file);
close_file( file_handle );
free( filedata );
return TWRC_SUCCESS;
}
......@@ -24,11 +24,6 @@
# error You must include config.h first
#endif
/* Hack for gphoto2, which changes behaviour when WIN32 is set. */
#undef WIN32
#include <gphoto2/gphoto2-camera.h>
#define WIN32
#include <stdio.h>
#ifdef SONAME_LIBJPEG
......@@ -55,14 +50,6 @@
extern HINSTANCE GPHOTO2_instance DECLSPEC_HIDDEN;
struct gphoto2_file {
struct list entry;
char *folder;
char *filename;
BOOL download; /* flag for downloading, set by GUI or so */
};
/* internal information about an active data source */
struct tagActiveDS
{
......@@ -72,18 +59,19 @@ struct tagActiveDS
TW_UINT16 twCC; /* condition code */
HWND progressWnd; /* window handle of the scanning window */
Camera *camera;
GPContext *context;
/* Capabilities */
TW_UINT32 capXferMech; /* ICAP_XFERMECH */
TW_UINT16 pixeltype; /* ICAP_PIXELTYPE */
TW_UINT16 pixelflavor; /* ICAP_PIXELFLAVOR */
struct list files;
unsigned int file_count;
unsigned int download_count;
BOOL *download_flags;
/* Download and decode JPEG STATE */
CameraFile *file;
void *file_handle;
unsigned char *file_data;
unsigned int file_size;
#ifdef SONAME_LIBJPEG
struct jpeg_source_mgr xjsm;
struct jpeg_decompress_struct jd;
......@@ -149,9 +137,6 @@ HWND TransferringDialogBox(HWND dialog, LONG progress) DECLSPEC_HIDDEN;
/* Helper function for GUI */
TW_UINT16
_get_gphoto2_file_as_DIB(
const char *folder, const char *filename, CameraFileType type,
HWND hwnd, HBITMAP *hDIB
) DECLSPEC_HIDDEN;
_get_gphoto2_file_as_DIB( unsigned int idx, BOOL preview, HWND hwnd, HBITMAP *hDIB ) DECLSPEC_HIDDEN;
#endif
......@@ -31,6 +31,7 @@
#include "winreg.h"
#include "commctrl.h"
#include "prsht.h"
#include "unixlib.h"
#include "wine/debug.h"
#include "resource.h"
......@@ -69,82 +70,66 @@ static void UI_EndDialog(HWND hwnd, INT_PTR rc)
static BOOL GetAllImages(void)
{
struct gphoto2_file *file;
BOOL has_images = FALSE;
unsigned int i;
LIST_FOR_EACH_ENTRY( file, &activeDS.files, struct gphoto2_file, entry)
{
if (strstr(file->filename,".JPG") || strstr(file->filename,".jpg"))
{
file->download = TRUE;
has_images = TRUE;
}
}
return has_images;
for (i = 0; i < activeDS.file_count; i++) activeDS.download_flags[i] = TRUE;
activeDS.download_count = activeDS.file_count;
return activeDS.download_count > 0;
}
static void PopulateListView(HWND List)
{
struct gphoto2_file *file;
LVITEMA item;
int index = 0;
char buffer[1024];
struct get_file_name_params params = { 0, sizeof(buffer), buffer };
LIST_FOR_EACH_ENTRY( file, &activeDS.files, struct gphoto2_file, entry)
for (params.idx = 0; params.idx < activeDS.file_count; params.idx++)
{
if (strstr(file->filename,".JPG") || strstr(file->filename,".jpg"))
{
item.mask = LVIF_PARAM | LVIF_TEXT | LVIF_IMAGE ;
item.iItem = index;
item.iSubItem = 0;
item.pszText = file->filename;
item.iImage = index;
item.lParam= (LPARAM)file;
SendMessageA(List, LVM_INSERTITEMA,0,(LPARAM)&item);
index ++;
}
GPHOTO2_CALL( get_file_name, &params );
item.mask = LVIF_PARAM | LVIF_TEXT | LVIF_IMAGE;
item.iItem = params.idx;
item.iSubItem = 0;
item.pszText = buffer;
item.iImage = params.idx;
item.lParam = 0;
SendMessageA(List, LVM_INSERTITEMA,0,(LPARAM)&item);
}
}
static void PopulateImageList(HIMAGELIST *iList, HWND list)
{
struct gphoto2_file *file;
unsigned int i;
HWND progress_dialog;
progress_dialog =
CreateDialogW(GPHOTO2_instance,(LPWSTR)MAKEINTRESOURCE(IDD_CONNECTING),
NULL, ConnectingProc);
LIST_FOR_EACH_ENTRY( file, &activeDS.files, struct gphoto2_file, entry)
for (i = 0; i < activeDS.file_count; i++)
{
if (strstr(file->filename,".JPG") || strstr(file->filename,".jpg"))
{
HBITMAP bitmap;
BITMAP bmpInfo;
HBITMAP bitmap;
BITMAP bmpInfo;
_get_gphoto2_file_as_DIB(file->folder, file->filename,
GP_FILE_TYPE_PREVIEW, 0, &bitmap);
GetObjectA(bitmap,sizeof(BITMAP),&bmpInfo);
_get_gphoto2_file_as_DIB( i, TRUE, 0, &bitmap );
GetObjectA(bitmap,sizeof(BITMAP),&bmpInfo);
if (*iList == 0)
{
*iList = ImageList_Create(bmpInfo.bmWidth,
bmpInfo.bmHeight,ILC_COLOR24, 10,10);
if (*iList == 0)
{
*iList = ImageList_Create(bmpInfo.bmWidth,
bmpInfo.bmHeight,ILC_COLOR24, 10,10);
SendMessageW(list, LVM_SETICONSPACING, 0,
MAKELONG(bmpInfo.bmWidth+6, bmpInfo.bmHeight+15) ); }
SendMessageW(list, LVM_SETICONSPACING, 0,
MAKELONG(bmpInfo.bmWidth+6, bmpInfo.bmHeight+15) ); }
ImageList_Add(*iList, bitmap, 0);
ImageList_Add(*iList, bitmap, 0);
DeleteObject(static_bitmap);
static_bitmap = bitmap;
SendMessageW(GetDlgItem(progress_dialog,IDC_BITMAP),STM_SETIMAGE,
IMAGE_BITMAP, (LPARAM)static_bitmap);
RedrawWindow(progress_dialog,NULL,NULL,RDW_INTERNALPAINT|RDW_UPDATENOW|RDW_ALLCHILDREN);
}
}
EndDialog(progress_dialog,0);
DeleteObject(static_bitmap);
static_bitmap = bitmap;
SendMessageW(GetDlgItem(progress_dialog,IDC_BITMAP),STM_SETIMAGE,
IMAGE_BITMAP, (LPARAM)static_bitmap);
RedrawWindow(progress_dialog,NULL,NULL,RDW_INTERNALPAINT|RDW_UPDATENOW|RDW_ALLCHILDREN);
}
EndDialog(progress_dialog,0);
}
static INT_PTR CALLBACK DialogProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
......@@ -180,38 +165,21 @@ static INT_PTR CALLBACK DialogProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lP
case IDC_IMPORT:
{
HWND list = GetDlgItem(hwnd,IDC_LIST1);
int count = SendMessageA(list,LVM_GETSELECTEDCOUNT,0,0);
int i;
unsigned int i;
if (count ==0)
if (activeDS.file_count == 0)
{
UI_EndDialog(hwnd,0);
return FALSE;
}
count = SendMessageA(list,LVM_GETITEMCOUNT,0,0);
for ( i = 0; i < count; i++)
for (i = 0; i < activeDS.file_count; i++)
{
INT state = 0x00000000;
state = SendMessageA(list,LVM_GETITEMSTATE,i,
LVIS_SELECTED);
if (state)
{
LVITEMA item;
struct gphoto2_file *file;
item.mask = LVIF_PARAM;
item.iItem = i;
item.iSubItem = 0;
SendMessageA(list,LVM_GETITEMA,0,(LPARAM)&item);
file = (struct gphoto2_file*)item.lParam;
file->download = TRUE;
}
if (SendMessageA(list,LVM_GETITEMSTATE,i, LVIS_SELECTED))
{
if (!activeDS.download_flags[i]) activeDS.download_count++;
activeDS.download_flags[i] = TRUE;
}
}
UI_EndDialog(hwnd,1);
......
/*
* Unix library interface for gphoto
*
* Copyright 2000 Corel Corporation
* Copyright 2006 Marcus Meissner
* Copyright 2021 Alexandre Julliard
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <stdarg.h>
#include "windef.h"
#include "winternl.h"
#include "wine/unixlib.h"
#include "twain.h"
struct get_identity_params
{
TW_IDENTITY *id;
};
struct open_ds_params
{
TW_IDENTITY *id;
};
struct load_file_list_params
{
const char *root;
const char **extensions;
unsigned int *count;
};
struct get_file_name_params
{
unsigned int idx;
unsigned int size;
char *buffer;
};
struct open_file_params
{
unsigned int idx;
BOOL preview;
void **handle;
unsigned int *size;
};
struct get_file_data_params
{
void *handle;
void *data;
unsigned int size;
};
struct close_file_params
{
void *handle;
};
enum gphoto2_funcs
{
unix_get_identity,
unix_open_ds,
unix_close_ds,
unix_load_file_list,
unix_get_file_name,
unix_open_file,
unix_get_file_data,
unix_close_file,
};
extern unixlib_handle_t gphoto2_handle DECLSPEC_HIDDEN;
#define GPHOTO2_CALL( func, params ) __wine_unix_call( gphoto2_handle, unix_ ## func, params )
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment