diff --git a/channels/audin/client/CMakeLists.txt b/channels/audin/client/CMakeLists.txt index 81b9cbb4e..a13a930c3 100644 --- a/channels/audin/client/CMakeLists.txt +++ b/channels/audin/client/CMakeLists.txt @@ -52,3 +52,7 @@ endif() if(WITH_WINMM) add_channel_client_subsystem(${MODULE_PREFIX} ${CHANNEL_NAME} "winmm" "") endif() + +if(WITH_MACAUDIO) + add_channel_client_subsystem(${MODULE_PREFIX} ${CHANNEL_NAME} "mac" "") +endif() diff --git a/channels/audin/client/audin_main.c b/channels/audin/client/audin_main.c index 455257066..17bb60f7d 100644 --- a/channels/audin/client/audin_main.c +++ b/channels/audin/client/audin_main.c @@ -5,6 +5,7 @@ * Copyright 2010-2011 Vic Lee * Copyright 2015 Thincast Technologies GmbH * Copyright 2015 DI (FH) Martin Haimberger + * Copyright 2015 Armin Novak * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -195,7 +196,7 @@ static UINT audin_process_formats(IWTSVirtualChannelCallback* pChannelCallback, Stream_Read_UINT16(s, format.cbSize); format.data = Stream_Pointer(s); Stream_Seek(s, format.cbSize); - + DEBUG_DVC("wFormatTag=%d nChannels=%d nSamplesPerSec=%d " "nBlockAlign=%d wBitsPerSample=%d cbSize=%d", format.wFormatTag, format.nChannels, format.nSamplesPerSec, @@ -310,7 +311,7 @@ static UINT audin_send_open_reply_pdu(IWTSVirtualChannelCallback* pChannelCallba * * @return 0 on success, otherwise a Win32 error code */ -static UINT audin_receive_wave_data(BYTE* data, int size, void* user_data) +static UINT audin_receive_wave_data(const BYTE* data, int size, void* user_data) { UINT error; wStream* out; @@ -667,7 +668,7 @@ static UINT audin_load_device_plugin(IWTSPlugin* pPlugin, const char* name, ADDI * * @return 0 on success, otherwise a Win32 error code */ -UINT audin_set_subsystem(AUDIN_PLUGIN* audin, char* subsystem) +static UINT audin_set_subsystem(AUDIN_PLUGIN* audin, char* subsystem) { free(audin->subsystem); audin->subsystem = _strdup(subsystem); @@ -684,7 +685,7 @@ UINT audin_set_subsystem(AUDIN_PLUGIN* audin, char* subsystem) * * @return 0 on success, otherwise a Win32 error code */ -UINT audin_set_device_name(AUDIN_PLUGIN* audin, char* device_name) +static UINT audin_set_device_name(AUDIN_PLUGIN* audin, char* device_name) { free(audin->device_name); audin->device_name = _strdup(device_name); @@ -696,7 +697,7 @@ UINT audin_set_device_name(AUDIN_PLUGIN* audin, char* device_name) return CHANNEL_RC_OK; } -COMMAND_LINE_ARGUMENT_A audin_args[] = +static COMMAND_LINE_ARGUMENT_A audin_args[] = { { "sys", COMMAND_LINE_VALUE_REQUIRED, "", NULL, NULL, -1, NULL, "subsystem" }, { "dev", COMMAND_LINE_VALUE_REQUIRED, "", NULL, NULL, -1, NULL, "device" }, @@ -779,9 +780,38 @@ static BOOL audin_process_addin_args(IWTSPlugin* pPlugin, ADDIN_ARGV* args) */ UINT DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints) { + struct SubsystemEntry + { + char *subsystem; + char *device; + }; + UINT error = CHANNEL_RC_OK; ADDIN_ARGV* args; AUDIN_PLUGIN* audin; + struct SubsystemEntry entries[] = + { +#if defined(WITH_PULSE) + {"pulse", ""}, +#endif +#if defined(WITH_OSS) + {"oss", "default"}, +#endif +#if defined(WITH_ALSA) + {"alsa", "default"}, +#endif +#if defined(WITH_OPENSLES) + {"opensles", "default"}, +#endif +#if defined(WITH_WINMM) + {"winmm", "default"}, +#endif +#if defined(WITH_MACAUDIO) + {"mac", "default"}, +#endif + {NULL,NULL} + }; + struct SubsystemEntry *entry = &entries[0]; assert(pEntryPoints); assert(pEntryPoints->GetPlugin); @@ -807,123 +837,26 @@ UINT DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints) args = pEntryPoints->GetPluginData(pEntryPoints); audin->rdpcontext = ((freerdp*)((rdpSettings*) pEntryPoints->GetRdpSettings(pEntryPoints))->instance)->context; - if (error == CHANNEL_RC_OK) - audin_process_addin_args((IWTSPlugin*) audin, args); - else + while (entry && entry->subsystem && !audin->device) { - WLog_ERR(TAG, "RegisterPlugin failed with error %lu!", error); - return error; - } + if ((error = audin_set_subsystem(audin, entry->subsystem))) + { + WLog_ERR(TAG, "audin_set_subsystem for %s failed with error %lu!", + entry->subsystem, error); + } + else if ((error = audin_set_device_name(audin, entry->device))) + { + WLog_ERR(TAG, "audin_set_device_name for %s failed with error %lu!", + entry->subsystem, error); + } + else if ((error = audin_load_device_plugin((IWTSPlugin*) audin, audin->subsystem, args))) + { + WLog_ERR(TAG, "audin_load_device_plugin %s failed with error %lu!", + entry->subsystem, error); + } - if (audin->subsystem && (error = audin_load_device_plugin((IWTSPlugin*) audin, audin->subsystem, args))) { - WLog_ERR(TAG, "audin_load_device_plugin failed!"); - return error; - } - -#if defined(WITH_PULSE) - if (!audin->device) - { - if ((error = audin_set_subsystem(audin, "pulse"))) - { - WLog_ERR(TAG, "audin_set_subsystem for pulse failed with error %lu!", error); - return error; - } - if ((error = audin_set_device_name(audin, ""))) - { - WLog_ERR(TAG, "audin_set_device_name for pulse failed with error %lu!", error); - return error; - } - if ((error = audin_load_device_plugin((IWTSPlugin*) audin, audin->subsystem, args))) - { - WLog_ERR(TAG, "audin_load_device_plugin for pulse failed with error %lu!", error); - return error; - } + entry++; } -#endif - -#if defined(WITH_OSS) - if (!audin->device) - { - if ((error = audin_set_subsystem(audin, "oss"))) - { - WLog_ERR(TAG, "audin_set_subsystem for oss failed with error %lu!", error); - return error; - } - if ((error = audin_set_device_name(audin, "default"))) - { - WLog_ERR(TAG, "audin_set_device_name for oss failed with error %lu!", error); - return error; - } - if ((error = audin_load_device_plugin((IWTSPlugin*) audin, audin->subsystem, args))) - { - WLog_ERR(TAG, "audin_load_device_plugin oss pulse failed with error %lu!", error); - return error; - } - } -#endif - -#if defined(WITH_ALSA) - if (!audin->device) - { - if ((error = audin_set_subsystem(audin, "alsa"))) - { - WLog_ERR(TAG, "audin_set_subsystem for alsa failed with error %lu!", error); - return error; - } - if ((error = audin_set_device_name(audin, "default"))) - { - WLog_ERR(TAG, "audin_set_device_name for alsa failed with error %lu!", error); - return error; - } - if ((error = audin_load_device_plugin((IWTSPlugin*) audin, audin->subsystem, args))) - { - WLog_ERR(TAG, "audin_load_device_plugin oss alsa failed with error %lu!", error); - return error; - } - } -#endif - -#if defined(WITH_OPENSLES) - if (!audin->device) - { - if ((error = audin_set_subsystem(audin, "opensles"))) - { - WLog_ERR(TAG, "audin_set_subsystem for opensles failed with error %lu!", error); - return error; - } - if ((error = audin_set_device_name(audin, "default"))) - { - WLog_ERR(TAG, "audin_set_device_name for opensles failed with error %lu!", error); - return error; - } - if ((error = audin_load_device_plugin((IWTSPlugin*) audin, audin->subsystem, args))) - { - WLog_ERR(TAG, "audin_load_device_plugin oss opensles failed with error %lu!", error); - return error; - } - } -#endif - -#if defined(WITH_WINMM) - if (!audin->device) - { - if ((error = audin_set_subsystem(audin, "winmm"))) - { - WLog_ERR(TAG, "audin_set_subsystem for winmm failed with error %lu!", error); - return error; - } - if ((error = audin_set_device_name(audin, "default"))) - { - WLog_ERR(TAG, "audin_set_device_name for winmm failed with error %lu!", error); - return error; - } - if ((error = audin_load_device_plugin((IWTSPlugin*) audin, audin->subsystem, args))) - { - WLog_ERR(TAG, "audin_load_device_plugin oss winmm failed with error %lu!", error); - return error; - } - } -#endif if (audin->device == NULL) { diff --git a/channels/audin/client/mac/CMakeLists.txt b/channels/audin/client/mac/CMakeLists.txt new file mode 100644 index 000000000..feca0d622 --- /dev/null +++ b/channels/audin/client/mac/CMakeLists.txt @@ -0,0 +1,34 @@ +# FreeRDP: A Remote Desktop Protocol Implementation +# FreeRDP cmake build script +# +# Copyright (c) 2015 Armin Novak +# Copyright (c) 2015 Thincast Technologies GmbH +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +define_channel_client_subsystem("audin" "mac" "") + +set(${MODULE_PREFIX}_SRCS + audin_mac.c) + +include_directories(..) +include_directories(${MAC_INCLUDE_DIRS}) + +add_channel_client_subsystem_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} "" TRUE "") + +set(${MODULE_PREFIX}_LIBS freerdp ${MAC_LIBRARIES}) + +target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS}) + +install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_ADDIN_PATH} EXPORT FreeRDPTargets) + diff --git a/channels/audin/client/mac/audin_mac.c b/channels/audin/client/mac/audin_mac.c new file mode 100644 index 000000000..07b789477 --- /dev/null +++ b/channels/audin/client/mac/audin_mac.c @@ -0,0 +1,461 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * Audio Input Redirection Virtual Channel - Mac OS X implementation + * + * Copyright (c) 2015 Armin Novak + * Copyright 2015 Thincast Technologies GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include "audin_main.h" + +#define MAC_AUDIO_QUEUE_NUM_BUFFERS 100 +#define MAC_AUDIO_QUEUE_BUFFER_SIZE 32768 + +typedef struct _AudinMacDevice +{ + IAudinDevice iface; + + FREERDP_DSP_CONTEXT* dsp_context; + + audinFormat format; + UINT32 FramesPerPacket; + int dev_unit; + + AudinReceive receive; + void* user_data; + + rdpContext* rdpcontext; + + bool isOpen; + AudioQueueRef audioQueue; + AudioStreamBasicDescription audioFormat; + AudioQueueBufferRef audioBuffers[MAC_AUDIO_QUEUE_NUM_BUFFERS]; +} AudinMacDevice; + +static AudioFormatID audin_mac_get_format(const audinFormat* format) +{ + switch (format->wFormatTag) + { + case WAVE_FORMAT_PCM: + return kAudioFormatLinearPCM; + /* + case WAVE_FORMAT_GSM610: + return kAudioFormatMicrosoftGSM; + case WAVE_FORMAT_ALAW: + return kAudioFormatALaw; + case WAVE_FORMAT_MULAW: + return kAudioFormatULaw; + case WAVE_FORMAT_AAC_MS: + return kAudioFormatMPEG4AAC; + case WAVE_FORMAT_ADPCM: + case WAVE_FORMAT_DVI_ADPCM: + return kAudioFormatLinearPCM; + */ + } + + return 0; +} + +static AudioFormatFlags audin_mac_get_flags_for_format(const audinFormat* format) +{ + switch(format->wFormatTag) + { + case WAVE_FORMAT_DVI_ADPCM: + case WAVE_FORMAT_ADPCM: + case WAVE_FORMAT_PCM: + return kAudioFormatFlagIsSignedInteger; + default: + return 0; + } +} + +static BOOL audin_mac_format_supported(IAudinDevice* device, audinFormat* format) +{ + AudioFormatID req_fmt = 0; + + if (device == NULL || format == NULL) + return FALSE; + + req_fmt = audin_mac_get_format(format); + + if (req_fmt == 0) + return FALSE; + + return TRUE; +} + +/** + * Function description + * + * @return 0 on success, otherwise a Win32 error code + */ +static UINT audin_mac_set_format(IAudinDevice* device, audinFormat* format, UINT32 FramesPerPacket) +{ + AudinMacDevice* mac = (AudinMacDevice*)device; + + if (device == NULL || format == NULL) + return ERROR_INVALID_PARAMETER; + + mac->FramesPerPacket = FramesPerPacket; + CopyMemory(&(mac->format), format, sizeof(audinFormat)); + + WLog_INFO(TAG, "Audio Format %s [channels=%d, samples=%d, bits=%d]", + rdpsnd_get_audio_tag_string(format->wFormatTag), + format->nChannels, format->nSamplesPerSec, format->wBitsPerSample); + + switch (format->wFormatTag) + { + case WAVE_FORMAT_ADPCM: + case WAVE_FORMAT_DVI_ADPCM: + mac->FramesPerPacket *= 4; /* Compression ratio. */ + mac->format.wBitsPerSample *= 4; + break; + } + + mac->audioFormat.mBitsPerChannel = mac->format.wBitsPerSample; + mac->audioFormat.mChannelsPerFrame = mac->format.nChannels; + mac->audioFormat.mFormatFlags = audin_mac_get_flags_for_format(format); + mac->audioFormat.mFormatID = audin_mac_get_format(format); + mac->audioFormat.mFramesPerPacket = 1; + mac->audioFormat.mSampleRate = mac->format.nSamplesPerSec; + mac->audioFormat.mBytesPerFrame = + mac->audioFormat.mChannelsPerFrame * mac->audioFormat.mBitsPerChannel / 8; + mac->audioFormat.mBytesPerPacket = + mac->audioFormat.mBytesPerFrame * mac->audioFormat.mFramesPerPacket; + + return CHANNEL_RC_OK; +} + +static void mac_audio_queue_input_cb(void *aqData, + AudioQueueRef inAQ, + AudioQueueBufferRef inBuffer, + const AudioTimeStamp *inStartTime, + UInt32 inNumPackets, + const AudioStreamPacketDescription *inPacketDesc) +{ + AudinMacDevice* mac = (AudinMacDevice*)aqData; + UINT error; + int encoded_size; + const BYTE *encoded_data; + BYTE *buffer = inBuffer->mAudioData; + int buffer_size = inBuffer->mAudioDataByteSize; + + (void)inAQ; + (void)inStartTime; + (void)inNumPackets; + (void)inPacketDesc; + + + /* Process. */ + switch (mac->format.wFormatTag) { + case WAVE_FORMAT_ADPCM: + if (!mac->dsp_context->encode_ms_adpcm(mac->dsp_context, + buffer, buffer_size, mac->format.nChannels, mac->format.nBlockAlign)) + { + SetLastError(ERROR_INTERNAL_ERROR); + return; + } + encoded_data = mac->dsp_context->adpcm_buffer; + encoded_size = mac->dsp_context->adpcm_size; + break; + case WAVE_FORMAT_DVI_ADPCM: + if (!mac->dsp_context->encode_ima_adpcm(mac->dsp_context, + buffer, buffer_size, mac->format.nChannels, mac->format.nBlockAlign)) + { + SetLastError(ERROR_INTERNAL_ERROR); + break; + } + encoded_data = mac->dsp_context->adpcm_buffer; + encoded_size = mac->dsp_context->adpcm_size; + break; + default: + encoded_data = buffer; + encoded_size = buffer_size; + break; + } + + if ((error = mac->receive(encoded_data, encoded_size, mac->user_data))) + { + WLog_ERR(TAG, "mac->receive failed with error %lu", error); + SetLastError(ERROR_INTERNAL_ERROR); + return; + } + +} + +static UINT audin_mac_close(IAudinDevice *device) +{ + UINT errCode = CHANNEL_RC_OK; + char errString[1024]; + OSStatus devStat; + AudinMacDevice *mac = (AudinMacDevice*)device; + + if (device == NULL) + return ERROR_INVALID_PARAMETER; + + if (mac->isOpen) + { + devStat = AudioQueueStop(mac->audioQueue, true); + if (devStat != 0) + { + errCode = GetLastError(); + WLog_ERR(TAG, "AudioQueueStop failed with %s [%d]", + winpr_strerror(errCode, errString, sizeof(errString)), errCode); + } + mac->isOpen = false; + } + + if (mac->audioQueue) + { + devStat = AudioQueueDispose(mac->audioQueue, true); + if (devStat != 0) + { + errCode = GetLastError(); + WLog_ERR(TAG, "AudioQueueDispose failed with %s [%d]", + winpr_strerror(errCode, errString, sizeof(errString)), errCode); + } + + mac->audioQueue = NULL; + } + + mac->receive = NULL; + mac->user_data = NULL; + + return errCode; +} + +static UINT audin_mac_open(IAudinDevice *device, AudinReceive receive, void *user_data) { + AudinMacDevice *mac = (AudinMacDevice*)device; + DWORD errCode; + char errString[1024]; + OSStatus devStat; + size_t index; + + mac->receive = receive; + mac->user_data = user_data; + + devStat = AudioQueueNewInput(&(mac->audioFormat), mac_audio_queue_input_cb, + mac, NULL, kCFRunLoopCommonModes, 0, &(mac->audioQueue)); + if (devStat != 0) + { + errCode = GetLastError(); + WLog_ERR(TAG, "AudioQueueNewInput failed with %s [%d]", + winpr_strerror(errCode, errString, sizeof(errString)), errCode); + goto err_out; + } + + for (index = 0; index < MAC_AUDIO_QUEUE_NUM_BUFFERS; index++) + { + devStat = AudioQueueAllocateBuffer(mac->audioQueue, MAC_AUDIO_QUEUE_BUFFER_SIZE, + &mac->audioBuffers[index]); + if (devStat != 0) + { + errCode = GetLastError(); + WLog_ERR(TAG, "AudioQueueAllocateBuffer failed with %s [%d]", + winpr_strerror(errCode, errString, sizeof(errString)), errCode); + goto err_out; + } + + devStat = AudioQueueEnqueueBuffer(mac->audioQueue, + mac->audioBuffers[index], + 0, + NULL); + if (devStat != 0) + { + errCode = GetLastError(); + WLog_ERR(TAG, "AudioQueueEnqueueBuffer failed with %s [%d]", + winpr_strerror(errCode, errString, sizeof(errString)), errCode); + goto err_out; + } + } + + freerdp_dsp_context_reset_adpcm(mac->dsp_context); + + devStat = AudioQueueStart(mac->audioQueue, NULL); + if (devStat != 0) + { + errCode = GetLastError(); + WLog_ERR(TAG, "AudioQueueStart failed with %s [%d]", + winpr_strerror(errCode, errString, sizeof(errString)), errCode); + goto err_out; + } + mac->isOpen = true; + + return CHANNEL_RC_OK; + +err_out: + audin_mac_close(device); + return CHANNEL_RC_INITIALIZATION_ERROR; +} + +static UINT audin_mac_free(IAudinDevice* device) +{ + AudinMacDevice *mac = (AudinMacDevice*)device; + + int error; + + if (device == NULL) + return ERROR_INVALID_PARAMETER; + + if ((error = audin_mac_close(device))) + { + WLog_ERR(TAG, "audin_oss_close failed with error code %d!", error); + } + freerdp_dsp_context_free(mac->dsp_context); + free(mac); + + return CHANNEL_RC_OK; +} + +static COMMAND_LINE_ARGUMENT_A audin_mac_args[] = +{ + { "dev", COMMAND_LINE_VALUE_REQUIRED, "", NULL, NULL, -1, NULL, "audio device name" }, + { NULL, 0, NULL, NULL, NULL, -1, NULL, NULL } +}; + +static UINT audin_mac_parse_addin_args(AudinMacDevice *device, ADDIN_ARGV *args) +{ + DWORD errCode; + char errString[1024]; + int status; + char* str_num, *eptr; + DWORD flags; + COMMAND_LINE_ARGUMENT_A* arg; + AudinMacDevice* mac = (AudinMacDevice*)device; + + if (args->argc == 1) + return CHANNEL_RC_OK; + + flags = COMMAND_LINE_SIGIL_NONE | COMMAND_LINE_SEPARATOR_COLON | COMMAND_LINE_IGN_UNKNOWN_KEYWORD; + status = CommandLineParseArgumentsA(args->argc, (const char**)args->argv, audin_mac_args, flags, mac, NULL, NULL); + + if (status < 0) + return ERROR_INVALID_PARAMETER; + + arg = audin_mac_args; + + do + { + if (!(arg->Flags & COMMAND_LINE_VALUE_PRESENT)) + continue; + + CommandLineSwitchStart(arg) + CommandLineSwitchCase(arg, "dev") + { + str_num = _strdup(arg->Value); + if (!str_num) + { + errCode = GetLastError(); + WLog_ERR(TAG, "_strdup failed with %s [%d]", + winpr_strerror(errCode, errString, sizeof(errString)), errCode); + return CHANNEL_RC_NO_MEMORY; + } + mac->dev_unit = strtol(str_num, &eptr, 10); + + if (mac->dev_unit < 0 || *eptr != '\0') + mac->dev_unit = -1; + + free(str_num); + } + CommandLineSwitchEnd(arg) + } + while ((arg = CommandLineFindNextArgumentA(arg)) != NULL); + + return CHANNEL_RC_OK; +} + +#ifdef STATIC_CHANNELS +#define freerdp_audin_client_subsystem_entry mac_freerdp_audin_client_subsystem_entry +#endif + +UINT freerdp_audin_client_subsystem_entry(PFREERDP_AUDIN_DEVICE_ENTRY_POINTS pEntryPoints) +{ + DWORD errCode; + char errString[1024]; + ADDIN_ARGV *args; + AudinMacDevice *mac; + UINT error; + + mac = (AudinMacDevice*)calloc(1, sizeof(AudinMacDevice)); + if (!mac) + { + errCode = GetLastError(); + WLog_ERR(TAG, "calloc failed with %s [%d]", + winpr_strerror(errCode, errString, sizeof(errString)), errCode); + return CHANNEL_RC_NO_MEMORY; + } + + mac->iface.Open = audin_mac_open; + mac->iface.FormatSupported = audin_mac_format_supported; + mac->iface.SetFormat = audin_mac_set_format; + mac->iface.Close = audin_mac_close; + mac->iface.Free = audin_mac_free; + mac->rdpcontext = pEntryPoints->rdpcontext; + + mac->dev_unit = -1; + args = pEntryPoints->args; + + if ((error = audin_mac_parse_addin_args(mac, args))) + { + WLog_ERR(TAG, "audin_mac_parse_addin_args failed with %lu!", error); + goto error_out; + } + + mac->dsp_context = freerdp_dsp_context_new(); + if (!mac->dsp_context) + { + WLog_ERR(TAG, "freerdp_dsp_context_new failed!"); + error = CHANNEL_RC_NO_MEMORY; + goto error_out; + } + + if ((error = pEntryPoints->pRegisterAudinDevice(pEntryPoints->plugin, (IAudinDevice*) mac))) + { + WLog_ERR(TAG, "RegisterAudinDevice failed with error %lu!", error); + goto error_out; + } + + return CHANNEL_RC_OK; + +error_out: + freerdp_dsp_context_free(mac->dsp_context); + free(mac); + return error; + +} diff --git a/include/freerdp/client/audin.h b/include/freerdp/client/audin.h index 87eec5d2d..56a7f0046 100644 --- a/include/freerdp/client/audin.h +++ b/include/freerdp/client/audin.h @@ -29,7 +29,7 @@ * Subsystem Interface */ -typedef UINT (*AudinReceive) (BYTE* data, int size, void* userData); +typedef UINT (*AudinReceive) (const BYTE* data, int size, void* userData); typedef struct audin_format audinFormat; struct audin_format diff --git a/include/freerdp/codec/audio.h b/include/freerdp/codec/audio.h index d797f84f3..c018c715b 100644 --- a/include/freerdp/codec/audio.h +++ b/include/freerdp/codec/audio.h @@ -181,6 +181,7 @@ typedef struct AUDIO_FORMAT AUDIO_FORMAT; #define WAVE_FORMAT_NORRIS 0x1400 #define WAVE_FORMAT_SOUNDSPACE_MUSICOMPRESS 0x1500 #define WAVE_FORMAT_DVM 0x2000 +#define WAVE_FORMAT_AAC_MS 0xA106 /** * Audio Format Functions diff --git a/libfreerdp/codec/audio.c b/libfreerdp/codec/audio.c index 6d96628a9..068f2f541 100644 --- a/libfreerdp/codec/audio.c +++ b/libfreerdp/codec/audio.c @@ -105,6 +105,9 @@ char* rdpsnd_get_audio_tag_string(UINT16 wFormatTag) case WAVE_FORMAT_WMAUDIO2: return "WAVE_FORMAT_WMAUDIO2"; + + case WAVE_FORMAT_AAC_MS: + return "WAVE_FORMAT_AAC_MS"; } return "WAVE_FORMAT_UNKNOWN";