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> "
62 #define MEMBLOCKQ_MAXLENGTH (16*1024*1024)
68 pa_sink_input
*sink_input
;
70 pa_memblockq
*memblockq
;
76 static const char* const valid_modargs
[] = {
87 /* Called from I/O thread context */
88 static int sink_process_msg_cb(pa_msgobject
*o
, int code
, void *data
, int64_t offset
, pa_memchunk
*chunk
) {
89 struct userdata
*u
= PA_SINK(o
)->userdata
;
93 case PA_SINK_MESSAGE_GET_LATENCY
:
95 /* The sink is _put() before the sink input is, so let's
96 * make sure we don't access it in that time. Also, the
97 * sink input is first shut down, the sink second. */
98 if (!PA_SINK_IS_LINKED(u
->sink
->thread_info
.state
) ||
99 !PA_SINK_INPUT_IS_LINKED(u
->sink_input
->thread_info
.state
)) {
100 *((pa_usec_t
*) data
) = 0;
104 *((pa_usec_t
*) data
) =
106 /* Get the latency of the master sink */
107 pa_sink_get_latency_within_thread(u
->sink_input
->sink
) +
109 /* Add the latency internal to our sink input on top */
110 pa_bytes_to_usec(pa_memblockq_get_length(u
->sink_input
->thread_info
.render_memblockq
), &u
->sink_input
->sink
->sample_spec
);
115 return pa_sink_process_msg(o
, code
, data
, offset
, chunk
);
118 /* Called from main context */
119 static int sink_set_state_cb(pa_sink
*s
, pa_sink_state_t state
) {
122 pa_sink_assert_ref(s
);
123 pa_assert_se(u
= s
->userdata
);
125 if (!PA_SINK_IS_LINKED(state
) ||
126 !PA_SINK_INPUT_IS_LINKED(pa_sink_input_get_state(u
->sink_input
)))
129 pa_sink_input_cork(u
->sink_input
, state
== PA_SINK_SUSPENDED
);
133 /* Called from I/O thread context */
134 static void sink_request_rewind_cb(pa_sink
*s
) {
137 pa_sink_assert_ref(s
);
138 pa_assert_se(u
= s
->userdata
);
140 if (!PA_SINK_IS_LINKED(u
->sink
->thread_info
.state
) ||
141 !PA_SINK_INPUT_IS_LINKED(u
->sink_input
->thread_info
.state
))
144 /* Just hand this one over to the master sink */
145 pa_sink_input_request_rewind(u
->sink_input
,
146 s
->thread_info
.rewind_nbytes
+
147 pa_memblockq_get_length(u
->memblockq
), TRUE
, FALSE
, FALSE
);
150 /* Called from I/O thread context */
151 static void sink_update_requested_latency_cb(pa_sink
*s
) {
154 pa_sink_assert_ref(s
);
155 pa_assert_se(u
= s
->userdata
);
157 if (!PA_SINK_IS_LINKED(u
->sink
->thread_info
.state
) ||
158 !PA_SINK_INPUT_IS_LINKED(u
->sink_input
->thread_info
.state
))
161 /* Just hand this one over to the master sink */
162 pa_sink_input_set_requested_latency_within_thread(
164 pa_sink_get_requested_latency_within_thread(s
));
167 /* Called from main context */
168 static void sink_set_volume_cb(pa_sink
*s
) {
171 pa_sink_assert_ref(s
);
172 pa_assert_se(u
= s
->userdata
);
174 if (!PA_SINK_IS_LINKED(pa_sink_get_state(s
)) ||
175 !PA_SINK_INPUT_IS_LINKED(pa_sink_input_get_state(u
->sink_input
)))
178 pa_sink_input_set_volume(u
->sink_input
, &s
->real_volume
, s
->save_volume
, TRUE
);
181 /* Called from main context */
182 static void sink_set_mute_cb(pa_sink
*s
) {
185 pa_sink_assert_ref(s
);
186 pa_assert_se(u
= s
->userdata
);
188 if (!PA_SINK_IS_LINKED(pa_sink_get_state(s
)) ||
189 !PA_SINK_INPUT_IS_LINKED(pa_sink_input_get_state(u
->sink_input
)))
192 pa_sink_input_set_mute(u
->sink_input
, s
->muted
, s
->save_muted
);
195 /* Called from I/O thread context */
196 static int sink_input_pop_cb(pa_sink_input
*i
, size_t nbytes
, pa_memchunk
*chunk
) {
202 pa_usec_t curr_latency
;
204 pa_sink_input_assert_ref(i
);
206 pa_assert_se(u
= i
->userdata
);
208 /* Hmm, process any rewind request that might be queued up */
209 pa_sink_process_rewind(u
->sink
, 0);
211 while (pa_memblockq_peek(u
->memblockq
, &tchunk
) < 0) {
214 pa_sink_render(u
->sink
, nbytes
, &nchunk
);
215 pa_memblockq_push(u
->memblockq
, &nchunk
);
216 pa_memblock_unref(nchunk
.memblock
);
219 tchunk
.length
= PA_MIN(nbytes
, tchunk
.length
);
220 pa_assert(tchunk
.length
> 0);
222 fs
= pa_frame_size(&i
->sample_spec
);
223 //n = (unsigned) (PA_MIN(tchunk.length, u->block_size) / fs);
224 n
= (unsigned) (tchunk
.length
/ fs
);
229 chunk
->length
= n
*fs
;
230 chunk
->memblock
= pa_memblock_new(i
->sink
->core
->mempool
, chunk
->length
);
231 pa_assert( chunk
->memblock
);
233 pa_memblockq_drop(u
->memblockq
, chunk
->length
);
235 src
= (float*) ((uint8_t*) pa_memblock_acquire(tchunk
.memblock
) + tchunk
.index
);
236 dst
= (float*) pa_memblock_acquire(chunk
->memblock
);
238 /* PUT YOUR CODE HERE TO DO SOMETHING WITH THE DATA */
240 /* As an example, copy input to output */
241 for (c
= 0; c
< u
->channels
; c
++) {
242 pa_sample_clamp(PA_SAMPLE_FLOAT32NE
,
243 dst
+c
, u
->channels
*sizeof(float),
244 src
+c
, u
->channels
*sizeof(float),
248 pa_memblock_release(tchunk
.memblock
);
249 pa_memblock_release(chunk
->memblock
);
251 pa_memblock_unref(tchunk
.memblock
);
254 /* Get the latency of the master sink */
255 pa_sink_get_latency_within_thread(i
->sink
) +
257 /* Add the latency internal to our sink input on top */
258 pa_bytes_to_usec(pa_memblockq_get_length(i
->thread_info
.render_memblockq
), &i
->sink
->sample_spec
);
260 /* FIXME: do something with the latency */
265 /* Called from I/O thread context */
266 static void sink_input_process_rewind_cb(pa_sink_input
*i
, size_t nbytes
) {
270 pa_sink_input_assert_ref(i
);
271 pa_assert_se(u
= i
->userdata
);
273 if (u
->sink
->thread_info
.rewind_nbytes
> 0) {
276 max_rewrite
= nbytes
+ pa_memblockq_get_length(u
->memblockq
);
277 amount
= PA_MIN(u
->sink
->thread_info
.rewind_nbytes
, max_rewrite
);
278 u
->sink
->thread_info
.rewind_nbytes
= 0;
281 pa_memblockq_seek(u
->memblockq
, - (int64_t) amount
, PA_SEEK_RELATIVE
, TRUE
);
283 /* PUT YOUR CODE HERE TO RESET POST-PROCESSING */
287 pa_sink_process_rewind(u
->sink
, amount
);
288 pa_memblockq_rewind(u
->memblockq
, nbytes
);
291 /* Called from I/O thread context */
292 static void sink_input_update_max_rewind_cb(pa_sink_input
*i
, size_t nbytes
) {
295 pa_sink_input_assert_ref(i
);
296 pa_assert_se(u
= i
->userdata
);
298 pa_memblockq_set_maxrewind(u
->memblockq
, nbytes
);
299 pa_sink_set_max_rewind_within_thread(u
->sink
, nbytes
);
302 /* Called from I/O thread context */
303 static void sink_input_update_max_request_cb(pa_sink_input
*i
, size_t nbytes
) {
306 pa_sink_input_assert_ref(i
);
307 pa_assert_se(u
= i
->userdata
);
309 pa_sink_set_max_request_within_thread(u
->sink
, nbytes
);
312 /* Called from I/O thread context */
313 static void sink_input_update_sink_latency_range_cb(pa_sink_input
*i
) {
316 pa_sink_input_assert_ref(i
);
317 pa_assert_se(u
= i
->userdata
);
319 pa_sink_set_latency_range_within_thread(u
->sink
, i
->sink
->thread_info
.min_latency
, i
->sink
->thread_info
.max_latency
);
322 /* Called from I/O thread context */
323 static void sink_input_update_sink_fixed_latency_cb(pa_sink_input
*i
) {
326 pa_sink_input_assert_ref(i
);
327 pa_assert_se(u
= i
->userdata
);
329 pa_sink_set_fixed_latency_within_thread(u
->sink
, i
->sink
->thread_info
.fixed_latency
);
332 /* Called from I/O thread context */
333 static void sink_input_detach_cb(pa_sink_input
*i
) {
336 pa_sink_input_assert_ref(i
);
337 pa_assert_se(u
= i
->userdata
);
339 pa_sink_detach_within_thread(u
->sink
);
341 pa_sink_set_rtpoll(u
->sink
, NULL
);
344 /* Called from I/O thread context */
345 static void sink_input_attach_cb(pa_sink_input
*i
) {
348 pa_sink_input_assert_ref(i
);
349 pa_assert_se(u
= i
->userdata
);
351 pa_sink_set_rtpoll(u
->sink
, i
->sink
->thread_info
.rtpoll
);
352 pa_sink_set_latency_range_within_thread(u
->sink
, i
->sink
->thread_info
.min_latency
, i
->sink
->thread_info
.max_latency
);
353 pa_sink_set_fixed_latency_within_thread(u
->sink
, i
->sink
->thread_info
.fixed_latency
);
354 pa_sink_set_max_request_within_thread(u
->sink
, pa_sink_input_get_max_request(i
));
355 pa_sink_set_max_rewind_within_thread(u
->sink
, pa_sink_input_get_max_rewind(i
));
357 pa_sink_attach_within_thread(u
->sink
);
360 /* Called from main context */
361 static void sink_input_kill_cb(pa_sink_input
*i
) {
364 pa_sink_input_assert_ref(i
);
365 pa_assert_se(u
= i
->userdata
);
367 /* The order here matters! We first kill the sink input, followed
368 * by the sink. That means the sink callbacks must be protected
369 * against an unconnected sink input! */
370 pa_sink_input_unlink(u
->sink_input
);
371 pa_sink_unlink(u
->sink
);
373 pa_sink_input_unref(u
->sink_input
);
374 u
->sink_input
= NULL
;
376 pa_sink_unref(u
->sink
);
379 pa_module_unload_request(u
->module
, TRUE
);
382 /* Called from IO thread context */
383 static void sink_input_state_change_cb(pa_sink_input
*i
, pa_sink_input_state_t state
) {
386 pa_sink_input_assert_ref(i
);
387 pa_assert_se(u
= i
->userdata
);
389 /* If we are added for the first time, ask for a rewinding so that
390 * we are heard right-away. */
391 if (PA_SINK_INPUT_IS_LINKED(state
) &&
392 i
->thread_info
.state
== PA_SINK_INPUT_INIT
) {
393 pa_log_debug("Requesting rewind due to state change.");
394 pa_sink_input_request_rewind(i
, 0, FALSE
, TRUE
, TRUE
);
398 /* Called from main context */
399 static pa_bool_t
sink_input_may_move_to_cb(pa_sink_input
*i
, pa_sink
*dest
) {
402 pa_sink_input_assert_ref(i
);
403 pa_assert_se(u
= i
->userdata
);
405 return u
->sink
!= dest
;
408 /* Called from main context */
409 static void sink_input_moving_cb(pa_sink_input
*i
, pa_sink
*dest
) {
412 pa_sink_input_assert_ref(i
);
413 pa_assert_se(u
= i
->userdata
);
416 pa_sink_set_asyncmsgq(u
->sink
, dest
->asyncmsgq
);
417 pa_sink_update_flags(u
->sink
, PA_SINK_LATENCY
|PA_SINK_DYNAMIC_LATENCY
, dest
->flags
);
419 pa_sink_set_asyncmsgq(u
->sink
, NULL
);
421 if (u
->auto_desc
&& dest
) {
425 pl
= pa_proplist_new();
426 z
= pa_proplist_gets(dest
->proplist
, PA_PROP_DEVICE_DESCRIPTION
);
427 pa_proplist_setf(pl
, PA_PROP_DEVICE_DESCRIPTION
, "Virtual Sink %s on %s",
428 pa_proplist_gets(u
->sink
->proplist
, "device.vsink.name"), z
? z
: dest
->name
);
430 pa_sink_update_proplist(u
->sink
, PA_UPDATE_REPLACE
, pl
);
431 pa_proplist_free(pl
);
435 /* Called from main context */
436 static void sink_input_volume_changed_cb(pa_sink_input
*i
) {
439 pa_sink_input_assert_ref(i
);
440 pa_assert_se(u
= i
->userdata
);
442 pa_sink_volume_changed(u
->sink
, &i
->volume
);
445 /* Called from main context */
446 static void sink_input_mute_changed_cb(pa_sink_input
*i
) {
449 pa_sink_input_assert_ref(i
);
450 pa_assert_se(u
= i
->userdata
);
452 pa_sink_mute_changed(u
->sink
, i
->muted
);
455 int pa__init(pa_module
*m
) {
460 pa_sink
*master
=NULL
;
461 pa_sink_input_new_data sink_input_data
;
462 pa_sink_new_data sink_data
;
463 pa_bool_t
*use_default
= NULL
;
467 if (!(ma
= pa_modargs_new(m
->argument
, valid_modargs
))) {
468 pa_log("Failed to parse module arguments.");
472 if (!(master
= pa_namereg_get(m
->core
, pa_modargs_get_value(ma
, "master", NULL
), PA_NAMEREG_SINK
))) {
473 pa_log("Master sink not found");
479 ss
= master
->sample_spec
;
480 ss
.format
= PA_SAMPLE_FLOAT32
;
481 map
= master
->channel_map
;
482 if (pa_modargs_get_sample_spec_and_channel_map(ma
, &ss
, &map
, PA_CHANNEL_MAP_DEFAULT
) < 0) {
483 pa_log("Invalid sample format specification or channel map");
487 u
= pa_xnew0(struct userdata
, 1);
490 u
->memblockq
= pa_memblockq_new(0, MEMBLOCKQ_MAXLENGTH
, 0, pa_frame_size(&ss
), 1, 1, 0, NULL
);
491 u
->channels
= ss
.channels
;
494 pa_sink_new_data_init(&sink_data
);
495 sink_data
.driver
= __FILE__
;
496 sink_data
.module
= m
;
497 if (!(sink_data
.name
= pa_xstrdup(pa_modargs_get_value(ma
, "sink_name", NULL
))))
498 sink_data
.name
= pa_sprintf_malloc("%s.vsink", master
->name
);
499 pa_sink_new_data_set_sample_spec(&sink_data
, &ss
);
500 pa_sink_new_data_set_channel_map(&sink_data
, &map
);
501 pa_proplist_sets(sink_data
.proplist
, PA_PROP_DEVICE_MASTER_DEVICE
, master
->name
);
502 pa_proplist_sets(sink_data
.proplist
, PA_PROP_DEVICE_CLASS
, "filter");
503 pa_proplist_sets(sink_data
.proplist
, "device.vsink.name", sink_data
.name
);
505 if (pa_modargs_get_proplist(ma
, "sink_properties", sink_data
.proplist
, PA_UPDATE_REPLACE
) < 0) {
506 pa_log("Invalid properties");
507 pa_sink_new_data_done(&sink_data
);
511 if ((u
->auto_desc
= !pa_proplist_contains(sink_data
.proplist
, PA_PROP_DEVICE_DESCRIPTION
))) {
514 z
= pa_proplist_gets(master
->proplist
, PA_PROP_DEVICE_DESCRIPTION
);
515 pa_proplist_setf(sink_data
.proplist
, PA_PROP_DEVICE_DESCRIPTION
, "Virtual Sink %s on %s", sink_data
.name
, z
? z
: master
->name
);
518 u
->sink
= pa_sink_new(m
->core
, &sink_data
,
519 PA_SINK_HW_MUTE_CTRL
|PA_SINK_HW_VOLUME_CTRL
|PA_SINK_DECIBEL_VOLUME
|
520 (master
->flags
& (PA_SINK_LATENCY
|PA_SINK_DYNAMIC_LATENCY
)));
521 pa_sink_new_data_done(&sink_data
);
524 pa_log("Failed to create sink.");
528 u
->sink
->parent
.process_msg
= sink_process_msg_cb
;
529 u
->sink
->set_state
= sink_set_state_cb
;
530 u
->sink
->update_requested_latency
= sink_update_requested_latency_cb
;
531 u
->sink
->request_rewind
= sink_request_rewind_cb
;
532 u
->sink
->set_volume
= sink_set_volume_cb
;
533 u
->sink
->set_mute
= sink_set_mute_cb
;
534 u
->sink
->userdata
= u
;
536 pa_sink_set_asyncmsgq(u
->sink
, master
->asyncmsgq
);
538 /* Create sink input */
539 pa_sink_input_new_data_init(&sink_input_data
);
540 sink_input_data
.driver
= __FILE__
;
541 sink_input_data
.module
= m
;
542 sink_input_data
.sink
= master
;
543 pa_proplist_sets(sink_input_data
.proplist
, PA_PROP_MEDIA_NAME
, "Virtual Sink Stream");
544 pa_proplist_sets(sink_input_data
.proplist
, PA_PROP_MEDIA_ROLE
, "filter");
545 pa_sink_input_new_data_set_sample_spec(&sink_input_data
, &ss
);
546 pa_sink_input_new_data_set_channel_map(&sink_input_data
, &map
);
548 pa_sink_input_new(&u
->sink_input
, m
->core
, &sink_input_data
);
549 pa_sink_input_new_data_done(&sink_input_data
);
554 u
->sink_input
->pop
= sink_input_pop_cb
;
555 u
->sink_input
->process_rewind
= sink_input_process_rewind_cb
;
556 u
->sink_input
->update_max_rewind
= sink_input_update_max_rewind_cb
;
557 u
->sink_input
->update_max_request
= sink_input_update_max_request_cb
;
558 u
->sink_input
->update_sink_latency_range
= sink_input_update_sink_latency_range_cb
;
559 u
->sink_input
->update_sink_fixed_latency
= sink_input_update_sink_fixed_latency_cb
;
560 u
->sink_input
->kill
= sink_input_kill_cb
;
561 u
->sink_input
->attach
= sink_input_attach_cb
;
562 u
->sink_input
->detach
= sink_input_detach_cb
;
563 u
->sink_input
->state_change
= sink_input_state_change_cb
;
564 u
->sink_input
->may_move_to
= sink_input_may_move_to_cb
;
565 u
->sink_input
->moving
= sink_input_moving_cb
;
566 u
->sink_input
->volume_changed
= sink_input_volume_changed_cb
;
567 u
->sink_input
->mute_changed
= sink_input_mute_changed_cb
;
568 u
->sink_input
->userdata
= u
;
570 pa_sink_put(u
->sink
);
571 pa_sink_input_put(u
->sink_input
);
575 pa_xfree(use_default
);
583 pa_xfree(use_default
);
590 int pa__get_n_used(pa_module
*m
) {
594 pa_assert_se(u
= m
->userdata
);
596 return pa_sink_linked_by(u
->sink
);
599 void pa__done(pa_module
*m
) {
604 if (!(u
= m
->userdata
))
607 /* See comments in sink_input_kill_cb() above regarding
608 * destruction order! */
611 pa_sink_input_unlink(u
->sink_input
);
614 pa_sink_unlink(u
->sink
);
617 pa_sink_input_unref(u
->sink_input
);
620 pa_sink_unref(u
->sink
);
623 pa_memblockq_free(u
->memblockq
);