bluetooth: Support port availability flag
[profile/ivi/pulseaudio.git] / src / modules / module-virtual-source.c
1 /***
2     This file is part of PulseAudio.
3
4     Copyright 2010 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/i18n.h>
32 #include <pulsecore/macro.h>
33 #include <pulsecore/namereg.h>
34 #include <pulsecore/sink.h>
35 #include <pulsecore/module.h>
36 #include <pulsecore/core-util.h>
37 #include <pulsecore/modargs.h>
38 #include <pulsecore/log.h>
39 #include <pulsecore/rtpoll.h>
40 #include <pulsecore/sample-util.h>
41 #include <pulsecore/ltdl-helper.h>
42
43 #include "module-virtual-source-symdef.h"
44
45 PA_MODULE_AUTHOR("Pierre-Louis Bossart");
46 PA_MODULE_DESCRIPTION("Virtual source");
47 PA_MODULE_VERSION(PACKAGE_VERSION);
48 PA_MODULE_LOAD_ONCE(FALSE);
49 PA_MODULE_USAGE(
50         _("source_name=<name for the source> "
51           "source_properties=<properties for the source> "
52           "master=<name of source to filter> "
53           "uplink_sink=<name> (optional)"
54           "format=<sample format> "
55           "rate=<sample rate> "
56           "channels=<number of channels> "
57           "channel_map=<channel map> "
58           "use_volume_sharing=<yes or no> "
59           "force_flat_volume=<yes or no> "
60         ));
61
62 #define MEMBLOCKQ_MAXLENGTH (16*1024*1024)
63 #define BLOCK_USEC 1000 /* FIXME */
64
65 struct userdata {
66     pa_module *module;
67
68     /* FIXME: Uncomment this and take "autoloaded" as a modarg if this is a filter */
69     /* pa_bool_t autoloaded; */
70
71     pa_source *source;
72     pa_source_output *source_output;
73
74     pa_memblockq *memblockq;
75
76     pa_bool_t auto_desc;
77     unsigned channels;
78
79     /* optional fields for uplink sink */
80     pa_sink *sink;
81     pa_usec_t block_usec;
82     pa_memblockq *sink_memblockq;
83
84 };
85
86 static const char* const valid_modargs[] = {
87     "source_name",
88     "source_properties",
89     "master",
90     "uplink_sink",
91     "format",
92     "rate",
93     "channels",
94     "channel_map",
95     "use_volume_sharing",
96     "force_flat_volume",
97     NULL
98 };
99
100 /* Called from I/O thread context */
101 static int sink_process_msg_cb(pa_msgobject *o, int code, void *data, int64_t offset, pa_memchunk *chunk) {
102
103     switch (code) {
104
105         case PA_SINK_MESSAGE_GET_LATENCY:
106
107             /* there's no real latency here */
108             *((pa_usec_t*) data) = 0;
109
110             return 0;
111     }
112
113     return pa_sink_process_msg(o, code, data, offset, chunk);
114 }
115
116 /* Called from main context */
117 static int sink_set_state_cb(pa_sink *s, pa_sink_state_t state) {
118     struct userdata *u;
119
120     pa_sink_assert_ref(s);
121     pa_assert_se(u = s->userdata);
122
123     if (!PA_SINK_IS_LINKED(state)) {
124         return 0;
125     }
126
127     if (state == PA_SINK_RUNNING) {
128         /* need to wake-up source if it was suspended */
129         pa_source_suspend(u->source, FALSE, PA_SUSPEND_ALL);
130
131         /* FIXME: if there's no client connected, the source will suspend
132            and playback will be stuck. You'd want to prevent the source from
133            sleeping when the uplink sink is active; even if the audio is
134            discarded at least the app isn't stuck */
135
136     } else {
137         /* nothing to do, if the sink becomes idle or suspended let
138            module-suspend-idle handle the sources later */
139     }
140
141     return 0;
142 }
143
144 static void sink_update_requested_latency_cb(pa_sink *s) {
145     struct userdata *u;
146
147     pa_sink_assert_ref(s);
148     pa_assert_se(u = s->userdata);
149
150     /* FIXME: there's no latency support */
151
152 }
153
154
155 /* Called from I/O thread context */
156 static void sink_request_rewind_cb(pa_sink *s) {
157     struct userdata *u;
158
159     pa_sink_assert_ref(s);
160     pa_assert_se(u = s->userdata);
161
162     /* Do nothing */
163     pa_sink_process_rewind(u->sink, 0);
164
165 }
166
167 /* Called from I/O thread context */
168 static int source_process_msg_cb(pa_msgobject *o, int code, void *data, int64_t offset, pa_memchunk *chunk) {
169     struct userdata *u = PA_SOURCE(o)->userdata;
170
171     switch (code) {
172
173         case PA_SOURCE_MESSAGE_GET_LATENCY:
174
175             /* The source is _put() before the source output is, so let's
176              * make sure we don't access it in that time. Also, the
177              * source output is first shut down, the source second. */
178             if (!PA_SOURCE_IS_LINKED(u->source->thread_info.state) ||
179                 !PA_SOURCE_OUTPUT_IS_LINKED(u->source_output->thread_info.state)) {
180                 *((pa_usec_t*) data) = 0;
181                 return 0;
182             }
183
184             *((pa_usec_t*) data) =
185
186                 /* Get the latency of the master source */
187                 pa_source_get_latency_within_thread(u->source_output->source) +
188
189                 /* Add the latency internal to our source output on top */
190                 /* FIXME, no idea what I am doing here */
191                 pa_bytes_to_usec(pa_memblockq_get_length(u->source_output->thread_info.delay_memblockq), &u->source_output->source->sample_spec);
192
193             return 0;
194     }
195
196     return pa_source_process_msg(o, code, data, offset, chunk);
197 }
198
199 /* Called from main context */
200 static int source_set_state_cb(pa_source *s, pa_source_state_t state) {
201     struct userdata *u;
202
203     pa_source_assert_ref(s);
204     pa_assert_se(u = s->userdata);
205
206     if (!PA_SOURCE_IS_LINKED(state) ||
207         !PA_SOURCE_OUTPUT_IS_LINKED(pa_source_output_get_state(u->source_output)))
208         return 0;
209
210     pa_source_output_cork(u->source_output, state == PA_SOURCE_SUSPENDED);
211     return 0;
212 }
213
214 /* Called from I/O thread context */
215 static void source_update_requested_latency_cb(pa_source *s) {
216     struct userdata *u;
217
218     pa_source_assert_ref(s);
219     pa_assert_se(u = s->userdata);
220
221     if (!PA_SOURCE_IS_LINKED(u->source->thread_info.state) ||
222         !PA_SOURCE_OUTPUT_IS_LINKED(u->source_output->thread_info.state))
223         return;
224
225     /* Just hand this one over to the master source */
226     pa_source_output_set_requested_latency_within_thread(
227             u->source_output,
228             pa_source_get_requested_latency_within_thread(s));
229 }
230
231 /* Called from main context */
232 static void source_set_volume_cb(pa_source *s) {
233     struct userdata *u;
234
235     pa_source_assert_ref(s);
236     pa_assert_se(u = s->userdata);
237
238     if (!PA_SOURCE_IS_LINKED(pa_source_get_state(s)) ||
239         !PA_SOURCE_OUTPUT_IS_LINKED(pa_source_output_get_state(u->source_output)))
240         return;
241
242     pa_source_output_set_volume(u->source_output, &s->real_volume, s->save_volume, TRUE);
243 }
244
245 /* Called from main context */
246 static void source_set_mute_cb(pa_source *s) {
247     struct userdata *u;
248
249     pa_source_assert_ref(s);
250     pa_assert_se(u = s->userdata);
251
252     if (!PA_SOURCE_IS_LINKED(pa_source_get_state(s)) ||
253         !PA_SOURCE_OUTPUT_IS_LINKED(pa_source_output_get_state(u->source_output)))
254         return;
255
256     pa_source_output_set_mute(u->source_output, s->muted, s->save_muted);
257 }
258
259 /* Called from input thread context */
260 static void source_output_push_cb(pa_source_output *o, const pa_memchunk *chunk) {
261     struct userdata *u;
262
263     pa_source_output_assert_ref(o);
264     pa_source_output_assert_io_context(o);
265     pa_assert_se(u = o->userdata);
266
267     if (!PA_SOURCE_OUTPUT_IS_LINKED(pa_source_output_get_state(u->source_output))) {
268         pa_log("push when no link?");
269         return;
270     }
271
272     /* PUT YOUR CODE HERE TO DO SOMETHING WITH THE SOURCE DATA */
273
274     /* if uplink sink exists, pull data from there; simplify by using
275        same length as chunk provided by source */
276     if(u->sink && (pa_sink_get_state(u->sink) == PA_SINK_RUNNING)) {
277         pa_memchunk tchunk;
278         size_t nbytes = chunk->length;
279         pa_mix_info streams[2];
280         pa_memchunk target_chunk;
281         void *target;
282         int ch;
283
284         /* Hmm, process any rewind request that might be queued up */
285         pa_sink_process_rewind(u->sink, 0);
286
287         /* get data from the sink */
288         while (pa_memblockq_peek(u->sink_memblockq, &tchunk) < 0) {
289             pa_memchunk nchunk;
290
291             /* make sure we get nbytes from the sink with render_full,
292                otherwise we cannot mix with the uplink */
293             pa_sink_render_full(u->sink, nbytes, &nchunk);
294             pa_memblockq_push(u->sink_memblockq, &nchunk);
295             pa_memblock_unref(nchunk.memblock);
296         }
297         pa_assert(tchunk.length == chunk->length);
298
299         /* move the read pointer for sink memblockq */
300         pa_memblockq_drop(u->sink_memblockq, tchunk.length);
301
302         /* allocate target chunk */
303         /* this could probably be done in-place, but having chunk as both
304            the input and output creates issues with reference counts */
305         target_chunk.index = 0;
306         target_chunk.length = chunk->length;
307         pa_assert(target_chunk.length == chunk->length);
308
309         target_chunk.memblock = pa_memblock_new(o->source->core->mempool,
310                                                 target_chunk.length);
311         pa_assert( target_chunk.memblock );
312
313         /* get target pointer */
314         target = (void*)((uint8_t*)pa_memblock_acquire(target_chunk.memblock)
315                          + target_chunk.index);
316
317         /* set-up mixing structure
318            volume was taken care of in sink and source already */
319         streams[0].chunk = *chunk;
320         for(ch=0;ch<o->sample_spec.channels;ch++)
321             streams[0].volume.values[ch] = PA_VOLUME_NORM; /* FIXME */
322         streams[0].volume.channels = o->sample_spec.channels;
323
324         streams[1].chunk = tchunk;
325         for(ch=0;ch<o->sample_spec.channels;ch++)
326             streams[1].volume.values[ch] = PA_VOLUME_NORM; /* FIXME */
327         streams[1].volume.channels = o->sample_spec.channels;
328
329         /* do mixing */
330         pa_mix(streams,                /* 2 streams to be mixed */
331                2,
332                target,                 /* put result in target chunk */
333                chunk->length,          /* same length as input */
334                (const pa_sample_spec *)&o->sample_spec, /* same sample spec for input and output */
335                NULL,                   /* no volume information */
336                FALSE);                 /* no mute */
337
338         pa_memblock_release(target_chunk.memblock);
339         pa_memblock_unref(tchunk.memblock); /* clean-up */
340
341         /* forward the data to the virtual source */
342         pa_source_post(u->source, &target_chunk);
343
344         pa_memblock_unref(target_chunk.memblock); /* clean-up */
345
346     } else {
347         /* forward the data to the virtual source */
348         pa_source_post(u->source, chunk);
349     }
350
351
352 }
353
354 /* Called from input thread context */
355 static void source_output_process_rewind_cb(pa_source_output *o, size_t nbytes) {
356     struct userdata *u;
357
358     pa_source_output_assert_ref(o);
359     pa_source_output_assert_io_context(o);
360     pa_assert_se(u = o->userdata);
361
362     /* FIXME, no idea what I am doing here */
363 #if 0
364     pa_asyncmsgq_post(u->asyncmsgq, PA_MSGOBJECT(u->sink_input), SINK_INPUT_MESSAGE_REWIND, NULL, (int64_t) nbytes, NULL, NULL);
365     u->send_counter -= (int64_t) nbytes;
366 #endif
367 }
368
369 /* Called from output thread context */
370 static int source_output_process_msg_cb(pa_msgobject *obj, int code, void *data, int64_t offset, pa_memchunk *chunk) {
371
372     /* FIXME, nothing to do here ? */
373
374     return pa_source_output_process_msg(obj, code, data, offset, chunk);
375 }
376
377 /* Called from output thread context */
378 static void source_output_attach_cb(pa_source_output *o) {
379     struct userdata *u;
380
381     pa_source_output_assert_ref(o);
382     pa_source_output_assert_io_context(o);
383     pa_assert_se(u = o->userdata);
384
385     pa_source_set_rtpoll(u->source, o->source->thread_info.rtpoll);
386     pa_source_set_latency_range_within_thread(u->source, o->source->thread_info.min_latency, o->source->thread_info.max_latency);
387     pa_source_set_fixed_latency_within_thread(u->source, o->source->thread_info.fixed_latency);
388     pa_source_set_max_rewind_within_thread(u->source, pa_source_output_get_max_rewind(o));
389
390     pa_source_attach_within_thread(u->source);
391 }
392
393 /* Called from output thread context */
394 static void source_output_detach_cb(pa_source_output *o) {
395     struct userdata *u;
396
397     pa_source_output_assert_ref(o);
398     pa_source_output_assert_io_context(o);
399     pa_assert_se(u = o->userdata);
400
401     pa_source_detach_within_thread(u->source);
402     pa_source_set_rtpoll(u->source, NULL);
403 }
404
405 /* Called from output thread context */
406 static void source_output_state_change_cb(pa_source_output *o, pa_source_output_state_t state) {
407     struct userdata *u;
408
409     pa_source_output_assert_ref(o);
410     pa_source_output_assert_io_context(o);
411     pa_assert_se(u = o->userdata);
412
413     /* FIXME */
414 #if 0
415     if (PA_SOURCE_OUTPUT_IS_LINKED(state) && o->thread_info.state == PA_SOURCE_OUTPUT_INIT) {
416
417         u->skip = pa_usec_to_bytes(PA_CLIP_SUB(pa_source_get_latency_within_thread(o->source),
418                                                u->latency),
419                                    &o->sample_spec);
420
421         pa_log_info("Skipping %lu bytes", (unsigned long) u->skip);
422     }
423 #endif
424 }
425
426 /* Called from main thread */
427 static void source_output_kill_cb(pa_source_output *o) {
428     struct userdata *u;
429
430     pa_source_output_assert_ref(o);
431     pa_assert_ctl_context();
432     pa_assert_se(u = o->userdata);
433
434     /* The order here matters! We first kill the source output, followed
435      * by the source. That means the source callbacks must be protected
436      * against an unconnected source output! */
437     pa_source_output_unlink(u->source_output);
438     pa_source_unlink(u->source);
439
440     pa_source_output_unref(u->source_output);
441     u->source_output = NULL;
442
443     pa_source_unref(u->source);
444     u->source = NULL;
445
446     pa_module_unload_request(u->module, TRUE);
447 }
448
449 /* Called from main thread */
450 static pa_bool_t source_output_may_move_to_cb(pa_source_output *o, pa_source *dest) {
451     struct userdata *u;
452
453     pa_source_output_assert_ref(o);
454     pa_assert_ctl_context();
455     pa_assert_se(u = o->userdata);
456
457     /* FIXME */
458     //return dest != u->source_input->source->monitor_source;
459
460     return TRUE;
461 }
462
463 /* Called from main thread */
464 static void source_output_moving_cb(pa_source_output *o, pa_source *dest) {
465     struct userdata *u;
466
467     pa_source_output_assert_ref(o);
468     pa_assert_ctl_context();
469     pa_assert_se(u = o->userdata);
470
471     if (dest) {
472         pa_source_set_asyncmsgq(u->source, dest->asyncmsgq);
473         pa_source_update_flags(u->source, PA_SOURCE_LATENCY|PA_SOURCE_DYNAMIC_LATENCY, dest->flags);
474     } else
475         pa_source_set_asyncmsgq(u->source, NULL);
476
477     if (u->auto_desc && dest) {
478         const char *z;
479         pa_proplist *pl;
480
481         pl = pa_proplist_new();
482         z = pa_proplist_gets(dest->proplist, PA_PROP_DEVICE_DESCRIPTION);
483         pa_proplist_setf(pl, PA_PROP_DEVICE_DESCRIPTION, "Virtual Source %s on %s",
484                          pa_proplist_gets(u->source->proplist, "device.vsource.name"), z ? z : dest->name);
485
486         pa_source_update_proplist(u->source, PA_UPDATE_REPLACE, pl);
487         pa_proplist_free(pl);
488     }
489 }
490
491
492 int pa__init(pa_module*m) {
493     struct userdata *u;
494     pa_sample_spec ss;
495     pa_channel_map map;
496     pa_modargs *ma;
497     pa_source *master=NULL;
498     pa_source_output_new_data source_output_data;
499     pa_source_new_data source_data;
500     pa_bool_t use_volume_sharing = TRUE;
501     pa_bool_t force_flat_volume = FALSE;
502
503     /* optional for uplink_sink */
504     pa_sink_new_data sink_data;
505     size_t nbytes;
506
507     pa_assert(m);
508
509     if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
510         pa_log("Failed to parse module arguments.");
511         goto fail;
512     }
513
514     if (!(master = pa_namereg_get(m->core, pa_modargs_get_value(ma, "master", NULL), PA_NAMEREG_SOURCE))) {
515         pa_log("Master source not found");
516         goto fail;
517     }
518
519     pa_assert(master);
520
521     ss = master->sample_spec;
522     ss.format = PA_SAMPLE_FLOAT32;
523     map = master->channel_map;
524     if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map, PA_CHANNEL_MAP_DEFAULT) < 0) {
525         pa_log("Invalid sample format specification or channel map");
526         goto fail;
527     }
528
529     if (pa_modargs_get_value_boolean(ma, "use_volume_sharing", &use_volume_sharing) < 0) {
530         pa_log("use_volume_sharing= expects a boolean argument");
531         goto fail;
532     }
533
534     if (pa_modargs_get_value_boolean(ma, "force_flat_volume", &force_flat_volume) < 0) {
535         pa_log("force_flat_volume= expects a boolean argument");
536         goto fail;
537     }
538
539     if (use_volume_sharing && force_flat_volume) {
540         pa_log("Flat volume can't be forced when using volume sharing.");
541         goto fail;
542     }
543
544     u = pa_xnew0(struct userdata, 1);
545     if (!u) {
546         pa_log("Failed to alloc userdata");
547         goto fail;
548     }
549     u->module = m;
550     m->userdata = u;
551     u->memblockq = pa_memblockq_new("module-virtual-source memblockq", 0, MEMBLOCKQ_MAXLENGTH, 0, &ss, 1, 1, 0, NULL);
552     if (!u->memblockq) {
553         pa_log("Failed to create source memblockq.");
554         goto fail;
555     }
556     u->channels = ss.channels;
557
558     /* Create source */
559     pa_source_new_data_init(&source_data);
560     source_data.driver = __FILE__;
561     source_data.module = m;
562     if (!(source_data.name = pa_xstrdup(pa_modargs_get_value(ma, "source_name", NULL))))
563         source_data.name = pa_sprintf_malloc("%s.vsource", master->name);
564     pa_source_new_data_set_sample_spec(&source_data, &ss);
565     pa_source_new_data_set_channel_map(&source_data, &map);
566     pa_proplist_sets(source_data.proplist, PA_PROP_DEVICE_MASTER_DEVICE, master->name);
567     pa_proplist_sets(source_data.proplist, PA_PROP_DEVICE_CLASS, "filter");
568     pa_proplist_sets(source_data.proplist, "device.vsource.name", source_data.name);
569
570     if (pa_modargs_get_proplist(ma, "source_properties", source_data.proplist, PA_UPDATE_REPLACE) < 0) {
571         pa_log("Invalid properties");
572         pa_source_new_data_done(&source_data);
573         goto fail;
574     }
575
576     if ((u->auto_desc = !pa_proplist_contains(source_data.proplist, PA_PROP_DEVICE_DESCRIPTION))) {
577         const char *z;
578
579         z = pa_proplist_gets(master->proplist, PA_PROP_DEVICE_DESCRIPTION);
580         pa_proplist_setf(source_data.proplist, PA_PROP_DEVICE_DESCRIPTION, "Virtual Source %s on %s", source_data.name, z ? z : master->name);
581     }
582
583     u->source = pa_source_new(m->core, &source_data, (master->flags & (PA_SOURCE_LATENCY|PA_SOURCE_DYNAMIC_LATENCY))
584                                                      | (use_volume_sharing ? PA_SOURCE_SHARE_VOLUME_WITH_MASTER : 0));
585
586     pa_source_new_data_done(&source_data);
587
588     if (!u->source) {
589         pa_log("Failed to create source.");
590         goto fail;
591     }
592
593     u->source->parent.process_msg = source_process_msg_cb;
594     u->source->set_state = source_set_state_cb;
595     u->source->update_requested_latency = source_update_requested_latency_cb;
596     pa_source_set_set_mute_callback(u->source, source_set_mute_cb);
597     if (!use_volume_sharing) {
598         pa_source_set_set_volume_callback(u->source, source_set_volume_cb);
599         pa_source_enable_decibel_volume(u->source, TRUE);
600     }
601     /* Normally this flag would be enabled automatically be we can force it. */
602     if (force_flat_volume)
603         u->source->flags |= PA_SOURCE_FLAT_VOLUME;
604     u->source->userdata = u;
605
606     pa_source_set_asyncmsgq(u->source, master->asyncmsgq);
607
608     /* Create source output */
609     pa_source_output_new_data_init(&source_output_data);
610     source_output_data.driver = __FILE__;
611     source_output_data.module = m;
612     pa_source_output_new_data_set_source(&source_output_data, master, FALSE);
613     source_output_data.destination_source = u->source;
614     /* FIXME
615        source_output_data.flags = PA_SOURCE_OUTPUT_DONT_INHIBIT_AUTO_SUSPEND; */
616
617     pa_proplist_setf(source_output_data.proplist, PA_PROP_MEDIA_NAME, "Virtual Source Stream of %s", pa_proplist_gets(u->source->proplist, PA_PROP_DEVICE_DESCRIPTION));
618     pa_proplist_sets(source_output_data.proplist, PA_PROP_MEDIA_ROLE, "filter");
619     pa_source_output_new_data_set_sample_spec(&source_output_data, &ss);
620     pa_source_output_new_data_set_channel_map(&source_output_data, &map);
621
622     pa_source_output_new(&u->source_output, m->core, &source_output_data);
623     pa_source_output_new_data_done(&source_output_data);
624
625     if (!u->source_output)
626         goto fail;
627
628     u->source_output->parent.process_msg = source_output_process_msg_cb;
629     u->source_output->push = source_output_push_cb;
630     u->source_output->process_rewind = source_output_process_rewind_cb;
631     u->source_output->kill = source_output_kill_cb;
632     u->source_output->attach = source_output_attach_cb;
633     u->source_output->detach = source_output_detach_cb;
634     u->source_output->state_change = source_output_state_change_cb;
635     u->source_output->may_move_to = source_output_may_move_to_cb;
636     u->source_output->moving = source_output_moving_cb;
637     u->source_output->userdata = u;
638
639     u->source->output_from_master = u->source_output;
640
641     pa_source_put(u->source);
642     pa_source_output_put(u->source_output);
643
644     /* Create optional uplink sink */
645     pa_sink_new_data_init(&sink_data);
646     sink_data.driver = __FILE__;
647     sink_data.module = m;
648     if ((sink_data.name = pa_xstrdup(pa_modargs_get_value(ma, "uplink_sink", NULL)))) {
649         pa_sink_new_data_set_sample_spec(&sink_data, &ss);
650         pa_sink_new_data_set_channel_map(&sink_data, &map);
651         pa_proplist_sets(sink_data.proplist, PA_PROP_DEVICE_MASTER_DEVICE, master->name);
652         pa_proplist_sets(sink_data.proplist, PA_PROP_DEVICE_CLASS, "uplink sink");
653         pa_proplist_sets(sink_data.proplist, "device.uplink_sink.name", sink_data.name);
654
655         if ((u->auto_desc = !pa_proplist_contains(sink_data.proplist, PA_PROP_DEVICE_DESCRIPTION))) {
656             const char *z;
657
658             z = pa_proplist_gets(master->proplist, PA_PROP_DEVICE_DESCRIPTION);
659             pa_proplist_setf(sink_data.proplist, PA_PROP_DEVICE_DESCRIPTION, "Uplink Sink %s on %s", sink_data.name, z ? z : master->name);
660         }
661
662         u->sink_memblockq = pa_memblockq_new("module-virtual-source sink_memblockq", 0, MEMBLOCKQ_MAXLENGTH, 0, &ss, 1, 1, 0, NULL);
663         if (!u->sink_memblockq) {
664             pa_sink_new_data_done(&sink_data);
665             pa_log("Failed to create sink memblockq.");
666             goto fail;
667         }
668
669         u->sink = pa_sink_new(m->core, &sink_data, 0);  /* FIXME, sink has no capabilities */
670         pa_sink_new_data_done(&sink_data);
671
672         if (!u->sink) {
673             pa_log("Failed to create sink.");
674             goto fail;
675         }
676
677         u->sink->parent.process_msg = sink_process_msg_cb;
678         u->sink->update_requested_latency = sink_update_requested_latency_cb;
679         u->sink->request_rewind = sink_request_rewind_cb;
680         u->sink->set_state = sink_set_state_cb;
681         u->sink->userdata = u;
682
683         pa_sink_set_asyncmsgq(u->sink, master->asyncmsgq);
684
685         /* FIXME: no idea what I am doing here */
686         u->block_usec = BLOCK_USEC;
687         nbytes = pa_usec_to_bytes(u->block_usec, &u->sink->sample_spec);
688         pa_sink_set_max_rewind(u->sink, nbytes);
689         pa_sink_set_max_request(u->sink, nbytes);
690
691         pa_sink_put(u->sink);
692     } else {
693         pa_sink_new_data_done(&sink_data);
694         /* optional uplink sink not enabled */
695         u->sink = NULL;
696     }
697
698     pa_modargs_free(ma);
699
700     return 0;
701
702 fail:
703     if (ma)
704         pa_modargs_free(ma);
705
706     pa__done(m);
707
708     return -1;
709 }
710
711 int pa__get_n_used(pa_module *m) {
712     struct userdata *u;
713
714     pa_assert(m);
715     pa_assert_se(u = m->userdata);
716
717     return pa_source_linked_by(u->source);
718 }
719
720 void pa__done(pa_module*m) {
721     struct userdata *u;
722
723     pa_assert(m);
724
725     if (!(u = m->userdata))
726         return;
727
728     /* See comments in source_output_kill_cb() above regarding
729      * destruction order! */
730
731     if (u->source_output)
732         pa_source_output_unlink(u->source_output);
733
734     if (u->source)
735         pa_source_unlink(u->source);
736
737     if (u->source_output)
738         pa_source_output_unref(u->source_output);
739
740     if (u->source)
741         pa_source_unref(u->source);
742
743     if (u->sink)
744         pa_sink_unref(u->sink);
745
746     if (u->memblockq)
747         pa_memblockq_free(u->memblockq);
748
749     if (u->sink_memblockq)
750         pa_memblockq_free(u->sink_memblockq);
751
752     pa_xfree(u);
753 }