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