diff --git a/camlibs/canon/ChangeLog b/camlibs/canon/ChangeLog index 783ab007a..73f16a665 100644 --- a/camlibs/canon/ChangeLog +++ b/camlibs/canon/ChangeLog @@ -1,3 +1,8 @@ +2008-05-12 Moreno Marzolla + + * canon.c, canon.h, README.canon: Added some more configuration + options. + 2008-03-30 Marcus Meissner * canon.c: SL_THUMB_CR2 should be as large as the CR2 image, diff --git a/camlibs/canon/README.canon b/camlibs/canon/README.canon index 5d8ae0bb7..6d85ca551 100644 --- a/camlibs/canon/README.canon +++ b/camlibs/canon/README.canon @@ -150,6 +150,48 @@ the programs offered on the website mentioned above for conversion from CRW to something else. +======================================================================== +Remote capture on Canon Powershot A40 +===================================== + +The Canon Powershot A40 supports remote capture with gphoto. However, +not all camera configuration parameters can be set via gphoto. Here +we summarize the current status: + +- shutterspeed: can _NOT_ be set; This parameter can not be remotely set, + most likely due to a camera limitation rather than a gphoto issue. In fact + even Canon RemoteCapture version 2.7.4.23 for MacOSX does not allow + setting this parameter. + +- aperture: can NOT be set; even Canon RemoteCapture for MacOSX does not + allow setting this. + +- ISO: WORKS. Setting the ISO to one of the supported camera values works + with gphoto. + +- Resolution: WORKS. + +- flashmode: WORKS. gphoto2 is able to denable/disable the flash, or set + it to automatic. + +- beep: WORKS. gphoto2 is able to enable/disable the audible beep which + is emitted by the camera after fucosing the scene. + +- zoom: WORKS. gphoto2 can remotely set the zoom. The range of zoom values + needs to be checked; at the moment the range 1 (no zoom at all) to 9 + has been observed to work, but it is unclear whether higher values + work as well. + +- macro mode: can _NOT_ be set. Apparently, RemoteCapture 2.7.4.23 is able + to enable macro mode; however, macro mode should be automatically enabled + by the camera when necessary (need to be checked) + +- exposure compensation: can _NOT_ be set. Apparently, RemoteCapture + 2.7.4.23 is able to set the exposure compensation, while gphoto2 is + not. Supporting this would probably require additional reverse engineering + work on the Canon protocol to understand the commands to issue. + + ======================================================================== Known Bugs ========== diff --git a/camlibs/canon/canon.c b/camlibs/canon/canon.c index fceccaa2e..a7f12ce4f 100644 --- a/camlibs/canon/canon.c +++ b/camlibs/canon/canon.c @@ -1783,6 +1783,13 @@ canon_int_get_release_params (Camera *camera, GPContext *context) GP_DEBUG ("canon_int_get_release_params: focus mode = 0x%02x", camera->pl->release_params[FOCUS_MODE_INDEX]); + GP_DEBUG ("canon_int_get_release_params: beep mode = 0x%02x", + camera->pl->release_params[BEEP_INDEX]); + + GP_DEBUG ("canon_int_get_release_params: flash mode = 0x%02x", + camera->pl->release_params[FLASH_INDEX]); + + camera->pl->secondary_image = 0; /* Based on the resolution settings in the release params, determine whether we expect one or two images to be returned @@ -1866,6 +1873,161 @@ canon_int_set_shutter_speed (Camera *camera, canonShutterSpeedState shutter_spee } +/** + * canon_int_set_beep + * @camera: camera to work with + * @beep_mode: beep mode - use one of the defines such as + * BEEP_ON for turning on the beep when the camera sets the focus. + * @context: context for error reporting + * + * Sets the camera's beep mode. Only tested for A40 via USB. + * + * Returns: gphoto2 error code + * + */ +int +canon_int_set_beep (Camera *camera, canonBeepMode beep_mode, + GPContext *context) +{ + int status; + + GP_DEBUG ("canon_int_set_beep() called for beep 0x%02x", + beep_mode); + + /* Get the current camera settings */ + + status = canon_int_get_release_params (camera, context); + + if (status < 0) + return status; + + /* Modify the beep mode */ + + /* XXX must test for valid shutter speeds here */ + camera->pl->release_params[BEEP_INDEX] = beep_mode; + + /* Upload the beep mode to the camera */ + status = canon_int_set_release_params (camera, context); + + if (status < 0) + return status; + + /* Make sure the camera changed it! */ + + status = canon_int_get_release_params (camera, context); + + if (status < 0) + return status; + + if (camera->pl->release_params[BEEP_INDEX] != beep_mode) { + GP_DEBUG ("canon_int_set_beep: Could not set beep " + "mode to 0x%02x (camera returned 0x%02x)", + beep_mode, + camera->pl->release_params[BEEP_INDEX]); + return GP_ERROR_NOT_SUPPORTED; + } else { + GP_DEBUG ("canon_int_set_beep: beep mode change verified"); + } + + GP_DEBUG ("canon_int_set_beep() finished successfully"); + + return GP_OK; +} + +/** + * canon_int_set_flash + * @camera: camera to work with + * @flash_mode: flash mode - use one of the defines such as + * FLASH_MODE_OFF for turning off the flash. + * @context: context for error reporting + * + * Sets the camera's flash mode. Only tested for A40 via USB. + * + * Returns: gphoto2 error code + * + */ +int +canon_int_set_flash (Camera *camera, canonFlashMode flash_mode, + GPContext *context) +{ + int status; + + GP_DEBUG ("canon_int_set_flash() called for flash 0x%02x", + flash_mode); + + /* Get the current camera settings */ + + status = canon_int_get_release_params (camera, context); + + if (status < 0) + return status; + + /* Modify the beep mode */ + + /* XXX must test for valid flash mode here */ + camera->pl->release_params[FLASH_INDEX] = flash_mode; + + /* Upload the flash mode to the camera */ + status = canon_int_set_release_params (camera, context); + + if (status < 0) + return status; + + /* Make sure the camera changed it! */ + + status = canon_int_get_release_params (camera, context); + + if (status < 0) + return status; + + if (camera->pl->release_params[FLASH_INDEX] != flash_mode) { + GP_DEBUG ("canon_int_set_flash: Could not set flash " + "mode to 0x%02x (camera returned 0x%02x)", + flash_mode, + camera->pl->release_params[FLASH_INDEX]); + return GP_ERROR_NOT_SUPPORTED; + } else { + GP_DEBUG ("canon_int_set_flash: flash mode change verified"); + } + + GP_DEBUG ("canon_int_set_flash() finished successfully"); + + return GP_OK; +} + + +/** + * canon_int_set_zoom + * @camera: camera to work with + * @zoom_level: zoom level to set - use one of the defines such as + * ZOOM_0 for no zoom + * @context: context for error reporting + * + * Sets the camera's zoom. Only tested for A40 via USB. + * + * Returns: gphoto2 error code + * + */ +int +canon_int_set_zoom (Camera *camera, canonZoomLevel zoom_level, + GPContext *context) +{ + int status; + + GP_DEBUG ("canon_int_set_zoom() called for zoom 0x%02x", + zoom_level); + + status = canon_int_do_control_command( camera, CANON_USB_CONTROL_SET_ZOOM_POS, 0x04, zoom_level ); + + if (status < 0) + return status; + + GP_DEBUG ("canon_int_set_zoom() finished successfully"); + + return GP_OK; +} + + /** * canon_int_set_resolution * @camera: camera to work with diff --git a/camlibs/canon/canon.h b/camlibs/canon/canon.h index ef995e129..b8f2bf1b3 100644 --- a/camlibs/canon/canon.h +++ b/camlibs/canon/canon.h @@ -351,6 +351,60 @@ struct canonFocusModeStateStruct { char *label; }; +/** + * canonFlashMode: + * @FLASH_MODE_OFF: The flash does not fire + * @FLASH_MODE_ON: The flash does fire (compulsory) + * @FLASH_MODE_AUTO: The flash fires if necessary + */ +typedef enum { + FLASH_MODE_OFF = 0, + FLASH_MODE_ON, + FLASH_MODE_AUTO +} canonFlashMode; + +struct canonFlashModeStateStruct { + canonFlashMode value; + char* label; +}; + +/** + * canonBeepMode: + * @BEEP_OFF: The camera does not beep after focusing the image + * @BEEP_ON: The camera emits an audible beep after focusing the image + */ +typedef enum { + BEEP_OFF = 0x00, + BEEP_ON = 0x01 +} canonBeepMode; + +struct canonBeepModeStateStruct { + canonBeepMode value; + char* label; +}; + +/* + * Controls che camera zoom. These values have been verified for the + * A40 only. + */ +typedef enum { + ZOOM_0 = 0x01, /* minimum (no zoom) */ + ZOOM_1 = 0x02, + ZOOM_2 = 0x03, + ZOOM_3 = 0x04, + ZOOM_4 = 0x05, + ZOOM_5 = 0x06, + ZOOM_6 = 0x07, + ZOOM_7 = 0x08, + ZOOM_8 = 0x09, + ZOOM_9 = 0x0a /* maximum zoom ?? */ +} canonZoomLevel; + +struct canonZoomLevelStateStruct { + canonZoomLevel value; + char* label; +}; + /* Size of the release parameter block */ #define RELEASE_PARAMS_LEN 0x2f @@ -358,7 +412,10 @@ struct canonFocusModeStateStruct { #define RESOLUTION_1_INDEX 0x01 #define RESOLUTION_2_INDEX 0x02 #define RESOLUTION_3_INDEX 0x03 -#define BEEP_INDEX 0x07 +#define SELF_TIMER_1_INDEX 0x04 /* Currently not used */ +#define SELF_TIMER_2_INDEX 0x05 /* Currently not used */ +#define FLASH_INDEX 0x06 +#define BEEP_INDEX 0x07 #define FOCUS_MODE_INDEX 0x12 #define ISO_INDEX 0x1a #define APERTURE_INDEX 0x1c @@ -645,6 +702,9 @@ int canon_int_identify_camera(Camera *camera, GPContext *context); int canon_int_set_owner_name(Camera *camera, const char *name, GPContext *context); int canon_int_start_remote_control(Camera *camera, GPContext *context); int canon_int_end_remote_control(Camera *camera, GPContext *context); +int canon_int_set_beep(Camera *camera, canonBeepMode beep_mode, GPContext *context); +int canon_int_set_flash(Camera *camera, canonFlashMode flash_mode, GPContext *context); +int canon_int_set_zoom(Camera *camera, canonZoomLevel zoom_level, GPContext *context); /* * introduced for capturing diff --git a/camlibs/canon/library.c b/camlibs/canon/library.c index 58d4d05ac..8a339c246 100644 --- a/camlibs/canon/library.c +++ b/camlibs/canon/library.c @@ -214,6 +214,33 @@ static const struct canonFocusModeStateStruct focusModeStateArray[] = { {0, NULL}, }; +static const struct canonBeepModeStateStruct beepModeStateArray[] = { + {BEEP_OFF, N_("Beep off")}, + {BEEP_ON, N_("Beep on")}, + {0, NULL}, +}; + +static const struct canonFlashModeStateStruct flashModeStateArray[] = { + {FLASH_MODE_OFF, N_("Flash off")}, + {FLASH_MODE_ON, N_("Flash on")}, + {FLASH_MODE_AUTO, N_("Flash auto")}, + {0, NULL}, +}; + +static const struct canonZoomLevelStateStruct zoomLevelStateArray[] = { + {ZOOM_0, N_("No zoom")}, + {ZOOM_1, N_("Zoom 1")}, + {ZOOM_2, N_("Zoom 2")}, + {ZOOM_3, N_("Zoom 3")}, + {ZOOM_4, N_("Zoom 4")}, + {ZOOM_5, N_("Zoom 5")}, + {ZOOM_6, N_("Zoom 6")}, + {ZOOM_7, N_("Zoom 7")}, + {ZOOM_8, N_("Zoom 8")}, + {ZOOM_9, N_("Zoom 9")}, + {0, NULL}, +}; + static const struct canonResolutionStateStruct resolutionStateArray[] = { {RESOLUTION_RAW, N_("RAW"), 0x04, 0x02, 0x00}, @@ -1469,7 +1496,7 @@ camera_get_config (Camera *camera, CameraWidget **window, GPContext *context) CameraWidget *t, *section; char power_str[128], firm[64]; - int iso, shutter_speed, aperture, focus_mode; + int iso, shutter_speed, aperture, focus_mode, flash_mode, beep_mode; int res_byte1, res_byte2, res_byte3; int pwr_status, pwr_source, res, i, menuval; time_t camtime; @@ -1596,6 +1623,27 @@ camera_get_config (Camera *camera, CameraWidget **window, GPContext *context) gp_widget_append (section, t); + + /* Zoom level */ + gp_widget_new (GP_WIDGET_MENU, _("Zoom"), &t); + gp_widget_set_name (t, "zoom"); + + i = 0; + while (zoomLevelStateArray[i].label) { + gp_widget_add_choice (t, _(zoomLevelStateArray[i].label)); + i++; + } + + + /* Set an unknown zoom level (at the moment we don't read the + * zoom level */ + gp_widget_add_choice (t, _("Unknown")); + gp_widget_set_value (t, _("Unknown")); + + gp_widget_append (section, t); + + + /* Aperture */ gp_widget_new (GP_WIDGET_MENU, _("Aperture"), &t); gp_widget_set_name (t, "aperture"); @@ -1702,6 +1750,75 @@ camera_get_config (Camera *camera, CameraWidget **window, GPContext *context) gp_widget_append (section, t); + + /* Flash mode */ + gp_widget_new (GP_WIDGET_MENU, _("Flash mode"), &t); + gp_widget_set_name (t, "flashmode"); + + /* Get the camera's current flash mode setting */ + flash_mode = -1; + if (camera->pl->cached_ready == 1) { + res = canon_int_get_release_params(camera, context); + if (res == GP_OK) + flash_mode = camera->pl->release_params[FLASH_INDEX]; + } + + /* Map it to the list of choices */ + i = 0; + menuval = -1; + while (flashModeStateArray[i].label) { + gp_widget_add_choice (t, _(flashModeStateArray[i].label)); + if (flash_mode == (int)flashModeStateArray[i].value) { + gp_widget_set_value (t, _(flashModeStateArray[i].label)); + menuval = i; + } + i++; + } + + /* Set an unknown shutter value if the + * camera is set to something weird */ + if (menuval == -1) { + gp_widget_add_choice (t, _("Unknown")); + gp_widget_set_value (t, _("Unknown")); + }; + + gp_widget_append (section, t); + + + /* Beep */ + gp_widget_new (GP_WIDGET_MENU, _("Beep"), &t); + gp_widget_set_name (t, "beep"); + + /* Get the camera's current beep setting */ + beep_mode = -1; + if (camera->pl->cached_ready == 1) { + res = canon_int_get_release_params(camera, context); + if (res == GP_OK) + beep_mode = camera->pl->release_params[FLASH_INDEX]; + } + + /* Map it to the list of choices */ + i = 0; + menuval = -1; + while (beepModeStateArray[i].label) { + gp_widget_add_choice (t, _(beepModeStateArray[i].label)); + if (beep_mode == (int)beepModeStateArray[i].value) { + gp_widget_set_value (t, _(beepModeStateArray[i].label)); + menuval = i; + } + i++; + } + + /* Set an unknown shutter value if the + * camera is set to something weird */ + if (menuval == -1) { + gp_widget_add_choice (t, _("Unknown")); + gp_widget_set_value (t, _("Unknown")); + }; + + gp_widget_append (section, t); + + /************************ end release params ************************/ gp_widget_new (GP_WIDGET_TEXT, _("Date and Time (readonly)"), &t);