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_SetPosition(s, 0);
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 Stream_SetPosition(s, 2);
93 Stream_Write_UINT16(s, (UINT16)(pos - 4));
94 Stream_SetPosition(s, pos);
96 WINPR_ASSERT(context->priv);
98 status = WTSVirtualChannelWrite(context->priv->ChannelHandle, Stream_BufferAs(s,
char),
99 (UINT32)pos, &written);
100 Stream_SetPosition(s, 0);
103 return status ? CHANNEL_RC_OK : ERROR_INTERNAL_ERROR;
111static UINT rdpsnd_server_recv_waveconfirm(RdpsndServerContext* context,
wStream* s)
113 UINT16 timestamp = 0;
114 BYTE confirmBlockNum = 0;
115 UINT error = CHANNEL_RC_OK;
117 WINPR_ASSERT(context);
119 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
120 return ERROR_INVALID_DATA;
122 Stream_Read_UINT16(s, timestamp);
123 Stream_Read_UINT8(s, confirmBlockNum);
124 Stream_Seek_UINT8(s);
125 IFCALLRET(context->ConfirmBlock, error, context, confirmBlockNum, timestamp);
128 WLog_ERR(TAG,
"context->ConfirmBlock failed with error %" PRIu32
"", error);
138static UINT rdpsnd_server_recv_trainingconfirm(RdpsndServerContext* context,
wStream* s)
140 UINT16 timestamp = 0;
142 UINT error = CHANNEL_RC_OK;
144 WINPR_ASSERT(context);
146 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
147 return ERROR_INVALID_DATA;
149 Stream_Read_UINT16(s, timestamp);
150 Stream_Read_UINT16(s, packsize);
152 IFCALLRET(context->TrainingConfirm, error, context, timestamp, packsize);
154 WLog_ERR(TAG,
"context->TrainingConfirm failed with error %" PRIu32
"", error);
164static UINT rdpsnd_server_recv_quality_mode(RdpsndServerContext* context,
wStream* s)
166 WINPR_ASSERT(context);
168 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
170 WLog_ERR(TAG,
"not enough data in stream!");
171 return ERROR_INVALID_DATA;
174 Stream_Read_UINT16(s, context->qualityMode);
175 Stream_Seek_UINT16(s);
177 WLog_DBG(TAG,
"Client requested sound quality: 0x%04" PRIX16
"", context->qualityMode);
179 return CHANNEL_RC_OK;
187static UINT rdpsnd_server_recv_formats(RdpsndServerContext* context,
wStream* s)
189 UINT error = CHANNEL_RC_OK;
191 WINPR_ASSERT(context);
193 if (!Stream_CheckAndLogRequiredLength(TAG, s, 20))
194 return ERROR_INVALID_DATA;
196 Stream_Read_UINT32(s, context->capsFlags);
197 Stream_Read_UINT32(s, context->initialVolume);
198 Stream_Read_UINT32(s, context->initialPitch);
199 Stream_Read_UINT16(s, context->udpPort);
200 Stream_Read_UINT16(s, context->num_client_formats);
201 Stream_Read_UINT8(s, context->lastblock);
202 Stream_Read_UINT16(s, context->clientVersion);
203 Stream_Seek_UINT8(s);
206 if (!Stream_CheckAndLogRequiredLengthOfSize(TAG, s, context->num_client_formats, 18ull))
207 return ERROR_INVALID_DATA;
209 if (!context->num_client_formats)
211 WLog_ERR(TAG,
"client doesn't support any format!");
212 return ERROR_INTERNAL_ERROR;
215 context->client_formats = audio_formats_new(context->num_client_formats);
217 if (!context->client_formats)
219 WLog_ERR(TAG,
"calloc failed!");
220 return CHANNEL_RC_NO_MEMORY;
223 for (UINT16 i = 0; i < context->num_client_formats; i++)
227 if (!Stream_CheckAndLogRequiredLength(TAG, s, 18))
229 WLog_ERR(TAG,
"not enough data in stream!");
230 error = ERROR_INVALID_DATA;
234 Stream_Read_UINT16(s, format->wFormatTag);
235 Stream_Read_UINT16(s, format->nChannels);
236 Stream_Read_UINT32(s, format->nSamplesPerSec);
237 Stream_Read_UINT32(s, format->nAvgBytesPerSec);
238 Stream_Read_UINT16(s, format->nBlockAlign);
239 Stream_Read_UINT16(s, format->wBitsPerSample);
240 Stream_Read_UINT16(s, format->cbSize);
242 if (format->cbSize > 0)
244 if (!Stream_SafeSeek(s, format->cbSize))
246 WLog_ERR(TAG,
"Stream_SafeSeek failed!");
247 error = ERROR_INTERNAL_ERROR;
253 if (!context->num_client_formats)
255 WLog_ERR(TAG,
"client doesn't support any known format!");
259 return CHANNEL_RC_OK;
261 free(context->client_formats);
265static DWORD WINAPI rdpsnd_server_thread(LPVOID arg)
269 HANDLE events[2] = WINPR_C_ARRAY_INIT;
270 RdpsndServerContext* context = (RdpsndServerContext*)arg;
271 UINT error = CHANNEL_RC_OK;
273 WINPR_ASSERT(context);
274 WINPR_ASSERT(context->priv);
276 events[nCount++] = context->priv->channelEvent;
277 events[nCount++] = context->priv->StopEvent;
279 WINPR_ASSERT(nCount <= ARRAYSIZE(events));
283 status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE);
285 if (status == WAIT_FAILED)
287 error = GetLastError();
288 WLog_ERR(TAG,
"WaitForMultipleObjects failed with error %" PRIu32
"!", error);
292 status = WaitForSingleObject(context->priv->StopEvent, 0);
294 if (status == WAIT_FAILED)
296 error = GetLastError();
297 WLog_ERR(TAG,
"WaitForSingleObject failed with error %" PRIu32
"!", error);
301 if (status == WAIT_OBJECT_0)
304 if ((error = rdpsnd_server_handle_messages(context)))
306 WLog_ERR(TAG,
"rdpsnd_server_handle_messages failed with error %" PRIu32
"", error);
311 if (error && context->rdpcontext)
312 setChannelError(context->rdpcontext, error,
"rdpsnd_server_thread reported an error");
323static UINT rdpsnd_server_initialize(RdpsndServerContext* context, BOOL ownThread)
325 WINPR_ASSERT(context);
326 WINPR_ASSERT(context->priv);
328 context->priv->ownThread = ownThread;
329 return context->Start(context);
337static UINT rdpsnd_server_select_format(RdpsndServerContext* context, UINT16 client_format_index)
340 size_t out_buffer_size = 0;
342 UINT error = CHANNEL_RC_OK;
344 WINPR_ASSERT(context);
345 WINPR_ASSERT(context->priv);
347 if ((client_format_index >= context->num_client_formats) || (!context->src_format))
349 WLog_ERR(TAG,
"index %" PRIu16
" is not correct.", client_format_index);
350 return ERROR_INVALID_DATA;
353 EnterCriticalSection(&context->priv->lock);
354 context->priv->src_bytes_per_sample = context->src_format->wBitsPerSample / 8;
355 context->priv->src_bytes_per_frame =
356 context->priv->src_bytes_per_sample * context->src_format->nChannels;
357 context->selected_client_format = client_format_index;
358 format = &context->client_formats[client_format_index];
360 if (format->nSamplesPerSec == 0)
362 WLog_ERR(TAG,
"invalid Client Sound Format!!");
363 error = ERROR_INVALID_DATA;
367 if (context->latency <= 0)
368 context->latency = 50;
370 context->priv->out_frames = context->src_format->nSamplesPerSec * context->latency / 1000;
372 if (context->priv->out_frames < 1)
373 context->priv->out_frames = 1;
375 switch (format->wFormatTag)
377 case WAVE_FORMAT_DVI_ADPCM:
378 bs = 4ULL * (format->nBlockAlign - 4ULL * format->nChannels);
379 context->priv->out_frames -= context->priv->out_frames % bs;
381 if (context->priv->out_frames < bs)
382 context->priv->out_frames = bs;
386 case WAVE_FORMAT_ADPCM:
387 bs = (format->nBlockAlign - 7 * format->nChannels) * 2 / format->nChannels + 2;
388 context->priv->out_frames -= context->priv->out_frames % bs;
390 if (context->priv->out_frames < bs)
391 context->priv->out_frames = bs;
398 context->priv->out_pending_frames = 0;
399 out_buffer_size = context->priv->out_frames * context->priv->src_bytes_per_frame;
401 if (context->priv->out_buffer_size < out_buffer_size)
403 BYTE* newBuffer =
nullptr;
404 newBuffer = (BYTE*)realloc(context->priv->out_buffer, out_buffer_size);
408 WLog_ERR(TAG,
"realloc failed!");
409 error = CHANNEL_RC_NO_MEMORY;
413 context->priv->out_buffer = newBuffer;
414 context->priv->out_buffer_size = out_buffer_size;
417 if (!freerdp_dsp_context_reset(context->priv->dsp_context, format, 0u))
418 error = ERROR_INTERNAL_ERROR;
420 LeaveCriticalSection(&context->priv->lock);
429static UINT rdpsnd_server_training(RdpsndServerContext* context, UINT16 timestamp, UINT16 packsize,
434 wStream* s = rdpsnd_server_get_buffer(context);
436 if (!Stream_EnsureRemainingCapacity(s, 8))
437 return ERROR_INTERNAL_ERROR;
439 Stream_Write_UINT8(s, SNDC_TRAINING);
440 Stream_Write_UINT8(s, 0);
441 Stream_Seek_UINT16(s);
442 Stream_Write_UINT16(s, timestamp);
443 Stream_Write_UINT16(s, packsize);
447 if (!Stream_EnsureRemainingCapacity(s, packsize))
449 Stream_SetPosition(s, 0);
450 return ERROR_INTERNAL_ERROR;
453 Stream_Write(s, data, packsize);
456 const size_t end = Stream_GetPosition(s);
457 if ((end < 4) || (end > UINT16_MAX))
458 return ERROR_INTERNAL_ERROR;
460 Stream_SetPosition(s, 2);
461 Stream_Write_UINT16(s, (UINT16)(end - 4));
463 status = WTSVirtualChannelWrite(context->priv->ChannelHandle, Stream_BufferAs(s,
char),
464 (UINT32)end, &written);
466 Stream_SetPosition(s, 0);
468 return status ? CHANNEL_RC_OK : ERROR_INTERNAL_ERROR;
471static BOOL rdpsnd_server_align_wave_pdu(
wStream* s, UINT32 alignment)
474 Stream_SealLength(s);
475 size = Stream_Length(s);
477 if ((size % alignment) != 0)
479 size_t offset = alignment - size % alignment;
481 if (!Stream_EnsureRemainingCapacity(s, offset))
484 Stream_Zero(s, offset);
487 Stream_SealLength(s);
497static UINT rdpsnd_server_send_wave_pdu(RdpsndServerContext* context, UINT16 wTimestamp)
501 UINT error = CHANNEL_RC_OK;
502 wStream* s = rdpsnd_server_get_buffer(context);
504 if (context->selected_client_format > context->num_client_formats)
505 return ERROR_INTERNAL_ERROR;
507 WINPR_ASSERT(context->client_formats);
509 format = &context->client_formats[context->selected_client_format];
511 Stream_SetPosition(s, 0);
513 if (!Stream_EnsureRemainingCapacity(s, 16))
514 return ERROR_OUTOFMEMORY;
516 Stream_Write_UINT8(s, SNDC_WAVE);
517 Stream_Write_UINT8(s, 0);
518 Stream_Write_UINT16(s, 0);
519 Stream_Write_UINT16(s, wTimestamp);
520 Stream_Write_UINT16(s, context->selected_client_format);
521 Stream_Write_UINT8(s, context->block_no);
523 const size_t start = Stream_GetPosition(s);
524 const BYTE* src = context->priv->out_buffer;
525 const size_t length =
526 1ull * context->priv->out_pending_frames * context->priv->src_bytes_per_frame;
528 if (!freerdp_dsp_encode(context->priv->dsp_context, context->src_format, src, length, s))
529 return ERROR_INTERNAL_ERROR;
532 if (!rdpsnd_server_align_wave_pdu(s, format->nBlockAlign))
533 return ERROR_INTERNAL_ERROR;
535 const size_t end = Stream_GetPosition(s);
536 const size_t pos = end - start + 8ULL;
537 if (pos > UINT16_MAX)
538 return ERROR_INTERNAL_ERROR;
539 Stream_SetPosition(s, 2);
540 Stream_Write_UINT16(s, (UINT16)pos);
541 Stream_SetPosition(s, end);
543 if (!WTSVirtualChannelWrite(context->priv->ChannelHandle, Stream_BufferAs(s,
char),
544 (UINT32)(start + 4), &written))
546 WLog_ERR(TAG,
"WTSVirtualChannelWrite failed!");
547 error = ERROR_INTERNAL_ERROR;
550 if (error != CHANNEL_RC_OK)
552 WLog_ERR(TAG,
"WTSVirtualChannelWrite failed!");
553 error = ERROR_INTERNAL_ERROR;
557 Stream_SetPosition(s, start);
558 Stream_Write_UINT32(s, 0);
559 Stream_SetPosition(s, start);
561 WINPR_ASSERT((end - start) <= UINT32_MAX);
562 if (!WTSVirtualChannelWrite(context->priv->ChannelHandle, Stream_Pointer(s),
563 (UINT32)(end - start), &written))
565 WLog_ERR(TAG,
"WTSVirtualChannelWrite failed!");
566 error = ERROR_INTERNAL_ERROR;
569 context->block_no = (context->block_no + 1) % 256;
572 Stream_SetPosition(s, 0);
573 context->priv->out_pending_frames = 0;
583static UINT rdpsnd_server_send_wave2_pdu(RdpsndServerContext* context, UINT16 formatNo,
584 const BYTE* data,
size_t size, BOOL encoded,
585 UINT16 timestamp, UINT32 audioTimeStamp)
588 UINT error = CHANNEL_RC_OK;
590 wStream* s = rdpsnd_server_get_buffer(context);
592 if (!Stream_EnsureRemainingCapacity(s, 16))
594 error = ERROR_INTERNAL_ERROR;
599 Stream_Write_UINT8(s, SNDC_WAVE2);
600 Stream_Write_UINT8(s, 0);
601 Stream_Write_UINT16(s, 0);
602 Stream_Write_UINT16(s, timestamp);
603 Stream_Write_UINT16(s, formatNo);
604 Stream_Write_UINT8(s, context->block_no);
605 Stream_Write_UINT8(s, 0);
606 Stream_Write_UINT8(s, 0);
607 Stream_Write_UINT8(s, 0);
608 Stream_Write_UINT32(s, audioTimeStamp);
612 if (!Stream_EnsureRemainingCapacity(s, size))
614 error = ERROR_INTERNAL_ERROR;
618 Stream_Write(s, data, size);
624 if (!freerdp_dsp_encode(context->priv->dsp_context, context->src_format, data, size, s))
626 error = ERROR_INTERNAL_ERROR;
630 format = &context->client_formats[formatNo];
631 if (!rdpsnd_server_align_wave_pdu(s, format->nBlockAlign))
633 error = ERROR_INTERNAL_ERROR;
639 const size_t end = Stream_GetPosition(s);
640 if (end > UINT16_MAX + 4)
642 error = ERROR_INTERNAL_ERROR;
646 Stream_SetPosition(s, 2);
647 Stream_Write_UINT16(s, (UINT16)(end - 4));
649 status = WTSVirtualChannelWrite(context->priv->ChannelHandle, Stream_BufferAs(s,
char),
650 (UINT32)end, &written);
652 if (!status || (end != written))
655 "WTSVirtualChannelWrite failed! [stream length=%" PRIuz
" - written=%" PRIu32,
657 error = ERROR_INTERNAL_ERROR;
661 context->block_no = (context->block_no + 1) % 256;
664 Stream_SetPosition(s, 0);
665 context->priv->out_pending_frames = 0;
670static UINT rdpsnd_server_send_audio_pdu(RdpsndServerContext* context, UINT16 wTimestamp)
672 const BYTE* src =
nullptr;
675 WINPR_ASSERT(context);
676 WINPR_ASSERT(context->priv);
678 if (context->selected_client_format >= context->num_client_formats)
679 return ERROR_INTERNAL_ERROR;
681 src = context->priv->out_buffer;
682 length = context->priv->out_pending_frames * context->priv->src_bytes_per_frame;
684 if (context->clientVersion >= CHANNEL_VERSION_WIN_8)
685 return rdpsnd_server_send_wave2_pdu(context, context->selected_client_format, src, length,
686 FALSE, wTimestamp, wTimestamp);
688 return rdpsnd_server_send_wave_pdu(context, wTimestamp);
696static UINT rdpsnd_server_send_samples(RdpsndServerContext* context,
const void* buf,
697 size_t nframes, UINT16 wTimestamp)
699 UINT error = CHANNEL_RC_OK;
701 WINPR_ASSERT(context);
702 WINPR_ASSERT(context->priv);
704 EnterCriticalSection(&context->priv->lock);
706 if (context->selected_client_format >= context->num_client_formats)
709 WLog_WARN(TAG,
"Drop samples because client format has not been negotiated.");
710 error = ERROR_NOT_READY;
716 const size_t cframes =
717 MIN(nframes, context->priv->out_frames - context->priv->out_pending_frames);
718 size_t cframesize = cframes * context->priv->src_bytes_per_frame;
719 CopyMemory(context->priv->out_buffer +
720 (context->priv->out_pending_frames * context->priv->src_bytes_per_frame),
722 buf = (
const BYTE*)buf + cframesize;
724 context->priv->out_pending_frames += cframes;
726 if (context->priv->out_pending_frames >= context->priv->out_frames)
728 if ((error = rdpsnd_server_send_audio_pdu(context, wTimestamp)))
730 WLog_ERR(TAG,
"rdpsnd_server_send_audio_pdu failed with error %" PRIu32
"", error);
737 LeaveCriticalSection(&context->priv->lock);
746static UINT rdpsnd_server_send_samples2(RdpsndServerContext* context, UINT16 formatNo,
747 const void* buf,
size_t size, UINT16 timestamp,
748 UINT32 audioTimeStamp)
750 UINT error = CHANNEL_RC_OK;
752 WINPR_ASSERT(context);
753 WINPR_ASSERT(context->priv);
755 if (context->clientVersion < CHANNEL_VERSION_WIN_8)
756 return ERROR_INTERNAL_ERROR;
758 EnterCriticalSection(&context->priv->lock);
761 rdpsnd_server_send_wave2_pdu(context, formatNo, buf, size, TRUE, timestamp, audioTimeStamp);
763 LeaveCriticalSection(&context->priv->lock);
773static UINT rdpsnd_server_set_volume(RdpsndServerContext* context, UINT16 left, UINT16 right)
777 wStream* s = rdpsnd_server_get_buffer(context);
779 if (!Stream_EnsureRemainingCapacity(s, 8))
780 return ERROR_NOT_ENOUGH_MEMORY;
782 Stream_Write_UINT8(s, SNDC_SETVOLUME);
783 Stream_Write_UINT8(s, 0);
784 Stream_Write_UINT16(s, 4);
785 Stream_Write_UINT16(s, left);
786 Stream_Write_UINT16(s, right);
788 const size_t len = Stream_GetPosition(s);
789 WINPR_ASSERT(len <= UINT32_MAX);
790 status = WTSVirtualChannelWrite(context->priv->ChannelHandle, Stream_BufferAs(s,
char),
791 (ULONG)len, &written);
792 Stream_SetPosition(s, 0);
793 return status ? CHANNEL_RC_OK : ERROR_INTERNAL_ERROR;
801static UINT rdpsnd_server_close(RdpsndServerContext* context)
805 UINT error = CHANNEL_RC_OK;
806 wStream* s = rdpsnd_server_get_buffer(context);
808 EnterCriticalSection(&context->priv->lock);
810 if (context->priv->out_pending_frames > 0)
812 if (context->selected_client_format >= context->num_client_formats)
814 WLog_ERR(TAG,
"Pending audio frame exists while no format selected.");
815 error = ERROR_INVALID_DATA;
817 else if ((error = rdpsnd_server_send_audio_pdu(context, 0)))
819 WLog_ERR(TAG,
"rdpsnd_server_send_audio_pdu failed with error %" PRIu32
"", error);
823 LeaveCriticalSection(&context->priv->lock);
828 context->selected_client_format = 0xFFFF;
830 if (!Stream_EnsureRemainingCapacity(s, 4))
831 return ERROR_OUTOFMEMORY;
833 Stream_Write_UINT8(s, SNDC_CLOSE);
834 Stream_Write_UINT8(s, 0);
835 Stream_Seek_UINT16(s);
836 const size_t pos = Stream_GetPosition(s);
837 WINPR_ASSERT(pos >= 4);
838 Stream_SetPosition(s, 2);
839 Stream_Write_UINT16(s, WINPR_ASSERTING_INT_CAST(uint16_t, pos - 4));
840 Stream_SetPosition(s, pos);
842 const size_t len = Stream_GetPosition(s);
843 WINPR_ASSERT(len <= UINT32_MAX);
844 status = WTSVirtualChannelWrite(context->priv->ChannelHandle, Stream_BufferAs(s,
char),
845 (UINT32)len, &written);
846 Stream_SetPosition(s, 0);
847 return status ? CHANNEL_RC_OK : ERROR_INTERNAL_ERROR;
855static UINT rdpsnd_server_start(RdpsndServerContext* context)
857 void* buffer =
nullptr;
858 DWORD bytesReturned = 0;
859 RdpsndServerPrivate* priv =
nullptr;
860 UINT error = ERROR_INTERNAL_ERROR;
861 PULONG pSessionId =
nullptr;
863 WINPR_ASSERT(context);
864 WINPR_ASSERT(context->priv);
866 priv = context->priv;
867 priv->SessionId = WTS_CURRENT_SESSION;
869 if (context->use_dynamic_virtual_channel)
871 UINT32 channelId = 0;
874 if (WTSQuerySessionInformationA(context->vcm, WTS_CURRENT_SESSION, WTSSessionId,
875 (LPSTR*)&pSessionId, &bytesReturned))
877 priv->SessionId = (DWORD)*pSessionId;
878 WTSFreeMemory(pSessionId);
879 priv->ChannelHandle = WTSVirtualChannelOpenEx(priv->SessionId, RDPSND_DVC_CHANNEL_NAME,
880 WTS_CHANNEL_OPTION_DYNAMIC);
881 if (!priv->ChannelHandle)
883 WLog_ERR(TAG,
"Open audio dynamic virtual channel (%s) failed!",
884 RDPSND_DVC_CHANNEL_NAME);
885 return ERROR_INTERNAL_ERROR;
888 channelId = WTSChannelGetIdByHandle(priv->ChannelHandle);
890 IFCALLRET(context->ChannelIdAssigned, status, context, channelId);
893 WLog_ERR(TAG,
"context->ChannelIdAssigned failed!");
899 WLog_ERR(TAG,
"WTSQuerySessionInformationA failed!");
900 return ERROR_INTERNAL_ERROR;
905 priv->ChannelHandle =
906 WTSVirtualChannelOpen(context->vcm, WTS_CURRENT_SESSION, RDPSND_CHANNEL_NAME);
907 if (!priv->ChannelHandle)
909 WLog_ERR(TAG,
"Open audio static virtual channel (rdpsnd) failed!");
910 return ERROR_INTERNAL_ERROR;
914 if (!WTSVirtualChannelQuery(priv->ChannelHandle, WTSVirtualEventHandle, &buffer,
916 (bytesReturned !=
sizeof(HANDLE)))
919 "error during WTSVirtualChannelQuery(WTSVirtualEventHandle) or invalid returned "
924 WTSFreeMemory(buffer);
929 priv->channelEvent = *(HANDLE*)buffer;
930 WTSFreeMemory(buffer);
931 priv->rdpsnd_pdu = Stream_New(
nullptr, 4096);
933 if (!priv->rdpsnd_pdu)
935 WLog_ERR(TAG,
"Stream_New failed!");
936 error = CHANNEL_RC_NO_MEMORY;
940 if (!InitializeCriticalSectionEx(&context->priv->lock, 0, 0))
942 WLog_ERR(TAG,
"InitializeCriticalSectionEx failed!");
946 if ((error = rdpsnd_server_send_formats(context)))
948 WLog_ERR(TAG,
"rdpsnd_server_send_formats failed with error %" PRIu32
"", error);
954 context->priv->StopEvent = CreateEvent(
nullptr, TRUE, FALSE,
nullptr);
956 if (!context->priv->StopEvent)
958 WLog_ERR(TAG,
"CreateEvent failed!");
962 context->priv->Thread =
963 CreateThread(
nullptr, 0, rdpsnd_server_thread, (
void*)context, 0,
nullptr);
965 if (!context->priv->Thread)
967 WLog_ERR(TAG,
"CreateThread failed!");
972 return CHANNEL_RC_OK;
974 (void)CloseHandle(context->priv->StopEvent);
975 context->priv->StopEvent =
nullptr;
977 DeleteCriticalSection(&context->priv->lock);
979 Stream_Free(context->priv->rdpsnd_pdu, TRUE);
980 context->priv->rdpsnd_pdu =
nullptr;
982 (void)WTSVirtualChannelClose(context->priv->ChannelHandle);
983 context->priv->ChannelHandle =
nullptr;
992static UINT rdpsnd_server_stop(RdpsndServerContext* context)
994 UINT error = CHANNEL_RC_OK;
996 WINPR_ASSERT(context);
997 WINPR_ASSERT(context->priv);
999 if (!context->priv->StopEvent)
1002 if (context->priv->ownThread)
1004 if (context->priv->StopEvent)
1006 (void)SetEvent(context->priv->StopEvent);
1008 if (WaitForSingleObject(context->priv->Thread, INFINITE) == WAIT_FAILED)
1010 error = GetLastError();
1011 WLog_ERR(TAG,
"WaitForSingleObject failed with error %" PRIu32
"!", error);
1015 (void)CloseHandle(context->priv->Thread);
1016 (void)CloseHandle(context->priv->StopEvent);
1017 context->priv->Thread =
nullptr;
1018 context->priv->StopEvent =
nullptr;
1022 DeleteCriticalSection(&context->priv->lock);
1024 if (context->priv->rdpsnd_pdu)
1026 Stream_Free(context->priv->rdpsnd_pdu, TRUE);
1027 context->priv->rdpsnd_pdu =
nullptr;
1030 if (context->priv->ChannelHandle)
1032 (void)WTSVirtualChannelClose(context->priv->ChannelHandle);
1033 context->priv->ChannelHandle =
nullptr;
1039RdpsndServerContext* rdpsnd_server_context_new(HANDLE vcm)
1041 RdpsndServerPrivate* priv =
nullptr;
1042 RdpsndServerContext* context = (RdpsndServerContext*)calloc(1,
sizeof(RdpsndServerContext));
1048 context->Start = rdpsnd_server_start;
1049 context->Stop = rdpsnd_server_stop;
1050 context->selected_client_format = 0xFFFF;
1051 context->Initialize = rdpsnd_server_initialize;
1052 context->SendFormats = rdpsnd_server_send_formats;
1053 context->SelectFormat = rdpsnd_server_select_format;
1054 context->Training = rdpsnd_server_training;
1055 context->SendSamples = rdpsnd_server_send_samples;
1056 context->SendSamples2 = rdpsnd_server_send_samples2;
1057 context->SetVolume = rdpsnd_server_set_volume;
1058 context->Close = rdpsnd_server_close;
1059 context->priv = priv = (RdpsndServerPrivate*)calloc(1,
sizeof(RdpsndServerPrivate));
1063 WLog_ERR(TAG,
"calloc failed!");
1067 priv->dsp_context = freerdp_dsp_context_new(TRUE);
1069 if (!priv->dsp_context)
1071 WLog_ERR(TAG,
"freerdp_dsp_context_new failed!");
1075 priv->input_stream = Stream_New(
nullptr, 4);
1077 if (!priv->input_stream)
1079 WLog_ERR(TAG,
"Stream_New failed!");
1083 priv->expectedBytes = 4;
1084 priv->waitingHeader = TRUE;
1085 priv->ownThread = TRUE;
1088 WINPR_PRAGMA_DIAG_PUSH
1089 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
1090 rdpsnd_server_context_free(context);
1091 WINPR_PRAGMA_DIAG_POP
1095void rdpsnd_server_context_reset(RdpsndServerContext* context)
1097 WINPR_ASSERT(context);
1098 WINPR_ASSERT(context->priv);
1100 context->priv->expectedBytes = 4;
1101 context->priv->waitingHeader = TRUE;
1102 Stream_SetPosition(context->priv->input_stream, 0);
1105void rdpsnd_server_context_free(RdpsndServerContext* context)
1112 rdpsnd_server_stop(context);
1114 free(context->priv->out_buffer);
1116 if (context->priv->dsp_context)
1117 freerdp_dsp_context_free(context->priv->dsp_context);
1119 if (context->priv->input_stream)
1120 Stream_Free(context->priv->input_stream, TRUE);
1123 free(context->server_formats);
1124 free(context->client_formats);
1125 free(context->priv);
1129HANDLE rdpsnd_server_get_event_handle(RdpsndServerContext* context)
1131 WINPR_ASSERT(context);
1132 WINPR_ASSERT(context->priv);
1134 return context->priv->channelEvent;
1151UINT rdpsnd_server_handle_messages(RdpsndServerContext* context)
1153 DWORD bytesReturned = 0;
1154 UINT ret = CHANNEL_RC_OK;
1155 RdpsndServerPrivate* priv =
nullptr;
1158 WINPR_ASSERT(context);
1159 WINPR_ASSERT(context->priv);
1161 priv = context->priv;
1162 s = priv->input_stream;
1164 if (!WTSVirtualChannelRead(priv->ChannelHandle, 0, Stream_Pointer(s), priv->expectedBytes,
1167 if (GetLastError() == ERROR_NO_DATA)
1168 return ERROR_NO_DATA;
1170 WLog_ERR(TAG,
"channel connection closed");
1171 return ERROR_INTERNAL_ERROR;
1174 priv->expectedBytes -= bytesReturned;
1175 Stream_Seek(s, bytesReturned);
1177 if (priv->expectedBytes)
1178 return CHANNEL_RC_OK;
1180 Stream_SealLength(s);
1181 Stream_SetPosition(s, 0);
1183 if (priv->waitingHeader)
1186 Stream_Read_UINT8(s, priv->msgType);
1187 Stream_Seek_UINT8(s);
1188 Stream_Read_UINT16(s, priv->expectedBytes);
1189 priv->waitingHeader = FALSE;
1190 Stream_SetPosition(s, 0);
1192 if (priv->expectedBytes)
1194 if (!Stream_EnsureCapacity(s, priv->expectedBytes))
1196 WLog_ERR(TAG,
"Stream_EnsureCapacity failed!");
1197 return CHANNEL_RC_NO_MEMORY;
1200 return CHANNEL_RC_OK;
1205#ifdef WITH_DEBUG_SND
1206 WLog_DBG(TAG,
"message type %" PRIu8
"", priv->msgType);
1208 priv->expectedBytes = 4;
1209 priv->waitingHeader = TRUE;
1211 switch (priv->msgType)
1213 case SNDC_WAVECONFIRM:
1214 ret = rdpsnd_server_recv_waveconfirm(context, s);
1218 ret = rdpsnd_server_recv_trainingconfirm(context, s);
1222 ret = rdpsnd_server_recv_formats(context, s);
1224 if ((ret == CHANNEL_RC_OK) && (context->clientVersion < CHANNEL_VERSION_WIN_7))
1225 IFCALL(context->Activated, context);
1229 case SNDC_QUALITYMODE:
1230 ret = rdpsnd_server_recv_quality_mode(context, s);
1232 if ((ret == CHANNEL_RC_OK) && (context->clientVersion >= CHANNEL_VERSION_WIN_7))
1233 IFCALL(context->Activated, context);
1238 WLog_ERR(TAG,
"UNKNOWN MESSAGE TYPE!! (0x%02" PRIX8
")", priv->msgType);
1239 ret = ERROR_INVALID_DATA;
1243 Stream_SetPosition(s, 0);