1use crate::{
6 ffi, AsyncResult, Cancellable, DriveStartFlags, DriveStartStopType, Icon, MountOperation,
7 MountUnmountFlags, Volume,
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 = "GDrive")]
80 pub struct Drive(Interface<ffi::GDrive, ffi::GDriveIface>);
81
82 match fn {
83 type_ => || ffi::g_drive_get_type(),
84 }
85}
86
87impl Drive {
88 pub const NONE: Option<&'static Drive> = None;
89}
90
91mod sealed {
92 pub trait Sealed {}
93 impl<T: super::IsA<super::Drive>> Sealed for T {}
94}
95
96pub trait DriveExt: IsA<Drive> + sealed::Sealed + 'static {
102 #[doc(alias = "g_drive_can_eject")]
108 fn can_eject(&self) -> bool {
109 unsafe { from_glib(ffi::g_drive_can_eject(self.as_ref().to_glib_none().0)) }
110 }
111
112 #[doc(alias = "g_drive_can_poll_for_media")]
119 fn can_poll_for_media(&self) -> bool {
120 unsafe {
121 from_glib(ffi::g_drive_can_poll_for_media(
122 self.as_ref().to_glib_none().0,
123 ))
124 }
125 }
126
127 #[doc(alias = "g_drive_can_start")]
133 fn can_start(&self) -> bool {
134 unsafe { from_glib(ffi::g_drive_can_start(self.as_ref().to_glib_none().0)) }
135 }
136
137 #[doc(alias = "g_drive_can_start_degraded")]
143 fn can_start_degraded(&self) -> bool {
144 unsafe {
145 from_glib(ffi::g_drive_can_start_degraded(
146 self.as_ref().to_glib_none().0,
147 ))
148 }
149 }
150
151 #[doc(alias = "g_drive_can_stop")]
157 fn can_stop(&self) -> bool {
158 unsafe { from_glib(ffi::g_drive_can_stop(self.as_ref().to_glib_none().0)) }
159 }
160
161 #[doc(alias = "g_drive_eject_with_operation")]
174 fn eject_with_operation<P: FnOnce(Result<(), glib::Error>) + 'static>(
175 &self,
176 flags: MountUnmountFlags,
177 mount_operation: Option<&impl IsA<MountOperation>>,
178 cancellable: Option<&impl IsA<Cancellable>>,
179 callback: P,
180 ) {
181 let main_context = glib::MainContext::ref_thread_default();
182 let is_main_context_owner = main_context.is_owner();
183 let has_acquired_main_context = (!is_main_context_owner)
184 .then(|| main_context.acquire().ok())
185 .flatten();
186 assert!(
187 is_main_context_owner || has_acquired_main_context.is_some(),
188 "Async operations only allowed if the thread is owning the MainContext"
189 );
190
191 let user_data: Box_<glib::thread_guard::ThreadGuard<P>> =
192 Box_::new(glib::thread_guard::ThreadGuard::new(callback));
193 unsafe extern "C" fn eject_with_operation_trampoline<
194 P: FnOnce(Result<(), glib::Error>) + 'static,
195 >(
196 _source_object: *mut glib::gobject_ffi::GObject,
197 res: *mut crate::ffi::GAsyncResult,
198 user_data: glib::ffi::gpointer,
199 ) {
200 let mut error = std::ptr::null_mut();
201 let _ =
202 ffi::g_drive_eject_with_operation_finish(_source_object as *mut _, res, &mut error);
203 let result = if error.is_null() {
204 Ok(())
205 } else {
206 Err(from_glib_full(error))
207 };
208 let callback: Box_<glib::thread_guard::ThreadGuard<P>> =
209 Box_::from_raw(user_data as *mut _);
210 let callback: P = callback.into_inner();
211 callback(result);
212 }
213 let callback = eject_with_operation_trampoline::<P>;
214 unsafe {
215 ffi::g_drive_eject_with_operation(
216 self.as_ref().to_glib_none().0,
217 flags.into_glib(),
218 mount_operation.map(|p| p.as_ref()).to_glib_none().0,
219 cancellable.map(|p| p.as_ref()).to_glib_none().0,
220 Some(callback),
221 Box_::into_raw(user_data) as *mut _,
222 );
223 }
224 }
225
226 fn eject_with_operation_future(
227 &self,
228 flags: MountUnmountFlags,
229 mount_operation: Option<&(impl IsA<MountOperation> + Clone + 'static)>,
230 ) -> Pin<Box_<dyn std::future::Future<Output = Result<(), glib::Error>> + 'static>> {
231 let mount_operation = mount_operation.map(ToOwned::to_owned);
232 Box_::pin(crate::GioFuture::new(
233 self,
234 move |obj, cancellable, send| {
235 obj.eject_with_operation(
236 flags,
237 mount_operation.as_ref().map(::std::borrow::Borrow::borrow),
238 Some(cancellable),
239 move |res| {
240 send.resolve(res);
241 },
242 );
243 },
244 ))
245 }
246
247 #[doc(alias = "g_drive_enumerate_identifiers")]
257 fn enumerate_identifiers(&self) -> Vec<glib::GString> {
258 unsafe {
259 FromGlibPtrContainer::from_glib_full(ffi::g_drive_enumerate_identifiers(
260 self.as_ref().to_glib_none().0,
261 ))
262 }
263 }
264
265 #[doc(alias = "g_drive_get_icon")]
272 #[doc(alias = "get_icon")]
273 fn icon(&self) -> Icon {
274 unsafe { from_glib_full(ffi::g_drive_get_icon(self.as_ref().to_glib_none().0)) }
275 }
276
277 #[doc(alias = "g_drive_get_identifier")]
289 #[doc(alias = "get_identifier")]
290 fn identifier(&self, kind: &str) -> Option<glib::GString> {
291 unsafe {
292 from_glib_full(ffi::g_drive_get_identifier(
293 self.as_ref().to_glib_none().0,
294 kind.to_glib_none().0,
295 ))
296 }
297 }
298
299 #[doc(alias = "g_drive_get_name")]
306 #[doc(alias = "get_name")]
307 fn name(&self) -> glib::GString {
308 unsafe { from_glib_full(ffi::g_drive_get_name(self.as_ref().to_glib_none().0)) }
309 }
310
311 #[doc(alias = "g_drive_get_sort_key")]
317 #[doc(alias = "get_sort_key")]
318 fn sort_key(&self) -> Option<glib::GString> {
319 unsafe { from_glib_none(ffi::g_drive_get_sort_key(self.as_ref().to_glib_none().0)) }
320 }
321
322 #[doc(alias = "g_drive_get_start_stop_type")]
328 #[doc(alias = "get_start_stop_type")]
329 fn start_stop_type(&self) -> DriveStartStopType {
330 unsafe {
331 from_glib(ffi::g_drive_get_start_stop_type(
332 self.as_ref().to_glib_none().0,
333 ))
334 }
335 }
336
337 #[doc(alias = "g_drive_get_symbolic_icon")]
344 #[doc(alias = "get_symbolic_icon")]
345 fn symbolic_icon(&self) -> Icon {
346 unsafe {
347 from_glib_full(ffi::g_drive_get_symbolic_icon(
348 self.as_ref().to_glib_none().0,
349 ))
350 }
351 }
352
353 #[doc(alias = "g_drive_get_volumes")]
362 #[doc(alias = "get_volumes")]
363 fn volumes(&self) -> Vec<Volume> {
364 unsafe {
365 FromGlibPtrContainer::from_glib_full(ffi::g_drive_get_volumes(
366 self.as_ref().to_glib_none().0,
367 ))
368 }
369 }
370
371 #[doc(alias = "g_drive_has_media")]
379 fn has_media(&self) -> bool {
380 unsafe { from_glib(ffi::g_drive_has_media(self.as_ref().to_glib_none().0)) }
381 }
382
383 #[doc(alias = "g_drive_has_volumes")]
389 fn has_volumes(&self) -> bool {
390 unsafe { from_glib(ffi::g_drive_has_volumes(self.as_ref().to_glib_none().0)) }
391 }
392
393 #[doc(alias = "g_drive_is_media_check_automatic")]
400 fn is_media_check_automatic(&self) -> bool {
401 unsafe {
402 from_glib(ffi::g_drive_is_media_check_automatic(
403 self.as_ref().to_glib_none().0,
404 ))
405 }
406 }
407
408 #[doc(alias = "g_drive_is_media_removable")]
414 fn is_media_removable(&self) -> bool {
415 unsafe {
416 from_glib(ffi::g_drive_is_media_removable(
417 self.as_ref().to_glib_none().0,
418 ))
419 }
420 }
421
422 #[doc(alias = "g_drive_is_removable")]
429 fn is_removable(&self) -> bool {
430 unsafe { from_glib(ffi::g_drive_is_removable(self.as_ref().to_glib_none().0)) }
431 }
432
433 #[doc(alias = "g_drive_poll_for_media")]
443 fn poll_for_media<P: FnOnce(Result<(), glib::Error>) + 'static>(
444 &self,
445 cancellable: Option<&impl IsA<Cancellable>>,
446 callback: P,
447 ) {
448 let main_context = glib::MainContext::ref_thread_default();
449 let is_main_context_owner = main_context.is_owner();
450 let has_acquired_main_context = (!is_main_context_owner)
451 .then(|| main_context.acquire().ok())
452 .flatten();
453 assert!(
454 is_main_context_owner || has_acquired_main_context.is_some(),
455 "Async operations only allowed if the thread is owning the MainContext"
456 );
457
458 let user_data: Box_<glib::thread_guard::ThreadGuard<P>> =
459 Box_::new(glib::thread_guard::ThreadGuard::new(callback));
460 unsafe extern "C" fn poll_for_media_trampoline<
461 P: FnOnce(Result<(), glib::Error>) + 'static,
462 >(
463 _source_object: *mut glib::gobject_ffi::GObject,
464 res: *mut crate::ffi::GAsyncResult,
465 user_data: glib::ffi::gpointer,
466 ) {
467 let mut error = std::ptr::null_mut();
468 let _ = ffi::g_drive_poll_for_media_finish(_source_object as *mut _, res, &mut error);
469 let result = if error.is_null() {
470 Ok(())
471 } else {
472 Err(from_glib_full(error))
473 };
474 let callback: Box_<glib::thread_guard::ThreadGuard<P>> =
475 Box_::from_raw(user_data as *mut _);
476 let callback: P = callback.into_inner();
477 callback(result);
478 }
479 let callback = poll_for_media_trampoline::<P>;
480 unsafe {
481 ffi::g_drive_poll_for_media(
482 self.as_ref().to_glib_none().0,
483 cancellable.map(|p| p.as_ref()).to_glib_none().0,
484 Some(callback),
485 Box_::into_raw(user_data) as *mut _,
486 );
487 }
488 }
489
490 fn poll_for_media_future(
491 &self,
492 ) -> Pin<Box_<dyn std::future::Future<Output = Result<(), glib::Error>> + 'static>> {
493 Box_::pin(crate::GioFuture::new(
494 self,
495 move |obj, cancellable, send| {
496 obj.poll_for_media(Some(cancellable), move |res| {
497 send.resolve(res);
498 });
499 },
500 ))
501 }
502
503 #[doc(alias = "g_drive_start")]
518 fn start<P: FnOnce(Result<(), glib::Error>) + 'static>(
519 &self,
520 flags: DriveStartFlags,
521 mount_operation: Option<&impl IsA<MountOperation>>,
522 cancellable: Option<&impl IsA<Cancellable>>,
523 callback: P,
524 ) {
525 let main_context = glib::MainContext::ref_thread_default();
526 let is_main_context_owner = main_context.is_owner();
527 let has_acquired_main_context = (!is_main_context_owner)
528 .then(|| main_context.acquire().ok())
529 .flatten();
530 assert!(
531 is_main_context_owner || has_acquired_main_context.is_some(),
532 "Async operations only allowed if the thread is owning the MainContext"
533 );
534
535 let user_data: Box_<glib::thread_guard::ThreadGuard<P>> =
536 Box_::new(glib::thread_guard::ThreadGuard::new(callback));
537 unsafe extern "C" fn start_trampoline<P: FnOnce(Result<(), glib::Error>) + 'static>(
538 _source_object: *mut glib::gobject_ffi::GObject,
539 res: *mut crate::ffi::GAsyncResult,
540 user_data: glib::ffi::gpointer,
541 ) {
542 let mut error = std::ptr::null_mut();
543 let _ = ffi::g_drive_start_finish(_source_object as *mut _, res, &mut error);
544 let result = if error.is_null() {
545 Ok(())
546 } else {
547 Err(from_glib_full(error))
548 };
549 let callback: Box_<glib::thread_guard::ThreadGuard<P>> =
550 Box_::from_raw(user_data as *mut _);
551 let callback: P = callback.into_inner();
552 callback(result);
553 }
554 let callback = start_trampoline::<P>;
555 unsafe {
556 ffi::g_drive_start(
557 self.as_ref().to_glib_none().0,
558 flags.into_glib(),
559 mount_operation.map(|p| p.as_ref()).to_glib_none().0,
560 cancellable.map(|p| p.as_ref()).to_glib_none().0,
561 Some(callback),
562 Box_::into_raw(user_data) as *mut _,
563 );
564 }
565 }
566
567 fn start_future(
568 &self,
569 flags: DriveStartFlags,
570 mount_operation: Option<&(impl IsA<MountOperation> + Clone + 'static)>,
571 ) -> Pin<Box_<dyn std::future::Future<Output = Result<(), glib::Error>> + 'static>> {
572 let mount_operation = mount_operation.map(ToOwned::to_owned);
573 Box_::pin(crate::GioFuture::new(
574 self,
575 move |obj, cancellable, send| {
576 obj.start(
577 flags,
578 mount_operation.as_ref().map(::std::borrow::Borrow::borrow),
579 Some(cancellable),
580 move |res| {
581 send.resolve(res);
582 },
583 );
584 },
585 ))
586 }
587
588 #[doc(alias = "g_drive_stop")]
603 fn stop<P: FnOnce(Result<(), glib::Error>) + 'static>(
604 &self,
605 flags: MountUnmountFlags,
606 mount_operation: Option<&impl IsA<MountOperation>>,
607 cancellable: Option<&impl IsA<Cancellable>>,
608 callback: P,
609 ) {
610 let main_context = glib::MainContext::ref_thread_default();
611 let is_main_context_owner = main_context.is_owner();
612 let has_acquired_main_context = (!is_main_context_owner)
613 .then(|| main_context.acquire().ok())
614 .flatten();
615 assert!(
616 is_main_context_owner || has_acquired_main_context.is_some(),
617 "Async operations only allowed if the thread is owning the MainContext"
618 );
619
620 let user_data: Box_<glib::thread_guard::ThreadGuard<P>> =
621 Box_::new(glib::thread_guard::ThreadGuard::new(callback));
622 unsafe extern "C" fn stop_trampoline<P: FnOnce(Result<(), glib::Error>) + 'static>(
623 _source_object: *mut glib::gobject_ffi::GObject,
624 res: *mut crate::ffi::GAsyncResult,
625 user_data: glib::ffi::gpointer,
626 ) {
627 let mut error = std::ptr::null_mut();
628 let _ = ffi::g_drive_stop_finish(_source_object as *mut _, res, &mut error);
629 let result = if error.is_null() {
630 Ok(())
631 } else {
632 Err(from_glib_full(error))
633 };
634 let callback: Box_<glib::thread_guard::ThreadGuard<P>> =
635 Box_::from_raw(user_data as *mut _);
636 let callback: P = callback.into_inner();
637 callback(result);
638 }
639 let callback = stop_trampoline::<P>;
640 unsafe {
641 ffi::g_drive_stop(
642 self.as_ref().to_glib_none().0,
643 flags.into_glib(),
644 mount_operation.map(|p| p.as_ref()).to_glib_none().0,
645 cancellable.map(|p| p.as_ref()).to_glib_none().0,
646 Some(callback),
647 Box_::into_raw(user_data) as *mut _,
648 );
649 }
650 }
651
652 fn stop_future(
653 &self,
654 flags: MountUnmountFlags,
655 mount_operation: Option<&(impl IsA<MountOperation> + Clone + 'static)>,
656 ) -> Pin<Box_<dyn std::future::Future<Output = Result<(), glib::Error>> + 'static>> {
657 let mount_operation = mount_operation.map(ToOwned::to_owned);
658 Box_::pin(crate::GioFuture::new(
659 self,
660 move |obj, cancellable, send| {
661 obj.stop(
662 flags,
663 mount_operation.as_ref().map(::std::borrow::Borrow::borrow),
664 Some(cancellable),
665 move |res| {
666 send.resolve(res);
667 },
668 );
669 },
670 ))
671 }
672
673 #[doc(alias = "changed")]
675 fn connect_changed<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId {
676 unsafe extern "C" fn changed_trampoline<P: IsA<Drive>, F: Fn(&P) + 'static>(
677 this: *mut ffi::GDrive,
678 f: glib::ffi::gpointer,
679 ) {
680 let f: &F = &*(f as *const F);
681 f(Drive::from_glib_borrow(this).unsafe_cast_ref())
682 }
683 unsafe {
684 let f: Box_<F> = Box_::new(f);
685 connect_raw(
686 self.as_ptr() as *mut _,
687 b"changed\0".as_ptr() as *const _,
688 Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
689 changed_trampoline::<Self, F> as *const (),
690 )),
691 Box_::into_raw(f),
692 )
693 }
694 }
695
696 #[doc(alias = "disconnected")]
701 fn connect_disconnected<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId {
702 unsafe extern "C" fn disconnected_trampoline<P: IsA<Drive>, F: Fn(&P) + 'static>(
703 this: *mut ffi::GDrive,
704 f: glib::ffi::gpointer,
705 ) {
706 let f: &F = &*(f as *const F);
707 f(Drive::from_glib_borrow(this).unsafe_cast_ref())
708 }
709 unsafe {
710 let f: Box_<F> = Box_::new(f);
711 connect_raw(
712 self.as_ptr() as *mut _,
713 b"disconnected\0".as_ptr() as *const _,
714 Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
715 disconnected_trampoline::<Self, F> as *const (),
716 )),
717 Box_::into_raw(f),
718 )
719 }
720 }
721
722 #[doc(alias = "eject-button")]
725 fn connect_eject_button<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId {
726 unsafe extern "C" fn eject_button_trampoline<P: IsA<Drive>, F: Fn(&P) + 'static>(
727 this: *mut ffi::GDrive,
728 f: glib::ffi::gpointer,
729 ) {
730 let f: &F = &*(f as *const F);
731 f(Drive::from_glib_borrow(this).unsafe_cast_ref())
732 }
733 unsafe {
734 let f: Box_<F> = Box_::new(f);
735 connect_raw(
736 self.as_ptr() as *mut _,
737 b"eject-button\0".as_ptr() as *const _,
738 Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
739 eject_button_trampoline::<Self, F> as *const (),
740 )),
741 Box_::into_raw(f),
742 )
743 }
744 }
745
746 #[doc(alias = "stop-button")]
749 fn connect_stop_button<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId {
750 unsafe extern "C" fn stop_button_trampoline<P: IsA<Drive>, F: Fn(&P) + 'static>(
751 this: *mut ffi::GDrive,
752 f: glib::ffi::gpointer,
753 ) {
754 let f: &F = &*(f as *const F);
755 f(Drive::from_glib_borrow(this).unsafe_cast_ref())
756 }
757 unsafe {
758 let f: Box_<F> = Box_::new(f);
759 connect_raw(
760 self.as_ptr() as *mut _,
761 b"stop-button\0".as_ptr() as *const _,
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 {}