~audio-recorder/audio-recorder/trunk

« back to all changes in this revision

Viewing changes to src/dbus-service.c

  • Committer: Osmo Antero
  • Date: 2012-04-18 19:22:01 UTC
  • Revision ID: osmoma@gmail.com-20120418192201-ejjs6ikv7o4aznbi
New media-player interface that's based on the MediaPlayer2 standard. See src/dbus-mpris2.c.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
#include "log.h"
2
 
#include "support.h"
3
 
#include "about.h"
4
 
#include "rec-manager.h"
5
 
#include <gst/gst.h>
6
 
 
7
 
// This module creates a DBus-server for this program.
8
 
// Other programs can control the recorder by calling methods via this DBus interface.
9
 
//
10
 
// Audio-recorder itself can send messages to the running instance of this program.
11
 
// See audio-recorder --help for more information.
12
 
//
13
 
//  Exported DBus methods are:
14
 
//  get_state(), returns current recording state: "not running" | "on" | off" | "paused".
15
 
//
16
 
//  set_state(state), set new state. The state can be one of: "start"|"stop"|"pause"|"hide"|"show"|"quit".
17
 
//                    returns "OK" if success. NULL if error.
18
 
//
19
 
// Ref: http://developer.gnome.org/gio/2.28/GDBusServer.html
20
 
//
21
 
// Notice: This module has nothing to do with dbus-player.[ch], dbus-mpris.[ch] and other dbus-<add your media player her>.[ch] modules.
22
 
//
23
 
 
24
 
#define R_DBUS_SERVER_ADDRESS "unix:abstract=audiorecorder"
25
 
 
26
 
#define R_DBUS_OBJECT_PATH "/org/gnome/API/AudioRecorder"
27
 
#define R_DBUS_INTERFACE_NAME "org.gnome.API.AudioRecorderInterface"
28
 
 
29
 
static GDBusServer *g_dbus_server = NULL;
30
 
static GDBusNodeInfo *g_introspection_data = NULL;
31
 
 
32
 
// Signatures for the methods we are exporting.
33
 
// DBus clients can get information or control the recorder by calling these functions.
34
 
static const gchar g_introspection_xml[] =
35
 
    "<node>"
36
 
    "  <interface name='org.gnome.API.AudioRecorderInterface'>"
37
 
    "    <method name='get_state'>"
38
 
    "      <arg type='s' name='response' direction='out'/>"  // Returns current recording state: "not running"|"on"|off"|"paused"
39
 
    "    </method>"
40
 
    "    <method name='set_state'>"
41
 
    "      <arg type='s' name='state' direction='in'/>"      // Set new state. Input argument:"start"|"stop"|"pause"|"hide"|"show"|"quit".
42
 
    "      <arg type='s' name='response' direction='out'/>"  // Returns "OK" or NULL if error.
43
 
    "    </method>"
44
 
    "  </interface>"
45
 
    "</node>";
46
 
 
47
 
static gboolean dbus_service_start();
48
 
static void dbus_service_set_state(gchar *new_state);
49
 
 
50
 
// -----------------------------------------------------------------------------------
51
 
 
52
 
void dbus_service_module_init() {
53
 
    LOG_DEBUG("Init dbus_service.c\n");
54
 
 
55
 
    g_dbus_server = NULL;
56
 
 
57
 
    // Start service
58
 
    dbus_service_start();
59
 
}
60
 
 
61
 
void dbus_service_module_exit() {
62
 
    LOG_DEBUG("Clean up dbus_service.c.\n");
63
 
 
64
 
    if (g_introspection_data) {
65
 
        g_dbus_node_info_unref(g_introspection_data);
66
 
    }
67
 
    g_introspection_data = NULL;
68
 
 
69
 
    if (g_dbus_server) {
70
 
        g_object_unref(g_dbus_server);
71
 
    }
72
 
    g_dbus_server = NULL;
73
 
}
74
 
 
75
 
