2 * module-murphy-ivi -- PulseAudio module for providing audio routing support
3 * Copyright (c) 2012, Intel Corporation.
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU Lesser General Public License,
7 * version 2.1, as published by the Free Software Foundation.
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE.
12 * See the GNU Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public License
15 * along with this program; if not, write to the
16 * Free Software Foundation, Inc., 51 Franklin St - Fifth Floor, Boston,
20 #include <pulsecore/pulsecore-config.h>
22 #include <pulse/def.h>
23 #include <pulsecore/card.h>
32 struct pa_card_hooks {
35 pa_hook_slot *profchg;
38 struct pa_port_hooks {
42 struct pa_sink_hooks {
45 pa_hook_slot *portchg;
48 struct pa_source_hooks {
51 pa_hook_slot *portchg;
54 struct pa_sink_input_hooks {
60 struct pa_source_output_hooks {
71 pa_source_hooks source;
72 pa_sink_input_hooks sink_input;
73 pa_source_output_hooks source_output;
77 static pa_hook_result_t card_put(void *, void *, void *);
78 static pa_hook_result_t card_unlink(void *, void *, void *);
79 static pa_hook_result_t card_profile_changed(void *, void *, void *);
81 static pa_hook_result_t port_available_changed(void *, void *, void *);
83 static pa_hook_result_t sink_put(void *, void *, void *);
84 static pa_hook_result_t sink_unlink(void *, void *, void *);
85 static pa_hook_result_t sink_port_changed(void *, void *, void *);
87 static pa_hook_result_t source_put(void *, void *, void *);
88 static pa_hook_result_t source_unlink(void *, void *, void *);
89 static pa_hook_result_t source_port_changed(void *, void *, void *);
91 static pa_hook_result_t sink_input_new(void *, void *, void *);
92 static pa_hook_result_t sink_input_put(void *, void *, void *);
93 static pa_hook_result_t sink_input_unlink(void *, void *, void *);
95 static pa_hook_result_t source_output_new(void *, void *, void *);
96 static pa_hook_result_t source_output_put(void *, void *, void *);
97 static pa_hook_result_t source_output_unlink(void *, void *, void *);
100 pa_tracker *pa_tracker_init(struct userdata *u)
108 pa_source_hooks *source;
109 pa_sink_input_hooks *sinp;
110 pa_source_output_hooks *sout;
113 pa_assert_se((core = u->core));
114 pa_assert_se((hooks = core->hooks));
116 tracker = pa_xnew0(pa_tracker, 1);
117 card = &tracker->card;
118 port = &tracker->port;
119 sink = &tracker->sink;
120 source = &tracker->source;
121 sinp = &tracker->sink_input;
122 sout = &tracker->source_output;
125 card->put = pa_hook_connect(
126 hooks + PA_CORE_HOOK_CARD_PUT,
127 PA_HOOK_LATE, card_put, u
129 card->unlink = pa_hook_connect(
130 hooks + PA_CORE_HOOK_CARD_UNLINK,
131 PA_HOOK_LATE, card_unlink, u
133 card->profchg = pa_hook_connect(
134 hooks + PA_CORE_HOOK_CARD_PROFILE_CHANGED,
135 PA_HOOK_LATE, card_profile_changed, u
138 port->avail = pa_hook_connect(
139 hooks + PA_CORE_HOOK_PORT_AVAILABLE_CHANGED,
140 PA_HOOK_LATE, port_available_changed, u
143 sink->put = pa_hook_connect(
144 hooks + PA_CORE_HOOK_SINK_PUT,
145 PA_HOOK_LATE, sink_put, u
147 sink->unlink = pa_hook_connect(
148 hooks + PA_CORE_HOOK_SINK_UNLINK,
149 PA_HOOK_LATE, sink_unlink, u
151 sink->portchg = pa_hook_connect(
152 hooks + PA_CORE_HOOK_SINK_PORT_CHANGED,
153 PA_HOOK_LATE, sink_port_changed, u
156 source->put = pa_hook_connect(
157 hooks + PA_CORE_HOOK_SOURCE_PUT,
158 PA_HOOK_LATE, source_put, u
160 source->unlink = pa_hook_connect(
161 hooks + PA_CORE_HOOK_SOURCE_UNLINK,
162 PA_HOOK_LATE, source_unlink, u
164 source->portchg = pa_hook_connect(
165 hooks + PA_CORE_HOOK_SOURCE_PORT_CHANGED,
166 PA_HOOK_LATE, source_port_changed, u
169 sinp->neew = pa_hook_connect(
170 hooks + PA_CORE_HOOK_SINK_INPUT_NEW,
171 PA_HOOK_EARLY, sink_input_new, u
173 sinp->put = pa_hook_connect(
174 hooks + PA_CORE_HOOK_SINK_INPUT_PUT,
175 PA_HOOK_LATE, sink_input_put, u
177 sinp->unlink = pa_hook_connect(
178 hooks + PA_CORE_HOOK_SINK_INPUT_UNLINK,
179 PA_HOOK_LATE, sink_input_unlink, u
183 sout->neew = pa_hook_connect(
184 hooks + PA_CORE_HOOK_SOURCE_OUTPUT_NEW,
185 PA_HOOK_EARLY, source_output_new, u
187 sout->put = pa_hook_connect(
188 hooks + PA_CORE_HOOK_SOURCE_OUTPUT_PUT,
189 PA_HOOK_LATE, source_output_put, u
191 sout->unlink = pa_hook_connect(
192 hooks + PA_CORE_HOOK_SOURCE_OUTPUT_UNLINK,
193 PA_HOOK_LATE, source_output_unlink, u
199 void pa_tracker_done(struct userdata *u)
205 pa_source_hooks *source;
206 pa_sink_input_hooks *sinp;
208 if (u && (tracker = u->tracker)) {
210 card = &tracker->card;
211 pa_hook_slot_free(card->put);
212 pa_hook_slot_free(card->unlink);
213 pa_hook_slot_free(card->profchg);
215 port = &tracker->port;
216 pa_hook_slot_free(port->avail);
218 sink = &tracker->sink;
219 pa_hook_slot_free(sink->put);
220 pa_hook_slot_free(sink->unlink);
221 pa_hook_slot_free(sink->portchg);
223 source = &tracker->source;
224 pa_hook_slot_free(source->put);
225 pa_hook_slot_free(source->unlink);
226 pa_hook_slot_free(source->portchg);
228 sinp = &tracker->sink_input;
229 pa_hook_slot_free(sinp->neew);
230 pa_hook_slot_free(sinp->put);
231 pa_hook_slot_free(sinp->unlink);
239 void pa_tracker_synchronize(struct userdata *u)
246 pa_source_output *sout;
250 pa_assert_se((core = u->core));
253 PA_IDXSET_FOREACH(card, core->cards, index) {
254 pa_discover_add_card(u, card);
257 PA_IDXSET_FOREACH(sink, core->sinks, index) {
258 pa_discover_add_sink(u, sink, FALSE);
261 PA_IDXSET_FOREACH(source, core->sources, index) {
262 pa_discover_add_source(u, source);
265 /* Hmm... we should first collect all sink-inputs & source-outputs, assign
266 priority to them, sort them, and call pa_discover_register_sink_input()
267 in reverse priority order. Until than we may experience sound leaks
268 unnecessary profile changes etc ... */
270 PA_IDXSET_FOREACH(sinp, core->sink_inputs, index) {
271 pa_discover_register_sink_input(u, sinp);
274 PA_IDXSET_FOREACH(sout, core->source_outputs, index) {
275 pa_discover_register_source_output(u, sout);
278 mir_router_make_routing(u);
282 static pa_hook_result_t card_put(void *hook_data,
286 pa_card *card = (pa_card *)call_data;
287 struct userdata *u = (struct userdata *)slot_data;
292 pa_discover_add_card(u, card);
297 static pa_hook_result_t card_unlink(void *hook_data,
301 pa_card *card = (pa_card *)call_data;
302 struct userdata *u = (struct userdata *)slot_data;
308 pa_discover_remove_card(u, card);
310 mir_router_print_rtgroups(u, buf, sizeof(buf));
311 pa_log_debug("%s", buf);
313 mir_router_make_routing(u);
319 static pa_hook_result_t card_profile_changed(void *hook_data,
323 pa_card *card = (pa_card *)call_data;
324 struct userdata *u = (struct userdata *)slot_data;
329 pa_discover_profile_changed(u, card);
335 static pa_hook_result_t port_available_changed(void *hook_data,
339 pa_device_port *port = (pa_device_port *)call_data;
340 struct userdata *u = (struct userdata *)slot_data;
345 pa_discover_port_available_changed(u, port);
352 static pa_hook_result_t sink_put(void *hook_data,
356 pa_sink *sink = (pa_sink *)call_data;
357 struct userdata *u = (struct userdata *)slot_data;
362 pa_discover_add_sink(u, sink, TRUE);
368 static pa_hook_result_t sink_unlink(void *hook_data,
372 pa_sink *sink = (pa_sink *)call_data;
373 struct userdata *u = (struct userdata *)slot_data;
378 pa_discover_remove_sink(u, sink);
384 static pa_hook_result_t sink_port_changed(void *hook_data,
388 pa_sink *sink = (pa_sink *)call_data;
389 struct userdata *u = (struct userdata *)slot_data;
399 static pa_hook_result_t source_put(void *hook_data,
403 pa_source *source = (pa_source *)call_data;
404 struct userdata *u = (struct userdata *)slot_data;
409 pa_discover_add_source(u, source);
415 static pa_hook_result_t source_unlink(void *hook_data,
419 pa_source *source = (pa_source *)call_data;
420 struct userdata *u = (struct userdata *)slot_data;
425 pa_discover_remove_source(u, source);
431 static pa_hook_result_t source_port_changed(void *hook_data,
435 pa_source *source = (pa_source *)call_data;
436 struct userdata *u = (struct userdata *)slot_data;
446 static pa_hook_result_t sink_input_new(void *hook_data,
450 pa_sink_input_new_data *data = (pa_sink_input_new_data *)call_data;
451 struct userdata *u = (struct userdata *)slot_data;
456 pa_discover_preroute_sink_input(u, data);
461 static pa_hook_result_t sink_input_put(void *hook_data,
465 pa_sink_input *sinp = (pa_sink_input *)call_data;
466 struct userdata *u = (struct userdata *)slot_data;
471 pa_discover_add_sink_input(u, sinp);
477 static pa_hook_result_t sink_input_unlink(void *hook_data,
481 struct pa_sink_input *sinp = (pa_sink_input *)call_data;
482 struct userdata *u = (struct userdata *)slot_data;
487 pa_discover_remove_sink_input(u, sinp);
493 static pa_hook_result_t source_output_new(void *hook_data,
497 pa_source_output_new_data *data = (pa_source_output_new_data *)call_data;
498 struct userdata *u = (struct userdata *)slot_data;
503 pa_discover_preroute_source_output(u, data);
508 static pa_hook_result_t source_output_put(void *hook_data,
512 pa_source_output *sout = (pa_source_output *)call_data;
513 struct userdata *u = (struct userdata *)slot_data;
518 pa_discover_add_source_output(u, sout);
524 static pa_hook_result_t source_output_unlink(void *hook_data,
528 struct pa_source_output *sout = (pa_source_output *)call_data;
529 struct userdata *u = (struct userdata *)slot_data;
534 pa_discover_remove_source_output(u, sout);
543 * indent-tabs-mode: nil