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] = { 0 };
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 = NULL;
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 freerdp_dsp_context_reset(context->priv->dsp_context, format, 0u);
419 LeaveCriticalSection(&context->priv->lock);
428static UINT rdpsnd_server_training(RdpsndServerContext* context, UINT16 timestamp, UINT16 packsize,
433 wStream* s = rdpsnd_server_get_buffer(context);
435 if (!Stream_EnsureRemainingCapacity(s, 8))
436 return ERROR_INTERNAL_ERROR;
438 Stream_Write_UINT8(s, SNDC_TRAINING);
439 Stream_Write_UINT8(s, 0);
440 Stream_Seek_UINT16(s);
441 Stream_Write_UINT16(s, timestamp);
442 Stream_Write_UINT16(s, packsize);
446 if (!Stream_EnsureRemainingCapacity(s, packsize))
448 Stream_SetPosition(s, 0);
449 return ERROR_INTERNAL_ERROR;
452 Stream_Write(s, data, packsize);
455 const size_t end = Stream_GetPosition(s);
456 if ((end < 4) || (end > UINT16_MAX))
457 return ERROR_INTERNAL_ERROR;
459 Stream_SetPosition(s, 2);
460 Stream_Write_UINT16(s, (UINT16)(end - 4));
462 status = WTSVirtualChannelWrite(context->priv->ChannelHandle, Stream_BufferAs(s,
char),
463 (UINT32)end, &written);
465 Stream_SetPosition(s, 0);
467 return status ? CHANNEL_RC_OK : ERROR_INTERNAL_ERROR;
470static BOOL rdpsnd_server_align_wave_pdu(
wStream* s, UINT32 alignment)
473 Stream_SealLength(s);
474 size = Stream_Length(s);
476 if ((size % alignment) != 0)
478 size_t offset = alignment - size % alignment;
480 if (!Stream_EnsureRemainingCapacity(s, offset))
483 Stream_Zero(s, offset);
486 Stream_SealLength(s);
496static UINT rdpsnd_server_send_wave_pdu(RdpsndServerContext* context, UINT16 wTimestamp)
500 UINT error = CHANNEL_RC_OK;
501 wStream* s = rdpsnd_server_get_buffer(context);
503 if (context->selected_client_format > context->num_client_formats)
504 return ERROR_INTERNAL_ERROR;
506 WINPR_ASSERT(context->client_formats);
508 format = &context->client_formats[context->selected_client_format];
510 Stream_SetPosition(s, 0);
512 if (!Stream_EnsureRemainingCapacity(s, 16))
513 return ERROR_OUTOFMEMORY;
515 Stream_Write_UINT8(s, SNDC_WAVE);
516 Stream_Write_UINT8(s, 0);
517 Stream_Write_UINT16(s, 0);
518 Stream_Write_UINT16(s, wTimestamp);
519 Stream_Write_UINT16(s, context->selected_client_format);
520 Stream_Write_UINT8(s, context->block_no);
522 const size_t start = Stream_GetPosition(s);
523 const BYTE* src = context->priv->out_buffer;
524 const size_t length =
525 1ull * context->priv->out_pending_frames * context->priv->src_bytes_per_frame;
527 if (!freerdp_dsp_encode(context->priv->dsp_context, context->src_format, src, length, s))
528 return ERROR_INTERNAL_ERROR;
531 if (!rdpsnd_server_align_wave_pdu(s, format->nBlockAlign))
532 return ERROR_INTERNAL_ERROR;
534 const size_t end = Stream_GetPosition(s);
535 const size_t pos = end - start + 8ULL;
536 if (pos > UINT16_MAX)
537 return ERROR_INTERNAL_ERROR;
538 Stream_SetPosition(s, 2);
539 Stream_Write_UINT16(s, (UINT16)pos);
540 Stream_SetPosition(s, end);
542 if (!WTSVirtualChannelWrite(context->priv->ChannelHandle, Stream_BufferAs(s,
char),
543 (UINT32)(start + 4), &written))
545 WLog_ERR(TAG,
"WTSVirtualChannelWrite failed!");
546 error = ERROR_INTERNAL_ERROR;
549 if (error != CHANNEL_RC_OK)
551 WLog_ERR(TAG,
"WTSVirtualChannelWrite failed!");
552 error = ERROR_INTERNAL_ERROR;
556 Stream_SetPosition(s, start);
557 Stream_Write_UINT32(s, 0);
558 Stream_SetPosition(s, start);
560 WINPR_ASSERT((end - start) <= UINT32_MAX);
561 if (!WTSVirtualChannelWrite(context->priv->ChannelHandle, Stream_Pointer(s),
562 (UINT32)(end - start), &written))
564 WLog_ERR(TAG,
"WTSVirtualChannelWrite failed!");
565 error = ERROR_INTERNAL_ERROR;
568 context->block_no = (context->block_no + 1) % 256;
571 Stream_SetPosition(s, 0);
572 context->priv->out_pending_frames = 0;
582static UINT rdpsnd_server_send_wave2_pdu(RdpsndServerContext* context, UINT16 formatNo,
583 const BYTE* data,
size_t size, BOOL encoded,
584 UINT16 timestamp, UINT32 audioTimeStamp)
587 UINT error = CHANNEL_RC_OK;
589 wStream* s = rdpsnd_server_get_buffer(context);
591 if (!Stream_EnsureRemainingCapacity(s, 16))
593 error = ERROR_INTERNAL_ERROR;
598 Stream_Write_UINT8(s, SNDC_WAVE2);
599 Stream_Write_UINT8(s, 0);
600 Stream_Write_UINT16(s, 0);
601 Stream_Write_UINT16(s, timestamp);
602 Stream_Write_UINT16(s, formatNo);
603 Stream_Write_UINT8(s, context->block_no);
604 Stream_Write_UINT8(s, 0);
605 Stream_Write_UINT8(s, 0);
606 Stream_Write_UINT8(s, 0);
607 Stream_Write_UINT32(s, audioTimeStamp);
611 if (!Stream_EnsureRemainingCapacity(s, size))
613 error = ERROR_INTERNAL_ERROR;
617 Stream_Write(s, data, size);
623 if (!freerdp_dsp_encode(context->priv->dsp_context, context->src_format, data, size, s))
625 error = ERROR_INTERNAL_ERROR;
629 format = &context->client_formats[formatNo];
630 if (!rdpsnd_server_align_wave_pdu(s, format->nBlockAlign))
632 error = ERROR_INTERNAL_ERROR;
638 const size_t end = Stream_GetPosition(s);
639 if (end > UINT16_MAX + 4)
641 error = ERROR_INTERNAL_ERROR;
645 Stream_SetPosition(s, 2);
646 Stream_Write_UINT16(s, (UINT16)(end - 4));
648 status = WTSVirtualChannelWrite(context->priv->ChannelHandle, Stream_BufferAs(s,
char),
649 (UINT32)end, &written);
651 if (!status || (end != written))
654 "WTSVirtualChannelWrite failed! [stream length=%" PRIuz
" - written=%" PRIu32,
656 error = ERROR_INTERNAL_ERROR;
660 context->block_no = (context->block_no + 1) % 256;
663 Stream_SetPosition(s, 0);
664 context->priv->out_pending_frames = 0;
669static UINT rdpsnd_server_send_audio_pdu(RdpsndServerContext* context, UINT16 wTimestamp)
671 const BYTE* src = NULL;
674 WINPR_ASSERT(context);
675 WINPR_ASSERT(context->priv);
677 if (context->selected_client_format >= context->num_client_formats)
678 return ERROR_INTERNAL_ERROR;
680 src = context->priv->out_buffer;
681 length = context->priv->out_pending_frames * context->priv->src_bytes_per_frame;
683 if (context->clientVersion >= CHANNEL_VERSION_WIN_8)
684 return rdpsnd_server_send_wave2_pdu(context, context->selected_client_format, src, length,
685 FALSE, wTimestamp, wTimestamp);
687 return rdpsnd_server_send_wave_pdu(context, wTimestamp);
695static UINT rdpsnd_server_send_samples(RdpsndServerContext* context,
const void* buf,
696 size_t nframes, UINT16 wTimestamp)
698 UINT error = CHANNEL_RC_OK;
700 WINPR_ASSERT(context);
701 WINPR_ASSERT(context->priv);
703 EnterCriticalSection(&context->priv->lock);
705 if (context->selected_client_format >= context->num_client_formats)
708 WLog_WARN(TAG,
"Drop samples because client format has not been negotiated.");
709 error = ERROR_NOT_READY;
715 const size_t cframes =
716 MIN(nframes, context->priv->out_frames - context->priv->out_pending_frames);
717 size_t cframesize = cframes * context->priv->src_bytes_per_frame;
718 CopyMemory(context->priv->out_buffer +
719 (context->priv->out_pending_frames * context->priv->src_bytes_per_frame),
721 buf = (
const BYTE*)buf + cframesize;
723 context->priv->out_pending_frames += cframes;
725 if (context->priv->out_pending_frames >= context->priv->out_frames)
727 if ((error = rdpsnd_server_send_audio_pdu(context, wTimestamp)))
729 WLog_ERR(TAG,
"rdpsnd_server_send_audio_pdu failed with error %" PRIu32
"", error);
736 LeaveCriticalSection(&context->priv->lock);
745static UINT rdpsnd_server_send_samples2(RdpsndServerContext* context, UINT16 formatNo,
746 const void* buf,
size_t size, UINT16 timestamp,
747 UINT32 audioTimeStamp)
749 UINT error = CHANNEL_RC_OK;
751 WINPR_ASSERT(context);
752 WINPR_ASSERT(context->priv);
754 if (context->clientVersion < CHANNEL_VERSION_WIN_8)
755 return ERROR_INTERNAL_ERROR;
757 EnterCriticalSection(&context->priv->lock);
760 rdpsnd_server_send_wave2_pdu(context, formatNo, buf, size, TRUE, timestamp, audioTimeStamp);
762 LeaveCriticalSection(&context->priv->lock);
772static UINT rdpsnd_server_set_volume(RdpsndServerContext* context, UINT16 left, UINT16 right)
776 wStream* s = rdpsnd_server_get_buffer(context);
778 if (!Stream_EnsureRemainingCapacity(s, 8))
779 return ERROR_NOT_ENOUGH_MEMORY;
781 Stream_Write_UINT8(s, SNDC_SETVOLUME);
782 Stream_Write_UINT8(s, 0);
783 Stream_Write_UINT16(s, 4);
784 Stream_Write_UINT16(s, left);
785 Stream_Write_UINT16(s, right);
787 const size_t len = Stream_GetPosition(s);
788 WINPR_ASSERT(len <= UINT32_MAX);
789 status = WTSVirtualChannelWrite(context->priv->ChannelHandle, Stream_BufferAs(s,
char),
790 (ULONG)len, &written);
791 Stream_SetPosition(s, 0);
792 return status ? CHANNEL_RC_OK : ERROR_INTERNAL_ERROR;
800static UINT rdpsnd_server_close(RdpsndServerContext* context)
804 UINT error = CHANNEL_RC_OK;
805 wStream* s = rdpsnd_server_get_buffer(context);
807 EnterCriticalSection(&context->priv->lock);
809 if (context->priv->out_pending_frames > 0)
811 if (context->selected_client_format >= context->num_client_formats)
813 WLog_ERR(TAG,
"Pending audio frame exists while no format selected.");
814 error = ERROR_INVALID_DATA;
816 else if ((error = rdpsnd_server_send_audio_pdu(context, 0)))
818 WLog_ERR(TAG,
"rdpsnd_server_send_audio_pdu failed with error %" PRIu32
"", error);
822 LeaveCriticalSection(&context->priv->lock);
827 context->selected_client_format = 0xFFFF;
829 if (!Stream_EnsureRemainingCapacity(s, 4))
830 return ERROR_OUTOFMEMORY;
832 Stream_Write_UINT8(s, SNDC_CLOSE);
833 Stream_Write_UINT8(s, 0);
834 Stream_Seek_UINT16(s);
835 const size_t pos = Stream_GetPosition(s);
836 WINPR_ASSERT(pos >= 4);
837 Stream_SetPosition(s, 2);
838 Stream_Write_UINT16(s, WINPR_ASSERTING_INT_CAST(uint16_t, pos - 4));
839 Stream_SetPosition(s, pos);
841 const size_t len = Stream_GetPosition(s);
842 WINPR_ASSERT(len <= UINT32_MAX);
843 status = WTSVirtualChannelWrite(context->priv->ChannelHandle, Stream_BufferAs(s,
char),
844 (UINT32)len, &written);
845 Stream_SetPosition(s, 0);
846 return status ? CHANNEL_RC_OK : ERROR_INTERNAL_ERROR;
854static UINT rdpsnd_server_start(RdpsndServerContext* context)
857 DWORD bytesReturned = 0;
858 RdpsndServerPrivate* priv = NULL;
859 UINT error = ERROR_INTERNAL_ERROR;
860 PULONG pSessionId = NULL;
862 WINPR_ASSERT(context);
863 WINPR_ASSERT(context->priv);
865 priv = context->priv;
866 priv->SessionId = WTS_CURRENT_SESSION;
868 if (context->use_dynamic_virtual_channel)
870 UINT32 channelId = 0;
873 if (WTSQuerySessionInformationA(context->vcm, WTS_CURRENT_SESSION, WTSSessionId,
874 (LPSTR*)&pSessionId, &bytesReturned))
876 priv->SessionId = (DWORD)*pSessionId;
877 WTSFreeMemory(pSessionId);
878 priv->ChannelHandle = WTSVirtualChannelOpenEx(priv->SessionId, RDPSND_DVC_CHANNEL_NAME,
879 WTS_CHANNEL_OPTION_DYNAMIC);
880 if (!priv->ChannelHandle)
882 WLog_ERR(TAG,
"Open audio dynamic virtual channel (%s) failed!",
883 RDPSND_DVC_CHANNEL_NAME);
884 return ERROR_INTERNAL_ERROR;
887 channelId = WTSChannelGetIdByHandle(priv->ChannelHandle);
889 IFCALLRET(context->ChannelIdAssigned, status, context, channelId);
892 WLog_ERR(TAG,
"context->ChannelIdAssigned failed!");
898 WLog_ERR(TAG,
"WTSQuerySessionInformationA failed!");
899 return ERROR_INTERNAL_ERROR;
904 priv->ChannelHandle =
905 WTSVirtualChannelOpen(context->vcm, WTS_CURRENT_SESSION, RDPSND_CHANNEL_NAME);
906 if (!priv->ChannelHandle)
908 WLog_ERR(TAG,
"Open audio static virtual channel (rdpsnd) failed!");
909 return ERROR_INTERNAL_ERROR;
913 if (!WTSVirtualChannelQuery(priv->ChannelHandle, WTSVirtualEventHandle, &buffer,
915 (bytesReturned !=
sizeof(HANDLE)))
918 "error during WTSVirtualChannelQuery(WTSVirtualEventHandle) or invalid returned "
923 WTSFreeMemory(buffer);
928 priv->channelEvent = *(HANDLE*)buffer;
929 WTSFreeMemory(buffer);
930 priv->rdpsnd_pdu = Stream_New(NULL, 4096);
932 if (!priv->rdpsnd_pdu)
934 WLog_ERR(TAG,
"Stream_New failed!");
935 error = CHANNEL_RC_NO_MEMORY;
939 if (!InitializeCriticalSectionEx(&context->priv->lock, 0, 0))
941 WLog_ERR(TAG,
"InitializeCriticalSectionEx failed!");
945 if ((error = rdpsnd_server_send_formats(context)))
947 WLog_ERR(TAG,
"rdpsnd_server_send_formats failed with error %" PRIu32
"", error);
953 context->priv->StopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
955 if (!context->priv->StopEvent)
957 WLog_ERR(TAG,
"CreateEvent failed!");
961 context->priv->Thread =
962 CreateThread(NULL, 0, rdpsnd_server_thread, (
void*)context, 0, NULL);
964 if (!context->priv->Thread)
966 WLog_ERR(TAG,
"CreateThread failed!");
971 return CHANNEL_RC_OK;
973 (void)CloseHandle(context->priv->StopEvent);
974 context->priv->StopEvent = NULL;
976 DeleteCriticalSection(&context->priv->lock);
978 Stream_Free(context->priv->rdpsnd_pdu, TRUE);
979 context->priv->rdpsnd_pdu = NULL;
981 (void)WTSVirtualChannelClose(context->priv->ChannelHandle);
982 context->priv->ChannelHandle = NULL;
991static UINT rdpsnd_server_stop(RdpsndServerContext* context)
993 UINT error = CHANNEL_RC_OK;
995 WINPR_ASSERT(context);
996 WINPR_ASSERT(context->priv);
998 if (!context->priv->StopEvent)
1001 if (context->priv->ownThread)
1003 if (context->priv->StopEvent)
1005 (void)SetEvent(context->priv->StopEvent);
1007 if (WaitForSingleObject(context->priv->Thread, INFINITE) == WAIT_FAILED)
1009 error = GetLastError();
1010 WLog_ERR(TAG,
"WaitForSingleObject failed with error %" PRIu32
"!", error);
1014 (void)CloseHandle(context->priv->Thread);
1015 (void)CloseHandle(context->priv->StopEvent);
1016 context->priv->Thread = NULL;
1017 context->priv->StopEvent = NULL;
1021 DeleteCriticalSection(&context->priv->lock);
1023 if (context->priv->rdpsnd_pdu)
1025 Stream_Free(context->priv->rdpsnd_pdu, TRUE);
1026 context->priv->rdpsnd_pdu = NULL;
1029 if (context->priv->ChannelHandle)
1031 (void)WTSVirtualChannelClose(context->priv->ChannelHandle);
1032 context->priv->ChannelHandle = NULL;
1038RdpsndServerContext* rdpsnd_server_context_new(HANDLE vcm)
1040 RdpsndServerPrivate* priv = NULL;
1041 RdpsndServerContext* context = (RdpsndServerContext*)calloc(1,
sizeof(RdpsndServerContext));
1047 context->Start = rdpsnd_server_start;
1048 context->Stop = rdpsnd_server_stop;
1049 context->selected_client_format = 0xFFFF;
1050 context->Initialize = rdpsnd_server_initialize;
1051 context->SendFormats = rdpsnd_server_send_formats;
1052 context->SelectFormat = rdpsnd_server_select_format;
1053 context->Training = rdpsnd_server_training;
1054 context->SendSamples = rdpsnd_server_send_samples;
1055 context->SendSamples2 = rdpsnd_server_send_samples2;
1056 context->SetVolume = rdpsnd_server_set_volume;
1057 context->Close = rdpsnd_server_close;
1058 context->priv = priv = (RdpsndServerPrivate*)calloc(1,
sizeof(RdpsndServerPrivate));
1062 WLog_ERR(TAG,
"calloc failed!");
1066 priv->dsp_context = freerdp_dsp_context_new(TRUE);
1068 if (!priv->dsp_context)
1070 WLog_ERR(TAG,
"freerdp_dsp_context_new failed!");
1074 priv->input_stream = Stream_New(NULL, 4);
1076 if (!priv->input_stream)
1078 WLog_ERR(TAG,
"Stream_New failed!");
1082 priv->expectedBytes = 4;
1083 priv->waitingHeader = TRUE;
1084 priv->ownThread = TRUE;
1087 WINPR_PRAGMA_DIAG_PUSH
1088 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
1089 rdpsnd_server_context_free(context);
1090 WINPR_PRAGMA_DIAG_POP
1094void rdpsnd_server_context_reset(RdpsndServerContext* context)
1096 WINPR_ASSERT(context);
1097 WINPR_ASSERT(context->priv);
1099 context->priv->expectedBytes = 4;
1100 context->priv->waitingHeader = TRUE;
1101 Stream_SetPosition(context->priv->input_stream, 0);
1104void rdpsnd_server_context_free(RdpsndServerContext* context)
1111 rdpsnd_server_stop(context);
1113 free(context->priv->out_buffer);
1115 if (context->priv->dsp_context)
1116 freerdp_dsp_context_free(context->priv->dsp_context);
1118 if (context->priv->input_stream)
1119 Stream_Free(context->priv->input_stream, TRUE);
1122 free(context->server_formats);
1123 free(context->client_formats);
1124 free(context->priv);
1128HANDLE rdpsnd_server_get_event_handle(RdpsndServerContext* context)
1130 WINPR_ASSERT(context);
1131 WINPR_ASSERT(context->priv);
1133 return context->priv->channelEvent;
1150UINT rdpsnd_server_handle_messages(RdpsndServerContext* context)
1152 DWORD bytesReturned = 0;
1153 UINT ret = CHANNEL_RC_OK;
1154 RdpsndServerPrivate* priv = NULL;
1157 WINPR_ASSERT(context);
1158 WINPR_ASSERT(context->priv);
1160 priv = context->priv;
1161 s = priv->input_stream;
1163 if (!WTSVirtualChannelRead(priv->ChannelHandle, 0, Stream_Pointer(s), priv->expectedBytes,
1166 if (GetLastError() == ERROR_NO_DATA)
1167 return ERROR_NO_DATA;
1169 WLog_ERR(TAG,
"channel connection closed");
1170 return ERROR_INTERNAL_ERROR;
1173 priv->expectedBytes -= bytesReturned;
1174 Stream_Seek(s, bytesReturned);
1176 if (priv->expectedBytes)
1177 return CHANNEL_RC_OK;
1179 Stream_SealLength(s);
1180 Stream_SetPosition(s, 0);
1182 if (priv->waitingHeader)
1185 Stream_Read_UINT8(s, priv->msgType);
1186 Stream_Seek_UINT8(s);
1187 Stream_Read_UINT16(s, priv->expectedBytes);
1188 priv->waitingHeader = FALSE;
1189 Stream_SetPosition(s, 0);
1191 if (priv->expectedBytes)
1193 if (!Stream_EnsureCapacity(s, priv->expectedBytes))
1195 WLog_ERR(TAG,
"Stream_EnsureCapacity failed!");
1196 return CHANNEL_RC_NO_MEMORY;
1199 return CHANNEL_RC_OK;
1204#ifdef WITH_DEBUG_SND
1205 WLog_DBG(TAG,
"message type %" PRIu8
"", priv->msgType);
1207 priv->expectedBytes = 4;
1208 priv->waitingHeader = TRUE;
1210 switch (priv->msgType)
1212 case SNDC_WAVECONFIRM:
1213 ret = rdpsnd_server_recv_waveconfirm(context, s);
1217 ret = rdpsnd_server_recv_trainingconfirm(context, s);
1221 ret = rdpsnd_server_recv_formats(context, s);
1223 if ((ret == CHANNEL_RC_OK) && (context->clientVersion < CHANNEL_VERSION_WIN_7))
1224 IFCALL(context->Activated, context);
1228 case SNDC_QUALITYMODE:
1229 ret = rdpsnd_server_recv_quality_mode(context, s);
1231 if ((ret == CHANNEL_RC_OK) && (context->clientVersion >= CHANNEL_VERSION_WIN_7))
1232 IFCALL(context->Activated, context);
1237 WLog_ERR(TAG,
"UNKNOWN MESSAGE TYPE!! (0x%02" PRIX8
")", priv->msgType);
1238 ret = ERROR_INVALID_DATA;
1242 Stream_SetPosition(s, 0);