static void handle_method_call(GDBusConnection *connection,
76
 
                               const gchar           *sender,
77
 
                               const gchar           *object_path,
78
 
                               const gchar           *interface_name,
79
 
                               const gchar           *method_name,
80
 
                               GVariant              *parameters,
81
 
                               GDBusMethodInvocation *invocation,
82
 
                               gpointer               user_data) {
83
 
 
84
 
    // DBus method call: get_state.
85
 
    // Returns "not running" | "on" | "off" | "paused"
86
 
    if (g_strcmp0(method_name, "get_state") == 0) {
87
 
 
88
 
        // Get recording state
89
 
        gint state = -1;
90
 
        gint pending = -1;
91
 
        rec_manager_get_state(&state, &pending);
92
 
 
93
 
        const gchar *state_str = NULL;
94
 
 
95
 
        switch (state) {
96
 
        case GST_STATE_PAUSED:
97
 
            state_str = "paused";
98
 
            break;
99
 
 
100
 
        case GST_STATE_PLAYING:
101
 
            state_str = "on";
102
 
            break;
103
 
 
104
 
        default:
105
 
            state_str = "off";
106
 
        }
107
 
 
108
 
        g_dbus_method_invocation_return_value(invocation, g_variant_new ("(s)", state_str));
109
 
        LOG_DEBUG("Audio recorder (DBus-server) executed method get_state().\n");
110
 
    }
111
 
 
112
 
    // DBus method call: set_state(new_state).
113
 
    // new_state can be: "start" | "stop" | "pause" | "show"  | "hide" | "quit".
114
 
    // Returns "OK" | NULL
115
 
    else if (g_strcmp0 (method_name, "set_state") == 0) {
116
 
        gchar *response = g_strdup("OK");
117
 
 
118
 
        gchar *new_state = NULL;
119
 
        g_variant_get(parameters, "(&s)", &new_state);
120
 
 
121
 
        g_dbus_method_invocation_return_value(invocation, g_variant_new ("(s)", response));
122
 
        g_free(response);
123
 
        LOG_DEBUG("Audio recorder (Dbus-server) executed method set_state(%s).\n", new_state);
124
 
 
125
 
        // Set recorder to new_state
126
 
        dbus_service_set_state(new_state);
127
 
    }
128
 
}
129
 
 
130
 
static void dbus_service_set_state(gchar *new_state) {
131
 
    // Set recorder to new_state
132
 
 
133
 
    // $ audio-recorder --command start
134
 
    if (!g_strcmp0(new_state, "start")) {
135
 
        rec_manager_start_recording();
136
 
    }
137
 
 
138
 
    // $ audio-recorder --command stop
139
 
    else if (!g_strcmp0(new_state, "stop")) {
140
 
        rec_manager_stop_recording();
141
 
    }
142
 
 
143
 
    // $ audio-recorder --command pause
144
 
    else if (!g_strcmp0(new_state, "pause")) {
145
 
        rec_manager_pause_recording();
146
 
    }
147
 
 
148
 
    // $ audio-recorder --command show
149
 
    else if (!g_strcmp0(new_state, "show")) {
150
 
        rec_manager_show_window(TRUE);
151
 
    }
152
 
 
153
 
    // $ audio-recorder --command hide
154
 
    else if (!g_strcmp0(new_state, "hide")) {
155
 
        rec_manager_show_window(FALSE);
156
 
    }
157
 
 
158
 
    // $ audio-recorder --command quit
159
 
    else if (!g_strcmp0(new_state, "quit")) {
160
 
        rec_manager_quit_application();
161
 
    }
162
 
}
163
 
 
164
 
static const GDBusInterfaceVTable interface_vtable = {
165
 
    handle_method_call,
166
 
    NULL,
167
 
    NULL,
168
 
};
169
 
 
170
 
// ---------------------------------------------------------------------------------
171
 
 
172
 
static gboolean on_new_connection(GDBusServer *server, GDBusConnection *connection, gpointer user_data) {
173
 
    /*
174
 
    GCredentials *credentials = NULL;
175
 
    credentials = g_dbus_connection_get_peer_credentials(connection);
176
 
 
177
 
    gchar *s = NULL;
178
 
    if (credentials == NULL)
179
 
        s = g_strdup ("(no credentials received)");
180
 
    else
181
 
        s = g_credentials_to_string(credentials);
182
 
 
183
 
 
184
 
    LOG_DEBUG("Client connected.\n"
185
 
           "Peer credentials: %s\n"
186
 
           "Negotiated capabilities: unix-fd-passing=%d\n",
187
 
           s,
188
 
           g_dbus_connection_get_capabilities(connection) & G_DBUS_CAPABILITY_FLAGS_UNIX_FD_PASSING);
189
 
    */
190
 
 
191
 
    g_object_ref(connection);
192
 
 
193
 
    gint registration_id = g_dbus_connection_register_object(connection,
194
 
                           R_DBUS_OBJECT_PATH,
195
 
                           g_introspection_data->interfaces[0],
196
 
                           &interface_vtable,
197
 
                           NULL,  /* user_data */
198
 
                           NULL,  /* user_data_free_func */
199
 
                           NULL); /* GError */
200
 
 
201
 
    return (registration_id > 0);
202
 
}
203
 
 
204
 
 
205
 
