2 * module-agl-audio -- PulseAudio module for providing audio routing support
3 * (forked from "module-murphy-ivi" - https://github.com/otcshare )
4 * Copyright (c) 2012, Intel Corporation.
5 * Copyright (c) 2016, IoT.bzh
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms and conditions of the GNU Lesser General Public License,
9 * version 2.1, as published by the Free Software Foundation.
11 * This program is distributed in the hope it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE.
14 * See the GNU Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program; if not, write to the
18 * Free Software Foundation, Inc., 51 Franklin St - Fifth Floor, Boston,
27 struct pa_card_hooks {
30 pa_hook_slot *profchg;
33 struct pa_port_hooks {
37 struct pa_sink_hooks {
40 pa_hook_slot *portchg;
43 struct pa_source_hooks {
46 pa_hook_slot *portchg;
49 struct pa_sink_input_hooks {
55 struct pa_source_output_hooks {
65 pa_source_hooks source;
66 pa_sink_input_hooks sink_input;
67 pa_source_output_hooks source_output;
71 static pa_hook_result_t card_put (void *, void *, void *);
72 static pa_hook_result_t card_unlink (void *, void *, void *);
73 static pa_hook_result_t card_profile_changed (void *, void *, void *);
75 static pa_hook_result_t port_available_changed (void *, void *, void *);
77 static pa_hook_result_t sink_put (void *, void *, void *);
78 static pa_hook_result_t sink_unlink (void *, void *, void *);
79 static pa_hook_result_t sink_port_changed (void *, void *, void *);
81 static pa_hook_result_t source_put (void *, void *, void *);
82 static pa_hook_result_t source_unlink (void *, void *, void *);
83 static pa_hook_result_t source_port_changed (void *, void *, void *);
85 static pa_hook_result_t sink_input_new (void *, void *, void *);
86 static pa_hook_result_t sink_input_put (void *, void *, void *);
87 static pa_hook_result_t sink_input_unlink (void *, void *, void *);
89 static pa_hook_result_t source_output_new (void *, void *, void *);
90 static pa_hook_result_t source_output_put (void *, void *, void *);
91 static pa_hook_result_t source_output_unlink (void *, void *, void *);
94 agl_tracker *agl_tracker_init (struct userdata *u)
102 pa_source_hooks *source;
103 pa_sink_input_hooks *sinp;
104 pa_source_output_hooks *sout;
107 pa_assert_se (core = u->core);
108 pa_assert_se (hooks = core->hooks);
110 tracker = pa_xnew0 (agl_tracker, 1);
111 card = &tracker->card;
112 port = &tracker->port;
113 sink = &tracker->sink;
114 source = &tracker->source;
115 sinp = &tracker->sink_input;
116 sout = &tracker->source_output;
119 card->put = pa_hook_connect (hooks + PA_CORE_HOOK_CARD_PUT,
120 PA_HOOK_LATE, card_put, u);
121 card->unlink = pa_hook_connect (hooks + PA_CORE_HOOK_CARD_UNLINK,
122 PA_HOOK_LATE, card_unlink, u);
123 card->profchg = pa_hook_connect (hooks + PA_CORE_HOOK_CARD_PROFILE_CHANGED,
124 PA_HOOK_LATE, card_profile_changed, u);
127 port->avail = pa_hook_connect (hooks + PA_CORE_HOOK_PORT_AVAILABLE_CHANGED,
128 PA_HOOK_LATE, port_available_changed, u);
131 sink->put = pa_hook_connect (hooks + PA_CORE_HOOK_SINK_PUT,
132 PA_HOOK_LATE, sink_put, u);
133 sink->unlink = pa_hook_connect (hooks + PA_CORE_HOOK_SINK_UNLINK,
134 PA_HOOK_LATE, sink_unlink, u);
135 sink->portchg = pa_hook_connect (hooks + PA_CORE_HOOK_SINK_PORT_CHANGED,
136 PA_HOOK_LATE, sink_port_changed, u);
139 source->put = pa_hook_connect (hooks + PA_CORE_HOOK_SOURCE_PUT,
140 PA_HOOK_LATE, source_put, u);
141 source->unlink = pa_hook_connect (hooks + PA_CORE_HOOK_SOURCE_UNLINK,
142 PA_HOOK_LATE, source_unlink, u);
143 source->portchg = pa_hook_connect (hooks + PA_CORE_HOOK_SOURCE_PORT_CHANGED,
144 PA_HOOK_LATE, source_port_changed, u);
147 sinp->neew = pa_hook_connect (hooks + PA_CORE_HOOK_SINK_INPUT_NEW,
148 PA_HOOK_EARLY, sink_input_new, u);
149 sinp->put = pa_hook_connect (hooks + PA_CORE_HOOK_SINK_INPUT_PUT,
150 PA_HOOK_LATE, sink_input_put, u);
151 sinp->unlink = pa_hook_connect (hooks + PA_CORE_HOOK_SINK_INPUT_UNLINK,
152 PA_HOOK_LATE, sink_input_unlink, u);
155 sout->neew = pa_hook_connect (hooks + PA_CORE_HOOK_SOURCE_OUTPUT_NEW,
156 PA_HOOK_EARLY, source_output_new, u);
157 sout->put = pa_hook_connect (hooks + PA_CORE_HOOK_SOURCE_OUTPUT_PUT,
158 PA_HOOK_LATE, source_output_put, u);
159 sout->unlink = pa_hook_connect (hooks + PA_CORE_HOOK_SOURCE_OUTPUT_UNLINK,
160 PA_HOOK_LATE, source_output_unlink, u);
165 void agl_tracker_done (struct userdata *u)
167 agl_tracker *tracker;
171 pa_source_hooks *source;
172 pa_sink_input_hooks *sinp;
174 if (u && (tracker = u->tracker)) {
176 card = &tracker->card;
177 pa_hook_slot_free (card->put);
178 pa_hook_slot_free (card->unlink);
179 pa_hook_slot_free (card->profchg);
181 port = &tracker->port;
182 pa_hook_slot_free (port->avail);
184 sink = &tracker->sink;
185 pa_hook_slot_free (sink->put);
186 pa_hook_slot_free (sink->unlink);
187 pa_hook_slot_free (sink->portchg);
189 source = &tracker->source;
190 pa_hook_slot_free (source->put);
191 pa_hook_slot_free (source->unlink);
192 pa_hook_slot_free (source->portchg);
194 sinp = &tracker->sink_input;
195 pa_hook_slot_free (sinp->neew);
196 pa_hook_slot_free (sinp->put);
197 pa_hook_slot_free (sinp->unlink);
205 /* main logic initialization function */
206 void agl_tracker_synchronize (struct userdata *u)
213 pa_source_output *sout;
217 pa_assert_se (core = u->core);
219 /* discover.c : add each valid USB/PCI/Platform ALSA sound card */
220 PA_IDXSET_FOREACH (card, core->cards, index) {
221 agl_discover_add_card (u, card);
224 PA_IDXSET_FOREACH (sink, core->sinks, index) {
225 agl_discover_add_sink (u, sink, false);
228 PA_IDXSET_FOREACH (source, core->sources, index) {
229 agl_discover_add_source (u, source);
232 PA_IDXSET_FOREACH(sinp, core->sink_inputs, index) {
233 agl_discover_register_sink_input (u, sinp);
236 PA_IDXSET_FOREACH(sout, core->source_outputs, index) {
237 agl_discover_register_source_output (u, sout);
240 agl_router_make_routing (u);
244 /* HOOK IMPLEMENTATIONS */
245 static pa_hook_result_t card_put (void *hook_data,
252 static pa_hook_result_t card_unlink (void *hook_data,
259 static pa_hook_result_t card_profile_changed (void *hook_data,
266 static pa_hook_result_t port_available_changed (void *hook_data,
273 static pa_hook_result_t sink_put (void *hook_data,
280 static pa_hook_result_t sink_unlink (void *hook_data,
287 static pa_hook_result_t sink_port_changed (void *hook_data,
294 static pa_hook_result_t source_put (void *hook_data,
301 static pa_hook_result_t source_unlink (void *hook_data,
308 static pa_hook_result_t source_port_changed (void *hook_data,
315 static pa_hook_result_t sink_input_new (void *hook_data,
319 /* main hook, called by each client in its 1st phase */
320 pa_sink_input_new_data *data = (pa_sink_input_new_data *)call_data;
321 struct userdata *u = (struct userdata *)slot_data;
324 success = agl_discover_preroute_sink_input (u, data);
326 return success ? PA_HOOK_OK : PA_HOOK_CANCEL;
329 static pa_hook_result_t sink_input_put (void *hook_data,
333 /* called by each client in its 2nd phase */
334 pa_sink_input *sinp = (pa_sink_input *)call_data;
335 struct userdata *u = (struct userdata *)slot_data;
337 agl_discover_add_sink_input (u, sinp);
342 static pa_hook_result_t sink_input_unlink (void *hook_data,
346 /* called by each client when stopping sound */
347 pa_sink_input *sinp = (pa_sink_input *)call_data;
348 struct userdata *u = (struct userdata *)slot_data;
350 agl_discover_remove_sink_input (u, sinp);
355 static pa_hook_result_t source_output_new (void *hook_data,
362 static pa_hook_result_t source_output_put (void *hook_data,
369 static pa_hook_result_t source_output_unlink (void *hook_data,