Merge branch 'master' of https://github.com/awakecoding/FreeRDP into awakecoding

This commit is contained in:
Mike McDonald 2014-06-24 13:49:00 -04:00
commit 38c39e172e
192 changed files with 13436 additions and 7879 deletions

View File

@ -76,11 +76,11 @@ if(ANDROID OR IOS)
SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM BOTH)
endif(ANDROID OR IOS)
include(GetGitRevisionDescription)
git_describe(GIT_REVISION --match "[0-9]*" --abbrev=4 --tags --always)
if(ANDROID OR IOS)
SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY)
endif(ANDROID OR IOS)
git_describe(GIT_REVISION --match "[0-9]*" --abbrev=4 --tags --always)
message(STATUS "Git Revision ${GIT_REVISION}")
# Turn on solution folders (2.8.4+)
@ -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})

View File

@ -312,34 +312,31 @@ static int audin_process_format_change(IWTSVirtualChannelCallback* pChannelCallb
return 0;
}
static int audin_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, UINT32 cbSize, BYTE* pBuffer)
static int audin_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, wStream *data)
{
int error;
wStream* s;
BYTE MessageId;
s = Stream_New(pBuffer, cbSize);
Stream_Read_UINT8(s, MessageId);
Stream_Read_UINT8(data, MessageId);
DEBUG_DVC("MessageId=0x%x", MessageId);
switch (MessageId)
{
case MSG_SNDIN_VERSION:
error = audin_process_version(pChannelCallback, s);
error = audin_process_version(pChannelCallback, data);
break;
case MSG_SNDIN_FORMATS:
error = audin_process_formats(pChannelCallback, s);
error = audin_process_formats(pChannelCallback, data);
break;
case MSG_SNDIN_OPEN:
error = audin_process_open(pChannelCallback, s);
error = audin_process_open(pChannelCallback, data);
break;
case MSG_SNDIN_FORMATCHANGE:
error = audin_process_format_change(pChannelCallback, s);
error = audin_process_format_change(pChannelCallback, data);
break;
default:
@ -348,8 +345,6 @@ static int audin_on_data_received(IWTSVirtualChannelCallback* pChannelCallback,
break;
}
Stream_Free(s, FALSE);
return error;
}

View File

@ -77,9 +77,11 @@ static void audin_server_select_format(audin_server_context* context, int client
static void audin_server_send_version(audin_server* audin, wStream* s)
{
ULONG written;
Stream_Write_UINT8(s, MSG_SNDIN_VERSION);
Stream_Write_UINT32(s, 1); /* Version (4 bytes) */
WTSVirtualChannelWrite(audin->audin_channel, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), NULL);
WTSVirtualChannelWrite(audin->audin_channel, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), &written);
}
static BOOL audin_server_recv_version(audin_server* audin, wStream* s, UINT32 length)
@ -101,6 +103,7 @@ static void audin_server_send_formats(audin_server* audin, wStream* s)
{
int i;
UINT32 nAvgBytesPerSec;
ULONG written;
Stream_SetPosition(s, 0);
Stream_Write_UINT8(s, MSG_SNDIN_FORMATS);
@ -131,7 +134,7 @@ static void audin_server_send_formats(audin_server* audin, wStream* s)
}
}
WTSVirtualChannelWrite(audin->audin_channel, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), NULL);
WTSVirtualChannelWrite(audin->audin_channel, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), &written);
}
static BOOL audin_server_recv_formats(audin_server* audin, wStream* s, UINT32 length)
@ -181,6 +184,8 @@ static BOOL audin_server_recv_formats(audin_server* audin, wStream* s, UINT32 le
static void audin_server_send_open(audin_server* audin, wStream* s)
{
ULONG written;
if (audin->context.selected_client_format < 0)
return;
@ -203,7 +208,7 @@ static void audin_server_send_open(audin_server* audin, wStream* s)
Stream_Write_UINT16(s, 16); /* wBitsPerSample */
Stream_Write_UINT16(s, 0); /* cbSize */
WTSVirtualChannelWrite(audin->audin_channel, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), NULL);
WTSVirtualChannelWrite(audin->audin_channel, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), &written);
}
static BOOL audin_server_recv_open_reply(audin_server* audin, wStream* s, UINT32 length)

View File

@ -31,7 +31,6 @@
#include <freerdp/types.h>
#include <freerdp/constants.h>
#include <freerdp/utils/svc_plugin.h>
#include <freerdp/client/cliprdr.h>
#include "cliprdr_main.h"

View File

@ -31,7 +31,6 @@
#include <freerdp/types.h>
#include <freerdp/constants.h>
#include <freerdp/utils/svc_plugin.h>
#include <freerdp/client/cliprdr.h>
#include "cliprdr_main.h"
@ -382,8 +381,6 @@ static void cliprdr_process_receive(rdpSvcPlugin* plugin, wStream* s)
DEBUG_WARN("unknown msgType %d", msgType);
break;
}
Stream_Free(s, TRUE);
}
static void cliprdr_process_filecontents_request_event(cliprdrPlugin* plugin, RDP_CB_FILECONTENTS_REQUEST_EVENT * event)
@ -506,6 +503,7 @@ static void cliprdr_process_event(rdpSvcPlugin* plugin, wMessage* event)
static void cliprdr_process_terminate(rdpSvcPlugin* plugin)
{
svc_plugin_terminate(plugin);
free(plugin);
}

View File

@ -24,6 +24,7 @@
#include <winpr/stream.h>
#include <freerdp/utils/debug.h>
#include <freerdp/utils/svc_plugin.h>
struct cliprdr_plugin
{

View File

@ -68,6 +68,7 @@ static int cliprdr_server_send_capabilities(CliprdrServerContext* context)
BOOL status;
UINT32 generalFlags;
CLIPRDR_HEADER header;
ULONG written;
printf("CliprdrServerSendCapabilities\n");
@ -96,7 +97,7 @@ static int cliprdr_server_send_capabilities(CliprdrServerContext* context)
Stream_SealLength(s);
status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_Length(s), NULL);
status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_Length(s), &written);
Stream_Free(s, TRUE);
@ -108,6 +109,7 @@ static int cliprdr_server_send_monitor_ready(CliprdrServerContext* context)
wStream* s;
BOOL status;
CLIPRDR_HEADER header;
ULONG written;
printf("CliprdrServerSendMonitorReady\n");
@ -123,7 +125,7 @@ static int cliprdr_server_send_monitor_ready(CliprdrServerContext* context)
Stream_SealLength(s);
status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_Length(s), NULL);
status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_Length(s), &written);
Stream_Free(s, TRUE);
@ -135,6 +137,7 @@ static int cliprdr_server_send_format_list_response(CliprdrServerContext* contex
wStream* s;
BOOL status;
CLIPRDR_HEADER header;
ULONG written;
printf("CliprdrServerSendFormatListResponse\n");
@ -150,7 +153,7 @@ static int cliprdr_server_send_format_list_response(CliprdrServerContext* contex
Stream_SealLength(s);
status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_Length(s), NULL);
status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_Length(s), &written);
Stream_Free(s, TRUE);

View File

@ -83,11 +83,7 @@ int disp_send_display_control_monitor_layout_pdu(DISP_CHANNEL_CALLBACK* callback
disp = (DISP_PLUGIN*) callback->plugin;
#ifdef DISP_PREVIEW
MonitorLayoutSize = 32;
#else
MonitorLayoutSize = 40;
#endif
length = 8 + 8 + (NumMonitors * MonitorLayoutSize);
@ -101,11 +97,7 @@ int disp_send_display_control_monitor_layout_pdu(DISP_CHANNEL_CALLBACK* callback
if (NumMonitors > disp->MaxNumMonitors)
NumMonitors = disp->MaxNumMonitors;
#ifdef DISP_PREVIEW
Stream_Write_UINT32(s, NumMonitors); /* NumMonitors (4 bytes) */
#else
Stream_Write_UINT32(s, MonitorLayoutSize); /* MonitorLayoutSize (4 bytes) */
#endif
Stream_Write_UINT32(s, NumMonitors); /* NumMonitors (4 bytes) */
@ -147,10 +139,8 @@ int disp_send_display_control_monitor_layout_pdu(DISP_CHANNEL_CALLBACK* callback
fprintf(stderr, "\t: Orientation: %d\n", Monitors[index].Orientation);
#endif
#ifndef DISP_PREVIEW
Stream_Write_UINT32(s, Monitors[index].DesktopScaleFactor); /* DesktopScaleFactor (4 bytes) */
Stream_Write_UINT32(s, Monitors[index].DeviceScaleFactor); /* DeviceScaleFactor (4 bytes) */
#endif
}
Stream_SealLength(s);
@ -201,17 +191,12 @@ int disp_recv_pdu(DISP_CHANNEL_CALLBACK* callback, wStream* s)
return 0;
}
static int disp_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, UINT32 cbSize, BYTE* pBuffer)
static int disp_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, wStream *data)
{
wStream* s;
int status = 0;
DISP_CHANNEL_CALLBACK* callback = (DISP_CHANNEL_CALLBACK*) pChannelCallback;
s = Stream_New(pBuffer, cbSize);
status = disp_recv_pdu(callback, s);
Stream_Free(s, FALSE);
status = disp_recv_pdu(callback, data);
return status;
}
@ -308,33 +293,34 @@ int DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints)
disp = (DISP_PLUGIN*) pEntryPoints->GetPlugin(pEntryPoints, "disp");
if (disp == NULL)
if (!disp)
{
disp = (DISP_PLUGIN*) malloc(sizeof(DISP_PLUGIN));
disp = (DISP_PLUGIN*) calloc(1, sizeof(DISP_PLUGIN));
if (disp)
{
ZeroMemory(disp, sizeof(DISP_PLUGIN));
if (!disp)
return -1;
disp->iface.Initialize = disp_plugin_initialize;
disp->iface.Connected = NULL;
disp->iface.Disconnected = NULL;
disp->iface.Terminated = disp_plugin_terminated;
disp->iface.Initialize = disp_plugin_initialize;
disp->iface.Connected = NULL;
disp->iface.Disconnected = NULL;
disp->iface.Terminated = disp_plugin_terminated;
context = (DispClientContext*) malloc(sizeof(DispClientContext));
context = (DispClientContext*) calloc(1, sizeof(DispClientContext));
context->handle = (void*) disp;
if (!context)
return -1;
context->SendMonitorLayout = disp_send_monitor_layout;
context->handle = (void*) disp;
disp->iface.pInterface = (void*) context;
context->SendMonitorLayout = disp_send_monitor_layout;
disp->MaxNumMonitors = 16;
disp->MaxMonitorWidth = 8192;
disp->MaxMonitorHeight = 8192;
disp->iface.pInterface = (void*) context;
error = pEntryPoints->RegisterPlugin(pEntryPoints, "disp", (IWTSPlugin*) disp);
}
disp->MaxNumMonitors = 16;
disp->MaxMonitorWidth = 8192;
disp->MaxMonitorHeight = 8192;
error = pEntryPoints->RegisterPlugin(pEntryPoints, "disp", (IWTSPlugin*) disp);
}
return error;

View File

@ -34,7 +34,5 @@
#define DISPLAY_CONTROL_PDU_TYPE_MONITOR_LAYOUT 0x00000002
#define DISPLAY_CONTROL_PDU_TYPE_CAPS 0x00000003
#define DISP_PREVIEW 1
#endif /* FREERDP_CHANNEL_DISP_CLIENT_MAIN_H */

View File

@ -29,45 +29,44 @@
#include <winpr/stream.h>
#include <freerdp/constants.h>
#include <freerdp/utils/svc_plugin.h>
#include "dvcman.h"
#include "drdynvc_types.h"
#include "drdynvc_main.h"
static int drdynvc_write_variable_uint(wStream* stream, UINT32 val)
static int drdynvc_write_variable_uint(wStream* s, UINT32 val)
{
int cb;
if (val <= 0xFF)
{
cb = 0;
Stream_Write_UINT8(stream, val);
Stream_Write_UINT8(s, val);
}
else if (val <= 0xFFFF)
{
cb = 1;
Stream_Write_UINT16(stream, val);
Stream_Write_UINT16(s, val);
}
else
{
cb = 2;
Stream_Write_UINT32(stream, val);
Stream_Write_UINT32(s, val);
}
return cb;
}
int drdynvc_write_data(drdynvcPlugin* drdynvc, UINT32 ChannelId, BYTE* data, UINT32 data_size)
int drdynvc_write_data(drdynvcPlugin* drdynvc, UINT32 ChannelId, BYTE* data, UINT32 dataSize)
{
wStream* data_out;
UINT32 pos = 0;
UINT32 cbChId;
UINT32 cbLen;
UINT32 chunk_len;
int error;
UINT32 chunkLength;
int status;
DEBUG_DVC("ChannelId=%d size=%d", ChannelId, data_size);
DEBUG_DVC("ChannelId=%d size=%d", ChannelId, dataSize);
if (drdynvc->channel_error != CHANNEL_RC_OK)
return 1;
@ -76,38 +75,38 @@ int drdynvc_write_data(drdynvcPlugin* drdynvc, UINT32 ChannelId, BYTE* data, UIN
Stream_SetPosition(data_out, 1);
cbChId = drdynvc_write_variable_uint(data_out, ChannelId);
if (data_size == 0)
if (dataSize == 0)
{
pos = Stream_GetPosition(data_out);
Stream_SetPosition(data_out, 0);
Stream_Write_UINT8(data_out, 0x40 | cbChId);
Stream_SetPosition(data_out, pos);
error = svc_plugin_send((rdpSvcPlugin*) drdynvc, data_out);
status = svc_plugin_send((rdpSvcPlugin*) drdynvc, data_out);
}
else if (data_size <= CHANNEL_CHUNK_LENGTH - pos)
else if (dataSize <= CHANNEL_CHUNK_LENGTH - pos)
{
pos = Stream_GetPosition(data_out);
Stream_SetPosition(data_out, 0);
Stream_Write_UINT8(data_out, 0x30 | cbChId);
Stream_SetPosition(data_out, pos);
Stream_Write(data_out, data, data_size);
error = svc_plugin_send((rdpSvcPlugin*) drdynvc, data_out);
Stream_Write(data_out, data, dataSize);
status = svc_plugin_send((rdpSvcPlugin*) drdynvc, data_out);
}
else
{
/* Fragment the data */
cbLen = drdynvc_write_variable_uint(data_out, data_size);
cbLen = drdynvc_write_variable_uint(data_out, dataSize);
pos = Stream_GetPosition(data_out);
Stream_SetPosition(data_out, 0);
Stream_Write_UINT8(data_out, 0x20 | cbChId | (cbLen << 2));
Stream_SetPosition(data_out, pos);
chunk_len = CHANNEL_CHUNK_LENGTH - pos;
Stream_Write(data_out, data, chunk_len);
data += chunk_len;
data_size -= chunk_len;
error = svc_plugin_send((rdpSvcPlugin*) drdynvc, data_out);
chunkLength = CHANNEL_CHUNK_LENGTH - pos;
Stream_Write(data_out, data, chunkLength);
data += chunkLength;
dataSize -= chunkLength;
status = svc_plugin_send((rdpSvcPlugin*) drdynvc, data_out);
while (error == CHANNEL_RC_OK && data_size > 0)
while (status == CHANNEL_RC_OK && dataSize > 0)
{
data_out = Stream_New(NULL, CHANNEL_CHUNK_LENGTH);
Stream_SetPosition(data_out, 1);
@ -118,20 +117,20 @@ int drdynvc_write_data(drdynvcPlugin* drdynvc, UINT32 ChannelId, BYTE* data, UIN
Stream_Write_UINT8(data_out, 0x30 | cbChId);
Stream_SetPosition(data_out, pos);
chunk_len = data_size;
if (chunk_len > CHANNEL_CHUNK_LENGTH - pos)
chunk_len = CHANNEL_CHUNK_LENGTH - pos;
Stream_Write(data_out, data, chunk_len);
data += chunk_len;
data_size -= chunk_len;
error = svc_plugin_send((rdpSvcPlugin*)drdynvc, data_out);
chunkLength = dataSize;
if (chunkLength > CHANNEL_CHUNK_LENGTH - pos)
chunkLength = CHANNEL_CHUNK_LENGTH - pos;
Stream_Write(data_out, data, chunkLength);
data += chunkLength;
dataSize -= chunkLength;
status = svc_plugin_send((rdpSvcPlugin*)drdynvc, data_out);
}
}
if (error != CHANNEL_RC_OK)
if (status != CHANNEL_RC_OK)
{
drdynvc->channel_error = error;
DEBUG_WARN("VirtualChannelWrite failed %d", error);
drdynvc->channel_error = status;
DEBUG_WARN("VirtualChannelWrite failed %d", status);
return 1;
}
@ -140,25 +139,45 @@ int drdynvc_write_data(drdynvcPlugin* drdynvc, UINT32 ChannelId, BYTE* data, UIN
int drdynvc_push_event(drdynvcPlugin* drdynvc, wMessage* event)
{
int error;
int status;
error = svc_plugin_send_event((rdpSvcPlugin*) drdynvc, event);
status = svc_plugin_send_event((rdpSvcPlugin*) drdynvc, event);
if (error != CHANNEL_RC_OK)
if (status != CHANNEL_RC_OK)
{
DEBUG_WARN("pVirtualChannelEventPush failed %d", error);
DEBUG_WARN("pVirtualChannelEventPush failed %d", status);
return 1;
}
return 0;
}
static int drdynvc_send_capability_response(drdynvcPlugin* drdynvc)
{
int status;
wStream* s;
s = Stream_New(NULL, 4);
Stream_Write_UINT16(s, 0x0050); /* Cmd+Sp+cbChId+Pad. Note: MSTSC sends 0x005c */
Stream_Write_UINT16(s, drdynvc->version);
status = svc_plugin_send((rdpSvcPlugin*) drdynvc, s);
if (status != CHANNEL_RC_OK)
{
DEBUG_WARN("VirtualChannelWrite failed %d", status);
return 1;
}
return status;
}
static int drdynvc_process_capability_request(drdynvcPlugin* drdynvc, int Sp, int cbChId, wStream* s)
{
wStream* data_out;
int error;
int status;
DEBUG_DVC("Sp=%d cbChId=%d", Sp, cbChId);
Stream_Seek(s, 1); /* pad */
Stream_Read_UINT16(s, drdynvc->version);
@ -173,38 +192,31 @@ static int drdynvc_process_capability_request(drdynvcPlugin* drdynvc, int Sp, in
Stream_Read_UINT16(s, drdynvc->PriorityCharge3);
}
data_out = Stream_New(NULL, 4);
Stream_Write_UINT16(data_out, 0x0050); /* Cmd+Sp+cbChId+Pad. Note: MSTSC sends 0x005c */
Stream_Write_UINT16(data_out, drdynvc->version);
error = svc_plugin_send((rdpSvcPlugin*) drdynvc, data_out);
status = drdynvc_send_capability_response(drdynvc);
if (error != CHANNEL_RC_OK)
{
DEBUG_WARN("VirtualChannelWrite failed %d", error);
return 1;
}
drdynvc->channel_error = status;
drdynvc->channel_error = error;
drdynvc->state = DRDYNVC_STATE_READY;
return 0;
}
static UINT32 drdynvc_read_variable_uint(wStream* stream, int cbLen)
static UINT32 drdynvc_read_variable_uint(wStream* s, int cbLen)
{
UINT32 val;
switch (cbLen)
{
case 0:
Stream_Read_UINT8(stream, val);
Stream_Read_UINT8(s, val);
break;
case 1:
Stream_Read_UINT16(stream, val);
Stream_Read_UINT16(s, val);
break;
default:
Stream_Read_UINT32(stream, val);
Stream_Read_UINT32(s, val);
break;
}
@ -217,19 +229,33 @@ static int drdynvc_process_create_request(drdynvcPlugin* drdynvc, int Sp, int cb
int status;
UINT32 ChannelId;
wStream* data_out;
int channel_status;
if (drdynvc->state == DRDYNVC_STATE_CAPABILITIES)
{
/**
* For some reason the server does not always send the
* capabilities pdu as it should. When this happens,
* send a capabilities response.
*/
drdynvc->version = 3;
drdynvc_send_capability_response(drdynvc);
drdynvc->state = DRDYNVC_STATE_READY;
}
ChannelId = drdynvc_read_variable_uint(s, cbChId);
pos = Stream_GetPosition(s);
DEBUG_DVC("ChannelId=%d ChannelName=%s", ChannelId, Stream_Pointer(s));
status = dvcman_create_channel(drdynvc->channel_mgr, ChannelId, (char*) Stream_Pointer(s));
channel_status = dvcman_create_channel(drdynvc->channel_mgr, ChannelId, (char*) Stream_Pointer(s));
data_out = Stream_New(NULL, pos + 4);
Stream_Write_UINT8(data_out, 0x10 | cbChId);
Stream_SetPosition(s, 1);
Stream_Copy(data_out, s, pos - 1);
if (status == 0)
if (channel_status == 0)
{
DEBUG_DVC("channel created");
Stream_Write_UINT32(data_out, 0);
@ -248,6 +274,11 @@ static int drdynvc_process_create_request(drdynvcPlugin* drdynvc, int Sp, int cb
return 1;
}
if (channel_status == 0)
{
dvcman_open_channel(drdynvc->channel_mgr, ChannelId);
}
return 0;
}
@ -266,8 +297,7 @@ static int drdynvc_process_data_first(drdynvcPlugin* drdynvc, int Sp, int cbChId
if (status)
return status;
return dvcman_receive_channel_data(drdynvc->channel_mgr, ChannelId,
Stream_Pointer(s), Stream_GetRemainingLength(s));
return dvcman_receive_channel_data(drdynvc->channel_mgr, ChannelId, s);
}
static int drdynvc_process_data(drdynvcPlugin* drdynvc, int Sp, int cbChId, wStream* s)
@ -277,8 +307,7 @@ static int drdynvc_process_data(drdynvcPlugin* drdynvc, int Sp, int cbChId, wStr
ChannelId = drdynvc_read_variable_uint(s, cbChId);
DEBUG_DVC("ChannelId=%d", ChannelId);
return dvcman_receive_channel_data(drdynvc->channel_mgr, ChannelId,
Stream_Pointer(s), Stream_GetRemainingLength(s));
return dvcman_receive_channel_data(drdynvc->channel_mgr, ChannelId, s);
}
static int drdynvc_process_close_request(drdynvcPlugin* drdynvc, int Sp, int cbChId, wStream* s)
@ -350,8 +379,6 @@ static void drdynvc_process_receive(rdpSvcPlugin* plugin, wStream* s)
DEBUG_WARN("unknown drdynvc cmd 0x%x", Cmd);
break;
}
Stream_Free(s, TRUE);
}
static void drdynvc_process_connect(rdpSvcPlugin* plugin)
@ -375,6 +402,8 @@ static void drdynvc_process_connect(rdpSvcPlugin* plugin)
}
dvcman_init(drdynvc->channel_mgr);
drdynvc->state = DRDYNVC_STATE_CAPABILITIES;
}
static void drdynvc_process_event(rdpSvcPlugin* plugin, wMessage* event)
@ -388,8 +417,16 @@ static void drdynvc_process_terminate(rdpSvcPlugin* plugin)
DEBUG_DVC("terminating");
if (!drdynvc)
return;
if (drdynvc->channel_mgr)
{
dvcman_free(drdynvc->channel_mgr);
drdynvc->channel_mgr = NULL;
}
svc_plugin_terminate(plugin);
free(drdynvc);
}
@ -413,8 +450,10 @@ BOOL VCAPITYPE VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints)
DrdynvcClientContext* context;
CHANNEL_ENTRY_POINTS_FREERDP* pEntryPointsEx;
_p = (drdynvcPlugin*) malloc(sizeof(drdynvcPlugin));
ZeroMemory(_p, sizeof(drdynvcPlugin));
_p = (drdynvcPlugin*) calloc(1, sizeof(drdynvcPlugin));
if (!_p)
return FALSE;
_p->plugin.channel_def.options =
CHANNEL_OPTION_INITIALIZED |
@ -423,6 +462,8 @@ BOOL VCAPITYPE VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints)
strcpy(_p->plugin.channel_def.name, "drdynvc");
_p->state = DRDYNVC_STATE_INITIAL;
_p->plugin.connect_callback = drdynvc_process_connect;
_p->plugin.receive_callback = drdynvc_process_receive;
_p->plugin.event_callback = drdynvc_process_event;
@ -433,7 +474,10 @@ BOOL VCAPITYPE VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints)
if ((pEntryPointsEx->cbSize >= sizeof(CHANNEL_ENTRY_POINTS_FREERDP)) &&
(pEntryPointsEx->MagicNumber == FREERDP_CHANNEL_MAGIC_NUMBER))
{
context = (DrdynvcClientContext*) malloc(sizeof(DrdynvcClientContext));
context = (DrdynvcClientContext*) calloc(1, sizeof(DrdynvcClientContext));
if (!context)
return -1;
context->handle = (void*) _p;
_p->context = context;
@ -447,3 +491,4 @@ BOOL VCAPITYPE VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints)
return 1;
}

