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))
86 const size_t pos = Stream_GetPosition(s);
90 WINPR_ASSERT(pos >= 4);
91 Stream_SetPosition(s, 2);
92 Stream_Write_UINT16(s, (UINT16)(pos - 4));
93 Stream_SetPosition(s, pos);
95 WINPR_ASSERT(context->priv);
97 status = WTSVirtualChannelWrite(context->priv->ChannelHandle, Stream_BufferAs(s,
char),
98 (UINT32)pos, &written);
99 Stream_SetPosition(s, 0);
101 return status ? CHANNEL_RC_OK : ERROR_INTERNAL_ERROR;
109static UINT rdpsnd_server_recv_waveconfirm(RdpsndServerContext* context,
wStream* s)
111 UINT16 timestamp = 0;
112 BYTE confirmBlockNum = 0;
113 UINT error = CHANNEL_RC_OK;
115 WINPR_ASSERT(context);
117 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
118 return ERROR_INVALID_DATA;
120 Stream_Read_UINT16(s, timestamp);
121 Stream_Read_UINT8(s, confirmBlockNum);
122 Stream_Seek_UINT8(s);
123 IFCALLRET(context->ConfirmBlock, error, context, confirmBlockNum, timestamp);
126 WLog_ERR(TAG,
"context->ConfirmBlock failed with error %" PRIu32
"", error);
136static UINT rdpsnd_server_recv_trainingconfirm(RdpsndServerContext* context,
wStream* s)
138 UINT16 timestamp = 0;
140 UINT error = CHANNEL_RC_OK;
142 WINPR_ASSERT(context);
144 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
145 return ERROR_INVALID_DATA;
147 Stream_Read_UINT16(s, timestamp);
148 Stream_Read_UINT16(s, packsize);
150 IFCALLRET(context->TrainingConfirm, error, context, timestamp, packsize);
152 WLog_ERR(TAG,
"context->TrainingConfirm failed with error %" PRIu32
"", error);
162static UINT rdpsnd_server_recv_quality_mode(RdpsndServerContext* context,
wStream* s)
164 WINPR_ASSERT(context);
166 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
168 WLog_ERR(TAG,
"not enough data in stream!");
169 return ERROR_INVALID_DATA;
172 Stream_Read_UINT16(s, context->qualityMode);
173 Stream_Seek_UINT16(s);
175 WLog_DBG(TAG,
"Client requested sound quality: 0x%04" PRIX16
"", context->qualityMode);
177 return CHANNEL_RC_OK;
185static UINT rdpsnd_server_recv_formats(RdpsndServerContext* context,
wStream* s)
187 UINT error = CHANNEL_RC_OK;
189 WINPR_ASSERT(context);
191 if (!Stream_CheckAndLogRequiredLength(TAG, s, 20))
192 return ERROR_INVALID_DATA;
194 Stream_Read_UINT32(s, context->capsFlags);
195 Stream_Read_UINT32(s, context->initialVolume);
196 Stream_Read_UINT32(s, context->initialPitch);
197 Stream_Read_UINT16(s, context->udpPort);
198 Stream_Read_UINT16(s, context->num_client_formats);
199 Stream_Read_UINT8(s, context->lastblock);
200 Stream_Read_UINT16(s, context->clientVersion);
201 Stream_Seek_UINT8(s);
204 if (!Stream_CheckAndLogRequiredLengthOfSize(TAG, s, context->num_client_formats, 18ull))
205 return ERROR_INVALID_DATA;
207 if (!context->num_client_formats)
209 WLog_ERR(TAG,
"client doesn't support any format!");
210 return ERROR_INTERNAL_ERROR;
213 context->client_formats = audio_formats_new(context->num_client_formats);
215 if (!context->client_formats)
217 WLog_ERR(TAG,
"calloc failed!");
218 return CHANNEL_RC_NO_MEMORY;
221 for (UINT16 i = 0; i < context->num_client_formats; i++)
225 if (!Stream_CheckAndLogRequiredLength(TAG, s, 18))
227 WLog_ERR(TAG,
"not enough data in stream!");
228 error = ERROR_INVALID_DATA;
232 Stream_Read_UINT16(s, format->wFormatTag);
233 Stream_Read_UINT16(s, format->nChannels);
234 Stream_Read_UINT32(s, format->nSamplesPerSec);
235 Stream_Read_UINT32(s, format->nAvgBytesPerSec);
236 Stream_Read_UINT16(s, format->nBlockAlign);
237 Stream_Read_UINT16(s, format->wBitsPerSample);
238 Stream_Read_UINT16(s, format->cbSize);
240 if (format->cbSize > 0)
242 if (!Stream_SafeSeek(s, format->cbSize))
244 WLog_ERR(TAG,
"Stream_SafeSeek failed!");
245 error = ERROR_INTERNAL_ERROR;
251 if (!context->num_client_formats)
253 WLog_ERR(TAG,
"client doesn't support any known format!");
257 return CHANNEL_RC_OK;
259 free(context->client_formats);
263static DWORD WINAPI rdpsnd_server_thread(LPVOID arg)
267 HANDLE events[2] = { 0 };
268 RdpsndServerContext* context = (RdpsndServerContext*)arg;
269 UINT error = CHANNEL_RC_OK;
271 WINPR_ASSERT(context);
272 WINPR_ASSERT(context->priv);
274 events[nCount++] = context->priv->channelEvent;
275 events[nCount++] = context->priv->StopEvent;
277 WINPR_ASSERT(nCount <= ARRAYSIZE(events));
281 status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE);
283 if (status == WAIT_FAILED)
285 error = GetLastError();
286 WLog_ERR(TAG,
"WaitForMultipleObjects failed with error %" PRIu32
"!", error);
290 status = WaitForSingleObject(context->priv->StopEvent, 0);
292 if (status == WAIT_FAILED)
294 error = GetLastError();
295 WLog_ERR(TAG,
"WaitForSingleObject failed with error %" PRIu32
"!", error);
299 if (status == WAIT_OBJECT_0)
302 if ((error = rdpsnd_server_handle_messages(context)))
304 WLog_ERR(TAG,
"rdpsnd_server_handle_messages failed with error %" PRIu32
"", error);
309 if (error && context->rdpcontext)
310 setChannelError(context->rdpcontext, error,
"rdpsnd_server_thread reported an error");
321static UINT rdpsnd_server_initialize(RdpsndServerContext* context, BOOL ownThread)
323 WINPR_ASSERT(context);
324 WINPR_ASSERT(context->priv);
326 context->priv->ownThread = ownThread;
327 return context->Start(context);
335static UINT rdpsnd_server_select_format(RdpsndServerContext* context, UINT16 client_format_index)
338 size_t out_buffer_size = 0;
340 UINT error = CHANNEL_RC_OK;
342 WINPR_ASSERT(context);
343 WINPR_ASSERT(context->priv);
345 if ((client_format_index >= context->num_client_formats) || (!context->src_format))
347 WLog_ERR(TAG,
"index %" PRIu16
" is not correct.", client_format_index);
348 return ERROR_INVALID_DATA;
351 EnterCriticalSection(&context->priv->lock);
352 context->priv->src_bytes_per_sample = context->src_format->wBitsPerSample / 8;
353 context->priv->src_bytes_per_frame =
354 context->priv->src_bytes_per_sample * context->src_format->nChannels;
355 context->selected_client_format = client_format_index;
356 format = &context->client_formats[client_format_index];
358 if (format->nSamplesPerSec == 0)
360 WLog_ERR(TAG,
"invalid Client Sound Format!!");
361 error = ERROR_INVALID_DATA;
365 if (context->latency <= 0)
366 context->latency = 50;
368 context->priv->out_frames = context->src_format->nSamplesPerSec * context->latency / 1000;
370 if (context->priv->out_frames < 1)
371 context->priv->out_frames = 1;
373 switch (format->wFormatTag)
375 case WAVE_FORMAT_DVI_ADPCM:
376 bs = 4ULL * (format->nBlockAlign - 4ULL * format->nChannels);
377 context->priv->out_frames -= context->priv->out_frames % bs;
379 if (context->priv->out_frames < bs)
380 context->priv->out_frames = bs;
384 case WAVE_FORMAT_ADPCM:
385 bs = (format->nBlockAlign - 7 * format->nChannels) * 2 / format->nChannels + 2;
386 context->priv->out_frames -= context->priv->out_frames % bs;
388 if (context->priv->out_frames < bs)
389 context->priv->out_frames = bs;
396 context->priv->out_pending_frames = 0;
397 out_buffer_size = context->priv->out_frames * context->priv->src_bytes_per_frame;
399 if (context->priv->out_buffer_size < out_buffer_size)
401 BYTE* newBuffer = NULL;
402 newBuffer = (BYTE*)realloc(context->priv->out_buffer, out_buffer_size);
406 WLog_ERR(TAG,
"realloc failed!");
407 error = CHANNEL_RC_NO_MEMORY;
411 context->priv->out_buffer = newBuffer;
412 context->priv->out_buffer_size = out_buffer_size;
415 freerdp_dsp_context_reset(context->priv->dsp_context, format, 0u);
417 LeaveCriticalSection(&context->priv->lock);
426static UINT rdpsnd_server_training(RdpsndServerContext* context, UINT16 timestamp, UINT16 packsize,
431 wStream* s = rdpsnd_server_get_buffer(context);
433 if (!Stream_EnsureRemainingCapacity(s, 8))
434 return ERROR_INTERNAL_ERROR;
436 Stream_Write_UINT8(s, SNDC_TRAINING);
437 Stream_Write_UINT8(s, 0);
438 Stream_Seek_UINT16(s);
439 Stream_Write_UINT16(s, timestamp);
440 Stream_Write_UINT16(s, packsize);
444 if (!Stream_EnsureRemainingCapacity(s, packsize))
446 Stream_SetPosition(s, 0);
447 return ERROR_INTERNAL_ERROR;
450 Stream_Write(s, data, packsize);
453 const size_t end = Stream_GetPosition(s);
454 if ((end < 4) || (end > UINT16_MAX))
455 return ERROR_INTERNAL_ERROR;
457 Stream_SetPosition(s, 2);
458 Stream_Write_UINT16(s, (UINT16)(end - 4));
460 status = WTSVirtualChannelWrite(context->priv->ChannelHandle, Stream_BufferAs(s,
char),
461 (UINT32)end, &written);
463 Stream_SetPosition(s, 0);
465 return status ? CHANNEL_RC_OK : ERROR_INTERNAL_ERROR;
468static BOOL rdpsnd_server_align_wave_pdu(
wStream* s, UINT32 alignment)
471 Stream_SealLength(s);
472 size = Stream_Length(s);
474 if ((size % alignment) != 0)
476 size_t offset = alignment - size % alignment;
478 if (!Stream_EnsureRemainingCapacity(s, offset))
481 Stream_Zero(s, offset);
484 Stream_SealLength(s);
494static UINT rdpsnd_server_send_wave_pdu(RdpsndServerContext* context, UINT16 wTimestamp)
498 UINT error = CHANNEL_RC_OK;
499 wStream* s = rdpsnd_server_get_buffer(context);
501 if (context->selected_client_format > context->num_client_formats)
502 return ERROR_INTERNAL_ERROR;
504 WINPR_ASSERT(context->client_formats);
506 format = &context->client_formats[context->selected_client_format];
508 Stream_SetPosition(s, 0);
510 if (!Stream_EnsureRemainingCapacity(s, 16))
511 return ERROR_OUTOFMEMORY;
513 Stream_Write_UINT8(s, SNDC_WAVE);
514 Stream_Write_UINT8(s, 0);
515 Stream_Write_UINT16(s, 0);
516 Stream_Write_UINT16(s, wTimestamp);
517 Stream_Write_UINT16(s, context->selected_client_format);
518 Stream_Write_UINT8(s, context->block_no);
520 const size_t start = Stream_GetPosition(s);
521 const BYTE* src = context->priv->out_buffer;
522 const size_t length =
523 1ull * context->priv->out_pending_frames * context->priv->src_bytes_per_frame;
525 if (!freerdp_dsp_encode(context->priv->dsp_context, context->src_format, src, length, s))
526 return ERROR_INTERNAL_ERROR;
529 if (!rdpsnd_server_align_wave_pdu(s, format->nBlockAlign))
530 return ERROR_INTERNAL_ERROR;
532 const size_t end = Stream_GetPosition(s);
533 const size_t pos = end - start + 8ULL;
534 if (pos > UINT16_MAX)
535 return ERROR_INTERNAL_ERROR;
536 Stream_SetPosition(s, 2);
537 Stream_Write_UINT16(s, (UINT16)pos);
538 Stream_SetPosition(s, end);
540 if (!WTSVirtualChannelWrite(context->priv->ChannelHandle, Stream_BufferAs(s,
char),
541 (UINT32)(start + 4), &written))
543 WLog_ERR(TAG,
"WTSVirtualChannelWrite failed!");
544 error = ERROR_INTERNAL_ERROR;
547 if (error != CHANNEL_RC_OK)
549 WLog_ERR(TAG,
"WTSVirtualChannelWrite failed!");
550 error = ERROR_INTERNAL_ERROR;
554 Stream_SetPosition(s, start);
555 Stream_Write_UINT32(s, 0);
556 Stream_SetPosition(s, start);
558 WINPR_ASSERT((end - start) <= UINT32_MAX);
559 if (!WTSVirtualChannelWrite(context->priv->ChannelHandle, Stream_Pointer(s),
560 (UINT32)(end - start), &written))
562 WLog_ERR(TAG,
"WTSVirtualChannelWrite failed!");
563 error = ERROR_INTERNAL_ERROR;
566 context->block_no = (context->block_no + 1) % 256;
569 Stream_SetPosition(s, 0);
570 context->priv->out_pending_frames = 0;
580static UINT rdpsnd_server_send_wave2_pdu(RdpsndServerContext* context, UINT16 formatNo,
581 const BYTE* data,
size_t size, BOOL encoded,
582 UINT16 timestamp, UINT32 audioTimeStamp)
585 UINT error = CHANNEL_RC_OK;
587 wStream* s = rdpsnd_server_get_buffer(context);
589 if (!Stream_EnsureRemainingCapacity(s, 16))
591 error = ERROR_INTERNAL_ERROR;
596 Stream_Write_UINT8(s, SNDC_WAVE2);
597 Stream_Write_UINT8(s, 0);
598 Stream_Write_UINT16(s, 0);
599 Stream_Write_UINT16(s, timestamp);
600 Stream_Write_UINT16(s, formatNo);
601 Stream_Write_UINT8(s, context->block_no);
602 Stream_Write_UINT8(s, 0);
603 Stream_Write_UINT8(s, 0);
604 Stream_Write_UINT8(s, 0);
605 Stream_Write_UINT32(s, audioTimeStamp);
609 if (!Stream_EnsureRemainingCapacity(s, size))
611 error = ERROR_INTERNAL_ERROR;
615 Stream_Write(s, data, size);
621 if (!freerdp_dsp_encode(context->priv->dsp_context, context->src_format, data, size, s))
623 error = ERROR_INTERNAL_ERROR;
627 format = &context->client_formats[formatNo];
628 if (!rdpsnd_server_align_wave_pdu(s, format->nBlockAlign))
630 error = ERROR_INTERNAL_ERROR;
635 const size_t end = Stream_GetPosition(s);
636 if (end > UINT16_MAX + 4)
638 error = ERROR_INTERNAL_ERROR;
642 Stream_SetPosition(s, 2);
643 Stream_Write_UINT16(s, (UINT16)(end - 4));
645 status = WTSVirtualChannelWrite(context->priv->ChannelHandle, Stream_BufferAs(s,
char),
646 (UINT32)end, &written);
648 if (!status || (end != written))
650 WLog_ERR(TAG,
"WTSVirtualChannelWrite failed! [stream length=%" PRIuz
" - written=%" PRIu32,
652 error = ERROR_INTERNAL_ERROR;
655 context->block_no = (context->block_no + 1) % 256;
658 Stream_SetPosition(s, 0);
659 context->priv->out_pending_frames = 0;
664static UINT rdpsnd_server_send_audio_pdu(RdpsndServerContext* context, UINT16 wTimestamp)
666 const BYTE* src = NULL;
669 WINPR_ASSERT(context);
670 WINPR_ASSERT(context->priv);
672 if (context->selected_client_format >= context->num_client_formats)
673 return ERROR_INTERNAL_ERROR;
675 src = context->priv->out_buffer;
676 length = context->priv->out_pending_frames * context->priv->src_bytes_per_frame;
678 if (context->clientVersion >= CHANNEL_VERSION_WIN_8)
679 return rdpsnd_server_send_wave2_pdu(context, context->selected_client_format, src, length,
680 FALSE, wTimestamp, wTimestamp);
682 return rdpsnd_server_send_wave_pdu(context, wTimestamp);
690static UINT rdpsnd_server_send_samples(RdpsndServerContext* context,
const void* buf,
691 size_t nframes, UINT16 wTimestamp)
693 UINT error = CHANNEL_RC_OK;
695 WINPR_ASSERT(context);
696 WINPR_ASSERT(context->priv);
698 EnterCriticalSection(&context->priv->lock);
700 if (context->selected_client_format >= context->num_client_formats)
703 WLog_WARN(TAG,
"Drop samples because client format has not been negotiated.");
704 error = ERROR_NOT_READY;
710 const size_t cframes =
711 MIN(nframes, context->priv->out_frames - context->priv->out_pending_frames);
712 size_t cframesize = cframes * context->priv->src_bytes_per_frame;
713 CopyMemory(context->priv->out_buffer +
714 (context->priv->out_pending_frames * context->priv->src_bytes_per_frame),
716 buf = (
const BYTE*)buf + cframesize;
718 context->priv->out_pending_frames += cframes;
720 if (context->priv->out_pending_frames >= context->priv->out_frames)
722 if ((error = rdpsnd_server_send_audio_pdu(context, wTimestamp)))
724 WLog_ERR(TAG,
"rdpsnd_server_send_audio_pdu failed with error %" PRIu32
"", error);
731 LeaveCriticalSection(&context->priv->lock);
740static UINT rdpsnd_server_send_samples2(RdpsndServerContext* context, UINT16 formatNo,
741 const void* buf,
size_t size, UINT16 timestamp,
742 UINT32 audioTimeStamp)
744 UINT error = CHANNEL_RC_OK;
746 WINPR_ASSERT(context);
747 WINPR_ASSERT(context->priv);
749 if (context->clientVersion < CHANNEL_VERSION_WIN_8)
750 return ERROR_INTERNAL_ERROR;
752 EnterCriticalSection(&context->priv->lock);
755 rdpsnd_server_send_wave2_pdu(context, formatNo, buf, size, TRUE, timestamp, audioTimeStamp);
757 LeaveCriticalSection(&context->priv->lock);
767static UINT rdpsnd_server_set_volume(RdpsndServerContext* context, UINT16 left, UINT16 right)
771 wStream* s = rdpsnd_server_get_buffer(context);
773 if (!Stream_EnsureRemainingCapacity(s, 8))
774 return ERROR_NOT_ENOUGH_MEMORY;
776 Stream_Write_UINT8(s, SNDC_SETVOLUME);
777 Stream_Write_UINT8(s, 0);
778 Stream_Write_UINT16(s, 4);
779 Stream_Write_UINT16(s, left);
780 Stream_Write_UINT16(s, right);
782 const size_t len = Stream_GetPosition(s);
783 WINPR_ASSERT(len <= UINT32_MAX);
784 status = WTSVirtualChannelWrite(context->priv->ChannelHandle, Stream_BufferAs(s,
char),
785 (ULONG)len, &written);
786 Stream_SetPosition(s, 0);
787 return status ? CHANNEL_RC_OK : ERROR_INTERNAL_ERROR;
795static UINT rdpsnd_server_close(RdpsndServerContext* context)
799 UINT error = CHANNEL_RC_OK;
800 wStream* s = rdpsnd_server_get_buffer(context);
802 EnterCriticalSection(&context->priv->lock);
804 if (context->priv->out_pending_frames > 0)
806 if (context->selected_client_format >= context->num_client_formats)
808 WLog_ERR(TAG,
"Pending audio frame exists while no format selected.");
809 error = ERROR_INVALID_DATA;
811 else if ((error = rdpsnd_server_send_audio_pdu(context, 0)))
813 WLog_ERR(TAG,
"rdpsnd_server_send_audio_pdu failed with error %" PRIu32
"", error);
817 LeaveCriticalSection(&context->priv->lock);
822 context->selected_client_format = 0xFFFF;
824 if (!Stream_EnsureRemainingCapacity(s, 4))
825 return ERROR_OUTOFMEMORY;
827 Stream_Write_UINT8(s, SNDC_CLOSE);
828 Stream_Write_UINT8(s, 0);
829 Stream_Seek_UINT16(s);
830 const size_t pos = Stream_GetPosition(s);
831 WINPR_ASSERT(pos >= 4);
832 Stream_SetPosition(s, 2);
833 Stream_Write_UINT16(s, WINPR_ASSERTING_INT_CAST(uint16_t, pos - 4));
834 Stream_SetPosition(s, pos);
836 const size_t len = Stream_GetPosition(s);
837 WINPR_ASSERT(len <= UINT32_MAX);
838 status = WTSVirtualChannelWrite(context->priv->ChannelHandle, Stream_BufferAs(s,
char),
839 (UINT32)len, &written);
840 Stream_SetPosition(s, 0);
841 return status ? CHANNEL_RC_OK : ERROR_INTERNAL_ERROR;
849static UINT rdpsnd_server_start(RdpsndServerContext* context)
852 DWORD bytesReturned = 0;
853 RdpsndServerPrivate* priv = NULL;
854 UINT error = ERROR_INTERNAL_ERROR;
855 PULONG pSessionId = NULL;
857 WINPR_ASSERT(context);
858 WINPR_ASSERT(context->priv);
860 priv = context->priv;
861 priv->SessionId = WTS_CURRENT_SESSION;
863 if (context->use_dynamic_virtual_channel)
865 UINT32 channelId = 0;
868 if (WTSQuerySessionInformationA(context->vcm, WTS_CURRENT_SESSION, WTSSessionId,
869 (LPSTR*)&pSessionId, &bytesReturned))
871 priv->SessionId = (DWORD)*pSessionId;
872 WTSFreeMemory(pSessionId);
873 priv->ChannelHandle = WTSVirtualChannelOpenEx(priv->SessionId, RDPSND_DVC_CHANNEL_NAME,
874 WTS_CHANNEL_OPTION_DYNAMIC);
875 if (!priv->ChannelHandle)
877 WLog_ERR(TAG,
"Open audio dynamic virtual channel (%s) failed!",
878 RDPSND_DVC_CHANNEL_NAME);
879 return ERROR_INTERNAL_ERROR;
882 channelId = WTSChannelGetIdByHandle(priv->ChannelHandle);
884 IFCALLRET(context->ChannelIdAssigned, status, context, channelId);
887 WLog_ERR(TAG,
"context->ChannelIdAssigned failed!");
893 WLog_ERR(TAG,
"WTSQuerySessionInformationA failed!");
894 return ERROR_INTERNAL_ERROR;
899 priv->ChannelHandle =
900 WTSVirtualChannelOpen(context->vcm, WTS_CURRENT_SESSION, RDPSND_CHANNEL_NAME);
901 if (!priv->ChannelHandle)
903 WLog_ERR(TAG,
"Open audio static virtual channel (rdpsnd) failed!");
904 return ERROR_INTERNAL_ERROR;
908 if (!WTSVirtualChannelQuery(priv->ChannelHandle, WTSVirtualEventHandle, &buffer,
910 (bytesReturned !=
sizeof(HANDLE)))
913 "error during WTSVirtualChannelQuery(WTSVirtualEventHandle) or invalid returned "
918 WTSFreeMemory(buffer);
923 priv->channelEvent = *(HANDLE*)buffer;
924 WTSFreeMemory(buffer);
925 priv->rdpsnd_pdu = Stream_New(NULL, 4096);
927 if (!priv->rdpsnd_pdu)
929 WLog_ERR(TAG,
"Stream_New failed!");
930 error = CHANNEL_RC_NO_MEMORY;
934 if (!InitializeCriticalSectionEx(&context->priv->lock, 0, 0))
936 WLog_ERR(TAG,
"InitializeCriticalSectionEx failed!");
940 if ((error = rdpsnd_server_send_formats(context)))
942 WLog_ERR(TAG,
"rdpsnd_server_send_formats failed with error %" PRIu32
"", error);
948 context->priv->StopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
950 if (!context->priv->StopEvent)
952 WLog_ERR(TAG,
"CreateEvent failed!");
956 context->priv->Thread =
957 CreateThread(NULL, 0, rdpsnd_server_thread, (
void*)context, 0, NULL);
959 if (!context->priv->Thread)
961 WLog_ERR(TAG,
"CreateThread failed!");
966 return CHANNEL_RC_OK;
968 (void)CloseHandle(context->priv->StopEvent);
969 context->priv->StopEvent = NULL;
971 DeleteCriticalSection(&context->priv->lock);
973 Stream_Free(context->priv->rdpsnd_pdu, TRUE);
974 context->priv->rdpsnd_pdu = NULL;
976 (void)WTSVirtualChannelClose(context->priv->ChannelHandle);
977 context->priv->ChannelHandle = NULL;
986static UINT rdpsnd_server_stop(RdpsndServerContext* context)
988 UINT error = CHANNEL_RC_OK;
990 WINPR_ASSERT(context);
991 WINPR_ASSERT(context->priv);
993 if (!context->priv->StopEvent)
996 if (context->priv->ownThread)
998 if (context->priv->StopEvent)
1000 (void)SetEvent(context->priv->StopEvent);
1002 if (WaitForSingleObject(context->priv->Thread, INFINITE) == WAIT_FAILED)
1004 error = GetLastError();
1005 WLog_ERR(TAG,
"WaitForSingleObject failed with error %" PRIu32
"!", error);
1009 (void)CloseHandle(context->priv->Thread);
1010 (void)CloseHandle(context->priv->StopEvent);
1011 context->priv->Thread = NULL;
1012 context->priv->StopEvent = NULL;
1016 DeleteCriticalSection(&context->priv->lock);
1018 if (context->priv->rdpsnd_pdu)
1020 Stream_Free(context->priv->rdpsnd_pdu, TRUE);
1021 context->priv->rdpsnd_pdu = NULL;
1024 if (context->priv->ChannelHandle)
1026 (void)WTSVirtualChannelClose(context->priv->ChannelHandle);
1027 context->priv->ChannelHandle = NULL;
1033RdpsndServerContext* rdpsnd_server_context_new(HANDLE vcm)
1035 RdpsndServerPrivate* priv = NULL;
1036 RdpsndServerContext* context = (RdpsndServerContext*)calloc(1,
sizeof(RdpsndServerContext));
1042 context->Start = rdpsnd_server_start;
1043 context->Stop = rdpsnd_server_stop;
1044 context->selected_client_format = 0xFFFF;
1045 context->Initialize = rdpsnd_server_initialize;
1046 context->SendFormats = rdpsnd_server_send_formats;
1047 context->SelectFormat = rdpsnd_server_select_format;
1048 context->Training = rdpsnd_server_training;
1049 context->SendSamples = rdpsnd_server_send_samples;
1050 context->SendSamples2 = rdpsnd_server_send_samples2;
1051 context->SetVolume = rdpsnd_server_set_volume;
1052 context->Close = rdpsnd_server_close;
1053 context->priv = priv = (RdpsndServerPrivate*)calloc(1,
sizeof(RdpsndServerPrivate));
1057 WLog_ERR(TAG,
"calloc failed!");
1061 priv->dsp_context = freerdp_dsp_context_new(TRUE);
1063 if (!priv->dsp_context)
1065 WLog_ERR(TAG,
"freerdp_dsp_context_new failed!");
1069 priv->input_stream = Stream_New(NULL, 4);
1071 if (!priv->input_stream)
1073 WLog_ERR(TAG,
"Stream_New failed!");
1077 priv->expectedBytes = 4;
1078 priv->waitingHeader = TRUE;
1079 priv->ownThread = TRUE;
1082 WINPR_PRAGMA_DIAG_PUSH
1083 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
1084 rdpsnd_server_context_free(context);
1085 WINPR_PRAGMA_DIAG_POP
1089void rdpsnd_server_context_reset(RdpsndServerContext* context)
1091 WINPR_ASSERT(context);
1092 WINPR_ASSERT(context->priv);
1094 context->priv->expectedBytes = 4;
1095 context->priv->waitingHeader = TRUE;
1096 Stream_SetPosition(context->priv->input_stream, 0);
1099void rdpsnd_server_context_free(RdpsndServerContext* context)
1106 rdpsnd_server_stop(context);
1108 free(context->priv->out_buffer);
1110 if (context->priv->dsp_context)
1111 freerdp_dsp_context_free(context->priv->dsp_context);
1113 if (context->priv->input_stream)
1114 Stream_Free(context->priv->input_stream, TRUE);
1117 free(context->server_formats);
1118 free(context->client_formats);
1119 free(context->priv);
1123HANDLE rdpsnd_server_get_event_handle(RdpsndServerContext* context)
1125 WINPR_ASSERT(context);
1126 WINPR_ASSERT(context->priv);
1128 return context->priv->channelEvent;
1145UINT rdpsnd_server_handle_messages(RdpsndServerContext* context)
1147 DWORD bytesReturned = 0;
1148 UINT ret = CHANNEL_RC_OK;
1149 RdpsndServerPrivate* priv = NULL;
1152 WINPR_ASSERT(context);
1153 WINPR_ASSERT(context->priv);
1155 priv = context->priv;
1156 s = priv->input_stream;
1158 if (!WTSVirtualChannelRead(priv->ChannelHandle, 0, Stream_Pointer(s), priv->expectedBytes,
1161 if (GetLastError() == ERROR_NO_DATA)
1162 return ERROR_NO_DATA;
1164 WLog_ERR(TAG,
"channel connection closed");
1165 return ERROR_INTERNAL_ERROR;
1168 priv->expectedBytes -= bytesReturned;
1169 Stream_Seek(s, bytesReturned);
1171 if (priv->expectedBytes)
1172 return CHANNEL_RC_OK;
1174 Stream_SealLength(s);
1175 Stream_SetPosition(s, 0);
1177 if (priv->waitingHeader)
1180 Stream_Read_UINT8(s, priv->msgType);
1181 Stream_Seek_UINT8(s);
1182 Stream_Read_UINT16(s, priv->expectedBytes);
1183 priv->waitingHeader = FALSE;
1184 Stream_SetPosition(s, 0);
1186 if (priv->expectedBytes)
1188 if (!Stream_EnsureCapacity(s, priv->expectedBytes))
1190 WLog_ERR(TAG,
"Stream_EnsureCapacity failed!");
1191 return CHANNEL_RC_NO_MEMORY;
1194 return CHANNEL_RC_OK;
1199#ifdef WITH_DEBUG_SND
1200 WLog_DBG(TAG,
"message type %" PRIu8
"", priv->msgType);
1202 priv->expectedBytes = 4;
1203 priv->waitingHeader = TRUE;
1205 switch (priv->msgType)
1207 case SNDC_WAVECONFIRM:
1208 ret = rdpsnd_server_recv_waveconfirm(context, s);
1212 ret = rdpsnd_server_recv_trainingconfirm(context, s);
1216 ret = rdpsnd_server_recv_formats(context, s);
1218 if ((ret == CHANNEL_RC_OK) && (context->clientVersion < CHANNEL_VERSION_WIN_7))
1219 IFCALL(context->Activated, context);
1223 case SNDC_QUALITYMODE:
1224 ret = rdpsnd_server_recv_quality_mode(context, s);
1226 if ((ret == CHANNEL_RC_OK) && (context->clientVersion >= CHANNEL_VERSION_WIN_7))
1227 IFCALL(context->Activated, context);
1232 WLog_ERR(TAG,
"UNKNOWN MESSAGE TYPE!! (0x%02" PRIX8
")", priv->msgType);
1233 ret = ERROR_INVALID_DATA;
1237 Stream_SetPosition(s, 0);