2 This file is part of PulseAudio.
4 Copyright 2010 Intel Corporation
5 Contributor: Pierre-Louis Bossart <pierre-louis.bossart@intel.com>
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.
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.
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
27 #include <pulse/gccmacro.h>
28 #include <pulse/xmalloc.h>
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>
41 #include "module-virtual-sink-symdef.h"
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
);
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> "
53 "channels=<number of channels> "
54 "channel_map=<channel map> "
55 "use_volume_sharing=<yes or no> "
56 "force_flat_volume=<yes or no> "
59 #define MEMBLOCKQ_MAXLENGTH (16*1024*1024)
64 /* FIXME: Uncomment this and take "autoloaded" as a modarg if this is a filter */
65 /* pa_bool_t autoloaded; */
68 pa_sink_input
*sink_input
;
70 pa_memblockq
*memblockq
;
76 static const char* const valid_modargs
[] = {
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
;
95 case PA_SINK_MESSAGE_GET_LATENCY
:
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;
106 *((pa_usec_t
*) data
) =
108 /* Get the latency of the master sink */
109 pa_sink_get_latency_within_thread(u
->sink_input
->sink
) +
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
);
117 return pa_sink_process_msg(o
, code
, data
, offset
, chunk
);
120 /* Called from main context */
121 static int sink_set_state_cb(pa_sink
*s
, pa_sink_state_t state
) {
124 pa_sink_assert_ref(s
);
125 pa_assert_se(u
= s
->userdata
);
127 if (!PA_SINK_IS_LINKED(state
) ||
128 !PA_SINK_INPUT_IS_LINKED(pa_sink_input_get_state(u
->sink_input
)))
131 pa_sink_input_cork(u
->sink_input
, state
== PA_SINK_SUSPENDED
);
135 /* Called from I/O thread context */
136 static void sink_request_rewind_cb(pa_sink
*s
) {
139 pa_sink_assert_ref(s
);
140 pa_assert_se(u
= s
->userdata
);
142 if (!PA_SINK_IS_LINKED(u
->sink
->thread_info
.state
) ||
143 !PA_SINK_INPUT_IS_LINKED(u
->sink_input
->thread_info
.state
))
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
);
152 /* Called from I/O thread context */
153 static void sink_update_requested_latency_cb(pa_sink
*s
) {
156 pa_sink_assert_ref(s
);
157 pa_assert_se(u
= s
->userdata
);
159 if (!PA_SINK_IS_LINKED(u
->sink
->thread_info
.state
) ||
160 !PA_SINK_INPUT_IS_LINKED(u
->sink_input
->thread_info
.state
))
163 /* Just hand this one over to the master sink */
164 pa_sink_input_set_requested_latency_within_thread(
166 pa_sink_get_requested_latency_within_thread(s
));
169 /* Called from main context */
170 static void sink_set_volume_cb(pa_sink
*s
) {
173 pa_sink_assert_ref(s
);
174 pa_assert_se(u
= s
->userdata
);
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
)))
180 pa_sink_input_set_volume(u
->sink_input
, &s
->real_volume
, s
->save_volume
, TRUE
);
183 /* Called from main context */
184 static void sink_set_mute_cb(pa_sink
*s
) {
187 pa_sink_assert_ref(s
);
188 pa_assert_se(u
= s
->userdata
);
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
)))
194 pa_sink_input_set_mute(u
->sink_input
, s
->muted
, s
->save_muted
);
197 /* Called from I/O thread context */
198 static int sink_input_pop_cb(pa_sink_input
*i
, size_t nbytes
, pa_memchunk
*chunk
) {
204 pa_usec_t current_latency PA_GCC_UNUSED
;
206 pa_sink_input_assert_ref(i
);
208 pa_assert_se(u
= i
->userdata
);
210 /* Hmm, process any rewind request that might be queued up */
211 pa_sink_process_rewind(u
->sink
, 0);
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
217 while (pa_memblockq_peek(u
->memblockq
, &tchunk
) < 0) {
220 pa_sink_render(u
->sink
, nbytes
, &nchunk
);
221 pa_memblockq_push(u
->memblockq
, &nchunk
);
222 pa_memblock_unref(nchunk
.memblock
);
225 /* (2) IF YOU NEED A FIXED BLOCK SIZE, THIS NEXT LINE IS NOT
227 tchunk
.length
= PA_MIN(nbytes
, tchunk
.length
);
228 pa_assert(tchunk
.length
> 0);
230 fs
= pa_frame_size(&i
->sample_spec
);
231 n
= (unsigned) (tchunk
.length
/ fs
);
236 chunk
->length
= n
*fs
;
237 chunk
->memblock
= pa_memblock_new(i
->sink
->core
->mempool
, chunk
->length
);
239 pa_memblockq_drop(u
->memblockq
, chunk
->length
);
241 src
= (float*) ((uint8_t*) pa_memblock_acquire(tchunk
.memblock
) + tchunk
.index
);
242 dst
= (float*) pa_memblock_acquire(chunk
->memblock
);
244 /* (3) PUT YOUR CODE HERE TO DO SOMETHING WITH THE DATA */
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),
254 pa_memblock_release(tchunk
.memblock
);
255 pa_memblock_release(chunk
->memblock
);
257 pa_memblock_unref(tchunk
.memblock
);
259 /* (4) IF YOU NEED THE LATENCY FOR SOMETHING ACQUIRE IT LIKE THIS: */
261 /* Get the latency of the master sink */
262 pa_sink_get_latency_within_thread(i
->sink
) +
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
);
270 /* Called from I/O thread context */
271 static void sink_input_process_rewind_cb(pa_sink_input
*i
, size_t nbytes
) {
275 pa_sink_input_assert_ref(i
);
276 pa_assert_se(u
= i
->userdata
);
278 if (u
->sink
->thread_info
.rewind_nbytes
> 0) {
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;
286 pa_memblockq_seek(u
->memblockq
, - (int64_t) amount
, PA_SEEK_RELATIVE
, TRUE
);
288 /* (5) PUT YOUR CODE HERE TO RESET YOUR FILTER */
292 pa_sink_process_rewind(u
->sink
, amount
);
293 pa_memblockq_rewind(u
->memblockq
, nbytes
);
296 /* Called from I/O thread context */
297 static void sink_input_update_max_rewind_cb(pa_sink_input
*i
, size_t nbytes
) {
300 pa_sink_input_assert_ref(i
);
301 pa_assert_se(u
= i
->userdata
);
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
);
309 /* Called from I/O thread context */
310 static void sink_input_update_max_request_cb(pa_sink_input
*i
, size_t nbytes
) {
313 pa_sink_input_assert_ref(i
);
314 pa_assert_se(u
= i
->userdata
);
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. */
319 pa_sink_set_max_request_within_thread(u
->sink
, nbytes
);
322 /* Called from I/O thread context */
323 static void sink_input_update_sink_latency_range_cb(pa_sink_input
*i
) {
326 pa_sink_input_assert_ref(i
);
327 pa_assert_se(u
= i
->userdata
);
329 pa_sink_set_latency_range_within_thread(u
->sink
, i
->sink
->thread_info
.min_latency
, i
->sink
->thread_info
.max_latency
);
332 /* Called from I/O thread context */
333 static void sink_input_update_sink_fixed_latency_cb(pa_sink_input
*i
) {
336 pa_sink_input_assert_ref(i
);
337 pa_assert_se(u
= i
->userdata
);
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. */
343 pa_sink_set_fixed_latency_within_thread(u
->sink
, i
->sink
->thread_info
.fixed_latency
);
346 /* Called from I/O thread context */
347 static void sink_input_detach_cb(pa_sink_input
*i
) {
350 pa_sink_input_assert_ref(i
);
351 pa_assert_se(u
= i
->userdata
);
353 pa_sink_detach_within_thread(u
->sink
);
355 pa_sink_set_rtpoll(u
->sink
, NULL
);
358 /* Called from I/O thread context */
359 static void sink_input_attach_cb(pa_sink_input
*i
) {
362 pa_sink_input_assert_ref(i
);
363 pa_assert_se(u
= i
->userdata
);
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
);
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
);
372 /* (8.2) IF YOU NEED A FIXED BLOCK SIZE ROUND
373 * pa_sink_input_get_max_request(i) UP TO MULTIPLES OF IT
375 pa_sink_set_max_request_within_thread(u
->sink
, pa_sink_input_get_max_request(i
));
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
));
381 pa_sink_attach_within_thread(u
->sink
);
384 /* Called from main context */
385 static void sink_input_kill_cb(pa_sink_input
*i
) {
388 pa_sink_input_assert_ref(i
);
389 pa_assert_se(u
= i
->userdata
);
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
);
397 pa_sink_input_unref(u
->sink_input
);
398 u
->sink_input
= NULL
;
400 pa_sink_unref(u
->sink
);
403 pa_module_unload_request(u
->module
, TRUE
);
406 /* Called from IO thread context */
407 static void sink_input_state_change_cb(pa_sink_input
*i
, pa_sink_input_state_t state
) {
410 pa_sink_input_assert_ref(i
);
411 pa_assert_se(u
= i
->userdata
);
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
);
422 /* Called from main context */
423 static pa_bool_t
sink_input_may_move_to_cb(pa_sink_input
*i
, pa_sink
*dest
) {
426 pa_sink_input_assert_ref(i
);
427 pa_assert_se(u
= i
->userdata
);
429 return u
->sink
!= dest
;
432 /* Called from main context */
433 static void sink_input_moving_cb(pa_sink_input
*i
, pa_sink
*dest
) {
436 pa_sink_input_assert_ref(i
);
437 pa_assert_se(u
= i
->userdata
);
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
);
443 pa_sink_set_asyncmsgq(u
->sink
, NULL
);
445 if (u
->auto_desc
&& dest
) {
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
);
454 pa_sink_update_proplist(u
->sink
, PA_UPDATE_REPLACE
, pl
);
455 pa_proplist_free(pl
);
459 /* Called from main context */
460 static void sink_input_volume_changed_cb(pa_sink_input
*i
) {
463 pa_sink_input_assert_ref(i
);
464 pa_assert_se(u
= i
->userdata
);
466 pa_sink_volume_changed(u
->sink
, &i
->volume
);
469 /* Called from main context */
470 static void sink_input_mute_changed_cb(pa_sink_input
*i
) {
473 pa_sink_input_assert_ref(i
);
474 pa_assert_se(u
= i
->userdata
);
476 pa_sink_mute_changed(u
->sink
, i
->muted
);
479 int pa__init(pa_module
*m
) {
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
;
493 if (!(ma
= pa_modargs_new(m
->argument
, valid_modargs
))) {
494 pa_log("Failed to parse module arguments.");
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");
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");
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");
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");
523 if (use_volume_sharing
&& force_flat_volume
) {
524 pa_log("Flat volume can't be forced when using volume sharing.");
528 u
= pa_xnew0(struct userdata
, 1);
531 u
->channels
= ss
.channels
;
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
);
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
);
551 if ((u
->auto_desc
= !pa_proplist_contains(sink_data
.proplist
, PA_PROP_DEVICE_DESCRIPTION
))) {
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
);
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
);
563 pa_log("Failed to create sink.");
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
);
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
;
581 pa_sink_set_asyncmsgq(u
->sink
, master
->asyncmsgq
);
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
);
594 pa_sink_input_new(&u
->sink_input
, m
->core
, &sink_input_data
);
595 pa_sink_input_new_data_done(&sink_input_data
);
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
;
616 u
->sink
->input_to_master
= u
->sink_input
;
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
);
622 /* (9) INITIALIZE ANYTHING ELSE YOU NEED HERE */
624 pa_sink_put(u
->sink
);
625 pa_sink_input_put(u
->sink_input
);
640 int pa__get_n_used(pa_module
*m
) {
644 pa_assert_se(u
= m
->userdata
);
646 return pa_sink_linked_by(u
->sink
);
649 void pa__done(pa_module
*m
) {
654 if (!(u
= m
->userdata
))
657 /* See comments in sink_input_kill_cb() above regarding
658 * destruction order! */
661 pa_sink_input_unlink(u
->sink_input
);
664 pa_sink_unlink(u
->sink
);
667 pa_sink_input_unref(u
->sink_input
);
670 pa_sink_unref(u
->sink
);
673 pa_memblockq_free(u
->memblockq
);