22 #include <freerdp/config.h>
28 #include <winpr/crt.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"
40 static 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);
56 static 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;
109 static 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);
136 static 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);
162 static 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;
185 static UINT rdpsnd_server_recv_formats(RdpsndServerContext* context,
wStream* s)
187 UINT16 num_known_format = 0;
190 UINT error = CHANNEL_RC_OK;
192 WINPR_ASSERT(context);
194 if (!Stream_CheckAndLogRequiredLength(TAG, s, 20))
195 return ERROR_INVALID_DATA;
197 Stream_Read_UINT32(s, context->capsFlags);
198 Stream_Read_UINT32(s, context->initialVolume);
199 Stream_Read_UINT32(s, context->initialPitch);
200 Stream_Read_UINT16(s, udpPort);
201 Stream_Read_UINT16(s, context->num_client_formats);
202 Stream_Read_UINT8(s, lastblock);
203 Stream_Read_UINT16(s, context->clientVersion);
204 Stream_Seek_UINT8(s);
207 if (!Stream_CheckAndLogRequiredLengthOfSize(TAG, s, context->num_client_formats, 18ull))
208 return ERROR_INVALID_DATA;
210 if (!context->num_client_formats)
212 WLog_ERR(TAG,
"client doesn't support any format!");
213 return ERROR_INTERNAL_ERROR;
216 context->client_formats = audio_formats_new(context->num_client_formats);
218 if (!context->client_formats)
220 WLog_ERR(TAG,
"calloc failed!");
221 return CHANNEL_RC_NO_MEMORY;
224 for (UINT16 i = 0; i < context->num_client_formats; i++)
228 if (!Stream_CheckAndLogRequiredLength(TAG, s, 18))
230 WLog_ERR(TAG,
"not enough data in stream!");
231 error = ERROR_INVALID_DATA;
235 Stream_Read_UINT16(s, format->wFormatTag);
236 Stream_Read_UINT16(s, format->nChannels);
237 Stream_Read_UINT32(s, format->nSamplesPerSec);
238 Stream_Read_UINT32(s, format->nAvgBytesPerSec);
239 Stream_Read_UINT16(s, format->nBlockAlign);
240 Stream_Read_UINT16(s, format->wBitsPerSample);
241 Stream_Read_UINT16(s, format->cbSize);
243 if (format->cbSize > 0)
245 if (!Stream_SafeSeek(s, format->cbSize))
247 WLog_ERR(TAG,
"Stream_SafeSeek failed!");
248 error = ERROR_INTERNAL_ERROR;
253 if (format->wFormatTag != 0)
261 if (!context->num_client_formats)
263 WLog_ERR(TAG,
"client doesn't support any known format!");
267 return CHANNEL_RC_OK;
269 free(context->client_formats);
273 static DWORD WINAPI rdpsnd_server_thread(LPVOID arg)
277 HANDLE events[2] = { 0 };
278 RdpsndServerContext* context = (RdpsndServerContext*)arg;
279 UINT error = CHANNEL_RC_OK;
281 WINPR_ASSERT(context);
282 WINPR_ASSERT(context->priv);
284 events[nCount++] = context->priv->channelEvent;
285 events[nCount++] = context->priv->StopEvent;
287 WINPR_ASSERT(nCount <= ARRAYSIZE(events));
291 status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE);
293 if (status == WAIT_FAILED)
295 error = GetLastError();
296 WLog_ERR(TAG,
"WaitForMultipleObjects failed with error %" PRIu32
"!", error);
300 status = WaitForSingleObject(context->priv->StopEvent, 0);
302 if (status == WAIT_FAILED)
304 error = GetLastError();
305 WLog_ERR(TAG,
"WaitForSingleObject failed with error %" PRIu32
"!", error);
309 if (status == WAIT_OBJECT_0)
312 if ((error = rdpsnd_server_handle_messages(context)))
314 WLog_ERR(TAG,
"rdpsnd_server_handle_messages failed with error %" PRIu32
"", error);
319 if (error && context->rdpcontext)
320 setChannelError(context->rdpcontext, error,
"rdpsnd_server_thread reported an error");
331 static UINT rdpsnd_server_initialize(RdpsndServerContext* context, BOOL ownThread)
333 WINPR_ASSERT(context);
334 WINPR_ASSERT(context->priv);
336 context->priv->ownThread = ownThread;
337 return context->Start(context);
345 static UINT rdpsnd_server_select_format(RdpsndServerContext* context, UINT16 client_format_index)
348 size_t out_buffer_size = 0;
350 UINT error = CHANNEL_RC_OK;
352 WINPR_ASSERT(context);
353 WINPR_ASSERT(context->priv);
355 if ((client_format_index >= context->num_client_formats) || (!context->src_format))
357 WLog_ERR(TAG,
"index %" PRIu16
" is not correct.", client_format_index);
358 return ERROR_INVALID_DATA;
361 EnterCriticalSection(&context->priv->lock);
362 context->priv->src_bytes_per_sample = context->src_format->wBitsPerSample / 8;
363 context->priv->src_bytes_per_frame =
364 context->priv->src_bytes_per_sample * context->src_format->nChannels;
365 context->selected_client_format = client_format_index;
366 format = &context->client_formats[client_format_index];
368 if (format->nSamplesPerSec == 0)
370 WLog_ERR(TAG,
"invalid Client Sound Format!!");
371 error = ERROR_INVALID_DATA;
375 if (context->latency <= 0)
376 context->latency = 50;
378 context->priv->out_frames = context->src_format->nSamplesPerSec * context->latency / 1000;
380 if (context->priv->out_frames < 1)
381 context->priv->out_frames = 1;
383 switch (format->wFormatTag)
385 case WAVE_FORMAT_DVI_ADPCM:
386 bs = 4ULL * (format->nBlockAlign - 4ULL * format->nChannels);
387 context->priv->out_frames -= context->priv->out_frames % bs;
389 if (context->priv->out_frames < bs)
390 context->priv->out_frames = bs;
394 case WAVE_FORMAT_ADPCM:
395 bs = (format->nBlockAlign - 7 * format->nChannels) * 2 / format->nChannels + 2;
396 context->priv->out_frames -= context->priv->out_frames % bs;
398 if (context->priv->out_frames < bs)
399 context->priv->out_frames = bs;
406 context->priv->out_pending_frames = 0;
407 out_buffer_size = context->priv->out_frames * context->priv->src_bytes_per_frame;
409 if (context->priv->out_buffer_size < out_buffer_size)
411 BYTE* newBuffer = NULL;
412 newBuffer = (BYTE*)realloc(context->priv->out_buffer, out_buffer_size);
416 WLog_ERR(TAG,
"realloc failed!");
417 error = CHANNEL_RC_NO_MEMORY;
421 context->priv->out_buffer = newBuffer;
422 context->priv->out_buffer_size = out_buffer_size;
425 freerdp_dsp_context_reset(context->priv->dsp_context, format, 0u);
427 LeaveCriticalSection(&context->priv->lock);
436 static UINT rdpsnd_server_training(RdpsndServerContext* context, UINT16 timestamp, UINT16 packsize,
441 wStream* s = rdpsnd_server_get_buffer(context);
443 if (!Stream_EnsureRemainingCapacity(s, 8))
444 return ERROR_INTERNAL_ERROR;
446 Stream_Write_UINT8(s, SNDC_TRAINING);
447 Stream_Write_UINT8(s, 0);
448 Stream_Seek_UINT16(s);
449 Stream_Write_UINT16(s, timestamp);
450 Stream_Write_UINT16(s, packsize);
454 if (!Stream_EnsureRemainingCapacity(s, packsize))
456 Stream_SetPosition(s, 0);
457 return ERROR_INTERNAL_ERROR;
460 Stream_Write(s, data, packsize);
463 const size_t end = Stream_GetPosition(s);
464 if ((end < 4) || (end > UINT16_MAX))
465 return ERROR_INTERNAL_ERROR;
467 Stream_SetPosition(s, 2);
468 Stream_Write_UINT16(s, (UINT16)(end - 4));
470 status = WTSVirtualChannelWrite(context->priv->ChannelHandle, Stream_BufferAs(s,
char),
471 (UINT32)end, &written);
473 Stream_SetPosition(s, 0);
475 return status ? CHANNEL_RC_OK : ERROR_INTERNAL_ERROR;
478 static BOOL rdpsnd_server_align_wave_pdu(
wStream* s, UINT32 alignment)
481 Stream_SealLength(s);
482 size = Stream_Length(s);
484 if ((size % alignment) != 0)
486 size_t offset = alignment - size % alignment;
488 if (!Stream_EnsureRemainingCapacity(s, offset))
491 Stream_Zero(s, offset);
494 Stream_SealLength(s);
504 static UINT rdpsnd_server_send_wave_pdu(RdpsndServerContext* context, UINT16 wTimestamp)
508 UINT error = CHANNEL_RC_OK;
509 wStream* s = rdpsnd_server_get_buffer(context);
511 if (context->selected_client_format > context->num_client_formats)
512 return ERROR_INTERNAL_ERROR;
514 WINPR_ASSERT(context->client_formats);
516 format = &context->client_formats[context->selected_client_format];
518 Stream_SetPosition(s, 0);
520 if (!Stream_EnsureRemainingCapacity(s, 16))
521 return ERROR_OUTOFMEMORY;
523 Stream_Write_UINT8(s, SNDC_WAVE);
524 Stream_Write_UINT8(s, 0);
525 Stream_Write_UINT16(s, 0);
526 Stream_Write_UINT16(s, wTimestamp);
527 Stream_Write_UINT16(s, context->selected_client_format);
528 Stream_Write_UINT8(s, context->block_no);
530 const size_t start = Stream_GetPosition(s);
531 const BYTE* src = context->priv->out_buffer;
532 const size_t length =
533 1ull * context->priv->out_pending_frames * context->priv->src_bytes_per_frame;
535 if (!freerdp_dsp_encode(context->priv->dsp_context, context->src_format, src, length, s))
536 return ERROR_INTERNAL_ERROR;
539 if (!rdpsnd_server_align_wave_pdu(s, format->nBlockAlign))
540 return ERROR_INTERNAL_ERROR;
542 const size_t end = Stream_GetPosition(s);
543 const size_t pos = end - start + 8ULL;
544 if (pos > UINT16_MAX)
545 return ERROR_INTERNAL_ERROR;
546 Stream_SetPosition(s, 2);
547 Stream_Write_UINT16(s, (UINT16)pos);
548 Stream_SetPosition(s, end);
550 if (!WTSVirtualChannelWrite(context->priv->ChannelHandle, Stream_BufferAs(s,
char),
551 (UINT32)(start + 4), &written))
553 WLog_ERR(TAG,
"WTSVirtualChannelWrite failed!");
554 error = ERROR_INTERNAL_ERROR;
557 if (error != CHANNEL_RC_OK)
559 WLog_ERR(TAG,
"WTSVirtualChannelWrite failed!");
560 error = ERROR_INTERNAL_ERROR;
564 Stream_SetPosition(s, start);
565 Stream_Write_UINT32(s, 0);
566 Stream_SetPosition(s, start);
568 WINPR_ASSERT((end - start) <= UINT32_MAX);
569 if (!WTSVirtualChannelWrite(context->priv->ChannelHandle, Stream_Pointer(s),
570 (UINT32)(end - start), &written))
572 WLog_ERR(TAG,
"WTSVirtualChannelWrite failed!");
573 error = ERROR_INTERNAL_ERROR;
576 context->block_no = (context->block_no + 1) % 256;
579 Stream_SetPosition(s, 0);
580 context->priv->out_pending_frames = 0;
590 static UINT rdpsnd_server_send_wave2_pdu(RdpsndServerContext* context, UINT16 formatNo,
591 const BYTE* data,
size_t size, BOOL encoded,
592 UINT16 timestamp, UINT32 audioTimeStamp)
595 UINT error = CHANNEL_RC_OK;
597 wStream* s = rdpsnd_server_get_buffer(context);
599 if (!Stream_EnsureRemainingCapacity(s, 16))
601 error = ERROR_INTERNAL_ERROR;
606 Stream_Write_UINT8(s, SNDC_WAVE2);
607 Stream_Write_UINT8(s, 0);
608 Stream_Write_UINT16(s, 0);
609 Stream_Write_UINT16(s, timestamp);
610 Stream_Write_UINT16(s, formatNo);
611 Stream_Write_UINT8(s, context->block_no);
612 Stream_Write_UINT8(s, 0);
613 Stream_Write_UINT8(s, 0);
614 Stream_Write_UINT8(s, 0);
615 Stream_Write_UINT32(s, audioTimeStamp);
619 if (!Stream_EnsureRemainingCapacity(s, size))
621 error = ERROR_INTERNAL_ERROR;
625 Stream_Write(s, data, size);
631 if (!freerdp_dsp_encode(context->priv->dsp_context, context->src_format, data, size, s))
633 error = ERROR_INTERNAL_ERROR;
637 format = &context->client_formats[formatNo];
638 if (!rdpsnd_server_align_wave_pdu(s, format->nBlockAlign))
640 error = ERROR_INTERNAL_ERROR;
645 const size_t end = Stream_GetPosition(s);
646 if (end > UINT16_MAX + 4)
648 error = ERROR_INTERNAL_ERROR;
652 Stream_SetPosition(s, 2);
653 Stream_Write_UINT16(s, (UINT16)(end - 4));
655 status = WTSVirtualChannelWrite(context->priv->ChannelHandle, Stream_BufferAs(s,
char),
656 (UINT32)end, &written);
658 if (!status || (end != written))
660 WLog_ERR(TAG,
"WTSVirtualChannelWrite failed! [stream length=%" PRIuz
" - written=%" PRIu32,
662 error = ERROR_INTERNAL_ERROR;
665 context->block_no = (context->block_no + 1) % 256;
668 Stream_SetPosition(s, 0);
669 context->priv->out_pending_frames = 0;
674 static UINT rdpsnd_server_send_audio_pdu(RdpsndServerContext* context, UINT16 wTimestamp)
676 const BYTE* src = NULL;
679 WINPR_ASSERT(context);
680 WINPR_ASSERT(context->priv);
682 if (context->selected_client_format >= context->num_client_formats)
683 return ERROR_INTERNAL_ERROR;
685 src = context->priv->out_buffer;
686 length = context->priv->out_pending_frames * context->priv->src_bytes_per_frame;
688 if (context->clientVersion >= CHANNEL_VERSION_WIN_8)
689 return rdpsnd_server_send_wave2_pdu(context, context->selected_client_format, src, length,
690 FALSE, wTimestamp, wTimestamp);
692 return rdpsnd_server_send_wave_pdu(context, wTimestamp);
700 static UINT rdpsnd_server_send_samples(RdpsndServerContext* context,
const void* buf,
701 size_t nframes, UINT16 wTimestamp)
703 UINT error = CHANNEL_RC_OK;
705 WINPR_ASSERT(context);
706 WINPR_ASSERT(context->priv);
708 EnterCriticalSection(&context->priv->lock);
710 if (context->selected_client_format >= context->num_client_formats)
713 WLog_WARN(TAG,
"Drop samples because client format has not been negotiated.");
714 error = ERROR_NOT_READY;
720 const size_t cframes =
721 MIN(nframes, context->priv->out_frames - context->priv->out_pending_frames);
722 size_t cframesize = cframes * context->priv->src_bytes_per_frame;
723 CopyMemory(context->priv->out_buffer +
724 (context->priv->out_pending_frames * context->priv->src_bytes_per_frame),
726 buf = (
const BYTE*)buf + cframesize;
728 context->priv->out_pending_frames += cframes;
730 if (context->priv->out_pending_frames >= context->priv->out_frames)
732 if ((error = rdpsnd_server_send_audio_pdu(context, wTimestamp)))
734 WLog_ERR(TAG,
"rdpsnd_server_send_audio_pdu failed with error %" PRIu32
"", error);
741 LeaveCriticalSection(&context->priv->lock);
750 static UINT rdpsnd_server_send_samples2(RdpsndServerContext* context, UINT16 formatNo,
751 const void* buf,
size_t size, UINT16 timestamp,
752 UINT32 audioTimeStamp)
754 UINT error = CHANNEL_RC_OK;
756 WINPR_ASSERT(context);
757 WINPR_ASSERT(context->priv);
759 if (context->clientVersion < CHANNEL_VERSION_WIN_8)
760 return ERROR_INTERNAL_ERROR;
762 EnterCriticalSection(&context->priv->lock);
765 rdpsnd_server_send_wave2_pdu(context, formatNo, buf, size, TRUE, timestamp, audioTimeStamp);
767 LeaveCriticalSection(&context->priv->lock);
777 static UINT rdpsnd_server_set_volume(RdpsndServerContext* context, UINT16 left, UINT16 right)
781 wStream* s = rdpsnd_server_get_buffer(context);
783 if (!Stream_EnsureRemainingCapacity(s, 8))
784 return ERROR_NOT_ENOUGH_MEMORY;
786 Stream_Write_UINT8(s, SNDC_SETVOLUME);
787 Stream_Write_UINT8(s, 0);
788 Stream_Write_UINT16(s, 4);
789 Stream_Write_UINT16(s, left);
790 Stream_Write_UINT16(s, right);
792 const size_t len = Stream_GetPosition(s);
793 WINPR_ASSERT(len <= UINT32_MAX);
794 status = WTSVirtualChannelWrite(context->priv->ChannelHandle, Stream_BufferAs(s,
char),
795 (ULONG)len, &written);
796 Stream_SetPosition(s, 0);
797 return status ? CHANNEL_RC_OK : ERROR_INTERNAL_ERROR;
805 static UINT rdpsnd_server_close(RdpsndServerContext* context)
809 UINT error = CHANNEL_RC_OK;
810 wStream* s = rdpsnd_server_get_buffer(context);
812 EnterCriticalSection(&context->priv->lock);
814 if (context->priv->out_pending_frames > 0)
816 if (context->selected_client_format >= context->num_client_formats)
818 WLog_ERR(TAG,
"Pending audio frame exists while no format selected.");
819 error = ERROR_INVALID_DATA;
821 else if ((error = rdpsnd_server_send_audio_pdu(context, 0)))
823 WLog_ERR(TAG,
"rdpsnd_server_send_audio_pdu failed with error %" PRIu32
"", error);
827 LeaveCriticalSection(&context->priv->lock);
832 context->selected_client_format = 0xFFFF;
834 if (!Stream_EnsureRemainingCapacity(s, 4))
835 return ERROR_OUTOFMEMORY;
837 Stream_Write_UINT8(s, SNDC_CLOSE);
838 Stream_Write_UINT8(s, 0);
839 Stream_Seek_UINT16(s);
840 const size_t pos = Stream_GetPosition(s);
841 WINPR_ASSERT(pos >= 4);
842 Stream_SetPosition(s, 2);
843 Stream_Write_UINT16(s, WINPR_ASSERTING_INT_CAST(uint16_t, pos - 4));
844 Stream_SetPosition(s, pos);
846 const size_t len = Stream_GetPosition(s);
847 WINPR_ASSERT(len <= UINT32_MAX);
848 status = WTSVirtualChannelWrite(context->priv->ChannelHandle, Stream_BufferAs(s,
char),
849 (UINT32)len, &written);
850 Stream_SetPosition(s, 0);
851 return status ? CHANNEL_RC_OK : ERROR_INTERNAL_ERROR;
859 static UINT rdpsnd_server_start(RdpsndServerContext* context)
862 DWORD bytesReturned = 0;
863 RdpsndServerPrivate* priv = NULL;
864 UINT error = ERROR_INTERNAL_ERROR;
865 PULONG pSessionId = NULL;
867 WINPR_ASSERT(context);
868 WINPR_ASSERT(context->priv);
870 priv = context->priv;
871 priv->SessionId = WTS_CURRENT_SESSION;
873 if (context->use_dynamic_virtual_channel)
875 UINT32 channelId = 0;
878 if (WTSQuerySessionInformationA(context->vcm, WTS_CURRENT_SESSION, WTSSessionId,
879 (LPSTR*)&pSessionId, &bytesReturned))
881 priv->SessionId = (DWORD)*pSessionId;
882 WTSFreeMemory(pSessionId);
883 priv->ChannelHandle = WTSVirtualChannelOpenEx(priv->SessionId, RDPSND_DVC_CHANNEL_NAME,
884 WTS_CHANNEL_OPTION_DYNAMIC);
885 if (!priv->ChannelHandle)
887 WLog_ERR(TAG,
"Open audio dynamic virtual channel (%s) failed!",
888 RDPSND_DVC_CHANNEL_NAME);
889 return ERROR_INTERNAL_ERROR;
892 channelId = WTSChannelGetIdByHandle(priv->ChannelHandle);
894 IFCALLRET(context->ChannelIdAssigned, status, context, channelId);
897 WLog_ERR(TAG,
"context->ChannelIdAssigned failed!");
903 WLog_ERR(TAG,
"WTSQuerySessionInformationA failed!");
904 return ERROR_INTERNAL_ERROR;
909 priv->ChannelHandle =
910 WTSVirtualChannelOpen(context->vcm, WTS_CURRENT_SESSION, RDPSND_CHANNEL_NAME);
911 if (!priv->ChannelHandle)
913 WLog_ERR(TAG,
"Open audio static virtual channel (rdpsnd) failed!");
914 return ERROR_INTERNAL_ERROR;
918 if (!WTSVirtualChannelQuery(priv->ChannelHandle, WTSVirtualEventHandle, &buffer,
920 (bytesReturned !=
sizeof(HANDLE)))
923 "error during WTSVirtualChannelQuery(WTSVirtualEventHandle) or invalid returned "
928 WTSFreeMemory(buffer);
933 priv->channelEvent = *(HANDLE*)buffer;
934 WTSFreeMemory(buffer);
935 priv->rdpsnd_pdu = Stream_New(NULL, 4096);
937 if (!priv->rdpsnd_pdu)
939 WLog_ERR(TAG,
"Stream_New failed!");
940 error = CHANNEL_RC_NO_MEMORY;
944 if (!InitializeCriticalSectionEx(&context->priv->lock, 0, 0))
946 WLog_ERR(TAG,
"InitializeCriticalSectionEx failed!");
950 if ((error = rdpsnd_server_send_formats(context)))
952 WLog_ERR(TAG,
"rdpsnd_server_send_formats failed with error %" PRIu32
"", error);
958 context->priv->StopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
960 if (!context->priv->StopEvent)
962 WLog_ERR(TAG,
"CreateEvent failed!");
966 context->priv->Thread =
967 CreateThread(NULL, 0, rdpsnd_server_thread, (
void*)context, 0, NULL);
969 if (!context->priv->Thread)
971 WLog_ERR(TAG,
"CreateThread failed!");
976 return CHANNEL_RC_OK;
978 (void)CloseHandle(context->priv->StopEvent);
979 context->priv->StopEvent = NULL;
981 DeleteCriticalSection(&context->priv->lock);
983 Stream_Free(context->priv->rdpsnd_pdu, TRUE);
984 context->priv->rdpsnd_pdu = NULL;
986 (void)WTSVirtualChannelClose(context->priv->ChannelHandle);
987 context->priv->ChannelHandle = NULL;
996 static UINT rdpsnd_server_stop(RdpsndServerContext* context)
998 UINT error = CHANNEL_RC_OK;
1000 WINPR_ASSERT(context);
1001 WINPR_ASSERT(context->priv);
1003 if (!context->priv->StopEvent)
1006 if (context->priv->ownThread)
1008 if (context->priv->StopEvent)
1010 (void)SetEvent(context->priv->StopEvent);
1012 if (WaitForSingleObject(context->priv->Thread, INFINITE) == WAIT_FAILED)
1014 error = GetLastError();
1015 WLog_ERR(TAG,
"WaitForSingleObject failed with error %" PRIu32
"!", error);
1019 (void)CloseHandle(context->priv->Thread);
1020 (void)CloseHandle(context->priv->StopEvent);
1021 context->priv->Thread = NULL;
1022 context->priv->StopEvent = NULL;
1026 DeleteCriticalSection(&context->priv->lock);
1028 if (context->priv->rdpsnd_pdu)
1030 Stream_Free(context->priv->rdpsnd_pdu, TRUE);
1031 context->priv->rdpsnd_pdu = NULL;
1034 if (context->priv->ChannelHandle)
1036 (void)WTSVirtualChannelClose(context->priv->ChannelHandle);
1037 context->priv->ChannelHandle = NULL;
1043 RdpsndServerContext* rdpsnd_server_context_new(HANDLE vcm)
1045 RdpsndServerPrivate* priv = NULL;
1046 RdpsndServerContext* context = (RdpsndServerContext*)calloc(1,
sizeof(RdpsndServerContext));
1052 context->Start = rdpsnd_server_start;
1053 context->Stop = rdpsnd_server_stop;
1054 context->selected_client_format = 0xFFFF;
1055 context->Initialize = rdpsnd_server_initialize;
1056 context->SendFormats = rdpsnd_server_send_formats;
1057 context->SelectFormat = rdpsnd_server_select_format;
1058 context->Training = rdpsnd_server_training;
1059 context->SendSamples = rdpsnd_server_send_samples;
1060 context->SendSamples2 = rdpsnd_server_send_samples2;
1061 context->SetVolume = rdpsnd_server_set_volume;
1062 context->Close = rdpsnd_server_close;
1063 context->priv = priv = (RdpsndServerPrivate*)calloc(1,
sizeof(RdpsndServerPrivate));
1067 WLog_ERR(TAG,
"calloc failed!");
1071 priv->dsp_context = freerdp_dsp_context_new(TRUE);
1073 if (!priv->dsp_context)
1075 WLog_ERR(TAG,
"freerdp_dsp_context_new failed!");
1079 priv->input_stream = Stream_New(NULL, 4);
1081 if (!priv->input_stream)
1083 WLog_ERR(TAG,
"Stream_New failed!");
1087 priv->expectedBytes = 4;
1088 priv->waitingHeader = TRUE;
1089 priv->ownThread = TRUE;
1092 WINPR_PRAGMA_DIAG_PUSH
1093 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
1094 rdpsnd_server_context_free(context);
1095 WINPR_PRAGMA_DIAG_POP
1099 void rdpsnd_server_context_reset(RdpsndServerContext* context)
1101 WINPR_ASSERT(context);
1102 WINPR_ASSERT(context->priv);
1104 context->priv->expectedBytes = 4;
1105 context->priv->waitingHeader = TRUE;
1106 Stream_SetPosition(context->priv->input_stream, 0);
1109 void rdpsnd_server_context_free(RdpsndServerContext* context)
1116 rdpsnd_server_stop(context);
1118 free(context->priv->out_buffer);
1120 if (context->priv->dsp_context)
1121 freerdp_dsp_context_free(context->priv->dsp_context);
1123 if (context->priv->input_stream)
1124 Stream_Free(context->priv->input_stream, TRUE);
1127 free(context->server_formats);
1128 free(context->client_formats);
1129 free(context->priv);
1133 HANDLE rdpsnd_server_get_event_handle(RdpsndServerContext* context)
1135 WINPR_ASSERT(context);
1136 WINPR_ASSERT(context->priv);
1138 return context->priv->channelEvent;
1155 UINT rdpsnd_server_handle_messages(RdpsndServerContext* context)
1157 DWORD bytesReturned = 0;
1158 UINT ret = CHANNEL_RC_OK;
1159 RdpsndServerPrivate* priv = NULL;
1162 WINPR_ASSERT(context);
1163 WINPR_ASSERT(context->priv);
1165 priv = context->priv;
1166 s = priv->input_stream;
1168 if (!WTSVirtualChannelRead(priv->ChannelHandle, 0, Stream_Pointer(s), priv->expectedBytes,
1171 if (GetLastError() == ERROR_NO_DATA)
1172 return ERROR_NO_DATA;
1174 WLog_ERR(TAG,
"channel connection closed");
1175 return ERROR_INTERNAL_ERROR;
1178 priv->expectedBytes -= bytesReturned;
1179 Stream_Seek(s, bytesReturned);
1181 if (priv->expectedBytes)
1182 return CHANNEL_RC_OK;
1184 Stream_SealLength(s);
1185 Stream_SetPosition(s, 0);
1187 if (priv->waitingHeader)
1190 Stream_Read_UINT8(s, priv->msgType);
1191 Stream_Seek_UINT8(s);
1192 Stream_Read_UINT16(s, priv->expectedBytes);
1193 priv->waitingHeader = FALSE;
1194 Stream_SetPosition(s, 0);
1196 if (priv->expectedBytes)
1198 if (!Stream_EnsureCapacity(s, priv->expectedBytes))
1200 WLog_ERR(TAG,
"Stream_EnsureCapacity failed!");
1201 return CHANNEL_RC_NO_MEMORY;
1204 return CHANNEL_RC_OK;
1209 #ifdef WITH_DEBUG_SND
1210 WLog_DBG(TAG,
"message type %" PRIu8
"", priv->msgType);
1212 priv->expectedBytes = 4;
1213 priv->waitingHeader = TRUE;
1215 switch (priv->msgType)
1217 case SNDC_WAVECONFIRM:
1218 ret = rdpsnd_server_recv_waveconfirm(context, s);
1222 ret = rdpsnd_server_recv_trainingconfirm(context, s);
1226 ret = rdpsnd_server_recv_formats(context, s);
1228 if ((ret == CHANNEL_RC_OK) && (context->clientVersion < CHANNEL_VERSION_WIN_7))
1229 IFCALL(context->Activated, context);
1233 case SNDC_QUALITYMODE:
1234 ret = rdpsnd_server_recv_quality_mode(context, s);
1236 if ((ret == CHANNEL_RC_OK) && (context->clientVersion >= CHANNEL_VERSION_WIN_7))
1237 IFCALL(context->Activated, context);
1242 WLog_ERR(TAG,
"UNKNOWN MESSAGE TYPE!! (0x%02" PRIX8
")", priv->msgType);
1243 ret = ERROR_INVALID_DATA;
1247 Stream_SetPosition(s, 0);