2 * module-murphy-ivi -- PulseAudio module for providing audio routing support
3 * Copyright (c) 2012, Intel Corporation.
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU Lesser General Public License,
7 * version 2.1, as published by the Free Software Foundation.
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE.
12 * See the GNU Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public License
15 * along with this program; if not, write to the
16 * Free Software Foundation, Inc., 51 Franklin St - Fifth Floor, Boston,
30 #include <sys/types.h>
31 #include <sys/socket.h>
33 #include <pulsecore/pulsecore-config.h>
35 #include <pulsecore/core-util.h>
36 #include <pulsecore/sink.h>
37 #include <pulsecore/card.h>
38 #include <pulsecore/source.h>
39 #include <pulsecore/sink-input.h>
40 #include <pulsecore/source-output.h>
47 #define DEFAULT_NULL_SINK_NAME "null.mir"
51 uint32_t module_index;
56 static uint32_t stamp;
58 static char *stream_name(pa_proplist *);
59 static bool get_unsigned_property(pa_proplist *, const char *,uint32_t *);
62 pa_null_sink *pa_utils_create_null_sink(struct userdata *u, const char *name)
73 pa_assert_se((core = u->core));
77 name = DEFAULT_NULL_SINK_NAME;
80 snprintf(args, sizeof(args), "sink_name=\"%s\" channels=2", name);
81 module = pa_module_load(core, "module-null-sink", args);
85 pa_log("failed to load null sink '%s'", name);
87 PA_IDXSET_FOREACH(s, core->sinks, idx) {
88 if (s->module && s->module == module) {
90 pa_log_info("mir null sink is '%s'", name);
96 ns = pa_xnew0(pa_null_sink, 1);
97 ns->name = pa_xstrdup(name);
98 ns->module_index = module ? module->index : PA_IDXSET_INVALID;
99 ns->sink_index = sink ? sink->index : PA_IDXSET_INVALID;
104 void pa_utils_destroy_null_sink(struct userdata *u)
110 if (u && (ns = u->nullsink) && (core = u->core)) {
111 if ((module = pa_idxset_get_by_index(core->modules,ns->module_index))){
112 pa_log_info("unloading null sink '%s'", ns->name);
113 pa_module_unload(core, module, false);
121 pa_sink *pa_utils_get_null_sink(struct userdata *u)
127 pa_assert_se((core = u->core));
128 pa_assert_se((ns = u->nullsink));
130 return pa_idxset_get_by_index(core->sinks, ns->sink_index);
133 pa_source *pa_utils_get_null_source(struct userdata *u)
135 pa_sink *ns = pa_utils_get_null_sink(u);
137 return ns ? ns->monitor_source : NULL;
142 const char *pa_utils_get_card_name(pa_card *card)
144 return (card && card->name) ? card->name : "<unknown>";
147 const char *pa_utils_get_card_bus(pa_card *card)
149 const char *bus = NULL;
152 if (card && !(bus = pa_proplist_gets(card->proplist,PA_PROP_DEVICE_BUS))) {
153 name = pa_utils_get_card_name(card);
154 if (!strncmp(name, "alsa_card.", 10)) {
155 if (!strncmp(name + 10, "pci-", 4))
157 else if (!strncmp(name + 10, "platform-", 9))
159 else if (!strncmp(name + 10, "usb-", 4))
167 const char *pa_utils_get_sink_name(pa_sink *sink)
169 return (sink && sink->name) ? sink->name : "<unknown>";
172 const char *pa_utils_get_source_name(pa_source *source)
174 return (source && source->name) ? source->name : "<unknown>";
177 const char *pa_utils_get_sink_input_name(pa_sink_input *sinp)
181 if (sinp && sinp->proplist && (name = stream_name(sinp->proplist)))
187 const char *pa_utils_get_sink_input_name_from_data(pa_sink_input_new_data *data)
191 if (data && (name = stream_name(data->proplist)))
198 const char *pa_utils_get_source_output_name(pa_source_output *sout)
202 if (sout && sout->proplist && (name = stream_name(sout->proplist)))
208 const char *pa_utils_get_source_output_name_from_data(pa_source_output_new_data*data)
212 if (data && (name = stream_name(data->proplist)))
218 char *pa_utils_get_zone(pa_proplist *pl, pa_proplist *client_props)
224 if (!(zone = pa_proplist_gets(pl, PA_PROP_ZONE_NAME))) {
225 if (!client_props || !(zone = pa_proplist_gets(client_props, PA_PROP_ENV_ZONE)))
226 zone = PA_ZONE_NAME_DEFAULT;
233 const char *pa_utils_get_appid(pa_proplist *pl)
237 if (pl && (appid = pa_proplist_gets(pl, PA_PROP_RESOURCE_SET_APPID)))
243 bool pa_utils_set_stream_routing_properties(pa_proplist *pl,
252 pa_assert(styp >= 0);
254 snprintf(clid, sizeof(clid), "%d", styp);
255 clnam = mir_node_type_str(styp);
256 method = target ? PA_ROUTING_EXPLICIT : PA_ROUTING_DEFAULT;
258 if (pa_proplist_sets(pl, PA_PROP_ROUTING_CLASS_NAME, clnam ) < 0 ||
259 pa_proplist_sets(pl, PA_PROP_ROUTING_CLASS_ID , clid ) < 0 ||
260 pa_proplist_sets(pl, PA_PROP_ROUTING_METHOD , method) < 0 )
262 pa_log("failed to set some stream property");
269 bool pa_utils_unset_stream_routing_properties(pa_proplist *pl)
273 if (pa_proplist_unset(pl, PA_PROP_ROUTING_CLASS_NAME) < 0 ||
274 pa_proplist_unset(pl, PA_PROP_ROUTING_CLASS_ID ) < 0 ||
275 pa_proplist_unset(pl, PA_PROP_ROUTING_METHOD ) < 0 )
277 pa_log("failed to unset some stream property");
284 void pa_utils_set_stream_routing_method_property(pa_proplist *pl,
287 const char *method = explicit ? PA_ROUTING_EXPLICIT : PA_ROUTING_DEFAULT;
291 if (pa_proplist_sets(pl, PA_PROP_ROUTING_METHOD, method) < 0) {
292 pa_log("failed to set routing method property on sink-input");
296 bool pa_utils_stream_has_default_route(pa_proplist *pl)
302 method = pa_proplist_gets(pl, PA_PROP_ROUTING_METHOD);
304 if (method && pa_streq(method, PA_ROUTING_DEFAULT))
310 int pa_utils_get_stream_class(pa_proplist *pl)
312 const char *clid_str;
314 unsigned long int clid = 0;
318 if ((clid_str = pa_proplist_gets(pl, PA_PROP_ROUTING_CLASS_ID))) {
319 clid = strtoul(clid_str, &e, 10);
330 char *pa_utils_get_rsetid(pa_proplist *pl, char *buf, int length)
334 if (buf && length >= 2) {
335 if ((prop = pa_proplist_gets(pl, PA_PROP_RESOURCE_SET_NAME))) {
336 snprintf(buf, (size_t)length, "#%s", prop);
340 if ((prop = pa_proplist_gets(pl, PA_PROP_RESOURCE_SET_ID))) {
341 strncpy(buf, prop, (size_t)length);
342 buf[length-1] = '\0';
350 bool pa_utils_set_resource_properties(pa_proplist *pl,
351 pa_nodeset_resdef *resdef)
362 snprintf(priority , sizeof(priority) , "%d", resdef->priority );
363 snprintf(rsetflags , sizeof(rsetflags) , "%d", resdef->flags.rset );
364 snprintf(audioflags, sizeof(audioflags), "%d", resdef->flags.audio);
366 if (pa_proplist_sets(pl, PA_PROP_RESOURCE_PRIORITY , priority ) < 0 ||
367 pa_proplist_sets(pl, PA_PROP_RESOURCE_SET_FLAGS , rsetflags ) < 0 ||
368 pa_proplist_sets(pl, PA_PROP_RESOURCE_AUDIO_FLAGS, audioflags) < 0 )
370 pa_log("failed to set some resource property");
377 bool pa_utils_unset_resource_properties(pa_proplist *pl)
381 if (pa_proplist_unset(pl, PA_PROP_RESOURCE_PRIORITY ) < 0 ||
382 pa_proplist_unset(pl, PA_PROP_RESOURCE_SET_FLAGS ) < 0 ||
383 pa_proplist_unset(pl, PA_PROP_RESOURCE_AUDIO_FLAGS) < 0 )
385 pa_log("failed to unset some resource property");
392 pa_nodeset_resdef *pa_utils_get_resource_properties(pa_proplist *pl,
393 pa_nodeset_resdef *rd)
400 memset(rd, 0, sizeof(pa_nodeset_resdef));
402 success = get_unsigned_property(pl, PA_PROP_RESOURCE_PRIORITY,
404 success |= get_unsigned_property(pl, PA_PROP_RESOURCE_SET_FLAGS,
406 success |= get_unsigned_property(pl, PA_PROP_RESOURCE_AUDIO_FLAGS,
409 return success ? rd : NULL;
413 static bool get_unsigned_property(pa_proplist *pl,
424 if (!(str = pa_proplist_gets(pl, name))) {
429 *value = strtoul(str, &e, 10);
431 if (e == str || *e) {
440 void pa_utils_set_port_properties(pa_device_port *port, mir_node *node)
447 pa_assert(port->proplist);
449 pa_assert_se((profile = node->pacard.profile));
451 snprintf(propnam, sizeof(propnam), "%s.%s", PA_PROP_NODE_INDEX, profile);
452 snprintf(nodeidx, sizeof(nodeidx), "%u", node->index);
454 pa_proplist_sets(port->proplist, propnam, nodeidx);
458 pa_sink_input *pa_utils_get_stream_origin(struct userdata *u, pa_sink_input *sinp)
460 pa_sink_input *origin = sinp;
468 pa_assert_se((core = u->core) == sinp->core);
470 if ((module = sinp->module) && !strcmp(module->name, "module-combine-sink")) {
471 if (!(mux = pa_multiplex_find_by_module(u->multiplex, module)) ||
472 !(sink = pa_idxset_get_by_index(core->sinks, mux->sink_index)) ||
473 !(origin = pa_idxset_first(sink->inputs, NULL)))
475 pa_log("failed to find origin for sink-input %u", sinp->index);
483 mir_node *pa_utils_get_node_from_port(struct userdata *u,
484 pa_device_port *port,
490 uint32_t index = PA_IDXSET_INVALID;
491 mir_node *node = NULL;
495 pa_assert(port->proplist);
497 while ((name = pa_proplist_iterate(port->proplist, state))) {
498 if (!strncmp(name, PA_PROP_NODE_INDEX, sizeof(PA_PROP_NODE_INDEX)-1)) {
499 if ((value = pa_proplist_gets(port->proplist, name))) {
500 index = strtoul(value, &e, 10);
503 if (value[0] && !e[0])
504 node = mir_node_find_by_index(u, index);
509 pa_log("Can't find node %u for port %s", index, port->name);
517 mir_node *pa_utils_get_node_from_stream(struct userdata *u,
522 pa_source_output *sout;
525 const char *index_str;
526 uint32_t index = PA_IDXSET_INVALID;
532 pa_assert(type == mir_input || type == mir_output);
534 if (type == mir_input) {
535 sinp = (pa_sink_input *)ptr;
537 snprintf(name, sizeof(name), "sink-input.%u", sinp->index);
540 sout = (pa_source_output *)ptr;
542 snprintf(name, sizeof(name), "source-output.%u", sout->index);
546 if ((index_str = pa_proplist_gets(pl, PA_PROP_NODE_INDEX))) {
547 index = strtoul(index_str, &e, 10);
548 if (e != index_str && *e == '\0') {
549 if ((node = mir_node_find_by_index(u, index)))
552 pa_log_debug("can't find find node for %s", name);
559 mir_node *pa_utils_get_node_from_data(struct userdata *u,
563 pa_sink_input_new_data *sinp;
564 pa_source_output_new_data *sout;
567 const char *index_str;
568 uint32_t index = PA_IDXSET_INVALID;
574 pa_assert(type == mir_input || type == mir_output);
576 if (type == mir_input) {
577 sinp = (pa_sink_input_new_data *)ptr;
579 snprintf(name, sizeof(name), "sink-input");
582 sout = (pa_source_output_new_data *)ptr;
584 snprintf(name, sizeof(name), "source-output");
588 if ((index_str = pa_proplist_gets(pl, PA_PROP_NODE_INDEX))) {
589 index = strtoul(index_str, &e, 10);
590 if (e != index_str && *e == '\0') {
591 if ((node = mir_node_find_by_index(u, index)))
594 pa_log_debug("can't find find node for %s", name);
601 static char *stream_name(pa_proplist *pl)
606 if ((appnam = pa_proplist_gets(pl, PA_PROP_APPLICATION_NAME)))
607 return (char *)appnam;
609 if ((binnam = pa_proplist_gets(pl, PA_PROP_APPLICATION_PROCESS_BINARY)))
610 return (char *)binnam;
616 const char *pa_utils_file_path(const char *dir, const char *file,
617 char *buf, size_t len)
623 snprintf(buf, len, "%s/%s", dir, file);
629 uint32_t pa_utils_new_stamp(void)
634 uint32_t pa_utils_get_stamp(void)
644 * indent-tabs-mode: nil