mirror of
https://github.com/morgan9e/FreeRDP
synced 2026-04-15 00:44:19 +09:00
Merge pull request #4889 from akallabeth/shadow_server_audin_refactor
Shadow server audin refactor
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -20,6 +20,8 @@
|
||||
#ifndef FREERDP_CODEC_AUDIO_H
|
||||
#define FREERDP_CODEC_AUDIO_H
|
||||
|
||||
#include <winpr/wlog.h>
|
||||
|
||||
#include <freerdp/api.h>
|
||||
#include <freerdp/types.h>
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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. ***/
|
||||
/**
|
||||
|
||||
@@ -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;
|
||||
|
||||
31
include/freerdp/server/server-common.h
Normal file
31
include/freerdp/server/server-common.h
Normal file
@@ -0,0 +1,31 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* FreeRDP Server Common
|
||||
*
|
||||
* Copyright 2018 Armin Novak <armin.novak@thincast.com>
|
||||
* 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 <winpr/wtypes.h>
|
||||
#include <freerdp/api.h>
|
||||
#include <freerdp/codec/audio.h>
|
||||
|
||||
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 */
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -27,15 +27,10 @@
|
||||
|
||||
#include "mf_audin.h"
|
||||
|
||||
#include <freerdp/server/server-common.h>
|
||||
#include <freerdp/log.h>
|
||||
#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;
|
||||
|
||||
@@ -29,17 +29,12 @@
|
||||
#include "mf_rdpsnd.h"
|
||||
|
||||
#include <winpr/sysinfo.h>
|
||||
#include <freerdp/server/server-common.h>
|
||||
#include <freerdp/log.h>
|
||||
#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;
|
||||
|
||||
@@ -32,12 +32,6 @@
|
||||
#include <freerdp/log.h>
|
||||
#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;
|
||||
|
||||
@@ -28,15 +28,10 @@
|
||||
|
||||
#include "sf_rdpsnd.h"
|
||||
|
||||
#include <freerdp/server/server-common.h>
|
||||
#include <freerdp/log.h>
|
||||
#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;
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <winpr/windows.h>
|
||||
#include <freerdp/server/server-common.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
|
||||
@@ -21,3 +21,154 @@
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <winpr/wtypes.h>
|
||||
#include <freerdp/codec/audio.h>
|
||||
#include <freerdp/codec/dsp.h>
|
||||
|
||||
#include <freerdp/server/server-common.h>
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ typedef struct mac_shadow_subsystem macShadowSubsystem;
|
||||
|
||||
struct mac_shadow_subsystem
|
||||
{
|
||||
RDP_SHADOW_SUBSYSTEM_COMMON();
|
||||
rdpShadowSubsystem common;
|
||||
|
||||
int width;
|
||||
int height;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -53,7 +53,7 @@ typedef struct x11_shadow_subsystem x11ShadowSubsystem;
|
||||
|
||||
struct x11_shadow_subsystem
|
||||
{
|
||||
RDP_SHADOW_SUBSYSTEM_COMMON();
|
||||
rdpShadowSubsystem common;
|
||||
|
||||
HANDLE thread;
|
||||
|
||||
|
||||
@@ -21,19 +21,14 @@
|
||||
#endif
|
||||
|
||||
#include <freerdp/log.h>
|
||||
#include <freerdp/codec/dsp.h>
|
||||
#include "shadow.h"
|
||||
|
||||
#include "shadow_audin.h"
|
||||
#include <freerdp/server/server-common.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 +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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include <winpr/crt.h>
|
||||
#include <freerdp/log.h>
|
||||
#include <freerdp/codec/dsp.h>
|
||||
#include <freerdp/server/server-common.h>
|
||||
|
||||
#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;
|
||||
|
||||
Reference in New Issue
Block a user