mir_node_type pa_classify_guess_stream_node_type(struct userdata *u,
- pa_proplist *pl)
+ pa_proplist *pl,
+ pa_nodeset_resdef **resdef)
{
- mir_node_type type;
- const char *role;
- const char *bin;
+ pa_nodeset_map *map;
+ const char *role;
+ const char *bin;
pa_assert(u);
pa_assert(pl);
- if ((bin = pa_proplist_gets(pl, PA_PROP_APPLICATION_PROCESS_BINARY)) &&
- (type = pa_nodeset_get_type_by_binary(u, bin)))
- return type;
- if ((role = pa_proplist_gets(pl, PA_PROP_MEDIA_ROLE)) &&
- (type = pa_nodeset_get_type_by_role(u, role)))
- return type;
+ do {
+ if ((bin = pa_proplist_gets(pl, PA_PROP_APPLICATION_PROCESS_BINARY)) &&
+ (map = pa_nodeset_get_map_by_binary(u, bin)))
+ break;
+
+ if ((role = pa_proplist_gets(pl, PA_PROP_MEDIA_ROLE)) &&
+ (map = pa_nodeset_get_map_by_role(u, role)))
+ break;
+
+ if (resdef)
+ *resdef = NULL;
+
+ return role ? mir_node_type_unknown : mir_player;
+
+ } while (0);
+
+ if (resdef)
+ *resdef = map->resdef;
- return role ? mir_node_type_unknown : mir_player;
+ return map->type;
}
mir_node_type pa_classify_guess_application_class(mir_node *node)
void pa_classify_guess_device_node_type_and_name(mir_node*, const char *,
const char *);
mir_node_type pa_classify_guess_stream_node_type(struct userdata *,
- pa_proplist *);
+ pa_proplist *,
+ pa_nodeset_resdef **);
mir_node_type pa_classify_guess_application_class(mir_node *);
pa_bool_t pa_classify_multiplex_stream(mir_node *);
#include "utils.h"
#include "extapi.h"
#include "stream-state.h"
+#include "murphyif.h"
#define MAX_CARD_TARGET 4
#define MAX_NAME_LENGTH 256
void pa_discover_register_sink_input(struct userdata *u, pa_sink_input *sinp)
{
- pa_core *core;
- pa_discover *discover;
- pa_proplist *pl;
- char *name;
- const char *media;
- mir_node_type type;
- mir_node data;
- mir_node *node;
- mir_node *target;
- char key[256];
- pa_sink *sink;
- const char *role;
+ pa_core *core;
+ pa_discover *discover;
+ pa_proplist *pl;
+ char *name;
+ const char *media;
+ mir_node_type type;
+ mir_node data;
+ mir_node *node;
+ mir_node *target;
+ char key[256];
+ pa_sink *sink;
+ const char *role;
+ pa_nodeset_resdef *resdef;
pa_assert(u);
pa_assert(sinp);
pa_log_debug("registering input stream '%s'", name);
- if (!(type = pa_classify_guess_stream_node_type(u, pl))) {
+ if (!(type = pa_classify_guess_stream_node_type(u, pl, &resdef))) {
pa_log_debug("cant find stream class for '%s'. "
"Leaving it alone", name);
return;
void pa_discover_preroute_sink_input(struct userdata *u,
pa_sink_input_new_data *data)
{
- pa_core *core;
- pa_module *m;
- pa_proplist *pl;
- pa_discover *discover;
- pa_multiplex *multiplex;
- mir_node fake;
- pa_sink *sink;
- pa_sink_input *sinp;
- const char *mnam;
- const char *role;
- mir_node_type type;
- mir_node *node;
- pa_muxnode *mux;
+ pa_core *core;
+ pa_module *m;
+ pa_proplist *pl;
+ pa_discover *discover;
+ pa_multiplex *multiplex;
+ mir_node fake;
+ pa_sink *sink;
+ pa_sink_input *sinp;
+ const char *mnam;
+ const char *role;
+ mir_node_type type;
+ mir_node *node;
+ pa_muxnode *mux;
+ pa_nodeset_resdef *resdef;
pa_assert(u);
pa_assert(data);
data->sink = NULL;
- type = pa_classify_guess_stream_node_type(u, pl);
+ type = pa_classify_guess_stream_node_type(u, pl, NULL);
}
else {
- type = pa_classify_guess_stream_node_type(u, pl);
- if (pa_stream_state_start_corked(u, data, type)) {
+ type = pa_classify_guess_stream_node_type(u, pl, &resdef);
+
+ pa_utils_set_resource_properties(pl, resdef);
+
+ if (pa_stream_state_start_corked(u, data, resdef)) {
pa_log("start corked");
}
}
void pa_discover_add_sink_input(struct userdata *u, pa_sink_input *sinp)
{
- pa_core *core;
- pa_sink *s;
- pa_sink_input *csinp;
- pa_proplist *pl;
- pa_discover *discover;
- pa_multiplex *multiplex;
- mir_node data;
- mir_node *node;
- mir_node *snod;
- char *name;
- const char *media;
- mir_node_type type;
- char key[256];
- pa_bool_t created;
- pa_muxnode *mux;
+ pa_core *core;
+ pa_sink *s;
+ pa_sink_input *csinp;
+ pa_proplist *pl;
+ pa_discover *discover;
+ pa_multiplex *multiplex;
+ mir_node data;
+ mir_node *node;
+ mir_node *snod;
+ char *name;
+ const char *media;
+ mir_node_type type;
+ char key[256];
+ pa_bool_t created;
+ pa_muxnode *mux;
+ pa_nodeset_resdef *resdef;
+ pa_nodeset_resdef rdbuf;
pa_assert(u);
pa_assert(sinp);
pa_assert_se((multiplex = u->multiplex));
pa_assert_se((pl = sinp->proplist));
+ resdef = NULL;
+
if (!(media = pa_proplist_gets(sinp->proplist, PA_PROP_MEDIA_NAME)))
media = "<unknown>";
pa_log_debug("dealing with new input stream '%s'", name);
- if ((type = get_stream_routing_class(pl)) == mir_node_type_unknown) {
- if (!(type = pa_classify_guess_stream_node_type(u, pl))) {
+ if ((type = get_stream_routing_class(pl)))
+ resdef = pa_utils_get_resource_properties(pl, &rdbuf);
+ else {
+ if (!(type = pa_classify_guess_stream_node_type(u, pl, &resdef))) {
pa_log_debug("cant find stream class for '%s'. "
"Leaving it alone", name);
return;
return;
}
+ if (node->rsetid)
+ pa_murphyif_add_node(u, node);
+ else if (resdef)
+ pa_murphyif_create_resource_set(u, node, resdef);
+
pa_discover_add_node_to_ptr_hash(u, sinp, node);
if (!data.mux)
void pa_discover_register_source_output(struct userdata *u,
pa_source_output *sout)
{
- pa_core *core;
- pa_discover *discover;
- pa_proplist *pl;
- char *name;
- const char *media;
- mir_node_type type;
- mir_node data;
- mir_node *node;
- mir_node *target;
- char key[256];
- pa_source *source;
- const char *role;
+ pa_core *core;
+ pa_discover *discover;
+ pa_proplist *pl;
+ char *name;
+ const char *media;
+ mir_node_type type;
+ mir_node data;
+ mir_node *node;
+ mir_node *target;
+ char key[256];
+ pa_source *source;
+ const char *role;
+ pa_nodeset_resdef *resdef;
pa_assert(u);
pa_assert(sout);
pa_log_debug("registering output stream '%s'", name);
- if (!(type = pa_classify_guess_stream_node_type(u, pl))) {
+ if (!(type = pa_classify_guess_stream_node_type(u, pl, &resdef))) {
pa_log_debug("cant find stream class for '%s'. "
"Leaving it alone", name);
return;
void pa_discover_preroute_source_output(struct userdata *u,
pa_source_output_new_data *data)
{
- pa_core *core;
- pa_module *m;
- pa_proplist *pl;
- pa_discover *discover;
- mir_node fake;
- pa_source *source;
- const char *mnam;
- const char *role;
- mir_node_type type;
- mir_node *node;
+ pa_core *core;
+ pa_module *m;
+ pa_proplist *pl;
+ pa_discover *discover;
+ mir_node fake;
+ pa_source *source;
+ const char *mnam;
+ const char *role;
+ mir_node_type type;
+ mir_node *node;
+ pa_nodeset_resdef *resdef;
pa_assert(u);
pa_assert(data);
}
data->source = NULL;
+
+ type = pa_classify_guess_stream_node_type(u, pl, NULL);
+ }
+ else {
+ type = pa_classify_guess_stream_node_type(u, pl, &resdef);
+
+ pa_utils_set_resource_properties(pl, resdef);
}
- type = pa_classify_guess_stream_node_type(u, pl);
+
pa_utils_set_stream_routing_properties(pl, type, data->source);
if (!data->source) {
void pa_discover_add_source_output(struct userdata *u, pa_source_output *sout)
{
- pa_core *core;
- pa_source *s;
- pa_proplist *pl;
- pa_discover *discover;
- mir_node data;
- mir_node *node;
- mir_node *snod;
- char *name;
- const char *media;
- mir_node_type type;
- char key[256];
- pa_bool_t created;
+ pa_core *core;
+ pa_source *s;
+ pa_proplist *pl;
+ pa_discover *discover;
+ mir_node data;
+ mir_node *node;
+ mir_node *snod;
+ char *name;
+ const char *media;
+ mir_node_type type;
+ char key[256];
+ pa_bool_t created;
+ pa_nodeset_resdef *resdef;
+ pa_nodeset_resdef rdbuf;
pa_assert(u);
pa_assert(sout);
pa_assert_se((discover = u->discover));
pa_assert_se((pl = sout->proplist));
+ resdef = NULL;
+
if (!(media = pa_proplist_gets(sout->proplist, PA_PROP_MEDIA_NAME)))
media = "<unknown>";
pa_log_debug("dealing with new output stream '%s'", name);
- if ((type = get_stream_routing_class(pl)) == mir_node_type_unknown) {
- if (!(type = pa_classify_guess_stream_node_type(u, pl))) {
+ if ((type = get_stream_routing_class(pl)))
+ resdef = pa_utils_get_resource_properties(pl, &rdbuf);
+ else {
+ if (!(type = pa_classify_guess_stream_node_type(u, pl, &resdef))) {
pa_log_debug("cant find stream class for '%s'. "
"Leaving it alone", name);
return;
return;
}
+ if (node->rsetid)
+ pa_murphyif_add_node(u, node);
+ else if (resdef)
+ pa_murphyif_create_resource_set(u, node, resdef);
+
pa_discover_add_node_to_ptr_hash(u, sout, node);
}
static mir_node_type get_stream_routing_class(pa_proplist *pl)
{
- const char *clid;
- mir_node_type type;
- char *e;
+ mir_node_type t;
pa_assert(pl);
- if ((clid = pa_proplist_gets(pl, PA_PROP_ROUTING_CLASS_ID))) {
- type = strtol(clid, &e, 10);
+ t = pa_utils_get_stream_class(pl);
- if (!*e) {
- if (type >= mir_application_class_begin &&
- type < mir_application_class_end)
- {
- return type;
- }
- }
- }
+ if (t >= mir_application_class_begin && t < mir_application_class_end)
+ return t;
return mir_node_type_unknown;
}
pa_module *module;
pa_mir_config *config;
int success;
+ char buf[4096];
pa_assert(u);
pa_assert_se((module = u->module));
success = use_default_configuration(u);
}
+ pa_nodeset_print_maps(u, buf, sizeof(buf));
+ pa_log_debug(buf);
+
return success;
}
mir_router_assign_class_to_rtgroup(u, c->class, c->type, c->rtgroup);
for (t = rolemap; t->id; t++)
- pa_nodeset_add_role(u, t->id, t->type);
+ pa_nodeset_add_role(u, t->id, t->type, NULL);
for (t = binmap; t->id; t++)
- pa_nodeset_add_binary(u, t->id, t->type);
+ pa_nodeset_add_binary(u, t->id, t->type, NULL);
for (p = priormap; p->class; p++)
mir_router_assign_class_priority(u, p->class, p->priority);
route = {
output = routing_group.default_output
},
- roles = { "event" },
+ roles = { event = no_resource }
}
application_class {
input = routing_group.phone_input,
output = routing_group.phone_output
},
- roles = { "phone", "carkit" },
+ roles = { phone = no_resource, carkit = no_resource }
}
application_class {
route = {
output = routing_group.default_output
},
- roles = { "ringtone", "alarm" },
+ roles = { ringtone = no_resource, alarm = no_resource }
}
application_class {
route = {
output = routing_group.default_output
},
- roles = { "navigator" },
- needs = { "resource" }
+ roles = { navigator = {0, "autorelease", "mandatory", "shared"} }
}
application_class {
route = {
output = routing_group.default_output
},
- roles = { "game" },
- needs = { "resource" }
+ roles = { game = {0, "mandatory", "exclusive"} }
}
application_class {
route = {
output = routing_group.default_output
},
- roles = { "radio" },
- needs = { "resource" }
+ roles = { radio = {1, "mandatory", "exclusive"} },
}
application_class {
route = {
output = routing_group.default_output
},
- roles = { "music", "video", "test" },
- needs = { "resource" }
+ roles = { music = {1, "mandatory", "exclusive"},
+ video = {1, "mandatory", "exclusive"},
+ test = {0, "mandatory", "exclusive"}
+ }
}
application_class {
route = {
output = routing_group.default_output
},
- roles = { "animation" },
- binaries = { "firefox", "chrome" }
+ roles = { animation = {0, "mandatory", "shared"} },
+ binaries = { firefox = {0, "mandatory","exclusive"},
+ chrome = {0, "mandatory", "exclusive"}
+ }
}
audio_resource {
static pa_bool_t resource_send_message(resource_interface *, mrp_msg_t *,
uint32_t, uint16_t, uint32_t);
static pa_bool_t resource_set_create_node(struct userdata *, mir_node *,
- pa_bool_t);
+ pa_nodeset_resdef *, pa_bool_t);
static pa_bool_t resource_set_create_all(struct userdata *);
static pa_bool_t resource_set_destroy_node(struct userdata *, uint32_t);
static pa_bool_t resource_set_destroy_all(struct userdata *);
#endif
}
-void pa_murphyif_create_resource_set(struct userdata *u, mir_node *node)
+void pa_murphyif_create_resource_set(struct userdata *u,
+ mir_node *node,
+ pa_nodeset_resdef *resdef)
{
pa_core *core;
pa_murphyif *murphyif;
break;
case CONNECTED:
- node->localrset = resource_set_create_node(u, node, TRUE);
+ node->localrset = resource_set_create_node(u, node, resdef, TRUE);
break;
case DISCONNECTED:
static pa_bool_t resource_set_create_node(struct userdata *u,
mir_node *node,
+ pa_nodeset_resdef *resdef,
pa_bool_t acquire)
{
- static uint32_t rset_flags = RESPROTO_RSETFLAG_NOEVENTS |
- RESPROTO_RSETFLAG_AUTOACQUIRE ;
-
pa_core *core;
pa_murphyif *murphyif;
resource_interface *rif;
mrp_msg_t *msg;
uint16_t reqid;
uint32_t seqno;
+ uint32_t rset_flags;
const char *class;
pa_sink_input *sinp;
pa_source_output *sout;
audio_resource_t *res;
const char *resnam;
uint32_t audio_flags = 0;
- uint32_t priority = 0;
+ uint32_t priority;
pa_proplist *proplist = NULL;
pa_bool_t success = TRUE;
pa_assert_se((resnam = res->name));
+ rset_flags = RESPROTO_RSETFLAG_NOEVENTS;
+ rset_flags |= (acquire ? RESPROTO_RSETFLAG_AUTOACQUIRE : 0);
+ rset_flags |= (resdef ? resdef->flags.rset : 0);
+
+ audio_flags = (resdef ? resdef->flags.audio : 0);
+
+ priority = (resdef ? resdef->priority : 0);
+
msg = resource_create_request(seqno, reqid);
if (PUSH_VALUE(msg, RESOURCE_FLAGS , UINT32, rset_flags) &&
while ((node = pa_nodeset_iterate_nodes(u, &idx))) {
if (node->implement == mir_stream && !node->rsetid) {
- node->localrset = resource_set_create_node(u, node, FALSE);
+ node->localrset = resource_set_create_node(u, node, NULL, FALSE);
success &= node->localrset;
}
}
#include "userdata.h"
+
typedef void (*pa_murphyif_watch_cb)(struct userdata *u, const char *,
int, mrp_domctl_value_t **);
const char *);
void pa_murphyif_add_audio_attribute(struct userdata *, const char *,
const char *, mqi_data_type_t, ... );
-void pa_murphyif_create_resource_set(struct userdata *, mir_node *);
+void pa_murphyif_create_resource_set(struct userdata *, mir_node *,
+ pa_nodeset_resdef *);
void pa_murphyif_destroy_resource_set(struct userdata *, mir_node *);
int pa_murphyif_add_node(struct userdata *, mir_node *);
#define APCLASS_DIM (mir_application_class_end - mir_application_class_begin)
struct pa_nodeset {
- pa_idxset *nodes;
- pa_hashmap *roles;
- pa_hashmap *binaries;
- const char *class_name[APCLASS_DIM];
- pa_bool_t need_resource[APCLASS_DIM];
+ pa_idxset *nodes;
+ pa_hashmap *roles;
+ pa_hashmap *binaries;
+ const char *class_name[APCLASS_DIM];
};
+static void free_map_cb(void *, void *);
+static int print_map(pa_hashmap *, const char *, char *, int);
+
pa_nodeset *pa_nodeset_init(struct userdata *u)
{
pa_nodeset *ns;
if (u && (ns = u->nodeset)) {
pa_idxset_free(ns->nodes, NULL, NULL);
- pa_hashmap_free(ns->roles, NULL, NULL);
- pa_hashmap_free(ns->binaries, NULL, NULL);
+ pa_hashmap_free(ns->roles, free_map_cb, u);
+ pa_hashmap_free(ns->binaries, free_map_cb, u);
for (i = 0; i < APCLASS_DIM; i++)
pa_xfree((void *)ns->class_name[i]);
return NULL;
}
-int pa_nodeset_add_role(struct userdata *u, const char *role, mir_node_type t)
+int pa_nodeset_add_role(struct userdata *u,
+ const char *role,
+ mir_node_type type,
+ pa_nodeset_resdef *resdef)
{
pa_nodeset *ns;
- void *value = NULL + t;
+ pa_nodeset_map *map;
pa_assert(u);
pa_assert(role);
- pa_assert(t >= mir_application_class_begin &&
- t < mir_application_class_end);
+ pa_assert(type >= mir_application_class_begin &&
+ type < mir_application_class_end);
pa_assert_se((ns = u->nodeset));
- return pa_hashmap_put(ns->roles, role, value);
+ map = pa_xnew0(pa_nodeset_map, 1);
+ map->name = pa_xstrdup(role);
+ map->type = type;
+
+ if (resdef) {
+ map->resdef = pa_xnew(pa_nodeset_resdef, 1);
+ memcpy(map->resdef, resdef, sizeof(pa_nodeset_resdef));
+ }
+
+ return pa_hashmap_put(ns->roles, map->name, map);
}
void pa_nodeset_delete_role(struct userdata *u, const char *role)
{
+ pa_nodeset_map *map;
pa_nodeset *ns;
pa_assert(u);
pa_assert(role);
pa_assert_se((ns = u->nodeset));
- pa_hashmap_remove(ns->roles, role);
+ if ((map = pa_hashmap_remove(ns->roles, role))) {
+ pa_xfree((void *)map->name);
+ pa_xfree((void *)map->resdef);
+ }
}
-mir_node_type pa_nodeset_get_type_by_role(struct userdata *u, const char *role)
+pa_nodeset_map *pa_nodeset_get_map_by_role(struct userdata *u,
+ const char *role)
{
+ pa_nodeset_map *map;
pa_nodeset *ns;
- mir_node_type t;
pa_assert(u);
pa_assert_se((ns = u->nodeset));
- if (role) {
- t = pa_hashmap_get(ns->roles, role) - NULL;
-
- if (t >= mir_application_class_begin && t < mir_application_class_end)
- return t;
- }
+ if (role)
+ map = pa_hashmap_get(ns->roles, role);
+ else
+ map = NULL;
+
- return mir_node_type_unknown;
+ return map;
}
-int pa_nodeset_add_binary(struct userdata *u, const char *bin, mir_node_type t)
+int pa_nodeset_add_binary(struct userdata *u,
+ const char *bin,
+ mir_node_type type,
+ pa_nodeset_resdef *resdef)
{
pa_nodeset *ns;
- void *value = NULL + t;
+ pa_nodeset_map *map;
pa_assert(u);
pa_assert(bin);
- pa_assert(t >= mir_application_class_begin &&
- t < mir_application_class_end);
+ pa_assert(type >= mir_application_class_begin &&
+ type < mir_application_class_end);
pa_assert_se((ns = u->nodeset));
- return pa_hashmap_put(ns->binaries, bin, value);
+ map = pa_xnew0(pa_nodeset_map, 1);
+ map->name = pa_xstrdup(bin);
+ map->type = type;
+
+ if (resdef) {
+ map->resdef = pa_xnew(pa_nodeset_resdef, 1);
+ memcpy(map->resdef, resdef, sizeof(pa_nodeset_resdef));
+ }
+
+ return pa_hashmap_put(ns->binaries, map->name, map);
}
void pa_nodeset_delete_binary(struct userdata *u, const char *bin)
{
+ pa_nodeset_map *map;
pa_nodeset *ns;
pa_assert(u);
pa_assert(bin);
pa_assert_se((ns = u->nodeset));
- pa_hashmap_remove(ns->binaries, bin);
+ if ((map = pa_hashmap_remove(ns->binaries, bin))) {
+ pa_xfree((void *)map->name);
+ pa_xfree((void *)map->resdef);
+ }
}
-mir_node_type pa_nodeset_get_type_by_binary(struct userdata *u,const char *bin)
+pa_nodeset_map *pa_nodeset_get_map_by_binary(struct userdata *u,
+ const char *bin)
{
+ pa_nodeset_map *map;
pa_nodeset *ns;
- mir_node_type t;
pa_assert(u);
pa_assert_se((ns = u->nodeset));
- if (bin) {
- t = pa_hashmap_get(ns->binaries, bin) - NULL;
-
- if (t >= mir_application_class_begin && t < mir_application_class_end)
- return t;
- }
+ if (bin)
+ map = pa_hashmap_get(ns->binaries, bin);
+ else
+ map = NULL;
+
- return mir_node_type_unknown;
+ return map;
}
-void pa_nodeset_need_resource(struct userdata *u, mir_node_type t)
+int pa_nodeset_print_maps(struct userdata *u, char *buf, int len)
{
pa_nodeset *ns;
- int ac;
+ char *p, *e;
pa_assert(u);
+ pa_assert(buf);
+ pa_assert(len > 0);
+
pa_assert_se((ns = u->nodeset));
- if (t >= mir_application_class_begin && t < mir_application_class_end) {
- ac = t - mir_application_class_begin;
- ns->need_resource[ac] = TRUE;
- }
+ e = (p = buf) + len;
+
+ p += print_map(ns->roles, "roles", p, e-p);
+ p += print_map(ns->binaries, "binaries", p, e-p);
+
+ return p - buf;
}
mir_node *pa_nodeset_iterate_nodes(struct userdata *u, uint32_t *pidx)
mir_router_register_node(u, node);
- if (node->implement == mir_stream) {
- if (!node->rsetid && mir_node_need_resource(u, node->type))
- pa_murphyif_create_resource_set(u, node);
- else
- pa_murphyif_add_node(u, node);
- }
return node;
}
if (node) {
if (node->implement == mir_stream) {
- if (node->type >= mir_application_class_begin &&
- node->type < mir_application_class_end &&
- ns->need_resource[node->type])
- {
+ if (node->localrset)
pa_murphyif_destroy_resource_set(u, node);
- }
- else {
+ else
pa_murphyif_delete_node(u, node);
- }
}
mir_router_unregister_node(u, node);
return node;
}
-pa_bool_t mir_node_need_resource(struct userdata *u, mir_node_type type)
-{
- pa_nodeset *ns;
-
- pa_assert(u);
- pa_assert_se((ns = u->nodeset));
- pa_assert(ns->need_resource);
-
- if (type < mir_application_class_begin ||
- type >= mir_application_class_end )
- return FALSE;
-
- return ns->need_resource[type];
-}
int mir_node_print(mir_node *node, char *buf, int len)
{
}
}
+
+static void free_map_cb(void *void_map, void *void_userdata)
+{
+ struct userdata *u = (struct userdata *)void_userdata;
+ pa_nodeset_map *map = (pa_nodeset_map *)void_map;
+
+ pa_xfree((void *)map->name);
+ pa_xfree((void *)map->resdef);
+
+ pa_xfree(map);
+}
+
+static int print_map(pa_hashmap *map, const char *name, char *buf, int len)
+{
+#define PRINT(fmt,args...) \
+ do { if (p < e) p += snprintf(p, e-p, fmt "\n", args); } while (0)
+
+ pa_nodeset_map *m;
+ pa_nodeset_resdef *r;
+ const char *type;
+ void *state;
+ char *p, *e;
+
+ e = (p = buf) + len;
+
+ if (buf && len > 0) {
+ PRINT("%s mappings:", name);
+
+ PA_HASHMAP_FOREACH(m, map, state) {
+ type = mir_node_type_str(m->type);
+
+ if (!(r = m->resdef))
+ PRINT(" %-15s => %-10s", m->name, type);
+ else {
+ PRINT(" %-15s => %-10s resource: priority %u, flags rset "
+ "0x%x, audio 0x%x", m->name, type, r->priority,
+ r->flags.rset, r->flags.audio);
+ }
+ }
+ }
+
+ return p - buf;
+
+#undef PRINT
+}
/*
* Local Variables:
mir_private
};
+struct pa_nodeset_resdef {
+ uint32_t priority;
+ struct {
+ uint32_t rset;
+ uint32_t audio;
+ } flags;
+};
+
+struct pa_nodeset_map {
+ const char *name;
+ mir_node_type type;
+ pa_nodeset_resdef *resdef;
+};
+
struct pa_node_card {
uint32_t index;
char *profile;
void pa_nodeset_delete_class(struct userdata *, mir_node_type);
const char *pa_nodeset_get_class(struct userdata *, mir_node_type);
-int pa_nodeset_add_role(struct userdata *, const char *, mir_node_type);
+int pa_nodeset_add_role(struct userdata *, const char *, mir_node_type,
+ pa_nodeset_resdef *);
void pa_nodeset_delete_role(struct userdata *, const char *);
-mir_node_type pa_nodeset_get_type_by_role(struct userdata *, const char *);
+pa_nodeset_map *pa_nodeset_get_map_by_role(struct userdata *, const char *);
-int pa_nodeset_add_binary(struct userdata *, const char *, mir_node_type);
+int pa_nodeset_add_binary(struct userdata *, const char *, mir_node_type,
+ pa_nodeset_resdef *);
void pa_nodeset_delete_binary(struct userdata *, const char *);
-mir_node_type pa_nodeset_get_type_by_binary(struct userdata *, const char *);
+pa_nodeset_map *pa_nodeset_get_map_by_binary(struct userdata *, const char *);
-void pa_nodeset_need_resource(struct userdata *, mir_node_type);
+int pa_nodeset_print_maps(struct userdata *, char *, int);
mir_node *pa_nodeset_iterate_nodes(struct userdata *, uint32_t *);
mir_node *mir_node_find_by_index(struct userdata *, uint32_t);
-pa_bool_t mir_node_need_resource(struct userdata *, mir_node_type);
int mir_node_print(mir_node *, char *, int);
#include <errno.h>
#include <pulsecore/pulsecore-config.h>
+#include <pulsecore/core-util.h>
#include <murphy/common/macros.h>
#include <murphy/core/lua-utils/object.h>
#include <murphy/core/lua-utils/funcbridge.h>
#include <murphy/domain-control/client.h>
#include <murphy/resource/data-types.h>
+#include <murphy/resource/protocol.h>
#include "scripting.h"
#include "node.h"
const char *output;
} route_t;
+typedef struct {
+ const char *name;
+ pa_bool_t needres;
+ pa_nodeset_resdef resource;
+} map_t;
+
struct scripting_apclass {
struct userdata *userdata;
const char *name;
mir_node_type type;
int priority;
route_t *route;
- mrp_lua_strarray_t *roles;
- mrp_lua_strarray_t *binaries;
+ map_t *roles;
+ map_t *binaries;
struct {
pa_bool_t resource;
} needs;
CLASS,
INPUT,
LIMIT,
- NEEDS,
ROUTE,
ROLES,
TABLE,
IMPLEMENT,
NODE_TYPE,
ATTRIBUTES,
+ AUTORELEASE,
DESCRIPTION,
} field_t;
static attribute_t *attributes_check(lua_State *, int);
static void attributes_destroy(attribute_t *);
+static map_t *map_check(lua_State *, int);
+static int map_push(lua_State *, map_t *);
+static void map_destroy(map_t *);
+
static field_t field_check(lua_State *, int, const char **);
static field_t field_name_to_type(const char *, size_t);
static int make_id(char *buf, size_t len, const char *fmt, ...);
mir_node_type type = -1;
int priority = -1;
route_t *route = NULL;
- mrp_lua_strarray_t *roles = NULL;
- mrp_lua_strarray_t *binaries = NULL;
- mrp_lua_strarray_t *needs = NULL;
+ map_t *roles = NULL;
+ map_t *binaries = NULL;
pa_bool_t needs_resource = FALSE;
- const char *role;
- const char *binary;
- const char *need;
+ pa_nodeset_resdef *resdef;
+ map_t *r, *b;
size_t i;
pa_bool_t ir, or;
case NODE_TYPE: type = luaL_checkint(L, -1); break;
case PRIORITY: priority = luaL_checkint(L, -1); break;
case ROUTE: route = route_check(L, -1); break;
- case ROLES: roles = mrp_lua_check_strarray(L, -1); break;
- case BINARIES: binaries = mrp_lua_check_strarray(L, -1); break;
- case NEEDS: needs = mrp_lua_check_strarray(L, -1); break;
+ case ROLES: roles = map_check(L, -1); break;
+ case BINARIES: binaries = map_check(L, -1); break;
default: luaL_error(L, "bad field '%s'", fldnam); break;
}
} /* MRP_LUA_FOREACH_FIELD */
- if (needs) {
- for (i = 0; i < needs->nstring; i++) {
- need = needs->strings[i];
-
- if (!strcmp(need, "resource"))
- needs_resource = TRUE;
- else
- luaL_error(L, "invalid need '%s'", need);
- }
- }
-
- if (needs_resource && !class)
- luaL_error(L, "missing or invalid class field");
if (type < mir_application_class_begin ||
type >= mir_application_class_end )
luaL_error(L, "missing or invalid node_type %d", type);
luaL_error(L, "missing or invalid priority field");
if (!route)
luaL_error(L, "missing or invalid route field");
+ if (!roles && !binaries)
+ luaL_error(L, "missing roles or binaries");
make_id(name, sizeof(name), "%s", mir_node_type_str(type));
}
if (roles) {
- for (i = 0; i < roles->nstring; i++) {
- role = roles->strings[i];
+ for (r = roles; r->name; r++) {
+ resdef = r->needres ? &r->resource : NULL;
- if (pa_nodeset_add_role(u, role, type)) {
+ if (pa_nodeset_add_role(u, r->name, type, resdef)) {
luaL_error(L, "role '%s' is added to mutiple application "
- "classes", role);
+ "classes", r->name);
}
}
}
if (binaries) {
- for (i = 0; i < binaries->nstring; i++) {
- binary = binaries->strings[i];
+ for (b = binaries; b->name; b++) {
+ resdef = b->needres ? &b->resource : NULL;
- if (pa_nodeset_add_binary(u, binary, type)) {
+ if (pa_nodeset_add_binary(u, b->name, type, resdef)) {
luaL_error(L, "binary '%s' is added to multiple application "
- "classes", binary);
+ "classes", b->name);
}
}
}
- if (needs_resource)
- pa_nodeset_need_resource(u, type);
-
MRP_LUA_LEAVE(1);
}
lua_pushnil(L);
else {
switch (fld) {
- case NAME: lua_pushstring(L, ac->name); break;
- case NODE_TYPE: lua_pushinteger(L, ac->type); break;
- case PRIORITY: lua_pushinteger(L, ac->priority); break;
- case ROUTE: route_push(L, ac->route); break;
- case ROLES: mrp_lua_push_strarray(L, ac->roles); break;
- case BINARIES: mrp_lua_push_strarray(L, ac->binaries); break;
- default: lua_pushnil(L); break;
+ case NAME: lua_pushstring(L, ac->name); break;
+ case NODE_TYPE: lua_pushinteger(L, ac->type); break;
+ case PRIORITY: lua_pushinteger(L, ac->priority); break;
+ case ROUTE: route_push(L, ac->route); break;
+ case ROLES: map_push(L, ac->roles); break;
+ case BINARIES: map_push(L, ac->binaries); break;
+ default: lua_pushnil(L); break;
}
}
{
scripting_apclass *ac = (scripting_apclass *)data;
struct userdata *u;
- mrp_lua_strarray_t *roles;
- mrp_lua_strarray_t *binaries;
+ map_t *r, *b;
size_t i;
MRP_LUA_ENTER;
pa_xfree((void *)ac->class);
ac->class = NULL;
- if ((roles = ac->roles)) {
- for (i = 0; i < roles->nstring; i++)
- pa_nodeset_delete_role(u, roles->strings[i]);
+ if (ac->roles) {
+ for (r = ac->roles; r->name; r++)
+ pa_nodeset_delete_role(u, r->name);
- mrp_lua_free_strarray(ac->roles);
+ map_destroy(ac->roles);
ac->roles = NULL;
}
- if ((binaries = ac->binaries)) {
- for (i = 0; i < binaries->nstring; i++)
- pa_nodeset_delete_binary(u, binaries->strings[i]);
+ if (ac->binaries) {
+ for (b = ac->binaries; b->name; b++)
+ pa_nodeset_delete_binary(u, b->name);
- mrp_lua_free_strarray(ac->binaries);
+ map_destroy(ac->binaries);
ac->binaries = NULL;
}
}
}
+static map_t *map_check(lua_State *L, int tbl)
+{
+ int def;
+ size_t namlen;
+ const char *name;
+ const char *flag;
+ map_t *m, *map = NULL;
+ size_t n = 0;
+ size_t i, len;
+ int priority;
+ pa_nodeset_resdef *rd;
+
+ tbl = (tbl < 0) ? lua_gettop(L) + tbl + 1 : tbl;
+
+ luaL_checktype(L, tbl, LUA_TTABLE);
+
+ MRP_LUA_FOREACH_FIELD(L, tbl, name, namlen) {
+ if (!name[0])
+ luaL_error(L, "invalid role or binary definition");
+
+ map = pa_xrealloc(map, sizeof(map_t) * (n + 2));
+ memset(map + n, 0, sizeof(map_t) * 2);
+
+ m = map + n++;
+ def = lua_gettop(L);
+
+ m->name = pa_xstrdup(name);
+
+ switch (lua_type(L, -1)) {
+
+ case LUA_TNUMBER:
+ m->needres = FALSE;
+ break;
+
+ case LUA_TTABLE:
+ m->needres = TRUE;
+
+ if ((len = luaL_getn(L, def)) < 1)
+ luaL_error(L, "invalid resource definition '%s'", name);
+
+ for (i = 1; i <= len; i++) {
+ lua_pushnumber(L, (int)i);
+ lua_gettable(L, def);
+
+ if (i == 1) {
+ priority = luaL_checkint(L, -1);
+
+ if (priority < 0 || priority > 7) {
+ luaL_error(L, "invalid priority %d for '%s'",
+ priority, name);
+ }
+
+ m->resource.priority = priority;
+ }
+ else {
+ flag = luaL_checkstring(L, -1);
+ rd = &m->resource;
+
+ if (pa_streq(flag, "autorelease"))
+ rd->flags.rset |= RESPROTO_RSETFLAG_AUTORELEASE;
+ else if (pa_streq(flag, "mandatory"))
+ rd->flags.audio |= RESPROTO_RESFLAG_MANDATORY;
+ else if (pa_streq(flag, "shared"))
+ rd->flags.audio |= RESPROTO_RESFLAG_SHARED;
+ else if (!pa_streq(flag, "optional") &&
+ !pa_streq(flag, "exclusive") )
+ {
+ luaL_error(L, "invalid flag '%s' for '%s'", flag,name);
+ }
+ }
+
+ lua_pop(L, 1);
+ }
+
+ break;
+
+ default:
+ luaL_error(L, "invalid resource specification. "
+ "Should be either 'no_resource' or a table");
+ break;
+ }
+ } /* FOREACH_FIELD */
+
+ return map;
+}
+
+static int map_push(lua_State *L, map_t *map)
+{
+ map_t *m;
+
+ if (!map)
+ lua_pushnil(L);
+ else {
+ lua_newtable(L);
+
+ for (m = map; m->name; m++) {
+ if (!m->needres)
+ lua_pushnumber(L, 0);
+ else {
+ lua_newtable(L);
+ lua_pushinteger(L, m->resource.priority);
+ if (m->resource.flags.rset & RESPROTO_RSETFLAG_AUTORELEASE)
+ lua_pushstring(L, "autorelease");
+ if (m->resource.flags.audio & RESPROTO_RESFLAG_MANDATORY)
+ lua_pushstring(L, "mandatory");
+ else
+ lua_pushstring(L, "optional");
+ if (m->resource.flags.audio & RESPROTO_RESFLAG_SHARED)
+ lua_pushstring(L, "shared");
+ else
+ lua_pushstring(L, "exclusive");
+ }
+ lua_setfield(L, -2, m->name);
+ }
+ }
+
+ return 1;
+}
+
+static void map_destroy(map_t *map)
+{
+ map_t *m;
+
+ if (map) {
+ for (m = map; m->name; m++) {
+ pa_xfree((void *)m->name);
+ }
+ pa_xfree(map);
+ }
+}
+
static field_t field_check(lua_State *L, int idx, const char **ret_fldnam)
{
if (!strcmp(name, "limit"))
return LIMIT;
break;
- case 'n':
- if (!strcmp(name, "needs"))
- return NEEDS;
- break;
case 'r':
if (!strcmp(name, "route"))
return ROUTE;
break;
case 11:
+ if (!strcmp(name, "autorelease"))
+ return AUTORELEASE;
if (!strcmp(name, "description"))
return DESCRIPTION;
break;
lua_pop(L, 1);
}
+ lua_pushnumber(L, 0);
+ lua_setglobal(L, "no_resource");
return success;
}
pa_bool_t pa_stream_state_start_corked(struct userdata *u,
pa_sink_input_new_data *data,
- mir_node_type type)
+ pa_nodeset_resdef *resdef)
{
- if (mir_node_need_resource(u, type)) {
+ if (resdef) {
data->flags |= PA_SINK_INPUT_START_CORKED;
return TRUE;
}
pa_bool_t pa_stream_state_start_corked(struct userdata *,
pa_sink_input_new_data *,
- mir_node_type);
+ pa_nodeset_resdef *);
void pa_stream_state_change(struct userdata *u, mir_node *, int);
#define PA_PROP_NODE_TYPE "node.type"
#define PA_PROP_NODE_ROLE "node.role"
#define PA_PROP_RESOURCE_SET_ID "resource.set.id"
+#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"
#define PA_ZONE_NAME_DEFAULT "driver"
typedef struct pa_mir_volume pa_mir_volume;
typedef struct pa_mir_config pa_mir_config;
typedef struct pa_nodeset pa_nodeset;
+typedef struct pa_nodeset_resdef pa_nodeset_resdef;
+typedef struct pa_nodeset_map pa_nodeset_map;
typedef struct pa_node_card pa_node_card;
typedef struct pa_card_hooks pa_card_hooks;
typedef struct pa_port_hooks pa_port_hooks;
static uint32_t stamp;
static char *stream_name(pa_proplist *);
+static pa_bool_t get_unsigned_property(pa_proplist *, const char *,uint32_t *);
pa_null_sink *pa_utils_create_null_sink(struct userdata *u, const char *name)
return (int)clid;
}
+
+pa_bool_t pa_utils_set_resource_properties(pa_proplist *pl,
+ pa_nodeset_resdef *resdef)
+{
+ char priority[32];
+ char rsetflags[32];
+ char audioflags[32];
+
+ pa_assert(pl);
+
+ if (!resdef)
+ return FALSE;
+
+ snprintf(priority , sizeof(priority) , "%d", resdef->priority );
+ snprintf(rsetflags , sizeof(rsetflags) , "%d", resdef->flags.rset );
+ snprintf(audioflags, sizeof(audioflags), "%d", resdef->flags.audio);
+
+ if (pa_proplist_sets(pl, PA_PROP_RESOURCE_PRIORITY , priority ) < 0 ||
+ pa_proplist_sets(pl, PA_PROP_RESOURCE_SET_FLAGS , rsetflags ) < 0 ||
+ pa_proplist_sets(pl, PA_PROP_RESOURCE_AUDIO_FLAGS, audioflags) < 0 )
+ {
+ pa_log("failed to set some resource property");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+pa_bool_t pa_utils_unset_resource_properties(pa_proplist *pl)
+{
+ pa_assert(pl);
+
+ if (pa_proplist_unset(pl, PA_PROP_RESOURCE_PRIORITY ) < 0 ||
+ pa_proplist_unset(pl, PA_PROP_RESOURCE_SET_FLAGS ) < 0 ||
+ pa_proplist_unset(pl, PA_PROP_RESOURCE_AUDIO_FLAGS) < 0 )
+ {
+ pa_log("failed to unset some resource property");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+pa_nodeset_resdef *pa_utils_get_resource_properties(pa_proplist *pl,
+ pa_nodeset_resdef *rd)
+{
+ pa_assert(pl);
+ pa_assert(rd);
+
+ int success;
+
+ memset(rd, 0, sizeof(pa_nodeset_resdef));
+
+ success = get_unsigned_property(pl, PA_PROP_RESOURCE_PRIORITY,
+ &rd->priority);
+ success |= get_unsigned_property(pl, PA_PROP_RESOURCE_SET_FLAGS,
+ &rd->flags.rset);
+ success |= get_unsigned_property(pl, PA_PROP_RESOURCE_AUDIO_FLAGS,
+ &rd->flags.audio);
+
+ return success ? rd : NULL;
+}
+
+
+static pa_bool_t get_unsigned_property(pa_proplist *pl,
+ const char *name,
+ uint32_t *value)
+{
+ const char *str;
+ char *e;
+
+ pa_assert(pl);
+ pa_assert(name);
+ pa_assert(value);
+
+ if (!(str = pa_proplist_gets(pl, name))) {
+ *value = 0;
+ return FALSE;
+ }
+
+ *value = strtoul(str, &e, 10);
+
+ if (e == str || *e) {
+ *value = 0;
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
void pa_utils_set_port_properties(pa_device_port *port, mir_node *node)
{
char nodeidx[256];
-
/*
* Local Variables:
* c-basic-offset: 4
pa_bool_t pa_utils_stream_has_default_route(pa_proplist *);
int pa_utils_get_stream_class(pa_proplist *);
+
#ifdef foomurphyuserdatafoo /* argh ... */
+pa_bool_t pa_utils_set_resource_properties(pa_proplist *, pa_nodeset_resdef *);
+pa_bool_t pa_utils_unset_resource_properties(pa_proplist *);
+pa_nodeset_resdef *pa_utils_get_resource_properties(pa_proplist *,
+ pa_nodeset_resdef *);
+
void pa_utils_set_port_properties(pa_device_port *, mir_node *);
mir_node *pa_utils_get_node_from_port(struct userdata *, pa_device_port *);
mir_node *pa_utils_get_node_from_stream(struct userdata *,mir_direction,void*);