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.
10
// Audio-recorder itself can send messages to the running instance of this program.
11
// See audio-recorder --help for more information.
13
// Exported DBus methods are:
14
// get_state(), returns current recording state: "not running" | "on" | off" | "paused".
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.
19
// Ref: http://developer.gnome.org/gio/2.28/GDBusServer.html
21
// Notice: This module has nothing to do with dbus-player.[ch], dbus-mpris2.[ch] modules.
24
#define R_DBUS_SERVER_ADDRESS "unix:abstract=audiorecorder"
26
#define R_DBUS_OBJECT_PATH "/org/gnome/API/AudioRecorder"
27
#define R_DBUS_INTERFACE_NAME "org.gnome.API.AudioRecorderInterface"
29
static GDBusServer *g_dbus_server = NULL;
30
static GDBusNodeInfo *g_introspection_data = NULL;
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[] =
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"
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.
47
static gboolean dbus_service_start();
48
static void dbus_service_set_state(gchar *new_state);
50
// -----------------------------------------------------------------------------------
52
void dbus_service_module_init() {
53
LOG_DEBUG("Init dbus_service.c\n");
61
void dbus_service_module_exit() {
62
LOG_DEBUG("Clean up dbus_service.c.\n");
64
if (g_introspection_data) {
65
g_dbus_node_info_unref(g_introspection_data);
67
g_introspection_data = NULL;
70
g_object_unref(g_dbus_server);
75
static void handle_method_call(GDBusConnection *connection,
77
const gchar *object_path,
78
const gchar *interface_name,
79
const gchar *method_name,
81
GDBusMethodInvocation *invocation,
84
// DBus method call: get_state.
85
// Returns "not running" | "on" | "off" | "paused"
86
if (g_strcmp0(method_name, "get_state") == 0) {
88
// Get recording state
91
rec_manager_get_state(&state, &pending);
93
const gchar *state_str = NULL;
96
case GST_STATE_PAUSED:
100
case GST_STATE_PLAYING:
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");
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");
118
gchar *new_state = NULL;
119
g_variant_get(parameters, "(&s)", &new_state);
121
g_dbus_method_invocation_return_value(invocation, g_variant_new ("(s)", response));
123
LOG_DEBUG("Audio recorder (Dbus-server) executed method set_state(%s).\n", new_state);
125
// Set recorder to new_state
126
dbus_service_set_state(new_state);
130
static void dbus_service_set_state(gchar *new_state) {
131
// Set recorder to new_state
133
// $ audio-recorder --command start
134
if (!g_strcmp0(new_state, "start")) {
135
rec_manager_start_recording();
138
// $ audio-recorder --command stop
139
else if (!g_strcmp0(new_state, "stop")) {
140
rec_manager_stop_recording();
143
// $ audio-recorder --command pause
144
else if (!g_strcmp0(new_state, "pause")) {
145
rec_manager_pause_recording();
148
// $ audio-recorder --command show
149
else if (!g_strcmp0(new_state, "show")) {
150
rec_manager_show_window(TRUE);
153
// $ audio-recorder --command hide
154
else if (!g_strcmp0(new_state, "hide")) {
155
rec_manager_show_window(FALSE);
158
// $ audio-recorder --command quit
159
else if (!g_strcmp0(new_state, "quit")) {
160
rec_manager_quit_application();
164
static const GDBusInterfaceVTable interface_vtable = {
170
// ---------------------------------------------------------------------------------
172
static gboolean on_new_connection(GDBusServer *server, GDBusConnection *connection, gpointer user_data) {
174
GCredentials *credentials = NULL;
175
credentials = g_dbus_connection_get_peer_credentials(connection);
178
if (credentials == NULL)
179
s = g_strdup ("(no credentials received)");
181
s = g_credentials_to_string(credentials);
184
LOG_DEBUG("Client connected.\n"
185
"Peer credentials: %s\n"
186
"Negotiated capabilities: unix-fd-passing=%d\n",
188
g_dbus_connection_get_capabilities(connection) & G_DBUS_CAPABILITY_FLAGS_UNIX_FD_PASSING);
191
g_object_ref(connection);
193
gint registration_id = g_dbus_connection_register_object(connection,
195
g_introspection_data->interfaces[0],
197
NULL, /* user_data */
198
NULL, /* user_data_free_func */
201
return (registration_id > 0);
205
static gboolean dbus_service_start() {
206
// Start DBus-server for this application.
207
// This will receive method calls from external programs.
209
// Build introspection data from XML
210
g_introspection_data = g_dbus_node_info_new_for_xml(g_introspection_xml, NULL);
213
GDBusServerFlags server_flags = G_DBUS_SERVER_FLAGS_NONE;
214
server_flags |= G_DBUS_SERVER_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS;
216
gchar *guid = g_dbus_generate_guid();
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,
223
NULL, /* GDBusAuthObserver */
224
NULL, /* GCancellable */
227
g_dbus_server_start(g_dbus_server);
230
if (g_dbus_server == NULL) {
231
LOG_ERROR("Cannot create server address %s for DBus. %s\n", R_DBUS_SERVER_ADDRESS, error->message);
236
LOG_DEBUG("This Audio Recorder is listening on DBus at: %s\n", g_dbus_server_get_client_address(g_dbus_server));
238
// Set up callback method (for client calls)
239
g_signal_connect(g_dbus_server, "new-connection", G_CALLBACK (on_new_connection), NULL);
241
return (g_dbus_server != NULL);
244
gchar *dbus_service_client_request(gchar *method_name, gchar *arg) {
245
// Execute method call on the server.
246
// Audio-recorder itself can call methods on the server.
247
// DBus-server will most likely return a value. We will pass it to the calling function.
249
GError *error = NULL;
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
258
LOG_DEBUG("Cannot connect to DBus address %s. %s\n", R_DBUS_SERVER_ADDRESS, error->message);
264
GVariant *argument = NULL;
266
argument = g_variant_new("(s)", arg);
269
GVariant *value = NULL;
270
value = g_dbus_connection_call_sync(connection,
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,
283
LOG_ERROR("Error invoking %s(%s). %s\n", method_name, arg, error->message);
288
gchar *server_response = NULL;
289
g_variant_get(value, "(&s)", &server_response);
291
// Take copy of the value
292
gchar *ret = g_strdup(server_response);
295
g_variant_unref(value);
299
g_variant_unref(argument);
303
g_object_unref(connection);