8 #include <gphoto2/gphoto2.h>
9 #include <gphoto2/gphoto2-port.h>
15 # define _(String) dgettext (PACKAGE, String)
16 # define N_(String) gettext_noop (String)
18 # define _(String) (String)
19 # define N_(String) (String)
22 # define _(String) (String)
23 # define N_(String) (String)
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"};
31 int camera_id (CameraText *id) {
33 strcpy(id->text, GP_MODULE);
38 int camera_abilities (CameraAbilitiesList *list) {
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;
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;
56 gp_abilities_list_append(list, a);
58 /* Mark Longridge <mark@cubeman.org> */
59 strcpy(a.model, "Kodak:DC215");
60 gp_abilities_list_append(list, a);
65 static int file_list_func (CameraFilesystem *fs, const char *folder,
66 CameraList *list, void *data, GPContext *context)
68 Camera *camera = data;
70 return dc210_get_filenames(camera, list, context);
74 static int get_file_func (CameraFilesystem *fs, const char *folder,
75 const char *filename, CameraFileType type,
76 CameraFile *file, void *data, GPContext *context)
78 Camera *camera = data;
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);
86 return (GP_ERROR_NOT_SUPPORTED);
92 static int delete_file_func (CameraFilesystem *fs, const char *folder,
93 const char *filename, void *data,
96 Camera *camera = data;
98 return dc210_delete_picture_by_name(camera, filename);
102 static int get_info_func (CameraFilesystem *fs, const char *folder, const char *file,
103 CameraFileInfo *info, void *data, GPContext *context)
105 Camera *camera = data;
106 dc210_picture_info picinfo;
108 if (dc210_get_picture_info_by_name(camera, &picinfo, file) == GP_ERROR)
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;
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);
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;
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;
138 switch(picinfo.resolution){
140 info->file.width = 640;
141 info->file.height = 480;
143 case DC210_FILE_1152:
144 info->file.width = 1152;
145 info->file.height = 864;
148 strncpy(info->file.name, picinfo.image_name, 13);
149 info->file.mtime = picinfo.picture_time;
151 info->audio.fields |= GP_FILE_INFO_NONE;
159 camera_get_config (Camera *camera, CameraWidget **window, GPContext *context)
161 CameraWidget *section, *widget;
162 CameraAbilities abilities;
163 GPPortSettings settings;
166 char stringbuffer[12];
170 if (dc210_get_status(camera, &status) == GP_ERROR) return GP_ERROR;
172 gp_widget_new (GP_WIDGET_WINDOW, _("Camera Configuration"), window);
174 gp_widget_new (GP_WIDGET_SECTION, _("File"), §ion);
175 gp_widget_append (*window, section);
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"));
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;
188 gp_widget_get_value (widget, &wvalue);
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"));
195 switch (status.resolution){
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;
201 DC210_DEBUG("Undefined value for file resolution.\n"); break;
203 gp_widget_get_value (widget, &wvalue);
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)"));
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;
219 gp_widget_get_value (widget, &wvalue);
221 gp_widget_new (GP_WIDGET_SECTION, _("Capture"), §ion);
222 gp_widget_append (*window, section);
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"));
233 switch (status.zoom){
235 gp_widget_set_value (widget, _("58 mm")); break;
237 gp_widget_set_value (widget, _("51 mm")); break;
239 gp_widget_set_value (widget, _("41 mm")); break;
241 gp_widget_set_value (widget, _("34 mm")); break;
243 gp_widget_set_value (widget, _("29 mm")); break;
244 case DC210_ZOOM_MACRO:
245 gp_widget_set_value (widget, _("Macro")); break;
247 gp_widget_get_value (widget, &wvalue);
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]);
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"));
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;
271 gp_widget_get_value (widget, &wvalue);
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"));
279 gp_widget_set_value (widget, _("On"));
281 gp_widget_set_value (widget, _("Off"));
282 gp_widget_get_value (widget, &wvalue);
284 gp_widget_new (GP_WIDGET_SECTION, _("Other"), §ion);
285 gp_widget_append (*window, section);
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"));
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);
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."));
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."));
315 gp_widget_new (GP_WIDGET_SECTION, _("Debug"), §ion);
316 gp_widget_append (*window, section);
318 gp_widget_new (GP_WIDGET_TEXT, "Parameter 1", &widget);
319 gp_widget_append (section, widget);
320 gp_widget_set_value (widget, "0");
322 gp_widget_new (GP_WIDGET_TEXT, "Parameter 2", &widget);
323 gp_widget_append (section, widget);
324 gp_widget_set_value (widget, "0");
326 gp_widget_new (GP_WIDGET_TEXT, "Parameter 3", &widget);
327 gp_widget_append (section, widget);
328 gp_widget_set_value (widget, "0");
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."));
340 camera_set_config (Camera *camera, CameraWidget *window, GPContext *context)
342 CameraWidget *w, *w2;
343 char *wvalue, *w2value;
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);
352 dc210_set_file_type(camera, DC210_FILE_TYPE_FPX);
355 gp_widget_get_child_by_label (window, _("File resolution"), &w);
356 if (gp_widget_changed (w)) {
357 gp_widget_get_value (w, &wvalue);
360 dc210_set_resolution(camera, DC210_FILE_640);
363 dc210_set_resolution(camera, DC210_FILE_1152);
368 gp_widget_get_child_by_label (window, _("File compression"), &w);
369 if (gp_widget_changed (w)) {
370 gp_widget_get_value (w, &wvalue);
373 dc210_set_compression(camera, DC210_LOW_COMPRESSION);
376 dc210_set_compression(camera, DC210_MEDIUM_COMPRESSION);
379 dc210_set_compression(camera, DC210_HIGH_COMPRESSION);
383 gp_widget_get_child_by_label (window, _("Zoom"), &w);
384 if (gp_widget_changed (w)) {
385 gp_widget_get_value (w, &wvalue);
388 if (wvalue[1] == '8')
389 dc210_set_zoom(camera, DC210_ZOOM_58);
391 dc210_set_zoom(camera, DC210_ZOOM_51);
394 dc210_set_zoom(camera, DC210_ZOOM_41);
397 dc210_set_zoom(camera, DC210_ZOOM_34);
400 dc210_set_zoom(camera, DC210_ZOOM_29);
403 dc210_set_zoom(camera, DC210_ZOOM_MACRO);
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);
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));
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);
432 dc210_set_flash(camera, DC210_FLASH_AUTO,
433 w2value[1] == 'n' ? 1 : 0);
436 dc210_set_flash(camera, DC210_FLASH_FORCE,
437 w2value[1] == 'n' ? 1 : 0);
440 dc210_set_flash(camera, DC210_FLASH_NONE, 0);
441 gp_widget_set_value(w2, _("Off"));
449 static int camera_capture (Camera *camera, CameraCaptureType type, CameraFilePath *path, GPContext *context) {
452 if (type && type != GP_CAPTURE_IMAGE){
453 DC210_DEBUG("Unsupported action 0x%.2X\n", type);
454 return (GP_ERROR_NOT_SUPPORTED);
457 if (dc210_capture(camera, path, context) == GP_ERROR)
460 if (gp_filesystem_append (camera->fs, path->folder, path->name, context) == GP_ERROR)
467 static int camera_capture_preview (Camera* camera, CameraFile* file, GPContext *context){
469 /* this function is to slow; don't export it */
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;
476 if (fatal_error) return GP_ERROR;
482 static int camera_summary (Camera *camera, CameraText *summary,
485 static char summary_string[2048] = "";
489 if (GP_OK == dc210_get_status (camera, &status))
491 strcpy(summary_string,"Kodak DC210\n");
493 snprintf(buff,1024,_("Pictures in camera: %d\n"),
494 status.numPicturesInCamera);
495 strcat(summary_string,buff);
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);
501 snprintf(buff,1024,_("Total pictures taken: %d\n"),
502 status.totalPicturesTaken);
503 strcat(summary_string,buff);
505 snprintf(buff,1024,_("Total flashes fired: %d\n"),
506 status.totalFlashesFired);
507 strcat(summary_string,buff);
509 snprintf(buff,1024,_("Firmware: %d.%d\n"),status.firmwareMajor,status.firmwareMinor);
510 strcat(summary_string,buff);
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;
518 strcat(summary_string, buff);
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;
528 snprintf(buff, 1024, _("unknown compression %d, "), status.compression_type); break;
530 strcat(summary_string, buff);
532 switch (status.resolution){
534 snprintf(buff, 1024, "640x480 pixel)\n"); break;
535 case DC210_FILE_1152:
536 snprintf(buff, 1024, "1152x864 pixel)\n"); break;
538 snprintf(buff, 1024, _("unknown resolution %d)\n"), status.resolution); break;
540 strcat(summary_string, buff);
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;
548 strcat(summary_string,buff);*/
551 snprintf(buff,1024,_("AC adapter is connected.\n"));
553 snprintf(buff,1024,_("AC adapter is not connected.\n"));
554 strcat(summary_string,buff);
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);
561 switch (status.zoom){
563 snprintf(buff, 1024, _("Zoom: 58 mm\n")); break;
565 snprintf(buff, 1024, _("Zoom: 51 mm\n")); break;
567 snprintf(buff, 1024, _("Zoom: 41 mm\n")); break;
569 snprintf(buff, 1024, _("Zoom: 34 mm\n")); break;
571 snprintf(buff, 1024, _("Zoom: 29 mm\n")); break;
572 case DC210_ZOOM_MACRO:
573 snprintf(buff, 1024, _("Zoom: macro\n")); break;
575 snprintf(buff, 1024, _("Unknown zoom mode %d\n"),
578 strcat(summary_string,buff);
580 if (status.exp_compensation > -5 && status.exp_compensation < 4)
581 snprintf(buff, 1024, _("Exposure compensation: %s\n"), exp_comp[status.exp_compensation + 4]);
583 snprintf(buff, 1024, _("Exposure compensation: %d\n"), status.exp_compensation);
584 strcat(summary_string,buff);
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;
594 snprintf(buff, 1024, _("Unknown flash mode %d, "),
595 status.flash); break;
597 strcat(summary_string,buff);
599 if (status.flash != DC210_FLASH_NONE){
601 /* trans: continuation of "Flash mode:" line */
602 snprintf(buff,1024,_("red eye flash on.\n"));
604 /* trans: continuation of "Flash mode:" line */
605 snprintf(buff,1024,_("red eye flash off.\n"));
606 strcat(summary_string,buff);
609 if (status.card_status.open == 0)
610 snprintf(buff, 1024, _("No card in camera.\n"));
612 snprintf(buff,1024, _("Card name: %s\nFree space on card: %d kB\n"),
614 status.card_status.space);
616 strcat(summary_string,buff);
620 DC210_DEBUG("Couldn't get summary for camera\n");
623 strcpy(summary->text, summary_string);
629 static int camera_manual (Camera *camera, CameraText *manual,
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."));
641 static int camera_about (Camera *camera, CameraText *about, GPContext *context)
644 _("Camera Library for the Kodak DC215 Zoom camera.\n"
645 "Michael Koltan <koltan@gmx.de>\n"));
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,
657 int camera_init (Camera *camera, GPContext *context) {
659 DC210_DEBUG("Initialising camera.\n");
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;
670 gp_filesystem_set_funcs (camera->fs, &fsfuncs, camera);
672 if (dc210_init_port (camera) == GP_ERROR) return GP_ERROR;
673 if (dc210_open_card (camera) == GP_ERROR) return GP_ERROR;
677 /****************************************************************************/