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
41PA_MODULE_AUTHOR("Stefan Huber");
42PA_MODULE_DESCRIPTION("Virtual channel remapping source");
43PA_MODULE_VERSION(PACKAGE_VERSION);
44PA_MODULE_LOAD_ONCE(false);
45PA_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
57struct userdata {
58    pa_module *module;
59
60    pa_source *source;
61    pa_source_output *source_output;
62
63    bool auto_desc;
64};
65
66static 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 */
81static 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 */
114static 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 */
129static 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 */
148static 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 */
167static 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 */
180static 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 */
191static 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 */
205static 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 */
222static 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. */
246static 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 */
256static 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
290int 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
431fail:
432    if (ma)
433        pa_modargs_free(ma);
434
435    pa__done(m);
436
437    return -1;
438}
439
440int 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
449void 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