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