From 156f86e487e76658101facb7121371bce9489595 Mon Sep 17 00:00:00 2001 From: Martin Haimberger Date: Tue, 2 Jun 2015 00:50:38 -0700 Subject: [PATCH] hardend channel audin --- channels/audin/client/alsa/audin_alsa.c | 132 ++++-- channels/audin/client/audin_main.c | 382 ++++++++++++++---- .../audin/client/opensles/audin_opensl_es.c | 130 ++++-- channels/audin/client/oss/audin_oss.c | 107 ++++- channels/audin/client/pulse/audin_pulse.c | 138 ++++--- channels/audin/client/winmm/audin_winmm.c | 99 ++++- channels/audin/server/audin.c | 216 +++++++--- include/freerdp/client/audin.h | 16 +- include/freerdp/server/audin.h | 11 +- server/Sample/sf_audin.c | 12 +- 10 files changed, 929 insertions(+), 314 deletions(-) diff --git a/channels/audin/client/alsa/audin_alsa.c b/channels/audin/client/alsa/audin_alsa.c index fa0c57b02..0f4b04285 100644 --- a/channels/audin/client/alsa/audin_alsa.c +++ b/channels/audin/client/alsa/audin_alsa.c @@ -3,6 +3,8 @@ * Audio Input Redirection Virtual Channel - ALSA implementation * * Copyright 2010-2011 Vic Lee + * Copyright 2015 Thincast Technologies GmbH + * Copyright 2015 DI (FH) Martin Haimberger * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -98,11 +100,11 @@ static BOOL audin_alsa_set_params(AudinALSADevice* alsa, snd_pcm_t* capture_hand return TRUE; } -static BOOL audin_alsa_thread_receive(AudinALSADevice* alsa, BYTE* src, int size) +static WIN32ERROR audin_alsa_thread_receive(AudinALSADevice* alsa, BYTE* src, int size) { int frames; int cframes; - int ret = 0; + WIN32ERROR ret = CHANNEL_RC_OK; int encoded_size; BYTE* encoded_data; int rbytes_per_frame; @@ -174,7 +176,7 @@ static BOOL audin_alsa_thread_receive(AudinALSADevice* alsa, BYTE* src, int size alsa->buffer_frames = 0; - if (!ret) + if (ret != CHANNEL_RC_OK) break; } @@ -182,12 +184,12 @@ static BOOL audin_alsa_thread_receive(AudinALSADevice* alsa, BYTE* src, int size frames -= cframes; } - return (ret) ? TRUE : FALSE; + return ret; } static void* audin_alsa_thread_func(void* arg) { - int error; + long error; BYTE* buffer; int rbytes_per_frame; int tbytes_per_frame; @@ -198,8 +200,15 @@ static void* audin_alsa_thread_func(void* arg) rbytes_per_frame = alsa->actual_channels * alsa->bytes_per_channel; tbytes_per_frame = alsa->target_channels * alsa->bytes_per_channel; - buffer = (BYTE*) malloc(rbytes_per_frame * alsa->frames_per_packet); - ZeroMemory(buffer, rbytes_per_frame * alsa->frames_per_packet); + buffer = (BYTE*) calloc(1, rbytes_per_frame * alsa->frames_per_packet); + if (!buffer) + { + WLog_ERR(TAG, "calloc failed!"); + //TODO: signal error to freerdp + ExitThread((DWORD)CHANNEL_RC_NO_MEMORY); + return NULL; + } + freerdp_dsp_context_reset_adpcm(alsa->dsp_context); do @@ -230,8 +239,12 @@ static void* audin_alsa_thread_func(void* arg) break; } - if (!audin_alsa_thread_receive(alsa, buffer, error * rbytes_per_frame)) + if ((error = audin_alsa_thread_receive(alsa, buffer, error * rbytes_per_frame))) + { + WLog_ERR(TAG, "audin_alsa_thread_receive failed with error %lu", error); break; + } + } } while (0); @@ -242,12 +255,12 @@ static void* audin_alsa_thread_func(void* arg) snd_pcm_close(capture_handle); DEBUG_DVC("out"); - ExitThread(0); + ExitThread((DWORD)error); return NULL; } -static void audin_alsa_free(IAudinDevice* device) +static WIN32ERROR audin_alsa_free(IAudinDevice* device) { AudinALSADevice* alsa = (AudinALSADevice*) device; @@ -256,6 +269,7 @@ static void audin_alsa_free(IAudinDevice* device) free(alsa->device_name); free(alsa); + return CHANNEL_RC_OK; } static BOOL audin_alsa_format_supported(IAudinDevice* device, audinFormat* format) @@ -285,7 +299,7 @@ static BOOL audin_alsa_format_supported(IAudinDevice* device, audinFormat* forma return FALSE; } -static void audin_alsa_set_format(IAudinDevice* device, audinFormat* format, UINT32 FramesPerPacket) +static WIN32ERROR audin_alsa_set_format(IAudinDevice* device, audinFormat* format, UINT32 FramesPerPacket) { int bs; AudinALSADevice* alsa = (AudinALSADevice*) device; @@ -324,36 +338,51 @@ static void audin_alsa_set_format(IAudinDevice* device, audinFormat* format, UIN alsa->wformat = format->wFormatTag; alsa->block_size = format->nBlockAlign; + return CHANNEL_RC_OK; } -static void audin_alsa_open(IAudinDevice* device, AudinReceive receive, void* user_data) +static WIN32ERROR audin_alsa_open(IAudinDevice* device, AudinReceive receive, void* user_data) { - int rbytes_per_frame; int tbytes_per_frame; AudinALSADevice* alsa = (AudinALSADevice*) device; - DEBUG_DVC(""); - alsa->receive = receive; alsa->user_data = user_data; - rbytes_per_frame = alsa->actual_channels * alsa->bytes_per_channel; tbytes_per_frame = alsa->target_channels * alsa->bytes_per_channel; - alsa->buffer = (BYTE*) malloc(tbytes_per_frame * alsa->frames_per_packet); - ZeroMemory(alsa->buffer, tbytes_per_frame * alsa->frames_per_packet); + alsa->buffer = (BYTE*) calloc(1, tbytes_per_frame * alsa->frames_per_packet); + if (!alsa->buffer) + { + WLog_ERR(TAG, "calloc failed!"); + return ERROR_NOT_ENOUGH_MEMORY; + } alsa->buffer_frames = 0; - alsa->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL); - alsa->thread = CreateThread(NULL, 0, - (LPTHREAD_START_ROUTINE) audin_alsa_thread_func, alsa, 0, NULL); + if (!(alsa->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL))) + { + WLog_ERR(TAG, "CreateEvent failed!"); + goto error_out; + } + // TODO: add mechanism that threads can signal failure + if (!(alsa->thread = CreateThread(NULL, 0, + (LPTHREAD_START_ROUTINE) audin_alsa_thread_func, alsa, 0, NULL))) + { + WLog_ERR(TAG, "CreateThread failed!"); + goto error_out; + } + return CHANNEL_RC_OK; +error_out: + free(alsa->buffer); + alsa->buffer = NULL; + CloseHandle(alsa->stopEvent); + alsa->stopEvent = NULL; + return ERROR_INTERNAL_ERROR; } -static void audin_alsa_close(IAudinDevice* device) +static WIN32ERROR audin_alsa_close(IAudinDevice* device) { AudinALSADevice* alsa = (AudinALSADevice*) device; - DEBUG_DVC(""); - if (alsa->stopEvent) { SetEvent(alsa->stopEvent); @@ -371,6 +400,8 @@ static void audin_alsa_close(IAudinDevice* device) alsa->receive = NULL; alsa->user_data = NULL; + + return CHANNEL_RC_OK; } COMMAND_LINE_ARGUMENT_A audin_alsa_args[] = @@ -379,7 +410,7 @@ COMMAND_LINE_ARGUMENT_A audin_alsa_args[] = { NULL, 0, NULL, NULL, NULL, -1, NULL, NULL } }; -static void audin_alsa_parse_addin_args(AudinALSADevice* device, ADDIN_ARGV* args) +static WIN32ERROR audin_alsa_parse_addin_args(AudinALSADevice* device, ADDIN_ARGV* args) { int status; DWORD flags; @@ -402,24 +433,36 @@ static void audin_alsa_parse_addin_args(AudinALSADevice* device, ADDIN_ARGV* arg CommandLineSwitchCase(arg, "dev") { alsa->device_name = _strdup(arg->Value); + if(!alsa->device_name) + { + WLog_ERR(TAG, "_strdup failed!"); + return CHANNEL_RC_NO_MEMORY; + } } CommandLineSwitchEnd(arg) } while ((arg = CommandLineFindNextArgumentA(arg)) != NULL); + + return CHANNEL_RC_OK; } #ifdef STATIC_CHANNELS #define freerdp_audin_client_subsystem_entry alsa_freerdp_audin_client_subsystem_entry #endif -int freerdp_audin_client_subsystem_entry(PFREERDP_AUDIN_DEVICE_ENTRY_POINTS pEntryPoints) +WIN32ERROR freerdp_audin_client_subsystem_entry(PFREERDP_AUDIN_DEVICE_ENTRY_POINTS pEntryPoints) { ADDIN_ARGV* args; AudinALSADevice* alsa; + WIN32ERROR error; - alsa = (AudinALSADevice*) malloc(sizeof(AudinALSADevice)); - ZeroMemory(alsa, sizeof(AudinALSADevice)); + alsa = (AudinALSADevice*) calloc(1, sizeof(AudinALSADevice)); + if (!alsa) + { + WLog_ERR(TAG, "calloc failed!"); + return CHANNEL_RC_NO_MEMORY; + } alsa->iface.Open = audin_alsa_open; alsa->iface.FormatSupported = audin_alsa_format_supported; @@ -429,10 +472,22 @@ int freerdp_audin_client_subsystem_entry(PFREERDP_AUDIN_DEVICE_ENTRY_POINTS pEnt args = pEntryPoints->args; - audin_alsa_parse_addin_args(alsa, args); + if ((error = audin_alsa_parse_addin_args(alsa, args))) + { + WLog_ERR(TAG, "audin_alsa_parse_addin_args failed with errorcode %lu!", error); + goto error_out; + } if (!alsa->device_name) + { alsa->device_name = _strdup("default"); + if (!alsa->device_name) + { + WLog_ERR(TAG, "_strdup failed!"); + error = CHANNEL_RC_NO_MEMORY; + goto error_out; + } + } alsa->frames_per_packet = 128; alsa->target_rate = 22050; @@ -443,8 +498,23 @@ int freerdp_audin_client_subsystem_entry(PFREERDP_AUDIN_DEVICE_ENTRY_POINTS pEnt alsa->bytes_per_channel = 2; alsa->dsp_context = freerdp_dsp_context_new(); + if (!alsa->dsp_context) + { + WLog_ERR(TAG, "freerdp_dsp_context_new failed!"); + error = CHANNEL_RC_NO_MEMORY; + goto error_out; + } - pEntryPoints->pRegisterAudinDevice(pEntryPoints->plugin, (IAudinDevice*) alsa); + if ((error = pEntryPoints->pRegisterAudinDevice(pEntryPoints->plugin, (IAudinDevice*) alsa))) + { + WLog_ERR(TAG, "RegisterAudinDevice failed with error %lu!", error); + goto error_out; + } - return 0; + return CHANNEL_RC_OK; +error_out: + freerdp_dsp_context_free(alsa->dsp_context); + free(alsa->device_name); + free(alsa); + return error; } diff --git a/channels/audin/client/audin_main.c b/channels/audin/client/audin_main.c index e86233d46..128498687 100644 --- a/channels/audin/client/audin_main.c +++ b/channels/audin/client/audin_main.c @@ -3,6 +3,8 @@ * Audio Input Redirection Virtual Channel * * Copyright 2010-2011 Vic Lee + * Copyright 2015 Thincast Technologies GmbH + * Copyright 2015 DI (FH) Martin Haimberger * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -32,7 +34,7 @@ #include #include - +#include #include "audin_main.h" #define MSG_SNDIN_VERSION 0x01 @@ -88,9 +90,9 @@ struct _AUDIN_PLUGIN IAudinDevice* device; }; -static int audin_process_version(IWTSVirtualChannelCallback* pChannelCallback, wStream* s) +static WIN32ERROR audin_process_version(IWTSVirtualChannelCallback* pChannelCallback, wStream* s) { - int error; + WIN32ERROR error; wStream* out; UINT32 Version; AUDIN_CHANNEL_CALLBACK* callback = (AUDIN_CHANNEL_CALLBACK*) pChannelCallback; @@ -100,6 +102,13 @@ static int audin_process_version(IWTSVirtualChannelCallback* pChannelCallback, w DEBUG_DVC("process_version: Version=%d", Version); out = Stream_New(NULL, 5); + + if (!out) + { + WLog_ERR(TAG, "Stream_New failed!"); + return ERROR_OUTOFMEMORY; + } + Stream_Write_UINT8(out, MSG_SNDIN_VERSION); Stream_Write_UINT32(out, Version); error = callback->channel->Write(callback->channel, (UINT32) Stream_GetPosition(out), Stream_Buffer(out), NULL); @@ -108,7 +117,7 @@ static int audin_process_version(IWTSVirtualChannelCallback* pChannelCallback, w return error; } -static int audin_send_incoming_data_pdu(IWTSVirtualChannelCallback* pChannelCallback) +static WIN32ERROR audin_send_incoming_data_pdu(IWTSVirtualChannelCallback* pChannelCallback) { BYTE out_data[1]; AUDIN_CHANNEL_CALLBACK* callback = (AUDIN_CHANNEL_CALLBACK*) pChannelCallback; @@ -117,13 +126,13 @@ static int audin_send_incoming_data_pdu(IWTSVirtualChannelCallback* pChannelCall return callback->channel->Write(callback->channel, 1, out_data, NULL); } -static int audin_process_formats(IWTSVirtualChannelCallback* pChannelCallback, wStream* s) +static WIN32ERROR audin_process_formats(IWTSVirtualChannelCallback* pChannelCallback, wStream* s) { AUDIN_CHANNEL_CALLBACK* callback = (AUDIN_CHANNEL_CALLBACK*) pChannelCallback; AUDIN_PLUGIN* audin = (AUDIN_PLUGIN*) callback->plugin; UINT32 i; BYTE* fm; - int error; + WIN32ERROR error; wStream* out; UINT32 NumFormats; audinFormat format; @@ -134,14 +143,26 @@ static int audin_process_formats(IWTSVirtualChannelCallback* pChannelCallback, w if ((NumFormats < 1) || (NumFormats > 1000)) { WLog_ERR(TAG, "bad NumFormats %d", NumFormats); - return 1; + return ERROR_INVALID_DATA; } Stream_Seek_UINT32(s); /* cbSizeFormatsPacket */ - callback->formats = (audinFormat*) malloc(NumFormats * sizeof(audinFormat)); - ZeroMemory(callback->formats, NumFormats * sizeof(audinFormat)); + callback->formats = (audinFormat*) calloc(1, NumFormats * sizeof(audinFormat)); + if (!callback->formats) + { + WLog_ERR(TAG, "calloc failed!"); + return ERROR_INVALID_DATA; + } out = Stream_New(NULL, 9); + + if (!out) + { + error = CHANNEL_RC_NO_MEMORY; + WLog_ERR(TAG, "Stream_New failed!"); + goto out; + } + Stream_Seek(out, 9); /* SoundFormats (variable) */ @@ -178,9 +199,9 @@ static int audin_process_formats(IWTSVirtualChannelCallback* pChannelCallback, w /* Put the format to output buffer */ if (!Stream_EnsureRemainingCapacity(out, 18 + format.cbSize)) { - free(callback->formats); - Stream_Free(out, TRUE); - return 1; + error = CHANNEL_RC_NO_MEMORY; + WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!"); + goto out; } @@ -188,7 +209,11 @@ static int audin_process_formats(IWTSVirtualChannelCallback* pChannelCallback, w } } - audin_send_incoming_data_pdu(pChannelCallback); + if ((error = audin_send_incoming_data_pdu(pChannelCallback))) + { + WLog_ERR(TAG, "audin_send_incoming_data_pdu failed!"); + goto out; + } cbSizeFormatsPacket = (UINT32) Stream_GetPosition(out); Stream_SetPosition(out, 0); @@ -198,18 +223,31 @@ static int audin_process_formats(IWTSVirtualChannelCallback* pChannelCallback, w Stream_Write_UINT32(out, cbSizeFormatsPacket); /* cbSizeFormatsPacket (4 bytes) */ error = callback->channel->Write(callback->channel, cbSizeFormatsPacket, Stream_Buffer(out), NULL); +out: + if (error != CHANNEL_RC_OK) + { + free(callback->formats); + callback->formats = NULL; + } Stream_Free(out, TRUE); return error; } -static int audin_send_format_change_pdu(IWTSVirtualChannelCallback* pChannelCallback, UINT32 NewFormat) +static WIN32ERROR audin_send_format_change_pdu(IWTSVirtualChannelCallback* pChannelCallback, UINT32 NewFormat) { - int error; + WIN32ERROR error; wStream* out; AUDIN_CHANNEL_CALLBACK* callback = (AUDIN_CHANNEL_CALLBACK*) pChannelCallback; out = Stream_New(NULL, 5); + + if (!out) + { + WLog_ERR(TAG, "Stream_New failed!"); + return CHANNEL_RC_OK; + } + Stream_Write_UINT8(out, MSG_SNDIN_FORMATCHANGE); Stream_Write_UINT32(out, NewFormat); error = callback->channel->Write(callback->channel, 5, Stream_Buffer(out), NULL); @@ -218,13 +256,20 @@ static int audin_send_format_change_pdu(IWTSVirtualChannelCallback* pChannelCall return error; } -static int audin_send_open_reply_pdu(IWTSVirtualChannelCallback* pChannelCallback, UINT32 Result) +static WIN32ERROR audin_send_open_reply_pdu(IWTSVirtualChannelCallback* pChannelCallback, UINT32 Result) { - int error; + WIN32ERROR error; wStream* out; AUDIN_CHANNEL_CALLBACK* callback = (AUDIN_CHANNEL_CALLBACK*) pChannelCallback; out = Stream_New(NULL, 5); + + if (!out) + { + WLog_ERR(TAG, "Stream_New failed!"); + return CHANNEL_RC_NO_MEMORY; + } + Stream_Write_UINT8(out, MSG_SNDIN_OPEN_REPLY); Stream_Write_UINT32(out, Result); error = callback->channel->Write(callback->channel, 5, Stream_Buffer(out), NULL); @@ -233,33 +278,42 @@ static int audin_send_open_reply_pdu(IWTSVirtualChannelCallback* pChannelCallbac return error; } -static BOOL audin_receive_wave_data(BYTE* data, int size, void* user_data) +static WIN32ERROR audin_receive_wave_data(BYTE* data, int size, void* user_data) { - int error; + WIN32ERROR error; wStream* out; AUDIN_CHANNEL_CALLBACK* callback = (AUDIN_CHANNEL_CALLBACK*) user_data; - error = audin_send_incoming_data_pdu((IWTSVirtualChannelCallback*) callback); - - if (error != 0) - return FALSE; + if ((error = audin_send_incoming_data_pdu((IWTSVirtualChannelCallback*) callback))) + { + WLog_ERR(TAG, "audin_send_incoming_data_pdu failed!"); + return error; + } out = Stream_New(NULL, size + 1); + + if (!out) + { + WLog_ERR(TAG, "Stream_New failed!"); + return ERROR_NOT_ENOUGH_MEMORY; + } + Stream_Write_UINT8(out, MSG_SNDIN_DATA); Stream_Write(out, data, size); error = callback->channel->Write(callback->channel, (UINT32) Stream_GetPosition(out), Stream_Buffer(out), NULL); Stream_Free(out, TRUE); - return (error == 0 ? TRUE : FALSE); + return error; } -static int audin_process_open(IWTSVirtualChannelCallback* pChannelCallback, wStream* s) +static WIN32ERROR audin_process_open(IWTSVirtualChannelCallback* pChannelCallback, wStream* s) { AUDIN_CHANNEL_CALLBACK* callback = (AUDIN_CHANNEL_CALLBACK*) pChannelCallback; AUDIN_PLUGIN* audin = (AUDIN_PLUGIN*) callback->plugin; audinFormat* format; UINT32 initialFormat; UINT32 FramesPerPacket; + WIN32ERROR error = CHANNEL_RC_OK; Stream_Read_UINT32(s, FramesPerPacket); Stream_Read_UINT32(s, initialFormat); @@ -271,28 +325,45 @@ static int audin_process_open(IWTSVirtualChannelCallback* pChannelCallback, wStr { WLog_ERR(TAG, "invalid format index %d (total %d)", initialFormat, callback->formats_count); - return 1; + return ERROR_INVALID_DATA; } format = &callback->formats[initialFormat]; if (audin->device) { - IFCALL(audin->device->SetFormat, audin->device, format, FramesPerPacket); - IFCALL(audin->device->Open, audin->device, audin_receive_wave_data, callback); + IFCALLRET(audin->device->SetFormat, error, audin->device, format, FramesPerPacket); + if (error != CHANNEL_RC_OK) + { + WLog_ERR(TAG, "SetFormat failed with errorcode %lu", error); + return error; + } + IFCALLRET(audin->device->Open, error, audin->device, audin_receive_wave_data, callback); + if (error != CHANNEL_RC_OK) + { + WLog_ERR(TAG, "Open failed with errorcode %lu", error); + return error; + } } - audin_send_format_change_pdu(pChannelCallback, initialFormat); - audin_send_open_reply_pdu(pChannelCallback, 0); + if ((error = audin_send_format_change_pdu(pChannelCallback, initialFormat))) + { + WLog_ERR(TAG, "audin_send_format_change_pdu failed!"); + return error; + } - return 0; + if ((error = audin_send_open_reply_pdu(pChannelCallback, 0))) + WLog_ERR(TAG, "audin_send_open_reply_pdu failed!"); + + return error; } -static int audin_process_format_change(IWTSVirtualChannelCallback* pChannelCallback, wStream* s) +static WIN32ERROR audin_process_format_change(IWTSVirtualChannelCallback* pChannelCallback, wStream* s) { AUDIN_CHANNEL_CALLBACK* callback = (AUDIN_CHANNEL_CALLBACK*) pChannelCallback; AUDIN_PLUGIN * audin = (AUDIN_PLUGIN*) callback->plugin; UINT32 NewFormat; audinFormat* format; + WIN32ERROR error = CHANNEL_RC_OK; Stream_Read_UINT32(s, NewFormat); @@ -302,26 +373,42 @@ static int audin_process_format_change(IWTSVirtualChannelCallback* pChannelCallb { WLog_ERR(TAG, "invalid format index %d (total %d)", NewFormat, callback->formats_count); - return 1; + return ERROR_INVALID_DATA; } format = &callback->formats[NewFormat]; if (audin->device) { - IFCALL(audin->device->Close, audin->device); - IFCALL(audin->device->SetFormat, audin->device, format, 0); - IFCALL(audin->device->Open, audin->device, audin_receive_wave_data, callback); + IFCALLRET(audin->device->Close, error, audin->device); + if (error != CHANNEL_RC_OK) + { + WLog_ERR(TAG, "Close failed with errorcode %lu", error); + return error; + } + IFCALLRET(audin->device->SetFormat, error, audin->device, format, 0); + if (error != CHANNEL_RC_OK) + { + WLog_ERR(TAG, "SetFormat failed with errorcode %lu", error); + return error; + } + IFCALLRET(audin->device->Open, error, audin->device, audin_receive_wave_data, callback); + if (error != CHANNEL_RC_OK) + { + WLog_ERR(TAG, "Open failed with errorcode %lu", error); + return error; + } } - audin_send_format_change_pdu(pChannelCallback, NewFormat); + if ((error = audin_send_format_change_pdu(pChannelCallback, NewFormat))) + WLog_ERR(TAG, "audin_send_format_change_pdu failed!"); - return 0; + return error; } -static int audin_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, wStream *data) +static WIN32ERROR audin_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, wStream *data) { - int error; + WIN32ERROR error; BYTE MessageId; Stream_Read_UINT8(data, MessageId); @@ -348,30 +435,38 @@ static int audin_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, default: WLog_ERR(TAG, "unknown MessageId=0x%x", MessageId); - error = 1; + error = ERROR_INVALID_DATA; break; } return error; } -static int audin_on_close(IWTSVirtualChannelCallback* pChannelCallback) +static WIN32ERROR audin_on_close(IWTSVirtualChannelCallback* pChannelCallback) { AUDIN_CHANNEL_CALLBACK* callback = (AUDIN_CHANNEL_CALLBACK*) pChannelCallback; AUDIN_PLUGIN* audin = (AUDIN_PLUGIN*) callback->plugin; + WIN32ERROR error = CHANNEL_RC_OK; DEBUG_DVC("on_close"); if (audin->device) - IFCALL(audin->device->Close, audin->device); + { + IFCALLRET(audin->device->Close, error, audin->device); + if (error != CHANNEL_RC_OK) + { + WLog_ERR(TAG, "Close failed with errorcode %lu", error); + return error; + } + } free(callback->formats); free(callback); - return 0; + return error; } -static int audin_on_new_channel_connection(IWTSListenerCallback* pListenerCallback, +static WIN32ERROR audin_on_new_channel_connection(IWTSListenerCallback* pListenerCallback, IWTSVirtualChannel* pChannel, BYTE* Data, int* pbAccept, IWTSVirtualChannelCallback** ppCallback) { @@ -380,8 +475,12 @@ static int audin_on_new_channel_connection(IWTSListenerCallback* pListenerCallba DEBUG_DVC("on_new_channel_connection"); - callback = (AUDIN_CHANNEL_CALLBACK*) malloc(sizeof(AUDIN_CHANNEL_CALLBACK)); - ZeroMemory(callback, sizeof(AUDIN_CHANNEL_CALLBACK)); + callback = (AUDIN_CHANNEL_CALLBACK*) calloc(1, sizeof(AUDIN_CHANNEL_CALLBACK)); + if (!callback) + { + WLog_ERR(TAG, "calloc failed!"); + return CHANNEL_RC_NO_MEMORY; + } callback->iface.OnDataReceived = audin_on_data_received; callback->iface.OnClose = audin_on_close; @@ -391,17 +490,21 @@ static int audin_on_new_channel_connection(IWTSListenerCallback* pListenerCallba *ppCallback = (IWTSVirtualChannelCallback*) callback; - return 0; + return CHANNEL_RC_OK; } -static int audin_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelManager* pChannelMgr) +static WIN32ERROR audin_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelManager* pChannelMgr) { AUDIN_PLUGIN* audin = (AUDIN_PLUGIN*) pPlugin; DEBUG_DVC("plugin_initialize"); - audin->listener_callback = (AUDIN_LISTENER_CALLBACK*) malloc(sizeof(AUDIN_LISTENER_CALLBACK)); - ZeroMemory(audin->listener_callback, sizeof(AUDIN_LISTENER_CALLBACK)); + audin->listener_callback = (AUDIN_LISTENER_CALLBACK*) calloc(1, sizeof(AUDIN_LISTENER_CALLBACK)); + if (!audin->listener_callback) + { + WLog_ERR(TAG, "calloc failed!"); + return CHANNEL_RC_NO_MEMORY; + } audin->listener_callback->iface.OnNewChannelConnection = audin_on_new_channel_connection; audin->listener_callback->plugin = pPlugin; @@ -411,15 +514,21 @@ static int audin_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelManage (IWTSListenerCallback*) audin->listener_callback, NULL); } -static int audin_plugin_terminated(IWTSPlugin* pPlugin) +static WIN32ERROR audin_plugin_terminated(IWTSPlugin* pPlugin) { AUDIN_PLUGIN* audin = (AUDIN_PLUGIN*) pPlugin; + WIN32ERROR error = CHANNEL_RC_OK; DEBUG_DVC("plugin_terminated"); if (audin->device) { - IFCALL(audin->device->Free, audin->device); + IFCALLRET(audin->device->Free, error, audin->device); + if (error != CHANNEL_RC_OK) + { + WLog_ERR(TAG, "Free failed with errorcode %lu", error); + // dont stop on error + } audin->device = NULL; } @@ -432,57 +541,74 @@ static int audin_plugin_terminated(IWTSPlugin* pPlugin) free(audin->listener_callback); free(audin); - return 0; + return CHANNEL_RC_OK; } -static void audin_register_device_plugin(IWTSPlugin* pPlugin, IAudinDevice* device) +static WIN32ERROR audin_register_device_plugin(IWTSPlugin* pPlugin, IAudinDevice* device) { AUDIN_PLUGIN* audin = (AUDIN_PLUGIN*) pPlugin; if (audin->device) { WLog_ERR(TAG, "existing device, abort."); - return; + return ERROR_ALREADY_EXISTS; } DEBUG_DVC("register_device_plugin: device registered."); audin->device = device; + return CHANNEL_RC_OK; } -static BOOL audin_load_device_plugin(IWTSPlugin* pPlugin, const char* name, ADDIN_ARGV* args) +static WIN32ERROR audin_load_device_plugin(IWTSPlugin* pPlugin, const char* name, ADDIN_ARGV* args) { PFREERDP_AUDIN_DEVICE_ENTRY entry; FREERDP_AUDIN_DEVICE_ENTRY_POINTS entryPoints; + WIN32ERROR error; entry = (PFREERDP_AUDIN_DEVICE_ENTRY) freerdp_load_channel_addin_entry("audin", (LPSTR) name, NULL, 0); if (entry == NULL) - return FALSE; + { + WLog_ERR(TAG, "freerdp_load_channel_addin_entry did not return any function pointers for %s ", name); + return ERROR_INVALID_FUNCTION; + } entryPoints.plugin = pPlugin; entryPoints.pRegisterAudinDevice = audin_register_device_plugin; entryPoints.args = args; - if (entry(&entryPoints) != 0) + if ((error = entry(&entryPoints))) { - WLog_ERR(TAG, "%s entry returns error.", name); - return FALSE; + WLog_ERR(TAG, "%s entry returned error %lu.", name, error); + return error; } - return TRUE; + return CHANNEL_RC_OK; } -void audin_set_subsystem(AUDIN_PLUGIN* audin, char* subsystem) +WIN32ERROR audin_set_subsystem(AUDIN_PLUGIN* audin, char* subsystem) { free(audin->subsystem); audin->subsystem = _strdup(subsystem); + if (!audin->subsystem) + { + WLog_ERR(TAG, "_strdup failed!"); + return ERROR_NOT_ENOUGH_MEMORY; + } + return CHANNEL_RC_OK; } -void audin_set_device_name(AUDIN_PLUGIN* audin, char* device_name) +WIN32ERROR audin_set_device_name(AUDIN_PLUGIN* audin, char* device_name) { free(audin->device_name); audin->device_name = _strdup(device_name); + if (!audin->device_name) + { + WLog_ERR(TAG, "_strdup failed!"); + return ERROR_NOT_ENOUGH_MEMORY; + } + return CHANNEL_RC_OK; } COMMAND_LINE_ARGUMENT_A audin_args[] = @@ -501,6 +627,7 @@ static BOOL audin_process_addin_args(IWTSPlugin* pPlugin, ADDIN_ARGV* args) DWORD flags; COMMAND_LINE_ARGUMENT_A* arg; AUDIN_PLUGIN* audin = (AUDIN_PLUGIN*) pPlugin; + WIN32ERROR error; flags = COMMAND_LINE_SIGIL_NONE | COMMAND_LINE_SEPARATOR_COLON; @@ -518,11 +645,19 @@ static BOOL audin_process_addin_args(IWTSPlugin* pPlugin, ADDIN_ARGV* args) CommandLineSwitchCase(arg, "sys") { - audin_set_subsystem(audin, arg->Value); + if ((error = audin_set_subsystem(audin, arg->Value))) + { + WLog_ERR(TAG, "audin_set_subsystem failed with error %lu!", error); + return FALSE; + } } CommandLineSwitchCase(arg, "dev") { - audin_set_device_name(audin, arg->Value); + if ((error = audin_set_device_name(audin, arg->Value))) + { + WLog_ERR(TAG, "audin_set_device_name failed with error %lu!", error); + return FALSE; + } } CommandLineSwitchCase(arg, "format") { @@ -552,9 +687,9 @@ static BOOL audin_process_addin_args(IWTSPlugin* pPlugin, ADDIN_ARGV* args) #define DVCPluginEntry audin_DVCPluginEntry #endif -int DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints) +WIN32ERROR DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints) { - int error = 0; + WIN32ERROR error = CHANNEL_RC_OK; ADDIN_ARGV* args; AUDIN_PLUGIN* audin; @@ -564,8 +699,12 @@ int DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints) audin = (AUDIN_PLUGIN*) pEntryPoints->GetPlugin(pEntryPoints, "audin"); if (audin == NULL) { - audin = (AUDIN_PLUGIN*) malloc(sizeof(AUDIN_PLUGIN)); - ZeroMemory(audin, sizeof(AUDIN_PLUGIN)); + audin = (AUDIN_PLUGIN*) calloc(1, sizeof(AUDIN_PLUGIN)); + if (!audin) + { + WLog_ERR(TAG, "calloc failed!"); + return CHANNEL_RC_NO_MEMORY; + } audin->iface.Initialize = audin_plugin_initialize; audin->iface.Connected = NULL; @@ -577,54 +716,121 @@ int DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints) args = pEntryPoints->GetPluginData(pEntryPoints); - if (error == 0) + if (error == CHANNEL_RC_OK) audin_process_addin_args((IWTSPlugin*) audin, args); + else + { + WLog_ERR(TAG, "RegisterPlugin failed with error %lu!", error); + return error; + } - if (audin->subsystem) - audin_load_device_plugin((IWTSPlugin*) audin, audin->subsystem, args); + 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) { - audin_set_subsystem(audin, "pulse"); - audin_set_device_name(audin, ""); - audin_load_device_plugin((IWTSPlugin*) audin, audin->subsystem, args); + 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; + } } #endif #if defined(WITH_OSS) if (!audin->device) { - audin_set_subsystem(audin, "oss"); - audin_set_device_name(audin, "default"); - audin_load_device_plugin((IWTSPlugin*) audin, audin->subsystem, args); + 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) { - audin_set_subsystem(audin, "alsa"); - audin_set_device_name(audin, "default"); - audin_load_device_plugin((IWTSPlugin*) audin, audin->subsystem, args); + 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) { - audin_set_subsystem(audin, "opensles"); - audin_set_device_name(audin, "default"); - audin_load_device_plugin((IWTSPlugin*) audin, audin->subsystem, args); + 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) { - audin_set_subsystem(audin, "winmm"); - audin_set_device_name(audin, "default"); - audin_load_device_plugin((IWTSPlugin*) audin, audin->subsystem, args); + 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 diff --git a/channels/audin/client/opensles/audin_opensl_es.c b/channels/audin/client/opensles/audin_opensl_es.c index 6d9869bd9..841b1e405 100644 --- a/channels/audin/client/opensles/audin_opensl_es.c +++ b/channels/audin/client/opensles/audin_opensl_es.c @@ -3,6 +3,8 @@ * Audio Input Redirection Virtual Channel - OpenSL ES implementation * * Copyright 2013 Armin Novak + * Copyright 2015 Thincast Technologies GmbH + * Copyright 2015 DI (FH) Martin Haimberger * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -30,6 +32,7 @@ #include #include #include +#include #include #include @@ -74,7 +77,8 @@ static void* audin_opensles_thread_func(void* arg) BYTE *b; } buffer; AudinOpenSLESDevice* opensles = (AudinOpenSLESDevice*) arg; - const size_t raw_size = opensles->frames_per_packet * opensles->bytes_per_channel; + const size_t raw_size = opensles->frames_per_packet * opensles->bytes_per_channel; + int rc = CHANNEL_RC_OK; DEBUG_DVC("opensles=%p", opensles); @@ -84,19 +88,26 @@ static void* audin_opensles_thread_func(void* arg) assert(opensles->stopEvent); assert(opensles->stream); - buffer.v = malloc(raw_size); - ZeroMemory(buffer.v, raw_size); + buffer.v = calloc(1, raw_size); + if (!buffer.v) + { + WLog_ERR(TAG, "calloc failed!"); + //TODO: signal error to freerdp + ExitThread((DWORD)CHANNEL_RC_NO_MEMORY); + return NULL; + } + freerdp_dsp_context_reset_adpcm(opensles->dsp_context); - while (!(WaitForSingleObject(opensles->stopEvent, 0) == WAIT_OBJECT_0)) + while (WAIT_OBJECT_0 != WaitForSingleObject(opensles->stopEvent, 0)) { size_t encoded_size; void *encoded_data; - int rc = android_RecIn(opensles->stream, buffer.s, raw_size); + rc = android_RecIn(opensles->stream, buffer.s, raw_size); if (rc < 0) { - WLog_ERR(TAG, "android_RecIn %d", rc); + WLog_ERR(TAG, "android_RecIn %lu", rc); continue; } @@ -125,7 +136,7 @@ static void* audin_opensles_thread_func(void* arg) } rc = opensles->receive(encoded_data, encoded_size, opensles->user_data); - if (!rc) + if (rc) break; } @@ -133,11 +144,11 @@ static void* audin_opensles_thread_func(void* arg) DEBUG_DVC("thread shutdown."); - ExitThread(0); + ExitThread((DWORD)rc); return NULL; } -static void audin_opensles_free(IAudinDevice* device) +static WIN32ERROR audin_opensles_free(IAudinDevice* device) { AudinOpenSLESDevice* opensles = (AudinOpenSLESDevice*) device; @@ -146,7 +157,7 @@ static void audin_opensles_free(IAudinDevice* device) /* The function may have been called out of order, * ignore duplicate requests. */ if (!opensles) - return; + return CHANNEL_RC_OK; assert(opensles); assert(opensles->dsp_context); @@ -157,6 +168,8 @@ static void audin_opensles_free(IAudinDevice* device) free(opensles->device_name); free(opensles); + + return CHANNEL_RC_OK; } static BOOL audin_opensles_format_supported(IAudinDevice* device, audinFormat* format) @@ -201,7 +214,7 @@ static BOOL audin_opensles_format_supported(IAudinDevice* device, audinFormat* f return FALSE; } -static void audin_opensles_set_format(IAudinDevice* device, +static WIN32ERROR audin_opensles_set_format(IAudinDevice* device, audinFormat* format, UINT32 FramesPerPacket) { int bs; @@ -215,7 +228,7 @@ static void audin_opensles_set_format(IAudinDevice* device, /* The function may have been called out of order, ignore * requests before the device is available. */ if (!opensles) - return; + return CHANNEL_RC_OK; switch (format->wFormatTag) { @@ -252,7 +265,7 @@ static void audin_opensles_set_format(IAudinDevice* device, WLog_ERR(TAG, "Encoding '%d' [%08X] not supported", (format->wFormatTag), format->wFormatTag); - return; + return ERROR_UNSUPPORTED_TYPE; } opensles->rate = format->nSamplesPerSec; @@ -263,9 +276,10 @@ static void audin_opensles_set_format(IAudinDevice* device, DEBUG_DVC("aligned frames_per_packet=%d, block_size=%d", opensles->frames_per_packet, opensles->block_size); + return CHANNEL_RC_OK; } -static void audin_opensles_open(IAudinDevice* device, AudinReceive receive, +static WIN32ERROR audin_opensles_open(IAudinDevice* device, AudinReceive receive, void* user_data) { AudinOpenSLESDevice* opensles = (AudinOpenSLESDevice*) device; @@ -277,26 +291,45 @@ static void audin_opensles_open(IAudinDevice* device, AudinReceive receive, /* The function may have been called out of order, * ignore duplicate open requests. */ if(opensles->stream) - return; + return CHANNEL_RC_OK; - opensles->stream = android_OpenRecDevice( + if(!(opensles->stream = android_OpenRecDevice( opensles->device_name, opensles->rate, opensles->channels, opensles->frames_per_packet, - opensles->bytes_per_channel * 8); - assert(opensles->stream); + opensles->bytes_per_channel * 8))) + { + WLog_ERR(TAG, "android_OpenRecDevice failed!"); + return ERROR_INTERNAL_ERROR; + } opensles->receive = receive; opensles->user_data = user_data; - opensles->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL); - opensles->thread = CreateThread(NULL, 0, - (LPTHREAD_START_ROUTINE) audin_opensles_thread_func, - opensles, 0, NULL); + if (!(opensles->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL))) + { + WLog_ERR(TAG, "CreateEvent failed!"); + goto error_out; + } + // TODO: add mechanism that threads can signal failure + if (!(opensles->thread = CreateThread(NULL, 0, + (LPTHREAD_START_ROUTINE) audin_opensles_thread_func, + opensles, 0, NULL))) + { + WLog_ERR(TAG, "CreateThread failed!"); + goto error_out; + } + return CHANNEL_RC_OK; +error_out: + android_CloseRecDevice(opensles->stream); + opensles->stream = NULL; + CloseHandle(opensles->stopEvent); + opensles->stopEvent = NULL; + return ERROR_INTERNAL_ERROR; } -static void audin_opensles_close(IAudinDevice* device) +static WIN32ERROR audin_opensles_close(IAudinDevice* device) { AudinOpenSLESDevice* opensles = (AudinOpenSLESDevice*) device; @@ -309,7 +342,7 @@ static void audin_opensles_close(IAudinDevice* device) if (!opensles->stopEvent) { WLog_ERR(TAG, "[ERROR] function called without matching open."); - return; + return ERROR_REQUEST_OUT_OF_SEQUENCE; } assert(opensles->stopEvent); @@ -328,6 +361,8 @@ static void audin_opensles_close(IAudinDevice* device) opensles->receive = NULL; opensles->user_data = NULL; opensles->stream = NULL; + + return CHANNEL_RC_OK; } static COMMAND_LINE_ARGUMENT_A audin_opensles_args[] = @@ -337,10 +372,10 @@ static COMMAND_LINE_ARGUMENT_A audin_opensles_args[] = { NULL, 0, NULL, NULL, NULL, -1, NULL, NULL } }; -static int audin_opensles_parse_addin_args(AudinOpenSLESDevice* device, +static WIN32ERROR audin_opensles_parse_addin_args(AudinOpenSLESDevice* device, ADDIN_ARGV* args) { - int status; + WIN32ERROR status; DWORD flags; COMMAND_LINE_ARGUMENT_A* arg; AudinOpenSLESDevice* opensles = (AudinOpenSLESDevice*) device; @@ -366,13 +401,18 @@ static int audin_opensles_parse_addin_args(AudinOpenSLESDevice* device, CommandLineSwitchCase(arg, "dev") { opensles->device_name = _strdup(arg->Value); + if (!opensles->device_name) + { + WLog_ERR(TAG, "_strdup failed!"); + return CHANNEL_RC_NO_MEMORY; + } } CommandLineSwitchEnd(arg) } while ((arg = CommandLineFindNextArgumentA(arg)) != NULL); - return status; + return CHANNEL_RC_OK; } #ifdef STATIC_CHANNELS @@ -380,16 +420,21 @@ static int audin_opensles_parse_addin_args(AudinOpenSLESDevice* device, opensles_freerdp_audin_client_subsystem_entry #endif -int freerdp_audin_client_subsystem_entry( +WIN32ERROR freerdp_audin_client_subsystem_entry( PFREERDP_AUDIN_DEVICE_ENTRY_POINTS pEntryPoints) { ADDIN_ARGV* args; AudinOpenSLESDevice* opensles; + WIN32ERROR error; DEBUG_DVC("pEntryPoints=%p", pEntryPoints); - opensles = (AudinOpenSLESDevice*) malloc(sizeof(AudinOpenSLESDevice)); - ZeroMemory(opensles, sizeof(AudinOpenSLESDevice)); + opensles = (AudinOpenSLESDevice*) calloc(1, sizeof(AudinOpenSLESDevice)); + if (!opensles) + { + WLog_ERR(TAG, "calloc failed!"); + return CHANNEL_RC_NO_MEMORY; + } opensles->iface.Open = audin_opensles_open; opensles->iface.FormatSupported = audin_opensles_format_supported; @@ -399,12 +444,29 @@ int freerdp_audin_client_subsystem_entry( args = pEntryPoints->args; - audin_opensles_parse_addin_args(opensles, args); + if ((error = audin_opensles_parse_addin_args(opensles, args))) + { + WLog_ERR(TAG, "audin_opensles_parse_addin_args failed with errorcode %d!", error); + goto error_out; + } opensles->dsp_context = freerdp_dsp_context_new(); + if (!opensles->dsp_context) + { + WLog_ERR(TAG, "freerdp_dsp_context_new failed!"); + error = CHANNEL_RC_NO_MEMORY; + goto error_out; + } - pEntryPoints->pRegisterAudinDevice(pEntryPoints->plugin, - (IAudinDevice*) opensles); + if ((error = pEntryPoints->pRegisterAudinDevice(pEntryPoints->plugin, (IAudinDevice*) opensles))) + { + WLog_ERR(TAG, "RegisterAudinDevice failed with error %d!", error); + goto error_out; + } - return 0; + return CHANNEL_RC_OK; +error_out: + freerdp_dsp_context_free(opensles->dsp_context); + free(opensles); + return error; } diff --git a/channels/audin/client/oss/audin_oss.c b/channels/audin/client/oss/audin_oss.c index 6052fd55e..b45f7b740 100644 --- a/channels/audin/client/oss/audin_oss.c +++ b/channels/audin/client/oss/audin_oss.c @@ -3,6 +3,8 @@ * Audio Input Redirection Virtual Channel - OSS implementation * * Copyright (c) 2015 Rozhuk Ivan + * Copyright 2015 Thincast Technologies GmbH + * Copyright 2015 DI (FH) Martin Haimberger * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -29,6 +31,7 @@ #include #include #include +#include #include #include @@ -125,11 +128,11 @@ static BOOL audin_oss_format_supported(IAudinDevice *device, audinFormat *format return TRUE; } -static void audin_oss_set_format(IAudinDevice *device, audinFormat *format, UINT32 FramesPerPacket) { +static WIN32ERROR audin_oss_set_format(IAudinDevice *device, audinFormat *format, UINT32 FramesPerPacket) { AudinOSSDevice *oss = (AudinOSSDevice*)device; if (device == NULL || format == NULL) - return; + return ERROR_INVALID_PARAMETER; oss->FramesPerPacket = FramesPerPacket; CopyMemory(&(oss->format), format, sizeof(audinFormat)); @@ -140,6 +143,7 @@ static void audin_oss_set_format(IAudinDevice *device, audinFormat *format, UINT oss->format.wBitsPerSample *= 4; break; } + return CHANNEL_RC_OK; } static void *audin_oss_thread_func(void *arg) @@ -149,6 +153,7 @@ static void *audin_oss_thread_func(void *arg) BYTE *buffer = NULL, *encoded_data; int tmp, buffer_size, encoded_size; AudinOSSDevice *oss = (AudinOSSDevice*)arg; + WIN32ERROR error; if (arg == NULL) goto err_out; @@ -184,12 +189,11 @@ static void *audin_oss_thread_func(void *arg) OSS_LOG_ERR("SNDCTL_DSP_SETFRAGMENT failed", errno); buffer_size = (oss->FramesPerPacket * oss->format.nChannels * (oss->format.wBitsPerSample / 8)); - buffer = (BYTE*)malloc((buffer_size + sizeof(void*))); + buffer = (BYTE*)calloc(1, (buffer_size + sizeof(void*))); if (NULL == buffer) { OSS_LOG_ERR("malloc() fail", errno); goto err_out; } - ZeroMemory(buffer, buffer_size); freerdp_dsp_context_reset_adpcm(oss->dsp_context); @@ -220,8 +224,12 @@ static void *audin_oss_thread_func(void *arg) encoded_size = buffer_size; break; } - if (0 != oss->receive(encoded_data, encoded_size, oss->user_data)) + if ((error = oss->receive(encoded_data, encoded_size, oss->user_data))) + { + WLog_ERR(TAG, "oss->receive failed with error %lu", error); break; + } + } err_out: @@ -234,21 +242,35 @@ err_out: return NULL; } -static void audin_oss_open(IAudinDevice *device, AudinReceive receive, void *user_data) { +static WIN32ERROR audin_oss_open(IAudinDevice *device, AudinReceive receive, void *user_data) { AudinOSSDevice *oss = (AudinOSSDevice*)device; oss->receive = receive; oss->user_data = user_data; - oss->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL); - oss->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)audin_oss_thread_func, oss, 0, NULL); + if (!(oss->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL))) + { + WLog_ERR(TAG, "CreateEvent failed!"); + return ERROR_INTERNAL_ERROR; + } + // TODO: add mechanism that threads can signal failure + if (!(oss->thread = CreateThread(NULL, 0, + (LPTHREAD_START_ROUTINE)audin_oss_thread_func, oss, 0, NULL))) + { + WLog_ERR(TAG, "CreateThread failed!"); + CloseHandle(oss->stopEvent); + oss->stopEvent = NULL; + return ERROR_INTERNAL_ERROR; + } + + return CHANNEL_RC_OK; } -static void audin_oss_close(IAudinDevice *device) { +static WIN32ERROR audin_oss_close(IAudinDevice *device) { AudinOSSDevice *oss = (AudinOSSDevice*)device; if (device == NULL) - return; + return ERROR_INVALID_PARAMETER; if (oss->stopEvent != NULL) { SetEvent(oss->stopEvent); @@ -263,18 +285,27 @@ static void audin_oss_close(IAudinDevice *device) { oss->receive = NULL; oss->user_data = NULL; + + return CHANNEL_RC_OK; } -static void audin_oss_free(IAudinDevice *device) { +static WIN32ERROR audin_oss_free(IAudinDevice *device) { AudinOSSDevice *oss = (AudinOSSDevice*)device; - if (device == NULL) - return; + int error; - audin_oss_close(device); + if (device == NULL) + return ERROR_INVALID_PARAMETER; + + if ((error = audin_oss_close(device))) + { + WLog_ERR(TAG, "audin_oss_close failed with error code %d!", error); + } freerdp_dsp_context_free(oss->dsp_context); free(oss); + + return CHANNEL_RC_OK; } COMMAND_LINE_ARGUMENT_A audin_oss_args[] = { @@ -282,7 +313,7 @@ COMMAND_LINE_ARGUMENT_A audin_oss_args[] = { { NULL, 0, NULL, NULL, NULL, -1, NULL, NULL } }; -static void audin_oss_parse_addin_args(AudinOSSDevice *device, ADDIN_ARGV *args) { +static WIN32ERROR audin_oss_parse_addin_args(AudinOSSDevice *device, ADDIN_ARGV *args) { int status; char *str_num, *eptr; DWORD flags; @@ -293,7 +324,7 @@ static void audin_oss_parse_addin_args(AudinOSSDevice *device, ADDIN_ARGV *args) status = CommandLineParseArgumentsA(args->argc, (const char**)args->argv, audin_oss_args, flags, oss, NULL, NULL); if (status < 0) - return; + return ERROR_INVALID_PARAMETER; arg = audin_oss_args; @@ -305,6 +336,11 @@ static void audin_oss_parse_addin_args(AudinOSSDevice *device, ADDIN_ARGV *args) CommandLineSwitchCase(arg, "dev") { str_num = _strdup(arg->Value); + if (!str_num) + { + WLog_ERR(TAG, "_strdup failed!"); + return CHANNEL_RC_NO_MEMORY; + } oss->dev_unit = strtol(str_num, &eptr, 10); if (oss->dev_unit < 0 || *eptr != '\0') oss->dev_unit = -1; @@ -313,18 +349,25 @@ static void audin_oss_parse_addin_args(AudinOSSDevice *device, ADDIN_ARGV *args) CommandLineSwitchEnd(arg) } while ((arg = CommandLineFindNextArgumentA(arg)) != NULL); + + return CHANNEL_RC_OK; } #ifdef STATIC_CHANNELS #define freerdp_audin_client_subsystem_entry oss_freerdp_audin_client_subsystem_entry #endif -int freerdp_audin_client_subsystem_entry(PFREERDP_AUDIN_DEVICE_ENTRY_POINTS pEntryPoints) { +WIN32ERROR freerdp_audin_client_subsystem_entry(PFREERDP_AUDIN_DEVICE_ENTRY_POINTS pEntryPoints) { ADDIN_ARGV *args; AudinOSSDevice *oss; + WIN32ERROR error; - oss = (AudinOSSDevice*)malloc(sizeof(AudinOSSDevice)); - ZeroMemory(oss, sizeof(AudinOSSDevice)); + oss = (AudinOSSDevice*)calloc(1, sizeof(AudinOSSDevice)); + if (!oss) + { + WLog_ERR(TAG, "calloc failed!"); + return CHANNEL_RC_NO_MEMORY; + } oss->iface.Open = audin_oss_open; oss->iface.FormatSupported = audin_oss_format_supported; @@ -335,11 +378,31 @@ int freerdp_audin_client_subsystem_entry(PFREERDP_AUDIN_DEVICE_ENTRY_POINTS pEnt oss->dev_unit = -1; args = pEntryPoints->args; - audin_oss_parse_addin_args(oss, args); + + if ((error = audin_oss_parse_addin_args(oss, args))) + { + WLog_ERR(TAG, "audin_oss_parse_addin_args failed with errorcode %lu!", error); + goto error_out; + } oss->dsp_context = freerdp_dsp_context_new(); + if (!oss->dsp_context) + { + WLog_ERR(TAG, "freerdp_dsp_context_new failed!"); + error = CHANNEL_RC_NO_MEMORY; + goto error_out; + } - pEntryPoints->pRegisterAudinDevice(pEntryPoints->plugin, (IAudinDevice*)oss); + if ((error = pEntryPoints->pRegisterAudinDevice(pEntryPoints->plugin, (IAudinDevice*) oss))) + { + WLog_ERR(TAG, "RegisterAudinDevice failed with error %lu!", error); + goto error_out; + } + + return CHANNEL_RC_OK; +error_out: + freerdp_dsp_context_free(oss->dsp_context); + free(oss); + return error; - return 0; } diff --git a/channels/audin/client/pulse/audin_pulse.c b/channels/audin/client/pulse/audin_pulse.c index 73b45f36c..a5cd78a56 100644 --- a/channels/audin/client/pulse/audin_pulse.c +++ b/channels/audin/client/pulse/audin_pulse.c @@ -3,6 +3,8 @@ * Audio Input Redirection Virtual Channel - PulseAudio implementation * * Copyright 2010-2011 Vic Lee + * Copyright 2015 Thincast Technologies GmbH + * Copyright 2015 DI (FH) Martin Haimberger * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -27,6 +29,7 @@ #include #include +#include #include @@ -84,19 +87,19 @@ static void audin_pulse_context_state_callback(pa_context* context, void* userda } } -static BOOL audin_pulse_connect(IAudinDevice* device) +static WIN32ERROR audin_pulse_connect(IAudinDevice* device) { pa_context_state_t state; AudinPulseDevice* pulse = (AudinPulseDevice*) device; if (!pulse->context) - return FALSE; + return ERROR_INVALID_PARAMETER; if (pa_context_connect(pulse->context, NULL, 0, NULL)) { WLog_ERR(TAG, "pa_context_connect failed (%d)", pa_context_errno(pulse->context)); - return FALSE; + return ERROR_INTERNAL_ERROR; } pa_threaded_mainloop_lock(pulse->mainloop); if (pa_threaded_mainloop_start(pulse->mainloop) < 0) @@ -104,7 +107,7 @@ static BOOL audin_pulse_connect(IAudinDevice* device) pa_threaded_mainloop_unlock(pulse->mainloop); WLog_ERR(TAG, "pa_threaded_mainloop_start failed (%d)", pa_context_errno(pulse->context)); - return FALSE; + return ERROR_INTERNAL_ERROR; } for (;;) { @@ -115,31 +118,22 @@ static BOOL audin_pulse_connect(IAudinDevice* device) { WLog_ERR(TAG, "bad context state (%d)", pa_context_errno(pulse->context)); - break; + pa_context_disconnect(pulse->context); + return ERROR_INVALID_STATE; } pa_threaded_mainloop_wait(pulse->mainloop); } pa_threaded_mainloop_unlock(pulse->mainloop); - if (state == PA_CONTEXT_READY) - { - DEBUG_DVC("connected"); - return TRUE; - } - else - { - pa_context_disconnect(pulse->context); - return FALSE; - } + DEBUG_DVC("connected"); + return CHANNEL_RC_OK; } -static void audin_pulse_free(IAudinDevice* device) +static WIN32ERROR audin_pulse_free(IAudinDevice* device) { AudinPulseDevice* pulse = (AudinPulseDevice*) device; - DEBUG_DVC(""); - if (!pulse) - return; + return ERROR_INVALID_PARAMETER; if (pulse->mainloop) { pa_threaded_mainloop_stop(pulse->mainloop); @@ -157,6 +151,8 @@ static void audin_pulse_free(IAudinDevice* device) } freerdp_dsp_context_free(pulse->dsp_context); free(pulse); + + return CHANNEL_RC_OK; } static BOOL audin_pulse_format_supported(IAudinDevice* device, audinFormat* format) @@ -201,14 +197,14 @@ static BOOL audin_pulse_format_supported(IAudinDevice* device, audinFormat* form return FALSE; } -static void audin_pulse_set_format(IAudinDevice* device, audinFormat* format, UINT32 FramesPerPacket) +static WIN32ERROR audin_pulse_set_format(IAudinDevice* device, audinFormat* format, UINT32 FramesPerPacket) { int bs; pa_sample_spec sample_spec = { 0 }; AudinPulseDevice* pulse = (AudinPulseDevice*) device; if (!pulse->context) - return; + return ERROR_INVALID_PARAMETER; if (FramesPerPacket > 0) { @@ -252,6 +248,7 @@ static void audin_pulse_set_format(IAudinDevice* device, audinFormat* format, UI pulse->sample_spec = sample_spec; pulse->format = format->wFormatTag; pulse->block_size = format->nBlockAlign; + return CHANNEL_RC_OK; } static void audin_pulse_stream_state_callback(pa_stream* stream, void* userdata) @@ -347,14 +344,12 @@ static void audin_pulse_stream_request_callback(pa_stream* stream, size_t length } -static void audin_pulse_close(IAudinDevice* device) +static WIN32ERROR audin_pulse_close(IAudinDevice* device) { AudinPulseDevice* pulse = (AudinPulseDevice*) device; if (!pulse->context || !pulse->stream) - return; - - DEBUG_DVC(""); + return ERROR_INVALID_PARAMETER; pa_threaded_mainloop_lock(pulse->mainloop); pa_stream_disconnect(pulse->stream); @@ -370,20 +365,19 @@ static void audin_pulse_close(IAudinDevice* device) pulse->buffer = NULL; pulse->buffer_frames = 0; } + return CHANNEL_RC_OK; } -static void audin_pulse_open(IAudinDevice* device, AudinReceive receive, void* user_data) +static WIN32ERROR audin_pulse_open(IAudinDevice* device, AudinReceive receive, void* user_data) { pa_stream_state_t state; pa_buffer_attr buffer_attr = { 0 }; AudinPulseDevice* pulse = (AudinPulseDevice*) device; if (!pulse->context) - return; + return ERROR_INVALID_PARAMETER; if (!pulse->sample_spec.rate || pulse->stream) - return; - - DEBUG_DVC(""); + return ERROR_INVALID_PARAMETER; pulse->buffer = NULL; pulse->receive = receive; @@ -397,7 +391,7 @@ static void audin_pulse_open(IAudinDevice* device, AudinReceive receive, void* u pa_threaded_mainloop_unlock(pulse->mainloop); DEBUG_DVC("pa_stream_new failed (%d)", pa_context_errno(pulse->context)); - return; + return pa_context_errno(pulse->context); } pulse->bytes_per_frame = pa_frame_size(&pulse->sample_spec); pa_stream_set_state_callback(pulse->stream, @@ -417,7 +411,7 @@ static void audin_pulse_open(IAudinDevice* device, AudinReceive receive, void* u pa_threaded_mainloop_unlock(pulse->mainloop); WLog_ERR(TAG, "pa_stream_connect_playback failed (%d)", pa_context_errno(pulse->context)); - return; + return pa_context_errno(pulse->context); } for (;;) @@ -427,25 +421,24 @@ static void audin_pulse_open(IAudinDevice* device, AudinReceive receive, void* u break; if (!PA_STREAM_IS_GOOD(state)) { + audin_pulse_close(device); WLog_ERR(TAG, "bad stream state (%d)", pa_context_errno(pulse->context)); - break; + pa_threaded_mainloop_unlock(pulse->mainloop); + return pa_context_errno(pulse->context); } pa_threaded_mainloop_wait(pulse->mainloop); } pa_threaded_mainloop_unlock(pulse->mainloop); - if (state == PA_STREAM_READY) - { - freerdp_dsp_context_reset_adpcm(pulse->dsp_context); - pulse->buffer = malloc(pulse->bytes_per_frame * pulse->frames_per_packet); - ZeroMemory(pulse->buffer, pulse->bytes_per_frame * pulse->frames_per_packet); - pulse->buffer_frames = 0; - DEBUG_DVC("connected"); - } - else - { - audin_pulse_close(device); + freerdp_dsp_context_reset_adpcm(pulse->dsp_context); + pulse->buffer = calloc(1, pulse->bytes_per_frame * pulse->frames_per_packet); + if (!pulse->buffer) { + WLog_ERR(TAG, "calloc failed!"); + return CHANNEL_RC_OK; } + pulse->buffer_frames = 0; + DEBUG_DVC("connected"); + return CHANNEL_RC_OK; } static COMMAND_LINE_ARGUMENT_A audin_pulse_args[] = @@ -454,7 +447,7 @@ static COMMAND_LINE_ARGUMENT_A audin_pulse_args[] = { NULL, 0, NULL, NULL, NULL, -1, NULL, NULL } }; -static void audin_pulse_parse_addin_args(AudinPulseDevice* device, ADDIN_ARGV* args) +static WIN32ERROR audin_pulse_parse_addin_args(AudinPulseDevice* device, ADDIN_ARGV* args) { int status; DWORD flags; @@ -477,24 +470,36 @@ static void audin_pulse_parse_addin_args(AudinPulseDevice* device, ADDIN_ARGV* a CommandLineSwitchCase(arg, "dev") { pulse->device_name = _strdup(arg->Value); + if (!pulse->device_name) + { + WLog_ERR(TAG, "_strdup failed!"); + return CHANNEL_RC_NO_MEMORY; + } } CommandLineSwitchEnd(arg) } while ((arg = CommandLineFindNextArgumentA(arg)) != NULL); + + return CHANNEL_RC_OK; } #ifdef STATIC_CHANNELS #define freerdp_audin_client_subsystem_entry pulse_freerdp_audin_client_subsystem_entry #endif -int freerdp_audin_client_subsystem_entry(PFREERDP_AUDIN_DEVICE_ENTRY_POINTS pEntryPoints) +WIN32ERROR freerdp_audin_client_subsystem_entry(PFREERDP_AUDIN_DEVICE_ENTRY_POINTS pEntryPoints) { ADDIN_ARGV* args; AudinPulseDevice* pulse; + WIN32ERROR error; - pulse = (AudinPulseDevice*) malloc(sizeof(AudinPulseDevice)); - ZeroMemory(pulse, sizeof(AudinPulseDevice)); + pulse = (AudinPulseDevice*) calloc(1, sizeof(AudinPulseDevice)); + if (!pulse) + { + WLog_ERR(TAG, "calloc failed!"); + return CHANNEL_RC_NO_MEMORY; + } pulse->iface.Open = audin_pulse_open; pulse->iface.FormatSupported = audin_pulse_format_supported; @@ -504,17 +509,27 @@ int freerdp_audin_client_subsystem_entry(PFREERDP_AUDIN_DEVICE_ENTRY_POINTS pEnt args = pEntryPoints->args; - audin_pulse_parse_addin_args(pulse, args); + if ((error = audin_pulse_parse_addin_args(pulse, args))) + { + WLog_ERR(TAG, "audin_pulse_parse_addin_args failed with error %lu!", error); + goto error_out; + } pulse->dsp_context = freerdp_dsp_context_new(); + if (!pulse->dsp_context) + { + WLog_ERR(TAG, "freerdp_dsp_context_new failed!"); + error = CHANNEL_RC_NO_MEMORY; + goto error_out; + } pulse->mainloop = pa_threaded_mainloop_new(); if (!pulse->mainloop) { WLog_ERR(TAG, "pa_threaded_mainloop_new failed"); - audin_pulse_free((IAudinDevice*) pulse); - return 1; + error = CHANNEL_RC_NO_MEMORY; + goto error_out; } pulse->context = pa_context_new(pa_threaded_mainloop_get_api(pulse->mainloop), "freerdp"); @@ -522,20 +537,27 @@ int freerdp_audin_client_subsystem_entry(PFREERDP_AUDIN_DEVICE_ENTRY_POINTS pEnt if (!pulse->context) { WLog_ERR(TAG, "pa_context_new failed"); - audin_pulse_free((IAudinDevice*) pulse); - return 1; + error = CHANNEL_RC_NO_MEMORY; + goto error_out; } pa_context_set_state_callback(pulse->context, audin_pulse_context_state_callback, pulse); - if (!audin_pulse_connect((IAudinDevice*) pulse)) + if ((error = audin_pulse_connect((IAudinDevice*) pulse))) { - audin_pulse_free((IAudinDevice*) pulse); - return 1; + WLog_ERR(TAG, "audin_pulse_connect failed"); + goto error_out; } - pEntryPoints->pRegisterAudinDevice(pEntryPoints->plugin, (IAudinDevice*) pulse); + if ((error = pEntryPoints->pRegisterAudinDevice(pEntryPoints->plugin, (IAudinDevice*) pulse))) + { + WLog_ERR(TAG, "RegisterAudinDevice failed with error %lu!", error); + goto error_out; + } - return 0; + return CHANNEL_RC_OK; +error_out: + audin_pulse_free((IAudinDevice*)pulse); + return error; } diff --git a/channels/audin/client/winmm/audin_winmm.c b/channels/audin/client/winmm/audin_winmm.c index 5f1b6bbdd..c651febb7 100644 --- a/channels/audin/client/winmm/audin_winmm.c +++ b/channels/audin/client/winmm/audin_winmm.c @@ -3,6 +3,8 @@ * Audio Input Redirection Virtual Channel - WinMM implementation * * Copyright 2013 Zhang Zhaolong + * Copyright 2015 Thincast Technologies GmbH + * Copyright 2015 DI (FH) Martin Haimberger * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -103,6 +105,8 @@ static DWORD audin_winmm_thread_func(void* arg) for (i = 0; i < 4; i++) { buffer = (char *) malloc(size); + if (!buffer) + return CHANNEL_RC_NO_MEMORY; waveHdr[i].dwBufferLength = size; waveHdr[i].dwFlags = 0; waveHdr[i].lpData = buffer; @@ -136,7 +140,7 @@ static DWORD audin_winmm_thread_func(void* arg) return 0; } -static void audin_winmm_free(IAudinDevice* device) +static WIN32ERROR audin_winmm_free(IAudinDevice* device) { UINT32 i; AudinWinmmDevice* winmm = (AudinWinmmDevice*) device; @@ -149,14 +153,14 @@ static void audin_winmm_free(IAudinDevice* device) free(winmm->ppwfx); free(winmm->device_name); free(winmm); + + return CHANNEL_RC_OK; } -static void audin_winmm_close(IAudinDevice* device) +static WIN32ERROR audin_winmm_close(IAudinDevice* device) { AudinWinmmDevice* winmm = (AudinWinmmDevice*) device; - DEBUG_DVC(""); - SetEvent(winmm->stopEvent); WaitForSingleObject(winmm->thread, INFINITE); @@ -168,9 +172,11 @@ static void audin_winmm_close(IAudinDevice* device) winmm->stopEvent = NULL; winmm->receive = NULL; winmm->user_data = NULL; + + return CHANNEL_RC_OK; } -static void audin_winmm_set_format(IAudinDevice* device, audinFormat* format, UINT32 FramesPerPacket) +static WIN32ERROR audin_winmm_set_format(IAudinDevice* device, audinFormat* format, UINT32 FramesPerPacket) { UINT32 i; AudinWinmmDevice* winmm = (AudinWinmmDevice*) device; @@ -187,6 +193,7 @@ static void audin_winmm_set_format(IAudinDevice* device, audinFormat* format, UI break; } } + return CHANNEL_RC_OK; } static BOOL audin_winmm_format_supported(IAudinDevice* device, audinFormat* format) @@ -196,6 +203,8 @@ static BOOL audin_winmm_format_supported(IAudinDevice* device, audinFormat* form BYTE *data; pwfx = (PWAVEFORMATEX)malloc(sizeof(WAVEFORMATEX) + format->cbSize); + if (!pwfx) + return FALSE; pwfx->cbSize = format->cbSize; pwfx->wFormatTag = format->wFormatTag; pwfx->nChannels = format->nChannels; @@ -216,32 +225,43 @@ static BOOL audin_winmm_format_supported(IAudinDevice* device, audinFormat* form PWAVEFORMATEX *tmp_ppwfx; tmp_ppwfx = realloc(winmm->ppwfx, sizeof(PWAVEFORMATEX) * winmm->ppwfx_size * 2); if (!tmp_ppwfx) - return 0; + return FALSE; winmm->ppwfx_size *= 2; winmm->ppwfx = tmp_ppwfx; } winmm->ppwfx[winmm->cFormats++] = pwfx; - return 1; + return TRUE; } } free(pwfx); - return 0; + return FALSE; } -static void audin_winmm_open(IAudinDevice* device, AudinReceive receive, void* user_data) +static WIN32ERROR audin_winmm_open(IAudinDevice* device, AudinReceive receive, void* user_data) { AudinWinmmDevice* winmm = (AudinWinmmDevice*) device; - DEBUG_DVC(""); - winmm->receive = receive; winmm->user_data = user_data; - winmm->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL); - winmm->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) audin_winmm_thread_func, winmm, 0, NULL); + if (!(winmm->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL))) + { + WLog_ERR(TAG, "CreateEvent failed!"); + return ERROR_INTERNAL_ERROR; + } + // TODO: add mechanism that threads can signal failure + if (!(winmm->thread = CreateThread(NULL, 0, + (LPTHREAD_START_ROUTINE) audin_winmm_thread_func, winmm, 0, NULL))) + { + WLog_ERR(TAG, "CreateThread failed!"); + CloseHandle(winmm->stopEvent); + winmm->stopEvent = NULL; + return ERROR_INTERNAL_ERROR; + } + return CHANNEL_RC_OK; } static COMMAND_LINE_ARGUMENT_A audin_winmm_args[] = @@ -250,7 +270,7 @@ static COMMAND_LINE_ARGUMENT_A audin_winmm_args[] = { NULL, 0, NULL, NULL, NULL, -1, NULL, NULL } }; -static void audin_winmm_parse_addin_args(AudinWinmmDevice* device, ADDIN_ARGV* args) +static WIN32ERROR audin_winmm_parse_addin_args(AudinWinmmDevice* device, ADDIN_ARGV* args) { int status; DWORD flags; @@ -273,24 +293,36 @@ static void audin_winmm_parse_addin_args(AudinWinmmDevice* device, ADDIN_ARGV* a CommandLineSwitchCase(arg, "dev") { winmm->device_name = _strdup(arg->Value); + if (!winmm->device_name) + { + WLog_ERR(TAG, "_strdup failed!"); + return CHANNEL_RC_NO_MEMORY; + } } CommandLineSwitchEnd(arg) } while ((arg = CommandLineFindNextArgumentA(arg)) != NULL); + + return CHANNEL_RC_OK; } #ifdef STATIC_CHANNELS #define freerdp_audin_client_subsystem_entry winmm_freerdp_audin_client_subsystem_entry #endif -int freerdp_audin_client_subsystem_entry(PFREERDP_AUDIN_DEVICE_ENTRY_POINTS pEntryPoints) +WIN32ERROR freerdp_audin_client_subsystem_entry(PFREERDP_AUDIN_DEVICE_ENTRY_POINTS pEntryPoints) { ADDIN_ARGV* args; AudinWinmmDevice* winmm; + WIN32ERROR error; - winmm = (AudinWinmmDevice*) malloc(sizeof(AudinWinmmDevice)); - ZeroMemory(winmm, sizeof(AudinWinmmDevice)); + winmm = (AudinWinmmDevice*) calloc(sizeof(AudinWinmmDevice)); + if (!winmm) + { + WLog_ERR(TAG, "calloc failed!"); + return CHANNEL_RC_NO_MEMORY; + } winmm->iface.Open = audin_winmm_open; winmm->iface.FormatSupported = audin_winmm_format_supported; @@ -300,15 +332,42 @@ int freerdp_audin_client_subsystem_entry(PFREERDP_AUDIN_DEVICE_ENTRY_POINTS pEnt args = pEntryPoints->args; - audin_winmm_parse_addin_args(winmm, args); + if ((error = audin_winmm_parse_addin_args(winmm, args))) + { + WLog_ERR(TAG, "audin_winmm_parse_addin_args failed with error %d!", error); + goto error_out; + } if (!winmm->device_name) + { winmm->device_name = _strdup("default"); + if (!winmm->device_name) + { + WLog_ERR(TAG, "_strdup failed!"); + error = CHANNEL_RC_NO_MEMORY; + goto error_out; + } + } winmm->ppwfx_size = 10; winmm->ppwfx = malloc(sizeof(PWAVEFORMATEX) * winmm->ppwfx_size); + if (!winmm->ppwfx) + { + WLog_ERR(TAG, "malloc failed!"); + error = CHANNEL_RC_NO_MEMORY; + goto error_out; + } - pEntryPoints->pRegisterAudinDevice(pEntryPoints->plugin, (IAudinDevice*) winmm); + if ((error = pEntryPoints->pRegisterAudinDevice(pEntryPoints->plugin, (IAudinDevice*) winmm))) + { + WLog_ERR(TAG, "RegisterAudinDevice failed with error %d!", error); + goto error_out; + } - return 0; + return CHANNEL_RC_OK; +error_out: + free(winmm->ppwfx); + free(winmm->device_name); + free(winmm); + return error; } diff --git a/channels/audin/server/audin.c b/channels/audin/server/audin.c index e5909cd85..982f99a63 100644 --- a/channels/audin/server/audin.c +++ b/channels/audin/server/audin.c @@ -3,6 +3,8 @@ * Server Audio Input Virtual Channel * * Copyright 2012 Vic Lee + * Copyright 2015 Thincast Technologies GmbH + * Copyright 2015 DI (FH) Martin Haimberger * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -29,6 +31,7 @@ #include #include #include +#include #include #include @@ -62,12 +65,15 @@ typedef struct _audin_server } audin_server; -static void audin_server_select_format(audin_server_context* context, int client_format_index) +static WIN32ERROR audin_server_select_format(audin_server_context* context, int client_format_index) { audin_server* audin = (audin_server*) context; if (client_format_index >= context->num_client_formats) - return; + { + WLog_ERR(TAG, "error in protocol: client_format_index >= context->num_client_formats!"); + return ERROR_INVALID_DATA; + } context->selected_client_format = client_format_index; @@ -75,33 +81,45 @@ static void audin_server_select_format(audin_server_context* context, int client { /* TODO: send MSG_SNDIN_FORMATCHANGE */ } + return CHANNEL_RC_OK; } -static void audin_server_send_version(audin_server* audin, wStream* s) +static WIN32ERROR audin_server_send_version(audin_server* audin, wStream* s) { ULONG written; Stream_Write_UINT8(s, MSG_SNDIN_VERSION); Stream_Write_UINT32(s, 1); /* Version (4 bytes) */ - WTSVirtualChannelWrite(audin->audin_channel, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), &written); + if (!WTSVirtualChannelWrite(audin->audin_channel, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), &written)) + { + WLog_ERR(TAG, "WTSVirtualChannelWrite failed!"); + return ERROR_INTERNAL_ERROR; + } + return CHANNEL_RC_OK; } -static BOOL audin_server_recv_version(audin_server* audin, wStream* s, UINT32 length) +static WIN32ERROR audin_server_recv_version(audin_server* audin, wStream* s, UINT32 length) { UINT32 Version; if (length < 4) - return FALSE; + { + WLog_ERR(TAG, "error parsing version info: expected at least 4 bytes, got %d", length); + return ERROR_INVALID_DATA; + } Stream_Read_UINT32(s, Version); if (Version < 1) - return FALSE; + { + WLog_ERR(TAG, "expected Version > 0 but got %d", Version); + return ERROR_INVALID_DATA; + } - return TRUE; + return CHANNEL_RC_OK; } -static void audin_server_send_formats(audin_server* audin, wStream* s) +static WIN32ERROR audin_server_send_formats(audin_server* audin, wStream* s) { int i; UINT32 nAvgBytesPerSec; @@ -119,7 +137,10 @@ static void audin_server_send_formats(audin_server* audin, wStream* s) audin->context.server_formats[i].wBitsPerSample / 8; if (!Stream_EnsureRemainingCapacity(s, 18)) - return; + { + WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!"); + return CHANNEL_RC_NO_MEMORY; + } Stream_Write_UINT16(s, audin->context.server_formats[i].wFormatTag); Stream_Write_UINT16(s, audin->context.server_formats[i].nChannels); @@ -132,29 +153,39 @@ static void audin_server_send_formats(audin_server* audin, wStream* s) if (audin->context.server_formats[i].cbSize) { if (!Stream_EnsureRemainingCapacity(s, audin->context.server_formats[i].cbSize)) - return; + { + WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!"); + return CHANNEL_RC_NO_MEMORY; + } Stream_Write(s, audin->context.server_formats[i].data, audin->context.server_formats[i].cbSize); } } - WTSVirtualChannelWrite(audin->audin_channel, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), &written); + return WTSVirtualChannelWrite(audin->audin_channel, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), &written) ? CHANNEL_RC_OK : ERROR_INTERNAL_ERROR; } -static BOOL audin_server_recv_formats(audin_server* audin, wStream* s, UINT32 length) +static WIN32ERROR audin_server_recv_formats(audin_server* audin, wStream* s, UINT32 length) { int i; + WIN32ERROR success = CHANNEL_RC_OK; if (length < 8) - return FALSE; + { + WLog_ERR(TAG, "error parsing rec formats: expected at least 8 bytes, got %d", length); + return ERROR_INVALID_DATA; + } Stream_Read_UINT32(s, audin->context.num_client_formats); /* NumFormats (4 bytes) */ Stream_Seek_UINT32(s); /* cbSizeFormatsPacket (4 bytes) */ length -= 8; if (audin->context.num_client_formats <= 0) - return FALSE; + { + WLog_ERR(TAG, "num_client_formats expected > 0 but got %d", audin->context.num_client_formats); + return ERROR_INVALID_DATA; + } audin->context.client_formats = malloc(audin->context.num_client_formats * sizeof(AUDIO_FORMAT)); ZeroMemory(audin->context.client_formats, audin->context.num_client_formats * sizeof(AUDIO_FORMAT)); @@ -165,7 +196,8 @@ static BOOL audin_server_recv_formats(audin_server* audin, wStream* s, UINT32 le { free(audin->context.client_formats); audin->context.client_formats = NULL; - return FALSE; + WLog_ERR(TAG, "expected length at least 18, but got %d", length); + return ERROR_INVALID_DATA; } Stream_Read_UINT16(s, audin->context.client_formats[i].wFormatTag); @@ -182,17 +214,20 @@ static BOOL audin_server_recv_formats(audin_server* audin, wStream* s, UINT32 le } } - IFCALL(audin->context.Opening, &audin->context); - - return TRUE; + IFCALLRET(audin->context.Opening, success, &audin->context); + return success; } -static void audin_server_send_open(audin_server* audin, wStream* s) +static WIN32ERROR audin_server_send_open(audin_server* audin, wStream* s) { ULONG written; if (audin->context.selected_client_format < 0) - return; + { + WLog_ERR(TAG, "audin->context.selected_client_format = %d", + audin->context.selected_client_format); + return ERROR_INVALID_DATA; + } audin->opened = TRUE; @@ -213,24 +248,29 @@ static void audin_server_send_open(audin_server* audin, wStream* s) Stream_Write_UINT16(s, 16); /* wBitsPerSample */ Stream_Write_UINT16(s, 0); /* cbSize */ - WTSVirtualChannelWrite(audin->audin_channel, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), &written); + return WTSVirtualChannelWrite(audin->audin_channel, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), &written) ? CHANNEL_RC_OK : ERROR_INTERNAL_ERROR; } -static BOOL audin_server_recv_open_reply(audin_server* audin, wStream* s, UINT32 length) +static WIN32ERROR audin_server_recv_open_reply(audin_server* audin, wStream* s, UINT32 length) { + UINT32 Result; + WIN32ERROR success = CHANNEL_RC_OK; if (length < 4) - return FALSE; + { + WLog_ERR(TAG, "error parsing version info: expected at least 4 bytes, got %d", length); + return ERROR_INVALID_DATA; + } Stream_Read_UINT32(s, Result); - IFCALL(audin->context.OpenResult, &audin->context, Result); + IFCALLRET(audin->context.OpenResult, success, &audin->context, Result); - return TRUE; + return success; } -static BOOL audin_server_recv_data(audin_server* audin, wStream* s, UINT32 length) +static WIN32ERROR audin_server_recv_data(audin_server* audin, wStream* s, UINT32 length) { AUDIO_FORMAT* format; int sbytes_per_sample; @@ -238,9 +278,14 @@ static BOOL audin_server_recv_data(audin_server* audin, wStream* s, UINT32 lengt BYTE* src; int size; int frames; + WIN32ERROR success = CHANNEL_RC_OK; if (audin->context.selected_client_format < 0) - return FALSE; + { + WLog_ERR(TAG, "audin->context.selected_client_format = %d", + audin->context.selected_client_format); + return ERROR_INVALID_DATA; + } format = &audin->context.client_formats[audin->context.selected_client_format]; @@ -283,9 +328,9 @@ static BOOL audin_server_recv_data(audin_server* audin, wStream* s, UINT32 lengt src = audin->dsp_context->resampled_buffer; } - IFCALL(audin->context.ReceiveSamples, &audin->context, src, frames); + IFCALLRET(audin->context.ReceiveSamples, success, &audin->context, src, frames); - return TRUE; + return success; } static void* audin_server_thread_func(void* arg) @@ -299,6 +344,7 @@ static void* audin_server_thread_func(void* arg) HANDLE ChannelEvent; DWORD BytesReturned = 0; audin_server* audin = (audin_server*) arg; + WIN32ERROR error = CHANNEL_RC_OK; buffer = NULL; BytesReturned = 0; @@ -311,6 +357,12 @@ static void* audin_server_thread_func(void* arg) WTSFreeMemory(buffer); } + else + { + WLog_ERR(TAG, "WTSVirtualChannelQuery failed"); + error = ERROR_INTERNAL_ERROR; + goto out; + } nCount = 0; events[nCount++] = audin->stopEvent; @@ -321,10 +373,14 @@ static void* audin_server_thread_func(void* arg) while (1) { if (WaitForMultipleObjects(nCount, events, FALSE, 100) == WAIT_OBJECT_0) - break; + goto out; if (WTSVirtualChannelQuery(audin->audin_channel, WTSVirtualChannelReady, &buffer, &BytesReturned) == FALSE) - break; + { + WLog_ERR(TAG, "WTSVirtualChannelQuery failed"); + error = ERROR_INTERNAL_ERROR; + goto out; + } ready = *((BOOL*) buffer); @@ -336,11 +392,20 @@ static void* audin_server_thread_func(void* arg) s = Stream_New(NULL, 4096); if (!s) + { + WLog_ERR(TAG, "Stream_New failed!"); + error = CHANNEL_RC_NO_MEMORY; goto out; + } + if (ready) { - audin_server_send_version(audin, s); + if ((error = audin_server_send_version(audin, s))) + { + WLog_ERR(TAG, "audin_server_send_version failed with error %lu!", error); + goto out_capacity; + } } while (ready) @@ -350,14 +415,21 @@ static void* audin_server_thread_func(void* arg) Stream_SetPosition(s, 0); - WTSVirtualChannelRead(audin->audin_channel, 0, NULL, 0, &BytesReturned); + if (!WTSVirtualChannelRead(audin->audin_channel, 0, NULL, 0, &BytesReturned)) + { + WLog_ERR(TAG, "WTSVirtualChannelRead failed!"); + error = ERROR_INTERNAL_ERROR; + break; + } if (BytesReturned < 1) continue; if (!Stream_EnsureRemainingCapacity(s, BytesReturned)) - goto out_capacity; + break; if (WTSVirtualChannelRead(audin->audin_channel, 0, (PCHAR) Stream_Buffer(s), Stream_Capacity(s), &BytesReturned) == FALSE) { + WLog_ERR(TAG, "WTSVirtualChannelRead failed!"); + error = ERROR_INTERNAL_ERROR; break; } @@ -367,31 +439,55 @@ static void* audin_server_thread_func(void* arg) switch (MessageId) { case MSG_SNDIN_VERSION: - if (audin_server_recv_version(audin, s, BytesReturned)) - audin_server_send_formats(audin, s); + if ((error = audin_server_recv_version(audin, s, BytesReturned))) + { + WLog_ERR(TAG, "audin_server_recv_version failed with error %lu!", error); + goto out_capacity; + } + if ((error = audin_server_send_formats(audin, s))) + { + WLog_ERR(TAG, "audin_server_send_formats failed with error %lu!", error); + goto out_capacity; + } break; case MSG_SNDIN_FORMATS: - if (audin_server_recv_formats(audin, s, BytesReturned)) - audin_server_send_open(audin, s); + if ((error = audin_server_recv_formats(audin, s, BytesReturned))) + { + WLog_ERR(TAG, "audin_server_recv_formats failed with error %lu!", error); + goto out_capacity; + } + if ((error = audin_server_send_open(audin, s))) + { + WLog_ERR(TAG, "audin_server_send_open failed with error %lu!", error); + goto out_capacity; + } break; case MSG_SNDIN_OPEN_REPLY: - audin_server_recv_open_reply(audin, s, BytesReturned); + if ((error = audin_server_recv_open_reply(audin, s, BytesReturned))) + { + WLog_ERR(TAG, "audin_server_recv_open_reply failed with error %lu!", error); + goto out_capacity; + } break; case MSG_SNDIN_DATA_INCOMING: break; case MSG_SNDIN_DATA: - audin_server_recv_data(audin, s, BytesReturned); + if ((error = audin_server_recv_data(audin, s, BytesReturned))) + { + WLog_ERR(TAG, "audin_server_recv_data failed with error %lu!", error); + goto out_capacity; + }; break; case MSG_SNDIN_FORMATCHANGE: break; default: - WLog_ERR(TAG, "audin_server_thread_func: unknown MessageId %d", MessageId); + WLog_ERR(TAG, "audin_server_thread_func: unknown MessageId %d", MessageId); break; } } @@ -401,7 +497,7 @@ out_capacity: out: WTSVirtualChannelClose(audin->audin_channel); audin->audin_channel = NULL; - + ExitThread((DWORD)error); return NULL; } @@ -427,16 +523,30 @@ static BOOL audin_server_open(audin_server_context* context) "AUDIO_INPUT", WTS_CHANNEL_OPTION_DYNAMIC); if (!audin->audin_channel) + { + WLog_ERR(TAG, "WTSVirtualChannelOpenEx failed!"); return FALSE; + } - audin->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + if (!(audin->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL))) + { + WLog_ERR(TAG, "CreateEvent failed!"); + return FALSE; + } - audin->thread = CreateThread(NULL, 0, - (LPTHREAD_START_ROUTINE) audin_server_thread_func, (void*) audin, 0, NULL); + // TODO: implement signaling an error + if (!(audin->thread = CreateThread(NULL, 0, + (LPTHREAD_START_ROUTINE) audin_server_thread_func, (void*) audin, 0, NULL))) + { + WLog_ERR(TAG, "CreateThread failed!"); + CloseHandle(audin->stopEvent); + audin->stopEvent = NULL; + return FALSE; + } return TRUE; } - + WLog_ERR(TAG, "thread already running!"); return FALSE; } @@ -470,6 +580,11 @@ audin_server_context* audin_server_context_new(HANDLE vcm) audin_server* audin; audin = (audin_server *)calloc(1, sizeof(audin_server)); + if (!audin) + { + WLog_ERR(TAG, "calloc failed!"); + return NULL; + } audin->context.vcm = vcm; audin->context.selected_client_format = -1; @@ -480,6 +595,13 @@ audin_server_context* audin_server_context_new(HANDLE vcm) audin->dsp_context = freerdp_dsp_context_new(); + if (!audin->dsp_context) + { + WLog_ERR(TAG, "freerdp_dsp_context_new failed!"); + free(audin); + return NULL; + } + return (audin_server_context*) audin; } diff --git a/include/freerdp/client/audin.h b/include/freerdp/client/audin.h index d7831b2f1..eff31964c 100644 --- a/include/freerdp/client/audin.h +++ b/include/freerdp/client/audin.h @@ -3,6 +3,8 @@ * Audio Input Redirection Virtual Channel * * Copyright 2010-2011 Vic Lee + * Copyright 2015 Thincast Technologies GmbH + * Copyright 2015 DI (FH) Martin Haimberger * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -26,7 +28,7 @@ * Subsystem Interface */ -typedef BOOL (*AudinReceive) (BYTE* data, int size, void* userData); +typedef WIN32ERROR (*AudinReceive) (BYTE* data, int size, void* userData); typedef struct audin_format audinFormat; struct audin_format @@ -43,16 +45,16 @@ struct audin_format typedef struct _IAudinDevice IAudinDevice; struct _IAudinDevice { - void (*Open) (IAudinDevice* devplugin, AudinReceive receive, void* userData); + WIN32ERROR (*Open) (IAudinDevice* devplugin, AudinReceive receive, void* userData); BOOL (*FormatSupported) (IAudinDevice* devplugin, audinFormat* format); - void (*SetFormat) (IAudinDevice* devplugin, audinFormat* format, UINT32 FramesPerPacket); - void (*Close) (IAudinDevice* devplugin); - void (*Free) (IAudinDevice* devplugin); + WIN32ERROR (*SetFormat) (IAudinDevice* devplugin, audinFormat* format, UINT32 FramesPerPacket); + WIN32ERROR (*Close) (IAudinDevice* devplugin); + WIN32ERROR (*Free) (IAudinDevice* devplugin); }; #define AUDIN_DEVICE_EXPORT_FUNC_NAME "freerdp_audin_client_subsystem_entry" -typedef void (*PREGISTERAUDINDEVICE)(IWTSPlugin* plugin, IAudinDevice* device); +typedef WIN32ERROR (*PREGISTERAUDINDEVICE)(IWTSPlugin* plugin, IAudinDevice* device); struct _FREERDP_AUDIN_DEVICE_ENTRY_POINTS { @@ -63,7 +65,7 @@ struct _FREERDP_AUDIN_DEVICE_ENTRY_POINTS typedef struct _FREERDP_AUDIN_DEVICE_ENTRY_POINTS FREERDP_AUDIN_DEVICE_ENTRY_POINTS; typedef FREERDP_AUDIN_DEVICE_ENTRY_POINTS* PFREERDP_AUDIN_DEVICE_ENTRY_POINTS; -typedef int (*PFREERDP_AUDIN_DEVICE_ENTRY)(PFREERDP_AUDIN_DEVICE_ENTRY_POINTS pEntryPoints); +typedef WIN32ERROR (*PFREERDP_AUDIN_DEVICE_ENTRY)(PFREERDP_AUDIN_DEVICE_ENTRY_POINTS pEntryPoints); #endif /* FREERDP_CHANNEL_CLIENT_AUDIN_H */ diff --git a/include/freerdp/server/audin.h b/include/freerdp/server/audin.h index d8ddafa43..f935ac1f7 100644 --- a/include/freerdp/server/audin.h +++ b/include/freerdp/server/audin.h @@ -3,6 +3,8 @@ * Server Audio Input Virtual Channel * * Copyright 2012 Vic Lee + * Copyright 2015 Thincast Technologies GmbH + * Copyright 2015 DI (FH) Martin Haimberger * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,16 +25,17 @@ #include #include #include +#include typedef struct _audin_server_context audin_server_context; -typedef void (*psAudinServerSelectFormat)(audin_server_context* context, int client_format_index); +typedef WIN32ERROR (*psAudinServerSelectFormat)(audin_server_context* context, int client_format_index); typedef BOOL (*psAudinServerOpen)(audin_server_context* context); typedef BOOL (*psAudinServerClose)(audin_server_context* context); -typedef void (*psAudinServerOpening)(audin_server_context* context); -typedef void (*psAudinServerOpenResult)(audin_server_context* context, UINT32 result); -typedef void (*psAudinServerReceiveSamples)(audin_server_context* context, const void* buf, int nframes); +typedef WIN32ERROR (*psAudinServerOpening)(audin_server_context* context); +typedef WIN32ERROR (*psAudinServerOpenResult)(audin_server_context* context, UINT32 result); +typedef WIN32ERROR (*psAudinServerReceiveSamples)(audin_server_context* context, const void* buf, int nframes); struct _audin_server_context { diff --git a/server/Sample/sf_audin.c b/server/Sample/sf_audin.c index 1fdf0f1fe..1191aa40e 100644 --- a/server/Sample/sf_audin.c +++ b/server/Sample/sf_audin.c @@ -3,6 +3,8 @@ * FreeRDP Sample Server (Audio Input) * * Copyright 2012 Marc-Andre Moreau + * Copyright 2015 Thincast Technologies GmbH + * Copyright 2015 DI (FH) Martin Haimberger * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -28,6 +30,7 @@ #include "sf_audin.h" #include +#include #define TAG SERVER_TAG("sample") static const AUDIO_FORMAT test_audio_formats[] = @@ -36,21 +39,24 @@ static const AUDIO_FORMAT test_audio_formats[] = { WAVE_FORMAT_ALAW, 2, 22050, 44100, 2, 8, 0, NULL } }; -static void sf_peer_audin_opening(audin_server_context* context) +static WIN32ERROR sf_peer_audin_opening(audin_server_context* context) { WLog_DBG(TAG, "AUDIN opening."); /* Simply choose the first format supported by the client. */ context->SelectFormat(context, 0); + return CHANNEL_RC_OK; } -static void sf_peer_audin_open_result(audin_server_context* context, UINT32 result) +static WIN32ERROR sf_peer_audin_open_result(audin_server_context* context, UINT32 result) { WLog_DBG(TAG, "AUDIN open result %d.", result); + return CHANNEL_RC_OK; } -static void sf_peer_audin_receive_samples(audin_server_context* context, const void* buf, int nframes) +static WIN32ERROR sf_peer_audin_receive_samples(audin_server_context* context, const void* buf, int nframes) { WLog_DBG(TAG, "AUDIN receive %d frames.", nframes); + return CHANNEL_RC_OK; } void sf_peer_audin_init(testPeerContext* context)