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
13pub 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 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 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 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 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 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 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 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 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 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
167pub struct CameraFile {
169 inner: ::gphoto2::CameraFilePath,
170}
171
172impl CameraFile {
173 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 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}