View File

@ -26,6 +26,17 @@
#include <freerdp/client/drdynvc.h>
#include <freerdp/utils/svc_plugin.h>
enum _DRDYNVC_STATE
{
DRDYNVC_STATE_INITIAL,
DRDYNVC_STATE_CAPABILITIES,
DRDYNVC_STATE_READY,
DRDYNVC_STATE_OPENING_CHANNEL,
DRDYNVC_STATE_SEND_RECEIVE,
DRDYNVC_STATE_FINAL
};
typedef enum _DRDYNVC_STATE DRDYNVC_STATE;
#define CREATE_REQUEST_PDU 0x01
#define DATA_FIRST_PDU 0x02
#define DATA_PDU 0x03
@ -38,6 +49,7 @@ struct drdynvc_plugin
{
rdpSvcPlugin plugin;
DRDYNVC_STATE state;
DrdynvcClientContext* context;
int version;

View File

@ -195,8 +195,7 @@ IWTSVirtualChannelManager* dvcman_new(drdynvcPlugin* plugin)
{
DVCMAN* dvcman;
dvcman = (DVCMAN*) malloc(sizeof(DVCMAN));
ZeroMemory(dvcman, sizeof(DVCMAN));
dvcman = (DVCMAN*) calloc(1, sizeof(DVCMAN));
dvcman->iface.CreateListener = dvcman_create_listener;
dvcman->iface.PushEvent = dvcman_push_event;
@ -204,6 +203,7 @@ IWTSVirtualChannelManager* dvcman_new(drdynvcPlugin* plugin)
dvcman->iface.GetChannelId = dvcman_get_channel_id;
dvcman->drdynvc = plugin;
dvcman->channels = ArrayList_New(TRUE);
dvcman->pool = StreamPool_New(TRUE, 10);
return (IWTSVirtualChannelManager*) dvcman;
}
@ -237,6 +237,8 @@ static void dvcman_channel_free(DVCMAN_CHANNEL* channel)
if (channel->channel_callback)
channel->channel_callback->OnClose(channel->channel_callback);
DeleteCriticalSection(&(channel->lock));
free(channel);
}
@ -278,6 +280,7 @@ void dvcman_free(IWTSVirtualChannelManager* pChannelMgr)
pPlugin->Terminated(pPlugin);
}
StreamPool_Free(dvcman->pool);
free(dvcman);
}
@ -303,9 +306,11 @@ static int dvcman_write_channel(IWTSVirtualChannel* pChannel, UINT32 cbSize, BYT
int status;
DVCMAN_CHANNEL* channel = (DVCMAN_CHANNEL*) pChannel;
WaitForSingleObject(channel->dvc_chan_mutex, INFINITE);
EnterCriticalSection(&(channel->lock));
status = drdynvc_write_data(channel->dvcman->drdynvc, channel->channel_id, pBuffer, cbSize);
ReleaseMutex(channel->dvc_chan_mutex);
LeaveCriticalSection(&(channel->lock));
return status;
}
@ -334,8 +339,10 @@ int dvcman_create_channel(IWTSVirtualChannelManager* pChannelMgr, UINT32 Channel
IWTSVirtualChannelCallback* pCallback;
DVCMAN* dvcman = (DVCMAN*) pChannelMgr;
channel = (DVCMAN_CHANNEL*) malloc(sizeof(DVCMAN_CHANNEL));
ZeroMemory(channel, sizeof(DVCMAN_CHANNEL));
channel = (DVCMAN_CHANNEL*) calloc(1, sizeof(DVCMAN_CHANNEL));
if (!channel)
return -1;
channel->dvcman = dvcman;
channel->channel_id = ChannelId;
@ -349,7 +356,8 @@ int dvcman_create_channel(IWTSVirtualChannelManager* pChannelMgr, UINT32 Channel
{
channel->iface.Write = dvcman_write_channel;
channel->iface.Close = dvcman_close_channel_iface;
channel->dvc_chan_mutex = CreateMutex(NULL, FALSE, NULL);
InitializeCriticalSection(&(channel->lock));
bAccept = 1;
pCallback = NULL;
@ -385,6 +393,28 @@ int dvcman_create_channel(IWTSVirtualChannelManager* pChannelMgr, UINT32 Channel
return 1;
}
int dvcman_open_channel(IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelId)
{
DVCMAN_CHANNEL* channel;
IWTSVirtualChannelCallback* pCallback;
channel = (DVCMAN_CHANNEL*) dvcman_find_channel_by_id(pChannelMgr, ChannelId);
if (!channel)
{
DEBUG_WARN("ChannelId %d not found!", ChannelId);
return 1;
}
if (channel->status == 0)
{
pCallback = channel->channel_callback;
pCallback->OnOpen(pCallback);
}
return 0;
}
int dvcman_close_channel(IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelId)
{
DVCMAN_CHANNEL* channel;
@ -402,7 +432,7 @@ int dvcman_close_channel(IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelI
if (channel->dvc_data)
{
Stream_Free(channel->dvc_data, TRUE);
Stream_Release(channel->dvc_data);
channel->dvc_data = NULL;
}
@ -435,17 +465,19 @@ int dvcman_receive_channel_data_first(IWTSVirtualChannelManager* pChannelMgr, UI
}
if (channel->dvc_data)
Stream_Free(channel->dvc_data, TRUE);
Stream_Release(channel->dvc_data);
channel->dvc_data = Stream_New(NULL, length);
channel->dvc_data = StreamPool_Take(channel->dvcman->pool, length);
Stream_AddRef(channel->dvc_data);
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, wStream* data)
{
int error = 0;
int status = 0;
DVCMAN_CHANNEL* channel;
UINT32 dataSize = Stream_GetRemainingLength(data);
channel = (DVCMAN_CHANNEL*) dvcman_find_channel_by_id(pChannelMgr, ChannelId);
@ -458,28 +490,30 @@ int dvcman_receive_channel_data(IWTSVirtualChannelManager* pChannelMgr, UINT32 C
if (channel->dvc_data)
{
/* Fragmented data */
if (Stream_GetPosition(channel->dvc_data) + data_size > (UINT32) Stream_Capacity(channel->dvc_data))
if (Stream_GetPosition(channel->dvc_data) + dataSize > (UINT32) Stream_Capacity(channel->dvc_data))
{
DEBUG_WARN("data exceeding declared length!");
Stream_Free(channel->dvc_data, TRUE);
Stream_Release(channel->dvc_data);
channel->dvc_data = NULL;
return 1;
}
Stream_Write(channel->dvc_data, data, data_size);
Stream_Write(channel->dvc_data, Stream_Pointer(data), dataSize);
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_Free(channel->dvc_data, TRUE);
Stream_SealLength(channel->dvc_data);
Stream_SetPosition(channel->dvc_data, 0);
status = channel->channel_callback->OnDataReceived(channel->channel_callback, channel->dvc_data);
Stream_Release(channel->dvc_data);
channel->dvc_data = NULL;
}
}
else
{
error = channel->channel_callback->OnDataReceived(channel->channel_callback, data_size, data);
status = channel->channel_callback->OnDataReceived(channel->channel_callback, data);
}
return error;
return status;
}

View File

@ -23,6 +23,7 @@
#include <freerdp/dvc.h>
#include <freerdp/addin.h>
#include <winpr/synch.h>
#include <winpr/collections.h>
#include "drdynvc_main.h"
@ -43,6 +44,7 @@ struct _DVCMAN
int num_listeners;
wArrayList* channels;
wStreamPool* pool;
};
typedef struct _DVCMAN DVCMAN;
@ -78,7 +80,7 @@ struct _DVCMAN_CHANNEL
IWTSVirtualChannelCallback* channel_callback;
wStream* dvc_data;
HANDLE dvc_chan_mutex;
CRITICAL_SECTION lock;
};
typedef struct _DVCMAN_CHANNEL DVCMAN_CHANNEL;
@ -87,9 +89,10 @@ int dvcman_load_addin(IWTSVirtualChannelManager* pChannelMgr, ADDIN_ARGV* args);
void dvcman_free(IWTSVirtualChannelManager* pChannelMgr);
int dvcman_init(IWTSVirtualChannelManager* pChannelMgr);
int dvcman_create_channel(IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelId, const char* ChannelName);
int dvcman_open_channel(IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelId);
int dvcman_close_channel(IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelId);
int dvcman_receive_channel_data_first(IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelId, UINT32 length);
int dvcman_receive_channel_data(IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelId, BYTE* data, UINT32 data_size);
int dvcman_receive_channel_data(IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelId, wStream *data);
void* dvcman_get_channel_interface_by_name(IWTSVirtualChannelManager* pChannelMgr, const char* ChannelName);

View File

@ -61,10 +61,12 @@ struct _ECHO_PLUGIN
ECHO_LISTENER_CALLBACK* listener_callback;
};
static int echo_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, UINT32 cbSize, BYTE* pBuffer)
static int echo_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, wStream *data)
{
int error;
ECHO_CHANNEL_CALLBACK* callback = (ECHO_CHANNEL_CALLBACK*) pChannelCallback;
BYTE *pBuffer = Stream_Pointer(data);
UINT32 cbSize = Stream_GetRemainingLength(data);
#ifdef WITH_DEBUG_DVC
int i = 0;

View File

@ -47,13 +47,12 @@
#include <winpr/crt.h>
#include <winpr/synch.h>
#include <winpr/thread.h>
#include <winpr/stream.h>
#include <winpr/collections.h>
#include <winpr/interlocked.h>
#include <freerdp/types.h>
#include <freerdp/constants.h>
#include <winpr/stream.h>
#include <freerdp/utils/svc_plugin.h>
#include <freerdp/channels/rdpdr.h>
struct _PARALLEL_DEVICE
@ -93,16 +92,14 @@ static void parallel_process_irp_create(PARALLEL_DEVICE* parallel, IRP* irp)
{
irp->IoStatus = STATUS_ACCESS_DENIED;
parallel->id = 0;
DEBUG_WARN("failed to create %s: %s", parallel->path, strerror(errno));
}
else
{
/* all read and write operations should be non-blocking */
if (fcntl(parallel->file, F_SETFL, O_NONBLOCK) == -1)
DEBUG_WARN("%s fcntl %s", path, strerror(errno));
{
DEBUG_SVC("%s(%d) created", parallel->path, parallel->file);
}
}
Stream_Write_UINT32(irp->output, parallel->id);
@ -116,9 +113,13 @@ static void parallel_process_irp_create(PARALLEL_DEVICE* parallel, IRP* irp)
static void parallel_process_irp_close(PARALLEL_DEVICE* parallel, IRP* irp)
{
if (close(parallel->file) < 0)
DEBUG_SVC("failed to close %s(%d)", parallel->path, parallel->id);
{
}
else
DEBUG_SVC("%s(%d) closed", parallel->path, parallel->id);
{
}
Stream_Zero(irp->output, 5); /* Padding(5) */
@ -145,12 +146,10 @@ static void parallel_process_irp_read(PARALLEL_DEVICE* parallel, IRP* irp)
free(buffer);
buffer = NULL;
Length = 0;
DEBUG_WARN("read %s(%d) failed", parallel->path, parallel->id);
}
else
{
DEBUG_SVC("read %llu-%llu from %d", Offset, Offset + Length, parallel->id);
}
Stream_Write_UINT32(irp->output, Length);
@ -177,8 +176,6 @@ static void parallel_process_irp_write(PARALLEL_DEVICE* parallel, IRP* irp)
Stream_Read_UINT64(irp->input, Offset);
Stream_Seek(irp->input, 20); /* Padding */
DEBUG_SVC("Length %u Offset %llu", Length, Offset);
len = Length;
while (len > 0)
@ -189,8 +186,6 @@ static void parallel_process_irp_write(PARALLEL_DEVICE* parallel, IRP* irp)
{
irp->IoStatus = STATUS_UNSUCCESSFUL;
Length = 0;
DEBUG_WARN("write %s(%d) failed.", parallel->path, parallel->id);
break;
}
@ -206,15 +201,12 @@ static void parallel_process_irp_write(PARALLEL_DEVICE* parallel, IRP* irp)
static void parallel_process_irp_device_control(PARALLEL_DEVICE* parallel, IRP* irp)
{
DEBUG_SVC("in");
Stream_Write_UINT32(irp->output, 0); /* OutputBufferLength */
irp->Complete(irp);
}
static void parallel_process_irp(PARALLEL_DEVICE* parallel, IRP* irp)
{
DEBUG_SVC("MajorFunction %u", irp->MajorFunction);
switch (irp->MajorFunction)
{
case IRP_MJ_CREATE:
@ -238,7 +230,6 @@ static void parallel_process_irp(PARALLEL_DEVICE* parallel, IRP* irp)
break;
default:
DEBUG_WARN("MajorFunction 0x%X not supported", irp->MajorFunction);
irp->IoStatus = STATUS_NOT_SUPPORTED;
irp->Complete(irp);
break;
@ -281,8 +272,6 @@ static void parallel_free(DEVICE* device)
{
PARALLEL_DEVICE* parallel = (PARALLEL_DEVICE*) device;
DEBUG_SVC("freeing device");
MessageQueue_PostQuit(parallel->queue, 0);
WaitForSingleObject(parallel->thread, INFINITE);
CloseHandle(parallel->thread);

View File

@ -31,7 +31,6 @@
#include <winpr/crt.h>
#include <freerdp/utils/svc_plugin.h>
#include <freerdp/channels/rdpdr.h>
#include "printer_main.h"
@ -87,15 +86,12 @@ static void printer_cups_write_printjob(rdpPrintJob* printjob, BYTE* data, int s
fp = fopen((const char*) cups_printjob->printjob_object, "a+b");
if (fp == NULL)
{
DEBUG_WARN("failed to open file %s", (char*) cups_printjob->printjob_object);
if (!fp)
return;
}
if (fwrite(data, 1, size, fp) < size)
{
DEBUG_WARN("failed to write file %s", (char*) cups_printjob->printjob_object);
}
fclose(fp);
@ -121,7 +117,7 @@ static void printer_cups_close_printjob(rdpPrintJob* printjob)
if (cupsPrintFile(printjob->printer->name, (const char*) cups_printjob->printjob_object, buf, 0, NULL) == 0)
{
DEBUG_WARN("cupsPrintFile: %s", cupsLastErrorString());
}
unlink(cups_printjob->printjob_object);
@ -167,20 +163,19 @@ static rdpPrintJob* printer_cups_create_printjob(rdpPrinter* printer, UINT32 id)
cups_printjob->printjob_object = httpConnectEncrypt(cupsServer(), ippPort(), HTTP_ENCRYPT_IF_REQUESTED);
if (cups_printjob->printjob_object == NULL)
if (!cups_printjob->printjob_object)
{
DEBUG_WARN("httpConnectEncrypt: %s", cupsLastErrorString());
free(cups_printjob);
return NULL;
}
printer_cups_get_printjob_name(buf, sizeof(buf));
cups_printjob->printjob_id = cupsCreateJob((http_t*) cups_printjob->printjob_object,
printer->name, buf, 0, NULL);
if (cups_printjob->printjob_id == 0)
if (!cups_printjob->printjob_id)
{
DEBUG_WARN("cupsCreateJob: %s", cupsLastErrorString());
httpClose((http_t*) cups_printjob->printjob_object);
free(cups_printjob);
return NULL;
@ -281,19 +276,15 @@ rdpPrinterDriver* printer_cups_get_driver(void)
{
if (cups_driver == NULL)
{
cups_driver = (rdpCupsPrinterDriver*) malloc(sizeof(rdpCupsPrinterDriver));
ZeroMemory(cups_driver, sizeof(rdpCupsPrinterDriver));
cups_driver = (rdpCupsPrinterDriver*) calloc(1, sizeof(rdpCupsPrinterDriver));
if (!cups_driver)
return NULL;
cups_driver->driver.EnumPrinters = printer_cups_enum_printers;
cups_driver->driver.GetPrinter = printer_cups_get_printer;
cups_driver->id_sequence = 1;
#ifdef _CUPS_API_1_4
DEBUG_SVC("using CUPS API 1.4");
#else
DEBUG_SVC("using CUPS API 1.2");
#endif
}
return (rdpPrinterDriver*) cups_driver;

View File

@ -28,11 +28,10 @@
#include <winpr/crt.h>
#include <winpr/synch.h>
#include <winpr/thread.h>
#include <winpr/stream.h>
#include <winpr/interlocked.h>
#include <winpr/stream.h>
#include <freerdp/channels/rdpdr.h>
#include <freerdp/utils/svc_plugin.h>
#ifdef WITH_CUPS
#include "printer_cups.h"
@ -69,15 +68,11 @@ static void printer_process_irp_create(PRINTER_DEVICE* printer_dev, IRP* irp)
if (printjob)
{
Stream_Write_UINT32(irp->output, printjob->id); /* FileId */
DEBUG_SVC("printjob id: %d", printjob->id);
}
else
{
Stream_Write_UINT32(irp->output, 0); /* FileId */
irp->IoStatus = STATUS_PRINT_QUEUE_FULL;
DEBUG_WARN("error creating print job.");
}
irp->Complete(irp);
@ -87,20 +82,16 @@ static void printer_process_irp_close(PRINTER_DEVICE* printer_dev, IRP* irp)
{
rdpPrintJob* printjob = NULL;
if (printer_dev->printer != NULL)
if (printer_dev->printer)
printjob = printer_dev->printer->FindPrintJob(printer_dev->printer, irp->FileId);
if (!printjob)
{
irp->IoStatus = STATUS_UNSUCCESSFUL;
DEBUG_WARN("printjob id %d not found.", irp->FileId);
}
else
{
printjob->Close(printjob);
DEBUG_SVC("printjob id %d closed.", irp->FileId);
}
Stream_Zero(irp->output, 4); /* Padding(4) */
@ -125,14 +116,10 @@ static void printer_process_irp_write(PRINTER_DEVICE* printer_dev, IRP* irp)
{
irp->IoStatus = STATUS_UNSUCCESSFUL;
Length = 0;
DEBUG_WARN("printjob id %d not found.", irp->FileId);
}
else
{
printjob->Write(printjob, Stream_Pointer(irp->input), Length);
DEBUG_SVC("printjob id %d written %d bytes.", irp->FileId, Length);
}
Stream_Write_UINT32(irp->output, Length);
@ -168,7 +155,6 @@ static void printer_process_irp(PRINTER_DEVICE* printer_dev, IRP* irp)
break;
default:
DEBUG_WARN("MajorFunction 0x%X not supported", irp->MajorFunction);
irp->IoStatus = STATUS_NOT_SUPPORTED;
irp->Complete(irp);
break;
@ -267,8 +253,6 @@ void printer_register(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints, rdpPrinter* pri
CachedFieldsLen = 0;
CachedPrinterConfigData = NULL;
DEBUG_SVC("Printer %s registered", printer->name);
Flags = 0;
if (printer->is_default)
@ -332,9 +316,8 @@ int DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
driver = printer_win_get_driver();
#endif
if (driver == NULL)
if (!driver)
{
DEBUG_WARN("no driver");
return 1;
}
@ -347,10 +330,7 @@ int DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
printer = driver->GetPrinter(driver, name);
if (!printer)
{
DEBUG_WARN("printer %s not found.", name);
return 1;
}
if (driver_name && driver_name[0])
printer->driver = driver_name;

View File

@ -30,8 +30,6 @@
#include <string.h>
#include <winspool.h>
#include <freerdp/utils/svc_plugin.h>
#include "printer_main.h"
#include "printer_win.h"
@ -69,45 +67,44 @@ static void printer_win_get_printjob_name(char* buf, int size)
time_t tt;
struct tm* t;
DEBUG_WINPR("");
tt = time(NULL);
t = localtime(&tt);
snprintf(buf, size - 1, "FreeRDP Print Job %d%02d%02d%02d%02d%02d",
t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
t->tm_hour, t->tm_min, t->tm_sec);
DEBUG_WINPR("buf: %s", buf);
}
static void printer_win_write_printjob(rdpPrintJob* printjob, BYTE* data, int size)
{
rdpWinPrintJob* win_printjob = (rdpWinPrintJob*)printjob;
rdpWinPrintJob* win_printjob = (rdpWinPrintJob*) printjob;
LPVOID pBuf = data;
DWORD cbBuf = size;
DWORD pcWritten;
if( ! WritePrinter( ((rdpWinPrinter*)printjob->printer)->hPrinter, pBuf, cbBuf, &pcWritten ) )
DEBUG_WINPR("WritePrinter failed");
;
if(!WritePrinter(((rdpWinPrinter*)printjob->printer)->hPrinter, pBuf, cbBuf, &pcWritten))
{
}
}
static void printer_win_close_printjob(rdpPrintJob* printjob)
{
rdpWinPrintJob* win_printjob = (rdpWinPrintJob*)printjob;
rdpWinPrintJob* win_printjob = (rdpWinPrintJob*) printjob;
DEBUG_WINPR("");
if (!EndPagePrinter(((rdpWinPrinter*) printjob->printer)->hPrinter))
{
if ( ! EndPagePrinter( ((rdpWinPrinter*)printjob->printer)->hPrinter ) )
DEBUG_WINPR("EndPagePrinter failed");;
if ( ! ClosePrinter( ((rdpWinPrinter*)printjob->printer)->hPrinter ) )
DEBUG_WINPR("ClosePrinter failed");;
}
((rdpWinPrinter*)printjob->printer)->printjob = NULL;
free(win_printjob) ;
if (!ClosePrinter(((rdpWinPrinter*) printjob->printer)->hPrinter))
{
}
((rdpWinPrinter*) printjob->printer)->printjob = NULL;
free(win_printjob);
}
static rdpPrintJob* printer_win_create_printjob(rdpPrinter* printer, UINT32 id)
@ -115,13 +112,10 @@ static rdpPrintJob* printer_win_create_printjob(rdpPrinter* printer, UINT32 id)
rdpWinPrinter* win_printer = (rdpWinPrinter*)printer;
rdpWinPrintJob* win_printjob;
DEBUG_WINPR("");
if (win_printer->printjob != NULL)
return NULL;
win_printjob = (rdpWinPrintJob*) malloc(sizeof(rdpWinPrintJob));
ZeroMemory(win_printjob, sizeof(rdpWinPrintJob));
win_printjob = (rdpWinPrintJob*) calloc(1, sizeof(rdpWinPrintJob));
win_printjob->printjob.id = id;
win_printjob->printjob.printer = printer;
@ -132,10 +126,14 @@ static rdpPrintJob* printer_win_create_printjob(rdpPrinter* printer, UINT32 id)
win_printjob->handle = StartDocPrinter(win_printer->hPrinter, 1, (LPBYTE) &(win_printjob->di));
if (!win_printjob->handle)
DEBUG_WINPR("StartDocPrinter failed");
{
}
if (!StartPagePrinter(win_printer->hPrinter))
DEBUG_WINPR("ClosePrinter failed");
{
}
win_printjob->printjob.Write = printer_win_write_printjob;
win_printjob->printjob.Close = printer_win_close_printjob;
@ -149,9 +147,7 @@ static rdpPrintJob* printer_win_find_printjob(rdpPrinter* printer, UINT32 id)
{
rdpWinPrinter* win_printer = (rdpWinPrinter*) printer;
DEBUG_WINPR("");
if (win_printer->printjob == NULL)
if (!win_printer->printjob)
return NULL;
if (win_printer->printjob->printjob.id != id)
@ -164,8 +160,6 @@ static void printer_win_free_printer(rdpPrinter* printer)
{
rdpWinPrinter* win_printer = (rdpWinPrinter*) printer;
DEBUG_WINPR("");
if (win_printer->printjob)
win_printer->printjob->printjob.Close((rdpPrintJob*) win_printer->printjob);
@ -180,10 +174,8 @@ static rdpPrinter* printer_win_new_printer(rdpWinPrinterDriver* win_driver, cons
DWORD needed;
PRINTER_INFO_2 *prninfo=NULL;
size_t charsConverted;
DEBUG_WINPR("");
win_printer = (rdpWinPrinter*) malloc(sizeof(rdpWinPrinter));
ZeroMemory(win_printer, sizeof(rdpWinPrinter));
win_printer = (rdpWinPrinter*) calloc(1, sizeof(rdpWinPrinter));
win_printer->printer.id = win_driver->id_sequence++;
win_printer->printer.name = _strdup(name);
@ -195,7 +187,6 @@ static rdpPrinter* printer_win_new_printer(rdpWinPrinterDriver* win_driver, cons
swprintf(wname, 256, L"%hs", name);
OpenPrinter(wname, &(win_printer->hPrinter), NULL);
DEBUG_WINPR("handle: 0x%08X", win_printer->hPrinter);
GetPrinter(win_printer->hPrinter, 2, (LPBYTE) prninfo, 0, &needed);
prninfo = (PRINTER_INFO_2*) GlobalAlloc(GPTR,needed);
@ -216,8 +207,6 @@ static rdpPrinter** printer_win_enum_printers(rdpPrinterDriver* driver)
size_t charsConverted;
PRINTER_INFO_2* prninfo = NULL;
DWORD needed, returned;
DEBUG_WINPR("");
/* find required size for the buffer */
EnumPrinters(PRINTER_ENUM_LOCAL|PRINTER_ENUM_CONNECTIONS, NULL, 2, NULL, 0, &needed, &returned);
@ -227,19 +216,16 @@ static rdpPrinter** printer_win_enum_printers(rdpPrinterDriver* driver)
prninfo = (PRINTER_INFO_2*) GlobalAlloc(GPTR,needed);
/* call again */
if ( !EnumPrinters(PRINTER_ENUM_LOCAL|PRINTER_ENUM_CONNECTIONS, NULL, 2, (LPBYTE) prninfo, needed, &needed, &returned) )
if (!EnumPrinters(PRINTER_ENUM_LOCAL|PRINTER_ENUM_CONNECTIONS, NULL, 2, (LPBYTE) prninfo, needed, &needed, &returned))
{
DEBUG_WINPR("EnumPrinters failed");
} ; /* ERROR... */
DEBUG_WINPR("printers found: %d", returned);
}
printers = (rdpPrinter**) malloc(sizeof(rdpPrinter*) * (returned + 1));
ZeroMemory(printers, sizeof(rdpPrinter*) * (returned + 1));
printers = (rdpPrinter**) calloc((returned + 1), sizeof(rdpPrinter*));
num_printers = 0;
for (i = 0; i < (int)returned; i++)
for (i = 0; i < (int) returned; i++)
{
wcstombs_s(&charsConverted, pname, 1000, prninfo[i].pPrinterName, _TRUNCATE);
printers[num_printers++] = printer_win_new_printer((rdpWinPrinterDriver*)driver,
@ -254,8 +240,6 @@ static rdpPrinter* printer_win_get_printer(rdpPrinterDriver* driver, const char*
{
rdpWinPrinterDriver* win_driver = (rdpWinPrinterDriver*)driver;
rdpPrinter *myPrinter = NULL;
DEBUG_WINPR("printer %s", name);
myPrinter = printer_win_new_printer(win_driver, name, L"", win_driver->id_sequence == 1 ? TRUE : FALSE);
@ -266,12 +250,9 @@ static rdpWinPrinterDriver* win_driver = NULL;
rdpPrinterDriver* printer_win_get_driver(void)
{
DEBUG_WINPR("");
if (win_driver == NULL)
if (!win_driver)
{
win_driver = (rdpWinPrinterDriver*) malloc(sizeof(rdpWinPrinterDriver));
ZeroMemory(win_driver, sizeof(rdpWinPrinterDriver));
win_driver = (rdpWinPrinterDriver*) calloc(1, sizeof(rdpWinPrinterDriver));
win_driver->driver.EnumPrinters = printer_win_enum_printers;
win_driver->driver.GetPrinter = printer_win_get_printer;

View File

@ -31,7 +31,6 @@
#include <freerdp/types.h>
#include <freerdp/constants.h>
#include <freerdp/utils/svc_plugin.h>
#include <freerdp/utils/rail.h>
#include <freerdp/rail.h>
@ -95,13 +94,13 @@ static void rail_process_terminate(rdpSvcPlugin* plugin)
railPlugin* rail = (railPlugin*) plugin;
WLog_Print(rail->log, WLOG_DEBUG, "Terminate");
svc_plugin_terminate(plugin);
}
static void rail_process_receive(rdpSvcPlugin* plugin, wStream* s)
{
railPlugin* rail = (railPlugin*) plugin;
rail_order_recv(rail, s);
Stream_Free(s, TRUE);
}
static void rail_process_addin_args(rdpRailOrder* railOrder, rdpSettings* settings)
@ -507,8 +506,7 @@ BOOL VCAPITYPE VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints)
RailClientContext* context;
CHANNEL_ENTRY_POINTS_FREERDP* pEntryPointsEx;
rail = (railPlugin*) malloc(sizeof(railPlugin));
ZeroMemory(rail, sizeof(railPlugin));
rail = (railPlugin*) calloc(1, sizeof(railPlugin));
rail->plugin.channel_def.options =
CHANNEL_OPTION_INITIALIZED |

View File

@ -34,6 +34,7 @@ static int rdpdr_server_send_announce_request(RdpdrServerContext* context)
wStream* s;
BOOL status;
RDPDR_HEADER header;
ULONG written;
printf("RdpdrServerSendAnnounceRequest\n");
@ -51,7 +52,7 @@ static int rdpdr_server_send_announce_request(RdpdrServerContext* context)
Stream_SealLength(s);
status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_Length(s), NULL);
status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_Length(s), &written);
Stream_Free(s, TRUE);
@ -295,6 +296,7 @@ static int rdpdr_server_send_core_capability_request(RdpdrServerContext* context
BOOL status;
RDPDR_HEADER header;
UINT16 numCapabilities;
ULONG written;
printf("RdpdrServerSendCoreCapabilityRequest\n");
@ -319,7 +321,7 @@ static int rdpdr_server_send_core_capability_request(RdpdrServerContext* context
Stream_SealLength(s);
status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_Length(s), NULL);
status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_Length(s), &written);
Stream_Free(s, TRUE);
@ -376,6 +378,7 @@ static int rdpdr_server_send_client_id_confirm(RdpdrServerContext* context)
wStream* s;
BOOL status;
RDPDR_HEADER header;
ULONG written;
printf("RdpdrServerSendClientIdConfirm\n");
@ -393,7 +396,7 @@ static int rdpdr_server_send_client_id_confirm(RdpdrServerContext* context)
Stream_SealLength(s);
status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_Length(s), NULL);
status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_Length(s), &written);
Stream_Free(s, TRUE);
@ -457,6 +460,7 @@ static int rdpdr_server_send_user_logged_on(RdpdrServerContext* context)
wStream* s;
BOOL status;
RDPDR_HEADER header;
ULONG written;
printf("%s\n", __FUNCTION__);
@ -470,7 +474,7 @@ static int rdpdr_server_send_user_logged_on(RdpdrServerContext* context)
Stream_SealLength(s);
status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_Length(s), NULL);
status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_Length(s), &written);
Stream_Free(s, TRUE);

View File

@ -434,17 +434,12 @@ int rdpei_recv_pdu(RDPEI_CHANNEL_CALLBACK* callback, wStream* s)
return 0;
}
static int rdpei_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, UINT32 cbSize, BYTE* pBuffer)
static int rdpei_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, wStream *data)
{
wStream* s;
int status = 0;
RDPEI_CHANNEL_CALLBACK* callback = (RDPEI_CHANNEL_CALLBACK*) pChannelCallback;
s = Stream_New(pBuffer, cbSize);
status = rdpei_recv_pdu(callback, s);
Stream_Free(s, FALSE);
status = rdpei_recv_pdu(callback, data);
return status;
}

View File

@ -20,6 +20,8 @@ define_channel_client("rdpgfx")
set(${MODULE_PREFIX}_SRCS
rdpgfx_main.c
rdpgfx_main.h
rdpgfx_codec.c
rdpgfx_codec.h
rdpgfx_common.c
rdpgfx_common.h)
@ -32,7 +34,7 @@ set_target_properties(${MODULE_NAME} PROPERTIES PREFIX "")
set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
MONOLITHIC ${MONOLITHIC_BUILD}
MODULE freerdp
MODULES freerdp-common freerdp-utils)
MODULES freerdp-common freerdp-codec freerdp-utils)
set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
MONOLITHIC ${MONOLITHIC_BUILD}

View File

@ -0,0 +1,111 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* Graphics Pipeline Extension
*
* Copyright 2014 Marc-Andre Moreau <marcandre.moreau@gmail.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.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <winpr/crt.h>
#include <winpr/stream.h>
#include "rdpgfx_codec.h"
int rdpgfx_decode_uncompressed(RDPGFX_PLUGIN* gfx, RDPGFX_SURFACE_COMMAND* cmd)
{
return 1;
}
int rdpgfx_decode_remotefx(RDPGFX_PLUGIN* gfx, RDPGFX_SURFACE_COMMAND* cmd)
{
fprintf(stderr, "RdpGfxDecodeRemoteFx\n");
return 1;
}
int rdpgfx_decode_clear(RDPGFX_PLUGIN* gfx, RDPGFX_SURFACE_COMMAND* cmd)
{
return 1;
}
int rdpgfx_decode_planar(RDPGFX_PLUGIN* gfx, RDPGFX_SURFACE_COMMAND* cmd)
{
return 1;
}
int rdpgfx_decode_h264(RDPGFX_PLUGIN* gfx, RDPGFX_SURFACE_COMMAND* cmd)
{
return 1;
}
int rdpgfx_decode_alpha(RDPGFX_PLUGIN* gfx, RDPGFX_SURFACE_COMMAND* cmd)
{
return 1;
}
int rdpgfx_decode_progressive(RDPGFX_PLUGIN* gfx, RDPGFX_SURFACE_COMMAND* cmd)
{
return 1;
}
int rdpgfx_decode_progressive_v2(RDPGFX_PLUGIN* gfx, RDPGFX_SURFACE_COMMAND* cmd)
{
return 1;
}
int rdpgfx_decode(RDPGFX_PLUGIN* gfx, RDPGFX_SURFACE_COMMAND* cmd)
{
int status;
switch (cmd->codecId)
{
case RDPGFX_CODECID_UNCOMPRESSED:
status = rdpgfx_decode_uncompressed(gfx, cmd);
break;
case RDPGFX_CODECID_CAVIDEO:
status = rdpgfx_decode_remotefx(gfx, cmd);
break;
case RDPGFX_CODECID_CLEARCODEC:
status = rdpgfx_decode_clear(gfx, cmd);
break;
case RDPGFX_CODECID_PLANAR:
status = rdpgfx_decode_planar(gfx, cmd);
break;
case RDPGFX_CODECID_H264:
status = rdpgfx_decode_h264(gfx, cmd);
break;
case RDPGFX_CODECID_ALPHA:
status = rdpgfx_decode_alpha(gfx, cmd);
break;
case RDPGFX_CODECID_CAPROGRESSIVE:
status = rdpgfx_decode_progressive(gfx, cmd);
break;
case RDPGFX_CODECID_CAPROGRESSIVE_V2:
status = rdpgfx_decode_progressive_v2(gfx, cmd);
break;
}
return 1;
}

View File

@ -1,9 +1,8 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* Sample Virtual Channel
* Graphics Pipeline Extension
*
* Copyright 2012 Jay Sorg
* Copyright 2010-2012 Vic Lee
* Copyright 2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -18,9 +17,16 @@
* limitations under the License.
*/
#ifndef __SAMPLE_MAIN_H
#define __SAMPLE_MAIN_H
#ifndef FREERDP_CHANNEL_RDPGFX_CLIENT_CODEC_H
#define FREERDP_CHANNEL_RDPGFX_CLIENT_CODEC_H
typedef struct sample_plugin samplePlugin;
#include <winpr/crt.h>
#include <winpr/stream.h>
#endif /* __SAMPLE_MAIN_H */
#include <freerdp/channels/rdpgfx.h>
#include "rdpgfx_main.h"
int rdpgfx_decode(RDPGFX_PLUGIN* gfx, RDPGFX_SURFACE_COMMAND* cmd);
#endif /* FREERDP_CHANNEL_RDPGFX_CLIENT_CODEC_H */

View File

@ -26,12 +26,89 @@
#include "rdpgfx_common.h"
int rdpgfx_read_point16(wStream* s, RDPGFX_POINT16* point16)
const char* RDPGFX_CMDID_STRINGS[] =
{
Stream_Read_UINT16(s, point16->x); /* x (2 bytes) */
Stream_Read_UINT16(s, point16->y); /* y (2 bytes) */
"RDPGFX_CMDID_UNUSED_0000",
"RDPGFX_CMDID_WIRETOSURFACE_1",
"RDPGFX_CMDID_WIRETOSURFACE_2",
"RDPGFX_CMDID_DELETEENCODINGCONTEXT",
"RDPGFX_CMDID_SOLIDFILL",
"RDPGFX_CMDID_SURFACETOSURFACE",
"RDPGFX_CMDID_SURFACETOCACHE",
"RDPGFX_CMDID_CACHETOSURFACE",
"RDPGFX_CMDID_EVICTCACHEENTRY",
"RDPGFX_CMDID_CREATESURFACE",
"RDPGFX_CMDID_DELETESURFACE",
"RDPGFX_CMDID_STARTFRAME",
"RDPGFX_CMDID_ENDFRAME",
"RDPGFX_CMDID_FRAMEACKNOWLEDGE",
"RDPGFX_CMDID_RESETGRAPHICS",
"RDPGFX_CMDID_MAPSURFACETOOUTPUT",
"RDPGFX_CMDID_CACHEIMPORTOFFER",
"RDPGFX_CMDID_CACHEIMPORTREPLY",
"RDPGFX_CMDID_CAPSADVERTISE",
"RDPGFX_CMDID_CAPSCONFIRM",
"RDPGFX_CMDID_UNUSED_0014",
"RDPGFX_CMDID_MAPSURFACETOWINDOW"
};
return 0;
const char* rdpgfx_get_cmd_id_string(UINT16 cmdId)
{
if (cmdId <= RDPGFX_CMDID_MAPSURFACETOWINDOW)
return RDPGFX_CMDID_STRINGS[cmdId];
else
return "RDPGFX_CMDID_UNKNOWN";
}
const char* rdpgfx_get_codec_id_string(UINT16 codecId)
{
switch (codecId)
{
case RDPGFX_CODECID_UNCOMPRESSED:
return "RDPGFX_CODECID_UNCOMPRESSED";
case RDPGFX_CODECID_CAVIDEO:
return "RDPGFX_CODECID_CAVIDEO";
case RDPGFX_CODECID_CLEARCODEC:
return "RDPGFX_CODECID_CLEARCODEC";
case RDPGFX_CODECID_PLANAR:
return "RDPGFX_CODECID_PLANAR";
case RDPGFX_CODECID_H264:
return "RDPGFX_CODECID_H264";
case RDPGFX_CODECID_ALPHA:
return "RDPGFX_CODECID_ALPHA";
case RDPGFX_CODECID_CAPROGRESSIVE:
return "RDPGFX_CODECID_CAPROGRESSIVE";
case RDPGFX_CODECID_CAPROGRESSIVE_V2:
return "RDPGFX_CODECID_CAPROGRESSIVE_V2";
}
return "RDPGFX_CODECID_UNKNOWN";
}
int rdpgfx_read_header(wStream* s, RDPGFX_HEADER* header)
{
Stream_Read_UINT16(s, header->cmdId); /* cmdId (2 bytes) */
Stream_Read_UINT16(s, header->flags); /* flags (2 bytes) */
Stream_Read_UINT32(s, header->pduLength); /* pduLength (4 bytes) */
return 1;
}
int rdpgfx_write_header(wStream* s, RDPGFX_HEADER* header)
{
Stream_Write_UINT16(s, header->cmdId); /* cmdId (2 bytes) */
Stream_Write_UINT16(s, header->flags); /* flags (2 bytes) */
Stream_Write_UINT32(s, header->pduLength); /* pduLength (4 bytes) */
return 1;
}
int rdpgfx_read_point16(wStream* s, RDPGFX_POINT16* pt16)
{
Stream_Read_UINT16(s, pt16->x); /* x (2 bytes) */
Stream_Read_UINT16(s, pt16->y); /* y (2 bytes) */
return 1;
}
int rdpgfx_write_point16(wStream* s, RDPGFX_POINT16* point16)
@ -39,7 +116,7 @@ int rdpgfx_write_point16(wStream* s, RDPGFX_POINT16* point16)
Stream_Write_UINT16(s, point16->x); /* x (2 bytes) */
Stream_Write_UINT16(s, point16->y); /* y (2 bytes) */
return 0;
return 1;
}
int rdpgfx_read_rect16(wStream* s, RDPGFX_RECT16* rect16)
@ -49,7 +126,7 @@ int rdpgfx_read_rect16(wStream* s, RDPGFX_RECT16* rect16)
Stream_Read_UINT16(s, rect16->right); /* right (2 bytes) */
Stream_Read_UINT16(s, rect16->bottom); /* bottom (2 bytes) */
return 0;
return 1;
}
int rdpgfx_write_rect16(wStream* s, RDPGFX_RECT16* rect16)
@ -59,7 +136,7 @@ int rdpgfx_write_rect16(wStream* s, RDPGFX_RECT16* rect16)
Stream_Write_UINT16(s, rect16->right); /* right (2 bytes) */
Stream_Write_UINT16(s, rect16->bottom); /* bottom (2 bytes) */
return 0;
return 1;
}
int rdpgfx_read_color32(wStream* s, RDPGFX_COLOR32* color32)
@ -69,7 +146,7 @@ int rdpgfx_read_color32(wStream* s, RDPGFX_COLOR32* color32)
Stream_Read_UINT8(s, color32->R); /* R (1 byte) */
Stream_Read_UINT8(s, color32->XA); /* XA (1 byte) */
return 0;
return 1;
}
int rdpgfx_write_color32(wStream* s, RDPGFX_COLOR32* color32)
@ -79,23 +156,5 @@ int rdpgfx_write_color32(wStream* s, RDPGFX_COLOR32* color32)
Stream_Write_UINT8(s, color32->R); /* R (1 byte) */
Stream_Write_UINT8(s, color32->XA); /* XA (1 byte) */
return 0;
}
int rdpgfx_read_header(wStream* s, RDPGFX_HEADER* header)
{
Stream_Read_UINT16(s, header->cmdId); /* cmdId (2 bytes) */
Stream_Read_UINT16(s, header->flags); /* flags (2 bytes) */
Stream_Read_UINT16(s, header->pduLength); /* pduLength (4 bytes) */
return 0;
}
int rdpgfx_write_header(wStream* s, RDPGFX_HEADER* header)
{
Stream_Write_UINT16(s, header->cmdId); /* cmdId (2 bytes) */
Stream_Write_UINT16(s, header->flags); /* flags (2 bytes) */
Stream_Write_UINT16(s, header->pduLength); /* pduLength (4 bytes) */
return 0;
return 1;
}

