Blame channels/tsmf/client/tsmf_ifman.c

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