format: Don't assert on errors in getters
[profile/ivi/pulseaudio-panda.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
365     if (!dest)
366         return;
367
368     pa_source_output_assert_ref(o);
369     pa_assert_ctl_context();
370     pa_assert_se(u = o->userdata);
371
372     p = pa_proplist_new();
373     pa_proplist_setf(p, PA_PROP_MEDIA_NAME, "Loopback of %s", pa_strnull(pa_proplist_gets(dest->proplist, PA_PROP_DEVICE_DESCRIPTION)));
374
375     if ((n = pa_proplist_gets(dest->proplist, PA_PROP_DEVICE_ICON_NAME)))
376         pa_proplist_sets(p, PA_PROP_MEDIA_ICON_NAME, n);
377
378     pa_sink_input_update_proplist(u->sink_input, PA_UPDATE_REPLACE, p);
379     pa_proplist_free(p);
380 }
381
382 /* Called from output thread context */
383 static void update_min_memblockq_length(struct userdata *u) {
384     size_t length;
385
386     pa_assert(u);
387     pa_sink_input_assert_io_context(u->sink_input);
388
389     length = pa_memblockq_get_length(u->memblockq);
390
391     if (u->min_memblockq_length == (size_t) -1 ||
392         length < u->min_memblockq_length)
393         u->min_memblockq_length = length;
394 }
395
396 /* Called from output thread context */
397 static int sink_input_pop_cb(pa_sink_input *i, size_t nbytes, pa_memchunk *chunk) {
398     struct userdata *u;
399
400     pa_sink_input_assert_ref(i);
401     pa_sink_input_assert_io_context(i);
402     pa_assert_se(u = i->userdata);
403     pa_assert(chunk);
404
405     u->in_pop = TRUE;
406     while (pa_asyncmsgq_process_one(u->asyncmsgq) > 0)
407         ;
408     u->in_pop = FALSE;
409
410     if (pa_memblockq_peek(u->memblockq, chunk) < 0) {
411         pa_log_info("Could not peek into queue");
412         return -1;
413     }
414
415     chunk->length = PA_MIN(chunk->length, nbytes);
416     pa_memblockq_drop(u->memblockq, chunk->length);
417
418     update_min_memblockq_length(u);
419
420     return 0;
421 }
422
423 /* Called from output thread context */
424 static void sink_input_process_rewind_cb(pa_sink_input *i, size_t nbytes) {
425     struct userdata *u;
426
427     pa_sink_input_assert_ref(i);
428     pa_sink_input_assert_io_context(i);
429     pa_assert_se(u = i->userdata);
430
431     pa_memblockq_rewind(u->memblockq, nbytes);
432 }
433
434 /* Called from output thread context */
435 static int sink_input_process_msg_cb(pa_msgobject *obj, int code, void *data, int64_t offset, pa_memchunk *chunk) {
436     struct userdata *u = PA_SINK_INPUT(obj)->userdata;
437
438     switch (code) {
439
440         case PA_SINK_INPUT_MESSAGE_GET_LATENCY: {
441             pa_usec_t *r = data;
442
443             pa_sink_input_assert_io_context(u->sink_input);
444
445             *r = pa_bytes_to_usec(pa_memblockq_get_length(u->memblockq), &u->sink_input->sample_spec);
446
447             /* Fall through, the default handler will add in the extra
448              * latency added by the resampler */
449             break;
450         }
451
452         case SINK_INPUT_MESSAGE_POST:
453
454             pa_sink_input_assert_io_context(u->sink_input);
455
456             if (PA_SINK_IS_OPENED(u->sink_input->sink->thread_info.state))
457                 pa_memblockq_push_align(u->memblockq, chunk);
458             else
459                 pa_memblockq_flush_write(u->memblockq, TRUE);
460
461             update_min_memblockq_length(u);
462
463             /* Is this the end of an underrun? Then let's start things
464              * right-away */
465             if (!u->in_pop &&
466                 u->sink_input->thread_info.underrun_for > 0 &&
467                 pa_memblockq_is_readable(u->memblockq)) {
468
469                 pa_log_debug("Requesting rewind due to end of underrun.");
470                 pa_sink_input_request_rewind(u->sink_input,
471                                              (size_t) (u->sink_input->thread_info.underrun_for == (size_t) -1 ? 0 : u->sink_input->thread_info.underrun_for),
472                                              FALSE, TRUE, FALSE);
473             }
474
475             u->recv_counter += (int64_t) chunk->length;
476
477             return 0;
478
479         case SINK_INPUT_MESSAGE_REWIND:
480
481             pa_sink_input_assert_io_context(u->sink_input);
482
483             if (PA_SINK_IS_OPENED(u->sink_input->sink->thread_info.state))
484                 pa_memblockq_seek(u->memblockq, -offset, PA_SEEK_RELATIVE, TRUE);
485             else
486                 pa_memblockq_flush_write(u->memblockq, TRUE);
487
488             u->recv_counter -= offset;
489
490             update_min_memblockq_length(u);
491
492             return 0;
493
494         case SINK_INPUT_MESSAGE_LATENCY_SNAPSHOT: {
495             size_t length;
496
497             update_min_memblockq_length(u);
498
499             length = pa_memblockq_get_length(u->sink_input->thread_info.render_memblockq);
500
501             u->latency_snapshot.recv_counter = u->recv_counter;
502             u->latency_snapshot.sink_input_buffer =
503                 pa_memblockq_get_length(u->memblockq) +
504                 (u->sink_input->thread_info.resampler ? pa_resampler_request(u->sink_input->thread_info.resampler, length) : length);
505             u->latency_snapshot.sink_latency = pa_sink_get_latency_within_thread(u->sink_input->sink);
506
507             u->latency_snapshot.max_request = pa_sink_input_get_max_request(u->sink_input);
508
509             u->latency_snapshot.min_memblockq_length = u->min_memblockq_length;
510             u->min_memblockq_length = (size_t) -1;
511
512             return 0;
513         }
514
515         case SINK_INPUT_MESSAGE_MAX_REQUEST_CHANGED: {
516             /* This message is sent from the IO thread to the main
517              * thread! So don't be confused. All the user cases above
518              * are executed in thread context, but this one is not! */
519
520             pa_assert_ctl_context();
521
522             if (u->adjust_time > 0)
523                 adjust_rates(u);
524             return 0;
525         }
526     }
527
528     return pa_sink_input_process_msg(obj, code, data, offset, chunk);
529 }
530
531 /* Called from output thread context */
532 static void sink_input_attach_cb(pa_sink_input *i) {
533     struct userdata *u;
534
535     pa_sink_input_assert_ref(i);
536     pa_sink_input_assert_io_context(i);
537     pa_assert_se(u = i->userdata);
538
539     u->rtpoll_item_read = pa_rtpoll_item_new_asyncmsgq_read(
540             i->sink->thread_info.rtpoll,
541             PA_RTPOLL_LATE,
542             u->asyncmsgq);
543
544     pa_memblockq_set_prebuf(u->memblockq, pa_sink_input_get_max_request(i)*2);
545     pa_memblockq_set_maxrewind(u->memblockq, pa_sink_input_get_max_rewind(i));
546
547     u->min_memblockq_length = (size_t) -1;
548 }
549
550 /* Called from output thread context */
551 static void sink_input_detach_cb(pa_sink_input *i) {
552     struct userdata *u;
553
554     pa_sink_input_assert_ref(i);
555     pa_sink_input_assert_io_context(i);
556     pa_assert_se(u = i->userdata);
557
558     if (u->rtpoll_item_read) {
559         pa_rtpoll_item_free(u->rtpoll_item_read);
560         u->rtpoll_item_read = NULL;
561     }
562 }
563
564 /* Called from output thread context */
565 static void sink_input_update_max_rewind_cb(pa_sink_input *i, size_t nbytes) {
566     struct userdata *u;
567
568     pa_sink_input_assert_ref(i);
569     pa_sink_input_assert_io_context(i);
570     pa_assert_se(u = i->userdata);
571
572     pa_memblockq_set_maxrewind(u->memblockq, nbytes);
573 }
574
575 /* Called from output thread context */
576 static void sink_input_update_max_request_cb(pa_sink_input *i, size_t nbytes) {
577     struct userdata *u;
578
579     pa_sink_input_assert_ref(i);
580     pa_sink_input_assert_io_context(i);
581     pa_assert_se(u = i->userdata);
582
583     pa_memblockq_set_prebuf(u->memblockq, nbytes*2);
584     pa_log_info("Max request changed");
585     pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(u->sink_input), SINK_INPUT_MESSAGE_MAX_REQUEST_CHANGED, NULL, 0, NULL, NULL);
586 }
587
588 /* Called from main thread */
589 static void sink_input_kill_cb(pa_sink_input *i) {
590     struct userdata *u;
591
592     pa_sink_input_assert_ref(i);
593     pa_assert_ctl_context();
594     pa_assert_se(u = i->userdata);
595
596     teardown(u);
597     pa_module_unload_request(u->module, TRUE);
598 }
599
600 /* Called from main thread */
601 static void sink_input_moving_cb(pa_sink_input *i, pa_sink *dest) {
602     struct userdata *u;
603     pa_proplist *p;
604     const char *n;
605
606     if (!dest)
607         return;
608
609     pa_sink_input_assert_ref(i);
610     pa_assert_ctl_context();
611     pa_assert_se(u = i->userdata);
612
613     p = pa_proplist_new();
614     pa_proplist_setf(p, PA_PROP_MEDIA_NAME, "Loopback to %s", pa_strnull(pa_proplist_gets(dest->proplist, PA_PROP_DEVICE_DESCRIPTION)));
615
616     if ((n = pa_proplist_gets(dest->proplist, PA_PROP_DEVICE_ICON_NAME)))
617         pa_proplist_sets(p, PA_PROP_MEDIA_ICON_NAME, n);
618
619     pa_source_output_update_proplist(u->source_output, PA_UPDATE_REPLACE, p);
620     pa_proplist_free(p);
621 }
622
623 /* Called from main thread */
624 static pa_bool_t sink_input_may_move_to_cb(pa_sink_input *i, pa_sink *dest) {
625     struct userdata *u;
626
627     pa_sink_input_assert_ref(i);
628     pa_assert_ctl_context();
629     pa_assert_se(u = i->userdata);
630
631     if (!u->source_output->source->monitor_of)
632         return TRUE;
633
634     return dest != u->source_output->source->monitor_of;
635 }
636
637 int pa__init(pa_module *m) {
638     pa_modargs *ma = NULL;
639     struct userdata *u;
640     pa_sink *sink;
641     pa_sink_input_new_data sink_input_data;
642     pa_bool_t sink_dont_move;
643     pa_source *source;
644     pa_source_output_new_data source_output_data;
645     pa_bool_t source_dont_move;
646     uint32_t latency_msec;
647     pa_sample_spec ss;
648     pa_channel_map map;
649     pa_memchunk silence;
650     uint32_t adjust_time_sec;
651     const char *n;
652     pa_bool_t remix = TRUE;
653
654     pa_assert(m);
655
656     if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
657         pa_log("Failed to parse module arguments");
658         goto fail;
659     }
660
661     if (!(source = pa_namereg_get(m->core, pa_modargs_get_value(ma, "source", NULL), PA_NAMEREG_SOURCE))) {
662         pa_log("No such source.");
663         goto fail;
664     }
665
666     if (!(sink = pa_namereg_get(m->core, pa_modargs_get_value(ma, "sink", NULL), PA_NAMEREG_SINK))) {
667         pa_log("No such sink.");
668         goto fail;
669     }
670
671     if (pa_modargs_get_value_boolean(ma, "remix", &remix) < 0) {
672         pa_log("Invalid boolean remix parameter");
673         goto fail;
674     }
675
676     ss = sink->sample_spec;
677     map = sink->channel_map;
678     if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map, PA_CHANNEL_MAP_DEFAULT) < 0) {
679         pa_log("Invalid sample format specification or channel map");
680         goto fail;
681     }
682
683     latency_msec = DEFAULT_LATENCY_MSEC;
684     if (pa_modargs_get_value_u32(ma, "latency_msec", &latency_msec) < 0 || latency_msec < 1 || latency_msec > 2000) {
685         pa_log("Invalid latency specification");
686         goto fail;
687     }
688
689     m->userdata = u = pa_xnew0(struct userdata, 1);
690     u->core = m->core;
691     u->module = m;
692     u->latency = (pa_usec_t) latency_msec * PA_USEC_PER_MSEC;
693
694     adjust_time_sec = DEFAULT_ADJUST_TIME_USEC / PA_USEC_PER_SEC;
695     if (pa_modargs_get_value_u32(ma, "adjust_time", &adjust_time_sec) < 0) {
696         pa_log("Failed to parse adjust_time value");
697         goto fail;
698     }
699
700     if (adjust_time_sec != DEFAULT_ADJUST_TIME_USEC / PA_USEC_PER_SEC)
701         u->adjust_time = adjust_time_sec * PA_USEC_PER_SEC;
702     else
703         u->adjust_time = DEFAULT_ADJUST_TIME_USEC;
704
705     pa_sink_input_new_data_init(&sink_input_data);
706     sink_input_data.driver = __FILE__;
707     sink_input_data.module = m;
708     pa_sink_input_new_data_set_sink(&sink_input_data, sink, FALSE);
709
710     if (pa_modargs_get_proplist(ma, "sink_input_properties", sink_input_data.proplist, PA_UPDATE_REPLACE) < 0) {
711         pa_log("Failed to parse the sink_input_properties value.");
712         pa_sink_input_new_data_done(&sink_input_data);
713         goto fail;
714     }
715
716     if (!pa_proplist_contains(sink_input_data.proplist, PA_PROP_MEDIA_NAME))
717         pa_proplist_setf(sink_input_data.proplist, PA_PROP_MEDIA_NAME, "Loopback from %s",
718                          pa_strnull(pa_proplist_gets(source->proplist, PA_PROP_DEVICE_DESCRIPTION)));
719
720     if (!pa_proplist_contains(sink_input_data.proplist, PA_PROP_MEDIA_ROLE))
721         pa_proplist_sets(sink_input_data.proplist, PA_PROP_MEDIA_ROLE, "abstract");
722
723     if (!pa_proplist_contains(sink_input_data.proplist, PA_PROP_MEDIA_ICON_NAME)
724             && (n = pa_proplist_gets(source->proplist, PA_PROP_DEVICE_ICON_NAME)))
725         pa_proplist_sets(sink_input_data.proplist, PA_PROP_MEDIA_ICON_NAME, n);
726
727     pa_sink_input_new_data_set_sample_spec(&sink_input_data, &ss);
728     pa_sink_input_new_data_set_channel_map(&sink_input_data, &map);
729     sink_input_data.flags = PA_SINK_INPUT_VARIABLE_RATE | (remix ? 0 : PA_SINK_INPUT_NO_REMIX);
730
731     sink_dont_move = FALSE;
732     if (pa_modargs_get_value_boolean(ma, "sink_dont_move", &sink_dont_move) < 0) {
733         pa_log("sink_dont_move= expects a boolean argument.");
734         goto fail;
735     }
736
737     if (sink_dont_move)
738         sink_input_data.flags |= PA_SINK_INPUT_DONT_MOVE;
739
740     pa_sink_input_new(&u->sink_input, m->core, &sink_input_data);
741     pa_sink_input_new_data_done(&sink_input_data);
742
743     if (!u->sink_input)
744         goto fail;
745
746     u->sink_input->parent.process_msg = sink_input_process_msg_cb;
747     u->sink_input->pop = sink_input_pop_cb;
748     u->sink_input->process_rewind = sink_input_process_rewind_cb;
749     u->sink_input->kill = sink_input_kill_cb;
750     u->sink_input->attach = sink_input_attach_cb;
751     u->sink_input->detach = sink_input_detach_cb;
752     u->sink_input->update_max_rewind = sink_input_update_max_rewind_cb;
753     u->sink_input->update_max_request = sink_input_update_max_request_cb;
754     u->sink_input->may_move_to = sink_input_may_move_to_cb;
755     u->sink_input->moving = sink_input_moving_cb;
756     u->sink_input->userdata = u;
757
758     pa_sink_input_set_requested_latency(u->sink_input, u->latency/3);
759
760     pa_source_output_new_data_init(&source_output_data);
761     source_output_data.driver = __FILE__;
762     source_output_data.module = m;
763     pa_source_output_new_data_set_source(&source_output_data, source, FALSE);
764
765     if (pa_modargs_get_proplist(ma, "source_output_properties", source_output_data.proplist, PA_UPDATE_REPLACE) < 0) {
766         pa_log("Failed to parse the source_output_properties value.");
767         pa_source_output_new_data_done(&source_output_data);
768         goto fail;
769     }
770
771     if (!pa_proplist_contains(source_output_data.proplist, PA_PROP_MEDIA_NAME))
772         pa_proplist_setf(source_output_data.proplist, PA_PROP_MEDIA_NAME, "Loopback to %s",
773                          pa_strnull(pa_proplist_gets(sink->proplist, PA_PROP_DEVICE_DESCRIPTION)));
774
775     if (!pa_proplist_contains(source_output_data.proplist, PA_PROP_MEDIA_ROLE))
776         pa_proplist_sets(source_output_data.proplist, PA_PROP_MEDIA_ROLE, "abstract");
777
778     if (!pa_proplist_contains(source_output_data.proplist, PA_PROP_MEDIA_ICON_NAME)
779             && (n = pa_proplist_gets(sink->proplist, PA_PROP_DEVICE_ICON_NAME)))
780         pa_proplist_sets(source_output_data.proplist, PA_PROP_MEDIA_ICON_NAME, n);
781
782     pa_source_output_new_data_set_sample_spec(&source_output_data, &ss);
783     pa_source_output_new_data_set_channel_map(&source_output_data, &map);
784     source_output_data.flags = (remix ? 0 : PA_SOURCE_OUTPUT_NO_REMIX);
785
786     source_dont_move = FALSE;
787     if (pa_modargs_get_value_boolean(ma, "source_dont_move", &source_dont_move) < 0) {
788         pa_log("source_dont_move= expects a boolean argument.");
789         goto fail;
790     }
791
792     if (source_dont_move)
793         source_output_data.flags |= PA_SOURCE_OUTPUT_DONT_MOVE;
794
795     pa_source_output_new(&u->source_output, m->core, &source_output_data);
796     pa_source_output_new_data_done(&source_output_data);
797
798     if (!u->source_output)
799         goto fail;
800
801     u->source_output->parent.process_msg = source_output_process_msg_cb;
802     u->source_output->push = source_output_push_cb;
803     u->source_output->process_rewind = source_output_process_rewind_cb;
804     u->source_output->kill = source_output_kill_cb;
805     u->source_output->attach = source_output_attach_cb;
806     u->source_output->detach = source_output_detach_cb;
807     u->source_output->state_change = source_output_state_change_cb;
808     u->source_output->may_move_to = source_output_may_move_to_cb;
809     u->source_output->moving = source_output_moving_cb;
810     u->source_output->userdata = u;
811
812     pa_source_output_set_requested_latency(u->source_output, u->latency/3);
813
814     pa_sink_input_get_silence(u->sink_input, &silence);
815     u->memblockq = pa_memblockq_new(
816             "module-loopback memblockq",
817             0,                      /* idx */
818             MEMBLOCKQ_MAXLENGTH,    /* maxlength */
819             MEMBLOCKQ_MAXLENGTH,    /* tlength */
820             &ss,                    /* sample_spec */
821             0,                      /* prebuf */
822             0,                      /* minreq */
823             0,                      /* maxrewind */
824             &silence);              /* silence frame */
825     pa_memblock_unref(silence.memblock);
826
827     u->asyncmsgq = pa_asyncmsgq_new(0);
828
829     pa_sink_input_put(u->sink_input);
830     pa_source_output_put(u->source_output);
831
832     if (u->adjust_time > 0)
833         u->time_event = pa_core_rttime_new(m->core, pa_rtclock_now() + u->adjust_time, time_callback, u);
834
835     pa_modargs_free(ma);
836     return 0;
837
838 fail:
839     if (ma)
840         pa_modargs_free(ma);
841
842     pa__done(m);
843
844     return -1;
845 }
846
847 void pa__done(pa_module*m) {
848     struct userdata *u;
849
850     pa_assert(m);
851
852     if (!(u = m->userdata))
853         return;
854
855     teardown(u);
856
857     if (u->memblockq)
858         pa_memblockq_free(u->memblockq);
859
860     if (u->asyncmsgq)
861         pa_asyncmsgq_unref(u->asyncmsgq);
862
863     if (u->time_event)
864         u->core->mainloop->time_free(u->time_event);
865
866     pa_xfree(u);
867 }