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
23 /* TODO: Some plugins cause latency, and some even report it by using a control
24 out port. We don't currently use the latency information. */
30 #include <pulse/xmalloc.h>
31 #include <pulse/i18n.h>
33 #include <pulsecore/core-error.h>
34 #include <pulsecore/namereg.h>
35 #include <pulsecore/sink.h>
36 #include <pulsecore/module.h>
37 #include <pulsecore/core-util.h>
38 #include <pulsecore/modargs.h>
39 #include <pulsecore/log.h>
40 #include <pulsecore/thread.h>
41 #include <pulsecore/thread-mq.h>
42 #include <pulsecore/rtpoll.h>
43 #include <pulsecore/sample-util.h>
44 #include <pulsecore/ltdl-helper.h>
46 #include "module-virtual-sink-symdef.h"
48 PA_MODULE_AUTHOR("Pierre-Louis Bossart");
49 PA_MODULE_DESCRIPTION(_("Virtual sink"));
50 PA_MODULE_VERSION(PACKAGE_VERSION
);
51 PA_MODULE_LOAD_ONCE(FALSE
);
53 _("sink_name=<name for the sink> "
54 "sink_properties=<properties for the sink> "
55 "master=<name of sink to filter> "
56 "format=<sample format> "
58 "channels=<number of channels> "
59 "channel_map=<channel map> "
60 "use_volume_sharing=<yes or no> "
61 "force_flat_volume=<yes or no> "
64 #define MEMBLOCKQ_MAXLENGTH (16*1024*1024)
70 pa_sink_input
*sink_input
;
72 pa_memblockq
*memblockq
;
78 static const char* const valid_modargs
[] = {
91 /* Called from I/O thread context */
92 static int sink_process_msg_cb(pa_msgobject
*o
, int code
, void *data
, int64_t offset
, pa_memchunk
*chunk
) {
93 struct userdata
*u
= PA_SINK(o
)->userdata
;
97 case PA_SINK_MESSAGE_GET_LATENCY
:
99 /* The sink is _put() before the sink input is, so let's
100 * make sure we don't access it in that time. Also, the
101 * sink input is first shut down, the sink second. */
102 if (!PA_SINK_IS_LINKED(u
->sink
->thread_info
.state
) ||
103 !PA_SINK_INPUT_IS_LINKED(u
->sink_input
->thread_info
.state
)) {
104 *((pa_usec_t
*) data
) = 0;
108 *((pa_usec_t
*) data
) =
110 /* Get the latency of the master sink */
111 pa_sink_get_latency_within_thread(u
->sink_input
->sink
) +
113 /* Add the latency internal to our sink input on top */
114 pa_bytes_to_usec(pa_memblockq_get_length(u
->sink_input
->thread_info
.render_memblockq
), &u
->sink_input
->sink
->sample_spec
);
119 return pa_sink_process_msg(o
, code
, data
, offset
, chunk
);
122 /* Called from main context */
123 static int sink_set_state_cb(pa_sink
*s
, pa_sink_state_t state
) {
126 pa_sink_assert_ref(s
);
127 pa_assert_se(u
= s
->userdata
);
129 if (!PA_SINK_IS_LINKED(state
) ||
130 !PA_SINK_INPUT_IS_LINKED(pa_sink_input_get_state(u
->sink_input
)))
133 pa_sink_input_cork(u
->sink_input
, state
== PA_SINK_SUSPENDED
);
137 /* Called from I/O thread context */
138 static void sink_request_rewind_cb(pa_sink
*s
) {
141 pa_sink_assert_ref(s
);
142 pa_assert_se(u
= s
->userdata
);
144 if (!PA_SINK_IS_LINKED(u
->sink
->thread_info
.state
) ||
145 !PA_SINK_INPUT_IS_LINKED(u
->sink_input
->thread_info
.state
))
148 /* Just hand this one over to the master sink */
149 pa_sink_input_request_rewind(u
->sink_input
,
150 s
->thread_info
.rewind_nbytes
+
151 pa_memblockq_get_length(u
->memblockq
), TRUE
, FALSE
, FALSE
);
154 /* Called from I/O thread context */
155 static void sink_update_requested_latency_cb(pa_sink
*s
) {
158 pa_sink_assert_ref(s
);
159 pa_assert_se(u
= s
->userdata
);
161 if (!PA_SINK_IS_LINKED(u
->sink
->thread_info
.state
) ||
162 !PA_SINK_INPUT_IS_LINKED(u
->sink_input
->thread_info
.state
))
165 /* Just hand this one over to the master sink */
166 pa_sink_input_set_requested_latency_within_thread(
168 pa_sink_get_requested_latency_within_thread(s
));
171 /* Called from main context */
172 static void sink_set_volume_cb(pa_sink
*s
) {
175 pa_sink_assert_ref(s
);
176 pa_assert_se(u
= s
->userdata
);
178 if (!PA_SINK_IS_LINKED(pa_sink_get_state(s
)) ||
179 !PA_SINK_INPUT_IS_LINKED(pa_sink_input_get_state(u
->sink_input
)))
182 pa_sink_input_set_volume(u
->sink_input
, &s
->real_volume
, s
->save_volume
, TRUE
);
185 /* Called from main context */
186 static void sink_set_mute_cb(pa_sink
*s
) {
189 pa_sink_assert_ref(s
);
190 pa_assert_se(u
= s
->userdata
);
192 if (!PA_SINK_IS_LINKED(pa_sink_get_state(s
)) ||
193 !PA_SINK_INPUT_IS_LINKED(pa_sink_input_get_state(u
->sink_input
)))
196 pa_sink_input_set_mute(u
->sink_input
, s
->muted
, s
->save_muted
);
199 /* Called from I/O thread context */
200 static int sink_input_pop_cb(pa_sink_input
*i
, size_t nbytes
, pa_memchunk
*chunk
) {
206 pa_usec_t current_latency
;
208 pa_sink_input_assert_ref(i
);
210 pa_assert_se(u
= i
->userdata
);
212 /* Hmm, process any rewind request that might be queued up */
213 pa_sink_process_rewind(u
->sink
, 0);
215 /* (1) IF YOU NEED A FIXED BLOCK SIZE USE
216 * pa_memblockq_peek_fixed_size() HERE INSTEAD. NOTE THAT FILTERS
217 * WHICH CAN DEAL WITH DYNAMIC BLOCK SIZES ARE HIGHLY
219 while (pa_memblockq_peek(u
->memblockq
, &tchunk
) < 0) {
222 pa_sink_render(u
->sink
, nbytes
, &nchunk
);
223 pa_memblockq_push(u
->memblockq
, &nchunk
);
224 pa_memblock_unref(nchunk
.memblock
);
227 /* (2) IF YOU NEED A FIXED BLOCK SIZE, THIS NEXT LINE IS NOT
229 tchunk
.length
= PA_MIN(nbytes
, tchunk
.length
);
230 pa_assert(tchunk
.length
> 0);
232 fs
= pa_frame_size(&i
->sample_spec
);
233 n
= (unsigned) (tchunk
.length
/ fs
);
238 chunk
->length
= n
*fs
;
239 chunk
->memblock
= pa_memblock_new(i
->sink
->core
->mempool
, chunk
->length
);
241 pa_memblockq_drop(u
->memblockq
, chunk
->length
);
243 src
= (float*) ((uint8_t*) pa_memblock_acquire(tchunk
.memblock
) + tchunk
.index
);
244 dst
= (float*) pa_memblock_acquire(chunk
->memblock
);
246 /* (3) PUT YOUR CODE HERE TO DO SOMETHING WITH THE DATA */
248 /* As an example, copy input to output */
249 for (c
= 0; c
< u
->channels
; c
++) {
250 pa_sample_clamp(PA_SAMPLE_FLOAT32NE
,
251 dst
+c
, u
->channels
* sizeof(float),
252 src
+c
, u
->channels
* sizeof(float),
256 pa_memblock_release(tchunk
.memblock
);
257 pa_memblock_release(chunk
->memblock
);
259 pa_memblock_unref(tchunk
.memblock
);
261 /* (4) IF YOU NEED THE LATENCY FOR SOMETHING ACQUIRE IT LIKE THIS: */
263 /* Get the latency of the master sink */
264 pa_sink_get_latency_within_thread(i
->sink
) +
266 /* Add the latency internal to our sink input on top */
267 pa_bytes_to_usec(pa_memblockq_get_length(i
->thread_info
.render_memblockq
), &i
->sink
->sample_spec
);
272 /* Called from I/O thread context */
273 static void sink_input_process_rewind_cb(pa_sink_input
*i
, size_t nbytes
) {
277 pa_sink_input_assert_ref(i
);
278 pa_assert_se(u
= i
->userdata
);
280 if (u
->sink
->thread_info
.rewind_nbytes
> 0) {
283 max_rewrite
= nbytes
+ pa_memblockq_get_length(u
->memblockq
);
284 amount
= PA_MIN(u
->sink
->thread_info
.rewind_nbytes
, max_rewrite
);
285 u
->sink
->thread_info
.rewind_nbytes
= 0;
288 pa_memblockq_seek(u
->memblockq
, - (int64_t) amount
, PA_SEEK_RELATIVE
, TRUE
);
290 /* (5) PUT YOUR CODE HERE TO RESET YOUR FILTER */
294 pa_sink_process_rewind(u
->sink
, amount
);
295 pa_memblockq_rewind(u
->memblockq
, nbytes
);
298 /* Called from I/O thread context */
299 static void sink_input_update_max_rewind_cb(pa_sink_input
*i
, size_t nbytes
) {
302 pa_sink_input_assert_ref(i
);
303 pa_assert_se(u
= i
->userdata
);
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
));
376 pa_sink_set_max_rewind_within_thread(u
->sink
, pa_sink_input_get_max_rewind(i
));
378 pa_sink_attach_within_thread(u
->sink
);
381 /* Called from main context */
382 static void sink_input_kill_cb(pa_sink_input
*i
) {
385 pa_sink_input_assert_ref(i
);
386 pa_assert_se(u
= i
->userdata
);
388 /* The order here matters! We first kill the sink input, followed
389 * by the sink. That means the sink callbacks must be protected
390 * against an unconnected sink input! */
391 pa_sink_input_unlink(u
->sink_input
);
392 pa_sink_unlink(u
->sink
);
394 pa_sink_input_unref(u
->sink_input
);
395 u
->sink_input
= NULL
;
397 pa_sink_unref(u
->sink
);
400 pa_module_unload_request(u
->module
, TRUE
);
403 /* Called from IO thread context */
404 static void sink_input_state_change_cb(pa_sink_input
*i
, pa_sink_input_state_t state
) {
407 pa_sink_input_assert_ref(i
);
408 pa_assert_se(u
= i
->userdata
);
410 /* If we are added for the first time, ask for a rewinding so that
411 * we are heard right-away. */
412 if (PA_SINK_INPUT_IS_LINKED(state
) &&
413 i
->thread_info
.state
== PA_SINK_INPUT_INIT
) {
414 pa_log_debug("Requesting rewind due to state change.");
415 pa_sink_input_request_rewind(i
, 0, FALSE
, TRUE
, TRUE
);
419 /* Called from main context */
420 static pa_bool_t
sink_input_may_move_to_cb(pa_sink_input
*i
, pa_sink
*dest
) {
423 pa_sink_input_assert_ref(i
);
424 pa_assert_se(u
= i
->userdata
);
426 return u
->sink
!= dest
;
429 /* Called from main context */
430 static void sink_input_moving_cb(pa_sink_input
*i
, pa_sink
*dest
) {
433 pa_sink_input_assert_ref(i
);
434 pa_assert_se(u
= i
->userdata
);
437 pa_sink_set_asyncmsgq(u
->sink
, dest
->asyncmsgq
);
438 pa_sink_update_flags(u
->sink
, PA_SINK_LATENCY
|PA_SINK_DYNAMIC_LATENCY
, dest
->flags
);
440 pa_sink_set_asyncmsgq(u
->sink
, NULL
);
442 if (u
->auto_desc
&& dest
) {
446 pl
= pa_proplist_new();
447 z
= pa_proplist_gets(dest
->proplist
, PA_PROP_DEVICE_DESCRIPTION
);
448 pa_proplist_setf(pl
, PA_PROP_DEVICE_DESCRIPTION
, "Virtual Sink %s on %s",
449 pa_proplist_gets(u
->sink
->proplist
, "device.vsink.name"), z
? z
: dest
->name
);
451 pa_sink_update_proplist(u
->sink
, PA_UPDATE_REPLACE
, pl
);
452 pa_proplist_free(pl
);
456 /* Called from main context */
457 static void sink_input_volume_changed_cb(pa_sink_input
*i
) {
460 pa_sink_input_assert_ref(i
);
461 pa_assert_se(u
= i
->userdata
);
463 pa_sink_volume_changed(u
->sink
, &i
->volume
);
466 /* Called from main context */
467 static void sink_input_mute_changed_cb(pa_sink_input
*i
) {
470 pa_sink_input_assert_ref(i
);
471 pa_assert_se(u
= i
->userdata
);
473 pa_sink_mute_changed(u
->sink
, i
->muted
);
476 int pa__init(pa_module
*m
) {
481 pa_sink
*master
=NULL
;
482 pa_sink_input_new_data sink_input_data
;
483 pa_sink_new_data sink_data
;
484 pa_bool_t
*use_default
= NULL
;
485 pa_bool_t use_volume_sharing
= FALSE
;
486 pa_bool_t force_flat_volume
= FALSE
;
490 if (!(ma
= pa_modargs_new(m
->argument
, valid_modargs
))) {
491 pa_log("Failed to parse module arguments.");
495 if (!(master
= pa_namereg_get(m
->core
, pa_modargs_get_value(ma
, "master", NULL
), PA_NAMEREG_SINK
))) {
496 pa_log("Master sink not found");
502 ss
= master
->sample_spec
;
503 ss
.format
= PA_SAMPLE_FLOAT32
;
504 map
= master
->channel_map
;
505 if (pa_modargs_get_sample_spec_and_channel_map(ma
, &ss
, &map
, PA_CHANNEL_MAP_DEFAULT
) < 0) {
506 pa_log("Invalid sample format specification or channel map");
510 if (pa_modargs_get_value_boolean(ma
, "use_volume_sharing", &use_volume_sharing
) < 0) {
511 pa_log("use_volume_sharing= expects a boolean argument");
515 if (pa_modargs_get_value_boolean(ma
, "force_flat_volume", &force_flat_volume
) < 0) {
516 pa_log("force_flat_volume= expects a boolean argument");
520 if (use_volume_sharing
&& force_flat_volume
) {
521 pa_log("Flat volume can't be forced when using volume sharing.");
525 u
= pa_xnew0(struct userdata
, 1);
528 u
->channels
= ss
.channels
;
531 pa_sink_new_data_init(&sink_data
);
532 sink_data
.driver
= __FILE__
;
533 sink_data
.module
= m
;
534 if (!(sink_data
.name
= pa_xstrdup(pa_modargs_get_value(ma
, "sink_name", NULL
))))
535 sink_data
.name
= pa_sprintf_malloc("%s.vsink", master
->name
);
536 pa_sink_new_data_set_sample_spec(&sink_data
, &ss
);
537 pa_sink_new_data_set_channel_map(&sink_data
, &map
);
538 pa_proplist_sets(sink_data
.proplist
, PA_PROP_DEVICE_MASTER_DEVICE
, master
->name
);
539 pa_proplist_sets(sink_data
.proplist
, PA_PROP_DEVICE_CLASS
, "filter");
540 pa_proplist_sets(sink_data
.proplist
, "device.vsink.name", sink_data
.name
);
542 if (pa_modargs_get_proplist(ma
, "sink_properties", sink_data
.proplist
, PA_UPDATE_REPLACE
) < 0) {
543 pa_log("Invalid properties");
544 pa_sink_new_data_done(&sink_data
);
548 if ((u
->auto_desc
= !pa_proplist_contains(sink_data
.proplist
, PA_PROP_DEVICE_DESCRIPTION
))) {
551 z
= pa_proplist_gets(master
->proplist
, PA_PROP_DEVICE_DESCRIPTION
);
552 pa_proplist_setf(sink_data
.proplist
, PA_PROP_DEVICE_DESCRIPTION
, "Virtual Sink %s on %s", sink_data
.name
, z
? z
: master
->name
);
555 u
->sink
= pa_sink_new(m
->core
, &sink_data
, (master
->flags
& (PA_SINK_LATENCY
|PA_SINK_DYNAMIC_LATENCY
))
556 | (use_volume_sharing
? PA_SINK_SHARE_VOLUME_WITH_MASTER
: 0)
557 | (force_flat_volume
? PA_SINK_FLAT_VOLUME
: 0));
558 pa_sink_new_data_done(&sink_data
);
561 pa_log("Failed to create sink.");
565 u
->sink
->parent
.process_msg
= sink_process_msg_cb
;
566 u
->sink
->set_state
= sink_set_state_cb
;
567 u
->sink
->update_requested_latency
= sink_update_requested_latency_cb
;
568 u
->sink
->request_rewind
= sink_request_rewind_cb
;
569 u
->sink
->set_volume
= use_volume_sharing
? NULL
: sink_set_volume_cb
;
570 u
->sink
->set_mute
= sink_set_mute_cb
;
571 u
->sink
->userdata
= u
;
573 pa_sink_set_asyncmsgq(u
->sink
, master
->asyncmsgq
);
575 /* Create sink input */
576 pa_sink_input_new_data_init(&sink_input_data
);
577 sink_input_data
.driver
= __FILE__
;
578 sink_input_data
.module
= m
;
579 sink_input_data
.sink
= master
;
580 sink_input_data
.origin_sink
= u
->sink
;
581 pa_proplist_sets(sink_input_data
.proplist
, PA_PROP_MEDIA_NAME
, "Virtual Sink Stream");
582 pa_proplist_sets(sink_input_data
.proplist
, PA_PROP_MEDIA_ROLE
, "filter");
583 pa_sink_input_new_data_set_sample_spec(&sink_input_data
, &ss
);
584 pa_sink_input_new_data_set_channel_map(&sink_input_data
, &map
);
586 pa_sink_input_new(&u
->sink_input
, m
->core
, &sink_input_data
);
587 pa_sink_input_new_data_done(&sink_input_data
);
592 u
->sink_input
->pop
= sink_input_pop_cb
;
593 u
->sink_input
->process_rewind
= sink_input_process_rewind_cb
;
594 u
->sink_input
->update_max_rewind
= sink_input_update_max_rewind_cb
;
595 u
->sink_input
->update_max_request
= sink_input_update_max_request_cb
;
596 u
->sink_input
->update_sink_latency_range
= sink_input_update_sink_latency_range_cb
;
597 u
->sink_input
->update_sink_fixed_latency
= sink_input_update_sink_fixed_latency_cb
;
598 u
->sink_input
->kill
= sink_input_kill_cb
;
599 u
->sink_input
->attach
= sink_input_attach_cb
;
600 u
->sink_input
->detach
= sink_input_detach_cb
;
601 u
->sink_input
->state_change
= sink_input_state_change_cb
;
602 u
->sink_input
->may_move_to
= sink_input_may_move_to_cb
;
603 u
->sink_input
->moving
= sink_input_moving_cb
;
604 u
->sink_input
->volume_changed
= use_volume_sharing
? NULL
: sink_input_volume_changed_cb
;
605 u
->sink_input
->mute_changed
= sink_input_mute_changed_cb
;
606 u
->sink_input
->userdata
= u
;
608 u
->sink
->input_to_master
= u
->sink_input
;
610 /* (9) IF YOU REQUIRE A FIXED BLOCK SIZE MAKE SURE TO PASS A
611 * SILENCE MEMBLOCK AS LAST PARAMETER
612 * HERE. pa_sink_input_get_silence() IS USEFUL HERE. */
613 u
->memblockq
= pa_memblockq_new(0, MEMBLOCKQ_MAXLENGTH
, 0, pa_frame_size(&ss
), 1, 1, 0, NULL
);
615 /* (10) INITIALIZE ANYTHING ELSE YOU NEED HERE */
617 pa_sink_put(u
->sink
);
618 pa_sink_input_put(u
->sink_input
);
622 pa_xfree(use_default
);
630 pa_xfree(use_default
);
637 int pa__get_n_used(pa_module
*m
) {
641 pa_assert_se(u
= m
->userdata
);
643 return pa_sink_linked_by(u
->sink
);
646 void pa__done(pa_module
*m
) {
651 if (!(u
= m
->userdata
))
654 /* See comments in sink_input_kill_cb() above regarding
655 * destruction order! */
658 pa_sink_input_unlink(u
->sink_input
);
661 pa_sink_unlink(u
->sink
);
664 pa_sink_input_unref(u
->sink_input
);
667 pa_sink_unref(u
->sink
);
670 pa_memblockq_free(u
->memblockq
);