Well, I could always try doing it with ctypes.
From the docs:
ctypes is a foreign function library for Python. It provides C compatible data types, and allows calling functions in DLLs or shared libraries. It can be used to wrap these libraries in pure Python.
Note: I haven't done any serious stuff with ctypes nor gphoto before so if you find any errors etc please post a comment.
It amazed my how easy it is to use ctypes. Here's a snippet that will take a picture (from the first camera found), download the image to local storage and then delete it from the camera's storage.
import ctypes
import os
# gphoto structures
""" From 'gphoto2-camera.h'
typedef struct {
char name [128];
char folder [1024];
} CameraFilePath;
"""
class CameraFilePath(ctypes.Structure):
_fields_ = [('name', (ctypes.c_char * 128)),
('folder', (ctypes.c_char * 1024))]
# gphoto constants
# Defined in 'gphoto2-port-result.h'
GP_OK = 0
# CameraCaptureType enum in 'gphoto2-camera.h'
GP_CAPTURE_IMAGE = 0
# CameraFileType enum in 'gphoto2-file.h'
GP_FILE_TYPE_NORMAL = 1
# Load library
gp = ctypes.CDLL('libgphoto2.so.2')
# Init camera
context = gp.gp_context_new()
camera = ctypes.c_void_p()
gp.gp_camera_new(ctypes.pointer(camera))
gp.gp_camera_init(camera, context)
# Capture image
cam_path = CameraFilePath()
gp.gp_camera_capture(camera,
GP_CAPTURE_IMAGE,
ctypes.pointer(cam_path),
context)
# Download and delete
cam_file = ctypes.c_void_p()
fd = os.open('image.jpg', os.O_CREAT | os.O_WRONLY)
gp.gp_file_new_from_fd(ctypes.pointer(cam_file), fd)
gp.gp_camera_file_get(camera,
cam_path.folder,
cam_path.name,
GP_FILE_TYPE_NORMAL,
cam_file,
context)
gp.gp_camera_file_delete(camera,
cam_path.folder,
cam_path.name,
context)
gp.gp_file_unref(cam_file)
# Release the camera
gp.gp_camera_exit(camera, context)
gp.gp_camera_unref(camera)
Ok, remember that I haven't done any wrapper or anything, it almost looks like 'C' code. I have also skipped all error checking for brevity.You can always use a c_void_p if you don't need access to the data in Python (if you only need to pass a pointer between foreign functions). I'm using c_void_p instead of defining ctypes structures for gphoto's data types such as Camera and CameraFile. I still had to define CameraFilePath since I needed access to the data in Python.
I really like ctypes because I don't have to maintain code in C to access native functionality. Maybe you won't get the same performance as with traditional bindings but in this particular case it's not an issue.
That's interesting. Do you have a link to the article you read about controlling the camera with gphoto?
ReplyDeleteAlso can you do other remote control things like snap a photo?
Actually, my "app" takes snapshots, the gp_camera_capture() function tells the camera to take a picture, if that is what you mean?
ReplyDeleteThe article was published in Linux Magazine (the paper magazine) but I found the article in their archive: http://www.linux-magazine.com/w3/issue/109/070-071_gphoto.pdf
This comment has been removed by a blog administrator.
ReplyDelete