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,
22 #include <pulsecore/pulsecore-config.h>
24 #include <pulsecore/hashmap.h>
25 #include <pulsecore/idxset.h>
26 #include <pulsecore/strbuf.h>
32 #include "constrain.h"
33 #include "scripting.h"
36 #define APCLASS_DIM (mir_application_class_end - mir_application_class_begin)
42 const char *class_name[APCLASS_DIM];
46 static void free_map_cb(void *);
47 static int print_map(pa_hashmap *, const char *, char *, int);
49 pa_nodeset *pa_nodeset_init(struct userdata *u)
55 ns = pa_xnew0(pa_nodeset, 1);
56 ns->nodes = pa_idxset_new(pa_idxset_trivial_hash_func,
57 pa_idxset_trivial_compare_func);
58 ns->roles = pa_hashmap_new(pa_idxset_string_hash_func,
59 pa_idxset_string_compare_func);
60 ns->binaries = pa_hashmap_new(pa_idxset_string_hash_func,
61 pa_idxset_string_compare_func);
65 void pa_nodeset_done(struct userdata *u)
68 pa_nodeset_map *role, *binary;
72 if (u && (ns = u->nodeset)) {
73 pa_idxset_free(ns->nodes, NULL);
75 PA_HASHMAP_FOREACH(role, ns->roles, state) {
76 pa_xfree((void *)role->name);
77 pa_xfree((void *)role->resdef);
80 pa_hashmap_free(ns->roles);
82 PA_HASHMAP_FOREACH(binary, ns->binaries, state) {
83 pa_xfree((void *)binary->name);
84 pa_xfree((void *)binary->resdef);
87 pa_hashmap_free(ns->binaries);
89 for (i = 0; i < APCLASS_DIM; i++)
90 pa_xfree((void *)ns->class_name[i]);
98 int pa_nodeset_add_class(struct userdata *u, mir_node_type t,const char *clnam)
103 pa_assert(t >= mir_application_class_begin &&
104 t < mir_application_class_end);
106 pa_assert_se((ns = u->nodeset));
108 if (!ns->class_name[t]) {
109 ns->class_name[t] = pa_xstrdup(clnam);
116 void pa_nodeset_delete_class(struct userdata *u, mir_node_type t)
121 pa_assert(t >= mir_application_class_begin &&
122 t < mir_application_class_end);
123 pa_assert_se((ns = u->nodeset));
125 pa_xfree((void *)ns->class_name[t]);
127 ns->class_name[t] = NULL;
130 const char *pa_nodeset_get_class(struct userdata *u, mir_node_type t)
135 pa_assert_se((ns = u->nodeset));
137 if (t >= mir_application_class_begin && t < mir_application_class_end)
138 return ns->class_name[t];
143 int pa_nodeset_add_role(struct userdata *u,
146 pa_nodeset_resdef *resdef)
153 pa_assert(type >= mir_application_class_begin &&
154 type < mir_application_class_end);
155 pa_assert_se((ns = u->nodeset));
157 map = pa_xnew0(pa_nodeset_map, 1);
158 map->name = pa_xstrdup(role);
160 map->role = pa_xstrdup(role);
163 map->resdef = pa_xnew(pa_nodeset_resdef, 1);
164 memcpy(map->resdef, resdef, sizeof(pa_nodeset_resdef));
167 return pa_hashmap_put(ns->roles, (void *)map->name, map);
170 void pa_nodeset_delete_role(struct userdata *u, const char *role)
177 pa_assert_se((ns = u->nodeset));
179 if ((map = pa_hashmap_remove(ns->roles, role))) {
180 pa_xfree((void *)map->name);
181 pa_xfree((void *)map->role);
182 pa_xfree((void *)map->resdef);
186 pa_nodeset_map *pa_nodeset_get_map_by_role(struct userdata *u,
193 pa_assert_se((ns = u->nodeset));
195 if (role && ns->roles)
196 map = pa_hashmap_get(ns->roles, role);
204 int pa_nodeset_add_binary(struct userdata *u,
208 pa_nodeset_resdef *resdef)
215 pa_assert(type >= mir_application_class_begin &&
216 type < mir_application_class_end);
217 pa_assert_se((ns = u->nodeset));
219 map = pa_xnew0(pa_nodeset_map, 1);
220 map->name = pa_xstrdup(bin);
222 map->role = role ? pa_xstrdup(role) : NULL;
225 map->resdef = pa_xnew(pa_nodeset_resdef, 1);
226 memcpy(map->resdef, resdef, sizeof(pa_nodeset_resdef));
229 return pa_hashmap_put(ns->binaries, (void *)map->name, map);
232 void pa_nodeset_delete_binary(struct userdata *u, const char *bin)
239 pa_assert_se((ns = u->nodeset));
241 if ((map = pa_hashmap_remove(ns->binaries, bin))) {
242 pa_xfree((void *)map->name);
243 pa_xfree((void *)map->role);
244 pa_xfree((void *)map->resdef);
248 pa_nodeset_map *pa_nodeset_get_map_by_binary(struct userdata *u,
255 pa_assert_se((ns = u->nodeset));
258 map = pa_hashmap_get(ns->binaries, bin);
266 int pa_nodeset_print_maps(struct userdata *u, char *buf, int len)
275 pa_assert_se((ns = u->nodeset));
279 p += print_map(ns->roles, "roles", p, e-p);
280 p += print_map(ns->binaries, "binaries", p, e-p);
285 mir_node *pa_nodeset_iterate_nodes(struct userdata *u, uint32_t *pidx)
293 pa_assert_se((ns = u->nodeset));
294 pa_assert_se((idxset = ns->nodes));
296 if (*pidx == PA_IDXSET_INVALID)
297 node = pa_idxset_first(idxset, pidx);
299 node = pa_idxset_next(idxset, pidx);
304 mir_node *mir_node_create(struct userdata *u, mir_node *data)
311 pa_assert_se((ns = u->nodeset));
312 pa_assert(data->key);
313 pa_assert(data->paname);
315 node = pa_xnew0(mir_node, 1);
317 pa_idxset_put(ns->nodes, node, &node->index);
319 node->key = pa_xstrdup(data->key);
320 node->direction = data->direction;
321 node->implement = data->implement;
322 node->channels = data->channels;
323 node->location = data->location;
324 node->privacy = data->privacy;
325 node->type = data->type;
326 node->zone = pa_xstrdup(data->zone);
327 node->visible = data->visible;
328 node->available = data->available;
329 node->amname = pa_xstrdup(data->amname ? data->amname : data->paname);
330 node->amdescr = pa_xstrdup(data->amdescr ? data->amdescr : "");
331 node->amid = data->amid;
332 node->paname = pa_xstrdup(data->paname);
333 node->paidx = data->paidx;
334 node->mux = data->mux;
335 node->loop = data->loop;
336 node->stamp = data->stamp;
337 node->rsetid = data->rsetid ? pa_xstrdup(data->rsetid) : NULL;
338 node->scripting = pa_scripting_node_create(u, node);
339 MIR_DLIST_INIT(node->rtentries);
340 MIR_DLIST_INIT(node->rtprilist);
341 MIR_DLIST_INIT(node->constrains);
343 if (node->implement == mir_device) {
344 node->pacard.index = data->pacard.index;
345 if (data->pacard.profile)
346 node->pacard.profile = pa_xstrdup(data->pacard.profile);
348 node->paport = pa_xstrdup(data->paport);
351 mir_router_register_node(u, node);
356 void mir_node_destroy(struct userdata *u, mir_node *node)
361 pa_assert_se((ns = u->nodeset));
364 if (node->implement == mir_stream) {
366 pa_murphyif_destroy_resource_set(u, node);
368 pa_murphyif_delete_node(u, node);
371 mir_router_unregister_node(u, node);
372 pa_scripting_node_destroy(u, node);
374 pa_idxset_remove_by_index(ns->nodes, node->index);
377 pa_xfree(node->zone);
378 pa_xfree(node->amname);
379 pa_xfree(node->amdescr);
380 pa_xfree(node->paname);
381 pa_xfree(node->pacard.profile);
382 pa_xfree(node->paport);
383 pa_xfree(node->rsetid);
389 mir_node *mir_node_find_by_index(struct userdata *u, uint32_t nodidx)
395 pa_assert_se((ns = u->nodeset));
397 node = pa_idxset_get_by_index(ns->nodes, nodidx);
403 int mir_node_print(mir_node *node, char *buf, int len)
414 pa_multiplex_print(node->mux, mux, sizeof(mux));
415 pa_loopback_print(node->loop, loop, sizeof(loop));
416 mir_constrain_print(node, constr, sizeof(constr));
420 #define PRINT(f,v) if (p < e) p += snprintf(p, e-p, f "\n", v)
422 PRINT(" index : %u" , node->index);
423 PRINT(" key : '%s'", node->key ? node->key : "");
424 PRINT(" direction : %s" , mir_direction_str(node->direction));
425 PRINT(" implement : %s" , mir_implement_str(node->implement));
426 PRINT(" channels : %u" , node->channels);
427 PRINT(" location : %s" , mir_location_str(node->location));
428 PRINT(" privacy : %s" , mir_privacy_str(node->privacy));
429 PRINT(" type : %s" , mir_node_type_str(node->type));
430 PRINT(" zone : '%s'", node->zone ? node->zone : "");
431 PRINT(" visible : %s" , node->visible ? "yes" : "no");
432 PRINT(" available : %s" , node->available ? "yes" : "no");
433 PRINT(" ignore : %s" , node->ignore ? "yes" : "no");
434 PRINT(" localrset : %s" , node->localrset ? "yes" : "no");
435 PRINT(" amname : '%s'", node->amname ? node->amname : "");
436 PRINT(" amdescr : '%s'", node->amdescr ? node->amdescr : "");
437 PRINT(" amid : %u" , node->amid);
438 PRINT(" paname : '%s'", node->paname ? node->paname : "");
439 PRINT(" paidx : %u" , node->paidx);
440 PRINT(" pacard.index : %u" , node->pacard.index);
441 PRINT(" pacard.profile: '%s'", node->pacard.profile ?
442 node->pacard.profile : "");
443 PRINT(" paport : '%s'", node->paport ? node->paport : "");
444 PRINT(" mux : %s" , mux);
445 PRINT(" loop : %s" , loop);
446 PRINT(" constrain : %s" , constr);
447 PRINT(" rsetid : '%s'", node->rsetid ? node->rsetid : "");
448 PRINT(" stamp : %u" , node->stamp);
455 const char *mir_direction_str(mir_direction direction)
458 case mir_direction_unknown: return "unknown";
459 case mir_input: return "input";
460 case mir_output: return "output";
461 default: return "< ??? >";
465 const char *mir_implement_str(mir_implement implement)
468 case mir_implementation_unknown: return "unknown";
469 case mir_device: return "device";
470 case mir_stream: return "stream";
471 default: return "< ??? >";
475 const char *mir_location_str(mir_location location)
478 case mir_location_unknown: return "unknown";
479 case mir_internal: return "internal";
480 case mir_external: return "external";
481 default: return "< ??? >";
486 const char *mir_node_type_str(mir_node_type type)
489 case mir_node_type_unknown: return "Unknown";
490 case mir_radio: return "Radio";
491 case mir_player: return "Player";
492 case mir_navigator: return "Navigator";
493 case mir_game: return "Game";
494 case mir_browser: return "Browser";
495 case mir_camera: return "Camera";
496 case mir_phone: return "Phone";
497 case mir_alert: return "Alert";
498 case mir_event: return "Event";
499 case mir_system: return "System";
500 case mir_speakers: return "Speakers";
501 case mir_microphone: return "Microphone";
502 case mir_jack: return "Line";
503 case mir_spdif: return "SPDIF";
504 case mir_hdmi: return "HDMI";
505 case mir_wired_headset: return "Wired Headset";
506 case mir_wired_headphone: return "Wired Headphone";
507 case mir_usb_headset: return "USB Headset";
508 case mir_bluetooth_sco: return "Bluetooth Mono Handsfree";
509 case mir_bluetooth_carkit: return "Car Kit";
510 case mir_bluetooth_a2dp: return "Bluetooth Stereo Headphone";
511 case mir_bluetooth_source: return "Bluetooth Source";
512 case mir_bluetooth_sink: return "Bluetooth Sink";
513 case mir_gateway_sink: return "Gateway Sink";
514 case mir_gateway_source: return "Gateway Source";
515 default: return "<user defined>";
520 const char *mir_privacy_str(mir_privacy privacy)
523 case mir_privacy_unknown: return "<unknown>";
524 case mir_public: return "public";
525 case mir_private: return "private";
526 default: return "< ??? >";
531 static void free_map_cb(void *void_map)
533 pa_nodeset_map *map = (pa_nodeset_map *)void_map;
535 pa_xfree((void *)map->name);
536 pa_xfree((void *)map->resdef);
541 static int print_map(pa_hashmap *map, const char *name, char *buf, int len)
543 #define PRINT(fmt,args...) \
544 do { if (p < e) p += snprintf(p, e-p, fmt "\n", args); } while (0)
547 pa_nodeset_resdef *r;
554 if (buf && len > 0) {
555 PRINT("%s mappings:", name);
557 PA_HASHMAP_FOREACH(m, map, state) {
558 type = mir_node_type_str(m->type);
560 if (!(r = m->resdef))
561 PRINT(" %-15s => %-10s", m->name, type);
563 PRINT(" %-15s => %-10s resource: priority %u, flags rset "
564 "0x%x, audio 0x%x", m->name, type, r->priority,
565 r->flags.rset, r->flags.audio);
578 * indent-tabs-mode: nil