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