View File

@ -25,14 +25,20 @@
#include <freerdp/channels/rdpgfx.h>
int rdpgfx_read_point16(wStream* s, RDPGFX_POINT16* point16);
int rdpgfx_write_point16(wStream* s, RDPGFX_POINT16* point16);
int rdpgfx_read_rect16(wStream* s, RDPGFX_RECT16* rect16);
int rdpgfx_write_rect16(wStream* s, RDPGFX_RECT16* rect16);
int rdpgfx_read_color32(wStream* s, RDPGFX_COLOR32* color32);
int rdpgfx_write_color32(wStream* s, RDPGFX_COLOR32* color32);
const char* rdpgfx_get_cmd_id_string(UINT16 cmdId);
const char* rdpgfx_get_codec_id_string(UINT16 codecId);
int rdpgfx_read_header(wStream* s, RDPGFX_HEADER* header);
int rdpgfx_write_header(wStream* s, RDPGFX_HEADER* header);
int rdpgfx_read_point16(wStream* s, RDPGFX_POINT16* pt16);
int rdpgfx_write_point16(wStream* s, RDPGFX_POINT16* point16);
int rdpgfx_read_rect16(wStream* s, RDPGFX_RECT16* rect16);
int rdpgfx_write_rect16(wStream* s, RDPGFX_RECT16* rect16);
int rdpgfx_read_color32(wStream* s, RDPGFX_COLOR32* color32);
int rdpgfx_write_color32(wStream* s, RDPGFX_COLOR32* color32);
#endif /* FREERDP_CHANNEL_RDPGFX_CLIENT_COMMON_H */

