]> code.delx.au - pulseaudio/blob - src/modules/module-stream-restore.c
Merge branch 'master' of git://0pointer.de/pulseaudio into dbus-work
[pulseaudio] / src / modules / module-stream-restore.c
1 /***
2 This file is part of PulseAudio.
3
4 Copyright 2008 Lennart Poettering
5 Copyright 2009 Tanu Kaskinen
6
7 PulseAudio is free software; you can redistribute it and/or modify
8 it under the terms of the GNU Lesser General Public License as published
9 by the Free Software Foundation; either version 2.1 of the License,
10 or (at your option) any later version.
11
12 PulseAudio is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public License
18 along with PulseAudio; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
20 USA.
21 ***/
22
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26
27 #include <unistd.h>
28 #include <string.h>
29 #include <errno.h>
30 #include <sys/types.h>
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <ctype.h>
34
35 #include <pulse/xmalloc.h>
36 #include <pulse/volume.h>
37 #include <pulse/timeval.h>
38 #include <pulse/util.h>
39 #include <pulse/rtclock.h>
40
41 #include <pulsecore/core-error.h>
42 #include <pulsecore/module.h>
43 #include <pulsecore/core-util.h>
44 #include <pulsecore/modargs.h>
45 #include <pulsecore/log.h>
46 #include <pulsecore/core-subscribe.h>
47 #include <pulsecore/sink-input.h>
48 #include <pulsecore/source-output.h>
49 #include <pulsecore/namereg.h>
50 #include <pulsecore/protocol-native.h>
51 #include <pulsecore/pstream.h>
52 #include <pulsecore/pstream-util.h>
53 #include <pulsecore/database.h>
54
55 #ifdef HAVE_DBUS
56 #include <pulsecore/dbus-util.h>
57 #include <pulsecore/protocol-dbus.h>
58 #endif
59
60 #include "module-stream-restore-symdef.h"
61
62 PA_MODULE_AUTHOR("Lennart Poettering");
63 PA_MODULE_DESCRIPTION("Automatically restore the volume/mute/device state of streams");
64 PA_MODULE_VERSION(PACKAGE_VERSION);
65 PA_MODULE_LOAD_ONCE(TRUE);
66 PA_MODULE_USAGE(
67 "restore_device=<Save/restore sinks/sources?> "
68 "restore_volume=<Save/restore volumes?> "
69 "restore_muted=<Save/restore muted states?> "
70 "on_hotplug=<When new device becomes available, recheck streams?> "
71 "on_rescue=<When device becomes unavailable, recheck streams?>");
72
73 #define SAVE_INTERVAL (10 * PA_USEC_PER_SEC)
74 #define IDENTIFICATION_PROPERTY "module-stream-restore.id"
75
76 static const char* const valid_modargs[] = {
77 "restore_device",
78 "restore_volume",
79 "restore_muted",
80 "on_hotplug",
81 "on_rescue",
82 NULL
83 };
84
85 struct userdata {
86 pa_core *core;
87 pa_module *module;
88 pa_subscription *subscription;
89 pa_hook_slot
90 *sink_input_new_hook_slot,
91 *sink_input_fixate_hook_slot,
92 *source_output_new_hook_slot,
93 *sink_put_hook_slot,
94 *source_put_hook_slot,
95 *sink_unlink_hook_slot,
96 *source_unlink_hook_slot,
97 *connection_unlink_hook_slot;
98 pa_time_event *save_time_event;
99 pa_database* database;
100
101 pa_bool_t restore_device:1;
102 pa_bool_t restore_volume:1;
103 pa_bool_t restore_muted:1;
104 pa_bool_t on_hotplug:1;
105 pa_bool_t on_rescue:1;
106
107 pa_native_protocol *protocol;
108 pa_idxset *subscribed;
109
110 #ifdef HAVE_DBUS
111 pa_dbus_protocol *dbus_protocol;
112 pa_hashmap *dbus_entries;
113 uint32_t next_index; /* For generating object paths for entries. */
114 #endif
115 };
116
117 #define ENTRY_VERSION 3
118
119 struct entry {
120 uint8_t version;
121 pa_bool_t muted_valid:1, volume_valid:1, device_valid:1, card_valid:1;
122 pa_bool_t muted:1;
123 pa_channel_map channel_map;
124 pa_cvolume volume;
125 char device[PA_NAME_MAX];
126 char card[PA_NAME_MAX];
127 } PA_GCC_PACKED;
128
129 enum {
130 SUBCOMMAND_TEST,
131 SUBCOMMAND_READ,
132 SUBCOMMAND_WRITE,
133 SUBCOMMAND_DELETE,
134 SUBCOMMAND_SUBSCRIBE,
135 SUBCOMMAND_EVENT
136 };
137
138 static struct entry *read_entry(struct userdata *u, const char *name);
139 static void apply_entry(struct userdata *u, const char *name, struct entry *e);
140 static void trigger_save(struct userdata *u);
141
142 #ifdef HAVE_DBUS
143
144 #define OBJECT_PATH "/org/pulseaudio/stream_restore1"
145 #define ENTRY_OBJECT_NAME "entry"
146 #define INTERFACE_STREAM_RESTORE "org.PulseAudio.Ext.StreamRestore1"
147 #define INTERFACE_ENTRY INTERFACE_STREAM_RESTORE ".RestoreEntry"
148
149 #define DBUS_INTERFACE_REVISION 0
150
151 struct dbus_entry {
152 struct userdata *userdata;
153
154 char *entry_name;
155 uint32_t index;
156 char *object_path;
157 };
158
159 static void handle_get_interface_revision(DBusConnection *conn, DBusMessage *msg, void *userdata);
160 static void handle_get_entries(DBusConnection *conn, DBusMessage *msg, void *userdata);
161
162 static void handle_get_all(DBusConnection *conn, DBusMessage *msg, void *userdata);
163
164 static void handle_add_entry(DBusConnection *conn, DBusMessage *msg, void *userdata);
165 static void handle_get_entry_by_name(DBusConnection *conn, DBusMessage *msg, void *userdata);
166
167 static void handle_entry_get_index(DBusConnection *conn, DBusMessage *msg, void *userdata);
168 static void handle_entry_get_name(DBusConnection *conn, DBusMessage *msg, void *userdata);
169 static void handle_entry_get_device(DBusConnection *conn, DBusMessage *msg, void *userdata);
170 static void handle_entry_set_device(DBusConnection *conn, DBusMessage *msg, void *userdata);
171 static void handle_entry_get_volume(DBusConnection *conn, DBusMessage *msg, void *userdata);
172 static void handle_entry_set_volume(DBusConnection *conn, DBusMessage *msg, void *userdata);
173 static void handle_entry_get_is_muted(DBusConnection *conn, DBusMessage *msg, void *userdata);
174 static void handle_entry_set_is_muted(DBusConnection *conn, DBusMessage *msg, void *userdata);
175
176 static void handle_entry_get_all(DBusConnection *conn, DBusMessage *msg, void *userdata);
177
178 static void handle_entry_remove(DBusConnection *conn, DBusMessage *msg, void *userdata);
179
180 enum property_handler_index {
181 PROPERTY_HANDLER_INTERFACE_REVISION,
182 PROPERTY_HANDLER_ENTRIES,
183 PROPERTY_HANDLER_MAX
184 };
185
186 enum entry_property_handler_index {
187 ENTRY_PROPERTY_HANDLER_INDEX,
188 ENTRY_PROPERTY_HANDLER_NAME,
189 ENTRY_PROPERTY_HANDLER_DEVICE,
190 ENTRY_PROPERTY_HANDLER_VOLUME,
191 ENTRY_PROPERTY_HANDLER_IS_MUTED,
192 ENTRY_PROPERTY_HANDLER_MAX
193 };
194
195 static pa_dbus_property_handler property_handlers[PROPERTY_HANDLER_MAX] = {
196 [PROPERTY_HANDLER_INTERFACE_REVISION] = { .property_name = "InterfaceRevision", .type = "u", .get_cb = handle_get_interface_revision, .set_cb = NULL },
197 [PROPERTY_HANDLER_ENTRIES] = { .property_name = "Entries", .type = "ao", .get_cb = handle_get_entries, .set_cb = NULL }
198 };
199
200 static pa_dbus_property_handler entry_property_handlers[ENTRY_PROPERTY_HANDLER_MAX] = {
201 [ENTRY_PROPERTY_HANDLER_INDEX] = { .property_name = "Index", .type = "u", .get_cb = handle_entry_get_index, .set_cb = NULL },
202 [ENTRY_PROPERTY_HANDLER_NAME] = { .property_name = "Name", .type = "s", .get_cb = handle_entry_get_name, .set_cb = NULL },
203 [ENTRY_PROPERTY_HANDLER_DEVICE] = { .property_name = "Device", .type = "s", .get_cb = handle_entry_get_device, .set_cb = handle_entry_set_device },
204 [ENTRY_PROPERTY_HANDLER_VOLUME] = { .property_name = "Volume", .type = "a(uu)", .get_cb = handle_entry_get_volume, .set_cb = handle_entry_set_volume },
205 [ENTRY_PROPERTY_HANDLER_IS_MUTED] = { .property_name = "IsMuted", .type = "b", .get_cb = handle_entry_get_is_muted, .set_cb = handle_entry_set_is_muted }
206 };
207
208 enum method_handler_index {
209 METHOD_HANDLER_ADD_ENTRY,
210 METHOD_HANDLER_GET_ENTRY_BY_NAME,
211 METHOD_HANDLER_MAX
212 };
213
214 enum entry_method_handler_index {
215 ENTRY_METHOD_HANDLER_REMOVE,
216 ENTRY_METHOD_HANDLER_MAX
217 };
218
219 static pa_dbus_arg_info add_entry_args[] = { { "name", "s", "in" },
220 { "device", "s", "in" },
221 { "volume", "a(uu)", "in" },
222 { "is_muted", "b", "in" },
223 { "entry", "o", "out" } };
224 static pa_dbus_arg_info get_entry_by_name_args[] = { { "name", "s", "in" }, { "entry", "o", "out" } };
225
226 static pa_dbus_method_handler method_handlers[METHOD_HANDLER_MAX] = {
227 [METHOD_HANDLER_ADD_ENTRY] = {
228 .method_name = "AddEntry",
229 .arguments = add_entry_args,
230 .n_arguments = sizeof(add_entry_args) / sizeof(pa_dbus_arg_info),
231 .receive_cb = handle_add_entry },
232 [METHOD_HANDLER_GET_ENTRY_BY_NAME] = {
233 .method_name = "GetEntryByName",
234 .arguments = get_entry_by_name_args,
235 .n_arguments = sizeof(get_entry_by_name_args) / sizeof(pa_dbus_arg_info),
236 .receive_cb = handle_get_entry_by_name }
237 };
238
239 static pa_dbus_method_handler entry_method_handlers[ENTRY_METHOD_HANDLER_MAX] = {
240 [ENTRY_METHOD_HANDLER_REMOVE] = {
241 .method_name = "Remove",
242 .arguments = NULL,
243 .n_arguments = 0,
244 .receive_cb = handle_entry_remove }
245 };
246
247 enum signal_index {
248 SIGNAL_NEW_ENTRY,
249 SIGNAL_ENTRY_REMOVED,
250 SIGNAL_MAX
251 };
252
253 enum entry_signal_index {
254 ENTRY_SIGNAL_DEVICE_UPDATED,
255 ENTRY_SIGNAL_VOLUME_UPDATED,
256 ENTRY_SIGNAL_MUTE_UPDATED,
257 ENTRY_SIGNAL_MAX
258 };
259
260 static pa_dbus_arg_info new_entry_args[] = { { "entry", "o", NULL } };
261 static pa_dbus_arg_info entry_removed_args[] = { { "entry", "o", NULL } };
262
263 static pa_dbus_arg_info entry_device_updated_args[] = { { "device", "s", NULL } };
264 static pa_dbus_arg_info entry_volume_updated_args[] = { { "volume", "a(uu)", NULL } };
265 static pa_dbus_arg_info entry_mute_updated_args[] = { { "muted", "b", NULL } };
266
267 static pa_dbus_signal_info signals[SIGNAL_MAX] = {
268 [SIGNAL_NEW_ENTRY] = { .name = "NewEntry", .arguments = new_entry_args, .n_arguments = 1 },
269 [SIGNAL_ENTRY_REMOVED] = { .name = "EntryRemoved", .arguments = entry_removed_args, .n_arguments = 1 }
270 };
271
272 static pa_dbus_signal_info entry_signals[ENTRY_SIGNAL_MAX] = {
273 [ENTRY_SIGNAL_DEVICE_UPDATED] = { .name = "DeviceUpdated", .arguments = entry_device_updated_args, .n_arguments = 1 },
274 [ENTRY_SIGNAL_VOLUME_UPDATED] = { .name = "VolumeUpdated", .arguments = entry_volume_updated_args, .n_arguments = 1 },
275 [ENTRY_SIGNAL_MUTE_UPDATED] = { .name = "MuteUpdated", .arguments = entry_mute_updated_args, .n_arguments = 1 }
276 };
277
278 static pa_dbus_interface_info stream_restore_interface_info = {
279 .name = INTERFACE_STREAM_RESTORE,
280 .method_handlers = method_handlers,
281 .n_method_handlers = METHOD_HANDLER_MAX,
282 .property_handlers = property_handlers,
283 .n_property_handlers = PROPERTY_HANDLER_MAX,
284 .get_all_properties_cb = handle_get_all,
285 .signals = signals,
286 .n_signals = SIGNAL_MAX
287 };
288
289 static pa_dbus_interface_info entry_interface_info = {
290 .name = INTERFACE_ENTRY,
291 .method_handlers = entry_method_handlers,
292 .n_method_handlers = ENTRY_METHOD_HANDLER_MAX,
293 .property_handlers = entry_property_handlers,
294 .n_property_handlers = ENTRY_PROPERTY_HANDLER_MAX,
295 .get_all_properties_cb = handle_entry_get_all,
296 .signals = entry_signals,
297 .n_signals = ENTRY_SIGNAL_MAX
298 };
299
300 static struct dbus_entry *dbus_entry_new(struct userdata *u, const char *entry_name) {
301 struct dbus_entry *de;
302
303 pa_assert(u);
304 pa_assert(entry_name);
305 pa_assert(*entry_name);
306
307 de = pa_xnew(struct dbus_entry, 1);
308 de->userdata = u;
309 de->entry_name = pa_xstrdup(entry_name);
310 de->index = u->next_index++;
311 de->object_path = pa_sprintf_malloc("%s/%s%u", OBJECT_PATH, ENTRY_OBJECT_NAME, de->index);
312
313 pa_assert_se(pa_dbus_protocol_add_interface(u->dbus_protocol, de->object_path, &entry_interface_info, u) >= 0);
314
315 return de;
316 }
317
318 static void dbus_entry_free(struct dbus_entry *de) {
319 pa_assert(de);
320
321 pa_assert_se(pa_dbus_protocol_remove_interface(de->userdata->dbus_protocol, de->object_path, entry_interface_info.name) >= 0);
322
323 pa_xfree(de->entry_name);
324 pa_xfree(de->object_path);
325 }
326
327 /* Reads an array [(UInt32, UInt32)] from the iterator. The struct items are
328 * are a channel position and a volume value, respectively. The result is
329 * stored in the map and vol arguments. If the volume can't be read from the
330 * iterator, an error reply is sent and a negative number is returned. In case
331 * of a failure we make no guarantees about the state of map and vol. In case
332 * of an empty array the channels field of both map and vol are set to 0. */
333 static int get_volume_arg(DBusConnection *conn, DBusMessage *msg, DBusMessageIter *iter, pa_channel_map *map, pa_cvolume *vol) {
334 DBusMessageIter array_iter;
335 DBusMessageIter struct_iter;
336 int arg_type;
337
338 pa_assert(conn);
339 pa_assert(msg);
340 pa_assert(iter);
341 pa_assert(map);
342 pa_assert(vol);
343
344 pa_channel_map_init(map);
345 pa_cvolume_init(vol);
346
347 map->channels = 0;
348 vol->channels = 0;
349
350 arg_type = dbus_message_iter_get_arg_type(iter);
351 if (arg_type != DBUS_TYPE_ARRAY) {
352 if (arg_type == DBUS_TYPE_INVALID)
353 pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "Too few arguments. An array was expected.");
354 else
355 pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "Wrong argument type: '%c'. An array was expected.", (char) arg_type);
356 return -1;
357 }
358
359 arg_type = dbus_message_iter_get_element_type(iter);
360 if (arg_type != DBUS_TYPE_STRUCT) {
361 pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "Wrong array element type: '%c'. A struct was expected.", (char) arg_type);
362 return -1;
363 }
364
365 dbus_message_iter_recurse(iter, &array_iter);
366
367 while (dbus_message_iter_get_arg_type(&array_iter) != DBUS_TYPE_INVALID) {
368 dbus_uint32_t chan_pos;
369 dbus_uint32_t chan_vol;
370
371 dbus_message_iter_recurse(&array_iter, &struct_iter);
372
373 arg_type = dbus_message_iter_get_arg_type(&struct_iter);
374 if (arg_type != DBUS_TYPE_UINT32) {
375 pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "Wrong channel position type: '%c'. An unsigned 32-bit integer was expected.", (char) arg_type);
376 return -1;
377 }
378
379 dbus_message_iter_get_basic(&struct_iter, &chan_pos);
380 dbus_message_iter_next(&struct_iter);
381
382 if (chan_pos >= PA_CHANNEL_POSITION_MAX) {
383 pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "Invalid channel position: %u", chan_pos);
384 return -1;
385 }
386
387 arg_type = dbus_message_iter_get_arg_type(&struct_iter);
388 if (arg_type != DBUS_TYPE_UINT32) {
389 if (arg_type == DBUS_TYPE_INVALID)
390 pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "Channel volume missing.");
391 else
392 pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "Wrong volume value type: '%c'. An unsigned 32-bit integer was expected.", (char) arg_type);
393 return -1;
394 }
395
396 dbus_message_iter_get_basic(&struct_iter, &chan_vol);
397
398 if (chan_vol > PA_VOLUME_MAX) {
399 pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "Invalid volume: %u", chan_vol);
400 return -1;
401 }
402
403 if (map->channels < PA_CHANNELS_MAX) {
404 map->map[map->channels] = chan_pos;
405 vol->values[map->channels] = chan_vol;
406 }
407 ++map->channels;
408 ++vol->channels;
409
410 dbus_message_iter_next(&array_iter);
411 }
412
413 if (map->channels > PA_CHANNELS_MAX) {
414 pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "Too many channels: %u. The maximum is %u.", map->channels, PA_CHANNELS_MAX);
415 return -1;
416 }
417
418 dbus_message_iter_next(iter);
419
420 return 0;
421 }
422
423 static void append_volume(DBusMessageIter *iter, struct entry *e) {
424 DBusMessageIter array_iter;
425 DBusMessageIter struct_iter;
426 unsigned i;
427
428 pa_assert(iter);
429 pa_assert(e);
430
431 pa_assert_se(dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY, "(uu)", &array_iter));
432
433 if (!e->volume_valid) {
434 pa_assert_se(dbus_message_iter_close_container(iter, &array_iter));
435 return;
436 }
437
438 for (i = 0; i < e->channel_map.channels; ++i) {
439 pa_assert_se(dbus_message_iter_open_container(&array_iter, DBUS_TYPE_STRUCT, NULL, &struct_iter));
440
441 pa_assert_se(dbus_message_iter_append_basic(&struct_iter, DBUS_TYPE_UINT32, &e->channel_map.map[i]));
442 pa_assert_se(dbus_message_iter_append_basic(&struct_iter, DBUS_TYPE_UINT32, &e->volume.values[i]));
443
444 pa_assert_se(dbus_message_iter_close_container(&array_iter, &struct_iter));
445 }
446
447 pa_assert_se(dbus_message_iter_close_container(iter, &array_iter));
448 }
449
450 static void append_volume_variant(DBusMessageIter *iter, struct entry *e) {
451 DBusMessageIter variant_iter;
452
453 pa_assert(iter);
454 pa_assert(e);
455
456 pa_assert_se(dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "a(uu)", &variant_iter));
457
458 append_volume(&variant_iter, e);
459
460 pa_assert_se(dbus_message_iter_close_container(iter, &variant_iter));
461 }
462
463 static void send_new_entry_signal(struct dbus_entry *entry) {
464 DBusMessage *signal;
465
466 pa_assert(entry);
467
468 pa_assert_se(signal = dbus_message_new_signal(OBJECT_PATH, INTERFACE_STREAM_RESTORE, signals[SIGNAL_NEW_ENTRY].name));
469 pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_OBJECT_PATH, &entry->object_path, DBUS_TYPE_INVALID));
470 pa_dbus_protocol_send_signal(entry->userdata->dbus_protocol, signal);
471 dbus_message_unref(signal);
472 }
473
474 static void send_entry_removed_signal(struct dbus_entry *entry) {
475 DBusMessage *signal;
476
477 pa_assert(entry);
478
479 pa_assert_se(signal = dbus_message_new_signal(OBJECT_PATH, INTERFACE_STREAM_RESTORE, signals[SIGNAL_ENTRY_REMOVED].name));
480 pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_OBJECT_PATH, &entry->object_path, DBUS_TYPE_INVALID));
481 pa_dbus_protocol_send_signal(entry->userdata->dbus_protocol, signal);
482 dbus_message_unref(signal);
483 }
484
485 static void send_device_updated_signal(struct dbus_entry *de, struct entry *e) {
486 DBusMessage *signal;
487 const char *device;
488
489 pa_assert(de);
490 pa_assert(e);
491
492 device = e->device_valid ? e->device : "";
493
494 pa_assert_se(signal = dbus_message_new_signal(de->object_path, INTERFACE_ENTRY, entry_signals[ENTRY_SIGNAL_DEVICE_UPDATED].name));
495 pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_STRING, &device, DBUS_TYPE_INVALID));
496 pa_dbus_protocol_send_signal(de->userdata->dbus_protocol, signal);
497 dbus_message_unref(signal);
498 }
499
500 static void send_volume_updated_signal(struct dbus_entry *de, struct entry *e) {
501 DBusMessage *signal;
502 DBusMessageIter msg_iter;
503
504 pa_assert(de);
505 pa_assert(e);
506
507 pa_assert_se(signal = dbus_message_new_signal(de->object_path, INTERFACE_ENTRY, entry_signals[ENTRY_SIGNAL_VOLUME_UPDATED].name));
508 dbus_message_iter_init_append(signal, &msg_iter);
509 append_volume(&msg_iter, e);
510 pa_dbus_protocol_send_signal(de->userdata->dbus_protocol, signal);
511 dbus_message_unref(signal);
512 }
513
514 static void send_mute_updated_signal(struct dbus_entry *de, struct entry *e) {
515 DBusMessage *signal;
516 dbus_bool_t muted;
517
518 pa_assert(de);
519 pa_assert(e);
520
521 pa_assert(e->muted_valid);
522
523 muted = e->muted;
524
525 pa_assert_se(signal = dbus_message_new_signal(de->object_path, INTERFACE_ENTRY, entry_signals[ENTRY_SIGNAL_MUTE_UPDATED].name));
526 pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_BOOLEAN, &muted, DBUS_TYPE_INVALID));
527 pa_dbus_protocol_send_signal(de->userdata->dbus_protocol, signal);
528 dbus_message_unref(signal);
529 }
530
531 static void handle_get_interface_revision(DBusConnection *conn, DBusMessage *msg, void *userdata) {
532 dbus_uint32_t interface_revision = DBUS_INTERFACE_REVISION;
533
534 pa_assert(conn);
535 pa_assert(msg);
536
537 pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT32, &interface_revision);
538 }
539
540 /* The caller frees the array, but not the strings. */
541 static const char **get_entries(struct userdata *u, unsigned *n) {
542 const char **entries;
543 unsigned i = 0;
544 void *state = NULL;
545 struct dbus_entry *de;
546
547 pa_assert(u);
548 pa_assert(n);
549
550 *n = pa_hashmap_size(u->dbus_entries);
551
552 if (*n == 0)
553 return NULL;
554
555 entries = pa_xnew(const char *, *n);
556
557 PA_HASHMAP_FOREACH(de, u->dbus_entries, state)
558 entries[i++] = de->object_path;
559
560 return entries;
561 }
562
563 static void handle_get_entries(DBusConnection *conn, DBusMessage *msg, void *userdata) {
564 struct userdata *u = userdata;
565 const char **entries;
566 unsigned n;
567
568 pa_assert(conn);
569 pa_assert(msg);
570 pa_assert(u);
571
572 entries = get_entries(u, &n);
573
574 pa_dbus_send_basic_array_variant_reply(conn, msg, DBUS_TYPE_OBJECT_PATH, entries, n);
575
576 pa_xfree(entries);
577 }
578
579 static void handle_get_all(DBusConnection *conn, DBusMessage *msg, void *userdata) {
580 struct userdata *u = userdata;
581 DBusMessage *reply = NULL;
582 DBusMessageIter msg_iter;
583 DBusMessageIter dict_iter;
584 dbus_uint32_t interface_revision;
585 const char **entries;
586 unsigned n_entries;
587
588 pa_assert(conn);
589 pa_assert(msg);
590 pa_assert(u);
591
592 interface_revision = DBUS_INTERFACE_REVISION;
593 entries = get_entries(u, &n_entries);
594
595 pa_assert_se((reply = dbus_message_new_method_return(msg)));
596
597 dbus_message_iter_init_append(reply, &msg_iter);
598 pa_assert_se(dbus_message_iter_open_container(&msg_iter, DBUS_TYPE_ARRAY, "{sv}", &dict_iter));
599
600 pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_INTERFACE_REVISION].property_name, DBUS_TYPE_UINT32, &interface_revision);
601 pa_dbus_append_basic_array_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_ENTRIES].property_name, DBUS_TYPE_OBJECT_PATH, entries, n_entries);
602
603 pa_assert_se(dbus_message_iter_close_container(&msg_iter, &dict_iter));
604
605 pa_assert_se(dbus_connection_send(conn, reply, NULL));
606
607 dbus_message_unref(reply);
608
609 pa_xfree(entries);
610 }
611
612 static void handle_add_entry(DBusConnection *conn, DBusMessage *msg, void *userdata) {
613 struct userdata *u = userdata;
614 DBusMessageIter msg_iter;
615 const char *name;
616 const char *device;
617 pa_channel_map map;
618 pa_cvolume vol;
619 dbus_bool_t muted;
620 dbus_bool_t apply_immediately;
621 pa_datum key;
622 pa_datum value;
623 struct dbus_entry *dbus_entry;
624 struct entry *e;
625
626 pa_assert(conn);
627 pa_assert(msg);
628 pa_assert(u);
629
630 if (!dbus_message_iter_init(msg, &msg_iter)) {
631 pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "Too few arguments.");
632 return;
633 }
634
635 if (pa_dbus_get_basic_arg(conn, msg, &msg_iter, DBUS_TYPE_STRING, &name) < 0)
636 return;
637
638 if (pa_dbus_get_basic_arg(conn, msg, &msg_iter, DBUS_TYPE_STRING, &device) < 0)
639 return;
640
641 if (get_volume_arg(conn, msg, &msg_iter, &map, &vol) < 0)
642 return;
643
644 if (pa_dbus_get_basic_arg(conn, msg, &msg_iter, DBUS_TYPE_BOOLEAN, &muted) < 0)
645 return;
646
647 if (pa_dbus_get_basic_arg(conn, msg, &msg_iter, DBUS_TYPE_BOOLEAN, &apply_immediately) < 0)
648 return;
649
650 if (!*name) {
651 pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "An empty string was given as the entry name.");
652 return;
653 }
654
655 if ((dbus_entry = pa_hashmap_get(u->dbus_entries, name))) {
656 pa_bool_t mute_updated = FALSE;
657 pa_bool_t volume_updated = FALSE;
658 pa_bool_t device_updated = FALSE;
659
660 pa_assert_se(e = read_entry(u, name));
661 mute_updated = e->muted != muted;
662 e->muted = muted;
663 e->muted_valid = TRUE;
664
665 volume_updated = (e->volume_valid != !!map.channels) || !pa_cvolume_equal(&e->volume, &vol);
666 e->volume = vol;
667 e->channel_map = map;
668 e->volume_valid = !!map.channels;
669
670 device_updated = (e->device_valid != !!device[0]) || !pa_streq(e->device, device);
671 pa_strlcpy(e->device, device, sizeof(e->device));
672 e->device_valid = !!device[0];
673
674 if (mute_updated)
675 send_mute_updated_signal(dbus_entry, e);
676 if (volume_updated)
677 send_volume_updated_signal(dbus_entry, e);
678 if (device_updated)
679 send_device_updated_signal(dbus_entry, e);
680
681 } else {
682 dbus_entry = dbus_entry_new(u, name);
683 pa_assert(pa_hashmap_put(u->dbus_entries, dbus_entry->entry_name, dbus_entry) >= 0);
684
685 e->muted_valid = TRUE;
686 e->volume_valid = !!map.channels;
687 e->device_valid = !!device[0];
688 e->muted = muted;
689 e->volume = vol;
690 e->channel_map = map;
691 pa_strlcpy(e->device, device, sizeof(e->device));
692
693 send_new_entry_signal(dbus_entry);
694 }
695
696 key.data = (char *) name;
697 key.size = strlen(name);
698
699 value.data = e;
700 value.size = sizeof(struct entry);
701
702 pa_assert_se(pa_database_set(u->database, &key, &value, TRUE) == 0);
703 if (apply_immediately)
704 apply_entry(u, name, e);
705
706 trigger_save(u);
707
708 pa_dbus_send_empty_reply(conn, msg);
709
710 pa_xfree(e);
711 }
712
713 static void handle_get_entry_by_name(DBusConnection *conn, DBusMessage *msg, void *userdata) {
714 struct userdata *u = userdata;
715 const char *name;
716 struct dbus_entry *de;
717 DBusError error;
718
719 pa_assert(conn);
720 pa_assert(msg);
721 pa_assert(u);
722
723 dbus_error_init(&error);
724
725 if (!dbus_message_get_args(msg, &error, DBUS_TYPE_STRING, &name, DBUS_TYPE_INVALID)) {
726 pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "%s", error.message);
727 dbus_error_free(&error);
728 return;
729 }
730
731 if (!(de = pa_hashmap_get(u->dbus_entries, name))) {
732 pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NOT_FOUND, "No such stream restore entry.");
733 return;
734 }
735
736 pa_dbus_send_basic_value_reply(conn, msg, DBUS_TYPE_OBJECT_PATH, &de->object_path);
737 }
738
739 static void handle_entry_get_index(DBusConnection *conn, DBusMessage *msg, void *userdata) {
740 struct dbus_entry *de = userdata;
741
742 pa_assert(conn);
743 pa_assert(msg);
744 pa_assert(de);
745
746 pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT32, &de->index);
747 }
748
749 static void handle_entry_get_name(DBusConnection *conn, DBusMessage *msg, void *userdata) {
750 struct dbus_entry *de = userdata;
751
752 pa_assert(conn);
753 pa_assert(msg);
754 pa_assert(de);
755
756 pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_STRING, &de->entry_name);
757 }
758
759 static void handle_entry_get_device(DBusConnection *conn, DBusMessage *msg, void *userdata) {
760 struct dbus_entry *de = userdata;
761 struct entry *e;
762 const char *device;
763
764 pa_assert(conn);
765 pa_assert(msg);
766 pa_assert(de);
767
768 pa_assert_se(e = read_entry(de->userdata, de->entry_name));
769
770 device = e->device_valid ? e->device : "";
771
772 pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_STRING, &device);
773
774 pa_xfree(e);
775 }
776
777 static void handle_entry_set_device(DBusConnection *conn, DBusMessage *msg, void *userdata) {
778 struct dbus_entry *de = userdata;
779 const char *device;
780 struct entry *e;
781 pa_bool_t updated;
782
783 pa_assert(conn);
784 pa_assert(msg);
785 pa_assert(de);
786
787 if (pa_dbus_get_basic_set_property_arg(conn, msg, DBUS_TYPE_STRING, &device) < 0)
788 return;
789
790 pa_assert_se(e = read_entry(de->userdata, de->entry_name));
791
792 updated = (e->device_valid != !!device[0]) || !pa_streq(e->device, device);
793
794 if (updated) {
795 pa_datum key;
796 pa_datum value;
797
798 pa_strlcpy(e->device, device, sizeof(e->device));
799 e->device_valid = !!device[0];
800
801 key.data = de->entry_name;
802 key.size = strlen(de->entry_name);
803 value.data = e;
804 value.size = sizeof(struct entry);
805 pa_assert_se(pa_database_set(de->userdata->database, &key, &value, TRUE) == 0);
806
807 send_device_updated_signal(de, e);
808 trigger_save(de->userdata);
809 }
810
811 pa_dbus_send_empty_reply(conn, msg);
812
813 pa_xfree(e);
814 }
815
816 static void handle_entry_get_volume(DBusConnection *conn, DBusMessage *msg, void *userdata) {
817 struct dbus_entry *de = userdata;
818 DBusMessage *reply;
819 DBusMessageIter msg_iter;
820 struct entry *e;
821
822 pa_assert(conn);
823 pa_assert(msg);
824 pa_assert(de);
825
826 pa_assert_se(e = read_entry(de->userdata, de->entry_name));
827
828 pa_assert_se(reply = dbus_message_new_method_return(msg));
829
830 dbus_message_iter_init_append(reply, &msg_iter);
831 append_volume_variant(&msg_iter, e);
832
833 pa_assert_se(dbus_connection_send(conn, reply, NULL));
834
835 pa_xfree(e);
836 }
837
838 static void handle_entry_set_volume(DBusConnection *conn, DBusMessage *msg, void *userdata) {
839 struct dbus_entry *de = userdata;
840 DBusMessageIter msg_iter;
841 pa_channel_map map;
842 pa_cvolume vol;
843 struct entry *e;
844 pa_bool_t updated;
845
846 pa_assert(conn);
847 pa_assert(msg);
848 pa_assert(de);
849
850 /* Skip the interface and property name arguments. */
851 if (!dbus_message_iter_init(msg, &msg_iter) || !dbus_message_iter_next(&msg_iter) || !dbus_message_iter_next(&msg_iter)) {
852 pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "Too few arguments.");
853 return;
854 }
855
856 if (get_volume_arg(conn, msg, &msg_iter, &map, &vol) < 0)
857 return;
858
859 pa_assert_se(e = read_entry(de->userdata, de->entry_name));
860
861 updated = (e->volume_valid != !!map.channels) || !pa_cvolume_equal(&e->volume, &vol);
862
863 if (updated) {
864 pa_datum key;
865 pa_datum value;
866
867 e->volume = vol;
868 e->channel_map = map;
869 e->volume_valid = !!map.channels;
870
871 key.data = de->entry_name;
872 key.size = strlen(de->entry_name);
873 value.data = e;
874 value.size = sizeof(struct entry);
875 pa_assert_se(pa_database_set(de->userdata->database, &key, &value, TRUE) == 0);
876
877 send_volume_updated_signal(de, e);
878 trigger_save(de->userdata);
879 }
880
881 pa_dbus_send_empty_reply(conn, msg);
882
883 pa_xfree(e);
884 }
885
886 static void handle_entry_get_is_muted(DBusConnection *conn, DBusMessage *msg, void *userdata) {
887 struct dbus_entry *de = userdata;
888 struct entry *e;
889 dbus_bool_t muted;
890
891 pa_assert(conn);
892 pa_assert(msg);
893 pa_assert(de);
894
895 pa_assert_se(e = read_entry(de->userdata, de->entry_name));
896
897 muted = e->muted_valid ? e->muted : FALSE;
898
899 pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_BOOLEAN, &muted);
900
901 pa_xfree(e);
902 }
903
904 static void handle_entry_set_is_muted(DBusConnection *conn, DBusMessage *msg, void *userdata) {
905 struct dbus_entry *de = userdata;
906 pa_bool_t muted;
907 struct entry *e;
908 pa_bool_t updated;
909
910 pa_assert(conn);
911 pa_assert(msg);
912 pa_assert(de);
913
914 if (pa_dbus_get_basic_set_property_arg(conn, msg, DBUS_TYPE_BOOLEAN, &muted) < 0)
915 return;
916
917 pa_assert_se(e = read_entry(de->userdata, de->entry_name));
918
919 updated = !e->muted_valid || e->muted != muted;
920
921 if (updated) {
922 pa_datum key;
923 pa_datum value;
924
925 e->muted = muted;
926 e->muted_valid = TRUE;
927
928 key.data = de->entry_name;
929 key.size = strlen(de->entry_name);
930 value.data = e;
931 value.size = sizeof(struct entry);
932 pa_assert_se(pa_database_set(de->userdata->database, &key, &value, TRUE) == 0);
933
934 send_mute_updated_signal(de, e);
935 trigger_save(de->userdata);
936 }
937
938 pa_dbus_send_empty_reply(conn, msg);
939
940 pa_xfree(e);
941 }
942
943 static void handle_entry_get_all(DBusConnection *conn, DBusMessage *msg, void *userdata) {
944 struct dbus_entry *de = userdata;
945 struct entry *e;
946 DBusMessage *reply = NULL;
947 DBusMessageIter msg_iter;
948 DBusMessageIter dict_iter;
949 DBusMessageIter dict_entry_iter;
950 const char *device;
951 dbus_bool_t muted;
952
953 pa_assert(conn);
954 pa_assert(msg);
955 pa_assert(de);
956
957 pa_assert_se(e = read_entry(de->userdata, de->entry_name));
958
959 device = e->device_valid ? e->device : "";
960 muted = e->muted_valid ? e->muted : FALSE;
961
962 pa_assert_se((reply = dbus_message_new_method_return(msg)));
963
964 dbus_message_iter_init_append(reply, &msg_iter);
965 pa_assert_se(dbus_message_iter_open_container(&msg_iter, DBUS_TYPE_ARRAY, "{sv}", &dict_iter));
966
967 pa_dbus_append_basic_variant_dict_entry(&dict_iter, entry_property_handlers[ENTRY_PROPERTY_HANDLER_INDEX].property_name, DBUS_TYPE_UINT32, &de->index);
968 pa_dbus_append_basic_variant_dict_entry(&dict_iter, entry_property_handlers[ENTRY_PROPERTY_HANDLER_NAME].property_name, DBUS_TYPE_STRING, &de->entry_name);
969 pa_dbus_append_basic_variant_dict_entry(&dict_iter, entry_property_handlers[ENTRY_PROPERTY_HANDLER_DEVICE].property_name, DBUS_TYPE_STRING, &device);
970
971 pa_assert_se(dbus_message_iter_open_container(&dict_iter, DBUS_TYPE_DICT_ENTRY, NULL, &dict_entry_iter));
972
973 pa_assert_se(dbus_message_iter_append_basic(&dict_entry_iter, DBUS_TYPE_STRING, &entry_property_handlers[ENTRY_PROPERTY_HANDLER_VOLUME].property_name));
974 append_volume_variant(&dict_entry_iter, e);
975
976 pa_assert_se(dbus_message_iter_close_container(&dict_iter, &dict_entry_iter));
977
978 pa_dbus_append_basic_variant_dict_entry(&dict_iter, entry_property_handlers[ENTRY_PROPERTY_HANDLER_IS_MUTED].property_name, DBUS_TYPE_BOOLEAN, &muted);
979
980 pa_assert_se(dbus_message_iter_close_container(&msg_iter, &dict_iter));
981
982 pa_assert_se(dbus_connection_send(conn, reply, NULL));
983
984 dbus_message_unref(reply);
985
986 pa_xfree(e);
987 }
988
989 static void handle_entry_remove(DBusConnection *conn, DBusMessage *msg, void *userdata) {
990 struct dbus_entry *de = userdata;
991 pa_datum key;
992
993 pa_assert(conn);
994 pa_assert(msg);
995 pa_assert(de);
996
997 key.data = de->entry_name;
998 key.size = strlen(de->entry_name);
999
1000 pa_assert_se(pa_database_unset(de->userdata->database, &key) == 0);
1001
1002 send_entry_removed_signal(de);
1003 trigger_save(de->userdata);
1004
1005 pa_assert_se(pa_hashmap_remove(de->userdata->dbus_entries, de->entry_name));
1006 dbus_entry_free(de);
1007
1008 pa_dbus_send_empty_reply(conn, msg);
1009 }
1010
1011 #endif /* HAVE_DBUS */
1012
1013 static void save_time_callback(pa_mainloop_api*a, pa_time_event* e, const struct timeval *t, void *userdata) {
1014 struct userdata *u = userdata;
1015
1016 pa_assert(a);
1017 pa_assert(e);
1018 pa_assert(u);
1019
1020 pa_assert(e == u->save_time_event);
1021 u->core->mainloop->time_free(u->save_time_event);
1022 u->save_time_event = NULL;
1023
1024 pa_database_sync(u->database);
1025 pa_log_info("Synced.");
1026 }
1027
1028 static char *get_name(pa_proplist *p, const char *prefix) {
1029 const char *r;
1030 char *t;
1031
1032 if (!p)
1033 return NULL;
1034
1035 if ((r = pa_proplist_gets(p, IDENTIFICATION_PROPERTY)))
1036 return pa_xstrdup(r);
1037
1038 if ((r = pa_proplist_gets(p, PA_PROP_MEDIA_ROLE)))
1039 t = pa_sprintf_malloc("%s-by-media-role:%s", prefix, r);
1040 else if ((r = pa_proplist_gets(p, PA_PROP_APPLICATION_ID)))
1041 t = pa_sprintf_malloc("%s-by-application-id:%s", prefix, r);
1042 else if ((r = pa_proplist_gets(p, PA_PROP_APPLICATION_NAME)))
1043 t = pa_sprintf_malloc("%s-by-application-name:%s", prefix, r);
1044 else if ((r = pa_proplist_gets(p, PA_PROP_MEDIA_NAME)))
1045 t = pa_sprintf_malloc("%s-by-media-name:%s", prefix, r);
1046 else
1047 t = pa_sprintf_malloc("%s-fallback:%s", prefix, r);
1048
1049 pa_proplist_sets(p, IDENTIFICATION_PROPERTY, t);
1050 return t;
1051 }
1052
1053 static struct entry *read_entry(struct userdata *u, const char *name) {
1054 pa_datum key, data;
1055 struct entry *e;
1056
1057 pa_assert(u);
1058 pa_assert(name);
1059
1060 key.data = (char*) name;
1061 key.size = strlen(name);
1062
1063 pa_zero(data);
1064
1065 if (!pa_database_get(u->database, &key, &data))
1066 goto fail;
1067
1068 if (data.size != sizeof(struct entry)) {
1069 /* This is probably just a database upgrade, hence let's not
1070 * consider this more than a debug message */
1071 pa_log_debug("Database contains entry for stream %s of wrong size %lu != %lu. Probably due to uprade, ignoring.", name, (unsigned long) data.size, (unsigned long) sizeof(struct entry));
1072 goto fail;
1073 }
1074
1075 e = (struct entry*) data.data;
1076
1077 if (e->version != ENTRY_VERSION) {
1078 pa_log_debug("Version of database entry for stream %s doesn't match our version. Probably due to upgrade, ignoring.", name);
1079 goto fail;
1080 }
1081
1082 if (!memchr(e->device, 0, sizeof(e->device))) {
1083 pa_log_warn("Database contains entry for stream %s with missing NUL byte in device name", name);
1084 goto fail;
1085 }
1086
1087 if (!memchr(e->card, 0, sizeof(e->card))) {
1088 pa_log_warn("Database contains entry for stream %s with missing NUL byte in card name", name);
1089 goto fail;
1090 }
1091
1092 if (e->device_valid && !pa_namereg_is_valid_name(e->device)) {
1093 pa_log_warn("Invalid device name stored in database for stream %s", name);
1094 goto fail;
1095 }
1096
1097 if (e->card_valid && !pa_namereg_is_valid_name(e->card)) {
1098 pa_log_warn("Invalid card name stored in database for stream %s", name);
1099 goto fail;
1100 }
1101
1102 if (e->volume_valid && !pa_channel_map_valid(&e->channel_map)) {
1103 pa_log_warn("Invalid channel map stored in database for stream %s", name);
1104 goto fail;
1105 }
1106
1107 if (e->volume_valid && (!pa_cvolume_valid(&e->volume) || !pa_cvolume_compatible_with_channel_map(&e->volume, &e->channel_map))) {
1108 pa_log_warn("Invalid volume stored in database for stream %s", name);
1109 goto fail;
1110 }
1111
1112 return e;
1113
1114 fail:
1115
1116 pa_datum_free(&data);
1117 return NULL;
1118 }
1119
1120 static void trigger_save(struct userdata *u) {
1121 pa_native_connection *c;
1122 uint32_t idx;
1123
1124 for (c = pa_idxset_first(u->subscribed, &idx); c; c = pa_idxset_next(u->subscribed, &idx)) {
1125 pa_tagstruct *t;
1126
1127 t = pa_tagstruct_new(NULL, 0);
1128 pa_tagstruct_putu32(t, PA_COMMAND_EXTENSION);
1129 pa_tagstruct_putu32(t, 0);
1130 pa_tagstruct_putu32(t, u->module->index);
1131 pa_tagstruct_puts(t, u->module->name);
1132 pa_tagstruct_putu32(t, SUBCOMMAND_EVENT);
1133
1134 pa_pstream_send_tagstruct(pa_native_connection_get_pstream(c), t);
1135 }
1136
1137 if (u->save_time_event)
1138 return;
1139
1140 u->save_time_event = pa_core_rttime_new(u->core, pa_rtclock_now() + SAVE_INTERVAL, save_time_callback, u);
1141 }
1142
1143 static pa_bool_t entries_equal(const struct entry *a, const struct entry *b) {
1144 pa_cvolume t;
1145
1146 pa_assert(a);
1147 pa_assert(b);
1148
1149 if (a->device_valid != b->device_valid ||
1150 (a->device_valid && strncmp(a->device, b->device, sizeof(a->device))))
1151 return FALSE;
1152
1153 if (a->card_valid != b->card_valid ||
1154 (a->card_valid && strncmp(a->card, b->card, sizeof(a->card))))
1155 return FALSE;
1156
1157 if (a->muted_valid != b->muted_valid ||
1158 (a->muted_valid && (a->muted != b->muted)))
1159 return FALSE;
1160
1161 t = b->volume;
1162 if (a->volume_valid != b->volume_valid ||
1163 (a->volume_valid && !pa_cvolume_equal(pa_cvolume_remap(&t, &b->channel_map, &a->channel_map), &a->volume)))
1164 return FALSE;
1165
1166 return TRUE;
1167 }
1168
1169 static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint32_t idx, void *userdata) {
1170 struct userdata *u = userdata;
1171 struct entry entry, *old;
1172 char *name;
1173 pa_datum key, data;
1174
1175 /* These are only used when D-Bus is enabled, but in order to reduce ifdef
1176 * clutter these are defined here unconditionally. */
1177 pa_bool_t created_new_entry = TRUE;
1178 pa_bool_t device_updated = FALSE;
1179 pa_bool_t volume_updated = FALSE;
1180 pa_bool_t mute_updated = FALSE;
1181
1182 #ifdef HAVE_DBUS
1183 struct dbus_entry *de = NULL;
1184 #endif
1185
1186 pa_assert(c);
1187 pa_assert(u);
1188
1189 if (t != (PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_NEW) &&
1190 t != (PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE) &&
1191 t != (PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_NEW) &&
1192 t != (PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_CHANGE))
1193 return;
1194
1195 pa_zero(entry);
1196 entry.version = ENTRY_VERSION;
1197
1198 if ((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SINK_INPUT) {
1199 pa_sink_input *sink_input;
1200
1201 if (!(sink_input = pa_idxset_get_by_index(c->sink_inputs, idx)))
1202 return;
1203
1204 if (!(name = get_name(sink_input->proplist, "sink-input")))
1205 return;
1206
1207 if ((old = read_entry(u, name))) {
1208 entry = *old;
1209 created_new_entry = FALSE;
1210 }
1211
1212 if (sink_input->save_volume) {
1213 entry.channel_map = sink_input->channel_map;
1214 pa_sink_input_get_volume(sink_input, &entry.volume, FALSE);
1215 entry.volume_valid = TRUE;
1216
1217 volume_updated = !created_new_entry
1218 && (!old->volume_valid
1219 || !pa_channel_map_equal(&entry.channel_map, &old->channel_map)
1220 || !pa_cvolume_equal(&entry.volume, &old->volume));
1221 }
1222
1223 if (sink_input->save_muted) {
1224 entry.muted = pa_sink_input_get_mute(sink_input);
1225 entry.muted_valid = TRUE;
1226
1227 mute_updated = !created_new_entry && (!old->muted_valid || entry.muted != old->muted);
1228 }
1229
1230 if (sink_input->save_sink) {
1231 pa_strlcpy(entry.device, sink_input->sink->name, sizeof(entry.device));
1232 entry.device_valid = TRUE;
1233
1234 device_updated = !created_new_entry && (!old->device_valid || !pa_streq(entry.device, old->device));
1235 if (sink_input->sink->card) {
1236 pa_strlcpy(entry.card, sink_input->sink->card->name, sizeof(entry.card));
1237 entry.card_valid = TRUE;
1238 }
1239 }
1240
1241 } else {
1242 pa_source_output *source_output;
1243
1244 pa_assert((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT);
1245
1246 if (!(source_output = pa_idxset_get_by_index(c->source_outputs, idx)))
1247 return;
1248
1249 if (!(name = get_name(source_output->proplist, "source-output")))
1250 return;
1251
1252 if ((old = read_entry(u, name))) {
1253 entry = *old;
1254 created_new_entry = FALSE;
1255 }
1256
1257 if (source_output->save_source) {
1258 pa_strlcpy(entry.device, source_output->source->name, sizeof(entry.device));
1259 entry.device_valid = source_output->save_source;
1260
1261 device_updated = !created_new_entry && (!old->device_valid || !pa_streq(entry.device, old->device));
1262
1263 if (source_output->source->card) {
1264 pa_strlcpy(entry.card, source_output->source->card->name, sizeof(entry.card));
1265 entry.card_valid = TRUE;
1266 }
1267 }
1268 }
1269
1270 if (old) {
1271
1272 if (entries_equal(old, &entry)) {
1273 pa_xfree(old);
1274 pa_xfree(name);
1275 return;
1276 }
1277
1278 pa_xfree(old);
1279 }
1280
1281 key.data = name;
1282 key.size = strlen(name);
1283
1284 data.data = &entry;
1285 data.size = sizeof(entry);
1286
1287 pa_log_info("Storing volume/mute/device for stream %s.", name);
1288
1289 pa_database_set(u->database, &key, &data, TRUE);
1290
1291 #ifdef HAVE_DBUS
1292 if (created_new_entry) {
1293 de = dbus_entry_new(u, name);
1294 pa_hashmap_put(u->dbus_entries, de->entry_name, de);
1295 send_new_entry_signal(de);
1296 } else {
1297 pa_assert((de = pa_hashmap_get(u->dbus_entries, name)));
1298
1299 if (device_updated)
1300 send_device_updated_signal(de, &entry);
1301 if (volume_updated)
1302 send_volume_updated_signal(de, &entry);
1303 if (mute_updated)
1304 send_mute_updated_signal(de, &entry);
1305 }
1306 #endif
1307
1308 pa_xfree(name);
1309
1310 trigger_save(u);
1311 }
1312
1313 static pa_hook_result_t sink_input_new_hook_callback(pa_core *c, pa_sink_input_new_data *new_data, struct userdata *u) {
1314 char *name;
1315 struct entry *e;
1316
1317 pa_assert(c);
1318 pa_assert(new_data);
1319 pa_assert(u);
1320 pa_assert(u->restore_device);
1321
1322 if (!(name = get_name(new_data->proplist, "sink-input")))
1323 return PA_HOOK_OK;
1324
1325 if (new_data->sink)
1326 pa_log_debug("Not restoring device for stream %s, because already set.", name);
1327 else if ((e = read_entry(u, name))) {
1328 pa_sink *s = NULL;
1329
1330 if (e->device_valid)
1331 s = pa_namereg_get(c, e->device, PA_NAMEREG_SINK);
1332
1333 if (!s && e->card_valid) {
1334 pa_card *card;
1335
1336 if ((card = pa_namereg_get(c, e->card, PA_NAMEREG_CARD)))
1337 s = pa_idxset_first(card->sinks, NULL);
1338 }
1339
1340 /* It might happen that a stream and a sink are set up at the
1341 same time, in which case we want to make sure we don't
1342 interfere with that */
1343 if (s && PA_SINK_IS_LINKED(pa_sink_get_state(s))) {
1344 pa_log_info("Restoring device for stream %s.", name);
1345 new_data->sink = s;
1346 new_data->save_sink = TRUE;
1347 }
1348
1349 pa_xfree(e);
1350 }
1351
1352 pa_xfree(name);
1353
1354 return PA_HOOK_OK;
1355 }
1356
1357 static pa_hook_result_t sink_input_fixate_hook_callback(pa_core *c, pa_sink_input_new_data *new_data, struct userdata *u) {
1358 char *name;
1359 struct entry *e;
1360
1361 pa_assert(c);
1362 pa_assert(new_data);
1363 pa_assert(u);
1364 pa_assert(u->restore_volume || u->restore_muted);
1365
1366 if (!(name = get_name(new_data->proplist, "sink-input")))
1367 return PA_HOOK_OK;
1368
1369 if ((e = read_entry(u, name))) {
1370
1371 if (u->restore_volume && e->volume_valid) {
1372
1373 if (!new_data->volume_is_set) {
1374 pa_cvolume v;
1375
1376 pa_log_info("Restoring volume for sink input %s.", name);
1377
1378 v = e->volume;
1379 pa_cvolume_remap(&v, &e->channel_map, &new_data->channel_map);
1380 pa_sink_input_new_data_set_volume(new_data, &v);
1381
1382 new_data->volume_is_absolute = FALSE;
1383 new_data->save_volume = TRUE;
1384 } else
1385 pa_log_debug("Not restoring volume for sink input %s, because already set.", name);
1386 }
1387
1388 if (u->restore_muted && e->muted_valid) {
1389
1390 if (!new_data->muted_is_set) {
1391 pa_log_info("Restoring mute state for sink input %s.", name);
1392 pa_sink_input_new_data_set_muted(new_data, e->muted);
1393 new_data->save_muted = TRUE;
1394 } else
1395 pa_log_debug("Not restoring mute state for sink input %s, because already set.", name);
1396 }
1397
1398 pa_xfree(e);
1399 }
1400
1401 pa_xfree(name);
1402
1403 return PA_HOOK_OK;
1404 }
1405
1406 static pa_hook_result_t source_output_new_hook_callback(pa_core *c, pa_source_output_new_data *new_data, struct userdata *u) {
1407 char *name;
1408 struct entry *e;
1409
1410 pa_assert(c);
1411 pa_assert(new_data);
1412 pa_assert(u);
1413 pa_assert(u->restore_device);
1414
1415 if (new_data->direct_on_input)
1416 return PA_HOOK_OK;
1417
1418 if (!(name = get_name(new_data->proplist, "source-output")))
1419 return PA_HOOK_OK;
1420
1421 if (new_data->source)
1422 pa_log_debug("Not restoring device for stream %s, because already set", name);
1423 else if ((e = read_entry(u, name))) {
1424 pa_source *s = NULL;
1425
1426 if (e->device_valid)
1427 s = pa_namereg_get(c, e->device, PA_NAMEREG_SOURCE);
1428
1429 if (!s && e->card_valid) {
1430 pa_card *card;
1431
1432 if ((card = pa_namereg_get(c, e->card, PA_NAMEREG_CARD)))
1433 s = pa_idxset_first(card->sources, NULL);
1434 }
1435
1436 /* It might happen that a stream and a sink are set up at the
1437 same time, in which case we want to make sure we don't
1438 interfere with that */
1439 if (s && PA_SOURCE_IS_LINKED(pa_source_get_state(s))) {
1440 pa_log_info("Restoring device for stream %s.", name);
1441 new_data->source = s;
1442 new_data->save_source = TRUE;
1443 }
1444
1445 pa_xfree(e);
1446 }
1447
1448 pa_xfree(name);
1449
1450 return PA_HOOK_OK;
1451 }
1452
1453 static pa_hook_result_t sink_put_hook_callback(pa_core *c, pa_sink *sink, struct userdata *u) {
1454 pa_sink_input *si;
1455 uint32_t idx;
1456
1457 pa_assert(c);
1458 pa_assert(sink);
1459 pa_assert(u);
1460 pa_assert(u->on_hotplug && u->restore_device);
1461
1462 PA_IDXSET_FOREACH(si, c->sink_inputs, idx) {
1463 char *name;
1464 struct entry *e;
1465
1466 if (si->sink == sink)
1467 continue;
1468
1469 if (si->save_sink)
1470 continue;
1471
1472 /* Skip this if it is already in the process of being moved
1473 * anyway */
1474 if (!si->sink)
1475 continue;
1476
1477 /* It might happen that a stream and a sink are set up at the
1478 same time, in which case we want to make sure we don't
1479 interfere with that */
1480 if (!PA_SINK_INPUT_IS_LINKED(pa_sink_input_get_state(si)))
1481 continue;
1482
1483 if (!(name = get_name(si->proplist, "sink-input")))
1484 continue;
1485
1486 if ((e = read_entry(u, name))) {
1487 if (e->device_valid && pa_streq(e->device, sink->name))
1488 pa_sink_input_move_to(si, sink, TRUE);
1489
1490 pa_xfree(e);
1491 }
1492
1493 pa_xfree(name);
1494 }
1495
1496 return PA_HOOK_OK;
1497 }
1498
1499 static pa_hook_result_t source_put_hook_callback(pa_core *c, pa_source *source, struct userdata *u) {
1500 pa_source_output *so;
1501 uint32_t idx;
1502
1503 pa_assert(c);
1504 pa_assert(source);
1505 pa_assert(u);
1506 pa_assert(u->on_hotplug && u->restore_device);
1507
1508 PA_IDXSET_FOREACH(so, c->source_outputs, idx) {
1509 char *name;
1510 struct entry *e;
1511
1512 if (so->source == source)
1513 continue;
1514
1515 if (so->save_source)
1516 continue;
1517
1518 if (so->direct_on_input)
1519 continue;
1520
1521 /* Skip this if it is already in the process of being moved anyway */
1522 if (!so->source)
1523 continue;
1524
1525 /* It might happen that a stream and a sink are set up at the
1526 same time, in which case we want to make sure we don't
1527 interfere with that */
1528 if (!PA_SOURCE_OUTPUT_IS_LINKED(pa_source_output_get_state(so)))
1529 continue;
1530
1531 if (!(name = get_name(so->proplist, "source-input")))
1532 continue;
1533
1534 if ((e = read_entry(u, name))) {
1535 if (e->device_valid && pa_streq(e->device, source->name))
1536 pa_source_output_move_to(so, source, TRUE);
1537
1538 pa_xfree(e);
1539 }
1540
1541 pa_xfree(name);
1542 }
1543
1544 return PA_HOOK_OK;
1545 }
1546
1547 static pa_hook_result_t sink_unlink_hook_callback(pa_core *c, pa_sink *sink, struct userdata *u) {
1548 pa_sink_input *si;
1549 uint32_t idx;
1550
1551 pa_assert(c);
1552 pa_assert(sink);
1553 pa_assert(u);
1554 pa_assert(u->on_rescue && u->restore_device);
1555
1556 /* There's no point in doing anything if the core is shut down anyway */
1557 if (c->state == PA_CORE_SHUTDOWN)
1558 return PA_HOOK_OK;
1559
1560 PA_IDXSET_FOREACH(si, sink->inputs, idx) {
1561 char *name;
1562 struct entry *e;
1563
1564 if (!si->sink)
1565 continue;
1566
1567 if (!(name = get_name(si->proplist, "sink-input")))
1568 continue;
1569
1570 if ((e = read_entry(u, name))) {
1571
1572 if (e->device_valid) {
1573 pa_sink *d;
1574
1575 if ((d = pa_namereg_get(c, e->device, PA_NAMEREG_SINK)) &&
1576 d != sink &&
1577 PA_SINK_IS_LINKED(pa_sink_get_state(d)))
1578 pa_sink_input_move_to(si, d, TRUE);
1579 }
1580
1581 pa_xfree(e);
1582 }
1583
1584 pa_xfree(name);
1585 }
1586
1587 return PA_HOOK_OK;
1588 }
1589
1590 static pa_hook_result_t source_unlink_hook_callback(pa_core *c, pa_source *source, struct userdata *u) {
1591 pa_source_output *so;
1592 uint32_t idx;
1593
1594 pa_assert(c);
1595 pa_assert(source);
1596 pa_assert(u);
1597 pa_assert(u->on_rescue && u->restore_device);
1598
1599 /* There's no point in doing anything if the core is shut down anyway */
1600 if (c->state == PA_CORE_SHUTDOWN)
1601 return PA_HOOK_OK;
1602
1603 PA_IDXSET_FOREACH(so, source->outputs, idx) {
1604 char *name;
1605 struct entry *e;
1606
1607 if (so->direct_on_input)
1608 continue;
1609
1610 if (!so->source)
1611 continue;
1612
1613 if (!(name = get_name(so->proplist, "source-output")))
1614 continue;
1615
1616 if ((e = read_entry(u, name))) {
1617
1618 if (e->device_valid) {
1619 pa_source *d;
1620
1621 if ((d = pa_namereg_get(c, e->device, PA_NAMEREG_SOURCE)) &&
1622 d != source &&
1623 PA_SOURCE_IS_LINKED(pa_source_get_state(d)))
1624 pa_source_output_move_to(so, d, TRUE);
1625 }
1626
1627 pa_xfree(e);
1628 }
1629
1630 pa_xfree(name);
1631 }
1632
1633 return PA_HOOK_OK;
1634 }
1635
1636 #define EXT_VERSION 1
1637
1638 static void apply_entry(struct userdata *u, const char *name, struct entry *e) {
1639 pa_sink_input *si;
1640 pa_source_output *so;
1641 uint32_t idx;
1642
1643 pa_assert(u);
1644 pa_assert(name);
1645 pa_assert(e);
1646
1647 PA_IDXSET_FOREACH(si, u->core->sink_inputs, idx) {
1648 char *n;
1649 pa_sink *s;
1650
1651 if (!(n = get_name(si->proplist, "sink-input")))
1652 continue;
1653
1654 if (!pa_streq(name, n)) {
1655 pa_xfree(n);
1656 continue;
1657 }
1658 pa_xfree(n);
1659
1660 if (u->restore_volume && e->volume_valid) {
1661 pa_cvolume v;
1662
1663 v = e->volume;
1664 pa_log_info("Restoring volume for sink input %s.", name);
1665 pa_cvolume_remap(&v, &e->channel_map, &si->channel_map);
1666 pa_sink_input_set_volume(si, &v, TRUE, FALSE);
1667 }
1668
1669 if (u->restore_muted && e->muted_valid) {
1670 pa_log_info("Restoring mute state for sink input %s.", name);
1671 pa_sink_input_set_mute(si, e->muted, TRUE);
1672 }
1673
1674 if (u->restore_device &&
1675 e->device_valid &&
1676 (s = pa_namereg_get(u->core, e->device, PA_NAMEREG_SINK))) {
1677
1678 pa_log_info("Restoring device for stream %s.", name);
1679 pa_sink_input_move_to(si, s, TRUE);
1680 }
1681 }
1682
1683 PA_IDXSET_FOREACH(so, u->core->source_outputs, idx) {
1684 char *n;
1685 pa_source *s;
1686
1687 if (!(n = get_name(so->proplist, "source-output")))
1688 continue;
1689
1690 if (!pa_streq(name, n)) {
1691 pa_xfree(n);
1692 continue;
1693 }
1694 pa_xfree(n);
1695
1696 if (u->restore_device &&
1697 e->device_valid &&
1698 (s = pa_namereg_get(u->core, e->device, PA_NAMEREG_SOURCE))) {
1699
1700 pa_log_info("Restoring device for stream %s.", name);
1701 pa_source_output_move_to(so, s, TRUE);
1702 }
1703 }
1704 }
1705
1706 #if 0
1707 static void dump_database(struct userdata *u) {
1708 pa_datum key;
1709 pa_bool_t done;
1710
1711 done = !pa_database_first(u->database, &key, NULL);
1712
1713 while (!done) {
1714 pa_datum next_key;
1715 struct entry *e;
1716 char *name;
1717
1718 done = !pa_database_next(u->database, &key, &next_key, NULL);
1719
1720 name = pa_xstrndup(key.data, key.size);
1721 pa_datum_free(&key);
1722
1723 if ((e = read_entry(u, name))) {
1724 char t[256];
1725 pa_log("name=%s", name);
1726 pa_log("device=%s %s", e->device, pa_yes_no(e->device_valid));
1727 pa_log("channel_map=%s", pa_channel_map_snprint(t, sizeof(t), &e->channel_map));
1728 pa_log("volume=%s %s", pa_cvolume_snprint(t, sizeof(t), &e->volume), pa_yes_no(e->volume_valid));
1729 pa_log("mute=%s %s", pa_yes_no(e->muted), pa_yes_no(e->volume_valid));
1730 pa_xfree(e);
1731 }
1732
1733 pa_xfree(name);
1734
1735 key = next_key;
1736 }
1737 }
1738 #endif
1739
1740 static int extension_cb(pa_native_protocol *p, pa_module *m, pa_native_connection *c, uint32_t tag, pa_tagstruct *t) {
1741 struct userdata *u;
1742 uint32_t command;
1743 pa_tagstruct *reply = NULL;
1744
1745 pa_assert(p);
1746 pa_assert(m);
1747 pa_assert(c);
1748 pa_assert(t);
1749
1750 u = m->userdata;
1751
1752 if (pa_tagstruct_getu32(t, &command) < 0)
1753 goto fail;
1754
1755 reply = pa_tagstruct_new(NULL, 0);
1756 pa_tagstruct_putu32(reply, PA_COMMAND_REPLY);
1757 pa_tagstruct_putu32(reply, tag);
1758
1759 switch (command) {
1760 case SUBCOMMAND_TEST: {
1761 if (!pa_tagstruct_eof(t))
1762 goto fail;
1763
1764 pa_tagstruct_putu32(reply, EXT_VERSION);
1765 break;
1766 }
1767
1768 case SUBCOMMAND_READ: {
1769 pa_datum key;
1770 pa_bool_t done;
1771
1772 if (!pa_tagstruct_eof(t))
1773 goto fail;
1774
1775 done = !pa_database_first(u->database, &key, NULL);
1776
1777 while (!done) {
1778 pa_datum next_key;
1779 struct entry *e;
1780 char *name;
1781
1782 done = !pa_database_next(u->database, &key, &next_key, NULL);
1783
1784 name = pa_xstrndup(key.data, key.size);
1785 pa_datum_free(&key);
1786
1787 if ((e = read_entry(u, name))) {
1788 pa_cvolume r;
1789 pa_channel_map cm;
1790
1791 pa_tagstruct_puts(reply, name);
1792 pa_tagstruct_put_channel_map(reply, e->volume_valid ? &e->channel_map : pa_channel_map_init(&cm));
1793 pa_tagstruct_put_cvolume(reply, e->volume_valid ? &e->volume : pa_cvolume_init(&r));
1794 pa_tagstruct_puts(reply, e->device_valid ? e->device : NULL);
1795 pa_tagstruct_put_boolean(reply, e->muted_valid ? e->muted : FALSE);
1796
1797 pa_xfree(e);
1798 }
1799
1800 pa_xfree(name);
1801
1802 key = next_key;
1803 }
1804
1805 break;
1806 }
1807
1808 case SUBCOMMAND_WRITE: {
1809 uint32_t mode;
1810 pa_bool_t apply_immediately = FALSE;
1811
1812 if (pa_tagstruct_getu32(t, &mode) < 0 ||
1813 pa_tagstruct_get_boolean(t, &apply_immediately) < 0)
1814 goto fail;
1815
1816 if (mode != PA_UPDATE_MERGE &&
1817 mode != PA_UPDATE_REPLACE &&
1818 mode != PA_UPDATE_SET)
1819 goto fail;
1820
1821 if (mode == PA_UPDATE_SET) {
1822 #ifdef HAVE_DBUS
1823 struct dbus_entry *de;
1824 void *state = NULL;
1825
1826 PA_HASHMAP_FOREACH(de, u->dbus_entries, state) {
1827 send_entry_removed_signal(de);
1828 dbus_entry_free(pa_hashmap_remove(u->dbus_entries, de->entry_name));
1829 }
1830 #endif
1831 pa_database_clear(u->database);
1832 }
1833
1834 while (!pa_tagstruct_eof(t)) {
1835 const char *name, *device;
1836 pa_bool_t muted;
1837 struct entry entry;
1838 pa_datum key, data;
1839 #ifdef HAVE_DBUS
1840 struct entry *old;
1841 #endif
1842
1843 pa_zero(entry);
1844 entry.version = ENTRY_VERSION;
1845
1846 if (pa_tagstruct_gets(t, &name) < 0 ||
1847 pa_tagstruct_get_channel_map(t, &entry.channel_map) ||
1848 pa_tagstruct_get_cvolume(t, &entry.volume) < 0 ||
1849 pa_tagstruct_gets(t, &device) < 0 ||
1850 pa_tagstruct_get_boolean(t, &muted) < 0)
1851 goto fail;
1852
1853 if (!name || !*name)
1854 goto fail;
1855
1856 entry.volume_valid = entry.volume.channels > 0;
1857
1858 if (entry.volume_valid)
1859 if (!pa_cvolume_compatible_with_channel_map(&entry.volume, &entry.channel_map))
1860 goto fail;
1861
1862 entry.muted = muted;
1863 entry.muted_valid = TRUE;
1864
1865 if (device)
1866 pa_strlcpy(entry.device, device, sizeof(entry.device));
1867 entry.device_valid = !!entry.device[0];
1868
1869 if (entry.device_valid &&
1870 !pa_namereg_is_valid_name(entry.device))
1871 goto fail;
1872
1873 #ifdef HAVE_DBUS
1874 old = read_entry(u, name);
1875 #endif
1876
1877 key.data = (char*) name;
1878 key.size = strlen(name);
1879
1880 data.data = &entry;
1881 data.size = sizeof(entry);
1882
1883 if (pa_database_set(u->database, &key, &data, mode == PA_UPDATE_REPLACE) == 0) {
1884 #ifdef HAVE_DBUS
1885 struct dbus_entry *de;
1886
1887 if (old) {
1888 pa_assert_se((de = pa_hashmap_get(u->dbus_entries, name)));
1889
1890 if ((old->device_valid != entry.device_valid)
1891 || (entry.device_valid && !pa_streq(entry.device, old->device)))
1892 send_device_updated_signal(de, &entry);
1893
1894 if ((old->volume_valid != entry.volume_valid)
1895 || (entry.volume_valid
1896 && (!pa_cvolume_equal(&entry.volume, &old->volume) || !pa_channel_map_equal(&entry.channel_map, &old->channel_map))))
1897 send_volume_updated_signal(de, &entry);
1898
1899 if (!old->muted_valid || (entry.muted != old->muted))
1900 send_mute_updated_signal(de, &entry);
1901
1902 } else {
1903 de = dbus_entry_new(u, name);
1904 pa_assert_se(pa_hashmap_put(u->dbus_entries, de->entry_name, de));
1905 send_new_entry_signal(de);
1906 }
1907 #endif
1908
1909 if (apply_immediately)
1910 apply_entry(u, name, &entry);
1911 }
1912
1913 #ifdef HAVE_DBUS
1914 if (old)
1915 pa_xfree(old);
1916 #endif
1917 }
1918
1919 trigger_save(u);
1920
1921 break;
1922 }
1923
1924 case SUBCOMMAND_DELETE:
1925
1926 while (!pa_tagstruct_eof(t)) {
1927 const char *name;
1928 pa_datum key;
1929 #ifdef HAVE_DBUS
1930 struct dbus_entry *de;
1931 #endif
1932
1933 if (pa_tagstruct_gets(t, &name) < 0)
1934 goto fail;
1935
1936 #ifdef HAVE_DBUS
1937 if ((de = pa_hashmap_get(u->dbus_entries, name))) {
1938 send_entry_removed_signal(de);
1939 dbus_entry_free(pa_hashmap_remove(u->dbus_entries, name));
1940 }
1941 #endif
1942
1943 key.data = (char*) name;
1944 key.size = strlen(name);
1945
1946 pa_database_unset(u->database, &key);
1947 }
1948
1949 trigger_save(u);
1950
1951 break;
1952
1953 case SUBCOMMAND_SUBSCRIBE: {
1954
1955 pa_bool_t enabled;
1956
1957 if (pa_tagstruct_get_boolean(t, &enabled) < 0 ||
1958 !pa_tagstruct_eof(t))
1959 goto fail;
1960
1961 if (enabled)
1962 pa_idxset_put(u->subscribed, c, NULL);
1963 else
1964 pa_idxset_remove_by_data(u->subscribed, c, NULL);
1965
1966 break;
1967 }
1968
1969 default:
1970 goto fail;
1971 }
1972
1973 pa_pstream_send_tagstruct(pa_native_connection_get_pstream(c), reply);
1974 return 0;
1975
1976 fail:
1977
1978 if (reply)
1979 pa_tagstruct_free(reply);
1980
1981 return -1;
1982 }
1983
1984 static pa_hook_result_t connection_unlink_hook_cb(pa_native_protocol *p, pa_native_connection *c, struct userdata *u) {
1985 pa_assert(p);
1986 pa_assert(c);
1987 pa_assert(u);
1988
1989 pa_idxset_remove_by_data(u->subscribed, c, NULL);
1990 return PA_HOOK_OK;
1991 }
1992
1993 int pa__init(pa_module*m) {
1994 pa_modargs *ma = NULL;
1995 struct userdata *u;
1996 char *fname;
1997 pa_sink_input *si;
1998 pa_source_output *so;
1999 uint32_t idx;
2000 pa_bool_t restore_device = TRUE, restore_volume = TRUE, restore_muted = TRUE, on_hotplug = TRUE, on_rescue = TRUE;
2001 #ifdef HAVE_DBUS
2002 pa_datum key;
2003 pa_bool_t done;
2004 #endif
2005
2006 pa_assert(m);
2007
2008 if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
2009 pa_log("Failed to parse module arguments");
2010 goto fail;
2011 }
2012
2013 if (pa_modargs_get_value_boolean(ma, "restore_device", &restore_device) < 0 ||
2014 pa_modargs_get_value_boolean(ma, "restore_volume", &restore_volume) < 0 ||
2015 pa_modargs_get_value_boolean(ma, "restore_muted", &restore_muted) < 0 ||
2016 pa_modargs_get_value_boolean(ma, "on_hotplug", &on_hotplug) < 0 ||
2017 pa_modargs_get_value_boolean(ma, "on_rescue", &on_rescue) < 0) {
2018 pa_log("restore_device=, restore_volume=, restore_muted=, on_hotplug= and on_rescue= expect boolean arguments");
2019 goto fail;
2020 }
2021
2022 if (!restore_muted && !restore_volume && !restore_device)
2023 pa_log_warn("Neither restoring volume, nor restoring muted, nor restoring device enabled!");
2024
2025 m->userdata = u = pa_xnew0(struct userdata, 1);
2026 u->core = m->core;
2027 u->module = m;
2028 u->restore_device = restore_device;
2029 u->restore_volume = restore_volume;
2030 u->restore_muted = restore_muted;
2031 u->on_hotplug = on_hotplug;
2032 u->on_rescue = on_rescue;
2033 u->subscribed = pa_idxset_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
2034
2035 u->protocol = pa_native_protocol_get(m->core);
2036 pa_native_protocol_install_ext(u->protocol, m, extension_cb);
2037
2038 u->connection_unlink_hook_slot = pa_hook_connect(&pa_native_protocol_hooks(u->protocol)[PA_NATIVE_HOOK_CONNECTION_UNLINK], PA_HOOK_NORMAL, (pa_hook_cb_t) connection_unlink_hook_cb, u);
2039
2040 u->subscription = pa_subscription_new(m->core, PA_SUBSCRIPTION_MASK_SINK_INPUT|PA_SUBSCRIPTION_MASK_SOURCE_OUTPUT, subscribe_callback, u);
2041
2042 if (restore_device) {
2043 /* A little bit earlier than module-intended-roles ... */
2044 u->sink_input_new_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_INPUT_NEW], PA_HOOK_EARLY, (pa_hook_cb_t) sink_input_new_hook_callback, u);
2045 u->source_output_new_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_NEW], PA_HOOK_EARLY, (pa_hook_cb_t) source_output_new_hook_callback, u);
2046 }
2047
2048 if (restore_device && on_hotplug) {
2049 /* A little bit earlier than module-intended-roles ... */
2050 u->sink_put_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_PUT], PA_HOOK_LATE, (pa_hook_cb_t) sink_put_hook_callback, u);
2051 u->source_put_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_PUT], PA_HOOK_LATE, (pa_hook_cb_t) source_put_hook_callback, u);
2052 }
2053
2054 if (restore_device && on_rescue) {
2055 /* A little bit earlier than module-intended-roles, module-rescue-streams, ... */
2056 u->sink_unlink_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_UNLINK], PA_HOOK_LATE, (pa_hook_cb_t) sink_unlink_hook_callback, u);
2057 u->source_unlink_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_UNLINK], PA_HOOK_LATE, (pa_hook_cb_t) source_unlink_hook_callback, u);
2058 }
2059
2060 if (restore_volume || restore_muted)
2061 u->sink_input_fixate_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_INPUT_FIXATE], PA_HOOK_EARLY, (pa_hook_cb_t) sink_input_fixate_hook_callback, u);
2062
2063 if (!(fname = pa_state_path("stream-volumes", TRUE)))
2064 goto fail;
2065
2066 if (!(u->database = pa_database_open(fname, TRUE))) {
2067 pa_log("Failed to open volume database '%s': %s", fname, pa_cstrerror(errno));
2068 pa_xfree(fname);
2069 goto fail;
2070 }
2071
2072 pa_log_info("Sucessfully opened database file '%s'.", fname);
2073 pa_xfree(fname);
2074
2075 #ifdef HAVE_DBUS
2076 u->dbus_protocol = pa_dbus_protocol_get(u->core);
2077 u->dbus_entries = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func);
2078
2079 pa_assert_se(pa_dbus_protocol_add_interface(u->dbus_protocol, OBJECT_PATH, &stream_restore_interface_info, u) >= 0);
2080 pa_assert_se(pa_dbus_protocol_register_extension(u->dbus_protocol, INTERFACE_STREAM_RESTORE) >= 0);
2081
2082 /* Create the initial dbus entries. */
2083 done = !pa_database_first(u->database, &key, NULL);
2084 while (!done) {
2085 pa_datum next_key;
2086 char *name;
2087 struct dbus_entry *de;
2088
2089 done = !pa_database_next(u->database, &key, &next_key, NULL);
2090
2091 name = pa_xstrndup(key.data, key.size);
2092 pa_datum_free(&key);
2093
2094 de = dbus_entry_new(u, name);
2095 pa_assert_se(pa_hashmap_put(u->dbus_entries, de->entry_name, de) >= 0);
2096
2097 pa_xfree(name);
2098
2099 key = next_key;
2100 }
2101 #endif
2102
2103 PA_IDXSET_FOREACH(si, m->core->sink_inputs, idx)
2104 subscribe_callback(m->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_NEW, si->index, u);
2105
2106 PA_IDXSET_FOREACH(so, m->core->source_outputs, idx)
2107 subscribe_callback(m->core, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_NEW, so->index, u);
2108
2109 pa_modargs_free(ma);
2110 return 0;
2111
2112 fail:
2113 pa__done(m);
2114
2115 if (ma)
2116 pa_modargs_free(ma);
2117
2118 return -1;
2119 }
2120
2121 #ifdef HAVE_DBUS
2122 static void free_dbus_entry_cb(void *p, void *userdata) {
2123 struct dbus_entry *de = p;
2124
2125 pa_assert(de);
2126
2127 dbus_entry_free(de);
2128 }
2129 #endif
2130
2131 void pa__done(pa_module*m) {
2132 struct userdata* u;
2133
2134 pa_assert(m);
2135
2136 if (!(u = m->userdata))
2137 return;
2138
2139 #ifdef HAVE_DBUS
2140 if (u->dbus_protocol) {
2141 pa_assert(u->dbus_entries);
2142
2143 pa_assert_se(pa_dbus_protocol_unregister_extension(u->dbus_protocol, INTERFACE_STREAM_RESTORE) >= 0);
2144 pa_assert_se(pa_dbus_protocol_remove_interface(u->dbus_protocol, OBJECT_PATH, stream_restore_interface_info.name) >= 0);
2145
2146 pa_hashmap_free(u->dbus_entries, free_dbus_entry_cb, NULL);
2147
2148 pa_dbus_protocol_unref(u->dbus_protocol);
2149 }
2150 #endif
2151
2152 if (u->subscription)
2153 pa_subscription_free(u->subscription);
2154
2155 if (u->sink_input_new_hook_slot)
2156 pa_hook_slot_free(u->sink_input_new_hook_slot);
2157 if (u->sink_input_fixate_hook_slot)
2158 pa_hook_slot_free(u->sink_input_fixate_hook_slot);
2159 if (u->source_output_new_hook_slot)
2160 pa_hook_slot_free(u->source_output_new_hook_slot);
2161
2162 if (u->sink_put_hook_slot)
2163 pa_hook_slot_free(u->sink_put_hook_slot);
2164 if (u->source_put_hook_slot)
2165 pa_hook_slot_free(u->source_put_hook_slot);
2166
2167 if (u->sink_unlink_hook_slot)
2168 pa_hook_slot_free(u->sink_unlink_hook_slot);
2169 if (u->source_unlink_hook_slot)
2170 pa_hook_slot_free(u->source_unlink_hook_slot);
2171
2172 if (u->connection_unlink_hook_slot)
2173 pa_hook_slot_free(u->connection_unlink_hook_slot);
2174
2175 if (u->save_time_event)
2176 u->core->mainloop->time_free(u->save_time_event);
2177
2178 if (u->database)
2179 pa_database_close(u->database);
2180
2181 if (u->protocol) {
2182 pa_native_protocol_remove_ext(u->protocol, m);
2183 pa_native_protocol_unref(u->protocol);
2184 }
2185
2186 if (u->subscribed)
2187 pa_idxset_free(u->subscribed, NULL, NULL);
2188
2189 pa_xfree(u);
2190 }