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