File diff suppressed because it is too large Load Diff

View File

@ -2,7 +2,7 @@
* FreeRDP: A Remote Desktop Protocol Implementation
* Graphics Pipeline Extension
*
* Copyright 2013 Marc-Andre Moreau <marcandre.moreau@gmail.com>
* Copyright 2013-2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -20,17 +20,60 @@
#ifndef FREERDP_CHANNEL_RDPGFX_CLIENT_MAIN_H
#define FREERDP_CHANNEL_RDPGFX_CLIENT_MAIN_H
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <freerdp/dvc.h>
#include <freerdp/types.h>
#include <freerdp/addin.h>
#include <winpr/wlog.h>
#include <winpr/collections.h>
#include <freerdp/client/rdpgfx.h>
#include <freerdp/codec/zgfx.h>
struct _RDPGFX_CHANNEL_CALLBACK
{
IWTSVirtualChannelCallback iface;
IWTSPlugin* plugin;
IWTSVirtualChannelManager* channel_mgr;
IWTSVirtualChannel* channel;
};
typedef struct _RDPGFX_CHANNEL_CALLBACK RDPGFX_CHANNEL_CALLBACK;
struct _RDPGFX_LISTENER_CALLBACK
{
IWTSListenerCallback iface;
IWTSPlugin* plugin;
IWTSVirtualChannelManager* channel_mgr;
RDPGFX_CHANNEL_CALLBACK* channel_callback;
};
typedef struct _RDPGFX_LISTENER_CALLBACK RDPGFX_LISTENER_CALLBACK;
struct _RDPGFX_PLUGIN
{
IWTSPlugin iface;
IWTSListener* listener;
RDPGFX_LISTENER_CALLBACK* listener_callback;
wLog* log;
BOOL ThinClient;
BOOL SmallCache;
BOOL H264;
ZGFX_CONTEXT* zgfx;
UINT32 UnacknowledgedFrames;
UINT32 TotalDecodedFrames;
wHashTable* SurfaceTable;
UINT16 MaxCacheSlot;
void* CacheSlots[25600];
};
typedef struct _RDPGFX_PLUGIN RDPGFX_PLUGIN;
#endif /* FREERDP_CHANNEL_RDPGFX_CLIENT_MAIN_H */

View File

@ -20,12 +20,11 @@
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <winpr/wtypes.h>
#include <freerdp/types.h>
#include <freerdp/codec/dsp.h>
#include <freerdp/utils/svc_plugin.h>
#import <AudioToolbox/AudioToolbox.h>
@ -37,66 +36,66 @@
typedef struct rdpsnd_ios_plugin
{
rdpsndDevicePlugin device;
AudioComponentInstance audio_unit;
TPCircularBuffer buffer;
BOOL is_opened;
BOOL is_playing;
rdpsndDevicePlugin device;
AudioComponentInstance audio_unit;
TPCircularBuffer buffer;
BOOL is_opened;
BOOL is_playing;
} rdpsndIOSPlugin;
#define THIS(__ptr) ((rdpsndIOSPlugin*)__ptr)
static OSStatus rdpsnd_ios_render_cb(
void *inRefCon,
AudioUnitRenderActionFlags __unused *ioActionFlags,
const AudioTimeStamp __unused *inTimeStamp,
UInt32 inBusNumber,
UInt32 __unused inNumberFrames,
AudioBufferList *ioData
void *inRefCon,
AudioUnitRenderActionFlags __unused *ioActionFlags,
const AudioTimeStamp __unused *inTimeStamp,
UInt32 inBusNumber,
UInt32 __unused inNumberFrames,
AudioBufferList *ioData
)
{
unsigned int i;
if (inBusNumber != 0)
{
return noErr;
}
rdpsndIOSPlugin *p = THIS(inRefCon);
for (i = 0; i < ioData->mNumberBuffers; i++)
{
AudioBuffer* target_buffer = &ioData->mBuffers[i];
int32_t available_bytes = 0;
const void *buffer = TPCircularBufferTail(&p->buffer, &available_bytes);
if (buffer != NULL && available_bytes > 0)
{
const int bytes_to_copy = MIN((int32_t)target_buffer->mDataByteSize, available_bytes);
memcpy(target_buffer->mData, buffer, bytes_to_copy);
target_buffer->mDataByteSize = bytes_to_copy;
TPCircularBufferConsume(&p->buffer, bytes_to_copy);
}
else
{
target_buffer->mDataByteSize = 0;
AudioOutputUnitStop(p->audio_unit);
p->is_playing = 0;
}
}
return noErr;
unsigned int i;
if (inBusNumber != 0)
{
return noErr;
}
rdpsndIOSPlugin *p = THIS(inRefCon);
for (i = 0; i < ioData->mNumberBuffers; i++)
{
AudioBuffer* target_buffer = &ioData->mBuffers[i];
int32_t available_bytes = 0;
const void *buffer = TPCircularBufferTail(&p->buffer, &available_bytes);
if (buffer != NULL && available_bytes > 0)
{
const int bytes_to_copy = MIN((int32_t)target_buffer->mDataByteSize, available_bytes);
memcpy(target_buffer->mData, buffer, bytes_to_copy);
target_buffer->mDataByteSize = bytes_to_copy;
TPCircularBufferConsume(&p->buffer, bytes_to_copy);
}
else
{
target_buffer->mDataByteSize = 0;
AudioOutputUnitStop(p->audio_unit);
p->is_playing = 0;
}
}
return noErr;
}
static BOOL rdpsnd_ios_format_supported(rdpsndDevicePlugin* __unused device, AUDIO_FORMAT* format)
{
if (format->wFormatTag == WAVE_FORMAT_PCM)
{
return 1;
}
return 0;
if (format->wFormatTag == WAVE_FORMAT_PCM)
{
return 1;
}
return 0;
}
static void rdpsnd_ios_set_format(rdpsndDevicePlugin* __unused device, AUDIO_FORMAT* __unused format, int __unused latency)
@ -109,170 +108,170 @@ static void rdpsnd_ios_set_volume(rdpsndDevicePlugin* __unused device, UINT32 __
static void rdpsnd_ios_start(rdpsndDevicePlugin* device)
{
rdpsndIOSPlugin *p = THIS(device);
rdpsndIOSPlugin *p = THIS(device);
/* If this device is not playing... */
if (!p->is_playing)
{
/* Start the device. */
int32_t available_bytes = 0;
TPCircularBufferTail(&p->buffer, &available_bytes);
if (available_bytes > 0)
{
p->is_playing = 1;
AudioOutputUnitStart(p->audio_unit);
}
}
/* If this device is not playing... */
if (!p->is_playing)
{
/* Start the device. */
int32_t available_bytes = 0;
TPCircularBufferTail(&p->buffer, &available_bytes);
if (available_bytes > 0)
{
p->is_playing = 1;
AudioOutputUnitStart(p->audio_unit);
}
}
}
static void rdpsnd_ios_stop(rdpsndDevicePlugin* __unused device)
{
rdpsndIOSPlugin *p = THIS(device);
rdpsndIOSPlugin *p = THIS(device);
/* If the device is playing... */
if (p->is_playing)
{
/* Stop the device. */
AudioOutputUnitStop(p->audio_unit);
p->is_playing = 0;
/* If the device is playing... */
if (p->is_playing)
{
/* Stop the device. */
AudioOutputUnitStop(p->audio_unit);
p->is_playing = 0;
/* Free all buffers. */
TPCircularBufferClear(&p->buffer);
}
/* Free all buffers. */
TPCircularBufferClear(&p->buffer);
}
}
static void rdpsnd_ios_play(rdpsndDevicePlugin* device, BYTE* data, int size)
{
rdpsndIOSPlugin *p = THIS(device);
const BOOL ok = TPCircularBufferProduceBytes(&p->buffer, data, size);
if (!ok)
{
return;
}
rdpsnd_ios_start(device);
rdpsndIOSPlugin *p = THIS(device);
const BOOL ok = TPCircularBufferProduceBytes(&p->buffer, data, size);
if (!ok)
{
return;
}
rdpsnd_ios_start(device);
}
static void rdpsnd_ios_open(rdpsndDevicePlugin* device, AUDIO_FORMAT* format, int __unused latency)
{
rdpsndIOSPlugin *p = THIS(device);
if (p->is_opened)
{
return;
}
rdpsndIOSPlugin *p = THIS(device);
/* Find the output audio unit. */
AudioComponentDescription desc;
desc.componentManufacturer = kAudioUnitManufacturer_Apple;
desc.componentType = kAudioUnitType_Output;
desc.componentSubType = kAudioUnitSubType_RemoteIO;
desc.componentFlags = 0;
desc.componentFlagsMask = 0;
AudioComponent audioComponent = AudioComponentFindNext(NULL, &desc);
if (audioComponent == NULL) return;
if (p->is_opened)
{
return;
}
/* Open the audio unit. */
OSStatus status = AudioComponentInstanceNew(audioComponent, &p->audio_unit);
if (status != 0) return;
/* Find the output audio unit. */
AudioComponentDescription desc;
desc.componentManufacturer = kAudioUnitManufacturer_Apple;
desc.componentType = kAudioUnitType_Output;
desc.componentSubType = kAudioUnitSubType_RemoteIO;
desc.componentFlags = 0;
desc.componentFlagsMask = 0;
/* Set the format for the AudioUnit. */
AudioStreamBasicDescription audioFormat = {0};
audioFormat.mSampleRate = format->nSamplesPerSec;
audioFormat.mFormatID = kAudioFormatLinearPCM;
audioFormat.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;
audioFormat.mFramesPerPacket = 1; /* imminent property of the Linear PCM */
audioFormat.mChannelsPerFrame = format->nChannels;
audioFormat.mBitsPerChannel = format->wBitsPerSample;
audioFormat.mBytesPerFrame = (format->wBitsPerSample * format->nChannels) / 8;
audioFormat.mBytesPerPacket = audioFormat.mBytesPerFrame * audioFormat.mFramesPerPacket;
status = AudioUnitSetProperty(
p->audio_unit,
kAudioUnitProperty_StreamFormat,
kAudioUnitScope_Input,
0,
&audioFormat,
sizeof(audioFormat));
if (status != 0)
{
AudioComponentInstanceDispose(p->audio_unit);
p->audio_unit = NULL;
return;
}
/* Set up the AudioUnit callback. */
AURenderCallbackStruct callbackStruct = {0};
callbackStruct.inputProc = rdpsnd_ios_render_cb;
callbackStruct.inputProcRefCon = p;
status = AudioUnitSetProperty(
p->audio_unit,
kAudioUnitProperty_SetRenderCallback,
kAudioUnitScope_Input,
0,
&callbackStruct,
sizeof(callbackStruct));
if (status != 0)
{
AudioComponentInstanceDispose(p->audio_unit);
p->audio_unit = NULL;
return;
}
AudioComponent audioComponent = AudioComponentFindNext(NULL, &desc);
if (audioComponent == NULL) return;
/* Initialize the AudioUnit. */
status = AudioUnitInitialize(p->audio_unit);
if (status != 0)
{
AudioComponentInstanceDispose(p->audio_unit);
p->audio_unit = NULL;
return;
}
/* Allocate the circular buffer. */
const BOOL ok = TPCircularBufferInit(&p->buffer, CIRCULAR_BUFFER_SIZE);
if (!ok)
{
AudioUnitUninitialize(p->audio_unit);
AudioComponentInstanceDispose(p->audio_unit);
p->audio_unit = NULL;
return;
}
/* Open the audio unit. */
OSStatus status = AudioComponentInstanceNew(audioComponent, &p->audio_unit);
if (status != 0) return;
p->is_opened = 1;
/* Set the format for the AudioUnit. */
AudioStreamBasicDescription audioFormat = {0};
audioFormat.mSampleRate = format->nSamplesPerSec;
audioFormat.mFormatID = kAudioFormatLinearPCM;
audioFormat.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;
audioFormat.mFramesPerPacket = 1; /* imminent property of the Linear PCM */
audioFormat.mChannelsPerFrame = format->nChannels;
audioFormat.mBitsPerChannel = format->wBitsPerSample;
audioFormat.mBytesPerFrame = (format->wBitsPerSample * format->nChannels) / 8;
audioFormat.mBytesPerPacket = audioFormat.mBytesPerFrame * audioFormat.mFramesPerPacket;
status = AudioUnitSetProperty(
p->audio_unit,
kAudioUnitProperty_StreamFormat,
kAudioUnitScope_Input,
0,
&audioFormat,
sizeof(audioFormat));
if (status != 0)
{
AudioComponentInstanceDispose(p->audio_unit);
p->audio_unit = NULL;
return;
}
/* Set up the AudioUnit callback. */
AURenderCallbackStruct callbackStruct = {0};
callbackStruct.inputProc = rdpsnd_ios_render_cb;
callbackStruct.inputProcRefCon = p;
status = AudioUnitSetProperty(
p->audio_unit,
kAudioUnitProperty_SetRenderCallback,
kAudioUnitScope_Input,
0,
&callbackStruct,
sizeof(callbackStruct));
if (status != 0)
{
AudioComponentInstanceDispose(p->audio_unit);
p->audio_unit = NULL;
return;
}
/* Initialize the AudioUnit. */
status = AudioUnitInitialize(p->audio_unit);
if (status != 0)
{
AudioComponentInstanceDispose(p->audio_unit);
p->audio_unit = NULL;
return;
}
/* Allocate the circular buffer. */
const BOOL ok = TPCircularBufferInit(&p->buffer, CIRCULAR_BUFFER_SIZE);
if (!ok)
{
AudioUnitUninitialize(p->audio_unit);
AudioComponentInstanceDispose(p->audio_unit);
p->audio_unit = NULL;
return;
}
p->is_opened = 1;
}
static void rdpsnd_ios_close(rdpsndDevicePlugin* device)
{
rdpsndIOSPlugin *p = THIS(device);
rdpsndIOSPlugin *p = THIS(device);
/* Make sure the device is stopped. */
rdpsnd_ios_stop(device);
/* Make sure the device is stopped. */
rdpsnd_ios_stop(device);
/* If the device is open... */
if (p->is_opened)
{
/* Close the device. */
AudioUnitUninitialize(p->audio_unit);
AudioComponentInstanceDispose(p->audio_unit);
p->audio_unit = NULL;
p->is_opened = 0;
/* Destroy the circular buffer. */
TPCircularBufferCleanup(&p->buffer);
}
/* If the device is open... */
if (p->is_opened)
{
/* Close the device. */
AudioUnitUninitialize(p->audio_unit);
AudioComponentInstanceDispose(p->audio_unit);
p->audio_unit = NULL;
p->is_opened = 0;
/* Destroy the circular buffer. */
TPCircularBufferCleanup(&p->buffer);
}
}
static void rdpsnd_ios_free(rdpsndDevicePlugin* device)
{
rdpsndIOSPlugin *p = THIS(device);
rdpsndIOSPlugin *p = THIS(device);
/* Ensure the device is closed. */
rdpsnd_ios_close(device);
/* Ensure the device is closed. */
rdpsnd_ios_close(device);
/* Free memory associated with the device. */
free(p);
/* Free memory associated with the device. */
free(p);
}
#ifdef STATIC_CHANNELS
@ -281,19 +280,21 @@ static void rdpsnd_ios_free(rdpsndDevicePlugin* device)
int freerdp_rdpsnd_client_subsystem_entry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pEntryPoints)
{
rdpsndIOSPlugin *p = (rdpsndIOSPlugin*)malloc(sizeof(rdpsndIOSPlugin));
memset(p, 0, sizeof(rdpsndIOSPlugin));
p->device.Open = rdpsnd_ios_open;
p->device.FormatSupported = rdpsnd_ios_format_supported;
p->device.SetFormat = rdpsnd_ios_set_format;
p->device.SetVolume = rdpsnd_ios_set_volume;
p->device.Play = rdpsnd_ios_play;
p->device.Start = rdpsnd_ios_start;
p->device.Close = rdpsnd_ios_close;
p->device.Free = rdpsnd_ios_free;
pEntryPoints->pRegisterRdpsndDevice(pEntryPoints->rdpsnd, (rdpsndDevicePlugin*)p);
return 0;
}
rdpsndIOSPlugin* p = (rdpsndIOSPlugin*) calloc(1, sizeof(rdpsndIOSPlugin));
if (!p)
return -1;
p->device.Open = rdpsnd_ios_open;
p->device.FormatSupported = rdpsnd_ios_format_supported;
p->device.SetFormat = rdpsnd_ios_set_format;
p->device.SetVolume = rdpsnd_ios_set_volume;
p->device.Play = rdpsnd_ios_play;
p->device.Start = rdpsnd_ios_start;
p->device.Close = rdpsnd_ios_close;
p->device.Free = rdpsnd_ios_free;
pEntryPoints->pRegisterRdpsndDevice(pEntryPoints->rdpsnd, (rdpsndDevicePlugin*)p);
return 0;
}

View File

@ -29,7 +29,6 @@
#include <freerdp/types.h>
#include <freerdp/codec/dsp.h>
#include <freerdp/utils/svc_plugin.h>
#include <AudioToolbox/AudioToolbox.h>
#include <AudioToolbox/AudioQueue.h>
@ -282,23 +281,21 @@ int freerdp_rdpsnd_client_subsystem_entry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pE
{
rdpsndMacPlugin* mac;
mac = (rdpsndMacPlugin*) malloc(sizeof(rdpsndMacPlugin));
mac = (rdpsndMacPlugin*) calloc(1, sizeof(rdpsndMacPlugin));
if (mac)
{
ZeroMemory(mac, sizeof(rdpsndMacPlugin));
if (!mac)
return -1;
mac->device.Open = rdpsnd_mac_open;
mac->device.FormatSupported = rdpsnd_mac_format_supported;
mac->device.SetFormat = rdpsnd_mac_set_format;
mac->device.SetVolume = rdpsnd_mac_set_volume;
mac->device.Play = rdpsnd_mac_play;
mac->device.Start = rdpsnd_mac_start;
mac->device.Close = rdpsnd_mac_close;
mac->device.Free = rdpsnd_mac_free;
mac->device.Open = rdpsnd_mac_open;
mac->device.FormatSupported = rdpsnd_mac_format_supported;
mac->device.SetFormat = rdpsnd_mac_set_format;
mac->device.SetVolume = rdpsnd_mac_set_volume;
mac->device.Play = rdpsnd_mac_play;
mac->device.Start = rdpsnd_mac_start;
mac->device.Close = rdpsnd_mac_close;
mac->device.Free = rdpsnd_mac_free;
pEntryPoints->pRegisterRdpsndDevice(pEntryPoints->rdpsnd, (rdpsndDevicePlugin*) mac);
}
pEntryPoints->pRegisterRdpsndDevice(pEntryPoints->rdpsnd, (rdpsndDevicePlugin*) mac);
return 0;
}

View File

