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
);
36 DSMENTRYPROC GPHOTO2_dsmentry
;
39 static char* GPHOTO2_StrDup(const char* str
)
41 char* dst
= HeapAlloc(GetProcessHeap(), 0, strlen(str
)+1);
48 load_filesystem(const char *folder
) {
53 ret
= gp_list_new (&list
);
56 ret
= gp_camera_folder_list_files (activeDS
.camera
, folder
, list
, activeDS
.context
);
61 count
= gp_list_count (list
);
66 for (i
= 0; i
< count
; i
++) {
68 struct gphoto2_file
*gpfile
;
70 ret
= gp_list_get_name (list
, i
, &name
);
73 gpfile
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct gphoto2_file
)); /* FIXME: Leaked */
76 TRACE("adding %s/%s\n", folder
, name
);
77 gpfile
->folder
= GPHOTO2_StrDup(folder
);
78 gpfile
->filename
= GPHOTO2_StrDup(name
);
79 gpfile
->download
= FALSE
;
80 list_add_tail( &activeDS
.files
, &gpfile
->entry
);
84 ret
= gp_camera_folder_list_folders (activeDS
.camera
, folder
, list
, activeDS
.context
);
86 FIXME("list_folders failed\n");
90 count
= gp_list_count (list
);
92 FIXME("list_folders failed\n");
96 for (i
= 0; i
< count
; i
++) {
99 ret
= gp_list_get_name (list
, i
, &name
);
102 TRACE("recursing into %s\n", name
);
103 newfolder
= HeapAlloc(GetProcessHeap(), 0, strlen(folder
)+1+strlen(name
)+1);
104 if (!strcmp(folder
,"/"))
105 sprintf (newfolder
, "/%s", name
);
107 sprintf (newfolder
, "%s/%s", folder
, name
);
108 load_filesystem (newfolder
); /* recurse ... happily */
114 /* DG_CONTROL/DAT_CAPABILITY/MSG_GET */
115 static TW_UINT16
GPHOTO2_CapabilityGet (pTW_IDENTITY pOrigin
, TW_MEMREF pData
)
117 pTW_CAPABILITY pCapability
= (pTW_CAPABILITY
) pData
;
119 TRACE("DG_CONTROL/DAT_CAPABILITY/MSG_GET\n");
120 if (activeDS
.currentState
< 4 || activeDS
.currentState
> 7) {
121 activeDS
.twCC
= TWCC_SEQERROR
;
124 activeDS
.twCC
= GPHOTO2_SaneCapability (pCapability
, MSG_GET
);
125 return (activeDS
.twCC
== TWCC_SUCCESS
)?TWRC_SUCCESS
:TWRC_FAILURE
;
128 /* DG_CONTROL/DAT_CAPABILITY/MSG_GETCURRENT */
129 static TW_UINT16
GPHOTO2_CapabilityGetCurrent (pTW_IDENTITY pOrigin
, TW_MEMREF pData
)
131 pTW_CAPABILITY pCapability
= (pTW_CAPABILITY
) pData
;
133 TRACE("DG_CONTROL/DAT_CAPABILITY/MSG_GETCURRENT\n");
135 if (activeDS
.currentState
< 4 || activeDS
.currentState
> 7) {
136 activeDS
.twCC
= TWCC_SEQERROR
;
139 activeDS
.twCC
= GPHOTO2_SaneCapability (pCapability
, MSG_GETCURRENT
);
140 return (activeDS
.twCC
== TWCC_SUCCESS
)?TWRC_SUCCESS
:TWRC_FAILURE
;
143 /* DG_CONTROL/DAT_CAPABILITY/MSG_GETDEFAULT */
144 static TW_UINT16
GPHOTO2_CapabilityGetDefault (pTW_IDENTITY pOrigin
, TW_MEMREF pData
)
146 pTW_CAPABILITY pCapability
= (pTW_CAPABILITY
) pData
;
148 TRACE("DG_CONTROL/DAT_CAPABILITY/MSG_GETDEFAULT\n");
149 if (activeDS
.currentState
< 4 || activeDS
.currentState
> 7) {
150 activeDS
.twCC
= TWCC_SEQERROR
;
153 activeDS
.twCC
= GPHOTO2_SaneCapability (pCapability
, MSG_GETDEFAULT
);
154 return (activeDS
.twCC
== TWCC_SUCCESS
)?TWRC_SUCCESS
:TWRC_FAILURE
;
157 /* DG_CONTROL/DAT_CAPABILITY/MSG_QUERYSUPPORT */
158 static TW_UINT16
GPHOTO2_CapabilityQuerySupport (pTW_IDENTITY pOrigin
,
166 /* DG_CONTROL/DAT_CAPABILITY/MSG_RESET */
167 static TW_UINT16
GPHOTO2_CapabilityReset (pTW_IDENTITY pOrigin
,
170 pTW_CAPABILITY pCapability
= (pTW_CAPABILITY
) pData
;
172 TRACE("DG_CONTROL/DAT_CAPABILITY/MSG_RESET\n");
174 if (activeDS
.currentState
< 4 || activeDS
.currentState
> 7) {
175 activeDS
.twCC
= TWCC_SEQERROR
;
178 activeDS
.twCC
= GPHOTO2_SaneCapability (pCapability
, MSG_RESET
);
179 return (activeDS
.twCC
== TWCC_SUCCESS
)?TWRC_SUCCESS
:TWRC_FAILURE
;
182 /* DG_CONTROL/DAT_CAPABILITY/MSG_SET */
183 static TW_UINT16
GPHOTO2_CapabilitySet (pTW_IDENTITY pOrigin
,
186 pTW_CAPABILITY pCapability
= (pTW_CAPABILITY
) pData
;
188 TRACE ("DG_CONTROL/DAT_CAPABILITY/MSG_SET\n");
190 if (activeDS
.currentState
!= 4) {
191 activeDS
.twCC
= TWCC_SEQERROR
;
194 activeDS
.twCC
= GPHOTO2_SaneCapability (pCapability
, MSG_SET
);
195 return (activeDS
.twCC
== TWCC_SUCCESS
)?TWRC_SUCCESS
:TWRC_FAILURE
;
198 /* DG_CONTROL/DAT_CUSTOMDSDATA/MSG_GET */
199 static TW_UINT16
GPHOTO2_CustomDSDataGet (pTW_IDENTITY pOrigin
,
207 /* DG_CONTROL/DAT_CUSTOMDSDATA/MSG_SET */
208 static TW_UINT16
GPHOTO2_CustomDSDataSet (pTW_IDENTITY pOrigin
,
216 /* DG_CONTROL/DAT_FILESYSTEM/MSG_CHANGEDIRECTORY */
217 static TW_UINT16
GPHOTO2_ChangeDirectory (pTW_IDENTITY pOrigin
,
225 /* DG_CONTROL/DAT_FILESYSTEM/MSG_CREATEDIRECTORY */
226 static TW_UINT16
GPHOTO2_CreateDirectory (pTW_IDENTITY pOrigin
,
234 /* DG_CONTROL/DAT_FILESYSTEM/MSG_DELETE */
235 static TW_UINT16
GPHOTO2_FileSystemDelete (pTW_IDENTITY pOrigin
,
243 /* DG_CONTROL/DAT_FILESYSTEM/MSG_FORMATMEDIA */
244 static TW_UINT16
GPHOTO2_FormatMedia (pTW_IDENTITY pOrigin
,
252 /* DG_CONTROL/DAT_FILESYSTEM/MSG_GETCLOSE */
253 static TW_UINT16
GPHOTO2_FileSystemGetClose (pTW_IDENTITY pOrigin
,
261 /* DG_CONTROL/DAT_FILESYSTEM/MSG_GETFIRSTFILE */
262 static TW_UINT16
GPHOTO2_FileSystemGetFirstFile (pTW_IDENTITY pOrigin
,
271 /* DG_CONTROL/DAT_FILESYSTEM/MSG_GETINFO */
272 static TW_UINT16
GPHOTO2_FileSystemGetInfo (pTW_IDENTITY pOrigin
,
280 /* DG_CONTROL/DAT_FILESYSTEM/MSG_GETNEXTFILE */
281 static TW_UINT16
GPHOTO2_FileSystemGetNextFile (pTW_IDENTITY pOrigin
,
290 /* DG_CONTROL/DAT_FILESYSTEM/MSG_RENAME */
291 static TW_UINT16
GPHOTO2_FileSystemRename (pTW_IDENTITY pOrigin
,
299 static void GPHOTO2_Notify (TW_UINT16 message
)
301 GPHOTO2_dsmentry (&activeDS
.identity
, &activeDS
.appIdentity
, DG_CONTROL
, DAT_NULL
, message
, NULL
);
304 /* DG_CONTROL/DAT_ENTRYPOINT/MSG_SET */
305 static TW_UINT16
GPHOTO2_SetEntryPoint (pTW_IDENTITY pOrigin
, TW_MEMREF pData
)
307 TW_ENTRYPOINT
*entry
= (TW_ENTRYPOINT
*)pData
;
309 GPHOTO2_dsmentry
= entry
->DSM_Entry
;
314 /* DG_CONTROL/DAT_EVENT/MSG_PROCESSEVENT */
315 static TW_UINT16
GPHOTO2_ProcessEvent (pTW_IDENTITY pOrigin
,
318 pTW_EVENT pEvent
= (pTW_EVENT
) pData
;
320 TRACE("DG_CONTROL/DAT_EVENT/MSG_PROCESSEVENT\n");
322 if (activeDS
.currentState
< 5 || activeDS
.currentState
> 7) {
323 activeDS
.twCC
= TWCC_SEQERROR
;
327 pEvent
->TWMessage
= MSG_NULL
; /* no message to the application */
328 activeDS
.twCC
= TWCC_SUCCESS
;
329 return TWRC_NOTDSEVENT
;
332 /* DG_CONTROL/DAT_PASSTHRU/MSG_PASSTHRU */
333 static TW_UINT16
GPHOTO2_PassThrough (pTW_IDENTITY pOrigin
,
341 /* DG_CONTROL/DAT_PENDINGXFERS/MSG_ENDXFER */
342 static TW_UINT16
GPHOTO2_PendingXfersEndXfer (pTW_IDENTITY pOrigin
,
346 pTW_PENDINGXFERS pPendingXfers
= (pTW_PENDINGXFERS
) pData
;
347 struct gphoto2_file
*file
;
349 TRACE("DG_CONTROL/DAT_PENDINGXFERS/MSG_ENDXFER\n");
351 if (activeDS
.currentState
!= 6 && activeDS
.currentState
!= 7) {
352 activeDS
.twCC
= TWCC_SEQERROR
;
356 LIST_FOR_EACH_ENTRY( file
, &activeDS
.files
, struct gphoto2_file
, entry
) {
360 TRACE("count = %d\n", count
);
361 pPendingXfers
->Count
= count
;
362 if (pPendingXfers
->Count
!= 0) {
363 activeDS
.currentState
= 6;
365 activeDS
.currentState
= 5;
366 /* Notify the application that it can close the data source */
367 GPHOTO2_Notify(MSG_CLOSEDSREQ
);
368 /* close any Transferring dialog */
369 TransferringDialogBox(activeDS
.progressWnd
,-1);
370 activeDS
.progressWnd
= 0;
372 activeDS
.twCC
= TWCC_SUCCESS
;
376 /* DG_CONTROL/DAT_PENDINGXFERS/MSG_GET */
377 static TW_UINT16
GPHOTO2_PendingXfersGet (pTW_IDENTITY pOrigin
,
381 pTW_PENDINGXFERS pPendingXfers
= (pTW_PENDINGXFERS
) pData
;
382 struct gphoto2_file
*file
;
384 TRACE("DG_CONTROL/DAT_PENDINGXFERS/MSG_GET\n");
386 if (activeDS
.currentState
< 4 || activeDS
.currentState
> 7) {
387 activeDS
.twCC
= TWCC_SEQERROR
;
392 LIST_FOR_EACH_ENTRY( file
, &activeDS
.files
, struct gphoto2_file
, entry
) {
396 TRACE("count = %d\n", count
);
397 pPendingXfers
->Count
= count
;
398 activeDS
.twCC
= TWCC_SUCCESS
;
402 /* DG_CONTROL/DAT_PENDINGXFERS/MSG_RESET */
403 static TW_UINT16
GPHOTO2_PendingXfersReset (pTW_IDENTITY pOrigin
,
406 pTW_PENDINGXFERS pPendingXfers
= (pTW_PENDINGXFERS
) pData
;
408 TRACE("DG_CONTROL/DAT_PENDINGXFERS/MSG_RESET\n");
410 if (activeDS
.currentState
!= 6) {
411 activeDS
.twCC
= TWCC_SEQERROR
;
414 pPendingXfers
->Count
= 0;
415 activeDS
.currentState
= 5;
416 activeDS
.twCC
= TWCC_SUCCESS
;
420 /* DG_CONTROL/DAT_SETUPFILEXFER/MSG_GET */
421 static TW_UINT16
GPHOTO2_SetupFileXferGet (pTW_IDENTITY pOrigin
,
429 /* DG_CONTROL/DAT_SETUPXFER/MSG_GETDEFAULT */
430 static TW_UINT16
GPHOTO2_SetupFileXferGetDefault (pTW_IDENTITY pOrigin
,
439 /* DG_CONTROL/DAT_SETUPFILEXFER/MSG_RESET */
440 static TW_UINT16
GPHOTO2_SetupFileXferReset (pTW_IDENTITY pOrigin
,
448 /* DG_CONTROL/DAT_SETUPFILEXFER/MSG_SET */
449 static TW_UINT16
GPHOTO2_SetupFileXferSet (pTW_IDENTITY pOrigin
,
457 /* DG_CONTROL/DAT_SETUPMEMXFER/MSG_GET */
458 static TW_UINT16
GPHOTO2_SetupMemXferGet (pTW_IDENTITY pOrigin
,
461 pTW_SETUPMEMXFER pSetupMemXfer
= (pTW_SETUPMEMXFER
)pData
;
463 TRACE("DG_CONTROL/DAT_SETUPMEMXFER/MSG_GET\n");
465 pSetupMemXfer
->MinBufSize
= 20000;
466 pSetupMemXfer
->MaxBufSize
= 80000;
467 pSetupMemXfer
->Preferred
= 40000;
471 /* DG_CONTROL/DAT_STATUS/MSG_GET */
472 static TW_UINT16
GPHOTO2_GetDSStatus (pTW_IDENTITY pOrigin
,
475 pTW_STATUS pSourceStatus
= (pTW_STATUS
) pData
;
477 TRACE ("DG_CONTROL/DAT_STATUS/MSG_GET\n");
478 pSourceStatus
->ConditionCode
= activeDS
.twCC
;
479 /* Reset the condition code */
480 activeDS
.twCC
= TWCC_SUCCESS
;
484 /* DG_CONTROL/DAT_USERINTERFACE/MSG_DISABLEDS */
485 static TW_UINT16
GPHOTO2_DisableDSUserInterface (pTW_IDENTITY pOrigin
,
488 TRACE ("DG_CONTROL/DAT_USERINTERFACE/MSG_DISABLEDS\n");
490 if (activeDS
.currentState
!= 5) {
491 activeDS
.twCC
= TWCC_SEQERROR
;
494 activeDS
.currentState
= 4;
495 activeDS
.twCC
= TWCC_SUCCESS
;
499 /* DG_CONTROL/DAT_USERINTERFACE/MSG_ENABLEDS */
500 static TW_UINT16
GPHOTO2_EnableDSUserInterface (pTW_IDENTITY pOrigin
,
503 pTW_USERINTERFACE pUserInterface
= (pTW_USERINTERFACE
) pData
;
505 load_filesystem("/");
507 TRACE ("DG_CONTROL/DAT_USERINTERFACE/MSG_ENABLEDS\n");
508 if (activeDS
.currentState
!= 4) {
509 FIXME("Sequence error %d\n", activeDS
.currentState
);
510 activeDS
.twCC
= TWCC_SEQERROR
;
513 if (pUserInterface
->ShowUI
)
516 activeDS
.currentState
= 5; /* Transitions to state 5 */
519 GPHOTO2_Notify(MSG_CLOSEDSREQ
);
521 /* FIXME: The GUI should have marked the files to download... */
522 GPHOTO2_Notify(MSG_XFERREADY
);
523 activeDS
.currentState
= 6; /* Transitions to state 6 directly */
526 /* no UI will be displayed, so source is ready to transfer data */
527 GPHOTO2_Notify(MSG_XFERREADY
);
528 activeDS
.currentState
= 6; /* Transitions to state 6 directly */
530 activeDS
.twCC
= TWCC_SUCCESS
;
534 /* DG_CONTROL/DAT_USERINTERFACE/MSG_ENABLEDSUIONLY */
535 static TW_UINT16
GPHOTO2_EnableDSUIOnly (pTW_IDENTITY pOrigin
,
538 TRACE("DG_CONTROL/DAT_USERINTERFACE/MSG_ENABLEDSUIONLY\n");
540 if (activeDS
.currentState
!= 4) {
541 activeDS
.twCC
= TWCC_SEQERROR
;
544 /* FIXME: we should replace xscanimage with our own UI */
545 FIXME ("not implemented!\n");
546 activeDS
.currentState
= 5;
547 activeDS
.twCC
= TWCC_SUCCESS
;
551 /* DG_CONTROL/DAT_XFERGROUP/MSG_GET */
552 static TW_UINT16
GPHOTO2_XferGroupGet (pTW_IDENTITY pOrigin
,
559 /* DG_CONTROL/DAT_XFERGROUP/MSG_SET */
560 static TW_UINT16
GPHOTO2_XferGroupSet (pTW_IDENTITY pOrigin
,
567 HINSTANCE GPHOTO2_instance
;
569 BOOL WINAPI
DllMain (HINSTANCE hinstDLL
, DWORD fdwReason
, LPVOID lpvReserved
)
571 TRACE("%p,%x,%p\n", hinstDLL
, fdwReason
, lpvReserved
);
575 case DLL_PROCESS_ATTACH
:
576 GPHOTO2_instance
= hinstDLL
;
577 DisableThreadLibraryCalls(hinstDLL
);
579 activeDS
.context
= gp_context_new ();
587 #if defined(HAVE_GPHOTO2) && defined(HAVE_GPHOTO2_PORT)
588 static TW_UINT16
GPHOTO2_GetIdentity( pTW_IDENTITY
, pTW_IDENTITY
);
589 static TW_UINT16
GPHOTO2_OpenDS( pTW_IDENTITY
, pTW_IDENTITY
);
592 static TW_UINT16
GPHOTO2_SourceControlHandler (
593 pTW_IDENTITY pOrigin
,
598 TW_UINT16 twRC
= TWRC_SUCCESS
;
606 #if defined(HAVE_GPHOTO2) && defined(HAVE_GPHOTO2_PORT)
607 if (activeDS
.camera
) {
608 gp_camera_free (activeDS
.camera
);
609 activeDS
.camera
= NULL
;
614 #if defined(HAVE_GPHOTO2) && defined(HAVE_GPHOTO2_PORT)
615 twRC
= GPHOTO2_GetIdentity(pOrigin
,(pTW_IDENTITY
)pData
);
621 #if defined(HAVE_GPHOTO2) && defined(HAVE_GPHOTO2_PORT)
622 twRC
= GPHOTO2_OpenDS(pOrigin
,(pTW_IDENTITY
)pData
);
633 twRC
= GPHOTO2_CapabilityGet (pOrigin
, pData
);
636 twRC
= GPHOTO2_CapabilityGetCurrent (pOrigin
, pData
);
639 twRC
= GPHOTO2_CapabilityGetDefault (pOrigin
, pData
);
641 case MSG_QUERYSUPPORT
:
642 twRC
= GPHOTO2_CapabilityQuerySupport (pOrigin
, pData
);
645 twRC
= GPHOTO2_CapabilityReset (pOrigin
, pData
);
648 twRC
= GPHOTO2_CapabilitySet (pOrigin
, pData
);
652 FIXME("unrecognized operation triplet\n");
656 case DAT_CUSTOMDSDATA
:
660 twRC
= GPHOTO2_CustomDSDataGet (pOrigin
, pData
);
663 twRC
= GPHOTO2_CustomDSDataSet (pOrigin
, pData
);
673 /*case MSG_AUTOMATICCAPTUREDIRECTORY:
674 twRC = GPHOTO2_AutomaticCaptureDirectory
677 case MSG_CHANGEDIRECTORY
:
678 twRC
= GPHOTO2_ChangeDirectory (pOrigin
, pData
);
681 twRC = GPHOTO2_FileSystemCopy (pOrigin, pData);
683 case MSG_CREATEDIRECTORY
:
684 twRC
= GPHOTO2_CreateDirectory (pOrigin
, pData
);
687 twRC
= GPHOTO2_FileSystemDelete (pOrigin
, pData
);
689 case MSG_FORMATMEDIA
:
690 twRC
= GPHOTO2_FormatMedia (pOrigin
, pData
);
693 twRC
= GPHOTO2_FileSystemGetClose (pOrigin
, pData
);
695 case MSG_GETFIRSTFILE
:
696 twRC
= GPHOTO2_FileSystemGetFirstFile (pOrigin
, pData
);
699 twRC
= GPHOTO2_FileSystemGetInfo (pOrigin
, pData
);
701 case MSG_GETNEXTFILE
:
702 twRC
= GPHOTO2_FileSystemGetNextFile (pOrigin
, pData
);
705 twRC
= GPHOTO2_FileSystemRename (pOrigin
, pData
);
715 twRC
= GPHOTO2_SetEntryPoint (pOrigin
, pData
);
721 if (MSG
== MSG_PROCESSEVENT
)
722 twRC
= GPHOTO2_ProcessEvent (pOrigin
, pData
);
728 if (MSG
== MSG_PASSTHRU
)
729 twRC
= GPHOTO2_PassThrough (pOrigin
, pData
);
734 case DAT_PENDINGXFERS
:
738 twRC
= GPHOTO2_PendingXfersEndXfer (pOrigin
, pData
);
741 twRC
= GPHOTO2_PendingXfersGet (pOrigin
, pData
);
744 twRC
= GPHOTO2_PendingXfersReset (pOrigin
, pData
);
746 /*case MSG_STOPFEEDER:
747 twRC = GPHOTO2_PendingXfersStopFeeder (pOrigin, pData);
754 case DAT_SETUPFILEXFER
:
758 twRC
= GPHOTO2_SetupFileXferGet (pOrigin
, pData
);
761 twRC
= GPHOTO2_SetupFileXferGetDefault (pOrigin
, pData
);
764 twRC
= GPHOTO2_SetupFileXferReset (pOrigin
, pData
);
767 twRC
= GPHOTO2_SetupFileXferSet (pOrigin
, pData
);
775 /*case DAT_SETUPFILEXFER2:
779 twRC = GPHOTO2_SetupFileXfer2Get (pOrigin, pData);
782 twRC = GPHOTO2_SetupFileXfer2GetDefault (pOrigin, pData);
785 twRC = GPHOTO2_SetupFileXfer2Reset (pOrigin, pData);
788 twRC = GPHOTO2_SetupFileXfer2Set (pOrigin, pData);
792 case DAT_SETUPMEMXFER
:
794 twRC
= GPHOTO2_SetupMemXferGet (pOrigin
, pData
);
801 twRC
= GPHOTO2_GetDSStatus (pOrigin
, pData
);
806 case DAT_USERINTERFACE
:
810 twRC
= GPHOTO2_DisableDSUserInterface (pOrigin
, pData
);
813 twRC
= GPHOTO2_EnableDSUserInterface (pOrigin
, pData
);
815 case MSG_ENABLEDSUIONLY
:
816 twRC
= GPHOTO2_EnableDSUIOnly (pOrigin
, pData
);
828 twRC
= GPHOTO2_XferGroupGet (pOrigin
, pData
);
831 twRC
= GPHOTO2_XferGroupSet (pOrigin
, pData
);
840 FIXME("code unknown: %d\n", DAT
);
849 static TW_UINT16
GPHOTO2_ImageGroupHandler (
850 pTW_IDENTITY pOrigin
,
855 TW_UINT16 twRC
= TWRC_SUCCESS
;
861 twRC
= GPHOTO2_CIEColorGet (pOrigin
, pData
);
866 case DAT_EXTIMAGEINFO
:
868 twRC
= GPHOTO2_ExtImageInfoGet (pOrigin
, pData
);
873 case DAT_GRAYRESPONSE
:
877 twRC
= GPHOTO2_GrayResponseReset (pOrigin
, pData
);
880 twRC
= GPHOTO2_GrayResponseSet (pOrigin
, pData
);
884 activeDS
.twCC
= TWCC_BADPROTOCOL
;
885 FIXME("unrecognized operation triplet\n");
889 case DAT_IMAGEFILEXFER
:
891 twRC
= GPHOTO2_ImageFileXferGet (pOrigin
, pData
);
898 twRC
= GPHOTO2_ImageInfoGet (pOrigin
, pData
);
903 case DAT_IMAGELAYOUT
:
907 twRC
= GPHOTO2_ImageLayoutGet (pOrigin
, pData
);
910 twRC
= GPHOTO2_ImageLayoutGetDefault (pOrigin
, pData
);
913 twRC
= GPHOTO2_ImageLayoutReset (pOrigin
, pData
);
916 twRC
= GPHOTO2_ImageLayoutSet (pOrigin
, pData
);
920 activeDS
.twCC
= TWCC_BADPROTOCOL
;
921 ERR("unrecognized operation triplet\n");
926 case DAT_IMAGEMEMXFER
:
928 twRC
= GPHOTO2_ImageMemXferGet (pOrigin
, pData
);
933 case DAT_IMAGENATIVEXFER
:
935 twRC
= GPHOTO2_ImageNativeXferGet (pOrigin
, pData
);
940 case DAT_JPEGCOMPRESSION
:
944 twRC
= GPHOTO2_JPEGCompressionGet (pOrigin
, pData
);
947 twRC
= GPHOTO2_JPEGCompressionGetDefault (pOrigin
, pData
);
950 twRC
= GPHOTO2_JPEGCompressionReset (pOrigin
, pData
);
953 twRC
= GPHOTO2_JPEGCompressionSet (pOrigin
, pData
);
957 activeDS
.twCC
= TWCC_BADPROTOCOL
;
958 WARN("unrecognized operation triplet\n");
967 twRC
= GPHOTO2_Palette8Get (pOrigin
, pData
);
970 twRC
= GPHOTO2_Palette8GetDefault (pOrigin
, pData
);
973 twRC
= GPHOTO2_Palette8Reset (pOrigin
, pData
);
976 twRC
= GPHOTO2_Palette8Set (pOrigin
, pData
);
980 activeDS
.twCC
= TWCC_BADPROTOCOL
;
981 WARN("unrecognized operation triplet\n");
985 case DAT_RGBRESPONSE
:
989 twRC
= GPHOTO2_RGBResponseReset (pOrigin
, pData
);
992 twRC
= GPHOTO2_RGBResponseSet (pOrigin
, pData
);
996 activeDS
.twCC
= TWCC_BADPROTOCOL
;
997 WARN("unrecognized operation triplet\n");
1003 twRC
= TWRC_FAILURE
;
1004 activeDS
.twCC
= TWCC_BADPROTOCOL
;
1005 FIXME("unrecognized DG type %d\n", DAT
);
1010 /* Main entry point for the TWAIN library */
1012 DS_Entry ( pTW_IDENTITY pOrigin
,
1018 TW_UINT16 twRC
= TWRC_SUCCESS
; /* Return Code */
1020 TRACE("(DG=%d DAT=%d MSG=%d)\n", DG
, DAT
, MSG
);
1025 twRC
= GPHOTO2_SourceControlHandler (pOrigin
,DAT
,MSG
,pData
);
1028 twRC
= GPHOTO2_ImageGroupHandler (pOrigin
,DAT
,MSG
,pData
);
1031 FIXME("The audio group of entry codes is not implemented.\n");
1033 activeDS
.twCC
= TWCC_BADPROTOCOL
;
1034 twRC
= TWRC_FAILURE
;
1040 #if defined(HAVE_GPHOTO2) && defined(HAVE_GPHOTO2_PORT)
1041 static GPPortInfoList
*port_list
;
1042 static int curcamera
;
1043 static CameraList
*detected_cameras
;
1044 static CameraAbilitiesList
*abilities_list
;
1047 gphoto2_auto_detect(void) {
1050 if (detected_cameras
&& (gp_list_count (detected_cameras
) == 0)) {
1051 /* Reload if previously no cameras, we might detect new ones. */
1052 TRACE("Reloading portlist trying to detect cameras.\n");
1054 gp_port_info_list_free (port_list
);
1059 TRACE("Auto detecting gphoto cameras.\n");
1060 TRACE("Loading ports...\n");
1061 if (gp_port_info_list_new (&port_list
) < GP_OK
)
1062 return TWRC_FAILURE
;
1063 result
= gp_port_info_list_load (port_list
);
1065 gp_port_info_list_free (port_list
);
1066 return TWRC_FAILURE
;
1068 count
= gp_port_info_list_count (port_list
);
1070 return TWRC_FAILURE
;
1071 if (gp_list_new (&detected_cameras
) < GP_OK
)
1072 return TWRC_FAILURE
;
1073 if (!abilities_list
) { /* Load only once per program start */
1074 gp_abilities_list_new (&abilities_list
);
1075 TRACE("Loading cameras...\n");
1076 gp_abilities_list_load (abilities_list
, NULL
);
1078 TRACE("Detecting cameras...\n");
1079 gp_abilities_list_detect (abilities_list
, port_list
, detected_cameras
, NULL
);
1081 TRACE("%d cameras detected\n", gp_list_count(detected_cameras
));
1083 return TWRC_SUCCESS
;
1087 GPHOTO2_GetIdentity( pTW_IDENTITY pOrigin
, pTW_IDENTITY self
) {
1089 const char *cname
, *pname
;
1091 if (TWRC_SUCCESS
!= gphoto2_auto_detect())
1092 return TWRC_FAILURE
;
1094 count
= gp_list_count (detected_cameras
);
1095 if (count
< GP_OK
) {
1096 gp_list_free (detected_cameras
);
1097 return TWRC_FAILURE
;
1099 TRACE("%d cameras detected.\n", count
);
1100 self
->ProtocolMajor
= TWON_PROTOCOLMAJOR
;
1101 self
->ProtocolMinor
= TWON_PROTOCOLMINOR
;
1102 self
->SupportedGroups
= DG_CONTROL
| DG_IMAGE
| DF_DS2
;
1103 lstrcpynA (self
->Manufacturer
, "The Wine Team", sizeof(self
->Manufacturer
) - 1);
1104 lstrcpynA (self
->ProductFamily
, "GPhoto2 Camera", sizeof(self
->ProductFamily
) - 1);
1106 if (!count
) { /* No camera detected. But we need to return an IDENTITY anyway. */
1107 lstrcpynA (self
->ProductName
, "GPhoto2 Camera", sizeof(self
->ProductName
) - 1);
1108 return TWRC_SUCCESS
;
1110 gp_list_get_name (detected_cameras
, curcamera
, &cname
);
1111 gp_list_get_value (detected_cameras
, curcamera
, &pname
);
1112 if (count
== 1) /* Normal case, only one camera. */
1113 snprintf (self
->ProductName
, sizeof(self
->ProductName
), "%s", cname
);
1115 snprintf (self
->ProductName
, sizeof(self
->ProductName
), "%s@%s", cname
, pname
);
1116 curcamera
= (curcamera
+1) % count
;
1117 return TWRC_SUCCESS
;
1121 GPHOTO2_OpenDS( pTW_IDENTITY pOrigin
, pTW_IDENTITY self
) {
1122 int ret
, m
, p
, count
, i
;
1125 const char *model
, *port
;
1127 if (GPHOTO2_dsmentry
== NULL
)
1129 static const WCHAR twain32W
[] = {'t','w','a','i','n','_','3','2',0};
1130 HMODULE moddsm
= GetModuleHandleW(twain32W
);
1133 GPHOTO2_dsmentry
= (void*)GetProcAddress(moddsm
, "DSM_Entry");
1135 if (!GPHOTO2_dsmentry
)
1137 ERR("can't find DSM entry point\n");
1138 return TWRC_FAILURE
;
1142 if (TWRC_SUCCESS
!= gphoto2_auto_detect())
1143 return TWRC_FAILURE
;
1145 if (lstrcmpA(self
->ProductFamily
,"GPhoto2 Camera")) {
1146 FIXME("identity passed is not a gphoto camera, but %s!?!\n", self
->ProductFamily
);
1147 return TWRC_FAILURE
;
1149 count
= gp_list_count (detected_cameras
);
1151 ERR("No camera found by autodetection. Returning failure.\n");
1152 return TWRC_FAILURE
;
1155 if (!lstrcmpA (self
->ProductName
, "GPhoto2 Camera")) {
1156 TRACE("Potential undetected camera. Just using the first autodetected one.\n");
1159 for (i
=0;i
<count
;i
++) {
1160 const char *cname
, *pname
;
1163 gp_list_get_name (detected_cameras
, i
, &cname
);
1164 gp_list_get_value (detected_cameras
, i
, &pname
);
1165 if (!lstrcmpA(self
->ProductName
,cname
))
1167 snprintf(name
, sizeof(name
), "%s", cname
);
1168 if (!lstrcmpA(self
->ProductName
,name
))
1170 snprintf(name
, sizeof(name
), "%s@%s", cname
, pname
);
1171 if (!lstrcmpA(self
->ProductName
,name
))
1175 TRACE("Camera %s not found in autodetected list. Using first entry.\n", self
->ProductName
);
1179 gp_list_get_name (detected_cameras
, i
, &model
);
1180 gp_list_get_value (detected_cameras
, i
, &port
);
1181 TRACE("model %s, port %s\n", model
, port
);
1182 ret
= gp_camera_new (&activeDS
.camera
);
1184 ERR("gp_camera_new: %d\n", ret
);
1185 return TWRC_FAILURE
;
1187 m
= gp_abilities_list_lookup_model (abilities_list
, model
);
1189 FIXME("Model %s not found, %d!\n", model
, m
);
1190 return TWRC_FAILURE
;
1192 ret
= gp_abilities_list_get_abilities (abilities_list
, m
, &a
);
1194 FIXME("gp_camera_list_get_abilities failed? %d\n", ret
);
1195 return TWRC_FAILURE
;
1197 ret
= gp_camera_set_abilities (activeDS
.camera
, a
);
1199 FIXME("gp_camera_set_abilities failed? %d\n", ret
);
1200 return TWRC_FAILURE
;
1203 p
= gp_port_info_list_lookup_path (port_list
, port
);
1205 FIXME("port %s not in portlist?\n", port
);
1206 return TWRC_FAILURE
;
1208 ret
= gp_port_info_list_get_info (port_list
, p
, &info
);
1210 FIXME("could not get portinfo for port %s?\n", port
);
1211 return TWRC_FAILURE
;
1213 ret
= gp_camera_set_port_info (activeDS
.camera
, info
);
1215 FIXME("could not set portinfo for port %s to camera?\n", port
);
1216 return TWRC_FAILURE
;
1218 list_init( &(activeDS
.files
) );
1219 activeDS
.currentState
= 4;
1220 activeDS
.twCC
= TWRC_SUCCESS
;
1221 activeDS
.pixelflavor
= TWPF_CHOCOLATE
;
1222 activeDS
.pixeltype
= TWPT_RGB
;
1223 activeDS
.capXferMech
= TWSX_MEMORY
;
1224 activeDS
.identity
.Id
= self
->Id
;
1225 activeDS
.appIdentity
= *pOrigin
;
1227 return TWRC_SUCCESS
;