gphoto/
camera.rs

1use std::borrow::Cow;
2use std::ffi::CStr;
3use std::mem;
4
5use ::context::Context;
6use ::abilities::Abilities;
7use ::media::Media;
8use ::port::Port;
9use ::storage::Storage;
10
11use ::handle::prelude::*;
12
13/// A structure representing a camera connected to the system.
14pub struct Camera {
15    camera: *mut ::gphoto2::Camera,
16}
17
18impl Drop for Camera {
19    fn drop(&mut self) {
20        unsafe {
21            ::gphoto2::gp_camera_unref(self.camera);
22        }
23    }
24}
25
26impl Camera {
27    /// Opens the first detected camera.
28    pub fn autodetect(context: &mut Context) -> ::Result<Self> {
29        let mut ptr = unsafe { mem::uninitialized() };
30
31        try_unsafe!(::gphoto2::gp_camera_new(&mut ptr));
32
33        let camera = Camera { camera: ptr };
34
35        try_unsafe!(::gphoto2::gp_camera_init(camera.camera, context.as_mut_ptr()));
36
37        Ok(camera)
38    }
39
40    /// Captures an image.
41    pub fn capture_image(&mut self, context: &mut Context) -> ::Result<CameraFile> {
42        let mut file_path = unsafe { mem::uninitialized() };
43
44        try_unsafe! {
45            ::gphoto2::gp_camera_capture(self.camera,
46                                         ::gphoto2::GP_CAPTURE_IMAGE,
47                                         &mut file_path,
48                                         context.as_mut_ptr())
49        };
50
51        Ok(CameraFile { inner: file_path })
52    }
53
54    /// Downloads a file from the camera.
55    pub fn download<T: Media>(&mut self, context: &mut Context, source: &CameraFile, destination: &mut T) -> ::Result<()> {
56        try_unsafe! {
57            ::gphoto2::gp_camera_file_get(self.camera,
58                                          source.inner.folder.as_ptr(),
59                                          source.inner.name.as_ptr(),
60                                          ::gphoto2::GP_FILE_TYPE_NORMAL,
61                                          destination.as_mut_ptr(),
62                                          context.as_mut_ptr())
63        };
64
65        Ok(())
66    }
67
68    /// Returns information about the port the camera is connected to.
69    pub fn port<'a>(&'a self) -> Port<'a> {
70        let mut ptr = unsafe { mem::uninitialized() };
71
72        unsafe {
73            assert_eq!(::gphoto2::GP_OK, ::gphoto2::gp_camera_get_port_info(self.camera, &mut ptr));
74        }
75
76        ::port::from_libgphoto2(self, ptr)
77    }
78
79    /// Retrieves the camera's abilities.
80    pub fn abilities(&self) -> Abilities {
81        let mut abilities = unsafe { mem::uninitialized() };
82
83        unsafe {
84            assert_eq!(::gphoto2::GP_OK, ::gphoto2::gp_camera_get_abilities(self.camera, &mut abilities));
85        }
86
87        ::abilities::from_libgphoto2(abilities)
88    }
89
90    /// Retrieves information about the camera's storage.
91    ///
92    /// Returns a `Vec` containing one `Storage` for each filesystem on the device.
93    pub fn storage(&mut self, context: &mut Context) -> ::Result<Vec<Storage>> {
94        let mut ptr = unsafe { mem::uninitialized() };
95        let mut len = unsafe { mem::uninitialized() };
96
97        try_unsafe! {
98            ::gphoto2::gp_camera_get_storageinfo(self.camera,
99                                                 &mut ptr,
100                                                 &mut len,
101                                                 context.as_mut_ptr())
102        };
103
104        let storage = ptr as *mut Storage;
105        let length = len as usize;
106
107        Ok(unsafe { Vec::from_raw_parts(storage, length, length) })
108    }
109
110    /// Returns the camera's summary.
111    ///
112    /// The summary typically contains non-configurable information about the camera, such as
113    /// manufacturer and number of pictures taken.
114    ///
115    /// ## Errors
116    ///
117    /// This function returns an error if the summary could not be retrieved:
118    ///
119    /// * `NotSupported` if there is no summary available for the camera.
120    /// * `CorruptedData` if the summary is invalid UTF-8.
121    pub fn summary(&mut self, context: &mut Context) -> ::Result<String> {
122        let mut summary = unsafe { mem::uninitialized() };
123
124        try_unsafe!(::gphoto2::gp_camera_get_summary(self.camera, &mut summary, context.as_mut_ptr()));
125
126        util::camera_text_to_string(summary)
127    }
128
129    /// Returns the camera's manual.
130    ///
131    /// The manual contains information about using the camera.
132    ///
133    /// ## Errors
134    ///
135    /// This function returns an error if the manual could not be retrieved:
136    ///
137    /// * `NotSupported` if there is no manual available for the camera.
138    /// * `CorruptedData` if the summary is invalid UTF-8.
139    pub fn manual(&mut self, context: &mut Context) -> ::Result<String> {
140        let mut manual = unsafe { mem::uninitialized() };
141
142        try_unsafe!(::gphoto2::gp_camera_get_manual(self.camera, &mut manual, context.as_mut_ptr()));
143
144        util::camera_text_to_string(manual)
145    }
146
147    /// Returns information about the camera driver.
148    ///
149    /// This text typically contains information about the driver's author, acknowledgements, etc.
150    ///
151    /// ## Errors
152    ///
153    /// This function returns an error if the about text could not be retrieved:
154    ///
155    /// * `NotSupported` if there is no about text available for the camera's driver.
156    /// * `CorruptedData` if the summary is invalid UTF-8.
157    pub fn about_driver(&mut self, context: &mut Context) -> ::Result<String> {
158        let mut about = unsafe { mem::uninitialized() };
159
160        try_unsafe!(::gphoto2::gp_camera_get_about(self.camera, &mut about, context.as_mut_ptr()));
161
162        util::camera_text_to_string(about)
163    }
164}
165
166
167/// A file stored on a camera's storage.
168pub struct CameraFile {
169    inner: ::gphoto2::CameraFilePath,
170}
171
172impl CameraFile {
173    /// Returns the directory that the file is stored in.
174    pub fn directory(&self) -> Cow<str> {
175        unsafe {
176            String::from_utf8_lossy(CStr::from_ptr(self.inner.folder.as_ptr()).to_bytes())
177        }
178    }
179
180    /// Returns the name of the file without the directory.
181    pub fn basename(&self) -> Cow<str> {
182        unsafe {
183            String::from_utf8_lossy(CStr::from_ptr(self.inner.name.as_ptr()).to_bytes())
184        }
185    }
186}
187
188mod util {
189    use std::ffi::CStr;
190
191    pub fn camera_text_to_string(mut camera_text: ::gphoto2::CameraText) -> ::Result<String> {
192        let length = unsafe {
193            CStr::from_ptr(camera_text.text.as_ptr()).to_bytes().len()
194        };
195
196        let vec = unsafe {
197            Vec::<u8>::from_raw_parts(camera_text.text.as_mut_ptr() as *mut u8, length, camera_text.text.len())
198        };
199
200        String::from_utf8(vec).map_err(|_| {
201            ::error::from_libgphoto2(::gphoto2::GP_ERROR_CORRUPTED_DATA)
202        })
203    }
204}