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
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);
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> "
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)
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
;
90 size_t min_memblockq_length
;
94 size_t source_output_buffer
;
95 pa_usec_t source_latency
;
98 size_t sink_input_buffer
;
99 pa_usec_t sink_latency
;
101 size_t min_memblockq_length
;
106 static const char* const valid_modargs
[] = {
115 "sink_input_properties",
116 "source_output_properties",
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
131 SOURCE_OUTPUT_MESSAGE_LATENCY_SNAPSHOT
134 static void enable_adjust_timer(struct userdata
*u
, bool enable
);
136 /* Called from main context */
137 static void teardown(struct userdata
*u
) {
139 pa_assert_ctl_context();
142 enable_adjust_timer(u
, false);
144 /* Handling the asyncmsgq between the source output and the sink input
145 * requires some care. When the source output is unlinked, nothing needs
146 * to be done for the asyncmsgq, because the source output is the sending
147 * end. But when the sink input is unlinked, we should ensure that the
148 * asyncmsgq is emptied, because the messages in the queue hold references
149 * to the sink input. Also, we need to ensure that new messages won't be
150 * written to the queue after we have emptied it.
152 * Emptying the queue can be done in the state_changed() callback of the
153 * sink input, when the new state is "unlinked".
155 * Preventing new messages from being written to the queue can be achieved
156 * by unlinking the source output before unlinking the sink input. There
157 * are no other writers for that queue, so this is sufficient. */
159 if (u
->source_output
) {
160 pa_source_output_unlink(u
->source_output
);
161 pa_source_output_unref(u
->source_output
);
162 u
->source_output
= NULL
;
166 pa_sink_input_unlink(u
->sink_input
);
167 pa_sink_input_unref(u
->sink_input
);
168 u
->sink_input
= NULL
;
172 /* Called from main context */
173 static void adjust_rates(struct userdata
*u
) {
175 uint32_t old_rate
, base_rate
, new_rate
;
176 pa_usec_t buffer_latency
;
179 pa_assert_ctl_context();
181 pa_asyncmsgq_send(u
->source_output
->source
->asyncmsgq
, PA_MSGOBJECT(u
->source_output
), SOURCE_OUTPUT_MESSAGE_LATENCY_SNAPSHOT
, NULL
, 0, NULL
);
182 pa_asyncmsgq_send(u
->sink_input
->sink
->asyncmsgq
, PA_MSGOBJECT(u
->sink_input
), SINK_INPUT_MESSAGE_LATENCY_SNAPSHOT
, NULL
, 0, NULL
);
185 u
->latency_snapshot
.sink_input_buffer
+
186 u
->latency_snapshot
.source_output_buffer
;
188 if (u
->latency_snapshot
.recv_counter
<= u
->latency_snapshot
.send_counter
)
189 buffer
+= (size_t) (u
->latency_snapshot
.send_counter
- u
->latency_snapshot
.recv_counter
);
191 buffer
+= PA_CLIP_SUB(buffer
, (size_t) (u
->latency_snapshot
.recv_counter
- u
->latency_snapshot
.send_counter
));
193 buffer_latency
= pa_bytes_to_usec(buffer
, &u
->sink_input
->sample_spec
);
195 pa_log_debug("Loopback overall latency is %0.2f ms + %0.2f ms + %0.2f ms = %0.2f ms",
196 (double) u
->latency_snapshot
.sink_latency
/ PA_USEC_PER_MSEC
,
197 (double) buffer_latency
/ PA_USEC_PER_MSEC
,
198 (double) u
->latency_snapshot
.source_latency
/ PA_USEC_PER_MSEC
,
199 ((double) u
->latency_snapshot
.sink_latency
+ buffer_latency
+ u
->latency_snapshot
.source_latency
) / PA_USEC_PER_MSEC
);
201 pa_log_debug("Should buffer %zu bytes, buffered at minimum %zu bytes",
202 u
->latency_snapshot
.max_request
*2,
203 u
->latency_snapshot
.min_memblockq_length
);
205 fs
= pa_frame_size(&u
->sink_input
->sample_spec
);
206 old_rate
= u
->sink_input
->sample_spec
.rate
;
207 base_rate
= u
->source_output
->sample_spec
.rate
;
209 if (u
->latency_snapshot
.min_memblockq_length
< u
->latency_snapshot
.max_request
*2)
210 new_rate
= base_rate
- (((u
->latency_snapshot
.max_request
*2 - u
->latency_snapshot
.min_memblockq_length
) / fs
) *PA_USEC_PER_SEC
)/u
->adjust_time
;
212 new_rate
= base_rate
+ (((u
->latency_snapshot
.min_memblockq_length
- u
->latency_snapshot
.max_request
*2) / fs
) *PA_USEC_PER_SEC
)/u
->adjust_time
;
214 if (new_rate
< (uint32_t) (base_rate
*0.8) || new_rate
> (uint32_t) (base_rate
*1.25)) {
215 pa_log_warn("Sample rates too different, not adjusting (%u vs. %u).", base_rate
, new_rate
);
216 new_rate
= base_rate
;
218 if (base_rate
< new_rate
+ 20 && new_rate
< base_rate
+ 20)
219 new_rate
= base_rate
;
220 /* Do the adjustment in small steps; 2‰ can be considered inaudible */
221 if (new_rate
< (uint32_t) (old_rate
*0.998) || new_rate
> (uint32_t) (old_rate
*1.002)) {
222 pa_log_info("New rate of %u Hz not within 2‰ of %u Hz, forcing smaller adjustment", new_rate
, old_rate
);
223 new_rate
= PA_CLAMP(new_rate
, (uint32_t) (old_rate
*0.998), (uint32_t) (old_rate
*1.002));
227 pa_sink_input_set_rate(u
->sink_input
, new_rate
);
228 pa_log_debug("[%s] Updated sampling rate to %lu Hz.", u
->sink_input
->sink
->name
, (unsigned long) new_rate
);
230 pa_core_rttime_restart(u
->core
, u
->time_event
, pa_rtclock_now() + u
->adjust_time
);
233 /* Called from main context */
234 static void time_callback(pa_mainloop_api
*a
, pa_time_event
*e
, const struct timeval
*t
, void *userdata
) {
235 struct userdata
*u
= userdata
;
239 pa_assert(u
->time_event
== e
);
244 /* Called from main context */
245 static void enable_adjust_timer(struct userdata
*u
, bool enable
) {
247 if (u
->time_event
|| u
->adjust_time
<= 0)
250 u
->time_event
= pa_core_rttime_new(u
->module
->core
, pa_rtclock_now() + u
->adjust_time
, time_callback
, u
);
255 u
->core
->mainloop
->time_free(u
->time_event
);
256 u
->time_event
= NULL
;
260 /* Called from main context */
261 static void update_adjust_timer(struct userdata
*u
) {
262 if (u
->sink_input
->state
== PA_SINK_INPUT_CORKED
|| u
->source_output
->state
== PA_SOURCE_OUTPUT_CORKED
)
263 enable_adjust_timer(u
, false);
265 enable_adjust_timer(u
, true);
268 /* Called from input thread context */
269 static void source_output_push_cb(pa_source_output
*o
, const pa_memchunk
*chunk
) {
273 pa_source_output_assert_ref(o
);
274 pa_source_output_assert_io_context(o
);
275 pa_assert_se(u
= o
->userdata
);
277 if (u
->skip
> chunk
->length
) {
278 u
->skip
-= chunk
->length
;
284 copy
.index
+= u
->skip
;
285 copy
.length
-= u
->skip
;
291 pa_asyncmsgq_post(u
->asyncmsgq
, PA_MSGOBJECT(u
->sink_input
), SINK_INPUT_MESSAGE_POST
, NULL
, 0, chunk
, NULL
);
292 u
->send_counter
+= (int64_t) chunk
->length
;
295 /* Called from input thread context */
296 static void source_output_process_rewind_cb(pa_source_output
*o
, size_t nbytes
) {
299 pa_source_output_assert_ref(o
);
300 pa_source_output_assert_io_context(o
);
301 pa_assert_se(u
= o
->userdata
);
303 pa_asyncmsgq_post(u
->asyncmsgq
, PA_MSGOBJECT(u
->sink_input
), SINK_INPUT_MESSAGE_REWIND
, NULL
, (int64_t) nbytes
, NULL
, NULL
);
304 u
->send_counter
-= (int64_t) nbytes
;
307 /* Called from output thread context */
308 static int source_output_process_msg_cb(pa_msgobject
*obj
, int code
, void *data
, int64_t offset
, pa_memchunk
*chunk
) {
309 struct userdata
*u
= PA_SOURCE_OUTPUT(obj
)->userdata
;
313 case SOURCE_OUTPUT_MESSAGE_LATENCY_SNAPSHOT
: {
316 length
= pa_memblockq_get_length(u
->source_output
->thread_info
.delay_memblockq
);
318 u
->latency_snapshot
.send_counter
= u
->send_counter
;
319 u
->latency_snapshot
.source_output_buffer
= u
->source_output
->thread_info
.resampler
? pa_resampler_result(u
->source_output
->thread_info
.resampler
, length
) : length
;
320 u
->latency_snapshot
.source_latency
= pa_source_get_latency_within_thread(u
->source_output
->source
);
326 return pa_source_output_process_msg(obj
, code
, data
, offset
, chunk
);
329 /* Called from output thread context */
330 static void source_output_attach_cb(pa_source_output
*o
) {
333 pa_source_output_assert_ref(o
);
334 pa_source_output_assert_io_context(o
);
335 pa_assert_se(u
= o
->userdata
);
337 u
->rtpoll_item_write
= pa_rtpoll_item_new_asyncmsgq_write(
338 o
->source
->thread_info
.rtpoll
,
343 /* Called from output thread context */
344 static void source_output_detach_cb(pa_source_output
*o
) {
347 pa_source_output_assert_ref(o
);
348 pa_source_output_assert_io_context(o
);
349 pa_assert_se(u
= o
->userdata
);
351 if (u
->rtpoll_item_write
) {
352 pa_rtpoll_item_free(u
->rtpoll_item_write
);
353 u
->rtpoll_item_write
= NULL
;
357 /* Called from output thread context */
358 static void source_output_state_change_cb(pa_source_output
*o
, pa_source_output_state_t state
) {
361 pa_source_output_assert_ref(o
);
362 pa_source_output_assert_io_context(o
);
363 pa_assert_se(u
= o
->userdata
);
365 if (PA_SOURCE_OUTPUT_IS_LINKED(state
) && o
->thread_info
.state
== PA_SOURCE_OUTPUT_INIT
) {
367 u
->skip
= pa_usec_to_bytes(PA_CLIP_SUB(pa_source_get_latency_within_thread(o
->source
),
371 pa_log_info("Skipping %lu bytes", (unsigned long) u
->skip
);
375 /* Called from main thread */
376 static void source_output_kill_cb(pa_source_output
*o
) {
379 pa_source_output_assert_ref(o
);
380 pa_assert_ctl_context();
381 pa_assert_se(u
= o
->userdata
);
384 pa_module_unload_request(u
->module
, true);
387 /* Called from main thread */
388 static bool source_output_may_move_to_cb(pa_source_output
*o
, pa_source
*dest
) {
391 pa_source_output_assert_ref(o
);
392 pa_assert_ctl_context();
393 pa_assert_se(u
= o
->userdata
);
395 if (!u
->sink_input
|| !u
->sink_input
->sink
)
398 return dest
!= u
->sink_input
->sink
->monitor_source
;
401 /* Called from main thread */
402 static void source_output_moving_cb(pa_source_output
*o
, pa_source
*dest
) {
410 pa_source_output_assert_ref(o
);
411 pa_assert_ctl_context();
412 pa_assert_se(u
= o
->userdata
);
414 p
= pa_proplist_new();
415 pa_proplist_setf(p
, PA_PROP_MEDIA_NAME
, "Loopback of %s", pa_strnull(pa_proplist_gets(dest
->proplist
, PA_PROP_DEVICE_DESCRIPTION
)));
417 if ((n
= pa_proplist_gets(dest
->proplist
, PA_PROP_DEVICE_ICON_NAME
)))
418 pa_proplist_sets(p
, PA_PROP_MEDIA_ICON_NAME
, n
);
420 pa_sink_input_update_proplist(u
->sink_input
, PA_UPDATE_REPLACE
, p
);
423 if (pa_source_get_state(dest
) == PA_SOURCE_SUSPENDED
)
424 pa_sink_input_cork(u
->sink_input
, true);
426 pa_sink_input_cork(u
->sink_input
, false);
428 update_adjust_timer(u
);
431 /* Called from main thread */
432 static void source_output_suspend_cb(pa_source_output
*o
, bool suspended
) {
435 pa_source_output_assert_ref(o
);
436 pa_assert_ctl_context();
437 pa_assert_se(u
= o
->userdata
);
439 pa_sink_input_cork(u
->sink_input
, suspended
);
441 update_adjust_timer(u
);
444 /* Called from output thread context */
445 static void update_min_memblockq_length(struct userdata
*u
) {
449 pa_sink_input_assert_io_context(u
->sink_input
);
451 length
= pa_memblockq_get_length(u
->memblockq
);
453 if (u
->min_memblockq_length
== (size_t) -1 ||
454 length
< u
->min_memblockq_length
)
455 u
->min_memblockq_length
= length
;
458 /* Called from output thread context */
459 static int sink_input_pop_cb(pa_sink_input
*i
, size_t nbytes
, pa_memchunk
*chunk
) {
462 pa_sink_input_assert_ref(i
);
463 pa_sink_input_assert_io_context(i
);
464 pa_assert_se(u
= i
->userdata
);
468 while (pa_asyncmsgq_process_one(u
->asyncmsgq
) > 0)
472 if (pa_memblockq_peek(u
->memblockq
, chunk
) < 0) {
473 pa_log_info("Could not peek into queue");
477 chunk
->length
= PA_MIN(chunk
->length
, nbytes
);
478 pa_memblockq_drop(u
->memblockq
, chunk
->length
);
480 update_min_memblockq_length(u
);
485 /* Called from output thread context */
486 static void sink_input_process_rewind_cb(pa_sink_input
*i
, size_t nbytes
) {
489 pa_sink_input_assert_ref(i
);
490 pa_sink_input_assert_io_context(i
);
491 pa_assert_se(u
= i
->userdata
);
493 pa_memblockq_rewind(u
->memblockq
, nbytes
);
496 /* Called from output thread context */
497 static int sink_input_process_msg_cb(pa_msgobject
*obj
, int code
, void *data
, int64_t offset
, pa_memchunk
*chunk
) {
498 struct userdata
*u
= PA_SINK_INPUT(obj
)->userdata
;
502 case PA_SINK_INPUT_MESSAGE_GET_LATENCY
: {
505 pa_sink_input_assert_io_context(u
->sink_input
);
507 *r
= pa_bytes_to_usec(pa_memblockq_get_length(u
->memblockq
), &u
->sink_input
->sample_spec
);
509 /* Fall through, the default handler will add in the extra
510 * latency added by the resampler */
514 case SINK_INPUT_MESSAGE_POST
:
516 pa_sink_input_assert_io_context(u
->sink_input
);
518 if (PA_SINK_IS_OPENED(u
->sink_input
->sink
->thread_info
.state
))
519 pa_memblockq_push_align(u
->memblockq
, chunk
);
521 pa_memblockq_flush_write(u
->memblockq
, true);
523 update_min_memblockq_length(u
);
525 /* Is this the end of an underrun? Then let's start things
528 u
->sink_input
->thread_info
.underrun_for
> 0 &&
529 pa_memblockq_is_readable(u
->memblockq
)) {
531 pa_log_debug("Requesting rewind due to end of underrun.");
532 pa_sink_input_request_rewind(u
->sink_input
,
533 (size_t) (u
->sink_input
->thread_info
.underrun_for
== (size_t) -1 ? 0 : u
->sink_input
->thread_info
.underrun_for
),
537 u
->recv_counter
+= (int64_t) chunk
->length
;
541 case SINK_INPUT_MESSAGE_REWIND
:
543 pa_sink_input_assert_io_context(u
->sink_input
);
545 if (PA_SINK_IS_OPENED(u
->sink_input
->sink
->thread_info
.state
))
546 pa_memblockq_seek(u
->memblockq
, -offset
, PA_SEEK_RELATIVE
, true);
548 pa_memblockq_flush_write(u
->memblockq
, true);
550 u
->recv_counter
-= offset
;
552 update_min_memblockq_length(u
);
556 case SINK_INPUT_MESSAGE_LATENCY_SNAPSHOT
: {
559 update_min_memblockq_length(u
);
561 length
= pa_memblockq_get_length(u
->sink_input
->thread_info
.render_memblockq
);
563 u
->latency_snapshot
.recv_counter
= u
->recv_counter
;
564 u
->latency_snapshot
.sink_input_buffer
=
565 pa_memblockq_get_length(u
->memblockq
) +
566 (u
->sink_input
->thread_info
.resampler
? pa_resampler_request(u
->sink_input
->thread_info
.resampler
, length
) : length
);
567 u
->latency_snapshot
.sink_latency
= pa_sink_get_latency_within_thread(u
->sink_input
->sink
);
569 u
->latency_snapshot
.max_request
= pa_sink_input_get_max_request(u
->sink_input
);
571 u
->latency_snapshot
.min_memblockq_length
= u
->min_memblockq_length
;
572 u
->min_memblockq_length
= (size_t) -1;
577 case SINK_INPUT_MESSAGE_MAX_REQUEST_CHANGED
: {
578 /* This message is sent from the IO thread to the main
579 * thread! So don't be confused. All the user cases above
580 * are executed in thread context, but this one is not! */
582 pa_assert_ctl_context();
590 return pa_sink_input_process_msg(obj
, code
, data
, offset
, chunk
);
593 /* Called from output thread context */
594 static void sink_input_attach_cb(pa_sink_input
*i
) {
597 pa_sink_input_assert_ref(i
);
598 pa_sink_input_assert_io_context(i
);
599 pa_assert_se(u
= i
->userdata
);
601 u
->rtpoll_item_read
= pa_rtpoll_item_new_asyncmsgq_read(
602 i
->sink
->thread_info
.rtpoll
,
606 pa_memblockq_set_prebuf(u
->memblockq
, pa_sink_input_get_max_request(i
)*2);
607 pa_memblockq_set_maxrewind(u
->memblockq
, pa_sink_input_get_max_rewind(i
));
609 u
->min_memblockq_length
= (size_t) -1;
612 /* Called from output thread context */
613 static void sink_input_detach_cb(pa_sink_input
*i
) {
616 pa_sink_input_assert_ref(i
);
617 pa_sink_input_assert_io_context(i
);
618 pa_assert_se(u
= i
->userdata
);
620 if (u
->rtpoll_item_read
) {
621 pa_rtpoll_item_free(u
->rtpoll_item_read
);
622 u
->rtpoll_item_read
= NULL
;
626 /* Called from output thread context */
627 static void sink_input_update_max_rewind_cb(pa_sink_input
*i
, size_t nbytes
) {
630 pa_sink_input_assert_ref(i
);
631 pa_sink_input_assert_io_context(i
);
632 pa_assert_se(u
= i
->userdata
);
634 pa_memblockq_set_maxrewind(u
->memblockq
, nbytes
);
637 /* Called from output thread context */
638 static void sink_input_update_max_request_cb(pa_sink_input
*i
, size_t nbytes
) {
641 pa_sink_input_assert_ref(i
);
642 pa_sink_input_assert_io_context(i
);
643 pa_assert_se(u
= i
->userdata
);
645 pa_memblockq_set_prebuf(u
->memblockq
, nbytes
*2);
646 pa_log_info("Max request changed");
647 pa_asyncmsgq_post(pa_thread_mq_get()->outq
, PA_MSGOBJECT(u
->sink_input
), SINK_INPUT_MESSAGE_MAX_REQUEST_CHANGED
, NULL
, 0, NULL
, NULL
);
650 /* Called from main thread */
651 static void sink_input_kill_cb(pa_sink_input
*i
) {
654 pa_sink_input_assert_ref(i
);
655 pa_assert_ctl_context();
656 pa_assert_se(u
= i
->userdata
);
659 pa_module_unload_request(u
->module
, true);
662 /* Called from the output thread context */
663 static void sink_input_state_change_cb(pa_sink_input
*i
, pa_sink_input_state_t state
) {
666 pa_sink_input_assert_ref(i
);
667 pa_assert_se(u
= i
->userdata
);
669 if (state
== PA_SINK_INPUT_UNLINKED
)
670 pa_asyncmsgq_flush(u
->asyncmsgq
, false);
673 /* Called from main thread */
674 static void sink_input_moving_cb(pa_sink_input
*i
, pa_sink
*dest
) {
682 pa_sink_input_assert_ref(i
);
683 pa_assert_ctl_context();
684 pa_assert_se(u
= i
->userdata
);
686 p
= pa_proplist_new();
687 pa_proplist_setf(p
, PA_PROP_MEDIA_NAME
, "Loopback to %s", pa_strnull(pa_proplist_gets(dest
->proplist
, PA_PROP_DEVICE_DESCRIPTION
)));
689 if ((n
= pa_proplist_gets(dest
->proplist
, PA_PROP_DEVICE_ICON_NAME
)))
690 pa_proplist_sets(p
, PA_PROP_MEDIA_ICON_NAME
, n
);
692 pa_source_output_update_proplist(u
->source_output
, PA_UPDATE_REPLACE
, p
);
695 if (pa_sink_get_state(dest
) == PA_SINK_SUSPENDED
)
696 pa_source_output_cork(u
->source_output
, true);
698 pa_source_output_cork(u
->source_output
, false);
700 update_adjust_timer(u
);
703 /* Called from main thread */
704 static bool sink_input_may_move_to_cb(pa_sink_input
*i
, pa_sink
*dest
) {
707 pa_sink_input_assert_ref(i
);
708 pa_assert_ctl_context();
709 pa_assert_se(u
= i
->userdata
);
711 if (!u
->source_output
|| !u
->source_output
->source
)
714 return dest
!= u
->source_output
->source
->monitor_of
;
717 /* Called from main thread */
718 static void sink_input_suspend_cb(pa_sink_input
*i
, bool suspended
) {
721 pa_sink_input_assert_ref(i
);
722 pa_assert_ctl_context();
723 pa_assert_se(u
= i
->userdata
);
725 pa_source_output_cork(u
->source_output
, suspended
);
727 update_adjust_timer(u
);
730 int pa__init(pa_module
*m
) {
731 pa_modargs
*ma
= NULL
;
733 pa_sink
*sink
= NULL
;
734 pa_sink_input_new_data sink_input_data
;
736 pa_source
*source
= NULL
;
737 pa_source_output_new_data source_output_data
;
738 bool source_dont_move
;
739 uint32_t latency_msec
;
742 bool format_set
= false;
743 bool rate_set
= false;
744 bool channels_set
= false;
746 uint32_t adjust_time_sec
;
752 if (!(ma
= pa_modargs_new(m
->argument
, valid_modargs
))) {
753 pa_log("Failed to parse module arguments");
757 n
= pa_modargs_get_value(ma
, "source", NULL
);
758 if (n
&& !(source
= pa_namereg_get(m
->core
, n
, PA_NAMEREG_SOURCE
))) {
759 pa_log("No such source.");
763 n
= pa_modargs_get_value(ma
, "sink", NULL
);
764 if (n
&& !(sink
= pa_namereg_get(m
->core
, n
, PA_NAMEREG_SINK
))) {
765 pa_log("No such sink.");
769 if (pa_modargs_get_value_boolean(ma
, "remix", &remix
) < 0) {
770 pa_log("Invalid boolean remix parameter");
775 ss
= sink
->sample_spec
;
776 map
= sink
->channel_map
;
781 ss
= source
->sample_spec
;
782 map
= source
->channel_map
;
787 /* FIXME: Dummy stream format, needed because pa_sink_input_new()
788 * requires valid sample spec and channel map even when all the FIX_*
789 * stream flags are specified. pa_sink_input_new() should be changed
790 * to ignore the sample spec and channel map when the FIX_* flags are
792 ss
.format
= PA_SAMPLE_U8
;
796 map
.map
[0] = PA_CHANNEL_POSITION_MONO
;
799 if (pa_modargs_get_sample_spec_and_channel_map(ma
, &ss
, &map
, PA_CHANNEL_MAP_DEFAULT
) < 0) {
800 pa_log("Invalid sample format specification or channel map");
804 if (pa_modargs_get_value(ma
, "format", NULL
))
807 if (pa_modargs_get_value(ma
, "rate", NULL
))
810 if (pa_modargs_get_value(ma
, "channels", NULL
) || pa_modargs_get_value(ma
, "channel_map", NULL
))
813 latency_msec
= DEFAULT_LATENCY_MSEC
;
814 if (pa_modargs_get_value_u32(ma
, "latency_msec", &latency_msec
) < 0 || latency_msec
< 1 || latency_msec
> 30000) {
815 pa_log("Invalid latency specification");
819 m
->userdata
= u
= pa_xnew0(struct userdata
, 1);
822 u
->latency
= (pa_usec_t
) latency_msec
* PA_USEC_PER_MSEC
;
824 adjust_time_sec
= DEFAULT_ADJUST_TIME_USEC
/ PA_USEC_PER_SEC
;
825 if (pa_modargs_get_value_u32(ma
, "adjust_time", &adjust_time_sec
) < 0) {
826 pa_log("Failed to parse adjust_time value");
830 if (adjust_time_sec
!= DEFAULT_ADJUST_TIME_USEC
/ PA_USEC_PER_SEC
)
831 u
->adjust_time
= adjust_time_sec
* PA_USEC_PER_SEC
;
833 u
->adjust_time
= DEFAULT_ADJUST_TIME_USEC
;
835 pa_sink_input_new_data_init(&sink_input_data
);
836 sink_input_data
.driver
= __FILE__
;
837 sink_input_data
.module
= m
;
840 pa_sink_input_new_data_set_sink(&sink_input_data
, sink
, false);
842 if (pa_modargs_get_proplist(ma
, "sink_input_properties", sink_input_data
.proplist
, PA_UPDATE_REPLACE
) < 0) {
843 pa_log("Failed to parse the sink_input_properties value.");
844 pa_sink_input_new_data_done(&sink_input_data
);
848 if (!pa_proplist_contains(sink_input_data
.proplist
, PA_PROP_MEDIA_ROLE
))
849 pa_proplist_sets(sink_input_data
.proplist
, PA_PROP_MEDIA_ROLE
, "abstract");
851 pa_sink_input_new_data_set_sample_spec(&sink_input_data
, &ss
);
852 pa_sink_input_new_data_set_channel_map(&sink_input_data
, &map
);
853 sink_input_data
.flags
= PA_SINK_INPUT_VARIABLE_RATE
| PA_SINK_INPUT_START_CORKED
;
856 sink_input_data
.flags
|= PA_SINK_INPUT_NO_REMIX
;
859 sink_input_data
.flags
|= PA_SINK_INPUT_FIX_FORMAT
;
862 sink_input_data
.flags
|= PA_SINK_INPUT_FIX_RATE
;
865 sink_input_data
.flags
|= PA_SINK_INPUT_FIX_CHANNELS
;
867 sink_dont_move
= false;
868 if (pa_modargs_get_value_boolean(ma
, "sink_dont_move", &sink_dont_move
) < 0) {
869 pa_log("sink_dont_move= expects a boolean argument.");
874 sink_input_data
.flags
|= PA_SINK_INPUT_DONT_MOVE
;
876 pa_sink_input_new(&u
->sink_input
, m
->core
, &sink_input_data
);
877 pa_sink_input_new_data_done(&sink_input_data
);
882 /* If format, rate or channels were originally unset, they are set now
883 * after the pa_sink_input_new() call. */
884 ss
= u
->sink_input
->sample_spec
;
885 map
= u
->sink_input
->channel_map
;
887 u
->sink_input
->parent
.process_msg
= sink_input_process_msg_cb
;
888 u
->sink_input
->pop
= sink_input_pop_cb
;
889 u
->sink_input
->process_rewind
= sink_input_process_rewind_cb
;
890 u
->sink_input
->kill
= sink_input_kill_cb
;
891 u
->sink_input
->state_change
= sink_input_state_change_cb
;
892 u
->sink_input
->attach
= sink_input_attach_cb
;
893 u
->sink_input
->detach
= sink_input_detach_cb
;
894 u
->sink_input
->update_max_rewind
= sink_input_update_max_rewind_cb
;
895 u
->sink_input
->update_max_request
= sink_input_update_max_request_cb
;
896 u
->sink_input
->may_move_to
= sink_input_may_move_to_cb
;
897 u
->sink_input
->moving
= sink_input_moving_cb
;
898 u
->sink_input
->suspend
= sink_input_suspend_cb
;
899 u
->sink_input
->userdata
= u
;
901 pa_sink_input_set_requested_latency(u
->sink_input
, u
->latency
/3);
903 pa_source_output_new_data_init(&source_output_data
);
904 source_output_data
.driver
= __FILE__
;
905 source_output_data
.module
= m
;
907 pa_source_output_new_data_set_source(&source_output_data
, source
, false);
909 if (pa_modargs_get_proplist(ma
, "source_output_properties", source_output_data
.proplist
, PA_UPDATE_REPLACE
) < 0) {
910 pa_log("Failed to parse the source_output_properties value.");
911 pa_source_output_new_data_done(&source_output_data
);
915 if (!pa_proplist_contains(source_output_data
.proplist
, PA_PROP_MEDIA_ROLE
))
916 pa_proplist_sets(source_output_data
.proplist
, PA_PROP_MEDIA_ROLE
, "abstract");
918 pa_source_output_new_data_set_sample_spec(&source_output_data
, &ss
);
919 pa_source_output_new_data_set_channel_map(&source_output_data
, &map
);
920 source_output_data
.flags
= PA_SOURCE_OUTPUT_START_CORKED
;
923 source_output_data
.flags
|= PA_SOURCE_OUTPUT_NO_REMIX
;
925 source_dont_move
= false;
926 if (pa_modargs_get_value_boolean(ma
, "source_dont_move", &source_dont_move
) < 0) {
927 pa_log("source_dont_move= expects a boolean argument.");
931 if (source_dont_move
)
932 source_output_data
.flags
|= PA_SOURCE_OUTPUT_DONT_MOVE
;
934 pa_source_output_new(&u
->source_output
, m
->core
, &source_output_data
);
935 pa_source_output_new_data_done(&source_output_data
);
937 if (!u
->source_output
)
940 u
->source_output
->parent
.process_msg
= source_output_process_msg_cb
;
941 u
->source_output
->push
= source_output_push_cb
;
942 u
->source_output
->process_rewind
= source_output_process_rewind_cb
;
943 u
->source_output
->kill
= source_output_kill_cb
;
944 u
->source_output
->attach
= source_output_attach_cb
;
945 u
->source_output
->detach
= source_output_detach_cb
;
946 u
->source_output
->state_change
= source_output_state_change_cb
;
947 u
->source_output
->may_move_to
= source_output_may_move_to_cb
;
948 u
->source_output
->moving
= source_output_moving_cb
;
949 u
->source_output
->suspend
= source_output_suspend_cb
;
950 u
->source_output
->userdata
= u
;
952 pa_source_output_set_requested_latency(u
->source_output
, u
->latency
/3);
954 pa_sink_input_get_silence(u
->sink_input
, &silence
);
955 u
->memblockq
= pa_memblockq_new(
956 "module-loopback memblockq",
958 MEMBLOCKQ_MAXLENGTH
, /* maxlength */
959 MEMBLOCKQ_MAXLENGTH
, /* tlength */
960 &ss
, /* sample_spec */
964 &silence
); /* silence frame */
965 pa_memblock_unref(silence
.memblock
);
967 u
->asyncmsgq
= pa_asyncmsgq_new(0);
969 if (!pa_proplist_contains(u
->source_output
->proplist
, PA_PROP_MEDIA_NAME
))
970 pa_proplist_setf(u
->source_output
->proplist
, PA_PROP_MEDIA_NAME
, "Loopback to %s",
971 pa_strnull(pa_proplist_gets(u
->sink_input
->sink
->proplist
, PA_PROP_DEVICE_DESCRIPTION
)));
973 if (!pa_proplist_contains(u
->source_output
->proplist
, PA_PROP_MEDIA_ICON_NAME
)
974 && (n
= pa_proplist_gets(u
->sink_input
->sink
->proplist
, PA_PROP_DEVICE_ICON_NAME
)))
975 pa_proplist_sets(u
->source_output
->proplist
, PA_PROP_MEDIA_ICON_NAME
, n
);
977 if (!pa_proplist_contains(u
->sink_input
->proplist
, PA_PROP_MEDIA_NAME
))
978 pa_proplist_setf(u
->sink_input
->proplist
, PA_PROP_MEDIA_NAME
, "Loopback from %s",
979 pa_strnull(pa_proplist_gets(u
->source_output
->source
->proplist
, PA_PROP_DEVICE_DESCRIPTION
)));
981 if (source
&& !pa_proplist_contains(u
->sink_input
->proplist
, PA_PROP_MEDIA_ICON_NAME
)
982 && (n
= pa_proplist_gets(u
->source_output
->source
->proplist
, PA_PROP_DEVICE_ICON_NAME
)))
983 pa_proplist_sets(u
->sink_input
->proplist
, PA_PROP_MEDIA_ICON_NAME
, n
);
985 pa_sink_input_put(u
->sink_input
);
986 pa_source_output_put(u
->source_output
);
988 if (pa_source_get_state(u
->source_output
->source
) != PA_SOURCE_SUSPENDED
)
989 pa_sink_input_cork(u
->sink_input
, false);
991 if (pa_sink_get_state(u
->sink_input
->sink
) != PA_SINK_SUSPENDED
)
992 pa_source_output_cork(u
->source_output
, false);
994 update_adjust_timer(u
);
1001 pa_modargs_free(ma
);
1008 void pa__done(pa_module
*m
) {
1013 if (!(u
= m
->userdata
))
1019 pa_memblockq_free(u
->memblockq
);
1022 pa_asyncmsgq_unref(u
->asyncmsgq
);