1/***
2  This file is part of PulseAudio.
3
4  Copyright 2006 Lennart Poettering
5  Copyright 2011 Canonical Ltd
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 <pulsecore/core.h>
26#include <pulsecore/core-util.h>
27#include <pulsecore/device-port.h>
28#include <pulsecore/hashmap.h>
29
30PA_MODULE_AUTHOR("David Henningsson");
31PA_MODULE_DESCRIPTION("Switches ports and profiles when devices are plugged/unplugged");
32PA_MODULE_LOAD_ONCE(true);
33PA_MODULE_VERSION(PACKAGE_VERSION);
34
35struct card_info {
36    struct userdata *userdata;
37    pa_card *card;
38
39    /* We need to cache the active profile, because we want to compare the old
40     * and new profiles in the PROFILE_CHANGED hook. Without this we'd only
41     * have access to the new profile. */
42    pa_card_profile *active_profile;
43};
44
45struct userdata {
46    pa_hashmap *card_infos; /* pa_card -> struct card_info */
47};
48
49static void card_info_new(struct userdata *u, pa_card *card) {
50    struct card_info *info;
51
52    info = pa_xnew0(struct card_info, 1);
53    info->userdata = u;
54    info->card = card;
55    info->active_profile = card->active_profile;
56
57    pa_hashmap_put(u->card_infos, card, info);
58}
59
60static void card_info_free(struct card_info *info) {
61    pa_hashmap_remove(info->userdata->card_infos, info->card);
62    pa_xfree(info);
63}
64
65static bool profile_good_for_output(pa_card_profile *profile, pa_device_port *port) {
66    pa_card *card;
67    pa_sink *sink;
68    uint32_t idx;
69
70    pa_assert(profile);
71
72    card = profile->card;
73
74    if (pa_safe_streq(card->active_profile->name, "off"))
75        return true;
76
77    if (!pa_safe_streq(card->active_profile->input_name, profile->input_name))
78        return false;
79
80    if (card->active_profile->n_sources != profile->n_sources)
81        return false;
82
83    if (card->active_profile->max_source_channels != profile->max_source_channels)
84        return false;
85
86    if (port == card->preferred_output_port)
87        return true;
88
89    PA_IDXSET_FOREACH(sink, card->sinks, idx) {
90        if (!sink->active_port)
91            continue;
92
93        if ((sink->active_port->available != PA_AVAILABLE_NO) && (sink->active_port->priority >= port->priority))
94            return false;
95    }
96
97    return true;
98}
99
100static bool profile_good_for_input(pa_card_profile *profile, pa_device_port *port) {
101    pa_card *card;
102    pa_source *source;
103    uint32_t idx;
104
105    pa_assert(profile);
106
107    card = profile->card;
108
109    if (pa_safe_streq(card->active_profile->name, "off"))
110        return true;
111
112    if (!pa_safe_streq(card->active_profile->output_name, profile->output_name))
113        return false;
114
115    if (card->active_profile->n_sinks != profile->n_sinks)
116        return false;
117
118    if (card->active_profile->max_sink_channels != profile->max_sink_channels)
119        return false;
120
121    if (port == card->preferred_input_port)
122        return true;
123
124    PA_IDXSET_FOREACH(source, card->sources, idx) {
125        if (!source->active_port)
126            continue;
127
128        if ((source->active_port->available != PA_AVAILABLE_NO) && (source->active_port->priority >= port->priority))
129            return false;
130    }
131
132    return true;
133}
134
135static int try_to_switch_profile(pa_device_port *port) {
136    pa_card_profile *best_profile = NULL, *profile;
137    void *state;
138    unsigned best_prio = 0;
139
140    if (port->card->profile_is_sticky) {
141        pa_log_info("Keeping sticky card profile '%s'", port->card->active_profile->name);
142        return -1;
143    }
144
145    pa_log_debug("Finding best profile for port %s, preferred = %s",
146                 port->name, pa_strnull(port->preferred_profile));
147
148    PA_HASHMAP_FOREACH(profile, port->profiles, state) {
149        bool good = false;
150        const char *name;
151        unsigned prio = profile->priority;
152
153        /* We make a best effort to keep other direction unchanged */
154        switch (port->direction) {
155            case PA_DIRECTION_OUTPUT:
156                name = profile->output_name;
157                good = profile_good_for_output(profile, port);
158                break;
159
160            case PA_DIRECTION_INPUT:
161                name = profile->input_name;
162                good = profile_good_for_input(profile, port);
163                break;
164        }
165
166        if (!good)
167            continue;
168
169        /* Give a high bonus in case this is the preferred profile */
170        if (pa_safe_streq(name ? name : profile->name, port->preferred_profile))
171            prio += 1000000;
172
173        if (best_profile && best_prio >= prio)
174            continue;
175
176        best_profile = profile;
177        best_prio = prio;
178    }
179
180    if (!best_profile) {
181        pa_log_debug("No suitable profile found");
182        return -1;
183    }
184
185    if (pa_card_set_profile(port->card, best_profile, false) != 0) {
186        pa_log_debug("Could not set profile %s", best_profile->name);
187        return -1;
188    }
189
190    return 0;
191}
192
193struct port_pointers {
194    pa_device_port *port;
195    pa_sink *sink;
196    pa_source *source;
197    bool is_possible_profile_active;
198    bool is_preferred_profile_active;
199    bool is_port_active;
200};
201
202static const char* profile_name_for_dir(pa_card_profile *cp, pa_direction_t dir) {
203    if (dir == PA_DIRECTION_OUTPUT && cp->output_name)
204        return cp->output_name;
205    if (dir == PA_DIRECTION_INPUT && cp->input_name)
206        return cp->input_name;
207    return cp->name;
208}
209
210static struct port_pointers find_port_pointers(pa_device_port *port) {
211    struct port_pointers pp = { .port = port };
212    uint32_t state;
213    pa_card *card;
214
215    pa_assert(port);
216    pa_assert_se(card = port->card);
217
218    switch (port->direction) {
219        case PA_DIRECTION_OUTPUT:
220            PA_IDXSET_FOREACH(pp.sink, card->sinks, state)
221                if (port == pa_hashmap_get(pp.sink->ports, port->name))
222                    break;
223            break;
224
225        case PA_DIRECTION_INPUT:
226            PA_IDXSET_FOREACH(pp.source, card->sources, state)
227                if (port == pa_hashmap_get(pp.source->ports, port->name))
228                    break;
229            break;
230    }
231
232    pp.is_possible_profile_active =
233        card->active_profile == pa_hashmap_get(port->profiles, card->active_profile->name);
234    pp.is_preferred_profile_active = pp.is_possible_profile_active && (!port->preferred_profile ||
235        pa_safe_streq(port->preferred_profile, profile_name_for_dir(card->active_profile, port->direction)));
236    pp.is_port_active = (pp.sink && pp.sink->active_port == port) || (pp.source && pp.source->active_port == port);
237
238    return pp;
239}
240
241/* Switches to a port, switching profiles if necessary or preferred */
242static void switch_to_port(pa_device_port *port, struct port_pointers pp) {
243    if (pp.is_port_active)
244        return; /* Already selected */
245
246    pa_log_debug("Trying to switch to port %s", port->name);
247    if (!pp.is_preferred_profile_active) {
248        if (try_to_switch_profile(port) < 0) {
249            if (!pp.is_possible_profile_active)
250                return;
251        }
252        else
253            /* Now that profile has changed, our sink and source pointers must be updated */
254            pp = find_port_pointers(port);
255    }
256
257    if (pp.source)
258        pa_source_set_port(pp.source, port->name, false);
259    if (pp.sink)
260        pa_sink_set_port(pp.sink, port->name, false);
261}
262
263/* Switches away from a port, switching profiles if necessary or preferred */
264static void switch_from_port(pa_device_port *port, struct port_pointers pp) {
265    pa_device_port *p, *best_port = NULL;
266    void *state;
267
268    if (!pp.is_port_active)
269        return; /* Already deselected */
270
271    /* Try to find a good enough port to switch to */
272    PA_HASHMAP_FOREACH(p, port->card->ports, state) {
273        if (p == port)
274            continue;
275
276        if (p->available == PA_AVAILABLE_NO)
277            continue;
278
279        if (p->direction != port->direction)
280            continue;
281
282        if (!best_port || best_port->priority < p->priority)
283           best_port = p;
284    }
285
286    pa_log_debug("Trying to switch away from port %s, found %s", port->name, best_port ? best_port->name : "no better option");
287
288    /* If there is no available port to switch to we need check if the active
289     * profile is still available in the
290     * PA_CORE_HOOK_CARD_PROFILE_AVAILABLE_CHANGED callback, as at this point
291     * the profile availability hasn't been updated yet. */
292    if (best_port) {
293        struct port_pointers best_pp = find_port_pointers(best_port);
294        switch_to_port(best_port, best_pp);
295    }
296}
297
298
299static pa_hook_result_t port_available_hook_callback(pa_core *c, pa_device_port *port, void* userdata) {
300    struct port_pointers pp = find_port_pointers(port);
301
302    if (!port->card) {
303        pa_log_warn("Port %s does not have a card", port->name);
304        return PA_HOOK_OK;
305    }
306
307    /* Our profile switching logic caused trouble with bluetooth headsets (see
308     * https://bugs.freedesktop.org/show_bug.cgi?id=107044) and
309     * module-bluetooth-policy takes care of automatic profile switching
310     * anyway, so we ignore bluetooth cards in
311     * module-switch-on-port-available. */
312    if (pa_safe_streq(pa_proplist_gets(port->card->proplist, PA_PROP_DEVICE_BUS), "bluetooth"))
313        return PA_HOOK_OK;
314
315    switch (port->available) {
316    case PA_AVAILABLE_UNKNOWN:
317        /* If a port availability became unknown, let's see if it's part of
318         * some availability group. If it is, it is likely to be a headphone
319         * jack that does not have impedance sensing to detect whether what was
320         * plugged in was a headphone, headset or microphone. In desktop
321         * environments that support it, this will trigger a user choice to
322         * select what kind of device was plugged in. However, let's switch to
323         * the headphone port at least, so that we have don't break
324         * functionality for setups that can't trigger this kind of
325         * interaction.
326         *
327         * For headset or microphone, if they are part of some availability group
328         * and they become unknown from off, it needs to check if their source is
329         * unlinked or not, if their source is unlinked, let switch_to_port()
330         * process them, then with the running of pa_card_set_profile(), their
331         * source will be created, otherwise the headset or microphone can't be used
332         * to record sound since there is no source for these 2 ports. This issue
333         * is observed on Dell machines which have multi-function audio jack but no
334         * internal mic.
335         *
336         * We should make this configurable so that users can optionally
337         * override the default to a headset or mic. */
338
339        /* Not part of a group of ports, so likely not a combination port */
340        if (!port->availability_group) {
341            pa_log_debug("Not switching to port %s, its availability is unknown and it's not in any availability group.", port->name);
342            break;
343        }
344
345        /* Switch the headphone port, the input ports without source and the
346         * input ports their source->active_port is part of a group of ports.
347         */
348        if (port->direction == PA_DIRECTION_INPUT && pp.source && !pp.source->active_port->availability_group) {
349            pa_log_debug("Not switching to input port %s, its availability is unknown.", port->name);
350            break;
351        }
352
353        switch_to_port(port, pp);
354        break;
355
356    case PA_AVAILABLE_YES:
357        switch_to_port(port, pp);
358        break;
359    case PA_AVAILABLE_NO:
360        switch_from_port(port, pp);
361        break;
362    default:
363        break;
364    }
365
366    return PA_HOOK_OK;
367}
368
369static pa_card_profile *find_best_profile(pa_card *card) {
370    pa_card_profile *profile, *best_profile;
371    void *state;
372
373    pa_assert(card);
374    best_profile = pa_hashmap_get(card->profiles, "off");
375
376    PA_HASHMAP_FOREACH(profile, card->profiles, state) {
377        if (profile->available == PA_AVAILABLE_NO)
378            continue;
379
380        if (profile->priority > best_profile->priority)
381            best_profile = profile;
382    }
383
384    return best_profile;
385}
386
387static pa_hook_result_t card_profile_available_hook_callback(pa_core *c, pa_card_profile *profile, struct userdata *u) {
388    pa_card *card;
389
390    pa_assert(profile);
391    pa_assert_se(card = profile->card);
392
393    if (profile->available != PA_AVAILABLE_NO)
394        return PA_HOOK_OK;
395
396    if (!pa_streq(profile->name, card->active_profile->name))
397        return PA_HOOK_OK;
398
399    if (card->profile_is_sticky) {
400        pa_log_info("Keeping sticky card profile '%s'", profile->name);
401        return PA_HOOK_OK;
402    }
403
404    pa_log_debug("Active profile %s on card %s became unavailable, switching to another profile", profile->name, card->name);
405    pa_card_set_profile(card, find_best_profile(card), false);
406
407    return PA_HOOK_OK;
408
409}
410
411static void handle_all_unavailable(pa_core *core) {
412    pa_card *card;
413    uint32_t state;
414
415    PA_IDXSET_FOREACH(card, core->cards, state) {
416        pa_device_port *port;
417        void *state2;
418
419        PA_HASHMAP_FOREACH(port, card->ports, state2) {
420            if (port->available == PA_AVAILABLE_NO)
421                port_available_hook_callback(core, port, NULL);
422        }
423    }
424}
425
426static pa_device_port *new_sink_source(pa_hashmap *ports, const char *name) {
427
428    void *state;
429    pa_device_port *i, *p = NULL;
430
431    if (!ports)
432        return NULL;
433    if (name)
434        p = pa_hashmap_get(ports, name);
435    if (!p)
436        PA_HASHMAP_FOREACH(i, ports, state)
437            if (!p || i->priority > p->priority)
438                p = i;
439    if (!p)
440        return NULL;
441    if (p->available != PA_AVAILABLE_NO)
442        return NULL;
443
444    pa_assert_se(p = pa_device_port_find_best(ports));
445    return p;
446}
447
448static pa_hook_result_t sink_new_hook_callback(pa_core *c, pa_sink_new_data *new_data, void *u) {
449
450    pa_device_port *p = new_sink_source(new_data->ports, new_data->active_port);
451
452    if (p) {
453        pa_log_debug("Switching initial port for sink '%s' to '%s'", new_data->name, p->name);
454        pa_sink_new_data_set_port(new_data, p->name);
455    }
456    return PA_HOOK_OK;
457}
458
459static pa_hook_result_t source_new_hook_callback(pa_core *c, pa_source_new_data *new_data, void *u) {
460
461    pa_device_port *p = new_sink_source(new_data->ports, new_data->active_port);
462
463    if (p) {
464        pa_log_debug("Switching initial port for source '%s' to '%s'", new_data->name, p->name);
465        pa_source_new_data_set_port(new_data, p->name);
466    }
467    return PA_HOOK_OK;
468}
469
470static pa_hook_result_t card_put_hook_callback(pa_core *core, pa_card *card, struct userdata *u) {
471    card_info_new(u, card);
472
473    return PA_HOOK_OK;
474}
475
476static pa_hook_result_t card_unlink_hook_callback(pa_core *core, pa_card *card, struct userdata *u) {
477    card_info_free(pa_hashmap_get(u->card_infos, card));
478
479    return PA_HOOK_OK;
480}
481
482static void update_preferred_input_port(pa_card *card, pa_card_profile *old_profile, pa_card_profile *new_profile) {
483    pa_source *source;
484
485    /* If the profile change didn't affect input, it doesn't indicate change in
486     * the user's input port preference. */
487    if (pa_safe_streq(old_profile->input_name, new_profile->input_name))
488        return;
489
490    /* If there are more than one source, we don't know which of those the user
491     * prefers. If there are no sources, then the user doesn't seem to care
492     * about input at all. */
493    if (pa_idxset_size(card->sources) != 1) {
494        pa_card_set_preferred_port(card, PA_DIRECTION_INPUT, NULL);
495        return;
496    }
497
498    /* If the profile change modified the set of sinks, then it's unclear
499     * whether the user wanted to activate some specific input port, or was the
500     * input change only a side effect of activating some output. If the new
501     * profile contains no sinks, though, then we know the user only cares
502     * about input. */
503    if (pa_idxset_size(card->sinks) > 0 && !pa_safe_streq(old_profile->output_name, new_profile->output_name)) {
504        pa_card_set_preferred_port(card, PA_DIRECTION_INPUT, NULL);
505        return;
506    }
507
508    source = pa_idxset_first(card->sources, NULL);
509
510    /* We know the user wanted to activate this source. The user might not have
511     * wanted to activate the port that was selected by default, but if that's
512     * the case, the user will change the port manually, and we'll update the
513     * port preference at that time. If no port change occurs, we can assume
514     * that the user likes the port that is now active. */
515    pa_card_set_preferred_port(card, PA_DIRECTION_INPUT, source->active_port);
516}
517
518static void update_preferred_output_port(pa_card *card, pa_card_profile *old_profile, pa_card_profile *new_profile) {
519    pa_sink *sink;
520
521    /* If the profile change didn't affect output, it doesn't indicate change in
522     * the user's output port preference. */
523    if (pa_safe_streq(old_profile->output_name, new_profile->output_name))
524        return;
525
526    /* If there are more than one sink, we don't know which of those the user
527     * prefers. If there are no sinks, then the user doesn't seem to care about
528     * output at all. */
529    if (pa_idxset_size(card->sinks) != 1) {
530        pa_card_set_preferred_port(card, PA_DIRECTION_OUTPUT, NULL);
531        return;
532    }
533
534    /* If the profile change modified the set of sources, then it's unclear
535     * whether the user wanted to activate some specific output port, or was
536     * the output change only a side effect of activating some input. If the
537     * new profile contains no sources, though, then we know the user only
538     * cares about output. */
539    if (pa_idxset_size(card->sources) > 0 && !pa_safe_streq(old_profile->input_name, new_profile->input_name)) {
540        pa_card_set_preferred_port(card, PA_DIRECTION_OUTPUT, NULL);
541        return;
542    }
543
544    sink = pa_idxset_first(card->sinks, NULL);
545
546    /* We know the user wanted to activate this sink. The user might not have
547     * wanted to activate the port that was selected by default, but if that's
548     * the case, the user will change the port manually, and we'll update the
549     * port preference at that time. If no port change occurs, we can assume
550     * that the user likes the port that is now active. */
551    pa_card_set_preferred_port(card, PA_DIRECTION_OUTPUT, sink->active_port);
552}
553
554static pa_hook_result_t card_profile_changed_callback(pa_core *core, pa_card *card, struct userdata *u) {
555    struct card_info *info;
556    pa_card_profile *old_profile;
557    pa_card_profile *new_profile;
558
559    info = pa_hashmap_get(u->card_infos, card);
560    old_profile = info->active_profile;
561    new_profile = card->active_profile;
562    info->active_profile = new_profile;
563
564    /* This profile change wasn't initiated by the user, so it doesn't signal
565     * a change in the user's port preferences. */
566    if (!card->save_profile)
567        return PA_HOOK_OK;
568
569    update_preferred_input_port(card, old_profile, new_profile);
570    update_preferred_output_port(card, old_profile, new_profile);
571
572    return PA_HOOK_OK;
573}
574
575static pa_hook_result_t source_port_changed_callback(pa_core *core, pa_source *source, void *userdata) {
576    if (!source->save_port)
577        return PA_HOOK_OK;
578
579    pa_card_set_preferred_port(source->card, PA_DIRECTION_INPUT, source->active_port);
580
581    return PA_HOOK_OK;
582}
583
584static pa_hook_result_t sink_port_changed_callback(pa_core *core, pa_sink *sink, void *userdata) {
585    if (!sink->save_port)
586        return PA_HOOK_OK;
587
588    pa_card_set_preferred_port(sink->card, PA_DIRECTION_OUTPUT, sink->active_port);
589
590    return PA_HOOK_OK;
591}
592
593int pa__init(pa_module*m) {
594    struct userdata *u;
595    pa_card *card;
596    uint32_t idx;
597
598    pa_assert(m);
599
600    u = m->userdata = pa_xnew0(struct userdata, 1);
601    u->card_infos = pa_hashmap_new(NULL, NULL);
602
603    PA_IDXSET_FOREACH(card, m->core->cards, idx)
604        card_info_new(u, card);
605
606    /* Make sure we are after module-device-restore, so we can overwrite that suggestion if necessary */
607    pa_module_hook_connect(m, &m->core->hooks[PA_CORE_HOOK_SINK_NEW],
608                           PA_HOOK_NORMAL, (pa_hook_cb_t) sink_new_hook_callback, NULL);
609    pa_module_hook_connect(m, &m->core->hooks[PA_CORE_HOOK_SOURCE_NEW],
610                           PA_HOOK_NORMAL, (pa_hook_cb_t) source_new_hook_callback, NULL);
611    pa_module_hook_connect(m, &m->core->hooks[PA_CORE_HOOK_PORT_AVAILABLE_CHANGED],
612                           PA_HOOK_LATE, (pa_hook_cb_t) port_available_hook_callback, NULL);
613    pa_module_hook_connect(m, &m->core->hooks[PA_CORE_HOOK_CARD_PROFILE_AVAILABLE_CHANGED],
614                           PA_HOOK_LATE, (pa_hook_cb_t) card_profile_available_hook_callback, NULL);
615    pa_module_hook_connect(m, &m->core->hooks[PA_CORE_HOOK_CARD_PUT],
616                           PA_HOOK_NORMAL, (pa_hook_cb_t) card_put_hook_callback, u);
617    pa_module_hook_connect(m, &m->core->hooks[PA_CORE_HOOK_CARD_UNLINK],
618                           PA_HOOK_NORMAL, (pa_hook_cb_t) card_unlink_hook_callback, u);
619    pa_module_hook_connect(m, &m->core->hooks[PA_CORE_HOOK_CARD_PROFILE_CHANGED],
620                           PA_HOOK_NORMAL, (pa_hook_cb_t) card_profile_changed_callback, u);
621    pa_module_hook_connect(m, &m->core->hooks[PA_CORE_HOOK_SOURCE_PORT_CHANGED],
622                           PA_HOOK_NORMAL, (pa_hook_cb_t) source_port_changed_callback, NULL);
623    pa_module_hook_connect(m, &m->core->hooks[PA_CORE_HOOK_SINK_PORT_CHANGED],
624                           PA_HOOK_NORMAL, (pa_hook_cb_t) sink_port_changed_callback, NULL);
625
626    handle_all_unavailable(m->core);
627
628    return 0;
629}
630
631void pa__done(pa_module *module) {
632    struct userdata *u;
633    struct card_info *info;
634
635    pa_assert(module);
636
637    if (!(u = module->userdata))
638        return;
639
640    while ((info = pa_hashmap_last(u->card_infos)))
641        card_info_free(info);
642
643    pa_hashmap_free(u->card_infos);
644
645    pa_xfree(u);
646}
647