4 * Copyright 2000 Shi Quan He <shiquan@cyberdude.com>
5 * Copyright 2006 Marcus Meissner
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
31 #include "gphoto2_i.h"
32 #include "wine/debug.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(twain
);
38 static char* GPHOTO2_StrDup(const char* str
)
40 char* dst
= HeapAlloc(GetProcessHeap(), 0, strlen(str
)+1);
47 load_filesystem(const char *folder
) {
52 ret
= gp_list_new (&list
);
55 ret
= gp_camera_folder_list_files (activeDS
.camera
, folder
, list
, activeDS
.context
);
60 count
= gp_list_count (list
);
65 for (i
= 0; i
< count
; i
++) {
67 struct gphoto2_file
*gpfile
;
69 ret
= gp_list_get_name (list
, i
, &name
);
72 gpfile
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct gphoto2_file
)); /* FIXME: Leaked */
75 TRACE("adding %s/%s\n", folder
, name
);
76 gpfile
->folder
= GPHOTO2_StrDup(folder
);
77 gpfile
->filename
= GPHOTO2_StrDup(name
);
78 gpfile
->download
= FALSE
;
79 list_add_tail( &activeDS
.files
, &gpfile
->entry
);
83 ret
= gp_camera_folder_list_folders (activeDS
.camera
, folder
, list
, activeDS
.context
);
85 FIXME("list_folders failed\n");
89 count
= gp_list_count (list
);
91 FIXME("list_folders failed\n");
95 for (i
= 0; i
< count
; i
++) {
98 ret
= gp_list_get_name (list
, i
, &name
);
101 TRACE("recursing into %s\n", name
);
102 newfolder
= HeapAlloc(GetProcessHeap(), 0, strlen(folder
)+1+strlen(name
)+1);
103 if (!strcmp(folder
,"/"))
104 sprintf (newfolder
, "/%s", name
);
106 sprintf (newfolder
, "%s/%s", folder
, name
);
107 load_filesystem (newfolder
); /* recurse ... happily */
113 /* DG_CONTROL/DAT_CAPABILITY/MSG_GET */
114 static TW_UINT16
GPHOTO2_CapabilityGet (pTW_IDENTITY pOrigin
, TW_MEMREF pData
)
116 pTW_CAPABILITY pCapability
= (pTW_CAPABILITY
) pData
;
118 TRACE("DG_CONTROL/DAT_CAPABILITY/MSG_GET\n");
119 if (activeDS
.currentState
< 4 || activeDS
.currentState
> 7) {
120 activeDS
.twCC
= TWCC_SEQERROR
;
123 activeDS
.twCC
= GPHOTO2_SaneCapability (pCapability
, MSG_GET
);
124 return (activeDS
.twCC
== TWCC_SUCCESS
)?TWRC_SUCCESS
:TWRC_FAILURE
;
127 /* DG_CONTROL/DAT_CAPABILITY/MSG_GETCURRENT */
128 static TW_UINT16
GPHOTO2_CapabilityGetCurrent (pTW_IDENTITY pOrigin
, TW_MEMREF pData
)
130 pTW_CAPABILITY pCapability
= (pTW_CAPABILITY
) pData
;
132 TRACE("DG_CONTROL/DAT_CAPABILITY/MSG_GETCURRENT\n");
134 if (activeDS
.currentState
< 4 || activeDS
.currentState
> 7) {
135 activeDS
.twCC
= TWCC_SEQERROR
;
138 activeDS
.twCC
= GPHOTO2_SaneCapability (pCapability
, MSG_GETCURRENT
);
139 return (activeDS
.twCC
== TWCC_SUCCESS
)?TWRC_SUCCESS
:TWRC_FAILURE
;
142 /* DG_CONTROL/DAT_CAPABILITY/MSG_GETDEFAULT */
143 static TW_UINT16
GPHOTO2_CapabilityGetDefault (pTW_IDENTITY pOrigin
, TW_MEMREF pData
)
145 pTW_CAPABILITY pCapability
= (pTW_CAPABILITY
) pData
;
147 TRACE("DG_CONTROL/DAT_CAPABILITY/MSG_GETDEFAULT\n");
148 if (activeDS
.currentState
< 4 || activeDS
.currentState
> 7) {
149 activeDS
.twCC
= TWCC_SEQERROR
;
152 activeDS
.twCC
= GPHOTO2_SaneCapability (pCapability
, MSG_GETDEFAULT
);
153 return (activeDS
.twCC
== TWCC_SUCCESS
)?TWRC_SUCCESS
:TWRC_FAILURE
;
156 /* DG_CONTROL/DAT_CAPABILITY/MSG_QUERYSUPPORT */
157 static TW_UINT16
GPHOTO2_CapabilityQuerySupport (pTW_IDENTITY pOrigin
,
165 /* DG_CONTROL/DAT_CAPABILITY/MSG_RESET */
166 static TW_UINT16
GPHOTO2_CapabilityReset (pTW_IDENTITY pOrigin
,
169 pTW_CAPABILITY pCapability
= (pTW_CAPABILITY
) pData
;
171 TRACE("DG_CONTROL/DAT_CAPABILITY/MSG_RESET\n");
173 if (activeDS
.currentState
< 4 || activeDS
.currentState
> 7) {
174 activeDS
.twCC
= TWCC_SEQERROR
;
177 activeDS
.twCC
= GPHOTO2_SaneCapability (pCapability
, MSG_RESET
);
178 return (activeDS
.twCC
== TWCC_SUCCESS
)?TWRC_SUCCESS
:TWRC_FAILURE
;
181 /* DG_CONTROL/DAT_CAPABILITY/MSG_SET */
182 static TW_UINT16
GPHOTO2_CapabilitySet (pTW_IDENTITY pOrigin
,
185 pTW_CAPABILITY pCapability
= (pTW_CAPABILITY
) pData
;
187 TRACE ("DG_CONTROL/DAT_CAPABILITY/MSG_SET\n");
189 if (activeDS
.currentState
!= 4) {
190 activeDS
.twCC
= TWCC_SEQERROR
;
193 activeDS
.twCC
= GPHOTO2_SaneCapability (pCapability
, MSG_SET
);
194 return (activeDS
.twCC
== TWCC_SUCCESS
)?TWRC_SUCCESS
:TWRC_FAILURE
;
197 /* DG_CONTROL/DAT_CUSTOMDSDATA/MSG_GET */
198 static TW_UINT16
GPHOTO2_CustomDSDataGet (pTW_IDENTITY pOrigin
,
206 /* DG_CONTROL/DAT_CUSTOMDSDATA/MSG_SET */
207 static TW_UINT16
GPHOTO2_CustomDSDataSet (pTW_IDENTITY pOrigin
,
215 /* DG_CONTROL/DAT_FILESYSTEM/MSG_CHANGEDIRECTORY */
216 static TW_UINT16
GPHOTO2_ChangeDirectory (pTW_IDENTITY pOrigin
,
224 /* DG_CONTROL/DAT_FILESYSTEM/MSG_CREATEDIRECTORY */
225 static TW_UINT16
GPHOTO2_CreateDirectory (pTW_IDENTITY pOrigin
,
233 /* DG_CONTROL/DAT_FILESYSTEM/MSG_DELETE */
234 static TW_UINT16
GPHOTO2_FileSystemDelete (pTW_IDENTITY pOrigin
,
242 /* DG_CONTROL/DAT_FILESYSTEM/MSG_FORMATMEDIA */
243 static TW_UINT16
GPHOTO2_FormatMedia (pTW_IDENTITY pOrigin
,
251 /* DG_CONTROL/DAT_FILESYSTEM/MSG_GETCLOSE */
252 static TW_UINT16
GPHOTO2_FileSystemGetClose (pTW_IDENTITY pOrigin
,
260 /* DG_CONTROL/DAT_FILESYSTEM/MSG_GETFIRSTFILE */
261 static TW_UINT16
GPHOTO2_FileSystemGetFirstFile (pTW_IDENTITY pOrigin
,
270 /* DG_CONTROL/DAT_FILESYSTEM/MSG_GETINFO */
271 static TW_UINT16
GPHOTO2_FileSystemGetInfo (pTW_IDENTITY pOrigin
,
279 /* DG_CONTROL/DAT_FILESYSTEM/MSG_GETNEXTFILE */
280 static TW_UINT16
GPHOTO2_FileSystemGetNextFile (pTW_IDENTITY pOrigin
,
289 /* DG_CONTROL/DAT_FILESYSTEM/MSG_RENAME */
290 static TW_UINT16
GPHOTO2_FileSystemRename (pTW_IDENTITY pOrigin
,
298 /* DG_CONTROL/DAT_EVENT/MSG_PROCESSEVENT */
299 static TW_UINT16
GPHOTO2_ProcessEvent (pTW_IDENTITY pOrigin
,
302 TW_UINT16 twRC
= TWRC_SUCCESS
;
303 pTW_EVENT pEvent
= (pTW_EVENT
) pData
;
305 TRACE("DG_CONTROL/DAT_EVENT/MSG_PROCESSEVENT\n");
307 if (activeDS
.currentState
< 5 || activeDS
.currentState
> 7) {
308 activeDS
.twCC
= TWCC_SEQERROR
;
312 if (activeDS
.pendingEvent
.TWMessage
!= MSG_NULL
) {
313 pEvent
->TWMessage
= activeDS
.pendingEvent
.TWMessage
;
314 activeDS
.pendingEvent
.TWMessage
= MSG_NULL
;
317 pEvent
->TWMessage
= MSG_NULL
; /* no message to the application */
318 twRC
= TWRC_NOTDSEVENT
;
320 activeDS
.twCC
= TWCC_SUCCESS
;
324 /* DG_CONTROL/DAT_PASSTHRU/MSG_PASSTHRU */
325 static TW_UINT16
GPHOTO2_PassThrough (pTW_IDENTITY pOrigin
,
333 /* DG_CONTROL/DAT_PENDINGXFERS/MSG_ENDXFER */
334 static TW_UINT16
GPHOTO2_PendingXfersEndXfer (pTW_IDENTITY pOrigin
,
338 pTW_PENDINGXFERS pPendingXfers
= (pTW_PENDINGXFERS
) pData
;
339 struct gphoto2_file
*file
;
341 TRACE("DG_CONTROL/DAT_PENDINGXFERS/MSG_ENDXFER\n");
343 if (activeDS
.currentState
!= 6 && activeDS
.currentState
!= 7) {
344 activeDS
.twCC
= TWCC_SEQERROR
;
348 LIST_FOR_EACH_ENTRY( file
, &activeDS
.files
, struct gphoto2_file
, entry
) {
352 TRACE("count = %d\n", count
);
353 pPendingXfers
->Count
= count
;
354 if (pPendingXfers
->Count
!= 0) {
355 activeDS
.currentState
= 6;
357 activeDS
.currentState
= 5;
358 /* Notify the application that it can close the data source */
359 activeDS
.pendingEvent
.TWMessage
= MSG_CLOSEDSREQ
;
360 /* close any Transferring dialog */
361 TransferringDialogBox(activeDS
.progressWnd
,-1);
362 activeDS
.progressWnd
= 0;
364 activeDS
.twCC
= TWCC_SUCCESS
;
368 /* DG_CONTROL/DAT_PENDINGXFERS/MSG_GET */
369 static TW_UINT16
GPHOTO2_PendingXfersGet (pTW_IDENTITY pOrigin
,
373 pTW_PENDINGXFERS pPendingXfers
= (pTW_PENDINGXFERS
) pData
;
374 struct gphoto2_file
*file
;
376 TRACE("DG_CONTROL/DAT_PENDINGXFERS/MSG_GET\n");
378 if (activeDS
.currentState
< 4 || activeDS
.currentState
> 7) {
379 activeDS
.twCC
= TWCC_SEQERROR
;
384 LIST_FOR_EACH_ENTRY( file
, &activeDS
.files
, struct gphoto2_file
, entry
) {
388 TRACE("count = %d\n", count
);
389 pPendingXfers
->Count
= count
;
390 activeDS
.twCC
= TWCC_SUCCESS
;
394 /* DG_CONTROL/DAT_PENDINGXFERS/MSG_RESET */
395 static TW_UINT16
GPHOTO2_PendingXfersReset (pTW_IDENTITY pOrigin
,
398 pTW_PENDINGXFERS pPendingXfers
= (pTW_PENDINGXFERS
) pData
;
400 TRACE("DG_CONTROL/DAT_PENDINGXFERS/MSG_RESET\n");
402 if (activeDS
.currentState
!= 6) {
403 activeDS
.twCC
= TWCC_SEQERROR
;
406 pPendingXfers
->Count
= 0;
407 activeDS
.currentState
= 5;
408 activeDS
.twCC
= TWCC_SUCCESS
;
412 /* DG_CONTROL/DAT_SETUPFILEXFER/MSG_GET */
413 static TW_UINT16
GPHOTO2_SetupFileXferGet (pTW_IDENTITY pOrigin
,
421 /* DG_CONTROL/DAT_SETUPXFER/MSG_GETDEFAULT */
422 static TW_UINT16
GPHOTO2_SetupFileXferGetDefault (pTW_IDENTITY pOrigin
,
431 /* DG_CONTROL/DAT_SETUPFILEXFER/MSG_RESET */
432 static TW_UINT16
GPHOTO2_SetupFileXferReset (pTW_IDENTITY pOrigin
,
440 /* DG_CONTROL/DAT_SETUPFILEXFER/MSG_SET */
441 static TW_UINT16
GPHOTO2_SetupFileXferSet (pTW_IDENTITY pOrigin
,
449 /* DG_CONTROL/DAT_SETUPMEMXFER/MSG_GET */
450 static TW_UINT16
GPHOTO2_SetupMemXferGet (pTW_IDENTITY pOrigin
,
453 pTW_SETUPMEMXFER pSetupMemXfer
= (pTW_SETUPMEMXFER
)pData
;
455 TRACE("DG_CONTROL/DAT_SETUPMEMXFER/MSG_GET\n");
457 pSetupMemXfer
->MinBufSize
= 20000;
458 pSetupMemXfer
->MaxBufSize
= 80000;
459 pSetupMemXfer
->Preferred
= 40000;
463 /* DG_CONTROL/DAT_STATUS/MSG_GET */
464 static TW_UINT16
GPHOTO2_GetDSStatus (pTW_IDENTITY pOrigin
,
467 pTW_STATUS pSourceStatus
= (pTW_STATUS
) pData
;
469 TRACE ("DG_CONTROL/DAT_STATUS/MSG_GET\n");
470 pSourceStatus
->ConditionCode
= activeDS
.twCC
;
471 /* Reset the condition code */
472 activeDS
.twCC
= TWCC_SUCCESS
;
476 /* DG_CONTROL/DAT_USERINTERFACE/MSG_DISABLEDS */
477 static TW_UINT16
GPHOTO2_DisableDSUserInterface (pTW_IDENTITY pOrigin
,
480 TRACE ("DG_CONTROL/DAT_USERINTERFACE/MSG_DISABLEDS\n");
482 if (activeDS
.currentState
!= 5) {
483 activeDS
.twCC
= TWCC_SEQERROR
;
486 activeDS
.currentState
= 4;
487 activeDS
.twCC
= TWCC_SUCCESS
;
491 /* DG_CONTROL/DAT_USERINTERFACE/MSG_ENABLEDS */
492 static TW_UINT16
GPHOTO2_EnableDSUserInterface (pTW_IDENTITY pOrigin
,
495 pTW_USERINTERFACE pUserInterface
= (pTW_USERINTERFACE
) pData
;
497 load_filesystem("/");
499 TRACE ("DG_CONTROL/DAT_USERINTERFACE/MSG_ENABLEDS\n");
500 if (activeDS
.currentState
!= 4) {
501 FIXME("Sequence error %d\n", activeDS
.currentState
);
502 activeDS
.twCC
= TWCC_SEQERROR
;
505 activeDS
.hwndOwner
= pUserInterface
->hParent
;
506 if (pUserInterface
->ShowUI
)
509 activeDS
.currentState
= 5; /* Transitions to state 5 */
512 activeDS
.pendingEvent
.TWMessage
= MSG_CLOSEDSREQ
;
514 /* FIXME: The GUI should have marked the files to download... */
515 activeDS
.pendingEvent
.TWMessage
= MSG_XFERREADY
;
516 activeDS
.currentState
= 6; /* Transitions to state 6 directly */
519 /* no UI will be displayed, so source is ready to transfer data */
520 activeDS
.pendingEvent
.TWMessage
= MSG_XFERREADY
;
521 activeDS
.currentState
= 6; /* Transitions to state 6 directly */
523 activeDS
.hwndOwner
= pUserInterface
->hParent
;
524 activeDS
.twCC
= TWCC_SUCCESS
;
528 /* DG_CONTROL/DAT_USERINTERFACE/MSG_ENABLEDSUIONLY */
529 static TW_UINT16
GPHOTO2_EnableDSUIOnly (pTW_IDENTITY pOrigin
,
532 TRACE("DG_CONTROL/DAT_USERINTERFACE/MSG_ENABLEDSUIONLY\n");
534 if (activeDS
.currentState
!= 4) {
535 activeDS
.twCC
= TWCC_SEQERROR
;
538 /* FIXME: we should replace xscanimage with our own UI */
539 FIXME ("not implemented!\n");
540 activeDS
.currentState
= 5;
541 activeDS
.twCC
= TWCC_SUCCESS
;
545 /* DG_CONTROL/DAT_XFERGROUP/MSG_GET */
546 static TW_UINT16
GPHOTO2_XferGroupGet (pTW_IDENTITY pOrigin
,
553 /* DG_CONTROL/DAT_XFERGROUP/MSG_SET */
554 static TW_UINT16
GPHOTO2_XferGroupSet (pTW_IDENTITY pOrigin
,
561 HINSTANCE GPHOTO2_instance
;
563 BOOL WINAPI
DllMain (HINSTANCE hinstDLL
, DWORD fdwReason
, LPVOID lpvReserved
)
565 TRACE("%p,%x,%p\n", hinstDLL
, fdwReason
, lpvReserved
);
569 case DLL_PROCESS_ATTACH
:
570 GPHOTO2_instance
= hinstDLL
;
571 DisableThreadLibraryCalls(hinstDLL
);
573 activeDS
.context
= gp_context_new ();
581 #if defined(HAVE_GPHOTO2) && defined(HAVE_GPHOTO2_PORT)
582 static TW_UINT16
GPHOTO2_GetIdentity( pTW_IDENTITY
, pTW_IDENTITY
);
583 static TW_UINT16
GPHOTO2_OpenDS( pTW_IDENTITY
, pTW_IDENTITY
);
586 static TW_UINT16
GPHOTO2_SourceControlHandler (
587 pTW_IDENTITY pOrigin
,
592 TW_UINT16 twRC
= TWRC_SUCCESS
;
600 #if defined(HAVE_GPHOTO2) && defined(HAVE_GPHOTO2_PORT)
601 if (activeDS
.camera
) {
602 gp_camera_free (activeDS
.camera
);
603 activeDS
.camera
= NULL
;
608 #if defined(HAVE_GPHOTO2) && defined(HAVE_GPHOTO2_PORT)
609 twRC
= GPHOTO2_GetIdentity(pOrigin
,(pTW_IDENTITY
)pData
);
615 #if defined(HAVE_GPHOTO2) && defined(HAVE_GPHOTO2_PORT)
616 twRC
= GPHOTO2_OpenDS(pOrigin
,(pTW_IDENTITY
)pData
);
627 twRC
= GPHOTO2_CapabilityGet (pOrigin
, pData
);
630 twRC
= GPHOTO2_CapabilityGetCurrent (pOrigin
, pData
);
633 twRC
= GPHOTO2_CapabilityGetDefault (pOrigin
, pData
);
635 case MSG_QUERYSUPPORT
:
636 twRC
= GPHOTO2_CapabilityQuerySupport (pOrigin
, pData
);
639 twRC
= GPHOTO2_CapabilityReset (pOrigin
, pData
);
642 twRC
= GPHOTO2_CapabilitySet (pOrigin
, pData
);
646 FIXME("unrecognized operation triplet\n");
650 case DAT_CUSTOMDSDATA
:
654 twRC
= GPHOTO2_CustomDSDataGet (pOrigin
, pData
);
657 twRC
= GPHOTO2_CustomDSDataSet (pOrigin
, pData
);
667 /*case MSG_AUTOMATICCAPTUREDIRECTORY:
668 twRC = GPHOTO2_AutomaticCaptureDirectory
671 case MSG_CHANGEDIRECTORY
:
672 twRC
= GPHOTO2_ChangeDirectory (pOrigin
, pData
);
675 twRC = GPHOTO2_FileSystemCopy (pOrigin, pData);
677 case MSG_CREATEDIRECTORY
:
678 twRC
= GPHOTO2_CreateDirectory (pOrigin
, pData
);
681 twRC
= GPHOTO2_FileSystemDelete (pOrigin
, pData
);
683 case MSG_FORMATMEDIA
:
684 twRC
= GPHOTO2_FormatMedia (pOrigin
, pData
);
687 twRC
= GPHOTO2_FileSystemGetClose (pOrigin
, pData
);
689 case MSG_GETFIRSTFILE
:
690 twRC
= GPHOTO2_FileSystemGetFirstFile (pOrigin
, pData
);
693 twRC
= GPHOTO2_FileSystemGetInfo (pOrigin
, pData
);
695 case MSG_GETNEXTFILE
:
696 twRC
= GPHOTO2_FileSystemGetNextFile (pOrigin
, pData
);
699 twRC
= GPHOTO2_FileSystemRename (pOrigin
, pData
);
708 if (MSG
== MSG_PROCESSEVENT
)
709 twRC
= GPHOTO2_ProcessEvent (pOrigin
, pData
);
715 if (MSG
== MSG_PASSTHRU
)
716 twRC
= GPHOTO2_PassThrough (pOrigin
, pData
);
721 case DAT_PENDINGXFERS
:
725 twRC
= GPHOTO2_PendingXfersEndXfer (pOrigin
, pData
);
728 twRC
= GPHOTO2_PendingXfersGet (pOrigin
, pData
);
731 twRC
= GPHOTO2_PendingXfersReset (pOrigin
, pData
);
733 /*case MSG_STOPFEEDER:
734 twRC = GPHOTO2_PendingXfersStopFeeder (pOrigin, pData);
741 case DAT_SETUPFILEXFER
:
745 twRC
= GPHOTO2_SetupFileXferGet (pOrigin
, pData
);
748 twRC
= GPHOTO2_SetupFileXferGetDefault (pOrigin
, pData
);
751 twRC
= GPHOTO2_SetupFileXferReset (pOrigin
, pData
);
754 twRC
= GPHOTO2_SetupFileXferSet (pOrigin
, pData
);
762 /*case DAT_SETUPFILEXFER2:
766 twRC = GPHOTO2_SetupFileXfer2Get (pOrigin, pData);
769 twRC = GPHOTO2_SetupFileXfer2GetDefault (pOrigin, pData);
772 twRC = GPHOTO2_SetupFileXfer2Reset (pOrigin, pData);
775 twRC = GPHOTO2_SetupFileXfer2Set (pOrigin, pData);
779 case DAT_SETUPMEMXFER
:
781 twRC
= GPHOTO2_SetupMemXferGet (pOrigin
, pData
);
788 twRC
= GPHOTO2_GetDSStatus (pOrigin
, pData
);
793 case DAT_USERINTERFACE
:
797 twRC
= GPHOTO2_DisableDSUserInterface (pOrigin
, pData
);
800 twRC
= GPHOTO2_EnableDSUserInterface (pOrigin
, pData
);
802 case MSG_ENABLEDSUIONLY
:
803 twRC
= GPHOTO2_EnableDSUIOnly (pOrigin
, pData
);
815 twRC
= GPHOTO2_XferGroupGet (pOrigin
, pData
);
818 twRC
= GPHOTO2_XferGroupSet (pOrigin
, pData
);
827 FIXME("code unknown: %d\n", DAT
);
836 static TW_UINT16
GPHOTO2_ImageGroupHandler (
837 pTW_IDENTITY pOrigin
,
842 TW_UINT16 twRC
= TWRC_SUCCESS
;
848 twRC
= GPHOTO2_CIEColorGet (pOrigin
, pData
);
853 case DAT_EXTIMAGEINFO
:
855 twRC
= GPHOTO2_ExtImageInfoGet (pOrigin
, pData
);
860 case DAT_GRAYRESPONSE
:
864 twRC
= GPHOTO2_GrayResponseReset (pOrigin
, pData
);
867 twRC
= GPHOTO2_GrayResponseSet (pOrigin
, pData
);
871 activeDS
.twCC
= TWCC_BADPROTOCOL
;
872 FIXME("unrecognized operation triplet\n");
876 case DAT_IMAGEFILEXFER
:
878 twRC
= GPHOTO2_ImageFileXferGet (pOrigin
, pData
);
885 twRC
= GPHOTO2_ImageInfoGet (pOrigin
, pData
);
890 case DAT_IMAGELAYOUT
:
894 twRC
= GPHOTO2_ImageLayoutGet (pOrigin
, pData
);
897 twRC
= GPHOTO2_ImageLayoutGetDefault (pOrigin
, pData
);
900 twRC
= GPHOTO2_ImageLayoutReset (pOrigin
, pData
);
903 twRC
= GPHOTO2_ImageLayoutSet (pOrigin
, pData
);
907 activeDS
.twCC
= TWCC_BADPROTOCOL
;
908 ERR("unrecognized operation triplet\n");
913 case DAT_IMAGEMEMXFER
:
915 twRC
= GPHOTO2_ImageMemXferGet (pOrigin
, pData
);
920 case DAT_IMAGENATIVEXFER
:
922 twRC
= GPHOTO2_ImageNativeXferGet (pOrigin
, pData
);
927 case DAT_JPEGCOMPRESSION
:
931 twRC
= GPHOTO2_JPEGCompressionGet (pOrigin
, pData
);
934 twRC
= GPHOTO2_JPEGCompressionGetDefault (pOrigin
, pData
);
937 twRC
= GPHOTO2_JPEGCompressionReset (pOrigin
, pData
);
940 twRC
= GPHOTO2_JPEGCompressionSet (pOrigin
, pData
);
944 activeDS
.twCC
= TWCC_BADPROTOCOL
;
945 WARN("unrecognized operation triplet\n");
954 twRC
= GPHOTO2_Palette8Get (pOrigin
, pData
);
957 twRC
= GPHOTO2_Palette8GetDefault (pOrigin
, pData
);
960 twRC
= GPHOTO2_Palette8Reset (pOrigin
, pData
);
963 twRC
= GPHOTO2_Palette8Set (pOrigin
, pData
);
967 activeDS
.twCC
= TWCC_BADPROTOCOL
;
968 WARN("unrecognized operation triplet\n");
972 case DAT_RGBRESPONSE
:
976 twRC
= GPHOTO2_RGBResponseReset (pOrigin
, pData
);
979 twRC
= GPHOTO2_RGBResponseSet (pOrigin
, pData
);
983 activeDS
.twCC
= TWCC_BADPROTOCOL
;
984 WARN("unrecognized operation triplet\n");
991 activeDS
.twCC
= TWCC_BADPROTOCOL
;
992 FIXME("unrecognized DG type %d\n", DAT
);
997 /* Main entry point for the TWAIN library */
999 DS_Entry ( pTW_IDENTITY pOrigin
,
1005 TW_UINT16 twRC
= TWRC_SUCCESS
; /* Return Code */
1007 TRACE("(DG=%d DAT=%d MSG=%d)\n", DG
, DAT
, MSG
);
1012 twRC
= GPHOTO2_SourceControlHandler (pOrigin
,DAT
,MSG
,pData
);
1015 twRC
= GPHOTO2_ImageGroupHandler (pOrigin
,DAT
,MSG
,pData
);
1018 FIXME("The audio group of entry codes is not implemented.\n");
1020 activeDS
.twCC
= TWCC_BADPROTOCOL
;
1021 twRC
= TWRC_FAILURE
;
1027 #if defined(HAVE_GPHOTO2) && defined(HAVE_GPHOTO2_PORT)
1028 static GPPortInfoList
*port_list
;
1029 static int curcamera
;
1030 static CameraList
*detected_cameras
;
1031 static CameraAbilitiesList
*abilities_list
;
1034 gphoto2_auto_detect(void) {
1037 if (detected_cameras
&& (gp_list_count (detected_cameras
) == 0)) {
1038 /* Reload if previously no cameras, we might detect new ones. */
1039 TRACE("Reloading portlist trying to detect cameras.\n");
1041 gp_port_info_list_free (port_list
);
1046 TRACE("Auto detecting gphoto cameras.\n");
1047 TRACE("Loading ports...\n");
1048 if (gp_port_info_list_new (&port_list
) < GP_OK
)
1049 return TWRC_FAILURE
;
1050 result
= gp_port_info_list_load (port_list
);
1052 gp_port_info_list_free (port_list
);
1053 return TWRC_FAILURE
;
1055 count
= gp_port_info_list_count (port_list
);
1057 return TWRC_FAILURE
;
1058 if (gp_list_new (&detected_cameras
) < GP_OK
)
1059 return TWRC_FAILURE
;
1060 if (!abilities_list
) { /* Load only once per program start */
1061 gp_abilities_list_new (&abilities_list
);
1062 TRACE("Loading cameras...\n");
1063 gp_abilities_list_load (abilities_list
, NULL
);
1065 TRACE("Detecting cameras...\n");
1066 gp_abilities_list_detect (abilities_list
, port_list
, detected_cameras
, NULL
);
1068 TRACE("%d cameras detected\n", gp_list_count(detected_cameras
));
1070 return TWRC_SUCCESS
;
1074 GPHOTO2_GetIdentity( pTW_IDENTITY pOrigin
, pTW_IDENTITY self
) {
1076 const char *cname
, *pname
;
1078 if (TWRC_SUCCESS
!= gphoto2_auto_detect())
1079 return TWRC_FAILURE
;
1081 count
= gp_list_count (detected_cameras
);
1082 if (count
< GP_OK
) {
1083 gp_list_free (detected_cameras
);
1084 return TWRC_FAILURE
;
1086 TRACE("%d cameras detected.\n", count
);
1087 self
->ProtocolMajor
= TWON_PROTOCOLMAJOR
;
1088 self
->ProtocolMinor
= TWON_PROTOCOLMINOR
;
1089 lstrcpynA (self
->Manufacturer
, "The Wine Team", sizeof(self
->Manufacturer
) - 1);
1090 lstrcpynA (self
->ProductFamily
, "GPhoto2 Camera", sizeof(self
->ProductFamily
) - 1);
1092 if (!count
) { /* No camera detected. But we need to return an IDENTITY anyway. */
1093 lstrcpynA (self
->ProductName
, "GPhoto2 Camera", sizeof(self
->ProductName
) - 1);
1094 return TWRC_SUCCESS
;
1096 gp_list_get_name (detected_cameras
, curcamera
, &cname
);
1097 gp_list_get_value (detected_cameras
, curcamera
, &pname
);
1098 if (count
== 1) /* Normal case, only one camera. */
1099 snprintf (self
->ProductName
, sizeof(self
->ProductName
), "%s", cname
);
1101 snprintf (self
->ProductName
, sizeof(self
->ProductName
), "%s@%s", cname
, pname
);
1102 curcamera
= (curcamera
+1) % count
;
1103 return TWRC_SUCCESS
;
1107 GPHOTO2_OpenDS( pTW_IDENTITY pOrigin
, pTW_IDENTITY self
) {
1108 int ret
, m
, p
, count
, i
;
1111 const char *model
, *port
;
1113 if (TWRC_SUCCESS
!= gphoto2_auto_detect())
1114 return TWRC_FAILURE
;
1116 if (lstrcmpA(self
->ProductFamily
,"GPhoto2 Camera")) {
1117 FIXME("identity passed is not a gphoto camera, but %s!?!\n", self
->ProductFamily
);
1118 return TWRC_FAILURE
;
1120 count
= gp_list_count (detected_cameras
);
1122 ERR("No camera found by autodetection. Returning failure.\n");
1123 return TWRC_FAILURE
;
1126 if (!lstrcmpA (self
->ProductName
, "GPhoto2 Camera")) {
1127 TRACE("Potential undetected camera. Just using the first autodetected one.\n");
1130 for (i
=0;i
<count
;i
++) {
1131 const char *cname
, *pname
;
1134 gp_list_get_name (detected_cameras
, i
, &cname
);
1135 gp_list_get_value (detected_cameras
, i
, &pname
);
1136 if (!lstrcmpA(self
->ProductName
,cname
))
1138 snprintf(name
, sizeof(name
), "%s", cname
);
1139 if (!lstrcmpA(self
->ProductName
,name
))
1141 snprintf(name
, sizeof(name
), "%s@%s", cname
, pname
);
1142 if (!lstrcmpA(self
->ProductName
,name
))
1146 TRACE("Camera %s not found in autodetected list. Using first entry.\n", self
->ProductName
);
1150 gp_list_get_name (detected_cameras
, i
, &model
);
1151 gp_list_get_value (detected_cameras
, i
, &port
);
1152 TRACE("model %s, port %s\n", model
, port
);
1153 ret
= gp_camera_new (&activeDS
.camera
);
1155 ERR("gp_camera_new: %d\n", ret
);
1156 return TWRC_FAILURE
;
1158 m
= gp_abilities_list_lookup_model (abilities_list
, model
);
1160 FIXME("Model %s not found, %d!\n", model
, m
);
1161 return TWRC_FAILURE
;
1163 ret
= gp_abilities_list_get_abilities (abilities_list
, m
, &a
);
1165 FIXME("gp_camera_list_get_abilities failed? %d\n", ret
);
1166 return TWRC_FAILURE
;
1168 ret
= gp_camera_set_abilities (activeDS
.camera
, a
);
1170 FIXME("gp_camera_set_abilities failed? %d\n", ret
);
1171 return TWRC_FAILURE
;
1174 p
= gp_port_info_list_lookup_path (port_list
, port
);
1176 FIXME("port %s not in portlist?\n", port
);
1177 return TWRC_FAILURE
;
1179 ret
= gp_port_info_list_get_info (port_list
, p
, &info
);
1181 FIXME("could not get portinfo for port %s?\n", port
);
1182 return TWRC_FAILURE
;
1184 ret
= gp_camera_set_port_info (activeDS
.camera
, info
);
1186 FIXME("could not set portinfo for port %s to camera?\n", port
);
1187 return TWRC_FAILURE
;
1189 list_init( &(activeDS
.files
) );
1190 activeDS
.currentState
= 4;
1191 activeDS
.twCC
= TWRC_SUCCESS
;
1192 activeDS
.pixelflavor
= TWPF_CHOCOLATE
;
1193 activeDS
.pixeltype
= TWPT_RGB
;
1194 activeDS
.capXferMech
= TWSX_MEMORY
;
1196 return TWRC_SUCCESS
;