@ -37,7 +37,6 @@
#include <freerdp/types.h>
#include <freerdp/codec/dsp.h>
#include <freerdp/utils/svc_plugin.h>
#include "rdpsnd_main.h"
@ -74,18 +73,15 @@ static void rdpsnd_pulse_context_state_callback(pa_context* context, void* userd
switch (state)
{
case PA_CONTEXT_READY:
DEBUG_SVC("PA_CONTEXT_READY");
pa_threaded_mainloop_signal(pulse->mainloop, 0);
break;
case PA_CONTEXT_FAILED:
case PA_CONTEXT_TERMINATED:
DEBUG_SVC("PA_CONTEXT_FAILED/PA_CONTEXT_TERMINATED %d", (int)state);
pa_threaded_mainloop_signal(pulse->mainloop, 0);
break;
default:
DEBUG_SVC("state %d", (int)state);
break;
}
}
@ -100,7 +96,6 @@ static BOOL rdpsnd_pulse_connect(rdpsndDevicePlugin* device)
if (pa_context_connect(pulse->context, NULL, 0, NULL))
{
DEBUG_WARN("pa_context_connect failed (%d)", pa_context_errno(pulse->context));
return FALSE;
}
@ -109,7 +104,6 @@ static BOOL rdpsnd_pulse_connect(rdpsndDevicePlugin* device)
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));
return FALSE;
}
@ -122,7 +116,6 @@ static BOOL rdpsnd_pulse_connect(rdpsndDevicePlugin* device)
if (!PA_CONTEXT_IS_GOOD(state))
{
DEBUG_WARN("bad context state (%d)", pa_context_errno(pulse->context));
break;
}
@ -133,7 +126,6 @@ static BOOL rdpsnd_pulse_connect(rdpsndDevicePlugin* device)
if (state == PA_CONTEXT_READY)
{
DEBUG_SVC("connected");
return TRUE;
}
else
@ -173,18 +165,15 @@ static void rdpsnd_pulse_stream_state_callback(pa_stream* stream, void* userdata
switch (state)
{
case PA_STREAM_READY:
DEBUG_SVC("PA_STREAM_READY");
pa_threaded_mainloop_signal(pulse->mainloop, 0);
break;
case PA_STREAM_FAILED:
case PA_STREAM_TERMINATED:
DEBUG_SVC("state %d", (int)state);
pa_threaded_mainloop_signal(pulse->mainloop, 0);
break;
default:
DEBUG_SVC("state %d", (int)state);
break;
}
}
@ -270,7 +259,6 @@ static void rdpsnd_pulse_open(rdpsndDevicePlugin* device, AUDIO_FORMAT* format,
if (!pulse->context || pulse->stream)
{
DEBUG_WARN("pulse stream has been created.");
return;
}
@ -280,7 +268,6 @@ static void rdpsnd_pulse_open(rdpsndDevicePlugin* device, AUDIO_FORMAT* format,
if (pa_sample_spec_valid(&pulse->sample_spec) == 0)
{
pa_sample_spec_snprint(ss, sizeof(ss), &pulse->sample_spec);
DEBUG_WARN("Invalid sample spec %s", ss);
return;
}
@ -291,7 +278,6 @@ static void rdpsnd_pulse_open(rdpsndDevicePlugin* device, AUDIO_FORMAT* format,
if (!pulse->stream)
{
pa_threaded_mainloop_unlock(pulse->mainloop);
DEBUG_WARN("pa_stream_new failed (%d)", pa_context_errno(pulse->context));
return;
}
@ -315,8 +301,6 @@ static void rdpsnd_pulse_open(rdpsndDevicePlugin* device, AUDIO_FORMAT* format,
pulse->device_name, pulse->latency > 0 ? &buffer_attr : NULL, flags, NULL, NULL) < 0)
{
pa_threaded_mainloop_unlock(pulse->mainloop);
DEBUG_WARN("pa_stream_connect_playback failed (%d)",
pa_context_errno(pulse->context));
return;
}
@ -329,8 +313,6 @@ static void rdpsnd_pulse_open(rdpsndDevicePlugin* device, AUDIO_FORMAT* format,
if (!PA_STREAM_IS_GOOD(state))
{
DEBUG_WARN("bad stream state (%d)",
pa_context_errno(pulse->context));
break;
}
@ -349,8 +331,6 @@ static void rdpsnd_pulse_open(rdpsndDevicePlugin* device, AUDIO_FORMAT* format,
pulse->gsm_context = gsm_create();
#endif
DEBUG_SVC("connected");
}
else
{
@ -584,8 +564,6 @@ static void rdpsnd_pulse_play(rdpsndDevicePlugin* device, BYTE* data, int size)
if (status < 0)
{
DEBUG_WARN("pa_stream_write failed (%d)",
pa_context_errno(pulse->context));
break;
}
@ -653,8 +631,10 @@ int freerdp_rdpsnd_client_subsystem_entry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pE
ADDIN_ARGV* args;
rdpsndPulsePlugin* pulse;
pulse = (rdpsndPulsePlugin*) malloc(sizeof(rdpsndPulsePlugin));
ZeroMemory(pulse, sizeof(rdpsndPulsePlugin));
pulse = (rdpsndPulsePlugin*) calloc(1, sizeof(rdpsndPulsePlugin));
if (!pulse)
return -1;
pulse->device.Open = rdpsnd_pulse_open;
pulse->device.FormatSupported = rdpsnd_pulse_format_supported;
@ -678,7 +658,6 @@ int freerdp_rdpsnd_client_subsystem_entry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pE
if (!pulse->mainloop)
{
DEBUG_WARN("pa_threaded_mainloop_new failed");
rdpsnd_pulse_free((rdpsndDevicePlugin*)pulse);
return 1;
}
@ -687,7 +666,6 @@ int freerdp_rdpsnd_client_subsystem_entry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pE
if (!pulse->context)
{
DEBUG_WARN("pa_context_new failed");
rdpsnd_pulse_free((rdpsndDevicePlugin*)pulse);
return 1;
}
@ -696,7 +674,6 @@ int freerdp_rdpsnd_client_subsystem_entry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pE
if (!rdpsnd_pulse_connect((rdpsndDevicePlugin*)pulse))
{
DEBUG_WARN("rdpsnd_pulse_connect failed");
rdpsnd_pulse_free((rdpsndDevicePlugin*)pulse);
return 1;
}

View File

@ -34,7 +34,6 @@
#include <freerdp/types.h>
#include <freerdp/codec/dsp.h>
#include <freerdp/utils/svc_plugin.h>
#include "rdpsnd_main.h"
@ -333,8 +332,10 @@ int freerdp_rdpsnd_client_subsystem_entry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pE
ADDIN_ARGV* args;
rdpsndWinmmPlugin* winmm;
winmm = (rdpsndWinmmPlugin*) malloc(sizeof(rdpsndWinmmPlugin));
ZeroMemory(winmm, sizeof(rdpsndWinmmPlugin));
winmm = (rdpsndWinmmPlugin*) calloc(1, sizeof(rdpsndWinmmPlugin));
if (!winmm)
return -1;
winmm->device.DisableConfirmThread = TRUE;

View File

@ -36,6 +36,7 @@ static BOOL rdpsnd_server_send_formats(RdpsndServerContext* context, wStream* s)
int pos;
UINT16 i;
BOOL status;
ULONG written;
Stream_Write_UINT8(s, SNDC_FORMATS);
Stream_Write_UINT8(s, 0);
@ -74,7 +75,7 @@ static BOOL rdpsnd_server_send_formats(RdpsndServerContext* context, wStream* s)
Stream_SetPosition(s, 2);
Stream_Write_UINT16(s, pos - 4);
Stream_SetPosition(s, pos);
status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), NULL);
status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), &written);
Stream_SetPosition(s, 0);
return status;
@ -82,8 +83,8 @@ static BOOL rdpsnd_server_send_formats(RdpsndServerContext* context, wStream* s)
static BOOL rdpsnd_server_recv_waveconfirm(RdpsndServerContext* context, wStream* s)
{
UINT16 timestamp = 0;
BYTE confirmBlockNum = 0;
UINT16 timestamp;
BYTE confirmBlockNum;
if (Stream_GetRemainingLength(s) < 4)
return FALSE;
@ -91,6 +92,9 @@ static BOOL rdpsnd_server_recv_waveconfirm(RdpsndServerContext* context, wStream
Stream_Read_UINT16(s, timestamp);
Stream_Read_UINT8(s, confirmBlockNum);
Stream_Seek_UINT8(s);
IFCALL(context->ConfirmBlock, context, confirmBlockNum, timestamp);
return TRUE;
}
@ -191,37 +195,41 @@ static void* rdpsnd_server_thread(void* arg)
UINT16 BodySize;
HANDLE events[8];
HANDLE ChannelEvent;
DWORD BytesReturned;
DWORD bytesReturned;
RdpsndServerContext* context;
BOOL doRun;
BOOL waitingHeader;
DWORD expectedBytes;
context = (RdpsndServerContext *)arg;
buffer = NULL;
BytesReturned = 0;
ChannelEvent = NULL;
bytesReturned = 0;
s = Stream_New(NULL, 4096);
if (!s)
return NULL;
if (WTSVirtualChannelQuery(context->priv->ChannelHandle, WTSVirtualEventHandle, &buffer, &BytesReturned))
if (!WTSVirtualChannelQuery(context->priv->ChannelHandle, WTSVirtualEventHandle, &buffer, &bytesReturned) || (bytesReturned != sizeof(HANDLE)))
{
if (BytesReturned == sizeof(HANDLE))
CopyMemory(&ChannelEvent, buffer, sizeof(HANDLE));
WTSFreeMemory(buffer);
fprintf(stderr, "%s: error during WTSVirtualChannelQuery(WTSVirtualEventHandle) or invalid returned size(%d)\n",
__FUNCTION__, bytesReturned);
return NULL;
}
CopyMemory(&ChannelEvent, buffer, sizeof(HANDLE));
WTSFreeMemory(buffer);
nCount = 0;
if (ChannelEvent)
events[nCount++] = ChannelEvent;
events[nCount++] = ChannelEvent;
events[nCount++] = context->priv->StopEvent;
if (!rdpsnd_server_send_formats(context, s))
goto out;
doRun = TRUE;
waitingHeader = TRUE;
expectedBytes = 4;
while (doRun)
{
status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE);
@ -229,31 +237,34 @@ static void* rdpsnd_server_thread(void* arg)
if (WaitForSingleObject(context->priv->StopEvent, 0) == WAIT_OBJECT_0)
break;
Stream_SetPosition(s, 0);
if (!WTSVirtualChannelRead(context->priv->ChannelHandle, 0, (PCHAR)Stream_Buffer(s),
Stream_Capacity(s), &BytesReturned))
if (!WTSVirtualChannelRead(ChannelEvent, 0, (PCHAR)Stream_Pointer(s), expectedBytes, &bytesReturned))
{
if (!BytesReturned)
break;
fprintf(stderr, "%s: channel connection closed\n", __FUNCTION__);
break;
}
expectedBytes -= bytesReturned;
Stream_Seek(s, bytesReturned);
Stream_EnsureRemainingCapacity(s, BytesReturned);
if (expectedBytes)
continue;
if (!WTSVirtualChannelRead(context->priv->ChannelHandle, 0, (PCHAR)Stream_Buffer(s),
Stream_Capacity(s), &BytesReturned))
break;
Stream_SetPosition(s, 0);
if (waitingHeader)
{
/* header case */
Stream_Read_UINT8(s, msgType);
Stream_Seek_UINT8(s); /* bPad */
Stream_Read_UINT16(s, BodySize);
expectedBytes = BodySize;
waitingHeader = FALSE;
Stream_SetPosition(s, 0);
Stream_EnsureCapacity(s, BodySize);
if (expectedBytes)
continue;
}
if (Stream_GetRemainingLength(s) < 4)
break;
Stream_Read_UINT8(s, msgType);
Stream_Seek_UINT8(s); /* bPad */
Stream_Read_UINT16(s, BodySize);
if (Stream_GetRemainingLength(s) < BodySize)
break;
/* when here we have the header + the body */
switch (msgType)
{
case SNDC_WAVECONFIRM:
@ -276,6 +287,10 @@ static void* rdpsnd_server_thread(void* arg)
fprintf(stderr, "%s: UNKOWN MESSAGE TYPE!! (%#0X)\n\n", __FUNCTION__, msgType);
break;
}
expectedBytes = 4;
waitingHeader = TRUE;
Stream_SetPosition(s, 0);
}
out:
@ -352,7 +367,7 @@ static BOOL rdpsnd_server_select_format(RdpsndServerContext* context, int client
return TRUE;
}
static BOOL rdpsnd_server_send_audio_pdu(RdpsndServerContext* context)
static BOOL rdpsnd_server_send_audio_pdu(RdpsndServerContext* context, UINT16 wTimestamp)
{
int size;
BYTE* src;
@ -361,6 +376,7 @@ static BOOL rdpsnd_server_send_audio_pdu(RdpsndServerContext* context)
BOOL status;
AUDIO_FORMAT* format;
int tbytes_per_frame;
ULONG written;
wStream* s = context->priv->rdpsnd_pdu;
format = &context->client_formats[context->selected_client_format];
@ -416,13 +432,13 @@ static BOOL rdpsnd_server_send_audio_pdu(RdpsndServerContext* context)
Stream_Write_UINT8(s, 0); /* bPad */
Stream_Write_UINT16(s, size + fill_size + 8); /* BodySize */
Stream_Write_UINT16(s, 0); /* wTimeStamp */
Stream_Write_UINT16(s, wTimestamp); /* wTimeStamp */
Stream_Write_UINT16(s, context->selected_client_format); /* wFormatNo */
Stream_Write_UINT8(s, context->block_no); /* cBlockNo */
Stream_Seek(s, 3); /* bPad */
Stream_Write(s, src, 4);
status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), NULL);
status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), &written);
if (!status)
goto out;
Stream_SetPosition(s, 0);
@ -435,7 +451,7 @@ static BOOL rdpsnd_server_send_audio_pdu(RdpsndServerContext* context)
if (fill_size > 0)
Stream_Zero(s, fill_size);
status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), NULL);
status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), &written);
out:
Stream_SetPosition(s, 0);
@ -443,7 +459,7 @@ out:
return status;
}
static BOOL rdpsnd_server_send_samples(RdpsndServerContext* context, const void* buf, int nframes)
static BOOL rdpsnd_server_send_samples(RdpsndServerContext* context, const void* buf, int nframes, UINT16 wTimestamp)
{
int cframes;
int cframesize;
@ -464,7 +480,7 @@ static BOOL rdpsnd_server_send_samples(RdpsndServerContext* context, const void*
if (context->priv->out_pending_frames >= context->priv->out_frames)
{
if (!rdpsnd_server_send_audio_pdu(context))
if (!rdpsnd_server_send_audio_pdu(context, wTimestamp))
return FALSE;
}
}
@ -476,6 +492,7 @@ static BOOL rdpsnd_server_set_volume(RdpsndServerContext* context, int left, int
{
int pos;
BOOL status;
ULONG written;
wStream* s = context->priv->rdpsnd_pdu;
Stream_Write_UINT8(s, SNDC_SETVOLUME);
@ -489,7 +506,7 @@ static BOOL rdpsnd_server_set_volume(RdpsndServerContext* context, int left, int
Stream_SetPosition(s, 2);
Stream_Write_UINT16(s, pos - 4);
Stream_SetPosition(s, pos);
status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), NULL);
status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), &written);
Stream_SetPosition(s, 0);
return status;
@ -499,6 +516,7 @@ static BOOL rdpsnd_server_close(RdpsndServerContext* context)
{
int pos;
BOOL status;
ULONG written;
wStream* s = context->priv->rdpsnd_pdu;
if (context->selected_client_format < 0)
@ -506,7 +524,7 @@ static BOOL rdpsnd_server_close(RdpsndServerContext* context)
if (context->priv->out_pending_frames > 0)
{
if (!rdpsnd_server_send_audio_pdu(context))
if (!rdpsnd_server_send_audio_pdu(context, 0))
return FALSE;
}
@ -520,7 +538,7 @@ static BOOL rdpsnd_server_close(RdpsndServerContext* context)
Stream_SetPosition(s, 2);
Stream_Write_UINT16(s, pos - 4);
Stream_SetPosition(s, pos);
status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), NULL);
status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), &written);
Stream_SetPosition(s, 0);
return status;

View File

@ -1,23 +0,0 @@
# FreeRDP: A Remote Desktop Protocol Implementation
# FreeRDP cmake build script
#
# Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.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.
define_channel("sample")
if(WITH_CLIENT_CHANNELS)
add_channel_client(${MODULE_PREFIX} ${CHANNEL_NAME})
endif()

View File

@ -1,16 +0,0 @@
set(OPTION_DEFAULT OFF)
if(WITH_SAMPLE)
set(OPTION_CLIENT_DEFAULT ON)
else()
set(OPTION_CLIENT_DEFAULT OFF)
endif()
set(OPTION_SERVER_DEFAULT OFF)
define_channel_options(NAME "sample" TYPE "static"
DESCRIPTION "Sample Virtual Channel Extension"
SPECIFICATIONS ""
DEFAULT ${OPTION_DEFAULT})
define_channel_client_options(${OPTION_CLIENT_DEFAULT})
define_channel_server_options(${OPTION_SERVER_DEFAULT})

View File

@ -1,35 +0,0 @@
# FreeRDP: A Remote Desktop Protocol Implementation
# FreeRDP cmake build script
#
# Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.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.
define_channel_client("sample")
set(${MODULE_PREFIX}_SRCS
sample_main.c
sample_main.h)
add_channel_client_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} FALSE "VirtualChannelEntry")
set_target_properties(${MODULE_NAME} PROPERTIES PREFIX "")
set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
MONOLITHIC ${MONOLITHIC_BUILD}
MODULE freerdp
MODULES freerdp-utils)
install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_ADDIN_PATH} EXPORT FreeRDPTargets)
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Channels/${CHANNEL_NAME}/Client")

View File

@ -1,11 +0,0 @@
This is a skeleton virtual channel plugin for freerdp
To create your own virtual channel plugin, copy this directory
then change all references of "skel" to your plugin name
remember, plugin name are 7 chars or less, no spaces or funny chars
server_chan_test.cpp is an example of how to open a channel to the client
this code needs to be compiled and run on the server in an rdp session
when connect with a client that has the "skel" plugin loaded
Jay

View File

@ -1,143 +0,0 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* Sample Virtual Channel
*
* Copyright 2009-2012 Jay Sorg
* Copyright 2010-2012 Vic Lee
*
* 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.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#ifndef _WIN32
#include <sys/time.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winpr/crt.h>
#include <winpr/stream.h>
#include <freerdp/types.h>
#include <freerdp/constants.h>
#include <freerdp/utils/svc_plugin.h>
#include "sample_main.h"
struct sample_plugin
{
rdpSvcPlugin plugin;
/* put your private data here */
};
static void sample_process_receive(rdpSvcPlugin* plugin, wStream* data_in)
{
int bytes;
wStream* data_out;
samplePlugin* sample = (samplePlugin*) plugin;
fprintf(stderr, "sample_process_receive:\n");
if (!sample)
{
fprintf(stderr, "sample_process_receive: sample is nil\n");
return;
}
/* process data in (from server) here */
/* here we just send the same data back */
bytes = Stream_Capacity(data_in);
fprintf(stderr, "sample_process_receive: got bytes %d\n", bytes);
if (bytes > 0)
{
data_out = Stream_New(NULL, bytes);
Stream_Copy(data_out, data_in, bytes);
/* svc_plugin_send takes ownership of data_out, that is why
we do not free it */
bytes = Stream_GetPosition(data_in);
fprintf(stderr, "sample_process_receive: sending bytes %d\n", bytes);
svc_plugin_send(plugin, data_out);
}
Stream_Free(data_in, TRUE);
}
static void sample_process_connect(rdpSvcPlugin* plugin)
{
samplePlugin* sample = (samplePlugin*) plugin;
DEBUG_SVC("connecting");
fprintf(stderr, "sample_process_connect:\n");
if (!sample)
return;
}
static void sample_process_event(rdpSvcPlugin* plugin, wMessage* event)
{
fprintf(stderr, "sample_process_event:\n");
/* events coming from main freerdp window to plugin */
/* send them back with svc_plugin_send_event */
freerdp_event_free(event);
}
static void sample_process_terminate(rdpSvcPlugin* plugin)
{
samplePlugin* sample = (samplePlugin*) plugin;
fprintf(stderr, "sample_process_terminate:\n");
if (!sample)
return;
/* put your cleanup here */
free(plugin);
}
#define VirtualChannelEntry sample_VirtualChannelEntry
int VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints)
{
samplePlugin* _p;
_p = (samplePlugin*) malloc(sizeof(samplePlugin));
ZeroMemory(_p, sizeof(samplePlugin));
_p->plugin.channel_def.options =
CHANNEL_OPTION_INITIALIZED |
CHANNEL_OPTION_ENCRYPT_RDP;
strcpy(_p->plugin.channel_def.name, "sample");
_p->plugin.connect_callback = sample_process_connect;
_p->plugin.receive_callback = sample_process_receive;
_p->plugin.event_callback = sample_process_event;
_p->plugin.terminate_callback = sample_process_terminate;
svc_plugin_init((rdpSvcPlugin*) _p, pEntryPoints);
return 1;
}

View File

@ -1,60 +0,0 @@
// xrdp_chan_test.cpp : Basic test for virtual channel use.
// These headers are required for the windows terminal service calls.
#include "windows.h"
#include "wtsapi32.h"
#include <string>
#define DSIZE 1024
int main()
{
// Initialize the data for send/receive
char* data;
char* data1;
data = (char*)malloc(DSIZE);
data1 = (char*)malloc(DSIZE);
memset(data, 0xca, DSIZE);
memset(data1, 0, DSIZE);
// Open the skel channel in current session
void* channel = WTSVirtualChannelOpenEx(WTS_CURRENT_SESSION, "skel", 0);
unsigned long written = 0;
// Write the data to the channel
bool ret = WTSVirtualChannelWrite(channel, data, DSIZE, &written);
if (!ret)
{
long err = GetLastError();
fprintf(stderr, "error 0x%8.8x\n", err);
return 1;
}
ret = WTSVirtualChannelRead(channel, 100, data1, DSIZE, &written);
if (!ret)
{
long err = GetLastError();
fprintf(stderr, "error 0x%8.8x\n", err);
return 1;
}
if (written != DSIZE)
{
fprintf(stderr, "error read %d\n", written);
return 1;
}
ret = WTSVirtualChannelClose(channel);
if (memcmp(data, data1, DSIZE) == 0)
{
}
else
{
fprintf(stderr, "error data no match\n");
return 1;
}
fprintf(stderr, "Success!\n");
Sleep(2000);
return 0;
}

View File

