1 // Take a look at the license at the top of the repository in the LICENSE file.
2 
3 use crate::ActionGroup;
4 use crate::DBusConnection;
5 use crate::DBusInterfaceInfo;
6 use crate::DBusMessage;
7 use crate::DBusMethodInvocation;
8 use crate::DBusSignalFlags;
9 use crate::MenuModel;
10 use glib::object::IsA;
11 use glib::translate::*;
12 use std::boxed::Box as Box_;
13 use std::num::NonZeroU32;
14 
15 #[derive(Debug, Eq, PartialEq)]
16 pub struct RegistrationId(NonZeroU32);
17 #[derive(Debug, Eq, PartialEq)]
18 pub struct WatcherId(NonZeroU32);
19 #[derive(Debug, Eq, PartialEq)]
20 pub struct ActionGroupExportId(NonZeroU32);
21 #[derive(Debug, Eq, PartialEq)]
22 pub struct MenuModelExportId(NonZeroU32);
23 #[derive(Debug, Eq, PartialEq)]
24 pub struct FilterId(NonZeroU32);
25 #[derive(Debug, Eq, PartialEq)]
26 pub struct SignalSubscriptionId(NonZeroU32);
27 
28 impl DBusConnection {
29     #[doc(alias = "g_dbus_connection_register_object_with_closures")]
register_object<MethodCall, SetProperty, GetProperty>( &self, object_path: &str, interface_info: &DBusInterfaceInfo, method_call: MethodCall, get_property: GetProperty, set_property: SetProperty, ) -> Result<RegistrationId, glib::Error> where MethodCall: Fn(DBusConnection, &str, &str, &str, &str, glib::Variant, DBusMethodInvocation) + Send + Sync + 'static, GetProperty: Fn(DBusConnection, &str, &str, &str, &str) -> glib::Variant + Send + Sync + 'static, SetProperty: Fn(DBusConnection, &str, &str, &str, &str, glib::Variant) -> bool + Send + Sync + 'static,30     pub fn register_object<MethodCall, SetProperty, GetProperty>(
31         &self,
32         object_path: &str,
33         interface_info: &DBusInterfaceInfo,
34         method_call: MethodCall,
35         get_property: GetProperty,
36         set_property: SetProperty,
37     ) -> Result<RegistrationId, glib::Error>
38     where
39         MethodCall: Fn(DBusConnection, &str, &str, &str, &str, glib::Variant, DBusMethodInvocation)
40             + Send
41             + Sync
42             + 'static,
43         GetProperty:
44             Fn(DBusConnection, &str, &str, &str, &str) -> glib::Variant + Send + Sync + 'static,
45         SetProperty: Fn(DBusConnection, &str, &str, &str, &str, glib::Variant) -> bool
46             + Send
47             + Sync
48             + 'static,
49     {
50         use glib::ToValue;
51         unsafe {
52             let mut error = std::ptr::null_mut();
53             let id = ffi::g_dbus_connection_register_object_with_closures(
54                 self.to_glib_none().0,
55                 object_path.to_glib_none().0,
56                 interface_info.to_glib_none().0,
57                 glib::Closure::new(move |args| {
58                     let conn = args[0].get::<DBusConnection>().unwrap();
59                     let sender = args[1].get::<&str>().unwrap();
60                     let object_path = args[2].get::<&str>().unwrap();
61                     let interface_name = args[3].get::<&str>().unwrap();
62                     let method_name = args[4].get::<&str>().unwrap();
63                     let parameters = args[5].get::<glib::Variant>().unwrap();
64                     let invocation = args[6].get::<DBusMethodInvocation>().unwrap();
65                     method_call(
66                         conn,
67                         sender,
68                         object_path,
69                         interface_name,
70                         method_name,
71                         parameters,
72                         invocation,
73                     );
74                     None
75                 })
76                 .to_glib_none()
77                 .0,
78                 glib::Closure::new(move |args| {
79                     let conn = args[0].get::<DBusConnection>().unwrap();
80                     let sender = args[1].get::<&str>().unwrap();
81                     let object_path = args[2].get::<&str>().unwrap();
82                     let interface_name = args[3].get::<&str>().unwrap();
83                     let property_name = args[4].get::<&str>().unwrap();
84                     let result =
85                         get_property(conn, sender, object_path, interface_name, property_name);
86                     Some(result.to_value())
87                 })
88                 .to_glib_none()
89                 .0,
90                 glib::Closure::new(move |args| {
91                     let conn = args[0].get::<DBusConnection>().unwrap();
92                     let sender = args[1].get::<&str>().unwrap();
93                     let object_path = args[2].get::<&str>().unwrap();
94                     let interface_name = args[3].get::<&str>().unwrap();
95                     let property_name = args[4].get::<&str>().unwrap();
96                     let value = args[5].get::<glib::Variant>().unwrap();
97                     let result = set_property(
98                         conn,
99                         sender,
100                         object_path,
101                         interface_name,
102                         property_name,
103                         value,
104                     );
105                     Some(result.to_value())
106                 })
107                 .to_glib_none()
108                 .0,
109                 &mut error,
110             );
111             if error.is_null() {
112                 Ok(RegistrationId(NonZeroU32::new_unchecked(id)))
113             } else {
114                 Err(from_glib_full(error))
115             }
116         }
117     }
118 
119     #[doc(alias = "g_dbus_connection_unregister_object")]
unregister_object( &self, registration_id: RegistrationId, ) -> Result<(), glib::error::BoolError>120     pub fn unregister_object(
121         &self,
122         registration_id: RegistrationId,
123     ) -> Result<(), glib::error::BoolError> {
124         unsafe {
125             glib::result_from_gboolean!(
126                 ffi::g_dbus_connection_unregister_object(
127                     self.to_glib_none().0,
128                     registration_id.0.into()
129                 ),
130                 "Failed to unregister D-Bus object"
131             )
132         }
133     }
134 
135     #[doc(alias = "g_dbus_connection_export_action_group")]
export_action_group<P: IsA<ActionGroup>>( &self, object_path: &str, action_group: &P, ) -> Result<ActionGroupExportId, glib::Error>136     pub fn export_action_group<P: IsA<ActionGroup>>(
137         &self,
138         object_path: &str,
139         action_group: &P,
140     ) -> Result<ActionGroupExportId, glib::Error> {
141         unsafe {
142             let mut error = std::ptr::null_mut();
143             let id = ffi::g_dbus_connection_export_action_group(
144                 self.to_glib_none().0,
145                 object_path.to_glib_none().0,
146                 action_group.as_ref().to_glib_none().0,
147                 &mut error,
148             );
149             if error.is_null() {
150                 Ok(ActionGroupExportId(NonZeroU32::new_unchecked(id)))
151             } else {
152                 Err(from_glib_full(error))
153             }
154         }
155     }
156 
157     #[doc(alias = "g_dbus_connection_unexport_action_group")]
unexport_action_group(&self, export_id: ActionGroupExportId)158     pub fn unexport_action_group(&self, export_id: ActionGroupExportId) {
159         unsafe {
160             ffi::g_dbus_connection_unexport_action_group(self.to_glib_none().0, export_id.0.into());
161         }
162     }
163 
164     #[doc(alias = "g_dbus_connection_export_menu_model")]
export_menu_model<P: IsA<MenuModel>>( &self, object_path: &str, menu: &P, ) -> Result<MenuModelExportId, glib::Error>165     pub fn export_menu_model<P: IsA<MenuModel>>(
166         &self,
167         object_path: &str,
168         menu: &P,
169     ) -> Result<MenuModelExportId, glib::Error> {
170         unsafe {
171             let mut error = std::ptr::null_mut();
172             let id = ffi::g_dbus_connection_export_menu_model(
173                 self.to_glib_none().0,
174                 object_path.to_glib_none().0,
175                 menu.as_ref().to_glib_none().0,
176                 &mut error,
177             );
178             if error.is_null() {
179                 Ok(MenuModelExportId(NonZeroU32::new_unchecked(id)))
180             } else {
181                 Err(from_glib_full(error))
182             }
183         }
184     }
185 
186     #[doc(alias = "g_dbus_connection_unexport_menu_model")]
unexport_menu_model(&self, export_id: MenuModelExportId)187     pub fn unexport_menu_model(&self, export_id: MenuModelExportId) {
188         unsafe {
189             ffi::g_dbus_connection_unexport_menu_model(self.to_glib_none().0, export_id.0.into());
190         }
191     }
192 
193     #[doc(alias = "g_dbus_connection_add_filter")]
add_filter< P: Fn(&DBusConnection, &DBusMessage, bool) -> Option<DBusMessage> + 'static, >( &self, filter_function: P, ) -> FilterId194     pub fn add_filter<
195         P: Fn(&DBusConnection, &DBusMessage, bool) -> Option<DBusMessage> + 'static,
196     >(
197         &self,
198         filter_function: P,
199     ) -> FilterId {
200         let filter_function_data: Box_<P> = Box_::new(filter_function);
201         unsafe extern "C" fn filter_function_func<
202             P: Fn(&DBusConnection, &DBusMessage, bool) -> Option<DBusMessage> + 'static,
203         >(
204             connection: *mut ffi::GDBusConnection,
205             message: *mut ffi::GDBusMessage,
206             incoming: glib::ffi::gboolean,
207             user_data: glib::ffi::gpointer,
208         ) -> *mut ffi::GDBusMessage {
209             let connection = from_glib_borrow(connection);
210             let message = from_glib_full(message);
211             let incoming = from_glib(incoming);
212             let callback: &P = &*(user_data as *mut _);
213             let res = (*callback)(&connection, &message, incoming);
214             res.to_glib_full()
215         }
216         let filter_function = Some(filter_function_func::<P> as _);
217         unsafe extern "C" fn user_data_free_func_func<
218             P: Fn(&DBusConnection, &DBusMessage, bool) -> Option<DBusMessage> + 'static,
219         >(
220             data: glib::ffi::gpointer,
221         ) {
222             let _callback: Box_<P> = Box_::from_raw(data as *mut _);
223         }
224         let destroy_call3 = Some(user_data_free_func_func::<P> as _);
225         let super_callback0: Box_<P> = filter_function_data;
226         unsafe {
227             let id = ffi::g_dbus_connection_add_filter(
228                 self.to_glib_none().0,
229                 filter_function,
230                 Box_::into_raw(super_callback0) as *mut _,
231                 destroy_call3,
232             );
233             FilterId(NonZeroU32::new_unchecked(id))
234         }
235     }
236 
237     #[doc(alias = "g_dbus_connection_remove_filter")]
remove_filter(&self, filter_id: FilterId)238     pub fn remove_filter(&self, filter_id: FilterId) {
239         unsafe {
240             ffi::g_dbus_connection_remove_filter(self.to_glib_none().0, filter_id.0.into());
241         }
242     }
243 
244     #[doc(alias = "g_dbus_connection_signal_subscribe")]
signal_subscribe< P: Fn(&DBusConnection, &str, &str, &str, &str, &glib::Variant) + 'static, >( &self, sender: Option<&str>, interface_name: Option<&str>, member: Option<&str>, object_path: Option<&str>, arg0: Option<&str>, flags: DBusSignalFlags, callback: P, ) -> SignalSubscriptionId245     pub fn signal_subscribe<
246         P: Fn(&DBusConnection, &str, &str, &str, &str, &glib::Variant) + 'static,
247     >(
248         &self,
249         sender: Option<&str>,
250         interface_name: Option<&str>,
251         member: Option<&str>,
252         object_path: Option<&str>,
253         arg0: Option<&str>,
254         flags: DBusSignalFlags,
255         callback: P,
256     ) -> SignalSubscriptionId {
257         let callback_data: Box_<P> = Box_::new(callback);
258         unsafe extern "C" fn callback_func<
259             P: Fn(&DBusConnection, &str, &str, &str, &str, &glib::Variant) + 'static,
260         >(
261             connection: *mut ffi::GDBusConnection,
262             sender_name: *const libc::c_char,
263             object_path: *const libc::c_char,
264             interface_name: *const libc::c_char,
265             signal_name: *const libc::c_char,
266             parameters: *mut glib::ffi::GVariant,
267             user_data: glib::ffi::gpointer,
268         ) {
269             let connection = from_glib_borrow(connection);
270             let sender_name: Borrowed<glib::GString> = from_glib_borrow(sender_name);
271             let object_path: Borrowed<glib::GString> = from_glib_borrow(object_path);
272             let interface_name: Borrowed<glib::GString> = from_glib_borrow(interface_name);
273             let signal_name: Borrowed<glib::GString> = from_glib_borrow(signal_name);
274             let parameters = from_glib_borrow(parameters);
275             let callback: &P = &*(user_data as *mut _);
276             (*callback)(
277                 &connection,
278                 sender_name.as_str(),
279                 object_path.as_str(),
280                 interface_name.as_str(),
281                 signal_name.as_str(),
282                 &parameters,
283             );
284         }
285         let callback = Some(callback_func::<P> as _);
286         unsafe extern "C" fn user_data_free_func_func<
287             P: Fn(&DBusConnection, &str, &str, &str, &str, &glib::Variant) + 'static,
288         >(
289             data: glib::ffi::gpointer,
290         ) {
291             let _callback: Box_<P> = Box_::from_raw(data as *mut _);
292         }
293         let destroy_call9 = Some(user_data_free_func_func::<P> as _);
294         let super_callback0: Box_<P> = callback_data;
295         unsafe {
296             let id = ffi::g_dbus_connection_signal_subscribe(
297                 self.to_glib_none().0,
298                 sender.to_glib_none().0,
299                 interface_name.to_glib_none().0,
300                 member.to_glib_none().0,
301                 object_path.to_glib_none().0,
302                 arg0.to_glib_none().0,
303                 flags.into_glib(),
304                 callback,
305                 Box_::into_raw(super_callback0) as *mut _,
306                 destroy_call9,
307             );
308             SignalSubscriptionId(NonZeroU32::new_unchecked(id))
309         }
310     }
311 
312     #[doc(alias = "g_dbus_connection_signal_unsubscribe")]
signal_unsubscribe(&self, subscription_id: SignalSubscriptionId)313     pub fn signal_unsubscribe(&self, subscription_id: SignalSubscriptionId) {
314         unsafe {
315             ffi::g_dbus_connection_signal_unsubscribe(
316                 self.to_glib_none().0,
317                 subscription_id.0.into(),
318             );
319         }
320     }
321 }
322