22#include <freerdp/config.h>
29#include <winpr/assert.h>
30#include <winpr/cast.h>
31#include <winpr/print.h>
32#include <winpr/stream.h>
34#include <freerdp/freerdp.h>
35#include <freerdp/channels/log.h>
37#include "rdpsnd_common.h"
38#include "rdpsnd_main.h"
40static wStream* rdpsnd_server_get_buffer(RdpsndServerContext* context)
43 WINPR_ASSERT(context);
44 WINPR_ASSERT(context->priv);
46 s = context->priv->rdpsnd_pdu;
47 Stream_ResetPosition(s);
56static UINT rdpsnd_server_send_formats(RdpsndServerContext* context)
58 wStream* s = rdpsnd_server_get_buffer(context);
62 if (!Stream_EnsureRemainingCapacity(s, 24))
63 return ERROR_OUTOFMEMORY;
65 Stream_Write_UINT8(s, SNDC_FORMATS);
66 Stream_Write_UINT8(s, 0);
67 Stream_Seek_UINT16(s);
68 Stream_Write_UINT32(s, 0);
69 Stream_Write_UINT32(s, 0);
70 Stream_Write_UINT32(s, 0);
71 Stream_Write_UINT16(s, 0);
73 s, WINPR_ASSERTING_INT_CAST(uint16_t, context->num_server_formats));
74 Stream_Write_UINT8(s, context->block_no);
75 Stream_Write_UINT16(s, CHANNEL_VERSION_WIN_MAX);
76 Stream_Write_UINT8(s, 0);
78 for (
size_t i = 0; i < context->num_server_formats; i++)
80 const AUDIO_FORMAT* format = &context->server_formats[i];
82 if (!audio_format_write(s, format))
87 const size_t pos = Stream_GetPosition(s);
91 WINPR_ASSERT(pos >= 4);
92 if (!Stream_SetPosition(s, 2))
94 Stream_Write_UINT16(s, (UINT16)(pos - 4));
95 if (!Stream_SetPosition(s, pos))
98 WINPR_ASSERT(context->priv);
100 status = WTSVirtualChannelWrite(context->priv->ChannelHandle, Stream_BufferAs(s,
char),
101 (UINT32)pos, &written);
102 Stream_ResetPosition(s);
105 return status ? CHANNEL_RC_OK : ERROR_INTERNAL_ERROR;
113static UINT rdpsnd_server_recv_waveconfirm(RdpsndServerContext* context,
wStream* s)
115 UINT16 timestamp = 0;
116 BYTE confirmBlockNum = 0;
117 UINT error = CHANNEL_RC_OK;
119 WINPR_ASSERT(context);
121 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
122 return ERROR_INVALID_DATA;
124 Stream_Read_UINT16(s, timestamp);
125 Stream_Read_UINT8(s, confirmBlockNum);
126 Stream_Seek_UINT8(s);
127 IFCALLRET(context->ConfirmBlock, error, context, confirmBlockNum, timestamp);
130 WLog_ERR(TAG,
"context->ConfirmBlock failed with error %" PRIu32
"", error);
140static UINT rdpsnd_server_recv_trainingconfirm(RdpsndServerContext* context,
wStream* s)
142 UINT16 timestamp = 0;
144 UINT error = CHANNEL_RC_OK;
146 WINPR_ASSERT(context);
148 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
149 return ERROR_INVALID_DATA;
151 Stream_Read_UINT16(s, timestamp);
152 Stream_Read_UINT16(s, packsize);
154 IFCALLRET(context->TrainingConfirm, error, context, timestamp, packsize);
156 WLog_ERR(TAG,
"context->TrainingConfirm failed with error %" PRIu32
"", error);
166static UINT rdpsnd_server_recv_quality_mode(RdpsndServerContext* context,
wStream* s)
168 WINPR_ASSERT(context);
170 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
172 WLog_ERR(TAG,
"not enough data in stream!");
173 return ERROR_INVALID_DATA;
176 Stream_Read_UINT16(s, context->qualityMode);
177 Stream_Seek_UINT16(s);
179 WLog_DBG(TAG,
"Client requested sound quality: 0x%04" PRIX16
"", context->qualityMode);
181 return CHANNEL_RC_OK;
184static void rdpsnd_server_client_format_free(RdpsndServerContext* context)
186 WINPR_ASSERT(context);
187 free(context->client_formats);
188 context->client_formats =
nullptr;
189 context->num_client_formats = 0;
197static UINT rdpsnd_server_recv_formats(RdpsndServerContext* context,
wStream* s)
199 UINT error = CHANNEL_RC_OK;
201 WINPR_ASSERT(context);
203 if (!Stream_CheckAndLogRequiredLength(TAG, s, 20))
204 return ERROR_INVALID_DATA;
206 Stream_Read_UINT32(s, context->capsFlags);
207 Stream_Read_UINT32(s, context->initialVolume);
208 Stream_Read_UINT32(s, context->initialPitch);
209 Stream_Read_UINT16(s, context->udpPort);
210 Stream_Read_UINT16(s, context->num_client_formats);
211 Stream_Read_UINT8(s, context->lastblock);
212 Stream_Read_UINT16(s, context->clientVersion);
213 Stream_Seek_UINT8(s);
216 if (!Stream_CheckAndLogRequiredLengthOfSize(TAG, s, context->num_client_formats, 18ull))
217 return ERROR_INVALID_DATA;
219 if (!context->num_client_formats)
221 WLog_ERR(TAG,
"client doesn't support any format!");
222 return ERROR_INTERNAL_ERROR;
225 context->client_formats = audio_formats_new(context->num_client_formats);
227 if (!context->client_formats)
229 WLog_ERR(TAG,
"calloc failed!");
230 return CHANNEL_RC_NO_MEMORY;
233 for (UINT16 i = 0; i < context->num_client_formats; i++)
237 if (!Stream_CheckAndLogRequiredLength(TAG, s, 18))
239 WLog_ERR(TAG,
"not enough data in stream!");
240 error = ERROR_INVALID_DATA;
244 Stream_Read_UINT16(s, format->wFormatTag);
245 Stream_Read_UINT16(s, format->nChannels);
246 Stream_Read_UINT32(s, format->nSamplesPerSec);
247 Stream_Read_UINT32(s, format->nAvgBytesPerSec);
248 Stream_Read_UINT16(s, format->nBlockAlign);
249 Stream_Read_UINT16(s, format->wBitsPerSample);
250 Stream_Read_UINT16(s, format->cbSize);
257 if ((format->nChannels == 0) || (format->nBlockAlign == 0))
259 WLog_ERR(TAG,
"invalid client audio format: nChannels or nBlockAlign is 0");
260 error = ERROR_INVALID_DATA;
265 switch (format->wFormatTag)
267 case WAVE_FORMAT_DVI_ADPCM:
268 if (format->nBlockAlign < 4)
271 "invalid client audio format %s: nBlockAlign is %" PRIu32
273 audio_format_get_tag_string(format->wFormatTag), format->nBlockAlign);
274 error = ERROR_INVALID_DATA;
278 case WAVE_FORMAT_ADPCM:
279 if (format->nBlockAlign < 8)
282 "invalid client audio format %s: nBlockAlign is %" PRIu32
284 audio_format_get_tag_string(format->wFormatTag), format->nBlockAlign);
285 error = ERROR_INVALID_DATA;
293 if (format->cbSize > 0)
295 if (!Stream_SafeSeek(s, format->cbSize))
297 WLog_ERR(TAG,
"Stream_SafeSeek failed!");
298 error = ERROR_INTERNAL_ERROR;
304 if (!context->num_client_formats)
306 WLog_ERR(TAG,
"client doesn't support any known format!");
310 return CHANNEL_RC_OK;
312 rdpsnd_server_client_format_free(context);
316static DWORD WINAPI rdpsnd_server_thread(LPVOID arg)
320 HANDLE events[2] = WINPR_C_ARRAY_INIT;
321 RdpsndServerContext* context = (RdpsndServerContext*)arg;
322 UINT error = CHANNEL_RC_OK;
324 WINPR_ASSERT(context);
325 WINPR_ASSERT(context->priv);
327 events[nCount++] = context->priv->channelEvent;
328 events[nCount++] = context->priv->StopEvent;
330 WINPR_ASSERT(nCount <= ARRAYSIZE(events));
334 status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE);
336 if (status == WAIT_FAILED)
338 error = GetLastError();
339 WLog_ERR(TAG,
"WaitForMultipleObjects failed with error %" PRIu32
"!", error);
343 status = WaitForSingleObject(context->priv->StopEvent, 0);
345 if (status == WAIT_FAILED)
347 error = GetLastError();
348 WLog_ERR(TAG,
"WaitForSingleObject failed with error %" PRIu32
"!", error);
352 if (status == WAIT_OBJECT_0)
355 if ((error = rdpsnd_server_handle_messages(context)))
357 WLog_ERR(TAG,
"rdpsnd_server_handle_messages failed with error %" PRIu32
"", error);
362 if (error && context->rdpcontext)
363 setChannelError(context->rdpcontext, error,
"rdpsnd_server_thread reported an error");
374static UINT rdpsnd_server_initialize(RdpsndServerContext* context, BOOL ownThread)
376 WINPR_ASSERT(context);
377 WINPR_ASSERT(context->priv);
379 context->priv->ownThread = ownThread;
380 return context->Start(context);
388static UINT rdpsnd_server_select_format(RdpsndServerContext* context, UINT16 client_format_index)
390 size_t out_buffer_size = 0;
392 UINT error = CHANNEL_RC_OK;
394 WINPR_ASSERT(context);
395 WINPR_ASSERT(context->priv);
397 if ((client_format_index >= context->num_client_formats) || (!context->src_format))
399 WLog_ERR(TAG,
"index %" PRIu16
" is not correct.", client_format_index);
400 return ERROR_INVALID_DATA;
403 EnterCriticalSection(&context->priv->lock);
404 context->priv->src_bytes_per_sample = context->src_format->wBitsPerSample / 8;
405 context->priv->src_bytes_per_frame =
406 context->priv->src_bytes_per_sample * context->src_format->nChannels;
407 context->selected_client_format = client_format_index;
408 format = &context->client_formats[client_format_index];
410 if (format->nSamplesPerSec == 0)
412 WLog_ERR(TAG,
"invalid Client Sound Format!!");
413 error = ERROR_INVALID_DATA;
417 if (context->latency <= 0)
418 context->latency = 50;
420 context->priv->out_frames = context->src_format->nSamplesPerSec * context->latency / 1000;
422 if (context->priv->out_frames < 1)
423 context->priv->out_frames = 1;
425 switch (format->wFormatTag)
427 case WAVE_FORMAT_DVI_ADPCM:
429 WINPR_ASSERT(format->nBlockAlign >= 4);
430 WINPR_ASSERT(format->nChannels > 0);
431 const UINT64 bs = 4ULL * (format->nBlockAlign - 4ULL * format->nChannels);
432 WINPR_ASSERT(bs > 0);
434 context->priv->out_frames -= context->priv->out_frames % bs;
436 if (context->priv->out_frames < bs)
437 context->priv->out_frames = bs;
441 case WAVE_FORMAT_ADPCM:
443 WINPR_ASSERT(format->nBlockAlign >= 8);
444 WINPR_ASSERT(format->nChannels > 0);
447 (format->nBlockAlign - 7 * format->nChannels) * 2 / format->nChannels + 2;
448 WINPR_ASSERT(bs > 0);
449 context->priv->out_frames -= context->priv->out_frames % bs;
451 if (context->priv->out_frames < bs)
452 context->priv->out_frames = bs;
459 context->priv->out_pending_frames = 0;
460 out_buffer_size = context->priv->out_frames * context->priv->src_bytes_per_frame;
462 if (context->priv->out_buffer_size < out_buffer_size)
464 BYTE* newBuffer =
nullptr;
465 newBuffer = (BYTE*)realloc(context->priv->out_buffer, out_buffer_size);
469 WLog_ERR(TAG,
"realloc failed!");
470 error = CHANNEL_RC_NO_MEMORY;
474 context->priv->out_buffer = newBuffer;
475 context->priv->out_buffer_size = out_buffer_size;
478 if (!freerdp_dsp_context_reset(context->priv->dsp_context, format, 0u))
479 error = ERROR_INTERNAL_ERROR;
481 LeaveCriticalSection(&context->priv->lock);
490static UINT rdpsnd_server_training(RdpsndServerContext* context, UINT16 timestamp, UINT16 packsize,
495 wStream* s = rdpsnd_server_get_buffer(context);
497 if (!Stream_EnsureRemainingCapacity(s, 8))
498 return ERROR_INTERNAL_ERROR;
500 Stream_Write_UINT8(s, SNDC_TRAINING);
501 Stream_Write_UINT8(s, 0);
502 Stream_Seek_UINT16(s);
503 Stream_Write_UINT16(s, timestamp);
504 Stream_Write_UINT16(s, packsize);
508 if (!Stream_EnsureRemainingCapacity(s, packsize))
510 Stream_ResetPosition(s);
511 return ERROR_INTERNAL_ERROR;
514 Stream_Write(s, data, packsize);
517 const size_t end = Stream_GetPosition(s);
518 if ((end < 4) || (end > UINT16_MAX))
519 return ERROR_INTERNAL_ERROR;
521 if (!Stream_SetPosition(s, 2))
522 return ERROR_INTERNAL_ERROR;
523 Stream_Write_UINT16(s, (UINT16)(end - 4));
525 status = WTSVirtualChannelWrite(context->priv->ChannelHandle, Stream_BufferAs(s,
char),
526 (UINT32)end, &written);
528 Stream_ResetPosition(s);
530 return status ? CHANNEL_RC_OK : ERROR_INTERNAL_ERROR;
533static BOOL rdpsnd_server_align_wave_pdu(
wStream* s, UINT32 alignment)
536 Stream_SealLength(s);
537 size = Stream_Length(s);
539 if ((size % alignment) != 0)
541 size_t offset = alignment - size % alignment;
543 if (!Stream_EnsureRemainingCapacity(s, offset))
546 Stream_Zero(s, offset);
549 Stream_SealLength(s);
559static UINT rdpsnd_server_send_wave_pdu(RdpsndServerContext* context, UINT16 wTimestamp)
563 UINT error = CHANNEL_RC_OK;
564 wStream* s = rdpsnd_server_get_buffer(context);
566 if (context->selected_client_format > context->num_client_formats)
567 return ERROR_INTERNAL_ERROR;
569 WINPR_ASSERT(context->client_formats);
571 format = &context->client_formats[context->selected_client_format];
573 Stream_ResetPosition(s);
575 if (!Stream_EnsureRemainingCapacity(s, 16))
576 return ERROR_OUTOFMEMORY;
578 Stream_Write_UINT8(s, SNDC_WAVE);
579 Stream_Write_UINT8(s, 0);
580 Stream_Write_UINT16(s, 0);
581 Stream_Write_UINT16(s, wTimestamp);
582 Stream_Write_UINT16(s, context->selected_client_format);
583 Stream_Write_UINT8(s, context->block_no);
585 const size_t start = Stream_GetPosition(s);
586 const BYTE* src = context->priv->out_buffer;
587 const size_t length =
588 1ull * context->priv->out_pending_frames * context->priv->src_bytes_per_frame;
590 if (!freerdp_dsp_encode(context->priv->dsp_context, context->src_format, src, length, s))
591 return ERROR_INTERNAL_ERROR;
594 if (!rdpsnd_server_align_wave_pdu(s, format->nBlockAlign))
595 return ERROR_INTERNAL_ERROR;
597 const size_t end = Stream_GetPosition(s);
598 const size_t pos = end - start + 8ULL;
599 if (pos > UINT16_MAX)
600 return ERROR_INTERNAL_ERROR;
601 if (!Stream_SetPosition(s, 2))
602 return ERROR_INTERNAL_ERROR;
603 Stream_Write_UINT16(s, (UINT16)pos);
604 if (!Stream_SetPosition(s, end))
605 return ERROR_INTERNAL_ERROR;
607 if (!WTSVirtualChannelWrite(context->priv->ChannelHandle, Stream_BufferAs(s,
char),
608 (UINT32)(start + 4), &written))
610 WLog_ERR(TAG,
"WTSVirtualChannelWrite failed!");
611 error = ERROR_INTERNAL_ERROR;
614 if (error != CHANNEL_RC_OK)
616 WLog_ERR(TAG,
"WTSVirtualChannelWrite failed!");
617 error = ERROR_INTERNAL_ERROR;
621 if (!Stream_SetPosition(s, start))
623 error = ERROR_INTERNAL_ERROR;
626 Stream_Write_UINT32(s, 0);
627 if (!Stream_SetPosition(s, start))
629 error = ERROR_INTERNAL_ERROR;
633 WINPR_ASSERT((end - start) <= UINT32_MAX);
634 if (!WTSVirtualChannelWrite(context->priv->ChannelHandle, Stream_Pointer(s),
635 (UINT32)(end - start), &written))
637 WLog_ERR(TAG,
"WTSVirtualChannelWrite failed!");
638 error = ERROR_INTERNAL_ERROR;
641 context->block_no = (context->block_no + 1) % 256;
644 Stream_ResetPosition(s);
645 context->priv->out_pending_frames = 0;
655static UINT rdpsnd_server_send_wave2_pdu(RdpsndServerContext* context, UINT16 formatNo,
656 const BYTE* data,
size_t size, BOOL encoded,
657 UINT16 timestamp, UINT32 audioTimeStamp)
660 UINT error = CHANNEL_RC_OK;
662 wStream* s = rdpsnd_server_get_buffer(context);
664 if (!Stream_EnsureRemainingCapacity(s, 16))
666 error = ERROR_INTERNAL_ERROR;
671 Stream_Write_UINT8(s, SNDC_WAVE2);
672 Stream_Write_UINT8(s, 0);
673 Stream_Write_UINT16(s, 0);
674 Stream_Write_UINT16(s, timestamp);
675 Stream_Write_UINT16(s, formatNo);
676 Stream_Write_UINT8(s, context->block_no);
677 Stream_Write_UINT8(s, 0);
678 Stream_Write_UINT8(s, 0);
679 Stream_Write_UINT8(s, 0);
680 Stream_Write_UINT32(s, audioTimeStamp);
684 if (!Stream_EnsureRemainingCapacity(s, size))
686 error = ERROR_INTERNAL_ERROR;
690 Stream_Write(s, data, size);
696 if (!freerdp_dsp_encode(context->priv->dsp_context, context->src_format, data, size, s))
698 error = ERROR_INTERNAL_ERROR;
702 format = &context->client_formats[formatNo];
703 if (!rdpsnd_server_align_wave_pdu(s, format->nBlockAlign))
705 error = ERROR_INTERNAL_ERROR;
711 const size_t end = Stream_GetPosition(s);
712 if (end > UINT16_MAX + 4)
714 error = ERROR_INTERNAL_ERROR;
718 if (!Stream_SetPosition(s, 2))
720 error = ERROR_INTERNAL_ERROR;
723 Stream_Write_UINT16(s, (UINT16)(end - 4));
725 status = WTSVirtualChannelWrite(context->priv->ChannelHandle, Stream_BufferAs(s,
char),
726 (UINT32)end, &written);
728 if (!status || (end != written))
731 "WTSVirtualChannelWrite failed! [stream length=%" PRIuz
" - written=%" PRIu32,
733 error = ERROR_INTERNAL_ERROR;
737 context->block_no = (context->block_no + 1) % 256;
740 Stream_ResetPosition(s);
741 context->priv->out_pending_frames = 0;
746static UINT rdpsnd_server_send_audio_pdu(RdpsndServerContext* context, UINT16 wTimestamp)
748 const BYTE* src =
nullptr;
751 WINPR_ASSERT(context);
752 WINPR_ASSERT(context->priv);
754 if (context->selected_client_format >= context->num_client_formats)
755 return ERROR_INTERNAL_ERROR;
757 src = context->priv->out_buffer;
758 length = context->priv->out_pending_frames * context->priv->src_bytes_per_frame;
760 if (context->clientVersion >= CHANNEL_VERSION_WIN_8)
761 return rdpsnd_server_send_wave2_pdu(context, context->selected_client_format, src, length,
762 FALSE, wTimestamp, wTimestamp);
764 return rdpsnd_server_send_wave_pdu(context, wTimestamp);
772static UINT rdpsnd_server_send_samples(RdpsndServerContext* context,
const void* buf,
773 size_t nframes, UINT16 wTimestamp)
775 UINT error = CHANNEL_RC_OK;
777 WINPR_ASSERT(context);
778 WINPR_ASSERT(context->priv);
780 EnterCriticalSection(&context->priv->lock);
782 if (context->selected_client_format >= context->num_client_formats)
785 WLog_WARN(TAG,
"Drop samples because client format has not been negotiated.");
786 error = ERROR_NOT_READY;
792 const size_t cframes =
793 MIN(nframes, context->priv->out_frames - context->priv->out_pending_frames);
794 size_t cframesize = cframes * context->priv->src_bytes_per_frame;
795 CopyMemory(context->priv->out_buffer +
796 (context->priv->out_pending_frames * context->priv->src_bytes_per_frame),
798 buf = (
const BYTE*)buf + cframesize;
800 context->priv->out_pending_frames += cframes;
802 if (context->priv->out_pending_frames >= context->priv->out_frames)
804 if ((error = rdpsnd_server_send_audio_pdu(context, wTimestamp)))
806 WLog_ERR(TAG,
"rdpsnd_server_send_audio_pdu failed with error %" PRIu32
"", error);
813 LeaveCriticalSection(&context->priv->lock);
822static UINT rdpsnd_server_send_samples2(RdpsndServerContext* context, UINT16 formatNo,
823 const void* buf,
size_t size, UINT16 timestamp,
824 UINT32 audioTimeStamp)
826 UINT error = CHANNEL_RC_OK;
828 WINPR_ASSERT(context);
829 WINPR_ASSERT(context->priv);
831 if (context->clientVersion < CHANNEL_VERSION_WIN_8)
832 return ERROR_INTERNAL_ERROR;
834 EnterCriticalSection(&context->priv->lock);
837 rdpsnd_server_send_wave2_pdu(context, formatNo, buf, size, TRUE, timestamp, audioTimeStamp);
839 LeaveCriticalSection(&context->priv->lock);
849static UINT rdpsnd_server_set_volume(RdpsndServerContext* context, UINT16 left, UINT16 right)
853 wStream* s = rdpsnd_server_get_buffer(context);
855 if (!Stream_EnsureRemainingCapacity(s, 8))
856 return ERROR_NOT_ENOUGH_MEMORY;
858 Stream_Write_UINT8(s, SNDC_SETVOLUME);
859 Stream_Write_UINT8(s, 0);
860 Stream_Write_UINT16(s, 4);
861 Stream_Write_UINT16(s, left);
862 Stream_Write_UINT16(s, right);
864 const size_t len = Stream_GetPosition(s);
865 WINPR_ASSERT(len <= UINT32_MAX);
866 status = WTSVirtualChannelWrite(context->priv->ChannelHandle, Stream_BufferAs(s,
char),
867 (ULONG)len, &written);
868 Stream_ResetPosition(s);
869 return status ? CHANNEL_RC_OK : ERROR_INTERNAL_ERROR;
877static UINT rdpsnd_server_close(RdpsndServerContext* context)
881 UINT error = CHANNEL_RC_OK;
882 wStream* s = rdpsnd_server_get_buffer(context);
884 EnterCriticalSection(&context->priv->lock);
886 if (context->priv->out_pending_frames > 0)
888 if (context->selected_client_format >= context->num_client_formats)
890 WLog_ERR(TAG,
"Pending audio frame exists while no format selected.");
891 error = ERROR_INVALID_DATA;
893 else if ((error = rdpsnd_server_send_audio_pdu(context, 0)))
895 WLog_ERR(TAG,
"rdpsnd_server_send_audio_pdu failed with error %" PRIu32
"", error);
899 LeaveCriticalSection(&context->priv->lock);
904 context->selected_client_format = 0xFFFF;
906 if (!Stream_EnsureRemainingCapacity(s, 4))
907 return ERROR_OUTOFMEMORY;
909 Stream_Write_UINT8(s, SNDC_CLOSE);
910 Stream_Write_UINT8(s, 0);
911 Stream_Seek_UINT16(s);
912 const size_t pos = Stream_GetPosition(s);
913 WINPR_ASSERT(pos >= 4);
914 if (!Stream_SetPosition(s, 2))
915 return ERROR_INVALID_DATA;
916 Stream_Write_UINT16(s, WINPR_ASSERTING_INT_CAST(uint16_t, pos - 4));
917 if (!Stream_SetPosition(s, pos))
918 return ERROR_INVALID_DATA;
920 const size_t len = Stream_GetPosition(s);
921 WINPR_ASSERT(len <= UINT32_MAX);
922 status = WTSVirtualChannelWrite(context->priv->ChannelHandle, Stream_BufferAs(s,
char),
923 (UINT32)len, &written);
924 Stream_ResetPosition(s);
925 return status ? CHANNEL_RC_OK : ERROR_INTERNAL_ERROR;
933static UINT rdpsnd_server_start(RdpsndServerContext* context)
935 void* buffer =
nullptr;
936 DWORD bytesReturned = 0;
937 RdpsndServerPrivate* priv =
nullptr;
938 UINT error = ERROR_INTERNAL_ERROR;
939 PULONG pSessionId =
nullptr;
941 WINPR_ASSERT(context);
942 WINPR_ASSERT(context->priv);
944 priv = context->priv;
945 priv->SessionId = WTS_CURRENT_SESSION;
947 if (context->use_dynamic_virtual_channel)
949 UINT32 channelId = 0;
952 if (WTSQuerySessionInformationA(context->vcm, WTS_CURRENT_SESSION, WTSSessionId,
953 (LPSTR*)&pSessionId, &bytesReturned))
955 priv->SessionId = (DWORD)*pSessionId;
956 WTSFreeMemory(pSessionId);
957 priv->ChannelHandle = WTSVirtualChannelOpenEx(priv->SessionId, RDPSND_DVC_CHANNEL_NAME,
958 WTS_CHANNEL_OPTION_DYNAMIC);
959 if (!priv->ChannelHandle)
961 WLog_ERR(TAG,
"Open audio dynamic virtual channel (%s) failed!",
962 RDPSND_DVC_CHANNEL_NAME);
963 return ERROR_INTERNAL_ERROR;
966 channelId = WTSChannelGetIdByHandle(priv->ChannelHandle);
968 IFCALLRET(context->ChannelIdAssigned, status, context, channelId);
971 WLog_ERR(TAG,
"context->ChannelIdAssigned failed!");
977 WLog_ERR(TAG,
"WTSQuerySessionInformationA failed!");
978 return ERROR_INTERNAL_ERROR;
983 priv->ChannelHandle =
984 WTSVirtualChannelOpen(context->vcm, WTS_CURRENT_SESSION, RDPSND_CHANNEL_NAME);
985 if (!priv->ChannelHandle)
987 WLog_ERR(TAG,
"Open audio static virtual channel (rdpsnd) failed!");
988 return ERROR_INTERNAL_ERROR;
992 if (!WTSVirtualChannelQuery(priv->ChannelHandle, WTSVirtualEventHandle, &buffer,
994 (bytesReturned !=
sizeof(HANDLE)))
997 "error during WTSVirtualChannelQuery(WTSVirtualEventHandle) or invalid returned "
1002 WTSFreeMemory(buffer);
1007 priv->channelEvent = *(HANDLE*)buffer;
1008 WTSFreeMemory(buffer);
1009 priv->rdpsnd_pdu = Stream_New(
nullptr, 4096);
1011 if (!priv->rdpsnd_pdu)
1013 WLog_ERR(TAG,
"Stream_New failed!");
1014 error = CHANNEL_RC_NO_MEMORY;
1018 if (!InitializeCriticalSectionEx(&context->priv->lock, 0, 0))
1020 WLog_ERR(TAG,
"InitializeCriticalSectionEx failed!");
1024 if ((error = rdpsnd_server_send_formats(context)))
1026 WLog_ERR(TAG,
"rdpsnd_server_send_formats failed with error %" PRIu32
"", error);
1030 if (priv->ownThread)
1032 context->priv->StopEvent = CreateEvent(
nullptr, TRUE, FALSE,
nullptr);
1034 if (!context->priv->StopEvent)
1036 WLog_ERR(TAG,
"CreateEvent failed!");
1040 context->priv->Thread =
1041 CreateThread(
nullptr, 0, rdpsnd_server_thread, (
void*)context, 0,
nullptr);
1043 if (!context->priv->Thread)
1045 WLog_ERR(TAG,
"CreateThread failed!");
1050 return CHANNEL_RC_OK;
1052 (void)CloseHandle(context->priv->StopEvent);
1053 context->priv->StopEvent =
nullptr;
1055 DeleteCriticalSection(&context->priv->lock);
1057 Stream_Free(context->priv->rdpsnd_pdu, TRUE);
1058 context->priv->rdpsnd_pdu =
nullptr;
1060 (void)WTSVirtualChannelClose(context->priv->ChannelHandle);
1061 context->priv->ChannelHandle =
nullptr;
1070static UINT rdpsnd_server_stop(RdpsndServerContext* context)
1072 UINT error = CHANNEL_RC_OK;
1074 WINPR_ASSERT(context);
1075 WINPR_ASSERT(context->priv);
1077 if (!context->priv->StopEvent)
1080 if (context->priv->ownThread)
1082 if (context->priv->StopEvent)
1084 (void)SetEvent(context->priv->StopEvent);
1086 if (WaitForSingleObject(context->priv->Thread, INFINITE) == WAIT_FAILED)
1088 error = GetLastError();
1089 WLog_ERR(TAG,
"WaitForSingleObject failed with error %" PRIu32
"!", error);
1093 (void)CloseHandle(context->priv->Thread);
1094 (void)CloseHandle(context->priv->StopEvent);
1095 context->priv->Thread =
nullptr;
1096 context->priv->StopEvent =
nullptr;
1100 DeleteCriticalSection(&context->priv->lock);
1102 if (context->priv->rdpsnd_pdu)
1104 Stream_Free(context->priv->rdpsnd_pdu, TRUE);
1105 context->priv->rdpsnd_pdu =
nullptr;
1108 if (context->priv->ChannelHandle)
1110 (void)WTSVirtualChannelClose(context->priv->ChannelHandle);
1111 context->priv->ChannelHandle =
nullptr;
1117RdpsndServerContext* rdpsnd_server_context_new(HANDLE vcm)
1119 RdpsndServerPrivate* priv =
nullptr;
1120 RdpsndServerContext* context = (RdpsndServerContext*)calloc(1,
sizeof(RdpsndServerContext));
1126 context->Start = rdpsnd_server_start;
1127 context->Stop = rdpsnd_server_stop;
1128 context->selected_client_format = 0xFFFF;
1129 context->Initialize = rdpsnd_server_initialize;
1130 context->SendFormats = rdpsnd_server_send_formats;
1131 context->SelectFormat = rdpsnd_server_select_format;
1132 context->Training = rdpsnd_server_training;
1133 context->SendSamples = rdpsnd_server_send_samples;
1134 context->SendSamples2 = rdpsnd_server_send_samples2;
1135 context->SetVolume = rdpsnd_server_set_volume;
1136 context->Close = rdpsnd_server_close;
1137 context->priv = priv = (RdpsndServerPrivate*)calloc(1,
sizeof(RdpsndServerPrivate));
1141 WLog_ERR(TAG,
"calloc failed!");
1145 priv->dsp_context = freerdp_dsp_context_new(TRUE);
1147 if (!priv->dsp_context)
1149 WLog_ERR(TAG,
"freerdp_dsp_context_new failed!");
1153 priv->input_stream = Stream_New(
nullptr, 4);
1155 if (!priv->input_stream)
1157 WLog_ERR(TAG,
"Stream_New failed!");
1161 priv->expectedBytes = 4;
1162 priv->waitingHeader = TRUE;
1163 priv->ownThread = TRUE;
1166 WINPR_PRAGMA_DIAG_PUSH
1167 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
1168 rdpsnd_server_context_free(context);
1169 WINPR_PRAGMA_DIAG_POP
1173void rdpsnd_server_context_reset(RdpsndServerContext* context)
1175 WINPR_ASSERT(context);
1176 WINPR_ASSERT(context->priv);
1178 context->priv->expectedBytes = 4;
1179 context->priv->waitingHeader = TRUE;
1180 Stream_ResetPosition(context->priv->input_stream);
1183void rdpsnd_server_context_free(RdpsndServerContext* context)
1190 rdpsnd_server_stop(context);
1192 free(context->priv->out_buffer);
1194 if (context->priv->dsp_context)
1195 freerdp_dsp_context_free(context->priv->dsp_context);
1197 if (context->priv->input_stream)
1198 Stream_Free(context->priv->input_stream, TRUE);
1201 free(context->server_formats);
1202 rdpsnd_server_client_format_free(context);
1203 free(context->priv);
1207HANDLE rdpsnd_server_get_event_handle(RdpsndServerContext* context)
1209 WINPR_ASSERT(context);
1210 WINPR_ASSERT(context->priv);
1212 return context->priv->channelEvent;
1229UINT rdpsnd_server_handle_messages(RdpsndServerContext* context)
1231 DWORD bytesReturned = 0;
1232 UINT ret = CHANNEL_RC_OK;
1233 RdpsndServerPrivate* priv =
nullptr;
1236 WINPR_ASSERT(context);
1237 WINPR_ASSERT(context->priv);
1239 priv = context->priv;
1240 s = priv->input_stream;
1242 if (!WTSVirtualChannelRead(priv->ChannelHandle, 0, Stream_Pointer(s), priv->expectedBytes,
1245 if (GetLastError() == ERROR_NO_DATA)
1246 return ERROR_NO_DATA;
1248 WLog_ERR(TAG,
"channel connection closed");
1249 return ERROR_INTERNAL_ERROR;
1252 priv->expectedBytes -= bytesReturned;
1253 Stream_Seek(s, bytesReturned);
1255 if (priv->expectedBytes)
1256 return CHANNEL_RC_OK;
1258 Stream_SealLength(s);
1259 Stream_ResetPosition(s);
1261 if (priv->waitingHeader)
1264 Stream_Read_UINT8(s, priv->msgType);
1265 Stream_Seek_UINT8(s);
1266 Stream_Read_UINT16(s, priv->expectedBytes);
1267 priv->waitingHeader = FALSE;
1268 Stream_ResetPosition(s);
1270 if (priv->expectedBytes)
1272 if (!Stream_EnsureCapacity(s, priv->expectedBytes))
1274 WLog_ERR(TAG,
"Stream_EnsureCapacity failed!");
1275 return CHANNEL_RC_NO_MEMORY;
1278 return CHANNEL_RC_OK;
1283#ifdef WITH_DEBUG_SND
1284 WLog_DBG(TAG,
"message type %" PRIu8
"", priv->msgType);
1286 priv->expectedBytes = 4;
1287 priv->waitingHeader = TRUE;
1289 switch (priv->msgType)
1291 case SNDC_WAVECONFIRM:
1292 ret = rdpsnd_server_recv_waveconfirm(context, s);
1296 ret = rdpsnd_server_recv_trainingconfirm(context, s);
1300 ret = rdpsnd_server_recv_formats(context, s);
1302 if ((ret == CHANNEL_RC_OK) && (context->clientVersion < CHANNEL_VERSION_WIN_7))
1303 IFCALL(context->Activated, context);
1307 case SNDC_QUALITYMODE:
1308 ret = rdpsnd_server_recv_quality_mode(context, s);
1310 if ((ret == CHANNEL_RC_OK) && (context->clientVersion >= CHANNEL_VERSION_WIN_7))
1311 IFCALL(context->Activated, context);
1316 WLog_ERR(TAG,
"UNKNOWN MESSAGE TYPE!! (0x%02" PRIX8
")", priv->msgType);
1317 ret = ERROR_INVALID_DATA;
1321 Stream_ResetPosition(s);