]> code.delx.au - pulseaudio/blob - src/modules/module-virtual-sink.c
Add comments referring to bug #53709.
[pulseaudio] / src / modules / module-virtual-sink.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 <pulse/gccmacro.h>
28 #include <pulse/xmalloc.h>
29
30 #include <pulsecore/i18n.h>
31 #include <pulsecore/namereg.h>
32 #include <pulsecore/sink.h>
33 #include <pulsecore/module.h>
34 #include <pulsecore/core-util.h>
35 #include <pulsecore/modargs.h>
36 #include <pulsecore/log.h>
37 #include <pulsecore/rtpoll.h>
38 #include <pulsecore/sample-util.h>
39 #include <pulsecore/ltdl-helper.h>
40
41 #include "module-virtual-sink-symdef.h"
42
43 PA_MODULE_AUTHOR("Pierre-Louis Bossart");
44 PA_MODULE_DESCRIPTION(_("Virtual sink"));
45 PA_MODULE_VERSION(PACKAGE_VERSION);
46 PA_MODULE_LOAD_ONCE(FALSE);
47 PA_MODULE_USAGE(
48 _("sink_name=<name for the sink> "
49 "sink_properties=<properties for the sink> "
50 "master=<name of sink to filter> "
51 "format=<sample format> "
52 "rate=<sample rate> "
53 "channels=<number of channels> "
54 "channel_map=<channel map> "
55 "use_volume_sharing=<yes or no> "
56 "force_flat_volume=<yes or no> "
57 ));
58
59 #define MEMBLOCKQ_MAXLENGTH (16*1024*1024)
60
61 struct userdata {
62 pa_module *module;
63
64 /* FIXME: Uncomment this and take "autoloaded" as a modarg if this is a filter */
65 /* pa_bool_t autoloaded; */
66
67 pa_sink *sink;
68 pa_sink_input *sink_input;
69
70 pa_memblockq *memblockq;
71
72 pa_bool_t auto_desc;
73 unsigned channels;
74 };
75
76 static const char* const valid_modargs[] = {
77 "sink_name",
78 "sink_properties",
79 "master",
80 "format",
81 "rate",
82 "channels",
83 "channel_map",
84 "use_volume_sharing",
85 "force_flat_volume",
86 NULL
87 };
88
89 /* Called from I/O thread context */
90 static int sink_process_msg_cb(pa_msgobject *o, int code, void *data, int64_t offset, pa_memchunk *chunk) {
91 struct userdata *u = PA_SINK(o)->userdata;
92
93 switch (code) {
94
95 case PA_SINK_MESSAGE_GET_LATENCY:
96
97 /* The sink is _put() before the sink input is, so let's
98 * make sure we don't access it in that time. Also, the
99 * sink input is first shut down, the sink second. */
100 if (!PA_SINK_IS_LINKED(u->sink->thread_info.state) ||
101 !PA_SINK_INPUT_IS_LINKED(u->sink_input->thread_info.state)) {
102 *((pa_usec_t*) data) = 0;
103 return 0;
104 }
105
106 *((pa_usec_t*) data) =
107
108 /* Get the latency of the master sink */
109 pa_sink_get_latency_within_thread(u->sink_input->sink) +
110
111 /* Add the latency internal to our sink input on top */
112 pa_bytes_to_usec(pa_memblockq_get_length(u->sink_input->thread_info.render_memblockq), &u->sink_input->sink->sample_spec);
113
114 return 0;
115 }
116
117 return pa_sink_process_msg(o, code, data, offset, chunk);
118 }
119
120 /* Called from main context */
121 static int sink_set_state_cb(pa_sink *s, pa_sink_state_t state) {
122 struct userdata *u;
123
124 pa_sink_assert_ref(s);
125 pa_assert_se(u = s->userdata);
126
127 if (!PA_SINK_IS_LINKED(state) ||
128 !PA_SINK_INPUT_IS_LINKED(pa_sink_input_get_state(u->sink_input)))
129 return 0;
130
131 pa_sink_input_cork(u->sink_input, state == PA_SINK_SUSPENDED);
132 return 0;
133 }
134
135 /* Called from I/O thread context */
136 static void sink_request_rewind_cb(pa_sink *s) {
137 struct userdata *u;
138
139 pa_sink_assert_ref(s);
140 pa_assert_se(u = s->userdata);
141
142 if (!PA_SINK_IS_LINKED(u->sink->thread_info.state) ||
143 !PA_SINK_INPUT_IS_LINKED(u->sink_input->thread_info.state))
144 return;
145
146 /* Just hand this one over to the master sink */
147 pa_sink_input_request_rewind(u->sink_input,
148 s->thread_info.rewind_nbytes +
149 pa_memblockq_get_length(u->memblockq), TRUE, FALSE, FALSE);
150 }
151
152 /* Called from I/O thread context */
153 static void sink_update_requested_latency_cb(pa_sink *s) {
154 struct userdata *u;
155
156 pa_sink_assert_ref(s);
157 pa_assert_se(u = s->userdata);
158
159 if (!PA_SINK_IS_LINKED(u->sink->thread_info.state) ||
160 !PA_SINK_INPUT_IS_LINKED(u->sink_input->thread_info.state))
161 return;
162
163 /* Just hand this one over to the master sink */
164 pa_sink_input_set_requested_latency_within_thread(
165 u->sink_input,
166 pa_sink_get_requested_latency_within_thread(s));
167 }
168
169 /* Called from main context */
170 static void sink_set_volume_cb(pa_sink *s) {
171 struct userdata *u;
172
173 pa_sink_assert_ref(s);
174 pa_assert_se(u = s->userdata);
175
176 if (!PA_SINK_IS_LINKED(pa_sink_get_state(s)) ||
177 !PA_SINK_INPUT_IS_LINKED(pa_sink_input_get_state(u->sink_input)))
178 return;
179
180 pa_sink_input_set_volume(u->sink_input, &s->real_volume, s->save_volume, TRUE);
181 }
182
183 /* Called from main context */
184 static void sink_set_mute_cb(pa_sink *s) {
185 struct userdata *u;
186
187 pa_sink_assert_ref(s);
188 pa_assert_se(u = s->userdata);
189
190 if (!PA_SINK_IS_LINKED(pa_sink_get_state(s)) ||
191 !PA_SINK_INPUT_IS_LINKED(pa_sink_input_get_state(u->sink_input)))
192 return;
193
194 pa_sink_input_set_mute(u->sink_input, s->muted, s->save_muted);
195 }
196
197 /* Called from I/O thread context */
198 static int sink_input_pop_cb(pa_sink_input *i, size_t nbytes, pa_memchunk *chunk) {
199 struct userdata *u;
200 float *src, *dst;
201 size_t fs;
202 unsigned n, c;
203 pa_memchunk tchunk;
204 pa_usec_t current_latency PA_GCC_UNUSED;
205
206 pa_sink_input_assert_ref(i);
207 pa_assert(chunk);
208 pa_assert_se(u = i->userdata);
209
210 /* Hmm, process any rewind request that might be queued up */
211 pa_sink_process_rewind(u->sink, 0);
212
213 /* (1) IF YOU NEED A FIXED BLOCK SIZE USE
214 * pa_memblockq_peek_fixed_size() HERE INSTEAD. NOTE THAT FILTERS
215 * WHICH CAN DEAL WITH DYNAMIC BLOCK SIZES ARE HIGHLY
216 * PREFERRED. */
217 while (pa_memblockq_peek(u->memblockq, &tchunk) < 0) {
218 pa_memchunk nchunk;
219
220 pa_sink_render(u->sink, nbytes, &nchunk);
221 pa_memblockq_push(u->memblockq, &nchunk);
222 pa_memblock_unref(nchunk.memblock);
223 }
224
225 /* (2) IF YOU NEED A FIXED BLOCK SIZE, THIS NEXT LINE IS NOT
226 * NECESSARY */
227 tchunk.length = PA_MIN(nbytes, tchunk.length);
228 pa_assert(tchunk.length > 0);
229
230 fs = pa_frame_size(&i->sample_spec);
231 n = (unsigned) (tchunk.length / fs);
232
233 pa_assert(n > 0);
234
235 chunk->index = 0;
236 chunk->length = n*fs;
237 chunk->memblock = pa_memblock_new(i->sink->core->mempool, chunk->length);
238
239 pa_memblockq_drop(u->memblockq, chunk->length);
240
241 src = (float*) ((uint8_t*) pa_memblock_acquire(tchunk.memblock) + tchunk.index);
242 dst = (float*) pa_memblock_acquire(chunk->memblock);
243
244 /* (3) PUT YOUR CODE HERE TO DO SOMETHING WITH THE DATA */
245
246 /* As an example, copy input to output */
247 for (c = 0; c < u->channels; c++) {
248 pa_sample_clamp(PA_SAMPLE_FLOAT32NE,
249 dst+c, u->channels * sizeof(float),
250 src+c, u->channels * sizeof(float),
251 n);
252 }
253
254 pa_memblock_release(tchunk.memblock);
255 pa_memblock_release(chunk->memblock);
256
257 pa_memblock_unref(tchunk.memblock);
258
259 /* (4) IF YOU NEED THE LATENCY FOR SOMETHING ACQUIRE IT LIKE THIS: */
260 current_latency =
261 /* Get the latency of the master sink */
262 pa_sink_get_latency_within_thread(i->sink) +
263
264 /* Add the latency internal to our sink input on top */
265 pa_bytes_to_usec(pa_memblockq_get_length(i->thread_info.render_memblockq), &i->sink->sample_spec);
266
267 return 0;
268 }
269
270 /* Called from I/O thread context */
271 static void sink_input_process_rewind_cb(pa_sink_input *i, size_t nbytes) {
272 struct userdata *u;
273 size_t amount = 0;
274
275 pa_sink_input_assert_ref(i);
276 pa_assert_se(u = i->userdata);
277
278 if (u->sink->thread_info.rewind_nbytes > 0) {
279 size_t max_rewrite;
280
281 max_rewrite = nbytes + pa_memblockq_get_length(u->memblockq);
282 amount = PA_MIN(u->sink->thread_info.rewind_nbytes, max_rewrite);
283 u->sink->thread_info.rewind_nbytes = 0;
284
285 if (amount > 0) {
286 pa_memblockq_seek(u->memblockq, - (int64_t) amount, PA_SEEK_RELATIVE, TRUE);
287
288 /* (5) PUT YOUR CODE HERE TO RESET YOUR FILTER */
289 }
290 }
291
292 pa_sink_process_rewind(u->sink, amount);
293 pa_memblockq_rewind(u->memblockq, nbytes);
294 }
295
296 /* Called from I/O thread context */
297 static void sink_input_update_max_rewind_cb(pa_sink_input *i, size_t nbytes) {
298 struct userdata *u;
299
300 pa_sink_input_assert_ref(i);
301 pa_assert_se(u = i->userdata);
302
303 /* FIXME: Too small max_rewind:
304 * https://bugs.freedesktop.org/show_bug.cgi?id=53709 */
305 pa_memblockq_set_maxrewind(u->memblockq, nbytes);
306 pa_sink_set_max_rewind_within_thread(u->sink, nbytes);
307 }
308
309 /* Called from I/O thread context */
310 static void sink_input_update_max_request_cb(pa_sink_input *i, size_t nbytes) {
311 struct userdata *u;
312
313 pa_sink_input_assert_ref(i);
314 pa_assert_se(u = i->userdata);
315
316 /* (6) IF YOU NEED A FIXED BLOCK SIZE ROUND nbytes UP TO MULTIPLES
317 * OF IT HERE. THE PA_ROUND_UP MACRO IS USEFUL FOR THAT. */
318
319 pa_sink_set_max_request_within_thread(u->sink, nbytes);
320 }
321
322 /* Called from I/O thread context */
323 static void sink_input_update_sink_latency_range_cb(pa_sink_input *i) {
324 struct userdata *u;
325
326 pa_sink_input_assert_ref(i);
327 pa_assert_se(u = i->userdata);
328
329 pa_sink_set_latency_range_within_thread(u->sink, i->sink->thread_info.min_latency, i->sink->thread_info.max_latency);
330 }
331
332 /* Called from I/O thread context */
333 static void sink_input_update_sink_fixed_latency_cb(pa_sink_input *i) {
334 struct userdata *u;
335
336 pa_sink_input_assert_ref(i);
337 pa_assert_se(u = i->userdata);
338
339 /* (7) IF YOU NEED A FIXED BLOCK SIZE ADD THE LATENCY FOR ONE
340 * BLOCK MINUS ONE SAMPLE HERE. pa_usec_to_bytes_round_up() IS
341 * USEFUL FOR THAT. */
342
343 pa_sink_set_fixed_latency_within_thread(u->sink, i->sink->thread_info.fixed_latency);
344 }
345
346 /* Called from I/O thread context */
347 static void sink_input_detach_cb(pa_sink_input *i) {
348 struct userdata *u;
349
350 pa_sink_input_assert_ref(i);
351 pa_assert_se(u = i->userdata);
352
353 pa_sink_detach_within_thread(u->sink);
354
355 pa_sink_set_rtpoll(u->sink, NULL);
356 }
357
358 /* Called from I/O thread context */
359 static void sink_input_attach_cb(pa_sink_input *i) {
360 struct userdata *u;
361
362 pa_sink_input_assert_ref(i);
363 pa_assert_se(u = i->userdata);
364
365 pa_sink_set_rtpoll(u->sink, i->sink->thread_info.rtpoll);
366 pa_sink_set_latency_range_within_thread(u->sink, i->sink->thread_info.min_latency, i->sink->thread_info.max_latency);
367
368 /* (8.1) IF YOU NEED A FIXED BLOCK SIZE ADD THE LATENCY FOR ONE
369 * BLOCK MINUS ONE SAMPLE HERE. SEE (7) */
370 pa_sink_set_fixed_latency_within_thread(u->sink, i->sink->thread_info.fixed_latency);
371
372 /* (8.2) IF YOU NEED A FIXED BLOCK SIZE ROUND
373 * pa_sink_input_get_max_request(i) UP TO MULTIPLES OF IT
374 * HERE. SEE (6) */
375 pa_sink_set_max_request_within_thread(u->sink, pa_sink_input_get_max_request(i));
376
377 /* FIXME: Too small max_rewind:
378 * https://bugs.freedesktop.org/show_bug.cgi?id=53709 */
379 pa_sink_set_max_rewind_within_thread(u->sink, pa_sink_input_get_max_rewind(i));
380
381 pa_sink_attach_within_thread(u->sink);
382 }
383
384 /* Called from main context */
385 static void sink_input_kill_cb(pa_sink_input *i) {
386 struct userdata *u;
387
388 pa_sink_input_assert_ref(i);
389 pa_assert_se(u = i->userdata);
390
391 /* The order here matters! We first kill the sink input, followed
392 * by the sink. That means the sink callbacks must be protected
393 * against an unconnected sink input! */
394 pa_sink_input_unlink(u->sink_input);
395 pa_sink_unlink(u->sink);
396
397 pa_sink_input_unref(u->sink_input);
398 u->sink_input = NULL;
399
400 pa_sink_unref(u->sink);
401 u->sink = NULL;
402
403 pa_module_unload_request(u->module, TRUE);
404 }
405
406 /* Called from IO thread context */
407 static void sink_input_state_change_cb(pa_sink_input *i, pa_sink_input_state_t state) {
408 struct userdata *u;
409
410 pa_sink_input_assert_ref(i);
411 pa_assert_se(u = i->userdata);
412
413 /* If we are added for the first time, ask for a rewinding so that
414 * we are heard right-away. */
415 if (PA_SINK_INPUT_IS_LINKED(state) &&
416 i->thread_info.state == PA_SINK_INPUT_INIT) {
417 pa_log_debug("Requesting rewind due to state change.");
418 pa_sink_input_request_rewind(i, 0, FALSE, TRUE, TRUE);
419 }
420 }
421
422 /* Called from main context */
423 static pa_bool_t sink_input_may_move_to_cb(pa_sink_input *i, pa_sink *dest) {
424 struct userdata *u;
425
426 pa_sink_input_assert_ref(i);
427 pa_assert_se(u = i->userdata);
428
429 return u->sink != dest;
430 }
431
432 /* Called from main context */
433 static void sink_input_moving_cb(pa_sink_input *i, pa_sink *dest) {
434 struct userdata *u;
435
436 pa_sink_input_assert_ref(i);
437 pa_assert_se(u = i->userdata);
438
439 if (dest) {
440 pa_sink_set_asyncmsgq(u->sink, dest->asyncmsgq);
441 pa_sink_update_flags(u->sink, PA_SINK_LATENCY|PA_SINK_DYNAMIC_LATENCY, dest->flags);
442 } else
443 pa_sink_set_asyncmsgq(u->sink, NULL);
444
445 if (u->auto_desc && dest) {
446 const char *z;
447 pa_proplist *pl;
448
449 pl = pa_proplist_new();
450 z = pa_proplist_gets(dest->proplist, PA_PROP_DEVICE_DESCRIPTION);
451 pa_proplist_setf(pl, PA_PROP_DEVICE_DESCRIPTION, "Virtual Sink %s on %s",
452 pa_proplist_gets(u->sink->proplist, "device.vsink.name"), z ? z : dest->name);
453
454 pa_sink_update_proplist(u->sink, PA_UPDATE_REPLACE, pl);
455 pa_proplist_free(pl);
456 }
457 }
458
459 /* Called from main context */
460 static void sink_input_volume_changed_cb(pa_sink_input *i) {
461 struct userdata *u;
462
463 pa_sink_input_assert_ref(i);
464 pa_assert_se(u = i->userdata);
465
466 pa_sink_volume_changed(u->sink, &i->volume);
467 }
468
469 /* Called from main context */
470 static void sink_input_mute_changed_cb(pa_sink_input *i) {
471 struct userdata *u;
472
473 pa_sink_input_assert_ref(i);
474 pa_assert_se(u = i->userdata);
475
476 pa_sink_mute_changed(u->sink, i->muted);
477 }
478
479 int pa__init(pa_module*m) {
480 struct userdata *u;
481 pa_sample_spec ss;
482 pa_channel_map map;
483 pa_modargs *ma;
484 pa_sink *master=NULL;
485 pa_sink_input_new_data sink_input_data;
486 pa_sink_new_data sink_data;
487 pa_bool_t use_volume_sharing = TRUE;
488 pa_bool_t force_flat_volume = FALSE;
489 pa_memchunk silence;
490
491 pa_assert(m);
492
493 if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
494 pa_log("Failed to parse module arguments.");
495 goto fail;
496 }
497
498 if (!(master = pa_namereg_get(m->core, pa_modargs_get_value(ma, "master", NULL), PA_NAMEREG_SINK))) {
499 pa_log("Master sink not found");
500 goto fail;
501 }
502
503 pa_assert(master);
504
505 ss = master->sample_spec;
506 ss.format = PA_SAMPLE_FLOAT32;
507 map = master->channel_map;
508 if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map, PA_CHANNEL_MAP_DEFAULT) < 0) {
509 pa_log("Invalid sample format specification or channel map");
510 goto fail;
511 }
512
513 if (pa_modargs_get_value_boolean(ma, "use_volume_sharing", &use_volume_sharing) < 0) {
514 pa_log("use_volume_sharing= expects a boolean argument");
515 goto fail;
516 }
517
518 if (pa_modargs_get_value_boolean(ma, "force_flat_volume", &force_flat_volume) < 0) {
519 pa_log("force_flat_volume= expects a boolean argument");
520 goto fail;
521 }
522
523 if (use_volume_sharing && force_flat_volume) {
524 pa_log("Flat volume can't be forced when using volume sharing.");
525 goto fail;
526 }
527
528 u = pa_xnew0(struct userdata, 1);
529 u->module = m;
530 m->userdata = u;
531 u->channels = ss.channels;
532
533 /* Create sink */
534 pa_sink_new_data_init(&sink_data);
535 sink_data.driver = __FILE__;
536 sink_data.module = m;
537 if (!(sink_data.name = pa_xstrdup(pa_modargs_get_value(ma, "sink_name", NULL))))
538 sink_data.name = pa_sprintf_malloc("%s.vsink", master->name);
539 pa_sink_new_data_set_sample_spec(&sink_data, &ss);
540 pa_sink_new_data_set_channel_map(&sink_data, &map);
541 pa_proplist_sets(sink_data.proplist, PA_PROP_DEVICE_MASTER_DEVICE, master->name);
542 pa_proplist_sets(sink_data.proplist, PA_PROP_DEVICE_CLASS, "filter");
543 pa_proplist_sets(sink_data.proplist, "device.vsink.name", sink_data.name);
544
545 if (pa_modargs_get_proplist(ma, "sink_properties", sink_data.proplist, PA_UPDATE_REPLACE) < 0) {
546 pa_log("Invalid properties");
547 pa_sink_new_data_done(&sink_data);
548 goto fail;
549 }
550
551 if ((u->auto_desc = !pa_proplist_contains(sink_data.proplist, PA_PROP_DEVICE_DESCRIPTION))) {
552 const char *z;
553
554 z = pa_proplist_gets(master->proplist, PA_PROP_DEVICE_DESCRIPTION);
555 pa_proplist_setf(sink_data.proplist, PA_PROP_DEVICE_DESCRIPTION, "Virtual Sink %s on %s", sink_data.name, z ? z : master->name);
556 }
557
558 u->sink = pa_sink_new(m->core, &sink_data, (master->flags & (PA_SINK_LATENCY|PA_SINK_DYNAMIC_LATENCY))
559 | (use_volume_sharing ? PA_SINK_SHARE_VOLUME_WITH_MASTER : 0));
560 pa_sink_new_data_done(&sink_data);
561
562 if (!u->sink) {
563 pa_log("Failed to create sink.");
564 goto fail;
565 }
566
567 u->sink->parent.process_msg = sink_process_msg_cb;
568 u->sink->set_state = sink_set_state_cb;
569 u->sink->update_requested_latency = sink_update_requested_latency_cb;
570 u->sink->request_rewind = sink_request_rewind_cb;
571 pa_sink_set_set_mute_callback(u->sink, sink_set_mute_cb);
572 if (!use_volume_sharing) {
573 pa_sink_set_set_volume_callback(u->sink, sink_set_volume_cb);
574 pa_sink_enable_decibel_volume(u->sink, TRUE);
575 }
576 /* Normally this flag would be enabled automatically be we can force it. */
577 if (force_flat_volume)
578 u->sink->flags |= PA_SINK_FLAT_VOLUME;
579 u->sink->userdata = u;
580
581 pa_sink_set_asyncmsgq(u->sink, master->asyncmsgq);
582
583 /* Create sink input */
584 pa_sink_input_new_data_init(&sink_input_data);
585 sink_input_data.driver = __FILE__;
586 sink_input_data.module = m;
587 pa_sink_input_new_data_set_sink(&sink_input_data, master, FALSE);
588 sink_input_data.origin_sink = u->sink;
589 pa_proplist_setf(sink_input_data.proplist, PA_PROP_MEDIA_NAME, "Virtual Sink Stream from %s", pa_proplist_gets(u->sink->proplist, PA_PROP_DEVICE_DESCRIPTION));
590 pa_proplist_sets(sink_input_data.proplist, PA_PROP_MEDIA_ROLE, "filter");
591 pa_sink_input_new_data_set_sample_spec(&sink_input_data, &ss);
592 pa_sink_input_new_data_set_channel_map(&sink_input_data, &map);
593
594 pa_sink_input_new(&u->sink_input, m->core, &sink_input_data);
595 pa_sink_input_new_data_done(&sink_input_data);
596
597 if (!u->sink_input)
598 goto fail;
599
600 u->sink_input->pop = sink_input_pop_cb;
601 u->sink_input->process_rewind = sink_input_process_rewind_cb;
602 u->sink_input->update_max_rewind = sink_input_update_max_rewind_cb;
603 u->sink_input->update_max_request = sink_input_update_max_request_cb;
604 u->sink_input->update_sink_latency_range = sink_input_update_sink_latency_range_cb;
605 u->sink_input->update_sink_fixed_latency = sink_input_update_sink_fixed_latency_cb;
606 u->sink_input->kill = sink_input_kill_cb;
607 u->sink_input->attach = sink_input_attach_cb;
608 u->sink_input->detach = sink_input_detach_cb;
609 u->sink_input->state_change = sink_input_state_change_cb;
610 u->sink_input->may_move_to = sink_input_may_move_to_cb;
611 u->sink_input->moving = sink_input_moving_cb;
612 u->sink_input->volume_changed = use_volume_sharing ? NULL : sink_input_volume_changed_cb;
613 u->sink_input->mute_changed = sink_input_mute_changed_cb;
614 u->sink_input->userdata = u;
615
616 u->sink->input_to_master = u->sink_input;
617
618 pa_sink_input_get_silence(u->sink_input, &silence);
619 u->memblockq = pa_memblockq_new("module-virtual-sink memblockq", 0, MEMBLOCKQ_MAXLENGTH, 0, &ss, 1, 1, 0, &silence);
620 pa_memblock_unref(silence.memblock);
621
622 /* (9) INITIALIZE ANYTHING ELSE YOU NEED HERE */
623
624 pa_sink_put(u->sink);
625 pa_sink_input_put(u->sink_input);
626
627 pa_modargs_free(ma);
628
629 return 0;
630
631 fail:
632 if (ma)
633 pa_modargs_free(ma);
634
635 pa__done(m);
636
637 return -1;
638 }
639
640 int pa__get_n_used(pa_module *m) {
641 struct userdata *u;
642
643 pa_assert(m);
644 pa_assert_se(u = m->userdata);
645
646 return pa_sink_linked_by(u->sink);
647 }
648
649 void pa__done(pa_module*m) {
650 struct userdata *u;
651
652 pa_assert(m);
653
654 if (!(u = m->userdata))
655 return;
656
657 /* See comments in sink_input_kill_cb() above regarding
658 * destruction order! */
659
660 if (u->sink_input)
661 pa_sink_input_unlink(u->sink_input);
662
663 if (u->sink)
664 pa_sink_unlink(u->sink);
665
666 if (u->sink_input)
667 pa_sink_input_unref(u->sink_input);
668
669 if (u->sink)
670 pa_sink_unref(u->sink);
671
672 if (u->memblockq)
673 pa_memblockq_free(u->memblockq);
674
675 pa_xfree(u);
676 }