// Disclaimer In this document, I will say "should" a lot, as in the way things "should" be done. That doesn't mean I'm trying to dictate dogma -- I'm just stating an opinion for discussion purposes. That said, here's the vision... // Project Scope Although we're developing on linux, there's no reason why our code shouldn't be aimed at generic unix. Where feasible, we should avoid linux-specific conventions, device names, driver properties, etc. We should stick to POSIX where possible and relevant. I don't mean that we should start testing on multiple unixes right away, but that we should try to make it easy to port to other unixes when that time comes. For example, where we do byte-swapping of 16-bit and 32-bit quantities, we should wrap the code with ifdefs, to ease porting to big-endian unixes. The Host Interface Specification (HIS) we're working from is a Flashpoint publication -- nowhere in it is Kodak mentioned by name. So, although we're developing for Kodak cameras we should make it our goal to support any Digita-equipped camera. The Minolta EX 1500 cameras will use Digita, and the Flashpoint web page lists Sharp as a manufacturer, so we may be seeing Digita cameras from them too. Following the HIS should ensure that we're compatible with these products, and we should take pains not to make our code, comments, or doco too Kodak-specific. // Products As I've mentioned in previous e-mail, we should start small, with a core library, then build new products around that core. Here, then, from low-level to high-level are the products I envision for camera support and somewhat beyond. Digita interface: The core library that speaks the wire protocol to the camera, and provides convenient access to camera function primitives from C code. This library should come first, although it need not necessarily be 100% finished before other products emerge. Bindings: Access to the camera from perl, C++, Java, Python. These will vary in complexity: C++ binding should be fairly easy. Java will require JNI and be necessarily more complicated. Perl and Python probably lie between C++ and Java in complexity. SANE module: A GNU Image Manipulation Program (GIMP) plug-in to allow the GIMP to download files directly from the camera. Command-line utility: A simple program, or suite of programs designed to move data to/from the camera from the command line. This product might have about the same feel as the mtools -- mdir, mcopy, etc., that provide access to DOS floppies (that's *not* to suggest that the command-line utility should have a similar syntax). EXIF utility: Not really a camera utility, but it would be useful to the same users, hence I include it under the project umbrella. The JPEG files downloaded from a Digita camera have an EXIF file embedded in them as a JPEG application extension (APP1 or APP2, I believe). Camera users would like to have a utility to extract and display this information from the JPEG file. The EXIF file includes the date and time the photo was taken, the camera settings (flash, f-stop, lens), the photo serial number, etc. camerafs: A virtual filesystem for linux. Image being able to "mount" your camera as a linux filesystem, and manipulate the camera's images and albums as if they were linux files and directories: %mount /dev/cua2 /camera -t camerafs -o donly %cd /camera %ls album1/ p0000100.jpg p0000101.jpg system %ls album1 p0000102.jpg %cp *.jpg album1/*.jpg ~/dc-260/ %ls ~/dc-260 p0000100.jpg p0000101.jpg p0000102.jpg %rm -rf *.jpg album1 GTK utility: A tool similar to Kodak's bundled DC-220/260 image browser, with a slick GTK user interface, but less fluff and more function than Kodak's. Drag-and-drop interactivity with GIMP, and perhaps hooks into GIMP scripting. The following two products are not built from the Digita libraries and are not limited to digital-camera users. I list them here because I see them as being part of the continuum of image-manipulation tools, with libraries like the Digita interface and imlib at the low end, and tools like the GIMP at the high end. The following products would complement the GIMP both for digital photographers and digital artists. image versioning: A command-line tool similar to RCS, but for tracking version histories of images instead of source files. Does not record literal source differences as does RCS, but the editing commands used to create one version from another. Will use a GIMP plug-in to track and record user changes to an image; the resulting differences can be stored in an external version file, or in the image file as JPEG application extensions. The purpose of this tool is to cut down on the file clutter that results as an image is worked on through its life-cycle. For example, when I scan a photo, I go through several standard iterations, and I like to keep the image resulting from each: the raw scan, the version with scratches and specks removed, the version that I crop and color-correct, the web-friendly (scaled down to 640x480) version, and the web thumbnail. An image versioning tool would allow all versions of an image to be kept in a single file for archival and management purposes. PhotoNav: A companion to the GIMP -- a GTK/GNOME tool for managing collections of images. Will include an image browser, and an image history viewer. Will have hooks into the image versioning tool for managing image revisions, and will have hooks into the GIMP for editing. GNOME- aware, so it will support drag-and-drop to the GIMP and to filesystem browsers. Will have guile scripting so that tasks can be automated. // Development Strategy At the heart of all the camera products is the Digita interface library; our first effort should (and has been) dedicated to this body of code. However, our users (and ourselves) have an itch: to get photos from linux. It is important for our first release to scratch that itch, even if only with limited functionality. My proposal is that our first release goal should be a well-engineered library accompanied by a utility to download images from the camera. This will "scratch the itch" of linux users wanting to download from their cameras without having to boot into Windows, and should get our project off to a nice start in our end-users' eyes. We should procede along these lines: 1. Perform proof-of-concept prototyping to demonstrate that we can communicate with the camera and understand its protocol. This has already been partly accomplished. 2. Design an API for the library, and code the header files declaring the API. See the API section below for thoughts on how we should structure the library and its API. 3a. Begin implementation using the prototype sources if they are suitably well-organized, discarding them and starting from scratch otherwise. In parallel with this we can begin two other activities: 3b. Begin design and implementation of the EXIF library, focusing on API design and on the code needed for support of the command-line utility. 3c. Begin implementation of the command-line camera utility. This can be done in parallel with 3a by writing stub libraries and using them until the core library becomes mature enough to use. 4. When the three components become mature enough that they can reliably copy images from the camera, we release our first versions of the libraries and utility. Note that, because we've very narrowly defined what the first release can do, we should be able to reach it fairly rapidly -- within a month or two. The first-release goals for the three components are: Digita library: can contact the camera over serial port, retrieve list of pictures, download pictures. Minimal error checking. EXIF library: can scan the JPEG image for embedded EXIF; can scan EXIF for date/time of photograph. Command-line app: uses Digita library to download images from camera and store to local file system. Uses EXIF library to retrieve date and time of photograph, and set creation times of files appropriately. Further development to be defined. // Digita Library API The API has three parts: first, the environmental part which sets up a camera "environment" by establishing a connection to a camera; next, the "common" part which corresponds to the Core Commands listed in chapter three of the HIS, pp 27-50; finally, the "low-level" part provides a means of talking directly to the camera. A possible fourth part "product-specific" might be considered eventually, but is beyond the present scope of the project. All Digita library API calls use a DLCamera structure; this structure is opaque to client code (in OO terms we have data encapsulation). To communicate with a Digita camera, one first gets a DLCamera pointer representing that camera: DLCamera camera = DLOpenCameraNSS("/dev/cua2"); All commands interacting with the camera then pass the DLCamera pointer as a first argument: DLPowerState pstate; DLGetPowerMode(camera, &pstate); The Environmental API creates, configures, and destroys DLCamera pointers; the Common and Low-level APIs perform operations on them. // Environment API Several calls are provided to open camera connections: DLCamera *DLOpenCameraNSS(const char *dev_name); DLCamera *DLOpenCameraUSB(const char *dev_name); DLCamera *DLOpenCameraIrDA(const char *dev_name); DLCamera *DLInitialize(int *argc, const char *argv[]); DLOpenCamera* opens a camera at a specific device. DLInitialize opens a camera after scanning the command-line and environment variables to determine which device to open. DLInitialize will enable Digita Library utilities to share a common command-line syntax and common use of environment variables without each application having to code its own. This is similar to the way X applications specify which X server to connect to: they can specify it on the command-line: xterm -display localhost:0 Or by setting an environment variable: DISPLAY=localhost:0 xterm For Digita libraries, the intent is similar, but we should use GNU-style arguments: camutil --dldevice=/dev/cua2 We will also examine environment variables: DLDEVICE=/dev/cua2 camutil DLInitialize can also scan other connection parameters from the command-line and environment. For example, the maximum time the library waits to connect to a camera, its timeout value, might be specified on the command-line: camutil --dltimeout=2 To specify a timeout of 2 seconds, or in the environment: DLTIMEOUT=2 camutil The environmental API will also provide calls to specifically configure parameters such as timeout: void DLSetTimeout(DLCamera *camera, unsigned int timeout); // Common API Flashpoint structured their HIS documentation so that camera commands look like API calls, and the Common API calls should directly reflect this. Each API call will take, in order, the camera pointer, the input arguments, and the output arguments. Input arguments will be integral types or const pointers; output arguments will be integral types or non-const pointers. Each call will return a value indicating whether the command completed, or encountered an error. The exemplar function listed on HIS p19 is: CommandName(ReqArgList) -> (ResArgList) This would become, for the Digita library API: DLResult DLCommandName(const ReqArg1 *in1, const ReqArg2 *in2, ..., ResArg1 *out1, ResArg2 *out2, ...); Allocating space for input and output arguments is the responsibility of the caller; the Digita library never allocates-and-returns. The character primitive types PName, DOSName, ShortStr, and String will be represented by C strings (arrays of char). // Low-Level API The Low-level API will provide client code a lower level of access than the Common API. Precisely how it should be structured isn't clear at the moment, but it is clear that *somebody* will eventually voice the comment that "the Common API doesn't do everything I need to" or "doesn't do it the way I want to". The low-level API gives these users the ability to talk directly to the camera. We will probably create the low-level API simply by exposing and documenting a subset of the library's internal functions. // Devices My reading of the HIS is that the protocol is independent of the transport layer. In other words, the NSS, USB, and IrDA versions of the library can be the same except for the code that establishes communication with the camera, and sends and receives messages. Initial development will be with the serial port, but we want to be able to also support USB and IrDA without having to change the API or the internal structure of the library. In C++ this would be easy -- we'd define an abstract class representing the connection to the camera, and defining virtual functions such as readMessage and writeMessage. We can approximate this in C using a struction with function pointers, through which the core library makes calls to read or write the camera. The idea is the same: to provide an abstract interface so that the core library doesn't have to know or care whether what the underlying transport layer is. // Project Name We need a project name. This can be fun, but it can also be kind of contentious, because here opinions will vary the most widely. An ideal project name would combine elements of open-source, camera, digita and/or unix. Or at least suggestions of the same. We should avoid names like "Project 220" because they suggest that we support only the DC220 or only Kodak cameras. We also want to avoid infringing on trademarks, because that brings lawyers, cease-and-desist letters, and other unpleasantness -- and in the end, we'd have to end up changing the project name. Here are the results of my brainstorming on the Project Name issue: "Open Camera" or "Open Camera Initiative". Symbolic but bland. Suggests Open and Camera. A web search turned up no obvious trademarks, but there is an "Open Camera" webcam in Zagreb. "DigitOpen". Suggests Digita and Open. Doesn't really roll off the tongue. "FlashOpen". Suggests Digita (Flashpoint) and Open. But doesn't really suggest cameras. Sounds more like the way a magician opens a box. "Digitalux". My favorite. Suggests Digita and Linux ("-ux"). Rolls off the tongue. Downside: there's a theatre production company called Digitalix. We could probably avoid trademark questions in that the two are spelled differently, and related to different fields. "Talux". A truncation of Digitalux. Cryptic, but catchy. "Project Rochester". Named after Kodak's headquarters. Not directly tied to Kodak, but suggestive of the project origins (which is OK). My least favorite of the project names, but might be recycled as a "code name" for our first release. Subsequent releases could be named for other NY cities: Ithaca, Syracuse, Geneva, Auburn, etc. // Publicity We need to establish a web site to provide information about the project, and to distribute code releases (though we can also allow anonymous access to our CVS repository). The web site does not have to fancy, but should include background information about the project -- our goals and approach (perhaps a rewrite of this document). I have found a site that offers free web support to open-source projects, and as soon as we have selected a project name, I will apply for an account. We also need to set up bug-tracking; the site announced in slashdot recently will do. When we have reliably functioning code, a basic web site, and bug tracking, we can make our first announcement to Freshmeat. // Licensing All the standalone programs should be GNU General Public License (GPL). For libraries, we have the option of choosing the GNU Library General Public License (LGPL). My preference would be to GPL the libraries, but could be persuaded to the LGPL.