Working mic redirection for shadow server.

This commit is contained in:
Armin Novak 2018-09-25 14:34:14 +02:00
parent 28efbbc01f
commit 106dde9571
12 changed files with 225 additions and 97 deletions

View File

@ -85,9 +85,7 @@ struct _AUDIN_PLUGIN
AUDIN_LISTENER_CALLBACK* listener_callback; AUDIN_LISTENER_CALLBACK* listener_callback;
/* Parsed plugin data */ /* Parsed plugin data */
UINT16 fixed_format; AUDIO_FORMAT* fixed_format;
UINT16 fixed_channel;
UINT32 fixed_rate;
char* subsystem; char* subsystem;
char* device_name; char* device_name;
@ -200,7 +198,7 @@ static UINT audin_process_formats(AUDIN_PLUGIN* audin, AUDIN_CHANNEL_CALLBACK* c
} }
Stream_Seek_UINT32(s); /* cbSizeFormatsPacket */ Stream_Seek_UINT32(s); /* cbSizeFormatsPacket */
callback->formats = (AUDIO_FORMAT*) calloc(NumFormats, sizeof(AUDIO_FORMAT)); callback->formats = audio_formats_new(NumFormats);
if (!callback->formats) if (!callback->formats)
{ {
@ -230,17 +228,11 @@ static UINT audin_process_formats(AUDIN_PLUGIN* audin, AUDIN_CHANNEL_CALLBACK* c
goto out; goto out;
} }
WLog_Print(audin->log, WLOG_DEBUG, audio_format_print(audin->log, WLOG_DEBUG, &format);
"wFormatTag=%s nChannels=%"PRIu16" nSamplesPerSec=%"PRIu32" "
"nBlockAlign=%"PRIu16" wBitsPerSample=%"PRIu16" cbSize=%"PRIu16"",
audio_format_get_tag_string(format.wFormatTag), format.nChannels, format.nSamplesPerSec,
format.nBlockAlign, format.wBitsPerSample, format.cbSize);
if ((audin->fixed_format > 0 && audin->fixed_format != format.wFormatTag) || if (!audio_format_compatible(audin->fixed_format, &format))
(audin->fixed_channel > 0 && audin->fixed_channel != format.nChannels) ||
(audin->fixed_rate > 0 && audin->fixed_rate != format.nSamplesPerSec))
{ {
rdpsnd_free_audio_format(&format); audio_format_free(&format);
continue; continue;
} }
@ -259,7 +251,7 @@ static UINT audin_process_formats(AUDIN_PLUGIN* audin, AUDIN_CHANNEL_CALLBACK* c
} }
else else
{ {
rdpsnd_free_audio_format(&format); audio_format_free(&format);
} }
} }
@ -591,7 +583,6 @@ static UINT audin_on_data_received(IWTSVirtualChannelCallback* pChannelCallback,
*/ */
static UINT audin_on_close(IWTSVirtualChannelCallback* pChannelCallback) static UINT audin_on_close(IWTSVirtualChannelCallback* pChannelCallback)
{ {
size_t x;
AUDIN_CHANNEL_CALLBACK* callback = (AUDIN_CHANNEL_CALLBACK*) pChannelCallback; AUDIN_CHANNEL_CALLBACK* callback = (AUDIN_CHANNEL_CALLBACK*) pChannelCallback;
AUDIN_PLUGIN* audin = (AUDIN_PLUGIN*) callback->plugin; AUDIN_PLUGIN* audin = (AUDIN_PLUGIN*) callback->plugin;
UINT error = CHANNEL_RC_OK; UINT error = CHANNEL_RC_OK;
@ -691,6 +682,7 @@ static UINT audin_plugin_terminated(IWTSPlugin* pPlugin)
return CHANNEL_RC_BAD_CHANNEL_HANDLE; return CHANNEL_RC_BAD_CHANNEL_HANDLE;
WLog_Print(audin->log, WLOG_TRACE, "..."); WLog_Print(audin->log, WLOG_TRACE, "...");
audio_format_free(audin->fixed_format);
if (audin->device) if (audin->device)
{ {
@ -891,7 +883,7 @@ BOOL audin_process_addin_args(AUDIN_PLUGIN* audin, ADDIN_ARGV* args)
if ((errno != 0) || (val > UINT16_MAX)) if ((errno != 0) || (val > UINT16_MAX))
return FALSE; return FALSE;
audin->fixed_format = val; audin->fixed_format->wFormatTag = val;
} }
CommandLineSwitchCase(arg, "rate") CommandLineSwitchCase(arg, "rate")
{ {
@ -900,14 +892,14 @@ BOOL audin_process_addin_args(AUDIN_PLUGIN* audin, ADDIN_ARGV* args)
if ((errno != 0) || (val < INT32_MIN) || (val > INT32_MAX)) if ((errno != 0) || (val < INT32_MIN) || (val > INT32_MAX))
return FALSE; return FALSE;
audin->fixed_rate = val; audin->fixed_format->nSamplesPerSec = val;
} }
CommandLineSwitchCase(arg, "channel") CommandLineSwitchCase(arg, "channel")
{ {
unsigned long val = strtoul(arg->Value, NULL, 0); unsigned long val = strtoul(arg->Value, NULL, 0);
if ((errno != 0) || (val > UINT16_MAX)) if ((errno != 0) || (val > UINT16_MAX))
audin->fixed_channel = val; audin->fixed_format->nChannels = val;
} }
CommandLineSwitchDefault(arg) CommandLineSwitchDefault(arg)
{ {
@ -980,6 +972,10 @@ UINT DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints)
audin->log = WLog_Get(TAG); audin->log = WLog_Get(TAG);
audin->data = Stream_New(NULL, 4096); audin->data = Stream_New(NULL, 4096);
audin->fixed_format = audio_format_new();
if (!audin->fixed_format)
goto out;
if (!audin->data) if (!audin->data)
goto out; goto out;

View File

@ -188,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, static UINT audin_server_recv_formats(audin_server* audin, wStream* s,
UINT32 length) UINT32 length)
{ {
int i; size_t i;
UINT success = CHANNEL_RC_OK; UINT success = CHANNEL_RC_OK;
if (length < 8) if (length < 8)
@ -210,8 +210,7 @@ static UINT audin_server_recv_formats(audin_server* audin, wStream* s,
return ERROR_INVALID_DATA; return ERROR_INVALID_DATA;
} }
audin->context.client_formats = calloc(audin->context.num_client_formats, audin->context.client_formats = audio_formats_new(audin->context.num_client_formats);
sizeof(AUDIO_FORMAT));
if (!audin->context.client_formats) if (!audin->context.client_formats)
return ERROR_NOT_ENOUGH_MEMORY; return ERROR_NOT_ENOUGH_MEMORY;
@ -227,6 +226,8 @@ static UINT audin_server_recv_formats(audin_server* audin, wStream* s,
WLog_ERR(TAG, "expected length at least 18, but got %"PRIu32"", length); WLog_ERR(TAG, "expected length at least 18, but got %"PRIu32"", length);
return ERROR_INVALID_DATA; return ERROR_INVALID_DATA;
} }
audio_format_print(WLog_Get(TAG), WLOG_DEBUG, format);
} }
IFCALLRET(audin->context.Opening, success, &audin->context); IFCALLRET(audin->context.Opening, success, &audin->context);

View File

@ -86,9 +86,7 @@ struct rdpsnd_plugin
UINT32 latency; UINT32 latency;
BOOL isOpen; BOOL isOpen;
UINT16 fixedFormat; AUDIO_FORMAT* fixed_format;
UINT16 fixedChannel;
UINT32 fixedRate;
char* subsystem; char* subsystem;
char* device_name; char* device_name;
@ -146,9 +144,7 @@ static void rdpsnd_select_supported_audio_formats(rdpsndPlugin* rdpsnd)
if (!rdpsnd->NumberOfServerFormats) if (!rdpsnd->NumberOfServerFormats)
return; return;
rdpsnd->ClientFormats = (AUDIO_FORMAT*) calloc( rdpsnd->ClientFormats = audio_formats_new(rdpsnd->NumberOfServerFormats);
rdpsnd->NumberOfServerFormats,
sizeof(AUDIO_FORMAT));
if (!rdpsnd->ClientFormats) if (!rdpsnd->ClientFormats)
return; return;
@ -157,16 +153,7 @@ static void rdpsnd_select_supported_audio_formats(rdpsndPlugin* rdpsnd)
{ {
const AUDIO_FORMAT* serverFormat = &rdpsnd->ServerFormats[index]; const AUDIO_FORMAT* serverFormat = &rdpsnd->ServerFormats[index];
if ((rdpsnd->fixedFormat > 0) && if (!audio_format_compatible(rdpsnd->fixed_format, serverFormat))
(rdpsnd->fixedFormat != serverFormat->wFormatTag))
continue;
if ((rdpsnd->fixedChannel > 0) &&
(rdpsnd->fixedChannel != serverFormat->nChannels))
continue;
if ((rdpsnd->fixedRate > 0) &&
(rdpsnd->fixedRate != serverFormat->nSamplesPerSec))
continue; continue;
if (freerdp_dsp_supports_format(serverFormat, FALSE) || if (freerdp_dsp_supports_format(serverFormat, FALSE) ||
@ -265,8 +252,7 @@ static UINT rdpsnd_recv_server_audio_formats_pdu(rdpsndPlugin* rdpsnd,
if (Stream_GetRemainingLength(s) / 14 < wNumberOfFormats) if (Stream_GetRemainingLength(s) / 14 < wNumberOfFormats)
return ERROR_BAD_LENGTH; return ERROR_BAD_LENGTH;
rdpsnd->ServerFormats = (AUDIO_FORMAT*) calloc(wNumberOfFormats, rdpsnd->ServerFormats = audio_formats_new(wNumberOfFormats);
sizeof(AUDIO_FORMAT));
if (!rdpsnd->ServerFormats) if (!rdpsnd->ServerFormats)
return CHANNEL_RC_NO_MEMORY; return CHANNEL_RC_NO_MEMORY;
@ -765,7 +751,7 @@ static UINT rdpsnd_process_addin_args(rdpsndPlugin* rdpsnd, ADDIN_ARGV* args)
if ((errno != 0) || (val > UINT16_MAX)) if ((errno != 0) || (val > UINT16_MAX))
return CHANNEL_RC_INITIALIZATION_ERROR; return CHANNEL_RC_INITIALIZATION_ERROR;
rdpsnd->fixedFormat = val; rdpsnd->fixed_format->wFormatTag = val;
} }
CommandLineSwitchCase(arg, "rate") CommandLineSwitchCase(arg, "rate")
{ {
@ -774,7 +760,7 @@ static UINT rdpsnd_process_addin_args(rdpsndPlugin* rdpsnd, ADDIN_ARGV* args)
if ((errno != 0) || (val > UINT32_MAX)) if ((errno != 0) || (val > UINT32_MAX))
return CHANNEL_RC_INITIALIZATION_ERROR; return CHANNEL_RC_INITIALIZATION_ERROR;
rdpsnd->fixedRate = val; rdpsnd->fixed_format->nSamplesPerSec = val;
} }
CommandLineSwitchCase(arg, "channel") CommandLineSwitchCase(arg, "channel")
{ {
@ -783,7 +769,7 @@ static UINT rdpsnd_process_addin_args(rdpsndPlugin* rdpsnd, ADDIN_ARGV* args)
if ((errno != 0) || (val > UINT16_MAX)) if ((errno != 0) || (val > UINT16_MAX))
return CHANNEL_RC_INITIALIZATION_ERROR; return CHANNEL_RC_INITIALIZATION_ERROR;
rdpsnd->fixedChannel = val; rdpsnd->fixed_format->nChannels = val;
} }
CommandLineSwitchCase(arg, "latency") CommandLineSwitchCase(arg, "latency")
{ {
@ -1211,6 +1197,7 @@ static void rdpsnd_virtual_channel_event_terminated(rdpsndPlugin* rdpsnd)
{ {
if (rdpsnd) if (rdpsnd)
{ {
audio_format_free(rdpsnd->fixed_format);
free(rdpsnd->subsystem); free(rdpsnd->subsystem);
free(rdpsnd->device_name); free(rdpsnd->device_name);
CloseHandle(rdpsnd->stopEvent); CloseHandle(rdpsnd->stopEvent);
@ -1306,6 +1293,14 @@ BOOL VCAPITYPE VirtualChannelEntryEx(PCHANNEL_ENTRY_POINTS pEntryPoints, PVOID p
rdpsnd->rdpcontext = pEntryPointsEx->context; 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"); rdpsnd->log = WLog_Get("com.freerdp.channels.rdpsnd.client");
CopyMemory(&(rdpsnd->channelEntryPoints), pEntryPoints, CopyMemory(&(rdpsnd->channelEntryPoints), pEntryPoints,
sizeof(CHANNEL_ENTRY_POINTS_FREERDP_EX)); sizeof(CHANNEL_ENTRY_POINTS_FREERDP_EX));

View File

@ -172,8 +172,7 @@ static UINT rdpsnd_server_recv_formats(RdpsndServerContext* context, wStream* s)
return ERROR_INTERNAL_ERROR; return ERROR_INTERNAL_ERROR;
} }
context->client_formats = (AUDIO_FORMAT*)calloc(context->num_client_formats, context->client_formats = audio_formats_new(context->num_client_formats);
sizeof(AUDIO_FORMAT));
if (!context->client_formats) if (!context->client_formats)
{ {

View File

@ -195,13 +195,17 @@ FREERDP_API UINT32 audio_format_compute_time_length(const AUDIO_FORMAT* format,
FREERDP_API char* audio_format_get_tag_string(UINT16 wFormatTag); FREERDP_API char* audio_format_get_tag_string(UINT16 wFormatTag);
FREERDP_API void audio_format_print(const AUDIO_FORMAT* format); FREERDP_API void audio_format_print(wLog* log, DWORD level, const AUDIO_FORMAT* format);
FREERDP_API void audio_formats_print(const AUDIO_FORMAT* formats, UINT16 count); FREERDP_API void audio_formats_print(wLog* log, DWORD level, const AUDIO_FORMAT* formats,
UINT16 count);
FREERDP_API BOOL audio_format_read(wStream* s, AUDIO_FORMAT* format); 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_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_copy(const AUDIO_FORMAT* srcFormat, AUDIO_FORMAT* dstFormat);
FREERDP_API BOOL audio_format_compatible(const AUDIO_FORMAT* formatA, const AUDIO_FORMAT* formatB); 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_format_free(AUDIO_FORMAT* format);
FREERDP_API void audio_formats_free(AUDIO_FORMAT* formats, size_t count); FREERDP_API void audio_formats_free(AUDIO_FORMAT* formats, size_t count);

View File

@ -58,7 +58,7 @@ struct _audin_server_context
/* Client supported formats. */ /* Client supported formats. */
AUDIO_FORMAT* client_formats; AUDIO_FORMAT* client_formats;
size_t num_client_formats; size_t num_client_formats;
size_t selected_client_format; SSIZE_T selected_client_format;
/*** APIs called by the server. ***/ /*** APIs called by the server. ***/
/** /**

View File

@ -58,7 +58,7 @@ struct _rdpsnd_server_context
/* Server supported formats. Set by server. */ /* Server supported formats. Set by server. */
const AUDIO_FORMAT* server_formats; const AUDIO_FORMAT* server_formats;
int num_server_formats; size_t num_server_formats;
/* Server source PCM audio format. Set by server. */ /* Server source PCM audio format. Set by server. */
AUDIO_FORMAT src_format; AUDIO_FORMAT src_format;

View File

@ -203,9 +203,9 @@ struct _RDP_SHADOW_ENTRY_POINTS
UINT32 pointerY; \ UINT32 pointerY; \
\ \
const AUDIO_FORMAT* rdpsndFormats; \ const AUDIO_FORMAT* rdpsndFormats; \
int nRdpsndFormats; \ size_t nRdpsndFormats; \
const AUDIO_FORMAT* audinFormats; \ const AUDIO_FORMAT* audinFormats; \
int nAudinFormats; \ size_t nAudinFormats; \
\ \
pfnShadowSynchronizeEvent SynchronizeEvent; \ pfnShadowSynchronizeEvent SynchronizeEvent; \
pfnShadowKeyboardEvent KeyboardEvent; \ pfnShadowKeyboardEvent KeyboardEvent; \

View File

@ -112,32 +112,33 @@ char* audio_format_get_tag_string(UINT16 wFormatTag)
return "WAVE_FORMAT_UNKNOWN"; return "WAVE_FORMAT_UNKNOWN";
} }
void audio_format_print(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" " WLog_Print(log, level,
"%s:\t wFormatTag: 0x%04"PRIX16" nChannels: %"PRIu16" nSamplesPerSec: %"PRIu32" "
"nAvgBytesPerSec: %"PRIu32" nBlockAlign: %"PRIu16" wBitsPerSample: %"PRIu16" cbSize: %"PRIu16"", "nAvgBytesPerSec: %"PRIu32" nBlockAlign: %"PRIu16" wBitsPerSample: %"PRIu16" cbSize: %"PRIu16"",
audio_format_get_tag_string(format->wFormatTag), format->wFormatTag, audio_format_get_tag_string(format->wFormatTag), format->wFormatTag,
format->nChannels, format->nSamplesPerSec, format->nAvgBytesPerSec, format->nChannels, format->nSamplesPerSec, format->nAvgBytesPerSec,
format->nBlockAlign, format->wBitsPerSample, format->cbSize); format->nBlockAlign, format->wBitsPerSample, format->cbSize);
} }
void audio_format_prints(const AUDIO_FORMAT* formats, UINT16 count) void audio_formats_print(wLog* log, DWORD level, const AUDIO_FORMAT* formats, UINT16 count)
{ {
UINT16 index; UINT16 index;
const AUDIO_FORMAT* format; const AUDIO_FORMAT* format;
if (formats) if (formats)
{ {
WLog_INFO(TAG, "AUDIO_FORMATS (%"PRIu16") ={", count); WLog_Print(log, level, "AUDIO_FORMATS (%"PRIu16") ={", count);
for (index = 0; index < count; index++) for (index = 0; index < count; index++)
{ {
format = &formats[index]; format = &formats[index];
WLog_ERR(TAG, "\t"); WLog_Print(log, level, "\t");
audio_format_print(format); audio_format_print(log, level, format);
} }
WLog_ERR(TAG, "}"); WLog_Print(log, level, "}");
} }
} }
@ -217,24 +218,63 @@ BOOL audio_format_copy(const AUDIO_FORMAT* srcFormat, AUDIO_FORMAT* dstFormat)
return TRUE; return TRUE;
} }
BOOL audio_format_compatible(const AUDIO_FORMAT* formatA, const AUDIO_FORMAT* formatB) BOOL audio_format_compatible(const AUDIO_FORMAT* with, const AUDIO_FORMAT* what)
{ {
if (!formatA || !formatB) if (!with || !what)
return FALSE; return FALSE;
if (formatA->wFormatTag != formatB->wFormatTag) 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; return FALSE;
if (formatA->nChannels != formatB->nChannels) if (format->nChannels == 0)
return FALSE; return FALSE;
if (formatA->nSamplesPerSec != formatB->nSamplesPerSec) if (format->nSamplesPerSec == 0)
return FALSE; return FALSE;
return TRUE; return TRUE;
} }
void rdpsnd_free_audio_format(AUDIO_FORMAT* format) 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) if (format)
free(format->data); free(format->data);
@ -249,7 +289,7 @@ void audio_formats_free(AUDIO_FORMAT* formats, size_t count)
for (index = 0; index < count; index++) for (index = 0; index < count; index++)
{ {
AUDIO_FORMAT* format = &formats[index]; AUDIO_FORMAT* format = &formats[index];
rdpsnd_free_audio_format(format); audio_format_free(format);
} }
free(formats); free(formats);

View File

@ -21,19 +21,13 @@
#endif #endif
#include <freerdp/log.h> #include <freerdp/log.h>
#include <freerdp/codec/dsp.h>
#include "shadow.h" #include "shadow.h"
#include "shadow_audin.h" #include "shadow_audin.h"
#define TAG SERVER_TAG("shadow") #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 * Function description
* *
@ -42,17 +36,15 @@ static const AUDIO_FORMAT default_supported_audio_formats[] =
static UINT AudinServerOpening(audin_server_context* context) static UINT AudinServerOpening(audin_server_context* context)
{ {
AUDIO_FORMAT* agreed_format = NULL; 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 (i = 0; i < context->num_client_formats; i++)
{ {
for (j = 0; j < context->num_server_formats; j++) for (j = 0; j < context->num_server_formats; j++)
{ {
if ((context->client_formats[i].wFormatTag == context->server_formats[j].wFormatTag) && if (audio_format_compatible(&context->server_formats[j], &context->client_formats[i]))
(context->client_formats[i].nChannels == context->server_formats[j].nChannels) &&
(context->client_formats[i].nSamplesPerSec == context->server_formats[j].nSamplesPerSec))
{ {
agreed_format = (AUDIO_FORMAT*) &context->server_formats[j]; agreed_format = &context->server_formats[j];
break; break;
} }
} }
@ -99,36 +91,137 @@ static UINT AudinServerReceiveSamples(audin_server_context* context, const void*
return CHANNEL_RC_OK; return CHANNEL_RC_OK;
} }
int shadow_client_audin_init(rdpShadowClient* client) BOOL shadow_client_audin_init(rdpShadowClient* client)
{ {
audin_server_context* audin; audin_server_context* audin;
audin = client->audin = audin_server_context_new(client->vcm); audin = client->audin = audin_server_context_new(client->vcm);
if (!audin) if (!audin)
{ return FALSE;
return 0;
}
audin->data = client; audin->data = client;
if (client->subsystem->audinFormats) 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; audin->num_server_formats = client->subsystem->nAudinFormats;
} }
else else
{ {
/* 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, 176400, 4, 16, 0, NULL },
{ WAVE_FORMAT_MSG723, 2, 22050, 176400, 4, 16, 0, NULL },
{ WAVE_FORMAT_MSG723, 1, 44100, 176400, 4, 16, 0, NULL },
{ WAVE_FORMAT_MSG723, 1, 22050, 176400, 4, 16, 0, NULL },
{ WAVE_FORMAT_PCM, 2, 44100, 176400, 4, 16, 0, NULL },
{ WAVE_FORMAT_PCM, 2, 22050, 176400, 4, 16, 0, NULL },
{ WAVE_FORMAT_PCM, 1, 44100, 176400, 4, 16, 0, NULL },
{ WAVE_FORMAT_PCM, 1, 22050, 176400, 4, 16, 0, NULL },
{ WAVE_FORMAT_MULAW, 2, 44100, 176400, 4, 16, 0, NULL },
{ WAVE_FORMAT_MULAW, 2, 22050, 176400, 4, 16, 0, NULL },
{ WAVE_FORMAT_MULAW, 1, 44100, 176400, 4, 16, 0, NULL },
{ WAVE_FORMAT_MULAW, 1, 22050, 176400, 4, 16, 0, NULL },
{ WAVE_FORMAT_ALAW, 2, 44100, 44100, 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, 44100, 2, 8, 0, NULL }
};
const size_t nrDefaultFormatsMax = ARRAYSIZE(default_supported_audio_formats);
size_t x;
audin->server_formats = audio_formats_new(nrDefaultFormatsMax);
if (!audin->server_formats)
goto fail;
/* Set default audio formats. */ /* Set default audio formats. */
audin->server_formats = default_supported_audio_formats; for (x = 0; x < nrDefaultFormatsMax; x++)
audin->num_server_formats = sizeof(default_supported_audio_formats) / sizeof( {
default_supported_audio_formats[0]); const AUDIO_FORMAT* format = &default_supported_audio_formats[x];
if (freerdp_dsp_supports_format(format, FALSE))
{
AUDIO_FORMAT* dst = &audin->server_formats[audin->num_server_formats++];
audio_format_copy(format, dst);
} }
}
}
if (audin->num_server_formats < 1)
goto fail;
audin->dst_format = audin->server_formats[0]; audin->dst_format = audin->server_formats[0];
audin->Opening = AudinServerOpening; audin->Opening = AudinServerOpening;
audin->OpenResult = AudinServerOpenResult; audin->OpenResult = AudinServerOpenResult;
audin->ReceiveSamples = AudinServerReceiveSamples; 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) void shadow_client_audin_uninit(rdpShadowClient* client)

View File

@ -28,7 +28,7 @@
extern "C" { extern "C" {
#endif #endif
int shadow_client_audin_init(rdpShadowClient* client); BOOL shadow_client_audin_init(rdpShadowClient* client);
void shadow_client_audin_uninit(rdpShadowClient* client); void shadow_client_audin_uninit(rdpShadowClient* client);
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -43,14 +43,14 @@ static AUDIO_FORMAT supported_audio_formats[ARRAYSIZE(default_supported_audio_fo
static void rdpsnd_activated(RdpsndServerContext* context) static void rdpsnd_activated(RdpsndServerContext* context)
{ {
AUDIO_FORMAT* agreed_format = NULL; const AUDIO_FORMAT* agreed_format = NULL;
UINT16 i = 0, j = 0; UINT16 i = 0, j = 0;
for (i = 0; i < context->num_client_formats; i++) for (i = 0; i < context->num_client_formats; i++)
{ {
for (j = 0; j < context->num_server_formats; j++) for (j = 0; j < context->num_server_formats; j++)
{ {
if (audio_format_compatible(&context->client_formats[i], &context->server_formats[j])) if (audio_format_compatible(&context->server_formats[j], &context->client_formats[i]))
{ {
agreed_format = &context->server_formats[j]; agreed_format = &context->server_formats[j];
break; break;