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