camlibs/sq905: New camera found, added
git-svn-id: https://svn.code.sf.net/p/gphoto/code/trunk/libgphoto2@12713 67ed7778-7388-44ab-90cf-0a291f65f57c
This commit is contained in:
@@ -1,3 +1,7 @@
|
||||
2008-05-29 Theodore Kilgore <kilgota@auburn.edu>
|
||||
* library.c: New camera. Global Point Splash Mini added.
|
||||
|
||||
|
||||
2008-05-29 Theodore Kilgore <kilgota@auburn.edu>
|
||||
* library.c: raw files now each have the corresponding catalog entry
|
||||
added as a 16-byte footer.
|
||||
|
||||
@@ -1,16 +1,19 @@
|
||||
/* This is the README file for libgphoto2/camlibs/sq905. This README is an
|
||||
* integral part of the libgphoto2/camlibs/sq905 library source and is
|
||||
* distributed with that source under the LGPL license. a copy of which
|
||||
* license may be seen in any of the source files in libgphoto2/camlibs/sq905,
|
||||
/* This is the README.sq905 file for libgphoto2/camlibs/sq905.
|
||||
*
|
||||
* This README is part of the libgphoto2/camlibs/sq905 library source and is
|
||||
* distributed with that source under the LGPL license. a copy of which
|
||||
* license may be seen in any of the source files in libgphoto2/camlibs/sq905,
|
||||
* or in the head directory of libgphoto2.
|
||||
*/
|
||||
*
|
||||
* Copyright (C) 2003 - 2010 Theodore Kilgore <kilgota@auburn.edu>
|
||||
*/
|
||||
|
||||
|
||||
INTRODUCTION:
|
||||
|
||||
Cameras with chip from S&Q Technologies are often called DSC(2770) cameras.
|
||||
They have USB Vendor:Product number 0x2770:0x9120, and are classified as
|
||||
Class:Subclass:Protocol ff:ff:ff (proprietary:proprietary:proprietary).
|
||||
They have USB Vendor:Product number 0x2770:0x9120, and are classified as USB
|
||||
Class:Subclass:Protocol ff:ff:ff (proprietary:proprietary:proprietary).
|
||||
|
||||
These cameras are cheap, basic, and come in many brands and models -- all
|
||||
with the same USB Vendor:Product number and identical /proc/bus/devices
|
||||
@@ -21,12 +24,24 @@ apparently due to different video sensor chips. Further complicating
|
||||
matters, neither S&Q Technologies nor the associated camera "manufacturers"
|
||||
seem responsive to requests for information about their chips or cameras.
|
||||
|
||||
At this time, I have four different SQ905 cameras for testing. For other
|
||||
cameras, I am totally dependent on reports from users and testers. If you
|
||||
have another 0x2770:0x9120 camera and want it to work and it currently does
|
||||
not, then I will be very glad to hear from you. Saying this a different way:
|
||||
I have several different SQ905 cameras for testing. For other cameras,
|
||||
I am totally dependent on reports from users and testers. If you have
|
||||
another 0x2770:0x9120 camera and want it to work and it currently does not,
|
||||
then I will be very glad to hear from you. Saying this a different way:
|
||||
further progress with your camera will depend upon your input.
|
||||
|
||||
Moreover, the Gphoto project tries very hard to keep a complete list of
|
||||
all supported cameras, by name and/or by any other distinguishing features,
|
||||
such as a model number if any is printed on the camera or on the packaging.
|
||||
If your camera is not on the list of supported cameras, then even if it works
|
||||
please report it, so that it can be explicitly added by name in the listing
|
||||
found in the source file camlibs/sq905/library.c. Please do this to help
|
||||
others. A camera is not sold with the USB vendor:product number printed on
|
||||
the package. Also even if it works perfectly in Linux with Gphoto software
|
||||
it will usually not say that on the package, either. For these reasons,
|
||||
again, please remember to report your camera if it is previously unlisted,
|
||||
even if it works.
|
||||
|
||||
One would reasonably suspect that all of these cameras have the same chip in
|
||||
them, or similar chips from SQ. The cameras do distinguish themselves from
|
||||
one another to some extent, reporting a number which can be thought of as a
|
||||
@@ -44,12 +59,12 @@ WHAT CHIP IS ACTUALLY IN THESE CAMERAS?
|
||||
The brief answer is that I do not know.
|
||||
|
||||
The website of SQ Technologies <www.sq.com.tw> lists several camera
|
||||
controller chips in addition to the SQ905, which is now (2007)
|
||||
controller chips in addition to the SQ905, which is now (2007)
|
||||
discontinued. All of the SQ cameras which have the same USB ID do use the
|
||||
same control sequences, however. The lower-resolution cameras all seem to use
|
||||
the same Hynix video sensor chip. The video chips in higher-resolution cameras
|
||||
do not all behave the same way and thus probably come from several sources.
|
||||
Fortunately, it seems that the "chip id" is a sufficiently reliable indicator
|
||||
same control sequences, however. The lower-resolution cameras all seem to use
|
||||
the same Hynix video sensor chip. The video chips in higher-resolution cameras
|
||||
do not all behave the same way and thus probably come from several sources.
|
||||
Fortunately, it seems that the "chip id" is a sufficiently reliable indicator
|
||||
of how to process data from the camera.
|
||||
|
||||
|
||||
@@ -79,6 +94,7 @@ Magpix B350 Binocular Camera 09 05 01 32 T. K.
|
||||
Precision Mini 50 05 00 26 Fabien Devaux
|
||||
Vivicam 3350 09 05 02 19 T. K.
|
||||
DC-N130t 09 05 02 25 Cedric Cellier
|
||||
Global Point Splash Mini (waterproof) 09 05 02 19 T. K.
|
||||
|
||||
Of these models, most actually use the "default" settings for photo processing.
|
||||
|
||||
@@ -86,9 +102,9 @@ Of these models, most actually use the "default" settings for photo processing.
|
||||
WHAT FEATURES DO THESE CAMERAS HAVE, AND WHAT DOES THIS DRIVER SUPPORT?
|
||||
|
||||
FEATURE LIST SUPPORTED (Y/N/Part)
|
||||
-- USB connection to computer
|
||||
-- High resolution 352x288 or 640x480, uncompressed Y
|
||||
-- Low resolution 176x144 or 320x240, uncompressed Y
|
||||
-- USB connection to computer Y
|
||||
-- High resolution 352x288 or 640x480, uncompressed Y
|
||||
-- Low resolution 176x144 or 320x240, uncompressed Y
|
||||
-- High resolution 352x288 or 640x480, compressed Y
|
||||
-- Low resolution 176x144 or 320x240, compressed Y
|
||||
-- Ability to "switch" resolution between pictures Y
|
||||
@@ -97,15 +113,21 @@ WHAT FEATURES DO THESE CAMERAS HAVE, AND WHAT DOES THIS DRIVER SUPPORT?
|
||||
k is less than the number on the camera Y
|
||||
-- Ability to download individual photos Y
|
||||
-- "Video clip" capability. Clips are saved as directories. Y
|
||||
-- Capture and immediate download of a 320x240 snapshot Y
|
||||
-- Capture and immediate download of a 320x240 snapshot Y
|
||||
-- Webcam mode: Not supported here. But see notes below. N
|
||||
-------------------------------------------------------------------------
|
||||
The following things can be done with button-pushes on the camera:
|
||||
-------------------------------------------------------------------------
|
||||
-- Frequency filter for use in artificial light. Can be set
|
||||
to cancel 60hz or 50hz interference.
|
||||
-- Delete all, delete last, resolution setting, compression mode setting.
|
||||
-- Delete all, delete last, resolution setting, compression mode setting.
|
||||
Unfortunately, it does not seem possible to do any of these things with
|
||||
commands sent from the computer even if the camera is tethered, except for
|
||||
the fact that for some of the cameras the command which triggers capture also
|
||||
has the effect of deleting everything stored on the camera. Thus, deletion
|
||||
of all photos may work for your camera, but it may not.
|
||||
|
||||
Notes:
|
||||
Notes:
|
||||
|
||||
All known sq905 cameras have either a 640x480 high-resolution setting and a
|
||||
320x240 low-resolution setting, or a 352x288 and a 176x144 setting. If your
|
||||
@@ -135,19 +157,30 @@ related command "gphoto2 --capture" is not implemented. It would be used to
|
||||
take a photo which can be downloaded later on, through normal photo download
|
||||
procedures. But the hardware seems unable to support "gphoto2 --capture".
|
||||
|
||||
The sq905 cameras can function as webcams. A Sourceforge project called
|
||||
"sqcam" provides the needed kernel support. If you want to use that module,
|
||||
remember that you cannot use a libgphoto2 camlib while the module for the
|
||||
same camera is installed. For, the camlib and the module will fight over
|
||||
the camera, and the camlib will lose.
|
||||
The sq905 cameras can function as webcams. Support for the webcam mode of
|
||||
these cameras is available through the module gspca_sq905, included as
|
||||
part of the regular kernel since kernel version 2.6.29. This means it is
|
||||
part of the kernel source, of course. It is then up to your distro to
|
||||
include the webcam support for these cameas, or not. The webcam mode for
|
||||
any of these cameras can do streaming at any of the resolutions 160x240,
|
||||
176x144, 320x240, 352x288, and in addition at 640x480 provided that the
|
||||
camera's hardware will do this (What is the max resolution for still photos?
|
||||
The same applies in webcam mode). However, do not expect a high frame rate
|
||||
in webcam mode. The camera is a USB 1.1 device, and it is streaming
|
||||
uncompressed frames, using bulk transport, not isochronous transport.
|
||||
|
||||
Thanks is hereby given to the authors and maintainers of the old "sq"
|
||||
module, which for several years provided an out-of-kernel module to support
|
||||
streaming with these cameras.
|
||||
|
||||
|
||||
|
||||
HARDWARE LIMITATIONS AND CONSTRAINTS
|
||||
|
||||
1. The downloading of "thumbnails" as special files is totally
|
||||
1. The downloading of "thumbnails" as special files is totally
|
||||
unsupported by the hardware. The manufacturer's driver downloads a
|
||||
consecutive list of photos and creates thumbnails, then "saves" only the
|
||||
photos which the user selects. Gphoto2 prefers ability to do random access.
|
||||
photos which the user selects. Gphoto2 prefers ability to do random access.
|
||||
|
||||
2. The camera's data storage provides only sequential access, not
|
||||
random access. In other words, it acts as though it were a tape drive
|
||||
@@ -156,7 +189,7 @@ instead of a disk. The constraints which this places are obvious.
|
||||
3. Considering the way the communication protocols of these cameras
|
||||
seem to work, it would seem nearly impossible to copy any data to the camera
|
||||
for storage and transport. The camera clearly does not have files on it,
|
||||
only data addresses. And the camera does not keep time. For similar
|
||||
only data addresses. And the camera does not keep time. For similar
|
||||
reasons, it would also seem impossible to delete a photo from the camera by
|
||||
action of software on the computer. The camera supports two choices for
|
||||
deletion: delete the last photo taken, or delete all. Each action is
|
||||
@@ -172,7 +205,9 @@ loss, then "Delete all" will probably work.)
|
||||
|
||||
To find a way around the listed constraints would indeed be most
|
||||
interesting. Who knows? Maybe these things can be done. Could be that these
|
||||
chips have undocumented capabilities. But maybe not.
|
||||
chips have undocumented capabilities. But maybe not. I have especially
|
||||
hunted for undocumented commands which would support things that the camera
|
||||
will only do with button presses, but I have not found any.
|
||||
|
||||
|
||||
WHAT GUI FRONTENDS DOES THIS CAMERA LIBRARY SUOPPORT?
|
||||
@@ -186,21 +221,21 @@ encouraged to try it. If you want to use either gtkam or digikam, you are
|
||||
encouraged to read the camera's manual.
|
||||
|
||||
|
||||
NOTES
|
||||
NOTES
|
||||
|
||||
1. The program is set up to put out pictures in PPM or raw format.
|
||||
1. The program is set up to put out pictures in PPM or raw format.
|
||||
|
||||
2. The gamma setting (actually seems to be one over gamma) used for
|
||||
2. The gamma setting (actually seems to be one over gamma) used for
|
||||
the construction of PPM image files has been obtained by trial and error. It
|
||||
seems to work very well for outdoor pictures, but the setting is a
|
||||
compromise between what happens with outdoor photos and what happens with
|
||||
indoor photos. Conceivably, the program could support a choice between two
|
||||
or more gamma settings, optimizing for different conditions.
|
||||
or more gamma settings, optimizing for different conditions.
|
||||
|
||||
4. Please get back to me with reports about other SQ cameras, with their
|
||||
4. Please get back to me with reports about other SQ cameras, with their
|
||||
specifications (what it says in the manual about resolution and number of
|
||||
pictures, as well as make and model, ID reported, and whether it works or
|
||||
not would be enough), and with a log file if there are problems.
|
||||
not would be enough), and with a log file if there are problems.
|
||||
|
||||
|
||||
ACKNOWLEDGMENTS:
|
||||
@@ -208,27 +243,27 @@ ACKNOWLEDGMENTS:
|
||||
-- to several members of East Alabama Linux Users group, for help
|
||||
and encouragement:
|
||||
|
||||
Bruce Gray,
|
||||
Darrel Hankerson,
|
||||
Bruce Gray,
|
||||
Darrel Hankerson,
|
||||
Thomas Kilgore (my son, the Perl hacker)
|
||||
Kelley Price,
|
||||
Kelley Price,
|
||||
for some basic help with C.
|
||||
Wade "Bear" Tinney,
|
||||
Wade "Bear" Tinney,
|
||||
for help in discovering how to subscribe to the gphoto-devel mailing
|
||||
list
|
||||
-- to Prof. Stan Reeves, Department of Electrical Engineering,
|
||||
Auburn University, for a very informative discussion of how a Bayer
|
||||
array is constructed.
|
||||
-- to my colleagues
|
||||
-- to my colleagues
|
||||
Darrel Hankerson, who knows clever ways to pass a character
|
||||
string from one function to another
|
||||
Steve Stuckwisch, who could explain to me Darrel's
|
||||
explanation
|
||||
-- to Christophe Barbe, for encouragement
|
||||
-- to Lutz Miller, for making me do it right.
|
||||
-- to Cedric Cellier, for devising the sq_rewind ( ) function, for
|
||||
implementing the directory structure for video clips, and in general
|
||||
for his continued interest in these cameras.
|
||||
-- to Cedric Cellier, for devising the sq_rewind ( ) function, for
|
||||
implementing the directory structure for video clips, and in general
|
||||
for his continued interest in these cameras.
|
||||
|
||||
|
||||
WARRANTY?
|
||||
@@ -250,4 +285,4 @@ WARRANTY?
|
||||
|
||||
|
||||
Theodore Kilgore
|
||||
07/07/03 (latest revision 03/09/07)
|
||||
07/07/03 (revised 03/09/07 and 02/18/10)
|
||||
@@ -7,10 +7,10 @@
|
||||
* 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
|
||||
* 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.
|
||||
* 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
|
||||
@@ -51,10 +51,10 @@
|
||||
#define GP_MODULE "sq905"
|
||||
|
||||
static const struct {
|
||||
char *name;
|
||||
char *name;
|
||||
CameraDriverStatus status;
|
||||
unsigned short idVendor;
|
||||
unsigned short idProduct;
|
||||
unsigned short idVendor;
|
||||
unsigned short idProduct;
|
||||
} models[] = {
|
||||
{"SQ chip camera", GP_DRIVER_STATUS_EXPERIMENTAL, 0x2770, 0x9120},
|
||||
{"Argus DC-1510", GP_DRIVER_STATUS_PRODUCTION, 0x2770, 0x9120},
|
||||
@@ -63,7 +63,7 @@ static const struct {
|
||||
{"Mitek CD30P", GP_DRIVER_STATUS_EXPERIMENTAL, 0x2770, 0x9120},
|
||||
{"GTW Electronics", GP_DRIVER_STATUS_EXPERIMENTAL, 0x2770, 0x9120},
|
||||
{"Concord Eye-Q Easy",GP_DRIVER_STATUS_EXPERIMENTAL, 0x2770, 0x9120},
|
||||
{"Concord Eye-Q Duo", GP_DRIVER_STATUS_EXPERIMENTAL, 0x2770, 0x9120},
|
||||
{"Concord Eye-Q Duo", GP_DRIVER_STATUS_EXPERIMENTAL, 0x2770, 0x9120},
|
||||
{"Che-ez Snap", GP_DRIVER_STATUS_EXPERIMENTAL, 0x2770, 0x9120},
|
||||
{"PockCam", GP_DRIVER_STATUS_EXPERIMENTAL, 0x2770, 0x9120},
|
||||
{"Magpix B350", GP_DRIVER_STATUS_EXPERIMENTAL, 0x2770, 0x9120},
|
||||
@@ -72,7 +72,7 @@ static const struct {
|
||||
GP_DRIVER_STATUS_PRODUCTION , 0x2770 , 0x9120},
|
||||
{"iConcepts digital camera" ,
|
||||
GP_DRIVER_STATUS_PRODUCTION , 0x2770 , 0x9120},
|
||||
{"Sakar Kidz Cam 86379", GP_DRIVER_STATUS_EXPERIMENTAL, 0x2770,
|
||||
{"Sakar Kidz Cam 86379", GP_DRIVER_STATUS_EXPERIMENTAL, 0x2770,
|
||||
0x9120},
|
||||
{"ViviCam3350", GP_DRIVER_STATUS_EXPERIMENTAL, 0x2770, 0x9120},
|
||||
{"ViviCam5B", GP_DRIVER_STATUS_EXPERIMENTAL, 0x2770, 0x9120},
|
||||
@@ -82,7 +82,9 @@ static const struct {
|
||||
{"Shark SDC-519", GP_DRIVER_STATUS_EXPERIMENTAL, 0x2770, 0x9120},
|
||||
{"Shark 2-in-1 Mini", GP_DRIVER_STATUS_EXPERIMENTAL, 0x2770, 0x9120},
|
||||
{"Argus DC-1730", GP_DRIVER_STATUS_EXPERIMENTAL, 0x2770, 0x913c},
|
||||
{"Request Ultra Slim",
|
||||
{"Request Ultra Slim",
|
||||
GP_DRIVER_STATUS_EXPERIMENTAL, 0x2770, 0x9120},
|
||||
{"Global Point Splash Mini (underwater camera)",
|
||||
GP_DRIVER_STATUS_EXPERIMENTAL, 0x2770, 0x9120},
|
||||
{NULL,0,0}
|
||||
};
|
||||
@@ -90,64 +92,66 @@ static const struct {
|
||||
int
|
||||
camera_id (CameraText *id)
|
||||
{
|
||||
strcpy (id->text, "SQ chipset camera");
|
||||
|
||||
return GP_OK;
|
||||
strcpy (id->text, "SQ chipset camera");
|
||||
|
||||
return GP_OK;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
camera_abilities (CameraAbilitiesList *list)
|
||||
{
|
||||
int i;
|
||||
CameraAbilities a;
|
||||
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)
|
||||
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_PREVIEW;
|
||||
a.folder_operations = GP_FOLDER_OPERATION_DELETE_ALL;
|
||||
a.file_operations = GP_FILE_OPERATION_PREVIEW + GP_FILE_OPERATION_RAW;
|
||||
gp_abilities_list_append (list, a);
|
||||
}
|
||||
a.folder_operations = GP_FOLDER_OPERATION_DELETE_ALL;
|
||||
a.file_operations = GP_FILE_OPERATION_PREVIEW
|
||||
+ GP_FILE_OPERATION_RAW;
|
||||
gp_abilities_list_append (list, a);
|
||||
}
|
||||
|
||||
return GP_OK;
|
||||
return GP_OK;
|
||||
}
|
||||
|
||||
static int
|
||||
camera_summary (Camera *camera, CameraText *summary, GPContext *context)
|
||||
{
|
||||
sprintf (summary->text,_("Your USB camera has a S&Q chipset.\n"
|
||||
sprintf (summary->text,_("Your USB camera has a S&Q chipset.\n"
|
||||
"The total number of pictures taken is %i\n"
|
||||
"Some of these could be clips containing\n"
|
||||
"several frames\n"),
|
||||
"several frames\n"),
|
||||
|
||||
camera->pl->nb_entries);
|
||||
camera->pl->nb_entries);
|
||||
|
||||
return GP_OK;
|
||||
return GP_OK;
|
||||
}
|
||||
|
||||
static int camera_manual (Camera *camera, CameraText *manual, GPContext *context)
|
||||
static int camera_manual (Camera *camera, CameraText *manual,
|
||||
GPContext *context)
|
||||
{
|
||||
strcpy(manual->text,
|
||||
strcpy(manual->text,
|
||||
_(
|
||||
"For cameras with S&Q Technologies chip.\n"
|
||||
"Should work with gtkam. Photos will be saved in PPM format.\n\n"
|
||||
|
||||
"All known S&Q cameras have two resolution settings. What\n"
|
||||
"All known S&Q cameras have two resolution settings. What\n"
|
||||
"those are, will depend on your particular camera.\n"
|
||||
"A few of these cameras allow deletion of all photos. Most do not.\n"
|
||||
"Uploading of data to the camera is not supported.\n"
|
||||
"The photo compression mode found on many of the S&Q\n"
|
||||
"cameras is supported, to some extent.\n"
|
||||
"The photo compression mode found on many of the S&Q\n"
|
||||
"cameras is supported, to some extent.\n"
|
||||
"If present on the camera, video clips are seen as subfolders.\n"
|
||||
"Gtkam will download these separately. When clips are present\n"
|
||||
"on the camera, there is a little triangle before the name of\n"
|
||||
@@ -157,7 +161,7 @@ static int camera_manual (Camera *camera, CameraText *manual, GPContext *context
|
||||
"be downloaded as separate photos, with special names which\n"
|
||||
"specify from which clip they came. Thus, you may freely \n"
|
||||
"choose to save clip frames in separate directories. or not.\n"
|
||||
));
|
||||
));
|
||||
|
||||
return (GP_OK);
|
||||
}
|
||||
@@ -167,10 +171,10 @@ static int camera_manual (Camera *camera, CameraText *manual, GPContext *context
|
||||
static int
|
||||
camera_about (Camera *camera, CameraText *about, GPContext *context)
|
||||
{
|
||||
strcpy (about->text, _("sq905 generic driver\n"
|
||||
strcpy (about->text, _("sq905 generic driver\n"
|
||||
"Theodore Kilgore <kilgota@auburn.edu>\n"));
|
||||
|
||||
return GP_OK;
|
||||
return GP_OK;
|
||||
}
|
||||
|
||||
/*************** File and Downloading Functions *******************/
|
||||
@@ -180,7 +184,7 @@ static int
|
||||
file_list_func (CameraFilesystem *fs, const char *folder, CameraList *list,
|
||||
void *data, GPContext *context)
|
||||
{
|
||||
Camera *camera = data;
|
||||
Camera *camera = data;
|
||||
int i,n;
|
||||
GP_DEBUG ("List files in %s\n", folder);
|
||||
if (0==strcmp(folder, "/")) {
|
||||
@@ -196,8 +200,10 @@ file_list_func (CameraFilesystem *fs, const char *folder, CameraList *list,
|
||||
if (sq_is_clip(camera->pl, i)) n--;
|
||||
}
|
||||
i--;
|
||||
if (!sq_is_clip(camera->pl, i)) return GP_ERROR_DIRECTORY_NOT_FOUND;
|
||||
gp_list_populate(list, format, sq_get_num_frames(camera->pl, i));
|
||||
if (!sq_is_clip(camera->pl, i))
|
||||
return GP_ERROR_DIRECTORY_NOT_FOUND;
|
||||
gp_list_populate(list, format,
|
||||
sq_get_num_frames(camera->pl, i));
|
||||
}
|
||||
return GP_OK;
|
||||
}
|
||||
@@ -216,7 +222,7 @@ folder_list_func (CameraFilesystem *fs, const char *folder, CameraList *list,
|
||||
gp_list_populate (list, "clip%03i", n);
|
||||
|
||||
}
|
||||
return GP_OK;
|
||||
return GP_OK;
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -225,7 +231,7 @@ get_info_func (CameraFilesystem *fs, const char *folder, const char *file,
|
||||
{
|
||||
memset (info, 0, sizeof(CameraFileInfo));
|
||||
/* FIXME: fill in some stuff? */
|
||||
return (GP_OK);
|
||||
return (GP_OK);
|
||||
}
|
||||
|
||||
|
||||
@@ -234,12 +240,12 @@ get_file_func (CameraFilesystem *fs, const char *folder, const char *filename,
|
||||
CameraFileType type, CameraFile *file, void *user_data,
|
||||
GPContext *context)
|
||||
{
|
||||
Camera *camera = user_data;
|
||||
Camera *camera = user_data;
|
||||
int i, w, h, b, entry, frame, is_in_clip;
|
||||
int nb_frames, to_fetch;
|
||||
int nb_frames, to_fetch;
|
||||
int do_preprocess;
|
||||
unsigned char comp_ratio;
|
||||
unsigned char *frame_data, *rawdata;
|
||||
unsigned char *frame_data, *rawdata;
|
||||
unsigned char *ppm, *ptr;
|
||||
unsigned char gtable[256];
|
||||
int size;
|
||||
@@ -259,41 +265,48 @@ get_file_func (CameraFilesystem *fs, const char *folder, const char *filename,
|
||||
if (0==strcmp(folder, "/")) {
|
||||
i = atoi(filename+4);
|
||||
do {
|
||||
do entry++;
|
||||
while (sq_is_clip(camera->pl, entry)
|
||||
&& entry<camera->pl->nb_entries);
|
||||
do entry++;
|
||||
while (sq_is_clip(camera->pl, entry)
|
||||
&& entry<camera->pl->nb_entries);
|
||||
i--;
|
||||
}
|
||||
while (i>0);
|
||||
if (entry == camera->pl->nb_entries) return GP_ERROR_FILE_NOT_FOUND;
|
||||
if (entry == camera->pl->nb_entries)
|
||||
return GP_ERROR_FILE_NOT_FOUND;
|
||||
frame = 0;
|
||||
is_in_clip = 0;
|
||||
} else {
|
||||
i = atoi(folder+1+4);
|
||||
do {
|
||||
do entry++; while (!sq_is_clip(camera->pl, entry) && entry<camera->pl->nb_entries);
|
||||
do entry++;
|
||||
while (!sq_is_clip(camera->pl, entry) &&
|
||||
entry<camera->pl->nb_entries);
|
||||
i--;
|
||||
} while (i>0);
|
||||
if (entry == camera->pl->nb_entries) return GP_ERROR_DIRECTORY_NOT_FOUND;
|
||||
if (entry == camera->pl->nb_entries)
|
||||
return GP_ERROR_DIRECTORY_NOT_FOUND;
|
||||
frame = atoi(filename+4)-1;
|
||||
if (frame >= sq_get_num_frames(camera->pl, entry)) return GP_ERROR_FILE_NOT_FOUND;
|
||||
if (frame >= sq_get_num_frames(camera->pl, entry))
|
||||
return GP_ERROR_FILE_NOT_FOUND;
|
||||
is_in_clip = 1;
|
||||
}
|
||||
|
||||
GP_DEBUG ("Download file %s from %s, entry = %d, frame = %d\n",
|
||||
|
||||
GP_DEBUG ("Download file %s from %s, entry = %d, frame = %d\n",
|
||||
filename, folder, entry, frame);
|
||||
|
||||
/* Fetch entries until the one we need, and toss all but the one we need.
|
||||
* TODO: Either find out how to use the location info in the catalog to
|
||||
* download just the entry needed, or show it is as impossible as it seems.
|
||||
/* Fetch entries until the one we need, and toss all before
|
||||
* the one we need.
|
||||
* TODO: Either find out how to use the location info in the catalog
|
||||
* to download just the entry needed, or show it is as impossible as
|
||||
* it seems to be.
|
||||
*/
|
||||
|
||||
GP_DEBUG ("last entry was %d\n", camera->pl->last_fetched_entry);
|
||||
|
||||
/* Change register to DATA, but only if necessary */
|
||||
if ((camera->pl->last_fetched_entry == -1)
|
||||
|| ((is_in_clip) && (frame == 0)) )
|
||||
|
||||
|| ((is_in_clip) && (frame == 0)) )
|
||||
|
||||
sq_access_reg(camera->port, DATA);
|
||||
|
||||
if (camera->pl->last_fetched_entry > entry) {
|
||||
@@ -310,7 +323,7 @@ get_file_func (CameraFilesystem *fs, const char *folder, const char *filename,
|
||||
nb_frames = sq_get_num_frames(camera->pl, to_fetch);
|
||||
comp_ratio = sq_get_comp_ratio (camera->pl, to_fetch);
|
||||
w = sq_get_picture_width (camera->pl, to_fetch);
|
||||
switch (w) {
|
||||
switch (w) {
|
||||
case 176: h = 144; break;
|
||||
case 640: h = 480; break;
|
||||
case 320: h = 240; break;
|
||||
@@ -327,20 +340,20 @@ get_file_func (CameraFilesystem *fs, const char *folder, const char *filename,
|
||||
}
|
||||
GP_DEBUG("Fetch entry %i\n", to_fetch);
|
||||
sq_read_picture_data
|
||||
(camera->port, camera->pl->last_fetched_data, b);
|
||||
(camera->port, camera->pl->last_fetched_data, b);
|
||||
camera->pl->last_fetched_entry = to_fetch;
|
||||
} while (camera->pl->last_fetched_entry<entry);
|
||||
|
||||
frame_data = camera->pl->last_fetched_data+(w*h)*frame/comp_ratio;
|
||||
/* sq_preprocess ( ) turns the photo right-side-up and for some
|
||||
* models must also de-mirror the photo
|
||||
* models must also de-mirror the photo
|
||||
*/
|
||||
|
||||
if (GP_FILE_TYPE_RAW!=type) {
|
||||
|
||||
if (do_preprocess) {
|
||||
sq_preprocess(camera->pl->model, comp_ratio, is_in_clip,
|
||||
frame_data, w, h);
|
||||
sq_preprocess(camera->pl->model, comp_ratio,
|
||||
is_in_clip, frame_data, w, h);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -348,7 +361,7 @@ get_file_func (CameraFilesystem *fs, const char *folder, const char *filename,
|
||||
*/
|
||||
ppm = malloc (w * h * 3 + 256); /* room for data + header */
|
||||
if (!ppm) { return GP_ERROR_NO_MEMORY; }
|
||||
sprintf ((char *)ppm,
|
||||
sprintf ((char *)ppm,
|
||||
"P6\n"
|
||||
"# CREATOR: gphoto2, SQ905 library\n"
|
||||
"%d %d\n"
|
||||
@@ -370,15 +383,15 @@ get_file_func (CameraFilesystem *fs, const char *folder, const char *filename,
|
||||
if (comp_ratio>1) {
|
||||
rawdata = malloc (w*h);
|
||||
if (!rawdata) return GP_ERROR_NO_MEMORY;
|
||||
sq_decompress (camera->pl->model, rawdata,
|
||||
frame_data, w, h);
|
||||
sq_decompress (camera->pl->model, rawdata,
|
||||
frame_data, w, h);
|
||||
gp_gamma_fill_table (gtable, .65);
|
||||
} else {
|
||||
rawdata = frame_data;
|
||||
gp_gamma_fill_table (gtable, .55);
|
||||
gp_gamma_fill_table (gtable, .55);
|
||||
}
|
||||
gp_ahd_decode (rawdata, w , h , ptr, this_cam_tile);
|
||||
gp_gamma_correct_single (gtable, ptr, w * h);
|
||||
gp_gamma_correct_single (gtable, ptr, w * h);
|
||||
|
||||
gp_file_set_mime_type (file, GP_MIME_PPM);
|
||||
gp_file_set_data_and_size (file, (char *)ppm, size);
|
||||
@@ -390,14 +403,14 @@ get_file_func (CameraFilesystem *fs, const char *folder, const char *filename,
|
||||
memcpy (rawdata, frame_data, size);
|
||||
memcpy (rawdata+size,camera->pl->catalog+16*entry,16);
|
||||
gp_file_set_mime_type (file, GP_MIME_RAW);
|
||||
gp_file_set_data_and_size (file, (char *)rawdata, size+16);
|
||||
gp_file_set_data_and_size (file, (char *)rawdata, size+16);
|
||||
}
|
||||
/* Reset camera when done, for more graceful exit. */
|
||||
if ((!(is_in_clip)&&(entry +1 == camera->pl->nb_entries))
|
||||
if ((!(is_in_clip)&&(entry +1 == camera->pl->nb_entries))
|
||||
|| ((is_in_clip)&& (frame +1 == nb_frames )))
|
||||
sq_reset (camera->port);
|
||||
|
||||
return GP_OK;
|
||||
return GP_OK;
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -414,10 +427,8 @@ delete_all_func (CameraFilesystem *fs, const char *folder, void *data,
|
||||
|
||||
static int
|
||||
camera_capture_preview (Camera *camera, CameraFile *file, GPContext *context)
|
||||
|
||||
|
||||
{
|
||||
unsigned char *frame_data;
|
||||
unsigned char *frame_data;
|
||||
unsigned char *ppm, *ptr;
|
||||
unsigned char gtable[256];
|
||||
int size;
|
||||
@@ -437,14 +448,15 @@ camera_capture_preview (Camera *camera, CameraFile *file, GPContext *context)
|
||||
sq_preprocess(camera->pl->model, 1, 0, frame_data, w, h);
|
||||
|
||||
/* Now put the data into a PPM image file. */
|
||||
ppm = malloc (w * h * 3 + 256);
|
||||
if (!ppm) { return GP_ERROR_NO_MEMORY; }
|
||||
sprintf ((char *)ppm,
|
||||
ppm = malloc (w * h * 3 + 256);
|
||||
if (!ppm)
|
||||
return GP_ERROR_NO_MEMORY;
|
||||
sprintf ((char *)ppm,
|
||||
"P6\n"
|
||||
"# CREATOR: gphoto2, SQ905 library\n"
|
||||
"%d %d\n"
|
||||
"255\n", w, h);
|
||||
ptr = ppm + strlen ((char*)ppm);
|
||||
ptr = ppm + strlen ((char*)ppm);
|
||||
size = strlen ((char*)ppm) + (w * h * 3);
|
||||
GP_DEBUG ("size = %i\n", size);
|
||||
switch (camera->pl->model) {
|
||||
@@ -455,15 +467,15 @@ camera_capture_preview (Camera *camera, CameraFile *file, GPContext *context)
|
||||
gp_bayer_decode (frame_data, w , h , ptr, BAYER_TILE_BGGR);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
/* TO DO:
|
||||
* Adapt some postprocessing routine to work here, because results
|
||||
* can vary greatly, depending both on lighting conditions and on
|
||||
* Adapt some postprocessing routine to work here, because results
|
||||
* can vary greatly, depending both on lighting conditions and on
|
||||
* camera model.
|
||||
*/
|
||||
|
||||
gp_gamma_fill_table (gtable, .5);
|
||||
gp_gamma_correct_single (gtable, ptr, w * h);
|
||||
gp_gamma_fill_table (gtable, .5);
|
||||
gp_gamma_correct_single (gtable, ptr, w * h);
|
||||
gp_file_set_mime_type (file, GP_MIME_PPM);
|
||||
gp_file_set_data_and_size (file, (char *)ppm, size);
|
||||
|
||||
@@ -506,22 +518,22 @@ camera_init(Camera *camera, GPContext *context)
|
||||
int ret = 0;
|
||||
|
||||
/* First, set up all the function pointers */
|
||||
camera->functions->summary = camera_summary;
|
||||
camera->functions->manual = camera_manual;
|
||||
camera->functions->about = camera_about;
|
||||
camera->functions->capture_preview
|
||||
camera->functions->summary = camera_summary;
|
||||
camera->functions->manual = camera_manual;
|
||||
camera->functions->about = camera_about;
|
||||
camera->functions->capture_preview
|
||||
= camera_capture_preview;
|
||||
camera->functions->exit = camera_exit;
|
||||
|
||||
camera->functions->exit = camera_exit;
|
||||
|
||||
GP_DEBUG ("Initializing the camera\n");
|
||||
|
||||
ret = gp_port_get_settings(camera->port,&settings);
|
||||
if (ret < 0) return ret;
|
||||
if (ret < 0) return ret;
|
||||
|
||||
ret = gp_port_set_settings(camera->port,settings);
|
||||
if (ret < 0) return ret;
|
||||
if (ret < 0) return ret;
|
||||
|
||||
/* Tell the CameraFilesystem where to get lists from */
|
||||
/* 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;
|
||||
@@ -538,6 +550,5 @@ camera_init(Camera *camera, GPContext *context)
|
||||
return ret;
|
||||
};
|
||||
|
||||
|
||||
return GP_OK;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user