Archive | libgphoto RSS for this section

The Smallest Things…

For the last few weeks I’ve been banging my head against a problem. I need my Photo Booth application to actually take a photo. It seems like such a simple thing, but it has actually been one of the most difficult ones I’ve encountered. Like the Great PostScript Debacle and the Mystery of the GAsyncQueue Ref before it, I spent a good week banging my head against the wall. I even took a day off to write an entire Lua Camera Module just so I could shell out and call a command line utility to try to work around it.

The best part? If you’ve been following the blog, you know I’m kind of a crybaby about poor documentation. While libgphoto2 is certainly a repeat offender on this count, no amount of documentation could have prepared me for what was to come.

But first, let’s go over my now-working implementation.

Taking A Picture With Libgphoto2

To take a picture, we need 3 functions:

  • gint dmp_cm_camera_init()
  • gint dmp_cm_camera_finalize()
  • gint dmp_cm_camera_capture(gchar * location)

dmp_cm_camera_init

gint dmp_cm_camera_init() { context = gp_context_new(); gp_log_add_func(GP_LOG_ERROR, (GPLogFunc) dmp_cm_log_func, NULL); if (gp_camera_new(&camera) != GP_OK) { //error handling } if (gp_camera_init(camera, context) != GP_OK) { //error handling } return DMP_PB_SUCCESS; }

There are two main structs: Camera and GPContext. A Camera represents, shockingly, a camera attached to the system. A GPContext represents work to be done. Callback functions, data, and other things of that nature.

First we create a new context. Next we can add a log function to accept log messages from libgphoto2. In my experience, no matter what you do you will get a lot of useless garbage output from libgphoto2. For this reason, I recommend you don’t just let this spew to the console or some other user-facing output. At first, I was going to send this to the console queue, but I’ve since decided against using this feature. It is good to know about though in case you need it for troubleshooting.

After all of that is done, we need to create our camera object, and initialize libgphoto2.

dmp_cm_camera_finalize

gint dmp_cm_camera_finalize() { gp_camera_unref(camera); gp_context_unref(context); return DMP_PB_SUCCESS; }

Nothing particularly tricky there. We need to ensure we free our memory when we’re done, so we unref our camera and context. Having seen these two functions, you may be wondering to yourself: “Are we dealing with GObjects here?” Luckily for us, there is a simple test for this:

g_assert(G_IS_OBJECT(camera));

I’ll spare you the effort of running this test: the assertion fails. Too bad really, but it is what it is. Libgphoto2 just uses function names similar to GObject.

dmp_cm_camera_capture

gint dmp_cm_camera_capture(gchar * location) { CameraFile * file; CameraFilePath camera_file_path; gint fd; CameraEventType event_type; void * event_data; if (gp_camera_capture(camera, GP_CAPTURE_IMAGE, &camera_file_path, context) != GP_OK) { //error handling } if ((fd = g_open(location, O_CREAT | O_WRONLY, 0644)) == -1) { //error handling } do { gp_camera_wait_for_event(camera, 1000, &event_type, &event_data, context); if (event_type == GP_EVENT_CAPTURE_COMPLETE) break; } while(event_type != GP_EVENT_TIMEOUT); if (gp_file_new_from_fd(&file, fd) != GP_OK) { //error handling } do { gp_camera_wait_for_event(camera, 1000, &event_type, &event_data, context); } while(event_type != GP_EVENT_TIMEOUT); if (gp_camera_file_get(camera, camera_file_path.folder, camera_file_path.name, GP_FILE_TYPE_NORMAL, file, context) != GP_OK) { //error handling } if (gp_camera_file_delete(camera, camera_file_path.folder, camera_file_path.name, context) != GP_OK) { //error handling } gp_file_free(file); do { gp_camera_wait_for_event(camera, 1000, &event_type, &event_data, context); } while(event_type != GP_EVENT_TIMEOUT); return DMP_PB_SUCCESS; }

This function is where the meat of the process is. First we need to do some housekeeping. We create a CameraFile pointer to represent the actual image file, and a CameraFilePath struct to represent the path to the file. We also create an int for use as a file descriptor, a CameraEventType and void pointer for our calls to gp_cmaera_wait_for_event

Next we call gp_camera_capture which triggers the camera to take a picture. After that is done, we’ll open a file descriptor to save the image. You’ll notice that the call to g_open is enclosed in parentheses. THIS STEP IS 100% MANDATORY Don’t omit it, you’ll be sorry. More on this in a bit.

Next, we wait for the camera to finish working. The camera uses an event system; it will emit events when things happen. After releasing the shutter, the camera has other work to do before it is “done taking the picture”. If you try to do the next step before the camera is ready libgphoto2 will spew garbage to your STDOUT and you’ll have to ctrl+c to fix it. To avoid this, we call gp_camera_wait_for_event while event_type != GP_EVENT_TIMEOUT || GP_EVENT_CAPTURE_COMPLETE Capture complete is obviously the event we care about, but it may have happened while we weren’t listening for it. In that case, we’ll settle for a timeout.

Next up is instantiating our CameraFile. We use our File descriptor that we just opened to call gp_file_new_from_fd. Unfortunately there is no gp_file_new_from_file_pointer which means that this call is POSIX only, and there’s no portable substitute.

After creating our CameraFile we download the image we just took by calling gp_camera_file_get and then delete the file from the camera using gp_camera_file_delete

Finally we make sure no events are pending, then return.

Why Are You Yelling At Me?

Good question. The block in question of course is

if ((fd = g_open(location, O_CREAT | O_WRONLY, 0644)) == -1) { //error handling }

Inside of that if block, I’m assigning a value and testing the result inside of the if statement. This operation is about a 2 out of 10 on the cleverness scale. Normally, you could omit the parentheses around (fd = g_open(location, O_CREAT | O_WRONLY, 0644). However, if we do it here, things go off the rails. Not right away, of course, but a few function calls later we get to:

if (gp_camera_file_get(camera, camera_file_path.folder, camera_file_path.name, GP_FILE_TYPE_NORMAL, file, context) != GP_OK) { //error handling }

As soon as gp_camera_file_get(...) is evaluated, this is spewed to the console:

mystic_runes

…and you have no choice but to kill the process.

Why does this happen? I have no idea. Why does enclosing the call to g_open in parenthesis fix it? Again, no idea. And it only happens here too. I just tried to modify the examples that come with libgphoto2 to reproduce the error and get that screenshot for this post, but it works fine there. Knowing my luck, if you download and build the program, it’ll work fine for you.

As long as it works, I guess…

DMP Camera Module: Shooting For The Moon

So there I was; several hours into my work on the Camera module. I may have mentioned this before, but lack of documentation is a pet peeve of mine. Unfortunately, some times it can’t be avoided. Take libgphoto2. If you click that link, you’ll get taken to a doxygen website. Seems promising, right? Go ahead and poke around, things start to look less rosy as you do. Unfortunately, this seems to be the gold standard of PTP libraries for Linux, so there’s really nothing for it. Right?

Maybe Not

After hours of frustration, I decided to try something crazy. I opened up a command prompt and entered:

gphoto2 --capture-image-and-download

And you know what? My camera took a picture and downloaded it to the current directory. Maybe that’s the answer I’m looking for. DMP Photo Booth doesn’t need to do anything fancy. It just needs to take a picture.

Now, I had been planning to provide modules that call out into Lua to allow people to implement modules in Lua. However, this was always a back-burner project. The sort of thing that happens after version 1.0 is released. But with implementing a libgphoto2 Camera Module seeming like So Much Work, maybe it was time to get on it. At least, for the Camera Module.

dmp_pb_lua_camera_module

So I committed and pushed my work on the Camera Module. I made a copy of it, and removed all the logic. After that, I committed it to the repository. It was officially official.

The first order of business was creating the lua script loader. I needed an init, finalize, and is_initialized function for lua, and a capture function. Let’s take a look:

(I’ve omitted error handling from these examples. If I didn’t they’d be 3 times as long and nobody wants to read that)

gint dmp_cm_lua_initialize() { dmp_cm_state = luaL_newstate(); luaL_openlibs(dmp_cm_state); luaL_loadfile(dmp_cm_state, DMP_CM_MODULE_SCRIPT); lua_pcall(dmp_cm_state, 0, 1, 0); lua_setglobal(dmp_cm_state, DMP_CM_NAMESPACE); lua_getglobal(dmp_cm_state, DMP_CM_NAMESPACE); lua_getfield(dmp_cm_state, -1, DMP_CM_MODULE); lua_pushcfunction(dmp_cm_state, dmp_cm_lua_console_write); lua_setfield(dmp_cm_state, -2, "console_write"); lua_getglobal(dmp_cm_state, DMP_CM_NAMESPACE); lua_getfield(dmp_cm_state, -1, DMP_CM_MODULE); lua_getfield(dmp_cm_state, -1, "initialize"); lua_pcall(dmp_cm_state, 0, 0, 0); is_initialized = TRUE; return DMP_PB_SUCCESS; }

First up is the initialize function. First, I initialize Lua and open the standard library. The call to luaL_loadfile loads the script and pops it onto the stack as a function, which is called by the subsequent call to lua_pcall.

If you’ve been following the blog, you may have noticed that I’m a fan of namespaces. I follow the GLib namespace style and use [NAMESPACE]::[APPLICATION/MODULE]::. I’ve decided that DMP Photo Booth modules implemented in Lua should do this as well. Lua doesn’t have actual namespaces as a language feature, but like most things, they can be approximated using tables. To that end a Lua camera module script should return a table named dmp, which contains a table named cm. In a future version, these will likely be configurable. The module will return the dmp dmp, which is set as a global in the next call.

Next, we must register the console write callback. This is accomplished by getting the dmp.cm table, pushing the console write function, and setting it as a field in dmp.cm.

Next, we get dmp.cm.initialize, and call it.

gint dmp_cm_lua_capture(gchar * location) { lua_getglobal(dmp_cm_state, DMP_CM_NAMESPACE); lua_getfield(dmp_cm_state, -1, DMP_CM_MODULE); lua_getfield(dmp_cm_state, -1, "capture"); lua_pushstring(dmp_cm_state, location); lua_pcall(dmp_cm_state, 1, 0, 0); return DMP_PB_SUCCESS; }

This is the basic method to call a function. First, get the dmp table, then get its cm field. Next, get the function from dmp.cm. After the function is on the stack, we push its arguments onto the stack, and finally we call it. The functions for finalize and is_initialized look strikingly similar, so I’ll spare you.

The Script

The script is extremely simple, thanks to Lua. I can print the whole thing here without editing it, it’s so small:

local dmp = {} dmp.cm = {} function dmp.cm.capture(location) os.execute("gphoto2 --capture-image-and-download" .. "--filename=" .. location) end function dmp.cm.initialize() end function dmp.cm.finalize() end function dmp.cm.is_initialized() return true end return dmp

In the first two lines, we create our dmp.cm namespace tables. Next we define our functions: capture, initialize, finalize, and is_initialized.

Finally, we return our namespace table for use within C. Of the four functions, only capture isn’t a placeholder. In capture, we fork and execute gphoto2, signaling our camera to capture.

How’s That Working Out For Me

Unfortunately, not so great. Well, the Lua module works perfectly. It loads, all functions call without a hitch. And a Lua script is a lot easier to implement than a C module. If only gphoto2 wasn’t so incredibly brittle.

The problem with a command line utility is that you have to count on it to work. Unfortunately, so many things can go wrong with gphoto2. So many errors, so many ways to get into an inconsistent state. Plus, my favorite part about all of this, is that all of this happens by magic! You can do the same thing twice and get different results! Take that Einstein!

No, it seems that my little forray into Lua has come to an end. The Module is live. However, work must re-start on dmp_pb_camera_module. Such a shame…

Introducing DMP Photo Booth

In June of 2014, I will be getting married. One problem: I am currently an unemployed student, and my fiancee Liz is also between jobs. Recent studies show that the average couple in this day and age spends an average of Twenty Four Bajillion Dollars on their wedding. Capital Bajillion. Italicised. Even were I still employed, this would pose a problem for me. Needless to say, we began looking for costs to cut. Liz really wants a photo booth, and I think it sounds fun. Unfortunatley photo booths run from $750-1000 to rent. The solution: DMP Photo Booth.

On Reinventing The Wheel

DMP Photo Booth wasn’t actually my first thought. That would be “well, there must be some open-source photo booth software we can use!” It turns out that there is. People like me who’ve had this issue and whipped something up for themselves. Some of these projects even have fancy websites. Unfortunately, none of these seem to have reached the level of maturity where you can just grab them and go. No, we’re talking old-school Linux status projects. If I’m going to have to put that much effort into making this work, I might as well roll my own. Besides, it will be good experience.

Requirements

The photo booth must do the usual photo booth stuff; it should programatically take 3-4 pictures, arrange them in a vertical strip with a background picture, and print them on photo paper. This should all work with the user only having to press a button(not a key on the laptop, an actual button), and there should be some sort of indicator when the pictures are going to be taken.

Some reasearch turns up the existence of a Picture Transfer Protocol, or PTP, that has been “supported” by the major camera vendors since 2002 or so. PTP allows you to programatically control a digital camera, and should serve nicely. I own a printer that can print on photo paper; it seems likely that I will be able to use the operating system’s printing facilities to handle this. Finally, I will construct a button and indicator thingamabober using Arduino.

Architecture

I have decided to go with a modular architecture. There will be four components: a Camera Module, a Printer Module, a Trigger Module, and the Core Application.

Core

The Core Application will bring the GUI, tenatively planned to be implemented using GTK+3, and will interface with the component modules. The core expects the component modules to implement specific functions that will be called to handle their operation. The component modules will be dynamic libraries that can be swapped out at runtime.

Camera Module

The Camera Module will handle the operation of the camera. The Camera Module currently is expected to implement two functions:

int dmp_cm_capture(); int dmp_cm_download(char * location);

These two functions do what they say: the first takes a picture, and the second downloads the picture to the passed-in path. The reference Camera Module will use libgphoto2 to implement these functions, but this module exists to provide the capability to use any method. A module that uses some other PTP library, or some custom protocol, or a dummy module that uses a picture on the filesystem, or uses a scanner, or anything else can be swapped in at runtime and this will all be transparent to the Core.

Printer Module

Shockingly, the Printer Module will handle printing. The Printer Module is currently expected to implement one function:

int dmp_pm_print(char * to_print);

This function prints the file at the path that is passed into the function. This module prevents the Core from needing to know how to print. The Core tells the Printer Module to print, and the Printer Module can figure out how to print in Linux, or Mac OSX, or how to print to a Game Boy Printer, or whatever. The Core doesn’t care.

Trigger Module

The Trigger Module is the module that knows how to operate the custom photo booth equipment. The Trigger Module currently is expected to implement two functions:

int dmp_tm_add_trigger_handler(void (*th)()); int dmp_tm_set_countdown(int current);

The first function adds a callback function that will be called by the Trigger Module when it detects that the button has been pressed. The second function updates the countdown indicator. Since some dealybopper that I made out of Arduino is basically the definition of non-portable, I decided to create a module for it. The reference implementation will be written for my equipment, but this module can be replaced with one that uses some other input device with minimal effort.

Moving Forward

DMP Photo Booth represents my first major open source project, and it has many moving parts. With this groundwork laid, I have broken the project down into more manageable chunks. I have four main components that each represent different challenges: GUI programming in the Core, poorly documented mystery libraries in the Camera Module, Learning to Arduino to finish the Trigger Module, and learning the Linux printing system for the Printer Module.

Rome wasn’t built in a day, but it was started in one. There will surely be many challenges and roadblocks on the way. Expect to hear all about them here!

%d bloggers like this: