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             /* Add resampler delay */
181             *((int64_t*) data) += pa_resampler_get_delay_usec(u->source_output->thread_info.resampler);
182 
183             return 0;
184     }
185 
186     return pa_source_process_msg(o, code, data, offset, chunk);
187 }
188 
189 /* 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)190 static int source_set_state_in_main_thread_cb(pa_source *s, pa_source_state_t state, pa_suspend_cause_t suspend_cause) {
191     struct userdata *u;
192 
193     pa_source_assert_ref(s);
194     pa_assert_se(u = s->userdata);
195 
196     if (!PA_SOURCE_IS_LINKED(state) ||
197         !PA_SOURCE_OUTPUT_IS_LINKED(u->source_output->state))
198         return 0;
199 
200     pa_source_output_cork(u->source_output, state == PA_SOURCE_SUSPENDED);
201     return 0;
202 }
203 
204 /* Called from I/O thread context */
source_update_requested_latency_cb(pa_source *s)205 static void source_update_requested_latency_cb(pa_source *s) {
206     struct userdata *u;
207 
208     pa_source_assert_ref(s);
209     pa_assert_se(u = s->userdata);
210 
211     if (!PA_SOURCE_IS_LINKED(u->source->thread_info.state) ||
212         !PA_SOURCE_OUTPUT_IS_LINKED(u->source_output->thread_info.state))
213         return;
214 
215     /* Just hand this one over to the master source */
216     pa_source_output_set_requested_latency_within_thread(
217             u->source_output,
218             pa_source_get_requested_latency_within_thread(s));
219 }
220 
221 /* Called from main context */
source_set_volume_cb(pa_source *s)222 static void source_set_volume_cb(pa_source *s) {
223     struct userdata *u;
224 
225     pa_source_assert_ref(s);
226     pa_assert_se(u = s->userdata);
227 
228     if (!PA_SOURCE_IS_LINKED(s->state) ||
229         !PA_SOURCE_OUTPUT_IS_LINKED(u->source_output->state))
230         return;
231 
232     pa_source_output_set_volume(u->source_output, &s->real_volume, s->save_volume, true);
233 }
234 
235 /* Called from main context */
source_set_mute_cb(pa_source *s)236 static void source_set_mute_cb(pa_source *s) {
237     struct userdata *u;
238 
239     pa_source_assert_ref(s);
240     pa_assert_se(u = s->userdata);
241 
242     if (!PA_SOURCE_IS_LINKED(s->state) ||
243         !PA_SOURCE_OUTPUT_IS_LINKED(u->source_output->state))
244         return;
245 
246     pa_source_output_set_mute(u->source_output, s->muted, s->save_muted);
247 }
248 
249 /* Called from input thread context */
source_output_push_cb(pa_source_output *o, const pa_memchunk *chunk)250 static void source_output_push_cb(pa_source_output *o, const pa_memchunk *chunk) {
251     struct userdata *u;
252 
253     pa_source_output_assert_ref(o);
254     pa_source_output_assert_io_context(o);
255     pa_assert_se(u = o->userdata);
256 
257     if (!PA_SOURCE_IS_LINKED(u->source->thread_info.state))
258         return;
259 
260     if (!PA_SOURCE_OUTPUT_IS_LINKED(u->source_output->thread_info.state)) {
261         pa_log("push when no link?");
262         return;
263     }
264 
265     /* PUT YOUR CODE HERE TO DO SOMETHING WITH THE SOURCE DATA */
266 
267     /* if uplink sink exists, pull data from there; simplify by using
268        same length as chunk provided by source */
269     if (u->sink && (u->sink->thread_info.state == PA_SINK_RUNNING)) {
270         pa_memchunk tchunk;
271         size_t nbytes = chunk->length;
272         pa_mix_info streams[2];
273         pa_memchunk target_chunk;
274         void *target;
275         int ch;
276 
277         /* Hmm, process any rewind request that might be queued up */
278         pa_sink_process_rewind(u->sink, 0);
279 
280         /* get data from the sink */
281         while (pa_memblockq_peek(u->sink_memblockq, &tchunk) < 0) {
282             pa_memchunk nchunk;
283 
284             /* make sure we get nbytes from the sink with render_full,
285                otherwise we cannot mix with the uplink */
286             pa_sink_render_full(u->sink, nbytes, &nchunk);
287             pa_memblockq_push(u->sink_memblockq, &nchunk);
288             pa_memblock_unref(nchunk.memblock);
289         }
290         pa_assert(tchunk.length == chunk->length);
291 
292         /* move the read pointer for sink memblockq */
293         pa_memblockq_drop(u->sink_memblockq, tchunk.length);
294 
295         /* allocate target chunk */
296         /* this could probably be done in-place, but having chunk as both
297            the input and output creates issues with reference counts */
298         target_chunk.index = 0;
299         target_chunk.length = chunk->length;
300         pa_assert(target_chunk.length == chunk->length);
301 
302         target_chunk.memblock = pa_memblock_new(o->source->core->mempool,
303                                                 target_chunk.length);
304         pa_assert( target_chunk.memblock );
305 
306         /* get target pointer */
307         target = pa_memblock_acquire_chunk(&target_chunk);
308 
309         /* set-up mixing structure
310            volume was taken care of in sink and source already */
311         streams[0].chunk = *chunk;
312         for(ch=0;ch<o->sample_spec.channels;ch++)
313             streams[0].volume.values[ch] = PA_VOLUME_NORM; /* FIXME */
314         streams[0].volume.channels = o->sample_spec.channels;
315 
316         streams[1].chunk = tchunk;
317         for(ch=0;ch<o->sample_spec.channels;ch++)
318             streams[1].volume.values[ch] = PA_VOLUME_NORM; /* FIXME */
319         streams[1].volume.channels = o->sample_spec.channels;
320 
321         /* do mixing */
322         pa_mix(streams,                /* 2 streams to be mixed */
323                2,
324                target,                 /* put result in target chunk */
325                chunk->length,          /* same length as input */
326                (const pa_sample_spec *)&o->sample_spec, /* same sample spec for input and output */
327                NULL,                   /* no volume information */
328                false);                 /* no mute */
329 
330         pa_memblock_release(target_chunk.memblock);
331         pa_memblock_unref(tchunk.memblock); /* clean-up */
332 
333         /* forward the data to the virtual source */
334         pa_source_post(u->source, &target_chunk);
335 
336         pa_memblock_unref(target_chunk.memblock); /* clean-up */
337 
338     } else {
339         /* forward the data to the virtual source */
340         pa_source_post(u->source, chunk);
341     }
342 
343 }
344 
345 /* Called from input thread context */
source_output_process_rewind_cb(pa_source_output *o, size_t nbytes)346 static void source_output_process_rewind_cb(pa_source_output *o, size_t nbytes) {
347     struct userdata *u;
348 
349     pa_source_output_assert_ref(o);
350     pa_source_output_assert_io_context(o);
351     pa_assert_se(u = o->userdata);
352 
353     /* If the source is not yet linked, there is nothing to rewind */
354     if (PA_SOURCE_IS_LINKED(u->source->thread_info.state))
355         pa_source_process_rewind(u->source, nbytes);
356 
357     /* FIXME, no idea what I am doing here */
358 #if 0
359     pa_asyncmsgq_post(u->asyncmsgq, PA_MSGOBJECT(u->sink_input), SINK_INPUT_MESSAGE_REWIND, NULL, (int64_t) nbytes, NULL, NULL);
360     u->send_counter -= (int64_t) nbytes;
361 #endif
362 }
363 
364 /* Called from output thread context */
source_output_update_max_rewind_cb(pa_source_output *o, size_t nbytes)365 static void source_output_update_max_rewind_cb(pa_source_output *o, size_t nbytes) {
366     struct userdata *u;
367 
368     pa_source_output_assert_ref(o);
369     pa_source_output_assert_io_context(o);
370     pa_assert_se(u = o->userdata);
371 
372     pa_source_set_max_rewind_within_thread(u->source, nbytes);
373 }
374 
375 /* Called from output thread context */
source_output_attach_cb(pa_source_output *o)376 static void source_output_attach_cb(pa_source_output *o) {
377     struct userdata *u;
378 
379     pa_source_output_assert_ref(o);
380     pa_source_output_assert_io_context(o);
381     pa_assert_se(u = o->userdata);
382 
383     pa_source_set_rtpoll(u->source, o->source->thread_info.rtpoll);
384     pa_source_set_latency_range_within_thread(u->source, o->source->thread_info.min_latency, o->source->thread_info.max_latency);
385     pa_source_set_fixed_latency_within_thread(u->source, o->source->thread_info.fixed_latency);
386     pa_source_set_max_rewind_within_thread(u->source, pa_source_output_get_max_rewind(o));
387 
388     if (PA_SOURCE_IS_LINKED(u->source->thread_info.state))
389         pa_source_attach_within_thread(u->source);
390 }
391 
392 /* Called from output thread context */
source_output_detach_cb(pa_source_output *o)393 static void source_output_detach_cb(pa_source_output *o) {
394     struct userdata *u;
395 
396     pa_source_output_assert_ref(o);
397     pa_source_output_assert_io_context(o);
398     pa_assert_se(u = o->userdata);
399 
400     if (PA_SOURCE_IS_LINKED(u->source->thread_info.state))
401         pa_source_detach_within_thread(u->source);
402     pa_source_set_rtpoll(u->source, NULL);
403 }
404 
405 /* 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)406 static void source_output_state_change_cb(pa_source_output *o, pa_source_output_state_t state) {
407     struct userdata *u;
408 
409     pa_source_output_assert_ref(o);
410     pa_assert_se(u = o->userdata);
411 
412     /* FIXME */
413 #if 0
414     if (PA_SOURCE_OUTPUT_IS_LINKED(state) && o->thread_info.state == PA_SOURCE_OUTPUT_INIT && o->source) {
415 
416         u->skip = pa_usec_to_bytes(PA_CLIP_SUB(pa_source_get_latency_within_thread(o->source, false),
417                                                u->latency),
418                                    &o->sample_spec);
419 
420         pa_log_info("Skipping %lu bytes", (unsigned long) u->skip);
421     }
422 #endif
423 }
424 
425 /* Called from main thread */
source_output_kill_cb(pa_source_output *o)426 static void source_output_kill_cb(pa_source_output *o) {
427     struct userdata *u;
428 
429     pa_source_output_assert_ref(o);
430     pa_assert_ctl_context();
431     pa_assert_se(u = o->userdata);
432 
433     /* The order here matters! We first kill the source so that streams
434      * can properly be moved away while the source output is still connected
435      * to the master. */
436     pa_source_output_cork(u->source_output, true);
437     pa_source_unlink(u->source);
438     pa_source_output_unlink(u->source_output);
439 
440     pa_source_output_unref(u->source_output);
441     u->source_output = NULL;
442 
443     pa_source_unref(u->source);
444     u->source = NULL;
445 
446     pa_module_unload_request(u->module, true);
447 }
448 
449 /* Called from main thread */
source_output_moving_cb(pa_source_output *o, pa_source *dest)450 static void source_output_moving_cb(pa_source_output *o, pa_source *dest) {
451     struct userdata *u;
452     uint32_t idx;
453     pa_source_output *output;
454 
455     pa_source_output_assert_ref(o);
456     pa_assert_ctl_context();
457     pa_assert_se(u = o->userdata);
458 
459     if (dest) {
460         pa_source_set_asyncmsgq(u->source, dest->asyncmsgq);
461         pa_source_update_flags(u->source, PA_SOURCE_LATENCY|PA_SOURCE_DYNAMIC_LATENCY, dest->flags);
462     } else
463         pa_source_set_asyncmsgq(u->source, NULL);
464 
465     /* Propagate asyncmsq change to attached virtual sources */
466     PA_IDXSET_FOREACH(output, u->source->outputs, idx) {
467         if (output->destination_source && output->moving)
468             output->moving(output, u->source);
469     }
470 
471     if (u->auto_desc && dest) {
472         const char *z;
473         pa_proplist *pl;
474 
475         pl = pa_proplist_new();
476         z = pa_proplist_gets(dest->proplist, PA_PROP_DEVICE_DESCRIPTION);
477         pa_proplist_setf(pl, PA_PROP_DEVICE_DESCRIPTION, "Virtual Source %s on %s",
478                          pa_proplist_gets(u->source->proplist, "device.vsource.name"), z ? z : dest->name);
479 
480         pa_source_update_proplist(u->source, PA_UPDATE_REPLACE, pl);
481         pa_proplist_free(pl);
482     }
483 }
484 
pa__init(pa_module*m)485 int pa__init(pa_module*m) {
486     struct userdata *u;
487     pa_sample_spec ss;
488     pa_channel_map map;
489     pa_modargs *ma;
490     pa_source *master=NULL;
491     pa_source_output_new_data source_output_data;
492     pa_source_new_data source_data;
493     bool use_volume_sharing = true;
494     bool force_flat_volume = false;
495 
496     /* optional for uplink_sink */
497     pa_sink_new_data sink_data;
498     size_t nbytes;
499 
500     pa_assert(m);
501 
502     if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
503         pa_log("Failed to parse module arguments.");
504         goto fail;
505     }
506 
507     if (!(master = pa_namereg_get(m->core, pa_modargs_get_value(ma, "master", NULL), PA_NAMEREG_SOURCE))) {
508         pa_log("Master source not found");
509         goto fail;
510     }
511 
512     pa_assert(master);
513 
514     ss = master->sample_spec;
515     ss.format = PA_SAMPLE_FLOAT32;
516     map = master->channel_map;
517     if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map, PA_CHANNEL_MAP_DEFAULT) < 0) {
518         pa_log("Invalid sample format specification or channel map");
519         goto fail;
520     }
521 
522     if (pa_modargs_get_value_boolean(ma, "use_volume_sharing", &use_volume_sharing) < 0) {
523         pa_log("use_volume_sharing= expects a boolean argument");
524         goto fail;
525     }
526 
527     if (pa_modargs_get_value_boolean(ma, "force_flat_volume", &force_flat_volume) < 0) {
528         pa_log("force_flat_volume= expects a boolean argument");
529         goto fail;
530     }
531 
532     if (use_volume_sharing && force_flat_volume) {
533         pa_log("Flat volume can't be forced when using volume sharing.");
534         goto fail;
535     }
536 
537     u = pa_xnew0(struct userdata, 1);
538     u->module = m;
539     m->userdata = u;
540     u->memblockq = pa_memblockq_new("module-virtual-source memblockq", 0, MEMBLOCKQ_MAXLENGTH, 0, &ss, 1, 1, 0, NULL);
541     if (!u->memblockq) {
542         pa_log("Failed to create source memblockq.");
543         goto fail;
544     }
545     u->channels = ss.channels;
546 
547     /* The rtpoll created here is never run. It is only necessary to avoid crashes
548      * when module-virtual-source is used together with module-loopback or
549      * module-combine-sink. Both modules base their asyncmsq on the rtpoll provided
550      * by the sink. module-loopback and combine-sink only work because they
551      * call pa_asyncmsq_process_one() themselves. */
552     u->rtpoll = pa_rtpoll_new();
553 
554     /* Create source */
555     pa_source_new_data_init(&source_data);
556     source_data.driver = __FILE__;
557     source_data.module = m;
558     if (!(source_data.name = pa_xstrdup(pa_modargs_get_value(ma, "source_name", NULL))))
559         source_data.name = pa_sprintf_malloc("%s.vsource", master->name);
560     pa_source_new_data_set_sample_spec(&source_data, &ss);
561     pa_source_new_data_set_channel_map(&source_data, &map);
562     pa_proplist_sets(source_data.proplist, PA_PROP_DEVICE_MASTER_DEVICE, master->name);
563     pa_proplist_sets(source_data.proplist, PA_PROP_DEVICE_CLASS, "filter");
564     pa_proplist_sets(source_data.proplist, "device.vsource.name", source_data.name);
565 
566     if (pa_modargs_get_proplist(ma, "source_properties", source_data.proplist, PA_UPDATE_REPLACE) < 0) {
567         pa_log("Invalid properties");
568         pa_source_new_data_done(&source_data);
569         goto fail;
570     }
571 
572     if ((u->auto_desc = !pa_proplist_contains(source_data.proplist, PA_PROP_DEVICE_DESCRIPTION))) {
573         const char *z;
574 
575         z = pa_proplist_gets(master->proplist, PA_PROP_DEVICE_DESCRIPTION);
576         pa_proplist_setf(source_data.proplist, PA_PROP_DEVICE_DESCRIPTION, "Virtual Source %s on %s", source_data.name, z ? z : master->name);
577     }
578 
579     u->source = pa_source_new(m->core, &source_data, (master->flags & (PA_SOURCE_LATENCY|PA_SOURCE_DYNAMIC_LATENCY))
580                                                      | (use_volume_sharing ? PA_SOURCE_SHARE_VOLUME_WITH_MASTER : 0));
581 
582     pa_source_new_data_done(&source_data);
583 
584     if (!u->source) {
585         pa_log("Failed to create source.");
586         goto fail;
587     }
588 
589     u->source->parent.process_msg = source_process_msg_cb;
590     u->source->set_state_in_main_thread = source_set_state_in_main_thread_cb;
591     u->source->update_requested_latency = source_update_requested_latency_cb;
592     pa_source_set_set_mute_callback(u->source, source_set_mute_cb);
593     if (!use_volume_sharing) {
594         pa_source_set_set_volume_callback(u->source, source_set_volume_cb);
595         pa_source_enable_decibel_volume(u->source, true);
596     }
597     /* Normally this flag would be enabled automatically be we can force it. */
598     if (force_flat_volume)
599         u->source->flags |= PA_SOURCE_FLAT_VOLUME;
600     u->source->userdata = u;
601 
602     pa_source_set_asyncmsgq(u->source, master->asyncmsgq);
603 
604     /* Create source output */
605     pa_source_output_new_data_init(&source_output_data);
606     source_output_data.driver = __FILE__;
607     source_output_data.module = m;
608     pa_source_output_new_data_set_source(&source_output_data, master, false, true);
609     source_output_data.destination_source = u->source;
610 
611     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));
612     pa_proplist_sets(source_output_data.proplist, PA_PROP_MEDIA_ROLE, "filter");
613     pa_source_output_new_data_set_sample_spec(&source_output_data, &ss);
614     pa_source_output_new_data_set_channel_map(&source_output_data, &map);
615     source_output_data.flags |= PA_SOURCE_OUTPUT_START_CORKED;
616 
617     pa_source_output_new(&u->source_output, m->core, &source_output_data);
618     pa_source_output_new_data_done(&source_output_data);
619 
620     if (!u->source_output)
621         goto fail;
622 
623     u->source_output->push = source_output_push_cb;
624     u->source_output->process_rewind = source_output_process_rewind_cb;
625     u->source_output->update_max_rewind = source_output_update_max_rewind_cb;
626     u->source_output->kill = source_output_kill_cb;
627     u->source_output->attach = source_output_attach_cb;
628     u->source_output->detach = source_output_detach_cb;
629     u->source_output->state_change = source_output_state_change_cb;
630     u->source_output->moving = source_output_moving_cb;
631     u->source_output->userdata = u;
632 
633     u->source->output_from_master = u->source_output;
634 
635     /* The order here is important. The output must be put first,
636      * otherwise streams might attach to the source before the
637      * source output is attached to the master. */
638     pa_source_output_put(u->source_output);
639     pa_source_put(u->source);
640     pa_source_output_cork(u->source_output, false);
641 
642     /* Create optional uplink sink */
643     pa_sink_new_data_init(&sink_data);
644     sink_data.driver = __FILE__;
645     sink_data.module = m;
646     if ((sink_data.name = pa_xstrdup(pa_modargs_get_value(ma, "uplink_sink", NULL)))) {
647         pa_sink_new_data_set_sample_spec(&sink_data, &ss);
648         pa_sink_new_data_set_channel_map(&sink_data, &map);
649         pa_proplist_sets(sink_data.proplist, PA_PROP_DEVICE_MASTER_DEVICE, master->name);
650         pa_proplist_sets(sink_data.proplist, PA_PROP_DEVICE_CLASS, "uplink sink");
651         pa_proplist_sets(sink_data.proplist, "device.uplink_sink.name", sink_data.name);
652 
653         if ((u->auto_desc = !pa_proplist_contains(sink_data.proplist, PA_PROP_DEVICE_DESCRIPTION))) {
654             const char *z;
655 
656             z = pa_proplist_gets(master->proplist, PA_PROP_DEVICE_DESCRIPTION);
657             pa_proplist_setf(sink_data.proplist, PA_PROP_DEVICE_DESCRIPTION, "Uplink Sink %s on %s", sink_data.name, z ? z : master->name);
658         }
659 
660         u->sink_memblockq = pa_memblockq_new("module-virtual-source sink_memblockq", 0, MEMBLOCKQ_MAXLENGTH, 0, &ss, 1, 1, 0, NULL);
661         if (!u->sink_memblockq) {
662             pa_sink_new_data_done(&sink_data);
663             pa_log("Failed to create sink memblockq.");
664             goto fail;
665         }
666 
667         u->sink = pa_sink_new(m->core, &sink_data, 0);  /* FIXME, sink has no capabilities */
668         pa_sink_new_data_done(&sink_data);
669 
670         if (!u->sink) {
671             pa_log("Failed to create sink.");
672             goto fail;
673         }
674 
675         u->sink->parent.process_msg = sink_process_msg_cb;
676         u->sink->update_requested_latency = sink_update_requested_latency_cb;
677         u->sink->set_state_in_main_thread = sink_set_state_in_main_thread_cb;
678         u->sink->userdata = u;
679 
680         pa_sink_set_asyncmsgq(u->sink, master->asyncmsgq);
681         pa_sink_set_rtpoll(u->sink, u->rtpoll);
682 
683         /* FIXME: no idea what I am doing here */
684         u->block_usec = BLOCK_USEC;
685         nbytes = pa_usec_to_bytes(u->block_usec, &u->sink->sample_spec);
686         pa_sink_set_max_rewind(u->sink, 0);
687         pa_sink_set_max_request(u->sink, nbytes);
688 
689         pa_sink_put(u->sink);
690     } else {
691         pa_sink_new_data_done(&sink_data);
692         /* optional uplink sink not enabled */
693         u->sink = NULL;
694     }
695 
696     pa_modargs_free(ma);
697 
698     return 0;
699 
700 fail:
701     if (ma)
702         pa_modargs_free(ma);
703 
704     pa__done(m);
705 
706     return -1;
707 }
708 
pa__get_n_used(pa_module *m)709 int pa__get_n_used(pa_module *m) {
710     struct userdata *u;
711 
712     pa_assert(m);
713     pa_assert_se(u = m->userdata);
714 
715     return pa_source_linked_by(u->source);
716 }
717 
pa__done(pa_module*m)718 void pa__done(pa_module*m) {
719     struct userdata *u;
720 
721     pa_assert(m);
722 
723     if (!(u = m->userdata))
724         return;
725 
726     /* See comments in source_output_kill_cb() above regarding
727      * destruction order! */
728 
729     if (u->source_output)
730         pa_source_output_cork(u->source_output, true);
731 
732     if (u->source)
733         pa_source_unlink(u->source);
734 
735     if (u->source_output) {
736         pa_source_output_unlink(u->source_output);
737         pa_source_output_unref(u->source_output);
738     }
739 
740     if (u->source)
741         pa_source_unref(u->source);
742 
743     if (u->sink) {
744         pa_sink_unlink(u->sink);
745         pa_sink_unref(u->sink);
746     }
747 
748     if (u->memblockq)
749         pa_memblockq_free(u->memblockq);
750 
751     if (u->sink_memblockq)
752         pa_memblockq_free(u->sink_memblockq);
753 
754     if (u->rtpoll)
755         pa_rtpoll_free(u->rtpoll);
756 
757     pa_xfree(u);
758 }
759