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 ¶meters, 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