2011-09-19 18:54:09 +04:00
|
|
|
/**
|
2012-10-09 07:02:04 +04:00
|
|
|
* FreeRDP: A Remote Desktop Protocol Implementation
|
2011-09-19 18:54:09 +04:00
|
|
|
* Video Redirection Virtual Channel - Interface Manipulation
|
|
|
|
*
|
|
|
|
* Copyright 2010-2011 Vic Lee
|
2012-06-13 23:45:58 +04:00
|
|
|
* Copyright 2012 Hewlett-Packard Development Company, L.P.
|
2015-07-15 10:50:35 +03:00
|
|
|
* Copyright 2015 Thincast Technologies GmbH
|
|
|
|
* Copyright 2015 DI (FH) Martin Haimberger <martin.haimberger@thincast.com>
|
2011-09-19 18:54:09 +04:00
|
|
|
*
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
* You may obtain a copy of the License at
|
|
|
|
*
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
*
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
* limitations under the License.
|
|
|
|
*/
|
|
|
|
|
2012-08-15 01:09:01 +04:00
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
#include "config.h"
|
|
|
|
#endif
|
|
|
|
|
2011-09-19 18:54:09 +04:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
2012-08-15 01:09:01 +04:00
|
|
|
|
2012-11-20 08:49:08 +04:00
|
|
|
#include <winpr/crt.h>
|
|
|
|
|
2013-03-22 00:45:25 +04:00
|
|
|
#include <winpr/stream.h>
|
2011-09-19 18:54:09 +04:00
|
|
|
|
2012-09-23 03:25:21 +04:00
|
|
|
#include "tsmf_types.h"
|
2011-09-19 18:54:09 +04:00
|
|
|
#include "tsmf_constants.h"
|
|
|
|
#include "tsmf_media.h"
|
|
|
|
#include "tsmf_codec.h"
|
|
|
|
|
|
|
|
#include "tsmf_ifman.h"
|
|
|
|
|
2015-08-27 15:25:09 +03:00
|
|
|
/**
|
|
|
|
* Function description
|
|
|
|
*
|
|
|
|
* @return 0 on success, otherwise a Win32 error code
|
|
|
|
*/
|
|
|
|
UINT tsmf_ifman_rim_exchange_capability_request(TSMF_IFMAN* ifman)
|
2011-09-19 18:54:09 +04:00
|
|
|
{
|
2012-10-09 11:26:39 +04:00
|
|
|
UINT32 CapabilityValue;
|
2014-11-10 22:02:54 +03:00
|
|
|
|
2015-06-29 16:21:53 +03:00
|
|
|
if (Stream_GetRemainingLength(ifman->input) < 4)
|
|
|
|
return ERROR_INVALID_DATA;
|
2014-11-10 22:02:54 +03:00
|
|
|
|
2017-01-17 12:03:05 +03:00
|
|
|
Stream_Read_UINT32(ifman->input, CapabilityValue);
|
2016-12-14 00:47:08 +03:00
|
|
|
DEBUG_TSMF("server CapabilityValue %"PRIu32"", CapabilityValue);
|
2014-11-10 22:02:54 +03:00
|
|
|
|
2015-03-30 18:15:45 +03:00
|
|
|
if (!Stream_EnsureRemainingCapacity(ifman->output, 8))
|
2015-06-29 16:21:53 +03:00
|
|
|
return ERROR_INVALID_DATA;
|
2017-01-17 12:03:05 +03:00
|
|
|
|
2013-05-09 00:09:16 +04:00
|
|
|
Stream_Write_UINT32(ifman->output, 1); /* CapabilityValue */
|
|
|
|
Stream_Write_UINT32(ifman->output, 0); /* Result */
|
2015-06-29 16:21:53 +03:00
|
|
|
return CHANNEL_RC_OK;
|
2011-09-19 18:54:09 +04:00
|
|
|
}
|
|
|
|
|
2015-08-27 15:25:09 +03:00
|
|
|
/**
|
|
|
|
* Function description
|
|
|
|
*
|
|
|
|
* @return 0 on success, otherwise a Win32 error code
|
|
|
|
*/
|
|
|
|
UINT tsmf_ifman_exchange_capability_request(TSMF_IFMAN* ifman)
|
2011-09-19 18:54:09 +04:00
|
|
|
{
|
2012-10-09 11:26:39 +04:00
|
|
|
UINT32 i;
|
|
|
|
UINT32 v;
|
|
|
|
UINT32 pos;
|
|
|
|
UINT32 CapabilityType;
|
|
|
|
UINT32 cbCapabilityLength;
|
|
|
|
UINT32 numHostCapabilities;
|
2014-11-10 22:02:54 +03:00
|
|
|
|
2015-03-30 18:15:45 +03:00
|
|
|
if (!Stream_EnsureRemainingCapacity(ifman->output, ifman->input_size + 4))
|
2015-06-29 16:21:53 +03:00
|
|
|
return ERROR_OUTOFMEMORY;
|
2017-01-17 12:03:05 +03:00
|
|
|
|
2013-04-30 06:35:15 +04:00
|
|
|
pos = Stream_GetPosition(ifman->output);
|
2016-03-01 13:39:21 +03:00
|
|
|
Stream_Copy(ifman->input, ifman->output, ifman->input_size);
|
2013-04-30 06:35:15 +04:00
|
|
|
Stream_SetPosition(ifman->output, pos);
|
2015-06-29 16:21:53 +03:00
|
|
|
|
|
|
|
if (Stream_GetRemainingLength(ifman->output) < 4)
|
|
|
|
return ERROR_INVALID_DATA;
|
2017-01-17 12:03:05 +03:00
|
|
|
|
2013-05-09 00:09:16 +04:00
|
|
|
Stream_Read_UINT32(ifman->output, numHostCapabilities);
|
2014-11-10 22:02:54 +03:00
|
|
|
|
|
|
|
for (i = 0; i < numHostCapabilities; i++)
|
2011-09-19 18:54:09 +04:00
|
|
|
{
|
2015-06-29 16:21:53 +03:00
|
|
|
if (Stream_GetRemainingLength(ifman->output) < 8)
|
|
|
|
return ERROR_INVALID_DATA;
|
|
|
|
|
2013-05-09 00:09:16 +04:00
|
|
|
Stream_Read_UINT32(ifman->output, CapabilityType);
|
|
|
|
Stream_Read_UINT32(ifman->output, cbCapabilityLength);
|
2015-06-29 16:21:53 +03:00
|
|
|
|
|
|
|
if (Stream_GetRemainingLength(ifman->output) < cbCapabilityLength)
|
|
|
|
return ERROR_INVALID_DATA;
|
|
|
|
|
2013-04-30 06:35:15 +04:00
|
|
|
pos = Stream_GetPosition(ifman->output);
|
2014-11-10 22:02:54 +03:00
|
|
|
|
|
|
|
switch (CapabilityType)
|
2011-09-19 18:54:09 +04:00
|
|
|
{
|
|
|
|
case 1: /* Protocol version request */
|
2015-06-29 16:21:53 +03:00
|
|
|
if (Stream_GetRemainingLength(ifman->output) < 4)
|
|
|
|
return ERROR_INVALID_DATA;
|
|
|
|
|
2013-05-09 00:09:16 +04:00
|
|
|
Stream_Read_UINT32(ifman->output, v);
|
2016-12-14 00:47:08 +03:00
|
|
|
DEBUG_TSMF("server protocol version %"PRIu32"", v);
|
2011-09-19 18:54:09 +04:00
|
|
|
break;
|
2017-01-17 12:03:05 +03:00
|
|
|
|
2011-09-19 18:54:09 +04:00
|
|
|
case 2: /* Supported platform */
|
2015-06-29 16:21:53 +03:00
|
|
|
if (Stream_GetRemainingLength(ifman->output) < 4)
|
|
|
|
return ERROR_INVALID_DATA;
|
|
|
|
|
2013-05-09 00:27:21 +04:00
|
|
|
Stream_Peek_UINT32(ifman->output, v);
|
2016-12-14 00:47:08 +03:00
|
|
|
DEBUG_TSMF("server supported platform %"PRIu32"", v);
|
2011-09-19 18:54:09 +04:00
|
|
|
/* Claim that we support both MF and DShow platforms. */
|
2017-01-17 12:03:05 +03:00
|
|
|
Stream_Write_UINT32(ifman->output,
|
|
|
|
MMREDIR_CAPABILITY_PLATFORM_MF | MMREDIR_CAPABILITY_PLATFORM_DSHOW);
|
2011-09-19 18:54:09 +04:00
|
|
|
break;
|
2017-01-17 12:03:05 +03:00
|
|
|
|
2011-09-19 18:54:09 +04:00
|
|
|
default:
|
2016-12-14 00:47:08 +03:00
|
|
|
WLog_ERR(TAG, "skipping unknown capability type %"PRIu32"", CapabilityType);
|
2011-09-19 18:54:09 +04:00
|
|
|
break;
|
|
|
|
}
|
2017-01-17 12:03:05 +03:00
|
|
|
|
2013-04-30 06:35:15 +04:00
|
|
|
Stream_SetPosition(ifman->output, pos + cbCapabilityLength);
|
2011-09-19 18:54:09 +04:00
|
|
|
}
|
2014-11-10 22:02:54 +03:00
|
|
|
|
2013-05-09 00:09:16 +04:00
|
|
|
Stream_Write_UINT32(ifman->output, 0); /* Result */
|
2011-09-19 18:54:09 +04:00
|
|
|
ifman->output_interface_id = TSMF_INTERFACE_DEFAULT | STREAM_ID_STUB;
|
2015-06-29 16:21:53 +03:00
|
|
|
return CHANNEL_RC_OK;
|
2011-09-19 18:54:09 +04:00
|
|
|
}
|
|
|
|
|
2015-08-27 15:25:09 +03:00
|
|
|
/**
|
|
|
|
* Function description
|
|
|
|
*
|
|
|
|
* @return 0 on success, otherwise a Win32 error code
|
|
|
|
*/
|
|
|
|
UINT tsmf_ifman_check_format_support_request(TSMF_IFMAN* ifman)
|
2011-09-19 18:54:09 +04:00
|
|
|
{
|
2012-10-09 11:26:39 +04:00
|
|
|
UINT32 numMediaType;
|
|
|
|
UINT32 PlatformCookie;
|
|
|
|
UINT32 FormatSupported = 1;
|
2014-11-10 22:02:54 +03:00
|
|
|
|
2015-06-29 16:21:53 +03:00
|
|
|
if (Stream_GetRemainingLength(ifman->input) < 12)
|
|
|
|
return ERROR_INVALID_DATA;
|
|
|
|
|
2013-05-09 00:09:16 +04:00
|
|
|
Stream_Read_UINT32(ifman->input, PlatformCookie);
|
2013-04-30 06:35:15 +04:00
|
|
|
Stream_Seek_UINT32(ifman->input); /* NoRolloverFlags (4 bytes) */
|
2013-05-09 00:09:16 +04:00
|
|
|
Stream_Read_UINT32(ifman->input, numMediaType);
|
2016-12-14 00:47:08 +03:00
|
|
|
DEBUG_TSMF("PlatformCookie %"PRIu32" numMediaType %"PRIu32"", PlatformCookie, numMediaType);
|
2014-11-10 22:02:54 +03:00
|
|
|
|
2014-11-10 22:18:23 +03:00
|
|
|
if (!tsmf_codec_check_media_type(ifman->decoder_name, ifman->input))
|
2011-09-19 18:54:09 +04:00
|
|
|
FormatSupported = 0;
|
2014-11-10 22:02:54 +03:00
|
|
|
|
|
|
|
if (FormatSupported)
|
2014-05-23 15:49:13 +04:00
|
|
|
DEBUG_TSMF("format ok.");
|
2014-11-10 22:02:54 +03:00
|
|
|
|
2015-03-30 18:15:45 +03:00
|
|
|
if (!Stream_EnsureRemainingCapacity(ifman->output, 12))
|
2015-03-26 19:09:47 +03:00
|
|
|
return -1;
|
2017-01-17 12:03:05 +03:00
|
|
|
|
2013-05-09 00:09:16 +04:00
|
|
|
Stream_Write_UINT32(ifman->output, FormatSupported);
|
|
|
|
Stream_Write_UINT32(ifman->output, PlatformCookie);
|
|
|
|
Stream_Write_UINT32(ifman->output, 0); /* Result */
|
2011-09-19 18:54:09 +04:00
|
|
|
ifman->output_interface_id = TSMF_INTERFACE_DEFAULT | STREAM_ID_STUB;
|
2015-06-29 16:21:53 +03:00
|
|
|
return CHANNEL_RC_OK;
|
2011-09-19 18:54:09 +04:00
|
|
|
}
|
|
|
|
|
2015-08-27 15:25:09 +03:00
|
|
|
/**
|
|
|
|
* Function description
|
|
|
|
*
|
|
|
|
* @return 0 on success, otherwise a Win32 error code
|
|
|
|
*/
|
|
|
|
UINT tsmf_ifman_on_new_presentation(TSMF_IFMAN* ifman)
|
2011-09-19 18:54:09 +04:00
|
|
|
{
|
2015-08-27 15:25:09 +03:00
|
|
|
UINT status = CHANNEL_RC_OK;
|
2014-11-10 22:02:54 +03:00
|
|
|
TSMF_PRESENTATION* presentation;
|
2014-05-23 15:49:13 +04:00
|
|
|
DEBUG_TSMF("");
|
2014-11-10 22:02:54 +03:00
|
|
|
|
2015-06-29 16:21:53 +03:00
|
|
|
if (Stream_GetRemainingLength(ifman->input) < GUID_SIZE)
|
|
|
|
return ERROR_INVALID_DATA;
|
|
|
|
|
2013-06-19 20:33:46 +04:00
|
|
|
presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input));
|
2014-11-10 22:02:54 +03:00
|
|
|
|
|
|
|
if (presentation)
|
2012-06-13 23:45:58 +04:00
|
|
|
{
|
2014-05-23 15:49:13 +04:00
|
|
|
DEBUG_TSMF("Presentation already exists");
|
2012-10-09 10:31:28 +04:00
|
|
|
ifman->output_pending = FALSE;
|
2015-06-29 16:21:53 +03:00
|
|
|
return CHANNEL_RC_OK;
|
2012-06-13 23:45:58 +04:00
|
|
|
}
|
2014-11-10 22:02:54 +03:00
|
|
|
|
2013-04-30 06:35:15 +04:00
|
|
|
presentation = tsmf_presentation_new(Stream_Pointer(ifman->input), ifman->channel_callback);
|
2014-11-10 22:02:54 +03:00
|
|
|
|
|
|
|
if (!presentation)
|
2015-06-29 16:21:53 +03:00
|
|
|
status = ERROR_OUTOFMEMORY;
|
2012-05-16 17:29:35 +04:00
|
|
|
else
|
|
|
|
tsmf_presentation_set_audio_device(presentation, ifman->audio_name, ifman->audio_device);
|
2014-11-10 22:02:54 +03:00
|
|
|
|
2012-10-09 10:31:28 +04:00
|
|
|
ifman->output_pending = TRUE;
|
2012-11-20 08:49:08 +04:00
|
|
|
return status;
|
2011-09-19 18:54:09 +04:00
|
|
|
}
|
|
|
|
|
2015-08-27 15:25:09 +03:00
|
|
|
/**
|
|
|
|
* Function description
|
|
|
|
*
|
|
|
|
* @return 0 on success, otherwise a Win32 error code
|
|
|
|
*/
|
|
|
|
UINT tsmf_ifman_add_stream(TSMF_IFMAN* ifman, rdpContext* rdpcontext)
|
2011-09-19 18:54:09 +04:00
|
|
|
{
|
2012-10-09 11:26:39 +04:00
|
|
|
UINT32 StreamId;
|
2015-08-27 15:25:09 +03:00
|
|
|
UINT status = CHANNEL_RC_OK;
|
2014-11-10 22:02:54 +03:00
|
|
|
TSMF_STREAM* stream;
|
|
|
|
TSMF_PRESENTATION* presentation;
|
2014-05-23 15:49:13 +04:00
|
|
|
DEBUG_TSMF("");
|
2014-11-10 22:02:54 +03:00
|
|
|
|
2015-06-29 16:21:53 +03:00
|
|
|
if (Stream_GetRemainingLength(ifman->input) < GUID_SIZE + 8)
|
|
|
|
return ERROR_INVALID_DATA;
|
|
|
|
|
2013-04-30 06:35:15 +04:00
|
|
|
presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input));
|
2015-06-29 16:21:53 +03:00
|
|
|
Stream_Seek(ifman->input, GUID_SIZE);
|
2014-11-10 22:02:54 +03:00
|
|
|
|
|
|
|
if (!presentation)
|
2012-11-20 08:49:08 +04:00
|
|
|
{
|
2015-09-03 20:58:16 +03:00
|
|
|
WLog_ERR(TAG, "unknown presentation id");
|
2015-06-29 16:21:53 +03:00
|
|
|
status = ERROR_NOT_FOUND;
|
2012-11-20 08:49:08 +04:00
|
|
|
}
|
2011-09-19 18:54:09 +04:00
|
|
|
else
|
|
|
|
{
|
2013-05-09 00:09:16 +04:00
|
|
|
Stream_Read_UINT32(ifman->input, StreamId);
|
2013-04-30 06:35:15 +04:00
|
|
|
Stream_Seek_UINT32(ifman->input); /* numMediaType */
|
2015-07-15 10:50:35 +03:00
|
|
|
stream = tsmf_stream_new(presentation, StreamId, rdpcontext);
|
2017-01-17 12:03:05 +03:00
|
|
|
|
2015-06-29 16:21:53 +03:00
|
|
|
if (!stream)
|
2015-09-03 20:58:16 +03:00
|
|
|
{
|
|
|
|
WLog_ERR(TAG, "failed to create stream");
|
2015-06-29 16:21:53 +03:00
|
|
|
return ERROR_OUTOFMEMORY;
|
2015-09-03 20:58:16 +03:00
|
|
|
}
|
2015-06-29 16:21:53 +03:00
|
|
|
|
|
|
|
if (!tsmf_stream_set_format(stream, ifman->decoder_name, ifman->input))
|
2015-09-03 20:58:16 +03:00
|
|
|
{
|
|
|
|
WLog_ERR(TAG, "failed to set stream format");
|
2015-06-29 16:21:53 +03:00
|
|
|
return ERROR_OUTOFMEMORY;
|
2015-09-03 20:58:16 +03:00
|
|
|
}
|
2017-01-17 12:03:05 +03:00
|
|
|
|
2015-05-14 17:06:34 +03:00
|
|
|
tsmf_stream_start_threads(stream);
|
2011-09-19 18:54:09 +04:00
|
|
|
}
|
2015-06-29 16:21:53 +03:00
|
|
|
|
2012-10-09 10:31:28 +04:00
|
|
|
ifman->output_pending = TRUE;
|
2012-11-20 08:49:08 +04:00
|
|
|
return status;
|
2011-09-19 18:54:09 +04:00
|
|
|
}
|
|
|
|
|
2015-08-27 15:25:09 +03:00
|
|
|
/**
|
|
|
|
* Function description
|
|
|
|
*
|
|
|
|
* @return 0 on success, otherwise a Win32 error code
|
|
|
|
*/
|
|
|
|
UINT tsmf_ifman_set_topology_request(TSMF_IFMAN* ifman)
|
2011-09-19 18:54:09 +04:00
|
|
|
{
|
2014-05-23 15:49:13 +04:00
|
|
|
DEBUG_TSMF("");
|
2017-01-17 12:03:05 +03:00
|
|
|
|
2015-03-30 18:15:45 +03:00
|
|
|
if (!Stream_EnsureRemainingCapacity(ifman->output, 8))
|
2015-06-29 16:21:53 +03:00
|
|
|
return ERROR_OUTOFMEMORY;
|
|
|
|
|
2013-05-09 00:09:16 +04:00
|
|
|
Stream_Write_UINT32(ifman->output, 1); /* TopologyReady */
|
|
|
|
Stream_Write_UINT32(ifman->output, 0); /* Result */
|
2011-09-19 18:54:09 +04:00
|
|
|
ifman->output_interface_id = TSMF_INTERFACE_DEFAULT | STREAM_ID_STUB;
|
2015-06-29 16:21:53 +03:00
|
|
|
return CHANNEL_RC_OK;
|
2011-09-19 18:54:09 +04:00
|
|
|
}
|
|
|
|
|
2015-08-27 15:25:09 +03:00
|
|
|
/**
|
|
|
|
* Function description
|
|
|
|
*
|
|
|
|
* @return 0 on success, otherwise a Win32 error code
|
|
|
|
*/
|
|
|
|
UINT tsmf_ifman_remove_stream(TSMF_IFMAN* ifman)
|
2011-09-19 18:54:09 +04:00
|
|
|
{
|
2015-06-29 16:21:53 +03:00
|
|
|
int status = CHANNEL_RC_OK;
|
2012-10-09 11:26:39 +04:00
|
|
|
UINT32 StreamId;
|
2014-11-10 22:02:54 +03:00
|
|
|
TSMF_STREAM* stream;
|
|
|
|
TSMF_PRESENTATION* presentation;
|
2014-05-23 15:49:13 +04:00
|
|
|
DEBUG_TSMF("");
|
2014-11-10 22:02:54 +03:00
|
|
|
|
2015-06-29 16:21:53 +03:00
|
|
|
if (Stream_GetRemainingLength(ifman->input) < 20)
|
|
|
|
return ERROR_INVALID_DATA;
|
|
|
|
|
2013-04-30 06:35:15 +04:00
|
|
|
presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input));
|
2015-06-29 16:21:53 +03:00
|
|
|
Stream_Seek(ifman->input, GUID_SIZE);
|
2014-11-10 22:02:54 +03:00
|
|
|
|
|
|
|
if (!presentation)
|
2012-11-20 08:49:08 +04:00
|
|
|
{
|
2015-06-29 16:21:53 +03:00
|
|
|
status = ERROR_NOT_FOUND;
|
2012-11-20 08:49:08 +04:00
|
|
|
}
|
2011-09-19 18:54:09 +04:00
|
|
|
else
|
|
|
|
{
|
2013-05-09 00:09:16 +04:00
|
|
|
Stream_Read_UINT32(ifman->input, StreamId);
|
2011-09-19 18:54:09 +04:00
|
|
|
stream = tsmf_stream_find_by_id(presentation, StreamId);
|
2014-11-10 22:02:54 +03:00
|
|
|
|
|
|
|
if (stream)
|
2011-09-19 18:54:09 +04:00
|
|
|
tsmf_stream_free(stream);
|
|
|
|
else
|
2015-06-29 16:21:53 +03:00
|
|
|
status = ERROR_NOT_FOUND;
|
2011-09-19 18:54:09 +04:00
|
|
|
}
|
2014-11-10 22:02:54 +03:00
|
|
|
|
2012-10-09 10:31:28 +04:00
|
|
|
ifman->output_pending = TRUE;
|
2012-11-20 08:49:08 +04:00
|
|
|
return status;
|
2011-09-19 18:54:09 +04:00
|
|
|
}
|
|
|
|
|
2017-01-17 12:03:05 +03:00
|
|
|
float tsmf_stream_read_float(wStream* s)
|
2013-05-11 01:36:27 +04:00
|
|
|
{
|
|
|
|
float fValue;
|
|
|
|
UINT32 iValue;
|
|
|
|
Stream_Read_UINT32(s, iValue);
|
|
|
|
CopyMemory(&fValue, &iValue, 4);
|
|
|
|
return fValue;
|
|
|
|
}
|
|
|
|
|
2015-08-27 15:25:09 +03:00
|
|
|
/**
|
|
|
|
* Function description
|
|
|
|
*
|
|
|
|
* @return 0 on success, otherwise a Win32 error code
|
|
|
|
*/
|
|
|
|
UINT tsmf_ifman_set_source_video_rect(TSMF_IFMAN* ifman)
|
2013-05-11 01:36:27 +04:00
|
|
|
{
|
2015-08-27 15:25:09 +03:00
|
|
|
UINT status = CHANNEL_RC_OK;
|
2013-05-11 01:36:27 +04:00
|
|
|
float Left, Top;
|
|
|
|
float Right, Bottom;
|
2014-11-10 22:02:54 +03:00
|
|
|
TSMF_PRESENTATION* presentation;
|
2014-05-23 15:49:13 +04:00
|
|
|
DEBUG_TSMF("");
|
2014-11-10 22:02:54 +03:00
|
|
|
|
2015-06-29 16:21:53 +03:00
|
|
|
if (Stream_GetRemainingLength(ifman->input) < 32)
|
|
|
|
return ERROR_INVALID_DATA;
|
|
|
|
|
2013-05-11 01:36:27 +04:00
|
|
|
presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input));
|
2015-06-29 16:21:53 +03:00
|
|
|
Stream_Seek(ifman->input, GUID_SIZE);
|
2014-11-10 22:02:54 +03:00
|
|
|
|
|
|
|
if (!presentation)
|
2013-05-11 01:36:27 +04:00
|
|
|
{
|
2015-06-29 16:21:53 +03:00
|
|
|
status = ERROR_NOT_FOUND;
|
2013-05-11 01:36:27 +04:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Left = tsmf_stream_read_float(ifman->input); /* Left (4 bytes) */
|
|
|
|
Top = tsmf_stream_read_float(ifman->input); /* Top (4 bytes) */
|
|
|
|
Right = tsmf_stream_read_float(ifman->input); /* Right (4 bytes) */
|
|
|
|
Bottom = tsmf_stream_read_float(ifman->input); /* Bottom (4 bytes) */
|
2014-05-23 15:49:13 +04:00
|
|
|
DEBUG_TSMF("SetSourceVideoRect: Left: %f Top: %f Right: %f Bottom: %f",
|
2017-01-17 12:03:05 +03:00
|
|
|
Left, Top, Right, Bottom);
|
2013-05-11 01:36:27 +04:00
|
|
|
}
|
2014-11-10 22:02:54 +03:00
|
|
|
|
2013-05-29 20:21:54 +04:00
|
|
|
ifman->output_pending = TRUE;
|
2013-05-11 01:36:27 +04:00
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
2015-08-27 15:25:09 +03:00
|
|
|
/**
|
|
|
|
* Function description
|
|
|
|
*
|
|
|
|
* @return 0 on success, otherwise a Win32 error code
|
|
|
|
*/
|
|
|
|
UINT tsmf_ifman_shutdown_presentation(TSMF_IFMAN* ifman)
|
2011-09-19 18:54:09 +04:00
|
|
|
{
|
2014-11-10 22:02:54 +03:00
|
|
|
TSMF_PRESENTATION* presentation;
|
2014-05-23 15:49:13 +04:00
|
|
|
DEBUG_TSMF("");
|
2014-11-10 22:02:54 +03:00
|
|
|
|
2015-06-29 16:21:53 +03:00
|
|
|
if (Stream_GetRemainingLength(ifman->input) < GUID_SIZE)
|
|
|
|
return ERROR_INVALID_DATA;
|
2014-11-10 22:02:54 +03:00
|
|
|
|
2015-06-29 16:21:53 +03:00
|
|
|
presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input));
|
2014-11-10 22:02:54 +03:00
|
|
|
|
|
|
|
if (presentation)
|
2011-09-19 18:54:09 +04:00
|
|
|
tsmf_presentation_free(presentation);
|
2013-06-19 20:33:46 +04:00
|
|
|
else
|
2015-06-29 16:21:53 +03:00
|
|
|
{
|
2014-09-12 18:19:32 +04:00
|
|
|
WLog_ERR(TAG, "unknown presentation id");
|
2015-06-29 16:21:53 +03:00
|
|
|
return ERROR_NOT_FOUND;
|
|
|
|
}
|
2014-11-10 22:02:54 +03:00
|
|
|
|
2015-03-30 18:15:45 +03:00
|
|
|
if (!Stream_EnsureRemainingCapacity(ifman->output, 4))
|
2015-06-29 16:21:53 +03:00
|
|
|
return ERROR_OUTOFMEMORY;
|
|
|
|
|
2013-05-09 00:09:16 +04:00
|
|
|
Stream_Write_UINT32(ifman->output, 0); /* Result */
|
2011-09-19 18:54:09 +04:00
|
|
|
ifman->output_interface_id = TSMF_INTERFACE_DEFAULT | STREAM_ID_STUB;
|
2015-06-29 16:21:53 +03:00
|
|
|
return CHANNEL_RC_OK;
|
2011-09-19 18:54:09 +04:00
|
|
|
}
|
|
|
|
|
2015-08-27 15:25:09 +03:00
|
|
|
/**
|
|
|
|
* Function description
|
|
|
|
*
|
|
|
|
* @return 0 on success, otherwise a Win32 error code
|
|
|
|
*/
|
|
|
|
UINT tsmf_ifman_on_stream_volume(TSMF_IFMAN* ifman)
|
2011-09-19 18:54:09 +04:00
|
|
|
{
|
2014-11-10 22:02:54 +03:00
|
|
|
TSMF_PRESENTATION* presentation;
|
2015-06-29 16:21:53 +03:00
|
|
|
UINT32 newVolume;
|
|
|
|
UINT32 muted;
|
2014-05-23 15:49:13 +04:00
|
|
|
DEBUG_TSMF("on stream volume");
|
2015-06-29 16:21:53 +03:00
|
|
|
|
|
|
|
if (Stream_GetRemainingLength(ifman->input) < GUID_SIZE + 8)
|
|
|
|
return ERROR_INVALID_DATA;
|
|
|
|
|
2013-04-30 06:35:15 +04:00
|
|
|
presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input));
|
2014-11-10 22:02:54 +03:00
|
|
|
|
2015-06-29 16:21:53 +03:00
|
|
|
if (!presentation)
|
2012-07-29 06:24:14 +04:00
|
|
|
{
|
2014-09-12 18:19:32 +04:00
|
|
|
WLog_ERR(TAG, "unknown presentation id");
|
2015-06-29 16:21:53 +03:00
|
|
|
return ERROR_NOT_FOUND;
|
2012-07-29 06:24:14 +04:00
|
|
|
}
|
2014-11-10 22:02:54 +03:00
|
|
|
|
2015-06-29 16:21:53 +03:00
|
|
|
Stream_Seek(ifman->input, 16);
|
|
|
|
Stream_Read_UINT32(ifman->input, newVolume);
|
2016-12-14 00:47:08 +03:00
|
|
|
DEBUG_TSMF("on stream volume: new volume=[%"PRIu32"]", newVolume);
|
2015-06-29 16:21:53 +03:00
|
|
|
Stream_Read_UINT32(ifman->input, muted);
|
2016-12-14 00:47:08 +03:00
|
|
|
DEBUG_TSMF("on stream volume: muted=[%"PRIu32"]", muted);
|
2015-06-29 16:21:53 +03:00
|
|
|
|
|
|
|
if (!tsmf_presentation_volume_changed(presentation, newVolume, muted))
|
|
|
|
return ERROR_INVALID_OPERATION;
|
|
|
|
|
2012-10-09 10:31:28 +04:00
|
|
|
ifman->output_pending = TRUE;
|
2011-09-19 18:54:09 +04:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2015-08-27 15:25:09 +03:00
|
|
|
/**
|
|
|
|
* Function description
|
|
|
|
*
|
|
|
|
* @return 0 on success, otherwise a Win32 error code
|
|
|
|
*/
|
|
|
|
UINT tsmf_ifman_on_channel_volume(TSMF_IFMAN* ifman)
|
2011-09-19 18:54:09 +04:00
|
|
|
{
|
2014-11-10 22:02:54 +03:00
|
|
|
TSMF_PRESENTATION* presentation;
|
2014-05-23 15:49:13 +04:00
|
|
|
DEBUG_TSMF("on channel volume");
|
2014-11-10 22:02:54 +03:00
|
|
|
|
2015-06-29 16:21:53 +03:00
|
|
|
if (Stream_GetRemainingLength(ifman->input) < GUID_SIZE + 8)
|
|
|
|
return ERROR_INVALID_DATA;
|
2014-11-10 22:02:54 +03:00
|
|
|
|
2015-06-29 16:21:53 +03:00
|
|
|
presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input));
|
2014-11-10 22:02:54 +03:00
|
|
|
|
|
|
|
if (presentation)
|
2012-06-13 23:45:58 +04:00
|
|
|
{
|
2012-10-09 11:26:39 +04:00
|
|
|
UINT32 channelVolume;
|
|
|
|
UINT32 changedChannel;
|
2013-04-30 06:35:15 +04:00
|
|
|
Stream_Seek(ifman->input, 16);
|
2013-05-09 00:09:16 +04:00
|
|
|
Stream_Read_UINT32(ifman->input, channelVolume);
|
2016-12-14 00:47:08 +03:00
|
|
|
DEBUG_TSMF("on channel volume: channel volume=[%"PRIu32"]", channelVolume);
|
2013-05-09 00:09:16 +04:00
|
|
|
Stream_Read_UINT32(ifman->input, changedChannel);
|
2016-12-14 00:47:08 +03:00
|
|
|
DEBUG_TSMF("on stream volume: changed channel=[%"PRIu32"]", changedChannel);
|
2012-06-13 23:45:58 +04:00
|
|
|
}
|
2014-11-10 22:02:54 +03:00
|
|
|
|
2012-10-09 10:31:28 +04:00
|
|
|
ifman->output_pending = TRUE;
|
2015-06-29 16:21:53 +03:00
|
|
|
return CHANNEL_RC_OK;
|
2011-09-19 18:54:09 +04:00
|
|
|
}
|
|
|
|
|
2015-08-27 15:25:09 +03:00
|
|
|
/**
|
|
|
|
* Function description
|
|
|
|
*
|
|
|
|
* @return 0 on success, otherwise a Win32 error code
|
|
|
|
*/
|
|
|
|
UINT tsmf_ifman_set_video_window(TSMF_IFMAN* ifman)
|
2011-09-19 18:54:09 +04:00
|
|
|
{
|
2014-05-23 15:49:13 +04:00
|
|
|
DEBUG_TSMF("");
|
2012-10-09 10:31:28 +04:00
|
|
|
ifman->output_pending = TRUE;
|
2015-06-29 16:21:53 +03:00
|
|
|
return CHANNEL_RC_OK;
|
2011-09-19 18:54:09 +04:00
|
|
|
}
|
|
|
|
|
2015-08-27 15:25:09 +03:00
|
|
|
/**
|
|
|
|
* Function description
|
|
|
|
*
|
|
|
|
* @return 0 on success, otherwise a Win32 error code
|
|
|
|
*/
|
|
|
|
UINT tsmf_ifman_update_geometry_info(TSMF_IFMAN* ifman)
|
2011-09-19 18:54:09 +04:00
|
|
|
{
|
2014-11-10 22:02:54 +03:00
|
|
|
TSMF_PRESENTATION* presentation;
|
2012-10-09 11:26:39 +04:00
|
|
|
UINT32 numGeometryInfo;
|
|
|
|
UINT32 Left;
|
|
|
|
UINT32 Top;
|
|
|
|
UINT32 Width;
|
|
|
|
UINT32 Height;
|
|
|
|
UINT32 cbVisibleRect;
|
2017-01-17 12:03:05 +03:00
|
|
|
RDP_RECT* rects = NULL;
|
2011-09-19 18:54:09 +04:00
|
|
|
int num_rects = 0;
|
2015-08-27 15:25:09 +03:00
|
|
|
UINT error = CHANNEL_RC_OK;
|
2011-09-19 18:54:09 +04:00
|
|
|
int i;
|
2017-12-11 12:25:21 +03:00
|
|
|
size_t pos;
|
2015-06-29 16:21:53 +03:00
|
|
|
|
|
|
|
if (Stream_GetRemainingLength(ifman->input) < GUID_SIZE + 32)
|
|
|
|
return ERROR_INVALID_DATA;
|
|
|
|
|
2013-04-30 06:35:15 +04:00
|
|
|
presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input));
|
2017-01-17 12:03:05 +03:00
|
|
|
|
2015-06-29 16:21:53 +03:00
|
|
|
if (!presentation)
|
|
|
|
return ERROR_NOT_FOUND;
|
|
|
|
|
2013-04-30 06:35:15 +04:00
|
|
|
Stream_Seek(ifman->input, 16);
|
2013-05-09 00:09:16 +04:00
|
|
|
Stream_Read_UINT32(ifman->input, numGeometryInfo);
|
2013-04-30 06:35:15 +04:00
|
|
|
pos = Stream_GetPosition(ifman->input);
|
|
|
|
Stream_Seek(ifman->input, 12); /* VideoWindowId (8 bytes), VideoWindowState (4 bytes) */
|
2013-05-09 00:09:16 +04:00
|
|
|
Stream_Read_UINT32(ifman->input, Width);
|
|
|
|
Stream_Read_UINT32(ifman->input, Height);
|
|
|
|
Stream_Read_UINT32(ifman->input, Left);
|
|
|
|
Stream_Read_UINT32(ifman->input, Top);
|
2013-04-30 06:35:15 +04:00
|
|
|
Stream_SetPosition(ifman->input, pos + numGeometryInfo);
|
2013-05-09 00:09:16 +04:00
|
|
|
Stream_Read_UINT32(ifman->input, cbVisibleRect);
|
2011-09-19 18:54:09 +04:00
|
|
|
num_rects = cbVisibleRect / 16;
|
2016-12-14 00:47:08 +03:00
|
|
|
DEBUG_TSMF("numGeometryInfo %"PRIu32" Width %"PRIu32" Height %"PRIu32" Left %"PRIu32" Top %"PRIu32" cbVisibleRect %"PRIu32" num_rects %d",
|
2017-01-17 12:03:05 +03:00
|
|
|
numGeometryInfo, Width, Height, Left, Top, cbVisibleRect, num_rects);
|
2015-06-29 16:21:53 +03:00
|
|
|
|
|
|
|
if (num_rects > 0)
|
2011-09-19 18:54:09 +04:00
|
|
|
{
|
2015-06-29 16:21:53 +03:00
|
|
|
rects = (RDP_RECT*) calloc(num_rects, sizeof(RDP_RECT));
|
|
|
|
|
|
|
|
for (i = 0; i < num_rects; i++)
|
2011-09-19 18:54:09 +04:00
|
|
|
{
|
2015-06-29 16:21:53 +03:00
|
|
|
Stream_Read_UINT16(ifman->input, rects[i].y); /* Top */
|
|
|
|
Stream_Seek_UINT16(ifman->input);
|
|
|
|
Stream_Read_UINT16(ifman->input, rects[i].x); /* Left */
|
|
|
|
Stream_Seek_UINT16(ifman->input);
|
|
|
|
Stream_Read_UINT16(ifman->input, rects[i].height); /* Bottom */
|
|
|
|
Stream_Seek_UINT16(ifman->input);
|
|
|
|
Stream_Read_UINT16(ifman->input, rects[i].width); /* Right */
|
|
|
|
Stream_Seek_UINT16(ifman->input);
|
|
|
|
rects[i].width -= rects[i].x;
|
|
|
|
rects[i].height -= rects[i].y;
|
2016-12-14 00:47:08 +03:00
|
|
|
DEBUG_TSMF("rect %d: %"PRId16" %"PRId16" %"PRId16" %"PRId16"", i,
|
2017-01-17 12:03:05 +03:00
|
|
|
rects[i].x, rects[i].y, rects[i].width, rects[i].height);
|
2011-09-19 18:54:09 +04:00
|
|
|
}
|
|
|
|
}
|
2014-11-10 22:02:54 +03:00
|
|
|
|
2015-06-29 16:21:53 +03:00
|
|
|
if (!tsmf_presentation_set_geometry_info(presentation, Left, Top, Width, Height, num_rects, rects))
|
|
|
|
return ERROR_INVALID_OPERATION;
|
|
|
|
|
2012-10-09 10:31:28 +04:00
|
|
|
ifman->output_pending = TRUE;
|
2011-09-19 18:54:09 +04:00
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
2015-08-27 15:25:09 +03:00
|
|
|
/**
|
|
|
|
* Function description
|
|
|
|
*
|
|
|
|
* @return 0 on success, otherwise a Win32 error code
|
|
|
|
*/
|
|
|
|
UINT tsmf_ifman_set_allocator(TSMF_IFMAN* ifman)
|
2011-09-19 18:54:09 +04:00
|
|
|
{
|
2014-05-23 15:49:13 +04:00
|
|
|
DEBUG_TSMF("");
|
2012-10-09 10:31:28 +04:00
|
|
|
ifman->output_pending = TRUE;
|
2015-06-29 16:21:53 +03:00
|
|
|
return CHANNEL_RC_OK;
|
2011-09-19 18:54:09 +04:00
|
|
|
}
|
|
|
|
|
2015-08-27 15:25:09 +03:00
|
|
|
/**
|
|
|
|
* Function description
|
|
|
|
*
|
|
|
|
* @return 0 on success, otherwise a Win32 error code
|
|
|
|
*/
|
|
|
|
UINT tsmf_ifman_notify_preroll(TSMF_IFMAN* ifman)
|
2011-09-19 18:54:09 +04:00
|
|
|
{
|
2014-05-23 15:49:13 +04:00
|
|
|
DEBUG_TSMF("");
|
2015-07-08 00:39:29 +03:00
|
|
|
tsmf_ifman_on_playback_paused(ifman);
|
2012-10-09 10:31:28 +04:00
|
|
|
ifman->output_pending = TRUE;
|
2015-06-29 16:21:53 +03:00
|
|
|
return CHANNEL_RC_OK;
|
2011-09-19 18:54:09 +04:00
|
|
|
}
|
|
|
|
|
2015-08-27 15:25:09 +03:00
|
|
|
/**
|
|
|
|
* Function description
|
|
|
|
*
|
|
|
|
* @return 0 on success, otherwise a Win32 error code
|
|
|
|
*/
|
|
|
|
UINT tsmf_ifman_on_sample(TSMF_IFMAN* ifman)
|
2011-09-19 18:54:09 +04:00
|
|
|
{
|
2014-11-10 22:02:54 +03:00
|
|
|
TSMF_PRESENTATION* presentation;
|
|
|
|
TSMF_STREAM* stream;
|
2012-10-09 11:26:39 +04:00
|
|
|
UINT32 StreamId;
|
|
|
|
UINT64 SampleStartTime;
|
|
|
|
UINT64 SampleEndTime;
|
|
|
|
UINT64 ThrottleDuration;
|
|
|
|
UINT32 SampleExtensions;
|
|
|
|
UINT32 cbData;
|
2016-11-25 14:40:11 +03:00
|
|
|
UINT error;
|
2014-11-10 22:02:54 +03:00
|
|
|
|
2015-06-29 16:21:53 +03:00
|
|
|
if (Stream_GetRemainingLength(ifman->input) < 60)
|
|
|
|
return ERROR_INVALID_DATA;
|
2014-11-10 22:02:54 +03:00
|
|
|
|
2013-04-30 06:35:15 +04:00
|
|
|
Stream_Seek(ifman->input, 16);
|
2013-05-09 00:09:16 +04:00
|
|
|
Stream_Read_UINT32(ifman->input, StreamId);
|
2013-04-30 06:35:15 +04:00
|
|
|
Stream_Seek_UINT32(ifman->input); /* numSample */
|
2013-05-09 00:09:16 +04:00
|
|
|
Stream_Read_UINT64(ifman->input, SampleStartTime);
|
|
|
|
Stream_Read_UINT64(ifman->input, SampleEndTime);
|
|
|
|
Stream_Read_UINT64(ifman->input, ThrottleDuration);
|
2013-04-30 06:35:15 +04:00
|
|
|
Stream_Seek_UINT32(ifman->input); /* SampleFlags */
|
2013-05-09 00:09:16 +04:00
|
|
|
Stream_Read_UINT32(ifman->input, SampleExtensions);
|
|
|
|
Stream_Read_UINT32(ifman->input, cbData);
|
2014-11-10 22:02:54 +03:00
|
|
|
|
2015-06-29 16:21:53 +03:00
|
|
|
if (Stream_GetRemainingLength(ifman->input) < cbData)
|
|
|
|
return ERROR_INVALID_DATA;
|
|
|
|
|
2016-12-14 00:47:08 +03:00
|
|
|
DEBUG_TSMF("MessageId %"PRIu32" StreamId %"PRIu32" SampleStartTime %"PRIu64" SampleEndTime %"PRIu64" "
|
2017-01-17 12:03:05 +03:00
|
|
|
"ThrottleDuration %"PRIu64" SampleExtensions %"PRIu32" cbData %"PRIu32"",
|
|
|
|
ifman->message_id, StreamId, SampleStartTime, SampleEndTime,
|
|
|
|
ThrottleDuration, SampleExtensions, cbData);
|
2011-09-19 18:54:09 +04:00
|
|
|
presentation = tsmf_presentation_find_by_id(ifman->presentation_id);
|
2014-11-10 22:02:54 +03:00
|
|
|
|
|
|
|
if (!presentation)
|
2011-09-19 18:54:09 +04:00
|
|
|
{
|
2014-09-12 18:19:32 +04:00
|
|
|
WLog_ERR(TAG, "unknown presentation id");
|
2015-06-29 16:21:53 +03:00
|
|
|
return ERROR_NOT_FOUND;
|
2011-09-19 18:54:09 +04:00
|
|
|
}
|
2014-11-10 22:02:54 +03:00
|
|
|
|
2011-09-19 18:54:09 +04:00
|
|
|
stream = tsmf_stream_find_by_id(presentation, StreamId);
|
2014-11-10 22:02:54 +03:00
|
|
|
|
|
|
|
if (!stream)
|
2011-09-19 18:54:09 +04:00
|
|
|
{
|
2014-09-12 18:19:32 +04:00
|
|
|
WLog_ERR(TAG, "unknown stream id");
|
2015-06-29 16:21:53 +03:00
|
|
|
return ERROR_NOT_FOUND;
|
2011-09-19 18:54:09 +04:00
|
|
|
}
|
2014-11-10 22:02:54 +03:00
|
|
|
|
2015-06-29 16:21:53 +03:00
|
|
|
if (!tsmf_stream_push_sample(stream, ifman->channel_callback,
|
2017-01-17 12:03:05 +03:00
|
|
|
ifman->message_id, SampleStartTime, SampleEndTime,
|
|
|
|
ThrottleDuration, SampleExtensions, cbData, Stream_Pointer(ifman->input)))
|
2015-06-29 16:21:53 +03:00
|
|
|
{
|
|
|
|
WLog_ERR(TAG, "unable to push sample");
|
|
|
|
return ERROR_OUTOFMEMORY;
|
|
|
|
}
|
2014-11-10 22:02:54 +03:00
|
|
|
|
2015-07-30 16:49:21 +03:00
|
|
|
if ((error = tsmf_presentation_sync(presentation)))
|
2017-01-17 12:03:05 +03:00
|
|
|
{
|
|
|
|
WLog_ERR(TAG, "tsmf_presentation_sync failed with error %"PRIu32"", error);
|
|
|
|
return error;
|
|
|
|
}
|
2014-11-10 22:02:54 +03:00
|
|
|
|
2017-01-17 12:03:05 +03:00
|
|
|
ifman->output_pending = TRUE;
|
2015-06-29 16:21:53 +03:00
|
|
|
return CHANNEL_RC_OK;
|
2011-09-19 18:54:09 +04:00
|
|
|
}
|
|
|
|
|
2015-08-27 15:25:09 +03:00
|
|
|
/**
|
|
|
|
* Function description
|
|
|
|
*
|
|
|
|
* @return 0 on success, otherwise a Win32 error code
|
|
|
|
*/
|
|
|
|
UINT tsmf_ifman_on_flush(TSMF_IFMAN* ifman)
|
2011-09-19 18:54:09 +04:00
|
|
|
{
|
2012-10-09 11:26:39 +04:00
|
|
|
UINT32 StreamId;
|
2014-11-10 22:02:54 +03:00
|
|
|
TSMF_PRESENTATION* presentation;
|
2015-07-08 00:39:29 +03:00
|
|
|
TSMF_STREAM* stream;
|
2014-11-10 22:02:54 +03:00
|
|
|
|
2015-06-29 16:21:53 +03:00
|
|
|
if (Stream_GetRemainingLength(ifman->input) < 20)
|
|
|
|
return ERROR_INVALID_DATA;
|
|
|
|
|
2013-04-30 06:35:15 +04:00
|
|
|
Stream_Seek(ifman->input, 16);
|
2013-05-09 00:09:16 +04:00
|
|
|
Stream_Read_UINT32(ifman->input, StreamId);
|
2016-12-14 00:47:08 +03:00
|
|
|
DEBUG_TSMF("StreamId %"PRIu32"", StreamId);
|
2011-09-19 18:54:09 +04:00
|
|
|
presentation = tsmf_presentation_find_by_id(ifman->presentation_id);
|
2014-11-10 22:02:54 +03:00
|
|
|
|
|
|
|
if (!presentation)
|
2011-09-19 18:54:09 +04:00
|
|
|
{
|
2014-09-12 18:19:32 +04:00
|
|
|
WLog_ERR(TAG, "unknown presentation id");
|
2015-06-29 16:21:53 +03:00
|
|
|
return ERROR_NOT_FOUND;
|
2011-09-19 18:54:09 +04:00
|
|
|
}
|
2014-11-10 22:02:54 +03:00
|
|
|
|
2015-07-08 21:10:21 +03:00
|
|
|
/* Flush message is for a stream, not the entire presentation
|
|
|
|
* therefore we only flush the stream as intended per the MS-RDPEV spec
|
|
|
|
*/
|
2015-07-08 00:39:29 +03:00
|
|
|
stream = tsmf_stream_find_by_id(presentation, StreamId);
|
2014-11-10 22:02:54 +03:00
|
|
|
|
2015-07-08 00:39:29 +03:00
|
|
|
if (stream)
|
2015-09-03 20:58:16 +03:00
|
|
|
{
|
2015-07-08 00:39:29 +03:00
|
|
|
if (!tsmf_stream_flush(stream))
|
|
|
|
return ERROR_INVALID_OPERATION;
|
2015-09-03 20:58:16 +03:00
|
|
|
}
|
2015-07-08 00:39:29 +03:00
|
|
|
else
|
|
|
|
WLog_ERR(TAG, "unknown stream id");
|
|
|
|
|
2012-10-09 10:31:28 +04:00
|
|
|
ifman->output_pending = TRUE;
|
2015-06-29 16:21:53 +03:00
|
|
|
return CHANNEL_RC_OK;
|
2011-09-19 18:54:09 +04:00
|
|
|
}
|
|
|
|
|
2015-08-27 15:25:09 +03:00
|
|
|
/**
|
|
|
|
* Function description
|
|
|
|
*
|
|
|
|
* @return 0 on success, otherwise a Win32 error code
|
|
|
|
*/
|
|
|
|
UINT tsmf_ifman_on_end_of_stream(TSMF_IFMAN* ifman)
|
2011-09-19 18:54:09 +04:00
|
|
|
{
|
2012-10-09 11:26:39 +04:00
|
|
|
UINT32 StreamId;
|
2015-07-08 00:39:29 +03:00
|
|
|
TSMF_STREAM* stream = NULL;
|
2014-11-10 22:02:54 +03:00
|
|
|
TSMF_PRESENTATION* presentation;
|
|
|
|
|
2015-06-29 16:21:53 +03:00
|
|
|
if (Stream_GetRemainingLength(ifman->input) < 20)
|
|
|
|
return ERROR_INVALID_DATA;
|
|
|
|
|
2013-04-30 06:35:15 +04:00
|
|
|
presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input));
|
|
|
|
Stream_Seek(ifman->input, 16);
|
2013-05-09 00:09:16 +04:00
|
|
|
Stream_Read_UINT32(ifman->input, StreamId);
|
2014-11-10 22:02:54 +03:00
|
|
|
|
|
|
|
if (presentation)
|
2012-05-16 17:29:35 +04:00
|
|
|
{
|
|
|
|
stream = tsmf_stream_find_by_id(presentation, StreamId);
|
2014-11-10 22:02:54 +03:00
|
|
|
|
|
|
|
if (stream)
|
2017-01-17 12:03:05 +03:00
|
|
|
tsmf_stream_end(stream, ifman->message_id, ifman->channel_callback);
|
2012-05-16 17:29:35 +04:00
|
|
|
}
|
2014-11-10 22:02:54 +03:00
|
|
|
|
2016-12-14 00:47:08 +03:00
|
|
|
DEBUG_TSMF("StreamId %"PRIu32"", StreamId);
|
2015-07-08 00:39:29 +03:00
|
|
|
ifman->output_pending = TRUE;
|
2015-06-29 16:21:53 +03:00
|
|
|
ifman->output_interface_id = TSMF_INTERFACE_CLIENT_NOTIFICATIONS | STREAM_ID_PROXY;
|
|
|
|
return CHANNEL_RC_OK;
|
2011-09-19 18:54:09 +04:00
|
|
|
}
|
|
|
|
|
2015-08-27 15:25:09 +03:00
|
|
|
/**
|
|
|
|
* Function description
|
|
|
|
*
|
|
|
|
* @return 0 on success, otherwise a Win32 error code
|
|
|
|
*/
|
|
|
|
UINT tsmf_ifman_on_playback_started(TSMF_IFMAN* ifman)
|
2011-09-19 18:54:09 +04:00
|
|
|
{
|
2014-11-10 22:02:54 +03:00
|
|
|
TSMF_PRESENTATION* presentation;
|
2014-05-23 15:49:13 +04:00
|
|
|
DEBUG_TSMF("");
|
2014-11-10 22:02:54 +03:00
|
|
|
|
2015-06-29 16:21:53 +03:00
|
|
|
if (Stream_GetRemainingLength(ifman->input) < 16)
|
|
|
|
return ERROR_INVALID_DATA;
|
|
|
|
|
2013-04-30 06:35:15 +04:00
|
|
|
presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input));
|
2014-11-10 22:02:54 +03:00
|
|
|
|
|
|
|
if (presentation)
|
2011-09-19 18:54:09 +04:00
|
|
|
tsmf_presentation_start(presentation);
|
|
|
|
else
|
2014-09-12 18:19:32 +04:00
|
|
|
WLog_ERR(TAG, "unknown presentation id");
|
2014-11-10 22:02:54 +03:00
|
|
|
|
2015-03-30 18:15:45 +03:00
|
|
|
if (!Stream_EnsureRemainingCapacity(ifman->output, 16))
|
2015-06-29 16:21:53 +03:00
|
|
|
return ERROR_OUTOFMEMORY;
|
|
|
|
|
2013-05-09 00:09:16 +04:00
|
|
|
Stream_Write_UINT32(ifman->output, CLIENT_EVENT_NOTIFICATION); /* FunctionId */
|
|
|
|
Stream_Write_UINT32(ifman->output, 0); /* StreamId */
|
|
|
|
Stream_Write_UINT32(ifman->output, TSMM_CLIENT_EVENT_START_COMPLETED); /* EventId */
|
|
|
|
Stream_Write_UINT32(ifman->output, 0); /* cbData */
|
2011-09-19 18:54:09 +04:00
|
|
|
ifman->output_interface_id = TSMF_INTERFACE_CLIENT_NOTIFICATIONS | STREAM_ID_PROXY;
|
2015-06-29 16:21:53 +03:00
|
|
|
return CHANNEL_RC_OK;
|
2011-09-19 18:54:09 +04:00
|
|
|
}
|
|
|
|
|
2015-08-27 15:25:09 +03:00
|
|
|
/**
|
|
|
|
* Function description
|
|
|
|
*
|
|
|
|
* @return 0 on success, otherwise a Win32 error code
|
|
|
|
*/
|
|
|
|
UINT tsmf_ifman_on_playback_paused(TSMF_IFMAN* ifman)
|
2011-09-19 18:54:09 +04:00
|
|
|
{
|
2014-11-10 22:02:54 +03:00
|
|
|
TSMF_PRESENTATION* presentation;
|
2014-05-23 15:49:13 +04:00
|
|
|
DEBUG_TSMF("");
|
2012-10-09 10:31:28 +04:00
|
|
|
ifman->output_pending = TRUE;
|
2012-06-13 23:45:58 +04:00
|
|
|
/* Added pause control so gstreamer pipeline can be paused accordingly */
|
2013-04-30 06:35:15 +04:00
|
|
|
presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input));
|
2014-11-10 22:02:54 +03:00
|
|
|
|
|
|
|
if (presentation)
|
2015-06-29 16:21:53 +03:00
|
|
|
{
|
|
|
|
if (!tsmf_presentation_paused(presentation))
|
|
|
|
return ERROR_INVALID_OPERATION;
|
|
|
|
}
|
2012-06-13 23:45:58 +04:00
|
|
|
else
|
2014-09-12 18:19:32 +04:00
|
|
|
WLog_ERR(TAG, "unknown presentation id");
|
2014-11-10 22:02:54 +03:00
|
|
|
|
2015-06-29 16:21:53 +03:00
|
|
|
return CHANNEL_RC_OK;
|
2011-09-19 18:54:09 +04:00
|
|
|
}
|
|
|
|
|
2015-08-27 15:25:09 +03:00
|
|
|
/**
|
|
|
|
* Function description
|
|
|
|
*
|
|
|
|
* @return 0 on success, otherwise a Win32 error code
|
|
|
|
*/
|
|
|
|
UINT tsmf_ifman_on_playback_restarted(TSMF_IFMAN* ifman)
|
2011-09-19 18:54:09 +04:00
|
|
|
{
|
2014-11-10 22:02:54 +03:00
|
|
|
TSMF_PRESENTATION* presentation;
|
2014-05-23 15:49:13 +04:00
|
|
|
DEBUG_TSMF("");
|
2012-10-09 10:31:28 +04:00
|
|
|
ifman->output_pending = TRUE;
|
2012-06-13 23:45:58 +04:00
|
|
|
/* Added restart control so gstreamer pipeline can be resumed accordingly */
|
2013-04-30 06:35:15 +04:00
|
|
|
presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input));
|
2014-11-10 22:02:54 +03:00
|
|
|
|
|
|
|
if (presentation)
|
2015-06-29 16:21:53 +03:00
|
|
|
{
|
|
|
|
if (!tsmf_presentation_restarted(presentation))
|
|
|
|
return ERROR_INVALID_OPERATION;
|
|
|
|
}
|
2012-06-13 23:45:58 +04:00
|
|
|
else
|
2014-09-12 18:19:32 +04:00
|
|
|
WLog_ERR(TAG, "unknown presentation id");
|
2014-11-10 22:02:54 +03:00
|
|
|
|
2015-06-29 16:21:53 +03:00
|
|
|
return CHANNEL_RC_OK;
|
2011-09-19 18:54:09 +04:00
|
|
|
}
|
|
|
|
|
2015-08-27 15:25:09 +03:00
|
|
|
/**
|
|
|
|
* Function description
|
|
|
|
*
|
|
|
|
* @return 0 on success, otherwise a Win32 error code
|
|
|
|
*/
|
|
|
|
UINT tsmf_ifman_on_playback_stopped(TSMF_IFMAN* ifman)
|
2011-09-19 18:54:09 +04:00
|
|
|
{
|
2014-11-10 22:02:54 +03:00
|
|
|
TSMF_PRESENTATION* presentation;
|
2014-05-23 15:49:13 +04:00
|
|
|
DEBUG_TSMF("");
|
2013-04-30 06:35:15 +04:00
|
|
|
presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input));
|
2014-11-10 22:02:54 +03:00
|
|
|
|
|
|
|
if (presentation)
|
2015-06-29 16:21:53 +03:00
|
|
|
{
|
|
|
|
if (!tsmf_presentation_stop(presentation))
|
|
|
|
return ERROR_INVALID_OPERATION;
|
|
|
|
}
|
2011-09-19 18:54:09 +04:00
|
|
|
else
|
2014-09-12 18:19:32 +04:00
|
|
|
WLog_ERR(TAG, "unknown presentation id");
|
2014-11-10 22:02:54 +03:00
|
|
|
|
2015-03-30 18:15:45 +03:00
|
|
|
if (!Stream_EnsureRemainingCapacity(ifman->output, 16))
|
2015-06-29 16:21:53 +03:00
|
|
|
return ERROR_OUTOFMEMORY;
|
|
|
|
|
2013-05-09 00:09:16 +04:00
|
|
|
Stream_Write_UINT32(ifman->output, CLIENT_EVENT_NOTIFICATION); /* FunctionId */
|
|
|
|
Stream_Write_UINT32(ifman->output, 0); /* StreamId */
|
|
|
|
Stream_Write_UINT32(ifman->output, TSMM_CLIENT_EVENT_STOP_COMPLETED); /* EventId */
|
|
|
|
Stream_Write_UINT32(ifman->output, 0); /* cbData */
|
2015-06-29 16:21:53 +03:00
|
|
|
ifman->output_interface_id = TSMF_INTERFACE_CLIENT_NOTIFICATIONS | STREAM_ID_PROXY;
|
|
|
|
return CHANNEL_RC_OK;
|
2011-09-19 18:54:09 +04:00
|
|
|
}
|
|
|
|
|
2015-08-27 15:25:09 +03:00
|
|
|
/**
|
|
|
|
* Function description
|
|
|
|
*
|
|
|
|
* @return 0 on success, otherwise a Win32 error code
|
|
|
|
*/
|
|
|
|
UINT tsmf_ifman_on_playback_rate_changed(TSMF_IFMAN* ifman)
|
2011-09-19 18:54:09 +04:00
|
|
|
{
|
2014-05-23 15:49:13 +04:00
|
|
|
DEBUG_TSMF("");
|
2015-06-29 16:21:53 +03:00
|
|
|
|
2015-03-30 18:15:45 +03:00
|
|
|
if (!Stream_EnsureRemainingCapacity(ifman->output, 16))
|
2015-06-29 16:21:53 +03:00
|
|
|
return ERROR_OUTOFMEMORY;
|
|
|
|
|
2013-05-09 00:09:16 +04:00
|
|
|
Stream_Write_UINT32(ifman->output, CLIENT_EVENT_NOTIFICATION); /* FunctionId */
|
|
|
|
Stream_Write_UINT32(ifman->output, 0); /* StreamId */
|
|
|
|
Stream_Write_UINT32(ifman->output, TSMM_CLIENT_EVENT_MONITORCHANGED); /* EventId */
|
|
|
|
Stream_Write_UINT32(ifman->output, 0); /* cbData */
|
2011-09-19 18:54:09 +04:00
|
|
|
ifman->output_interface_id = TSMF_INTERFACE_CLIENT_NOTIFICATIONS | STREAM_ID_PROXY;
|
2015-06-29 16:21:53 +03:00
|
|
|
return CHANNEL_RC_OK;
|
2011-09-19 18:54:09 +04:00
|
|
|
}
|