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