This is basically a continuation of the work from #1002 but her for the camlibs directory. The purpose was to replace spaces as a means for indentation with tab characters. Note: there are some files which are still offending the general rule but are (mostly) consistent within themselves. I let them be for the moment. Fixing them would basically replace the whole file. Also: there are still a ton of whitespace related inconsistencies like "x=10" vs "x = 10" or "func(10)" vs "func (10)". This is a whitespace only change (if you include newlines as whitespace).
362 lines
9.3 KiB
C
362 lines
9.3 KiB
C
/* library.c
|
|
*
|
|
* Copyright (C) 2003 Theodore Kilgore <kilgota@auburn.edu>
|
|
*
|
|
* 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., 51 Franklin Street, Fifth Floor,
|
|
* Boston, MA 02110-1301 USA
|
|
*/
|
|
|
|
#define _DEFAULT_SOURCE
|
|
|
|
#include <config.h>
|
|
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
#include <libgphoto2/bayer.h>
|
|
#include <libgphoto2/gamma.h>
|
|
|
|
#include <gphoto2/gphoto2.h>
|
|
|
|
#ifdef ENABLE_NLS
|
|
# include <libintl.h>
|
|
# undef _
|
|
# define _(String) dgettext (PACKAGE, String)
|
|
# ifdef gettext_noop
|
|
# define N_(String) gettext_noop (String)
|
|
# else
|
|
# define N_(String) (String)
|
|
# endif
|
|
#else
|
|
# define _(String) (String)
|
|
# define N_(String) (String)
|
|
#endif
|
|
|
|
#include "aox.h"
|
|
#include <gphoto2/gphoto2-port.h>
|
|
|
|
#define GP_MODULE "aox"
|
|
|
|
struct _CameraPrivateLibrary {
|
|
Model model;
|
|
Info info[2];
|
|
};
|
|
|
|
static struct {
|
|
char *name;
|
|
CameraDriverStatus status;
|
|
unsigned short idVendor;
|
|
unsigned short idProduct;
|
|
} models[] = {
|
|
{"Concord EyeQMini_1", GP_DRIVER_STATUS_EXPERIMENTAL, 0x03e8, 0x2182},
|
|
{"Concord EyeQMini_2", GP_DRIVER_STATUS_EXPERIMENTAL, 0x03e8, 0x2180},
|
|
{"D-MAX DM3588", GP_DRIVER_STATUS_EXPERIMENTAL, 0x03e8, 0x2130},
|
|
{NULL,0,0,0}
|
|
};
|
|
|
|
int
|
|
camera_id (CameraText *id)
|
|
{
|
|
strcpy (id->text, "Aox chipset camera");
|
|
return GP_OK;
|
|
}
|
|
|
|
int
|
|
camera_abilities (CameraAbilitiesList *list)
|
|
{
|
|
int i;
|
|
CameraAbilities a;
|
|
|
|
for (i = 0; models[i].name; i++) {
|
|
memset (&a, 0, sizeof(a));
|
|
strcpy (a.model, models[i].name);
|
|
a.status = models[i].status;
|
|
a.port = GP_PORT_USB;
|
|
a.speed[0] = 0;
|
|
a.usb_vendor = models[i].idVendor;
|
|
a.usb_product = models[i].idProduct;
|
|
if (a.status == GP_DRIVER_STATUS_EXPERIMENTAL)
|
|
a.operations = GP_OPERATION_NONE;
|
|
else
|
|
a.operations = GP_OPERATION_CAPTURE_IMAGE;
|
|
a.folder_operations = GP_FOLDER_OPERATION_NONE;
|
|
a.file_operations = GP_FILE_OPERATION_PREVIEW;
|
|
gp_abilities_list_append (list, a);
|
|
}
|
|
return GP_OK;
|
|
}
|
|
|
|
static int
|
|
camera_summary (Camera *camera, CameraText *summary, GPContext *context)
|
|
{
|
|
|
|
int num_lo_pics = aox_get_num_lo_pics(camera->pl->info);
|
|
int num_hi_pics = aox_get_num_hi_pics(camera->pl->info);
|
|
|
|
sprintf (summary->text, _("Your USB camera has an Aox chipset.\n"
|
|
"Number of lo-res PICs = %i\n"
|
|
"Number of hi-res PICs = %i\n"
|
|
"Number of PICs = %i\n"
|
|
), num_lo_pics, num_hi_pics, num_lo_pics + num_hi_pics);
|
|
|
|
return GP_OK;
|
|
}
|
|
|
|
|
|
static int
|
|
camera_about (Camera *camera, CameraText *about, GPContext *context)
|
|
{
|
|
strcpy (about->text, _("Aox generic driver\n"
|
|
"Theodore Kilgore <kilgota@auburn.edu>\n"));
|
|
return GP_OK;
|
|
}
|
|
|
|
/*************** File and Downloading Functions *******************/
|
|
|
|
static int
|
|
file_list_func (CameraFilesystem *fs, const char *folder, CameraList *list,
|
|
void *data, GPContext *context)
|
|
{
|
|
Camera *camera = data;
|
|
int num_lo_pics = aox_get_num_lo_pics (camera->pl->info);
|
|
int num_hi_pics = aox_get_num_hi_pics (camera->pl->info);
|
|
int n = num_hi_pics + num_lo_pics;
|
|
char name[30];
|
|
int i;
|
|
/* Low-resolution pictures are always downloaded first. We do not know
|
|
* yet how to process them, so they will remain in RAW format. */
|
|
|
|
for (i=0; i< num_lo_pics; i++){
|
|
snprintf( name, sizeof(name), "aox_pic%03i.raw", i+1 );
|
|
gp_list_append(list, name, NULL);
|
|
}
|
|
|
|
for (i = num_lo_pics; i < n; i++){
|
|
snprintf( name, sizeof(name), "aox_pic%03i.ppm", i+1 );
|
|
gp_list_append(list, name, NULL);
|
|
}
|
|
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;
|
|
|
|
/* The camera will always download the low-resolution pictures first, if any.
|
|
* As those are compressed, they are not of fixed size. Unfortunately, the
|
|
* compression method is not known.
|
|
* For a high-resolution picture, the size is always the same.
|
|
* Every picture file has a header, which is of length 0x98. The high-
|
|
* resolution pictures are just Bayer data; their headers will be discarded.
|
|
*/
|
|
|
|
int i, j, k, n, num_lo_pics, num_hi_pics, w = 0, h = 0;
|
|
unsigned char temp;
|
|
unsigned char *data;
|
|
unsigned char *p_data = NULL;
|
|
unsigned char *output = NULL;
|
|
int len;
|
|
int header_len;
|
|
char header[128];
|
|
unsigned char gtable[256];
|
|
|
|
k = gp_filesystem_number(camera->fs, "/", filename, context);
|
|
|
|
|
|
num_lo_pics = aox_get_num_lo_pics(camera->pl->info);
|
|
num_hi_pics = aox_get_num_hi_pics(camera->pl->info);
|
|
|
|
|
|
GP_DEBUG("There are %i compressed photos\n", num_lo_pics);
|
|
GP_DEBUG("There are %i hi-res photos\n", num_hi_pics);
|
|
|
|
if ( (k < num_lo_pics) ) {
|
|
n = k;
|
|
w = 320;
|
|
h = 240;
|
|
} else {
|
|
n = k - num_lo_pics;
|
|
w = 640;
|
|
h = 480;
|
|
}
|
|
|
|
len = aox_get_picture_size (camera->port, num_lo_pics,
|
|
num_hi_pics, n, k);
|
|
if (len < GP_OK) return len;
|
|
|
|
GP_DEBUG("len = %i\n", len);
|
|
data = malloc(len);
|
|
if (!data) {
|
|
printf("Malloc failed\n"); return 0;}
|
|
aox_read_picture_data (camera->port, (char *)data, len, n);
|
|
|
|
switch (type) {
|
|
case GP_FILE_TYPE_EXIF:
|
|
free (data);
|
|
return (GP_ERROR_FILE_EXISTS);
|
|
|
|
case GP_FILE_TYPE_PREVIEW:
|
|
case GP_FILE_TYPE_NORMAL:
|
|
if (w == 320) {
|
|
gp_file_detect_mime_type (file); /* Detected as "raw"*/
|
|
gp_file_set_data_and_size (file, (char *)data, len);
|
|
gp_file_adjust_name_for_mime_type (file);
|
|
break;
|
|
}
|
|
if (w == 640) {
|
|
|
|
if (len < 0x98 + w*h) {
|
|
GP_DEBUG("len %d is less than expected %d\n", len, 0x98+w*h);
|
|
return GP_ERROR;
|
|
}
|
|
|
|
/* Stripping useless header */
|
|
p_data = data + 0x98;
|
|
/* Picture is mirror-imaged.*/
|
|
for (i = 0; i < h; ++i) {
|
|
for (j = 0; j < w / 2; j++) {
|
|
temp = p_data[w * i + j];
|
|
p_data[w * i + j] = p_data[w * i + w - 1 - j];
|
|
p_data[w * i + w - 1 - j] = temp;
|
|
}
|
|
}
|
|
/* Not only this, but some columns are
|
|
* interchanged, too. */
|
|
for (i = 0; i < w*h/4; i++) {
|
|
temp = p_data[4 * i + 1];
|
|
p_data[4 * i + 1] = p_data[4 * i + 2];
|
|
p_data[4 * i + 2] = temp;
|
|
}
|
|
/* And now create a ppm file, with our own header */
|
|
header_len = snprintf(header, 127,
|
|
"P6\n"
|
|
"# CREATOR: gphoto2, aox library\n"
|
|
"%d %d\n"
|
|
"255\n", w, h);
|
|
|
|
output = malloc(3*w*h);
|
|
if(!output) {
|
|
free(output);
|
|
return GP_ERROR_NO_MEMORY;
|
|
}
|
|
if (camera->pl->model == AOX_MODEL_DMAX)
|
|
gp_bayer_decode (p_data, w, h, output, BAYER_TILE_RGGB);
|
|
else
|
|
gp_bayer_decode (p_data, w, h, output, BAYER_TILE_GRBG);
|
|
/* gamma correction of .70 may not be optimal. */
|
|
gp_gamma_fill_table (gtable, .65);
|
|
gp_gamma_correct_single (gtable, output, w * h);
|
|
gp_file_set_mime_type (file, GP_MIME_PPM);
|
|
gp_file_append (file, header, header_len);
|
|
gp_file_append (file, (char *)output, 3*w*h);
|
|
}
|
|
free (data);
|
|
free (output);
|
|
return GP_OK;
|
|
case GP_FILE_TYPE_RAW:
|
|
gp_file_set_data_and_size (file, (char *)data, len);
|
|
gp_file_set_mime_type (file, GP_MIME_RAW);
|
|
gp_file_adjust_name_for_mime_type(file);
|
|
break;
|
|
default:
|
|
free (data);
|
|
return (GP_ERROR_NOT_SUPPORTED);
|
|
}
|
|
return GP_OK;
|
|
}
|
|
|
|
/*************** Exit and Initialization Functions ******************/
|
|
|
|
static int
|
|
camera_exit (Camera *camera, GPContext *context)
|
|
{
|
|
GP_DEBUG ("Aox camera_exit");
|
|
|
|
free (camera->pl);
|
|
camera->pl = NULL;
|
|
|
|
return GP_OK;
|
|
}
|
|
|
|
static CameraFilesystemFuncs fsfuncs = {
|
|
.file_list_func = file_list_func,
|
|
.get_file_func = get_file_func
|
|
};
|
|
|
|
int
|
|
camera_init(Camera *camera, GPContext *context)
|
|
{
|
|
GPPortSettings settings;
|
|
CameraAbilities abilities;
|
|
int ret = 0;
|
|
|
|
/* First, set up all the function pointers */
|
|
camera->functions->summary = camera_summary;
|
|
camera->functions->about = camera_about;
|
|
camera->functions->exit = camera_exit;
|
|
|
|
GP_DEBUG ("Initializing the camera\n");
|
|
ret = gp_port_get_settings(camera->port,&settings);
|
|
if (ret < 0) return ret;
|
|
|
|
ret = gp_camera_get_abilities(camera, &abilities);
|
|
if (ret < 0) return ret;
|
|
GP_DEBUG("product number is 0x%x\n", abilities.usb_product);
|
|
|
|
switch (camera->port->type) {
|
|
case GP_PORT_SERIAL:
|
|
return ( GP_ERROR );
|
|
case GP_PORT_USB:
|
|
settings.usb.config = 1;
|
|
settings.usb.altsetting = 0;
|
|
settings.usb.interface = 1;
|
|
settings.usb.inep = 0x84;
|
|
settings.usb.outep =0x05;
|
|
break;
|
|
default:
|
|
return ( GP_ERROR );
|
|
}
|
|
|
|
ret = gp_port_set_settings(camera->port,settings);
|
|
if (ret < 0) return ret;
|
|
|
|
GP_DEBUG("interface = %i\n", settings.usb.interface);
|
|
GP_DEBUG("inep = %x\n", settings.usb.inep);
|
|
GP_DEBUG("outep = %x\n", settings.usb.outep);
|
|
|
|
/* Tell the CameraFilesystem where to get lists from */
|
|
gp_filesystem_set_funcs (camera->fs, &fsfuncs, camera);
|
|
|
|
camera->pl = malloc (sizeof (CameraPrivateLibrary));
|
|
if (!camera->pl) return GP_ERROR_NO_MEMORY;
|
|
memset (camera->pl, 0, sizeof (CameraPrivateLibrary));
|
|
|
|
switch(abilities.usb_product) {
|
|
case 0x2130:
|
|
camera->pl->model = AOX_MODEL_DMAX;
|
|
break;
|
|
default:
|
|
camera->pl->model = AOX_MODEL_MINI;
|
|
}
|
|
/* Connect to the camera */
|
|
aox_init (camera->port, &camera->pl->model, camera->pl->info);
|
|
|
|
return GP_OK;
|
|
}
|