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