From 229d4e0d3c0cf00be0fe322c2482fbeb6eda7521 Mon Sep 17 00:00:00 2001 From: Vic Lee Date: Tue, 29 May 2012 23:36:47 +0800 Subject: [PATCH 1/2] rdpsnd/alsa: support volume change. --- channels/rdpsnd/alsa/rdpsnd_alsa.c | 69 ++++++++++++++++++++++++++++++ channels/rdpsnd/rdpsnd_main.c | 4 +- 2 files changed, 71 insertions(+), 2 deletions(-) diff --git a/channels/rdpsnd/alsa/rdpsnd_alsa.c b/channels/rdpsnd/alsa/rdpsnd_alsa.c index 72c6979d0..86426bf9c 100644 --- a/channels/rdpsnd/alsa/rdpsnd_alsa.c +++ b/channels/rdpsnd/alsa/rdpsnd_alsa.c @@ -36,6 +36,7 @@ struct rdpsnd_alsa_plugin char* device_name; snd_pcm_t* out_handle; + snd_mixer_t* mixer_handle; uint32 source_rate; uint32 actual_rate; snd_pcm_format_t format; @@ -153,6 +154,42 @@ static void rdpsnd_alsa_set_format(rdpsndDevicePlugin* device, rdpsndFormat* for rdpsnd_alsa_set_params(alsa); } +static void rdpsnd_alsa_open_mixer(rdpsndAlsaPlugin* alsa) +{ + int error; + snd_mixer_t* handle; + + error = snd_mixer_open(&handle, 0); + if (error < 0) + { + DEBUG_WARN("snd_mixer_open failed"); + return; + } + error = snd_mixer_attach(handle, alsa->device_name); + if (error < 0) + { + DEBUG_WARN("snd_mixer_attach failed"); + snd_mixer_close(handle); + return; + } + error = snd_mixer_selem_register(handle, NULL, NULL); + if (error < 0) + { + DEBUG_WARN("snd_mixer_selem_register failed"); + snd_mixer_close(handle); + return; + } + error = snd_mixer_load(handle); + if (error < 0) + { + DEBUG_WARN("snd_mixer_load failed"); + snd_mixer_close(handle); + return; + } + + alsa->mixer_handle = handle; +} + static void rdpsnd_alsa_open(rdpsndDevicePlugin* device, rdpsndFormat* format, int latency) { rdpsndAlsaPlugin* alsa = (rdpsndAlsaPlugin*)device; @@ -173,6 +210,7 @@ static void rdpsnd_alsa_open(rdpsndDevicePlugin* device, rdpsndFormat* format, i { freerdp_dsp_context_reset_adpcm(alsa->dsp_context); rdpsnd_alsa_set_format(device, format, latency); + rdpsnd_alsa_open_mixer(alsa); } } @@ -187,6 +225,11 @@ static void rdpsnd_alsa_close(rdpsndDevicePlugin* device) snd_pcm_close(alsa->out_handle); alsa->out_handle = 0; } + if (alsa->mixer_handle) + { + snd_mixer_close(alsa->mixer_handle); + alsa->mixer_handle = NULL; + } } static void rdpsnd_alsa_free(rdpsndDevicePlugin* device) @@ -228,6 +271,32 @@ static boolean rdpsnd_alsa_format_supported(rdpsndDevicePlugin* device, rdpsndFo static void rdpsnd_alsa_set_volume(rdpsndDevicePlugin* device, uint32 value) { + rdpsndAlsaPlugin* alsa = (rdpsndAlsaPlugin*)device; + long left; + long right; + long volume_min; + long volume_max; + long volume_left; + long volume_right; + snd_mixer_elem_t* elem; + + if (!alsa->mixer_handle) + return; + + left = (value & 0xFFFF); + right = ((value >> 16) & 0xFFFF); + + for (elem = snd_mixer_first_elem(alsa->mixer_handle); elem; elem = snd_mixer_elem_next(elem)) + { + if (snd_mixer_selem_has_playback_volume(elem)) + { + snd_mixer_selem_get_playback_volume_range(elem, &volume_min, &volume_max); + volume_left = volume_min + (left * (volume_max - volume_min)) / 0xFFFF; + volume_right = volume_min + (right * (volume_max - volume_min)) / 0xFFFF; + snd_mixer_selem_set_playback_volume(elem, SND_MIXER_SCHN_FRONT_LEFT, volume_left); + snd_mixer_selem_set_playback_volume(elem, SND_MIXER_SCHN_FRONT_RIGHT, volume_right); + } + } } static void rdpsnd_alsa_play(rdpsndDevicePlugin* device, uint8* data, int size) diff --git a/channels/rdpsnd/rdpsnd_main.c b/channels/rdpsnd/rdpsnd_main.c index ec0e5a6c3..ca774d8ad 100644 --- a/channels/rdpsnd/rdpsnd_main.c +++ b/channels/rdpsnd/rdpsnd_main.c @@ -172,8 +172,8 @@ static void rdpsnd_process_message_formats(rdpsndPlugin* rdpsnd, STREAM* data_in stream_write_uint8(data_out, SNDC_FORMATS); /* msgType */ stream_write_uint8(data_out, 0); /* bPad */ stream_seek_uint16(data_out); /* BodySize */ - stream_write_uint32(data_out, TSSNDCAPS_ALIVE); /* dwFlags */ - stream_write_uint32(data_out, 0); /* dwVolume */ + stream_write_uint32(data_out, TSSNDCAPS_ALIVE | TSSNDCAPS_VOLUME); /* dwFlags */ + stream_write_uint32(data_out, 0xFFFFFFFF); /* dwVolume */ stream_write_uint32(data_out, 0); /* dwPitch */ stream_write_uint16_be(data_out, 0); /* wDGramPort */ stream_seek_uint16(data_out); /* wNumberOfFormats */ From 2633484e8d24ac3d9c855ab76de975cb187ef06c Mon Sep 17 00:00:00 2001 From: Vic Lee Date: Wed, 30 May 2012 00:22:58 +0800 Subject: [PATCH 2/2] rdpsnd/pulse: support volume change. --- channels/rdpsnd/pulse/rdpsnd_pulse.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/channels/rdpsnd/pulse/rdpsnd_pulse.c b/channels/rdpsnd/pulse/rdpsnd_pulse.c index 06f5a1716..faa3f416c 100644 --- a/channels/rdpsnd/pulse/rdpsnd_pulse.c +++ b/channels/rdpsnd/pulse/rdpsnd_pulse.c @@ -395,6 +395,25 @@ static void rdpsnd_pulse_set_format(rdpsndDevicePlugin* device, rdpsndFormat* fo static void rdpsnd_pulse_set_volume(rdpsndDevicePlugin* device, uint32 value) { + rdpsndPulsePlugin* pulse = (rdpsndPulsePlugin*)device; + pa_cvolume cv; + pa_volume_t left; + pa_volume_t right; + pa_operation* operation; + + if (!pulse->context || !pulse->stream) + return; + + left = (pa_volume_t) (value & 0xFFFF); + right = (pa_volume_t) ((value >> 16) & 0xFFFF); + + pa_cvolume_init(&cv); + cv.channels = 2; + cv.values[0] = PA_VOLUME_MUTED + (left * (PA_VOLUME_NORM - PA_VOLUME_MUTED)) / 0xFFFF; + cv.values[1] = PA_VOLUME_MUTED + (right * (PA_VOLUME_NORM - PA_VOLUME_MUTED)) / 0xFFFF; + operation = pa_context_set_sink_input_volume(pulse->context, pa_stream_get_index(pulse->stream), &cv, NULL, NULL); + if(operation) + pa_operation_unref(operation); } static void rdpsnd_pulse_play(rdpsndDevicePlugin* device, uint8* data, int size)