3 * Copyright © 2002 Lutz Müller <lutz@users.sourceforge.net>
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 * Boston, MA 02111-1307, USA.
27 #include <gphoto2/gphoto2-library.h>
28 #include <gphoto2/gphoto2-port-log.h>
32 #define GP_MODULE "ricoh"
37 # define _(String) dgettext (GETTEXT_PACKAGE, String)
39 # define N_(String) gettext_noop (String)
41 # define N_(String) (String)
44 # define textdomain(String) (String)
45 # define gettext(String) (String)
46 # define dgettext(Domain,Message) (Message)
47 # define dcgettext(Domain,Message,Type) (Message)
48 # define bindtextdomain(Domain,Directory) (Domain)
49 # define _(String) (String)
50 # define N_(String) (String)
53 #define CR(result) {int r=(result); if (r<0) return r;}
54 #define CRW(result,widget) {int r=(result); if (r<0) { gp_widget_free (widget); return r; } }
60 {RICOH_MODEL_1, "Ricoh:RDC-1"},
61 {RICOH_MODEL_2, "Ricoh:RDC-2"},
62 {RICOH_MODEL_2E, "Ricoh:RDC-2E"},
63 {RICOH_MODEL_100G, "Ricoh:RDC-100G"},
64 {RICOH_MODEL_300, "Ricoh:RDC-300"},
65 {RICOH_MODEL_300Z, "Ricoh:RDC-300Z"},
66 {RICOH_MODEL_4200, "Ricoh:RDC-4200"},
67 {RICOH_MODEL_4300, "Ricoh:RDC-4300"},
68 {RICOH_MODEL_5000, "Ricoh:RDC-5000"},
69 {RICOH_MODEL_ESP2, "Philips:ESP2"},
70 {RICOH_MODEL_ESP50, "Philips:ESP50"},
71 {RICOH_MODEL_ESP60, "Philips:ESP60"},
72 {RICOH_MODEL_ESP70, "Philips:ESP70"},
73 {RICOH_MODEL_ESP80, "Philips:ESP80"},
74 {RICOH_MODEL_ESP80SXG, "Philips:ESP80SXG"},
78 struct _CameraPrivateLibrary {
83 camera_abilities (CameraAbilitiesList *list)
88 memset (&a, 0, sizeof (CameraAbilities));
89 for (i = 0; models[i].model; i++) {
90 strcpy (a.model, models[i].model);
91 a.status = GP_DRIVER_STATUS_EXPERIMENTAL;
92 a.port = GP_PORT_SERIAL;
93 a.operations = GP_OPERATION_CAPTURE_IMAGE |
95 a.file_operations = GP_FILE_OPERATION_DELETE |
96 GP_FILE_OPERATION_PREVIEW;
97 a.folder_operations = GP_FOLDER_OPERATION_PUT_FILE;
98 CR (gp_abilities_list_append (list, a));
105 camera_exit (Camera *camera, GPContext *context)
112 ricoh_disconnect (camera, context);
118 file_list_func (CameraFilesystem *fs, const char *folder, CameraList *list,
119 void *data, GPContext *context)
121 Camera *camera = data;
125 CR (ricoh_get_num (camera, context, &n));
126 for (i = 0; i < n; i++) {
127 CR (ricoh_get_pic_name (camera, context, i + 1, &name));
128 CR (gp_list_append (list, name, NULL));
135 get_info_func (CameraFilesystem *fs, const char *folder, const char *filename,
136 CameraFileInfo *info, void *data, GPContext *context)
138 Camera *camera = data;
142 CR (n = gp_filesystem_number (fs, folder, filename, context));
145 info->audio.fields = GP_FILE_INFO_NONE; /* no info anbout audio files */
147 info->preview.width = 80;
148 info->preview.height = 60;
149 info->preview.fields = GP_FILE_INFO_WIDTH | GP_FILE_INFO_HEIGHT;
151 CR (ricoh_get_pic_name (camera, context, n, &name));
152 strcpy (info->file.name, name);
153 CR (ricoh_get_pic_date (camera, context, n, &info->file.mtime));
154 CR (ricoh_get_pic_size (camera, context, n, &info->file.size));
155 strcpy (info->file.type, GP_MIME_EXIF);
156 info->file.fields = GP_FILE_INFO_NAME | GP_FILE_INFO_SIZE | GP_FILE_INFO_MTIME
163 get_file_func (CameraFilesystem *fs, const char *folder, const char *filename,
164 CameraFileType type, CameraFile *file, void *user_data,
167 Camera *camera = user_data;
172 CR (n = gp_filesystem_number (fs, folder, filename, context));
176 case GP_FILE_TYPE_NORMAL:
177 CR (ricoh_get_pic (camera, context, n,
178 RICOH_FILE_TYPE_NORMAL, &data, &size));
179 gp_file_set_mime_type (file, GP_MIME_EXIF);
181 case GP_FILE_TYPE_PREVIEW:
182 CR (ricoh_get_pic (camera, context, n,
183 RICOH_FILE_TYPE_PREVIEW, &data, &size));
184 gp_file_set_mime_type (file, GP_MIME_TIFF);
187 return (GP_ERROR_NOT_SUPPORTED);
190 gp_file_set_data_and_size (file, data, size);
196 del_file_func (CameraFilesystem *fs, const char *folder, const char *filename,
197 void *user_data, GPContext *context)
199 Camera *camera = user_data;
202 CR (n = gp_filesystem_number (fs, folder, filename, context));
205 CR (ricoh_del_pic (camera, context, n));
211 camera_about (Camera *camera, CameraText *about, GPContext *context)
213 GP_DEBUG ("camera_about()");
216 _("Ricoh / Philips driver by\n"
217 "Lutz Mueller <lutz@users.sourceforge.net>,\n"
218 "Martin Fischer <martin.fischer@inka.de>,\n"
219 "based on Bob Paauwe's driver\n" )
226 camera_id (CameraText *id)
228 strcpy (id->text, "Ricoh");
234 camera_summary (Camera *camera, CameraText *about, GPContext *context)
236 int avail_mem, total_mem;
240 CR (ricoh_get_cam_amem (camera, context, &avail_mem));
241 CR (ricoh_get_cam_mem (camera, context, &total_mem));
243 memset (model, 0, sizeof (model));
244 for (i = 0; models[i].model; i++)
245 if (models[i].id == camera->pl->model)
248 strncpy (model, models[i].model, sizeof (model) - 1);
250 snprintf (model, sizeof (model) - 1, _("unknown (0x%02x)"),
253 sprintf (about->text, _("Model: %s\n"
254 "Memory: %d byte(s) of %d available"),
255 model, avail_mem, total_mem);
261 camera_capture (Camera *camera, CameraCaptureType type,
262 CameraFilePath *path, GPContext *context)
266 if (type != GP_CAPTURE_IMAGE)
267 return (GP_ERROR_NOT_SUPPORTED);
269 CR (ricoh_get_num (camera, context, &n));
270 CR (ricoh_take_pic (camera, context));
272 sprintf (path->name, "rdc%04i.jpg", n + 1);
273 strcpy (path->folder, "/");
274 CR (gp_filesystem_append (camera->fs, path->folder,
275 path->name, context));
281 put_file_func (CameraFilesystem *fs, const char *folder, CameraFile *file,
282 void *user_data, GPContext *context)
284 const char *data, *name;
285 unsigned long int size;
286 Camera *camera = user_data;
288 CR (gp_file_get_data_and_size (file, &data, &size));
289 CR (gp_file_get_name (file, &name));
291 CR (ricoh_put_file (camera, context, name, data, size));
297 #define N_ELEMENTS(v) (sizeof(v)/sizeof(v[0]))
300 RicohExposure exposure;
302 } ricoh_exposures[] = {
303 {RICOH_EXPOSURE_M20, N_("-2.0")},
304 {RICOH_EXPOSURE_M15, N_("-1.5")},
305 {RICOH_EXPOSURE_M10, N_("-1.0")},
306 {RICOH_EXPOSURE_M05, N_("-0.5")},
307 {RICOH_EXPOSURE_00, N_("0.0")},
308 {RICOH_EXPOSURE_05, N_("0.5")},
309 {RICOH_EXPOSURE_10, N_("1.0")},
310 {RICOH_EXPOSURE_15, N_("1.5")},
311 {RICOH_EXPOSURE_20, N_("2.0")},
312 {RICOH_EXPOSURE_AUTO, N_("Auto")}
316 RicohResolution resolution;
318 } ricoh_resolutions[] = {
319 {RICOH_RESOLUTION_640_480, N_("640 x 480")},
320 {RICOH_RESOLUTION_1280_960, N_("1280 x 960")}
324 RicohWhiteLevel white_level;
326 } ricoh_white_levels[] = {
327 {RICOH_WHITE_LEVEL_AUTO, N_("Auto")},
328 {RICOH_WHITE_LEVEL_OUTDOOR, N_("Outdoor")},
329 {RICOH_WHITE_LEVEL_FLUORESCENT, N_("Fluorescent")},
330 {RICOH_WHITE_LEVEL_INCANDESCENT, N_("Incandescent")},
331 {RICOH_WHITE_LEVEL_BLACK_WHITE, N_("Black & White")},
332 {RICOH_WHITE_LEVEL_SEPIA, N_("Sepia")}
339 {RICOH_MACRO_ON, N_("On")},
340 {RICOH_MACRO_OFF, N_("Off")}
344 RicohCompression compression;
346 } ricoh_compressions[] = {
347 {RICOH_COMPRESSION_NONE, N_("None")},
348 {RICOH_COMPRESSION_MAX, N_("Maximal")},
349 {RICOH_COMPRESSION_NORM, N_("Normal")},
350 {RICOH_COMPRESSION_MIN, N_("Minimal")}
354 RicohRecMode rec_mode;
356 } ricoh_rec_modes[] = {
357 {RICOH_REC_MODE_IMAGE, N_("Image")},
358 {RICOH_REC_MODE_CHARACTER, N_("Character")},
359 {RICOH_REC_MODE_SOUND, N_("Sound")},
360 {RICOH_REC_MODE_IMAGE_SOUND, N_("Image & Sound")},
361 {RICOH_REC_MODE_CHARACTER_SOUND, N_("Character & Sound")}
368 {RICOH_FLASH_AUTO, N_("Auto")},
369 {RICOH_FLASH_OFF, N_("Off")},
370 {RICOH_FLASH_ON, N_("On")}
377 {RICOH_ZOOM_OFF, N_("Off")},
378 {RICOH_ZOOM_1, N_("2x")},
379 {RICOH_ZOOM_2, N_("3x")},
380 {RICOH_ZOOM_3, N_("4x")},
381 {RICOH_ZOOM_4, N_("5x")},
382 {RICOH_ZOOM_5, N_("6x")},
383 {RICOH_ZOOM_6, N_("7x")},
384 {RICOH_ZOOM_7, N_("8x")},
385 {RICOH_ZOOM_8, N_("9x")}
389 #define R_ADD_RADIO(ca,co,s,type,n,Name) \
391 CameraWidget *w = NULL; \
395 CR (gp_widget_new (GP_WIDGET_RADIO, _(Name), &w)); \
396 CR (gp_widget_set_name (w, (Name))); \
397 CR (gp_widget_append ((s), w)); \
398 CR (ricoh_get_##n ((ca), (co), &v)); \
399 for (i = 0; i < N_ELEMENTS (ricoh_##n##s); i++) { \
400 CR (gp_widget_add_choice (w, _(ricoh_##n##s[i].name))); \
401 if (v == ricoh_##n##s[i].n) \
402 CR (gp_widget_set_value (w, \
403 _(ricoh_##n##s[i].name))); \
408 #define R_CHECK_RADIO(c,co,wi,n,Name) \
410 CameraWidget *w = NULL; \
411 const char *v = NULL; \
414 CR (gp_widget_get_child_by_name (wi, Name, &w)); \
415 if (gp_widget_changed (w)) { \
416 CR (gp_widget_get_value (w, &v)); \
417 for (i = 0; i < N_ELEMENTS (ricoh_##n##s); i++) \
418 if (!strcmp (v, _(ricoh_##n##s[i].name))) { \
419 CR (ricoh_set_##n (c, co, ricoh_##n##s[i].n)); \
426 camera_get_config (Camera *c, CameraWidget **window, GPContext *co)
429 const char *copyright;
432 CR (gp_widget_new (GP_WIDGET_WINDOW, _("Configuration"), window));
434 /* General settings */
435 CR (gp_widget_new (GP_WIDGET_SECTION, _("General"), &s));
436 CR (gp_widget_append (*window, s));
439 CR (gp_widget_new (GP_WIDGET_TEXT, _("Copyright"), &w));
440 CR (gp_widget_set_name (w, "copyright"));
441 CR (gp_widget_set_info (w, _("Copyright (max. 20 characters)")));
442 CR (gp_widget_append (s, w));
443 CR (ricoh_get_copyright (c, co, ©right));
444 CR (gp_widget_set_value (w, (void *) copyright));
447 CR (gp_widget_new (GP_WIDGET_DATE, _("Date & Time"), &w));
448 CRW (gp_widget_set_name (w, "date"), w);
449 CRW (gp_widget_set_info (w, _("Date & Time")), w);
450 CRW (gp_widget_append (s, w), w);
451 CR (ricoh_get_date (c, co, &time));
452 CR (gp_widget_set_value (w, &time));
454 /* Picture related settings */
455 CR (gp_widget_new (GP_WIDGET_SECTION, _("Pictures"), &s));
456 CRW (gp_widget_append (*window, s), w);
458 R_ADD_RADIO (c, co, s, RicohResolution, resolution, "Resolution")
459 R_ADD_RADIO (c, co, s, RicohExposure, exposure, "Exposure")
460 R_ADD_RADIO (c, co, s, RicohMacro, macro, "Macro")
461 R_ADD_RADIO (c, co, s, RicohFlash, flash, "Flash")
462 R_ADD_RADIO (c, co, s, RicohZoom, zoom, "Zoom")
463 R_ADD_RADIO (c, co, s, RicohCompression, compression, "Compression")
464 R_ADD_RADIO (c, co, s, RicohWhiteLevel, white_level, "White Level")
465 R_ADD_RADIO (c, co, s, RicohRecMode, rec_mode, "Record Mode")
471 camera_set_config (Camera *c, CameraWidget *window, GPContext *co)
478 /* We need to be in record mode to set settings. */
479 CR (ricoh_get_mode (c, co, &mode));
480 if (mode != RICOH_MODE_RECORD)
481 CR (ricoh_set_mode (c, co, RICOH_MODE_RECORD));
484 CR (gp_widget_get_child_by_name (window, "copyright", &w));
485 if (gp_widget_changed (w)) {
486 CR (gp_widget_get_value (w, &v_char));
487 CR (ricoh_set_copyright (c, co, v_char));
491 CR (gp_widget_get_child_by_name (window, "date", &w));
492 if (gp_widget_changed (w)) {
493 CR (gp_widget_get_value (w, &time));
494 CR (ricoh_set_date (c, co, time));
497 R_CHECK_RADIO (c, co, window, resolution, N_("Resolution"))
498 R_CHECK_RADIO (c, co, window, exposure, N_("Exposure"))
499 R_CHECK_RADIO (c, co, window, white_level, N_("White level"))
500 R_CHECK_RADIO (c, co, window, macro, N_("Macro"))
501 R_CHECK_RADIO (c, co, window, zoom, N_("Zoom"))
502 R_CHECK_RADIO (c, co, window, flash, N_("Flash"))
503 R_CHECK_RADIO (c, co, window, rec_mode, N_("Record Mode"))
504 R_CHECK_RADIO (c, co, window, compression, N_("Compression"))
513 { 2400, RICOH_SPEED_2400},
514 {115200, RICOH_SPEED_115200},
515 { 4800, RICOH_SPEED_4800},
516 { 19200, RICOH_SPEED_19200},
517 { 38400, RICOH_SPEED_38400},
518 { 57600, RICOH_SPEED_57600},
522 static CameraFilesystemFuncs fsfuncs = {
523 .file_list_func = file_list_func,
524 .get_file_func = get_file_func,
525 .del_file_func = del_file_func,
526 .put_file_func = put_file_func,
527 .get_info_func = get_info_func
531 camera_init (Camera *camera, GPContext *context)
533 GPPortSettings settings;
534 unsigned int speed, i;
536 RicohModel model = 0;
538 /* Try to contact the camera. */
539 CR (gp_port_set_timeout (camera->port, 5000));
540 CR (gp_port_get_settings (camera->port, &settings));
541 speed = (settings.serial.speed ? settings.serial.speed : 115200);
542 for (i = 0; speeds[i].speed; i++) {
543 GP_DEBUG ("Trying speed %i...", speeds[i].speed);
544 settings.serial.speed = speeds[i].speed;
545 CR (gp_port_set_settings (camera->port, settings));
548 * Note that ricoh_connect can only be called to
549 * initialize the connection at 2400 bps. At other
550 * speeds, a different function needs to be used.
552 result = (speeds[i].rspeed == RICOH_SPEED_2400) ?
553 ricoh_connect (camera, NULL, &model) :
554 ricoh_get_mode (camera, NULL, NULL);
559 /* Contact made? If not, report error. */
560 if (!speeds[i].speed) {
561 gp_context_error (context, _("Could not contact camera."));
565 /* Contact made. Do we need to change the speed? */
566 if (settings.serial.speed != speed) {
567 for (i = 0; speeds[i].speed; i++)
568 if (speeds[i].speed == speed)
570 if (!speeds[i].speed) {
571 gp_context_error (context, _("Speed %i is not "
572 "supported!"), speed);
575 CR (ricoh_set_speed (camera, context, speeds[i].rspeed));
576 settings.serial.speed = speed;
577 CR (gp_port_set_settings (camera->port, settings));
579 /* Check if the camera is still there. */
580 CR (ricoh_get_mode (camera, context, NULL));
583 /* setup the function calls */
584 camera->functions->exit = camera_exit;
585 camera->functions->summary = camera_summary;
586 camera->functions->capture = camera_capture;
587 camera->functions->about = camera_about;
588 camera->functions->get_config = camera_get_config;
589 camera->functions->set_config = camera_set_config;
590 CR (gp_filesystem_set_funcs (camera->fs, &fsfuncs, camera));
592 * Remember the model. It could be that there hasn't been the
593 * need to call ricoh_connect. Then we don't have a model. Should
594 * we disconnect and reconnect in this case?
596 camera->pl = malloc (sizeof (CameraPrivateLibrary));
598 return (GP_ERROR_NO_MEMORY);
599 memset (camera->pl, 0, sizeof (CameraPrivateLibrary));
600 camera->pl->model = model;