1use crate::{
6 AsyncResult, Cancellable, DriveStartFlags, DriveStartStopType, Icon, MountOperation,
7 MountUnmountFlags, Volume, ffi,
8};
9use glib::{
10 object::ObjectType as _,
11 prelude::*,
12 signal::{SignalHandlerId, connect_raw},
13 translate::*,
14};
15use std::{boxed::Box as Box_, pin::Pin};
16
17glib::wrapper! {
18 #[doc(alias = "GDrive")]
19 pub struct Drive(Interface<ffi::GDrive, ffi::GDriveIface>);
20
21 match fn {
22 type_ => || ffi::g_drive_get_type(),
23 }
24}
25
26impl Drive {
27 pub const NONE: Option<&'static Drive> = None;
28}
29
30pub trait DriveExt: IsA<Drive> + 'static {
31 #[doc(alias = "g_drive_can_eject")]
32 fn can_eject(&self) -> bool {
33 unsafe { from_glib(ffi::g_drive_can_eject(self.as_ref().to_glib_none().0)) }
34 }
35
36 #[doc(alias = "g_drive_can_poll_for_media")]
37 fn can_poll_for_media(&self) -> bool {
38 unsafe {
39 from_glib(ffi::g_drive_can_poll_for_media(
40 self.as_ref().to_glib_none().0,
41 ))
42 }
43 }
44
45 #[doc(alias = "g_drive_can_start")]
46 fn can_start(&self) -> bool {
47 unsafe { from_glib(ffi::g_drive_can_start(self.as_ref().to_glib_none().0)) }
48 }
49
50 #[doc(alias = "g_drive_can_start_degraded")]
51 fn can_start_degraded(&self) -> bool {
52 unsafe {
53 from_glib(ffi::g_drive_can_start_degraded(
54 self.as_ref().to_glib_none().0,
55 ))
56 }
57 }
58
59 #[doc(alias = "g_drive_can_stop")]
60 fn can_stop(&self) -> bool {
61 unsafe { from_glib(ffi::g_drive_can_stop(self.as_ref().to_glib_none().0)) }
62 }
63
64 #[doc(alias = "g_drive_eject_with_operation")]
65 fn eject_with_operation<P: FnOnce(Result<(), glib::Error>) + 'static>(
66 &self,
67 flags: MountUnmountFlags,
68 mount_operation: Option<&impl IsA<MountOperation>>,
69 cancellable: Option<&impl IsA<Cancellable>>,
70 callback: P,
71 ) {
72 let main_context = glib::MainContext::ref_thread_default();
73 let is_main_context_owner = main_context.is_owner();
74 let has_acquired_main_context = (!is_main_context_owner)
75 .then(|| main_context.acquire().ok())
76 .flatten();
77 assert!(
78 is_main_context_owner || has_acquired_main_context.is_some(),
79 "Async operations only allowed if the thread is owning the MainContext"
80 );
81
82 let user_data: Box_<glib::thread_guard::ThreadGuard<P>> =
83 Box_::new(glib::thread_guard::ThreadGuard::new(callback));
84 unsafe extern "C" fn eject_with_operation_trampoline<
85 P: FnOnce(Result<(), glib::Error>) + 'static,
86 >(
87 _source_object: *mut glib::gobject_ffi::GObject,
88 res: *mut crate::ffi::GAsyncResult,
89 user_data: glib::ffi::gpointer,
90 ) {
91 unsafe {
92 let mut error = std::ptr::null_mut();
93 ffi::g_drive_eject_with_operation_finish(_source_object as *mut _, res, &mut error);
94 let result = if error.is_null() {
95 Ok(())
96 } else {
97 Err(from_glib_full(error))
98 };
99 let callback: Box_<glib::thread_guard::ThreadGuard<P>> =
100 Box_::from_raw(user_data as *mut _);
101 let callback: P = callback.into_inner();
102 callback(result);
103 }
104 }
105 let callback = eject_with_operation_trampoline::<P>;
106 unsafe {
107 ffi::g_drive_eject_with_operation(
108 self.as_ref().to_glib_none().0,
109 flags.into_glib(),
110 mount_operation.map(|p| p.as_ref()).to_glib_none().0,
111 cancellable.map(|p| p.as_ref()).to_glib_none().0,
112 Some(callback),
113 Box_::into_raw(user_data) as *mut _,
114 );
115 }
116 }
117
118 fn eject_with_operation_future(
119 &self,
120 flags: MountUnmountFlags,
121 mount_operation: Option<&(impl IsA<MountOperation> + Clone + 'static)>,
122 ) -> Pin<Box_<dyn std::future::Future<Output = Result<(), glib::Error>> + 'static>> {
123 let mount_operation = mount_operation.map(ToOwned::to_owned);
124 Box_::pin(crate::GioFuture::new(
125 self,
126 move |obj, cancellable, send| {
127 obj.eject_with_operation(
128 flags,
129 mount_operation.as_ref().map(::std::borrow::Borrow::borrow),
130 Some(cancellable),
131 move |res| {
132 send.resolve(res);
133 },
134 );
135 },
136 ))
137 }
138
139 #[doc(alias = "g_drive_enumerate_identifiers")]
140 fn enumerate_identifiers(&self) -> Vec<glib::GString> {
141 unsafe {
142 FromGlibPtrContainer::from_glib_full(ffi::g_drive_enumerate_identifiers(
143 self.as_ref().to_glib_none().0,
144 ))
145 }
146 }
147
148 #[doc(alias = "g_drive_get_icon")]
149 #[doc(alias = "get_icon")]
150 fn icon(&self) -> Icon {
151 unsafe { from_glib_full(ffi::g_drive_get_icon(self.as_ref().to_glib_none().0)) }
152 }
153
154 #[doc(alias = "g_drive_get_identifier")]
155 #[doc(alias = "get_identifier")]
156 fn identifier(&self, kind: &str) -> Option<glib::GString> {
157 unsafe {
158 from_glib_full(ffi::g_drive_get_identifier(
159 self.as_ref().to_glib_none().0,
160 kind.to_glib_none().0,
161 ))
162 }
163 }
164
165 #[doc(alias = "g_drive_get_name")]
166 #[doc(alias = "get_name")]
167 fn name(&self) -> glib::GString {
168 unsafe { from_glib_full(ffi::g_drive_get_name(self.as_ref().to_glib_none().0)) }
169 }
170
171 #[doc(alias = "g_drive_get_sort_key")]
172 #[doc(alias = "get_sort_key")]
173 fn sort_key(&self) -> Option<glib::GString> {
174 unsafe { from_glib_none(ffi::g_drive_get_sort_key(self.as_ref().to_glib_none().0)) }
175 }
176
177 #[doc(alias = "g_drive_get_start_stop_type")]
178 #[doc(alias = "get_start_stop_type")]
179 fn start_stop_type(&self) -> DriveStartStopType {
180 unsafe {
181 from_glib(ffi::g_drive_get_start_stop_type(
182 self.as_ref().to_glib_none().0,
183 ))
184 }
185 }
186
187 #[doc(alias = "g_drive_get_symbolic_icon")]
188 #[doc(alias = "get_symbolic_icon")]
189 fn symbolic_icon(&self) -> Icon {
190 unsafe {
191 from_glib_full(ffi::g_drive_get_symbolic_icon(
192 self.as_ref().to_glib_none().0,
193 ))
194 }
195 }
196
197 #[doc(alias = "g_drive_get_volumes")]
198 #[doc(alias = "get_volumes")]
199 fn volumes(&self) -> Vec<Volume> {
200 unsafe {
201 FromGlibPtrContainer::from_glib_full(ffi::g_drive_get_volumes(
202 self.as_ref().to_glib_none().0,
203 ))
204 }
205 }
206
207 #[doc(alias = "g_drive_has_media")]
208 fn has_media(&self) -> bool {
209 unsafe { from_glib(ffi::g_drive_has_media(self.as_ref().to_glib_none().0)) }
210 }
211
212 #[doc(alias = "g_drive_has_volumes")]
213 fn has_volumes(&self) -> bool {
214 unsafe { from_glib(ffi::g_drive_has_volumes(self.as_ref().to_glib_none().0)) }
215 }
216
217 #[doc(alias = "g_drive_is_media_check_automatic")]
218 fn is_media_check_automatic(&self) -> bool {
219 unsafe {
220 from_glib(ffi::g_drive_is_media_check_automatic(
221 self.as_ref().to_glib_none().0,
222 ))
223 }
224 }
225
226 #[doc(alias = "g_drive_is_media_removable")]
227 fn is_media_removable(&self) -> bool {
228 unsafe {
229 from_glib(ffi::g_drive_is_media_removable(
230 self.as_ref().to_glib_none().0,
231 ))
232 }
233 }
234
235 #[doc(alias = "g_drive_is_removable")]
236 fn is_removable(&self) -> bool {
237 unsafe { from_glib(ffi::g_drive_is_removable(self.as_ref().to_glib_none().0)) }
238 }
239
240 #[doc(alias = "g_drive_poll_for_media")]
241 fn poll_for_media<P: FnOnce(Result<(), glib::Error>) + 'static>(
242 &self,
243 cancellable: Option<&impl IsA<Cancellable>>,
244 callback: P,
245 ) {
246 let main_context = glib::MainContext::ref_thread_default();
247 let is_main_context_owner = main_context.is_owner();
248 let has_acquired_main_context = (!is_main_context_owner)
249 .then(|| main_context.acquire().ok())
250 .flatten();
251 assert!(
252 is_main_context_owner || has_acquired_main_context.is_some(),
253 "Async operations only allowed if the thread is owning the MainContext"
254 );
255
256 let user_data: Box_<glib::thread_guard::ThreadGuard<P>> =
257 Box_::new(glib::thread_guard::ThreadGuard::new(callback));
258 unsafe extern "C" fn poll_for_media_trampoline<
259 P: FnOnce(Result<(), glib::Error>) + 'static,
260 >(
261 _source_object: *mut glib::gobject_ffi::GObject,
262 res: *mut crate::ffi::GAsyncResult,
263 user_data: glib::ffi::gpointer,
264 ) {
265 unsafe {
266 let mut error = std::ptr::null_mut();
267 ffi::g_drive_poll_for_media_finish(_source_object as *mut _, res, &mut error);
268 let result = if error.is_null() {
269 Ok(())
270 } else {
271 Err(from_glib_full(error))
272 };
273 let callback: Box_<glib::thread_guard::ThreadGuard<P>> =
274 Box_::from_raw(user_data as *mut _);
275 let callback: P = callback.into_inner();
276 callback(result);
277 }
278 }
279 let callback = poll_for_media_trampoline::<P>;
280 unsafe {
281 ffi::g_drive_poll_for_media(
282 self.as_ref().to_glib_none().0,
283 cancellable.map(|p| p.as_ref()).to_glib_none().0,
284 Some(callback),
285 Box_::into_raw(user_data) as *mut _,
286 );
287 }
288 }
289
290 fn poll_for_media_future(
291 &self,
292 ) -> Pin<Box_<dyn std::future::Future<Output = Result<(), glib::Error>> + 'static>> {
293 Box_::pin(crate::GioFuture::new(
294 self,
295 move |obj, cancellable, send| {
296 obj.poll_for_media(Some(cancellable), move |res| {
297 send.resolve(res);
298 });
299 },
300 ))
301 }
302
303 #[doc(alias = "g_drive_start")]
304 fn start<P: FnOnce(Result<(), glib::Error>) + 'static>(
305 &self,
306 flags: DriveStartFlags,
307 mount_operation: Option<&impl IsA<MountOperation>>,
308 cancellable: Option<&impl IsA<Cancellable>>,
309 callback: P,
310 ) {
311 let main_context = glib::MainContext::ref_thread_default();
312 let is_main_context_owner = main_context.is_owner();
313 let has_acquired_main_context = (!is_main_context_owner)
314 .then(|| main_context.acquire().ok())
315 .flatten();
316 assert!(
317 is_main_context_owner || has_acquired_main_context.is_some(),
318 "Async operations only allowed if the thread is owning the MainContext"
319 );
320
321 let user_data: Box_<glib::thread_guard::ThreadGuard<P>> =
322 Box_::new(glib::thread_guard::ThreadGuard::new(callback));
323 unsafe extern "C" fn start_trampoline<P: FnOnce(Result<(), glib::Error>) + 'static>(
324 _source_object: *mut glib::gobject_ffi::GObject,
325 res: *mut crate::ffi::GAsyncResult,
326 user_data: glib::ffi::gpointer,
327 ) {
328 unsafe {
329 let mut error = std::ptr::null_mut();
330 ffi::g_drive_start_finish(_source_object as *mut _, res, &mut error);
331 let result = if error.is_null() {
332 Ok(())
333 } else {
334 Err(from_glib_full(error))
335 };
336 let callback: Box_<glib::thread_guard::ThreadGuard<P>> =
337 Box_::from_raw(user_data as *mut _);
338 let callback: P = callback.into_inner();
339 callback(result);
340 }
341 }
342 let callback = start_trampoline::<P>;
343 unsafe {
344 ffi::g_drive_start(
345 self.as_ref().to_glib_none().0,
346 flags.into_glib(),
347 mount_operation.map(|p| p.as_ref()).to_glib_none().0,
348 cancellable.map(|p| p.as_ref()).to_glib_none().0,
349 Some(callback),
350 Box_::into_raw(user_data) as *mut _,
351 );
352 }
353 }
354
355 fn start_future(
356 &self,
357 flags: DriveStartFlags,
358 mount_operation: Option<&(impl IsA<MountOperation> + Clone + 'static)>,
359 ) -> Pin<Box_<dyn std::future::Future<Output = Result<(), glib::Error>> + 'static>> {
360 let mount_operation = mount_operation.map(ToOwned::to_owned);
361 Box_::pin(crate::GioFuture::new(
362 self,
363 move |obj, cancellable, send| {
364 obj.start(
365 flags,
366 mount_operation.as_ref().map(::std::borrow::Borrow::borrow),
367 Some(cancellable),
368 move |res| {
369 send.resolve(res);
370 },
371 );
372 },
373 ))
374 }
375
376 #[doc(alias = "g_drive_stop")]
377 fn stop<P: FnOnce(Result<(), glib::Error>) + 'static>(
378 &self,
379 flags: MountUnmountFlags,
380 mount_operation: Option<&impl IsA<MountOperation>>,
381 cancellable: Option<&impl IsA<Cancellable>>,
382 callback: P,
383 ) {
384 let main_context = glib::MainContext::ref_thread_default();
385 let is_main_context_owner = main_context.is_owner();
386 let has_acquired_main_context = (!is_main_context_owner)
387 .then(|| main_context.acquire().ok())
388 .flatten();
389 assert!(
390 is_main_context_owner || has_acquired_main_context.is_some(),
391 "Async operations only allowed if the thread is owning the MainContext"
392 );
393
394 let user_data: Box_<glib::thread_guard::ThreadGuard<P>> =
395 Box_::new(glib::thread_guard::ThreadGuard::new(callback));
396 unsafe extern "C" fn stop_trampoline<P: FnOnce(Result<(), glib::Error>) + 'static>(
397 _source_object: *mut glib::gobject_ffi::GObject,
398 res: *mut crate::ffi::GAsyncResult,
399 user_data: glib::ffi::gpointer,
400 ) {
401 unsafe {
402 let mut error = std::ptr::null_mut();
403 ffi::g_drive_stop_finish(_source_object as *mut _, res, &mut error);
404 let result = if error.is_null() {
405 Ok(())
406 } else {
407 Err(from_glib_full(error))
408 };
409 let callback: Box_<glib::thread_guard::ThreadGuard<P>> =
410 Box_::from_raw(user_data as *mut _);
411 let callback: P = callback.into_inner();
412 callback(result);
413 }
414 }
415 let callback = stop_trampoline::<P>;
416 unsafe {
417 ffi::g_drive_stop(
418 self.as_ref().to_glib_none().0,
419 flags.into_glib(),
420 mount_operation.map(|p| p.as_ref()).to_glib_none().0,
421 cancellable.map(|p| p.as_ref()).to_glib_none().0,
422 Some(callback),
423 Box_::into_raw(user_data) as *mut _,
424 );
425 }
426 }
427
428 fn stop_future(
429 &self,
430 flags: MountUnmountFlags,
431 mount_operation: Option<&(impl IsA<MountOperation> + Clone + 'static)>,
432 ) -> Pin<Box_<dyn std::future::Future<Output = Result<(), glib::Error>> + 'static>> {
433 let mount_operation = mount_operation.map(ToOwned::to_owned);
434 Box_::pin(crate::GioFuture::new(
435 self,
436 move |obj, cancellable, send| {
437 obj.stop(
438 flags,
439 mount_operation.as_ref().map(::std::borrow::Borrow::borrow),
440 Some(cancellable),
441 move |res| {
442 send.resolve(res);
443 },
444 );
445 },
446 ))
447 }
448
449 #[doc(alias = "changed")]
450 fn connect_changed<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId {
451 unsafe extern "C" fn changed_trampoline<P: IsA<Drive>, F: Fn(&P) + 'static>(
452 this: *mut ffi::GDrive,
453 f: glib::ffi::gpointer,
454 ) {
455 unsafe {
456 let f: &F = &*(f as *const F);
457 f(Drive::from_glib_borrow(this).unsafe_cast_ref())
458 }
459 }
460 unsafe {
461 let f: Box_<F> = Box_::new(f);
462 connect_raw(
463 self.as_ptr() as *mut _,
464 c"changed".as_ptr(),
465 Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
466 changed_trampoline::<Self, F> as *const (),
467 )),
468 Box_::into_raw(f),
469 )
470 }
471 }
472
473 #[doc(alias = "disconnected")]
474 fn connect_disconnected<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId {
475 unsafe extern "C" fn disconnected_trampoline<P: IsA<Drive>, F: Fn(&P) + 'static>(
476 this: *mut ffi::GDrive,
477 f: glib::ffi::gpointer,
478 ) {
479 unsafe {
480 let f: &F = &*(f as *const F);
481 f(Drive::from_glib_borrow(this).unsafe_cast_ref())
482 }
483 }
484 unsafe {
485 let f: Box_<F> = Box_::new(f);
486 connect_raw(
487 self.as_ptr() as *mut _,
488 c"disconnected".as_ptr(),
489 Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
490 disconnected_trampoline::<Self, F> as *const (),
491 )),
492 Box_::into_raw(f),
493 )
494 }
495 }
496
497 #[doc(alias = "eject-button")]
498 fn connect_eject_button<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId {
499 unsafe extern "C" fn eject_button_trampoline<P: IsA<Drive>, F: Fn(&P) + 'static>(
500 this: *mut ffi::GDrive,
501 f: glib::ffi::gpointer,
502 ) {
503 unsafe {
504 let f: &F = &*(f as *const F);
505 f(Drive::from_glib_borrow(this).unsafe_cast_ref())
506 }
507 }
508 unsafe {
509 let f: Box_<F> = Box_::new(f);
510 connect_raw(
511 self.as_ptr() as *mut _,
512 c"eject-button".as_ptr(),
513 Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
514 eject_button_trampoline::<Self, F> as *const (),
515 )),
516 Box_::into_raw(f),
517 )
518 }
519 }
520
521 #[doc(alias = "stop-button")]
522 fn connect_stop_button<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId {
523 unsafe extern "C" fn stop_button_trampoline<P: IsA<Drive>, F: Fn(&P) + 'static>(
524 this: *mut ffi::GDrive,
525 f: glib::ffi::gpointer,
526 ) {
527 unsafe {
528 let f: &F = &*(f as *const F);
529 f(Drive::from_glib_borrow(this).unsafe_cast_ref())
530 }
531 }
532 unsafe {
533 let f: Box_<F> = Box_::new(f);
534 connect_raw(
535 self.as_ptr() as *mut _,
536 c"stop-button".as_ptr(),
537 Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
538 stop_button_trampoline::<Self, F> as *const (),
539 )),
540 Box_::into_raw(f),
541 )
542 }
543 }
544}
545
546impl<O: IsA<Drive>> DriveExt for O {}