virtual: minor simplifications for the virtual sink
[pulseaudio-mirror.git] / src / modules / module-virtual-sink.c
blobde8ea585ae4f20cc43afec63e0c6c27f05dbe39a
1 /***
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
20 USA.
21 ***/
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. */
26 #ifdef HAVE_CONFIG_H
27 #include <config.h>
28 #endif
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);
52 PA_MODULE_USAGE(
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> "
57 "rate=<sample rate> "
58 "channels=<number of channels> "
59 "channel_map=<channel map> "
60 ));
62 #define MEMBLOCKQ_MAXLENGTH (16*1024*1024)
64 struct userdata {
65 pa_module *module;
67 pa_sink *sink;
68 pa_sink_input *sink_input;
70 pa_memblockq *memblockq;
72 pa_bool_t auto_desc;
73 unsigned channels;
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 NULL
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;
91 switch (code) {
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;
101 return 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);
112 return 0;
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) {
120 struct userdata *u;
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)))
127 return 0;
129 pa_sink_input_cork(u->sink_input, state == PA_SINK_SUSPENDED);
130 return 0;
133 /* Called from I/O thread context */
134 static void sink_request_rewind_cb(pa_sink *s) {
135 struct userdata *u;
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))
142 return;
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) {
152 struct userdata *u;
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))
159 return;
161 /* Just hand this one over to the master sink */
162 pa_sink_input_set_requested_latency_within_thread(
163 u->sink_input,
164 pa_sink_get_requested_latency_within_thread(s));
167 /* Called from main context */
168 static void sink_set_volume_cb(pa_sink *s) {
169 struct userdata *u;
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)))
176 return;
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) {
183 struct userdata *u;
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)))
190 return;
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) {
197 struct userdata *u;
198 float *src, *dst;
199 size_t fs;
200 unsigned n, c;
201 pa_memchunk tchunk;
202 pa_usec_t curr_latency;
204 pa_sink_input_assert_ref(i);
205 pa_assert(chunk);
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) {
212 pa_memchunk nchunk;
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);
226 pa_assert(n > 0);
228 chunk->index = 0;
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);
253 curr_latency =
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 */
262 return 0;
265 /* Called from I/O thread context */
266 static void sink_input_process_rewind_cb(pa_sink_input *i, size_t nbytes) {
267 struct userdata *u;
268 size_t amount = 0;
270 pa_sink_input_assert_ref(i);
271 pa_assert_se(u = i->userdata);
273 if (u->sink->thread_info.rewind_nbytes > 0) {
274 size_t max_rewrite;
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;
280 if (amount > 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) {
293 struct userdata *u;
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) {
304 struct userdata *u;
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) {
314 struct userdata *u;
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) {
324 struct userdata *u;
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) {
334 struct userdata *u;
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) {
346 struct userdata *u;
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) {
362 struct userdata *u;
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);
377 u->sink = NULL;
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) {
384 struct userdata *u;
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) {
400 struct userdata *u;
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) {
410 struct userdata *u;
412 pa_sink_input_assert_ref(i);
413 pa_assert_se(u = i->userdata);
415 if (dest) {
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);
418 } else
419 pa_sink_set_asyncmsgq(u->sink, NULL);
421 if (u->auto_desc && dest) {
422 const char *z;
423 pa_proplist *pl;
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) {
437 struct userdata *u;
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) {
447 struct userdata *u;
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) {
456 struct userdata *u;
457 pa_sample_spec ss;
458 pa_channel_map map;
459 pa_modargs *ma;
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;
465 pa_assert(m);
467 if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
468 pa_log("Failed to parse module arguments.");
469 goto fail;
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");
474 goto fail;
477 pa_assert(master);
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");
484 goto fail;
487 u = pa_xnew0(struct userdata, 1);
488 u->module = m;
489 m->userdata = u;
490 u->memblockq = pa_memblockq_new(0, MEMBLOCKQ_MAXLENGTH, 0, pa_frame_size(&ss), 1, 1, 0, NULL);
491 u->channels = ss.channels;
493 /* Create sink */
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);
508 goto fail;
511 if ((u->auto_desc = !pa_proplist_contains(sink_data.proplist, PA_PROP_DEVICE_DESCRIPTION))) {
512 const char *z;
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);
523 if (!u->sink) {
524 pa_log("Failed to create sink.");
525 goto fail;
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);
551 if (!u->sink_input)
552 goto fail;
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);
573 pa_modargs_free(ma);
575 pa_xfree(use_default);
577 return 0;
579 fail:
580 if (ma)
581 pa_modargs_free(ma);
583 pa_xfree(use_default);
585 pa__done(m);
587 return -1;
590 int pa__get_n_used(pa_module *m) {
591 struct userdata *u;
593 pa_assert(m);
594 pa_assert_se(u = m->userdata);
596 return pa_sink_linked_by(u->sink);
599 void pa__done(pa_module*m) {
600 struct userdata *u;
602 pa_assert(m);
604 if (!(u = m->userdata))
605 return;
607 /* See comments in sink_input_kill_cb() above regarding
608 * destruction order! */
610 if (u->sink_input)
611 pa_sink_input_unlink(u->sink_input);
613 if (u->sink)
614 pa_sink_unlink(u->sink);
616 if (u->sink_input)
617 pa_sink_input_unref(u->sink_input);
619 if (u->sink)
620 pa_sink_unref(u->sink);
622 if (u->memblockq)
623 pa_memblockq_free(u->memblockq);
625 pa_xfree(u);