2 * module-agl-audio -- PulseAudio module for providing audio routing support
3 * (forked from "module-murphy-ivi" - https://github.com/otcshare )
4 * Copyright (c) 2012, Intel Corporation.
5 * Copyright (c) 2016, IoT.bzh
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms and conditions of the GNU Lesser General Public License,
9 * version 2.1, as published by the Free Software Foundation.
11 * This program is distributed in the hope it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE.
14 * See the GNU Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program; if not, write to the
18 * Free Software Foundation, Inc., 51 Franklin St - Fifth Floor, Boston,
26 #define DEFAULT_NULL_SINK_NAME "null.agl"
28 #ifndef PA_PROP_PROCESS_ENVIRONMENT
29 #define PA_PROP_PROCESS_ENVIRONMENT "application.process.environment"
31 #define PA_ZONE_NAME_DEFAULT "driver"
32 #define PA_PROP_ZONE_NAME "zone.name"
33 #define PA_PROP_ENV_ZONE PA_PROP_PROCESS_ENVIRONMENT ".AUDIO_ZONE"
35 #define PA_PROP_ROUTING_CLASS_NAME "routing.class.name"
36 #define PA_PROP_ROUTING_CLASS_ID "routing.class.id"
37 #define PA_PROP_ROUTING_METHOD "routing.method"
39 static uint32_t stamp;
41 struct agl_null_sink {
43 uint32_t module_index;
47 agl_null_sink *agl_utils_create_null_sink (struct userdata *u, const char *name)
57 pa_assert_se (core = u->core);
60 name = DEFAULT_NULL_SINK_NAME; /* default is "null.agl" */
62 snprintf (args, sizeof(args), "sink_name=\"%s.%d\" channels=2", name, agl_utils_new_stamp ());
63 module = pa_module_load (core, "module-null-sink", args);
67 pa_log ("failed to load null sink '%s'", name);
70 PA_IDXSET_FOREACH(s, core->sinks, idx) {
71 if (s->module && s->module == module) {
73 pa_log_info("created agl null sink named '%s'", name);
79 ns = pa_xnew0 (agl_null_sink, 1);
80 ns->name = pa_xstrdup (name);
81 ns->module_index = module ? module->index : PA_IDXSET_INVALID;
82 ns->sink_index = sink ? sink->index : PA_IDXSET_INVALID;
87 void agl_utils_destroy_null_sink (struct userdata *u, agl_null_sink *ns)
92 if (u && (core = u->core)) {
93 if ((module = pa_idxset_get_by_index (core->modules, ns->module_index))){
94 pa_log_info ("unloading null sink '%s'", ns->name);
95 pa_module_unload (module, false);
103 pa_sink *agl_utils_get_null_sink (struct userdata *u, struct agl_null_sink *ns)
109 pa_assert_se ((core = u->core));
111 return pa_idxset_get_by_index (core->sinks, ns->sink_index);
114 pa_source *agl_utils_get_null_source (struct userdata *u, struct agl_null_sink *ns)
118 sink = agl_utils_get_null_sink (u, ns);
120 return sink ? sink->monitor_source : NULL;
123 void agl_utils_volume_ramp (struct userdata *u, struct agl_null_sink *ns, bool up)
129 pa_cvolume_ramp rampvol;
134 newvol = PA_VOLUME_NORM;
137 newvol = PA_VOLUME_NORM *10/100;
142 pa_assert_se ((core = u->core));
144 sink = agl_utils_get_null_sink (u, ns);
145 PA_IDXSET_FOREACH(sinp, core->sink_inputs, index) {
146 if (sinp->sink && sinp->sink == sink)
152 pa_cvolume_ramp_set (&rampvol, sinp->volume.channels, PA_VOLUME_RAMP_TYPE_LINEAR,
154 pa_sink_input_set_volume_ramp (sinp, &rampvol, true);
157 const char *agl_utils_get_card_name (pa_card *card)
159 return (card && card->name) ? card->name : "<unknown>";
162 const char *agl_utils_get_card_bus (pa_card *card)
164 const char *bus = NULL;
167 if (card && !(bus = pa_proplist_gets (card->proplist,PA_PROP_DEVICE_BUS))) {
168 name = agl_utils_get_card_name (card);
169 if (!strncmp (name, "alsa_card.", 10)) {
170 if (!strncmp (name + 10, "pci-", 4))
172 else if (!strncmp (name + 10, "platform-", 9))
174 else if (!strncmp (name + 10, "usb-", 4))
182 const char *agl_utils_get_sink_name (pa_sink *sink)
184 return (sink && sink->name) ? sink->name : "<unknown>";
187 const char *agl_utils_get_source_name (pa_source *source)
189 return (source && source->name) ? source->name : "<unknown>";
192 const char *agl_utils_get_sink_input_name (pa_sink_input *sinp)
196 if (sinp && sinp->proplist) {
197 name = (char *)pa_proplist_gets (sinp->proplist, PA_PROP_APPLICATION_NAME);
199 name = (char *)pa_proplist_gets (sinp->proplist, PA_PROP_APPLICATION_PROCESS_BINARY);
204 return (const char *)name;
207 const char *agl_utils_get_source_output_name (pa_source_output *sout)
211 if (sout && sout->proplist) {
212 name = (char *)pa_proplist_gets (sout->proplist, PA_PROP_APPLICATION_NAME);
214 name = (char *)pa_proplist_gets (sout->proplist, PA_PROP_APPLICATION_PROCESS_BINARY);
219 return (const char *)name;
222 pa_sink *agl_utils_get_primary_alsa_sink (struct userdata *u)
229 pa_assert_se ((core = u->core));
231 PA_IDXSET_FOREACH(sink, core->sinks, idx) {
232 if (sink->name && strstr (sink->name, "alsa_output"))
239 pa_sink *agl_utils_get_alsa_sink (struct userdata *u, const char *name)
246 pa_assert_se ((core = u->core));
248 PA_IDXSET_FOREACH(sink, core->sinks, idx) {
249 if (sink->name && strstr (sink->name, "alsa_output")
250 && strstr (sink->name, name))
257 void agl_utils_init_stamp (void)
262 uint32_t agl_utils_new_stamp (void)
267 uint32_t agl_utils_get_stamp (void)
274 char *agl_utils_get_zone (pa_proplist *pl, pa_proplist *client_props)
280 /* grab the "zone.name" PA_PROP environment variable ;
281 * otherwise just fall back to default "driver" zone */
282 zone = pa_proplist_gets (pl, PA_PROP_ZONE_NAME);
284 if (!client_props || !(zone = pa_proplist_gets (client_props, PA_PROP_ENV_ZONE)))
285 zone = PA_ZONE_NAME_DEFAULT;
291 bool agl_utils_set_stream_routing_properties (pa_proplist *pl, int styp, void *target)
293 const char *clnam; /* will become "agl_player" e.g. */
294 char clid[32]; /* will become "1" e.g. */
295 const char *method; /* will become "default" (it target is NULL) or "explicit" */
298 pa_assert (styp >= 0); /* type different from "agl_node_type_unknown" */
300 clnam = agl_node_type_str (styp);
301 snprintf (clid, sizeof(clid), "%d", styp);
302 method = target ? "explicit" : "default";
304 if (pa_proplist_sets (pl, PA_PROP_ROUTING_CLASS_NAME, clnam ) < 0 ||
305 pa_proplist_sets (pl, PA_PROP_ROUTING_CLASS_ID , clid ) < 0 ||
306 pa_proplist_sets (pl, PA_PROP_ROUTING_METHOD , method) < 0)
308 pa_log ("failed to set some stream property");
315 bool agl_utils_unset_stream_routing_properties (pa_proplist *pl)
319 if (pa_proplist_unset (pl, PA_PROP_ROUTING_CLASS_NAME) < 0 ||
320 pa_proplist_unset (pl, PA_PROP_ROUTING_CLASS_ID ) < 0 ||
321 pa_proplist_unset (pl, PA_PROP_ROUTING_METHOD ) < 0)
323 pa_log ("failed to unset some stream property");