]> code.delx.au - pulseaudio/blob - src/modules/module-loopback.c
Limit rate adjustments to small, inaudible jumps
[pulseaudio] / src / modules / module-loopback.c
1 /***
2 This file is part of PulseAudio.
3
4 Copyright 2009 Intel Corporation
5 Contributor: Pierre-Louis Bossart <pierre-louis.bossart@intel.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, write to the Free Software
19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
20 USA.
21 ***/
22
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26
27 #include <stdio.h>
28 #include <math.h>
29
30 #include <pulse/xmalloc.h>
31
32 #include <pulsecore/sink-input.h>
33 #include <pulsecore/module.h>
34 #include <pulsecore/modargs.h>
35 #include <pulsecore/namereg.h>
36 #include <pulsecore/log.h>
37 #include <pulsecore/core-util.h>
38
39 #include <pulse/rtclock.h>
40 #include <pulse/timeval.h>
41
42 #include "module-loopback-symdef.h"
43
44 PA_MODULE_AUTHOR("Pierre-Louis Bossart");
45 PA_MODULE_DESCRIPTION("Loopback from source to sink");
46 PA_MODULE_VERSION(PACKAGE_VERSION);
47 PA_MODULE_LOAD_ONCE(FALSE);
48 PA_MODULE_USAGE(
49 "source=<source to connect to> "
50 "sink=<sink to connect to> "
51 "adjust_time=<how often to readjust rates in s> "
52 "latency_msec=<latency in ms> "
53 "format=<sample format> "
54 "rate=<sample rate> "
55 "channels=<number of channels> "
56 "channel_map=<channel map> "
57 "sink_input_name=<custom name for the sink input> "
58 "source_output_name=<custom name for the source output> "
59 "sink_input_role=<media.role for the sink input> "
60 "source_output_role=<media.role for the source output>");
61
62 #define DEFAULT_LATENCY_MSEC 200
63
64 #define MEMBLOCKQ_MAXLENGTH (1024*1024*16)
65
66 #define DEFAULT_ADJUST_TIME_USEC (10*PA_USEC_PER_SEC)
67
68 struct userdata {
69 pa_core *core;
70 pa_module *module;
71
72 pa_sink_input *sink_input;
73 pa_source_output *source_output;
74
75 pa_asyncmsgq *asyncmsgq;
76 pa_memblockq *memblockq;
77
78 pa_rtpoll_item *rtpoll_item_read, *rtpoll_item_write;
79
80 pa_time_event *time_event;
81 pa_usec_t adjust_time;
82
83 int64_t recv_counter;
84 int64_t send_counter;
85
86 size_t skip;
87 pa_usec_t latency;
88
89 pa_bool_t in_pop;
90 size_t min_memblockq_length;
91
92 struct {
93 int64_t send_counter;
94 size_t source_output_buffer;
95 pa_usec_t source_latency;
96
97 int64_t recv_counter;
98 size_t sink_input_buffer;
99 pa_usec_t sink_latency;
100
101 size_t min_memblockq_length;
102 size_t max_request;
103 } latency_snapshot;
104 };
105
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_name",
116 "source_output_name",
117 "sink_input_role",
118 "source_output_role",
119 NULL,
120 };
121
122 enum {
123 SINK_INPUT_MESSAGE_POST = PA_SINK_INPUT_MESSAGE_MAX,
124 SINK_INPUT_MESSAGE_REWIND,
125 SINK_INPUT_MESSAGE_LATENCY_SNAPSHOT,
126 SINK_INPUT_MESSAGE_MAX_REQUEST_CHANGED
127 };
128
129 enum {
130 SOURCE_OUTPUT_MESSAGE_LATENCY_SNAPSHOT
131 };
132
133 /* Called from main context */
134 static void teardown(struct userdata *u) {
135 pa_assert(u);
136 pa_assert_ctl_context();
137
138 if (u->sink_input)
139 pa_sink_input_unlink(u->sink_input);
140
141 if (u->source_output)
142 pa_source_output_unlink(u->source_output);
143
144 if (u->sink_input) {
145 pa_sink_input_unref(u->sink_input);
146 u->sink_input = NULL;
147 }
148
149 if (u->source_output) {
150 pa_source_output_unref(u->source_output);
151 u->source_output = NULL;
152 }
153 }
154
155 /* Called from main context */
156 static void adjust_rates(struct userdata *u) {
157 size_t buffer, fs;
158 uint32_t old_rate, base_rate, new_rate;
159 pa_usec_t buffer_latency;
160
161 pa_assert(u);
162 pa_assert_ctl_context();
163
164 pa_asyncmsgq_send(u->source_output->source->asyncmsgq, PA_MSGOBJECT(u->source_output), SOURCE_OUTPUT_MESSAGE_LATENCY_SNAPSHOT, NULL, 0, NULL);
165 pa_asyncmsgq_send(u->sink_input->sink->asyncmsgq, PA_MSGOBJECT(u->sink_input), SINK_INPUT_MESSAGE_LATENCY_SNAPSHOT, NULL, 0, NULL);
166
167 buffer =
168 u->latency_snapshot.sink_input_buffer +
169 u->latency_snapshot.source_output_buffer;
170
171 if (u->latency_snapshot.recv_counter <= u->latency_snapshot.send_counter)
172 buffer += (size_t) (u->latency_snapshot.send_counter - u->latency_snapshot.recv_counter);
173 else
174 buffer += PA_CLIP_SUB(buffer, (size_t) (u->latency_snapshot.recv_counter - u->latency_snapshot.send_counter));
175
176 buffer_latency = pa_bytes_to_usec(buffer, &u->sink_input->sample_spec);
177
178 pa_log_debug("Loopback overall latency is %0.2f ms + %0.2f ms + %0.2f ms = %0.2f ms",
179 (double) u->latency_snapshot.sink_latency / PA_USEC_PER_MSEC,
180 (double) buffer_latency / PA_USEC_PER_MSEC,
181 (double) u->latency_snapshot.source_latency / PA_USEC_PER_MSEC,
182 ((double) u->latency_snapshot.sink_latency + buffer_latency + u->latency_snapshot.source_latency) / PA_USEC_PER_MSEC);
183
184 pa_log_debug("Should buffer %zu bytes, buffered at minimum %zu bytes",
185 u->latency_snapshot.max_request*2,
186 u->latency_snapshot.min_memblockq_length);
187
188 fs = pa_frame_size(&u->sink_input->sample_spec);
189 old_rate = u->sink_input->sample_spec.rate;
190 base_rate = u->source_output->sample_spec.rate;
191
192 if (u->latency_snapshot.min_memblockq_length < u->latency_snapshot.max_request*2)
193 new_rate = base_rate - (((u->latency_snapshot.max_request*2 - u->latency_snapshot.min_memblockq_length) / fs) *PA_USEC_PER_SEC)/u->adjust_time;
194 else
195 new_rate = base_rate + (((u->latency_snapshot.min_memblockq_length - u->latency_snapshot.max_request*2) / fs) *PA_USEC_PER_SEC)/u->adjust_time;
196
197 if (new_rate < (uint32_t) (base_rate*0.8) || new_rate > (uint32_t) (base_rate*1.25)) {
198 pa_log_warn("Sample rates too different, not adjusting (%u vs. %u).", base_rate, new_rate);
199 new_rate = base_rate;
200 } else {
201 if (base_rate < new_rate + 20 && new_rate < base_rate + 20)
202 new_rate = base_rate;
203 /* Do the adjustment in small steps; 2‰ can be considered inaudible */
204 if (new_rate < (uint32_t) (old_rate*0.998) || new_rate > (uint32_t) (old_rate*1.002)) {
205 pa_log_info("New rate of %u Hz not within 2‰ of %u Hz, forcing smaller adjustment", new_rate, old_rate);
206 new_rate = PA_CLAMP(new_rate, (uint32_t) (old_rate*0.998), (uint32_t) (old_rate*1.002));
207 }
208 }
209
210 pa_sink_input_set_rate(u->sink_input, new_rate);
211 pa_log_debug("[%s] Updated sampling rate to %lu Hz.", u->sink_input->sink->name, (unsigned long) new_rate);
212
213 pa_core_rttime_restart(u->core, u->time_event, pa_rtclock_now() + u->adjust_time);
214 }
215
216 /* Called from main context */
217 static void time_callback(pa_mainloop_api *a, pa_time_event *e, const struct timeval *t, void *userdata) {
218 struct userdata *u = userdata;
219
220 pa_assert(u);
221 pa_assert(a);
222 pa_assert(u->time_event == e);
223
224 adjust_rates(u);
225 }
226
227 /* Called from input thread context */
228 static void source_output_push_cb(pa_source_output *o, const pa_memchunk *chunk) {
229 struct userdata *u;
230 pa_memchunk copy;
231
232 pa_source_output_assert_ref(o);
233 pa_source_output_assert_io_context(o);
234 pa_assert_se(u = o->userdata);
235
236 if (u->skip > chunk->length) {
237 u->skip -= chunk->length;
238 return;
239 }
240
241 if (u->skip > 0) {
242 copy = *chunk;
243 copy.index += u->skip;
244 copy.length -= u->skip;
245 u->skip = 0;
246
247 chunk = &copy;
248 }
249
250 pa_asyncmsgq_post(u->asyncmsgq, PA_MSGOBJECT(u->sink_input), SINK_INPUT_MESSAGE_POST, NULL, 0, chunk, NULL);
251 u->send_counter += (int64_t) chunk->length;
252 }
253
254 /* Called from input thread context */
255 static void source_output_process_rewind_cb(pa_source_output *o, size_t nbytes) {
256 struct userdata *u;
257
258 pa_source_output_assert_ref(o);
259 pa_source_output_assert_io_context(o);
260 pa_assert_se(u = o->userdata);
261
262 pa_asyncmsgq_post(u->asyncmsgq, PA_MSGOBJECT(u->sink_input), SINK_INPUT_MESSAGE_REWIND, NULL, (int64_t) nbytes, NULL, NULL);
263 u->send_counter -= (int64_t) nbytes;
264 }
265
266 /* Called from output thread context */
267 static int source_output_process_msg_cb(pa_msgobject *obj, int code, void *data, int64_t offset, pa_memchunk *chunk) {
268 struct userdata *u = PA_SOURCE_OUTPUT(obj)->userdata;
269
270 switch (code) {
271
272 case SOURCE_OUTPUT_MESSAGE_LATENCY_SNAPSHOT: {
273 size_t length;
274
275 length = pa_memblockq_get_length(u->source_output->thread_info.delay_memblockq);
276
277 u->latency_snapshot.send_counter = u->send_counter;
278 u->latency_snapshot.source_output_buffer = u->source_output->thread_info.resampler ? pa_resampler_result(u->source_output->thread_info.resampler, length) : length;
279 u->latency_snapshot.source_latency = pa_source_get_latency_within_thread(u->source_output->source);
280
281 return 0;
282 }
283 }
284
285 return pa_source_output_process_msg(obj, code, data, offset, chunk);
286 }
287
288 /* Called from output thread context */
289 static void source_output_attach_cb(pa_source_output *o) {
290 struct userdata *u;
291
292 pa_source_output_assert_ref(o);
293 pa_source_output_assert_io_context(o);
294 pa_assert_se(u = o->userdata);
295
296 u->rtpoll_item_write = pa_rtpoll_item_new_asyncmsgq_write(
297 o->source->thread_info.rtpoll,
298 PA_RTPOLL_LATE,
299 u->asyncmsgq);
300 }
301
302 /* Called from output thread context */
303 static void source_output_detach_cb(pa_source_output *o) {
304 struct userdata *u;
305
306 pa_source_output_assert_ref(o);
307 pa_source_output_assert_io_context(o);
308 pa_assert_se(u = o->userdata);
309
310 if (u->rtpoll_item_write) {
311 pa_rtpoll_item_free(u->rtpoll_item_write);
312 u->rtpoll_item_write = NULL;
313 }
314 }
315
316 /* Called from output thread context */
317 static void source_output_state_change_cb(pa_source_output *o, pa_source_output_state_t state) {
318 struct userdata *u;
319
320 pa_source_output_assert_ref(o);
321 pa_source_output_assert_io_context(o);
322 pa_assert_se(u = o->userdata);
323
324 if (PA_SOURCE_OUTPUT_IS_LINKED(state) && o->thread_info.state == PA_SOURCE_OUTPUT_INIT) {
325
326 u->skip = pa_usec_to_bytes(PA_CLIP_SUB(pa_source_get_latency_within_thread(o->source),
327 u->latency),
328 &o->sample_spec);
329
330 pa_log_info("Skipping %lu bytes", (unsigned long) u->skip);
331 }
332 }
333
334 /* Called from main thread */
335 static void source_output_kill_cb(pa_source_output *o) {
336 struct userdata *u;
337
338 pa_source_output_assert_ref(o);
339 pa_assert_ctl_context();
340 pa_assert_se(u = o->userdata);
341
342 teardown(u);
343 pa_module_unload_request(u->module, TRUE);
344 }
345
346 /* Called from main thread */
347 static pa_bool_t source_output_may_move_to_cb(pa_source_output *o, pa_source *dest) {
348 struct userdata *u;
349
350 pa_source_output_assert_ref(o);
351 pa_assert_ctl_context();
352 pa_assert_se(u = o->userdata);
353
354 return dest != u->sink_input->sink->monitor_source;
355 }
356
357 /* Called from main thread */
358 static void source_output_moving_cb(pa_source_output *o, pa_source *dest) {
359 pa_proplist *p;
360 const char *n;
361 struct userdata *u;
362
363 pa_source_output_assert_ref(o);
364 pa_assert_ctl_context();
365 pa_assert_se(u = o->userdata);
366
367 p = pa_proplist_new();
368 pa_proplist_setf(p, PA_PROP_MEDIA_NAME, "Loopback of %s", pa_strnull(pa_proplist_gets(dest->proplist, PA_PROP_DEVICE_DESCRIPTION)));
369
370 if ((n = pa_proplist_gets(dest->proplist, PA_PROP_DEVICE_ICON_NAME)))
371 pa_proplist_sets(p, PA_PROP_MEDIA_ICON_NAME, n);
372
373 pa_sink_input_update_proplist(u->sink_input, PA_UPDATE_REPLACE, p);
374 pa_proplist_free(p);
375 }
376
377 /* Called from output thread context */
378 static void update_min_memblockq_length(struct userdata *u) {
379 size_t length;
380
381 pa_assert(u);
382 pa_sink_input_assert_io_context(u->sink_input);
383
384 length = pa_memblockq_get_length(u->memblockq);
385
386 if (u->min_memblockq_length == (size_t) -1 ||
387 length < u->min_memblockq_length)
388 u->min_memblockq_length = length;
389 }
390
391 /* Called from output thread context */
392 static int sink_input_pop_cb(pa_sink_input *i, size_t nbytes, pa_memchunk *chunk) {
393 struct userdata *u;
394
395 pa_sink_input_assert_ref(i);
396 pa_sink_input_assert_io_context(i);
397 pa_assert_se(u = i->userdata);
398 pa_assert(chunk);
399
400 u->in_pop = TRUE;
401 while (pa_asyncmsgq_process_one(u->asyncmsgq) > 0)
402 ;
403 u->in_pop = FALSE;
404
405 if (pa_memblockq_peek(u->memblockq, chunk) < 0) {
406 pa_log_info("Coud not peek into queue");
407 return -1;
408 }
409
410 chunk->length = PA_MIN(chunk->length, nbytes);
411 pa_memblockq_drop(u->memblockq, chunk->length);
412
413 update_min_memblockq_length(u);
414
415 return 0;
416 }
417
418 /* Called from output thread context */
419 static void sink_input_process_rewind_cb(pa_sink_input *i, size_t nbytes) {
420 struct userdata *u;
421
422 pa_sink_input_assert_ref(i);
423 pa_sink_input_assert_io_context(i);
424 pa_assert_se(u = i->userdata);
425
426 pa_memblockq_rewind(u->memblockq, nbytes);
427 }
428
429 /* Called from output thread context */
430 static int sink_input_process_msg_cb(pa_msgobject *obj, int code, void *data, int64_t offset, pa_memchunk *chunk) {
431 struct userdata *u = PA_SINK_INPUT(obj)->userdata;
432
433 switch (code) {
434
435 case PA_SINK_INPUT_MESSAGE_GET_LATENCY: {
436 pa_usec_t *r = data;
437
438 pa_sink_input_assert_io_context(u->sink_input);
439
440 *r = pa_bytes_to_usec(pa_memblockq_get_length(u->memblockq), &u->sink_input->sample_spec);
441
442 /* Fall through, the default handler will add in the extra
443 * latency added by the resampler */
444 break;
445 }
446
447 case SINK_INPUT_MESSAGE_POST:
448
449 pa_sink_input_assert_io_context(u->sink_input);
450
451 if (PA_SINK_IS_OPENED(u->sink_input->sink->thread_info.state))
452 pa_memblockq_push_align(u->memblockq, chunk);
453 else
454 pa_memblockq_flush_write(u->memblockq, TRUE);
455
456 update_min_memblockq_length(u);
457
458 /* Is this the end of an underrun? Then let's start things
459 * right-away */
460 if (!u->in_pop &&
461 u->sink_input->thread_info.underrun_for > 0 &&
462 pa_memblockq_is_readable(u->memblockq)) {
463
464 pa_log_debug("Requesting rewind due to end of underrun.");
465 pa_sink_input_request_rewind(u->sink_input,
466 (size_t) (u->sink_input->thread_info.underrun_for == (size_t) -1 ? 0 : u->sink_input->thread_info.underrun_for),
467 FALSE, TRUE, FALSE);
468 }
469
470 u->recv_counter += (int64_t) chunk->length;
471
472 return 0;
473
474 case SINK_INPUT_MESSAGE_REWIND:
475
476 pa_sink_input_assert_io_context(u->sink_input);
477
478 if (PA_SINK_IS_OPENED(u->sink_input->sink->thread_info.state))
479 pa_memblockq_seek(u->memblockq, -offset, PA_SEEK_RELATIVE, TRUE);
480 else
481 pa_memblockq_flush_write(u->memblockq, TRUE);
482
483 u->recv_counter -= offset;
484
485 update_min_memblockq_length(u);
486
487 return 0;
488
489 case SINK_INPUT_MESSAGE_LATENCY_SNAPSHOT: {
490 size_t length;
491
492 update_min_memblockq_length(u);
493
494 length = pa_memblockq_get_length(u->sink_input->thread_info.render_memblockq);
495
496 u->latency_snapshot.recv_counter = u->recv_counter;
497 u->latency_snapshot.sink_input_buffer =
498 pa_memblockq_get_length(u->memblockq) +
499 (u->sink_input->thread_info.resampler ? pa_resampler_request(u->sink_input->thread_info.resampler, length) : length);
500 u->latency_snapshot.sink_latency = pa_sink_get_latency_within_thread(u->sink_input->sink);
501
502 u->latency_snapshot.max_request = pa_sink_input_get_max_request(u->sink_input);
503
504 u->latency_snapshot.min_memblockq_length = u->min_memblockq_length;
505 u->min_memblockq_length = (size_t) -1;
506
507 return 0;
508 }
509
510 case SINK_INPUT_MESSAGE_MAX_REQUEST_CHANGED: {
511 /* This message is sent from the IO thread to the main
512 * thread! So don't be confused. All the user cases above
513 * are executed in thread context, but this one is not! */
514
515 pa_assert_ctl_context();
516
517 if (u->adjust_time > 0)
518 adjust_rates(u);
519 return 0;
520 }
521 }
522
523 return pa_sink_input_process_msg(obj, code, data, offset, chunk);
524 }
525
526 /* Called from output thread context */
527 static void sink_input_attach_cb(pa_sink_input *i) {
528 struct userdata *u;
529
530 pa_sink_input_assert_ref(i);
531 pa_sink_input_assert_io_context(i);
532 pa_assert_se(u = i->userdata);
533
534 u->rtpoll_item_read = pa_rtpoll_item_new_asyncmsgq_read(
535 i->sink->thread_info.rtpoll,
536 PA_RTPOLL_LATE,
537 u->asyncmsgq);
538
539 pa_memblockq_set_prebuf(u->memblockq, pa_sink_input_get_max_request(i)*2);
540 pa_memblockq_set_maxrewind(u->memblockq, pa_sink_input_get_max_rewind(i));
541
542 u->min_memblockq_length = (size_t) -1;
543 }
544
545 /* Called from output thread context */
546 static void sink_input_detach_cb(pa_sink_input *i) {
547 struct userdata *u;
548
549 pa_sink_input_assert_ref(i);
550 pa_sink_input_assert_io_context(i);
551 pa_assert_se(u = i->userdata);
552
553 if (u->rtpoll_item_read) {
554 pa_rtpoll_item_free(u->rtpoll_item_read);
555 u->rtpoll_item_read = NULL;
556 }
557 }
558
559 /* Called from output thread context */
560 static void sink_input_update_max_rewind_cb(pa_sink_input *i, size_t nbytes) {
561 struct userdata *u;
562
563 pa_sink_input_assert_ref(i);
564 pa_sink_input_assert_io_context(i);
565 pa_assert_se(u = i->userdata);
566
567 pa_memblockq_set_maxrewind(u->memblockq, nbytes);
568 }
569
570 /* Called from output thread context */
571 static void sink_input_update_max_request_cb(pa_sink_input *i, size_t nbytes) {
572 struct userdata *u;
573
574 pa_sink_input_assert_ref(i);
575 pa_sink_input_assert_io_context(i);
576 pa_assert_se(u = i->userdata);
577
578 pa_memblockq_set_prebuf(u->memblockq, nbytes*2);
579 pa_log_info("Max request changed");
580 pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(u->sink_input), SINK_INPUT_MESSAGE_MAX_REQUEST_CHANGED, NULL, 0, NULL, NULL);
581 }
582
583 /* Called from main thread */
584 static void sink_input_kill_cb(pa_sink_input *i) {
585 struct userdata *u;
586
587 pa_sink_input_assert_ref(i);
588 pa_assert_ctl_context();
589 pa_assert_se(u = i->userdata);
590
591 teardown(u);
592 pa_module_unload_request(u->module, TRUE);
593 }
594
595 /* Called from main thread */
596 static void sink_input_moving_cb(pa_sink_input *i, pa_sink *dest) {
597 struct userdata *u;
598 pa_proplist *p;
599 const char *n;
600
601 pa_sink_input_assert_ref(i);
602 pa_assert_ctl_context();
603 pa_assert_se(u = i->userdata);
604
605 p = pa_proplist_new();
606 pa_proplist_setf(p, PA_PROP_MEDIA_NAME, "Loopback to %s", pa_strnull(pa_proplist_gets(dest->proplist, PA_PROP_DEVICE_DESCRIPTION)));
607
608 if ((n = pa_proplist_gets(dest->proplist, PA_PROP_DEVICE_ICON_NAME)))
609 pa_proplist_sets(p, PA_PROP_MEDIA_ICON_NAME, n);
610
611 pa_source_output_update_proplist(u->source_output, PA_UPDATE_REPLACE, p);
612 pa_proplist_free(p);
613 }
614
615 /* Called from main thread */
616 static pa_bool_t sink_input_may_move_to_cb(pa_sink_input *i, pa_sink *dest) {
617 struct userdata *u;
618
619 pa_sink_input_assert_ref(i);
620 pa_assert_ctl_context();
621 pa_assert_se(u = i->userdata);
622
623 if (!u->source_output->source->monitor_of)
624 return TRUE;
625
626 return dest != u->source_output->source->monitor_of;
627 }
628
629 int pa__init(pa_module *m) {
630 pa_modargs *ma = NULL;
631 struct userdata *u;
632 pa_sink *sink;
633 pa_sink_input_new_data sink_input_data;
634 pa_source *source;
635 pa_source_output_new_data source_output_data;
636 uint32_t latency_msec;
637 pa_sample_spec ss;
638 pa_channel_map map;
639 pa_memchunk silence;
640 uint32_t adjust_time_sec;
641 const char *n;
642
643 pa_assert(m);
644
645 if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
646 pa_log("Failed to parse module arguments");
647 goto fail;
648 }
649
650 if (!(source = pa_namereg_get(m->core, pa_modargs_get_value(ma, "source", NULL), PA_NAMEREG_SOURCE))) {
651 pa_log("No such source.");
652 goto fail;
653 }
654
655 if (!(sink = pa_namereg_get(m->core, pa_modargs_get_value(ma, "sink", NULL), PA_NAMEREG_SINK))) {
656 pa_log("No such sink.");
657 goto fail;
658 }
659
660 ss = sink->sample_spec;
661 map = sink->channel_map;
662 if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map, PA_CHANNEL_MAP_DEFAULT) < 0) {
663 pa_log("Invalid sample format specification or channel map");
664 goto fail;
665 }
666
667 latency_msec = DEFAULT_LATENCY_MSEC;
668 if (pa_modargs_get_value_u32(ma, "latency_msec", &latency_msec) < 0 || latency_msec < 1 || latency_msec > 2000) {
669 pa_log("Invalid latency specification");
670 goto fail;
671 }
672
673 m->userdata = u = pa_xnew0(struct userdata, 1);
674 u->core = m->core;
675 u->module = m;
676 u->latency = (pa_usec_t) latency_msec * PA_USEC_PER_MSEC;
677
678 adjust_time_sec = DEFAULT_ADJUST_TIME_USEC / PA_USEC_PER_SEC;
679 if (pa_modargs_get_value_u32(ma, "adjust_time", &adjust_time_sec) < 0) {
680 pa_log("Failed to parse adjust_time value");
681 goto fail;
682 }
683
684 if (adjust_time_sec != DEFAULT_ADJUST_TIME_USEC / PA_USEC_PER_SEC)
685 u->adjust_time = adjust_time_sec * PA_USEC_PER_SEC;
686 else
687 u->adjust_time = DEFAULT_ADJUST_TIME_USEC;
688
689 pa_sink_input_new_data_init(&sink_input_data);
690 sink_input_data.driver = __FILE__;
691 sink_input_data.module = m;
692 sink_input_data.sink = sink;
693
694 if ((n = pa_modargs_get_value(ma, "sink_input_name", NULL)))
695 pa_proplist_sets(sink_input_data.proplist, PA_PROP_MEDIA_NAME, n);
696 else
697 pa_proplist_setf(sink_input_data.proplist, PA_PROP_MEDIA_NAME, "Loopback from %s",
698 pa_strnull(pa_proplist_gets(source->proplist, PA_PROP_DEVICE_DESCRIPTION)));
699
700 if ((n = pa_modargs_get_value(ma, "sink_input_role", NULL)))
701 pa_proplist_sets(sink_input_data.proplist, PA_PROP_MEDIA_ROLE, n);
702 else
703 pa_proplist_sets(sink_input_data.proplist, PA_PROP_MEDIA_ROLE, "abstract");
704
705 if ((n = pa_proplist_gets(source->proplist, PA_PROP_DEVICE_ICON_NAME)))
706 pa_proplist_sets(sink_input_data.proplist, PA_PROP_MEDIA_ICON_NAME, n);
707
708 pa_sink_input_new_data_set_sample_spec(&sink_input_data, &ss);
709 pa_sink_input_new_data_set_channel_map(&sink_input_data, &map);
710 sink_input_data.flags = PA_SINK_INPUT_VARIABLE_RATE;
711
712 pa_sink_input_new(&u->sink_input, m->core, &sink_input_data);
713 pa_sink_input_new_data_done(&sink_input_data);
714
715 if (!u->sink_input)
716 goto fail;
717
718 u->sink_input->parent.process_msg = sink_input_process_msg_cb;
719 u->sink_input->pop = sink_input_pop_cb;
720 u->sink_input->process_rewind = sink_input_process_rewind_cb;
721 u->sink_input->kill = sink_input_kill_cb;
722 u->sink_input->attach = sink_input_attach_cb;
723 u->sink_input->detach = sink_input_detach_cb;
724 u->sink_input->update_max_rewind = sink_input_update_max_rewind_cb;
725 u->sink_input->update_max_request = sink_input_update_max_request_cb;
726 u->sink_input->may_move_to = sink_input_may_move_to_cb;
727 u->sink_input->moving = sink_input_moving_cb;
728 u->sink_input->userdata = u;
729
730 pa_sink_input_set_requested_latency(u->sink_input, u->latency/3);
731
732 pa_source_output_new_data_init(&source_output_data);
733 source_output_data.driver = __FILE__;
734 source_output_data.module = m;
735 source_output_data.source = source;
736
737 if ((n = pa_modargs_get_value(ma, "source_output_name", NULL)))
738 pa_proplist_sets(source_output_data.proplist, PA_PROP_MEDIA_NAME, n);
739 else
740 pa_proplist_setf(source_output_data.proplist, PA_PROP_MEDIA_NAME, "Loopback to %s",
741 pa_strnull(pa_proplist_gets(sink->proplist, PA_PROP_DEVICE_DESCRIPTION)));
742
743 if ((n = pa_modargs_get_value(ma, "source_output_role", NULL)))
744 pa_proplist_sets(source_output_data.proplist, PA_PROP_MEDIA_ROLE, n);
745 else
746 pa_proplist_sets(source_output_data.proplist, PA_PROP_MEDIA_ROLE, "abstract");
747
748 if ((n = pa_proplist_gets(sink->proplist, PA_PROP_DEVICE_ICON_NAME)))
749 pa_proplist_sets(source_output_data.proplist, PA_PROP_MEDIA_ICON_NAME, n);
750
751 pa_source_output_new_data_set_sample_spec(&source_output_data, &ss);
752 pa_sink_input_new_data_set_channel_map(&sink_input_data, &map);
753
754 pa_source_output_new(&u->source_output, m->core, &source_output_data);
755 pa_source_output_new_data_done(&source_output_data);
756
757 if (!u->source_output)
758 goto fail;
759
760 u->source_output->parent.process_msg = source_output_process_msg_cb;
761 u->source_output->push = source_output_push_cb;
762 u->source_output->process_rewind = source_output_process_rewind_cb;
763 u->source_output->kill = source_output_kill_cb;
764 u->source_output->attach = source_output_attach_cb;
765 u->source_output->detach = source_output_detach_cb;
766 u->source_output->state_change = source_output_state_change_cb;
767 u->source_output->may_move_to = source_output_may_move_to_cb;
768 u->source_output->moving = source_output_moving_cb;
769 u->source_output->userdata = u;
770
771 pa_source_output_set_requested_latency(u->source_output, u->latency/3);
772
773 pa_sink_input_get_silence(u->sink_input, &silence);
774 u->memblockq = pa_memblockq_new(
775 0, /* idx */
776 MEMBLOCKQ_MAXLENGTH, /* maxlength */
777 MEMBLOCKQ_MAXLENGTH, /* tlength */
778 pa_frame_size(&ss), /* base */
779 0, /* prebuf */
780 0, /* minreq */
781 0, /* maxrewind */
782 &silence); /* silence frame */
783 pa_memblock_unref(silence.memblock);
784
785 u->asyncmsgq = pa_asyncmsgq_new(0);
786
787 pa_sink_input_put(u->sink_input);
788 pa_source_output_put(u->source_output);
789
790 if (u->adjust_time > 0)
791 u->time_event = pa_core_rttime_new(m->core, pa_rtclock_now() + u->adjust_time, time_callback, u);
792
793 pa_modargs_free(ma);
794 return 0;
795
796 fail:
797 if (ma)
798 pa_modargs_free(ma);
799
800 pa__done(m);
801
802 return -1;
803 }
804
805 void pa__done(pa_module*m) {
806 struct userdata *u;
807
808 pa_assert(m);
809
810 if (!(u = m->userdata))
811 return;
812
813 teardown(u);
814
815 if (u->memblockq)
816 pa_memblockq_free(u->memblockq);
817
818 if (u->asyncmsgq)
819 pa_asyncmsgq_unref(u->asyncmsgq);
820
821 if (u->time_event)
822 u->core->mainloop->time_free(u->time_event);
823
824 pa_xfree(u);
825 }