Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/FreeRDP/FreeRDP.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarc-André Moreau <marcandre.moreau@gmail.com>2014-06-12 17:51:57 +0400
committerMarc-André Moreau <marcandre.moreau@gmail.com>2014-06-12 17:51:57 +0400
commit9e14f5e1644e7c6b01eb4d3371018b03105dd9c2 (patch)
treeca5e3fd8748bc53d867cd85be050b463054eefa7
parent33b440731417b448ec6d0828318e872c5a66707d (diff)
parent43257415833ed4b2a58bcdc4752f9d3add915f30 (diff)
Merge pull request #1861 from akallabeth/tsmf-gstreamer-1.01.2.0-beta1+android7
Tsmf gstreamer 1.0 port and enhancements
-rwxr-xr-xCMakeLists.txt25
-rw-r--r--channels/drdynvc/client/dvcman.c363
-rw-r--r--channels/tsmf/client/CMakeLists.txt2
-rw-r--r--channels/tsmf/client/alsa/tsmf_alsa.c180
-rw-r--r--channels/tsmf/client/ffmpeg/tsmf_ffmpeg.c301
-rw-r--r--channels/tsmf/client/gstreamer/CMakeLists.txt56
-rw-r--r--channels/tsmf/client/gstreamer/tsmf_X11.c316
-rw-r--r--channels/tsmf/client/gstreamer/tsmf_gstreamer.c1735
-rw-r--r--channels/tsmf/client/gstreamer/tsmf_platform.h83
-rw-r--r--channels/tsmf/client/pulse/tsmf_pulse.c240
-rw-r--r--channels/tsmf/client/tsmf_codec.c136
-rw-r--r--channels/tsmf/client/tsmf_decoder.c34
-rw-r--r--channels/tsmf/client/tsmf_decoder.h39
-rw-r--r--channels/tsmf/client/tsmf_ifman.c337
-rw-r--r--channels/tsmf/client/tsmf_main.c264
-rw-r--r--channels/tsmf/client/tsmf_media.c865
-rw-r--r--channels/tsmf/client/tsmf_media.h49
-rw-r--r--channels/tsmf/client/tsmf_types.h10
-rw-r--r--client/X11/generate_argument_docbook.c64
-rw-r--r--client/X11/xf_client.c975
-rw-r--r--client/X11/xf_window.c692
-rw-r--r--client/X11/xf_window.h58
-rw-r--r--cmake/ConfigOptions.cmake1
-rw-r--r--cmake/FindGStreamer_0_10.cmake118
-rw-r--r--cmake/FindGStreamer_1_0.cmake153
-rw-r--r--cmake/FindGlib.cmake43
-rw-r--r--cmake/FindGstreamer.cmake12
-rw-r--r--cmake/LibFindMacros.cmake116
-rwxr-xr-xconfig.h.in4
-rw-r--r--include/freerdp/channels/tsmf.h63
-rw-r--r--include/freerdp/dvc.h84
-rwxr-xr-xscripts/format_code.sh23
-rw-r--r--winpr/libwinpr/utils/collections/ArrayList.c6
33 files changed, 3392 insertions, 4055 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index a8cb7701b..34efa35f8 100755
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -417,9 +417,13 @@ set(FFMPEG_FEATURE_TYPE "RECOMMENDED")
set(FFMPEG_FEATURE_PURPOSE "multimedia")
set(FFMPEG_FEATURE_DESCRIPTION "multimedia redirection, audio and video playback")
-set(GSTREAMER_FEATURE_TYPE "RECOMMENDED")
-set(GSTREAMER_FEATURE_PURPOSE "multimedia")
-set(GSTREAMER_FEATURE_DESCRIPTION "multimedia redirection, audio and video playback")
+set(GSTREAMER_0_10_FEATURE_TYPE "OPTIONAL")
+set(GSTREAMER_0_10_FEATURE_PURPOSE "multimedia")
+set(GSTREAMER_0_10_FEATURE_DESCRIPTION "multimedia redirection, audio and video playback, gstreamer 0.10 version")
+
+set(GSTREAMER_1_0_FEATURE_TYPE "RECOMMENDED")
+set(GSTREAMER_1_0_FEATURE_PURPOSE "multimedia")
+set(GSTREAMER_1_0_FEATURE_DESCRIPTION "multimedia redirection, audio and video playback")
set(IPP_FEATURE_TYPE "OPTIONAL")
set(IPP_FEATURE_PURPOSE "performance")
@@ -442,14 +446,15 @@ if(WIN32)
set(CUPS_FEATURE_TYPE "DISABLED")
set(PCSC_FEATURE_TYPE "DISABLED")
set(FFMPEG_FEATURE_TYPE "DISABLED")
- set(GSTREAMER_FEATURE_TYPE "DISABLED")
+ set(GSTREAMER_1_0_FEATURE_TYPE "DISABLED")
+ set(GSTREAMER_0_10_FEATURE_TYPE "OPTIONAL")
set(OPENSLES_FEATURE_TYPE "DISABLED")
endif()
if(APPLE)
set(DIRECTFB_FEATURE_TYPE "DISABLED")
set(FFMPEG_FEATURE_TYPE "OPTIONAL")
- set(GSTREAMER_FEATURE_TYPE "OPTIONAL")
+ set(GSTREAMER_1_0_FEATURE_TYPE "OPTIONAL")
set(X11_FEATURE_TYPE "OPTIONAL")
if(IOS)
set(X11_FEATURE_TYPE "DISABLED")
@@ -457,7 +462,8 @@ if(APPLE)
set(PULSE_FEATURE_TYPE "DISABLED")
set(CUPS_FEATURE_TYPE "DISABLED")
set(PCSC_FEATURE_TYPE "DISABLED")
- set(GSTREAMER_FEATURE_TYPE "DISABLED")
+ set(GSTREAMER_1_0_FEATURE_TYPE "DISABLED")
+ set(GSTREAMER_0_10_FEATURE_TYPE "DISABLED")
endif()
set(OPENSLES_FEATURE_TYPE "DISABLED")
endif()
@@ -470,7 +476,8 @@ if(ANDROID)
set(CUPS_FEATURE_TYPE "DISABLED")
set(PCSC_FEATURE_TYPE "DISABLED")
set(FFMPEG_FEATURE_TYPE "DISABLED")
- set(GSTREAMER_FEATURE_TYPE "DISABLED")
+ set(GSTREAMER_1_0_FEATURE_TYPE "DISABLED")
+ set(GSTREAMER_0_10_FEATURE_TYPE "DISABLED")
set(OPENSLES_FEATURE_TYPE "REQUIRED")
endif()
@@ -492,7 +499,9 @@ find_feature(Cups ${CUPS_FEATURE_TYPE} ${CUPS_FEATURE_PURPOSE} ${CUPS_FEATURE_DE
find_feature(PCSC ${PCSC_FEATURE_TYPE} ${PCSC_FEATURE_PURPOSE} ${PCSC_FEATURE_DESCRIPTION})
find_feature(FFmpeg ${FFMPEG_FEATURE_TYPE} ${FFMPEG_FEATURE_PURPOSE} ${FFMPEG_FEATURE_DESCRIPTION})
-find_feature(Gstreamer ${GSTREAMER_FEATURE_TYPE} ${GSTREAMER_FEATURE_PURPOSE} ${GSTREAMER_FEATURE_DESCRIPTION})
+
+find_feature(GStreamer_0_10 ${GSTREAMER_0_10_FEATURE_TYPE} ${GSTREAMER_0_10_FEATURE_PURPOSE} ${GSTREAMER_0_10_FEATURE_DESCRIPTION})
+find_feature(GStreamer_1_0 ${GSTREAMER_1_0_FEATURE_TYPE} ${GSTREAMER_1_0_FEATURE_PURPOSE} ${GSTREAMER_1_0_FEATURE_DESCRIPTION})
find_feature(JPEG ${JPEG_FEATURE_TYPE} ${JPEG_FEATURE_PURPOSE} ${JPEG_FEATURE_DESCRIPTION})
find_feature(GSM ${GSM_FEATURE_TYPE} ${GSM_FEATURE_PURPOSE} ${GSM_FEATURE_DESCRIPTION})
diff --git a/channels/drdynvc/client/dvcman.c b/channels/drdynvc/client/dvcman.c
index da170160d..670d84ecc 100644
--- a/channels/drdynvc/client/dvcman.c
+++ b/channels/drdynvc/client/dvcman.c
@@ -3,6 +3,8 @@
* Dynamic Virtual Channel Manager
*
* Copyright 2010-2011 Vic Lee
+ * Copyright 2014 Thincast Technologies GmbH
+ * Copyright 2014 Armin Novak <armin.novak@thincast.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -21,6 +23,9 @@
#include "config.h"
#endif
+#include <assert.h>
+#include <errno.h>
+
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -28,45 +33,61 @@
#include <winpr/crt.h>
#include <winpr/synch.h>
#include <winpr/stream.h>
+#include <winpr/collections.h>
#include <freerdp/addin.h>
#include "drdynvc_types.h"
#include "dvcman.h"
+static wListDictionary *cb_dict = NULL;
+struct cb_value
+{
+ void *fkt;
+ void *context;
+};
-static int dvcman_get_configuration(IWTSListener* pListener, void** ppPropertyBag)
+static int dvcman_get_configuration(IWTSListener *pListener, void **ppPropertyBag)
{
+ if (!ppPropertyBag)
+ {
+ DEBUG_WARN("ppPropertyBag=%p", ppPropertyBag);
+ return 0;
+ }
+
*ppPropertyBag = NULL;
return 1;
}
-static int dvcman_create_listener(IWTSVirtualChannelManager* pChannelMgr,
- const char* pszChannelName, UINT32 ulFlags,
- IWTSListenerCallback* pListenerCallback, IWTSListener** ppListener)
+static int dvcman_create_listener(IWTSVirtualChannelManager *pChannelMgr,
+ const char *pszChannelName, UINT32 ulFlags,
+ IWTSListenerCallback *pListenerCallback, IWTSListener **ppListener)
{
- DVCMAN* dvcman = (DVCMAN*) pChannelMgr;
- DVCMAN_LISTENER* listener;
+ DVCMAN *dvcman = (DVCMAN *) pChannelMgr;
+ DVCMAN_LISTENER *listener;
+ assert(dvcman);
if (dvcman->num_listeners < MAX_PLUGINS)
{
DEBUG_DVC("%d.%s.", dvcman->num_listeners, pszChannelName);
+ listener = (DVCMAN_LISTENER *) calloc(1, sizeof(DVCMAN_LISTENER));
- listener = (DVCMAN_LISTENER*) malloc(sizeof(DVCMAN_LISTENER));
- ZeroMemory(listener, sizeof(DVCMAN_LISTENER));
+ if (!listener)
+ {
+ DEBUG_WARN("calloc failed %s (%d)!", strerror(errno), errno);
+ return 2;
+ }
listener->iface.GetConfiguration = dvcman_get_configuration;
listener->iface.pInterface = NULL;
-
listener->dvcman = dvcman;
listener->channel_name = _strdup(pszChannelName);
listener->flags = ulFlags;
listener->listener_callback = pListenerCallback;
if (ppListener)
- *ppListener = (IWTSListener*) listener;
+ *ppListener = (IWTSListener *) listener;
- dvcman->listeners[dvcman->num_listeners++] = (IWTSListener*) listener;
-
+ dvcman->listeners[dvcman->num_listeners++] = (IWTSListener *) listener;
return 0;
}
else
@@ -76,11 +97,11 @@ static int dvcman_create_listener(IWTSVirtualChannelManager* pChannelMgr,
}
}
-static int dvcman_push_event(IWTSVirtualChannelManager* pChannelMgr, wMessage* pEvent)
+static int dvcman_push_event(IWTSVirtualChannelManager *pChannelMgr, wMessage *pEvent)
{
int status;
- DVCMAN* dvcman = (DVCMAN*) pChannelMgr;
-
+ DVCMAN *dvcman = (DVCMAN *) pChannelMgr;
+ assert(dvcman);
status = drdynvc_push_event(dvcman->drdynvc, pEvent);
if (status == 0)
@@ -95,9 +116,11 @@ static int dvcman_push_event(IWTSVirtualChannelManager* pChannelMgr, wMessage* p
return status;
}
-static int dvcman_register_plugin(IDRDYNVC_ENTRY_POINTS* pEntryPoints, const char* name, IWTSPlugin* pPlugin)
+static int dvcman_register_plugin(IDRDYNVC_ENTRY_POINTS *pEntryPoints, const char *name, IWTSPlugin *pPlugin)
{
- DVCMAN* dvcman = ((DVCMAN_ENTRY_POINTS*) pEntryPoints)->dvcman;
+ DVCMAN *dvcman = ((DVCMAN_ENTRY_POINTS *) pEntryPoints)->dvcman;
+ assert(pEntryPoints);
+ assert(dvcman);
if (dvcman->num_plugins < MAX_PLUGINS)
{
@@ -113,15 +136,17 @@ static int dvcman_register_plugin(IDRDYNVC_ENTRY_POINTS* pEntryPoints, const cha
}
}
-IWTSPlugin* dvcman_get_plugin(IDRDYNVC_ENTRY_POINTS* pEntryPoints, const char* name)
+IWTSPlugin *dvcman_get_plugin(IDRDYNVC_ENTRY_POINTS *pEntryPoints, const char *name)
{
int i;
- DVCMAN* dvcman = ((DVCMAN_ENTRY_POINTS*) pEntryPoints)->dvcman;
+ DVCMAN *dvcman = ((DVCMAN_ENTRY_POINTS *) pEntryPoints)->dvcman;
+ assert(pEntryPoints);
+ assert(dvcman);
for (i = 0; i < dvcman->num_plugins; i++)
{
if (dvcman->plugin_names[i] == name ||
- strcmp(dvcman->plugin_names[i], name) == 0)
+ strcmp(dvcman->plugin_names[i], name) == 0)
{
return dvcman->plugins[i];
}
@@ -130,27 +155,28 @@ IWTSPlugin* dvcman_get_plugin(IDRDYNVC_ENTRY_POINTS* pEntryPoints, const char* n
return NULL;
}
-ADDIN_ARGV* dvcman_get_plugin_data(IDRDYNVC_ENTRY_POINTS* pEntryPoints)
+ADDIN_ARGV *dvcman_get_plugin_data(IDRDYNVC_ENTRY_POINTS *pEntryPoints)
{
- return ((DVCMAN_ENTRY_POINTS*) pEntryPoints)->args;
+ assert(pEntryPoints);
+ return ((DVCMAN_ENTRY_POINTS *) pEntryPoints)->args;
}
-UINT32 dvcman_get_channel_id(IWTSVirtualChannel * channel)
+UINT32 dvcman_get_channel_id(IWTSVirtualChannel *channel)
{
- return ((DVCMAN_CHANNEL*) channel)->channel_id;
+ assert(channel);
+ return ((DVCMAN_CHANNEL *) channel)->channel_id;
}
-IWTSVirtualChannel* dvcman_find_channel_by_id(IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelId)
+IWTSVirtualChannel *dvcman_find_channel_by_id(IWTSVirtualChannelManager *pChannelMgr, UINT32 ChannelId)
{
int index;
BOOL found = FALSE;
- DVCMAN_CHANNEL* channel;
- DVCMAN* dvcman = (DVCMAN*) pChannelMgr;
-
+ DVCMAN_CHANNEL *channel;
+ DVCMAN *dvcman = (DVCMAN *) pChannelMgr;
+ assert(dvcman);
ArrayList_Lock(dvcman->channels);
-
index = 0;
- channel = (DVCMAN_CHANNEL*) ArrayList_GetItem(dvcman->channels, index++);
+ channel = (DVCMAN_CHANNEL *) ArrayList_GetItem(dvcman->channels, index++);
while (channel)
{
@@ -160,25 +186,26 @@ IWTSVirtualChannel* dvcman_find_channel_by_id(IWTSVirtualChannelManager* pChanne
break;
}
- channel = (DVCMAN_CHANNEL*) ArrayList_GetItem(dvcman->channels, index++);
+ channel = (DVCMAN_CHANNEL *) ArrayList_GetItem(dvcman->channels, index++);
}
ArrayList_Unlock(dvcman->channels);
-
- return (found) ? ((IWTSVirtualChannel*) channel) : NULL;
+ return (found) ? ((IWTSVirtualChannel *) channel) : NULL;
}
-void* dvcman_get_channel_interface_by_name(IWTSVirtualChannelManager* pChannelMgr, const char* ChannelName)
+void *dvcman_get_channel_interface_by_name(IWTSVirtualChannelManager *pChannelMgr, const char *ChannelName)
{
int i;
BOOL found = FALSE;
- void* pInterface = NULL;
- DVCMAN_LISTENER* listener;
- DVCMAN* dvcman = (DVCMAN*) pChannelMgr;
+ void *pInterface = NULL;
+ DVCMAN_LISTENER *listener;
+ DVCMAN *dvcman = (DVCMAN *) pChannelMgr;
+ assert(dvcman);
for (i = 0; i < dvcman->num_listeners; i++)
{
- listener = (DVCMAN_LISTENER*) dvcman->listeners[i];
+ listener = (DVCMAN_LISTENER *) dvcman->listeners[i];
+ assert(listener);
if (strcmp(listener->channel_name, ChannelName) == 0)
{
@@ -191,12 +218,16 @@ void* dvcman_get_channel_interface_by_name(IWTSVirtualChannelManager* pChannelMg
return (found) ? pInterface : NULL;
}
-IWTSVirtualChannelManager* dvcman_new(drdynvcPlugin* plugin)
+IWTSVirtualChannelManager *dvcman_new(drdynvcPlugin *plugin)
{
- DVCMAN* dvcman;
+ DVCMAN *dvcman;
+ dvcman = (DVCMAN *) calloc(1,sizeof(DVCMAN));
- dvcman = (DVCMAN*) malloc(sizeof(DVCMAN));
- ZeroMemory(dvcman, sizeof(DVCMAN));
+ if (!dvcman)
+ {
+ DEBUG_WARN("calloc failed %s (%d)!", strerror(errno), errno);
+ return NULL;
+ }
dvcman->iface.CreateListener = dvcman_create_listener;
dvcman->iface.PushEvent = dvcman_push_event;
@@ -204,68 +235,68 @@ IWTSVirtualChannelManager* dvcman_new(drdynvcPlugin* plugin)
dvcman->iface.GetChannelId = dvcman_get_channel_id;
dvcman->drdynvc = plugin;
dvcman->channels = ArrayList_New(TRUE);
-
- return (IWTSVirtualChannelManager*) dvcman;
+ return (IWTSVirtualChannelManager *) dvcman;
}
-int dvcman_load_addin(IWTSVirtualChannelManager* pChannelMgr, ADDIN_ARGV* args)
+int dvcman_load_addin(IWTSVirtualChannelManager *pChannelMgr, ADDIN_ARGV *args)
{
DVCMAN_ENTRY_POINTS entryPoints;
PDVC_PLUGIN_ENTRY pDVCPluginEntry = NULL;
-
+ assert(args);
fprintf(stderr, "Loading Dynamic Virtual Channel %s\n", args->argv[0]);
-
pDVCPluginEntry = (PDVC_PLUGIN_ENTRY) freerdp_load_channel_addin_entry(args->argv[0],
- NULL, NULL, FREERDP_ADDIN_CHANNEL_DYNAMIC);
+ NULL, NULL, FREERDP_ADDIN_CHANNEL_DYNAMIC);
if (pDVCPluginEntry)
{
entryPoints.iface.RegisterPlugin = dvcman_register_plugin;
entryPoints.iface.GetPlugin = dvcman_get_plugin;
entryPoints.iface.GetPluginData = dvcman_get_plugin_data;
- entryPoints.dvcman = (DVCMAN*) pChannelMgr;
+ entryPoints.dvcman = (DVCMAN *) pChannelMgr;
entryPoints.args = args;
-
- pDVCPluginEntry((IDRDYNVC_ENTRY_POINTS*) &entryPoints);
+ pDVCPluginEntry((IDRDYNVC_ENTRY_POINTS *) &entryPoints);
}
return 0;
}
-static void dvcman_channel_free(DVCMAN_CHANNEL* channel)
+static void dvcman_channel_free(DVCMAN_CHANNEL *channel)
{
+ assert(channel);
+
if (channel->channel_callback)
channel->channel_callback->OnClose(channel->channel_callback);
+ if (channel->channel_name)
+ free(channel->channel_name);
+
free(channel);
}
-void dvcman_free(IWTSVirtualChannelManager* pChannelMgr)
+void dvcman_free(IWTSVirtualChannelManager *pChannelMgr)
{
int i;
int count;
- IWTSPlugin* pPlugin;
- DVCMAN_LISTENER* listener;
- DVCMAN_CHANNEL* channel;
- DVCMAN* dvcman = (DVCMAN*) pChannelMgr;
-
+ IWTSPlugin *pPlugin;
+ DVCMAN_LISTENER *listener;
+ DVCMAN_CHANNEL *channel;
+ DVCMAN *dvcman = (DVCMAN *) pChannelMgr;
+ assert(dvcman);
ArrayList_Lock(dvcman->channels);
-
count = ArrayList_Count(dvcman->channels);
for (i = 0; i < count; i++)
{
- channel = (DVCMAN_CHANNEL*) ArrayList_GetItem(dvcman->channels, i);
+ channel = (DVCMAN_CHANNEL *) ArrayList_GetItem(dvcman->channels, i);
dvcman_channel_free(channel);
}
ArrayList_Unlock(dvcman->channels);
-
ArrayList_Free(dvcman->channels);
for (i = 0; i < dvcman->num_listeners; i++)
{
- listener = (DVCMAN_LISTENER*) dvcman->listeners[i];
+ listener = (DVCMAN_LISTENER *) dvcman->listeners[i];
free(listener->channel_name);
free(listener);
}
@@ -281,11 +312,12 @@ void dvcman_free(IWTSVirtualChannelManager* pChannelMgr)
free(dvcman);
}
-int dvcman_init(IWTSVirtualChannelManager* pChannelMgr)
+int dvcman_init(IWTSVirtualChannelManager *pChannelMgr)
{
int i;
- IWTSPlugin* pPlugin;
- DVCMAN* dvcman = (DVCMAN*) pChannelMgr;
+ IWTSPlugin *pPlugin;
+ DVCMAN *dvcman = (DVCMAN *) pChannelMgr;
+ assert(dvcman);
for (i = 0; i < dvcman->num_plugins; i++)
{
@@ -298,83 +330,83 @@ int dvcman_init(IWTSVirtualChannelManager* pChannelMgr)
return 0;
}
-static int dvcman_write_channel(IWTSVirtualChannel* pChannel, UINT32 cbSize, BYTE* pBuffer, void* pReserved)
+static int dvcman_write_channel(IWTSVirtualChannel *pChannel, UINT32 cbSize, BYTE *pBuffer, void *pReserved)
{
int status;
- DVCMAN_CHANNEL* channel = (DVCMAN_CHANNEL*) pChannel;
-
+ DVCMAN_CHANNEL *channel = (DVCMAN_CHANNEL *) pChannel;
+ assert(channel);
WaitForSingleObject(channel->dvc_chan_mutex, INFINITE);
status = drdynvc_write_data(channel->dvcman->drdynvc, channel->channel_id, pBuffer, cbSize);
ReleaseMutex(channel->dvc_chan_mutex);
-
return status;
}
-static int dvcman_close_channel_iface(IWTSVirtualChannel* pChannel)
+static int dvcman_close_channel_iface(IWTSVirtualChannel *pChannel)
{
- DVCMAN_CHANNEL* channel = (DVCMAN_CHANNEL*) pChannel;
- DVCMAN* dvcman = channel->dvcman;
-
+ DVCMAN_CHANNEL *channel = (DVCMAN_CHANNEL *) pChannel;
+ DVCMAN *dvcman = channel->dvcman;
+ assert(channel);
+ assert(dvcman);
DEBUG_DVC("id=%d", channel->channel_id);
-
ArrayList_Remove(dvcman->channels, channel);
-
dvcman_channel_free(channel);
-
return 1;
}
-int dvcman_create_channel(IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelId, const char* ChannelName)
+int dvcman_create_channel(IWTSVirtualChannelManager *pChannelMgr, UINT32 ChannelId, const char *ChannelName)
{
int i;
int bAccept;
- DVCMAN_LISTENER* listener;
- DVCMAN_CHANNEL* channel;
- DrdynvcClientContext* context;
- IWTSVirtualChannelCallback* pCallback;
- DVCMAN* dvcman = (DVCMAN*) pChannelMgr;
+ DVCMAN_LISTENER *listener;
+ DVCMAN_CHANNEL *channel;
+ DrdynvcClientContext *context;
+ IWTSVirtualChannelCallback *pCallback;
+ DVCMAN *dvcman = (DVCMAN *) pChannelMgr;
+ channel = (DVCMAN_CHANNEL *) calloc(1, sizeof(DVCMAN_CHANNEL));
- channel = (DVCMAN_CHANNEL*) malloc(sizeof(DVCMAN_CHANNEL));
- ZeroMemory(channel, sizeof(DVCMAN_CHANNEL));
+ if (!channel)
+ {
+ DEBUG_WARN("calloc failed %s (%d)!", strerror(errno), errno);
+ return -1;
+ }
+ ZeroMemory(channel, sizeof(DVCMAN_CHANNEL));
channel->dvcman = dvcman;
channel->channel_id = ChannelId;
channel->channel_name = _strdup(ChannelName);
for (i = 0; i < dvcman->num_listeners; i++)
{
- listener = (DVCMAN_LISTENER*) dvcman->listeners[i];
+ listener = (DVCMAN_LISTENER *) dvcman->listeners[i];
+ assert(listener);
if (strcmp(listener->channel_name, ChannelName) == 0)
{
channel->iface.Write = dvcman_write_channel;
channel->iface.Close = dvcman_close_channel_iface;
channel->dvc_chan_mutex = CreateMutex(NULL, FALSE, NULL);
-
bAccept = 1;
pCallback = NULL;
+ assert(listener->listener_callback);
+ assert(listener->listener_callback->OnNewChannelConnection);
if (listener->listener_callback->OnNewChannelConnection(listener->listener_callback,
- (IWTSVirtualChannel*) channel, NULL, &bAccept, &pCallback) == 0 && bAccept == 1)
+ (IWTSVirtualChannel *) channel, NULL, &bAccept, &pCallback) == 0 && bAccept == 1)
{
DEBUG_DVC("listener %s created new channel %d",
- listener->channel_name, channel->channel_id);
-
+ listener->channel_name, channel->channel_id);
channel->status = 0;
channel->channel_callback = pCallback;
channel->pInterface = listener->iface.pInterface;
-
+ assert(dvcman->drdynvc);
ArrayList_Add(dvcman->channels, channel);
-
context = dvcman->drdynvc->context;
IFCALL(context->OnChannelConnected, context, ChannelName, listener->iface.pInterface);
-
return 0;
}
else
{
DEBUG_WARN("channel rejected by plugin");
-
free(channel);
return 1;
}
@@ -385,14 +417,14 @@ int dvcman_create_channel(IWTSVirtualChannelManager* pChannelMgr, UINT32 Channel
return 1;
}
-int dvcman_close_channel(IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelId)
+int dvcman_close_channel(IWTSVirtualChannelManager *pChannelMgr, UINT32 ChannelId)
{
- DVCMAN_CHANNEL* channel;
- IWTSVirtualChannel* ichannel;
- DrdynvcClientContext* context;
- DVCMAN* dvcman = (DVCMAN*) pChannelMgr;
-
- channel = (DVCMAN_CHANNEL*) dvcman_find_channel_by_id(pChannelMgr, ChannelId);
+ DVCMAN_CHANNEL *channel;
+ IWTSVirtualChannel *ichannel;
+ DrdynvcClientContext *context;
+ DVCMAN *dvcman = (DVCMAN *) pChannelMgr;
+ assert(dvcman);
+ channel = (DVCMAN_CHANNEL *) dvcman_find_channel_by_id(pChannelMgr, ChannelId);
if (!channel)
{
@@ -408,25 +440,21 @@ int dvcman_close_channel(IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelI
if (channel->status == 0)
{
+ assert(dvcman->drdynvc);
context = dvcman->drdynvc->context;
-
IFCALL(context->OnChannelDisconnected, context, channel->channel_name, channel->pInterface);
-
- free(channel->channel_name);
-
DEBUG_DVC("dvcman_close_channel: channel %d closed", ChannelId);
- ichannel = (IWTSVirtualChannel*) channel;
+ ichannel = (IWTSVirtualChannel *) channel;
ichannel->Close(ichannel);
}
return 0;
}
-int dvcman_receive_channel_data_first(IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelId, UINT32 length)
+int dvcman_receive_channel_data_first(IWTSVirtualChannelManager *pChannelMgr, UINT32 ChannelId, UINT32 length)
{
- DVCMAN_CHANNEL* channel;
-
- channel = (DVCMAN_CHANNEL*) dvcman_find_channel_by_id(pChannelMgr, ChannelId);
+ DVCMAN_CHANNEL *channel;
+ channel = (DVCMAN_CHANNEL *) dvcman_find_channel_by_id(pChannelMgr, ChannelId);
if (!channel)
{
@@ -438,16 +466,14 @@ int dvcman_receive_channel_data_first(IWTSVirtualChannelManager* pChannelMgr, UI
Stream_Free(channel->dvc_data, TRUE);
channel->dvc_data = Stream_New(NULL, length);
-
return 0;
}
-int dvcman_receive_channel_data(IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelId, BYTE* data, UINT32 data_size)
+int dvcman_receive_channel_data(IWTSVirtualChannelManager *pChannelMgr, UINT32 ChannelId, BYTE *data, UINT32 data_size)
{
int error = 0;
- DVCMAN_CHANNEL* channel;
-
- channel = (DVCMAN_CHANNEL*) dvcman_find_channel_by_id(pChannelMgr, ChannelId);
+ DVCMAN_CHANNEL *channel;
+ channel = (DVCMAN_CHANNEL *) dvcman_find_channel_by_id(pChannelMgr, ChannelId);
if (!channel)
{
@@ -471,15 +497,122 @@ int dvcman_receive_channel_data(IWTSVirtualChannelManager* pChannelMgr, UINT32 C
if (((size_t) Stream_GetPosition(channel->dvc_data)) >= Stream_Capacity(channel->dvc_data))
{
error = channel->channel_callback->OnDataReceived(channel->channel_callback,
- Stream_Capacity(channel->dvc_data), Stream_Buffer(channel->dvc_data));
+ Stream_Capacity(channel->dvc_data), Stream_Buffer(channel->dvc_data));
Stream_Free(channel->dvc_data, TRUE);
channel->dvc_data = NULL;
}
}
else
{
+ assert(channel->channel_callback);
+ assert(channel->channel_callback->OnDataReceived);
error = channel->channel_callback->OnDataReceived(channel->channel_callback, data_size, data);
}
return error;
}
+
+static void dump_callbacks(void)
+{
+ wListDictionaryItem *cur;
+ DEBUG_DVC("Dumping all currently registered callbacks");
+
+ if (!cb_dict)
+ {
+ DEBUG_DVC("cb_dict=NULL");
+ return;
+ }
+
+ cur = cb_dict->head;
+
+ while (cur)
+ {
+ DEBUG_DVC("cb_dict %s:%p", cur->key, cur->value);
+ cur = cur->next;
+ }
+}
+
+void *get_callback_by_name(const char *name, void **context)
+{
+ struct cb_value *rc;
+
+ if (!cb_dict)
+ {
+ DEBUG_WARN("'%s' not found, function list does not exist.",
+ name);
+ return NULL;
+ }
+
+ if (!ListDictionary_Contains(cb_dict, (void *)name))
+ {
+ DEBUG_WARN("'%s' not found", name);
+ return NULL;
+ }
+
+ rc = ListDictionary_GetItemValue(cb_dict, (void *)name);
+ DEBUG_DVC("'%s'=%p found", name, rc);
+
+ if (context)
+ *context = rc->context;
+
+ return rc->fkt;
+}
+
+static BOOL callback_key_cmp(void *a, void *b)
+{
+ return strcmp(a, b) ? FALSE : TRUE;
+}
+
+void add_callback_by_name(const char *name, void *fkt, void *context)
+{
+ struct cb_value *value = calloc(1, sizeof(struct cb_value));
+
+ if (!value)
+ {
+ DEBUG_WARN("calloc failed %s (%d)!", strerror(errno), errno);
+ assert(FALSE);
+ return;
+ }
+
+ if (!cb_dict)
+ {
+ DEBUG_DVC("Function list is empty, allocating new.");
+ cb_dict = ListDictionary_New(TRUE);
+ ListDictionary_KeyObject(cb_dict)->fnObjectEquals = callback_key_cmp;
+ }
+
+ value->fkt = fkt;
+ value->context = context;
+ DEBUG_DVC("Adding '%s'=%p to function list.", name, fkt);
+ ListDictionary_Add(cb_dict, (void *)name, value);
+ dump_callbacks();
+}
+
+void remove_callback_by_name(const char *name, void *context)
+{
+ if (!cb_dict)
+ {
+ DEBUG_WARN("trying to remove '%s', but function list does not exist.",
+ name);
+ return;
+ }
+
+ if (!ListDictionary_Contains(cb_dict, (void *)name))
+ {
+ DEBUG_WARN("trying to remove '%s', which is not in function list.",
+ name);
+ return;
+ }
+
+ DEBUG_DVC("Removing '%s' from function list.", name);
+ ListDictionary_Remove(cb_dict, (void *)name);
+
+ if (ListDictionary_Count(cb_dict) < 1)
+ {
+ DEBUG_DVC("Function list is empty, freeing resources.");
+ ListDictionary_Free(cb_dict);
+ cb_dict = NULL;
+ }
+
+ dump_callbacks();
+}
diff --git a/channels/tsmf/client/CMakeLists.txt b/channels/tsmf/client/CMakeLists.txt
index 18f463d4f..a92ceda1d 100644
--- a/channels/tsmf/client/CMakeLists.txt
+++ b/channels/tsmf/client/CMakeLists.txt
@@ -55,7 +55,7 @@ if(WITH_FFMPEG)
add_channel_client_subsystem(${MODULE_PREFIX} ${CHANNEL_NAME} "ffmpeg" "decoder")
endif()
-if(WITH_GSTREAMER)
+if(WITH_GSTREAMER_0_10 OR WITH_GSTREAMER_1_0)
set(XRANDR_FEATURE_TYPE "REQUIRED")
set(XRANDR_FEATURE_PURPOSE "X11 randr")
set(XRANDR_FEATURE_DESCRIPTION "X11 randr extension")
diff --git a/channels/tsmf/client/alsa/tsmf_alsa.c b/channels/tsmf/client/alsa/tsmf_alsa.c
index a6b67d71a..d442dca8c 100644
--- a/channels/tsmf/client/alsa/tsmf_alsa.c
+++ b/channels/tsmf/client/alsa/tsmf_alsa.c
@@ -24,7 +24,6 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <pthread.h>
#include <unistd.h>
#include <winpr/crt.h>
@@ -41,225 +40,194 @@ typedef struct _TSMFALSAAudioDevice
ITSMFAudioDevice iface;
char device[32];
- snd_pcm_t* out_handle;
+ snd_pcm_t *out_handle;
UINT32 source_rate;
UINT32 actual_rate;
UINT32 source_channels;
UINT32 actual_channels;
UINT32 bytes_per_sample;
- FREERDP_DSP_CONTEXT* dsp_context;
+ FREERDP_DSP_CONTEXT *dsp_context;
} TSMFAlsaAudioDevice;
-static BOOL tsmf_alsa_open_device(TSMFAlsaAudioDevice* alsa)
+static BOOL tsmf_alsa_open_device(TSMFAlsaAudioDevice *alsa)
{
int error;
-
error = snd_pcm_open(&alsa->out_handle, alsa->device, SND_PCM_STREAM_PLAYBACK, 0);
-
- if (error < 0)
+ if(error < 0)
{
DEBUG_WARN("failed to open device %s", alsa->device);
return FALSE;
}
-
- DEBUG_DVC("open device %s", alsa->device);
+ DEBUG_TSMF("open device %s", alsa->device);
return TRUE;
}
-static BOOL tsmf_alsa_open(ITSMFAudioDevice* audio, const char* device)
+static BOOL tsmf_alsa_open(ITSMFAudioDevice *audio, const char *device)
{
- TSMFAlsaAudioDevice* alsa = (TSMFAlsaAudioDevice*) audio;
-
- if (!device)
+ TSMFAlsaAudioDevice *alsa = (TSMFAlsaAudioDevice *) audio;
+ if(!device)
{
- if (!alsa->device[0])
+ if(!alsa->device[0])
strncpy(alsa->device, "default", sizeof(alsa->device));
}
else
{
strncpy(alsa->device, device, sizeof(alsa->device));
}
-
return tsmf_alsa_open_device(alsa);
}
-static BOOL tsmf_alsa_set_format(ITSMFAudioDevice* audio,
- UINT32 sample_rate, UINT32 channels, UINT32 bits_per_sample)
+static BOOL tsmf_alsa_set_format(ITSMFAudioDevice *audio,
+ UINT32 sample_rate, UINT32 channels, UINT32 bits_per_sample)
{
int error;
snd_pcm_uframes_t frames;
- snd_pcm_hw_params_t* hw_params;
- snd_pcm_sw_params_t* sw_params;
- TSMFAlsaAudioDevice* alsa = (TSMFAlsaAudioDevice*) audio;
-
- if (!alsa->out_handle)
+ snd_pcm_hw_params_t *hw_params;
+ snd_pcm_sw_params_t *sw_params;
+ TSMFAlsaAudioDevice *alsa = (TSMFAlsaAudioDevice *) audio;
+ if(!alsa->out_handle)
return FALSE;
-
snd_pcm_drop(alsa->out_handle);
-
alsa->actual_rate = alsa->source_rate = sample_rate;
alsa->actual_channels = alsa->source_channels = channels;
alsa->bytes_per_sample = bits_per_sample / 8;
-
error = snd_pcm_hw_params_malloc(&hw_params);
-
- if (error < 0)
+ if(error < 0)
{
DEBUG_WARN("snd_pcm_hw_params_malloc failed");
return FALSE;
}
-
snd_pcm_hw_params_any(alsa->out_handle, hw_params);
snd_pcm_hw_params_set_access(alsa->out_handle, hw_params,
- SND_PCM_ACCESS_RW_INTERLEAVED);
+ SND_PCM_ACCESS_RW_INTERLEAVED);
snd_pcm_hw_params_set_format(alsa->out_handle, hw_params,
- SND_PCM_FORMAT_S16_LE);
+ SND_PCM_FORMAT_S16_LE);
snd_pcm_hw_params_set_rate_near(alsa->out_handle, hw_params,
- &alsa->actual_rate, NULL);
+ &alsa->actual_rate, NULL);
snd_pcm_hw_params_set_channels_near(alsa->out_handle, hw_params,
- &alsa->actual_channels);
+ &alsa->actual_channels);
frames = sample_rate;
snd_pcm_hw_params_set_buffer_size_near(alsa->out_handle, hw_params,
- &frames);
+ &frames);
snd_pcm_hw_params(alsa->out_handle, hw_params);
snd_pcm_hw_params_free(hw_params);
-
error = snd_pcm_sw_params_malloc(&sw_params);
-
- if (error < 0)
+ if(error < 0)
{
DEBUG_WARN("snd_pcm_sw_params_malloc");
return FALSE;
}
-
snd_pcm_sw_params_current(alsa->out_handle, sw_params);
snd_pcm_sw_params_set_start_threshold(alsa->out_handle, sw_params,
- frames / 2);
+ frames / 2);
snd_pcm_sw_params(alsa->out_handle, sw_params);
snd_pcm_sw_params_free(sw_params);
-
snd_pcm_prepare(alsa->out_handle);
-
- DEBUG_DVC("sample_rate %d channels %d bits_per_sample %d",
- sample_rate, channels, bits_per_sample);
- DEBUG_DVC("hardware buffer %d frames", (int)frames);
-
- if ((alsa->actual_rate != alsa->source_rate) ||
- (alsa->actual_channels != alsa->source_channels))
+ DEBUG_TSMF("sample_rate %d channels %d bits_per_sample %d",
+ sample_rate, channels, bits_per_sample);
+ DEBUG_TSMF("hardware buffer %d frames", (int)frames);
+ if((alsa->actual_rate != alsa->source_rate) ||
+ (alsa->actual_channels != alsa->source_channels))
{
- DEBUG_DVC("actual rate %d / channel %d is different "
- "from source rate %d / channel %d, resampling required.",
- alsa->actual_rate, alsa->actual_channels,
- alsa->source_rate, alsa->source_channels);
+ DEBUG_TSMF("actual rate %d / channel %d is different "
+ "from source rate %d / channel %d, resampling required.",
+ alsa->actual_rate, alsa->actual_channels,
+ alsa->source_rate, alsa->source_channels);
}
-
return TRUE;
}
-static BOOL tsmf_alsa_play(ITSMFAudioDevice* audio, BYTE* data, UINT32 data_size)
+static BOOL tsmf_alsa_play(ITSMFAudioDevice *audio, BYTE *data, UINT32 data_size)
{
int len;
int error;
int frames;
- BYTE* end;
- BYTE* src;
- BYTE* pindex;
+ BYTE *end;
+ BYTE *src;
+ BYTE *pindex;
int rbytes_per_frame;
int sbytes_per_frame;
- TSMFAlsaAudioDevice* alsa = (TSMFAlsaAudioDevice*) audio;
-
- DEBUG_DVC("data_size %d", data_size);
-
- if (alsa->out_handle)
+ TSMFAlsaAudioDevice *alsa = (TSMFAlsaAudioDevice *) audio;
+ DEBUG_TSMF("data_size %d", data_size);
+ if(alsa->out_handle)
{
sbytes_per_frame = alsa->source_channels * alsa->bytes_per_sample;
rbytes_per_frame = alsa->actual_channels * alsa->bytes_per_sample;
-
- if ((alsa->source_rate == alsa->actual_rate) &&
- (alsa->source_channels == alsa->actual_channels))
+ if((alsa->source_rate == alsa->actual_rate) &&
+ (alsa->source_channels == alsa->actual_channels))
{
src = data;
}
else
{
alsa->dsp_context->resample(alsa->dsp_context, data, alsa->bytes_per_sample,
- alsa->source_channels, alsa->source_rate, data_size / sbytes_per_frame,
- alsa->actual_channels, alsa->actual_rate);
+ alsa->source_channels, alsa->source_rate, data_size / sbytes_per_frame,
+ alsa->actual_channels, alsa->actual_rate);
frames = alsa->dsp_context->resampled_frames;
- DEBUG_DVC("resampled %d frames at %d to %d frames at %d",
- data_size / sbytes_per_frame, alsa->source_rate, frames, alsa->actual_rate);
+ DEBUG_TSMF("resampled %d frames at %d to %d frames at %d",
+ data_size / sbytes_per_frame, alsa->source_rate, frames, alsa->actual_rate);
data_size = frames * rbytes_per_frame;
src = alsa->dsp_context->resampled_buffer;
}
-
pindex = src;
end = pindex + data_size;
- while (pindex < end)
+ while(pindex < end)
{
len = end - pindex;
frames = len / rbytes_per_frame;
error = snd_pcm_writei(alsa->out_handle, pindex, frames);
-
- if (error == -EPIPE)
+ if(error == -EPIPE)
{
snd_pcm_recover(alsa->out_handle, error, 0);
error = 0;
}
- else if (error < 0)
- {
- DEBUG_DVC("error len %d", error);
- snd_pcm_close(alsa->out_handle);
- alsa->out_handle = 0;
- tsmf_alsa_open_device(alsa);
- break;
- }
-
- DEBUG_DVC("%d frames played.", error);
-
- if (error == 0)
+ else
+ if(error < 0)
+ {
+ DEBUG_TSMF("error len %d", error);
+ snd_pcm_close(alsa->out_handle);
+ alsa->out_handle = 0;
+ tsmf_alsa_open_device(alsa);
+ break;
+ }
+ DEBUG_TSMF("%d frames played.", error);
+ if(error == 0)
break;
-
pindex += error * rbytes_per_frame;
}
}
free(data);
-
return TRUE;
}
-static UINT64 tsmf_alsa_get_latency(ITSMFAudioDevice* audio)
+static UINT64 tsmf_alsa_get_latency(ITSMFAudioDevice *audio)
{
UINT64 latency = 0;
snd_pcm_sframes_t frames = 0;
- TSMFAlsaAudioDevice* alsa = (TSMFAlsaAudioDevice*) audio;
-
- if (alsa->out_handle && alsa->actual_rate > 0 &&
- snd_pcm_delay(alsa->out_handle, &frames) == 0 &&
- frames > 0)
+ TSMFAlsaAudioDevice *alsa = (TSMFAlsaAudioDevice *) audio;
+ if(alsa->out_handle && alsa->actual_rate > 0 &&
+ snd_pcm_delay(alsa->out_handle, &frames) == 0 &&
+ frames > 0)
{
latency = ((UINT64)frames) * 10000000LL / (UINT64) alsa->actual_rate;
}
-
return latency;
}
-static void tsmf_alsa_flush(ITSMFAudioDevice* audio)
+static void tsmf_alsa_flush(ITSMFAudioDevice *audio)
{
}
-static void tsmf_alsa_free(ITSMFAudioDevice* audio)
+static void tsmf_alsa_free(ITSMFAudioDevice *audio)
{
- TSMFAlsaAudioDevice* alsa = (TSMFAlsaAudioDevice*) audio;
-
- DEBUG_DVC("");
-
- if (alsa->out_handle)
+ TSMFAlsaAudioDevice *alsa = (TSMFAlsaAudioDevice *) audio;
+ DEBUG_TSMF("");
+ if(alsa->out_handle)
{
snd_pcm_drain(alsa->out_handle);
snd_pcm_close(alsa->out_handle);
}
-
freerdp_dsp_context_free(alsa->dsp_context);
free(alsa);
}
@@ -268,21 +236,17 @@ static void tsmf_alsa_free(ITSMFAudioDevice* audio)
#define freerdp_tsmf_client_audio_subsystem_entry alsa_freerdp_tsmf_client_audio_subsystem_entry
#endif
-ITSMFAudioDevice* freerdp_tsmf_client_audio_subsystem_entry(void)
+ITSMFAudioDevice *freerdp_tsmf_client_audio_subsystem_entry(void)
{
- TSMFAlsaAudioDevice* alsa;
-
- alsa = (TSMFAlsaAudioDevice*) malloc(sizeof(TSMFAlsaAudioDevice));
+ TSMFAlsaAudioDevice *alsa;
+ alsa = (TSMFAlsaAudioDevice *) malloc(sizeof(TSMFAlsaAudioDevice));
ZeroMemory(alsa, sizeof(TSMFAlsaAudioDevice));
-
alsa->iface.Open = tsmf_alsa_open;
alsa->iface.SetFormat = tsmf_alsa_set_format;
alsa->iface.Play = tsmf_alsa_play;
alsa->iface.GetLatency = tsmf_alsa_get_latency;
alsa->iface.Flush = tsmf_alsa_flush;
alsa->iface.Free = tsmf_alsa_free;
-
alsa->dsp_context = freerdp_dsp_context_new();
-
- return (ITSMFAudioDevice*) alsa;
+ return (ITSMFAudioDevice *) alsa;
}
diff --git a/channels/tsmf/client/ffmpeg/tsmf_ffmpeg.c b/channels/tsmf/client/ffmpeg/tsmf_ffmpeg.c
index 09b4f685c..e2c9da2c5 100644
--- a/channels/tsmf/client/ffmpeg/tsmf_ffmpeg.c
+++ b/channels/tsmf/client/ffmpeg/tsmf_ffmpeg.c
@@ -32,8 +32,6 @@
#include <libavcodec/avcodec.h>
-#include <pthread.h>
-
#include "tsmf_constants.h"
#include "tsmf_decoder.h"
@@ -59,55 +57,47 @@ typedef struct _TSMFFFmpegDecoder
#else
enum AVCodecID codec_id;
#endif
- AVCodecContext* codec_context;
- AVCodec* codec;
- AVFrame* frame;
+ AVCodecContext *codec_context;
+ AVCodec *codec;
+ AVFrame *frame;
int prepared;
- BYTE* decoded_data;
+ BYTE *decoded_data;
UINT32 decoded_size;
UINT32 decoded_size_max;
} TSMFFFmpegDecoder;
-static BOOL tsmf_ffmpeg_init_context(ITSMFDecoder* decoder)
+static BOOL tsmf_ffmpeg_init_context(ITSMFDecoder *decoder)
{
- TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*) decoder;
-
+ TSMFFFmpegDecoder *mdecoder = (TSMFFFmpegDecoder *) decoder;
mdecoder->codec_context = avcodec_alloc_context3(NULL);
-
- if (!mdecoder->codec_context)
+ if(!mdecoder->codec_context)
{
DEBUG_WARN("avcodec_alloc_context failed.");
return FALSE;
}
-
return TRUE;
}
-static BOOL tsmf_ffmpeg_init_video_stream(ITSMFDecoder* decoder, const TS_AM_MEDIA_TYPE* media_type)
+static BOOL tsmf_ffmpeg_init_video_stream(ITSMFDecoder *decoder, const TS_AM_MEDIA_TYPE *media_type)
{
- TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*) decoder;
-
+ TSMFFFmpegDecoder *mdecoder = (TSMFFFmpegDecoder *) decoder;
mdecoder->codec_context->width = media_type->Width;
mdecoder->codec_context->height = media_type->Height;
mdecoder->codec_context->bit_rate = media_type->BitRate;
mdecoder->codec_context->time_base.den = media_type->SamplesPerSecond.Numerator;
mdecoder->codec_context->time_base.num = media_type->SamplesPerSecond.Denominator;
-
mdecoder->frame = avcodec_alloc_frame();
-
return TRUE;
}
-static BOOL tsmf_ffmpeg_init_audio_stream(ITSMFDecoder* decoder, const TS_AM_MEDIA_TYPE* media_type)
+static BOOL tsmf_ffmpeg_init_audio_stream(ITSMFDecoder *decoder, const TS_AM_MEDIA_TYPE *media_type)
{
- TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*) decoder;
-
+ TSMFFFmpegDecoder *mdecoder = (TSMFFFmpegDecoder *) decoder;
mdecoder->codec_context->sample_rate = media_type->SamplesPerSecond.Numerator;
mdecoder->codec_context->bit_rate = media_type->BitRate;
mdecoder->codec_context->channels = media_type->Channels;
mdecoder->codec_context->block_align = media_type->BlockAlign;
-
#if LIBAVCODEC_VERSION_MAJOR < 55
#ifdef AV_CPU_FLAG_SSE2
mdecoder->codec_context->dsp_mask = AV_CPU_FLAG_SSE2 | AV_CPU_FLAG_MMX2;
@@ -125,43 +115,38 @@ static BOOL tsmf_ffmpeg_init_audio_stream(ITSMFDecoder* decoder, const TS_AM_MED
av_set_cpu_flags_mask(FF_MM_SSE2 | FF_MM_MMX2);
#endif
#endif /* LIBAVCODEC_VERSION_MAJOR < 55 */
-
return TRUE;
}
-static BOOL tsmf_ffmpeg_init_stream(ITSMFDecoder* decoder, const TS_AM_MEDIA_TYPE* media_type)
+static BOOL tsmf_ffmpeg_init_stream(ITSMFDecoder *decoder, const TS_AM_MEDIA_TYPE *media_type)
{
- BYTE* p;
+ BYTE *p;
UINT32 size;
- const BYTE* s;
- TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*) decoder;
-
+ const BYTE *s;
+ TSMFFFmpegDecoder *mdecoder = (TSMFFFmpegDecoder *) decoder;
mdecoder->codec = avcodec_find_decoder(mdecoder->codec_id);
-
- if (!mdecoder->codec)
+ if(!mdecoder->codec)
{
DEBUG_WARN("avcodec_find_decoder failed.");
return FALSE;
}
-
mdecoder->codec_context->codec_id = mdecoder->codec_id;
mdecoder->codec_context->codec_type = mdecoder->media_type;
-
- if (mdecoder->media_type == AVMEDIA_TYPE_VIDEO)
+ if(mdecoder->media_type == AVMEDIA_TYPE_VIDEO)
{
- if (!tsmf_ffmpeg_init_video_stream(decoder, media_type))
+ if(!tsmf_ffmpeg_init_video_stream(decoder, media_type))
return FALSE;
}
- else if (mdecoder->media_type == AVMEDIA_TYPE_AUDIO)
- {
- if (!tsmf_ffmpeg_init_audio_stream(decoder, media_type))
- return FALSE;
- }
-
- if (media_type->ExtraData)
+ else
+ if(mdecoder->media_type == AVMEDIA_TYPE_AUDIO)
+ {
+ if(!tsmf_ffmpeg_init_audio_stream(decoder, media_type))
+ return FALSE;
+ }
+ if(media_type->ExtraData)
{
- if (media_type->SubType == TSMF_SUB_TYPE_AVC1 &&
- media_type->FormatType == TSMF_FORMAT_TYPE_MPEG2VIDEOINFO)
+ if(media_type->SubType == TSMF_SUB_TYPE_AVC1 &&
+ media_type->FormatType == TSMF_FORMAT_TYPE_MPEG2VIDEOINFO)
{
/* The extradata format that FFmpeg uses is following CodecPrivate in Matroska.
See http://haali.su/mkv/codecs.pdf */
@@ -194,33 +179,27 @@ static BOOL tsmf_ffmpeg_init_stream(ITSMFDecoder* decoder, const TS_AM_MEDIA_TYP
memset(mdecoder->codec_context->extradata + media_type->ExtraDataSize, 0, 8);
}
}
-
- if (mdecoder->codec->capabilities & CODEC_CAP_TRUNCATED)
+ if(mdecoder->codec->capabilities & CODEC_CAP_TRUNCATED)
mdecoder->codec_context->flags |= CODEC_FLAG_TRUNCATED;
-
return TRUE;
}
-static BOOL tsmf_ffmpeg_prepare(ITSMFDecoder* decoder)
+static BOOL tsmf_ffmpeg_prepare(ITSMFDecoder *decoder)
{
- TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*) decoder;
-
- if (avcodec_open2(mdecoder->codec_context, mdecoder->codec, NULL) < 0)
+ TSMFFFmpegDecoder *mdecoder = (TSMFFFmpegDecoder *) decoder;
+ if(avcodec_open2(mdecoder->codec_context, mdecoder->codec, NULL) < 0)
{
DEBUG_WARN("avcodec_open2 failed.");
return FALSE;
}
-
mdecoder->prepared = 1;
-
return TRUE;
}
-static BOOL tsmf_ffmpeg_set_format(ITSMFDecoder* decoder, TS_AM_MEDIA_TYPE* media_type)
+static BOOL tsmf_ffmpeg_set_format(ITSMFDecoder *decoder, TS_AM_MEDIA_TYPE *media_type)
{
- TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*) decoder;
-
- switch (media_type->MajorType)
+ TSMFFFmpegDecoder *mdecoder = (TSMFFFmpegDecoder *) decoder;
+ switch(media_type->MajorType)
{
case TSMF_MAJOR_TYPE_VIDEO:
mdecoder->media_type = AVMEDIA_TYPE_VIDEO;
@@ -231,7 +210,7 @@ static BOOL tsmf_ffmpeg_set_format(ITSMFDecoder* decoder, TS_AM_MEDIA_TYPE* medi
default:
return FALSE;
}
- switch (media_type->SubType)
+ switch(media_type->SubType)
{
case TSMF_SUB_TYPE_WVC1:
mdecoder->codec_id = CODEC_ID_VC1;
@@ -259,7 +238,7 @@ static BOOL tsmf_ffmpeg_set_format(ITSMFDecoder* decoder, TS_AM_MEDIA_TYPE* medi
/* For AAC the pFormat is a HEAACWAVEINFO struct, and the codec data
is at the end of it. See
http://msdn.microsoft.com/en-us/library/dd757806.aspx */
- if (media_type->ExtraData)
+ if(media_type->ExtraData)
{
media_type->ExtraData += 12;
media_type->ExtraDataSize -= 12;
@@ -275,118 +254,108 @@ static BOOL tsmf_ffmpeg_set_format(ITSMFDecoder* decoder, TS_AM_MEDIA_TYPE* medi
default:
return FALSE;
}
-
- if (!tsmf_ffmpeg_init_context(decoder))
+ if(!tsmf_ffmpeg_init_context(decoder))
return FALSE;
- if (!tsmf_ffmpeg_init_stream(decoder, media_type))
+ if(!tsmf_ffmpeg_init_stream(decoder, media_type))
return FALSE;
- if (!tsmf_ffmpeg_prepare(decoder))
+ if(!tsmf_ffmpeg_prepare(decoder))
return FALSE;
-
return TRUE;
}
-static BOOL tsmf_ffmpeg_decode_video(ITSMFDecoder* decoder, const BYTE* data, UINT32 data_size, UINT32 extensions)
+static BOOL tsmf_ffmpeg_decode_video(ITSMFDecoder *decoder, const BYTE *data, UINT32 data_size, UINT32 extensions)
{
- TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*) decoder;
+ TSMFFFmpegDecoder *mdecoder = (TSMFFFmpegDecoder *) decoder;
int decoded;
int len;
- AVFrame* frame;
+ AVFrame *frame;
BOOL ret = TRUE;
-
#if LIBAVCODEC_VERSION_MAJOR < 52 || (LIBAVCODEC_VERSION_MAJOR == 52 && LIBAVCODEC_VERSION_MINOR <= 20)
len = avcodec_decode_video(mdecoder->codec_context, mdecoder->frame, &decoded, data, data_size);
#else
{
AVPacket pkt;
av_init_packet(&pkt);
- pkt.data = (BYTE*) data;
+ pkt.data = (BYTE *) data;
pkt.size = data_size;
- if (extensions & TSMM_SAMPLE_EXT_CLEANPOINT)
+ if(extensions & TSMM_SAMPLE_EXT_CLEANPOINT)
pkt.flags |= AV_PKT_FLAG_KEY;
len = avcodec_decode_video2(mdecoder->codec_context, mdecoder->frame, &decoded, &pkt);
}
#endif
-
- if (len < 0)
+ if(len < 0)
{
DEBUG_WARN("data_size %d, avcodec_decode_video failed (%d)", data_size, len);
ret = FALSE;
}
- else if (!decoded)
- {
- DEBUG_WARN("data_size %d, no frame is decoded.", data_size);
- ret = FALSE;
- }
else
- {
- DEBUG_DVC("linesize[0] %d linesize[1] %d linesize[2] %d linesize[3] %d "
- "pix_fmt %d width %d height %d",
- mdecoder->frame->linesize[0], mdecoder->frame->linesize[1],
- mdecoder->frame->linesize[2], mdecoder->frame->linesize[3],
- mdecoder->codec_context->pix_fmt,
- mdecoder->codec_context->width, mdecoder->codec_context->height);
-
- mdecoder->decoded_size = avpicture_get_size(mdecoder->codec_context->pix_fmt,
- mdecoder->codec_context->width, mdecoder->codec_context->height);
- mdecoder->decoded_data = malloc(mdecoder->decoded_size);
- ZeroMemory(mdecoder->decoded_data, mdecoder->decoded_size);
- frame = avcodec_alloc_frame();
- avpicture_fill((AVPicture*) frame, mdecoder->decoded_data,
- mdecoder->codec_context->pix_fmt,
- mdecoder->codec_context->width, mdecoder->codec_context->height);
-
- av_picture_copy((AVPicture*) frame, (AVPicture*) mdecoder->frame,
- mdecoder->codec_context->pix_fmt,
- mdecoder->codec_context->width, mdecoder->codec_context->height);
-
- av_free(frame);
- }
-
+ if(!decoded)
+ {
+ DEBUG_WARN("data_size %d, no frame is decoded.", data_size);
+ ret = FALSE;
+ }
+ else
+ {
+ DEBUG_TSMF("linesize[0] %d linesize[1] %d linesize[2] %d linesize[3] %d "
+ "pix_fmt %d width %d height %d",
+ mdecoder->frame->linesize[0], mdecoder->frame->linesize[1],
+ mdecoder->frame->linesize[2], mdecoder->frame->linesize[3],
+ mdecoder->codec_context->pix_fmt,
+ mdecoder->codec_context->width, mdecoder->codec_context->height);
+ mdecoder->decoded_size = avpicture_get_size(mdecoder->codec_context->pix_fmt,
+ mdecoder->codec_context->width, mdecoder->codec_context->height);
+ mdecoder->decoded_data = malloc(mdecoder->decoded_size);
+ ZeroMemory(mdecoder->decoded_data, mdecoder->decoded_size);
+ frame = avcodec_alloc_frame();
+ avpicture_fill((AVPicture *) frame, mdecoder->decoded_data,
+ mdecoder->codec_context->pix_fmt,
+ mdecoder->codec_context->width, mdecoder->codec_context->height);
+ av_picture_copy((AVPicture *) frame, (AVPicture *) mdecoder->frame,
+ mdecoder->codec_context->pix_fmt,
+ mdecoder->codec_context->width, mdecoder->codec_context->height);
+ av_free(frame);
+ }
return ret;
}
-static BOOL tsmf_ffmpeg_decode_audio(ITSMFDecoder* decoder, const BYTE* data, UINT32 data_size, UINT32 extensions)
+static BOOL tsmf_ffmpeg_decode_audio(ITSMFDecoder *decoder, const BYTE *data, UINT32 data_size, UINT32 extensions)
{
- TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*) decoder;
+ TSMFFFmpegDecoder *mdecoder = (TSMFFFmpegDecoder *) decoder;
int len;
int frame_size;
UINT32 src_size;
- const BYTE* src;
- BYTE* dst;
+ const BYTE *src;
+ BYTE *dst;
int dst_offset;
-
#if 0
LLOGLN(0, ("tsmf_ffmpeg_decode_audio: data_size %d", data_size));
int i;
- for (i = 0; i < data_size; i++)
+ for(i = 0; i < data_size; i++)
{
LLOG(0, ("%02X ", data[i]));
- if (i % 16 == 15)
+ if(i % 16 == 15)
LLOG(0, ("\n"));
}
LLOG(0, ("\n"));
#endif
-
- if (mdecoder->decoded_size_max == 0)
+ if(mdecoder->decoded_size_max == 0)
mdecoder->decoded_size_max = MAX_AUDIO_FRAME_SIZE + 16;
mdecoder->decoded_data = malloc(mdecoder->decoded_size_max);
ZeroMemory(mdecoder->decoded_data, mdecoder->decoded_size_max);
/* align the memory for SSE2 needs */
- dst = (BYTE*) (((uintptr_t) mdecoder->decoded_data + 15) & ~ 0x0F);
+ dst = (BYTE *)(((uintptr_t) mdecoder->decoded_data + 15) & ~ 0x0F);
dst_offset = dst - mdecoder->decoded_data;
src = data;
src_size = data_size;
-
- while (src_size > 0)
+ while(src_size > 0)
{
/* Ensure enough space for decoding */
- if (mdecoder->decoded_size_max - mdecoder->decoded_size < MAX_AUDIO_FRAME_SIZE)
+ if(mdecoder->decoded_size_max - mdecoder->decoded_size < MAX_AUDIO_FRAME_SIZE)
{
mdecoder->decoded_size_max = mdecoder->decoded_size_max * 2 + 16;
mdecoder->decoded_data = realloc(mdecoder->decoded_data, mdecoder->decoded_size_max);
- dst = (BYTE*) (((uintptr_t)mdecoder->decoded_data + 15) & ~ 0x0F);
- if (dst - mdecoder->decoded_data != dst_offset)
+ dst = (BYTE *)(((uintptr_t)mdecoder->decoded_data + 15) & ~ 0x0F);
+ if(dst - mdecoder->decoded_data != dst_offset)
{
/* re-align the memory if the alignment has changed after realloc */
memmove(dst, mdecoder->decoded_data + dst_offset, mdecoder->decoded_size);
@@ -394,72 +363,64 @@ static BOOL tsmf_ffmpeg_decode_audio(ITSMFDecoder* decoder, const BYTE* data, UI
}
dst += mdecoder->decoded_size;
}
-
frame_size = mdecoder->decoded_size_max - mdecoder->decoded_size;
#if LIBAVCODEC_VERSION_MAJOR < 52 || (LIBAVCODEC_VERSION_MAJOR == 52 && LIBAVCODEC_VERSION_MINOR <= 20)
len = avcodec_decode_audio2(mdecoder->codec_context,
- (int16_t*) dst, &frame_size, src, src_size);
+ (int16_t *) dst, &frame_size, src, src_size);
#else
{
- AVFrame* decoded_frame = avcodec_alloc_frame();
+ AVFrame *decoded_frame = avcodec_alloc_frame();
int got_frame = 0;
AVPacket pkt;
av_init_packet(&pkt);
- pkt.data = (BYTE*) src;
+ pkt.data = (BYTE *) src;
pkt.size = src_size;
len = avcodec_decode_audio4(mdecoder->codec_context, decoded_frame, &got_frame, &pkt);
-
- if (len >= 0 && got_frame)
+ if(len >= 0 && got_frame)
{
frame_size = av_samples_get_buffer_size(NULL, mdecoder->codec_context->channels,
- decoded_frame->nb_samples, mdecoder->codec_context->sample_fmt, 1);
+ decoded_frame->nb_samples, mdecoder->codec_context->sample_fmt, 1);
memcpy(dst, decoded_frame->data[0], frame_size);
}
-
av_free(decoded_frame);
}
#endif
- if (len <= 0 || frame_size <= 0)
+ if(len <= 0 || frame_size <= 0)
{
DEBUG_WARN("error decoding");
break;
}
-
src += len;
src_size -= len;
mdecoder->decoded_size += frame_size;
dst += frame_size;
}
-
- if (mdecoder->decoded_size == 0)
+ if(mdecoder->decoded_size == 0)
{
free(mdecoder->decoded_data);
mdecoder->decoded_data = NULL;
}
- else if (dst_offset)
- {
- /* move the aligned decoded data to original place */
- memmove(mdecoder->decoded_data, mdecoder->decoded_data + dst_offset, mdecoder->decoded_size);
- }
-
- DEBUG_DVC("data_size %d decoded_size %d",
- data_size, mdecoder->decoded_size);
-
+ else
+ if(dst_offset)
+ {
+ /* move the aligned decoded data to original place */
+ memmove(mdecoder->decoded_data, mdecoder->decoded_data + dst_offset, mdecoder->decoded_size);
+ }
+ DEBUG_TSMF("data_size %d decoded_size %d",
+ data_size, mdecoder->decoded_size);
return TRUE;
}
-static BOOL tsmf_ffmpeg_decode(ITSMFDecoder* decoder, const BYTE* data, UINT32 data_size, UINT32 extensions)
+static BOOL tsmf_ffmpeg_decode(ITSMFDecoder *decoder, const BYTE *data, UINT32 data_size, UINT32 extensions)
{
- TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*) decoder;
-
- if (mdecoder->decoded_data)
+ TSMFFFmpegDecoder *mdecoder = (TSMFFFmpegDecoder *) decoder;
+ if(mdecoder->decoded_data)
{
free(mdecoder->decoded_data);
mdecoder->decoded_data = NULL;
}
mdecoder->decoded_size = 0;
-
- switch (mdecoder->media_type)
+ switch(mdecoder->media_type)
{
case AVMEDIA_TYPE_VIDEO:
return tsmf_ffmpeg_decode_video(decoder, data, data_size, extensions);
@@ -471,40 +432,35 @@ static BOOL tsmf_ffmpeg_decode(ITSMFDecoder* decoder, const BYTE* data, UINT32 d
}
}
-static BYTE* tsmf_ffmpeg_get_decoded_data(ITSMFDecoder* decoder, UINT32* size)
+static BYTE *tsmf_ffmpeg_get_decoded_data(ITSMFDecoder *decoder, UINT32 *size)
{
- BYTE* buf;
- TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*) decoder;
-
+ BYTE *buf;
+ TSMFFFmpegDecoder *mdecoder = (TSMFFFmpegDecoder *) decoder;
*size = mdecoder->decoded_size;
buf = mdecoder->decoded_data;
mdecoder->decoded_data = NULL;
mdecoder->decoded_size = 0;
-
return buf;
}
-static UINT32 tsmf_ffmpeg_get_decoded_format(ITSMFDecoder* decoder)
+static UINT32 tsmf_ffmpeg_get_decoded_format(ITSMFDecoder *decoder)
{
- TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*) decoder;
-
- switch (mdecoder->codec_context->pix_fmt)
+ TSMFFFmpegDecoder *mdecoder = (TSMFFFmpegDecoder *) decoder;
+ switch(mdecoder->codec_context->pix_fmt)
{
case PIX_FMT_YUV420P:
return RDP_PIXFMT_I420;
-
default:
DEBUG_WARN("unsupported pixel format %u",
- mdecoder->codec_context->pix_fmt);
+ mdecoder->codec_context->pix_fmt);
return (UINT32) -1;
}
}
-static BOOL tsmf_ffmpeg_get_decoded_dimension(ITSMFDecoder* decoder, UINT32* width, UINT32* height)
+static BOOL tsmf_ffmpeg_get_decoded_dimension(ITSMFDecoder *decoder, UINT32 *width, UINT32 *height)
{
- TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*) decoder;
-
- if (mdecoder->codec_context->width > 0 && mdecoder->codec_context->height > 0)
+ TSMFFFmpegDecoder *mdecoder = (TSMFFFmpegDecoder *) decoder;
+ if(mdecoder->codec_context->width > 0 && mdecoder->codec_context->height > 0)
{
*width = mdecoder->codec_context->width;
*height = mdecoder->codec_context->height;
@@ -516,25 +472,21 @@ static BOOL tsmf_ffmpeg_get_decoded_dimension(ITSMFDecoder* decoder, UINT32* wid
}
}
-static void tsmf_ffmpeg_free(ITSMFDecoder* decoder)
+static void tsmf_ffmpeg_free(ITSMFDecoder *decoder)
{
- TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*) decoder;
-
- if (mdecoder->frame)
+ TSMFFFmpegDecoder *mdecoder = (TSMFFFmpegDecoder *) decoder;
+ if(mdecoder->frame)
av_free(mdecoder->frame);
-
- if (mdecoder->decoded_data)
+ if(mdecoder->decoded_data)
free(mdecoder->decoded_data);
-
- if (mdecoder->codec_context)
+ if(mdecoder->codec_context)
{
- if (mdecoder->prepared)
+ if(mdecoder->prepared)
avcodec_close(mdecoder->codec_context);
- if (mdecoder->codec_context->extradata)
+ if(mdecoder->codec_context->extradata)
free(mdecoder->codec_context->extradata);
av_free(mdecoder->codec_context);
}
-
free(decoder);
}
@@ -544,27 +496,22 @@ static BOOL initialized = FALSE;
#define freerdp_tsmf_client_decoder_subsystem_entry ffmpeg_freerdp_tsmf_client_decoder_subsystem_entry
#endif
-ITSMFDecoder* freerdp_tsmf_client_decoder_subsystem_entry(void)
+ITSMFDecoder *freerdp_tsmf_client_decoder_subsystem_entry(void)
{
- TSMFFFmpegDecoder* decoder;
-
- if (!initialized)
+ TSMFFFmpegDecoder *decoder;
+ if(!initialized)
{
avcodec_register_all();
initialized = TRUE;
}
-
fprintf(stderr, "TSMFDecoderEntry FFMPEG\n");
-
- decoder = (TSMFFFmpegDecoder*) malloc(sizeof(TSMFFFmpegDecoder));
+ decoder = (TSMFFFmpegDecoder *) malloc(sizeof(TSMFFFmpegDecoder));
ZeroMemory(decoder, sizeof(TSMFFFmpegDecoder));
-
decoder->iface.SetFormat = tsmf_ffmpeg_set_format;
decoder->iface.Decode = tsmf_ffmpeg_decode;
decoder->iface.GetDecodedData = tsmf_ffmpeg_get_decoded_data;
decoder->iface.GetDecodedFormat = tsmf_ffmpeg_get_decoded_format;
decoder->iface.GetDecodedDimension = tsmf_ffmpeg_get_decoded_dimension;
decoder->iface.Free = tsmf_ffmpeg_free;
-
- return (ITSMFDecoder*) decoder;
+ return (ITSMFDecoder *) decoder;
}
diff --git a/channels/tsmf/client/gstreamer/CMakeLists.txt b/channels/tsmf/client/gstreamer/CMakeLists.txt
index 5080358c8..3415da717 100644
--- a/channels/tsmf/client/gstreamer/CMakeLists.txt
+++ b/channels/tsmf/client/gstreamer/CMakeLists.txt
@@ -7,7 +7,7 @@
# 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
+# 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,
@@ -17,26 +17,60 @@
define_channel_client_subsystem("tsmf" "gstreamer" "decoder")
-set(${MODULE_PREFIX}_SRCS
- tsmf_gstreamer.c)
+if(NOT GSTREAMER_0_10_FOUND AND NOT GSTREAMER_1_0_FOUND)
+ message(FATAL_ERROR "GStreamer library not found, but required for TSMF module.")
+elseif (GSTREAMER_0_10_FOUND AND GSTREAMER_1_0_FOUND)
+ message(FATAL_ERROR "GStreamer 0.10 and GStreamer 1.0 support are mutually exclusive!")
+endif()
+
+set(SRC "tsmf_gstreamer.c")
+
+if (GSTREAMER_1_0_FOUND)
+ set(LIBS ${GSTREAMER_1_0_LIBRARIES})
+ include_directories(${GSTREAMER_1_0_INCLUDE_DIRS})
+elseif (GSTREAMER_0_10_FOUND)
+ set(LIBS ${GSTREAMER_0_10_LIBRARIES})
+ include_directories(${GSTREAMER_0_10_INCLUDE_DIRS})
+endif()
+
+if(ANDROID)
+ set(SRC ${SRC}
+ tsmf_android.c)
+ set(LIBS ${LIBS})
+else()
+ set(XEXT_FEATURE_TYPE "RECOMMENDED")
+ set(XEXT_FEATURE_PURPOSE "X11 extension")
+ set(XEXT_FEATURE_DESCRIPTION "X11 core extensions")
+
+ find_feature(Xext ${XEXT_FEATURE_TYPE} ${XEXT_FEATURE_PURPOSE} ${XEXT_FEATURE_DESCRIPTION})
+
+ set(SRC ${SRC}
+ tsmf_X11.c)
+ set(LIBS ${LIBS} ${X11_LIBRARIES} ${XEXT_LIBRARIES})
+
+ if(NOT XEXT_FOUND)
+ message(FATAL_ERROR "Xext library not found, but required for TSMF module.")
+ else()
+ add_definitions(-DWITH_XEXT=1)
+ endif()
+
+endif()
+
+set(${MODULE_PREFIX}_SRCS "${SRC}")
include_directories(..)
-include_directories(${GSTREAMER_INCLUDE_DIRS})
add_channel_client_subsystem_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} "" TRUE "")
set_target_properties(${MODULE_NAME} PROPERTIES PREFIX "")
set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
- MONOLITHIC ${MONOLITHIC_BUILD}
- MODULE freerdp
- MODULES freerdp-utils)
+ MONOLITHIC ${MONOLITHIC_BUILD}
+ MODULE freerdp
+ MODULES freerdp-utils)
set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS}
- ${GSTREAMER_LIBRARIES}
- gstapp-0.10
- gstinterfaces-0.10
- Xrandr X11 Xext)
+ ${LIBS})
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
diff --git a/channels/tsmf/client/gstreamer/tsmf_X11.c b/channels/tsmf/client/gstreamer/tsmf_X11.c
new file mode 100644
index 000000000..6acc6eeb3
--- /dev/null
+++ b/channels/tsmf/client/gstreamer/tsmf_X11.c
@@ -0,0 +1,316 @@
+/*
+ * FreeRDP: A Remote Desktop Protocol Implementation
+ * Video Redirection Virtual Channel - GStreamer Decoder X11 specifics
+ *
+ * (C) Copyright 2014 Thincast Technologies GmbH
+ * (C) Copyright 2014 Armin Novak <armin.novak@thincast.com>
+ *
+ * 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.
+*/
+
+#include <assert.h>
+
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/syscall.h>
+
+#include <unistd.h>
+#include <fcntl.h>
+#include <winpr/thread.h>
+
+#include <gst/gst.h>
+#if GST_VERSION_MAJOR > 0
+#include <gst/video/videooverlay.h>
+#else
+#include <gst/interfaces/xoverlay.h>
+#endif
+
+#include <X11/Xlib.h>
+#include <X11/extensions/Xrandr.h>
+#include <X11/extensions/shape.h>
+
+#include <freerdp/channels/tsmf.h>
+
+#include "tsmf_platform.h"
+#include "tsmf_constants.h"
+#include "tsmf_decoder.h"
+
+#if !defined(WITH_XEXT)
+#warning "Building TSMF without shape extension support"
+#endif
+
+struct X11Handle
+{
+ int shmid;
+ int *xfwin;
+#if defined(WITH_XEXT)
+ BOOL has_shape;
+#endif
+ Display *disp;
+ Window subwin;
+};
+
+static const char *get_shm_id()
+{
+ static char shm_id[64];
+ snprintf(shm_id, sizeof(shm_id), "com.freerdp.xfreerpd.tsmf_%016X", GetCurrentProcessId());
+ return shm_id;
+}
+
+const char *tsmf_platform_get_video_sink(void)
+{
+ return "xvimagesink";
+}
+
+const char *tsmf_platform_get_audio_sink(void)
+{
+ return "autoaudiosink";
+}
+
+int tsmf_platform_create(TSMFGstreamerDecoder *decoder)
+{
+ struct X11Handle *hdl;
+ assert(decoder);
+ assert(!decoder->platform);
+ hdl = malloc(sizeof(struct X11Handle));
+
+ if (!hdl)
+ {
+ DEBUG_WARN("%s: Could not allocate handle.", __func__);
+ return -1;
+ }
+
+ memset(hdl, 0, sizeof(struct X11Handle));
+ decoder->platform = hdl;
+ hdl->shmid = shm_open(get_shm_id(), O_RDWR, PROT_READ | PROT_WRITE);;
+
+ if (hdl->shmid < 0)
+ {
+ DEBUG_WARN("%s: failed to get access to shared memory - shmget()",
+ __func__);
+ return -2;
+ }
+ else
+ hdl->xfwin = mmap(0, sizeof(void *), PROT_READ | PROT_WRITE, MAP_SHARED, hdl->shmid, 0);
+
+ if (hdl->xfwin == (int *)-1)
+ {
+ DEBUG_WARN("%s: shmat failed!", __func__);
+ return -3;
+ }
+
+ hdl->disp = XOpenDisplay(NULL);
+
+ if (!hdl->disp)
+ {
+ DEBUG_WARN("Failed to open display");
+ return -4;
+ }
+
+ return 0;
+}
+
+int tsmf_platform_set_format(TSMFGstreamerDecoder *decoder)
+{
+ assert(decoder);
+
+ if (decoder->media_type == TSMF_MAJOR_TYPE_VIDEO)
+ {
+ }
+
+ return 0;
+}
+
+int tsmf_platform_register_handler(TSMFGstreamerDecoder *decoder)
+{
+ assert(decoder);
+ assert(decoder->pipe);
+ GstBus *bus = gst_pipeline_get_bus(GST_PIPELINE(decoder->pipe));
+
+ if (!bus)
+ {
+ DEBUG_WARN("gst_pipeline_get_bus failed!");
+ return 1;
+ }
+
+ return 0;
+}
+
+int tsmf_platform_free(TSMFGstreamerDecoder *decoder)
+{
+ struct X11Handle *hdl = decoder->platform;
+
+ if (!hdl)
+ return -1;
+
+ if (hdl->disp)
+ XCloseDisplay(hdl->disp);
+
+ if (hdl->xfwin)
+ munmap(0, sizeof(void *));
+
+ if (hdl->shmid >= 0)
+ close(hdl->shmid);
+
+ free(hdl);
+ decoder->platform = NULL;
+ return 0;
+}
+
+int tsmf_window_create(TSMFGstreamerDecoder *decoder)
+{
+ if (decoder->media_type != TSMF_MAJOR_TYPE_VIDEO)
+ {
+ decoder->ready = TRUE;
+ return -3;
+ }
+ else
+ {
+#if GST_VERSION_MAJOR > 0
+ GstVideoOverlay *overlay = GST_VIDEO_OVERLAY(decoder->outsink);
+#else
+ GstXOverlay *overlay = GST_X_OVERLAY(decoder->outsink);
+#endif
+ struct X11Handle *hdl = (struct X11Handle *)decoder->platform;
+ assert(decoder);
+ assert(hdl);
+
+ if (!hdl->subwin)
+ {
+ int event, error;
+ hdl->subwin = XCreateSimpleWindow(hdl->disp, *(int *)hdl->xfwin, 0, 0, 1, 1, 0, 0, 0);
+
+ if (!hdl->subwin)
+ {
+ DEBUG_WARN("Could not create subwindow!");
+ }
+
+ XMapWindow(hdl->disp, hdl->subwin);
+ XSync(hdl->disp, FALSE);
+#if GST_VERSION_MAJOR > 0
+ gst_video_overlay_set_window_handle(overlay, hdl->subwin);
+#else
+ gst_x_overlay_set_window_handle(overlay, hdl->subwin);
+#endif
+ decoder->ready = TRUE;
+#if defined(WITH_XEXT)
+ hdl->has_shape = XShapeQueryExtension(hdl->disp, &event, &error);
+#endif
+ }
+
+#if GST_VERSION_MAJOR > 0
+ gst_video_overlay_handle_events(overlay, TRUE);
+#else
+ gst_x_overlay_handle_events(overlay, TRUE);
+#endif
+ return 0;
+ }
+}
+
+int tsmf_window_resize(TSMFGstreamerDecoder *decoder, int x, int y, int width,
+ int height, int nr_rects, RDP_RECT *rects)
+{
+ if (decoder->media_type != TSMF_MAJOR_TYPE_VIDEO)
+ return -3;
+ else
+ {
+#if GST_VERSION_MAJOR > 0
+ GstVideoOverlay *overlay = GST_VIDEO_OVERLAY(decoder->outsink);
+#else
+ GstXOverlay *overlay = GST_X_OVERLAY(decoder->outsink);
+#endif
+ struct X11Handle *hdl = (struct X11Handle *)decoder->platform;
+ DEBUG_TSMF("resize: x=%d, y=%d, w=%d, h=%d", x, y, width, height);
+ assert(decoder);
+ assert(hdl);
+#if GST_VERSION_MAJOR > 0
+
+ if (!gst_video_overlay_set_render_rectangle(overlay, 0, 0, width, height))
+ {
+ DEBUG_WARN("Could not resize overlay!");
+ }
+
+ gst_video_overlay_expose(overlay);
+#else
+ if (!gst_x_overlay_set_render_rectangle(overlay, 0, 0, width, height))
+ {
+ DEBUG_WARN("Could not resize overlay!");
+ }
+
+ gst_x_overlay_expose(overlay);
+#endif
+
+ if (hdl->subwin)
+ {
+ XMoveResizeWindow(hdl->disp, hdl->subwin, x, y, width, height);
+#if defined(WITH_XEXT)
+
+ if (hdl->has_shape)
+ {
+ int i;
+ XRectangle *xrects = calloc(nr_rects, sizeof(XRectangle));
+
+ for (i=0; i<nr_rects; i++)
+ {
+ xrects[i].x = rects[i].x - x;
+ xrects[i].y = rects[i].y - y;
+ xrects[i].width = rects[i].width;
+ xrects[i].height = rects[i].height;
+ }
+
+ XShapeCombineRectangles(hdl->disp, hdl->subwin, ShapeBounding, x, y, xrects, nr_rects, ShapeSet, 0);
+ free(xrects);
+ }
+
+#endif
+ XSync(hdl->disp, FALSE);
+ }
+
+ return 0;
+ }
+}
+
+int tsmf_window_pause(TSMFGstreamerDecoder *decoder)
+{
+ assert(decoder);
+ return 0;
+}
+
+int tsmf_window_resume(TSMFGstreamerDecoder *decoder)
+{
+ assert(decoder);
+ return 0;
+}
+
+int tsmf_window_destroy(TSMFGstreamerDecoder *decoder)
+{
+ struct X11Handle *hdl = (struct X11Handle *)decoder->platform;
+ decoder->ready = FALSE;
+
+ if (decoder->media_type != TSMF_MAJOR_TYPE_VIDEO)
+ return -3;
+
+ assert(decoder);
+ assert(hdl);
+
+ if (hdl->subwin)
+ {
+ XDestroyWindow(hdl->disp, hdl->subwin);
+ XSync(hdl->disp, FALSE);
+ }
+
+ hdl->subwin = 0;
+ return 0;
+}
+
diff --git a/channels/tsmf/client/gstreamer/tsmf_gstreamer.c b/channels/tsmf/client/gstreamer/tsmf_gstreamer.c
index d3c477c92..33a609bef 100644
--- a/channels/tsmf/client/gstreamer/tsmf_gstreamer.c
+++ b/channels/tsmf/client/gstreamer/tsmf_gstreamer.c
@@ -2,8 +2,10 @@
* FreeRDP: A Remote Desktop Protocol Implementation
* Video Redirection Virtual Channel - GStreamer Decoder
*
- * (C) Copyright 2012 HP Development Company, LLC
- *
+ * (C) Copyright 2012 HP Development Company, LLC
+ * (C) Copyright 2014 Thincast Technologies GmbH
+ * (C) Copyright 2014 Armin Novak <armin.novak@thincast.com>
+ *
* 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
@@ -21,329 +23,165 @@
#include "config.h"
#endif
-#include <X11/Xlib.h>
-#include <X11/extensions/Xrandr.h>
-#include <X11/extensions/shape.h>
+#include <assert.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
-#include <pthread.h>
#include <gst/gst.h>
#include <gst/app/gstappsrc.h>
#include <gst/app/gstappsink.h>
-#include <gst/interfaces/xoverlay.h>
-
-#include <sys/types.h>
-#include <sys/shm.h>
-#include <sys/mman.h>
-#include <sys/stat.h>
-#include <sys/syscall.h>
#include "tsmf_constants.h"
#include "tsmf_decoder.h"
+#include "tsmf_platform.h"
#ifdef HAVE_INTTYPES_H
#include <inttypes.h>
#endif
-#define SHARED_MEM_KEY 7777
-#define TRY_DECODEBIN 0
+static BOOL tsmf_gstreamer_pipeline_build(TSMFGstreamerDecoder *mdecoder);
+static void tsmf_gstreamer_clean_up(TSMFGstreamerDecoder *mdecoder);
+static int tsmf_gstreamer_pipeline_set_state(TSMFGstreamerDecoder *mdecoder,
+ GstState desired_state);
-typedef struct _TSMFGstreamerDecoder
+const char *get_type(TSMFGstreamerDecoder *mdecoder)
{
- ITSMFDecoder iface;
-
- int media_type; /* TSMF_MAJOR_TYPE_AUDIO or TSMF_MAJOR_TYPE_VIDEO */
-
- TS_AM_MEDIA_TYPE tsmf_media_type; /* TSMF description of the media type, (without ExtraData) */
+ assert(mdecoder);
- pthread_t eventloop_thread;
+ if (mdecoder->media_type == TSMF_MAJOR_TYPE_VIDEO)
+ return "VIDEO";
+ else
+ return "AUDIO";
+}
- GstCaps *gst_caps; /* Gstreamer description of the media type */
+static void tsmf_gstreamer_enough_data(GstAppSrc *src, gpointer user_data)
+{
+ TSMFGstreamerDecoder *mdecoder = user_data;
+ (void)mdecoder;
+ DEBUG_TSMF("%s", get_type(mdecoder));
+}
- GstState state;
+static void tsmf_gstreamer_need_data(GstAppSrc *src, guint length, gpointer user_data)
+{
+ TSMFGstreamerDecoder *mdecoder = user_data;
+ (void)mdecoder;
+ DEBUG_TSMF("%s length=%lu", get_type(mdecoder), length);
+}
- GstElement *pipe;
- GstElement *src;
- GstElement *queue;
- GstElement *decbin;
- GstElement *outbin;
- GstElement *outconv;
- GstElement *outsink;
- GstElement *aVolume;
+static gboolean tsmf_gstreamer_seek_data(GstAppSrc *src, guint64 offset, gpointer user_data)
+{
+ TSMFGstreamerDecoder *mdecoder = user_data;
+ (void)mdecoder;
+ DEBUG_TSMF("%s offset=%llu", get_type(mdecoder), offset);
- BOOL paused;
- UINT64 last_sample_end_time;
+ if (!mdecoder->paused)
+ tsmf_gstreamer_pipeline_set_state(mdecoder, GST_STATE_PAUSED);
- Display *disp;
- int *xfwin;
- Window subwin;
- int xOffset;
- int yOffset;
- BOOL offsetObtained;
- int linked;
- double gstVolume;
- BOOL gstMuted;
+ gst_app_src_end_of_stream((GstAppSrc *)mdecoder->src);
- int pipeline_start_time_valid; /* We've set the start time and have not reset the pipeline */
- int shutdown; /* The decoder stream is shutting down */
- pthread_mutex_t gst_mutex;
+ if (!mdecoder->paused)
+ tsmf_gstreamer_pipeline_set_state(mdecoder, GST_STATE_PLAYING);
-} TSMFGstreamerDecoder;
+ if (mdecoder->sync_cb)
+ mdecoder->sync_cb(mdecoder->stream);
-const char *NAME_GST_STATE_PLAYING = "GST_STATE_PLAYING";
-const char *NAME_GST_STATE_PAUSED = "GST_STATE_PAUSED";
-const char *NAME_GST_STATE_READY = "GST_STATE_READY";
-const char *NAME_GST_STATE_NULL = "GST_STATE_NULL";
-const char *NAME_GST_STATE_VOID_PENDING = "GST_STATE_VOID_PENDING";
-const char *NAME_GST_STATE_OTHER = "GST_STATE_?";
+ return TRUE;
+}
static inline const GstClockTime tsmf_gstreamer_timestamp_ms_to_gst(UINT64 ms_timestamp)
{
- /*
+ /*
* Convert Microsoft 100ns timestamps to Gstreamer 1ns units.
*/
return (GstClockTime)(ms_timestamp * 100);
}
-static const char *tsmf_gstreamer_state_name(GstState state)
+int tsmf_gstreamer_pipeline_set_state(TSMFGstreamerDecoder *mdecoder, GstState desired_state)
{
+ GstStateChangeReturn state_change;
const char *name;
+ const char *sname = get_type(mdecoder);
- if (state == GST_STATE_PLAYING) name = NAME_GST_STATE_PLAYING;
- else if (state == GST_STATE_PAUSED) name = NAME_GST_STATE_PAUSED;
- else if (state == GST_STATE_READY) name = NAME_GST_STATE_READY;
- else if (state == GST_STATE_NULL) name = NAME_GST_STATE_NULL;
- else if (state == GST_STATE_VOID_PENDING) name = NAME_GST_STATE_VOID_PENDING;
- else name = NAME_GST_STATE_OTHER;
-
- return name;
-}
-
-#if 0
-static void *tsmf_gstreamer_eventloop_thread_func(void * arg)
-{
- TSMFGstreamerDecoder * mdecoder = (TSMFGstreamerDecoder *) arg;
- GstBus *bus;
- GstMessage *message = NULL;
- GstState old, new, pending;
- int loop;
-
- DEBUG_DVC("tsmf_gstreamer_eventloop_thread_func: ");
-
- bus = gst_element_get_bus(mdecoder->pipe);
-
- loop = 1;
- while (loop)
- {
- message = gst_bus_poll (bus, GST_MESSAGE_ANY, -1);
-
- if (mdecoder->shutdown)
- {
- loop =0; /* We are done with this stream */
- }
- else
- {
- switch (message->type)
- {
- case GST_MESSAGE_EOS:
- DEBUG_DVC("tsmf_gstreamer_eventloop_thread_func: GST_MESSAGE_EOS");
- gst_message_unref (message);
- break;
-
- case GST_MESSAGE_WARNING:
- case GST_MESSAGE_ERROR:
- {
- DEBUG_DVC("tsmf_gstreamer_eventloop_thread_func: GST_MESSAGE_ERROR");
- /*GError *err;
- gchar *debug;
- gst_message_parse_error(message, &err, &debug);
- g_print("ERROR: %s\nDEBUG:%s\n", err->message, debug);
- g_error_free(err);
- g_free(debug);
- gst_message_unref(message);*/
- break;
- }
- case GST_MESSAGE_STATE_CHANGED:
- {
- gchar *name = gst_object_get_path_string (GST_MESSAGE_SRC(message));
-
- gst_message_parse_state_changed (message, &old, &new, &pending);
-
- DEBUG_DVC("tsmf_gstreamer_eventloop_thread_func: GST_MESSAGE_STATE_CHANGED %s old %s new %s pending %s",
- name,
- gst_element_state_get_name(old),
- gst_element_state_get_name(new),
- gst_element_state_get_name(pending));
-
- g_free (name);
- gst_message_unref(message);
-
- break;
- }
-
- case GST_MESSAGE_REQUEST_STATE:
- {
- GstState state;
- gchar *name = gst_object_get_path_string (GST_MESSAGE_SRC(message));
-
- gst_message_parse_request_state(message, &state);
-
- DEBUG_DVC("GST_MESSAGE_REQUEST_STATE: Setting %s state to %s", name, gst_element_state_get_name(state));
-
- gst_element_set_state (mdecoder->pipe, state);
-
- g_free (name);
-
- gst_message_unref(message);
- break;
- }
-
- default:
- gst_message_unref(message);
- break;
- }
- }
- }
-
- mdecoder->eventloop_thread = 0;
-
- DEBUG_DVC("tsmf_gstreamer_eventloop_thread_func: EXITED");
- return 0;
-}
+ if (!mdecoder)
+ return 0;
-static int tsmf_gstreamer_start_eventloop_thread(TSMFGstreamerDecoder *mdecoder)
-{
- pthread_create(&(mdecoder->eventloop_thread), 0, tsmf_gstreamer_eventloop_thread_func, mdecoder);
- pthread_detach(mdecoder->eventloop_thread);
+ if (!mdecoder->pipe)
+ return 0; /* Just in case this is called during startup or shutdown when we don't expect it */
- return 0;
-}
-#endif
+ if (desired_state == mdecoder->state)
+ return 0; /* Redundant request - Nothing to do */
-static int tsmf_gstreamer_stop_eventloop_thread(TSMFGstreamerDecoder *mdecoder)
-{
- DEBUG_DVC("tsmf_gstreamer_stop_eventloop_thread: ");
- if (!mdecoder)
- return 0;
+ name = gst_element_state_get_name(desired_state); /* For debug */
+ DEBUG_TSMF("%s to %s", sname, name);
+ state_change = gst_element_set_state(mdecoder->pipe, desired_state);
- if (mdecoder->eventloop_thread != 0)
+ if (state_change == GST_STATE_CHANGE_FAILURE)
+ DEBUG_WARN("%s: (%s) GST_STATE_CHANGE_FAILURE.", sname, name);
+ else if (state_change == GST_STATE_CHANGE_ASYNC)
{
- pthread_cancel(mdecoder->eventloop_thread);
+ DEBUG_WARN("%s: (%s) GST_STATE_CHANGE_ASYNC.", sname, name);
+ mdecoder->state = desired_state;
}
+ else
+ mdecoder->state = desired_state;
return 0;
}
-static int tsmf_gstreamer_pipeline_set_state(TSMFGstreamerDecoder * mdecoder, GstState desired_state)
+static GstBuffer *tsmf_get_buffer_from_data(const void *raw_data, gsize size)
{
- if (!mdecoder)
- return 0;
- GstStateChangeReturn state_change;
- int keep_waiting;
- int timeout;
- GstState current_state;
- GstState pending_state;
- const char *name;
- const char *current_name;
- const char *pending_name;
-
- if (!mdecoder->pipe)
- return 0; /* Just in case this is called during startup or shutdown when we don't expect it */
-
- if (desired_state == mdecoder->state)
- return 0; /* Redundant request - Nothing to do */
+ GstBuffer *buffer;
+ gpointer data;
+ assert(raw_data);
+ assert(size > 0);
+ data = g_malloc(size);
- name = tsmf_gstreamer_state_name(desired_state); /* For debug */
+ if (!data)
+ {
+ DEBUG_WARN("Could not allocate %"G_GSIZE_FORMAT" bytes of data.", size);
+ return NULL;
+ }
- keep_waiting = 1;
- state_change = gst_element_set_state (mdecoder->pipe, desired_state);
- timeout = 1000;
- if (mdecoder->media_type == TSMF_MAJOR_TYPE_VIDEO)
- DEBUG_DVC("tsmf_gstreamer_pipeline_set_state_VIDEO:");
- else
- DEBUG_DVC("tsmf_gstreamer_pipeline_set_state_AUDIO:");
+ memcpy(data, raw_data, size);
+#if GST_VERSION_MAJOR > 0
+ buffer = gst_buffer_new_wrapped(data, size);
+#else
+ buffer = gst_buffer_new();
- while (keep_waiting)
+ if (!buffer)
{
- if (state_change == GST_STATE_CHANGE_FAILURE)
- {
- DEBUG_WARN("tsmf_gstreamer_pipeline_set_state(%s) GST_STATE_CHANGE_FAILURE.", name);
- keep_waiting = 0;
- }
- else if (state_change == GST_STATE_CHANGE_SUCCESS)
- {
- DEBUG_DVC("tsmf_gstreamer_pipeline_set_state(%s) GST_STATE_CHANGE_SUCCESS.", name);
- mdecoder->state = desired_state;
- keep_waiting = 0;
- }
- else if (state_change == GST_STATE_CHANGE_NO_PREROLL)
- {
- DEBUG_DVC("tsmf_gstreamer_pipeline_set_state(%s) GST_STATE_CHANGE_NO_PREROLL.", name);
- keep_waiting = 0;
- }
- else if (state_change == GST_STATE_CHANGE_ASYNC)
- {
- DEBUG_DVC("tsmf_gstreamer_pipeline_set_state(%s) GST_STATE_CHANGE_ASYNC.", name);
-
- state_change = gst_element_get_state(mdecoder->pipe, &current_state, &pending_state, 10 * GST_MSECOND);
- current_name = tsmf_gstreamer_state_name(current_state);
- pending_name = tsmf_gstreamer_state_name(pending_state);
-
- if (current_state == desired_state)
- {
- DEBUG_DVC("tsmf_gstreamer_pipeline_set_state(%s) GST_STATE_CHANGE_SUCCESS.", name);
- mdecoder->state = desired_state;
- keep_waiting = 0;
- }
- else if (pending_state != desired_state)
- {
- DEBUG_DVC("tsmf_gstreamer_pipeline_set_state(%s) changing to %s instead.", name, pending_name);
- keep_waiting = 0;
- }
- else
- {
- DEBUG_DVC("tsmf_gstreamer_pipeline_set_state(%s) Waiting - current %s pending %s.", name, current_name, pending_name);
- }
- }
- /*
- To avoid RDP session hang. set timeout for changing gstreamer state to 5 seconds.
- */
- usleep(10000);
- timeout--;
- if (timeout <= 0)
- {
- DEBUG_WARN("tsmf_gstreamer_pipeline_set_state: TIMED OUT - failed to change state");
- keep_waiting = 0;
- break;
- }
+ DEBUG_WARN("Could not create GstBuffer");
+ free(data);
+ return NULL;
}
- //sleep(1);
- return 0;
+
+ GST_BUFFER_MALLOCDATA(buffer) = data;
+ GST_BUFFER_SIZE(buffer) = size;
+ GST_BUFFER_DATA(buffer) = GST_BUFFER_MALLOCDATA(buffer);
+#endif
+ return buffer;
}
-static BOOL tsmf_gstreamer_set_format(ITSMFDecoder * decoder, TS_AM_MEDIA_TYPE * media_type)
+static BOOL tsmf_gstreamer_set_format(ITSMFDecoder *decoder, TS_AM_MEDIA_TYPE *media_type)
{
- TSMFGstreamerDecoder * mdecoder = (TSMFGstreamerDecoder *) decoder;
+ TSMFGstreamerDecoder *mdecoder = (TSMFGstreamerDecoder *) decoder;
+
if (!mdecoder)
- return FALSE;
- GstBuffer *gst_buf_cap_codec_data; /* Buffer to hold extra descriptive codec-specific caps data */
+ return FALSE;
- DEBUG_DVC("tsmf_gstreamer_set_format: ");
+ DEBUG_TSMF("");
switch (media_type->MajorType)
{
case TSMF_MAJOR_TYPE_VIDEO:
mdecoder->media_type = TSMF_MAJOR_TYPE_VIDEO;
- mdecoder->tsmf_media_type = *media_type; /* Structure copy */
break;
case TSMF_MAJOR_TYPE_AUDIO:
mdecoder->media_type = TSMF_MAJOR_TYPE_AUDIO;
- mdecoder->tsmf_media_type = *media_type; /* Structure copy */
break;
default:
return FALSE;
@@ -352,230 +190,104 @@ static BOOL tsmf_gstreamer_set_format(ITSMFDecoder * decoder, TS_AM_MEDIA_TYPE *
switch (media_type->SubType)
{
case TSMF_SUB_TYPE_WVC1:
- gst_buf_cap_codec_data = gst_buffer_try_new_and_alloc(media_type->ExtraDataSize);
- if (gst_buf_cap_codec_data != NULL)
- {
- memcpy(GST_BUFFER_MALLOCDATA(gst_buf_cap_codec_data),
- media_type->ExtraData, media_type->ExtraDataSize);
- }
- else
- {
- DEBUG_WARN("tsmf_gstreamer_set_format: gst_buffer_try_new_and_alloc(%d) failed.",
- media_type->ExtraDataSize);
- }
- mdecoder->gst_caps = gst_caps_new_simple ("video/x-wmv",
- "bitrate", G_TYPE_UINT, media_type->BitRate,
- "width", G_TYPE_INT, media_type->Width,
- "height", G_TYPE_INT, media_type->Height,
- "wmvversion", G_TYPE_INT, 3,
- "codec_data", GST_TYPE_BUFFER, gst_buf_cap_codec_data,
- "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('W', 'V', 'C', '1'),
- //"framerate", GST_TYPE_FRACTION, media_type->SamplesPerSecond.Numerator, media_type->SamplesPerSecond.Denominator,
- NULL);
+ mdecoder->gst_caps = gst_caps_new_simple("video/x-wmv",
+ "bitrate", G_TYPE_UINT, media_type->BitRate,
+ "width", G_TYPE_INT, media_type->Width,
+ "height", G_TYPE_INT, media_type->Height,
+ "wmvversion", G_TYPE_INT, 3,
+ NULL);
break;
case TSMF_SUB_TYPE_MP4S:
- if (media_type->ExtraDataSize > 0)
- {
- gst_buf_cap_codec_data = gst_buffer_try_new_and_alloc(media_type->ExtraDataSize);
- if (gst_buf_cap_codec_data != NULL)
- {
- memcpy(GST_BUFFER_MALLOCDATA(gst_buf_cap_codec_data), media_type->ExtraData, media_type->ExtraDataSize);
- }
- else
- {
- DEBUG_WARN("tsmf_gstreamer_set_format: gst_buffer_try_new_and_alloc(%d) failed.", media_type->ExtraDataSize);
- }
- mdecoder->gst_caps = gst_caps_new_simple ("video/x-divx",
- "divxversion", G_TYPE_INT, 5,
- "bitrate", G_TYPE_UINT, media_type->BitRate,
- "width", G_TYPE_INT, media_type->Width,
- "height", G_TYPE_INT, media_type->Height,
- "codec_data", GST_TYPE_BUFFER, gst_buf_cap_codec_data,
- NULL);
- }
- else
- {
- mdecoder->gst_caps = gst_caps_new_simple ("video/x-divx",
- "divxversion", G_TYPE_INT, 5,
- "bitrate", G_TYPE_UINT, media_type->BitRate,
- "width", G_TYPE_INT, media_type->Width,
- "height", G_TYPE_INT, media_type->Height,
- NULL);
- }
+ mdecoder->gst_caps = gst_caps_new_simple("video/x-divx",
+ "divxversion", G_TYPE_INT, 5,
+ "bitrate", G_TYPE_UINT, media_type->BitRate,
+ "width", G_TYPE_INT, media_type->Width,
+ "height", G_TYPE_INT, media_type->Height,
+ NULL);
break;
case TSMF_SUB_TYPE_MP42:
- mdecoder->gst_caps = gst_caps_new_simple ("video/x-msmpeg",
- "msmpegversion", G_TYPE_INT, 42,
- "bitrate", G_TYPE_UINT, media_type->BitRate,
- "width", G_TYPE_INT, media_type->Width,
- "height", G_TYPE_INT, media_type->Height,
- NULL);
+ mdecoder->gst_caps = gst_caps_new_simple("video/x-msmpeg",
+ "msmpegversion", G_TYPE_INT, 42,
+ "bitrate", G_TYPE_UINT, media_type->BitRate,
+ "width", G_TYPE_INT, media_type->Width,
+ "height", G_TYPE_INT, media_type->Height,
+ NULL);
break;
case TSMF_SUB_TYPE_MP43:
- mdecoder->gst_caps = gst_caps_new_simple ("video/x-msmpeg",
- "bitrate", G_TYPE_UINT, media_type->BitRate,
- "width", G_TYPE_INT, media_type->Width,
- "height", G_TYPE_INT, media_type->Height,
- "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('M', 'P', '4', '3'),
- NULL);
+ mdecoder->gst_caps = gst_caps_new_simple("video/x-msmpeg",
+ "bitrate", G_TYPE_UINT, media_type->BitRate,
+ "width", G_TYPE_INT, media_type->Width,
+ "height", G_TYPE_INT, media_type->Height,
+ NULL);
break;
case TSMF_SUB_TYPE_WMA9:
- if (media_type->ExtraDataSize > 0)
- {
- gst_buf_cap_codec_data = gst_buffer_try_new_and_alloc(media_type->ExtraDataSize);
- if (gst_buf_cap_codec_data != NULL)
- {
- memcpy(GST_BUFFER_MALLOCDATA(gst_buf_cap_codec_data), media_type->ExtraData, media_type->ExtraDataSize);
- }
- else
- {
- DEBUG_WARN("tsmf_gstreamer_set_format: gst_buffer_try_new_and_alloc(%d) failed.", media_type->ExtraDataSize);
- }
- mdecoder->gst_caps = gst_caps_new_simple ("audio/x-wma",
- "wmaversion", G_TYPE_INT, 3,
- "rate", G_TYPE_INT, media_type->SamplesPerSecond.Numerator,
- "channels", G_TYPE_INT, media_type->Channels,
- "bitrate", G_TYPE_INT, media_type->BitRate,
- "depth", G_TYPE_INT, media_type->BitsPerSample,
- "width", G_TYPE_INT, media_type->BitsPerSample,
- "block_align", G_TYPE_INT, media_type->BlockAlign,
- "codec_data", GST_TYPE_BUFFER, gst_buf_cap_codec_data,
- NULL);
- }
- else
- {
- mdecoder->gst_caps = gst_caps_new_simple ("audio/x-wma",
- "wmaversion", G_TYPE_INT, 3,
- "rate", G_TYPE_INT, media_type->SamplesPerSecond.Numerator,
- "channels", G_TYPE_INT, media_type->Channels,
- "bitrate", G_TYPE_INT, media_type->BitRate,
- "depth", G_TYPE_INT, media_type->BitsPerSample,
- "width", G_TYPE_INT, media_type->BitsPerSample,
- "block_align", G_TYPE_INT, media_type->BlockAlign,
- NULL);
- }
+ mdecoder->gst_caps = gst_caps_new_simple("audio/x-wma",
+ "wmaversion", G_TYPE_INT, 3,
+ "rate", G_TYPE_INT, media_type->SamplesPerSecond.Numerator,
+ "channels", G_TYPE_INT, media_type->Channels,
+ "bitrate", G_TYPE_INT, media_type->BitRate,
+ "depth", G_TYPE_INT, media_type->BitsPerSample,
+ "width", G_TYPE_INT, media_type->BitsPerSample,
+ "block_align", G_TYPE_INT, media_type->BlockAlign,
+ NULL);
break;
case TSMF_SUB_TYPE_WMA2:
- gst_buf_cap_codec_data = gst_buffer_try_new_and_alloc(media_type->ExtraDataSize);
- if (gst_buf_cap_codec_data != NULL)
- {
- memcpy(GST_BUFFER_MALLOCDATA(gst_buf_cap_codec_data),
- media_type->ExtraData, media_type->ExtraDataSize);
- }
- else
- {
- DEBUG_WARN("tsmf_gstreamer_set_format: gst_buffer_try_new_and_alloc(%d) failed.",
- media_type->ExtraDataSize);
- }
-
- mdecoder->gst_caps = gst_caps_new_simple ("audio/x-wma",
- "wmaversion", G_TYPE_INT, 2,
- "rate", G_TYPE_INT, media_type->SamplesPerSecond.Numerator,
- "channels", G_TYPE_INT, media_type->Channels,
- "bitrate", G_TYPE_INT, media_type->BitRate,
- "depth", G_TYPE_INT, media_type->BitsPerSample,
- "width", G_TYPE_INT, media_type->BitsPerSample,
- "block_align", G_TYPE_INT, media_type->BlockAlign,
- "codec_data", GST_TYPE_BUFFER, gst_buf_cap_codec_data,
- NULL);
+ mdecoder->gst_caps = gst_caps_new_simple("audio/x-wma",
+ "wmaversion", G_TYPE_INT, 2,
+ "rate", G_TYPE_INT, media_type->SamplesPerSecond.Numerator,
+ "channels", G_TYPE_INT, media_type->Channels,
+ "bitrate", G_TYPE_INT, media_type->BitRate,
+ "depth", G_TYPE_INT, media_type->BitsPerSample,
+ "width", G_TYPE_INT, media_type->BitsPerSample,
+ "block_align", G_TYPE_INT, media_type->BlockAlign,
+ NULL);
break;
case TSMF_SUB_TYPE_MP3:
- mdecoder->gst_caps = gst_caps_new_simple ("audio/mpeg",
- "mpegversion", G_TYPE_INT, 1,
- "mpegaudioversion", G_TYPE_INT, 1,
- "layer", G_TYPE_INT, 3,
- "rate", G_TYPE_INT, media_type->SamplesPerSecond.Numerator,
- "channels", G_TYPE_INT, media_type->Channels,
- "parsed", G_TYPE_BOOLEAN, TRUE,
- NULL);
+ mdecoder->gst_caps = gst_caps_new_simple("audio/mpeg",
+ "mpegversion", G_TYPE_INT, 1,
+ "layer", G_TYPE_INT, 3,
+ "rate", G_TYPE_INT, media_type->SamplesPerSecond.Numerator,
+ "channels", G_TYPE_INT, media_type->Channels,
+ NULL);
break;
case TSMF_SUB_TYPE_WMV1:
- mdecoder->gst_caps = gst_caps_new_simple ("video/x-wmv",
- "bitrate", G_TYPE_UINT, media_type->BitRate,
- "width", G_TYPE_INT, media_type->Width,
- "height", G_TYPE_INT, media_type->Height,
- "wmvversion", G_TYPE_INT, 1,
- "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('W', 'M', 'V', '1'),
- NULL);
+ mdecoder->gst_caps = gst_caps_new_simple("video/x-wmv",
+ "bitrate", G_TYPE_UINT, media_type->BitRate,
+ "width", G_TYPE_INT, media_type->Width,
+ "height", G_TYPE_INT, media_type->Height,
+ "wmvversion", G_TYPE_INT, 1,
+ NULL);
break;
case TSMF_SUB_TYPE_WMV2:
- gst_buf_cap_codec_data = gst_buffer_try_new_and_alloc(media_type->ExtraDataSize);
- if (gst_buf_cap_codec_data != NULL)
- {
- memcpy(GST_BUFFER_MALLOCDATA(gst_buf_cap_codec_data),
- media_type->ExtraData, media_type->ExtraDataSize);
- }
- else
- {
- DEBUG_WARN("tsmf_gstreamer_set_format: gst_buffer_try_new_and_alloc(%d) failed.",
- media_type->ExtraDataSize);
- }
- mdecoder->gst_caps = gst_caps_new_simple ("video/x-wmv",
- "width", G_TYPE_INT, media_type->Width,
- "height", G_TYPE_INT, media_type->Height,
- "wmvversion", G_TYPE_INT, 2,
- "codec_data", GST_TYPE_BUFFER, gst_buf_cap_codec_data,
- "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('W', 'M', 'V', '2'),
- NULL);
+ mdecoder->gst_caps = gst_caps_new_simple("video/x-wmv",
+ "width", G_TYPE_INT, media_type->Width,
+ "height", G_TYPE_INT, media_type->Height,
+ "wmvversion", G_TYPE_INT, 2,
+ NULL);
break;
case TSMF_SUB_TYPE_WMV3:
- gst_buf_cap_codec_data = gst_buffer_try_new_and_alloc(media_type->ExtraDataSize);
- if (gst_buf_cap_codec_data != NULL)
- {
- memcpy(GST_BUFFER_MALLOCDATA(gst_buf_cap_codec_data),
- media_type->ExtraData, media_type->ExtraDataSize);
- }
- else
- {
- DEBUG_WARN("tsmf_gstreamer_set_format: gst_buffer_try_new_and_alloc(%d) failed.",
- media_type->ExtraDataSize);
- }
- mdecoder->gst_caps = gst_caps_new_simple ("video/x-wmv",
- "bitrate", G_TYPE_UINT, media_type->BitRate,
- "width", G_TYPE_INT, media_type->Width,
- "height", G_TYPE_INT, media_type->Height,
- "wmvversion", G_TYPE_INT, 3,
- "codec_data", GST_TYPE_BUFFER, gst_buf_cap_codec_data,
- "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('W', 'M', 'V', '3'),
- //"framerate", GST_TYPE_FRACTION, media_type->SamplesPerSecond.Numerator, media_type->SamplesPerSecond.Denominator,
- NULL);
+ mdecoder->gst_caps = gst_caps_new_simple("video/x-wmv",
+ "bitrate", G_TYPE_UINT, media_type->BitRate,
+ "width", G_TYPE_INT, media_type->Width,
+ "height", G_TYPE_INT, media_type->Height,
+ "wmvversion", G_TYPE_INT, 3,
+ NULL);
break;
case TSMF_SUB_TYPE_AVC1:
case TSMF_SUB_TYPE_H264:
- if (media_type->ExtraDataSize > 0)
- {
- gst_buf_cap_codec_data = gst_buffer_try_new_and_alloc(media_type->ExtraDataSize);
- if (gst_buf_cap_codec_data != NULL)
- {
- memcpy(GST_BUFFER_MALLOCDATA(gst_buf_cap_codec_data), media_type->ExtraData, media_type->ExtraDataSize);
- }
- else
- {
- DEBUG_WARN("tsmf_gstreamer_set_format: gst_buffer_try_new_and_alloc(%d) failed.", media_type->ExtraDataSize);
- }
- mdecoder->gst_caps = gst_caps_new_simple ("video/x-h264",
- "width", G_TYPE_INT, media_type->Width,
- "height", G_TYPE_INT, media_type->Height,
- "codec_data", GST_TYPE_BUFFER, gst_buf_cap_codec_data,
- //"framerate", GST_TYPE_FRACTION, media_type->SamplesPerSecond.Numerator, media_type->SamplesPerSecond.Denominator,
- NULL);
- }
- else
- {
- mdecoder->gst_caps = gst_caps_new_simple ("video/x-h264",
- "width", G_TYPE_INT, media_type->Width,
- "height", G_TYPE_INT, media_type->Height,
- //"framerate", GST_TYPE_FRACTION, media_type->SamplesPerSecond.Numerator, media_type->SamplesPerSecond.Denominator,
- NULL);
- }
+ mdecoder->gst_caps = gst_caps_new_simple("video/x-h264",
+ "width", G_TYPE_INT, media_type->Width,
+ "height", G_TYPE_INT, media_type->Height,
+ NULL);
break;
case TSMF_SUB_TYPE_AC3:
- mdecoder->gst_caps = gst_caps_new_simple ("audio/x-ac3",
- "rate", G_TYPE_INT, media_type->SamplesPerSecond.Numerator,
- "channels", G_TYPE_INT, media_type->Channels,
- NULL);
+ mdecoder->gst_caps = gst_caps_new_simple("audio/x-ac3",
+ "rate", G_TYPE_INT, media_type->SamplesPerSecond.Numerator,
+ "channels", G_TYPE_INT, media_type->Channels,
+ NULL);
break;
case TSMF_SUB_TYPE_AAC:
+
/* For AAC the pFormat is a HEAACWAVEINFO struct, and the codec data
is at the end of it. See
http://msdn.microsoft.com/en-us/library/dd757806.aspx */
@@ -584,1010 +296,472 @@ static BOOL tsmf_gstreamer_set_format(ITSMFDecoder * decoder, TS_AM_MEDIA_TYPE *
media_type->ExtraData += 12;
media_type->ExtraDataSize -= 12;
}
- gst_buf_cap_codec_data = gst_buffer_try_new_and_alloc(media_type->ExtraDataSize);
- if (gst_buf_cap_codec_data != NULL)
- {
- memcpy(GST_BUFFER_MALLOCDATA(gst_buf_cap_codec_data),
- media_type->ExtraData, media_type->ExtraDataSize);
- }
- else
- {
- DEBUG_WARN("tsmf_gstreamer_set_format: gst_buffer_try_new_and_alloc(%d) failed.",
- media_type->ExtraDataSize);
- }
- mdecoder->gst_caps = gst_caps_new_simple ("audio/mpeg",
- "rate", G_TYPE_INT, media_type->SamplesPerSecond.Numerator,
- "channels", G_TYPE_INT, media_type->Channels,
- "mpegversion", G_TYPE_INT, 4,
- "codec_data", GST_TYPE_BUFFER, gst_buf_cap_codec_data,
- NULL);
+
+ mdecoder->gst_caps = gst_caps_new_simple("audio/mpeg",
+ "rate", G_TYPE_INT, media_type->SamplesPerSecond.Numerator,
+ "channels", G_TYPE_INT, media_type->Channels,
+ "mpegversion", G_TYPE_INT, 4,
+ NULL);
break;
case TSMF_SUB_TYPE_MP1A:
- if (media_type->ExtraDataSize > 0)
- {
- gst_buf_cap_codec_data = gst_buffer_try_new_and_alloc(media_type->ExtraDataSize);
- if (gst_buf_cap_codec_data != NULL)
- {
- memcpy(GST_BUFFER_MALLOCDATA(gst_buf_cap_codec_data), media_type->ExtraData, media_type->ExtraDataSize);
- }
- else
- {
- DEBUG_WARN("tsmf_gstreamer_set_format: gst_buffer_try_new_and_alloc(%d) failed.", media_type->ExtraDataSize);
- }
- mdecoder->gst_caps = gst_caps_new_simple ("audio/mpeg",
- "mpegversion", G_TYPE_INT, 1,
- "channels", G_TYPE_INT, media_type->Channels,
- "codec_data", GST_TYPE_BUFFER, gst_buf_cap_codec_data,
- NULL);
- }
- else
- {
- mdecoder->gst_caps = gst_caps_new_simple ("audio/mpeg",
- "mpegversion", G_TYPE_INT, 1,
- "channels", G_TYPE_INT, media_type->Channels,
- NULL);
- }
+ mdecoder->gst_caps = gst_caps_new_simple("audio/mpeg",
+ "mpegversion", G_TYPE_INT, 1,
+ "channels", G_TYPE_INT, media_type->Channels,
+ NULL);
break;
case TSMF_SUB_TYPE_MP1V:
- mdecoder->gst_caps = gst_caps_new_simple ("video/mpeg",
- "mpegversion", G_TYPE_INT, 1,
- "width", G_TYPE_INT, media_type->Width,
- "height", G_TYPE_INT, media_type->Height,
- "systemstream", G_TYPE_BOOLEAN, FALSE,
- NULL);
+ mdecoder->gst_caps = gst_caps_new_simple("video/mpeg",
+ "mpegversion", G_TYPE_INT, 1,
+ "width", G_TYPE_INT, media_type->Width,
+ "height", G_TYPE_INT, media_type->Height,
+ "systemstream", G_TYPE_BOOLEAN, FALSE,
+ NULL);
break;
case TSMF_SUB_TYPE_YUY2:
- mdecoder->gst_caps = gst_caps_new_simple ("video/x-raw-yuv",
- "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('Y', 'U', 'Y', '2'),
- //"bitrate", G_TYPE_UINT, media_type->BitRate,
- "width", G_TYPE_INT, media_type->Width,
- "height", G_TYPE_INT, media_type->Height,
- NULL);
+#if GST_VERSION_MAJOR > 0
+ mdecoder->gst_caps = gst_caps_new_simple("video/x-raw",
+ "format", G_TYPE_STRING, "YUY2",
+ "width", G_TYPE_INT, media_type->Width,
+ "height", G_TYPE_INT, media_type->Height,
+ NULL);
+#else
+ mdecoder->gst_caps = gst_caps_new_simple("video/x-raw-yuv",
+ "format", G_TYPE_STRING, "YUY2",
+ "width", G_TYPE_INT, media_type->Width,
+ "height", G_TYPE_INT, media_type->Height,
+ NULL);
+#endif
break;
case TSMF_SUB_TYPE_MP2V:
- mdecoder->gst_caps = gst_caps_new_simple ("video/mpeg",
- //"bitrate", G_TYPE_UINT, media_type->BitRate,
- //"width", G_TYPE_INT, media_type->Width,
- //"height", G_TYPE_INT, media_type->Height,
- "mpegversion", G_TYPE_INT, 2,
- "systemstream", G_TYPE_BOOLEAN, FALSE,
- NULL);
+ mdecoder->gst_caps = gst_caps_new_simple("video/mpeg",
+ "mpegversion", G_TYPE_INT, 2,
+ "systemstream", G_TYPE_BOOLEAN, FALSE,
+ NULL);
break;
case TSMF_SUB_TYPE_MP2A:
- mdecoder->gst_caps = gst_caps_new_simple ("audio/mpeg",
- "mpegversion", G_TYPE_INT, 2,
- "rate", G_TYPE_INT, media_type->SamplesPerSecond.Numerator,
- "channels", G_TYPE_INT, media_type->Channels,
- NULL);
- break;
-#if 0
- case TSMF_SUB_TYPE_AC3:
+ mdecoder->gst_caps = gst_caps_new_simple("audio/mpeg",
+ "mpegversion", G_TYPE_INT, 2,
+ "rate", G_TYPE_INT, media_type->SamplesPerSecond.Numerator,
+ "channels", G_TYPE_INT, media_type->Channels,
+ NULL);
break;
-#endif
default:
- DEBUG_WARN("tsmf_gstreamer_set_format: unknown format:(%d).", media_type->SubType);
+ DEBUG_WARN("unknown format:(%d).", media_type->SubType);
return FALSE;
}
- return TRUE;
-}
-
-static void tsmf_gstreamer_pipeline_send_end_of_stream(TSMFGstreamerDecoder * mdecoder)
-{
- DEBUG_DVC("tsmf_gstreamer_pipeline_send_end_of_stream: ");
-
- if (mdecoder && mdecoder->src)
- {
- gst_app_src_end_of_stream(GST_APP_SRC(mdecoder->src));
- }
-
- return;
-}
-
-#ifdef __arm__
-/* code from TI to check whether OMX is being lock or not */
-static BOOL tsmf_gstreamer_pipeline_omx_available()
-{
- BOOL ret = TRUE;
- int shm_fd = 0;
- struct shm_info
+ if (media_type->ExtraDataSize > 0)
{
- pid_t pid;
- }shm_info;
- struct shm_info *info = NULL;
+ GstBuffer *buffer;
+ DEBUG_TSMF("Extra data available (%d)", media_type->ExtraDataSize);
+ buffer = tsmf_get_buffer_from_data(media_type->ExtraData, media_type->ExtraDataSize);
- shm_fd = shm_open ("gstomx", (O_CREAT | O_RDWR), (S_IREAD | S_IWRITE));
- if (shm_fd < 0)
- {
- DEBUG_DVC("ERROR: failed to open shm");
- goto exit;
- }
-
- /* set file size */
- ftruncate(shm_fd, sizeof(struct shm_info));
-
- if ((info = mmap(0, sizeof(struct shm_info), (PROT_READ | PROT_WRITE), MAP_SHARED, shm_fd, 0)) == MAP_FAILED)
- {
- DEBUG_DVC("ERROR: failed to map");
- goto exit;
- }
+ if (!buffer)
+ {
+ DEBUG_WARN("could not allocate GstBuffer!");
+ return FALSE;
+ }
- if (info->pid)
- {
- DEBUG_DVC ("ERROR: omxcore is in use by '%d'", info->pid);
- ret = FALSE;
- }
- else
- {
- DEBUG_DVC ("omxcore is available for use");
+ gst_caps_set_simple(mdecoder->gst_caps, "codec_data", GST_TYPE_BUFFER, buffer, NULL);
}
+ DEBUG_TSMF("%p format '%s'", mdecoder, gst_caps_to_string(mdecoder->gst_caps));
+ tsmf_platform_set_format(mdecoder);
- exit:
- if (info)
- munmap (info, sizeof(struct shm_info));
-
- if (shm_fd)
- close (shm_fd);
+ /* Create the pipeline... */
+ if (!tsmf_gstreamer_pipeline_build(mdecoder))
+ return FALSE;
- return ret;
+ return TRUE;
}
-#endif
-static void tsmf_gstreamer_clean_up(TSMFGstreamerDecoder * mdecoder)
+void tsmf_gstreamer_clean_up(TSMFGstreamerDecoder *mdecoder)
{
//Cleaning up elements
- if (!mdecoder)
+ if (!mdecoder || !mdecoder->pipe)
return;
- if (mdecoder->src)
+ if (mdecoder->pipe && GST_OBJECT_REFCOUNT_VALUE(mdecoder->pipe) > 0)
{
- gst_object_unref(mdecoder->src);
- mdecoder->src = NULL;
+ tsmf_gstreamer_pipeline_set_state(mdecoder, GST_STATE_NULL);
+ gst_object_unref(mdecoder->pipe);
}
- if (mdecoder->queue)
- {
- gst_object_unref(mdecoder->queue);
- mdecoder->queue = NULL;
- }
- if (mdecoder->decbin)
- {
- gst_object_unref(mdecoder->decbin);
- mdecoder->decbin = NULL;
- }
- if(mdecoder->outbin)
- {
- gst_object_unref(mdecoder->outbin);
- mdecoder->outbin = NULL;
- }
- if (mdecoder->outconv)
- {
- gst_object_unref(mdecoder->outconv);
- mdecoder->outconv = NULL;
- }
- if (mdecoder->outsink)
- {
- gst_object_unref(mdecoder->outsink);
- mdecoder->outsink = NULL;
- }
- if (mdecoder->aVolume)
- {
- gst_object_unref(mdecoder->aVolume);
- mdecoder->aVolume = NULL;
- }
-}
+ tsmf_window_destroy(mdecoder);
+ mdecoder->ready = FALSE;
+ mdecoder->pipe = NULL;
+ mdecoder->src = NULL;
+}
-static BOOL tsmf_gstreamer_pipeline_build(TSMFGstreamerDecoder * mdecoder)
+BOOL tsmf_gstreamer_pipeline_build(TSMFGstreamerDecoder *mdecoder)
{
+ const char *appsrc = "appsrc name=source ! decodebin name=decoder !";
+ const char *video = "autovideoconvert ! videoscale !";
+ const char *audio = "audioconvert ! audiorate ! audioresample ! volume name=audiovolume !";
+ char pipeline[1024];
+
if (!mdecoder)
return FALSE;
- GstPad *out_pad;
- mdecoder->pipe = gst_pipeline_new (NULL);
+ /* TODO: Construction of the pipeline from a string allows easy overwrite with arguments.
+ * The only fixed elements necessary are appsrc and the volume element for audio streams.
+ * The rest could easily be provided in gstreamer pipeline notation from command line. */
+ if (mdecoder->media_type == TSMF_MAJOR_TYPE_VIDEO)
+ snprintf(pipeline, sizeof(pipeline), "%s %s %s name=outsink", appsrc, video, tsmf_platform_get_video_sink());
+ else
+ snprintf(pipeline, sizeof(pipeline), "%s %s %s name=outsink", appsrc, audio, tsmf_platform_get_audio_sink());
+
+ DEBUG_TSMF("pipeline=%s", pipeline);
+ mdecoder->pipe = gst_parse_launch(pipeline, NULL);
+
if (!mdecoder->pipe)
{
- DEBUG_WARN("tsmf_gstreamer_pipeline_build: Failed to create new pipe");
+ DEBUG_WARN("Failed to create new pipe");
return FALSE;
}
- BOOL OMXavailable = FALSE;
-
-#ifdef __arm__
- OMXavailable = tsmf_gstreamer_pipeline_omx_available();
-#endif
-
- /*
- * On Atlas without this printf, we'll see Illegal instruction only with optimization level set to -O2.
- */
- const char *blank = "";
- printf("%s", blank);
-
- BOOL hwaccelflu = FALSE;
- BOOL hwaccelomx = FALSE;
+ mdecoder->src = gst_bin_get_by_name(GST_BIN(mdecoder->pipe), "source");
- switch (mdecoder->tsmf_media_type.SubType)
+ if (!mdecoder->src)
{
- case TSMF_SUB_TYPE_WMA2:
- mdecoder->decbin = gst_element_factory_make ("fluwmadec", NULL);
- if (!mdecoder->decbin)
- mdecoder->decbin = gst_element_factory_make ("ffdec_wmav2", NULL);
- DEBUG_DVC("tsmf_gstreamer_pipeline_build: WMA2");
- break;
- case TSMF_SUB_TYPE_WMA9:
- mdecoder->decbin = gst_element_factory_make ("fluwmadec", NULL);
- if (!mdecoder->decbin)
- mdecoder->decbin = gst_element_factory_make ("ffdec_wmapro", NULL);
- DEBUG_DVC("tsmf_gstreamer_pipeline_build: WMA9 - WMA PRO version 3");
- break;
- case TSMF_SUB_TYPE_MP3:
- mdecoder->decbin = gst_element_factory_make ("flump3dec", NULL);
- DEBUG_DVC("tsmf_gstreamer_pipeline_build: MP3");
- break;
- case TSMF_SUB_TYPE_MP4S:
- if (OMXavailable)
- {
- mdecoder->decbin = gst_element_factory_make ("omx_mpeg4dec", NULL);
- if (mdecoder->decbin)
- {
- hwaccelomx = TRUE;
- }
- }
- else
- mdecoder->decbin = NULL;
-
- if(!mdecoder->decbin)
- mdecoder->decbin = gst_element_factory_make ("flumpeg4vdec", NULL);
- if(!mdecoder->decbin)
- mdecoder->decbin = gst_element_factory_make ("ffdec_mpeg4", NULL);
- DEBUG_DVC("tsmf_gstreamer_pipeline_build: MP4S");
- break;
- case TSMF_SUB_TYPE_MP42:
- mdecoder->decbin = gst_element_factory_make ("ffdec_msmpeg4v2", NULL);
- DEBUG_DVC("tsmf_gstreamer_pipeline_build: MP42");
- break;
- case TSMF_SUB_TYPE_MP43:
- mdecoder->decbin = gst_element_factory_make ("ffdec_msmpeg4", NULL);
- DEBUG_DVC("tsmf_gstreamer_pipeline_build: MP43");
- break;
- case TSMF_SUB_TYPE_MP2V:
- if (OMXavailable)
- {
- mdecoder->decbin = gst_element_factory_make ("omx_mpeg2dec", NULL);
- if (mdecoder->decbin)
- {
- hwaccelomx = TRUE;
- }
- }
- else
- mdecoder->decbin = NULL;
- if (!mdecoder->decbin)
- mdecoder->decbin = gst_element_factory_make ("ffdec_mpeg2video", NULL);
-
- DEBUG_DVC("tsmf_gstreamer_pipeline_build: MPEG2 Video");
- break;
- case TSMF_SUB_TYPE_WMV1:
- mdecoder->decbin = gst_element_factory_make ("ffdec_wmv1", NULL);
- DEBUG_DVC("tsmf_gstreamer_pipeline_build: WMV1");
- break;
- case TSMF_SUB_TYPE_WMV2:
- mdecoder->decbin = gst_element_factory_make ("ffdec_wmv2", NULL);
- DEBUG_DVC("tsmf_gstreamer_pipeline_build: WMV2");
- break;
- case TSMF_SUB_TYPE_WVC1:
- case TSMF_SUB_TYPE_WMV3:
- mdecoder->decbin = gst_element_factory_make ("fluvadec", NULL);
- if (mdecoder->decbin)
- {
- hwaccelflu = TRUE;
- }
- else
- {
- if (OMXavailable)
- {
- mdecoder->decbin = gst_element_factory_make ("omx_vc1dec", NULL);
- if (mdecoder->decbin)
- hwaccelomx = TRUE;
- }
- else
- mdecoder->decbin = NULL;
- }
+ DEBUG_WARN("Failed to get appsrc");
+ return FALSE;
+ }
- if (!mdecoder->decbin)
- mdecoder->decbin = gst_element_factory_make ("fluwmvdec", NULL);
- if (!mdecoder->decbin)
- mdecoder->decbin = gst_element_factory_make ("ffdec_wmv3", NULL);
- DEBUG_DVC("tsmf_gstreamer_pipeline_build: WMV3");
- break;
- case TSMF_SUB_TYPE_AVC1:
- case TSMF_SUB_TYPE_H264:
- mdecoder->decbin = gst_element_factory_make ("fluvadec", NULL);
- if (mdecoder->decbin)
- {
- hwaccelflu = TRUE;
- }
- else
- {
- if (OMXavailable)
- {
- mdecoder->decbin = gst_element_factory_make ("omx_h264dec", NULL);
- if (mdecoder->decbin)
- hwaccelomx = TRUE;
- }
- else
- mdecoder->decbin = NULL;
- }
- if (!mdecoder->decbin)
- mdecoder->decbin = gst_element_factory_make ("fluh264dec", NULL);
+ mdecoder->outsink = gst_bin_get_by_name(GST_BIN(mdecoder->pipe), "outsink");
- if (!mdecoder->decbin)
- mdecoder->decbin = gst_element_factory_make ("ffdec_h264", NULL);
- DEBUG_DVC("tsmf_gstreamer_pipeline_build: H264");
- break;
- case TSMF_SUB_TYPE_AC3:
- mdecoder->decbin = gst_element_factory_make ("ffdec_ac3", NULL);
- //mdecoder->decbin = gst_element_factory_make ("ffdec_ac3", NULL);//no fluendo equivalent?
- DEBUG_DVC("tsmf_gstreamer_pipeline_build: AC3");
- break;
- case TSMF_SUB_TYPE_AAC:
- mdecoder->decbin = gst_element_factory_make ("fluaacdec", NULL);
- if (!mdecoder->decbin)
- mdecoder->decbin = gst_element_factory_make ("faad", NULL);
- if (!mdecoder->decbin)
- mdecoder->decbin = gst_element_factory_make ("ffdec_aac", NULL);
- DEBUG_DVC("tsmf_gstreamer_pipeline_build: AAC");
- break;
- case TSMF_SUB_TYPE_MP2A:
- mdecoder->decbin = gst_element_factory_make ("fluaacdec", NULL);
- if (!mdecoder->decbin)
- mdecoder->decbin = gst_element_factory_make ("faad", NULL);
- DEBUG_DVC("tsmf_gstreamer_pipeline_build: MP2A");
- break;
- case TSMF_SUB_TYPE_MP1A:
- mdecoder->decbin = gst_element_factory_make ("flump3dec", NULL);
- DEBUG_DVC("tsmf_gstreamer_pipeline_build: MP1A");
- break;
- case TSMF_SUB_TYPE_MP1V:
- mdecoder->decbin = gst_element_factory_make ("ffdec_mpegvideo", NULL);
- DEBUG_DVC("tsmf_gstreamer_pipeline_build: MP1V");
- break;
- default:
- DEBUG_WARN("tsmf_gstreamer_pipeline_build: Unsupported media type %d", mdecoder->tsmf_media_type.SubType);
- return FALSE;
- }
- if (!mdecoder->decbin)
+ if (!mdecoder->outsink)
{
- DEBUG_WARN("tsmf_gstreamer_pipeline_build: Failed to load decoder plugin");
+ DEBUG_WARN("Failed to get sink");
return FALSE;
}
- switch (mdecoder->media_type)
+ if (mdecoder->media_type != TSMF_MAJOR_TYPE_VIDEO)
{
- case TSMF_MAJOR_TYPE_VIDEO:
- {
- mdecoder->outbin = gst_bin_new ("videobin");
- if (hwaccelflu)
- {
- mdecoder->outconv = gst_element_factory_make ("queue", "queuetosink");
- mdecoder->outsink = gst_element_factory_make ("fluvasink", "videosink");
- }
- else if(hwaccelomx)
- {
- mdecoder->outconv = gst_element_factory_make ("queue", "queuetosink");
- mdecoder->outsink = gst_element_factory_make ("gemxvimagesink", "videosink");
- }
- else
- {
- mdecoder->outconv = gst_element_factory_make ("ffmpegcolorspace", "vconv");
- mdecoder->outsink = gst_element_factory_make ("xvimagesink", "videosink");
- }
- DEBUG_DVC("tsmf_gstreamer_pipeline_build: building Video Pipe");
+ mdecoder->volume = gst_bin_get_by_name(GST_BIN(mdecoder->pipe), "audiovolume");
- if (mdecoder->xfwin == (int *) -1)
- DEBUG_WARN("tsmf_gstreamer_entry: failed to assign pointer to the memory address - shmat()");
- else
- {
- if (!mdecoder->disp)
- mdecoder->disp = XOpenDisplay(NULL);
-
- if (!mdecoder->subwin)
- {
- mdecoder->subwin = XCreateSimpleWindow(mdecoder->disp, *mdecoder->xfwin, 0, 0, 1, 1, 0, 0, 0);
- XMapWindow(mdecoder->disp, mdecoder->subwin);
- XSync(mdecoder->disp, FALSE);
- }
- }
- mdecoder->aVolume = 0;
- break;
- }
- case TSMF_MAJOR_TYPE_AUDIO:
+ if (!mdecoder->volume)
{
- mdecoder->outbin = gst_bin_new ("audiobin");
- mdecoder->outconv = gst_element_factory_make ("audioconvert", "aconv");
- mdecoder->outsink = gst_element_factory_make ("alsasink", NULL);
- mdecoder->aVolume = gst_element_factory_make ("volume", "AudioVol");
- if (mdecoder->aVolume)
- {
- g_object_set(mdecoder->aVolume, "mute", mdecoder->gstMuted, NULL);
- g_object_set(mdecoder->aVolume, "volume", mdecoder->gstVolume, NULL);
- }
- DEBUG_DVC("tsmf_gstreamer_pipeline_build: building Audio Pipe");
- break;
+ DEBUG_WARN("Failed to get volume");
+ return FALSE;
}
- default:
- break;
- }
- if (!mdecoder->outconv)
- {
- DEBUG_WARN("tsmf_gstreamer_pipeline_build: Failed to load media converter");
- tsmf_gstreamer_clean_up(mdecoder);
- return FALSE;
- }
- if (!mdecoder->outsink)
- {
- DEBUG_WARN("tsmf_gstreamer_pipeline_build: Failed to load xvimagesink plugin");
- tsmf_gstreamer_clean_up(mdecoder);
- return FALSE;
}
- mdecoder->src = gst_element_factory_make ("appsrc", NULL);
- mdecoder->queue = gst_element_factory_make ("queue2", NULL);
- g_object_set(mdecoder->queue, "use-buffering", FALSE, NULL);
- g_object_set(mdecoder->queue, "use-rate-estimate", FALSE, NULL);
- g_object_set(mdecoder->outsink, "async", FALSE, NULL);
+ tsmf_platform_register_handler(mdecoder);
+ /* AppSrc settings */
+ GstAppSrcCallbacks callbacks =
+ {
+ tsmf_gstreamer_need_data,
+ tsmf_gstreamer_enough_data,
+ tsmf_gstreamer_seek_data
+ };
g_object_set(mdecoder->src, "format", GST_FORMAT_TIME, NULL);
- gst_app_src_set_stream_type((GstAppSrc *) mdecoder->src, GST_APP_STREAM_TYPE_STREAM);
- gst_app_src_set_max_bytes((GstAppSrc *) mdecoder->src, 4*1024*1024); /* 32 Mbits */
+ g_object_set(mdecoder->src, "is-live", TRUE, NULL);
+ g_object_set(mdecoder->src, "block", TRUE, NULL);
gst_app_src_set_caps((GstAppSrc *) mdecoder->src, mdecoder->gst_caps);
+ gst_app_src_set_callbacks((GstAppSrc *)mdecoder->src, &callbacks, mdecoder, NULL);
+ gst_app_src_set_stream_type((GstAppSrc *) mdecoder->src, GST_APP_STREAM_TYPE_SEEKABLE);
+ tsmf_window_create(mdecoder);
+ tsmf_gstreamer_pipeline_set_state(mdecoder, GST_STATE_READY);
+ tsmf_gstreamer_pipeline_set_state(mdecoder, GST_STATE_PLAYING);
+ mdecoder->pipeline_start_time_valid = 0;
+ mdecoder->shutdown = 0;
- out_pad = gst_element_get_static_pad(mdecoder->outconv, "sink");
-
- gboolean linkResult = FALSE;
- gst_bin_add(GST_BIN(mdecoder->outbin), mdecoder->outconv);
- gst_bin_add(GST_BIN(mdecoder->outbin), mdecoder->outsink);
- if (mdecoder->aVolume)
- {
- gst_bin_add(GST_BIN(mdecoder->outbin), mdecoder->aVolume);
- linkResult = gst_element_link_many(mdecoder->outconv, mdecoder->aVolume, mdecoder->outsink, NULL);
- }
- else
- {
- linkResult = gst_element_link(mdecoder->outconv, mdecoder->outsink);
- }
- if (!linkResult)
- {
- DEBUG_WARN("tsmf_gstreamer_pipeline_build: Failed to link these elements: converter->sink");
- tsmf_gstreamer_clean_up(mdecoder);
- return FALSE;
- }
-
- gst_element_add_pad(mdecoder->outbin, gst_ghost_pad_new ("sink", out_pad));
- gst_object_unref(out_pad);
-
- gst_bin_add(GST_BIN(mdecoder->pipe), mdecoder->src);
- gst_bin_add(GST_BIN(mdecoder->pipe), mdecoder->queue);
- gst_bin_add(GST_BIN(mdecoder->pipe), mdecoder->decbin);
- gst_bin_add(GST_BIN(mdecoder->pipe), mdecoder->outbin);
-
- linkResult = gst_element_link_many(mdecoder->src, mdecoder->queue, mdecoder->decbin, NULL);
- if (!linkResult)
- {
- DEBUG_WARN("tsmf_gstreamer_pipeline_build: Failed to link these elements: source->decoder");
- tsmf_gstreamer_clean_up(mdecoder);
- return FALSE;
- }
+ GST_DEBUG_BIN_TO_DOT_FILE(GST_BIN(mdecoder->pipe), GST_DEBUG_GRAPH_SHOW_ALL, get_type(mdecoder));
- mdecoder->linked = gst_element_link(mdecoder->decbin, mdecoder->outbin);
- if (!mdecoder->linked)
- {
- DEBUG_WARN("tsmf_gstreamer_pipeline_build: Failed to link these elements: decoder->output_bin");
- tsmf_gstreamer_clean_up(mdecoder);
- return FALSE;
- }
-
- if (GST_IS_X_OVERLAY (mdecoder->outsink))
- {
- //gst_x_overlay_set_window_handle (GST_X_OVERLAY (mdecoder->outsink), *mdecoder->xfwin);
- if(mdecoder->subwin)
- {
- //gdk_threads_enter();
- gst_x_overlay_set_xwindow_id (GST_X_OVERLAY (mdecoder->outsink), mdecoder->subwin);
- //gdk_threads_leave();
- }
- }
-
- g_object_set(mdecoder->outsink, "preroll-queue-len", 10, NULL);
return TRUE;
}
-static BOOL tsmf_gstreamer_decodeEx(ITSMFDecoder * decoder, const BYTE * data, UINT32 data_size, UINT32 extensions,
- UINT64 start_time, UINT64 end_time, UINT64 duration)
+static BOOL tsmf_gstreamer_decodeEx(ITSMFDecoder *decoder, const BYTE *data, UINT32 data_size, UINT32 extensions,
+ UINT64 start_time, UINT64 end_time, UINT64 duration)
{
- TSMFGstreamerDecoder * mdecoder = (TSMFGstreamerDecoder*) decoder;
+ GstBuffer *gst_buf;
+ TSMFGstreamerDecoder *mdecoder = (TSMFGstreamerDecoder *) decoder;
+ UINT64 sample_time = tsmf_gstreamer_timestamp_ms_to_gst(start_time);
+ UINT64 sample_duration = tsmf_gstreamer_timestamp_ms_to_gst(duration);
if (!mdecoder)
{
+ DEBUG_WARN("Decoder not initialized!");
return FALSE;
}
- int mutexret = pthread_mutex_lock(&mdecoder->gst_mutex);
-
- if (mutexret != 0)
- return FALSE;
+ /*
+ * This function is always called from a stream-specific thread.
+ * It should be alright to block here if necessary.
+ * We don't expect to block here often, since the pipeline should
+ * have more than enough buffering.
+ */
+ DEBUG_TSMF("%s. Start:(%llu) End:(%llu) Duration:(%llu) Last End:(%llu)",
+ get_type(mdecoder), start_time, end_time, duration,
+ mdecoder->last_sample_end_time);
- if (mdecoder->shutdown)
+ if (mdecoder->gst_caps == NULL)
{
- pthread_mutex_unlock(&mdecoder->gst_mutex);
+ DEBUG_WARN("tsmf_gstreamer_set_format not called or invalid format.");
return FALSE;
}
- GstBuffer *gst_buf;
-
- /*
- * This function is always called from a stream-specific thread.
- * It should be alright to block here if necessary.
- * We don't expect to block here often, since the pipeline should
- * have more than enough buffering.
- */
-
- if (mdecoder->media_type == TSMF_MAJOR_TYPE_VIDEO)
- {
- DEBUG_DVC("tsmf_gstreamer_decodeEx_VIDEO. Start:(%"PRIu64") End:(%"PRIu64") Duration:(%"PRIu64") Last End:(%"PRIu64")",
- start_time, end_time, duration, mdecoder->last_sample_end_time);
- }
- else
+ if (!mdecoder->src)
{
- DEBUG_DVC("tsmf_gstreamer_decodeEx_AUDIO. Start:(%"PRIu64") End:(%"PRIu64") Duration:(%"PRIu64") Last End:(%"PRIu64")",
- start_time, end_time, duration, mdecoder->last_sample_end_time);
+ DEBUG_WARN("failed to construct pipeline correctly. Unable to push buffer to source element.");
+ return FALSE;
}
- if (mdecoder->gst_caps == NULL)
+ gst_buf = tsmf_get_buffer_from_data(data, data_size);
+
+ if (gst_buf == NULL)
{
- DEBUG_WARN("tsmf_gstreamer_decodeEx: tsmf_gstreamer_set_format not called or invalid format.");
- pthread_mutex_unlock(&mdecoder->gst_mutex);
+ DEBUG_WARN("tsmf_get_buffer_from_data(%p, %d) failed.", data, data_size);
return FALSE;
}
- if (mdecoder->pipe == NULL)
+ if (mdecoder->pipeline_start_time_valid)
{
- if (!tsmf_gstreamer_pipeline_build(mdecoder))
- {
- if (mdecoder->pipe)
- {
- tsmf_gstreamer_pipeline_set_state(mdecoder, GST_STATE_NULL);
- gst_object_unref(mdecoder->pipe);
- mdecoder->pipe = NULL;
- }
- pthread_mutex_unlock(&mdecoder->gst_mutex);
- return FALSE;
- }
+ long long diff = start_time;
+ diff -= mdecoder->last_sample_end_time;
- //tsmf_gstreamer_start_eventloop_thread(mdecoder);
+ if (diff < 0)
+ diff *= -1;
- tsmf_gstreamer_pipeline_set_state(mdecoder, GST_STATE_READY);
- mdecoder->pipeline_start_time_valid = 0;
- }
- else
- {
- /*
- * this is to fix gstreamer's seeking forward/backward issue with live stream.
- * set the seeking tolerance to 1 second.
- */
- if (start_time > (mdecoder->last_sample_end_time + 10000000) || (end_time + 10000000) < mdecoder->last_sample_end_time)
+ /* The pipe is initialized, but there is a discontinuity.
+ * Seek to the start position... */
+ if (diff > 50)
{
- DEBUG_DVC("tsmf_gstreamer_decodeEx: start_time=[%"PRIu64"] > last_sample_end_time=[%"PRIu64"]", start_time, mdecoder->last_sample_end_time);
- DEBUG_DVC("tsmf_gstreamer_decodeEx: Stream seek detected - flushing element.");
- tsmf_gstreamer_pipeline_set_state(mdecoder, GST_STATE_NULL);
- gst_object_unref(mdecoder->pipe);
- mdecoder->pipe = NULL;
- if (!tsmf_gstreamer_pipeline_build(mdecoder))
- {
- if (mdecoder->pipe)
- {
- tsmf_gstreamer_pipeline_set_state(mdecoder, GST_STATE_NULL);
- gst_object_unref(mdecoder->pipe);
- mdecoder->pipe = NULL;
- }
- pthread_mutex_unlock(&mdecoder->gst_mutex);
- return FALSE;
- }
- tsmf_gstreamer_pipeline_set_state(mdecoder, GST_STATE_READY);
- mdecoder->pipeline_start_time_valid = 0;
- /*
- * This is to fix the discrepancy between audio/video start time during a seek
- */
- FILE *fout = NULL;
- if (mdecoder->media_type == TSMF_MAJOR_TYPE_VIDEO)
- fout = fopen("/tmp/tsmf_vseek.info", "wt");
- else
- fout = fopen("/tmp/tsmf_aseek.info", "wt");
-
- if (fout)
- {
- fprintf(fout, "%"PRIu64"\n", (long unsigned int) start_time);
- fclose(fout);
- }
+ DEBUG_TSMF("%s seeking to %lld", get_type(mdecoder), start_time);
- }
- }
-
- if (!mdecoder->src)
- {
- pthread_mutex_unlock(&mdecoder->gst_mutex);
- DEBUG_WARN("tsmf_gstreamer_decodeEx: failed to construct pipeline correctly. Unable to push buffer to source element.");
- return FALSE;
- }
-
- if (GST_STATE(mdecoder->pipe) != GST_STATE_PAUSED && GST_STATE(mdecoder->pipe) != GST_STATE_PLAYING)
- {
- tsmf_gstreamer_pipeline_set_state(mdecoder, GST_STATE_PAUSED);
- if (mdecoder->media_type == TSMF_MAJOR_TYPE_VIDEO)
- {
- FILE *fout = fopen("/tmp/tsmf_video.ready", "wt");
- if (fout)
- fclose(fout);
- FILE *fin = fopen("/tmp/tsmf_aseek.info", "rt");
- if (fin)
- {
- UINT64 AStartTime = 0;
- fscanf(fin, "%"PRIu64, (long unsigned int*) &AStartTime);
- fclose(fin);
- if (start_time > AStartTime)
- {
- UINT64 streamDelay = (start_time - AStartTime) / 10;
- usleep(streamDelay);
- }
- unlink("/tmp/tsmf_aseek.info");
- }
- }
- else if (mdecoder->media_type == TSMF_MAJOR_TYPE_AUDIO)
- {
- int timeout = 0;
- FILE *fin = fopen("/tmp/tsmf_video.ready", "rt");
- while (fin == NULL)
- {
- timeout++;
- usleep(1000);
- //wait up to 1.5 second
- if (timeout >= 1500)
- break;
- fin = fopen("/tmp/tsmf_video.ready", "rt");
- }
- if (fin)
+ if (!gst_element_seek(mdecoder->pipe, 1.0, GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE,
+ GST_SEEK_TYPE_SET, sample_time,
+ GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE))
{
- fclose(fin);
- unlink("/tmp/tsmf_video.ready");
- fin = NULL;
+ DEBUG_WARN("seek failed");
}
- fin = fopen("/tmp/tsmf_vseek.info", "rt");
- if (fin)
- {
- UINT64 VStartTime = 0;
- fscanf(fin, "%"PRIu64, (long unsigned int*) &VStartTime);
- fclose(fin);
- if (start_time > VStartTime)
- {
- UINT64 streamDelay = (start_time - VStartTime) / 10;
- usleep(streamDelay);
- }
- unlink("/tmp/tsmf_vseek.info");
- }
+ mdecoder->pipeline_start_time_valid = 0;
}
}
-
- gst_buf = gst_buffer_try_new_and_alloc(data_size);
- if (gst_buf == NULL)
+ else
{
- pthread_mutex_unlock(&mdecoder->gst_mutex);
- DEBUG_WARN("tsmf_gstreamer_decodeEx: gst_buffer_try_new_and_alloc(%d) failed.", data_size);
- return FALSE;
+ DEBUG_TSMF("%s start time %llu", get_type(mdecoder), sample_time);
+ mdecoder->pipeline_start_time_valid = 1;
}
- gst_buffer_set_caps(gst_buf, mdecoder->gst_caps);
- memcpy(GST_BUFFER_MALLOCDATA(gst_buf), data, data_size);
- GST_BUFFER_TIMESTAMP(gst_buf) = tsmf_gstreamer_timestamp_ms_to_gst(start_time);
- GST_BUFFER_DURATION(gst_buf) = tsmf_gstreamer_timestamp_ms_to_gst(duration);
+#if GST_VERSION_MAJOR > 0
+ GST_BUFFER_PTS(gst_buf) = sample_time;
+#else
+ GST_BUFFER_TIMESTAMP(gst_buf) = sample_time;
+#endif
+ GST_BUFFER_DURATION(gst_buf) = sample_duration;
gst_app_src_push_buffer(GST_APP_SRC(mdecoder->src), gst_buf);
+ if (mdecoder->ack_cb)
+ mdecoder->ack_cb(mdecoder->stream, TRUE);
+
mdecoder->last_sample_end_time = end_time;
-
- if (!mdecoder->pipeline_start_time_valid)
- {
- gst_element_set_base_time(mdecoder->pipe, tsmf_gstreamer_timestamp_ms_to_gst(start_time));
- gst_element_set_start_time(mdecoder->pipe, tsmf_gstreamer_timestamp_ms_to_gst(start_time));
- mdecoder->pipeline_start_time_valid = 1;
- }
- if(GST_STATE(mdecoder->pipe) != GST_STATE_PLAYING)
+ if (GST_STATE(mdecoder->pipe) != GST_STATE_PLAYING)
{
- if (!mdecoder->paused)
- {
- if (mdecoder->subwin)
- {
- XMapWindow(mdecoder->disp, mdecoder->subwin);
- XSync(mdecoder->disp, FALSE);
- }
+ DEBUG_TSMF("%s: state=%s", get_type(mdecoder), gst_element_state_get_name(GST_STATE(mdecoder->pipe)));
+
+ if (!mdecoder->paused && !mdecoder->shutdown && mdecoder->ready)
tsmf_gstreamer_pipeline_set_state(mdecoder, GST_STATE_PLAYING);
- }
}
- pthread_mutex_unlock(&mdecoder->gst_mutex);
+
return TRUE;
}
-static void tsmf_gstreamer_change_volume(ITSMFDecoder * decoder, UINT32 newVolume, UINT32 muted)
+static void tsmf_gstreamer_change_volume(ITSMFDecoder *decoder, UINT32 newVolume, UINT32 muted)
{
- TSMFGstreamerDecoder * mdecoder = (TSMFGstreamerDecoder *) decoder;
- if (!mdecoder)
- return;
+ TSMFGstreamerDecoder *mdecoder = (TSMFGstreamerDecoder *) decoder;
- if (mdecoder->shutdown)
+ if (!mdecoder || !mdecoder->pipe)
return;
if (mdecoder->media_type == TSMF_MAJOR_TYPE_VIDEO)
return;
mdecoder->gstMuted = (BOOL) muted;
- DEBUG_DVC("tsmf_gstreamer_change_volume: mute=[%d]", mdecoder->gstMuted);
+ DEBUG_TSMF("mute=[%d]", mdecoder->gstMuted);
mdecoder->gstVolume = (double) newVolume / (double) 10000;
- DEBUG_DVC("tsmf_gstreamer_change_volume: gst_new_vol=[%f]", mdecoder->gstVolume);
+ DEBUG_TSMF("gst_new_vol=[%f]", mdecoder->gstVolume);
- if (!mdecoder->aVolume)
+ if (!mdecoder->volume)
return;
- if (!G_IS_OBJECT(mdecoder->aVolume))
+ if (!G_IS_OBJECT(mdecoder->volume))
return;
- g_object_set(mdecoder->aVolume, "mute", mdecoder->gstMuted, NULL);
- g_object_set(mdecoder->aVolume, "volume", mdecoder->gstVolume, NULL);
+ g_object_set(mdecoder->volume, "mute", mdecoder->gstMuted, NULL);
+ g_object_set(mdecoder->volume, "volume", mdecoder->gstVolume, NULL);
}
-static void tsmf_gstreamer_control(ITSMFDecoder * decoder, ITSMFControlMsg control_msg, UINT32 *arg)
+static void tsmf_gstreamer_control(ITSMFDecoder *decoder, ITSMFControlMsg control_msg, UINT32 *arg)
{
- TSMFGstreamerDecoder * mdecoder = (TSMFGstreamerDecoder *) decoder;
+ TSMFGstreamerDecoder *mdecoder = (TSMFGstreamerDecoder *) decoder;
+
if (!mdecoder)
return;
- if (control_msg == Control_Pause)
+ if (control_msg == Control_Pause)
{
- DEBUG_DVC("tsmf_gstreamer_control: Control_Pause");
- tsmf_gstreamer_pipeline_set_state(mdecoder, GST_STATE_PAUSED);
- mdecoder->paused = TRUE;
+ DEBUG_TSMF("Control_Pause %s", get_type(mdecoder));
- if (mdecoder->subwin)
+ if (mdecoder->paused)
{
- XUnmapWindow(mdecoder->disp, mdecoder->subwin);
- XSync(mdecoder->disp, FALSE);
+ DEBUG_WARN("%s: Ignoring control PAUSE, already received!", get_type(mdecoder));
+ return;
}
+
+ tsmf_gstreamer_pipeline_set_state(mdecoder, GST_STATE_PAUSED);
+ mdecoder->paused = TRUE;
+
+ if (mdecoder->media_type == TSMF_MAJOR_TYPE_VIDEO)
+ tsmf_window_pause(mdecoder);
}
- else if (control_msg == Control_Restart)
+ else if (control_msg == Control_Resume)
{
- DEBUG_DVC("tsmf_gstreamer_control: Control_Restart");
- mdecoder->paused = FALSE;
- if (mdecoder->subwin)
+ DEBUG_TSMF("Control_Resume %s", get_type(mdecoder));
+
+ if (!mdecoder->paused && !mdecoder->shutdown)
{
- XMapWindow(mdecoder->disp, mdecoder->subwin);
- XSync(mdecoder->disp, FALSE);
+ DEBUG_WARN("%s: Ignoring control RESUME, already received!", get_type(mdecoder));
+ return;
}
- if (mdecoder->pipeline_start_time_valid)
- tsmf_gstreamer_pipeline_set_state(mdecoder, GST_STATE_PLAYING);
+
+ mdecoder->paused = FALSE;
+ mdecoder->shutdown = FALSE;
+
+ if (mdecoder->media_type == TSMF_MAJOR_TYPE_VIDEO)
+ tsmf_window_resume(mdecoder);
+
+ tsmf_gstreamer_pipeline_set_state(mdecoder, GST_STATE_PLAYING);
}
- else if (control_msg == Control_Flush)
+ else if (control_msg == Control_Stop)
{
- DEBUG_DVC("tsmf_gstreamer_control: Control_Flush");
- /* Reset stamps, flush buffers, etc */
- if (mdecoder->pipe)
- {
- tsmf_gstreamer_pipeline_set_state(mdecoder, GST_STATE_NULL);
- gst_object_unref(mdecoder->pipe);
- mdecoder->pipe = NULL;
- }
- mdecoder->pipeline_start_time_valid = 0;
- mdecoder->paused = FALSE;
-
- if (mdecoder->subwin)
+ DEBUG_TSMF("Control_Stop %s", get_type(mdecoder));
+
+ if (mdecoder->shutdown)
{
- XUnmapWindow(mdecoder->disp, mdecoder->subwin);
- XSync(mdecoder->disp, FALSE);
+ DEBUG_WARN("%s: Ignoring control STOP, already received!", get_type(mdecoder));
+ return;
}
+
+ mdecoder->shutdown = TRUE;
+ /* Reset stamps, flush buffers, etc */
+ tsmf_gstreamer_pipeline_set_state(mdecoder, GST_STATE_PAUSED);
+
+ if (mdecoder->media_type == TSMF_MAJOR_TYPE_VIDEO)
+ tsmf_window_pause(mdecoder);
+
+ gst_app_src_end_of_stream((GstAppSrc *)mdecoder->src);
}
- else if (control_msg == Control_EndOfStream)
- {
- mdecoder->paused = FALSE;
- DEBUG_DVC("tsmf_gstreamer_control: Control_EndOfStream");
- /*
- * The EOS may take some time to flow through the pipeline
- * If the server sees the client "End of Stream Processed"
- * notification too soon, it may shut down the stream
- * and clip the end of files.
- * If that's the case, then we'll need to change the TSMF layer
- * to send the "End of Stream Processed" only after the stream
- * is truly EOS.
- * (It's unlikely we can simply "wait" here for it to happen
- * since we don't want to hold up acks, etc.)
- */
- tsmf_gstreamer_pipeline_send_end_of_stream(mdecoder);
- }
+ else
+ DEBUG_WARN("Unknown control message %08x", control_msg);
}
-static guint tsmf_gstreamer_buffer_level(ITSMFDecoder * decoder)
+static BOOL tsmf_gstreamer_buffer_filled(ITSMFDecoder *decoder)
{
- TSMFGstreamerDecoder * mdecoder = (TSMFGstreamerDecoder *) decoder;
- DEBUG_DVC("tsmf_gstreamer_buffer_level\n");
+ TSMFGstreamerDecoder *mdecoder = (TSMFGstreamerDecoder *) decoder;
+ DEBUG_TSMF("");
if (!mdecoder)
- return 0;
-
- if (mdecoder->shutdown)
- return 0;
-
- if (!G_IS_OBJECT(mdecoder->queue))
- return 0;
+ return FALSE;
+ guint buff_max = 0;
guint clbuff = 0;
- g_object_get(mdecoder->queue, "current-level-buffers", &clbuff, NULL);
- return clbuff;
+ DEBUG_TSMF("%s buffer fill %u/%u", get_type(mdecoder), clbuff, buff_max);
+ return clbuff >= buff_max ? TRUE : FALSE;
}
-static void tsmf_gstreamer_free(ITSMFDecoder * decoder)
+static void tsmf_gstreamer_free(ITSMFDecoder *decoder)
{
- TSMFGstreamerDecoder * mdecoder = (TSMFGstreamerDecoder *) decoder;
- DEBUG_DVC("tsmf_gstreamer_free\n");
+ TSMFGstreamerDecoder *mdecoder = (TSMFGstreamerDecoder *) decoder;
+ DEBUG_TSMF("%s", get_type(mdecoder));
if (mdecoder)
{
- pthread_mutex_lock(&mdecoder->gst_mutex);
mdecoder->shutdown = 1;
- if (mdecoder->pipe)
- {
- tsmf_gstreamer_pipeline_set_state(mdecoder, GST_STATE_NULL);
- gst_object_unref(mdecoder->pipe);
- mdecoder->pipe = NULL;
- }
- tsmf_gstreamer_stop_eventloop_thread(mdecoder);
+ tsmf_gstreamer_clean_up(mdecoder);
+
if (mdecoder->gst_caps)
gst_caps_unref(mdecoder->gst_caps);
- if (mdecoder->subwin)
- {
- DEBUG_DVC("destroy subwindow\n");
- XDestroyWindow(mdecoder->disp, mdecoder->subwin);
- XSync(mdecoder->disp, FALSE);
- }
-
- if (mdecoder->disp)
- XCloseDisplay(mdecoder->disp);
-
- unlink("/tmp/tsmf_aseek.info");
- unlink("/tmp/tsmf_vseek.info");
- unlink("/tmp/tsmf_video.ready");
-
- pthread_mutex_unlock(&mdecoder->gst_mutex);
+ tsmf_platform_free(mdecoder);
+ memset(mdecoder, 0, sizeof(TSMFGstreamerDecoder));
free(mdecoder);
- mdecoder = 0;
+ mdecoder = NULL;
}
}
-static UINT64 tsmf_gstreamer_get_running_time(ITSMFDecoder * decoder)
+static UINT64 tsmf_gstreamer_get_running_time(ITSMFDecoder *decoder)
{
TSMFGstreamerDecoder *mdecoder = (TSMFGstreamerDecoder *) decoder;
+
if (!mdecoder)
return 0;
+
if (!mdecoder->outsink)
return mdecoder->last_sample_end_time;
- if(GST_STATE(mdecoder->pipe) != GST_STATE_PLAYING)
+ if (GST_STATE(mdecoder->pipe) != GST_STATE_PLAYING)
return 0;
GstFormat fmt = GST_FORMAT_TIME;
gint64 pos = 0;
- gst_element_query_position (mdecoder->outsink, &fmt, &pos);
- DEBUG_DVC("tsmf_gstreamer_current_pos=[%"PRIu64"]", pos);
+#if GST_VERSION_MAJOR > 0
+ gst_element_query_position(mdecoder->outsink, fmt, &pos);
+#else
+ gst_element_query_position(mdecoder->outsink, &fmt, &pos);
+#endif
return pos/100;
}
-static void tsmf_gstreamer_update_rendering_area(ITSMFDecoder * decoder, int newX, int newY, int newWidth, int newHeight, int numRectangles, RDP_RECT *rectangles)
+static void tsmf_gstreamer_update_rendering_area(ITSMFDecoder *decoder,
+ int newX, int newY, int newWidth, int newHeight, int numRectangles,
+ RDP_RECT *rectangles)
{
- DEBUG_DVC("tsmf_gstreamer_update_rendering_area");
TSMFGstreamerDecoder *mdecoder = (TSMFGstreamerDecoder *) decoder;
- if (!mdecoder)
- return;
-
- if (mdecoder->shutdown)
- return;
-
- if (GST_IS_X_OVERLAY (mdecoder->outsink))
- {
- if (!mdecoder->disp)
- mdecoder->disp = XOpenDisplay(NULL);
+ DEBUG_TSMF("x=%d, y=%d, w=%d, h=%d, rect=%d", newX, newY, newWidth,
+ newHeight, numRectangles);
- //multi-mon test
- int anewX = newX;
- int anewY = newY;
- if (!mdecoder->offsetObtained)
- {
- XSync(mdecoder->disp, FALSE);
- RROutput primary_output;
- XRRScreenResources *res = 0;
- int screen = 0;
- res = XRRGetScreenResourcesCurrent(mdecoder->disp, RootWindow(mdecoder->disp, screen));
- if (res)
- {
- DEBUG_DVC("number of output:%d", res->ncrtc);
- primary_output = XRRGetOutputPrimary(mdecoder->disp, DefaultRootWindow(mdecoder->disp));
- DEBUG_DVC("primary_output:%d", (int)primary_output);
- int i = 0;
- for (i = 0; i < res->ncrtc; i++)
- {
- XRRCrtcInfo *info = XRRGetCrtcInfo(mdecoder->disp, res, res->crtcs[i]);
- if (info)
- {
- if (info->noutput > 0)
- {
- if (info->outputs[0] == primary_output || i == 0)
- {
- mdecoder->xOffset = info->x;
- mdecoder->yOffset = info->y;
- }
- DEBUG_DVC("output %d ID: %lu (x,y): (%d,%d) (w,h): (%d,%d) primary: %d", i, info->outputs[0], info->x, info->y, info->width, info->height, (info->outputs[0] == primary_output));
- }
- XRRFreeCrtcInfo(info);
- }
- }
- }
- mdecoder->offsetObtained = TRUE;
- }
- anewX += mdecoder->xOffset;
- anewY += mdecoder->yOffset;
-
- XSync(mdecoder->disp, FALSE);
- //end of multi-mon test
-
- if(mdecoder->subwin)
- {
- XMoveWindow(mdecoder->disp, mdecoder->subwin, anewX, anewY);
- if(newWidth > 0 && newHeight > 0) {
- XResizeWindow(mdecoder->disp, mdecoder->subwin, newWidth, newHeight);
- } else {
- XResizeWindow(mdecoder->disp, mdecoder->subwin, 1, 1);
- }
+ if (mdecoder->media_type == TSMF_MAJOR_TYPE_VIDEO)
+ tsmf_window_resize(mdecoder, newX, newY, newWidth, newHeight,
+ numRectangles, rectangles);
+}
- XSync(mdecoder->disp, FALSE);
- XShapeCombineRectangles (mdecoder->disp, mdecoder->subwin, ShapeBounding, 0, 0,(XRectangle*) rectangles, numRectangles, ShapeSet, Unsorted);
- XSync(mdecoder->disp, FALSE);
- //Sending Expose Event so freeRDP can do a redraw.
- XExposeEvent xpose;
- xpose.type = Expose;
- xpose.display = mdecoder->disp;
- xpose.window = *mdecoder->xfwin;
- xpose.x = 0;
- xpose.y = 0;
- XSendEvent(mdecoder->disp, *mdecoder->xfwin, TRUE, ExposureMask, (XEvent *)&xpose);
- XSync(mdecoder->disp, FALSE);
- }
- gst_x_overlay_expose (GST_X_OVERLAY (mdecoder->outsink));
- }
+BOOL tsmf_gstreamer_ack(ITSMFDecoder *decoder, BOOL (*cb)(void *, BOOL), void *stream)
+{
+ TSMFGstreamerDecoder *mdecoder = (TSMFGstreamerDecoder *) decoder;
+ DEBUG_TSMF("");
+ mdecoder->ack_cb = cb;
+ mdecoder->stream = stream;
+ return TRUE;
}
-static int initialized = 0;
+BOOL tsmf_gstreamer_sync(ITSMFDecoder *decoder, void (*cb)(void *), void *stream)
+{
+ TSMFGstreamerDecoder *mdecoder = (TSMFGstreamerDecoder *) decoder;
+ DEBUG_TSMF("");
+ mdecoder->sync_cb = NULL;
+ mdecoder->stream = stream;
+ return TRUE;
+}
#ifdef STATIC_CHANNELS
#define freerdp_tsmf_client_decoder_subsystem_entry gstreamer_freerdp_tsmf_client_decoder_subsystem_entry
#endif
-ITSMFDecoder* freerdp_tsmf_client_decoder_subsystem_entry(void)
+ITSMFDecoder *freerdp_tsmf_client_decoder_subsystem_entry(void)
{
- TSMFGstreamerDecoder* decoder;
+ TSMFGstreamerDecoder *decoder;
- if (!initialized)
+ if (!gst_is_initialized())
{
- gst_init(0, 0);
- initialized = 1;
+ gst_init(NULL, NULL);
}
decoder = malloc(sizeof(TSMFGstreamerDecoder));
memset(decoder, 0, sizeof(TSMFGstreamerDecoder));
-
decoder->iface.SetFormat = tsmf_gstreamer_set_format;
decoder->iface.Decode = NULL;
decoder->iface.GetDecodedData = NULL;
@@ -1599,28 +773,13 @@ ITSMFDecoder* freerdp_tsmf_client_decoder_subsystem_entry(void)
decoder->iface.Control = tsmf_gstreamer_control;
decoder->iface.DecodeEx = tsmf_gstreamer_decodeEx;
decoder->iface.ChangeVolume = tsmf_gstreamer_change_volume;
- decoder->iface.BufferLevel = tsmf_gstreamer_buffer_level;
+ decoder->iface.BufferFilled = tsmf_gstreamer_buffer_filled;
+ decoder->iface.SetAckFunc = tsmf_gstreamer_ack;
+ decoder->iface.SetSyncFunc = tsmf_gstreamer_sync;
decoder->paused = FALSE;
- decoder->subwin = 0;
- decoder->xOffset = 0;
- decoder->yOffset = 0;
- decoder->offsetObtained = FALSE;
decoder->gstVolume = 0.5;
decoder->gstMuted = FALSE;
decoder->state = GST_STATE_VOID_PENDING; /* No real state yet */
- pthread_mutex_init(&decoder->gst_mutex, NULL);
-
- int shmid = shmget(SHARED_MEM_KEY, sizeof(int), 0666);
- if (shmid < 0)
- {
- DEBUG_WARN("tsmf_gstreamer_entry: failed to get access to shared memory - shmget()");
- }
- else
- {
- decoder->xfwin = shmat(shmid, NULL, 0);
- }
-
- XInitThreads();
-
+ tsmf_platform_create(decoder);
return (ITSMFDecoder *) decoder;
}
diff --git a/channels/tsmf/client/gstreamer/tsmf_platform.h b/channels/tsmf/client/gstreamer/tsmf_platform.h
new file mode 100644
index 000000000..32484236e
--- /dev/null
+++ b/channels/tsmf/client/gstreamer/tsmf_platform.h
@@ -0,0 +1,83 @@
+/*
+ * FreeRDP: A Remote Desktop Protocol Implementation
+ * Video Redirection Virtual Channel - GStreamer Decoder
+ * platform specific functions
+ *
+ * (C) Copyright 2014 Thincast Technologies GmbH
+ * (C) Copyright 2014 Armin Novak <armin.novak@thincast.com>
+ *
+ * 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.
+*/
+
+#ifndef _TSMF_PLATFORM_H_
+#define _TSMF_PLATFORM_H_
+
+#include <gst/gst.h>
+#include <tsmf_decoder.h>
+
+typedef struct _TSMFGstreamerDecoder
+{
+ ITSMFDecoder iface;
+
+ int media_type; /* TSMF_MAJOR_TYPE_AUDIO or TSMF_MAJOR_TYPE_VIDEO */
+
+ gint64 duration;
+
+ GstState state;
+ GstCaps *gst_caps;
+
+ GstElement *pipe;
+ GstElement *src;
+ GstElement *outsink;
+ GstElement *volume;
+
+ BOOL ready;
+ BOOL paused;
+ UINT64 last_sample_end_time;
+
+ double gstVolume;
+ BOOL gstMuted;
+
+ int pipeline_start_time_valid; /* We've set the start time and have not reset the pipeline */
+ int shutdown; /* The decoder stream is shutting down */
+
+ void *platform;
+
+ BOOL (*ack_cb)(void *,BOOL);
+ void (*sync_cb)(void *);
+ void *stream;
+
+} TSMFGstreamerDecoder;
+
+const char *get_type(TSMFGstreamerDecoder *mdecoder);
+
+const char *tsmf_platform_get_video_sink(void);
+const char *tsmf_platform_get_audio_sink(void);
+
+int tsmf_platform_create(TSMFGstreamerDecoder *decoder);
+int tsmf_platform_set_format(TSMFGstreamerDecoder *decoder);
+int tsmf_platform_register_handler(TSMFGstreamerDecoder *decoder);
+int tsmf_platform_free(TSMFGstreamerDecoder *decoder);
+
+int tsmf_window_create(TSMFGstreamerDecoder *decoder);
+int tsmf_window_resize(TSMFGstreamerDecoder *decoder, int x, int y,
+ int width, int height, int nr_rect, RDP_RECT *visible);
+int tsmf_window_destroy(TSMFGstreamerDecoder *decoder);
+
+int tsmf_window_pause(TSMFGstreamerDecoder *decoder);
+int tsmf_window_resume(TSMFGstreamerDecoder *decoder);
+
+BOOL tsmf_gstreamer_add_pad(TSMFGstreamerDecoder *mdecoder);
+void tsmf_gstreamer_remove_pad(TSMFGstreamerDecoder *mdecoder);
+
+#endif
diff --git a/channels/tsmf/client/pulse/tsmf_pulse.c b/channels/tsmf/client/pulse/tsmf_pulse.c
index 4524809d4..8b476eb23 100644
--- a/channels/tsmf/client/pulse/tsmf_pulse.c
+++ b/channels/tsmf/client/pulse/tsmf_pulse.c
@@ -37,75 +37,70 @@ typedef struct _TSMFPulseAudioDevice
ITSMFAudioDevice iface;
char device[32];
- pa_threaded_mainloop* mainloop;
- pa_context* context;
+ pa_threaded_mainloop *mainloop;
+ pa_context *context;
pa_sample_spec sample_spec;
- pa_stream* stream;
+ pa_stream *stream;
} TSMFPulseAudioDevice;
-static void tsmf_pulse_context_state_callback(pa_context* context, void* userdata)
+static void tsmf_pulse_context_state_callback(pa_context *context, void *userdata)
{
- TSMFPulseAudioDevice* pulse = (TSMFPulseAudioDevice*) userdata;
+ TSMFPulseAudioDevice *pulse = (TSMFPulseAudioDevice *) userdata;
pa_context_state_t state;
-
state = pa_context_get_state(context);
- switch (state)
+ switch(state)
{
case PA_CONTEXT_READY:
- DEBUG_DVC("PA_CONTEXT_READY");
+ DEBUG_TSMF("PA_CONTEXT_READY");
pa_threaded_mainloop_signal(pulse->mainloop, 0);
break;
-
case PA_CONTEXT_FAILED:
case PA_CONTEXT_TERMINATED:
- DEBUG_DVC("state %d", (int)state);
+ DEBUG_TSMF("state %d", (int)state);
pa_threaded_mainloop_signal(pulse->mainloop, 0);
break;
-
default:
- DEBUG_DVC("state %d", (int)state);
+ DEBUG_TSMF("state %d", (int)state);
break;
}
}
-static BOOL tsmf_pulse_connect(TSMFPulseAudioDevice* pulse)
+static BOOL tsmf_pulse_connect(TSMFPulseAudioDevice *pulse)
{
pa_context_state_t state;
-
- if (!pulse->context)
+ if(!pulse->context)
return FALSE;
-
- if (pa_context_connect(pulse->context, NULL, 0, NULL))
+ if(pa_context_connect(pulse->context, NULL, 0, NULL))
{
DEBUG_WARN("pa_context_connect failed (%d)",
- pa_context_errno(pulse->context));
+ pa_context_errno(pulse->context));
return FALSE;
}
pa_threaded_mainloop_lock(pulse->mainloop);
- if (pa_threaded_mainloop_start(pulse->mainloop) < 0)
+ if(pa_threaded_mainloop_start(pulse->mainloop) < 0)
{
pa_threaded_mainloop_unlock(pulse->mainloop);
DEBUG_WARN("pa_threaded_mainloop_start failed (%d)",
- pa_context_errno(pulse->context));
+ pa_context_errno(pulse->context));
return FALSE;
}
- for (;;)
+ for(;;)
{
state = pa_context_get_state(pulse->context);
- if (state == PA_CONTEXT_READY)
+ if(state == PA_CONTEXT_READY)
break;
- if (!PA_CONTEXT_IS_GOOD(state))
+ if(!PA_CONTEXT_IS_GOOD(state))
{
- DEBUG_DVC("bad context state (%d)",
- pa_context_errno(pulse->context));
+ DEBUG_TSMF("bad context state (%d)",
+ pa_context_errno(pulse->context));
break;
}
pa_threaded_mainloop_wait(pulse->mainloop);
}
pa_threaded_mainloop_unlock(pulse->mainloop);
- if (state == PA_CONTEXT_READY)
+ if(state == PA_CONTEXT_READY)
{
- DEBUG_DVC("connected");
+ DEBUG_TSMF("connected");
return TRUE;
}
else
@@ -115,166 +110,150 @@ static BOOL tsmf_pulse_connect(TSMFPulseAudioDevice* pulse)
}
}
-static BOOL tsmf_pulse_open(ITSMFAudioDevice* audio, const char* device)
+static BOOL tsmf_pulse_open(ITSMFAudioDevice *audio, const char *device)
{
- TSMFPulseAudioDevice* pulse = (TSMFPulseAudioDevice*) audio;
-
- if (device)
+ TSMFPulseAudioDevice *pulse = (TSMFPulseAudioDevice *) audio;
+ if(device)
{
strcpy(pulse->device, device);
}
-
pulse->mainloop = pa_threaded_mainloop_new();
- if (!pulse->mainloop)
+ if(!pulse->mainloop)
{
DEBUG_WARN("pa_threaded_mainloop_new failed");
return FALSE;
}
pulse->context = pa_context_new(pa_threaded_mainloop_get_api(pulse->mainloop), "freerdp");
- if (!pulse->context)
+ if(!pulse->context)
{
DEBUG_WARN("pa_context_new failed");
return FALSE;
}
pa_context_set_state_callback(pulse->context, tsmf_pulse_context_state_callback, pulse);
- if (tsmf_pulse_connect(pulse))
+ if(tsmf_pulse_connect(pulse))
{
DEBUG_WARN("tsmf_pulse_connect failed");
return FALSE;
}
-
- DEBUG_DVC("open device %s", pulse->device);
+ DEBUG_TSMF("open device %s", pulse->device);
return TRUE;
}
-static void tsmf_pulse_stream_success_callback(pa_stream* stream, int success, void* userdata)
+static void tsmf_pulse_stream_success_callback(pa_stream *stream, int success, void *userdata)
{
- TSMFPulseAudioDevice* pulse = (TSMFPulseAudioDevice*) userdata;
-
+ TSMFPulseAudioDevice *pulse = (TSMFPulseAudioDevice *) userdata;
pa_threaded_mainloop_signal(pulse->mainloop, 0);
}
-static void tsmf_pulse_wait_for_operation(TSMFPulseAudioDevice* pulse, pa_operation* operation)
+static void tsmf_pulse_wait_for_operation(TSMFPulseAudioDevice *pulse, pa_operation *operation)
{
- if (operation == NULL)
+ if(operation == NULL)
return;
- while (pa_operation_get_state(operation) == PA_OPERATION_RUNNING)
+ while(pa_operation_get_state(operation) == PA_OPERATION_RUNNING)
{
pa_threaded_mainloop_wait(pulse->mainloop);
}
pa_operation_unref(operation);
}
-static void tsmf_pulse_stream_state_callback(pa_stream* stream, void* userdata)
+static void tsmf_pulse_stream_state_callback(pa_stream *stream, void *userdata)
{
- TSMFPulseAudioDevice* pulse = (TSMFPulseAudioDevice*) userdata;
+ TSMFPulseAudioDevice *pulse = (TSMFPulseAudioDevice *) userdata;
pa_stream_state_t state;
-
state = pa_stream_get_state(stream);
- switch (state)
+ switch(state)
{
case PA_STREAM_READY:
- DEBUG_DVC("PA_STREAM_READY");
- pa_threaded_mainloop_signal (pulse->mainloop, 0);
+ DEBUG_TSMF("PA_STREAM_READY");
+ pa_threaded_mainloop_signal(pulse->mainloop, 0);
break;
-
case PA_STREAM_FAILED:
case PA_STREAM_TERMINATED:
- DEBUG_DVC("state %d", (int)state);
- pa_threaded_mainloop_signal (pulse->mainloop, 0);
+ DEBUG_TSMF("state %d", (int)state);
+ pa_threaded_mainloop_signal(pulse->mainloop, 0);
break;
-
default:
- DEBUG_DVC("state %d", (int)state);
+ DEBUG_TSMF("state %d", (int)state);
break;
}
}
-static void tsmf_pulse_stream_request_callback(pa_stream* stream, size_t length, void* userdata)
+static void tsmf_pulse_stream_request_callback(pa_stream *stream, size_t length, void *userdata)
{
- TSMFPulseAudioDevice* pulse = (TSMFPulseAudioDevice*) userdata;
-
- DEBUG_DVC("%d", (int) length);
-
+ TSMFPulseAudioDevice *pulse = (TSMFPulseAudioDevice *) userdata;
+ DEBUG_TSMF("%d", (int) length);
pa_threaded_mainloop_signal(pulse->mainloop, 0);
}
-static BOOL tsmf_pulse_close_stream(TSMFPulseAudioDevice* pulse)
+static BOOL tsmf_pulse_close_stream(TSMFPulseAudioDevice *pulse)
{
- if (!pulse->context || !pulse->stream)
+ if(!pulse->context || !pulse->stream)
return FALSE;
-
- DEBUG_DVC("");
-
+ DEBUG_TSMF("");
pa_threaded_mainloop_lock(pulse->mainloop);
pa_stream_set_write_callback(pulse->stream, NULL, NULL);
tsmf_pulse_wait_for_operation(pulse,
- pa_stream_drain(pulse->stream, tsmf_pulse_stream_success_callback, pulse));
+ pa_stream_drain(pulse->stream, tsmf_pulse_stream_success_callback, pulse));
pa_stream_disconnect(pulse->stream);
pa_stream_unref(pulse->stream);
pulse->stream = NULL;
pa_threaded_mainloop_unlock(pulse->mainloop);
-
return TRUE;
}
-static BOOL tsmf_pulse_open_stream(TSMFPulseAudioDevice* pulse)
+static BOOL tsmf_pulse_open_stream(TSMFPulseAudioDevice *pulse)
{
pa_stream_state_t state;
pa_buffer_attr buffer_attr = { 0 };
-
- if (!pulse->context)
+ if(!pulse->context)
return FALSE;
-
- DEBUG_DVC("");
-
+ DEBUG_TSMF("");
pa_threaded_mainloop_lock(pulse->mainloop);
pulse->stream = pa_stream_new(pulse->context, "freerdp",
- &pulse->sample_spec, NULL);
- if (!pulse->stream)
+ &pulse->sample_spec, NULL);
+ if(!pulse->stream)
{
pa_threaded_mainloop_unlock(pulse->mainloop);
DEBUG_WARN("pa_stream_new failed (%d)",
- pa_context_errno(pulse->context));
+ pa_context_errno(pulse->context));
return FALSE;
}
pa_stream_set_state_callback(pulse->stream,
- tsmf_pulse_stream_state_callback, pulse);
+ tsmf_pulse_stream_state_callback, pulse);
pa_stream_set_write_callback(pulse->stream,
- tsmf_pulse_stream_request_callback, pulse);
+ tsmf_pulse_stream_request_callback, pulse);
buffer_attr.maxlength = pa_usec_to_bytes(500000, &pulse->sample_spec);
buffer_attr.tlength = pa_usec_to_bytes(250000, &pulse->sample_spec);
buffer_attr.prebuf = (UINT32) -1;
buffer_attr.minreq = (UINT32) -1;
buffer_attr.fragsize = (UINT32) -1;
- if (pa_stream_connect_playback(pulse->stream,
- pulse->device[0] ? pulse->device : NULL, &buffer_attr,
- PA_STREAM_ADJUST_LATENCY | PA_STREAM_INTERPOLATE_TIMING | PA_STREAM_AUTO_TIMING_UPDATE,
- NULL, NULL) < 0)
+ if(pa_stream_connect_playback(pulse->stream,
+ pulse->device[0] ? pulse->device : NULL, &buffer_attr,
+ PA_STREAM_ADJUST_LATENCY | PA_STREAM_INTERPOLATE_TIMING | PA_STREAM_AUTO_TIMING_UPDATE,
+ NULL, NULL) < 0)
{
pa_threaded_mainloop_unlock(pulse->mainloop);
DEBUG_WARN("pa_stream_connect_playback failed (%d)",
- pa_context_errno(pulse->context));
+ pa_context_errno(pulse->context));
return FALSE;
}
-
- for (;;)
+ for(;;)
{
state = pa_stream_get_state(pulse->stream);
- if (state == PA_STREAM_READY)
+ if(state == PA_STREAM_READY)
break;
- if (!PA_STREAM_IS_GOOD(state))
+ if(!PA_STREAM_IS_GOOD(state))
{
DEBUG_WARN("bad stream state (%d)",
- pa_context_errno(pulse->context));
+ pa_context_errno(pulse->context));
break;
}
pa_threaded_mainloop_wait(pulse->mainloop);
}
pa_threaded_mainloop_unlock(pulse->mainloop);
- if (state == PA_STREAM_READY)
+ if(state == PA_STREAM_READY)
{
- DEBUG_DVC("connected");
+ DEBUG_TSMF("connected");
return TRUE;
}
else
@@ -284,105 +263,93 @@ static BOOL tsmf_pulse_open_stream(TSMFPulseAudioDevice* pulse)
}
}
-static BOOL tsmf_pulse_set_format(ITSMFAudioDevice* audio,
- UINT32 sample_rate, UINT32 channels, UINT32 bits_per_sample)
+static BOOL tsmf_pulse_set_format(ITSMFAudioDevice *audio,
+ UINT32 sample_rate, UINT32 channels, UINT32 bits_per_sample)
{
- TSMFPulseAudioDevice* pulse = (TSMFPulseAudioDevice*) audio;
-
- DEBUG_DVC("sample_rate %d channels %d bits_per_sample %d",
- sample_rate, channels, bits_per_sample);
-
+ TSMFPulseAudioDevice *pulse = (TSMFPulseAudioDevice *) audio;
+ DEBUG_TSMF("sample_rate %d channels %d bits_per_sample %d",
+ sample_rate, channels, bits_per_sample);
pulse->sample_spec.rate = sample_rate;
pulse->sample_spec.channels = channels;
pulse->sample_spec.format = PA_SAMPLE_S16LE;
-
return tsmf_pulse_open_stream(pulse);
}
-static BOOL tsmf_pulse_play(ITSMFAudioDevice* audio, BYTE* data, UINT32 data_size)
+static BOOL tsmf_pulse_play(ITSMFAudioDevice *audio, BYTE *data, UINT32 data_size)
{
- TSMFPulseAudioDevice* pulse = (TSMFPulseAudioDevice*) audio;
- BYTE* src;
+ TSMFPulseAudioDevice *pulse = (TSMFPulseAudioDevice *) audio;
+ BYTE *src;
int len;
int ret;
-
- DEBUG_DVC("data_size %d", data_size);
-
- if (pulse->stream)
+ DEBUG_TSMF("data_size %d", data_size);
+ if(pulse->stream)
{
pa_threaded_mainloop_lock(pulse->mainloop);
-
src = data;
- while (data_size > 0)
+ while(data_size > 0)
{
- while ((len = pa_stream_writable_size(pulse->stream)) == 0)
+ while((len = pa_stream_writable_size(pulse->stream)) == 0)
{
- DEBUG_DVC("waiting");
+ DEBUG_TSMF("waiting");
pa_threaded_mainloop_wait(pulse->mainloop);
}
- if (len < 0)
+ if(len < 0)
break;
- if (len > data_size)
+ if(len > data_size)
len = data_size;
ret = pa_stream_write(pulse->stream, src, len, NULL, 0LL, PA_SEEK_RELATIVE);
- if (ret < 0)
+ if(ret < 0)
{
- DEBUG_DVC("pa_stream_write failed (%d)",
- pa_context_errno(pulse->context));
+ DEBUG_TSMF("pa_stream_write failed (%d)",
+ pa_context_errno(pulse->context));
break;
}
src += len;
data_size -= len;
}
-
pa_threaded_mainloop_unlock(pulse->mainloop);
}
free(data);
-
return TRUE;
}
-static UINT64 tsmf_pulse_get_latency(ITSMFAudioDevice* audio)
+static UINT64 tsmf_pulse_get_latency(ITSMFAudioDevice *audio)
{
pa_usec_t usec;
UINT64 latency = 0;
- TSMFPulseAudioDevice* pulse = (TSMFPulseAudioDevice*) audio;
-
- if (pulse->stream && pa_stream_get_latency(pulse->stream, &usec, NULL) == 0)
+ TSMFPulseAudioDevice *pulse = (TSMFPulseAudioDevice *) audio;
+ if(pulse->stream && pa_stream_get_latency(pulse->stream, &usec, NULL) == 0)
{
latency = ((UINT64)usec) * 10LL;
}
return latency;
}
-static void tsmf_pulse_flush(ITSMFAudioDevice* audio)
+static void tsmf_pulse_flush(ITSMFAudioDevice *audio)
{
- TSMFPulseAudioDevice* pulse = (TSMFPulseAudioDevice*) audio;
-
+ TSMFPulseAudioDevice *pulse = (TSMFPulseAudioDevice *) audio;
pa_threaded_mainloop_lock(pulse->mainloop);
tsmf_pulse_wait_for_operation(pulse,
- pa_stream_flush(pulse->stream, tsmf_pulse_stream_success_callback, pulse));
+ pa_stream_flush(pulse->stream, tsmf_pulse_stream_success_callback, pulse));
pa_threaded_mainloop_unlock(pulse->mainloop);
}
-static void tsmf_pulse_free(ITSMFAudioDevice* audio)
+static void tsmf_pulse_free(ITSMFAudioDevice *audio)
{
- TSMFPulseAudioDevice* pulse = (TSMFPulseAudioDevice*) audio;
-
- DEBUG_DVC("");
-
+ TSMFPulseAudioDevice *pulse = (TSMFPulseAudioDevice *) audio;
+ DEBUG_TSMF("");
tsmf_pulse_close_stream(pulse);
- if (pulse->mainloop)
+ if(pulse->mainloop)
{
pa_threaded_mainloop_stop(pulse->mainloop);
}
- if (pulse->context)
+ if(pulse->context)
{
pa_context_disconnect(pulse->context);
pa_context_unref(pulse->context);
pulse->context = NULL;
}
- if (pulse->mainloop)
+ if(pulse->mainloop)
{
pa_threaded_mainloop_free(pulse->mainloop);
pulse->mainloop = NULL;
@@ -394,20 +361,17 @@ static void tsmf_pulse_free(ITSMFAudioDevice* audio)
#define freerdp_tsmf_client_audio_subsystem_entry pulse_freerdp_tsmf_client_audio_subsystem_entry
#endif
-ITSMFAudioDevice* freerdp_tsmf_client_audio_subsystem_entry(void)
+ITSMFAudioDevice *freerdp_tsmf_client_audio_subsystem_entry(void)
{
- TSMFPulseAudioDevice* pulse;
-
- pulse = (TSMFPulseAudioDevice*) malloc(sizeof(TSMFPulseAudioDevice));
+ TSMFPulseAudioDevice *pulse;
+ pulse = (TSMFPulseAudioDevice *) malloc(sizeof(TSMFPulseAudioDevice));
ZeroMemory(pulse, sizeof(TSMFPulseAudioDevice));
-
pulse->iface.Open = tsmf_pulse_open;
pulse->iface.SetFormat = tsmf_pulse_set_format;
pulse->iface.Play = tsmf_pulse_play;
pulse->iface.GetLatency = tsmf_pulse_get_latency;
pulse->iface.Flush = tsmf_pulse_flush;
pulse->iface.Free = tsmf_pulse_free;
-
- return (ITSMFAudioDevice*) pulse;
+ return (ITSMFAudioDevice *) pulse;
}
diff --git a/channels/tsmf/client/tsmf_codec.c b/channels/tsmf/client/tsmf_codec.c
index 2b0af5031..5fac84991 100644
--- a/channels/tsmf/client/tsmf_codec.c
+++ b/channels/tsmf/client/tsmf_codec.c
@@ -37,7 +37,7 @@
typedef struct _TSMFMediaTypeMap
{
BYTE guid[16];
- const char* name;
+ const char *name;
int type;
} TSMFMediaTypeMap;
@@ -259,24 +259,23 @@ static const TSMFMediaTypeMap tsmf_format_type_map[] =
}
};
-static void tsmf_print_guid(const BYTE* guid)
+static void tsmf_print_guid(const BYTE *guid)
{
-#ifdef WITH_DEBUG_DVC
+#ifdef WITH_DEBUG_TSMF
int i;
-
- for (i = 3; i >= 0; i--)
+ for(i = 3; i >= 0; i--)
fprintf(stderr, "%02X", guid[i]);
fprintf(stderr, "-");
- for (i = 5; i >= 4; i--)
+ for(i = 5; i >= 4; i--)
fprintf(stderr, "%02X", guid[i]);
fprintf(stderr, "-");
- for (i = 7; i >= 6; i--)
+ for(i = 7; i >= 6; i--)
fprintf(stderr, "%02X", guid[i]);
fprintf(stderr, "-");
- for (i = 8; i < 16; i++)
+ for(i = 8; i < 16; i++)
{
fprintf(stderr, "%02X", guid[i]);
- if (i == 9)
+ if(i == 9)
fprintf(stderr, "-");
}
fprintf(stderr, "\n");
@@ -284,34 +283,29 @@ static void tsmf_print_guid(const BYTE* guid)
}
/* http://msdn.microsoft.com/en-us/library/dd318229.aspx */
-static UINT32 tsmf_codec_parse_BITMAPINFOHEADER(TS_AM_MEDIA_TYPE* mediatype, wStream* s, BOOL bypass)
+static UINT32 tsmf_codec_parse_BITMAPINFOHEADER(TS_AM_MEDIA_TYPE *mediatype, wStream *s, BOOL bypass)
{
UINT32 biSize;
UINT32 biWidth;
UINT32 biHeight;
-
Stream_Read_UINT32(s, biSize);
Stream_Read_UINT32(s, biWidth);
Stream_Read_UINT32(s, biHeight);
Stream_Seek(s, 28);
-
- if (mediatype->Width == 0)
+ if(mediatype->Width == 0)
mediatype->Width = biWidth;
- if (mediatype->Height == 0)
+ if(mediatype->Height == 0)
mediatype->Height = biHeight;
/* Assume there will be no color table for video? */
-
- if (bypass && biSize > 40)
+ if(bypass && biSize > 40)
Stream_Seek(s, biSize - 40);
-
return (bypass ? biSize : 40);
}
/* http://msdn.microsoft.com/en-us/library/dd407326.aspx */
-static UINT32 tsmf_codec_parse_VIDEOINFOHEADER2(TS_AM_MEDIA_TYPE* mediatype, wStream* s)
+static UINT32 tsmf_codec_parse_VIDEOINFOHEADER2(TS_AM_MEDIA_TYPE *mediatype, wStream *s)
{
UINT64 AvgTimePerFrame;
-
/* VIDEOINFOHEADER2.rcSource, RECT(LONG left, LONG top, LONG right, LONG bottom) */
Stream_Seek_UINT32(s);
Stream_Seek_UINT32(s);
@@ -329,25 +323,23 @@ static UINT32 tsmf_codec_parse_VIDEOINFOHEADER2(TS_AM_MEDIA_TYPE* mediatype, wSt
mediatype->SamplesPerSecond.Denominator = (int)(AvgTimePerFrame / 10LL);
/* Remaining fields before bmiHeader */
Stream_Seek(s, 24);
-
return 72;
}
/* http://msdn.microsoft.com/en-us/library/dd390700.aspx */
-static UINT32 tsmf_codec_parse_VIDEOINFOHEADER(TS_AM_MEDIA_TYPE* mediatype, wStream* s)
+static UINT32 tsmf_codec_parse_VIDEOINFOHEADER(TS_AM_MEDIA_TYPE *mediatype, wStream *s)
{
-/*
-typedef struct tagVIDEOINFOHEADER {
- RECT rcSource; //16
- RECT rcTarget; //16 32
- DWORD dwBitRate; //4 36
- DWORD dwBitErrorRate; //4 40
- REFERENCE_TIME AvgTimePerFrame; //8 48
- BITMAPINFOHEADER bmiHeader;
-} VIDEOINFOHEADER;
-*/
+ /*
+ typedef struct tagVIDEOINFOHEADER {
+ RECT rcSource; //16
+ RECT rcTarget; //16 32
+ DWORD dwBitRate; //4 36
+ DWORD dwBitErrorRate; //4 40
+ REFERENCE_TIME AvgTimePerFrame; //8 48
+ BITMAPINFOHEADER bmiHeader;
+ } VIDEOINFOHEADER;
+ */
UINT64 AvgTimePerFrame;
-
/* VIDEOINFOHEADER.rcSource, RECT(LONG left, LONG top, LONG right, LONG bottom) */
Stream_Seek_UINT32(s);
Stream_Seek_UINT32(s);
@@ -363,76 +355,66 @@ typedef struct tagVIDEOINFOHEADER {
Stream_Read_UINT64(s, AvgTimePerFrame);
mediatype->SamplesPerSecond.Numerator = 1000000;
mediatype->SamplesPerSecond.Denominator = (int)(AvgTimePerFrame / 10LL);
-
return 48;
}
-BOOL tsmf_codec_parse_media_type(TS_AM_MEDIA_TYPE* mediatype, wStream* s)
+BOOL tsmf_codec_parse_media_type(TS_AM_MEDIA_TYPE *mediatype, wStream *s)
{
int i;
UINT32 cbFormat;
BOOL ret = TRUE;
-
memset(mediatype, 0, sizeof(TS_AM_MEDIA_TYPE));
-
/* MajorType */
- DEBUG_DVC("MajorType:");
+ DEBUG_TSMF("MajorType:");
tsmf_print_guid(Stream_Pointer(s));
- for (i = 0; tsmf_major_type_map[i].type != TSMF_MAJOR_TYPE_UNKNOWN; i++)
+ for(i = 0; tsmf_major_type_map[i].type != TSMF_MAJOR_TYPE_UNKNOWN; i++)
{
- if (memcmp(tsmf_major_type_map[i].guid, Stream_Pointer(s), 16) == 0)
+ if(memcmp(tsmf_major_type_map[i].guid, Stream_Pointer(s), 16) == 0)
break;
}
mediatype->MajorType = tsmf_major_type_map[i].type;
- if (mediatype->MajorType == TSMF_MAJOR_TYPE_UNKNOWN)
+ if(mediatype->MajorType == TSMF_MAJOR_TYPE_UNKNOWN)
ret = FALSE;
- DEBUG_DVC("MajorType %s", tsmf_major_type_map[i].name);
+ DEBUG_TSMF("MajorType %s", tsmf_major_type_map[i].name);
Stream_Seek(s, 16);
-
/* SubType */
- DEBUG_DVC("SubType:");
+ DEBUG_TSMF("SubType:");
tsmf_print_guid(Stream_Pointer(s));
- for (i = 0; tsmf_sub_type_map[i].type != TSMF_SUB_TYPE_UNKNOWN; i++)
+ for(i = 0; tsmf_sub_type_map[i].type != TSMF_SUB_TYPE_UNKNOWN; i++)
{
- if (memcmp(tsmf_sub_type_map[i].guid, Stream_Pointer(s), 16) == 0)
+ if(memcmp(tsmf_sub_type_map[i].guid, Stream_Pointer(s), 16) == 0)
break;
}
mediatype->SubType = tsmf_sub_type_map[i].type;
- if (mediatype->SubType == TSMF_SUB_TYPE_UNKNOWN)
+ if(mediatype->SubType == TSMF_SUB_TYPE_UNKNOWN)
ret = FALSE;
- DEBUG_DVC("SubType %s", tsmf_sub_type_map[i].name);
+ DEBUG_TSMF("SubType %s", tsmf_sub_type_map[i].name);
Stream_Seek(s, 16);
-
/* bFixedSizeSamples, bTemporalCompression, SampleSize */
Stream_Seek(s, 12);
-
/* FormatType */
- DEBUG_DVC("FormatType:");
+ DEBUG_TSMF("FormatType:");
tsmf_print_guid(Stream_Pointer(s));
- for (i = 0; tsmf_format_type_map[i].type != TSMF_FORMAT_TYPE_UNKNOWN; i++)
+ for(i = 0; tsmf_format_type_map[i].type != TSMF_FORMAT_TYPE_UNKNOWN; i++)
{
- if (memcmp(tsmf_format_type_map[i].guid, Stream_Pointer(s), 16) == 0)
+ if(memcmp(tsmf_format_type_map[i].guid, Stream_Pointer(s), 16) == 0)
break;
}
mediatype->FormatType = tsmf_format_type_map[i].type;
- if (mediatype->FormatType == TSMF_FORMAT_TYPE_UNKNOWN)
+ if(mediatype->FormatType == TSMF_FORMAT_TYPE_UNKNOWN)
ret = FALSE;
- DEBUG_DVC("FormatType %s", tsmf_format_type_map[i].name);
+ DEBUG_TSMF("FormatType %s", tsmf_format_type_map[i].name);
Stream_Seek(s, 16);
-
/* cbFormat */
Stream_Read_UINT32(s, cbFormat);
- DEBUG_DVC("cbFormat %d", cbFormat);
-
-#ifdef WITH_DEBUG_DVC
+ DEBUG_TSMF("cbFormat %d", cbFormat);
+#ifdef WITH_DEBUG_TSMF
winpr_HexDump(Stream_Pointer(s), cbFormat);
#endif
-
- switch (mediatype->FormatType)
+ switch(mediatype->FormatType)
{
case TSMF_FORMAT_TYPE_MFVIDEOFORMAT:
/* http://msdn.microsoft.com/en-us/library/aa473808.aspx */
-
Stream_Seek(s, 8); /* dwSize and ? */
Stream_Read_UINT32(s, mediatype->Width); /* videoInfo.dwWidth */
Stream_Read_UINT32(s, mediatype->Height); /* videoInfo.dwHeight */
@@ -443,17 +425,14 @@ BOOL tsmf_codec_parse_media_type(TS_AM_MEDIA_TYPE* mediatype, wStream* s)
Stream_Seek(s, 80);
Stream_Read_UINT32(s, mediatype->BitRate); /* compressedInfo.AvgBitrate */
Stream_Seek(s, 36);
-
- if (cbFormat > 176)
+ if(cbFormat > 176)
{
mediatype->ExtraDataSize = cbFormat - 176;
mediatype->ExtraData = Stream_Pointer(s);
}
break;
-
case TSMF_FORMAT_TYPE_WAVEFORMATEX:
/* http://msdn.microsoft.com/en-us/library/dd757720.aspx */
-
Stream_Seek_UINT16(s);
Stream_Read_UINT16(s, mediatype->Channels);
Stream_Read_UINT32(s, mediatype->SamplesPerSecond.Numerator);
@@ -463,66 +442,55 @@ BOOL tsmf_codec_parse_media_type(TS_AM_MEDIA_TYPE* mediatype, wStream* s)
Stream_Read_UINT16(s, mediatype->BlockAlign);
Stream_Read_UINT16(s, mediatype->BitsPerSample);
Stream_Read_UINT16(s, mediatype->ExtraDataSize);
- if (mediatype->ExtraDataSize > 0)
+ if(mediatype->ExtraDataSize > 0)
mediatype->ExtraData = Stream_Pointer(s);
-
break;
-
case TSMF_FORMAT_TYPE_MPEG1VIDEOINFO:
/* http://msdn.microsoft.com/en-us/library/dd390700.aspx */
-
i = tsmf_codec_parse_VIDEOINFOHEADER(mediatype, s);
i += tsmf_codec_parse_BITMAPINFOHEADER(mediatype, s, TRUE);
- if (cbFormat > i)
+ if(cbFormat > i)
{
mediatype->ExtraDataSize = cbFormat - i;
mediatype->ExtraData = Stream_Pointer(s);
}
break;
-
case TSMF_FORMAT_TYPE_MPEG2VIDEOINFO:
/* http://msdn.microsoft.com/en-us/library/dd390707.aspx */
-
i = tsmf_codec_parse_VIDEOINFOHEADER2(mediatype, s);
i += tsmf_codec_parse_BITMAPINFOHEADER(mediatype, s, TRUE);
- if (cbFormat > i)
+ if(cbFormat > i)
{
mediatype->ExtraDataSize = cbFormat - i;
mediatype->ExtraData = Stream_Pointer(s);
}
break;
-
case TSMF_FORMAT_TYPE_VIDEOINFO2:
i = tsmf_codec_parse_VIDEOINFOHEADER2(mediatype, s);
i += tsmf_codec_parse_BITMAPINFOHEADER(mediatype, s, FALSE);
- if (cbFormat > i)
+ if(cbFormat > i)
{
mediatype->ExtraDataSize = cbFormat - i;
mediatype->ExtraData = Stream_Pointer(s);
}
break;
-
default:
break;
}
-
- if (mediatype->SamplesPerSecond.Numerator == 0)
+ if(mediatype->SamplesPerSecond.Numerator == 0)
mediatype->SamplesPerSecond.Numerator = 1;
- if (mediatype->SamplesPerSecond.Denominator == 0)
+ if(mediatype->SamplesPerSecond.Denominator == 0)
mediatype->SamplesPerSecond.Denominator = 1;
-
return ret;
}
-BOOL tsmf_codec_check_media_type(wStream* s)
+BOOL tsmf_codec_check_media_type(wStream *s)
{
- BYTE* m;
+ BYTE *m;
BOOL ret;
TS_AM_MEDIA_TYPE mediatype;
-
Stream_GetPointer(s, m);
ret = tsmf_codec_parse_media_type(&mediatype, s);
Stream_SetPointer(s, m);
-
return ret;
}
diff --git a/channels/tsmf/client/tsmf_decoder.c b/channels/tsmf/client/tsmf_decoder.c
index 630154776..3d17c60d0 100644
--- a/channels/tsmf/client/tsmf_decoder.c
+++ b/channels/tsmf/client/tsmf_decoder.c
@@ -32,45 +32,41 @@
#include "tsmf_constants.h"
#include "tsmf_decoder.h"
-static ITSMFDecoder* tsmf_load_decoder_by_name(const char* name, TS_AM_MEDIA_TYPE* media_type)
+static ITSMFDecoder *tsmf_load_decoder_by_name(const char *name, TS_AM_MEDIA_TYPE *media_type)
{
- ITSMFDecoder* decoder;
+ ITSMFDecoder *decoder;
TSMF_DECODER_ENTRY entry;
-
entry = (TSMF_DECODER_ENTRY) freerdp_load_channel_addin_entry("tsmf", (LPSTR) name, "decoder", 0);
-
- if (entry == NULL)
+ if(entry == NULL)
return NULL;
-
decoder = entry();
-
- if (decoder == NULL)
+ if(decoder == NULL)
{
DEBUG_WARN("failed to call export function in %s", name);
return NULL;
}
-
- if (!decoder->SetFormat(decoder, media_type))
+ if(!decoder->SetFormat(decoder, media_type))
{
decoder->Free(decoder);
decoder = NULL;
}
-
return decoder;
}
-ITSMFDecoder* tsmf_load_decoder(const char* name, TS_AM_MEDIA_TYPE* media_type)
+ITSMFDecoder *tsmf_load_decoder(const char *name, TS_AM_MEDIA_TYPE *media_type)
{
- ITSMFDecoder* decoder;
-
- if (name)
+ ITSMFDecoder *decoder = NULL;
+ if(name)
{
decoder = tsmf_load_decoder_by_name(name, media_type);
}
- else
- {
+#if defined(WITH_GSTREAMER_1_0) || defined(WITH_GSTREAMER_0_10)
+ if(!decoder)
+ decoder = tsmf_load_decoder_by_name("gstreamer", media_type);
+#endif
+#if defined(WITH_FFMPEG)
+ if(!decoder)
decoder = tsmf_load_decoder_by_name("ffmpeg", media_type);
- }
-
+#endif
return decoder;
}
diff --git a/channels/tsmf/client/tsmf_decoder.h b/channels/tsmf/client/tsmf_decoder.h
index 792bc6e62..1215d0e98 100644
--- a/channels/tsmf/client/tsmf_decoder.h
+++ b/channels/tsmf/client/tsmf_decoder.h
@@ -26,9 +26,8 @@
typedef enum _ITSMFControlMsg
{
Control_Pause,
- Control_Restart,
- Control_Flush,
- Control_EndOfStream
+ Control_Resume,
+ Control_Stop
} ITSMFControlMsg;
typedef struct _ITSMFDecoder ITSMFDecoder;
@@ -36,36 +35,40 @@ typedef struct _ITSMFDecoder ITSMFDecoder;
struct _ITSMFDecoder
{
/* Set the decoder format. Return true if supported. */
- BOOL (*SetFormat) (ITSMFDecoder* decoder, TS_AM_MEDIA_TYPE* media_type);
+ BOOL (*SetFormat)(ITSMFDecoder *decoder, TS_AM_MEDIA_TYPE *media_type);
/* Decode a sample. */
- BOOL (*Decode) (ITSMFDecoder* decoder, const BYTE* data, UINT32 data_size, UINT32 extensions);
+ BOOL (*Decode)(ITSMFDecoder *decoder, const BYTE *data, UINT32 data_size, UINT32 extensions);
/* Get the decoded data */
- BYTE* (*GetDecodedData) (ITSMFDecoder* decoder, UINT32* size);
+ BYTE *(*GetDecodedData)(ITSMFDecoder *decoder, UINT32 *size);
/* Get the pixel format of decoded video frame */
- UINT32 (*GetDecodedFormat) (ITSMFDecoder* decoder);
+ UINT32(*GetDecodedFormat)(ITSMFDecoder *decoder);
/* Get the width and height of decoded video frame */
- BOOL (*GetDecodedDimension) (ITSMFDecoder* decoder, UINT32* width, UINT32* height);
+ BOOL (*GetDecodedDimension)(ITSMFDecoder *decoder, UINT32 *width, UINT32 *height);
/* Free the decoder */
- void (*Free) (ITSMFDecoder * decoder);
+ void (*Free)(ITSMFDecoder *decoder);
/* Optional Contol function */
- void (*Control) (ITSMFDecoder * decoder, ITSMFControlMsg control_msg, UINT32 *arg);
+ void (*Control)(ITSMFDecoder *decoder, ITSMFControlMsg control_msg, UINT32 *arg);
/* Decode a sample with extended interface. */
- int (*DecodeEx) (ITSMFDecoder * decoder, const BYTE * data, UINT32 data_size, UINT32 extensions,
- UINT64 start_time, UINT64 end_time, UINT64 duration);
+ int (*DecodeEx)(ITSMFDecoder *decoder, const BYTE *data, UINT32 data_size, UINT32 extensions,
+ UINT64 start_time, UINT64 end_time, UINT64 duration);
/* Get current play time */
- UINT64 (*GetRunningTime) (ITSMFDecoder * decoder);
+ UINT64(*GetRunningTime)(ITSMFDecoder *decoder);
/* Update Gstreamer Rendering Area */
- void (*UpdateRenderingArea) (ITSMFDecoder * decoder, int newX, int newY, int newWidth, int newHeight, int numRectangles, RDP_RECT *rectangles);
+ void (*UpdateRenderingArea)(ITSMFDecoder *decoder, int newX, int newY, int newWidth, int newHeight, int numRectangles, RDP_RECT *rectangles);
/* Change Gstreamer Audio Volume */
- void (*ChangeVolume) (ITSMFDecoder * decoder, UINT32 newVolume, UINT32 muted);
+ void (*ChangeVolume)(ITSMFDecoder *decoder, UINT32 newVolume, UINT32 muted);
/* Check buffer level */
- UINT32 (*BufferLevel) (ITSMFDecoder * decoder);
+ BOOL (*BufferFilled)(ITSMFDecoder *decoder);
+ /* Register a callback for frame ack. */
+ BOOL (*SetAckFunc)(ITSMFDecoder *decoder, BOOL (*cb)(void *,BOOL), void *stream);
+ /* Register a callback for stream seek detection. */
+ BOOL (*SetSyncFunc)(ITSMFDecoder *decoder, void (*cb)(void *), void *stream);
};
#define TSMF_DECODER_EXPORT_FUNC_NAME "TSMFDecoderEntry"
-typedef ITSMFDecoder* (*TSMF_DECODER_ENTRY) (void);
+typedef ITSMFDecoder *(*TSMF_DECODER_ENTRY)(void);
-ITSMFDecoder* tsmf_load_decoder(const char* name, TS_AM_MEDIA_TYPE* media_type);
+ITSMFDecoder *tsmf_load_decoder(const char *name, TS_AM_MEDIA_TYPE *media_type);
#endif
diff --git a/channels/tsmf/client/tsmf_ifman.c b/channels/tsmf/client/tsmf_ifman.c
index 03229adb5..40e89e439 100644
--- a/channels/tsmf/client/tsmf_ifman.c
+++ b/channels/tsmf/client/tsmf_ifman.c
@@ -37,21 +37,18 @@
#include "tsmf_ifman.h"
-int tsmf_ifman_rim_exchange_capability_request(TSMF_IFMAN* ifman)
+int tsmf_ifman_rim_exchange_capability_request(TSMF_IFMAN *ifman)
{
UINT32 CapabilityValue;
-
Stream_Read_UINT32(ifman->input, CapabilityValue);
- DEBUG_DVC("server CapabilityValue %d", CapabilityValue);
-
+ DEBUG_TSMF("server CapabilityValue %d", CapabilityValue);
Stream_EnsureRemainingCapacity(ifman->output, 8);
Stream_Write_UINT32(ifman->output, 1); /* CapabilityValue */
Stream_Write_UINT32(ifman->output, 0); /* Result */
-
return 0;
}
-int tsmf_ifman_exchange_capability_request(TSMF_IFMAN* ifman)
+int tsmf_ifman_exchange_capability_request(TSMF_IFMAN *ifman)
{
UINT32 i;
UINT32 v;
@@ -59,32 +56,28 @@ int tsmf_ifman_exchange_capability_request(TSMF_IFMAN* ifman)
UINT32 CapabilityType;
UINT32 cbCapabilityLength;
UINT32 numHostCapabilities;
-
pos = Stream_GetPosition(ifman->output);
Stream_EnsureRemainingCapacity(ifman->output, ifman->input_size + 4);
Stream_Copy(ifman->output, ifman->input, ifman->input_size);
-
Stream_SetPosition(ifman->output, pos);
Stream_Read_UINT32(ifman->output, numHostCapabilities);
-
- for (i = 0; i < numHostCapabilities; i++)
+ for(i = 0; i < numHostCapabilities; i++)
{
Stream_Read_UINT32(ifman->output, CapabilityType);
Stream_Read_UINT32(ifman->output, cbCapabilityLength);
pos = Stream_GetPosition(ifman->output);
-
- switch (CapabilityType)
+ switch(CapabilityType)
{
case 1: /* Protocol version request */
Stream_Read_UINT32(ifman->output, v);
- DEBUG_DVC("server protocol version %d", v);
+ DEBUG_TSMF("server protocol version %d", v);
break;
case 2: /* Supported platform */
Stream_Peek_UINT32(ifman->output, v);
- DEBUG_DVC("server supported platform %d", v);
+ DEBUG_TSMF("server supported platform %d", v);
/* Claim that we support both MF and DShow platforms. */
Stream_Write_UINT32(ifman->output,
- MMREDIR_CAPABILITY_PLATFORM_MF | MMREDIR_CAPABILITY_PLATFORM_DSHOW);
+ MMREDIR_CAPABILITY_PLATFORM_MF | MMREDIR_CAPABILITY_PLATFORM_DSHOW);
break;
default:
DEBUG_WARN("unknown capability type %d", CapabilityType);
@@ -93,81 +86,62 @@ int tsmf_ifman_exchange_capability_request(TSMF_IFMAN* ifman)
Stream_SetPosition(ifman->output, pos + cbCapabilityLength);
}
Stream_Write_UINT32(ifman->output, 0); /* Result */
-
ifman->output_interface_id = TSMF_INTERFACE_DEFAULT | STREAM_ID_STUB;
-
return 0;
}
-int tsmf_ifman_check_format_support_request(TSMF_IFMAN* ifman)
+int tsmf_ifman_check_format_support_request(TSMF_IFMAN *ifman)
{
UINT32 numMediaType;
UINT32 PlatformCookie;
UINT32 FormatSupported = 1;
-
Stream_Read_UINT32(ifman->input, PlatformCookie);
Stream_Seek_UINT32(ifman->input); /* NoRolloverFlags (4 bytes) */
Stream_Read_UINT32(ifman->input, numMediaType);
-
- DEBUG_DVC("PlatformCookie %d numMediaType %d", PlatformCookie, numMediaType);
-
- if (!tsmf_codec_check_media_type(ifman->input))
+ DEBUG_TSMF("PlatformCookie %d numMediaType %d", PlatformCookie, numMediaType);
+ if(!tsmf_codec_check_media_type(ifman->input))
FormatSupported = 0;
-
- if (FormatSupported)
- DEBUG_DVC("format ok.");
-
+ if(FormatSupported)
+ DEBUG_TSMF("format ok.");
Stream_EnsureRemainingCapacity(ifman->output, 12);
Stream_Write_UINT32(ifman->output, FormatSupported);
Stream_Write_UINT32(ifman->output, PlatformCookie);
Stream_Write_UINT32(ifman->output, 0); /* Result */
-
ifman->output_interface_id = TSMF_INTERFACE_DEFAULT | STREAM_ID_STUB;
-
return 0;
}
-int tsmf_ifman_on_new_presentation(TSMF_IFMAN* ifman)
+int tsmf_ifman_on_new_presentation(TSMF_IFMAN *ifman)
{
int status = 0;
- TSMF_PRESENTATION* presentation;
-
- DEBUG_DVC("");
-
+ TSMF_PRESENTATION *presentation;
+ DEBUG_TSMF("");
presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input));
- if (presentation)
+ if(presentation)
{
- DEBUG_DVC("Presentation already exists");
+ DEBUG_TSMF("Presentation already exists");
ifman->output_pending = FALSE;
return 0;
-
}
-
presentation = tsmf_presentation_new(Stream_Pointer(ifman->input), ifman->channel_callback);
-
- if (presentation == NULL)
+ if(presentation == NULL)
status = 1;
else
tsmf_presentation_set_audio_device(presentation, ifman->audio_name, ifman->audio_device);
-
ifman->output_pending = TRUE;
-
return status;
}
-int tsmf_ifman_add_stream(TSMF_IFMAN* ifman)
+int tsmf_ifman_add_stream(TSMF_IFMAN *ifman)
{
UINT32 StreamId;
int status = 0;
- TSMF_STREAM* stream;
- TSMF_PRESENTATION* presentation;
-
- DEBUG_DVC("");
-
+ TSMF_STREAM *stream;
+ TSMF_PRESENTATION *presentation;
+ DEBUG_TSMF("");
presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input));
Stream_Seek(ifman->input, 16);
-
- if (presentation == NULL)
+ if(presentation == NULL)
{
status = 1;
}
@@ -176,41 +150,33 @@ int tsmf_ifman_add_stream(TSMF_IFMAN* ifman)
Stream_Read_UINT32(ifman->input, StreamId);
Stream_Seek_UINT32(ifman->input); /* numMediaType */
stream = tsmf_stream_new(presentation, StreamId);
-
- if (stream)
+ if(stream)
tsmf_stream_set_format(stream, ifman->decoder_name, ifman->input);
}
-
ifman->output_pending = TRUE;
-
return status;
}
-int tsmf_ifman_set_topology_request(TSMF_IFMAN* ifman)
+int tsmf_ifman_set_topology_request(TSMF_IFMAN *ifman)
{
- DEBUG_DVC("");
-
+ DEBUG_TSMF("");
Stream_EnsureRemainingCapacity(ifman->output, 8);
Stream_Write_UINT32(ifman->output, 1); /* TopologyReady */
Stream_Write_UINT32(ifman->output, 0); /* Result */
ifman->output_interface_id = TSMF_INTERFACE_DEFAULT | STREAM_ID_STUB;
-
return 0;
}
-int tsmf_ifman_remove_stream(TSMF_IFMAN* ifman)
+int tsmf_ifman_remove_stream(TSMF_IFMAN *ifman)
{
int status = 0;
UINT32 StreamId;
- TSMF_STREAM* stream;
- TSMF_PRESENTATION* presentation;
-
- DEBUG_DVC("");
-
+ TSMF_STREAM *stream;
+ TSMF_PRESENTATION *presentation;
+ DEBUG_TSMF("");
presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input));
Stream_Seek(ifman->input, 16);
-
- if (presentation == NULL)
+ if(presentation == NULL)
{
status = 1;
}
@@ -218,41 +184,34 @@ int tsmf_ifman_remove_stream(TSMF_IFMAN* ifman)
{
Stream_Read_UINT32(ifman->input, StreamId);
stream = tsmf_stream_find_by_id(presentation, StreamId);
- if (stream)
+ if(stream)
tsmf_stream_free(stream);
else
status = 1;
}
-
ifman->output_pending = TRUE;
-
return status;
}
-float tsmf_stream_read_float(wStream* s)
+float tsmf_stream_read_float(wStream *s)
{
float fValue;
UINT32 iValue;
-
Stream_Read_UINT32(s, iValue);
CopyMemory(&fValue, &iValue, 4);
-
return fValue;
}
-int tsmf_ifman_set_source_video_rect(TSMF_IFMAN* ifman)
+int tsmf_ifman_set_source_video_rect(TSMF_IFMAN *ifman)
{
int status = 0;
float Left, Top;
float Right, Bottom;
- TSMF_PRESENTATION* presentation;
-
- DEBUG_DVC("");
-
+ TSMF_PRESENTATION *presentation;
+ DEBUG_TSMF("");
presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input));
Stream_Seek(ifman->input, 16);
-
- if (!presentation)
+ if(!presentation)
{
status = 1;
}
@@ -262,144 +221,117 @@ int tsmf_ifman_set_source_video_rect(TSMF_IFMAN* ifman)
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) */
-
- DEBUG_DVC("SetSourceVideoRect: Left: %f Top: %f Right: %f Bottom: %f",
- Left, Top, Right, Bottom);
+ DEBUG_TSMF("SetSourceVideoRect: Left: %f Top: %f Right: %f Bottom: %f",
+ Left, Top, Right, Bottom);
}
-
ifman->output_pending = TRUE;
-
return status;
}
-int tsmf_ifman_shutdown_presentation(TSMF_IFMAN* ifman)
+int tsmf_ifman_shutdown_presentation(TSMF_IFMAN *ifman)
{
- TSMF_PRESENTATION* presentation;
-
- DEBUG_DVC("");
-
+ TSMF_PRESENTATION *presentation;
+ DEBUG_TSMF("");
presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input));
-
- if (presentation)
+ if(presentation)
tsmf_presentation_free(presentation);
else
DEBUG_WARN("unknown presentation id");
-
Stream_EnsureRemainingCapacity(ifman->output, 4);
Stream_Write_UINT32(ifman->output, 0); /* Result */
ifman->output_interface_id = TSMF_INTERFACE_DEFAULT | STREAM_ID_STUB;
-
return 0;
}
-int tsmf_ifman_on_stream_volume(TSMF_IFMAN* ifman)
+int tsmf_ifman_on_stream_volume(TSMF_IFMAN *ifman)
{
- TSMF_PRESENTATION* presentation;
-
- DEBUG_DVC("on stream volume");
-
+ TSMF_PRESENTATION *presentation;
+ DEBUG_TSMF("on stream volume");
presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input));
-
- if (presentation)
+ if(presentation)
{
UINT32 newVolume;
UINT32 muted;
-
Stream_Seek(ifman->input, 16);
Stream_Read_UINT32(ifman->input, newVolume);
- DEBUG_DVC("on stream volume: new volume=[%d]", newVolume);
+ DEBUG_TSMF("on stream volume: new volume=[%d]", newVolume);
Stream_Read_UINT32(ifman->input, muted);
- DEBUG_DVC("on stream volume: muted=[%d]", muted);
+ DEBUG_TSMF("on stream volume: muted=[%d]", muted);
tsmf_presentation_volume_changed(presentation, newVolume, muted);
}
else
{
DEBUG_WARN("unknown presentation id");
}
-
ifman->output_pending = TRUE;
-
return 0;
}
-int tsmf_ifman_on_channel_volume(TSMF_IFMAN* ifman)
+int tsmf_ifman_on_channel_volume(TSMF_IFMAN *ifman)
{
- TSMF_PRESENTATION* presentation;
-
- DEBUG_DVC("on channel volume");
-
+ TSMF_PRESENTATION *presentation;
+ DEBUG_TSMF("on channel volume");
presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input));
-
- if (presentation)
+ if(presentation)
{
UINT32 channelVolume;
UINT32 changedChannel;
-
Stream_Seek(ifman->input, 16);
Stream_Read_UINT32(ifman->input, channelVolume);
- DEBUG_DVC("on channel volume: channel volume=[%d]", channelVolume);
+ DEBUG_TSMF("on channel volume: channel volume=[%d]", channelVolume);
Stream_Read_UINT32(ifman->input, changedChannel);
- DEBUG_DVC("on stream volume: changed channel=[%d]", changedChannel);
+ DEBUG_TSMF("on stream volume: changed channel=[%d]", changedChannel);
}
-
ifman->output_pending = TRUE;
-
return 0;
}
-int tsmf_ifman_set_video_window(TSMF_IFMAN* ifman)
+int tsmf_ifman_set_video_window(TSMF_IFMAN *ifman)
{
- DEBUG_DVC("");
+ DEBUG_TSMF("");
ifman->output_pending = TRUE;
return 0;
}
-int tsmf_ifman_update_geometry_info(TSMF_IFMAN* ifman)
+int tsmf_ifman_update_geometry_info(TSMF_IFMAN *ifman)
{
- TSMF_PRESENTATION* presentation;
+ TSMF_PRESENTATION *presentation;
UINT32 numGeometryInfo;
UINT32 Left;
UINT32 Top;
UINT32 Width;
UINT32 Height;
UINT32 cbVisibleRect;
- RDP_RECT* rects = NULL;
+ RDP_RECT *rects = NULL;
int num_rects = 0;
int error = 0;
int i;
int pos;
-
presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input));
Stream_Seek(ifman->input, 16);
-
Stream_Read_UINT32(ifman->input, numGeometryInfo);
pos = Stream_GetPosition(ifman->input);
-
Stream_Seek(ifman->input, 12); /* VideoWindowId (8 bytes), VideoWindowState (4 bytes) */
Stream_Read_UINT32(ifman->input, Width);
Stream_Read_UINT32(ifman->input, Height);
Stream_Read_UINT32(ifman->input, Left);
Stream_Read_UINT32(ifman->input, Top);
-
Stream_SetPosition(ifman->input, pos + numGeometryInfo);
Stream_Read_UINT32(ifman->input, cbVisibleRect);
num_rects = cbVisibleRect / 16;
-
- DEBUG_DVC("numGeometryInfo %d Width %d Height %d Left %d Top %d cbVisibleRect %d num_rects %d",
- numGeometryInfo, Width, Height, Left, Top, cbVisibleRect, num_rects);
-
- if (presentation == NULL)
+ DEBUG_TSMF("numGeometryInfo %d Width %d Height %d Left %d Top %d cbVisibleRect %d num_rects %d",
+ numGeometryInfo, Width, Height, Left, Top, cbVisibleRect, num_rects);
+ if(presentation == NULL)
{
error = 1;
}
else
{
- if (num_rects > 0)
+ if(num_rects > 0)
{
- rects = (RDP_RECT*) malloc(sizeof(RDP_RECT) * num_rects);
+ rects = (RDP_RECT *) malloc(sizeof(RDP_RECT) * num_rects);
ZeroMemory(rects, sizeof(RDP_RECT) * num_rects);
-
- for (i = 0; i < num_rects; i++)
+ for(i = 0; i < num_rects; i++)
{
Stream_Read_UINT16(ifman->input, rects[i].y); /* Top */
Stream_Seek_UINT16(ifman->input);
@@ -411,44 +343,40 @@ int tsmf_ifman_update_geometry_info(TSMF_IFMAN* ifman)
Stream_Seek_UINT16(ifman->input);
rects[i].width -= rects[i].x;
rects[i].height -= rects[i].y;
-
- DEBUG_DVC("rect %d: %d %d %d %d", i,
- rects[i].x, rects[i].y, rects[i].width, rects[i].height);
+ DEBUG_TSMF("rect %d: %d %d %d %d", i,
+ rects[i].x, rects[i].y, rects[i].width, rects[i].height);
}
}
tsmf_presentation_set_geometry_info(presentation, Left, Top, Width, Height, num_rects, rects);
}
-
ifman->output_pending = TRUE;
-
return error;
}
-int tsmf_ifman_set_allocator(TSMF_IFMAN* ifman)
+int tsmf_ifman_set_allocator(TSMF_IFMAN *ifman)
{
- DEBUG_DVC("");
+ DEBUG_TSMF("");
ifman->output_pending = TRUE;
return 0;
}
-int tsmf_ifman_notify_preroll(TSMF_IFMAN* ifman)
+int tsmf_ifman_notify_preroll(TSMF_IFMAN *ifman)
{
- DEBUG_DVC("");
+ DEBUG_TSMF("");
ifman->output_pending = TRUE;
return 0;
}
-int tsmf_ifman_on_sample(TSMF_IFMAN* ifman)
+int tsmf_ifman_on_sample(TSMF_IFMAN *ifman)
{
- TSMF_PRESENTATION* presentation;
- TSMF_STREAM* stream;
+ TSMF_PRESENTATION *presentation;
+ TSMF_STREAM *stream;
UINT32 StreamId;
UINT64 SampleStartTime;
UINT64 SampleEndTime;
UINT64 ThrottleDuration;
UINT32 SampleExtensions;
UINT32 cbData;
-
Stream_Seek(ifman->input, 16);
Stream_Read_UINT32(ifman->input, StreamId);
Stream_Seek_UINT32(ifman->input); /* numSample */
@@ -458,183 +386,144 @@ int tsmf_ifman_on_sample(TSMF_IFMAN* ifman)
Stream_Seek_UINT32(ifman->input); /* SampleFlags */
Stream_Read_UINT32(ifman->input, SampleExtensions);
Stream_Read_UINT32(ifman->input, cbData);
-
- DEBUG_DVC("MessageId %d StreamId %d SampleStartTime %d SampleEndTime %d "
- "ThrottleDuration %d SampleExtensions %d cbData %d",
- ifman->message_id, StreamId, (int)SampleStartTime, (int)SampleEndTime,
- (int)ThrottleDuration, SampleExtensions, cbData);
-
+ DEBUG_TSMF("MessageId %d StreamId %d SampleStartTime %d SampleEndTime %d "
+ "ThrottleDuration %d SampleExtensions %d cbData %d",
+ ifman->message_id, StreamId, (int)SampleStartTime, (int)SampleEndTime,
+ (int)ThrottleDuration, SampleExtensions, cbData);
presentation = tsmf_presentation_find_by_id(ifman->presentation_id);
-
- if (presentation == NULL)
+ if(presentation == NULL)
{
DEBUG_WARN("unknown presentation id");
return 1;
}
-
stream = tsmf_stream_find_by_id(presentation, StreamId);
-
- if (stream == NULL)
+ if(stream == NULL)
{
DEBUG_WARN("unknown stream id");
return 1;
}
-
tsmf_stream_push_sample(stream, ifman->channel_callback,
- ifman->message_id, SampleStartTime, SampleEndTime, ThrottleDuration, SampleExtensions,
- cbData, Stream_Pointer(ifman->input));
-
+ ifman->message_id, SampleStartTime, SampleEndTime, ThrottleDuration, SampleExtensions,
+ cbData, Stream_Pointer(ifman->input));
+ tsmf_presentation_sync(presentation);
ifman->output_pending = TRUE;
-
return 0;
}
-int tsmf_ifman_on_flush(TSMF_IFMAN* ifman)
+int tsmf_ifman_on_flush(TSMF_IFMAN *ifman)
{
UINT32 StreamId;
- TSMF_PRESENTATION* presentation;
-
+ TSMF_PRESENTATION *presentation;
Stream_Seek(ifman->input, 16);
Stream_Read_UINT32(ifman->input, StreamId);
- DEBUG_DVC("StreamId %d", StreamId);
-
+ DEBUG_TSMF("StreamId %d", StreamId);
presentation = tsmf_presentation_find_by_id(ifman->presentation_id);
-
- if (presentation == NULL)
+ if(presentation == NULL)
{
DEBUG_WARN("unknown presentation id");
return 1;
}
-
tsmf_presentation_flush(presentation);
-
ifman->output_pending = TRUE;
-
return 0;
}
-int tsmf_ifman_on_end_of_stream(TSMF_IFMAN* ifman)
+int tsmf_ifman_on_end_of_stream(TSMF_IFMAN *ifman)
{
UINT32 StreamId;
- TSMF_STREAM* stream;
- TSMF_PRESENTATION* presentation;
-
+ TSMF_STREAM *stream;
+ TSMF_PRESENTATION *presentation;
presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input));
Stream_Seek(ifman->input, 16);
Stream_Read_UINT32(ifman->input, StreamId);
-
- if (presentation)
+ if(presentation)
{
stream = tsmf_stream_find_by_id(presentation, StreamId);
- if (stream)
+ if(stream)
tsmf_stream_end(stream);
}
- DEBUG_DVC("StreamId %d", StreamId);
-
+ DEBUG_TSMF("StreamId %d", StreamId);
Stream_EnsureRemainingCapacity(ifman->output, 16);
Stream_Write_UINT32(ifman->output, CLIENT_EVENT_NOTIFICATION); /* FunctionId */
Stream_Write_UINT32(ifman->output, StreamId); /* StreamId */
Stream_Write_UINT32(ifman->output, TSMM_CLIENT_EVENT_ENDOFSTREAM); /* EventId */
Stream_Write_UINT32(ifman->output, 0); /* cbData */
ifman->output_interface_id = TSMF_INTERFACE_CLIENT_NOTIFICATIONS | STREAM_ID_PROXY;
-
return 0;
}
-int tsmf_ifman_on_playback_started(TSMF_IFMAN* ifman)
+int tsmf_ifman_on_playback_started(TSMF_IFMAN *ifman)
{
- TSMF_PRESENTATION* presentation;
-
- DEBUG_DVC("");
-
+ TSMF_PRESENTATION *presentation;
+ DEBUG_TSMF("");
presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input));
-
- if (presentation)
+ if(presentation)
tsmf_presentation_start(presentation);
else
DEBUG_WARN("unknown presentation id");
-
Stream_EnsureRemainingCapacity(ifman->output, 16);
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 */
ifman->output_interface_id = TSMF_INTERFACE_CLIENT_NOTIFICATIONS | STREAM_ID_PROXY;
-
return 0;
}
-int tsmf_ifman_on_playback_paused(TSMF_IFMAN* ifman)
+int tsmf_ifman_on_playback_paused(TSMF_IFMAN *ifman)
{
- TSMF_PRESENTATION* presentation;
-
- DEBUG_DVC("");
+ TSMF_PRESENTATION *presentation;
+ DEBUG_TSMF("");
ifman->output_pending = TRUE;
-
/* Added pause control so gstreamer pipeline can be paused accordingly */
-
presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input));
-
- if (presentation)
+ if(presentation)
tsmf_presentation_paused(presentation);
else
DEBUG_WARN("unknown presentation id");
-
return 0;
}
-int tsmf_ifman_on_playback_restarted(TSMF_IFMAN* ifman)
+int tsmf_ifman_on_playback_restarted(TSMF_IFMAN *ifman)
{
- TSMF_PRESENTATION* presentation;
-
- DEBUG_DVC("");
+ TSMF_PRESENTATION *presentation;
+ DEBUG_TSMF("");
ifman->output_pending = TRUE;
-
/* Added restart control so gstreamer pipeline can be resumed accordingly */
-
presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input));
-
- if (presentation)
+ if(presentation)
tsmf_presentation_restarted(presentation);
else
DEBUG_WARN("unknown presentation id");
-
return 0;
}
-int tsmf_ifman_on_playback_stopped(TSMF_IFMAN* ifman)
+int tsmf_ifman_on_playback_stopped(TSMF_IFMAN *ifman)
{
- TSMF_PRESENTATION* presentation;
-
- DEBUG_DVC("");
-
+ TSMF_PRESENTATION *presentation;
+ DEBUG_TSMF("");
presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input));
-
- if (presentation)
+ if(presentation)
tsmf_presentation_stop(presentation);
else
DEBUG_WARN("unknown presentation id");
-
Stream_EnsureRemainingCapacity(ifman->output, 16);
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 */
ifman->output_interface_id = TSMF_INTERFACE_CLIENT_NOTIFICATIONS | STREAM_ID_PROXY;
-
return 0;
}
-int tsmf_ifman_on_playback_rate_changed(TSMF_IFMAN * ifman)
+int tsmf_ifman_on_playback_rate_changed(TSMF_IFMAN *ifman)
{
- DEBUG_DVC("");
-
+ DEBUG_TSMF("");
Stream_EnsureRemainingCapacity(ifman->output, 16);
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 */
ifman->output_interface_id = TSMF_INTERFACE_CLIENT_NOTIFICATIONS | STREAM_ID_PROXY;
-
return 0;
}
diff --git a/channels/tsmf/client/tsmf_main.c b/channels/tsmf/client/tsmf_main.c
index e449e5935..ec1ee44c3 100644
--- a/channels/tsmf/client/tsmf_main.c
+++ b/channels/tsmf/client/tsmf_main.c
@@ -47,19 +47,19 @@ struct _TSMF_LISTENER_CALLBACK
{
IWTSListenerCallback iface;
- IWTSPlugin* plugin;
- IWTSVirtualChannelManager* channel_mgr;
+ IWTSPlugin *plugin;
+ IWTSVirtualChannelManager *channel_mgr;
};
struct _TSMF_CHANNEL_CALLBACK
{
IWTSVirtualChannelCallback iface;
- IWTSPlugin* plugin;
- IWTSVirtualChannelManager* channel_mgr;
- IWTSVirtualChannel* channel;
+ IWTSPlugin *plugin;
+ IWTSVirtualChannelManager *channel_mgr;
+ IWTSVirtualChannel *channel;
- BYTE presentation_id[16];
+ BYTE presentation_id[GUID_SIZE];
UINT32 stream_id;
};
@@ -67,20 +67,19 @@ struct _TSMF_PLUGIN
{
IWTSPlugin iface;
- TSMF_LISTENER_CALLBACK* listener_callback;
+ TSMF_LISTENER_CALLBACK *listener_callback;
- const char* decoder_name;
- const char* audio_name;
- const char* audio_device;
+ const char *decoder_name;
+ const char *audio_name;
+ const char *audio_device;
};
-void tsmf_playback_ack(IWTSVirtualChannelCallback* pChannelCallback,
- UINT32 message_id, UINT64 duration, UINT32 data_size)
+void tsmf_playback_ack(IWTSVirtualChannelCallback *pChannelCallback,
+ UINT32 message_id, UINT64 duration, UINT32 data_size)
{
- wStream* s;
- int status;
- TSMF_CHANNEL_CALLBACK* callback = (TSMF_CHANNEL_CALLBACK*) pChannelCallback;
-
+ wStream *s;
+ int status = -1;
+ TSMF_CHANNEL_CALLBACK *callback = (TSMF_CHANNEL_CALLBACK *) pChannelCallback;
s = Stream_New(NULL, 32);
Stream_Write_UINT32(s, TSMF_INTERFACE_CLIENT_NOTIFICATIONS | STREAM_ID_PROXY);
Stream_Write_UINT32(s, message_id);
@@ -88,71 +87,66 @@ void tsmf_playback_ack(IWTSVirtualChannelCallback* pChannelCallback,
Stream_Write_UINT32(s, callback->stream_id); /* StreamId */
Stream_Write_UINT64(s, duration); /* DataDuration */
Stream_Write_UINT64(s, data_size); /* cbData */
-
- DEBUG_DVC("response size %d", (int) Stream_GetPosition(s));
- status = callback->channel->Write(callback->channel, Stream_GetPosition(s), Stream_Buffer(s), NULL);
-
- if (status)
+ DEBUG_TSMF("response size %d", (int) Stream_GetPosition(s));
+ if(!callback || !callback->channel || !callback->channel->Write)
+ DEBUG_WARN("callback=%p, channel=%p, write=%p", callback,
+ callback->channel, callback->channel->Write);
+ else
+ status = callback->channel->Write(callback->channel,
+ Stream_GetPosition(s), Stream_Buffer(s), NULL);
+ if(status)
{
DEBUG_WARN("response error %d", status);
}
-
Stream_Free(s, TRUE);
}
-BOOL tsmf_push_event(IWTSVirtualChannelCallback* pChannelCallback, wMessage* event)
+BOOL tsmf_push_event(IWTSVirtualChannelCallback *pChannelCallback, wMessage *event)
{
int status;
- TSMF_CHANNEL_CALLBACK* callback = (TSMF_CHANNEL_CALLBACK*) pChannelCallback;
-
+ TSMF_CHANNEL_CALLBACK *callback = (TSMF_CHANNEL_CALLBACK *) pChannelCallback;
status = callback->channel_mgr->PushEvent(callback->channel_mgr, event);
-
- if (status)
+ if(status)
{
DEBUG_WARN("response error %d", status);
return FALSE;
}
-
return TRUE;
}
-static int tsmf_on_data_received(IWTSVirtualChannelCallback* pChannelCallback,
- UINT32 cbSize,
- BYTE* pBuffer)
+static int tsmf_on_data_received(IWTSVirtualChannelCallback *pChannelCallback,
+ UINT32 cbSize,
+ BYTE *pBuffer)
{
int length;
- wStream* input;
- wStream* output;
+ wStream *input;
+ wStream *output;
int status = -1;
TSMF_IFMAN ifman;
UINT32 MessageId;
UINT32 FunctionId;
UINT32 InterfaceId;
- TSMF_CHANNEL_CALLBACK* callback = (TSMF_CHANNEL_CALLBACK*) pChannelCallback;
-
+ TSMF_CHANNEL_CALLBACK *callback = (TSMF_CHANNEL_CALLBACK *) pChannelCallback;
/* 2.2.1 Shared Message Header (SHARED_MSG_HEADER) */
- if (cbSize < 12)
+ if(cbSize < 12)
{
DEBUG_WARN("invalid size. cbSize=%d", cbSize);
return 1;
}
-
- input = Stream_New((BYTE*) pBuffer, cbSize);
+ input = Stream_New((BYTE *) pBuffer, cbSize);
output = Stream_New(NULL, 256);
Stream_Seek(output, 8);
-
Stream_Read_UINT32(input, InterfaceId);
Stream_Read_UINT32(input, MessageId);
Stream_Read_UINT32(input, FunctionId);
- DEBUG_DVC("cbSize=%d InterfaceId=0x%X MessageId=0x%X FunctionId=0x%X",
- cbSize, InterfaceId, MessageId, FunctionId);
-
+ DEBUG_TSMF("cbSize=%d InterfaceId=0x%X MessageId=0x%X FunctionId=0x%X",
+ cbSize, InterfaceId, MessageId, FunctionId);
memset(&ifman, 0, sizeof(TSMF_IFMAN));
ifman.channel_callback = pChannelCallback;
- ifman.decoder_name = ((TSMF_PLUGIN*) callback->plugin)->decoder_name;
- ifman.audio_name = ((TSMF_PLUGIN*) callback->plugin)->audio_name;
- ifman.audio_device = ((TSMF_PLUGIN*) callback->plugin)->audio_device;
- memcpy(ifman.presentation_id, callback->presentation_id, 16);
+ ifman.decoder_name = ((TSMF_PLUGIN *) callback->plugin)->decoder_name;
+ ifman.audio_name = ((TSMF_PLUGIN *) callback->plugin)->audio_name;
+ ifman.audio_device = ((TSMF_PLUGIN *) callback->plugin)->audio_device;
+ memcpy(ifman.presentation_id, callback->presentation_id, GUID_SIZE);
ifman.stream_id = callback->stream_id;
ifman.message_id = MessageId;
ifman.input = input;
@@ -160,139 +154,108 @@ static int tsmf_on_data_received(IWTSVirtualChannelCallback* pChannelCallback,
ifman.output = output;
ifman.output_pending = FALSE;
ifman.output_interface_id = InterfaceId;
-
- switch (InterfaceId)
+ switch(InterfaceId)
{
case TSMF_INTERFACE_CAPABILITIES | STREAM_ID_NONE:
-
- switch (FunctionId)
+ switch(FunctionId)
{
case RIM_EXCHANGE_CAPABILITY_REQUEST:
status = tsmf_ifman_rim_exchange_capability_request(&ifman);
break;
-
default:
break;
}
break;
-
case TSMF_INTERFACE_DEFAULT | STREAM_ID_PROXY:
-
- switch (FunctionId)
+ switch(FunctionId)
{
case SET_CHANNEL_PARAMS:
- memcpy(callback->presentation_id, Stream_Pointer(input), 16);
- Stream_Seek(input, 16);
+ memcpy(callback->presentation_id, Stream_Pointer(input), GUID_SIZE);
+ Stream_Seek(input, GUID_SIZE);
Stream_Read_UINT32(input, callback->stream_id);
- DEBUG_DVC("SET_CHANNEL_PARAMS StreamId=%d", callback->stream_id);
+ DEBUG_TSMF("SET_CHANNEL_PARAMS StreamId=%d", callback->stream_id);
ifman.output_pending = TRUE;
status = 0;
break;
-
case EXCHANGE_CAPABILITIES_REQ:
status = tsmf_ifman_exchange_capability_request(&ifman);
break;
-
case CHECK_FORMAT_SUPPORT_REQ:
status = tsmf_ifman_check_format_support_request(&ifman);
break;
-
case ON_NEW_PRESENTATION:
status = tsmf_ifman_on_new_presentation(&ifman);
break;
-
case ADD_STREAM:
status = tsmf_ifman_add_stream(&ifman);
break;
-
case SET_TOPOLOGY_REQ:
status = tsmf_ifman_set_topology_request(&ifman);
break;
-
case REMOVE_STREAM:
status = tsmf_ifman_remove_stream(&ifman);
break;
-
case SET_SOURCE_VIDEO_RECT:
status = tsmf_ifman_set_source_video_rect(&ifman);
break;
-
case SHUTDOWN_PRESENTATION_REQ:
status = tsmf_ifman_shutdown_presentation(&ifman);
break;
-
case ON_STREAM_VOLUME:
status = tsmf_ifman_on_stream_volume(&ifman);
break;
-
case ON_CHANNEL_VOLUME:
status = tsmf_ifman_on_channel_volume(&ifman);
break;
-
case SET_VIDEO_WINDOW:
status = tsmf_ifman_set_video_window(&ifman);
break;
-
case UPDATE_GEOMETRY_INFO:
status = tsmf_ifman_update_geometry_info(&ifman);
break;
-
case SET_ALLOCATOR:
status = tsmf_ifman_set_allocator(&ifman);
break;
-
case NOTIFY_PREROLL:
status = tsmf_ifman_notify_preroll(&ifman);
break;
-
case ON_SAMPLE:
status = tsmf_ifman_on_sample(&ifman);
break;
-
case ON_FLUSH:
status = tsmf_ifman_on_flush(&ifman);
break;
-
case ON_END_OF_STREAM:
status = tsmf_ifman_on_end_of_stream(&ifman);
break;
-
case ON_PLAYBACK_STARTED:
status = tsmf_ifman_on_playback_started(&ifman);
break;
-
case ON_PLAYBACK_PAUSED:
status = tsmf_ifman_on_playback_paused(&ifman);
break;
-
case ON_PLAYBACK_RESTARTED:
status = tsmf_ifman_on_playback_restarted(&ifman);
break;
-
case ON_PLAYBACK_STOPPED:
status = tsmf_ifman_on_playback_stopped(&ifman);
break;
-
case ON_PLAYBACK_RATE_CHANGED:
status = tsmf_ifman_on_playback_rate_changed(&ifman);
break;
-
default:
break;
}
break;
-
default:
break;
}
-
Stream_Free(input, FALSE);
input = NULL;
ifman.input = NULL;
-
- if (status == -1)
+ if(status == -1)
{
- switch (FunctionId)
+ switch(FunctionId)
{
case RIMCALL_RELEASE:
/* [MS-RDPEXPS] 2.2.2.2 Interface Release (IFACE_RELEASE)
@@ -300,121 +263,98 @@ static int tsmf_on_data_received(IWTSVirtualChannelCallback* pChannelCallback,
status = 0;
ifman.output_pending = 1;
break;
-
case RIMCALL_QUERYINTERFACE:
/* [MS-RDPEXPS] 2.2.2.1.2 Query Interface Response (QI_RSP)
This message is not supported in this channel. */
status = 0;
break;
}
-
- if (status == -1)
+ if(status == -1)
{
DEBUG_WARN("InterfaceId 0x%X FunctionId 0x%X not processed.",
- InterfaceId, FunctionId);
+ InterfaceId, FunctionId);
/* When a request is not implemented we return empty response indicating error */
}
status = 0;
}
-
- if (status == 0 && !ifman.output_pending)
+ if(status == 0 && !ifman.output_pending)
{
/* Response packet does not have FunctionId */
length = Stream_GetPosition(output);
Stream_SetPosition(output, 0);
Stream_Write_UINT32(output, ifman.output_interface_id);
Stream_Write_UINT32(output, MessageId);
-
- DEBUG_DVC("response size %d", length);
+ DEBUG_TSMF("response size %d", length);
status = callback->channel->Write(callback->channel, length, Stream_Buffer(output), NULL);
- if (status)
+ if(status)
{
DEBUG_WARN("response error %d", status);
}
}
-
Stream_Free(output, TRUE);
-
return status;
}
-static int tsmf_on_close(IWTSVirtualChannelCallback* pChannelCallback)
+static int tsmf_on_close(IWTSVirtualChannelCallback *pChannelCallback)
{
- TSMF_STREAM* stream;
- TSMF_PRESENTATION* presentation;
- TSMF_CHANNEL_CALLBACK* callback = (TSMF_CHANNEL_CALLBACK*) pChannelCallback;
-
- DEBUG_DVC("");
-
- if (callback->stream_id)
+ TSMF_STREAM *stream;
+ TSMF_PRESENTATION *presentation;
+ TSMF_CHANNEL_CALLBACK *callback = (TSMF_CHANNEL_CALLBACK *) pChannelCallback;
+ DEBUG_TSMF("");
+ if(callback->stream_id)
{
presentation = tsmf_presentation_find_by_id(callback->presentation_id);
-
- if (presentation)
+ if(presentation)
{
stream = tsmf_stream_find_by_id(presentation, callback->stream_id);
-
- if (stream)
+ if(stream)
tsmf_stream_free(stream);
}
}
-
free(pChannelCallback);
-
return 0;
}
-static int tsmf_on_new_channel_connection(IWTSListenerCallback* pListenerCallback,
- IWTSVirtualChannel* pChannel,
- BYTE* Data,
- int* pbAccept,
- IWTSVirtualChannelCallback** ppCallback)
+static int tsmf_on_new_channel_connection(IWTSListenerCallback *pListenerCallback,
+ IWTSVirtualChannel *pChannel,
+ BYTE *Data,
+ int *pbAccept,
+ IWTSVirtualChannelCallback **ppCallback)
{
- TSMF_CHANNEL_CALLBACK* callback;
- TSMF_LISTENER_CALLBACK* listener_callback = (TSMF_LISTENER_CALLBACK*) pListenerCallback;
-
- DEBUG_DVC("");
-
- callback = (TSMF_CHANNEL_CALLBACK*) malloc(sizeof(TSMF_CHANNEL_CALLBACK));
+ TSMF_CHANNEL_CALLBACK *callback;
+ TSMF_LISTENER_CALLBACK *listener_callback = (TSMF_LISTENER_CALLBACK *) pListenerCallback;
+ DEBUG_TSMF("");
+ callback = (TSMF_CHANNEL_CALLBACK *) malloc(sizeof(TSMF_CHANNEL_CALLBACK));
ZeroMemory(callback, sizeof(TSMF_CHANNEL_CALLBACK));
-
callback->iface.OnDataReceived = tsmf_on_data_received;
callback->iface.OnClose = tsmf_on_close;
callback->plugin = listener_callback->plugin;
callback->channel_mgr = listener_callback->channel_mgr;
callback->channel = pChannel;
- *ppCallback = (IWTSVirtualChannelCallback*) callback;
-
+ *ppCallback = (IWTSVirtualChannelCallback *) callback;
return 0;
}
-static int tsmf_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelManager* pChannelMgr)
+static int tsmf_plugin_initialize(IWTSPlugin *pPlugin, IWTSVirtualChannelManager *pChannelMgr)
{
- TSMF_PLUGIN* tsmf = (TSMF_PLUGIN*) pPlugin;
-
- DEBUG_DVC("");
-
- tsmf->listener_callback = (TSMF_LISTENER_CALLBACK*) malloc(sizeof(TSMF_LISTENER_CALLBACK));
+ TSMF_PLUGIN *tsmf = (TSMF_PLUGIN *) pPlugin;
+ DEBUG_TSMF("");
+ tsmf->listener_callback = (TSMF_LISTENER_CALLBACK *) malloc(sizeof(TSMF_LISTENER_CALLBACK));
ZeroMemory(tsmf->listener_callback, sizeof(TSMF_LISTENER_CALLBACK));
-
tsmf->listener_callback->iface.OnNewChannelConnection = tsmf_on_new_channel_connection;
tsmf->listener_callback->plugin = pPlugin;
tsmf->listener_callback->channel_mgr = pChannelMgr;
-
return pChannelMgr->CreateListener(pChannelMgr, "TSMF", 0,
- (IWTSListenerCallback*) tsmf->listener_callback, NULL);
+ (IWTSListenerCallback *) tsmf->listener_callback, NULL);
}
-static int tsmf_plugin_terminated(IWTSPlugin* pPlugin)
+static int tsmf_plugin_terminated(IWTSPlugin *pPlugin)
{
- TSMF_PLUGIN* tsmf = (TSMF_PLUGIN*) pPlugin;
-
- DEBUG_DVC("");
-
- if (tsmf->listener_callback)
+ TSMF_PLUGIN *tsmf = (TSMF_PLUGIN *) pPlugin;
+ DEBUG_TSMF("");
+ if(tsmf->listener_callback)
free(tsmf->listener_callback);
free(tsmf);
-
return 0;
}
@@ -426,27 +366,21 @@ COMMAND_LINE_ARGUMENT_A tsmf_args[] =
{ NULL, 0, NULL, NULL, NULL, -1, NULL, NULL }
};
-static void tsmf_process_addin_args(IWTSPlugin* pPlugin, ADDIN_ARGV* args)
+static void tsmf_process_addin_args(IWTSPlugin *pPlugin, ADDIN_ARGV *args)
{
int status;
DWORD flags;
- COMMAND_LINE_ARGUMENT_A* arg;
- TSMF_PLUGIN* tsmf = (TSMF_PLUGIN*) pPlugin;
-
+ COMMAND_LINE_ARGUMENT_A *arg;
+ TSMF_PLUGIN *tsmf = (TSMF_PLUGIN *) pPlugin;
flags = COMMAND_LINE_SIGIL_NONE | COMMAND_LINE_SEPARATOR_COLON;
-
- status = CommandLineParseArgumentsA(args->argc, (const char**) args->argv,
- tsmf_args, flags, tsmf, NULL, NULL);
-
+ status = CommandLineParseArgumentsA(args->argc, (const char **) args->argv,
+ tsmf_args, flags, tsmf, NULL, NULL);
arg = tsmf_args;
-
do
{
- if (!(arg->Flags & COMMAND_LINE_VALUE_PRESENT))
+ if(!(arg->Flags & COMMAND_LINE_VALUE_PRESENT))
continue;
-
CommandLineSwitchStart(arg)
-
CommandLineSwitchCase(arg, "audio")
{
tsmf->audio_name = _strdup(arg->Value);
@@ -461,43 +395,35 @@ static void tsmf_process_addin_args(IWTSPlugin* pPlugin, ADDIN_ARGV* args)
}
CommandLineSwitchDefault(arg)
{
-
}
-
CommandLineSwitchEnd(arg)
}
- while ((arg = CommandLineFindNextArgumentA(arg)) != NULL);
+ while((arg = CommandLineFindNextArgumentA(arg)) != NULL);
}
#ifdef STATIC_CHANNELS
#define DVCPluginEntry tsmf_DVCPluginEntry
#endif
-int DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints)
+int DVCPluginEntry(IDRDYNVC_ENTRY_POINTS *pEntryPoints)
{
int status = 0;
- TSMF_PLUGIN* tsmf;
-
- tsmf = (TSMF_PLUGIN*) pEntryPoints->GetPlugin(pEntryPoints, "tsmf");
-
- if (tsmf == NULL)
+ TSMF_PLUGIN *tsmf;
+ tsmf = (TSMF_PLUGIN *) pEntryPoints->GetPlugin(pEntryPoints, "tsmf");
+ if(tsmf == NULL)
{
- tsmf = (TSMF_PLUGIN*) malloc(sizeof(TSMF_PLUGIN));
+ tsmf = (TSMF_PLUGIN *) malloc(sizeof(TSMF_PLUGIN));
ZeroMemory(tsmf, sizeof(TSMF_PLUGIN));
-
tsmf->iface.Initialize = tsmf_plugin_initialize;
tsmf->iface.Connected = NULL;
tsmf->iface.Disconnected = NULL;
tsmf->iface.Terminated = tsmf_plugin_terminated;
- status = pEntryPoints->RegisterPlugin(pEntryPoints, "tsmf", (IWTSPlugin*) tsmf);
-
+ status = pEntryPoints->RegisterPlugin(pEntryPoints, "tsmf", (IWTSPlugin *) tsmf);
tsmf_media_init();
}
-
- if (status == 0)
+ if(status == 0)
{
- tsmf_process_addin_args((IWTSPlugin*) tsmf, pEntryPoints->GetPluginData(pEntryPoints));
+ tsmf_process_addin_args((IWTSPlugin *) tsmf, pEntryPoints->GetPluginData(pEntryPoints));
}
-
return status;
}
diff --git a/channels/tsmf/client/tsmf_media.c b/channels/tsmf/client/tsmf_media.c
index eece46b65..51465554b 100644
--- a/channels/tsmf/client/tsmf_media.c
+++ b/channels/tsmf/client/tsmf_media.c
@@ -22,6 +22,8 @@
#include "config.h"
#endif
+#include <assert.h>
+
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -52,33 +54,17 @@
#include "tsmf_codec.h"
#include "tsmf_media.h"
-#include <pthread.h>
-
#define AUDIO_TOLERANCE 10000000LL
struct _TSMF_PRESENTATION
{
BYTE presentation_id[GUID_SIZE];
- const char* audio_name;
- const char* audio_device;
+ const char *audio_name;
+ const char *audio_device;
int eos;
- UINT32 last_x;
- UINT32 last_y;
- UINT32 last_width;
- UINT32 last_height;
- UINT16 last_num_rects;
- RDP_RECT* last_rects;
-
- UINT32 output_x;
- UINT32 output_y;
- UINT32 output_width;
- UINT32 output_height;
- UINT16 output_num_rects;
- RDP_RECT* output_rects;
-
- IWTSVirtualChannelCallback* channel_callback;
+ IWTSVirtualChannelCallback *channel_callback;
UINT64 audio_start_time;
UINT64 audio_end_time;
@@ -86,26 +72,31 @@ struct _TSMF_PRESENTATION
UINT32 volume;
UINT32 muted;
- HANDLE mutex;
- HANDLE thread;
+ wArrayList *stream_list;
+
+ int x;
+ int y;
+ int width;
+ int height;
- wArrayList* stream_list;
+ int nr_rects;
+ void *rects;
};
struct _TSMF_STREAM
{
UINT32 stream_id;
- TSMF_PRESENTATION* presentation;
+ TSMF_PRESENTATION *presentation;
- ITSMFDecoder* decoder;
+ ITSMFDecoder *decoder;
int major_type;
int eos;
UINT32 width;
UINT32 height;
- ITSMFAudioDevice* audio;
+ ITSMFAudioDevice *audio;
UINT32 sample_rate;
UINT32 channels;
UINT32 bits_per_sample;
@@ -115,13 +106,13 @@ struct _TSMF_STREAM
/* Next sample should not start before this system time. */
UINT64 next_start_time;
- BOOL started;
-
- HANDLE thread;
+ HANDLE play_thread;
+ HANDLE ack_thread;
HANDLE stopEvent;
+ HANDLE ready;
- wQueue* sample_list;
- wQueue* sample_ack_list;
+ wQueue *sample_list;
+ wQueue *sample_ack_list;
};
struct _TSMF_SAMPLE
@@ -132,36 +123,37 @@ struct _TSMF_SAMPLE
UINT64 duration;
UINT32 extensions;
UINT32 data_size;
- BYTE* data;
+ BYTE *data;
UINT32 decoded_size;
UINT32 pixfmt;
- TSMF_STREAM* stream;
- IWTSVirtualChannelCallback* channel_callback;
+ TSMF_STREAM *stream;
+ IWTSVirtualChannelCallback *channel_callback;
UINT64 ack_time;
};
-static wArrayList* presentation_list = NULL;
-static UINT64 last_played_audio_time = 0;
-static HANDLE tsmf_mutex = NULL;
+static wArrayList *presentation_list = NULL;
static int TERMINATING = 0;
+static void _tsmf_presentation_free(TSMF_PRESENTATION *presentation);
+static void _tsmf_stream_free(TSMF_STREAM *stream);
+
static UINT64 get_current_time(void)
{
struct timeval tp;
-
gettimeofday(&tp, 0);
return ((UINT64)tp.tv_sec) * 10000000LL + ((UINT64)tp.tv_usec) * 10LL;
}
-static TSMF_SAMPLE* tsmf_stream_pop_sample(TSMF_STREAM* stream, int sync)
+static TSMF_SAMPLE *tsmf_stream_pop_sample(TSMF_STREAM *stream, int sync)
{
UINT32 index;
UINT32 count;
- TSMF_STREAM* s;
- TSMF_SAMPLE* sample;
+ TSMF_STREAM *s;
+ TSMF_SAMPLE *sample;
BOOL pending = FALSE;
- TSMF_PRESENTATION* presentation = stream->presentation;
+ TSMF_PRESENTATION *presentation = stream->presentation;
+ assert(stream);
if (Queue_Count(stream->sample_list) < 1)
return NULL;
@@ -178,18 +170,17 @@ static TSMF_SAMPLE* tsmf_stream_pop_sample(TSMF_STREAM* stream, int sync)
if (stream->last_end_time > AUDIO_TOLERANCE)
{
ArrayList_Lock(presentation->stream_list);
-
count = ArrayList_Count(presentation->stream_list);
for (index = 0; index < count; index++)
{
- s = (TSMF_STREAM*) ArrayList_GetItem(presentation->stream_list, index);
+ s = (TSMF_STREAM *) ArrayList_GetItem(presentation->stream_list, index);
if (s != stream && !s->eos && s->last_end_time &&
- s->last_end_time < stream->last_end_time - AUDIO_TOLERANCE)
+ s->last_end_time < stream->last_end_time - AUDIO_TOLERANCE)
{
- pending = TRUE;
- break;
+ pending = TRUE;
+ break;
}
}
@@ -203,7 +194,6 @@ static TSMF_SAMPLE* tsmf_stream_pop_sample(TSMF_STREAM* stream, int sync)
pending = TRUE;
}
}
-
}
}
}
@@ -211,7 +201,7 @@ static TSMF_SAMPLE* tsmf_stream_pop_sample(TSMF_STREAM* stream, int sync)
if (pending)
return NULL;
- sample = (TSMF_SAMPLE*) Queue_Dequeue(stream->sample_list);
+ sample = (TSMF_SAMPLE *) Queue_Dequeue(stream->sample_list);
if (sample && (sample->end_time > stream->last_end_time))
stream->last_end_time = sample->end_time;
@@ -219,99 +209,106 @@ static TSMF_SAMPLE* tsmf_stream_pop_sample(TSMF_STREAM* stream, int sync)
return sample;
}
-static void tsmf_sample_free(TSMF_SAMPLE* sample)
+static void tsmf_sample_free(void *arg)
{
+ TSMF_SAMPLE *sample = arg;
+ assert(sample);
+
if (sample->data)
free(sample->data);
free(sample);
}
-static void tsmf_sample_ack(TSMF_SAMPLE* sample)
+static void tsmf_sample_ack(TSMF_SAMPLE *sample)
{
+ assert(sample);
tsmf_playback_ack(sample->channel_callback, sample->sample_id, sample->duration, sample->data_size);
}
-static void tsmf_sample_queue_ack(TSMF_SAMPLE* sample)
+static void tsmf_sample_queue_ack(TSMF_SAMPLE *sample)
{
- TSMF_STREAM* stream = sample->stream;
-
- Queue_Enqueue(stream->sample_ack_list, sample);
+ assert(sample);
+ assert(sample->stream);
+ Queue_Enqueue(sample->stream->sample_ack_list, sample);
}
-static void tsmf_stream_process_ack(TSMF_STREAM* stream)
+static BOOL tsmf_stream_process_ack(void *arg, BOOL force)
{
- TSMF_SAMPLE* sample;
+ TSMF_STREAM *stream = arg;
+ TSMF_SAMPLE *sample;
UINT64 ack_time;
+ BOOL rc = FALSE;
+ assert(stream);
+ Queue_Lock(stream->sample_ack_list);
+ sample = (TSMF_SAMPLE *) Queue_Peek(stream->sample_ack_list);
- ack_time = get_current_time();
+ if (!sample)
+ goto finally;
- while ((Queue_Count(stream->sample_ack_list) > 0) && !(WaitForSingleObject(stream->stopEvent, 0) == WAIT_OBJECT_0))
+ if (!force)
{
- sample = (TSMF_SAMPLE*) Queue_Peek(stream->sample_ack_list);
-
- if (!sample || (sample->ack_time > ack_time))
- break;
+ ack_time = get_current_time();
- sample = Queue_Dequeue(stream->sample_ack_list);
-
- tsmf_sample_ack(sample);
- tsmf_sample_free(sample);
+ if (sample->ack_time > ack_time)
+ goto finally;
}
+
+ sample = Queue_Dequeue(stream->sample_ack_list);
+ tsmf_sample_ack(sample);
+ tsmf_sample_free(sample);
+finally:
+ Queue_Unlock(stream->sample_ack_list);
+ return rc;
}
-TSMF_PRESENTATION* tsmf_presentation_new(const BYTE* guid, IWTSVirtualChannelCallback* pChannelCallback)
+TSMF_PRESENTATION *tsmf_presentation_new(const BYTE *guid, IWTSVirtualChannelCallback *pChannelCallback)
{
- TSMF_PRESENTATION* presentation;
- pthread_t thid = pthread_self();
- FILE* fout = NULL;
- fout = fopen("/tmp/tsmf.tid", "wt");
-
- if (fout)
- {
- fprintf(fout, "%d\n", (int) (size_t) thid);
- fclose(fout);
- }
+ TSMF_PRESENTATION *presentation;
+ assert(guid);
+ assert(pChannelCallback);
+ presentation = (TSMF_PRESENTATION *) calloc(1, sizeof(TSMF_PRESENTATION));
- presentation = tsmf_presentation_find_by_id(guid);
-
- if (presentation)
+ if (!presentation)
{
- DEBUG_WARN("duplicated presentation id!");
+ DEBUG_WARN("calloc failed");
return NULL;
}
- presentation = (TSMF_PRESENTATION*) calloc(1, sizeof(TSMF_PRESENTATION));
-
CopyMemory(presentation->presentation_id, guid, GUID_SIZE);
presentation->channel_callback = pChannelCallback;
-
presentation->volume = 5000; /* 50% */
- presentation->muted = 0;
-
- presentation->mutex = CreateMutex(NULL, FALSE, NULL);
presentation->stream_list = ArrayList_New(TRUE);
- ArrayList_Object(presentation->stream_list)->fnObjectFree = (OBJECT_FREE_FN) tsmf_stream_free;
-
+ ArrayList_Object(presentation->stream_list)->fnObjectFree = (OBJECT_FREE_FN) _tsmf_stream_free;
ArrayList_Add(presentation_list, presentation);
-
return presentation;
}
-TSMF_PRESENTATION* tsmf_presentation_find_by_id(const BYTE* guid)
+static char *guid_to_string(const BYTE *guid, char *str, size_t len)
{
+ int i;
+ assert(guid);
+ assert(str);
+
+ for (i=0; i<GUID_SIZE && len > 2*i; i++)
+ snprintf(str + (2*i), len - 2*i, "%02X", guid[i]);
+
+ return str;
+}
+
+TSMF_PRESENTATION *tsmf_presentation_find_by_id(const BYTE *guid)
+{
+ char guid_str[GUID_SIZE * 2 + 1];
UINT32 index;
UINT32 count;
BOOL found = FALSE;
- TSMF_PRESENTATION* presentation;
-
+ TSMF_PRESENTATION *presentation;
ArrayList_Lock(presentation_list);
-
count = ArrayList_Count(presentation_list);
for (index = 0; index < count; index++)
{
- presentation = (TSMF_PRESENTATION*) ArrayList_GetItem(presentation_list, index);
+ presentation = (TSMF_PRESENTATION *) ArrayList_GetItem(presentation_list, index);
if (memcmp(presentation->presentation_id, guid, GUID_SIZE) == 0)
{
@@ -322,122 +319,47 @@ TSMF_PRESENTATION* tsmf_presentation_find_by_id(const BYTE* guid)
ArrayList_Unlock(presentation_list);
- return (found) ? presentation : NULL;
-}
-
-static void tsmf_presentation_restore_last_video_frame(TSMF_PRESENTATION* presentation)
-{
- RDP_REDRAW_EVENT* revent;
+ if (!found)
+ DEBUG_WARN("presentation id %s not found", guid_to_string(guid, guid_str, sizeof(guid_str)));
- if (presentation->last_width && presentation->last_height)
- {
- revent = (RDP_REDRAW_EVENT*) freerdp_event_new(TsmfChannel_Class, TsmfChannel_Redraw,
- NULL, NULL);
-
- revent->x = presentation->last_x;
- revent->y = presentation->last_y;
- revent->width = presentation->last_width;
- revent->height = presentation->last_height;
-
- if (!tsmf_push_event(presentation->channel_callback, (wMessage*) revent))
- {
- freerdp_event_free((wMessage*) revent);
- }
-
- presentation->last_x = 0;
- presentation->last_y = 0;
- presentation->last_width = 0;
- presentation->last_height = 0;
- }
+ return (found) ? presentation : NULL;
}
-static void tsmf_sample_playback_video(TSMF_SAMPLE* sample)
+static void tsmf_sample_playback_video(TSMF_SAMPLE *sample)
{
UINT64 t;
- RDP_VIDEO_FRAME_EVENT* vevent;
- TSMF_STREAM* stream = sample->stream;
- TSMF_PRESENTATION* presentation = stream->presentation;
-
- DEBUG_DVC("MessageId %d EndTime %d data_size %d consumed.",
- sample->sample_id, (int)sample->end_time, sample->data_size);
+ RDP_VIDEO_FRAME_EVENT *vevent;
+ TSMF_STREAM *stream = sample->stream;
+ TSMF_PRESENTATION *presentation = stream->presentation;
+ DEBUG_TSMF("MessageId %d EndTime %d data_size %d consumed.",
+ sample->sample_id, (int)sample->end_time, sample->data_size);
if (sample->data)
{
t = get_current_time();
if (stream->next_start_time > t &&
- (sample->end_time >= presentation->audio_start_time ||
- sample->end_time < stream->last_end_time))
+ (sample->end_time >= presentation->audio_start_time ||
+ sample->end_time < stream->last_end_time))
{
USleep((stream->next_start_time - t) / 10);
}
- stream->next_start_time = t + sample->duration - 50000;
-
- if (presentation->last_x != presentation->output_x ||
- presentation->last_y != presentation->output_y ||
- presentation->last_width != presentation->output_width ||
- presentation->last_height != presentation->output_height ||
- presentation->last_num_rects != presentation->output_num_rects ||
- (presentation->last_rects && presentation->output_rects &&
- memcmp(presentation->last_rects, presentation->output_rects,
- presentation->last_num_rects * sizeof(RDP_RECT)) != 0))
- {
- tsmf_presentation_restore_last_video_frame(presentation);
-
- presentation->last_x = presentation->output_x;
- presentation->last_y = presentation->output_y;
- presentation->last_width = presentation->output_width;
- presentation->last_height = presentation->output_height;
-
- if (presentation->last_rects)
- {
- free(presentation->last_rects);
- presentation->last_rects = NULL;
- }
-
- presentation->last_num_rects = presentation->output_num_rects;
-
- if (presentation->last_num_rects > 0)
- {
- presentation->last_rects = malloc(presentation->last_num_rects * sizeof(RDP_RECT));
- ZeroMemory(presentation->last_rects, presentation->last_num_rects * sizeof(RDP_RECT));
-
- memcpy(presentation->last_rects, presentation->output_rects,
- presentation->last_num_rects * sizeof(RDP_RECT));
- }
- }
-
- vevent = (RDP_VIDEO_FRAME_EVENT*) freerdp_event_new(TsmfChannel_Class, TsmfChannel_VideoFrame,
- NULL, NULL);
+ stream->next_start_time = t + sample->duration - 50000;
+ vevent = (RDP_VIDEO_FRAME_EVENT *) freerdp_event_new(TsmfChannel_Class, TsmfChannel_VideoFrame,
+ NULL, NULL);
vevent->frame_data = sample->data;
vevent->frame_size = sample->decoded_size;
vevent->frame_pixfmt = sample->pixfmt;
vevent->frame_width = sample->stream->width;
vevent->frame_height = sample->stream->height;
- vevent->x = presentation->output_x;
- vevent->y = presentation->output_y;
- vevent->width = presentation->output_width;
- vevent->height = presentation->output_height;
-
- if (presentation->output_num_rects > 0)
- {
- vevent->num_visible_rects = presentation->output_num_rects;
-
- vevent->visible_rects = (RDP_RECT*) malloc(presentation->output_num_rects * sizeof(RDP_RECT));
- ZeroMemory(vevent->visible_rects, presentation->output_num_rects * sizeof(RDP_RECT));
-
- memcpy(vevent->visible_rects, presentation->output_rects,
- presentation->output_num_rects * sizeof(RDP_RECT));
- }
-
/* The frame data ownership is passed to the event object, and is freed after the event is processed. */
sample->data = NULL;
sample->decoded_size = 0;
- if (!tsmf_push_event(sample->channel_callback, (wMessage*) vevent))
+ if (!tsmf_push_event(sample->channel_callback, (wMessage *) vevent))
{
- freerdp_event_free((wMessage*) vevent);
+ freerdp_event_free((wMessage *) vevent);
}
#if 0
@@ -445,7 +367,8 @@ static void tsmf_sample_playback_video(TSMF_SAMPLE* sample)
extract the Y values to create a grayscale image. */
static int frame_id = 0;
char buf[100];
- FILE * fp;
+ FILE *fp;
+
if ((frame_id % 30) == 0)
{
snprintf(buf, sizeof(buf), "/tmp/FreeRDP_Frame_%d.ppm", frame_id);
@@ -458,23 +381,23 @@ static void tsmf_sample_playback_video(TSMF_SAMPLE* sample)
fflush(fp);
fclose(fp);
}
+
frame_id++;
#endif
}
}
-static void tsmf_sample_playback_audio(TSMF_SAMPLE* sample)
+static void tsmf_sample_playback_audio(TSMF_SAMPLE *sample)
{
UINT64 latency = 0;
- TSMF_STREAM* stream = sample->stream;
-
- DEBUG_DVC("MessageId %d EndTime %d consumed.",
- sample->sample_id, (int)sample->end_time);
+ TSMF_STREAM *stream = sample->stream;
+ DEBUG_TSMF("MessageId %d EndTime %d consumed.",
+ sample->sample_id, (int)sample->end_time);
if (sample->stream->audio && sample->data)
{
sample->stream->audio->Play(sample->stream->audio,
- sample->data, sample->decoded_size);
+ sample->data, sample->decoded_size);
sample->data = NULL;
sample->decoded_size = 0;
@@ -492,27 +415,26 @@ static void tsmf_sample_playback_audio(TSMF_SAMPLE* sample)
stream->presentation->audio_end_time = sample->end_time + latency;
}
-static void tsmf_sample_playback(TSMF_SAMPLE* sample)
+static void tsmf_sample_playback(TSMF_SAMPLE *sample)
{
BOOL ret = FALSE;
UINT32 width;
UINT32 height;
UINT32 pixfmt = 0;
- TSMF_STREAM* stream = sample->stream;
+ TSMF_STREAM *stream = sample->stream;
if (stream->decoder)
{
if (stream->decoder->DecodeEx)
ret = stream->decoder->DecodeEx(stream->decoder, sample->data, sample->data_size, sample->extensions,
- sample->start_time, sample->end_time, sample->duration);
+ sample->start_time, sample->end_time, sample->duration);
else
ret = stream->decoder->Decode(stream->decoder, sample->data, sample->data_size, sample->extensions);
}
if (!ret)
{
- tsmf_sample_ack(sample);
- tsmf_sample_free(sample);
+ tsmf_sample_queue_ack(sample);
return;
}
@@ -524,22 +446,25 @@ static void tsmf_sample_playback(TSMF_SAMPLE* sample)
if (stream->decoder->GetDecodedFormat)
{
pixfmt = stream->decoder->GetDecodedFormat(stream->decoder);
+
if (pixfmt == ((UINT32) -1))
{
- tsmf_sample_ack(sample);
- tsmf_sample_free(sample);
+ tsmf_sample_queue_ack(sample);
return;
}
+
sample->pixfmt = pixfmt;
}
ret = FALSE ;
+
if (stream->decoder->GetDecodedDimension)
{
ret = stream->decoder->GetDecodedDimension(stream->decoder, &width, &height);
+
if (ret && (width != stream->width || height != stream->height))
{
- DEBUG_DVC("video dimension changed to %d x %d", width, height);
+ DEBUG_TSMF("video dimension changed to %d x %d", width, height);
stream->width = width;
stream->height = height;
}
@@ -549,13 +474,14 @@ static void tsmf_sample_playback(TSMF_SAMPLE* sample)
if (stream->decoder->GetDecodedData)
{
sample->data = stream->decoder->GetDecodedData(stream->decoder, &sample->decoded_size);
+
switch (sample->stream->major_type)
{
case TSMF_MAJOR_TYPE_VIDEO:
tsmf_sample_playback_video(sample);
- tsmf_sample_ack(sample);
- tsmf_sample_free(sample);
+ tsmf_sample_queue_ack(sample);
break;
+
case TSMF_MAJOR_TYPE_AUDIO:
tsmf_sample_playback_audio(sample);
tsmf_sample_queue_ack(sample);
@@ -564,157 +490,124 @@ static void tsmf_sample_playback(TSMF_SAMPLE* sample)
}
else
{
- TSMF_STREAM * stream = sample->stream;
+ TSMF_STREAM *stream = sample->stream;
UINT64 ack_anticipation_time = get_current_time();
UINT64 currentRunningTime = sample->start_time;
- UINT32 bufferLevel = 0;
+ BOOL buffer_filled = TRUE;
+
if (stream->decoder->GetRunningTime)
{
currentRunningTime = stream->decoder->GetRunningTime(stream->decoder);
}
- if (stream->decoder->BufferLevel)
+
+ if (stream->decoder->BufferFilled)
{
- bufferLevel = stream->decoder->BufferLevel(stream->decoder);
+ buffer_filled = stream->decoder->BufferFilled(stream->decoder);
}
+
+ if (buffer_filled)
+ {
+ if (currentRunningTime > sample->start_time)
+ {
+ ack_anticipation_time += sample->duration;
+ }
+ else if (currentRunningTime == 0)
+ {
+ ack_anticipation_time += sample->duration;
+ }
+ else
+ {
+ ack_anticipation_time += (sample->start_time - currentRunningTime);
+ }
+ }
+ else
+ ack_anticipation_time += sample->duration / 2;
+
switch (sample->stream->major_type)
{
case TSMF_MAJOR_TYPE_VIDEO:
- {
- TSMF_PRESENTATION * presentation = sample->stream->presentation;
- /*
- * Tell gstreamer that presentation screen area has moved.
- * So it can render on the new area.
- */
- if (presentation->last_x != presentation->output_x || presentation->last_y != presentation->output_y ||
- presentation->last_width != presentation->output_width || presentation->last_height != presentation->output_height)
{
- presentation->last_x = presentation->output_x;
- presentation->last_y = presentation->output_y;
- presentation->last_width = presentation->output_width;
- presentation->last_height = presentation->output_height;
- if(stream->decoder->UpdateRenderingArea)
- {
- stream->decoder->UpdateRenderingArea(stream->decoder, presentation->output_x, presentation->output_y,
- presentation->output_width, presentation->output_height, presentation->output_num_rects, presentation->output_rects);
- }
+ break;
}
- if ( presentation->last_num_rects != presentation->output_num_rects || (presentation->last_rects && presentation->output_rects &&
- memcmp(presentation->last_rects, presentation->output_rects, presentation->last_num_rects * sizeof(RDP_RECT)) != 0))
- {
- if (presentation->last_rects)
- {
- free(presentation->last_rects);
- presentation->last_rects = NULL;
- }
- presentation->last_num_rects = presentation->output_num_rects;
-
- if (presentation->last_num_rects > 0)
- {
- presentation->last_rects = malloc(presentation->last_num_rects * sizeof(RDP_RECT));
- ZeroMemory(presentation->last_rects, presentation->last_num_rects * sizeof(RDP_RECT));
- memcpy(presentation->last_rects, presentation->output_rects, presentation->last_num_rects * sizeof(RDP_RECT));
- }
- if(stream->decoder->UpdateRenderingArea)
- {
- stream->decoder->UpdateRenderingArea(stream->decoder, presentation->output_x, presentation->output_y,
- presentation->output_width, presentation->output_height, presentation->output_num_rects, presentation->output_rects);
- }
- }
-
- if (bufferLevel < 24)
- {
- ack_anticipation_time += sample->duration;
- }
- else
- {
- if (currentRunningTime > sample->start_time)
- {
- ack_anticipation_time += sample->duration;
- }
- else if(currentRunningTime == 0)
- {
- ack_anticipation_time += sample->duration;
- }
- else
- {
- ack_anticipation_time += (sample->start_time - currentRunningTime);
- }
- }
- break;
- }
case TSMF_MAJOR_TYPE_AUDIO:
- {
- last_played_audio_time = currentRunningTime;
- if (bufferLevel < 2)
{
- ack_anticipation_time += sample->duration;
- }
- else
- {
- if (currentRunningTime > sample->start_time)
- {
- ack_anticipation_time += sample->duration;
- }
- else if(currentRunningTime == 0)
- {
- ack_anticipation_time += sample->duration;
- }
- else
- {
- ack_anticipation_time += (sample->start_time - currentRunningTime);
- }
+ break;
}
- break;
- }
}
+
sample->ack_time = ack_anticipation_time;
tsmf_sample_queue_ack(sample);
- }
+ }
}
-static void* tsmf_stream_playback_func(void* arg)
+static void *tsmf_stream_ack_func(void *arg)
{
- TSMF_SAMPLE* sample;
- TSMF_STREAM* stream = (TSMF_STREAM*) arg;
- TSMF_PRESENTATION* presentation = stream->presentation;
+ TSMF_STREAM *stream = (TSMF_STREAM *) arg;
+ HANDLE hdl[2];
+ DEBUG_TSMF("in %d", stream->stream_id);
+ hdl[0] = stream->stopEvent;
+ hdl[1] = Queue_Event(stream->sample_ack_list);
+
+ while (1)
+ {
+ DWORD ev = WaitForMultipleObjects(2, hdl, FALSE, INFINITE);
+
+ if (ev == WAIT_OBJECT_0)
+ break;
+
+ if (!stream->decoder)
+ continue;
+
+ if (stream->decoder->SetAckFunc)
+ continue;
+
+ if (tsmf_stream_process_ack(stream, FALSE))
+ break;
+ }
- DEBUG_DVC("in %d", stream->stream_id);
+ DEBUG_TSMF("out %d", stream->stream_id);
+ ExitThread(0);
+ return NULL;
+}
+
+static void *tsmf_stream_playback_func(void *arg)
+{
+ HANDLE hdl[2];
+ TSMF_SAMPLE *sample;
+ TSMF_STREAM *stream = (TSMF_STREAM *) arg;
+ TSMF_PRESENTATION *presentation = stream->presentation;
+ DEBUG_TSMF("in %d", stream->stream_id);
if (stream->major_type == TSMF_MAJOR_TYPE_AUDIO &&
- stream->sample_rate && stream->channels && stream->bits_per_sample)
+ stream->sample_rate && stream->channels && stream->bits_per_sample)
{
if (stream->decoder)
{
if (stream->decoder->GetDecodedData)
{
stream->audio = tsmf_load_audio_device(
- presentation->audio_name && presentation->audio_name[0] ? presentation->audio_name : NULL,
- presentation->audio_device && presentation->audio_device[0] ? presentation->audio_device : NULL);
+ presentation->audio_name && presentation->audio_name[0] ? presentation->audio_name : NULL,
+ presentation->audio_device && presentation->audio_device[0] ? presentation->audio_device : NULL);
+
if (stream->audio)
{
stream->audio->SetFormat(stream->audio,
- stream->sample_rate, stream->channels, stream->bits_per_sample);
+ stream->sample_rate, stream->channels, stream->bits_per_sample);
}
}
}
}
- while (!(WaitForSingleObject(stream->stopEvent, 0) == WAIT_OBJECT_0))
+ hdl[0] = stream->stopEvent;
+ hdl[1] = Queue_Event(stream->sample_list);
+
+ while (!(WaitForMultipleObjects(2, hdl, FALSE, INFINITE) == WAIT_OBJECT_0))
{
- tsmf_stream_process_ack(stream);
- sample = tsmf_stream_pop_sample(stream, 1);
+ sample = tsmf_stream_pop_sample(stream, 0);
if (sample)
tsmf_sample_playback(sample);
- else
- USleep(5000);
- }
-
- if (stream->eos || presentation->eos)
- {
- while ((sample = tsmf_stream_pop_sample(stream, 1)) != NULL)
- tsmf_sample_playback(sample);
}
if (stream->audio)
@@ -723,48 +616,36 @@ static void* tsmf_stream_playback_func(void* arg)
stream->audio = NULL;
}
- SetEvent(stream->stopEvent);
-
- DEBUG_DVC("out %d", stream->stream_id);
-
+ DEBUG_TSMF("out %d", stream->stream_id);
+ ExitThread(0);
return NULL;
}
-static void tsmf_stream_start(TSMF_STREAM* stream)
+static void tsmf_stream_start(TSMF_STREAM *stream)
{
- if (!stream->started)
+ if (!stream || !stream->presentation || !stream->decoder)
+ return;
+
+ if (stream->decoder->Control)
{
- ResumeThread(stream->thread);
- stream->started = TRUE;
+ stream->decoder->Control(stream->decoder, Control_Resume, NULL);
}
}
-static void tsmf_stream_stop(TSMF_STREAM* stream)
+static void tsmf_stream_stop(TSMF_STREAM *stream)
{
- if (!stream)
+ if (!stream || !stream->decoder)
return;
- if (!stream->decoder)
- return;
-
- if (stream->started)
- {
- SetEvent(stream->stopEvent);
- stream->started = FALSE;
- }
-
if (stream->decoder->Control)
{
- stream->decoder->Control(stream->decoder, Control_Flush, NULL);
+ stream->decoder->Control(stream->decoder, Control_Stop, NULL);
}
}
-static void tsmf_stream_pause(TSMF_STREAM* stream)
+static void tsmf_stream_pause(TSMF_STREAM *stream)
{
- if (!stream)
- return;
-
- if (!stream->decoder)
+ if (!stream || !stream->decoder)
return;
if (stream->decoder->Control)
@@ -773,25 +654,22 @@ static void tsmf_stream_pause(TSMF_STREAM* stream)
}
}
-static void tsmf_stream_restart(TSMF_STREAM* stream)
+static void tsmf_stream_restart(TSMF_STREAM *stream)
{
- if (!stream)
- return;
-
- if (!stream->decoder)
+ if (!stream || !stream->decoder)
return;
if (stream->decoder->Control)
{
- stream->decoder->Control(stream->decoder, Control_Restart, NULL);
+ stream->decoder->Control(stream->decoder, Control_Resume, NULL);
}
}
-static void tsmf_stream_change_volume(TSMF_STREAM* stream, UINT32 newVolume, UINT32 muted)
+static void tsmf_stream_change_volume(TSMF_STREAM *stream, UINT32 newVolume, UINT32 muted)
{
- if (!stream)
+ if (!stream || !stream->decoder)
return;
-
+
if (stream->decoder != NULL && stream->decoder->ChangeVolume)
{
stream->decoder->ChangeVolume(stream->decoder, newVolume, muted);
@@ -802,151 +680,169 @@ static void tsmf_stream_change_volume(TSMF_STREAM* stream, UINT32 newVolume, UIN
}
}
-void tsmf_presentation_volume_changed(TSMF_PRESENTATION* presentation, UINT32 newVolume, UINT32 muted)
+void tsmf_presentation_volume_changed(TSMF_PRESENTATION *presentation, UINT32 newVolume, UINT32 muted)
{
UINT32 index;
UINT32 count;
- TSMF_STREAM* stream;
-
+ TSMF_STREAM *stream;
presentation->volume = newVolume;
presentation->muted = muted;
-
ArrayList_Lock(presentation->stream_list);
-
count = ArrayList_Count(presentation->stream_list);
for (index = 0; index < count; index++)
{
- stream = (TSMF_STREAM*) ArrayList_GetItem(presentation->stream_list, index);
+ stream = (TSMF_STREAM *) ArrayList_GetItem(presentation->stream_list, index);
tsmf_stream_change_volume(stream, newVolume, muted);
}
ArrayList_Unlock(presentation->stream_list);
}
-void tsmf_presentation_paused(TSMF_PRESENTATION* presentation)
+void tsmf_presentation_paused(TSMF_PRESENTATION *presentation)
{
UINT32 index;
UINT32 count;
- TSMF_STREAM* stream;
-
+ TSMF_STREAM *stream;
ArrayList_Lock(presentation->stream_list);
-
count = ArrayList_Count(presentation->stream_list);
for (index = 0; index < count; index++)
{
- stream = (TSMF_STREAM*) ArrayList_GetItem(presentation->stream_list, index);
+ stream = (TSMF_STREAM *) ArrayList_GetItem(presentation->stream_list, index);
tsmf_stream_pause(stream);
}
ArrayList_Unlock(presentation->stream_list);
}
-void tsmf_presentation_restarted(TSMF_PRESENTATION* presentation)
+void tsmf_presentation_restarted(TSMF_PRESENTATION *presentation)
{
UINT32 index;
UINT32 count;
- TSMF_STREAM* stream;
-
+ TSMF_STREAM *stream;
ArrayList_Lock(presentation->stream_list);
-
count = ArrayList_Count(presentation->stream_list);
for (index = 0; index < count; index++)
{
- stream = (TSMF_STREAM*) ArrayList_GetItem(presentation->stream_list, index);
+ stream = (TSMF_STREAM *) ArrayList_GetItem(presentation->stream_list, index);
tsmf_stream_restart(stream);
}
ArrayList_Unlock(presentation->stream_list);
}
-void tsmf_presentation_start(TSMF_PRESENTATION* presentation)
+void tsmf_presentation_start(TSMF_PRESENTATION *presentation)
{
UINT32 index;
UINT32 count;
- TSMF_STREAM* stream;
-
+ TSMF_STREAM *stream;
ArrayList_Lock(presentation->stream_list);
-
count = ArrayList_Count(presentation->stream_list);
for (index = 0; index < count; index++)
{
- stream = (TSMF_STREAM*) ArrayList_GetItem(presentation->stream_list, index);
+ stream = (TSMF_STREAM *) ArrayList_GetItem(presentation->stream_list, index);
tsmf_stream_start(stream);
}
ArrayList_Unlock(presentation->stream_list);
}
-void tsmf_presentation_stop(TSMF_PRESENTATION* presentation)
+void tsmf_presentation_sync(TSMF_PRESENTATION *presentation)
{
UINT32 index;
UINT32 count;
- TSMF_STREAM* stream;
+ ArrayList_Lock(presentation->stream_list);
+ count = ArrayList_Count(presentation->stream_list);
- tsmf_presentation_flush(presentation);
+ for (index = 0; index < count; index++)
+ {
+ TSMF_STREAM *stream = (TSMF_STREAM *) ArrayList_GetItem(presentation->stream_list, index);
+ WaitForSingleObject(stream->ready, 500);
+ }
- ArrayList_Lock(presentation->stream_list);
+ ArrayList_Unlock(presentation->stream_list);
+}
+void tsmf_presentation_stop(TSMF_PRESENTATION *presentation)
+{
+ UINT32 index;
+ UINT32 count;
+ TSMF_STREAM *stream;
+ tsmf_presentation_flush(presentation);
+ ArrayList_Lock(presentation->stream_list);
count = ArrayList_Count(presentation->stream_list);
for (index = 0; index < count; index++)
{
- stream = (TSMF_STREAM*) ArrayList_GetItem(presentation->stream_list, index);
+ stream = (TSMF_STREAM *) ArrayList_GetItem(presentation->stream_list, index);
tsmf_stream_stop(stream);
}
ArrayList_Unlock(presentation->stream_list);
+}
- tsmf_presentation_restore_last_video_frame(presentation);
+void tsmf_presentation_set_geometry_info(TSMF_PRESENTATION *presentation,
+ UINT32 x, UINT32 y, UINT32 width, UINT32 height, int num_rects, RDP_RECT *rects)
+{
+ UINT32 index;
+ UINT32 count;
+ TSMF_STREAM *stream;
+
+ /* The server may send messages with invalid width / height.
+ * Ignore those messages. */
+ if (!width || !height)
+ return;
- if (presentation->last_rects)
+ if ((width == presentation->width) && (height == presentation->height) &&
+ (x == presentation->x) && (y == presentation->y) &&
+ (num_rects == presentation->nr_rects) &&
+ (0 == memcmp(rects, presentation->rects, num_rects * sizeof(RDP_RECT))))
{
- free(presentation->last_rects);
- presentation->last_rects = NULL;
+ return;
}
- presentation->last_num_rects = 0;
+ presentation->x = x;
+ presentation->y = y;
+ presentation->width = width;
+ presentation->height = height;
+ presentation->nr_rects = num_rects;
+ presentation->rects = realloc(presentation->rects, sizeof(RDP_RECT) * num_rects);
- if (presentation->output_rects)
- {
- free(presentation->output_rects);
- presentation->output_rects = NULL;
- }
+ if (presentation->rects)
+ memcpy(presentation->rects, rects, sizeof(RDP_RECT) * num_rects);
- presentation->output_num_rects = 0;
-}
+ ArrayList_Lock(presentation->stream_list);
+ count = ArrayList_Count(presentation->stream_list);
-void tsmf_presentation_set_geometry_info(TSMF_PRESENTATION* presentation,
- UINT32 x, UINT32 y, UINT32 width, UINT32 height, int num_rects, RDP_RECT* rects)
-{
- presentation->output_x = x;
- presentation->output_y = y;
- presentation->output_width = width;
- presentation->output_height = height;
+ for (index = 0; index < count; index++)
+ {
+ stream = (TSMF_STREAM *) ArrayList_GetItem(presentation->stream_list, index);
- if (presentation->output_rects)
- free(presentation->output_rects);
+ if (!stream->decoder)
+ continue;
- presentation->output_rects = rects;
- presentation->output_num_rects = num_rects;
+ if (stream->decoder->UpdateRenderingArea)
+ {
+ stream->decoder->UpdateRenderingArea(stream->decoder, x, y, width, height, num_rects, rects);
+ }
+ }
+
+ ArrayList_Unlock(presentation->stream_list);
}
-void tsmf_presentation_set_audio_device(TSMF_PRESENTATION* presentation, const char* name, const char* device)
+void tsmf_presentation_set_audio_device(TSMF_PRESENTATION *presentation, const char *name, const char *device)
{
presentation->audio_name = name;
presentation->audio_device = device;
}
-static void tsmf_stream_flush(TSMF_STREAM* stream)
+static void tsmf_stream_flush(TSMF_STREAM *stream)
{
//TSMF_SAMPLE* sample;
-
/* TODO: free lists */
-
if (stream->audio)
stream->audio->Flush(stream->audio);
@@ -961,45 +857,47 @@ static void tsmf_stream_flush(TSMF_STREAM* stream)
}
}
-void tsmf_presentation_flush(TSMF_PRESENTATION* presentation)
+void tsmf_presentation_flush(TSMF_PRESENTATION *presentation)
{
UINT32 index;
UINT32 count;
- TSMF_STREAM * stream;
-
+ TSMF_STREAM *stream;
ArrayList_Lock(presentation->stream_list);
-
count = ArrayList_Count(presentation->stream_list);
for (index = 0; index < count; index++)
{
- stream = (TSMF_STREAM*) ArrayList_GetItem(presentation->stream_list, index);
+ stream = (TSMF_STREAM *) ArrayList_GetItem(presentation->stream_list, index);
tsmf_stream_flush(stream);
}
ArrayList_Unlock(presentation->stream_list);
-
presentation->eos = 0;
presentation->audio_start_time = 0;
presentation->audio_end_time = 0;
}
-void tsmf_presentation_free(TSMF_PRESENTATION* presentation)
+void _tsmf_presentation_free(TSMF_PRESENTATION *presentation)
{
tsmf_presentation_stop(presentation);
-
- ArrayList_Remove(presentation_list, presentation);
+ ArrayList_Clear(presentation->stream_list);
ArrayList_Free(presentation->stream_list);
- CloseHandle(presentation->mutex);
+ if (presentation->rects)
+ free(presentation->rects);
+ memset(presentation, 0, sizeof(TSMF_PRESENTATION));
free(presentation);
}
-TSMF_STREAM* tsmf_stream_new(TSMF_PRESENTATION* presentation, UINT32 stream_id)
+void tsmf_presentation_free(TSMF_PRESENTATION *presentation)
{
- TSMF_STREAM* stream;
+ ArrayList_Remove(presentation_list, presentation);
+}
+TSMF_STREAM *tsmf_stream_new(TSMF_PRESENTATION *presentation, UINT32 stream_id)
+{
+ TSMF_STREAM *stream;
stream = tsmf_stream_find_by_id(presentation, stream_id);
if (stream)
@@ -1008,42 +906,42 @@ TSMF_STREAM* tsmf_stream_new(TSMF_PRESENTATION* presentation, UINT32 stream_id)
return NULL;
}
- stream = (TSMF_STREAM*) malloc(sizeof(TSMF_STREAM));
- ZeroMemory(stream, sizeof(TSMF_STREAM));
+ stream = (TSMF_STREAM *) calloc(1, sizeof(TSMF_STREAM));
+
+ if (!stream)
+ {
+ DEBUG_WARN("Calloc failed");
+ return NULL;
+ }
stream->stream_id = stream_id;
stream->presentation = presentation;
-
- stream->started = FALSE;
-
stream->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
- stream->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) tsmf_stream_playback_func, stream, CREATE_SUSPENDED, NULL);
-
+ stream->ready = CreateEvent(NULL, TRUE, TRUE, NULL);
stream->sample_list = Queue_New(TRUE, -1, -1);
- stream->sample_list->object.fnObjectFree = free;
-
+ stream->sample_list->object.fnObjectFree = tsmf_sample_free;
stream->sample_ack_list = Queue_New(TRUE, -1, -1);
- stream->sample_ack_list->object.fnObjectFree = free;
-
+ stream->sample_ack_list->object.fnObjectFree = tsmf_sample_free;
+ stream->play_thread = CreateThread(NULL, 0,
+ (LPTHREAD_START_ROUTINE)tsmf_stream_playback_func, stream, 0, NULL);
+ stream->ack_thread = CreateThread(NULL, 0,
+ (LPTHREAD_START_ROUTINE)tsmf_stream_ack_func, stream, 0, NULL);
ArrayList_Add(presentation->stream_list, stream);
-
return stream;
}
-TSMF_STREAM* tsmf_stream_find_by_id(TSMF_PRESENTATION* presentation, UINT32 stream_id)
+TSMF_STREAM *tsmf_stream_find_by_id(TSMF_PRESENTATION *presentation, UINT32 stream_id)
{
UINT32 index;
UINT32 count;
BOOL found = FALSE;
- TSMF_STREAM* stream;
-
+ TSMF_STREAM *stream;
ArrayList_Lock(presentation->stream_list);
-
count = ArrayList_Count(presentation->stream_list);
for (index = 0; index < count; index++)
{
- stream = (TSMF_STREAM*) ArrayList_GetItem(presentation->stream_list, index);
+ stream = (TSMF_STREAM *) ArrayList_GetItem(presentation->stream_list, index);
if (stream->stream_id == stream_id)
{
@@ -1053,11 +951,16 @@ TSMF_STREAM* tsmf_stream_find_by_id(TSMF_PRESENTATION* presentation, UINT32 stre
}
ArrayList_Unlock(presentation->stream_list);
-
return (found) ? stream : NULL;
}
-void tsmf_stream_set_format(TSMF_STREAM* stream, const char* name, wStream* s)
+static void tsmf_stream_resync(void *arg)
+{
+ TSMF_STREAM *stream = arg;
+ ResetEvent(stream->ready);
+}
+
+void tsmf_stream_set_format(TSMF_STREAM *stream, const char *name, wStream *s)
{
TS_AM_MEDIA_TYPE mediatype;
@@ -1071,17 +974,16 @@ void tsmf_stream_set_format(TSMF_STREAM* stream, const char* name, wStream* s)
if (mediatype.MajorType == TSMF_MAJOR_TYPE_VIDEO)
{
- DEBUG_DVC("video width %d height %d bit_rate %d frame_rate %f codec_data %d",
- mediatype.Width, mediatype.Height, mediatype.BitRate,
- (double) mediatype.SamplesPerSecond.Numerator / (double) mediatype.SamplesPerSecond.Denominator,
- mediatype.ExtraDataSize);
+ DEBUG_TSMF("video width %d height %d bit_rate %d frame_rate %f codec_data %d",
+ mediatype.Width, mediatype.Height, mediatype.BitRate,
+ (double) mediatype.SamplesPerSecond.Numerator / (double) mediatype.SamplesPerSecond.Denominator,
+ mediatype.ExtraDataSize);
}
else if (mediatype.MajorType == TSMF_MAJOR_TYPE_AUDIO)
{
- DEBUG_DVC("audio channel %d sample_rate %d bits_per_sample %d codec_data %d",
- mediatype.Channels, mediatype.SamplesPerSecond.Numerator, mediatype.BitsPerSample,
- mediatype.ExtraDataSize);
-
+ DEBUG_TSMF("audio channel %d sample_rate %d bits_per_sample %d codec_data %d",
+ mediatype.Channels, mediatype.SamplesPerSecond.Numerator, mediatype.BitsPerSample,
+ mediatype.ExtraDataSize);
stream->sample_rate = mediatype.SamplesPerSecond.Numerator;
stream->channels = mediatype.Channels;
stream->bits_per_sample = mediatype.BitsPerSample;
@@ -1095,55 +997,83 @@ void tsmf_stream_set_format(TSMF_STREAM* stream, const char* name, wStream* s)
stream->height = mediatype.Height;
stream->decoder = tsmf_load_decoder(name, &mediatype);
tsmf_stream_change_volume(stream, stream->presentation->volume, stream->presentation->muted);
+
+ if (!stream->decoder)
+ return;
+
+ if (stream->decoder->SetAckFunc)
+ stream->decoder->SetAckFunc(stream->decoder, tsmf_stream_process_ack, stream);
+
+ if (stream->decoder->SetSyncFunc)
+ stream->decoder->SetSyncFunc(stream->decoder, tsmf_stream_resync, stream);
}
-void tsmf_stream_end(TSMF_STREAM* stream)
+void tsmf_stream_end(TSMF_STREAM *stream)
{
+ assert(stream);
stream->eos = 1;
stream->presentation->eos = 1;
}
-void tsmf_stream_free(TSMF_STREAM* stream)
+void _tsmf_stream_free(TSMF_STREAM *stream)
{
- TSMF_PRESENTATION* presentation = stream->presentation;
-
+ assert(stream);
tsmf_stream_stop(stream);
tsmf_stream_flush(stream);
+ SetEvent(stream->stopEvent);
- ArrayList_Remove(presentation->stream_list, stream);
+ if (stream->play_thread)
+ {
+ WaitForSingleObject(stream->play_thread, INFINITE);
+ CloseHandle(stream->play_thread);
+ stream->play_thread = NULL;
+ }
+
+ if (stream->ack_thread)
+ {
+ WaitForSingleObject(stream->ack_thread, INFINITE);
+ CloseHandle(stream->ack_thread);
+ stream->ack_thread = NULL;
+ }
Queue_Free(stream->sample_list);
Queue_Free(stream->sample_ack_list);
- if (stream->decoder)
+ if (stream->decoder && stream->decoder->Free)
{
stream->decoder->Free(stream->decoder);
- stream->decoder = 0;
+ stream->decoder = NULL;
}
- SetEvent(stream->thread);
-
+ CloseHandle(stream->stopEvent);
+ CloseHandle(stream->ready);
+ memset(stream, 0, sizeof(TSMF_STREAM));
free(stream);
- stream = 0;
}
-void tsmf_stream_push_sample(TSMF_STREAM* stream, IWTSVirtualChannelCallback* pChannelCallback,
- UINT32 sample_id, UINT64 start_time, UINT64 end_time, UINT64 duration, UINT32 extensions,
- UINT32 data_size, BYTE* data)
+void tsmf_stream_free(TSMF_STREAM *stream)
{
- TSMF_SAMPLE* sample;
+ TSMF_PRESENTATION *presentation = stream->presentation;
+ ArrayList_Remove(presentation->stream_list, stream);
+}
+
+void tsmf_stream_push_sample(TSMF_STREAM *stream, IWTSVirtualChannelCallback *pChannelCallback,
+ UINT32 sample_id, UINT64 start_time, UINT64 end_time, UINT64 duration, UINT32 extensions,
+ UINT32 data_size, BYTE *data)
+{
+ TSMF_SAMPLE *sample;
+ SetEvent(stream->ready);
- WaitForSingleObject(tsmf_mutex, INFINITE);
-
if (TERMINATING)
+ return;
+
+ sample = (TSMF_SAMPLE *) calloc(1, sizeof(TSMF_SAMPLE));
+
+ if (!sample)
{
- ReleaseMutex(tsmf_mutex);
+ DEBUG_WARN("calloc failed!");
return;
}
-
- ReleaseMutex(tsmf_mutex);
-
- sample = (TSMF_SAMPLE*) calloc(1, sizeof(TSMF_SAMPLE));
sample->sample_id = sample_id;
sample->start_time = start_time;
@@ -1153,10 +1083,16 @@ void tsmf_stream_push_sample(TSMF_STREAM* stream, IWTSVirtualChannelCallback* pC
sample->stream = stream;
sample->channel_callback = pChannelCallback;
sample->data_size = data_size;
- sample->data = malloc(data_size + TSMF_BUFFER_PADDING_SIZE);
- ZeroMemory(sample->data, data_size + TSMF_BUFFER_PADDING_SIZE);
- CopyMemory(sample->data, data, data_size);
+ sample->data = calloc(1, data_size + TSMF_BUFFER_PADDING_SIZE);
+ if (!sample->data)
+ {
+ DEBUG_WARN("calloc failed!");
+ free(sample);
+ return;
+ }
+
+ CopyMemory(sample->data, data, data_size);
Queue_Enqueue(stream->sample_list, sample);
}
@@ -1164,14 +1100,9 @@ void tsmf_stream_push_sample(TSMF_STREAM* stream, IWTSVirtualChannelCallback* pC
static void tsmf_signal_handler(int s)
{
- WaitForSingleObject(tsmf_mutex, INFINITE);
TERMINATING = 1;
- ReleaseMutex(tsmf_mutex);
-
ArrayList_Free(presentation_list);
- unlink("/tmp/tsmf.tid");
-
if (s == SIGINT)
{
signal(s, SIG_DFL);
@@ -1196,11 +1127,9 @@ void tsmf_media_init(void)
sigaction(SIGUSR1, &sigtrap, 0);
#endif
- tsmf_mutex = CreateMutex(NULL, FALSE, NULL);
-
if (!presentation_list)
{
presentation_list = ArrayList_New(TRUE);
- ArrayList_Object(presentation_list)->fnObjectFree = (OBJECT_FREE_FN) tsmf_presentation_free;
+ ArrayList_Object(presentation_list)->fnObjectFree = (OBJECT_FREE_FN) _tsmf_presentation_free;
}
}
diff --git a/channels/tsmf/client/tsmf_media.h b/channels/tsmf/client/tsmf_media.h
index fe52ccd79..116ae088c 100644
--- a/channels/tsmf/client/tsmf_media.h
+++ b/channels/tsmf/client/tsmf_media.h
@@ -32,30 +32,31 @@ typedef struct _TSMF_STREAM TSMF_STREAM;
typedef struct _TSMF_SAMPLE TSMF_SAMPLE;
-TSMF_PRESENTATION* tsmf_presentation_new(const BYTE* guid, IWTSVirtualChannelCallback* pChannelCallback);
-TSMF_PRESENTATION* tsmf_presentation_find_by_id(const BYTE* guid);
-void tsmf_presentation_start(TSMF_PRESENTATION* presentation);
-void tsmf_presentation_stop(TSMF_PRESENTATION* presentation);
-void tsmf_presentation_paused(TSMF_PRESENTATION* presentation);
-void tsmf_presentation_restarted(TSMF_PRESENTATION* presentation);
-void tsmf_presentation_volume_changed(TSMF_PRESENTATION* presentation, UINT32 newVolume, UINT32 muted);
-void tsmf_presentation_set_geometry_info(TSMF_PRESENTATION* presentation,
- UINT32 x, UINT32 y, UINT32 width, UINT32 height,
- int num_rects, RDP_RECT* rects);
-void tsmf_presentation_set_audio_device(TSMF_PRESENTATION* presentation,
- const char* name, const char* device);
-void tsmf_presentation_flush(TSMF_PRESENTATION* presentation);
-void tsmf_presentation_free(TSMF_PRESENTATION* presentation);
-
-TSMF_STREAM* tsmf_stream_new(TSMF_PRESENTATION* presentation, UINT32 stream_id);
-TSMF_STREAM* tsmf_stream_find_by_id(TSMF_PRESENTATION* presentation, UINT32 stream_id);
-void tsmf_stream_set_format(TSMF_STREAM* stream, const char* name, wStream* s);
-void tsmf_stream_end(TSMF_STREAM* stream);
-void tsmf_stream_free(TSMF_STREAM* stream);
-
-void tsmf_stream_push_sample(TSMF_STREAM* stream, IWTSVirtualChannelCallback* pChannelCallback,
- UINT32 sample_id, UINT64 start_time, UINT64 end_time, UINT64 duration, UINT32 extensions,
- UINT32 data_size, BYTE* data);
+TSMF_PRESENTATION *tsmf_presentation_new(const BYTE *guid, IWTSVirtualChannelCallback *pChannelCallback);
+TSMF_PRESENTATION *tsmf_presentation_find_by_id(const BYTE *guid);
+void tsmf_presentation_start(TSMF_PRESENTATION *presentation);
+void tsmf_presentation_stop(TSMF_PRESENTATION *presentation);
+void tsmf_presentation_sync(TSMF_PRESENTATION *presentation);
+void tsmf_presentation_paused(TSMF_PRESENTATION *presentation);
+void tsmf_presentation_restarted(TSMF_PRESENTATION *presentation);
+void tsmf_presentation_volume_changed(TSMF_PRESENTATION *presentation, UINT32 newVolume, UINT32 muted);
+void tsmf_presentation_set_geometry_info(TSMF_PRESENTATION *presentation,
+ UINT32 x, UINT32 y, UINT32 width, UINT32 height,
+ int num_rects, RDP_RECT *rects);
+void tsmf_presentation_set_audio_device(TSMF_PRESENTATION *presentation,
+ const char *name, const char *device);
+void tsmf_presentation_flush(TSMF_PRESENTATION *presentation);
+void tsmf_presentation_free(TSMF_PRESENTATION *presentation);
+
+TSMF_STREAM *tsmf_stream_new(TSMF_PRESENTATION *presentation, UINT32 stream_id);
+TSMF_STREAM *tsmf_stream_find_by_id(TSMF_PRESENTATION *presentation, UINT32 stream_id);
+void tsmf_stream_set_format(TSMF_STREAM *stream, const char *name, wStream *s);
+void tsmf_stream_end(TSMF_STREAM *stream);
+void tsmf_stream_free(TSMF_STREAM *stream);
+
+void tsmf_stream_push_sample(TSMF_STREAM *stream, IWTSVirtualChannelCallback *pChannelCallback,
+ UINT32 sample_id, UINT64 start_time, UINT64 end_time, UINT64 duration, UINT32 extensions,
+ UINT32 data_size, BYTE *data);
void tsmf_media_init(void);
diff --git a/channels/tsmf/client/tsmf_types.h b/channels/tsmf/client/tsmf_types.h
index 0ccdafae8..4911209d4 100644
--- a/channels/tsmf/client/tsmf_types.h
+++ b/channels/tsmf/client/tsmf_types.h
@@ -28,10 +28,10 @@
#include <freerdp/types.h>
#include <freerdp/utils/debug.h>
-#ifdef WITH_DEBUG_DVC
-#define DEBUG_DVC(fmt, ...) DEBUG_CLASS(DVC, fmt, ## __VA_ARGS__)
+#ifdef WITH_DEBUG_TSMF
+#define DEBUG_TSMF(fmt, ...) DEBUG_CLASS(TSMF, fmt, ## __VA_ARGS__)
#else
-#define DEBUG_DVC(fmt, ...) DEBUG_NULL(fmt, ## __VA_ARGS__)
+#define DEBUG_TSMF(fmt, ...) DEBUG_NULL(fmt, ## __VA_ARGS__)
#endif
typedef struct _TS_AM_MEDIA_TYPE
@@ -41,7 +41,7 @@ typedef struct _TS_AM_MEDIA_TYPE
int FormatType;
UINT32 Width;
- UINT32 Height;
+ UINT32 Height;
UINT32 BitRate;
struct
{
@@ -51,7 +51,7 @@ typedef struct _TS_AM_MEDIA_TYPE
UINT32 Channels;
UINT32 BitsPerSample;
UINT32 BlockAlign;
- const BYTE* ExtraData;
+ const BYTE *ExtraData;
UINT32 ExtraDataSize;
} TS_AM_MEDIA_TYPE;
diff --git a/client/X11/generate_argument_docbook.c b/client/X11/generate_argument_docbook.c
index dd7b9d937..aaab2239c 100644
--- a/client/X11/generate_argument_docbook.c
+++ b/client/X11/generate_argument_docbook.c
@@ -9,33 +9,28 @@
* the argument struct. */
#include "../common/cmdline.c"
-LPSTR tmp = NULL;
-
LPSTR tr_esc_str(LPCSTR arg)
{
+ LPSTR tmp = NULL;
size_t cs = 0, x, ds;
size_t s;
-
- if( NULL == arg )
+ if(NULL == arg)
return NULL;
-
s = strlen(arg);
-
/* Find trailing whitespaces */
- while( (s > 0) && isspace(arg[s-1]))
+ while((s > 0) && isspace(arg[s-1]))
s--;
-
/* Prepare a initial buffer with the size of the result string. */
- if (s)
- tmp = (LPSTR)malloc(s * sizeof(CHAR));
- if( NULL == tmp )
+ ds = s + 1;
+ if(s)
+ tmp = (LPSTR)realloc(tmp, ds * sizeof(CHAR));
+ if(NULL == tmp)
{
fprintf(stderr, "Could not allocate string buffer.");
exit(-2);
}
-
/* Copy character for character and check, if it is necessary to escape. */
- ds = s + 1;
+ memset(tmp, 0, ds * sizeof(CHAR));
for(x=0; x<s; x++)
{
switch(arg[x])
@@ -43,7 +38,7 @@ LPSTR tr_esc_str(LPCSTR arg)
case '<':
ds += 3;
tmp = (LPSTR)realloc(tmp, ds * sizeof(CHAR));
- if( NULL == tmp )
+ if(NULL == tmp)
{
fprintf(stderr, "Could not reallocate string buffer.");
exit(-3);
@@ -56,7 +51,7 @@ LPSTR tr_esc_str(LPCSTR arg)
case '>':
ds += 3;
tmp = (LPSTR)realloc(tmp, ds * sizeof(CHAR));
- if( NULL == tmp )
+ if(NULL == tmp)
{
fprintf(stderr, "Could not reallocate string buffer.");
exit(-4);
@@ -69,7 +64,7 @@ LPSTR tr_esc_str(LPCSTR arg)
case '\'':
ds += 5;
tmp = (LPSTR)realloc(tmp, ds * sizeof(CHAR));
- if( NULL == tmp )
+ if(NULL == tmp)
{
fprintf(stderr, "Could not reallocate string buffer.");
exit(-5);
@@ -84,7 +79,7 @@ LPSTR tr_esc_str(LPCSTR arg)
case '"':
ds += 5;
tmp = (LPSTR)realloc(tmp, ds * sizeof(CHAR));
- if( NULL == tmp )
+ if(NULL == tmp)
{
fprintf(stderr, "Could not reallocate string buffer.");
exit(-6);
@@ -99,7 +94,7 @@ LPSTR tr_esc_str(LPCSTR arg)
case '&':
ds += 4;
tmp = (LPSTR)realloc(tmp, ds * sizeof(CHAR));
- if( NULL == tmp )
+ if(NULL == tmp)
{
fprintf(stderr, "Could not reallocate string buffer.");
exit(-7);
@@ -114,11 +109,9 @@ LPSTR tr_esc_str(LPCSTR arg)
tmp[cs++] = arg[x];
break;
}
-
/* Assure, the string is '\0' terminated. */
tmp[ds-1] = '\0';
}
-
return tmp;
}
@@ -128,51 +121,46 @@ int main(int argc, char *argv[])
size_t x;
const char *fname = "xfreerdp-argument.1.xml";
FILE *fp = NULL;
-
/* Open output file for writing, truncate if existing. */
fp = fopen(fname, "w");
- if( NULL == fp )
+ if(NULL == fp)
{
fprintf(stderr, "Could not open '%s' for writing.", fname);
return -1;
}
-
/* The tag used as header in the manpage */
fprintf(fp, "<refsect1>\n");
fprintf(fp, "\t<title>Options</title>\n");
fprintf(fp, "\t\t<variablelist>\n");
-
- /* Iterate over argument struct and write data to docbook 4.5
+ /* Iterate over argument struct and write data to docbook 4.5
* compatible XML */
- if( elements < 2 )
+ if(elements < 2)
{
fprintf(stderr, "The argument array 'args' is empty, writing an empty file.");
elements = 1;
}
-
for(x=0; x<elements - 1; x++)
{
const COMMAND_LINE_ARGUMENT_A *arg = &args[x];
-
+ const char *name = tr_esc_str((LPSTR) arg->Name);
+ const char *format = tr_esc_str(arg->Format);
+ const char *text = tr_esc_str((LPSTR) arg->Text);
fprintf(fp, "\t\t\t<varlistentry>\n");
- if ( COMMAND_LINE_VALUE_REQUIRED == arg->Flags)
- fprintf(fp, "\t\t\t\t<term><option>/%s</option> <replaceable>%s</replaceable></term>\n", tr_esc_str((LPSTR) arg->Name), tr_esc_str(arg->Format) );
+ if(COMMAND_LINE_VALUE_REQUIRED == arg->Flags)
+ fprintf(fp, "\t\t\t\t<term><option>/%s</option> <replaceable>%s</replaceable></term>\n", name, format);
else
- fprintf(fp, "\t\t\t\t<term><option>/%s</option></term>\n", tr_esc_str((LPSTR) arg->Name));
+ fprintf(fp, "\t\t\t\t<term><option>/%s</option></term>\n", name);
fprintf(fp, "\t\t\t\t<listitem>\n");
- fprintf(fp, "\t\t\t\t\t<para>%s</para>\n", tr_esc_str((LPSTR) arg->Text));
-
+ fprintf(fp, "\t\t\t\t\t<para>%s</para>\n", format);
fprintf(fp, "\t\t\t\t</listitem>\n");
fprintf(fp, "\t\t\t</varlistentry>\n");
+ free(name);
+ free(format);
+ free(text);
}
-
fprintf(fp, "\t\t</variablelist>\n");
fprintf(fp, "\t</refsect1>\n");
fclose(fp);
-
- if(NULL != tmp)
- free(tmp);
-
return 0;
}
diff --git a/client/X11/xf_client.c b/client/X11/xf_client.c
index e8d09031a..26a4bb5be 100644
--- a/client/X11/xf_client.c
+++ b/client/X11/xf_client.c
@@ -102,73 +102,59 @@
static long xv_port = 0;
static const size_t password_size = 512;
-void xf_transform_window(xfContext* xfc)
+void xf_transform_window(xfContext *xfc)
{
int ret;
int w;
int h;
long supplied;
Atom hints_atom;
- XSizeHints* size_hints = NULL;
-
+ XSizeHints *size_hints = NULL;
hints_atom = XInternAtom(xfc->display, "WM_SIZE_HINTS", 1);
-
ret = XGetWMSizeHints(xfc->display, xfc->window->handle, size_hints, &supplied, hints_atom);
-
if(ret == 0)
size_hints = XAllocSizeHints();
-
w = (xfc->originalWidth * xfc->settings->ScalingFactor) + xfc->offset_x;
h = (xfc->originalHeight * xfc->settings->ScalingFactor) + xfc->offset_y;
-
if(w < 1)
w = 1;
-
if(h < 1)
h = 1;
-
- if (size_hints)
+ if(size_hints)
{
size_hints->flags |= PMinSize | PMaxSize;
size_hints->min_width = size_hints->max_width = w;
size_hints->min_height = size_hints->max_height = h;
XSetWMNormalHints(xfc->display, xfc->window->handle, size_hints);
XResizeWindow(xfc->display, xfc->window->handle, w, h);
-
XFree(size_hints);
}
}
-void xf_draw_screen_scaled(xfContext* xfc, int x, int y, int w, int h, BOOL scale)
+void xf_draw_screen_scaled(xfContext *xfc, int x, int y, int w, int h, BOOL scale)
{
#ifdef WITH_XRENDER
XTransform transform;
Picture windowPicture;
Picture primaryPicture;
XRenderPictureAttributes pa;
- XRenderPictFormat* picFormat;
+ XRenderPictFormat *picFormat;
XRectangle xr;
-
picFormat = XRenderFindStandardFormat(xfc->display, PictStandardRGB24);
pa.subwindow_mode = IncludeInferiors;
primaryPicture = XRenderCreatePicture(xfc->display, xfc->primary, picFormat, CPSubwindowMode, &pa);
windowPicture = XRenderCreatePicture(xfc->display, xfc->window->handle, picFormat, CPSubwindowMode, &pa);
-
transform.matrix[0][0] = XDoubleToFixed(1);
transform.matrix[0][1] = XDoubleToFixed(0);
transform.matrix[0][2] = XDoubleToFixed(0);
-
transform.matrix[1][0] = XDoubleToFixed(0);
transform.matrix[1][1] = XDoubleToFixed(1);
transform.matrix[1][2] = XDoubleToFixed(0);
-
transform.matrix[2][0] = XDoubleToFixed(0);
transform.matrix[2][1] = XDoubleToFixed(0);
transform.matrix[2][2] = XDoubleToFixed(xfc->settings->ScalingFactor);
-
- if( (w != 0) && (h != 0) )
+ if((w != 0) && (h != 0))
{
-
if(scale == TRUE)
{
xr.x = x * xfc->settings->ScalingFactor;
@@ -183,54 +169,42 @@ void xf_draw_screen_scaled(xfContext* xfc, int x, int y, int w, int h, BOOL scal
xr.width = w;
xr.height = h;
}
-
XRenderSetPictureClipRectangles(xfc->display, primaryPicture, 0, 0, &xr, 1);
}
-
XRenderSetPictureTransform(xfc->display, primaryPicture, &transform);
-
XRenderComposite(xfc->display, PictOpSrc, primaryPicture, 0, windowPicture, 0, 0, 0, 0, xfc->offset_x, xfc->offset_y, xfc->currentWidth, xfc->currentHeight);
-
XRenderFreePicture(xfc->display, primaryPicture);
XRenderFreePicture(xfc->display, windowPicture);
-
#endif
-
}
-void xf_sw_begin_paint(rdpContext* context)
+void xf_sw_begin_paint(rdpContext *context)
{
- rdpGdi* gdi = context->gdi;
+ rdpGdi *gdi = context->gdi;
gdi->primary->hdc->hwnd->invalid->null = 1;
gdi->primary->hdc->hwnd->ninvalid = 0;
}
-void xf_sw_end_paint(rdpContext* context)
+void xf_sw_end_paint(rdpContext *context)
{
- rdpGdi* gdi;
+ rdpGdi *gdi;
INT32 x, y;
UINT32 w, h;
- xfContext* xfc = (xfContext*) context;
-
+ xfContext *xfc = (xfContext *) context;
gdi = context->gdi;
-
- if (!xfc->remote_app)
+ if(!xfc->remote_app)
{
- if (!xfc->complex_regions)
+ if(!xfc->complex_regions)
{
- if (gdi->primary->hdc->hwnd->invalid->null)
+ if(gdi->primary->hdc->hwnd->invalid->null)
return;
-
x = gdi->primary->hdc->hwnd->invalid->x;
y = gdi->primary->hdc->hwnd->invalid->y;
w = gdi->primary->hdc->hwnd->invalid->w;
h = gdi->primary->hdc->hwnd->invalid->h;
-
xf_lock_x11(xfc, FALSE);
-
XPutImage(xfc->display, xfc->primary, xfc->gc, xfc->image, x, y, x, y, w, h);
-
- if ( (xfc->settings->ScalingFactor != 1.0) || (xfc->offset_x) || (xfc->offset_y) )
+ if((xfc->settings->ScalingFactor != 1.0) || (xfc->offset_x) || (xfc->offset_y))
{
xf_draw_screen_scaled(xfc, x, y, w, h, TRUE);
}
@@ -238,7 +212,6 @@ void xf_sw_end_paint(rdpContext* context)
{
XCopyArea(xfc->display, xfc->primary, xfc->window->handle, xfc->gc, x, y, w, h, x, y);
}
-
xf_unlock_x11(xfc, FALSE);
}
else
@@ -246,26 +219,20 @@ void xf_sw_end_paint(rdpContext* context)
int i;
int ninvalid;
HGDI_RGN cinvalid;
-
- if (gdi->primary->hdc->hwnd->ninvalid < 1)
+ if(gdi->primary->hdc->hwnd->ninvalid < 1)
return;
-
ninvalid = gdi->primary->hdc->hwnd->ninvalid;
cinvalid = gdi->primary->hdc->hwnd->cinvalid;
-
xf_lock_x11(xfc, FALSE);
-
- for (i = 0; i < ninvalid; i++)
+ for(i = 0; i < ninvalid; i++)
{
x = cinvalid[i].x;
y = cinvalid[i].y;
w = cinvalid[i].w;
h = cinvalid[i].h;
-
//combine xfc->primary with xfc->image
XPutImage(xfc->display, xfc->primary, xfc->gc, xfc->image, x, y, x, y, w, h);
-
- if ( (xfc->settings->ScalingFactor != 1.0) || (xfc->offset_x) || (xfc->offset_y) )
+ if((xfc->settings->ScalingFactor != 1.0) || (xfc->offset_x) || (xfc->offset_y))
{
xf_draw_screen_scaled(xfc, x, y, w, h, TRUE);
}
@@ -274,85 +241,69 @@ void xf_sw_end_paint(rdpContext* context)
XCopyArea(xfc->display, xfc->primary, xfc->window->handle, xfc->gc, x, y, w, h, x, y);
}
}
-
XFlush(xfc->display);
-
xf_unlock_x11(xfc, FALSE);
}
}
else
{
- if (gdi->primary->hdc->hwnd->invalid->null)
+ if(gdi->primary->hdc->hwnd->invalid->null)
return;
-
x = gdi->primary->hdc->hwnd->invalid->x;
y = gdi->primary->hdc->hwnd->invalid->y;
w = gdi->primary->hdc->hwnd->invalid->w;
h = gdi->primary->hdc->hwnd->invalid->h;
-
xf_lock_x11(xfc, FALSE);
-
xf_rail_paint(xfc, context->rail, x, y, x + w - 1, y + h - 1);
-
xf_unlock_x11(xfc, FALSE);
}
}
-void xf_sw_desktop_resize(rdpContext* context)
+void xf_sw_desktop_resize(rdpContext *context)
{
- rdpSettings* settings;
- xfContext* xfc = (xfContext*) context;
-
+ rdpSettings *settings;
+ xfContext *xfc = (xfContext *) context;
settings = xfc->instance->settings;
-
xf_lock_x11(xfc, TRUE);
-
- if (!xfc->fullscreen)
+ if(!xfc->fullscreen)
{
- rdpGdi* gdi = context->gdi;
+ rdpGdi *gdi = context->gdi;
gdi_resize(gdi, xfc->width, xfc->height);
-
- if (xfc->image)
+ if(xfc->image)
{
xfc->image->data = NULL;
XDestroyImage(xfc->image);
xfc->image = XCreateImage(xfc->display, xfc->visual, xfc->depth, ZPixmap, 0,
- (char*) gdi->primary_buffer, gdi->width, gdi->height, xfc->scanline_pad, 0);
+ (char *) gdi->primary_buffer, gdi->width, gdi->height, xfc->scanline_pad, 0);
}
}
-
xf_unlock_x11(xfc, TRUE);
}
-void xf_hw_begin_paint(rdpContext* context)
+void xf_hw_begin_paint(rdpContext *context)
{
- xfContext* xfc = (xfContext*) context;
-
+ xfContext *xfc = (xfContext *) context;
xfc->hdc->hwnd->invalid->null = 1;
xfc->hdc->hwnd->ninvalid = 0;
}
-void xf_hw_end_paint(rdpContext* context)
+void xf_hw_end_paint(rdpContext *context)
{
INT32 x, y;
UINT32 w, h;
- xfContext* xfc = (xfContext*) context;
-
- if (!xfc->remote_app)
+ xfContext *xfc = (xfContext *) context;
+ if(!xfc->remote_app)
{
- if (!xfc->complex_regions)
+ if(!xfc->complex_regions)
{
- if (xfc->hdc->hwnd->invalid->null)
+ if(xfc->hdc->hwnd->invalid->null)
return;
-
x = xfc->hdc->hwnd->invalid->x;
y = xfc->hdc->hwnd->invalid->y;
w = xfc->hdc->hwnd->invalid->w;
h = xfc->hdc->hwnd->invalid->h;
-
xf_lock_x11(xfc, FALSE);
-
- if ( (xfc->settings->ScalingFactor != 1.0) || (xfc->offset_x) || (xfc->offset_y) )
+ if((xfc->settings->ScalingFactor != 1.0) || (xfc->offset_x) || (xfc->offset_y))
{
xf_draw_screen_scaled(xfc, x, y, w, h, TRUE);
}
@@ -360,7 +311,6 @@ void xf_hw_end_paint(rdpContext* context)
{
XCopyArea(xfc->display, xfc->primary, xfc->drawable, xfc->gc, x, y, w, h, x, y);
}
-
xf_unlock_x11(xfc, FALSE);
}
else
@@ -368,23 +318,18 @@ void xf_hw_end_paint(rdpContext* context)
int i;
int ninvalid;
HGDI_RGN cinvalid;
-
- if (xfc->hdc->hwnd->ninvalid < 1)
+ if(xfc->hdc->hwnd->ninvalid < 1)
return;
-
ninvalid = xfc->hdc->hwnd->ninvalid;
cinvalid = xfc->hdc->hwnd->cinvalid;
-
xf_lock_x11(xfc, FALSE);
-
- for (i = 0; i < ninvalid; i++)
+ for(i = 0; i < ninvalid; i++)
{
x = cinvalid[i].x;
y = cinvalid[i].y;
w = cinvalid[i].w;
h = cinvalid[i].h;
-
- if ( (xfc->settings->ScalingFactor != 1.0) || (xfc->offset_x) || (xfc->offset_y) )
+ if((xfc->settings->ScalingFactor != 1.0) || (xfc->offset_x) || (xfc->offset_y))
{
xf_draw_screen_scaled(xfc, x, y, w, h, TRUE);
}
@@ -393,58 +338,44 @@ void xf_hw_end_paint(rdpContext* context)
XCopyArea(xfc->display, xfc->primary, xfc->drawable, xfc->gc, x, y, w, h, x, y);
}
}
-
XFlush(xfc->display);
-
xf_unlock_x11(xfc, FALSE);
}
}
else
{
- if (xfc->hdc->hwnd->invalid->null)
+ if(xfc->hdc->hwnd->invalid->null)
return;
-
x = xfc->hdc->hwnd->invalid->x;
y = xfc->hdc->hwnd->invalid->y;
w = xfc->hdc->hwnd->invalid->w;
h = xfc->hdc->hwnd->invalid->h;
-
xf_lock_x11(xfc, FALSE);
-
xf_rail_paint(xfc, context->rail, x, y, x + w - 1, y + h - 1);
-
xf_unlock_x11(xfc, FALSE);
}
}
-void xf_hw_desktop_resize(rdpContext* context)
+void xf_hw_desktop_resize(rdpContext *context)
{
BOOL same;
- rdpSettings* settings;
- xfContext* xfc = (xfContext*) context;
-
+ rdpSettings *settings;
+ xfContext *xfc = (xfContext *) context;
settings = xfc->instance->settings;
-
xf_lock_x11(xfc, TRUE);
-
- if (!xfc->fullscreen)
+ if(!xfc->fullscreen)
{
xfc->width = settings->DesktopWidth;
xfc->height = settings->DesktopHeight;
-
- if (xfc->window)
+ if(xfc->window)
xf_ResizeDesktopWindow(xfc, xfc->window, settings->DesktopWidth, settings->DesktopHeight);
-
- if (xfc->primary)
+ if(xfc->primary)
{
same = (xfc->primary == xfc->drawing) ? TRUE : FALSE;
-
XFreePixmap(xfc->display, xfc->primary);
-
xfc->primary = XCreatePixmap(xfc->display, xfc->drawable,
- xfc->width, xfc->height, xfc->depth);
-
- if (same)
+ xfc->width, xfc->height, xfc->depth);
+ if(same)
xfc->drawing = xfc->primary;
}
}
@@ -455,65 +386,51 @@ void xf_hw_desktop_resize(rdpContext* context)
XSetForeground(xfc->display, xfc->gc, 0);
XFillRectangle(xfc->display, xfc->drawable, xfc->gc, 0, 0, xfc->width, xfc->height);
}
-
xf_unlock_x11(xfc, TRUE);
}
-BOOL xf_get_fds(freerdp* instance, void** rfds, int* rcount, void** wfds, int* wcount)
+BOOL xf_get_fds(freerdp *instance, void **rfds, int *rcount, void **wfds, int *wcount)
{
- xfContext* xfc = (xfContext*) instance->context;
-
- rfds[*rcount] = (void*)(long)(xfc->xfds);
+ xfContext *xfc = (xfContext *) instance->context;
+ rfds[*rcount] = (void *)(long)(xfc->xfds);
(*rcount)++;
-
return TRUE;
}
-BOOL xf_process_x_events(freerdp* instance)
+BOOL xf_process_x_events(freerdp *instance)
{
BOOL status;
XEvent xevent;
int pending_status;
- xfContext* xfc = (xfContext*) instance->context;
-
+ xfContext *xfc = (xfContext *) instance->context;
status = TRUE;
pending_status = TRUE;
-
- while (pending_status)
+ while(pending_status)
{
xf_lock_x11(xfc, FALSE);
-
pending_status = XPending(xfc->display);
-
xf_unlock_x11(xfc, FALSE);
-
- if (pending_status)
+ if(pending_status)
{
ZeroMemory(&xevent, sizeof(xevent));
-
XNextEvent(xfc->display, &xevent);
status = xf_event_process(instance, &xevent);
-
- if (!status)
+ if(!status)
return status;
}
}
-
return status;
}
-void xf_create_window(xfContext* xfc)
+void xf_create_window(xfContext *xfc)
{
XEvent xevent;
int width, height;
- char* windowTitle;
-
+ char *windowTitle;
ZeroMemory(&xevent, sizeof(xevent));
-
width = xfc->width;
height = xfc->height;
-
- if (!xfc->remote_app)
+ if(!xfc->remote_app)
{
xfc->attribs.background_pixel = BlackPixelOfScreen(xfc->screen);
xfc->attribs.border_pixel = WhitePixelOfScreen(xfc->screen);
@@ -522,30 +439,26 @@ void xf_create_window(xfContext* xfc)
xfc->attribs.colormap = xfc->colormap;
xfc->attribs.bit_gravity = NorthWestGravity;
xfc->attribs.win_gravity = NorthWestGravity;
-
- if (xfc->instance->settings->WindowTitle)
+ if(xfc->instance->settings->WindowTitle)
{
windowTitle = _strdup(xfc->instance->settings->WindowTitle);
}
- else if (xfc->instance->settings->ServerPort == 3389)
- {
- windowTitle = malloc(1 + sizeof("FreeRDP: ") + strlen(xfc->instance->settings->ServerHostname));
- sprintf(windowTitle, "FreeRDP: %s", xfc->instance->settings->ServerHostname);
- }
else
- {
- windowTitle = malloc(1 + sizeof("FreeRDP: ") + strlen(xfc->instance->settings->ServerHostname) + sizeof(":00000"));
- sprintf(windowTitle, "FreeRDP: %s:%i", xfc->instance->settings->ServerHostname, xfc->instance->settings->ServerPort);
- }
-
+ if(xfc->instance->settings->ServerPort == 3389)
+ {
+ windowTitle = malloc(1 + sizeof("FreeRDP: ") + strlen(xfc->instance->settings->ServerHostname));
+ sprintf(windowTitle, "FreeRDP: %s", xfc->instance->settings->ServerHostname);
+ }
+ else
+ {
+ windowTitle = malloc(1 + sizeof("FreeRDP: ") + strlen(xfc->instance->settings->ServerHostname) + sizeof(":00000"));
+ sprintf(windowTitle, "FreeRDP: %s:%i", xfc->instance->settings->ServerHostname, xfc->instance->settings->ServerPort);
+ }
xfc->window = xf_CreateDesktopWindow(xfc, windowTitle, width, height, xfc->settings->Decorations);
free(windowTitle);
-
- if (xfc->fullscreen)
+ if(xfc->fullscreen)
xf_SetWindowFullscreen(xfc, xfc->window, xfc->fullscreen);
-
xfc->unobscured = (xevent.xvisibility.state == VisibilityUnobscured);
-
XSetWMProtocols(xfc->display, xfc->window->handle, &(xfc->WM_DELETE_WINDOW), 1);
xfc->drawable = xfc->window->handle;
}
@@ -555,81 +468,71 @@ void xf_create_window(xfContext* xfc)
}
}
-void xf_toggle_fullscreen(xfContext* xfc)
+void xf_toggle_fullscreen(xfContext *xfc)
{
Pixmap contents = 0;
WindowStateChangeEventArgs e;
-
xf_lock_x11(xfc, TRUE);
-
contents = XCreatePixmap(xfc->display, xfc->window->handle, xfc->width, xfc->height, xfc->depth);
XCopyArea(xfc->display, xfc->primary, contents, xfc->gc, 0, 0, xfc->width, xfc->height, 0, 0);
-
XDestroyWindow(xfc->display, xfc->window->handle);
xfc->fullscreen = (xfc->fullscreen) ? FALSE : TRUE;
xf_create_window(xfc);
-
XCopyArea(xfc->display, contents, xfc->primary, xfc->gc, 0, 0, xfc->width, xfc->height, 0, 0);
XFreePixmap(xfc->display, contents);
-
xf_unlock_x11(xfc, TRUE);
-
EventArgsInit(&e, "xfreerdp");
e.state = xfc->fullscreen ? FREERDP_WINDOW_STATE_FULLSCREEN : 0;
- PubSub_OnWindowStateChange(((rdpContext*) xfc)->pubSub, xfc, &e);
+ PubSub_OnWindowStateChange(((rdpContext *) xfc)->pubSub, xfc, &e);
}
-void xf_lock_x11(xfContext* xfc, BOOL display)
+void xf_lock_x11(xfContext *xfc, BOOL display)
{
- if (!xfc->UseXThreads)
+ if(!xfc->UseXThreads)
{
WaitForSingleObject(xfc->mutex, INFINITE);
}
else
{
- if (display)
+ if(display)
XLockDisplay(xfc->display);
}
}
-void xf_unlock_x11(xfContext* xfc, BOOL display)
+void xf_unlock_x11(xfContext *xfc, BOOL display)
{
- if (!xfc->UseXThreads)
+ if(!xfc->UseXThreads)
{
ReleaseMutex(xfc->mutex);
}
else
{
- if (display)
+ if(display)
XUnlockDisplay(xfc->display);
}
}
-BOOL xf_get_pixmap_info(xfContext* xfc)
+BOOL xf_get_pixmap_info(xfContext *xfc)
{
int i;
int vi_count;
int pf_count;
- XVisualInfo* vi;
- XVisualInfo* vis;
+ XVisualInfo *vi;
+ XVisualInfo *vis;
XVisualInfo template;
- XPixmapFormatValues* pf;
- XPixmapFormatValues* pfs;
+ XPixmapFormatValues *pf;
+ XPixmapFormatValues *pfs;
XWindowAttributes window_attributes;
-
pfs = XListPixmapFormats(xfc->display, &pf_count);
-
- if (pfs == NULL)
+ if(pfs == NULL)
{
fprintf(stderr, "xf_get_pixmap_info: XListPixmapFormats failed\n");
return 1;
}
-
- for (i = 0; i < pf_count; i++)
+ for(i = 0; i < pf_count; i++)
{
pf = pfs + i;
-
- if (pf->depth == xfc->depth)
+ if(pf->depth == xfc->depth)
{
xfc->bpp = pf->bits_per_pixel;
xfc->scanline_pad = pf->scanline_pad;
@@ -637,104 +540,86 @@ BOOL xf_get_pixmap_info(xfContext* xfc)
}
}
XFree(pfs);
-
ZeroMemory(&template, sizeof(template));
template.class = TrueColor;
template.screen = xfc->screen_number;
-
- if (XGetWindowAttributes(xfc->display, RootWindowOfScreen(xfc->screen), &window_attributes) == 0)
+ if(XGetWindowAttributes(xfc->display, RootWindowOfScreen(xfc->screen), &window_attributes) == 0)
{
fprintf(stderr, "xf_get_pixmap_info: XGetWindowAttributes failed\n");
return FALSE;
}
-
vis = XGetVisualInfo(xfc->display, VisualClassMask | VisualScreenMask, &template, &vi_count);
-
- if (vis == NULL)
+ if(vis == NULL)
{
fprintf(stderr, "xf_get_pixmap_info: XGetVisualInfo failed\n");
return FALSE;
}
-
vi = NULL;
- for (i = 0; i < vi_count; i++)
+ for(i = 0; i < vi_count; i++)
{
vi = vis + i;
-
- if (vi->visual == window_attributes.visual)
+ if(vi->visual == window_attributes.visual)
{
xfc->visual = vi->visual;
break;
}
}
-
- if (vi)
+ if(vi)
{
/*
* Detect if the server visual has an inverted colormap
* (BGR vs RGB, or red being the least significant byte)
*/
-
- if (vi->red_mask & 0xFF)
+ if(vi->red_mask & 0xFF)
{
xfc->clrconv->invert = TRUE;
}
}
-
XFree(vis);
-
- if ((xfc->visual == NULL) || (xfc->scanline_pad == 0))
+ if((xfc->visual == NULL) || (xfc->scanline_pad == 0))
{
return FALSE;
}
-
return TRUE;
}
-static int (*_def_error_handler)(Display*, XErrorEvent*);
+static int (*_def_error_handler)(Display *, XErrorEvent *);
-int xf_error_handler(Display* d, XErrorEvent* ev)
+int xf_error_handler(Display *d, XErrorEvent *ev)
{
char buf[256];
int do_abort = TRUE;
-
XGetErrorText(d, ev->error_code, buf, sizeof(buf));
fprintf(stderr, "%s", buf);
-
- if (do_abort)
+ if(do_abort)
abort();
-
_def_error_handler(d, ev);
-
return FALSE;
}
-int _xf_error_handler(Display* d, XErrorEvent* ev)
+int _xf_error_handler(Display *d, XErrorEvent *ev)
{
/*
- * ungrab the keyboard, in case a debugger is running in
- * another window. This make xf_error_handler() a potential
- * debugger breakpoint.
- */
+ * ungrab the keyboard, in case a debugger is running in
+ * another window. This make xf_error_handler() a potential
+ * debugger breakpoint.
+ */
XUngrabKeyboard(d, CurrentTime);
return xf_error_handler(d, ev);
}
static void xf_post_disconnect(freerdp *instance)
{
- xfContext* xfc = (xfContext*) instance->context;
-
+ xfContext *xfc = (xfContext *) instance->context;
assert(NULL != instance);
assert(NULL != xfc);
assert(NULL != instance->settings);
-
- if (xfc->mutex)
+ if(xfc->mutex)
{
WaitForSingleObject(xfc->mutex, INFINITE);
CloseHandle(xfc->mutex);
xfc->mutex = NULL;
}
-
xf_monitors_free(xfc, instance->settings);
}
@@ -748,21 +633,17 @@ static void xf_post_disconnect(freerdp *instance)
* @return TRUE if successful. FALSE otherwise.
* Can exit with error code XF_EXIT_PARSE_ARGUMENTS if there is an error in the parameters.
*/
-BOOL xf_pre_connect(freerdp* instance)
+BOOL xf_pre_connect(freerdp *instance)
{
- rdpChannels* channels;
- rdpSettings* settings;
- xfContext* xfc = (xfContext*) instance->context;
-
+ rdpChannels *channels;
+ rdpSettings *settings;
+ xfContext *xfc = (xfContext *) instance->context;
xfc->settings = instance->settings;
xfc->instance = instance;
-
settings = instance->settings;
channels = instance->context->channels;
-
settings->OsMajorType = OSMAJORTYPE_UNIX;
settings->OsMinorType = OSMINORTYPE_NATIVE_XSERVER;
-
ZeroMemory(settings->OrderSupport, 32);
settings->OrderSupport[NEG_DSTBLT_INDEX] = TRUE;
settings->OrderSupport[NEG_PATBLT_INDEX] = TRUE;
@@ -788,55 +669,44 @@ BOOL xf_pre_connect(freerdp* instance)
settings->OrderSupport[NEG_POLYGON_CB_INDEX] = (settings->SoftwareGdi) ? FALSE : TRUE;
settings->OrderSupport[NEG_ELLIPSE_SC_INDEX] = FALSE;
settings->OrderSupport[NEG_ELLIPSE_CB_INDEX] = FALSE;
-
xfc->UseXThreads = TRUE;
-
- if (xfc->UseXThreads)
+ if(xfc->UseXThreads)
{
- if (!XInitThreads())
+ if(!XInitThreads())
{
fprintf(stderr, "warning: XInitThreads() failure\n");
xfc->UseXThreads = FALSE;
}
}
-
xfc->display = XOpenDisplay(NULL);
-
- if (!xfc->display)
+ if(!xfc->display)
{
fprintf(stderr, "xf_pre_connect: failed to open display: %s\n", XDisplayName(NULL));
fprintf(stderr, "Please check that the $DISPLAY environment variable is properly set.\n");
return FALSE;
}
-
- if (xfc->debug)
+ if(xfc->debug)
{
fprintf(stderr, "Enabling X11 debug mode.\n");
XSynchronize(xfc->display, TRUE);
_def_error_handler = XSetErrorHandler(_xf_error_handler);
}
-
xfc->mutex = CreateMutex(NULL, FALSE, NULL);
-
PubSub_SubscribeChannelConnected(instance->context->pubSub,
- (pChannelConnectedEventHandler) xf_OnChannelConnectedEventHandler);
-
+ (pChannelConnectedEventHandler) xf_OnChannelConnectedEventHandler);
PubSub_SubscribeChannelDisconnected(instance->context->pubSub,
- (pChannelDisconnectedEventHandler) xf_OnChannelDisconnectedEventHandler);
-
+ (pChannelDisconnectedEventHandler) xf_OnChannelDisconnectedEventHandler);
freerdp_client_load_addins(channels, instance->settings);
-
freerdp_channels_pre_connect(channels, instance);
-
- if (settings->AuthenticationOnly)
+ if(settings->AuthenticationOnly)
{
/* Check --authonly has a username and password. */
- if (settings->Username == NULL)
+ if(settings->Username == NULL)
{
fprintf(stderr, "--authonly, but no -u username. Please provide one.\n");
return FALSE;
}
- if (settings->Password == NULL)
+ if(settings->Password == NULL)
{
fprintf(stderr, "--authonly, but no -p password. Please provide one.\n");
return FALSE;
@@ -845,7 +715,6 @@ BOOL xf_pre_connect(freerdp* instance)
/* Avoid XWindows initialization and configuration below. */
return TRUE;
}
-
xfc->_NET_WM_ICON = XInternAtom(xfc->display, "_NET_WM_ICON", False);
xfc->_MOTIF_WM_HINTS = XInternAtom(xfc->display, "_MOTIF_WM_HINTS", False);
xfc->_NET_CURRENT_DESKTOP = XInternAtom(xfc->display, "_NET_CURRENT_DESKTOP", False);
@@ -853,7 +722,6 @@ BOOL xf_pre_connect(freerdp* instance)
xfc->_NET_WM_STATE = XInternAtom(xfc->display, "_NET_WM_STATE", False);
xfc->_NET_WM_STATE_FULLSCREEN = XInternAtom(xfc->display, "_NET_WM_STATE_FULLSCREEN", False);
xfc->_NET_WM_WINDOW_TYPE = XInternAtom(xfc->display, "_NET_WM_WINDOW_TYPE", False);
-
xfc->_NET_WM_WINDOW_TYPE_NORMAL = XInternAtom(xfc->display, "_NET_WM_WINDOW_TYPE_NORMAL", False);
xfc->_NET_WM_WINDOW_TYPE_DIALOG = XInternAtom(xfc->display, "_NET_WM_WINDOW_TYPE_DIALOG", False);
xfc->_NET_WM_WINDOW_TYPE_POPUP = XInternAtom(xfc->display, "_NET_WM_WINDOW_TYPE_POPUP", False);
@@ -863,30 +731,22 @@ BOOL xf_pre_connect(freerdp* instance)
xfc->_NET_WM_STATE_SKIP_PAGER = XInternAtom(xfc->display, "_NET_WM_STATE_SKIP_PAGER", False);
xfc->_NET_WM_MOVERESIZE = XInternAtom(xfc->display, "_NET_WM_MOVERESIZE", False);
xfc->_NET_MOVERESIZE_WINDOW = XInternAtom(xfc->display, "_NET_MOVERESIZE_WINDOW", False);
-
xfc->WM_PROTOCOLS = XInternAtom(xfc->display, "WM_PROTOCOLS", False);
xfc->WM_DELETE_WINDOW = XInternAtom(xfc->display, "WM_DELETE_WINDOW", False);
xfc->WM_STATE = XInternAtom(xfc->display, "WM_STATE", False);
-
xf_keyboard_init(xfc);
-
xfc->clrconv = freerdp_clrconv_new(CLRCONV_ALPHA);
-
instance->context->cache = cache_new(instance->settings);
-
xfc->xfds = ConnectionNumber(xfc->display);
xfc->screen_number = DefaultScreen(xfc->display);
xfc->screen = ScreenOfDisplay(xfc->display, xfc->screen_number);
xfc->depth = DefaultDepthOfScreen(xfc->screen);
xfc->big_endian = (ImageByteOrder(xfc->display) == MSBFirst);
-
xfc->complex_regions = TRUE;
xfc->fullscreen = settings->Fullscreen;
xfc->grab_keyboard = settings->GrabKeyboard;
xfc->fullscreen_toggle = settings->ToggleFullscreen;
-
xf_detect_monitors(xfc, settings);
-
return TRUE;
}
@@ -895,107 +755,82 @@ BOOL xf_pre_connect(freerdp* instance)
* It will be called only if the connection was initialized properly, and will continue the initialization based on the
* newly created connection.
*/
-BOOL xf_post_connect(freerdp* instance)
+BOOL xf_post_connect(freerdp *instance)
{
XGCValues gcv;
- rdpCache* cache;
- rdpChannels* channels;
- rdpSettings* settings;
+ rdpCache *cache;
+ rdpChannels *channels;
+ rdpSettings *settings;
ResizeWindowEventArgs e;
- RFX_CONTEXT* rfx_context = NULL;
- NSC_CONTEXT* nsc_context = NULL;
- xfContext* xfc = (xfContext*) instance->context;
-
+ RFX_CONTEXT *rfx_context = NULL;
+ NSC_CONTEXT *nsc_context = NULL;
+ xfContext *xfc = (xfContext *) instance->context;
cache = instance->context->cache;
channels = instance->context->channels;
settings = instance->settings;
-
- if (!xf_get_pixmap_info(xfc))
+ if(!xf_get_pixmap_info(xfc))
return FALSE;
-
xf_register_graphics(instance->context->graphics);
-
- if (xfc->settings->SoftwareGdi)
+ if(xfc->settings->SoftwareGdi)
{
- rdpGdi* gdi;
+ rdpGdi *gdi;
UINT32 flags;
-
flags = CLRCONV_ALPHA;
-
- if (xfc->bpp > 16)
+ if(xfc->bpp > 16)
flags |= CLRBUF_32BPP;
else
flags |= CLRBUF_16BPP;
-
gdi_init(instance, flags, NULL);
gdi = instance->context->gdi;
xfc->primary_buffer = gdi->primary_buffer;
-
rfx_context = gdi->rfx_context;
}
else
{
xfc->srcBpp = instance->settings->ColorDepth;
xf_gdi_register_update_callbacks(instance->update);
-
xfc->hdc = gdi_CreateDC(xfc->clrconv, xfc->bpp);
-
- if (instance->settings->RemoteFxCodec)
+ if(instance->settings->RemoteFxCodec)
{
- rfx_context = (void*) rfx_context_new(FALSE);
+ rfx_context = (void *) rfx_context_new(FALSE);
xfc->rfx_context = rfx_context;
}
-
- if (instance->settings->NSCodec)
+ if(instance->settings->NSCodec)
{
- nsc_context = (void*) nsc_context_new();
+ nsc_context = (void *) nsc_context_new();
xfc->nsc_context = nsc_context;
}
}
-
xfc->originalWidth = settings->DesktopWidth;
xfc->originalHeight = settings->DesktopHeight;
xfc->currentWidth = xfc->originalWidth;
xfc->currentHeight = xfc->originalWidth;
xfc->settings->ScalingFactor = 1.0;
-
xfc->offset_x = 0;
xfc->offset_y = 0;
-
xfc->width = settings->DesktopWidth;
xfc->height = settings->DesktopHeight;
-
- if (settings->RemoteApplicationMode)
+ if(settings->RemoteApplicationMode)
xfc->remote_app = TRUE;
-
xf_create_window(xfc);
-
ZeroMemory(&gcv, sizeof(gcv));
-
- if (xfc->modifierMap)
+ if(xfc->modifierMap)
XFreeModifiermap(xfc->modifierMap);
-
xfc->modifierMap = XGetModifierMapping(xfc->display);
-
xfc->gc = XCreateGC(xfc->display, xfc->drawable, GCGraphicsExposures, &gcv);
xfc->primary = XCreatePixmap(xfc->display, xfc->drawable, xfc->width, xfc->height, xfc->depth);
xfc->drawing = xfc->primary;
-
xfc->bitmap_mono = XCreatePixmap(xfc->display, xfc->drawable, 8, 8, 1);
xfc->gc_mono = XCreateGC(xfc->display, xfc->bitmap_mono, GCGraphicsExposures, &gcv);
-
XSetFunction(xfc->display, xfc->gc, GXcopy);
XSetFillStyle(xfc->display, xfc->gc, FillSolid);
XSetForeground(xfc->display, xfc->gc, BlackPixelOfScreen(xfc->screen));
XFillRectangle(xfc->display, xfc->primary, xfc->gc, 0, 0, xfc->width, xfc->height);
XFlush(xfc->display);
-
xfc->image = XCreateImage(xfc->display, xfc->visual, xfc->depth, ZPixmap, 0,
- (char*) xfc->primary_buffer, xfc->width, xfc->height, xfc->scanline_pad, 0);
-
- xfc->bmp_codec_none = (BYTE*) malloc(64 * 64 * 4);
-
- if (xfc->settings->SoftwareGdi)
+ (char *) xfc->primary_buffer, xfc->width, xfc->height, xfc->scanline_pad, 0);
+ xfc->bmp_codec_none = (BYTE *) malloc(64 * 64 * 4);
+ if(xfc->settings->SoftwareGdi)
{
instance->update->BeginPaint = xf_sw_begin_paint;
instance->update->EndPaint = xf_sw_end_paint;
@@ -1007,10 +842,8 @@ BOOL xf_post_connect(freerdp* instance)
instance->update->EndPaint = xf_hw_end_paint;
instance->update->DesktopResize = xf_hw_desktop_resize;
}
-
pointer_cache_register_callbacks(instance->update);
-
- if (!xfc->settings->SoftwareGdi)
+ if(!xfc->settings->SoftwareGdi)
{
glyph_cache_register_callbacks(instance->update);
brush_cache_register_callbacks(instance->update);
@@ -1018,22 +851,16 @@ BOOL xf_post_connect(freerdp* instance)
offscreen_cache_register_callbacks(instance->update);
palette_cache_register_callbacks(instance->update);
}
-
instance->context->rail = rail_new(instance->settings);
rail_register_update_callbacks(instance->context->rail, instance->update);
xf_rail_register_callbacks(xfc, instance->context->rail);
-
freerdp_channels_post_connect(channels, instance);
-
xf_tsmf_init(xfc, xv_port);
-
xf_cliprdr_init(xfc, channels);
-
EventArgsInit(&e, "xfreerdp");
e.width = settings->DesktopWidth;
e.height = settings->DesktopHeight;
- PubSub_OnResizeWindow(((rdpContext*) xfc)->pubSub, xfc, &e);
-
+ PubSub_OnResizeWindow(((rdpContext *) xfc)->pubSub, xfc, &e);
return TRUE;
}
@@ -1049,15 +876,13 @@ BOOL xf_post_connect(freerdp* instance)
* @param domain - unused
* @return TRUE if a password was successfully entered. See freerdp_passphrase_read() for more details.
*/
-BOOL xf_authenticate(freerdp* instance, char** username, char** password, char** domain)
+BOOL xf_authenticate(freerdp *instance, char **username, char **password, char **domain)
{
// FIXME: seems this callback may be called when 'username' is not known.
// But it doesn't do anything to fix it...
*password = malloc(password_size * sizeof(char));
-
- if (freerdp_passphrase_read("Password: ", *password, password_size, instance->settings->CredentialsFromStdin) == NULL)
+ if(freerdp_passphrase_read("Password: ", *password, password_size, instance->settings->CredentialsFromStdin) == NULL)
return FALSE;
-
return TRUE;
}
@@ -1071,346 +896,273 @@ BOOL xf_authenticate(freerdp* instance, char** username, char** password, char**
* @param fingerprint
* @return TRUE if the certificate is trusted. FALSE otherwise.
*/
-BOOL xf_verify_certificate(freerdp* instance, char* subject, char* issuer, char* fingerprint)
+BOOL xf_verify_certificate(freerdp *instance, char *subject, char *issuer, char *fingerprint)
{
char answer;
-
printf("Certificate details:\n");
printf("\tSubject: %s\n", subject);
printf("\tIssuer: %s\n", issuer);
printf("\tThumbprint: %s\n", fingerprint);
printf("The above X.509 certificate could not be verified, possibly because you do not have "
- "the CA certificate in your certificate store, or the certificate has expired. "
- "Please look at the documentation on how to create local certificate store for a private CA.\n");
-
- while (1)
+ "the CA certificate in your certificate store, or the certificate has expired. "
+ "Please look at the documentation on how to create local certificate store for a private CA.\n");
+ while(1)
{
printf("Do you trust the above certificate? (Y/N) ");
answer = fgetc(stdin);
-
- if (feof(stdin))
+ if(feof(stdin))
{
printf("\nError: Could not read answer from stdin.");
- if (instance->settings->CredentialsFromStdin)
+ if(instance->settings->CredentialsFromStdin)
printf(" - Run without parameter \"--from-stdin\" to set trust.");
printf("\n");
return FALSE;
}
-
- if (answer == 'y' || answer == 'Y')
+ if(answer == 'y' || answer == 'Y')
{
return TRUE;
}
- else if (answer == 'n' || answer == 'N')
- {
- break;
- }
+ else
+ if(answer == 'n' || answer == 'N')
+ {
+ break;
+ }
printf("\n");
}
-
return FALSE;
}
-int xf_logon_error_info(freerdp* instance, UINT32 data, UINT32 type)
+int xf_logon_error_info(freerdp *instance, UINT32 data, UINT32 type)
{
- xfContext* xfc = (xfContext*) instance->context;
-
+ xfContext *xfc = (xfContext *) instance->context;
xf_rail_disable_remoteapp_mode(xfc);
-
return 1;
}
-void xf_process_channel_event(rdpChannels* channels, freerdp* instance)
+void xf_process_channel_event(rdpChannels *channels, freerdp *instance)
{
- xfContext* xfc;
- wMessage* event;
-
- xfc = (xfContext*) instance->context;
-
+ xfContext *xfc;
+ wMessage *event;
+ xfc = (xfContext *) instance->context;
event = freerdp_channels_pop_event(channels);
-
- if (event)
+ if(event)
{
- switch (GetMessageClass(event->id))
+ switch(GetMessageClass(event->id))
{
case RailChannel_Class:
xf_process_rail_event(xfc, channels, event);
break;
-
case TsmfChannel_Class:
xf_process_tsmf_event(xfc, event);
break;
-
case CliprdrChannel_Class:
xf_process_cliprdr_event(xfc, event);
break;
-
case RdpeiChannel_Class:
xf_process_rdpei_event(xfc, event);
break;
-
default:
break;
}
-
freerdp_event_free(event);
}
}
-void xf_window_free(xfContext* xfc)
+void xf_window_free(xfContext *xfc)
{
- rdpContext* context = (rdpContext*) xfc;
-
+ rdpContext *context = (rdpContext *) xfc;
xf_keyboard_free(xfc);
-
- if (xfc->gc)
+ if(xfc->gc)
{
XFreeGC(xfc->display, xfc->gc);
xfc->gc = 0;
}
-
- if (xfc->gc_mono)
+ if(xfc->gc_mono)
{
XFreeGC(xfc->display, xfc->gc_mono);
xfc->gc_mono = 0;
}
-
- if (xfc->window)
+ if(xfc->window)
{
xf_DestroyWindow(xfc, xfc->window);
xfc->window = NULL;
}
-
- if (xfc->primary)
+ if(xfc->primary)
{
XFreePixmap(xfc->display, xfc->primary);
xfc->primary = 0;
}
-
- if (xfc->bitmap_mono)
+ if(xfc->bitmap_mono)
{
XFreePixmap(xfc->display, xfc->bitmap_mono);
xfc->bitmap_mono = 0;
}
-
- if (xfc->image)
+ if(xfc->image)
{
xfc->image->data = NULL;
XDestroyImage(xfc->image);
xfc->image = NULL;
}
-
- if (context->cache)
+ if(context->cache)
{
cache_free(context->cache);
context->cache = NULL;
}
-
- if (context->rail)
+ if(context->rail)
{
rail_free(context->rail);
context->rail = NULL;
}
-
- if (xfc->rfx_context)
+ if(xfc->rfx_context)
{
rfx_context_free(xfc->rfx_context);
xfc->rfx_context = NULL;
}
-
- if (xfc->nsc_context)
+ if(xfc->nsc_context)
{
nsc_context_free(xfc->nsc_context);
xfc->nsc_context = NULL;
}
-
- if (xfc->clrconv)
+ if(xfc->clrconv)
{
freerdp_clrconv_free(xfc->clrconv);
xfc->clrconv = NULL;
}
-
- if (xfc->hdc)
+ if(xfc->hdc)
gdi_DeleteDC(xfc->hdc);
-
- if (xfc->xv_context)
+ if(xfc->xv_context)
{
xf_tsmf_uninit(xfc);
xfc->xv_context = NULL;
}
-
- if (xfc->clipboard_context)
+ if(xfc->clipboard_context)
{
xf_cliprdr_uninit(xfc);
xfc->clipboard_context = NULL;
}
}
-void* xf_update_thread(void* arg)
+void *xf_update_thread(void *arg)
{
int status;
wMessage message;
- wMessageQueue* queue;
- freerdp* instance = (freerdp*) arg;
-
- assert( NULL != instance);
-
+ wMessageQueue *queue;
+ freerdp *instance = (freerdp *) arg;
+ assert(NULL != instance);
status = 1;
queue = freerdp_get_message_queue(instance, FREERDP_UPDATE_MESSAGE_QUEUE);
-
- while (MessageQueue_Wait(queue))
+ while(MessageQueue_Wait(queue))
{
- while (MessageQueue_Peek(queue, &message, TRUE))
+ while(MessageQueue_Peek(queue, &message, TRUE))
{
status = freerdp_message_queue_process_message(instance, FREERDP_UPDATE_MESSAGE_QUEUE, &message);
-
- if (!status)
+ if(!status)
break;
}
-
- if (!status)
+ if(!status)
break;
}
-
ExitThread(0);
return NULL;
}
-void* xf_input_thread(void* arg)
+void *xf_input_thread(void *arg)
{
xfContext *xfc;
- HANDLE event[2];
+ HANDLE event;
XEvent xevent;
- wMessageQueue* queue;
+ wMessageQueue *queue;
int pending_status = 1;
int process_status = 1;
- freerdp* instance = (freerdp*) arg;
+ freerdp *instance = (freerdp *) arg;
assert(NULL != instance);
-
- xfc = (xfContext*) instance->context;
+ xfc = (xfContext *) instance->context;
assert(NULL != xfc);
-
queue = freerdp_get_message_queue(instance, FREERDP_INPUT_MESSAGE_QUEUE);
- event[0] = CreateFileDescriptorEvent(NULL, FALSE, FALSE, xfc->xfds);
- event[1] = MessageQueue_Event(queue);
- while(TRUE)
+ event = CreateFileDescriptorEvent(NULL, FALSE, FALSE, xfc->xfds);
+ while(WaitForSingleObject(event, INFINITE) == WAIT_OBJECT_0)
{
- DWORD ev = WaitForMultipleObjects(2, event, FALSE, INFINITE);
-
- if (ev == WAIT_OBJECT_0)
+ do
{
- do
+ xf_lock_x11(xfc, FALSE);
+ pending_status = XPending(xfc->display);
+ xf_unlock_x11(xfc, FALSE);
+ if(pending_status)
{
xf_lock_x11(xfc, FALSE);
-
- pending_status = XPending(xfc->display);
-
+ ZeroMemory(&xevent, sizeof(xevent));
+ XNextEvent(xfc->display, &xevent);
+ process_status = xf_event_process(instance, &xevent);
xf_unlock_x11(xfc, FALSE);
-
- if (pending_status)
- {
- xf_lock_x11(xfc, FALSE);
-
- ZeroMemory(&xevent, sizeof(xevent));
- XNextEvent(xfc->display, &xevent);
- process_status = xf_event_process(instance, &xevent);
-
- xf_unlock_x11(xfc, FALSE);
-
- if (!process_status)
- break;
- }
+ if(!process_status)
+ break;
}
- while(pending_status && WaitForSingleObject(event[1], 0) != WAIT_OBJECT_0);
- if(!process_status)
- break;
- }
- else if (ev == WAIT_OBJECT_0 + 1)
- {
- wMessage msg;
- MessageQueue_Peek(queue, &msg, FALSE);
-
- if (msg.id == WMQ_QUIT)
- break;
}
+ while(pending_status);
+ if(!process_status)
+ break;
}
-
MessageQueue_PostQuit(queue, 0);
ExitThread(0);
return NULL;
}
-void* xf_channels_thread(void* arg)
+void *xf_channels_thread(void *arg)
{
int status;
- xfContext* xfc;
+ xfContext *xfc;
HANDLE event;
- rdpChannels* channels;
- freerdp* instance = (freerdp*) arg;
+ rdpChannels *channels;
+ freerdp *instance = (freerdp *) arg;
assert(NULL != instance);
-
- xfc = (xfContext*) instance->context;
+ xfc = (xfContext *) instance->context;
assert(NULL != xfc);
-
channels = instance->context->channels;
event = freerdp_channels_get_event_handle(instance);
-
- while (WaitForSingleObject(event, INFINITE) == WAIT_OBJECT_0)
+ while(WaitForSingleObject(event, INFINITE) == WAIT_OBJECT_0)
{
status = freerdp_channels_process_pending_messages(instance);
- if (!status)
+ if(!status)
break;
-
xf_process_channel_event(channels, instance);
}
-
ExitThread(0);
return NULL;
}
-BOOL xf_auto_reconnect(freerdp* instance)
+BOOL xf_auto_reconnect(freerdp *instance)
{
- xfContext* xfc = (xfContext*) instance->context;
-
+ xfContext *xfc = (xfContext *) instance->context;
UINT32 num_retries = 0;
UINT32 max_retries = instance->settings->AutoReconnectMaxRetries;
-
/* Only auto reconnect on network disconnects. */
- if (freerdp_error_info(instance) != 0)
+ if(freerdp_error_info(instance) != 0)
return FALSE;
-
/* A network disconnect was detected */
fprintf(stderr, "Network disconnect!\n");
-
- if (!instance->settings->AutoReconnectionEnabled)
+ if(!instance->settings->AutoReconnectionEnabled)
{
/* No auto-reconnect - just quit */
return FALSE;
}
-
/* Perform an auto-reconnect. */
- for (;;)
+ for(;;)
{
/* Quit retrying if max retries has been exceeded */
- if (num_retries++ >= max_retries)
+ if(num_retries++ >= max_retries)
{
return FALSE;
}
-
/* Attempt the next reconnect */
fprintf(stderr, "Attempting reconnect (%u of %u)\n", num_retries, max_retries);
-
- if (freerdp_reconnect(instance))
+ if(freerdp_reconnect(instance))
{
xfc->disconnect = FALSE;
return TRUE;
}
-
sleep(5);
}
-
fprintf(stderr, "Maximum reconnect retries exceeded\n");
-
return FALSE;
}
@@ -1421,21 +1173,21 @@ BOOL xf_auto_reconnect(freerdp* instance)
* @param instance - pointer to the rdp_freerdp structure that contains the session's settings
* @return A code from the enum XF_EXIT_CODE (0 if successful)
*/
-void* xf_thread(void* param)
+void *xf_thread(void *param)
{
int i;
int fds;
- xfContext* xfc;
+ xfContext *xfc;
int max_fds;
int rcount;
int wcount;
BOOL status;
int exit_code;
- void* rfds[32];
- void* wfds[32];
+ void *rfds[32];
+ void *wfds[32];
fd_set rfds_set;
fd_set wfds_set;
- freerdp* instance;
+ freerdp *instance;
int fd_input_event;
HANDLE input_event;
int select_status;
@@ -1446,110 +1198,91 @@ void* xf_thread(void* param)
HANDLE update_thread;
HANDLE input_thread;
HANDLE channels_thread;
- rdpChannels* channels;
- rdpSettings* settings;
+ rdpChannels *channels;
+ rdpSettings *settings;
struct timeval timeout;
-
exit_code = 0;
input_event = NULL;
-
- instance = (freerdp*) param;
+ instance = (freerdp *) param;
assert(NULL != instance);
-
ZeroMemory(rfds, sizeof(rfds));
ZeroMemory(wfds, sizeof(wfds));
ZeroMemory(&timeout, sizeof(struct timeval));
-
status = freerdp_connect(instance);
-
- xfc = (xfContext*) instance->context;
+ xfc = (xfContext *) instance->context;
assert(NULL != xfc);
-
/* Connection succeeded. --authonly ? */
- if (instance->settings->AuthenticationOnly)
+ if(instance->settings->AuthenticationOnly)
{
freerdp_disconnect(instance);
fprintf(stderr, "Authentication only, exit status %d\n", !status);
ExitThread(exit_code);
}
-
- if (!status)
+ if(!status)
{
- if (xfc->mutex)
+ if(xfc->mutex)
{
WaitForSingleObject(xfc->mutex, INFINITE);
CloseHandle(xfc->mutex);
xfc->mutex = NULL;
}
-
xf_monitors_free(xfc, instance->settings);
-
exit_code = XF_EXIT_CONN_FAILED;
ExitThread(exit_code);
}
-
channels = instance->context->channels;
settings = instance->context->settings;
-
async_update = settings->AsyncUpdate;
async_input = settings->AsyncInput;
async_channels = settings->AsyncChannels;
async_transport = settings->AsyncTransport;
-
- if (async_update)
+ if(async_update)
{
update_thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) xf_update_thread, instance, 0, NULL);
}
-
- if (async_input)
+ if(async_input)
{
input_thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) xf_input_thread, instance, 0, NULL);
}
-
- if (async_channels)
+ if(async_channels)
{
channels_thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) xf_channels_thread, instance, 0, NULL);
}
-
- while (!xfc->disconnect && !freerdp_shall_disconnect(instance))
+ while(!xfc->disconnect && !freerdp_shall_disconnect(instance))
{
rcount = 0;
wcount = 0;
-
/*
* win8 and server 2k12 seem to have some timing issue/race condition
* when a initial sync request is send to sync the keyboard inidcators
* sending the sync event twice fixed this problem
*/
- if (freerdp_focus_required(instance))
+ if(freerdp_focus_required(instance))
{
xf_keyboard_focus_in(xfc);
xf_keyboard_focus_in(xfc);
}
-
- if (!async_transport)
+ if(!async_transport)
{
- if (freerdp_get_fds(instance, rfds, &rcount, wfds, &wcount) != TRUE)
+ if(freerdp_get_fds(instance, rfds, &rcount, wfds, &wcount) != TRUE)
{
fprintf(stderr, "Failed to get FreeRDP file descriptor\n");
exit_code = XF_EXIT_CONN_FAILED;
break;
}
}
-
- if (!async_channels)
+ if(!async_channels)
{
- if (freerdp_channels_get_fds(channels, instance, rfds, &rcount, wfds, &wcount) != TRUE)
+ if(freerdp_channels_get_fds(channels, instance, rfds, &rcount, wfds, &wcount) != TRUE)
{
fprintf(stderr, "Failed to get channel manager file descriptor\n");
exit_code = XF_EXIT_CONN_FAILED;
break;
}
}
-
- if (!async_input)
+ if(!async_input)
{
- if (xf_get_fds(instance, rfds, &rcount, wfds, &wcount) != TRUE)
+ if(xf_get_fds(instance, rfds, &rcount, wfds, &wcount) != TRUE)
{
fprintf(stderr, "Failed to get xfreerdp file descriptor\n");
exit_code = XF_EXIT_CONN_FAILED;
@@ -1560,72 +1293,60 @@ void* xf_thread(void* param)
{
input_event = freerdp_get_message_queue_event_handle(instance, FREERDP_INPUT_MESSAGE_QUEUE);
fd_input_event = GetEventFileDescriptor(input_event);
- rfds[rcount++] = (void*) (long) fd_input_event;
+ rfds[rcount++] = (void *)(long) fd_input_event;
}
-
max_fds = 0;
FD_ZERO(&rfds_set);
FD_ZERO(&wfds_set);
-
- for (i = 0; i < rcount; i++)
+ for(i = 0; i < rcount; i++)
{
fds = (int)(long)(rfds[i]);
-
- if (fds > max_fds)
+ if(fds > max_fds)
max_fds = fds;
-
FD_SET(fds, &rfds_set);
}
-
- if (max_fds == 0)
+ if(max_fds == 0)
break;
-
timeout.tv_sec = 1;
timeout.tv_usec = 0;
-
select_status = select(max_fds + 1, &rfds_set, NULL, NULL, &timeout);
-
- if (select_status == 0)
+ if(select_status == 0)
{
continue; /* select timeout */
}
- else if (select_status == -1)
- {
- /* these are not really errors */
- if (!((errno == EAGAIN) || (errno == EWOULDBLOCK) ||
- (errno == EINPROGRESS) || (errno == EINTR))) /* signal occurred */
+ else
+ if(select_status == -1)
{
- fprintf(stderr, "xfreerdp_run: select failed\n");
- break;
+ /* these are not really errors */
+ if(!((errno == EAGAIN) || (errno == EWOULDBLOCK) ||
+ (errno == EINPROGRESS) || (errno == EINTR))) /* signal occurred */
+ {
+ fprintf(stderr, "xfreerdp_run: select failed\n");
+ break;
+ }
}
- }
-
- if (!async_transport)
+ if(!async_transport)
{
- if (freerdp_check_fds(instance) != TRUE)
+ if(freerdp_check_fds(instance) != TRUE)
{
- if (xf_auto_reconnect(instance))
+ if(xf_auto_reconnect(instance))
continue;
-
fprintf(stderr, "Failed to check FreeRDP file descriptor\n");
break;
}
}
-
- if (!async_channels)
+ if(!async_channels)
{
- if (freerdp_channels_check_fds(channels, instance) != TRUE)
+ if(freerdp_channels_check_fds(channels, instance) != TRUE)
{
fprintf(stderr, "Failed to check channel manager file descriptor\n");
break;
}
-
xf_process_channel_event(channels, instance);
}
-
- if (!async_input)
+ if(!async_input)
{
- if (xf_process_x_events(instance) != TRUE)
+ if(xf_process_x_events(instance) != TRUE)
{
fprintf(stderr, "Closed from X11\n");
break;
@@ -1633,9 +1354,9 @@ void* xf_thread(void* param)
}
else
{
- if (WaitForSingleObject(input_event, 0) == WAIT_OBJECT_0)
+ if(WaitForSingleObject(input_event, 0) == WAIT_OBJECT_0)
{
- if (!freerdp_message_queue_process_pending_messages(instance, FREERDP_INPUT_MESSAGE_QUEUE))
+ if(!freerdp_message_queue_process_pending_messages(instance, FREERDP_INPUT_MESSAGE_QUEUE))
{
fprintf(stderr, "User Disconnect\n");
xfc->disconnect = TRUE;
@@ -1644,108 +1365,64 @@ void* xf_thread(void* param)
}
}
}
-
/* Close the channels first. This will signal the internal message pipes
* that the threads should quit. */
freerdp_channels_close(channels, instance);
-
- if (async_update)
+ if(async_update)
{
- wMessageQueue* update_queue = freerdp_get_message_queue(instance, FREERDP_UPDATE_MESSAGE_QUEUE);
+ wMessageQueue *update_queue = freerdp_get_message_queue(instance, FREERDP_UPDATE_MESSAGE_QUEUE);
MessageQueue_PostQuit(update_queue, 0);
WaitForSingleObject(update_thread, INFINITE);
CloseHandle(update_thread);
}
-
- if (async_input)
+ if(async_input)
{
- wMessageQueue* input_queue = freerdp_get_message_queue(instance, FREERDP_INPUT_MESSAGE_QUEUE);
+ wMessageQueue *input_queue = freerdp_get_message_queue(instance, FREERDP_INPUT_MESSAGE_QUEUE);
MessageQueue_PostQuit(input_queue, 0);
WaitForSingleObject(input_thread, INFINITE);
CloseHandle(input_thread);
}
-
- if (async_channels)
+ if(async_channels)
{
WaitForSingleObject(channels_thread, INFINITE);
CloseHandle(channels_thread);
}
-
- FILE* fin = fopen("/tmp/tsmf.tid", "rt");
-
- if (fin)
- {
- FILE* fin1;
- int thid = 0;
- int timeout;
-
- fscanf(fin, "%d", &thid);
- fclose(fin);
-
- pthread_kill((pthread_t) (size_t) thid, SIGUSR1);
-
- fin1 = fopen("/tmp/tsmf.tid", "rt");
- timeout = 5;
-
- while (fin1)
- {
- fclose(fin1);
- sleep(1);
- timeout--;
-
- if (timeout <= 0)
- {
- unlink("/tmp/tsmf.tid");
- pthread_kill((pthread_t) (size_t) thid, SIGKILL);
- break;
- }
-
- fin1 = fopen("/tmp/tsmf.tid", "rt");
- }
- }
-
- if (!exit_code)
+ if(!exit_code)
exit_code = freerdp_error_info(instance);
-
freerdp_channels_free(channels);
freerdp_disconnect(instance);
gdi_free(instance);
-
ExitThread(exit_code);
-
return NULL;
}
DWORD xf_exit_code_from_disconnect_reason(DWORD reason)
{
- if (reason == 0 || (reason >= XF_EXIT_PARSE_ARGUMENTS && reason <= XF_EXIT_CONN_FAILED))
- return reason;
-
+ if(reason == 0 || (reason >= XF_EXIT_PARSE_ARGUMENTS && reason <= XF_EXIT_CONN_FAILED))
+ return reason;
/* License error set */
- else if (reason >= 0x100 && reason <= 0x10A)
- reason -= 0x100 + XF_EXIT_LICENSE_INTERNAL;
-
+ else
+ if(reason >= 0x100 && reason <= 0x10A)
+ reason -= 0x100 + XF_EXIT_LICENSE_INTERNAL;
/* RDP protocol error set */
- else if (reason >= 0x10c9 && reason <= 0x1193)
- reason = XF_EXIT_RDP;
-
+ else
+ if(reason >= 0x10c9 && reason <= 0x1193)
+ reason = XF_EXIT_RDP;
/* There's no need to test protocol-independent codes: they match */
- else if (!(reason <= 0xB))
- reason = XF_EXIT_UNKNOWN;
-
+ else
+ if(!(reason <= 0xB))
+ reason = XF_EXIT_UNKNOWN;
return reason;
}
-void xf_TerminateEventHandler(rdpContext* context, TerminateEventArgs* e)
+void xf_TerminateEventHandler(rdpContext *context, TerminateEventArgs *e)
{
- wMessageQueue* queue;
- xfContext* xfc = (xfContext*) context;
-
- if (context->settings->AsyncInput)
+ wMessageQueue *queue;
+ xfContext *xfc = (xfContext *) context;
+ if(context->settings->AsyncInput)
{
queue = freerdp_get_message_queue(context->instance, FREERDP_INPUT_MESSAGE_QUEUE);
-
- if (queue)
+ if(queue)
MessageQueue_PostQuit(queue, 0);
}
else
@@ -1754,33 +1431,25 @@ void xf_TerminateEventHandler(rdpContext* context, TerminateEventArgs* e)
}
}
-static void xf_ScalingFactorChangeEventHandler(rdpContext* context, ScalingFactorChangeEventArgs* e)
+static void xf_ScalingFactorChangeEventHandler(rdpContext *context, ScalingFactorChangeEventArgs *e)
{
- xfContext* xfc = (xfContext*) context;
-
+ xfContext *xfc = (xfContext *) context;
xfc->settings->ScalingFactor += e->ScalingFactor;
-
- if (xfc->settings->ScalingFactor > 1.2)
+ if(xfc->settings->ScalingFactor > 1.2)
xfc->settings->ScalingFactor = 1.2;
- if (xfc->settings->ScalingFactor < 0.8)
+ if(xfc->settings->ScalingFactor < 0.8)
xfc->settings->ScalingFactor = 0.8;
-
-
xfc->currentWidth = xfc->originalWidth * xfc->settings->ScalingFactor;
xfc->currentHeight = xfc->originalHeight * xfc->settings->ScalingFactor;
-
xf_transform_window(xfc);
-
{
ResizeWindowEventArgs ev;
-
EventArgsInit(&ev, "xfreerdp");
ev.width = (int) xfc->originalWidth * xfc->settings->ScalingFactor;
ev.height = (int) xfc->originalHeight * xfc->settings->ScalingFactor;
- PubSub_OnResizeWindow(((rdpContext*) xfc)->pubSub, xfc, &ev);
+ PubSub_OnResizeWindow(((rdpContext *) xfc)->pubSub, xfc, &ev);
}
xf_draw_screen_scaled(xfc, 0, 0, 0, 0, FALSE);
-
}
/**
@@ -1799,107 +1468,85 @@ static void xfreerdp_client_global_uninit()
freerdp_channels_global_uninit();
}
-static int xfreerdp_client_start(rdpContext* context)
+static int xfreerdp_client_start(rdpContext *context)
{
- xfContext* xfc = (xfContext*) context;
-
- rdpSettings* settings = context->settings;
-
- if (!settings->ServerHostname)
+ xfContext *xfc = (xfContext *) context;
+ rdpSettings *settings = context->settings;
+ if(!settings->ServerHostname)
{
fprintf(stderr, "error: server hostname was not specified with /v:<server>[:port]\n");
return -1;
}
-
xfc->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) xf_thread,
- context->instance, 0, NULL);
-
+ context->instance, 0, NULL);
return 0;
}
-static int xfreerdp_client_stop(rdpContext* context)
+static int xfreerdp_client_stop(rdpContext *context)
{
- xfContext* xfc = (xfContext*) context;
-
+ xfContext *xfc = (xfContext *) context;
assert(NULL != context);
-
- if (context->settings->AsyncInput)
+ if(context->settings->AsyncInput)
{
- wMessageQueue* queue;
+ wMessageQueue *queue;
queue = freerdp_get_message_queue(context->instance, FREERDP_INPUT_MESSAGE_QUEUE);
-
- if (queue)
+ if(queue)
MessageQueue_PostQuit(queue, 0);
}
else
{
xfc->disconnect = TRUE;
}
-
- if (xfc->thread)
+ if(xfc->thread)
{
CloseHandle(xfc->thread);
xfc->thread = NULL;
}
-
return 0;
}
-static int xfreerdp_client_new(freerdp* instance, rdpContext* context)
+static int xfreerdp_client_new(freerdp *instance, rdpContext *context)
{
- xfContext* xfc;
- rdpSettings* settings;
-
- xfc = (xfContext*) instance->context;
-
+ xfContext *xfc;
+ rdpSettings *settings;
+ xfc = (xfContext *) instance->context;
instance->PreConnect = xf_pre_connect;
instance->PostConnect = xf_post_connect;
instance->PostDisconnect = xf_post_disconnect;
instance->Authenticate = xf_authenticate;
instance->VerifyCertificate = xf_verify_certificate;
instance->LogonErrorInfo = xf_logon_error_info;
-
context->channels = freerdp_channels_new();
-
settings = instance->settings;
xfc->settings = instance->context->settings;
-
PubSub_SubscribeTerminate(context->pubSub, (pTerminateEventHandler) xf_TerminateEventHandler);
PubSub_SubscribeScalingFactorChange(context->pubSub, (pScalingFactorChangeEventHandler) xf_ScalingFactorChangeEventHandler);
-
return 0;
}
-static void xfreerdp_client_free(freerdp* instance, rdpContext* context)
+static void xfreerdp_client_free(freerdp *instance, rdpContext *context)
{
- xfContext* xfc = (xfContext*) context;
-
- if (context)
+ xfContext *xfc = (xfContext *) context;
+ if(context)
{
xf_window_free(xfc);
-
- if (xfc->bmp_codec_none)
+ if(xfc->bmp_codec_none)
free(xfc->bmp_codec_none);
-
- if (xfc->display)
+ if(xfc->display)
XCloseDisplay(xfc->display);
}
}
-int RdpClientEntry(RDP_CLIENT_ENTRY_POINTS* pEntryPoints)
+int RdpClientEntry(RDP_CLIENT_ENTRY_POINTS *pEntryPoints)
{
pEntryPoints->Version = 1;
pEntryPoints->Size = sizeof(RDP_CLIENT_ENTRY_POINTS_V1);
-
pEntryPoints->GlobalInit = xfreerdp_client_global_init;
pEntryPoints->GlobalUninit = xfreerdp_client_global_uninit;
-
pEntryPoints->ContextSize = sizeof(xfContext);
pEntryPoints->ClientNew = xfreerdp_client_new;
pEntryPoints->ClientFree = xfreerdp_client_free;
-
pEntryPoints->ClientStart = xfreerdp_client_start;
pEntryPoints->ClientStop = xfreerdp_client_stop;
-
return 0;
}
diff --git a/client/X11/xf_window.c b/client/X11/xf_window.c
index 5b7c96b17..ba42368da 100644
--- a/client/X11/xf_window.c
+++ b/client/X11/xf_window.c
@@ -3,7 +3,7 @@
* X11 Windows
*
* Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
- * Copyright 2012 HP Development Company, LLC
+ * Copyright 2012 HP Development Company, LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -30,9 +30,11 @@
#include <X11/Xutil.h>
#include <X11/Xatom.h>
-#include <sys/shm.h>
-#include <sys/ipc.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <winpr/thread.h>
#include <winpr/crt.h>
#include <freerdp/rail.h>
@@ -93,9 +95,6 @@
#define PROP_MOTIF_WM_HINTS_ELEMENTS 5
-/* to be accessed by gstreamer plugin */
-#define SHARED_MEM_KEY 7777
-
struct _PropMotifWmHints
{
unsigned long flags;
@@ -109,164 +108,133 @@ typedef struct _PropMotifWmHints PropMotifWmHints;
/**
* Post an event from the client to the X server
*/
-void xf_SendClientEvent(xfContext* xfc, xfWindow* window, Atom atom, unsigned int numArgs, ...)
+void xf_SendClientEvent(xfContext *xfc, xfWindow *window, Atom atom, unsigned int numArgs, ...)
{
- XEvent xevent;
- unsigned int i;
- va_list argp;
-
- va_start(argp, numArgs);
-
- xevent.xclient.type = ClientMessage;
- xevent.xclient.serial = 0;
- xevent.xclient.send_event = False;
- xevent.xclient.display = xfc->display;
- xevent.xclient.window = window->handle;
- xevent.xclient.message_type = atom;
- xevent.xclient.format = 32;
-
- for (i=0; i<numArgs; i++)
- {
- xevent.xclient.data.l[i] = va_arg(argp, int);
- }
-
- DEBUG_X11("Send ClientMessage Event: wnd=0x%04X", (unsigned int) xevent.xclient.window);
-
- XSendEvent(xfc->display, RootWindowOfScreen(xfc->screen), False,
- SubstructureRedirectMask | SubstructureNotifyMask, &xevent);
- XSync(xfc->display, False);
-
- va_end(argp);
+ XEvent xevent;
+ unsigned int i;
+ va_list argp;
+ va_start(argp, numArgs);
+ xevent.xclient.type = ClientMessage;
+ xevent.xclient.serial = 0;
+ xevent.xclient.send_event = False;
+ xevent.xclient.display = xfc->display;
+ xevent.xclient.window = window->handle;
+ xevent.xclient.message_type = atom;
+ xevent.xclient.format = 32;
+ for(i=0; i<numArgs; i++)
+ {
+ xevent.xclient.data.l[i] = va_arg(argp, int);
+ }
+ DEBUG_X11("Send ClientMessage Event: wnd=0x%04X", (unsigned int) xevent.xclient.window);
+ XSendEvent(xfc->display, RootWindowOfScreen(xfc->screen), False,
+ SubstructureRedirectMask | SubstructureNotifyMask, &xevent);
+ XSync(xfc->display, False);
+ va_end(argp);
}
-void xf_SetWindowFullscreen(xfContext* xfc, xfWindow* window, BOOL fullscreen)
+void xf_SetWindowFullscreen(xfContext *xfc, xfWindow *window, BOOL fullscreen)
{
- if (fullscreen)
+ if(fullscreen)
{
- rdpSettings* settings = xfc->instance->settings;
-
+ rdpSettings *settings = xfc->instance->settings;
xf_SetWindowDecorations(xfc, window, FALSE);
-
XMoveResizeWindow(xfc->display, window->handle, settings->DesktopPosX, settings->DesktopPosY, window->width, window->height);
- XMapRaised(xfc->display, window->handle);
-
+ XMapRaised(xfc->display, window->handle);
window->fullscreen = TRUE;
}
}
/* http://tronche.com/gui/x/xlib/window-information/XGetWindowProperty.html */
-BOOL xf_GetWindowProperty(xfContext* xfc, Window window, Atom property, int length,
- unsigned long* nitems, unsigned long* bytes, BYTE** prop)
+BOOL xf_GetWindowProperty(xfContext *xfc, Window window, Atom property, int length,
+ unsigned long *nitems, unsigned long *bytes, BYTE **prop)
{
int status;
Atom actual_type;
int actual_format;
-
- if (property == None)
+ if(property == None)
return FALSE;
-
status = XGetWindowProperty(xfc->display, window,
- property, 0, length, FALSE, AnyPropertyType,
- &actual_type, &actual_format, nitems, bytes, prop);
-
- if (status != Success)
+ property, 0, length, FALSE, AnyPropertyType,
+ &actual_type, &actual_format, nitems, bytes, prop);
+ if(status != Success)
return FALSE;
-
- if (actual_type == None)
+ if(actual_type == None)
{
DEBUG_WARN("Property %lu does not exist", property);
return FALSE;
}
-
return TRUE;
}
-BOOL xf_GetCurrentDesktop(xfContext* xfc)
+BOOL xf_GetCurrentDesktop(xfContext *xfc)
{
BOOL status;
unsigned long nitems;
unsigned long bytes;
- unsigned char* prop;
-
+ unsigned char *prop;
status = xf_GetWindowProperty(xfc, DefaultRootWindow(xfc->display),
- xfc->_NET_CURRENT_DESKTOP, 1, &nitems, &bytes, &prop);
-
- if (!status)
+ xfc->_NET_CURRENT_DESKTOP, 1, &nitems, &bytes, &prop);
+ if(!status)
return FALSE;
-
xfc->current_desktop = (int) *prop;
free(prop);
-
return TRUE;
}
-BOOL xf_GetWorkArea(xfContext* xfc)
+BOOL xf_GetWorkArea(xfContext *xfc)
{
- long* plong;
+ long *plong;
BOOL status;
unsigned long nitems;
unsigned long bytes;
- unsigned char* prop;
-
+ unsigned char *prop;
status = xf_GetCurrentDesktop(xfc);
-
- if (status != TRUE)
+ if(status != TRUE)
return FALSE;
-
status = xf_GetWindowProperty(xfc, DefaultRootWindow(xfc->display),
- xfc->_NET_WORKAREA, 32 * 4, &nitems, &bytes, &prop);
-
- if (status != TRUE)
+ xfc->_NET_WORKAREA, 32 * 4, &nitems, &bytes, &prop);
+ if(status != TRUE)
return FALSE;
-
- if ((xfc->current_desktop * 4 + 3) >= nitems)
+ if((xfc->current_desktop * 4 + 3) >= nitems)
{
free(prop);
return FALSE;
}
-
- plong = (long*) prop;
-
+ plong = (long *) prop;
xfc->workArea.x = plong[xfc->current_desktop * 4 + 0];
xfc->workArea.y = plong[xfc->current_desktop * 4 + 1];
xfc->workArea.width = plong[xfc->current_desktop * 4 + 2];
xfc->workArea.height = plong[xfc->current_desktop * 4 + 3];
free(prop);
-
return TRUE;
}
-void xf_SetWindowDecorations(xfContext* xfc, xfWindow* window, BOOL show)
+void xf_SetWindowDecorations(xfContext *xfc, xfWindow *window, BOOL show)
{
PropMotifWmHints hints;
-
hints.decorations = (show) ? MWM_DECOR_ALL : 0;
- hints.functions = MWM_FUNC_ALL ;
+ hints.functions = MWM_FUNC_ALL ;
hints.flags = MWM_HINTS_DECORATIONS | MWM_HINTS_FUNCTIONS;
hints.inputMode = 0;
hints.status = 0;
-
XChangeProperty(xfc->display, window->handle, xfc->_MOTIF_WM_HINTS, xfc->_MOTIF_WM_HINTS, 32,
- PropModeReplace, (BYTE*) &hints, PROP_MOTIF_WM_HINTS_ELEMENTS);
+ PropModeReplace, (BYTE *) &hints, PROP_MOTIF_WM_HINTS_ELEMENTS);
}
-void xf_SetWindowUnlisted(xfContext* xfc, xfWindow* window)
+void xf_SetWindowUnlisted(xfContext *xfc, xfWindow *window)
{
Atom window_state[2];
-
window_state[0] = xfc->_NET_WM_STATE_SKIP_PAGER;
window_state[1] = xfc->_NET_WM_STATE_SKIP_TASKBAR;
-
XChangeProperty(xfc->display, window->handle, xfc->_NET_WM_STATE,
- XA_ATOM, 32, PropModeReplace, (BYTE*) &window_state, 2);
+ XA_ATOM, 32, PropModeReplace, (BYTE *) &window_state, 2);
}
-void xf_SetWindowStyle(xfContext* xfc, xfWindow* window, UINT32 style, UINT32 ex_style)
+void xf_SetWindowStyle(xfContext *xfc, xfWindow *window, UINT32 style, UINT32 ex_style)
{
Atom window_type;
-
- if (/*(ex_style & WS_EX_TOPMOST) ||*/ (ex_style & WS_EX_TOOLWINDOW))
+ if(/*(ex_style & WS_EX_TOPMOST) ||*/ (ex_style & WS_EX_TOOLWINDOW))
{
/*
* Tooltips and menu items should be unmanaged windows
@@ -280,7 +248,6 @@ void xf_SetWindowStyle(xfContext* xfc, xfWindow* window, UINT32 style, UINT32 ex
XSetWindowAttributes attrs;
attrs.override_redirect = True;
XChangeWindowAttributes(xfc->display, window->handle, CWOverrideRedirect, &attrs);
-
window->is_transient = TRUE;
xf_SetWindowUnlisted(xfc, window);
window_type = xfc->_NET_WM_WINDOW_TYPE_POPUP;
@@ -289,61 +256,61 @@ void xf_SetWindowStyle(xfContext* xfc, xfWindow* window, UINT32 style, UINT32 ex
* TOPMOST window that is not a toolwindow is treated like a regular window(ie. task manager).
* Want to do this here, since the window may have type WS_POPUP
*/
- else if (ex_style & WS_EX_TOPMOST)
- {
- window_type = xfc->_NET_WM_WINDOW_TYPE_NORMAL;
- }
- else if (style & WS_POPUP)
- {
- /* this includes dialogs, popups, etc, that need to be full-fledged windows */
- window->is_transient = TRUE;
- window_type = xfc->_NET_WM_WINDOW_TYPE_DIALOG;
- xf_SetWindowUnlisted(xfc, window);
- }
else
- {
- window_type = xfc->_NET_WM_WINDOW_TYPE_NORMAL;
- }
-
+ if(ex_style & WS_EX_TOPMOST)
+ {
+ window_type = xfc->_NET_WM_WINDOW_TYPE_NORMAL;
+ }
+ else
+ if(style & WS_POPUP)
+ {
+ /* this includes dialogs, popups, etc, that need to be full-fledged windows */
+ window->is_transient = TRUE;
+ window_type = xfc->_NET_WM_WINDOW_TYPE_DIALOG;
+ xf_SetWindowUnlisted(xfc, window);
+ }
+ else
+ {
+ window_type = xfc->_NET_WM_WINDOW_TYPE_NORMAL;
+ }
XChangeProperty(xfc->display, window->handle, xfc->_NET_WM_WINDOW_TYPE,
- XA_ATOM, 32, PropModeReplace, (BYTE*) &window_type, 1);
-
+ XA_ATOM, 32, PropModeReplace, (BYTE *) &window_type, 1);
}
-void xf_SetWindowText(xfContext* xfc, xfWindow* window, char *name)
+void xf_SetWindowText(xfContext *xfc, xfWindow *window, char *name)
{
XStoreName(xfc->display, window->handle, name);
}
-static void xf_SetWindowPID(xfContext* xfc, xfWindow* window, pid_t pid)
+static void xf_SetWindowPID(xfContext *xfc, xfWindow *window, pid_t pid)
{
Atom am_wm_pid;
-
- if (!pid)
+ if(!pid)
pid = getpid();
-
am_wm_pid = XInternAtom(xfc->display, "_NET_WM_PID", False);
-
XChangeProperty(xfc->display, window->handle, am_wm_pid, XA_CARDINAL,
- 32, PropModeReplace, (unsigned char *)&pid, 1);
+ 32, PropModeReplace, (unsigned char *)&pid, 1);
}
-xfWindow* xf_CreateDesktopWindow(xfContext* xfc, char* name, int width, int height, BOOL decorations)
+static const char *get_shm_id()
{
- xfWindow* window;
- XEvent xevent;
- rdpSettings* settings;
+ static char shm_id[64];
+ snprintf(shm_id, sizeof(shm_id), "com.freerdp.xfreerpd.tsmf_%016X", GetCurrentProcessId());
+ return shm_id;
+}
- window = (xfWindow*) malloc(sizeof(xfWindow));
+xfWindow *xf_CreateDesktopWindow(xfContext *xfc, char *name, int width, int height, BOOL decorations)
+{
+ xfWindow *window;
+ XEvent xevent;
+ rdpSettings *settings;
+ window = (xfWindow *) malloc(sizeof(xfWindow));
ZeroMemory(window, sizeof(xfWindow));
settings = xfc->instance->settings;
-
- if (window)
+ if(window)
{
- int shmid;
int input_mask;
- XClassHint* class_hints;
-
+ XClassHint *class_hints;
window->width = width;
window->height = height;
window->fullscreen = FALSE;
@@ -351,109 +318,89 @@ xfWindow* xf_CreateDesktopWindow(xfContext* xfc, char* name, int width, int heig
window->local_move.state = LMS_NOT_ACTIVE;
window->is_mapped = FALSE;
window->is_transient = FALSE;
-
window->handle = XCreateWindow(xfc->display, RootWindowOfScreen(xfc->screen),
- xfc->workArea.x, xfc->workArea.y, xfc->workArea.width, xfc->workArea.height, 0, xfc->depth, InputOutput, xfc->visual,
- CWBackPixel | CWBackingStore | CWOverrideRedirect | CWColormap |
- CWBorderPixel | CWWinGravity | CWBitGravity, &xfc->attribs);
-
- shmid = shmget(SHARED_MEM_KEY, sizeof(int), IPC_CREAT | 0666);
-
- if (shmid < 0)
+ xfc->workArea.x, xfc->workArea.y, xfc->workArea.width, xfc->workArea.height, 0, xfc->depth, InputOutput, xfc->visual,
+ CWBackPixel | CWBackingStore | CWOverrideRedirect | CWColormap |
+ CWBorderPixel | CWWinGravity | CWBitGravity, &xfc->attribs);
+ window->shmid = shm_open(get_shm_id(), O_CREAT | O_EXCL | O_RDWR, S_IREAD | S_IWRITE);
+ if(window->shmid < 0)
{
DEBUG_X11("xf_CreateDesktopWindow: failed to get access to shared memory - shmget()\n");
}
else
{
- int* xfwin = shmat(shmid, NULL, 0);
-
- if (xfwin == (int*) -1)
+ ftruncate(window->shmid, sizeof(window->handle));
+ window->xfwin = mmap(0, sizeof(window->handle), PROT_READ | PROT_WRITE, MAP_SHARED, window->shmid, 0);
+ if(window->xfwin == (int *) -1)
{
DEBUG_X11("xf_CreateDesktopWindow: failed to assign pointer to the memory address - shmat()\n");
}
else
{
- *xfwin = (int) window->handle;
+ *window->xfwin = window->handle;
}
}
-
class_hints = XAllocClassHint();
-
- if (class_hints)
+ if(class_hints)
{
class_hints->res_name = "xfreerdp";
-
- if (xfc->instance->settings->WmClass)
+ if(xfc->instance->settings->WmClass)
class_hints->res_class = xfc->instance->settings->WmClass;
- else
+ else
class_hints->res_class = "xfreerdp";
-
XSetClassHint(xfc->display, window->handle, class_hints);
XFree(class_hints);
}
-
xf_ResizeDesktopWindow(xfc, window, width, height);
xf_SetWindowDecorations(xfc, window, decorations);
xf_SetWindowPID(xfc, window, 0);
-
input_mask =
KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |
VisibilityChangeMask | FocusChangeMask | StructureNotifyMask |
PointerMotionMask | ExposureMask | PropertyChangeMask;
-
- if (xfc->grab_keyboard)
+ if(xfc->grab_keyboard)
input_mask |= EnterWindowMask | LeaveWindowMask;
-
XChangeProperty(xfc->display, window->handle, xfc->_NET_WM_ICON, XA_CARDINAL, 32,
- PropModeReplace, (BYTE*) xf_icon_prop, ARRAYSIZE(xf_icon_prop));
-
- if (xfc->settings->ParentWindowId)
- XReparentWindow(xfc->display, window->handle, (Window) xfc->settings->ParentWindowId, 0, 0);
-
+ PropModeReplace, (BYTE *) xf_icon_prop, ARRAYSIZE(xf_icon_prop));
+ if(xfc->settings->ParentWindowId)
+ XReparentWindow(xfc->display, window->handle, (Window) xfc->settings->ParentWindowId, 0, 0);
XSelectInput(xfc->display, window->handle, input_mask);
XClearWindow(xfc->display, window->handle);
XMapWindow(xfc->display, window->handle);
-
xf_input_init(xfc, window->handle);
-
/*
- * NOTE: This must be done here to handle reparenting the window,
+ * NOTE: This must be done here to handle reparenting the window,
* so that we don't miss the event and hang waiting for the next one
*/
- do
- {
- XMaskEvent(xfc->display, VisibilityChangeMask, &xevent);
- }
- while (xevent.type != VisibilityNotify);
-
+ do
+ {
+ XMaskEvent(xfc->display, VisibilityChangeMask, &xevent);
+ }
+ while(xevent.type != VisibilityNotify);
/*
* The XCreateWindow call will start the window in the upper-left corner of our current
* monitor instead of the upper-left monitor for remote app mode(which uses all monitors).
* This extra call after the window is mapped will position the login window correctly
*/
-
- if (xfc->instance->settings->RemoteApplicationMode)
- {
- XMoveWindow(xfc->display, window->handle, 0, 0);
- }
- else if (settings->DesktopPosX || settings->DesktopPosY)
+ if(xfc->instance->settings->RemoteApplicationMode)
{
- XMoveWindow(xfc->display, window->handle, settings->DesktopPosX, settings->DesktopPosY);
+ XMoveWindow(xfc->display, window->handle, 0, 0);
}
+ else
+ if(settings->DesktopPosX || settings->DesktopPosY)
+ {
+ XMoveWindow(xfc->display, window->handle, settings->DesktopPosX, settings->DesktopPosY);
+ }
}
-
xf_SetWindowText(xfc, window, name);
-
return window;
}
-void xf_ResizeDesktopWindow(xfContext* xfc, xfWindow* window, int width, int height)
+void xf_ResizeDesktopWindow(xfContext *xfc, xfWindow *window, int width, int height)
{
- XSizeHints* size_hints;
-
+ XSizeHints *size_hints;
size_hints = XAllocSizeHints();
-
- if (size_hints)
+ if(size_hints)
{
size_hints->flags = PMinSize | PMaxSize;
size_hints->min_width = size_hints->max_width = xfc->width;
@@ -464,37 +411,35 @@ void xf_ResizeDesktopWindow(xfContext* xfc, xfWindow* window, int width, int hei
}
}
-void xf_FixWindowCoordinates(xfContext* xfc, int* x, int* y, int* width, int* height)
+void xf_FixWindowCoordinates(xfContext *xfc, int *x, int *y, int *width, int *height)
{
int vscreen_width;
int vscreen_height;
-
vscreen_width = xfc->vscreen.area.right - xfc->vscreen.area.left + 1;
vscreen_height = xfc->vscreen.area.bottom - xfc->vscreen.area.top + 1;
-
- if (*width < 1)
+ if(*width < 1)
{
*width = 1;
}
- if (*height < 1)
+ if(*height < 1)
{
*height = 1;
}
- if (*x < xfc->vscreen.area.left)
+ if(*x < xfc->vscreen.area.left)
{
*width += *x;
*x = xfc->vscreen.area.left;
}
- if (*y < xfc->vscreen.area.top)
+ if(*y < xfc->vscreen.area.top)
{
*height += *y;
*y = xfc->vscreen.area.top;
}
- if (*width > vscreen_width)
+ if(*width > vscreen_width)
{
*width = vscreen_width;
}
- if (*height > vscreen_height)
+ if(*height > vscreen_height)
{
*height = vscreen_height;
}
@@ -502,59 +447,47 @@ void xf_FixWindowCoordinates(xfContext* xfc, int* x, int* y, int* width, int* he
char rail_window_class[] = "RAIL:00000000";
-xfWindow* xf_CreateWindow(xfContext* xfc, rdpWindow* wnd, int x, int y, int width, int height, UINT32 id)
+xfWindow *xf_CreateWindow(xfContext *xfc, rdpWindow *wnd, int x, int y, int width, int height, UINT32 id)
{
XGCValues gcv;
int input_mask;
- xfWindow* window;
- XWMHints* InputModeHint;
- XClassHint* class_hints;
-
- window = (xfWindow*) malloc(sizeof(xfWindow));
+ xfWindow *window;
+ XWMHints *InputModeHint;
+ XClassHint *class_hints;
+ window = (xfWindow *) malloc(sizeof(xfWindow));
ZeroMemory(window, sizeof(xfWindow));
-
xf_FixWindowCoordinates(xfc, &x, &y, &width, &height);
-
window->left = x;
window->top = y;
window->right = x + width - 1;
window->bottom = y + height - 1;
window->width = width;
window->height = height;
-
/*
* WS_EX_DECORATIONS is used by XRDP and instructs
* the client to use local window decorations
*/
-
window->decorations = (wnd->extendedStyle & WS_EX_DECORATIONS) ? TRUE : FALSE;
-
window->fullscreen = FALSE;
window->window = wnd;
window->local_move.state = LMS_NOT_ACTIVE;
window->is_mapped = FALSE;
window->is_transient = FALSE;
window->rail_state = 0;
- window->rail_ignore_configure = FALSE;
-
+ window->rail_ignore_configure = FALSE;
window->handle = XCreateWindow(xfc->display, RootWindowOfScreen(xfc->screen),
- x, y, window->width, window->height, 0, xfc->depth, InputOutput, xfc->visual,
- 0, &xfc->attribs);
-
+ x, y, window->width, window->height, 0, xfc->depth, InputOutput, xfc->visual,
+ 0, &xfc->attribs);
DEBUG_X11_LMS("Create window=0x%X rc={l=%d t=%d r=%d b=%d} w=%d h=%d rdp=0x%X",
- (UINT32) window->handle, window->left, window->top, window->right, window->bottom,
- window->width, window->height, wnd->windowId);
-
+ (UINT32) window->handle, window->left, window->top, window->right, window->bottom,
+ window->width, window->height, wnd->windowId);
ZeroMemory(&gcv, sizeof(gcv));
window->gc = XCreateGC(xfc->display, window->handle, GCGraphicsExposures, &gcv);
-
class_hints = XAllocClassHint();
-
- if (class_hints)
+ if(class_hints)
{
- char* class = NULL;
-
- if (xfc->instance->settings->WmClass != NULL)
+ char *class = NULL;
+ if(xfc->instance->settings->WmClass != NULL)
{
class_hints->res_class = xfc->instance->settings->WmClass;
}
@@ -564,294 +497,242 @@ xfWindow* xf_CreateWindow(xfContext* xfc, rdpWindow* wnd, int x, int y, int widt
snprintf(class, sizeof(rail_window_class), "RAIL:%08X", id);
class_hints->res_class = class;
}
-
class_hints->res_name = "RAIL";
XSetClassHint(xfc->display, window->handle, class_hints);
XFree(class_hints);
-
- if (class)
+ if(class)
free(class);
}
-
/* Set the input mode hint for the WM */
- InputModeHint = XAllocWMHints();
- InputModeHint->flags = (1L << 0);
- InputModeHint->input = True;
- XSetWMHints(xfc->display, window->handle, InputModeHint);
- XFree(InputModeHint);
-
+ InputModeHint = XAllocWMHints();
+ InputModeHint->flags = (1L << 0);
+ InputModeHint->input = True;
+ XSetWMHints(xfc->display, window->handle, InputModeHint);
+ XFree(InputModeHint);
XSetWMProtocols(xfc->display, window->handle, &(xfc->WM_DELETE_WINDOW), 1);
-
input_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask |
- ButtonReleaseMask | EnterWindowMask | LeaveWindowMask |
- PointerMotionMask | Button1MotionMask | Button2MotionMask |
- Button3MotionMask | Button4MotionMask | Button5MotionMask |
- ButtonMotionMask | KeymapStateMask | ExposureMask |
- VisibilityChangeMask | StructureNotifyMask | SubstructureNotifyMask |
- SubstructureRedirectMask | FocusChangeMask | PropertyChangeMask |
- ColormapChangeMask | OwnerGrabButtonMask;
-
+ ButtonReleaseMask | EnterWindowMask | LeaveWindowMask |
+ PointerMotionMask | Button1MotionMask | Button2MotionMask |
+ Button3MotionMask | Button4MotionMask | Button5MotionMask |
+ ButtonMotionMask | KeymapStateMask | ExposureMask |
+ VisibilityChangeMask | StructureNotifyMask | SubstructureNotifyMask |
+ SubstructureRedirectMask | FocusChangeMask | PropertyChangeMask |
+ ColormapChangeMask | OwnerGrabButtonMask;
XSelectInput(xfc->display, window->handle, input_mask);
-
xf_SetWindowDecorations(xfc, window, window->decorations);
xf_SetWindowStyle(xfc, window, wnd->style, wnd->extendedStyle);
xf_SetWindowPID(xfc, window, 0);
xf_ShowWindow(xfc, window, WINDOW_SHOW);
-
XClearWindow(xfc->display, window->handle);
XMapWindow(xfc->display, window->handle);
-
/* Move doesn't seem to work until window is mapped. */
xf_MoveWindow(xfc, window, x, y, width, height);
-
return window;
}
-void xf_SetWindowMinMaxInfo(xfContext* xfc, xfWindow* window,
- int maxWidth, int maxHeight, int maxPosX, int maxPosY,
- int minTrackWidth, int minTrackHeight, int maxTrackWidth, int maxTrackHeight)
+void xf_SetWindowMinMaxInfo(xfContext *xfc, xfWindow *window,
+ int maxWidth, int maxHeight, int maxPosX, int maxPosY,
+ int minTrackWidth, int minTrackHeight, int maxTrackWidth, int maxTrackHeight)
{
- XSizeHints* size_hints;
-
+ XSizeHints *size_hints;
size_hints = XAllocSizeHints();
-
- if (size_hints)
+ if(size_hints)
{
size_hints->flags = PMinSize | PMaxSize | PResizeInc;
-
size_hints->min_width = minTrackWidth;
size_hints->min_height = minTrackHeight;
-
size_hints->max_width = maxTrackWidth;
size_hints->max_height = maxTrackHeight;
-
/* to speedup window drawing we need to select optimal value for sizing step. */
size_hints->width_inc = size_hints->height_inc = 1;
-
XSetWMNormalHints(xfc->display, window->handle, size_hints);
XFree(size_hints);
}
}
-void xf_StartLocalMoveSize(xfContext* xfc, xfWindow* window, int direction, int x, int y)
+void xf_StartLocalMoveSize(xfContext *xfc, xfWindow *window, int direction, int x, int y)
{
- if (window->local_move.state != LMS_NOT_ACTIVE)
+ if(window->local_move.state != LMS_NOT_ACTIVE)
return;
-
DEBUG_X11_LMS("direction=%d window=0x%X rc={l=%d t=%d r=%d b=%d} w=%d h=%d "
- "RDP=0x%X rc={l=%d t=%d} w=%d h=%d mouse_x=%d mouse_y=%d",
- direction, (UINT32) window->handle,
- window->left, window->top, window->right, window->bottom,
- window->width, window->height, window->window->windowId,
- window->window->windowOffsetX, window->window->windowOffsetY,
- window->window->windowWidth, window->window->windowHeight, x, y);
-
+ "RDP=0x%X rc={l=%d t=%d} w=%d h=%d mouse_x=%d mouse_y=%d",
+ direction, (UINT32) window->handle,
+ window->left, window->top, window->right, window->bottom,
+ window->width, window->height, window->window->windowId,
+ window->window->windowOffsetX, window->window->windowOffsetY,
+ window->window->windowWidth, window->window->windowHeight, x, y);
/*
* Save original mouse location relative to root. This will be needed
* to end local move to RDP server and/or X server
*/
- window->local_move.root_x = x;
+ window->local_move.root_x = x;
window->local_move.root_y = y;
window->local_move.state = LMS_STARTING;
window->local_move.direction = direction;
-
XUngrabPointer(xfc->display, CurrentTime);
-
- xf_SendClientEvent(xfc, window,
- xfc->_NET_WM_MOVERESIZE, /* request X window manager to initiate a local move */
- 5, /* 5 arguments to follow */
- x, /* x relative to root window */
- y, /* y relative to root window */
- direction, /* extended ICCM direction flag */
- 1, /* simulated mouse button 1 */
- 1); /* 1 == application request per extended ICCM */
+ xf_SendClientEvent(xfc, window,
+ xfc->_NET_WM_MOVERESIZE, /* request X window manager to initiate a local move */
+ 5, /* 5 arguments to follow */
+ x, /* x relative to root window */
+ y, /* y relative to root window */
+ direction, /* extended ICCM direction flag */
+ 1, /* simulated mouse button 1 */
+ 1); /* 1 == application request per extended ICCM */
}
-void xf_EndLocalMoveSize(xfContext* xfc, xfWindow *window)
+void xf_EndLocalMoveSize(xfContext *xfc, xfWindow *window)
{
-
DEBUG_X11_LMS("state=%d window=0x%X rc={l=%d t=%d r=%d b=%d} w=%d h=%d "
- "RDP=0x%X rc={l=%d t=%d} w=%d h=%d",
- window->local_move.state,
- (UINT32) window->handle, window->left, window->top, window->right, window->bottom,
- window->width, window->height, window->window->windowId,
- window->window->windowOffsetX, window->window->windowOffsetY,
- window->window->windowWidth, window->window->windowHeight);
-
- if (window->local_move.state == LMS_NOT_ACTIVE)
+ "RDP=0x%X rc={l=%d t=%d} w=%d h=%d",
+ window->local_move.state,
+ (UINT32) window->handle, window->left, window->top, window->right, window->bottom,
+ window->width, window->height, window->window->windowId,
+ window->window->windowOffsetX, window->window->windowOffsetY,
+ window->window->windowWidth, window->window->windowHeight);
+ if(window->local_move.state == LMS_NOT_ACTIVE)
return;
-
- if (window->local_move.state == LMS_STARTING)
+ if(window->local_move.state == LMS_STARTING)
{
/*
* The move never was property started. This can happen due to race
* conditions between the mouse button up and the communications to the
* RDP server for local moves. We must cancel the X window manager move.
- * Per ICCM, the X client can ask to cancel an active move.
+ * Per ICCM, the X client can ask to cancel an active move.
*/
- xf_SendClientEvent(xfc, window,
- xfc->_NET_WM_MOVERESIZE, /* request X window manager to abort a local move */
- 5, /* 5 arguments to follow */
- window->local_move.root_x, /* x relative to root window */
- window->local_move.root_y, /* y relative to root window */
- _NET_WM_MOVERESIZE_CANCEL, /* extended ICCM direction flag */
- 1, /* simulated mouse button 1 */
- 1); /* 1 == application request per extended ICCM */
+ xf_SendClientEvent(xfc, window,
+ xfc->_NET_WM_MOVERESIZE, /* request X window manager to abort a local move */
+ 5, /* 5 arguments to follow */
+ window->local_move.root_x, /* x relative to root window */
+ window->local_move.root_y, /* y relative to root window */
+ _NET_WM_MOVERESIZE_CANCEL, /* extended ICCM direction flag */
+ 1, /* simulated mouse button 1 */
+ 1); /* 1 == application request per extended ICCM */
}
-
window->local_move.state = LMS_NOT_ACTIVE;
}
-void xf_MoveWindow(xfContext* xfc, xfWindow* window, int x, int y, int width, int height)
+void xf_MoveWindow(xfContext *xfc, xfWindow *window, int x, int y, int width, int height)
{
BOOL resize = FALSE;
-
- if ((width * height) < 1)
+ if((width * height) < 1)
return;
-
- if ((window->width != width) || (window->height != height))
+ if((window->width != width) || (window->height != height))
resize = TRUE;
-
- if (window->local_move.state == LMS_STARTING ||
- window->local_move.state == LMS_ACTIVE)
+ if(window->local_move.state == LMS_STARTING ||
+ window->local_move.state == LMS_ACTIVE)
return;
-
DEBUG_X11_LMS("window=0x%X rc={l=%d t=%d r=%d b=%d} w=%u h=%u "
- "new rc={l=%d t=%d r=%d b=%d} w=%u h=%u"
- " RDP=0x%X rc={l=%d t=%d} w=%d h=%d",
- (UINT32) window->handle, window->left, window->top,
- window->right, window->bottom, window->width, window->height,
- x, y, x + width -1, y + height -1, width, height,
- window->window->windowId,
- window->window->windowOffsetX, window->window->windowOffsetY,
- window->window->windowWidth, window->window->windowHeight);
-
+ "new rc={l=%d t=%d r=%d b=%d} w=%u h=%u"
+ " RDP=0x%X rc={l=%d t=%d} w=%d h=%d",
+ (UINT32) window->handle, window->left, window->top,
+ window->right, window->bottom, window->width, window->height,
+ x, y, x + width -1, y + height -1, width, height,
+ window->window->windowId,
+ window->window->windowOffsetX, window->window->windowOffsetY,
+ window->window->windowWidth, window->window->windowHeight);
window->left = x;
window->top = y;
window->right = x + width - 1;
window->bottom = y + height - 1;
window->width = width;
window->height = height;
-
- if (resize)
+ if(resize)
XMoveResizeWindow(xfc->display, window->handle, x, y, width, height);
else
XMoveWindow(xfc->display, window->handle, x, y);
-
xf_UpdateWindowArea(xfc, window, 0, 0, width, height);
}
-void xf_ShowWindow(xfContext* xfc, xfWindow* window, BYTE state)
+void xf_ShowWindow(xfContext *xfc, xfWindow *window, BYTE state)
{
- switch (state)
+ switch(state)
{
case WINDOW_HIDE:
XWithdrawWindow(xfc->display, window->handle, xfc->screen_number);
break;
-
case WINDOW_SHOW_MINIMIZED:
XIconifyWindow(xfc->display, window->handle, xfc->screen_number);
break;
-
case WINDOW_SHOW_MAXIMIZED:
/* Set the window as maximized */
xf_SendClientEvent(xfc, window, xfc->_NET_WM_STATE, 4, 1,
- XInternAtom(xfc->display, "_NET_WM_STATE_MAXIMIZED_VERT", False),
- XInternAtom(xfc->display, "_NET_WM_STATE_MAXIMIZED_HORZ", False), 0);
-
+ XInternAtom(xfc->display, "_NET_WM_STATE_MAXIMIZED_VERT", False),
+ XInternAtom(xfc->display, "_NET_WM_STATE_MAXIMIZED_HORZ", False), 0);
/*
* This is a workaround for the case where the window is maximized locally before the rail server is told to maximize
* the window, this appears to be a race condition where the local window with incomplete data and once the window is
* actually maximized on the server - an update of the new areas may not happen. So, we simply to do a full update of
* the entire window once the rail server notifies us that the window is now maximized.
*/
-
- if (window->rail_state == WINDOW_SHOW_MAXIMIZED)
- xf_UpdateWindowArea(xfc, window, 0, 0, window->window->windowWidth, window->window->windowHeight);
+ if(window->rail_state == WINDOW_SHOW_MAXIMIZED)
+ xf_UpdateWindowArea(xfc, window, 0, 0, window->window->windowWidth, window->window->windowHeight);
break;
-
case WINDOW_SHOW:
/* Ensure the window is not maximized */
xf_SendClientEvent(xfc, window, xfc->_NET_WM_STATE, 4, 0,
- XInternAtom(xfc->display, "_NET_WM_STATE_MAXIMIZED_VERT", False),
- XInternAtom(xfc->display, "_NET_WM_STATE_MAXIMIZED_HORZ", False), 0);
-
+ XInternAtom(xfc->display, "_NET_WM_STATE_MAXIMIZED_VERT", False),
+ XInternAtom(xfc->display, "_NET_WM_STATE_MAXIMIZED_HORZ", False), 0);
/*
* Ignore configure requests until both the Maximized properties have been processed
* to prevent condition where WM overrides size of request due to one or both of these properties
* still being set - which causes a position adjustment to be sent back to the server
* thus causing the window to not return to its original size
*/
-
- if (window->rail_state == WINDOW_SHOW_MAXIMIZED)
- window->rail_ignore_configure = TRUE;
-
- if (window->is_transient)
+ if(window->rail_state == WINDOW_SHOW_MAXIMIZED)
+ window->rail_ignore_configure = TRUE;
+ if(window->is_transient)
xf_SetWindowUnlisted(xfc, window);
-
break;
}
-
/* Save the current rail state of this window */
window->rail_state = state;
-
XFlush(xfc->display);
}
-void xf_SetWindowIcon(xfContext* xfc, xfWindow* window, rdpIcon* icon)
+void xf_SetWindowIcon(xfContext *xfc, xfWindow *window, rdpIcon *icon)
{
int x, y;
int pixels;
int propsize;
- long* propdata;
- long* dstp;
- UINT32* srcp;
-
- if (!icon->big)
+ long *propdata;
+ long *dstp;
+ UINT32 *srcp;
+ if(!icon->big)
return;
-
pixels = icon->entry->width * icon->entry->height;
propsize = 2 + pixels;
propdata = malloc(propsize * sizeof(long));
-
propdata[0] = icon->entry->width;
propdata[1] = icon->entry->height;
dstp = &(propdata[2]);
- srcp = (UINT32*) icon->extra;
-
- for (y = 0; y < icon->entry->height; y++)
+ srcp = (UINT32 *) icon->extra;
+ for(y = 0; y < icon->entry->height; y++)
{
- for (x = 0; x < icon->entry->width; x++)
+ for(x = 0; x < icon->entry->width; x++)
{
*dstp++ = *srcp++;
}
}
-
XChangeProperty(xfc->display, window->handle, xfc->_NET_WM_ICON, XA_CARDINAL, 32,
- PropModeReplace, (BYTE*) propdata, propsize);
-
+ PropModeReplace, (BYTE *) propdata, propsize);
XFlush(xfc->display);
free(propdata);
}
-void xf_SetWindowRects(xfContext* xfc, xfWindow* window, RECTANGLE_16* rects, int nrects)
+void xf_SetWindowRects(xfContext *xfc, xfWindow *window, RECTANGLE_16 *rects, int nrects)
{
int i;
- XRectangle* xrects;
-
- if (nrects == 0)
+ XRectangle *xrects;
+ if(nrects == 0)
return;
-
xrects = malloc(sizeof(XRectangle) * nrects);
-
- for (i = 0; i < nrects; i++)
+ for(i = 0; i < nrects; i++)
{
xrects[i].x = rects[i].left;
xrects[i].y = rects[i].top;
xrects[i].width = rects[i].right - rects[i].left;
xrects[i].height = rects[i].bottom - rects[i].top;
}
-
#ifdef WITH_XEXT
/*
* This is currently unsupported with the new logic to handle window placement with VisibleOffset variables
@@ -860,28 +741,23 @@ void xf_SetWindowRects(xfContext* xfc, xfWindow* window, RECTANGLE_16* rects, in
*/
XShapeCombineRectangles(xfc->display, window->handle, ShapeBounding, 0, 0, xrects, nrects, ShapeSet, 0);
#endif
-
free(xrects);
}
-void xf_SetWindowVisibilityRects(xfContext* xfc, xfWindow* window, RECTANGLE_16* rects, int nrects)
+void xf_SetWindowVisibilityRects(xfContext *xfc, xfWindow *window, RECTANGLE_16 *rects, int nrects)
{
int i;
- XRectangle* xrects;
-
- if (nrects == 0)
+ XRectangle *xrects;
+ if(nrects == 0)
return;
-
xrects = malloc(sizeof(XRectangle) * nrects);
-
- for (i = 0; i < nrects; i++)
+ for(i = 0; i < nrects; i++)
{
xrects[i].x = rects[i].left;
xrects[i].y = rects[i].top;
xrects[i].width = rects[i].right - rects[i].left;
xrects[i].height = rects[i].bottom - rects[i].top;
}
-
#ifdef WITH_XEXT
/*
* This is currently unsupported with the new logic to handle window placement with VisibleOffset variables
@@ -890,110 +766,94 @@ void xf_SetWindowVisibilityRects(xfContext* xfc, xfWindow* window, RECTANGLE_16*
*/
XShapeCombineRectangles(xfc->display, window->handle, ShapeBounding, 0, 0, xrects, nrects, ShapeSet, 0);
#endif
-
free(xrects);
}
-void xf_UpdateWindowArea(xfContext* xfc, xfWindow* window, int x, int y, int width, int height)
+void xf_UpdateWindowArea(xfContext *xfc, xfWindow *window, int x, int y, int width, int height)
{
int ax, ay;
- rdpWindow* wnd;
+ rdpWindow *wnd;
wnd = window->window;
-
/* RemoteApp mode uses visibleOffset instead of windowOffset */
-
- if (!xfc->remote_app)
+ if(!xfc->remote_app)
{
ax = x + wnd->windowOffsetX;
- ay = y + wnd->windowOffsetY;
-
- if (ax + width > wnd->windowOffsetX + wnd->windowWidth)
+ ay = y + wnd->windowOffsetY;
+ if(ax + width > wnd->windowOffsetX + wnd->windowWidth)
width = (wnd->windowOffsetX + wnd->windowWidth - 1) - ax;
-
- if (ay + height > wnd->windowOffsetY + wnd->windowHeight)
+ if(ay + height > wnd->windowOffsetY + wnd->windowHeight)
height = (wnd->windowOffsetY + wnd->windowHeight - 1) - ay;
}
else
{
ax = x + wnd->visibleOffsetX;
- ay = y + wnd->visibleOffsetY;
-
- if (ax + width > wnd->visibleOffsetX + wnd->windowWidth)
- width = (wnd->visibleOffsetX + wnd->windowWidth - 1) - ax;
-
- if (ay + height > wnd->visibleOffsetY + wnd->windowHeight)
- height = (wnd->visibleOffsetY + wnd->windowHeight - 1) - ay;
+ ay = y + wnd->visibleOffsetY;
+ if(ax + width > wnd->visibleOffsetX + wnd->windowWidth)
+ width = (wnd->visibleOffsetX + wnd->windowWidth - 1) - ax;
+ if(ay + height > wnd->visibleOffsetY + wnd->windowHeight)
+ height = (wnd->visibleOffsetY + wnd->windowHeight - 1) - ay;
}
-
WaitForSingleObject(xfc->mutex, INFINITE);
-
- if (xfc->settings->SoftwareGdi)
+ if(xfc->settings->SoftwareGdi)
{
XPutImage(xfc->display, xfc->primary, window->gc, xfc->image,
- ax, ay, ax, ay, width, height);
+ ax, ay, ax, ay, width, height);
}
-
XCopyArea(xfc->display, xfc->primary, window->handle, window->gc,
- ax, ay, width, height, x, y);
-
+ ax, ay, width, height, x, y);
XFlush(xfc->display);
-
ReleaseMutex(xfc->mutex);
}
-BOOL xf_IsWindowBorder(xfContext* xfc, xfWindow* xfw, int x, int y)
+BOOL xf_IsWindowBorder(xfContext *xfc, xfWindow *xfw, int x, int y)
{
- rdpWindow* wnd;
+ rdpWindow *wnd;
BOOL clientArea = FALSE;
BOOL windowArea = FALSE;
-
wnd = xfw->window;
-
- if (((x > wnd->clientOffsetX) && (x < wnd->clientOffsetX + wnd->clientAreaWidth)) &&
- ((y > wnd->clientOffsetY) && (y < wnd->clientOffsetY + wnd->clientAreaHeight)))
+ if(((x > wnd->clientOffsetX) && (x < wnd->clientOffsetX + wnd->clientAreaWidth)) &&
+ ((y > wnd->clientOffsetY) && (y < wnd->clientOffsetY + wnd->clientAreaHeight)))
clientArea = TRUE;
-
- if (((x > wnd->windowOffsetX) && (x < wnd->windowOffsetX + wnd->windowWidth)) &&
- ((y > wnd->windowOffsetY) && (y < wnd->windowOffsetY + wnd->windowHeight)))
+ if(((x > wnd->windowOffsetX) && (x < wnd->windowOffsetX + wnd->windowWidth)) &&
+ ((y > wnd->windowOffsetY) && (y < wnd->windowOffsetY + wnd->windowHeight)))
windowArea = TRUE;
-
return (windowArea && !(clientArea));
}
-void xf_DestroyWindow(xfContext* xfc, xfWindow* window)
+void xf_DestroyWindow(xfContext *xfc, xfWindow *window)
{
- if (window == NULL)
+ if(window == NULL)
return;
-
- if (xfc->window == window)
+ if(xfc->window == window)
xfc->window = NULL;
-
- if (window->gc)
+ if(window->gc)
XFreeGC(xfc->display, window->gc);
-
- if (window->handle)
+ if(window->handle)
{
XUnmapWindow(xfc->display, window->handle);
XDestroyWindow(xfc->display, window->handle);
}
-
free(window);
+ if(window->xfwin)
+ munmap(0, sizeof(*window->xfwin));
+ if(window->shmid >= 0)
+ close(window->shmid);
+ shm_unlink(get_shm_id());
+ window->xfwin = -1;
+ window->shmid = -1;
}
-rdpWindow* xf_rdpWindowFromWindow(xfContext* xfc, Window wnd)
+rdpWindow *xf_rdpWindowFromWindow(xfContext *xfc, Window wnd)
{
- rdpRail* rail;
-
- if (xfc)
+ rdpRail *rail;
+ if(xfc)
{
- if (wnd)
+ if(wnd)
{
- rail = ((rdpContext*) xfc)->rail;
-
- if (rail)
- return window_list_get_by_extra_id(rail->list, (void*) (long) wnd);
+ rail = ((rdpContext *) xfc)->rail;
+ if(rail)
+ return window_list_get_by_extra_id(rail->list, (void *)(long) wnd);
}
}
-
return NULL;
}
diff --git a/client/X11/xf_window.h b/client/X11/xf_window.h
index e80023981..cc3acf38f 100644
--- a/client/X11/xf_window.h
+++ b/client/X11/xf_window.h
@@ -71,10 +71,12 @@ struct xf_window
int bottom;
int width;
int height;
+ int shmid;
Window handle;
+ Window *xfwin;
BOOL fullscreen;
BOOL decorations;
- rdpWindow* window;
+ rdpWindow *window;
BOOL is_mapped;
BOOL is_transient;
xfLocalMove local_move;
@@ -82,39 +84,39 @@ struct xf_window
BOOL rail_ignore_configure;
};
-void xf_ewmhints_init(xfContext* xfc);
+void xf_ewmhints_init(xfContext *xfc);
-BOOL xf_GetCurrentDesktop(xfContext* xfc);
-BOOL xf_GetWorkArea(xfContext* xfc);
+BOOL xf_GetCurrentDesktop(xfContext *xfc);
+BOOL xf_GetWorkArea(xfContext *xfc);
-void xf_SetWindowFullscreen(xfContext* xfc, xfWindow* window, BOOL fullscreen);
-void xf_SetWindowDecorations(xfContext* xfc, xfWindow* window, BOOL show);
-void xf_SetWindowUnlisted(xfContext* xfc, xfWindow* window);
+void xf_SetWindowFullscreen(xfContext *xfc, xfWindow *window, BOOL fullscreen);
+void xf_SetWindowDecorations(xfContext *xfc, xfWindow *window, BOOL show);
+void xf_SetWindowUnlisted(xfContext *xfc, xfWindow *window);
-xfWindow* xf_CreateDesktopWindow(xfContext* xfc, char* name, int width, int height, BOOL decorations);
-void xf_ResizeDesktopWindow(xfContext* xfc, xfWindow* window, int width, int height);
+xfWindow *xf_CreateDesktopWindow(xfContext *xfc, char *name, int width, int height, BOOL decorations);
+void xf_ResizeDesktopWindow(xfContext *xfc, xfWindow *window, int width, int height);
-xfWindow* xf_CreateWindow(xfContext* xfc, rdpWindow* wnd, int x, int y, int width, int height, UINT32 id);
-void xf_SetWindowText(xfContext* xfc, xfWindow* window, char *name);
-void xf_MoveWindow(xfContext* xfc, xfWindow* window, int x, int y, int width, int height);
-void xf_ShowWindow(xfContext* xfc, xfWindow* window, BYTE state);
-void xf_SetWindowIcon(xfContext* xfc, xfWindow* window, rdpIcon* icon);
-void xf_SetWindowRects(xfContext* xfc, xfWindow* window, RECTANGLE_16* rects, int nrects);
-void xf_SetWindowVisibilityRects(xfContext* xfc, xfWindow* window, RECTANGLE_16* rects, int nrects);
-void xf_SetWindowStyle(xfContext* xfc, xfWindow* window, UINT32 style, UINT32 ex_style);
-void xf_UpdateWindowArea(xfContext* xfc, xfWindow* window, int x, int y, int width, int height);
-BOOL xf_IsWindowBorder(xfContext* xfc, xfWindow* xfw, int x, int y);
-void xf_DestroyWindow(xfContext* xfc, xfWindow* window);
-rdpWindow* xf_rdpWindowFromWindow(xfContext* xfc, Window wnd);
+xfWindow *xf_CreateWindow(xfContext *xfc, rdpWindow *wnd, int x, int y, int width, int height, UINT32 id);
+void xf_SetWindowText(xfContext *xfc, xfWindow *window, char *name);
+void xf_MoveWindow(xfContext *xfc, xfWindow *window, int x, int y, int width, int height);
+void xf_ShowWindow(xfContext *xfc, xfWindow *window, BYTE state);
+void xf_SetWindowIcon(xfContext *xfc, xfWindow *window, rdpIcon *icon);
+void xf_SetWindowRects(xfContext *xfc, xfWindow *window, RECTANGLE_16 *rects, int nrects);
+void xf_SetWindowVisibilityRects(xfContext *xfc, xfWindow *window, RECTANGLE_16 *rects, int nrects);
+void xf_SetWindowStyle(xfContext *xfc, xfWindow *window, UINT32 style, UINT32 ex_style);
+void xf_UpdateWindowArea(xfContext *xfc, xfWindow *window, int x, int y, int width, int height);
+BOOL xf_IsWindowBorder(xfContext *xfc, xfWindow *xfw, int x, int y);
+void xf_DestroyWindow(xfContext *xfc, xfWindow *window);
+rdpWindow *xf_rdpWindowFromWindow(xfContext *xfc, Window wnd);
-BOOL xf_GetWindowProperty(xfContext* xfc, Window window, Atom property, int length,
- unsigned long* nitems, unsigned long* bytes, BYTE** prop);
+BOOL xf_GetWindowProperty(xfContext *xfc, Window window, Atom property, int length,
+ unsigned long *nitems, unsigned long *bytes, BYTE **prop);
-void xf_SetWindowMinMaxInfo(xfContext* xfc, xfWindow* window, int maxWidth, int maxHeight,
- int maxPosX, int maxPosY, int minTrackWidth, int minTrackHeight, int maxTrackWidth, int maxTrackHeight);
+void xf_SetWindowMinMaxInfo(xfContext *xfc, xfWindow *window, int maxWidth, int maxHeight,
+ int maxPosX, int maxPosY, int minTrackWidth, int minTrackHeight, int maxTrackWidth, int maxTrackHeight);
-void xf_StartLocalMoveSize(xfContext* xfc, xfWindow* window, int direction, int x, int y);
-void xf_EndLocalMoveSize(xfContext* xfc, xfWindow *window);
-void xf_SendClientEvent(xfContext* xfc, xfWindow* window, Atom atom, unsigned int numArgs, ...);
+void xf_StartLocalMoveSize(xfContext *xfc, xfWindow *window, int direction, int x, int y);
+void xf_EndLocalMoveSize(xfContext *xfc, xfWindow *window);
+void xf_SendClientEvent(xfContext *xfc, xfWindow *window, Atom atom, unsigned int numArgs, ...);
#endif /* __XF_WINDOW_H */
diff --git a/cmake/ConfigOptions.cmake b/cmake/ConfigOptions.cmake
index f644c8050..d2e56eade 100644
--- a/cmake/ConfigOptions.cmake
+++ b/cmake/ConfigOptions.cmake
@@ -100,6 +100,7 @@ option(WITH_DEBUG_CAPABILITIES "Print capability negotiation debug messages." ${
option(WITH_DEBUG_CHANNELS "Print channel manager debug messages." ${DEFAULT_DEBUG_OPTION})
option(WITH_DEBUG_CLIPRDR "Print clipboard redirection debug messages" ${DEFAULT_DEBUG_OPTION})
option(WITH_DEBUG_DVC "Print dynamic virtual channel debug messages." ${DEFAULT_DEBUG_OPTION})
+option(WITH_DEBUG_TSMF "Print TSMF virtual channel debug messages." ${DEFAULT_DEBUG_OPTION})
option(WITH_DEBUG_GDI "Print graphics debug messages." ${DEFAULT_DEBUG_OPTION})
option(WITH_DEBUG_KBD "Print keyboard related debug messages." ${DEFAULT_DEBUG_OPTION})
option(WITH_DEBUG_LICENSE "Print license debug messages." ${DEFAULT_DEBUG_OPTION})
diff --git a/cmake/FindGStreamer_0_10.cmake b/cmake/FindGStreamer_0_10.cmake
new file mode 100644
index 000000000..0342f4c64
--- /dev/null
+++ b/cmake/FindGStreamer_0_10.cmake
@@ -0,0 +1,118 @@
+# - Try to find GStreamer
+# Once done this will define
+#
+# GSTREAMER_0_10_FOUND - system has GStreamer
+# GSTREAMER_0_10_INCLUDE_DIRS - the GStreamer include directory
+# GSTREAMER_0_10_LIBRARIES - the libraries needed to use GStreamer
+# GSTREAMER_0_10_DEFINITIONS - Compiler switches required for using GStreamer
+
+# Copyright (c) 2006, Tim Beaulen <tbscope@gmail.com>
+#
+# Redistribution and use is allowed according to the terms of the BSD license.
+# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
+
+# TODO: Other versions --> GSTREAMER_X_Y_FOUND (Example: GSTREAMER_0_8_FOUND and GSTREAMER_0_10_FOUND etc)
+
+IF (GSTREAMER_0_10_INCLUDE_DIRS AND GSTREAMER_0_10_LIBRARIES AND GSTREAMER_0_10_BASE_LIBRARY AND GSTREAMER_0_10_INTERFACE_LIBRARY)
+ # in cache already
+ SET(GSTREAMER_0_10_FIND_QUIETLY TRUE)
+ELSE (GSTREAMER_0_10_INCLUDE_DIRS AND GSTREAMER_0_10_LIBRARIES AND GSTREAMER_0_10_BASE_LIBRARY AND GSTREAMER_0_10_INTERFACE_LIBRARY)
+ SET(GSTREAMER_0_10_FIND_QUIETLY FALSE)
+ENDIF (GSTREAMER_0_10_INCLUDE_DIRS AND GSTREAMER_0_10_LIBRARIES AND GSTREAMER_0_10_BASE_LIBRARY AND GSTREAMER_0_10_INTERFACE_LIBRARY)
+
+IF (NOT WIN32)
+ # use pkg-config to get the directories and then use these values
+ # in the FIND_PATH() and FIND_LIBRARY() calls
+ FIND_PACKAGE(PkgConfig)
+ PKG_CHECK_MODULES(PC_GSTREAMER_0_10 QUIET gstreamer-0.10)
+ #MESSAGE(STATUS "DEBUG: GStreamer include directory = ${GSTREAMER_0_10_INCLUDE_DIRSS}")
+ #MESSAGE(STATUS "DEBUG: GStreamer link directory = ${GSTREAMER_0_10_LIBRARY_DIRS}")
+ #MESSAGE(STATUS "DEBUG: GStreamer CFlags = ${GSTREAMER_0_10_CFLAGS_OTHER}")
+ SET(GSTREAMER_0_10_DEFINITIONS ${PC_GSTREAMER_0_10_CFLAGS_OTHER})
+ENDIF (NOT WIN32)
+
+FIND_PATH(GSTREAMER_0_10_INCLUDE_DIRS gst/gst.h
+ PATHS
+ ${PC_GSTREAMER_0_10_INCLUDEDIR}
+ ${PC_GSTREAMER_0_10_INCLUDE_DIRSS}
+ #PATH_SUFFIXES gst
+ )
+
+FIND_LIBRARY(GSTREAMER_0_10_LIBRARIES NAMES gstreamer-0.10
+ PATHS
+ ${PC_GSTREAMER_0_10_LIBDIR}
+ ${PC_GSTREAMER_0_10_LIBRARY_DIRS}
+ )
+
+FIND_LIBRARY(GSTREAMER_0_10_BASE_LIBRARY NAMES gstbase-0.10
+ PATHS
+ ${PC_GSTREAMER_0_10_LIBDIR}
+ ${PC_GSTREAMER_0_10_LIBRARY_DIRS}
+ )
+
+FIND_LIBRARY(GSTREAMER_0_10_APP_LIBRARY NAMES gstapp-0.10
+ PATHS
+ ${PC_GSTREAMER_0_10_LIBDIR}
+ ${PC_GSTREAMER_0_10_LIBRARY_DIRS}
+ )
+
+FIND_LIBRARY(GSTREAMER_0_10_INTERFACE_LIBRARY NAMES gstinterfaces-0.10
+ PATHS
+ ${PC_GSTREAMER_0_10_LIBDIR}
+ ${PC_GSTREAMER_0_10_LIBRARY_DIRS}
+ )
+
+FIND_PACKAGE(Glib REQUIRED)
+FIND_PACKAGE(LibXml2 REQUIRED)
+
+IF (GSTREAMER_0_10_INCLUDE_DIRS)
+ #MESSAGE(STATUS "DEBUG: Found GStreamer include dir: ${GSTREAMER_0_10_INCLUDE_DIRS}")
+ELSE (GSTREAMER_0_10_INCLUDE_DIRS)
+ MESSAGE(STATUS "GStreamer: WARNING: include dir not found")
+ENDIF (GSTREAMER_0_10_INCLUDE_DIRS)
+
+IF (GSTREAMER_0_10_LIBRARIES)
+ #MESSAGE(STATUS "DEBUG: Found GStreamer library: ${GSTREAMER_0_10_LIBRARIES}")
+ELSE (GSTREAMER_0_10_LIBRARIES)
+ MESSAGE(STATUS "GStreamer: WARNING: library not found")
+ENDIF (GSTREAMER_0_10_LIBRARIES)
+
+IF (GSTREAMER_0_10_INTERFACE_LIBRARY)
+ #MESSAGE(STATUS "DEBUG: Found GStreamer interface library: ${GSTREAMER_0_10_INTERFACE_LIBRARY}")
+ELSE (GSTREAMER_0_10_INTERFACE_LIBRARY)
+ MESSAGE(STATUS "GStreamer: WARNING: interface library not found")
+ENDIF (GSTREAMER_0_10_INTERFACE_LIBRARY)
+
+set(_GSTREAMER_0_10_REQUIRED_VARS
+ Glib_INCLUDE_DIRS
+ Glib_LIBRARIES
+ LIBXML2_INCLUDE_DIR
+ LIBXML2_LIBRARIES
+ GSTREAMER_0_10_INCLUDE_DIRS
+ GSTREAMER_0_10_LIBRARIES
+ VERSION_OK
+ GSTREAMER_0_10_BASE_INCLUDE_DIRS
+ GSTREAMER_0_10_BASE_LIBRARY
+ GSTREAMER_0_10_INTERFACE_INCLUDE_DIRS
+ GSTREAMER_0_10_INTERFACE_LIBRARY)
+
+INCLUDE(FindPackageHandleStandardArgs)
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(GSTREAMER_0_10 DEFAULT_MSG
+ GSTREAMER_0_10_LIBRARIES
+ GSTREAMER_0_10_INCLUDE_DIRS
+ GSTREAMER_0_10_BASE_LIBRARY
+ GSTREAMER_0_10_INTERFACE_LIBRARY)
+
+list(APPEND GSTREAMER_0_10_INCLUDE_DIRS ${Glib_INCLUDE_DIRS})
+list(APPEND GSTREAMER_0_10_LIBRARIES ${Glib_LIBRARIES})
+list(APPEND GSTREAMER_0_10_INCLUDE_DIRS ${LIBXML2_INCLUDE_DIR})
+list(APPEND GSTREAMER_0_10_LIBRARIES ${LIBXML2_LIBRARIES})
+list(APPEND GSTREAMER_0_10_INCLUDE_DIRS ${GSTREAMER_0_10_BASE_INCLUDE_DIR})
+list(APPEND GSTREAMER_0_10_LIBRARIES ${GSTREAMER_0_10_BASE_LIBRARY})
+list(APPEND GSTREAMER_0_10_INCLUDE_DIRS ${GSTREAMER_0_10_APP_INCLUDE_DIR})
+list(APPEND GSTREAMER_0_10_LIBRARIES ${GSTREAMER_0_10_APP_LIBRARY})
+list(APPEND GSTREAMER_0_10_INCLUDE_DIRS ${GSTREAMER_0_10_INTERFACE_INCLUDE_DIR})
+list(APPEND GSTREAMER_0_10_LIBRARIES ${GSTREAMER_0_10_INTERFACE_LIBRARY})
+
+MARK_AS_ADVANCED(GSTREAMER_0_10_INCLUDE_DIRS GSTREAMER_0_10_LIBRARIES GSTREAMER_0_10_BASE_LIBRARY GSTREAMER_0_10_INTERFACE_LIBRARY)
+
diff --git a/cmake/FindGStreamer_1_0.cmake b/cmake/FindGStreamer_1_0.cmake
new file mode 100644
index 000000000..f7bf990db
--- /dev/null
+++ b/cmake/FindGStreamer_1_0.cmake
@@ -0,0 +1,153 @@
+# - Try to find Gstreamer and its plugins
+# Once done, this will define
+#
+# GSTREAMER_1_0_FOUND - system has Gstreamer
+# GSTREAMER_1_0_INCLUDE_DIRS - the Gstreamer include directories
+# GSTREAMER_1_0_LIBRARIES - link these to use Gstreamer
+#
+# Additionally, gstreamer-base is always looked for and required, and
+# the following related variables are defined:
+#
+# GSTREAMER_1_0_BASE_INCLUDE_DIRS - gstreamer-base's include directory
+# GSTREAMER_1_0_BASE_LIBRARIES - link to these to use gstreamer-base
+#
+# Optionally, the COMPONENTS keyword can be passed to find_package()
+# and Gstreamer plugins can be looked for. Currently, the following
+# plugins can be searched, and they define the following variables if
+# found:
+#
+# gstreamer-app: GSTREAMER_1_0_APP_INCLUDE_DIRS and GSTREAMER_1_0_APP_LIBRARIES
+# gstreamer-audio: GSTREAMER_1_0_AUDIO_INCLUDE_DIRS and GSTREAMER_1_0_AUDIO_LIBRARIES
+# gstreamer-fft: GSTREAMER_1_0_FFT_INCLUDE_DIRS and GSTREAMER_1_0_FFT_LIBRARIES
+# gstreamer-pbutils: GSTREAMER_1_0_PBUTILS_INCLUDE_DIRS and GSTREAMER_1_0_PBUTILS_LIBRARIES
+# gstreamer-video: GSTREAMER_1_0_VIDEO_INCLUDE_DIRS and GSTREAMER_1_0_VIDEO_LIBRARIES
+#
+# Copyright (C) 2012 Raphael Kubo da Costa <rakuco@webkit.org>
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND ITS CONTRIBUTORS ``AS
+# IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR ITS
+# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+find_package(PkgConfig)
+
+# The minimum Gstreamer version we support.
+set(GSTREAMER_1_0_MINIMUM_VERSION 1.0.5)
+
+# Helper macro to find a Gstreamer plugin (or Gstreamer itself)
+# _component_prefix is prepended to the _INCLUDE_DIRS and _LIBRARIES variables (eg. "GSTREAMER_1_0_AUDIO")
+# _pkgconfig_name is the component's pkg-config name (eg. "gstreamer-1.0", or "gstreamer-video-1.0").
+# _header is the component's header, relative to the gstreamer-1.0 directory (eg. "gst/gst.h").
+# _library is the component's library name (eg. "gstreamer-1.0" or "gstvideo-1.0")
+macro(FIND_GSTREAMER_COMPONENT _component_prefix _pkgconfig_name _header _library)
+ # FIXME: The QUIET keyword can be used once we require CMake 2.8.2.
+ pkg_check_modules(PC_${_component_prefix} ${_pkgconfig_name})
+
+ find_path(${_component_prefix}_INCLUDE_DIRS
+ NAMES ${_header}
+ HINTS ${PC_${_component_prefix}_INCLUDE_DIRS} ${PC_${_component_prefix}_INCLUDEDIR}
+ PATH_SUFFIXES gstreamer-1.0
+ )
+
+ find_library(${_component_prefix}_LIBRARIES
+ NAMES ${_library} gstreamer_android
+ HINTS ${PC_${_component_prefix}_LIBRARY_DIRS} ${PC_${_component_prefix}_LIBDIR} ${GSTREAMER_1_0_ROOT_DIR}
+ )
+endmacro()
+
+# ------------------------
+# 1. Find Gstreamer itself
+# ------------------------
+
+# 1.1. Find headers and libraries
+set(GLIB_ROOT_DIR ${GSTREAMER_1_0_ROOT_DIR})
+find_package(Glib REQUIRED)
+FIND_GSTREAMER_COMPONENT(GSTREAMER_1_0 gstreamer-1.0 gst/gst.h gstreamer-1.0)
+FIND_GSTREAMER_COMPONENT(GSTREAMER_1_0_BASE gstreamer-base-1.0 gst/gst.h gstbase-1.0)
+
+# 1.2. Check Gstreamer version
+if (GSTREAMER_1_0_INCLUDE_DIRS)
+ if (EXISTS "${GSTREAMER_1_0_INCLUDE_DIRS}/gst/gstversion.h")
+ file(READ "${GSTREAMER_1_0_INCLUDE_DIRS}/gst/gstversion.h" GSTREAMER_VERSION_CONTENTS)
+
+ string(REGEX MATCH "#define +GST_VERSION_MAJOR +\\(([0-9]+)\\)" _dummy "${GSTREAMER_VERSION_CONTENTS}")
+ set(GSTREAMER_1_0_VERSION_MAJOR "${CMAKE_MATCH_1}")
+
+ string(REGEX MATCH "#define +GST_VERSION_MINOR +\\(([0-9]+)\\)" _dummy "${GSTREAMER_1_0_VERSION_CONTENTS}")
+ set(GSTREAMER_1_0_VERSION_MINOR "${CMAKE_MATCH_1}")
+
+ string(REGEX MATCH "#define +GST_VERSION_MICRO +\\(([0-9]+)\\)" _dummy "${GSTREAMER_1_0_VERSION_CONTENTS}")
+ set(GSTREAMER_1_0_VERSION_MICRO "${CMAKE_MATCH_1}")
+
+ set(GSTREAMER_1_0_VERSION "${GSTREAMER_1_0_VERSION_MAJOR}.${GSTREAMER_1_0_VERSION_MINOR}.${GSTREAMER_1_0_VERSION_MICRO}")
+ endif ()
+endif ()
+
+# FIXME: With CMake 2.8.3 we can just pass GSTREAMER_1_0_VERSION to FIND_PACKAGE_HANDLE_STANDARD_ARGS as VERSION_VAR
+# and remove the version check here (GSTREAMER_1_0_MINIMUM_VERSION would be passed to FIND_PACKAGE).
+set(VERSION_OK TRUE)
+if ("${GSTREAMER_1_0_VERSION}" VERSION_LESS "${GSTREAMER_1_0_MINIMUM_VERSION}")
+ set(VERSION_OK FALSE)
+endif ()
+
+# -------------------------
+# 2. Find Gstreamer plugins
+# -------------------------
+
+FIND_GSTREAMER_COMPONENT(GSTREAMER_1_0_APP gstreamer-app-1.0 gst/app/gstappsink.h gstapp-1.0)
+FIND_GSTREAMER_COMPONENT(GSTREAMER_1_0_AUDIO gstreamer-audio-1.0 gst/audio/audio.h gstaudio-1.0)
+FIND_GSTREAMER_COMPONENT(GSTREAMER_1_0_FFT gstreamer-fft-1.0 gst/fft/gstfft.h gstfft-1.0)
+FIND_GSTREAMER_COMPONENT(GSTREAMER_1_0_PBUTILS gstreamer-pbutils-1.0 gst/pbutils/pbutils.h gstpbutils-1.0)
+FIND_GSTREAMER_COMPONENT(GSTREAMER_1_0_VIDEO gstreamer-video-1.0 gst/video/video.h gstvideo-1.0)
+
+# ------------------------------------------------
+# 3. Process the COMPONENTS passed to FIND_PACKAGE
+# ------------------------------------------------
+set(_GSTREAMER_1_0_REQUIRED_VARS
+ Glib_INCLUDE_DIRS
+ Glib_LIBRARIES
+ GSTREAMER_1_0_INCLUDE_DIRS
+ GSTREAMER_1_0_LIBRARIES
+ VERSION_OK
+ GSTREAMER_1_0_BASE_INCLUDE_DIRS
+ GSTREAMER_1_0_BASE_LIBRARIES)
+
+include(FindPackageHandleStandardArgs)
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(GSTREAMER_1_0 DEFAULT_MSG GSTREAMER_1_0_LIBRARIES GSTREAMER_1_0_INCLUDE_DIRS)
+
+list(APPEND GSTREAMER_1_0_INCLUDE_DIRS ${Glib_INCLUDE_DIRS})
+list(APPEND GSTREAMER_1_0_LIBRARIES ${Glib_LIBRARIES})
+list(APPEND GSTREAMER_1_0_INCLUDE_DIRS ${GSTREAMER_1_0_BASE_INCLUDE_DIRS})
+list(APPEND GSTREAMER_1_0_LIBRARIES ${GSTREAMER_1_0_BASE_LIBRARIES})
+list(APPEND GSTREAMER_1_0_INCLUDE_DIRS ${GSTREAMER_1_0_APP_INCLUDE_DIRS})
+list(APPEND GSTREAMER_1_0_LIBRARIES ${GSTREAMER_1_0_APP_LIBRARIES})
+list(APPEND GSTREAMER_1_0_INCLUDE_DIRS ${GSTREAMER_1_0_VIDEO_INCLUDE_DIRS})
+list(APPEND GSTREAMER_1_0_LIBRARIES ${GSTREAMER_1_0_VIDEO_LIBRARIES})
+
+foreach (_component ${Gstreamer_FIND_COMPONENTS})
+ set(_gst_component "GSTREAMER_1_0_${_component}")
+ string(TOUPPER ${_gst_component} _UPPER_NAME)
+
+ FIND_PACKAGE_HANDLE_STANDARD_ARGS(${_UPPER_NAME} DEFAULT_MSG ${_UPPER_NAME}_INCLUDE_DIRS ${_UPPER_NAME}_LIBRARIES)
+ list(APPEND GSTREAMER_1_0_INCLUDE_DIRS ${${_UPPER_NAME}_INCLUDE_DIRS})
+ list(APPEND GSTREAMER_1_0_LIBRARIES ${${_UPPER_NAME}_LIBRARIES})
+endforeach ()
+
+MARK_AS_ADVANCED(GSTREAMER_1_0_INCLUDE_DIRS GSTREAMER_1_0_LIBRARIES GSTREAMER_1_0_BASE_LIBRARY GSTREAMER_1_0_APP_LIBRARY)
+
diff --git a/cmake/FindGlib.cmake b/cmake/FindGlib.cmake
new file mode 100644
index 000000000..3e22eb075
--- /dev/null
+++ b/cmake/FindGlib.cmake
@@ -0,0 +1,43 @@
+# - Try to find Glib-2.0 (with gobject)
+# Once done, this will define
+#
+# Glib_FOUND - system has Glib
+# Glib_INCLUDE_DIRS - the Glib include directories
+# Glib_LIBRARIES - link these to use Glib
+#
+# GLIB_ROOT_DIR - Primary search directory
+include(LibFindMacros)
+
+# Use pkg-config to get hints about paths
+libfind_pkg_check_modules(Glib_PKGCONF glib-2.0)
+
+# Main include dir
+find_path(Glib_INCLUDE_DIR
+ NAMES glib.h
+ PATHS ${Glib_PKGCONF_INCLUDE_DIRS} ${GLIB_ROOT_DIR}
+ PATH_SUFFIXES glib-2.0
+ )
+
+# Finally the library itself
+find_library(Glib_LIBRARY
+ NAMES glib-2.0 gstreamer_android
+ PATHS ${Glib_PKGCONF_LIBRARY_DIRS} ${GLIB_ROOT_DIR}
+ )
+find_library(Gobject_LIBRARY
+ NAMES gobject-2.0 gstreamer_android
+ PATHS ${Glib_PKGCONF_LIBRARY_DIRS} ${GLIB_ROOT_DIR}
+ )
+
+# Glib-related libraries also use a separate config header, which is in lib dir
+find_path(GlibConfig_INCLUDE_DIR
+ NAMES glibconfig.h
+ PATHS ${Glib_PKGCONF_INCLUDE_DIRS} /usr ${GLIB_ROOT_DIR}
+ PATH_SUFFIXES lib/glib-2.0/include glib-2.0/include
+ )
+
+# Set the include dir variables and the libraries and let libfind_process do the rest.
+# NOTE: Singular variables for this library, plural for libraries this this lib depends on.
+set(Glib_PROCESS_INCLUDES Glib_INCLUDE_DIR GlibConfig_INCLUDE_DIR)
+set(Glib_PROCESS_LIBS Glib_LIBRARY Gobject_LIBRARY)
+libfind_process(Glib)
+
diff --git a/cmake/FindGstreamer.cmake b/cmake/FindGstreamer.cmake
deleted file mode 100644
index c4451c61a..000000000
--- a/cmake/FindGstreamer.cmake
+++ /dev/null
@@ -1,12 +0,0 @@
-include(FindPkgConfig)
-
-pkg_check_modules(PC_GSTREAMER_0_10 gstreamer-0.10)
-pkg_check_modules(PC_GSTREAMER_PLUGINS_BASE_0_10 gstreamer-plugins-base-0.10)
-
-if(PC_GSTREAMER_0_10_FOUND AND PC_GSTREAMER_PLUGINS_BASE_0_10_FOUND)
- set(GSTREAMER_INCLUDE_DIRS ${PC_GSTREAMER_0_10_INCLUDE_DIRS} ${PC_GSTREAMER_PLUGINS_BASE_0_10_INCLUDE_DIRS})
- set(GSTREAMER_LIBRARIES ${PC_GSTREAMER_0_10_LIBRARIES} ${PC_GSTREAMER_PLUGINS_BASE_0_10_LIBRARIES})
-endif()
-
-include(FindPackageHandleStandardArgs)
-FIND_PACKAGE_HANDLE_STANDARD_ARGS(GSTREAMER DEFAULT_MSG GSTREAMER_LIBRARIES GSTREAMER_INCLUDE_DIRS)
diff --git a/cmake/LibFindMacros.cmake b/cmake/LibFindMacros.cmake
new file mode 100644
index 000000000..0e47404c5
--- /dev/null
+++ b/cmake/LibFindMacros.cmake
@@ -0,0 +1,116 @@
+# Works the same as find_package, but forwards the "REQUIRED" and "QUIET" arguments
+# used for the current package. For this to work, the first parameter must be the
+# prefix of the current package, then the prefix of the new package etc, which are
+# passed to find_package.
+macro(libfind_package PREFIX)
+ set(LIBFIND_PACKAGE_ARGS $ {ARGN})
+ if($ {PREFIX} _FIND_QUIETLY)
+ set(LIBFIND_PACKAGE_ARGS $ {LIBFIND_PACKAGE_ARGS} QUIET)
+ endif($ {PREFIX} _FIND_QUIETLY)
+ if($ {PREFIX} _FIND_REQUIRED)
+ set(LIBFIND_PACKAGE_ARGS $ {LIBFIND_PACKAGE_ARGS} REQUIRED)
+ endif($ {PREFIX} _FIND_REQUIRED)
+ find_package($ {LIBFIND_PACKAGE_ARGS})
+endmacro(libfind_package)
+
+# CMake developers made the UsePkgConfig system deprecated in the same release (2.6)
+# where they added pkg_check_modules. Consequently I need to support both in my scripts
+# to avoid those deprecated warnings. Here's a helper that does just that.
+# Works identically to pkg_check_modules, except that no checks are needed prior to use.
+macro (libfind_pkg_check_modules PREFIX PKGNAME)
+ if (${CMAKE_MAJOR_VERSION} EQUAL 2 AND ${CMAKE_MINOR_VERSION} EQUAL 4)
+ include(UsePkgConfig)
+ pkgconfig(${PKGNAME} ${PREFIX}_INCLUDE_DIRS ${PREFIX}_LIBRARY_DIRS ${PREFIX}_LDFLAGS ${PREFIX}_CFLAGS)
+ else (${CMAKE_MAJOR_VERSION} EQUAL 2 AND ${CMAKE_MINOR_VERSION} EQUAL 4)
+ find_package(PkgConfig)
+ if (PKG_CONFIG_FOUND)
+ pkg_check_modules(${PREFIX} ${PKGNAME})
+ endif (PKG_CONFIG_FOUND)
+ endif (${CMAKE_MAJOR_VERSION} EQUAL 2 AND ${CMAKE_MINOR_VERSION} EQUAL 4)
+endmacro (libfind_pkg_check_modules)
+
+# Do the final processing once the paths have been detected.
+# If include dirs are needed, ${PREFIX}_PROCESS_INCLUDES should be set to contain
+# all the variables, each of which contain one include directory.
+# Ditto for ${PREFIX}_PROCESS_LIBS and library files.
+# Will set ${PREFIX}_FOUND, ${PREFIX}_INCLUDE_DIRS and ${PREFIX}_LIBRARIES.
+# Also handles errors in case library detection was required, etc.
+macro (libfind_process PREFIX)
+# Skip processing if already processed during this run
+ if (NOT ${PREFIX}_FOUND)
+# Start with the assumption that the library was found
+ set (${PREFIX}_FOUND TRUE)
+
+# Process all includes and set _FOUND to false if any are missing
+ foreach (i ${${PREFIX}_PROCESS_INCLUDES})
+ if (${i})
+ set (${PREFIX}_INCLUDE_DIRS ${${PREFIX}_INCLUDE_DIRS} ${${i}})
+ mark_as_advanced(${i})
+ else (${i})
+ set (${PREFIX}_FOUND FALSE)
+ endif (${i})
+ endforeach (i)
+
+# Process all libraries and set _FOUND to false if any are missing
+ foreach (i ${${PREFIX}_PROCESS_LIBS})
+ if (${i})
+ set (${PREFIX}_LIBRARIES ${${PREFIX}_LIBRARIES} ${${i}})
+ mark_as_advanced(${i})
+ else (${i})
+ set (${PREFIX}_FOUND FALSE)
+ endif (${i})
+ endforeach (i)
+
+# Print message and/or exit on fatal error
+ if (${PREFIX}_FOUND)
+ if (NOT ${PREFIX}_FIND_QUIETLY)
+ message (STATUS "Found ${PREFIX} ${${PREFIX}_VERSION}")
+ endif (NOT ${PREFIX}_FIND_QUIETLY)
+ else (${PREFIX}_FOUND)
+ if (${PREFIX}_FIND_REQUIRED)
+ foreach (i ${${PREFIX}_PROCESS_INCLUDES} ${${PREFIX}_PROCESS_LIBS})
+ message("${i}=${${i}}")
+ endforeach (i)
+ message (FATAL_ERROR "Required library ${PREFIX} NOT FOUND.\nInstall the library (dev version) and try again. If the library is already installed, use ccmake to set the missing variables manually.")
+ endif (${PREFIX}_FIND_REQUIRED)
+ endif (${PREFIX}_FOUND)
+ endif (NOT ${PREFIX}_FOUND)
+endmacro (libfind_process)
+
+macro(libfind_library PREFIX basename)
+ set(TMP "")
+ if(MSVC80)
+ set(TMP -vc80)
+ endif(MSVC80)
+ if(MSVC90)
+ set(TMP -vc90)
+ endif(MSVC90)
+ set(${PREFIX}_LIBNAMES ${basename}${TMP})
+ if(${ARGC} GREATER 2)
+ set(${PREFIX}_LIBNAMES ${basename}${TMP}-${ARGV2})
+ string(REGEX REPLACE "\\." "_" TMP ${${PREFIX}_LIBNAMES})
+ set(${PREFIX}_LIBNAMES ${${PREFIX}_LIBNAMES} ${TMP})
+ endif(${ARGC} GREATER 2)
+ find_library(${PREFIX}_LIBRARY
+ NAMES ${${PREFIX}_LIBNAMES}
+ PATHS ${${PREFIX}_PKGCONF_LIBRARY_DIRS})
+endmacro(libfind_library)
+
+SET(THREE_PART_VERSION_REGEX "[0-9]+\\.[0-9]+\\.[0-9]+")
+# Breaks up a string in the form n1.n2.n3 into three parts and stores
+# them in major, minor, and patch. version should be a value, not a
+# variable, while major, minor and patch should be variables.
+MACRO(THREE_PART_VERSION_TO_VARS version major minor patch)
+ IF(${version} MATCHES ${THREE_PART_VERSION_REGEX})
+ STRING(REPLACE "." " " version_list ${version})
+ SEPARATE_ARGUMENTS(version_list)
+ LIST(GET version_list 0 ${major})
+ LIST(GET version_list 1 ${minor})
+ LIST(GET version_list 2 ${patch})
+ ELSE(${version} MATCHES ${THREE_PART_VERSION_REGEX})
+ MESSAGE("MACRO(THREE_PART_VERSION_TO_VARS ${version} ${major} ${minor} ${patch}")
+ MESSAGE(FATAL_ERROR "Problem parsing version string, I can't parse it properly.")
+ ENDIF(${version} MATCHES ${THREE_PART_VERSION_REGEX})
+ENDMACRO(THREE_PART_VERSION_TO_VARS)
+
+
diff --git a/config.h.in b/config.h.in
index 043dae23d..df9001f72 100755
--- a/config.h.in
+++ b/config.h.in
@@ -39,6 +39,9 @@
#cmakedefine WITH_WIN8
#cmakedefine WITH_RDPSND_DSOUND
+#cmakedefine WITH_FFMPEG
+#cmakedefine WITH_GSTREAMER_1_0
+#cmakedefine WITH_GSTREAMER_0_10
#cmakedefine WITH_WINMM
#cmakedefine WITH_MACAUDIO
#cmakedefine WITH_ALSA
@@ -58,6 +61,7 @@
#cmakedefine WITH_DEBUG_CHANNELS
#cmakedefine WITH_DEBUG_CLIPRDR
#cmakedefine WITH_DEBUG_DVC
+#cmakedefine WITH_DEBUG_TSMF
#cmakedefine WITH_DEBUG_GDI
#cmakedefine WITH_DEBUG_KBD
#cmakedefine WITH_DEBUG_LICENSE
diff --git a/include/freerdp/channels/tsmf.h b/include/freerdp/channels/tsmf.h
new file mode 100644
index 000000000..f6a7ef4c2
--- /dev/null
+++ b/include/freerdp/channels/tsmf.h
@@ -0,0 +1,63 @@
+/*
+ * FreeRDP: A Remote Desktop Protocol Implementation
+ * Video Redirection Virtual Channel - Callback interface
+ *
+ * (C) Copyright 2014 Thincast Technologies GmbH
+ * (C) Copyright 2014 Armin Novak <armin.novak@thincast.com>
+ *
+ * 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.
+ */
+
+#ifndef _TSMF_H_
+#define _TSMF_H_
+
+#include <freerdp/types.h>
+
+/* Callback function setup order:
+ *
+ * When the channel is loaded, it calls TSMF_REGISTER to register the
+ * decoder handle with the client.
+ * The client then stores the handle and calls TSMF_REGISTER_INSTANCE
+ * to give the channel the current handle to the session necessary
+ * to call other functions.
+ * After this initial setup the other functions can be used.
+ */
+/* Functions called from client -> registered by channel */
+#define TSMF_GET_INSTANCE "tsmf_get_instance"
+typedef void (*tsmf_get_instance)(void *instance, void *decoder);
+
+#define TSMF_ADD_WINDOW_HANDLE "tsmf_add_window_handle"
+typedef void (*tsmf_add_window_handle)(void *instance, void *decoder, void *window);
+
+#define TSMF_DEL_WINDOW_HANDLE "tsmf_del_window_handle"
+typedef void (*tsmf_del_window_handle)(void *instance, void *decoder);
+
+/* Functions called from channel -> registered by client */
+#define TSMF_REGISTER "tsmf_register"
+typedef void (*tsmf_register)(void *instance, void *decoder);
+
+#define TSMF_DESTROY "tsmf_destroy"
+typedef void (*tsmf_destroy)(void *instance, void *decoder);
+
+#define TSMF_PLAY "tsmf_play"
+typedef void (*tsmf_play)(void *instance, void *decoder);
+
+#define TSMF_PAUSE "tsmf_pause"
+typedef void (*tsmf_pause)(void *instance, void *decoder);
+
+#define TSMF_RESIZE_WINDOW "tsmf_resize_window"
+typedef void (*tsmf_resize_window)(void *instance, void *decoder, int x, int y, int width,
+ int height, int nr_rect, RDP_RECT *visible);
+
+#endif
+
diff --git a/include/freerdp/dvc.h b/include/freerdp/dvc.h
index a2350bfe8..7911fa556 100644
--- a/include/freerdp/dvc.h
+++ b/include/freerdp/dvc.h
@@ -65,96 +65,100 @@ typedef struct _IWTSVirtualChannelCallback IWTSVirtualChannelCallback;
struct _IWTSListener
{
/* Retrieves the listener-specific configuration. */
- int (*GetConfiguration) (IWTSListener* pListener,
- void** ppPropertyBag);
+ int (*GetConfiguration)(IWTSListener *pListener,
+ void **ppPropertyBag);
- void* pInterface;
+ void *pInterface;
};
struct _IWTSVirtualChannel
{
/* Starts a write request on the channel. */
- int (*Write) (IWTSVirtualChannel* pChannel,
- UINT32 cbSize,
- BYTE* pBuffer,
- void* pReserved);
+ int (*Write)(IWTSVirtualChannel *pChannel,
+ UINT32 cbSize,
+ BYTE *pBuffer,
+ void *pReserved);
/* Closes the channel. */
- int (*Close) (IWTSVirtualChannel* pChannel);
+ int (*Close)(IWTSVirtualChannel *pChannel);
};
struct _IWTSVirtualChannelManager
{
/* Returns an instance of a listener object that listens on a specific
endpoint, or creates a static channel. */
- int (*CreateListener) (IWTSVirtualChannelManager* pChannelMgr,
- const char* pszChannelName,
- UINT32 ulFlags,
- IWTSListenerCallback* pListenerCallback,
- IWTSListener** ppListener);
+ int (*CreateListener)(IWTSVirtualChannelManager *pChannelMgr,
+ const char *pszChannelName,
+ UINT32 ulFlags,
+ IWTSListenerCallback *pListenerCallback,
+ IWTSListener **ppListener);
/* Push a virtual channel event.
This is a FreeRDP extension to standard MS API. */
- int (*PushEvent) (IWTSVirtualChannelManager* pChannelMgr,
- wMessage* pEvent);
+ int (*PushEvent)(IWTSVirtualChannelManager *pChannelMgr,
+ wMessage *pEvent);
/* Find the channel or ID to send data to a specific endpoint. */
- UINT32 (*GetChannelId) (IWTSVirtualChannel * channel);
- IWTSVirtualChannel* (*FindChannelById) (IWTSVirtualChannelManager* pChannelMgr,
- UINT32 ChannelId);
+ UINT32(*GetChannelId)(IWTSVirtualChannel *channel);
+ IWTSVirtualChannel *(*FindChannelById)(IWTSVirtualChannelManager *pChannelMgr,
+ UINT32 ChannelId);
};
struct _IWTSPlugin
{
/* Used for the first call that is made from the client to the plug-in. */
- int (*Initialize) (IWTSPlugin* pPlugin,
- IWTSVirtualChannelManager* pChannelMgr);
+ int (*Initialize)(IWTSPlugin *pPlugin,
+ IWTSVirtualChannelManager *pChannelMgr);
/* Notifies the plug-in that the Remote Desktop Connection (RDC) client
has successfully connected to the Remote Desktop Session Host (RD
Session Host) server. */
- int (*Connected) (IWTSPlugin* pPlugin);
+ int (*Connected)(IWTSPlugin *pPlugin);
/* Notifies the plug-in that the Remote Desktop Connection (RDC) client
has disconnected from the RD Session Host server. */
- int (*Disconnected) (IWTSPlugin* pPlugin,
- UINT32 dwDisconnectCode);
+ int (*Disconnected)(IWTSPlugin *pPlugin,
+ UINT32 dwDisconnectCode);
/* Notifies the plug-in that the Remote Desktop Connection (RDC) client
has terminated. */
- int (*Terminated) (IWTSPlugin* pPlugin);
+ int (*Terminated)(IWTSPlugin *pPlugin);
/* Extended */
- void* pInterface;
+ void *pInterface;
};
struct _IWTSListenerCallback
{
/* Accepts or denies a connection request for an incoming connection to
the associated listener. */
- int (*OnNewChannelConnection) (IWTSListenerCallback* pListenerCallback,
- IWTSVirtualChannel* pChannel,
- BYTE* Data,
- int* pbAccept,
- IWTSVirtualChannelCallback** ppCallback);
+ int (*OnNewChannelConnection)(IWTSListenerCallback *pListenerCallback,
+ IWTSVirtualChannel *pChannel,
+ BYTE *Data,
+ int *pbAccept,
+ IWTSVirtualChannelCallback **ppCallback);
};
struct _IWTSVirtualChannelCallback
{
/* Notifies the user about data that is being received. */
- int (*OnDataReceived) (IWTSVirtualChannelCallback* pChannelCallback,
- UINT32 cbSize,
- BYTE* pBuffer);
+ int (*OnDataReceived)(IWTSVirtualChannelCallback *pChannelCallback,
+ UINT32 cbSize,
+ BYTE *pBuffer);
/* Notifies the user that the channel has been closed. */
- int (*OnClose) (IWTSVirtualChannelCallback* pChannelCallback);
+ int (*OnClose)(IWTSVirtualChannelCallback *pChannelCallback);
};
/* The DVC Plugin entry points */
typedef struct _IDRDYNVC_ENTRY_POINTS IDRDYNVC_ENTRY_POINTS;
struct _IDRDYNVC_ENTRY_POINTS
{
- int (*RegisterPlugin) (IDRDYNVC_ENTRY_POINTS* pEntryPoints,
- const char* name, IWTSPlugin* pPlugin);
- IWTSPlugin* (*GetPlugin) (IDRDYNVC_ENTRY_POINTS* pEntryPoints,
- const char* name);
- ADDIN_ARGV* (*GetPluginData) (IDRDYNVC_ENTRY_POINTS* pEntryPoints);
+ int (*RegisterPlugin)(IDRDYNVC_ENTRY_POINTS *pEntryPoints,
+ const char *name, IWTSPlugin *pPlugin);
+ IWTSPlugin *(*GetPlugin)(IDRDYNVC_ENTRY_POINTS *pEntryPoints,
+ const char *name);
+ ADDIN_ARGV *(*GetPluginData)(IDRDYNVC_ENTRY_POINTS *pEntryPoints);
};
-typedef int (*PDVC_PLUGIN_ENTRY) (IDRDYNVC_ENTRY_POINTS*);
+typedef int (*PDVC_PLUGIN_ENTRY)(IDRDYNVC_ENTRY_POINTS *);
+
+void *get_callback_by_name(const char *name, void **context);
+void add_callback_by_name(const char *name, void *fkt, void *context);
+void remove_callback_by_name(const char *name, void *context);
#endif /* FREERDP_DVC_H */
diff --git a/scripts/format_code.sh b/scripts/format_code.sh
new file mode 100755
index 000000000..d4c30e020
--- /dev/null
+++ b/scripts/format_code.sh
@@ -0,0 +1,23 @@
+#!/bin/sh
+
+ASTYLE=`which astyle`
+
+if [ ! -x $ASTYLE ];
+then
+ echo "No astyle found in path, please install."
+ exit 1
+fi
+
+if [ $# -le 0 ]; then
+ echo "Usage:"
+ echo "\t$0 <file1> [<file2> ...]"
+# echo "\t$0 -r <directory>"
+ exit 2
+fi
+
+$ASTYLE --lineend=linux --mode=c --indent=force-tab=4 --brackets=linux --pad-header \
+ --indent-switches --indent-cases --indent-preprocessor \
+ --indent-col1-comments --delete-empty-lines --break-closing-brackets \
+ --align-pointer=name --indent-labels --brackets=break \
+ --unpad-paren --break-blocks $@
+exit $?
diff --git a/winpr/libwinpr/utils/collections/ArrayList.c b/winpr/libwinpr/utils/collections/ArrayList.c
index 938a17f93..478f26b74 100644
--- a/winpr/libwinpr/utils/collections/ArrayList.c
+++ b/winpr/libwinpr/utils/collections/ArrayList.c
@@ -285,7 +285,11 @@ BOOL ArrayList_Remove(wArrayList* arrayList, void* obj)
}
if (found)
+ {
+ if (arrayList->object.fnObjectFree)
+ arrayList->object.fnObjectFree(arrayList->array[index]);
ret = ArrayList_Shift(arrayList, index, -1);
+ }
if (arrayList->synchronized)
LeaveCriticalSection(&arrayList->lock);
@@ -305,6 +309,8 @@ BOOL ArrayList_RemoveAt(wArrayList* arrayList, int index)
if ((index >= 0) && (index < arrayList->size))
{
+ if (arrayList->object.fnObjectFree)
+ arrayList->object.fnObjectFree(arrayList->array[index]);
ret = ArrayList_Shift(arrayList, index, -1);
}