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