47c78d41a00d2aeb3500b0ff031c1d4a1bf3d044
[platform/upstream/pulseaudio.git] / src / modules / module-device-manager.c
1 /***
2   This file is part of PulseAudio.
3
4   Copyright 2006-2008 Lennart Poettering
5   Copyright 2009 Colin Guthrie
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/timeval.h>
37 #include <pulse/rtclock.h>
38
39 #include <pulsecore/core-error.h>
40 #include <pulsecore/module.h>
41 #include <pulsecore/core-util.h>
42 #include <pulsecore/modargs.h>
43 #include <pulsecore/log.h>
44 #include <pulsecore/core-subscribe.h>
45 #include <pulsecore/sink-input.h>
46 #include <pulsecore/source-output.h>
47 #include <pulsecore/namereg.h>
48 #include <pulsecore/protocol-native.h>
49 #include <pulsecore/pstream.h>
50 #include <pulsecore/pstream-util.h>
51 #include <pulsecore/database.h>
52 #include <pulsecore/tagstruct.h>
53
54 #include "module-device-manager-symdef.h"
55
56 PA_MODULE_AUTHOR("Colin Guthrie");
57 PA_MODULE_DESCRIPTION("Keep track of devices (and their descriptions) both past and present and prioritise by role");
58 PA_MODULE_VERSION(PACKAGE_VERSION);
59 PA_MODULE_LOAD_ONCE(TRUE);
60 PA_MODULE_USAGE(
61     "do_routing=<Automatically route streams based on a priority list (unique per-role)?> "
62     "on_hotplug=<When new device becomes available, recheck streams?> "
63     "on_rescue=<When device becomes unavailable, recheck streams?>");
64
65 #define SAVE_INTERVAL (10 * PA_USEC_PER_SEC)
66 #define DUMP_DATABASE
67
68 static const char* const valid_modargs[] = {
69     "do_routing",
70     "on_hotplug",
71     "on_rescue",
72     NULL
73 };
74
75 #define NUM_ROLES 9
76 enum {
77     ROLE_NONE,
78     ROLE_VIDEO,
79     ROLE_MUSIC,
80     ROLE_GAME,
81     ROLE_EVENT,
82     ROLE_PHONE,
83     ROLE_ANIMATION,
84     ROLE_PRODUCTION,
85     ROLE_A11Y,
86     ROLE_MAX
87 };
88
89 typedef uint32_t role_indexes_t[NUM_ROLES];
90
91 static const char* role_names[NUM_ROLES] = {
92     "none",
93     "video",
94     "music",
95     "game",
96     "event",
97     "phone",
98     "animation",
99     "production",
100     "a11y",
101 };
102
103 struct userdata {
104     pa_core *core;
105     pa_module *module;
106     pa_subscription *subscription;
107     pa_hook_slot
108         *sink_new_hook_slot,
109         *source_new_hook_slot,
110         *sink_input_new_hook_slot,
111         *source_output_new_hook_slot,
112         *sink_put_hook_slot,
113         *source_put_hook_slot,
114         *sink_unlink_hook_slot,
115         *source_unlink_hook_slot,
116         *connection_unlink_hook_slot;
117     pa_time_event *save_time_event;
118     pa_database *database;
119
120     pa_native_protocol *protocol;
121     pa_idxset *subscribed;
122
123     pa_bool_t on_hotplug;
124     pa_bool_t on_rescue;
125     pa_bool_t do_routing;
126
127     role_indexes_t preferred_sinks;
128     role_indexes_t preferred_sources;
129 };
130
131 #define ENTRY_VERSION 1
132
133 struct entry {
134     uint8_t version;
135     char *description;
136     pa_bool_t user_set_description;
137     char *icon;
138     role_indexes_t priority;
139 };
140
141 enum {
142     SUBCOMMAND_TEST,
143     SUBCOMMAND_READ,
144     SUBCOMMAND_RENAME,
145     SUBCOMMAND_DELETE,
146     SUBCOMMAND_ROLE_DEVICE_PRIORITY_ROUTING,
147     SUBCOMMAND_REORDER,
148     SUBCOMMAND_SUBSCRIBE,
149     SUBCOMMAND_EVENT
150 };
151
152 /* Forward declarations */
153 #ifdef DUMP_DATABASE
154 static void dump_database(struct userdata *);
155 #endif
156 static void notify_subscribers(struct userdata *);
157
158 static void save_time_callback(pa_mainloop_api*a, pa_time_event* e, const struct timeval *t, void *userdata) {
159     struct userdata *u = userdata;
160
161     pa_assert(a);
162     pa_assert(e);
163     pa_assert(u);
164
165     pa_assert(e == u->save_time_event);
166     u->core->mainloop->time_free(u->save_time_event);
167     u->save_time_event = NULL;
168
169     pa_database_sync(u->database);
170     pa_log_info("Synced.");
171
172 #ifdef DUMP_DATABASE
173     dump_database(u);
174 #endif
175 }
176
177 static void trigger_save(struct userdata *u) {
178
179     pa_assert(u);
180
181     notify_subscribers(u);
182
183     if (u->save_time_event)
184         return;
185
186     u->save_time_event = pa_core_rttime_new(u->core, pa_rtclock_now() + SAVE_INTERVAL, save_time_callback, u);
187 }
188
189 static struct entry* entry_new(void) {
190     struct entry *r = pa_xnew0(struct entry, 1);
191     r->version = ENTRY_VERSION;
192     return r;
193 }
194
195 static void entry_free(struct entry* e) {
196     pa_assert(e);
197
198     pa_xfree(e->description);
199     pa_xfree(e->icon);
200     pa_xfree(e);
201 }
202
203 static pa_bool_t entry_write(struct userdata *u, const char *name, const struct entry *e) {
204     pa_tagstruct *t;
205     pa_datum key, data;
206     pa_bool_t r;
207
208     pa_assert(u);
209     pa_assert(name);
210     pa_assert(e);
211
212     t = pa_tagstruct_new(NULL, 0);
213     pa_tagstruct_putu8(t, e->version);
214     pa_tagstruct_puts(t, e->description);
215     pa_tagstruct_put_boolean(t, e->user_set_description);
216     pa_tagstruct_puts(t, e->icon);
217     for (uint8_t i=0; i<ROLE_MAX; ++i)
218         pa_tagstruct_putu32(t, e->priority[i]);
219
220     key.data = (char *) name;
221     key.size = strlen(name);
222
223     data.data = (void*)pa_tagstruct_data(t, &data.size);
224
225     r = (pa_database_set(u->database, &key, &data, TRUE) == 0);
226
227     pa_tagstruct_free(t);
228
229     return r;
230 }
231
232 #ifdef ENABLE_LEGACY_DATABASE_ENTRY_FORMAT
233
234 #define LEGACY_ENTRY_VERSION 1
235 static struct entry* legacy_entry_read(struct userdata *u, pa_datum *data) {
236     struct legacy_entry {
237         uint8_t version;
238         char description[PA_NAME_MAX];
239         pa_bool_t user_set_description;
240         char icon[PA_NAME_MAX];
241         role_indexes_t priority;
242     } PA_GCC_PACKED;
243     struct legacy_entry *le;
244     struct entry *e;
245
246     pa_assert(u);
247     pa_assert(data);
248
249     if (data->size != sizeof(struct legacy_entry)) {
250         pa_log_debug("Size does not match.");
251         return NULL;
252     }
253
254     le = (struct legacy_entry*)data->data;
255
256     if (le->version != LEGACY_ENTRY_VERSION) {
257         pa_log_debug("Version mismatch.");
258         return NULL;
259     }
260
261     if (!memchr(le->description, 0, sizeof(le->description))) {
262         pa_log_warn("Description has missing NUL byte.");
263         return NULL;
264     }
265
266     if (!memchr(le->icon, 0, sizeof(le->icon))) {
267         pa_log_warn("Icon has missing NUL byte.");
268         return NULL;
269     }
270
271     e = entry_new();
272     e->description = pa_xstrdup(le->description);
273     e->icon = pa_xstrdup(le->icon);
274     return e;
275 }
276 #endif
277
278 static struct entry* entry_read(struct userdata *u, const char *name) {
279     pa_datum key, data;
280     struct entry *e = NULL;
281     pa_tagstruct *t = NULL;
282     const char *description, *icon;
283
284     pa_assert(u);
285     pa_assert(name);
286
287     key.data = (char*) name;
288     key.size = strlen(name);
289
290     pa_zero(data);
291
292     if (!pa_database_get(u->database, &key, &data))
293         goto fail;
294
295     t = pa_tagstruct_new(data.data, data.size);
296     e = entry_new();
297
298     if (pa_tagstruct_getu8(t, &e->version) < 0 ||
299         e->version > ENTRY_VERSION ||
300         pa_tagstruct_gets(t, &description) < 0 ||
301         pa_tagstruct_get_boolean(t, &e->user_set_description) < 0 ||
302         pa_tagstruct_gets(t, &icon) < 0) {
303
304         goto fail;
305     }
306
307     e->description = pa_xstrdup(description);
308     e->icon = pa_xstrdup(icon);
309
310     for (uint8_t i=0; i<ROLE_MAX; ++i) {
311         if (pa_tagstruct_getu32(t, &e->priority[i]) < 0)
312             goto fail;
313     }
314
315     if (!pa_tagstruct_eof(t))
316         goto fail;
317
318     pa_tagstruct_free(t);
319     pa_datum_free(&data);
320
321     return e;
322
323 fail:
324     pa_log_debug("Database contains invalid data for key: %s (probably pre-v1.0 data)", name);
325
326     if (e)
327         entry_free(e);
328     if (t)
329         pa_tagstruct_free(t);
330
331 #ifdef ENABLE_LEGACY_DATABASE_ENTRY_FORMAT
332     pa_log_debug("Attempting to load legacy (pre-v1.0) data for key: %s", name);
333     if ((e = legacy_entry_read(u, &data))) {
334         pa_log_debug("Success. Saving new format for key: %s", name);
335         if (entry_write(u, name, e))
336             trigger_save(u);
337         pa_datum_free(&data);
338         return e;
339     } else
340         pa_log_debug("Unable to load legacy (pre-v1.0) data for key: %s. Ignoring.", name);
341 #endif
342
343     pa_datum_free(&data);
344     return NULL;
345 }
346
347 #ifdef DUMP_DATABASE
348 static void dump_database_helper(struct userdata *u, uint32_t role_index, const char* human, pa_bool_t sink_mode) {
349     pa_assert(u);
350     pa_assert(human);
351
352     if (sink_mode) {
353         pa_sink *s;
354         if (PA_INVALID_INDEX != u->preferred_sinks[role_index] && (s = pa_idxset_get_by_index(u->core->sinks, u->preferred_sinks[role_index])))
355             pa_log_debug("   %s %s (%s)", human, pa_strnull(pa_proplist_gets(s->proplist, PA_PROP_DEVICE_DESCRIPTION)), s->name);
356         else
357             pa_log_debug("   %s No sink specified", human);
358     } else {
359         pa_source *s;
360         if (PA_INVALID_INDEX != u->preferred_sources[role_index] && (s = pa_idxset_get_by_index(u->core->sources, u->preferred_sources[role_index])))
361             pa_log_debug("   %s %s (%s)", human, pa_strnull(pa_proplist_gets(s->proplist, PA_PROP_DEVICE_DESCRIPTION)), s->name);
362         else
363             pa_log_debug("   %s No source specified", human);
364     }
365 }
366
367 static void dump_database(struct userdata *u) {
368     pa_datum key;
369     pa_bool_t done;
370
371     pa_assert(u);
372
373     done = !pa_database_first(u->database, &key, NULL);
374
375     pa_log_debug("Dumping database");
376     while (!done) {
377         char *name;
378         struct entry *e;
379         pa_datum next_key;
380
381         done = !pa_database_next(u->database, &key, &next_key, NULL);
382
383         name = pa_xstrndup(key.data, key.size);
384
385         if ((e = entry_read(u, name))) {
386             pa_log_debug(" Got entry: %s", name);
387             pa_log_debug("  Description: %s", e->description);
388             pa_log_debug("  Priorities: None:   %3u, Video: %3u, Music:  %3u, Game: %3u, Event: %3u",
389                          e->priority[ROLE_NONE], e->priority[ROLE_VIDEO], e->priority[ROLE_MUSIC], e->priority[ROLE_GAME], e->priority[ROLE_EVENT]);
390             pa_log_debug("              Phone:  %3u, Anim:  %3u, Prodtn: %3u, A11y: %3u",
391                          e->priority[ROLE_PHONE], e->priority[ROLE_ANIMATION], e->priority[ROLE_PRODUCTION], e->priority[ROLE_A11Y]);
392             entry_free(e);
393         }
394
395         pa_xfree(name);
396
397         pa_datum_free(&key);
398         key = next_key;
399     }
400
401     if (u->do_routing) {
402         pa_log_debug(" Highest priority devices per-role:");
403
404         pa_log_debug("  Sinks:");
405         for (uint32_t role = ROLE_NONE; role < NUM_ROLES; ++role) {
406             char name[13];
407             uint32_t len = PA_MIN(12u, strlen(role_names[role]));
408             strncpy(name, role_names[role], len);
409             for (int i = len+1; i < 12; ++i) name[i] = ' ';
410             name[len] = ':'; name[0] -= 32; name[12] = '\0';
411             dump_database_helper(u, role, name, TRUE);
412         }
413
414         pa_log_debug("  Sources:");
415         for (uint32_t role = ROLE_NONE; role < NUM_ROLES; ++role) {
416             char name[13];
417             uint32_t len = PA_MIN(12u, strlen(role_names[role]));
418             strncpy(name, role_names[role], len);
419             for (int i = len+1; i < 12; ++i) name[i] = ' ';
420             name[len] = ':'; name[0] -= 32; name[12] = '\0';
421             dump_database_helper(u, role, name, FALSE);
422         }
423     }
424
425     pa_log_debug("Completed database dump");
426 }
427 #endif
428
429 static void notify_subscribers(struct userdata *u) {
430
431     pa_native_connection *c;
432     uint32_t idx;
433
434     pa_assert(u);
435
436     PA_IDXSET_FOREACH(c, u->subscribed, idx) {
437         pa_tagstruct *t;
438
439         t = pa_tagstruct_new(NULL, 0);
440         pa_tagstruct_putu32(t, PA_COMMAND_EXTENSION);
441         pa_tagstruct_putu32(t, 0);
442         pa_tagstruct_putu32(t, u->module->index);
443         pa_tagstruct_puts(t, u->module->name);
444         pa_tagstruct_putu32(t, SUBCOMMAND_EVENT);
445
446         pa_pstream_send_tagstruct(pa_native_connection_get_pstream(c), t);
447     }
448 }
449
450 static pa_bool_t entries_equal(const struct entry *a, const struct entry *b) {
451
452     pa_assert(a);
453     pa_assert(b);
454
455     if (!pa_streq(a->description, b->description)
456         || a->user_set_description != b->user_set_description
457         || !pa_streq(a->icon, b->icon))
458         return FALSE;
459
460     for (int i=0; i < NUM_ROLES; ++i)
461         if (a->priority[i] != b->priority[i])
462             return FALSE;
463
464     return TRUE;
465 }
466
467 static char *get_name(const char *key, const char *prefix) {
468     char *t;
469
470     if (strncmp(key, prefix, strlen(prefix)))
471         return NULL;
472
473     t = pa_xstrdup(key + strlen(prefix));
474     return t;
475 }
476
477 static inline struct entry *load_or_initialize_entry(struct userdata *u, struct entry *entry, const char *name, const char *prefix) {
478     struct entry *old;
479
480     pa_assert(u);
481     pa_assert(entry);
482     pa_assert(name);
483     pa_assert(prefix);
484
485     if ((old = entry_read(u, name))) {
486         *entry = *old;
487         entry->description = pa_xstrdup(old->description);
488         entry->icon = pa_xstrdup(old->icon);
489     } else {
490         /* This is a new device, so make sure we write it's priority list correctly */
491         role_indexes_t max_priority;
492         pa_datum key;
493         pa_bool_t done;
494
495         pa_zero(max_priority);
496         done = !pa_database_first(u->database, &key, NULL);
497
498         /* Find all existing devices with the same prefix so we calculate the current max priority for each role */
499         while (!done) {
500             pa_datum next_key;
501
502             done = !pa_database_next(u->database, &key, &next_key, NULL);
503
504             if (key.size > strlen(prefix) && strncmp(key.data, prefix, strlen(prefix)) == 0) {
505                 char *name2;
506                 struct entry *e;
507
508                 name2 = pa_xstrndup(key.data, key.size);
509
510                 if ((e = entry_read(u, name2))) {
511                     for (uint32_t i = 0; i < NUM_ROLES; ++i) {
512                         max_priority[i] = PA_MAX(max_priority[i], e->priority[i]);
513                     }
514
515                     entry_free(e);
516                 }
517
518                 pa_xfree(name2);
519             }
520             pa_datum_free(&key);
521             key = next_key;
522         }
523
524         /* Actually initialise our entry now we've calculated it */
525         for (uint32_t i = 0; i < NUM_ROLES; ++i) {
526             entry->priority[i] = max_priority[i] + 1;
527         }
528         entry->user_set_description = FALSE;
529     }
530
531     return old;
532 }
533
534 static uint32_t get_role_index(const char* role) {
535     pa_assert(role);
536
537     for (uint32_t i = ROLE_NONE; i < NUM_ROLES; ++i)
538         if (pa_streq(role, role_names[i]))
539             return i;
540
541     return PA_INVALID_INDEX;
542 }
543
544 static void update_highest_priority_device_indexes(struct userdata *u, const char *prefix, void *ignore_device) {
545     role_indexes_t *indexes, highest_priority_available;
546     pa_datum key;
547     pa_bool_t done, sink_mode;
548
549     pa_assert(u);
550     pa_assert(prefix);
551
552     sink_mode = pa_streq(prefix, "sink:");
553
554     if (sink_mode)
555         indexes = &u->preferred_sinks;
556     else
557         indexes = &u->preferred_sources;
558
559     for (uint32_t i = 0; i < NUM_ROLES; ++i) {
560         (*indexes)[i] = PA_INVALID_INDEX;
561     }
562     pa_zero(highest_priority_available);
563
564     done = !pa_database_first(u->database, &key, NULL);
565
566     /* Find all existing devices with the same prefix so we find the highest priority device for each role */
567     while (!done) {
568         pa_datum next_key;
569
570         done = !pa_database_next(u->database, &key, &next_key, NULL);
571
572         if (key.size > strlen(prefix) && strncmp(key.data, prefix, strlen(prefix)) == 0) {
573             char *name, *device_name;
574             struct entry *e;
575
576             name = pa_xstrndup(key.data, key.size);
577             pa_assert_se(device_name = get_name(name, prefix));
578
579             if ((e = entry_read(u, name))) {
580                 for (uint32_t i = 0; i < NUM_ROLES; ++i) {
581                     if (!highest_priority_available[i] || e->priority[i] < highest_priority_available[i]) {
582                         /* We've found a device with a higher priority than that we've currently got,
583                            so see if it is currently available or not and update our list */
584                         uint32_t idx;
585                         pa_bool_t found = FALSE;
586
587                         if (sink_mode) {
588                             pa_sink *sink;
589
590                             PA_IDXSET_FOREACH(sink, u->core->sinks, idx) {
591                                 if ((pa_sink*) ignore_device == sink)
592                                     continue;
593                                 if (pa_streq(sink->name, device_name)) {
594                                     found = TRUE;
595                                     idx = sink->index; /* Is this needed? */
596                                     break;
597                                 }
598                             }
599                         } else {
600                             pa_source *source;
601
602                             PA_IDXSET_FOREACH(source, u->core->sources, idx) {
603                                 if ((pa_source*) ignore_device == source)
604                                     continue;
605                                 if (pa_streq(source->name, device_name)) {
606                                     found = TRUE;
607                                     idx = source->index; /* Is this needed? */
608                                     break;
609                                 }
610                             }
611                         }
612                         if (found) {
613                             highest_priority_available[i] = e->priority[i];
614                             (*indexes)[i] = idx;
615                         }
616
617                     }
618                 }
619
620                 entry_free(e);
621             }
622
623             pa_xfree(name);
624             pa_xfree(device_name);
625         }
626
627         pa_datum_free(&key);
628         key = next_key;
629     }
630 }
631
632 static void route_sink_input(struct userdata *u, pa_sink_input *si) {
633     const char *role;
634     uint32_t role_index, device_index;
635     pa_sink *sink;
636
637     pa_assert(u);
638     pa_assert(u->do_routing);
639
640     if (si->save_sink)
641         return;
642
643     /* Skip this if it is already in the process of being moved anyway */
644     if (!si->sink)
645         return;
646
647     /* It might happen that a stream and a sink are set up at the
648     same time, in which case we want to make sure we don't
649     interfere with that */
650     if (!PA_SINK_INPUT_IS_LINKED(pa_sink_input_get_state(si)))
651         return;
652
653     if (!(role = pa_proplist_gets(si->proplist, PA_PROP_MEDIA_ROLE)))
654         role_index = get_role_index("none");
655     else
656         role_index = get_role_index(role);
657
658     if (PA_INVALID_INDEX == role_index)
659         return;
660
661     device_index = u->preferred_sinks[role_index];
662     if (PA_INVALID_INDEX == device_index)
663         return;
664
665     if (!(sink = pa_idxset_get_by_index(u->core->sinks, device_index)))
666         return;
667
668     if (si->sink != sink)
669         pa_sink_input_move_to(si, sink, FALSE);
670 }
671
672 static pa_hook_result_t route_sink_inputs(struct userdata *u, pa_sink *ignore_sink) {
673     pa_sink_input *si;
674     uint32_t idx;
675
676     pa_assert(u);
677
678     if (!u->do_routing)
679         return PA_HOOK_OK;
680
681     update_highest_priority_device_indexes(u, "sink:", ignore_sink);
682
683     PA_IDXSET_FOREACH(si, u->core->sink_inputs, idx) {
684         route_sink_input(u, si);
685     }
686
687     return PA_HOOK_OK;
688 }
689
690 static void route_source_output(struct userdata *u, pa_source_output *so) {
691     const char *role;
692     uint32_t role_index, device_index;
693     pa_source *source;
694
695     pa_assert(u);
696     pa_assert(u->do_routing);
697
698     if (so->save_source)
699         return;
700
701     if (so->direct_on_input)
702         return;
703
704     /* Skip this if it is already in the process of being moved anyway */
705     if (!so->source)
706         return;
707
708     /* It might happen that a stream and a source are set up at the
709     same time, in which case we want to make sure we don't
710     interfere with that */
711     if (!PA_SOURCE_OUTPUT_IS_LINKED(pa_source_output_get_state(so)))
712         return;
713
714     if (!(role = pa_proplist_gets(so->proplist, PA_PROP_MEDIA_ROLE)))
715         role_index = get_role_index("none");
716     else
717         role_index = get_role_index(role);
718
719     if (PA_INVALID_INDEX == role_index)
720         return;
721
722     device_index = u->preferred_sources[role_index];
723     if (PA_INVALID_INDEX == device_index)
724         return;
725
726     if (!(source = pa_idxset_get_by_index(u->core->sources, device_index)))
727         return;
728
729     if (so->source != source)
730         pa_source_output_move_to(so, source, FALSE);
731 }
732
733 static pa_hook_result_t route_source_outputs(struct userdata *u, pa_source* ignore_source) {
734     pa_source_output *so;
735     uint32_t idx;
736
737     pa_assert(u);
738
739     if (!u->do_routing)
740         return PA_HOOK_OK;
741
742     update_highest_priority_device_indexes(u, "source:", ignore_source);
743
744     PA_IDXSET_FOREACH(so, u->core->source_outputs, idx) {
745         route_source_output(u, so);
746     }
747
748     return PA_HOOK_OK;
749 }
750
751 static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint32_t idx, void *userdata) {
752     struct userdata *u = userdata;
753     struct entry *entry, *old = NULL;
754     char *name = NULL;
755
756     pa_assert(c);
757     pa_assert(u);
758
759     if (t != (PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_NEW) &&
760         t != (PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE) &&
761         t != (PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_NEW) &&
762         t != (PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE) &&
763
764         /*t != (PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_NEW) &&*/
765         t != (PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE) &&
766         /*t != (PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_NEW) &&*/
767         t != (PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_CHANGE))
768         return;
769
770     if ((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SINK_INPUT) {
771         pa_sink_input *si;
772
773         if (!u->do_routing)
774             return;
775         if (!(si = pa_idxset_get_by_index(c->sink_inputs, idx)))
776             return;
777
778         /* The role may change mid-stream, so we reroute */
779         route_sink_input(u, si);
780
781         return;
782     } else if ((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT) {
783         pa_source_output *so;
784
785         if (!u->do_routing)
786             return;
787         if (!(so = pa_idxset_get_by_index(c->source_outputs, idx)))
788             return;
789
790         /* The role may change mid-stream, so we reroute */
791         route_source_output(u, so);
792
793         return;
794     } else if ((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SINK) {
795         pa_sink *sink;
796
797         if (!(sink = pa_idxset_get_by_index(c->sinks, idx)))
798             return;
799
800         entry = entry_new();
801         name = pa_sprintf_malloc("sink:%s", sink->name);
802
803         old = load_or_initialize_entry(u, entry, name, "sink:");
804
805         if (!entry->user_set_description) {
806             pa_xfree(entry->description);
807             entry->description = pa_xstrdup(pa_proplist_gets(sink->proplist, PA_PROP_DEVICE_DESCRIPTION));
808         } else if (!pa_streq(entry->description, pa_proplist_gets(sink->proplist, PA_PROP_DEVICE_DESCRIPTION))) {
809             /* Warning: If two modules fight over the description, this could cause an infinite loop.
810                by changing the description here, we retrigger this subscription callback. The only thing stopping us from
811                looping is the fact that the string comparison will fail on the second iteration. If another module tries to manage
812                the description, this will fail... */
813             pa_sink_set_description(sink, entry->description);
814         }
815
816         pa_xfree(entry->icon);
817         entry->icon = pa_xstrdup(pa_proplist_gets(sink->proplist, PA_PROP_DEVICE_ICON_NAME));
818
819     } else if ((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SOURCE) {
820         pa_source *source;
821
822         pa_assert((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SOURCE);
823
824         if (!(source = pa_idxset_get_by_index(c->sources, idx)))
825             return;
826
827         if (source->monitor_of)
828             return;
829
830         entry = entry_new();
831         name = pa_sprintf_malloc("source:%s", source->name);
832
833         old = load_or_initialize_entry(u, entry, name, "source:");
834
835         if (!entry->user_set_description) {
836             pa_xfree(entry->description);
837             entry->description = pa_xstrdup(pa_proplist_gets(source->proplist, PA_PROP_DEVICE_DESCRIPTION));
838         } else if (!pa_streq(entry->description, pa_proplist_gets(source->proplist, PA_PROP_DEVICE_DESCRIPTION))) {
839             /* Warning: If two modules fight over the description, this could cause an infinite loop.
840                by changing the description here, we retrigger this subscription callback. The only thing stopping us from
841                looping is the fact that the string comparison will fail on the second iteration. If another module tries to manage
842                the description, this will fail... */
843             pa_source_set_description(source, entry->description);
844         }
845
846         pa_xfree(entry->icon);
847         entry->icon = pa_xstrdup(pa_proplist_gets(source->proplist, PA_PROP_DEVICE_ICON_NAME));
848     } else {
849         pa_assert_not_reached();
850     }
851
852     pa_assert(name);
853
854     if (old) {
855
856         if (entries_equal(old, entry)) {
857             entry_free(old);
858             entry_free(entry);
859             pa_xfree(name);
860
861             return;
862         }
863
864         entry_free(old);
865     }
866
867     pa_log_info("Storing device %s.", name);
868
869     if (entry_write(u, name, entry))
870         trigger_save(u);
871     else
872         pa_log_warn("Could not save device");;
873
874     entry_free(entry);
875     pa_xfree(name);
876 }
877
878 static pa_hook_result_t sink_new_hook_callback(pa_core *c, pa_sink_new_data *new_data, struct userdata *u) {
879     char *name;
880     struct entry *e;
881
882     pa_assert(c);
883     pa_assert(new_data);
884     pa_assert(u);
885
886     name = pa_sprintf_malloc("sink:%s", new_data->name);
887
888     if ((e = entry_read(u, name))) {
889         if (e->user_set_description && !pa_safe_streq(e->description, pa_proplist_gets(new_data->proplist, PA_PROP_DEVICE_DESCRIPTION))) {
890             pa_log_info("Restoring description for sink %s.", new_data->name);
891             pa_proplist_sets(new_data->proplist, PA_PROP_DEVICE_DESCRIPTION, e->description);
892         }
893
894         entry_free(e);
895     }
896
897     pa_xfree(name);
898
899     return PA_HOOK_OK;
900 }
901
902 static pa_hook_result_t source_new_hook_callback(pa_core *c, pa_source_new_data *new_data, struct userdata *u) {
903     char *name;
904     struct entry *e;
905
906     pa_assert(c);
907     pa_assert(new_data);
908     pa_assert(u);
909
910     name = pa_sprintf_malloc("source:%s", new_data->name);
911
912     if ((e = entry_read(u, name))) {
913         if (e->user_set_description && !pa_safe_streq(e->description, pa_proplist_gets(new_data->proplist, PA_PROP_DEVICE_DESCRIPTION))) {
914             /* NB, We cannot detect if we are a monitor here... this could mess things up a bit... */
915             pa_log_info("Restoring description for source %s.", new_data->name);
916             pa_proplist_sets(new_data->proplist, PA_PROP_DEVICE_DESCRIPTION, e->description);
917         }
918
919         entry_free(e);
920     }
921
922     pa_xfree(name);
923
924     return PA_HOOK_OK;
925 }
926
927 static pa_hook_result_t sink_input_new_hook_callback(pa_core *c, pa_sink_input_new_data *new_data, struct userdata *u) {
928     const char *role;
929     uint32_t role_index;
930
931     pa_assert(c);
932     pa_assert(new_data);
933     pa_assert(u);
934
935     if (!u->do_routing)
936         return PA_HOOK_OK;
937
938     if (new_data->sink)
939         pa_log_debug("Not restoring device for stream because already set.");
940     else {
941         if (!(role = pa_proplist_gets(new_data->proplist, PA_PROP_MEDIA_ROLE)))
942             role_index = get_role_index("none");
943         else
944             role_index = get_role_index(role);
945
946         if (PA_INVALID_INDEX != role_index) {
947             uint32_t device_index;
948
949             device_index = u->preferred_sinks[role_index];
950             if (PA_INVALID_INDEX != device_index) {
951                 pa_sink *sink;
952
953                 if ((sink = pa_idxset_get_by_index(u->core->sinks, device_index))) {
954                     if (!pa_sink_input_new_data_set_sink(new_data, sink, FALSE))
955                         pa_log_debug("Not restoring device for stream because no supported format was found");
956                 }
957             }
958         }
959     }
960
961     return PA_HOOK_OK;
962 }
963
964 static pa_hook_result_t source_output_new_hook_callback(pa_core *c, pa_source_output_new_data *new_data, struct userdata *u) {
965     const char *role;
966     uint32_t role_index;
967
968     pa_assert(c);
969     pa_assert(new_data);
970     pa_assert(u);
971
972     if (!u->do_routing)
973         return PA_HOOK_OK;
974
975     if (new_data->direct_on_input)
976         return PA_HOOK_OK;
977
978     if (new_data->source)
979         pa_log_debug("Not restoring device for stream because already set.");
980     else {
981         if (!(role = pa_proplist_gets(new_data->proplist, PA_PROP_MEDIA_ROLE)))
982             role_index = get_role_index("none");
983         else
984             role_index = get_role_index(role);
985
986         if (PA_INVALID_INDEX != role_index) {
987             uint32_t device_index;
988
989             device_index = u->preferred_sources[role_index];
990             if (PA_INVALID_INDEX != device_index) {
991                 pa_source *source;
992
993                 if ((source = pa_idxset_get_by_index(u->core->sources, device_index)))
994                     if (!pa_source_output_new_data_set_source(new_data, source, FALSE))
995                         pa_log_debug("Not restoring device for stream because no supported format was found");
996             }
997         }
998     }
999
1000     return PA_HOOK_OK;
1001 }
1002
1003 static pa_hook_result_t sink_put_hook_callback(pa_core *c, PA_GCC_UNUSED pa_sink *sink, struct userdata *u) {
1004     pa_assert(c);
1005     pa_assert(u);
1006     pa_assert(u->core == c);
1007     pa_assert(u->on_hotplug);
1008
1009     notify_subscribers(u);
1010
1011     return route_sink_inputs(u, NULL);
1012 }
1013
1014 static pa_hook_result_t source_put_hook_callback(pa_core *c, PA_GCC_UNUSED pa_source *source, struct userdata *u) {
1015     pa_assert(c);
1016     pa_assert(u);
1017     pa_assert(u->core == c);
1018     pa_assert(u->on_hotplug);
1019
1020     notify_subscribers(u);
1021
1022     return route_source_outputs(u, NULL);
1023 }
1024
1025 static pa_hook_result_t sink_unlink_hook_callback(pa_core *c, pa_sink *sink, struct userdata *u) {
1026     pa_assert(c);
1027     pa_assert(sink);
1028     pa_assert(u);
1029     pa_assert(u->core == c);
1030     pa_assert(u->on_rescue);
1031
1032     /* There's no point in doing anything if the core is shut down anyway */
1033     if (c->state == PA_CORE_SHUTDOWN)
1034         return PA_HOOK_OK;
1035
1036     notify_subscribers(u);
1037
1038     return route_sink_inputs(u, sink);
1039 }
1040
1041 static pa_hook_result_t source_unlink_hook_callback(pa_core *c, pa_source *source, struct userdata *u) {
1042     pa_assert(c);
1043     pa_assert(source);
1044     pa_assert(u);
1045     pa_assert(u->core == c);
1046     pa_assert(u->on_rescue);
1047
1048     /* There's no point in doing anything if the core is shut down anyway */
1049     if (c->state == PA_CORE_SHUTDOWN)
1050         return PA_HOOK_OK;
1051
1052     notify_subscribers(u);
1053
1054     return route_source_outputs(u, source);
1055 }
1056
1057 static void apply_entry(struct userdata *u, const char *name, struct entry *e) {
1058     uint32_t idx;
1059     char *n;
1060
1061     pa_assert(u);
1062     pa_assert(name);
1063     pa_assert(e);
1064
1065     if (!e->user_set_description)
1066         return;
1067
1068     if ((n = get_name(name, "sink:"))) {
1069         pa_sink *s;
1070         PA_IDXSET_FOREACH(s, u->core->sinks, idx) {
1071             if (!pa_streq(s->name, n)) {
1072                 continue;
1073             }
1074
1075             pa_log_info("Setting description for sink %s to '%s'", s->name, e->description);
1076             pa_sink_set_description(s, e->description);
1077         }
1078         pa_xfree(n);
1079     }
1080     else if ((n = get_name(name, "source:"))) {
1081         pa_source *s;
1082         PA_IDXSET_FOREACH(s, u->core->sources, idx) {
1083             if (!pa_streq(s->name, n)) {
1084                 continue;
1085             }
1086
1087             if (s->monitor_of) {
1088                 pa_log_warn("Cowardly refusing to set the description for monitor source %s.", s->name);
1089                 continue;
1090             }
1091
1092             pa_log_info("Setting description for source %s to '%s'", s->name, e->description);
1093             pa_source_set_description(s, e->description);
1094         }
1095         pa_xfree(n);
1096     }
1097 }
1098
1099 #define EXT_VERSION 1
1100
1101 static int extension_cb(pa_native_protocol *p, pa_module *m, pa_native_connection *c, uint32_t tag, pa_tagstruct *t) {
1102   struct userdata *u;
1103   uint32_t command;
1104   pa_tagstruct *reply = NULL;
1105
1106   pa_assert(p);
1107   pa_assert(m);
1108   pa_assert(c);
1109   pa_assert(t);
1110
1111   u = m->userdata;
1112
1113   if (pa_tagstruct_getu32(t, &command) < 0)
1114     goto fail;
1115
1116   reply = pa_tagstruct_new(NULL, 0);
1117   pa_tagstruct_putu32(reply, PA_COMMAND_REPLY);
1118   pa_tagstruct_putu32(reply, tag);
1119
1120   switch (command) {
1121     case SUBCOMMAND_TEST: {
1122       if (!pa_tagstruct_eof(t))
1123         goto fail;
1124
1125       pa_tagstruct_putu32(reply, EXT_VERSION);
1126       break;
1127     }
1128
1129     case SUBCOMMAND_READ: {
1130       pa_datum key;
1131       pa_bool_t done;
1132
1133       if (!pa_tagstruct_eof(t))
1134         goto fail;
1135
1136       done = !pa_database_first(u->database, &key, NULL);
1137
1138       while (!done) {
1139         pa_datum next_key;
1140         struct entry *e;
1141         char *name;
1142
1143         done = !pa_database_next(u->database, &key, &next_key, NULL);
1144
1145         name = pa_xstrndup(key.data, key.size);
1146         pa_datum_free(&key);
1147
1148         if ((e = entry_read(u, name))) {
1149             uint32_t idx;
1150             char *device_name;
1151             uint32_t found_index = PA_INVALID_INDEX;
1152
1153             if ((device_name = get_name(name, "sink:"))) {
1154                 pa_sink* s;
1155                 PA_IDXSET_FOREACH(s, u->core->sinks, idx) {
1156                     if (pa_streq(s->name, device_name)) {
1157                         found_index = s->index;
1158                         break;
1159                     }
1160                 }
1161                 pa_xfree(device_name);
1162             } else if ((device_name = get_name(name, "source:"))) {
1163                 pa_source* s;
1164                 PA_IDXSET_FOREACH(s, u->core->sources, idx) {
1165                     if (pa_streq(s->name, device_name)) {
1166                         found_index = s->index;
1167                         break;
1168                     }
1169                 }
1170                 pa_xfree(device_name);
1171             }
1172
1173             pa_tagstruct_puts(reply, name);
1174             pa_tagstruct_puts(reply, e->description);
1175             pa_tagstruct_puts(reply, e->icon);
1176             pa_tagstruct_putu32(reply, found_index);
1177             pa_tagstruct_putu32(reply, NUM_ROLES);
1178
1179             for (uint32_t i = ROLE_NONE; i < NUM_ROLES; ++i) {
1180                 pa_tagstruct_puts(reply, role_names[i]);
1181                 pa_tagstruct_putu32(reply, e->priority[i]);
1182             }
1183
1184             entry_free(e);
1185         }
1186
1187         pa_xfree(name);
1188
1189         key = next_key;
1190       }
1191
1192       break;
1193     }
1194
1195     case SUBCOMMAND_RENAME: {
1196
1197         struct entry *e;
1198         const char *device, *description;
1199
1200         if (pa_tagstruct_gets(t, &device) < 0 ||
1201           pa_tagstruct_gets(t, &description) < 0)
1202           goto fail;
1203
1204         if (!device || !*device || !description || !*description)
1205           goto fail;
1206
1207         if ((e = entry_read(u, device))) {
1208             pa_xfree(e->description);
1209             e->description = pa_xstrdup(description);
1210             e->user_set_description = TRUE;
1211
1212             if (entry_write(u, (char *)device, e)) {
1213                 apply_entry(u, device, e);
1214
1215                 trigger_save(u);
1216             }
1217             else
1218                 pa_log_warn("Could not save device");
1219
1220             entry_free(e);
1221         }
1222         else
1223             pa_log_warn("Could not rename device %s, no entry in database", device);
1224
1225       break;
1226     }
1227
1228     case SUBCOMMAND_DELETE:
1229
1230       while (!pa_tagstruct_eof(t)) {
1231         const char *name;
1232         pa_datum key;
1233
1234         if (pa_tagstruct_gets(t, &name) < 0)
1235           goto fail;
1236
1237         key.data = (char*) name;
1238         key.size = strlen(name);
1239
1240         /** @todo: Reindex the priorities */
1241         pa_database_unset(u->database, &key);
1242       }
1243
1244       trigger_save(u);
1245
1246       break;
1247
1248     case SUBCOMMAND_ROLE_DEVICE_PRIORITY_ROUTING: {
1249
1250         pa_bool_t enable;
1251
1252         if (pa_tagstruct_get_boolean(t, &enable) < 0)
1253             goto fail;
1254
1255         if ((u->do_routing = enable)) {
1256             /* Update our caches */
1257             update_highest_priority_device_indexes(u, "sink:", NULL);
1258             update_highest_priority_device_indexes(u, "source:", NULL);
1259         }
1260
1261         break;
1262     }
1263
1264     case SUBCOMMAND_REORDER: {
1265
1266         const char *role;
1267         struct entry *e;
1268         uint32_t role_index, n_devices;
1269         pa_datum key;
1270         pa_bool_t done, sink_mode = TRUE;
1271         struct device_t { uint32_t prio; char *device; };
1272         struct device_t *device;
1273         struct device_t **devices;
1274         uint32_t i, idx, offset;
1275         pa_hashmap *h;
1276         /*void *state;*/
1277         pa_bool_t first;
1278
1279         if (pa_tagstruct_gets(t, &role) < 0 ||
1280             pa_tagstruct_getu32(t, &n_devices) < 0 ||
1281             n_devices < 1)
1282             goto fail;
1283
1284         if (PA_INVALID_INDEX == (role_index = get_role_index(role)))
1285             goto fail;
1286
1287         /* Cycle through the devices given and make sure they exist */
1288         h = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func);
1289         first = TRUE;
1290         idx = 0;
1291         for (i = 0; i < n_devices; ++i) {
1292             const char *s;
1293             if (pa_tagstruct_gets(t, &s) < 0) {
1294                 while ((device = pa_hashmap_steal_first(h))) {
1295                     pa_xfree(device->device);
1296                     pa_xfree(device);
1297                 }
1298
1299                 pa_hashmap_free(h, NULL);
1300                 pa_log_error("Protocol error on reorder");
1301                 goto fail;
1302             }
1303
1304             /* Ensure this is a valid entry */
1305             if (!(e = entry_read(u, s))) {
1306                 while ((device = pa_hashmap_steal_first(h))) {
1307                     pa_xfree(device->device);
1308                     pa_xfree(device);
1309                 }
1310
1311                 pa_hashmap_free(h, NULL);
1312                 pa_log_error("Client specified an unknown device in it's reorder list.");
1313                 goto fail;
1314             }
1315             entry_free(e);
1316
1317             if (first) {
1318                 first = FALSE;
1319                 sink_mode = (0 == strncmp("sink:", s, 5));
1320             } else if ((sink_mode && 0 != strncmp("sink:", s, 5)) || (!sink_mode && 0 != strncmp("source:", s, 7))) {
1321                 while ((device = pa_hashmap_steal_first(h))) {
1322                     pa_xfree(device->device);
1323                     pa_xfree(device);
1324                 }
1325
1326                 pa_hashmap_free(h, NULL);
1327                 pa_log_error("Attempted to reorder mixed devices (sinks and sources)");
1328                 goto fail;
1329             }
1330
1331             /* Add the device to our hashmap. If it's already in it, free it now and carry on */
1332             device = pa_xnew(struct device_t, 1);
1333             device->device = pa_xstrdup(s);
1334             if (pa_hashmap_put(h, device->device, device) == 0) {
1335                 device->prio = idx;
1336                 idx++;
1337             } else {
1338                 pa_xfree(device->device);
1339                 pa_xfree(device);
1340             }
1341         }
1342
1343         /*pa_log_debug("Hashmap contents (received from client)");
1344         PA_HASHMAP_FOREACH(device, h, state) {
1345             pa_log_debug("  - %s (%d)", device->device, device->prio);
1346         }*/
1347
1348         /* Now cycle through our list and add all the devices.
1349            This has the effect of adding in any in our DB,
1350            not specified in the device list (and thus will be
1351            tacked on at the end) */
1352         offset = idx;
1353         done = !pa_database_first(u->database, &key, NULL);
1354
1355         while (!done && idx < 256) {
1356             pa_datum next_key;
1357
1358             done = !pa_database_next(u->database, &key, &next_key, NULL);
1359
1360             device = pa_xnew(struct device_t, 1);
1361             device->device = pa_xstrndup(key.data, key.size);
1362             if ((sink_mode && 0 == strncmp("sink:", device->device, 5))
1363                 || (!sink_mode && 0 == strncmp("source:", device->device, 7))) {
1364
1365                 /* Add the device to our hashmap. If it's already in it, free it now and carry on */
1366                 if (pa_hashmap_put(h, device->device, device) == 0
1367                     && (e = entry_read(u, device->device))) {
1368                     /* We add offset on to the existing priority so that when we order, the
1369                        existing entries are always lower priority than the new ones. */
1370                     device->prio = (offset + e->priority[role_index]);
1371                     pa_xfree(e);
1372                 }
1373                 else {
1374                     pa_xfree(device->device);
1375                     pa_xfree(device);
1376                 }
1377             } else {
1378                 pa_xfree(device->device);
1379                 pa_xfree(device);
1380             }
1381
1382             pa_datum_free(&key);
1383
1384             key = next_key;
1385         }
1386
1387         /*pa_log_debug("Hashmap contents (combined with database)");
1388         PA_HASHMAP_FOREACH(device, h, state) {
1389             pa_log_debug("  - %s (%d)", device->device, device->prio);
1390         }*/
1391
1392         /* Now we put all the entries in a simple list for sorting it. */
1393         n_devices = pa_hashmap_size(h);
1394         devices = pa_xnew(struct device_t *,  n_devices);
1395         idx = 0;
1396         while ((device = pa_hashmap_steal_first(h))) {
1397             devices[idx++] = device;
1398         }
1399         pa_hashmap_free(h, NULL);
1400
1401         /* Simple bubble sort */
1402         for (i = 0; i < n_devices; ++i) {
1403             for (uint32_t j = i; j < n_devices; ++j) {
1404                 if (devices[i]->prio > devices[j]->prio) {
1405                     struct device_t *tmp;
1406                     tmp = devices[i];
1407                     devices[i] = devices[j];
1408                     devices[j] = tmp;
1409                 }
1410             }
1411         }
1412
1413         /*pa_log_debug("Sorted device list");
1414         for (i = 0; i < n_devices; ++i) {
1415             pa_log_debug("  - %s (%d)", devices[i]->device, devices[i]->prio);
1416         }*/
1417
1418         /* Go through in order and write the new entry and cleanup our own list */
1419         idx = 1;
1420         first = TRUE;
1421         for (i = 0; i < n_devices; ++i) {
1422             if ((e = entry_read(u, devices[i]->device))) {
1423                 if (e->priority[role_index] == idx)
1424                     idx++;
1425                 else {
1426                     e->priority[role_index] = idx;
1427
1428                     if (entry_write(u, (char *) devices[i]->device, e)) {
1429                         first = FALSE;
1430                         idx++;
1431                     }
1432                 }
1433
1434                 pa_xfree(e);
1435             }
1436             pa_xfree(devices[i]->device);
1437             pa_xfree(devices[i]);
1438         }
1439
1440         pa_xfree(devices);
1441
1442         if (!first) {
1443             trigger_save(u);
1444
1445             if (sink_mode)
1446                 route_sink_inputs(u, NULL);
1447             else
1448                 route_source_outputs(u, NULL);
1449         }
1450
1451         break;
1452     }
1453
1454     case SUBCOMMAND_SUBSCRIBE: {
1455
1456       pa_bool_t enabled;
1457
1458       if (pa_tagstruct_get_boolean(t, &enabled) < 0 ||
1459         !pa_tagstruct_eof(t))
1460         goto fail;
1461
1462       if (enabled)
1463         pa_idxset_put(u->subscribed, c, NULL);
1464       else
1465         pa_idxset_remove_by_data(u->subscribed, c, NULL);
1466
1467       break;
1468     }
1469
1470     default:
1471       goto fail;
1472   }
1473
1474   pa_pstream_send_tagstruct(pa_native_connection_get_pstream(c), reply);
1475   return 0;
1476
1477   fail:
1478
1479   if (reply)
1480     pa_tagstruct_free(reply);
1481
1482   return -1;
1483 }
1484
1485 static pa_hook_result_t connection_unlink_hook_cb(pa_native_protocol *p, pa_native_connection *c, struct userdata *u) {
1486     pa_assert(p);
1487     pa_assert(c);
1488     pa_assert(u);
1489
1490     pa_idxset_remove_by_data(u->subscribed, c, NULL);
1491     return PA_HOOK_OK;
1492 }
1493
1494 struct prioritised_indexes {
1495     uint32_t index;
1496     int32_t priority;
1497 };
1498
1499 int pa__init(pa_module*m) {
1500     pa_modargs *ma = NULL;
1501     struct userdata *u;
1502     char *fname;
1503     pa_sink *sink;
1504     pa_source *source;
1505     uint32_t idx;
1506     pa_bool_t do_routing = FALSE, on_hotplug = TRUE, on_rescue = TRUE;
1507     uint32_t total_devices;
1508
1509     pa_assert(m);
1510
1511     if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
1512         pa_log("Failed to parse module arguments");
1513         goto fail;
1514     }
1515
1516     if (pa_modargs_get_value_boolean(ma, "do_routing", &do_routing) < 0 ||
1517         pa_modargs_get_value_boolean(ma, "on_hotplug", &on_hotplug) < 0 ||
1518         pa_modargs_get_value_boolean(ma, "on_rescue", &on_rescue) < 0) {
1519         pa_log("on_hotplug= and on_rescue= expect boolean arguments");
1520         goto fail;
1521     }
1522
1523     m->userdata = u = pa_xnew0(struct userdata, 1);
1524     u->core = m->core;
1525     u->module = m;
1526     u->do_routing = do_routing;
1527     u->on_hotplug = on_hotplug;
1528     u->on_rescue = on_rescue;
1529     u->subscribed = pa_idxset_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
1530
1531     u->protocol = pa_native_protocol_get(m->core);
1532     pa_native_protocol_install_ext(u->protocol, m, extension_cb);
1533
1534     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);
1535
1536     u->subscription = pa_subscription_new(m->core, PA_SUBSCRIPTION_MASK_SINK|PA_SUBSCRIPTION_MASK_SOURCE|PA_SUBSCRIPTION_MASK_SINK_INPUT|PA_SUBSCRIPTION_MASK_SOURCE_OUTPUT, subscribe_callback, u);
1537
1538     /* Used to handle device description management */
1539     u->sink_new_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_NEW], PA_HOOK_EARLY, (pa_hook_cb_t) sink_new_hook_callback, u);
1540     u->source_new_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_NEW], PA_HOOK_EARLY, (pa_hook_cb_t) source_new_hook_callback, u);
1541
1542     /* The following slots are used to deal with routing */
1543     /* A little bit later than module-stream-restore, but before module-intended-roles */
1544     u->sink_input_new_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_INPUT_NEW], PA_HOOK_EARLY+5, (pa_hook_cb_t) sink_input_new_hook_callback, u);
1545     u->source_output_new_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_NEW], PA_HOOK_EARLY+5, (pa_hook_cb_t) source_output_new_hook_callback, u);
1546
1547     if (on_hotplug) {
1548         /* A little bit later than module-stream-restore, but before module-intended-roles */
1549         u->sink_put_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_PUT], PA_HOOK_LATE+5, (pa_hook_cb_t) sink_put_hook_callback, u);
1550         u->source_put_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_PUT], PA_HOOK_LATE+5, (pa_hook_cb_t) source_put_hook_callback, u);
1551     }
1552
1553     if (on_rescue) {
1554         /* A little bit later than module-stream-restore, a little bit earlier than module-intended-roles, module-rescue-streams, ... */
1555         u->sink_unlink_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_UNLINK], PA_HOOK_LATE+5, (pa_hook_cb_t) sink_unlink_hook_callback, u);
1556         u->source_unlink_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_UNLINK], PA_HOOK_LATE+5, (pa_hook_cb_t) source_unlink_hook_callback, u);
1557     }
1558
1559     if (!(fname = pa_state_path("device-manager", TRUE)))
1560         goto fail;
1561
1562     if (!(u->database = pa_database_open(fname, TRUE))) {
1563         pa_log("Failed to open volume database '%s': %s", fname, pa_cstrerror(errno));
1564         pa_xfree(fname);
1565         goto fail;
1566     }
1567
1568     pa_log_info("Successfully opened database file '%s'.", fname);
1569     pa_xfree(fname);
1570
1571     /* Attempt to inject the devices into the list in priority order */
1572     total_devices = PA_MAX(pa_idxset_size(m->core->sinks), pa_idxset_size(m->core->sources));
1573     if (total_devices > 0 && total_devices < 128) {
1574         uint32_t i;
1575         struct prioritised_indexes p_i[128];
1576
1577         /* We cycle over all the available sinks so that they are added to our database if they are not in it yet */
1578         i = 0;
1579         PA_IDXSET_FOREACH(sink, m->core->sinks, idx) {
1580             pa_log_debug("Found sink index %u", sink->index);
1581             p_i[i  ].index = sink->index;
1582             p_i[i++].priority = sink->priority;
1583         }
1584         /* Bubble sort it (only really useful for first time creation) */
1585         if (i > 1)
1586           for (uint32_t j = 0; j < i; ++j)
1587               for (uint32_t k = 0; k < i; ++k)
1588                   if (p_i[j].priority > p_i[k].priority) {
1589                       struct prioritised_indexes tmp_pi = p_i[k];
1590                       p_i[k] = p_i[j];
1591                       p_i[j] = tmp_pi;
1592                   }
1593         /* Register it */
1594         for (uint32_t j = 0; j < i; ++j)
1595             subscribe_callback(m->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_NEW, p_i[j].index, u);
1596
1597         /* We cycle over all the available sources so that they are added to our database if they are not in it yet */
1598         i = 0;
1599         PA_IDXSET_FOREACH(source, m->core->sources, idx) {
1600             p_i[i  ].index = source->index;
1601             p_i[i++].priority = source->priority;
1602         }
1603         /* Bubble sort it (only really useful for first time creation) */
1604         if (i > 1)
1605           for (uint32_t j = 0; j < i; ++j)
1606               for (uint32_t k = 0; k < i; ++k)
1607                   if (p_i[j].priority > p_i[k].priority) {
1608                       struct prioritised_indexes tmp_pi = p_i[k];
1609                       p_i[k] = p_i[j];
1610                       p_i[j] = tmp_pi;
1611                   }
1612         /* Register it */
1613         for (uint32_t j = 0; j < i; ++j)
1614             subscribe_callback(m->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_NEW, p_i[j].index, u);
1615     }
1616     else if (total_devices > 0) {
1617         /* This user has a *lot* of devices... */
1618         PA_IDXSET_FOREACH(sink, m->core->sinks, idx)
1619             subscribe_callback(m->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_NEW, sink->index, u);
1620
1621         PA_IDXSET_FOREACH(source, m->core->sources, idx)
1622             subscribe_callback(m->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_NEW, source->index, u);
1623     }
1624
1625     /* Perform the routing (if it's enabled) which will update our priority list cache too */
1626     for (uint32_t i = 0; i < NUM_ROLES; ++i) {
1627         u->preferred_sinks[i] = u->preferred_sources[i] = PA_INVALID_INDEX;
1628     }
1629
1630     route_sink_inputs(u, NULL);
1631     route_source_outputs(u, NULL);
1632
1633 #ifdef DUMP_DATABASE
1634     dump_database(u);
1635 #endif
1636
1637     pa_modargs_free(ma);
1638     return 0;
1639
1640 fail:
1641     pa__done(m);
1642
1643     if (ma)
1644         pa_modargs_free(ma);
1645
1646     return -1;
1647 }
1648
1649 void pa__done(pa_module*m) {
1650     struct userdata* u;
1651
1652     pa_assert(m);
1653
1654     if (!(u = m->userdata))
1655         return;
1656
1657     if (u->subscription)
1658         pa_subscription_free(u->subscription);
1659
1660     if (u->sink_new_hook_slot)
1661         pa_hook_slot_free(u->sink_new_hook_slot);
1662     if (u->source_new_hook_slot)
1663         pa_hook_slot_free(u->source_new_hook_slot);
1664
1665     if (u->sink_input_new_hook_slot)
1666         pa_hook_slot_free(u->sink_input_new_hook_slot);
1667     if (u->source_output_new_hook_slot)
1668         pa_hook_slot_free(u->source_output_new_hook_slot);
1669
1670     if (u->sink_put_hook_slot)
1671         pa_hook_slot_free(u->sink_put_hook_slot);
1672     if (u->source_put_hook_slot)
1673         pa_hook_slot_free(u->source_put_hook_slot);
1674
1675     if (u->sink_unlink_hook_slot)
1676         pa_hook_slot_free(u->sink_unlink_hook_slot);
1677     if (u->source_unlink_hook_slot)
1678         pa_hook_slot_free(u->source_unlink_hook_slot);
1679
1680     if (u->connection_unlink_hook_slot)
1681         pa_hook_slot_free(u->connection_unlink_hook_slot);
1682
1683     if (u->save_time_event)
1684         u->core->mainloop->time_free(u->save_time_event);
1685
1686     if (u->database)
1687         pa_database_close(u->database);
1688
1689     if (u->protocol) {
1690         pa_native_protocol_remove_ext(u->protocol, m);
1691         pa_native_protocol_unref(u->protocol);
1692     }
1693
1694     if (u->subscribed)
1695         pa_idxset_free(u->subscribed, NULL);
1696
1697     pa_xfree(u);
1698 }