From 4597ebb6ee776fc17b372aa6a4c897b25b7d5b3f Mon Sep 17 00:00:00 2001 From: Janos Kovacs Date: Sun, 12 Aug 2012 21:36:32 +0300 Subject: [PATCH] volume: volume limit support for loopback --- murphy/discover.c | 142 +++++++++++++++++++++++++++++------------------------- murphy/loopback.c | 9 ++-- murphy/loopback.h | 3 +- murphy/userdata.h | 1 + murphy/utils.c | 22 +++++++++ murphy/utils.h | 3 ++ 6 files changed, 111 insertions(+), 69 deletions(-) diff --git a/murphy/discover.c b/murphy/discover.c index 68840d3..b240550 100644 --- a/murphy/discover.c +++ b/murphy/discover.c @@ -480,6 +480,7 @@ void pa_discover_remove_sink(struct userdata *u, pa_sink *sink) void pa_discover_add_source(struct userdata *u, pa_source *source) { + pa_core *core; pa_discover *discover; mir_node *node; pa_card *card; @@ -487,12 +488,13 @@ void pa_discover_add_source(struct userdata *u, pa_source *source) char kbf[256]; char nbf[2048]; const char *loopback_role; - uint32_t si; + uint32_t sink_index; pa_sink *ns; mir_node data; pa_assert(u); pa_assert(source); + pa_assert_se((core = u->core)); pa_assert_se((discover = u->discover)); if ((card = source->card)) { @@ -514,12 +516,12 @@ void pa_discover_add_source(struct userdata *u, pa_source *source) pa_log("Can't load loopback module: no initial null sink"); return; } - node->loop = pa_loopback_create(u->loopback, u->core, + node->loop = pa_loopback_create(u->loopback, core, node->index, source->index, ns->index, loopback_role); if (node->loop) { - si = pa_loopback_get_sink_index(u->core, node->loop); - node->mux = pa_multiplex_find(u->multiplex, si); + sink_index = pa_loopback_get_sink_index(core, node->loop); + node->mux = pa_multiplex_find(u->multiplex, sink_index); } mir_node_print(node, nbf, sizeof(nbf)); @@ -745,71 +747,79 @@ void pa_discover_add_sink_input(struct userdata *u, pa_sink_input *sinp) pa_assert_se((discover = u->discover)); pa_assert_se((pl = sinp->proplist)); + if (!(media = pa_proplist_gets(sinp->proplist, PA_PROP_MEDIA_NAME))) + media = ""; - if ((media = pa_proplist_gets(sinp->proplist, PA_PROP_MEDIA_NAME))) { - if (!strncmp(media, combine_pattern, sizeof(combine_pattern)-1)) { - pa_log_debug("New stream is a combine stream. Nothing to do ..."); - return; - } - if (!strncmp(media, loopback_pattern, sizeof(loopback_pattern)-1)) { - pa_log_debug("New stream is a loopback stream. Nothing to do ..."); - return; - } - } - - name = pa_utils_get_sink_input_name(sinp); - - pa_log_debug("dealing with new stream '%s'", name); + if (!strncmp(media, combine_pattern, sizeof(combine_pattern)-1)) { + pa_log_debug("New stream is a combine stream. Nothing to do ..."); + return; + } else if (!strncmp(media, loopback_pattern, sizeof(loopback_pattern)-1)) { + pa_log_debug("New stream is a loopback stream"); - if ((type = get_stream_routing_class(pl)) == mir_node_type_unknown) { - if (!(type = pa_classify_guess_stream_node_type(pl))) { - pa_log_debug("cant find stream class for '%s'. " - "Leaving it alone", name); + if ((node = pa_utils_get_node_from_stream(u, sinp))) + pa_log_debug("loopback stream node '%s' found", node->amname); + else { + pa_log_debug("can't find node for the loopback stream"); return; } - pa_utils_set_stream_routing_properties(pl, type, NULL); - - /* if needed, make some post-routing here */ + s = sinp->sink; } + else { + name = pa_utils_get_sink_input_name(sinp); - /* we need to add this to main hashmap as that is used for loop - through on all nodes. */ - snprintf(key, sizeof(key), "stream_input.%d", sinp->index); - - memset(&data, 0, sizeof(data)); - data.key = key; - data.direction = mir_input; - data.implement = mir_stream; - data.channels = sinp->channel_map.channels; - data.type = type; - data.visible = TRUE; - data.available = TRUE; - data.amname = name; - data.amdescr = (char *)pa_proplist_gets(pl, PA_PROP_MEDIA_NAME); - data.amid = AM_ID_INVALID; - data.paname = name; - data.paidx = sinp->index; - data.mux = pa_multiplex_find(u->multiplex, sinp->sink->index); - - node = create_node(u, &data, &created); - - pa_assert(node); + pa_log_debug("dealing with new stream '%s'", name); + + if ((type = get_stream_routing_class(pl)) == mir_node_type_unknown) { + if (!(type = pa_classify_guess_stream_node_type(pl))) { + pa_log_debug("cant find stream class for '%s'. " + "Leaving it alone", name); + return; + } + + pa_utils_set_stream_routing_properties(pl, type, NULL); + + /* if needed, make some post-routing here */ + } + + /* we need to add this to main hashmap as that is used for loop + through on all nodes. */ + snprintf(key, sizeof(key), "stream_input.%d", sinp->index); + + memset(&data, 0, sizeof(data)); + data.key = key; + data.direction = mir_input; + data.implement = mir_stream; + data.channels = sinp->channel_map.channels; + data.type = type; + data.visible = TRUE; + data.available = TRUE; + data.amname = name; + data.amdescr = (char *)pa_proplist_gets(pl, PA_PROP_MEDIA_NAME); + data.amid = AM_ID_INVALID; + data.paname = name; + data.paidx = sinp->index; + data.mux = pa_multiplex_find(u->multiplex, sinp->sink->index); + + node = create_node(u, &data, &created); - if (!created) { - pa_log("%s: confused with stream. '%s' did exists", - __FILE__, node->amname); - return; - } + pa_assert(node); - pa_discover_add_node_to_ptr_hash(u, sinp, node); + if (!created) { + pa_log("%s: confused with stream. '%s' did exists", + __FILE__, node->amname); + return; + } - if (!data.mux) - s = sinp->sink; - else { - csinp = pa_idxset_get_by_index(core->sink_inputs, - data.mux->defstream_index); - s = csinp ? csinp->sink : NULL; + pa_discover_add_node_to_ptr_hash(u, sinp, node); + + if (!data.mux) + s = sinp->sink; + else { + csinp = pa_idxset_get_by_index(core->sink_inputs, + data.mux->defstream_index); + s = csinp ? csinp->sink : NULL; + } } if (s) @@ -822,7 +832,6 @@ void pa_discover_add_sink_input(struct userdata *u, pa_sink_input *sinp) node->amname, snod->amname); /* FIXME: and actually do it ... */ - pa_fader_apply_volume_limits(u, pa_utils_get_stamp()); } } @@ -834,6 +843,7 @@ void pa_discover_remove_sink_input(struct userdata *u, pa_sink_input *sinp) mir_node *node; mir_node *sinknod; char *name; + pa_loopnode *loop; pa_assert(u); pa_assert(sinp); @@ -841,10 +851,12 @@ void pa_discover_remove_sink_input(struct userdata *u, pa_sink_input *sinp) name = pa_utils_get_sink_input_name(sinp); + pa_log("sink-input '%s' going to be destroyed", name); + if (!(node = pa_discover_remove_node_from_ptr_hash(u, sinp))) pa_log_debug("can't find node for sink-input (name '%s')", name); else { - pa_log_debug("node found for '%s'. After clearing the route " + pa_log_debug("node found for '%s'. After clearing routes " "it will be destroyed", name); if (!(sinknod = pa_hashmap_get(discover->nodes.byptr, sinp->sink))) @@ -852,13 +864,13 @@ void pa_discover_remove_sink_input(struct userdata *u, pa_sink_input *sinp) else { pa_log_debug("clear route '%s' => '%s'", node->amname, sinknod->amname); - + /* FIXME: and actually do it ... */ - + } - + destroy_node(u, node); - + mir_router_make_routing(u); } } diff --git a/murphy/loopback.c b/murphy/loopback.c index 77d689d..de5275e 100644 --- a/murphy/loopback.c +++ b/murphy/loopback.c @@ -30,7 +30,7 @@ #include #include -struct userdata; +#include "userdata.h" #include "loopback.h" #include "utils.h" @@ -57,6 +57,7 @@ void pa_loopback_done(pa_loopback *loopback, pa_core *core) pa_loopnode *pa_loopback_create(pa_loopback *loopback, pa_core *core, + uint32_t node_index, uint32_t source_index, uint32_t sink_index, const char *media_role) @@ -88,9 +89,10 @@ pa_loopnode *pa_loopback_create(pa_loopback *loopback, media_role = "music"; snprintf(args, sizeof(args), "source=\"%s\" sink=\"%s\" " - "sink_input_properties=%s=\"%s\"", + "sink_input_properties=\"%s=%s %s=%u\"", source->name, sink->name, - PA_PROP_MEDIA_ROLE, media_role); + PA_PROP_MEDIA_ROLE, media_role, + PA_PROP_NODE_INDEX, node_index); pa_log_debug("loading %s %s", modnam, args); @@ -115,6 +117,7 @@ pa_loopnode *pa_loopback_create(pa_loopback *loopback, loop = pa_xnew0(pa_loopnode, 1); loop->module_index = module->index; + loop->node_index = node_index; loop->sink_input_index = sink_input->index; PA_LLIST_PREPEND(pa_loopnode, loopback->loopnodes, loop); diff --git a/murphy/loopback.h b/murphy/loopback.h index 8efbd5a..6d09838 100644 --- a/murphy/loopback.h +++ b/murphy/loopback.h @@ -35,6 +35,7 @@ typedef struct pa_loopback { struct pa_loopnode { PA_LLIST_FIELDS(pa_loopnode); uint32_t module_index; + uint32_t node_index; uint32_t sink_input_index; }; @@ -43,7 +44,7 @@ pa_loopback *pa_loopback_init(void); void pa_loopback_done(pa_loopback *, pa_core *); pa_loopnode *pa_loopback_create(pa_loopback *, pa_core *, uint32_t, uint32_t, - const char *); + uint32_t, const char *); void pa_loopback_destroy(pa_loopback *, pa_core *, pa_loopnode *); uint32_t pa_loopback_get_sink_index(pa_core *, pa_loopnode *); diff --git a/murphy/userdata.h b/murphy/userdata.h index 8bb1561..eab55c8 100644 --- a/murphy/userdata.h +++ b/murphy/userdata.h @@ -32,6 +32,7 @@ #define PA_PROP_ROUTING_CLASS_ID "routing.class.id" #define PA_PROP_ROUTING_METHOD "routing.method" #define PA_PROP_ROUTING_TABLE "routing.table" +#define PA_PROP_NODE_INDEX "node.index" #define PA_ROUTING_DEFAULT "default" #define PA_ROUTING_EXPLICIT "explicit" diff --git a/murphy/utils.c b/murphy/utils.c index 5c9c5d8..5316cf1 100644 --- a/murphy/utils.c +++ b/murphy/utils.c @@ -243,6 +243,28 @@ int pa_utils_get_stream_class(pa_proplist *pl) return (int)clid; } +mir_node *pa_utils_get_node_from_stream(struct userdata *u,pa_sink_input *sinp) +{ + mir_node *node; + const char *index_str; + uint32_t index = PA_IDXSET_INVALID; + char *e; + + pa_assert(u); + pa_assert(sinp); + + if ((index_str = pa_proplist_gets(sinp->proplist, PA_PROP_NODE_INDEX))) { + index = strtoul(index_str, &e, 10); + if (e != index_str && *e == '\0') { + if ((node = mir_node_find_by_index(u, index))) + return node; + + pa_log_debug("can't find find node for sink-input.%u",sinp->index); + } + } + + return NULL; +} static char *sink_input_name(pa_proplist *pl) { diff --git a/murphy/utils.h b/murphy/utils.h index 2758607..b2fd42d 100644 --- a/murphy/utils.h +++ b/murphy/utils.h @@ -41,6 +41,9 @@ void pa_utils_set_stream_routing_method_property(pa_proplist *, pa_bool_t); pa_bool_t pa_utils_stream_has_default_route(pa_proplist *); int pa_utils_get_stream_class(pa_proplist *); +#ifdef foouserdatafoo /* argh ... */ +mir_node *pa_utils_get_node_from_stream(struct userdata *, pa_sink_input *); +#endif const char *pa_utils_file_path(const char *, char *, size_t); -- 2.7.4