discovery: add support for stream output (i.e. source-ouput in PA terms)
[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 mir_node *pa_utils_get_node_from_stream(struct userdata *u,
269                                         mir_direction    type,
270                                         void            *ptr)
271 {
272     pa_sink_input    *sinp;
273     pa_source_output *sout;
274     pa_proplist      *pl;
275     mir_node         *node;
276     const char       *index_str;
277     uint32_t          index = PA_IDXSET_INVALID;
278     char             *e;
279     char              name[256];
280
281     pa_assert(u);
282     pa_assert(ptr);
283     pa_assert(type == mir_input || type == mir_output);
284
285     if (type == mir_input) {
286         sinp = (pa_sink_input *)ptr;
287         pl = sinp->proplist;
288         snprintf(name, sizeof(name), "sink-input.%u", sinp->index);
289     }
290     else {
291         sout = (pa_source_output *)ptr;
292         pl = sout->proplist;
293         snprintf(name, sizeof(name), "source-output.%u", sout->index);
294     }
295     
296
297     if ((index_str = pa_proplist_gets(pl, PA_PROP_NODE_INDEX))) {
298         index = strtoul(index_str, &e, 10);
299         if (e != index_str && *e == '\0') {
300             if ((node = mir_node_find_by_index(u, index)))
301                 return node;
302
303             pa_log_debug("can't find find node for %s", name);
304         }
305     }
306
307     return NULL;
308 }
309
310 mir_node *pa_utils_get_node_from_data(struct userdata *u,
311                                       mir_direction    type,
312                                       void            *ptr)
313 {
314     pa_sink_input_new_data *sinp;
315     pa_source_output_new_data *sout;
316     pa_proplist  *pl;
317     mir_node     *node;
318     const char   *index_str;
319     uint32_t      index = PA_IDXSET_INVALID;
320     char         *e;
321     char          name[256];
322
323     pa_assert(u);
324     pa_assert(ptr);
325     pa_assert(type == mir_input || type == mir_output);
326
327     if (type == mir_input) {
328         sinp = (pa_sink_input_new_data *)ptr;
329         pl = sinp->proplist;
330         snprintf(name, sizeof(name), "sink-input");
331     }
332     else {
333         sout = (pa_source_output_new_data *)ptr;
334         pl = sout->proplist;
335         snprintf(name, sizeof(name), "source-output");
336     }
337     
338
339     if ((index_str = pa_proplist_gets(pl, PA_PROP_NODE_INDEX))) {
340         index = strtoul(index_str, &e, 10);
341         if (e != index_str && *e == '\0') {
342             if ((node = mir_node_find_by_index(u, index)))
343                 return node;
344
345             pa_log_debug("can't find find node for %s", name);
346         }
347     }
348
349     return NULL;
350 }
351
352 static char *stream_name(pa_proplist *pl)
353 {
354     const char  *appnam;
355     const char  *binnam;
356
357     if ((appnam = pa_proplist_gets(pl, PA_PROP_APPLICATION_NAME)))
358         return (char *)appnam;
359
360     if ((binnam = pa_proplist_gets(pl, PA_PROP_APPLICATION_PROCESS_BINARY)))
361         return (char *)binnam;
362
363     return NULL;
364 }
365
366
367 const char *pa_utils_file_path(const char *file, char *buf, size_t len)
368 {
369     pa_assert(file);
370     pa_assert(buf);
371     pa_assert(len > 0);
372
373     snprintf(buf, len, "%s/%s", DEFAULT_CONFIG_DIR, file);
374
375     return buf;
376 }
377
378
379 uint32_t pa_utils_new_stamp(void)
380 {
381     return ++stamp;
382 }
383
384 uint32_t pa_utils_get_stamp(void)
385 {
386     return stamp;
387 }
388
389
390
391
392 /*
393  * Local Variables:
394  * c-basic-offset: 4
395  * indent-tabs-mode: nil
396  * End:
397  *
398  */
399
400