From: Janos Kovacs Date: Thu, 20 Nov 2014 13:25:37 +0000 (+0200) Subject: appid based resource and stream synching (needed by xwalk) X-Git-Tag: accepted/tizen/ivi/20141216.021000~5 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=dd0f210aa6fdefff990a00921ec917f4b27ac63b;p=profile%2Fivi%2Fpulseaudio-module-murphy-ivi.git appid based resource and stream synching (needed by xwalk) Change-Id: I38da04ef45347e262394c023b9e665b704219bcf --- diff --git a/murphy/discover.c b/murphy/discover.c index 631d6a4..86860c8 100644 --- a/murphy/discover.c +++ b/murphy/discover.c @@ -778,6 +778,7 @@ void pa_discover_register_sink_input(struct userdata *u, pa_sink_input *sinp) pa_sink *sink; const char *role; pa_nodeset_resdef *resdef; + char idbuf[512]; pa_assert(u); pa_assert(sinp); @@ -824,7 +825,7 @@ void pa_discover_register_sink_input(struct userdata *u, pa_sink_input *sinp) data.amid = AM_ID_INVALID; data.paname = name; data.paidx = sinp->index; - data.rsetid = (char *)pa_proplist_gets(pl, PA_PROP_RESOURCE_SET_ID); + data.rsetid = pa_utils_get_rsetid(pl, idbuf, sizeof(idbuf)); /* * here we can't guess whether the application requested an explicit @@ -1004,6 +1005,7 @@ void pa_discover_add_sink_input(struct userdata *u, pa_sink_input *sinp) pa_muxnode *mux; pa_nodeset_resdef *resdef; pa_nodeset_resdef rdbuf; + char idbuf[512]; pa_assert(u); pa_assert(sinp); @@ -1087,7 +1089,7 @@ void pa_discover_add_sink_input(struct userdata *u, pa_sink_input *sinp) data.paidx = sinp->index; data.mux = pa_multiplex_find_by_sink(u->multiplex, sinp->sink->index); - data.rsetid = (char *)pa_proplist_gets(pl, PA_PROP_RESOURCE_SET_ID); + data.rsetid = pa_utils_get_rsetid(pl, idbuf, sizeof(idbuf)); node = create_node(u, &data, &created); pa_assert(node); @@ -1201,6 +1203,7 @@ void pa_discover_register_source_output(struct userdata *u, pa_source *source; const char *role; pa_nodeset_resdef *resdef; + char idbuf[512]; pa_assert(u); pa_assert(sout); @@ -1243,7 +1246,7 @@ void pa_discover_register_source_output(struct userdata *u, data.amid = AM_ID_INVALID; data.paname = name; data.paidx = sout->index; - data.rsetid = (char *)pa_proplist_gets(pl, PA_PROP_RESOURCE_SET_ID); + data.rsetid = pa_utils_get_rsetid(pl, idbuf, sizeof(idbuf)); /* * here we can't guess whether the application requested an explicit @@ -1364,9 +1367,10 @@ void pa_discover_add_source_output(struct userdata *u, pa_source_output *sout) const char *media; mir_node_type type; char key[256]; - bool created; + bool created; pa_nodeset_resdef *resdef; pa_nodeset_resdef rdbuf; + char idbuf[512]; pa_assert(u); pa_assert(sout); @@ -1432,7 +1436,7 @@ void pa_discover_add_source_output(struct userdata *u, pa_source_output *sout) data.amid = AM_ID_INVALID; data.paname = name; data.paidx = sout->index; - data.rsetid = (char *)pa_proplist_gets(pl, PA_PROP_RESOURCE_SET_ID); + data.rsetid = pa_utils_get_rsetid(pl, idbuf, sizeof(idbuf)); node = create_node(u, &data, &created); diff --git a/murphy/murphy-ivi.lua b/murphy/murphy-ivi.lua index b2b40dc..95988a0 100644 --- a/murphy/murphy-ivi.lua +++ b/murphy/murphy-ivi.lua @@ -134,7 +134,7 @@ audio_resource { attributes = { role = {"media.role", mdb.string, "music"}, pid = {"application.process.id", mdb.string, ""}, - appid = {"resource.set.appid", mdb.string, ""} + name = {"resource.set.name", mdb.string, ""} } } diff --git a/murphy/murphyif.c b/murphy/murphyif.c index fab0970..2f4596a 100644 --- a/murphy/murphyif.c +++ b/murphy/murphyif.c @@ -58,25 +58,29 @@ #include "utils.h" #ifdef WITH_RESOURCES -#define INVALID_ID (~(uint32_t)0) -#define INVALID_INDEX (~(uint32_t)0) -#define INVALID_SEQNO (~(uint32_t)0) -#define INVALID_REQUEST (~(uint16_t)0) +#define INVALID_ID (~(uint32_t)0) +#define INVALID_INDEX (~(uint32_t)0) +#define INVALID_SEQNO (~(uint32_t)0) +#define INVALID_REQUEST (~(uint16_t)0) #define DISCONNECTED -1 #define CONNECTED 0 #define CONNECTING 1 -#define RESCOL_NAMES "rsetid,autorel,state,grant,pid,policy" -#define RESCOL_RSETID 0 -#define RESCOL_AUTOREL 1 -#define RESCOL_STATE 2 -#define RESCOL_GRANT 3 -#define RESCOL_PID 4 -#define RESCOL_POLICY 5 +#define RESCOL_NAMES "rsetid,autorel,state,grant,pid,policy,name" +#define RESCOL_RSETID 0 +#define RESCOL_AUTOREL 1 +#define RESCOL_STATE 2 +#define RESCOL_GRANT 3 +#define RESCOL_PID 4 +#define RESCOL_POLICY 5 +#define RESCOL_RSETNAME 6 -#define RSET_RELEASE 1 -#define RSET_ACQUIRE 2 +#define RSET_RELEASE 1 +#define RSET_ACQUIRE 2 + +#define RSET_INPUT 0 +#define RSET_OUTPUT 1 #define PUSH_VALUE(msg, tag, typ, val) \ mrp_msg_append(msg, MRP_MSG_TAG_##typ(RESPROTO_##tag, val)) @@ -116,6 +120,7 @@ typedef struct { typedef struct { const char *name; + const char *tblnam; int tblidx; } audio_resource_t; @@ -140,6 +145,7 @@ typedef struct { struct { pa_hashmap *rsetid; pa_hashmap *pid; + unsigned nres[2]; } nodes; PA_LLIST_HEAD(resource_attribute, attrs); PA_LLIST_HEAD(resource_request, reqs); @@ -157,11 +163,15 @@ struct pa_murphyif { #ifdef WITH_RESOURCES typedef struct { + const char *hashkey; + bool dead; const char *id; - bool autorel; + bool autorel; int state; - bool grant; + bool grant; const char *policy; + const char *name; + const char *pid; } rset_data; typedef struct { @@ -174,6 +184,8 @@ typedef struct { size_t nnode; mir_node **nodes; rset_data *rset; + bool type[2]; + uint32_t updid; } rset_hash; #endif @@ -192,26 +204,27 @@ static int resource_transport_connect(resource_interface *); static void resource_xport_closed_evt(mrp_transport_t *, int, void *); static mrp_msg_t *resource_create_request(uint32_t, mrp_resproto_request_t); -static bool resource_send_message(resource_interface *, mrp_msg_t *, +static bool resource_send_message(resource_interface *, mrp_msg_t *, uint32_t, uint16_t, uint32_t); -static bool resource_set_create_node(struct userdata *, mir_node *, +static bool resource_set_create_node(struct userdata *, mir_node *, pa_nodeset_resdef *, bool); -static bool resource_set_create_all(struct userdata *); -static bool resource_set_destroy_node(struct userdata *, uint32_t); -static bool resource_set_destroy_all(struct userdata *); +static bool resource_set_create_all(struct userdata *); +static bool resource_set_destroy_node(struct userdata *, uint32_t); +static bool resource_set_destroy_all(struct userdata *); static void resource_set_notification(struct userdata *, const char *, int, mrp_domctl_value_t **); +static void resource_set_enforce_policy(struct userdata *, rset_hash *); static bool resource_push_attributes(mrp_msg_t *, resource_interface *, pa_proplist *); -static void resource_recv_msg(mrp_transport_t *, mrp_msg_t *, void *); -static void resource_recvfrom_msg(mrp_transport_t *, mrp_msg_t *, - mrp_sockaddr_t *, socklen_t, void *); -static void resource_set_create_response(struct userdata *, mir_node *, - mrp_msg_t *, void **); -static void resource_set_create_response_abort(struct userdata *, - mrp_msg_t *, void **); +static void resource_recv_msg(mrp_transport_t *, mrp_msg_t *, void *); +static void resource_recvfrom_msg(mrp_transport_t *, mrp_msg_t *, + mrp_sockaddr_t *, socklen_t, void *); +static void resource_set_create_response(struct userdata *, mir_node *, + mrp_msg_t *, void **); +static void resource_set_create_response_abort(struct userdata *, + mrp_msg_t *, void **); static bool resource_fetch_seqno(mrp_msg_t *, void **, uint32_t *); static bool resource_fetch_request(mrp_msg_t *, void **, uint16_t *); @@ -247,7 +260,8 @@ static mir_node *pid_hashmap_remove_node(struct userdata *, const char *); static rset_data *pid_hashmap_remove_rset(struct userdata *, const char *); static void rset_hashmap_free(void *, void *); -static rset_hash *rset_hashmap_put(struct userdata *, const char *, mir_node *); +static rset_hash *rset_hashmap_put(struct userdata *, const char *, + int, mir_node *); static rset_hash *rset_hashmap_get(struct userdata *u, const char *rsetid); static int rset_hashmap_remove(struct userdata *,const char *,mir_node*); @@ -544,6 +558,7 @@ void pa_murphyif_add_audio_resource(struct userdata *u, res->name = pa_xstrdup(name); #ifdef WITH_DOMCTL snprintf(table, sizeof(table), "%s_users", name); + res->tblnam = pa_xstrdup(table); res->tblidx = pa_murphyif_add_watch(u, table, columns, NULL, maxrow); #endif } @@ -685,6 +700,7 @@ int pa_murphyif_add_node(struct userdata *u, mir_node *node) const char *pid; rset_data *rset; rset_hash *rh; + int type; char buf[64]; pa_assert(u); @@ -727,12 +743,15 @@ int pa_murphyif_add_node(struct userdata *u, mir_node *node) } } else { - if ((rh = rset_hashmap_put(u, node->rsetid, node))) { + type = (node->direction == mir_input) ? RSET_INPUT : RSET_OUTPUT; + + if ((rh = rset_hashmap_put(u, node->rsetid, type, node))) { rset = rh->rset; - pa_log_debug("enforce policies on node %u '%s' rsetid:%s autorel:%s " - "state:%s grant:%s policy:%s", node->paidx, node->amname, - rset->id, rset->autorel ? "yes":"no", + pa_log_debug("enforce policies on node %u '%s' hashkey:%s " + "autorel:%s state:%s grant:%s policy:%s", + node->paidx, node->amname, + rset->hashkey, rset->autorel ? "yes":"no", rset->state == RSET_ACQUIRE ? "acquire":"release", rset->grant ? "yes":"no", rset->policy); @@ -1222,8 +1241,11 @@ static void resource_set_notification(struct userdata *u, int nrow, mrp_domctl_value_t **values) { + static uint32_t updid; + pa_murphyif *murphyif; resource_interface *rif; + int type; int r; mrp_domctl_value_t *row; mrp_domctl_value_t *crsetid; @@ -1232,12 +1254,16 @@ static void resource_set_notification(struct userdata *u, mrp_domctl_value_t *cgrant; mrp_domctl_value_t *cpid; mrp_domctl_value_t *cpolicy; + mrp_domctl_value_t *crsetname; char rsetid[32]; + char name[256]; const char *pid; mir_node *node, **nodes; rset_hash *rh; rset_data rset, *rs; size_t i, size; + unsigned nrset; + void *it; pa_assert(u); pa_assert(table); @@ -1245,21 +1271,34 @@ static void resource_set_notification(struct userdata *u, pa_assert_se((murphyif = u->murphyif)); rif = &murphyif->resource; - for (r = 0; r < nrow; r++) { + if (pa_streq(table, rif->inpres.tblnam)) + type = RSET_INPUT; + else if (pa_streq(table, rif->outres.tblnam)) + type = RSET_OUTPUT; + else { + pa_log_debug("ignoring unregistered table '%s'", table); + return; + } + + updid++; + + for (r = 0, nrset = 0; r < nrow; r++) { row = values[r]; - crsetid = row + RESCOL_RSETID; - cautorel = row + RESCOL_AUTOREL; - cstate = row + RESCOL_STATE; - cgrant = row + RESCOL_GRANT; - cpid = row + RESCOL_PID; - cpolicy = row + RESCOL_POLICY; - - if (crsetid->type != MRP_DOMCTL_UNSIGNED || - cautorel->type != MRP_DOMCTL_INTEGER || - cstate->type != MRP_DOMCTL_INTEGER || - cgrant->type != MRP_DOMCTL_INTEGER || - cpid->type != MRP_DOMCTL_STRING || - cpolicy->type != MRP_DOMCTL_STRING ) + crsetid = row + RESCOL_RSETID; + cautorel = row + RESCOL_AUTOREL; + cstate = row + RESCOL_STATE; + cgrant = row + RESCOL_GRANT; + cpid = row + RESCOL_PID; + cpolicy = row + RESCOL_POLICY; + crsetname = row + RESCOL_RSETNAME; + + if (crsetid->type != MRP_DOMCTL_UNSIGNED || + cautorel->type != MRP_DOMCTL_INTEGER || + cstate->type != MRP_DOMCTL_INTEGER || + cgrant->type != MRP_DOMCTL_INTEGER || + cpid->type != MRP_DOMCTL_STRING || + cpolicy->type != MRP_DOMCTL_STRING || + crsetname->type != MRP_DOMCTL_STRING ) { pa_log("invalid field type in '%s' (%d|%d|%d|%d|%d|%d)", table, crsetid->type, cautorel->type, cstate->type, @@ -1267,15 +1306,22 @@ static void resource_set_notification(struct userdata *u, continue; } - snprintf(rsetid, sizeof(rsetid), "%d", crsetid->s32); + snprintf(rsetid, sizeof(rsetid), "%d" , crsetid->s32); + if (crsetname->str[0] && !pa_streq(crsetname->str, "")) + snprintf(name, sizeof(name), "#%s", crsetname->str); + else + name[0] = 0; + pid = cpid->str; + memset(&rset, 0, sizeof(rset)); rset.id = rsetid; rset.autorel = cautorel->s32; rset.state = cstate->s32; rset.grant = cgrant->s32; rset.policy = cpolicy->str; - + rset.name = name; + rset.pid = pid; if (rset.autorel != 0 && rset.autorel != 1) { pa_log_debug("invalid autorel %d in table '%s'", @@ -1290,68 +1336,117 @@ static void resource_set_notification(struct userdata *u, pa_log_debug("invalid grant %d in table '%s'", rset.grant, table); continue; } + if (!rset.policy) { + pa_log_debug("invalid 'policy' string in table '%s'", table); + continue; + } + + if (rset.name[0] == '#') { + rset.hashkey = rset.name; - if (!(rh = rset_hashmap_get(u, rset.id))) { - if (!pid) { - pa_log_debug("can't find node for resource set %s " - "(pid in resource set unknown)", rset.id); + if (!(rh = rset_hashmap_put(u, rset.hashkey, type, NULL))) { + pa_log_debug("can't add to hashmap '%s' resource set", + rset.hashkey); continue; } + } + else { + rset.hashkey = rset.id; - if ((node = pid_hashmap_remove_node(u, pid))) { - pa_log_debug("found node %s for resource-set '%s'", - node->amname, rset.id); - - if (!(rh = node_put_rset(u, node, &rset))) { - pa_log("can't register resource set for node '%s': " - "failed to set rsetid", node->amname); + if (!(rh = rset_hashmap_get(u, rset.hashkey))) { + if (!pid) { + pa_log_debug("can't find node for resource set %s " + "(pid in resource set unknown)", rset.id); continue; } - } - else { - if (pid_hashmap_put(u, pid, NULL, rset_data_dup(&rset)) < 0) { - if (!(rs = pid_hashmap_get_rset(u, pid))) - pa_log("failed to add resource set to pid hash"); - else { - if (!pa_streq(rs->id, rset.id)) { - pa_log("process %s appears to have multiple resour" - "ce sets (%s and %s)", pid, rs->id,rset.id); - } - pa_log_debug("update resource-set %s data in " - "pid hash (pid %s)", rs->id, pid); - rset_data_copy(rs, &rset); + + if ((node = pid_hashmap_remove_node(u, pid))) { + pa_log_debug("found node %s for resource-set '%s'", + node->amname, rset.id); + + if (!(rh = node_put_rset(u, node, &rset))) { + pa_log("can't register resource set for node '%s': " + "failed to set rsetid", node->amname); + continue; } } else { - pa_log_debug("can't find node for resource set %s. " - "Beleive the stream will appear later on", - rset.id); - } + if (pid_hashmap_put(u,pid,NULL,rset_data_dup(&rset)) < 0) { + if (!(rs = pid_hashmap_get_rset(u, pid))) + pa_log("failed to add resource set to pid hash"); + else { + if (!pa_streq(rs->id, rset.id)) { + pa_log("process %s appears to have multiple " + "resource sets (%s and %s)", + pid, rs->id,rset.id); + } + pa_log_debug("update resource-set %s data in " + "pid hash (pid %s)", rs->id, pid); + rset_data_copy(rs, &rset); + } + } + else { + pa_log_debug("can't find node for resource set %s. " + "Beleive the stream will appear later on", + rset.id); + } - continue; + continue; + } } } rset_data_update(rh->rset, &rset); - /* we need to make a copy of this as node_enforce_resource_policy() - will delete/modify it */ - size = sizeof(mir_node *) * (rh->nnode + 1); - nodes = alloca(size); - memcpy(nodes, rh->nodes, size); + rh->updid = updid; + nrset++; + + resource_set_enforce_policy(u, rh); + + } /* for each row */ - for (i = 0; (node = nodes[i]); i++) { - pa_log_debug("%u: resource notification for node '%s' autorel:%s " - "state:%s grant:%s pid:%s policy:%s", i, - node->amname, rset.autorel ? "yes":"no", - rset.state == RSET_ACQUIRE ? "acquire":"release", - rset.grant ? "yes":"no", pid, rset.policy); + if (nrset < rif->nodes.nres[type]) { + pa_log_debug("some of the resource sets were not updated => " + "find the %u resource sets that need to be deleted", + pa_hashmap_size(rif->nodes.rsetid) - nrset); - node_enforce_resource_policy(u, node, &rset); + PA_HASHMAP_FOREACH(rh, rif->nodes.rsetid, it) { + if (rh->type[type] && rh->updid != updid) { + pa_log_debug("'%s' was not updated => assume it's gone " + "and delete it", rh->rset->hashkey); + + rh->rset->dead = true; + rh->rset->grant = false; + + resource_set_enforce_policy(u, rh); + } } } } +static void resource_set_enforce_policy(struct userdata *u, rset_hash *rh) { + size_t i, size; + mir_node *node, **nodes; + + /* we need to make a copy of this as node_enforce_resource_policy() + will delete/modify it */ + size = sizeof(mir_node *) * (rh->nnode + 1); + nodes = alloca(size); + memcpy(nodes, rh->nodes, size); + + for (i = 0; (node = nodes[i]); i++) { + pa_log_debug("%u: resource notification for node '%s' hashkey=%s " + "autorel:%s state:%s grant:%s pid:%s policy:%s", + i, node->amname, rh->rset->hashkey, + rh->rset->autorel ? "yes":"no", + rh->rset->state == RSET_ACQUIRE ? "acquire":"release", + rh->rset->grant ? "yes":"no", + rh->rset->pid, rh->rset->policy); + + node_enforce_resource_policy(u, node, rh->rset); + } +} + static bool resource_push_attributes(mrp_msg_t *msg, resource_interface *rif, @@ -1818,6 +1913,7 @@ static rset_hash *node_put_rset(struct userdata *u, mir_node *node, rset_data *r resource_interface *rif; pa_proplist *pl; rset_hash *rh; + int type; pa_assert(u); pa_assert(node); @@ -1829,6 +1925,7 @@ static rset_hash *node_put_rset(struct userdata *u, mir_node *node, rset_data *r pa_assert_se((murphyif = u->murphyif)); rif = &murphyif->resource; + type = (node->direction == mir_input) ? RSET_INPUT : RSET_OUTPUT; pa_log_debug("setting rsetid %s for node %s", rset->id, node->amname); @@ -1848,7 +1945,7 @@ static rset_hash *node_put_rset(struct userdata *u, mir_node *node, rset_data *r return NULL; } - if (!(rh = rset_hashmap_put(u, node->rsetid, node))) { + if (!(rh = rset_hashmap_put(u, node->rsetid, type, node))) { pa_log("conflicting rsetid %s for %s", node->rsetid, node->amname); return NULL; } @@ -1935,22 +2032,30 @@ static void rset_data_update(rset_data *dst, rset_data *src) pa_assert(src->id); pa_assert(src->policy); - pa_assert_se(pa_streq(src->id, dst->id)); + pa_assert(pa_streq(src->hashkey, dst->hashkey)); + pa_xfree((void *)dst->id); pa_xfree((void *)dst->policy); + pa_xfree((void *)dst->name); + pa_xfree((void *)dst->pid); + dst->id = pa_xstrdup(src->id); dst->autorel = src->autorel; dst->state = src->state; dst->grant = src->grant; dst->policy = pa_xstrdup(src->policy); + dst->name = pa_xstrdup(src->name); + dst->pid = pa_xstrdup(src->pid); } static void rset_data_free(rset_data *rset) { if (rset) { + pa_xfree((void *)rset->hashkey); pa_xfree((void *)rset->id); pa_xfree((void *)rset->policy); + pa_xfree((void *)rset->name); pa_xfree(rset); } } @@ -2095,50 +2200,68 @@ static void rset_hashmap_free(void *r, void *userdata) static rset_hash *rset_hashmap_put(struct userdata *u, const char *rsetid, + int type, mir_node *node) { pa_murphyif *murphyif; resource_interface *rif; rset_hash *rh; rset_data *rset; - size_t i; + size_t i, size; pa_assert(u); pa_assert(rsetid); - pa_assert(node); + pa_assert(type == RSET_INPUT || type == RSET_OUTPUT); pa_assert_se((murphyif = u->murphyif)); rif = &murphyif->resource; if ((rh = pa_hashmap_get(rif->nodes.rsetid, rsetid))) { - for (i = 0; i < rh->nnode; i++) { - if (rh->nodes[i] == node) - return NULL; + if (rh->rset->dead) { + pa_log_debug("attempt to add dead rset '%s' to hashmap", + rh->rset->hashkey); + return NULL; } - i = rh->nnode++; - rh->nodes = pa_xrealloc(rh->nodes, sizeof(mir_node *) * (rh->nnode+1)); + if (node) { + for (i = 0; i < rh->nnode; i++) { + if (rh->nodes[i] == node) + return NULL; + } + + i = rh->nnode++; + size = sizeof(mir_node *) * (rh->nnode + 1); + rh->nodes = pa_xrealloc(rh->nodes, size); + } } else { rset = pa_xnew0(rset_data, 1); - rset->id = pa_xstrdup(rsetid); - rset->policy = pa_xstrdup("unknown"); + rset->hashkey = pa_xstrdup(rsetid); + rset->dead = false; + rset->id = pa_xstrdup("unknown"); + rset->policy = pa_xstrdup("unknown"); + rset->name = pa_xstrdup("unknown"); rh = pa_xnew0(rset_hash, 1); - rh->nnode = 1; - rh->nodes = pa_xnew0(mir_node *, 2); + rh->nnode = node ? 1 : 0; + rh->nodes = pa_xnew0(mir_node *, rh->nnode + 1); rh->rset = rset; - pa_hashmap_put(rif->nodes.rsetid, (void *)rh->rset->id, rh); + pa_hashmap_put(rif->nodes.rsetid, (void *)rh->rset->hashkey, rh); + + rif->nodes.nres[type]++; i = 0; } + if (node) { + rh->nodes[i+0] = node; + rh->nodes[i+1] = NULL; + } - rh->nodes[i+0] = node; - rh->nodes[i+1] = NULL; + rh->type[type] = true; return rh; } @@ -2168,6 +2291,8 @@ static int rset_hashmap_remove(struct userdata *u, pa_murphyif *murphyif; resource_interface *rif; rset_hash *rh; + rset_data *rset; + int type; size_t i,j; pa_assert(u); @@ -2176,22 +2301,28 @@ static int rset_hashmap_remove(struct userdata *u, rif = &murphyif->resource; if ((rh = pa_hashmap_get(rif->nodes.rsetid, rsetid))) { + pa_assert_se((rset = rh->rset)); for (i = 0; i < rh->nnode; i++) { if (node == rh->nodes[i]) { - if (rh->nnode <= 1) { + if (rh->nnode <= 1 && (rset->hashkey[0] != '#' || rset->dead)){ pa_hashmap_remove(rif->nodes.rsetid, rsetid); rset_hashmap_free(rh, NULL); - return 0; + + type = (node->direction == mir_input) ? + RSET_INPUT : RSET_OUTPUT; + + if (rif->nodes.nres[type] > 0) + rif->nodes.nres[type]--; } else { for (j = i; j < rh->nnode; j++) rh->nodes[j] = rh->nodes[j+1]; rh->nnode--; - - return 0; } + + return 0; } } } diff --git a/murphy/node.c b/murphy/node.c index cc06e90..4fe715b 100644 --- a/murphy/node.c +++ b/murphy/node.c @@ -90,7 +90,7 @@ void pa_nodeset_done(struct userdata *u) pa_xfree((void *)ns->class_name[i]); free(ns); - } + } } @@ -98,7 +98,7 @@ void pa_nodeset_done(struct userdata *u) int pa_nodeset_add_class(struct userdata *u, mir_node_type t,const char *clnam) { pa_nodeset *ns; - + pa_assert(u); pa_assert(t >= mir_application_class_begin && t < mir_application_class_end); @@ -196,7 +196,7 @@ pa_nodeset_map *pa_nodeset_get_map_by_role(struct userdata *u, map = pa_hashmap_get(ns->roles, role); else map = NULL; - + return map; } @@ -258,7 +258,7 @@ pa_nodeset_map *pa_nodeset_get_map_by_binary(struct userdata *u, map = pa_hashmap_get(ns->binaries, bin); else map = NULL; - + return map; } @@ -311,7 +311,7 @@ mir_node *mir_node_create(struct userdata *u, mir_node *data) pa_assert_se((ns = u->nodeset)); pa_assert(data->key); pa_assert(data->paname); - + node = pa_xnew0(mir_node, 1); pa_idxset_put(ns->nodes, node, &node->index); @@ -339,7 +339,7 @@ mir_node *mir_node_create(struct userdata *u, mir_node *data) MIR_DLIST_INIT(node->rtentries); MIR_DLIST_INIT(node->rtprilist); MIR_DLIST_INIT(node->constrains); - + if (node->implement == mir_device) { node->pacard.index = data->pacard.index; if (data->pacard.profile) @@ -480,7 +480,7 @@ const char *mir_location_str(mir_location location) case mir_external: return "external"; default: return "< ??? >"; } -} +} const char *mir_node_type_str(mir_node_type type) @@ -566,12 +566,12 @@ static int print_map(pa_hashmap *map, const char *name, char *buf, int len) } } } - + return p - buf; #undef PRINT } - + /* * Local Variables: * c-basic-offset: 4 diff --git a/murphy/userdata.h b/murphy/userdata.h index b43c82b..dc38aa3 100644 --- a/murphy/userdata.h +++ b/murphy/userdata.h @@ -43,6 +43,7 @@ #define PA_PROP_NODE_ROLE "node.role" #define PA_PROP_RESOURCE_SET_ID "resource.set.id" #define PA_PROP_RESOURCE_SET_APPID "resource.set.appid" +#define PA_PROP_RESOURCE_SET_NAME "resource.set.name" #define PA_PROP_RESOURCE_PRIORITY "resource.set.priority" #define PA_PROP_RESOURCE_SET_FLAGS "resource.set.flags" #define PA_PROP_RESOURCE_AUDIO_FLAGS "resource.audio.flags" diff --git a/murphy/utils.c b/murphy/utils.c index 43aa75e..09cc11b 100644 --- a/murphy/utils.c +++ b/murphy/utils.c @@ -322,6 +322,25 @@ int pa_utils_get_stream_class(pa_proplist *pl) return (int)clid; } +char *pa_utils_get_rsetid(pa_proplist *pl, char *buf, int length) +{ + const char *prop; + + if (buf && length >= 2) { + if ((prop = pa_proplist_gets(pl, PA_PROP_RESOURCE_SET_NAME))) { + snprintf(buf, length, "#%s", prop); + return buf; + } + + if ((prop = pa_proplist_gets(pl, PA_PROP_RESOURCE_SET_ID))) { + strncpy(buf, prop, length); + buf[length-1] = '\0'; + return buf; + } + } + + return NULL; +} bool pa_utils_set_resource_properties(pa_proplist *pl, pa_nodeset_resdef *resdef) diff --git a/murphy/utils.h b/murphy/utils.h index e0c345c..26ff93c 100644 --- a/murphy/utils.h +++ b/murphy/utils.h @@ -47,6 +47,7 @@ bool pa_utils_unset_stream_routing_properties(pa_proplist *); void pa_utils_set_stream_routing_method_property(pa_proplist *,bool); bool pa_utils_stream_has_default_route(pa_proplist *); int pa_utils_get_stream_class(pa_proplist *); +char *pa_utils_get_rsetid(pa_proplist *, char *, int); #ifdef foomurphyuserdatafoo /* argh ... */