1use crate::{ffi, Session, UsbDevice};
7use glib::{
8 object::ObjectType as _,
9 prelude::*,
10 signal::{connect_raw, SignalHandlerId},
11 translate::*,
12};
13use std::{boxed::Box as Box_, pin::Pin};
14
15glib::wrapper! {
16 #[doc(alias = "SpiceUsbDeviceManager")]
17 pub struct UsbDeviceManager(Object<ffi::SpiceUsbDeviceManager, ffi::SpiceUsbDeviceManagerClass>);
18
19 match fn {
20 type_ => || ffi::spice_usb_device_manager_get_type(),
21 }
22}
23
24impl UsbDeviceManager {
25 #[cfg(feature = "v0_40")]
26 #[cfg_attr(docsrs, doc(cfg(feature = "v0_40")))]
27 #[doc(alias = "spice_usb_device_manager_allocate_device_for_file_descriptor")]
28 pub fn allocate_device_for_file_descriptor(
29 &self,
30 file_descriptor: i32,
31 ) -> Result<Option<UsbDevice>, glib::Error> {
32 unsafe {
33 let mut error = std::ptr::null_mut();
34 let ret = ffi::spice_usb_device_manager_allocate_device_for_file_descriptor(
35 self.to_glib_none().0,
36 file_descriptor,
37 &mut error,
38 );
39 if error.is_null() {
40 Ok(from_glib_full(ret))
41 } else {
42 Err(from_glib_full(error))
43 }
44 }
45 }
46
47 #[doc(alias = "spice_usb_device_manager_can_redirect_device")]
48 pub fn can_redirect_device(&self, device: &UsbDevice) -> Result<(), glib::Error> {
49 unsafe {
50 let mut error = std::ptr::null_mut();
51 let is_ok = ffi::spice_usb_device_manager_can_redirect_device(
52 self.to_glib_none().0,
53 mut_override(device.to_glib_none().0),
54 &mut error,
55 );
56 debug_assert_eq!(is_ok == glib::ffi::GFALSE, !error.is_null());
57 if error.is_null() {
58 Ok(())
59 } else {
60 Err(from_glib_full(error))
61 }
62 }
63 }
64
65 #[doc(alias = "spice_usb_device_manager_connect_device_async")]
66 pub fn connect_device_async<P: FnOnce(Result<(), glib::Error>) + 'static>(
67 &self,
68 device: &UsbDevice,
69 cancellable: Option<&impl IsA<gio::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 connect_device_async_trampoline<
85 P: FnOnce(Result<(), glib::Error>) + 'static,
86 >(
87 _source_object: *mut glib::gobject_ffi::GObject,
88 res: *mut gio::ffi::GAsyncResult,
89 user_data: glib::ffi::gpointer,
90 ) {
91 unsafe {
92 let mut error = std::ptr::null_mut();
93 ffi::spice_usb_device_manager_connect_device_finish(
94 _source_object as *mut _,
95 res,
96 &mut error,
97 );
98 let result = if error.is_null() {
99 Ok(())
100 } else {
101 Err(from_glib_full(error))
102 };
103 let callback: Box_<glib::thread_guard::ThreadGuard<P>> =
104 Box_::from_raw(user_data as *mut _);
105 let callback: P = callback.into_inner();
106 callback(result);
107 }
108 }
109 let callback = connect_device_async_trampoline::<P>;
110 unsafe {
111 ffi::spice_usb_device_manager_connect_device_async(
112 self.to_glib_none().0,
113 mut_override(device.to_glib_none().0),
114 cancellable.map(|p| p.as_ref()).to_glib_none().0,
115 Some(callback),
116 Box_::into_raw(user_data) as *mut _,
117 );
118 }
119 }
120
121 pub fn connect_device_future(
122 &self,
123 device: &UsbDevice,
124 ) -> Pin<Box_<dyn std::future::Future<Output = Result<(), glib::Error>> + 'static>> {
125 let device = device.clone();
126 Box_::pin(gio::GioFuture::new(self, move |obj, cancellable, send| {
127 obj.connect_device_async(&device, Some(cancellable), move |res| {
128 send.resolve(res);
129 });
130 }))
131 }
132
133 #[doc(alias = "spice_usb_device_manager_create_shared_cd_device")]
134 pub fn create_shared_cd_device(&self, filename: &str) -> Result<(), glib::Error> {
135 unsafe {
136 let mut error = std::ptr::null_mut();
137 let is_ok = ffi::spice_usb_device_manager_create_shared_cd_device(
138 self.to_glib_none().0,
139 filename.to_glib_none().0,
140 &mut error,
141 );
142 debug_assert_eq!(is_ok == glib::ffi::GFALSE, !error.is_null());
143 if error.is_null() {
144 Ok(())
145 } else {
146 Err(from_glib_full(error))
147 }
148 }
149 }
150
151 #[doc(alias = "spice_usb_device_manager_disconnect_device")]
152 pub fn disconnect_device(&self, device: &UsbDevice) {
153 unsafe {
154 ffi::spice_usb_device_manager_disconnect_device(
155 self.to_glib_none().0,
156 mut_override(device.to_glib_none().0),
157 );
158 }
159 }
160
161 #[doc(alias = "spice_usb_device_manager_disconnect_device_async")]
162 pub fn disconnect_device_async<P: FnOnce(Result<(), glib::Error>) + 'static>(
163 &self,
164 device: &UsbDevice,
165 cancellable: Option<&impl IsA<gio::Cancellable>>,
166 callback: P,
167 ) {
168 let main_context = glib::MainContext::ref_thread_default();
169 let is_main_context_owner = main_context.is_owner();
170 let has_acquired_main_context = (!is_main_context_owner)
171 .then(|| main_context.acquire().ok())
172 .flatten();
173 assert!(
174 is_main_context_owner || has_acquired_main_context.is_some(),
175 "Async operations only allowed if the thread is owning the MainContext"
176 );
177
178 let user_data: Box_<glib::thread_guard::ThreadGuard<P>> =
179 Box_::new(glib::thread_guard::ThreadGuard::new(callback));
180 unsafe extern "C" fn disconnect_device_async_trampoline<
181 P: FnOnce(Result<(), glib::Error>) + 'static,
182 >(
183 _source_object: *mut glib::gobject_ffi::GObject,
184 res: *mut gio::ffi::GAsyncResult,
185 user_data: glib::ffi::gpointer,
186 ) {
187 unsafe {
188 let mut error = std::ptr::null_mut();
189 ffi::spice_usb_device_manager_disconnect_device_finish(
190 _source_object as *mut _,
191 res,
192 &mut error,
193 );
194 let result = if error.is_null() {
195 Ok(())
196 } else {
197 Err(from_glib_full(error))
198 };
199 let callback: Box_<glib::thread_guard::ThreadGuard<P>> =
200 Box_::from_raw(user_data as *mut _);
201 let callback: P = callback.into_inner();
202 callback(result);
203 }
204 }
205 let callback = disconnect_device_async_trampoline::<P>;
206 unsafe {
207 ffi::spice_usb_device_manager_disconnect_device_async(
208 self.to_glib_none().0,
209 mut_override(device.to_glib_none().0),
210 cancellable.map(|p| p.as_ref()).to_glib_none().0,
211 Some(callback),
212 Box_::into_raw(user_data) as *mut _,
213 );
214 }
215 }
216
217 pub fn disconnect_device_future(
218 &self,
219 device: &UsbDevice,
220 ) -> Pin<Box_<dyn std::future::Future<Output = Result<(), glib::Error>> + 'static>> {
221 let device = device.clone();
222 Box_::pin(gio::GioFuture::new(self, move |obj, cancellable, send| {
223 obj.disconnect_device_async(&device, Some(cancellable), move |res| {
224 send.resolve(res);
225 });
226 }))
227 }
228
229 #[doc(alias = "spice_usb_device_manager_get_devices")]
230 #[doc(alias = "get_devices")]
231 pub fn devices(&self) -> Vec<UsbDevice> {
232 unsafe {
233 FromGlibPtrContainer::from_glib_full(ffi::spice_usb_device_manager_get_devices(
234 self.to_glib_none().0,
235 ))
236 }
237 }
238
239 #[doc(alias = "spice_usb_device_manager_get_devices_with_filter")]
240 #[doc(alias = "get_devices_with_filter")]
241 pub fn devices_with_filter(&self, filter: Option<&str>) -> Vec<UsbDevice> {
242 unsafe {
243 FromGlibPtrContainer::from_glib_full(
244 ffi::spice_usb_device_manager_get_devices_with_filter(
245 self.to_glib_none().0,
246 filter.to_glib_none().0,
247 ),
248 )
249 }
250 }
251
252 #[doc(alias = "spice_usb_device_manager_is_device_connected")]
253 pub fn is_device_connected(&self, device: &UsbDevice) -> bool {
254 unsafe {
255 from_glib(ffi::spice_usb_device_manager_is_device_connected(
256 self.to_glib_none().0,
257 mut_override(device.to_glib_none().0),
258 ))
259 }
260 }
261
262 #[doc(alias = "spice_usb_device_manager_is_device_shared_cd")]
263 pub fn is_device_shared_cd(&self, device: &UsbDevice) -> bool {
264 unsafe {
265 from_glib(ffi::spice_usb_device_manager_is_device_shared_cd(
266 self.to_glib_none().0,
267 mut_override(device.to_glib_none().0),
268 ))
269 }
270 }
271
272 #[doc(alias = "spice_usb_device_manager_is_redirecting")]
273 pub fn is_redirecting(&self) -> bool {
274 unsafe {
275 from_glib(ffi::spice_usb_device_manager_is_redirecting(
276 self.to_glib_none().0,
277 ))
278 }
279 }
280
281 #[doc(alias = "auto-connect")]
282 pub fn is_auto_connect(&self) -> bool {
283 ObjectExt::property(self, "auto-connect")
284 }
285
286 #[doc(alias = "auto-connect")]
287 pub fn set_auto_connect(&self, auto_connect: bool) {
288 ObjectExt::set_property(self, "auto-connect", auto_connect)
289 }
290
291 #[doc(alias = "auto-connect-filter")]
292 pub fn auto_connect_filter(&self) -> Option<glib::GString> {
293 ObjectExt::property(self, "auto-connect-filter")
294 }
295
296 #[doc(alias = "auto-connect-filter")]
297 pub fn set_auto_connect_filter(&self, auto_connect_filter: Option<&str>) {
298 ObjectExt::set_property(self, "auto-connect-filter", auto_connect_filter)
299 }
300
301 #[doc(alias = "free-channels")]
302 pub fn free_channels(&self) -> i32 {
303 ObjectExt::property(self, "free-channels")
304 }
305
306 #[doc(alias = "redirect-on-connect")]
307 pub fn redirect_on_connect(&self) -> Option<glib::GString> {
308 ObjectExt::property(self, "redirect-on-connect")
309 }
310
311 #[doc(alias = "redirect-on-connect")]
312 pub fn set_redirect_on_connect(&self, redirect_on_connect: Option<&str>) {
313 ObjectExt::set_property(self, "redirect-on-connect", redirect_on_connect)
314 }
315
316 pub fn session(&self) -> Option<Session> {
317 ObjectExt::property(self, "session")
318 }
319
320 #[doc(alias = "spice_usb_device_manager_get")]
321 pub fn get(session: &Session) -> Result<UsbDeviceManager, glib::Error> {
322 skip_assert_initialized!();
323 unsafe {
324 let mut error = std::ptr::null_mut();
325 let ret = ffi::spice_usb_device_manager_get(session.to_glib_none().0, &mut error);
326 if error.is_null() {
327 Ok(from_glib_none(ret))
328 } else {
329 Err(from_glib_full(error))
330 }
331 }
332 }
333
334 #[doc(alias = "auto-connect-failed")]
335 pub fn connect_auto_connect_failed<F: Fn(&Self, &UsbDevice, &glib::Error) + 'static>(
336 &self,
337 f: F,
338 ) -> SignalHandlerId {
339 unsafe extern "C" fn auto_connect_failed_trampoline<
340 F: Fn(&UsbDeviceManager, &UsbDevice, &glib::Error) + 'static,
341 >(
342 this: *mut ffi::SpiceUsbDeviceManager,
343 device: *mut ffi::SpiceUsbDevice,
344 error: *mut glib::ffi::GError,
345 f: glib::ffi::gpointer,
346 ) {
347 unsafe {
348 let f: &F = &*(f as *const F);
349 f(
350 &from_glib_borrow(this),
351 &from_glib_borrow(device),
352 &from_glib_borrow(error),
353 )
354 }
355 }
356 unsafe {
357 let f: Box_<F> = Box_::new(f);
358 connect_raw(
359 self.as_ptr() as *mut _,
360 c"auto-connect-failed".as_ptr(),
361 Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
362 auto_connect_failed_trampoline::<F> as *const (),
363 )),
364 Box_::into_raw(f),
365 )
366 }
367 }
368
369 #[doc(alias = "device-added")]
370 pub fn connect_device_added<F: Fn(&Self, &UsbDevice) + 'static>(
371 &self,
372 f: F,
373 ) -> SignalHandlerId {
374 unsafe extern "C" fn device_added_trampoline<
375 F: Fn(&UsbDeviceManager, &UsbDevice) + 'static,
376 >(
377 this: *mut ffi::SpiceUsbDeviceManager,
378 device: *mut ffi::SpiceUsbDevice,
379 f: glib::ffi::gpointer,
380 ) {
381 unsafe {
382 let f: &F = &*(f as *const F);
383 f(&from_glib_borrow(this), &from_glib_borrow(device))
384 }
385 }
386 unsafe {
387 let f: Box_<F> = Box_::new(f);
388 connect_raw(
389 self.as_ptr() as *mut _,
390 c"device-added".as_ptr(),
391 Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
392 device_added_trampoline::<F> as *const (),
393 )),
394 Box_::into_raw(f),
395 )
396 }
397 }
398
399 #[doc(alias = "device-error")]
400 pub fn connect_device_error<F: Fn(&Self, &UsbDevice, &glib::Error) + 'static>(
401 &self,
402 f: F,
403 ) -> SignalHandlerId {
404 unsafe extern "C" fn device_error_trampoline<
405 F: Fn(&UsbDeviceManager, &UsbDevice, &glib::Error) + 'static,
406 >(
407 this: *mut ffi::SpiceUsbDeviceManager,
408 device: *mut ffi::SpiceUsbDevice,
409 error: *mut glib::ffi::GError,
410 f: glib::ffi::gpointer,
411 ) {
412 unsafe {
413 let f: &F = &*(f as *const F);
414 f(
415 &from_glib_borrow(this),
416 &from_glib_borrow(device),
417 &from_glib_borrow(error),
418 )
419 }
420 }
421 unsafe {
422 let f: Box_<F> = Box_::new(f);
423 connect_raw(
424 self.as_ptr() as *mut _,
425 c"device-error".as_ptr(),
426 Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
427 device_error_trampoline::<F> as *const (),
428 )),
429 Box_::into_raw(f),
430 )
431 }
432 }
433
434 #[doc(alias = "device-removed")]
435 pub fn connect_device_removed<F: Fn(&Self, &UsbDevice) + 'static>(
436 &self,
437 f: F,
438 ) -> SignalHandlerId {
439 unsafe extern "C" fn device_removed_trampoline<
440 F: Fn(&UsbDeviceManager, &UsbDevice) + 'static,
441 >(
442 this: *mut ffi::SpiceUsbDeviceManager,
443 device: *mut ffi::SpiceUsbDevice,
444 f: glib::ffi::gpointer,
445 ) {
446 unsafe {
447 let f: &F = &*(f as *const F);
448 f(&from_glib_borrow(this), &from_glib_borrow(device))
449 }
450 }
451 unsafe {
452 let f: Box_<F> = Box_::new(f);
453 connect_raw(
454 self.as_ptr() as *mut _,
455 c"device-removed".as_ptr(),
456 Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
457 device_removed_trampoline::<F> as *const (),
458 )),
459 Box_::into_raw(f),
460 )
461 }
462 }
463
464 #[doc(alias = "auto-connect")]
465 pub fn connect_auto_connect_notify<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId {
466 unsafe extern "C" fn notify_auto_connect_trampoline<F: Fn(&UsbDeviceManager) + 'static>(
467 this: *mut ffi::SpiceUsbDeviceManager,
468 _param_spec: glib::ffi::gpointer,
469 f: glib::ffi::gpointer,
470 ) {
471 unsafe {
472 let f: &F = &*(f as *const F);
473 f(&from_glib_borrow(this))
474 }
475 }
476 unsafe {
477 let f: Box_<F> = Box_::new(f);
478 connect_raw(
479 self.as_ptr() as *mut _,
480 c"notify::auto-connect".as_ptr(),
481 Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
482 notify_auto_connect_trampoline::<F> as *const (),
483 )),
484 Box_::into_raw(f),
485 )
486 }
487 }
488
489 #[doc(alias = "auto-connect-filter")]
490 pub fn connect_auto_connect_filter_notify<F: Fn(&Self) + 'static>(
491 &self,
492 f: F,
493 ) -> SignalHandlerId {
494 unsafe extern "C" fn notify_auto_connect_filter_trampoline<
495 F: Fn(&UsbDeviceManager) + 'static,
496 >(
497 this: *mut ffi::SpiceUsbDeviceManager,
498 _param_spec: glib::ffi::gpointer,
499 f: glib::ffi::gpointer,
500 ) {
501 unsafe {
502 let f: &F = &*(f as *const F);
503 f(&from_glib_borrow(this))
504 }
505 }
506 unsafe {
507 let f: Box_<F> = Box_::new(f);
508 connect_raw(
509 self.as_ptr() as *mut _,
510 c"notify::auto-connect-filter".as_ptr(),
511 Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
512 notify_auto_connect_filter_trampoline::<F> as *const (),
513 )),
514 Box_::into_raw(f),
515 )
516 }
517 }
518
519 #[doc(alias = "free-channels")]
520 pub fn connect_free_channels_notify<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId {
521 unsafe extern "C" fn notify_free_channels_trampoline<F: Fn(&UsbDeviceManager) + 'static>(
522 this: *mut ffi::SpiceUsbDeviceManager,
523 _param_spec: glib::ffi::gpointer,
524 f: glib::ffi::gpointer,
525 ) {
526 unsafe {
527 let f: &F = &*(f as *const F);
528 f(&from_glib_borrow(this))
529 }
530 }
531 unsafe {
532 let f: Box_<F> = Box_::new(f);
533 connect_raw(
534 self.as_ptr() as *mut _,
535 c"notify::free-channels".as_ptr(),
536 Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
537 notify_free_channels_trampoline::<F> as *const (),
538 )),
539 Box_::into_raw(f),
540 )
541 }
542 }
543
544 #[doc(alias = "redirect-on-connect")]
545 pub fn connect_redirect_on_connect_notify<F: Fn(&Self) + 'static>(
546 &self,
547 f: F,
548 ) -> SignalHandlerId {
549 unsafe extern "C" fn notify_redirect_on_connect_trampoline<
550 F: Fn(&UsbDeviceManager) + 'static,
551 >(
552 this: *mut ffi::SpiceUsbDeviceManager,
553 _param_spec: glib::ffi::gpointer,
554 f: glib::ffi::gpointer,
555 ) {
556 unsafe {
557 let f: &F = &*(f as *const F);
558 f(&from_glib_borrow(this))
559 }
560 }
561 unsafe {
562 let f: Box_<F> = Box_::new(f);
563 connect_raw(
564 self.as_ptr() as *mut _,
565 c"notify::redirect-on-connect".as_ptr(),
566 Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
567 notify_redirect_on_connect_trampoline::<F> as *const (),
568 )),
569 Box_::into_raw(f),
570 )
571 }
572 }
573}