1 /***
2 This file is part of PulseAudio.
3
4 Copyright 2013 bct electronic GmbH
5 Contributor: Stefan Huber <s.huber@bct-electronic.com>
6
7 PulseAudio is free software; you can redistribute it and/or modify
8 it under the terms of the GNU Lesser General Public License as published
9 by the Free Software Foundation; either version 2.1 of the License,
10 or (at your option) any later version.
11
12 PulseAudio is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public License
18 along with PulseAudio; if not, see <http://www.gnu.org/licenses/>.
19 ***/
20
21 #ifdef HAVE_CONFIG_H
22 #include <config.h>
23 #endif
24
25 #include <stdio.h>
26
27 #include <pulse/xmalloc.h>
28
29 #include <pulsecore/i18n.h>
30 #include <pulsecore/macro.h>
31 #include <pulsecore/namereg.h>
32 #include <pulsecore/module.h>
33 #include <pulsecore/core-util.h>
34 #include <pulsecore/modargs.h>
35 #include <pulsecore/log.h>
36 #include <pulsecore/rtpoll.h>
37 #include <pulsecore/sample-util.h>
38 #include <pulsecore/ltdl-helper.h>
39 #include <pulsecore/mix.h>
40
41 PA_MODULE_AUTHOR("Stefan Huber");
42 PA_MODULE_DESCRIPTION("Virtual channel remapping source");
43 PA_MODULE_VERSION(PACKAGE_VERSION);
44 PA_MODULE_LOAD_ONCE(false);
45 PA_MODULE_USAGE(
46 "source_name=<name for the source> "
47 "source_properties=<properties for the source> "
48 "master=<name of source to filter> "
49 "master_channel_map=<channel map> "
50 "format=<sample format> "
51 "rate=<sample rate> "
52 "channels=<number of channels> "
53 "channel_map=<channel map> "
54 "resample_method=<resampler> "
55 "remix=<remix channels?>");
56
57 struct userdata {
58 pa_module *module;
59
60 pa_source *source;
61 pa_source_output *source_output;
62
63 bool auto_desc;
64 };
65
66 static const char* const valid_modargs[] = {
67 "source_name",
68 "source_properties",
69 "master",
70 "master_channel_map",
71 "format",
72 "rate",
73 "channels",
74 "channel_map",
75 "resample_method",
76 "remix",
77 NULL
78 };
79
80 /* Called from I/O thread context */
source_process_msg_cb(pa_msgobject * o,int code,void * data,int64_t offset,pa_memchunk * chunk)81 static int source_process_msg_cb(pa_msgobject *o, int code, void *data, int64_t offset, pa_memchunk *chunk) {
82 struct userdata *u = PA_SOURCE(o)->userdata;
83
84 switch (code) {
85
86 case PA_SOURCE_MESSAGE_GET_LATENCY:
87
88 /* The source is _put() before the source output is, so let's
89 * make sure we don't access it in that time. Also, the
90 * source output is first shut down, the source second. */
91 if (!PA_SOURCE_IS_LINKED(u->source->thread_info.state) ||
92 !PA_SOURCE_OUTPUT_IS_LINKED(u->source_output->thread_info.state)) {
93 *((int64_t*) data) = 0;
94 return 0;
95 }
96
97 *((int64_t*) data) =
98
99 /* Get the latency of the master source */
100 pa_source_get_latency_within_thread(u->source_output->source, true) +
101 /* Add the latency internal to our source output on top */
102 pa_bytes_to_usec(pa_memblockq_get_length(u->source_output->thread_info.delay_memblockq), &u->source_output->source->sample_spec);
103
104 return 0;
105 }
106
107 return pa_source_process_msg(o, code, data, offset, chunk);
108 }
109
110 /* Called from main context */
source_set_state_in_main_thread_cb(pa_source * s,pa_source_state_t state,pa_suspend_cause_t suspend_cause)111 static int source_set_state_in_main_thread_cb(pa_source *s, pa_source_state_t state, pa_suspend_cause_t suspend_cause) {
112 struct userdata *u;
113
114 pa_source_assert_ref(s);
115 pa_assert_se(u = s->userdata);
116
117 if (!PA_SOURCE_IS_LINKED(state) ||
118 !PA_SOURCE_OUTPUT_IS_LINKED(u->source_output->state))
119 return 0;
120
121 pa_source_output_cork(u->source_output, state == PA_SOURCE_SUSPENDED);
122 return 0;
123 }
124
125 /* Called from I/O thread context */
source_update_requested_latency_cb(pa_source * s)126 static void source_update_requested_latency_cb(pa_source *s) {
127 struct userdata *u;
128
129 pa_source_assert_ref(s);
130 pa_assert_se(u = s->userdata);
131
132 if (!PA_SOURCE_IS_LINKED(u->source->thread_info.state) ||
133 !PA_SOURCE_OUTPUT_IS_LINKED(u->source_output->thread_info.state))
134 return;
135
136 pa_log_debug("Source update requested latency.");
137
138 /* Just hand this one over to the master source */
139 pa_source_output_set_requested_latency_within_thread(
140 u->source_output,
141 pa_source_get_requested_latency_within_thread(s));
142 }
143
144 /* Called from output thread context */
source_output_push_cb(pa_source_output * o,const pa_memchunk * chunk)145 static void source_output_push_cb(pa_source_output *o, const pa_memchunk *chunk) {
146 struct userdata *u;
147
148 pa_source_output_assert_ref(o);
149 pa_source_output_assert_io_context(o);
150 pa_assert_se(u = o->userdata);
151
152 if (!PA_SOURCE_IS_LINKED(u->source->thread_info.state))
153 return;
154
155 if (!PA_SOURCE_OUTPUT_IS_LINKED(u->source_output->thread_info.state)) {
156 pa_log("push when no link?");
157 return;
158 }
159
160 pa_source_post(u->source, chunk);
161 }
162
163 /* Called from output thread context */
source_output_process_rewind_cb(pa_source_output * o,size_t nbytes)164 static void source_output_process_rewind_cb(pa_source_output *o, size_t nbytes) {
165 struct userdata *u;
166
167 pa_source_output_assert_ref(o);
168 pa_source_output_assert_io_context(o);
169 pa_assert_se(u = o->userdata);
170
171 /* If the source is not yet linked, there is nothing to rewind */
172 if (PA_SOURCE_IS_LINKED(u->source->thread_info.state))
173 pa_source_process_rewind(u->source, nbytes);
174 }
175
176 /* Called from output thread context */
source_output_update_max_rewind_cb(pa_source_output * o,size_t nbytes)177 static void source_output_update_max_rewind_cb(pa_source_output *o, size_t nbytes) {
178 struct userdata *u;
179
180 pa_source_output_assert_ref(o);
181 pa_source_output_assert_io_context(o);
182 pa_assert_se(u = o->userdata);
183
184 pa_source_set_max_rewind_within_thread(u->source, nbytes);
185 }
186
187 /* Called from output thread context */
source_output_detach_cb(pa_source_output * o)188 static void source_output_detach_cb(pa_source_output *o) {
189 struct userdata *u;
190
191 pa_source_output_assert_ref(o);
192 pa_source_output_assert_io_context(o);
193 pa_assert_se(u = o->userdata);
194
195 if (PA_SOURCE_IS_LINKED(u->source->thread_info.state))
196 pa_source_detach_within_thread(u->source);
197
198 pa_source_set_rtpoll(u->source, NULL);
199 }
200
201 /* Called from output thread context */
source_output_attach_cb(pa_source_output * o)202 static void source_output_attach_cb(pa_source_output *o) {
203 struct userdata *u;
204
205 pa_source_output_assert_ref(o);
206 pa_source_output_assert_io_context(o);
207 pa_assert_se(u = o->userdata);
208
209 pa_source_set_rtpoll(u->source, o->source->thread_info.rtpoll);
210 pa_source_set_latency_range_within_thread(u->source, o->source->thread_info.min_latency, o->source->thread_info.max_latency);
211 pa_source_set_fixed_latency_within_thread(u->source, o->source->thread_info.fixed_latency);
212 pa_source_set_max_rewind_within_thread(u->source, pa_source_output_get_max_rewind(o));
213
214 if (PA_SOURCE_IS_LINKED(u->source->thread_info.state))
215 pa_source_attach_within_thread(u->source);
216 }
217
218 /* Called from main thread */
source_output_kill_cb(pa_source_output * o)219 static void source_output_kill_cb(pa_source_output *o) {
220 struct userdata *u;
221
222 pa_source_output_assert_ref(o);
223 pa_assert_ctl_context();
224 pa_assert_se(u = o->userdata);
225
226 /* The order here matters! We first kill the source so that streams
227 * can properly be moved away while the source output is still connected
228 * to the master. */
229 pa_source_output_cork(u->source_output, true);
230 pa_source_unlink(u->source);
231 pa_source_output_unlink(u->source_output);
232
233 pa_source_output_unref(u->source_output);
234 u->source_output = NULL;
235
236 pa_source_unref(u->source);
237 u->source = NULL;
238
239 pa_module_unload_request(u->module, true);
240 }
241
242 /* Called from output thread context except when cork() is called without valid source. */
source_output_state_change_cb(pa_source_output * o,pa_source_output_state_t state)243 static void source_output_state_change_cb(pa_source_output *o, pa_source_output_state_t state) {
244 struct userdata *u;
245
246 pa_source_output_assert_ref(o);
247 pa_assert_se(u = o->userdata);
248
249 pa_log_debug("Source output %d state %d.", o->index, state);
250 }
251
252 /* Called from main thread */
source_output_moving_cb(pa_source_output * o,pa_source * dest)253 static void source_output_moving_cb(pa_source_output *o, pa_source *dest) {
254 struct userdata *u;
255 uint32_t idx;
256 pa_source_output *output;
257
258 pa_source_output_assert_ref(o);
259 pa_assert_ctl_context();
260 pa_assert_se(u = o->userdata);
261
262 if (dest) {
263 pa_source_set_asyncmsgq(u->source, dest->asyncmsgq);
264 pa_source_update_flags(u->source, PA_SOURCE_LATENCY|PA_SOURCE_DYNAMIC_LATENCY, dest->flags);
265 } else
266 pa_source_set_asyncmsgq(u->source, NULL);
267
268 /* Propagate asyncmsq change to attached virtual sources */
269 PA_IDXSET_FOREACH(output, u->source->outputs, idx) {
270 if (output->destination_source && output->moving)
271 output->moving(output, u->source);
272 }
273
274 if (u->auto_desc && dest) {
275 const char *k;
276 pa_proplist *pl;
277
278 pl = pa_proplist_new();
279 k = pa_proplist_gets(dest->proplist, PA_PROP_DEVICE_DESCRIPTION);
280 pa_proplist_setf(pl, PA_PROP_DEVICE_DESCRIPTION, "Remapped %s", k ? k : dest->name);
281
282 pa_source_update_proplist(u->source, PA_UPDATE_REPLACE, pl);
283 pa_proplist_free(pl);
284 }
285 }
286
pa__init(pa_module * m)287 int pa__init(pa_module*m) {
288 struct userdata *u;
289 pa_sample_spec ss;
290 pa_resample_method_t resample_method = PA_RESAMPLER_INVALID;
291 pa_channel_map source_map, stream_map;
292 pa_modargs *ma;
293 pa_source *master;
294 pa_source_output_new_data source_output_data;
295 pa_source_new_data source_data;
296 bool remix = true;
297
298 pa_assert(m);
299
300 if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
301 pa_log("Failed to parse module arguments.");
302 goto fail;
303 }
304
305 if (!(master = pa_namereg_get(m->core, pa_modargs_get_value(ma, "master", NULL), PA_NAMEREG_SOURCE))) {
306 pa_log("Master source not found.");
307 goto fail;
308 }
309
310 ss = master->sample_spec;
311 source_map = master->channel_map;
312 if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &source_map, PA_CHANNEL_MAP_DEFAULT) < 0) {
313 pa_log("Invalid sample format specification or channel map.");
314 goto fail;
315 }
316
317 stream_map = source_map;
318 if (pa_modargs_get_channel_map(ma, "master_channel_map", &stream_map) < 0) {
319 pa_log("Invalid master channel map.");
320 goto fail;
321 }
322
323 if (stream_map.channels != ss.channels) {
324 pa_log("Number of channels doesn't match.");
325 goto fail;
326 }
327
328 if (pa_channel_map_equal(&stream_map, &master->channel_map))
329 pa_log_warn("No remapping configured, proceeding nonetheless!");
330
331 if (pa_modargs_get_value_boolean(ma, "remix", &remix) < 0) {
332 pa_log("Invalid boolean remix parameter.");
333 goto fail;
334 }
335
336 if (pa_modargs_get_resample_method(ma, &resample_method) < 0) {
337 pa_log("Invalid resampling method");
338 goto fail;
339 }
340
341 u = pa_xnew0(struct userdata, 1);
342 u->module = m;
343 m->userdata = u;
344
345 /* Create source */
346 pa_source_new_data_init(&source_data);
347 source_data.driver = __FILE__;
348 source_data.module = m;
349 if (!(source_data.name = pa_xstrdup(pa_modargs_get_value(ma, "source_name", NULL))))
350 source_data.name = pa_sprintf_malloc("%s.remapped", master->name);
351 pa_source_new_data_set_sample_spec(&source_data, &ss);
352 pa_source_new_data_set_channel_map(&source_data, &source_map);
353 pa_proplist_sets(source_data.proplist, PA_PROP_DEVICE_MASTER_DEVICE, master->name);
354 pa_proplist_sets(source_data.proplist, PA_PROP_DEVICE_CLASS, "filter");
355
356 if (pa_modargs_get_proplist(ma, "source_properties", source_data.proplist, PA_UPDATE_REPLACE) < 0) {
357 pa_log("Invalid properties.");
358 pa_source_new_data_done(&source_data);
359 goto fail;
360 }
361
362 if ((u->auto_desc = !pa_proplist_contains(source_data.proplist, PA_PROP_DEVICE_DESCRIPTION))) {
363 const char *k;
364
365 k = pa_proplist_gets(master->proplist, PA_PROP_DEVICE_DESCRIPTION);
366 pa_proplist_setf(source_data.proplist, PA_PROP_DEVICE_DESCRIPTION, "Remapped %s", k ? k : master->name);
367 }
368
369 u->source = pa_source_new(m->core, &source_data, master->flags & (PA_SOURCE_LATENCY|PA_SOURCE_DYNAMIC_LATENCY));
370 pa_source_new_data_done(&source_data);
371
372 if (!u->source) {
373 pa_log("Failed to create source.");
374 goto fail;
375 }
376
377 u->source->parent.process_msg = source_process_msg_cb;
378 u->source->set_state_in_main_thread = source_set_state_in_main_thread_cb;
379 u->source->update_requested_latency = source_update_requested_latency_cb;
380
381 u->source->userdata = u;
382
383 pa_source_set_asyncmsgq(u->source, master->asyncmsgq);
384
385 /* Create source output */
386 pa_source_output_new_data_init(&source_output_data);
387 source_output_data.driver = __FILE__;
388 source_output_data.module = m;
389 pa_source_output_new_data_set_source(&source_output_data, master, false, true);
390 source_output_data.destination_source = u->source;
391
392 pa_proplist_sets(source_output_data.proplist, PA_PROP_MEDIA_NAME, "Remapped Stream");
393 pa_proplist_sets(source_output_data.proplist, PA_PROP_MEDIA_ROLE, "filter");
394 pa_source_output_new_data_set_sample_spec(&source_output_data, &ss);
395 pa_source_output_new_data_set_channel_map(&source_output_data, &stream_map);
396 source_output_data.flags = (remix ? 0 : PA_SOURCE_OUTPUT_NO_REMIX) | PA_SOURCE_OUTPUT_START_CORKED;
397 source_output_data.resample_method = resample_method;
398
399 pa_source_output_new(&u->source_output, m->core, &source_output_data);
400 pa_source_output_new_data_done(&source_output_data);
401
402 if (!u->source_output)
403 goto fail;
404
405 u->source_output->push = source_output_push_cb;
406 u->source_output->process_rewind = source_output_process_rewind_cb;
407 u->source_output->update_max_rewind = source_output_update_max_rewind_cb;
408 u->source_output->kill = source_output_kill_cb;
409 u->source_output->attach = source_output_attach_cb;
410 u->source_output->detach = source_output_detach_cb;
411 u->source_output->state_change = source_output_state_change_cb;
412 u->source_output->moving = source_output_moving_cb;
413 u->source_output->userdata = u;
414
415 u->source->output_from_master = u->source_output;
416
417 /* The order here is important. The output must be put first,
418 * otherwise streams might attach to the source before the
419 * source output is attached to the master. */
420 pa_source_output_put(u->source_output);
421 pa_source_put(u->source);
422 pa_source_output_cork(u->source_output, false);
423
424 pa_modargs_free(ma);
425
426 return 0;
427
428 fail:
429 if (ma)
430 pa_modargs_free(ma);
431
432 pa__done(m);
433
434 return -1;
435 }
436
pa__get_n_used(pa_module * m)437 int pa__get_n_used(pa_module *m) {
438 struct userdata *u;
439
440 pa_assert(m);
441 pa_assert_se(u = m->userdata);
442
443 return pa_source_linked_by(u->source);
444 }
445
pa__done(pa_module * m)446 void pa__done(pa_module*m) {
447 struct userdata *u;
448
449 pa_assert(m);
450
451 if (!(u = m->userdata))
452 return;
453
454 /* See comments in source_output_kill_cb() above regarding
455 * destruction order! */
456
457 if (u->source_output)
458 pa_source_output_cork(u->source_output, true);
459
460 if (u->source)
461 pa_source_unlink(u->source);
462
463 if (u->source_output) {
464 pa_source_output_unlink(u->source_output);
465 pa_source_output_unref(u->source_output);
466 }
467
468 if (u->source)
469 pa_source_unref(u->source);
470
471 pa_xfree(u);
472 }
473