4
#include "rec-manager.h"
7
// This module creates a DBus-server for this program.
8
// Other programs can control the recorder by calling methods via this DBus interface.
11
// get_identity(), returns program name + version, eg. "Audio Recorder 1.0".
13
// get_state(), returns current recording state: "not running" | "on" | off" | "paused".
15
// set_state(state), state can be one of: "start"|"stop"|"pause"|"hide"|"show"|"quit".
16
// returns "OK" or NULL if error.
18
// Ref: http://developer.gnome.org/gio/2.28/GDBusServer.html
20
#define R_DBUS_SERVER_ADDRESS "unix:abstract=audiorecorder"
22
#define R_DBUS_OBJECT_PATH "/org/gnome/API/AudioRecorder"
23
#define R_DBUS_INTERFACE_NAME "org.gnome.API.AudioRecorderInterface"
25
static GDBusServer *g_dbus_server = NULL;
26
static GDBusNodeInfo *g_introspection_data = NULL;
28
// Signatures for the methods we are exporting.
29
// DBus clients can get information or control the recorder by calling these functions.
30
static const gchar g_introspection_xml[] =
32
" <interface name='org.gnome.API.AudioRecorderInterface'>"
33
" <method name='get_identity'>"
34
" <arg type='s' name='response' direction='out'/>" // Returns program name + version, eg. "Audio Recorder 1.0"
36
" <method name='get_state'>"
37
" <arg type='s' name='response' direction='out'/>" // Returns current recording state: "not running"|"on"|off"|"paused"
39
" <method name='set_state'>"
40
" <arg type='s' name='state' direction='in'/>" // Set new state. Input argument:"start"|"stop"|"pause"|"hide"|"show"|"quit".
41
" <arg type='s' name='response' direction='out'/>" // Output: "OK" or NULL if error.
46
static gboolean dbus_service_start();
47
static void dbus_service_set_state(gchar *new_state);
49
// -----------------------------------------------------------------------------------
51
void dbus_service_module_init() {
52
LOG_DEBUG("Init dbus_service.c\n");
60
void dbus_service_module_exit() {
61
LOG_DEBUG("Clean up dbus_service.c.\n");
63
if (g_introspection_data) {
64
g_dbus_node_info_unref(g_introspection_data);
66
g_introspection_data = NULL;
69
g_object_unref(g_dbus_server);
74
static void handle_method_call(GDBusConnection *connection,
76
const gchar *object_path,
77
const gchar *interface_name,
78
const gchar *method_name,
80
GDBusMethodInvocation *invocation,
83
// DBus method call: get_identity.
84
// Returns program name + version.
85
if (g_strcmp0(method_name, "get_identity") == 0) {
87
// Eg. "Audio Recorder 2.x"
88
gchar *response = about_program_name();
90
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(s)", response));
92
LOG_DEBUG("Audio recorder (DBus-server) executed method get_identity().\n");
95
// DBus method call: get_state.
96
// Returns "not running" | "on" | "off" | "paused"
97
else if (g_strcmp0(method_name, "get_state") == 0) {
99
// Get recording state
102
rec_manager_get_state(&state, &pending);
104
const gchar *state_str = NULL;
107
case GST_STATE_PAUSED:
108
state_str = "paused";
111
case GST_STATE_PLAYING:
119
g_dbus_method_invocation_return_value(invocation, g_variant_new ("(s)", state_str));
120
LOG_DEBUG("Audio recorder (DBus-server) executed method get_state().\n");
123
// DBus method call: set_state(new_state).
124
// new_state can be: "start" | "stop" | "pause" | "show" | "hide" | "quit".
125
// Returns "OK" | NULL
126
else if (g_strcmp0 (method_name, "set_state") == 0) {
127
gchar *response = g_strdup("OK");
129
gchar *new_state = NULL;
130
g_variant_get(parameters, "(&s)", &new_state);
132
g_dbus_method_invocation_return_value(invocation, g_variant_new ("(s)", response));
134
LOG_DEBUG("Audio recorder (Dbus-server) executed method set_state(%s).\n", new_state);
136
// Set recorder to new_state
137
dbus_service_set_state(new_state);
141
static void dbus_service_set_state(gchar *new_state) {
142
// Set recorder to new_state
144
// $ audio-recorder --command start
145
if (!g_strcmp0(new_state, "start")) {
146
rec_manager_start_recording();
149
// $ audio-recorder --command stop
150
else if (!g_strcmp0(new_state, "stop")) {
151
rec_manager_stop_recording();
154
// $ audio-recorder --command pause
155
else if (!g_strcmp0(new_state, "pause")) {
156
rec_manager_pause_recording();
159
// $ audio-recorder --command show
160
else if (!g_strcmp0(new_state, "show")) {
161
rec_manager_show_window(TRUE);
164
// $ audio-recorder --command hide
165
else if (!g_strcmp0(new_state, "hide")) {
166
rec_manager_show_window(FALSE);
169
// $ audio-recorder --command quit
170
else if (!g_strcmp0(new_state, "quit")) {
171
rec_manager_quit_application();
175
static const GDBusInterfaceVTable interface_vtable = {
181
// ---------------------------------------------------------------------------------
183
static gboolean on_new_connection(GDBusServer *server, GDBusConnection *connection, gpointer user_data) {
185
GCredentials *credentials = NULL;
186
credentials = g_dbus_connection_get_peer_credentials(connection);
189
if (credentials == NULL)
190
s = g_strdup ("(no credentials received)");
192
s = g_credentials_to_string(credentials);
195
LOG_DEBUG("Client connected.\n"
196
"Peer credentials: %s\n"
197
"Negotiated capabilities: unix-fd-passing=%d\n",
199
g_dbus_connection_get_capabilities(connection) & G_DBUS_CAPABILITY_FLAGS_UNIX_FD_PASSING);
202
g_object_ref(connection);
204
gint registration_id = g_dbus_connection_register_object(connection,
206
g_introspection_data->interfaces[0],
208
NULL, /* user_data */
209
NULL, /* user_data_free_func */
212
return (registration_id > 0);
216
static gboolean dbus_service_start() {
217
// Start DBus-server for this application.
218
// This will receive method calls from external programs.
220
// Build introspection data from XML
221
g_introspection_data = g_dbus_node_info_new_for_xml(g_introspection_xml, NULL);
224
GDBusServerFlags server_flags = G_DBUS_SERVER_FLAGS_NONE;
225
server_flags |= G_DBUS_SERVER_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS;
227
gchar *guid = g_dbus_generate_guid();
229
// Create a new D-Bus server that listens on R_DBUS_SERVER_ADDRESS
230
GError *error = NULL;
231
g_dbus_server = g_dbus_server_new_sync(R_DBUS_SERVER_ADDRESS,
234
NULL, /* GDBusAuthObserver */
235
NULL, /* GCancellable */
238
g_dbus_server_start(g_dbus_server);
241
if (g_dbus_server == NULL) {
242
LOG_ERROR("Cannot create server address %s for DBus. %s\n", R_DBUS_SERVER_ADDRESS, error->message);
247
LOG_DEBUG("This Audio Recorder is listening on DBus at: %s\n", g_dbus_server_get_client_address(g_dbus_server));
249
// Set up callback method (for client calls)
250
g_signal_connect(g_dbus_server, "new-connection", G_CALLBACK (on_new_connection), NULL);
252
return (g_dbus_server != NULL);
255
gchar *dbus_service_client_request(gchar *method_name, gchar *arg) {
256
// Execute method call on DBus-server.
257
// Audio-recorder itself can call methods on the server.
258
// DBus-server will most likely return a value. Pass it to the calling function.
260
GError *error = NULL;
262
GDBusConnection *connection = g_dbus_connection_new_for_address_sync(R_DBUS_SERVER_ADDRESS,
263
G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT,
264
NULL, // GDBusAuthObserver
265
NULL, // GCancellable
269
LOG_DEBUG("Cannot connect to DBus address %s. %s\n", R_DBUS_SERVER_ADDRESS, error->message);
275
GVariant *argument = NULL;
277
argument = g_variant_new("(s)", arg);
280
GVariant *value = NULL;
281
value = g_dbus_connection_call_sync(connection,
284
R_DBUS_INTERFACE_NAME,
285
method_name, // method_name
286
argument, // input parm
287
G_VARIANT_TYPE ("(s)"), // return value (one string)
288
G_DBUS_CALL_FLAGS_NONE,
294
LOG_ERROR("Error invoking %s(%s). %s\n", method_name, arg, error->message);
299
gchar *server_response = NULL;
300
g_variant_get(value, "(&s)", &server_response);
302
// Take copy of the value
303
gchar *ret = g_strdup(server_response);
306
g_variant_unref(value);
310
g_object_unref(connection);