Files
libgphoto2/camlibs/ricoh/library.c
2003-01-10 21:37:23 +00:00

604 lines
16 KiB
C

/* library.c
*
* Copyright © 2002 Lutz Müller <lutz@users.sourceforge.net>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <gphoto2-library.h>
#include <gphoto2-port-log.h>
#include "ricoh.h"
#define GP_MODULE "ricoh"
#ifdef ENABLE_NLS
# include <libintl.h>
# undef _
# define _(String) dgettext (GETTEXT_PACKAGE, String)
# ifdef gettext_noop
# define N_(String) gettext_noop (String)
# else
# define N_(String) (String)
# endif
#else
# define textdomain(String) (String)
# define gettext(String) (String)
# define dgettext(Domain,Message) (Message)
# define dcgettext(Domain,Message,Type) (Message)
# define bindtextdomain(Domain,Directory) (Domain)
# define _(String) (String)
# define N_(String) (String)
#endif
#define CR(result) {int r=(result); if (r<0) return r;}
static struct {
RicohModel id;
const char *model;
} models[] = {
{RICOH_MODEL_1, "Ricoh:RDC-1"},
{RICOH_MODEL_2, "Ricoh:RDC-2"},
{RICOH_MODEL_2E, "Ricoh:RDC-2E"},
{RICOH_MODEL_100G, "Ricoh:RDC-100G"},
{RICOH_MODEL_300, "Ricoh:RDC-300"},
{RICOH_MODEL_300Z, "Ricoh:RDC-300Z"},
{RICOH_MODEL_4200, "Ricoh:RDC-4200"},
{RICOH_MODEL_4300, "Ricoh:RDC-4300"},
{RICOH_MODEL_5000, "Ricoh:RDC-5000"},
{RICOH_MODEL_ESP2, "Philips:ESP2"},
{RICOH_MODEL_ESP50, "Philips:ESP50"},
{RICOH_MODEL_ESP60, "Philips:ESP60"},
{RICOH_MODEL_ESP70, "Philips:ESP70"},
{RICOH_MODEL_ESP80, "Philips:ESP80"},
{RICOH_MODEL_ESP80SXG, "Philips:ESP80SXG"},
{0, NULL}
};
struct _CameraPrivateLibrary {
RicohModel model;
};
int
camera_abilities (CameraAbilitiesList *list)
{
int i;
CameraAbilities a;
memset (&a, 0, sizeof (CameraAbilities));
for (i = 0; models[i].model; i++) {
strcpy (a.model, models[i].model);
a.status = GP_DRIVER_STATUS_EXPERIMENTAL;
a.port = GP_PORT_SERIAL;
a.operations = GP_OPERATION_CAPTURE_IMAGE |
GP_OPERATION_CONFIG;
a.file_operations = GP_FILE_OPERATION_DELETE |
GP_FILE_OPERATION_PREVIEW;
a.folder_operations = GP_FOLDER_OPERATION_PUT_FILE;
CR (gp_abilities_list_append (list, a));
}
return (GP_OK);
}
static int
camera_exit (Camera *camera, GPContext *context)
{
if (camera->pl) {
free (camera->pl);
camera->pl = NULL;
}
ricoh_disconnect (camera, context);
return GP_OK;
}
static int
file_list_func (CameraFilesystem *fs, const char *folder, CameraList *list,
void *data, GPContext *context)
{
Camera *camera = data;
unsigned int n, i;
const char *name;
CR (ricoh_get_num (camera, context, &n));
for (i = 0; i < n; i++) {
CR (ricoh_get_pic_name (camera, context, i + 1, &name));
CR (gp_list_append (list, name, NULL));
}
return (GP_OK);
}
static int
get_info_func (CameraFilesystem *fs, const char *folder, const char *filename,
CameraFileInfo *info, void *data, GPContext *context)
{
Camera *camera = data;
int n;
const char *name;
CR (n = gp_filesystem_number (fs, folder, filename, context));
n++;
info->audio.fields = GP_FILE_INFO_NONE; /* no info anbout audio files */
info->preview.width = 80;
info->preview.height = 60;
info->preview.fields = GP_FILE_INFO_WIDTH | GP_FILE_INFO_HEIGHT;
CR (ricoh_get_pic_name (camera, context, n, &name));
strcpy (info->file.name, name);
CR (ricoh_get_pic_date (camera, context, n, &info->file.mtime));
CR (ricoh_get_pic_size (camera, context, n, &info->file.size));
strcpy (info->file.type, GP_MIME_EXIF);
info->file.fields = GP_FILE_INFO_NAME | GP_FILE_INFO_SIZE | GP_FILE_INFO_MTIME
| GP_FILE_INFO_TYPE;
return (GP_OK);
}
static int
get_file_func (CameraFilesystem *fs, const char *folder, const char *filename,
CameraFileType type, CameraFile *file, void *user_data,
GPContext *context)
{
Camera *camera = user_data;
int n;
unsigned int size;
unsigned char *data;
CR (n = gp_filesystem_number (fs, folder, filename, context));
n++;
switch (type) {
case GP_FILE_TYPE_NORMAL:
CR (ricoh_get_pic (camera, context, n,
RICOH_FILE_TYPE_NORMAL, &data, &size));
gp_file_set_mime_type (file, GP_MIME_EXIF);
break;
case GP_FILE_TYPE_PREVIEW:
CR (ricoh_get_pic (camera, context, n,
RICOH_FILE_TYPE_PREVIEW, &data, &size));
gp_file_set_mime_type (file, GP_MIME_TIFF);
break;
default:
return (GP_ERROR_NOT_SUPPORTED);
}
gp_file_set_data_and_size (file, data, size);
return (GP_OK);
}
static int
del_file_func (CameraFilesystem *fs, const char *folder, const char *filename,
void *user_data, GPContext *context)
{
Camera *camera = user_data;
int n;
CR (n = gp_filesystem_number (fs, folder, filename, context));
n++;
CR (ricoh_del_pic (camera, context, n));
return (GP_OK);
}
static int
camera_about (Camera *camera, CameraText *about, GPContext *context)
{
GP_DEBUG ("camera_about()");
strcpy (about->text,
_("Ricoh / Philips driver by\n"
"Lutz Mueller <lutz@users.sourceforge.net>,\n"
"Martin Fischer <martin.fischer@inka.de>,\n"
"based on Bob Paauwe's driver\n" )
);
return GP_OK;
}
int
camera_id (CameraText *id)
{
strcpy (id->text, "Ricoh");
return (GP_OK);
}
static int
camera_summary (Camera *camera, CameraText *about, GPContext *context)
{
int avail_mem, total_mem;
char model[128];
unsigned int i;
CR (ricoh_get_cam_amem (camera, context, &avail_mem));
CR (ricoh_get_cam_mem (camera, context, &total_mem));
memset (model, 0, sizeof (model));
for (i = 0; models[i].model; i++)
if (models[i].id == camera->pl->model)
break;
if (models[i].model)
strncpy (model, models[i].model, sizeof (model) - 1);
else
snprintf (model, sizeof (model) - 1, _("unknown (0x%02x)"),
camera->pl->model);
sprintf (about->text, _("Model: %s\n"
"Memory: %d byte(s) of %d available"),
model, avail_mem, total_mem);
return (GP_OK);
}
static int
camera_capture (Camera *camera, CameraCaptureType type,
CameraFilePath *path, GPContext *context)
{
unsigned int n;
if (type != GP_CAPTURE_IMAGE)
return (GP_ERROR_NOT_SUPPORTED);
CR (ricoh_get_num (camera, context, &n));
CR (ricoh_take_pic (camera, context));
sprintf (path->name, "rdc%04i.jpg", n + 1);
strcpy (path->folder, "/");
CR (gp_filesystem_append (camera->fs, path->folder,
path->name, context));
return (GP_OK);
}
static int
put_file_func (CameraFilesystem *fs, const char *folder, CameraFile *file,
void *user_data, GPContext *context)
{
const char *data, *name;
unsigned long int size;
Camera *camera = user_data;
CR (gp_file_get_data_and_size (file, &data, &size));
CR (gp_file_get_name (file, &name));
CR (ricoh_put_file (camera, context, name, data, size));
return (GP_OK);
}
#undef N_ELEMENTS
#define N_ELEMENTS(v) (sizeof(v)/sizeof(v[0]))
static struct {
RicohExposure exposure;
const char *name;
} ricoh_exposures[] = {
{RICOH_EXPOSURE_M20, N_("-2.0")},
{RICOH_EXPOSURE_M15, N_("-1.5")},
{RICOH_EXPOSURE_M10, N_("-1.0")},
{RICOH_EXPOSURE_M05, N_("-0.5")},
{RICOH_EXPOSURE_00, N_("0.0")},
{RICOH_EXPOSURE_05, N_("0.5")},
{RICOH_EXPOSURE_10, N_("1.0")},
{RICOH_EXPOSURE_15, N_("1.5")},
{RICOH_EXPOSURE_20, N_("2.0")},
{RICOH_EXPOSURE_AUTO, N_("Auto")}
};
static struct {
RicohResolution resolution;
const char *name;
} ricoh_resolutions[] = {
{RICOH_RESOLUTION_640_480, N_("640 x 480")},
{RICOH_RESOLUTION_1280_960, N_("1280 x 960")}
};
static struct {
RicohWhiteLevel white_level;
const char *name;
} ricoh_white_levels[] = {
{RICOH_WHITE_LEVEL_AUTO, N_("Auto")},
{RICOH_WHITE_LEVEL_OUTDOOR, N_("Outdoor")},
{RICOH_WHITE_LEVEL_FLUORESCENT, N_("Fluorescent")},
{RICOH_WHITE_LEVEL_INCANDESCENT, N_("Incandescent")},
{RICOH_WHITE_LEVEL_BLACK_WHITE, N_("Black & White")},
{RICOH_WHITE_LEVEL_SEPIA, N_("Sepia")}
};
static struct {
RicohMacro macro;
const char *name;
} ricoh_macros[] = {
{RICOH_MACRO_ON, N_("On")},
{RICOH_MACRO_OFF, N_("Off")}
};
static struct {
RicohCompression compression;
const char *name;
} ricoh_compressions[] = {
{RICOH_COMPRESSION_NONE, N_("None")},
{RICOH_COMPRESSION_MAX, N_("Maximal")},
{RICOH_COMPRESSION_NORM, N_("Normal")},
{RICOH_COMPRESSION_MIN, N_("Minimal")}
};
static struct {
RicohRecMode rec_mode;
const char *name;
} ricoh_rec_modes[] = {
{RICOH_REC_MODE_IMAGE, N_("Image")},
{RICOH_REC_MODE_CHARACTER, N_("Character")},
{RICOH_REC_MODE_SOUND, N_("Sound")},
{RICOH_REC_MODE_IMAGE_SOUND, N_("Image & Sound")},
{RICOH_REC_MODE_CHARACTER_SOUND, N_("Character & Sound")}
};
static struct {
RicohFlash flash;
const char *name;
} ricoh_flashs[] = {
{RICOH_FLASH_AUTO, N_("Auto")},
{RICOH_FLASH_OFF, N_("Off")},
{RICOH_FLASH_ON, N_("On")}
};
static struct {
RicohZoom zoom;
const char *name;
} ricoh_zooms[] = {
{RICOH_ZOOM_OFF, N_("Off")},
{RICOH_ZOOM_1, N_("2x")},
{RICOH_ZOOM_2, N_("3x")},
{RICOH_ZOOM_3, N_("4x")},
{RICOH_ZOOM_4, N_("5x")},
{RICOH_ZOOM_5, N_("6x")},
{RICOH_ZOOM_6, N_("7x")},
{RICOH_ZOOM_7, N_("8x")},
{RICOH_ZOOM_8, N_("9x")}
};
#undef R_ADD_RADIO
#define R_ADD_RADIO(ca,co,s,type,n,Name) \
{ \
CameraWidget *w = NULL; \
type v; \
unsigned int i; \
\
CR (gp_widget_new (GP_WIDGET_RADIO, _(Name), &w)); \
CR (gp_widget_set_name (w, (Name))); \
CR (gp_widget_append ((s), w)); \
CR (ricoh_get_##n ((ca), (co), &v)); \
for (i = 0; i < N_ELEMENTS (ricoh_##n##s); i++) { \
CR (gp_widget_add_choice (w, _(ricoh_##n##s[i].name))); \
if (v == ricoh_##n##s[i].n) \
CR (gp_widget_set_value (w, \
_(ricoh_##n##s[i].name))); \
} \
}
#undef R_CHECK_RADIO
#define R_CHECK_RADIO(c,co,wi,n,Name) \
{ \
CameraWidget *w = NULL; \
const char *v = NULL; \
unsigned int i; \
\
CR (gp_widget_get_child_by_name (wi, Name, &w)); \
if (gp_widget_changed (w)) { \
CR (gp_widget_get_value (w, &v)); \
for (i = 0; i < N_ELEMENTS (ricoh_##n##s); i++) \
if (!strcmp (v, _(ricoh_##n##s[i].name))) \
break; \
CR (ricoh_set_##n (c, co, ricoh_##n##s[i].n)); \
} \
}
static int
camera_get_config (Camera *c, CameraWidget **window, GPContext *co)
{
CameraWidget *s, *w;
const char *copyright;
time_t time;
CR (gp_widget_new (GP_WIDGET_WINDOW, _("Configuration"), window));
/* General settings */
CR (gp_widget_new (GP_WIDGET_SECTION, _("General"), &s));
CR (gp_widget_append (*window, s));
/* Copyright */
CR (gp_widget_new (GP_WIDGET_TEXT, _("Copyright"), &w));
CR (gp_widget_set_name (w, "copyright"));
CR (gp_widget_set_info (w, _("Copyright (max. 20 characters)")));
CR (gp_widget_append (s, w));
CR (ricoh_get_copyright (c, co, &copyright));
CR (gp_widget_set_value (w, (void *) copyright));
/* Date */
CR (gp_widget_new (GP_WIDGET_DATE, _("Date & Time"), &w));
CR (gp_widget_set_name (w, "date"));
CR (gp_widget_set_info (w, _("Date & Time")));
CR (gp_widget_append (s, w));
CR (ricoh_get_date (c, co, &time));
CR (gp_widget_set_value (w, &time));
/* Picture related settings */
CR (gp_widget_new (GP_WIDGET_SECTION, _("Pictures"), &s));
CR (gp_widget_append (*window, s));
R_ADD_RADIO (c, co, s, RicohResolution, resolution, "Resolution")
R_ADD_RADIO (c, co, s, RicohExposure, exposure, "Exposure")
R_ADD_RADIO (c, co, s, RicohMacro, macro, "Macro")
R_ADD_RADIO (c, co, s, RicohFlash, flash, "Flash")
R_ADD_RADIO (c, co, s, RicohZoom, zoom, "Zoom")
R_ADD_RADIO (c, co, s, RicohCompression, compression, "Compression")
R_ADD_RADIO (c, co, s, RicohWhiteLevel, white_level, "White Level")
R_ADD_RADIO (c, co, s, RicohRecMode, rec_mode, "Record Mode")
return (GP_OK);
}
static int
camera_set_config (Camera *c, CameraWidget *window, GPContext *co)
{
CameraWidget *w;
const char *v_char;
time_t time;
RicohMode mode;
/* We need to be in record mode to set settings. */
CR (ricoh_get_mode (c, co, &mode));
if (mode != RICOH_MODE_RECORD)
CR (ricoh_set_mode (c, co, RICOH_MODE_RECORD));
/* Copyright */
CR (gp_widget_get_child_by_name (window, "copyright", &w));
if (gp_widget_changed (w)) {
CR (gp_widget_get_value (w, &v_char));
CR (ricoh_set_copyright (c, co, v_char));
}
/* Date */
CR (gp_widget_get_child_by_name (window, "date", &w));
if (gp_widget_changed (w)) {
CR (gp_widget_get_value (w, &time));
CR (ricoh_set_date (c, co, time));
}
R_CHECK_RADIO (c, co, window, resolution, N_("Resolution"))
R_CHECK_RADIO (c, co, window, exposure, N_("Exposure"))
R_CHECK_RADIO (c, co, window, white_level, N_("White level"))
R_CHECK_RADIO (c, co, window, macro, N_("Macro"))
R_CHECK_RADIO (c, co, window, zoom, N_("Zoom"))
R_CHECK_RADIO (c, co, window, flash, N_("Flash"))
R_CHECK_RADIO (c, co, window, rec_mode, N_("Record Mode"))
R_CHECK_RADIO (c, co, window, compression, N_("Compression"))
return (GP_OK);
}
static struct {
unsigned int speed;
RicohSpeed rspeed;
} speeds[] = {
{ 2400, RICOH_SPEED_2400},
{115200, RICOH_SPEED_115200},
{ 4800, RICOH_SPEED_4800},
{ 19200, RICOH_SPEED_19200},
{ 38400, RICOH_SPEED_38400},
{ 57600, RICOH_SPEED_57600},
{ 0, 0}
};
int
camera_init (Camera *camera, GPContext *context)
{
GPPortSettings settings;
unsigned int speed, i;
int result;
RicohModel model = 0;
/* Try to contact the camera. */
CR (gp_port_set_timeout (camera->port, 5000));
CR (gp_port_get_settings (camera->port, &settings));
speed = (settings.serial.speed ? settings.serial.speed : 115200);
for (i = 0; speeds[i].speed; i++) {
GP_DEBUG ("Trying speed %i...", speeds[i].speed);
settings.serial.speed = speeds[i].speed;
CR (gp_port_set_settings (camera->port, settings));
/*
* Note that ricoh_connect can only be called to
* initialize the connection at 2400 bps. At other
* speeds, a different function needs to be used.
*/
result = (speeds[i].rspeed == RICOH_SPEED_2400) ?
ricoh_connect (camera, NULL, &model) :
ricoh_get_mode (camera, NULL, NULL);
if (result == GP_OK)
break;
}
/* Contact made? If not, report error. */
if (!speeds[i].speed) {
gp_context_error (context, _("Could not contact camera."));
return (GP_ERROR);
}
/* Contact made. Do we need to change the speed? */
if (settings.serial.speed != speed) {
for (i = 0; speeds[i].speed; i++)
if (speeds[i].speed == speed)
break;
if (!speeds[i].speed) {
gp_context_error (context, _("Speed %i is not "
"supported!"), speed);
return (GP_ERROR);
}
CR (ricoh_set_speed (camera, context, speeds[i].rspeed));
settings.serial.speed = speed;
CR (gp_port_set_settings (camera->port, settings));
/* Check if the camera is still there. */
CR (ricoh_get_mode (camera, context, NULL));
}
/* setup the function calls */
camera->functions->exit = camera_exit;
camera->functions->summary = camera_summary;
camera->functions->capture = camera_capture;
camera->functions->about = camera_about;
camera->functions->get_config = camera_get_config;
camera->functions->set_config = camera_set_config;
CR (gp_filesystem_set_list_funcs (camera->fs, file_list_func, NULL,
camera));
CR (gp_filesystem_set_file_funcs (camera->fs, get_file_func,
del_file_func, camera));
CR (gp_filesystem_set_info_funcs (camera->fs, get_info_func,
NULL, camera));
CR (gp_filesystem_set_folder_funcs (camera->fs, put_file_func,
NULL, NULL, NULL, camera));
/*
* Remember the model. It could be that there hasn't been the
* need to call ricoh_connect. Then we don't have a model. Should
* we disconnect and reconnect in this case?
*/
camera->pl = malloc (sizeof (CameraPrivateLibrary));
if (!camera->pl)
return (GP_ERROR_NO_MEMORY);
memset (camera->pl, 0, sizeof (CameraPrivateLibrary));
camera->pl->model = model;
return (GP_OK);
}