diff --git a/channels/audin/client/audin_main.c b/channels/audin/client/audin_main.c index 79e0127c2..8b86830c1 100644 --- a/channels/audin/client/audin_main.c +++ b/channels/audin/client/audin_main.c @@ -85,9 +85,7 @@ struct _AUDIN_PLUGIN AUDIN_LISTENER_CALLBACK* listener_callback; /* Parsed plugin data */ - UINT16 fixed_format; - UINT16 fixed_channel; - UINT32 fixed_rate; + AUDIO_FORMAT* fixed_format; char* subsystem; char* device_name; @@ -210,7 +208,7 @@ static UINT audin_process_formats(AUDIN_PLUGIN* audin, AUDIN_CHANNEL_CALLBACK* c } Stream_Seek_UINT32(s); /* cbSizeFormatsPacket */ - callback->formats = (AUDIO_FORMAT*) calloc(NumFormats, sizeof(AUDIO_FORMAT)); + callback->formats = audio_formats_new(NumFormats); if (!callback->formats) { @@ -234,51 +232,17 @@ static UINT audin_process_formats(AUDIN_PLUGIN* audin, AUDIN_CHANNEL_CALLBACK* c { AUDIO_FORMAT format = { 0 }; - if (Stream_GetRemainingLength(s) < 18) + if (!audio_format_read(s, &format)) { error = ERROR_INVALID_DATA; goto out; } - Stream_Read_UINT16(s, format.wFormatTag); - Stream_Read_UINT16(s, format.nChannels); - Stream_Read_UINT32(s, format.nSamplesPerSec); - Stream_Read_UINT32(s, format.nAvgBytesPerSec); - Stream_Read_UINT16(s, format.nBlockAlign); - Stream_Read_UINT16(s, format.wBitsPerSample); - Stream_Read_UINT16(s, format.cbSize); + audio_format_print(audin->log, WLOG_DEBUG, &format); - if (Stream_GetRemainingLength(s) < format.cbSize) + if (!audio_format_compatible(audin->fixed_format, &format)) { - error = ERROR_INVALID_DATA; - goto out; - } - - if (format.cbSize > 0) - { - format.data = malloc(format.cbSize); - - if (!format.data) - { - error = ERROR_OUTOFMEMORY; - goto out; - } - - memcpy(format.data, Stream_Pointer(s), format.cbSize); - Stream_Seek(s, format.cbSize); - } - - WLog_Print(audin->log, WLOG_DEBUG, - "wFormatTag=%s nChannels=%"PRIu16" nSamplesPerSec=%"PRIu32" " - "nBlockAlign=%"PRIu16" wBitsPerSample=%"PRIu16" cbSize=%"PRIu16"", - rdpsnd_get_audio_tag_string(format.wFormatTag), format.nChannels, format.nSamplesPerSec, - format.nBlockAlign, format.wBitsPerSample, format.cbSize); - - if ((audin->fixed_format > 0 && audin->fixed_format != format.wFormatTag) || - (audin->fixed_channel > 0 && audin->fixed_channel != format.nChannels) || - (audin->fixed_rate > 0 && audin->fixed_rate != format.nSamplesPerSec)) - { - free(format.data); + audio_format_free(&format); continue; } @@ -288,20 +252,16 @@ static UINT audin_process_formats(AUDIN_PLUGIN* audin, AUDIN_CHANNEL_CALLBACK* c /* Store the agreed format in the corresponding index */ callback->formats[callback->formats_count++] = format; - /* Put the format to output buffer */ - if (!Stream_EnsureRemainingCapacity(out, 18 + format.cbSize)) + if (!audio_format_write(out, &format)) { error = CHANNEL_RC_NO_MEMORY; WLog_Print(audin->log, WLOG_ERROR, "Stream_EnsureRemainingCapacity failed!"); goto out; } - - Stream_Write(out, &format, 18); - Stream_Write(out, format.data, format.cbSize); } else { - free(format.data); + audio_format_free(&format); } } @@ -322,16 +282,8 @@ out: if (error != CHANNEL_RC_OK) { - size_t x; - - if (callback->formats) - { - for (x = 0; x < NumFormats; x++) - free(callback->formats[x].data); - - free(callback->formats); - callback->formats = NULL; - } + audio_formats_free(callback->formats, NumFormats); + callback->formats = NULL; } Stream_Free(out, TRUE); @@ -427,12 +379,8 @@ static UINT audin_receive_wave_data(const AUDIO_FORMAT* format, if (Stream_GetPosition(audin->data) <= 1) return CHANNEL_RC_OK; - WLog_Print(audin->log, WLOG_TRACE, - "%s: nChannels: %"PRIu16" nSamplesPerSec: %"PRIu32" " - "nAvgBytesPerSec: %"PRIu32" nBlockAlign: %"PRIu16" wBitsPerSample: %"PRIu16" cbSize: %"PRIu16" [%"PRIdz"/%"PRIdz"]", - rdpsnd_get_audio_tag_string(audin->format->wFormatTag), - audin->format->nChannels, audin->format->nSamplesPerSec, audin->format->nAvgBytesPerSec, - audin->format->nBlockAlign, audin->format->wBitsPerSample, audin->format->cbSize, size, + audio_format_print(audin->log, WLOG_TRACE, audin->format); + WLog_Print(audin->log, WLOG_TRACE, "[%"PRIdz"/%"PRIdz"]", size, Stream_GetPosition(audin->data) - 1); if ((error = audin_send_incoming_data_pdu(callback))) @@ -456,7 +404,7 @@ static BOOL audin_open_device(AUDIN_PLUGIN* audin, AUDIN_CHANNEL_CALLBACK* callb format = *audin->format; supported = IFCALLRESULT(FALSE, audin->device->FormatSupported, audin->device, &format); WLog_Print(audin->log, WLOG_DEBUG, "microphone uses %s codec", - rdpsnd_get_audio_tag_string(format.wFormatTag)); + audio_format_get_tag_string(format.wFormatTag)); if (!supported) { @@ -641,7 +589,6 @@ static UINT audin_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, */ static UINT audin_on_close(IWTSVirtualChannelCallback* pChannelCallback) { - size_t x; AUDIN_CHANNEL_CALLBACK* callback = (AUDIN_CHANNEL_CALLBACK*) pChannelCallback; AUDIN_PLUGIN* audin = (AUDIN_PLUGIN*) callback->plugin; UINT error = CHANNEL_RC_OK; @@ -656,18 +603,7 @@ static UINT audin_on_close(IWTSVirtualChannelCallback* pChannelCallback) } audin->format = NULL; - - if (callback->formats) - { - for (x = 0; x < callback->formats_count; x++) - { - AUDIO_FORMAT* format = &callback->formats[x]; - free(format->data); - } - - free(callback->formats); - } - + audio_formats_free(callback->formats, callback->formats_count); free(callback); return error; } @@ -752,6 +688,7 @@ static UINT audin_plugin_terminated(IWTSPlugin* pPlugin) return CHANNEL_RC_BAD_CHANNEL_HANDLE; WLog_Print(audin->log, WLOG_TRACE, "..."); + audio_format_free(audin->fixed_format); if (audin->device) { @@ -952,7 +889,7 @@ BOOL audin_process_addin_args(AUDIN_PLUGIN* audin, ADDIN_ARGV* args) if ((errno != 0) || (val > UINT16_MAX)) return FALSE; - audin->fixed_format = val; + audin->fixed_format->wFormatTag = val; } CommandLineSwitchCase(arg, "rate") { @@ -961,14 +898,14 @@ BOOL audin_process_addin_args(AUDIN_PLUGIN* audin, ADDIN_ARGV* args) if ((errno != 0) || (val < INT32_MIN) || (val > INT32_MAX)) return FALSE; - audin->fixed_rate = val; + audin->fixed_format->nSamplesPerSec = val; } CommandLineSwitchCase(arg, "channel") { unsigned long val = strtoul(arg->Value, NULL, 0); if ((errno != 0) || (val > UINT16_MAX)) - audin->fixed_channel = val; + audin->fixed_format->nChannels = val; } CommandLineSwitchDefault(arg) { @@ -1041,6 +978,10 @@ UINT DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints) audin->log = WLog_Get(TAG); audin->data = Stream_New(NULL, 4096); + audin->fixed_format = audio_format_new(); + + if (!audin->fixed_format) + goto out; if (!audin->data) goto out; diff --git a/channels/audin/client/mac/audin_mac.c b/channels/audin/client/mac/audin_mac.c index d60acb8a5..40ba05d47 100644 --- a/channels/audin/client/mac/audin_mac.c +++ b/channels/audin/client/mac/audin_mac.c @@ -133,7 +133,7 @@ static UINT audin_mac_set_format(IAudinDevice* device, const AUDIO_FORMAT* forma mac->FramesPerPacket = FramesPerPacket; mac->format = *format; WLog_INFO(TAG, "Audio Format %s [channels=%d, samples=%d, bits=%d]", - rdpsnd_get_audio_tag_string(format->wFormatTag), + audio_format_get_tag_string(format->wFormatTag), format->nChannels, format->nSamplesPerSec, format->wBitsPerSample); mac->audioFormat.mBitsPerChannel = format->wBitsPerSample; @@ -169,6 +169,7 @@ static void mac_audio_queue_input_cb(void* aqData, if (buffer_size > 0) error = mac->receive(&mac->format, buffer, buffer_size, mac->user_data); + AudioQueueEnqueueBuffer(inAQ, inBuffer, 0, NULL); if (error) diff --git a/channels/audin/client/opensles/audin_opensl_es.c b/channels/audin/client/opensles/audin_opensl_es.c index 6838b1b3a..549edd080 100644 --- a/channels/audin/client/opensles/audin_opensl_es.c +++ b/channels/audin/client/opensles/audin_opensl_es.c @@ -129,7 +129,7 @@ static BOOL audin_opensles_format_supported(IAudinDevice* device, default: WLog_Print(opensles->log, WLOG_DEBUG, "Encoding '%s' [0x%04X"PRIX16"] not supported", - rdpsnd_get_audio_tag_string(format->wFormatTag), + audio_format_get_tag_string(format->wFormatTag), format->wFormatTag); break; } diff --git a/channels/audin/server/audin.c b/channels/audin/server/audin.c index 0a4773e8c..f5216676d 100644 --- a/channels/audin/server/audin.c +++ b/channels/audin/server/audin.c @@ -70,7 +70,7 @@ typedef struct _audin_server * @return 0 on success, otherwise a Win32 error code */ static UINT audin_server_select_format(audin_server_context* context, - int client_format_index) + size_t client_format_index) { audin_server* audin = (audin_server*) context; @@ -81,7 +81,7 @@ static UINT audin_server_select_format(audin_server_context* context, return ERROR_INVALID_DATA; } - context->selected_client_format = client_format_index; + context->selected_client_format = (SSIZE_T)client_format_index; if (!freerdp_dsp_context_reset(audin->dsp_context, &audin->context.client_formats[client_format_index])) @@ -154,8 +154,7 @@ static UINT audin_server_recv_version(audin_server* audin, wStream* s, */ static UINT audin_server_send_formats(audin_server* audin, wStream* s) { - int i; - UINT32 nAvgBytesPerSec; + size_t i; ULONG written; Stream_SetPosition(s, 0); Stream_Write_UINT8(s, MSG_SNDIN_FORMATS); @@ -166,35 +165,15 @@ static UINT audin_server_send_formats(audin_server* audin, wStream* s) for (i = 0; i < audin->context.num_server_formats; i++) { - nAvgBytesPerSec = audin->context.server_formats[i].nSamplesPerSec * - audin->context.server_formats[i].nChannels * - audin->context.server_formats[i].wBitsPerSample / 8; + AUDIO_FORMAT format = audin->context.server_formats[i]; + // TODO: Eliminate this + format.nAvgBytesPerSec = format.nSamplesPerSec * format.nChannels * format.wBitsPerSample / 8; - if (!Stream_EnsureRemainingCapacity(s, 18)) + if (!audio_format_write(s, &format)) { 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); - Stream_Write_UINT32(s, audin->context.server_formats[i].nSamplesPerSec); - Stream_Write_UINT32(s, nAvgBytesPerSec); - Stream_Write_UINT16(s, audin->context.server_formats[i].nBlockAlign); - Stream_Write_UINT16(s, audin->context.server_formats[i].wBitsPerSample); - Stream_Write_UINT16(s, audin->context.server_formats[i].cbSize); - - if (audin->context.server_formats[i].cbSize) - { - if (!Stream_EnsureRemainingCapacity(s, audin->context.server_formats[i].cbSize)) - { - 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); - } } return WTSVirtualChannelWrite(audin->audin_channel, (PCHAR) Stream_Buffer(s), @@ -209,7 +188,7 @@ static UINT audin_server_send_formats(audin_server* audin, wStream* s) static UINT audin_server_recv_formats(audin_server* audin, wStream* s, UINT32 length) { - int i; + size_t i; UINT success = CHANNEL_RC_OK; if (length < 8) @@ -231,34 +210,24 @@ static UINT audin_server_recv_formats(audin_server* audin, wStream* s, return ERROR_INVALID_DATA; } - audin->context.client_formats = calloc(audin->context.num_client_formats, - sizeof(AUDIO_FORMAT)); + audin->context.client_formats = audio_formats_new(audin->context.num_client_formats); if (!audin->context.client_formats) return ERROR_NOT_ENOUGH_MEMORY; for (i = 0; i < audin->context.num_client_formats; i++) { - if (length < 18) + AUDIO_FORMAT* format = &audin->context.client_formats[i]; + + if (!audio_format_read(s, format)) { - free(audin->context.client_formats); + audio_formats_free(audin->context.client_formats, i); audin->context.client_formats = NULL; WLog_ERR(TAG, "expected length at least 18, but got %"PRIu32"", length); return ERROR_INVALID_DATA; } - Stream_Read_UINT16(s, audin->context.client_formats[i].wFormatTag); - Stream_Read_UINT16(s, audin->context.client_formats[i].nChannels); - Stream_Read_UINT32(s, audin->context.client_formats[i].nSamplesPerSec); - Stream_Seek_UINT32(s); /* nAvgBytesPerSec */ - Stream_Read_UINT16(s, audin->context.client_formats[i].nBlockAlign); - Stream_Read_UINT16(s, audin->context.client_formats[i].wBitsPerSample); - Stream_Read_UINT16(s, audin->context.client_formats[i].cbSize); - - if (audin->context.client_formats[i].cbSize > 0) - { - Stream_Seek(s, audin->context.client_formats[i].cbSize); - } + audio_format_print(WLog_Get(TAG), WLOG_DEBUG, format); } IFCALLRET(audin->context.Opening, success, &audin->context); @@ -366,11 +335,15 @@ static UINT audin_server_recv_data(audin_server* audin, wStream* s, if (freerdp_dsp_decode(audin->dsp_context, format, Stream_Pointer(s), length, out)) { + AUDIO_FORMAT dformat = *format; + dformat.wFormatTag = WAVE_FORMAT_PCM; + dformat.wBitsPerSample = 16; Stream_SealLength(out); + Stream_SetPosition(out, 0); sbytes_per_sample = format->wBitsPerSample / 8; sbytes_per_frame = format->nChannels * sbytes_per_sample; frames = Stream_Length(out) / sbytes_per_frame; - IFCALLRET(audin->context.ReceiveSamples, success, &audin->context, Stream_Buffer(out), frames); + IFCALLRET(audin->context.ReceiveSamples, success, &audin->context, &dformat, out, frames); if (success) WLog_ERR(TAG, "context.ReceiveSamples failed with error %"PRIu32"", success); @@ -701,11 +674,13 @@ audin_server_context* audin_server_context_new(HANDLE vcm) void audin_server_context_free(audin_server_context* context) { audin_server* audin = (audin_server*) context; + + if (!audin) + return; + audin_server_close(context); - - if (audin->dsp_context) - freerdp_dsp_context_free(audin->dsp_context); - - free(audin->context.client_formats); + freerdp_dsp_context_free(audin->dsp_context); + audio_formats_free(audin->context.client_formats, audin->context.num_client_formats); + audio_formats_free(audin->context.server_formats, audin->context.num_server_formats); free(audin); } diff --git a/channels/rdpsnd/client/mac/rdpsnd_mac.c b/channels/rdpsnd/client/mac/rdpsnd_mac.c index 02a6da252..3bb290249 100644 --- a/channels/rdpsnd/client/mac/rdpsnd_mac.c +++ b/channels/rdpsnd/client/mac/rdpsnd_mac.c @@ -109,7 +109,7 @@ static BOOL rdpsnd_mac_set_format(rdpsndDevicePlugin* device, const AUDIO_FORMAT return FALSE; } - rdpsnd_print_audio_format(format); + audio_format_print(WLog_Get(TAG), WLOG_DEBUG, format); return TRUE; } diff --git a/channels/rdpsnd/client/rdpsnd_main.c b/channels/rdpsnd/client/rdpsnd_main.c index da0fb673a..33ac176ea 100644 --- a/channels/rdpsnd/client/rdpsnd_main.c +++ b/channels/rdpsnd/client/rdpsnd_main.c @@ -86,9 +86,7 @@ struct rdpsnd_plugin UINT32 latency; BOOL isOpen; - UINT16 fixedFormat; - UINT16 fixedChannel; - UINT32 fixedRate; + AUDIO_FORMAT* fixed_format; char* subsystem; char* device_name; @@ -139,16 +137,14 @@ static UINT rdpsnd_send_quality_mode_pdu(rdpsndPlugin* rdpsnd) static void rdpsnd_select_supported_audio_formats(rdpsndPlugin* rdpsnd) { UINT16 index; - rdpsnd_free_audio_formats(rdpsnd->ClientFormats, rdpsnd->NumberOfClientFormats); + audio_formats_free(rdpsnd->ClientFormats, rdpsnd->NumberOfClientFormats); rdpsnd->NumberOfClientFormats = 0; rdpsnd->ClientFormats = NULL; if (!rdpsnd->NumberOfServerFormats) return; - rdpsnd->ClientFormats = (AUDIO_FORMAT*) calloc( - rdpsnd->NumberOfServerFormats, - sizeof(AUDIO_FORMAT)); + rdpsnd->ClientFormats = audio_formats_new(rdpsnd->NumberOfServerFormats); if (!rdpsnd->ClientFormats) return; @@ -157,29 +153,14 @@ static void rdpsnd_select_supported_audio_formats(rdpsndPlugin* rdpsnd) { const AUDIO_FORMAT* serverFormat = &rdpsnd->ServerFormats[index]; - if ((rdpsnd->fixedFormat > 0) && - (rdpsnd->fixedFormat != serverFormat->wFormatTag)) - continue; - - if ((rdpsnd->fixedChannel > 0) && - (rdpsnd->fixedChannel != serverFormat->nChannels)) - continue; - - if ((rdpsnd->fixedRate > 0) && - (rdpsnd->fixedRate != serverFormat->nSamplesPerSec)) + if (!audio_format_compatible(rdpsnd->fixed_format, serverFormat)) continue; if (freerdp_dsp_supports_format(serverFormat, FALSE) || rdpsnd->device->FormatSupported(rdpsnd->device, serverFormat)) { AUDIO_FORMAT* clientFormat = &rdpsnd->ClientFormats[rdpsnd->NumberOfClientFormats++]; - *clientFormat = *serverFormat; - - if (serverFormat->cbSize > 0) - { - clientFormat->data = (BYTE*) malloc(serverFormat->cbSize); - CopyMemory(clientFormat->data, serverFormat->data, serverFormat->cbSize); - } + audio_format_copy(serverFormat, clientFormat); } } } @@ -226,16 +207,12 @@ static UINT rdpsnd_send_client_audio_formats(rdpsndPlugin* rdpsnd) for (index = 0; index < wNumberOfFormats; index++) { const AUDIO_FORMAT* clientFormat = &rdpsnd->ClientFormats[index]; - Stream_Write_UINT16(pdu, clientFormat->wFormatTag); - Stream_Write_UINT16(pdu, clientFormat->nChannels); - Stream_Write_UINT32(pdu, clientFormat->nSamplesPerSec); - Stream_Write_UINT32(pdu, clientFormat->nAvgBytesPerSec); - Stream_Write_UINT16(pdu, clientFormat->nBlockAlign); - Stream_Write_UINT16(pdu, clientFormat->wBitsPerSample); - Stream_Write_UINT16(pdu, clientFormat->cbSize); - if (clientFormat->cbSize > 0) - Stream_Write(pdu, clientFormat->data, clientFormat->cbSize); + if (!audio_format_write(pdu, clientFormat)) + { + Stream_Free(pdu, TRUE); + return ERROR_INTERNAL_ERROR; + } } WLog_Print(rdpsnd->log, WLOG_DEBUG, "Client Audio Formats"); @@ -254,7 +231,7 @@ static UINT rdpsnd_recv_server_audio_formats_pdu(rdpsndPlugin* rdpsnd, UINT16 wVersion; UINT16 wNumberOfFormats; UINT ret = ERROR_BAD_LENGTH; - rdpsnd_free_audio_formats(rdpsnd->ServerFormats, rdpsnd->NumberOfServerFormats); + audio_formats_free(rdpsnd->ServerFormats, rdpsnd->NumberOfServerFormats); rdpsnd->NumberOfServerFormats = 0; rdpsnd->ServerFormats = NULL; @@ -275,8 +252,7 @@ static UINT rdpsnd_recv_server_audio_formats_pdu(rdpsndPlugin* rdpsnd, if (Stream_GetRemainingLength(s) / 14 < wNumberOfFormats) return ERROR_BAD_LENGTH; - rdpsnd->ServerFormats = (AUDIO_FORMAT*) calloc(wNumberOfFormats, - sizeof(AUDIO_FORMAT)); + rdpsnd->ServerFormats = audio_formats_new(wNumberOfFormats); if (!rdpsnd->ServerFormats) return CHANNEL_RC_NO_MEMORY; @@ -285,32 +261,8 @@ static UINT rdpsnd_recv_server_audio_formats_pdu(rdpsndPlugin* rdpsnd, { AUDIO_FORMAT* format = &rdpsnd->ServerFormats[index]; - if (Stream_GetRemainingLength(s) < 14) + if (!audio_format_read(s, format)) goto out_fail; - - Stream_Read_UINT16(s, format->wFormatTag); /* wFormatTag */ - Stream_Read_UINT16(s, format->nChannels); /* nChannels */ - Stream_Read_UINT32(s, format->nSamplesPerSec); /* nSamplesPerSec */ - Stream_Read_UINT32(s, format->nAvgBytesPerSec); /* nAvgBytesPerSec */ - Stream_Read_UINT16(s, format->nBlockAlign); /* nBlockAlign */ - Stream_Read_UINT16(s, format->wBitsPerSample); /* wBitsPerSample */ - Stream_Read_UINT16(s, format->cbSize); /* cbSize */ - - if (format->cbSize > 0) - { - if (Stream_GetRemainingLength(s) < format->cbSize) - goto out_fail; - - format->data = (BYTE*) malloc(format->cbSize); - - if (!format->data) - { - ret = CHANNEL_RC_NO_MEMORY; - goto out_fail; - } - - Stream_Read(s, format->data, format->cbSize); - } } rdpsnd_select_supported_audio_formats(rdpsnd); @@ -325,7 +277,7 @@ static UINT rdpsnd_recv_server_audio_formats_pdu(rdpsndPlugin* rdpsnd, return ret; out_fail: - rdpsnd_free_audio_formats(rdpsnd->ServerFormats, rdpsnd->NumberOfServerFormats); + audio_formats_free(rdpsnd->ServerFormats, rdpsnd->NumberOfServerFormats); rdpsnd->ServerFormats = NULL; rdpsnd->NumberOfServerFormats = 0; return ret; @@ -407,7 +359,7 @@ static UINT rdpsnd_recv_wave_info_pdu(rdpsndPlugin* rdpsnd, wStream* s, rdpsnd->waveDataSize = BodySize - 8; format = &rdpsnd->ClientFormats[wFormatNo]; WLog_Print(rdpsnd->log, WLOG_DEBUG, "WaveInfo: cBlockNo: %"PRIu8" wFormatNo: %"PRIu16" [%s]", - rdpsnd->cBlockNo, wFormatNo, rdpsnd_get_audio_tag_string(format->wFormatTag)); + rdpsnd->cBlockNo, wFormatNo, audio_format_get_tag_string(format->wFormatTag)); if (!rdpsnd->isOpen || (wFormatNo != rdpsnd->wCurrentFormatNo)) { @@ -799,7 +751,7 @@ static UINT rdpsnd_process_addin_args(rdpsndPlugin* rdpsnd, ADDIN_ARGV* args) if ((errno != 0) || (val > UINT16_MAX)) return CHANNEL_RC_INITIALIZATION_ERROR; - rdpsnd->fixedFormat = val; + rdpsnd->fixed_format->wFormatTag = val; } CommandLineSwitchCase(arg, "rate") { @@ -808,7 +760,7 @@ static UINT rdpsnd_process_addin_args(rdpsndPlugin* rdpsnd, ADDIN_ARGV* args) if ((errno != 0) || (val > UINT32_MAX)) return CHANNEL_RC_INITIALIZATION_ERROR; - rdpsnd->fixedRate = val; + rdpsnd->fixed_format->nSamplesPerSec = val; } CommandLineSwitchCase(arg, "channel") { @@ -817,7 +769,7 @@ static UINT rdpsnd_process_addin_args(rdpsndPlugin* rdpsnd, ADDIN_ARGV* args) if ((errno != 0) || (val > UINT16_MAX)) return CHANNEL_RC_INITIALIZATION_ERROR; - rdpsnd->fixedChannel = val; + rdpsnd->fixed_format->nChannels = val; } CommandLineSwitchCase(arg, "latency") { @@ -1225,10 +1177,10 @@ static UINT rdpsnd_virtual_channel_event_disconnected(rdpsndPlugin* rdpsnd) StreamPool_Return(rdpsnd->pool, rdpsnd->data_in); StreamPool_Free(rdpsnd->pool); Queue_Free(rdpsnd->queue); - rdpsnd_free_audio_formats(rdpsnd->ClientFormats, rdpsnd->NumberOfClientFormats); + audio_formats_free(rdpsnd->ClientFormats, rdpsnd->NumberOfClientFormats); rdpsnd->NumberOfClientFormats = 0; rdpsnd->ClientFormats = NULL; - rdpsnd_free_audio_formats(rdpsnd->ServerFormats, rdpsnd->NumberOfServerFormats); + audio_formats_free(rdpsnd->ServerFormats, rdpsnd->NumberOfServerFormats); rdpsnd->NumberOfServerFormats = 0; rdpsnd->ServerFormats = NULL; @@ -1245,6 +1197,7 @@ static void rdpsnd_virtual_channel_event_terminated(rdpsndPlugin* rdpsnd) { if (rdpsnd) { + audio_format_free(rdpsnd->fixed_format); free(rdpsnd->subsystem); free(rdpsnd->device_name); CloseHandle(rdpsnd->stopEvent); @@ -1340,6 +1293,14 @@ BOOL VCAPITYPE VirtualChannelEntryEx(PCHANNEL_ENTRY_POINTS pEntryPoints, PVOID p rdpsnd->rdpcontext = pEntryPointsEx->context; } + rdpsnd->fixed_format = audio_format_new(); + + if (!rdpsnd->fixed_format) + { + free(rdpsnd); + return FALSE; + } + rdpsnd->log = WLog_Get("com.freerdp.channels.rdpsnd.client"); CopyMemory(&(rdpsnd->channelEntryPoints), pEntryPoints, sizeof(CHANNEL_ENTRY_POINTS_FREERDP_EX)); diff --git a/channels/rdpsnd/server/rdpsnd_main.c b/channels/rdpsnd/server/rdpsnd_main.c index caebacab5..335c2204b 100644 --- a/channels/rdpsnd/server/rdpsnd_main.c +++ b/channels/rdpsnd/server/rdpsnd_main.c @@ -45,7 +45,7 @@ static UINT rdpsnd_server_send_formats(RdpsndServerContext* context, wStream* s) { size_t pos; UINT16 i; - BOOL status; + BOOL status = FALSE; ULONG written; Stream_Write_UINT8(s, SNDC_FORMATS); Stream_Write_UINT8(s, 0); @@ -61,25 +61,12 @@ static UINT rdpsnd_server_send_formats(RdpsndServerContext* context, wStream* s) for (i = 0; i < context->num_server_formats; i++) { - Stream_Write_UINT16(s, - context->server_formats[i].wFormatTag); /* wFormatTag (WAVE_FORMAT_PCM) */ - Stream_Write_UINT16(s, context->server_formats[i].nChannels); /* nChannels */ - Stream_Write_UINT32(s, - context->server_formats[i].nSamplesPerSec); /* nSamplesPerSec */ - Stream_Write_UINT32(s, context->server_formats[i].nSamplesPerSec* - context->server_formats[i].nChannels* - context->server_formats[i].wBitsPerSample / 8); /* nAvgBytesPerSec */ - Stream_Write_UINT16(s, - context->server_formats[i].nBlockAlign); /* nBlockAlign */ - Stream_Write_UINT16(s, - context->server_formats[i].wBitsPerSample); /* wBitsPerSample */ - Stream_Write_UINT16(s, context->server_formats[i].cbSize); /* cbSize */ + AUDIO_FORMAT format = context->server_formats[i]; + // TODO: Eliminate this!!! + format.nAvgBytesPerSec = format.nSamplesPerSec * format.nChannels * format.wBitsPerSample / 8; - if (context->server_formats[i].cbSize > 0) - { - Stream_Write(s, context->server_formats[i].data, - context->server_formats[i].cbSize); - } + if (!audio_format_write(s, &format)) + goto fail; } pos = Stream_GetPosition(s); @@ -89,6 +76,7 @@ static UINT rdpsnd_server_send_formats(RdpsndServerContext* context, wStream* s) status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), &written); Stream_SetPosition(s, 0); +fail: return status ? CHANNEL_RC_OK : ERROR_INTERNAL_ERROR; } @@ -184,8 +172,7 @@ static UINT rdpsnd_server_recv_formats(RdpsndServerContext* context, wStream* s) return ERROR_INTERNAL_ERROR; } - context->client_formats = (AUDIO_FORMAT*)calloc(context->num_client_formats, - sizeof(AUDIO_FORMAT)); + context->client_formats = audio_formats_new(context->num_client_formats); if (!context->client_formats) { @@ -322,17 +309,18 @@ static UINT rdpsnd_server_select_format(RdpsndServerContext* context, AUDIO_FORMAT* format; UINT error = CHANNEL_RC_OK; - if (client_format_index < 0 - || client_format_index >= context->num_client_formats) + if ((client_format_index < 0) + || (client_format_index >= context->num_client_formats) + || (!context->src_format)) { WLog_ERR(TAG, "index %d is not correct.", client_format_index); return ERROR_INVALID_DATA; } EnterCriticalSection(&context->priv->lock); - context->priv->src_bytes_per_sample = context->src_format.wBitsPerSample / 8; + context->priv->src_bytes_per_sample = context->src_format->wBitsPerSample / 8; context->priv->src_bytes_per_frame = context->priv->src_bytes_per_sample * - context->src_format.nChannels; + context->src_format->nChannels; context->selected_client_format = client_format_index; format = &context->client_formats[client_format_index]; @@ -346,7 +334,7 @@ static UINT rdpsnd_server_select_format(RdpsndServerContext* context, if (context->latency <= 0) context->latency = 50; - context->priv->out_frames = context->src_format.nSamplesPerSec * + context->priv->out_frames = context->src_format->nSamplesPerSec * context->latency / 1000; if (context->priv->out_frames < 1) diff --git a/include/freerdp/codec/audio.h b/include/freerdp/codec/audio.h index 73ee571b2..21e9fc538 100644 --- a/include/freerdp/codec/audio.h +++ b/include/freerdp/codec/audio.h @@ -20,6 +20,8 @@ #ifndef FREERDP_CODEC_AUDIO_H #define FREERDP_CODEC_AUDIO_H +#include + #include #include @@ -191,14 +193,24 @@ typedef struct AUDIO_FORMAT AUDIO_FORMAT; extern "C" { #endif -FREERDP_API UINT32 rdpsnd_compute_audio_time_length(const AUDIO_FORMAT* format, size_t size); +FREERDP_API UINT32 audio_format_compute_time_length(const AUDIO_FORMAT* format, size_t size); -FREERDP_API char* rdpsnd_get_audio_tag_string(UINT16 wFormatTag); +FREERDP_API char* audio_format_get_tag_string(UINT16 wFormatTag); -FREERDP_API void rdpsnd_print_audio_format(const AUDIO_FORMAT* format); -FREERDP_API void rdpsnd_print_audio_formats(const AUDIO_FORMAT* formats, UINT16 count); +FREERDP_API void audio_format_print(wLog* log, DWORD level, const AUDIO_FORMAT* format); +FREERDP_API void audio_formats_print(wLog* log, DWORD level, const AUDIO_FORMAT* formats, + UINT16 count); -FREERDP_API void rdpsnd_free_audio_formats(AUDIO_FORMAT* formats, UINT16 count); +FREERDP_API BOOL audio_format_read(wStream* s, AUDIO_FORMAT* format); +FREERDP_API BOOL audio_format_write(wStream* s, const AUDIO_FORMAT* format); +FREERDP_API BOOL audio_format_copy(const AUDIO_FORMAT* srcFormat, AUDIO_FORMAT* dstFormat); +FREERDP_API BOOL audio_format_compatible(const AUDIO_FORMAT* with, const AUDIO_FORMAT* what); + +FREERDP_API AUDIO_FORMAT* audio_format_new(void); +FREERDP_API AUDIO_FORMAT* audio_formats_new(size_t count); + +FREERDP_API void audio_format_free(AUDIO_FORMAT* format); +FREERDP_API void audio_formats_free(AUDIO_FORMAT* formats, size_t count); #ifdef __cplusplus } diff --git a/include/freerdp/server/audin.h b/include/freerdp/server/audin.h index 10c7a88c6..ade14abfd 100644 --- a/include/freerdp/server/audin.h +++ b/include/freerdp/server/audin.h @@ -28,15 +28,16 @@ typedef struct _audin_server_context audin_server_context; -typedef UINT(*psAudinServerSelectFormat)(audin_server_context* context, int client_format_index); +typedef UINT(*psAudinServerSelectFormat)(audin_server_context* context, size_t client_format_index); typedef BOOL (*psAudinServerOpen)(audin_server_context* context); typedef BOOL (*psAudinServerIsOpen)(audin_server_context* context); typedef BOOL (*psAudinServerClose)(audin_server_context* context); typedef UINT(*psAudinServerOpening)(audin_server_context* context); typedef UINT(*psAudinServerOpenResult)(audin_server_context* context, UINT32 result); -typedef UINT(*psAudinServerReceiveSamples)(audin_server_context* context, const void* buf, - int nframes); +typedef UINT(*psAudinServerReceiveSamples)(audin_server_context* context, + const AUDIO_FORMAT* format, wStream* buf, + size_t nframes); struct _audin_server_context { @@ -46,19 +47,19 @@ struct _audin_server_context void* data; /* Server supported formats. Set by server. */ - const AUDIO_FORMAT* server_formats; - int num_server_formats; + AUDIO_FORMAT* server_formats; + size_t num_server_formats; /* Server destination PCM audio format. Set by server. */ - AUDIO_FORMAT dst_format; + AUDIO_FORMAT* dst_format; /* Server preferred frames per packet. */ int frames_per_packet; /* Client supported formats. */ AUDIO_FORMAT* client_formats; - int num_client_formats; - int selected_client_format; + size_t num_client_formats; + SSIZE_T selected_client_format; /*** APIs called by the server. ***/ /** diff --git a/include/freerdp/server/rdpsnd.h b/include/freerdp/server/rdpsnd.h index 64f480524..ee6e87536 100644 --- a/include/freerdp/server/rdpsnd.h +++ b/include/freerdp/server/rdpsnd.h @@ -57,11 +57,11 @@ struct _rdpsnd_server_context void* data; /* Server supported formats. Set by server. */ - const AUDIO_FORMAT* server_formats; - int num_server_formats; + AUDIO_FORMAT* server_formats; + size_t num_server_formats; /* Server source PCM audio format. Set by server. */ - AUDIO_FORMAT src_format; + AUDIO_FORMAT* src_format; /* Server audio latency, or buffer size, in milli-seconds. Set by server. */ int latency; diff --git a/include/freerdp/server/server-common.h b/include/freerdp/server/server-common.h new file mode 100644 index 000000000..b19b12d93 --- /dev/null +++ b/include/freerdp/server/server-common.h @@ -0,0 +1,31 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * FreeRDP Server Common + * + * Copyright 2018 Armin Novak + * Copyright 2018 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. + */ + +#ifndef FREERDP_SERVER_COMMON_SERVER_H +#define FREERDP_SERVER_COMMON_SERVER_H + +#include +#include +#include + +FREERDP_API size_t server_audin_get_formats(AUDIO_FORMAT** dst_formats); +FREERDP_API size_t server_rdpsnd_get_formats(AUDIO_FORMAT** dst_formats); + +#endif /* FREERDP_SERVER_COMMON_SERVER_H */ diff --git a/include/freerdp/server/shadow.h b/include/freerdp/server/shadow.h index 6cfc6a085..5e10422d1 100644 --- a/include/freerdp/server/shadow.h +++ b/include/freerdp/server/shadow.h @@ -63,7 +63,7 @@ typedef int (*pfnShadowSubsystemUninit)(rdpShadowSubsystem* subsystem); typedef int (*pfnShadowSubsystemStart)(rdpShadowSubsystem* subsystem); typedef int (*pfnShadowSubsystemStop)(rdpShadowSubsystem* subsystem); -typedef UINT32 (*pfnShadowEnumMonitors)(MONITOR_DEF* monitors, UINT32 maxMonitors); +typedef UINT32(*pfnShadowEnumMonitors)(MONITOR_DEF* monitors, UINT32 maxMonitors); typedef int (*pfnShadowAuthenticate)(rdpShadowSubsystem* subsystem, rdpShadowClient* client, @@ -75,20 +75,20 @@ typedef void (*pfnShadowClientDisconnect)(rdpShadowSubsystem* subsystem, typedef BOOL (*pfnShadowClientCapabilities)(rdpShadowSubsystem* subsystem, rdpShadowClient* client); -typedef int (*pfnShadowSynchronizeEvent)(rdpShadowSubsystem* subsystem, +typedef BOOL (*pfnShadowSynchronizeEvent)(rdpShadowSubsystem* subsystem, rdpShadowClient* client, UINT32 flags); -typedef int (*pfnShadowKeyboardEvent)(rdpShadowSubsystem* subsystem, - rdpShadowClient* client, UINT16 flags, UINT16 code); -typedef int (*pfnShadowUnicodeKeyboardEvent)(rdpShadowSubsystem* subsystem, +typedef BOOL (*pfnShadowKeyboardEvent)(rdpShadowSubsystem* subsystem, + rdpShadowClient* client, UINT16 flags, UINT16 code); +typedef BOOL (*pfnShadowUnicodeKeyboardEvent)(rdpShadowSubsystem* subsystem, rdpShadowClient* client, UINT16 flags, UINT16 code); -typedef int (*pfnShadowMouseEvent)(rdpShadowSubsystem* subsystem, - rdpShadowClient* client, UINT16 flags, UINT16 x, UINT16 y); -typedef int (*pfnShadowExtendedMouseEvent)(rdpShadowSubsystem* subsystem, +typedef BOOL (*pfnShadowMouseEvent)(rdpShadowSubsystem* subsystem, + rdpShadowClient* client, UINT16 flags, UINT16 x, UINT16 y); +typedef BOOL (*pfnShadowExtendedMouseEvent)(rdpShadowSubsystem* subsystem, rdpShadowClient* client, UINT16 flags, UINT16 x, UINT16 y); -typedef void (*pfnShadowChannelAudinServerReceiveSamples)( - rdpShadowSubsystem* subsystem, rdpShadowClient* client, const void* buf, - int nframes); +typedef BOOL (*pfnShadowChannelAudinServerReceiveSamples)( + rdpShadowSubsystem* subsystem, rdpShadowClient* client, + const AUDIO_FORMAT* format, wStream* buf, size_t nframes); struct rdp_shadow_client { @@ -184,46 +184,43 @@ struct _RDP_SHADOW_ENTRY_POINTS pfnShadowEnumMonitors EnumMonitors; }; -#define RDP_SHADOW_SUBSYSTEM_COMMON() \ - RDP_SHADOW_ENTRY_POINTS ep; \ - HANDLE event; \ - int numMonitors; \ - int captureFrameRate; \ - int selectedMonitor; \ - MONITOR_DEF monitors[16]; \ - MONITOR_DEF virtualScreen; \ - \ - /* This event indicates that we have graphic change */ \ - /* such as screen update and resize. It should not be */ \ - /* used by subsystem implementation directly */ \ - rdpShadowMultiClientEvent* updateEvent; \ - \ - wMessagePipe* MsgPipe; \ - UINT32 pointerX; \ - UINT32 pointerY; \ - \ - const AUDIO_FORMAT* rdpsndFormats; \ - int nRdpsndFormats; \ - const AUDIO_FORMAT* audinFormats; \ - int nAudinFormats; \ - \ - pfnShadowSynchronizeEvent SynchronizeEvent; \ - pfnShadowKeyboardEvent KeyboardEvent; \ - pfnShadowUnicodeKeyboardEvent UnicodeKeyboardEvent; \ - pfnShadowMouseEvent MouseEvent; \ - pfnShadowExtendedMouseEvent ExtendedMouseEvent; \ - pfnShadowChannelAudinServerReceiveSamples AudinServerReceiveSamples; \ - \ - pfnShadowAuthenticate Authenticate; \ - pfnShadowClientConnect ClientConnect; \ - pfnShadowClientDisconnect ClientDisconnect; \ - pfnShadowClientCapabilities ClientCapabilities; \ - \ - rdpShadowServer* server - struct rdp_shadow_subsystem { - RDP_SHADOW_SUBSYSTEM_COMMON(); + RDP_SHADOW_ENTRY_POINTS ep; + HANDLE event; + int numMonitors; + int captureFrameRate; + int selectedMonitor; + MONITOR_DEF monitors[16]; + MONITOR_DEF virtualScreen; + + /* This event indicates that we have graphic change */ + /* such as screen update and resize. It should not be */ + /* used by subsystem implementation directly */ + rdpShadowMultiClientEvent* updateEvent; + + wMessagePipe* MsgPipe; + UINT32 pointerX; + UINT32 pointerY; + + AUDIO_FORMAT* rdpsndFormats; + size_t nRdpsndFormats; + AUDIO_FORMAT* audinFormats; + size_t nAudinFormats; + + pfnShadowSynchronizeEvent SynchronizeEvent; + pfnShadowKeyboardEvent KeyboardEvent; + pfnShadowUnicodeKeyboardEvent UnicodeKeyboardEvent; + pfnShadowMouseEvent MouseEvent; + pfnShadowExtendedMouseEvent ExtendedMouseEvent; + pfnShadowChannelAudinServerReceiveSamples AudinServerReceiveSamples; + + pfnShadowAuthenticate Authenticate; + pfnShadowClientConnect ClientConnect; + pfnShadowClientDisconnect ClientDisconnect; + pfnShadowClientCapabilities ClientCapabilities; + + rdpShadowServer* server; }; /* Definition of message between subsystem and clients */ @@ -232,13 +229,11 @@ struct rdp_shadow_subsystem typedef struct _SHADOW_MSG_OUT SHADOW_MSG_OUT; typedef void (*MSG_OUT_FREE_FN)(UINT32 id, SHADOW_MSG_OUT* msg); /* function to free SHADOW_MSG_OUT */ -#define RDP_SHADOW_MSG_OUT_COMMON() \ - int refCount; \ - MSG_OUT_FREE_FN Free struct _SHADOW_MSG_OUT { - RDP_SHADOW_MSG_OUT_COMMON(); + int refCount; + MSG_OUT_FREE_FN Free; }; #define SHADOW_MSG_OUT_POINTER_POSITION_UPDATE_ID 2001 @@ -248,16 +243,16 @@ struct _SHADOW_MSG_OUT struct _SHADOW_MSG_OUT_POINTER_POSITION_UPDATE { - RDP_SHADOW_MSG_OUT_COMMON(); + SHADOW_MSG_OUT common; UINT32 xPos; UINT32 yPos; }; typedef struct _SHADOW_MSG_OUT_POINTER_POSITION_UPDATE - SHADOW_MSG_OUT_POINTER_POSITION_UPDATE; + SHADOW_MSG_OUT_POINTER_POSITION_UPDATE; struct _SHADOW_MSG_OUT_POINTER_ALPHA_UPDATE { - RDP_SHADOW_MSG_OUT_COMMON(); + SHADOW_MSG_OUT common; UINT32 xHot; UINT32 yHot; UINT32 width; @@ -268,22 +263,22 @@ struct _SHADOW_MSG_OUT_POINTER_ALPHA_UPDATE BYTE* andMaskData; }; typedef struct _SHADOW_MSG_OUT_POINTER_ALPHA_UPDATE - SHADOW_MSG_OUT_POINTER_ALPHA_UPDATE; + SHADOW_MSG_OUT_POINTER_ALPHA_UPDATE; struct _SHADOW_MSG_OUT_AUDIO_OUT_SAMPLES { - RDP_SHADOW_MSG_OUT_COMMON(); - AUDIO_FORMAT audio_format; + SHADOW_MSG_OUT common; + AUDIO_FORMAT* audio_format; void* buf; int nFrames; UINT16 wTimestamp; }; typedef struct _SHADOW_MSG_OUT_AUDIO_OUT_SAMPLES - SHADOW_MSG_OUT_AUDIO_OUT_SAMPLES; + SHADOW_MSG_OUT_AUDIO_OUT_SAMPLES; struct _SHADOW_MSG_OUT_AUDIO_OUT_VOLUME { - RDP_SHADOW_MSG_OUT_COMMON(); + SHADOW_MSG_OUT common; int left; int right; }; diff --git a/libfreerdp/codec/audio.c b/libfreerdp/codec/audio.c index d5e52d7c1..e7f3735c8 100644 --- a/libfreerdp/codec/audio.c +++ b/libfreerdp/codec/audio.c @@ -28,7 +28,7 @@ #define TAG FREERDP_TAG("codec") -UINT32 rdpsnd_compute_audio_time_length(const AUDIO_FORMAT* format, size_t size) +UINT32 audio_format_compute_time_length(const AUDIO_FORMAT* format, size_t size) { UINT32 mstime; UINT32 wSamples; @@ -59,19 +59,19 @@ UINT32 rdpsnd_compute_audio_time_length(const AUDIO_FORMAT* format, size_t size) } else { - WLog_ERR(TAG, "rdpsnd_compute_audio_time_length: invalid WAVE_FORMAT_GSM610 format"); + WLog_ERR(TAG, "audio_format_compute_time_length: invalid WAVE_FORMAT_GSM610 format"); } } else { - WLog_ERR(TAG, "rdpsnd_compute_audio_time_length: unknown format %"PRIu16"", format->wFormatTag); + WLog_ERR(TAG, "audio_format_compute_time_length: unknown format %"PRIu16"", format->wFormatTag); } } return mstime; } -char* rdpsnd_get_audio_tag_string(UINT16 wFormatTag) +char* audio_format_get_tag_string(UINT16 wFormatTag) { switch (wFormatTag) { @@ -112,45 +112,184 @@ char* rdpsnd_get_audio_tag_string(UINT16 wFormatTag) return "WAVE_FORMAT_UNKNOWN"; } -void rdpsnd_print_audio_format(const AUDIO_FORMAT* format) +void audio_format_print(wLog* log, DWORD level, const AUDIO_FORMAT* format) { - WLog_INFO(TAG, "%s:\t wFormatTag: 0x%04"PRIX16" nChannels: %"PRIu16" nSamplesPerSec: %"PRIu32" " - "nAvgBytesPerSec: %"PRIu32" nBlockAlign: %"PRIu16" wBitsPerSample: %"PRIu16" cbSize: %"PRIu16"", - rdpsnd_get_audio_tag_string(format->wFormatTag), format->wFormatTag, - format->nChannels, format->nSamplesPerSec, format->nAvgBytesPerSec, - format->nBlockAlign, format->wBitsPerSample, format->cbSize); + WLog_Print(log, level, + "%s:\t wFormatTag: 0x%04"PRIX16" nChannels: %"PRIu16" nSamplesPerSec: %"PRIu32" " + "nAvgBytesPerSec: %"PRIu32" nBlockAlign: %"PRIu16" wBitsPerSample: %"PRIu16" cbSize: %"PRIu16"", + audio_format_get_tag_string(format->wFormatTag), format->wFormatTag, + format->nChannels, format->nSamplesPerSec, format->nAvgBytesPerSec, + format->nBlockAlign, format->wBitsPerSample, format->cbSize); } -void rdpsnd_print_audio_formats(const AUDIO_FORMAT* formats, UINT16 count) +void audio_formats_print(wLog* log, DWORD level, const AUDIO_FORMAT* formats, UINT16 count) { UINT16 index; const AUDIO_FORMAT* format; if (formats) { - WLog_INFO(TAG, "AUDIO_FORMATS (%"PRIu16") ={", count); + WLog_Print(log, level, "AUDIO_FORMATS (%"PRIu16") ={", count); for (index = 0; index < count; index++) { format = &formats[index]; - WLog_ERR(TAG, "\t"); - rdpsnd_print_audio_format(format); + WLog_Print(log, level, "\t"); + audio_format_print(log, level, format); } - WLog_ERR(TAG, "}"); + WLog_Print(log, level, "}"); } } -void rdpsnd_free_audio_formats(AUDIO_FORMAT* formats, UINT16 count) +BOOL audio_format_read(wStream* s, AUDIO_FORMAT* format) { - UINT16 index; + if (!s || !format) + return FALSE; + + if (Stream_GetRemainingLength(s) < 18) + return FALSE; + + Stream_Read_UINT16(s, format->wFormatTag); + Stream_Read_UINT16(s, format->nChannels); + Stream_Read_UINT32(s, format->nSamplesPerSec); + Stream_Read_UINT32(s, format->nAvgBytesPerSec); + Stream_Read_UINT16(s, format->nBlockAlign); + Stream_Read_UINT16(s, format->wBitsPerSample); + Stream_Read_UINT16(s, format->cbSize); + + if (Stream_GetRemainingLength(s) < format->cbSize) + return FALSE; + + format->data = NULL; + + if (format->cbSize > 0) + { + format->data = malloc(format->cbSize); + + if (!format->data) + return FALSE; + + Stream_Read(s, format->data, format->cbSize); + } + + return TRUE; +} + +BOOL audio_format_write(wStream* s, const AUDIO_FORMAT* format) +{ + if (!s || !format) + return FALSE; + + if (!Stream_EnsureRemainingCapacity(s, 18 + format->cbSize)) + return FALSE; + + Stream_Write_UINT16(s, format->wFormatTag); /* wFormatTag (WAVE_FORMAT_PCM) */ + Stream_Write_UINT16(s, format->nChannels); /* nChannels */ + Stream_Write_UINT32(s, format->nSamplesPerSec); /* nSamplesPerSec */ + Stream_Write_UINT32(s, format->nAvgBytesPerSec); /* nAvgBytesPerSec */ + Stream_Write_UINT16(s, format->nBlockAlign); /* nBlockAlign */ + Stream_Write_UINT16(s, format->wBitsPerSample); /* wBitsPerSample */ + Stream_Write_UINT16(s, format->cbSize); /* cbSize */ + + if (format->cbSize > 0) + Stream_Write(s, format->data, format->cbSize); + + return TRUE; +} + +BOOL audio_format_copy(const AUDIO_FORMAT* srcFormat, AUDIO_FORMAT* dstFormat) +{ + if (!srcFormat || !dstFormat) + return FALSE; + + *dstFormat = *srcFormat; + + if (srcFormat->cbSize > 0) + { + dstFormat->data = malloc(srcFormat->cbSize); + + if (!dstFormat->data) + return FALSE; + + memcpy(dstFormat->data, srcFormat->data, dstFormat->cbSize); + } + + return TRUE; +} + +BOOL audio_format_compatible(const AUDIO_FORMAT* with, const AUDIO_FORMAT* what) +{ + if (!with || !what) + return FALSE; + + if (with->wFormatTag != WAVE_FORMAT_UNKNOWN) + { + if (with->wFormatTag != what->wFormatTag) + return FALSE; + } + + if (with->nChannels != 0) + { + if (with->nChannels != what->nChannels) + return FALSE; + } + + if (with->nSamplesPerSec != 0) + { + if (with->nSamplesPerSec != what->nSamplesPerSec) + return FALSE; + } + + if (with->wBitsPerSample != 0) + { + if (with->wBitsPerSample != what->wBitsPerSample) + return FALSE; + } + + return TRUE; +} + +BOOL audio_format_valid(const AUDIO_FORMAT* format) +{ + if (!format) + return FALSE; + + if (format->nChannels == 0) + return FALSE; + + if (format->nSamplesPerSec == 0) + return FALSE; + + return TRUE; +} + +AUDIO_FORMAT* audio_format_new(void) +{ + return audio_formats_new(1); +} + +AUDIO_FORMAT* audio_formats_new(size_t count) +{ + return calloc(count, sizeof(AUDIO_FORMAT)); +} + +void audio_format_free(AUDIO_FORMAT* format) +{ + if (format) + free(format->data); +} + +void audio_formats_free(AUDIO_FORMAT* formats, size_t count) +{ + size_t index; if (formats) { for (index = 0; index < count; index++) { AUDIO_FORMAT* format = &formats[index]; - free(format->data); + audio_format_free(format); } free(formats); diff --git a/libfreerdp/codec/dsp_ffmpeg.c b/libfreerdp/codec/dsp_ffmpeg.c index ea6814fb3..672843c11 100644 --- a/libfreerdp/codec/dsp_ffmpeg.c +++ b/libfreerdp/codec/dsp_ffmpeg.c @@ -91,7 +91,7 @@ static enum AVCodecID ffmpeg_get_avcodec(const AUDIO_FORMAT* format) if (!format) return AV_CODEC_ID_NONE; - id = rdpsnd_get_audio_tag_string(format->wFormatTag); + id = audio_format_get_tag_string(format->wFormatTag); switch (format->wFormatTag) { diff --git a/server/Mac/mf_audin.c b/server/Mac/mf_audin.c index bc0a83c42..3584a571b 100644 --- a/server/Mac/mf_audin.c +++ b/server/Mac/mf_audin.c @@ -27,15 +27,10 @@ #include "mf_audin.h" +#include #include #define TAG SERVER_TAG("mac") -static const AUDIO_FORMAT supported_audio_formats[] = -{ - { WAVE_FORMAT_PCM, 2, 44100, 176400, 4, 16, 0, NULL }, - { WAVE_FORMAT_ALAW, 2, 22050, 44100, 2, 8, 0, NULL } -}; - /** * Function description * @@ -73,13 +68,9 @@ void mf_peer_audin_init(mfPeerContext* context) context->audin = audin_server_context_new(context->vcm); context->audin->rdpcontext = &context->_p; context->audin->data = context; - context->audin->server_formats = supported_audio_formats; - context->audin->num_server_formats = sizeof(supported_audio_formats) / sizeof( - supported_audio_formats[0]); - context->audin->dst_format.wFormatTag = 1; - context->audin->dst_format.nChannels = 2; - context->audin->dst_format.nSamplesPerSec = 44100; - context->audin->dst_format.wBitsPerSample = 16; + context->audin->num_server_formats = server_audin_get_formats(&context->audin->server_formats); + if (context->audin->num_server_formats > 0) + context->audin->dst_format = &context->audin->server_formats[0]; context->audin->Opening = mf_peer_audin_opening; context->audin->OpenResult = mf_peer_audin_open_result; context->audin->ReceiveSamples = mf_peer_audin_receive_samples; diff --git a/server/Mac/mf_rdpsnd.c b/server/Mac/mf_rdpsnd.c index 55900db2c..1230439d7 100644 --- a/server/Mac/mf_rdpsnd.c +++ b/server/Mac/mf_rdpsnd.c @@ -29,17 +29,12 @@ #include "mf_rdpsnd.h" #include +#include #include #define TAG SERVER_TAG("mac") AQRecorderState recorderState; -static const AUDIO_FORMAT supported_audio_formats[] = -{ - { WAVE_FORMAT_PCM, 2, 44100, 176400, 4, 16, 0, NULL }, - { WAVE_FORMAT_ALAW, 2, 22050, 44100, 2, 8, 0, NULL } -}; - static void mf_peer_rdpsnd_activated(RdpsndServerContext* context) { OSStatus status; @@ -145,13 +140,11 @@ BOOL mf_peer_rdpsnd_init(mfPeerContext* context) context->rdpsnd = rdpsnd_server_context_new(context->vcm); context->rdpsnd->rdpcontext = &context->_p; context->rdpsnd->data = context; - context->rdpsnd->server_formats = supported_audio_formats; - context->rdpsnd->num_server_formats = sizeof(supported_audio_formats) / sizeof( - supported_audio_formats[0]); - context->rdpsnd->src_format.wFormatTag = 1; - context->rdpsnd->src_format.nChannels = 2; - context->rdpsnd->src_format.nSamplesPerSec = 44100; - context->rdpsnd->src_format.wBitsPerSample = 16; + context->rdpsnd->num_server_formats = server_rdpsnd_get_formats(&context->rdpsnd->server_formats); + + if (context->rdpsnd->num_server_formats > 0) + context->rdpsnd->src_format = &context->rdpsnd->server_formats[0]; + context->rdpsnd->Activated = mf_peer_rdpsnd_activated; context->rdpsnd->Initialize(context->rdpsnd, TRUE); return TRUE; diff --git a/server/Sample/sf_audin.c b/server/Sample/sf_audin.c index 67dc92351..022b5bc62 100644 --- a/server/Sample/sf_audin.c +++ b/server/Sample/sf_audin.c @@ -32,12 +32,6 @@ #include #define TAG SERVER_TAG("sample") -static const AUDIO_FORMAT test_audio_formats[] = -{ - { WAVE_FORMAT_PCM, 2, 44100, 176400, 4, 16, 0, NULL }, - { WAVE_FORMAT_ALAW, 2, 22050, 44100, 2, 8, 0, NULL } -}; - /** * Function description * @@ -67,7 +61,8 @@ static UINT sf_peer_audin_open_result(audin_server_context* context, UINT32 resu * * @return 0 on success, otherwise a Win32 error code */ -static UINT sf_peer_audin_receive_samples(audin_server_context* context, const void* buf, int nframes) +static UINT 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; @@ -78,15 +73,10 @@ void sf_peer_audin_init(testPeerContext* context) context->audin = audin_server_context_new(context->vcm); context->audin->rdpcontext = &context->_p; context->audin->data = context; + context->audin->num_server_formats = server_audin_get_formats(&context->audin->server_formats); - context->audin->server_formats = test_audio_formats; - context->audin->num_server_formats = - sizeof(test_audio_formats) / sizeof(test_audio_formats[0]); - - context->audin->dst_format.wFormatTag = 1; - context->audin->dst_format.nChannels = 2; - context->audin->dst_format.nSamplesPerSec = 44100; - context->audin->dst_format.wBitsPerSample = 16; + if (context->audin->num_server_formats > 0) + context->audin->dst_format = &context->audin->server_formats[0]; context->audin->Opening = sf_peer_audin_opening; context->audin->OpenResult = sf_peer_audin_open_result; diff --git a/server/Sample/sf_rdpsnd.c b/server/Sample/sf_rdpsnd.c index 63fcb7549..3d87f740a 100644 --- a/server/Sample/sf_rdpsnd.c +++ b/server/Sample/sf_rdpsnd.c @@ -28,15 +28,10 @@ #include "sf_rdpsnd.h" +#include #include #define TAG SERVER_TAG("sample") -static const AUDIO_FORMAT test_audio_formats[] = -{ - { WAVE_FORMAT_PCM, 2, 44100, 176400, 4, 16, 0, NULL }, - { WAVE_FORMAT_ALAW, 2, 22050, 44100, 2, 8, 0, NULL } -}; - static void sf_peer_rdpsnd_activated(RdpsndServerContext* context) { WLog_DBG(TAG, "RDPSND Activated"); @@ -47,15 +42,10 @@ BOOL sf_peer_rdpsnd_init(testPeerContext* context) context->rdpsnd = rdpsnd_server_context_new(context->vcm); context->rdpsnd->rdpcontext = &context->_p; context->rdpsnd->data = context; + context->rdpsnd->num_server_formats = server_rdpsnd_get_formats(&context->rdpsnd->server_formats); - context->rdpsnd->server_formats = test_audio_formats; - context->rdpsnd->num_server_formats = - sizeof(test_audio_formats) / sizeof(test_audio_formats[0]); - - context->rdpsnd->src_format.wFormatTag = 1; - context->rdpsnd->src_format.nChannels = 2; - context->rdpsnd->src_format.nSamplesPerSec = 44100; - context->rdpsnd->src_format.wBitsPerSample = 16; + if (context->rdpsnd->num_server_formats > 0) + context->rdpsnd->src_format = &context->rdpsnd->server_formats[0]; context->rdpsnd->Activated = sf_peer_rdpsnd_activated; diff --git a/server/Windows/wf_rdpsnd.c b/server/Windows/wf_rdpsnd.c index 4dce37fc9..84be3067c 100644 --- a/server/Windows/wf_rdpsnd.c +++ b/server/Windows/wf_rdpsnd.c @@ -26,6 +26,7 @@ #include #include +#include #include "wf_rdpsnd.h" #include "wf_info.h" @@ -42,19 +43,11 @@ #define TAG SERVER_TAG("windows") -static const AUDIO_FORMAT supported_audio_formats[] = -{ - { WAVE_FORMAT_PCM, 2, 44100, 176400, 4, 16, 0, NULL }, - { WAVE_FORMAT_ALAW, 2, 22050, 44100, 2, 8, 0, NULL } -}; - static void wf_peer_rdpsnd_activated(RdpsndServerContext* context) { wfInfo* wfi; int i, j; - wfi = wf_info_get_instance(); - wfi->agreed_format = NULL; WLog_DBG(TAG, "Client supports the following %d formats:", context->num_client_formats); @@ -72,56 +65,48 @@ static void wf_peer_rdpsnd_activated(RdpsndServerContext* context) break; } } + if (wfi->agreed_format != NULL) break; - } - + if (wfi->agreed_format == NULL) { WLog_ERR(TAG, "Could not agree on a audio format with the server"); return; } - + context->SelectFormat(context, i); context->SetVolume(context, 0x7FFF, 0x7FFF); - #ifdef WITH_RDPSND_DSOUND - wf_directsound_activate(context); - #else - wf_wasapi_activate(context); - #endif - } int wf_rdpsnd_lock() { DWORD dRes; wfInfo* wfi; - wfi = wf_info_get_instance(); - dRes = WaitForSingleObject(wfi->snd_mutex, INFINITE); switch (dRes) { - case WAIT_ABANDONED: - case WAIT_OBJECT_0: - return TRUE; - break; + case WAIT_ABANDONED: + case WAIT_OBJECT_0: + return TRUE; + break; - case WAIT_TIMEOUT: - return FALSE; - break; + case WAIT_TIMEOUT: + return FALSE; + break; - case WAIT_FAILED: - WLog_ERR(TAG, "wf_rdpsnd_lock failed with 0x%08lX", GetLastError()); - return -1; - break; + case WAIT_FAILED: + WLog_ERR(TAG, "wf_rdpsnd_lock failed with 0x%08lX", GetLastError()); + return -1; + break; } return -1; @@ -130,7 +115,6 @@ int wf_rdpsnd_lock() int wf_rdpsnd_unlock() { wfInfo* wfi; - wfi = wf_info_get_instance(); if (ReleaseMutex(wfi->snd_mutex) == 0) @@ -145,7 +129,7 @@ int wf_rdpsnd_unlock() BOOL wf_peer_rdpsnd_init(wfPeerContext* context) { wfInfo* wfi = wf_info_get_instance(); - + if (!wfi) return FALSE; @@ -155,22 +139,14 @@ BOOL wf_peer_rdpsnd_init(wfPeerContext* context) context->rdpsnd = rdpsnd_server_context_new(context->vcm); context->rdpsnd->rdpcontext = &context->_p; context->rdpsnd->data = context; + context->rdpsnd->num_server_formats = server_rdpsnd_get_formats(&context->rdpsnd->server_formats); - context->rdpsnd->server_formats = supported_audio_formats; - context->rdpsnd->num_server_formats = - sizeof(supported_audio_formats) / sizeof(supported_audio_formats[0]); - - context->rdpsnd->src_format.wFormatTag = 1; - context->rdpsnd->src_format.nChannels = 2; - context->rdpsnd->src_format.nSamplesPerSec = 44100; - context->rdpsnd->src_format.wBitsPerSample = 16; + if (context->rdpsnd->num_server_formats > 0) + context->rdpsnd->src_format = &context->rdpsnd->server_formats[0]; context->rdpsnd->Activated = wf_peer_rdpsnd_activated; - context->rdpsnd->Initialize(context->rdpsnd, TRUE); - wf_rdpsnd_set_latest_peer(context); - wfi->snd_stop = FALSE; return TRUE; } diff --git a/server/common/server.c b/server/common/server.c index c2ea8fc5b..e8211d939 100644 --- a/server/common/server.c +++ b/server/common/server.c @@ -21,3 +21,154 @@ #include "config.h" #endif +#include +#include +#include + +#include + +size_t server_audin_get_formats(AUDIO_FORMAT** dst_formats) +{ + /* Default supported audio formats */ + BYTE adpcm_data_7[] = + { + 0xf4, 0x07, 0x07, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, + 0xff, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x40, 0x00, 0xf0, 0x00, + 0x00, 0x00, 0xcc, 0x01, 0x30, 0xff, 0x88, 0x01, 0x18, 0xff + }; + BYTE adpcm_data_3[] = + { + 0xf4, 0x03, 0x07, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, + 0xff, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x40, 0x00, 0xf0, 0x00, + 0x00, 0x00, 0xcc, 0x01, 0x30, 0xff, 0x88, 0x01, 0x18, 0xff + }; + BYTE adpcm_data_1[] = + { + 0xf4, 0x01, 0x07, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, + 0xff, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x40, 0x00, 0xf0, 0x00, + 0x00, 0x00, 0xcc, 0x01, 0x30, 0xff, 0x88, 0x01, 0x18, 0xff + }; + BYTE adpcm_dvi_data_7[] = { 0xf9, 0x07 }; + BYTE adpcm_dvi_data_3[] = { 0xf9, 0x03 }; + BYTE adpcm_dvi_data_1[] = { 0xf9, 0x01 }; + BYTE gsm610_data[] = { 0x40, 0x01 }; + const AUDIO_FORMAT default_supported_audio_formats[] = + { + /* Formats sent by windows 10 server */ + { WAVE_FORMAT_AAC_MS, 2, 44100, 24000, 4, 16, 0, NULL }, + { WAVE_FORMAT_AAC_MS, 2, 44100, 20000, 4, 16, 0, NULL }, + { WAVE_FORMAT_AAC_MS, 2, 44100, 16000, 4, 16, 0, NULL }, + { WAVE_FORMAT_AAC_MS, 2, 44100, 12000, 4, 16, 0, NULL }, + { WAVE_FORMAT_PCM, 2, 44100, 176400, 4, 16, 0, NULL }, + { WAVE_FORMAT_ADPCM, 2, 44100, 44359, 2048, 4, 32, adpcm_data_7 }, + { WAVE_FORMAT_DVI_ADPCM, 2, 44100, 44251, 2048, 4, 2, adpcm_dvi_data_7 }, + { WAVE_FORMAT_ALAW, 2, 22050, 44100, 2, 8, 0, NULL }, + { WAVE_FORMAT_ADPCM, 2, 22050, 22311, 1024, 4, 32, adpcm_data_3 }, + { WAVE_FORMAT_DVI_ADPCM, 2, 22050, 22201, 1024, 4, 2, adpcm_dvi_data_3 }, + { WAVE_FORMAT_ADPCM, 1, 44100, 22179, 1024, 4, 32, adpcm_data_7 }, + { WAVE_FORMAT_DVI_ADPCM, 1, 44100, 22125, 1024, 4, 2, adpcm_dvi_data_7 }, + { WAVE_FORMAT_ADPCM, 2, 11025, 11289, 512, 4, 32, adpcm_data_1 }, + { WAVE_FORMAT_DVI_ADPCM, 2, 11025, 11177, 512, 4, 2, adpcm_dvi_data_1 }, + { WAVE_FORMAT_ADPCM, 1, 22050, 11155, 512, 4, 32, adpcm_data_3 }, + { WAVE_FORMAT_DVI_ADPCM, 1, 22050, 11100, 512, 4, 2, adpcm_dvi_data_3 }, + { WAVE_FORMAT_GSM610, 1, 44100, 8957, 65, 0, 2, gsm610_data }, + { WAVE_FORMAT_ADPCM, 2, 8000, 8192, 512, 4, 32, adpcm_data_1 }, + { WAVE_FORMAT_DVI_ADPCM, 2, 8000, 8110, 512, 4, 2, adpcm_dvi_data_1 }, + { WAVE_FORMAT_ADPCM, 1, 11025, 5644, 256, 4, 32, adpcm_data_1 }, + { WAVE_FORMAT_DVI_ADPCM, 1, 11025, 5588, 256, 4, 2, adpcm_dvi_data_1 }, + { WAVE_FORMAT_GSM610, 1, 22050, 4478, 65, 0, 2, gsm610_data }, + { WAVE_FORMAT_ADPCM, 1, 8000, 4096, 256, 4, 32, adpcm_data_1 }, + { WAVE_FORMAT_DVI_ADPCM, 1, 8000, 4055, 256, 4, 2, adpcm_dvi_data_1 }, + { WAVE_FORMAT_GSM610, 1, 11025, 2239, 65, 0, 2, gsm610_data }, + { WAVE_FORMAT_GSM610, 1, 8000, 1625, 65, 0, 2, gsm610_data }, + /* Formats added for others */ + + { WAVE_FORMAT_MSG723, 2, 44100, 0, 4, 16, 0, NULL }, + { WAVE_FORMAT_MSG723, 2, 22050, 0, 4, 16, 0, NULL }, + { WAVE_FORMAT_MSG723, 1, 44100, 0, 4, 16, 0, NULL }, + { WAVE_FORMAT_MSG723, 1, 22050, 0, 4, 16, 0, NULL }, + { WAVE_FORMAT_PCM, 2, 44100, 176400, 4, 16, 0, NULL }, + { WAVE_FORMAT_PCM, 2, 22050, 88200, 4, 16, 0, NULL }, + { WAVE_FORMAT_PCM, 1, 44100, 88200, 4, 16, 0, NULL }, + { WAVE_FORMAT_PCM, 1, 22050, 44100, 4, 16, 0, NULL }, + { WAVE_FORMAT_MULAW, 2, 44100, 88200, 4, 16, 0, NULL }, + { WAVE_FORMAT_MULAW, 2, 22050, 44100, 4, 16, 0, NULL }, + { WAVE_FORMAT_MULAW, 1, 44100, 44100, 4, 16, 0, NULL }, + { WAVE_FORMAT_MULAW, 1, 22050, 22050, 4, 16, 0, NULL }, + { WAVE_FORMAT_ALAW, 2, 44100, 88200, 2, 8, 0, NULL }, + { WAVE_FORMAT_ALAW, 2, 22050, 44100, 2, 8, 0, NULL }, + { WAVE_FORMAT_ALAW, 1, 44100, 44100, 2, 8, 0, NULL }, + { WAVE_FORMAT_ALAW, 1, 22050, 22050, 2, 8, 0, NULL } + }; + const size_t nrDefaultFormatsMax = ARRAYSIZE(default_supported_audio_formats); + size_t x, nr_formats = 0; + AUDIO_FORMAT* formats = audio_formats_new(nrDefaultFormatsMax); + + if (!dst_formats) + goto fail; + + *dst_formats = NULL; + + if (!formats) + goto fail; + + for (x = 0; x < nrDefaultFormatsMax; x++) + { + const AUDIO_FORMAT* format = &default_supported_audio_formats[x]; + + if (freerdp_dsp_supports_format(format, FALSE)) + { + AUDIO_FORMAT* dst = &formats[nr_formats++]; + + if (!audio_format_copy(format, dst)) + goto fail; + } + } + + *dst_formats = formats; + return nr_formats; +fail: + audio_formats_free(formats, nrDefaultFormatsMax); + return 0; +} + + +size_t server_rdpsnd_get_formats(AUDIO_FORMAT** dst_formats) +{ + size_t x, y = 0; + /* Default supported audio formats */ + static const AUDIO_FORMAT default_supported_audio_formats[] = + { + { WAVE_FORMAT_AAC_MS, 2, 44100, 176400, 4, 16, 0, NULL }, + { WAVE_FORMAT_MPEGLAYER3, 2, 44100, 176400, 4, 16, 0, NULL }, + { WAVE_FORMAT_MSG723, 2, 44100, 176400, 4, 16, 0, NULL }, + { WAVE_FORMAT_GSM610, 2, 44100, 176400, 4, 16, 0, NULL }, + { WAVE_FORMAT_ADPCM, 2, 44100, 176400, 4, 16, 0, NULL }, + { WAVE_FORMAT_PCM, 2, 44100, 176400, 4, 16, 0, NULL }, + { WAVE_FORMAT_ALAW, 2, 22050, 44100, 2, 8, 0, NULL }, + { WAVE_FORMAT_MULAW, 2, 22050, 44100, 2, 8, 0, NULL }, + }; + AUDIO_FORMAT* supported_audio_formats = audio_formats_new(ARRAYSIZE( + default_supported_audio_formats)); + + if (!supported_audio_formats) + goto fail; + + for (x = 0; x < ARRAYSIZE(default_supported_audio_formats); x++) + { + const AUDIO_FORMAT* format = &default_supported_audio_formats[x]; + + if (freerdp_dsp_supports_format(format, TRUE)) + supported_audio_formats[y++] = *format; + } + + /* Set default audio formats. */ + *dst_formats = supported_audio_formats; +fail: + audio_formats_free(supported_audio_formats, ARRAYSIZE(default_supported_audio_formats)); + + if (dst_formats) + *dst_formats = NULL; + + return 0; +} diff --git a/server/shadow/Mac/mac_shadow.c b/server/shadow/Mac/mac_shadow.c index a8b74a916..2297005a0 100644 --- a/server/shadow/Mac/mac_shadow.c +++ b/server/shadow/Mac/mac_shadow.c @@ -32,12 +32,16 @@ static macShadowSubsystem* g_Subsystem = NULL; -static void mac_shadow_input_synchronize_event(macShadowSubsystem* subsystem, +static BOOL mac_shadow_input_synchronize_event(rdpShadowSubsystem* subsystem, rdpShadowClient* client, UINT32 flags) { + if (!subsystem || !client) + return FALSE; + + return TRUE; } -static void mac_shadow_input_keyboard_event(macShadowSubsystem* subsystem, +static BOOL mac_shadow_input_keyboard_event(rdpShadowSubsystem* subsystem, rdpShadowClient* client, UINT16 flags, UINT16 code) { DWORD vkcode; @@ -47,6 +51,9 @@ static void mac_shadow_input_keyboard_event(macShadowSubsystem* subsystem, CGEventSourceRef source; extended = (flags & KBD_FLAGS_EXTENDED) ? TRUE : FALSE; + if (!subsystem || !client) + return FALSE; + if (extended) code |= KBDEXT; @@ -58,7 +65,7 @@ static void mac_shadow_input_keyboard_event(macShadowSubsystem* subsystem, keycode = GetKeycodeFromVirtualKeyCode(vkcode, KEYCODE_TYPE_APPLE); if (keycode < 8) - return; + return TRUE; keycode -= 8; source = CGEventSourceCreate(kCGEventSourceStateHIDSystemState); @@ -77,20 +84,29 @@ static void mac_shadow_input_keyboard_event(macShadowSubsystem* subsystem, } CFRelease(source); + return TRUE; } -static void mac_shadow_input_unicode_keyboard_event(macShadowSubsystem* +static BOOL mac_shadow_input_unicode_keyboard_event(rdpShadowSubsystem* subsystem, rdpShadowClient* client, UINT16 flags, UINT16 code) { + if (!subsystem || !client) + return FALSE; + + return TRUE; } -static void mac_shadow_input_mouse_event(macShadowSubsystem* subsystem, +static BOOL mac_shadow_input_mouse_event(rdpShadowSubsystem* subsystem, rdpShadowClient* client, UINT16 flags, UINT16 x, UINT16 y) { + macShadowSubsystem* mac = (macShadowSubsystem*)subsystem; UINT32 scrollX = 0; UINT32 scrollY = 0; CGWheelCount wheelCount = 2; + if (!subsystem || !client) + return FALSE; + if (flags & PTR_FLAGS_WHEEL) { scrollY = flags & WheelRotationMask; @@ -122,11 +138,11 @@ static void mac_shadow_input_mouse_event(macShadowSubsystem* subsystem, if (flags & PTR_FLAGS_MOVE) { - if (subsystem->mouseDownLeft) + if (mac->mouseDownLeft) mouseType = kCGEventLeftMouseDragged; - else if (subsystem->mouseDownRight) + else if (mac->mouseDownRight) mouseType = kCGEventRightMouseDragged; - else if (subsystem->mouseDownOther) + else if (mac->mouseDownOther) mouseType = kCGEventOtherMouseDragged; else mouseType = kCGEventMouseMoved; @@ -144,12 +160,12 @@ static void mac_shadow_input_mouse_event(macShadowSubsystem* subsystem, if (flags & PTR_FLAGS_DOWN) { mouseType = kCGEventLeftMouseDown; - subsystem->mouseDownLeft = TRUE; + mac->mouseDownLeft = TRUE; } else { mouseType = kCGEventLeftMouseUp; - subsystem->mouseDownLeft = FALSE; + mac->mouseDownLeft = FALSE; } } else if (flags & PTR_FLAGS_BUTTON2) @@ -159,12 +175,12 @@ static void mac_shadow_input_mouse_event(macShadowSubsystem* subsystem, if (flags & PTR_FLAGS_DOWN) { mouseType = kCGEventRightMouseDown; - subsystem->mouseDownRight = TRUE; + mac->mouseDownRight = TRUE; } else { mouseType = kCGEventRightMouseUp; - subsystem->mouseDownRight = FALSE; + mac->mouseDownRight = FALSE; } } else if (flags & PTR_FLAGS_BUTTON3) @@ -174,12 +190,12 @@ static void mac_shadow_input_mouse_event(macShadowSubsystem* subsystem, if (flags & PTR_FLAGS_DOWN) { mouseType = kCGEventOtherMouseDown; - subsystem->mouseDownOther = TRUE; + mac->mouseDownOther = TRUE; } else { mouseType = kCGEventOtherMouseUp; - subsystem->mouseDownOther = FALSE; + mac->mouseDownOther = FALSE; } } @@ -189,11 +205,17 @@ static void mac_shadow_input_mouse_event(macShadowSubsystem* subsystem, CFRelease(mouseEvent); CFRelease(source); } + + return TRUE; } -static void mac_shadow_input_extended_mouse_event(macShadowSubsystem* subsystem, +static BOOL mac_shadow_input_extended_mouse_event(rdpShadowSubsystem* subsystem, rdpShadowClient* client, UINT16 flags, UINT16 x, UINT16 y) { + if (!subsystem || !client) + return FALSE; + + return TRUE; } static int mac_shadow_detect_monitors(macShadowSubsystem* subsystem) @@ -221,8 +243,8 @@ static int mac_shadow_detect_monitors(macShadowSubsystem* subsystem) subsystem->height = subsystem->pixelHeight; } - subsystem->numMonitors = 1; - monitor = &(subsystem->monitors[0]); + subsystem->common.numMonitors = 1; + monitor = &(subsystem->common.monitors[0]); monitor->left = 0; monitor->top = 0; monitor->right = subsystem->width; @@ -259,7 +281,7 @@ static int mac_shadow_capture_get_dirty_region(macShadowSubsystem* subsystem) size_t numRects; const CGRect* rects; RECTANGLE_16 invalidRect; - rdpShadowSurface* surface = subsystem->server->surface; + rdpShadowSurface* surface = subsystem->common.server->surface; rects = CGDisplayStreamUpdateGetRects(subsystem->lastUpdate, kCGDisplayStreamUpdateDirtyRects, &numRects); @@ -359,7 +381,7 @@ static void (^mac_capture_stream_handler)(CGDisplayStreamFrameStatus, uint64_t, RECTANGLE_16 surfaceRect; const RECTANGLE_16* extents; macShadowSubsystem* subsystem = g_Subsystem; - rdpShadowServer* server = subsystem->server; + rdpShadowServer* server = subsystem->common.server; rdpShadowSurface* surface = server->surface; count = ArrayList_Count(server->clients); @@ -401,7 +423,7 @@ static void (^mac_capture_stream_handler)(CGDisplayStreamFrameStatus, uint64_t, ArrayList_Lock(server->clients); count = ArrayList_Count(server->clients); EnterCriticalSection(&(surface->lock)); - shadow_subsystem_frame_update((rdpShadowSubsystem*)subsystem); + shadow_subsystem_frame_update(&subsystem->common); LeaveCriticalSection(&(surface->lock)); if (count == 1) @@ -411,7 +433,7 @@ static void (^mac_capture_stream_handler)(CGDisplayStreamFrameStatus, uint64_t, if (client) { - subsystem->captureFrameRate = shadow_encoder_preferred_fps(client->encoder); + subsystem->common.captureFrameRate = shadow_encoder_preferred_fps(client->encoder); } } @@ -477,7 +499,7 @@ static int mac_shadow_screen_grab(macShadowSubsystem* subsystem) static int mac_shadow_subsystem_process_message(macShadowSubsystem* subsystem, wMessage* message) { - rdpShadowServer* server = subsystem->server; + rdpShadowServer* server = subsystem->common.server; rdpShadowSurface* surface = server->surface; switch (message->id) @@ -511,11 +533,11 @@ static DWORD WINAPI mac_shadow_subsystem_thread(LPVOID arg) HANDLE events[32]; wMessage message; wMessagePipe* MsgPipe; - MsgPipe = subsystem->MsgPipe; + MsgPipe = subsystem->common.MsgPipe; nCount = 0; events[nCount++] = MessageQueue_Event(MsgPipe->In); - subsystem->captureFrameRate = 16; - dwInterval = 1000 / subsystem->captureFrameRate; + subsystem->common.captureFrameRate = 16; + dwInterval = 1000 / subsystem->common.captureFrameRate; frameTime = GetTickCount64() + dwInterval; while (1) @@ -538,7 +560,7 @@ static DWORD WINAPI mac_shadow_subsystem_thread(LPVOID arg) if ((status == WAIT_TIMEOUT) || (GetTickCount64() > frameTime)) { mac_shadow_screen_grab(subsystem); - dwInterval = 1000 / subsystem->captureFrameRate; + dwInterval = 1000 / subsystem->common.captureFrameRate; frameTime += dwInterval; } } @@ -636,15 +658,11 @@ static macShadowSubsystem* mac_shadow_subsystem_new(void) if (!subsystem) return NULL; - subsystem->SynchronizeEvent = (pfnShadowSynchronizeEvent) - mac_shadow_input_synchronize_event; - subsystem->KeyboardEvent = (pfnShadowKeyboardEvent) - mac_shadow_input_keyboard_event; - subsystem->UnicodeKeyboardEvent = (pfnShadowUnicodeKeyboardEvent) - mac_shadow_input_unicode_keyboard_event; - subsystem->MouseEvent = (pfnShadowMouseEvent) mac_shadow_input_mouse_event; - subsystem->ExtendedMouseEvent = (pfnShadowExtendedMouseEvent) - mac_shadow_input_extended_mouse_event; + subsystem->common.SynchronizeEvent = mac_shadow_input_synchronize_event; + subsystem->common.KeyboardEvent = mac_shadow_input_keyboard_event; + subsystem->common.UnicodeKeyboardEvent = mac_shadow_input_unicode_keyboard_event; + subsystem->common.MouseEvent = mac_shadow_input_mouse_event; + subsystem->common.ExtendedMouseEvent = mac_shadow_input_extended_mouse_event; return subsystem; } diff --git a/server/shadow/Mac/mac_shadow.h b/server/shadow/Mac/mac_shadow.h index dff555e17..e776afb80 100644 --- a/server/shadow/Mac/mac_shadow.h +++ b/server/shadow/Mac/mac_shadow.h @@ -37,7 +37,7 @@ typedef struct mac_shadow_subsystem macShadowSubsystem; struct mac_shadow_subsystem { - RDP_SHADOW_SUBSYSTEM_COMMON(); + rdpShadowSubsystem common; int width; int height; diff --git a/server/shadow/X11/x11_shadow.c b/server/shadow/X11/x11_shadow.c index d3a07f939..7245432c9 100644 --- a/server/shadow/X11/x11_shadow.c +++ b/server/shadow/X11/x11_shadow.c @@ -162,7 +162,7 @@ static int x11_shadow_pam_get_service_name(SHADOW_PAM_AUTH_INFO* info) return 1; } -static int x11_shadow_pam_authenticate(x11ShadowSubsystem* subsystem, +static int x11_shadow_pam_authenticate(rdpShadowSubsystem* subsystem, rdpShadowClient* client, const char* user, const char* domain, const char* password) { @@ -219,19 +219,24 @@ static int x11_shadow_pam_authenticate(x11ShadowSubsystem* subsystem, #endif -static void x11_shadow_input_synchronize_event(x11ShadowSubsystem* subsystem, +static BOOL x11_shadow_input_synchronize_event(rdpShadowSubsystem* subsystem, rdpShadowClient* client, UINT32 flags) { + return TRUE; } -static void x11_shadow_input_keyboard_event(x11ShadowSubsystem* subsystem, +static BOOL x11_shadow_input_keyboard_event(rdpShadowSubsystem* subsystem, rdpShadowClient* client, UINT16 flags, UINT16 code) { #ifdef WITH_XTEST + x11ShadowSubsystem* x11 = (x11ShadowSubsystem*)subsystem; DWORD vkcode; DWORD keycode; BOOL extended = FALSE; + if (!client || !subsystem) + return FALSE; + if (flags & KBD_FLAGS_EXTENDED) extended = TRUE; @@ -247,43 +252,58 @@ static void x11_shadow_input_keyboard_event(x11ShadowSubsystem* subsystem, if (keycode != 0) { - XLockDisplay(subsystem->display); - XTestGrabControl(subsystem->display, True); + XLockDisplay(x11->display); + XTestGrabControl(x11->display, True); if (flags & KBD_FLAGS_DOWN) - XTestFakeKeyEvent(subsystem->display, keycode, True, CurrentTime); + XTestFakeKeyEvent(x11->display, keycode, True, CurrentTime); else if (flags & KBD_FLAGS_RELEASE) - XTestFakeKeyEvent(subsystem->display, keycode, False, CurrentTime); + XTestFakeKeyEvent(x11->display, keycode, False, CurrentTime); - XTestGrabControl(subsystem->display, False); - XFlush(subsystem->display); - XUnlockDisplay(subsystem->display); + XTestGrabControl(x11->display, False); + XFlush(x11->display); + XUnlockDisplay(x11->display); } #endif + return TRUE; } -static void x11_shadow_input_unicode_keyboard_event(x11ShadowSubsystem* +static BOOL x11_shadow_input_unicode_keyboard_event(rdpShadowSubsystem* subsystem, rdpShadowClient* client, UINT16 flags, UINT16 code) { + return TRUE; } -static void x11_shadow_input_mouse_event(x11ShadowSubsystem* subsystem, +static BOOL x11_shadow_input_mouse_event(rdpShadowSubsystem* subsystem, rdpShadowClient* client, UINT16 flags, UINT16 x, UINT16 y) { #ifdef WITH_XTEST + x11ShadowSubsystem* x11 = (x11ShadowSubsystem*)subsystem; int button = 0; BOOL down = FALSE; rdpShadowServer* server; rdpShadowSurface* surface; + + if (!subsystem || !client) + return FALSE; + server = subsystem->server; + + if (!server) + return FALSE; + surface = server->surface; - subsystem->lastMouseClient = client; + + if (!surface) + return FALSE; + + x11->lastMouseClient = client; x += surface->x; y += surface->y; - XLockDisplay(subsystem->display); - XTestGrabControl(subsystem->display, True); + XLockDisplay(x11->display); + XTestGrabControl(x11->display, True); if (flags & PTR_FLAGS_WHEEL) { @@ -293,13 +313,13 @@ static void x11_shadow_input_mouse_event(x11ShadowSubsystem* subsystem, negative = TRUE; button = (negative) ? 5 : 4; - XTestFakeButtonEvent(subsystem->display, button, True, CurrentTime); - XTestFakeButtonEvent(subsystem->display, button, False, CurrentTime); + XTestFakeButtonEvent(x11->display, button, True, CurrentTime); + XTestFakeButtonEvent(x11->display, button, False, CurrentTime); } else { if (flags & PTR_FLAGS_MOVE) - XTestFakeMotionEvent(subsystem->display, 0, x, y, CurrentTime); + XTestFakeMotionEvent(x11->display, 0, x, y, CurrentTime); if (flags & PTR_FLAGS_BUTTON1) button = 1; @@ -312,31 +332,45 @@ static void x11_shadow_input_mouse_event(x11ShadowSubsystem* subsystem, down = TRUE; if (button) - XTestFakeButtonEvent(subsystem->display, button, down, CurrentTime); + XTestFakeButtonEvent(x11->display, button, down, CurrentTime); } - XTestGrabControl(subsystem->display, False); - XFlush(subsystem->display); - XUnlockDisplay(subsystem->display); + XTestGrabControl(x11->display, False); + XFlush(x11->display); + XUnlockDisplay(x11->display); #endif + return TRUE; } -static void x11_shadow_input_extended_mouse_event(x11ShadowSubsystem* subsystem, +static BOOL x11_shadow_input_extended_mouse_event(rdpShadowSubsystem* subsystem, rdpShadowClient* client, UINT16 flags, UINT16 x, UINT16 y) { #ifdef WITH_XTEST + x11ShadowSubsystem* x11 = (x11ShadowSubsystem*)subsystem; int button = 0; BOOL down = FALSE; rdpShadowServer* server; rdpShadowSurface* surface; + + if (!subsystem || !client) + return FALSE; + server = subsystem->server; + + if (!server) + return FALSE; + surface = server->surface; - subsystem->lastMouseClient = client; + + if (!surface) + return FALSE; + + x11->lastMouseClient = client; x += surface->x; y += surface->y; - XLockDisplay(subsystem->display); - XTestGrabControl(subsystem->display, True); - XTestFakeMotionEvent(subsystem->display, 0, x, y, CurrentTime); + XLockDisplay(x11->display); + XTestGrabControl(x11->display, True); + XTestFakeMotionEvent(x11->display, 0, x, y, CurrentTime); if (flags & PTR_XFLAGS_BUTTON1) button = 8; @@ -347,12 +381,13 @@ static void x11_shadow_input_extended_mouse_event(x11ShadowSubsystem* subsystem, down = TRUE; if (button) - XTestFakeButtonEvent(subsystem->display, button, down, CurrentTime); + XTestFakeButtonEvent(x11->display, button, down, CurrentTime); - XTestGrabControl(subsystem->display, False); - XFlush(subsystem->display); - XUnlockDisplay(subsystem->display); + XTestGrabControl(x11->display, False); + XFlush(x11->display); + XUnlockDisplay(x11->display); #endif + return TRUE; } static void x11_shadow_message_free(UINT32 id, SHADOW_MSG_OUT* msg) @@ -384,13 +419,13 @@ static int x11_shadow_pointer_position_update(x11ShadowSubsystem* subsystem) int count = 0; int index = 0; - if (!subsystem || !subsystem->server || !subsystem->server->clients) + if (!subsystem || !subsystem->common.server || !subsystem->common.server->clients) return -1; - templateMsg.xPos = subsystem->pointerX; - templateMsg.yPos = subsystem->pointerY; - templateMsg.Free = x11_shadow_message_free; - server = subsystem->server; + templateMsg.xPos = subsystem->common.pointerX; + templateMsg.yPos = subsystem->common.pointerY; + templateMsg.common.Free = x11_shadow_message_free; + server = subsystem->common.server; ArrayList_Lock(server->clients); for (index = 0; index < ArrayList_Count(server->clients); index++) @@ -443,8 +478,8 @@ static int x11_shadow_pointer_alpha_update(x11ShadowSubsystem* subsystem) return -1; } - msg->Free = x11_shadow_message_free; - return shadow_client_boardcast_msg(subsystem->server, NULL, msgId, + msg->common.Free = x11_shadow_message_free; + return shadow_client_boardcast_msg(subsystem->common.server, NULL, msgId, (SHADOW_MSG_OUT*) msg, NULL) ? 1 : -1; } @@ -453,7 +488,7 @@ static int x11_shadow_query_cursor(x11ShadowSubsystem* subsystem, BOOL getImage) int x = 0, y = 0, n, k; rdpShadowServer* server; rdpShadowSurface* surface; - server = subsystem->server; + server = subsystem->common.server; surface = server->surface; if (getImage) @@ -522,10 +557,10 @@ static int x11_shadow_query_cursor(x11ShadowSubsystem* subsystem, BOOL getImage) y -= surface->y; } - if ((x != subsystem->pointerX) || (y != subsystem->pointerY)) + if ((x != subsystem->common.pointerX) || (y != subsystem->common.pointerY)) { - subsystem->pointerX = x; - subsystem->pointerY = y; + subsystem->common.pointerX = x; + subsystem->common.pointerY = y; x11_shadow_pointer_position_update(subsystem); } @@ -594,13 +629,13 @@ static int x11_shadow_blend_cursor(x11ShadowSubsystem* subsystem) if (!subsystem) return -1; - surface = subsystem->server->surface; + surface = subsystem->common.server->surface; nXSrc = 0; nYSrc = 0; nWidth = subsystem->cursorWidth; nHeight = subsystem->cursorHeight; - nXDst = subsystem->pointerX - subsystem->cursorHotX; - nYDst = subsystem->pointerY - subsystem->cursorHotY; + nXDst = subsystem->common.pointerX - subsystem->cursorHotX; + nYDst = subsystem->common.pointerY - subsystem->cursorHotY; if (nXDst >= surface->width) return 1; @@ -687,11 +722,11 @@ static BOOL x11_shadow_check_resize(x11ShadowSubsystem* subsystem) if (attr.width != subsystem->width || attr.height != subsystem->height) { /* Screen size changed. Refresh monitor definitions and trigger screen resize */ - subsystem->numMonitors = x11_shadow_enum_monitors(subsystem->monitors, 16); - shadow_screen_resize(subsystem->server->screen); + subsystem->common.numMonitors = x11_shadow_enum_monitors(subsystem->common.monitors, 16); + shadow_screen_resize(subsystem->common.server->screen); subsystem->width = attr.width; subsystem->height = attr.height; - virtualScreen = &(subsystem->virtualScreen); + virtualScreen = &(subsystem->common.virtualScreen); virtualScreen->left = 0; virtualScreen->top = 0; virtualScreen->right = subsystem->width; @@ -732,7 +767,7 @@ static int x11_shadow_screen_grab(x11ShadowSubsystem* subsystem) RECTANGLE_16 invalidRect; RECTANGLE_16 surfaceRect; const RECTANGLE_16* extents; - server = subsystem->server; + server = subsystem->common.server; surface = server->surface; count = ArrayList_Count(server->clients); @@ -815,7 +850,7 @@ static int x11_shadow_screen_grab(x11ShadowSubsystem* subsystem) client = (rdpShadowClient*) ArrayList_GetItem(server->clients, 0); if (client) - subsystem->captureFrameRate = shadow_encoder_preferred_fps(client->encoder); + subsystem->common.captureFrameRate = shadow_encoder_preferred_fps(client->encoder); } region16_clear(&(surface->invalidRegion)); @@ -870,12 +905,12 @@ static DWORD WINAPI x11_shadow_subsystem_thread(LPVOID arg) HANDLE events[32]; wMessage message; wMessagePipe* MsgPipe; - MsgPipe = subsystem->MsgPipe; + MsgPipe = subsystem->common.MsgPipe; nCount = 0; - events[nCount++] = subsystem->event; + events[nCount++] = subsystem->common.event; events[nCount++] = MessageQueue_Event(MsgPipe->In); - subsystem->captureFrameRate = 16; - dwInterval = 1000 / subsystem->captureFrameRate; + subsystem->common.captureFrameRate = 16; + dwInterval = 1000 / subsystem->common.captureFrameRate; frameTime = GetTickCount64() + dwInterval; while (1) @@ -895,7 +930,7 @@ static DWORD WINAPI x11_shadow_subsystem_thread(LPVOID arg) } } - if (WaitForSingleObject(subsystem->event, 0) == WAIT_OBJECT_0) + if (WaitForSingleObject(subsystem->common.event, 0) == WAIT_OBJECT_0) { XLockDisplay(subsystem->display); @@ -913,7 +948,7 @@ static DWORD WINAPI x11_shadow_subsystem_thread(LPVOID arg) x11_shadow_check_resize(subsystem); x11_shadow_screen_grab(subsystem); x11_shadow_query_cursor(subsystem, FALSE); - dwInterval = 1000 / subsystem->captureFrameRate; + dwInterval = 1000 / subsystem->common.captureFrameRate; frameTime += dwInterval; } } @@ -1198,7 +1233,7 @@ static int x11_shadow_subsystem_init(rdpShadowSubsystem* sub) if (!subsystem) return -1; - subsystem->numMonitors = x11_shadow_enum_monitors(subsystem->monitors, 16); + subsystem->common.numMonitors = x11_shadow_enum_monitors(subsystem->common.monitors, 16); x11_shadow_subsystem_base_init(subsystem); if ((subsystem->depth != 24) && (subsystem->depth != 32)) @@ -1304,11 +1339,11 @@ static int x11_shadow_subsystem_init(rdpShadowSubsystem* sub) subsystem->use_xdamage = FALSE; } - if (!(subsystem->event = CreateFileDescriptorEvent(NULL, FALSE, FALSE, - subsystem->xfds, WINPR_FD_READ))) + if (!(subsystem->common.event = CreateFileDescriptorEvent(NULL, FALSE, FALSE, + subsystem->xfds, WINPR_FD_READ))) return -1; - virtualScreen = &(subsystem->virtualScreen); + virtualScreen = &(subsystem->common.virtualScreen); virtualScreen->left = 0; virtualScreen->top = 0; virtualScreen->right = subsystem->width; @@ -1334,10 +1369,10 @@ static int x11_shadow_subsystem_uninit(rdpShadowSubsystem* sub) subsystem->display = NULL; } - if (subsystem->event) + if (subsystem->common.event) { - CloseHandle(subsystem->event); - subsystem->event = NULL; + CloseHandle(subsystem->common.event); + subsystem->common.event = NULL; } if (subsystem->cursorPixels) @@ -1375,7 +1410,7 @@ static int x11_shadow_subsystem_stop(rdpShadowSubsystem* sub) if (subsystem->thread) { - if (MessageQueue_PostQuit(subsystem->MsgPipe->In, 0)) + if (MessageQueue_PostQuit(subsystem->common.MsgPipe->In, 0)) WaitForSingleObject(subsystem->thread, INFINITE); CloseHandle(subsystem->thread); @@ -1394,17 +1429,13 @@ static rdpShadowSubsystem* x11_shadow_subsystem_new(void) return NULL; #ifdef WITH_PAM - subsystem->Authenticate = (pfnShadowAuthenticate) x11_shadow_pam_authenticate; + subsystem->common.Authenticate = x11_shadow_pam_authenticate; #endif - subsystem->SynchronizeEvent = (pfnShadowSynchronizeEvent) - x11_shadow_input_synchronize_event; - subsystem->KeyboardEvent = (pfnShadowKeyboardEvent) - x11_shadow_input_keyboard_event; - subsystem->UnicodeKeyboardEvent = (pfnShadowUnicodeKeyboardEvent) - x11_shadow_input_unicode_keyboard_event; - subsystem->MouseEvent = (pfnShadowMouseEvent) x11_shadow_input_mouse_event; - subsystem->ExtendedMouseEvent = (pfnShadowExtendedMouseEvent) - x11_shadow_input_extended_mouse_event; + subsystem->common.SynchronizeEvent = x11_shadow_input_synchronize_event; + subsystem->common.KeyboardEvent = x11_shadow_input_keyboard_event; + subsystem->common.UnicodeKeyboardEvent = x11_shadow_input_unicode_keyboard_event; + subsystem->common.MouseEvent = x11_shadow_input_mouse_event; + subsystem->common.ExtendedMouseEvent = x11_shadow_input_extended_mouse_event; subsystem->composite = FALSE; subsystem->use_xshm = FALSE; /* temporarily disabled */ subsystem->use_xfixes = TRUE; diff --git a/server/shadow/X11/x11_shadow.h b/server/shadow/X11/x11_shadow.h index e6e361e37..12629f47a 100644 --- a/server/shadow/X11/x11_shadow.h +++ b/server/shadow/X11/x11_shadow.h @@ -53,7 +53,7 @@ typedef struct x11_shadow_subsystem x11ShadowSubsystem; struct x11_shadow_subsystem { - RDP_SHADOW_SUBSYSTEM_COMMON(); + rdpShadowSubsystem common; HANDLE thread; diff --git a/server/shadow/shadow_audin.c b/server/shadow/shadow_audin.c index 6e0959b4e..469debe3e 100644 --- a/server/shadow/shadow_audin.c +++ b/server/shadow/shadow_audin.c @@ -21,19 +21,14 @@ #endif #include +#include #include "shadow.h" #include "shadow_audin.h" +#include #define TAG SERVER_TAG("shadow") -/* Default supported audio formats */ -static const AUDIO_FORMAT default_supported_audio_formats[] = -{ - { WAVE_FORMAT_PCM, 2, 44100, 176400, 4, 16, 0, NULL }, - { WAVE_FORMAT_ALAW, 2, 22050, 44100, 2, 8, 0, NULL } -}; - /** * Function description * @@ -42,17 +37,15 @@ static const AUDIO_FORMAT default_supported_audio_formats[] = static UINT AudinServerOpening(audin_server_context* context) { AUDIO_FORMAT* agreed_format = NULL; - int i = 0, j = 0; + size_t i = 0, j = 0; for (i = 0; i < context->num_client_formats; i++) { for (j = 0; j < context->num_server_formats; j++) { - if ((context->client_formats[i].wFormatTag == context->server_formats[j].wFormatTag) && - (context->client_formats[i].nChannels == context->server_formats[j].nChannels) && - (context->client_formats[i].nSamplesPerSec == context->server_formats[j].nSamplesPerSec)) + if (audio_format_compatible(&context->server_formats[j], &context->client_formats[i])) { - agreed_format = (AUDIO_FORMAT*) &context->server_formats[j]; + agreed_format = &context->server_formats[j]; break; } } @@ -67,8 +60,7 @@ static UINT AudinServerOpening(audin_server_context* context) return CHANNEL_RC_OK; } - context->SelectFormat(context, i); - return CHANNEL_RC_OK; + return IFCALLRESULT(ERROR_CALL_NOT_IMPLEMENTED, context->SelectFormat, context, i); } /** * Function description @@ -85,7 +77,8 @@ static UINT AudinServerOpenResult(audin_server_context* context, UINT32 result) * * @return 0 on success, otherwise a Win32 error code */ -static UINT AudinServerReceiveSamples(audin_server_context* context, const void* buf, int nframes) +static UINT AudinServerReceiveSamples(audin_server_context* context, const AUDIO_FORMAT* format, + wStream* buf, size_t nframes) { rdpShadowClient* client = (rdpShadowClient*)context->data; rdpShadowSubsystem* subsystem = client->server->subsystem; @@ -93,42 +86,56 @@ static UINT AudinServerReceiveSamples(audin_server_context* context, const void* if (!client->mayInteract) return CHANNEL_RC_OK; - if (subsystem->AudinServerReceiveSamples) - subsystem->AudinServerReceiveSamples(subsystem, client, buf, nframes); + if (!IFCALLRESULT(TRUE, subsystem->AudinServerReceiveSamples, subsystem, client, format, buf, + nframes)) + return ERROR_INTERNAL_ERROR; return CHANNEL_RC_OK; } -int shadow_client_audin_init(rdpShadowClient* client) +BOOL shadow_client_audin_init(rdpShadowClient* client) { audin_server_context* audin; audin = client->audin = audin_server_context_new(client->vcm); if (!audin) - { - return 0; - } + return FALSE; audin->data = client; if (client->subsystem->audinFormats) { - audin->server_formats = client->subsystem->audinFormats; + size_t x; + audin->server_formats = audio_formats_new(client->subsystem->nAudinFormats); + + if (!audin->server_formats) + goto fail; + + for (x = 0; x < client->subsystem->nAudinFormats; x++) + { + if (!audio_format_copy(&client->subsystem->audinFormats[x], &audin->server_formats[x])) + goto fail; + } + audin->num_server_formats = client->subsystem->nAudinFormats; } else { - /* Set default audio formats. */ - audin->server_formats = default_supported_audio_formats; - audin->num_server_formats = sizeof(default_supported_audio_formats) / sizeof( - default_supported_audio_formats[0]); + audin->num_server_formats = server_audin_get_formats(&audin->server_formats); } - audin->dst_format = audin->server_formats[0]; + if (audin->num_server_formats < 1) + goto fail; + + audin->dst_format = &audin->server_formats[0]; audin->Opening = AudinServerOpening; audin->OpenResult = AudinServerOpenResult; audin->ReceiveSamples = AudinServerReceiveSamples; - return 1; + return TRUE; +fail: + audin_server_context_free(audin); + client->audin = NULL; + return FALSE; } void shadow_client_audin_uninit(rdpShadowClient* client) diff --git a/server/shadow/shadow_audin.h b/server/shadow/shadow_audin.h index 5bc6252a7..6fe0d8528 100644 --- a/server/shadow/shadow_audin.h +++ b/server/shadow/shadow_audin.h @@ -28,7 +28,7 @@ extern "C" { #endif -int shadow_client_audin_init(rdpShadowClient* client); +BOOL shadow_client_audin_init(rdpShadowClient* client); void shadow_client_audin_uninit(rdpShadowClient* client); #ifdef __cplusplus diff --git a/server/shadow/shadow_input.c b/server/shadow/shadow_input.c index 7f97b2911..229ef1483 100644 --- a/server/shadow/shadow_input.c +++ b/server/shadow/shadow_input.c @@ -22,7 +22,7 @@ #include "shadow.h" -BOOL shadow_input_synchronize_event(rdpInput* input, UINT32 flags) +static BOOL shadow_input_synchronize_event(rdpInput* input, UINT32 flags) { rdpShadowClient* client = (rdpShadowClient*) input->context; rdpShadowSubsystem* subsystem = client->server->subsystem; @@ -30,29 +30,10 @@ BOOL shadow_input_synchronize_event(rdpInput* input, UINT32 flags) if (!client->mayInteract) return TRUE; - if (subsystem->SynchronizeEvent) - { - subsystem->SynchronizeEvent(subsystem, client, flags); - } - return TRUE; + return IFCALLRESULT(TRUE, subsystem->SynchronizeEvent, subsystem, client, flags); } -BOOL shadow_input_keyboard_event(rdpInput* input, UINT16 flags, UINT16 code) -{ - rdpShadowClient* client = (rdpShadowClient*) input->context; - rdpShadowSubsystem* subsystem = client->server->subsystem; - - if (!client->mayInteract) - return TRUE; - - if (subsystem->KeyboardEvent) - { - subsystem->KeyboardEvent(subsystem, client, flags, code); - } - return TRUE; -} - -BOOL shadow_input_unicode_keyboard_event(rdpInput* input, UINT16 flags, UINT16 code) +static BOOL shadow_input_keyboard_event(rdpInput* input, UINT16 flags, UINT16 code) { rdpShadowClient* client = (rdpShadowClient*) input->context; rdpShadowSubsystem* subsystem = client->server->subsystem; @@ -60,14 +41,21 @@ BOOL shadow_input_unicode_keyboard_event(rdpInput* input, UINT16 flags, UINT16 c if (!client->mayInteract) return TRUE; - if (subsystem->UnicodeKeyboardEvent) - { - subsystem->UnicodeKeyboardEvent(subsystem, client, flags, code); - } - return TRUE; + return IFCALLRESULT(TRUE, subsystem->KeyboardEvent, subsystem, client, flags, code); } -BOOL shadow_input_mouse_event(rdpInput* input, UINT16 flags, UINT16 x, UINT16 y) +static BOOL shadow_input_unicode_keyboard_event(rdpInput* input, UINT16 flags, UINT16 code) +{ + rdpShadowClient* client = (rdpShadowClient*) input->context; + rdpShadowSubsystem* subsystem = client->server->subsystem; + + if (!client->mayInteract) + return TRUE; + + return IFCALLRESULT(TRUE, subsystem->UnicodeKeyboardEvent, subsystem, client, flags, code); +} + +static BOOL shadow_input_mouse_event(rdpInput* input, UINT16 flags, UINT16 x, UINT16 y) { rdpShadowClient* client = (rdpShadowClient*) input->context; rdpShadowSubsystem* subsystem = client->server->subsystem; @@ -84,7 +72,7 @@ BOOL shadow_input_mouse_event(rdpInput* input, UINT16 flags, UINT16 x, UINT16 y) client->pointerY = y; if ((client->pointerX == subsystem->pointerX) && - (client->pointerY == subsystem->pointerY)) + (client->pointerY == subsystem->pointerY)) { flags &= ~PTR_FLAGS_MOVE; @@ -96,14 +84,10 @@ BOOL shadow_input_mouse_event(rdpInput* input, UINT16 flags, UINT16 x, UINT16 y) if (!client->mayInteract) return TRUE; - if (subsystem->MouseEvent) - { - subsystem->MouseEvent(subsystem, client, flags, x, y); - } - return TRUE; + return IFCALLRESULT(TRUE, subsystem->MouseEvent, subsystem, client, flags, x, y); } -BOOL shadow_input_extended_mouse_event(rdpInput* input, UINT16 flags, UINT16 x, UINT16 y) +static BOOL shadow_input_extended_mouse_event(rdpInput* input, UINT16 flags, UINT16 x, UINT16 y) { rdpShadowClient* client = (rdpShadowClient*) input->context; rdpShadowSubsystem* subsystem = client->server->subsystem; @@ -120,11 +104,7 @@ BOOL shadow_input_extended_mouse_event(rdpInput* input, UINT16 flags, UINT16 x, if (!client->mayInteract) return TRUE; - if (subsystem->ExtendedMouseEvent) - { - subsystem->ExtendedMouseEvent(subsystem, client, flags, x, y); - } - return TRUE; + return IFCALLRESULT(TRUE, subsystem->ExtendedMouseEvent, subsystem, client, flags, x, y); } void shadow_input_register_callbacks(rdpInput* input) diff --git a/server/shadow/shadow_rdpsnd.c b/server/shadow/shadow_rdpsnd.c index 21b693239..5983959fb 100644 --- a/server/shadow/shadow_rdpsnd.c +++ b/server/shadow/shadow_rdpsnd.c @@ -23,6 +23,7 @@ #include #include #include +#include #include "shadow.h" @@ -30,31 +31,18 @@ #define TAG SERVER_TAG("shadow") -/* Default supported audio formats */ -static const AUDIO_FORMAT default_supported_audio_formats[] = -{ - { WAVE_FORMAT_AAC_MS, 2, 44100, 176400, 4, 16, 0, NULL }, - { WAVE_FORMAT_MPEGLAYER3, 2, 44100, 176400, 4, 16, 0, NULL }, - { WAVE_FORMAT_GSM610, 2, 44100, 176400, 4, 16, 0, NULL }, - { WAVE_FORMAT_PCM, 2, 44100, 176400, 4, 16, 0, NULL }, - { WAVE_FORMAT_ALAW, 2, 22050, 44100, 2, 8, 0, NULL }, -}; -static AUDIO_FORMAT supported_audio_formats[ARRAYSIZE(default_supported_audio_formats)] = { 0 }; - static void rdpsnd_activated(RdpsndServerContext* context) { - AUDIO_FORMAT* agreed_format = NULL; + const AUDIO_FORMAT* agreed_format = NULL; UINT16 i = 0, j = 0; for (i = 0; i < context->num_client_formats; i++) { for (j = 0; j < context->num_server_formats; j++) { - if ((context->client_formats[i].wFormatTag == context->server_formats[j].wFormatTag) && - (context->client_formats[i].nChannels == context->server_formats[j].nChannels) && - (context->client_formats[i].nSamplesPerSec == context->server_formats[j].nSamplesPerSec)) + if (audio_format_compatible(&context->server_formats[j], &context->client_formats[i])) { - agreed_format = (AUDIO_FORMAT*) &context->server_formats[j]; + agreed_format = &context->server_formats[j]; break; } } @@ -91,22 +79,12 @@ int shadow_client_rdpsnd_init(rdpShadowClient* client) } else { - size_t x, y = 0; - - for (x = 0; x < ARRAYSIZE(default_supported_audio_formats); x++) - { - const AUDIO_FORMAT* format = &default_supported_audio_formats[x]; - - if (freerdp_dsp_supports_format(format, TRUE)) - supported_audio_formats[y++] = *format; - } - - /* Set default audio formats. */ - rdpsnd->server_formats = supported_audio_formats; - rdpsnd->num_server_formats = y; + rdpsnd->num_server_formats = server_rdpsnd_get_formats(&rdpsnd->server_formats); } - rdpsnd->src_format = rdpsnd->server_formats[0]; + if (rdpsnd->num_server_formats > 0) + rdpsnd->src_format = &rdpsnd->server_formats[0]; + rdpsnd->Activated = rdpsnd_activated; rdpsnd->Initialize(rdpsnd, TRUE); return 1;