2
* Copyright (C) 2008 Nokia Corporation.
3
* Copyright (C) 2008 Zeeshan Ali (Khattak) <zeeshanak@gnome.org>.
5
* Author: Zeeshan Ali (Khattak) <zeeshanak@gnome.org>
7
* This file is part of Rygel.
9
* Rygel is free software; you can redistribute it and/or modify
10
* it under the terms of the GNU Lesser General Public License as published by
11
* the Free Software Foundation; either version 2 of the License, or
12
* (at your option) any later version.
14
* Rygel is distributed in the hope that it will be useful,
15
* but WITHOUT ANY WARRANTY; without even the implied warranty of
16
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
* GNU Lesser General Public License for more details.
19
* You should have received a copy of the GNU Lesser General Public License
20
* along with this program; if not, write to the Free Software Foundation,
21
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
25
#include <glib-object.h>
28
#include <dbus/dbus-glib-lowlevel.h>
29
#include <dbus/dbus-glib.h>
30
#include <dbus/dbus.h>
33
#define RYGEL_TYPE_DBUS_SERVICE (rygel_dbus_service_get_type ())
34
#define RYGEL_DBUS_SERVICE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), RYGEL_TYPE_DBUS_SERVICE, RygelDBusService))
35
#define RYGEL_DBUS_SERVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), RYGEL_TYPE_DBUS_SERVICE, RygelDBusServiceClass))
36
#define RYGEL_IS_DBUS_SERVICE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), RYGEL_TYPE_DBUS_SERVICE))
37
#define RYGEL_IS_DBUS_SERVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), RYGEL_TYPE_DBUS_SERVICE))
38
#define RYGEL_DBUS_SERVICE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), RYGEL_TYPE_DBUS_SERVICE, RygelDBusServiceClass))
40
typedef struct _RygelDBusService RygelDBusService;
41
typedef struct _RygelDBusServiceClass RygelDBusServiceClass;
42
typedef struct _RygelDBusServicePrivate RygelDBusServicePrivate;
44
#define RYGEL_TYPE_MAIN (rygel_main_get_type ())
45
#define RYGEL_MAIN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), RYGEL_TYPE_MAIN, RygelMain))
46
#define RYGEL_MAIN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), RYGEL_TYPE_MAIN, RygelMainClass))
47
#define RYGEL_IS_MAIN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), RYGEL_TYPE_MAIN))
48
#define RYGEL_IS_MAIN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), RYGEL_TYPE_MAIN))
49
#define RYGEL_MAIN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), RYGEL_TYPE_MAIN, RygelMainClass))
51
typedef struct _RygelMain RygelMain;
52
typedef struct _RygelMainClass RygelMainClass;
53
#define _g_object_unref0(var) ((var == NULL) ? NULL : (var = (g_object_unref (var), NULL)))
54
#define _dbus_g_connection_unref0(var) ((var == NULL) ? NULL : (var = (dbus_g_connection_unref (var), NULL)))
55
typedef struct _DBusObjectVTable _DBusObjectVTable;
57
struct _RygelDBusService {
58
GObject parent_instance;
59
RygelDBusServicePrivate * priv;
62
struct _RygelDBusServiceClass {
63
GObjectClass parent_class;
66
struct _RygelDBusServicePrivate {
70
struct _DBusObjectVTable {
71
void (*register_object) (DBusConnection*, const char*, void*);
75
static char* rygel_dbus_service_RYGEL_SERVICE;
76
static char* rygel_dbus_service_RYGEL_SERVICE = NULL;
77
static char* rygel_dbus_service_RYGEL_PATH;
78
static char* rygel_dbus_service_RYGEL_PATH = NULL;
79
static gpointer rygel_dbus_service_parent_class = NULL;
81
GType rygel_dbus_service_get_type (void);
82
GType rygel_main_get_type (void);
83
#define RYGEL_DBUS_SERVICE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), RYGEL_TYPE_DBUS_SERVICE, RygelDBusServicePrivate))
85
RYGEL_DBUS_SERVICE_DUMMY_PROPERTY
87
guint _dynamic_request_name2 (DBusGProxy* self, const char* param1, guint param2, GError** error);
88
RygelDBusService* rygel_dbus_service_new (RygelMain* main, GError** error);
89
RygelDBusService* rygel_dbus_service_construct (GType object_type, RygelMain* main, GError** error);
90
void rygel_main_exit (RygelMain* self, gint exit_code);
91
void rygel_dbus_service_Shutdown (RygelDBusService* self);
92
void rygel_dbus_service_dbus_register_object (DBusConnection* connection, const char* path, void* object);
93
void _rygel_dbus_service_dbus_unregister (DBusConnection* connection, void* _user_data_);
94
DBusHandlerResult rygel_dbus_service_dbus_message (DBusConnection* connection, DBusMessage* message, void* object);
95
static DBusHandlerResult _dbus_rygel_dbus_service_introspect (RygelDBusService* self, DBusConnection* connection, DBusMessage* message);
96
static DBusHandlerResult _dbus_rygel_dbus_service_property_get_all (RygelDBusService* self, DBusConnection* connection, DBusMessage* message);
97
static DBusHandlerResult _dbus_rygel_dbus_service_Shutdown (RygelDBusService* self, DBusConnection* connection, DBusMessage* message);
98
static void rygel_dbus_service_finalize (GObject* obj);
99
static void _vala_dbus_register_object (DBusConnection* connection, const char* path, void* object);
100
static void _vala_dbus_unregister_object (gpointer connection, GObject* object);
102
static const DBusObjectPathVTable _rygel_dbus_service_dbus_path_vtable = {_rygel_dbus_service_dbus_unregister, rygel_dbus_service_dbus_message};
103
static const _DBusObjectVTable _rygel_dbus_service_dbus_vtable = {rygel_dbus_service_dbus_register_object};
106
static gpointer _g_object_ref0 (gpointer self) {
107
return self ? g_object_ref (self) : NULL;
111
guint _dynamic_request_name2 (DBusGProxy* self, const char* param1, guint param2, GError** error) {
113
dbus_g_proxy_call (self, "RequestName", error, G_TYPE_STRING, param1, G_TYPE_UINT, param2, G_TYPE_INVALID, G_TYPE_UINT, &result, G_TYPE_INVALID);
121
RygelDBusService* rygel_dbus_service_construct (GType object_type, RygelMain* main, GError** error) {
122
GError * _inner_error_;
123
RygelDBusService * self;
125
DBusGConnection* conn;
127
guint request_name_result;
128
g_return_val_if_fail (main != NULL, NULL);
129
_inner_error_ = NULL;
130
self = (RygelDBusService*) g_object_new (object_type, NULL);
131
self->priv->main = (_tmp0_ = _g_object_ref0 (main), _g_object_unref0 (self->priv->main), _tmp0_);
132
conn = dbus_g_bus_get (DBUS_BUS_SESSION, &_inner_error_);
133
if (_inner_error_ != NULL) {
134
g_propagate_error (error, _inner_error_);
137
bus = dbus_g_proxy_new_for_name (conn, "org.freedesktop.DBus", "/org/freedesktop/DBus", "org.freedesktop.DBus");
138
request_name_result = _dynamic_request_name2 (bus, rygel_dbus_service_RYGEL_SERVICE, (guint) 0, &_inner_error_);
139
if (_inner_error_ != NULL) {
140
g_propagate_error (error, _inner_error_);
141
_dbus_g_connection_unref0 (conn);
142
_g_object_unref0 (bus);
145
if (request_name_result != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
146
g_warning ("rygel-dbus-service.vala:45: Failed to start D-Bus service, name '%s' already taken", rygel_dbus_service_RYGEL_SERVICE);
148
_vala_dbus_register_object (dbus_g_connection_get_connection (conn), rygel_dbus_service_RYGEL_PATH, (GObject*) self);
149
_dbus_g_connection_unref0 (conn);
150
_g_object_unref0 (bus);
155
RygelDBusService* rygel_dbus_service_new (RygelMain* main, GError** error) {
156
return rygel_dbus_service_construct (RYGEL_TYPE_DBUS_SERVICE, main, error);
160
void rygel_dbus_service_Shutdown (RygelDBusService* self) {
161
g_return_if_fail (self != NULL);
162
rygel_main_exit (self->priv->main, 0);
166
void _rygel_dbus_service_dbus_unregister (DBusConnection* connection, void* _user_data_) {
170
static DBusHandlerResult _dbus_rygel_dbus_service_introspect (RygelDBusService* self, DBusConnection* connection, DBusMessage* message) {
172
DBusMessageIter iter;
176
reply = dbus_message_new_method_return (message);
177
dbus_message_iter_init_append (reply, &iter);
178
xml_data = g_string_new ("<!DOCTYPE node PUBLIC \"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN\" \"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd\">\n");
179
g_string_append (xml_data, "<node>\n<interface name=\"org.freedesktop.DBus.Introspectable\">\n <method name=\"Introspect\">\n <arg name=\"data\" direction=\"out\" type=\"s\"/>\n </method>\n</interface>\n<interface name=\"org.freedesktop.DBus.Properties\">\n <method name=\"Get\">\n <arg name=\"interface\" direction=\"in\" type=\"s\"/>\n <arg name=\"propname\" direction=\"in\" type=\"s\"/>\n <arg name=\"value\" direction=\"out\" type=\"v\"/>\n </method>\n <method name=\"Set\">\n <arg name=\"interface\" direction=\"in\" type=\"s\"/>\n <arg name=\"propname\" direction=\"in\" type=\"s\"/>\n <arg name=\"value\" direction=\"in\" type=\"v\"/>\n </method>\n <method name=\"GetAll\">\n <arg name=\"interface\" direction=\"in\" type=\"s\"/>\n <arg name=\"props\" direction=\"out\" type=\"a{sv}\"/>\n </method>\n</interface>\n<interface name=\"org.gnome.Rygel1\">\n <method name=\"Shutdown\">\n </method>\n</interface>\n");
180
dbus_connection_list_registered (connection, g_object_get_data ((GObject *) self, "dbus_object_path"), &children);
181
for (i = 0; children[i]; i++) {
182
g_string_append_printf (xml_data, "<node name=\"%s\"/>\n", children[i]);
184
dbus_free_string_array (children);
185
g_string_append (xml_data, "</node>\n");
186
dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &xml_data->str);
187
g_string_free (xml_data, TRUE);
189
dbus_connection_send (connection, reply, NULL);
190
dbus_message_unref (reply);
191
return DBUS_HANDLER_RESULT_HANDLED;
193
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
198
static DBusHandlerResult _dbus_rygel_dbus_service_property_get_all (RygelDBusService* self, DBusConnection* connection, DBusMessage* message) {
200
DBusMessageIter iter, reply_iter, subiter;
201
char* interface_name;
203
if (strcmp (dbus_message_get_signature (message), "s")) {
204
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
206
dbus_message_iter_init (message, &iter);
207
reply = dbus_message_new_method_return (message);
208
dbus_message_iter_init_append (reply, &reply_iter);
209
dbus_message_iter_get_basic (&iter, &_tmp0_);
210
dbus_message_iter_next (&iter);
211
interface_name = g_strdup (_tmp0_);
212
if (strcmp (interface_name, "org.gnome.Rygel1") == 0) {
213
dbus_message_iter_open_container (&reply_iter, DBUS_TYPE_ARRAY, "{sv}", &subiter);
214
dbus_message_iter_close_container (&reply_iter, &subiter);
216
dbus_message_unref (reply);
219
g_free (interface_name);
221
dbus_connection_send (connection, reply, NULL);
222
dbus_message_unref (reply);
223
return DBUS_HANDLER_RESULT_HANDLED;
225
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
230
static DBusHandlerResult _dbus_rygel_dbus_service_Shutdown (RygelDBusService* self, DBusConnection* connection, DBusMessage* message) {
231
DBusMessageIter iter;
235
if (strcmp (dbus_message_get_signature (message), "")) {
236
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
238
dbus_message_iter_init (message, &iter);
239
rygel_dbus_service_Shutdown (self);
240
reply = dbus_message_new_method_return (message);
241
dbus_message_iter_init_append (reply, &iter);
243
dbus_connection_send (connection, reply, NULL);
244
dbus_message_unref (reply);
245
return DBUS_HANDLER_RESULT_HANDLED;
247
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
252
DBusHandlerResult rygel_dbus_service_dbus_message (DBusConnection* connection, DBusMessage* message, void* object) {
253
DBusHandlerResult result;
254
result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
255
if (dbus_message_is_method_call (message, "org.freedesktop.DBus.Introspectable", "Introspect")) {
256
result = _dbus_rygel_dbus_service_introspect (object, connection, message);
257
} else if (dbus_message_is_method_call (message, "org.freedesktop.DBus.Properties", "GetAll")) {
258
result = _dbus_rygel_dbus_service_property_get_all (object, connection, message);
259
} else if (dbus_message_is_method_call (message, "org.gnome.Rygel1", "Shutdown")) {
260
result = _dbus_rygel_dbus_service_Shutdown (object, connection, message);
262
if (result == DBUS_HANDLER_RESULT_HANDLED) {
265
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
270
void rygel_dbus_service_dbus_register_object (DBusConnection* connection, const char* path, void* object) {
271
if (!g_object_get_data (object, "dbus_object_path")) {
272
g_object_set_data (object, "dbus_object_path", g_strdup (path));
273
dbus_connection_register_object_path (connection, path, &_rygel_dbus_service_dbus_path_vtable, object);
274
g_object_weak_ref (object, _vala_dbus_unregister_object, connection);
279
static void rygel_dbus_service_class_init (RygelDBusServiceClass * klass) {
280
rygel_dbus_service_parent_class = g_type_class_peek_parent (klass);
281
g_type_class_add_private (klass, sizeof (RygelDBusServicePrivate));
282
G_OBJECT_CLASS (klass)->finalize = rygel_dbus_service_finalize;
283
g_type_set_qdata (RYGEL_TYPE_DBUS_SERVICE, g_quark_from_static_string ("DBusObjectVTable"), (void*) (&_rygel_dbus_service_dbus_vtable));
284
rygel_dbus_service_RYGEL_SERVICE = g_strdup ("org.gnome.Rygel1");
285
rygel_dbus_service_RYGEL_PATH = g_strdup ("/org/gnome/Rygel1");
289
static void rygel_dbus_service_instance_init (RygelDBusService * self) {
290
self->priv = RYGEL_DBUS_SERVICE_GET_PRIVATE (self);
294
static void rygel_dbus_service_finalize (GObject* obj) {
295
RygelDBusService * self;
296
self = RYGEL_DBUS_SERVICE (obj);
297
_g_object_unref0 (self->priv->main);
298
G_OBJECT_CLASS (rygel_dbus_service_parent_class)->finalize (obj);
302
GType rygel_dbus_service_get_type (void) {
303
static GType rygel_dbus_service_type_id = 0;
304
if (rygel_dbus_service_type_id == 0) {
305
static const GTypeInfo g_define_type_info = { sizeof (RygelDBusServiceClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) rygel_dbus_service_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (RygelDBusService), 0, (GInstanceInitFunc) rygel_dbus_service_instance_init, NULL };
306
rygel_dbus_service_type_id = g_type_register_static (G_TYPE_OBJECT, "RygelDBusService", &g_define_type_info, 0);
308
return rygel_dbus_service_type_id;
312
static void _vala_dbus_register_object (DBusConnection* connection, const char* path, void* object) {
313
const _DBusObjectVTable * vtable;
314
vtable = g_type_get_qdata (G_TYPE_FROM_INSTANCE (object), g_quark_from_static_string ("DBusObjectVTable"));
316
vtable->register_object (connection, path, object);
318
g_warning ("Object does not implement any D-Bus interface");
323
static void _vala_dbus_unregister_object (gpointer connection, GObject* object) {
325
path = g_object_steal_data ((GObject*) object, "dbus_object_path");
326
dbus_connection_unregister_object_path (connection, path);