1use crate::{
6 ffi, AsyncResult, Cancellable, Drive, File, Icon, Mount, MountMountFlags, MountOperation,
7 MountUnmountFlags,
8};
9use glib::{
10 object::ObjectType as _,
11 prelude::*,
12 signal::{connect_raw, SignalHandlerId},
13 translate::*,
14};
15use std::{boxed::Box as Box_, pin::Pin};
16
17glib::wrapper! {
18 #[doc(alias = "GVolume")]
19 pub struct Volume(Interface<ffi::GVolume, ffi::GVolumeIface>);
20
21 match fn {
22 type_ => || ffi::g_volume_get_type(),
23 }
24}
25
26impl Volume {
27 pub const NONE: Option<&'static Volume> = None;
28}
29
30pub trait VolumeExt: IsA<Volume> + 'static {
31 #[doc(alias = "g_volume_can_eject")]
32 fn can_eject(&self) -> bool {
33 unsafe { from_glib(ffi::g_volume_can_eject(self.as_ref().to_glib_none().0)) }
34 }
35
36 #[doc(alias = "g_volume_can_mount")]
37 fn can_mount(&self) -> bool {
38 unsafe { from_glib(ffi::g_volume_can_mount(self.as_ref().to_glib_none().0)) }
39 }
40
41 #[doc(alias = "g_volume_eject_with_operation")]
42 fn eject_with_operation<P: FnOnce(Result<(), glib::Error>) + 'static>(
43 &self,
44 flags: MountUnmountFlags,
45 mount_operation: Option<&impl IsA<MountOperation>>,
46 cancellable: Option<&impl IsA<Cancellable>>,
47 callback: P,
48 ) {
49 let main_context = glib::MainContext::ref_thread_default();
50 let is_main_context_owner = main_context.is_owner();
51 let has_acquired_main_context = (!is_main_context_owner)
52 .then(|| main_context.acquire().ok())
53 .flatten();
54 assert!(
55 is_main_context_owner || has_acquired_main_context.is_some(),
56 "Async operations only allowed if the thread is owning the MainContext"
57 );
58
59 let user_data: Box_<glib::thread_guard::ThreadGuard<P>> =
60 Box_::new(glib::thread_guard::ThreadGuard::new(callback));
61 unsafe extern "C" fn eject_with_operation_trampoline<
62 P: FnOnce(Result<(), glib::Error>) + 'static,
63 >(
64 _source_object: *mut glib::gobject_ffi::GObject,
65 res: *mut crate::ffi::GAsyncResult,
66 user_data: glib::ffi::gpointer,
67 ) {
68 let mut error = std::ptr::null_mut();
69 ffi::g_volume_eject_with_operation_finish(_source_object as *mut _, res, &mut error);
70 let result = if error.is_null() {
71 Ok(())
72 } else {
73 Err(from_glib_full(error))
74 };
75 let callback: Box_<glib::thread_guard::ThreadGuard<P>> =
76 Box_::from_raw(user_data as *mut _);
77 let callback: P = callback.into_inner();
78 callback(result);
79 }
80 let callback = eject_with_operation_trampoline::<P>;
81 unsafe {
82 ffi::g_volume_eject_with_operation(
83 self.as_ref().to_glib_none().0,
84 flags.into_glib(),
85 mount_operation.map(|p| p.as_ref()).to_glib_none().0,
86 cancellable.map(|p| p.as_ref()).to_glib_none().0,
87 Some(callback),
88 Box_::into_raw(user_data) as *mut _,
89 );
90 }
91 }
92
93 fn eject_with_operation_future(
94 &self,
95 flags: MountUnmountFlags,
96 mount_operation: Option<&(impl IsA<MountOperation> + Clone + 'static)>,
97 ) -> Pin<Box_<dyn std::future::Future<Output = Result<(), glib::Error>> + 'static>> {
98 let mount_operation = mount_operation.map(ToOwned::to_owned);
99 Box_::pin(crate::GioFuture::new(
100 self,
101 move |obj, cancellable, send| {
102 obj.eject_with_operation(
103 flags,
104 mount_operation.as_ref().map(::std::borrow::Borrow::borrow),
105 Some(cancellable),
106 move |res| {
107 send.resolve(res);
108 },
109 );
110 },
111 ))
112 }
113
114 #[doc(alias = "g_volume_enumerate_identifiers")]
115 fn enumerate_identifiers(&self) -> Vec<glib::GString> {
116 unsafe {
117 FromGlibPtrContainer::from_glib_full(ffi::g_volume_enumerate_identifiers(
118 self.as_ref().to_glib_none().0,
119 ))
120 }
121 }
122
123 #[doc(alias = "g_volume_get_activation_root")]
124 #[doc(alias = "get_activation_root")]
125 fn activation_root(&self) -> Option<File> {
126 unsafe {
127 from_glib_full(ffi::g_volume_get_activation_root(
128 self.as_ref().to_glib_none().0,
129 ))
130 }
131 }
132
133 #[doc(alias = "g_volume_get_drive")]
134 #[doc(alias = "get_drive")]
135 fn drive(&self) -> Option<Drive> {
136 unsafe { from_glib_full(ffi::g_volume_get_drive(self.as_ref().to_glib_none().0)) }
137 }
138
139 #[doc(alias = "g_volume_get_icon")]
140 #[doc(alias = "get_icon")]
141 fn icon(&self) -> Icon {
142 unsafe { from_glib_full(ffi::g_volume_get_icon(self.as_ref().to_glib_none().0)) }
143 }
144
145 #[doc(alias = "g_volume_get_identifier")]
146 #[doc(alias = "get_identifier")]
147 fn identifier(&self, kind: &str) -> Option<glib::GString> {
148 unsafe {
149 from_glib_full(ffi::g_volume_get_identifier(
150 self.as_ref().to_glib_none().0,
151 kind.to_glib_none().0,
152 ))
153 }
154 }
155
156 #[doc(alias = "g_volume_get_mount")]
157 fn get_mount(&self) -> Option<Mount> {
158 unsafe { from_glib_full(ffi::g_volume_get_mount(self.as_ref().to_glib_none().0)) }
159 }
160
161 #[doc(alias = "g_volume_get_name")]
162 #[doc(alias = "get_name")]
163 fn name(&self) -> glib::GString {
164 unsafe { from_glib_full(ffi::g_volume_get_name(self.as_ref().to_glib_none().0)) }
165 }
166
167 #[doc(alias = "g_volume_get_sort_key")]
168 #[doc(alias = "get_sort_key")]
169 fn sort_key(&self) -> Option<glib::GString> {
170 unsafe { from_glib_none(ffi::g_volume_get_sort_key(self.as_ref().to_glib_none().0)) }
171 }
172
173 #[doc(alias = "g_volume_get_symbolic_icon")]
174 #[doc(alias = "get_symbolic_icon")]
175 fn symbolic_icon(&self) -> Icon {
176 unsafe {
177 from_glib_full(ffi::g_volume_get_symbolic_icon(
178 self.as_ref().to_glib_none().0,
179 ))
180 }
181 }
182
183 #[doc(alias = "g_volume_get_uuid")]
184 #[doc(alias = "get_uuid")]
185 fn uuid(&self) -> Option<glib::GString> {
186 unsafe { from_glib_full(ffi::g_volume_get_uuid(self.as_ref().to_glib_none().0)) }
187 }
188
189 #[doc(alias = "g_volume_mount")]
190 fn mount<P: FnOnce(Result<(), glib::Error>) + 'static>(
191 &self,
192 flags: MountMountFlags,
193 mount_operation: Option<&impl IsA<MountOperation>>,
194 cancellable: Option<&impl IsA<Cancellable>>,
195 callback: P,
196 ) {
197 let main_context = glib::MainContext::ref_thread_default();
198 let is_main_context_owner = main_context.is_owner();
199 let has_acquired_main_context = (!is_main_context_owner)
200 .then(|| main_context.acquire().ok())
201 .flatten();
202 assert!(
203 is_main_context_owner || has_acquired_main_context.is_some(),
204 "Async operations only allowed if the thread is owning the MainContext"
205 );
206
207 let user_data: Box_<glib::thread_guard::ThreadGuard<P>> =
208 Box_::new(glib::thread_guard::ThreadGuard::new(callback));
209 unsafe extern "C" fn mount_trampoline<P: FnOnce(Result<(), glib::Error>) + 'static>(
210 _source_object: *mut glib::gobject_ffi::GObject,
211 res: *mut crate::ffi::GAsyncResult,
212 user_data: glib::ffi::gpointer,
213 ) {
214 let mut error = std::ptr::null_mut();
215 ffi::g_volume_mount_finish(_source_object as *mut _, res, &mut error);
216 let result = if error.is_null() {
217 Ok(())
218 } else {
219 Err(from_glib_full(error))
220 };
221 let callback: Box_<glib::thread_guard::ThreadGuard<P>> =
222 Box_::from_raw(user_data as *mut _);
223 let callback: P = callback.into_inner();
224 callback(result);
225 }
226 let callback = mount_trampoline::<P>;
227 unsafe {
228 ffi::g_volume_mount(
229 self.as_ref().to_glib_none().0,
230 flags.into_glib(),
231 mount_operation.map(|p| p.as_ref()).to_glib_none().0,
232 cancellable.map(|p| p.as_ref()).to_glib_none().0,
233 Some(callback),
234 Box_::into_raw(user_data) as *mut _,
235 );
236 }
237 }
238
239 fn mount_future(
240 &self,
241 flags: MountMountFlags,
242 mount_operation: Option<&(impl IsA<MountOperation> + Clone + 'static)>,
243 ) -> Pin<Box_<dyn std::future::Future<Output = Result<(), glib::Error>> + 'static>> {
244 let mount_operation = mount_operation.map(ToOwned::to_owned);
245 Box_::pin(crate::GioFuture::new(
246 self,
247 move |obj, cancellable, send| {
248 obj.mount(
249 flags,
250 mount_operation.as_ref().map(::std::borrow::Borrow::borrow),
251 Some(cancellable),
252 move |res| {
253 send.resolve(res);
254 },
255 );
256 },
257 ))
258 }
259
260 #[doc(alias = "g_volume_should_automount")]
261 fn should_automount(&self) -> bool {
262 unsafe {
263 from_glib(ffi::g_volume_should_automount(
264 self.as_ref().to_glib_none().0,
265 ))
266 }
267 }
268
269 #[doc(alias = "changed")]
270 fn connect_changed<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId {
271 unsafe extern "C" fn changed_trampoline<P: IsA<Volume>, F: Fn(&P) + 'static>(
272 this: *mut ffi::GVolume,
273 f: glib::ffi::gpointer,
274 ) {
275 let f: &F = &*(f as *const F);
276 f(Volume::from_glib_borrow(this).unsafe_cast_ref())
277 }
278 unsafe {
279 let f: Box_<F> = Box_::new(f);
280 connect_raw(
281 self.as_ptr() as *mut _,
282 c"changed".as_ptr() as *const _,
283 Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
284 changed_trampoline::<Self, F> as *const (),
285 )),
286 Box_::into_raw(f),
287 )
288 }
289 }
290
291 #[doc(alias = "removed")]
292 fn connect_removed<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId {
293 unsafe extern "C" fn removed_trampoline<P: IsA<Volume>, F: Fn(&P) + 'static>(
294 this: *mut ffi::GVolume,
295 f: glib::ffi::gpointer,
296 ) {
297 let f: &F = &*(f as *const F);
298 f(Volume::from_glib_borrow(this).unsafe_cast_ref())
299 }
300 unsafe {
301 let f: Box_<F> = Box_::new(f);
302 connect_raw(
303 self.as_ptr() as *mut _,
304 c"removed".as_ptr() as *const _,
305 Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
306 removed_trampoline::<Self, F> as *const (),
307 )),
308 Box_::into_raw(f),
309 )
310 }
311 }
312}
313
314impl<O: IsA<Volume>> VolumeExt for O {}