Merge pull request #1923 from awakecoding/egfx
MS-RDPEGFX Initial Implementation (WIP)
This commit is contained in:
commit
d0a0f61236
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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"
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include <winpr/stream.h>
|
||||
|
||||
#include <freerdp/utils/debug.h>
|
||||
#include <freerdp/utils/svc_plugin.h>
|
||||
|
||||
struct cliprdr_plugin
|
||||
{
|
||||
|
@ -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;
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -3,8 +3,6 @@
|
||||
* Dynamic Virtual Channel Manager
|
||||
*
|
||||
* Copyright 2010-2011 Vic Lee
|
||||
* Copyright 2014 Thincast Technologies GmbH
|
||||
* Copyright 2014 Armin Novak <armin.novak@thincast.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -23,9 +21,6 @@
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@ -33,61 +28,45 @@
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/synch.h>
|
||||
#include <winpr/stream.h>
|
||||
#include <winpr/collections.h>
|
||||
|
||||
#include <freerdp/addin.h>
|
||||
|
||||
#include "drdynvc_types.h"
|
||||
#include "dvcman.h"
|
||||
static wListDictionary *cb_dict = NULL;
|
||||
struct cb_value
|
||||
{
|
||||
void *fkt;
|
||||
void *context;
|
||||
};
|
||||
|
||||
static int dvcman_get_configuration(IWTSListener *pListener, void **ppPropertyBag)
|
||||
static int dvcman_get_configuration(IWTSListener* pListener, void** ppPropertyBag)
|
||||
{
|
||||
if (!ppPropertyBag)
|
||||
{
|
||||
DEBUG_WARN("ppPropertyBag=%p", ppPropertyBag);
|
||||
return 0;
|
||||
}
|
||||
|
||||
*ppPropertyBag = NULL;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int dvcman_create_listener(IWTSVirtualChannelManager *pChannelMgr,
|
||||
const char *pszChannelName, UINT32 ulFlags,
|
||||
IWTSListenerCallback *pListenerCallback, IWTSListener **ppListener)
|
||||
static int dvcman_create_listener(IWTSVirtualChannelManager* pChannelMgr,
|
||||
const char* pszChannelName, UINT32 ulFlags,
|
||||
IWTSListenerCallback* pListenerCallback, IWTSListener** ppListener)
|
||||
{
|
||||
DVCMAN *dvcman = (DVCMAN *) pChannelMgr;
|
||||
DVCMAN_LISTENER *listener;
|
||||
assert(dvcman);
|
||||
DVCMAN* dvcman = (DVCMAN*) pChannelMgr;
|
||||
DVCMAN_LISTENER* listener;
|
||||
|
||||
if (dvcman->num_listeners < MAX_PLUGINS)
|
||||
{
|
||||
DEBUG_DVC("%d.%s.", dvcman->num_listeners, pszChannelName);
|
||||
listener = (DVCMAN_LISTENER *) calloc(1, sizeof(DVCMAN_LISTENER));
|
||||
|
||||
if (!listener)
|
||||
{
|
||||
DEBUG_WARN("calloc failed %s (%d)!", strerror(errno), errno);
|
||||
return 2;
|
||||
}
|
||||
listener = (DVCMAN_LISTENER*) malloc(sizeof(DVCMAN_LISTENER));
|
||||
ZeroMemory(listener, sizeof(DVCMAN_LISTENER));
|
||||
|
||||
listener->iface.GetConfiguration = dvcman_get_configuration;
|
||||
listener->iface.pInterface = NULL;
|
||||
|
||||
listener->dvcman = dvcman;
|
||||
listener->channel_name = _strdup(pszChannelName);
|
||||
listener->flags = ulFlags;
|
||||
listener->listener_callback = pListenerCallback;
|
||||
|
||||
if (ppListener)
|
||||
*ppListener = (IWTSListener *) listener;
|
||||
*ppListener = (IWTSListener*) listener;
|
||||
|
||||
dvcman->listeners[dvcman->num_listeners++] = (IWTSListener *) listener;
|
||||
dvcman->listeners[dvcman->num_listeners++] = (IWTSListener*) listener;
|
||||
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
@ -97,11 +76,11 @@ static int dvcman_create_listener(IWTSVirtualChannelManager *pChannelMgr,
|
||||
}
|
||||
}
|
||||
|
||||
static int dvcman_push_event(IWTSVirtualChannelManager *pChannelMgr, wMessage *pEvent)
|
||||
static int dvcman_push_event(IWTSVirtualChannelManager* pChannelMgr, wMessage* pEvent)
|
||||
{
|
||||
int status;
|
||||
DVCMAN *dvcman = (DVCMAN *) pChannelMgr;
|
||||
assert(dvcman);
|
||||
DVCMAN* dvcman = (DVCMAN*) pChannelMgr;
|
||||
|
||||
status = drdynvc_push_event(dvcman->drdynvc, pEvent);
|
||||
|
||||
if (status == 0)
|
||||
@ -116,11 +95,9 @@ static int dvcman_push_event(IWTSVirtualChannelManager *pChannelMgr, wMessage *p
|
||||
return status;
|
||||
}
|
||||
|
||||
static int dvcman_register_plugin(IDRDYNVC_ENTRY_POINTS *pEntryPoints, const char *name, IWTSPlugin *pPlugin)
|
||||
static int dvcman_register_plugin(IDRDYNVC_ENTRY_POINTS* pEntryPoints, const char* name, IWTSPlugin* pPlugin)
|
||||
{
|
||||
DVCMAN *dvcman = ((DVCMAN_ENTRY_POINTS *) pEntryPoints)->dvcman;
|
||||
assert(pEntryPoints);
|
||||
assert(dvcman);
|
||||
DVCMAN* dvcman = ((DVCMAN_ENTRY_POINTS*) pEntryPoints)->dvcman;
|
||||
|
||||
if (dvcman->num_plugins < MAX_PLUGINS)
|
||||
{
|
||||
@ -136,17 +113,15 @@ static int dvcman_register_plugin(IDRDYNVC_ENTRY_POINTS *pEntryPoints, const cha
|
||||
}
|
||||
}
|
||||
|
||||
IWTSPlugin *dvcman_get_plugin(IDRDYNVC_ENTRY_POINTS *pEntryPoints, const char *name)
|
||||
IWTSPlugin* dvcman_get_plugin(IDRDYNVC_ENTRY_POINTS* pEntryPoints, const char* name)
|
||||
{
|
||||
int i;
|
||||
DVCMAN *dvcman = ((DVCMAN_ENTRY_POINTS *) pEntryPoints)->dvcman;
|
||||
assert(pEntryPoints);
|
||||
assert(dvcman);
|
||||
DVCMAN* dvcman = ((DVCMAN_ENTRY_POINTS*) pEntryPoints)->dvcman;
|
||||
|
||||
for (i = 0; i < dvcman->num_plugins; i++)
|
||||
{
|
||||
if (dvcman->plugin_names[i] == name ||
|
||||
strcmp(dvcman->plugin_names[i], name) == 0)
|
||||
strcmp(dvcman->plugin_names[i], name) == 0)
|
||||
{
|
||||
return dvcman->plugins[i];
|
||||
}
|
||||
@ -155,28 +130,27 @@ IWTSPlugin *dvcman_get_plugin(IDRDYNVC_ENTRY_POINTS *pEntryPoints, const char *n
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ADDIN_ARGV *dvcman_get_plugin_data(IDRDYNVC_ENTRY_POINTS *pEntryPoints)
|
||||
ADDIN_ARGV* dvcman_get_plugin_data(IDRDYNVC_ENTRY_POINTS* pEntryPoints)
|
||||
{
|
||||
assert(pEntryPoints);
|
||||
return ((DVCMAN_ENTRY_POINTS *) pEntryPoints)->args;
|
||||
return ((DVCMAN_ENTRY_POINTS*) pEntryPoints)->args;
|
||||
}
|
||||
|
||||
UINT32 dvcman_get_channel_id(IWTSVirtualChannel *channel)
|
||||
UINT32 dvcman_get_channel_id(IWTSVirtualChannel * channel)
|
||||
{
|
||||
assert(channel);
|
||||
return ((DVCMAN_CHANNEL *) channel)->channel_id;
|
||||
return ((DVCMAN_CHANNEL*) channel)->channel_id;
|
||||
}
|
||||
|
||||
IWTSVirtualChannel *dvcman_find_channel_by_id(IWTSVirtualChannelManager *pChannelMgr, UINT32 ChannelId)
|
||||
IWTSVirtualChannel* dvcman_find_channel_by_id(IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelId)
|
||||
{
|
||||
int index;
|
||||
BOOL found = FALSE;
|
||||
DVCMAN_CHANNEL *channel;
|
||||
DVCMAN *dvcman = (DVCMAN *) pChannelMgr;
|
||||
assert(dvcman);
|
||||
DVCMAN_CHANNEL* channel;
|
||||
DVCMAN* dvcman = (DVCMAN*) pChannelMgr;
|
||||
|
||||
ArrayList_Lock(dvcman->channels);
|
||||
|
||||
index = 0;
|
||||
channel = (DVCMAN_CHANNEL *) ArrayList_GetItem(dvcman->channels, index++);
|
||||
channel = (DVCMAN_CHANNEL*) ArrayList_GetItem(dvcman->channels, index++);
|
||||
|
||||
while (channel)
|
||||
{
|
||||
@ -186,26 +160,25 @@ IWTSVirtualChannel *dvcman_find_channel_by_id(IWTSVirtualChannelManager *pChanne
|
||||
break;
|
||||
}
|
||||
|
||||
channel = (DVCMAN_CHANNEL *) ArrayList_GetItem(dvcman->channels, index++);
|
||||
channel = (DVCMAN_CHANNEL*) ArrayList_GetItem(dvcman->channels, index++);
|
||||
}
|
||||
|
||||
ArrayList_Unlock(dvcman->channels);
|
||||
return (found) ? ((IWTSVirtualChannel *) channel) : NULL;
|
||||
|
||||
return (found) ? ((IWTSVirtualChannel*) channel) : NULL;
|
||||
}
|
||||
|
||||
void *dvcman_get_channel_interface_by_name(IWTSVirtualChannelManager *pChannelMgr, const char *ChannelName)
|
||||
void* dvcman_get_channel_interface_by_name(IWTSVirtualChannelManager* pChannelMgr, const char* ChannelName)
|
||||
{
|
||||
int i;
|
||||
BOOL found = FALSE;
|
||||
void *pInterface = NULL;
|
||||
DVCMAN_LISTENER *listener;
|
||||
DVCMAN *dvcman = (DVCMAN *) pChannelMgr;
|
||||
assert(dvcman);
|
||||
void* pInterface = NULL;
|
||||
DVCMAN_LISTENER* listener;
|
||||
DVCMAN* dvcman = (DVCMAN*) pChannelMgr;
|
||||
|
||||
for (i = 0; i < dvcman->num_listeners; i++)
|
||||
{
|
||||
listener = (DVCMAN_LISTENER *) dvcman->listeners[i];
|
||||
assert(listener);
|
||||
listener = (DVCMAN_LISTENER*) dvcman->listeners[i];
|
||||
|
||||
if (strcmp(listener->channel_name, ChannelName) == 0)
|
||||
{
|
||||
@ -218,16 +191,11 @@ void *dvcman_get_channel_interface_by_name(IWTSVirtualChannelManager *pChannelMg
|
||||
return (found) ? pInterface : NULL;
|
||||
}
|
||||
|
||||
IWTSVirtualChannelManager *dvcman_new(drdynvcPlugin *plugin)
|
||||
IWTSVirtualChannelManager* dvcman_new(drdynvcPlugin* plugin)
|
||||
{
|
||||
DVCMAN *dvcman;
|
||||
dvcman = (DVCMAN *) calloc(1,sizeof(DVCMAN));
|
||||
DVCMAN* dvcman;
|
||||
|
||||
if (!dvcman)
|
||||
{
|
||||
DEBUG_WARN("calloc failed %s (%d)!", strerror(errno), errno);
|
||||
return NULL;
|
||||
}
|
||||
dvcman = (DVCMAN*) calloc(1, sizeof(DVCMAN));
|
||||
|
||||
dvcman->iface.CreateListener = dvcman_create_listener;
|
||||
dvcman->iface.PushEvent = dvcman_push_event;
|
||||
@ -235,68 +203,71 @@ IWTSVirtualChannelManager *dvcman_new(drdynvcPlugin *plugin)
|
||||
dvcman->iface.GetChannelId = dvcman_get_channel_id;
|
||||
dvcman->drdynvc = plugin;
|
||||
dvcman->channels = ArrayList_New(TRUE);
|
||||
return (IWTSVirtualChannelManager *) dvcman;
|
||||
dvcman->pool = StreamPool_New(TRUE, 10);
|
||||
|
||||
return (IWTSVirtualChannelManager*) dvcman;
|
||||
}
|
||||
|
||||
int dvcman_load_addin(IWTSVirtualChannelManager *pChannelMgr, ADDIN_ARGV *args)
|
||||
int dvcman_load_addin(IWTSVirtualChannelManager* pChannelMgr, ADDIN_ARGV* args)
|
||||
{
|
||||
DVCMAN_ENTRY_POINTS entryPoints;
|
||||
PDVC_PLUGIN_ENTRY pDVCPluginEntry = NULL;
|
||||
assert(args);
|
||||
|
||||
fprintf(stderr, "Loading Dynamic Virtual Channel %s\n", args->argv[0]);
|
||||
|
||||
pDVCPluginEntry = (PDVC_PLUGIN_ENTRY) freerdp_load_channel_addin_entry(args->argv[0],
|
||||
NULL, NULL, FREERDP_ADDIN_CHANNEL_DYNAMIC);
|
||||
NULL, NULL, FREERDP_ADDIN_CHANNEL_DYNAMIC);
|
||||
|
||||
if (pDVCPluginEntry)
|
||||
{
|
||||
entryPoints.iface.RegisterPlugin = dvcman_register_plugin;
|
||||
entryPoints.iface.GetPlugin = dvcman_get_plugin;
|
||||
entryPoints.iface.GetPluginData = dvcman_get_plugin_data;
|
||||
entryPoints.dvcman = (DVCMAN *) pChannelMgr;
|
||||
entryPoints.dvcman = (DVCMAN*) pChannelMgr;
|
||||
entryPoints.args = args;
|
||||
pDVCPluginEntry((IDRDYNVC_ENTRY_POINTS *) &entryPoints);
|
||||
|
||||
pDVCPluginEntry((IDRDYNVC_ENTRY_POINTS*) &entryPoints);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void dvcman_channel_free(DVCMAN_CHANNEL *channel)
|
||||
static void dvcman_channel_free(DVCMAN_CHANNEL* channel)
|
||||
{
|
||||
assert(channel);
|
||||
|
||||
if (channel->channel_callback)
|
||||
channel->channel_callback->OnClose(channel->channel_callback);
|
||||
|
||||
if (channel->channel_name)
|
||||
free(channel->channel_name);
|
||||
DeleteCriticalSection(&(channel->lock));
|
||||
|
||||
free(channel);
|
||||
}
|
||||
|
||||
void dvcman_free(IWTSVirtualChannelManager *pChannelMgr)
|
||||
void dvcman_free(IWTSVirtualChannelManager* pChannelMgr)
|
||||
{
|
||||
int i;
|
||||
int count;
|
||||
IWTSPlugin *pPlugin;
|
||||
DVCMAN_LISTENER *listener;
|
||||
DVCMAN_CHANNEL *channel;
|
||||
DVCMAN *dvcman = (DVCMAN *) pChannelMgr;
|
||||
assert(dvcman);
|
||||
IWTSPlugin* pPlugin;
|
||||
DVCMAN_LISTENER* listener;
|
||||
DVCMAN_CHANNEL* channel;
|
||||
DVCMAN* dvcman = (DVCMAN*) pChannelMgr;
|
||||
|
||||
ArrayList_Lock(dvcman->channels);
|
||||
|
||||
count = ArrayList_Count(dvcman->channels);
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
channel = (DVCMAN_CHANNEL *) ArrayList_GetItem(dvcman->channels, i);
|
||||
channel = (DVCMAN_CHANNEL*) ArrayList_GetItem(dvcman->channels, i);
|
||||
dvcman_channel_free(channel);
|
||||
}
|
||||
|
||||
ArrayList_Unlock(dvcman->channels);
|
||||
|
||||
ArrayList_Free(dvcman->channels);
|
||||
|
||||
for (i = 0; i < dvcman->num_listeners; i++)
|
||||
{
|
||||
listener = (DVCMAN_LISTENER *) dvcman->listeners[i];
|
||||
listener = (DVCMAN_LISTENER*) dvcman->listeners[i];
|
||||
free(listener->channel_name);
|
||||
free(listener);
|
||||
}
|
||||
@ -309,15 +280,15 @@ void dvcman_free(IWTSVirtualChannelManager *pChannelMgr)
|
||||
pPlugin->Terminated(pPlugin);
|
||||
}
|
||||
|
||||
StreamPool_Free(dvcman->pool);
|
||||
free(dvcman);
|
||||
}
|
||||
|
||||
int dvcman_init(IWTSVirtualChannelManager *pChannelMgr)
|
||||
int dvcman_init(IWTSVirtualChannelManager* pChannelMgr)
|
||||
{
|
||||
int i;
|
||||
IWTSPlugin *pPlugin;
|
||||
DVCMAN *dvcman = (DVCMAN *) pChannelMgr;
|
||||
assert(dvcman);
|
||||
IWTSPlugin* pPlugin;
|
||||
DVCMAN* dvcman = (DVCMAN*) pChannelMgr;
|
||||
|
||||
for (i = 0; i < dvcman->num_plugins; i++)
|
||||
{
|
||||
@ -330,83 +301,88 @@ int dvcman_init(IWTSVirtualChannelManager *pChannelMgr)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dvcman_write_channel(IWTSVirtualChannel *pChannel, UINT32 cbSize, BYTE *pBuffer, void *pReserved)
|
||||
static int dvcman_write_channel(IWTSVirtualChannel* pChannel, UINT32 cbSize, BYTE* pBuffer, void* pReserved)
|
||||
{
|
||||
int status;
|
||||
DVCMAN_CHANNEL *channel = (DVCMAN_CHANNEL *) pChannel;
|
||||
assert(channel);
|
||||
WaitForSingleObject(channel->dvc_chan_mutex, INFINITE);
|
||||
DVCMAN_CHANNEL* channel = (DVCMAN_CHANNEL*) pChannel;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
static int dvcman_close_channel_iface(IWTSVirtualChannel *pChannel)
|
||||
static int dvcman_close_channel_iface(IWTSVirtualChannel* pChannel)
|
||||
{
|
||||
DVCMAN_CHANNEL *channel = (DVCMAN_CHANNEL *) pChannel;
|
||||
DVCMAN *dvcman = channel->dvcman;
|
||||
assert(channel);
|
||||
assert(dvcman);
|
||||
DVCMAN_CHANNEL* channel = (DVCMAN_CHANNEL*) pChannel;
|
||||
DVCMAN* dvcman = channel->dvcman;
|
||||
|
||||
DEBUG_DVC("id=%d", channel->channel_id);
|
||||
|
||||
ArrayList_Remove(dvcman->channels, channel);
|
||||
|
||||
dvcman_channel_free(channel);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int dvcman_create_channel(IWTSVirtualChannelManager *pChannelMgr, UINT32 ChannelId, const char *ChannelName)
|
||||
int dvcman_create_channel(IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelId, const char* ChannelName)
|
||||
{
|
||||
int i;
|
||||
int bAccept;
|
||||
DVCMAN_LISTENER *listener;
|
||||
DVCMAN_CHANNEL *channel;
|
||||
DrdynvcClientContext *context;
|
||||
IWTSVirtualChannelCallback *pCallback;
|
||||
DVCMAN *dvcman = (DVCMAN *) pChannelMgr;
|
||||
channel = (DVCMAN_CHANNEL *) calloc(1, sizeof(DVCMAN_CHANNEL));
|
||||
DVCMAN_LISTENER* listener;
|
||||
DVCMAN_CHANNEL* channel;
|
||||
DrdynvcClientContext* context;
|
||||
IWTSVirtualChannelCallback* pCallback;
|
||||
DVCMAN* dvcman = (DVCMAN*) pChannelMgr;
|
||||
|
||||
channel = (DVCMAN_CHANNEL*) calloc(1, sizeof(DVCMAN_CHANNEL));
|
||||
|
||||
if (!channel)
|
||||
{
|
||||
DEBUG_WARN("calloc failed %s (%d)!", strerror(errno), errno);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ZeroMemory(channel, sizeof(DVCMAN_CHANNEL));
|
||||
channel->dvcman = dvcman;
|
||||
channel->channel_id = ChannelId;
|
||||
channel->channel_name = _strdup(ChannelName);
|
||||
|
||||
for (i = 0; i < dvcman->num_listeners; i++)
|
||||
{
|
||||
listener = (DVCMAN_LISTENER *) dvcman->listeners[i];
|
||||
assert(listener);
|
||||
listener = (DVCMAN_LISTENER*) dvcman->listeners[i];
|
||||
|
||||
if (strcmp(listener->channel_name, ChannelName) == 0)
|
||||
{
|
||||
channel->iface.Write = dvcman_write_channel;
|
||||
channel->iface.Close = dvcman_close_channel_iface;
|
||||
channel->dvc_chan_mutex = CreateMutex(NULL, FALSE, NULL);
|
||||
|
||||
InitializeCriticalSection(&(channel->lock));
|
||||
|
||||
bAccept = 1;
|
||||
pCallback = NULL;
|
||||
assert(listener->listener_callback);
|
||||
assert(listener->listener_callback->OnNewChannelConnection);
|
||||
|
||||
if (listener->listener_callback->OnNewChannelConnection(listener->listener_callback,
|
||||
(IWTSVirtualChannel *) channel, NULL, &bAccept, &pCallback) == 0 && bAccept == 1)
|
||||
(IWTSVirtualChannel*) channel, NULL, &bAccept, &pCallback) == 0 && bAccept == 1)
|
||||
{
|
||||
DEBUG_DVC("listener %s created new channel %d",
|
||||
listener->channel_name, channel->channel_id);
|
||||
listener->channel_name, channel->channel_id);
|
||||
|
||||
channel->status = 0;
|
||||
channel->channel_callback = pCallback;
|
||||
channel->pInterface = listener->iface.pInterface;
|
||||
assert(dvcman->drdynvc);
|
||||
|
||||
ArrayList_Add(dvcman->channels, channel);
|
||||
|
||||
context = dvcman->drdynvc->context;
|
||||
IFCALL(context->OnChannelConnected, context, ChannelName, listener->iface.pInterface);
|
||||
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_WARN("channel rejected by plugin");
|
||||
|
||||
free(channel);
|
||||
return 1;
|
||||
}
|
||||
@ -417,14 +393,36 @@ int dvcman_create_channel(IWTSVirtualChannelManager *pChannelMgr, UINT32 Channel
|
||||
return 1;
|
||||
}
|
||||
|
||||
int dvcman_close_channel(IWTSVirtualChannelManager *pChannelMgr, UINT32 ChannelId)
|
||||
int dvcman_open_channel(IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelId)
|
||||
{
|
||||
DVCMAN_CHANNEL *channel;
|
||||
IWTSVirtualChannel *ichannel;
|
||||
DrdynvcClientContext *context;
|
||||
DVCMAN *dvcman = (DVCMAN *) pChannelMgr;
|
||||
assert(dvcman);
|
||||
channel = (DVCMAN_CHANNEL *) dvcman_find_channel_by_id(pChannelMgr, 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;
|
||||
IWTSVirtualChannel* ichannel;
|
||||
DrdynvcClientContext* context;
|
||||
DVCMAN* dvcman = (DVCMAN*) pChannelMgr;
|
||||
|
||||
channel = (DVCMAN_CHANNEL*) dvcman_find_channel_by_id(pChannelMgr, ChannelId);
|
||||
|
||||
if (!channel)
|
||||
{
|
||||
@ -434,27 +432,31 @@ 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;
|
||||
}
|
||||
|
||||
if (channel->status == 0)
|
||||
{
|
||||
assert(dvcman->drdynvc);
|
||||
context = dvcman->drdynvc->context;
|
||||
|
||||
IFCALL(context->OnChannelDisconnected, context, channel->channel_name, channel->pInterface);
|
||||
|
||||
free(channel->channel_name);
|
||||
|
||||
DEBUG_DVC("dvcman_close_channel: channel %d closed", ChannelId);
|
||||
ichannel = (IWTSVirtualChannel *) channel;
|
||||
ichannel = (IWTSVirtualChannel*) channel;
|
||||
ichannel->Close(ichannel);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dvcman_receive_channel_data_first(IWTSVirtualChannelManager *pChannelMgr, UINT32 ChannelId, UINT32 length)
|
||||
int dvcman_receive_channel_data_first(IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelId, UINT32 length)
|
||||
{
|
||||
DVCMAN_CHANNEL *channel;
|
||||
channel = (DVCMAN_CHANNEL *) dvcman_find_channel_by_id(pChannelMgr, ChannelId);
|
||||
DVCMAN_CHANNEL* channel;
|
||||
|
||||
channel = (DVCMAN_CHANNEL*) dvcman_find_channel_by_id(pChannelMgr, ChannelId);
|
||||
|
||||
if (!channel)
|
||||
{
|
||||
@ -463,17 +465,21 @@ 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 = StreamPool_Take(channel->dvcman->pool, length);
|
||||
Stream_AddRef(channel->dvc_data);
|
||||
|
||||
channel->dvc_data = Stream_New(NULL, length);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dvcman_receive_channel_data(IWTSVirtualChannelManager *pChannelMgr, UINT32 ChannelId, BYTE *data, UINT32 data_size)
|
||||
int dvcman_receive_channel_data(IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelId, wStream* data)
|
||||
{
|
||||
int error = 0;
|
||||
DVCMAN_CHANNEL *channel;
|
||||
channel = (DVCMAN_CHANNEL *) dvcman_find_channel_by_id(pChannelMgr, ChannelId);
|
||||
int status = 0;
|
||||
DVCMAN_CHANNEL* channel;
|
||||
UINT32 dataSize = Stream_GetRemainingLength(data);
|
||||
|
||||
channel = (DVCMAN_CHANNEL*) dvcman_find_channel_by_id(pChannelMgr, ChannelId);
|
||||
|
||||
if (!channel)
|
||||
{
|
||||
@ -484,135 +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
|
||||
{
|
||||
assert(channel->channel_callback);
|
||||
assert(channel->channel_callback->OnDataReceived);
|
||||
error = channel->channel_callback->OnDataReceived(channel->channel_callback, data_size, data);
|
||||
status = channel->channel_callback->OnDataReceived(channel->channel_callback, data);
|
||||
}
|
||||
|
||||
return error;
|
||||
return status;
|
||||
}
|
||||
|
||||
static void dump_callbacks(void)
|
||||
{
|
||||
wListDictionaryItem *cur;
|
||||
DEBUG_DVC("Dumping all currently registered callbacks");
|
||||
|
||||
if (!cb_dict)
|
||||
{
|
||||
DEBUG_DVC("cb_dict=NULL");
|
||||
return;
|
||||
}
|
||||
|
||||
cur = cb_dict->head;
|
||||
|
||||
while (cur)
|
||||
{
|
||||
DEBUG_DVC("cb_dict %s:%p", cur->key, cur->value);
|
||||
cur = cur->next;
|
||||
}
|
||||
}
|
||||
|
||||
void *get_callback_by_name(const char *name, void **context)
|
||||
{
|
||||
struct cb_value *rc;
|
||||
|
||||
if (!cb_dict)
|
||||
{
|
||||
DEBUG_WARN("'%s' not found, function list does not exist.",
|
||||
name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!ListDictionary_Contains(cb_dict, (void *)name))
|
||||
{
|
||||
DEBUG_WARN("'%s' not found", name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
rc = ListDictionary_GetItemValue(cb_dict, (void *)name);
|
||||
DEBUG_DVC("'%s'=%p found", name, rc);
|
||||
|
||||
if (context)
|
||||
*context = rc->context;
|
||||
|
||||
return rc->fkt;
|
||||
}
|
||||
|
||||
static BOOL callback_key_cmp(void *a, void *b)
|
||||
{
|
||||
return strcmp(a, b) ? FALSE : TRUE;
|
||||
}
|
||||
|
||||
void add_callback_by_name(const char *name, void *fkt, void *context)
|
||||
{
|
||||
struct cb_value *value = calloc(1, sizeof(struct cb_value));
|
||||
|
||||
if (!value)
|
||||
{
|
||||
DEBUG_WARN("calloc failed %s (%d)!", strerror(errno), errno);
|
||||
assert(FALSE);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!cb_dict)
|
||||
{
|
||||
DEBUG_DVC("Function list is empty, allocating new.");
|
||||
cb_dict = ListDictionary_New(TRUE);
|
||||
ListDictionary_KeyObject(cb_dict)->fnObjectEquals = callback_key_cmp;
|
||||
}
|
||||
|
||||
value->fkt = fkt;
|
||||
value->context = context;
|
||||
DEBUG_DVC("Adding '%s'=%p to function list.", name, fkt);
|
||||
ListDictionary_Add(cb_dict, (void *)name, value);
|
||||
dump_callbacks();
|
||||
}
|
||||
|
||||
void remove_callback_by_name(const char *name, void *context)
|
||||
{
|
||||
if (!cb_dict)
|
||||
{
|
||||
DEBUG_WARN("trying to remove '%s', but function list does not exist.",
|
||||
name);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ListDictionary_Contains(cb_dict, (void *)name))
|
||||
{
|
||||
DEBUG_WARN("trying to remove '%s', which is not in function list.",
|
||||
name);
|
||||
return;
|
||||
}
|
||||
|
||||
DEBUG_DVC("Removing '%s' from function list.", name);
|
||||
ListDictionary_Remove(cb_dict, (void *)name);
|
||||
|
||||
if (ListDictionary_Count(cb_dict) < 1)
|
||||
{
|
||||
DEBUG_DVC("Function list is empty, freeing resources.");
|
||||
ListDictionary_Free(cb_dict);
|
||||
cb_dict = NULL;
|
||||
}
|
||||
|
||||
dump_callbacks();
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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 |
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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}
|
||||
|
111
channels/rdpgfx/client/rdpgfx_codec.c
Normal file
111
channels/rdpgfx/client/rdpgfx_codec.c
Normal 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;
|
||||
}
|
@ -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 */
|
@ -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;
|
||||
}
|
||||
|
@ -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
@ -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 */
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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()
|
||||
|
@ -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})
|
@ -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")
|
@ -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
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -114,9 +114,7 @@ BOOL tsmf_push_event(IWTSVirtualChannelCallback *pChannelCallback, wMessage *eve
|
||||
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;
|
||||
@ -126,14 +124,17 @@ static int tsmf_on_data_received(IWTSVirtualChannelCallback *pChannelCallback,
|
||||
UINT32 MessageId;
|
||||
UINT32 FunctionId;
|
||||
UINT32 InterfaceId;
|
||||
TSMF_CHANNEL_CALLBACK *callback = (TSMF_CHANNEL_CALLBACK *) pChannelCallback;
|
||||
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)
|
||||
{
|
||||
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);
|
||||
@ -250,7 +251,7 @@ static int tsmf_on_data_received(IWTSVirtualChannelCallback *pChannelCallback,
|
||||
default:
|
||||
break;
|
||||
}
|
||||
Stream_Free(input, FALSE);
|
||||
|
||||
input = NULL;
|
||||
ifman.input = NULL;
|
||||
if(status == -1)
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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>
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -154,9 +154,9 @@ int main(int argc, char *argv[])
|
||||
fprintf(fp, "\t\t\t\t\t<para>%s</para>\n", format);
|
||||
fprintf(fp, "\t\t\t\t</listitem>\n");
|
||||
fprintf(fp, "\t\t\t</varlistentry>\n");
|
||||
free(name);
|
||||
free(format);
|
||||
free(text);
|
||||
free((void*) name);
|
||||
free((void*) format);
|
||||
free((void*) text);
|
||||
}
|
||||
fprintf(fp, "\t\t</variablelist>\n");
|
||||
fprintf(fp, "\t</refsect1>\n");
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -762,16 +762,18 @@ BOOL xf_post_connect(freerdp *instance)
|
||||
rdpChannels *channels;
|
||||
rdpSettings *settings;
|
||||
ResizeWindowEventArgs e;
|
||||
RFX_CONTEXT *rfx_context = NULL;
|
||||
NSC_CONTEXT *nsc_context = NULL;
|
||||
xfContext *xfc = (xfContext *) instance->context;
|
||||
xfContext* xfc = (xfContext*) instance->context;
|
||||
|
||||
cache = instance->context->cache;
|
||||
channels = instance->context->channels;
|
||||
settings = instance->settings;
|
||||
if(!xf_get_pixmap_info(xfc))
|
||||
|
||||
if (!xf_get_pixmap_info(xfc))
|
||||
return FALSE;
|
||||
|
||||
xf_register_graphics(instance->context->graphics);
|
||||
if(xfc->settings->SoftwareGdi)
|
||||
|
||||
if (xfc->settings->SoftwareGdi)
|
||||
{
|
||||
rdpGdi *gdi;
|
||||
UINT32 flags;
|
||||
@ -783,24 +785,26 @@ BOOL xf_post_connect(freerdp *instance)
|
||||
gdi_init(instance, flags, NULL);
|
||||
gdi = instance->context->gdi;
|
||||
xfc->primary_buffer = gdi->primary_buffer;
|
||||
rfx_context = gdi->rfx_context;
|
||||
|
||||
xfc->rfx = gdi->rfx_context;
|
||||
}
|
||||
else
|
||||
{
|
||||
xfc->srcBpp = instance->settings->ColorDepth;
|
||||
xf_gdi_register_update_callbacks(instance->update);
|
||||
xfc->hdc = gdi_CreateDC(xfc->clrconv, xfc->bpp);
|
||||
if(instance->settings->RemoteFxCodec)
|
||||
|
||||
if (instance->settings->RemoteFxCodec)
|
||||
{
|
||||
rfx_context = (void *) rfx_context_new(FALSE);
|
||||
xfc->rfx_context = rfx_context;
|
||||
xfc->rfx = rfx_context_new(FALSE);
|
||||
}
|
||||
if(instance->settings->NSCodec)
|
||||
|
||||
if (instance->settings->NSCodec)
|
||||
{
|
||||
nsc_context = (void *) nsc_context_new();
|
||||
xfc->nsc_context = nsc_context;
|
||||
xfc->nsc = nsc_context_new();
|
||||
}
|
||||
}
|
||||
|
||||
xfc->originalWidth = settings->DesktopWidth;
|
||||
xfc->originalHeight = settings->DesktopHeight;
|
||||
xfc->currentWidth = xfc->originalWidth;
|
||||
@ -810,12 +814,17 @@ BOOL xf_post_connect(freerdp *instance)
|
||||
xfc->offset_y = 0;
|
||||
xfc->width = settings->DesktopWidth;
|
||||
xfc->height = settings->DesktopHeight;
|
||||
if(settings->RemoteApplicationMode)
|
||||
|
||||
if (settings->RemoteApplicationMode)
|
||||
xfc->remote_app = TRUE;
|
||||
|
||||
xf_create_window(xfc);
|
||||
|
||||
ZeroMemory(&gcv, sizeof(gcv));
|
||||
|
||||
if(xfc->modifierMap)
|
||||
XFreeModifiermap(xfc->modifierMap);
|
||||
|
||||
xfc->modifierMap = XGetModifierMapping(xfc->display);
|
||||
xfc->gc = XCreateGC(xfc->display, xfc->drawable, GCGraphicsExposures, &gcv);
|
||||
xfc->primary = XCreatePixmap(xfc->display, xfc->drawable, xfc->width, xfc->height, xfc->depth);
|
||||
@ -830,7 +839,8 @@ BOOL xf_post_connect(freerdp *instance)
|
||||
xfc->image = XCreateImage(xfc->display, xfc->visual, xfc->depth, ZPixmap, 0,
|
||||
(char *) xfc->primary_buffer, xfc->width, xfc->height, xfc->scanline_pad, 0);
|
||||
xfc->bmp_codec_none = (BYTE *) malloc(64 * 64 * 4);
|
||||
if(xfc->settings->SoftwareGdi)
|
||||
|
||||
if (xfc->settings->SoftwareGdi)
|
||||
{
|
||||
instance->update->BeginPaint = xf_sw_begin_paint;
|
||||
instance->update->EndPaint = xf_sw_end_paint;
|
||||
@ -842,8 +852,10 @@ BOOL xf_post_connect(freerdp *instance)
|
||||
instance->update->EndPaint = xf_hw_end_paint;
|
||||
instance->update->DesktopResize = xf_hw_desktop_resize;
|
||||
}
|
||||
|
||||
pointer_cache_register_callbacks(instance->update);
|
||||
if(!xfc->settings->SoftwareGdi)
|
||||
|
||||
if (!xfc->settings->SoftwareGdi)
|
||||
{
|
||||
glyph_cache_register_callbacks(instance->update);
|
||||
brush_cache_register_callbacks(instance->update);
|
||||
@ -851,16 +863,19 @@ BOOL xf_post_connect(freerdp *instance)
|
||||
offscreen_cache_register_callbacks(instance->update);
|
||||
palette_cache_register_callbacks(instance->update);
|
||||
}
|
||||
|
||||
instance->context->rail = rail_new(instance->settings);
|
||||
rail_register_update_callbacks(instance->context->rail, instance->update);
|
||||
xf_rail_register_callbacks(xfc, instance->context->rail);
|
||||
freerdp_channels_post_connect(channels, instance);
|
||||
xf_tsmf_init(xfc, xv_port);
|
||||
xf_cliprdr_init(xfc, channels);
|
||||
|
||||
EventArgsInit(&e, "xfreerdp");
|
||||
e.width = settings->DesktopWidth;
|
||||
e.height = settings->DesktopHeight;
|
||||
PubSub_OnResizeWindow(((rdpContext *) xfc)->pubSub, xfc, &e);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@ -970,79 +985,102 @@ void xf_process_channel_event(rdpChannels *channels, freerdp *instance)
|
||||
|
||||
void xf_window_free(xfContext *xfc)
|
||||
{
|
||||
rdpContext *context = (rdpContext *) xfc;
|
||||
rdpContext* context = (rdpContext*) xfc;
|
||||
|
||||
xf_keyboard_free(xfc);
|
||||
if(xfc->gc)
|
||||
|
||||
if (xfc->gc)
|
||||
{
|
||||
XFreeGC(xfc->display, xfc->gc);
|
||||
xfc->gc = 0;
|
||||
}
|
||||
if(xfc->gc_mono)
|
||||
|
||||
if (xfc->gc_mono)
|
||||
{
|
||||
XFreeGC(xfc->display, xfc->gc_mono);
|
||||
xfc->gc_mono = 0;
|
||||
}
|
||||
if(xfc->window)
|
||||
|
||||
if (xfc->window)
|
||||
{
|
||||
xf_DestroyWindow(xfc, xfc->window);
|
||||
xfc->window = NULL;
|
||||
}
|
||||
if(xfc->primary)
|
||||
|
||||
if (xfc->primary)
|
||||
{
|
||||
XFreePixmap(xfc->display, xfc->primary);
|
||||
xfc->primary = 0;
|
||||
}
|
||||
if(xfc->bitmap_mono)
|
||||
|
||||
if (xfc->bitmap_mono)
|
||||
{
|
||||
XFreePixmap(xfc->display, xfc->bitmap_mono);
|
||||
xfc->bitmap_mono = 0;
|
||||
}
|
||||
if(xfc->image)
|
||||
|
||||
if (xfc->image)
|
||||
{
|
||||
xfc->image->data = NULL;
|
||||
XDestroyImage(xfc->image);
|
||||
xfc->image = NULL;
|
||||
}
|
||||
if(context->cache)
|
||||
|
||||
if (context->cache)
|
||||
{
|
||||
cache_free(context->cache);
|
||||
context->cache = NULL;
|
||||
}
|
||||
if(context->rail)
|
||||
|
||||
if (context->rail)
|
||||
{
|
||||
rail_free(context->rail);
|
||||
context->rail = NULL;
|
||||
}
|
||||
if(xfc->rfx_context)
|
||||
|
||||
if (xfc->rfx)
|
||||
{
|
||||
rfx_context_free(xfc->rfx_context);
|
||||
xfc->rfx_context = NULL;
|
||||
rfx_context_free(xfc->rfx);
|
||||
xfc->rfx = NULL;
|
||||
}
|
||||
if(xfc->nsc_context)
|
||||
|
||||
if (xfc->nsc)
|
||||
{
|
||||
nsc_context_free(xfc->nsc_context);
|
||||
xfc->nsc_context = NULL;
|
||||
nsc_context_free(xfc->nsc);
|
||||
xfc->nsc = NULL;
|
||||
}
|
||||
if(xfc->clrconv)
|
||||
|
||||
if (xfc->clear)
|
||||
{
|
||||
clear_context_free(xfc->clear);
|
||||
xfc->clear = NULL;
|
||||
}
|
||||
|
||||
if (xfc->clrconv)
|
||||
{
|
||||
freerdp_clrconv_free(xfc->clrconv);
|
||||
xfc->clrconv = NULL;
|
||||
}
|
||||
if(xfc->hdc)
|
||||
|
||||
if (xfc->hdc)
|
||||
{
|
||||
gdi_DeleteDC(xfc->hdc);
|
||||
if(xfc->xv_context)
|
||||
}
|
||||
|
||||
if (xfc->xv_context)
|
||||
{
|
||||
xf_tsmf_uninit(xfc);
|
||||
xfc->xv_context = NULL;
|
||||
}
|
||||
if(xfc->clipboard_context)
|
||||
|
||||
if (xfc->clipboard_context)
|
||||
{
|
||||
xf_cliprdr_uninit(xfc);
|
||||
xfc->clipboard_context = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void *xf_update_thread(void *arg)
|
||||
void* xf_update_thread(void *arg)
|
||||
{
|
||||
int status;
|
||||
wMessage message;
|
||||
@ -1460,12 +1498,11 @@ static void xfreerdp_client_global_init()
|
||||
{
|
||||
setlocale(LC_ALL, "");
|
||||
freerdp_handle_signals();
|
||||
freerdp_channels_global_init();
|
||||
}
|
||||
|
||||
static void xfreerdp_client_global_uninit()
|
||||
{
|
||||
freerdp_channels_global_uninit();
|
||||
|
||||
}
|
||||
|
||||
static int xfreerdp_client_start(rdpContext *context)
|
||||
|
@ -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
|
||||
|
@ -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
672
client/X11/xf_gfx.c
Normal 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
54
client/X11/xf_gfx.h
Normal 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 */
|
@ -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;
|
||||
|
||||
|
@ -299,15 +299,16 @@ static const char *get_shm_id()
|
||||
return shm_id;
|
||||
}
|
||||
|
||||
xfWindow *xf_CreateDesktopWindow(xfContext *xfc, char *name, int width, int height, BOOL decorations)
|
||||
xfWindow* xf_CreateDesktopWindow(xfContext *xfc, char *name, int width, int height, BOOL decorations)
|
||||
{
|
||||
xfWindow *window;
|
||||
xfWindow* window;
|
||||
XEvent xevent;
|
||||
rdpSettings *settings;
|
||||
window = (xfWindow *) malloc(sizeof(xfWindow));
|
||||
ZeroMemory(window, sizeof(xfWindow));
|
||||
rdpSettings* settings;
|
||||
window = (xfWindow*) calloc(1, sizeof(xfWindow));
|
||||
|
||||
settings = xfc->instance->settings;
|
||||
if(window)
|
||||
|
||||
if (window)
|
||||
{
|
||||
int input_mask;
|
||||
XClassHint *class_hints;
|
||||
@ -322,48 +323,65 @@ xfWindow *xf_CreateDesktopWindow(xfContext *xfc, char *name, int width, int heig
|
||||
xfc->workArea.x, xfc->workArea.y, xfc->workArea.width, xfc->workArea.height, 0, xfc->depth, InputOutput, xfc->visual,
|
||||
CWBackPixel | CWBackingStore | CWOverrideRedirect | CWColormap |
|
||||
CWBorderPixel | CWWinGravity | CWBitGravity, &xfc->attribs);
|
||||
|
||||
window->shmid = shm_open(get_shm_id(), O_CREAT | O_EXCL | O_RDWR, S_IREAD | S_IWRITE);
|
||||
if(window->shmid < 0)
|
||||
|
||||
if (window->shmid < 0)
|
||||
{
|
||||
DEBUG_X11("xf_CreateDesktopWindow: failed to get access to shared memory - shmget()\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
void* mem;
|
||||
|
||||
ftruncate(window->shmid, sizeof(window->handle));
|
||||
window->xfwin = mmap(0, sizeof(window->handle), PROT_READ | PROT_WRITE, MAP_SHARED, window->shmid, 0);
|
||||
if(window->xfwin == (int *) -1)
|
||||
|
||||
mem = mmap(0, sizeof(window->handle), PROT_READ | PROT_WRITE, MAP_SHARED, window->shmid, 0);
|
||||
|
||||
if (mem == ((int*) -1))
|
||||
{
|
||||
DEBUG_X11("xf_CreateDesktopWindow: failed to assign pointer to the memory address - shmat()\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
window->xfwin = mem;
|
||||
*window->xfwin = window->handle;
|
||||
}
|
||||
}
|
||||
|
||||
class_hints = XAllocClassHint();
|
||||
if(class_hints)
|
||||
|
||||
if (class_hints)
|
||||
{
|
||||
class_hints->res_name = "xfreerdp";
|
||||
if(xfc->instance->settings->WmClass)
|
||||
|
||||
if (xfc->instance->settings->WmClass)
|
||||
class_hints->res_class = xfc->instance->settings->WmClass;
|
||||
else
|
||||
class_hints->res_class = "xfreerdp";
|
||||
|
||||
XSetClassHint(xfc->display, window->handle, class_hints);
|
||||
XFree(class_hints);
|
||||
}
|
||||
|
||||
xf_ResizeDesktopWindow(xfc, window, width, height);
|
||||
xf_SetWindowDecorations(xfc, window, decorations);
|
||||
xf_SetWindowPID(xfc, window, 0);
|
||||
|
||||
input_mask =
|
||||
KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |
|
||||
VisibilityChangeMask | FocusChangeMask | StructureNotifyMask |
|
||||
PointerMotionMask | ExposureMask | PropertyChangeMask;
|
||||
if(xfc->grab_keyboard)
|
||||
|
||||
if (xfc->grab_keyboard)
|
||||
input_mask |= EnterWindowMask | LeaveWindowMask;
|
||||
|
||||
XChangeProperty(xfc->display, window->handle, xfc->_NET_WM_ICON, XA_CARDINAL, 32,
|
||||
PropModeReplace, (BYTE *) xf_icon_prop, ARRAYSIZE(xf_icon_prop));
|
||||
if(xfc->settings->ParentWindowId)
|
||||
|
||||
if (xfc->settings->ParentWindowId)
|
||||
XReparentWindow(xfc->display, window->handle, (Window) xfc->settings->ParentWindowId, 0, 0);
|
||||
|
||||
XSelectInput(xfc->display, window->handle, input_mask);
|
||||
XClearWindow(xfc->display, window->handle);
|
||||
XMapWindow(xfc->display, window->handle);
|
||||
@ -382,15 +400,14 @@ xfWindow *xf_CreateDesktopWindow(xfContext *xfc, char *name, int width, int heig
|
||||
* monitor instead of the upper-left monitor for remote app mode(which uses all monitors).
|
||||
* This extra call after the window is mapped will position the login window correctly
|
||||
*/
|
||||
if(xfc->instance->settings->RemoteApplicationMode)
|
||||
if (xfc->instance->settings->RemoteApplicationMode)
|
||||
{
|
||||
XMoveWindow(xfc->display, window->handle, 0, 0);
|
||||
}
|
||||
else
|
||||
if(settings->DesktopPosX || settings->DesktopPosY)
|
||||
{
|
||||
XMoveWindow(xfc->display, window->handle, settings->DesktopPosX, settings->DesktopPosY);
|
||||
}
|
||||
else if(settings->DesktopPosX || settings->DesktopPosY)
|
||||
{
|
||||
XMoveWindow(xfc->display, window->handle, settings->DesktopPosX, settings->DesktopPosY);
|
||||
}
|
||||
}
|
||||
xf_SetWindowText(xfc, window, name);
|
||||
return window;
|
||||
@ -822,25 +839,33 @@ BOOL xf_IsWindowBorder(xfContext *xfc, xfWindow *xfw, int x, int y)
|
||||
|
||||
void xf_DestroyWindow(xfContext *xfc, xfWindow *window)
|
||||
{
|
||||
if(window == NULL)
|
||||
if (!window)
|
||||
return;
|
||||
if(xfc->window == window)
|
||||
|
||||
if (xfc->window == window)
|
||||
xfc->window = NULL;
|
||||
if(window->gc)
|
||||
|
||||
if (window->gc)
|
||||
XFreeGC(xfc->display, window->gc);
|
||||
if(window->handle)
|
||||
|
||||
if (window->handle)
|
||||
{
|
||||
XUnmapWindow(xfc->display, window->handle);
|
||||
XDestroyWindow(xfc->display, window->handle);
|
||||
}
|
||||
free(window);
|
||||
if(window->xfwin)
|
||||
|
||||
if (window->xfwin)
|
||||
munmap(0, sizeof(*window->xfwin));
|
||||
if(window->shmid >= 0)
|
||||
|
||||
if (window->shmid >= 0)
|
||||
close(window->shmid);
|
||||
|
||||
shm_unlink(get_shm_id());
|
||||
window->xfwin = -1;
|
||||
|
||||
window->xfwin = (Window*) -1;
|
||||
window->shmid = -1;
|
||||
|
||||
free(window);
|
||||
}
|
||||
|
||||
rdpWindow *xf_rdpWindowFromWindow(xfContext *xfc, Window wnd)
|
||||
|
@ -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);
|
||||
|
@ -1609,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")
|
||||
{
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
|
||||
}
|
||||
|
||||
|
@ -31,13 +31,11 @@
|
||||
|
||||
int init_cliprdr_suite(void)
|
||||
{
|
||||
freerdp_channels_global_init();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int clean_cliprdr_suite(void)
|
||||
{
|
||||
freerdp_channels_global_uninit();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -31,13 +31,11 @@
|
||||
|
||||
int init_drdynvc_suite(void)
|
||||
{
|
||||
freerdp_channels_global_init();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int clean_drdynvc_suite(void)
|
||||
{
|
||||
freerdp_channels_global_uninit();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -46,13 +46,11 @@
|
||||
|
||||
int init_rail_suite(void)
|
||||
{
|
||||
freerdp_channels_global_init();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int clean_rail_suite(void)
|
||||
{
|
||||
freerdp_channels_global_uninit();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -32,8 +32,6 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
FREERDP_API int freerdp_channels_global_init(void);
|
||||
FREERDP_API int freerdp_channels_global_uninit(void);
|
||||
FREERDP_API rdpChannels* freerdp_channels_new(void);
|
||||
FREERDP_API void freerdp_channels_free(rdpChannels* channels);
|
||||
FREERDP_API int freerdp_channels_client_load(rdpChannels* channels, rdpSettings* settings,
|
||||
|
@ -60,6 +60,7 @@ typedef struct _RDPGFX_COLOR32 RDPGFX_COLOR32;
|
||||
|
||||
typedef BYTE RDPGFX_PIXELFORMAT;
|
||||
|
||||
#define RDPGFX_CMDID_UNUSED_0000 0x0000
|
||||
#define RDPGFX_CMDID_WIRETOSURFACE_1 0x0001
|
||||
#define RDPGFX_CMDID_WIRETOSURFACE_2 0x0002
|
||||
#define RDPGFX_CMDID_DELETEENCODINGCONTEXT 0x0003
|
||||
@ -79,8 +80,11 @@ typedef BYTE RDPGFX_PIXELFORMAT;
|
||||
#define RDPGFX_CMDID_CACHEIMPORTREPLY 0x0011
|
||||
#define RDPGFX_CMDID_CAPSADVERTISE 0x0012
|
||||
#define RDPGFX_CMDID_CAPSCONFIRM 0x0013
|
||||
#define RDPGFX_CMDID_UNUSED_0014 0x0014
|
||||
#define RDPGFX_CMDID_MAPSURFACETOWINDOW 0x0015
|
||||
|
||||
#define RDPGFX_HEADER_SIZE 8
|
||||
|
||||
struct _RDPGFX_HEADER
|
||||
{
|
||||
UINT16 cmdId;
|
||||
@ -96,11 +100,12 @@ typedef struct _RDPGFX_HEADER RDPGFX_HEADER;
|
||||
#define RDPGFX_CAPVERSION_8 0x00080004
|
||||
#define RDPGFX_CAPVERSION_81 0x00080105
|
||||
|
||||
#define RDPGFX_CAPSET_SIZE 12
|
||||
|
||||
struct _RDPGFX_CAPSET
|
||||
{
|
||||
UINT32 version;
|
||||
UINT32 capsDataLength;
|
||||
/* capsData (variable) */
|
||||
UINT32 flags;
|
||||
};
|
||||
typedef struct _RDPGFX_CAPSET RDPGFX_CAPSET;
|
||||
|
||||
@ -160,6 +165,23 @@ struct _RDPGFX_WIRE_TO_SURFACE_PDU_2
|
||||
};
|
||||
typedef struct _RDPGFX_WIRE_TO_SURFACE_PDU_2 RDPGFX_WIRE_TO_SURFACE_PDU_2;
|
||||
|
||||
struct _RDPGFX_SURFACE_COMMAND
|
||||
{
|
||||
UINT32 surfaceId;
|
||||
UINT32 codecId;
|
||||
UINT32 contextId;
|
||||
UINT32 format;
|
||||
UINT32 left;
|
||||
UINT32 top;
|
||||
UINT32 right;
|
||||
UINT32 bottom;
|
||||
UINT32 width;
|
||||
UINT32 height;
|
||||
UINT32 length;
|
||||
BYTE* data;
|
||||
};
|
||||
typedef struct _RDPGFX_SURFACE_COMMAND RDPGFX_SURFACE_COMMAND;
|
||||
|
||||
struct _RDPGFX_DELETE_ENCODING_CONTEXT_PDU
|
||||
{
|
||||
UINT16 surfaceId;
|
||||
@ -167,14 +189,14 @@ struct _RDPGFX_DELETE_ENCODING_CONTEXT_PDU
|
||||
};
|
||||
typedef struct _RDPGFX_DELETE_ENCODING_CONTEXT_PDU RDPGFX_DELETE_ENCODING_CONTEXT_PDU;
|
||||
|
||||
struct _RDPGFX_SOLIDFILL_PDU
|
||||
struct _RDPGFX_SOLID_FILL_PDU
|
||||
{
|
||||
UINT16 surfaceId;
|
||||
RDPGFX_COLOR32 fillPixel;
|
||||
UINT16 fillRectCount;
|
||||
RDPGFX_RECT16* fillRects;
|
||||
};
|
||||
typedef struct _RDPGFX_SOLIDFILL_PDU RDPGFX_SOLIDFILL_PDU;
|
||||
typedef struct _RDPGFX_SOLID_FILL_PDU RDPGFX_SOLID_FILL_PDU;
|
||||
|
||||
struct _RDPGFX_SURFACE_TO_SURFACE_PDU
|
||||
{
|
||||
@ -254,8 +276,7 @@ struct _RDPGFX_RESET_GRAPHICS_PDU
|
||||
UINT32 width;
|
||||
UINT32 height;
|
||||
UINT32 monitorCount;
|
||||
/* monitorDefArray */
|
||||
/* pad */
|
||||
MONITOR_DEF* monitorDefArray;
|
||||
};
|
||||
typedef struct _RDPGFX_RESET_GRAPHICS_PDU RDPGFX_RESET_GRAPHICS_PDU;
|
||||
|
||||
@ -292,14 +313,13 @@ typedef struct _RDPGFX_CACHE_IMPORT_REPLY_PDU RDPGFX_CACHE_IMPORT_REPLY_PDU;
|
||||
struct _RDPGFX_CAPS_ADVERTISE_PDU
|
||||
{
|
||||
UINT16 capsSetCount;
|
||||
/* capsSets */
|
||||
RDPGFX_CAPSET* capsSets;
|
||||
};
|
||||
typedef struct _RDPGFX_CAPS_ADVERTISE_PDU RDPGFX_CAPS_ADVERTISE_PDU;
|
||||
|
||||
struct _RDPGFX_CAPS_CONFIRM_PDU
|
||||
{
|
||||
RDPGFX_CAPSET* capSet;
|
||||
/* capSet */
|
||||
RDPGFX_CAPSET* capsSet;
|
||||
};
|
||||
typedef struct _RDPGFX_CAPS_CONFIRM_PDU RDPGFX_CAPS_CONFIRM_PDU;
|
||||
|
||||
|
@ -28,14 +28,54 @@
|
||||
|
||||
typedef struct _rdpgfx_client_context RdpgfxClientContext;
|
||||
|
||||
typedef UINT32 (*pcRdpgfxGetVersion)(RdpgfxClientContext* context);
|
||||
typedef int (*pcRdpgfxResetGraphics)(RdpgfxClientContext* context, RDPGFX_RESET_GRAPHICS_PDU* resetGraphics);
|
||||
typedef int (*pcRdpgfxStartFrame)(RdpgfxClientContext* context, RDPGFX_START_FRAME_PDU* startFrame);
|
||||
typedef int (*pcRdpgfxEndFrame)(RdpgfxClientContext* context, RDPGFX_END_FRAME_PDU* endFrame);
|
||||
typedef int (*pcRdpgfxSurfaceCommand)(RdpgfxClientContext* context, RDPGFX_SURFACE_COMMAND* cmd);
|
||||
typedef int (*pcRdpgfxDeleteEncodingContext)(RdpgfxClientContext* context, RDPGFX_DELETE_ENCODING_CONTEXT_PDU* deleteEncodingContext);
|
||||
typedef int (*pcRdpgfxCreateSurface)(RdpgfxClientContext* context, RDPGFX_CREATE_SURFACE_PDU* createSurface);
|
||||
typedef int (*pcRdpgfxDeleteSurface)(RdpgfxClientContext* context, RDPGFX_DELETE_SURFACE_PDU* deleteSurface);
|
||||
typedef int (*pcRdpgfxSolidFill)(RdpgfxClientContext* context, RDPGFX_SOLID_FILL_PDU* solidFill);
|
||||
typedef int (*pcRdpgfxSurfaceToSurface)(RdpgfxClientContext* context, RDPGFX_SURFACE_TO_SURFACE_PDU* surfaceToSurface);
|
||||
typedef int (*pcRdpgfxSurfaceToCache)(RdpgfxClientContext* context, RDPGFX_SURFACE_TO_CACHE_PDU* surfaceToCache);
|
||||
typedef int (*pcRdpgfxCacheToSurface)(RdpgfxClientContext* context, RDPGFX_CACHE_TO_SURFACE_PDU* cacheToSurface);
|
||||
typedef int (*pcRdpgfxCacheImportOffer)(RdpgfxClientContext* context, RDPGFX_CACHE_IMPORT_OFFER_PDU* cacheImportOffer);
|
||||
typedef int (*pcRdpgfxCacheImportReply)(RdpgfxClientContext* context, RDPGFX_CACHE_IMPORT_REPLY_PDU* cacheImportReply);
|
||||
typedef int (*pcRdpgfxEvictCacheEntry)(RdpgfxClientContext* context, RDPGFX_EVICT_CACHE_ENTRY_PDU* evictCacheEntry);
|
||||
typedef int (*pcRdpgfxMapSurfaceToOutput)(RdpgfxClientContext* context, RDPGFX_MAP_SURFACE_TO_OUTPUT_PDU* surfaceToOutput);
|
||||
typedef int (*pcRdpgfxMapSurfaceToWindow)(RdpgfxClientContext* context, RDPGFX_MAP_SURFACE_TO_WINDOW_PDU* surfaceToWindow);
|
||||
|
||||
typedef int (*pcRdpgfxSetSurfaceData)(RdpgfxClientContext* context, UINT16 surfaceId, void* pData);
|
||||
typedef void* (*pcRdpgfxGetSurfaceData)(RdpgfxClientContext* context, UINT16 surfaceId);
|
||||
typedef int (*pcRdpgfxSetCacheSlotData)(RdpgfxClientContext* context, UINT16 cacheSlot, void* pData);
|
||||
typedef void* (*pcRdpgfxGetCacheSlotData)(RdpgfxClientContext* context, UINT16 cacheSlot);
|
||||
|
||||
struct _rdpgfx_client_context
|
||||
{
|
||||
void* handle;
|
||||
void* custom;
|
||||
|
||||
pcRdpgfxGetVersion GetVersion;
|
||||
pcRdpgfxResetGraphics ResetGraphics;
|
||||
pcRdpgfxStartFrame StartFrame;
|
||||
pcRdpgfxEndFrame EndFrame;
|
||||
pcRdpgfxSurfaceCommand SurfaceCommand;
|
||||
pcRdpgfxDeleteEncodingContext DeleteEncodingContext;
|
||||
pcRdpgfxCreateSurface CreateSurface;
|
||||
pcRdpgfxDeleteSurface DeleteSurface;
|
||||
pcRdpgfxSolidFill SolidFill;
|
||||
pcRdpgfxSurfaceToSurface SurfaceToSurface;
|
||||
pcRdpgfxSurfaceToCache SurfaceToCache;
|
||||
pcRdpgfxCacheToSurface CacheToSurface;
|
||||
pcRdpgfxCacheImportOffer CacheImportOffer;
|
||||
pcRdpgfxCacheImportReply CacheImportReply;
|
||||
pcRdpgfxEvictCacheEntry EvictCacheEntry;
|
||||
pcRdpgfxMapSurfaceToOutput MapSurfaceToOutput;
|
||||
pcRdpgfxMapSurfaceToWindow MapSurfaceToWindow;
|
||||
|
||||
pcRdpgfxSetSurfaceData SetSurfaceData;
|
||||
pcRdpgfxGetSurfaceData GetSurfaceData;
|
||||
pcRdpgfxSetCacheSlotData SetCacheSlotData;
|
||||
pcRdpgfxGetCacheSlotData GetCacheSlotData;
|
||||
};
|
||||
|
||||
#endif /* FREERDP_CHANNEL_CLIENT_RDPGFX_H */
|
||||
|
@ -46,4 +46,7 @@ FREERDP_API BYTE* freerdp_bitmap_compress_planar(BITMAP_PLANAR_CONTEXT* context,
|
||||
FREERDP_API BITMAP_PLANAR_CONTEXT* freerdp_bitmap_planar_context_new(DWORD flags, int maxWidth, int maxHeight);
|
||||
FREERDP_API void freerdp_bitmap_planar_context_free(BITMAP_PLANAR_CONTEXT* context);
|
||||
|
||||
FREERDP_API int planar_decompress(BITMAP_PLANAR_CONTEXT* planar, BYTE* pSrcData, UINT32 SrcSize,
|
||||
BYTE** ppDstData, DWORD DstFormat, int nDstStep, int nXDst, int nYDst, int nWidth, int nHeight);
|
||||
|
||||
#endif /* FREERDP_CODEC_BITMAP_H */
|
||||
|
57
include/freerdp/codec/clear.h
Normal file
57
include/freerdp/codec/clear.h
Normal file
@ -0,0 +1,57 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* ClearCodec Bitmap Compression
|
||||
*
|
||||
* 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 FREERDP_CODEC_CLEAR_H
|
||||
#define FREERDP_CODEC_CLEAR_H
|
||||
|
||||
#include <freerdp/api.h>
|
||||
#include <freerdp/types.h>
|
||||
|
||||
#define CLEARCODEC_FLAG_GLYPH_INDEX 0x01
|
||||
#define CLEARCODEC_FLAG_GLYPH_HIT 0x02
|
||||
#define CLEARCODEC_FLAG_CACHE_RESET 0x03
|
||||
|
||||
struct _CLEAR_CONTEXT
|
||||
{
|
||||
BOOL Compressor;
|
||||
UINT32 VBarStorageCursor;
|
||||
void* VBarStorage[32768];
|
||||
UINT32 ShortVBarStorageCursor;
|
||||
void* ShortVBarStorage[16384];
|
||||
};
|
||||
typedef struct _CLEAR_CONTEXT CLEAR_CONTEXT;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
FREERDP_API int clear_compress(CLEAR_CONTEXT* clear, BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstData, UINT32* pDstSize);
|
||||
FREERDP_API int clear_decompress(CLEAR_CONTEXT* clear, BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstData, UINT32* pDstSize);
|
||||
|
||||
FREERDP_API void clear_context_reset(CLEAR_CONTEXT* clear);
|
||||
|
||||
FREERDP_API CLEAR_CONTEXT* clear_context_new(BOOL Compressor);
|
||||
FREERDP_API void clear_context_free(CLEAR_CONTEXT* clear);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* FREERDP_CODEC_CLEAR_H */
|
||||
|
@ -33,10 +33,10 @@
|
||||
#define FREERDP_PIXEL_FLIP_VERTICAL 1
|
||||
#define FREERDP_PIXEL_FLIP_HORIZONTAL 2
|
||||
|
||||
#define FREERDP_PIXEL_FORMAT(_bpp, _type, _a, _r, _g, _b) \
|
||||
((_bpp << 24) | (_type << 16) | (_a << 12) | (_r << 8) | (_g << 4) | (_b))
|
||||
#define FREERDP_PIXEL_FORMAT(_flip, _bpp, _type, _a, _r, _g, _b) \
|
||||
((_flip << 30) | (_bpp << 24) | (_type << 16) | (_a << 12) | (_r << 8) | (_g << 4) | (_b))
|
||||
|
||||
#define FREERDP_PIXEL_FORMAT_FLIP(_format) (((_format) >> 30) & 0x02)
|
||||
#define FREERDP_PIXEL_FORMAT_FLIP(_format) (((_format) >> 30) & 0x03)
|
||||
#define FREERDP_PIXEL_FORMAT_BPP(_format) (((_format) >> 24) & 0x3F)
|
||||
#define FREERDP_PIXEL_FORMAT_TYPE(_format) (((_format) >> 16) & 0xFF)
|
||||
#define FREERDP_PIXEL_FORMAT_A(_format) (((_format) >> 12) & 0x0F)
|
||||
@ -54,84 +54,110 @@
|
||||
|
||||
/* 32bpp formats */
|
||||
|
||||
#define PIXEL_FORMAT_A8R8G8B8 FREERDP_PIXEL_FORMAT(32, FREERDP_PIXEL_FORMAT_TYPE_ARGB, 8, 8, 8, 8)
|
||||
#define PIXEL_FORMAT_ARGB32 PIXEL_FORMAT_A8R8G8B8
|
||||
#define PIXEL_FORMAT_A8R8G8B8_F(_flip) FREERDP_PIXEL_FORMAT(_flip, 32, FREERDP_PIXEL_FORMAT_TYPE_ARGB, 8, 8, 8, 8)
|
||||
#define PIXEL_FORMAT_A8R8G8B8 PIXEL_FORMAT_A8R8G8B8_F(0)
|
||||
#define PIXEL_FORMAT_ARGB32 PIXEL_FORMAT_A8R8G8B8
|
||||
#define PIXEL_FORMAT_A8R8G8B8_VF PIXEL_FORMAT_A8R8G8B8_F(1)
|
||||
#define PIXEL_FORMAT_ARGB32_VF PIXEL_FORMAT_A8R8G8B8_VF
|
||||
|
||||
#define PIXEL_FORMAT_X8R8G8B8 FREERDP_PIXEL_FORMAT(32, FREERDP_PIXEL_FORMAT_TYPE_ARGB, 0, 8, 8, 8)
|
||||
#define PIXEL_FORMAT_XRGB32 PIXEL_FORMAT_X8R8G8B8
|
||||
#define PIXEL_FORMAT_RGB32 PIXEL_FORMAT_XRGB32
|
||||
#define PIXEL_FORMAT_X8R8G8B8_F(_flip) FREERDP_PIXEL_FORMAT(_flip, 32, FREERDP_PIXEL_FORMAT_TYPE_ARGB, 0, 8, 8, 8)
|
||||
#define PIXEL_FORMAT_X8R8G8B8 PIXEL_FORMAT_X8R8G8B8_F(0)
|
||||
#define PIXEL_FORMAT_XRGB32 PIXEL_FORMAT_X8R8G8B8
|
||||
#define PIXEL_FORMAT_RGB32 PIXEL_FORMAT_XRGB32
|
||||
#define PIXEL_FORMAT_X8R8G8B8_VF PIXEL_FORMAT_X8R8G8B8_F(1)
|
||||
#define PIXEL_FORMAT_XRGB32_VF PIXEL_FORMAT_X8R8G8B8_VF
|
||||
#define PIXEL_FORMAT_RGB32_VF PIXEL_FORMAT_XRGB32_VF
|
||||
|
||||
#define PIXEL_FORMAT_A8B8G8R8 FREERDP_PIXEL_FORMAT(32, FREERDP_PIXEL_FORMAT_TYPE_ABGR, 8, 8, 8, 8)
|
||||
#define PIXEL_FORMAT_ABGR32 PIXEL_FORMAT_A8B8G8R8
|
||||
#define PIXEL_FORMAT_A8B8G8R8_F(_flip) FREERDP_PIXEL_FORMAT(_flip, 32, FREERDP_PIXEL_FORMAT_TYPE_ABGR, 8, 8, 8, 8)
|
||||
#define PIXEL_FORMAT_A8B8G8R8 PIXEL_FORMAT_A8B8G8R8_F(0)
|
||||
#define PIXEL_FORMAT_ABGR32 PIXEL_FORMAT_A8B8G8R8
|
||||
#define PIXEL_FORMAT_A8B8G8R8_VF PIXEL_FORMAT_A8B8G8R8_F(1)
|
||||
#define PIXEL_FORMAT_ABGR32_VF PIXEL_FORMAT_A8B8G8R8_VF
|
||||
|
||||
#define PIXEL_FORMAT_X8B8G8R8 FREERDP_PIXEL_FORMAT(32, FREERDP_PIXEL_FORMAT_TYPE_ABGR, 0, 8, 8, 8)
|
||||
#define PIXEL_FORMAT_XBGR32 PIXEL_FORMAT_X8B8G8R8
|
||||
#define PIXEL_FORMAT_BGR32 PIXEL_FORMAT_XBGR32
|
||||
#define PIXEL_FORMAT_X8B8G8R8_F(_flip) FREERDP_PIXEL_FORMAT(_flip, 32, FREERDP_PIXEL_FORMAT_TYPE_ABGR, 0, 8, 8, 8)
|
||||
#define PIXEL_FORMAT_X8B8G8R8 PIXEL_FORMAT_X8B8G8R8_F(0)
|
||||
#define PIXEL_FORMAT_XBGR32 PIXEL_FORMAT_X8B8G8R8
|
||||
#define PIXEL_FORMAT_BGR32 PIXEL_FORMAT_XBGR32
|
||||
#define PIXEL_FORMAT_X8B8G8R8_VF PIXEL_FORMAT_X8B8G8R8_F(1)
|
||||
#define PIXEL_FORMAT_XBGR32_VF PIXEL_FORMAT_X8B8G8R8_VF
|
||||
#define PIXEL_FORMAT_BGR32_VF PIXEL_FORMAT_XBGR32_VF
|
||||
|
||||
#define PIXEL_FORMAT_B8G8R8A8 FREERDP_PIXEL_FORMAT(32, FREERDP_PIXEL_FORMAT_TYPE_BGRA, 8, 8, 8, 8)
|
||||
#define PIXEL_FORMAT_BGRA32 PIXEL_FORMAT_B8G8R8A8
|
||||
#define PIXEL_FORMAT_B8G8R8A8_F(_flip) FREERDP_PIXEL_FORMAT(_flip, 32, FREERDP_PIXEL_FORMAT_TYPE_BGRA, 8, 8, 8, 8)
|
||||
#define PIXEL_FORMAT_B8G8R8A8 PIXEL_FORMAT_B8G8R8A8_F(0)
|
||||
#define PIXEL_FORMAT_BGRA32 PIXEL_FORMAT_B8G8R8A8
|
||||
#define PIXEL_FORMAT_B8G8R8A8_VF PIXEL_FORMAT_B8G8R8A8_F(1)
|
||||
#define PIXEL_FORMAT_BGRA32_VF PIXEL_FORMAT_B8G8R8A8_VF
|
||||
|
||||
#define PIXEL_FORMAT_B8G8R8X8 FREERDP_PIXEL_FORMAT(32, FREERDP_PIXEL_FORMAT_TYPE_BGRA, 0, 8, 8, 8)
|
||||
#define PIXEL_FORMAT_BGRX32 PIXEL_FORMAT_B8G8R8X8
|
||||
#define PIXEL_FORMAT_B8G8R8X8_F(_flip) FREERDP_PIXEL_FORMAT(_flip, 32, FREERDP_PIXEL_FORMAT_TYPE_BGRA, 0, 8, 8, 8)
|
||||
#define PIXEL_FORMAT_B8G8R8X8 PIXEL_FORMAT_B8G8R8X8_F(0)
|
||||
#define PIXEL_FORMAT_BGRX32 PIXEL_FORMAT_B8G8R8X8
|
||||
#define PIXEL_FORMAT_B8G8R8X8_VF PIXEL_FORMAT_B8G8R8X8_F(1)
|
||||
#define PIXEL_FORMAT_BGRX32_VF PIXEL_FORMAT_B8G8R8X8_VF
|
||||
|
||||
#define PIXEL_FORMAT_R8G8B8A8 FREERDP_PIXEL_FORMAT(32, FREERDP_PIXEL_FORMAT_TYPE_RGBA, 8, 8, 8, 8)
|
||||
#define PIXEL_FORMAT_RGBA32 PIXEL_FORMAT_R8G8B8A8
|
||||
#define PIXEL_FORMAT_R8G8B8A8_F(_flip) FREERDP_PIXEL_FORMAT(_flip, 32, FREERDP_PIXEL_FORMAT_TYPE_RGBA, 8, 8, 8, 8)
|
||||
#define PIXEL_FORMAT_R8G8B8A8 PIXEL_FORMAT_R8G8B8A8_F(0)
|
||||
#define PIXEL_FORMAT_RGBA32 PIXEL_FORMAT_R8G8B8A8
|
||||
#define PIXEL_FORMAT_R8G8B8A8_VF PIXEL_FORMAT_R8G8B8A8_F(1)
|
||||
#define PIXEL_FORMAT_RGBA32_VF PIXEL_FORMAT_R8G8B8A8_VF
|
||||
|
||||
#define PIXEL_FORMAT_R8G8B8X8 FREERDP_PIXEL_FORMAT(32, FREERDP_PIXEL_FORMAT_TYPE_RGBA, 0, 8, 8, 8)
|
||||
#define PIXEL_FORMAT_RGBX32 PIXEL_FORMAT_R8G8B8X8
|
||||
#define PIXEL_FORMAT_R8G8B8X8_F(_flip) FREERDP_PIXEL_FORMAT(_flip, 32, FREERDP_PIXEL_FORMAT_TYPE_RGBA, 0, 8, 8, 8)
|
||||
#define PIXEL_FORMAT_R8G8B8X8 PIXEL_FORMAT_R8G8B8X8_F(0)
|
||||
#define PIXEL_FORMAT_RGBX32 PIXEL_FORMAT_R8G8B8X8
|
||||
#define PIXEL_FORMAT_R8G8B8X8_VF PIXEL_FORMAT_R8G8B8X8_F(1)
|
||||
#define PIXEL_FORMAT_RGBX32_VF PIXEL_FORMAT_R8G8B8X8_VF
|
||||
|
||||
/* 24bpp formats */
|
||||
|
||||
#define PIXEL_FORMAT_R8G8B8 FREERDP_PIXEL_FORMAT(24, FREERDP_PIXEL_FORMAT_TYPE_ARGB, 0, 8, 8, 8)
|
||||
#define PIXEL_FORMAT_RGB24 PIXEL_FORMAT_R8G8B8
|
||||
#define PIXEL_FORMAT_R8G8B8 FREERDP_PIXEL_FORMAT(0, 24, FREERDP_PIXEL_FORMAT_TYPE_ARGB, 0, 8, 8, 8)
|
||||
#define PIXEL_FORMAT_RGB24 PIXEL_FORMAT_R8G8B8
|
||||
|
||||
#define PIXEL_FORMAT_B8G8R8 FREERDP_PIXEL_FORMAT(24, FREERDP_PIXEL_FORMAT_TYPE_ABGR, 0, 8, 8, 8)
|
||||
#define PIXEL_FORMAT_BGR24 PIXEL_FORMAT_B8G8R8
|
||||
#define PIXEL_FORMAT_B8G8R8 FREERDP_PIXEL_FORMAT(0, 24, FREERDP_PIXEL_FORMAT_TYPE_ABGR, 0, 8, 8, 8)
|
||||
#define PIXEL_FORMAT_BGR24 PIXEL_FORMAT_B8G8R8
|
||||
|
||||
/* 16bpp formats */
|
||||
|
||||
#define PIXEL_FORMAT_R5G6B5 FREERDP_PIXEL_FORMAT(16, FREERDP_PIXEL_FORMAT_TYPE_ARGB, 0, 5, 6, 5)
|
||||
#define PIXEL_FORMAT_RGB565 PIXEL_FORMAT_R5G6B5
|
||||
#define PIXEL_FORMAT_RGB16 PIXEL_FORMAT_R5G6B5
|
||||
#define PIXEL_FORMAT_R5G6B5 FREERDP_PIXEL_FORMAT(0, 16, FREERDP_PIXEL_FORMAT_TYPE_ARGB, 0, 5, 6, 5)
|
||||
#define PIXEL_FORMAT_RGB565 PIXEL_FORMAT_R5G6B5
|
||||
#define PIXEL_FORMAT_RGB16 PIXEL_FORMAT_R5G6B5
|
||||
|
||||
#define PIXEL_FORMAT_B5G6R5 FREERDP_PIXEL_FORMAT(16, FREERDP_PIXEL_FORMAT_TYPE_ABGR, 0, 5, 6, 5)
|
||||
#define PIXEL_FORMAT_BGR565 PIXEL_FORMAT_B5G6R5
|
||||
#define PIXEL_FORMAT_BGR16 PIXEL_FORMAT_B5G6R5
|
||||
#define PIXEL_FORMAT_B5G6R5 FREERDP_PIXEL_FORMAT(0, 16, FREERDP_PIXEL_FORMAT_TYPE_ABGR, 0, 5, 6, 5)
|
||||
#define PIXEL_FORMAT_BGR565 PIXEL_FORMAT_B5G6R5
|
||||
#define PIXEL_FORMAT_BGR16 PIXEL_FORMAT_B5G6R5
|
||||
|
||||
#define PIXEL_FORMAT_A1R5G5B5 FREERDP_PIXEL_FORMAT(16, FREERDP_PIXEL_FORMAT_TYPE_ARGB, 1, 5, 5, 5)
|
||||
#define PIXEL_FORMAT_ARGB555 PIXEL_FORMAT_A1R5G5B5
|
||||
#define PIXEL_FORMAT_ARGB15 PIXEL_FORMAT_A1R5G5B5
|
||||
#define PIXEL_FORMAT_A1R5G5B5 FREERDP_PIXEL_FORMAT(0, 16, FREERDP_PIXEL_FORMAT_TYPE_ARGB, 1, 5, 5, 5)
|
||||
#define PIXEL_FORMAT_ARGB555 PIXEL_FORMAT_A1R5G5B5
|
||||
#define PIXEL_FORMAT_ARGB15 PIXEL_FORMAT_A1R5G5B5
|
||||
|
||||
#define PIXEL_FORMAT_X1R5G5B5 FREERDP_PIXEL_FORMAT(16, FREERDP_PIXEL_FORMAT_TYPE_ARGB, 0, 5, 5, 5)
|
||||
#define PIXEL_FORMAT_XRGB555 PIXEL_FORMAT_X1R5G5B5
|
||||
#define PIXEL_FORMAT_RGB555 PIXEL_FORMAT_X1R5G5B5
|
||||
#define PIXEL_FORMAT_RGB15 PIXEL_FORMAT_X1R5G5B5
|
||||
#define PIXEL_FORMAT_X1R5G5B5 FREERDP_PIXEL_FORMAT(0, 16, FREERDP_PIXEL_FORMAT_TYPE_ARGB, 0, 5, 5, 5)
|
||||
#define PIXEL_FORMAT_XRGB555 PIXEL_FORMAT_X1R5G5B5
|
||||
#define PIXEL_FORMAT_RGB555 PIXEL_FORMAT_X1R5G5B5
|
||||
#define PIXEL_FORMAT_RGB15 PIXEL_FORMAT_X1R5G5B5
|
||||
|
||||
#define PIXEL_FORMAT_A1B5G5R5 FREERDP_PIXEL_FORMAT(16, FREERDP_PIXEL_FORMAT_TYPE_ABGR, 1, 5, 5, 5)
|
||||
#define PIXEL_FORMAT_ABGR555 PIXEL_FORMAT_A1B5G5R5
|
||||
#define PIXEL_FORMAT_ABGR15 PIXEL_FORMAT_A1B5G5R5
|
||||
#define PIXEL_FORMAT_A1B5G5R5 FREERDP_PIXEL_FORMAT(0, 16, FREERDP_PIXEL_FORMAT_TYPE_ABGR, 1, 5, 5, 5)
|
||||
#define PIXEL_FORMAT_ABGR555 PIXEL_FORMAT_A1B5G5R5
|
||||
#define PIXEL_FORMAT_ABGR15 PIXEL_FORMAT_A1B5G5R5
|
||||
|
||||
#define PIXEL_FORMAT_X1B5G5R5 FREERDP_PIXEL_FORMAT(16, FREERDP_PIXEL_FORMAT_TYPE_ABGR, 0, 5, 5, 5)
|
||||
#define PIXEL_FORMAT_XBGR555 PIXEL_FORMAT_X1B5G5R5
|
||||
#define PIXEL_FORMAT_BGR555 PIXEL_FORMAT_X1B5G5R5
|
||||
#define PIXEL_FORMAT_BGR15 PIXEL_FORMAT_X1B5G5R5
|
||||
#define PIXEL_FORMAT_X1B5G5R5 FREERDP_PIXEL_FORMAT(0, 16, FREERDP_PIXEL_FORMAT_TYPE_ABGR, 0, 5, 5, 5)
|
||||
#define PIXEL_FORMAT_XBGR555 PIXEL_FORMAT_X1B5G5R5
|
||||
#define PIXEL_FORMAT_BGR555 PIXEL_FORMAT_X1B5G5R5
|
||||
#define PIXEL_FORMAT_BGR15 PIXEL_FORMAT_X1B5G5R5
|
||||
|
||||
/* 8bpp formats */
|
||||
|
||||
#define PIXEL_FORMAT_A8 FREERDP_PIXEL_FORMAT(8, FREERDP_PIXEL_FORMAT_TYPE_A, 8, 0, 0, 0)
|
||||
#define PIXEL_FORMAT_8BPP PIXEL_FORMAT_A8
|
||||
#define PIXEL_FORMAT_256 PIXEL_FORMAT_A8
|
||||
#define PIXEL_FORMAT_A8 FREERDP_PIXEL_FORMAT(0, 8, FREERDP_PIXEL_FORMAT_TYPE_A, 8, 0, 0, 0)
|
||||
#define PIXEL_FORMAT_8BPP PIXEL_FORMAT_A8
|
||||
#define PIXEL_FORMAT_256 PIXEL_FORMAT_A8
|
||||
|
||||
/* 4 bpp formats */
|
||||
|
||||
#define PIXEL_FORMAT_A4 FREERDP_PIXEL_FORMAT(4, FREERDP_PIXEL_FORMAT_TYPE_A, 4, 0, 0, 0)
|
||||
#define PIXEL_FORMAT_4BPP PIXEL_FORMAT_A4
|
||||
#define PIXEL_FORMAT_A4 FREERDP_PIXEL_FORMAT(0, 4, FREERDP_PIXEL_FORMAT_TYPE_A, 4, 0, 0, 0)
|
||||
#define PIXEL_FORMAT_4BPP PIXEL_FORMAT_A4
|
||||
|
||||
/* 1bpp formats */
|
||||
|
||||
#define PIXEL_FORMAT_A1 FREERDP_PIXEL_FORMAT(1, FREERDP_PIXEL_FORMAT_TYPE_A, 1, 0, 0, 0)
|
||||
#define PIXEL_FORMAT_1BPP PIXEL_FORMAT_A1
|
||||
#define PIXEL_FORMAT_MONO PIXEL_FORMAT_A1
|
||||
#define PIXEL_FORMAT_A1 FREERDP_PIXEL_FORMAT(0, 1, FREERDP_PIXEL_FORMAT_TYPE_A, 1, 0, 0, 0)
|
||||
#define PIXEL_FORMAT_1BPP PIXEL_FORMAT_A1
|
||||
#define PIXEL_FORMAT_MONO PIXEL_FORMAT_A1
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@ -372,6 +398,8 @@ FREERDP_API void freerdp_clrconv_free(HCLRCONV clrconv);
|
||||
|
||||
FREERDP_API int freerdp_image_copy(BYTE* pDstData, DWORD dwDstFormat, int nDstStep, int nXDst, int nYDst,
|
||||
int nWidth, int nHeight, BYTE* pSrcData, DWORD dwSrcFormat, int nSrcStep, int nXSrc, int nYSrc);
|
||||
FREERDP_API int freerdp_image_fill(BYTE* pDstData, DWORD dwDstFormat, int nDstStep, int nXDst, int nYDst,
|
||||
int nWidth, int nHeight, UINT32 color);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
69
include/freerdp/codec/zgfx.h
Normal file
69
include/freerdp/codec/zgfx.h
Normal file
@ -0,0 +1,69 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* ZGFX (RDP8) Bulk Data Compression
|
||||
*
|
||||
* 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 FREERDP_CODEC_ZGFX_H
|
||||
#define FREERDP_CODEC_ZGFX_H
|
||||
|
||||
#include <freerdp/api.h>
|
||||
#include <freerdp/types.h>
|
||||
|
||||
#include <freerdp/codec/bulk.h>
|
||||
|
||||
#define ZGFX_SEGMENTED_SINGLE 0xE0
|
||||
#define ZGFX_SEGMENTED_MULTIPART 0xE1
|
||||
|
||||
struct _ZGFX_CONTEXT
|
||||
{
|
||||
BOOL Compressor;
|
||||
|
||||
BYTE* pbInputCurrent;
|
||||
BYTE* pbInputEnd;
|
||||
|
||||
UINT32 bits;
|
||||
UINT32 cBitsRemaining;
|
||||
UINT32 BitsCurrent;
|
||||
UINT32 cBitsCurrent;
|
||||
|
||||
BYTE OutputBuffer[65536];
|
||||
UINT32 OutputCount;
|
||||
|
||||
BYTE HistoryBuffer[2500000];
|
||||
UINT32 HistoryIndex;
|
||||
UINT32 HistoryBufferSize;
|
||||
};
|
||||
typedef struct _ZGFX_CONTEXT ZGFX_CONTEXT;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
FREERDP_API int zgfx_compress(ZGFX_CONTEXT* zgfx, BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstData, UINT32* pDstSize, UINT32* pFlags);
|
||||
FREERDP_API int zgfx_decompress(ZGFX_CONTEXT* zgfx, BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstData, UINT32* pDstSize, UINT32 flags);
|
||||
|
||||
FREERDP_API void zgfx_context_reset(ZGFX_CONTEXT* zgfx, BOOL flush);
|
||||
|
||||
FREERDP_API ZGFX_CONTEXT* zgfx_context_new(BOOL Compressor);
|
||||
FREERDP_API void zgfx_context_free(ZGFX_CONTEXT* zgfx);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* FREERDP_CODEC_ZGFX_H */
|
||||
|
@ -137,11 +137,11 @@ struct _IWTSListenerCallback
|
||||
struct _IWTSVirtualChannelCallback
|
||||
{
|
||||
/* Notifies the user about data that is being received. */
|
||||
int (*OnDataReceived)(IWTSVirtualChannelCallback *pChannelCallback,
|
||||
UINT32 cbSize,
|
||||
BYTE *pBuffer);
|
||||
int (*OnDataReceived) (IWTSVirtualChannelCallback* pChannelCallback, wStream* data);
|
||||
/* Notifies the user that the channel has been opened. */
|
||||
int (*OnOpen) (IWTSVirtualChannelCallback* pChannelCallback);
|
||||
/* Notifies the user that the channel has been closed. */
|
||||
int (*OnClose)(IWTSVirtualChannelCallback *pChannelCallback);
|
||||
int (*OnClose) (IWTSVirtualChannelCallback* pChannelCallback);
|
||||
};
|
||||
|
||||
/* The DVC Plugin entry points */
|
||||
|
@ -55,6 +55,7 @@ struct rdp_svc_plugin
|
||||
void* InitHandle;
|
||||
DWORD OpenHandle;
|
||||
wMessagePipe* MsgPipe;
|
||||
wStreamPool *pool;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
@ -62,6 +63,8 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
FREERDP_API void svc_plugin_init(rdpSvcPlugin* plugin, CHANNEL_ENTRY_POINTS* pEntryPoints);
|
||||
FREERDP_API void svc_plugin_terminate(rdpSvcPlugin* plugin);
|
||||
|
||||
FREERDP_API int svc_plugin_send(rdpSvcPlugin* plugin, wStream* data_out);
|
||||
FREERDP_API int svc_plugin_send_event(rdpSvcPlugin* plugin, wMessage* event);
|
||||
|
||||
|
@ -50,6 +50,8 @@ set(${MODULE_PREFIX}_SRCS
|
||||
ncrush.c
|
||||
xcrush.c
|
||||
mppc.c
|
||||
zgfx.c
|
||||
clear.c
|
||||
jpeg.c)
|
||||
|
||||
set(${MODULE_PREFIX}_SSE2_SRCS
|
||||
|
@ -260,7 +260,9 @@ static UINT32 ExtractRunLength(UINT32 code, BYTE* pbOrderHdr, UINT32* advance)
|
||||
*/
|
||||
BOOL bitmap_decompress(BYTE* srcData, BYTE* dstData, int width, int height, int size, int srcBpp, int dstBpp)
|
||||
{
|
||||
BYTE* TmpBfr;
|
||||
int status;
|
||||
BYTE* TmpBfr;
|
||||
BYTE* pDstData;
|
||||
|
||||
if (srcBpp == 16 && dstBpp == 16)
|
||||
{
|
||||
@ -271,7 +273,12 @@ BOOL bitmap_decompress(BYTE* srcData, BYTE* dstData, int width, int height, int
|
||||
}
|
||||
else if (srcBpp == 32 && dstBpp == 32)
|
||||
{
|
||||
if (freerdp_bitmap_planar_decompress(srcData, dstData, width, height, size) < 0)
|
||||
pDstData = dstData;
|
||||
|
||||
status = planar_decompress(NULL, srcData, size, &pDstData,
|
||||
PIXEL_FORMAT_XRGB32_VF, width * 4, 0, 0, width, height);
|
||||
|
||||
if (status < 0)
|
||||
return FALSE;
|
||||
}
|
||||
else if (srcBpp == 15 && dstBpp == 15)
|
||||
|
340
libfreerdp/codec/clear.c
Normal file
340
libfreerdp/codec/clear.c
Normal file
@ -0,0 +1,340 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* ClearCodec Bitmap Compression
|
||||
*
|
||||
* 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/print.h>
|
||||
#include <winpr/bitstream.h>
|
||||
|
||||
#include <freerdp/codec/clear.h>
|
||||
|
||||
int clear_decompress(CLEAR_CONTEXT* clear, BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstData, UINT32* pDstSize)
|
||||
{
|
||||
int index;
|
||||
BYTE glyphFlags;
|
||||
BYTE seqNumber;
|
||||
UINT16 glyphIndex;
|
||||
UINT32 offset = 0;
|
||||
UINT32 residualByteCount;
|
||||
UINT32 bandsByteCount;
|
||||
UINT32 subcodecByteCount;
|
||||
|
||||
if (SrcSize < 2)
|
||||
return -1001;
|
||||
|
||||
glyphFlags = pSrcData[0];
|
||||
seqNumber = pSrcData[1];
|
||||
offset += 2;
|
||||
|
||||
printf("glyphFlags: 0x%02X seqNumber: %d\n", glyphFlags, seqNumber);
|
||||
|
||||
if (glyphFlags & CLEARCODEC_FLAG_GLYPH_INDEX)
|
||||
{
|
||||
if (SrcSize < 4)
|
||||
return -1002;
|
||||
|
||||
glyphIndex = *((UINT16*) &pSrcData[2]);
|
||||
offset += 2;
|
||||
|
||||
if (glyphFlags & CLEARCODEC_FLAG_GLYPH_HIT)
|
||||
{
|
||||
/**
|
||||
* Copy pixels from the Decompressor Glyph Storage position
|
||||
* specified by the glyphIndex field to the output bitmap
|
||||
*/
|
||||
|
||||
return 1; /* Finish */
|
||||
}
|
||||
}
|
||||
|
||||
/* Read composition payload header parameters */
|
||||
|
||||
if ((SrcSize - offset) < 12)
|
||||
return -1003;
|
||||
|
||||
residualByteCount = *((UINT32*) &pSrcData[offset]);
|
||||
bandsByteCount = *((UINT32*) &pSrcData[offset + 4]);
|
||||
subcodecByteCount = *((UINT32*) &pSrcData[offset + 8]);
|
||||
offset += 12;
|
||||
|
||||
printf("residualByteCount: %d bandsByteCount: %d subcodecByteCount: %d\n",
|
||||
residualByteCount, bandsByteCount, subcodecByteCount);
|
||||
|
||||
if (residualByteCount > 0)
|
||||
{
|
||||
BYTE blueValue;
|
||||
BYTE greenValue;
|
||||
BYTE redValue;
|
||||
UINT32 suboffset;
|
||||
BYTE* residualData;
|
||||
BYTE runLengthFactor1 = 0;
|
||||
UINT16 runLengthFactor2 = 0;
|
||||
UINT32 runLengthFactor3 = 0;
|
||||
UINT32 runLengthFactor = 0;
|
||||
|
||||
if ((SrcSize - offset) < residualByteCount)
|
||||
return -1004;
|
||||
|
||||
suboffset = 0;
|
||||
residualData = &pSrcData[offset];
|
||||
|
||||
while (suboffset < residualByteCount)
|
||||
{
|
||||
if ((residualByteCount - suboffset) < 4)
|
||||
return -1005;
|
||||
|
||||
blueValue = residualData[suboffset];
|
||||
greenValue = residualData[suboffset + 1];
|
||||
redValue = residualData[suboffset + 2];
|
||||
suboffset += 3;
|
||||
|
||||
runLengthFactor1 = residualData[suboffset];
|
||||
runLengthFactor = runLengthFactor1;
|
||||
suboffset += 1;
|
||||
|
||||
if (runLengthFactor1 >= 0xFF)
|
||||
{
|
||||
if ((residualByteCount - suboffset) < 2)
|
||||
return -1006;
|
||||
|
||||
runLengthFactor2 = *((UINT16*) &residualData[suboffset]);
|
||||
runLengthFactor = runLengthFactor2;
|
||||
suboffset += 2;
|
||||
|
||||
if (runLengthFactor2 >= 0xFFFF)
|
||||
{
|
||||
if ((residualByteCount - suboffset) < 4)
|
||||
return -1007;
|
||||
|
||||
runLengthFactor3 = *((UINT32*) &residualData[suboffset]);
|
||||
runLengthFactor = runLengthFactor3;
|
||||
suboffset += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Decompress residual layer and write to output bitmap */
|
||||
offset += residualByteCount;
|
||||
}
|
||||
|
||||
if (bandsByteCount > 0)
|
||||
{
|
||||
BYTE* bandsData;
|
||||
UINT32 suboffset;
|
||||
|
||||
if ((SrcSize - offset) < bandsByteCount)
|
||||
return -1008;
|
||||
|
||||
suboffset = 0;
|
||||
bandsData = &pSrcData[offset];
|
||||
|
||||
while (suboffset < bandsByteCount)
|
||||
{
|
||||
UINT16 xStart;
|
||||
UINT16 xEnd;
|
||||
UINT16 yStart;
|
||||
UINT16 yEnd;
|
||||
BYTE blueBkg;
|
||||
BYTE greenBkg;
|
||||
BYTE redBkg;
|
||||
BYTE* vBars;
|
||||
UINT16 vBarHeader;
|
||||
UINT16 vBarIndex;
|
||||
UINT16 vBarYOn;
|
||||
UINT16 vBarYOff;
|
||||
int vBarCount;
|
||||
int vBarPixelCount;
|
||||
|
||||
if ((bandsByteCount - suboffset) < 11)
|
||||
return -1009;
|
||||
|
||||
xStart = *((UINT16*) &bandsData[suboffset]);
|
||||
xEnd = *((UINT16*) &bandsData[suboffset + 2]);
|
||||
yStart = *((UINT16*) &bandsData[suboffset + 4]);
|
||||
yEnd = *((UINT16*) &bandsData[suboffset + 6]);
|
||||
blueBkg = bandsData[suboffset + 8];
|
||||
greenBkg = bandsData[suboffset + 9];
|
||||
redBkg = bandsData[suboffset + 10];
|
||||
suboffset += 11;
|
||||
|
||||
vBarCount = (xEnd - xStart) + 1;
|
||||
|
||||
printf("CLEARCODEC_BAND: xStart: %d xEnd: %d yStart: %d yEnd: %d vBarCount: %d blueBkg: 0x%02X greenBkg: 0x%02X redBkg: 0x%02X\n",
|
||||
xStart, xEnd, yStart, yEnd, vBarCount, blueBkg, greenBkg, redBkg);
|
||||
|
||||
for (index = 0; index < vBarCount; index++)
|
||||
{
|
||||
vBars = &bandsData[suboffset];
|
||||
|
||||
if ((bandsByteCount - suboffset) < 2)
|
||||
return -1010;
|
||||
|
||||
vBarHeader = *((UINT16*) &vBars[0]);
|
||||
suboffset += 2;
|
||||
|
||||
if ((vBarHeader & 0xC000) == 0x8000) /* VBAR_CACHE_HIT */
|
||||
{
|
||||
vBarIndex = (vBarHeader & 0x7FFF);
|
||||
|
||||
printf("VBAR_CACHE_HIT: vBarIndex: %d\n",
|
||||
vBarIndex);
|
||||
}
|
||||
else if ((vBarHeader & 0xC000) == 0xC000) /* SHORT_VBAR_CACHE_HIT */
|
||||
{
|
||||
vBarIndex = (vBarHeader & 0x3FFF);
|
||||
|
||||
if ((bandsByteCount - suboffset) < 1)
|
||||
return -1011;
|
||||
|
||||
vBarYOn = vBars[2];
|
||||
suboffset += 1;
|
||||
|
||||
printf("SHORT_VBAR_CACHE_HIT: vBarIndex: %d vBarYOn: %d\n",
|
||||
vBarIndex, vBarYOn);
|
||||
}
|
||||
else if ((vBarHeader & 0xC000) == 0x0000) /* SHORT_VBAR_CACHE_MISS */
|
||||
{
|
||||
vBarYOn = (vBarHeader & 0xFF);
|
||||
vBarYOff = ((vBarHeader >> 8) & 0x3F);
|
||||
|
||||
if (vBarYOff < vBarYOn)
|
||||
return -1012;
|
||||
|
||||
/* shortVBarPixels: variable */
|
||||
|
||||
vBarPixelCount = (3 * (vBarYOff - vBarYOn));
|
||||
|
||||
printf("SHORT_VBAR_CACHE_MISS: vBarYOn: %d vBarYOff: %d bytes: %d\n",
|
||||
vBarYOn, vBarYOff, vBarPixelCount);
|
||||
|
||||
if ((bandsByteCount - suboffset) < vBarPixelCount)
|
||||
return -1013;
|
||||
|
||||
suboffset += vBarPixelCount;
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1014; /* invalid vBarHeader */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Decompress bands layer and write to output bitmap */
|
||||
offset += bandsByteCount;
|
||||
}
|
||||
|
||||
if (subcodecByteCount > 0)
|
||||
{
|
||||
UINT16 xStart;
|
||||
UINT16 yStart;
|
||||
UINT16 width;
|
||||
UINT16 height;
|
||||
BYTE* bitmapData;
|
||||
UINT32 bitmapDataByteCount;
|
||||
BYTE subcodecId;
|
||||
BYTE* subcodecs;
|
||||
UINT32 suboffset;
|
||||
|
||||
if ((SrcSize - offset) < subcodecByteCount)
|
||||
return -1015;
|
||||
|
||||
suboffset = 0;
|
||||
subcodecs = &pSrcData[offset];
|
||||
|
||||
while (suboffset < subcodecByteCount)
|
||||
{
|
||||
if ((subcodecByteCount - suboffset) < 13)
|
||||
return -1016;
|
||||
|
||||
xStart = *((UINT16*) &subcodecs[suboffset]);
|
||||
yStart = *((UINT16*) &subcodecs[suboffset + 2]);
|
||||
width = *((UINT16*) &subcodecs[suboffset + 4]);
|
||||
height = *((UINT16*) &subcodecs[suboffset + 6]);
|
||||
bitmapDataByteCount = *((UINT32*) &subcodecs[suboffset + 8]);
|
||||
subcodecId = subcodecs[suboffset + 12];
|
||||
suboffset += 13;
|
||||
|
||||
printf("bitmapDataByteCount: %d subcodecByteCount: %d suboffset: %d subCodecId: %d\n",
|
||||
bitmapDataByteCount, subcodecByteCount, suboffset, subcodecId);
|
||||
|
||||
if ((subcodecByteCount - suboffset) < bitmapDataByteCount)
|
||||
return -1017;
|
||||
|
||||
bitmapData = &subcodecs[suboffset];
|
||||
|
||||
suboffset += bitmapDataByteCount;
|
||||
}
|
||||
|
||||
/* Decompress subcodec layer and write to output bitmap */
|
||||
offset += subcodecByteCount;
|
||||
}
|
||||
|
||||
if (glyphFlags & CLEARCODEC_FLAG_GLYPH_INDEX)
|
||||
{
|
||||
/**
|
||||
* Copy decompressed bitmap to the Decompressor Glyph
|
||||
* Storage position specified by the glyphIndex field
|
||||
*/
|
||||
}
|
||||
|
||||
if (offset != SrcSize)
|
||||
{
|
||||
printf("clear_decompress: incomplete processing of bytes: Actual: %d, Expected: %d\n", offset, SrcSize);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int clear_compress(CLEAR_CONTEXT* clear, BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstData, UINT32* pDstSize)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
void clear_context_reset(CLEAR_CONTEXT* clear)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
CLEAR_CONTEXT* clear_context_new(BOOL Compressor)
|
||||
{
|
||||
CLEAR_CONTEXT* clear;
|
||||
|
||||
clear = (CLEAR_CONTEXT*) calloc(1, sizeof(CLEAR_CONTEXT));
|
||||
|
||||
if (clear)
|
||||
{
|
||||
clear->Compressor = Compressor;
|
||||
|
||||
clear_context_reset(clear);
|
||||
}
|
||||
|
||||
return clear;
|
||||
}
|
||||
|
||||
void clear_context_free(CLEAR_CONTEXT* clear)
|
||||
{
|
||||
if (clear)
|
||||
{
|
||||
free(clear);
|
||||
}
|
||||
}
|
||||
|
@ -1175,18 +1175,34 @@ void freerdp_clrconv_free(HCLRCONV clrconv)
|
||||
int freerdp_image_copy(BYTE* pDstData, DWORD dwDstFormat, int nDstStep, int nXDst, int nYDst,
|
||||
int nWidth, int nHeight, BYTE* pSrcData, DWORD dwSrcFormat, int nSrcStep, int nXSrc, int nYSrc)
|
||||
{
|
||||
int i, j;
|
||||
int x, y;
|
||||
int srcFlip;
|
||||
int dstFlip;
|
||||
BYTE a, r, g, b;
|
||||
int beg, end, inc;
|
||||
int srcBitsPerPixel;
|
||||
int srcBytesPerPixel;
|
||||
int dstBitsPerPixel;
|
||||
int dstBytesPerPixel;
|
||||
BOOL overlap = FALSE;
|
||||
BOOL vFlip = FALSE;
|
||||
|
||||
srcBitsPerPixel = FREERDP_PIXEL_FORMAT_DEPTH(dwSrcFormat);
|
||||
srcBytesPerPixel = (FREERDP_PIXEL_FORMAT_BPP(dwSrcFormat) / 8);
|
||||
srcFlip = FREERDP_PIXEL_FORMAT_FLIP(dwSrcFormat);
|
||||
|
||||
dstBitsPerPixel = FREERDP_PIXEL_FORMAT_DEPTH(dwDstFormat);
|
||||
dstBytesPerPixel = (FREERDP_PIXEL_FORMAT_BPP(dwDstFormat) / 8);
|
||||
dstFlip = FREERDP_PIXEL_FORMAT_FLIP(dwDstFormat);
|
||||
|
||||
if (srcFlip != dstFlip)
|
||||
vFlip = TRUE;
|
||||
|
||||
if (pDstData == pSrcData)
|
||||
{
|
||||
overlap = (((nXDst + nWidth) > nXSrc) && (nXDst < (nXSrc + nWidth)) &&
|
||||
((nYDst + nHeight) > nYSrc) && (nYDst < (nYSrc + nHeight))) ? TRUE : FALSE;
|
||||
}
|
||||
|
||||
if (srcBytesPerPixel == 4)
|
||||
{
|
||||
@ -1195,7 +1211,7 @@ int freerdp_image_copy(BYTE* pDstData, DWORD dwDstFormat, int nDstStep, int nXDs
|
||||
|
||||
if (srcBitsPerPixel == 24)
|
||||
{
|
||||
if (dstBytesPerPixel == 4)
|
||||
if (dstBytesPerPixel == 4) /* srcBytesPerPixel == dstBytesPerPixel */
|
||||
{
|
||||
if (dstBitsPerPixel == 32)
|
||||
{
|
||||
@ -1208,9 +1224,9 @@ int freerdp_image_copy(BYTE* pDstData, DWORD dwDstFormat, int nDstStep, int nXDs
|
||||
pSrcPixel = (UINT32*) &pSrcData[(nYSrc * nSrcStep) + (nXSrc * srcBytesPerPixel)];
|
||||
pDstPixel = (UINT32*) &pDstData[(nYDst * nDstStep) + (nXDst * dstBytesPerPixel)];
|
||||
|
||||
for (i = 0; i < nHeight; i++)
|
||||
for (y = 0; y < nHeight; y++)
|
||||
{
|
||||
for (j = 0; j < nWidth; j++)
|
||||
for (x = 0; x < nWidth; x++)
|
||||
{
|
||||
GetARGB32(a, r, g, b, *pSrcPixel);
|
||||
*pDstPixel = ARGB32(a, r, g, b);
|
||||
@ -1223,7 +1239,7 @@ int freerdp_image_copy(BYTE* pDstData, DWORD dwDstFormat, int nDstStep, int nXDs
|
||||
pDstPixel = (UINT32*) &((BYTE*) pDstPixel)[(nDstStep - (nWidth * dstBytesPerPixel))];
|
||||
}
|
||||
}
|
||||
else if (dstBitsPerPixel == 24)
|
||||
else if (dstBitsPerPixel == 24) /* srcBitsPerPixel == dstBitsPerPixel */
|
||||
{
|
||||
UINT32* pSrcPixel;
|
||||
UINT32* pDstPixel;
|
||||
@ -1231,22 +1247,36 @@ int freerdp_image_copy(BYTE* pDstData, DWORD dwDstFormat, int nDstStep, int nXDs
|
||||
if (nDstStep < 0)
|
||||
nDstStep = dstBytesPerPixel * nWidth;
|
||||
|
||||
pSrcPixel = (UINT32*) &pSrcData[(nYSrc * nSrcStep) + (nXSrc * srcBytesPerPixel)];
|
||||
pDstPixel = (UINT32*) &pDstData[(nYDst * nDstStep) + (nXDst * dstBytesPerPixel)];
|
||||
|
||||
for (i = 0; i < nHeight; i++)
|
||||
if (overlap && (nYSrc < nYDst))
|
||||
{
|
||||
for (j = 0; j < nWidth; j++)
|
||||
beg = nHeight - 1;
|
||||
inc = -1; /* downward copy */
|
||||
end = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
beg = 0;
|
||||
inc = 1; /* upward copy */
|
||||
end = nHeight;
|
||||
}
|
||||
|
||||
if (!vFlip)
|
||||
{
|
||||
for (y = beg; y != end; y += inc)
|
||||
{
|
||||
GetRGB32(r, g, b, *pSrcPixel);
|
||||
*pDstPixel = RGB32(r, g, b);
|
||||
|
||||
pSrcPixel++;
|
||||
pDstPixel++;
|
||||
pSrcPixel = (UINT32*) &pSrcData[((nYSrc + y) * nSrcStep) + (nXSrc * srcBytesPerPixel)];
|
||||
pDstPixel = (UINT32*) &pDstData[((nYDst + y) * nDstStep) + (nXDst * dstBytesPerPixel)];
|
||||
MoveMemory(pDstPixel, pSrcPixel, nWidth * 4);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (y = beg; y != end; y += inc)
|
||||
{
|
||||
pSrcPixel = (UINT32*) &pSrcData[((nYSrc + y) * nSrcStep) + (nXSrc * srcBytesPerPixel)];
|
||||
pDstPixel = (UINT32*) &pDstData[((nYDst + (nHeight - y - 1)) * nDstStep) + (nXDst * dstBytesPerPixel)];
|
||||
MoveMemory(pDstPixel, pSrcPixel, nWidth * 4);
|
||||
}
|
||||
|
||||
pSrcPixel = (UINT32*) &((BYTE*) pSrcPixel)[(nSrcStep - (nWidth * srcBytesPerPixel))];
|
||||
pDstPixel = (UINT32*) &((BYTE*) pDstPixel)[(nDstStep - (nWidth * dstBytesPerPixel))];
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1261,9 +1291,9 @@ int freerdp_image_copy(BYTE* pDstData, DWORD dwDstFormat, int nDstStep, int nXDs
|
||||
pSrcPixel = (UINT32*) &pSrcData[(nYSrc * nSrcStep) + (nXSrc * srcBytesPerPixel)];
|
||||
pDstPixel = (BYTE*) &pDstData[(nYDst * nDstStep) + (nXDst * dstBytesPerPixel)];
|
||||
|
||||
for (i = 0; i < nHeight; i++)
|
||||
for (y = 0; y < nHeight; y++)
|
||||
{
|
||||
for (j = 0; j < nWidth; j++)
|
||||
for (x = 0; x < nWidth; x++)
|
||||
{
|
||||
GetRGB32(r, g, b, *pSrcPixel);
|
||||
|
||||
@ -1291,9 +1321,9 @@ int freerdp_image_copy(BYTE* pDstData, DWORD dwDstFormat, int nDstStep, int nXDs
|
||||
pSrcPixel = (UINT32*) &pSrcData[(nYSrc * nSrcStep) + (nXSrc * srcBytesPerPixel)];
|
||||
pDstPixel = (UINT16*) &pDstData[(nYDst * nDstStep) + (nXDst * dstBytesPerPixel)];
|
||||
|
||||
for (i = 0; i < nHeight; i++)
|
||||
for (y = 0; y < nHeight; y++)
|
||||
{
|
||||
for (j = 0; j < nWidth; j++)
|
||||
for (x = 0; x < nWidth; x++)
|
||||
{
|
||||
GetRGB32(r, g, b, *pSrcPixel);
|
||||
RGB_888_565(r, g, b);
|
||||
@ -1318,9 +1348,9 @@ int freerdp_image_copy(BYTE* pDstData, DWORD dwDstFormat, int nDstStep, int nXDs
|
||||
pSrcPixel = (UINT32*) &pSrcData[(nYSrc * nSrcStep) + (nXSrc * srcBytesPerPixel)];
|
||||
pDstPixel = (UINT16*) &pDstData[(nYDst * nDstStep) + (nXDst * dstBytesPerPixel)];
|
||||
|
||||
for (i = 0; i < nHeight; i++)
|
||||
for (y = 0; y < nHeight; y++)
|
||||
{
|
||||
for (j = 0; j < nWidth; j++)
|
||||
for (x = 0; x < nWidth; x++)
|
||||
{
|
||||
GetRGB32(r, g, b, *pSrcPixel);
|
||||
RGB_888_555(r, g, b);
|
||||
@ -1340,3 +1370,56 @@ int freerdp_image_copy(BYTE* pDstData, DWORD dwDstFormat, int nDstStep, int nXDs
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void* freerdp_image_memset32(UINT32* ptr, UINT32 fill, size_t length)
|
||||
{
|
||||
while (length--)
|
||||
{
|
||||
*ptr++ = fill;
|
||||
}
|
||||
|
||||
return (void*) ptr;
|
||||
}
|
||||
|
||||
int freerdp_image_fill(BYTE* pDstData, DWORD dwDstFormat, int nDstStep, int nXDst, int nYDst,
|
||||
int nWidth, int nHeight, UINT32 color)
|
||||
{
|
||||
int y;
|
||||
int dstBitsPerPixel;
|
||||
int dstBytesPerPixel;
|
||||
|
||||
dstBitsPerPixel = FREERDP_PIXEL_FORMAT_DEPTH(dwDstFormat);
|
||||
dstBytesPerPixel = (FREERDP_PIXEL_FORMAT_BPP(dwDstFormat) / 8);
|
||||
|
||||
if (dstBytesPerPixel == 4)
|
||||
{
|
||||
UINT32* pDstPixel;
|
||||
|
||||
if (nDstStep < 0)
|
||||
nDstStep = dstBytesPerPixel * nWidth;
|
||||
|
||||
for (y = 0; y < nHeight; y++)
|
||||
{
|
||||
pDstPixel = (UINT32*) &pDstData[((nYDst + y) * nDstStep) + (nXDst * dstBytesPerPixel)];
|
||||
freerdp_image_memset32(pDstPixel, color, nWidth);
|
||||
}
|
||||
}
|
||||
else if (dstBytesPerPixel == 3)
|
||||
{
|
||||
|
||||
}
|
||||
else if (dstBytesPerPixel == 2)
|
||||
{
|
||||
if (dstBitsPerPixel == 16)
|
||||
{
|
||||
|
||||
}
|
||||
else if (dstBitsPerPixel == 15)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -28,54 +28,59 @@
|
||||
|
||||
#include "planar.h"
|
||||
|
||||
static int freerdp_bitmap_planar_decompress_plane_rle(BYTE* inPlane, int width, int height, BYTE* outPlane, int srcSize)
|
||||
static int planar_decompress_plane_rle(BYTE* pSrcData, UINT32 SrcSize, BYTE* pDstData,
|
||||
int nDstStep, int nXDst, int nYDst, int nWidth, int nHeight, int nChannel, BOOL vFlip)
|
||||
{
|
||||
int k;
|
||||
int x, y;
|
||||
BYTE* srcp;
|
||||
BYTE* dstp;
|
||||
UINT32 pixel;
|
||||
int scanline;
|
||||
int cRawBytes;
|
||||
int nRunLength;
|
||||
int deltaValue;
|
||||
int beg, end, inc;
|
||||
BYTE controlByte;
|
||||
BYTE* currentScanline;
|
||||
BYTE* previousScanline;
|
||||
|
||||
k = 0;
|
||||
|
||||
srcp = inPlane;
|
||||
dstp = outPlane;
|
||||
scanline = width * 4;
|
||||
srcp = pSrcData;
|
||||
dstp = pDstData;
|
||||
previousScanline = NULL;
|
||||
|
||||
y = 0;
|
||||
|
||||
while (y < height)
|
||||
if (vFlip)
|
||||
{
|
||||
beg = nHeight - 1;
|
||||
end = -1;
|
||||
inc = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
beg = 0;
|
||||
end = nHeight;
|
||||
inc = 1;
|
||||
}
|
||||
|
||||
for (y = beg; y != end; y += inc)
|
||||
{
|
||||
dstp = &pDstData[((nYDst + y) * nDstStep) + (nXDst * 4) + nChannel];
|
||||
|
||||
pixel = 0;
|
||||
dstp = (outPlane + height * scanline) - ((y + 1) * scanline);
|
||||
currentScanline = dstp;
|
||||
|
||||
x = 0;
|
||||
|
||||
while (x < width)
|
||||
for (x = 0; x < nWidth; )
|
||||
{
|
||||
controlByte = *srcp;
|
||||
srcp++;
|
||||
|
||||
if ((srcp - inPlane) > srcSize)
|
||||
if ((srcp - pSrcData) > SrcSize)
|
||||
{
|
||||
printf("freerdp_bitmap_planar_decompress_plane_rle: error reading input buffer\n");
|
||||
fprintf(stderr, "planar_decompress_plane_rle: error reading input buffer\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
nRunLength = PLANAR_CONTROL_BYTE_RUN_LENGTH(controlByte);
|
||||
cRawBytes = PLANAR_CONTROL_BYTE_RAW_BYTES(controlByte);
|
||||
|
||||
//printf("CONTROL(%d, %d)\n", cRawBytes, nRunLength);
|
||||
|
||||
if (nRunLength == 1)
|
||||
{
|
||||
nRunLength = cRawBytes + 16;
|
||||
@ -87,23 +92,9 @@ static int freerdp_bitmap_planar_decompress_plane_rle(BYTE* inPlane, int width,
|
||||
cRawBytes = 0;
|
||||
}
|
||||
|
||||
#if 0
|
||||
printf("y: %d cRawBytes: %d nRunLength: %d\n", y, cRawBytes, nRunLength);
|
||||
|
||||
printf("RAW[");
|
||||
|
||||
for (k = 0; k < cRawBytes; k++)
|
||||
if (((dstp + (cRawBytes + nRunLength)) - currentScanline) > nWidth * 4)
|
||||
{
|
||||
printf("0x%02X%s", srcp[k],
|
||||
((k + 1) == cRawBytes) ? "" : ", ");
|
||||
}
|
||||
|
||||
printf("] RUN[%d]\n", nRunLength);
|
||||
#endif
|
||||
|
||||
if (((dstp + (cRawBytes + nRunLength)) - currentScanline) > width * 4)
|
||||
{
|
||||
printf("freerdp_bitmap_planar_decompress_plane_rle: too many pixels in scanline\n");
|
||||
fprintf(stderr, "planar_decompress_plane_rle: too many pixels in scanline\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -170,34 +161,76 @@ static int freerdp_bitmap_planar_decompress_plane_rle(BYTE* inPlane, int width,
|
||||
}
|
||||
|
||||
previousScanline = currentScanline;
|
||||
y++;
|
||||
}
|
||||
|
||||
return (int) (srcp - inPlane);
|
||||
return (int) (srcp - pSrcData);
|
||||
}
|
||||
|
||||
static int freerdp_bitmap_planar_decompress_plane_raw(BYTE* srcData, int width, int height, BYTE* dstData, int size)
|
||||
static int planar_decompress_plane_raw(BYTE* pSrcData, UINT32 SrcSize, BYTE* pDstData,
|
||||
int nDstStep, int nXDst, int nYDst, int nWidth, int nHeight, int nChannel, BOOL vFlip)
|
||||
{
|
||||
int x, y;
|
||||
int beg, end, inc;
|
||||
BYTE* dstp = NULL;
|
||||
BYTE* srcp = pSrcData;
|
||||
|
||||
for (y = 0; y < height; y++)
|
||||
if (vFlip)
|
||||
{
|
||||
for (x = 0; x < width; x++)
|
||||
beg = nHeight - 1;
|
||||
end = -1;
|
||||
inc = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
beg = 0;
|
||||
end = nHeight;
|
||||
inc = 1;
|
||||
}
|
||||
|
||||
for (y = beg; y != end; y += inc)
|
||||
{
|
||||
dstp = &pDstData[((nYDst + y) * nDstStep) + (nXDst * 4) + nChannel];
|
||||
|
||||
for (x = 0; x < nWidth; x++)
|
||||
{
|
||||
dstData[(((height - y - 1) * width) + x) * 4] = srcData[((y * width) + x)];
|
||||
*dstp = *srcp;
|
||||
dstp += 4;
|
||||
srcp++;
|
||||
}
|
||||
}
|
||||
|
||||
return (width * height);
|
||||
return (int) (srcp - pSrcData);
|
||||
}
|
||||
|
||||
int freerdp_bitmap_planar_decompress(BYTE* srcData, BYTE* dstData, int width, int height, int size)
|
||||
int planar_decompress(BITMAP_PLANAR_CONTEXT* planar, BYTE* pSrcData, UINT32 SrcSize,
|
||||
BYTE** ppDstData, DWORD DstFormat, int nDstStep, int nXDst, int nYDst, int nWidth, int nHeight)
|
||||
{
|
||||
int status;
|
||||
BYTE* srcp;
|
||||
int dstSize;
|
||||
BOOL vFlip;
|
||||
BYTE FormatHeader;
|
||||
BYTE* pDstData = NULL;
|
||||
UINT32 UncompressedSize;
|
||||
|
||||
srcp = srcData;
|
||||
if ((nWidth * nHeight) <= 0)
|
||||
return -1;
|
||||
|
||||
vFlip = FREERDP_PIXEL_FORMAT_FLIP(DstFormat) ? TRUE : FALSE;
|
||||
|
||||
srcp = pSrcData;
|
||||
UncompressedSize = nWidth * nHeight * 4;
|
||||
|
||||
pDstData = *ppDstData;
|
||||
|
||||
if (!pDstData)
|
||||
{
|
||||
pDstData = (BYTE*) malloc(UncompressedSize);
|
||||
|
||||
if (!pDstData)
|
||||
return -1;
|
||||
|
||||
*ppDstData = pDstData;
|
||||
}
|
||||
|
||||
FormatHeader = *srcp;
|
||||
srcp++;
|
||||
@ -208,17 +241,23 @@ int freerdp_bitmap_planar_decompress(BYTE* srcData, BYTE* dstData, int width, in
|
||||
{
|
||||
if (FormatHeader & PLANAR_FORMAT_HEADER_RLE)
|
||||
{
|
||||
dstSize = freerdp_bitmap_planar_decompress_plane_rle(srcp, width, height, dstData + 3, size - (srcp - srcData));
|
||||
status = planar_decompress_plane_rle(srcp, SrcSize - (srcp - pSrcData),
|
||||
pDstData, nDstStep, nXDst, nYDst, nWidth, nHeight, 3, vFlip);
|
||||
|
||||
if (dstSize < 0)
|
||||
if (status < 0)
|
||||
return -1;
|
||||
|
||||
srcp += dstSize;
|
||||
srcp += status;
|
||||
}
|
||||
else
|
||||
{
|
||||
dstSize = freerdp_bitmap_planar_decompress_plane_raw(srcp, width, height, dstData + 3, size - (srcp - srcData));
|
||||
srcp += dstSize;
|
||||
status = planar_decompress_plane_raw(srcp, SrcSize - (srcp - pSrcData),
|
||||
pDstData, nDstStep, nXDst, nYDst, nWidth, nHeight, 3, vFlip);
|
||||
|
||||
if (status < 0)
|
||||
return -1;
|
||||
|
||||
srcp += status;
|
||||
}
|
||||
}
|
||||
|
||||
@ -226,51 +265,71 @@ int freerdp_bitmap_planar_decompress(BYTE* srcData, BYTE* dstData, int width, in
|
||||
{
|
||||
/* LumaOrRedPlane */
|
||||
|
||||
dstSize = freerdp_bitmap_planar_decompress_plane_rle(srcp, width, height, dstData + 2, size - (srcp - srcData));
|
||||
status = planar_decompress_plane_rle(srcp, SrcSize - (srcp - pSrcData),
|
||||
pDstData, nDstStep, nXDst, nYDst, nWidth, nHeight, 2, vFlip);
|
||||
|
||||
if (dstSize < 0)
|
||||
if (status < 0)
|
||||
return -1;
|
||||
|
||||
srcp += dstSize;
|
||||
srcp += status;
|
||||
|
||||
/* OrangeChromaOrGreenPlane */
|
||||
|
||||
dstSize = freerdp_bitmap_planar_decompress_plane_rle(srcp, width, height, dstData + 1, size - (srcp - srcData));
|
||||
status = planar_decompress_plane_rle(srcp, SrcSize - (srcp - pSrcData),
|
||||
pDstData, nDstStep, nXDst, nYDst, nWidth, nHeight, 1, vFlip);
|
||||
|
||||
if (dstSize < 0)
|
||||
if (status < 0)
|
||||
return -1;
|
||||
|
||||
srcp += dstSize;
|
||||
srcp += status;
|
||||
|
||||
/* GreenChromeOrBluePlane */
|
||||
|
||||
dstSize = freerdp_bitmap_planar_decompress_plane_rle(srcp, width, height, dstData + 0, size - (srcp - srcData));
|
||||
status = planar_decompress_plane_rle(srcp, SrcSize - (srcp - pSrcData),
|
||||
pDstData, nDstStep, nXDst, nYDst, nWidth, nHeight, 0, vFlip);
|
||||
|
||||
if (dstSize < 0)
|
||||
if (status < 0)
|
||||
return -1;
|
||||
|
||||
srcp += dstSize;
|
||||
srcp += status;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* LumaOrRedPlane */
|
||||
|
||||
dstSize = freerdp_bitmap_planar_decompress_plane_raw(srcp, width, height, dstData + 2, size - (srcp - srcData));
|
||||
srcp += dstSize;
|
||||
status = planar_decompress_plane_raw(srcp, SrcSize - (srcp - pSrcData),
|
||||
pDstData, nDstStep, nXDst, nYDst, nWidth, nHeight, 2, vFlip);
|
||||
|
||||
if (status < 0)
|
||||
return -1;
|
||||
|
||||
srcp += status;
|
||||
|
||||
/* OrangeChromaOrGreenPlane */
|
||||
|
||||
dstSize = freerdp_bitmap_planar_decompress_plane_raw(srcp, width, height, dstData + 1, size - (srcp - srcData));
|
||||
srcp += dstSize;
|
||||
status = planar_decompress_plane_raw(srcp, SrcSize - (srcp - pSrcData),
|
||||
pDstData, nDstStep, nXDst, nYDst, nWidth, nHeight, 1, vFlip);
|
||||
|
||||
if (status < 0)
|
||||
return -1;
|
||||
|
||||
srcp += status;
|
||||
|
||||
/* GreenChromeOrBluePlane */
|
||||
|
||||
dstSize = freerdp_bitmap_planar_decompress_plane_raw(srcp, width, height, dstData + 0, size - (srcp - srcData));
|
||||
srcp += dstSize;
|
||||
status = planar_decompress_plane_raw(srcp, SrcSize - (srcp - pSrcData),
|
||||
pDstData, nDstStep, nXDst, nYDst, nWidth, nHeight, 0, vFlip);
|
||||
|
||||
if (status < 0)
|
||||
return -1;
|
||||
|
||||
srcp += status;
|
||||
srcp++;
|
||||
}
|
||||
|
||||
return (size == (srcp - srcData)) ? 0 : -1;
|
||||
status = (SrcSize == (srcp - pSrcData)) ? 1 : -1;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
int freerdp_split_color_planes(BYTE* data, UINT32 format, int width, int height, int scanline, BYTE* planes[4])
|
||||
|
@ -87,8 +87,6 @@ struct _BITMAP_PLANAR_CONTEXT
|
||||
BYTE* rlePlanesBuffer;
|
||||
};
|
||||
|
||||
FREERDP_API int freerdp_bitmap_planar_decompress(BYTE* srcData, BYTE* dstData, int width, int height, int size);
|
||||
|
||||
FREERDP_API int freerdp_split_color_planes(BYTE* data, UINT32 format, int width, int height, int scanline, BYTE* planes[4]);
|
||||
FREERDP_API BYTE* freerdp_bitmap_planar_compress_plane_rle(BYTE* plane, int width, int height, BYTE* outPlane, int* dstSize);
|
||||
FREERDP_API BYTE* freerdp_bitmap_planar_delta_encode_plane(BYTE* inPlane, int width, int height, BYTE* outPlane);
|
||||
|
@ -107,13 +107,14 @@ const RECTANGLE_16 *region16_rects(const REGION16 *region, int *nbRects)
|
||||
|
||||
static INLINE RECTANGLE_16 *region16_rects_noconst(REGION16 *region)
|
||||
{
|
||||
REGION16_DATA *data;
|
||||
REGION16_DATA* data;
|
||||
|
||||
data = region->data;
|
||||
if (!data)
|
||||
return 0;
|
||||
|
||||
return (RECTANGLE_16 *)(data + 1);
|
||||
if (!data)
|
||||
return NULL;
|
||||
|
||||
return (RECTANGLE_16*)(&data[1]);
|
||||
}
|
||||
|
||||
const RECTANGLE_16 *region16_extents(const REGION16 *region)
|
||||
@ -158,20 +159,24 @@ void region16_clear(REGION16 *region)
|
||||
|
||||
if (region->data->size)
|
||||
free(region->data);
|
||||
|
||||
region->data = &empty_region;
|
||||
|
||||
ZeroMemory(®ion->extents, sizeof(region->extents));
|
||||
}
|
||||
|
||||
static INLINE REGION16_DATA *allocateRegion(long nbItems)
|
||||
static INLINE REGION16_DATA* allocateRegion(long nbItems)
|
||||
{
|
||||
long allocSize = sizeof(REGION16_DATA) + nbItems * sizeof(RECTANGLE_16);
|
||||
REGION16_DATA *ret = (REGION16_DATA *)malloc(allocSize);
|
||||
long allocSize = sizeof(REGION16_DATA) + (nbItems * sizeof(RECTANGLE_16));
|
||||
|
||||
REGION16_DATA* ret = (REGION16_DATA*) malloc(allocSize);
|
||||
|
||||
if (!ret)
|
||||
return ret;
|
||||
|
||||
ret->size = allocSize;
|
||||
ret->nbRects = nbItems;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -186,6 +191,7 @@ BOOL region16_copy(REGION16 *dst, const REGION16 *src)
|
||||
return TRUE;
|
||||
|
||||
dst->extents = src->extents;
|
||||
|
||||
if (dst->data->size)
|
||||
free(dst->data);
|
||||
|
||||
@ -196,11 +202,13 @@ BOOL region16_copy(REGION16 *dst, const REGION16 *src)
|
||||
else
|
||||
{
|
||||
dst->data = allocateRegion(src->data->nbRects);
|
||||
|
||||
if (!dst->data)
|
||||
return FALSE;
|
||||
|
||||
memcpy(dst->data, src->data, src->data->size);
|
||||
CopyMemory(dst->data, src->data, src->data->size);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@ -310,29 +318,34 @@ void region16_copy_band_with_union(RECTANGLE_16 *dst,
|
||||
src++; dst++; *dstCounter += 1;
|
||||
}
|
||||
|
||||
if(srcPtr)
|
||||
if (srcPtr)
|
||||
*srcPtr = src;
|
||||
|
||||
*dstPtr = dst;
|
||||
}
|
||||
|
||||
static RECTANGLE_16 *next_band(RECTANGLE_16 *band1, RECTANGLE_16 *endPtr, int *nbItems)
|
||||
static RECTANGLE_16* next_band(RECTANGLE_16* band1, RECTANGLE_16* endPtr, int* nbItems)
|
||||
{
|
||||
UINT16 refY = band1->top;
|
||||
|
||||
*nbItems = 0;
|
||||
while((band1 < endPtr) && (band1->top == refY)) {
|
||||
|
||||
while((band1 < endPtr) && (band1->top == refY))
|
||||
{
|
||||
band1++;
|
||||
*nbItems += 1;
|
||||
}
|
||||
|
||||
return band1;
|
||||
}
|
||||
|
||||
static BOOL band_match(const RECTANGLE_16 *band1, const RECTANGLE_16 *band2, RECTANGLE_16 *endPtr)
|
||||
static BOOL band_match(const RECTANGLE_16* band1, const RECTANGLE_16* band2, RECTANGLE_16* endPtr)
|
||||
{
|
||||
int refBand2 = band2->top;
|
||||
const RECTANGLE_16 *band2Start = band2;
|
||||
const RECTANGLE_16* band2Start = band2;
|
||||
|
||||
while ((band1 < band2Start) && (band2 < endPtr) && (band2->top == refBand2)) {
|
||||
while ((band1 < band2Start) && (band2 < endPtr) && (band2->top == refBand2))
|
||||
{
|
||||
if ((band1->left != band2->left) || (band1->right != band2->right))
|
||||
return FALSE;
|
||||
|
||||
@ -391,14 +404,17 @@ BOOL region16_simplify_bands(REGION16 *region)
|
||||
int bandItems, toMove;
|
||||
|
||||
finalNbRects = nbRects = region16_n_rects(region);
|
||||
|
||||
if (nbRects < 2)
|
||||
return TRUE;
|
||||
|
||||
band1 = region16_rects_noconst(region);
|
||||
endPtr = band1 + nbRects;
|
||||
|
||||
do {
|
||||
do
|
||||
{
|
||||
band2 = next_band(band1, endPtr, &bandItems);
|
||||
|
||||
if (band2 == endPtr)
|
||||
break;
|
||||
|
||||
@ -416,38 +432,45 @@ BOOL region16_simplify_bands(REGION16 *region)
|
||||
* may be merged too */
|
||||
endBand = band2 + bandItems;
|
||||
toMove = (endPtr - endBand) * sizeof(RECTANGLE_16);
|
||||
|
||||
if (toMove)
|
||||
memmove(band2, endBand, toMove);
|
||||
MoveMemory(band2, endBand, toMove);
|
||||
|
||||
finalNbRects -= bandItems;
|
||||
endPtr -= bandItems;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
band1 = band2;
|
||||
}
|
||||
} while(TRUE);
|
||||
}
|
||||
while(TRUE);
|
||||
|
||||
if (finalNbRects != nbRects)
|
||||
{
|
||||
int allocSize = sizeof(REGION16_DATA) + finalNbRects * sizeof(RECTANGLE_16);
|
||||
int allocSize = sizeof(REGION16_DATA) + (finalNbRects * sizeof(RECTANGLE_16));
|
||||
region->data = realloc(region->data, allocSize);
|
||||
|
||||
if (!region->data)
|
||||
{
|
||||
region->data = &empty_region;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
region->data->nbRects = finalNbRects;
|
||||
region->data->size = allocSize;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
BOOL region16_union_rect(REGION16 *dst, const REGION16 *src, const RECTANGLE_16 *rect)
|
||||
{
|
||||
const RECTANGLE_16 *srcExtents;
|
||||
RECTANGLE_16 *dstExtents;
|
||||
const RECTANGLE_16* srcExtents;
|
||||
RECTANGLE_16* dstExtents;
|
||||
const RECTANGLE_16 *currentBand, *endSrcRect, *nextBand;
|
||||
REGION16_DATA *newItems;
|
||||
RECTANGLE_16 *dstRect;
|
||||
REGION16_DATA* newItems = NULL;
|
||||
RECTANGLE_16* dstRect = NULL;
|
||||
int usedRects, srcNbRects;
|
||||
UINT16 topInterBand;
|
||||
|
||||
@ -463,19 +486,26 @@ BOOL region16_union_rect(REGION16 *dst, const REGION16 *src, const RECTANGLE_16
|
||||
/* source is empty, so the union is rect */
|
||||
dst->extents = *rect;
|
||||
dst->data = allocateRegion(1);
|
||||
|
||||
if (!dst->data)
|
||||
return FALSE;
|
||||
|
||||
dstRect = region16_rects_noconst(dst);
|
||||
*dstRect = *rect;
|
||||
|
||||
dstRect->top = rect->top;
|
||||
dstRect->left = rect->left;
|
||||
dstRect->right = rect->right;
|
||||
dstRect->bottom = rect->bottom;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
newItems = allocateRegion((1 + region16_n_rects(src)) * 2);
|
||||
newItems = allocateRegion((1 + region16_n_rects(src)) * 4);
|
||||
|
||||
if (!newItems)
|
||||
return FALSE;
|
||||
|
||||
dstRect = (RECTANGLE_16 *)(newItems + 1);
|
||||
dstRect = (RECTANGLE_16*) (&newItems[1]);
|
||||
usedRects = 0;
|
||||
|
||||
/* adds the piece of rect that is on the top of src */
|
||||
@ -497,8 +527,7 @@ BOOL region16_union_rect(REGION16 *dst, const REGION16 *src, const RECTANGLE_16
|
||||
while (currentBand < endSrcRect)
|
||||
{
|
||||
if ((currentBand->bottom <= rect->top) || (rect->bottom <= currentBand->top) ||
|
||||
rectangle_contained_in_band(currentBand, endSrcRect, rect)
|
||||
)
|
||||
rectangle_contained_in_band(currentBand, endSrcRect, rect))
|
||||
{
|
||||
/* no overlap between rect and the band, rect is totally below or totally above
|
||||
* the current band, or rect is already covered by an item of the band.
|
||||
@ -560,9 +589,10 @@ BOOL region16_union_rect(REGION16 *dst, const REGION16 *src, const RECTANGLE_16
|
||||
mergeTop = rect->top;
|
||||
}
|
||||
|
||||
/* do the merge zone (all cases ) */
|
||||
/* do the merge zone (all cases) */
|
||||
if (rect->bottom < currentBand->bottom)
|
||||
mergeBottom = rect->bottom;
|
||||
|
||||
region16_copy_band_with_union(dstRect,
|
||||
currentBand, endSrcRect,
|
||||
mergeTop, mergeBottom,
|
||||
@ -629,19 +659,20 @@ BOOL region16_union_rect(REGION16 *dst, const REGION16 *src, const RECTANGLE_16
|
||||
dstExtents->bottom = MAX(rect->bottom, srcExtents->bottom);
|
||||
dstExtents->right = MAX(rect->right, srcExtents->right);
|
||||
|
||||
newItems->size = sizeof(REGION16_DATA) + usedRects * sizeof(RECTANGLE_16);
|
||||
newItems->size = sizeof(REGION16_DATA) + (usedRects * sizeof(RECTANGLE_16));
|
||||
dst->data = realloc(newItems, newItems->size);
|
||||
|
||||
if (!dst->data)
|
||||
{
|
||||
free(newItems);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
dst->data->nbRects = usedRects;
|
||||
|
||||
return region16_simplify_bands(dst);
|
||||
}
|
||||
|
||||
|
||||
BOOL region16_intersects_rect(const REGION16 *src, const RECTANGLE_16 *arg2)
|
||||
{
|
||||
const RECTANGLE_16 *rect, *endPtr, *srcExtents;
|
||||
@ -651,10 +682,12 @@ BOOL region16_intersects_rect(const REGION16 *src, const RECTANGLE_16 *arg2)
|
||||
assert(src->data);
|
||||
|
||||
rect = region16_rects(src, &nbRects);
|
||||
|
||||
if (!nbRects)
|
||||
return FALSE;
|
||||
|
||||
srcExtents = region16_extents(src);
|
||||
|
||||
if (nbRects == 1)
|
||||
return rectangles_intersects(srcExtents, arg2);
|
||||
|
||||
@ -684,6 +717,7 @@ BOOL region16_intersect_rect(REGION16 *dst, const REGION16 *src, const RECTANGLE
|
||||
assert(src->data);
|
||||
|
||||
srcPtr = region16_rects(src, &nbRects);
|
||||
|
||||
if (!nbRects)
|
||||
{
|
||||
region16_clear(dst);
|
||||
@ -691,27 +725,32 @@ BOOL region16_intersect_rect(REGION16 *dst, const REGION16 *src, const RECTANGLE
|
||||
}
|
||||
|
||||
srcExtents = region16_extents(src);
|
||||
|
||||
if (nbRects == 1)
|
||||
{
|
||||
BOOL intersects = rectangles_intersection(srcExtents, rect, &common);
|
||||
|
||||
region16_clear(dst);
|
||||
|
||||
if (intersects)
|
||||
return region16_union_rect(dst, dst, &common);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
newItems = allocateRegion(nbRects);
|
||||
|
||||
if (!newItems)
|
||||
return FALSE;
|
||||
dstPtr = (RECTANGLE_16 *)(newItems + 1);
|
||||
|
||||
dstPtr = (RECTANGLE_16*) (&newItems[1]);
|
||||
usedRects = 0;
|
||||
ZeroMemory(&newExtents, sizeof(newExtents));
|
||||
|
||||
/* accumulate intersecting rectangles, the final region16_simplify_bands() will
|
||||
* do all the bad job to recreate correct rectangles
|
||||
*/
|
||||
for(endPtr = srcPtr + nbRects; (srcPtr < endPtr) && (rect->bottom > srcPtr->top); srcPtr++)
|
||||
for (endPtr = srcPtr + nbRects; (srcPtr < endPtr) && (rect->bottom > srcPtr->top); srcPtr++)
|
||||
{
|
||||
if (rectangles_intersection(srcPtr, rect, &common))
|
||||
{
|
||||
@ -727,13 +766,15 @@ BOOL region16_intersect_rect(REGION16 *dst, const REGION16 *src, const RECTANGLE
|
||||
}
|
||||
|
||||
newItems->nbRects = usedRects;
|
||||
newItems->size = sizeof(REGION16_DATA) + usedRects * sizeof(RECTANGLE_16);
|
||||
newItems->size = sizeof(REGION16_DATA) + (usedRects * sizeof(RECTANGLE_16));
|
||||
|
||||
if (dst->data->size)
|
||||
free(dst->data);
|
||||
|
||||
dst->data = realloc(newItems, newItems->size);
|
||||
if (!dst->data) {
|
||||
|
||||
if (!dst->data)
|
||||
{
|
||||
free(newItems);
|
||||
return FALSE;
|
||||
}
|
||||
@ -742,15 +783,13 @@ BOOL region16_intersect_rect(REGION16 *dst, const REGION16 *src, const RECTANGLE
|
||||
return region16_simplify_bands(dst);
|
||||
}
|
||||
|
||||
void region16_uninit(REGION16 *region) {
|
||||
void region16_uninit(REGION16 *region)
|
||||
{
|
||||
assert(region);
|
||||
assert(region->data);
|
||||
|
||||
if(region->data->size)
|
||||
if (region->data->size)
|
||||
free(region->data);
|
||||
region->data = 0;
|
||||
|
||||
region->data = NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -9,7 +9,9 @@ set(${MODULE_PREFIX}_TESTS
|
||||
TestFreeRDPCodecMppc.c
|
||||
TestFreeRDPCodecNCrush.c
|
||||
TestFreeRDPCodecXCrush.c
|
||||
TestFreeRDPCodecZGfx.c
|
||||
TestFreeRDPCodecPlanar.c
|
||||
TestFreeRDPCodecClear.c
|
||||
TestFreeRDPCodecRemoteFX.c)
|
||||
|
||||
create_test_sourcelist(${MODULE_PREFIX}_SRCS
|
||||
|
144
libfreerdp/codec/test/TestFreeRDPCodecClear.c
Normal file
144
libfreerdp/codec/test/TestFreeRDPCodecClear.c
Normal file
@ -0,0 +1,144 @@
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/print.h>
|
||||
|
||||
#include <freerdp/codec/clear.h>
|
||||
|
||||
static BYTE TEST_CLEAR_EXAMPLE_1[] = "\x03\xc3\x11\x00";
|
||||
|
||||
static BYTE TEST_CLEAR_EXAMPLE_2[] =
|
||||
"\x00\x0d\x00\x00\x00\x00\x00\x00\x00\x00\x82\x00\x00\x00\x00\x00"
|
||||
"\x00\x00\x4e\x00\x11\x00\x75\x00\x00\x00\x02\x0e\xff\xff\xff\x00"
|
||||
"\x00\x00\xdb\xff\xff\x00\x3a\x90\xff\xb6\x66\x66\xb6\xff\xb6\x66"
|
||||
"\x00\x90\xdb\xff\x00\x00\x3a\xdb\x90\x3a\x3a\x90\xdb\x66\x00\x00"
|
||||
"\xff\xff\xb6\x64\x64\x64\x11\x04\x11\x4c\x11\x4c\x11\x4c\x11\x4c"
|
||||
"\x11\x4c\x00\x47\x13\x00\x01\x01\x04\x00\x01\x00\x00\x47\x16\x00"
|
||||
"\x11\x02\x00\x47\x29\x00\x11\x01\x00\x49\x0a\x00\x01\x00\x04\x00"
|
||||
"\x01\x00\x00\x4a\x0a\x00\x09\x00\x01\x00\x00\x47\x05\x00\x01\x01"
|
||||
"\x1c\x00\x01\x00\x11\x4c\x11\x4c\x11\x4c\x00\x47\x0d\x4d\x00\x4d";
|
||||
|
||||
static BYTE TEST_CLEAR_EXAMPLE_3[] =
|
||||
"\x00\xdf\x0e\x00\x00\x00\x8b\x00\x00\x00\x00\x00\x00\x00\xfe\xfe"
|
||||
"\xfe\xff\x80\x05\xff\xff\xff\x40\xfe\xfe\xfe\x40\x00\x00\x3f\x00"
|
||||
"\x03\x00\x0b\x00\xfe\xfe\xfe\xc5\xd0\xc6\xd0\xc7\xd0\x68\xd4\x69"
|
||||
"\xd4\x6a\xd4\x6b\xd4\x6c\xd4\x6d\xd4\x1a\xd4\x1a\xd4\xa6\xd0\x6e"
|
||||
"\xd4\x6f\xd4\x70\xd4\x71\xd4\x72\xd4\x73\xd4\x74\xd4\x21\xd4\x22"
|
||||
"\xd4\x23\xd4\x24\xd4\x25\xd4\xd9\xd0\xda\xd0\xdb\xd0\xc5\xd0\xc5"
|
||||
"\xd0\xdc\xd0\xc2\xd0\x21\xd4\x22\xd4\x23\xd4\x24\xd4\x25\xd4\xc9"
|
||||
"\xd0\xca\xd0\x5a\xd4\x2b\xd1\x28\xd1\x2c\xd1\x75\xd4\x27\xd4\x28"
|
||||
"\xd4\x29\xd4\x2a\xd4\x1a\xd4\x1a\xd4\x1a\xd4\xb7\xd0\xb8\xd0\xb9"
|
||||
"\xd0\xba\xd0\xbb\xd0\xbc\xd0\xbd\xd0\xbe\xd0\xbf\xd0\xc0\xd0\xc1"
|
||||
"\xd0\xc2\xd0\xc3\xd0\xc4\xd0";
|
||||
|
||||
static BYTE TEST_CLEAR_EXAMPLE_4[] =
|
||||
"\x01\x0b\x78\x00\x00\x00\x00\x00\x46\x00\x00\x00\x00\x00\x00\x00"
|
||||
"\x00\x00\x06\x00\x00\x00\x0e\x00\x00\x00\x00\x00\x0f\xff\xff\xff"
|
||||
"\xff\xff\xff\xff\xff\xff\xb6\xff\xff\xff\xff\xff\xff\xff\xff\xff"
|
||||
"\xb6\x66\xff\xff\xff\xff\xff\xff\xff\xb6\x66\xdb\x90\x3a\xff\xff"
|
||||
"\xb6\xff\xff\xff\xff\xff\xff\xff\xff\xff\x46\x91\x47\x91\x48\x91"
|
||||
"\x49\x91\x4a\x91\x1b\x91";
|
||||
|
||||
int test_ClearDecompressExample1()
|
||||
{
|
||||
int status;
|
||||
BYTE* pSrcData;
|
||||
UINT32 SrcSize;
|
||||
UINT32 DstSize;
|
||||
BYTE* pDstData = NULL;
|
||||
CLEAR_CONTEXT* clear;
|
||||
|
||||
clear = clear_context_new(FALSE);
|
||||
|
||||
SrcSize = sizeof(TEST_CLEAR_EXAMPLE_1) - 1;
|
||||
pSrcData = (BYTE*) TEST_CLEAR_EXAMPLE_1;
|
||||
|
||||
status = clear_decompress(clear, pSrcData, SrcSize, &pDstData, &DstSize);
|
||||
|
||||
printf("clear_decompress example 1 status: %d\n", status);
|
||||
|
||||
clear_context_free(clear);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_ClearDecompressExample2()
|
||||
{
|
||||
int status;
|
||||
BYTE* pSrcData;
|
||||
UINT32 SrcSize;
|
||||
UINT32 DstSize;
|
||||
BYTE* pDstData = NULL;
|
||||
CLEAR_CONTEXT* clear;
|
||||
|
||||
clear = clear_context_new(FALSE);
|
||||
|
||||
SrcSize = sizeof(TEST_CLEAR_EXAMPLE_2) - 1;
|
||||
pSrcData = (BYTE*) TEST_CLEAR_EXAMPLE_2;
|
||||
|
||||
status = clear_decompress(clear, pSrcData, SrcSize, &pDstData, &DstSize);
|
||||
|
||||
printf("clear_decompress example 2 status: %d\n", status);
|
||||
|
||||
clear_context_free(clear);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_ClearDecompressExample3()
|
||||
{
|
||||
int status;
|
||||
BYTE* pSrcData;
|
||||
UINT32 SrcSize;
|
||||
UINT32 DstSize;
|
||||
BYTE* pDstData = NULL;
|
||||
CLEAR_CONTEXT* clear;
|
||||
|
||||
clear = clear_context_new(FALSE);
|
||||
|
||||
SrcSize = sizeof(TEST_CLEAR_EXAMPLE_3) - 1;
|
||||
pSrcData = (BYTE*) TEST_CLEAR_EXAMPLE_3;
|
||||
|
||||
status = clear_decompress(clear, pSrcData, SrcSize, &pDstData, &DstSize);
|
||||
|
||||
printf("clear_decompress example 3 status: %d\n", status);
|
||||
|
||||
clear_context_free(clear);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_ClearDecompressExample4()
|
||||
{
|
||||
int status;
|
||||
BYTE* pSrcData;
|
||||
UINT32 SrcSize;
|
||||
UINT32 DstSize;
|
||||
BYTE* pDstData = NULL;
|
||||
CLEAR_CONTEXT* clear;
|
||||
|
||||
clear = clear_context_new(FALSE);
|
||||
|
||||
SrcSize = sizeof(TEST_CLEAR_EXAMPLE_4) - 1;
|
||||
pSrcData = (BYTE*) TEST_CLEAR_EXAMPLE_4;
|
||||
|
||||
status = clear_decompress(clear, pSrcData, SrcSize, &pDstData, &DstSize);
|
||||
|
||||
printf("clear_decompress example 4 status: %d\n", status);
|
||||
|
||||
clear_context_free(clear);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int TestFreeRDPCodecClear(int argc, char* argv[])
|
||||
{
|
||||
//test_ClearDecompressExample1();
|
||||
|
||||
//test_ClearDecompressExample2();
|
||||
|
||||
//test_ClearDecompressExample3();
|
||||
|
||||
test_ClearDecompressExample4();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
10
libfreerdp/codec/test/TestFreeRDPCodecZGfx.c
Normal file
10
libfreerdp/codec/test/TestFreeRDPCodecZGfx.c
Normal file
@ -0,0 +1,10 @@
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/print.h>
|
||||
|
||||
#include <freerdp/codec/zgfx.h>
|
||||
|
||||
int TestFreeRDPCodecZGfx(int argc, char* argv[])
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
417
libfreerdp/codec/zgfx.c
Normal file
417
libfreerdp/codec/zgfx.c
Normal file
@ -0,0 +1,417 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* ZGFX (RDP8) Bulk Data Compression
|
||||
*
|
||||
* 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/print.h>
|
||||
#include <winpr/bitstream.h>
|
||||
|
||||
#include <freerdp/codec/zgfx.h>
|
||||
|
||||
/**
|
||||
* RDP8 Compressor Limits:
|
||||
*
|
||||
* Maximum number of uncompressed bytes in a single segment: 65535
|
||||
* Maximum match distance / minimum history size: 2500000 bytes.
|
||||
* Maximum number of segments: 65535
|
||||
* Maximum expansion of a segment (when compressed size exceeds uncompressed): 1000 bytes
|
||||
* Minimum match length: 3 bytes
|
||||
*/
|
||||
|
||||
struct _ZGFX_TOKEN
|
||||
{
|
||||
int prefixLength;
|
||||
int prefixCode;
|
||||
int valueBits;
|
||||
int tokenType;
|
||||
UINT32 valueBase;
|
||||
};
|
||||
typedef struct _ZGFX_TOKEN ZGFX_TOKEN;
|
||||
|
||||
static const ZGFX_TOKEN ZGFX_TOKEN_TABLE[] =
|
||||
{
|
||||
// len code vbits type vbase
|
||||
{ 1, 0, 8, 0, 0 }, // 0
|
||||
{ 5, 17, 5, 1, 0 }, // 10001
|
||||
{ 5, 18, 7, 1, 32 }, // 10010
|
||||
{ 5, 19, 9, 1, 160 }, // 10011
|
||||
{ 5, 20, 10, 1, 672 }, // 10100
|
||||
{ 5, 21, 12, 1, 1696 }, // 10101
|
||||
{ 5, 24, 0, 0, 0x00 }, // 11000
|
||||
{ 5, 25, 0, 0, 0x01 }, // 11001
|
||||
{ 6, 44, 14, 1, 5792 }, // 101100
|
||||
{ 6, 45, 15, 1, 22176 }, // 101101
|
||||
{ 6, 52, 0, 0, 0x02 }, // 110100
|
||||
{ 6, 53, 0, 0, 0x03 }, // 110101
|
||||
{ 6, 54, 0, 0, 0xFF }, // 110110
|
||||
{ 7, 92, 18, 1, 54944 }, // 1011100
|
||||
{ 7, 93, 20, 1, 317088 }, // 1011101
|
||||
{ 7, 110, 0, 0, 0x04 }, // 1101110
|
||||
{ 7, 111, 0, 0, 0x05 }, // 1101111
|
||||
{ 7, 112, 0, 0, 0x06 }, // 1110000
|
||||
{ 7, 113, 0, 0, 0x07 }, // 1110001
|
||||
{ 7, 114, 0, 0, 0x08 }, // 1110010
|
||||
{ 7, 115, 0, 0, 0x09 }, // 1110011
|
||||
{ 7, 116, 0, 0, 0x0A }, // 1110100
|
||||
{ 7, 117, 0, 0, 0x0B }, // 1110101
|
||||
{ 7, 118, 0, 0, 0x3A }, // 1110110
|
||||
{ 7, 119, 0, 0, 0x3B }, // 1110111
|
||||
{ 7, 120, 0, 0, 0x3C }, // 1111000
|
||||
{ 7, 121, 0, 0, 0x3D }, // 1111001
|
||||
{ 7, 122, 0, 0, 0x3E }, // 1111010
|
||||
{ 7, 123, 0, 0, 0x3F }, // 1111011
|
||||
{ 7, 124, 0, 0, 0x40 }, // 1111100
|
||||
{ 7, 125, 0, 0, 0x80 }, // 1111101
|
||||
{ 8, 188, 20, 1, 1365664 }, // 10111100
|
||||
{ 8, 189, 21, 1, 2414240 }, // 10111101
|
||||
{ 8, 252, 0, 0, 0x0C }, // 11111100
|
||||
{ 8, 253, 0, 0, 0x38 }, // 11111101
|
||||
{ 8, 254, 0, 0, 0x39 }, // 11111110
|
||||
{ 8, 255, 0, 0, 0x66 }, // 11111111
|
||||
{ 9, 380, 22, 1, 4511392 }, // 101111100
|
||||
{ 9, 381, 23, 1, 8705696 }, // 101111101
|
||||
{ 9, 382, 24, 1, 17094304 }, // 101111110
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
#define zgfx_GetBits(_zgfx, _nbits) \
|
||||
while (_zgfx->cBitsCurrent < _nbits) { \
|
||||
_zgfx->BitsCurrent <<= 8; \
|
||||
if (_zgfx->pbInputCurrent < _zgfx->pbInputEnd) \
|
||||
_zgfx->BitsCurrent += *(_zgfx->pbInputCurrent)++; \
|
||||
_zgfx->cBitsCurrent += 8; \
|
||||
} \
|
||||
_zgfx->cBitsRemaining -= _nbits; \
|
||||
_zgfx->cBitsCurrent -= _nbits; \
|
||||
_zgfx->bits = _zgfx->BitsCurrent >> _zgfx->cBitsCurrent; \
|
||||
_zgfx->BitsCurrent &= ((1 << _zgfx->cBitsCurrent) - 1);
|
||||
|
||||
void zgfx_history_buffer_ring_write(ZGFX_CONTEXT* zgfx, BYTE* src, UINT32 count)
|
||||
{
|
||||
UINT32 front;
|
||||
UINT32 residue;
|
||||
|
||||
if (count <= 0)
|
||||
return;
|
||||
|
||||
if (count > zgfx->HistoryBufferSize)
|
||||
{
|
||||
residue = count - zgfx->HistoryBufferSize;
|
||||
count = zgfx->HistoryBufferSize;
|
||||
src += residue;
|
||||
|
||||
zgfx->HistoryIndex = (zgfx->HistoryIndex + residue) % zgfx->HistoryBufferSize;
|
||||
}
|
||||
|
||||
if (zgfx->HistoryIndex + count <= zgfx->HistoryBufferSize)
|
||||
{
|
||||
CopyMemory(&(zgfx->HistoryBuffer[zgfx->HistoryIndex]), src, count);
|
||||
|
||||
if ((zgfx->HistoryIndex += count) == zgfx->HistoryBufferSize)
|
||||
zgfx->HistoryIndex = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
front = zgfx->HistoryBufferSize - zgfx->HistoryIndex;
|
||||
CopyMemory(&(zgfx->HistoryBuffer[zgfx->HistoryIndex]), src, front);
|
||||
CopyMemory(zgfx->HistoryBuffer, &src[front], count - front);
|
||||
zgfx->HistoryIndex = count - front;
|
||||
}
|
||||
}
|
||||
|
||||
void zgfx_history_buffer_ring_read(ZGFX_CONTEXT* zgfx, int offset, BYTE* dst, UINT32 count)
|
||||
{
|
||||
UINT32 front;
|
||||
UINT32 index;
|
||||
UINT32 bytes;
|
||||
UINT32 valid;
|
||||
UINT32 bytesLeft;
|
||||
BYTE* dptr = dst;
|
||||
BYTE* origDst = dst;
|
||||
|
||||
if (count <= 0)
|
||||
return;
|
||||
|
||||
bytesLeft = count;
|
||||
|
||||
index = (zgfx->HistoryIndex + zgfx->HistoryBufferSize - offset) % zgfx->HistoryBufferSize;
|
||||
|
||||
bytes = MIN(bytesLeft, offset);
|
||||
|
||||
if ((index + bytes) <= zgfx->HistoryBufferSize)
|
||||
{
|
||||
CopyMemory(dptr, &(zgfx->HistoryBuffer[index]), bytes);
|
||||
}
|
||||
else
|
||||
{
|
||||
front = zgfx->HistoryBufferSize - index;
|
||||
CopyMemory(dptr, &(zgfx->HistoryBuffer[index]), front);
|
||||
CopyMemory(&dptr[front], zgfx->HistoryBuffer, bytes - front);
|
||||
}
|
||||
|
||||
if ((bytesLeft -= bytes) == 0)
|
||||
return;
|
||||
|
||||
dptr += bytes;
|
||||
valid = bytes;
|
||||
|
||||
do
|
||||
{
|
||||
bytes = valid;
|
||||
|
||||
if (bytes > bytesLeft)
|
||||
bytes = bytesLeft;
|
||||
|
||||
CopyMemory(dptr, origDst, bytes);
|
||||
dptr += bytes;
|
||||
valid <<= 1;
|
||||
}
|
||||
while ((bytesLeft -= bytes) > 0);
|
||||
}
|
||||
|
||||
int zgfx_decompress_segment(ZGFX_CONTEXT* zgfx, BYTE* pbSegment, UINT32 cbSegment)
|
||||
{
|
||||
BYTE c;
|
||||
BYTE flags;
|
||||
int extra;
|
||||
int opIndex;
|
||||
int haveBits;
|
||||
int inPrefix;
|
||||
UINT32 count;
|
||||
UINT32 distance;
|
||||
|
||||
if (cbSegment < 1)
|
||||
return -1;
|
||||
|
||||
flags = pbSegment[0]; /* header (1 byte) */
|
||||
|
||||
pbSegment++;
|
||||
cbSegment--;
|
||||
|
||||
zgfx->OutputCount = 0;
|
||||
|
||||
if (!(flags & PACKET_COMPRESSED))
|
||||
{
|
||||
zgfx_history_buffer_ring_write(zgfx, pbSegment, cbSegment);
|
||||
CopyMemory(zgfx->OutputBuffer, pbSegment, cbSegment);
|
||||
zgfx->OutputCount = cbSegment;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
zgfx->pbInputCurrent = pbSegment;
|
||||
zgfx->pbInputEnd = &pbSegment[cbSegment - 1];
|
||||
|
||||
/* NumberOfBitsToDecode = ((NumberOfBytesToDecode - 1) * 8) - ValueOfLastByte */
|
||||
zgfx->cBitsRemaining = 8 * (cbSegment - 1) - *zgfx->pbInputEnd;
|
||||
zgfx->cBitsCurrent = 0;
|
||||
zgfx->BitsCurrent = 0;
|
||||
|
||||
while (zgfx->cBitsRemaining)
|
||||
{
|
||||
haveBits = 0;
|
||||
inPrefix = 0;
|
||||
|
||||
for (opIndex = 0; ZGFX_TOKEN_TABLE[opIndex].prefixLength != 0; opIndex++)
|
||||
{
|
||||
while (haveBits < ZGFX_TOKEN_TABLE[opIndex].prefixLength)
|
||||
{
|
||||
zgfx_GetBits(zgfx, 1);
|
||||
inPrefix = (inPrefix << 1) + zgfx->bits;
|
||||
haveBits++;
|
||||
}
|
||||
|
||||
if (inPrefix == ZGFX_TOKEN_TABLE[opIndex].prefixCode)
|
||||
{
|
||||
if (ZGFX_TOKEN_TABLE[opIndex].tokenType == 0)
|
||||
{
|
||||
/* Literal */
|
||||
|
||||
zgfx_GetBits(zgfx, ZGFX_TOKEN_TABLE[opIndex].valueBits);
|
||||
c = (BYTE) (ZGFX_TOKEN_TABLE[opIndex].valueBase + zgfx->bits);
|
||||
|
||||
zgfx->HistoryBuffer[zgfx->HistoryIndex] = c;
|
||||
|
||||
if (++zgfx->HistoryIndex == zgfx->HistoryBufferSize)
|
||||
zgfx->HistoryIndex = 0;
|
||||
|
||||
zgfx->OutputBuffer[zgfx->OutputCount++] = c;
|
||||
}
|
||||
else
|
||||
{
|
||||
zgfx_GetBits(zgfx, ZGFX_TOKEN_TABLE[opIndex].valueBits);
|
||||
distance = ZGFX_TOKEN_TABLE[opIndex].valueBase + zgfx->bits;
|
||||
|
||||
if (distance != 0)
|
||||
{
|
||||
/* Match */
|
||||
|
||||
zgfx_GetBits(zgfx, 1);
|
||||
|
||||
if (zgfx->bits == 0)
|
||||
{
|
||||
count = 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
count = 4;
|
||||
extra = 2;
|
||||
|
||||
zgfx_GetBits(zgfx, 1);
|
||||
|
||||
while (zgfx->bits == 1)
|
||||
{
|
||||
count *= 2;
|
||||
extra++;
|
||||
|
||||
zgfx_GetBits(zgfx, 1);
|
||||
}
|
||||
|
||||
zgfx_GetBits(zgfx, extra);
|
||||
count += zgfx->bits;
|
||||
}
|
||||
|
||||
zgfx_history_buffer_ring_read(zgfx, distance, &(zgfx->OutputBuffer[zgfx->OutputCount]), count);
|
||||
zgfx_history_buffer_ring_write(zgfx, &(zgfx->OutputBuffer[zgfx->OutputCount]), count);
|
||||
zgfx->OutputCount += count;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Unencoded */
|
||||
|
||||
zgfx_GetBits(zgfx, 15);
|
||||
count = zgfx->bits;
|
||||
|
||||
zgfx->cBitsRemaining -= zgfx->cBitsCurrent;
|
||||
zgfx->cBitsCurrent = 0;
|
||||
zgfx->BitsCurrent = 0;
|
||||
|
||||
CopyMemory(&(zgfx->OutputBuffer[zgfx->OutputCount]), zgfx->pbInputCurrent, count);
|
||||
zgfx_history_buffer_ring_write(zgfx, zgfx->pbInputCurrent, count);
|
||||
|
||||
zgfx->pbInputCurrent += count;
|
||||
zgfx->cBitsRemaining -= (8 * count);
|
||||
zgfx->OutputCount += count;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int zgfx_decompress(ZGFX_CONTEXT* zgfx, BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstData, UINT32* pDstSize, UINT32 flags)
|
||||
{
|
||||
int status;
|
||||
BYTE descriptor;
|
||||
|
||||
if (SrcSize < 1)
|
||||
return -1;
|
||||
|
||||
descriptor = pSrcData[0]; /* descriptor (1 byte) */
|
||||
|
||||
if (descriptor == ZGFX_SEGMENTED_SINGLE)
|
||||
{
|
||||
status = zgfx_decompress_segment(zgfx, &pSrcData[1], SrcSize - 1);
|
||||
|
||||
*ppDstData = (BYTE*) malloc(zgfx->OutputCount);
|
||||
*pDstSize = zgfx->OutputCount;
|
||||
|
||||
CopyMemory(*ppDstData, zgfx->OutputBuffer, zgfx->OutputCount);
|
||||
}
|
||||
else if (descriptor == ZGFX_SEGMENTED_MULTIPART)
|
||||
{
|
||||
UINT32 segmentSize;
|
||||
UINT16 segmentNumber;
|
||||
UINT16 segmentCount;
|
||||
UINT32 segmentOffset;
|
||||
UINT32 uncompressedSize;
|
||||
BYTE* pConcatenated;
|
||||
|
||||
segmentOffset = 7;
|
||||
segmentCount = *((UINT16*) &pSrcData[1]); /* segmentCount (2 bytes) */
|
||||
uncompressedSize = *((UINT32*) &pSrcData[3]); /* uncompressedSize (4 bytes) */
|
||||
|
||||
pConcatenated = (BYTE*) malloc(uncompressedSize);
|
||||
|
||||
*ppDstData = pConcatenated;
|
||||
*pDstSize = uncompressedSize;
|
||||
|
||||
for (segmentNumber = 0; segmentNumber < segmentCount; segmentNumber++)
|
||||
{
|
||||
segmentSize = *((UINT32*) &pSrcData[segmentOffset]); /* segmentSize (4 bytes) */
|
||||
segmentOffset += 4;
|
||||
|
||||
status = zgfx_decompress_segment(zgfx, &pSrcData[segmentOffset], segmentSize);
|
||||
segmentOffset += segmentSize;
|
||||
|
||||
CopyMemory(pConcatenated, zgfx->OutputBuffer, zgfx->OutputCount);
|
||||
pConcatenated += zgfx->OutputCount;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int zgfx_compress(ZGFX_CONTEXT* zgfx, BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstData, UINT32* pDstSize, UINT32* pFlags)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
void zgfx_context_reset(ZGFX_CONTEXT* zgfx, BOOL flush)
|
||||
{
|
||||
zgfx->HistoryIndex = 0;
|
||||
}
|
||||
|
||||
ZGFX_CONTEXT* zgfx_context_new(BOOL Compressor)
|
||||
{
|
||||
ZGFX_CONTEXT* zgfx;
|
||||
|
||||
zgfx = (ZGFX_CONTEXT*) calloc(1, sizeof(ZGFX_CONTEXT));
|
||||
|
||||
if (zgfx)
|
||||
{
|
||||
zgfx->Compressor = Compressor;
|
||||
|
||||
zgfx->HistoryBufferSize = sizeof(zgfx->HistoryBuffer);
|
||||
|
||||
zgfx_context_reset(zgfx, FALSE);
|
||||
}
|
||||
|
||||
return zgfx;
|
||||
}
|
||||
|
||||
void zgfx_context_free(ZGFX_CONTEXT* zgfx)
|
||||
{
|
||||
if (zgfx)
|
||||
{
|
||||
free(zgfx);
|
||||
}
|
||||
}
|
||||
|
@ -517,11 +517,16 @@ out_free:
|
||||
|
||||
void freerdp_dynamic_channel_collection_free(rdpSettings* settings)
|
||||
{
|
||||
UINT32 index;
|
||||
int j;
|
||||
UINT32 i;
|
||||
|
||||
for (index = 0; index < settings->DynamicChannelCount; index++)
|
||||
for (i = 0; i < settings->DynamicChannelCount; i++)
|
||||
{
|
||||
free(settings->DynamicChannelArray[index]);
|
||||
for (j = 0; j < settings->DynamicChannelArray[i]->argc; j++)
|
||||
free(settings->DynamicChannelArray[i]->argv[j]);
|
||||
|
||||
free(settings->DynamicChannelArray[i]->argv);
|
||||
free(settings->DynamicChannelArray[i]);
|
||||
}
|
||||
|
||||
free(settings->DynamicChannelArray);
|
||||
|
@ -72,27 +72,14 @@ rdpMcsChannel* freerdp_channels_find_channel_by_name(rdpRdp* rdp, const char* na
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* this is called shortly after the application starts and
|
||||
* before any other function in the file
|
||||
* called only from main thread
|
||||
*/
|
||||
int freerdp_channels_global_init(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int freerdp_channels_global_uninit(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
rdpChannels* freerdp_channels_new(void)
|
||||
{
|
||||
rdpChannels* channels;
|
||||
|
||||
channels = (rdpChannels*) malloc(sizeof(rdpChannels));
|
||||
ZeroMemory(channels, sizeof(rdpChannels));
|
||||
channels = (rdpChannels*) calloc(1, sizeof(rdpChannels));
|
||||
|
||||
if (!channels)
|
||||
return NULL;
|
||||
|
||||
channels->MsgPipe = MessagePipe_New();
|
||||
|
||||
@ -280,10 +267,6 @@ FREERDP_API int freerdp_channels_send_event(rdpChannels* channels, wMessage* eve
|
||||
|
||||
switch (GetMessageClass(event->id))
|
||||
{
|
||||
case DebugChannel_Class:
|
||||
name = "rdpdbg";
|
||||
break;
|
||||
|
||||
case CliprdrChannel_Class:
|
||||
name = "cliprdr";
|
||||
break;
|
||||
|
@ -169,8 +169,6 @@ BOOL freerdp_connect(freerdp* instance)
|
||||
update_recv_surfcmds(update, Stream_Length(s) , s);
|
||||
update->EndPaint(update->context);
|
||||
Stream_Release(s);
|
||||
|
||||
StreamPool_Return(rdp->transport->ReceivePool, s);
|
||||
}
|
||||
|
||||
pcap_close(update->pcap_rfx);
|
||||
|
@ -102,10 +102,11 @@ static void svc_plugin_process_received(rdpSvcPlugin* plugin, void* pData, UINT3
|
||||
|
||||
if (dataFlags & CHANNEL_FLAG_FIRST)
|
||||
{
|
||||
if (plugin->data_in != NULL)
|
||||
Stream_Free(plugin->data_in, TRUE);
|
||||
if (plugin->data_in)
|
||||
Stream_Release(plugin->data_in);
|
||||
|
||||
plugin->data_in = Stream_New(NULL, totalLength);
|
||||
plugin->data_in = StreamPool_Take(plugin->pool, totalLength);
|
||||
Stream_AddRef(plugin->data_in);
|
||||
}
|
||||
|
||||
s = plugin->data_in;
|
||||
@ -178,6 +179,7 @@ static void* svc_plugin_thread_func(void* arg)
|
||||
IFCALL(plugin->connect_callback, plugin);
|
||||
|
||||
SetEvent(plugin->started);
|
||||
|
||||
while (1)
|
||||
{
|
||||
if (!MessageQueue_Wait(plugin->MsgPipe->In))
|
||||
@ -192,6 +194,7 @@ static void* svc_plugin_thread_func(void* arg)
|
||||
{
|
||||
data = (wStream*) message.wParam;
|
||||
IFCALL(plugin->receive_callback, plugin, data);
|
||||
Stream_Release(data);
|
||||
}
|
||||
else if (message.id == 1)
|
||||
{
|
||||
@ -236,7 +239,12 @@ static void svc_plugin_process_terminated(rdpSvcPlugin* plugin)
|
||||
|
||||
MessagePipe_Free(plugin->MsgPipe);
|
||||
CloseHandle(plugin->thread);
|
||||
CloseHandle(plugin->started);
|
||||
|
||||
if (plugin->started)
|
||||
{
|
||||
CloseHandle(plugin->started);
|
||||
plugin->started = NULL;
|
||||
}
|
||||
|
||||
plugin->channel_entry_points.pVirtualChannelClose(plugin->OpenHandle);
|
||||
|
||||
@ -246,10 +254,10 @@ static void svc_plugin_process_terminated(rdpSvcPlugin* plugin)
|
||||
plugin->data_in = NULL;
|
||||
}
|
||||
|
||||
IFCALL(plugin->terminate_callback, plugin);
|
||||
|
||||
svc_plugin_remove_open_handle_data(plugin->OpenHandle);
|
||||
svc_plugin_remove_init_handle_data(plugin->InitHandle);
|
||||
|
||||
IFCALL(plugin->terminate_callback, plugin);
|
||||
}
|
||||
|
||||
static VOID VCAPITYPE svc_plugin_init_event(LPVOID pInitHandle, UINT event, LPVOID pData, UINT dataLength)
|
||||
@ -295,11 +303,27 @@ void svc_plugin_init(rdpSvcPlugin* plugin, CHANNEL_ENTRY_POINTS* pEntryPoints)
|
||||
|
||||
plugin->channel_entry_points.pInterface = *(plugin->channel_entry_points.ppInterface);
|
||||
plugin->channel_entry_points.ppInterface = &(plugin->channel_entry_points.pInterface);
|
||||
plugin->started = CreateEvent(NULL,TRUE,FALSE,NULL);
|
||||
plugin->started = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
plugin->pool = StreamPool_New(TRUE, 10);
|
||||
|
||||
svc_plugin_add_init_handle_data(plugin->InitHandle, plugin);
|
||||
}
|
||||
|
||||
void svc_plugin_terminate(rdpSvcPlugin* plugin)
|
||||
{
|
||||
if (plugin->pool)
|
||||
{
|
||||
StreamPool_Free(plugin->pool);
|
||||
plugin->pool = NULL;
|
||||
}
|
||||
|
||||
if (plugin->started)
|
||||
{
|
||||
CloseHandle(plugin->started);
|
||||
plugin->started = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int svc_plugin_send(rdpSvcPlugin* plugin, wStream* data_out)
|
||||
{
|
||||
UINT32 status = 0;
|
||||
|
@ -326,6 +326,8 @@ WINPR_API void CountdownEvent_Free(wCountdownEvent* countdown);
|
||||
|
||||
/* Hash Table */
|
||||
|
||||
typedef void (*KEY_VALUE_FREE_FN)(void* context, void* key, void* value);
|
||||
|
||||
struct _wHashTable
|
||||
{
|
||||
BOOL synchronized;
|
||||
@ -342,6 +344,9 @@ struct _wHashTable
|
||||
unsigned long (*hashFunction)(void* key);
|
||||
void (*keyDeallocator)(void* key);
|
||||
void (*valueDeallocator)(void* value);
|
||||
|
||||
void* context;
|
||||
KEY_VALUE_FREE_FN pfnKeyValueFree;
|
||||
};
|
||||
typedef struct _wHashTable wHashTable;
|
||||
|
||||
@ -354,6 +359,8 @@ WINPR_API BOOL HashTable_ContainsKey(wHashTable* table, void* key);
|
||||
WINPR_API BOOL HashTable_ContainsValue(wHashTable* table, void* value);
|
||||
WINPR_API void* HashTable_GetItemValue(wHashTable* table, void* key);
|
||||
WINPR_API BOOL HashTable_SetItemValue(wHashTable* table, void* key, void* value);
|
||||
WINPR_API void HashTable_SetFreeFunction(wHashTable* table, void* context, KEY_VALUE_FREE_FN pfnKeyValueFree);
|
||||
WINPR_API int HashTable_GetKeys(wHashTable* table, ULONG_PTR** ppKeys);
|
||||
|
||||
WINPR_API wHashTable* HashTable_New(BOOL synchronized);
|
||||
WINPR_API void HashTable_Free(wHashTable* table);
|
||||
|
@ -368,6 +368,9 @@ void HashTable_Clear(wHashTable* table)
|
||||
{
|
||||
nextPair = pair->next;
|
||||
|
||||
if (table->pfnKeyValueFree)
|
||||
table->pfnKeyValueFree(table->context, pair->key, pair->value);
|
||||
|
||||
if (table->keyDeallocator)
|
||||
table->keyDeallocator((void*) pair->key);
|
||||
|
||||
@ -389,6 +392,48 @@ void HashTable_Clear(wHashTable* table)
|
||||
LeaveCriticalSection(&table->lock);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the list of keys as an array
|
||||
*/
|
||||
|
||||
int HashTable_GetKeys(wHashTable* table, ULONG_PTR** ppKeys)
|
||||
{
|
||||
int iKey;
|
||||
int count;
|
||||
int index;
|
||||
ULONG_PTR* pKeys;
|
||||
wKeyValuePair* pair;
|
||||
wKeyValuePair* nextPair;
|
||||
|
||||
if (table->synchronized)
|
||||
EnterCriticalSection(&table->lock);
|
||||
|
||||
iKey = 0;
|
||||
count = table->numOfElements;
|
||||
pKeys = (ULONG_PTR*) calloc(count, sizeof(ULONG_PTR));
|
||||
|
||||
for (index = 0; index < table->numOfBuckets; index++)
|
||||
{
|
||||
pair = table->bucketArray[index];
|
||||
|
||||
while (pair)
|
||||
{
|
||||
nextPair = pair->next;
|
||||
|
||||
pKeys[iKey++] = (ULONG_PTR) pair->key;
|
||||
|
||||
pair = nextPair;
|
||||
}
|
||||
}
|
||||
|
||||
if (table->synchronized)
|
||||
LeaveCriticalSection(&table->lock);
|
||||
|
||||
*ppKeys = pKeys;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether the HashTable contains a specific key.
|
||||
*/
|
||||
@ -465,6 +510,12 @@ BOOL HashTable_ContainsValue(wHashTable* table, void* value)
|
||||
return status;
|
||||
}
|
||||
|
||||
void HashTable_SetFreeFunction(wHashTable* table, void* context, KEY_VALUE_FREE_FN pfnKeyValueFree)
|
||||
{
|
||||
table->context = context;
|
||||
table->pfnKeyValueFree = pfnKeyValueFree;
|
||||
}
|
||||
|
||||
/**
|
||||
* Construction, Destruction
|
||||
*/
|
||||
@ -479,7 +530,7 @@ wHashTable* HashTable_New(BOOL synchronized)
|
||||
if (table)
|
||||
{
|
||||
table->synchronized = synchronized;
|
||||
InitializeCriticalSectionAndSpinCount(&table->lock, 4000);
|
||||
InitializeCriticalSectionAndSpinCount(&(table->lock), 4000);
|
||||
|
||||
table->numOfBuckets = 64;
|
||||
table->numOfElements = 0;
|
||||
@ -537,6 +588,8 @@ void HashTable_Free(wHashTable* table)
|
||||
}
|
||||
}
|
||||
|
||||
DeleteCriticalSection(&(table->lock));
|
||||
|
||||
free(table->bucketArray);
|
||||
free(table);
|
||||
}
|
||||
|
@ -144,8 +144,7 @@ int ListDictionary_GetKeys(wListDictionary* listDictionary, ULONG_PTR** ppKeys)
|
||||
}
|
||||
}
|
||||
|
||||
pKeys = (ULONG_PTR*) malloc(sizeof(ULONG_PTR) * count);
|
||||
ZeroMemory(pKeys, sizeof(ULONG_PTR) * count);
|
||||
pKeys = (ULONG_PTR*) calloc(count, sizeof(ULONG_PTR));
|
||||
|
||||
index = 0;
|
||||
|
||||
|
@ -182,6 +182,11 @@ void StreamPool_Return(wStreamPool* pool, wStream* s)
|
||||
pool->aCapacity *= 2;
|
||||
pool->aArray = (wStream**) realloc(pool->aArray, sizeof(wStream*) * pool->aCapacity);
|
||||
}
|
||||
else if ((pool->aSize + 1) * 3 < pool->aCapacity)
|
||||
{
|
||||
pool->aCapacity /= 2;
|
||||
pool->aArray = (wStream**) realloc(pool->aArray, sizeof(wStream*) * pool->aCapacity);
|
||||
}
|
||||
|
||||
pool->aArray[(pool->aSize)++] = s;
|
||||
StreamPool_RemoveUsed(pool, s);
|
||||
|
Loading…
Reference in New Issue
Block a user