mshtml: Implement IHTMLStyle_get_backgroundColor.
[wine] / dlls / gphoto2.ds / gphoto2_main.c
1 /*
2  * SANE.DS functions
3  *
4  * Copyright 2000 Shi Quan He <shiquan@cyberdude.com>
5  * Copyright 2006 Marcus Meissner
6  *
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.
11  *
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.
16  *
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
20  */
21
22 #include "config.h"
23
24 #include <stdarg.h>
25 #include <stdio.h>
26 #ifdef HAVE_UNISTD_H
27 # include <unistd.h>
28 #endif
29 #include <stdlib.h>
30
31 #include "windef.h"
32 #include "winbase.h"
33 #include "twain.h"
34 #include "gphoto2_i.h"
35 #include "wine/debug.h"
36
37 WINE_DEFAULT_DEBUG_CHANNEL(twain);
38
39
40 static void
41 load_filesystem(const char *folder) {
42 #ifdef HAVE_GPHOTO2
43     int         i, count, ret;
44     CameraList  *list;
45
46     ret = gp_list_new (&list);
47     if (ret < GP_OK)
48         return;
49     ret = gp_camera_folder_list_files (activeDS.camera, folder, list, activeDS.context);
50     if (ret < GP_OK) {
51         gp_list_free (list);
52         return;
53     }
54     count = gp_list_count (list);
55     if (count < GP_OK) {
56         gp_list_free (list);
57         return;
58     }
59     for (i = 0; i < count; i++) {
60         const char *name;
61         struct gphoto2_file *gpfile;
62
63         ret = gp_list_get_name (list, i, &name);
64         if (ret < GP_OK)
65             continue;
66         gpfile = malloc(sizeof(struct gphoto2_file));
67         if (!gpfile)
68             continue;
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 );
74     }
75     gp_list_reset (list);
76
77     ret = gp_camera_folder_list_folders (activeDS.camera, folder, list, activeDS.context);
78     if (ret < GP_OK) {
79         FIXME("list_folders failed\n");
80         gp_list_free (list);
81         return;
82     }
83     count = gp_list_count (list);
84     if (count < GP_OK) {
85         FIXME("list_folders failed\n");
86         gp_list_free (list);
87         return;
88     }
89     for (i = 0; i < count; i++) {
90         const char *name;
91         char *newfolder;
92         ret = gp_list_get_name (list, i, &name);
93         if (ret < GP_OK)
94             continue;
95         TRACE("recursing into %s\n", name);
96         newfolder = malloc(strlen(folder)+1+strlen(name)+1);
97         if (!strcmp(folder,"/"))
98             sprintf (newfolder, "/%s", name);
99         else
100             sprintf (newfolder, "%s/%s", folder, name);
101         load_filesystem (newfolder); /* recurse ... happily */
102     }
103     gp_list_free (list);
104 #endif
105 }
106
107 /* DG_CONTROL/DAT_CAPABILITY/MSG_GET */
108 static TW_UINT16 GPHOTO2_CapabilityGet (pTW_IDENTITY pOrigin, TW_MEMREF pData)
109 {
110     pTW_CAPABILITY pCapability = (pTW_CAPABILITY) pData;
111
112     TRACE("DG_CONTROL/DAT_CAPABILITY/MSG_GET\n");
113     if (activeDS.currentState < 4 || activeDS.currentState > 7) {
114         activeDS.twCC = TWCC_SEQERROR;
115         return TWRC_FAILURE;
116     }
117     activeDS.twCC = GPHOTO2_SaneCapability (pCapability, MSG_GET);
118     return (activeDS.twCC == TWCC_SUCCESS)?TWRC_SUCCESS:TWRC_FAILURE;
119 }
120
121 /* DG_CONTROL/DAT_CAPABILITY/MSG_GETCURRENT */
122 static TW_UINT16 GPHOTO2_CapabilityGetCurrent (pTW_IDENTITY pOrigin, TW_MEMREF pData)
123 {
124     pTW_CAPABILITY pCapability = (pTW_CAPABILITY) pData;
125
126     TRACE("DG_CONTROL/DAT_CAPABILITY/MSG_GETCURRENT\n");
127
128     if (activeDS.currentState < 4 || activeDS.currentState > 7) {
129         activeDS.twCC = TWCC_SEQERROR;
130         return TWRC_FAILURE;
131     }
132     activeDS.twCC = GPHOTO2_SaneCapability (pCapability, MSG_GETCURRENT);
133     return (activeDS.twCC == TWCC_SUCCESS)?TWRC_SUCCESS:TWRC_FAILURE;
134 }
135
136 /* DG_CONTROL/DAT_CAPABILITY/MSG_GETDEFAULT */
137 static TW_UINT16 GPHOTO2_CapabilityGetDefault (pTW_IDENTITY pOrigin, TW_MEMREF pData)
138 {
139     pTW_CAPABILITY pCapability = (pTW_CAPABILITY) pData;
140
141     TRACE("DG_CONTROL/DAT_CAPABILITY/MSG_GETDEFAULT\n");
142     if (activeDS.currentState < 4 || activeDS.currentState > 7) {
143         activeDS.twCC = TWCC_SEQERROR;
144         return TWRC_FAILURE;
145     }
146     activeDS.twCC = GPHOTO2_SaneCapability (pCapability, MSG_GETDEFAULT);
147     return (activeDS.twCC == TWCC_SUCCESS)?TWRC_SUCCESS:TWRC_FAILURE;
148 }
149
150 /* DG_CONTROL/DAT_CAPABILITY/MSG_QUERYSUPPORT */
151 static TW_UINT16 GPHOTO2_CapabilityQuerySupport (pTW_IDENTITY pOrigin,
152                                         TW_MEMREF pData)
153 {
154     FIXME ("stub!\n");
155
156     return TWRC_FAILURE;
157 }
158
159 /* DG_CONTROL/DAT_CAPABILITY/MSG_RESET */
160 static TW_UINT16 GPHOTO2_CapabilityReset (pTW_IDENTITY pOrigin,
161                                  TW_MEMREF pData)
162 {
163     pTW_CAPABILITY pCapability = (pTW_CAPABILITY) pData;
164
165     TRACE("DG_CONTROL/DAT_CAPABILITY/MSG_RESET\n");
166
167     if (activeDS.currentState < 4 || activeDS.currentState > 7) {
168         activeDS.twCC = TWCC_SEQERROR;
169         return TWRC_FAILURE;
170     }
171     activeDS.twCC = GPHOTO2_SaneCapability (pCapability, MSG_RESET);
172     return (activeDS.twCC == TWCC_SUCCESS)?TWRC_SUCCESS:TWRC_FAILURE;
173 }
174
175 /* DG_CONTROL/DAT_CAPABILITY/MSG_SET */
176 static TW_UINT16 GPHOTO2_CapabilitySet (pTW_IDENTITY pOrigin,
177                                TW_MEMREF pData)
178 {
179     pTW_CAPABILITY pCapability = (pTW_CAPABILITY) pData;
180
181     TRACE ("DG_CONTROL/DAT_CAPABILITY/MSG_SET\n");
182
183     if (activeDS.currentState != 4) {
184         activeDS.twCC = TWCC_SEQERROR;
185         return TWRC_FAILURE;
186     }
187     activeDS.twCC = GPHOTO2_SaneCapability (pCapability, MSG_SET);
188     return (activeDS.twCC == TWCC_SUCCESS)?TWRC_SUCCESS:TWRC_FAILURE;
189 }
190
191 /* DG_CONTROL/DAT_CUSTOMDSDATA/MSG_GET */
192 static TW_UINT16 GPHOTO2_CustomDSDataGet (pTW_IDENTITY pOrigin,
193                                 TW_MEMREF pData)
194 {
195     FIXME ("stub!\n");
196
197     return TWRC_FAILURE;
198 }
199
200 /* DG_CONTROL/DAT_CUSTOMDSDATA/MSG_SET */
201 static TW_UINT16 GPHOTO2_CustomDSDataSet (pTW_IDENTITY pOrigin,
202                                  TW_MEMREF pData)
203 {
204     FIXME ("stub!\n");
205
206     return TWRC_FAILURE;
207 }
208
209 /* DG_CONTROL/DAT_FILESYSTEM/MSG_CHANGEDIRECTORY */
210 static TW_UINT16 GPHOTO2_ChangeDirectory (pTW_IDENTITY pOrigin,
211                                  TW_MEMREF pData)
212 {
213     FIXME ("stub!\n");
214
215     return TWRC_FAILURE;
216 }
217
218 /* DG_CONTROL/DAT_FILESYSTEM/MSG_CREATEDIRECTORY */
219 static TW_UINT16 GPHOTO2_CreateDirectory (pTW_IDENTITY pOrigin,
220                                  TW_MEMREF pData)
221 {
222     FIXME ("stub!\n");
223
224     return TWRC_FAILURE;
225 }
226
227 /* DG_CONTROL/DAT_FILESYSTEM/MSG_DELETE */
228 static TW_UINT16 GPHOTO2_FileSystemDelete (pTW_IDENTITY pOrigin,
229                                   TW_MEMREF pData)
230 {
231     FIXME ("stub!\n");
232
233     return TWRC_FAILURE;
234 }
235
236 /* DG_CONTROL/DAT_FILESYSTEM/MSG_FORMATMEDIA */
237 static TW_UINT16 GPHOTO2_FormatMedia (pTW_IDENTITY pOrigin,
238                              TW_MEMREF pData)
239 {
240     FIXME ("stub!\n");
241
242     return TWRC_FAILURE;
243 }
244
245 /* DG_CONTROL/DAT_FILESYSTEM/MSG_GETCLOSE */
246 static TW_UINT16 GPHOTO2_FileSystemGetClose (pTW_IDENTITY pOrigin,
247                                     TW_MEMREF pData)
248 {
249     FIXME ("stub!\n");
250
251     return TWRC_FAILURE;
252 }
253
254 /* DG_CONTROL/DAT_FILESYSTEM/MSG_GETFIRSTFILE */
255 static TW_UINT16 GPHOTO2_FileSystemGetFirstFile (pTW_IDENTITY pOrigin,
256
257                                         TW_MEMREF pData)
258 {
259     FIXME ("stub!\n");
260
261     return TWRC_FAILURE;
262 }
263
264 /* DG_CONTROL/DAT_FILESYSTEM/MSG_GETINFO */
265 static TW_UINT16 GPHOTO2_FileSystemGetInfo (pTW_IDENTITY pOrigin,
266                                    TW_MEMREF pData)
267 {
268     FIXME ("stub!\n");
269
270     return TWRC_FAILURE;
271 }
272
273 /* DG_CONTROL/DAT_FILESYSTEM/MSG_GETNEXTFILE */
274 static TW_UINT16 GPHOTO2_FileSystemGetNextFile (pTW_IDENTITY pOrigin,
275
276                                        TW_MEMREF pData)
277 {
278     FIXME ("stub!\n");
279
280     return TWRC_FAILURE;
281 }
282
283 /* DG_CONTROL/DAT_FILESYSTEM/MSG_RENAME */
284 static TW_UINT16 GPHOTO2_FileSystemRename (pTW_IDENTITY pOrigin,
285                                   TW_MEMREF pData)
286 {
287     FIXME ("stub!\n");
288
289     return TWRC_FAILURE;
290 }
291
292 /* DG_CONTROL/DAT_EVENT/MSG_PROCESSEVENT */
293 static TW_UINT16 GPHOTO2_ProcessEvent (pTW_IDENTITY pOrigin,
294                               TW_MEMREF pData)
295 {
296     TW_UINT16 twRC = TWRC_SUCCESS;
297     pTW_EVENT pEvent = (pTW_EVENT) pData;
298
299     TRACE("DG_CONTROL/DAT_EVENT/MSG_PROCESSEVENT\n");
300
301     if (activeDS.currentState < 5 || activeDS.currentState > 7) {
302         activeDS.twCC = TWCC_SEQERROR;
303         return TWRC_FAILURE;
304     }
305
306     if (activeDS.pendingEvent.TWMessage != MSG_NULL) {
307         pEvent->TWMessage = activeDS.pendingEvent.TWMessage;
308         activeDS.pendingEvent.TWMessage = MSG_NULL;
309         twRC = TWRC_SUCCESS;
310     } else {
311         pEvent->TWMessage = MSG_NULL;  /* no message to the application */
312         twRC = TWRC_NOTDSEVENT;
313     }
314     activeDS.twCC = TWCC_SUCCESS;
315     return twRC;
316 }
317
318 /* DG_CONTROL/DAT_PASSTHRU/MSG_PASSTHRU */
319 static TW_UINT16 GPHOTO2_PassThrough (pTW_IDENTITY pOrigin,
320                              TW_MEMREF pData)
321 {
322     FIXME ("stub!\n");
323
324     return TWRC_FAILURE;
325 }
326
327 /* DG_CONTROL/DAT_PENDINGXFERS/MSG_ENDXFER */
328 static TW_UINT16 GPHOTO2_PendingXfersEndXfer (pTW_IDENTITY pOrigin,
329                                      TW_MEMREF pData)
330 {
331     TW_UINT32 count;
332     pTW_PENDINGXFERS pPendingXfers = (pTW_PENDINGXFERS) pData;
333     struct gphoto2_file *file;
334
335     TRACE("DG_CONTROL/DAT_PENDINGXFERS/MSG_ENDXFER\n");
336
337     if (activeDS.currentState != 6 && activeDS.currentState != 7) {
338         activeDS.twCC = TWCC_SEQERROR;
339         return TWRC_FAILURE;
340     }
341     count = 0;
342     LIST_FOR_EACH_ENTRY( file, &activeDS.files, struct gphoto2_file, entry ) {
343         if (file->download)
344             count++;
345     }
346     TRACE("count = %d\n", count);
347     pPendingXfers->Count = count;
348     if (pPendingXfers->Count != 0) {
349         activeDS.currentState = 6;
350     } else {
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;
357     }
358     activeDS.twCC = TWCC_SUCCESS;
359     return TWRC_SUCCESS;
360 }
361
362 /* DG_CONTROL/DAT_PENDINGXFERS/MSG_GET */
363 static TW_UINT16 GPHOTO2_PendingXfersGet (pTW_IDENTITY pOrigin,
364                                  TW_MEMREF pData)
365 {
366     TW_UINT32 count;
367     pTW_PENDINGXFERS pPendingXfers = (pTW_PENDINGXFERS) pData;
368     struct gphoto2_file *file;
369
370     TRACE("DG_CONTROL/DAT_PENDINGXFERS/MSG_GET\n");
371
372     if (activeDS.currentState < 4 || activeDS.currentState > 7) {
373         activeDS.twCC = TWCC_SEQERROR;
374         return TWRC_FAILURE;
375     }
376
377     count = 0;
378     LIST_FOR_EACH_ENTRY( file, &activeDS.files, struct gphoto2_file, entry ) {
379         if (file->download)
380             count++;
381     }
382     TRACE("count = %d\n", count);
383     pPendingXfers->Count = count;
384     activeDS.twCC = TWCC_SUCCESS;
385     return TWRC_SUCCESS;
386 }
387
388 /* DG_CONTROL/DAT_PENDINGXFERS/MSG_RESET */
389 static TW_UINT16 GPHOTO2_PendingXfersReset (pTW_IDENTITY pOrigin,
390                                    TW_MEMREF pData)
391 {
392     pTW_PENDINGXFERS pPendingXfers = (pTW_PENDINGXFERS) pData;
393
394     TRACE("DG_CONTROL/DAT_PENDINGXFERS/MSG_RESET\n");
395
396     if (activeDS.currentState != 6) {
397         activeDS.twCC = TWCC_SEQERROR;
398         return TWRC_FAILURE;
399     }
400     pPendingXfers->Count = 0;
401     activeDS.currentState = 5;
402     activeDS.twCC = TWCC_SUCCESS;
403     return TWRC_SUCCESS;
404 }
405
406 /* DG_CONTROL/DAT_SETUPFILEXFER/MSG_GET */
407 static TW_UINT16 GPHOTO2_SetupFileXferGet (pTW_IDENTITY pOrigin,
408                                   TW_MEMREF pData)
409 {
410     FIXME ("stub!\n");
411
412     return TWRC_FAILURE;
413 }
414
415 /* DG_CONTROL/DAT_SETUPXFER/MSG_GETDEFAULT */
416 static TW_UINT16 GPHOTO2_SetupFileXferGetDefault (pTW_IDENTITY pOrigin,
417                                          TW_MEMREF pData)
418 {
419     FIXME ("stub!\n");
420
421     return TWRC_FAILURE;
422 }
423
424
425 /* DG_CONTROL/DAT_SETUPFILEXFER/MSG_RESET */
426 static TW_UINT16 GPHOTO2_SetupFileXferReset (pTW_IDENTITY pOrigin,
427                                     TW_MEMREF pData)
428 {
429     FIXME ("stub!\n");
430
431     return TWRC_FAILURE;
432 }
433
434 /* DG_CONTROL/DAT_SETUPFILEXFER/MSG_SET */
435 static TW_UINT16 GPHOTO2_SetupFileXferSet (pTW_IDENTITY pOrigin,
436                                   TW_MEMREF pData)
437 {
438     FIXME ("stub!\n");
439
440     return TWRC_FAILURE;
441 }
442
443 /* DG_CONTROL/DAT_SETUPMEMXFER/MSG_GET */
444 static TW_UINT16 GPHOTO2_SetupMemXferGet (pTW_IDENTITY pOrigin,
445                                   TW_MEMREF pData)
446 {
447     pTW_SETUPMEMXFER  pSetupMemXfer = (pTW_SETUPMEMXFER)pData;
448
449     TRACE("DG_CONTROL/DAT_SETUPMEMXFER/MSG_GET\n");
450     /* Guessing */
451     pSetupMemXfer->MinBufSize = 20000;
452     pSetupMemXfer->MaxBufSize = 80000;
453     pSetupMemXfer->Preferred = 40000;
454     return TWRC_SUCCESS;
455 }
456
457 /* DG_CONTROL/DAT_STATUS/MSG_GET */
458 static TW_UINT16 GPHOTO2_GetDSStatus (pTW_IDENTITY pOrigin,
459                              TW_MEMREF pData)
460 {
461     pTW_STATUS pSourceStatus = (pTW_STATUS) pData;
462
463     TRACE ("DG_CONTROL/DAT_STATUS/MSG_GET\n");
464     pSourceStatus->ConditionCode = activeDS.twCC;
465     /* Reset the condition code */
466     activeDS.twCC = TWCC_SUCCESS;
467     return TWRC_SUCCESS;
468 }
469
470 /* DG_CONTROL/DAT_USERINTERFACE/MSG_DISABLEDS */
471 static TW_UINT16 GPHOTO2_DisableDSUserInterface (pTW_IDENTITY pOrigin,
472                                         TW_MEMREF pData)
473 {
474     TRACE ("DG_CONTROL/DAT_USERINTERFACE/MSG_DISABLEDS\n");
475
476     if (activeDS.currentState != 5) {
477         activeDS.twCC = TWCC_SEQERROR;
478         return TWRC_FAILURE;
479     }
480     activeDS.currentState = 4;
481     activeDS.twCC = TWCC_SUCCESS;
482     return TWRC_SUCCESS;
483 }
484
485 /* DG_CONTROL/DAT_USERINTERFACE/MSG_ENABLEDS */
486 static TW_UINT16 GPHOTO2_EnableDSUserInterface (pTW_IDENTITY pOrigin,
487                                        TW_MEMREF pData)
488 {
489     pTW_USERINTERFACE pUserInterface = (pTW_USERINTERFACE) pData;
490
491     load_filesystem("/");
492
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;
497         return TWRC_FAILURE;
498     }
499     activeDS.hwndOwner = pUserInterface->hParent;
500     if (pUserInterface->ShowUI)
501     {
502         BOOL rc;
503         activeDS.currentState = 5; /* Transitions to state 5 */
504         rc = DoCameraUI();
505         if (!rc) {
506             activeDS.pendingEvent.TWMessage = MSG_CLOSEDSREQ;
507         } else {
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 */
511         }
512     } else {
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 */
516     }
517     activeDS.hwndOwner = pUserInterface->hParent;
518     activeDS.twCC = TWCC_SUCCESS;
519     return TWRC_SUCCESS;
520 }
521
522 /* DG_CONTROL/DAT_USERINTERFACE/MSG_ENABLEDSUIONLY */
523 static TW_UINT16 GPHOTO2_EnableDSUIOnly (pTW_IDENTITY pOrigin,
524                                 TW_MEMREF pData)
525 {
526     TRACE("DG_CONTROL/DAT_USERINTERFACE/MSG_ENABLEDSUIONLY\n");
527
528     if (activeDS.currentState != 4) {
529         activeDS.twCC = TWCC_SEQERROR;
530         return TWRC_FAILURE;
531     }
532     /* FIXME: we should replace xscanimage with our own UI */
533     FIXME ("not implemented!\n");
534     activeDS.currentState = 5;
535     activeDS.twCC = TWCC_SUCCESS;
536     return TWRC_SUCCESS;
537 }
538
539 /* DG_CONTROL/DAT_XFERGROUP/MSG_GET */
540 static TW_UINT16 GPHOTO2_XferGroupGet (pTW_IDENTITY pOrigin,
541                               TW_MEMREF pData)
542 {
543     FIXME ("stub!\n");
544     return TWRC_FAILURE;
545 }
546
547 /* DG_CONTROL/DAT_XFERGROUP/MSG_SET */
548 static TW_UINT16 GPHOTO2_XferGroupSet (pTW_IDENTITY pOrigin,
549                                   TW_MEMREF pData)
550 {
551     FIXME ("stub!\n");
552     return TWRC_FAILURE;
553 }
554
555 HINSTANCE GPHOTO2_instance;
556
557 BOOL WINAPI DllMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
558 {
559     TRACE("%p,%x,%p\n", hinstDLL, fdwReason, lpvReserved);
560
561     switch (fdwReason)
562     {
563         case DLL_PROCESS_ATTACH:
564             GPHOTO2_instance = hinstDLL;
565             DisableThreadLibraryCalls(hinstDLL);
566 #ifdef HAVE_GPHOTO2
567             activeDS.context = gp_context_new ();
568 #endif
569             break;
570
571         case DLL_PROCESS_DETACH:
572             GPHOTO2_instance = NULL;
573             break;
574     }
575
576     return TRUE;
577 }
578
579 #ifdef HAVE_GPHOTO2
580 static TW_UINT16 GPHOTO2_GetIdentity( pTW_IDENTITY, pTW_IDENTITY);
581 static TW_UINT16 GPHOTO2_OpenDS( pTW_IDENTITY, pTW_IDENTITY);
582 #endif
583
584 static TW_UINT16 GPHOTO2_SourceControlHandler (
585    pTW_IDENTITY pOrigin,
586    TW_UINT16    DAT,
587    TW_UINT16    MSG,
588    TW_MEMREF    pData)
589 {
590     TW_UINT16 twRC = TWRC_SUCCESS;
591
592     switch (DAT)
593     {
594         case DAT_IDENTITY:
595             switch (MSG)
596             {
597                 case MSG_CLOSEDS:
598 #ifdef HAVE_GPHOTO2
599                      if (activeDS.camera) {
600                         gp_camera_free (activeDS.camera);
601                         activeDS.camera = NULL;
602                      }
603 #endif
604                      break;
605                 case MSG_GET:
606 #ifdef HAVE_GPHOTO2
607                      twRC = GPHOTO2_GetIdentity(pOrigin,(pTW_IDENTITY)pData);
608 #else
609                      twRC = TWRC_FAILURE;
610 #endif
611                      break;
612                 case MSG_OPENDS:
613 #ifdef HAVE_GPHOTO2
614                      twRC = GPHOTO2_OpenDS(pOrigin,(pTW_IDENTITY)pData);
615 #else
616                      twRC = TWRC_FAILURE;
617 #endif
618                      break;
619             }
620             break;
621         case DAT_CAPABILITY:
622             switch (MSG)
623             {
624                 case MSG_GET:
625                     twRC = GPHOTO2_CapabilityGet (pOrigin, pData);
626                     break;
627                 case MSG_GETCURRENT:
628                     twRC = GPHOTO2_CapabilityGetCurrent (pOrigin, pData);
629                     break;
630                 case MSG_GETDEFAULT:
631                     twRC = GPHOTO2_CapabilityGetDefault (pOrigin, pData);
632                     break;
633                 case MSG_QUERYSUPPORT:
634                     twRC = GPHOTO2_CapabilityQuerySupport (pOrigin, pData);
635                     break;
636                 case MSG_RESET:
637                     twRC = GPHOTO2_CapabilityReset (pOrigin, pData);
638                     break;
639                 case MSG_SET:
640                     twRC = GPHOTO2_CapabilitySet (pOrigin, pData);
641                     break;
642                 default:
643                     twRC = TWRC_FAILURE;
644                     FIXME("unrecognized opertion triplet\n");
645             }
646             break;
647
648         case DAT_CUSTOMDSDATA:
649             switch (MSG)
650             {
651                 case MSG_GET:
652                     twRC = GPHOTO2_CustomDSDataGet (pOrigin, pData);
653                     break;
654                 case MSG_SET:
655                     twRC = GPHOTO2_CustomDSDataSet (pOrigin, pData);
656                     break;
657                 default:
658                     break;
659             }
660             break;
661
662         case DAT_FILESYSTEM:
663             switch (MSG)
664             {
665                 /*case MSG_AUTOMATICCAPTUREDIRECTORY:
666                     twRC = GPHOTO2_AutomaticCaptureDirectory
667                                (pOrigin, pData);
668                     break;*/
669                 case MSG_CHANGEDIRECTORY:
670                     twRC = GPHOTO2_ChangeDirectory (pOrigin, pData);
671                     break;
672                 /*case MSG_COPY:
673                     twRC = GPHOTO2_FileSystemCopy (pOrigin, pData);
674                     break;*/
675                 case MSG_CREATEDIRECTORY:
676                     twRC = GPHOTO2_CreateDirectory (pOrigin, pData);
677                     break;
678                 case MSG_DELETE:
679                     twRC = GPHOTO2_FileSystemDelete (pOrigin, pData);
680                     break;
681                 case MSG_FORMATMEDIA:
682                     twRC = GPHOTO2_FormatMedia (pOrigin, pData);
683                     break;
684                 case MSG_GETCLOSE:
685                     twRC = GPHOTO2_FileSystemGetClose (pOrigin, pData);
686                     break;
687                 case MSG_GETFIRSTFILE:
688                     twRC = GPHOTO2_FileSystemGetFirstFile (pOrigin, pData);
689                     break;
690                 case MSG_GETINFO:
691                     twRC = GPHOTO2_FileSystemGetInfo (pOrigin, pData);
692                     break;
693                 case MSG_GETNEXTFILE:
694                     twRC = GPHOTO2_FileSystemGetNextFile (pOrigin, pData);
695                     break;
696                 case MSG_RENAME:
697                     twRC = GPHOTO2_FileSystemRename (pOrigin, pData);
698                     break;
699                 default:
700                     twRC = TWRC_FAILURE;
701                     break;
702             }
703             break;
704
705         case DAT_EVENT:
706             if (MSG == MSG_PROCESSEVENT)
707                 twRC = GPHOTO2_ProcessEvent (pOrigin, pData);
708             else
709                 twRC = TWRC_FAILURE;
710             break;
711
712         case DAT_PASSTHRU:
713             if (MSG == MSG_PASSTHRU)
714                 twRC = GPHOTO2_PassThrough (pOrigin, pData);
715             else
716                 twRC = TWRC_FAILURE;
717             break;
718
719         case DAT_PENDINGXFERS:
720             switch (MSG)
721             {
722                 case MSG_ENDXFER:
723                     twRC = GPHOTO2_PendingXfersEndXfer (pOrigin, pData);
724                     break;
725                 case MSG_GET:
726                     twRC = GPHOTO2_PendingXfersGet (pOrigin, pData);
727                     break;
728                 case MSG_RESET:
729                     twRC = GPHOTO2_PendingXfersReset (pOrigin, pData);
730                     break;
731                 /*case MSG_STOPFEEDER:
732                     twRC = GPHOTO2_PendingXfersStopFeeder (pOrigin, pData);
733                     break;*/
734                 default:
735                     twRC = TWRC_FAILURE;
736             }
737             break;
738
739         case DAT_SETUPFILEXFER:
740             switch (MSG)
741             {
742                 case MSG_GET:
743                     twRC = GPHOTO2_SetupFileXferGet (pOrigin, pData);
744                     break;
745                 case MSG_GETDEFAULT:
746                     twRC = GPHOTO2_SetupFileXferGetDefault (pOrigin, pData);
747                     break;
748                 case MSG_RESET:
749                     twRC = GPHOTO2_SetupFileXferReset (pOrigin, pData);
750                     break;
751                 case MSG_SET:
752                     twRC = GPHOTO2_SetupFileXferSet (pOrigin, pData);
753                     break;
754                 default:
755                     twRC = TWRC_FAILURE;
756                     break;
757             }
758             break;
759
760         /*case DAT_SETUPFILEXFER2:
761             switch (MSG)
762             {
763                 case MSG_GET:
764                     twRC = GPHOTO2_SetupFileXfer2Get (pOrigin, pData);
765                     break;
766                 case MSG_GETDEFAULT:
767                     twRC = GPHOTO2_SetupFileXfer2GetDefault (pOrigin, pData);
768                     break;
769                 case MSG_RESET:
770                     twRC = GPHOTO2_SetupFileXfer2Reset (pOrigin, pData);
771                     break;
772                 case MSG_SET:
773                     twRC = GPHOTO2_SetupFileXfer2Set (pOrigin, pData);
774                     break;
775             }
776             break;*/
777         case DAT_SETUPMEMXFER:
778             if (MSG == MSG_GET)
779                 twRC = GPHOTO2_SetupMemXferGet (pOrigin, pData);
780             else
781                 twRC = TWRC_FAILURE;
782             break;
783
784         case DAT_STATUS:
785             if (MSG == MSG_GET)
786                 twRC = GPHOTO2_GetDSStatus (pOrigin, pData);
787             else
788                 twRC = TWRC_FAILURE;
789             break;
790
791         case DAT_USERINTERFACE:
792             switch (MSG)
793             {
794                 case MSG_DISABLEDS:
795                     twRC = GPHOTO2_DisableDSUserInterface (pOrigin, pData);
796                     break;
797                 case MSG_ENABLEDS:
798                     twRC = GPHOTO2_EnableDSUserInterface (pOrigin, pData);
799                     break;
800                 case MSG_ENABLEDSUIONLY:
801                     twRC = GPHOTO2_EnableDSUIOnly (pOrigin, pData);
802                     break;
803                 default:
804                     twRC = TWRC_FAILURE;
805                     break;
806             }
807             break;
808
809         case DAT_XFERGROUP:
810             switch (MSG)
811             {
812                 case MSG_GET:
813                     twRC = GPHOTO2_XferGroupGet (pOrigin, pData);
814                     break;
815                 case MSG_SET:
816                     twRC = GPHOTO2_XferGroupSet (pOrigin, pData);
817                     break;
818                 default:
819                     twRC = TWRC_FAILURE;
820                     break;
821             }
822             break;
823
824         default:
825             FIXME("code unknown: %d\n", DAT);
826             twRC = TWRC_FAILURE;
827             break;
828     }
829
830     return twRC;
831 }
832
833
834 static TW_UINT16 GPHOTO2_ImageGroupHandler (
835            pTW_IDENTITY pOrigin,
836            TW_UINT16    DAT,
837            TW_UINT16    MSG,
838            TW_MEMREF    pData)
839 {
840     TW_UINT16 twRC = TWRC_SUCCESS;
841
842     switch (DAT)
843     {
844         case DAT_CIECOLOR:
845             if (MSG == MSG_GET)
846                 twRC = GPHOTO2_CIEColorGet (pOrigin, pData);
847             else
848                 twRC = TWRC_FAILURE;
849             break;
850
851         case DAT_EXTIMAGEINFO:
852             if (MSG == MSG_GET)
853                 twRC = GPHOTO2_ExtImageInfoGet (pOrigin, pData);
854             else
855                 twRC = TWRC_FAILURE;
856             break;
857
858         case DAT_GRAYRESPONSE:
859             switch (MSG)
860             {
861                 case MSG_RESET:
862                     twRC = GPHOTO2_GrayResponseReset (pOrigin, pData);
863                     break;
864                 case MSG_SET:
865                     twRC = GPHOTO2_GrayResponseSet (pOrigin, pData);
866                     break;
867                 default:
868                     twRC = TWRC_FAILURE;
869                     activeDS.twCC = TWCC_BADPROTOCOL;
870                     FIXME("unrecognized operation triplet\n");
871                     break;
872             }
873             break;
874         case DAT_IMAGEFILEXFER:
875             if (MSG == MSG_GET)
876                 twRC = GPHOTO2_ImageFileXferGet (pOrigin, pData);
877             else
878                 twRC = TWRC_FAILURE;
879             break;
880
881         case DAT_IMAGEINFO:
882             if (MSG == MSG_GET)
883                 twRC = GPHOTO2_ImageInfoGet (pOrigin, pData);
884             else
885                 twRC = TWRC_FAILURE;
886             break;
887
888         case DAT_IMAGELAYOUT:
889             switch (MSG)
890             {
891                 case MSG_GET:
892                     twRC = GPHOTO2_ImageLayoutGet (pOrigin, pData);
893                     break;
894                 case MSG_GETDEFAULT:
895                     twRC = GPHOTO2_ImageLayoutGetDefault (pOrigin, pData);
896                     break;
897                 case MSG_RESET:
898                     twRC = GPHOTO2_ImageLayoutReset (pOrigin, pData);
899                     break;
900                 case MSG_SET:
901                     twRC = GPHOTO2_ImageLayoutSet (pOrigin, pData);
902                     break;
903                 default:
904                     twRC = TWRC_FAILURE;
905                     activeDS.twCC = TWCC_BADPROTOCOL;
906                     ERR("unrecognized operation triplet\n");
907                     break;
908             }
909             break;
910
911         case DAT_IMAGEMEMXFER:
912             if (MSG == MSG_GET)
913                 twRC = GPHOTO2_ImageMemXferGet (pOrigin, pData);
914             else
915                 twRC = TWRC_FAILURE;
916             break;
917
918         case DAT_IMAGENATIVEXFER:
919             if (MSG == MSG_GET)
920                 twRC = GPHOTO2_ImageNativeXferGet (pOrigin, pData);
921             else
922                 twRC = TWRC_FAILURE;
923             break;
924
925         case DAT_JPEGCOMPRESSION:
926             switch (MSG)
927             {
928                 case MSG_GET:
929                     twRC = GPHOTO2_JPEGCompressionGet (pOrigin, pData);
930                     break;
931                 case MSG_GETDEFAULT:
932                     twRC = GPHOTO2_JPEGCompressionGetDefault (pOrigin, pData);
933                     break;
934                 case MSG_RESET:
935                     twRC = GPHOTO2_JPEGCompressionReset (pOrigin, pData);
936                     break;
937                 case MSG_SET:
938                     twRC = GPHOTO2_JPEGCompressionSet (pOrigin, pData);
939                     break;
940                 default:
941                     twRC = TWRC_FAILURE;
942                     activeDS.twCC = TWCC_BADPROTOCOL;
943                     WARN("unrecognized operation triplet\n");
944                     break;
945             }
946             break;
947
948         case DAT_PALETTE8:
949             switch (MSG)
950             {
951                 case MSG_GET:
952                     twRC = GPHOTO2_Palette8Get (pOrigin, pData);
953                     break;
954                 case MSG_GETDEFAULT:
955                     twRC = GPHOTO2_Palette8GetDefault (pOrigin, pData);
956                     break;
957                 case MSG_RESET:
958                     twRC = GPHOTO2_Palette8Reset (pOrigin, pData);
959                     break;
960                 case MSG_SET:
961                     twRC = GPHOTO2_Palette8Set (pOrigin, pData);
962                     break;
963                 default:
964                     twRC = TWRC_FAILURE;
965                     activeDS.twCC = TWCC_BADPROTOCOL;
966                     WARN("unrecognized operation triplet\n");
967             }
968             break;
969
970         case DAT_RGBRESPONSE:
971             switch (MSG)
972             {
973                 case MSG_RESET:
974                     twRC = GPHOTO2_RGBResponseReset (pOrigin, pData);
975                     break;
976                 case MSG_SET:
977                     twRC = GPHOTO2_RGBResponseSet (pOrigin, pData);
978                     break;
979                 default:
980                     twRC = TWRC_FAILURE;
981                     activeDS.twCC = TWCC_BADPROTOCOL;
982                     WARN("unrecognized operation triplet\n");
983                     break;
984             }
985             break;
986
987         default:
988             twRC = TWRC_FAILURE;
989             activeDS.twCC = TWCC_BADPROTOCOL;
990             FIXME("unrecognized DG type %d\n", DAT);
991     }
992     return twRC;
993 }
994
995 /* Main entry point for the TWAIN library */
996 TW_UINT16 WINAPI
997 DS_Entry ( pTW_IDENTITY pOrigin,
998            TW_UINT32    DG,
999            TW_UINT16    DAT,
1000            TW_UINT16    MSG,
1001            TW_MEMREF    pData)
1002 {
1003     TW_UINT16 twRC = TWRC_SUCCESS;  /* Return Code */
1004
1005     TRACE("(DG=%d DAT=%d MSG=%d)\n", DG, DAT, MSG);
1006
1007     switch (DG)
1008     {
1009         case DG_CONTROL:
1010             twRC = GPHOTO2_SourceControlHandler (pOrigin,DAT,MSG,pData);
1011             break;
1012         case DG_IMAGE:
1013             twRC = GPHOTO2_ImageGroupHandler (pOrigin,DAT,MSG,pData);
1014             break;
1015         case DG_AUDIO:
1016             FIXME("The audio group of entry codes is not implemented.\n");
1017         default:
1018             activeDS.twCC = TWCC_BADPROTOCOL;
1019             twRC = TWRC_FAILURE;
1020     }
1021
1022     return twRC;
1023 }
1024
1025 #ifdef HAVE_GPHOTO2
1026 static GPPortInfoList *port_list;
1027 static int curcamera;
1028 static CameraList *detected_cameras;
1029 static CameraAbilitiesList *abilities_list;
1030
1031 static TW_UINT16
1032 gphoto2_auto_detect(void) {
1033     int result, count;
1034
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");
1038         if (port_list) {
1039             gp_port_info_list_free (port_list);
1040             port_list = NULL;
1041         }
1042     }
1043     if (!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);
1049         if (result < 0) {
1050             gp_port_info_list_free (port_list);
1051             return TWRC_FAILURE;
1052         }
1053         count = gp_port_info_list_count (port_list);
1054         if (count <= 0)
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);
1062         }
1063         TRACE("Detecting cameras...\n");
1064         gp_abilities_list_detect (abilities_list, port_list, detected_cameras, NULL);
1065         curcamera = 0;
1066         TRACE("%d cameras detected\n", gp_list_count(detected_cameras));
1067     }
1068     return TWRC_SUCCESS;
1069 }
1070
1071 static TW_UINT16
1072 GPHOTO2_GetIdentity( pTW_IDENTITY pOrigin, pTW_IDENTITY self) {
1073     int count;
1074     const char *cname, *pname;
1075
1076     if (TWRC_SUCCESS != gphoto2_auto_detect())
1077         return TWRC_FAILURE;
1078
1079     count = gp_list_count (detected_cameras);
1080     if (count < GP_OK) {
1081         gp_list_free (detected_cameras);
1082         return TWRC_FAILURE;
1083     }
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);
1089
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;
1093     }
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);
1098     else
1099         snprintf (self->ProductName, sizeof(self->ProductName), "%s@%s", cname, pname);
1100     curcamera = (curcamera+1) % count;
1101     return TWRC_SUCCESS;
1102 }
1103
1104 static TW_UINT16
1105 GPHOTO2_OpenDS( pTW_IDENTITY pOrigin, pTW_IDENTITY self) {
1106     int ret, m, p, count, i;
1107     CameraAbilities a;
1108     GPPortInfo info;
1109     const char  *model, *port;
1110
1111     if (TWRC_SUCCESS != gphoto2_auto_detect())
1112         return TWRC_FAILURE;
1113
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;
1117     }
1118     count = gp_list_count (detected_cameras);
1119     if (!count) {
1120         ERR("No camera found by autodetection. Returning failure.\n");
1121         return TWRC_FAILURE;
1122     }
1123
1124     if (!lstrcmpA (self->ProductName, "GPhoto2 Camera")) {
1125         TRACE("Potential undetected camera. Just using the first autodetected one.\n");
1126         i = 0;
1127     } else {
1128         for (i=0;i<count;i++) {
1129             const char *cname, *pname;
1130             TW_STR32    name;
1131
1132             gp_list_get_name  (detected_cameras, i, &cname);
1133             gp_list_get_value (detected_cameras, i, &pname);
1134             if (!lstrcmpA(self->ProductName,cname))
1135                 break;
1136             snprintf(name, sizeof(name), "%s", cname);
1137             if (!lstrcmpA(self->ProductName,name))
1138                 break;
1139             snprintf(name, sizeof(name), "%s@%s", cname, pname);
1140             if (!lstrcmpA(self->ProductName,name))
1141                 break;
1142         }
1143         if (i == count) {
1144             TRACE("Camera %s not found in autodetected list. Using first entry.\n", self->ProductName);
1145             i=0;
1146         }
1147     }
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);
1152     if (ret < GP_OK) {
1153         ERR("gp_camera_new: %d\n", ret);
1154         return TWRC_FAILURE;
1155     }
1156     m = gp_abilities_list_lookup_model (abilities_list, model);
1157     if (m < GP_OK) {
1158         FIXME("Model %s not found, %d!\n", model, m);
1159         return TWRC_FAILURE;
1160     }
1161     ret = gp_abilities_list_get_abilities (abilities_list, m, &a);
1162     if (ret < GP_OK) {
1163         FIXME("gp_camera_list_get_abilities failed? %d\n", ret);
1164         return TWRC_FAILURE;
1165     }
1166     ret = gp_camera_set_abilities (activeDS.camera, a);
1167     if (ret < GP_OK) {
1168         FIXME("gp_camera_set_abilities failed? %d\n", ret);
1169         return TWRC_FAILURE;
1170     }
1171
1172     p = gp_port_info_list_lookup_path (port_list, port);
1173     if (p < GP_OK) {
1174         FIXME("port %s not in portlist?\n", port);
1175         return TWRC_FAILURE;
1176     }
1177     ret = gp_port_info_list_get_info (port_list, p, &info);
1178     if (ret < GP_OK) {
1179         FIXME("could not get portinfo for port %s?\n", port);
1180         return TWRC_FAILURE;
1181     }
1182     ret = gp_camera_set_port_info (activeDS.camera, info);
1183     if (ret < GP_OK) {
1184         FIXME("could not set portinfo for port %s to camera?\n", port);
1185         return TWRC_FAILURE;
1186     }
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;
1193     TRACE("OK!\n");
1194     return TWRC_SUCCESS;
1195 }
1196 #endif