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/sink.h>
24 #include <pulsecore/card.h>
33 struct pa_card_hooks {
36 pa_hook_slot *profchg;
39 struct pa_port_hooks {
43 struct pa_sink_hooks {
46 pa_hook_slot *portchg;
49 struct pa_source_hooks {
52 pa_hook_slot *portchg;
55 struct pa_sink_input_hooks {
61 struct pa_source_output_hooks {
72 pa_source_hooks source;
73 pa_sink_input_hooks sink_input;
74 pa_source_output_hooks source_output;
78 static pa_hook_result_t card_put(void *, void *, void *);
79 static pa_hook_result_t card_unlink(void *, void *, void *);
80 static pa_hook_result_t card_profile_changed(void *, void *, void *);
82 static pa_hook_result_t port_available_changed(void *, void *, void *);
84 static pa_hook_result_t sink_put(void *, void *, void *);
85 static pa_hook_result_t sink_unlink(void *, void *, void *);
86 static pa_hook_result_t sink_port_changed(void *, void *, void *);
88 static pa_hook_result_t source_put(void *, void *, void *);
89 static pa_hook_result_t source_unlink(void *, void *, void *);
90 static pa_hook_result_t source_port_changed(void *, void *, void *);
92 static pa_hook_result_t sink_input_new(void *, void *, void *);
93 static pa_hook_result_t sink_input_put(void *, void *, void *);
94 static pa_hook_result_t sink_input_unlink(void *, void *, void *);
96 static pa_hook_result_t source_output_new(void *, void *, void *);
97 static pa_hook_result_t source_output_put(void *, void *, void *);
98 static pa_hook_result_t source_output_unlink(void *, void *, void *);
101 pa_tracker *pa_tracker_init(struct userdata *u)
109 pa_source_hooks *source;
110 pa_sink_input_hooks *sinp;
111 pa_source_output_hooks *sout;
114 pa_assert_se((core = u->core));
115 pa_assert_se((hooks = core->hooks));
117 tracker = pa_xnew0(pa_tracker, 1);
118 card = &tracker->card;
119 port = &tracker->port;
120 sink = &tracker->sink;
121 source = &tracker->source;
122 sinp = &tracker->sink_input;
123 sout = &tracker->source_output;
126 card->put = pa_hook_connect(
127 hooks + PA_CORE_HOOK_CARD_PUT,
128 PA_HOOK_LATE, card_put, u
130 card->unlink = pa_hook_connect(
131 hooks + PA_CORE_HOOK_CARD_UNLINK,
132 PA_HOOK_LATE, card_unlink, u
134 card->profchg = pa_hook_connect(
135 hooks + PA_CORE_HOOK_CARD_PROFILE_CHANGED,
136 PA_HOOK_LATE, card_profile_changed, u
139 port->avail = pa_hook_connect(
140 hooks + PA_CORE_HOOK_PORT_AVAILABLE_CHANGED,
141 PA_HOOK_LATE, port_available_changed, u
144 sink->put = pa_hook_connect(
145 hooks + PA_CORE_HOOK_SINK_PUT,
146 PA_HOOK_LATE, sink_put, u
148 sink->unlink = pa_hook_connect(
149 hooks + PA_CORE_HOOK_SINK_UNLINK,
150 PA_HOOK_LATE, sink_unlink, u
152 sink->portchg = pa_hook_connect(
153 hooks + PA_CORE_HOOK_SINK_PORT_CHANGED,
154 PA_HOOK_LATE, sink_port_changed, u
157 source->put = pa_hook_connect(
158 hooks + PA_CORE_HOOK_SOURCE_PUT,
159 PA_HOOK_LATE, source_put, u
161 source->unlink = pa_hook_connect(
162 hooks + PA_CORE_HOOK_SOURCE_UNLINK,
163 PA_HOOK_LATE, source_unlink, u
165 source->portchg = pa_hook_connect(
166 hooks + PA_CORE_HOOK_SOURCE_PORT_CHANGED,
167 PA_HOOK_LATE, source_port_changed, u
170 sinp->neew = pa_hook_connect(
171 hooks + PA_CORE_HOOK_SINK_INPUT_NEW,
172 PA_HOOK_EARLY, sink_input_new, u
174 sinp->put = pa_hook_connect(
175 hooks + PA_CORE_HOOK_SINK_INPUT_PUT,
176 PA_HOOK_LATE, sink_input_put, u
178 sinp->unlink = pa_hook_connect(
179 hooks + PA_CORE_HOOK_SINK_INPUT_UNLINK,
180 PA_HOOK_LATE, sink_input_unlink, u
184 sout->neew = pa_hook_connect(
185 hooks + PA_CORE_HOOK_SOURCE_OUTPUT_NEW,
186 PA_HOOK_EARLY, source_output_new, u
188 sout->put = pa_hook_connect(
189 hooks + PA_CORE_HOOK_SOURCE_OUTPUT_PUT,
190 PA_HOOK_LATE, source_output_put, u
192 sout->unlink = pa_hook_connect(
193 hooks + PA_CORE_HOOK_SOURCE_OUTPUT_UNLINK,
194 PA_HOOK_LATE, source_output_unlink, u
200 void pa_tracker_done(struct userdata *u)
206 pa_source_hooks *source;
207 pa_sink_input_hooks *sinp;
209 if (u && (tracker = u->tracker)) {
211 card = &tracker->card;
212 pa_hook_slot_free(card->put);
213 pa_hook_slot_free(card->unlink);
214 pa_hook_slot_free(card->profchg);
216 port = &tracker->port;
217 pa_hook_slot_free(port->avail);
219 sink = &tracker->sink;
220 pa_hook_slot_free(sink->put);
221 pa_hook_slot_free(sink->unlink);
222 pa_hook_slot_free(sink->portchg);
224 source = &tracker->source;
225 pa_hook_slot_free(source->put);
226 pa_hook_slot_free(source->unlink);
227 pa_hook_slot_free(source->portchg);
229 sinp = &tracker->sink_input;
230 pa_hook_slot_free(sinp->neew);
231 pa_hook_slot_free(sinp->put);
232 pa_hook_slot_free(sinp->unlink);
240 void pa_tracker_synchronize(struct userdata *u)
247 pa_source_output *sout;
251 pa_assert_se((core = u->core));
254 PA_IDXSET_FOREACH(card, core->cards, index) {
255 pa_discover_add_card(u, card);
258 PA_IDXSET_FOREACH(sink, core->sinks, index) {
259 pa_discover_add_sink(u, sink, FALSE);
262 PA_IDXSET_FOREACH(source, core->sources, index) {
263 pa_discover_add_source(u, source);
266 /* Hmm... we should first collect all sink-inputs & source-outputs, assign
267 priority to them, sort them, and call pa_discover_register_sink_input()
268 in reverse priority order. Until than we may experience sound leaks
269 unnecessary profile changes etc ... */
271 PA_IDXSET_FOREACH(sinp, core->sink_inputs, index) {
272 pa_discover_register_sink_input(u, sinp);
275 PA_IDXSET_FOREACH(sout, core->source_outputs, index) {
276 pa_discover_register_source_output(u, sout);
279 mir_router_make_routing(u);
283 static pa_hook_result_t card_put(void *hook_data,
287 pa_card *card = (pa_card *)call_data;
288 struct userdata *u = (struct userdata *)slot_data;
293 pa_discover_add_card(u, card);
298 static pa_hook_result_t card_unlink(void *hook_data,
302 pa_card *card = (pa_card *)call_data;
303 struct userdata *u = (struct userdata *)slot_data;
309 pa_discover_remove_card(u, card);
311 mir_router_print_rtgroups(u, buf, sizeof(buf));
312 pa_log_debug("%s", buf);
314 mir_router_make_routing(u);
320 static pa_hook_result_t card_profile_changed(void *hook_data,
324 pa_card *card = (pa_card *)call_data;
325 struct userdata *u = (struct userdata *)slot_data;
330 pa_discover_profile_changed(u, card);
336 static pa_hook_result_t port_available_changed(void *hook_data,
340 pa_device_port *port = (pa_device_port *)call_data;
341 struct userdata *u = (struct userdata *)slot_data;
346 pa_discover_port_available_changed(u, port);
353 static pa_hook_result_t sink_put(void *hook_data,
357 pa_sink *sink = (pa_sink *)call_data;
358 struct userdata *u = (struct userdata *)slot_data;
363 pa_discover_add_sink(u, sink, TRUE);
369 static pa_hook_result_t sink_unlink(void *hook_data,
373 pa_sink *sink = (pa_sink *)call_data;
374 struct userdata *u = (struct userdata *)slot_data;
379 pa_discover_remove_sink(u, sink);
385 static pa_hook_result_t sink_port_changed(void *hook_data,
389 pa_sink *sink = (pa_sink *)call_data;
390 struct userdata *u = (struct userdata *)slot_data;
400 static pa_hook_result_t source_put(void *hook_data,
404 pa_source *source = (pa_source *)call_data;
405 struct userdata *u = (struct userdata *)slot_data;
410 pa_discover_add_source(u, source);
416 static pa_hook_result_t source_unlink(void *hook_data,
420 pa_source *source = (pa_source *)call_data;
421 struct userdata *u = (struct userdata *)slot_data;
426 pa_discover_remove_source(u, source);
432 static pa_hook_result_t source_port_changed(void *hook_data,
436 pa_source *source = (pa_source *)call_data;
437 struct userdata *u = (struct userdata *)slot_data;
447 static pa_hook_result_t sink_input_new(void *hook_data,
451 pa_sink_input_new_data *data = (pa_sink_input_new_data *)call_data;
452 struct userdata *u = (struct userdata *)slot_data;
458 success = pa_discover_preroute_sink_input(u, data);
460 return success ? PA_HOOK_OK : PA_HOOK_CANCEL;
463 static pa_hook_result_t sink_input_put(void *hook_data,
467 pa_sink_input *sinp = (pa_sink_input *)call_data;
468 struct userdata *u = (struct userdata *)slot_data;
473 pa_discover_add_sink_input(u, sinp);
479 static pa_hook_result_t sink_input_unlink(void *hook_data,
483 struct pa_sink_input *sinp = (pa_sink_input *)call_data;
484 struct userdata *u = (struct userdata *)slot_data;
489 pa_discover_remove_sink_input(u, sinp);
495 static pa_hook_result_t source_output_new(void *hook_data,
499 pa_source_output_new_data *data = (pa_source_output_new_data *)call_data;
500 struct userdata *u = (struct userdata *)slot_data;
506 success = pa_discover_preroute_source_output(u, data);
508 return success ? PA_HOOK_OK : PA_HOOK_CANCEL;
511 static pa_hook_result_t source_output_put(void *hook_data,
515 pa_source_output *sout = (pa_source_output *)call_data;
516 struct userdata *u = (struct userdata *)slot_data;
521 pa_discover_add_source_output(u, sout);
527 static pa_hook_result_t source_output_unlink(void *hook_data,
531 struct pa_source_output *sout = (pa_source_output *)call_data;
532 struct userdata *u = (struct userdata *)slot_data;
537 pa_discover_remove_source_output(u, sout);
546 * indent-tabs-mode: nil