node, discover: add zone support
[profile/ivi/pulseaudio-module-murphy-ivi.git] / murphy / utils.c
1 /*
2  * module-murphy-ivi -- PulseAudio module for providing audio routing support
3  * Copyright (c) 2012, Intel Corporation.
4  *
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.
8  *
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.
13  *
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,
17  * MA 02110-1301 USA.
18  *
19  */
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <sys/stat.h>
23 #include <stdio.h>
24 #include <errno.h>
25 #include <string.h>
26 #include <fcntl.h>
27 #include <unistd.h>
28 #include <limits.h>
29
30 #include <sys/types.h>
31 #include <sys/socket.h>
32
33 #include <pulsecore/pulsecore-config.h>
34
35 #include <pulsecore/core-util.h>
36 #include <pulsecore/card.h>
37 #include <pulsecore/sink.h>
38 #include <pulsecore/source.h>
39 #include <pulsecore/sink-input.h>
40 #include <pulsecore/source-output.h>
41
42 #include "userdata.h"
43 #include "utils.h"
44 #include "node.h"
45
46
47 #define DEFAULT_NULL_SINK_NAME "null.mir"
48
49 struct pa_null_sink {
50     char      *name;
51     uint32_t   module_index;
52     uint32_t   sink_index;
53 };
54
55
56 static uint32_t stamp;
57
58 static char *stream_name(pa_proplist *);
59
60
61 pa_null_sink *pa_utils_create_null_sink(struct userdata *u, const char *name)
62 {
63     pa_core      *core;
64     pa_module    *module;
65     pa_null_sink *ns;
66     pa_sink      *sink;
67     pa_sink      *s;
68     uint32_t      idx;
69     char          args[256];
70
71     pa_assert(u);
72     pa_assert_se((core = u->core));
73
74
75     if (!name)
76         name = DEFAULT_NULL_SINK_NAME;
77
78
79     snprintf(args, sizeof(args), "sink_name=\"%s\" channels=2", name);
80     module = pa_module_load(core, "module-null-sink", args);
81     sink = NULL;
82
83     if (!module)
84         pa_log("failed to load null sink '%s'", name);
85     else {
86         PA_IDXSET_FOREACH(s, core->sinks, idx) {
87             if (s->module && s->module == module) {
88                 sink = s;
89                 pa_log_info("mir null sink is '%s'", name);
90                 break;
91             }
92         }
93     }
94
95     ns = pa_xnew0(pa_null_sink, 1);
96     ns->name = pa_xstrdup(name);
97     ns->module_index = module ? module->index : PA_IDXSET_INVALID;
98     ns->sink_index = sink ? sink->index : PA_IDXSET_INVALID;
99
100     return ns;
101 }
102
103 void pa_utils_destroy_null_sink(struct userdata *u)
104 {
105     pa_core      *core;
106     pa_module    *module;
107     pa_null_sink *ns;
108
109     if (u && (ns = u->nullsink) && (core = u->core)) {
110         if ((module = pa_idxset_get_by_index(core->modules,ns->module_index))){
111             pa_log_info("unloading null sink '%s'", ns->name);
112             pa_module_unload(core, module, FALSE);
113         }
114
115         pa_xfree(ns->name);
116         pa_xfree(ns);
117     }
118 }
119
120 pa_sink *pa_utils_get_null_sink(struct userdata *u)
121 {
122     pa_core *core;
123     pa_null_sink *ns;
124
125     pa_assert(u);
126     pa_assert_se((core = u->core));
127     pa_assert_se((ns = u->nullsink));
128
129     return pa_idxset_get_by_index(core->sinks, ns->sink_index);
130 }
131
132 pa_source *pa_utils_get_null_source(struct userdata *u)
133 {
134     pa_sink *ns = pa_utils_get_null_sink(u);
135
136     return ns ? ns->monitor_source : NULL;
137 }
138
139
140
141 char *pa_utils_get_card_name(pa_card *card)
142 {
143     return (card && card->name) ? card->name : "<unknown>";
144 }
145
146 char *pa_utils_get_card_bus(pa_card *card)
147 {
148     const char *bus = NULL;
149     char       *name;
150
151     if (card && !(bus = pa_proplist_gets(card->proplist,PA_PROP_DEVICE_BUS))) {
152         name = pa_utils_get_card_name(card);
153         if (!strncmp(name, "alsa_card.", 10)) {
154             if (!strncmp(name + 10, "pci-", 4))
155                 bus = "pci";
156             else if (!strncmp(name + 10, "usb-", 4))
157                 bus = "usb";
158         }
159     }
160
161     return (char *)bus;
162 }
163
164 char *pa_utils_get_sink_name(pa_sink *sink)
165 {
166     return (sink && sink->name) ? sink->name : "<unknown>";
167 }
168
169 char *pa_utils_get_source_name(pa_source *source)
170 {
171     return (source && source->name) ? source->name : "<unknown>";
172 }
173
174 char *pa_utils_get_sink_input_name(pa_sink_input *sinp)
175 {
176     char *name;
177
178     if (sinp && (name = stream_name(sinp->proplist)))
179         return name;
180
181     return "<unknown>";
182 }
183
184 char *pa_utils_get_sink_input_name_from_data(pa_sink_input_new_data *data)
185 {
186     char *name;
187
188     if (data && (name = stream_name(data->proplist)))
189         return name;
190
191     return "<unknown>";
192 }
193
194
195 char *pa_utils_get_source_output_name(pa_source_output *sout)
196 {
197     char *name;
198
199     if (sout && (name = stream_name(sout->proplist)))
200         return name;
201
202     return "<unknown>";
203 }
204
205 char *pa_utils_get_source_output_name_from_data(pa_source_output_new_data*data)
206 {
207     char *name;
208
209     if (data && (name = stream_name(data->proplist)))
210         return name;
211
212     return "<unknown>";
213 }
214
215 char *pa_utils_get_zone(pa_proplist *pl)
216 {
217     const char *zone;
218
219     pa_assert(pl);
220
221     if (!(zone = pa_proplist_gets(pl, PA_PROP_ZONE_NAME)))
222         zone = PA_ZONE_NAME_DEFAULT;
223
224     return (char *)zone;
225 }
226
227 pa_bool_t pa_utils_set_stream_routing_properties(pa_proplist *pl,
228                                                  int          styp,
229                                                  void        *target)
230 {
231     const char    *clnam;
232     const char    *method;
233     char           clid[32];
234
235     pa_assert(pl);
236     pa_assert(styp >= 0);
237
238     snprintf(clid, sizeof(clid), "%d", styp);
239     clnam  = mir_node_type_str(styp);
240     method = target ? PA_ROUTING_EXPLICIT : PA_ROUTING_DEFAULT;
241
242     if (pa_proplist_sets(pl, PA_PROP_ROUTING_CLASS_NAME, clnam ) < 0 ||
243         pa_proplist_sets(pl, PA_PROP_ROUTING_CLASS_ID  , clid  ) < 0 ||
244         pa_proplist_sets(pl, PA_PROP_ROUTING_METHOD    , method) < 0  )
245     {
246         pa_log("failed to set some stream property");
247         return FALSE;
248     }
249
250     return TRUE;
251 }
252
253 pa_bool_t pa_utils_unset_stream_routing_properties(pa_proplist *pl)
254 {
255     pa_assert(pl);
256
257     if (pa_proplist_unset(pl, PA_PROP_ROUTING_CLASS_NAME) < 0 ||
258         pa_proplist_unset(pl, PA_PROP_ROUTING_CLASS_ID  ) < 0 ||
259         pa_proplist_unset(pl, PA_PROP_ROUTING_METHOD    ) < 0  )
260     {
261         pa_log("failed to unset some stream property");
262         return FALSE;
263     }
264
265     return TRUE;
266 }
267
268 void pa_utils_set_stream_routing_method_property(pa_proplist *pl,
269                                                  pa_bool_t explicit)
270 {
271     const char *method = explicit ? PA_ROUTING_EXPLICIT : PA_ROUTING_DEFAULT;
272
273     pa_assert(pl);
274
275     if (pa_proplist_sets(pl, PA_PROP_ROUTING_METHOD, method) < 0) {
276         pa_log("failed to set routing method property on sink-input");
277     }
278 }
279
280 pa_bool_t pa_utils_stream_has_default_route(pa_proplist *pl)
281 {
282     const char *method;
283
284     pa_assert(pl);
285
286     method = pa_proplist_gets(pl, PA_PROP_ROUTING_METHOD);
287
288     if (method && pa_streq(method, PA_ROUTING_DEFAULT))
289         return TRUE;
290
291     return FALSE;
292 }
293
294 int pa_utils_get_stream_class(pa_proplist *pl)
295 {
296     const char *clid_str;
297     char *e;
298     unsigned long int clid = 0;
299
300     pa_assert(pl);
301
302     if ((clid_str = pa_proplist_gets(pl, PA_PROP_ROUTING_CLASS_ID))) {
303         clid = strtoul(clid_str, &e, 10);
304
305         if (*e)
306             clid = 0;
307     }
308
309     return (int)clid;
310 }
311
312 void pa_utils_set_port_properties(pa_device_port *port, mir_node *node)
313 {
314     char nodeidx[256];
315
316     pa_assert(port);
317     pa_assert(port->proplist);
318     pa_assert(node);
319
320     snprintf(nodeidx, sizeof(nodeidx), "%u", node->index);
321
322     pa_proplist_sets(port->proplist, PA_PROP_NODE_INDEX, nodeidx);
323 }
324
325 mir_node *pa_utils_get_node_from_port(struct userdata *u,
326                                       pa_device_port *port)
327 {
328     const char *value;
329     char *e;
330     uint32_t index = PA_IDXSET_INVALID;
331     mir_node *node = NULL;
332
333     pa_assert(u);
334     pa_assert(port);
335     pa_assert(port->proplist);
336
337     if ((value = pa_proplist_gets(port->proplist, PA_PROP_NODE_INDEX))) {
338         index = strtoul(value, &e, 10);
339
340         if (value[0] && !e[0])
341             node = mir_node_find_by_index(u, index);
342     }
343
344     return node;
345 }
346
347 mir_node *pa_utils_get_node_from_stream(struct userdata *u,
348                                         mir_direction    type,
349                                         void            *ptr)
350 {
351     pa_sink_input    *sinp;
352     pa_source_output *sout;
353     pa_proplist      *pl;
354     mir_node         *node;
355     const char       *index_str;
356     uint32_t          index = PA_IDXSET_INVALID;
357     char             *e;
358     char              name[256];
359
360     pa_assert(u);
361     pa_assert(ptr);
362     pa_assert(type == mir_input || type == mir_output);
363
364     if (type == mir_input) {
365         sinp = (pa_sink_input *)ptr;
366         pl = sinp->proplist;
367         snprintf(name, sizeof(name), "sink-input.%u", sinp->index);
368     }
369     else {
370         sout = (pa_source_output *)ptr;
371         pl = sout->proplist;
372         snprintf(name, sizeof(name), "source-output.%u", sout->index);
373     }
374
375
376     if ((index_str = pa_proplist_gets(pl, PA_PROP_NODE_INDEX))) {
377         index = strtoul(index_str, &e, 10);
378         if (e != index_str && *e == '\0') {
379             if ((node = mir_node_find_by_index(u, index)))
380                 return node;
381
382             pa_log_debug("can't find find node for %s", name);
383         }
384     }
385
386     return NULL;
387 }
388
389 mir_node *pa_utils_get_node_from_data(struct userdata *u,
390                                       mir_direction    type,
391                                       void            *ptr)
392 {
393     pa_sink_input_new_data *sinp;
394     pa_source_output_new_data *sout;
395     pa_proplist  *pl;
396     mir_node     *node;
397     const char   *index_str;
398     uint32_t      index = PA_IDXSET_INVALID;
399     char         *e;
400     char          name[256];
401
402     pa_assert(u);
403     pa_assert(ptr);
404     pa_assert(type == mir_input || type == mir_output);
405
406     if (type == mir_input) {
407         sinp = (pa_sink_input_new_data *)ptr;
408         pl = sinp->proplist;
409         snprintf(name, sizeof(name), "sink-input");
410     }
411     else {
412         sout = (pa_source_output_new_data *)ptr;
413         pl = sout->proplist;
414         snprintf(name, sizeof(name), "source-output");
415     }
416
417
418     if ((index_str = pa_proplist_gets(pl, PA_PROP_NODE_INDEX))) {
419         index = strtoul(index_str, &e, 10);
420         if (e != index_str && *e == '\0') {
421             if ((node = mir_node_find_by_index(u, index)))
422                 return node;
423
424             pa_log_debug("can't find find node for %s", name);
425         }
426     }
427
428     return NULL;
429 }
430
431 static char *stream_name(pa_proplist *pl)
432 {
433     const char  *appnam;
434     const char  *binnam;
435
436     if ((appnam = pa_proplist_gets(pl, PA_PROP_APPLICATION_NAME)))
437         return (char *)appnam;
438
439     if ((binnam = pa_proplist_gets(pl, PA_PROP_APPLICATION_PROCESS_BINARY)))
440         return (char *)binnam;
441
442     return NULL;
443 }
444
445
446 const char *pa_utils_file_path(const char *dir, const char *file,
447                                char *buf, size_t len)
448 {
449     pa_assert(file);
450     pa_assert(buf);
451     pa_assert(len > 0);
452
453     snprintf(buf, len, "%s/%s", dir, file);
454
455     return buf;
456 }
457
458
459 uint32_t pa_utils_new_stamp(void)
460 {
461     return ++stamp;
462 }
463
464 uint32_t pa_utils_get_stamp(void)
465 {
466     return stamp;
467 }
468
469
470
471
472 /*
473  * Local Variables:
474  * c-basic-offset: 4
475  * indent-tabs-mode: nil
476  * End:
477  *
478  */
479
480