diff --git a/channels/rdpsnd/client/alsa/rdpsnd_alsa.c b/channels/rdpsnd/client/alsa/rdpsnd_alsa.c index 706a15616..1f395be63 100644 --- a/channels/rdpsnd/client/alsa/rdpsnd_alsa.c +++ b/channels/rdpsnd/client/alsa/rdpsnd_alsa.c @@ -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; } diff --git a/channels/rdpsnd/client/ios/rdpsnd_ios.c b/channels/rdpsnd/client/ios/rdpsnd_ios.c index 1adcc3eee..f0ede99fc 100644 --- a/channels/rdpsnd/client/ios/rdpsnd_ios.c +++ b/channels/rdpsnd/client/ios/rdpsnd_ios.c @@ -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) diff --git a/channels/rdpsnd/client/mac/rdpsnd_mac.c b/channels/rdpsnd/client/mac/rdpsnd_mac.c index cfcfa51ad..1c9394da3 100644 --- a/channels/rdpsnd/client/mac/rdpsnd_mac.c +++ b/channels/rdpsnd/client/mac/rdpsnd_mac.c @@ -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) diff --git a/channels/rdpsnd/client/opensles/rdpsnd_opensles.c b/channels/rdpsnd/client/opensles/rdpsnd_opensles.c index d73f91fbe..d3133c10d 100644 --- a/channels/rdpsnd/client/opensles/rdpsnd_opensles.c +++ b/channels/rdpsnd/client/opensles/rdpsnd_opensles.c @@ -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, diff --git a/channels/rdpsnd/client/oss/rdpsnd_oss.c b/channels/rdpsnd/client/oss/rdpsnd_oss.c index 047d03813..2db5e02f0 100644 --- a/channels/rdpsnd/client/oss/rdpsnd_oss.c +++ b/channels/rdpsnd/client/oss/rdpsnd_oss.c @@ -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) { diff --git a/channels/rdpsnd/client/pulse/rdpsnd_pulse.c b/channels/rdpsnd/client/pulse/rdpsnd_pulse.c index ff23000e8..b339f8e91 100644 --- a/channels/rdpsnd/client/pulse/rdpsnd_pulse.c +++ b/channels/rdpsnd/client/pulse/rdpsnd_pulse.c @@ -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) diff --git a/channels/rdpsnd/client/rdpsnd_main.c b/channels/rdpsnd/client/rdpsnd_main.c index 1059051ec..246a0acec 100644 --- a/channels/rdpsnd/client/rdpsnd_main.c +++ b/channels/rdpsnd/client/rdpsnd_main.c @@ -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; } diff --git a/channels/rdpsnd/client/rdpsnd_main.h b/channels/rdpsnd/client/rdpsnd_main.h index 5b9c41358..7a06205cf 100644 --- a/channels/rdpsnd/client/rdpsnd_main.h +++ b/channels/rdpsnd/client/rdpsnd_main.h @@ -21,6 +21,8 @@ #ifndef __RDPSND_MAIN_H #define __RDPSND_MAIN_H +#include + #include #include #include @@ -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 */ diff --git a/channels/rdpsnd/client/winmm/rdpsnd_winmm.c b/channels/rdpsnd/client/winmm/rdpsnd_winmm.c index 70e4029f9..0d8718531 100644 --- a/channels/rdpsnd/client/winmm/rdpsnd_winmm.c +++ b/channels/rdpsnd/client/winmm/rdpsnd_winmm.c @@ -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) diff --git a/include/freerdp/client/rdpsnd.h b/include/freerdp/client/rdpsnd.h index d52950c3d..7e482aed9 100644 --- a/include/freerdp/client/rdpsnd.h +++ b/include/freerdp/client/rdpsnd.h @@ -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 {