Harden the sound channel

This patch adds checks for the sound channel and plugins:

* checks for protocol bytes;
* checks for malloc/calloc;
* be more strict when interacting with sound plugin
This commit is contained in:
David FORT 2015-06-24 17:06:45 +02:00
parent 0c3a62be7a
commit a8fefae3a1
10 changed files with 408 additions and 217 deletions

View File

@ -200,12 +200,10 @@ static int rdpsnd_alsa_set_params(rdpsndAlsaPlugin* alsa)
if (rdpsnd_alsa_set_sw_params(alsa) < 0)
return -1;
rdpsnd_alsa_validate_params(alsa);
return 0;
return rdpsnd_alsa_validate_params(alsa);
}
static void rdpsnd_alsa_set_format(rdpsndDevicePlugin* device, AUDIO_FORMAT* format, int latency)
static BOOL rdpsnd_alsa_set_format(rdpsndDevicePlugin* device, AUDIO_FORMAT* format, int latency)
{
rdpsndAlsaPlugin* alsa = (rdpsndAlsaPlugin*) device;
@ -246,76 +244,73 @@ static void rdpsnd_alsa_set_format(rdpsndDevicePlugin* device, AUDIO_FORMAT* for
alsa->latency = latency;
rdpsnd_alsa_set_params(alsa);
return (rdpsnd_alsa_set_params(alsa) == 0);
}
static void rdpsnd_alsa_open_mixer(rdpsndAlsaPlugin* alsa)
static BOOL rdpsnd_alsa_open_mixer(rdpsndAlsaPlugin* alsa)
{
int status;
if (alsa->mixer_handle)
return;
return TRUE;
status = snd_mixer_open(&alsa->mixer_handle, 0);
if (status < 0)
{
WLog_ERR(TAG, "snd_mixer_open failed");
return;
return FALSE;
}
status = snd_mixer_attach(alsa->mixer_handle, alsa->device_name);
if (status < 0)
{
WLog_ERR(TAG, "snd_mixer_attach failed");
snd_mixer_close(alsa->mixer_handle);
return;
return FALSE;
}
status = snd_mixer_selem_register(alsa->mixer_handle, NULL, NULL);
if (status < 0)
{
WLog_ERR(TAG, "snd_mixer_selem_register failed");
snd_mixer_close(alsa->mixer_handle);
return;
return FALSE;
}
status = snd_mixer_load(alsa->mixer_handle);
if (status < 0)
{
WLog_ERR(TAG, "snd_mixer_load failed");
snd_mixer_close(alsa->mixer_handle);
return;
return FALSE;
}
return TRUE;
}
static void rdpsnd_alsa_open(rdpsndDevicePlugin* device, AUDIO_FORMAT* format, int latency)
static BOOL rdpsnd_alsa_open(rdpsndDevicePlugin* device, AUDIO_FORMAT* format, int latency)
{
int mode;
int status;
rdpsndAlsaPlugin* alsa = (rdpsndAlsaPlugin*) device;
if (alsa->pcm_handle)
return;
return TRUE;
mode = 0;
//mode |= SND_PCM_NONBLOCK;
/*mode |= SND_PCM_NONBLOCK;*/
status = snd_pcm_open(&alsa->pcm_handle, alsa->device_name, SND_PCM_STREAM_PLAYBACK, mode);
if (status < 0)
{
WLog_ERR(TAG, "snd_pcm_open failed");
return FALSE;
}
else
{
freerdp_dsp_context_reset_adpcm(alsa->dsp_context);
rdpsnd_alsa_set_format(device, format, latency);
rdpsnd_alsa_open_mixer(alsa);
}
freerdp_dsp_context_reset_adpcm(alsa->dsp_context);
return rdpsnd_alsa_set_format(device, format, latency) &&
rdpsnd_alsa_open_mixer(alsa);
}
static void rdpsnd_alsa_close(rdpsndDevicePlugin* device)
@ -386,12 +381,9 @@ static BOOL rdpsnd_alsa_format_supported(rdpsndDevicePlugin* device, AUDIO_FORMA
break;
case WAVE_FORMAT_ALAW:
break;
case WAVE_FORMAT_MULAW:
break;
case WAVE_FORMAT_GSM610:
default:
break;
}
@ -436,7 +428,7 @@ static UINT32 rdpsnd_alsa_get_volume(rdpsndDevicePlugin* device)
return dwVolume;
}
static void rdpsnd_alsa_set_volume(rdpsndDevicePlugin* device, UINT32 value)
static BOOL rdpsnd_alsa_set_volume(rdpsndDevicePlugin* device, UINT32 value)
{
long left;
long right;
@ -447,8 +439,8 @@ static void rdpsnd_alsa_set_volume(rdpsndDevicePlugin* device, UINT32 value)
snd_mixer_elem_t* elem;
rdpsndAlsaPlugin* alsa = (rdpsndAlsaPlugin*) device;
if (!alsa->mixer_handle)
rdpsnd_alsa_open_mixer(alsa);
if (!alsa->mixer_handle && !rdpsnd_alsa_open_mixer(alsa))
return FALSE;
left = (value & 0xFFFF);
right = ((value >> 16) & 0xFFFF);
@ -460,10 +452,16 @@ static void rdpsnd_alsa_set_volume(rdpsndDevicePlugin* device, UINT32 value)
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);
if ((snd_mixer_selem_set_playback_volume(elem, SND_MIXER_SCHN_FRONT_LEFT, volume_left) < 0) ||
(snd_mixer_selem_set_playback_volume(elem, SND_MIXER_SCHN_FRONT_RIGHT, volume_right) < 0))
{
WLog_ERR(TAG, "error setting the volume\n");
return FALSE;
}
}
}
return TRUE;
}
static BYTE* rdpsnd_alsa_process_audio_sample(rdpsndDevicePlugin* device, BYTE* data, int* size)
@ -518,7 +516,7 @@ static BYTE* rdpsnd_alsa_process_audio_sample(rdpsndDevicePlugin* device, BYTE*
return data;
}
static void rdpsnd_alsa_wave_decode(rdpsndDevicePlugin* device, RDPSND_WAVE* wave)
static BOOL rdpsnd_alsa_wave_decode(rdpsndDevicePlugin* device, RDPSND_WAVE* wave)
{
int size;
BYTE* data;
@ -527,8 +525,12 @@ static void rdpsnd_alsa_wave_decode(rdpsndDevicePlugin* device, RDPSND_WAVE* wav
data = rdpsnd_alsa_process_audio_sample(device, wave->data, &size);
wave->data = (BYTE*) malloc(size);
if (!wave->data)
return FALSE;
CopyMemory(wave->data, data, size);
wave->length = size;
return TRUE;
}
static void rdpsnd_alsa_wave_play(rdpsndDevicePlugin* device, RDPSND_WAVE* wave)
@ -624,6 +626,8 @@ static int rdpsnd_alsa_parse_addin_args(rdpsndDevicePlugin* device, ADDIN_ARGV*
CommandLineSwitchCase(arg, "dev")
{
alsa->device_name = _strdup(arg->Value);
if (!alsa->device_name)
return CHANNEL_RC_NO_MEMORY;
}
CommandLineSwitchEnd(arg)
@ -642,8 +646,9 @@ int freerdp_rdpsnd_client_subsystem_entry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pE
ADDIN_ARGV* args;
rdpsndAlsaPlugin* alsa;
alsa = (rdpsndAlsaPlugin*) malloc(sizeof(rdpsndAlsaPlugin));
ZeroMemory(alsa, sizeof(rdpsndAlsaPlugin));
alsa = (rdpsndAlsaPlugin*) calloc(1, sizeof(rdpsndAlsaPlugin));
if (!alsa)
return -1;
alsa->device.Open = rdpsnd_alsa_open;
alsa->device.FormatSupported = rdpsnd_alsa_format_supported;
@ -656,10 +661,15 @@ int freerdp_rdpsnd_client_subsystem_entry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pE
alsa->device.Free = rdpsnd_alsa_free;
args = pEntryPoints->args;
rdpsnd_alsa_parse_addin_args((rdpsndDevicePlugin*) alsa, args);
if (rdpsnd_alsa_parse_addin_args((rdpsndDevicePlugin*) alsa, args) != 0)
goto error_parse_args;
if (!alsa->device_name)
{
alsa->device_name = _strdup("default");
if (!alsa->device_name)
goto error_strdup;
}
alsa->pcm_handle = 0;
alsa->source_rate = 22050;
@ -670,8 +680,18 @@ int freerdp_rdpsnd_client_subsystem_entry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pE
alsa->bytes_per_channel = 2;
alsa->dsp_context = freerdp_dsp_context_new();
if (!alsa->dsp_context)
goto error_dsp_context;
pEntryPoints->pRegisterRdpsndDevice(pEntryPoints->rdpsnd, (rdpsndDevicePlugin*) alsa);
return 0;
error_dsp_context:
free(alsa->device_name);
error_strdup:
free(alsa->device_name);
error_parse_args:
free(alsa);
return -1;
}

View File

@ -98,12 +98,14 @@ static BOOL rdpsnd_ios_format_supported(rdpsndDevicePlugin* __unused device, AUD
return 0;
}
static void rdpsnd_ios_set_format(rdpsndDevicePlugin* __unused device, AUDIO_FORMAT* __unused format, int __unused latency)
static BOOL rdpsnd_ios_set_format(rdpsndDevicePlugin* __unused device, AUDIO_FORMAT* __unused format, int __unused latency)
{
return TRUE;
}
static void rdpsnd_ios_set_volume(rdpsndDevicePlugin* __unused device, UINT32 __unused value)
static BOOL rdpsnd_ios_set_volume(rdpsndDevicePlugin* __unused device, UINT32 __unused value)
{
return TRUE;
}
static void rdpsnd_ios_start(rdpsndDevicePlugin* device)
@ -153,14 +155,12 @@ static void rdpsnd_ios_play(rdpsndDevicePlugin* device, BYTE* data, int size)
rdpsnd_ios_start(device);
}
static void rdpsnd_ios_open(rdpsndDevicePlugin* device, AUDIO_FORMAT* format, int __unused latency)
static BOOL rdpsnd_ios_open(rdpsndDevicePlugin* device, AUDIO_FORMAT* format, int __unused latency)
{
rdpsndIOSPlugin *p = THIS(device);
if (p->is_opened)
{
return;
}
return TRUE;
/* Find the output audio unit. */
AudioComponentDescription desc;
@ -171,11 +171,13 @@ static void rdpsnd_ios_open(rdpsndDevicePlugin* device, AUDIO_FORMAT* format, in
desc.componentFlagsMask = 0;
AudioComponent audioComponent = AudioComponentFindNext(NULL, &desc);
if (audioComponent == NULL) return;
if (audioComponent == NULL)
return FALSE;
/* Open the audio unit. */
OSStatus status = AudioComponentInstanceNew(audioComponent, &p->audio_unit);
if (status != 0) return;
if (status != 0)
return FALSE;
/* Set the format for the AudioUnit. */
AudioStreamBasicDescription audioFormat = {0};
@ -199,7 +201,7 @@ static void rdpsnd_ios_open(rdpsndDevicePlugin* device, AUDIO_FORMAT* format, in
{
AudioComponentInstanceDispose(p->audio_unit);
p->audio_unit = NULL;
return;
return FALSE;
}
/* Set up the AudioUnit callback. */
@ -217,7 +219,7 @@ static void rdpsnd_ios_open(rdpsndDevicePlugin* device, AUDIO_FORMAT* format, in
{
AudioComponentInstanceDispose(p->audio_unit);
p->audio_unit = NULL;
return;
return FALSE;
}
/* Initialize the AudioUnit. */
@ -226,7 +228,7 @@ static void rdpsnd_ios_open(rdpsndDevicePlugin* device, AUDIO_FORMAT* format, in
{
AudioComponentInstanceDispose(p->audio_unit);
p->audio_unit = NULL;
return;
return FALSE;
}
/* Allocate the circular buffer. */
@ -236,10 +238,11 @@ static void rdpsnd_ios_open(rdpsndDevicePlugin* device, AUDIO_FORMAT* format, in
AudioUnitUninitialize(p->audio_unit);
AudioComponentInstanceDispose(p->audio_unit);
p->audio_unit = NULL;
return;
return FALSE;
}
p->is_opened = 1;
return TRUE;
}
static void rdpsnd_ios_close(rdpsndDevicePlugin* device)

View File

@ -60,7 +60,7 @@ static void mac_audio_queue_output_cb(void* inUserData, AudioQueueRef inAQ, Audi
}
static void rdpsnd_mac_set_format(rdpsndDevicePlugin* device, AUDIO_FORMAT* format, int latency)
static BOOL rdpsnd_mac_set_format(rdpsndDevicePlugin* device, AUDIO_FORMAT* format, int latency)
{
rdpsndMacPlugin* mac = (rdpsndMacPlugin*) device;
@ -99,9 +99,10 @@ static void rdpsnd_mac_set_format(rdpsndDevicePlugin* device, AUDIO_FORMAT* form
mac->audioFormat.mReserved = 0;
rdpsnd_print_audio_format(format);
return TRUE;
}
static void rdpsnd_mac_open(rdpsndDevicePlugin* device, AUDIO_FORMAT* format, int latency)
static BOOL rdpsnd_mac_open(rdpsndDevicePlugin* device, AUDIO_FORMAT* format, int latency)
{
int index;
OSStatus status;
@ -109,11 +110,15 @@ static void rdpsnd_mac_open(rdpsndDevicePlugin* device, AUDIO_FORMAT* format, in
rdpsndMacPlugin* mac = (rdpsndMacPlugin*) device;
if (mac->isOpen)
return;
return TRUE;
mac->audioBufferIndex = 0;
device->SetFormat(device, format, 0);
if (!device->SetFormat(device, format, 0))
{
WLog_ERR(TAG, "SetFormat failure\n");
return FALSE;
}
status = AudioQueueNewOutput(&(mac->audioFormat),
mac_audio_queue_output_cb, mac,
@ -121,8 +126,8 @@ static void rdpsnd_mac_open(rdpsndDevicePlugin* device, AUDIO_FORMAT* format, in
if (status != 0)
{
WLog_ERR(TAG, "AudioQueueNewOutput failure\n");
return;
WLog_ERR(TAG, "AudioQueueNewOutput failure\n");
return FALSE;
}
UInt32 DecodeBufferSizeFrames;
@ -136,6 +141,7 @@ static void rdpsnd_mac_open(rdpsndDevicePlugin* device, AUDIO_FORMAT* format, in
if (status != 0)
{
WLog_DBG(TAG, "AudioQueueGetProperty failure: kAudioQueueProperty_DecodeBufferSizeFrames\n");
return FALSE;
}
for (index = 0; index < MAC_AUDIO_QUEUE_NUM_BUFFERS; index++)
@ -145,10 +151,12 @@ static void rdpsnd_mac_open(rdpsndDevicePlugin* device, AUDIO_FORMAT* format, in
if (status != 0)
{
WLog_ERR(TAG, "AudioQueueAllocateBuffer failed\n");
return FALSE;
}
}
mac->isOpen = TRUE;
return TRUE;
}
static void rdpsnd_mac_close(rdpsndDevicePlugin* device)
@ -199,7 +207,7 @@ static BOOL rdpsnd_mac_format_supported(rdpsndDevicePlugin* device, AUDIO_FORMAT
return FALSE;
}
static void rdpsnd_mac_set_volume(rdpsndDevicePlugin* device, UINT32 value)
static BOOL rdpsnd_mac_set_volume(rdpsndDevicePlugin* device, UINT32 value)
{
OSStatus status;
Float32 fVolume;
@ -208,7 +216,7 @@ static void rdpsnd_mac_set_volume(rdpsndDevicePlugin* device, UINT32 value)
rdpsndMacPlugin* mac = (rdpsndMacPlugin*) device;
if (!mac->audioQueue)
return;
return FALSE;
volumeLeft = (value & 0xFFFF);
volumeRight = ((value >> 16) & 0xFFFF);
@ -220,7 +228,10 @@ static void rdpsnd_mac_set_volume(rdpsndDevicePlugin* device, UINT32 value)
if (status != 0)
{
WLog_ERR(TAG, "AudioQueueSetParameter kAudioQueueParam_Volume failed: %f\n", fVolume);
return FALSE;
}
return TRUE;
}
static void rdpsnd_mac_start(rdpsndDevicePlugin* device)

View File

@ -120,7 +120,7 @@ static int rdpsnd_opensles_set_params(rdpsndopenslesPlugin* opensles)
return 0;
}
static void rdpsnd_opensles_set_format(rdpsndDevicePlugin* device,
static BOOL rdpsnd_opensles_set_format(rdpsndDevicePlugin* device,
AUDIO_FORMAT* format, int latency)
{
rdpsndopenslesPlugin* opensles = (rdpsndopenslesPlugin*) device;
@ -168,10 +168,10 @@ static void rdpsnd_opensles_set_format(rdpsndDevicePlugin* device,
opensles->latency = latency;
rdpsnd_opensles_set_params(opensles);
return (rdpsnd_opensles_set_params(opensles) == 0);
}
static void rdpsnd_opensles_open(rdpsndDevicePlugin* device,
static BOOL rdpsnd_opensles_open(rdpsndDevicePlugin* device,
AUDIO_FORMAT* format, int latency)
{
rdpsndopenslesPlugin* opensles = (rdpsndopenslesPlugin*) device;
@ -179,11 +179,10 @@ static void rdpsnd_opensles_open(rdpsndDevicePlugin* device,
DEBUG_SND("opensles=%p format=%p, latency=%d, rate=%d",
opensles, format, latency, opensles->rate);
if( rdpsnd_opensles_check_handle(opensles))
return;
if (rdpsnd_opensles_check_handle(opensles))
return TRUE;
opensles->stream = android_OpenAudioDevice(
opensles->rate, opensles->channels, 20);
opensles->stream = android_OpenAudioDevice(opensles->rate, opensles->channels, 20);
assert(opensles->stream);
if (!opensles->stream)
@ -192,6 +191,7 @@ static void rdpsnd_opensles_open(rdpsndDevicePlugin* device,
rdpsnd_opensles_set_volume(device, opensles->volume);
rdpsnd_opensles_set_format(device, format, latency);
return TRUE;
}
static void rdpsnd_opensles_close(rdpsndDevicePlugin* device)
@ -290,7 +290,7 @@ static UINT32 rdpsnd_opensles_get_volume(rdpsndDevicePlugin* device)
return opensles->volume;
}
static void rdpsnd_opensles_set_volume(rdpsndDevicePlugin* device,
static BOOL rdpsnd_opensles_set_volume(rdpsndDevicePlugin* device,
UINT32 value)
{
rdpsndopenslesPlugin* opensles = (rdpsndopenslesPlugin*) device;
@ -313,6 +313,8 @@ static void rdpsnd_opensles_set_volume(rdpsndDevicePlugin* device,
android_SetOutputVolume(opensles->stream, vol);
}
}
return TRUE;
}
static void rdpsnd_opensles_play(rdpsndDevicePlugin* device,

View File

@ -132,28 +132,45 @@ static BOOL rdpsnd_oss_format_supported(rdpsndDevicePlugin *device, AUDIO_FORMAT
return TRUE;
}
static void rdpsnd_oss_set_format(rdpsndDevicePlugin *device, AUDIO_FORMAT *format, int latency) {
static BOOL rdpsnd_oss_set_format(rdpsndDevicePlugin *device, AUDIO_FORMAT *format, int latency) {
int tmp;
rdpsndOssPlugin *oss = (rdpsndOssPlugin*)device;
if (device == NULL || oss->pcm_handle == -1 || format == NULL)
return;
return FALSE;
oss->latency = latency;
CopyMemory(&(oss->format), format, sizeof(AUDIO_FORMAT));
tmp = rdpsnd_oss_get_format(format);
if (ioctl(oss->pcm_handle, SNDCTL_DSP_SETFMT, &tmp) == -1)
{
OSS_LOG_ERR("SNDCTL_DSP_SETFMT failed", errno);
return FALSE;
}
tmp = format->nChannels;
if (ioctl(oss->pcm_handle, SNDCTL_DSP_CHANNELS, &tmp) == -1)
{
OSS_LOG_ERR("SNDCTL_DSP_CHANNELS failed", errno);
return FALSE;
}
tmp = format->nSamplesPerSec;
if (ioctl(oss->pcm_handle, SNDCTL_DSP_SPEED, &tmp) == -1)
{
OSS_LOG_ERR("SNDCTL_DSP_SPEED failed", errno);
return FALSE;
}
tmp = format->nBlockAlign;
if (ioctl(oss->pcm_handle, SNDCTL_DSP_SETFRAGMENT, &tmp) == -1)
{
OSS_LOG_ERR("SNDCTL_DSP_SETFRAGMENT failed", errno);
return FALSE;
}
return TRUE;
}
static void rdpsnd_oss_open_mixer(rdpsndOssPlugin *oss) {
@ -178,21 +195,23 @@ static void rdpsnd_oss_open_mixer(rdpsndOssPlugin *oss) {
}
}
static void rdpsnd_oss_open(rdpsndDevicePlugin *device, AUDIO_FORMAT *format, int latency) {
static BOOL rdpsnd_oss_open(rdpsndDevicePlugin *device, AUDIO_FORMAT *format, int latency) {
char dev_name[PATH_MAX] = "/dev/dsp";
rdpsndOssPlugin *oss = (rdpsndOssPlugin*)device;
if (device == NULL || oss->pcm_handle != -1)
return;
return TRUE;
if (oss->dev_unit != -1)
snprintf(dev_name, PATH_MAX - 1, "/dev/dsp%i", oss->dev_unit);
WLog_INFO(TAG, "open: %s", dev_name);
if ((oss->pcm_handle = open(dev_name, O_WRONLY)) < 0) {
OSS_LOG_ERR("sound dev open failed", errno);
oss->pcm_handle = -1;
return;
return FALSE;
}
#if 0 /* FreeBSD OSS implementation at this moment (2015.03) does not set PCM_CAP_OUTPUT flag. */
int mask = 0;
@ -205,15 +224,18 @@ static void rdpsnd_oss_open(rdpsndDevicePlugin *device, AUDIO_FORMAT *format, in
return;
}
#endif
if (ioctl(oss->pcm_handle, SNDCTL_DSP_GETFMTS, &oss->supported_formats) == -1) {
OSS_LOG_ERR("SNDCTL_DSP_GETFMTS failed", errno);
close(oss->pcm_handle);
oss->pcm_handle = -1;
return;
return FALSE;
}
freerdp_dsp_context_reset_adpcm(oss->dsp_context);
rdpsnd_oss_set_format(device, format, latency);
rdpsnd_oss_open_mixer(oss);
return TRUE;
}
static void rdpsnd_oss_close(rdpsndDevicePlugin *device) {
@ -271,12 +293,12 @@ static UINT32 rdpsnd_oss_get_volume(rdpsndDevicePlugin *device) {
return dwVolume;
}
static void rdpsnd_oss_set_volume(rdpsndDevicePlugin *device, UINT32 value) {
static BOOL rdpsnd_oss_set_volume(rdpsndDevicePlugin *device, UINT32 value) {
int left, right;
rdpsndOssPlugin *oss = (rdpsndOssPlugin*)device;
if (device == NULL || oss->mixer_handle == -1)
return;
return FALSE;
left = (value & 0xFFFF);
right = ((value >> 16) & 0xFFFF);
@ -292,16 +314,21 @@ static void rdpsnd_oss_set_volume(rdpsndDevicePlugin *device, UINT32 value) {
left |= (right << 8);
if (ioctl(oss->mixer_handle, MIXER_WRITE(SOUND_MIXER_VOLUME), &left) == -1)
{
OSS_LOG_ERR("WRITE_MIXER", errno);
return FALSE;
}
return TRUE;
}
static void rdpsnd_oss_wave_decode(rdpsndDevicePlugin *device, RDPSND_WAVE *wave) {
static BOOL rdpsnd_oss_wave_decode(rdpsndDevicePlugin *device, RDPSND_WAVE *wave) {
int size;
BYTE *data;
rdpsndOssPlugin *oss = (rdpsndOssPlugin*)device;
if (device == NULL || wave == NULL)
return;
return FALSE;
switch (oss->format.wFormatTag) {
case WAVE_FORMAT_ADPCM:
@ -322,8 +349,12 @@ static void rdpsnd_oss_wave_decode(rdpsndDevicePlugin *device, RDPSND_WAVE *wave
}
wave->data = (BYTE*)malloc(size);
if (!wave->data)
return FALSE;
CopyMemory(wave->data, data, size);
wave->length = size;
return TRUE;
}
static void rdpsnd_oss_wave_play(rdpsndDevicePlugin *device, RDPSND_WAVE *wave) {

View File

@ -249,7 +249,7 @@ static void rdpsnd_pulse_set_format_spec(rdpsndPulsePlugin* pulse, AUDIO_FORMAT*
pulse->block_size = format->nBlockAlign;
}
static void rdpsnd_pulse_open(rdpsndDevicePlugin* device, AUDIO_FORMAT* format, int latency)
static BOOL rdpsnd_pulse_open(rdpsndDevicePlugin* device, AUDIO_FORMAT* format, int latency)
{
pa_stream_state_t state;
pa_stream_flags_t flags;
@ -258,9 +258,7 @@ static void rdpsnd_pulse_open(rdpsndDevicePlugin* device, AUDIO_FORMAT* format,
rdpsndPulsePlugin* pulse = (rdpsndPulsePlugin*) device;
if (!pulse->context || pulse->stream)
{
return;
}
return TRUE;
rdpsnd_pulse_set_format_spec(pulse, format);
pulse->latency = latency;
@ -268,17 +266,16 @@ static void rdpsnd_pulse_open(rdpsndDevicePlugin* device, AUDIO_FORMAT* format,
if (pa_sample_spec_valid(&pulse->sample_spec) == 0)
{
pa_sample_spec_snprint(ss, sizeof(ss), &pulse->sample_spec);
return;
return TRUE;
}
pa_threaded_mainloop_lock(pulse->mainloop);
pulse->stream = pa_stream_new(pulse->context, "freerdp", &pulse->sample_spec, NULL);
if (!pulse->stream)
{
pa_threaded_mainloop_unlock(pulse->mainloop);
return;
return FALSE;
}
/* register essential callbacks */
@ -301,7 +298,7 @@ static void rdpsnd_pulse_open(rdpsndDevicePlugin* device, AUDIO_FORMAT* format,
pulse->device_name, pulse->latency > 0 ? &buffer_attr : NULL, flags, NULL, NULL) < 0)
{
pa_threaded_mainloop_unlock(pulse->mainloop);
return;
return TRUE;
}
for (;;)
@ -331,11 +328,11 @@ static void rdpsnd_pulse_open(rdpsndDevicePlugin* device, AUDIO_FORMAT* format,
pulse->gsm_context = gsm_create();
#endif
return TRUE;
}
else
{
rdpsnd_pulse_close(device);
}
rdpsnd_pulse_close(device);
return FALSE;
}
static void rdpsnd_pulse_free(rdpsndDevicePlugin* device)
@ -424,7 +421,7 @@ static BOOL rdpsnd_pulse_format_supported(rdpsndDevicePlugin* device, AUDIO_FORM
return FALSE;
}
static void rdpsnd_pulse_set_format(rdpsndDevicePlugin* device, AUDIO_FORMAT* format, int latency)
static BOOL rdpsnd_pulse_set_format(rdpsndDevicePlugin* device, AUDIO_FORMAT* format, int latency)
{
rdpsndPulsePlugin* pulse = (rdpsndPulsePlugin*) device;
@ -437,10 +434,10 @@ static void rdpsnd_pulse_set_format(rdpsndDevicePlugin* device, AUDIO_FORMAT* fo
pa_threaded_mainloop_unlock(pulse->mainloop);
}
rdpsnd_pulse_open(device, format, latency);
return rdpsnd_pulse_open(device, format, latency);
}
static void rdpsnd_pulse_set_volume(rdpsndDevicePlugin* device, UINT32 value)
static BOOL rdpsnd_pulse_set_volume(rdpsndDevicePlugin* device, UINT32 value)
{
pa_cvolume cv;
pa_volume_t left;
@ -449,7 +446,7 @@ static void rdpsnd_pulse_set_volume(rdpsndDevicePlugin* device, UINT32 value)
rdpsndPulsePlugin* pulse = (rdpsndPulsePlugin*) device;
if (!pulse->context || !pulse->stream)
return;
return FALSE;
left = (pa_volume_t) (value & 0xFFFF);
right = (pa_volume_t) ((value >> 16) & 0xFFFF);
@ -467,6 +464,7 @@ static void rdpsnd_pulse_set_volume(rdpsndDevicePlugin* device, UINT32 value)
pa_operation_unref(operation);
pa_threaded_mainloop_unlock(pulse->mainloop);
return TRUE;
}
static BYTE* rdpsnd_pulse_convert_audio(rdpsndDevicePlugin* device, BYTE* data, int* size)

View File

@ -95,7 +95,7 @@ struct rdpsnd_plugin
rdpsndDevicePlugin* device;
};
static void rdpsnd_confirm_wave(rdpsndPlugin* rdpsnd, RDPSND_WAVE* wave);
static WIN32ERROR rdpsnd_confirm_wave(rdpsndPlugin* rdpsnd, RDPSND_WAVE* wave);
static void* rdpsnd_schedule_thread(void* arg)
{
@ -128,7 +128,12 @@ static void* rdpsnd_schedule_thread(void* arg)
Sleep(wTimeDiff);
}
rdpsnd_confirm_wave(rdpsnd, wave);
if (rdpsnd_confirm_wave(rdpsnd, wave) != CHANNEL_RC_OK)
{
WLog_ERR(TAG, "error confirming wave");
break;
}
message.wParam = NULL;
free(wave);
@ -138,11 +143,13 @@ static void* rdpsnd_schedule_thread(void* arg)
return NULL;
}
void rdpsnd_send_quality_mode_pdu(rdpsndPlugin* rdpsnd)
WIN32ERROR rdpsnd_send_quality_mode_pdu(rdpsndPlugin* rdpsnd)
{
wStream* pdu;
pdu = Stream_New(NULL, 8);
if (!pdu)
return CHANNEL_RC_NO_MEMORY;
Stream_Write_UINT8(pdu, SNDC_QUALITYMODE); /* msgType */
Stream_Write_UINT8(pdu, 0); /* bPad */
Stream_Write_UINT16(pdu, 4); /* BodySize */
@ -151,7 +158,7 @@ void rdpsnd_send_quality_mode_pdu(rdpsndPlugin* rdpsnd)
WLog_Print(rdpsnd->log, WLOG_DEBUG, "QualityMode: %d", rdpsnd->wQualityMode);
rdpsnd_virtual_channel_write(rdpsnd, pdu);
return rdpsnd_virtual_channel_write(rdpsnd, pdu);
}
static void rdpsnd_select_supported_audio_formats(rdpsndPlugin* rdpsnd)
@ -207,7 +214,7 @@ static void rdpsnd_select_supported_audio_formats(rdpsndPlugin* rdpsnd)
#endif
}
void rdpsnd_send_client_audio_formats(rdpsndPlugin* rdpsnd)
WIN32ERROR rdpsnd_send_client_audio_formats(rdpsndPlugin* rdpsnd)
{
int index;
wStream* pdu;
@ -236,6 +243,8 @@ void rdpsnd_send_client_audio_formats(rdpsndPlugin* rdpsnd)
length += (18 + rdpsnd->ClientFormats[index].cbSize);
pdu = Stream_New(NULL, length);
if (!pdu)
return CHANNEL_RC_NO_MEMORY;
Stream_Write_UINT8(pdu, SNDC_FORMATS); /* msgType */
Stream_Write_UINT8(pdu, 0); /* bPad */
@ -268,20 +277,24 @@ void rdpsnd_send_client_audio_formats(rdpsndPlugin* rdpsnd)
WLog_Print(rdpsnd->log, WLOG_DEBUG, "Client Audio Formats");
rdpsnd_virtual_channel_write(rdpsnd, pdu);
return rdpsnd_virtual_channel_write(rdpsnd, pdu);
}
void rdpsnd_recv_server_audio_formats_pdu(rdpsndPlugin* rdpsnd, wStream* s)
WIN32ERROR rdpsnd_recv_server_audio_formats_pdu(rdpsndPlugin* rdpsnd, wStream* s)
{
int index;
UINT16 wVersion;
AUDIO_FORMAT* format;
UINT16 wNumberOfFormats;
WIN32ERROR ret = ERROR_BAD_LENGTH;
rdpsnd_free_audio_formats(rdpsnd->ServerFormats, rdpsnd->NumberOfServerFormats);
rdpsnd->NumberOfServerFormats = 0;
rdpsnd->ServerFormats = NULL;
if (Stream_GetRemainingLength(s) < 30)
return ERROR_BAD_LENGTH;
/* http://msdn.microsoft.com/en-us/library/cc240956.aspx */
Stream_Seek_UINT32(s); /* dwFlags */
Stream_Seek_UINT32(s); /* dwVolume */
@ -293,12 +306,19 @@ void rdpsnd_recv_server_audio_formats_pdu(rdpsndPlugin* rdpsnd, wStream* s)
Stream_Seek_UINT8(s); /* bPad */
rdpsnd->NumberOfServerFormats = wNumberOfFormats;
rdpsnd->ServerFormats = (AUDIO_FORMAT*) malloc(sizeof(AUDIO_FORMAT) * wNumberOfFormats);
if (Stream_GetRemainingLength(s) / 14 < wNumberOfFormats)
return ERROR_BAD_LENGTH;
rdpsnd->ServerFormats = (AUDIO_FORMAT*) calloc(wNumberOfFormats, sizeof(AUDIO_FORMAT));
if (!rdpsnd->ServerFormats)
return CHANNEL_RC_NO_MEMORY;
for (index = 0; index < (int) wNumberOfFormats; index++)
{
format = &rdpsnd->ServerFormats[index];
if (Stream_GetRemainingLength(s) < 14)
goto out_fail;
Stream_Read_UINT16(s, format->wFormatTag); /* wFormatTag */
Stream_Read_UINT16(s, format->nChannels); /* nChannels */
Stream_Read_UINT32(s, format->nSamplesPerSec); /* nSamplesPerSec */
@ -309,30 +329,49 @@ void rdpsnd_recv_server_audio_formats_pdu(rdpsndPlugin* rdpsnd, wStream* s)
if (format->cbSize > 0)
{
if (Stream_GetRemainingLength(s) < format->cbSize)
goto out_fail;
format->data = (BYTE*) malloc(format->cbSize);
if (!format->data)
{
ret = CHANNEL_RC_NO_MEMORY;
goto out_fail;
}
Stream_Read(s, format->data, format->cbSize);
}
else
{
format->data = NULL;
}
}
rdpsnd_select_supported_audio_formats(rdpsnd);
WLog_Print(rdpsnd->log, WLOG_DEBUG, "Server Audio Formats");
rdpsnd_send_client_audio_formats(rdpsnd);
ret = rdpsnd_send_client_audio_formats(rdpsnd);
if (ret == CHANNEL_RC_OK)
{
if (wVersion >= 6)
ret = rdpsnd_send_quality_mode_pdu(rdpsnd);
}
if (wVersion >= 6)
rdpsnd_send_quality_mode_pdu(rdpsnd);
return ret;
out_fail:
for (index = 0; index < (int) wNumberOfFormats; index++)
free(format->data);
free(rdpsnd->ServerFormats);
rdpsnd->ServerFormats = NULL;
return ret;
}
void rdpsnd_send_training_confirm_pdu(rdpsndPlugin* rdpsnd, UINT16 wTimeStamp, UINT16 wPackSize)
WIN32ERROR rdpsnd_send_training_confirm_pdu(rdpsndPlugin* rdpsnd, UINT16 wTimeStamp, UINT16 wPackSize)
{
wStream* pdu;
pdu = Stream_New(NULL, 8);
if (!pdu)
return CHANNEL_RC_NO_MEMORY;
Stream_Write_UINT8(pdu, SNDC_TRAINING); /* msgType */
Stream_Write_UINT8(pdu, 0); /* bPad */
Stream_Write_UINT16(pdu, 4); /* BodySize */
@ -342,30 +381,36 @@ void rdpsnd_send_training_confirm_pdu(rdpsndPlugin* rdpsnd, UINT16 wTimeStamp, U
WLog_Print(rdpsnd->log, WLOG_DEBUG, "Training Response: wTimeStamp: %d wPackSize: %d",
wTimeStamp, wPackSize);
rdpsnd_virtual_channel_write(rdpsnd, pdu);
return rdpsnd_virtual_channel_write(rdpsnd, pdu);
}
static void rdpsnd_recv_training_pdu(rdpsndPlugin* rdpsnd, wStream* s)
static WIN32ERROR rdpsnd_recv_training_pdu(rdpsndPlugin* rdpsnd, wStream* s)
{
UINT16 wTimeStamp;
UINT16 wPackSize;
if (Stream_GetRemainingLength(s) < 4)
return ERROR_BAD_LENGTH;
Stream_Read_UINT16(s, wTimeStamp);
Stream_Read_UINT16(s, wPackSize);
WLog_Print(rdpsnd->log, WLOG_DEBUG, "Training Request: wTimeStamp: %d wPackSize: %d",
wTimeStamp, wPackSize);
rdpsnd_send_training_confirm_pdu(rdpsnd, wTimeStamp, wPackSize);
return rdpsnd_send_training_confirm_pdu(rdpsnd, wTimeStamp, wPackSize);
}
static void rdpsnd_recv_wave_info_pdu(rdpsndPlugin* rdpsnd, wStream* s, UINT16 BodySize)
static WIN32ERROR rdpsnd_recv_wave_info_pdu(rdpsndPlugin* rdpsnd, wStream* s, UINT16 BodySize)
{
UINT16 wFormatNo;
AUDIO_FORMAT* format;
rdpsnd->expectingWave = TRUE;
if (Stream_GetRemainingLength(s) < 12)
return ERROR_BAD_LENGTH;
Stream_Read_UINT16(s, rdpsnd->wTimeStamp);
Stream_Read_UINT16(s, wFormatNo);
Stream_Read_UINT8(s, rdpsnd->cBlockNo);
@ -386,9 +431,10 @@ static void rdpsnd_recv_wave_info_pdu(rdpsndPlugin* rdpsnd, wStream* s, UINT16 B
//rdpsnd_print_audio_format(format);
if (rdpsnd->device)
if (rdpsnd->device && rdpsnd->device->Open &&
!rdpsnd->device->Open(rdpsnd->device, format, rdpsnd->latency))
{
IFCALL(rdpsnd->device->Open, rdpsnd->device, format, rdpsnd->latency);
return CHANNEL_RC_INITIALIZATION_ERROR;
}
}
else if (wFormatNo != rdpsnd->wCurrentFormatNo)
@ -397,16 +443,22 @@ static void rdpsnd_recv_wave_info_pdu(rdpsndPlugin* rdpsnd, wStream* s, UINT16 B
if (rdpsnd->device)
{
IFCALL(rdpsnd->device->SetFormat, rdpsnd->device, format, rdpsnd->latency);
if(rdpsnd->device->SetFormat && !rdpsnd->device->SetFormat(rdpsnd->device, format, rdpsnd->latency))
return CHANNEL_RC_INITIALIZATION_ERROR;
}
}
return CHANNEL_RC_OK;
}
void rdpsnd_send_wave_confirm_pdu(rdpsndPlugin* rdpsnd, UINT16 wTimeStamp, BYTE cConfirmedBlockNo)
WIN32ERROR rdpsnd_send_wave_confirm_pdu(rdpsndPlugin* rdpsnd, UINT16 wTimeStamp, BYTE cConfirmedBlockNo)
{
wStream* pdu;
pdu = Stream_New(NULL, 8);
if (!pdu)
return CHANNEL_RC_NO_MEMORY;
Stream_Write_UINT8(pdu, SNDC_WAVECONFIRM);
Stream_Write_UINT8(pdu, 0);
Stream_Write_UINT16(pdu, 4);
@ -414,31 +466,36 @@ void rdpsnd_send_wave_confirm_pdu(rdpsndPlugin* rdpsnd, UINT16 wTimeStamp, BYTE
Stream_Write_UINT8(pdu, cConfirmedBlockNo); /* cConfirmedBlockNo */
Stream_Write_UINT8(pdu, 0); /* bPad */
rdpsnd_virtual_channel_write(rdpsnd, pdu);
return rdpsnd_virtual_channel_write(rdpsnd, pdu);
}
void rdpsnd_confirm_wave(rdpsndPlugin* rdpsnd, RDPSND_WAVE* wave)
WIN32ERROR rdpsnd_confirm_wave(rdpsndPlugin* rdpsnd, RDPSND_WAVE* wave)
{
WLog_Print(rdpsnd->log, WLOG_DEBUG, "WaveConfirm: cBlockNo: %d wTimeStamp: %d wTimeDiff: %d",
wave->cBlockNo, wave->wTimeStampB, wave->wTimeStampB - wave->wTimeStampA);
rdpsnd_send_wave_confirm_pdu(rdpsnd, wave->wTimeStampB, wave->cBlockNo);
return rdpsnd_send_wave_confirm_pdu(rdpsnd, wave->wTimeStampB, wave->cBlockNo);
}
static void rdpsnd_device_send_wave_confirm_pdu(rdpsndDevicePlugin* device, RDPSND_WAVE* wave)
static WIN32ERROR rdpsnd_device_send_wave_confirm_pdu(rdpsndDevicePlugin* device, RDPSND_WAVE* wave)
{
if (device->DisableConfirmThread)
rdpsnd_confirm_wave(device->rdpsnd, wave);
else
MessageQueue_Post(device->rdpsnd->MsgPipe->Out, NULL, 0, (void*) wave, NULL);
return rdpsnd_confirm_wave(device->rdpsnd, wave);
if (!MessageQueue_Post(device->rdpsnd->MsgPipe->Out, NULL, 0, (void*) wave, NULL))
return CHANNEL_RC_NO_MEMORY;
return CHANNEL_RC_OK;
}
static void rdpsnd_recv_wave_pdu(rdpsndPlugin* rdpsnd, wStream* s)
static WIN32ERROR rdpsnd_recv_wave_pdu(rdpsndPlugin* rdpsnd, wStream* s)
{
int size;
BYTE* data;
RDPSND_WAVE* wave;
AUDIO_FORMAT* format;
WIN32ERROR status;
rdpsnd->expectingWave = FALSE;
@ -455,6 +512,8 @@ static void rdpsnd_recv_wave_pdu(rdpsndPlugin* rdpsnd, wStream* s)
size = (int) Stream_Capacity(s);
wave = (RDPSND_WAVE*) malloc(sizeof(RDPSND_WAVE));
if (!wave)
return CHANNEL_RC_NO_MEMORY;
wave->wLocalTimeA = GetTickCount();
wave->wTimeStampA = rdpsnd->wTimeStamp;
@ -475,14 +534,15 @@ static void rdpsnd_recv_wave_pdu(rdpsndPlugin* rdpsnd, wStream* s)
{
wave->wLocalTimeB = wave->wLocalTimeA;
wave->wTimeStampB = wave->wTimeStampA;
rdpsnd_confirm_wave(rdpsnd, wave);
status = rdpsnd_confirm_wave(rdpsnd, wave);
free(wave);
return;
return status;
}
if (rdpsnd->device->WaveDecode)
if (rdpsnd->device->WaveDecode && !rdpsnd->device->WaveDecode(rdpsnd->device, wave))
{
IFCALL(rdpsnd->device->WaveDecode, rdpsnd->device, wave);
free(wave);
return CHANNEL_RC_NO_MEMORY;
}
if (rdpsnd->device->WavePlay)
@ -500,8 +560,10 @@ static void rdpsnd_recv_wave_pdu(rdpsndPlugin* rdpsnd, wStream* s)
wave->wLocalTimeB = wave->wLocalTimeA + wave->wAudioLength + TIME_DELAY_MS;
}
status = CHANNEL_RC_OK;
if (wave->AutoConfirm)
rdpsnd->device->WaveConfirm(rdpsnd->device, wave);
status = rdpsnd->device->WaveConfirm(rdpsnd->device, wave);
return status;
}
static void rdpsnd_recv_close_pdu(rdpsndPlugin* rdpsnd)
@ -516,30 +578,42 @@ static void rdpsnd_recv_close_pdu(rdpsndPlugin* rdpsnd)
rdpsnd->isOpen = FALSE;
}
static void rdpsnd_recv_volume_pdu(rdpsndPlugin* rdpsnd, wStream* s)
static WIN32ERROR rdpsnd_recv_volume_pdu(rdpsndPlugin* rdpsnd, wStream* s)
{
UINT32 dwVolume;
if (Stream_GetRemainingLength(s) < 4)
return ERROR_BAD_LENGTH;
Stream_Read_UINT32(s, dwVolume);
WLog_Print(rdpsnd->log, WLOG_DEBUG, "Volume: 0x%04X", dwVolume);
if (rdpsnd->device)
if (rdpsnd->device && rdpsnd->device->SetVolume &&
!rdpsnd->device->SetVolume(rdpsnd->device, dwVolume))
{
IFCALL(rdpsnd->device->SetVolume, rdpsnd->device, dwVolume);
WLog_ERR(TAG, "error setting volume");
return CHANNEL_RC_INITIALIZATION_ERROR;
}
return CHANNEL_RC_OK;
}
static void rdpsnd_recv_pdu(rdpsndPlugin* rdpsnd, wStream* s)
static WIN32ERROR rdpsnd_recv_pdu(rdpsndPlugin* rdpsnd, wStream* s)
{
BYTE msgType;
UINT16 BodySize;
WIN32ERROR status = CHANNEL_RC_OK;
if (rdpsnd->expectingWave)
{
rdpsnd_recv_wave_pdu(rdpsnd, s);
Stream_Free(s, TRUE);
return;
status = rdpsnd_recv_wave_pdu(rdpsnd, s);
goto out;
}
if (Stream_GetRemainingLength(s) < 4)
{
status = ERROR_BAD_LENGTH;
goto out;
}
Stream_Read_UINT8(s, msgType); /* msgType */
@ -551,15 +625,15 @@ static void rdpsnd_recv_pdu(rdpsndPlugin* rdpsnd, wStream* s)
switch (msgType)
{
case SNDC_FORMATS:
rdpsnd_recv_server_audio_formats_pdu(rdpsnd, s);
status = rdpsnd_recv_server_audio_formats_pdu(rdpsnd, s);
break;
case SNDC_TRAINING:
rdpsnd_recv_training_pdu(rdpsnd, s);
status = rdpsnd_recv_training_pdu(rdpsnd, s);
break;
case SNDC_WAVE:
rdpsnd_recv_wave_info_pdu(rdpsnd, s, BodySize);
status = rdpsnd_recv_wave_info_pdu(rdpsnd, s, BodySize);
break;
case SNDC_CLOSE:
@ -567,7 +641,7 @@ static void rdpsnd_recv_pdu(rdpsndPlugin* rdpsnd, wStream* s)
break;
case SNDC_SETVOLUME:
rdpsnd_recv_volume_pdu(rdpsnd, s);
status = rdpsnd_recv_volume_pdu(rdpsnd, s);
break;
default:
@ -575,7 +649,9 @@ static void rdpsnd_recv_pdu(rdpsndPlugin* rdpsnd, wStream* s)
break;
}
out:
Stream_Free(s, TRUE);
return status;
}
static void rdpsnd_register_device_plugin(rdpsndPlugin* rdpsnd, rdpsndDevicePlugin* device)
@ -615,16 +691,18 @@ static BOOL rdpsnd_load_device_plugin(rdpsndPlugin* rdpsnd, const char* name, AD
return TRUE;
}
void rdpsnd_set_subsystem(rdpsndPlugin* rdpsnd, char* subsystem)
BOOL rdpsnd_set_subsystem(rdpsndPlugin* rdpsnd, const char* subsystem)
{
free(rdpsnd->subsystem);
rdpsnd->subsystem = _strdup(subsystem);
return (rdpsnd->subsystem != NULL);
}
void rdpsnd_set_device_name(rdpsndPlugin* rdpsnd, char* device_name)
BOOL rdpsnd_set_device_name(rdpsndPlugin* rdpsnd, const char* device_name)
{
free(rdpsnd->device_name);
rdpsnd->device_name = _strdup(device_name);
return (rdpsnd->device_name != NULL);
}
COMMAND_LINE_ARGUMENT_A rdpsnd_args[] =
@ -639,7 +717,7 @@ COMMAND_LINE_ARGUMENT_A rdpsnd_args[] =
{ NULL, 0, NULL, NULL, NULL, -1, NULL, NULL }
};
static void rdpsnd_process_addin_args(rdpsndPlugin* rdpsnd, ADDIN_ARGV* args)
static WIN32ERROR rdpsnd_process_addin_args(rdpsndPlugin* rdpsnd, ADDIN_ARGV* args)
{
int status;
DWORD flags;
@ -653,7 +731,7 @@ static void rdpsnd_process_addin_args(rdpsndPlugin* rdpsnd, ADDIN_ARGV* args)
rdpsnd_args, flags, rdpsnd, NULL, NULL);
if (status < 0)
return;
return CHANNEL_RC_INITIALIZATION_ERROR;
arg = rdpsnd_args;
@ -666,11 +744,13 @@ static void rdpsnd_process_addin_args(rdpsndPlugin* rdpsnd, ADDIN_ARGV* args)
CommandLineSwitchCase(arg, "sys")
{
rdpsnd_set_subsystem(rdpsnd, arg->Value);
if (!rdpsnd_set_subsystem(rdpsnd, arg->Value))
return CHANNEL_RC_NO_MEMORY;
}
CommandLineSwitchCase(arg, "dev")
{
rdpsnd_set_device_name(rdpsnd, arg->Value);
if (!rdpsnd_set_device_name(rdpsnd, arg->Value))
return CHANNEL_RC_NO_MEMORY;
}
CommandLineSwitchCase(arg, "format")
{
@ -714,105 +794,131 @@ static void rdpsnd_process_addin_args(rdpsndPlugin* rdpsnd, ADDIN_ARGV* args)
CommandLineSwitchEnd(arg)
}
while ((arg = CommandLineFindNextArgumentA(arg)) != NULL);
return CHANNEL_RC_OK;
}
static void rdpsnd_process_connect(rdpsndPlugin* rdpsnd)
static WIN32ERROR rdpsnd_process_connect(rdpsndPlugin* rdpsnd)
{
ADDIN_ARGV* args;
WIN32ERROR status;
char *subsystem_name = NULL, *device_name = NULL;
rdpsnd->latency = -1;
args = (ADDIN_ARGV*) rdpsnd->channelEntryPoints.pExtendedData;
if (args)
rdpsnd_process_addin_args(rdpsnd, args);
{
status = rdpsnd_process_addin_args(rdpsnd, args);
if (status != CHANNEL_RC_OK)
return status;
}
if (rdpsnd->subsystem)
{
if (strcmp(rdpsnd->subsystem, "fake") == 0)
return CHANNEL_RC_OK;
if (!rdpsnd_load_device_plugin(rdpsnd, rdpsnd->subsystem, args))
{
return;
WLog_ERR(TAG, "unable to load the %s subsystem plugin", rdpsnd->subsystem);
return CHANNEL_RC_INITIALIZATION_ERROR;
}
rdpsnd_load_device_plugin(rdpsnd, rdpsnd->subsystem, args);
}
#if defined(WITH_IOSAUDIO)
if (!rdpsnd->device)
else
{
rdpsnd_set_subsystem(rdpsnd, "ios");
rdpsnd_set_device_name(rdpsnd, "");
rdpsnd_load_device_plugin(rdpsnd, rdpsnd->subsystem, args);
}
#if defined(WITH_IOSAUDIO)
if (!rdpsnd->device)
{
subsystem_name = "ios";
device_name = "";
rdpsnd_load_device_plugin(rdpsnd, subsystem_name, args);
}
#endif
#if defined(WITH_OPENSLES)
if (!rdpsnd->device)
{
rdpsnd_set_subsystem(rdpsnd, "opensles");
rdpsnd_set_device_name(rdpsnd, "");
rdpsnd_load_device_plugin(rdpsnd, rdpsnd->subsystem, args);
}
if (!rdpsnd->device)
{
subsystem_name = "opensles";
device_name = "";
rdpsnd_load_device_plugin(rdpsnd, subsystem_name, args);
}
#endif
#if defined(WITH_PULSE)
if (!rdpsnd->device)
{
rdpsnd_set_subsystem(rdpsnd, "pulse");
rdpsnd_set_device_name(rdpsnd, "");
rdpsnd_load_device_plugin(rdpsnd, rdpsnd->subsystem, args);
}
#endif
#if defined(WITH_OSS)
if (!rdpsnd->device)
{
rdpsnd_set_subsystem(rdpsnd, "oss");
rdpsnd_set_device_name(rdpsnd, "");
rdpsnd_load_device_plugin(rdpsnd, rdpsnd->subsystem, args);
}
if (!rdpsnd->device)
{
subsystem_name = "pulse";
device_name = "";
rdpsnd_load_device_plugin(rdpsnd, subsystem_name, args);
}
#endif
#if defined(WITH_ALSA)
if (!rdpsnd->device)
{
rdpsnd_set_subsystem(rdpsnd, "alsa");
rdpsnd_set_device_name(rdpsnd, "default");
rdpsnd_load_device_plugin(rdpsnd, rdpsnd->subsystem, args);
}
if (!rdpsnd->device)
{
subsystem_name = "alsa";
device_name = "default";
rdpsnd_load_device_plugin(rdpsnd, subsystem_name, args);
}
#endif
#if defined(WITH_OSS)
if (!rdpsnd->device)
{
subsystem_name = "oss";
device_name = "";
rdpsnd_load_device_plugin(rdpsnd, subsystem_name, args);
}
#endif
#if defined(WITH_MACAUDIO)
if (!rdpsnd->device)
{
rdpsnd_set_subsystem(rdpsnd, "mac");
rdpsnd_set_device_name(rdpsnd, "default");
rdpsnd_load_device_plugin(rdpsnd, rdpsnd->subsystem, args);
}
if (!rdpsnd->device)
{
subsystem_name = "mac";
device_name = "default";
rdpsnd_load_device_plugin(rdpsnd, subsystem_name, args);
}
#endif
#if defined(WITH_WINMM)
if (!rdpsnd->device)
{
rdpsnd_set_subsystem(rdpsnd, "winmm");
rdpsnd_set_device_name(rdpsnd, "");
rdpsnd_load_device_plugin(rdpsnd, rdpsnd->subsystem, args);
}
if (!rdpsnd->device)
{
subsystem_name = "winmm";
device_name = "";
rdpsnd_load_device_plugin(rdpsnd, subsystem_name, args);
}
#endif
if (rdpsnd->device)
{
if (!rdpsnd_set_subsystem(rdpsnd, subsystem_name) || !rdpsnd_set_device_name(rdpsnd, device_name))
return CHANNEL_RC_NO_MEMORY;
}
}
if (!rdpsnd->device)
{
WLog_ERR(TAG, "no sound device.");
return;
return CHANNEL_RC_INITIALIZATION_ERROR;
}
if (!rdpsnd->device->DisableConfirmThread)
{
rdpsnd->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (!rdpsnd->stopEvent)
return CHANNEL_RC_INITIALIZATION_ERROR;
rdpsnd->ScheduleThread = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE) rdpsnd_schedule_thread,
(void*) rdpsnd, 0, NULL);
if (!rdpsnd->ScheduleThread)
return CHANNEL_RC_INITIALIZATION_ERROR;
}
return CHANNEL_RC_OK;
}
static void rdpsnd_process_disconnect(rdpsndPlugin* rdpsnd)
@ -894,9 +1000,9 @@ void rdpsnd_remove_open_handle_data(DWORD openHandle)
}
}
int rdpsnd_virtual_channel_write(rdpsndPlugin* rdpsnd, wStream* s)
WIN32ERROR rdpsnd_virtual_channel_write(rdpsndPlugin* rdpsnd, wStream* s)
{
UINT32 status = 0;
WIN32ERROR status = CHANNEL_RC_OK;
if (!rdpsnd)
{
@ -989,7 +1095,11 @@ static void* rdpsnd_virtual_channel_client_thread(void* arg)
wMessage message;
rdpsndPlugin* rdpsnd = (rdpsndPlugin*) arg;
rdpsnd_process_connect(rdpsnd);
if (rdpsnd_process_connect(rdpsnd) != CHANNEL_RC_OK)
{
WLog_ERR(TAG, "error connecting sound channel");
goto out;
}
while (1)
{
@ -1004,11 +1114,16 @@ static void* rdpsnd_virtual_channel_client_thread(void* arg)
if (message.id == 0)
{
data = (wStream*) message.wParam;
rdpsnd_recv_pdu(rdpsnd, data);
if (rdpsnd_recv_pdu(rdpsnd, data) != CHANNEL_RC_OK)
{
WLog_ERR(TAG, "error treating sound channel message");
break;
}
}
}
}
out:
rdpsnd_process_disconnect(rdpsnd);
ExitThread(0);
@ -1030,7 +1145,7 @@ static void rdpsnd_virtual_channel_event_connected(rdpsndPlugin* plugin, LPVOID
if (status != CHANNEL_RC_OK)
{
WLog_ERR(TAG, "pVirtualChannelOpen failed with %s [%08X]",
WLog_ERR(TAG, "pVirtualChannelOpen failed with %s [%08X]",
WTSErrorToString(status), status);
return;
}

View File

@ -21,6 +21,8 @@
#ifndef __RDPSND_MAIN_H
#define __RDPSND_MAIN_H
#include <winpr/win32error.h>
#include <freerdp/api.h>
#include <freerdp/svc.h>
#include <freerdp/addin.h>
@ -35,6 +37,6 @@
#define DEBUG_SND(fmt, ...) do { } while (0)
#endif
int rdpsnd_virtual_channel_write(rdpsndPlugin* rdpsnd, wStream* s);
WIN32ERROR rdpsnd_virtual_channel_write(rdpsndPlugin* rdpsnd, wStream* s);
#endif /* __RDPSND_MAIN_H */

View File

@ -80,17 +80,19 @@ static BOOL rdpsnd_winmm_convert_format(const AUDIO_FORMAT* in, WAVEFORMATEX* ou
return result;
}
static void rdpsnd_winmm_set_format(rdpsndDevicePlugin* device, AUDIO_FORMAT* format, int latency)
static BOOL rdpsnd_winmm_set_format(rdpsndDevicePlugin* device, AUDIO_FORMAT* format, int latency)
{
rdpsndWinmmPlugin* winmm = (rdpsndWinmmPlugin*) device;
if (format)
{
rdpsnd_winmm_convert_format(format, &winmm->format);
if (!rdpsnd_winmm_convert_format(format, &winmm->format))
return FALSE;
winmm->wformat = format->wFormatTag;
winmm->block_size = format->nBlockAlign;
}
return TRUE;
}
static void CALLBACK rdpsnd_winmm_callback_function(HWAVEOUT hwo, UINT uMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2)
@ -138,13 +140,13 @@ static void CALLBACK rdpsnd_winmm_callback_function(HWAVEOUT hwo, UINT uMsg, DWO
}
}
static void rdpsnd_winmm_open(rdpsndDevicePlugin* device, AUDIO_FORMAT* format, int latency)
static BOOL rdpsnd_winmm_open(rdpsndDevicePlugin* device, AUDIO_FORMAT* format, int latency)
{
MMRESULT mmResult;
rdpsndWinmmPlugin* winmm = (rdpsndWinmmPlugin*) device;
if (winmm->hWaveOut)
return;
return TRUE;
rdpsnd_winmm_set_format(device, format, latency);
freerdp_dsp_context_reset_adpcm(winmm->dsp_context);
@ -155,7 +157,10 @@ static void rdpsnd_winmm_open(rdpsndDevicePlugin* device, AUDIO_FORMAT* format,
if (mmResult != MMSYSERR_NOERROR)
{
WLog_ERR(TAG, "waveOutOpen failed: %d", mmResult);
return FALSE;
}
return TRUE;
}
static void rdpsnd_winmm_close(rdpsndDevicePlugin* device)
@ -228,14 +233,14 @@ static UINT32 rdpsnd_winmm_get_volume(rdpsndDevicePlugin* device)
return dwVolume;
}
static void rdpsnd_winmm_set_volume(rdpsndDevicePlugin* device, UINT32 value)
static BOOL rdpsnd_winmm_set_volume(rdpsndDevicePlugin* device, UINT32 value)
{
rdpsndWinmmPlugin* winmm = (rdpsndWinmmPlugin*) device;
if (!winmm->hWaveOut)
return;
return FALSE;
waveOutSetVolume(winmm->hWaveOut, value);
return (waveOutSetVolume(winmm->hWaveOut, value) == MMSYSERR_NOERROR);
}
static void rdpsnd_winmm_wave_decode(rdpsndDevicePlugin* device, RDPSND_WAVE* wave)
@ -265,8 +270,12 @@ static void rdpsnd_winmm_wave_decode(rdpsndDevicePlugin* device, RDPSND_WAVE* wa
}
wave->data = (BYTE*) malloc(length);
if (!wave->data)
return FALSE;
CopyMemory(wave->data, data, length);
wave->length = length;
return TRUE;
}
void rdpsnd_winmm_wave_play(rdpsndDevicePlugin* device, RDPSND_WAVE* wave)

View File

@ -51,18 +51,18 @@ typedef struct rdpsnd_plugin rdpsndPlugin;
typedef struct rdpsnd_device_plugin rdpsndDevicePlugin;
typedef BOOL (*pcFormatSupported) (rdpsndDevicePlugin* device, AUDIO_FORMAT* format);
typedef void (*pcOpen) (rdpsndDevicePlugin* device, AUDIO_FORMAT* format, int latency);
typedef void (*pcSetFormat) (rdpsndDevicePlugin* device, AUDIO_FORMAT* format, int latency);
typedef BOOL (*pcOpen) (rdpsndDevicePlugin* device, AUDIO_FORMAT* format, int latency);
typedef BOOL (*pcSetFormat) (rdpsndDevicePlugin* device, AUDIO_FORMAT* format, int latency);
typedef UINT32 (*pcGetVolume) (rdpsndDevicePlugin* device);
typedef void (*pcSetVolume) (rdpsndDevicePlugin* device, UINT32 value);
typedef BOOL (*pcSetVolume) (rdpsndDevicePlugin* device, UINT32 value);
typedef void (*pcPlay) (rdpsndDevicePlugin* device, BYTE* data, int size);
typedef void (*pcStart) (rdpsndDevicePlugin* device);
typedef void (*pcClose) (rdpsndDevicePlugin* device);
typedef void (*pcFree) (rdpsndDevicePlugin* device);
typedef void (*pcWaveDecode) (rdpsndDevicePlugin* device, RDPSND_WAVE* wave);
typedef BOOL (*pcWaveDecode) (rdpsndDevicePlugin* device, RDPSND_WAVE* wave);
typedef void (*pcWavePlay) (rdpsndDevicePlugin* device, RDPSND_WAVE* wave);
typedef void (*pcWaveConfirm) (rdpsndDevicePlugin* device, RDPSND_WAVE* wave);
typedef WIN32ERROR (*pcWaveConfirm) (rdpsndDevicePlugin* device, RDPSND_WAVE* wave);
struct rdpsnd_device_plugin
{