~audio-recorder/audio-recorder/trunk

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