]> code.delx.au - pulseaudio/blob - src/modules/module-stream-restore.c
Use pa_hashmap_remove_and_free() where appropriate
[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
34 #include <pulse/gccmacro.h>
35 #include <pulse/xmalloc.h>
36 #include <pulse/volume.h>
37 #include <pulse/timeval.h>
38 #include <pulse/rtclock.h>
39
40 #include <pulsecore/core-error.h>
41 #include <pulsecore/module.h>
42 #include <pulsecore/core-util.h>
43 #include <pulsecore/modargs.h>
44 #include <pulsecore/log.h>
45 #include <pulsecore/core-subscribe.h>
46 #include <pulsecore/sink-input.h>
47 #include <pulsecore/source-output.h>
48 #include <pulsecore/namereg.h>
49 #include <pulsecore/protocol-native.h>
50 #include <pulsecore/pstream.h>
51 #include <pulsecore/pstream-util.h>
52 #include <pulsecore/database.h>
53 #include <pulsecore/tagstruct.h>
54 #include <pulsecore/proplist-util.h>
55
56 #ifdef HAVE_DBUS
57 #include <pulsecore/dbus-util.h>
58 #include <pulsecore/protocol-dbus.h>
59 #endif
60
61 #include "module-stream-restore-symdef.h"
62
63 PA_MODULE_AUTHOR("Lennart Poettering");
64 PA_MODULE_DESCRIPTION("Automatically restore the volume/mute/device state of streams");
65 PA_MODULE_VERSION(PACKAGE_VERSION);
66 PA_MODULE_LOAD_ONCE(true);
67 PA_MODULE_USAGE(
68 "restore_device=<Save/restore sinks/sources?> "
69 "restore_volume=<Save/restore volumes?> "
70 "restore_muted=<Save/restore muted states?> "
71 "on_hotplug=<When new device becomes available, recheck streams?> "
72 "on_rescue=<When device becomes unavailable, recheck streams?> "
73 "fallback_table=<filename>");
74
75 #define SAVE_INTERVAL (10 * PA_USEC_PER_SEC)
76 #define IDENTIFICATION_PROPERTY "module-stream-restore.id"
77
78 #define DEFAULT_FALLBACK_FILE PA_DEFAULT_CONFIG_DIR"/stream-restore.table"
79 #define DEFAULT_FALLBACK_FILE_USER "stream-restore.table"
80
81 #define WHITESPACE "\n\r \t"
82
83 static const char* const valid_modargs[] = {
84 "restore_device",
85 "restore_volume",
86 "restore_muted",
87 "on_hotplug",
88 "on_rescue",
89 "fallback_table",
90 NULL
91 };
92
93 struct userdata {
94 pa_core *core;
95 pa_module *module;
96 pa_subscription *subscription;
97 pa_hook_slot
98 *sink_input_new_hook_slot,
99 *sink_input_fixate_hook_slot,
100 *source_output_new_hook_slot,
101 *source_output_fixate_hook_slot,
102 *sink_put_hook_slot,
103 *source_put_hook_slot,
104 *sink_unlink_hook_slot,
105 *source_unlink_hook_slot,
106 *connection_unlink_hook_slot;
107 pa_time_event *save_time_event;
108 pa_database* database;
109
110 bool restore_device:1;
111 bool restore_volume:1;
112 bool restore_muted:1;
113 bool on_hotplug:1;
114 bool on_rescue:1;
115
116 pa_native_protocol *protocol;
117 pa_idxset *subscribed;
118
119 #ifdef HAVE_DBUS
120 pa_dbus_protocol *dbus_protocol;
121 pa_hashmap *dbus_entries;
122 uint32_t next_index; /* For generating object paths for entries. */
123 #endif
124 };
125
126 #define ENTRY_VERSION 1
127
128 struct entry {
129 uint8_t version;
130 bool muted_valid, volume_valid, device_valid, card_valid;
131 bool muted;
132 pa_channel_map channel_map;
133 pa_cvolume volume;
134 char* device;
135 char* card;
136 };
137
138 enum {
139 SUBCOMMAND_TEST,
140 SUBCOMMAND_READ,
141 SUBCOMMAND_WRITE,
142 SUBCOMMAND_DELETE,
143 SUBCOMMAND_SUBSCRIBE,
144 SUBCOMMAND_EVENT
145 };
146
147 static struct entry* entry_new(void);
148 static void entry_free(struct entry *e);
149 static struct entry *entry_read(struct userdata *u, const char *name);
150 static bool entry_write(struct userdata *u, const char *name, const struct entry *e, bool replace);
151 static struct entry* entry_copy(const struct entry *e);
152 static void entry_apply(struct userdata *u, const char *name, struct entry *e);
153 static void trigger_save(struct userdata *u);
154
155 #ifdef HAVE_DBUS
156
157 #define OBJECT_PATH "/org/pulseaudio/stream_restore1"
158 #define ENTRY_OBJECT_NAME "entry"
159 #define INTERFACE_STREAM_RESTORE "org.PulseAudio.Ext.StreamRestore1"
160 #define INTERFACE_ENTRY INTERFACE_STREAM_RESTORE ".RestoreEntry"
161
162 #define DBUS_INTERFACE_REVISION 0
163
164 struct dbus_entry {
165 struct userdata *userdata;
166
167 char *entry_name;
168 uint32_t index;
169 char *object_path;
170 };
171
172 static void handle_get_interface_revision(DBusConnection *conn, DBusMessage *msg, void *userdata);
173 static void handle_get_entries(DBusConnection *conn, DBusMessage *msg, void *userdata);
174
175 static void handle_get_all(DBusConnection *conn, DBusMessage *msg, void *userdata);
176
177 static void handle_add_entry(DBusConnection *conn, DBusMessage *msg, void *userdata);
178 static void handle_get_entry_by_name(DBusConnection *conn, DBusMessage *msg, void *userdata);
179
180 static void handle_entry_get_index(DBusConnection *conn, DBusMessage *msg, void *userdata);
181 static void handle_entry_get_name(DBusConnection *conn, DBusMessage *msg, void *userdata);
182 static void handle_entry_get_device(DBusConnection *conn, DBusMessage *msg, void *userdata);
183 static void handle_entry_set_device(DBusConnection *conn, DBusMessage *msg, DBusMessageIter *iter, void *userdata);
184 static void handle_entry_get_volume(DBusConnection *conn, DBusMessage *msg, void *userdata);
185 static void handle_entry_set_volume(DBusConnection *conn, DBusMessage *msg, DBusMessageIter *iter, void *userdata);
186 static void handle_entry_get_mute(DBusConnection *conn, DBusMessage *msg, void *userdata);
187 static void handle_entry_set_mute(DBusConnection *conn, DBusMessage *msg, DBusMessageIter *iter, void *userdata);
188
189 static void handle_entry_get_all(DBusConnection *conn, DBusMessage *msg, void *userdata);
190
191 static void handle_entry_remove(DBusConnection *conn, DBusMessage *msg, void *userdata);
192
193 enum property_handler_index {
194 PROPERTY_HANDLER_INTERFACE_REVISION,
195 PROPERTY_HANDLER_ENTRIES,
196 PROPERTY_HANDLER_MAX
197 };
198
199 enum entry_property_handler_index {
200 ENTRY_PROPERTY_HANDLER_INDEX,
201 ENTRY_PROPERTY_HANDLER_NAME,
202 ENTRY_PROPERTY_HANDLER_DEVICE,
203 ENTRY_PROPERTY_HANDLER_VOLUME,
204 ENTRY_PROPERTY_HANDLER_MUTE,
205 ENTRY_PROPERTY_HANDLER_MAX
206 };
207
208 static pa_dbus_property_handler property_handlers[PROPERTY_HANDLER_MAX] = {
209 [PROPERTY_HANDLER_INTERFACE_REVISION] = { .property_name = "InterfaceRevision", .type = "u", .get_cb = handle_get_interface_revision, .set_cb = NULL },
210 [PROPERTY_HANDLER_ENTRIES] = { .property_name = "Entries", .type = "ao", .get_cb = handle_get_entries, .set_cb = NULL }
211 };
212
213 static pa_dbus_property_handler entry_property_handlers[ENTRY_PROPERTY_HANDLER_MAX] = {
214 [ENTRY_PROPERTY_HANDLER_INDEX] = { .property_name = "Index", .type = "u", .get_cb = handle_entry_get_index, .set_cb = NULL },
215 [ENTRY_PROPERTY_HANDLER_NAME] = { .property_name = "Name", .type = "s", .get_cb = handle_entry_get_name, .set_cb = NULL },
216 [ENTRY_PROPERTY_HANDLER_DEVICE] = { .property_name = "Device", .type = "s", .get_cb = handle_entry_get_device, .set_cb = handle_entry_set_device },
217 [ENTRY_PROPERTY_HANDLER_VOLUME] = { .property_name = "Volume", .type = "a(uu)", .get_cb = handle_entry_get_volume, .set_cb = handle_entry_set_volume },
218 [ENTRY_PROPERTY_HANDLER_MUTE] = { .property_name = "Mute", .type = "b", .get_cb = handle_entry_get_mute, .set_cb = handle_entry_set_mute }
219 };
220
221 enum method_handler_index {
222 METHOD_HANDLER_ADD_ENTRY,
223 METHOD_HANDLER_GET_ENTRY_BY_NAME,
224 METHOD_HANDLER_MAX
225 };
226
227 enum entry_method_handler_index {
228 ENTRY_METHOD_HANDLER_REMOVE,
229 ENTRY_METHOD_HANDLER_MAX
230 };
231
232 static pa_dbus_arg_info add_entry_args[] = { { "name", "s", "in" },
233 { "device", "s", "in" },
234 { "volume", "a(uu)", "in" },
235 { "mute", "b", "in" },
236 { "apply_immediately", "b", "in" },
237 { "entry", "o", "out" } };
238 static pa_dbus_arg_info get_entry_by_name_args[] = { { "name", "s", "in" }, { "entry", "o", "out" } };
239
240 static pa_dbus_method_handler method_handlers[METHOD_HANDLER_MAX] = {
241 [METHOD_HANDLER_ADD_ENTRY] = {
242 .method_name = "AddEntry",
243 .arguments = add_entry_args,
244 .n_arguments = sizeof(add_entry_args) / sizeof(pa_dbus_arg_info),
245 .receive_cb = handle_add_entry },
246 [METHOD_HANDLER_GET_ENTRY_BY_NAME] = {
247 .method_name = "GetEntryByName",
248 .arguments = get_entry_by_name_args,
249 .n_arguments = sizeof(get_entry_by_name_args) / sizeof(pa_dbus_arg_info),
250 .receive_cb = handle_get_entry_by_name }
251 };
252
253 static pa_dbus_method_handler entry_method_handlers[ENTRY_METHOD_HANDLER_MAX] = {
254 [ENTRY_METHOD_HANDLER_REMOVE] = {
255 .method_name = "Remove",
256 .arguments = NULL,
257 .n_arguments = 0,
258 .receive_cb = handle_entry_remove }
259 };
260
261 enum signal_index {
262 SIGNAL_NEW_ENTRY,
263 SIGNAL_ENTRY_REMOVED,
264 SIGNAL_MAX
265 };
266
267 enum entry_signal_index {
268 ENTRY_SIGNAL_DEVICE_UPDATED,
269 ENTRY_SIGNAL_VOLUME_UPDATED,
270 ENTRY_SIGNAL_MUTE_UPDATED,
271 ENTRY_SIGNAL_MAX
272 };
273
274 static pa_dbus_arg_info new_entry_args[] = { { "entry", "o", NULL } };
275 static pa_dbus_arg_info entry_removed_args[] = { { "entry", "o", NULL } };
276
277 static pa_dbus_arg_info entry_device_updated_args[] = { { "device", "s", NULL } };
278 static pa_dbus_arg_info entry_volume_updated_args[] = { { "volume", "a(uu)", NULL } };
279 static pa_dbus_arg_info entry_mute_updated_args[] = { { "muted", "b", NULL } };
280
281 static pa_dbus_signal_info signals[SIGNAL_MAX] = {
282 [SIGNAL_NEW_ENTRY] = { .name = "NewEntry", .arguments = new_entry_args, .n_arguments = 1 },
283 [SIGNAL_ENTRY_REMOVED] = { .name = "EntryRemoved", .arguments = entry_removed_args, .n_arguments = 1 }
284 };
285
286 static pa_dbus_signal_info entry_signals[ENTRY_SIGNAL_MAX] = {
287 [ENTRY_SIGNAL_DEVICE_UPDATED] = { .name = "DeviceUpdated", .arguments = entry_device_updated_args, .n_arguments = 1 },
288 [ENTRY_SIGNAL_VOLUME_UPDATED] = { .name = "VolumeUpdated", .arguments = entry_volume_updated_args, .n_arguments = 1 },
289 [ENTRY_SIGNAL_MUTE_UPDATED] = { .name = "MuteUpdated", .arguments = entry_mute_updated_args, .n_arguments = 1 }
290 };
291
292 static pa_dbus_interface_info stream_restore_interface_info = {
293 .name = INTERFACE_STREAM_RESTORE,
294 .method_handlers = method_handlers,
295 .n_method_handlers = METHOD_HANDLER_MAX,
296 .property_handlers = property_handlers,
297 .n_property_handlers = PROPERTY_HANDLER_MAX,
298 .get_all_properties_cb = handle_get_all,
299 .signals = signals,
300 .n_signals = SIGNAL_MAX
301 };
302
303 static pa_dbus_interface_info entry_interface_info = {
304 .name = INTERFACE_ENTRY,
305 .method_handlers = entry_method_handlers,
306 .n_method_handlers = ENTRY_METHOD_HANDLER_MAX,
307 .property_handlers = entry_property_handlers,
308 .n_property_handlers = ENTRY_PROPERTY_HANDLER_MAX,
309 .get_all_properties_cb = handle_entry_get_all,
310 .signals = entry_signals,
311 .n_signals = ENTRY_SIGNAL_MAX
312 };
313
314 static struct dbus_entry *dbus_entry_new(struct userdata *u, const char *entry_name) {
315 struct dbus_entry *de;
316
317 pa_assert(u);
318 pa_assert(entry_name);
319 pa_assert(*entry_name);
320
321 de = pa_xnew(struct dbus_entry, 1);
322 de->userdata = u;
323 de->entry_name = pa_xstrdup(entry_name);
324 de->index = u->next_index++;
325 de->object_path = pa_sprintf_malloc("%s/%s%u", OBJECT_PATH, ENTRY_OBJECT_NAME, de->index);
326
327 pa_assert_se(pa_dbus_protocol_add_interface(u->dbus_protocol, de->object_path, &entry_interface_info, de) >= 0);
328
329 return de;
330 }
331
332 static void dbus_entry_free(struct dbus_entry *de) {
333 pa_assert(de);
334
335 pa_assert_se(pa_dbus_protocol_remove_interface(de->userdata->dbus_protocol, de->object_path, entry_interface_info.name) >= 0);
336
337 pa_xfree(de->entry_name);
338 pa_xfree(de->object_path);
339 pa_xfree(de);
340 }
341
342 /* Reads an array [(UInt32, UInt32)] from the iterator. The struct items are
343 * are a channel position and a volume value, respectively. The result is
344 * stored in the map and vol arguments. The iterator must point to a "a(uu)"
345 * element. If the data is invalid, an error reply is sent and a negative
346 * number is returned. In case of a failure we make no guarantees about the
347 * state of map and vol. In case of an empty array the channels field of both
348 * map and vol are set to 0. This function calls dbus_message_iter_next(iter)
349 * before returning. */
350 static int get_volume_arg(DBusConnection *conn, DBusMessage *msg, DBusMessageIter *iter, pa_channel_map *map, pa_cvolume *vol) {
351 DBusMessageIter array_iter;
352 DBusMessageIter struct_iter;
353
354 pa_assert(conn);
355 pa_assert(msg);
356 pa_assert(iter);
357 pa_assert(pa_streq(dbus_message_iter_get_signature(iter), "a(uu)"));
358 pa_assert(map);
359 pa_assert(vol);
360
361 pa_channel_map_init(map);
362 pa_cvolume_init(vol);
363
364 map->channels = 0;
365 vol->channels = 0;
366
367 dbus_message_iter_recurse(iter, &array_iter);
368
369 while (dbus_message_iter_get_arg_type(&array_iter) != DBUS_TYPE_INVALID) {
370 dbus_uint32_t chan_pos;
371 dbus_uint32_t chan_vol;
372
373 dbus_message_iter_recurse(&array_iter, &struct_iter);
374
375 dbus_message_iter_get_basic(&struct_iter, &chan_pos);
376
377 if (chan_pos >= PA_CHANNEL_POSITION_MAX) {
378 pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "Invalid channel position: %u", chan_pos);
379 return -1;
380 }
381
382 pa_assert_se(dbus_message_iter_next(&struct_iter));
383 dbus_message_iter_get_basic(&struct_iter, &chan_vol);
384
385 if (!PA_VOLUME_IS_VALID(chan_vol)) {
386 pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "Invalid volume: %u", chan_vol);
387 return -1;
388 }
389
390 if (map->channels < PA_CHANNELS_MAX) {
391 map->map[map->channels] = chan_pos;
392 vol->values[map->channels] = chan_vol;
393 }
394 ++map->channels;
395 ++vol->channels;
396
397 dbus_message_iter_next(&array_iter);
398 }
399
400 if (map->channels > PA_CHANNELS_MAX) {
401 pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "Too many channels: %u. The maximum is %u.", map->channels, PA_CHANNELS_MAX);
402 return -1;
403 }
404
405 dbus_message_iter_next(iter);
406
407 return 0;
408 }
409
410 static void append_volume(DBusMessageIter *iter, struct entry *e) {
411 DBusMessageIter array_iter;
412 DBusMessageIter struct_iter;
413 unsigned i;
414
415 pa_assert(iter);
416 pa_assert(e);
417
418 pa_assert_se(dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY, "(uu)", &array_iter));
419
420 if (!e->volume_valid) {
421 pa_assert_se(dbus_message_iter_close_container(iter, &array_iter));
422 return;
423 }
424
425 for (i = 0; i < e->channel_map.channels; ++i) {
426 pa_assert_se(dbus_message_iter_open_container(&array_iter, DBUS_TYPE_STRUCT, NULL, &struct_iter));
427
428 pa_assert_se(dbus_message_iter_append_basic(&struct_iter, DBUS_TYPE_UINT32, &e->channel_map.map[i]));
429 pa_assert_se(dbus_message_iter_append_basic(&struct_iter, DBUS_TYPE_UINT32, &e->volume.values[i]));
430
431 pa_assert_se(dbus_message_iter_close_container(&array_iter, &struct_iter));
432 }
433
434 pa_assert_se(dbus_message_iter_close_container(iter, &array_iter));
435 }
436
437 static void append_volume_variant(DBusMessageIter *iter, struct entry *e) {
438 DBusMessageIter variant_iter;
439
440 pa_assert(iter);
441 pa_assert(e);
442
443 pa_assert_se(dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "a(uu)", &variant_iter));
444
445 append_volume(&variant_iter, e);
446
447 pa_assert_se(dbus_message_iter_close_container(iter, &variant_iter));
448 }
449
450 static void send_new_entry_signal(struct dbus_entry *entry) {
451 DBusMessage *signal_msg;
452
453 pa_assert(entry);
454
455 pa_assert_se(signal_msg = dbus_message_new_signal(OBJECT_PATH, INTERFACE_STREAM_RESTORE, signals[SIGNAL_NEW_ENTRY].name));
456 pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &entry->object_path, DBUS_TYPE_INVALID));
457 pa_dbus_protocol_send_signal(entry->userdata->dbus_protocol, signal_msg);
458 dbus_message_unref(signal_msg);
459 }
460
461 static void send_entry_removed_signal(struct dbus_entry *entry) {
462 DBusMessage *signal_msg;
463
464 pa_assert(entry);
465
466 pa_assert_se(signal_msg = dbus_message_new_signal(OBJECT_PATH, INTERFACE_STREAM_RESTORE, signals[SIGNAL_ENTRY_REMOVED].name));
467 pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &entry->object_path, DBUS_TYPE_INVALID));
468 pa_dbus_protocol_send_signal(entry->userdata->dbus_protocol, signal_msg);
469 dbus_message_unref(signal_msg);
470 }
471
472 static void send_device_updated_signal(struct dbus_entry *de, struct entry *e) {
473 DBusMessage *signal_msg;
474 const char *device;
475
476 pa_assert(de);
477 pa_assert(e);
478
479 device = e->device_valid ? e->device : "";
480
481 pa_assert_se(signal_msg = dbus_message_new_signal(de->object_path, INTERFACE_ENTRY, entry_signals[ENTRY_SIGNAL_DEVICE_UPDATED].name));
482 pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_STRING, &device, DBUS_TYPE_INVALID));
483 pa_dbus_protocol_send_signal(de->userdata->dbus_protocol, signal_msg);
484 dbus_message_unref(signal_msg);
485 }
486
487 static void send_volume_updated_signal(struct dbus_entry *de, struct entry *e) {
488 DBusMessage *signal_msg;
489 DBusMessageIter msg_iter;
490
491 pa_assert(de);
492 pa_assert(e);
493
494 pa_assert_se(signal_msg = dbus_message_new_signal(de->object_path, INTERFACE_ENTRY, entry_signals[ENTRY_SIGNAL_VOLUME_UPDATED].name));
495 dbus_message_iter_init_append(signal_msg, &msg_iter);
496 append_volume(&msg_iter, e);
497 pa_dbus_protocol_send_signal(de->userdata->dbus_protocol, signal_msg);
498 dbus_message_unref(signal_msg);
499 }
500
501 static void send_mute_updated_signal(struct dbus_entry *de, struct entry *e) {
502 DBusMessage *signal_msg;
503 dbus_bool_t muted;
504
505 pa_assert(de);
506 pa_assert(e);
507
508 pa_assert(e->muted_valid);
509
510 muted = e->muted;
511
512 pa_assert_se(signal_msg = dbus_message_new_signal(de->object_path, INTERFACE_ENTRY, entry_signals[ENTRY_SIGNAL_MUTE_UPDATED].name));
513 pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_BOOLEAN, &muted, DBUS_TYPE_INVALID));
514 pa_dbus_protocol_send_signal(de->userdata->dbus_protocol, signal_msg);
515 dbus_message_unref(signal_msg);
516 }
517
518 static void handle_get_interface_revision(DBusConnection *conn, DBusMessage *msg, void *userdata) {
519 dbus_uint32_t interface_revision = DBUS_INTERFACE_REVISION;
520
521 pa_assert(conn);
522 pa_assert(msg);
523
524 pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT32, &interface_revision);
525 }
526
527 /* The caller frees the array, but not the strings. */
528 static const char **get_entries(struct userdata *u, unsigned *n) {
529 const char **entries;
530 unsigned i = 0;
531 void *state = NULL;
532 struct dbus_entry *de;
533
534 pa_assert(u);
535 pa_assert(n);
536
537 *n = pa_hashmap_size(u->dbus_entries);
538
539 if (*n == 0)
540 return NULL;
541
542 entries = pa_xnew(const char *, *n);
543
544 PA_HASHMAP_FOREACH(de, u->dbus_entries, state)
545 entries[i++] = de->object_path;
546
547 return entries;
548 }
549
550 static void handle_get_entries(DBusConnection *conn, DBusMessage *msg, void *userdata) {
551 struct userdata *u = userdata;
552 const char **entries;
553 unsigned n;
554
555 pa_assert(conn);
556 pa_assert(msg);
557 pa_assert(u);
558
559 entries = get_entries(u, &n);
560
561 pa_dbus_send_basic_array_variant_reply(conn, msg, DBUS_TYPE_OBJECT_PATH, entries, n);
562
563 pa_xfree(entries);
564 }
565
566 static void handle_get_all(DBusConnection *conn, DBusMessage *msg, void *userdata) {
567 struct userdata *u = userdata;
568 DBusMessage *reply = NULL;
569 DBusMessageIter msg_iter;
570 DBusMessageIter dict_iter;
571 dbus_uint32_t interface_revision;
572 const char **entries;
573 unsigned n_entries;
574
575 pa_assert(conn);
576 pa_assert(msg);
577 pa_assert(u);
578
579 interface_revision = DBUS_INTERFACE_REVISION;
580 entries = get_entries(u, &n_entries);
581
582 pa_assert_se((reply = dbus_message_new_method_return(msg)));
583
584 dbus_message_iter_init_append(reply, &msg_iter);
585 pa_assert_se(dbus_message_iter_open_container(&msg_iter, DBUS_TYPE_ARRAY, "{sv}", &dict_iter));
586
587 pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_INTERFACE_REVISION].property_name, DBUS_TYPE_UINT32, &interface_revision);
588 pa_dbus_append_basic_array_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_ENTRIES].property_name, DBUS_TYPE_OBJECT_PATH, entries, n_entries);
589
590 pa_assert_se(dbus_message_iter_close_container(&msg_iter, &dict_iter));
591
592 pa_assert_se(dbus_connection_send(conn, reply, NULL));
593
594 dbus_message_unref(reply);
595
596 pa_xfree(entries);
597 }
598
599 static void handle_add_entry(DBusConnection *conn, DBusMessage *msg, void *userdata) {
600 struct userdata *u = userdata;
601 DBusMessageIter msg_iter;
602 const char *name = NULL;
603 const char *device = NULL;
604 pa_channel_map map;
605 pa_cvolume vol;
606 dbus_bool_t muted = FALSE;
607 dbus_bool_t apply_immediately = FALSE;
608 struct dbus_entry *dbus_entry = NULL;
609 struct entry *e = NULL;
610
611 pa_assert(conn);
612 pa_assert(msg);
613 pa_assert(u);
614
615 pa_assert_se(dbus_message_iter_init(msg, &msg_iter));
616 dbus_message_iter_get_basic(&msg_iter, &name);
617
618 pa_assert_se(dbus_message_iter_next(&msg_iter));
619 dbus_message_iter_get_basic(&msg_iter, &device);
620
621 pa_assert_se(dbus_message_iter_next(&msg_iter));
622 if (get_volume_arg(conn, msg, &msg_iter, &map, &vol) < 0)
623 return;
624
625 dbus_message_iter_get_basic(&msg_iter, &muted);
626
627 pa_assert_se(dbus_message_iter_next(&msg_iter));
628 dbus_message_iter_get_basic(&msg_iter, &apply_immediately);
629
630 if (!*name) {
631 pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "An empty string was given as the entry name.");
632 return;
633 }
634
635 if ((dbus_entry = pa_hashmap_get(u->dbus_entries, name))) {
636 bool mute_updated = false;
637 bool volume_updated = false;
638 bool device_updated = false;
639
640 pa_assert_se(e = entry_read(u, name));
641 mute_updated = e->muted != muted;
642 e->muted = muted;
643 e->muted_valid = true;
644
645 volume_updated = (e->volume_valid != !!map.channels) || !pa_cvolume_equal(&e->volume, &vol);
646 e->volume = vol;
647 e->channel_map = map;
648 e->volume_valid = !!map.channels;
649
650 device_updated = (e->device_valid != !!device[0]) || !pa_streq(e->device, device);
651 pa_xfree(e->device);
652 e->device = pa_xstrdup(device);
653 e->device_valid = !!device[0];
654
655 if (mute_updated)
656 send_mute_updated_signal(dbus_entry, e);
657 if (volume_updated)
658 send_volume_updated_signal(dbus_entry, e);
659 if (device_updated)
660 send_device_updated_signal(dbus_entry, e);
661
662 } else {
663 dbus_entry = dbus_entry_new(u, name);
664 pa_assert_se(pa_hashmap_put(u->dbus_entries, dbus_entry->entry_name, dbus_entry) == 0);
665
666 e = entry_new();
667 e->muted_valid = true;
668 e->volume_valid = !!map.channels;
669 e->device_valid = !!device[0];
670 e->muted = muted;
671 e->volume = vol;
672 e->channel_map = map;
673 e->device = pa_xstrdup(device);
674
675 send_new_entry_signal(dbus_entry);
676 }
677
678 pa_assert_se(entry_write(u, name, e, true));
679
680 if (apply_immediately)
681 entry_apply(u, name, e);
682
683 trigger_save(u);
684
685 pa_dbus_send_empty_reply(conn, msg);
686
687 entry_free(e);
688 }
689
690 static void handle_get_entry_by_name(DBusConnection *conn, DBusMessage *msg, void *userdata) {
691 struct userdata *u = userdata;
692 const char *name;
693 struct dbus_entry *de;
694
695 pa_assert(conn);
696 pa_assert(msg);
697 pa_assert(u);
698
699 pa_assert_se(dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &name, DBUS_TYPE_INVALID));
700
701 if (!(de = pa_hashmap_get(u->dbus_entries, name))) {
702 pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NOT_FOUND, "No such stream restore entry.");
703 return;
704 }
705
706 pa_dbus_send_basic_value_reply(conn, msg, DBUS_TYPE_OBJECT_PATH, &de->object_path);
707 }
708
709 static void handle_entry_get_index(DBusConnection *conn, DBusMessage *msg, void *userdata) {
710 struct dbus_entry *de = userdata;
711
712 pa_assert(conn);
713 pa_assert(msg);
714 pa_assert(de);
715
716 pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT32, &de->index);
717 }
718
719 static void handle_entry_get_name(DBusConnection *conn, DBusMessage *msg, void *userdata) {
720 struct dbus_entry *de = userdata;
721
722 pa_assert(conn);
723 pa_assert(msg);
724 pa_assert(de);
725
726 pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_STRING, &de->entry_name);
727 }
728
729 static void handle_entry_get_device(DBusConnection *conn, DBusMessage *msg, void *userdata) {
730 struct dbus_entry *de = userdata;
731 struct entry *e;
732 const char *device;
733
734 pa_assert(conn);
735 pa_assert(msg);
736 pa_assert(de);
737
738 pa_assert_se(e = entry_read(de->userdata, de->entry_name));
739
740 device = e->device_valid ? e->device : "";
741
742 pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_STRING, &device);
743
744 entry_free(e);
745 }
746
747 static void handle_entry_set_device(DBusConnection *conn, DBusMessage *msg, DBusMessageIter *iter, void *userdata) {
748 struct dbus_entry *de = userdata;
749 const char *device;
750 struct entry *e;
751 bool updated;
752
753 pa_assert(conn);
754 pa_assert(msg);
755 pa_assert(iter);
756 pa_assert(de);
757
758 dbus_message_iter_get_basic(iter, &device);
759
760 pa_assert_se(e = entry_read(de->userdata, de->entry_name));
761
762 updated = (e->device_valid != !!device[0]) || !pa_streq(e->device, device);
763
764 if (updated) {
765 pa_xfree(e->device);
766 e->device = pa_xstrdup(device);
767 e->device_valid = !!device[0];
768
769 pa_assert_se(entry_write(de->userdata, de->entry_name, e, true));
770
771 entry_apply(de->userdata, de->entry_name, e);
772 send_device_updated_signal(de, e);
773 trigger_save(de->userdata);
774 }
775
776 pa_dbus_send_empty_reply(conn, msg);
777
778 entry_free(e);
779 }
780
781 static void handle_entry_get_volume(DBusConnection *conn, DBusMessage *msg, void *userdata) {
782 struct dbus_entry *de = userdata;
783 DBusMessage *reply;
784 DBusMessageIter msg_iter;
785 struct entry *e;
786
787 pa_assert(conn);
788 pa_assert(msg);
789 pa_assert(de);
790
791 pa_assert_se(e = entry_read(de->userdata, de->entry_name));
792
793 pa_assert_se(reply = dbus_message_new_method_return(msg));
794
795 dbus_message_iter_init_append(reply, &msg_iter);
796 append_volume_variant(&msg_iter, e);
797
798 pa_assert_se(dbus_connection_send(conn, reply, NULL));
799
800 entry_free(e);
801 }
802
803 static void handle_entry_set_volume(DBusConnection *conn, DBusMessage *msg, DBusMessageIter *iter, void *userdata) {
804 struct dbus_entry *de = userdata;
805 pa_channel_map map;
806 pa_cvolume vol;
807 struct entry *e = NULL;
808 bool updated = false;
809
810 pa_assert(conn);
811 pa_assert(msg);
812 pa_assert(iter);
813 pa_assert(de);
814
815 if (get_volume_arg(conn, msg, iter, &map, &vol) < 0)
816 return;
817
818 pa_assert_se(e = entry_read(de->userdata, de->entry_name));
819
820 updated = (e->volume_valid != !!map.channels) || !pa_cvolume_equal(&e->volume, &vol);
821
822 if (updated) {
823 e->volume = vol;
824 e->channel_map = map;
825 e->volume_valid = !!map.channels;
826
827 pa_assert_se(entry_write(de->userdata, de->entry_name, e, true));
828
829 entry_apply(de->userdata, de->entry_name, e);
830 send_volume_updated_signal(de, e);
831 trigger_save(de->userdata);
832 }
833
834 pa_dbus_send_empty_reply(conn, msg);
835
836 entry_free(e);
837 }
838
839 static void handle_entry_get_mute(DBusConnection *conn, DBusMessage *msg, void *userdata) {
840 struct dbus_entry *de = userdata;
841 struct entry *e;
842 dbus_bool_t mute;
843
844 pa_assert(conn);
845 pa_assert(msg);
846 pa_assert(de);
847
848 pa_assert_se(e = entry_read(de->userdata, de->entry_name));
849
850 mute = e->muted_valid ? e->muted : FALSE;
851
852 pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_BOOLEAN, &mute);
853
854 entry_free(e);
855 }
856
857 static void handle_entry_set_mute(DBusConnection *conn, DBusMessage *msg, DBusMessageIter *iter, void *userdata) {
858 struct dbus_entry *de = userdata;
859 dbus_bool_t mute;
860 struct entry *e;
861 bool updated;
862
863 pa_assert(conn);
864 pa_assert(msg);
865 pa_assert(iter);
866 pa_assert(de);
867
868 dbus_message_iter_get_basic(iter, &mute);
869
870 pa_assert_se(e = entry_read(de->userdata, de->entry_name));
871
872 updated = !e->muted_valid || e->muted != mute;
873
874 if (updated) {
875 e->muted = mute;
876 e->muted_valid = true;
877
878 pa_assert_se(entry_write(de->userdata, de->entry_name, e, true));
879
880 entry_apply(de->userdata, de->entry_name, e);
881 send_mute_updated_signal(de, e);
882 trigger_save(de->userdata);
883 }
884
885 pa_dbus_send_empty_reply(conn, msg);
886
887 entry_free(e);
888 }
889
890 static void handle_entry_get_all(DBusConnection *conn, DBusMessage *msg, void *userdata) {
891 struct dbus_entry *de = userdata;
892 struct entry *e;
893 DBusMessage *reply = NULL;
894 DBusMessageIter msg_iter;
895 DBusMessageIter dict_iter;
896 DBusMessageIter dict_entry_iter;
897 const char *device;
898 dbus_bool_t mute;
899
900 pa_assert(conn);
901 pa_assert(msg);
902 pa_assert(de);
903
904 pa_assert_se(e = entry_read(de->userdata, de->entry_name));
905
906 device = e->device_valid ? e->device : "";
907 mute = e->muted_valid ? e->muted : FALSE;
908
909 pa_assert_se((reply = dbus_message_new_method_return(msg)));
910
911 dbus_message_iter_init_append(reply, &msg_iter);
912 pa_assert_se(dbus_message_iter_open_container(&msg_iter, DBUS_TYPE_ARRAY, "{sv}", &dict_iter));
913
914 pa_dbus_append_basic_variant_dict_entry(&dict_iter, entry_property_handlers[ENTRY_PROPERTY_HANDLER_INDEX].property_name, DBUS_TYPE_UINT32, &de->index);
915 pa_dbus_append_basic_variant_dict_entry(&dict_iter, entry_property_handlers[ENTRY_PROPERTY_HANDLER_NAME].property_name, DBUS_TYPE_STRING, &de->entry_name);
916 pa_dbus_append_basic_variant_dict_entry(&dict_iter, entry_property_handlers[ENTRY_PROPERTY_HANDLER_DEVICE].property_name, DBUS_TYPE_STRING, &device);
917
918 pa_assert_se(dbus_message_iter_open_container(&dict_iter, DBUS_TYPE_DICT_ENTRY, NULL, &dict_entry_iter));
919
920 pa_assert_se(dbus_message_iter_append_basic(&dict_entry_iter, DBUS_TYPE_STRING, &entry_property_handlers[ENTRY_PROPERTY_HANDLER_VOLUME].property_name));
921 append_volume_variant(&dict_entry_iter, e);
922
923 pa_assert_se(dbus_message_iter_close_container(&dict_iter, &dict_entry_iter));
924
925 pa_dbus_append_basic_variant_dict_entry(&dict_iter, entry_property_handlers[ENTRY_PROPERTY_HANDLER_MUTE].property_name, DBUS_TYPE_BOOLEAN, &mute);
926
927 pa_assert_se(dbus_message_iter_close_container(&msg_iter, &dict_iter));
928
929 pa_assert_se(dbus_connection_send(conn, reply, NULL));
930
931 dbus_message_unref(reply);
932
933 entry_free(e);
934 }
935
936 static void handle_entry_remove(DBusConnection *conn, DBusMessage *msg, void *userdata) {
937 struct dbus_entry *de = userdata;
938 pa_datum key;
939
940 pa_assert(conn);
941 pa_assert(msg);
942 pa_assert(de);
943
944 key.data = de->entry_name;
945 key.size = strlen(de->entry_name);
946
947 pa_assert_se(pa_database_unset(de->userdata->database, &key) == 0);
948
949 send_entry_removed_signal(de);
950 trigger_save(de->userdata);
951
952 pa_assert_se(pa_hashmap_remove_and_free(de->userdata->dbus_entries, de->entry_name) >= 0);
953
954 pa_dbus_send_empty_reply(conn, msg);
955 }
956
957 #endif /* HAVE_DBUS */
958
959 static void save_time_callback(pa_mainloop_api*a, pa_time_event* e, const struct timeval *t, void *userdata) {
960 struct userdata *u = userdata;
961
962 pa_assert(a);
963 pa_assert(e);
964 pa_assert(u);
965
966 pa_assert(e == u->save_time_event);
967 u->core->mainloop->time_free(u->save_time_event);
968 u->save_time_event = NULL;
969
970 pa_database_sync(u->database);
971 pa_log_info("Synced.");
972 }
973
974 static struct entry* entry_new(void) {
975 struct entry *r = pa_xnew0(struct entry, 1);
976 r->version = ENTRY_VERSION;
977 return r;
978 }
979
980 static void entry_free(struct entry* e) {
981 pa_assert(e);
982
983 pa_xfree(e->device);
984 pa_xfree(e->card);
985 pa_xfree(e);
986 }
987
988 static bool entry_write(struct userdata *u, const char *name, const struct entry *e, bool replace) {
989 pa_tagstruct *t;
990 pa_datum key, data;
991 bool r;
992
993 pa_assert(u);
994 pa_assert(name);
995 pa_assert(e);
996
997 t = pa_tagstruct_new(NULL, 0);
998 pa_tagstruct_putu8(t, e->version);
999 pa_tagstruct_put_boolean(t, e->volume_valid);
1000 pa_tagstruct_put_channel_map(t, &e->channel_map);
1001 pa_tagstruct_put_cvolume(t, &e->volume);
1002 pa_tagstruct_put_boolean(t, e->muted_valid);
1003 pa_tagstruct_put_boolean(t, e->muted);
1004 pa_tagstruct_put_boolean(t, e->device_valid);
1005 pa_tagstruct_puts(t, e->device);
1006 pa_tagstruct_put_boolean(t, e->card_valid);
1007 pa_tagstruct_puts(t, e->card);
1008
1009 key.data = (char *) name;
1010 key.size = strlen(name);
1011
1012 data.data = (void*)pa_tagstruct_data(t, &data.size);
1013
1014 r = (pa_database_set(u->database, &key, &data, replace) == 0);
1015
1016 pa_tagstruct_free(t);
1017
1018 return r;
1019 }
1020
1021 #ifdef ENABLE_LEGACY_DATABASE_ENTRY_FORMAT
1022
1023 #define LEGACY_ENTRY_VERSION 3
1024 static struct entry *legacy_entry_read(struct userdata *u, const char *name) {
1025 struct legacy_entry {
1026 uint8_t version;
1027 bool muted_valid:1, volume_valid:1, device_valid:1, card_valid:1;
1028 bool muted:1;
1029 pa_channel_map channel_map;
1030 pa_cvolume volume;
1031 char device[PA_NAME_MAX];
1032 char card[PA_NAME_MAX];
1033 } PA_GCC_PACKED;
1034
1035 pa_datum key;
1036 pa_datum data;
1037 struct legacy_entry *le;
1038 struct entry *e;
1039
1040 pa_assert(u);
1041 pa_assert(name);
1042
1043 key.data = (char *) name;
1044 key.size = strlen(name);
1045
1046 pa_zero(data);
1047
1048 if (!pa_database_get(u->database, &key, &data))
1049 goto fail;
1050
1051 if (data.size != sizeof(struct legacy_entry)) {
1052 pa_log_debug("Size does not match.");
1053 goto fail;
1054 }
1055
1056 le = (struct legacy_entry *) data.data;
1057
1058 if (le->version != LEGACY_ENTRY_VERSION) {
1059 pa_log_debug("Version mismatch.");
1060 goto fail;
1061 }
1062
1063 if (!memchr(le->device, 0, sizeof(le->device))) {
1064 pa_log_warn("Device has missing NUL byte.");
1065 goto fail;
1066 }
1067
1068 if (!memchr(le->card, 0, sizeof(le->card))) {
1069 pa_log_warn("Card has missing NUL byte.");
1070 goto fail;
1071 }
1072
1073 if (le->device_valid && !pa_namereg_is_valid_name(le->device)) {
1074 pa_log_warn("Invalid device name stored in database for legacy stream");
1075 goto fail;
1076 }
1077
1078 if (le->card_valid && !pa_namereg_is_valid_name(le->card)) {
1079 pa_log_warn("Invalid card name stored in database for legacy stream");
1080 goto fail;
1081 }
1082
1083 if (le->volume_valid && !pa_channel_map_valid(&le->channel_map)) {
1084 pa_log_warn("Invalid channel map stored in database for legacy stream");
1085 goto fail;
1086 }
1087
1088 if (le->volume_valid && (!pa_cvolume_valid(&le->volume) || !pa_cvolume_compatible_with_channel_map(&le->volume, &le->channel_map))) {
1089 pa_log_warn("Invalid volume stored in database for legacy stream");
1090 goto fail;
1091 }
1092
1093 e = entry_new();
1094 e->muted_valid = le->muted_valid;
1095 e->muted = le->muted;
1096 e->volume_valid = le->volume_valid;
1097 e->channel_map = le->channel_map;
1098 e->volume = le->volume;
1099 e->device_valid = le->device_valid;
1100 e->device = pa_xstrdup(le->device);
1101 e->card_valid = le->card_valid;
1102 e->card = pa_xstrdup(le->card);
1103 return e;
1104
1105 fail:
1106 pa_datum_free(&data);
1107
1108 return NULL;
1109 }
1110 #endif
1111
1112 static struct entry *entry_read(struct userdata *u, const char *name) {
1113 pa_datum key, data;
1114 struct entry *e = NULL;
1115 pa_tagstruct *t = NULL;
1116 const char *device, *card;
1117
1118 pa_assert(u);
1119 pa_assert(name);
1120
1121 key.data = (char*) name;
1122 key.size = strlen(name);
1123
1124 pa_zero(data);
1125
1126 if (!pa_database_get(u->database, &key, &data))
1127 goto fail;
1128
1129 t = pa_tagstruct_new(data.data, data.size);
1130 e = entry_new();
1131
1132 if (pa_tagstruct_getu8(t, &e->version) < 0 ||
1133 e->version > ENTRY_VERSION ||
1134 pa_tagstruct_get_boolean(t, &e->volume_valid) < 0 ||
1135 pa_tagstruct_get_channel_map(t, &e->channel_map) < 0 ||
1136 pa_tagstruct_get_cvolume(t, &e->volume) < 0 ||
1137 pa_tagstruct_get_boolean(t, &e->muted_valid) < 0 ||
1138 pa_tagstruct_get_boolean(t, &e->muted) < 0 ||
1139 pa_tagstruct_get_boolean(t, &e->device_valid) < 0 ||
1140 pa_tagstruct_gets(t, &device) < 0 ||
1141 pa_tagstruct_get_boolean(t, &e->card_valid) < 0 ||
1142 pa_tagstruct_gets(t, &card) < 0) {
1143
1144 goto fail;
1145 }
1146
1147 e->device = pa_xstrdup(device);
1148 e->card = pa_xstrdup(card);
1149
1150 if (!pa_tagstruct_eof(t))
1151 goto fail;
1152
1153 if (e->device_valid && !pa_namereg_is_valid_name(e->device)) {
1154 pa_log_warn("Invalid device name stored in database for stream %s", name);
1155 goto fail;
1156 }
1157
1158 if (e->card_valid && !pa_namereg_is_valid_name(e->card)) {
1159 pa_log_warn("Invalid card name stored in database for stream %s", name);
1160 goto fail;
1161 }
1162
1163 if (e->volume_valid && !pa_channel_map_valid(&e->channel_map)) {
1164 pa_log_warn("Invalid channel map stored in database for stream %s", name);
1165 goto fail;
1166 }
1167
1168 if (e->volume_valid && (!pa_cvolume_valid(&e->volume) || !pa_cvolume_compatible_with_channel_map(&e->volume, &e->channel_map))) {
1169 pa_log_warn("Invalid volume stored in database for stream %s", name);
1170 goto fail;
1171 }
1172
1173 pa_tagstruct_free(t);
1174 pa_datum_free(&data);
1175
1176 return e;
1177
1178 fail:
1179 if (e)
1180 entry_free(e);
1181 if (t)
1182 pa_tagstruct_free(t);
1183
1184 pa_datum_free(&data);
1185 return NULL;
1186 }
1187
1188 static struct entry* entry_copy(const struct entry *e) {
1189 struct entry* r;
1190
1191 pa_assert(e);
1192 r = entry_new();
1193 *r = *e;
1194 r->device = pa_xstrdup(e->device);
1195 r->card = pa_xstrdup(e->card);
1196 return r;
1197 }
1198
1199 static void trigger_save(struct userdata *u) {
1200 pa_native_connection *c;
1201 uint32_t idx;
1202
1203 PA_IDXSET_FOREACH(c, u->subscribed, idx) {
1204 pa_tagstruct *t;
1205
1206 t = pa_tagstruct_new(NULL, 0);
1207 pa_tagstruct_putu32(t, PA_COMMAND_EXTENSION);
1208 pa_tagstruct_putu32(t, 0);
1209 pa_tagstruct_putu32(t, u->module->index);
1210 pa_tagstruct_puts(t, u->module->name);
1211 pa_tagstruct_putu32(t, SUBCOMMAND_EVENT);
1212
1213 pa_pstream_send_tagstruct(pa_native_connection_get_pstream(c), t);
1214 }
1215
1216 if (u->save_time_event)
1217 return;
1218
1219 u->save_time_event = pa_core_rttime_new(u->core, pa_rtclock_now() + SAVE_INTERVAL, save_time_callback, u);
1220 }
1221
1222 static bool entries_equal(const struct entry *a, const struct entry *b) {
1223 pa_cvolume t;
1224
1225 pa_assert(a);
1226 pa_assert(b);
1227
1228 if (a->device_valid != b->device_valid ||
1229 (a->device_valid && !pa_streq(a->device, b->device)))
1230 return false;
1231
1232 if (a->card_valid != b->card_valid ||
1233 (a->card_valid && !pa_streq(a->card, b->card)))
1234 return false;
1235
1236 if (a->muted_valid != b->muted_valid ||
1237 (a->muted_valid && (a->muted != b->muted)))
1238 return false;
1239
1240 t = b->volume;
1241 if (a->volume_valid != b->volume_valid ||
1242 (a->volume_valid && !pa_cvolume_equal(pa_cvolume_remap(&t, &b->channel_map, &a->channel_map), &a->volume)))
1243 return false;
1244
1245 return true;
1246 }
1247
1248 static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint32_t idx, void *userdata) {
1249 struct userdata *u = userdata;
1250 struct entry *entry, *old = NULL;
1251 char *name = NULL;
1252
1253 /* These are only used when D-Bus is enabled, but in order to reduce ifdef
1254 * clutter these are defined here unconditionally. */
1255 bool created_new_entry = true;
1256 bool device_updated = false;
1257 bool volume_updated = false;
1258 bool mute_updated = false;
1259
1260 #ifdef HAVE_DBUS
1261 struct dbus_entry *de = NULL;
1262 #endif
1263
1264 pa_assert(c);
1265 pa_assert(u);
1266
1267 if (t != (PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_NEW) &&
1268 t != (PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE) &&
1269 t != (PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_NEW) &&
1270 t != (PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_CHANGE))
1271 return;
1272
1273 if ((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SINK_INPUT) {
1274 pa_sink_input *sink_input;
1275
1276 if (!(sink_input = pa_idxset_get_by_index(c->sink_inputs, idx)))
1277 return;
1278
1279 if (!(name = pa_proplist_get_stream_group(sink_input->proplist, "sink-input", IDENTIFICATION_PROPERTY)))
1280 return;
1281
1282 if ((old = entry_read(u, name))) {
1283 entry = entry_copy(old);
1284 created_new_entry = false;
1285 } else
1286 entry = entry_new();
1287
1288 if (sink_input->save_volume && pa_sink_input_is_volume_readable(sink_input)) {
1289 pa_assert(sink_input->volume_writable);
1290
1291 entry->channel_map = sink_input->channel_map;
1292 pa_sink_input_get_volume(sink_input, &entry->volume, false);
1293 entry->volume_valid = true;
1294
1295 volume_updated = !created_new_entry
1296 && (!old->volume_valid
1297 || !pa_channel_map_equal(&entry->channel_map, &old->channel_map)
1298 || !pa_cvolume_equal(&entry->volume, &old->volume));
1299 }
1300
1301 if (sink_input->save_muted) {
1302 entry->muted = pa_sink_input_get_mute(sink_input);
1303 entry->muted_valid = true;
1304
1305 mute_updated = !created_new_entry && (!old->muted_valid || entry->muted != old->muted);
1306 }
1307
1308 if (sink_input->save_sink) {
1309 pa_xfree(entry->device);
1310 entry->device = pa_xstrdup(sink_input->sink->name);
1311 entry->device_valid = true;
1312
1313 device_updated = !created_new_entry && (!old->device_valid || !pa_streq(entry->device, old->device));
1314 if (sink_input->sink->card) {
1315 pa_xfree(entry->card);
1316 entry->card = pa_xstrdup(sink_input->sink->card->name);
1317 entry->card_valid = true;
1318 }
1319 }
1320
1321 } else {
1322 pa_source_output *source_output;
1323
1324 pa_assert((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT);
1325
1326 if (!(source_output = pa_idxset_get_by_index(c->source_outputs, idx)))
1327 return;
1328
1329 if (!(name = pa_proplist_get_stream_group(source_output->proplist, "source-output", IDENTIFICATION_PROPERTY)))
1330 return;
1331
1332 if ((old = entry_read(u, name))) {
1333 entry = entry_copy(old);
1334 created_new_entry = false;
1335 } else
1336 entry = entry_new();
1337
1338 if (source_output->save_volume && pa_source_output_is_volume_readable(source_output)) {
1339 pa_assert(source_output->volume_writable);
1340
1341 entry->channel_map = source_output->channel_map;
1342 pa_source_output_get_volume(source_output, &entry->volume, false);
1343 entry->volume_valid = true;
1344
1345 volume_updated = !created_new_entry
1346 && (!old->volume_valid
1347 || !pa_channel_map_equal(&entry->channel_map, &old->channel_map)
1348 || !pa_cvolume_equal(&entry->volume, &old->volume));
1349 }
1350
1351 if (source_output->save_muted) {
1352 entry->muted = pa_source_output_get_mute(source_output);
1353 entry->muted_valid = true;
1354
1355 mute_updated = !created_new_entry && (!old->muted_valid || entry->muted != old->muted);
1356 }
1357
1358 if (source_output->save_source) {
1359 pa_xfree(entry->device);
1360 entry->device = pa_xstrdup(source_output->source->name);
1361 entry->device_valid = true;
1362
1363 device_updated = !created_new_entry && (!old->device_valid || !pa_streq(entry->device, old->device));
1364
1365 if (source_output->source->card) {
1366 pa_xfree(entry->card);
1367 entry->card = pa_xstrdup(source_output->source->card->name);
1368 entry->card_valid = true;
1369 }
1370 }
1371 }
1372
1373 pa_assert(entry);
1374
1375 if (old) {
1376
1377 if (entries_equal(old, entry)) {
1378 entry_free(old);
1379 entry_free(entry);
1380 pa_xfree(name);
1381 return;
1382 }
1383
1384 entry_free(old);
1385 }
1386
1387 pa_log_info("Storing volume/mute/device for stream %s.", name);
1388
1389 if (entry_write(u, name, entry, true))
1390 trigger_save(u);
1391
1392 #ifdef HAVE_DBUS
1393 if (created_new_entry) {
1394 de = dbus_entry_new(u, name);
1395 pa_assert_se(pa_hashmap_put(u->dbus_entries, de->entry_name, de) == 0);
1396 send_new_entry_signal(de);
1397 } else {
1398 pa_assert_se(de = pa_hashmap_get(u->dbus_entries, name));
1399
1400 if (device_updated)
1401 send_device_updated_signal(de, entry);
1402 if (volume_updated)
1403 send_volume_updated_signal(de, entry);
1404 if (mute_updated)
1405 send_mute_updated_signal(de, entry);
1406 }
1407 #endif
1408
1409 entry_free(entry);
1410 pa_xfree(name);
1411 }
1412
1413 static pa_hook_result_t sink_input_new_hook_callback(pa_core *c, pa_sink_input_new_data *new_data, struct userdata *u) {
1414 char *name;
1415 struct entry *e;
1416
1417 pa_assert(c);
1418 pa_assert(new_data);
1419 pa_assert(u);
1420 pa_assert(u->restore_device);
1421
1422 if (!(name = pa_proplist_get_stream_group(new_data->proplist, "sink-input", IDENTIFICATION_PROPERTY)))
1423 return PA_HOOK_OK;
1424
1425 if (new_data->sink)
1426 pa_log_debug("Not restoring device for stream %s, because already set to '%s'.", name, new_data->sink->name);
1427 else if ((e = entry_read(u, name))) {
1428 pa_sink *s = NULL;
1429
1430 if (e->device_valid)
1431 s = pa_namereg_get(c, e->device, PA_NAMEREG_SINK);
1432
1433 if (!s && e->card_valid) {
1434 pa_card *card;
1435
1436 if ((card = pa_namereg_get(c, e->card, PA_NAMEREG_CARD)))
1437 s = pa_idxset_first(card->sinks, NULL);
1438 }
1439
1440 /* It might happen that a stream and a sink are set up at the
1441 same time, in which case we want to make sure we don't
1442 interfere with that */
1443 if (s && PA_SINK_IS_LINKED(pa_sink_get_state(s)))
1444 if (pa_sink_input_new_data_set_sink(new_data, s, true))
1445 pa_log_info("Restoring device for stream %s.", name);
1446
1447 entry_free(e);
1448 }
1449
1450 pa_xfree(name);
1451
1452 return PA_HOOK_OK;
1453 }
1454
1455 static pa_hook_result_t sink_input_fixate_hook_callback(pa_core *c, pa_sink_input_new_data *new_data, struct userdata *u) {
1456 char *name;
1457 struct entry *e;
1458
1459 pa_assert(c);
1460 pa_assert(new_data);
1461 pa_assert(u);
1462 pa_assert(u->restore_volume || u->restore_muted);
1463
1464 if (!(name = pa_proplist_get_stream_group(new_data->proplist, "sink-input", IDENTIFICATION_PROPERTY)))
1465 return PA_HOOK_OK;
1466
1467 if ((e = entry_read(u, name))) {
1468
1469 if (u->restore_volume && e->volume_valid) {
1470 if (!new_data->volume_writable)
1471 pa_log_debug("Not restoring volume for sink input %s, because its volume can't be changed.", name);
1472 else if (new_data->volume_is_set)
1473 pa_log_debug("Not restoring volume for sink input %s, because already set.", name);
1474 else {
1475 pa_cvolume v;
1476
1477 pa_log_info("Restoring volume for sink input %s.", name);
1478
1479 v = e->volume;
1480 pa_cvolume_remap(&v, &e->channel_map, &new_data->channel_map);
1481 pa_sink_input_new_data_set_volume(new_data, &v);
1482
1483 new_data->volume_is_absolute = false;
1484 new_data->save_volume = true;
1485 }
1486 }
1487
1488 if (u->restore_muted && e->muted_valid) {
1489
1490 if (!new_data->muted_is_set) {
1491 pa_log_info("Restoring mute state for sink input %s.", name);
1492 pa_sink_input_new_data_set_muted(new_data, e->muted);
1493 new_data->save_muted = true;
1494 } else
1495 pa_log_debug("Not restoring mute state for sink input %s, because already set.", name);
1496 }
1497
1498 entry_free(e);
1499 }
1500
1501 pa_xfree(name);
1502
1503 return PA_HOOK_OK;
1504 }
1505
1506 static pa_hook_result_t source_output_new_hook_callback(pa_core *c, pa_source_output_new_data *new_data, struct userdata *u) {
1507 char *name;
1508 struct entry *e;
1509
1510 pa_assert(c);
1511 pa_assert(new_data);
1512 pa_assert(u);
1513 pa_assert(u->restore_device);
1514
1515 if (new_data->direct_on_input)
1516 return PA_HOOK_OK;
1517
1518 if (!(name = pa_proplist_get_stream_group(new_data->proplist, "source-output", IDENTIFICATION_PROPERTY)))
1519 return PA_HOOK_OK;
1520
1521 if (new_data->source)
1522 pa_log_debug("Not restoring device for stream %s, because already set", name);
1523 else if ((e = entry_read(u, name))) {
1524 pa_source *s = NULL;
1525
1526 if (e->device_valid)
1527 s = pa_namereg_get(c, e->device, PA_NAMEREG_SOURCE);
1528
1529 if (!s && e->card_valid) {
1530 pa_card *card;
1531
1532 if ((card = pa_namereg_get(c, e->card, PA_NAMEREG_CARD)))
1533 s = pa_idxset_first(card->sources, NULL);
1534 }
1535
1536 /* It might happen that a stream and a sink are set up at the
1537 same time, in which case we want to make sure we don't
1538 interfere with that */
1539 if (s && PA_SOURCE_IS_LINKED(pa_source_get_state(s))) {
1540 pa_log_info("Restoring device for stream %s.", name);
1541 pa_source_output_new_data_set_source(new_data, s, true);
1542 }
1543
1544 entry_free(e);
1545 }
1546
1547 pa_xfree(name);
1548
1549 return PA_HOOK_OK;
1550 }
1551
1552 static pa_hook_result_t source_output_fixate_hook_callback(pa_core *c, pa_source_output_new_data *new_data, struct userdata *u) {
1553 char *name;
1554 struct entry *e;
1555
1556 pa_assert(c);
1557 pa_assert(new_data);
1558 pa_assert(u);
1559 pa_assert(u->restore_volume || u->restore_muted);
1560
1561 if (!(name = pa_proplist_get_stream_group(new_data->proplist, "source-output", IDENTIFICATION_PROPERTY)))
1562 return PA_HOOK_OK;
1563
1564 if ((e = entry_read(u, name))) {
1565
1566 if (u->restore_volume && e->volume_valid) {
1567 if (!new_data->volume_writable)
1568 pa_log_debug("Not restoring volume for source output %s, because its volume can't be changed.", name);
1569 else if (new_data->volume_is_set)
1570 pa_log_debug("Not restoring volume for source output %s, because already set.", name);
1571 else {
1572 pa_cvolume v;
1573
1574 pa_log_info("Restoring volume for source output %s.", name);
1575
1576 v = e->volume;
1577 pa_cvolume_remap(&v, &e->channel_map, &new_data->channel_map);
1578 pa_source_output_new_data_set_volume(new_data, &v);
1579
1580 new_data->volume_is_absolute = false;
1581 new_data->save_volume = true;
1582 }
1583 }
1584
1585 if (u->restore_muted && e->muted_valid) {
1586
1587 if (!new_data->muted_is_set) {
1588 pa_log_info("Restoring mute state for source output %s.", name);
1589 pa_source_output_new_data_set_muted(new_data, e->muted);
1590 new_data->save_muted = true;
1591 } else
1592 pa_log_debug("Not restoring mute state for source output %s, because already set.", name);
1593 }
1594
1595 entry_free(e);
1596 }
1597
1598 pa_xfree(name);
1599
1600 return PA_HOOK_OK;
1601 }
1602
1603 static pa_hook_result_t sink_put_hook_callback(pa_core *c, pa_sink *sink, struct userdata *u) {
1604 pa_sink_input *si;
1605 uint32_t idx;
1606
1607 pa_assert(c);
1608 pa_assert(sink);
1609 pa_assert(u);
1610 pa_assert(u->on_hotplug && u->restore_device);
1611
1612 PA_IDXSET_FOREACH(si, c->sink_inputs, idx) {
1613 char *name;
1614 struct entry *e;
1615
1616 if (si->sink == sink)
1617 continue;
1618
1619 if (si->save_sink)
1620 continue;
1621
1622 /* Skip this if it is already in the process of being moved
1623 * anyway */
1624 if (!si->sink)
1625 continue;
1626
1627 /* It might happen that a stream and a sink are set up at the
1628 same time, in which case we want to make sure we don't
1629 interfere with that */
1630 if (!PA_SINK_INPUT_IS_LINKED(pa_sink_input_get_state(si)))
1631 continue;
1632
1633 if (!(name = pa_proplist_get_stream_group(si->proplist, "sink-input", IDENTIFICATION_PROPERTY)))
1634 continue;
1635
1636 if ((e = entry_read(u, name))) {
1637 if (e->device_valid && pa_streq(e->device, sink->name))
1638 pa_sink_input_move_to(si, sink, true);
1639
1640 entry_free(e);
1641 }
1642
1643 pa_xfree(name);
1644 }
1645
1646 return PA_HOOK_OK;
1647 }
1648
1649 static pa_hook_result_t source_put_hook_callback(pa_core *c, pa_source *source, struct userdata *u) {
1650 pa_source_output *so;
1651 uint32_t idx;
1652
1653 pa_assert(c);
1654 pa_assert(source);
1655 pa_assert(u);
1656 pa_assert(u->on_hotplug && u->restore_device);
1657
1658 PA_IDXSET_FOREACH(so, c->source_outputs, idx) {
1659 char *name;
1660 struct entry *e;
1661
1662 if (so->source == source)
1663 continue;
1664
1665 if (so->save_source)
1666 continue;
1667
1668 if (so->direct_on_input)
1669 continue;
1670
1671 /* Skip this if it is already in the process of being moved anyway */
1672 if (!so->source)
1673 continue;
1674
1675 /* It might happen that a stream and a source are set up at the
1676 same time, in which case we want to make sure we don't
1677 interfere with that */
1678 if (!PA_SOURCE_OUTPUT_IS_LINKED(pa_source_output_get_state(so)))
1679 continue;
1680
1681 if (!(name = pa_proplist_get_stream_group(so->proplist, "source-output", IDENTIFICATION_PROPERTY)))
1682 continue;
1683
1684 if ((e = entry_read(u, name))) {
1685 if (e->device_valid && pa_streq(e->device, source->name))
1686 pa_source_output_move_to(so, source, true);
1687
1688 entry_free(e);
1689 }
1690
1691 pa_xfree(name);
1692 }
1693
1694 return PA_HOOK_OK;
1695 }
1696
1697 static pa_hook_result_t sink_unlink_hook_callback(pa_core *c, pa_sink *sink, struct userdata *u) {
1698 pa_sink_input *si;
1699 uint32_t idx;
1700
1701 pa_assert(c);
1702 pa_assert(sink);
1703 pa_assert(u);
1704 pa_assert(u->on_rescue && u->restore_device);
1705
1706 /* There's no point in doing anything if the core is shut down anyway */
1707 if (c->state == PA_CORE_SHUTDOWN)
1708 return PA_HOOK_OK;
1709
1710 PA_IDXSET_FOREACH(si, sink->inputs, idx) {
1711 char *name;
1712 struct entry *e;
1713
1714 if (!si->sink)
1715 continue;
1716
1717 if (!(name = pa_proplist_get_stream_group(si->proplist, "sink-input", IDENTIFICATION_PROPERTY)))
1718 continue;
1719
1720 if ((e = entry_read(u, name))) {
1721
1722 if (e->device_valid) {
1723 pa_sink *d;
1724
1725 if ((d = pa_namereg_get(c, e->device, PA_NAMEREG_SINK)) &&
1726 d != sink &&
1727 PA_SINK_IS_LINKED(pa_sink_get_state(d)))
1728 pa_sink_input_move_to(si, d, true);
1729 }
1730
1731 entry_free(e);
1732 }
1733
1734 pa_xfree(name);
1735 }
1736
1737 return PA_HOOK_OK;
1738 }
1739
1740 static pa_hook_result_t source_unlink_hook_callback(pa_core *c, pa_source *source, struct userdata *u) {
1741 pa_source_output *so;
1742 uint32_t idx;
1743
1744 pa_assert(c);
1745 pa_assert(source);
1746 pa_assert(u);
1747 pa_assert(u->on_rescue && u->restore_device);
1748
1749 /* There's no point in doing anything if the core is shut down anyway */
1750 if (c->state == PA_CORE_SHUTDOWN)
1751 return PA_HOOK_OK;
1752
1753 PA_IDXSET_FOREACH(so, source->outputs, idx) {
1754 char *name;
1755 struct entry *e;
1756
1757 if (so->direct_on_input)
1758 continue;
1759
1760 if (!so->source)
1761 continue;
1762
1763 if (!(name = pa_proplist_get_stream_group(so->proplist, "source-output", IDENTIFICATION_PROPERTY)))
1764 continue;
1765
1766 if ((e = entry_read(u, name))) {
1767
1768 if (e->device_valid) {
1769 pa_source *d;
1770
1771 if ((d = pa_namereg_get(c, e->device, PA_NAMEREG_SOURCE)) &&
1772 d != source &&
1773 PA_SOURCE_IS_LINKED(pa_source_get_state(d)))
1774 pa_source_output_move_to(so, d, true);
1775 }
1776
1777 entry_free(e);
1778 }
1779
1780 pa_xfree(name);
1781 }
1782
1783 return PA_HOOK_OK;
1784 }
1785
1786 static int fill_db(struct userdata *u, const char *filename) {
1787 FILE *f;
1788 int n = 0;
1789 int ret = -1;
1790 char *fn = NULL;
1791
1792 pa_assert(u);
1793
1794 if (filename)
1795 f = fopen(fn = pa_xstrdup(filename), "r");
1796 else
1797 f = pa_open_config_file(DEFAULT_FALLBACK_FILE, DEFAULT_FALLBACK_FILE_USER, NULL, &fn);
1798
1799 if (!f) {
1800 if (filename)
1801 pa_log("Failed to open %s: %s", filename, pa_cstrerror(errno));
1802 else
1803 ret = 0;
1804
1805 goto finish;
1806 }
1807
1808 while (!feof(f)) {
1809 char ln[256];
1810 char *d, *v;
1811 double db;
1812
1813 if (!fgets(ln, sizeof(ln), f))
1814 break;
1815
1816 n++;
1817
1818 pa_strip_nl(ln);
1819
1820 if (!*ln || ln[0] == '#' || ln[0] == ';')
1821 continue;
1822
1823 d = ln+strcspn(ln, WHITESPACE);
1824 v = d+strspn(d, WHITESPACE);
1825
1826 if (!*v) {
1827 pa_log("[%s:%u] failed to parse line - too few words", fn, n);
1828 goto finish;
1829 }
1830
1831 *d = 0;
1832 if (pa_atod(v, &db) >= 0) {
1833 if (db <= 0.0) {
1834 pa_datum key, data;
1835 struct entry e;
1836
1837 pa_zero(e);
1838 e.version = ENTRY_VERSION;
1839 e.volume_valid = true;
1840 pa_cvolume_set(&e.volume, 1, pa_sw_volume_from_dB(db));
1841 pa_channel_map_init_mono(&e.channel_map);
1842
1843 key.data = (void *) ln;
1844 key.size = strlen(ln);
1845
1846 data.data = (void *) &e;
1847 data.size = sizeof(e);
1848
1849 if (pa_database_set(u->database, &key, &data, false) == 0)
1850 pa_log_debug("Setting %s to %0.2f dB.", ln, db);
1851 } else
1852 pa_log_warn("[%s:%u] Positive dB values are not allowed, not setting entry %s.", fn, n, ln);
1853 } else
1854 pa_log_warn("[%s:%u] Couldn't parse '%s' as a double, not setting entry %s.", fn, n, v, ln);
1855 }
1856
1857 trigger_save(u);
1858 ret = 0;
1859
1860 finish:
1861 if (f)
1862 fclose(f);
1863
1864 pa_xfree(fn);
1865
1866 return ret;
1867 }
1868
1869 static void entry_apply(struct userdata *u, const char *name, struct entry *e) {
1870 pa_sink_input *si;
1871 pa_source_output *so;
1872 uint32_t idx;
1873
1874 pa_assert(u);
1875 pa_assert(name);
1876 pa_assert(e);
1877
1878 PA_IDXSET_FOREACH(si, u->core->sink_inputs, idx) {
1879 char *n;
1880 pa_sink *s;
1881
1882 if (!(n = pa_proplist_get_stream_group(si->proplist, "sink-input", IDENTIFICATION_PROPERTY)))
1883 continue;
1884
1885 if (!pa_streq(name, n)) {
1886 pa_xfree(n);
1887 continue;
1888 }
1889 pa_xfree(n);
1890
1891 if (u->restore_volume && e->volume_valid && si->volume_writable) {
1892 pa_cvolume v;
1893
1894 v = e->volume;
1895 pa_log_info("Restoring volume for sink input %s.", name);
1896 pa_cvolume_remap(&v, &e->channel_map, &si->channel_map);
1897 pa_sink_input_set_volume(si, &v, true, false);
1898 }
1899
1900 if (u->restore_muted && e->muted_valid) {
1901 pa_log_info("Restoring mute state for sink input %s.", name);
1902 pa_sink_input_set_mute(si, e->muted, true);
1903 }
1904
1905 if (u->restore_device) {
1906 if (!e->device_valid) {
1907 if (si->save_sink) {
1908 pa_log_info("Ensuring device is not saved for stream %s.", name);
1909 /* If the device is not valid we should make sure the
1910 save flag is cleared as the user may have specifically
1911 removed the sink element from the rule. */
1912 si->save_sink = false;
1913 /* This is cheating a bit. The sink input itself has not changed
1914 but the rules governing its routing have, so we fire this event
1915 such that other routing modules (e.g. module-device-manager)
1916 will pick up the change and reapply their routing */
1917 pa_subscription_post(si->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, si->index);
1918 }
1919 } else if ((s = pa_namereg_get(u->core, e->device, PA_NAMEREG_SINK))) {
1920 pa_log_info("Restoring device for stream %s.", name);
1921 pa_sink_input_move_to(si, s, true);
1922 }
1923 }
1924 }
1925
1926 PA_IDXSET_FOREACH(so, u->core->source_outputs, idx) {
1927 char *n;
1928 pa_source *s;
1929
1930 if (!(n = pa_proplist_get_stream_group(so->proplist, "source-output", IDENTIFICATION_PROPERTY)))
1931 continue;
1932
1933 if (!pa_streq(name, n)) {
1934 pa_xfree(n);
1935 continue;
1936 }
1937 pa_xfree(n);
1938
1939 if (u->restore_volume && e->volume_valid && so->volume_writable) {
1940 pa_cvolume v;
1941
1942 v = e->volume;
1943 pa_log_info("Restoring volume for source output %s.", name);
1944 pa_cvolume_remap(&v, &e->channel_map, &so->channel_map);
1945 pa_source_output_set_volume(so, &v, true, false);
1946 }
1947
1948 if (u->restore_muted && e->muted_valid) {
1949 pa_log_info("Restoring mute state for source output %s.", name);
1950 pa_source_output_set_mute(so, e->muted, true);
1951 }
1952
1953 if (u->restore_device) {
1954 if (!e->device_valid) {
1955 if (so->save_source) {
1956 pa_log_info("Ensuring device is not saved for stream %s.", name);
1957 /* If the device is not valid we should make sure the
1958 save flag is cleared as the user may have specifically
1959 removed the source element from the rule. */
1960 so->save_source = false;
1961 /* This is cheating a bit. The source output itself has not changed
1962 but the rules governing its routing have, so we fire this event
1963 such that other routing modules (e.g. module-device-manager)
1964 will pick up the change and reapply their routing */
1965 pa_subscription_post(so->core, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_CHANGE, so->index);
1966 }
1967 } else if ((s = pa_namereg_get(u->core, e->device, PA_NAMEREG_SOURCE))) {
1968 pa_log_info("Restoring device for stream %s.", name);
1969 pa_source_output_move_to(so, s, true);
1970 }
1971 }
1972 }
1973 }
1974
1975 #ifdef DEBUG_VOLUME
1976 PA_GCC_UNUSED static void stream_restore_dump_database(struct userdata *u) {
1977 pa_datum key;
1978 bool done;
1979
1980 done = !pa_database_first(u->database, &key, NULL);
1981
1982 while (!done) {
1983 pa_datum next_key;
1984 struct entry *e;
1985 char *name;
1986
1987 done = !pa_database_next(u->database, &key, &next_key, NULL);
1988
1989 name = pa_xstrndup(key.data, key.size);
1990 pa_datum_free(&key);
1991
1992 if ((e = entry_read(u, name))) {
1993 char t[256];
1994 pa_log("name=%s", name);
1995 pa_log("device=%s %s", e->device, pa_yes_no(e->device_valid));
1996 pa_log("channel_map=%s", pa_channel_map_snprint(t, sizeof(t), &e->channel_map));
1997 pa_log("volume=%s %s",
1998 pa_cvolume_snprint_verbose(t, sizeof(t), &e->volume, &e->channel_map, true),
1999 pa_yes_no(e->volume_valid));
2000 pa_log("mute=%s %s", pa_yes_no(e->muted), pa_yes_no(e->volume_valid));
2001 entry_free(e);
2002 }
2003
2004 pa_xfree(name);
2005
2006 key = next_key;
2007 }
2008 }
2009 #endif
2010
2011 #define EXT_VERSION 1
2012
2013 static int extension_cb(pa_native_protocol *p, pa_module *m, pa_native_connection *c, uint32_t tag, pa_tagstruct *t) {
2014 struct userdata *u;
2015 uint32_t command;
2016 pa_tagstruct *reply = NULL;
2017
2018 pa_assert(p);
2019 pa_assert(m);
2020 pa_assert(c);
2021 pa_assert(t);
2022
2023 u = m->userdata;
2024
2025 if (pa_tagstruct_getu32(t, &command) < 0)
2026 goto fail;
2027
2028 reply = pa_tagstruct_new(NULL, 0);
2029 pa_tagstruct_putu32(reply, PA_COMMAND_REPLY);
2030 pa_tagstruct_putu32(reply, tag);
2031
2032 switch (command) {
2033 case SUBCOMMAND_TEST: {
2034 if (!pa_tagstruct_eof(t))
2035 goto fail;
2036
2037 pa_tagstruct_putu32(reply, EXT_VERSION);
2038 break;
2039 }
2040
2041 case SUBCOMMAND_READ: {
2042 pa_datum key;
2043 bool done;
2044
2045 if (!pa_tagstruct_eof(t))
2046 goto fail;
2047
2048 done = !pa_database_first(u->database, &key, NULL);
2049
2050 while (!done) {
2051 pa_datum next_key;
2052 struct entry *e;
2053 char *name;
2054
2055 done = !pa_database_next(u->database, &key, &next_key, NULL);
2056
2057 name = pa_xstrndup(key.data, key.size);
2058 pa_datum_free(&key);
2059
2060 if ((e = entry_read(u, name))) {
2061 pa_cvolume r;
2062 pa_channel_map cm;
2063
2064 pa_tagstruct_puts(reply, name);
2065 pa_tagstruct_put_channel_map(reply, e->volume_valid ? &e->channel_map : pa_channel_map_init(&cm));
2066 pa_tagstruct_put_cvolume(reply, e->volume_valid ? &e->volume : pa_cvolume_init(&r));
2067 pa_tagstruct_puts(reply, e->device_valid ? e->device : NULL);
2068 pa_tagstruct_put_boolean(reply, e->muted_valid ? e->muted : false);
2069
2070 entry_free(e);
2071 }
2072
2073 pa_xfree(name);
2074
2075 key = next_key;
2076 }
2077
2078 break;
2079 }
2080
2081 case SUBCOMMAND_WRITE: {
2082 uint32_t mode;
2083 bool apply_immediately = false;
2084
2085 if (pa_tagstruct_getu32(t, &mode) < 0 ||
2086 pa_tagstruct_get_boolean(t, &apply_immediately) < 0)
2087 goto fail;
2088
2089 if (mode != PA_UPDATE_MERGE &&
2090 mode != PA_UPDATE_REPLACE &&
2091 mode != PA_UPDATE_SET)
2092 goto fail;
2093
2094 if (mode == PA_UPDATE_SET) {
2095 #ifdef HAVE_DBUS
2096 struct dbus_entry *de;
2097 void *state = NULL;
2098
2099 PA_HASHMAP_FOREACH(de, u->dbus_entries, state) {
2100 send_entry_removed_signal(de);
2101 pa_hashmap_remove_and_free(u->dbus_entries, de->entry_name);
2102 }
2103 #endif
2104 pa_database_clear(u->database);
2105 }
2106
2107 while (!pa_tagstruct_eof(t)) {
2108 const char *name, *device;
2109 bool muted;
2110 struct entry *entry;
2111 #ifdef HAVE_DBUS
2112 struct entry *old;
2113 #endif
2114
2115 entry = entry_new();
2116
2117 if (pa_tagstruct_gets(t, &name) < 0 ||
2118 pa_tagstruct_get_channel_map(t, &entry->channel_map) ||
2119 pa_tagstruct_get_cvolume(t, &entry->volume) < 0 ||
2120 pa_tagstruct_gets(t, &device) < 0 ||
2121 pa_tagstruct_get_boolean(t, &muted) < 0) {
2122 entry_free(entry);
2123 goto fail;
2124 }
2125
2126 if (!name || !*name) {
2127 entry_free(entry);
2128 goto fail;
2129 }
2130
2131 entry->volume_valid = entry->volume.channels > 0;
2132
2133 if (entry->volume_valid)
2134 if (!pa_cvolume_compatible_with_channel_map(&entry->volume, &entry->channel_map)) {
2135 entry_free(entry);
2136 goto fail;
2137 }
2138
2139 entry->muted = muted;
2140 entry->muted_valid = true;
2141
2142 entry->device = pa_xstrdup(device);
2143 entry->device_valid = device && !!entry->device[0];
2144
2145 if (entry->device_valid && !pa_namereg_is_valid_name(entry->device)) {
2146 entry_free(entry);
2147 goto fail;
2148 }
2149
2150 #ifdef HAVE_DBUS
2151 old = entry_read(u, name);
2152 #endif
2153
2154 pa_log_debug("Client %s changes entry %s.",
2155 pa_strnull(pa_proplist_gets(pa_native_connection_get_client(c)->proplist, PA_PROP_APPLICATION_PROCESS_BINARY)),
2156 name);
2157
2158 if (entry_write(u, name, entry, mode == PA_UPDATE_REPLACE)) {
2159 #ifdef HAVE_DBUS
2160 struct dbus_entry *de;
2161
2162 if (old) {
2163 pa_assert_se((de = pa_hashmap_get(u->dbus_entries, name)));
2164
2165 if ((old->device_valid != entry->device_valid)
2166 || (entry->device_valid && !pa_streq(entry->device, old->device)))
2167 send_device_updated_signal(de, entry);
2168
2169 if ((old->volume_valid != entry->volume_valid)
2170 || (entry->volume_valid && (!pa_cvolume_equal(&entry->volume, &old->volume)
2171 || !pa_channel_map_equal(&entry->channel_map, &old->channel_map))))
2172 send_volume_updated_signal(de, entry);
2173
2174 if (!old->muted_valid || (entry->muted != old->muted))
2175 send_mute_updated_signal(de, entry);
2176
2177 } else {
2178 de = dbus_entry_new(u, name);
2179 pa_assert_se(pa_hashmap_put(u->dbus_entries, de->entry_name, de) == 0);
2180 send_new_entry_signal(de);
2181 }
2182 #endif
2183
2184 if (apply_immediately)
2185 entry_apply(u, name, entry);
2186 }
2187
2188 #ifdef HAVE_DBUS
2189 if (old)
2190 entry_free(old);
2191 #endif
2192 entry_free(entry);
2193 }
2194
2195 trigger_save(u);
2196
2197 break;
2198 }
2199
2200 case SUBCOMMAND_DELETE:
2201
2202 while (!pa_tagstruct_eof(t)) {
2203 const char *name;
2204 pa_datum key;
2205 #ifdef HAVE_DBUS
2206 struct dbus_entry *de;
2207 #endif
2208
2209 if (pa_tagstruct_gets(t, &name) < 0)
2210 goto fail;
2211
2212 #ifdef HAVE_DBUS
2213 if ((de = pa_hashmap_get(u->dbus_entries, name))) {
2214 send_entry_removed_signal(de);
2215 pa_hashmap_remove_and_free(u->dbus_entries, name);
2216 }
2217 #endif
2218
2219 key.data = (char*) name;
2220 key.size = strlen(name);
2221
2222 pa_database_unset(u->database, &key);
2223 }
2224
2225 trigger_save(u);
2226
2227 break;
2228
2229 case SUBCOMMAND_SUBSCRIBE: {
2230
2231 bool enabled;
2232
2233 if (pa_tagstruct_get_boolean(t, &enabled) < 0 ||
2234 !pa_tagstruct_eof(t))
2235 goto fail;
2236
2237 if (enabled)
2238 pa_idxset_put(u->subscribed, c, NULL);
2239 else
2240 pa_idxset_remove_by_data(u->subscribed, c, NULL);
2241
2242 break;
2243 }
2244
2245 default:
2246 goto fail;
2247 }
2248
2249 pa_pstream_send_tagstruct(pa_native_connection_get_pstream(c), reply);
2250 return 0;
2251
2252 fail:
2253
2254 if (reply)
2255 pa_tagstruct_free(reply);
2256
2257 return -1;
2258 }
2259
2260 static pa_hook_result_t connection_unlink_hook_cb(pa_native_protocol *p, pa_native_connection *c, struct userdata *u) {
2261 pa_assert(p);
2262 pa_assert(c);
2263 pa_assert(u);
2264
2265 pa_idxset_remove_by_data(u->subscribed, c, NULL);
2266 return PA_HOOK_OK;
2267 }
2268
2269 static void clean_up_db(struct userdata *u) {
2270 struct clean_up_item {
2271 PA_LLIST_FIELDS(struct clean_up_item);
2272 char *entry_name;
2273 struct entry *entry;
2274 };
2275
2276 PA_LLIST_HEAD(struct clean_up_item, to_be_removed);
2277 #ifdef ENABLE_LEGACY_DATABASE_ENTRY_FORMAT
2278 PA_LLIST_HEAD(struct clean_up_item, to_be_converted);
2279 #endif
2280 bool done = false;
2281 pa_datum key;
2282 struct clean_up_item *item = NULL;
2283 struct clean_up_item *next = NULL;
2284
2285 pa_assert(u);
2286
2287 /* It would be convenient to remove or replace the entries in the database
2288 * in the same loop that iterates through the database, but modifying the
2289 * database is not supported while iterating through it. That's why we
2290 * collect the entries that need to be removed or replaced to these
2291 * lists. */
2292 PA_LLIST_HEAD_INIT(struct clean_up_item, to_be_removed);
2293 #ifdef ENABLE_LEGACY_DATABASE_ENTRY_FORMAT
2294 PA_LLIST_HEAD_INIT(struct clean_up_item, to_be_converted);
2295 #endif
2296
2297 done = !pa_database_first(u->database, &key, NULL);
2298 while (!done) {
2299 pa_datum next_key;
2300 char *entry_name = NULL;
2301 struct entry *e = NULL;
2302
2303 entry_name = pa_xstrndup(key.data, key.size);
2304
2305 /* Use entry_read() to check whether this entry is valid. */
2306 if (!(e = entry_read(u, entry_name))) {
2307 item = pa_xnew0(struct clean_up_item, 1);
2308 PA_LLIST_INIT(struct clean_up_item, item);
2309 item->entry_name = entry_name;
2310
2311 #ifdef ENABLE_LEGACY_DATABASE_ENTRY_FORMAT
2312 /* entry_read() failed, but what about legacy_entry_read()? */
2313 if (!(e = legacy_entry_read(u, entry_name)))
2314 /* Not a legacy entry either, let's remove this. */
2315 PA_LLIST_PREPEND(struct clean_up_item, to_be_removed, item);
2316 else {
2317 /* Yay, it's valid after all! Now let's convert the entry to the current format. */
2318 item->entry = e;
2319 PA_LLIST_PREPEND(struct clean_up_item, to_be_converted, item);
2320 }
2321 #else
2322 /* Invalid entry, let's remove this. */
2323 PA_LLIST_PREPEND(struct clean_up_item, to_be_removed, item);
2324 #endif
2325 } else {
2326 pa_xfree(entry_name);
2327 entry_free(e);
2328 }
2329
2330 done = !pa_database_next(u->database, &key, &next_key, NULL);
2331 pa_datum_free(&key);
2332 key = next_key;
2333 }
2334
2335 PA_LLIST_FOREACH_SAFE(item, next, to_be_removed) {
2336 key.data = item->entry_name;
2337 key.size = strlen(item->entry_name);
2338
2339 pa_log_debug("Removing an invalid entry: %s", item->entry_name);
2340
2341 pa_assert_se(pa_database_unset(u->database, &key) >= 0);
2342 trigger_save(u);
2343
2344 PA_LLIST_REMOVE(struct clean_up_item, to_be_removed, item);
2345 pa_xfree(item->entry_name);
2346 pa_xfree(item);
2347 }
2348
2349 #ifdef ENABLE_LEGACY_DATABASE_ENTRY_FORMAT
2350 PA_LLIST_FOREACH_SAFE(item, next, to_be_converted) {
2351 pa_log_debug("Upgrading a legacy entry to the current format: %s", item->entry_name);
2352
2353 pa_assert_se(entry_write(u, item->entry_name, item->entry, true) >= 0);
2354 trigger_save(u);
2355
2356 PA_LLIST_REMOVE(struct clean_up_item, to_be_converted, item);
2357 pa_xfree(item->entry_name);
2358 entry_free(item->entry);
2359 pa_xfree(item);
2360 }
2361 #endif
2362 }
2363
2364 int pa__init(pa_module*m) {
2365 pa_modargs *ma = NULL;
2366 struct userdata *u;
2367 char *fname;
2368 pa_sink_input *si;
2369 pa_source_output *so;
2370 uint32_t idx;
2371 bool restore_device = true, restore_volume = true, restore_muted = true, on_hotplug = true, on_rescue = true;
2372 #ifdef HAVE_DBUS
2373 pa_datum key;
2374 bool done;
2375 #endif
2376
2377 pa_assert(m);
2378
2379 if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
2380 pa_log("Failed to parse module arguments");
2381 goto fail;
2382 }
2383
2384 if (pa_modargs_get_value_boolean(ma, "restore_device", &restore_device) < 0 ||
2385 pa_modargs_get_value_boolean(ma, "restore_volume", &restore_volume) < 0 ||
2386 pa_modargs_get_value_boolean(ma, "restore_muted", &restore_muted) < 0 ||
2387 pa_modargs_get_value_boolean(ma, "on_hotplug", &on_hotplug) < 0 ||
2388 pa_modargs_get_value_boolean(ma, "on_rescue", &on_rescue) < 0) {
2389 pa_log("restore_device=, restore_volume=, restore_muted=, on_hotplug= and on_rescue= expect boolean arguments");
2390 goto fail;
2391 }
2392
2393 if (!restore_muted && !restore_volume && !restore_device)
2394 pa_log_warn("Neither restoring volume, nor restoring muted, nor restoring device enabled!");
2395
2396 m->userdata = u = pa_xnew0(struct userdata, 1);
2397 u->core = m->core;
2398 u->module = m;
2399 u->restore_device = restore_device;
2400 u->restore_volume = restore_volume;
2401 u->restore_muted = restore_muted;
2402 u->on_hotplug = on_hotplug;
2403 u->on_rescue = on_rescue;
2404 u->subscribed = pa_idxset_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
2405
2406 u->protocol = pa_native_protocol_get(m->core);
2407 pa_native_protocol_install_ext(u->protocol, m, extension_cb);
2408
2409 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);
2410
2411 u->subscription = pa_subscription_new(m->core, PA_SUBSCRIPTION_MASK_SINK_INPUT|PA_SUBSCRIPTION_MASK_SOURCE_OUTPUT, subscribe_callback, u);
2412
2413 if (restore_device) {
2414 /* A little bit earlier than module-intended-roles ... */
2415 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);
2416 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);
2417 }
2418
2419 if (restore_device && on_hotplug) {
2420 /* A little bit earlier than module-intended-roles ... */
2421 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);
2422 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);
2423 }
2424
2425 if (restore_device && on_rescue) {
2426 /* A little bit earlier than module-intended-roles, module-rescue-streams, ... */
2427 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);
2428 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);
2429 }
2430
2431 if (restore_volume || restore_muted) {
2432 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);
2433 u->source_output_fixate_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_FIXATE], PA_HOOK_EARLY, (pa_hook_cb_t) source_output_fixate_hook_callback, u);
2434 }
2435
2436 if (!(fname = pa_state_path("stream-volumes", true)))
2437 goto fail;
2438
2439 if (!(u->database = pa_database_open(fname, true))) {
2440 pa_log("Failed to open volume database '%s': %s", fname, pa_cstrerror(errno));
2441 pa_xfree(fname);
2442 goto fail;
2443 }
2444
2445 pa_log_info("Successfully opened database file '%s'.", fname);
2446 pa_xfree(fname);
2447
2448 clean_up_db(u);
2449
2450 if (fill_db(u, pa_modargs_get_value(ma, "fallback_table", NULL)) < 0)
2451 goto fail;
2452
2453 #ifdef HAVE_DBUS
2454 u->dbus_protocol = pa_dbus_protocol_get(u->core);
2455 u->dbus_entries = pa_hashmap_new_full(pa_idxset_string_hash_func, pa_idxset_string_compare_func, NULL, (pa_free_cb_t) dbus_entry_free);
2456
2457 pa_assert_se(pa_dbus_protocol_add_interface(u->dbus_protocol, OBJECT_PATH, &stream_restore_interface_info, u) >= 0);
2458 pa_assert_se(pa_dbus_protocol_register_extension(u->dbus_protocol, INTERFACE_STREAM_RESTORE) >= 0);
2459
2460 /* Create the initial dbus entries. */
2461 done = !pa_database_first(u->database, &key, NULL);
2462 while (!done) {
2463 pa_datum next_key;
2464 char *name;
2465 struct dbus_entry *de;
2466
2467 name = pa_xstrndup(key.data, key.size);
2468 de = dbus_entry_new(u, name);
2469 pa_assert_se(pa_hashmap_put(u->dbus_entries, de->entry_name, de) == 0);
2470 pa_xfree(name);
2471
2472 done = !pa_database_next(u->database, &key, &next_key, NULL);
2473 pa_datum_free(&key);
2474 key = next_key;
2475 }
2476 #endif
2477
2478 PA_IDXSET_FOREACH(si, m->core->sink_inputs, idx)
2479 subscribe_callback(m->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_NEW, si->index, u);
2480
2481 PA_IDXSET_FOREACH(so, m->core->source_outputs, idx)
2482 subscribe_callback(m->core, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_NEW, so->index, u);
2483
2484 pa_modargs_free(ma);
2485 return 0;
2486
2487 fail:
2488 pa__done(m);
2489
2490 if (ma)
2491 pa_modargs_free(ma);
2492
2493 return -1;
2494 }
2495
2496 void pa__done(pa_module*m) {
2497 struct userdata* u;
2498
2499 pa_assert(m);
2500
2501 if (!(u = m->userdata))
2502 return;
2503
2504 #ifdef HAVE_DBUS
2505 if (u->dbus_protocol) {
2506 pa_assert(u->dbus_entries);
2507
2508 pa_assert_se(pa_dbus_protocol_unregister_extension(u->dbus_protocol, INTERFACE_STREAM_RESTORE) >= 0);
2509 pa_assert_se(pa_dbus_protocol_remove_interface(u->dbus_protocol, OBJECT_PATH, stream_restore_interface_info.name) >= 0);
2510
2511 pa_hashmap_free(u->dbus_entries);
2512
2513 pa_dbus_protocol_unref(u->dbus_protocol);
2514 }
2515 #endif
2516
2517 if (u->subscription)
2518 pa_subscription_free(u->subscription);
2519
2520 if (u->sink_input_new_hook_slot)
2521 pa_hook_slot_free(u->sink_input_new_hook_slot);
2522 if (u->sink_input_fixate_hook_slot)
2523 pa_hook_slot_free(u->sink_input_fixate_hook_slot);
2524 if (u->source_output_new_hook_slot)
2525 pa_hook_slot_free(u->source_output_new_hook_slot);
2526 if (u->source_output_fixate_hook_slot)
2527 pa_hook_slot_free(u->source_output_fixate_hook_slot);
2528
2529 if (u->sink_put_hook_slot)
2530 pa_hook_slot_free(u->sink_put_hook_slot);
2531 if (u->source_put_hook_slot)
2532 pa_hook_slot_free(u->source_put_hook_slot);
2533
2534 if (u->sink_unlink_hook_slot)
2535 pa_hook_slot_free(u->sink_unlink_hook_slot);
2536 if (u->source_unlink_hook_slot)
2537 pa_hook_slot_free(u->source_unlink_hook_slot);
2538
2539 if (u->connection_unlink_hook_slot)
2540 pa_hook_slot_free(u->connection_unlink_hook_slot);
2541
2542 if (u->save_time_event)
2543 u->core->mainloop->time_free(u->save_time_event);
2544
2545 if (u->database)
2546 pa_database_close(u->database);
2547
2548 if (u->protocol) {
2549 pa_native_protocol_remove_ext(u->protocol, m);
2550 pa_native_protocol_unref(u->protocol);
2551 }
2552
2553 if (u->subscribed)
2554 pa_idxset_free(u->subscribed, NULL);
2555
2556 pa_xfree(u);
2557 }