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")]
70 pub struct Drive(Interface<ffi::GDrive, ffi::GDriveIface>);
71
72 match fn {
73 type_ => || ffi::g_drive_get_type(),
74 }
75}
76
77impl Drive {
78 pub const NONE: Option<&'static Drive> = None;
79}
80
81pub trait DriveExt: IsA<Drive> + 'static {
87 #[doc(alias = "g_drive_can_eject")]
93 fn can_eject(&self) -> bool {
94 unsafe { from_glib(ffi::g_drive_can_eject(self.as_ref().to_glib_none().0)) }
95 }
96
97 #[doc(alias = "g_drive_can_poll_for_media")]
104 fn can_poll_for_media(&self) -> bool {
105 unsafe {
106 from_glib(ffi::g_drive_can_poll_for_media(
107 self.as_ref().to_glib_none().0,
108 ))
109 }
110 }
111
112 #[doc(alias = "g_drive_can_start")]
118 fn can_start(&self) -> bool {
119 unsafe { from_glib(ffi::g_drive_can_start(self.as_ref().to_glib_none().0)) }
120 }
121
122 #[doc(alias = "g_drive_can_start_degraded")]
128 fn can_start_degraded(&self) -> bool {
129 unsafe {
130 from_glib(ffi::g_drive_can_start_degraded(
131 self.as_ref().to_glib_none().0,
132 ))
133 }
134 }
135
136 #[doc(alias = "g_drive_can_stop")]
142 fn can_stop(&self) -> bool {
143 unsafe { from_glib(ffi::g_drive_can_stop(self.as_ref().to_glib_none().0)) }
144 }
145
146 #[doc(alias = "g_drive_eject_with_operation")]
159 fn eject_with_operation<P: FnOnce(Result<(), glib::Error>) + 'static>(
160 &self,
161 flags: MountUnmountFlags,
162 mount_operation: Option<&impl IsA<MountOperation>>,
163 cancellable: Option<&impl IsA<Cancellable>>,
164 callback: P,
165 ) {
166 let main_context = glib::MainContext::ref_thread_default();
167 let is_main_context_owner = main_context.is_owner();
168 let has_acquired_main_context = (!is_main_context_owner)
169 .then(|| main_context.acquire().ok())
170 .flatten();
171 assert!(
172 is_main_context_owner || has_acquired_main_context.is_some(),
173 "Async operations only allowed if the thread is owning the MainContext"
174 );
175
176 let user_data: Box_<glib::thread_guard::ThreadGuard<P>> =
177 Box_::new(glib::thread_guard::ThreadGuard::new(callback));
178 unsafe extern "C" fn eject_with_operation_trampoline<
179 P: FnOnce(Result<(), glib::Error>) + 'static,
180 >(
181 _source_object: *mut glib::gobject_ffi::GObject,
182 res: *mut crate::ffi::GAsyncResult,
183 user_data: glib::ffi::gpointer,
184 ) {
185 unsafe {
186 let mut error = std::ptr::null_mut();
187 ffi::g_drive_eject_with_operation_finish(_source_object as *mut _, res, &mut error);
188 let result = if error.is_null() {
189 Ok(())
190 } else {
191 Err(from_glib_full(error))
192 };
193 let callback: Box_<glib::thread_guard::ThreadGuard<P>> =
194 Box_::from_raw(user_data as *mut _);
195 let callback: P = callback.into_inner();
196 callback(result);
197 }
198 }
199 let callback = eject_with_operation_trampoline::<P>;
200 unsafe {
201 ffi::g_drive_eject_with_operation(
202 self.as_ref().to_glib_none().0,
203 flags.into_glib(),
204 mount_operation.map(|p| p.as_ref()).to_glib_none().0,
205 cancellable.map(|p| p.as_ref()).to_glib_none().0,
206 Some(callback),
207 Box_::into_raw(user_data) as *mut _,
208 );
209 }
210 }
211
212 fn eject_with_operation_future(
213 &self,
214 flags: MountUnmountFlags,
215 mount_operation: Option<&(impl IsA<MountOperation> + Clone + 'static)>,
216 ) -> Pin<Box_<dyn std::future::Future<Output = Result<(), glib::Error>> + 'static>> {
217 let mount_operation = mount_operation.map(ToOwned::to_owned);
218 Box_::pin(crate::GioFuture::new(
219 self,
220 move |obj, cancellable, send| {
221 obj.eject_with_operation(
222 flags,
223 mount_operation.as_ref().map(::std::borrow::Borrow::borrow),
224 Some(cancellable),
225 move |res| {
226 send.resolve(res);
227 },
228 );
229 },
230 ))
231 }
232
233 #[doc(alias = "g_drive_enumerate_identifiers")]
243 fn enumerate_identifiers(&self) -> Vec<glib::GString> {
244 unsafe {
245 FromGlibPtrContainer::from_glib_full(ffi::g_drive_enumerate_identifiers(
246 self.as_ref().to_glib_none().0,
247 ))
248 }
249 }
250
251 #[doc(alias = "g_drive_get_icon")]
258 #[doc(alias = "get_icon")]
259 fn icon(&self) -> Icon {
260 unsafe { from_glib_full(ffi::g_drive_get_icon(self.as_ref().to_glib_none().0)) }
261 }
262
263 #[doc(alias = "g_drive_get_identifier")]
275 #[doc(alias = "get_identifier")]
276 fn identifier(&self, kind: &str) -> Option<glib::GString> {
277 unsafe {
278 from_glib_full(ffi::g_drive_get_identifier(
279 self.as_ref().to_glib_none().0,
280 kind.to_glib_none().0,
281 ))
282 }
283 }
284
285 #[doc(alias = "g_drive_get_name")]
292 #[doc(alias = "get_name")]
293 fn name(&self) -> glib::GString {
294 unsafe { from_glib_full(ffi::g_drive_get_name(self.as_ref().to_glib_none().0)) }
295 }
296
297 #[doc(alias = "g_drive_get_sort_key")]
303 #[doc(alias = "get_sort_key")]
304 fn sort_key(&self) -> Option<glib::GString> {
305 unsafe { from_glib_none(ffi::g_drive_get_sort_key(self.as_ref().to_glib_none().0)) }
306 }
307
308 #[doc(alias = "g_drive_get_start_stop_type")]
314 #[doc(alias = "get_start_stop_type")]
315 fn start_stop_type(&self) -> DriveStartStopType {
316 unsafe {
317 from_glib(ffi::g_drive_get_start_stop_type(
318 self.as_ref().to_glib_none().0,
319 ))
320 }
321 }
322
323 #[doc(alias = "g_drive_get_symbolic_icon")]
330 #[doc(alias = "get_symbolic_icon")]
331 fn symbolic_icon(&self) -> Icon {
332 unsafe {
333 from_glib_full(ffi::g_drive_get_symbolic_icon(
334 self.as_ref().to_glib_none().0,
335 ))
336 }
337 }
338
339 #[doc(alias = "g_drive_get_volumes")]
348 #[doc(alias = "get_volumes")]
349 fn volumes(&self) -> Vec<Volume> {
350 unsafe {
351 FromGlibPtrContainer::from_glib_full(ffi::g_drive_get_volumes(
352 self.as_ref().to_glib_none().0,
353 ))
354 }
355 }
356
357 #[doc(alias = "g_drive_has_media")]
365 fn has_media(&self) -> bool {
366 unsafe { from_glib(ffi::g_drive_has_media(self.as_ref().to_glib_none().0)) }
367 }
368
369 #[doc(alias = "g_drive_has_volumes")]
375 fn has_volumes(&self) -> bool {
376 unsafe { from_glib(ffi::g_drive_has_volumes(self.as_ref().to_glib_none().0)) }
377 }
378
379 #[doc(alias = "g_drive_is_media_check_automatic")]
386 fn is_media_check_automatic(&self) -> bool {
387 unsafe {
388 from_glib(ffi::g_drive_is_media_check_automatic(
389 self.as_ref().to_glib_none().0,
390 ))
391 }
392 }
393
394 #[doc(alias = "g_drive_is_media_removable")]
400 fn is_media_removable(&self) -> bool {
401 unsafe {
402 from_glib(ffi::g_drive_is_media_removable(
403 self.as_ref().to_glib_none().0,
404 ))
405 }
406 }
407
408 #[doc(alias = "g_drive_is_removable")]
415 fn is_removable(&self) -> bool {
416 unsafe { from_glib(ffi::g_drive_is_removable(self.as_ref().to_glib_none().0)) }
417 }
418
419 #[doc(alias = "g_drive_poll_for_media")]
429 fn poll_for_media<P: FnOnce(Result<(), glib::Error>) + 'static>(
430 &self,
431 cancellable: Option<&impl IsA<Cancellable>>,
432 callback: P,
433 ) {
434 let main_context = glib::MainContext::ref_thread_default();
435 let is_main_context_owner = main_context.is_owner();
436 let has_acquired_main_context = (!is_main_context_owner)
437 .then(|| main_context.acquire().ok())
438 .flatten();
439 assert!(
440 is_main_context_owner || has_acquired_main_context.is_some(),
441 "Async operations only allowed if the thread is owning the MainContext"
442 );
443
444 let user_data: Box_<glib::thread_guard::ThreadGuard<P>> =
445 Box_::new(glib::thread_guard::ThreadGuard::new(callback));
446 unsafe extern "C" fn poll_for_media_trampoline<
447 P: FnOnce(Result<(), glib::Error>) + 'static,
448 >(
449 _source_object: *mut glib::gobject_ffi::GObject,
450 res: *mut crate::ffi::GAsyncResult,
451 user_data: glib::ffi::gpointer,
452 ) {
453 unsafe {
454 let mut error = std::ptr::null_mut();
455 ffi::g_drive_poll_for_media_finish(_source_object as *mut _, res, &mut error);
456 let result = if error.is_null() {
457 Ok(())
458 } else {
459 Err(from_glib_full(error))
460 };
461 let callback: Box_<glib::thread_guard::ThreadGuard<P>> =
462 Box_::from_raw(user_data as *mut _);
463 let callback: P = callback.into_inner();
464 callback(result);
465 }
466 }
467 let callback = poll_for_media_trampoline::<P>;
468 unsafe {
469 ffi::g_drive_poll_for_media(
470 self.as_ref().to_glib_none().0,
471 cancellable.map(|p| p.as_ref()).to_glib_none().0,
472 Some(callback),
473 Box_::into_raw(user_data) as *mut _,
474 );
475 }
476 }
477
478 fn poll_for_media_future(
479 &self,
480 ) -> Pin<Box_<dyn std::future::Future<Output = Result<(), glib::Error>> + 'static>> {
481 Box_::pin(crate::GioFuture::new(
482 self,
483 move |obj, cancellable, send| {
484 obj.poll_for_media(Some(cancellable), move |res| {
485 send.resolve(res);
486 });
487 },
488 ))
489 }
490
491 #[doc(alias = "g_drive_start")]
506 fn start<P: FnOnce(Result<(), glib::Error>) + 'static>(
507 &self,
508 flags: DriveStartFlags,
509 mount_operation: Option<&impl IsA<MountOperation>>,
510 cancellable: Option<&impl IsA<Cancellable>>,
511 callback: P,
512 ) {
513 let main_context = glib::MainContext::ref_thread_default();
514 let is_main_context_owner = main_context.is_owner();
515 let has_acquired_main_context = (!is_main_context_owner)
516 .then(|| main_context.acquire().ok())
517 .flatten();
518 assert!(
519 is_main_context_owner || has_acquired_main_context.is_some(),
520 "Async operations only allowed if the thread is owning the MainContext"
521 );
522
523 let user_data: Box_<glib::thread_guard::ThreadGuard<P>> =
524 Box_::new(glib::thread_guard::ThreadGuard::new(callback));
525 unsafe extern "C" fn start_trampoline<P: FnOnce(Result<(), glib::Error>) + 'static>(
526 _source_object: *mut glib::gobject_ffi::GObject,
527 res: *mut crate::ffi::GAsyncResult,
528 user_data: glib::ffi::gpointer,
529 ) {
530 unsafe {
531 let mut error = std::ptr::null_mut();
532 ffi::g_drive_start_finish(_source_object as *mut _, res, &mut error);
533 let result = if error.is_null() {
534 Ok(())
535 } else {
536 Err(from_glib_full(error))
537 };
538 let callback: Box_<glib::thread_guard::ThreadGuard<P>> =
539 Box_::from_raw(user_data as *mut _);
540 let callback: P = callback.into_inner();
541 callback(result);
542 }
543 }
544 let callback = start_trampoline::<P>;
545 unsafe {
546 ffi::g_drive_start(
547 self.as_ref().to_glib_none().0,
548 flags.into_glib(),
549 mount_operation.map(|p| p.as_ref()).to_glib_none().0,
550 cancellable.map(|p| p.as_ref()).to_glib_none().0,
551 Some(callback),
552 Box_::into_raw(user_data) as *mut _,
553 );
554 }
555 }
556
557 fn start_future(
558 &self,
559 flags: DriveStartFlags,
560 mount_operation: Option<&(impl IsA<MountOperation> + Clone + 'static)>,
561 ) -> Pin<Box_<dyn std::future::Future<Output = Result<(), glib::Error>> + 'static>> {
562 let mount_operation = mount_operation.map(ToOwned::to_owned);
563 Box_::pin(crate::GioFuture::new(
564 self,
565 move |obj, cancellable, send| {
566 obj.start(
567 flags,
568 mount_operation.as_ref().map(::std::borrow::Borrow::borrow),
569 Some(cancellable),
570 move |res| {
571 send.resolve(res);
572 },
573 );
574 },
575 ))
576 }
577
578 #[doc(alias = "g_drive_stop")]
593 fn stop<P: FnOnce(Result<(), glib::Error>) + 'static>(
594 &self,
595 flags: MountUnmountFlags,
596 mount_operation: Option<&impl IsA<MountOperation>>,
597 cancellable: Option<&impl IsA<Cancellable>>,
598 callback: P,
599 ) {
600 let main_context = glib::MainContext::ref_thread_default();
601 let is_main_context_owner = main_context.is_owner();
602 let has_acquired_main_context = (!is_main_context_owner)
603 .then(|| main_context.acquire().ok())
604 .flatten();
605 assert!(
606 is_main_context_owner || has_acquired_main_context.is_some(),
607 "Async operations only allowed if the thread is owning the MainContext"
608 );
609
610 let user_data: Box_<glib::thread_guard::ThreadGuard<P>> =
611 Box_::new(glib::thread_guard::ThreadGuard::new(callback));
612 unsafe extern "C" fn stop_trampoline<P: FnOnce(Result<(), glib::Error>) + 'static>(
613 _source_object: *mut glib::gobject_ffi::GObject,
614 res: *mut crate::ffi::GAsyncResult,
615 user_data: glib::ffi::gpointer,
616 ) {
617 unsafe {
618 let mut error = std::ptr::null_mut();
619 ffi::g_drive_stop_finish(_source_object as *mut _, res, &mut error);
620 let result = if error.is_null() {
621 Ok(())
622 } else {
623 Err(from_glib_full(error))
624 };
625 let callback: Box_<glib::thread_guard::ThreadGuard<P>> =
626 Box_::from_raw(user_data as *mut _);
627 let callback: P = callback.into_inner();
628 callback(result);
629 }
630 }
631 let callback = stop_trampoline::<P>;
632 unsafe {
633 ffi::g_drive_stop(
634 self.as_ref().to_glib_none().0,
635 flags.into_glib(),
636 mount_operation.map(|p| p.as_ref()).to_glib_none().0,
637 cancellable.map(|p| p.as_ref()).to_glib_none().0,
638 Some(callback),
639 Box_::into_raw(user_data) as *mut _,
640 );
641 }
642 }
643
644 fn stop_future(
645 &self,
646 flags: MountUnmountFlags,
647 mount_operation: Option<&(impl IsA<MountOperation> + Clone + 'static)>,
648 ) -> Pin<Box_<dyn std::future::Future<Output = Result<(), glib::Error>> + 'static>> {
649 let mount_operation = mount_operation.map(ToOwned::to_owned);
650 Box_::pin(crate::GioFuture::new(
651 self,
652 move |obj, cancellable, send| {
653 obj.stop(
654 flags,
655 mount_operation.as_ref().map(::std::borrow::Borrow::borrow),
656 Some(cancellable),
657 move |res| {
658 send.resolve(res);
659 },
660 );
661 },
662 ))
663 }
664
665 #[doc(alias = "changed")]
667 fn connect_changed<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId {
668 unsafe extern "C" fn changed_trampoline<P: IsA<Drive>, F: Fn(&P) + 'static>(
669 this: *mut ffi::GDrive,
670 f: glib::ffi::gpointer,
671 ) {
672 unsafe {
673 let f: &F = &*(f as *const F);
674 f(Drive::from_glib_borrow(this).unsafe_cast_ref())
675 }
676 }
677 unsafe {
678 let f: Box_<F> = Box_::new(f);
679 connect_raw(
680 self.as_ptr() as *mut _,
681 c"changed".as_ptr(),
682 Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
683 changed_trampoline::<Self, F> as *const (),
684 )),
685 Box_::into_raw(f),
686 )
687 }
688 }
689
690 #[doc(alias = "disconnected")]
695 fn connect_disconnected<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId {
696 unsafe extern "C" fn disconnected_trampoline<P: IsA<Drive>, F: Fn(&P) + 'static>(
697 this: *mut ffi::GDrive,
698 f: glib::ffi::gpointer,
699 ) {
700 unsafe {
701 let f: &F = &*(f as *const F);
702 f(Drive::from_glib_borrow(this).unsafe_cast_ref())
703 }
704 }
705 unsafe {
706 let f: Box_<F> = Box_::new(f);
707 connect_raw(
708 self.as_ptr() as *mut _,
709 c"disconnected".as_ptr(),
710 Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
711 disconnected_trampoline::<Self, F> as *const (),
712 )),
713 Box_::into_raw(f),
714 )
715 }
716 }
717
718 #[doc(alias = "eject-button")]
721 fn connect_eject_button<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId {
722 unsafe extern "C" fn eject_button_trampoline<P: IsA<Drive>, F: Fn(&P) + 'static>(
723 this: *mut ffi::GDrive,
724 f: glib::ffi::gpointer,
725 ) {
726 unsafe {
727 let f: &F = &*(f as *const F);
728 f(Drive::from_glib_borrow(this).unsafe_cast_ref())
729 }
730 }
731 unsafe {
732 let f: Box_<F> = Box_::new(f);
733 connect_raw(
734 self.as_ptr() as *mut _,
735 c"eject-button".as_ptr(),
736 Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
737 eject_button_trampoline::<Self, F> as *const (),
738 )),
739 Box_::into_raw(f),
740 )
741 }
742 }
743
744 #[doc(alias = "stop-button")]
747 fn connect_stop_button<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId {
748 unsafe extern "C" fn stop_button_trampoline<P: IsA<Drive>, F: Fn(&P) + 'static>(
749 this: *mut ffi::GDrive,
750 f: glib::ffi::gpointer,
751 ) {
752 unsafe {
753 let f: &F = &*(f as *const F);
754 f(Drive::from_glib_borrow(this).unsafe_cast_ref())
755 }
756 }
757 unsafe {
758 let f: Box_<F> = Box_::new(f);
759 connect_raw(
760 self.as_ptr() as *mut _,
761 c"stop-button".as_ptr(),
762 Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
763 stop_button_trampoline::<Self, F> as *const (),
764 )),
765 Box_::into_raw(f),
766 )
767 }
768 }
769}
770
771impl<O: IsA<Drive>> DriveExt for O {}