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 ffi::g_drive_eject_with_operation_finish(_source_object as *mut _, res, &mut error);
202 let result = if error.is_null() {
203 Ok(())
204 } else {
205 Err(from_glib_full(error))
206 };
207 let callback: Box_<glib::thread_guard::ThreadGuard<P>> =
208 Box_::from_raw(user_data as *mut _);
209 let callback: P = callback.into_inner();
210 callback(result);
211 }
212 let callback = eject_with_operation_trampoline::<P>;
213 unsafe {
214 ffi::g_drive_eject_with_operation(
215 self.as_ref().to_glib_none().0,
216 flags.into_glib(),
217 mount_operation.map(|p| p.as_ref()).to_glib_none().0,
218 cancellable.map(|p| p.as_ref()).to_glib_none().0,
219 Some(callback),
220 Box_::into_raw(user_data) as *mut _,
221 );
222 }
223 }
224
225 fn eject_with_operation_future(
226 &self,
227 flags: MountUnmountFlags,
228 mount_operation: Option<&(impl IsA<MountOperation> + Clone + 'static)>,
229 ) -> Pin<Box_<dyn std::future::Future<Output = Result<(), glib::Error>> + 'static>> {
230 let mount_operation = mount_operation.map(ToOwned::to_owned);
231 Box_::pin(crate::GioFuture::new(
232 self,
233 move |obj, cancellable, send| {
234 obj.eject_with_operation(
235 flags,
236 mount_operation.as_ref().map(::std::borrow::Borrow::borrow),
237 Some(cancellable),
238 move |res| {
239 send.resolve(res);
240 },
241 );
242 },
243 ))
244 }
245
246 #[doc(alias = "g_drive_enumerate_identifiers")]
256 fn enumerate_identifiers(&self) -> Vec<glib::GString> {
257 unsafe {
258 FromGlibPtrContainer::from_glib_full(ffi::g_drive_enumerate_identifiers(
259 self.as_ref().to_glib_none().0,
260 ))
261 }
262 }
263
264 #[doc(alias = "g_drive_get_icon")]
271 #[doc(alias = "get_icon")]
272 fn icon(&self) -> Icon {
273 unsafe { from_glib_full(ffi::g_drive_get_icon(self.as_ref().to_glib_none().0)) }
274 }
275
276 #[doc(alias = "g_drive_get_identifier")]
288 #[doc(alias = "get_identifier")]
289 fn identifier(&self, kind: &str) -> Option<glib::GString> {
290 unsafe {
291 from_glib_full(ffi::g_drive_get_identifier(
292 self.as_ref().to_glib_none().0,
293 kind.to_glib_none().0,
294 ))
295 }
296 }
297
298 #[doc(alias = "g_drive_get_name")]
305 #[doc(alias = "get_name")]
306 fn name(&self) -> glib::GString {
307 unsafe { from_glib_full(ffi::g_drive_get_name(self.as_ref().to_glib_none().0)) }
308 }
309
310 #[doc(alias = "g_drive_get_sort_key")]
316 #[doc(alias = "get_sort_key")]
317 fn sort_key(&self) -> Option<glib::GString> {
318 unsafe { from_glib_none(ffi::g_drive_get_sort_key(self.as_ref().to_glib_none().0)) }
319 }
320
321 #[doc(alias = "g_drive_get_start_stop_type")]
327 #[doc(alias = "get_start_stop_type")]
328 fn start_stop_type(&self) -> DriveStartStopType {
329 unsafe {
330 from_glib(ffi::g_drive_get_start_stop_type(
331 self.as_ref().to_glib_none().0,
332 ))
333 }
334 }
335
336 #[doc(alias = "g_drive_get_symbolic_icon")]
343 #[doc(alias = "get_symbolic_icon")]
344 fn symbolic_icon(&self) -> Icon {
345 unsafe {
346 from_glib_full(ffi::g_drive_get_symbolic_icon(
347 self.as_ref().to_glib_none().0,
348 ))
349 }
350 }
351
352 #[doc(alias = "g_drive_get_volumes")]
361 #[doc(alias = "get_volumes")]
362 fn volumes(&self) -> Vec<Volume> {
363 unsafe {
364 FromGlibPtrContainer::from_glib_full(ffi::g_drive_get_volumes(
365 self.as_ref().to_glib_none().0,
366 ))
367 }
368 }
369
370 #[doc(alias = "g_drive_has_media")]
378 fn has_media(&self) -> bool {
379 unsafe { from_glib(ffi::g_drive_has_media(self.as_ref().to_glib_none().0)) }
380 }
381
382 #[doc(alias = "g_drive_has_volumes")]
388 fn has_volumes(&self) -> bool {
389 unsafe { from_glib(ffi::g_drive_has_volumes(self.as_ref().to_glib_none().0)) }
390 }
391
392 #[doc(alias = "g_drive_is_media_check_automatic")]
399 fn is_media_check_automatic(&self) -> bool {
400 unsafe {
401 from_glib(ffi::g_drive_is_media_check_automatic(
402 self.as_ref().to_glib_none().0,
403 ))
404 }
405 }
406
407 #[doc(alias = "g_drive_is_media_removable")]
413 fn is_media_removable(&self) -> bool {
414 unsafe {
415 from_glib(ffi::g_drive_is_media_removable(
416 self.as_ref().to_glib_none().0,
417 ))
418 }
419 }
420
421 #[doc(alias = "g_drive_is_removable")]
428 fn is_removable(&self) -> bool {
429 unsafe { from_glib(ffi::g_drive_is_removable(self.as_ref().to_glib_none().0)) }
430 }
431
432 #[doc(alias = "g_drive_poll_for_media")]
442 fn poll_for_media<P: FnOnce(Result<(), glib::Error>) + 'static>(
443 &self,
444 cancellable: Option<&impl IsA<Cancellable>>,
445 callback: P,
446 ) {
447 let main_context = glib::MainContext::ref_thread_default();
448 let is_main_context_owner = main_context.is_owner();
449 let has_acquired_main_context = (!is_main_context_owner)
450 .then(|| main_context.acquire().ok())
451 .flatten();
452 assert!(
453 is_main_context_owner || has_acquired_main_context.is_some(),
454 "Async operations only allowed if the thread is owning the MainContext"
455 );
456
457 let user_data: Box_<glib::thread_guard::ThreadGuard<P>> =
458 Box_::new(glib::thread_guard::ThreadGuard::new(callback));
459 unsafe extern "C" fn poll_for_media_trampoline<
460 P: FnOnce(Result<(), glib::Error>) + 'static,
461 >(
462 _source_object: *mut glib::gobject_ffi::GObject,
463 res: *mut crate::ffi::GAsyncResult,
464 user_data: glib::ffi::gpointer,
465 ) {
466 let mut error = std::ptr::null_mut();
467 ffi::g_drive_poll_for_media_finish(_source_object as *mut _, res, &mut error);
468 let result = if error.is_null() {
469 Ok(())
470 } else {
471 Err(from_glib_full(error))
472 };
473 let callback: Box_<glib::thread_guard::ThreadGuard<P>> =
474 Box_::from_raw(user_data as *mut _);
475 let callback: P = callback.into_inner();
476 callback(result);
477 }
478 let callback = poll_for_media_trampoline::<P>;
479 unsafe {
480 ffi::g_drive_poll_for_media(
481 self.as_ref().to_glib_none().0,
482 cancellable.map(|p| p.as_ref()).to_glib_none().0,
483 Some(callback),
484 Box_::into_raw(user_data) as *mut _,
485 );
486 }
487 }
488
489 fn poll_for_media_future(
490 &self,
491 ) -> Pin<Box_<dyn std::future::Future<Output = Result<(), glib::Error>> + 'static>> {
492 Box_::pin(crate::GioFuture::new(
493 self,
494 move |obj, cancellable, send| {
495 obj.poll_for_media(Some(cancellable), move |res| {
496 send.resolve(res);
497 });
498 },
499 ))
500 }
501
502 #[doc(alias = "g_drive_start")]
517 fn start<P: FnOnce(Result<(), glib::Error>) + 'static>(
518 &self,
519 flags: DriveStartFlags,
520 mount_operation: Option<&impl IsA<MountOperation>>,
521 cancellable: Option<&impl IsA<Cancellable>>,
522 callback: P,
523 ) {
524 let main_context = glib::MainContext::ref_thread_default();
525 let is_main_context_owner = main_context.is_owner();
526 let has_acquired_main_context = (!is_main_context_owner)
527 .then(|| main_context.acquire().ok())
528 .flatten();
529 assert!(
530 is_main_context_owner || has_acquired_main_context.is_some(),
531 "Async operations only allowed if the thread is owning the MainContext"
532 );
533
534 let user_data: Box_<glib::thread_guard::ThreadGuard<P>> =
535 Box_::new(glib::thread_guard::ThreadGuard::new(callback));
536 unsafe extern "C" fn start_trampoline<P: FnOnce(Result<(), glib::Error>) + 'static>(
537 _source_object: *mut glib::gobject_ffi::GObject,
538 res: *mut crate::ffi::GAsyncResult,
539 user_data: glib::ffi::gpointer,
540 ) {
541 let mut error = std::ptr::null_mut();
542 ffi::g_drive_start_finish(_source_object as *mut _, res, &mut error);
543 let result = if error.is_null() {
544 Ok(())
545 } else {
546 Err(from_glib_full(error))
547 };
548 let callback: Box_<glib::thread_guard::ThreadGuard<P>> =
549 Box_::from_raw(user_data as *mut _);
550 let callback: P = callback.into_inner();
551 callback(result);
552 }
553 let callback = start_trampoline::<P>;
554 unsafe {
555 ffi::g_drive_start(
556 self.as_ref().to_glib_none().0,
557 flags.into_glib(),
558 mount_operation.map(|p| p.as_ref()).to_glib_none().0,
559 cancellable.map(|p| p.as_ref()).to_glib_none().0,
560 Some(callback),
561 Box_::into_raw(user_data) as *mut _,
562 );
563 }
564 }
565
566 fn start_future(
567 &self,
568 flags: DriveStartFlags,
569 mount_operation: Option<&(impl IsA<MountOperation> + Clone + 'static)>,
570 ) -> Pin<Box_<dyn std::future::Future<Output = Result<(), glib::Error>> + 'static>> {
571 let mount_operation = mount_operation.map(ToOwned::to_owned);
572 Box_::pin(crate::GioFuture::new(
573 self,
574 move |obj, cancellable, send| {
575 obj.start(
576 flags,
577 mount_operation.as_ref().map(::std::borrow::Borrow::borrow),
578 Some(cancellable),
579 move |res| {
580 send.resolve(res);
581 },
582 );
583 },
584 ))
585 }
586
587 #[doc(alias = "g_drive_stop")]
602 fn stop<P: FnOnce(Result<(), glib::Error>) + 'static>(
603 &self,
604 flags: MountUnmountFlags,
605 mount_operation: Option<&impl IsA<MountOperation>>,
606 cancellable: Option<&impl IsA<Cancellable>>,
607 callback: P,
608 ) {
609 let main_context = glib::MainContext::ref_thread_default();
610 let is_main_context_owner = main_context.is_owner();
611 let has_acquired_main_context = (!is_main_context_owner)
612 .then(|| main_context.acquire().ok())
613 .flatten();
614 assert!(
615 is_main_context_owner || has_acquired_main_context.is_some(),
616 "Async operations only allowed if the thread is owning the MainContext"
617 );
618
619 let user_data: Box_<glib::thread_guard::ThreadGuard<P>> =
620 Box_::new(glib::thread_guard::ThreadGuard::new(callback));
621 unsafe extern "C" fn stop_trampoline<P: FnOnce(Result<(), glib::Error>) + 'static>(
622 _source_object: *mut glib::gobject_ffi::GObject,
623 res: *mut crate::ffi::GAsyncResult,
624 user_data: glib::ffi::gpointer,
625 ) {
626 let mut error = std::ptr::null_mut();
627 ffi::g_drive_stop_finish(_source_object as *mut _, res, &mut error);
628 let result = if error.is_null() {
629 Ok(())
630 } else {
631 Err(from_glib_full(error))
632 };
633 let callback: Box_<glib::thread_guard::ThreadGuard<P>> =
634 Box_::from_raw(user_data as *mut _);
635 let callback: P = callback.into_inner();
636 callback(result);
637 }
638 let callback = stop_trampoline::<P>;
639 unsafe {
640 ffi::g_drive_stop(
641 self.as_ref().to_glib_none().0,
642 flags.into_glib(),
643 mount_operation.map(|p| p.as_ref()).to_glib_none().0,
644 cancellable.map(|p| p.as_ref()).to_glib_none().0,
645 Some(callback),
646 Box_::into_raw(user_data) as *mut _,
647 );
648 }
649 }
650
651 fn stop_future(
652 &self,
653 flags: MountUnmountFlags,
654 mount_operation: Option<&(impl IsA<MountOperation> + Clone + 'static)>,
655 ) -> Pin<Box_<dyn std::future::Future<Output = Result<(), glib::Error>> + 'static>> {
656 let mount_operation = mount_operation.map(ToOwned::to_owned);
657 Box_::pin(crate::GioFuture::new(
658 self,
659 move |obj, cancellable, send| {
660 obj.stop(
661 flags,
662 mount_operation.as_ref().map(::std::borrow::Borrow::borrow),
663 Some(cancellable),
664 move |res| {
665 send.resolve(res);
666 },
667 );
668 },
669 ))
670 }
671
672 #[doc(alias = "changed")]
674 fn connect_changed<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId {
675 unsafe extern "C" fn changed_trampoline<P: IsA<Drive>, F: Fn(&P) + 'static>(
676 this: *mut ffi::GDrive,
677 f: glib::ffi::gpointer,
678 ) {
679 let f: &F = &*(f as *const F);
680 f(Drive::from_glib_borrow(this).unsafe_cast_ref())
681 }
682 unsafe {
683 let f: Box_<F> = Box_::new(f);
684 connect_raw(
685 self.as_ptr() as *mut _,
686 b"changed\0".as_ptr() as *const _,
687 Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
688 changed_trampoline::<Self, F> as *const (),
689 )),
690 Box_::into_raw(f),
691 )
692 }
693 }
694
695 #[doc(alias = "disconnected")]
700 fn connect_disconnected<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId {
701 unsafe extern "C" fn disconnected_trampoline<P: IsA<Drive>, F: Fn(&P) + 'static>(
702 this: *mut ffi::GDrive,
703 f: glib::ffi::gpointer,
704 ) {
705 let f: &F = &*(f as *const F);
706 f(Drive::from_glib_borrow(this).unsafe_cast_ref())
707 }
708 unsafe {
709 let f: Box_<F> = Box_::new(f);
710 connect_raw(
711 self.as_ptr() as *mut _,
712 b"disconnected\0".as_ptr() as *const _,
713 Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
714 disconnected_trampoline::<Self, F> as *const (),
715 )),
716 Box_::into_raw(f),
717 )
718 }
719 }
720
721 #[doc(alias = "eject-button")]
724 fn connect_eject_button<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId {
725 unsafe extern "C" fn eject_button_trampoline<P: IsA<Drive>, F: Fn(&P) + 'static>(
726 this: *mut ffi::GDrive,
727 f: glib::ffi::gpointer,
728 ) {
729 let f: &F = &*(f as *const F);
730 f(Drive::from_glib_borrow(this).unsafe_cast_ref())
731 }
732 unsafe {
733 let f: Box_<F> = Box_::new(f);
734 connect_raw(
735 self.as_ptr() as *mut _,
736 b"eject-button\0".as_ptr() as *const _,
737 Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
738 eject_button_trampoline::<Self, F> as *const (),
739 )),
740 Box_::into_raw(f),
741 )
742 }
743 }
744
745 #[doc(alias = "stop-button")]
748 fn connect_stop_button<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId {
749 unsafe extern "C" fn stop_button_trampoline<P: IsA<Drive>, F: Fn(&P) + 'static>(
750 this: *mut ffi::GDrive,
751 f: glib::ffi::gpointer,
752 ) {
753 let f: &F = &*(f as *const F);
754 f(Drive::from_glib_borrow(this).unsafe_cast_ref())
755 }
756 unsafe {
757 let f: Box_<F> = Box_::new(f);
758 connect_raw(
759 self.as_ptr() as *mut _,
760 b"stop-button\0".as_ptr() as *const _,
761 Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
762 stop_button_trampoline::<Self, F> as *const (),
763 )),
764 Box_::into_raw(f),
765 )
766 }
767 }
768}
769
770impl<O: IsA<Drive>> DriveExt for O {}