Files
libgphoto2/camlibs/digita/digita.c
axxel f41df32817 fix white-space and indentation inconsistencies (second round)
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).
2024-09-15 10:53:41 +02:00

477 lines
11 KiB
C

/*
* digita.c
*
* Copyright 1999-2001 Johannes Erdfelt
*
* 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 <errno.h>
#include <fcntl.h>
#include <string.h>
#ifdef HAVE_LIMITS_H
#include <limits.h>
#endif
#define GP_MODULE "digita"
#include <gphoto2/gphoto2.h>
#include <gphoto2/gphoto2-port.h>
#include "libgphoto2/i18n.h"
#include "libgphoto2/gphoto2-endian.h"
#include "digita.h"
#ifndef MAX
# define MAX(a, b) ((a) > (b) ? (a) : (b))
#endif
#ifndef MIN
# define MIN(a, b) ((a) < (b) ? (a) : (b))
#endif
static const struct {
char *model;
int usb_vendor;
int usb_product;
} models[] = {
{"Kodak:DC220", 0x040A, 0x0100 },
{"Kodak:DC260", 0x040A, 0x0110 },
{"Kodak:DC265", 0x040A, 0x0111 },
{"Kodak:DC290", 0x040A, 0x0112 },
{"HP:PhotoSmart C500", 0x03F0, 0x4102 },
{"HP:PhotoSmart 618", 0x03F0, 0x4102 },
{"HP:PhotoSmart 912", 0x03F0, 0x4102 },
{"HP:PhotoSmart C500 2",0xf003, 0x6002 },
};
int camera_abilities(CameraAbilitiesList *list)
{
unsigned int i;
CameraAbilities a;
for (i = 0; i < sizeof(models) / sizeof(models[0]); i++) {
memset(&a, 0, sizeof(a));
strcpy(a.model, models[i].model);
a.status = GP_DRIVER_STATUS_PRODUCTION;
a.port = GP_PORT_SERIAL | GP_PORT_USB;
a.speed[0] = 9600;
a.speed[1] = 19200;
a.speed[2] = 38400;
a.speed[3] = 57600;
a.speed[4] = 115200;
a.speed[5] = 0;
a.operations = GP_OPERATION_NONE;
a.folder_operations = GP_FOLDER_OPERATION_NONE;
a.file_operations = GP_FILE_OPERATION_PREVIEW |
GP_FILE_OPERATION_DELETE;
a.usb_vendor = models[i].usb_vendor;
a.usb_product = models[i].usb_product;
gp_abilities_list_append(list, a);
}
return GP_OK;
}
int camera_id(CameraText *id)
{
strcpy(id->text, "digita");
return GP_OK;
}
static int camera_exit(Camera *camera, GPContext *context)
{
if (camera->pl) {
free(camera->pl);
camera->pl = NULL;
}
return GP_OK;
}
static int folder_list_func(CameraFilesystem *fs, const char *folder,
CameraList *list, void *data, GPContext *context)
{
Camera *camera = data;
int i, i1;
if (digita_get_file_list(camera->pl) < 0)
return GP_ERROR;
if (folder[0] == '/')
folder++;
/* Walk through all of the pictures building a list of folders */
for (i = 0; i < camera->pl->num_pictures; i++) {
int found;
char *path,*newfolder;
/* Check to make sure the path matches the folder we're */
/* looking through */
if (strlen(folder) && strncmp(camera->pl->file_list[i].fn.path,
folder, strlen(folder)))
continue;
/* If it's not the root, then we skip the / as well */
if (strlen(folder))
path = camera->pl->file_list[i].fn.path + strlen(folder) + 1;
else
path = camera->pl->file_list[i].fn.path;
if (!strlen(path))
continue;
if (strchr(path, '/') != path + strlen(path) - 1)
continue;
newfolder = strdup(path);
*strchr(newfolder,'/') = 0;
found = 0;
for (i1 = 0; i1 < gp_list_count(list); i1++) {
const char *name;
gp_list_get_name(list, i1, &name);
if (!strcmp(name, newfolder)) {
found = 1;
break;
}
}
if (!found)
gp_list_append(list, newfolder, NULL);
free (newfolder);
}
return GP_OK;
}
static int file_list_func(CameraFilesystem *fs, const char *folder,
CameraList *list, void *data, GPContext *context)
{
Camera *camera = data;
int i;
/* We should probably check to see if we have a list already and */
/* get the changes since */
if (digita_get_file_list(camera->pl) < 0)
return GP_ERROR;
if (folder[0] == '/')
folder++;
/* Walk through all of the pictures building a list of folders */
for (i = 0; i < camera->pl->num_pictures; i++) {
if (strncmp(camera->pl->file_list[i].fn.path, folder, strlen(folder)) ||
camera->pl->file_list[i].fn.path[strlen(folder)] != '/')
continue;
gp_list_append(list, camera->pl->file_list[i].fn.dosname, NULL);
}
return GP_OK;
}
#define GFD_BUFSIZE 19432
static unsigned char *digita_file_get(Camera *camera, const char *folder,
const char *filename, int thumbnail, int *size,
GPContext *context)
{
struct filename fn;
struct partial_tag tag;
unsigned char *data;
int pos, len, buflen;
unsigned int id;
GP_DEBUG ("Getting %s from folder %s...", filename, folder);
/* Setup the filename */
/* FIXME: This is kinda lame, but it's a quick hack */
fn.driveno = camera->pl->file_list[0].fn.driveno;
strcpy(fn.path, folder);
strcat(fn.path, "/");
strcpy(fn.dosname, filename);
/* How much data we're willing to accept */
tag.offset = htobe32(0);
tag.length = htobe32(GFD_BUFSIZE);
tag.filesize = htobe32(0);
buflen = GFD_BUFSIZE;
data = malloc(buflen);
if (!data) {
GP_DEBUG( "digita_file_get: allocating memory");
return NULL;
}
memset(data, 0, buflen);
if (digita_get_file_data(camera->pl, thumbnail, &fn, &tag, data) < 0) {
GP_DEBUG( "digita_get_picture: digita_get_file_data failed");
free (data);
return NULL;
}
buflen = be32toh(tag.filesize);
if (thumbnail)
buflen += 16;
data = realloc(data, buflen);
if (!data) {
GP_DEBUG( "digita_file_get: couldn't reallocate memory");
return NULL;
}
len = be32toh(tag.filesize);
pos = be32toh(tag.length);
id = gp_context_progress_start (context, len, _("Getting file..."));
while (pos < len) {
gp_context_progress_update (context, id, pos);
tag.offset = htobe32(pos);
if ((len - pos) > GFD_BUFSIZE)
tag.length = htobe32(GFD_BUFSIZE);
else
tag.length = htobe32(len - pos);
if (digita_get_file_data(camera->pl, thumbnail, &fn, &tag, data + pos) < 0) {
GP_DEBUG ("digita_get_file_data failed.");
free (data);
return NULL;
}
pos += be32toh(tag.length);
}
gp_context_progress_stop (context, id);
*size = buflen;
return data;
}
/* Colorspace conversion is voodoo-magic to me --jerdfelt */
static void decode_ycc422(unsigned char *input, int width, int height, unsigned char *output)
{
int x, y;
for (y = 0; y < height; y++) {
for (x = 0; x < width / 2; x++) {
int _y, u, y1, v, r, g, b;
#define LIMIT(_x) ((((_x)>0xffffff)?0xff0000:(((_x)<=0xffff)?0:(_x)&0xff0000))>>16)
u = *input++ - 128;
_y = *input++ - 16;
v = *input++ - 128;
y1 = *input++ - 16;
r = 104635 * v;
g = -25690 * u + -53294 * v;
b = 132278 * u;
_y *= 76310;
y1 *= 76310;
*output++ = LIMIT(r + _y);
*output++ = LIMIT(g + _y);
*output++ = LIMIT(b + _y);
*output++ = LIMIT(r + y1);
*output++ = LIMIT(g + y1);
*output++ = LIMIT(b + y1);
}
}
}
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;
unsigned char *data;
unsigned int width, height;
char ppmhead[64];
int buflen;
if (folder[0] == '/')
folder++;
switch (type) {
case GP_FILE_TYPE_NORMAL:
GP_DEBUG("digita/get_file_func: Getting picture");
data = digita_file_get(camera, folder, filename, 0, &buflen, context);
break;
case GP_FILE_TYPE_PREVIEW:
GP_DEBUG("digita/get_file_func: Getting thumbnail");
data = digita_file_get(camera, folder, filename, 1, &buflen, context);
break;
default:
gp_context_error(context, _("Image type is not supported"));
return GP_ERROR_NOT_SUPPORTED;
}
if (!data)
return GP_ERROR;
switch (type) {
case GP_FILE_TYPE_NORMAL:
gp_file_set_data_and_size(file, (char*)data, buflen);
gp_file_set_mime_type(file, GP_MIME_JPEG);
break;
case GP_FILE_TYPE_PREVIEW:
{
char *ppm;
memcpy((void *)&height, data + 4, 4);
height = be32toh(height);
memcpy((void *)&width, data + 8, 4);
width = be32toh(width);
GP_DEBUG( "picture size %dx%d", width, height);
GP_DEBUG( "data size %d", buflen - 16);
sprintf(ppmhead,
"P6\n"
"# CREATOR: gphoto2, digita library\n"
"%i %i\n"
"255\n", width, height);
ppm = malloc(strlen(ppmhead) + (width * height * 3));
if (!ppm)
return -1;
strcpy(ppm, ppmhead);
decode_ycc422(data + 16, width, height, (unsigned char*)(ppm + strlen(ppmhead)));
free(data);
gp_file_set_mime_type(file, GP_MIME_PPM);
gp_file_set_data_and_size(file, ppm, strlen(ppmhead) + (width * height * 3));
break;
}
default:
return GP_ERROR_NOT_SUPPORTED;
}
return GP_OK;
}
static int camera_summary(Camera *camera, CameraText *summary, GPContext *context)
{
int taken;
if (digita_get_storage_status(camera->pl, &taken, NULL, NULL) < 0)
return 0;
sprintf(summary->text, _("Number of pictures: %d"), taken);
return GP_OK;
}
static int camera_about(Camera *camera, CameraText *about, GPContext *context)
{
strcpy(about->text, _("Digita\n" \
"Johannes Erdfelt <johannes@erdfelt.com>"));
return GP_OK;
}
static int digita_file_delete(Camera *camera, const char *folder,
const char *filename, GPContext *context)
{
struct filename fn;
/* Setup the filename */
/* FIXME: This is kinda lame, but it's a quick hack */
fn.driveno = camera->pl->file_list[0].fn.driveno;
strcpy(fn.path, folder);
strcat(fn.path, "/");
strcpy(fn.dosname, filename);
if (digita_delete_picture(camera->pl, &fn) < 0)
return 0;
if (digita_get_file_list(camera->pl) < 0)
return 0;
return GP_OK;
}
static int delete_file_func(CameraFilesystem *fs, const char *folder,
const char *filename, void *user_data, GPContext *context)
{
Camera *camera = user_data;
if (folder[0] == '/')
folder++;
return digita_file_delete(camera, folder, filename, context);
}
static CameraFilesystemFuncs fsfuncs = {
.file_list_func = file_list_func,
.folder_list_func = folder_list_func,
.get_file_func = get_file_func,
.del_file_func = delete_file_func
};
int camera_init(Camera *camera, GPContext *context)
{
int ret = 0;
if (!camera)
return GP_ERROR;
/* First, set up all the function pointers */
camera->functions->exit = camera_exit;
camera->functions->summary = camera_summary;
camera->functions->about = camera_about;
/* Set up the CameraFilesystem */
gp_filesystem_set_funcs(camera->fs, &fsfuncs, camera);
GP_DEBUG( "Initializing the camera");
camera->pl = malloc(sizeof(CameraPrivateLibrary));
if (!camera->pl)
return GP_ERROR_NO_MEMORY;
memset(camera->pl, 0, sizeof(CameraPrivateLibrary));
camera->pl->gpdev = camera->port;
switch (camera->port->type) {
case GP_PORT_USB:
ret = digita_usb_open(camera->pl, camera);
break;
case GP_PORT_SERIAL:
ret = digita_serial_open(camera->pl, camera);
break;
default:
free(camera->pl);
camera->pl = NULL;
return GP_ERROR_UNKNOWN_PORT;
}
if (ret < 0) {
GP_DEBUG( "camera_init: couldn't open digita device");
free(camera->pl);
camera->pl = NULL;
return ret;
}
return GP_OK;
}