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)]
96 #[doc(alias = "g_dbus_object_manager_client_new")]
97 pub fn new<P: FnOnce(Result<DBusObjectManagerClient, glib::Error>) + Send + Sync + 'static>(
98 connection: &DBusConnection,
99 flags: DBusObjectManagerClientFlags,
100 name: &str,
101 object_path: &str,
102 cancellable: Option<&impl IsA<Cancellable>>,
103 callback: P,
104 ) {
105 Self::new_impl(
106 connection,
107 flags,
108 name,
109 object_path,
110 None,
111 cancellable,
112 callback,
113 )
114 }
115
116 #[allow(clippy::new_ret_no_self)]
117 #[doc(alias = "g_dbus_object_manager_client_new")]
118 pub fn new_with_fn<
119 P: FnOnce(Result<DBusObjectManagerClient, glib::Error>) + Send + Sync + 'static,
120 F: Fn(&DBusObjectManagerClient, &str, Option<&str>) -> glib::types::Type
121 + Send
122 + Sync
123 + 'static,
124 >(
125 connection: &DBusConnection,
126 flags: DBusObjectManagerClientFlags,
127 name: &str,
128 object_path: &str,
129 get_proxy_type_func: F,
130 cancellable: Option<&impl IsA<Cancellable>>,
131 callback: P,
132 ) {
133 Self::new_impl(
134 connection,
135 flags,
136 name,
137 object_path,
138 Some(Box::new(get_proxy_type_func)),
139 cancellable,
140 callback,
141 )
142 }
143
144 #[allow(clippy::new_ret_no_self)]
145 fn new_impl<P: FnOnce(Result<DBusObjectManagerClient, glib::Error>) + Send + Sync + 'static>(
146 connection: &DBusConnection,
147 flags: DBusObjectManagerClientFlags,
148 name: &str,
149 object_path: &str,
150 get_proxy_type_func: Option<DBusProxyTypeFn>,
151 cancellable: Option<&impl IsA<Cancellable>>,
152 callback: P,
153 ) {
154 let main_context = glib::MainContext::ref_thread_default();
155 let is_main_context_owner = main_context.is_owner();
156 let has_acquired_main_context = (!is_main_context_owner)
157 .then(|| main_context.acquire().ok())
158 .flatten();
159 assert!(
160 is_main_context_owner || has_acquired_main_context.is_some(),
161 "Async operations only allowed if the thread is owning the MainContext"
162 );
163
164 unsafe extern "C" fn get_proxy_type_func_func(
165 manager: *mut ffi::GDBusObjectManagerClient,
166 object_path: *const std::ffi::c_char,
167 interface_name: *const std::ffi::c_char,
168 data: glib::ffi::gpointer,
169 ) -> glib::ffi::GType {
170 let manager = from_glib_borrow(manager);
171 let object_path: Borrowed<glib::GString> = from_glib_borrow(object_path);
172 let interface_name: Borrowed<Option<glib::GString>> = from_glib_borrow(interface_name);
173 let callback = &*(data as *mut Option<DBusProxyTypeFn>);
174 if let Some(ref callback) = *callback {
175 callback(
176 &manager,
177 object_path.as_str(),
178 (*interface_name).as_ref().map(|s| s.as_str()),
179 )
180 } else {
181 panic!("cannot get closure...")
182 }
183 .into_glib()
184 }
185
186 unsafe extern "C" fn get_proxy_type_destroy_notify_func(data: glib::ffi::gpointer) {
187 let _callback = Box::from_raw(data as *mut Option<DBusProxyTypeFn>);
188 }
189
190 unsafe extern "C" fn new_trampoline<
191 P: FnOnce(Result<DBusObjectManagerClient, glib::Error>) + Send + Sync + 'static,
192 >(
193 _source_object: *mut glib::gobject_ffi::GObject,
194 res: *mut crate::ffi::GAsyncResult,
195 user_data: glib::ffi::gpointer,
196 ) {
197 let mut error = std::ptr::null_mut();
198 let ret = ffi::g_dbus_object_manager_client_new_finish(res, &mut error);
199 let result = if error.is_null() {
200 Ok(from_glib_full(ret))
201 } else {
202 Err(from_glib_full(error))
203 };
204 let callback: Box<glib::thread_guard::ThreadGuard<P>> =
205 Box::from_raw(user_data as *mut _);
206 let callback: P = callback.into_inner();
207 callback(result);
208 }
209
210 let get_proxy_type_user_data = Box::new(get_proxy_type_func);
211 let get_proxy_type_func = if get_proxy_type_user_data.is_some() {
212 Some(get_proxy_type_func_func as _)
213 } else {
214 None
215 };
216 let get_proxy_type_destroy_notify = if get_proxy_type_user_data.is_some() {
217 Some(get_proxy_type_destroy_notify_func as _)
218 } else {
219 None
220 };
221
222 let user_data: Box<glib::thread_guard::ThreadGuard<P>> =
223 Box::new(glib::thread_guard::ThreadGuard::new(callback));
224 let callback = new_trampoline::<P>;
225
226 unsafe {
227 ffi::g_dbus_object_manager_client_new(
228 connection.to_glib_none().0,
229 flags.into_glib(),
230 name.to_glib_none().0,
231 object_path.to_glib_none().0,
232 get_proxy_type_func,
233 Box::into_raw(get_proxy_type_user_data) as *mut _,
234 get_proxy_type_destroy_notify,
235 cancellable.map(|p| p.as_ref()).to_glib_none().0,
236 Some(callback),
237 Box::into_raw(user_data) as *mut _,
238 );
239 }
240 }
241
242 pub fn new_future(
243 connection: &DBusConnection,
244 flags: DBusObjectManagerClientFlags,
245 name: &str,
246 object_path: &str,
247 ) -> Pin<Box<dyn Future<Output = Result<DBusObjectManagerClient, glib::Error>> + 'static>> {
248 Self::new_future_impl(connection, flags, name, object_path, None)
249 }
250
251 pub fn new_future_with_fn<
252 F: Fn(&DBusObjectManagerClient, &str, Option<&str>) -> glib::types::Type
253 + Send
254 + Sync
255 + 'static,
256 >(
257 connection: &DBusConnection,
258 flags: DBusObjectManagerClientFlags,
259 name: &str,
260 object_path: &str,
261 get_proxy_type_func: F,
262 ) -> Pin<Box<dyn Future<Output = Result<DBusObjectManagerClient, glib::Error>> + 'static>> {
263 Self::new_future_impl(
264 connection,
265 flags,
266 name,
267 object_path,
268 Some(Box::new(get_proxy_type_func)),
269 )
270 }
271
272 fn new_future_impl(
273 connection: &DBusConnection,
274 flags: DBusObjectManagerClientFlags,
275 name: &str,
276 object_path: &str,
277 get_proxy_type_func: Option<DBusProxyTypeFn>,
278 ) -> Pin<Box<dyn Future<Output = Result<DBusObjectManagerClient, glib::Error>> + 'static>> {
279 let connection = connection.clone();
280 let name = String::from(name);
281 let object_path = String::from(object_path);
282 Box::pin(GioFuture::new(&(), move |_obj, cancellable, send| {
283 Self::new_impl(
284 &connection,
285 flags,
286 &name,
287 &object_path,
288 get_proxy_type_func,
289 Some(cancellable),
290 move |res| {
291 send.resolve(res);
292 },
293 );
294 }))
295 }
296
297 #[doc(alias = "g_dbus_object_manager_client_new_for_bus")]
298 #[allow(clippy::new_ret_no_self)]
299 pub fn new_for_bus<
300 P: FnOnce(Result<DBusObjectManagerClient, glib::Error>) + Send + Sync + 'static,
301 >(
302 bus_type: BusType,
303 flags: DBusObjectManagerClientFlags,
304 name: &str,
305 object_path: &str,
306 cancellable: Option<&impl IsA<Cancellable>>,
307 callback: P,
308 ) {
309 Self::new_for_bus_impl(
310 bus_type,
311 flags,
312 name,
313 object_path,
314 None,
315 cancellable,
316 callback,
317 );
318 }
319
320 #[doc(alias = "g_dbus_object_manager_client_new_for_bus")]
321 #[allow(clippy::new_ret_no_self)]
322 pub fn new_for_bus_with_fn<
323 P: FnOnce(Result<DBusObjectManagerClient, glib::Error>) + Send + Sync + 'static,
324 F: Fn(&DBusObjectManagerClient, &str, Option<&str>) -> glib::types::Type
325 + Send
326 + Sync
327 + 'static,
328 >(
329 bus_type: BusType,
330 flags: DBusObjectManagerClientFlags,
331 name: &str,
332 object_path: &str,
333 get_proxy_type_func: F,
334 cancellable: Option<&impl IsA<Cancellable>>,
335 callback: P,
336 ) {
337 Self::new_for_bus_impl(
338 bus_type,
339 flags,
340 name,
341 object_path,
342 Some(Box::new(get_proxy_type_func)),
343 cancellable,
344 callback,
345 );
346 }
347
348 #[allow(clippy::new_ret_no_self)]
349 fn new_for_bus_impl<
350 P: FnOnce(Result<DBusObjectManagerClient, glib::Error>) + Send + Sync + 'static,
351 >(
352 bus_type: BusType,
353 flags: DBusObjectManagerClientFlags,
354 name: &str,
355 object_path: &str,
356 get_proxy_type_func: Option<DBusProxyTypeFn>,
357 cancellable: Option<&impl IsA<Cancellable>>,
358 callback: P,
359 ) {
360 let main_context = glib::MainContext::ref_thread_default();
361 let is_main_context_owner = main_context.is_owner();
362 let has_acquired_main_context = (!is_main_context_owner)
363 .then(|| main_context.acquire().ok())
364 .flatten();
365 assert!(
366 is_main_context_owner || has_acquired_main_context.is_some(),
367 "Async operations only allowed if the thread is owning the MainContext"
368 );
369
370 unsafe extern "C" fn get_proxy_type_func_func(
371 manager: *mut ffi::GDBusObjectManagerClient,
372 object_path: *const std::ffi::c_char,
373 interface_name: *const std::ffi::c_char,
374 data: glib::ffi::gpointer,
375 ) -> glib::ffi::GType {
376 let manager = from_glib_borrow(manager);
377 let object_path: Borrowed<glib::GString> = from_glib_borrow(object_path);
378 let interface_name: Borrowed<Option<glib::GString>> = from_glib_borrow(interface_name);
379 let callback = &*(data as *mut Option<DBusProxyTypeFn>);
380 if let Some(ref callback) = *callback {
381 callback(
382 &manager,
383 object_path.as_str(),
384 (*interface_name).as_ref().map(|s| s.as_str()),
385 )
386 } else {
387 panic!("cannot get closure...")
388 }
389 .into_glib()
390 }
391
392 unsafe extern "C" fn get_proxy_type_destroy_notify_func(data: glib::ffi::gpointer) {
393 let _callback = Box::from_raw(data as *mut Option<DBusProxyTypeFn>);
394 }
395
396 unsafe extern "C" fn new_for_bus_trampoline<
397 P: FnOnce(Result<DBusObjectManagerClient, glib::Error>) + Send + Sync + 'static,
398 >(
399 _source_object: *mut glib::gobject_ffi::GObject,
400 res: *mut crate::ffi::GAsyncResult,
401 user_data: glib::ffi::gpointer,
402 ) {
403 let mut error = std::ptr::null_mut();
404 let ret = ffi::g_dbus_object_manager_client_new_finish(res, &mut error);
405 let result = if error.is_null() {
406 Ok(from_glib_full(ret))
407 } else {
408 Err(from_glib_full(error))
409 };
410 let callback: Box<glib::thread_guard::ThreadGuard<P>> =
411 Box::from_raw(user_data as *mut _);
412 let callback: P = callback.into_inner();
413 callback(result);
414 }
415
416 let get_proxy_type_user_data = Box::new(get_proxy_type_func);
417 let get_proxy_type_func = if get_proxy_type_user_data.is_some() {
418 Some(get_proxy_type_func_func as _)
419 } else {
420 None
421 };
422 let get_proxy_type_destroy_notify = if get_proxy_type_user_data.is_some() {
423 Some(get_proxy_type_destroy_notify_func as _)
424 } else {
425 None
426 };
427
428 let user_data: Box<glib::thread_guard::ThreadGuard<P>> =
429 Box::new(glib::thread_guard::ThreadGuard::new(callback));
430 let callback = new_for_bus_trampoline::<P>;
431
432 unsafe {
433 ffi::g_dbus_object_manager_client_new_for_bus(
434 bus_type.into_glib(),
435 flags.into_glib(),
436 name.to_glib_none().0,
437 object_path.to_glib_none().0,
438 get_proxy_type_func,
439 Box::into_raw(get_proxy_type_user_data) as *mut _,
440 get_proxy_type_destroy_notify,
441 cancellable.map(|p| p.as_ref()).to_glib_none().0,
442 Some(callback),
443 Box::into_raw(user_data) as *mut _,
444 );
445 }
446 }
447
448 pub fn new_for_bus_future(
449 bus_type: BusType,
450 flags: DBusObjectManagerClientFlags,
451 name: &str,
452 object_path: &str,
453 ) -> Pin<Box<dyn Future<Output = Result<DBusObjectManagerClient, glib::Error>> + 'static>> {
454 Self::new_for_bus_future_impl(bus_type, flags, name, object_path, None)
455 }
456
457 pub fn new_for_bus_future_with_fn<
458 F: Fn(&DBusObjectManagerClient, &str, Option<&str>) -> glib::types::Type
459 + Send
460 + Sync
461 + 'static,
462 >(
463 bus_type: BusType,
464 flags: DBusObjectManagerClientFlags,
465 name: &str,
466 object_path: &str,
467 get_proxy_type_func: F,
468 ) -> Pin<Box<dyn Future<Output = Result<DBusObjectManagerClient, glib::Error>> + 'static>> {
469 Self::new_for_bus_future_impl(
470 bus_type,
471 flags,
472 name,
473 object_path,
474 Some(Box::new(get_proxy_type_func)),
475 )
476 }
477
478 fn new_for_bus_future_impl(
479 bus_type: BusType,
480 flags: DBusObjectManagerClientFlags,
481 name: &str,
482 object_path: &str,
483 get_proxy_type_func: Option<DBusProxyTypeFn>,
484 ) -> Pin<Box<dyn Future<Output = Result<DBusObjectManagerClient, glib::Error>> + 'static>> {
485 let name = String::from(name);
486 let object_path = String::from(object_path);
487 Box::pin(GioFuture::new(&(), move |_obj, cancellable, send| {
488 Self::new_for_bus_impl(
489 bus_type,
490 flags,
491 &name,
492 &object_path,
493 get_proxy_type_func,
494 Some(cancellable),
495 move |res| {
496 send.resolve(res);
497 },
498 );
499 }))
500 }
501}
502
503pub trait DBusObjectManagerClientExtManual: IsA<DBusObjectManagerClient> + 'static {
504 #[doc(alias = "interface-proxy-properties-changed")]
505 fn connect_interface_proxy_properties_changed<
506 F: Fn(&Self, &DBusObjectProxy, &DBusProxy, &glib::Variant, &StrVRef) + Send + Sync + 'static,
507 >(
508 &self,
509 f: F,
510 ) -> SignalHandlerId {
511 unsafe extern "C" fn interface_proxy_properties_changed_trampoline<
512 P: IsA<DBusObjectManagerClient>,
513 F: Fn(&P, &DBusObjectProxy, &DBusProxy, &glib::Variant, &StrVRef) + Send + Sync + 'static,
514 >(
515 this: *mut ffi::GDBusObjectManagerClient,
516 object_proxy: *mut ffi::GDBusObjectProxy,
517 interface_proxy: *mut ffi::GDBusProxy,
518 changed_properties: *mut glib::ffi::GVariant,
519 invalidated_properties: *const *const std::ffi::c_char,
520 f: glib::ffi::gpointer,
521 ) {
522 let f: &F = &*(f as *const F);
523 f(
524 DBusObjectManagerClient::from_glib_borrow(this).unsafe_cast_ref(),
525 &from_glib_borrow(object_proxy),
526 &from_glib_borrow(interface_proxy),
527 &from_glib_borrow(changed_properties),
528 StrVRef::from_glib_borrow(invalidated_properties),
529 )
530 }
531 unsafe {
532 let f: Box<F> = Box::new(f);
533 connect_raw(
534 self.as_ptr() as *mut _,
535 c"interface-proxy-properties-changed".as_ptr() as *const _,
536 Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
537 interface_proxy_properties_changed_trampoline::<Self, F> as *const (),
538 )),
539 Box::into_raw(f),
540 )
541 }
542 }
543}
544
545impl<O: IsA<DBusObjectManagerClient>> DBusObjectManagerClientExtManual for O {}