FreeRDP
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Modules Pages
tsmf_ifman.c
1
23#include <freerdp/config.h>
24
25#include <math.h>
26#include <stdio.h>
27#include <stdlib.h>
28#include <string.h>
29
30#include <winpr/crt.h>
31
32#include <winpr/stream.h>
33
34#include "tsmf_types.h"
35#include "tsmf_constants.h"
36#include "tsmf_media.h"
37#include "tsmf_codec.h"
38
39#include "tsmf_ifman.h"
40
46UINT tsmf_ifman_rim_exchange_capability_request(TSMF_IFMAN* ifman)
47{
48 UINT32 CapabilityValue = 0;
49
50 if (!Stream_CheckAndLogRequiredLength(TAG, ifman->input, 4))
51 return ERROR_INVALID_DATA;
52
53 Stream_Read_UINT32(ifman->input, CapabilityValue);
54 DEBUG_TSMF("server CapabilityValue %" PRIu32 "", CapabilityValue);
55
56 if (!Stream_EnsureRemainingCapacity(ifman->output, 8))
57 return ERROR_INVALID_DATA;
58
59 Stream_Write_UINT32(ifman->output, 1); /* CapabilityValue */
60 Stream_Write_UINT32(ifman->output, 0); /* Result */
61 return CHANNEL_RC_OK;
62}
63
69UINT tsmf_ifman_exchange_capability_request(TSMF_IFMAN* ifman)
70{
71 UINT32 CapabilityType = 0;
72 UINT32 cbCapabilityLength = 0;
73 UINT32 numHostCapabilities = 0;
74
75 WINPR_ASSERT(ifman);
76 if (!Stream_EnsureRemainingCapacity(ifman->output, ifman->input_size + 4))
77 return ERROR_OUTOFMEMORY;
78
79 if (!Stream_CheckAndLogRequiredLength(TAG, ifman->input, ifman->input_size))
80 return ERROR_INVALID_DATA;
81
82 const size_t xpos = Stream_GetPosition(ifman->output);
83 Stream_Copy(ifman->input, ifman->output, ifman->input_size);
84 Stream_SetPosition(ifman->output, xpos);
85
86 if (!Stream_CheckAndLogRequiredLength(TAG, ifman->output, 4))
87 return ERROR_INVALID_DATA;
88
89 Stream_Read_UINT32(ifman->output, numHostCapabilities);
90
91 for (UINT32 i = 0; i < numHostCapabilities; i++)
92 {
93 if (!Stream_CheckAndLogRequiredLength(TAG, ifman->output, 8))
94 return ERROR_INVALID_DATA;
95
96 Stream_Read_UINT32(ifman->output, CapabilityType);
97 Stream_Read_UINT32(ifman->output, cbCapabilityLength);
98
99 if (!Stream_CheckAndLogRequiredLength(TAG, ifman->output, cbCapabilityLength))
100 return ERROR_INVALID_DATA;
101
102 const size_t pos = Stream_GetPosition(ifman->output);
103
104 switch (CapabilityType)
105 {
106 case 1: /* Protocol version request */
107 {
108 if (!Stream_CheckAndLogRequiredLength(TAG, ifman->output, 4))
109 return ERROR_INVALID_DATA;
110
111 const UINT32 v = Stream_Get_UINT32(ifman->output);
112 WINPR_UNUSED(v);
113 DEBUG_TSMF("server protocol version %" PRIu32 "", v);
114 }
115 break;
116
117 case 2: /* Supported platform */
118 {
119 if (!Stream_CheckAndLogRequiredLength(TAG, ifman->output, 4))
120 return ERROR_INVALID_DATA;
121
122 const UINT32 v = Stream_Get_UINT32(ifman->output);
123 WINPR_UNUSED(v);
124 DEBUG_TSMF("server supported platform %" PRIu32 "", v);
125 /* Claim that we support both MF and DShow platforms. */
126 Stream_Write_UINT32(ifman->output, MMREDIR_CAPABILITY_PLATFORM_MF |
127 MMREDIR_CAPABILITY_PLATFORM_DSHOW);
128 }
129 break;
130
131 default:
132 WLog_ERR(TAG, "skipping unknown capability type %" PRIu32 "", CapabilityType);
133 break;
134 }
135
136 Stream_SetPosition(ifman->output, pos + cbCapabilityLength);
137 }
138
139 Stream_Write_UINT32(ifman->output, 0); /* Result */
140 ifman->output_interface_id = TSMF_INTERFACE_DEFAULT | STREAM_ID_STUB;
141 return CHANNEL_RC_OK;
142}
143
149UINT tsmf_ifman_check_format_support_request(TSMF_IFMAN* ifman)
150{
151 UINT32 numMediaType = 0;
152 UINT32 PlatformCookie = 0;
153 UINT32 FormatSupported = 1;
154
155 if (!Stream_CheckAndLogRequiredLength(TAG, ifman->input, 12))
156 return ERROR_INVALID_DATA;
157
158 Stream_Read_UINT32(ifman->input, PlatformCookie);
159 Stream_Seek_UINT32(ifman->input); /* NoRolloverFlags (4 bytes) */
160 Stream_Read_UINT32(ifman->input, numMediaType);
161 DEBUG_TSMF("PlatformCookie %" PRIu32 " numMediaType %" PRIu32 "", PlatformCookie, numMediaType);
162
163 if (!tsmf_codec_check_media_type(ifman->decoder_name, ifman->input))
164 FormatSupported = 0;
165
166 if (FormatSupported)
167 DEBUG_TSMF("format ok.");
168
169 if (!Stream_EnsureRemainingCapacity(ifman->output, 12))
170 return -1;
171
172 Stream_Write_UINT32(ifman->output, FormatSupported);
173 Stream_Write_UINT32(ifman->output, PlatformCookie);
174 Stream_Write_UINT32(ifman->output, 0); /* Result */
175 ifman->output_interface_id = TSMF_INTERFACE_DEFAULT | STREAM_ID_STUB;
176 return CHANNEL_RC_OK;
177}
178
184UINT tsmf_ifman_on_new_presentation(TSMF_IFMAN* ifman)
185{
186 UINT status = CHANNEL_RC_OK;
187 TSMF_PRESENTATION* presentation = NULL;
188 DEBUG_TSMF("");
189
190 if (!Stream_CheckAndLogRequiredLength(TAG, ifman->input, GUID_SIZE))
191 return ERROR_INVALID_DATA;
192
193 presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input));
194
195 if (presentation)
196 {
197 DEBUG_TSMF("Presentation already exists");
198 ifman->output_pending = FALSE;
199 return CHANNEL_RC_OK;
200 }
201
202 presentation = tsmf_presentation_new(Stream_Pointer(ifman->input), ifman->channel_callback);
203
204 if (!presentation)
205 status = ERROR_OUTOFMEMORY;
206 else
207 tsmf_presentation_set_audio_device(presentation, ifman->audio_name, ifman->audio_device);
208
209 ifman->output_pending = TRUE;
210 return status;
211}
212
218UINT tsmf_ifman_add_stream(TSMF_IFMAN* ifman, rdpContext* rdpcontext)
219{
220 UINT32 StreamId = 0;
221 UINT status = CHANNEL_RC_OK;
222 TSMF_STREAM* stream = NULL;
223 TSMF_PRESENTATION* presentation = NULL;
224 DEBUG_TSMF("");
225
226 if (!Stream_CheckAndLogRequiredLength(TAG, ifman->input, GUID_SIZE + 8))
227 return ERROR_INVALID_DATA;
228
229 presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input));
230 Stream_Seek(ifman->input, GUID_SIZE);
231
232 if (!presentation)
233 {
234 WLog_ERR(TAG, "unknown presentation id");
235 status = ERROR_NOT_FOUND;
236 }
237 else
238 {
239 Stream_Read_UINT32(ifman->input, StreamId);
240 Stream_Seek_UINT32(ifman->input); /* numMediaType */
241 stream = tsmf_stream_new(presentation, StreamId, rdpcontext);
242
243 if (!stream)
244 {
245 WLog_ERR(TAG, "failed to create stream");
246 return ERROR_OUTOFMEMORY;
247 }
248
249 if (!tsmf_stream_set_format(stream, ifman->decoder_name, ifman->input))
250 {
251 WLog_ERR(TAG, "failed to set stream format");
252 return ERROR_OUTOFMEMORY;
253 }
254
255 tsmf_stream_start_threads(stream);
256 }
257
258 ifman->output_pending = TRUE;
259 return status;
260}
261
267UINT tsmf_ifman_set_topology_request(TSMF_IFMAN* ifman)
268{
269 DEBUG_TSMF("");
270
271 if (!Stream_EnsureRemainingCapacity(ifman->output, 8))
272 return ERROR_OUTOFMEMORY;
273
274 Stream_Write_UINT32(ifman->output, 1); /* TopologyReady */
275 Stream_Write_UINT32(ifman->output, 0); /* Result */
276 ifman->output_interface_id = TSMF_INTERFACE_DEFAULT | STREAM_ID_STUB;
277 return CHANNEL_RC_OK;
278}
279
285UINT tsmf_ifman_remove_stream(TSMF_IFMAN* ifman)
286{
287 int status = CHANNEL_RC_OK;
288 UINT32 StreamId = 0;
289 TSMF_STREAM* stream = NULL;
290 TSMF_PRESENTATION* presentation = NULL;
291 DEBUG_TSMF("");
292
293 if (!Stream_CheckAndLogRequiredLength(TAG, ifman->input, 20))
294 return ERROR_INVALID_DATA;
295
296 presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input));
297 Stream_Seek(ifman->input, GUID_SIZE);
298
299 if (!presentation)
300 {
301 status = ERROR_NOT_FOUND;
302 }
303 else
304 {
305 Stream_Read_UINT32(ifman->input, StreamId);
306 stream = tsmf_stream_find_by_id(presentation, StreamId);
307
308 if (stream)
309 tsmf_stream_free(stream);
310 else
311 status = ERROR_NOT_FOUND;
312 }
313
314 ifman->output_pending = TRUE;
315 return status;
316}
317
318static float tsmf_stream_read_float(wStream* s)
319{
320 float fValue = NAN;
321 UINT32 iValue = 0;
322 Stream_Read_UINT32(s, iValue);
323 CopyMemory(&fValue, &iValue, 4);
324 return fValue;
325}
326
332UINT tsmf_ifman_set_source_video_rect(TSMF_IFMAN* ifman)
333{
334 UINT status = CHANNEL_RC_OK;
335 float Left = NAN;
336 float Top = NAN;
337 float Right = NAN;
338 float Bottom = NAN;
339 TSMF_PRESENTATION* presentation = NULL;
340 DEBUG_TSMF("");
341
342 if (!Stream_CheckAndLogRequiredLength(TAG, ifman->input, 32))
343 return ERROR_INVALID_DATA;
344
345 presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input));
346 Stream_Seek(ifman->input, GUID_SIZE);
347
348 if (!presentation)
349 {
350 status = ERROR_NOT_FOUND;
351 }
352 else
353 {
354#ifdef WITH_DEBUG_TSMF
355 Left = tsmf_stream_read_float(ifman->input); /* Left (4 bytes) */
356 Top = tsmf_stream_read_float(ifman->input); /* Top (4 bytes) */
357 Right = tsmf_stream_read_float(ifman->input); /* Right (4 bytes) */
358 Bottom = tsmf_stream_read_float(ifman->input); /* Bottom (4 bytes) */
359 DEBUG_TSMF("SetSourceVideoRect: Left: %f Top: %f Right: %f Bottom: %f", Left, Top, Right,
360 Bottom);
361#endif
362 }
363
364 ifman->output_pending = TRUE;
365 return status;
366}
367
373UINT tsmf_ifman_shutdown_presentation(TSMF_IFMAN* ifman)
374{
375 TSMF_PRESENTATION* presentation = NULL;
376 DEBUG_TSMF("");
377
378 if (!Stream_CheckAndLogRequiredLength(TAG, ifman->input, GUID_SIZE))
379 return ERROR_INVALID_DATA;
380
381 presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input));
382
383 if (presentation)
384 tsmf_presentation_free(presentation);
385 else
386 {
387 WLog_ERR(TAG, "unknown presentation id");
388 return ERROR_NOT_FOUND;
389 }
390
391 if (!Stream_EnsureRemainingCapacity(ifman->output, 4))
392 return ERROR_OUTOFMEMORY;
393
394 Stream_Write_UINT32(ifman->output, 0); /* Result */
395 ifman->output_interface_id = TSMF_INTERFACE_DEFAULT | STREAM_ID_STUB;
396 return CHANNEL_RC_OK;
397}
398
404UINT tsmf_ifman_on_stream_volume(TSMF_IFMAN* ifman)
405{
406 TSMF_PRESENTATION* presentation = NULL;
407 UINT32 newVolume = 0;
408 UINT32 muted = 0;
409 DEBUG_TSMF("on stream volume");
410
411 if (!Stream_CheckAndLogRequiredLength(TAG, ifman->input, GUID_SIZE + 8))
412 return ERROR_INVALID_DATA;
413
414 presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input));
415
416 if (!presentation)
417 {
418 WLog_ERR(TAG, "unknown presentation id");
419 return ERROR_NOT_FOUND;
420 }
421
422 Stream_Seek(ifman->input, 16);
423 Stream_Read_UINT32(ifman->input, newVolume);
424 DEBUG_TSMF("on stream volume: new volume=[%" PRIu32 "]", newVolume);
425 Stream_Read_UINT32(ifman->input, muted);
426 DEBUG_TSMF("on stream volume: muted=[%" PRIu32 "]", muted);
427
428 if (!tsmf_presentation_volume_changed(presentation, newVolume, muted))
429 return ERROR_INVALID_OPERATION;
430
431 ifman->output_pending = TRUE;
432 return 0;
433}
434
440UINT tsmf_ifman_on_channel_volume(TSMF_IFMAN* ifman)
441{
442 TSMF_PRESENTATION* presentation = NULL;
443 DEBUG_TSMF("on channel volume");
444
445 if (!Stream_CheckAndLogRequiredLength(TAG, ifman->input, GUID_SIZE + 8))
446 return ERROR_INVALID_DATA;
447
448 presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input));
449
450 if (presentation)
451 {
452 UINT32 channelVolume = 0;
453 UINT32 changedChannel = 0;
454 Stream_Seek(ifman->input, 16);
455 Stream_Read_UINT32(ifman->input, channelVolume);
456 DEBUG_TSMF("on channel volume: channel volume=[%" PRIu32 "]", channelVolume);
457 Stream_Read_UINT32(ifman->input, changedChannel);
458 DEBUG_TSMF("on stream volume: changed channel=[%" PRIu32 "]", changedChannel);
459 }
460
461 ifman->output_pending = TRUE;
462 return CHANNEL_RC_OK;
463}
464
470UINT tsmf_ifman_set_video_window(TSMF_IFMAN* ifman)
471{
472 DEBUG_TSMF("");
473 ifman->output_pending = TRUE;
474 return CHANNEL_RC_OK;
475}
476
482UINT tsmf_ifman_update_geometry_info(TSMF_IFMAN* ifman)
483{
484 TSMF_PRESENTATION* presentation = NULL;
485 UINT32 numGeometryInfo = 0;
486 UINT32 Left = 0;
487 UINT32 Top = 0;
488 UINT32 Width = 0;
489 UINT32 Height = 0;
490 UINT32 cbVisibleRect = 0;
491 RECTANGLE_32* rects = NULL;
492 UINT error = CHANNEL_RC_OK;
493 size_t pos = 0;
494
495 if (!Stream_CheckAndLogRequiredLength(TAG, ifman->input, GUID_SIZE + 32))
496 return ERROR_INVALID_DATA;
497
498 presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input));
499
500 if (!presentation)
501 return ERROR_NOT_FOUND;
502
503 Stream_Seek(ifman->input, 16);
504 Stream_Read_UINT32(ifman->input, numGeometryInfo);
505 pos = Stream_GetPosition(ifman->input);
506 Stream_Seek(ifman->input, 12); /* VideoWindowId (8 bytes), VideoWindowState (4 bytes) */
507 Stream_Read_UINT32(ifman->input, Width);
508 Stream_Read_UINT32(ifman->input, Height);
509 Stream_Read_UINT32(ifman->input, Left);
510 Stream_Read_UINT32(ifman->input, Top);
511 Stream_SetPosition(ifman->input, pos + numGeometryInfo);
512 Stream_Read_UINT32(ifman->input, cbVisibleRect);
513 const UINT32 num_rects = cbVisibleRect / 16;
514 DEBUG_TSMF("numGeometryInfo %" PRIu32 " Width %" PRIu32 " Height %" PRIu32 " Left %" PRIu32
515 " Top %" PRIu32 " cbVisibleRect %" PRIu32 " num_rects %d",
516 numGeometryInfo, Width, Height, Left, Top, cbVisibleRect, num_rects);
517
518 if (num_rects > 0)
519 {
520 rects = (RECTANGLE_32*)calloc(num_rects, sizeof(RECTANGLE_32));
521
522 for (size_t i = 0; i < num_rects; i++)
523 {
524 Stream_Read_UINT32(ifman->input, rects[i].top); /* Top */
525 Stream_Read_UINT32(ifman->input, rects[i].left); /* Left */
526 Stream_Read_UINT32(ifman->input, rects[i].height); /* Bottom */
527 Stream_Read_UINT32(ifman->input, rects[i].width); /* Right */
528 rects[i].width -= rects[i].left;
529 rects[i].height -= rects[i].top;
530 DEBUG_TSMF("rect %d: %" PRId16 " %" PRId16 " %" PRId16 " %" PRId16 "", i, rects[i].x,
531 rects[i].y, rects[i].width, rects[i].height);
532 }
533 }
534
535 const BOOL rc = tsmf_presentation_set_geometry_info(presentation, Left, Top, Width, Height,
536 num_rects, rects);
537 free(rects);
538 if (!rc)
539 return ERROR_INVALID_OPERATION;
540
541 ifman->output_pending = TRUE;
542 return error;
543}
544
550UINT tsmf_ifman_set_allocator(TSMF_IFMAN* ifman)
551{
552 DEBUG_TSMF("");
553 ifman->output_pending = TRUE;
554 return CHANNEL_RC_OK;
555}
556
562UINT tsmf_ifman_notify_preroll(TSMF_IFMAN* ifman)
563{
564 DEBUG_TSMF("");
565 tsmf_ifman_on_playback_paused(ifman);
566 ifman->output_pending = TRUE;
567 return CHANNEL_RC_OK;
568}
569
575UINT tsmf_ifman_on_sample(TSMF_IFMAN* ifman)
576{
577 TSMF_PRESENTATION* presentation = NULL;
578 TSMF_STREAM* stream = NULL;
579 UINT32 StreamId = 0;
580 UINT64 SampleStartTime = 0;
581 UINT64 SampleEndTime = 0;
582 UINT64 ThrottleDuration = 0;
583 UINT32 SampleExtensions = 0;
584 UINT32 cbData = 0;
585 UINT error = 0;
586
587 if (!Stream_CheckAndLogRequiredLength(TAG, ifman->input, 60))
588 return ERROR_INVALID_DATA;
589
590 Stream_Seek(ifman->input, 16);
591 Stream_Read_UINT32(ifman->input, StreamId);
592 Stream_Seek_UINT32(ifman->input); /* numSample */
593 Stream_Read_UINT64(ifman->input, SampleStartTime);
594 Stream_Read_UINT64(ifman->input, SampleEndTime);
595 Stream_Read_UINT64(ifman->input, ThrottleDuration);
596 Stream_Seek_UINT32(ifman->input); /* SampleFlags */
597 Stream_Read_UINT32(ifman->input, SampleExtensions);
598 Stream_Read_UINT32(ifman->input, cbData);
599
600 if (!Stream_CheckAndLogRequiredLength(TAG, ifman->input, cbData))
601 return ERROR_INVALID_DATA;
602
603 DEBUG_TSMF("MessageId %" PRIu32 " StreamId %" PRIu32 " SampleStartTime %" PRIu64
604 " SampleEndTime %" PRIu64 " "
605 "ThrottleDuration %" PRIu64 " SampleExtensions %" PRIu32 " cbData %" PRIu32 "",
606 ifman->message_id, StreamId, SampleStartTime, SampleEndTime, ThrottleDuration,
607 SampleExtensions, cbData);
608 presentation = tsmf_presentation_find_by_id(ifman->presentation_id);
609
610 if (!presentation)
611 {
612 WLog_ERR(TAG, "unknown presentation id");
613 return ERROR_NOT_FOUND;
614 }
615
616 stream = tsmf_stream_find_by_id(presentation, StreamId);
617
618 if (!stream)
619 {
620 WLog_ERR(TAG, "unknown stream id");
621 return ERROR_NOT_FOUND;
622 }
623
624 if (!tsmf_stream_push_sample(stream, ifman->channel_callback, ifman->message_id,
625 SampleStartTime, SampleEndTime, ThrottleDuration, SampleExtensions,
626 cbData, Stream_Pointer(ifman->input)))
627 {
628 WLog_ERR(TAG, "unable to push sample");
629 return ERROR_OUTOFMEMORY;
630 }
631
632 if ((error = tsmf_presentation_sync(presentation)))
633 {
634 WLog_ERR(TAG, "tsmf_presentation_sync failed with error %" PRIu32 "", error);
635 return error;
636 }
637
638 ifman->output_pending = TRUE;
639 return CHANNEL_RC_OK;
640}
641
647UINT tsmf_ifman_on_flush(TSMF_IFMAN* ifman)
648{
649 UINT32 StreamId = 0;
650 TSMF_PRESENTATION* presentation = NULL;
651 TSMF_STREAM* stream = NULL;
652
653 if (!Stream_CheckAndLogRequiredLength(TAG, ifman->input, 20))
654 return ERROR_INVALID_DATA;
655
656 Stream_Seek(ifman->input, 16);
657 Stream_Read_UINT32(ifman->input, StreamId);
658 DEBUG_TSMF("StreamId %" PRIu32 "", StreamId);
659 presentation = tsmf_presentation_find_by_id(ifman->presentation_id);
660
661 if (!presentation)
662 {
663 WLog_ERR(TAG, "unknown presentation id");
664 return ERROR_NOT_FOUND;
665 }
666
667 /* Flush message is for a stream, not the entire presentation
668 * therefore we only flush the stream as intended per the MS-RDPEV spec
669 */
670 stream = tsmf_stream_find_by_id(presentation, StreamId);
671
672 if (stream)
673 {
674 if (!tsmf_stream_flush(stream))
675 return ERROR_INVALID_OPERATION;
676 }
677 else
678 WLog_ERR(TAG, "unknown stream id");
679
680 ifman->output_pending = TRUE;
681 return CHANNEL_RC_OK;
682}
683
689UINT tsmf_ifman_on_end_of_stream(TSMF_IFMAN* ifman)
690{
691 UINT32 StreamId = 0;
692 TSMF_STREAM* stream = NULL;
693 TSMF_PRESENTATION* presentation = NULL;
694
695 if (!Stream_CheckAndLogRequiredLength(TAG, ifman->input, 20))
696 return ERROR_INVALID_DATA;
697
698 presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input));
699 Stream_Seek(ifman->input, 16);
700 Stream_Read_UINT32(ifman->input, StreamId);
701
702 if (presentation)
703 {
704 stream = tsmf_stream_find_by_id(presentation, StreamId);
705
706 if (stream)
707 tsmf_stream_end(stream, ifman->message_id, ifman->channel_callback);
708 }
709
710 DEBUG_TSMF("StreamId %" PRIu32 "", StreamId);
711 ifman->output_pending = TRUE;
712 ifman->output_interface_id = TSMF_INTERFACE_CLIENT_NOTIFICATIONS | STREAM_ID_PROXY;
713 return CHANNEL_RC_OK;
714}
715
721UINT tsmf_ifman_on_playback_started(TSMF_IFMAN* ifman)
722{
723 TSMF_PRESENTATION* presentation = NULL;
724 DEBUG_TSMF("");
725
726 if (!Stream_CheckAndLogRequiredLength(TAG, ifman->input, 16))
727 return ERROR_INVALID_DATA;
728
729 presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input));
730
731 if (presentation)
732 tsmf_presentation_start(presentation);
733 else
734 WLog_ERR(TAG, "unknown presentation id");
735
736 if (!Stream_EnsureRemainingCapacity(ifman->output, 16))
737 return ERROR_OUTOFMEMORY;
738
739 Stream_Write_UINT32(ifman->output, CLIENT_EVENT_NOTIFICATION); /* FunctionId */
740 Stream_Write_UINT32(ifman->output, 0); /* StreamId */
741 Stream_Write_UINT32(ifman->output, TSMM_CLIENT_EVENT_START_COMPLETED); /* EventId */
742 Stream_Write_UINT32(ifman->output, 0); /* cbData */
743 ifman->output_interface_id = TSMF_INTERFACE_CLIENT_NOTIFICATIONS | STREAM_ID_PROXY;
744 return CHANNEL_RC_OK;
745}
746
752UINT tsmf_ifman_on_playback_paused(TSMF_IFMAN* ifman)
753{
754 TSMF_PRESENTATION* presentation = NULL;
755 DEBUG_TSMF("");
756 ifman->output_pending = TRUE;
757 /* Added pause control so gstreamer pipeline can be paused accordingly */
758 presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input));
759
760 if (presentation)
761 {
762 if (!tsmf_presentation_paused(presentation))
763 return ERROR_INVALID_OPERATION;
764 }
765 else
766 WLog_ERR(TAG, "unknown presentation id");
767
768 return CHANNEL_RC_OK;
769}
770
776UINT tsmf_ifman_on_playback_restarted(TSMF_IFMAN* ifman)
777{
778 TSMF_PRESENTATION* presentation = NULL;
779 DEBUG_TSMF("");
780 ifman->output_pending = TRUE;
781 /* Added restart control so gstreamer pipeline can be resumed accordingly */
782 presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input));
783
784 if (presentation)
785 {
786 if (!tsmf_presentation_restarted(presentation))
787 return ERROR_INVALID_OPERATION;
788 }
789 else
790 WLog_ERR(TAG, "unknown presentation id");
791
792 return CHANNEL_RC_OK;
793}
794
800UINT tsmf_ifman_on_playback_stopped(TSMF_IFMAN* ifman)
801{
802 TSMF_PRESENTATION* presentation = NULL;
803 DEBUG_TSMF("");
804 presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input));
805
806 if (presentation)
807 {
808 if (!tsmf_presentation_stop(presentation))
809 return ERROR_INVALID_OPERATION;
810 }
811 else
812 WLog_ERR(TAG, "unknown presentation id");
813
814 if (!Stream_EnsureRemainingCapacity(ifman->output, 16))
815 return ERROR_OUTOFMEMORY;
816
817 Stream_Write_UINT32(ifman->output, CLIENT_EVENT_NOTIFICATION); /* FunctionId */
818 Stream_Write_UINT32(ifman->output, 0); /* StreamId */
819 Stream_Write_UINT32(ifman->output, TSMM_CLIENT_EVENT_STOP_COMPLETED); /* EventId */
820 Stream_Write_UINT32(ifman->output, 0); /* cbData */
821 ifman->output_interface_id = TSMF_INTERFACE_CLIENT_NOTIFICATIONS | STREAM_ID_PROXY;
822 return CHANNEL_RC_OK;
823}
824
830UINT tsmf_ifman_on_playback_rate_changed(TSMF_IFMAN* ifman)
831{
832 DEBUG_TSMF("");
833
834 if (!Stream_EnsureRemainingCapacity(ifman->output, 16))
835 return ERROR_OUTOFMEMORY;
836
837 Stream_Write_UINT32(ifman->output, CLIENT_EVENT_NOTIFICATION); /* FunctionId */
838 Stream_Write_UINT32(ifman->output, 0); /* StreamId */
839 Stream_Write_UINT32(ifman->output, TSMM_CLIENT_EVENT_MONITORCHANGED); /* EventId */
840 Stream_Write_UINT32(ifman->output, 0); /* cbData */
841 ifman->output_interface_id = TSMF_INTERFACE_CLIENT_NOTIFICATIONS | STREAM_ID_PROXY;
842 return CHANNEL_RC_OK;
843}