]> code.delx.au - pulseaudio/blob - src/modules/module-virtual-source.c
Whitespace cleanup: Remove all multiple newlines
[pulseaudio] / src / modules / module-virtual-source.c
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, write to the Free Software
19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
20 USA.
21 ***/
22
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26
27 #include <stdio.h>
28
29 #include <pulse/xmalloc.h>
30
31 #include <pulsecore/i18n.h>
32 #include <pulsecore/macro.h>
33 #include <pulsecore/namereg.h>
34 #include <pulsecore/sink.h>
35 #include <pulsecore/module.h>
36 #include <pulsecore/core-util.h>
37 #include <pulsecore/modargs.h>
38 #include <pulsecore/log.h>
39 #include <pulsecore/rtpoll.h>
40 #include <pulsecore/sample-util.h>
41 #include <pulsecore/ltdl-helper.h>
42 #include <pulsecore/mix.h>
43
44 #include "module-virtual-source-symdef.h"
45
46 PA_MODULE_AUTHOR("Pierre-Louis Bossart");
47 PA_MODULE_DESCRIPTION("Virtual source");
48 PA_MODULE_VERSION(PACKAGE_VERSION);
49 PA_MODULE_LOAD_ONCE(FALSE);
50 PA_MODULE_USAGE(
51 _("source_name=<name for the source> "
52 "source_properties=<properties for the source> "
53 "master=<name of source to filter> "
54 "uplink_sink=<name> (optional)"
55 "format=<sample format> "
56 "rate=<sample rate> "
57 "channels=<number of channels> "
58 "channel_map=<channel map> "
59 "use_volume_sharing=<yes or no> "
60 "force_flat_volume=<yes or no> "
61 ));
62
63 #define MEMBLOCKQ_MAXLENGTH (16*1024*1024)
64 #define BLOCK_USEC 1000 /* FIXME */
65
66 struct userdata {
67 pa_module *module;
68
69 /* FIXME: Uncomment this and take "autoloaded" as a modarg if this is a filter */
70 /* pa_bool_t autoloaded; */
71
72 pa_source *source;
73 pa_source_output *source_output;
74
75 pa_memblockq *memblockq;
76
77 pa_bool_t auto_desc;
78 unsigned channels;
79
80 /* optional fields for uplink sink */
81 pa_sink *sink;
82 pa_usec_t block_usec;
83 pa_memblockq *sink_memblockq;
84
85 };
86
87 static const char* const valid_modargs[] = {
88 "source_name",
89 "source_properties",
90 "master",
91 "uplink_sink",
92 "format",
93 "rate",
94 "channels",
95 "channel_map",
96 "use_volume_sharing",
97 "force_flat_volume",
98 NULL
99 };
100
101 /* Called from I/O thread context */
102 static int sink_process_msg_cb(pa_msgobject *o, int code, void *data, int64_t offset, pa_memchunk *chunk) {
103
104 switch (code) {
105
106 case PA_SINK_MESSAGE_GET_LATENCY:
107
108 /* there's no real latency here */
109 *((pa_usec_t*) data) = 0;
110
111 return 0;
112 }
113
114 return pa_sink_process_msg(o, code, data, offset, chunk);
115 }
116
117 /* Called from main context */
118 static int sink_set_state_cb(pa_sink *s, pa_sink_state_t state) {
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 return 0;
126 }
127
128 if (state == PA_SINK_RUNNING) {
129 /* need to wake-up source if it was suspended */
130 pa_log_debug("Resuming source %s, because its uplink sink became active.", u->source->name);
131 pa_source_suspend(u->source, FALSE, PA_SUSPEND_ALL);
132
133 /* FIXME: if there's no client connected, the source will suspend
134 and playback will be stuck. You'd want to prevent the source from
135 sleeping when the uplink sink is active; even if the audio is
136 discarded at least the app isn't stuck */
137
138 } else {
139 /* nothing to do, if the sink becomes idle or suspended let
140 module-suspend-idle handle the sources later */
141 }
142
143 return 0;
144 }
145
146 static void sink_update_requested_latency_cb(pa_sink *s) {
147 struct userdata *u;
148
149 pa_sink_assert_ref(s);
150 pa_assert_se(u = s->userdata);
151
152 /* FIXME: there's no latency support */
153
154 }
155
156 /* Called from I/O thread context */
157 static void sink_request_rewind_cb(pa_sink *s) {
158 struct userdata *u;
159
160 pa_sink_assert_ref(s);
161 pa_assert_se(u = s->userdata);
162
163 /* Do nothing */
164 pa_sink_process_rewind(u->sink, 0);
165
166 }
167
168 /* Called from I/O thread context */
169 static int source_process_msg_cb(pa_msgobject *o, int code, void *data, int64_t offset, pa_memchunk *chunk) {
170 struct userdata *u = PA_SOURCE(o)->userdata;
171
172 switch (code) {
173
174 case PA_SOURCE_MESSAGE_GET_LATENCY:
175
176 /* The source is _put() before the source output is, so let's
177 * make sure we don't access it in that time. Also, the
178 * source output is first shut down, the source second. */
179 if (!PA_SOURCE_IS_LINKED(u->source->thread_info.state) ||
180 !PA_SOURCE_OUTPUT_IS_LINKED(u->source_output->thread_info.state)) {
181 *((pa_usec_t*) data) = 0;
182 return 0;
183 }
184
185 *((pa_usec_t*) data) =
186
187 /* Get the latency of the master source */
188 pa_source_get_latency_within_thread(u->source_output->source) +
189
190 /* Add the latency internal to our source output on top */
191 /* FIXME, no idea what I am doing here */
192 pa_bytes_to_usec(pa_memblockq_get_length(u->source_output->thread_info.delay_memblockq), &u->source_output->source->sample_spec);
193
194 return 0;
195 }
196
197 return pa_source_process_msg(o, code, data, offset, chunk);
198 }
199
200 /* Called from main context */
201 static int source_set_state_cb(pa_source *s, pa_source_state_t state) {
202 struct userdata *u;
203
204 pa_source_assert_ref(s);
205 pa_assert_se(u = s->userdata);
206
207 if (!PA_SOURCE_IS_LINKED(state) ||
208 !PA_SOURCE_OUTPUT_IS_LINKED(pa_source_output_get_state(u->source_output)))
209 return 0;
210
211 pa_source_output_cork(u->source_output, state == PA_SOURCE_SUSPENDED);
212 return 0;
213 }
214
215 /* Called from I/O thread context */
216 static void source_update_requested_latency_cb(pa_source *s) {
217 struct userdata *u;
218
219 pa_source_assert_ref(s);
220 pa_assert_se(u = s->userdata);
221
222 if (!PA_SOURCE_IS_LINKED(u->source->thread_info.state) ||
223 !PA_SOURCE_OUTPUT_IS_LINKED(u->source_output->thread_info.state))
224 return;
225
226 /* Just hand this one over to the master source */
227 pa_source_output_set_requested_latency_within_thread(
228 u->source_output,
229 pa_source_get_requested_latency_within_thread(s));
230 }
231
232 /* Called from main context */
233 static void source_set_volume_cb(pa_source *s) {
234 struct userdata *u;
235
236 pa_source_assert_ref(s);
237 pa_assert_se(u = s->userdata);
238
239 if (!PA_SOURCE_IS_LINKED(pa_source_get_state(s)) ||
240 !PA_SOURCE_OUTPUT_IS_LINKED(pa_source_output_get_state(u->source_output)))
241 return;
242
243 pa_source_output_set_volume(u->source_output, &s->real_volume, s->save_volume, TRUE);
244 }
245
246 /* Called from main context */
247 static void source_set_mute_cb(pa_source *s) {
248 struct userdata *u;
249
250 pa_source_assert_ref(s);
251 pa_assert_se(u = s->userdata);
252
253 if (!PA_SOURCE_IS_LINKED(pa_source_get_state(s)) ||
254 !PA_SOURCE_OUTPUT_IS_LINKED(pa_source_output_get_state(u->source_output)))
255 return;
256
257 pa_source_output_set_mute(u->source_output, s->muted, s->save_muted);
258 }
259
260 /* Called from input thread context */
261 static void source_output_push_cb(pa_source_output *o, const pa_memchunk *chunk) {
262 struct userdata *u;
263
264 pa_source_output_assert_ref(o);
265 pa_source_output_assert_io_context(o);
266 pa_assert_se(u = o->userdata);
267
268 if (!PA_SOURCE_OUTPUT_IS_LINKED(pa_source_output_get_state(u->source_output))) {
269 pa_log("push when no link?");
270 return;
271 }
272
273 /* PUT YOUR CODE HERE TO DO SOMETHING WITH THE SOURCE DATA */
274
275 /* if uplink sink exists, pull data from there; simplify by using
276 same length as chunk provided by source */
277 if (u->sink && (pa_sink_get_state(u->sink) == PA_SINK_RUNNING)) {
278 pa_memchunk tchunk;
279 size_t nbytes = chunk->length;
280 pa_mix_info streams[2];
281 pa_memchunk target_chunk;
282 void *target;
283 int ch;
284
285 /* Hmm, process any rewind request that might be queued up */
286 pa_sink_process_rewind(u->sink, 0);
287
288 /* get data from the sink */
289 while (pa_memblockq_peek(u->sink_memblockq, &tchunk) < 0) {
290 pa_memchunk nchunk;
291
292 /* make sure we get nbytes from the sink with render_full,
293 otherwise we cannot mix with the uplink */
294 pa_sink_render_full(u->sink, nbytes, &nchunk);
295 pa_memblockq_push(u->sink_memblockq, &nchunk);
296 pa_memblock_unref(nchunk.memblock);
297 }
298 pa_assert(tchunk.length == chunk->length);
299
300 /* move the read pointer for sink memblockq */
301 pa_memblockq_drop(u->sink_memblockq, tchunk.length);
302
303 /* allocate target chunk */
304 /* this could probably be done in-place, but having chunk as both
305 the input and output creates issues with reference counts */
306 target_chunk.index = 0;
307 target_chunk.length = chunk->length;
308 pa_assert(target_chunk.length == chunk->length);
309
310 target_chunk.memblock = pa_memblock_new(o->source->core->mempool,
311 target_chunk.length);
312 pa_assert( target_chunk.memblock );
313
314 /* get target pointer */
315 target = pa_memblock_acquire_chunk(&target_chunk);
316
317 /* set-up mixing structure
318 volume was taken care of in sink and source already */
319 streams[0].chunk = *chunk;
320 for(ch=0;ch<o->sample_spec.channels;ch++)
321 streams[0].volume.values[ch] = PA_VOLUME_NORM; /* FIXME */
322 streams[0].volume.channels = o->sample_spec.channels;
323
324 streams[1].chunk = tchunk;
325 for(ch=0;ch<o->sample_spec.channels;ch++)
326 streams[1].volume.values[ch] = PA_VOLUME_NORM; /* FIXME */
327 streams[1].volume.channels = o->sample_spec.channels;
328
329 /* do mixing */
330 pa_mix(streams, /* 2 streams to be mixed */
331 2,
332 target, /* put result in target chunk */
333 chunk->length, /* same length as input */
334 (const pa_sample_spec *)&o->sample_spec, /* same sample spec for input and output */
335 NULL, /* no volume information */
336 FALSE); /* no mute */
337
338 pa_memblock_release(target_chunk.memblock);
339 pa_memblock_unref(tchunk.memblock); /* clean-up */
340
341 /* forward the data to the virtual source */
342 pa_source_post(u->source, &target_chunk);
343
344 pa_memblock_unref(target_chunk.memblock); /* clean-up */
345
346 } else {
347 /* forward the data to the virtual source */
348 pa_source_post(u->source, chunk);
349 }
350
351 }
352
353 /* Called from input thread context */
354 static void source_output_process_rewind_cb(pa_source_output *o, size_t nbytes) {
355 struct userdata *u;
356
357 pa_source_output_assert_ref(o);
358 pa_source_output_assert_io_context(o);
359 pa_assert_se(u = o->userdata);
360
361 /* FIXME, no idea what I am doing here */
362 #if 0
363 pa_asyncmsgq_post(u->asyncmsgq, PA_MSGOBJECT(u->sink_input), SINK_INPUT_MESSAGE_REWIND, NULL, (int64_t) nbytes, NULL, NULL);
364 u->send_counter -= (int64_t) nbytes;
365 #endif
366 }
367
368 /* Called from output thread context */
369 static void source_output_attach_cb(pa_source_output *o) {
370 struct userdata *u;
371
372 pa_source_output_assert_ref(o);
373 pa_source_output_assert_io_context(o);
374 pa_assert_se(u = o->userdata);
375
376 pa_source_set_rtpoll(u->source, o->source->thread_info.rtpoll);
377 pa_source_set_latency_range_within_thread(u->source, o->source->thread_info.min_latency, o->source->thread_info.max_latency);
378 pa_source_set_fixed_latency_within_thread(u->source, o->source->thread_info.fixed_latency);
379 pa_source_set_max_rewind_within_thread(u->source, pa_source_output_get_max_rewind(o));
380
381 pa_source_attach_within_thread(u->source);
382 }
383
384 /* Called from output thread context */
385 static void source_output_detach_cb(pa_source_output *o) {
386 struct userdata *u;
387
388 pa_source_output_assert_ref(o);
389 pa_source_output_assert_io_context(o);
390 pa_assert_se(u = o->userdata);
391
392 pa_source_detach_within_thread(u->source);
393 pa_source_set_rtpoll(u->source, NULL);
394 }
395
396 /* Called from output thread context */
397 static void source_output_state_change_cb(pa_source_output *o, pa_source_output_state_t state) {
398 struct userdata *u;
399
400 pa_source_output_assert_ref(o);
401 pa_source_output_assert_io_context(o);
402 pa_assert_se(u = o->userdata);
403
404 /* FIXME */
405 #if 0
406 if (PA_SOURCE_OUTPUT_IS_LINKED(state) && o->thread_info.state == PA_SOURCE_OUTPUT_INIT) {
407
408 u->skip = pa_usec_to_bytes(PA_CLIP_SUB(pa_source_get_latency_within_thread(o->source),
409 u->latency),
410 &o->sample_spec);
411
412 pa_log_info("Skipping %lu bytes", (unsigned long) u->skip);
413 }
414 #endif
415 }
416
417 /* Called from main thread */
418 static void source_output_kill_cb(pa_source_output *o) {
419 struct userdata *u;
420
421 pa_source_output_assert_ref(o);
422 pa_assert_ctl_context();
423 pa_assert_se(u = o->userdata);
424
425 /* The order here matters! We first kill the source output, followed
426 * by the source. That means the source callbacks must be protected
427 * against an unconnected source output! */
428 pa_source_output_unlink(u->source_output);
429 pa_source_unlink(u->source);
430
431 pa_source_output_unref(u->source_output);
432 u->source_output = NULL;
433
434 pa_source_unref(u->source);
435 u->source = NULL;
436
437 pa_module_unload_request(u->module, TRUE);
438 }
439
440 /* Called from main thread */
441 static void source_output_moving_cb(pa_source_output *o, pa_source *dest) {
442 struct userdata *u;
443
444 pa_source_output_assert_ref(o);
445 pa_assert_ctl_context();
446 pa_assert_se(u = o->userdata);
447
448 if (dest) {
449 pa_source_set_asyncmsgq(u->source, dest->asyncmsgq);
450 pa_source_update_flags(u->source, PA_SOURCE_LATENCY|PA_SOURCE_DYNAMIC_LATENCY, dest->flags);
451 } else
452 pa_source_set_asyncmsgq(u->source, NULL);
453
454 if (u->auto_desc && dest) {
455 const char *z;
456 pa_proplist *pl;
457
458 pl = pa_proplist_new();
459 z = pa_proplist_gets(dest->proplist, PA_PROP_DEVICE_DESCRIPTION);
460 pa_proplist_setf(pl, PA_PROP_DEVICE_DESCRIPTION, "Virtual Source %s on %s",
461 pa_proplist_gets(u->source->proplist, "device.vsource.name"), z ? z : dest->name);
462
463 pa_source_update_proplist(u->source, PA_UPDATE_REPLACE, pl);
464 pa_proplist_free(pl);
465 }
466 }
467
468 int pa__init(pa_module*m) {
469 struct userdata *u;
470 pa_sample_spec ss;
471 pa_channel_map map;
472 pa_modargs *ma;
473 pa_source *master=NULL;
474 pa_source_output_new_data source_output_data;
475 pa_source_new_data source_data;
476 pa_bool_t use_volume_sharing = TRUE;
477 pa_bool_t force_flat_volume = FALSE;
478
479 /* optional for uplink_sink */
480 pa_sink_new_data sink_data;
481 size_t nbytes;
482
483 pa_assert(m);
484
485 if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
486 pa_log("Failed to parse module arguments.");
487 goto fail;
488 }
489
490 if (!(master = pa_namereg_get(m->core, pa_modargs_get_value(ma, "master", NULL), PA_NAMEREG_SOURCE))) {
491 pa_log("Master source not found");
492 goto fail;
493 }
494
495 pa_assert(master);
496
497 ss = master->sample_spec;
498 ss.format = PA_SAMPLE_FLOAT32;
499 map = master->channel_map;
500 if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map, PA_CHANNEL_MAP_DEFAULT) < 0) {
501 pa_log("Invalid sample format specification or channel map");
502 goto fail;
503 }
504
505 if (pa_modargs_get_value_boolean(ma, "use_volume_sharing", &use_volume_sharing) < 0) {
506 pa_log("use_volume_sharing= expects a boolean argument");
507 goto fail;
508 }
509
510 if (pa_modargs_get_value_boolean(ma, "force_flat_volume", &force_flat_volume) < 0) {
511 pa_log("force_flat_volume= expects a boolean argument");
512 goto fail;
513 }
514
515 if (use_volume_sharing && force_flat_volume) {
516 pa_log("Flat volume can't be forced when using volume sharing.");
517 goto fail;
518 }
519
520 u = pa_xnew0(struct userdata, 1);
521 u->module = m;
522 m->userdata = u;
523 u->memblockq = pa_memblockq_new("module-virtual-source memblockq", 0, MEMBLOCKQ_MAXLENGTH, 0, &ss, 1, 1, 0, NULL);
524 if (!u->memblockq) {
525 pa_log("Failed to create source memblockq.");
526 goto fail;
527 }
528 u->channels = ss.channels;
529
530 /* Create source */
531 pa_source_new_data_init(&source_data);
532 source_data.driver = __FILE__;
533 source_data.module = m;
534 if (!(source_data.name = pa_xstrdup(pa_modargs_get_value(ma, "source_name", NULL))))
535 source_data.name = pa_sprintf_malloc("%s.vsource", master->name);
536 pa_source_new_data_set_sample_spec(&source_data, &ss);
537 pa_source_new_data_set_channel_map(&source_data, &map);
538 pa_proplist_sets(source_data.proplist, PA_PROP_DEVICE_MASTER_DEVICE, master->name);
539 pa_proplist_sets(source_data.proplist, PA_PROP_DEVICE_CLASS, "filter");
540 pa_proplist_sets(source_data.proplist, "device.vsource.name", source_data.name);
541
542 if (pa_modargs_get_proplist(ma, "source_properties", source_data.proplist, PA_UPDATE_REPLACE) < 0) {
543 pa_log("Invalid properties");
544 pa_source_new_data_done(&source_data);
545 goto fail;
546 }
547
548 if ((u->auto_desc = !pa_proplist_contains(source_data.proplist, PA_PROP_DEVICE_DESCRIPTION))) {
549 const char *z;
550
551 z = pa_proplist_gets(master->proplist, PA_PROP_DEVICE_DESCRIPTION);
552 pa_proplist_setf(source_data.proplist, PA_PROP_DEVICE_DESCRIPTION, "Virtual Source %s on %s", source_data.name, z ? z : master->name);
553 }
554
555 u->source = pa_source_new(m->core, &source_data, (master->flags & (PA_SOURCE_LATENCY|PA_SOURCE_DYNAMIC_LATENCY))
556 | (use_volume_sharing ? PA_SOURCE_SHARE_VOLUME_WITH_MASTER : 0));
557
558 pa_source_new_data_done(&source_data);
559
560 if (!u->source) {
561 pa_log("Failed to create source.");
562 goto fail;
563 }
564
565 u->source->parent.process_msg = source_process_msg_cb;
566 u->source->set_state = source_set_state_cb;
567 u->source->update_requested_latency = source_update_requested_latency_cb;
568 pa_source_set_set_mute_callback(u->source, source_set_mute_cb);
569 if (!use_volume_sharing) {
570 pa_source_set_set_volume_callback(u->source, source_set_volume_cb);
571 pa_source_enable_decibel_volume(u->source, TRUE);
572 }
573 /* Normally this flag would be enabled automatically be we can force it. */
574 if (force_flat_volume)
575 u->source->flags |= PA_SOURCE_FLAT_VOLUME;
576 u->source->userdata = u;
577
578 pa_source_set_asyncmsgq(u->source, master->asyncmsgq);
579
580 /* Create source output */
581 pa_source_output_new_data_init(&source_output_data);
582 source_output_data.driver = __FILE__;
583 source_output_data.module = m;
584 pa_source_output_new_data_set_source(&source_output_data, master, FALSE);
585 source_output_data.destination_source = u->source;
586
587 pa_proplist_setf(source_output_data.proplist, PA_PROP_MEDIA_NAME, "Virtual Source Stream of %s", pa_proplist_gets(u->source->proplist, PA_PROP_DEVICE_DESCRIPTION));
588 pa_proplist_sets(source_output_data.proplist, PA_PROP_MEDIA_ROLE, "filter");
589 pa_source_output_new_data_set_sample_spec(&source_output_data, &ss);
590 pa_source_output_new_data_set_channel_map(&source_output_data, &map);
591
592 pa_source_output_new(&u->source_output, m->core, &source_output_data);
593 pa_source_output_new_data_done(&source_output_data);
594
595 if (!u->source_output)
596 goto fail;
597
598 u->source_output->push = source_output_push_cb;
599 u->source_output->process_rewind = source_output_process_rewind_cb;
600 u->source_output->kill = source_output_kill_cb;
601 u->source_output->attach = source_output_attach_cb;
602 u->source_output->detach = source_output_detach_cb;
603 u->source_output->state_change = source_output_state_change_cb;
604 u->source_output->moving = source_output_moving_cb;
605 u->source_output->userdata = u;
606
607 u->source->output_from_master = u->source_output;
608
609 pa_source_put(u->source);
610 pa_source_output_put(u->source_output);
611
612 /* Create optional uplink sink */
613 pa_sink_new_data_init(&sink_data);
614 sink_data.driver = __FILE__;
615 sink_data.module = m;
616 if ((sink_data.name = pa_xstrdup(pa_modargs_get_value(ma, "uplink_sink", NULL)))) {
617 pa_sink_new_data_set_sample_spec(&sink_data, &ss);
618 pa_sink_new_data_set_channel_map(&sink_data, &map);
619 pa_proplist_sets(sink_data.proplist, PA_PROP_DEVICE_MASTER_DEVICE, master->name);
620 pa_proplist_sets(sink_data.proplist, PA_PROP_DEVICE_CLASS, "uplink sink");
621 pa_proplist_sets(sink_data.proplist, "device.uplink_sink.name", sink_data.name);
622
623 if ((u->auto_desc = !pa_proplist_contains(sink_data.proplist, PA_PROP_DEVICE_DESCRIPTION))) {
624 const char *z;
625
626 z = pa_proplist_gets(master->proplist, PA_PROP_DEVICE_DESCRIPTION);
627 pa_proplist_setf(sink_data.proplist, PA_PROP_DEVICE_DESCRIPTION, "Uplink Sink %s on %s", sink_data.name, z ? z : master->name);
628 }
629
630 u->sink_memblockq = pa_memblockq_new("module-virtual-source sink_memblockq", 0, MEMBLOCKQ_MAXLENGTH, 0, &ss, 1, 1, 0, NULL);
631 if (!u->sink_memblockq) {
632 pa_sink_new_data_done(&sink_data);
633 pa_log("Failed to create sink memblockq.");
634 goto fail;
635 }
636
637 u->sink = pa_sink_new(m->core, &sink_data, 0); /* FIXME, sink has no capabilities */
638 pa_sink_new_data_done(&sink_data);
639
640 if (!u->sink) {
641 pa_log("Failed to create sink.");
642 goto fail;
643 }
644
645 u->sink->parent.process_msg = sink_process_msg_cb;
646 u->sink->update_requested_latency = sink_update_requested_latency_cb;
647 u->sink->request_rewind = sink_request_rewind_cb;
648 u->sink->set_state = sink_set_state_cb;
649 u->sink->userdata = u;
650
651 pa_sink_set_asyncmsgq(u->sink, master->asyncmsgq);
652
653 /* FIXME: no idea what I am doing here */
654 u->block_usec = BLOCK_USEC;
655 nbytes = pa_usec_to_bytes(u->block_usec, &u->sink->sample_spec);
656 pa_sink_set_max_rewind(u->sink, nbytes);
657 pa_sink_set_max_request(u->sink, nbytes);
658
659 pa_sink_put(u->sink);
660 } else {
661 pa_sink_new_data_done(&sink_data);
662 /* optional uplink sink not enabled */
663 u->sink = NULL;
664 }
665
666 pa_modargs_free(ma);
667
668 return 0;
669
670 fail:
671 if (ma)
672 pa_modargs_free(ma);
673
674 pa__done(m);
675
676 return -1;
677 }
678
679 int pa__get_n_used(pa_module *m) {
680 struct userdata *u;
681
682 pa_assert(m);
683 pa_assert_se(u = m->userdata);
684
685 return pa_source_linked_by(u->source);
686 }
687
688 void pa__done(pa_module*m) {
689 struct userdata *u;
690
691 pa_assert(m);
692
693 if (!(u = m->userdata))
694 return;
695
696 /* See comments in source_output_kill_cb() above regarding
697 * destruction order! */
698
699 if (u->source_output)
700 pa_source_output_unlink(u->source_output);
701
702 if (u->source)
703 pa_source_unlink(u->source);
704
705 if (u->source_output)
706 pa_source_output_unref(u->source_output);
707
708 if (u->source)
709 pa_source_unref(u->source);
710
711 if (u->sink)
712 pa_sink_unref(u->sink);
713
714 if (u->memblockq)
715 pa_memblockq_free(u->memblockq);
716
717 if (u->sink_memblockq)
718 pa_memblockq_free(u->sink_memblockq);
719
720 pa_xfree(u);
721 }