]> code.delx.au - pulseaudio/blob - src/modules/module-virtual-sink.c
virtual-sink: Remove irrelevant comment.
[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 pa_memblockq_set_maxrewind(u->memblockq, nbytes);
304 pa_sink_set_max_rewind_within_thread(u->sink, nbytes);
305 }
306
307 /* Called from I/O thread context */
308 static void sink_input_update_max_request_cb(pa_sink_input *i, size_t nbytes) {
309 struct userdata *u;
310
311 pa_sink_input_assert_ref(i);
312 pa_assert_se(u = i->userdata);
313
314 /* (6) IF YOU NEED A FIXED BLOCK SIZE ROUND nbytes UP TO MULTIPLES
315 * OF IT HERE. THE PA_ROUND_UP MACRO IS USEFUL FOR THAT. */
316
317 pa_sink_set_max_request_within_thread(u->sink, nbytes);
318 }
319
320 /* Called from I/O thread context */
321 static void sink_input_update_sink_latency_range_cb(pa_sink_input *i) {
322 struct userdata *u;
323
324 pa_sink_input_assert_ref(i);
325 pa_assert_se(u = i->userdata);
326
327 pa_sink_set_latency_range_within_thread(u->sink, i->sink->thread_info.min_latency, i->sink->thread_info.max_latency);
328 }
329
330 /* Called from I/O thread context */
331 static void sink_input_update_sink_fixed_latency_cb(pa_sink_input *i) {
332 struct userdata *u;
333
334 pa_sink_input_assert_ref(i);
335 pa_assert_se(u = i->userdata);
336
337 /* (7) IF YOU NEED A FIXED BLOCK SIZE ADD THE LATENCY FOR ONE
338 * BLOCK MINUS ONE SAMPLE HERE. pa_usec_to_bytes_round_up() IS
339 * USEFUL FOR THAT. */
340
341 pa_sink_set_fixed_latency_within_thread(u->sink, i->sink->thread_info.fixed_latency);
342 }
343
344 /* Called from I/O thread context */
345 static void sink_input_detach_cb(pa_sink_input *i) {
346 struct userdata *u;
347
348 pa_sink_input_assert_ref(i);
349 pa_assert_se(u = i->userdata);
350
351 pa_sink_detach_within_thread(u->sink);
352
353 pa_sink_set_rtpoll(u->sink, NULL);
354 }
355
356 /* Called from I/O thread context */
357 static void sink_input_attach_cb(pa_sink_input *i) {
358 struct userdata *u;
359
360 pa_sink_input_assert_ref(i);
361 pa_assert_se(u = i->userdata);
362
363 pa_sink_set_rtpoll(u->sink, i->sink->thread_info.rtpoll);
364 pa_sink_set_latency_range_within_thread(u->sink, i->sink->thread_info.min_latency, i->sink->thread_info.max_latency);
365
366 /* (8.1) IF YOU NEED A FIXED BLOCK SIZE ADD THE LATENCY FOR ONE
367 * BLOCK MINUS ONE SAMPLE HERE. SEE (7) */
368 pa_sink_set_fixed_latency_within_thread(u->sink, i->sink->thread_info.fixed_latency);
369
370 /* (8.2) IF YOU NEED A FIXED BLOCK SIZE ROUND
371 * pa_sink_input_get_max_request(i) UP TO MULTIPLES OF IT
372 * HERE. SEE (6) */
373 pa_sink_set_max_request_within_thread(u->sink, pa_sink_input_get_max_request(i));
374 pa_sink_set_max_rewind_within_thread(u->sink, pa_sink_input_get_max_rewind(i));
375
376 pa_sink_attach_within_thread(u->sink);
377 }
378
379 /* Called from main context */
380 static void sink_input_kill_cb(pa_sink_input *i) {
381 struct userdata *u;
382
383 pa_sink_input_assert_ref(i);
384 pa_assert_se(u = i->userdata);
385
386 /* The order here matters! We first kill the sink input, followed
387 * by the sink. That means the sink callbacks must be protected
388 * against an unconnected sink input! */
389 pa_sink_input_unlink(u->sink_input);
390 pa_sink_unlink(u->sink);
391
392 pa_sink_input_unref(u->sink_input);
393 u->sink_input = NULL;
394
395 pa_sink_unref(u->sink);
396 u->sink = NULL;
397
398 pa_module_unload_request(u->module, TRUE);
399 }
400
401 /* Called from IO thread context */
402 static void sink_input_state_change_cb(pa_sink_input *i, pa_sink_input_state_t state) {
403 struct userdata *u;
404
405 pa_sink_input_assert_ref(i);
406 pa_assert_se(u = i->userdata);
407
408 /* If we are added for the first time, ask for a rewinding so that
409 * we are heard right-away. */
410 if (PA_SINK_INPUT_IS_LINKED(state) &&
411 i->thread_info.state == PA_SINK_INPUT_INIT) {
412 pa_log_debug("Requesting rewind due to state change.");
413 pa_sink_input_request_rewind(i, 0, FALSE, TRUE, TRUE);
414 }
415 }
416
417 /* Called from main context */
418 static pa_bool_t sink_input_may_move_to_cb(pa_sink_input *i, pa_sink *dest) {
419 struct userdata *u;
420
421 pa_sink_input_assert_ref(i);
422 pa_assert_se(u = i->userdata);
423
424 return u->sink != dest;
425 }
426
427 /* Called from main context */
428 static void sink_input_moving_cb(pa_sink_input *i, pa_sink *dest) {
429 struct userdata *u;
430
431 pa_sink_input_assert_ref(i);
432 pa_assert_se(u = i->userdata);
433
434 if (dest) {
435 pa_sink_set_asyncmsgq(u->sink, dest->asyncmsgq);
436 pa_sink_update_flags(u->sink, PA_SINK_LATENCY|PA_SINK_DYNAMIC_LATENCY, dest->flags);
437 } else
438 pa_sink_set_asyncmsgq(u->sink, NULL);
439
440 if (u->auto_desc && dest) {
441 const char *z;
442 pa_proplist *pl;
443
444 pl = pa_proplist_new();
445 z = pa_proplist_gets(dest->proplist, PA_PROP_DEVICE_DESCRIPTION);
446 pa_proplist_setf(pl, PA_PROP_DEVICE_DESCRIPTION, "Virtual Sink %s on %s",
447 pa_proplist_gets(u->sink->proplist, "device.vsink.name"), z ? z : dest->name);
448
449 pa_sink_update_proplist(u->sink, PA_UPDATE_REPLACE, pl);
450 pa_proplist_free(pl);
451 }
452 }
453
454 /* Called from main context */
455 static void sink_input_volume_changed_cb(pa_sink_input *i) {
456 struct userdata *u;
457
458 pa_sink_input_assert_ref(i);
459 pa_assert_se(u = i->userdata);
460
461 pa_sink_volume_changed(u->sink, &i->volume);
462 }
463
464 /* Called from main context */
465 static void sink_input_mute_changed_cb(pa_sink_input *i) {
466 struct userdata *u;
467
468 pa_sink_input_assert_ref(i);
469 pa_assert_se(u = i->userdata);
470
471 pa_sink_mute_changed(u->sink, i->muted);
472 }
473
474 int pa__init(pa_module*m) {
475 struct userdata *u;
476 pa_sample_spec ss;
477 pa_channel_map map;
478 pa_modargs *ma;
479 pa_sink *master=NULL;
480 pa_sink_input_new_data sink_input_data;
481 pa_sink_new_data sink_data;
482 pa_bool_t use_volume_sharing = TRUE;
483 pa_bool_t force_flat_volume = FALSE;
484 pa_memchunk silence;
485
486 pa_assert(m);
487
488 if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
489 pa_log("Failed to parse module arguments.");
490 goto fail;
491 }
492
493 if (!(master = pa_namereg_get(m->core, pa_modargs_get_value(ma, "master", NULL), PA_NAMEREG_SINK))) {
494 pa_log("Master sink not found");
495 goto fail;
496 }
497
498 pa_assert(master);
499
500 ss = master->sample_spec;
501 ss.format = PA_SAMPLE_FLOAT32;
502 map = master->channel_map;
503 if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map, PA_CHANNEL_MAP_DEFAULT) < 0) {
504 pa_log("Invalid sample format specification or channel map");
505 goto fail;
506 }
507
508 if (pa_modargs_get_value_boolean(ma, "use_volume_sharing", &use_volume_sharing) < 0) {
509 pa_log("use_volume_sharing= expects a boolean argument");
510 goto fail;
511 }
512
513 if (pa_modargs_get_value_boolean(ma, "force_flat_volume", &force_flat_volume) < 0) {
514 pa_log("force_flat_volume= expects a boolean argument");
515 goto fail;
516 }
517
518 if (use_volume_sharing && force_flat_volume) {
519 pa_log("Flat volume can't be forced when using volume sharing.");
520 goto fail;
521 }
522
523 u = pa_xnew0(struct userdata, 1);
524 u->module = m;
525 m->userdata = u;
526 u->channels = ss.channels;
527
528 /* Create sink */
529 pa_sink_new_data_init(&sink_data);
530 sink_data.driver = __FILE__;
531 sink_data.module = m;
532 if (!(sink_data.name = pa_xstrdup(pa_modargs_get_value(ma, "sink_name", NULL))))
533 sink_data.name = pa_sprintf_malloc("%s.vsink", master->name);
534 pa_sink_new_data_set_sample_spec(&sink_data, &ss);
535 pa_sink_new_data_set_channel_map(&sink_data, &map);
536 pa_proplist_sets(sink_data.proplist, PA_PROP_DEVICE_MASTER_DEVICE, master->name);
537 pa_proplist_sets(sink_data.proplist, PA_PROP_DEVICE_CLASS, "filter");
538 pa_proplist_sets(sink_data.proplist, "device.vsink.name", sink_data.name);
539
540 if (pa_modargs_get_proplist(ma, "sink_properties", sink_data.proplist, PA_UPDATE_REPLACE) < 0) {
541 pa_log("Invalid properties");
542 pa_sink_new_data_done(&sink_data);
543 goto fail;
544 }
545
546 if ((u->auto_desc = !pa_proplist_contains(sink_data.proplist, PA_PROP_DEVICE_DESCRIPTION))) {
547 const char *z;
548
549 z = pa_proplist_gets(master->proplist, PA_PROP_DEVICE_DESCRIPTION);
550 pa_proplist_setf(sink_data.proplist, PA_PROP_DEVICE_DESCRIPTION, "Virtual Sink %s on %s", sink_data.name, z ? z : master->name);
551 }
552
553 u->sink = pa_sink_new(m->core, &sink_data, (master->flags & (PA_SINK_LATENCY|PA_SINK_DYNAMIC_LATENCY))
554 | (use_volume_sharing ? PA_SINK_SHARE_VOLUME_WITH_MASTER : 0));
555 pa_sink_new_data_done(&sink_data);
556
557 if (!u->sink) {
558 pa_log("Failed to create sink.");
559 goto fail;
560 }
561
562 u->sink->parent.process_msg = sink_process_msg_cb;
563 u->sink->set_state = sink_set_state_cb;
564 u->sink->update_requested_latency = sink_update_requested_latency_cb;
565 u->sink->request_rewind = sink_request_rewind_cb;
566 pa_sink_set_set_mute_callback(u->sink, sink_set_mute_cb);
567 if (!use_volume_sharing) {
568 pa_sink_set_set_volume_callback(u->sink, sink_set_volume_cb);
569 pa_sink_enable_decibel_volume(u->sink, TRUE);
570 }
571 /* Normally this flag would be enabled automatically be we can force it. */
572 if (force_flat_volume)
573 u->sink->flags |= PA_SINK_FLAT_VOLUME;
574 u->sink->userdata = u;
575
576 pa_sink_set_asyncmsgq(u->sink, master->asyncmsgq);
577
578 /* Create sink input */
579 pa_sink_input_new_data_init(&sink_input_data);
580 sink_input_data.driver = __FILE__;
581 sink_input_data.module = m;
582 pa_sink_input_new_data_set_sink(&sink_input_data, master, FALSE);
583 sink_input_data.origin_sink = u->sink;
584 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));
585 pa_proplist_sets(sink_input_data.proplist, PA_PROP_MEDIA_ROLE, "filter");
586 pa_sink_input_new_data_set_sample_spec(&sink_input_data, &ss);
587 pa_sink_input_new_data_set_channel_map(&sink_input_data, &map);
588
589 pa_sink_input_new(&u->sink_input, m->core, &sink_input_data);
590 pa_sink_input_new_data_done(&sink_input_data);
591
592 if (!u->sink_input)
593 goto fail;
594
595 u->sink_input->pop = sink_input_pop_cb;
596 u->sink_input->process_rewind = sink_input_process_rewind_cb;
597 u->sink_input->update_max_rewind = sink_input_update_max_rewind_cb;
598 u->sink_input->update_max_request = sink_input_update_max_request_cb;
599 u->sink_input->update_sink_latency_range = sink_input_update_sink_latency_range_cb;
600 u->sink_input->update_sink_fixed_latency = sink_input_update_sink_fixed_latency_cb;
601 u->sink_input->kill = sink_input_kill_cb;
602 u->sink_input->attach = sink_input_attach_cb;
603 u->sink_input->detach = sink_input_detach_cb;
604 u->sink_input->state_change = sink_input_state_change_cb;
605 u->sink_input->may_move_to = sink_input_may_move_to_cb;
606 u->sink_input->moving = sink_input_moving_cb;
607 u->sink_input->volume_changed = use_volume_sharing ? NULL : sink_input_volume_changed_cb;
608 u->sink_input->mute_changed = sink_input_mute_changed_cb;
609 u->sink_input->userdata = u;
610
611 u->sink->input_to_master = u->sink_input;
612
613 pa_sink_input_get_silence(u->sink_input, &silence);
614 u->memblockq = pa_memblockq_new("module-virtual-sink memblockq", 0, MEMBLOCKQ_MAXLENGTH, 0, &ss, 1, 1, 0, &silence);
615 pa_memblock_unref(silence.memblock);
616
617 /* (9) INITIALIZE ANYTHING ELSE YOU NEED HERE */
618
619 pa_sink_put(u->sink);
620 pa_sink_input_put(u->sink_input);
621
622 pa_modargs_free(ma);
623
624 return 0;
625
626 fail:
627 if (ma)
628 pa_modargs_free(ma);
629
630 pa__done(m);
631
632 return -1;
633 }
634
635 int pa__get_n_used(pa_module *m) {
636 struct userdata *u;
637
638 pa_assert(m);
639 pa_assert_se(u = m->userdata);
640
641 return pa_sink_linked_by(u->sink);
642 }
643
644 void pa__done(pa_module*m) {
645 struct userdata *u;
646
647 pa_assert(m);
648
649 if (!(u = m->userdata))
650 return;
651
652 /* See comments in sink_input_kill_cb() above regarding
653 * destruction order! */
654
655 if (u->sink_input)
656 pa_sink_input_unlink(u->sink_input);
657
658 if (u->sink)
659 pa_sink_unlink(u->sink);
660
661 if (u->sink_input)
662 pa_sink_input_unref(u->sink_input);
663
664 if (u->sink)
665 pa_sink_unref(u->sink);
666
667 if (u->memblockq)
668 pa_memblockq_free(u->memblockq);
669
670 pa_xfree(u);
671 }