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")]
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
91pub trait DriveExt: IsA<Drive> + 'static {
97 #[doc(alias = "g_drive_can_eject")]
103 fn can_eject(&self) -> bool {
104 unsafe { from_glib(ffi::g_drive_can_eject(self.as_ref().to_glib_none().0)) }
105 }
106
107 #[doc(alias = "g_drive_can_poll_for_media")]
114 fn can_poll_for_media(&self) -> bool {
115 unsafe {
116 from_glib(ffi::g_drive_can_poll_for_media(
117 self.as_ref().to_glib_none().0,
118 ))
119 }
120 }
121
122 #[doc(alias = "g_drive_can_start")]
128 fn can_start(&self) -> bool {
129 unsafe { from_glib(ffi::g_drive_can_start(self.as_ref().to_glib_none().0)) }
130 }
131
132 #[doc(alias = "g_drive_can_start_degraded")]
138 fn can_start_degraded(&self) -> bool {
139 unsafe {
140 from_glib(ffi::g_drive_can_start_degraded(
141 self.as_ref().to_glib_none().0,
142 ))
143 }
144 }
145
146 #[doc(alias = "g_drive_can_stop")]
152 fn can_stop(&self) -> bool {
153 unsafe { from_glib(ffi::g_drive_can_stop(self.as_ref().to_glib_none().0)) }
154 }
155
156 #[doc(alias = "g_drive_eject_with_operation")]
169 fn eject_with_operation<P: FnOnce(Result<(), glib::Error>) + 'static>(
170 &self,
171 flags: MountUnmountFlags,
172 mount_operation: Option<&impl IsA<MountOperation>>,
173 cancellable: Option<&impl IsA<Cancellable>>,
174 callback: P,
175 ) {
176 let main_context = glib::MainContext::ref_thread_default();
177 let is_main_context_owner = main_context.is_owner();
178 let has_acquired_main_context = (!is_main_context_owner)
179 .then(|| main_context.acquire().ok())
180 .flatten();
181 assert!(
182 is_main_context_owner || has_acquired_main_context.is_some(),
183 "Async operations only allowed if the thread is owning the MainContext"
184 );
185
186 let user_data: Box_<glib::thread_guard::ThreadGuard<P>> =
187 Box_::new(glib::thread_guard::ThreadGuard::new(callback));
188 unsafe extern "C" fn eject_with_operation_trampoline<
189 P: FnOnce(Result<(), glib::Error>) + 'static,
190 >(
191 _source_object: *mut glib::gobject_ffi::GObject,
192 res: *mut crate::ffi::GAsyncResult,
193 user_data: glib::ffi::gpointer,
194 ) {
195 unsafe {
196 let mut error = std::ptr::null_mut();
197 ffi::g_drive_eject_with_operation_finish(_source_object as *mut _, res, &mut error);
198 let result = if error.is_null() {
199 Ok(())
200 } else {
201 Err(from_glib_full(error))
202 };
203 let callback: Box_<glib::thread_guard::ThreadGuard<P>> =
204 Box_::from_raw(user_data as *mut _);
205 let callback: P = callback.into_inner();
206 callback(result);
207 }
208 }
209 let callback = eject_with_operation_trampoline::<P>;
210 unsafe {
211 ffi::g_drive_eject_with_operation(
212 self.as_ref().to_glib_none().0,
213 flags.into_glib(),
214 mount_operation.map(|p| p.as_ref()).to_glib_none().0,
215 cancellable.map(|p| p.as_ref()).to_glib_none().0,
216 Some(callback),
217 Box_::into_raw(user_data) as *mut _,
218 );
219 }
220 }
221
222 fn eject_with_operation_future(
223 &self,
224 flags: MountUnmountFlags,
225 mount_operation: Option<&(impl IsA<MountOperation> + Clone + 'static)>,
226 ) -> Pin<Box_<dyn std::future::Future<Output = Result<(), glib::Error>> + 'static>> {
227 let mount_operation = mount_operation.map(ToOwned::to_owned);
228 Box_::pin(crate::GioFuture::new(
229 self,
230 move |obj, cancellable, send| {
231 obj.eject_with_operation(
232 flags,
233 mount_operation.as_ref().map(::std::borrow::Borrow::borrow),
234 Some(cancellable),
235 move |res| {
236 send.resolve(res);
237 },
238 );
239 },
240 ))
241 }
242
243 #[doc(alias = "g_drive_enumerate_identifiers")]
253 fn enumerate_identifiers(&self) -> Vec<glib::GString> {
254 unsafe {
255 FromGlibPtrContainer::from_glib_full(ffi::g_drive_enumerate_identifiers(
256 self.as_ref().to_glib_none().0,
257 ))
258 }
259 }
260
261 #[doc(alias = "g_drive_get_icon")]
268 #[doc(alias = "get_icon")]
269 fn icon(&self) -> Icon {
270 unsafe { from_glib_full(ffi::g_drive_get_icon(self.as_ref().to_glib_none().0)) }
271 }
272
273 #[doc(alias = "g_drive_get_identifier")]
285 #[doc(alias = "get_identifier")]
286 fn identifier(&self, kind: &str) -> Option<glib::GString> {
287 unsafe {
288 from_glib_full(ffi::g_drive_get_identifier(
289 self.as_ref().to_glib_none().0,
290 kind.to_glib_none().0,
291 ))
292 }
293 }
294
295 #[doc(alias = "g_drive_get_name")]
302 #[doc(alias = "get_name")]
303 fn name(&self) -> glib::GString {
304 unsafe { from_glib_full(ffi::g_drive_get_name(self.as_ref().to_glib_none().0)) }
305 }
306
307 #[doc(alias = "g_drive_get_sort_key")]
313 #[doc(alias = "get_sort_key")]
314 fn sort_key(&self) -> Option<glib::GString> {
315 unsafe { from_glib_none(ffi::g_drive_get_sort_key(self.as_ref().to_glib_none().0)) }
316 }
317
318 #[doc(alias = "g_drive_get_start_stop_type")]
324 #[doc(alias = "get_start_stop_type")]
325 fn start_stop_type(&self) -> DriveStartStopType {
326 unsafe {
327 from_glib(ffi::g_drive_get_start_stop_type(
328 self.as_ref().to_glib_none().0,
329 ))
330 }
331 }
332
333 #[doc(alias = "g_drive_get_symbolic_icon")]
340 #[doc(alias = "get_symbolic_icon")]
341 fn symbolic_icon(&self) -> Icon {
342 unsafe {
343 from_glib_full(ffi::g_drive_get_symbolic_icon(
344 self.as_ref().to_glib_none().0,
345 ))
346 }
347 }
348
349 #[doc(alias = "g_drive_get_volumes")]
358 #[doc(alias = "get_volumes")]
359 fn volumes(&self) -> Vec<Volume> {
360 unsafe {
361 FromGlibPtrContainer::from_glib_full(ffi::g_drive_get_volumes(
362 self.as_ref().to_glib_none().0,
363 ))
364 }
365 }
366
367 #[doc(alias = "g_drive_has_media")]
375 fn has_media(&self) -> bool {
376 unsafe { from_glib(ffi::g_drive_has_media(self.as_ref().to_glib_none().0)) }
377 }
378
379 #[doc(alias = "g_drive_has_volumes")]
385 fn has_volumes(&self) -> bool {
386 unsafe { from_glib(ffi::g_drive_has_volumes(self.as_ref().to_glib_none().0)) }
387 }
388
389 #[doc(alias = "g_drive_is_media_check_automatic")]
396 fn is_media_check_automatic(&self) -> bool {
397 unsafe {
398 from_glib(ffi::g_drive_is_media_check_automatic(
399 self.as_ref().to_glib_none().0,
400 ))
401 }
402 }
403
404 #[doc(alias = "g_drive_is_media_removable")]
410 fn is_media_removable(&self) -> bool {
411 unsafe {
412 from_glib(ffi::g_drive_is_media_removable(
413 self.as_ref().to_glib_none().0,
414 ))
415 }
416 }
417
418 #[doc(alias = "g_drive_is_removable")]
425 fn is_removable(&self) -> bool {
426 unsafe { from_glib(ffi::g_drive_is_removable(self.as_ref().to_glib_none().0)) }
427 }
428
429 #[doc(alias = "g_drive_poll_for_media")]
439 fn poll_for_media<P: FnOnce(Result<(), glib::Error>) + 'static>(
440 &self,
441 cancellable: Option<&impl IsA<Cancellable>>,
442 callback: P,
443 ) {
444 let main_context = glib::MainContext::ref_thread_default();
445 let is_main_context_owner = main_context.is_owner();
446 let has_acquired_main_context = (!is_main_context_owner)
447 .then(|| main_context.acquire().ok())
448 .flatten();
449 assert!(
450 is_main_context_owner || has_acquired_main_context.is_some(),
451 "Async operations only allowed if the thread is owning the MainContext"
452 );
453
454 let user_data: Box_<glib::thread_guard::ThreadGuard<P>> =
455 Box_::new(glib::thread_guard::ThreadGuard::new(callback));
456 unsafe extern "C" fn poll_for_media_trampoline<
457 P: FnOnce(Result<(), glib::Error>) + 'static,
458 >(
459 _source_object: *mut glib::gobject_ffi::GObject,
460 res: *mut crate::ffi::GAsyncResult,
461 user_data: glib::ffi::gpointer,
462 ) {
463 unsafe {
464 let mut error = std::ptr::null_mut();
465 ffi::g_drive_poll_for_media_finish(_source_object as *mut _, res, &mut error);
466 let result = if error.is_null() {
467 Ok(())
468 } else {
469 Err(from_glib_full(error))
470 };
471 let callback: Box_<glib::thread_guard::ThreadGuard<P>> =
472 Box_::from_raw(user_data as *mut _);
473 let callback: P = callback.into_inner();
474 callback(result);
475 }
476 }
477 let callback = poll_for_media_trampoline::<P>;
478 unsafe {
479 ffi::g_drive_poll_for_media(
480 self.as_ref().to_glib_none().0,
481 cancellable.map(|p| p.as_ref()).to_glib_none().0,
482 Some(callback),
483 Box_::into_raw(user_data) as *mut _,
484 );
485 }
486 }
487
488 fn poll_for_media_future(
489 &self,
490 ) -> Pin<Box_<dyn std::future::Future<Output = Result<(), glib::Error>> + 'static>> {
491 Box_::pin(crate::GioFuture::new(
492 self,
493 move |obj, cancellable, send| {
494 obj.poll_for_media(Some(cancellable), move |res| {
495 send.resolve(res);
496 });
497 },
498 ))
499 }
500
501 #[doc(alias = "g_drive_start")]
516 fn start<P: FnOnce(Result<(), glib::Error>) + 'static>(
517 &self,
518 flags: DriveStartFlags,
519 mount_operation: Option<&impl IsA<MountOperation>>,
520 cancellable: Option<&impl IsA<Cancellable>>,
521 callback: P,
522 ) {
523 let main_context = glib::MainContext::ref_thread_default();
524 let is_main_context_owner = main_context.is_owner();
525 let has_acquired_main_context = (!is_main_context_owner)
526 .then(|| main_context.acquire().ok())
527 .flatten();
528 assert!(
529 is_main_context_owner || has_acquired_main_context.is_some(),
530 "Async operations only allowed if the thread is owning the MainContext"
531 );
532
533 let user_data: Box_<glib::thread_guard::ThreadGuard<P>> =
534 Box_::new(glib::thread_guard::ThreadGuard::new(callback));
535 unsafe extern "C" fn start_trampoline<P: FnOnce(Result<(), glib::Error>) + 'static>(
536 _source_object: *mut glib::gobject_ffi::GObject,
537 res: *mut crate::ffi::GAsyncResult,
538 user_data: glib::ffi::gpointer,
539 ) {
540 unsafe {
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 }
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 unsafe {
628 let mut error = std::ptr::null_mut();
629 ffi::g_drive_stop_finish(_source_object as *mut _, res, &mut error);
630 let result = if error.is_null() {
631 Ok(())
632 } else {
633 Err(from_glib_full(error))
634 };
635 let callback: Box_<glib::thread_guard::ThreadGuard<P>> =
636 Box_::from_raw(user_data as *mut _);
637 let callback: P = callback.into_inner();
638 callback(result);
639 }
640 }
641 let callback = stop_trampoline::<P>;
642 unsafe {
643 ffi::g_drive_stop(
644 self.as_ref().to_glib_none().0,
645 flags.into_glib(),
646 mount_operation.map(|p| p.as_ref()).to_glib_none().0,
647 cancellable.map(|p| p.as_ref()).to_glib_none().0,
648 Some(callback),
649 Box_::into_raw(user_data) as *mut _,
650 );
651 }
652 }
653
654 fn stop_future(
655 &self,
656 flags: MountUnmountFlags,
657 mount_operation: Option<&(impl IsA<MountOperation> + Clone + 'static)>,
658 ) -> Pin<Box_<dyn std::future::Future<Output = Result<(), glib::Error>> + 'static>> {
659 let mount_operation = mount_operation.map(ToOwned::to_owned);
660 Box_::pin(crate::GioFuture::new(
661 self,
662 move |obj, cancellable, send| {
663 obj.stop(
664 flags,
665 mount_operation.as_ref().map(::std::borrow::Borrow::borrow),
666 Some(cancellable),
667 move |res| {
668 send.resolve(res);
669 },
670 );
671 },
672 ))
673 }
674
675 #[doc(alias = "changed")]
677 fn connect_changed<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId {
678 unsafe extern "C" fn changed_trampoline<P: IsA<Drive>, F: Fn(&P) + 'static>(
679 this: *mut ffi::GDrive,
680 f: glib::ffi::gpointer,
681 ) {
682 unsafe {
683 let f: &F = &*(f as *const F);
684 f(Drive::from_glib_borrow(this).unsafe_cast_ref())
685 }
686 }
687 unsafe {
688 let f: Box_<F> = Box_::new(f);
689 connect_raw(
690 self.as_ptr() as *mut _,
691 c"changed".as_ptr() as *const _,
692 Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
693 changed_trampoline::<Self, F> as *const (),
694 )),
695 Box_::into_raw(f),
696 )
697 }
698 }
699
700 #[doc(alias = "disconnected")]
705 fn connect_disconnected<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId {
706 unsafe extern "C" fn disconnected_trampoline<P: IsA<Drive>, F: Fn(&P) + 'static>(
707 this: *mut ffi::GDrive,
708 f: glib::ffi::gpointer,
709 ) {
710 unsafe {
711 let f: &F = &*(f as *const F);
712 f(Drive::from_glib_borrow(this).unsafe_cast_ref())
713 }
714 }
715 unsafe {
716 let f: Box_<F> = Box_::new(f);
717 connect_raw(
718 self.as_ptr() as *mut _,
719 c"disconnected".as_ptr() as *const _,
720 Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
721 disconnected_trampoline::<Self, F> as *const (),
722 )),
723 Box_::into_raw(f),
724 )
725 }
726 }
727
728 #[doc(alias = "eject-button")]
731 fn connect_eject_button<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId {
732 unsafe extern "C" fn eject_button_trampoline<P: IsA<Drive>, F: Fn(&P) + 'static>(
733 this: *mut ffi::GDrive,
734 f: glib::ffi::gpointer,
735 ) {
736 unsafe {
737 let f: &F = &*(f as *const F);
738 f(Drive::from_glib_borrow(this).unsafe_cast_ref())
739 }
740 }
741 unsafe {
742 let f: Box_<F> = Box_::new(f);
743 connect_raw(
744 self.as_ptr() as *mut _,
745 c"eject-button".as_ptr() as *const _,
746 Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
747 eject_button_trampoline::<Self, F> as *const (),
748 )),
749 Box_::into_raw(f),
750 )
751 }
752 }
753
754 #[doc(alias = "stop-button")]
757 fn connect_stop_button<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId {
758 unsafe extern "C" fn stop_button_trampoline<P: IsA<Drive>, F: Fn(&P) + 'static>(
759 this: *mut ffi::GDrive,
760 f: glib::ffi::gpointer,
761 ) {
762 unsafe {
763 let f: &F = &*(f as *const F);
764 f(Drive::from_glib_borrow(this).unsafe_cast_ref())
765 }
766 }
767 unsafe {
768 let f: Box_<F> = Box_::new(f);
769 connect_raw(
770 self.as_ptr() as *mut _,
771 c"stop-button".as_ptr() as *const _,
772 Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
773 stop_button_trampoline::<Self, F> as *const (),
774 )),
775 Box_::into_raw(f),
776 )
777 }
778 }
779}
780
781impl<O: IsA<Drive>> DriveExt for O {}