loopback: Enable routing on loopback streams
[pulseaudio-raopUDP/pulseaudio-raop-alac.git] / src / modules / module-loopback.c
blob9054700c5d638cfdd6033e401161c00c3c6da687
1 /***
2 This file is part of PulseAudio.
4 Copyright 2009 Intel Corporation
5 Contributor: Pierre-Louis Bossart <pierre-louis.bossart@intel.com>
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.
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.
17 You should have received a copy of the GNU Lesser General Public License
18 along with PulseAudio; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
20 USA.
21 ***/
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
27 #include <stdio.h>
29 #include <pulse/xmalloc.h>
31 #include <pulsecore/sink-input.h>
32 #include <pulsecore/module.h>
33 #include <pulsecore/modargs.h>
34 #include <pulsecore/namereg.h>
35 #include <pulsecore/log.h>
36 #include <pulsecore/core-util.h>
38 #include <pulse/rtclock.h>
39 #include <pulse/timeval.h>
41 #include "module-loopback-symdef.h"
43 PA_MODULE_AUTHOR("Pierre-Louis Bossart");
44 PA_MODULE_DESCRIPTION("Loopback from source to sink");
45 PA_MODULE_VERSION(PACKAGE_VERSION);
46 PA_MODULE_LOAD_ONCE(FALSE);
47 PA_MODULE_USAGE(
48 "source=<source to connect to> "
49 "sink=<sink to connect to> "
50 "adjust_time=<how often to readjust rates in s> "
51 "latency_msec=<latency in ms> "
52 "format=<sample format> "
53 "rate=<sample rate> "
54 "channels=<number of channels> "
55 "channel_map=<channel map> "
56 "sink_input_properties=<proplist> "
57 "source_output_properties=<proplist> "
58 "source_dont_move=<boolean> "
59 "sink_dont_move=<boolean> "
60 "remix=<remix channels?> ");
62 #define DEFAULT_LATENCY_MSEC 200
64 #define MEMBLOCKQ_MAXLENGTH (1024*1024*16)
66 #define DEFAULT_ADJUST_TIME_USEC (10*PA_USEC_PER_SEC)
68 struct userdata {
69 pa_core *core;
70 pa_module *module;
72 pa_sink_input *sink_input;
73 pa_source_output *source_output;
75 pa_asyncmsgq *asyncmsgq;
76 pa_memblockq *memblockq;
78 pa_rtpoll_item *rtpoll_item_read, *rtpoll_item_write;
80 pa_time_event *time_event;
81 pa_usec_t adjust_time;
83 int64_t recv_counter;
84 int64_t send_counter;
86 size_t skip;
87 pa_usec_t latency;
89 pa_bool_t in_pop;
90 size_t min_memblockq_length;
92 struct {
93 int64_t send_counter;
94 size_t source_output_buffer;
95 pa_usec_t source_latency;
97 int64_t recv_counter;
98 size_t sink_input_buffer;
99 pa_usec_t sink_latency;
101 size_t min_memblockq_length;
102 size_t max_request;
103 } latency_snapshot;
106 static const char* const valid_modargs[] = {
107 "source",
108 "sink",
109 "adjust_time",
110 "latency_msec",
111 "format",
112 "rate",
113 "channels",
114 "channel_map",
115 "sink_input_properties",
116 "source_output_properties",
117 "source_dont_move",
118 "sink_dont_move",
119 "remix",
120 NULL,
123 enum {
124 SINK_INPUT_MESSAGE_POST = PA_SINK_INPUT_MESSAGE_MAX,
125 SINK_INPUT_MESSAGE_REWIND,
126 SINK_INPUT_MESSAGE_LATENCY_SNAPSHOT,
127 SINK_INPUT_MESSAGE_MAX_REQUEST_CHANGED
130 enum {
131 SOURCE_OUTPUT_MESSAGE_LATENCY_SNAPSHOT
134 /* Called from main context */
135 static void teardown(struct userdata *u) {
136 pa_assert(u);
137 pa_assert_ctl_context();
139 if (u->asyncmsgq)
140 pa_asyncmsgq_flush(u->asyncmsgq, 0);
142 u->adjust_time = 0;
143 if (u->time_event) {
144 u->core->mainloop->time_free(u->time_event);
145 u->time_event = NULL;
148 if (u->sink_input)
149 pa_sink_input_unlink(u->sink_input);
151 if (u->source_output)
152 pa_source_output_unlink(u->source_output);
154 if (u->sink_input) {
155 u->sink_input->parent.process_msg = pa_sink_input_process_msg;
156 pa_sink_input_unref(u->sink_input);
157 u->sink_input = NULL;
160 if (u->source_output) {
161 u->source_output->parent.process_msg = pa_source_output_process_msg;
162 pa_source_output_unref(u->source_output);
163 u->source_output = NULL;
167 /* Called from main context */
168 static void adjust_rates(struct userdata *u) {
169 size_t buffer, fs;
170 uint32_t old_rate, base_rate, new_rate;
171 pa_usec_t buffer_latency;
173 pa_assert(u);
174 pa_assert_ctl_context();
176 pa_asyncmsgq_send(u->source_output->source->asyncmsgq, PA_MSGOBJECT(u->source_output), SOURCE_OUTPUT_MESSAGE_LATENCY_SNAPSHOT, NULL, 0, NULL);
177 pa_asyncmsgq_send(u->sink_input->sink->asyncmsgq, PA_MSGOBJECT(u->sink_input), SINK_INPUT_MESSAGE_LATENCY_SNAPSHOT, NULL, 0, NULL);
179 buffer =
180 u->latency_snapshot.sink_input_buffer +
181 u->latency_snapshot.source_output_buffer;
183 if (u->latency_snapshot.recv_counter <= u->latency_snapshot.send_counter)
184 buffer += (size_t) (u->latency_snapshot.send_counter - u->latency_snapshot.recv_counter);
185 else
186 buffer += PA_CLIP_SUB(buffer, (size_t) (u->latency_snapshot.recv_counter - u->latency_snapshot.send_counter));
188 buffer_latency = pa_bytes_to_usec(buffer, &u->sink_input->sample_spec);
190 pa_log_debug("Loopback overall latency is %0.2f ms + %0.2f ms + %0.2f ms = %0.2f ms",
191 (double) u->latency_snapshot.sink_latency / PA_USEC_PER_MSEC,
192 (double) buffer_latency / PA_USEC_PER_MSEC,
193 (double) u->latency_snapshot.source_latency / PA_USEC_PER_MSEC,
194 ((double) u->latency_snapshot.sink_latency + buffer_latency + u->latency_snapshot.source_latency) / PA_USEC_PER_MSEC);
196 pa_log_debug("Should buffer %zu bytes, buffered at minimum %zu bytes",
197 u->latency_snapshot.max_request*2,
198 u->latency_snapshot.min_memblockq_length);
200 fs = pa_frame_size(&u->sink_input->sample_spec);
201 old_rate = u->sink_input->sample_spec.rate;
202 base_rate = u->source_output->sample_spec.rate;
204 if (u->latency_snapshot.min_memblockq_length < u->latency_snapshot.max_request*2)
205 new_rate = base_rate - (((u->latency_snapshot.max_request*2 - u->latency_snapshot.min_memblockq_length) / fs) *PA_USEC_PER_SEC)/u->adjust_time;
206 else
207 new_rate = base_rate + (((u->latency_snapshot.min_memblockq_length - u->latency_snapshot.max_request*2) / fs) *PA_USEC_PER_SEC)/u->adjust_time;
209 if (new_rate < (uint32_t) (base_rate*0.8) || new_rate > (uint32_t) (base_rate*1.25)) {
210 pa_log_warn("Sample rates too different, not adjusting (%u vs. %u).", base_rate, new_rate);
211 new_rate = base_rate;
212 } else {
213 if (base_rate < new_rate + 20 && new_rate < base_rate + 20)
214 new_rate = base_rate;
215 /* Do the adjustment in small steps; 2‰ can be considered inaudible */
216 if (new_rate < (uint32_t) (old_rate*0.998) || new_rate > (uint32_t) (old_rate*1.002)) {
217 pa_log_info("New rate of %u Hz not within 2‰ of %u Hz, forcing smaller adjustment", new_rate, old_rate);
218 new_rate = PA_CLAMP(new_rate, (uint32_t) (old_rate*0.998), (uint32_t) (old_rate*1.002));
222 pa_sink_input_set_rate(u->sink_input, new_rate);
223 pa_log_debug("[%s] Updated sampling rate to %lu Hz.", u->sink_input->sink->name, (unsigned long) new_rate);
225 pa_core_rttime_restart(u->core, u->time_event, pa_rtclock_now() + u->adjust_time);
228 /* Called from main context */
229 static void time_callback(pa_mainloop_api *a, pa_time_event *e, const struct timeval *t, void *userdata) {
230 struct userdata *u = userdata;
232 pa_assert(u);
233 pa_assert(a);
234 pa_assert(u->time_event == e);
236 adjust_rates(u);
239 /* Called from input thread context */
240 static void source_output_push_cb(pa_source_output *o, const pa_memchunk *chunk) {
241 struct userdata *u;
242 pa_memchunk copy;
244 pa_source_output_assert_ref(o);
245 pa_source_output_assert_io_context(o);
246 pa_assert_se(u = o->userdata);
248 if (u->skip > chunk->length) {
249 u->skip -= chunk->length;
250 return;
253 if (u->skip > 0) {
254 copy = *chunk;
255 copy.index += u->skip;
256 copy.length -= u->skip;
257 u->skip = 0;
259 chunk = &copy;
262 pa_asyncmsgq_post(u->asyncmsgq, PA_MSGOBJECT(u->sink_input), SINK_INPUT_MESSAGE_POST, NULL, 0, chunk, NULL);
263 u->send_counter += (int64_t) chunk->length;
266 /* Called from input thread context */
267 static void source_output_process_rewind_cb(pa_source_output *o, size_t nbytes) {
268 struct userdata *u;
270 pa_source_output_assert_ref(o);
271 pa_source_output_assert_io_context(o);
272 pa_assert_se(u = o->userdata);
274 pa_asyncmsgq_post(u->asyncmsgq, PA_MSGOBJECT(u->sink_input), SINK_INPUT_MESSAGE_REWIND, NULL, (int64_t) nbytes, NULL, NULL);
275 u->send_counter -= (int64_t) nbytes;
278 /* Called from output thread context */
279 static int source_output_process_msg_cb(pa_msgobject *obj, int code, void *data, int64_t offset, pa_memchunk *chunk) {
280 struct userdata *u = PA_SOURCE_OUTPUT(obj)->userdata;
282 switch (code) {
284 case SOURCE_OUTPUT_MESSAGE_LATENCY_SNAPSHOT: {
285 size_t length;
287 length = pa_memblockq_get_length(u->source_output->thread_info.delay_memblockq);
289 u->latency_snapshot.send_counter = u->send_counter;
290 u->latency_snapshot.source_output_buffer = u->source_output->thread_info.resampler ? pa_resampler_result(u->source_output->thread_info.resampler, length) : length;
291 u->latency_snapshot.source_latency = pa_source_get_latency_within_thread(u->source_output->source);
293 return 0;
297 return pa_source_output_process_msg(obj, code, data, offset, chunk);
300 /* Called from output thread context */
301 static void source_output_attach_cb(pa_source_output *o) {
302 struct userdata *u;
304 pa_source_output_assert_ref(o);
305 pa_source_output_assert_io_context(o);
306 pa_assert_se(u = o->userdata);
308 u->rtpoll_item_write = pa_rtpoll_item_new_asyncmsgq_write(
309 o->source->thread_info.rtpoll,
310 PA_RTPOLL_LATE,
311 u->asyncmsgq);
314 /* Called from output thread context */
315 static void source_output_detach_cb(pa_source_output *o) {
316 struct userdata *u;
318 pa_source_output_assert_ref(o);
319 pa_source_output_assert_io_context(o);
320 pa_assert_se(u = o->userdata);
322 if (u->rtpoll_item_write) {
323 pa_rtpoll_item_free(u->rtpoll_item_write);
324 u->rtpoll_item_write = NULL;
328 /* Called from output thread context */
329 static void source_output_state_change_cb(pa_source_output *o, pa_source_output_state_t state) {
330 struct userdata *u;
332 pa_source_output_assert_ref(o);
333 pa_source_output_assert_io_context(o);
334 pa_assert_se(u = o->userdata);
336 if (PA_SOURCE_OUTPUT_IS_LINKED(state) && o->thread_info.state == PA_SOURCE_OUTPUT_INIT) {
338 u->skip = pa_usec_to_bytes(PA_CLIP_SUB(pa_source_get_latency_within_thread(o->source),
339 u->latency),
340 &o->sample_spec);
342 pa_log_info("Skipping %lu bytes", (unsigned long) u->skip);
346 /* Called from main thread */
347 static void source_output_kill_cb(pa_source_output *o) {
348 struct userdata *u;
350 pa_source_output_assert_ref(o);
351 pa_assert_ctl_context();
352 pa_assert_se(u = o->userdata);
354 teardown(u);
355 pa_module_unload_request(u->module, TRUE);
358 /* Called from main thread */
359 static pa_bool_t source_output_may_move_to_cb(pa_source_output *o, pa_source *dest) {
360 struct userdata *u;
362 pa_source_output_assert_ref(o);
363 pa_assert_ctl_context();
364 pa_assert_se(u = o->userdata);
366 return dest != u->sink_input->sink->monitor_source;
369 /* Called from main thread */
370 static void source_output_moving_cb(pa_source_output *o, pa_source *dest) {
371 pa_proplist *p;
372 const char *n;
373 struct userdata *u;
375 if (!dest)
376 return;
378 pa_source_output_assert_ref(o);
379 pa_assert_ctl_context();
380 pa_assert_se(u = o->userdata);
382 p = pa_proplist_new();
383 pa_proplist_setf(p, PA_PROP_MEDIA_NAME, "Loopback of %s", pa_strnull(pa_proplist_gets(dest->proplist, PA_PROP_DEVICE_DESCRIPTION)));
385 if ((n = pa_proplist_gets(dest->proplist, PA_PROP_DEVICE_ICON_NAME)))
386 pa_proplist_sets(p, PA_PROP_MEDIA_ICON_NAME, n);
388 pa_sink_input_update_proplist(u->sink_input, PA_UPDATE_REPLACE, p);
389 pa_proplist_free(p);
392 /* Called from output thread context */
393 static void update_min_memblockq_length(struct userdata *u) {
394 size_t length;
396 pa_assert(u);
397 pa_sink_input_assert_io_context(u->sink_input);
399 length = pa_memblockq_get_length(u->memblockq);
401 if (u->min_memblockq_length == (size_t) -1 ||
402 length < u->min_memblockq_length)
403 u->min_memblockq_length = length;
406 /* Called from output thread context */
407 static int sink_input_pop_cb(pa_sink_input *i, size_t nbytes, pa_memchunk *chunk) {
408 struct userdata *u;
410 pa_sink_input_assert_ref(i);
411 pa_sink_input_assert_io_context(i);
412 pa_assert_se(u = i->userdata);
413 pa_assert(chunk);
415 u->in_pop = TRUE;
416 while (pa_asyncmsgq_process_one(u->asyncmsgq) > 0)
418 u->in_pop = FALSE;
420 if (pa_memblockq_peek(u->memblockq, chunk) < 0) {
421 pa_log_info("Could not peek into queue");
422 return -1;
425 chunk->length = PA_MIN(chunk->length, nbytes);
426 pa_memblockq_drop(u->memblockq, chunk->length);
428 update_min_memblockq_length(u);
430 return 0;
433 /* Called from output thread context */
434 static void sink_input_process_rewind_cb(pa_sink_input *i, size_t nbytes) {
435 struct userdata *u;
437 pa_sink_input_assert_ref(i);
438 pa_sink_input_assert_io_context(i);
439 pa_assert_se(u = i->userdata);
441 pa_memblockq_rewind(u->memblockq, nbytes);
444 /* Called from output thread context */
445 static int sink_input_process_msg_cb(pa_msgobject *obj, int code, void *data, int64_t offset, pa_memchunk *chunk) {
446 struct userdata *u = PA_SINK_INPUT(obj)->userdata;
448 switch (code) {
450 case PA_SINK_INPUT_MESSAGE_GET_LATENCY: {
451 pa_usec_t *r = data;
453 pa_sink_input_assert_io_context(u->sink_input);
455 *r = pa_bytes_to_usec(pa_memblockq_get_length(u->memblockq), &u->sink_input->sample_spec);
457 /* Fall through, the default handler will add in the extra
458 * latency added by the resampler */
459 break;
462 case SINK_INPUT_MESSAGE_POST:
464 pa_sink_input_assert_io_context(u->sink_input);
466 if (PA_SINK_IS_OPENED(u->sink_input->sink->thread_info.state))
467 pa_memblockq_push_align(u->memblockq, chunk);
468 else
469 pa_memblockq_flush_write(u->memblockq, TRUE);
471 update_min_memblockq_length(u);
473 /* Is this the end of an underrun? Then let's start things
474 * right-away */
475 if (!u->in_pop &&
476 u->sink_input->thread_info.underrun_for > 0 &&
477 pa_memblockq_is_readable(u->memblockq)) {
479 pa_log_debug("Requesting rewind due to end of underrun.");
480 pa_sink_input_request_rewind(u->sink_input,
481 (size_t) (u->sink_input->thread_info.underrun_for == (size_t) -1 ? 0 : u->sink_input->thread_info.underrun_for),
482 FALSE, TRUE, FALSE);
485 u->recv_counter += (int64_t) chunk->length;
487 return 0;
489 case SINK_INPUT_MESSAGE_REWIND:
491 pa_sink_input_assert_io_context(u->sink_input);
493 if (PA_SINK_IS_OPENED(u->sink_input->sink->thread_info.state))
494 pa_memblockq_seek(u->memblockq, -offset, PA_SEEK_RELATIVE, TRUE);
495 else
496 pa_memblockq_flush_write(u->memblockq, TRUE);
498 u->recv_counter -= offset;
500 update_min_memblockq_length(u);
502 return 0;
504 case SINK_INPUT_MESSAGE_LATENCY_SNAPSHOT: {
505 size_t length;
507 update_min_memblockq_length(u);
509 length = pa_memblockq_get_length(u->sink_input->thread_info.render_memblockq);
511 u->latency_snapshot.recv_counter = u->recv_counter;
512 u->latency_snapshot.sink_input_buffer =
513 pa_memblockq_get_length(u->memblockq) +
514 (u->sink_input->thread_info.resampler ? pa_resampler_request(u->sink_input->thread_info.resampler, length) : length);
515 u->latency_snapshot.sink_latency = pa_sink_get_latency_within_thread(u->sink_input->sink);
517 u->latency_snapshot.max_request = pa_sink_input_get_max_request(u->sink_input);
519 u->latency_snapshot.min_memblockq_length = u->min_memblockq_length;
520 u->min_memblockq_length = (size_t) -1;
522 return 0;
525 case SINK_INPUT_MESSAGE_MAX_REQUEST_CHANGED: {
526 /* This message is sent from the IO thread to the main
527 * thread! So don't be confused. All the user cases above
528 * are executed in thread context, but this one is not! */
530 pa_assert_ctl_context();
532 if (u->adjust_time > 0)
533 adjust_rates(u);
534 return 0;
538 return pa_sink_input_process_msg(obj, code, data, offset, chunk);
541 /* Called from output thread context */
542 static void sink_input_attach_cb(pa_sink_input *i) {
543 struct userdata *u;
545 pa_sink_input_assert_ref(i);
546 pa_sink_input_assert_io_context(i);
547 pa_assert_se(u = i->userdata);
549 u->rtpoll_item_read = pa_rtpoll_item_new_asyncmsgq_read(
550 i->sink->thread_info.rtpoll,
551 PA_RTPOLL_LATE,
552 u->asyncmsgq);
554 pa_memblockq_set_prebuf(u->memblockq, pa_sink_input_get_max_request(i)*2);
555 pa_memblockq_set_maxrewind(u->memblockq, pa_sink_input_get_max_rewind(i));
557 u->min_memblockq_length = (size_t) -1;
560 /* Called from output thread context */
561 static void sink_input_detach_cb(pa_sink_input *i) {
562 struct userdata *u;
564 pa_sink_input_assert_ref(i);
565 pa_sink_input_assert_io_context(i);
566 pa_assert_se(u = i->userdata);
568 if (u->rtpoll_item_read) {
569 pa_rtpoll_item_free(u->rtpoll_item_read);
570 u->rtpoll_item_read = NULL;
574 /* Called from output thread context */
575 static void sink_input_update_max_rewind_cb(pa_sink_input *i, size_t nbytes) {
576 struct userdata *u;
578 pa_sink_input_assert_ref(i);
579 pa_sink_input_assert_io_context(i);
580 pa_assert_se(u = i->userdata);
582 pa_memblockq_set_maxrewind(u->memblockq, nbytes);
585 /* Called from output thread context */
586 static void sink_input_update_max_request_cb(pa_sink_input *i, size_t nbytes) {
587 struct userdata *u;
589 pa_sink_input_assert_ref(i);
590 pa_sink_input_assert_io_context(i);
591 pa_assert_se(u = i->userdata);
593 pa_memblockq_set_prebuf(u->memblockq, nbytes*2);
594 pa_log_info("Max request changed");
595 pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(u->sink_input), SINK_INPUT_MESSAGE_MAX_REQUEST_CHANGED, NULL, 0, NULL, NULL);
598 /* Called from main thread */
599 static void sink_input_kill_cb(pa_sink_input *i) {
600 struct userdata *u;
602 pa_sink_input_assert_ref(i);
603 pa_assert_ctl_context();
604 pa_assert_se(u = i->userdata);
606 teardown(u);
607 pa_module_unload_request(u->module, TRUE);
610 /* Called from main thread */
611 static void sink_input_moving_cb(pa_sink_input *i, pa_sink *dest) {
612 struct userdata *u;
613 pa_proplist *p;
614 const char *n;
616 if (!dest)
617 return;
619 pa_sink_input_assert_ref(i);
620 pa_assert_ctl_context();
621 pa_assert_se(u = i->userdata);
623 p = pa_proplist_new();
624 pa_proplist_setf(p, PA_PROP_MEDIA_NAME, "Loopback to %s", pa_strnull(pa_proplist_gets(dest->proplist, PA_PROP_DEVICE_DESCRIPTION)));
626 if ((n = pa_proplist_gets(dest->proplist, PA_PROP_DEVICE_ICON_NAME)))
627 pa_proplist_sets(p, PA_PROP_MEDIA_ICON_NAME, n);
629 pa_source_output_update_proplist(u->source_output, PA_UPDATE_REPLACE, p);
630 pa_proplist_free(p);
633 /* Called from main thread */
634 static pa_bool_t sink_input_may_move_to_cb(pa_sink_input *i, pa_sink *dest) {
635 struct userdata *u;
637 pa_sink_input_assert_ref(i);
638 pa_assert_ctl_context();
639 pa_assert_se(u = i->userdata);
641 if (!u->source_output->source->monitor_of)
642 return TRUE;
644 return dest != u->source_output->source->monitor_of;
647 int pa__init(pa_module *m) {
648 pa_modargs *ma = NULL;
649 struct userdata *u;
650 pa_sink *sink = NULL;
651 pa_sink_input_new_data sink_input_data;
652 pa_bool_t sink_dont_move;
653 pa_source *source = NULL;
654 pa_source_output_new_data source_output_data;
655 pa_bool_t source_dont_move;
656 uint32_t latency_msec;
657 pa_sample_spec ss;
658 pa_channel_map map;
659 bool format_set = false;
660 bool rate_set = false;
661 bool channels_set = false;
662 pa_memchunk silence;
663 uint32_t adjust_time_sec;
664 const char *n;
665 pa_bool_t remix = TRUE;
667 pa_assert(m);
669 if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
670 pa_log("Failed to parse module arguments");
671 goto fail;
674 n = pa_modargs_get_value(ma, "source", NULL);
675 if (n && !(source = pa_namereg_get(m->core, n, PA_NAMEREG_SOURCE))) {
676 pa_log("No such source.");
677 goto fail;
680 n = pa_modargs_get_value(ma, "sink", NULL);
681 if (n && !(sink = pa_namereg_get(m->core, n, PA_NAMEREG_SINK))) {
682 pa_log("No such sink.");
683 goto fail;
686 if (pa_modargs_get_value_boolean(ma, "remix", &remix) < 0) {
687 pa_log("Invalid boolean remix parameter");
688 goto fail;
691 if (sink) {
692 ss = sink->sample_spec;
693 map = sink->channel_map;
694 format_set = true;
695 rate_set = true;
696 channels_set = true;
697 } else if (source) {
698 ss = source->sample_spec;
699 map = source->channel_map;
700 format_set = true;
701 rate_set = true;
702 channels_set = true;
703 } else {
704 /* FIXME: Dummy stream format, needed because pa_sink_input_new()
705 * requires valid sample spec and channel map even when all the FIX_*
706 * stream flags are specified. pa_sink_input_new() should be changed
707 * to ignore the sample spec and channel map when the FIX_* flags are
708 * present. */
709 ss.format = PA_SAMPLE_U8;
710 ss.rate = 8000;
711 ss.channels = 1;
712 map.channels = 1;
713 map.map[0] = PA_CHANNEL_POSITION_MONO;
716 if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map, PA_CHANNEL_MAP_DEFAULT) < 0) {
717 pa_log("Invalid sample format specification or channel map");
718 goto fail;
721 if (pa_modargs_get_value(ma, "format", NULL))
722 format_set = true;
724 if (pa_modargs_get_value(ma, "rate", NULL))
725 rate_set = true;
727 if (pa_modargs_get_value(ma, "channels", NULL) || pa_modargs_get_value(ma, "channel_map", NULL))
728 channels_set = true;
730 latency_msec = DEFAULT_LATENCY_MSEC;
731 if (pa_modargs_get_value_u32(ma, "latency_msec", &latency_msec) < 0 || latency_msec < 1 || latency_msec > 2000) {
732 pa_log("Invalid latency specification");
733 goto fail;
736 m->userdata = u = pa_xnew0(struct userdata, 1);
737 u->core = m->core;
738 u->module = m;
739 u->latency = (pa_usec_t) latency_msec * PA_USEC_PER_MSEC;
741 adjust_time_sec = DEFAULT_ADJUST_TIME_USEC / PA_USEC_PER_SEC;
742 if (pa_modargs_get_value_u32(ma, "adjust_time", &adjust_time_sec) < 0) {
743 pa_log("Failed to parse adjust_time value");
744 goto fail;
747 if (adjust_time_sec != DEFAULT_ADJUST_TIME_USEC / PA_USEC_PER_SEC)
748 u->adjust_time = adjust_time_sec * PA_USEC_PER_SEC;
749 else
750 u->adjust_time = DEFAULT_ADJUST_TIME_USEC;
752 pa_sink_input_new_data_init(&sink_input_data);
753 sink_input_data.driver = __FILE__;
754 sink_input_data.module = m;
756 if (sink)
757 pa_sink_input_new_data_set_sink(&sink_input_data, sink, FALSE);
759 if (pa_modargs_get_proplist(ma, "sink_input_properties", sink_input_data.proplist, PA_UPDATE_REPLACE) < 0) {
760 pa_log("Failed to parse the sink_input_properties value.");
761 pa_sink_input_new_data_done(&sink_input_data);
762 goto fail;
765 if (!pa_proplist_contains(sink_input_data.proplist, PA_PROP_MEDIA_ROLE))
766 pa_proplist_sets(sink_input_data.proplist, PA_PROP_MEDIA_ROLE, "abstract");
768 pa_sink_input_new_data_set_sample_spec(&sink_input_data, &ss);
769 pa_sink_input_new_data_set_channel_map(&sink_input_data, &map);
770 sink_input_data.flags = PA_SINK_INPUT_VARIABLE_RATE;
772 if (!remix)
773 sink_input_data.flags |= PA_SINK_INPUT_NO_REMIX;
775 if (!format_set)
776 sink_input_data.flags |= PA_SINK_INPUT_FIX_FORMAT;
778 if (!rate_set)
779 sink_input_data.flags |= PA_SINK_INPUT_FIX_RATE;
781 if (!channels_set)
782 sink_input_data.flags |= PA_SINK_INPUT_FIX_CHANNELS;
784 sink_dont_move = FALSE;
785 if (pa_modargs_get_value_boolean(ma, "sink_dont_move", &sink_dont_move) < 0) {
786 pa_log("sink_dont_move= expects a boolean argument.");
787 goto fail;
790 if (sink_dont_move)
791 sink_input_data.flags |= PA_SINK_INPUT_DONT_MOVE;
793 pa_sink_input_new(&u->sink_input, m->core, &sink_input_data);
794 pa_sink_input_new_data_done(&sink_input_data);
796 if (!u->sink_input)
797 goto fail;
799 u->sink_input->parent.process_msg = sink_input_process_msg_cb;
800 u->sink_input->pop = sink_input_pop_cb;
801 u->sink_input->process_rewind = sink_input_process_rewind_cb;
802 u->sink_input->kill = sink_input_kill_cb;
803 u->sink_input->attach = sink_input_attach_cb;
804 u->sink_input->detach = sink_input_detach_cb;
805 u->sink_input->update_max_rewind = sink_input_update_max_rewind_cb;
806 u->sink_input->update_max_request = sink_input_update_max_request_cb;
807 u->sink_input->may_move_to = sink_input_may_move_to_cb;
808 u->sink_input->moving = sink_input_moving_cb;
809 u->sink_input->userdata = u;
811 pa_sink_input_set_requested_latency(u->sink_input, u->latency/3);
813 pa_source_output_new_data_init(&source_output_data);
814 source_output_data.driver = __FILE__;
815 source_output_data.module = m;
816 if (source)
817 pa_source_output_new_data_set_source(&source_output_data, source, FALSE);
819 if (pa_modargs_get_proplist(ma, "source_output_properties", source_output_data.proplist, PA_UPDATE_REPLACE) < 0) {
820 pa_log("Failed to parse the source_output_properties value.");
821 pa_source_output_new_data_done(&source_output_data);
822 goto fail;
825 if (!pa_proplist_contains(source_output_data.proplist, PA_PROP_MEDIA_ROLE))
826 pa_proplist_sets(source_output_data.proplist, PA_PROP_MEDIA_ROLE, "abstract");
828 pa_source_output_new_data_set_sample_spec(&source_output_data, &ss);
829 pa_source_output_new_data_set_channel_map(&source_output_data, &map);
831 if (!remix)
832 source_output_data.flags |= PA_SOURCE_OUTPUT_NO_REMIX;
834 if (!format_set)
835 source_output_data.flags |= PA_SOURCE_OUTPUT_FIX_FORMAT;
837 if (!rate_set)
838 source_output_data.flags |= PA_SOURCE_OUTPUT_FIX_RATE;
840 if (!channels_set)
841 source_output_data.flags |= PA_SOURCE_OUTPUT_FIX_CHANNELS;
843 source_dont_move = FALSE;
844 if (pa_modargs_get_value_boolean(ma, "source_dont_move", &source_dont_move) < 0) {
845 pa_log("source_dont_move= expects a boolean argument.");
846 goto fail;
849 if (source_dont_move)
850 source_output_data.flags |= PA_SOURCE_OUTPUT_DONT_MOVE;
852 pa_source_output_new(&u->source_output, m->core, &source_output_data);
853 pa_source_output_new_data_done(&source_output_data);
855 if (!u->source_output)
856 goto fail;
858 u->source_output->parent.process_msg = source_output_process_msg_cb;
859 u->source_output->push = source_output_push_cb;
860 u->source_output->process_rewind = source_output_process_rewind_cb;
861 u->source_output->kill = source_output_kill_cb;
862 u->source_output->attach = source_output_attach_cb;
863 u->source_output->detach = source_output_detach_cb;
864 u->source_output->state_change = source_output_state_change_cb;
865 u->source_output->may_move_to = source_output_may_move_to_cb;
866 u->source_output->moving = source_output_moving_cb;
867 u->source_output->userdata = u;
869 pa_source_output_set_requested_latency(u->source_output, u->latency/3);
871 pa_sink_input_get_silence(u->sink_input, &silence);
872 u->memblockq = pa_memblockq_new(
873 "module-loopback memblockq",
874 0, /* idx */
875 MEMBLOCKQ_MAXLENGTH, /* maxlength */
876 MEMBLOCKQ_MAXLENGTH, /* tlength */
877 &ss, /* sample_spec */
878 0, /* prebuf */
879 0, /* minreq */
880 0, /* maxrewind */
881 &silence); /* silence frame */
882 pa_memblock_unref(silence.memblock);
884 u->asyncmsgq = pa_asyncmsgq_new(0);
886 if (!pa_proplist_contains(u->source_output->proplist, PA_PROP_MEDIA_NAME))
887 pa_proplist_setf(u->source_output->proplist, PA_PROP_MEDIA_NAME, "Loopback to %s",
888 pa_strnull(pa_proplist_gets(u->sink_input->sink->proplist, PA_PROP_DEVICE_DESCRIPTION)));
890 if (!pa_proplist_contains(u->source_output->proplist, PA_PROP_MEDIA_ICON_NAME)
891 && (n = pa_proplist_gets(u->sink_input->sink->proplist, PA_PROP_DEVICE_ICON_NAME)))
892 pa_proplist_sets(u->source_output->proplist, PA_PROP_MEDIA_ICON_NAME, n);
894 if (!pa_proplist_contains(u->sink_input->proplist, PA_PROP_MEDIA_NAME))
895 pa_proplist_setf(u->sink_input->proplist, PA_PROP_MEDIA_NAME, "Loopback from %s",
896 pa_strnull(pa_proplist_gets(u->source_output->source->proplist, PA_PROP_DEVICE_DESCRIPTION)));
898 if (source && !pa_proplist_contains(u->sink_input->proplist, PA_PROP_MEDIA_ICON_NAME)
899 && (n = pa_proplist_gets(u->source_output->source->proplist, PA_PROP_DEVICE_ICON_NAME)))
900 pa_proplist_sets(u->sink_input->proplist, PA_PROP_MEDIA_ICON_NAME, n);
902 pa_sink_input_put(u->sink_input);
903 pa_source_output_put(u->source_output);
905 if (u->adjust_time > 0)
906 u->time_event = pa_core_rttime_new(m->core, pa_rtclock_now() + u->adjust_time, time_callback, u);
908 pa_modargs_free(ma);
909 return 0;
911 fail:
912 if (ma)
913 pa_modargs_free(ma);
915 pa__done(m);
917 return -1;
920 void pa__done(pa_module*m) {
921 struct userdata *u;
923 pa_assert(m);
925 if (!(u = m->userdata))
926 return;
928 teardown(u);
930 if (u->memblockq)
931 pa_memblockq_free(u->memblockq);
933 if (u->asyncmsgq)
934 pa_asyncmsgq_unref(u->asyncmsgq);
936 pa_xfree(u);