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,
26 pa_router *pa_router_init (struct userdata *u)
31 num_classes = agl_application_class_end;
33 router = pa_xnew0 (pa_router, 1);
34 router->rtgroups.input = pa_hashmap_new (pa_idxset_string_hash_func,
35 pa_idxset_string_compare_func);
36 router->rtgroups.output = pa_hashmap_new (pa_idxset_string_hash_func,
37 pa_idxset_string_compare_func);
38 router->maplen = num_classes;
39 router->priormap = pa_xnew0 (int, num_classes);
41 AGL_DLIST_INIT (router->nodlist);
42 AGL_DLIST_INIT (router->connlist);
47 void pa_router_done (struct userdata *u)
51 agl_connection *conn, *c;
56 if (u && (router = u->router)) {
57 AGL_DLIST_FOR_EACH_SAFE(agl_node, rtprilist, e,n, &router->nodlist)
58 AGL_DLIST_UNLINK(agl_node, rtprilist, e);
59 AGL_DLIST_FOR_EACH_SAFE(agl_connection, link, conn,c, &router->connlist) {
60 AGL_DLIST_UNLINK(agl_connection, link, conn);
64 PA_HASHMAP_FOREACH(rtg, router->rtgroups.input, state) {
65 rtgroup_destroy(u, rtg);
67 PA_HASHMAP_FOREACH(rtg, router->rtgroups.output, state) {
68 rtgroup_destroy(u, rtg);
70 pa_hashmap_free (router->rtgroups.input);
71 pa_hashmap_free (router->rtgroups.output);
73 for (i = 0; i < AGL_ZONE_MAX; i++) {
74 if ((map = router->classmap.input[i]))
76 if ((map = router->classmap.output[i]))
80 pa_xfree (router->priormap);
87 bool agl_router_default_accept (struct userdata *u, agl_rtgroup *rtg, agl_node *node)
93 bool agl_router_phone_accept (struct userdata *u, agl_rtgroup *rtg, agl_node *node)
99 int agl_router_default_compare (struct userdata *u, agl_rtgroup *rtg, agl_node *n1, agl_node *n2)
105 int agl_router_phone_compare (struct userdata *u, agl_rtgroup *rtg, agl_node *n1, agl_node *n2)
111 void agl_router_register_node (struct userdata *u, agl_node *node)
116 implement_default_route (u, node, NULL, pa_utils_new_stamp ());
119 void agl_router_unregister_node (struct userdata *u, agl_node *node)
124 remove_routes (u, node, NULL, pa_utils_new_stamp ());
127 agl_node *agl_router_make_prerouting (struct userdata *u, agl_node *data)
131 static bool done_prerouting;
133 agl_node *start, *end;
137 pa_assert_se (router = u->router);
138 pa_assert_se (data->implement == agl_stream);
140 //priority = node_priority (u, data);
142 done_prerouting = false;
144 stamp = pa_utils_new_stamp ();
146 //make_explicit_routes (u, stamp);
148 //pa_audiomgr_delete_default_routes(u);
150 AGL_DLIST_FOR_EACH_BACKWARDS(agl_node, rtprilist, start, &router->nodlist) {
151 //if ((start->implement == agl_device) &&
152 // (!start->loop)) /* only manage looped real devices */
155 /*if (priority >= node_priority (u, start)) {
156 target = find_default_route (u, data, stamp);
158 implement_preroute (u, data, target, stamp);
160 done_prerouting = true;
163 if (start->stamp >= stamp)
166 //end = find_default_route (u, start, stamp);
168 // implement_default_route(u, start, end, stamp);
171 if (!done_prerouting) {
172 pa_log_debug ("Prerouting failed, trying to find default route as last resort");
174 //target = find_default_route (u, data, stamp);
176 // implement_preroute (u, data, target, stamp);
182 void agl_router_make_routing (struct userdata *u)
185 static bool ongoing_routing; /* true while we are actively routing */
187 agl_node *start, *end;
190 pa_assert_se (router = u->router);
192 if (ongoing_routing) /* already routing, canceling */
194 ongoing_routing = true;
195 stamp = pa_utils_new_stamp ();
197 pa_log_debug("stamp for routing: %d", stamp);
199 // make_explicit_routes (u, stamp);
201 // pa_audiomgr_delete_default_routes (u);
203 AGL_DLIST_FOR_EACH_BACKWARDS(agl_node, rtprilist, start, &router->nodlist) {
204 //if ((start->implement == agl_device) &&
205 // (!start->loop)) /* only manage looped real devices */
208 if (start->stamp >= stamp)
211 end = find_default_route (u, start, stamp);
213 implement_default_route (u, start, end, stamp);
216 // pa_audiomgr_send_default_routes (u);
218 ongoing_routing = false;
221 void implement_default_route (struct userdata *u,
222 agl_node *start, agl_node *end,
225 if (start->direction == agl_input) {
226 agl_switch_setup_link (u, start, end, false);
227 //agl_volume_add_limiting_class(u, end, volume_class(start), stamp);
229 agl_switch_setup_link (u, end, start, false);
233 agl_node *find_default_route (struct userdata *u, agl_node *start, uint32_t stamp)
240 void remove_routes (struct userdata *u, agl_node *start, agl_node *end, uint32_t stamp)
242 if (start->direction == agl_input) {
243 agl_switch_teardown_link (u, start, end);
245 agl_switch_teardown_link (u, end, start);