1use crate::{
4 ffi, BusType, Cancellable, DBusConnection, DBusObjectManagerClient,
5 DBusObjectManagerClientFlags, DBusObjectProxy, DBusProxy, GioFuture,
6};
7use glib::object::{Cast as _, IsA};
8use glib::signal::connect_raw;
9use glib::translate::{
10 from_glib_borrow, from_glib_full, Borrowed, FromGlibPtrBorrow as _, IntoGlib as _,
11 ToGlibPtr as _,
12};
13use glib::{SignalHandlerId, StrVRef};
14use std::future::Future;
15use std::pin::Pin;
16
17type DBusProxyTypeFn = Box<
18 dyn Fn(&DBusObjectManagerClient, &str, Option<&str>) -> glib::types::Type
19 + Send
20 + Sync
21 + 'static,
22>;
23
24impl DBusObjectManagerClient {
25 #[doc(alias = "g_dbus_object_manager_client_new_sync")]
26 pub fn new_sync(
27 connection: &DBusConnection,
28 flags: DBusObjectManagerClientFlags,
29 name: Option<&str>,
30 object_path: &str,
31 cancellable: Option<&impl IsA<Cancellable>>,
32 ) -> Result<DBusObjectManagerClient, glib::Error> {
33 Self::new_sync_impl(connection, flags, name, object_path, None, cancellable)
34 }
35
36 #[doc(alias = "g_dbus_object_manager_client_new_sync")]
37 pub fn new_sync_with_fn<
38 F: Fn(&DBusObjectManagerClient, &str, Option<&str>) -> glib::types::Type
39 + Send
40 + Sync
41 + 'static,
42 >(
43 connection: &DBusConnection,
44 flags: DBusObjectManagerClientFlags,
45 name: Option<&str>,
46 object_path: &str,
47 get_proxy_type_func: F,
48 cancellable: Option<&impl IsA<Cancellable>>,
49 ) -> Result<DBusObjectManagerClient, glib::Error> {
50 Self::new_sync_impl(
51 connection,
52 flags,
53 name,
54 object_path,
55 Some(Box::new(get_proxy_type_func)),
56 cancellable,
57 )
58 }
59
60 #[doc(alias = "g_dbus_object_manager_client_new_for_bus_sync")]
61 pub fn for_bus_sync(
62 bus_type: BusType,
63 flags: DBusObjectManagerClientFlags,
64 name: &str,
65 object_path: &str,
66 cancellable: Option<&impl IsA<Cancellable>>,
67 ) -> Result<DBusObjectManagerClient, glib::Error> {
68 Self::for_bus_sync_impl(bus_type, flags, name, object_path, None, cancellable)
69 }
70
71 #[doc(alias = "g_dbus_object_manager_client_new_for_bus_sync")]
72 pub fn for_bus_sync_with_fn<
73 F: Fn(&DBusObjectManagerClient, &str, Option<&str>) -> glib::types::Type
74 + Send
75 + Sync
76 + 'static,
77 >(
78 bus_type: BusType,
79 flags: DBusObjectManagerClientFlags,
80 name: &str,
81 object_path: &str,
82 get_proxy_type_func: F,
83 cancellable: Option<&impl IsA<Cancellable>>,
84 ) -> Result<DBusObjectManagerClient, glib::Error> {
85 Self::for_bus_sync_impl(
86 bus_type,
87 flags,
88 name,
89 object_path,
90 Some(Box::new(get_proxy_type_func)),
91 cancellable,
92 )
93 }
94
95 #[allow(clippy::new_ret_no_self)]
122 #[doc(alias = "g_dbus_object_manager_client_new")]
123 pub fn new<P: FnOnce(Result<DBusObjectManagerClient, glib::Error>) + Send + Sync + 'static>(
124 connection: &DBusConnection,
125 flags: DBusObjectManagerClientFlags,
126 name: &str,
127 object_path: &str,
128 cancellable: Option<&impl IsA<Cancellable>>,
129 callback: P,
130 ) {
131 Self::new_impl(
132 connection,
133 flags,
134 name,
135 object_path,
136 None,
137 cancellable,
138 callback,
139 )
140 }
141
142 #[allow(clippy::new_ret_no_self)]
143 #[doc(alias = "g_dbus_object_manager_client_new")]
144 pub fn new_with_fn<
145 P: FnOnce(Result<DBusObjectManagerClient, glib::Error>) + Send + Sync + 'static,
146 F: Fn(&DBusObjectManagerClient, &str, Option<&str>) -> glib::types::Type
147 + Send
148 + Sync
149 + 'static,
150 >(
151 connection: &DBusConnection,
152 flags: DBusObjectManagerClientFlags,
153 name: &str,
154 object_path: &str,
155 get_proxy_type_func: F,
156 cancellable: Option<&impl IsA<Cancellable>>,
157 callback: P,
158 ) {
159 Self::new_impl(
160 connection,
161 flags,
162 name,
163 object_path,
164 Some(Box::new(get_proxy_type_func)),
165 cancellable,
166 callback,
167 )
168 }
169
170 #[allow(clippy::new_ret_no_self)]
171 fn new_impl<P: FnOnce(Result<DBusObjectManagerClient, glib::Error>) + Send + Sync + 'static>(
172 connection: &DBusConnection,
173 flags: DBusObjectManagerClientFlags,
174 name: &str,
175 object_path: &str,
176 get_proxy_type_func: Option<DBusProxyTypeFn>,
177 cancellable: Option<&impl IsA<Cancellable>>,
178 callback: P,
179 ) {
180 let main_context = glib::MainContext::ref_thread_default();
181 let is_main_context_owner = main_context.is_owner();
182 let has_acquired_main_context = (!is_main_context_owner)
183 .then(|| main_context.acquire().ok())
184 .flatten();
185 assert!(
186 is_main_context_owner || has_acquired_main_context.is_some(),
187 "Async operations only allowed if the thread is owning the MainContext"
188 );
189
190 unsafe extern "C" fn get_proxy_type_func_func(
191 manager: *mut ffi::GDBusObjectManagerClient,
192 object_path: *const std::ffi::c_char,
193 interface_name: *const std::ffi::c_char,
194 data: glib::ffi::gpointer,
195 ) -> glib::ffi::GType {
196 let manager = from_glib_borrow(manager);
197 let object_path: Borrowed<glib::GString> = from_glib_borrow(object_path);
198 let interface_name: Borrowed<Option<glib::GString>> = from_glib_borrow(interface_name);
199 let callback = &*(data as *mut Option<DBusProxyTypeFn>);
200 if let Some(ref callback) = *callback {
201 callback(
202 &manager,
203 object_path.as_str(),
204 (*interface_name).as_ref().map(|s| s.as_str()),
205 )
206 } else {
207 panic!("cannot get closure...")
208 }
209 .into_glib()
210 }
211
212 unsafe extern "C" fn get_proxy_type_destroy_notify_func(data: glib::ffi::gpointer) {
213 let _callback = Box::from_raw(data as *mut Option<DBusProxyTypeFn>);
214 }
215
216 unsafe extern "C" fn new_trampoline<
217 P: FnOnce(Result<DBusObjectManagerClient, glib::Error>) + Send + Sync + 'static,
218 >(
219 _source_object: *mut glib::gobject_ffi::GObject,
220 res: *mut crate::ffi::GAsyncResult,
221 user_data: glib::ffi::gpointer,
222 ) {
223 let mut error = std::ptr::null_mut();
224 let ret = ffi::g_dbus_object_manager_client_new_finish(res, &mut error);
225 let result = if error.is_null() {
226 Ok(from_glib_full(ret))
227 } else {
228 Err(from_glib_full(error))
229 };
230 let callback: Box<glib::thread_guard::ThreadGuard<P>> =
231 Box::from_raw(user_data as *mut _);
232 let callback: P = callback.into_inner();
233 callback(result);
234 }
235
236 let get_proxy_type_user_data = Box::new(get_proxy_type_func);
237 let get_proxy_type_func = if get_proxy_type_user_data.is_some() {
238 Some(get_proxy_type_func_func as _)
239 } else {
240 None
241 };
242 let get_proxy_type_destroy_notify = if get_proxy_type_user_data.is_some() {
243 Some(get_proxy_type_destroy_notify_func as _)
244 } else {
245 None
246 };
247
248 let user_data: Box<glib::thread_guard::ThreadGuard<P>> =
249 Box::new(glib::thread_guard::ThreadGuard::new(callback));
250 let callback = new_trampoline::<P>;
251
252 unsafe {
253 ffi::g_dbus_object_manager_client_new(
254 connection.to_glib_none().0,
255 flags.into_glib(),
256 name.to_glib_none().0,
257 object_path.to_glib_none().0,
258 get_proxy_type_func,
259 Box::into_raw(get_proxy_type_user_data) as *mut _,
260 get_proxy_type_destroy_notify,
261 cancellable.map(|p| p.as_ref()).to_glib_none().0,
262 Some(callback),
263 Box::into_raw(user_data) as *mut _,
264 );
265 }
266 }
267
268 pub fn new_future(
269 connection: &DBusConnection,
270 flags: DBusObjectManagerClientFlags,
271 name: &str,
272 object_path: &str,
273 ) -> Pin<Box<dyn Future<Output = Result<DBusObjectManagerClient, glib::Error>> + 'static>> {
274 Self::new_future_impl(connection, flags, name, object_path, None)
275 }
276
277 pub fn new_future_with_fn<
278 F: Fn(&DBusObjectManagerClient, &str, Option<&str>) -> glib::types::Type
279 + Send
280 + Sync
281 + 'static,
282 >(
283 connection: &DBusConnection,
284 flags: DBusObjectManagerClientFlags,
285 name: &str,
286 object_path: &str,
287 get_proxy_type_func: F,
288 ) -> Pin<Box<dyn Future<Output = Result<DBusObjectManagerClient, glib::Error>> + 'static>> {
289 Self::new_future_impl(
290 connection,
291 flags,
292 name,
293 object_path,
294 Some(Box::new(get_proxy_type_func)),
295 )
296 }
297
298 fn new_future_impl(
299 connection: &DBusConnection,
300 flags: DBusObjectManagerClientFlags,
301 name: &str,
302 object_path: &str,
303 get_proxy_type_func: Option<DBusProxyTypeFn>,
304 ) -> Pin<Box<dyn Future<Output = Result<DBusObjectManagerClient, glib::Error>> + 'static>> {
305 let connection = connection.clone();
306 let name = String::from(name);
307 let object_path = String::from(object_path);
308 Box::pin(GioFuture::new(&(), move |_obj, cancellable, send| {
309 Self::new_impl(
310 &connection,
311 flags,
312 &name,
313 &object_path,
314 get_proxy_type_func,
315 Some(cancellable),
316 move |res| {
317 send.resolve(res);
318 },
319 );
320 }))
321 }
322
323 #[doc(alias = "g_dbus_object_manager_client_new_for_bus")]
351 #[allow(clippy::new_ret_no_self)]
352 pub fn new_for_bus<
353 P: FnOnce(Result<DBusObjectManagerClient, glib::Error>) + Send + Sync + 'static,
354 >(
355 bus_type: BusType,
356 flags: DBusObjectManagerClientFlags,
357 name: &str,
358 object_path: &str,
359 cancellable: Option<&impl IsA<Cancellable>>,
360 callback: P,
361 ) {
362 Self::new_for_bus_impl(
363 bus_type,
364 flags,
365 name,
366 object_path,
367 None,
368 cancellable,
369 callback,
370 );
371 }
372
373 #[doc(alias = "g_dbus_object_manager_client_new_for_bus")]
374 #[allow(clippy::new_ret_no_self)]
375 pub fn new_for_bus_with_fn<
376 P: FnOnce(Result<DBusObjectManagerClient, glib::Error>) + Send + Sync + 'static,
377 F: Fn(&DBusObjectManagerClient, &str, Option<&str>) -> glib::types::Type
378 + Send
379 + Sync
380 + 'static,
381 >(
382 bus_type: BusType,
383 flags: DBusObjectManagerClientFlags,
384 name: &str,
385 object_path: &str,
386 get_proxy_type_func: F,
387 cancellable: Option<&impl IsA<Cancellable>>,
388 callback: P,
389 ) {
390 Self::new_for_bus_impl(
391 bus_type,
392 flags,
393 name,
394 object_path,
395 Some(Box::new(get_proxy_type_func)),
396 cancellable,
397 callback,
398 );
399 }
400
401 #[allow(clippy::new_ret_no_self)]
402 fn new_for_bus_impl<
403 P: FnOnce(Result<DBusObjectManagerClient, glib::Error>) + Send + Sync + 'static,
404 >(
405 bus_type: BusType,
406 flags: DBusObjectManagerClientFlags,
407 name: &str,
408 object_path: &str,
409 get_proxy_type_func: Option<DBusProxyTypeFn>,
410 cancellable: Option<&impl IsA<Cancellable>>,
411 callback: P,
412 ) {
413 let main_context = glib::MainContext::ref_thread_default();
414 let is_main_context_owner = main_context.is_owner();
415 let has_acquired_main_context = (!is_main_context_owner)
416 .then(|| main_context.acquire().ok())
417 .flatten();
418 assert!(
419 is_main_context_owner || has_acquired_main_context.is_some(),
420 "Async operations only allowed if the thread is owning the MainContext"
421 );
422
423 unsafe extern "C" fn get_proxy_type_func_func(
424 manager: *mut ffi::GDBusObjectManagerClient,
425 object_path: *const std::ffi::c_char,
426 interface_name: *const std::ffi::c_char,
427 data: glib::ffi::gpointer,
428 ) -> glib::ffi::GType {
429 let manager = from_glib_borrow(manager);
430 let object_path: Borrowed<glib::GString> = from_glib_borrow(object_path);
431 let interface_name: Borrowed<Option<glib::GString>> = from_glib_borrow(interface_name);
432 let callback = &*(data as *mut Option<DBusProxyTypeFn>);
433 if let Some(ref callback) = *callback {
434 callback(
435 &manager,
436 object_path.as_str(),
437 (*interface_name).as_ref().map(|s| s.as_str()),
438 )
439 } else {
440 panic!("cannot get closure...")
441 }
442 .into_glib()
443 }
444
445 unsafe extern "C" fn get_proxy_type_destroy_notify_func(data: glib::ffi::gpointer) {
446 let _callback = Box::from_raw(data as *mut Option<DBusProxyTypeFn>);
447 }
448
449 unsafe extern "C" fn new_for_bus_trampoline<
450 P: FnOnce(Result<DBusObjectManagerClient, glib::Error>) + Send + Sync + 'static,
451 >(
452 _source_object: *mut glib::gobject_ffi::GObject,
453 res: *mut crate::ffi::GAsyncResult,
454 user_data: glib::ffi::gpointer,
455 ) {
456 let mut error = std::ptr::null_mut();
457 let ret = ffi::g_dbus_object_manager_client_new_finish(res, &mut error);
458 let result = if error.is_null() {
459 Ok(from_glib_full(ret))
460 } else {
461 Err(from_glib_full(error))
462 };
463 let callback: Box<glib::thread_guard::ThreadGuard<P>> =
464 Box::from_raw(user_data as *mut _);
465 let callback: P = callback.into_inner();
466 callback(result);
467 }
468
469 let get_proxy_type_user_data = Box::new(get_proxy_type_func);
470 let get_proxy_type_func = if get_proxy_type_user_data.is_some() {
471 Some(get_proxy_type_func_func as _)
472 } else {
473 None
474 };
475 let get_proxy_type_destroy_notify = if get_proxy_type_user_data.is_some() {
476 Some(get_proxy_type_destroy_notify_func as _)
477 } else {
478 None
479 };
480
481 let user_data: Box<glib::thread_guard::ThreadGuard<P>> =
482 Box::new(glib::thread_guard::ThreadGuard::new(callback));
483 let callback = new_for_bus_trampoline::<P>;
484
485 unsafe {
486 ffi::g_dbus_object_manager_client_new_for_bus(
487 bus_type.into_glib(),
488 flags.into_glib(),
489 name.to_glib_none().0,
490 object_path.to_glib_none().0,
491 get_proxy_type_func,
492 Box::into_raw(get_proxy_type_user_data) as *mut _,
493 get_proxy_type_destroy_notify,
494 cancellable.map(|p| p.as_ref()).to_glib_none().0,
495 Some(callback),
496 Box::into_raw(user_data) as *mut _,
497 );
498 }
499 }
500
501 pub fn new_for_bus_future(
502 bus_type: BusType,
503 flags: DBusObjectManagerClientFlags,
504 name: &str,
505 object_path: &str,
506 ) -> Pin<Box<dyn Future<Output = Result<DBusObjectManagerClient, glib::Error>> + 'static>> {
507 Self::new_for_bus_future_impl(bus_type, flags, name, object_path, None)
508 }
509
510 pub fn new_for_bus_future_with_fn<
511 F: Fn(&DBusObjectManagerClient, &str, Option<&str>) -> glib::types::Type
512 + Send
513 + Sync
514 + 'static,
515 >(
516 bus_type: BusType,
517 flags: DBusObjectManagerClientFlags,
518 name: &str,
519 object_path: &str,
520 get_proxy_type_func: F,
521 ) -> Pin<Box<dyn Future<Output = Result<DBusObjectManagerClient, glib::Error>> + 'static>> {
522 Self::new_for_bus_future_impl(
523 bus_type,
524 flags,
525 name,
526 object_path,
527 Some(Box::new(get_proxy_type_func)),
528 )
529 }
530
531 fn new_for_bus_future_impl(
532 bus_type: BusType,
533 flags: DBusObjectManagerClientFlags,
534 name: &str,
535 object_path: &str,
536 get_proxy_type_func: Option<DBusProxyTypeFn>,
537 ) -> Pin<Box<dyn Future<Output = Result<DBusObjectManagerClient, glib::Error>> + 'static>> {
538 let name = String::from(name);
539 let object_path = String::from(object_path);
540 Box::pin(GioFuture::new(&(), move |_obj, cancellable, send| {
541 Self::new_for_bus_impl(
542 bus_type,
543 flags,
544 &name,
545 &object_path,
546 get_proxy_type_func,
547 Some(cancellable),
548 move |res| {
549 send.resolve(res);
550 },
551 );
552 }))
553 }
554}
555
556pub trait DBusObjectManagerClientExtManual: IsA<DBusObjectManagerClient> + 'static {
557 #[doc(alias = "interface-proxy-properties-changed")]
558 fn connect_interface_proxy_properties_changed<
559 F: Fn(&Self, &DBusObjectProxy, &DBusProxy, &glib::Variant, &StrVRef) + Send + Sync + 'static,
560 >(
561 &self,
562 f: F,
563 ) -> SignalHandlerId {
564 unsafe extern "C" fn interface_proxy_properties_changed_trampoline<
565 P: IsA<DBusObjectManagerClient>,
566 F: Fn(&P, &DBusObjectProxy, &DBusProxy, &glib::Variant, &StrVRef) + Send + Sync + 'static,
567 >(
568 this: *mut ffi::GDBusObjectManagerClient,
569 object_proxy: *mut ffi::GDBusObjectProxy,
570 interface_proxy: *mut ffi::GDBusProxy,
571 changed_properties: *mut glib::ffi::GVariant,
572 invalidated_properties: *const *const std::ffi::c_char,
573 f: glib::ffi::gpointer,
574 ) {
575 let f: &F = &*(f as *const F);
576 f(
577 DBusObjectManagerClient::from_glib_borrow(this).unsafe_cast_ref(),
578 &from_glib_borrow(object_proxy),
579 &from_glib_borrow(interface_proxy),
580 &from_glib_borrow(changed_properties),
581 StrVRef::from_glib_borrow(invalidated_properties),
582 )
583 }
584 unsafe {
585 let f: Box<F> = Box::new(f);
586 connect_raw(
587 self.as_ptr() as *mut _,
588 c"interface-proxy-properties-changed".as_ptr() as *const _,
589 Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
590 interface_proxy_properties_changed_trampoline::<Self, F> as *const (),
591 )),
592 Box::into_raw(f),
593 )
594 }
595 }
596}
597
598impl<O: IsA<DBusObjectManagerClient>> DBusObjectManagerClientExtManual for O {}