vlc | branch: master | Rémi Denis-Courmont <[email protected]> | Tue Apr 12 20:01:02 2011 +0300| [7553aa0fbe893bac3df934f8d914acde52c47292] | committer: Rémi Denis-Courmont
PulseAudio output device (sink) run-time selection Notes: - The variable value represents the PulseAudio sink index. It is not a member of the AOUT_VAR_ enumeration. - There is no configuration item. PulseAudio normally remembers the last sink VLC used. So I think there is no need value in writing code to duplicate that effort. - I am not sure if we need more locking inside the variable callback. This needs to be clarified with PulseAudio guys. > http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=7553aa0fbe893bac3df934f8d914acde52c47292 --- modules/audio_output/pulse.c | 63 ++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 63 insertions(+), 0 deletions(-) diff --git a/modules/audio_output/pulse.c b/modules/audio_output/pulse.c index bad3e1d..3041a5b 100644 --- a/modules/audio_output/pulse.c +++ b/modules/audio_output/pulse.c @@ -47,6 +47,12 @@ vlc_module_end () /* TODO: single static mainloop */ +/* NOTE: + * Be careful what you do when the PulseAudio mainloop is held, which is to say + * within PulseAudio callbacks, or after pa_threaded_mainloop_lock(). + * In particular, the VLC audio output object variables can be manipulated with + * the PulseAudio mainloop lock held, but not vice versa! */ + struct aout_sys_t { pa_stream *stream; /**< PulseAudio playback stream object */ @@ -90,6 +96,23 @@ static void error(aout_instance_t *aout, const char *msg, pa_context *context) } /* Sink */ +static void sink_list_cb(pa_context *c, const pa_sink_info *i, int eol, + void *userdata) +{ + aout_instance_t *aout = userdata; + vlc_value_t val, text; + + if (eol) + return; + (void) c; + + msg_Dbg(aout, "listing sink %s (%"PRIu32"): %s", i->name, i->index, + i->description); + val.i_int = i->index; + text.psz_string = (char *)i->description; + var_Change(aout, "audio-device", VLC_VAR_ADDCHOICE, &val, &text); +} + static void sink_info_cb(pa_context *c, const pa_sink_info *i, int eol, void *userdata) { @@ -317,12 +340,36 @@ static int VolumeSet(aout_instance_t *aout, audio_volume_t vol, bool mute) return 0; } +static int StreamMove(vlc_object_t *obj, const char *varname, vlc_value_t old, + vlc_value_t val, void *userdata) +{ + aout_instance_t *aout = (aout_instance_t *)obj; + aout_sys_t *sys = aout->output.p_sys; + pa_stream *s = userdata; + pa_operation *op; + uint32_t idx = pa_stream_get_index(s); + uint32_t sink_idx = val.i_int; + + op = pa_context_move_sink_input_by_index(sys->context, idx, sink_idx, + NULL, NULL); + if (unlikely(op == NULL)) { + error(aout, "cannot move sink", sys->context); + return VLC_EGENERIC; + } + pa_operation_unref(op); + msg_Dbg(aout, "moving to sink %"PRIu32, sink_idx); + (void) varname; (void) old; + return VLC_SUCCESS; +} + + /***************************************************************************** * Open: open the audio device *****************************************************************************/ static int Open(vlc_object_t *obj) { aout_instance_t *aout = (aout_instance_t *)obj; + pa_operation *op; /* Sample format specification */ struct pa_sample_spec ss; @@ -514,6 +561,16 @@ static int Open(vlc_object_t *obj) pba->maxlength, pba->tlength, pba->prebuf, pba->minreq); aout->output.i_nb_samples = pba->minreq / pa_frame_size(&ss); + + var_Create(aout, "audio-device", VLC_VAR_INTEGER|VLC_VAR_HASCHOICE); + var_Change(aout, "audio-device", VLC_VAR_SETTEXT, + &(vlc_value_t){ .psz_string = (char *)_("Audio device") }, + NULL); + var_AddCallback (aout, "audio-device", StreamMove, s); + op = pa_context_get_sink_info_list(ctx, sink_list_cb, aout); + /* We may need to wait for completion... once LibVLC supports this */ + if (op != NULL) + pa_operation_unref(op); pa_threaded_mainloop_unlock(mainloop); aout->output.pf_play = Play; @@ -537,6 +594,12 @@ static void Close (vlc_object_t *obj) pa_context *ctx = sys->context; pa_stream *s = sys->stream; + if (s != NULL) { + /* The callback takes mainloop lock, so it CANNOT be held here! */ + var_DelCallback (aout, "audio-device", StreamMove, s); + var_Destroy (aout, "audio-device"); + } + pa_threaded_mainloop_lock(mainloop); if (s != NULL) { pa_operation *op; _______________________________________________ vlc-commits mailing list [email protected] http://mailman.videolan.org/listinfo/vlc-commits
