2 * Copyright © 2013 Lars Uebernickel
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License as published
6 * by the Free Software Foundation; either version 2 of the licence or (at
7 * your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General
15 * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
17 * Authors: Lars Uebernickel <lars@uebernic.de>
20 #include "gnotification-server.h"
24 typedef GObjectClass GNotificationServerClass
;
26 struct _GNotificationServer
30 GDBusConnection
*connection
;
36 /* app_ids -> hashtables of notification ids -> a{sv} */
37 GHashTable
*applications
;
40 G_DEFINE_TYPE (GNotificationServer
, g_notification_server
, G_TYPE_OBJECT
);
48 static GDBusInterfaceInfo
*
49 org_gtk_Notifications_get_interface (void)
51 static GDBusInterfaceInfo
*iface_info
;
53 if (iface_info
== NULL
)
58 info
= g_dbus_node_info_new_for_xml (
60 " <interface name='org.gtk.Notifications'>"
61 " <method name='AddNotification'>"
62 " <arg type='s' direction='in' />"
63 " <arg type='s' direction='in' />"
64 " <arg type='a{sv}' direction='in' />"
66 " <method name='RemoveNotification'>"
67 " <arg type='s' direction='in' />"
68 " <arg type='s' direction='in' />"
74 g_error ("%s", error
->message
);
76 iface_info
= g_dbus_node_info_lookup_interface (info
, "org.gtk.Notifications");
77 g_assert (iface_info
);
79 g_dbus_interface_info_ref (iface_info
);
80 g_dbus_node_info_unref (info
);
87 g_notification_server_notification_added (GNotificationServer
*server
,
89 const gchar
*notification_id
,
90 GVariant
*notification
)
92 GHashTable
*notifications
;
94 notifications
= g_hash_table_lookup (server
->applications
, app_id
);
95 if (notifications
== NULL
)
97 notifications
= g_hash_table_new_full (g_str_hash
, g_str_equal
,
98 g_free
, (GDestroyNotify
) g_variant_unref
);
99 g_hash_table_insert (server
->applications
, g_strdup (app_id
), notifications
);
102 g_hash_table_replace (notifications
, g_strdup (notification_id
), g_variant_ref (notification
));
104 g_signal_emit_by_name (server
, "notification-received", app_id
, notification_id
, notification
);
108 g_notification_server_notification_removed (GNotificationServer
*server
,
110 const gchar
*notification_id
)
112 GHashTable
*notifications
;
114 notifications
= g_hash_table_lookup (server
->applications
, app_id
);
117 g_hash_table_remove (notifications
, notification_id
);
118 if (g_hash_table_size (notifications
) == 0)
119 g_hash_table_remove (server
->applications
, app_id
);
122 g_signal_emit_by_name (server
, "notification-removed", app_id
, notification_id
);
126 org_gtk_Notifications_method_call (GDBusConnection
*connection
,
128 const gchar
*object_path
,
129 const gchar
*interface_name
,
130 const gchar
*method_name
,
131 GVariant
*parameters
,
132 GDBusMethodInvocation
*invocation
,
135 GNotificationServer
*server
= user_data
;
137 if (g_str_equal (method_name
, "AddNotification"))
140 const gchar
*notification_id
;
141 GVariant
*notification
;
143 g_variant_get (parameters
, "(&s&s@a{sv})", &app_id
, ¬ification_id
, ¬ification
);
144 g_notification_server_notification_added (server
, app_id
, notification_id
, notification
);
145 g_dbus_method_invocation_return_value (invocation
, NULL
);
147 g_variant_unref (notification
);
149 else if (g_str_equal (method_name
, "RemoveNotification"))
152 const gchar
*notification_id
;
154 g_variant_get (parameters
, "(&s&s)", &app_id
, ¬ification_id
);
155 g_notification_server_notification_removed (server
, app_id
, notification_id
);
156 g_dbus_method_invocation_return_value (invocation
, NULL
);
160 g_dbus_method_invocation_return_dbus_error (invocation
, "UnknownMethod", "No such method");
165 g_notification_server_dispose (GObject
*object
)
167 GNotificationServer
*server
= G_NOTIFICATION_SERVER (object
);
169 g_notification_server_stop (server
);
171 g_clear_pointer (&server
->applications
, g_hash_table_unref
);
172 g_clear_object (&server
->connection
);
174 G_OBJECT_CLASS (g_notification_server_parent_class
)->dispose (object
);
178 g_notification_server_get_property (GObject
*object
,
183 GNotificationServer
*server
= G_NOTIFICATION_SERVER (object
);
187 case PROP_IS_RUNNING
:
188 g_value_set_boolean (value
, server
->is_running
);
192 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, property_id
, pspec
);
197 g_notification_server_class_init (GNotificationServerClass
*class)
199 GObjectClass
*object_class
= G_OBJECT_CLASS (class);
201 object_class
->get_property
= g_notification_server_get_property
;
202 object_class
->dispose
= g_notification_server_dispose
;
204 g_object_class_install_property (object_class
, PROP_IS_RUNNING
,
205 g_param_spec_boolean ("is-running", "", "", FALSE
,
206 G_PARAM_READABLE
| G_PARAM_STATIC_STRINGS
));
208 g_signal_new ("notification-received", G_TYPE_NOTIFICATION_SERVER
, G_SIGNAL_RUN_FIRST
,
209 0, NULL
, NULL
, g_cclosure_marshal_generic
, G_TYPE_NONE
, 3,
210 G_TYPE_STRING
, G_TYPE_STRING
, G_TYPE_VARIANT
);
212 g_signal_new ("notification-removed", G_TYPE_NOTIFICATION_SERVER
, G_SIGNAL_RUN_FIRST
,
213 0, NULL
, NULL
, g_cclosure_marshal_generic
, G_TYPE_NONE
, 2,
214 G_TYPE_STRING
, G_TYPE_STRING
);
218 g_notification_server_bus_acquired (GDBusConnection
*connection
,
222 const GDBusInterfaceVTable vtable
= {
223 org_gtk_Notifications_method_call
, NULL
, NULL
225 GNotificationServer
*server
= user_data
;
227 server
->object_id
= g_dbus_connection_register_object (connection
, "/org/gtk/Notifications",
228 org_gtk_Notifications_get_interface (),
229 &vtable
, server
, NULL
, NULL
);
231 /* register_object only fails if the same object is exported more than once */
232 g_assert (server
->object_id
> 0);
234 server
->connection
= g_object_ref (connection
);
238 g_notification_server_name_acquired (GDBusConnection
*connection
,
242 GNotificationServer
*server
= user_data
;
244 server
->is_running
= TRUE
;
245 g_object_notify (G_OBJECT (server
), "is-running");
249 g_notification_server_name_lost (GDBusConnection
*connection
,
253 GNotificationServer
*server
= user_data
;
255 g_notification_server_stop (server
);
257 if (connection
== NULL
&& server
->connection
)
258 g_clear_object (&server
->connection
);
262 g_notification_server_init (GNotificationServer
*server
)
264 server
->applications
= g_hash_table_new_full (g_str_hash
, g_str_equal
,
265 g_free
, (GDestroyNotify
) g_hash_table_unref
);
267 server
->name_owner_id
= g_bus_own_name (G_BUS_TYPE_SESSION
,
268 "org.gtk.Notifications",
269 G_BUS_NAME_OWNER_FLAGS_NONE
,
270 g_notification_server_bus_acquired
,
271 g_notification_server_name_acquired
,
272 g_notification_server_name_lost
,
276 GNotificationServer
*
277 g_notification_server_new (void)
279 return g_object_new (G_TYPE_NOTIFICATION_SERVER
, NULL
);
283 g_notification_server_stop (GNotificationServer
*server
)
285 g_return_if_fail (G_IS_NOTIFICATION_SERVER (server
));
287 if (server
->name_owner_id
)
289 g_bus_unown_name (server
->name_owner_id
);
290 server
->name_owner_id
= 0;
293 if (server
->object_id
&& server
->connection
)
295 g_dbus_connection_unregister_object (server
->connection
, server
->object_id
);
296 server
->object_id
= 0;
299 if (server
->is_running
)
301 server
->is_running
= FALSE
;
302 g_object_notify (G_OBJECT (server
), "is-running");
307 g_notification_server_get_is_running (GNotificationServer
*server
)
309 g_return_val_if_fail (G_IS_NOTIFICATION_SERVER (server
), FALSE
);
311 return server
->is_running
;
315 g_notification_server_list_applications (GNotificationServer
*server
)
317 g_return_val_if_fail (G_IS_NOTIFICATION_SERVER (server
), NULL
);
319 return (gchar
**) g_hash_table_get_keys_as_array (server
->applications
, NULL
);
323 g_notification_server_list_notifications (GNotificationServer
*server
,
326 GHashTable
*notifications
;
328 g_return_val_if_fail (G_IS_NOTIFICATION_SERVER (server
), NULL
);
329 g_return_val_if_fail (app_id
!= NULL
, NULL
);
331 notifications
= g_hash_table_lookup (server
->applications
, app_id
);
333 if (notifications
== NULL
)
336 return (gchar
**) g_hash_table_get_keys_as_array (notifications
, NULL
);