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