Source code upload
[framework/connectivity/libgphoto2.git] / camlibs / kodak / dc210 / dc210.c
1 #include "config.h"
2
3 #include <stdlib.h>
4 #include <stdio.h>
5 #include <string.h>
6 #include <time.h>
7
8 #include <gphoto2/gphoto2.h>
9 #include <gphoto2/gphoto2-port.h>
10
11 #ifdef ENABLE_NLS
12 #  include <libintl.h>
13 #  undef _
14 #  ifdef gettext_noop
15 #    define _(String) dgettext (PACKAGE, String)
16 #    define N_(String) gettext_noop (String)
17 #  else
18 #    define _(String) (String)
19 #    define N_(String) (String)
20 #  endif
21 #else
22 #  define _(String) (String)
23 #  define N_(String) (String)
24 #endif
25
26 #include "dc210.h"
27
28 static char * exp_comp[] = {"-2.0 EV", "-1.5 EV", "-1.0 EV", "-0.5 EV", "AUTO", "+0.5 EV",
29                      "+1.0 EV", "+1.5 EV", "+2.0 EV"};
30
31 int camera_id (CameraText *id) {
32
33         strcpy(id->text, GP_MODULE);
34
35         return (GP_OK);
36 }
37
38 int camera_abilities (CameraAbilitiesList *list) {
39
40         CameraAbilities a;
41
42         memset (&a, 0, sizeof(a));
43         strcpy(a.model, "Kodak:DC210");
44         a.status = GP_DRIVER_STATUS_PRODUCTION;
45         a.port     = GP_PORT_SERIAL;
46         a.speed[0] = 9600;
47         a.speed[1] = 19200;
48         a.speed[2] = 38400;
49         a.speed[3] = 57600;
50         a.speed[4] = 115200;
51         a.speed[5] = 0;
52         a.operations        =   GP_OPERATION_CAPTURE_IMAGE | GP_OPERATION_CONFIG;
53         a.file_operations   =   GP_FILE_OPERATION_DELETE |  GP_FILE_OPERATION_PREVIEW;
54         a.folder_operations =   GP_FOLDER_OPERATION_NONE;
55
56         gp_abilities_list_append(list, a);
57
58         /* Mark Longridge <mark@cubeman.org> */
59         strcpy(a.model, "Kodak:DC215");
60         gp_abilities_list_append(list, a);
61
62         return (GP_OK);
63 }
64
65 static int file_list_func (CameraFilesystem *fs, const char *folder,
66                            CameraList *list, void *data, GPContext *context) 
67 {
68     Camera *camera = data;
69     
70     return dc210_get_filenames(camera, list, context);
71     
72 }
73
74 static int get_file_func (CameraFilesystem *fs, const char *folder,
75                           const char *filename, CameraFileType type,
76                           CameraFile *file, void *data, GPContext *context) 
77 {
78         Camera *camera = data;
79
80         switch (type) {
81         case GP_FILE_TYPE_NORMAL:
82                 return dc210_download_picture_by_name(camera, file, filename, DC210_FULL_PICTURE, context);
83         case GP_FILE_TYPE_PREVIEW:
84                 return dc210_download_picture_by_name(camera, file, filename, DC210_CFA_THUMB, context);
85         default:
86                 return (GP_ERROR_NOT_SUPPORTED);
87         };
88
89         return GP_OK;
90 }
91
92 static int delete_file_func (CameraFilesystem *fs, const char *folder, 
93                              const char *filename, void *data,
94                              GPContext *context) 
95 {
96         Camera *camera = data;
97
98         return dc210_delete_picture_by_name(camera, filename);
99
100 };
101
102 static int get_info_func (CameraFilesystem *fs, const char *folder, const char *file,
103                           CameraFileInfo *info, void *data, GPContext *context)
104 {
105         Camera *camera = data;
106         dc210_picture_info picinfo;
107         
108         if (dc210_get_picture_info_by_name(camera, &picinfo, file) == GP_ERROR)
109                 return GP_ERROR;
110
111         info->preview.fields |= GP_FILE_INFO_TYPE;
112         info->preview.fields |= GP_FILE_INFO_NAME;
113         info->preview.fields |= GP_FILE_INFO_SIZE;
114         info->preview.fields |= GP_FILE_INFO_WIDTH;
115         info->preview.fields |= GP_FILE_INFO_HEIGHT;
116
117         strcpy(info->preview.type, GP_MIME_PPM);
118         info->preview.width = 96;
119         info->preview.height = 72;
120         info->preview.size = picinfo.preview_size;
121         strncpy(info->file.name, picinfo.image_name, 9);
122         strncpy(info->file.name + 9, "PPM\0", 4);
123
124         info->file.fields |= GP_FILE_INFO_TYPE;
125         info->file.fields |= GP_FILE_INFO_NAME;
126         info->file.fields |= GP_FILE_INFO_SIZE;
127         info->file.fields |= GP_FILE_INFO_WIDTH;
128         info->file.fields |= GP_FILE_INFO_HEIGHT;
129         info->file.fields |= GP_FILE_INFO_MTIME;
130
131         info->file.size = picinfo.picture_size;
132         switch(picinfo.file_type){
133         case DC210_FILE_TYPE_JPEG:
134                 strcpy(info->file.type, GP_MIME_JPEG); break;
135         case DC210_FILE_TYPE_FPX:
136                 strcpy(info->file.type, GP_MIME_UNKNOWN); break;
137         };
138         switch(picinfo.resolution){
139         case DC210_FILE_640:
140                 info->file.width = 640;
141                 info->file.height = 480;
142                 break;
143         case DC210_FILE_1152:
144                 info->file.width = 1152;
145                 info->file.height = 864;
146                 break;
147         };
148         strncpy(info->file.name, picinfo.image_name, 13);
149         info->file.mtime = picinfo.picture_time;
150
151         info->audio.fields |= GP_FILE_INFO_NONE;
152
153         return GP_OK;
154
155 };
156
157
158 static int
159 camera_get_config (Camera *camera, CameraWidget **window, GPContext *context)
160 {
161         CameraWidget *section, *widget;
162         CameraAbilities abilities;
163         GPPortSettings settings;
164         int i;
165         char * wvalue;
166         char stringbuffer[12];
167         
168         dc210_status status;
169
170         if (dc210_get_status(camera, &status) == GP_ERROR) return GP_ERROR;
171
172         gp_widget_new (GP_WIDGET_WINDOW, _("Camera Configuration"), window);
173
174         gp_widget_new (GP_WIDGET_SECTION, _("File"), &section);
175         gp_widget_append (*window, section);
176
177         gp_widget_new (GP_WIDGET_RADIO, _("File type"), &widget);
178         gp_widget_append (section, widget);
179         gp_widget_add_choice (widget, _("JPEG"));
180         gp_widget_add_choice (widget, _("FlashPix"));
181
182         switch (status.file_type){
183         case DC210_FILE_TYPE_JPEG:  
184           gp_widget_set_value (widget, _("JPEG")); break;
185         case DC210_FILE_TYPE_FPX:  
186           gp_widget_set_value (widget, _("FlashPix")); break;
187         };
188         gp_widget_get_value (widget, &wvalue);
189
190         gp_widget_new (GP_WIDGET_RADIO, _("File resolution"), &widget);
191         gp_widget_append (section, widget);
192         gp_widget_add_choice (widget, _("640 x 480"));
193         gp_widget_add_choice (widget, _("1152 x 864"));
194
195         switch (status.resolution){
196         case DC210_FILE_640:  
197           gp_widget_set_value (widget, _("640 x 480")); break;
198         case DC210_FILE_1152:  
199           gp_widget_set_value (widget, _("1152 x 864")); break;
200         default:
201           DC210_DEBUG("Undefined value for file resolution.\n"); break;
202         };
203         gp_widget_get_value (widget, &wvalue);
204
205         gp_widget_new (GP_WIDGET_MENU, _("File compression"), &widget);
206         gp_widget_append (section, widget);
207         gp_widget_add_choice (widget, _("Low (best quality)"));
208         gp_widget_add_choice (widget, _("Medium (better quality)"));
209         gp_widget_add_choice (widget, _("High (good quality)"));
210
211         switch (status.compression_type){
212         case DC210_LOW_COMPRESSION:  
213           gp_widget_set_value (widget, _("Low (best quality)")); break;
214         case DC210_MEDIUM_COMPRESSION:  
215           gp_widget_set_value (widget, _("Medium (better quality)")); break;
216         case DC210_HIGH_COMPRESSION:  
217           gp_widget_set_value (widget, _("High (good quality)")); break;
218         };
219         gp_widget_get_value (widget, &wvalue);
220
221         gp_widget_new (GP_WIDGET_SECTION, _("Capture"), &section);
222         gp_widget_append (*window, section);
223
224         gp_widget_new (GP_WIDGET_MENU, _("Zoom"), &widget);
225         gp_widget_append (section, widget);
226         gp_widget_add_choice (widget, "58 mm"); /* no need to translate strings with SI units! */
227         gp_widget_add_choice (widget, "51 mm");
228         gp_widget_add_choice (widget, "41 mm");
229         gp_widget_add_choice (widget, "34 mm");
230         gp_widget_add_choice (widget, "29 mm");
231         gp_widget_add_choice (widget, _("Macro"));
232
233         switch (status.zoom){
234         case DC210_ZOOM_58:  
235           gp_widget_set_value (widget, _("58 mm")); break;
236         case DC210_ZOOM_51:  
237           gp_widget_set_value (widget, _("51 mm")); break;
238         case DC210_ZOOM_41:  
239           gp_widget_set_value (widget, _("41 mm")); break;
240         case DC210_ZOOM_34:  
241           gp_widget_set_value (widget, _("34 mm")); break;
242         case DC210_ZOOM_29:  
243           gp_widget_set_value (widget, _("29 mm")); break;
244         case DC210_ZOOM_MACRO:  
245           gp_widget_set_value (widget, _("Macro")); break;
246         };
247         gp_widget_get_value (widget, &wvalue);
248
249         gp_widget_new (GP_WIDGET_MENU, _("Exposure compensation"), &widget);
250         gp_widget_append (section, widget);
251         for (i = 0; i < sizeof(exp_comp)/sizeof(*exp_comp); i++){
252                 gp_widget_add_choice (widget, exp_comp[i]);
253                 if (status.exp_compensation + 4 == i)
254                         gp_widget_set_value (widget, exp_comp[i]);
255         };
256
257         gp_widget_new (GP_WIDGET_RADIO, _("Flash"), &widget);
258         gp_widget_append (section, widget);
259         gp_widget_add_choice (widget, _("Auto"));
260         gp_widget_add_choice (widget, _("Force"));
261         gp_widget_add_choice (widget, _("None"));
262
263         switch (status.flash){
264         case DC210_FLASH_AUTO:  
265           gp_widget_set_value (widget, _("Auto")); break;
266         case DC210_FLASH_FORCE:  
267           gp_widget_set_value (widget, _("Force")); break;
268         case DC210_FLASH_NONE:  
269           gp_widget_set_value (widget, _("None")); break;
270         };
271         gp_widget_get_value (widget, &wvalue);
272
273         gp_widget_new (GP_WIDGET_RADIO, _("Red eye flash"), &widget);
274         gp_widget_append (section, widget);
275         gp_widget_add_choice (widget, _("On"));
276         gp_widget_add_choice (widget, _("Off"));
277
278         if (status.preflash)
279           gp_widget_set_value (widget, _("On"));
280         else
281           gp_widget_set_value (widget, _("Off"));
282         gp_widget_get_value (widget, &wvalue);
283
284         gp_widget_new (GP_WIDGET_SECTION, _("Other"), &section);
285         gp_widget_append (*window, section);
286
287         gp_widget_new (GP_WIDGET_BUTTON, "Set time to system time", &widget);
288         gp_widget_append (section, widget);
289         gp_widget_set_value (widget, dc210_system_time_callback);
290         gp_widget_set_info (widget, _("Set clock in camera"));
291         
292         gp_camera_get_abilities(camera, &abilities);
293         gp_port_get_settings (camera->port, &settings);
294         gp_widget_new (GP_WIDGET_MENU, _("Port speed"), &widget);
295         gp_widget_append (section, widget);
296         for (i = 0; i < sizeof(abilities.speed); i++){
297                 if (abilities.speed[i] == 0) break;
298                 snprintf(stringbuffer, 12, "%d", abilities.speed[i]);
299                 gp_widget_add_choice (widget, stringbuffer);
300                 if (settings.serial.speed == abilities.speed[i])
301                         gp_widget_set_value (widget, stringbuffer);
302         };
303
304         gp_widget_new (GP_WIDGET_TEXT, _("Album name"), &widget);
305         gp_widget_append (section, widget);
306         gp_widget_set_value (widget, status.album_name);
307         gp_widget_set_info (widget, _("Name to set on card when formatting."));
308
309         gp_widget_new (GP_WIDGET_BUTTON, _("Format compact flash"), &widget);
310         gp_widget_append (section, widget);
311         gp_widget_set_value (widget, dc210_format_callback);
312         gp_widget_set_info (widget, _("Format card and set album name."));
313
314 #ifdef DEBUG
315         gp_widget_new (GP_WIDGET_SECTION, _("Debug"), &section);
316         gp_widget_append (*window, section);
317
318         gp_widget_new (GP_WIDGET_TEXT, "Parameter 1", &widget);
319         gp_widget_append (section, widget);
320         gp_widget_set_value (widget, "0");
321
322         gp_widget_new (GP_WIDGET_TEXT, "Parameter 2", &widget);
323         gp_widget_append (section, widget);
324         gp_widget_set_value (widget, "0");
325
326         gp_widget_new (GP_WIDGET_TEXT, "Parameter 3", &widget);
327         gp_widget_append (section, widget);
328         gp_widget_set_value (widget, "0");
329
330         gp_widget_new (GP_WIDGET_BUTTON, "Execute debug command", &widget);
331         gp_widget_append (section, widget);
332         gp_widget_set_value (widget, dc210_debug_callback);
333         gp_widget_set_info (widget, _("Execute predefined command\nwith parameter values."));
334 #endif
335
336         return GP_OK;
337 }
338
339 static int
340 camera_set_config (Camera *camera, CameraWidget *window, GPContext *context)
341 {
342         CameraWidget *w, *w2;
343         char *wvalue, *w2value;
344         int i;
345
346         gp_widget_get_child_by_label (window, _("File type"), &w);
347         if (gp_widget_changed (w)) {
348                 gp_widget_get_value (w, &wvalue);
349                 if (wvalue[0] == 'J')
350                         dc210_set_file_type(camera, DC210_FILE_TYPE_JPEG);
351                 else
352                         dc210_set_file_type(camera, DC210_FILE_TYPE_FPX);
353         };
354
355         gp_widget_get_child_by_label (window, _("File resolution"), &w);
356         if (gp_widget_changed (w)) {
357                 gp_widget_get_value (w, &wvalue);
358                 switch(wvalue[0]){
359                 case '6':
360                   dc210_set_resolution(camera, DC210_FILE_640);
361                   break;
362                 case '1':
363                   dc210_set_resolution(camera, DC210_FILE_1152);
364                   break;
365                 };
366         };
367
368         gp_widget_get_child_by_label (window, _("File compression"), &w);
369         if (gp_widget_changed (w)) {
370                 gp_widget_get_value (w, &wvalue);
371                 switch(wvalue[0]){
372                 case 'L':
373                   dc210_set_compression(camera, DC210_LOW_COMPRESSION);
374                   break;
375                 case 'M':
376                   dc210_set_compression(camera, DC210_MEDIUM_COMPRESSION);
377                   break;
378                 case 'H':
379                   dc210_set_compression(camera, DC210_HIGH_COMPRESSION);
380                 };
381         };
382
383         gp_widget_get_child_by_label (window, _("Zoom"), &w);
384         if (gp_widget_changed (w)) {
385                 gp_widget_get_value (w, &wvalue);
386                 switch(wvalue[0]){
387                 case '5':
388                         if (wvalue[1] == '8')
389                                 dc210_set_zoom(camera, DC210_ZOOM_58);
390                         else
391                                 dc210_set_zoom(camera, DC210_ZOOM_51);
392                         break;
393                 case '4':
394                         dc210_set_zoom(camera, DC210_ZOOM_41);
395                         break;
396                 case '3':
397                         dc210_set_zoom(camera, DC210_ZOOM_34);
398                         break;
399                 case '2':
400                         dc210_set_zoom(camera, DC210_ZOOM_29);
401                         break;
402                 case 'M':
403                         dc210_set_zoom(camera, DC210_ZOOM_MACRO);
404                         break;
405                 };
406         };
407
408         gp_widget_get_child_by_label (window, _("Exposure compensation"), &w);
409         if (gp_widget_changed (w)) {
410                 gp_widget_get_value (w, &wvalue);
411                 for (i = 0; i < sizeof(exp_comp)/sizeof(*exp_comp); i++){
412                         if (strncmp(wvalue, exp_comp[i], 4) == 0){
413                                 dc210_set_exp_compensation(camera, i - 4);
414                                 break;
415                         };
416                 };
417         };
418
419         gp_widget_get_child_by_label (window, _("Port speed"), &w);
420         if (gp_widget_changed (w)) {
421                 gp_widget_get_value (w, &wvalue);
422                 dc210_set_speed(camera, atoi(wvalue));
423         };
424
425         gp_widget_get_child_by_label (window, _("Flash"), &w);
426         gp_widget_get_child_by_label (window, _("Red eye flash"), &w2);
427         if (gp_widget_changed (w) || gp_widget_changed(w2)) {
428                 gp_widget_get_value (w, &wvalue);
429                 gp_widget_get_value (w2, &w2value);
430                 switch(wvalue[0]){
431                 case 'A':
432                         dc210_set_flash(camera, DC210_FLASH_AUTO, 
433                                         w2value[1] == 'n' ? 1 : 0);
434                         break;
435                 case 'F':
436                         dc210_set_flash(camera, DC210_FLASH_FORCE, 
437                                         w2value[1] == 'n' ? 1 : 0);
438                         break;
439                 case 'N':
440                         dc210_set_flash(camera, DC210_FLASH_NONE, 0);
441                         gp_widget_set_value(w2, _("Off"));
442                         break;
443                 };
444         };
445
446         return GP_OK;
447 }
448
449 static int camera_capture (Camera *camera, CameraCaptureType type, CameraFilePath *path, GPContext *context) {
450
451
452         if (type && type != GP_CAPTURE_IMAGE){
453                 DC210_DEBUG("Unsupported action 0x%.2X\n", type);
454                 return (GP_ERROR_NOT_SUPPORTED);
455         };
456
457         if (dc210_capture(camera, path, context) == GP_ERROR) 
458                 return GP_ERROR;
459
460         if (gp_filesystem_append (camera->fs, path->folder, path->name, context) == GP_ERROR)
461                 return GP_ERROR;;
462
463         return (GP_OK);
464
465 }
466
467 static int camera_capture_preview (Camera* camera, CameraFile* file, GPContext *context){
468
469         /* this function is to slow; don't export it */
470         int fatal_error = 0;
471
472         if (dc210_take_picture(camera, context) == GP_ERROR) return GP_ERROR;
473         if (dc210_download_last_picture(camera, file, DC210_FULL_PICTURE, context) == GP_ERROR) fatal_error = 1;
474         if (dc210_delete_last_picture(camera) == GP_ERROR) fatal_error = 1;
475
476         if (fatal_error) return GP_ERROR;
477
478         return GP_OK;
479
480 };
481
482 static int camera_summary (Camera *camera, CameraText *summary,
483                            GPContext *context) 
484 {
485     static char summary_string[2048] = "";
486     char buff[1024];
487     dc210_status status;
488
489     if (GP_OK == dc210_get_status (camera, &status))
490     {
491         strcpy(summary_string,"Kodak DC210\n");
492         
493         snprintf(buff,1024,_("Pictures in camera: %d\n"),
494                  status.numPicturesInCamera);
495         strcat(summary_string,buff);
496
497         snprintf(buff,1024,_("There is space for another\n   %d low compressed\n   %d medium compressed or\n   %d high compressed pictures\n"),
498                  status.remainingLow, status.remainingMedium, status.remainingHigh);
499         strcat(summary_string,buff);
500
501         snprintf(buff,1024,_("Total pictures taken: %d\n"),
502                  status.totalPicturesTaken);
503         strcat(summary_string,buff);
504
505         snprintf(buff,1024,_("Total flashes fired: %d\n"),
506                  status.totalFlashesFired);
507         strcat(summary_string,buff);
508
509         snprintf(buff,1024,_("Firmware: %d.%d\n"),status.firmwareMajor,status.firmwareMinor);
510         strcat(summary_string,buff);
511
512         switch (status.file_type){
513         case DC210_FILE_TYPE_JPEG: 
514                 snprintf(buff, 1024, _("Filetype: JPEG (")); break;
515         case DC210_FILE_TYPE_FPX: 
516                 snprintf(buff, 1024, _("Filetype: FlashPix (")); break;
517         };
518         strcat(summary_string, buff);
519         
520         switch (status.compression_type){
521         case DC210_LOW_COMPRESSION:    
522                 snprintf(buff, 1024, _("low compression, ")); break;
523         case DC210_MEDIUM_COMPRESSION: 
524                 snprintf(buff, 1024, _("medium compression, ")); break;
525         case DC210_HIGH_COMPRESSION:   
526                 snprintf(buff, 1024, _("high compression, ")); break;
527         default:                       
528                 snprintf(buff, 1024, _("unknown compression %d, "), status.compression_type); break;
529         };
530         strcat(summary_string, buff);
531         
532         switch (status.resolution){
533         case DC210_FILE_640: 
534                 snprintf(buff, 1024, "640x480 pixel)\n"); break;
535         case DC210_FILE_1152: 
536                 snprintf(buff, 1024, "1152x864 pixel)\n"); break;
537         default: 
538                 snprintf(buff, 1024, _("unknown resolution %d)\n"), status.resolution); break;
539         };
540         strcat(summary_string, buff);
541         
542         /* battery check still doesn't work */
543         /* switch (status.battery){
544         case 0: snprintf(buff,1024,"Battery charge is good\n"); break;
545         case 1: snprintf(buff,1024,"Battery charge is low\n"); break;
546         case 2: snprintf(buff,1024,"Battery is not charged\n"); break;
547         };
548         strcat(summary_string,buff);*/
549         
550         if (status.acstatus)
551                 snprintf(buff,1024,_("AC adapter is connected.\n"));
552         else
553                 snprintf(buff,1024,_("AC adapter is not connected.\n"));
554         strcat(summary_string,buff);
555         
556         /* time string, do not change the % escapes */
557         strftime(buff,1024,_("Time: %a, %d %b %Y %T\n"),
558                  localtime((time_t *)&status.time));
559         strcat(summary_string,buff);
560         
561         switch (status.zoom){
562         case DC210_ZOOM_58: 
563                 snprintf(buff, 1024, _("Zoom: 58 mm\n")); break;
564         case DC210_ZOOM_51: 
565                 snprintf(buff, 1024, _("Zoom: 51 mm\n")); break;
566         case DC210_ZOOM_41: 
567                 snprintf(buff, 1024, _("Zoom: 41 mm\n")); break;
568         case DC210_ZOOM_34: 
569                 snprintf(buff, 1024, _("Zoom: 34 mm\n")); break;
570         case DC210_ZOOM_29: 
571                 snprintf(buff, 1024, _("Zoom: 29 mm\n")); break;
572         case DC210_ZOOM_MACRO: 
573                 snprintf(buff, 1024, _("Zoom: macro\n")); break;
574         default: 
575                 snprintf(buff, 1024, _("Unknown zoom mode %d\n"), 
576                          status.zoom); break;
577         };
578         strcat(summary_string,buff);
579         
580         if (status.exp_compensation > -5 && status.exp_compensation < 4)
581                 snprintf(buff, 1024, _("Exposure compensation: %s\n"), exp_comp[status.exp_compensation + 4]);
582         else
583                 snprintf(buff, 1024, _("Exposure compensation: %d\n"), status.exp_compensation);
584         strcat(summary_string,buff);
585
586         switch (status.flash){
587         case DC210_FLASH_AUTO: 
588                 snprintf(buff, 1024, _("Flash mode: auto, ")); break;
589         case DC210_FLASH_FORCE: 
590                 snprintf(buff, 1024, _("Flash mode: force, ")); break;
591         case DC210_FLASH_NONE: 
592                 snprintf(buff, 1024, _("Flash mode: off\n")); break;
593         default: 
594                 snprintf(buff, 1024, _("Unknown flash mode %d, "), 
595                          status.flash); break;
596         };
597         strcat(summary_string,buff);
598
599         if (status.flash != DC210_FLASH_NONE){
600                 if (status.preflash)
601                         /* trans: continuation of "Flash mode:" line */
602                         snprintf(buff,1024,_("red eye flash on.\n"));
603                 else
604                         /* trans: continuation of "Flash mode:" line */
605                         snprintf(buff,1024,_("red eye flash off.\n"));
606                 strcat(summary_string,buff);
607         };
608
609         if (status.card_status.open == 0)
610                 snprintf(buff, 1024, _("No card in camera.\n"));
611         else
612                 snprintf(buff,1024, _("Card name: %s\nFree space on card: %d kB\n"),
613                          status.album_name,
614                          status.card_status.space);
615         
616         strcat(summary_string,buff);
617
618     }
619     else{
620             DC210_DEBUG("Couldn't get summary for camera\n");
621     };
622     
623     strcpy(summary->text, summary_string);
624     
625     return (GP_OK);
626 }
627
628
629 static int camera_manual (Camera *camera, CameraText *manual,
630                           GPContext *context) 
631 {
632         strcpy (manual->text, _("This library has been tested with a Kodak DC 215 Zoom camera. "
633                                 "It might work also with DC 200 and DC 210 cameras. "
634                                 "If you happen to have such a camera, please send a "
635                                 "message to koltan@gmx.de to let me know, if you have any "
636                                 "troubles with this driver library or if everything is okay."));
637
638         return (GP_OK);
639 }
640
641 static int camera_about (Camera *camera, CameraText *about, GPContext *context) 
642 {
643         strcpy(about->text, 
644                 _("Camera Library for the Kodak DC215 Zoom camera.\n"
645                   "Michael Koltan <koltan@gmx.de>\n"));
646
647         return (GP_OK);
648 }
649
650 static CameraFilesystemFuncs fsfuncs = {
651         .file_list_func = file_list_func,
652         .get_file_func = get_file_func,
653         .get_info_func = get_info_func,
654         .del_file_func = delete_file_func,
655 };
656
657 int camera_init (Camera *camera, GPContext *context) {
658
659         DC210_DEBUG("Initialising camera.\n");
660
661         /* First, set up all the function pointers */
662         camera->functions->get_config = camera_get_config;
663         camera->functions->set_config = camera_set_config;
664         camera->functions->capture      = camera_capture;
665         camera->functions->capture_preview      = camera_capture_preview;
666         camera->functions->summary      = camera_summary;
667         camera->functions->manual       = camera_manual;
668         camera->functions->about        = camera_about;
669
670         gp_filesystem_set_funcs (camera->fs, &fsfuncs, camera);
671
672         if (dc210_init_port (camera) == GP_ERROR) return GP_ERROR;
673         if (dc210_open_card (camera) == GP_ERROR) return GP_ERROR;
674
675         return (GP_OK);
676 }
677 /****************************************************************************/