X-Git-Url: https://gerrit.automotivelinux.org/gerrit/gitweb?a=blobdiff_plain;f=router.c;h=df469811685bf065746acb85ba4b3c87b797acba;hb=1d150864f72a103aebed4a43381ce109a414cfe2;hp=2478ab231e4c47538d99269648cdd2af3d83657a;hpb=6fc3e02df9de8347eb76fdfd26ed781686d37b6c;p=staging%2Fagl-audio-plugin.git diff --git a/router.c b/router.c index 2478ab2..df46981 100644 --- a/router.c +++ b/router.c @@ -21,16 +21,17 @@ */ #include "router.h" #include "switch.h" +#include "zone.h" #include "utils.h" -pa_router *pa_router_init (struct userdata *u) +agl_router *agl_router_init (struct userdata *u) { - pa_router *router; + agl_router *router; size_t num_classes; num_classes = agl_application_class_end; - router = pa_xnew0 (pa_router, 1); + router = pa_xnew0 (agl_router, 1); router->rtgroups.input = pa_hashmap_new (pa_idxset_string_hash_func, pa_idxset_string_compare_func); router->rtgroups.output = pa_hashmap_new (pa_idxset_string_hash_func, @@ -44,9 +45,9 @@ pa_router *pa_router_init (struct userdata *u) return router; } -void pa_router_done (struct userdata *u) +void agl_router_done (struct userdata *u) { - pa_router *router; + agl_router *router; agl_node *e,*n; agl_connection *conn, *c; agl_rtgroup *rtg; @@ -84,12 +85,316 @@ void pa_router_done (struct userdata *u) } } +bool agl_router_default_accept (struct userdata *u, agl_rtgroup *rtg, agl_node *node) +{ + /* TODO */ + return true; +} + +bool agl_router_phone_accept (struct userdata *u, agl_rtgroup *rtg, agl_node *node) +{ + /* TODO */ + return true; +} + +int agl_router_default_effect (struct userdata *u, agl_rtgroup *rtg, agl_node *node, bool new) +{ + /* TODO */ + return 1; +} + +int agl_router_phone_effect (struct userdata *u, agl_rtgroup *rtg, agl_node *node, bool new) +{ + pa_assert (u); + pa_assert (node); + + if (new) + agl_utils_volume_ramp (u, node->nullsink, false); + else + agl_utils_volume_ramp (u, node->nullsink, true); + + return 1; +} + +agl_rtgroup *agl_router_create_rtgroup (struct userdata *u, agl_direction type, const char *name, const char *node_desc, agl_rtgroup_accept_t accept, agl_rtgroup_effect_t effect) +{ + agl_router *router; + agl_rtgroup *rtg; + agl_nodeset *nodeset; + agl_node *node; + pa_hashmap *table; + + pa_assert (u); + pa_assert (type == agl_input || type == agl_output); + pa_assert (name); + pa_assert_se (router = u->router); + pa_assert_se (nodeset = u->nodeset); + + if (type == agl_input) + table = router->rtgroups.input; + else + table = router->rtgroups.output; + pa_assert (table); + + rtg = pa_xnew0 (agl_rtgroup, 1); + rtg->name = pa_xstrdup (name); + rtg->accept = accept; + rtg->effect = effect; + AGL_DLIST_INIT(rtg->entries); + /* associate an agl_output node for an agl_input routing group */ + if (type == agl_input) { + node = agl_node_create (u, NULL); + node->direction = agl_output; + node->implement = agl_device; + node->visible = true; + node->available = true; + node->paname = pa_xstrdup (node_desc); + /* add to global nodeset */ + pa_idxset_put (nodeset->nodes, node, &node->index); + rtg->node = node; + } else { + rtg->node = NULL; + } + + + pa_hashmap_put (table, rtg->name, rtg); + + pa_log_debug ("routing group '%s' created", name); + + return rtg; +} + +void agl_router_destroy_rtgroup (struct userdata *u, agl_direction type, const char *name) +{ + agl_router *router; + agl_rtgroup *rtg; + pa_hashmap *table; + + pa_assert (u); + pa_assert (name); + pa_assert_se (router = u->router); + + if (type == agl_input) + table = router->rtgroups.input; + else + table = router->rtgroups.output; + pa_assert (table); + + rtg = pa_hashmap_remove (table, name); + if (!rtg) { + pa_log_debug ("can't destroy routing group '%s': not found", name); + } else { + //rtgroup_destroy (u, rtg); + pa_log_debug ("routing group '%s' destroyed", name); + } +} + +bool agl_router_assign_class_to_rtgroup (struct userdata *u, agl_node_type class, uint32_t zone, agl_direction type, const char *name) +{ + agl_router *router; + pa_hashmap *rtable; + agl_rtgroup ***classmap; + agl_rtgroup **zonemap; + const char *classname; + const char *direction; + agl_rtgroup *rtg; + agl_zone *rzone; + + pa_assert (u); + pa_assert (zone < AGL_ZONE_MAX); + pa_assert (type == agl_input || type == agl_output); + pa_assert (name); + pa_assert_se (router = u->router); + + if (type == agl_input) { + rtable = router->rtgroups.input; + classmap = router->classmap.input; + } else { + rtable = router->rtgroups.output; + classmap = router->classmap.output; + } + + if (class < 0 || class >= router->maplen) { + pa_log_debug ("Cannot assign class to routing group '%s': " + "id %d out of range (0 - %d)", + name, class, router->maplen); + return false; + } + + classname = agl_node_type_str (class); /* "Player", "Radio"... */ + direction = agl_node_direction_str (type); /* "input", "output" */ + + rtg = pa_hashmap_get (rtable, name); + if (!rtg) { + pa_log_debug ("Cannot assign class to routing group '%s': " + "router group not found", name); + return false; + } + + zonemap = classmap[zone]; + if (!zonemap) { + zonemap = pa_xnew0 (agl_rtgroup *, router->maplen); + classmap[zone] = zonemap; + } + + zonemap[class] = rtg; + + /* try to get zone name for logging, if fails, only print id number */ + rzone = agl_zoneset_get_zone_by_index (u, zone); + if (rzone) { + pa_log_debug ("class '%s'@'%s' assigned to routing group '%s'", + classname, rzone->name, name); + } else { + pa_log_debug ("class '%s'@zone%d assigned to routing group '%s'", + classname, zone, name); + } + + return true; +} + +agl_rtgroup * agl_router_get_rtgroup_from_class (struct userdata *u, agl_node_type class, uint32_t zone, agl_direction type) +{ + agl_router *router; + pa_hashmap *rtable; + agl_rtgroup ***classmap; + agl_rtgroup **zonemap; + agl_rtgroup * rtg; + + pa_assert (u); + pa_assert_se (router = u->router); + pa_assert (class >= 0 && class < router->maplen); + pa_assert (zone < AGL_ZONE_MAX); + pa_assert (type == agl_input || type == agl_output); + + if (type == agl_input) { + rtable = router->rtgroups.input; + classmap = router->classmap.input; + } else { + rtable = router->rtgroups.output; + classmap = router->classmap.output; + } + + zonemap = classmap[zone]; + rtg = zonemap[class]; + + return rtg; +} + +void agl_router_assign_class_priority (struct userdata *u, agl_node_type class, int priority) +{ + agl_router *router; + int *priormap; + + pa_assert (u); + pa_assert_se (router = u->router); + pa_assert_se (priormap = router->priormap); + + if (class > 0 && class < router->maplen) { + pa_log_debug ("assigning priority %d to class '%s'", + priority, agl_node_type_str (class)); + priormap[class] = priority; + } +} + +int agl_router_get_node_priority (struct userdata *u, agl_node *node) +{ + agl_router *router; + int class; + + pa_assert (u); + pa_assert (node); + pa_assert_se (router = u->router); + + class = node->type; + + if (class < 0 || class >= (int)router->maplen) + return 0; + + return router->priormap[class]; +} + +bool agl_router_apply_node_priority_effect (struct userdata *u, agl_node *node, bool new) +{ + agl_router *router; + agl_rtgroup *rtg; + agl_nodeset *nodeset; + agl_node *n; + pa_sink *sink; + int priority; + uint32_t index; + + pa_assert (u); + pa_assert (node); + pa_assert_se (router = u->router); + pa_assert_se (nodeset = u->nodeset); + + /* do we have a routing group associated with this node ? It may have a custom effect */ + if (node->direction == agl_input) + rtg = pa_hashmap_get (router->rtgroups.input, agl_node_type_str (node->type)); + else + rtg = pa_hashmap_get (router->rtgroups.output, agl_node_type_str (node->type)); + + /* now let us compare priorities, and apply effect if needed */ + /* "new" case */ + if (new) { + priority = agl_router_get_node_priority (u, node); + PA_IDXSET_FOREACH(n, nodeset->nodes, index) { + if (n->nullsink && (priority > agl_router_get_node_priority (u, n))) { + sink = agl_utils_get_null_sink (u, n->nullsink); + if (sink) { + /* do we have a custom effect ? otherwise, just mute it */ + if (rtg && rtg->effect) + rtg->effect (u, rtg, n, new); + else + pa_sink_set_mute (sink, new, false); + } + } + } + } else { + /* "old" case */ + if (!agl_node_has_highest_priority (u, node)) + return true; + PA_IDXSET_FOREACH(n, nodeset->nodes, index) { + if (n->nullsink) { + sink = agl_utils_get_null_sink (u, n->nullsink); + if (sink) { + /* do we have a custom effect ? otherwise, just unmute it */ + if (rtg && rtg->effect) + rtg->effect (u, rtg, n, new); + else + pa_sink_set_mute (sink, new, false); + } + } + } + } + + return true; +} + void agl_router_register_node (struct userdata *u, agl_node *node) { + agl_router *router; + agl_rtgroup *rtg; + pa_assert (u); pa_assert (node); + pa_assert_se (router = u->router); - implement_default_route (u, node, NULL, pa_utils_new_stamp ()); + /* we try to discover node routing group from the configuration, "Phone" for instance, + * see defaults in "config.c. Otherwise we just say NULL, a.k.a. default */ + if (node->direction == agl_input) { + rtg = pa_hashmap_get (router->rtgroups.input, agl_node_type_str (node->type)); + if (rtg) + implement_default_route (u, node, rtg->node, agl_utils_new_stamp ()); + else + implement_default_route (u, node, NULL, agl_utils_new_stamp ()); + } else { + rtg = pa_hashmap_get (router->rtgroups.output, agl_node_type_str (node->type)); + if (rtg) + implement_default_route (u, rtg->node, node, agl_utils_new_stamp ()); + else + implement_default_route (u, NULL, node, agl_utils_new_stamp ()); + } } void agl_router_unregister_node (struct userdata *u, agl_node *node) @@ -97,12 +402,12 @@ void agl_router_unregister_node (struct userdata *u, agl_node *node) pa_assert (u); pa_assert (node); - remove_routes (u, node, NULL, pa_utils_new_stamp ()); + remove_routes (u, node, NULL, agl_utils_new_stamp ()); } agl_node *agl_router_make_prerouting (struct userdata *u, agl_node *data) { - pa_router *router; + agl_router *router; int priority; static bool done_prerouting; uint32_t stamp; @@ -117,7 +422,7 @@ agl_node *agl_router_make_prerouting (struct userdata *u, agl_node *data) done_prerouting = false; target = NULL; - stamp = pa_utils_new_stamp (); + stamp = agl_utils_new_stamp (); //make_explicit_routes (u, stamp); @@ -157,7 +462,7 @@ agl_node *agl_router_make_prerouting (struct userdata *u, agl_node *data) void agl_router_make_routing (struct userdata *u) { - pa_router *router; + agl_router *router; static bool ongoing_routing; /* true while we are actively routing */ uint32_t stamp; agl_node *start, *end; @@ -168,7 +473,7 @@ void agl_router_make_routing (struct userdata *u) if (ongoing_routing) /* already routing, canceling */ return; ongoing_routing = true; - stamp = pa_utils_new_stamp (); + stamp = agl_utils_new_stamp (); pa_log_debug("stamp for routing: %d", stamp); @@ -198,12 +503,10 @@ void implement_default_route (struct userdata *u, agl_node *start, agl_node *end, uint32_t stamp) { - if (start->direction == agl_input) { + if (start->direction == agl_input) agl_switch_setup_link (u, start, end, false); - //agl_volume_add_limiting_class(u, end, volume_class(start), stamp); - } else { + else agl_switch_setup_link (u, end, start, false); - } } agl_node *find_default_route (struct userdata *u, agl_node *start, uint32_t stamp)