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;
/* Parsed plugin data */
UINT16 fixed_format;
UINT16 fixed_channel;
UINT32 fixed_rate;
AUDIO_FORMAT* fixed_format;
char* subsystem;
char* device_name;
@ -200,7 +198,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)
{
@ -230,17 +228,11 @@ static UINT audin_process_formats(AUDIN_PLUGIN* audin, AUDIN_CHANNEL_CALLBACK* c
goto out;
}
WLog_Print(audin->log, WLOG_DEBUG,
"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);
audio_format_print(audin->log, WLOG_DEBUG, &format);
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))
if (!audio_format_compatible(audin->fixed_format, &format))
{
rdpsnd_free_audio_format(&format);
audio_format_free(&format);
continue;
}
@ -259,7 +251,7 @@ static UINT audin_process_formats(AUDIN_PLUGIN* audin, AUDIN_CHANNEL_CALLBACK* c
}
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)
{
size_t x;
AUDIN_CHANNEL_CALLBACK* callback = (AUDIN_CHANNEL_CALLBACK*) pChannelCallback;
AUDIN_PLUGIN* audin = (AUDIN_PLUGIN*) callback->plugin;
UINT error = CHANNEL_RC_OK;
@ -691,6 +682,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)
{
@ -891,7 +883,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")
{
@ -900,14 +892,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)
{
@ -980,6 +972,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;

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,
UINT32 length)
{
int i;
size_t i;
UINT success = CHANNEL_RC_OK;
if (length < 8)
@ -210,8 +210,7 @@ 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;
@ -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);
return ERROR_INVALID_DATA;
}
audio_format_print(WLog_Get(TAG), WLOG_DEBUG, format);
}
IFCALLRET(audin->context.Opening, success, &audin->context);

View File

@ -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;
@ -146,9 +144,7 @@ static void rdpsnd_select_supported_audio_formats(rdpsndPlugin* rdpsnd)
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,16 +153,7 @@ 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) ||
@ -265,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;
@ -765,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")
{
@ -774,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")
{
@ -783,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")
{
@ -1211,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);
@ -1306,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));

View File

@ -172,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)
{

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 void audio_format_print(const AUDIO_FORMAT* format);
FREERDP_API void audio_formats_print(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 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* 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_formats_free(AUDIO_FORMAT* formats, size_t count);

View File

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

View File

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

View File

@ -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,
@ -203,9 +203,9 @@ struct _RDP_SHADOW_ENTRY_POINTS
UINT32 pointerY; \
\
const AUDIO_FORMAT* rdpsndFormats; \
int nRdpsndFormats; \
size_t nRdpsndFormats; \
const AUDIO_FORMAT* audinFormats; \
int nAudinFormats; \
size_t nAudinFormats; \
\
pfnShadowSynchronizeEvent SynchronizeEvent; \
pfnShadowKeyboardEvent KeyboardEvent; \
@ -253,7 +253,7 @@ struct _SHADOW_MSG_OUT_POINTER_POSITION_UPDATE
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
{
@ -268,7 +268,7 @@ 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
{
@ -279,7 +279,7 @@ struct _SHADOW_MSG_OUT_AUDIO_OUT_SAMPLES
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
{

View File

@ -112,32 +112,33 @@ char* audio_format_get_tag_string(UINT16 wFormatTag)
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" "
"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);
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 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;
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");
audio_format_print(format);
WLog_Print(log, level, "\t");
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;
}
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;
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;
if (formatA->nChannels != formatB->nChannels)
if (format->nChannels == 0)
return FALSE;
if (formatA->nSamplesPerSec != formatB->nSamplesPerSec)
if (format->nSamplesPerSec == 0)
return FALSE;
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)
free(format->data);
@ -249,7 +289,7 @@ void audio_formats_free(AUDIO_FORMAT* formats, size_t count)
for (index = 0; index < count; index++)
{
AUDIO_FORMAT* format = &formats[index];
rdpsnd_free_audio_format(format);
audio_format_free(format);
}
free(formats);

View File

@ -21,19 +21,13 @@
#endif
#include <freerdp/log.h>
#include <freerdp/codec/dsp.h>
#include "shadow.h"
#include "shadow_audin.h"
#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 +36,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;
}
}
@ -99,36 +91,137 @@ static UINT AudinServerReceiveSamples(audin_server_context* context, const void*
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
{
/* 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. */
audin->server_formats = default_supported_audio_formats;
audin->num_server_formats = sizeof(default_supported_audio_formats) / sizeof(
default_supported_audio_formats[0]);
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 = &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->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)

View File

@ -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

View File

@ -43,14 +43,14 @@ static AUDIO_FORMAT supported_audio_formats[ARRAYSIZE(default_supported_audio_fo
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 (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];
break;