]>
code.delx.au - pulseaudio/blob - src/modules/module-switch-on-connect.c
2 This file is part of PulseAudio.
4 Copyright 2006 Lennart Poettering
5 Copyright 2009 Canonical Ltd
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.
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.
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
27 #include <pulse/xmalloc.h>
29 #include <pulsecore/core.h>
30 #include <pulsecore/sink-input.h>
31 #include <pulsecore/source-output.h>
32 #include <pulsecore/source.h>
33 #include <pulsecore/modargs.h>
34 #include <pulsecore/log.h>
35 #include <pulsecore/namereg.h>
36 #include <pulsecore/core-util.h>
38 #include "module-switch-on-connect-symdef.h"
40 PA_MODULE_AUTHOR("Michael Terry");
41 PA_MODULE_DESCRIPTION("When a sink/source is added, switch to it");
42 PA_MODULE_VERSION(PACKAGE_VERSION
);
43 PA_MODULE_LOAD_ONCE(true);
45 static const char* const valid_modargs
[] = {
55 static pa_hook_result_t
sink_put_hook_callback(pa_core
*c
, pa_sink
*sink
, void* userdata
) {
64 /* Don't want to run during startup or shutdown */
65 if (c
->state
!= PA_CORE_RUNNING
)
68 /* Don't switch to any internal devices */
69 if ((s
= pa_proplist_gets(sink
->proplist
, PA_PROP_DEVICE_BUS
))) {
70 if (pa_streq(s
, "pci"))
72 else if (pa_streq(s
, "isa"))
76 def
= pa_namereg_get_default_sink(c
);
80 /* Actually do the switch to the new sink */
81 pa_namereg_set_default_sink(c
, sink
);
83 /* Now move all old inputs over */
84 if (pa_idxset_size(def
->inputs
) <= 0) {
85 pa_log_debug("No sink inputs to move away.");
89 PA_IDXSET_FOREACH(i
, def
->inputs
, idx
) {
90 if (i
->save_sink
|| !PA_SINK_INPUT_IS_LINKED(i
->state
))
93 if (pa_sink_input_move_to(i
, sink
, false) < 0)
94 pa_log_info("Failed to move sink input %u \"%s\" to %s.", i
->index
,
95 pa_strnull(pa_proplist_gets(i
->proplist
, PA_PROP_APPLICATION_NAME
)), sink
->name
);
97 pa_log_info("Successfully moved sink input %u \"%s\" to %s.", i
->index
,
98 pa_strnull(pa_proplist_gets(i
->proplist
, PA_PROP_APPLICATION_NAME
)), sink
->name
);
104 static pa_hook_result_t
source_put_hook_callback(pa_core
*c
, pa_source
*source
, void* userdata
) {
113 /* Don't want to run during startup or shutdown */
114 if (c
->state
!= PA_CORE_RUNNING
)
117 /* Don't switch to a monitoring source */
118 if (source
->monitor_of
)
121 /* Don't switch to any internal devices */
122 if ((s
= pa_proplist_gets(source
->proplist
, PA_PROP_DEVICE_BUS
))) {
123 if (pa_streq(s
, "pci"))
125 else if (pa_streq(s
, "isa"))
129 def
= pa_namereg_get_default_source(c
);
133 /* Actually do the switch to the new source */
134 pa_namereg_set_default_source(c
, source
);
136 /* Now move all old outputs over */
137 if (pa_idxset_size(def
->outputs
) <= 0) {
138 pa_log_debug("No source outputs to move away.");
142 PA_IDXSET_FOREACH(o
, def
->outputs
, idx
) {
143 if (o
->save_source
|| !PA_SOURCE_OUTPUT_IS_LINKED(o
->state
))
146 if (pa_source_output_move_to(o
, source
, false) < 0)
147 pa_log_info("Failed to move source output %u \"%s\" to %s.", o
->index
,
148 pa_strnull(pa_proplist_gets(o
->proplist
, PA_PROP_APPLICATION_NAME
)), source
->name
);
150 pa_log_info("Successfully moved source output %u \"%s\" to %s.", o
->index
,
151 pa_strnull(pa_proplist_gets(o
->proplist
, PA_PROP_APPLICATION_NAME
)), source
->name
);
157 int pa__init(pa_module
*m
) {
163 if (!(ma
= pa_modargs_new(m
->argument
, valid_modargs
))) {
164 pa_log("Failed to parse module arguments");
168 m
->userdata
= u
= pa_xnew(struct userdata
, 1);
170 /* A little bit later than module-rescue-streams... */
171 u
->sink_put_slot
= pa_hook_connect(&m
->core
->hooks
[PA_CORE_HOOK_SINK_PUT
], PA_HOOK_LATE
+30, (pa_hook_cb_t
) sink_put_hook_callback
, u
);
172 u
->source_put_slot
= pa_hook_connect(&m
->core
->hooks
[PA_CORE_HOOK_SOURCE_PUT
], PA_HOOK_LATE
+20, (pa_hook_cb_t
) source_put_hook_callback
, u
);
178 void pa__done(pa_module
*m
) {
183 if (!(u
= m
->userdata
))
186 if (u
->sink_put_slot
)
187 pa_hook_slot_free(u
->sink_put_slot
);
188 if (u
->source_put_slot
)
189 pa_hook_slot_free(u
->source_put_slot
);