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
34 #include "gphoto2_i.h"
35 #include "wine/debug.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(twain
);
41 load_filesystem(const char *folder
) {
46 ret
= gp_list_new (&list
);
49 ret
= gp_camera_folder_list_files (activeDS
.camera
, folder
, list
, activeDS
.context
);
54 count
= gp_list_count (list
);
59 for (i
= 0; i
< count
; i
++) {
61 struct gphoto2_file
*gpfile
;
63 ret
= gp_list_get_name (list
, i
, &name
);
66 gpfile
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct gphoto2_file
));
69 TRACE("adding %s/%s\n", folder
, name
);
70 gpfile
->folder
= strdup(folder
);
71 gpfile
->filename
= strdup(name
);
72 gpfile
->download
= FALSE
;
73 list_add_tail( &activeDS
.files
, &gpfile
->entry
);
77 ret
= gp_camera_folder_list_folders (activeDS
.camera
, folder
, list
, activeDS
.context
);
79 FIXME("list_folders failed\n");
83 count
= gp_list_count (list
);
85 FIXME("list_folders failed\n");
89 for (i
= 0; i
< count
; i
++) {
92 ret
= gp_list_get_name (list
, i
, &name
);
95 TRACE("recursing into %s\n", name
);
96 newfolder
= HeapAlloc(GetProcessHeap(), 0, strlen(folder
)+1+strlen(name
)+1);
97 if (!strcmp(folder
,"/"))
98 sprintf (newfolder
, "/%s", name
);
100 sprintf (newfolder
, "%s/%s", folder
, name
);
101 load_filesystem (newfolder
); /* recurse ... happily */
107 /* DG_CONTROL/DAT_CAPABILITY/MSG_GET */
108 static TW_UINT16
GPHOTO2_CapabilityGet (pTW_IDENTITY pOrigin
, TW_MEMREF pData
)
110 pTW_CAPABILITY pCapability
= (pTW_CAPABILITY
) pData
;
112 TRACE("DG_CONTROL/DAT_CAPABILITY/MSG_GET\n");
113 if (activeDS
.currentState
< 4 || activeDS
.currentState
> 7) {
114 activeDS
.twCC
= TWCC_SEQERROR
;
117 activeDS
.twCC
= GPHOTO2_SaneCapability (pCapability
, MSG_GET
);
118 return (activeDS
.twCC
== TWCC_SUCCESS
)?TWRC_SUCCESS
:TWRC_FAILURE
;
121 /* DG_CONTROL/DAT_CAPABILITY/MSG_GETCURRENT */
122 static TW_UINT16
GPHOTO2_CapabilityGetCurrent (pTW_IDENTITY pOrigin
, TW_MEMREF pData
)
124 pTW_CAPABILITY pCapability
= (pTW_CAPABILITY
) pData
;
126 TRACE("DG_CONTROL/DAT_CAPABILITY/MSG_GETCURRENT\n");
128 if (activeDS
.currentState
< 4 || activeDS
.currentState
> 7) {
129 activeDS
.twCC
= TWCC_SEQERROR
;
132 activeDS
.twCC
= GPHOTO2_SaneCapability (pCapability
, MSG_GETCURRENT
);
133 return (activeDS
.twCC
== TWCC_SUCCESS
)?TWRC_SUCCESS
:TWRC_FAILURE
;
136 /* DG_CONTROL/DAT_CAPABILITY/MSG_GETDEFAULT */
137 static TW_UINT16
GPHOTO2_CapabilityGetDefault (pTW_IDENTITY pOrigin
, TW_MEMREF pData
)
139 pTW_CAPABILITY pCapability
= (pTW_CAPABILITY
) pData
;
141 TRACE("DG_CONTROL/DAT_CAPABILITY/MSG_GETDEFAULT\n");
142 if (activeDS
.currentState
< 4 || activeDS
.currentState
> 7) {
143 activeDS
.twCC
= TWCC_SEQERROR
;
146 activeDS
.twCC
= GPHOTO2_SaneCapability (pCapability
, MSG_GETDEFAULT
);
147 return (activeDS
.twCC
== TWCC_SUCCESS
)?TWRC_SUCCESS
:TWRC_FAILURE
;
150 /* DG_CONTROL/DAT_CAPABILITY/MSG_QUERYSUPPORT */
151 static TW_UINT16
GPHOTO2_CapabilityQuerySupport (pTW_IDENTITY pOrigin
,
159 /* DG_CONTROL/DAT_CAPABILITY/MSG_RESET */
160 static TW_UINT16
GPHOTO2_CapabilityReset (pTW_IDENTITY pOrigin
,
163 pTW_CAPABILITY pCapability
= (pTW_CAPABILITY
) pData
;
165 TRACE("DG_CONTROL/DAT_CAPABILITY/MSG_RESET\n");
167 if (activeDS
.currentState
< 4 || activeDS
.currentState
> 7) {
168 activeDS
.twCC
= TWCC_SEQERROR
;
171 activeDS
.twCC
= GPHOTO2_SaneCapability (pCapability
, MSG_RESET
);
172 return (activeDS
.twCC
== TWCC_SUCCESS
)?TWRC_SUCCESS
:TWRC_FAILURE
;
175 /* DG_CONTROL/DAT_CAPABILITY/MSG_SET */
176 static TW_UINT16
GPHOTO2_CapabilitySet (pTW_IDENTITY pOrigin
,
179 pTW_CAPABILITY pCapability
= (pTW_CAPABILITY
) pData
;
181 TRACE ("DG_CONTROL/DAT_CAPABILITY/MSG_SET\n");
183 if (activeDS
.currentState
!= 4) {
184 activeDS
.twCC
= TWCC_SEQERROR
;
187 activeDS
.twCC
= GPHOTO2_SaneCapability (pCapability
, MSG_SET
);
188 return (activeDS
.twCC
== TWCC_SUCCESS
)?TWRC_SUCCESS
:TWRC_FAILURE
;
191 /* DG_CONTROL/DAT_CUSTOMDSDATA/MSG_GET */
192 static TW_UINT16
GPHOTO2_CustomDSDataGet (pTW_IDENTITY pOrigin
,
200 /* DG_CONTROL/DAT_CUSTOMDSDATA/MSG_SET */
201 static TW_UINT16
GPHOTO2_CustomDSDataSet (pTW_IDENTITY pOrigin
,
209 /* DG_CONTROL/DAT_FILESYSTEM/MSG_CHANGEDIRECTORY */
210 static TW_UINT16
GPHOTO2_ChangeDirectory (pTW_IDENTITY pOrigin
,
218 /* DG_CONTROL/DAT_FILESYSTEM/MSG_CREATEDIRECTORY */
219 static TW_UINT16
GPHOTO2_CreateDirectory (pTW_IDENTITY pOrigin
,
227 /* DG_CONTROL/DAT_FILESYSTEM/MSG_DELETE */
228 static TW_UINT16
GPHOTO2_FileSystemDelete (pTW_IDENTITY pOrigin
,
236 /* DG_CONTROL/DAT_FILESYSTEM/MSG_FORMATMEDIA */
237 static TW_UINT16
GPHOTO2_FormatMedia (pTW_IDENTITY pOrigin
,
245 /* DG_CONTROL/DAT_FILESYSTEM/MSG_GETCLOSE */
246 static TW_UINT16
GPHOTO2_FileSystemGetClose (pTW_IDENTITY pOrigin
,
254 /* DG_CONTROL/DAT_FILESYSTEM/MSG_GETFIRSTFILE */
255 static TW_UINT16
GPHOTO2_FileSystemGetFirstFile (pTW_IDENTITY pOrigin
,
264 /* DG_CONTROL/DAT_FILESYSTEM/MSG_GETINFO */
265 static TW_UINT16
GPHOTO2_FileSystemGetInfo (pTW_IDENTITY pOrigin
,
273 /* DG_CONTROL/DAT_FILESYSTEM/MSG_GETNEXTFILE */
274 static TW_UINT16
GPHOTO2_FileSystemGetNextFile (pTW_IDENTITY pOrigin
,
283 /* DG_CONTROL/DAT_FILESYSTEM/MSG_RENAME */
284 static TW_UINT16
GPHOTO2_FileSystemRename (pTW_IDENTITY pOrigin
,
292 /* DG_CONTROL/DAT_EVENT/MSG_PROCESSEVENT */
293 static TW_UINT16
GPHOTO2_ProcessEvent (pTW_IDENTITY pOrigin
,
296 TW_UINT16 twRC
= TWRC_SUCCESS
;
297 pTW_EVENT pEvent
= (pTW_EVENT
) pData
;
299 TRACE("DG_CONTROL/DAT_EVENT/MSG_PROCESSEVENT\n");
301 if (activeDS
.currentState
< 5 || activeDS
.currentState
> 7) {
302 activeDS
.twCC
= TWCC_SEQERROR
;
306 if (activeDS
.pendingEvent
.TWMessage
!= MSG_NULL
) {
307 pEvent
->TWMessage
= activeDS
.pendingEvent
.TWMessage
;
308 activeDS
.pendingEvent
.TWMessage
= MSG_NULL
;
311 pEvent
->TWMessage
= MSG_NULL
; /* no message to the application */
312 twRC
= TWRC_NOTDSEVENT
;
314 activeDS
.twCC
= TWCC_SUCCESS
;
318 /* DG_CONTROL/DAT_PASSTHRU/MSG_PASSTHRU */
319 static TW_UINT16
GPHOTO2_PassThrough (pTW_IDENTITY pOrigin
,
327 /* DG_CONTROL/DAT_PENDINGXFERS/MSG_ENDXFER */
328 static TW_UINT16
GPHOTO2_PendingXfersEndXfer (pTW_IDENTITY pOrigin
,
332 pTW_PENDINGXFERS pPendingXfers
= (pTW_PENDINGXFERS
) pData
;
333 struct gphoto2_file
*file
;
335 TRACE("DG_CONTROL/DAT_PENDINGXFERS/MSG_ENDXFER\n");
337 if (activeDS
.currentState
!= 6 && activeDS
.currentState
!= 7) {
338 activeDS
.twCC
= TWCC_SEQERROR
;
342 LIST_FOR_EACH_ENTRY( file
, &activeDS
.files
, struct gphoto2_file
, entry
) {
346 TRACE("count = %d\n", count
);
347 pPendingXfers
->Count
= count
;
348 if (pPendingXfers
->Count
!= 0) {
349 activeDS
.currentState
= 6;
351 activeDS
.currentState
= 5;
352 /* Notify the application that it can close the data source */
353 activeDS
.pendingEvent
.TWMessage
= MSG_CLOSEDSREQ
;
354 /* close any Transferring dialog */
355 TransferringDialogBox(activeDS
.progressWnd
,-1);
356 activeDS
.progressWnd
= 0;
358 activeDS
.twCC
= TWCC_SUCCESS
;
362 /* DG_CONTROL/DAT_PENDINGXFERS/MSG_GET */
363 static TW_UINT16
GPHOTO2_PendingXfersGet (pTW_IDENTITY pOrigin
,
367 pTW_PENDINGXFERS pPendingXfers
= (pTW_PENDINGXFERS
) pData
;
368 struct gphoto2_file
*file
;
370 TRACE("DG_CONTROL/DAT_PENDINGXFERS/MSG_GET\n");
372 if (activeDS
.currentState
< 4 || activeDS
.currentState
> 7) {
373 activeDS
.twCC
= TWCC_SEQERROR
;
378 LIST_FOR_EACH_ENTRY( file
, &activeDS
.files
, struct gphoto2_file
, entry
) {
382 TRACE("count = %d\n", count
);
383 pPendingXfers
->Count
= count
;
384 activeDS
.twCC
= TWCC_SUCCESS
;
388 /* DG_CONTROL/DAT_PENDINGXFERS/MSG_RESET */
389 static TW_UINT16
GPHOTO2_PendingXfersReset (pTW_IDENTITY pOrigin
,
392 pTW_PENDINGXFERS pPendingXfers
= (pTW_PENDINGXFERS
) pData
;
394 TRACE("DG_CONTROL/DAT_PENDINGXFERS/MSG_RESET\n");
396 if (activeDS
.currentState
!= 6) {
397 activeDS
.twCC
= TWCC_SEQERROR
;
400 pPendingXfers
->Count
= 0;
401 activeDS
.currentState
= 5;
402 activeDS
.twCC
= TWCC_SUCCESS
;
406 /* DG_CONTROL/DAT_SETUPFILEXFER/MSG_GET */
407 static TW_UINT16
GPHOTO2_SetupFileXferGet (pTW_IDENTITY pOrigin
,
415 /* DG_CONTROL/DAT_SETUPXFER/MSG_GETDEFAULT */
416 static TW_UINT16
GPHOTO2_SetupFileXferGetDefault (pTW_IDENTITY pOrigin
,
425 /* DG_CONTROL/DAT_SETUPFILEXFER/MSG_RESET */
426 static TW_UINT16
GPHOTO2_SetupFileXferReset (pTW_IDENTITY pOrigin
,
434 /* DG_CONTROL/DAT_SETUPFILEXFER/MSG_SET */
435 static TW_UINT16
GPHOTO2_SetupFileXferSet (pTW_IDENTITY pOrigin
,
443 /* DG_CONTROL/DAT_SETUPMEMXFER/MSG_GET */
444 static TW_UINT16
GPHOTO2_SetupMemXferGet (pTW_IDENTITY pOrigin
,
447 pTW_SETUPMEMXFER pSetupMemXfer
= (pTW_SETUPMEMXFER
)pData
;
449 TRACE("DG_CONTROL/DAT_SETUPMEMXFER/MSG_GET\n");
451 pSetupMemXfer
->MinBufSize
= 20000;
452 pSetupMemXfer
->MaxBufSize
= 80000;
453 pSetupMemXfer
->Preferred
= 40000;
457 /* DG_CONTROL/DAT_STATUS/MSG_GET */
458 static TW_UINT16
GPHOTO2_GetDSStatus (pTW_IDENTITY pOrigin
,
461 pTW_STATUS pSourceStatus
= (pTW_STATUS
) pData
;
463 TRACE ("DG_CONTROL/DAT_STATUS/MSG_GET\n");
464 pSourceStatus
->ConditionCode
= activeDS
.twCC
;
465 /* Reset the condition code */
466 activeDS
.twCC
= TWCC_SUCCESS
;
470 /* DG_CONTROL/DAT_USERINTERFACE/MSG_DISABLEDS */
471 static TW_UINT16
GPHOTO2_DisableDSUserInterface (pTW_IDENTITY pOrigin
,
474 TRACE ("DG_CONTROL/DAT_USERINTERFACE/MSG_DISABLEDS\n");
476 if (activeDS
.currentState
!= 5) {
477 activeDS
.twCC
= TWCC_SEQERROR
;
480 activeDS
.currentState
= 4;
481 activeDS
.twCC
= TWCC_SUCCESS
;
485 /* DG_CONTROL/DAT_USERINTERFACE/MSG_ENABLEDS */
486 static TW_UINT16
GPHOTO2_EnableDSUserInterface (pTW_IDENTITY pOrigin
,
489 pTW_USERINTERFACE pUserInterface
= (pTW_USERINTERFACE
) pData
;
491 load_filesystem("/");
493 TRACE ("DG_CONTROL/DAT_USERINTERFACE/MSG_ENABLEDS\n");
494 if (activeDS
.currentState
!= 4) {
495 FIXME("Sequence error %d\n", activeDS
.currentState
);
496 activeDS
.twCC
= TWCC_SEQERROR
;
499 activeDS
.hwndOwner
= pUserInterface
->hParent
;
500 if (pUserInterface
->ShowUI
)
503 activeDS
.currentState
= 5; /* Transitions to state 5 */
506 activeDS
.pendingEvent
.TWMessage
= MSG_CLOSEDSREQ
;
508 /* FIXME: The GUI should have marked the files to download... */
509 activeDS
.pendingEvent
.TWMessage
= MSG_XFERREADY
;
510 activeDS
.currentState
= 6; /* Transitions to state 6 directly */
513 /* no UI will be displayed, so source is ready to transfer data */
514 activeDS
.pendingEvent
.TWMessage
= MSG_XFERREADY
;
515 activeDS
.currentState
= 6; /* Transitions to state 6 directly */
517 activeDS
.hwndOwner
= pUserInterface
->hParent
;
518 activeDS
.twCC
= TWCC_SUCCESS
;
522 /* DG_CONTROL/DAT_USERINTERFACE/MSG_ENABLEDSUIONLY */
523 static TW_UINT16
GPHOTO2_EnableDSUIOnly (pTW_IDENTITY pOrigin
,
526 TRACE("DG_CONTROL/DAT_USERINTERFACE/MSG_ENABLEDSUIONLY\n");
528 if (activeDS
.currentState
!= 4) {
529 activeDS
.twCC
= TWCC_SEQERROR
;
532 /* FIXME: we should replace xscanimage with our own UI */
533 FIXME ("not implemented!\n");
534 activeDS
.currentState
= 5;
535 activeDS
.twCC
= TWCC_SUCCESS
;
539 /* DG_CONTROL/DAT_XFERGROUP/MSG_GET */
540 static TW_UINT16
GPHOTO2_XferGroupGet (pTW_IDENTITY pOrigin
,
547 /* DG_CONTROL/DAT_XFERGROUP/MSG_SET */
548 static TW_UINT16
GPHOTO2_XferGroupSet (pTW_IDENTITY pOrigin
,
555 HINSTANCE GPHOTO2_instance
;
557 BOOL WINAPI
DllMain (HINSTANCE hinstDLL
, DWORD fdwReason
, LPVOID lpvReserved
)
559 TRACE("%p,%x,%p\n", hinstDLL
, fdwReason
, lpvReserved
);
563 case DLL_PROCESS_ATTACH
:
564 GPHOTO2_instance
= hinstDLL
;
565 DisableThreadLibraryCalls(hinstDLL
);
567 activeDS
.context
= gp_context_new ();
571 case DLL_PROCESS_DETACH
:
572 GPHOTO2_instance
= NULL
;
580 static TW_UINT16
GPHOTO2_GetIdentity( pTW_IDENTITY
, pTW_IDENTITY
);
581 static TW_UINT16
GPHOTO2_OpenDS( pTW_IDENTITY
, pTW_IDENTITY
);
584 static TW_UINT16
GPHOTO2_SourceControlHandler (
585 pTW_IDENTITY pOrigin
,
590 TW_UINT16 twRC
= TWRC_SUCCESS
;
599 if (activeDS
.camera
) {
600 gp_camera_free (activeDS
.camera
);
601 activeDS
.camera
= NULL
;
607 twRC
= GPHOTO2_GetIdentity(pOrigin
,(pTW_IDENTITY
)pData
);
614 twRC
= GPHOTO2_OpenDS(pOrigin
,(pTW_IDENTITY
)pData
);
625 twRC
= GPHOTO2_CapabilityGet (pOrigin
, pData
);
628 twRC
= GPHOTO2_CapabilityGetCurrent (pOrigin
, pData
);
631 twRC
= GPHOTO2_CapabilityGetDefault (pOrigin
, pData
);
633 case MSG_QUERYSUPPORT
:
634 twRC
= GPHOTO2_CapabilityQuerySupport (pOrigin
, pData
);
637 twRC
= GPHOTO2_CapabilityReset (pOrigin
, pData
);
640 twRC
= GPHOTO2_CapabilitySet (pOrigin
, pData
);
644 FIXME("unrecognized opertion triplet\n");
648 case DAT_CUSTOMDSDATA
:
652 twRC
= GPHOTO2_CustomDSDataGet (pOrigin
, pData
);
655 twRC
= GPHOTO2_CustomDSDataSet (pOrigin
, pData
);
665 /*case MSG_AUTOMATICCAPTUREDIRECTORY:
666 twRC = GPHOTO2_AutomaticCaptureDirectory
669 case MSG_CHANGEDIRECTORY
:
670 twRC
= GPHOTO2_ChangeDirectory (pOrigin
, pData
);
673 twRC = GPHOTO2_FileSystemCopy (pOrigin, pData);
675 case MSG_CREATEDIRECTORY
:
676 twRC
= GPHOTO2_CreateDirectory (pOrigin
, pData
);
679 twRC
= GPHOTO2_FileSystemDelete (pOrigin
, pData
);
681 case MSG_FORMATMEDIA
:
682 twRC
= GPHOTO2_FormatMedia (pOrigin
, pData
);
685 twRC
= GPHOTO2_FileSystemGetClose (pOrigin
, pData
);
687 case MSG_GETFIRSTFILE
:
688 twRC
= GPHOTO2_FileSystemGetFirstFile (pOrigin
, pData
);
691 twRC
= GPHOTO2_FileSystemGetInfo (pOrigin
, pData
);
693 case MSG_GETNEXTFILE
:
694 twRC
= GPHOTO2_FileSystemGetNextFile (pOrigin
, pData
);
697 twRC
= GPHOTO2_FileSystemRename (pOrigin
, pData
);
706 if (MSG
== MSG_PROCESSEVENT
)
707 twRC
= GPHOTO2_ProcessEvent (pOrigin
, pData
);
713 if (MSG
== MSG_PASSTHRU
)
714 twRC
= GPHOTO2_PassThrough (pOrigin
, pData
);
719 case DAT_PENDINGXFERS
:
723 twRC
= GPHOTO2_PendingXfersEndXfer (pOrigin
, pData
);
726 twRC
= GPHOTO2_PendingXfersGet (pOrigin
, pData
);
729 twRC
= GPHOTO2_PendingXfersReset (pOrigin
, pData
);
731 /*case MSG_STOPFEEDER:
732 twRC = GPHOTO2_PendingXfersStopFeeder (pOrigin, pData);
739 case DAT_SETUPFILEXFER
:
743 twRC
= GPHOTO2_SetupFileXferGet (pOrigin
, pData
);
746 twRC
= GPHOTO2_SetupFileXferGetDefault (pOrigin
, pData
);
749 twRC
= GPHOTO2_SetupFileXferReset (pOrigin
, pData
);
752 twRC
= GPHOTO2_SetupFileXferSet (pOrigin
, pData
);
760 /*case DAT_SETUPFILEXFER2:
764 twRC = GPHOTO2_SetupFileXfer2Get (pOrigin, pData);
767 twRC = GPHOTO2_SetupFileXfer2GetDefault (pOrigin, pData);
770 twRC = GPHOTO2_SetupFileXfer2Reset (pOrigin, pData);
773 twRC = GPHOTO2_SetupFileXfer2Set (pOrigin, pData);
777 case DAT_SETUPMEMXFER
:
779 twRC
= GPHOTO2_SetupMemXferGet (pOrigin
, pData
);
786 twRC
= GPHOTO2_GetDSStatus (pOrigin
, pData
);
791 case DAT_USERINTERFACE
:
795 twRC
= GPHOTO2_DisableDSUserInterface (pOrigin
, pData
);
798 twRC
= GPHOTO2_EnableDSUserInterface (pOrigin
, pData
);
800 case MSG_ENABLEDSUIONLY
:
801 twRC
= GPHOTO2_EnableDSUIOnly (pOrigin
, pData
);
813 twRC
= GPHOTO2_XferGroupGet (pOrigin
, pData
);
816 twRC
= GPHOTO2_XferGroupSet (pOrigin
, pData
);
825 FIXME("code unknown: %d\n", DAT
);
834 static TW_UINT16
GPHOTO2_ImageGroupHandler (
835 pTW_IDENTITY pOrigin
,
840 TW_UINT16 twRC
= TWRC_SUCCESS
;
846 twRC
= GPHOTO2_CIEColorGet (pOrigin
, pData
);
851 case DAT_EXTIMAGEINFO
:
853 twRC
= GPHOTO2_ExtImageInfoGet (pOrigin
, pData
);
858 case DAT_GRAYRESPONSE
:
862 twRC
= GPHOTO2_GrayResponseReset (pOrigin
, pData
);
865 twRC
= GPHOTO2_GrayResponseSet (pOrigin
, pData
);
869 activeDS
.twCC
= TWCC_BADPROTOCOL
;
870 FIXME("unrecognized operation triplet\n");
874 case DAT_IMAGEFILEXFER
:
876 twRC
= GPHOTO2_ImageFileXferGet (pOrigin
, pData
);
883 twRC
= GPHOTO2_ImageInfoGet (pOrigin
, pData
);
888 case DAT_IMAGELAYOUT
:
892 twRC
= GPHOTO2_ImageLayoutGet (pOrigin
, pData
);
895 twRC
= GPHOTO2_ImageLayoutGetDefault (pOrigin
, pData
);
898 twRC
= GPHOTO2_ImageLayoutReset (pOrigin
, pData
);
901 twRC
= GPHOTO2_ImageLayoutSet (pOrigin
, pData
);
905 activeDS
.twCC
= TWCC_BADPROTOCOL
;
906 ERR("unrecognized operation triplet\n");
911 case DAT_IMAGEMEMXFER
:
913 twRC
= GPHOTO2_ImageMemXferGet (pOrigin
, pData
);
918 case DAT_IMAGENATIVEXFER
:
920 twRC
= GPHOTO2_ImageNativeXferGet (pOrigin
, pData
);
925 case DAT_JPEGCOMPRESSION
:
929 twRC
= GPHOTO2_JPEGCompressionGet (pOrigin
, pData
);
932 twRC
= GPHOTO2_JPEGCompressionGetDefault (pOrigin
, pData
);
935 twRC
= GPHOTO2_JPEGCompressionReset (pOrigin
, pData
);
938 twRC
= GPHOTO2_JPEGCompressionSet (pOrigin
, pData
);
942 activeDS
.twCC
= TWCC_BADPROTOCOL
;
943 WARN("unrecognized operation triplet\n");
952 twRC
= GPHOTO2_Palette8Get (pOrigin
, pData
);
955 twRC
= GPHOTO2_Palette8GetDefault (pOrigin
, pData
);
958 twRC
= GPHOTO2_Palette8Reset (pOrigin
, pData
);
961 twRC
= GPHOTO2_Palette8Set (pOrigin
, pData
);
965 activeDS
.twCC
= TWCC_BADPROTOCOL
;
966 WARN("unrecognized operation triplet\n");
970 case DAT_RGBRESPONSE
:
974 twRC
= GPHOTO2_RGBResponseReset (pOrigin
, pData
);
977 twRC
= GPHOTO2_RGBResponseSet (pOrigin
, pData
);
981 activeDS
.twCC
= TWCC_BADPROTOCOL
;
982 WARN("unrecognized operation triplet\n");
989 activeDS
.twCC
= TWCC_BADPROTOCOL
;
990 FIXME("unrecognized DG type %d\n", DAT
);
995 /* Main entry point for the TWAIN library */
997 DS_Entry ( pTW_IDENTITY pOrigin
,
1003 TW_UINT16 twRC
= TWRC_SUCCESS
; /* Return Code */
1005 TRACE("(DG=%d DAT=%d MSG=%d)\n", DG
, DAT
, MSG
);
1010 twRC
= GPHOTO2_SourceControlHandler (pOrigin
,DAT
,MSG
,pData
);
1013 twRC
= GPHOTO2_ImageGroupHandler (pOrigin
,DAT
,MSG
,pData
);
1016 FIXME("The audio group of entry codes is not implemented.\n");
1018 activeDS
.twCC
= TWCC_BADPROTOCOL
;
1019 twRC
= TWRC_FAILURE
;
1026 static GPPortInfoList
*port_list
;
1027 static int curcamera
;
1028 static CameraList
*detected_cameras
;
1029 static CameraAbilitiesList
*abilities_list
;
1032 gphoto2_auto_detect(void) {
1035 if (detected_cameras
&& (gp_list_count (detected_cameras
) == 0)) {
1036 /* Reload if previously no cameras, we might detect new ones. */
1037 TRACE("Reloading portlist trying to detect cameras.\n");
1039 gp_port_info_list_free (port_list
);
1044 TRACE("Auto detecting gphoto cameras.\n");
1045 TRACE("Loading ports...\n");
1046 if (gp_port_info_list_new (&port_list
) < GP_OK
)
1047 return TWRC_FAILURE
;
1048 result
= gp_port_info_list_load (port_list
);
1050 gp_port_info_list_free (port_list
);
1051 return TWRC_FAILURE
;
1053 count
= gp_port_info_list_count (port_list
);
1055 return TWRC_FAILURE
;
1056 if (gp_list_new (&detected_cameras
) < GP_OK
)
1057 return TWRC_FAILURE
;
1058 if (!abilities_list
) { /* Load only once per program start */
1059 gp_abilities_list_new (&abilities_list
);
1060 TRACE("Loading cameras...\n");
1061 gp_abilities_list_load (abilities_list
, NULL
);
1063 TRACE("Detecting cameras...\n");
1064 gp_abilities_list_detect (abilities_list
, port_list
, detected_cameras
, NULL
);
1066 TRACE("%d cameras detected\n", gp_list_count(detected_cameras
));
1068 return TWRC_SUCCESS
;
1072 GPHOTO2_GetIdentity( pTW_IDENTITY pOrigin
, pTW_IDENTITY self
) {
1074 const char *cname
, *pname
;
1076 if (TWRC_SUCCESS
!= gphoto2_auto_detect())
1077 return TWRC_FAILURE
;
1079 count
= gp_list_count (detected_cameras
);
1080 if (count
< GP_OK
) {
1081 gp_list_free (detected_cameras
);
1082 return TWRC_FAILURE
;
1084 TRACE("%d cameras detected.\n", count
);
1085 self
->ProtocolMajor
= TWON_PROTOCOLMAJOR
;
1086 self
->ProtocolMinor
= TWON_PROTOCOLMINOR
;
1087 lstrcpynA (self
->Manufacturer
, "The Wine Team", sizeof(self
->Manufacturer
) - 1);
1088 lstrcpynA (self
->ProductFamily
, "GPhoto2 Camera", sizeof(self
->ProductFamily
) - 1);
1090 if (!count
) { /* No camera detected. But we need to return an IDENTITY anyway. */
1091 lstrcpynA (self
->ProductName
, "GPhoto2 Camera", sizeof(self
->ProductName
) - 1);
1092 return TWRC_SUCCESS
;
1094 gp_list_get_name (detected_cameras
, curcamera
, &cname
);
1095 gp_list_get_value (detected_cameras
, curcamera
, &pname
);
1096 if (count
== 1) /* Normal case, only one camera. */
1097 snprintf (self
->ProductName
, sizeof(self
->ProductName
), "%s", cname
);
1099 snprintf (self
->ProductName
, sizeof(self
->ProductName
), "%s@%s", cname
, pname
);
1100 curcamera
= (curcamera
+1) % count
;
1101 return TWRC_SUCCESS
;
1105 GPHOTO2_OpenDS( pTW_IDENTITY pOrigin
, pTW_IDENTITY self
) {
1106 int ret
, m
, p
, count
, i
;
1109 const char *model
, *port
;
1111 if (TWRC_SUCCESS
!= gphoto2_auto_detect())
1112 return TWRC_FAILURE
;
1114 if (lstrcmpA(self
->ProductFamily
,"GPhoto2 Camera")) {
1115 FIXME("identity passed is not a gphoto camera, but %s!?!\n", self
->ProductFamily
);
1116 return TWRC_FAILURE
;
1118 count
= gp_list_count (detected_cameras
);
1120 ERR("No camera found by autodetection. Returning failure.\n");
1121 return TWRC_FAILURE
;
1124 if (!lstrcmpA (self
->ProductName
, "GPhoto2 Camera")) {
1125 TRACE("Potential undetected camera. Just using the first autodetected one.\n");
1128 for (i
=0;i
<count
;i
++) {
1129 const char *cname
, *pname
;
1132 gp_list_get_name (detected_cameras
, i
, &cname
);
1133 gp_list_get_value (detected_cameras
, i
, &pname
);
1134 if (!lstrcmpA(self
->ProductName
,cname
))
1136 snprintf(name
, sizeof(name
), "%s", cname
);
1137 if (!lstrcmpA(self
->ProductName
,name
))
1139 snprintf(name
, sizeof(name
), "%s@%s", cname
, pname
);
1140 if (!lstrcmpA(self
->ProductName
,name
))
1144 TRACE("Camera %s not found in autodetected list. Using first entry.\n", self
->ProductName
);
1148 gp_list_get_name (detected_cameras
, i
, &model
);
1149 gp_list_get_value (detected_cameras
, i
, &port
);
1150 TRACE("model %s, port %s\n", model
, port
);
1151 ret
= gp_camera_new (&activeDS
.camera
);
1153 ERR("gp_camera_new: %d\n", ret
);
1154 return TWRC_FAILURE
;
1156 m
= gp_abilities_list_lookup_model (abilities_list
, model
);
1158 FIXME("Model %s not found, %d!\n", model
, m
);
1159 return TWRC_FAILURE
;
1161 ret
= gp_abilities_list_get_abilities (abilities_list
, m
, &a
);
1163 FIXME("gp_camera_list_get_abilities failed? %d\n", ret
);
1164 return TWRC_FAILURE
;
1166 ret
= gp_camera_set_abilities (activeDS
.camera
, a
);
1168 FIXME("gp_camera_set_abilities failed? %d\n", ret
);
1169 return TWRC_FAILURE
;
1172 p
= gp_port_info_list_lookup_path (port_list
, port
);
1174 FIXME("port %s not in portlist?\n", port
);
1175 return TWRC_FAILURE
;
1177 ret
= gp_port_info_list_get_info (port_list
, p
, &info
);
1179 FIXME("could not get portinfo for port %s?\n", port
);
1180 return TWRC_FAILURE
;
1182 ret
= gp_camera_set_port_info (activeDS
.camera
, info
);
1184 FIXME("could not set portinfo for port %s to camera?\n", port
);
1185 return TWRC_FAILURE
;
1187 list_init( &(activeDS
.files
) );
1188 activeDS
.currentState
= 4;
1189 activeDS
.twCC
= TWRC_SUCCESS
;
1190 activeDS
.pixelflavor
= TWPF_CHOCOLATE
;
1191 activeDS
.pixeltype
= TWPT_RGB
;
1192 activeDS
.capXferMech
= TWSX_MEMORY
;
1194 return TWRC_SUCCESS
;