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