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:
parent
0c3a62be7a
commit
a8fefae3a1
@ -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;
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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,
|
||||
|
@ -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) {
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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 */
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user