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