• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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