static gboolean dbus_service_start() {
206
 
    // Start DBus-server for this application.
207
 
    // This will receive method calls from external programs.
208
 
 
209
 
    // Build introspection data from XML
210
 
    g_introspection_data = g_dbus_node_info_new_for_xml(g_introspection_xml, NULL);
211
 
 
212
 
    // Server flags
213
 
    GDBusServerFlags server_flags = G_DBUS_SERVER_FLAGS_NONE;
214
 
    server_flags |= G_DBUS_SERVER_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS;
215
 
 
216
 
    gchar *guid = g_dbus_generate_guid();
217
 
 
218
 
    // Create a new D-Bus server that listens on R_DBUS_SERVER_ADDRESS
219
 
    GError *error = NULL;
220
 
    g_dbus_server = g_dbus_server_new_sync(R_DBUS_SERVER_ADDRESS,
221
 
                                           server_flags,
222
 
                                           guid,
223
 
                                           NULL, /* GDBusAuthObserver */
224
 
                                           NULL, /* GCancellable */
225
 
                                           &error);
226
 
 
227
 
    g_dbus_server_start(g_dbus_server);
228
 
    g_free(guid);
229
 
 
230
 
    if (g_dbus_server == NULL) {
231
 
        LOG_ERROR("Cannot create server address %s for DBus. %s\n", R_DBUS_SERVER_ADDRESS, error->message);
232
 
        g_error_free(error);
233
 
        return FALSE;
234
 
    }
235
 
 
236
 
    LOG_DEBUG("This Audio Recorder is listening on DBus at: %s\n", g_dbus_server_get_client_address(g_dbus_server));
237
 
 
238
 
    // Set up callback method (for client calls)
239
 
    g_signal_connect(g_dbus_server, "new-connection", G_CALLBACK (on_new_connection), NULL);
240
 
 
241
 
    return (g_dbus_server != NULL);
242
 
}
243
 
 
244
 
gchar *dbus_service_client_request(gchar *method_name, gchar *arg) {
245
 
    // Execute method call on DBus-server.
246
 
    // Audio-recorder itself can call methods on the server.
247
 
    // DBus-server will most likely return a value. Pass it to the calling function.
248
 
 
249
 
    GError *error = NULL;
250
 
 
251
 
    GDBusConnection *connection = g_dbus_connection_new_for_address_sync(R_DBUS_SERVER_ADDRESS,
252
 
                                  G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT,
253
 
                                  NULL, // GDBusAuthObserver
254
 
                                  NULL, // GCancellable
255
 
                                  &error);
256
 
 
257
 
    if (!connection) {
258
 
        LOG_DEBUG("Cannot connect to DBus address %s. %s\n", R_DBUS_SERVER_ADDRESS, error->message);
259
 
        g_error_free(error);
260
 
        return NULL;
261
 
    }
262
 
 
263
 
    // Optional argument
264
 
    GVariant *argument = NULL;
265
 
    if (arg) {
266
 
        argument = g_variant_new("(s)", arg);
267
 
    }
268
 
 
269
 
    GVariant *value = NULL;
270
 
    value = g_dbus_connection_call_sync(connection,
271
 
                                        NULL, // bus_name
272
 
                                        R_DBUS_OBJECT_PATH,
273
 
                                        R_DBUS_INTERFACE_NAME,
274
 
                                        method_name, // method_name
275
 
                                        argument, // input parm
276
 
                                        G_VARIANT_TYPE ("(s)"), // return value (one string)
277
 
                                        G_DBUS_CALL_FLAGS_NONE,
278
 
                                        -1,
279
 
                                        NULL,
280
 
                                        &error);
281
 
 
282
 
    if (!value) {
283
 
        LOG_ERROR("Error invoking %s(%s). %s\n", method_name, arg, error->message);
284
 
        g_error_free(error);
285
 
        return NULL;
286
 
    }
287
 
 
288
 
    gchar *server_response = NULL;
289
 
    g_variant_get(value, "(&s)", &server_response);
290
 
 
291
 
    // Take copy of the value
292
 
    gchar *ret = g_strdup(server_response);
293
 
 
294
 
    if (value) {
295
 
        g_variant_unref(value);
296
 
    }
297
 
 
298
 
    if (connection) {
299
 
        g_object_unref(connection);
300
 
    }
301
 
 
302
 
    // Return ret
303
 
    return ret;
304
 
}
305
 
 
306