@ -53,7 +53,6 @@
#include <freerdp/freerdp.h>
#include <freerdp/channels/rdpdr.h>
#include <freerdp/utils/svc_plugin.h>
typedef struct _SERIAL_DEVICE SERIAL_DEVICE;
@ -100,13 +99,10 @@ static void serial_process_irp_create(SERIAL_DEVICE* serial, IRP* irp)
{
irp->IoStatus = STATUS_UNSUCCESSFUL;
FileId = 0;
DEBUG_WARN("failed to create %s", path);
}
else
{
serial->tty = tty;
DEBUG_SVC("%s(%d) created.", serial->path, FileId);
}
Stream_Write_UINT32(irp->output, FileId); /* FileId (4 bytes) */
@ -126,12 +122,9 @@ static void serial_process_irp_close(SERIAL_DEVICE* serial, IRP* irp)
if (!tty)
{
irp->IoStatus = STATUS_UNSUCCESSFUL;
DEBUG_WARN("tty not valid.");
}
else
{
DEBUG_SVC("%s(%d) closed.", serial->path, tty->id);
serial_tty_free(tty);
serial->tty = NULL;
}
@ -156,8 +149,6 @@ static void serial_process_irp_read(SERIAL_DEVICE* serial, IRP* irp)
{
irp->IoStatus = STATUS_UNSUCCESSFUL;
Length = 0;
DEBUG_WARN("tty not valid.");
}
else
{
@ -169,12 +160,10 @@ static void serial_process_irp_read(SERIAL_DEVICE* serial, IRP* irp)
free(buffer);
buffer = NULL;
Length = 0;
DEBUG_WARN("read %s(%d) failed.", serial->path, tty->id);
}
else
{
DEBUG_SVC("read %llu-%llu from %d", Offset, Offset + Length, tty->id);
}
}
@ -207,8 +196,6 @@ static void serial_process_irp_write(SERIAL_DEVICE* serial, IRP* irp)
irp->IoStatus = STATUS_UNSUCCESSFUL;
Length = 0;
DEBUG_WARN("tty not valid.");
Stream_Write_UINT32(irp->output, Length); /* Length (4 bytes) */
Stream_Write_UINT8(irp->output, 0); /* Padding (1 byte) */
irp->Complete(irp);
@ -252,8 +239,6 @@ static void serial_process_irp_device_control(SERIAL_DEVICE* serial, IRP* irp)
{
irp->IoStatus = STATUS_UNSUCCESSFUL;
OutputBufferLength = 0;
DEBUG_WARN("tty not valid.");
}
else
{
@ -291,7 +276,6 @@ static void serial_process_irp(SERIAL_DEVICE* serial, IRP* irp)
break;
default:
DEBUG_WARN("MajorFunction 0x%X not supported", irp->MajorFunction);
irp->IoStatus = STATUS_NOT_SUPPORTED;
irp->Complete(irp);
break;

View File

@ -30,7 +30,6 @@
#include <winpr/print.h>
#include <winpr/stream.h>
#include <freerdp/utils/svc_plugin.h>
#include <freerdp/channels/rdpdr.h>
#ifndef _WIN32
@ -119,19 +118,16 @@ UINT32 serial_tty_control(SERIAL_TTY* tty, UINT32 IoControlCode, wStream* input,
case IOCTL_SERIAL_SET_BAUD_RATE:
Stream_Read_UINT32(input, tty->baud_rate);
tty_set_termios(tty);
DEBUG_SVC("SERIAL_SET_BAUD_RATE %d", tty->baud_rate);
break;
case IOCTL_SERIAL_GET_BAUD_RATE:
OutputBufferLength = 4;
Stream_Write_UINT32(output, tty->baud_rate);
DEBUG_SVC("SERIAL_GET_BAUD_RATE %d", tty->baud_rate);
break;
case IOCTL_SERIAL_SET_QUEUE_SIZE:
Stream_Read_UINT32(input, tty->queue_in_size);
Stream_Read_UINT32(input, tty->queue_out_size);
DEBUG_SVC("SERIAL_SET_QUEUE_SIZE in %d out %d", tty->queue_in_size, tty->queue_out_size);
break;
case IOCTL_SERIAL_SET_LINE_CONTROL:
@ -139,12 +135,9 @@ UINT32 serial_tty_control(SERIAL_TTY* tty, UINT32 IoControlCode, wStream* input,
Stream_Read_UINT8(input, tty->parity);
Stream_Read_UINT8(input, tty->word_length);
tty_set_termios(tty);
DEBUG_SVC("SERIAL_SET_LINE_CONTROL stop %d parity %d word %d",
tty->stop_bits, tty->parity, tty->word_length);
break;
case IOCTL_SERIAL_GET_LINE_CONTROL:
DEBUG_SVC("SERIAL_GET_LINE_CONTROL");
OutputBufferLength = 3;
Stream_Write_UINT8(output, tty->stop_bits);
Stream_Write_UINT8(output, tty->parity);
@ -152,25 +145,21 @@ UINT32 serial_tty_control(SERIAL_TTY* tty, UINT32 IoControlCode, wStream* input,
break;
case IOCTL_SERIAL_IMMEDIATE_CHAR:
DEBUG_SVC("SERIAL_IMMEDIATE_CHAR");
Stream_Read_UINT8(input, immediate);
tty_write_data(tty, &immediate, 1);
break;
case IOCTL_SERIAL_CONFIG_SIZE:
DEBUG_SVC("SERIAL_CONFIG_SIZE");
OutputBufferLength = 4;
Stream_Write_UINT32(output, 0);
break;
case IOCTL_SERIAL_GET_CHARS:
DEBUG_SVC("SERIAL_GET_CHARS");
OutputBufferLength = 6;
Stream_Write(output, tty->chars, 6);
break;
case IOCTL_SERIAL_SET_CHARS:
DEBUG_SVC("SERIAL_SET_CHARS");
Stream_Read(input, tty->chars, 6);
tty_set_termios(tty);
break;
@ -182,8 +171,6 @@ UINT32 serial_tty_control(SERIAL_TTY* tty, UINT32 IoControlCode, wStream* input,
Stream_Write_UINT32(output, tty->xonoff);
Stream_Write_UINT32(output, tty->onlimit);
Stream_Write_UINT32(output, tty->offlimit);
DEBUG_SVC("IOCTL_SERIAL_GET_HANDFLOW %X %X %X %X",
tty->control, tty->xonoff, tty->onlimit, tty->offlimit);
break;
case IOCTL_SERIAL_SET_HANDFLOW:
@ -191,8 +178,6 @@ UINT32 serial_tty_control(SERIAL_TTY* tty, UINT32 IoControlCode, wStream* input,
Stream_Read_UINT32(input, tty->xonoff);
Stream_Read_UINT32(input, tty->onlimit);
Stream_Read_UINT32(input, tty->offlimit);
DEBUG_SVC("IOCTL_SERIAL_SET_HANDFLOW %X %X %X %X",
tty->control, tty->xonoff, tty->onlimit, tty->offlimit);
tty_set_termios(tty);
break;
@ -211,17 +196,9 @@ UINT32 serial_tty_control(SERIAL_TTY* tty, UINT32 IoControlCode, wStream* input,
tty->read_total_timeout_multiplier = 0;
}
DEBUG_SVC("SERIAL_SET_TIMEOUTS read timeout %d %d %d",
tty->read_interval_timeout,
tty->read_total_timeout_multiplier,
tty->read_total_timeout_constant);
break;
case IOCTL_SERIAL_GET_TIMEOUTS:
DEBUG_SVC("SERIAL_GET_TIMEOUTS read timeout %d %d %d",
tty->read_interval_timeout,
tty->read_total_timeout_multiplier,
tty->read_total_timeout_constant);
OutputBufferLength = 20;
Stream_Write_UINT32(output, tty->read_interval_timeout);
Stream_Write_UINT32(output, tty->read_total_timeout_multiplier);
@ -231,18 +208,15 @@ UINT32 serial_tty_control(SERIAL_TTY* tty, UINT32 IoControlCode, wStream* input,
break;
case IOCTL_SERIAL_GET_WAIT_MASK:
DEBUG_SVC("SERIAL_GET_WAIT_MASK %X", tty->wait_mask);
OutputBufferLength = 4;
Stream_Write_UINT32(output, tty->wait_mask);
break;
case IOCTL_SERIAL_SET_WAIT_MASK:
Stream_Read_UINT32(input, tty->wait_mask);
DEBUG_SVC("SERIAL_SET_WAIT_MASK %X", tty->wait_mask);
break;
case IOCTL_SERIAL_SET_DTR:
DEBUG_SVC("SERIAL_SET_DTR");
ioctl(tty->fd, TIOCMGET, &result);
result |= TIOCM_DTR;
ioctl(tty->fd, TIOCMSET, &result);
@ -250,7 +224,6 @@ UINT32 serial_tty_control(SERIAL_TTY* tty, UINT32 IoControlCode, wStream* input,
break;
case IOCTL_SERIAL_CLR_DTR:
DEBUG_SVC("SERIAL_CLR_DTR");
ioctl(tty->fd, TIOCMGET, &result);
result &= ~TIOCM_DTR;
ioctl(tty->fd, TIOCMSET, &result);
@ -258,7 +231,6 @@ UINT32 serial_tty_control(SERIAL_TTY* tty, UINT32 IoControlCode, wStream* input,
break;
case IOCTL_SERIAL_SET_RTS:
DEBUG_SVC("SERIAL_SET_RTS");
ioctl(tty->fd, TIOCMGET, &result);
result |= TIOCM_RTS;
ioctl(tty->fd, TIOCMSET, &result);
@ -266,7 +238,6 @@ UINT32 serial_tty_control(SERIAL_TTY* tty, UINT32 IoControlCode, wStream* input,
break;
case IOCTL_SERIAL_CLR_RTS:
DEBUG_SVC("SERIAL_CLR_RTS");
ioctl(tty->fd, TIOCMGET, &result);
result &= ~TIOCM_RTS;
ioctl(tty->fd, TIOCMSET, &result);
@ -290,7 +261,6 @@ UINT32 serial_tty_control(SERIAL_TTY* tty, UINT32 IoControlCode, wStream* input,
if (result & TIOCM_RTS)
modemstate |= SERIAL_MS_RTS;
#endif
DEBUG_SVC("SERIAL_GET_MODEMSTATUS %X", modemstate);
OutputBufferLength = 4;
Stream_Write_UINT32(output, modemstate);
break;
@ -305,23 +275,18 @@ UINT32 serial_tty_control(SERIAL_TTY* tty, UINT32 IoControlCode, wStream* input,
ioctl(tty->fd, TIOCINQ, &result);
#endif
Stream_Write_UINT32(output, result); /* Amount in in queue */
if (result)
DEBUG_SVC("SERIAL_GET_COMMSTATUS in queue %d", result);
result = 0;
#ifdef TIOCOUTQ
ioctl(tty->fd, TIOCOUTQ, &result);
#endif
Stream_Write_UINT32(output, result); /* Amount in out queue */
DEBUG_SVC("SERIAL_GET_COMMSTATUS out queue %d", result);
Stream_Write_UINT8(output, 0); /* EofReceived */
Stream_Write_UINT8(output, 0); /* WaitForImmediate */
break;
case IOCTL_SERIAL_PURGE:
Stream_Read_UINT32(input, purge_mask);
DEBUG_SVC("SERIAL_PURGE purge_mask %X", purge_mask);
/* See http://msdn.microsoft.com/en-us/library/ms901431.aspx
PURGE_TXCLEAR Clears the output buffer, if the driver has one.
@ -330,25 +295,16 @@ UINT32 serial_tty_control(SERIAL_TTY* tty, UINT32 IoControlCode, wStream* input,
It clearly states to clear the *driver* buffer, not the port buffer
*/
#ifdef DEBUG_SVC
if (purge_mask & SERIAL_PURGE_TXCLEAR)
DEBUG_SVC("Ignoring SERIAL_PURGE_TXCLEAR");
if (purge_mask & SERIAL_PURGE_RXCLEAR)
DEBUG_SVC("Ignoring SERIAL_PURGE_RXCLEAR");
#endif
if (purge_mask & SERIAL_PURGE_TXABORT)
*abortIo |= SERIAL_ABORT_IO_WRITE;
if (purge_mask & SERIAL_PURGE_RXABORT)
*abortIo |= SERIAL_ABORT_IO_READ;
break;
case IOCTL_SERIAL_WAIT_ON_MASK:
DEBUG_SVC("SERIAL_WAIT_ON_MASK %X", tty->wait_mask);
tty->event_pending = 1;
OutputBufferLength = 4;
if (serial_tty_get_event(tty, &result))
{
DEBUG_SVC("WAIT end event = %X", result);
Stream_Write_UINT32(output, result);
break;
}
@ -356,29 +312,23 @@ UINT32 serial_tty_control(SERIAL_TTY* tty, UINT32 IoControlCode, wStream* input,
break;
case IOCTL_SERIAL_SET_BREAK_ON:
DEBUG_SVC("SERIAL_SET_BREAK_ON");
tcsendbreak(tty->fd, 0);
break;
case IOCTL_SERIAL_RESET_DEVICE:
DEBUG_SVC("SERIAL_RESET_DEVICE");
break;
case IOCTL_SERIAL_SET_BREAK_OFF:
DEBUG_SVC("SERIAL_SET_BREAK_OFF");
break;
case IOCTL_SERIAL_SET_XOFF:
DEBUG_SVC("SERIAL_SET_XOFF");
break;
case IOCTL_SERIAL_SET_XON:
DEBUG_SVC("SERIAL_SET_XON");
tcflow(tty->fd, TCION);
break;
default:
DEBUG_SVC("NOT FOUND IoControlCode SERIAL IOCTL 0x%08X", IoControlCode);
return STATUS_INVALID_PARAMETER;
}
@ -457,11 +407,7 @@ BOOL serial_tty_read(SERIAL_TTY* tty, BYTE* buffer, UINT32* Length)
status = read(tty->fd, buffer, *Length);
if (status < 0)
{
DEBUG_WARN("failed with %zd, errno=[%d] %s\n",
status, errno, strerror(errno));
return FALSE;
}
tty->event_txempty = status;
*Length = status;
@ -535,13 +481,12 @@ SERIAL_TTY* serial_tty_new(const char* path, UINT32 id)
if (tty->fd < 0)
{
perror("open");
DEBUG_WARN("failed to open device %s", path);
serial_tty_free(tty);
return NULL;
}
else
{
DEBUG_SVC("tty fd %d successfully opened", tty->fd);
}
tty->ptermios = (struct termios*) calloc(1, sizeof(struct termios));
@ -563,7 +508,6 @@ SERIAL_TTY* serial_tty_new(const char* path, UINT32 id)
if (!tty_get_termios(tty))
{
DEBUG_WARN("%s access denied", path);
fflush(stdout);
serial_tty_free(tty);
return NULL;
@ -589,7 +533,6 @@ SERIAL_TTY* serial_tty_new(const char* path, UINT32 id)
/* all read and writes should be non-blocking */
if (fcntl(tty->fd, F_SETFL, O_NONBLOCK) == -1)
{
DEBUG_WARN("%s fcntl", path);
perror("fcntl");
serial_tty_free(tty) ;
return NULL;
@ -620,15 +563,12 @@ BOOL serial_tty_get_event(SERIAL_TTY* tty, UINT32* result)
if (bytes > 0)
{
DEBUG_SVC("bytes %d", bytes);
if (bytes > tty->event_rlsd)
{
tty->event_rlsd = bytes;
if (tty->wait_mask & SERIAL_EV_RLSD)
{
DEBUG_SVC("SERIAL_EV_RLSD");
*result |= SERIAL_EV_RLSD;
status = TRUE;
}
@ -636,14 +576,12 @@ BOOL serial_tty_get_event(SERIAL_TTY* tty, UINT32* result)
if ((bytes > 1) && (tty->wait_mask & SERIAL_EV_RXFLAG))
{
DEBUG_SVC("SERIAL_EV_RXFLAG bytes %d", bytes);
*result |= SERIAL_EV_RXFLAG;
status = TRUE;
}
if ((tty->wait_mask & SERIAL_EV_RXCHAR))
{
DEBUG_SVC("SERIAL_EV_RXCHAR bytes %d", bytes);
*result |= SERIAL_EV_RXCHAR;
status = TRUE;
}
@ -658,7 +596,6 @@ BOOL serial_tty_get_event(SERIAL_TTY* tty, UINT32* result)
ioctl(tty->fd, TIOCOUTQ, &bytes);
if ((bytes == 0) && (tty->event_txempty > 0) && (tty->wait_mask & SERIAL_EV_TXEMPTY))
{
DEBUG_SVC("SERIAL_EV_TXEMPTY");
*result |= SERIAL_EV_TXEMPTY;
status = TRUE;
}
@ -669,9 +606,9 @@ BOOL serial_tty_get_event(SERIAL_TTY* tty, UINT32* result)
if ((bytes & TIOCM_DSR) != tty->event_dsr)
{
tty->event_dsr = bytes & TIOCM_DSR;
if (tty->wait_mask & SERIAL_EV_DSR)
{
DEBUG_SVC("SERIAL_EV_DSR %s", (bytes & TIOCM_DSR) ? "ON" : "OFF");
*result |= SERIAL_EV_DSR;
status = TRUE;
}
@ -680,9 +617,9 @@ BOOL serial_tty_get_event(SERIAL_TTY* tty, UINT32* result)
if ((bytes & TIOCM_CTS) != tty->event_cts)
{
tty->event_cts = bytes & TIOCM_CTS;
if (tty->wait_mask & SERIAL_EV_CTS)
{
DEBUG_SVC("SERIAL_EV_CTS %s", (bytes & TIOCM_CTS) ? "ON" : "OFF");
*result |= SERIAL_EV_CTS;
status = TRUE;
}
@ -700,8 +637,6 @@ static BOOL tty_get_termios(SERIAL_TTY* tty)
struct termios* ptermios;
ptermios = tty->ptermios;
DEBUG_SVC("tcgetattr? %d", tcgetattr(tty->fd, ptermios) >= 0);
if (tcgetattr(tty->fd, ptermios) < 0)
return FALSE;

View File

@ -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")

View File

@ -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);
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;
}
DEBUG_DVC("%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;
}

View File

@ -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)
else
if(mdecoder->media_type == AVMEDIA_TYPE_AUDIO)
{
if(!tsmf_ffmpeg_init_audio_stream(decoder, media_type))
return FALSE;
}
if(media_type->ExtraData)
{
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;
}

View File

@ -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})

View File

@ -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;
}

File diff suppressed because it is too large Load Diff

View File

@ -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

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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

View File

@ -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)
{
DEBUG_DVC("");
ifman->output_pending = TRUE;
return 0;
}
int tsmf_ifman_update_geometry_info(TSMF_IFMAN* ifman)
int tsmf_ifman_set_video_window(TSMF_IFMAN *ifman)
{
TSMF_PRESENTATION* presentation;
DEBUG_TSMF("");
ifman->output_pending = TRUE;
return 0;
}
int tsmf_ifman_update_geometry_info(TSMF_IFMAN *ifman)
{
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;
}

View File

@ -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,67 @@ 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, wStream *data)
{
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;
UINT32 cbSize = Stream_GetRemainingLength(data);
/* 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 = data;
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 +155,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 +264,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 +367,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 +396,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;
}

File diff suppressed because it is too large Load Diff

View File

@ -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_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);
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_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);

View File

@ -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;

View File

@ -8,6 +8,7 @@ libs/armeabi*
AndroidManifest.xml
local.properties
!.project
appcompat_v7
FreeRDPCore/project.properties
FreeRDPCore/src/com/freerdp/freerdpcore/utils/BuildConfiguration.java

View File

@ -42,6 +42,11 @@ if(ANDROID_BUILD_JAVA)
endif()
endif(ANDROID_BUILD_JAVA)
set(ANDROID_COMMAND "${ANDROID_SDK}/tools/android")
if(NOT EXISTS ${ANDROID_COMMAND})
message(FATAL_ERROR "android not found but required to build android java")
endif()
if(ANDROID_BUILD_JAVA_DEBUG)
set(ANDROID_BUILD_TYPE "debug")
else()
@ -56,5 +61,11 @@ else()
set(NDK_DEBUG "0")
endif()
set(APPCOMPAT_DIR "${CMAKE_CURRENT_BINARY_DIR}/appcompat_v7")
add_custom_target(copy_appcompat ALL
COMMAND ${CMAKE_COMMAND} -E copy_directory ${ANDROID_SDK}/extras/android/support/v7/appcompat ${APPCOMPAT_DIR}
COMMAND ${ANDROID_COMMAND} update lib-project -p ${APPCOMPAT_DIR}
)
add_subdirectory(FreeRDPCore)
add_subdirectory(aFreeRDP)

View File

@ -65,7 +65,7 @@
android:windowSoftInputMode="stateHidden">
</activity>
<activity android:name=".presentation.SessionActivity"
android:theme="@android:style/Theme.Black.NoTitleBar"
android:theme="@style/Theme.AppCompat"
android:configChanges="orientation|keyboardHidden|keyboard"
android:windowSoftInputMode="adjustResize">
</activity>

View File

@ -203,8 +203,6 @@ jint JNI_OnLoad(JavaVM* vm, void* reserved)
result = init_callback_environment(vm);
setlocale(LC_ALL, "");
freerdp_channels_global_init();
return result;
}

View File

@ -0,0 +1,3 @@
<?xml version="1.0" encoding="UTF-8"?>
<lint>
</lint>

View File

@ -13,3 +13,4 @@
# Project target.
target=android-@ANDROID_APP_TARGET_SDK@
android.library=true
android.library.reference.1=../appcompat_v7

View File

@ -18,7 +18,6 @@
android:paddingRight="6dip"
android:paddingTop="7dip"
android:paddingBottom="16dip"
android:background="@drawable/search_plate"
android:gravity="center_vertical"
android:focusable="true"
android:descendantFocusability="afterDescendants">
@ -36,8 +35,6 @@
android:singleLine="true"
android:ellipsize="end"
android:inputType="text"
android:textColor="?android:attr/textColorPrimary"
android:textColorHint="?android:attr/textColorHint"
android:drawableLeft="@drawable/icon_edittext_search"
android:drawableRight="@drawable/icon_edittext_clear"
/>

View File

@ -4,14 +4,17 @@
<item android:id="@+id/bookmark_connect"
android:title="@string/menu_connect"
android:showAsAction="ifRoom"
/>
<item android:id="@+id/bookmark_edit"
android:title="@string/menu_edit"
android:showAsAction="ifRoom"
/>
<item android:id="@+id/bookmark_delete"
android:title="@string/menu_delete"
android:showAsAction="ifRoom"
/>
</menu>

View File

@ -4,21 +4,21 @@
<item android:id="@+id/newBookmark"
android:icon="@drawable/icon_menu_add"
android:title="@string/menu_new_bookmark"
android:showAsAction="ifRoom"
/>
<item android:id="@+id/appSettings"
android:icon="@drawable/icon_menu_settings"
android:title="@string/menu_app_settings"
android:showAsAction="ifRoom"
/>
<item android:id="@+id/help"
android:icon="@drawable/icon_menu_help"
android:title="@string/menu_help"
android:showAsAction="ifRoom"
/>
<item android:id="@+id/about"
android:icon="@drawable/icon_menu_about"
android:title="@string/menu_about"
android:showAsAction="ifRoom"
/>
<item android:id="@+id/exit"
android:icon="@drawable/icon_menu_exit"
android:title="@string/menu_exit"
/>
</menu>

View File

@ -5,22 +5,27 @@
<item android:id="@+id/session_touch_pointer"
android:title="@string/pointer"
android:icon="@drawable/icon_zoom_in"
android:showAsAction="ifRoom"
/>
-->
<item android:id="@+id/session_touch_pointer"
android:title="@string/menu_touch_pointer"
android:icon="@drawable/icon_menu_touch_pointer"
android:showAsAction="ifRoom"
/>
<item android:id="@+id/session_sys_keyboard"
android:title="@string/menu_sys_keyboard"
android:icon="@drawable/icon_menu_sys_keyboard"
android:showAsAction="ifRoom"
/>
<item android:id="@+id/session_ext_keyboard"
android:title="@string/menu_ext_keyboard"
android:icon="@drawable/icon_menu_ext_keyboard"
android:showAsAction="ifRoom"
/>
<item android:id="@+id/session_disconnect"
android:title="@string/menu_disconnect"
android:icon="@drawable/icon_menu_disconnect"
android:showAsAction="ifRoom"
/>
</menu>

View File

@ -23,7 +23,7 @@
<string name="menu_ext_keyboard">Funcion teclado</string>
<string name="menu_touch_pointer">Puntero Tactil</string>
<string name="menu_home">Inicio</string>
<string name="menu_disconnect">desconectart</string>
<string name="menu_disconnect">Desconectart</string>
<!-- List section headers -->
<string name="section_bookmarks">Conexión Manual</string>
<string name="section_active_sessions">Sesiones Activas</string>
@ -197,4 +197,6 @@
<string name="dlg_msg_exit">Esta seguro que desea salir del programa?</string>
<string name="dlg_title_clear_cert_cache">Borrar Certificados?</string>
<string name="dlg_msg_clear_cert_cache">Esta seguro que desea borrar todos los certificados?</string>
<string name="debug_level">Debug Level</string>
<string name="settings_debug">Debug Settings</string>
</resources>

View File

@ -196,4 +196,6 @@
<string name="dlg_msg_exit">"Êtes-vous sûr de vouloir quitter l'application?"</string>
<string name="dlg_title_clear_cert_cache">"Êtes-vous sûrs de vouloir supprimer les certificats?"</string>
<string name="dlg_msg_clear_cert_cache">"Êtes-vous sûr de vouloir supprimer tous les certificats mis en cache?"</string>
<string name="debug_level">Debug Level</string>
<string name="settings_debug">Debug Settings</string>
</resources>

View File

@ -197,4 +197,6 @@
<string name="dlg_msg_exit">Weet u zeker dat u de applicatie wilt sluiten?</string>
<string name="dlg_title_clear_cert_cache">Verwijder certificaten?</string>
<string name="dlg_msg_clear_cert_cache">Weet u zeker dat u al uw cache certificaten wilt verwijderen?</string>
<string name="debug_level">Debug Level</string>
<string name="settings_debug">Debug Settings</string>
</resources>

View File

@ -23,7 +23,7 @@
<string name="menu_ext_keyboard">Function Keys</string>
<string name="menu_touch_pointer">Touch Pointer</string>
<string name="menu_home">home</string>
<string name="menu_disconnect">disconnect</string>
<string name="menu_disconnect">Disconnect</string>
<!-- List section headers -->
<string name="section_bookmarks">Manual Connections</string>
<string name="section_active_sessions">Active Sessions</string>

View File

@ -1,10 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<resources>
<style name="Theme.Settings" parent="android:Theme.Light">
<style name="Theme.Settings" parent="@style/Theme.AppCompat">
<item name="android:listSeparatorTextViewStyle">@style/SettingsCategory</item>
</style>
<style name="Theme.Main" parent="android:Theme.Light">
<style name="Theme.Main" parent="@style/Theme.AppCompat">
</style>
<style name="SettingsCategory">
<item name="android:layout_width">match_parent</item>

View File

@ -363,10 +363,6 @@ public class HomeActivity extends Activity
Intent helpIntent = new Intent(this, HelpActivity.class);
startActivity(helpIntent);
}
else if (itemId == R.id.exit)
{
finish();
}
else if (itemId == R.id.about)
{
Intent aboutIntent = new Intent(this, AboutActivity.class);

View File

@ -0,0 +1,3 @@
<?xml version="1.0" encoding="UTF-8"?>
<lint>
</lint>

View File

@ -0,0 +1,20 @@
# To enable ProGuard in your project, edit project.properties
# to define the proguard.config property as described in that file.
#
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in ${sdk.dir}/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the ProGuard
# include property in project.properties.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# Add any project specific keep options here:
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}

View File

@ -441,8 +441,6 @@ int main(int argc, char* argv[])
setlocale(LC_ALL, "");
freerdp_channels_global_init();
g_sem = CreateSemaphore(NULL, 0, 1, NULL);
instance = freerdp_new();
@ -484,7 +482,5 @@ int main(int argc, char* argv[])
WaitForSingleObject(g_sem, INFINITE);
}
freerdp_channels_global_uninit();
return 0;
}

View File

@ -760,8 +760,6 @@ DWORD fixKeyCode(DWORD keyCode, unichar keyChar, enum APPLE_KEYBOARD_TYPE type)
return;
gdi_free(context->instance);
freerdp_channels_global_uninit();
if (pixel_data)
free(pixel_data);

View File

@ -33,12 +33,11 @@
void mfreerdp_client_global_init()
{
freerdp_handle_signals();
freerdp_channels_global_init();
}
void mfreerdp_client_global_uninit()
{
freerdp_channels_global_uninit();
}
int mfreerdp_client_start(rdpContext* context)

View File

@ -305,8 +305,6 @@ int main(int argc, char* argv[])
rdpChannels* channels;
struct thread_data* data;
freerdp_channels_global_init();
g_sem = CreateSemaphore(NULL, 0, 1, NULL);
instance = freerdp_new();
@ -341,7 +339,5 @@ int main(int argc, char* argv[])
WaitForSingleObject(g_sem, INFINITE);
}
freerdp_channels_global_uninit();
return 0;
}

View File

@ -31,7 +31,6 @@
#include <freerdp/freerdp.h>
#include <freerdp/constants.h>
#include <freerdp/utils/event.h>
#include <freerdp/utils/svc_plugin.h>
#include <freerdp/client/file.h>
#include <freerdp/client/cmdline.h>

View File

@ -43,9 +43,7 @@
#include <freerdp/freerdp.h>
#include <freerdp/constants.h>
#include <freerdp/utils/event.h>
#include <freerdp/utils/svc_plugin.h>
//#include <freerdp/client/file.h>
#include <freerdp/client/cmdline.h>
#include <freerdp/client/channels.h>
#include <freerdp/channels/channels.h>
@ -1171,8 +1169,6 @@ void wfreerdp_client_global_init(void)
wf_create_console();
#endif
freerdp_channels_global_init();
freerdp_register_addin_provider(freerdp_channels_load_static_addin_entry, 0);
}

View File

@ -26,6 +26,8 @@ include_directories(${OPENSSL_INCLUDE_DIR})
set(${MODULE_PREFIX}_SRCS
xf_gdi.c
xf_gdi.h
xf_gfx.c
xf_gfx.h
xf_rail.c
xf_rail.h
xf_tsmf.c

View File

@ -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((void*) name);
free((void*) format);
free((void*) text);
}
fprintf(fp, "\t\t</variablelist>\n");
fprintf(fp, "\t</refsect1>\n");
fclose(fp);
if(NULL != tmp)
free(tmp);
return 0;
}

View File

@ -26,6 +26,8 @@
#include "xf_client.h"
#include "xfreerdp.h"
#include "xf_gfx.h"
void xf_OnChannelConnectedEventHandler(rdpContext* context, ChannelConnectedEventArgs* e)
{
xfContext* xfc = (xfContext*) context;
@ -34,9 +36,22 @@ void xf_OnChannelConnectedEventHandler(rdpContext* context, ChannelConnectedEven
{
xfc->rdpei = (RdpeiClientContext*) e->pInterface;
}
else if (strcmp(e->name, RDPGFX_DVC_CHANNEL_NAME) == 0)
{
xf_graphics_pipeline_init(xfc, (RdpgfxClientContext*) e->pInterface);
}
}
void xf_OnChannelDisconnectedEventHandler(rdpContext* context, ChannelDisconnectedEventArgs* e)
{
xfContext* xfc = (xfContext*) context;
if (strcmp(e->name, RDPEI_DVC_CHANNEL_NAME) == 0)
{
xfc->rdpei = NULL;
}
else if (strcmp(e->name, RDPGFX_DVC_CHANNEL_NAME) == 0)
{
xf_graphics_pipeline_uninit(xfc, (RdpgfxClientContext*) e->pInterface);
}
}

View File

@ -23,6 +23,7 @@
#include <freerdp/freerdp.h>
#include <freerdp/client/channels.h>
#include <freerdp/client/rdpei.h>
#include <freerdp/client/rdpgfx.h>
int xf_on_channel_connected(freerdp* instance, const char* name, void* pInterface);
int xf_on_channel_disconnected(freerdp* instance, const char* name, void* pInterface);

File diff suppressed because it is too large Load Diff

View File

@ -30,6 +30,7 @@
#include "xf_window.h"
#include "xf_cliprdr.h"
#include "xf_input.h"
#include "xf_gfx.h"
#include "xf_event.h"
#include "xf_input.h"
@ -189,7 +190,13 @@ static BOOL xf_event_Expose(xfContext* xfc, XEvent* event, BOOL app)
y = event->xexpose.y;
w = event->xexpose.width;
h = event->xexpose.height;
if (xfc->gfx)
{
xf_OutputExpose(xfc, x, y, w, h);
return TRUE;
}
if (!app)
{
if ((xfc->settings->ScalingFactor != 1.0) || (xfc->offset_x) || (xfc->offset_y))
@ -199,9 +206,7 @@ static BOOL xf_event_Expose(xfContext* xfc, XEvent* event, BOOL app)
}
else
{
XCopyArea(xfc->display, xfc->primary,
xfc->window->handle, xfc->gc, x, y, w,
h, x, y);
XCopyArea(xfc->display, xfc->primary, xfc->window->handle, xfc->gc, x, y, w, h, x, y);
}
}
else

View File

@ -990,14 +990,12 @@ void xf_gdi_surface_bits(rdpContext* context, SURFACE_BITS_COMMAND* surface_bits
XImage* image;
RFX_MESSAGE* message;
xfContext* xfc = (xfContext*) context;
RFX_CONTEXT* rfx_context = (RFX_CONTEXT*) xfc->rfx_context;
NSC_CONTEXT* nsc_context = (NSC_CONTEXT*) xfc->nsc_context;
xf_lock_x11(xfc, FALSE);
if (surface_bits_command->codecID == RDP_CODEC_ID_REMOTEFX)
{
message = rfx_process_message(rfx_context,
message = rfx_process_message(xfc->rfx,
surface_bits_command->bitmapData, surface_bits_command->bitmapDataLength);
XSetFunction(xfc->display, xfc->gc, GXcopy);
@ -1034,11 +1032,11 @@ void xf_gdi_surface_bits(rdpContext* context, SURFACE_BITS_COMMAND* surface_bits
}
XSetClipMask(xfc->display, xfc->gc, None);
rfx_message_free(rfx_context, message);
rfx_message_free(xfc->rfx, message);
}
else if (surface_bits_command->codecID == RDP_CODEC_ID_NSCODEC)
{
nsc_process_message(nsc_context, surface_bits_command->bpp, surface_bits_command->width, surface_bits_command->height,
nsc_process_message(xfc->nsc, surface_bits_command->bpp, surface_bits_command->width, surface_bits_command->height,
surface_bits_command->bitmapData, surface_bits_command->bitmapDataLength);
XSetFunction(xfc->display, xfc->gc, GXcopy);
@ -1047,7 +1045,7 @@ void xf_gdi_surface_bits(rdpContext* context, SURFACE_BITS_COMMAND* surface_bits
xfc->bmp_codec_nsc = (BYTE*) realloc(xfc->bmp_codec_nsc,
surface_bits_command->width * surface_bits_command->height * 4);
freerdp_image_flip(nsc_context->BitmapData, xfc->bmp_codec_nsc,
freerdp_image_flip(xfc->nsc->BitmapData, xfc->bmp_codec_nsc,
surface_bits_command->width, surface_bits_command->height, 32);
image = XCreateImage(xfc->display, xfc->visual, 24, ZPixmap, 0,
@ -1060,13 +1058,14 @@ void xf_gdi_surface_bits(rdpContext* context, SURFACE_BITS_COMMAND* surface_bits
free(xfc->bmp_codec_nsc);
xfc->bmp_codec_nsc = NULL;
if (xfc->remote_app != TRUE)
if (!xfc->remote_app)
{
XCopyArea(xfc->display, xfc->primary, xfc->window->handle, xfc->gc,
surface_bits_command->destLeft, surface_bits_command->destTop,
surface_bits_command->width, surface_bits_command->height,
surface_bits_command->destLeft, surface_bits_command->destTop);
}
xf_gdi_surface_update_frame(xfc,
surface_bits_command->destLeft, surface_bits_command->destTop,
surface_bits_command->width, surface_bits_command->height);

672
client/X11/xf_gfx.c Normal file
View File

@ -0,0 +1,672 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* X11 Graphics Pipeline
*
* Copyright 2014 Marc-Andre Moreau <marcandre.moreau@gmail.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.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "xf_gfx.h"
int xf_ResetGraphics(RdpgfxClientContext* context, RDPGFX_RESET_GRAPHICS_PDU* resetGraphics)
{
xfContext* xfc = (xfContext*) context->custom;
printf("xf_ResetGraphics: width: %d height: %d\n",
resetGraphics->width, resetGraphics->height);
if (xfc->rfx)
{
rfx_context_free(xfc->rfx);
xfc->rfx = NULL;
}
xfc->rfx = rfx_context_new(FALSE);
xfc->rfx->width = resetGraphics->width;
xfc->rfx->height = resetGraphics->height;
rfx_context_set_pixel_format(xfc->rfx, RDP_PIXEL_FORMAT_B8G8R8A8);
if (xfc->nsc)
{
nsc_context_free(xfc->nsc);
xfc->nsc = NULL;
}
xfc->nsc = nsc_context_new();
xfc->nsc->width = resetGraphics->width;
xfc->nsc->height = resetGraphics->height;
nsc_context_set_pixel_format(xfc->nsc, RDP_PIXEL_FORMAT_B8G8R8A8);
xfc->clear = clear_context_new(FALSE);
region16_init(&(xfc->invalidRegion));
xfc->graphicsReset = TRUE;
return 1;
}
int xf_OutputUpdate(xfContext* xfc)
{
UINT16 width, height;
xfGfxSurface* surface;
RECTANGLE_16 surfaceRect;
const RECTANGLE_16* extents;
if (!xfc->graphicsReset)
return 1;
surface = (xfGfxSurface*) xfc->gfx->GetSurfaceData(xfc->gfx, xfc->outputSurfaceId);
if (!surface)
return -1;
surfaceRect.left = 0;
surfaceRect.top = 0;
surfaceRect.right = xfc->width;
surfaceRect.bottom = xfc->height;
region16_intersect_rect(&(xfc->invalidRegion), &(xfc->invalidRegion), &surfaceRect);
XSetClipMask(xfc->display, xfc->gc, None);
XSetFunction(xfc->display, xfc->gc, GXcopy);
XSetFillStyle(xfc->display, xfc->gc, FillSolid);
if (!region16_is_empty(&(xfc->invalidRegion)))
{
extents = region16_extents(&(xfc->invalidRegion));
width = extents->right - extents->left;
height = extents->bottom - extents->top;
if (width > xfc->width)
width = xfc->width;
if (height > xfc->height)
height = xfc->height;
XPutImage(xfc->display, xfc->drawable, xfc->gc, surface->image,
extents->left, extents->top,
extents->left, extents->top, width, height);
}
region16_clear(&(xfc->invalidRegion));
XSetClipMask(xfc->display, xfc->gc, None);
XSync(xfc->display, True);
return 1;
}
int xf_OutputExpose(xfContext* xfc, int x, int y, int width, int height)
{
RECTANGLE_16 invalidRect;
invalidRect.left = x;
invalidRect.top = y;
invalidRect.right = x + width;
invalidRect.bottom = y + height;
region16_union_rect(&(xfc->invalidRegion), &(xfc->invalidRegion), &invalidRect);
xf_OutputUpdate(xfc);
return 1;
}
int xf_StartFrame(RdpgfxClientContext* context, RDPGFX_START_FRAME_PDU* startFrame)
{
xfContext* xfc = (xfContext*) context->custom;
xfc->inGfxFrame = TRUE;
return 1;
}
int xf_EndFrame(RdpgfxClientContext* context, RDPGFX_END_FRAME_PDU* endFrame)
{
xfContext* xfc = (xfContext*) context->custom;
xf_OutputUpdate(xfc);
xfc->inGfxFrame = FALSE;
return 1;
}
int xf_SurfaceCommand_Uncompressed(xfContext* xfc, RdpgfxClientContext* context, RDPGFX_SURFACE_COMMAND* cmd)
{
xfGfxSurface* surface;
RECTANGLE_16 invalidRect;
surface = (xfGfxSurface*) context->GetSurfaceData(context, cmd->surfaceId);
if (!surface)
return -1;
freerdp_image_copy(surface->data, PIXEL_FORMAT_XRGB32, surface->scanline, cmd->left, cmd->top,
cmd->width, cmd->height, cmd->data, PIXEL_FORMAT_XRGB32, cmd->width * 4, 0, 0);
invalidRect.left = cmd->left;
invalidRect.top = cmd->top;
invalidRect.right = cmd->right;
invalidRect.bottom = cmd->bottom;
region16_union_rect(&(xfc->invalidRegion), &(xfc->invalidRegion), &invalidRect);
if (!xfc->inGfxFrame)
xf_OutputUpdate(xfc);
return 1;
}
int xf_SurfaceCommand_RemoteFX(xfContext* xfc, RdpgfxClientContext* context, RDPGFX_SURFACE_COMMAND* cmd)
{
int j;
UINT16 i;
RFX_RECT* rect;
RFX_TILE* tile;
int nXDst, nYDst;
int nWidth, nHeight;
int nbUpdateRects;
RFX_MESSAGE* message;
xfGfxSurface* surface;
REGION16 updateRegion;
RECTANGLE_16 updateRect;
RECTANGLE_16* updateRects;
REGION16 clippingRects;
RECTANGLE_16 clippingRect;
surface = (xfGfxSurface*) context->GetSurfaceData(context, cmd->surfaceId);
if (!surface)
return -1;
message = rfx_process_message(xfc->rfx, cmd->data, cmd->length);
if (!message)
return -1;
region16_init(&clippingRects);
for (i = 0; i < message->numRects; i++)
{
rect = &(message->rects[i]);
clippingRect.left = cmd->left + rect->x;
clippingRect.top = cmd->top + rect->y;
clippingRect.right = clippingRect.left + rect->width;
clippingRect.bottom = clippingRect.top + rect->height;
region16_union_rect(&clippingRects, &clippingRects, &clippingRect);
}
for (i = 0; i < message->numTiles; i++)
{
tile = message->tiles[i];
updateRect.left = cmd->left + tile->x;
updateRect.top = cmd->top + tile->y;
updateRect.right = updateRect.left + 64;
updateRect.bottom = updateRect.top + 64;
region16_init(&updateRegion);
region16_intersect_rect(&updateRegion, &clippingRects, &updateRect);
updateRects = (RECTANGLE_16*) region16_rects(&updateRegion, &nbUpdateRects);
for (j = 0; j < nbUpdateRects; j++)
{
nXDst = updateRects[j].left;
nYDst = updateRects[j].top;
nWidth = updateRects[j].right - updateRects[j].left;
nHeight = updateRects[j].bottom - updateRects[j].top;
freerdp_image_copy(surface->data, PIXEL_FORMAT_XRGB32, surface->scanline,
nXDst, nYDst, nWidth, nHeight,
tile->data, PIXEL_FORMAT_XRGB32, 64 * 4, 0, 0);
region16_union_rect(&(xfc->invalidRegion), &(xfc->invalidRegion), &updateRects[j]);
}
region16_uninit(&updateRegion);
}
rfx_message_free(xfc->rfx, message);
if (!xfc->inGfxFrame)
xf_OutputUpdate(xfc);
return 1;
}
int xf_SurfaceCommand_ClearCodec(xfContext* xfc, RdpgfxClientContext* context, RDPGFX_SURFACE_COMMAND* cmd)
{
int status;
UINT32 DstSize = 0;
BYTE* pDstData = NULL;
xfGfxSurface* surface;
RECTANGLE_16 invalidRect;
surface = (xfGfxSurface*) context->GetSurfaceData(context, cmd->surfaceId);
if (!surface)
return -1;
status = clear_decompress(xfc->clear, cmd->data, cmd->length, &pDstData, &DstSize);
printf("xf_SurfaceCommand_ClearCodec: status: %d\n", status);
/* fill with pink for now to distinguish from the rest */
freerdp_image_fill(surface->data, PIXEL_FORMAT_XRGB32, surface->scanline,
cmd->left, cmd->top, cmd->width, cmd->height, 0xFF69B4);
invalidRect.left = cmd->left;
invalidRect.top = cmd->top;
invalidRect.right = cmd->right;
invalidRect.bottom = cmd->bottom;
region16_union_rect(&(xfc->invalidRegion), &(xfc->invalidRegion), &invalidRect);
if (!xfc->inGfxFrame)
xf_OutputUpdate(xfc);
return 1;
}
int xf_SurfaceCommand_Planar(xfContext* xfc, RdpgfxClientContext* context, RDPGFX_SURFACE_COMMAND* cmd)
{
int status;
BYTE* DstData = NULL;
xfGfxSurface* surface;
RECTANGLE_16 invalidRect;
surface = (xfGfxSurface*) context->GetSurfaceData(context, cmd->surfaceId);
if (!surface)
return -1;
DstData = surface->data;
status = planar_decompress(NULL, cmd->data, cmd->length, &DstData,
PIXEL_FORMAT_XRGB32, surface->scanline, cmd->left, cmd->top, cmd->width, cmd->height);
invalidRect.left = cmd->left;
invalidRect.top = cmd->top;
invalidRect.right = cmd->right;
invalidRect.bottom = cmd->bottom;
region16_union_rect(&(xfc->invalidRegion), &(xfc->invalidRegion), &invalidRect);
if (!xfc->inGfxFrame)
xf_OutputUpdate(xfc);
return 1;
}
int xf_SurfaceCommand(RdpgfxClientContext* context, RDPGFX_SURFACE_COMMAND* cmd)
{
int status = 1;
xfContext* xfc = (xfContext*) context->custom;
switch (cmd->codecId)
{
case RDPGFX_CODECID_UNCOMPRESSED:
status = xf_SurfaceCommand_Uncompressed(xfc, context, cmd);
break;
case RDPGFX_CODECID_CAVIDEO:
status = xf_SurfaceCommand_RemoteFX(xfc, context, cmd);
break;
case RDPGFX_CODECID_CLEARCODEC:
status = xf_SurfaceCommand_ClearCodec(xfc, context, cmd);
break;
case RDPGFX_CODECID_PLANAR:
status = xf_SurfaceCommand_Planar(xfc, context, cmd);
break;
case RDPGFX_CODECID_H264:
printf("xf_SurfaceCommand_H264\n");
break;
case RDPGFX_CODECID_ALPHA:
printf("xf_SurfaceCommand_Alpha\n");
break;
case RDPGFX_CODECID_CAPROGRESSIVE:
printf("xf_SurfaceCommand_Progressive\n");
break;
case RDPGFX_CODECID_CAPROGRESSIVE_V2:
printf("xf_SurfaceCommand_ProgressiveV2\n");
break;
}
return 1;
}
int xf_DeleteEncodingContext(RdpgfxClientContext* context, RDPGFX_DELETE_ENCODING_CONTEXT_PDU* deleteEncodingContext)
{
printf("xf_DeleteEncodingContext\n");
return 1;
}
int xf_CreateSurface(RdpgfxClientContext* context, RDPGFX_CREATE_SURFACE_PDU* createSurface)
{
xfGfxSurface* surface;
xfContext* xfc = (xfContext*) context->custom;
printf("xf_CreateSurface: surfaceId: %d width: %d height: %d format: 0x%02X\n",
createSurface->surfaceId, createSurface->width, createSurface->height, createSurface->pixelFormat);
surface = (xfGfxSurface*) calloc(1, sizeof(xfGfxSurface));
if (!surface)
return -1;
surface->surfaceId = createSurface->surfaceId;
surface->width = (UINT32) createSurface->width;
surface->height = (UINT32) createSurface->height;
surface->alpha = (createSurface->pixelFormat == PIXEL_FORMAT_ARGB_8888) ? TRUE : FALSE;
surface->scanline = (surface->width + (surface->width % 4)) * 4;
surface->data = (BYTE*) calloc(1, surface->scanline * surface->height);
if (!surface->data)
return -1;
surface->image = XCreateImage(xfc->display, xfc->visual, 24, ZPixmap, 0,
(char*) surface->data, surface->width, surface->height, 32, surface->scanline);
context->SetSurfaceData(context, surface->surfaceId, (void*) surface);
return 1;
}
int xf_DeleteSurface(RdpgfxClientContext* context, RDPGFX_DELETE_SURFACE_PDU* deleteSurface)
{
xfGfxSurface* surface = NULL;
surface = (xfGfxSurface*) context->GetSurfaceData(context, deleteSurface->surfaceId);
printf("xf_DeleteSurface: surfaceId: %d\n", deleteSurface->surfaceId);
if (surface)
{
XFree(surface->image);
free(surface->data);
free(surface);
}
context->SetSurfaceData(context, deleteSurface->surfaceId, NULL);
return 1;
}
int xf_SolidFill(RdpgfxClientContext* context, RDPGFX_SOLID_FILL_PDU* solidFill)
{
UINT16 index;
UINT32 color;
BYTE a, r, g, b;
int nWidth, nHeight;
RDPGFX_RECT16* rect;
xfGfxSurface* surface;
RECTANGLE_16 invalidRect;
xfContext* xfc = (xfContext*) context->custom;
surface = (xfGfxSurface*) context->GetSurfaceData(context, solidFill->surfaceId);
printf("xf_SolidFill\n");
if (!surface)
return -1;
b = solidFill->fillPixel.B;
g = solidFill->fillPixel.G;
r = solidFill->fillPixel.R;
a = solidFill->fillPixel.XA;
color = ARGB32(a, r, g, b);
for (index = 0; index < solidFill->fillRectCount; index++)
{
rect = &(solidFill->fillRects[index]);
nWidth = rect->right - rect->left;
nHeight = rect->bottom - rect->top;
invalidRect.left = rect->left;
invalidRect.top = rect->top;
invalidRect.right = rect->right;
invalidRect.bottom = rect->bottom;
freerdp_image_fill(surface->data, PIXEL_FORMAT_XRGB32, surface->scanline,
rect->left, rect->top, nWidth, nHeight, color);
region16_union_rect(&(xfc->invalidRegion), &(xfc->invalidRegion), &invalidRect);
}
if (!xfc->inGfxFrame)
xf_OutputUpdate(xfc);
return 1;
}
int xf_SurfaceToSurface(RdpgfxClientContext* context, RDPGFX_SURFACE_TO_SURFACE_PDU* surfaceToSurface)
{
UINT16 index;
int nWidth, nHeight;
RDPGFX_RECT16* rectSrc;
RDPGFX_POINT16* destPt;
RECTANGLE_16 invalidRect;
xfGfxSurface* surfaceSrc;
xfGfxSurface* surfaceDst;
xfContext* xfc = (xfContext*) context->custom;
rectSrc = &(surfaceToSurface->rectSrc);
destPt = &surfaceToSurface->destPts[0];
surfaceSrc = (xfGfxSurface*) context->GetSurfaceData(context, surfaceToSurface->surfaceIdSrc);
if (surfaceToSurface->surfaceIdSrc != surfaceToSurface->surfaceIdDest)
surfaceDst = (xfGfxSurface*) context->GetSurfaceData(context, surfaceToSurface->surfaceIdDest);
else
surfaceDst = surfaceSrc;
if (!surfaceSrc || !surfaceDst)
return -1;
nWidth = rectSrc->right - rectSrc->left + 1;
nHeight = rectSrc->bottom - rectSrc->top + 1;
for (index = 0; index < surfaceToSurface->destPtsCount; index++)
{
destPt = &surfaceToSurface->destPts[index];
freerdp_image_copy(surfaceDst->data, PIXEL_FORMAT_XRGB32, surfaceDst->scanline,
destPt->x, destPt->y, nWidth, nHeight, surfaceSrc->data, PIXEL_FORMAT_XRGB32,
surfaceSrc->scanline, rectSrc->left, rectSrc->top);
invalidRect.left = destPt->x;
invalidRect.top = destPt->y;
invalidRect.right = destPt->x + rectSrc->right;
invalidRect.bottom = destPt->y + rectSrc->bottom;
region16_union_rect(&(xfc->invalidRegion), &(xfc->invalidRegion), &invalidRect);
}
if (!xfc->inGfxFrame)
xf_OutputUpdate(xfc);
return 1;
}
int xf_SurfaceToCache(RdpgfxClientContext* context, RDPGFX_SURFACE_TO_CACHE_PDU* surfaceToCache)
{
RDPGFX_RECT16* rect;
xfGfxSurface* surface;
xfGfxCacheEntry* cacheEntry;
rect = &(surfaceToCache->rectSrc);
surface = (xfGfxSurface*) context->GetSurfaceData(context, surfaceToCache->surfaceId);
//printf("xf_SurfaceToCache: cacheKey: 0x%016X cacheSlot: %ld\n",
// surfaceToCache->cacheKey, surfaceToCache->cacheSlot);
if (!surface)
return -1;
cacheEntry = (xfGfxCacheEntry*) calloc(1, sizeof(xfGfxCacheEntry));
if (!cacheEntry)
return -1;
cacheEntry->width = (UINT32) (rect->right - rect->left);
cacheEntry->height = (UINT32) (rect->bottom - rect->top);
cacheEntry->alpha = surface->alpha;
cacheEntry->scanline = (cacheEntry->width + (cacheEntry->width % 4)) * 4;
cacheEntry->data = (BYTE*) calloc(1, surface->scanline * surface->height);
if (!cacheEntry->data)
return -1;
freerdp_image_copy(cacheEntry->data, PIXEL_FORMAT_XRGB32, cacheEntry->scanline,
0, 0, cacheEntry->width, cacheEntry->height, surface->data,
PIXEL_FORMAT_XRGB32, surface->scanline, rect->left, rect->top);
context->SetCacheSlotData(context, surfaceToCache->cacheSlot, (void*) cacheEntry);
return 1;
}
int xf_CacheToSurface(RdpgfxClientContext* context, RDPGFX_CACHE_TO_SURFACE_PDU* cacheToSurface)
{
UINT16 index;
RDPGFX_POINT16* destPt;
xfGfxSurface* surface;
xfGfxCacheEntry* cacheEntry;
RECTANGLE_16 invalidRect;
xfContext* xfc = (xfContext*) context->custom;
surface = (xfGfxSurface*) context->GetSurfaceData(context, cacheToSurface->surfaceId);
cacheEntry = (xfGfxCacheEntry*) context->GetCacheSlotData(context, cacheToSurface->cacheSlot);
//printf("xf_CacheToSurface: cacheEntry: %d\n",
// cacheToSurface->cacheSlot);
if (!surface || !cacheEntry)
return -1;
for (index = 0; index < cacheToSurface->destPtsCount; index++)
{
destPt = &cacheToSurface->destPts[index];
freerdp_image_copy(surface->data, PIXEL_FORMAT_XRGB32, surface->scanline,
destPt->x, destPt->y, cacheEntry->width, cacheEntry->height,
cacheEntry->data, PIXEL_FORMAT_XRGB32, cacheEntry->scanline, 0, 0);
invalidRect.left = destPt->x;
invalidRect.top = destPt->y;
invalidRect.right = destPt->x + cacheEntry->width - 1;
invalidRect.bottom = destPt->y + cacheEntry->height - 1;
region16_union_rect(&(xfc->invalidRegion), &(xfc->invalidRegion), &invalidRect);
}
if (!xfc->inGfxFrame)
xf_OutputUpdate(xfc);
return 1;
}
int xf_CacheImportReply(RdpgfxClientContext* context, RDPGFX_CACHE_IMPORT_REPLY_PDU* cacheImportReply)
{
return 1;
}
int xf_EvictCacheEntry(RdpgfxClientContext* context, RDPGFX_EVICT_CACHE_ENTRY_PDU* evictCacheEntry)
{
xfGfxCacheEntry* cacheEntry;
//printf("xf_EvictCacheEntry\n");
cacheEntry = (xfGfxCacheEntry*) context->GetCacheSlotData(context, evictCacheEntry->cacheSlot);
if (cacheEntry)
{
free(cacheEntry->data);
free(cacheEntry);
}
context->SetCacheSlotData(context, evictCacheEntry->cacheSlot, NULL);
return 1;
}
int xf_MapSurfaceToOutput(RdpgfxClientContext* context, RDPGFX_MAP_SURFACE_TO_OUTPUT_PDU* surfaceToOutput)
{
xfContext* xfc = (xfContext*) context->custom;
xfc->outputSurfaceId = surfaceToOutput->surfaceId;
return 1;
}
int xf_MapSurfaceToWindow(RdpgfxClientContext* context, RDPGFX_MAP_SURFACE_TO_WINDOW_PDU* surfaceToWindow)
{
return 1;
}
void xf_graphics_pipeline_init(xfContext* xfc, RdpgfxClientContext* gfx)
{
xfc->gfx = gfx;
gfx->custom = (void*) xfc;
gfx->ResetGraphics = xf_ResetGraphics;
gfx->StartFrame = xf_StartFrame;
gfx->EndFrame = xf_EndFrame;
gfx->SurfaceCommand = xf_SurfaceCommand;
gfx->DeleteEncodingContext = xf_DeleteEncodingContext;
gfx->CreateSurface = xf_CreateSurface;
gfx->DeleteSurface = xf_DeleteSurface;
gfx->SolidFill = xf_SolidFill;
gfx->SurfaceToSurface = xf_SurfaceToSurface;
gfx->SurfaceToCache = xf_SurfaceToCache;
gfx->CacheToSurface = xf_CacheToSurface;
gfx->CacheImportReply = xf_CacheImportReply;
gfx->EvictCacheEntry = xf_EvictCacheEntry;
gfx->MapSurfaceToOutput = xf_MapSurfaceToOutput;
gfx->MapSurfaceToWindow = xf_MapSurfaceToWindow;
region16_init(&(xfc->invalidRegion));
}
void xf_graphics_pipeline_uninit(xfContext* xfc, RdpgfxClientContext* gfx)
{
region16_uninit(&(xfc->invalidRegion));
gfx->custom = NULL;
xfc->gfx = NULL;
}

54
client/X11/xf_gfx.h Normal file
View File

@ -0,0 +1,54 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* X11 Graphics Pipeline
*
* Copyright 2014 Marc-Andre Moreau <marcandre.moreau@gmail.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 __XF_GRAPHICS_PIPELINE_H
#define __XF_GRAPHICS_PIPELINE_H
#include "xf_client.h"
#include "xfreerdp.h"
struct xf_gfx_surface
{
UINT16 surfaceId;
UINT32 width;
UINT32 height;
BOOL alpha;
BYTE* data;
XImage* image;
int scanline;
};
typedef struct xf_gfx_surface xfGfxSurface;
struct xf_gfx_cache_entry
{
UINT64 cacheKey;
UINT32 width;
UINT32 height;
BOOL alpha;
BYTE* data;
int scanline;
};
typedef struct xf_gfx_cache_entry xfGfxCacheEntry;
int xf_OutputExpose(xfContext* xfc, int x, int y, int width, int height);
void xf_graphics_pipeline_init(xfContext* xfc, RdpgfxClientContext* gfx);
void xf_graphics_pipeline_uninit(xfContext* xfc, RdpgfxClientContext* gfx);
#endif /* __XF_GRAPHICS_PIPELINE_H */

View File

@ -145,8 +145,8 @@ void xf_Bitmap_Decompress(rdpContext* context, rdpBitmap* bitmap,
break;
case RDP_CODEC_ID_REMOTEFX:
rfx_context_set_pixel_format(xfc->rfx_context, RDP_PIXEL_FORMAT_B8G8R8A8);
msg = rfx_process_message(xfc->rfx_context, data, length);
rfx_context_set_pixel_format(xfc->rfx, RDP_PIXEL_FORMAT_B8G8R8A8);
msg = rfx_process_message(xfc->rfx, data, length);
if (msg == NULL)
{
@ -166,7 +166,7 @@ void xf_Bitmap_Decompress(rdpContext* context, rdpBitmap* bitmap,
src++;
}
}
rfx_message_free(xfc->rfx_context, msg);
rfx_message_free(xfc->rfx, msg);
}
break;

File diff suppressed because it is too large Load Diff

View File

@ -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 */

View File

@ -28,6 +28,14 @@ typedef struct xf_context xfContext;
#include "xf_monitor.h"
#include "xf_channels.h"
#include <freerdp/gdi/gdi.h>
#include <freerdp/codec/rfx.h>
#include <freerdp/codec/nsc.h>
#include <freerdp/codec/clear.h>
#include <freerdp/codec/color.h>
#include <freerdp/codec/bitmap.h>
#include <freerdp/codec/region.h>
struct xf_WorkArea
{
UINT32 x;
@ -103,6 +111,10 @@ struct xf_context
HGDI_DC hdc;
BYTE* primary_buffer;
REGION16 invalidRegion;
BOOL inGfxFrame;
BOOL graphicsReset;
UINT16 outputSurfaceId;
BOOL frame_begin;
UINT16 frame_x1;
@ -137,8 +149,9 @@ struct xf_context
VIRTUAL_SCREEN vscreen;
BYTE* bmp_codec_none;
BYTE* bmp_codec_nsc;
void* rfx_context;
void* nsc_context;
RFX_CONTEXT* rfx;
NSC_CONTEXT* nsc;
CLEAR_CONTEXT* clear;
void* xv_context;
void* clipboard_context;
@ -168,6 +181,7 @@ struct xf_context
/* Channels */
RdpeiClientContext* rdpei;
RdpgfxClientContext* gfx;
};
void xf_create_window(xfContext* xfc);

View File

@ -814,6 +814,38 @@ int freerdp_parse_username(char* username, char** user, char** domain)
return 0;
}
int freerdp_parse_hostname(char* hostname, char** host, int* port)
{
char* p;
int length;
p = strrchr(hostname, ':');
if (p)
{
length = (p - hostname);
*host = (char*) malloc(length + 1);
if (!(*host))
return -1;
CopyMemory(*host, hostname, length);
(*host)[length] = '\0';
*port = atoi(p + 1);
}
else
{
*host = _strdup(hostname);
if (!(*host))
return -1;
*port = -1;
}
return 0;
}
int freerdp_set_connection_type(rdpSettings* settings, int type)
{
settings->ConnectionType = type;
@ -1577,6 +1609,10 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings,
CommandLineSwitchCase(arg, "gfx")
{
settings->SupportGraphicsPipeline = TRUE;
settings->FastPathOutput = TRUE;
settings->ColorDepth = 32;
settings->LargePointerFlag = TRUE;
settings->FrameMarkerCommandEnabled = TRUE;
}
CommandLineSwitchCase(arg, "rfx")
{

View File

@ -63,7 +63,7 @@ BOOL freerdp_client_rdp_file_set_integer(rdpFile* file, const char* name, int va
file->ScreenModeId = value;
else if (_stricmp(name, "span monitors") == 0)
file->SpanMonitors = value;
else if (_stricmp(name, "smartsizing") == 0)
else if (_stricmp(name, "smart sizing") == 0)
file->SmartSizing = value;
else if (_stricmp(name, "enablesuperpan") == 0)
file->EnableSuperSpan = value;
@ -767,10 +767,23 @@ BOOL freerdp_client_populate_settings_from_rdp_file(rdpFile* file, rdpSettings*
free(domain);
}
if (~((size_t) file->FullAddress))
{
int port = -1;
char* host = NULL;
freerdp_parse_hostname(file->FullAddress, &host, &port);
freerdp_set_param_string(settings, FreeRDP_ServerHostname, host);
if (port > 0)
freerdp_set_param_uint32(settings, FreeRDP_ServerPort, (UINT32) port);
free(host);
}
if (~file->ServerPort)
freerdp_set_param_uint32(settings, FreeRDP_ServerPort, file->ServerPort);
if (~((size_t) file->FullAddress))
freerdp_set_param_string(settings, FreeRDP_ServerHostname, file->FullAddress);
if (~file->DesktopWidth)
freerdp_set_param_uint32(settings, FreeRDP_DesktopWidth, file->DesktopWidth);
@ -802,12 +815,12 @@ BOOL freerdp_client_populate_settings_from_rdp_file(rdpFile* file, rdpSettings*
*
* Values:
*
* 0: The remote session will appear in a window.
* 1: The remote session will appear full screen.
* 1: The remote session will appear in a window.
* 2: The remote session will appear full screen.
*/
freerdp_set_param_bool(settings, FreeRDP_Fullscreen,
(file->ScreenModeId == 1) ? TRUE : FALSE);
(file->ScreenModeId == 2) ? TRUE : FALSE);
}
if (~((size_t) file->SmartSizing))
@ -867,7 +880,19 @@ BOOL freerdp_client_populate_settings_from_rdp_file(rdpFile* file, rdpSettings*
freerdp_set_param_bool(settings, FreeRDP_CompressionEnabled, file->Compression);
if (~((size_t) file->GatewayHostname))
freerdp_set_param_string(settings, FreeRDP_GatewayHostname, file->GatewayHostname);
{
int port = -1;
char* host = NULL;
freerdp_parse_hostname(file->GatewayHostname, &host, &port);
freerdp_set_param_string(settings, FreeRDP_GatewayHostname, host);
if (port > 0)
freerdp_set_param_uint32(settings, FreeRDP_GatewayPort, (UINT32) port);
free(host);
}
if (~file->GatewayUsageMethod)
freerdp_set_gateway_usage_method(settings, file->GatewayUsageMethod);

View File

@ -303,12 +303,11 @@ void ios_freerdp_free(freerdp* instance)
void ios_init_freerdp()
{
signal(SIGPIPE, SIG_IGN);
freerdp_channels_global_init();
freerdp_register_addin_provider(freerdp_channels_load_static_addin_entry, 0);
}
void ios_uninit_freerdp()
{
freerdp_channels_global_uninit();
}

View File

@ -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})

View File

@ -27,7 +27,7 @@ option(ANDROID_BUILD_JAVA "Automatically android java code - build type depends
option(ANDROID_BUILD_JAVA_DEBUG "Create a android debug package" ${JAVA_DEBUG_DEFAULT})
set(ANDROID_APP_VERSION 3 CACHE STRING "Application version")
set(ANDROID_APP_TARGET_SDK 11 CACHE STRING "Application target android SDK")
set(ANDROID_APP_TARGET_SDK 14 CACHE STRING "Application target android SDK")
set(ANDROID_APP_MIN_SDK 9 CACHE STRING "Application minimum android SDK requirement")
set(ANDROID_APP_GOOGLE_TARGET_SDK "16" CACHE STRING "Application target google SDK")

Some files were not shown because too many files have changed in this diff Show More