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 /* Add resampler delay */
105 *((int64_t*) data) += pa_resampler_get_delay_usec(u->source_output->thread_info.resampler);
106
107 return 0;
108 }
109
110 return pa_source_process_msg(o, code, data, offset, chunk);
111 }
112
113 /* 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)114 static int source_set_state_in_main_thread_cb(pa_source *s, pa_source_state_t state, pa_suspend_cause_t suspend_cause) {
115 struct userdata *u;
116
117 pa_source_assert_ref(s);
118 pa_assert_se(u = s->userdata);
119
120 if (!PA_SOURCE_IS_LINKED(state) ||
121 !PA_SOURCE_OUTPUT_IS_LINKED(u->source_output->state))
122 return 0;
123
124 pa_source_output_cork(u->source_output, state == PA_SOURCE_SUSPENDED);
125 return 0;
126 }
127
128 /* Called from I/O thread context */
source_update_requested_latency_cb(pa_source * s)129 static void source_update_requested_latency_cb(pa_source *s) {
130 struct userdata *u;
131
132 pa_source_assert_ref(s);
133 pa_assert_se(u = s->userdata);
134
135 if (!PA_SOURCE_IS_LINKED(u->source->thread_info.state) ||
136 !PA_SOURCE_OUTPUT_IS_LINKED(u->source_output->thread_info.state))
137 return;
138
139 pa_log_debug("Source update requested latency.");
140
141 /* Just hand this one over to the master source */
142 pa_source_output_set_requested_latency_within_thread(
143 u->source_output,
144 pa_source_get_requested_latency_within_thread(s));
145 }
146
147 /* Called from output thread context */
source_output_push_cb(pa_source_output * o,const pa_memchunk * chunk)148 static void source_output_push_cb(pa_source_output *o, const pa_memchunk *chunk) {
149 struct userdata *u;
150
151 pa_source_output_assert_ref(o);
152 pa_source_output_assert_io_context(o);
153 pa_assert_se(u = o->userdata);
154
155 if (!PA_SOURCE_IS_LINKED(u->source->thread_info.state))
156 return;
157
158 if (!PA_SOURCE_OUTPUT_IS_LINKED(u->source_output->thread_info.state)) {
159 pa_log("push when no link?");
160 return;
161 }
162
163 pa_source_post(u->source, chunk);
164 }
165
166 /* Called from output thread context */
source_output_process_rewind_cb(pa_source_output * o,size_t nbytes)167 static void source_output_process_rewind_cb(pa_source_output *o, size_t nbytes) {
168 struct userdata *u;
169
170 pa_source_output_assert_ref(o);
171 pa_source_output_assert_io_context(o);
172 pa_assert_se(u = o->userdata);
173
174 /* If the source is not yet linked, there is nothing to rewind */
175 if (PA_SOURCE_IS_LINKED(u->source->thread_info.state))
176 pa_source_process_rewind(u->source, nbytes);
177 }
178
179 /* Called from output thread context */
source_output_update_max_rewind_cb(pa_source_output * o,size_t nbytes)180 static void source_output_update_max_rewind_cb(pa_source_output *o, size_t nbytes) {
181 struct userdata *u;
182
183 pa_source_output_assert_ref(o);
184 pa_source_output_assert_io_context(o);
185 pa_assert_se(u = o->userdata);
186
187 pa_source_set_max_rewind_within_thread(u->source, nbytes);
188 }
189
190 /* Called from output thread context */
source_output_detach_cb(pa_source_output * o)191 static void source_output_detach_cb(pa_source_output *o) {
192 struct userdata *u;
193
194 pa_source_output_assert_ref(o);
195 pa_source_output_assert_io_context(o);
196 pa_assert_se(u = o->userdata);
197
198 if (PA_SOURCE_IS_LINKED(u->source->thread_info.state))
199 pa_source_detach_within_thread(u->source);
200
201 pa_source_set_rtpoll(u->source, NULL);
202 }
203
204 /* Called from output thread context */
source_output_attach_cb(pa_source_output * o)205 static void source_output_attach_cb(pa_source_output *o) {
206 struct userdata *u;
207
208 pa_source_output_assert_ref(o);
209 pa_source_output_assert_io_context(o);
210 pa_assert_se(u = o->userdata);
211
212 pa_source_set_rtpoll(u->source, o->source->thread_info.rtpoll);
213 pa_source_set_latency_range_within_thread(u->source, o->source->thread_info.min_latency, o->source->thread_info.max_latency);
214 pa_source_set_fixed_latency_within_thread(u->source, o->source->thread_info.fixed_latency);
215 pa_source_set_max_rewind_within_thread(u->source, pa_source_output_get_max_rewind(o));
216
217 if (PA_SOURCE_IS_LINKED(u->source->thread_info.state))
218 pa_source_attach_within_thread(u->source);
219 }
220
221 /* Called from main thread */
source_output_kill_cb(pa_source_output * o)222 static void source_output_kill_cb(pa_source_output *o) {
223 struct userdata *u;
224
225 pa_source_output_assert_ref(o);
226 pa_assert_ctl_context();
227 pa_assert_se(u = o->userdata);
228
229 /* The order here matters! We first kill the source so that streams
230 * can properly be moved away while the source output is still connected
231 * to the master. */
232 pa_source_output_cork(u->source_output, true);
233 pa_source_unlink(u->source);
234 pa_source_output_unlink(u->source_output);
235
236 pa_source_output_unref(u->source_output);
237 u->source_output = NULL;
238
239 pa_source_unref(u->source);
240 u->source = NULL;
241
242 pa_module_unload_request(u->module, true);
243 }
244
245 /* 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)246 static void source_output_state_change_cb(pa_source_output *o, pa_source_output_state_t state) {
247 struct userdata *u;
248
249 pa_source_output_assert_ref(o);
250 pa_assert_se(u = o->userdata);
251
252 pa_log_debug("Source output %d state %d.", o->index, state);
253 }
254
255 /* Called from main thread */
source_output_moving_cb(pa_source_output * o,pa_source * dest)256 static void source_output_moving_cb(pa_source_output *o, pa_source *dest) {
257 struct userdata *u;
258 uint32_t idx;
259 pa_source_output *output;
260
261 pa_source_output_assert_ref(o);
262 pa_assert_ctl_context();
263 pa_assert_se(u = o->userdata);
264
265 if (dest) {
266 pa_source_set_asyncmsgq(u->source, dest->asyncmsgq);
267 pa_source_update_flags(u->source, PA_SOURCE_LATENCY|PA_SOURCE_DYNAMIC_LATENCY, dest->flags);
268 } else
269 pa_source_set_asyncmsgq(u->source, NULL);
270
271 /* Propagate asyncmsq change to attached virtual sources */
272 PA_IDXSET_FOREACH(output, u->source->outputs, idx) {
273 if (output->destination_source && output->moving)
274 output->moving(output, u->source);
275 }
276
277 if (u->auto_desc && dest) {
278 const char *k;
279 pa_proplist *pl;
280
281 pl = pa_proplist_new();
282 k = pa_proplist_gets(dest->proplist, PA_PROP_DEVICE_DESCRIPTION);
283 pa_proplist_setf(pl, PA_PROP_DEVICE_DESCRIPTION, "Remapped %s", k ? k : dest->name);
284
285 pa_source_update_proplist(u->source, PA_UPDATE_REPLACE, pl);
286 pa_proplist_free(pl);
287 }
288 }
289
pa__init(pa_module * m)290 int pa__init(pa_module*m) {
291 struct userdata *u;
292 pa_sample_spec ss;
293 pa_resample_method_t resample_method = PA_RESAMPLER_INVALID;
294 pa_channel_map source_map, stream_map;
295 pa_modargs *ma;
296 pa_source *master;
297 pa_source_output_new_data source_output_data;
298 pa_source_new_data source_data;
299 bool remix = true;
300
301 pa_assert(m);
302
303 if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
304 pa_log("Failed to parse module arguments.");
305 goto fail;
306 }
307
308 if (!(master = pa_namereg_get(m->core, pa_modargs_get_value(ma, "master", NULL), PA_NAMEREG_SOURCE))) {
309 pa_log("Master source not found.");
310 goto fail;
311 }
312
313 ss = master->sample_spec;
314 source_map = master->channel_map;
315 if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &source_map, PA_CHANNEL_MAP_DEFAULT) < 0) {
316 pa_log("Invalid sample format specification or channel map.");
317 goto fail;
318 }
319
320 stream_map = source_map;
321 if (pa_modargs_get_channel_map(ma, "master_channel_map", &stream_map) < 0) {
322 pa_log("Invalid master channel map.");
323 goto fail;
324 }
325
326 if (stream_map.channels != ss.channels) {
327 pa_log("Number of channels doesn't match.");
328 goto fail;
329 }
330
331 if (pa_channel_map_equal(&stream_map, &master->channel_map))
332 pa_log_warn("No remapping configured, proceeding nonetheless!");
333
334 if (pa_modargs_get_value_boolean(ma, "remix", &remix) < 0) {
335 pa_log("Invalid boolean remix parameter.");
336 goto fail;
337 }
338
339 if (pa_modargs_get_resample_method(ma, &resample_method) < 0) {
340 pa_log("Invalid resampling method");
341 goto fail;
342 }
343
344 u = pa_xnew0(struct userdata, 1);
345 u->module = m;
346 m->userdata = u;
347
348 /* Create source */
349 pa_source_new_data_init(&source_data);
350 source_data.driver = __FILE__;
351 source_data.module = m;
352 if (!(source_data.name = pa_xstrdup(pa_modargs_get_value(ma, "source_name", NULL))))
353 source_data.name = pa_sprintf_malloc("%s.remapped", master->name);
354 pa_source_new_data_set_sample_spec(&source_data, &ss);
355 pa_source_new_data_set_channel_map(&source_data, &source_map);
356 pa_proplist_sets(source_data.proplist, PA_PROP_DEVICE_MASTER_DEVICE, master->name);
357 pa_proplist_sets(source_data.proplist, PA_PROP_DEVICE_CLASS, "filter");
358
359 if (pa_modargs_get_proplist(ma, "source_properties", source_data.proplist, PA_UPDATE_REPLACE) < 0) {
360 pa_log("Invalid properties.");
361 pa_source_new_data_done(&source_data);
362 goto fail;
363 }
364
365 if ((u->auto_desc = !pa_proplist_contains(source_data.proplist, PA_PROP_DEVICE_DESCRIPTION))) {
366 const char *k;
367
368 k = pa_proplist_gets(master->proplist, PA_PROP_DEVICE_DESCRIPTION);
369 pa_proplist_setf(source_data.proplist, PA_PROP_DEVICE_DESCRIPTION, "Remapped %s", k ? k : master->name);
370 }
371
372 u->source = pa_source_new(m->core, &source_data, master->flags & (PA_SOURCE_LATENCY|PA_SOURCE_DYNAMIC_LATENCY));
373 pa_source_new_data_done(&source_data);
374
375 if (!u->source) {
376 pa_log("Failed to create source.");
377 goto fail;
378 }
379
380 u->source->parent.process_msg = source_process_msg_cb;
381 u->source->set_state_in_main_thread = source_set_state_in_main_thread_cb;
382 u->source->update_requested_latency = source_update_requested_latency_cb;
383
384 u->source->userdata = u;
385
386 pa_source_set_asyncmsgq(u->source, master->asyncmsgq);
387
388 /* Create source output */
389 pa_source_output_new_data_init(&source_output_data);
390 source_output_data.driver = __FILE__;
391 source_output_data.module = m;
392 pa_source_output_new_data_set_source(&source_output_data, master, false, true);
393 source_output_data.destination_source = u->source;
394
395 pa_proplist_sets(source_output_data.proplist, PA_PROP_MEDIA_NAME, "Remapped Stream");
396 pa_proplist_sets(source_output_data.proplist, PA_PROP_MEDIA_ROLE, "filter");
397 pa_source_output_new_data_set_sample_spec(&source_output_data, &ss);
398 pa_source_output_new_data_set_channel_map(&source_output_data, &stream_map);
399 source_output_data.flags = (remix ? 0 : PA_SOURCE_OUTPUT_NO_REMIX) | PA_SOURCE_OUTPUT_START_CORKED;
400 source_output_data.resample_method = resample_method;
401
402 pa_source_output_new(&u->source_output, m->core, &source_output_data);
403 pa_source_output_new_data_done(&source_output_data);
404
405 if (!u->source_output)
406 goto fail;
407
408 u->source_output->push = source_output_push_cb;
409 u->source_output->process_rewind = source_output_process_rewind_cb;
410 u->source_output->update_max_rewind = source_output_update_max_rewind_cb;
411 u->source_output->kill = source_output_kill_cb;
412 u->source_output->attach = source_output_attach_cb;
413 u->source_output->detach = source_output_detach_cb;
414 u->source_output->state_change = source_output_state_change_cb;
415 u->source_output->moving = source_output_moving_cb;
416 u->source_output->userdata = u;
417
418 u->source->output_from_master = u->source_output;
419
420 /* The order here is important. The output must be put first,
421 * otherwise streams might attach to the source before the
422 * source output is attached to the master. */
423 pa_source_output_put(u->source_output);
424 pa_source_put(u->source);
425 pa_source_output_cork(u->source_output, false);
426
427 pa_modargs_free(ma);
428
429 return 0;
430
431 fail:
432 if (ma)
433 pa_modargs_free(ma);
434
435 pa__done(m);
436
437 return -1;
438 }
439
pa__get_n_used(pa_module * m)440 int pa__get_n_used(pa_module *m) {
441 struct userdata *u;
442
443 pa_assert(m);
444 pa_assert_se(u = m->userdata);
445
446 return pa_source_linked_by(u->source);
447 }
448
pa__done(pa_module * m)449 void pa__done(pa_module*m) {
450 struct userdata *u;
451
452 pa_assert(m);
453
454 if (!(u = m->userdata))
455 return;
456
457 /* See comments in source_output_kill_cb() above regarding
458 * destruction order! */
459
460 if (u->source_output)
461 pa_source_output_cork(u->source_output, true);
462
463 if (u->source)
464 pa_source_unlink(u->source);
465
466 if (u->source_output) {
467 pa_source_output_unlink(u->source_output);
468 pa_source_output_unref(u->source_output);
469 }
470
471 if (u->source)
472 pa_source_unref(u->source);
473
474 pa_xfree(u);
475 }
476