diff options
author | 2016-06-09 18:22:08 +0200 | |
---|---|---|
committer | 2016-10-11 17:09:06 +0200 | |
commit | 6c2aef81c4182695487fabbd19c5c0a84409b49f (patch) | |
tree | 00343bff2a76a3193ac3c586c97f63c26e37f6b4 /tracker.c | |
parent | 0d031cbfdcb94efa7daa596df5106666b12e9e2b (diff) |
Initial commit
Change-Id: Ic974941bdd30309b4adb72b7a05959332750210b
Signed-off-by: Manuel Bachmann <manuel.bachmann@iot.bzh>
Diffstat (limited to 'tracker.c')
-rw-r--r-- | tracker.c | 371 |
1 files changed, 371 insertions, 0 deletions
diff --git a/tracker.c b/tracker.c new file mode 100644 index 0000000..21ce02c --- /dev/null +++ b/tracker.c @@ -0,0 +1,371 @@ +/* + * module-agl-audio -- PulseAudio module for providing audio routing support + * (forked from "module-murphy-ivi" - https://github.com/otcshare ) + * Copyright (c) 2012, Intel Corporation. + * Copyright (c) 2016, IoT.bzh + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU Lesser General Public License, + * version 2.1, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, + * MA 02110-1301 USA. + * + */ +#include "tracker.h" +#include "discover.h" +#include "router.h" +#include "utils.h" + +struct pa_card_hooks { + pa_hook_slot *put; + pa_hook_slot *unlink; + pa_hook_slot *profchg; +}; + +struct pa_port_hooks { + pa_hook_slot *avail; +}; + +struct pa_sink_hooks { + pa_hook_slot *put; + pa_hook_slot *unlink; + pa_hook_slot *portchg; +}; + +struct pa_source_hooks { + pa_hook_slot *put; + pa_hook_slot *unlink; + pa_hook_slot *portchg; +}; + +struct pa_sink_input_hooks { + pa_hook_slot *neew; + pa_hook_slot *put; + pa_hook_slot *unlink; +}; + +struct pa_source_output_hooks { + pa_hook_slot *neew; + pa_hook_slot *put; + pa_hook_slot *unlink; +}; + +struct pa_tracker { + pa_card_hooks card; + pa_port_hooks port; + pa_sink_hooks sink; + pa_source_hooks source; + pa_sink_input_hooks sink_input; + pa_source_output_hooks source_output; +}; + + +static pa_hook_result_t card_put (void *, void *, void *); +static pa_hook_result_t card_unlink (void *, void *, void *); +static pa_hook_result_t card_profile_changed (void *, void *, void *); + +static pa_hook_result_t port_available_changed (void *, void *, void *); + +static pa_hook_result_t sink_put (void *, void *, void *); +static pa_hook_result_t sink_unlink (void *, void *, void *); +static pa_hook_result_t sink_port_changed (void *, void *, void *); + +static pa_hook_result_t source_put (void *, void *, void *); +static pa_hook_result_t source_unlink (void *, void *, void *); +static pa_hook_result_t source_port_changed (void *, void *, void *); + +static pa_hook_result_t sink_input_new (void *, void *, void *); +static pa_hook_result_t sink_input_put (void *, void *, void *); +static pa_hook_result_t sink_input_unlink (void *, void *, void *); + +static pa_hook_result_t source_output_new (void *, void *, void *); +static pa_hook_result_t source_output_put (void *, void *, void *); +static pa_hook_result_t source_output_unlink (void *, void *, void *); + + +pa_tracker *pa_tracker_init (struct userdata *u) +{ + pa_core *core; + pa_hook *hooks; + pa_tracker *tracker; + pa_card_hooks *card; + pa_port_hooks *port; + pa_sink_hooks *sink; + pa_source_hooks *source; + pa_sink_input_hooks *sinp; + pa_source_output_hooks *sout; + + pa_assert (u); + pa_assert_se (core = u->core); + pa_assert_se (hooks = core->hooks); + + tracker = pa_xnew0 (pa_tracker, 1); + card = &tracker->card; + port = &tracker->port; + sink = &tracker->sink; + source = &tracker->source; + sinp = &tracker->sink_input; + sout = &tracker->source_output; + + /* card */ + card->put = pa_hook_connect (hooks + PA_CORE_HOOK_CARD_PUT, + PA_HOOK_LATE, card_put, u); + card->unlink = pa_hook_connect (hooks + PA_CORE_HOOK_CARD_UNLINK, + PA_HOOK_LATE, card_unlink, u); + card->profchg = pa_hook_connect (hooks + PA_CORE_HOOK_CARD_UNLINK, + PA_HOOK_LATE, card_profile_changed, u); + + /* port */ + port->avail = pa_hook_connect (hooks + PA_CORE_HOOK_PORT_AVAILABLE_CHANGED, + PA_HOOK_LATE, port_available_changed, u); + + /* sink */ + sink->put = pa_hook_connect (hooks + PA_CORE_HOOK_SINK_PUT, + PA_HOOK_LATE, sink_put, u); + sink->unlink = pa_hook_connect (hooks + PA_CORE_HOOK_SINK_UNLINK, + PA_HOOK_LATE, sink_unlink, u); + sink->portchg = pa_hook_connect (hooks + PA_CORE_HOOK_SINK_PORT_CHANGED, + PA_HOOK_LATE, sink_port_changed, u); + + /* source */ + source->put = pa_hook_connect (hooks + PA_CORE_HOOK_SOURCE_PUT, + PA_HOOK_LATE, source_put, u); + source->unlink = pa_hook_connect (hooks + PA_CORE_HOOK_SOURCE_UNLINK, + PA_HOOK_LATE, source_unlink, u); + source->portchg = pa_hook_connect (hooks + PA_CORE_HOOK_SOURCE_PORT_CHANGED, + PA_HOOK_LATE, source_port_changed, u); + + /* sink-input */ + sinp->neew = pa_hook_connect (hooks + PA_CORE_HOOK_SINK_INPUT_NEW, + PA_HOOK_EARLY, sink_input_new, u); + sinp->put = pa_hook_connect (hooks + PA_CORE_HOOK_SINK_INPUT_PUT, + PA_HOOK_LATE, sink_input_put, u); + sinp->unlink = pa_hook_connect (hooks + PA_CORE_HOOK_SINK_INPUT_UNLINK, + PA_HOOK_LATE, sink_input_unlink, u); + + /* source-output */ + sout->neew = pa_hook_connect (hooks + PA_CORE_HOOK_SOURCE_OUTPUT_NEW, + PA_HOOK_EARLY, source_output_new, u); + sout->put = pa_hook_connect (hooks + PA_CORE_HOOK_SOURCE_OUTPUT_UNLINK, + PA_HOOK_LATE, source_output_put, u); + sout->unlink = pa_hook_connect (hooks + PA_CORE_HOOK_SOURCE_OUTPUT_UNLINK, + PA_HOOK_LATE, source_output_unlink, u); + + return tracker; +} + +void pa_tracker_done (struct userdata *u) +{ + pa_tracker *tracker; + pa_card_hooks *card; + pa_port_hooks *port; + pa_sink_hooks *sink; + pa_source_hooks *source; + pa_sink_input_hooks *sinp; + + if (u && (tracker = u->tracker)) { + + card = &tracker->card; + pa_hook_slot_free (card->put); + pa_hook_slot_free (card->unlink); + pa_hook_slot_free (card->profchg); + + port = &tracker->port; + pa_hook_slot_free (port->avail); + + sink = &tracker->sink; + pa_hook_slot_free (sink->put); + pa_hook_slot_free (sink->unlink); + pa_hook_slot_free (sink->portchg); + + source = &tracker->source; + pa_hook_slot_free (source->put); + pa_hook_slot_free (source->unlink); + pa_hook_slot_free (source->portchg); + + sinp = &tracker->sink_input; + pa_hook_slot_free (sinp->neew); + pa_hook_slot_free (sinp->put); + pa_hook_slot_free (sinp->unlink); + + pa_xfree(tracker); + + u->tracker = NULL; + } +} + + /* main logic initialization function */ +void pa_tracker_synchronize (struct userdata *u) +{ + pa_core *core; + pa_card *card; + pa_sink *sink; + pa_source *source; + pa_sink_input *sinp; + pa_source_output *sout; + uint32_t index; + + pa_assert (u); + pa_assert_se (core = u->core); + + /* initialize "stamp" incremental card property to 0 */ + pa_utils_init_stamp (); + + /* discover.c : add each valid USB/PCI/Platform ALSA sound card */ + PA_IDXSET_FOREACH (card, core->cards, index) { + pa_discover_add_card (u, card); + } + + PA_IDXSET_FOREACH (sink, core->sinks, index) { + pa_discover_add_sink (u, sink, false); + } + + PA_IDXSET_FOREACH (source, core->sources, index) { + pa_discover_add_source (u, source); + } + + PA_IDXSET_FOREACH(sinp, core->sink_inputs, index) { + pa_discover_register_sink_input (u, sinp); + } + + PA_IDXSET_FOREACH(sout, core->source_outputs, index) { + pa_discover_register_source_output (u, sout); + } + + agl_router_make_routing (u); +} + + + /* HOOK IMPLEMENTATIONS */ +static pa_hook_result_t card_put (void *hook_data, + void *call_data, + void *slot_data) +{ + return PA_HOOK_OK; +} + +static pa_hook_result_t card_unlink (void *hook_data, + void *call_data, + void *slot_data) +{ + return PA_HOOK_OK; +} + +static pa_hook_result_t card_profile_changed (void *hook_data, + void *call_data, + void *slot_data) +{ + return PA_HOOK_OK; +} + +static pa_hook_result_t port_available_changed (void *hook_data, + void *call_data, + void *slot_data) +{ + return PA_HOOK_OK; +} + +static pa_hook_result_t sink_put (void *hook_data, + void *call_data, + void *slot_data) +{ + return PA_HOOK_OK; +} + +static pa_hook_result_t sink_unlink (void *hook_data, + void *call_data, + void *slot_data) +{ + return PA_HOOK_OK; +} + +static pa_hook_result_t sink_port_changed (void *hook_data, + void *call_data, + void *slot_data) +{ + return PA_HOOK_OK; +} + +static pa_hook_result_t source_put (void *hook_data, + void *call_data, + void *slot_data) +{ + return PA_HOOK_OK; +} + +static pa_hook_result_t source_unlink (void *hook_data, + void *call_data, + void *slot_data) +{ + return PA_HOOK_OK; +} + +static pa_hook_result_t source_port_changed (void *hook_data, + void *call_data, + void *slot_data) +{ + return PA_HOOK_OK; +} + +static pa_hook_result_t sink_input_new (void *hook_data, + void *call_data, + void *slot_data) +{ + /* main hook, called by each client in its 1st phase */ + pa_sink_input_new_data *data = (pa_sink_input_new_data *)call_data; + struct userdata *u = (struct userdata *)slot_data; + bool success; + + success = pa_discover_preroute_sink_input (u, data); + + return success ? PA_HOOK_OK : PA_HOOK_CANCEL; +} + +static pa_hook_result_t sink_input_put (void *hook_data, + void *call_data, + void *slot_data) +{ + /* called by each client in its 2nd phase */ + pa_sink_input *sinp = (pa_sink_input *)call_data; + struct userdata *u = (struct userdata *)slot_data; + + pa_discover_add_sink_input (u, sinp); + + return PA_HOOK_OK; +} + +static pa_hook_result_t sink_input_unlink (void *hook_data, + void *call_data, + void *slot_data) +{ + return PA_HOOK_OK; +} + +static pa_hook_result_t source_output_new (void *hook_data, + void *call_data, + void *slot_data) +{ + return PA_HOOK_OK; +} + +static pa_hook_result_t source_output_put (void *hook_data, + void *call_data, + void *slot_data) +{ + return PA_HOOK_OK; +} + +static pa_hook_result_t source_output_unlink (void *hook_data, + void *call_data, + void *slot_data) +{ + return PA_HOOK_OK; +} |