mirror of https://github.com/FreeRDP/FreeRDP
Merge remote-tracking branch 'upstream/master' into androidlib
This commit is contained in:
commit
2ca493dbf5
|
@ -685,9 +685,9 @@ void drive_register_drive_path(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints, char*
|
|||
* We cannot enter paths like c:\ because : is an arg separator
|
||||
* thus, paths are entered as c+\ and the + is substituted here
|
||||
*/
|
||||
if ( path[1] == '+' )
|
||||
if (path[1] == '+')
|
||||
{
|
||||
if ( (path[0]>='a' && path[0]<='z') || (path[0]>='A' && path[0]<='Z') )
|
||||
if ((path[0]>='a' && path[0]<='z') || (path[0]>='A' && path[0]<='Z'))
|
||||
{
|
||||
path[1] = ':';
|
||||
}
|
||||
|
@ -732,8 +732,6 @@ void drive_register_drive_path(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints, char*
|
|||
|
||||
int DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
|
||||
{
|
||||
char* name;
|
||||
char* path;
|
||||
RDPDR_DRIVE* drive;
|
||||
#ifdef WIN32
|
||||
char* dev;
|
||||
|
@ -742,20 +740,42 @@ int DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
|
|||
#endif
|
||||
|
||||
drive = (RDPDR_DRIVE*) pEntryPoints->device;
|
||||
name = drive->Name;
|
||||
path = drive->Path;
|
||||
|
||||
#ifndef WIN32
|
||||
drive_register_drive_path(pEntryPoints, name, path);
|
||||
|
||||
if (strcmp(drive->Path, "*") == 0)
|
||||
{
|
||||
/* all drives */
|
||||
|
||||
free(drive->Path);
|
||||
drive->Path = _strdup("/");
|
||||
}
|
||||
else if (strcmp(drive->Path, "%") == 0)
|
||||
{
|
||||
char* home_env = NULL;
|
||||
|
||||
/* home directory */
|
||||
|
||||
home_env = getenv("HOME");
|
||||
free(drive->Path);
|
||||
|
||||
if (home_env)
|
||||
drive->Path = _strdup(home_env);
|
||||
else
|
||||
drive->Path = _strdup("/");
|
||||
}
|
||||
|
||||
drive_register_drive_path(pEntryPoints, drive->Name, drive->Path);
|
||||
|
||||
#else
|
||||
/* Special case: path[0] == '*' -> export all drives */
|
||||
/* Special case: path[0] == '%' -> user home dir */
|
||||
if( path[0] == '%' )
|
||||
if (strcmp(drive->Path, "%") == 0)
|
||||
{
|
||||
_snprintf(buf, sizeof(buf), "%s\\", getenv("USERPROFILE"));
|
||||
drive_register_drive_path(pEntryPoints, name, _strdup(buf));
|
||||
drive_register_drive_path(pEntryPoints, drive->Name, _strdup(buf));
|
||||
}
|
||||
else if( path[0] == '*' )
|
||||
else if (strcmp(drive->Path, "*") == 0)
|
||||
{
|
||||
int i;
|
||||
|
||||
|
@ -767,7 +787,7 @@ int DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
|
|||
if (*dev > 'B')
|
||||
{
|
||||
/* Suppress disk drives A and B to avoid pesty messages */
|
||||
_snprintf(buf, sizeof(buf) - 4, "%s", name);
|
||||
_snprintf(buf, sizeof(buf) - 4, "%s", drive->Name);
|
||||
len = strlen(buf);
|
||||
buf[len] = '_';
|
||||
buf[len + 1] = dev[0];
|
||||
|
@ -779,7 +799,7 @@ int DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
|
|||
}
|
||||
else
|
||||
{
|
||||
drive_register_drive_path(pEntryPoints, name, path);
|
||||
drive_register_drive_path(pEntryPoints, drive->Name, drive->Path);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#
|
||||
# Copyright 2012 Laxmikant Rashinkar <LK.Rashinkar@gmail.com>
|
||||
# Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
# Copyright 2013 Corey Clayton <can.of.tuna@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,6 +19,10 @@
|
|||
|
||||
define_channel_client_subsystem("rdpsnd" "mac" "")
|
||||
|
||||
FIND_LIBRARY(CORE_AUDIO CoreAudio)
|
||||
FIND_LIBRARY(AUDIO_TOOL AudioToolbox)
|
||||
FIND_LIBRARY(CORE_FOUNDATION CoreFoundation)
|
||||
|
||||
set(${MODULE_PREFIX}_SRCS
|
||||
rdpsnd_mac.c)
|
||||
|
||||
|
@ -33,8 +38,10 @@ set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
|
|||
MODULE freerdp
|
||||
MODULES freerdp-utils)
|
||||
|
||||
set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} ${MAC_AUDIOTOOLBOX_LIBRARY_PATH})
|
||||
set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} ${MAC_COREFOUNDATION_LIBRARY_PATH})
|
||||
set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS}
|
||||
${AUDIO_TOOL}
|
||||
${CORE_AUDIO}
|
||||
${CORE_FOUNDATION})
|
||||
|
||||
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
|
||||
|
||||
|
|
|
@ -97,16 +97,17 @@ static void rdpsnd_audio_open(rdpsndDevicePlugin* device, rdpsndFormat* format,
|
|||
aq_plugin_p->data_format.mChannelsPerFrame = 2;
|
||||
aq_plugin_p->data_format.mBitsPerChannel = 16;
|
||||
|
||||
rv = AudioQueueNewOutput(&aq_plugin_p->data_format, // audio stream basic desc
|
||||
aq_playback_cb, // callback when more data is required
|
||||
aq_plugin_p, // data to pass to callback
|
||||
CFRunLoopGetCurrent(), // The current run loop, and the one on
|
||||
// which the audio queue playback callback
|
||||
// will be invoked
|
||||
kCFRunLoopCommonModes, // run loop modes in which callbacks can
|
||||
// be invoked
|
||||
0, // flags - reserved
|
||||
&aq_plugin_p->aq_ref
|
||||
rv = AudioQueueNewOutput(
|
||||
&aq_plugin_p->data_format, // audio stream basic desc
|
||||
aq_playback_cb, // callback when more data is required
|
||||
aq_plugin_p, // data to pass to callback
|
||||
CFRunLoopGetCurrent(), // The current run loop, and the one on
|
||||
// which the audio queue playback callback
|
||||
// will be invoked
|
||||
kCFRunLoopCommonModes, // run loop modes in which callbacks can
|
||||
// be invoked
|
||||
0, // flags - reserved
|
||||
&aq_plugin_p->aq_ref
|
||||
);
|
||||
if (rv != 0) {
|
||||
printf("rdpsnd_audio_open: AudioQueueNewOutput() failed with error %d\n", rv);
|
||||
|
@ -204,6 +205,8 @@ static void aq_playback_cb(void* user_data, AudioQueueRef aq_ref, AudioQueueBuff
|
|||
|
||||
int freerdp_rdpsnd_client_subsystem_entry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pEntryPoints)
|
||||
{
|
||||
printf("freerdp_rdpsnd_client_subsystem_entry()\n\n");
|
||||
|
||||
ADDIN_ARGV* args;
|
||||
rdpsndAudioQPlugin* aqPlugin;
|
||||
|
||||
|
|
|
@ -713,8 +713,7 @@ static BOOL xf_cliprdr_get_requested_data(xfInfo* xfi, Atom target)
|
|||
unsigned long length, bytes_left, dummy;
|
||||
clipboardContext* cb = (clipboardContext*) xfi->clipboard_context;
|
||||
|
||||
if ((cb->request_index < 0) ||
|
||||
(cb->format_mappings[cb->request_index].target_format != target))
|
||||
if ((cb->request_index < 0) || (cb->format_mappings[cb->request_index].target_format != target))
|
||||
{
|
||||
DEBUG_X11_CLIPRDR("invalid target");
|
||||
xf_cliprdr_send_null_data_response(xfi);
|
||||
|
@ -1132,6 +1131,7 @@ BOOL xf_cliprdr_process_selection_request(xfInfo* xfi, XEvent* xevent)
|
|||
{
|
||||
format = cb->format_mappings[i].format_id;
|
||||
alt_format = format;
|
||||
|
||||
if (format == CB_FORMAT_RAW)
|
||||
{
|
||||
if (XGetWindowProperty(xfi->display, xevent->xselectionrequest.requestor,
|
||||
|
@ -1146,7 +1146,9 @@ BOOL xf_cliprdr_process_selection_request(xfInfo* xfi, XEvent* xevent)
|
|||
XFree(data);
|
||||
}
|
||||
}
|
||||
|
||||
DEBUG_X11_CLIPRDR("provide format 0x%04x alt_format 0x%04x", format, alt_format);
|
||||
|
||||
if ((cb->data != 0) && (format == cb->data_format) && (alt_format == cb->data_alt_format))
|
||||
{
|
||||
/* Cached clipboard data available. Send it now */
|
||||
|
@ -1206,6 +1208,9 @@ BOOL xf_cliprdr_process_property_notify(xfInfo* xfi, XEvent* xevent)
|
|||
{
|
||||
clipboardContext* cb = (clipboardContext*) xfi->clipboard_context;
|
||||
|
||||
if (!cb)
|
||||
return TRUE;
|
||||
|
||||
if (xevent->xproperty.atom != cb->property_atom)
|
||||
return FALSE; /* Not cliprdr-related */
|
||||
|
||||
|
|
|
@ -83,7 +83,7 @@ static BOOL xf_event_Expose(xfInfo* xfi, XEvent* event, BOOL app)
|
|||
w = event->xexpose.width;
|
||||
h = event->xexpose.height;
|
||||
|
||||
if (app != TRUE)
|
||||
if (!app)
|
||||
{
|
||||
XCopyArea(xfi->display, xfi->primary, xfi->window->handle, xfi->gc, x, y, w, h, x, y);
|
||||
}
|
||||
|
@ -381,7 +381,7 @@ static BOOL xf_event_FocusIn(xfInfo* xfi, XEvent* event, BOOL app)
|
|||
|
||||
xfi->focused = TRUE;
|
||||
|
||||
if (xfi->mouse_active && (app != TRUE))
|
||||
if (xfi->mouse_active && (!app))
|
||||
XGrabKeyboard(xfi->display, xfi->window->handle, TRUE, GrabModeAsync, GrabModeAsync, CurrentTime);
|
||||
|
||||
if (app)
|
||||
|
@ -397,9 +397,10 @@ static BOOL xf_event_FocusIn(xfInfo* xfi, XEvent* event, BOOL app)
|
|||
if (window != NULL)
|
||||
xf_rail_adjust_position(xfi, window);
|
||||
}
|
||||
|
||||
xf_kbd_focus_in(xfi);
|
||||
|
||||
if (app != TRUE)
|
||||
if (!app)
|
||||
xf_cliprdr_check_owner(xfi);
|
||||
|
||||
return TRUE;
|
||||
|
@ -466,7 +467,7 @@ static BOOL xf_event_ClientMessage(xfInfo* xfi, XEvent* event, BOOL app)
|
|||
|
||||
static BOOL xf_event_EnterNotify(xfInfo* xfi, XEvent* event, BOOL app)
|
||||
{
|
||||
if (app != TRUE)
|
||||
if (!app)
|
||||
{
|
||||
xfi->mouse_active = TRUE;
|
||||
|
||||
|
@ -497,7 +498,7 @@ static BOOL xf_event_EnterNotify(xfInfo* xfi, XEvent* event, BOOL app)
|
|||
|
||||
static BOOL xf_event_LeaveNotify(xfInfo* xfi, XEvent* event, BOOL app)
|
||||
{
|
||||
if (app != TRUE)
|
||||
if (!app)
|
||||
{
|
||||
xfi->mouse_active = FALSE;
|
||||
XUngrabKeyboard(xfi->display, CurrentTime);
|
||||
|
@ -573,17 +574,14 @@ static BOOL xf_event_MapNotify(xfInfo* xfi, XEvent* event, BOOL app)
|
|||
rdpUpdate* update = xfi->instance->update;
|
||||
rdpRail* rail = ((rdpContext*) xfi->context)->rail;
|
||||
|
||||
if (app != TRUE)
|
||||
if (!app)
|
||||
{
|
||||
if (xfi->suppress_output == TRUE)
|
||||
{
|
||||
xfi->suppress_output = FALSE;
|
||||
rect.left = 0;
|
||||
rect.top = 0;
|
||||
rect.right = xfi->width;
|
||||
rect.bottom = xfi->height;
|
||||
update->SuppressOutput((rdpContext*) xfi->context, 1, &rect);
|
||||
}
|
||||
rect.left = 0;
|
||||
rect.top = 0;
|
||||
rect.right = xfi->width;
|
||||
rect.bottom = xfi->height;
|
||||
|
||||
update->SuppressOutput((rdpContext*) xfi->context, 1, &rect);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -615,13 +613,9 @@ static BOOL xf_event_UnmapNotify(xfInfo* xfi, XEvent* event, BOOL app)
|
|||
|
||||
xf_kbd_release_all_keypress(xfi);
|
||||
|
||||
if (app != TRUE)
|
||||
if (!app)
|
||||
{
|
||||
if (xfi->suppress_output == FALSE)
|
||||
{
|
||||
xfi->suppress_output = TRUE;
|
||||
update->SuppressOutput((rdpContext*) xfi->context, 0, NULL);
|
||||
}
|
||||
update->SuppressOutput((rdpContext*) xfi->context, 0, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -629,7 +623,7 @@ static BOOL xf_event_UnmapNotify(xfInfo* xfi, XEvent* event, BOOL app)
|
|||
|
||||
if (window != NULL)
|
||||
{
|
||||
xfWindow *xfw = (xfWindow*) window->extra;
|
||||
xfWindow* xfw = (xfWindow*) window->extra;
|
||||
xfw->is_mapped = FALSE;
|
||||
}
|
||||
}
|
||||
|
@ -639,7 +633,7 @@ static BOOL xf_event_UnmapNotify(xfInfo* xfi, XEvent* event, BOOL app)
|
|||
|
||||
static BOOL xf_event_SelectionNotify(xfInfo* xfi, XEvent* event, BOOL app)
|
||||
{
|
||||
if (app != TRUE)
|
||||
if (!app)
|
||||
{
|
||||
if (xf_cliprdr_process_selection_notify(xfi, event))
|
||||
return TRUE;
|
||||
|
@ -650,7 +644,7 @@ static BOOL xf_event_SelectionNotify(xfInfo* xfi, XEvent* event, BOOL app)
|
|||
|
||||
static BOOL xf_event_SelectionRequest(xfInfo* xfi, XEvent* event, BOOL app)
|
||||
{
|
||||
if (app != TRUE)
|
||||
if (!app)
|
||||
{
|
||||
if (xf_cliprdr_process_selection_request(xfi, event))
|
||||
return TRUE;
|
||||
|
@ -661,7 +655,7 @@ static BOOL xf_event_SelectionRequest(xfInfo* xfi, XEvent* event, BOOL app)
|
|||
|
||||
static BOOL xf_event_SelectionClear(xfInfo* xfi, XEvent* event, BOOL app)
|
||||
{
|
||||
if (app != TRUE)
|
||||
if (!app)
|
||||
{
|
||||
if (xf_cliprdr_process_selection_clear(xfi, event))
|
||||
return TRUE;
|
||||
|
@ -678,15 +672,14 @@ static BOOL xf_event_PropertyNotify(xfInfo* xfi, XEvent* event, BOOL app)
|
|||
* ie. not using the buttons on the rail window itself
|
||||
*/
|
||||
|
||||
if (app == TRUE)
|
||||
if (app)
|
||||
{
|
||||
rdpWindow* window;
|
||||
|
||||
window = xf_rdpWindowFromWindow(xfi, event->xproperty.window);
|
||||
|
||||
if (window == NULL)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if ((((Atom)event->xproperty.atom == xfi->_NET_WM_STATE) && (event->xproperty.state != PropertyDelete)) ||
|
||||
(((Atom)event->xproperty.atom == xfi->WM_STATE) && (event->xproperty.state != PropertyDelete)))
|
||||
|
@ -703,7 +696,8 @@ static BOOL xf_event_PropertyNotify(xfInfo* xfi, XEvent* event, BOOL app)
|
|||
status = xf_GetWindowProperty(xfi, event->xproperty.window,
|
||||
xfi->_NET_WM_STATE, 12, &nitems, &bytes, &prop);
|
||||
|
||||
if (status != TRUE) {
|
||||
if (!status)
|
||||
{
|
||||
DEBUG_X11_LMS("No return _NET_WM_STATE, window is not maximized");
|
||||
}
|
||||
|
||||
|
@ -725,7 +719,8 @@ static BOOL xf_event_PropertyNotify(xfInfo* xfi, XEvent* event, BOOL app)
|
|||
status = xf_GetWindowProperty(xfi, event->xproperty.window,
|
||||
xfi->WM_STATE, 1, &nitems, &bytes, &prop);
|
||||
|
||||
if (status != TRUE) {
|
||||
if (!status)
|
||||
{
|
||||
DEBUG_X11_LMS("No return WM_STATE, window is not minimized");
|
||||
}
|
||||
else
|
||||
|
@ -760,9 +755,7 @@ static BOOL xf_event_PropertyNotify(xfInfo* xfi, XEvent* event, BOOL app)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (app != TRUE)
|
||||
else
|
||||
{
|
||||
if (xf_cliprdr_process_property_notify(xfi, event))
|
||||
return TRUE;
|
||||
|
@ -773,7 +766,7 @@ static BOOL xf_event_PropertyNotify(xfInfo* xfi, XEvent* event, BOOL app)
|
|||
|
||||
static BOOL xf_event_suppress_events(xfInfo *xfi, rdpWindow *window, XEvent*event)
|
||||
{
|
||||
if (! xfi->remote_app)
|
||||
if (!xfi->remote_app)
|
||||
return FALSE;
|
||||
|
||||
switch (xfi->window->local_move.state)
|
||||
|
@ -866,7 +859,7 @@ BOOL xf_event_process(freerdp* instance, XEvent* event)
|
|||
if (window)
|
||||
{
|
||||
/* Update "current" window for cursor change orders */
|
||||
xfi->window = (xfWindow *) window->extra;
|
||||
xfi->window = (xfWindow*) window->extra;
|
||||
|
||||
if (xf_event_suppress_events(xfi, window, event))
|
||||
return TRUE;
|
||||
|
@ -968,5 +961,7 @@ BOOL xf_event_process(freerdp* instance, XEvent* event)
|
|||
break;
|
||||
}
|
||||
|
||||
XSync(xfi->display, FALSE);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
|
||||
#include "xf_gdi.h"
|
||||
|
||||
static UINT8 GDI_BS_HACHTED_PATTERNS[] =
|
||||
static UINT8 GDI_BS_HATCHED_PATTERNS[] =
|
||||
{
|
||||
0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, /* HS_HORIZONTAL */
|
||||
0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, /* HS_VERTICAL */
|
||||
|
@ -267,11 +267,11 @@ void xf_gdi_palette_update(rdpContext* context, PALETTE_UPDATE* palette)
|
|||
{
|
||||
xfInfo* xfi = ((xfContext*) context)->xfi;
|
||||
|
||||
WaitForSingleObject(xfi->mutex, INFINITE);
|
||||
xf_lock_x11(xfi, FALSE);
|
||||
|
||||
CopyMemory(xfi->clrconv->palette, palette, sizeof(rdpPalette));
|
||||
|
||||
ReleaseMutex(xfi->mutex);
|
||||
xf_unlock_x11(xfi, FALSE);
|
||||
}
|
||||
|
||||
void xf_gdi_set_bounds(rdpContext* context, rdpBounds* bounds)
|
||||
|
@ -279,7 +279,7 @@ void xf_gdi_set_bounds(rdpContext* context, rdpBounds* bounds)
|
|||
XRectangle clip;
|
||||
xfInfo* xfi = ((xfContext*) context)->xfi;
|
||||
|
||||
WaitForSingleObject(xfi->mutex, INFINITE);
|
||||
xf_lock_x11(xfi, FALSE);
|
||||
|
||||
if (bounds != NULL)
|
||||
{
|
||||
|
@ -294,14 +294,14 @@ void xf_gdi_set_bounds(rdpContext* context, rdpBounds* bounds)
|
|||
XSetClipMask(xfi->display, xfi->gc, None);
|
||||
}
|
||||
|
||||
ReleaseMutex(xfi->mutex);
|
||||
xf_unlock_x11(xfi, FALSE);
|
||||
}
|
||||
|
||||
void xf_gdi_dstblt(rdpContext* context, DSTBLT_ORDER* dstblt)
|
||||
{
|
||||
xfInfo* xfi = ((xfContext*) context)->xfi;
|
||||
|
||||
WaitForSingleObject(xfi->mutex, INFINITE);
|
||||
xf_lock_x11(xfi, FALSE);
|
||||
|
||||
xf_set_rop3(xfi, gdi_rop3_code(dstblt->bRop));
|
||||
|
||||
|
@ -312,18 +312,12 @@ void xf_gdi_dstblt(rdpContext* context, DSTBLT_ORDER* dstblt)
|
|||
|
||||
if (xfi->drawing == xfi->primary)
|
||||
{
|
||||
if (xfi->remote_app != TRUE)
|
||||
{
|
||||
XFillRectangle(xfi->display, xfi->drawable, xfi->gc,
|
||||
dstblt->nLeftRect, dstblt->nTopRect, dstblt->nWidth, dstblt->nHeight);
|
||||
}
|
||||
|
||||
gdi_InvalidateRegion(xfi->hdc, dstblt->nLeftRect, dstblt->nTopRect, dstblt->nWidth, dstblt->nHeight);
|
||||
}
|
||||
|
||||
XSetFunction(xfi->display, xfi->gc, GXcopy);
|
||||
|
||||
ReleaseMutex(xfi->mutex);
|
||||
xf_unlock_x11(xfi, FALSE);
|
||||
}
|
||||
|
||||
void xf_gdi_patblt(rdpContext* context, PATBLT_ORDER* patblt)
|
||||
|
@ -335,7 +329,7 @@ void xf_gdi_patblt(rdpContext* context, PATBLT_ORDER* patblt)
|
|||
xfContext* context_ = (xfContext*) context;
|
||||
xfInfo* xfi = context_->xfi;
|
||||
|
||||
WaitForSingleObject(xfi->mutex, INFINITE);
|
||||
xf_lock_x11(xfi, FALSE);
|
||||
|
||||
brush = &patblt->brush;
|
||||
xf_set_rop3(xfi, gdi_rop3_code(patblt->bRop));
|
||||
|
@ -353,7 +347,7 @@ void xf_gdi_patblt(rdpContext* context, PATBLT_ORDER* patblt)
|
|||
}
|
||||
else if (brush->style == GDI_BS_HATCHED)
|
||||
{
|
||||
pattern = xf_mono_bitmap_new(xfi, 8, 8, GDI_BS_HACHTED_PATTERNS + 8 * brush->hatch);
|
||||
pattern = xf_mono_bitmap_new(xfi, 8, 8, GDI_BS_HATCHED_PATTERNS + 8 * brush->hatch);
|
||||
|
||||
XSetForeground(xfi->display, xfi->gc, backColor);
|
||||
XSetBackground(xfi->display, xfi->gc, foreColor);
|
||||
|
@ -406,27 +400,19 @@ void xf_gdi_patblt(rdpContext* context, PATBLT_ORDER* patblt)
|
|||
|
||||
if (xfi->drawing == xfi->primary)
|
||||
{
|
||||
XSetFunction(xfi->display, xfi->gc, GXcopy);
|
||||
|
||||
if (xfi->remote_app != TRUE)
|
||||
{
|
||||
XCopyArea(xfi->display, xfi->primary, xfi->drawable, xfi->gc, patblt->nLeftRect, patblt->nTopRect,
|
||||
patblt->nWidth, patblt->nHeight, patblt->nLeftRect, patblt->nTopRect);
|
||||
}
|
||||
|
||||
gdi_InvalidateRegion(xfi->hdc, patblt->nLeftRect, patblt->nTopRect, patblt->nWidth, patblt->nHeight);
|
||||
}
|
||||
|
||||
XSetFunction(xfi->display, xfi->gc, GXcopy);
|
||||
|
||||
ReleaseMutex(xfi->mutex);
|
||||
xf_unlock_x11(xfi, FALSE);
|
||||
}
|
||||
|
||||
void xf_gdi_scrblt(rdpContext* context, SCRBLT_ORDER* scrblt)
|
||||
{
|
||||
xfInfo* xfi = ((xfContext*) context)->xfi;
|
||||
|
||||
WaitForSingleObject(xfi->mutex, INFINITE);
|
||||
xf_lock_x11(xfi, FALSE);
|
||||
|
||||
xf_set_rop3(xfi, gdi_rop3_code(scrblt->bRop));
|
||||
|
||||
|
@ -435,29 +421,12 @@ void xf_gdi_scrblt(rdpContext* context, SCRBLT_ORDER* scrblt)
|
|||
|
||||
if (xfi->drawing == xfi->primary)
|
||||
{
|
||||
if (xfi->remote_app != TRUE)
|
||||
{
|
||||
if (xfi->unobscured)
|
||||
{
|
||||
XCopyArea(xfi->display, xfi->drawable, xfi->drawable, xfi->gc,
|
||||
scrblt->nXSrc, scrblt->nYSrc, scrblt->nWidth, scrblt->nHeight,
|
||||
scrblt->nLeftRect, scrblt->nTopRect);
|
||||
}
|
||||
else
|
||||
{
|
||||
XSetFunction(xfi->display, xfi->gc, GXcopy);
|
||||
XCopyArea(xfi->display, xfi->primary, xfi->drawable, xfi->gc,
|
||||
scrblt->nLeftRect, scrblt->nTopRect, scrblt->nWidth, scrblt->nHeight,
|
||||
scrblt->nLeftRect, scrblt->nTopRect);
|
||||
}
|
||||
}
|
||||
|
||||
gdi_InvalidateRegion(xfi->hdc, scrblt->nLeftRect, scrblt->nTopRect, scrblt->nWidth, scrblt->nHeight);
|
||||
}
|
||||
|
||||
XSetFunction(xfi->display, xfi->gc, GXcopy);
|
||||
|
||||
ReleaseMutex(xfi->mutex);
|
||||
xf_unlock_x11(xfi, FALSE);
|
||||
}
|
||||
|
||||
void xf_gdi_opaque_rect(rdpContext* context, OPAQUE_RECT_ORDER* opaque_rect)
|
||||
|
@ -466,7 +435,7 @@ void xf_gdi_opaque_rect(rdpContext* context, OPAQUE_RECT_ORDER* opaque_rect)
|
|||
xfContext* context_ = (xfContext*) context;
|
||||
xfInfo* xfi = context_->xfi;
|
||||
|
||||
WaitForSingleObject(xfi->mutex, INFINITE);
|
||||
xf_lock_x11(xfi, FALSE);
|
||||
|
||||
color = freerdp_color_convert_var(opaque_rect->color, context_->settings->ColorDepth, xfi->bpp, xfi->clrconv);
|
||||
|
||||
|
@ -480,17 +449,11 @@ void xf_gdi_opaque_rect(rdpContext* context, OPAQUE_RECT_ORDER* opaque_rect)
|
|||
|
||||
if (xfi->drawing == xfi->primary)
|
||||
{
|
||||
if (xfi->remote_app != TRUE)
|
||||
{
|
||||
XFillRectangle(xfi->display, xfi->drawable, xfi->gc,
|
||||
opaque_rect->nLeftRect, opaque_rect->nTopRect, opaque_rect->nWidth, opaque_rect->nHeight);
|
||||
}
|
||||
|
||||
gdi_InvalidateRegion(xfi->hdc, opaque_rect->nLeftRect, opaque_rect->nTopRect,
|
||||
opaque_rect->nWidth, opaque_rect->nHeight);
|
||||
}
|
||||
|
||||
ReleaseMutex(xfi->mutex);
|
||||
xf_unlock_x11(xfi, FALSE);
|
||||
}
|
||||
|
||||
void xf_gdi_multi_opaque_rect(rdpContext* context, MULTI_OPAQUE_RECT_ORDER* multi_opaque_rect)
|
||||
|
@ -501,7 +464,7 @@ void xf_gdi_multi_opaque_rect(rdpContext* context, MULTI_OPAQUE_RECT_ORDER* mult
|
|||
xfContext* context_ = (xfContext*) context;
|
||||
xfInfo* xfi = context_->xfi;
|
||||
|
||||
WaitForSingleObject(xfi->mutex, INFINITE);
|
||||
xf_lock_x11(xfi, FALSE);
|
||||
|
||||
color = freerdp_color_convert_var(multi_opaque_rect->color, context_->settings->ColorDepth, xfi->bpp, xfi->clrconv);
|
||||
|
||||
|
@ -519,17 +482,11 @@ void xf_gdi_multi_opaque_rect(rdpContext* context, MULTI_OPAQUE_RECT_ORDER* mult
|
|||
|
||||
if (xfi->drawing == xfi->primary)
|
||||
{
|
||||
if (xfi->remote_app != TRUE)
|
||||
{
|
||||
XFillRectangle(xfi->display, xfi->drawable, xfi->gc,
|
||||
rectangle->left, rectangle->top, rectangle->width, rectangle->height);
|
||||
}
|
||||
|
||||
gdi_InvalidateRegion(xfi->hdc, rectangle->left, rectangle->top, rectangle->width, rectangle->height);
|
||||
}
|
||||
}
|
||||
|
||||
ReleaseMutex(xfi->mutex);
|
||||
xf_unlock_x11(xfi, FALSE);
|
||||
}
|
||||
|
||||
void xf_gdi_draw_nine_grid(rdpContext* context, DRAW_NINE_GRID_ORDER* draw_nine_grid)
|
||||
|
@ -543,7 +500,7 @@ void xf_gdi_line_to(rdpContext* context, LINE_TO_ORDER* line_to)
|
|||
xfContext* context_ = (xfContext*) context;
|
||||
xfInfo* xfi = context_->xfi;
|
||||
|
||||
WaitForSingleObject(xfi->mutex, INFINITE);
|
||||
xf_lock_x11(xfi, FALSE);
|
||||
|
||||
xf_set_rop2(xfi, line_to->bRop2);
|
||||
color = freerdp_color_convert_var(line_to->penColor, context_->settings->ColorDepth, xfi->bpp, xfi->clrconv);
|
||||
|
@ -558,12 +515,6 @@ void xf_gdi_line_to(rdpContext* context, LINE_TO_ORDER* line_to)
|
|||
{
|
||||
int width, height;
|
||||
|
||||
if (xfi->remote_app != TRUE)
|
||||
{
|
||||
XDrawLine(xfi->display, xfi->drawable, xfi->gc,
|
||||
line_to->nXStart, line_to->nYStart, line_to->nXEnd, line_to->nYEnd);
|
||||
}
|
||||
|
||||
width = line_to->nXStart - line_to->nXEnd;
|
||||
height = line_to->nYStart - line_to->nYEnd;
|
||||
|
||||
|
@ -579,7 +530,7 @@ void xf_gdi_line_to(rdpContext* context, LINE_TO_ORDER* line_to)
|
|||
|
||||
XSetFunction(xfi->display, xfi->gc, GXcopy);
|
||||
|
||||
ReleaseMutex(xfi->mutex);
|
||||
xf_unlock_x11(xfi, FALSE);
|
||||
}
|
||||
|
||||
void xf_gdi_polyline(rdpContext* context, POLYLINE_ORDER* polyline)
|
||||
|
@ -595,7 +546,7 @@ void xf_gdi_polyline(rdpContext* context, POLYLINE_ORDER* polyline)
|
|||
xfContext* context_ = (xfContext*) context;
|
||||
xfInfo* xfi = context_->xfi;
|
||||
|
||||
WaitForSingleObject(xfi->mutex, INFINITE);
|
||||
xf_lock_x11(xfi, FALSE);
|
||||
|
||||
xf_set_rop2(xfi, polyline->bRop2);
|
||||
color = freerdp_color_convert_var(polyline->penColor, context_->settings->ColorDepth, xfi->bpp, xfi->clrconv);
|
||||
|
@ -619,9 +570,6 @@ void xf_gdi_polyline(rdpContext* context, POLYLINE_ORDER* polyline)
|
|||
|
||||
if (xfi->drawing == xfi->primary)
|
||||
{
|
||||
if (xfi->remote_app != TRUE)
|
||||
XDrawLines(xfi->display, xfi->drawable, xfi->gc, points, npoints, CoordModePrevious);
|
||||
|
||||
x1 = points[0].x;
|
||||
y1 = points[0].y;
|
||||
|
||||
|
@ -646,7 +594,7 @@ void xf_gdi_polyline(rdpContext* context, POLYLINE_ORDER* polyline)
|
|||
XSetFunction(xfi->display, xfi->gc, GXcopy);
|
||||
free(points);
|
||||
|
||||
ReleaseMutex(xfi->mutex);
|
||||
xf_unlock_x11(xfi, FALSE);
|
||||
}
|
||||
|
||||
void xf_gdi_memblt(rdpContext* context, MEMBLT_ORDER* memblt)
|
||||
|
@ -654,7 +602,7 @@ void xf_gdi_memblt(rdpContext* context, MEMBLT_ORDER* memblt)
|
|||
xfBitmap* bitmap;
|
||||
xfInfo* xfi = ((xfContext*) context)->xfi;
|
||||
|
||||
WaitForSingleObject(xfi->mutex, INFINITE);
|
||||
xf_lock_x11(xfi, FALSE);
|
||||
|
||||
bitmap = (xfBitmap*) memblt->bitmap;
|
||||
xf_set_rop3(xfi, gdi_rop3_code(memblt->bRop));
|
||||
|
@ -665,19 +613,12 @@ void xf_gdi_memblt(rdpContext* context, MEMBLT_ORDER* memblt)
|
|||
|
||||
if (xfi->drawing == xfi->primary)
|
||||
{
|
||||
if (xfi->remote_app != TRUE)
|
||||
{
|
||||
XCopyArea(xfi->display, bitmap->pixmap, xfi->drawable, xfi->gc,
|
||||
memblt->nXSrc, memblt->nYSrc, memblt->nWidth, memblt->nHeight,
|
||||
memblt->nLeftRect, memblt->nTopRect);
|
||||
}
|
||||
|
||||
gdi_InvalidateRegion(xfi->hdc, memblt->nLeftRect, memblt->nTopRect, memblt->nWidth, memblt->nHeight);
|
||||
}
|
||||
|
||||
XSetFunction(xfi->display, xfi->gc, GXcopy);
|
||||
|
||||
ReleaseMutex(xfi->mutex);
|
||||
xf_unlock_x11(xfi, FALSE);
|
||||
}
|
||||
|
||||
void xf_gdi_mem3blt(rdpContext* context, MEM3BLT_ORDER* mem3blt)
|
||||
|
@ -690,7 +631,7 @@ void xf_gdi_mem3blt(rdpContext* context, MEM3BLT_ORDER* mem3blt)
|
|||
xfContext* context_ = (xfContext*) context;
|
||||
xfInfo* xfi = context_->xfi;
|
||||
|
||||
WaitForSingleObject(xfi->mutex, INFINITE);
|
||||
xf_lock_x11(xfi, FALSE);
|
||||
|
||||
brush = &mem3blt->brush;
|
||||
bitmap = (xfBitmap*) mem3blt->bitmap;
|
||||
|
@ -738,13 +679,6 @@ void xf_gdi_mem3blt(rdpContext* context, MEM3BLT_ORDER* mem3blt)
|
|||
|
||||
if (xfi->drawing == xfi->primary)
|
||||
{
|
||||
if (xfi->remote_app != TRUE)
|
||||
{
|
||||
XCopyArea(xfi->display, bitmap->pixmap, xfi->drawable, xfi->gc,
|
||||
mem3blt->nXSrc, mem3blt->nYSrc, mem3blt->nWidth, mem3blt->nHeight,
|
||||
mem3blt->nLeftRect, mem3blt->nTopRect);
|
||||
}
|
||||
|
||||
gdi_InvalidateRegion(xfi->hdc, mem3blt->nLeftRect, mem3blt->nTopRect, mem3blt->nWidth, mem3blt->nHeight);
|
||||
}
|
||||
|
||||
|
@ -756,7 +690,7 @@ void xf_gdi_mem3blt(rdpContext* context, MEM3BLT_ORDER* mem3blt)
|
|||
|
||||
XSetFunction(xfi->display, xfi->gc, GXcopy);
|
||||
|
||||
ReleaseMutex(xfi->mutex);
|
||||
xf_unlock_x11(xfi, FALSE);
|
||||
}
|
||||
|
||||
void xf_gdi_polygon_sc(rdpContext* context, POLYGON_SC_ORDER* polygon_sc)
|
||||
|
@ -766,7 +700,7 @@ void xf_gdi_polygon_sc(rdpContext* context, POLYGON_SC_ORDER* polygon_sc)
|
|||
UINT32 brush_color;
|
||||
xfInfo* xfi = ((xfContext*) context)->xfi;
|
||||
|
||||
WaitForSingleObject(xfi->mutex, INFINITE);
|
||||
xf_lock_x11(xfi, FALSE);
|
||||
|
||||
xf_set_rop2(xfi, polygon_sc->bRop2);
|
||||
brush_color = freerdp_color_convert_var(polygon_sc->brushColor, ((xfContext*)context)->settings->ColorDepth, xfi->bpp, xfi->clrconv);
|
||||
|
@ -813,7 +747,7 @@ void xf_gdi_polygon_sc(rdpContext* context, POLYGON_SC_ORDER* polygon_sc)
|
|||
XSetFunction(xfi->display, xfi->gc, GXcopy);
|
||||
free(points);
|
||||
|
||||
ReleaseMutex(xfi->mutex);
|
||||
xf_unlock_x11(xfi, FALSE);
|
||||
}
|
||||
|
||||
void xf_gdi_polygon_cb(rdpContext* context, POLYGON_CB_ORDER* polygon_cb)
|
||||
|
@ -826,7 +760,7 @@ void xf_gdi_polygon_cb(rdpContext* context, POLYGON_CB_ORDER* polygon_cb)
|
|||
UINT32 backColor;
|
||||
xfInfo* xfi = ((xfContext*) context)->xfi;
|
||||
|
||||
WaitForSingleObject(xfi->mutex, INFINITE);
|
||||
xf_lock_x11(xfi, FALSE);
|
||||
|
||||
brush = &(polygon_cb->brush);
|
||||
xf_set_rop2(xfi, polygon_cb->bRop2);
|
||||
|
@ -920,7 +854,7 @@ void xf_gdi_polygon_cb(rdpContext* context, POLYGON_CB_ORDER* polygon_cb)
|
|||
XSetFunction(xfi->display, xfi->gc, GXcopy);
|
||||
free(points);
|
||||
|
||||
ReleaseMutex(xfi->mutex);
|
||||
xf_unlock_x11(xfi, FALSE);
|
||||
}
|
||||
|
||||
void xf_gdi_ellipse_sc(rdpContext* context, ELLIPSE_SC_ORDER* ellipse_sc)
|
||||
|
@ -941,7 +875,7 @@ void xf_gdi_surface_frame_marker(rdpContext* context, SURFACE_FRAME_MARKER* surf
|
|||
xfi = ((xfContext*) context)->xfi;
|
||||
settings = xfi->instance->settings;
|
||||
|
||||
WaitForSingleObject(xfi->mutex, INFINITE);
|
||||
xf_lock_x11(xfi, FALSE);
|
||||
|
||||
switch (surface_frame_marker->frameAction)
|
||||
{
|
||||
|
@ -955,15 +889,8 @@ void xf_gdi_surface_frame_marker(rdpContext* context, SURFACE_FRAME_MARKER* surf
|
|||
|
||||
case SURFACECMD_FRAMEACTION_END:
|
||||
xfi->frame_begin = FALSE;
|
||||
if (xfi->frame_x2 > xfi->frame_x1 && xfi->frame_y2 > xfi->frame_y1)
|
||||
if ((xfi->frame_x2 > xfi->frame_x1) && (xfi->frame_y2 > xfi->frame_y1))
|
||||
{
|
||||
XSetFunction(xfi->display, xfi->gc, GXcopy);
|
||||
XSetFillStyle(xfi->display, xfi->gc, FillSolid);
|
||||
|
||||
XCopyArea(xfi->display, xfi->primary, xfi->drawable, xfi->gc,
|
||||
xfi->frame_x1, xfi->frame_y1,
|
||||
xfi->frame_x2 - xfi->frame_x1, xfi->frame_y2 - xfi->frame_y1,
|
||||
xfi->frame_x1, xfi->frame_y1);
|
||||
gdi_InvalidateRegion(xfi->hdc, xfi->frame_x1, xfi->frame_y1,
|
||||
xfi->frame_x2 - xfi->frame_x1, xfi->frame_y2 - xfi->frame_y1);
|
||||
}
|
||||
|
@ -974,12 +901,12 @@ void xf_gdi_surface_frame_marker(rdpContext* context, SURFACE_FRAME_MARKER* surf
|
|||
break;
|
||||
}
|
||||
|
||||
ReleaseMutex(xfi->mutex);
|
||||
xf_unlock_x11(xfi, FALSE);
|
||||
}
|
||||
|
||||
static void xf_gdi_surface_update_frame(xfInfo* xfi, UINT16 tx, UINT16 ty, UINT16 width, UINT16 height)
|
||||
{
|
||||
if (xfi->remote_app != TRUE)
|
||||
if (!xfi->remote_app)
|
||||
{
|
||||
if (xfi->frame_begin)
|
||||
{
|
||||
|
@ -1000,8 +927,6 @@ static void xf_gdi_surface_update_frame(xfInfo* xfi, UINT16 tx, UINT16 ty, UINT1
|
|||
}
|
||||
else
|
||||
{
|
||||
XCopyArea(xfi->display, xfi->primary, xfi->drawable, xfi->gc,
|
||||
tx, ty, width, height, tx, ty);
|
||||
gdi_InvalidateRegion(xfi->hdc, tx, ty, width, height);
|
||||
}
|
||||
}
|
||||
|
@ -1020,7 +945,7 @@ void xf_gdi_surface_bits(rdpContext* context, SURFACE_BITS_COMMAND* surface_bits
|
|||
RFX_CONTEXT* rfx_context = (RFX_CONTEXT*) xfi->rfx_context;
|
||||
NSC_CONTEXT* nsc_context = (NSC_CONTEXT*) xfi->nsc_context;
|
||||
|
||||
WaitForSingleObject(xfi->mutex, INFINITE);
|
||||
xf_lock_x11(xfi, FALSE);
|
||||
|
||||
if (surface_bits_command->codecID == RDP_CODEC_ID_REMOTEFX)
|
||||
{
|
||||
|
@ -1125,7 +1050,7 @@ void xf_gdi_surface_bits(rdpContext* context, SURFACE_BITS_COMMAND* surface_bits
|
|||
printf("Unsupported codecID %d\n", surface_bits_command->codecID);
|
||||
}
|
||||
|
||||
ReleaseMutex(xfi->mutex);
|
||||
xf_unlock_x11(xfi, FALSE);
|
||||
}
|
||||
|
||||
void xf_gdi_register_update_callbacks(rdpUpdate* update)
|
||||
|
|
|
@ -46,7 +46,7 @@ void xf_Bitmap_New(rdpContext* context, rdpBitmap* bitmap)
|
|||
xfContext* context_ = (xfContext*) context;
|
||||
xfInfo* xfi = context_->xfi;
|
||||
|
||||
WaitForSingleObject(xfi->mutex, INFINITE);
|
||||
xf_lock_x11(xfi, FALSE);
|
||||
|
||||
XSetFunction(xfi->display, xfi->gc, GXcopy);
|
||||
pixmap = XCreatePixmap(xfi->display, xfi->drawable, bitmap->width, bitmap->height, xfi->depth);
|
||||
|
@ -78,19 +78,19 @@ void xf_Bitmap_New(rdpContext* context, rdpBitmap* bitmap)
|
|||
|
||||
((xfBitmap*) bitmap)->pixmap = pixmap;
|
||||
|
||||
ReleaseMutex(xfi->mutex);
|
||||
xf_unlock_x11(xfi, FALSE);
|
||||
}
|
||||
|
||||
void xf_Bitmap_Free(rdpContext* context, rdpBitmap* bitmap)
|
||||
{
|
||||
xfInfo* xfi = ((xfContext*) context)->xfi;
|
||||
|
||||
WaitForSingleObject(xfi->mutex, INFINITE);
|
||||
xf_lock_x11(xfi, FALSE);
|
||||
|
||||
if (((xfBitmap*) bitmap)->pixmap != 0)
|
||||
XFreePixmap(xfi->display, ((xfBitmap*) bitmap)->pixmap);
|
||||
|
||||
ReleaseMutex(xfi->mutex);
|
||||
xf_unlock_x11(xfi, FALSE);
|
||||
}
|
||||
|
||||
void xf_Bitmap_Paint(rdpContext* context, rdpBitmap* bitmap)
|
||||
|
@ -102,7 +102,7 @@ void xf_Bitmap_Paint(rdpContext* context, rdpBitmap* bitmap)
|
|||
width = bitmap->right - bitmap->left + 1;
|
||||
height = bitmap->bottom - bitmap->top + 1;
|
||||
|
||||
WaitForSingleObject(xfi->mutex, INFINITE);
|
||||
xf_lock_x11(xfi, FALSE);
|
||||
|
||||
XSetFunction(xfi->display, xfi->gc, GXcopy);
|
||||
|
||||
|
@ -114,15 +114,9 @@ void xf_Bitmap_Paint(rdpContext* context, rdpBitmap* bitmap)
|
|||
|
||||
XFree(image);
|
||||
|
||||
if (xfi->remote_app != TRUE)
|
||||
{
|
||||
XCopyArea(xfi->display, xfi->primary, xfi->drawable, xfi->gc,
|
||||
bitmap->left, bitmap->top, width, height, bitmap->left, bitmap->top);
|
||||
}
|
||||
|
||||
gdi_InvalidateRegion(xfi->hdc, bitmap->left, bitmap->top, width, height);
|
||||
|
||||
ReleaseMutex(xfi->mutex);
|
||||
xf_unlock_x11(xfi, FALSE);
|
||||
}
|
||||
|
||||
void xf_Bitmap_Decompress(rdpContext* context, rdpBitmap* bitmap,
|
||||
|
@ -212,14 +206,14 @@ void xf_Bitmap_SetSurface(rdpContext* context, rdpBitmap* bitmap, BOOL primary)
|
|||
{
|
||||
xfInfo* xfi = ((xfContext*) context)->xfi;
|
||||
|
||||
WaitForSingleObject(xfi->mutex, INFINITE);
|
||||
xf_lock_x11(xfi, FALSE);
|
||||
|
||||
if (primary)
|
||||
xfi->drawing = xfi->primary;
|
||||
else
|
||||
xfi->drawing = ((xfBitmap*) bitmap)->pixmap;
|
||||
|
||||
ReleaseMutex(xfi->mutex);
|
||||
xf_unlock_x11(xfi, FALSE);
|
||||
}
|
||||
|
||||
/* Pointer Class */
|
||||
|
@ -230,7 +224,7 @@ void xf_Pointer_New(rdpContext* context, rdpPointer* pointer)
|
|||
XcursorImage ci;
|
||||
xfInfo* xfi = ((xfContext*) context)->xfi;
|
||||
|
||||
WaitForSingleObject(xfi->mutex, INFINITE);
|
||||
xf_lock_x11(xfi, FALSE);
|
||||
|
||||
ZeroMemory(&ci, sizeof(ci));
|
||||
ci.version = XCURSOR_IMAGE_VERSION;
|
||||
|
@ -253,7 +247,7 @@ void xf_Pointer_New(rdpContext* context, rdpPointer* pointer)
|
|||
|
||||
free(ci.pixels);
|
||||
|
||||
ReleaseMutex(xfi->mutex);
|
||||
xf_unlock_x11(xfi, FALSE);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -262,12 +256,12 @@ void xf_Pointer_Free(rdpContext* context, rdpPointer* pointer)
|
|||
#ifdef WITH_XCURSOR
|
||||
xfInfo* xfi = ((xfContext*) context)->xfi;
|
||||
|
||||
WaitForSingleObject(xfi->mutex, INFINITE);
|
||||
xf_lock_x11(xfi, FALSE);
|
||||
|
||||
if (((xfPointer*) pointer)->cursor != 0)
|
||||
XFreeCursor(xfi->display, ((xfPointer*) pointer)->cursor);
|
||||
|
||||
ReleaseMutex(xfi->mutex);
|
||||
xf_unlock_x11(xfi, FALSE);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -276,14 +270,14 @@ void xf_Pointer_Set(rdpContext* context, rdpPointer* pointer)
|
|||
#ifdef WITH_XCURSOR
|
||||
xfInfo* xfi = ((xfContext*) context)->xfi;
|
||||
|
||||
WaitForSingleObject(xfi->mutex, INFINITE);
|
||||
xf_lock_x11(xfi, FALSE);
|
||||
|
||||
/* in RemoteApp mode, window can be null if none has had focus */
|
||||
|
||||
if (xfi->window != NULL)
|
||||
XDefineCursor(xfi->display, xfi->window->handle, ((xfPointer*) pointer)->cursor);
|
||||
|
||||
ReleaseMutex(xfi->mutex);
|
||||
xf_unlock_x11(xfi, FALSE);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -293,7 +287,7 @@ void xf_Pointer_SetNull(rdpContext* context)
|
|||
xfInfo* xfi = ((xfContext*) context)->xfi;
|
||||
static Cursor nullcursor = None;
|
||||
|
||||
WaitForSingleObject(xfi->mutex, INFINITE);
|
||||
xf_lock_x11(xfi, FALSE);
|
||||
|
||||
if (nullcursor == None)
|
||||
{
|
||||
|
@ -311,7 +305,7 @@ void xf_Pointer_SetNull(rdpContext* context)
|
|||
if (xfi->window != NULL && nullcursor != None)
|
||||
XDefineCursor(xfi->display, xfi->window->handle, nullcursor);
|
||||
|
||||
ReleaseMutex(xfi->mutex);
|
||||
xf_unlock_x11(xfi, FALSE);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -320,12 +314,12 @@ void xf_Pointer_SetDefault(rdpContext* context)
|
|||
#ifdef WITH_XCURSOR
|
||||
xfInfo* xfi = ((xfContext*) context)->xfi;
|
||||
|
||||
WaitForSingleObject(xfi->mutex, INFINITE);
|
||||
xf_lock_x11(xfi, FALSE);
|
||||
|
||||
if (xfi->window != NULL)
|
||||
XUndefineCursor(xfi->display, xfi->window->handle);
|
||||
|
||||
ReleaseMutex(xfi->mutex);
|
||||
xf_unlock_x11(xfi, FALSE);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -341,7 +335,7 @@ void xf_Glyph_New(rdpContext* context, rdpGlyph* glyph)
|
|||
xf_glyph = (xfGlyph*) glyph;
|
||||
xfi = ((xfContext*) context)->xfi;
|
||||
|
||||
WaitForSingleObject(xfi->mutex, INFINITE);
|
||||
xf_lock_x11(xfi, FALSE);
|
||||
|
||||
scanline = (glyph->cx + 7) / 8;
|
||||
|
||||
|
@ -357,19 +351,19 @@ void xf_Glyph_New(rdpContext* context, rdpGlyph* glyph)
|
|||
XPutImage(xfi->display, xf_glyph->pixmap, xfi->gc_mono, image, 0, 0, 0, 0, glyph->cx, glyph->cy);
|
||||
XFree(image);
|
||||
|
||||
ReleaseMutex(xfi->mutex);
|
||||
xf_unlock_x11(xfi, FALSE);
|
||||
}
|
||||
|
||||
void xf_Glyph_Free(rdpContext* context, rdpGlyph* glyph)
|
||||
{
|
||||
xfInfo* xfi = ((xfContext*) context)->xfi;
|
||||
|
||||
WaitForSingleObject(xfi->mutex, INFINITE);
|
||||
xf_lock_x11(xfi, FALSE);
|
||||
|
||||
if (((xfGlyph*) glyph)->pixmap != 0)
|
||||
XFreePixmap(xfi->display, ((xfGlyph*) glyph)->pixmap);
|
||||
|
||||
ReleaseMutex(xfi->mutex);
|
||||
xf_unlock_x11(xfi, FALSE);
|
||||
}
|
||||
|
||||
void xf_Glyph_Draw(rdpContext* context, rdpGlyph* glyph, int x, int y)
|
||||
|
@ -379,14 +373,14 @@ void xf_Glyph_Draw(rdpContext* context, rdpGlyph* glyph, int x, int y)
|
|||
|
||||
xf_glyph = (xfGlyph*) glyph;
|
||||
|
||||
WaitForSingleObject(xfi->mutex, INFINITE);
|
||||
xf_lock_x11(xfi, FALSE);
|
||||
|
||||
XSetStipple(xfi->display, xfi->gc, xf_glyph->pixmap);
|
||||
XSetTSOrigin(xfi->display, xfi->gc, x, y);
|
||||
XFillRectangle(xfi->display, xfi->drawing, xfi->gc, x, y, glyph->cx, glyph->cy);
|
||||
XSetStipple(xfi->display, xfi->gc, xfi->bitmap_mono);
|
||||
|
||||
ReleaseMutex(xfi->mutex);
|
||||
xf_unlock_x11(xfi, FALSE);
|
||||
}
|
||||
|
||||
void xf_Glyph_BeginDraw(rdpContext* context, int x, int y, int width, int height, UINT32 bgcolor, UINT32 fgcolor)
|
||||
|
@ -402,7 +396,7 @@ void xf_Glyph_BeginDraw(rdpContext* context, int x, int y, int width, int height
|
|||
freerdp_color_convert_var_bgr(fgcolor, context_->settings->ColorDepth, xfi->bpp, xfi->clrconv):
|
||||
freerdp_color_convert_var_rgb(fgcolor, context_->settings->ColorDepth, xfi->bpp, xfi->clrconv);
|
||||
|
||||
WaitForSingleObject(xfi->mutex, INFINITE);
|
||||
xf_lock_x11(xfi, FALSE);
|
||||
|
||||
XSetFunction(xfi->display, xfi->gc, GXcopy);
|
||||
XSetFillStyle(xfi->display, xfi->gc, FillSolid);
|
||||
|
@ -413,26 +407,21 @@ void xf_Glyph_BeginDraw(rdpContext* context, int x, int y, int width, int height
|
|||
XSetBackground(xfi->display, xfi->gc, fgcolor);
|
||||
XSetFillStyle(xfi->display, xfi->gc, FillStippled);
|
||||
|
||||
ReleaseMutex(xfi->mutex);
|
||||
xf_unlock_x11(xfi, FALSE);
|
||||
}
|
||||
|
||||
void xf_Glyph_EndDraw(rdpContext* context, int x, int y, int width, int height, UINT32 bgcolor, UINT32 fgcolor)
|
||||
{
|
||||
xfInfo* xfi = ((xfContext*) context)->xfi;
|
||||
|
||||
WaitForSingleObject(xfi->mutex, INFINITE);
|
||||
xf_lock_x11(xfi, FALSE);
|
||||
|
||||
if (xfi->drawing == xfi->primary)
|
||||
{
|
||||
if (xfi->remote_app != TRUE)
|
||||
{
|
||||
XCopyArea(xfi->display, xfi->primary, xfi->drawable, xfi->gc, x, y, width, height, x, y);
|
||||
}
|
||||
|
||||
gdi_InvalidateRegion(xfi->hdc, x, y, width, height);
|
||||
}
|
||||
|
||||
ReleaseMutex(xfi->mutex);
|
||||
xf_unlock_x11(xfi, FALSE);
|
||||
}
|
||||
|
||||
/* Graphics Module */
|
||||
|
|
|
@ -41,11 +41,12 @@ void xf_kbd_init(xfInfo* xfi)
|
|||
xfi->keyboard_layout_id = xfi->instance->settings->KeyboardLayout;
|
||||
xfi->keyboard_layout_id = freerdp_keyboard_init(xfi->keyboard_layout_id);
|
||||
xfi->instance->settings->KeyboardLayout = xfi->keyboard_layout_id;
|
||||
xfi->modifier_map = XGetModifierMapping(xfi->display);
|
||||
}
|
||||
|
||||
void xf_kbd_clear(xfInfo* xfi)
|
||||
{
|
||||
memset(xfi->pressed_keys, 0, 256 * sizeof(BOOL));
|
||||
ZeroMemory(xfi->pressed_keys, 256 * sizeof(BOOL));
|
||||
}
|
||||
|
||||
void xf_kbd_set_keypress(xfInfo* xfi, BYTE keycode, KeySym keysym)
|
||||
|
@ -129,7 +130,7 @@ int xf_kbd_read_keyboard_state(xfInfo* xfi)
|
|||
Window wdummy;
|
||||
UINT32 state = 0;
|
||||
|
||||
if (xfi->remote_app != TRUE)
|
||||
if (!xfi->remote_app)
|
||||
{
|
||||
XQueryPointer(xfi->display, xfi->window->handle,
|
||||
&wdummy, &wdummy, &dummy, &dummy, &dummy, &dummy, &state);
|
||||
|
@ -154,6 +155,7 @@ BOOL xf_kbd_get_key_state(xfInfo* xfi, int state, int keysym)
|
|||
for (modifierpos = 0; modifierpos < 8; modifierpos++)
|
||||
{
|
||||
offset = xfi->modifier_map->max_keypermod * modifierpos;
|
||||
|
||||
for (key = 0; key < xfi->modifier_map->max_keypermod; key++)
|
||||
{
|
||||
if (xfi->modifier_map->modifiermap[offset + key] == keycode)
|
||||
|
@ -172,6 +174,7 @@ int xf_kbd_get_toggle_keys_state(xfInfo* xfi)
|
|||
int toggle_keys_state = 0;
|
||||
|
||||
state = xf_kbd_read_keyboard_state(xfi);
|
||||
|
||||
if (xf_kbd_get_key_state(xfi, state, XK_Scroll_Lock))
|
||||
toggle_keys_state |= KBD_SYNC_SCROLL_LOCK;
|
||||
if (xf_kbd_get_key_state(xfi, state, XK_Num_Lock))
|
||||
|
|
|
@ -112,6 +112,7 @@ void xf_SendClientEvent(xfInfo* xfi, xfWindow* window, Atom atom, unsigned int n
|
|||
}
|
||||
|
||||
DEBUG_X11("Send ClientMessage Event: wnd=0x%04X", (unsigned int) xevent.xclient.window);
|
||||
|
||||
XSendEvent(xfi->display, RootWindowOfScreen(xfi->screen), False,
|
||||
SubstructureRedirectMask | SubstructureNotifyMask, &xevent);
|
||||
XSync(xfi->display, False);
|
||||
|
@ -170,9 +171,8 @@ BOOL xf_GetCurrentDesktop(xfInfo* xfi)
|
|||
status = xf_GetWindowProperty(xfi, DefaultRootWindow(xfi->display),
|
||||
xfi->_NET_CURRENT_DESKTOP, 1, &nitems, &bytes, &prop);
|
||||
|
||||
if (status != TRUE) {
|
||||
if (status != TRUE)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
xfi->current_desktop = (int) *prop;
|
||||
free(prop);
|
||||
|
@ -199,7 +199,8 @@ BOOL xf_GetWorkArea(xfInfo* xfi)
|
|||
if (status != TRUE)
|
||||
return FALSE;
|
||||
|
||||
if ((xfi->current_desktop * 4 + 3) >= nitems) {
|
||||
if ((xfi->current_desktop * 4 + 3) >= nitems)
|
||||
{
|
||||
free(prop);
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -507,7 +508,7 @@ xfWindow* xf_CreateWindow(xfInfo* xfi, rdpWindow* wnd, int x, int y, int width,
|
|||
(UINT32) window->handle, window->left, window->top, window->right, window->bottom,
|
||||
window->width, window->height, wnd->windowId);
|
||||
|
||||
memset(&gcv, 0, sizeof(gcv));
|
||||
ZeroMemory(&gcv, sizeof(gcv));
|
||||
window->gc = XCreateGC(xfi->display, window->handle, GCGraphicsExposures, &gcv);
|
||||
|
||||
class_hints = XAllocClassHint();
|
||||
|
@ -939,12 +940,12 @@ rdpWindow* xf_rdpWindowFromWindow(xfInfo* xfi, Window wnd)
|
|||
if (xfi->_context != NULL)
|
||||
{
|
||||
rail = xfi->_context->rail;
|
||||
|
||||
if (rail != NULL)
|
||||
{
|
||||
return window_list_get_by_extra_id(rail->list, (void*)(long)wnd);
|
||||
}
|
||||
return window_list_get_by_extra_id(rail->list, (void*) (long) wnd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -127,12 +127,12 @@ void xf_sw_end_paint(rdpContext* context)
|
|||
w = gdi->primary->hdc->hwnd->invalid->w;
|
||||
h = gdi->primary->hdc->hwnd->invalid->h;
|
||||
|
||||
WaitForSingleObject(xfi->mutex, INFINITE);
|
||||
xf_lock_x11(xfi, FALSE);
|
||||
|
||||
XPutImage(xfi->display, xfi->primary, xfi->gc, xfi->image, x, y, x, y, w, h);
|
||||
XCopyArea(xfi->display, xfi->primary, xfi->window->handle, xfi->gc, x, y, w, h, x, y);
|
||||
|
||||
ReleaseMutex(xfi->mutex);
|
||||
xf_unlock_x11(xfi, FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -146,7 +146,7 @@ void xf_sw_end_paint(rdpContext* context)
|
|||
ninvalid = gdi->primary->hdc->hwnd->ninvalid;
|
||||
cinvalid = gdi->primary->hdc->hwnd->cinvalid;
|
||||
|
||||
WaitForSingleObject(xfi->mutex, INFINITE);
|
||||
xf_lock_x11(xfi, FALSE);
|
||||
|
||||
for (i = 0; i < ninvalid; i++)
|
||||
{
|
||||
|
@ -161,7 +161,7 @@ void xf_sw_end_paint(rdpContext* context)
|
|||
|
||||
XFlush(xfi->display);
|
||||
|
||||
ReleaseMutex(xfi->mutex);
|
||||
xf_unlock_x11(xfi, FALSE);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -174,11 +174,11 @@ void xf_sw_end_paint(rdpContext* context)
|
|||
w = gdi->primary->hdc->hwnd->invalid->w;
|
||||
h = gdi->primary->hdc->hwnd->invalid->h;
|
||||
|
||||
WaitForSingleObject(xfi->mutex, INFINITE);
|
||||
xf_lock_x11(xfi, FALSE);
|
||||
|
||||
xf_rail_paint(xfi, context->rail, x, y, x + w - 1, y + h - 1);
|
||||
|
||||
ReleaseMutex(xfi->mutex);
|
||||
xf_unlock_x11(xfi, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -190,7 +190,7 @@ void xf_sw_desktop_resize(rdpContext* context)
|
|||
xfi = ((xfContext*) context)->xfi;
|
||||
settings = xfi->instance->settings;
|
||||
|
||||
WaitForSingleObject(xfi->mutex, INFINITE);
|
||||
xf_lock_x11(xfi, TRUE);
|
||||
|
||||
if (xfi->fullscreen != TRUE)
|
||||
{
|
||||
|
@ -206,7 +206,7 @@ void xf_sw_desktop_resize(rdpContext* context)
|
|||
}
|
||||
}
|
||||
|
||||
ReleaseMutex(xfi->mutex);
|
||||
xf_unlock_x11(xfi, TRUE);
|
||||
}
|
||||
|
||||
void xf_hw_begin_paint(rdpContext* context)
|
||||
|
@ -226,7 +226,54 @@ void xf_hw_end_paint(rdpContext* context)
|
|||
|
||||
xfi = ((xfContext*) context)->xfi;
|
||||
|
||||
if (xfi->remote_app)
|
||||
if (!xfi->remote_app)
|
||||
{
|
||||
if (!xfi->complex_regions)
|
||||
{
|
||||
if (xfi->hdc->hwnd->invalid->null)
|
||||
return;
|
||||
|
||||
x = xfi->hdc->hwnd->invalid->x;
|
||||
y = xfi->hdc->hwnd->invalid->y;
|
||||
w = xfi->hdc->hwnd->invalid->w;
|
||||
h = xfi->hdc->hwnd->invalid->h;
|
||||
|
||||
xf_lock_x11(xfi, FALSE);
|
||||
|
||||
XCopyArea(xfi->display, xfi->primary, xfi->drawable, xfi->gc, x, y, w, h, x, y);
|
||||
|
||||
xf_unlock_x11(xfi, FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
int i;
|
||||
int ninvalid;
|
||||
HGDI_RGN cinvalid;
|
||||
|
||||
if (xfi->hdc->hwnd->ninvalid < 1)
|
||||
return;
|
||||
|
||||
ninvalid = xfi->hdc->hwnd->ninvalid;
|
||||
cinvalid = xfi->hdc->hwnd->cinvalid;
|
||||
|
||||
xf_lock_x11(xfi, FALSE);
|
||||
|
||||
for (i = 0; i < ninvalid; i++)
|
||||
{
|
||||
x = cinvalid[i].x;
|
||||
y = cinvalid[i].y;
|
||||
w = cinvalid[i].w;
|
||||
h = cinvalid[i].h;
|
||||
|
||||
XCopyArea(xfi->display, xfi->primary, xfi->drawable, xfi->gc, x, y, w, h, x, y);
|
||||
}
|
||||
|
||||
XFlush(xfi->display);
|
||||
|
||||
xf_unlock_x11(xfi, FALSE);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (xfi->hdc->hwnd->invalid->null)
|
||||
return;
|
||||
|
@ -236,11 +283,11 @@ void xf_hw_end_paint(rdpContext* context)
|
|||
w = xfi->hdc->hwnd->invalid->w;
|
||||
h = xfi->hdc->hwnd->invalid->h;
|
||||
|
||||
WaitForSingleObject(xfi->mutex, INFINITE);
|
||||
xf_lock_x11(xfi, FALSE);
|
||||
|
||||
xf_rail_paint(xfi, context->rail, x, y, x + w - 1, y + h - 1);
|
||||
|
||||
ReleaseMutex(xfi->mutex);
|
||||
xf_unlock_x11(xfi, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -253,7 +300,7 @@ void xf_hw_desktop_resize(rdpContext* context)
|
|||
xfi = ((xfContext*) context)->xfi;
|
||||
settings = xfi->instance->settings;
|
||||
|
||||
WaitForSingleObject(xfi->mutex, INFINITE);
|
||||
xf_lock_x11(xfi, TRUE);
|
||||
|
||||
if (xfi->fullscreen != TRUE)
|
||||
{
|
||||
|
@ -284,7 +331,7 @@ void xf_hw_desktop_resize(rdpContext* context)
|
|||
XFillRectangle(xfi->display, xfi->drawable, xfi->gc, 0, 0, xfi->width, xfi->height);
|
||||
}
|
||||
|
||||
ReleaseMutex(xfi->mutex);
|
||||
xf_unlock_x11(xfi, TRUE);
|
||||
}
|
||||
|
||||
BOOL xf_get_fds(freerdp* instance, void** rfds, int* rcount, void** wfds, int* wcount)
|
||||
|
@ -309,11 +356,11 @@ BOOL xf_process_x_events(freerdp* instance)
|
|||
|
||||
while (pending_status)
|
||||
{
|
||||
WaitForSingleObject(xfi->mutex, INFINITE);
|
||||
xf_lock_x11(xfi, FALSE);
|
||||
|
||||
pending_status = XPending(xfi->display);
|
||||
|
||||
ReleaseMutex(xfi->mutex);
|
||||
xf_unlock_x11(xfi, FALSE);
|
||||
|
||||
if (pending_status)
|
||||
{
|
||||
|
@ -380,6 +427,8 @@ void xf_toggle_fullscreen(xfInfo* xfi)
|
|||
{
|
||||
Pixmap contents = 0;
|
||||
|
||||
xf_lock_x11(xfi, TRUE);
|
||||
|
||||
contents = XCreatePixmap(xfi->display, xfi->window->handle, xfi->width, xfi->height, xfi->depth);
|
||||
XCopyArea(xfi->display, xfi->primary, contents, xfi->gc, 0, 0, xfi->width, xfi->height, 0, 0);
|
||||
|
||||
|
@ -389,6 +438,34 @@ void xf_toggle_fullscreen(xfInfo* xfi)
|
|||
|
||||
XCopyArea(xfi->display, contents, xfi->primary, xfi->gc, 0, 0, xfi->width, xfi->height, 0, 0);
|
||||
XFreePixmap(xfi->display, contents);
|
||||
|
||||
xf_unlock_x11(xfi, TRUE);
|
||||
}
|
||||
|
||||
void xf_lock_x11(xfInfo* xfi, BOOL display)
|
||||
{
|
||||
if (!xfi->UseXThreads)
|
||||
{
|
||||
WaitForSingleObject(xfi->mutex, INFINITE);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (display)
|
||||
XLockDisplay(xfi->display);
|
||||
}
|
||||
}
|
||||
|
||||
void xf_unlock_x11(xfInfo* xfi, BOOL display)
|
||||
{
|
||||
if (!xfi->UseXThreads)
|
||||
{
|
||||
ReleaseMutex(xfi->mutex);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (display)
|
||||
XUnlockDisplay(xfi->display);
|
||||
}
|
||||
}
|
||||
|
||||
BOOL xf_get_pixmap_info(xfInfo* xfi)
|
||||
|
@ -529,6 +606,8 @@ BOOL xf_pre_connect(freerdp* instance)
|
|||
|
||||
((xfContext*) instance->context)->xfi = xfi;
|
||||
|
||||
xfi->mutex = CreateMutex(NULL, FALSE, NULL);
|
||||
|
||||
xfi->_context = instance->context;
|
||||
xfi->context = (xfContext*) instance->context;
|
||||
xfi->context->settings = instance->settings;
|
||||
|
@ -608,8 +687,16 @@ BOOL xf_pre_connect(freerdp* instance)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
if (!XInitThreads())
|
||||
printf("warning: XInitThreads() failure\n");
|
||||
xfi->UseXThreads = TRUE;
|
||||
|
||||
if (xfi->UseXThreads)
|
||||
{
|
||||
if (!XInitThreads())
|
||||
{
|
||||
printf("warning: XInitThreads() failure\n");
|
||||
xfi->UseXThreads = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
xfi->display = XOpenDisplay(NULL);
|
||||
|
||||
|
@ -1050,19 +1137,26 @@ void xf_free(xfInfo* xfi)
|
|||
|
||||
void* xf_update_thread(void* arg)
|
||||
{
|
||||
int status;
|
||||
wMessage message;
|
||||
wMessageQueue* queue;
|
||||
freerdp* instance = (freerdp*) arg;
|
||||
|
||||
status = 1;
|
||||
queue = freerdp_get_message_queue(instance, FREERDP_UPDATE_MESSAGE_QUEUE);
|
||||
|
||||
while (MessageQueue_Wait(queue))
|
||||
{
|
||||
if (MessageQueue_Peek(queue, &message, TRUE))
|
||||
while (MessageQueue_Peek(queue, &message, TRUE))
|
||||
{
|
||||
if (!freerdp_message_queue_process_message(instance, FREERDP_UPDATE_MESSAGE_QUEUE, &message))
|
||||
status = freerdp_message_queue_process_message(instance, FREERDP_UPDATE_MESSAGE_QUEUE, &message);
|
||||
|
||||
if (!status)
|
||||
break;
|
||||
}
|
||||
|
||||
if (!status)
|
||||
break;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
@ -1070,42 +1164,50 @@ void* xf_update_thread(void* arg)
|
|||
|
||||
void* xf_input_thread(void* arg)
|
||||
{
|
||||
int status;
|
||||
xfInfo* xfi;
|
||||
HANDLE event;
|
||||
XEvent xevent;
|
||||
wMessageQueue* queue;
|
||||
int pending_status = 1;
|
||||
int process_status = 1;
|
||||
freerdp* instance = (freerdp*) arg;
|
||||
|
||||
xfi = ((xfContext*) instance->context)->xfi;
|
||||
|
||||
event = CreateFileDescriptorEvent(NULL, TRUE, FALSE, xfi->xfds);
|
||||
event = CreateFileDescriptorEvent(NULL, FALSE, FALSE, xfi->xfds);
|
||||
|
||||
while (WaitForSingleObject(event, INFINITE) == WAIT_OBJECT_0)
|
||||
{
|
||||
WaitForSingleObject(xfi->mutex, INFINITE);
|
||||
|
||||
status = XPending(xfi->display);
|
||||
|
||||
ReleaseMutex(xfi->mutex);
|
||||
|
||||
if (status)
|
||||
do
|
||||
{
|
||||
ZeroMemory(&xevent, sizeof(xevent));
|
||||
xf_lock_x11(xfi, FALSE);
|
||||
|
||||
WaitForSingleObject(xfi->mutex, INFINITE);
|
||||
pending_status = XPending(xfi->display);
|
||||
|
||||
XNextEvent(xfi->display, &xevent);
|
||||
status = xf_event_process(instance, &xevent);
|
||||
xf_unlock_x11(xfi, FALSE);
|
||||
|
||||
ReleaseMutex(xfi->mutex);
|
||||
if (pending_status)
|
||||
{
|
||||
xf_lock_x11(xfi, FALSE);
|
||||
|
||||
if (!status)
|
||||
break;
|
||||
ZeroMemory(&xevent, sizeof(xevent));
|
||||
XNextEvent(xfi->display, &xevent);
|
||||
process_status = xf_event_process(instance, &xevent);
|
||||
|
||||
xf_unlock_x11(xfi, FALSE);
|
||||
|
||||
if (!process_status)
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (pending_status);
|
||||
|
||||
if (!process_status)
|
||||
break;
|
||||
}
|
||||
|
||||
printf("Closed from X\n");
|
||||
xfi->disconnect = TRUE;
|
||||
queue = freerdp_get_message_queue(instance, FREERDP_INPUT_MESSAGE_QUEUE);
|
||||
MessageQueue_PostQuit(queue, 0);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
@ -1172,6 +1274,8 @@ int xfreerdp_run(freerdp* instance)
|
|||
|
||||
status = freerdp_connect(instance);
|
||||
|
||||
xfi = ((xfContext*) instance->context)->xfi;
|
||||
|
||||
/* Connection succeeded. --authonly ? */
|
||||
if (instance->settings->AuthenticationOnly)
|
||||
{
|
||||
|
@ -1182,19 +1286,16 @@ int xfreerdp_run(freerdp* instance)
|
|||
|
||||
if (!status)
|
||||
{
|
||||
xf_free(((xfContext*) instance->context)->xfi);
|
||||
xf_free(xfi);
|
||||
return XF_EXIT_CONN_FAILED;
|
||||
}
|
||||
|
||||
xfi = ((xfContext*) instance->context)->xfi;
|
||||
channels = instance->context->channels;
|
||||
settings = instance->context->settings;
|
||||
|
||||
async_update = settings->AsyncUpdate;
|
||||
async_input = settings->AsyncInput;
|
||||
|
||||
xfi->mutex = CreateMutex(NULL, FALSE, NULL);
|
||||
|
||||
if (async_update)
|
||||
{
|
||||
update_thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) xf_update_thread, instance, 0, NULL);
|
||||
|
@ -1202,9 +1303,6 @@ int xfreerdp_run(freerdp* instance)
|
|||
|
||||
if (async_input)
|
||||
{
|
||||
input_event = freerdp_get_message_queue_event_handle(instance, FREERDP_INPUT_MESSAGE_QUEUE);
|
||||
fd_input_event = GetEventFileDescriptor(input_event);
|
||||
|
||||
input_thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) xf_input_thread, instance, 0, NULL);
|
||||
}
|
||||
|
||||
|
@ -1248,6 +1346,8 @@ int xfreerdp_run(freerdp* instance)
|
|||
}
|
||||
else
|
||||
{
|
||||
input_event = freerdp_get_message_queue_event_handle(instance, FREERDP_INPUT_MESSAGE_QUEUE);
|
||||
fd_input_event = GetEventFileDescriptor(input_event);
|
||||
rfds[rcount++] = (void*) (long) fd_input_event;
|
||||
}
|
||||
|
||||
|
@ -1271,11 +1371,11 @@ int xfreerdp_run(freerdp* instance)
|
|||
timeout.tv_sec = 1;
|
||||
timeout.tv_usec = 0;
|
||||
|
||||
select_status = select(max_fds + 1, &rfds_set, &wfds_set, NULL, &timeout);
|
||||
select_status = select(max_fds + 1, &rfds_set, NULL, NULL, &timeout);
|
||||
|
||||
if (select_status == 0)
|
||||
{
|
||||
continue;
|
||||
continue; /* select timeout */
|
||||
}
|
||||
else if (select_status == -1)
|
||||
{
|
||||
|
@ -1309,13 +1409,21 @@ int xfreerdp_run(freerdp* instance)
|
|||
{
|
||||
if (xf_process_x_events(instance) != TRUE)
|
||||
{
|
||||
printf("Closed from X\n");
|
||||
printf("Closed from X11\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
freerdp_message_queue_process_pending_messages(instance, FREERDP_INPUT_MESSAGE_QUEUE);
|
||||
if (WaitForSingleObject(input_event, 0) == WAIT_OBJECT_0)
|
||||
{
|
||||
if (!freerdp_message_queue_process_pending_messages(instance, FREERDP_INPUT_MESSAGE_QUEUE))
|
||||
{
|
||||
printf("User Disconnect\n");
|
||||
xfi->disconnect = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -115,6 +115,7 @@ struct xf_info
|
|||
HCLRCONV clrconv;
|
||||
Window parent_window;
|
||||
HANDLE mutex;
|
||||
BOOL UseXThreads;
|
||||
|
||||
HGDI_DC hdc;
|
||||
BOOL sw_gdi;
|
||||
|
@ -214,6 +215,9 @@ enum XF_EXIT_CODE
|
|||
XF_EXIT_UNKNOWN = 255,
|
||||
};
|
||||
|
||||
void xf_lock_x11(xfInfo* xfi, BOOL display);
|
||||
void xf_unlock_x11(xfInfo* xfi, BOOL display);
|
||||
|
||||
#ifdef WITH_DEBUG_X11
|
||||
#define DEBUG_X11(fmt, ...) DEBUG_CLASS(X11, fmt, ## __VA_ARGS__)
|
||||
#else
|
||||
|
|
|
@ -71,11 +71,21 @@ COMMAND_LINE_ARGUMENT_A args[] =
|
|||
{ "compression", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, "z", "Compression" },
|
||||
{ "shell", COMMAND_LINE_VALUE_REQUIRED, NULL, NULL, NULL, -1, NULL, "Alternate shell" },
|
||||
{ "shell-dir", COMMAND_LINE_VALUE_REQUIRED, NULL, NULL, NULL, -1, NULL, "Shell working directory" },
|
||||
{ "sound", COMMAND_LINE_VALUE_OPTIONAL, NULL, NULL, NULL, -1, "audio", "Audio output (sound)" },
|
||||
{ "microphone", COMMAND_LINE_VALUE_OPTIONAL, NULL, NULL, NULL, -1, "mic", "Audio input (microphone)" },
|
||||
{ "audio-mode", COMMAND_LINE_VALUE_REQUIRED, NULL, NULL, NULL, -1, NULL, "Audio output mode" },
|
||||
{ "mic", COMMAND_LINE_VALUE_FLAG, NULL, NULL, NULL, -1, NULL, "Audio input (microphone)" },
|
||||
{ "multimedia", COMMAND_LINE_VALUE_OPTIONAL, NULL, NULL, NULL, -1, "mmr", "Redirect multimedia (video)" },
|
||||
{ "network", COMMAND_LINE_VALUE_REQUIRED, NULL, NULL, NULL, -1, NULL, "Network connection type" },
|
||||
{ "drive", COMMAND_LINE_VALUE_REQUIRED, NULL, NULL, NULL, -1, NULL, "Redirect drive" },
|
||||
{ "drives", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "Redirect all drives" },
|
||||
{ "home-drive", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "Redirect home drive" },
|
||||
{ "clipboard", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "Redirect clipboard" },
|
||||
{ "fonts", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "Smooth fonts (cleartype)" },
|
||||
{ "serial", COMMAND_LINE_VALUE_REQUIRED, NULL, NULL, NULL, -1, "tty", "Redirect serial device" },
|
||||
{ "parallel", COMMAND_LINE_VALUE_REQUIRED, NULL, NULL, NULL, -1, NULL, "Redirect parallel device" },
|
||||
{ "smartcard", COMMAND_LINE_VALUE_REQUIRED, NULL, NULL, NULL, -1, NULL, "Redirect smartcard device" },
|
||||
{ "printer", COMMAND_LINE_VALUE_REQUIRED, NULL, NULL, NULL, -1, NULL, "Redirect printer device" },
|
||||
{ "usb", COMMAND_LINE_VALUE_REQUIRED, NULL, NULL, NULL, -1, NULL, "Redirect USB device" },
|
||||
{ "fonts", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "Smooth fonts (ClearType)" },
|
||||
{ "aero", COMMAND_LINE_VALUE_BOOL, NULL, NULL, BoolValueFalse, -1, NULL, "Desktop composition" },
|
||||
{ "window-drag", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "Full window drag" },
|
||||
{ "menu-anims", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "Menu animations" },
|
||||
|
@ -85,7 +95,7 @@ COMMAND_LINE_ARGUMENT_A args[] =
|
|||
{ "rfx", COMMAND_LINE_VALUE_FLAG, NULL, NULL, NULL, -1, NULL, "RemoteFX" },
|
||||
{ "rfx-mode", COMMAND_LINE_VALUE_REQUIRED, "<image|video>", NULL, NULL, -1, NULL, "RemoteFX mode" },
|
||||
{ "frame-ack", COMMAND_LINE_VALUE_REQUIRED, "<number>", NULL, NULL, -1, NULL, "Frame acknowledgement" },
|
||||
{ "nsc", COMMAND_LINE_VALUE_FLAG, NULL, NULL, NULL, -1, NULL, "NSCodec" },
|
||||
{ "nsc", COMMAND_LINE_VALUE_FLAG, NULL, NULL, NULL, -1, "nscodec", "NSCodec" },
|
||||
{ "jpeg", COMMAND_LINE_VALUE_FLAG, NULL, NULL, NULL, -1, NULL, "JPEG codec" },
|
||||
{ "jpeg-quality", COMMAND_LINE_VALUE_REQUIRED, "<percentage>", NULL, NULL, -1, NULL, "JPEG quality" },
|
||||
{ "nego", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL, "protocol security negotiation" },
|
||||
|
@ -159,7 +169,7 @@ int freerdp_client_print_command_line_help(int argc, char** argv)
|
|||
if (arg->Format)
|
||||
{
|
||||
length = strlen(arg->Name) + strlen(arg->Format) + 2;
|
||||
str = malloc(length + 1);
|
||||
str = (char*) malloc(length + 1);
|
||||
sprintf_s(str, length + 1, "%s:%s", arg->Name, arg->Format);
|
||||
printf("%-20s", str);
|
||||
free(str);
|
||||
|
@ -174,7 +184,7 @@ int freerdp_client_print_command_line_help(int argc, char** argv)
|
|||
else if (arg->Flags & COMMAND_LINE_VALUE_BOOL)
|
||||
{
|
||||
length = strlen(arg->Name) + 32;
|
||||
str = malloc(length + 1);
|
||||
str = (char*) malloc(length + 1);
|
||||
sprintf_s(str, length + 1, "%s (default:%s)", arg->Name,
|
||||
arg->Default ? "on" : "off");
|
||||
|
||||
|
@ -200,20 +210,20 @@ int freerdp_client_print_command_line_help(int argc, char** argv)
|
|||
printf("Clipboard Redirection: +clipboard\n");
|
||||
printf("\n");
|
||||
|
||||
printf("Drive Redirection: /a:drive,home,/home\n");
|
||||
printf("Smartcard Redirection: /a:smartcard,<device>\n");
|
||||
printf("Printer Redirection: /a:printer,<device>,<driver>\n");
|
||||
printf("Serial Port Redirection: /a:serial,<device>\n");
|
||||
printf("Parallel Port Redirection: /a:parallel,<device>\n");
|
||||
printf("Printer Redirection: /a:printer,<device>,<driver>\n");
|
||||
printf("Drive Redirection: /drive:home,/home/user\n");
|
||||
printf("Smartcard Redirection: /smartcard:<device>\n");
|
||||
printf("Printer Redirection: /printer:<device>,<driver>\n");
|
||||
printf("Serial Port Redirection: /serial:<device>\n");
|
||||
printf("Parallel Port Redirection: /parallel:<device>\n");
|
||||
printf("Printer Redirection: /printer:<device>,<driver>\n");
|
||||
printf("\n");
|
||||
|
||||
printf("Audio Input Redirection: /dvc:audin,sys:alsa\n");
|
||||
printf("Audio Output Redirection: /vc:rdpsnd,sys:alsa\n");
|
||||
printf("Audio Output Redirection: /sound:sys:alsa\n");
|
||||
printf("Audio Input Redirection: /microphone:sys:alsa\n");
|
||||
printf("\n");
|
||||
|
||||
printf("Multimedia Redirection: /dvc:tsmf,sys:alsa\n");
|
||||
printf("USB Device Redirection: /dvc:urbdrc,id,dev:054c:0268\n");
|
||||
printf("Multimedia Redirection: /multimedia:sys:alsa\n");
|
||||
printf("USB Device Redirection: /usb:id,dev:054c:0268\n");
|
||||
printf("\n");
|
||||
|
||||
printf("More documentation is coming, in the meantime consult source files\n");
|
||||
|
@ -422,9 +432,22 @@ char** freerdp_command_line_parse_comma_separated_values(char* list, int* count)
|
|||
return p;
|
||||
}
|
||||
|
||||
char** freerdp_command_line_parse_comma_separated_values_offset(char* list, int* count)
|
||||
{
|
||||
char** p;
|
||||
|
||||
p = freerdp_command_line_parse_comma_separated_values(list, count);
|
||||
|
||||
p = (char**) realloc(p, sizeof(char*) * (*count + 1));
|
||||
MoveMemory(&p[1], p, sizeof(char*) * *count);
|
||||
(*count)++;
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
int freerdp_client_command_line_post_filter(void* context, COMMAND_LINE_ARGUMENT_A* arg)
|
||||
{
|
||||
rdpSettings* settings;
|
||||
rdpSettings* settings = (rdpSettings*) context;
|
||||
|
||||
CommandLineSwitchStart(arg)
|
||||
|
||||
|
@ -432,7 +455,6 @@ int freerdp_client_command_line_post_filter(void* context, COMMAND_LINE_ARGUMENT
|
|||
{
|
||||
char** p;
|
||||
int count;
|
||||
settings = (rdpSettings*) context;
|
||||
|
||||
p = freerdp_command_line_parse_comma_separated_values(arg->Value, &count);
|
||||
|
||||
|
@ -447,7 +469,6 @@ int freerdp_client_command_line_post_filter(void* context, COMMAND_LINE_ARGUMENT
|
|||
{
|
||||
char** p;
|
||||
int count;
|
||||
settings = (rdpSettings*) context;
|
||||
|
||||
p = freerdp_command_line_parse_comma_separated_values(arg->Value, &count);
|
||||
|
||||
|
@ -459,7 +480,6 @@ int freerdp_client_command_line_post_filter(void* context, COMMAND_LINE_ARGUMENT
|
|||
{
|
||||
char** p;
|
||||
int count;
|
||||
settings = (rdpSettings*) context;
|
||||
|
||||
p = freerdp_command_line_parse_comma_separated_values(arg->Value, &count);
|
||||
|
||||
|
@ -467,6 +487,153 @@ int freerdp_client_command_line_post_filter(void* context, COMMAND_LINE_ARGUMENT
|
|||
|
||||
free(p);
|
||||
}
|
||||
CommandLineSwitchCase(arg, "drive")
|
||||
{
|
||||
char** p;
|
||||
int count;
|
||||
|
||||
p = freerdp_command_line_parse_comma_separated_values_offset(arg->Value, &count);
|
||||
p[0] = "drive";
|
||||
|
||||
freerdp_client_add_device_channel(settings, count, p);
|
||||
|
||||
free(p);
|
||||
}
|
||||
CommandLineSwitchCase(arg, "serial")
|
||||
{
|
||||
char** p;
|
||||
int count;
|
||||
|
||||
p = freerdp_command_line_parse_comma_separated_values_offset(arg->Value, &count);
|
||||
p[0] = "serial";
|
||||
|
||||
freerdp_client_add_device_channel(settings, count, p);
|
||||
|
||||
free(p);
|
||||
}
|
||||
CommandLineSwitchCase(arg, "parallel")
|
||||
{
|
||||
char** p;
|
||||
int count;
|
||||
|
||||
p = freerdp_command_line_parse_comma_separated_values_offset(arg->Value, &count);
|
||||
p[0] = "parallel";
|
||||
|
||||
freerdp_client_add_device_channel(settings, count, p);
|
||||
|
||||
free(p);
|
||||
}
|
||||
CommandLineSwitchCase(arg, "smartcard")
|
||||
{
|
||||
char** p;
|
||||
int count;
|
||||
|
||||
p = freerdp_command_line_parse_comma_separated_values_offset(arg->Value, &count);
|
||||
p[0] = "smartcard";
|
||||
|
||||
freerdp_client_add_device_channel(settings, count, p);
|
||||
|
||||
free(p);
|
||||
}
|
||||
CommandLineSwitchCase(arg, "printer")
|
||||
{
|
||||
char** p;
|
||||
int count;
|
||||
|
||||
p = freerdp_command_line_parse_comma_separated_values_offset(arg->Value, &count);
|
||||
p[0] = "printer";
|
||||
|
||||
freerdp_client_add_device_channel(settings, count, p);
|
||||
|
||||
free(p);
|
||||
}
|
||||
CommandLineSwitchCase(arg, "usb")
|
||||
{
|
||||
char** p;
|
||||
int count;
|
||||
|
||||
p = freerdp_command_line_parse_comma_separated_values_offset(arg->Value, &count);
|
||||
p[0] = "urbdrc";
|
||||
|
||||
freerdp_client_add_dynamic_channel(settings, count, p);
|
||||
|
||||
free(p);
|
||||
}
|
||||
CommandLineSwitchCase(arg, "sound")
|
||||
{
|
||||
if (arg->Flags & COMMAND_LINE_VALUE_PRESENT)
|
||||
{
|
||||
char** p;
|
||||
int count;
|
||||
|
||||
p = freerdp_command_line_parse_comma_separated_values_offset(arg->Value, &count);
|
||||
p[0] = "rdpsnd";
|
||||
|
||||
freerdp_client_add_static_channel(settings, count, p);
|
||||
|
||||
free(p);
|
||||
}
|
||||
else
|
||||
{
|
||||
char* p[1];
|
||||
int count;
|
||||
|
||||
count = 1;
|
||||
p[0] = "rdpsnd";
|
||||
|
||||
freerdp_client_add_static_channel(settings, count, p);
|
||||
}
|
||||
}
|
||||
CommandLineSwitchCase(arg, "microphone")
|
||||
{
|
||||
if (arg->Flags & COMMAND_LINE_VALUE_PRESENT)
|
||||
{
|
||||
char** p;
|
||||
int count;
|
||||
|
||||
p = freerdp_command_line_parse_comma_separated_values_offset(arg->Value, &count);
|
||||
p[0] = "audin";
|
||||
|
||||
freerdp_client_add_dynamic_channel(settings, count, p);
|
||||
|
||||
free(p);
|
||||
}
|
||||
else
|
||||
{
|
||||
char* p[1];
|
||||
int count;
|
||||
|
||||
count = 1;
|
||||
p[0] = "audin";
|
||||
|
||||
freerdp_client_add_dynamic_channel(settings, count, p);
|
||||
}
|
||||
}
|
||||
CommandLineSwitchCase(arg, "multimedia")
|
||||
{
|
||||
if (arg->Flags & COMMAND_LINE_VALUE_PRESENT)
|
||||
{
|
||||
char** p;
|
||||
int count;
|
||||
|
||||
p = freerdp_command_line_parse_comma_separated_values_offset(arg->Value, &count);
|
||||
p[0] = "tsmf";
|
||||
|
||||
freerdp_client_add_dynamic_channel(settings, count, p);
|
||||
|
||||
free(p);
|
||||
}
|
||||
else
|
||||
{
|
||||
char* p[1];
|
||||
int count;
|
||||
|
||||
count = 1;
|
||||
p[0] = "tsmf";
|
||||
|
||||
freerdp_client_add_dynamic_channel(settings, count, p);
|
||||
}
|
||||
}
|
||||
|
||||
CommandLineSwitchEnd(arg)
|
||||
|
||||
|
@ -1051,6 +1218,14 @@ int freerdp_client_parse_command_line_arguments(int argc, char** argv, rdpSettin
|
|||
{
|
||||
settings->CompressionEnabled = arg->Value ? TRUE : FALSE;
|
||||
}
|
||||
CommandLineSwitchCase(arg, "drives")
|
||||
{
|
||||
settings->RedirectDrives = arg->Value ? TRUE : FALSE;
|
||||
}
|
||||
CommandLineSwitchCase(arg, "home-drive")
|
||||
{
|
||||
settings->RedirectHomeDrive = arg->Value ? TRUE : FALSE;
|
||||
}
|
||||
CommandLineSwitchCase(arg, "clipboard")
|
||||
{
|
||||
settings->RedirectClipboard = arg->Value ? TRUE : FALSE;
|
||||
|
@ -1405,6 +1580,38 @@ int freerdp_client_load_addins(rdpChannels* channels, rdpSettings* settings)
|
|||
settings->AudioPlayback = TRUE; /* Both rdpsnd and tsmf require this flag to be set */
|
||||
}
|
||||
|
||||
if (settings->RedirectDrives)
|
||||
{
|
||||
settings->DeviceRedirection = TRUE;
|
||||
|
||||
if (!freerdp_device_collection_find(settings, "drive"))
|
||||
{
|
||||
char* params[3];
|
||||
|
||||
params[0] = "drive";
|
||||
params[1] = "media";
|
||||
params[2] = "*";
|
||||
|
||||
freerdp_client_add_device_channel(settings, 3, (char**) params);
|
||||
}
|
||||
}
|
||||
|
||||
if (settings->RedirectHomeDrive)
|
||||
{
|
||||
settings->DeviceRedirection = TRUE;
|
||||
|
||||
if (!freerdp_device_collection_find(settings, "drive"))
|
||||
{
|
||||
char* params[3];
|
||||
|
||||
params[0] = "drive";
|
||||
params[1] = "home";
|
||||
params[2] = "%";
|
||||
|
||||
freerdp_client_add_device_channel(settings, 3, (char**) params);
|
||||
}
|
||||
}
|
||||
|
||||
if (settings->DeviceRedirection)
|
||||
{
|
||||
freerdp_client_load_static_channel_addin(channels, settings, "rdpdr", settings);
|
||||
|
|
|
@ -121,7 +121,7 @@ int freerdp_client_old_process_plugin(rdpSettings* settings, ADDIN_ARGV* args)
|
|||
if (strcmp(args->argv[0], "cliprdr") == 0)
|
||||
{
|
||||
settings->RedirectClipboard = TRUE;
|
||||
printf("--plugin cliprdr -> --enable-clipboard\n");
|
||||
printf("--plugin cliprdr -> +clipboard\n");
|
||||
}
|
||||
else if (strcmp(args->argv[0], "rdpdr") == 0)
|
||||
{
|
||||
|
@ -398,37 +398,37 @@ int freerdp_client_parse_old_command_line_arguments(int argc, char** argv, rdpSe
|
|||
CommandLineSwitchCase(arg, "0")
|
||||
{
|
||||
settings->ConsoleSession = TRUE;
|
||||
printf("-0 -> --admin\n");
|
||||
printf("-0 -> /admin\n");
|
||||
}
|
||||
CommandLineSwitchCase(arg, "a")
|
||||
{
|
||||
settings->ColorDepth = atoi(arg->Value);
|
||||
printf("-a %s -> --bpp %s\n", arg->Value, arg->Value);
|
||||
printf("-a %s -> /bpp:%s\n", arg->Value, arg->Value);
|
||||
}
|
||||
CommandLineSwitchCase(arg, "c")
|
||||
{
|
||||
settings->ShellWorkingDirectory = _strdup(arg->Value);
|
||||
printf("-c %s -> --shell-dir %s\n", arg->Value, arg->Value);
|
||||
printf("-c %s -> /shell-dir:%s\n", arg->Value, arg->Value);
|
||||
}
|
||||
CommandLineSwitchCase(arg, "D")
|
||||
{
|
||||
settings->Decorations = FALSE;
|
||||
printf("-D -> --disable-decorations\n");
|
||||
printf("-D -> -decorations\n");
|
||||
}
|
||||
CommandLineSwitchCase(arg, "T")
|
||||
{
|
||||
settings->WindowTitle = _strdup(arg->Value);
|
||||
printf("-T %s -> --title %s\n", arg->Value, arg->Value);
|
||||
printf("-T %s -> /title:%s\n", arg->Value, arg->Value);
|
||||
}
|
||||
CommandLineSwitchCase(arg, "d")
|
||||
{
|
||||
settings->Domain = _strdup(arg->Value);
|
||||
printf("-d %s -> -d %s\n", arg->Value, arg->Value);
|
||||
printf("-d %s -> /d:%s\n", arg->Value, arg->Value);
|
||||
}
|
||||
CommandLineSwitchCase(arg, "f")
|
||||
{
|
||||
settings->Fullscreen = TRUE;
|
||||
printf("-f -> -f\n");
|
||||
printf("-f -> /f\n");
|
||||
}
|
||||
CommandLineSwitchCase(arg, "g")
|
||||
{
|
||||
|
@ -445,18 +445,18 @@ int freerdp_client_parse_old_command_line_arguments(int argc, char** argv, rdpSe
|
|||
|
||||
free(str);
|
||||
|
||||
printf("-g %s -> --size %s or -w %d -h %d\n", arg->Value, arg->Value,
|
||||
printf("-g %s -> /size:%s or /w:%d /h:%d\n", arg->Value, arg->Value,
|
||||
settings->DesktopWidth, settings->DesktopHeight);
|
||||
}
|
||||
CommandLineSwitchCase(arg, "k")
|
||||
{
|
||||
sscanf(arg->Value, "%X", &(settings->KeyboardLayout));
|
||||
printf("-k %s -> --kbd %s\n", arg->Value, arg->Value);
|
||||
printf("-k %s -> /kbd:%s\n", arg->Value, arg->Value);
|
||||
}
|
||||
CommandLineSwitchCase(arg, "K")
|
||||
{
|
||||
settings->GrabKeyboard = FALSE;
|
||||
printf("-K -> --disable-grab-keyboard\n");
|
||||
printf("-K -> -grab-keyboard\n");
|
||||
}
|
||||
CommandLineSwitchCase(arg, "n")
|
||||
{
|
||||
|
@ -465,27 +465,27 @@ int freerdp_client_parse_old_command_line_arguments(int argc, char** argv, rdpSe
|
|||
CommandLineSwitchCase(arg, "o")
|
||||
{
|
||||
settings->RemoteConsoleAudio = TRUE;
|
||||
printf("-o -> --audio-mode 1\n");
|
||||
printf("-o -> /audio-mode:1\n");
|
||||
}
|
||||
CommandLineSwitchCase(arg, "p")
|
||||
{
|
||||
settings->Password = _strdup(arg->Value);
|
||||
printf("-p %s -> -p %s\n", arg->Value, arg->Value);
|
||||
printf("-p %s -> /p:%s\n", arg->Value, arg->Value);
|
||||
}
|
||||
CommandLineSwitchCase(arg, "s")
|
||||
{
|
||||
settings->AlternateShell = _strdup(arg->Value);
|
||||
printf("-s %s -> --shell %s\n", arg->Value, arg->Value);
|
||||
printf("-s %s -> /shell:%s\n", arg->Value, arg->Value);
|
||||
}
|
||||
CommandLineSwitchCase(arg, "t")
|
||||
{
|
||||
settings->ServerPort = atoi(arg->Value);
|
||||
printf("-t %s -> --port %s\n", arg->Value, arg->Value);
|
||||
printf("-t %s -> /port:%s\n", arg->Value, arg->Value);
|
||||
}
|
||||
CommandLineSwitchCase(arg, "u")
|
||||
{
|
||||
settings->Username = _strdup(arg->Value);
|
||||
printf("-u %s -> -u %s\n", arg->Value, arg->Value);
|
||||
printf("-u %s -> /u:%s\n", arg->Value, arg->Value);
|
||||
}
|
||||
CommandLineSwitchCase(arg, "x")
|
||||
{
|
||||
|
@ -512,7 +512,7 @@ int freerdp_client_parse_old_command_line_arguments(int argc, char** argv, rdpSe
|
|||
settings->PerformanceFlags = type;
|
||||
}
|
||||
|
||||
printf("-x %s -> --network ", arg->Value);
|
||||
printf("-x %s -> /network ", arg->Value);
|
||||
|
||||
if (type == CONNECTION_TYPE_MODEM)
|
||||
printf("modem");
|
||||
|
@ -526,17 +526,17 @@ int freerdp_client_parse_old_command_line_arguments(int argc, char** argv, rdpSe
|
|||
CommandLineSwitchCase(arg, "X")
|
||||
{
|
||||
settings->ParentWindowId = strtol(arg->Value, NULL, 0);
|
||||
printf("-X %s -> --parent-window %s\n", arg->Value, arg->Value);
|
||||
printf("-X %s -> /parent-window:%s\n", arg->Value, arg->Value);
|
||||
}
|
||||
CommandLineSwitchCase(arg, "z")
|
||||
{
|
||||
settings->CompressionEnabled = TRUE;
|
||||
printf("-z -> --compression\n");
|
||||
printf("-z -> /compression\n");
|
||||
}
|
||||
CommandLineSwitchCase(arg, "app")
|
||||
{
|
||||
settings->RemoteApplicationMode = TRUE;
|
||||
printf("--app -> --app + program name or alias\n");
|
||||
printf("--app -> /app + program name or alias\n");
|
||||
}
|
||||
CommandLineSwitchCase(arg, "ext")
|
||||
{
|
||||
|
@ -545,7 +545,7 @@ int freerdp_client_parse_old_command_line_arguments(int argc, char** argv, rdpSe
|
|||
CommandLineSwitchCase(arg, "no-auth")
|
||||
{
|
||||
settings->Authentication = FALSE;
|
||||
printf("--no-auth -> --disable-authentication\n");
|
||||
printf("--no-auth -> -authentication\n");
|
||||
}
|
||||
CommandLineSwitchCase(arg, "authonly")
|
||||
{
|
||||
|
@ -559,12 +559,12 @@ int freerdp_client_parse_old_command_line_arguments(int argc, char** argv, rdpSe
|
|||
{
|
||||
settings->FastPathInput = FALSE;
|
||||
settings->FastPathOutput = FALSE;
|
||||
printf("--no-fastpath -> --disable-fast-path\n");
|
||||
printf("--no-fastpath -> -fast-path\n");
|
||||
}
|
||||
CommandLineSwitchCase(arg, "no-motion")
|
||||
{
|
||||
settings->MouseMotion = FALSE;
|
||||
printf("--no-motion -> --disable-mouse-motion\n");
|
||||
printf("--no-motion -> -mouse-motion\n");
|
||||
}
|
||||
CommandLineSwitchCase(arg, "gdi")
|
||||
{
|
||||
|
@ -573,26 +573,26 @@ int freerdp_client_parse_old_command_line_arguments(int argc, char** argv, rdpSe
|
|||
else if (strcmp(arg->Value, "hw") == 0)
|
||||
settings->SoftwareGdi = FALSE;
|
||||
|
||||
printf("--gdi %s -> --gdi %s\n", arg->Value, arg->Value);
|
||||
printf("--gdi %s -> /gdi:%s\n", arg->Value, arg->Value);
|
||||
}
|
||||
CommandLineSwitchCase(arg, "no-osb")
|
||||
{
|
||||
settings->OffscreenSupportLevel = FALSE;
|
||||
printf("--no-osb -> --disable-offscreen-cache\n");
|
||||
printf("--no-osb -> -offscreen-cache\n");
|
||||
}
|
||||
CommandLineSwitchCase(arg, "no-bmp-cache")
|
||||
{
|
||||
settings->BitmapCacheEnabled = FALSE;
|
||||
printf("--no-bmp-cache -> --disable-bitmap-cache\n");
|
||||
printf("--no-bmp-cache -> -bitmap-cache\n");
|
||||
}
|
||||
CommandLineSwitchCase(arg, "plugin")
|
||||
{
|
||||
printf("--plugin -> -a, --vc, --dvc and channel-specific options\n");
|
||||
printf("--plugin -> /a, /vc, /dvc and channel-specific options\n");
|
||||
}
|
||||
CommandLineSwitchCase(arg, "rfx")
|
||||
{
|
||||
settings->RemoteFxCodec = TRUE;
|
||||
printf("--rfx -> --rfx\n");
|
||||
printf("--rfx -> /rfx\n");
|
||||
}
|
||||
CommandLineSwitchCase(arg, "rfx-mode")
|
||||
{
|
||||
|
@ -600,37 +600,38 @@ int freerdp_client_parse_old_command_line_arguments(int argc, char** argv, rdpSe
|
|||
settings->RemoteFxCodecMode = 0x00;
|
||||
else if (arg->Value[0] == 'i')
|
||||
settings->RemoteFxCodecMode = 0x02;
|
||||
printf("--rfx-mode -> --rfx-mode\n");
|
||||
|
||||
printf("--rfx-mode -> /rfx-mode\n");
|
||||
}
|
||||
CommandLineSwitchCase(arg, "nsc")
|
||||
{
|
||||
settings->NSCodec = TRUE;
|
||||
printf("--nsc -> --nsc\n");
|
||||
printf("--nsc -> /nsc\n");
|
||||
}
|
||||
CommandLineSwitchCase(arg, "disable-wallpaper")
|
||||
{
|
||||
settings->DisableWallpaper = TRUE;
|
||||
printf("--disable-wallpaper -> --disable-wallpaper\n");
|
||||
printf("--disable-wallpaper -> -wallpaper\n");
|
||||
}
|
||||
CommandLineSwitchCase(arg, "composition")
|
||||
{
|
||||
settings->AllowDesktopComposition = TRUE;
|
||||
printf("--composition -> --enable-composition\n");
|
||||
printf("--composition -> +composition\n");
|
||||
}
|
||||
CommandLineSwitchCase(arg, "disable-full-window-drag")
|
||||
{
|
||||
settings->DisableFullWindowDrag = TRUE;
|
||||
printf("--disable-full-window-drag -> --disable-window-drag\n");
|
||||
printf("--disable-full-window-drag -> -window-drag\n");
|
||||
}
|
||||
CommandLineSwitchCase(arg, "disable-menu-animations")
|
||||
{
|
||||
settings->DisableMenuAnims = TRUE;
|
||||
printf("--disable-menu-animations -> --disable-menu-anims\n");
|
||||
printf("--disable-menu-animations -> -menu-anims\n");
|
||||
}
|
||||
CommandLineSwitchCase(arg, "disable-theming")
|
||||
{
|
||||
settings->DisableThemes = TRUE;
|
||||
printf("--disable-theming -> --disable-themes\n");
|
||||
printf("--disable-theming -> -themes\n");
|
||||
}
|
||||
CommandLineSwitchCase(arg, "ntlm")
|
||||
{
|
||||
|
@ -639,7 +640,7 @@ int freerdp_client_parse_old_command_line_arguments(int argc, char** argv, rdpSe
|
|||
CommandLineSwitchCase(arg, "ignore-certificate")
|
||||
{
|
||||
settings->IgnoreCertificate = TRUE;
|
||||
printf("--ignore-certificate -> --cert-ignore\n");
|
||||
printf("--ignore-certificate -> /cert-ignore\n");
|
||||
}
|
||||
CommandLineSwitchCase(arg, "sec")
|
||||
{
|
||||
|
@ -665,22 +666,22 @@ int freerdp_client_parse_old_command_line_arguments(int argc, char** argv, rdpSe
|
|||
settings->NlaSecurity = TRUE;
|
||||
}
|
||||
|
||||
printf("--sec %s -> --sec %s\n", arg->Value, arg->Value);
|
||||
printf("--sec %s -> /sec:%s\n", arg->Value, arg->Value);
|
||||
}
|
||||
CommandLineSwitchCase(arg, "no-rdp")
|
||||
{
|
||||
settings->RdpSecurity = FALSE;
|
||||
printf("--no-rdp -> --disable-sec-rdp\n");
|
||||
printf("--no-rdp -> -sec-rdp\n");
|
||||
}
|
||||
CommandLineSwitchCase(arg, "no-tls")
|
||||
{
|
||||
settings->TlsSecurity = FALSE;
|
||||
printf("--no-tls -> --disable-sec-tls\n");
|
||||
printf("--no-tls -> -sec-tls\n");
|
||||
}
|
||||
CommandLineSwitchCase(arg, "no-nla")
|
||||
{
|
||||
settings->NlaSecurity = FALSE;
|
||||
printf("--no-nla -> --disable-sec-nla\n");
|
||||
printf("--no-nla -> -sec-nla\n");
|
||||
}
|
||||
CommandLineSwitchCase(arg, "secure-checksum")
|
||||
{
|
||||
|
@ -695,10 +696,10 @@ int freerdp_client_parse_old_command_line_arguments(int argc, char** argv, rdpSe
|
|||
}
|
||||
while ((arg = CommandLineFindNextArgumentA(arg)) != NULL);
|
||||
|
||||
printf("%s -> -v %s", settings->ServerHostname, settings->ServerHostname);
|
||||
printf("%s -> /v:%s", settings->ServerHostname, settings->ServerHostname);
|
||||
|
||||
if (settings->ServerPort != 3389)
|
||||
printf(" --port %d", settings->ServerPort);
|
||||
printf(" /port:%d", settings->ServerPort);
|
||||
|
||||
printf("\n");
|
||||
|
||||
|
|
|
@ -17,10 +17,18 @@ else()
|
|||
option(WITH_SSE2 "Enable SSE2 optimization." OFF)
|
||||
endif()
|
||||
|
||||
if((TARGET_ARCH MATCHES "ARM") AND (NOT DEFINED WITH_NEON))
|
||||
option(WITH_NEON "Enable NEON optimization." ON)
|
||||
else()
|
||||
option(WITH_NEON "Enable NEON optimization." OFF)
|
||||
if(TARGET_ARCH MATCHES "ARM")
|
||||
if (NOT DEFINED WITH_NEON)
|
||||
option(WITH_NEON "Enable NEON optimization." ON)
|
||||
else()
|
||||
option(WITH_NEON "Enable NEON optimization." OFF)
|
||||
endif()
|
||||
if (NOT DEFINED ARM_FP_ABI)
|
||||
set(ARM_FP_ABI "softfp" CACHE STRING "Floating point ABI to use on arm")
|
||||
else()
|
||||
set(ARM_FP_ABI ${ARM_FP_API} CACHE STRING "Floating point ABI to use on arm")
|
||||
endif()
|
||||
mark_as_advanced(ARM_FP_ABI)
|
||||
endif()
|
||||
|
||||
option(WITH_JPEG "Use JPEG decoding." OFF)
|
||||
|
@ -74,6 +82,7 @@ else()
|
|||
endif()
|
||||
|
||||
option(WITH_DEBUG_CERTIFICATE "Print certificate related debug messages." ${DEFAULT_DEBUG_OPTION})
|
||||
option(WITH_DEBUG_CAPABILITIES "Print capability negotiation debug messages." ${DEFAULT_DEBUG_OPTION})
|
||||
option(WITH_DEBUG_CHANNELS "Print channel manager debug messages." ${DEFAULT_DEBUG_OPTION})
|
||||
option(WITH_DEBUG_CLIPRDR "Print clipboard redirection debug messages" ${DEFAULT_DEBUG_OPTION})
|
||||
option(WITH_DEBUG_DVC "Print dynamic virtual channel debug messages." ${DEFAULT_DEBUG_OPTION})
|
||||
|
|
|
@ -40,6 +40,7 @@
|
|||
#cmakedefine WITH_NATIVE_SSPI
|
||||
#cmakedefine WITH_JPEG
|
||||
#cmakedefine WITH_WIN8
|
||||
#cmakedefine WITH_RDPSND_DSOUND
|
||||
|
||||
/* Plugins */
|
||||
#cmakedefine STATIC_CHANNELS
|
||||
|
@ -48,6 +49,7 @@
|
|||
|
||||
/* Debug */
|
||||
#cmakedefine WITH_DEBUG_CERTIFICATE
|
||||
#cmakedefine WITH_DEBUG_CAPABILITIES
|
||||
#cmakedefine WITH_DEBUG_CHANNELS
|
||||
#cmakedefine WITH_DEBUG_CLIPRDR
|
||||
#cmakedefine WITH_DEBUG_DVC
|
||||
|
|
|
@ -28,7 +28,8 @@ enum RDP_CODEC_ID
|
|||
RDP_CODEC_ID_NONE = 0x00,
|
||||
RDP_CODEC_ID_NSCODEC = 0x01,
|
||||
RDP_CODEC_ID_JPEG = 0x02,
|
||||
RDP_CODEC_ID_REMOTEFX = 0x03
|
||||
RDP_CODEC_ID_REMOTEFX = 0x03,
|
||||
RDP_CODEC_ID_IMAGE_REMOTEFX = 0x04
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -176,6 +176,7 @@
|
|||
#define NEG_POLYGON_SC_INDEX 0x14
|
||||
#define NEG_POLYGON_CB_INDEX 0x15
|
||||
#define NEG_POLYLINE_INDEX 0x16
|
||||
#define NEG_UNUSED23_INDEX 0x17
|
||||
#define NEG_FAST_GLYPH_INDEX 0x18
|
||||
#define NEG_ELLIPSE_SC_INDEX 0x19
|
||||
#define NEG_ELLIPSE_CB_INDEX 0x1A
|
||||
|
@ -183,6 +184,7 @@
|
|||
#define NEG_GLYPH_WEXTTEXTOUT_INDEX 0x1C
|
||||
#define NEG_GLYPH_WLONGTEXTOUT_INDEX 0x1D
|
||||
#define NEG_GLYPH_WLONGEXTTEXTOUT_INDEX 0x1E
|
||||
#define NEG_UNUSED31_INDEX 0x1F
|
||||
|
||||
/* Glyph Support Level */
|
||||
#define GLYPH_SUPPORT_NONE 0x0000
|
||||
|
@ -872,7 +874,8 @@ struct rdp_settings
|
|||
ALIGN64 BOOL RemoteFxCodec; /* 3649 */
|
||||
ALIGN64 UINT32 RemoteFxCodecId; /* 3650 */
|
||||
ALIGN64 UINT32 RemoteFxCodecMode; /* 3651 */
|
||||
UINT64 padding3712[3712 - 3652]; /* 3652 */
|
||||
ALIGN64 BOOL RemoteFxImageCodec; /* 3652 */
|
||||
UINT64 padding3712[3712 - 3653]; /* 3653 */
|
||||
|
||||
/* NSCodec */
|
||||
ALIGN64 BOOL NSCodec; /* 3712 */
|
||||
|
@ -926,6 +929,7 @@ struct rdp_settings
|
|||
|
||||
/* Drive Redirection */
|
||||
ALIGN64 BOOL RedirectDrives; /* */
|
||||
ALIGN64 BOOL RedirectHomeDrive; /* */
|
||||
ALIGN64 char* DrivesToRedirect; /* */
|
||||
|
||||
/* Smartcard Redirection */
|
||||
|
@ -985,6 +989,7 @@ FREERDP_API int freerdp_addin_set_argument_value(ADDIN_ARGV* args, char* option,
|
|||
FREERDP_API int freerdp_addin_replace_argument_value(ADDIN_ARGV* args, char* previous, char* option, char* value);
|
||||
|
||||
FREERDP_API void freerdp_device_collection_add(rdpSettings* settings, RDPDR_DEVICE* device);
|
||||
FREERDP_API RDPDR_DEVICE* freerdp_device_collection_find(rdpSettings* settings, const char* name);
|
||||
FREERDP_API void freerdp_device_collection_free(rdpSettings* settings);
|
||||
|
||||
FREERDP_API void freerdp_static_channel_collection_add(rdpSettings* settings, ADDIN_ARGV* channel);
|
||||
|
|
|
@ -76,7 +76,7 @@ if(WITH_NEON)
|
|||
${ANDROID_CPU_FEATURES_PATH}/cpu-features.h)
|
||||
endif()
|
||||
set(${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_SRCS} ${${MODULE_PREFIX}_NEON_SRCS})
|
||||
set_source_files_properties(${${MODULE_PREFIX}_NEON_SRCS} PROPERTIES COMPILE_FLAGS "-mfpu=neon -mfloat-abi=softfp -Wno-unused-variable")
|
||||
set_source_files_properties(${${MODULE_PREFIX}_NEON_SRCS} PROPERTIES COMPILE_FLAGS "-mfpu=neon -mfloat-abi=${ARM_FP_ABI} -Wno-unused-variable")
|
||||
endif()
|
||||
|
||||
if(WITH_JPEG)
|
||||
|
|
|
@ -143,6 +143,22 @@ void freerdp_device_collection_add(rdpSettings* settings, RDPDR_DEVICE* device)
|
|||
settings->DeviceArray[settings->DeviceCount++] = device;
|
||||
}
|
||||
|
||||
RDPDR_DEVICE* freerdp_device_collection_find(rdpSettings* settings, const char* name)
|
||||
{
|
||||
int index;
|
||||
RDPDR_DEVICE* device;
|
||||
|
||||
for (index = 0; index < settings->DeviceCount; index++)
|
||||
{
|
||||
device = (RDPDR_DEVICE*) settings->DeviceArray[index];
|
||||
|
||||
if (strcmp(device->Name, name) == 0)
|
||||
return device;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void freerdp_device_collection_free(rdpSettings* settings)
|
||||
{
|
||||
int index;
|
||||
|
|
|
@ -136,7 +136,7 @@ set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
|
|||
set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
|
||||
MONOLITHIC ${MONOLITHIC_BUILD}
|
||||
MODULE winpr
|
||||
MODULES winpr-registry winpr-utils winpr-interlocked winpr-dsparse winpr-sspi winpr-crt)
|
||||
MODULES winpr-registry winpr-utils winpr-interlocked winpr-dsparse winpr-sspi winpr-rpc winpr-crt)
|
||||
|
||||
if(MONOLITHIC_BUILD)
|
||||
set(FREERDP_LIBS ${FREERDP_LIBS} ${${MODULE_PREFIX}_LIBS} PARENT_SCOPE)
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -439,6 +439,7 @@ BOOL rdp_client_connect_mcs_channel_join_confirm(rdpRdp* rdp, STREAM* s)
|
|||
{
|
||||
if (channel_id != rdp->mcs->user_id)
|
||||
return FALSE;
|
||||
|
||||
rdp->mcs->user_channel_joined = TRUE;
|
||||
|
||||
if (!mcs_send_channel_join_request(rdp->mcs, MCS_GLOBAL_CHANNEL_ID))
|
||||
|
@ -448,6 +449,7 @@ BOOL rdp_client_connect_mcs_channel_join_confirm(rdpRdp* rdp, STREAM* s)
|
|||
{
|
||||
if (channel_id != MCS_GLOBAL_CHANNEL_ID)
|
||||
return FALSE;
|
||||
|
||||
rdp->mcs->global_channel_joined = TRUE;
|
||||
|
||||
if (rdp->settings->ChannelCount > 0)
|
||||
|
@ -471,6 +473,7 @@ BOOL rdp_client_connect_mcs_channel_join_confirm(rdpRdp* rdp, STREAM* s)
|
|||
rdp->settings->ChannelDefArray[i].joined = TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
if (i + 1 < rdp->settings->ChannelCount)
|
||||
{
|
||||
if (!mcs_send_channel_join_request(rdp->mcs, rdp->settings->ChannelDefArray[i + 1].ChannelId))
|
||||
|
@ -484,8 +487,10 @@ BOOL rdp_client_connect_mcs_channel_join_confirm(rdpRdp* rdp, STREAM* s)
|
|||
{
|
||||
if (!rdp_client_establish_keys(rdp))
|
||||
return FALSE;
|
||||
|
||||
if (!rdp_send_client_info(rdp))
|
||||
return FALSE;
|
||||
|
||||
rdp->state = CONNECTION_STATE_LICENSE;
|
||||
}
|
||||
|
||||
|
|
|
@ -59,6 +59,9 @@ int connectErrorCode;
|
|||
#define ERRINFO_RPC_INITIATED_DISCONNECT_BY_USER_STRING \
|
||||
"The disconnection was initiated by an administrative tool on the server running in the user's session."
|
||||
|
||||
#define ERRINFO_LOGOFF_BY_USER_STRING \
|
||||
"The disconnection was initiated by the user logging off his or her session on the server."
|
||||
|
||||
/* Protocol-independent licensing codes */
|
||||
|
||||
#define ERRINFO_LICENSE_INTERNAL_STRING \
|
||||
|
@ -351,6 +354,7 @@ static const ERRINFO ERRINFO_CODES[] =
|
|||
ERRINFO_DEFINE(SERVER_INSUFFICIENT_PRIVILEGES),
|
||||
ERRINFO_DEFINE(SERVER_FRESH_CREDENTIALS_REQUIRED),
|
||||
ERRINFO_DEFINE(RPC_INITIATED_DISCONNECT_BY_USER),
|
||||
ERRINFO_DEFINE(LOGOFF_BY_USER),
|
||||
|
||||
/* Protocol-independent licensing codes */
|
||||
ERRINFO_DEFINE(LICENSE_INTERNAL),
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#define ERRINFO_SERVER_INSUFFICIENT_PRIVILEGES 0x00000009
|
||||
#define ERRINFO_SERVER_FRESH_CREDENTIALS_REQUIRED 0x0000000A
|
||||
#define ERRINFO_RPC_INITIATED_DISCONNECT_BY_USER 0x0000000B
|
||||
#define ERRINFO_LOGOFF_BY_USER 0x0000000C
|
||||
|
||||
/* Protocol-independent licensing codes */
|
||||
#define ERRINFO_LICENSE_INTERNAL 0x00000100
|
||||
|
|
|
@ -193,9 +193,9 @@ static const char* const mcs_result_enumerated[] =
|
|||
|
||||
BOOL mcs_read_domain_mcspdu_header(STREAM* s, enum DomainMCSPDU* domainMCSPDU, UINT16* length)
|
||||
{
|
||||
UINT16 li;
|
||||
BYTE choice;
|
||||
enum DomainMCSPDU MCSPDU;
|
||||
UINT16 li;
|
||||
|
||||
*length = tpkt_read_header(s);
|
||||
|
||||
|
@ -203,8 +203,10 @@ BOOL mcs_read_domain_mcspdu_header(STREAM* s, enum DomainMCSPDU* domainMCSPDU, U
|
|||
return FALSE;
|
||||
|
||||
MCSPDU = *domainMCSPDU;
|
||||
if(!per_read_choice(s, &choice))
|
||||
|
||||
if (!per_read_choice(s, &choice))
|
||||
return FALSE;
|
||||
|
||||
*domainMCSPDU = (choice >> 2);
|
||||
|
||||
if (*domainMCSPDU != MCSPDU)
|
||||
|
@ -736,19 +738,23 @@ BOOL mcs_send_channel_join_request(rdpMcs* mcs, UINT16 channel_id)
|
|||
|
||||
BOOL mcs_recv_channel_join_confirm(rdpMcs* mcs, STREAM* s, UINT16* channel_id)
|
||||
{
|
||||
BOOL status;
|
||||
UINT16 length;
|
||||
BYTE result;
|
||||
UINT16 initiator;
|
||||
UINT16 requested;
|
||||
enum DomainMCSPDU MCSPDU;
|
||||
|
||||
status = TRUE;
|
||||
MCSPDU = DomainMCSPDU_ChannelJoinConfirm;
|
||||
return
|
||||
mcs_read_domain_mcspdu_header(s, &MCSPDU, &length) &&
|
||||
per_read_enumerated(s, &result, MCS_Result_enum_length) && /* result */
|
||||
per_read_integer16(s, &initiator, MCS_BASE_CHANNEL_ID) && /* initiator (UserId) */
|
||||
per_read_integer16(s, &requested, 0) && /* requested (ChannelId) */
|
||||
per_read_integer16(s, channel_id, 0); /* channelId */
|
||||
|
||||
status &= mcs_read_domain_mcspdu_header(s, &MCSPDU, &length);
|
||||
status &= per_read_enumerated(s, &result, MCS_Result_enum_length); /* result */
|
||||
status &= per_read_integer16(s, &initiator, MCS_BASE_CHANNEL_ID); /* initiator (UserId) */
|
||||
status &= per_read_integer16(s, &requested, 0); /* requested (ChannelId) */
|
||||
status &= per_read_integer16(s, channel_id, 0); /* channelId */
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -127,10 +127,13 @@ static void update_message_RefreshRect(rdpContext* context, BYTE count, RECTANGL
|
|||
|
||||
static void update_message_SuppressOutput(rdpContext* context, BYTE allow, RECTANGLE_16* area)
|
||||
{
|
||||
RECTANGLE_16* lParam;
|
||||
RECTANGLE_16* lParam = NULL;
|
||||
|
||||
lParam = (RECTANGLE_16*) malloc(sizeof(RECTANGLE_16));
|
||||
CopyMemory(lParam, area, sizeof(RECTANGLE_16));
|
||||
if (area)
|
||||
{
|
||||
lParam = (RECTANGLE_16*) malloc(sizeof(RECTANGLE_16));
|
||||
CopyMemory(lParam, area, sizeof(RECTANGLE_16));
|
||||
}
|
||||
|
||||
MessageQueue_Post(context->update->queue, (void*) context,
|
||||
MakeMessageId(Update, SuppressOutput), (void*) (size_t) allow, (void*) lParam);
|
||||
|
@ -974,7 +977,8 @@ int update_message_process_update_class(rdpUpdateProxy* proxy, wMessage* msg, in
|
|||
case Update_SuppressOutput:
|
||||
IFCALL(proxy->SuppressOutput, msg->context,
|
||||
(BYTE) (size_t) msg->wParam, (RECTANGLE_16*) msg->lParam);
|
||||
free(msg->lParam);
|
||||
if (msg->lParam)
|
||||
free(msg->lParam);
|
||||
break;
|
||||
|
||||
case Update_SurfaceCommand:
|
||||
|
@ -1491,13 +1495,29 @@ int update_message_queue_process_message(rdpUpdate* update, wMessage* message)
|
|||
if (message->id == WMQ_QUIT)
|
||||
return 0;
|
||||
|
||||
/**
|
||||
* FIXME:
|
||||
*
|
||||
* Certain messages like RefreshRect, SuppressOutput and SurfaceFrameAcknowledge
|
||||
* and not really output but really input events that send a message to the server.
|
||||
* Right now they will race with other code making use of the transport layer.
|
||||
*/
|
||||
|
||||
switch (message->id)
|
||||
{
|
||||
case FREERDP_UPDATE_REFRESH_RECT:
|
||||
case FREERDP_UPDATE_SUPPRESS_OUTPUT:
|
||||
case FREERDP_UPDATE_SURFACE_FRAME_ACKNOWLEDGE:
|
||||
return 1;
|
||||
}
|
||||
|
||||
msgClass = GetMessageClass(message->id);
|
||||
msgType = GetMessageType(message->id);
|
||||
|
||||
status = update_message_process_class(update->proxy, message, msgClass, msgType);
|
||||
|
||||
if (status < 0)
|
||||
return -1;
|
||||
status = -1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
@ -1508,15 +1528,11 @@ int update_message_queue_process_pending_messages(rdpUpdate* update)
|
|||
wMessage message;
|
||||
wMessageQueue* queue;
|
||||
|
||||
status = 1;
|
||||
queue = update->queue;
|
||||
|
||||
while (1)
|
||||
while (MessageQueue_Peek(queue, &message, TRUE))
|
||||
{
|
||||
status = MessageQueue_Peek(queue, &message, TRUE);
|
||||
|
||||
if (!status)
|
||||
break;
|
||||
|
||||
status = update_message_queue_process_message(update, &message);
|
||||
|
||||
if (!status)
|
||||
|
@ -1865,26 +1881,26 @@ int input_message_queue_process_message(rdpInput* input, wMessage* message)
|
|||
|
||||
int input_message_queue_process_pending_messages(rdpInput* input)
|
||||
{
|
||||
int count;
|
||||
int status;
|
||||
wMessage message;
|
||||
wMessageQueue* queue;
|
||||
|
||||
count = 0;
|
||||
status = 1;
|
||||
queue = input->queue;
|
||||
|
||||
while (1)
|
||||
while (MessageQueue_Peek(queue, &message, TRUE))
|
||||
{
|
||||
status = MessageQueue_Peek(queue, &message, TRUE);
|
||||
|
||||
if (!status)
|
||||
break;
|
||||
|
||||
status = input_message_queue_process_message(input, &message);
|
||||
|
||||
if (!status)
|
||||
break;
|
||||
|
||||
count++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return status;
|
||||
}
|
||||
|
||||
void input_message_proxy_register(rdpInputProxy* proxy, rdpInput* input)
|
||||
|
|
|
@ -483,12 +483,14 @@ BOOL rdp_send_data_pdu(rdpRdp* rdp, STREAM* s, BYTE type, UINT16 channel_id)
|
|||
|
||||
BOOL rdp_recv_set_error_info_data_pdu(rdpRdp* rdp, STREAM* s)
|
||||
{
|
||||
if(stream_get_left(s) < 4)
|
||||
if (stream_get_left(s) < 4)
|
||||
return FALSE;
|
||||
|
||||
stream_read_UINT32(s, rdp->errorInfo); /* errorInfo (4 bytes) */
|
||||
|
||||
if (rdp->errorInfo != ERRINFO_SUCCESS)
|
||||
rdp_print_errinfo(rdp->errorInfo);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -913,10 +915,7 @@ static int rdp_recv_callback(rdpTransport* transport, STREAM* s, void* extra)
|
|||
|
||||
case CONNECTION_STATE_CAPABILITY:
|
||||
if (!rdp_client_connect_demand_active(rdp, s))
|
||||
{
|
||||
printf("rdp_client_connect_demand_active failed\n");
|
||||
status = -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case CONNECTION_STATE_FINALIZATION:
|
||||
|
|
|
@ -679,7 +679,8 @@ int transport_check_fds(rdpTransport** ptransport)
|
|||
}
|
||||
|
||||
received = transport->ReceiveBuffer;
|
||||
transport->ReceiveBuffer = transport_receive_pool_take(transport);
|
||||
transport->ReceiveBuffer = ObjectPool_Take(transport->ReceivePool);
|
||||
transport->ReceiveBuffer->p = transport->ReceiveBuffer->data;
|
||||
|
||||
stream_set_pos(received, length);
|
||||
stream_seal(received);
|
||||
|
@ -695,7 +696,7 @@ int transport_check_fds(rdpTransport** ptransport)
|
|||
|
||||
recv_status = transport->ReceiveCallback(transport, received, transport->ReceiveExtra);
|
||||
|
||||
transport_receive_pool_return(transport, received);
|
||||
ObjectPool_Return(transport->ReceivePool, received);
|
||||
|
||||
if (recv_status < 0)
|
||||
status = -1;
|
||||
|
@ -735,29 +736,16 @@ BOOL transport_set_blocking_mode(rdpTransport* transport, BOOL blocking)
|
|||
return status;
|
||||
}
|
||||
|
||||
STREAM* transport_receive_pool_take(rdpTransport* transport)
|
||||
STREAM* transport_receive_buffer_pool_new()
|
||||
{
|
||||
STREAM* pdu = NULL;
|
||||
|
||||
if (WaitForSingleObject(Queue_Event(transport->ReceivePool), 0) == WAIT_OBJECT_0)
|
||||
pdu = Queue_Dequeue(transport->ReceivePool);
|
||||
|
||||
if (!pdu)
|
||||
{
|
||||
pdu = stream_new(BUFFER_SIZE);
|
||||
}
|
||||
|
||||
pdu = stream_new(BUFFER_SIZE);
|
||||
pdu->p = pdu->data;
|
||||
|
||||
return pdu;
|
||||
}
|
||||
|
||||
int transport_receive_pool_return(rdpTransport* transport, STREAM* pdu)
|
||||
{
|
||||
Queue_Enqueue(transport->ReceivePool, pdu);
|
||||
return 0;
|
||||
}
|
||||
|
||||
rdpTransport* transport_new(rdpSettings* settings)
|
||||
{
|
||||
rdpTransport* transport;
|
||||
|
@ -774,13 +762,12 @@ rdpTransport* transport_new(rdpSettings* settings)
|
|||
/* a small 0.1ms delay when transport is blocking. */
|
||||
transport->SleepInterval = 100;
|
||||
|
||||
transport->ReceivePool = Queue_New(TRUE, -1, -1);
|
||||
transport->ReceiveQueue = Queue_New(TRUE, -1, -1);
|
||||
Queue_Object(transport->ReceivePool)->fnObjectFree = (OBJECT_FREE_FN) stream_free;
|
||||
Queue_Object(transport->ReceiveQueue)->fnObjectFree = (OBJECT_FREE_FN) stream_free;
|
||||
transport->ReceivePool = ObjectPool_New(TRUE);
|
||||
ObjectPool_Object(transport->ReceivePool)->fnObjectFree = (OBJECT_FREE_FN) stream_free;
|
||||
ObjectPool_Object(transport->ReceivePool)->fnObjectNew = (OBJECT_NEW_FN) transport_receive_buffer_pool_new;
|
||||
|
||||
/* receive buffer for non-blocking read. */
|
||||
transport->ReceiveBuffer = transport_receive_pool_take(transport);
|
||||
transport->ReceiveBuffer = ObjectPool_Take(transport->ReceivePool);
|
||||
transport->ReceiveEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
|
||||
/* buffers for blocking read/write */
|
||||
|
@ -800,7 +787,9 @@ void transport_free(rdpTransport* transport)
|
|||
if (transport != NULL)
|
||||
{
|
||||
if (transport->ReceiveBuffer)
|
||||
stream_free(transport->ReceiveBuffer);
|
||||
ObjectPool_Return(transport->ReceivePool, transport->ReceiveBuffer);
|
||||
|
||||
ObjectPool_Free(transport->ReceivePool);
|
||||
|
||||
stream_free(transport->ReceiveStream);
|
||||
stream_free(transport->SendStream);
|
||||
|
@ -819,9 +808,6 @@ void transport_free(rdpTransport* transport)
|
|||
|
||||
tsg_free(transport->tsg);
|
||||
|
||||
Queue_Free(transport->ReceivePool);
|
||||
Queue_Free(transport->ReceiveQueue);
|
||||
|
||||
free(transport);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -66,9 +66,7 @@ struct rdp_transport
|
|||
HANDLE ReceiveEvent;
|
||||
BOOL blocking;
|
||||
BOOL SplitInputOutput;
|
||||
|
||||
wQueue* ReceivePool;
|
||||
wQueue* ReceiveQueue;
|
||||
wObjectPool* ReceivePool;
|
||||
};
|
||||
|
||||
STREAM* transport_recv_stream_init(rdpTransport* transport, int size);
|
||||
|
|
|
@ -109,6 +109,8 @@ BOOL tls_connect(rdpTls* tls)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
//SSL_CTX_set_mode(tls->ctx, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER | SSL_MODE_ENABLE_PARTIAL_WRITE);
|
||||
|
||||
/**
|
||||
* SSL_OP_NO_COMPRESSION:
|
||||
*
|
||||
|
@ -390,8 +392,7 @@ int tls_write(rdpTls* tls, BYTE* data, int length)
|
|||
{
|
||||
error = SSL_get_error(tls->ssl, status);
|
||||
|
||||
//printf("tls_write: length: %d status: %d error: 0x%08X\n",
|
||||
// length, status, error);
|
||||
//printf("tls_write: length: %d status: %d error: 0x%08X\n", length, status, error);
|
||||
|
||||
switch (error)
|
||||
{
|
||||
|
|
|
@ -49,7 +49,7 @@ if(WITH_SSE2)
|
|||
endif()
|
||||
elseif(WITH_NEON)
|
||||
if(CMAKE_COMPILER_IS_GNUCC)
|
||||
set(OPTIMIZATION "${OPTIMIZATION} -mfpu=neon -mfloat-abi=softfp")
|
||||
set(OPTIMIZATION "${OPTIMIZATION} -mfpu=neon -mfloat-abi=${ARM_FP_ABI}")
|
||||
endif()
|
||||
# TODO: Add MSVC equivalent
|
||||
endif()
|
||||
|
|
|
@ -85,7 +85,7 @@ if(WITH_SSE2)
|
|||
endif()
|
||||
elseif(WITH_NEON)
|
||||
if(CMAKE_COMPILER_IS_GNUCC)
|
||||
set(OPTIMZATION "${OPTFLAGS} -mfpu=neon -mfloat-abi=softfp -O2")
|
||||
set(OPTIMZATION "${OPTFLAGS} -mfpu=neon -mfloat-abi=${ARM_FP_ABI} -O2")
|
||||
endif()
|
||||
# TODO: Add MSVC equivalent
|
||||
endif()
|
||||
|
|
|
@ -60,15 +60,15 @@ void mf_peer_audin_init(mfPeerContext* context)
|
|||
{
|
||||
context->audin = audin_server_context_new(context->vcm);
|
||||
context->audin->data = context;
|
||||
|
||||
|
||||
context->audin->server_formats = audio_formats;
|
||||
context->audin->num_server_formats = sizeof(audio_formats) / sizeof(audio_formats[0]);
|
||||
|
||||
|
||||
context->audin->dst_format.wFormatTag = 1;
|
||||
context->audin->dst_format.nChannels = 2;
|
||||
context->audin->dst_format.nSamplesPerSec = 44100;
|
||||
context->audin->dst_format.wBitsPerSample = 16;
|
||||
|
||||
|
||||
context->audin->Opening = mf_peer_audin_opening;
|
||||
context->audin->OpenResult = mf_peer_audin_open_result;
|
||||
context->audin->ReceiveSamples = mf_peer_audin_receive_samples;
|
||||
|
|
|
@ -35,21 +35,21 @@ int mf_is_event_set(mfEventQueue* event_queue)
|
|||
fd_set rfds;
|
||||
int num_set;
|
||||
struct timeval time;
|
||||
|
||||
|
||||
FD_ZERO(&rfds);
|
||||
FD_SET(event_queue->pipe_fd[0], &rfds);
|
||||
memset(&time, 0, sizeof(time));
|
||||
num_set = select(event_queue->pipe_fd[0] + 1, &rfds, 0, 0, &time);
|
||||
|
||||
|
||||
return (num_set == 1);
|
||||
}
|
||||
|
||||
void mf_signal_event(mfEventQueue* event_queue)
|
||||
{
|
||||
int length;
|
||||
|
||||
|
||||
length = write(event_queue->pipe_fd[1], "sig", 4);
|
||||
|
||||
|
||||
if (length != 4)
|
||||
printf("mf_signal_event: error\n");
|
||||
}
|
||||
|
@ -57,9 +57,9 @@ void mf_signal_event(mfEventQueue* event_queue)
|
|||
void mf_set_event(mfEventQueue* event_queue)
|
||||
{
|
||||
int length;
|
||||
|
||||
|
||||
length = write(event_queue->pipe_fd[1], "sig", 4);
|
||||
|
||||
|
||||
if (length != 4)
|
||||
printf("mf_set_event: error\n");
|
||||
}
|
||||
|
@ -67,11 +67,11 @@ void mf_set_event(mfEventQueue* event_queue)
|
|||
void mf_clear_events(mfEventQueue* event_queue)
|
||||
{
|
||||
int length;
|
||||
|
||||
|
||||
while (mf_is_event_set(event_queue))
|
||||
{
|
||||
length = read(event_queue->pipe_fd[0], &length, 4);
|
||||
|
||||
|
||||
if (length != 4)
|
||||
printf("mf_clear_event: error\n");
|
||||
}
|
||||
|
@ -80,9 +80,9 @@ void mf_clear_events(mfEventQueue* event_queue)
|
|||
void mf_clear_event(mfEventQueue* event_queue)
|
||||
{
|
||||
int length;
|
||||
|
||||
|
||||
length = read(event_queue->pipe_fd[0], &length, 4);
|
||||
|
||||
|
||||
if (length != 4)
|
||||
printf("mf_clear_event: error\n");
|
||||
}
|
||||
|
@ -90,62 +90,62 @@ void mf_clear_event(mfEventQueue* event_queue)
|
|||
void mf_event_push(mfEventQueue* event_queue, mfEvent* event)
|
||||
{
|
||||
pthread_mutex_lock(&(event_queue->mutex));
|
||||
|
||||
|
||||
if (event_queue->count >= event_queue->size)
|
||||
{
|
||||
event_queue->size *= 2;
|
||||
event_queue->events = (mfEvent**) realloc((void*) event_queue->events, sizeof(mfEvent*) * event_queue->size);
|
||||
}
|
||||
|
||||
|
||||
event_queue->events[(event_queue->count)++] = event;
|
||||
|
||||
|
||||
pthread_mutex_unlock(&(event_queue->mutex));
|
||||
|
||||
|
||||
mf_set_event(event_queue);
|
||||
}
|
||||
|
||||
mfEvent* mf_event_peek(mfEventQueue* event_queue)
|
||||
{
|
||||
mfEvent* event;
|
||||
|
||||
|
||||
pthread_mutex_lock(&(event_queue->mutex));
|
||||
|
||||
|
||||
if (event_queue->count < 1)
|
||||
event = NULL;
|
||||
else
|
||||
event = event_queue->events[0];
|
||||
|
||||
|
||||
pthread_mutex_unlock(&(event_queue->mutex));
|
||||
|
||||
|
||||
return event;
|
||||
}
|
||||
|
||||
mfEvent* mf_event_pop(mfEventQueue* event_queue)
|
||||
{
|
||||
mfEvent* event;
|
||||
|
||||
|
||||
pthread_mutex_lock(&(event_queue->mutex));
|
||||
|
||||
|
||||
if (event_queue->count < 1)
|
||||
return NULL;
|
||||
|
||||
|
||||
/* remove event signal */
|
||||
mf_clear_event(event_queue);
|
||||
|
||||
|
||||
event = event_queue->events[0];
|
||||
(event_queue->count)--;
|
||||
|
||||
|
||||
memmove(&event_queue->events[0], &event_queue->events[1], event_queue->count * sizeof(void*));
|
||||
|
||||
|
||||
pthread_mutex_unlock(&(event_queue->mutex));
|
||||
|
||||
|
||||
return event;
|
||||
}
|
||||
|
||||
mfEventRegion* mf_event_region_new(int x, int y, int width, int height)
|
||||
{
|
||||
mfEventRegion* event_region = malloc(sizeof(mfEventRegion));
|
||||
|
||||
|
||||
if (event_region != NULL)
|
||||
{
|
||||
event_region->x = x;
|
||||
|
@ -153,7 +153,7 @@ mfEventRegion* mf_event_region_new(int x, int y, int width, int height)
|
|||
event_region->width = width;
|
||||
event_region->height = height;
|
||||
}
|
||||
|
||||
|
||||
return event_region;
|
||||
}
|
||||
|
||||
|
@ -177,22 +177,22 @@ void mf_event_free(mfEvent* event)
|
|||
mfEventQueue* mf_event_queue_new()
|
||||
{
|
||||
mfEventQueue* event_queue = malloc(sizeof(mfEventQueue));
|
||||
|
||||
|
||||
if (event_queue != NULL)
|
||||
{
|
||||
event_queue->pipe_fd[0] = -1;
|
||||
event_queue->pipe_fd[1] = -1;
|
||||
|
||||
|
||||
event_queue->size = 16;
|
||||
event_queue->count = 0;
|
||||
event_queue->events = (mfEvent**) malloc(sizeof(mfEvent*) * event_queue->size);
|
||||
|
||||
|
||||
if (pipe(event_queue->pipe_fd) < 0)
|
||||
printf("mf_event_queue_new: pipe failed\n");
|
||||
|
||||
|
||||
pthread_mutex_init(&(event_queue->mutex), NULL);
|
||||
}
|
||||
|
||||
|
||||
return event_queue;
|
||||
}
|
||||
|
||||
|
@ -203,12 +203,12 @@ void mf_event_queue_free(mfEventQueue* event_queue)
|
|||
close(event_queue->pipe_fd[0]);
|
||||
event_queue->pipe_fd[0] = -1;
|
||||
}
|
||||
|
||||
|
||||
if (event_queue->pipe_fd[1] != -1)
|
||||
{
|
||||
close(event_queue->pipe_fd[1]);
|
||||
event_queue->pipe_fd[1] = -1;
|
||||
}
|
||||
|
||||
|
||||
pthread_mutex_destroy(&(event_queue->mutex));
|
||||
}
|
|
@ -52,7 +52,7 @@ struct mf_event_queue
|
|||
struct mf_event_region
|
||||
{
|
||||
int type;
|
||||
|
||||
|
||||
int x;
|
||||
int y;
|
||||
int width;
|
||||
|
|
|
@ -1,21 +1,21 @@
|
|||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Client
|
||||
* FreeRDP Mac OS X Server
|
||||
*
|
||||
* Copyright 2012 Corey Clayton <can.of.tuna@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.
|
||||
*/
|
||||
* FreeRDP: A Remote Desktop Protocol Client
|
||||
* FreeRDP Mac OS X Server
|
||||
*
|
||||
* Copyright 2012 Corey Clayton <can.of.tuna@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
|
||||
|
@ -34,116 +34,116 @@ static mfInfo* mfInfoInstance = NULL;
|
|||
|
||||
int mf_info_lock(mfInfo* mfi)
|
||||
{
|
||||
|
||||
int status = pthread_mutex_lock(&mfi->mutex);
|
||||
|
||||
switch (status) {
|
||||
case 0:
|
||||
return TRUE;
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("mf_info_lock failed with %#X\n", status);
|
||||
return -1;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
int status = pthread_mutex_lock(&mfi->mutex);
|
||||
|
||||
switch (status) {
|
||||
case 0:
|
||||
return TRUE;
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("mf_info_lock failed with %#X\n", status);
|
||||
return -1;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int mf_info_try_lock(mfInfo* mfi, UINT32 ms)
|
||||
{
|
||||
|
||||
int status = pthread_mutex_trylock(&mfi->mutex);
|
||||
|
||||
switch (status) {
|
||||
case 0:
|
||||
return TRUE;
|
||||
break;
|
||||
|
||||
case EBUSY:
|
||||
return FALSE;
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("mf_info_try_lock failed with %#X\n", status);
|
||||
return -1;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
int status = pthread_mutex_trylock(&mfi->mutex);
|
||||
|
||||
switch (status) {
|
||||
case 0:
|
||||
return TRUE;
|
||||
break;
|
||||
|
||||
case EBUSY:
|
||||
return FALSE;
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("mf_info_try_lock failed with %#X\n", status);
|
||||
return -1;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int mf_info_unlock(mfInfo* mfi)
|
||||
{
|
||||
int status = pthread_mutex_unlock(&mfi->mutex);
|
||||
|
||||
switch (status) {
|
||||
case 0:
|
||||
return TRUE;
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("mf_info_unlock failed with %#X\n", status);
|
||||
return -1;
|
||||
break;
|
||||
}
|
||||
|
||||
int status = pthread_mutex_unlock(&mfi->mutex);
|
||||
|
||||
switch (status) {
|
||||
case 0:
|
||||
return TRUE;
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("mf_info_unlock failed with %#X\n", status);
|
||||
return -1;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
mfInfo* mf_info_init()
|
||||
{
|
||||
mfInfo* mfi;
|
||||
|
||||
mfi = (mfInfo*) malloc(sizeof(mfInfo));
|
||||
memset(mfi, 0, sizeof(mfInfo));
|
||||
|
||||
|
||||
mfi = (mfInfo*) malloc(sizeof(mfInfo));
|
||||
memset(mfi, 0, sizeof(mfInfo));
|
||||
|
||||
|
||||
if (mfi != NULL)
|
||||
{
|
||||
/* HKEY hKey;
|
||||
LONG status;
|
||||
DWORD dwType;
|
||||
DWORD dwSize;
|
||||
DWORD dwValue;
|
||||
*/
|
||||
|
||||
int mutexInitStatus = pthread_mutex_init(&mfi->mutex, NULL);
|
||||
|
||||
/* HKEY hKey;
|
||||
LONG status;
|
||||
DWORD dwType;
|
||||
DWORD dwSize;
|
||||
DWORD dwValue;
|
||||
*/
|
||||
|
||||
int mutexInitStatus = pthread_mutex_init(&mfi->mutex, NULL);
|
||||
|
||||
if (mutexInitStatus != 0)
|
||||
{
|
||||
printf(_T("CreateMutex error: %#X\n"), mutexInitStatus);
|
||||
}
|
||||
|
||||
|
||||
mfi->peers = (freerdp_peer**) malloc(sizeof(freerdp_peer*) * MF_INFO_MAXPEERS);
|
||||
memset(mfi->peers, 0, sizeof(freerdp_peer*) * MF_INFO_MAXPEERS);
|
||||
|
||||
|
||||
//Set FPS
|
||||
mfi->framesPerSecond = MF_INFO_DEFAULT_FPS;
|
||||
|
||||
|
||||
/*status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("Software\\FreeRDP\\Server"), 0, KEY_READ | KEY_WOW64_64KEY, &hKey);
|
||||
if (status == ERROR_SUCCESS)
|
||||
{
|
||||
if (RegQueryValueEx(hKey, _T("FramesPerSecond"), NULL, &dwType, (BYTE*) &dwValue, &dwSize) == ERROR_SUCCESS)
|
||||
mfi->framesPerSecond = dwValue;
|
||||
}
|
||||
RegCloseKey(hKey);*/
|
||||
|
||||
if (status == ERROR_SUCCESS)
|
||||
{
|
||||
if (RegQueryValueEx(hKey, _T("FramesPerSecond"), NULL, &dwType, (BYTE*) &dwValue, &dwSize) == ERROR_SUCCESS)
|
||||
mfi->framesPerSecond = dwValue;
|
||||
}
|
||||
RegCloseKey(hKey);*/
|
||||
|
||||
//Set input toggle
|
||||
mfi->input_disabled = FALSE;
|
||||
|
||||
|
||||
/*status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("Software\\FreeRDP\\Server"), 0, KEY_READ | KEY_WOW64_64KEY, &hKey);
|
||||
if (status == ERROR_SUCCESS)
|
||||
{
|
||||
if (RegQueryValueEx(hKey, _T("DisableInput"), NULL, &dwType, (BYTE*) &dwValue, &dwSize) == ERROR_SUCCESS)
|
||||
{
|
||||
if (dwValue != 0)
|
||||
mfi->input_disabled = TRUE;
|
||||
}
|
||||
}
|
||||
RegCloseKey(hKey);*/
|
||||
|
||||
if (status == ERROR_SUCCESS)
|
||||
{
|
||||
if (RegQueryValueEx(hKey, _T("DisableInput"), NULL, &dwType, (BYTE*) &dwValue, &dwSize) == ERROR_SUCCESS)
|
||||
{
|
||||
if (dwValue != 0)
|
||||
mfi->input_disabled = TRUE;
|
||||
}
|
||||
}
|
||||
RegCloseKey(hKey);*/
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
return mfi;
|
||||
}
|
||||
|
||||
|
@ -151,7 +151,7 @@ mfInfo* mf_info_get_instance()
|
|||
{
|
||||
if (mfInfoInstance == NULL)
|
||||
mfInfoInstance = mf_info_init();
|
||||
|
||||
|
||||
return mfInfoInstance;
|
||||
}
|
||||
|
||||
|
@ -163,27 +163,28 @@ void mf_info_peer_register(mfInfo* mfi, mfPeerContext* context)
|
|||
int peerId;
|
||||
if (mfi->peerCount == MF_INFO_MAXPEERS)
|
||||
{
|
||||
printf("TODO: socketClose on OS X\n");
|
||||
printf("TODO: socketClose on OS X\n");
|
||||
//context->socketClose = TRUE;
|
||||
mf_info_unlock(mfi);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
context->info = mfi;
|
||||
|
||||
//get the offset of the top left corner of selected screen
|
||||
//EnumDisplayMonitors(NULL, NULL, mf_info_monEnumCB, 0);
|
||||
//_IDcount = 0;
|
||||
|
||||
//initialize screen capture
|
||||
|
||||
//initialize screen capture
|
||||
if (mfi->peerCount == 0)
|
||||
{
|
||||
mf_mlion_display_info(&mfi->servscreen_width, &mfi->servscreen_height, &mfi->scale);
|
||||
mf_mlion_screen_updates_init();
|
||||
mf_mlion_start_getting_screen_updates();
|
||||
}
|
||||
|
||||
{
|
||||
mf_mlion_display_info(&mfi->servscreen_width, &mfi->servscreen_height, &mfi->scale);
|
||||
mf_mlion_screen_updates_init();
|
||||
mf_mlion_start_getting_screen_updates();
|
||||
}
|
||||
|
||||
//look trhough the array of peers until an empty slot
|
||||
peerId = NULL;
|
||||
for(i=0; i<MF_INFO_MAXPEERS; ++i)
|
||||
{
|
||||
//empty index will be our peer id
|
||||
|
@ -193,14 +194,14 @@ void mf_info_peer_register(mfInfo* mfi, mfPeerContext* context)
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
mfi->peers[peerId] = ((rdpContext*) context)->peer;
|
||||
mfi->peers[peerId]->pId = peerId;
|
||||
mfi->peerCount++;
|
||||
printf("Registering Peer: id=%d #=%d\n", peerId, mfi->peerCount);
|
||||
|
||||
//printf("Registering Peer: id=%d #=%d\n", peerId, mfi->peerCount);
|
||||
|
||||
mf_info_unlock(mfi);
|
||||
|
||||
|
||||
//mfreerdp_server_peer_callback_event(peerId, MF_SRV_CALLBACK_EVENT_CONNECT);
|
||||
}
|
||||
}
|
||||
|
@ -210,20 +211,20 @@ void mf_info_peer_unregister(mfInfo* mfi, mfPeerContext* context)
|
|||
if (mf_info_lock(mfi) > 0)
|
||||
{
|
||||
int peerId;
|
||||
|
||||
|
||||
peerId = ((rdpContext*) context)->peer->pId;
|
||||
mfi->peers[peerId] = NULL;
|
||||
mfi->peerCount--;
|
||||
|
||||
printf("Unregistering Peer: id=%d, #=%d\n", peerId, mfi->peerCount);
|
||||
|
||||
//screen capture cleanup
|
||||
|
||||
//printf("Unregistering Peer: id=%d, #=%d\n", peerId, mfi->peerCount);
|
||||
|
||||
//screen capture cleanup
|
||||
if (mfi->peerCount == 0)
|
||||
{
|
||||
mf_mlion_stop_getting_screen_updates();
|
||||
}
|
||||
{
|
||||
mf_mlion_stop_getting_screen_updates();
|
||||
}
|
||||
mf_info_unlock(mfi);
|
||||
|
||||
|
||||
//mfreerdp_server_peer_callback_event(peerId, MF_SRV_CALLBACK_EVENT_DISCONNECT);
|
||||
}
|
||||
}
|
||||
|
@ -232,77 +233,77 @@ BOOL mf_info_have_updates(mfInfo* mfi)
|
|||
{
|
||||
if(mfi->framesWaiting == 0)
|
||||
return FALSE;
|
||||
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void mf_info_update_changes(mfInfo* mfi)
|
||||
{
|
||||
/*#ifdef WITH_WIN8
|
||||
mf_dxgi_nextFrame(mfi, mfi->framesPerSecond * 1000);
|
||||
#else
|
||||
GETCHANGESBUF* buf;
|
||||
|
||||
buf = (GETCHANGESBUF*) mfi->changeBuffer;
|
||||
mfi->nextUpdate = buf->buffer->counter;
|
||||
#endif*/
|
||||
/*#ifdef WITH_WIN8
|
||||
mf_dxgi_nextFrame(mfi, mfi->framesPerSecond * 1000);
|
||||
#else
|
||||
GETCHANGESBUF* buf;
|
||||
|
||||
buf = (GETCHANGESBUF*) mfi->changeBuffer;
|
||||
mfi->nextUpdate = buf->buffer->counter;
|
||||
#endif*/
|
||||
}
|
||||
|
||||
void mf_info_find_invalid_region(mfInfo* mfi)
|
||||
{
|
||||
mf_mlion_get_dirty_region(&mfi->invalid);
|
||||
mf_mlion_get_dirty_region(&mfi->invalid);
|
||||
}
|
||||
|
||||
void mf_info_clear_invalid_region(mfInfo* mfi)
|
||||
{
|
||||
mf_mlion_clear_dirty_region();
|
||||
mfi->invalid.height = 0;
|
||||
mfi->invalid.width = 0;
|
||||
mf_mlion_clear_dirty_region();
|
||||
mfi->invalid.height = 0;
|
||||
mfi->invalid.width = 0;
|
||||
}
|
||||
|
||||
void mf_info_invalidate_full_screen(mfInfo* mfi)
|
||||
{
|
||||
mfi->invalid.x = 0;
|
||||
mfi->invalid.y = 0;
|
||||
mfi->invalid.height = mfi->servscreen_height;
|
||||
mfi->invalid.height = mfi->servscreen_width;
|
||||
mfi->invalid.x = 0;
|
||||
mfi->invalid.y = 0;
|
||||
mfi->invalid.height = mfi->servscreen_height;
|
||||
mfi->invalid.height = mfi->servscreen_width;
|
||||
}
|
||||
|
||||
BOOL mf_info_have_invalid_region(mfInfo* mfi)
|
||||
{
|
||||
if (mfi->invalid.width * mfi->invalid.height == 0) {
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
if (mfi->invalid.width * mfi->invalid.height == 0) {
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void mf_info_getScreenData(mfInfo* mfi, long* width, long* height, BYTE** pBits, int* pitch)
|
||||
{
|
||||
*width = mfi->invalid.width / mfi->scale;
|
||||
*height = mfi->invalid.height / mfi->scale;
|
||||
*pitch = mfi->servscreen_width * mfi->scale * 4;
|
||||
|
||||
mf_mlion_get_pixelData(mfi->invalid.x / mfi->scale, mfi->invalid.y / mfi->scale, *width, *height, pBits);
|
||||
|
||||
*pBits = *pBits + (mfi->invalid.x * 4) + (*pitch * mfi->invalid.y);
|
||||
|
||||
*width = mfi->invalid.width / mfi->scale;
|
||||
*height = mfi->invalid.height / mfi->scale;
|
||||
*pitch = mfi->servscreen_width * mfi->scale * 4;
|
||||
|
||||
mf_mlion_get_pixelData(mfi->invalid.x / mfi->scale, mfi->invalid.y / mfi->scale, *width, *height, pBits);
|
||||
|
||||
*pBits = *pBits + (mfi->invalid.x * 4) + (*pitch * mfi->invalid.y);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
BOOL CALLBACK mf_info_monEnumCB(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData)
|
||||
{
|
||||
mfInfo * mfi;
|
||||
|
||||
mfi = mf_info_get_instance();
|
||||
|
||||
if(_IDcount == mfi->screenID)
|
||||
{
|
||||
mfi->servscreen_xoffset = lprcMonitor->left;
|
||||
mfi->servscreen_yoffset = lprcMonitor->top;
|
||||
}
|
||||
|
||||
_IDcount++;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
*/
|
||||
BOOL CALLBACK mf_info_monEnumCB(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData)
|
||||
{
|
||||
mfInfo * mfi;
|
||||
|
||||
mfi = mf_info_get_instance();
|
||||
|
||||
if(_IDcount == mfi->screenID)
|
||||
{
|
||||
mfi->servscreen_xoffset = lprcMonitor->left;
|
||||
mfi->servscreen_yoffset = lprcMonitor->top;
|
||||
}
|
||||
|
||||
_IDcount++;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
*/
|
||||
|
|
|
@ -48,32 +48,32 @@ typedef struct mf_peer_context mfPeerContext;
|
|||
struct mf_peer_context
|
||||
{
|
||||
rdpContext _p;
|
||||
|
||||
mfInfo* info;
|
||||
|
||||
mfInfo* info;
|
||||
STREAM* s;
|
||||
BOOL activated;
|
||||
UINT32 frame_id;
|
||||
BOOL audin_open;
|
||||
RFX_CONTEXT* rfx_context;
|
||||
NSC_CONTEXT* nsc_context;
|
||||
|
||||
//#ifdef WITH_SERVER_CHANNELS
|
||||
|
||||
//#ifdef WITH_SERVER_CHANNELS
|
||||
WTSVirtualChannelManager* vcm;
|
||||
//#endif
|
||||
//#ifdef CHANNEL_AUDIN_SERVER
|
||||
//#endif
|
||||
//#ifdef CHANNEL_AUDIN_SERVER
|
||||
audin_server_context* audin;
|
||||
//#endif
|
||||
|
||||
//#ifdef CHANNEL_RDPSND_SERVER
|
||||
//#endif
|
||||
|
||||
//#ifdef CHANNEL_RDPSND_SERVER
|
||||
rdpsnd_server_context* rdpsnd;
|
||||
//#endif
|
||||
//#endif
|
||||
};
|
||||
|
||||
|
||||
struct mf_info
|
||||
{
|
||||
//STREAM* s;
|
||||
|
||||
|
||||
//screen and monitor info
|
||||
UINT32 screenID;
|
||||
UINT32 virtscreen_width;
|
||||
|
@ -82,7 +82,7 @@ struct mf_info
|
|||
UINT32 servscreen_height;
|
||||
UINT32 servscreen_xoffset;
|
||||
UINT32 servscreen_yoffset;
|
||||
|
||||
|
||||
//int frame_idx;
|
||||
int bitsPerPixel;
|
||||
//HDC driverDC;
|
||||
|
@ -95,11 +95,11 @@ struct mf_info
|
|||
freerdp_peer** peers;
|
||||
//BOOL mirrorDriverActive;
|
||||
unsigned int framesWaiting;
|
||||
UINT32 scale;
|
||||
|
||||
UINT32 scale;
|
||||
|
||||
//HANDLE snd_mutex;
|
||||
//BOOL snd_stop;
|
||||
|
||||
|
||||
RFX_RECT invalid;
|
||||
pthread_mutex_t mutex;
|
||||
//BOOL updatePending;
|
||||
|
@ -110,7 +110,7 @@ struct mf_info
|
|||
//unsigned long lastUpdate;
|
||||
//unsigned long nextUpdate;
|
||||
//SURFACE_BITS_COMMAND cmd;
|
||||
|
||||
|
||||
BOOL input_disabled;
|
||||
BOOL force_all_disconnect;
|
||||
};
|
||||
|
|
|
@ -34,273 +34,241 @@ CGDisplayStreamUpdateRef lastUpdate = NULL;
|
|||
|
||||
BYTE* localBuf = NULL;
|
||||
|
||||
//CVPixelBufferRef pxbuffer = NULL;
|
||||
//void *baseAddress = NULL;
|
||||
|
||||
//CGContextRef bitmapcontext = NULL;
|
||||
|
||||
//CGImageRef image = NULL;
|
||||
|
||||
BOOL ready = FALSE;
|
||||
|
||||
void (^streamHandler)(CGDisplayStreamFrameStatus, uint64_t, IOSurfaceRef, CGDisplayStreamUpdateRef) = ^(CGDisplayStreamFrameStatus status, uint64_t displayTime, IOSurfaceRef frameSurface, CGDisplayStreamUpdateRef updateRef)
|
||||
{
|
||||
|
||||
dispatch_semaphore_wait(region_sem, DISPATCH_TIME_FOREVER);
|
||||
|
||||
//may need to move this down
|
||||
if(ready == TRUE)
|
||||
{
|
||||
|
||||
RFX_RECT rect;
|
||||
unsigned long offset_beg;
|
||||
unsigned long stride;
|
||||
|
||||
rect.x = 0;
|
||||
rect.y = 0;
|
||||
rect.width = 0;
|
||||
rect.height = 0;
|
||||
mf_mlion_peek_dirty_region(&rect);
|
||||
|
||||
|
||||
//lock surface
|
||||
IOSurfaceLock(frameSurface, kIOSurfaceLockReadOnly, NULL);
|
||||
//get pointer
|
||||
void* baseAddress = IOSurfaceGetBaseAddress(frameSurface);
|
||||
//copy region
|
||||
|
||||
stride = IOSurfaceGetBytesPerRow(frameSurface);
|
||||
//memcpy(localBuf, baseAddress + offset_beg, surflen);
|
||||
for(int i = 0; i < rect.height; i++)
|
||||
{
|
||||
offset_beg = (stride * (rect.y + i) + (rect.x * 4));
|
||||
memcpy(localBuf + offset_beg,
|
||||
baseAddress + offset_beg,
|
||||
rect.width * 4);
|
||||
}
|
||||
|
||||
//unlock surface
|
||||
IOSurfaceUnlock(frameSurface, kIOSurfaceLockReadOnly, NULL);
|
||||
|
||||
ready = FALSE;
|
||||
dispatch_semaphore_signal(data_sem);
|
||||
}
|
||||
|
||||
if (status != kCGDisplayStreamFrameStatusFrameComplete)
|
||||
{
|
||||
//unhandled
|
||||
switch(status)
|
||||
{
|
||||
case kCGDisplayStreamFrameStatusFrameIdle:
|
||||
printf("kCGDisplayStreamFrameStatusFrameIdle\n");
|
||||
break;
|
||||
|
||||
case kCGDisplayStreamFrameStatusStopped:
|
||||
printf("kCGDisplayStreamFrameStatusStopped\n");
|
||||
break;
|
||||
|
||||
case kCGDisplayStreamFrameStatusFrameBlank:
|
||||
printf("kCGDisplayStreamFrameStatusFrameBlank\n");
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("Unhandled Frame Status!!!\n");
|
||||
|
||||
}
|
||||
}
|
||||
else if (lastUpdate == NULL)
|
||||
{
|
||||
CFRetain(updateRef);
|
||||
lastUpdate = updateRef;
|
||||
}
|
||||
else
|
||||
{
|
||||
CGDisplayStreamUpdateRef tmpRef;
|
||||
tmpRef = lastUpdate;
|
||||
lastUpdate = CGDisplayStreamUpdateCreateMergedUpdate(tmpRef, updateRef);
|
||||
CFRelease(tmpRef);
|
||||
}
|
||||
|
||||
dispatch_semaphore_signal(region_sem);
|
||||
|
||||
dispatch_semaphore_wait(region_sem, DISPATCH_TIME_FOREVER);
|
||||
|
||||
//may need to move this down
|
||||
if(ready == TRUE)
|
||||
{
|
||||
|
||||
RFX_RECT rect;
|
||||
unsigned long offset_beg;
|
||||
unsigned long stride;
|
||||
|
||||
rect.x = 0;
|
||||
rect.y = 0;
|
||||
rect.width = 0;
|
||||
rect.height = 0;
|
||||
mf_mlion_peek_dirty_region(&rect);
|
||||
|
||||
|
||||
//lock surface
|
||||
IOSurfaceLock(frameSurface, kIOSurfaceLockReadOnly, NULL);
|
||||
//get pointer
|
||||
void* baseAddress = IOSurfaceGetBaseAddress(frameSurface);
|
||||
//copy region
|
||||
|
||||
stride = IOSurfaceGetBytesPerRow(frameSurface);
|
||||
//memcpy(localBuf, baseAddress + offset_beg, surflen);
|
||||
for(int i = 0; i < rect.height; i++)
|
||||
{
|
||||
offset_beg = (stride * (rect.y + i) + (rect.x * 4));
|
||||
memcpy(localBuf + offset_beg,
|
||||
baseAddress + offset_beg,
|
||||
rect.width * 4);
|
||||
}
|
||||
|
||||
//unlock surface
|
||||
IOSurfaceUnlock(frameSurface, kIOSurfaceLockReadOnly, NULL);
|
||||
|
||||
ready = FALSE;
|
||||
dispatch_semaphore_signal(data_sem);
|
||||
}
|
||||
|
||||
if (status != kCGDisplayStreamFrameStatusFrameComplete)
|
||||
{
|
||||
//unhandled
|
||||
switch(status)
|
||||
{
|
||||
case kCGDisplayStreamFrameStatusFrameIdle:
|
||||
printf("kCGDisplayStreamFrameStatusFrameIdle\n");
|
||||
break;
|
||||
|
||||
case kCGDisplayStreamFrameStatusStopped:
|
||||
//we dont need to clean up
|
||||
//printf("kCGDisplayStreamFrameStatusStopped\n");
|
||||
break;
|
||||
|
||||
case kCGDisplayStreamFrameStatusFrameBlank:
|
||||
printf("kCGDisplayStreamFrameStatusFrameBlank\n");
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("Unhandled Frame Status!!!\n");
|
||||
|
||||
}
|
||||
}
|
||||
else if (lastUpdate == NULL)
|
||||
{
|
||||
CFRetain(updateRef);
|
||||
lastUpdate = updateRef;
|
||||
}
|
||||
else
|
||||
{
|
||||
CGDisplayStreamUpdateRef tmpRef;
|
||||
tmpRef = lastUpdate;
|
||||
lastUpdate = CGDisplayStreamUpdateCreateMergedUpdate(tmpRef, updateRef);
|
||||
CFRelease(tmpRef);
|
||||
}
|
||||
|
||||
dispatch_semaphore_signal(region_sem);
|
||||
};
|
||||
|
||||
int mf_mlion_display_info(UINT32* disp_width, UINT32* disp_height, UINT32* scale)
|
||||
{
|
||||
CGDirectDisplayID display_id;
|
||||
|
||||
display_id = CGMainDisplayID();
|
||||
|
||||
CGDisplayModeRef mode = CGDisplayCopyDisplayMode(display_id);
|
||||
|
||||
size_t pixelWidth = CGDisplayModeGetPixelWidth(mode);
|
||||
//size_t pixelHeight = CGDisplayModeGetPixelHeight(mode);
|
||||
|
||||
size_t wide = CGDisplayPixelsWide(display_id);
|
||||
size_t high = CGDisplayPixelsHigh(display_id);
|
||||
|
||||
CGDisplayModeRelease(mode);
|
||||
|
||||
*disp_width = wide;//pixelWidth;
|
||||
*disp_height = high;//pixelHeight;
|
||||
*scale = pixelWidth / wide;
|
||||
|
||||
return 0;
|
||||
CGDirectDisplayID display_id;
|
||||
|
||||
display_id = CGMainDisplayID();
|
||||
|
||||
CGDisplayModeRef mode = CGDisplayCopyDisplayMode(display_id);
|
||||
|
||||
size_t pixelWidth = CGDisplayModeGetPixelWidth(mode);
|
||||
//size_t pixelHeight = CGDisplayModeGetPixelHeight(mode);
|
||||
|
||||
size_t wide = CGDisplayPixelsWide(display_id);
|
||||
size_t high = CGDisplayPixelsHigh(display_id);
|
||||
|
||||
CGDisplayModeRelease(mode);
|
||||
|
||||
*disp_width = wide;//pixelWidth;
|
||||
*disp_height = high;//pixelHeight;
|
||||
*scale = pixelWidth / wide;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mf_mlion_screen_updates_init()
|
||||
{
|
||||
printf("mf_mlion_screen_updates_init()\n");
|
||||
CGDirectDisplayID display_id;
|
||||
|
||||
display_id = CGMainDisplayID();
|
||||
|
||||
screen_update_q = dispatch_queue_create("mfreerdp.server.screenUpdate", NULL);
|
||||
|
||||
region_sem = dispatch_semaphore_create(1);
|
||||
data_sem = dispatch_semaphore_create(1);
|
||||
|
||||
UINT32 pixelWidth;
|
||||
UINT32 pixelHeight;
|
||||
UINT32 scale;
|
||||
|
||||
mf_mlion_display_info(&pixelWidth, &pixelHeight, &scale);
|
||||
|
||||
localBuf = malloc(pixelWidth * pixelHeight * 4);
|
||||
|
||||
|
||||
stream = CGDisplayStreamCreateWithDispatchQueue(display_id,
|
||||
pixelWidth,
|
||||
pixelHeight,
|
||||
'BGRA',
|
||||
NULL,
|
||||
screen_update_q,
|
||||
streamHandler);
|
||||
|
||||
|
||||
return 0;
|
||||
|
||||
CGDirectDisplayID display_id;
|
||||
|
||||
display_id = CGMainDisplayID();
|
||||
|
||||
screen_update_q = dispatch_queue_create("mfreerdp.server.screenUpdate", NULL);
|
||||
|
||||
region_sem = dispatch_semaphore_create(1);
|
||||
data_sem = dispatch_semaphore_create(1);
|
||||
|
||||
UINT32 pixelWidth;
|
||||
UINT32 pixelHeight;
|
||||
UINT32 scale;
|
||||
|
||||
mf_mlion_display_info(&pixelWidth, &pixelHeight, &scale);
|
||||
|
||||
localBuf = malloc(pixelWidth * pixelHeight * 4);
|
||||
|
||||
|
||||
stream = CGDisplayStreamCreateWithDispatchQueue(display_id,
|
||||
pixelWidth,
|
||||
pixelHeight,
|
||||
'BGRA',
|
||||
NULL,
|
||||
screen_update_q,
|
||||
streamHandler);
|
||||
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int mf_mlion_start_getting_screen_updates()
|
||||
{
|
||||
CGError err;
|
||||
|
||||
err = CGDisplayStreamStart(stream);
|
||||
if(err != kCGErrorSuccess)
|
||||
{
|
||||
printf("Failed to start displaystream!! err = %d\n", err);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
CGError err;
|
||||
|
||||
err = CGDisplayStreamStart(stream);
|
||||
if(err != kCGErrorSuccess)
|
||||
{
|
||||
printf("Failed to start displaystream!! err = %d\n", err);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
int mf_mlion_stop_getting_screen_updates()
|
||||
{
|
||||
CGError err;
|
||||
|
||||
err = CGDisplayStreamStop(stream);
|
||||
if(err != kCGErrorSuccess)
|
||||
{
|
||||
printf("Failed to stop displaystream!! err = %d\n", err);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
return 0;
|
||||
CGError err;
|
||||
|
||||
err = CGDisplayStreamStop(stream);
|
||||
if(err != kCGErrorSuccess)
|
||||
{
|
||||
printf("Failed to stop displaystream!! err = %d\n", err);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mf_mlion_get_dirty_region(RFX_RECT* invalid)
|
||||
{
|
||||
dispatch_semaphore_wait(region_sem, DISPATCH_TIME_FOREVER);
|
||||
|
||||
if (lastUpdate != NULL)
|
||||
{
|
||||
mf_mlion_peek_dirty_region(invalid);
|
||||
|
||||
//CFRelease(lastUpdate);
|
||||
|
||||
//lastUpdate = NULL;
|
||||
|
||||
}
|
||||
|
||||
|
||||
dispatch_semaphore_signal(region_sem);
|
||||
|
||||
return 0;
|
||||
dispatch_semaphore_wait(region_sem, DISPATCH_TIME_FOREVER);
|
||||
|
||||
if (lastUpdate != NULL)
|
||||
{
|
||||
mf_mlion_peek_dirty_region(invalid);
|
||||
}
|
||||
|
||||
|
||||
dispatch_semaphore_signal(region_sem);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mf_mlion_peek_dirty_region(RFX_RECT* invalid)
|
||||
{
|
||||
size_t num_rects;
|
||||
CGRect dirtyRegion;
|
||||
|
||||
const CGRect * rects = CGDisplayStreamUpdateGetRects(lastUpdate, kCGDisplayStreamUpdateDirtyRects, &num_rects);
|
||||
|
||||
//printf("\trectangles: %zd\n", num_rects);
|
||||
|
||||
if (num_rects == 0) {
|
||||
//dispatch_semaphore_signal(region_sem);
|
||||
return 0;
|
||||
}
|
||||
|
||||
dirtyRegion = *rects;
|
||||
for (size_t i = 0; i < num_rects; i++)
|
||||
{
|
||||
dirtyRegion = CGRectUnion(dirtyRegion, *(rects+i));
|
||||
}
|
||||
|
||||
invalid->x = dirtyRegion.origin.x;
|
||||
invalid->y = dirtyRegion.origin.y;
|
||||
invalid->height = dirtyRegion.size.height;
|
||||
invalid->width = dirtyRegion.size.width;
|
||||
|
||||
return 0;
|
||||
size_t num_rects;
|
||||
CGRect dirtyRegion;
|
||||
|
||||
const CGRect * rects = CGDisplayStreamUpdateGetRects(lastUpdate, kCGDisplayStreamUpdateDirtyRects, &num_rects);
|
||||
|
||||
if (num_rects == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
dirtyRegion = *rects;
|
||||
for (size_t i = 0; i < num_rects; i++)
|
||||
{
|
||||
dirtyRegion = CGRectUnion(dirtyRegion, *(rects+i));
|
||||
}
|
||||
|
||||
invalid->x = dirtyRegion.origin.x;
|
||||
invalid->y = dirtyRegion.origin.y;
|
||||
invalid->height = dirtyRegion.size.height;
|
||||
invalid->width = dirtyRegion.size.width;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mf_mlion_clear_dirty_region()
|
||||
{
|
||||
dispatch_semaphore_wait(region_sem, DISPATCH_TIME_FOREVER);
|
||||
|
||||
CFRelease(lastUpdate);
|
||||
lastUpdate = NULL;
|
||||
|
||||
dispatch_semaphore_signal(region_sem);
|
||||
|
||||
|
||||
return 0;
|
||||
dispatch_semaphore_wait(region_sem, DISPATCH_TIME_FOREVER);
|
||||
|
||||
CFRelease(lastUpdate);
|
||||
lastUpdate = NULL;
|
||||
|
||||
dispatch_semaphore_signal(region_sem);
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mf_mlion_get_pixelData(long x, long y, long width, long height, BYTE** pxData)
|
||||
{
|
||||
dispatch_semaphore_wait(region_sem, DISPATCH_TIME_FOREVER);
|
||||
ready = TRUE;
|
||||
dispatch_semaphore_wait(data_sem, DISPATCH_TIME_FOREVER);
|
||||
dispatch_semaphore_signal(region_sem);
|
||||
|
||||
//this second wait allows us to block until data is copied... more on this later
|
||||
dispatch_semaphore_wait(data_sem, DISPATCH_TIME_FOREVER);
|
||||
*pxData = localBuf;
|
||||
dispatch_semaphore_signal(data_sem);
|
||||
|
||||
/*
|
||||
if (image != NULL) {
|
||||
CGImageRelease(image);
|
||||
}
|
||||
image = CGDisplayCreateImageForRect(
|
||||
kCGDirectMainDisplay,
|
||||
CGRectMake(x, y, width, height) );
|
||||
|
||||
CGContextDrawImage(
|
||||
bitmapcontext,
|
||||
CGRectMake(0, 1800 - height, width, height),
|
||||
image);
|
||||
|
||||
*pxData = baseAddress;
|
||||
|
||||
*/
|
||||
|
||||
return 0;
|
||||
dispatch_semaphore_wait(region_sem, DISPATCH_TIME_FOREVER);
|
||||
ready = TRUE;
|
||||
dispatch_semaphore_wait(data_sem, DISPATCH_TIME_FOREVER);
|
||||
dispatch_semaphore_signal(region_sem);
|
||||
|
||||
//this second wait allows us to block until data is copied... more on this later
|
||||
dispatch_semaphore_wait(data_sem, DISPATCH_TIME_FOREVER);
|
||||
*pxData = localBuf;
|
||||
dispatch_semaphore_signal(data_sem);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,21 +1,21 @@
|
|||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Client
|
||||
* FreeRDP Mac OS X Server
|
||||
*
|
||||
* Copyright 2012 Corey Clayton <can.of.tuna@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.
|
||||
*/
|
||||
* FreeRDP: A Remote Desktop Protocol Client
|
||||
* FreeRDP Mac OS X Server
|
||||
*
|
||||
* Copyright 2012 Corey Clayton <can.of.tuna@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"
|
||||
|
@ -61,151 +61,136 @@ BOOL mf_peer_get_fds(freerdp_peer* client, void** rfds, int* rcount)
|
|||
{
|
||||
if (info_event_queue->pipe_fd[0] == -1)
|
||||
return TRUE;
|
||||
|
||||
|
||||
rfds[*rcount] = (void *)(long) info_event_queue->pipe_fd[0];
|
||||
(*rcount)++;
|
||||
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL mf_peer_check_fds(freerdp_peer* client)
|
||||
{
|
||||
mfPeerContext* context = (mfPeerContext*) client->context;
|
||||
mfPeerContext* context = (mfPeerContext*) client->context;
|
||||
mfEvent* event;
|
||||
//HGDI_RGN invalid_region;
|
||||
|
||||
|
||||
if (context->activated == FALSE)
|
||||
return TRUE;
|
||||
|
||||
|
||||
event = mf_event_peek(info_event_queue);
|
||||
|
||||
|
||||
if (event != NULL)
|
||||
{
|
||||
if (event->type == MF_EVENT_TYPE_REGION)
|
||||
{
|
||||
printf("unhandled event\n");
|
||||
/*mfEventRegion* region = (mfEventRegion*) mf_event_pop(info_event_queue);
|
||||
gdi_InvalidateRegion(xfp->hdc, region->x, region->y, region->width, region->height);
|
||||
xf_event_region_free(region);*/
|
||||
printf("unhandled event\n");
|
||||
}
|
||||
else if (event->type == MF_EVENT_TYPE_FRAME_TICK)
|
||||
{
|
||||
event = mf_event_pop(info_event_queue);
|
||||
|
||||
mf_peer_rfx_update(client);
|
||||
|
||||
mf_peer_rfx_update(client);
|
||||
|
||||
mf_event_free(event);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void mf_peer_rfx_update(freerdp_peer* client)
|
||||
{
|
||||
//check
|
||||
mfInfo* mfi = mf_info_get_instance();
|
||||
|
||||
mf_info_find_invalid_region(mfi);
|
||||
|
||||
if (mf_info_have_invalid_region(mfi) == false) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
long width;
|
||||
long height;
|
||||
int pitch;
|
||||
BYTE* dataBits = NULL;
|
||||
|
||||
mf_info_getScreenData(mfi, &width, &height, &dataBits, &pitch);
|
||||
|
||||
mf_info_clear_invalid_region(mfi);
|
||||
|
||||
//encode
|
||||
|
||||
STREAM* s;
|
||||
//check
|
||||
mfInfo* mfi = mf_info_get_instance();
|
||||
|
||||
mf_info_find_invalid_region(mfi);
|
||||
|
||||
if (mf_info_have_invalid_region(mfi) == false) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
long width;
|
||||
long height;
|
||||
int pitch;
|
||||
BYTE* dataBits = NULL;
|
||||
|
||||
mf_info_getScreenData(mfi, &width, &height, &dataBits, &pitch);
|
||||
|
||||
mf_info_clear_invalid_region(mfi);
|
||||
|
||||
//encode
|
||||
|
||||
STREAM* s;
|
||||
RFX_RECT rect;
|
||||
rdpUpdate* update;
|
||||
mfPeerContext* mfp;
|
||||
SURFACE_BITS_COMMAND* cmd;
|
||||
|
||||
|
||||
update = client->update;
|
||||
mfp = (mfPeerContext*) client->context;
|
||||
cmd = &update->surface_bits_command;
|
||||
|
||||
|
||||
s = mfp->s;
|
||||
stream_clear(s);
|
||||
|
||||
|
||||
s = mfp->s;
|
||||
stream_clear(s);
|
||||
stream_set_pos(s, 0);
|
||||
|
||||
UINT32 x = mfi->invalid.x / mfi->scale;
|
||||
UINT32 y = mfi->invalid.y / mfi->scale;
|
||||
|
||||
rect.x = 0;
|
||||
rect.y = 0;
|
||||
rect.width = width;
|
||||
rect.height = height;
|
||||
|
||||
mfp->rfx_context->width = mfi->servscreen_width;
|
||||
mfp->rfx_context->height = mfi->servscreen_height;
|
||||
|
||||
rfx_compose_message(mfp->rfx_context, s, &rect, 1,
|
||||
(BYTE*) dataBits, rect.width, rect.height, pitch);
|
||||
|
||||
cmd->destLeft = x;
|
||||
cmd->destTop = y;
|
||||
cmd->destRight = x + rect.width;
|
||||
cmd->destBottom = y + rect.height;
|
||||
|
||||
|
||||
|
||||
UINT32 x = mfi->invalid.x / mfi->scale;
|
||||
UINT32 y = mfi->invalid.y / mfi->scale;
|
||||
|
||||
rect.x = 0;
|
||||
rect.y = 0;
|
||||
rect.width = width;
|
||||
rect.height = height;
|
||||
|
||||
mfp->rfx_context->width = mfi->servscreen_width;
|
||||
mfp->rfx_context->height = mfi->servscreen_height;
|
||||
|
||||
rfx_compose_message(mfp->rfx_context, s, &rect, 1,
|
||||
(BYTE*) dataBits, rect.width, rect.height, pitch);
|
||||
|
||||
cmd->destLeft = x;
|
||||
cmd->destTop = y;
|
||||
cmd->destRight = x + rect.width;
|
||||
cmd->destBottom = y + rect.height;
|
||||
|
||||
|
||||
cmd->bpp = 32;
|
||||
cmd->codecID = 3;
|
||||
cmd->width = rect.width;
|
||||
cmd->height = rect.height;
|
||||
cmd->bitmapDataLength = stream_get_length(s);
|
||||
cmd->bitmapData = stream_get_head(s);
|
||||
|
||||
//send
|
||||
|
||||
update->SurfaceBits(update->context, cmd);
|
||||
|
||||
//clean up
|
||||
|
||||
// note: need to stop getting new dirty rects until here
|
||||
|
||||
|
||||
/*
|
||||
CGColorSpaceRelease(rgbColorSpace);
|
||||
CGImageRelease(image);
|
||||
CGContextRelease(context);
|
||||
|
||||
CVPixelBufferUnlockBaseAddress(pxbuffer, 0);
|
||||
CVPixelBufferRelease(pxbuffer);
|
||||
*/
|
||||
|
||||
//send
|
||||
|
||||
update->SurfaceBits(update->context, cmd);
|
||||
|
||||
//clean up... maybe?
|
||||
|
||||
}
|
||||
|
||||
/* Called when we have a new peer connecting */
|
||||
void mf_peer_context_new(freerdp_peer* client, mfPeerContext* context)
|
||||
{
|
||||
context->info = mf_info_get_instance();
|
||||
context->info = mf_info_get_instance();
|
||||
context->rfx_context = rfx_context_new();
|
||||
context->rfx_context->mode = RLGR3;
|
||||
context->rfx_context->width = client->settings->DesktopWidth;
|
||||
context->rfx_context->height = client->settings->DesktopHeight;
|
||||
rfx_context_set_pixel_format(context->rfx_context, RDP_PIXEL_FORMAT_B8G8R8A8);
|
||||
rfx_context_set_cpu_opt(context->rfx_context, CPU_SSE2);
|
||||
|
||||
rfx_context_set_cpu_opt(context->rfx_context, CPU_SSE2);
|
||||
|
||||
//context->nsc_context = nsc_context_new();
|
||||
//nsc_context_set_pixel_format(context->nsc_context, RDP_PIXEL_FORMAT_B8G8R8A8);
|
||||
|
||||
|
||||
context->s = stream_new(0xFFFF);
|
||||
|
||||
//#ifdef WITH_SERVER_CHANNELS
|
||||
|
||||
//#ifdef WITH_SERVER_CHANNELS
|
||||
context->vcm = WTSCreateVirtualChannelManager(client);
|
||||
//#endif
|
||||
|
||||
mf_info_peer_register(context->info, context);
|
||||
//#endif
|
||||
|
||||
mf_info_peer_register(context->info, context);
|
||||
}
|
||||
|
||||
|
||||
|
@ -214,29 +199,29 @@ void mf_peer_context_free(freerdp_peer* client, mfPeerContext* context)
|
|||
{
|
||||
if (context)
|
||||
{
|
||||
mf_info_peer_unregister(context->info, context);
|
||||
|
||||
dispatch_suspend(info_timer);
|
||||
|
||||
mf_info_peer_unregister(context->info, context);
|
||||
|
||||
dispatch_suspend(info_timer);
|
||||
|
||||
stream_free(context->s);
|
||||
|
||||
|
||||
rfx_context_free(context->rfx_context);
|
||||
//nsc_context_free(context->nsc_context);
|
||||
|
||||
|
||||
#ifdef CHANNEL_AUDIN_SERVER
|
||||
if (context->audin)
|
||||
audin_server_context_free(context->audin);
|
||||
#endif
|
||||
|
||||
//#ifdef CHANNEL_RDPSND_SERVER
|
||||
mf_peer_rdpsnd_stop();
|
||||
|
||||
//#ifdef CHANNEL_RDPSND_SERVER
|
||||
mf_peer_rdpsnd_stop();
|
||||
if (context->rdpsnd)
|
||||
rdpsnd_server_context_free(context->rdpsnd);
|
||||
//#endif
|
||||
|
||||
//#ifdef WITH_SERVER_CHANNELS
|
||||
//#endif
|
||||
|
||||
//#ifdef WITH_SERVER_CHANNELS
|
||||
WTSDestroyVirtualChannelManager(context->vcm);
|
||||
//#endif
|
||||
//#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -247,86 +232,86 @@ void mf_peer_init(freerdp_peer* client)
|
|||
client->ContextNew = (psPeerContextNew) mf_peer_context_new;
|
||||
client->ContextFree = (psPeerContextFree) mf_peer_context_free;
|
||||
freerdp_peer_context_new(client);
|
||||
|
||||
info_event_queue = mf_event_queue_new();
|
||||
|
||||
info_queue = dispatch_queue_create("testing.101", DISPATCH_QUEUE_SERIAL);
|
||||
info_timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, info_queue);
|
||||
|
||||
if(info_timer)
|
||||
{
|
||||
//printf("created timer\n");
|
||||
dispatch_source_set_timer(info_timer, DISPATCH_TIME_NOW, 42ull * NSEC_PER_MSEC, 100ull * NSEC_PER_MSEC);
|
||||
dispatch_source_set_event_handler(info_timer, ^{
|
||||
//printf("dispatch\n");
|
||||
mfEvent* event = mf_event_new(MF_EVENT_TYPE_FRAME_TICK);
|
||||
mf_event_push(info_event_queue, (mfEvent*) event);}
|
||||
);
|
||||
dispatch_resume(info_timer);
|
||||
}
|
||||
|
||||
info_event_queue = mf_event_queue_new();
|
||||
|
||||
info_queue = dispatch_queue_create("testing.101", DISPATCH_QUEUE_SERIAL);
|
||||
info_timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, info_queue);
|
||||
|
||||
if(info_timer)
|
||||
{
|
||||
//printf("created timer\n");
|
||||
dispatch_source_set_timer(info_timer, DISPATCH_TIME_NOW, 42ull * NSEC_PER_MSEC, 100ull * NSEC_PER_MSEC);
|
||||
dispatch_source_set_event_handler(info_timer, ^{
|
||||
//printf("dispatch\n");
|
||||
mfEvent* event = mf_event_new(MF_EVENT_TYPE_FRAME_TICK);
|
||||
mf_event_push(info_event_queue, (mfEvent*) event);}
|
||||
);
|
||||
dispatch_resume(info_timer);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
BOOL mf_peer_post_connect(freerdp_peer* client)
|
||||
{
|
||||
mfPeerContext* context = (mfPeerContext*) client->context;
|
||||
rdpSettings* settings = client->settings;
|
||||
|
||||
rdpSettings* settings = client->settings;
|
||||
|
||||
printf("Client %s post connect\n", client->hostname);
|
||||
|
||||
|
||||
if (client->settings->AutoLogonEnabled)
|
||||
{
|
||||
printf(" and wants to login automatically as %s\\%s",
|
||||
client->settings->Domain ? client->settings->Domain : "",
|
||||
client->settings->Username);
|
||||
|
||||
client->settings->Domain ? client->settings->Domain : "",
|
||||
client->settings->Username);
|
||||
|
||||
/* A real server may perform OS login here if NLA is not executed previously. */
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
mfInfo* mfi = mf_info_get_instance();
|
||||
mfi->scale = 1;
|
||||
|
||||
//mfi->servscreen_width = 2880 / mfi->scale;
|
||||
//mfi->servscreen_height = 1800 / mfi->scale;
|
||||
UINT32 bitsPerPixel = 32;
|
||||
|
||||
if ((settings->DesktopWidth != mfi->servscreen_width) || (settings->DesktopHeight != mfi->servscreen_height))
|
||||
|
||||
mfInfo* mfi = mf_info_get_instance();
|
||||
mfi->scale = 1;
|
||||
|
||||
//mfi->servscreen_width = 2880 / mfi->scale;
|
||||
//mfi->servscreen_height = 1800 / mfi->scale;
|
||||
UINT32 bitsPerPixel = 32;
|
||||
|
||||
if ((settings->DesktopWidth != mfi->servscreen_width) || (settings->DesktopHeight != mfi->servscreen_height))
|
||||
{
|
||||
printf("Client requested resolution %dx%d, but will resize to %dx%d\n",
|
||||
settings->DesktopWidth, settings->DesktopHeight, mfi->servscreen_width, mfi->servscreen_height);
|
||||
}
|
||||
|
||||
settings->DesktopWidth = mfi->servscreen_width;
|
||||
settings->DesktopHeight = mfi->servscreen_height;
|
||||
settings->ColorDepth = bitsPerPixel;
|
||||
|
||||
client->update->DesktopResize(client->update->context);
|
||||
settings->DesktopWidth, settings->DesktopHeight, mfi->servscreen_width, mfi->servscreen_height);
|
||||
}
|
||||
|
||||
|
||||
//#ifdef WITH_SERVER_CHANNELS
|
||||
settings->DesktopWidth = mfi->servscreen_width;
|
||||
settings->DesktopHeight = mfi->servscreen_height;
|
||||
settings->ColorDepth = bitsPerPixel;
|
||||
|
||||
client->update->DesktopResize(client->update->context);
|
||||
|
||||
|
||||
//#ifdef WITH_SERVER_CHANNELS
|
||||
/* Iterate all channel names requested by the client and activate those supported by the server */
|
||||
int i;
|
||||
int i;
|
||||
for (i = 0; i < client->settings->ChannelCount; i++)
|
||||
{
|
||||
if (client->settings->ChannelDefArray[i].joined)
|
||||
{
|
||||
//#ifdef CHANNEL_RDPSND_SERVER
|
||||
//#ifdef CHANNEL_RDPSND_SERVER
|
||||
if (strncmp(client->settings->ChannelDefArray[i].Name, "rdpsnd", 6) == 0)
|
||||
{
|
||||
mf_peer_rdpsnd_init(context); /* Audio Output */
|
||||
}
|
||||
//#endif
|
||||
//#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Dynamic Virtual Channels */
|
||||
//#endif
|
||||
|
||||
//#endif
|
||||
|
||||
#ifdef CHANNEL_AUDIN_SERVER
|
||||
mf_peer_audin_init(context); /* Audio Input */
|
||||
#endif
|
||||
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -334,27 +319,27 @@ BOOL mf_peer_post_connect(freerdp_peer* client)
|
|||
BOOL mf_peer_activate(freerdp_peer* client)
|
||||
{
|
||||
mfPeerContext* context = (mfPeerContext*) client->context;
|
||||
|
||||
|
||||
rfx_context_reset(context->rfx_context);
|
||||
context->activated = TRUE;
|
||||
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*BOOL wf_peer_logon(freerdp_peer* client, SEC_WINNT_AUTH_IDENTITY* identity, BOOL automatic)
|
||||
{
|
||||
printf("PeerLogon\n");
|
||||
|
||||
if (automatic)
|
||||
{
|
||||
_tprintf(_T("Logon: User:%s Domain:%s Password:%s\n"),
|
||||
identity->User, identity->Domain, identity->Password);
|
||||
}
|
||||
|
||||
|
||||
wfreerdp_server_peer_callback_event(((rdpContext*) client->context)->peer->pId, WF_SRV_CALLBACK_EVENT_AUTH);
|
||||
return TRUE;
|
||||
}*/
|
||||
{
|
||||
printf("PeerLogon\n");
|
||||
|
||||
if (automatic)
|
||||
{
|
||||
_tprintf(_T("Logon: User:%s Domain:%s Password:%s\n"),
|
||||
identity->User, identity->Domain, identity->Password);
|
||||
}
|
||||
|
||||
|
||||
wfreerdp_server_peer_callback_event(((rdpContext*) client->context)->peer->pId, WF_SRV_CALLBACK_EVENT_AUTH);
|
||||
return TRUE;
|
||||
}*/
|
||||
|
||||
void mf_peer_synchronize_event(rdpInput* input, UINT32 flags)
|
||||
{
|
||||
|
@ -364,23 +349,23 @@ void mf_peer_synchronize_event(rdpInput* input, UINT32 flags)
|
|||
void mf_peer_keyboard_event(rdpInput* input, UINT16 flags, UINT16 code)
|
||||
{
|
||||
printf("Client sent a keyboard event (flags:0x%04X code:0x%04X)\n", flags, code);
|
||||
|
||||
UINT16 down = 0x4000;
|
||||
//UINT16 up = 0x8000;
|
||||
|
||||
bool state_down = FALSE;
|
||||
|
||||
if (flags == down)
|
||||
{
|
||||
state_down = TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
CGEventRef event;
|
||||
event = CGEventCreateKeyboardEvent(NULL, (CGKeyCode)code, state_down);
|
||||
CGEventPost(kCGHIDEventTap, event);
|
||||
CFRelease(event);
|
||||
*/
|
||||
|
||||
UINT16 down = 0x4000;
|
||||
//UINT16 up = 0x8000;
|
||||
|
||||
bool state_down = FALSE;
|
||||
|
||||
if (flags == down)
|
||||
{
|
||||
state_down = TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
CGEventRef event;
|
||||
event = CGEventCreateKeyboardEvent(NULL, (CGKeyCode)code, state_down);
|
||||
CGEventPost(kCGHIDEventTap, event);
|
||||
CFRelease(event);
|
||||
*/
|
||||
}
|
||||
|
||||
void mf_peer_unicode_keyboard_event(rdpInput* input, UINT16 flags, UINT16 code)
|
||||
|
@ -399,16 +384,16 @@ void mf_peer_extended_mouse_event(rdpInput* input, UINT16 flags, UINT16 x, UINT1
|
|||
}
|
||||
|
||||
/*static void mf_peer_refresh_rect(rdpContext* context, BYTE count, RECTANGLE_16* areas)
|
||||
{
|
||||
BYTE i;
|
||||
|
||||
printf("Client requested to refresh:\n");
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
printf(" (%d, %d) (%d, %d)\n", areas[i].left, areas[i].top, areas[i].right, areas[i].bottom);
|
||||
}
|
||||
}*/
|
||||
{
|
||||
BYTE i;
|
||||
|
||||
printf("Client requested to refresh:\n");
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
printf(" (%d, %d) (%d, %d)\n", areas[i].left, areas[i].top, areas[i].right, areas[i].bottom);
|
||||
}
|
||||
}*/
|
||||
|
||||
static void mf_peer_suppress_output(rdpContext* context, BYTE allow, RECTANGLE_16* area)
|
||||
{
|
||||
|
@ -425,74 +410,74 @@ static void mf_peer_suppress_output(rdpContext* context, BYTE allow, RECTANGLE_1
|
|||
void mf_peer_accepted(freerdp_listener* instance, freerdp_peer* client)
|
||||
{
|
||||
pthread_t th;
|
||||
|
||||
|
||||
pthread_create(&th, 0, mf_peer_main_loop, client);
|
||||
pthread_detach(th);
|
||||
}
|
||||
|
||||
/*DWORD WINAPI wf_peer_socket_listener(LPVOID lpParam)
|
||||
{
|
||||
int i, fds;
|
||||
int rcount;
|
||||
int max_fds;
|
||||
void* rfds[32];
|
||||
fd_set rfds_set;
|
||||
wfPeerContext* context;
|
||||
freerdp_peer* client = (freerdp_peer*) lpParam;
|
||||
|
||||
ZeroMemory(rfds, sizeof(rfds));
|
||||
context = (wfPeerContext*) client->context;
|
||||
|
||||
printf("PeerSocketListener\n");
|
||||
|
||||
while (1)
|
||||
{
|
||||
rcount = 0;
|
||||
|
||||
if (client->GetFileDescriptor(client, rfds, &rcount) != TRUE)
|
||||
{
|
||||
printf("Failed to get peer file descriptor\n");
|
||||
break;
|
||||
}
|
||||
|
||||
max_fds = 0;
|
||||
FD_ZERO(&rfds_set);
|
||||
|
||||
for (i = 0; i < rcount; i++)
|
||||
{
|
||||
fds = (int)(long)(rfds[i]);
|
||||
|
||||
if (fds > max_fds)
|
||||
max_fds = fds;
|
||||
|
||||
FD_SET(fds, &rfds_set);
|
||||
}
|
||||
|
||||
if (max_fds == 0)
|
||||
break;
|
||||
|
||||
select(max_fds + 1, &rfds_set, NULL, NULL, NULL);
|
||||
|
||||
SetEvent(context->socketEvent);
|
||||
WaitForSingleObject(context->socketSemaphore, INFINITE);
|
||||
|
||||
if (context->socketClose)
|
||||
break;
|
||||
}
|
||||
|
||||
printf("Exiting Peer Socket Listener Thread\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void wf_peer_read_settings(freerdp_peer* client)
|
||||
{
|
||||
if (!wf_settings_read_string_ascii(HKEY_LOCAL_MACHINE, _T("Software\\FreeRDP\\Server"), _T("CertificateFile"), &(client->settings->CertificateFile)))
|
||||
client->settings->CertificateFile = _strdup("server.crt");
|
||||
|
||||
if (!wf_settings_read_string_ascii(HKEY_LOCAL_MACHINE, _T("Software\\FreeRDP\\Server"), _T("PrivateKeyFile"), &(client->settings->PrivateKeyFile)))
|
||||
client->settings->PrivateKeyFile = _strdup("server.key");
|
||||
}*/
|
||||
{
|
||||
int i, fds;
|
||||
int rcount;
|
||||
int max_fds;
|
||||
void* rfds[32];
|
||||
fd_set rfds_set;
|
||||
wfPeerContext* context;
|
||||
freerdp_peer* client = (freerdp_peer*) lpParam;
|
||||
|
||||
ZeroMemory(rfds, sizeof(rfds));
|
||||
context = (wfPeerContext*) client->context;
|
||||
|
||||
printf("PeerSocketListener\n");
|
||||
|
||||
while (1)
|
||||
{
|
||||
rcount = 0;
|
||||
|
||||
if (client->GetFileDescriptor(client, rfds, &rcount) != TRUE)
|
||||
{
|
||||
printf("Failed to get peer file descriptor\n");
|
||||
break;
|
||||
}
|
||||
|
||||
max_fds = 0;
|
||||
FD_ZERO(&rfds_set);
|
||||
|
||||
for (i = 0; i < rcount; i++)
|
||||
{
|
||||
fds = (int)(long)(rfds[i]);
|
||||
|
||||
if (fds > max_fds)
|
||||
max_fds = fds;
|
||||
|
||||
FD_SET(fds, &rfds_set);
|
||||
}
|
||||
|
||||
if (max_fds == 0)
|
||||
break;
|
||||
|
||||
select(max_fds + 1, &rfds_set, NULL, NULL, NULL);
|
||||
|
||||
SetEvent(context->socketEvent);
|
||||
WaitForSingleObject(context->socketSemaphore, INFINITE);
|
||||
|
||||
if (context->socketClose)
|
||||
break;
|
||||
}
|
||||
|
||||
printf("Exiting Peer Socket Listener Thread\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void wf_peer_read_settings(freerdp_peer* client)
|
||||
{
|
||||
if (!wf_settings_read_string_ascii(HKEY_LOCAL_MACHINE, _T("Software\\FreeRDP\\Server"), _T("CertificateFile"), &(client->settings->CertificateFile)))
|
||||
client->settings->CertificateFile = _strdup("server.crt");
|
||||
|
||||
if (!wf_settings_read_string_ascii(HKEY_LOCAL_MACHINE, _T("Software\\FreeRDP\\Server"), _T("PrivateKeyFile"), &(client->settings->PrivateKeyFile)))
|
||||
client->settings->PrivateKeyFile = _strdup("server.key");
|
||||
}*/
|
||||
|
||||
void* mf_peer_main_loop(void* arg)
|
||||
{
|
||||
|
@ -504,11 +489,11 @@ void* mf_peer_main_loop(void* arg)
|
|||
fd_set rfds_set;
|
||||
mfPeerContext* context;
|
||||
freerdp_peer* client = (freerdp_peer*) arg;
|
||||
|
||||
|
||||
memset(rfds, 0, sizeof(rfds));
|
||||
|
||||
|
||||
mf_peer_init(client);
|
||||
|
||||
|
||||
/* Initialize the real server settings here */
|
||||
client->settings->CertificateFile = _strdup("server.crt");
|
||||
client->settings->PrivateKeyFile = _strdup("server.key");
|
||||
|
@ -517,73 +502,73 @@ void* mf_peer_main_loop(void* arg)
|
|||
client->settings->ColorDepth = 32;
|
||||
client->settings->SuppressOutput = TRUE;
|
||||
client->settings->RefreshRect = FALSE;
|
||||
|
||||
|
||||
client->PostConnect = mf_peer_post_connect;
|
||||
client->Activate = mf_peer_activate;
|
||||
|
||||
|
||||
client->input->SynchronizeEvent = mf_peer_synchronize_event;
|
||||
client->input->KeyboardEvent = mf_peer_keyboard_event;
|
||||
client->input->UnicodeKeyboardEvent = mf_peer_unicode_keyboard_event;
|
||||
client->input->MouseEvent = mf_peer_mouse_event;
|
||||
client->input->ExtendedMouseEvent = mf_peer_extended_mouse_event;
|
||||
|
||||
|
||||
//client->update->RefreshRect = mf_peer_refresh_rect;
|
||||
client->update->SuppressOutput = mf_peer_suppress_output;
|
||||
|
||||
|
||||
client->Initialize(client);
|
||||
context = (mfPeerContext*) client->context;
|
||||
|
||||
|
||||
printf("We've got a client %s\n", client->local ? "(local)" : client->hostname);
|
||||
|
||||
|
||||
while (1)
|
||||
{
|
||||
rcount = 0;
|
||||
|
||||
|
||||
if (client->GetFileDescriptor(client, rfds, &rcount) != TRUE)
|
||||
{
|
||||
printf("Failed to get FreeRDP file descriptor\n");
|
||||
break;
|
||||
}
|
||||
if (mf_peer_get_fds(client, rfds, &rcount) != TRUE)
|
||||
if (mf_peer_get_fds(client, rfds, &rcount) != TRUE)
|
||||
{
|
||||
printf("Failed to get mfreerdp file descriptor\n");
|
||||
break;
|
||||
}
|
||||
|
||||
//#ifdef WITH_SERVER_CHANNELS
|
||||
|
||||
//#ifdef WITH_SERVER_CHANNELS
|
||||
WTSVirtualChannelManagerGetFileDescriptor(context->vcm, rfds, &rcount);
|
||||
//#endif
|
||||
|
||||
//#endif
|
||||
|
||||
max_fds = 0;
|
||||
FD_ZERO(&rfds_set);
|
||||
|
||||
|
||||
for (i = 0; i < rcount; i++)
|
||||
{
|
||||
fds = (int)(long)(rfds[i]);
|
||||
|
||||
|
||||
if (fds > max_fds)
|
||||
max_fds = fds;
|
||||
|
||||
|
||||
FD_SET(fds, &rfds_set);
|
||||
}
|
||||
|
||||
|
||||
if (max_fds == 0)
|
||||
break;
|
||||
|
||||
|
||||
if (select(max_fds + 1, &rfds_set, NULL, NULL, NULL) == -1)
|
||||
{
|
||||
/* these are not really errors */
|
||||
if (!((errno == EAGAIN) ||
|
||||
(errno == EWOULDBLOCK) ||
|
||||
(errno == EINPROGRESS) ||
|
||||
(errno == EINTR))) /* signal occurred */
|
||||
(errno == EWOULDBLOCK) ||
|
||||
(errno == EINPROGRESS) ||
|
||||
(errno == EINTR))) /* signal occurred */
|
||||
{
|
||||
printf("select failed\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (client->CheckFileDescriptor(client) != TRUE)
|
||||
|
||||
if (client->CheckFileDescriptor(client) != TRUE)
|
||||
{
|
||||
printf("Failed to check freerdp file descriptor\n");
|
||||
break;
|
||||
|
@ -593,20 +578,20 @@ void* mf_peer_main_loop(void* arg)
|
|||
printf("Failed to check mfreerdp file descriptor\n");
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
//#ifdef WITH_SERVER_CHANNELS
|
||||
|
||||
|
||||
//#ifdef WITH_SERVER_CHANNELS
|
||||
if (WTSVirtualChannelManagerCheckFileDescriptor(context->vcm) != TRUE)
|
||||
break;
|
||||
//#endif
|
||||
|
||||
//#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
printf("Client %s disconnected.\n", client->local ? "(local)" : client->hostname);
|
||||
|
||||
|
||||
client->Disconnect(client);
|
||||
freerdp_peer_context_free(client);
|
||||
freerdp_peer_free(client);
|
||||
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -44,107 +44,94 @@ static const rdpsndFormat audio_formats[] =
|
|||
|
||||
static void mf_peer_rdpsnd_activated(rdpsnd_server_context* context)
|
||||
{
|
||||
printf("RDPSND Activated\n");
|
||||
|
||||
|
||||
|
||||
printf("Let's create an audio queue for input!\n");
|
||||
|
||||
OSStatus status;
|
||||
|
||||
recorderState.dataFormat.mSampleRate = 44100.0;
|
||||
recorderState.dataFormat.mFormatID = kAudioFormatLinearPCM;
|
||||
recorderState.dataFormat.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagsNativeEndian | kAudioFormatFlagIsPacked;
|
||||
recorderState.dataFormat.mBytesPerPacket = 4;
|
||||
recorderState.dataFormat.mFramesPerPacket = 1;
|
||||
recorderState.dataFormat.mBytesPerFrame = 4;
|
||||
recorderState.dataFormat.mChannelsPerFrame = 2;
|
||||
recorderState.dataFormat.mBitsPerChannel = 16;
|
||||
|
||||
recorderState.snd_context = context;
|
||||
|
||||
status = AudioQueueNewInput(&recorderState.dataFormat,
|
||||
mf_peer_rdpsnd_input_callback,
|
||||
&recorderState,
|
||||
NULL,
|
||||
kCFRunLoopCommonModes,
|
||||
0,
|
||||
&recorderState.queue);
|
||||
|
||||
if (status != noErr)
|
||||
{
|
||||
printf("Failed to create a new Audio Queue. Status code: %d\n", status);
|
||||
}
|
||||
|
||||
|
||||
UInt32 dataFormatSize = sizeof (recorderState.dataFormat);
|
||||
|
||||
AudioQueueGetProperty(recorderState.queue,
|
||||
kAudioConverterCurrentInputStreamDescription,
|
||||
&recorderState.dataFormat,
|
||||
&dataFormatSize);
|
||||
|
||||
|
||||
mf_rdpsnd_derive_buffer_size(recorderState.queue, &recorderState.dataFormat, 0.05, &recorderState.bufferByteSize);
|
||||
|
||||
|
||||
printf("Preparing a set of buffers...");
|
||||
|
||||
for (int i = 0; i < snd_numBuffers; ++i)
|
||||
{
|
||||
AudioQueueAllocateBuffer(recorderState.queue,
|
||||
recorderState.bufferByteSize,
|
||||
&recorderState.buffers[i]);
|
||||
|
||||
AudioQueueEnqueueBuffer(recorderState.queue,
|
||||
recorderState.buffers[i],
|
||||
0,
|
||||
NULL);
|
||||
}
|
||||
|
||||
printf("done\n");
|
||||
|
||||
printf("recording...\n");
|
||||
|
||||
|
||||
|
||||
recorderState.currentPacket = 0;
|
||||
recorderState.isRunning = true;
|
||||
|
||||
context->SelectFormat(context, 4);
|
||||
context->SetVolume(context, 0x7FFF, 0x7FFF);
|
||||
|
||||
AudioQueueStart (recorderState.queue, NULL);
|
||||
|
||||
OSStatus status;
|
||||
|
||||
recorderState.dataFormat.mSampleRate = 44100.0;
|
||||
recorderState.dataFormat.mFormatID = kAudioFormatLinearPCM;
|
||||
recorderState.dataFormat.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagsNativeEndian | kAudioFormatFlagIsPacked;
|
||||
recorderState.dataFormat.mBytesPerPacket = 4;
|
||||
recorderState.dataFormat.mFramesPerPacket = 1;
|
||||
recorderState.dataFormat.mBytesPerFrame = 4;
|
||||
recorderState.dataFormat.mChannelsPerFrame = 2;
|
||||
recorderState.dataFormat.mBitsPerChannel = 16;
|
||||
|
||||
recorderState.snd_context = context;
|
||||
|
||||
status = AudioQueueNewInput(&recorderState.dataFormat,
|
||||
mf_peer_rdpsnd_input_callback,
|
||||
&recorderState,
|
||||
NULL,
|
||||
kCFRunLoopCommonModes,
|
||||
0,
|
||||
&recorderState.queue);
|
||||
|
||||
if (status != noErr)
|
||||
{
|
||||
printf("Failed to create a new Audio Queue. Status code: %d\n", status);
|
||||
}
|
||||
|
||||
|
||||
UInt32 dataFormatSize = sizeof (recorderState.dataFormat);
|
||||
|
||||
AudioQueueGetProperty(recorderState.queue,
|
||||
kAudioConverterCurrentInputStreamDescription,
|
||||
&recorderState.dataFormat,
|
||||
&dataFormatSize);
|
||||
|
||||
|
||||
mf_rdpsnd_derive_buffer_size(recorderState.queue, &recorderState.dataFormat, 0.05, &recorderState.bufferByteSize);
|
||||
|
||||
|
||||
for (int i = 0; i < snd_numBuffers; ++i)
|
||||
{
|
||||
AudioQueueAllocateBuffer(recorderState.queue,
|
||||
recorderState.bufferByteSize,
|
||||
&recorderState.buffers[i]);
|
||||
|
||||
AudioQueueEnqueueBuffer(recorderState.queue,
|
||||
recorderState.buffers[i],
|
||||
0,
|
||||
NULL);
|
||||
}
|
||||
|
||||
|
||||
recorderState.currentPacket = 0;
|
||||
recorderState.isRunning = true;
|
||||
|
||||
context->SelectFormat(context, 4);
|
||||
context->SetVolume(context, 0x7FFF, 0x7FFF);
|
||||
|
||||
AudioQueueStart (recorderState.queue, NULL);
|
||||
|
||||
}
|
||||
|
||||
BOOL mf_peer_rdpsnd_init(mfPeerContext* context)
|
||||
{
|
||||
//printf("RDPSND INIT\n");
|
||||
context->rdpsnd = rdpsnd_server_context_new(context->vcm);
|
||||
context->rdpsnd->data = context;
|
||||
|
||||
|
||||
context->rdpsnd->server_formats = audio_formats;
|
||||
context->rdpsnd->num_server_formats = sizeof(audio_formats) / sizeof(audio_formats[0]);
|
||||
|
||||
|
||||
context->rdpsnd->src_format.wFormatTag = 1;
|
||||
context->rdpsnd->src_format.nChannels = 2;
|
||||
context->rdpsnd->src_format.nSamplesPerSec = 44100;
|
||||
context->rdpsnd->src_format.wBitsPerSample = 16;
|
||||
|
||||
|
||||
context->rdpsnd->Activated = mf_peer_rdpsnd_activated;
|
||||
|
||||
|
||||
context->rdpsnd->Initialize(context->rdpsnd);
|
||||
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL mf_peer_rdpsnd_stop()
|
||||
{
|
||||
recorderState.isRunning = false;
|
||||
AudioQueueStop(recorderState.queue, true);
|
||||
|
||||
return TRUE;
|
||||
recorderState.isRunning = false;
|
||||
AudioQueueStop(recorderState.queue, true);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void mf_peer_rdpsnd_input_callback (void *inUserData,
|
||||
|
@ -154,35 +141,35 @@ void mf_peer_rdpsnd_input_callback (void *inUserD
|
|||
UInt32 inNumberPacketDescriptions,
|
||||
const AudioStreamPacketDescription *inPacketDescs)
|
||||
{
|
||||
OSStatus status;
|
||||
AQRecorderState * rState;
|
||||
rState = inUserData;
|
||||
|
||||
|
||||
if (inNumberPacketDescriptions == 0 && rState->dataFormat.mBytesPerPacket != 0)
|
||||
{
|
||||
inNumberPacketDescriptions = inBuffer->mAudioDataByteSize / rState->dataFormat.mBytesPerPacket;
|
||||
}
|
||||
|
||||
|
||||
if (rState->isRunning == 0)
|
||||
{
|
||||
return ;
|
||||
}
|
||||
|
||||
rState->snd_context->SendSamples(rState->snd_context, inBuffer->mAudioData, inBuffer->mAudioDataByteSize/4);
|
||||
|
||||
status = AudioQueueEnqueueBuffer(
|
||||
rState->queue,
|
||||
inBuffer,
|
||||
0,
|
||||
NULL);
|
||||
|
||||
if (status != noErr)
|
||||
{
|
||||
printf("AudioQueueEnqueueBuffer() returned status = %d\n", status);
|
||||
}
|
||||
|
||||
OSStatus status;
|
||||
AQRecorderState * rState;
|
||||
rState = inUserData;
|
||||
|
||||
|
||||
if (inNumberPacketDescriptions == 0 && rState->dataFormat.mBytesPerPacket != 0)
|
||||
{
|
||||
inNumberPacketDescriptions = inBuffer->mAudioDataByteSize / rState->dataFormat.mBytesPerPacket;
|
||||
}
|
||||
|
||||
|
||||
if (rState->isRunning == 0)
|
||||
{
|
||||
return ;
|
||||
}
|
||||
|
||||
rState->snd_context->SendSamples(rState->snd_context, inBuffer->mAudioData, inBuffer->mAudioDataByteSize/4);
|
||||
|
||||
status = AudioQueueEnqueueBuffer(
|
||||
rState->queue,
|
||||
inBuffer,
|
||||
0,
|
||||
NULL);
|
||||
|
||||
if (status != noErr)
|
||||
{
|
||||
printf("AudioQueueEnqueueBuffer() returned status = %d\n", status);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void mf_rdpsnd_derive_buffer_size (AudioQueueRef audioQueue,
|
||||
|
@ -190,23 +177,23 @@ void mf_rdpsnd_derive_buffer_size (AudioQueueRef audioQueue,
|
|||
Float64 seconds,
|
||||
UInt32 *outBufferSize)
|
||||
{
|
||||
static const int maxBufferSize = 0x50000;
|
||||
|
||||
int maxPacketSize = ASBDescription->mBytesPerPacket;
|
||||
if (maxPacketSize == 0)
|
||||
{
|
||||
UInt32 maxVBRPacketSize = sizeof(maxPacketSize);
|
||||
AudioQueueGetProperty (audioQueue,
|
||||
kAudioQueueProperty_MaximumOutputPacketSize,
|
||||
// in Mac OS X v10.5, instead use
|
||||
// kAudioConverterPropertyMaximumOutputPacketSize
|
||||
&maxPacketSize,
|
||||
&maxVBRPacketSize
|
||||
);
|
||||
}
|
||||
|
||||
Float64 numBytesForTime =
|
||||
ASBDescription->mSampleRate * maxPacketSize * seconds;
|
||||
*outBufferSize = (UInt32) (numBytesForTime < maxBufferSize ? numBytesForTime : maxBufferSize);
|
||||
static const int maxBufferSize = 0x50000;
|
||||
|
||||
int maxPacketSize = ASBDescription->mBytesPerPacket;
|
||||
if (maxPacketSize == 0)
|
||||
{
|
||||
UInt32 maxVBRPacketSize = sizeof(maxPacketSize);
|
||||
AudioQueueGetProperty (audioQueue,
|
||||
kAudioQueueProperty_MaximumOutputPacketSize,
|
||||
// in Mac OS X v10.5, instead use
|
||||
// kAudioConverterPropertyMaximumOutputPacketSize
|
||||
&maxPacketSize,
|
||||
&maxVBRPacketSize
|
||||
);
|
||||
}
|
||||
|
||||
Float64 numBytesForTime =
|
||||
ASBDescription->mSampleRate * maxPacketSize * seconds;
|
||||
*outBufferSize = (UInt32) (numBytesForTime < maxBufferSize ? numBytesForTime : maxBufferSize);
|
||||
}
|
||||
|
||||
|
|
|
@ -36,25 +36,25 @@ void mf_rdpsnd_derive_buffer_size (AudioQueueRef audioQueue,
|
|||
UInt32 *outBufferSize);
|
||||
|
||||
void mf_peer_rdpsnd_input_callback (void *inUserData,
|
||||
AudioQueueRef inAQ,
|
||||
AudioQueueBufferRef inBuffer,
|
||||
const AudioTimeStamp *inStartTime,
|
||||
UInt32 inNumberPacketDescriptions,
|
||||
const AudioStreamPacketDescription *inPacketDescs);
|
||||
AudioQueueRef inAQ,
|
||||
AudioQueueBufferRef inBuffer,
|
||||
const AudioTimeStamp *inStartTime,
|
||||
UInt32 inNumberPacketDescriptions,
|
||||
const AudioStreamPacketDescription *inPacketDescs);
|
||||
|
||||
|
||||
static const int snd_numBuffers = 3;
|
||||
struct _AQRecorderState
|
||||
{
|
||||
AudioStreamBasicDescription dataFormat;
|
||||
AudioQueueRef queue;
|
||||
AudioQueueBufferRef buffers[snd_numBuffers];
|
||||
AudioFileID audioFile;
|
||||
UInt32 bufferByteSize;
|
||||
SInt64 currentPacket;
|
||||
bool isRunning;
|
||||
rdpsnd_server_context* snd_context;
|
||||
|
||||
AudioStreamBasicDescription dataFormat;
|
||||
AudioQueueRef queue;
|
||||
AudioQueueBufferRef buffers[snd_numBuffers];
|
||||
AudioFileID audioFile;
|
||||
UInt32 bufferByteSize;
|
||||
SInt64 currentPacket;
|
||||
bool isRunning;
|
||||
rdpsnd_server_context* snd_context;
|
||||
|
||||
};
|
||||
|
||||
typedef struct _AQRecorderState AQRecorderState;
|
||||
|
|
|
@ -655,6 +655,7 @@ static void* test_peer_mainloop(void* arg)
|
|||
client->settings->PrivateKeyFile = _strdup("server.key");
|
||||
client->settings->NlaSecurity = FALSE;
|
||||
client->settings->RemoteFxCodec = TRUE;
|
||||
client->settings->ColorDepth = 32;
|
||||
client->settings->SuppressOutput = TRUE;
|
||||
client->settings->RefreshRect = TRUE;
|
||||
|
||||
|
|
|
@ -33,12 +33,30 @@ set(${MODULE_PREFIX}_SRCS
|
|||
wf_mirage.h
|
||||
wf_peer.c
|
||||
wf_peer.h
|
||||
wf_rdpsnd.c
|
||||
wf_rdpsnd.h
|
||||
wf_settings.c
|
||||
wf_settings.h
|
||||
wf_info.c
|
||||
wf_info.h)
|
||||
|
||||
if(CHANNEL_RDPSND AND NOT WITH_RDPSND_DSOUND)
|
||||
set(${MODULE_PREFIX}_SRCS
|
||||
${${MODULE_PREFIX}_SRCS}
|
||||
wf_rdpsnd.c
|
||||
wf_rdpsnd.h
|
||||
wf_wasapi.c
|
||||
wf_wasapi.h
|
||||
)
|
||||
endif()
|
||||
|
||||
if(CHANNEL_RDPSND AND WITH_RDPSND_DSOUND)
|
||||
set(${MODULE_PREFIX}_SRCS
|
||||
${${MODULE_PREFIX}_SRCS}
|
||||
wf_rdpsnd.c
|
||||
wf_rdpsnd.h
|
||||
wf_directsound.c
|
||||
wf_directsound.h
|
||||
)
|
||||
endif()
|
||||
|
||||
if(WITH_SERVER_INTERFACE)
|
||||
add_library(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS})
|
||||
|
|
|
@ -0,0 +1,203 @@
|
|||
#include "wf_directsound.h"
|
||||
#include "wf_interface.h"
|
||||
#include "wf_info.h"
|
||||
#include "wf_rdpsnd.h"
|
||||
|
||||
|
||||
#include <winpr/windows.h>
|
||||
|
||||
#define INITGUID
|
||||
#include <initguid.h>
|
||||
#include <objbase.h>
|
||||
|
||||
#define CINTERFACE 1
|
||||
#include <mmsystem.h>
|
||||
#include <dsound.h>
|
||||
|
||||
IDirectSoundCapture8* cap;
|
||||
IDirectSoundCaptureBuffer8* capBuf;
|
||||
DSCBUFFERDESC dscbd;
|
||||
DWORD lastPos;
|
||||
wfPeerContext* latestPeer;
|
||||
|
||||
int wf_rdpsnd_set_latest_peer(wfPeerContext* peer)
|
||||
{
|
||||
latestPeer = peer;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int wf_directsound_activate(rdpsnd_server_context* context)
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
LPDIRECTSOUNDCAPTUREBUFFER pDSCB;
|
||||
WAVEFORMATEX wfx = {WAVE_FORMAT_PCM, 2, 44100, 176400, 4, 16, 0};
|
||||
|
||||
|
||||
printf("RDPSND (direct sound) Activated\n");
|
||||
|
||||
hr = DirectSoundCaptureCreate8(NULL, &cap, NULL);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
_tprintf(_T("Failed to create sound capture device\n"));
|
||||
return 1;
|
||||
}
|
||||
_tprintf(_T("Created sound capture device\n"));
|
||||
|
||||
dscbd.dwSize = sizeof(DSCBUFFERDESC);
|
||||
dscbd.dwFlags = 0;
|
||||
dscbd.dwBufferBytes = 176400;
|
||||
dscbd.dwReserved = 0;
|
||||
dscbd.lpwfxFormat = &wfx;
|
||||
dscbd.dwFXCount = 0;
|
||||
dscbd.lpDSCFXDesc = NULL;
|
||||
|
||||
hr = cap->lpVtbl->CreateCaptureBuffer(cap, &dscbd, &pDSCB, NULL);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
_tprintf(_T("Failed to create capture buffer\n"));
|
||||
}
|
||||
_tprintf(_T("Created capture buffer"));
|
||||
|
||||
hr = pDSCB->lpVtbl->QueryInterface(pDSCB, &IID_IDirectSoundCaptureBuffer8, (LPVOID*)&capBuf);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
_tprintf(_T("Failed to QI capture buffer\n"));
|
||||
}
|
||||
_tprintf(_T("Created IDirectSoundCaptureBuffer8\n"));
|
||||
pDSCB->lpVtbl->Release(pDSCB);
|
||||
|
||||
context->SelectFormat(context, 4);
|
||||
context->SetVolume(context, 0x7FFF, 0x7FFF);
|
||||
lastPos = 0;
|
||||
|
||||
CreateThread(NULL, 0, wf_rdpsnd_directsound_thread, latestPeer, 0, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
DWORD WINAPI wf_rdpsnd_directsound_thread(LPVOID lpParam)
|
||||
{
|
||||
HRESULT hr;
|
||||
DWORD beg = 0;
|
||||
DWORD end = 0;
|
||||
DWORD diff, rate;
|
||||
wfPeerContext* context;
|
||||
wfInfo* wfi;
|
||||
|
||||
VOID* pbCaptureData = NULL;
|
||||
DWORD dwCaptureLength = 0;
|
||||
VOID* pbCaptureData2 = NULL;
|
||||
DWORD dwCaptureLength2 = 0;
|
||||
VOID* pbPlayData = NULL;
|
||||
DWORD dwReadPos = 0;
|
||||
LONG lLockSize = 0;
|
||||
|
||||
wfi = wf_info_get_instance();
|
||||
|
||||
context = (wfPeerContext*)lpParam;
|
||||
rate = 1000 / 24;
|
||||
|
||||
_tprintf(_T("Trying to start capture\n"));
|
||||
hr = capBuf->lpVtbl->Start(capBuf, DSCBSTART_LOOPING);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
_tprintf(_T("Failed to start capture\n"));
|
||||
}
|
||||
_tprintf(_T("Capture started\n"));
|
||||
|
||||
while (1)
|
||||
{
|
||||
|
||||
end = GetTickCount();
|
||||
diff = end - beg;
|
||||
|
||||
if (diff < rate)
|
||||
{
|
||||
Sleep(rate - diff);
|
||||
}
|
||||
|
||||
beg = GetTickCount();
|
||||
|
||||
if (wf_rdpsnd_lock() > 0)
|
||||
{
|
||||
//check for main exit condition
|
||||
if (wfi->snd_stop == TRUE)
|
||||
{
|
||||
wf_rdpsnd_unlock();
|
||||
break;
|
||||
}
|
||||
|
||||
hr = capBuf->lpVtbl->GetCurrentPosition(capBuf, NULL, &dwReadPos);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
_tprintf(_T("Failed to get read pos\n"));
|
||||
wf_rdpsnd_unlock();
|
||||
break;
|
||||
}
|
||||
|
||||
lLockSize = dwReadPos - lastPos;//dscbd.dwBufferBytes;
|
||||
if (lLockSize < 0) lLockSize += dscbd.dwBufferBytes;
|
||||
|
||||
//printf("Last, read, lock = [%d, %d, %d]\n", lastPos, dwReadPos, lLockSize);
|
||||
|
||||
if (lLockSize == 0)
|
||||
{
|
||||
wf_rdpsnd_unlock();
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
hr = capBuf->lpVtbl->Lock(capBuf, lastPos, lLockSize, &pbCaptureData, &dwCaptureLength, &pbCaptureData2, &dwCaptureLength2, 0L);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
_tprintf(_T("Failed to lock sound capture buffer\n"));
|
||||
wf_rdpsnd_unlock();
|
||||
break;
|
||||
}
|
||||
|
||||
//fwrite(pbCaptureData, 1, dwCaptureLength, pFile);
|
||||
//fwrite(pbCaptureData2, 1, dwCaptureLength2, pFile);
|
||||
|
||||
//FIXME: frames = bytes/(bytespersample * channels)
|
||||
|
||||
context->rdpsnd->SendSamples(context->rdpsnd, pbCaptureData, dwCaptureLength/4);
|
||||
context->rdpsnd->SendSamples(context->rdpsnd, pbCaptureData2, dwCaptureLength2/4);
|
||||
|
||||
|
||||
hr = capBuf->lpVtbl->Unlock(capBuf, pbCaptureData, dwCaptureLength, pbCaptureData2, dwCaptureLength2);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
_tprintf(_T("Failed to unlock sound capture buffer\n"));
|
||||
wf_rdpsnd_unlock();
|
||||
return 0;
|
||||
}
|
||||
|
||||
//TODO keep track of location in buffer
|
||||
lastPos += dwCaptureLength;
|
||||
lastPos %= dscbd.dwBufferBytes;
|
||||
lastPos += dwCaptureLength2;
|
||||
lastPos %= dscbd.dwBufferBytes;
|
||||
|
||||
wf_rdpsnd_unlock();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
_tprintf(_T("Trying to stop sound capture\n"));
|
||||
hr = capBuf->lpVtbl->Stop(capBuf);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
_tprintf(_T("Failed to stop capture\n"));
|
||||
}
|
||||
_tprintf(_T("Capture stopped\n"));
|
||||
capBuf->lpVtbl->Release(capBuf);
|
||||
cap->lpVtbl->Release(cap);
|
||||
|
||||
lastPos = 0;
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
#ifndef WF_DSOUND_H
|
||||
#define WF_DSOUND_H
|
||||
|
||||
#include <freerdp/server/rdpsnd.h>
|
||||
#include "wf_interface.h"
|
||||
|
||||
int wf_rdpsnd_set_latest_peer(wfPeerContext* peer);
|
||||
|
||||
int wf_directsound_activate(rdpsnd_server_context* context);
|
||||
|
||||
DWORD WINAPI wf_rdpsnd_directsound_thread(LPVOID lpParam);
|
||||
|
||||
#endif
|
|
@ -54,7 +54,8 @@ int get_screen_info(int id, _TCHAR* name, int* width, int* height, int* bpp)
|
|||
*width = GetDeviceCaps(dc, HORZRES);
|
||||
*height = GetDeviceCaps(dc, VERTRES);
|
||||
*bpp = GetDeviceCaps(dc, BITSPIXEL);
|
||||
ReleaseDC(NULL, dc);
|
||||
//ReleaseDC(NULL, dc);
|
||||
DeleteDC(dc);
|
||||
|
||||
}
|
||||
else
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
* FreeRDP Windows Server (Audio Output)
|
||||
*
|
||||
* Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
* Copyright 2013 Corey Clayton <can.of.tuna@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -26,32 +27,19 @@
|
|||
|
||||
#include <winpr/windows.h>
|
||||
|
||||
#define INITGUID
|
||||
#include <initguid.h>
|
||||
#include <objbase.h>
|
||||
|
||||
#define CINTERFACE
|
||||
#include <mmsystem.h>
|
||||
#include <dsound.h>
|
||||
|
||||
#include <freerdp/server/rdpsnd.h>
|
||||
|
||||
#include "wf_rdpsnd.h"
|
||||
#include "wf_info.h"
|
||||
|
||||
/*
|
||||
* Here are some temp things that shall be moved
|
||||
*
|
||||
*/
|
||||
IDirectSoundCapture8* cap;
|
||||
IDirectSoundCaptureBuffer8* capBuf;
|
||||
DSCBUFFERDESC dscbd;
|
||||
DWORD lastPos;
|
||||
#ifdef WITH_RDPSND_DSOUND
|
||||
|
||||
#define BYTESPERSEC 176400
|
||||
#include "wf_directsound.h"
|
||||
|
||||
#else
|
||||
|
||||
#include "wf_wasapi.h"
|
||||
|
||||
#endif
|
||||
|
||||
//FIXME support multiple clients
|
||||
wfPeerContext* latestPeer;
|
||||
|
||||
static const rdpsndFormat test_audio_formats[] =
|
||||
{
|
||||
|
@ -69,54 +57,16 @@ static const rdpsndFormat test_audio_formats[] =
|
|||
|
||||
static void wf_peer_rdpsnd_activated(rdpsnd_server_context* context)
|
||||
{
|
||||
HRESULT hr;
|
||||
#ifdef WITH_RDPSND_DSOUND
|
||||
|
||||
wf_directsound_activate(context);
|
||||
|
||||
#else
|
||||
|
||||
wf_wasapi_activate(context);
|
||||
|
||||
#endif
|
||||
|
||||
LPDIRECTSOUNDCAPTUREBUFFER pDSCB;
|
||||
WAVEFORMATEX wfx = {WAVE_FORMAT_PCM, 2, 44100, BYTESPERSEC, 4, 16, 0};
|
||||
|
||||
|
||||
printf("RDPSND Activated\n");
|
||||
|
||||
hr = DirectSoundCaptureCreate8(NULL, &cap, NULL);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
_tprintf(_T("Failed to create sound capture device\n"));
|
||||
return;
|
||||
}
|
||||
_tprintf(_T("Created sound capture device\n"));
|
||||
|
||||
dscbd.dwSize = sizeof(DSCBUFFERDESC);
|
||||
dscbd.dwFlags = 0;
|
||||
dscbd.dwBufferBytes = BYTESPERSEC;
|
||||
dscbd.dwReserved = 0;
|
||||
dscbd.lpwfxFormat = &wfx;
|
||||
dscbd.dwFXCount = 0;
|
||||
dscbd.lpDSCFXDesc = NULL;
|
||||
|
||||
hr = cap->lpVtbl->CreateCaptureBuffer(cap, &dscbd, &pDSCB, NULL);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
_tprintf(_T("Failed to create capture buffer\n"));
|
||||
}
|
||||
_tprintf(_T("Created capture buffer"));
|
||||
|
||||
hr = pDSCB->lpVtbl->QueryInterface(pDSCB, &IID_IDirectSoundCaptureBuffer8, (LPVOID*)&capBuf);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
_tprintf(_T("Failed to QI capture buffer\n"));
|
||||
}
|
||||
_tprintf(_T("Created IDirectSoundCaptureBuffer8\n"));
|
||||
pDSCB->lpVtbl->Release(pDSCB);
|
||||
|
||||
context->SelectFormat(context, 4);
|
||||
context->SetVolume(context, 0x7FFF, 0x7FFF);
|
||||
lastPos = 0;
|
||||
|
||||
CreateThread(NULL, 0, wf_rdpsnd_thread, latestPeer, 0, NULL);
|
||||
|
||||
|
||||
}
|
||||
|
||||
int wf_rdpsnd_lock()
|
||||
|
@ -186,131 +136,9 @@ BOOL wf_peer_rdpsnd_init(wfPeerContext* context)
|
|||
|
||||
context->rdpsnd->Initialize(context->rdpsnd);
|
||||
|
||||
latestPeer = context;
|
||||
wf_rdpsnd_set_latest_peer(context);
|
||||
|
||||
wfi->snd_stop = FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
DWORD WINAPI wf_rdpsnd_thread(LPVOID lpParam)
|
||||
{
|
||||
HRESULT hr;
|
||||
DWORD beg = 0;
|
||||
DWORD end = 0;
|
||||
DWORD diff, rate;
|
||||
wfPeerContext* context;
|
||||
wfInfo* wfi;
|
||||
|
||||
VOID* pbCaptureData = NULL;
|
||||
DWORD dwCaptureLength = 0;
|
||||
VOID* pbCaptureData2 = NULL;
|
||||
DWORD dwCaptureLength2 = 0;
|
||||
VOID* pbPlayData = NULL;
|
||||
DWORD dwReadPos = 0;
|
||||
LONG lLockSize = 0;
|
||||
|
||||
wfi = wf_info_get_instance();
|
||||
|
||||
context = (wfPeerContext*)lpParam;
|
||||
rate = 1000 / 24;
|
||||
|
||||
_tprintf(_T("Trying to start capture\n"));
|
||||
hr = capBuf->lpVtbl->Start(capBuf, DSCBSTART_LOOPING);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
_tprintf(_T("Failed to start capture\n"));
|
||||
}
|
||||
_tprintf(_T("Capture started\n"));
|
||||
|
||||
while (1)
|
||||
{
|
||||
|
||||
end = GetTickCount();
|
||||
diff = end - beg;
|
||||
|
||||
if (diff < rate)
|
||||
{
|
||||
Sleep(rate - diff);
|
||||
}
|
||||
|
||||
beg = GetTickCount();
|
||||
|
||||
if (wf_rdpsnd_lock() > 0)
|
||||
{
|
||||
//check for main exit condition
|
||||
if (wfi->snd_stop == TRUE)
|
||||
{
|
||||
wf_rdpsnd_unlock();
|
||||
break;
|
||||
}
|
||||
|
||||
hr = capBuf->lpVtbl->GetCurrentPosition(capBuf, NULL, &dwReadPos);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
_tprintf(_T("Failed to get read pos\n"));
|
||||
wf_rdpsnd_unlock();
|
||||
break;
|
||||
}
|
||||
|
||||
lLockSize = dwReadPos - lastPos;//dscbd.dwBufferBytes;
|
||||
if (lLockSize < 0) lLockSize += dscbd.dwBufferBytes;
|
||||
|
||||
//printf("Last, read, lock = [%d, %d, %d]\n", lastPos, dwReadPos, lLockSize);
|
||||
|
||||
if (lLockSize == 0)
|
||||
{
|
||||
wf_rdpsnd_unlock();
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
hr = capBuf->lpVtbl->Lock(capBuf, lastPos, lLockSize, &pbCaptureData, &dwCaptureLength, &pbCaptureData2, &dwCaptureLength2, 0L);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
_tprintf(_T("Failed to lock sound capture buffer\n"));
|
||||
wf_rdpsnd_unlock();
|
||||
break;
|
||||
}
|
||||
|
||||
//fwrite(pbCaptureData, 1, dwCaptureLength, pFile);
|
||||
//fwrite(pbCaptureData2, 1, dwCaptureLength2, pFile);
|
||||
|
||||
//FIXME: frames = bytes/(bytespersample * channels)
|
||||
|
||||
context->rdpsnd->SendSamples(context->rdpsnd, pbCaptureData, dwCaptureLength/4);
|
||||
context->rdpsnd->SendSamples(context->rdpsnd, pbCaptureData2, dwCaptureLength2/4);
|
||||
|
||||
|
||||
hr = capBuf->lpVtbl->Unlock(capBuf, pbCaptureData, dwCaptureLength, pbCaptureData2, dwCaptureLength2);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
_tprintf(_T("Failed to unlock sound capture buffer\n"));
|
||||
wf_rdpsnd_unlock();
|
||||
return 0;
|
||||
}
|
||||
|
||||
//TODO keep track of location in buffer
|
||||
lastPos += dwCaptureLength;
|
||||
lastPos %= dscbd.dwBufferBytes;
|
||||
lastPos += dwCaptureLength2;
|
||||
lastPos %= dscbd.dwBufferBytes;
|
||||
|
||||
wf_rdpsnd_unlock();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
_tprintf(_T("Trying to stop sound capture\n"));
|
||||
hr = capBuf->lpVtbl->Stop(capBuf);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
_tprintf(_T("Failed to stop capture\n"));
|
||||
}
|
||||
_tprintf(_T("Capture stopped\n"));
|
||||
capBuf->lpVtbl->Release(capBuf);
|
||||
cap->lpVtbl->Release(cap);
|
||||
|
||||
lastPos = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -30,7 +30,6 @@ int wf_rdpsnd_lock(void);
|
|||
int wf_rdpsnd_unlock(void);
|
||||
BOOL wf_peer_rdpsnd_init(wfPeerContext* context);
|
||||
|
||||
DWORD WINAPI wf_rdpsnd_thread(LPVOID lpParam);
|
||||
|
||||
#endif /* WF_RDPSND_H */
|
||||
|
||||
|
|
|
@ -0,0 +1,333 @@
|
|||
|
||||
#include "wf_wasapi.h"
|
||||
#include "wf_info.h"
|
||||
|
||||
#include <initguid.h>
|
||||
#include <mmdeviceapi.h>
|
||||
#include <Functiondiscoverykeys_devpkey.h>
|
||||
#include <Audioclient.h>
|
||||
|
||||
//#define REFTIMES_PER_SEC 10000000
|
||||
//#define REFTIMES_PER_MILLISEC 10000
|
||||
|
||||
#define REFTIMES_PER_SEC 100000
|
||||
#define REFTIMES_PER_MILLISEC 100
|
||||
|
||||
//#define REFTIMES_PER_SEC 50000
|
||||
//#define REFTIMES_PER_MILLISEC 50
|
||||
|
||||
|
||||
DEFINE_GUID(CLSID_MMDeviceEnumerator, 0xBCDE0395, 0xE52F, 0x467C,
|
||||
0x8E, 0x3D, 0xC4, 0x57, 0x92, 0x91, 0x69, 0x2E);
|
||||
DEFINE_GUID(IID_IMMDeviceEnumerator, 0xA95664D2, 0x9614, 0x4F35,
|
||||
0xA7, 0x46, 0xDE, 0x8D, 0xB6, 0x36, 0x17, 0xE6);
|
||||
DEFINE_GUID(IID_IAudioClient, 0x1cb9ad4c, 0xdbfa, 0x4c32, 0xb1,0x78, 0xc2,0xf5,0x68,0xa7,0x03,0xb2);
|
||||
DEFINE_GUID(IID_IAudioCaptureClient, 0xc8adbd64, 0xe71e, 0x48a0, 0xa4,0xde, 0x18,0x5c,0x39,0x5c,0xd3,0x17);
|
||||
|
||||
LPWSTR devStr = NULL;
|
||||
wfPeerContext* latestPeer = NULL;
|
||||
|
||||
int wf_rdpsnd_set_latest_peer(wfPeerContext* peer)
|
||||
{
|
||||
latestPeer = peer;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int wf_wasapi_activate(rdpsnd_server_context* context)
|
||||
{
|
||||
wchar_t * pattern = L"Stereo Mix";
|
||||
|
||||
wf_wasapi_get_device_string(pattern, &devStr);
|
||||
|
||||
if(devStr == NULL)
|
||||
{
|
||||
_tprintf(_T("Failed to match for output device! Disabling rdpsnd.\n"));
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("RDPSND (WASAPI) Activated\n");
|
||||
|
||||
context->SelectFormat(context, 4);
|
||||
context->SetVolume(context, 0x7FFF, 0x7FFF);
|
||||
|
||||
CreateThread(NULL, 0, wf_rdpsnd_wasapi_thread, latestPeer, 0, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int wf_wasapi_get_device_string(LPWSTR pattern, LPWSTR * deviceStr)
|
||||
{
|
||||
HRESULT hr;
|
||||
IMMDeviceEnumerator *pEnumerator = NULL;
|
||||
IMMDeviceCollection *pCollection = NULL;
|
||||
IMMDevice *pEndpoint = NULL;
|
||||
IPropertyStore *pProps = NULL;
|
||||
LPWSTR pwszID = NULL;
|
||||
unsigned int count, i;
|
||||
|
||||
CoInitialize(NULL);
|
||||
hr = CoCreateInstance(&CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL, &IID_IMMDeviceEnumerator, (void **) &pEnumerator);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
_tprintf(_T("Failed to cocreate device enumerator\n"));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
hr = pEnumerator->lpVtbl->EnumAudioEndpoints(pEnumerator, eCapture, DEVICE_STATE_ACTIVE, &pCollection);
|
||||
if ( FAILED(hr) )
|
||||
{
|
||||
_tprintf(_T("Failed to create endpoint collection\n"));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
pCollection->lpVtbl->GetCount(pCollection, &count);
|
||||
_tprintf(_T("Num endpoints: %d\n"), count);
|
||||
|
||||
if (count == 0)
|
||||
{
|
||||
_tprintf(_T("No endpoints!\n"));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
for (i = 0; i < count; ++i)
|
||||
{
|
||||
PROPVARIANT nameVar;
|
||||
PropVariantInit(&nameVar);
|
||||
|
||||
hr = pCollection->lpVtbl->Item(pCollection, i, &pEndpoint);
|
||||
if ( FAILED(hr) )
|
||||
{
|
||||
_tprintf(_T("Failed to get endpoint %d\n"), i);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
hr = pEndpoint->lpVtbl->GetId(pEndpoint, &pwszID);
|
||||
if ( FAILED(hr) )
|
||||
{
|
||||
_tprintf(_T("Failed to get endpoint ID\n"));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
hr = pEndpoint->lpVtbl->OpenPropertyStore(pEndpoint, STGM_READ, &pProps);
|
||||
if ( FAILED(hr) )
|
||||
{
|
||||
_tprintf(_T("Failed to open property store\n"));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
hr = pProps->lpVtbl->GetValue(pProps, &PKEY_Device_FriendlyName, &nameVar);
|
||||
if ( FAILED(hr) )
|
||||
{
|
||||
_tprintf(_T("Failed to get device friendly name\n"));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
//do this a more reliable way
|
||||
if (wcscmp(pattern, nameVar.pwszVal) < 0)
|
||||
{
|
||||
unsigned int devStrLen;
|
||||
_tprintf(_T("Using sound ouput endpoint: [%s] (%s)\n"), nameVar.pwszVal, pwszID);
|
||||
//_tprintf(_T("matched %d characters\n"), wcscmp(pattern, nameVar.pwszVal));
|
||||
|
||||
devStrLen = wcslen(pwszID);
|
||||
*deviceStr = (LPWSTR) malloc((devStrLen * 2) + 2);
|
||||
ZeroMemory(*deviceStr, (devStrLen * 2) + 2);
|
||||
wcscpy_s(*deviceStr, devStrLen+1, pwszID);
|
||||
}
|
||||
CoTaskMemFree(pwszID);
|
||||
pwszID = NULL;
|
||||
PropVariantClear(&nameVar);
|
||||
|
||||
pProps->lpVtbl->Release(pProps);
|
||||
pProps = NULL;
|
||||
|
||||
pEndpoint->lpVtbl->Release(pEndpoint);
|
||||
pEndpoint = NULL;
|
||||
|
||||
}
|
||||
|
||||
pCollection->lpVtbl->Release(pCollection);
|
||||
pCollection = NULL;
|
||||
|
||||
pEnumerator->lpVtbl->Release(pEnumerator);
|
||||
pEnumerator = NULL;
|
||||
CoUninitialize();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
DWORD WINAPI wf_rdpsnd_wasapi_thread(LPVOID lpParam)
|
||||
{
|
||||
IMMDeviceEnumerator *pEnumerator = NULL;
|
||||
IMMDevice *pDevice = NULL;
|
||||
IAudioClient *pAudioClient = NULL;
|
||||
IAudioCaptureClient *pCaptureClient = NULL;
|
||||
WAVEFORMATEX *pwfx = NULL;
|
||||
HRESULT hr;
|
||||
REFERENCE_TIME hnsRequestedDuration = REFTIMES_PER_SEC;
|
||||
REFERENCE_TIME hnsActualDuration;
|
||||
UINT32 bufferFrameCount;
|
||||
UINT32 numFramesAvailable;
|
||||
UINT32 packetLength = 0;
|
||||
UINT32 dCount = 0;
|
||||
BYTE *pData;
|
||||
|
||||
wfPeerContext* context;
|
||||
wfInfo* wfi;
|
||||
|
||||
wfi = wf_info_get_instance();
|
||||
context = (wfPeerContext*)lpParam;
|
||||
|
||||
CoInitialize(NULL);
|
||||
hr = CoCreateInstance(&CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL, &IID_IMMDeviceEnumerator, (void **) &pEnumerator);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
_tprintf(_T("Failed to cocreate device enumerator\n"));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
hr = pEnumerator->lpVtbl->GetDevice(pEnumerator, devStr, &pDevice);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
_tprintf(_T("Failed to cocreate get device\n"));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
hr = pDevice->lpVtbl->Activate(pDevice, &IID_IAudioClient, CLSCTX_ALL, NULL, (void **)&pAudioClient);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
_tprintf(_T("Failed to activate audio client\n"));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
hr = pAudioClient->lpVtbl->GetMixFormat(pAudioClient, &pwfx);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
_tprintf(_T("Failed to get mix format\n"));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
//screw it, use our own format
|
||||
//WAVEFORMATEX wfx = {WAVE_FORMAT_PCM, 2, 44100, 176400, 4, 16, 0};
|
||||
pwfx->wFormatTag = WAVE_FORMAT_PCM;
|
||||
pwfx->nChannels = 2;
|
||||
pwfx->nSamplesPerSec = 44100;
|
||||
pwfx->nAvgBytesPerSec = 176400;
|
||||
pwfx->nBlockAlign = 4;
|
||||
pwfx->wBitsPerSample = 16;
|
||||
pwfx->cbSize = 0;
|
||||
|
||||
hr = pAudioClient->lpVtbl->Initialize(
|
||||
pAudioClient,
|
||||
AUDCLNT_SHAREMODE_SHARED,
|
||||
0,
|
||||
hnsRequestedDuration,
|
||||
0,
|
||||
pwfx,
|
||||
NULL);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
_tprintf(_T("Failed to initialize the audio client\n"));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
hr = pAudioClient->lpVtbl->GetBufferSize(pAudioClient, &bufferFrameCount);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
_tprintf(_T("Failed to get buffer size\n"));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
hr = pAudioClient->lpVtbl->GetService(pAudioClient, &IID_IAudioCaptureClient, (void **) &pCaptureClient);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
_tprintf(_T("Failed to get the capture client\n"));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
hnsActualDuration = (UINT32)REFTIMES_PER_SEC * bufferFrameCount / pwfx->nSamplesPerSec;
|
||||
|
||||
hr = pAudioClient->lpVtbl->Start(pAudioClient);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
_tprintf(_T("Failed to start capture\n"));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
dCount = 0;
|
||||
while(wfi->snd_stop == FALSE)
|
||||
{
|
||||
DWORD flags;
|
||||
|
||||
|
||||
Sleep(hnsActualDuration/REFTIMES_PER_MILLISEC/2);
|
||||
|
||||
hr = pCaptureClient->lpVtbl->GetNextPacketSize(pCaptureClient, &packetLength);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
_tprintf(_T("Failed to get packet length\n"));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
while(packetLength != 0)
|
||||
{
|
||||
hr = pCaptureClient->lpVtbl->GetBuffer(pCaptureClient, &pData, &numFramesAvailable, &flags, NULL, NULL);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
_tprintf(_T("Failed to get buffer\n"));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
//Here we are writing the audio data
|
||||
//not sure if this flag is ever set by the system; msdn is not clear about it
|
||||
if (!(flags & AUDCLNT_BUFFERFLAGS_SILENT))
|
||||
context->rdpsnd->SendSamples(context->rdpsnd, pData, packetLength);
|
||||
|
||||
hr = pCaptureClient->lpVtbl->ReleaseBuffer(pCaptureClient, numFramesAvailable);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
_tprintf(_T("Failed to release buffer\n"));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
hr = pCaptureClient->lpVtbl->GetNextPacketSize(pCaptureClient, &packetLength);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
_tprintf(_T("Failed to get packet length\n"));
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pAudioClient->lpVtbl->Stop(pAudioClient);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
_tprintf(_T("Failed to stop audio client\n"));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
CoTaskMemFree(pwfx);
|
||||
|
||||
if (pEnumerator != NULL)
|
||||
pEnumerator->lpVtbl->Release(pEnumerator);
|
||||
|
||||
if (pDevice != NULL)
|
||||
pDevice->lpVtbl->Release(pDevice);
|
||||
|
||||
if (pAudioClient != NULL)
|
||||
pAudioClient->lpVtbl->Release(pAudioClient);
|
||||
|
||||
if (pCaptureClient != NULL)
|
||||
pCaptureClient->lpVtbl->Release(pCaptureClient);
|
||||
|
||||
CoUninitialize();
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
#ifndef WF_WASAPI_H
|
||||
#define WF_WASAPI_H
|
||||
|
||||
#include <freerdp/server/rdpsnd.h>
|
||||
#include "wf_interface.h"
|
||||
|
||||
int wf_rdpsnd_set_latest_peer(wfPeerContext* peer);
|
||||
|
||||
int wf_wasapi_activate(rdpsnd_server_context* context);
|
||||
|
||||
int wf_wasapi_get_device_string(LPWSTR pattern, LPWSTR * deviceStr);
|
||||
|
||||
DWORD WINAPI wf_rdpsnd_wasapi_thread(LPVOID lpParam);
|
||||
|
||||
#endif
|
|
@ -22,7 +22,6 @@ include_directories(${X11_INCLUDE_DIRS})
|
|||
|
||||
set(${MODULE_PREFIX}_SRCS
|
||||
xf_peer.c
|
||||
xf_event.c
|
||||
xf_input.c
|
||||
xf_encode.c
|
||||
xfreerdp.c)
|
||||
|
|
|
@ -38,25 +38,12 @@ XImage* xf_snapshot(xfPeerContext* xfp, int x, int y, int width, int height)
|
|||
|
||||
if (xfi->use_xshm)
|
||||
{
|
||||
pthread_mutex_lock(&(xfp->mutex));
|
||||
|
||||
XCopyArea(xfi->display, xfi->root_window, xfi->fb_pixmap,
|
||||
xfi->xdamage_gc, x, y, width, height, x, y);
|
||||
|
||||
XSync(xfi->display, False);
|
||||
|
||||
XCopyArea(xfi->display, xfi->root_window, xfi->fb_pixmap, xfi->xdamage_gc, x, y, width, height, x, y);
|
||||
image = xfi->fb_image;
|
||||
|
||||
pthread_mutex_unlock(&(xfp->mutex));
|
||||
}
|
||||
else
|
||||
{
|
||||
pthread_mutex_lock(&(xfp->mutex));
|
||||
|
||||
image = XGetImage(xfi->display, xfi->root_window,
|
||||
x, y, width, height, AllPlanes, ZPixmap);
|
||||
|
||||
pthread_mutex_unlock(&(xfp->mutex));
|
||||
image = XGetImage(xfi->display, xfi->root_window, x, y, width, height, AllPlanes, ZPixmap);
|
||||
}
|
||||
|
||||
return image;
|
||||
|
@ -73,17 +60,15 @@ void xf_xdamage_subtract_region(xfPeerContext* xfp, int x, int y, int width, int
|
|||
region.height = height;
|
||||
|
||||
#ifdef WITH_XFIXES
|
||||
pthread_mutex_lock(&(xfp->mutex));
|
||||
XFixesSetRegion(xfi->display, xfi->xdamage_region, ®ion, 1);
|
||||
XDamageSubtract(xfi->display, xfi->xdamage, xfi->xdamage_region, None);
|
||||
pthread_mutex_unlock(&(xfp->mutex));
|
||||
#endif
|
||||
}
|
||||
|
||||
void* xf_frame_rate_thread(void* param)
|
||||
{
|
||||
xfInfo* xfi;
|
||||
xfEvent* event;
|
||||
HGDI_RGN region;
|
||||
xfPeerContext* xfp;
|
||||
freerdp_peer* client;
|
||||
UINT32 wait_interval;
|
||||
|
@ -92,17 +77,35 @@ void* xf_frame_rate_thread(void* param)
|
|||
xfp = (xfPeerContext*) client->context;
|
||||
xfi = xfp->info;
|
||||
|
||||
region = xfp->hdc->hwnd->invalid;
|
||||
wait_interval = 1000000 / xfp->fps;
|
||||
|
||||
while (1)
|
||||
{
|
||||
/* check if we should terminate */
|
||||
pthread_testcancel();
|
||||
|
||||
event = xf_event_new(XF_EVENT_TYPE_FRAME_TICK);
|
||||
xf_event_push(xfp->event_queue, (xfEvent*) event);
|
||||
|
||||
if (!region->null)
|
||||
{
|
||||
UINT32 xy, wh;
|
||||
|
||||
pthread_mutex_lock(&(xfp->mutex));
|
||||
|
||||
xy = (region->x << 16) | region->y;
|
||||
wh = (region->w << 16) | region->h;
|
||||
region->null = 1;
|
||||
|
||||
pthread_mutex_unlock(&(xfp->mutex));
|
||||
|
||||
MessageQueue_Post(xfp->queue, (void*) xfp,
|
||||
MakeMessageId(PeerEvent, EncodeRegion),
|
||||
(void*) (size_t) xy, (void*) (size_t) wh);
|
||||
}
|
||||
|
||||
USleep(wait_interval);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void* xf_monitor_updates(void* param)
|
||||
|
@ -112,22 +115,20 @@ void* xf_monitor_updates(void* param)
|
|||
XEvent xevent;
|
||||
fd_set rfds_set;
|
||||
int select_status;
|
||||
int pending_events;
|
||||
xfPeerContext* xfp;
|
||||
freerdp_peer* client;
|
||||
UINT32 wait_interval;
|
||||
struct timeval timeout;
|
||||
int x, y, width, height;
|
||||
XDamageNotifyEvent* notify;
|
||||
xfEventRegion* event_region;
|
||||
|
||||
client = (freerdp_peer*) param;
|
||||
xfp = (xfPeerContext*) client->context;
|
||||
xfi = xfp->info;
|
||||
|
||||
fds = xfi->xfds;
|
||||
wait_interval = (1000000 / 2500);
|
||||
memset(&timeout, 0, sizeof(struct timeval));
|
||||
wait_interval = 1000000 / xfp->fps;
|
||||
ZeroMemory(&timeout, sizeof(struct timeval));
|
||||
|
||||
pthread_create(&(xfp->frame_rate_thread), 0, xf_frame_rate_thread, (void*) client);
|
||||
|
||||
|
@ -149,19 +150,13 @@ void* xf_monitor_updates(void* param)
|
|||
}
|
||||
else if (select_status == 0)
|
||||
{
|
||||
//printf("select timeout\n");
|
||||
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&(xfp->mutex));
|
||||
pending_events = XPending(xfi->display);
|
||||
pthread_mutex_unlock(&(xfp->mutex));
|
||||
|
||||
if (pending_events > 0)
|
||||
while (XPending(xfi->display) > 0)
|
||||
{
|
||||
pthread_mutex_lock(&(xfp->mutex));
|
||||
memset(&xevent, 0, sizeof(xevent));
|
||||
ZeroMemory(&xevent, sizeof(xevent));
|
||||
XNextEvent(xfi->display, &xevent);
|
||||
pthread_mutex_unlock(&(xfp->mutex));
|
||||
|
||||
if (xevent.type == xfi->xdamage_notify_event)
|
||||
{
|
||||
|
@ -172,10 +167,11 @@ void* xf_monitor_updates(void* param)
|
|||
width = notify->area.width;
|
||||
height = notify->area.height;
|
||||
|
||||
xf_xdamage_subtract_region(xfp, x, y, width, height);
|
||||
pthread_mutex_lock(&(xfp->mutex));
|
||||
gdi_InvalidateRegion(xfp->hdc, x, y, width, height);
|
||||
pthread_mutex_unlock(&(xfp->mutex));
|
||||
|
||||
event_region = xf_event_region_new(x, y, width, height);
|
||||
xf_event_push(xfp->event_queue, (xfEvent*) event_region);
|
||||
xf_xdamage_subtract_region(xfp, x, y, width, height);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,225 +0,0 @@
|
|||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* X11 Server Event Handling
|
||||
*
|
||||
* Copyright 2011 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 <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <X11/Xlib.h>
|
||||
|
||||
#include <winpr/crt.h>
|
||||
|
||||
#include "xf_event.h"
|
||||
|
||||
int xf_is_event_set(xfEventQueue* event_queue)
|
||||
{
|
||||
fd_set rfds;
|
||||
int num_set;
|
||||
struct timeval time;
|
||||
|
||||
FD_ZERO(&rfds);
|
||||
FD_SET(event_queue->pipe_fd[0], &rfds);
|
||||
memset(&time, 0, sizeof(time));
|
||||
num_set = select(event_queue->pipe_fd[0] + 1, &rfds, 0, 0, &time);
|
||||
|
||||
return (num_set == 1);
|
||||
}
|
||||
|
||||
void xf_signal_event(xfEventQueue* event_queue)
|
||||
{
|
||||
int length;
|
||||
|
||||
length = write(event_queue->pipe_fd[1], "sig", 4);
|
||||
|
||||
if (length != 4)
|
||||
printf("xf_signal_event: error\n");
|
||||
}
|
||||
|
||||
void xf_set_event(xfEventQueue* event_queue)
|
||||
{
|
||||
int length;
|
||||
|
||||
length = write(event_queue->pipe_fd[1], "sig", 4);
|
||||
|
||||
if (length != 4)
|
||||
printf("xf_set_event: error\n");
|
||||
}
|
||||
|
||||
void xf_clear_events(xfEventQueue* event_queue)
|
||||
{
|
||||
int length;
|
||||
|
||||
while (xf_is_event_set(event_queue))
|
||||
{
|
||||
length = read(event_queue->pipe_fd[0], &length, 4);
|
||||
|
||||
if (length != 4)
|
||||
printf("xf_clear_event: error\n");
|
||||
}
|
||||
}
|
||||
|
||||
void xf_clear_event(xfEventQueue* event_queue)
|
||||
{
|
||||
int length;
|
||||
|
||||
length = read(event_queue->pipe_fd[0], &length, 4);
|
||||
|
||||
if (length != 4)
|
||||
printf("xf_clear_event: error\n");
|
||||
}
|
||||
|
||||
void xf_event_push(xfEventQueue* event_queue, xfEvent* event)
|
||||
{
|
||||
pthread_mutex_lock(&(event_queue->mutex));
|
||||
|
||||
if (event_queue->count >= event_queue->size)
|
||||
{
|
||||
event_queue->size *= 2;
|
||||
event_queue->events = (xfEvent**) realloc((void*) event_queue->events, sizeof(xfEvent*) * event_queue->size);
|
||||
}
|
||||
|
||||
event_queue->events[(event_queue->count)++] = event;
|
||||
|
||||
pthread_mutex_unlock(&(event_queue->mutex));
|
||||
|
||||
xf_set_event(event_queue);
|
||||
}
|
||||
|
||||
xfEvent* xf_event_peek(xfEventQueue* event_queue)
|
||||
{
|
||||
xfEvent* event;
|
||||
|
||||
pthread_mutex_lock(&(event_queue->mutex));
|
||||
|
||||
if (event_queue->count < 1)
|
||||
event = NULL;
|
||||
else
|
||||
event = event_queue->events[0];
|
||||
|
||||
pthread_mutex_unlock(&(event_queue->mutex));
|
||||
|
||||
return event;
|
||||
}
|
||||
|
||||
xfEvent* xf_event_pop(xfEventQueue* event_queue)
|
||||
{
|
||||
xfEvent* event;
|
||||
|
||||
pthread_mutex_lock(&(event_queue->mutex));
|
||||
|
||||
if (event_queue->count < 1)
|
||||
return NULL;
|
||||
|
||||
/* remove event signal */
|
||||
xf_clear_event(event_queue);
|
||||
|
||||
event = event_queue->events[0];
|
||||
(event_queue->count)--;
|
||||
|
||||
memmove(&event_queue->events[0], &event_queue->events[1], event_queue->count * sizeof(void*));
|
||||
|
||||
pthread_mutex_unlock(&(event_queue->mutex));
|
||||
|
||||
return event;
|
||||
}
|
||||
|
||||
xfEventRegion* xf_event_region_new(int x, int y, int width, int height)
|
||||
{
|
||||
xfEventRegion* event_region;
|
||||
|
||||
event_region = (xfEventRegion*) malloc(sizeof(xfEventRegion));
|
||||
ZeroMemory(event_region, sizeof(xfEventRegion));
|
||||
|
||||
if (event_region != NULL)
|
||||
{
|
||||
event_region->x = x;
|
||||
event_region->y = y;
|
||||
event_region->width = width;
|
||||
event_region->height = height;
|
||||
}
|
||||
|
||||
return event_region;
|
||||
}
|
||||
|
||||
void xf_event_region_free(xfEventRegion* event_region)
|
||||
{
|
||||
free(event_region);
|
||||
}
|
||||
|
||||
xfEvent* xf_event_new(int type)
|
||||
{
|
||||
xfEvent* event;
|
||||
event = (xfEvent*) malloc(sizeof(xfEvent));
|
||||
ZeroMemory(event, sizeof(xfEvent));
|
||||
event->type = type;
|
||||
return event;
|
||||
}
|
||||
|
||||
void xf_event_free(xfEvent* event)
|
||||
{
|
||||
free(event);
|
||||
}
|
||||
|
||||
xfEventQueue* xf_event_queue_new()
|
||||
{
|
||||
xfEventQueue* event_queue;
|
||||
|
||||
event_queue = (xfEventQueue*) malloc(sizeof(xfEventQueue));
|
||||
ZeroMemory(event_queue, sizeof(xfEventQueue));
|
||||
|
||||
if (event_queue != NULL)
|
||||
{
|
||||
event_queue->pipe_fd[0] = -1;
|
||||
event_queue->pipe_fd[1] = -1;
|
||||
|
||||
event_queue->size = 16;
|
||||
event_queue->count = 0;
|
||||
event_queue->events = (xfEvent**) malloc(sizeof(xfEvent*) * event_queue->size);
|
||||
ZeroMemory(event_queue->events, sizeof(xfEvent*) * event_queue->size);
|
||||
|
||||
if (pipe(event_queue->pipe_fd) < 0)
|
||||
printf("xf_event_queue_new: pipe failed\n");
|
||||
|
||||
pthread_mutex_init(&(event_queue->mutex), NULL);
|
||||
}
|
||||
|
||||
return event_queue;
|
||||
}
|
||||
|
||||
void xf_event_queue_free(xfEventQueue* event_queue)
|
||||
{
|
||||
if (event_queue->pipe_fd[0] != -1)
|
||||
{
|
||||
close(event_queue->pipe_fd[0]);
|
||||
event_queue->pipe_fd[0] = -1;
|
||||
}
|
||||
|
||||
if (event_queue->pipe_fd[1] != -1)
|
||||
{
|
||||
close(event_queue->pipe_fd[1]);
|
||||
event_queue->pipe_fd[1] = -1;
|
||||
}
|
||||
|
||||
pthread_mutex_destroy(&(event_queue->mutex));
|
||||
}
|
|
@ -1,75 +0,0 @@
|
|||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* X11 Server Event Handling
|
||||
*
|
||||
* Copyright 2011 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_EVENT_H
|
||||
#define __XF_EVENT_H
|
||||
|
||||
typedef struct xf_event xfEvent;
|
||||
typedef struct xf_event_queue xfEventQueue;
|
||||
typedef struct xf_event_region xfEventRegion;
|
||||
|
||||
#include <pthread.h>
|
||||
#include "xfreerdp.h"
|
||||
|
||||
#include "xf_peer.h"
|
||||
|
||||
enum xf_event_type
|
||||
{
|
||||
XF_EVENT_TYPE_REGION,
|
||||
XF_EVENT_TYPE_FRAME_TICK
|
||||
};
|
||||
|
||||
struct xf_event
|
||||
{
|
||||
int type;
|
||||
};
|
||||
|
||||
struct xf_event_queue
|
||||
{
|
||||
int size;
|
||||
int count;
|
||||
int pipe_fd[2];
|
||||
xfEvent** events;
|
||||
pthread_mutex_t mutex;
|
||||
};
|
||||
|
||||
struct xf_event_region
|
||||
{
|
||||
int type;
|
||||
|
||||
int x;
|
||||
int y;
|
||||
int width;
|
||||
int height;
|
||||
};
|
||||
|
||||
void xf_event_push(xfEventQueue* event_queue, xfEvent* event);
|
||||
xfEvent* xf_event_peek(xfEventQueue* event_queue);
|
||||
xfEvent* xf_event_pop(xfEventQueue* event_queue);
|
||||
|
||||
xfEventRegion* xf_event_region_new(int x, int y, int width, int height);
|
||||
void xf_event_region_free(xfEventRegion* event_region);
|
||||
|
||||
xfEvent* xf_event_new(int type);
|
||||
void xf_event_free(xfEvent* event);
|
||||
|
||||
xfEventQueue* xf_event_queue_new(void);
|
||||
void xf_event_queue_free(xfEventQueue* event_queue);
|
||||
|
||||
#endif /* __XF_EVENT_H */
|
|
@ -25,6 +25,8 @@
|
|||
|
||||
#include <freerdp/locale/keyboard.h>
|
||||
|
||||
#include "xf_peer.h"
|
||||
|
||||
#include "xf_input.h"
|
||||
|
||||
void xf_input_synchronize_event(rdpInput* input, UINT32 flags)
|
||||
|
@ -47,8 +49,6 @@ void xf_input_keyboard_event(rdpInput* input, UINT16 flags, UINT16 code)
|
|||
|
||||
if (keycode != 0)
|
||||
{
|
||||
pthread_mutex_lock(&(xfp->mutex));
|
||||
|
||||
XTestGrabControl(xfi->display, True);
|
||||
|
||||
if (flags & KBD_FLAGS_DOWN)
|
||||
|
@ -57,8 +57,6 @@ void xf_input_keyboard_event(rdpInput* input, UINT16 flags, UINT16 code)
|
|||
XTestFakeKeyEvent(xfi->display, keycode, False, 0);
|
||||
|
||||
XTestGrabControl(xfi->display, False);
|
||||
|
||||
pthread_mutex_unlock(&(xfp->mutex));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -76,7 +74,6 @@ void xf_input_mouse_event(rdpInput* input, UINT16 flags, UINT16 x, UINT16 y)
|
|||
BOOL down = FALSE;
|
||||
xfInfo* xfi = xfp->info;
|
||||
|
||||
pthread_mutex_lock(&(xfp->mutex));
|
||||
XTestGrabControl(xfi->display, True);
|
||||
|
||||
if (flags & PTR_FLAGS_WHEEL)
|
||||
|
@ -111,7 +108,6 @@ void xf_input_mouse_event(rdpInput* input, UINT16 flags, UINT16 x, UINT16 y)
|
|||
}
|
||||
|
||||
XTestGrabControl(xfi->display, False);
|
||||
pthread_mutex_unlock(&(xfp->mutex));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -121,11 +117,9 @@ void xf_input_extended_mouse_event(rdpInput* input, UINT16 flags, UINT16 x, UINT
|
|||
xfPeerContext* xfp = (xfPeerContext*) input->context;
|
||||
xfInfo* xfi = xfp->info;
|
||||
|
||||
pthread_mutex_lock(&(xfp->mutex));
|
||||
XTestGrabControl(xfi->display, True);
|
||||
XTestFakeMotionEvent(xfi->display, 0, x, y, CurrentTime);
|
||||
XTestGrabControl(xfi->display, False);
|
||||
pthread_mutex_unlock(&(xfp->mutex));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -41,10 +41,6 @@
|
|||
#include <freerdp/utils/file.h>
|
||||
#include <freerdp/utils/thread.h>
|
||||
|
||||
extern char* xf_pcap_file;
|
||||
extern BOOL xf_pcap_dump_realtime;
|
||||
|
||||
#include "xf_event.h"
|
||||
#include "xf_input.h"
|
||||
#include "xf_encode.h"
|
||||
|
||||
|
@ -134,7 +130,7 @@ void xf_xshm_init(xfInfo* xfi)
|
|||
xfi->fb_image = XShmCreateImage(xfi->display, xfi->visual, xfi->depth,
|
||||
ZPixmap, NULL, &(xfi->fb_shm_info), xfi->width, xfi->height);
|
||||
|
||||
if (xfi->fb_image == NULL)
|
||||
if (!xfi->fb_image)
|
||||
{
|
||||
printf("XShmCreateImage failed\n");
|
||||
return;
|
||||
|
@ -199,7 +195,7 @@ xfInfo* xf_info_init()
|
|||
|
||||
xfi->display = XOpenDisplay(NULL);
|
||||
|
||||
if (xfi->display == NULL)
|
||||
if (!xfi->display)
|
||||
{
|
||||
printf("failed to open display: %s\n", XDisplayName(NULL));
|
||||
exit(1);
|
||||
|
@ -215,7 +211,7 @@ xfInfo* xf_info_init()
|
|||
|
||||
pfs = XListPixmapFormats(xfi->display, &pf_count);
|
||||
|
||||
if (pfs == NULL)
|
||||
if (!pfs)
|
||||
{
|
||||
printf("XListPixmapFormats failed\n");
|
||||
exit(1);
|
||||
|
@ -234,7 +230,7 @@ xfInfo* xf_info_init()
|
|||
}
|
||||
XFree(pfs);
|
||||
|
||||
memset(&template, 0, sizeof(template));
|
||||
ZeroMemory(&template, sizeof(template));
|
||||
template.class = TrueColor;
|
||||
template.screen = xfi->number;
|
||||
|
||||
|
@ -310,10 +306,11 @@ void xf_peer_init(freerdp_peer* client)
|
|||
|
||||
xfp = (xfPeerContext*) client->context;
|
||||
|
||||
xfp->fps = 24;
|
||||
xfp->fps = 16;
|
||||
xfp->thread = 0;
|
||||
xfp->activations = 0;
|
||||
xfp->event_queue = xf_event_queue_new();
|
||||
|
||||
xfp->queue = MessageQueue_New();
|
||||
|
||||
xfi = xfp->info;
|
||||
xfp->hdc = gdi_CreateDC(xfi->clrconv, xfi->bpp);
|
||||
|
@ -331,85 +328,9 @@ STREAM* xf_peer_stream_init(xfPeerContext* context)
|
|||
void xf_peer_live_rfx(freerdp_peer* client)
|
||||
{
|
||||
xfPeerContext* xfp = (xfPeerContext*) client->context;
|
||||
|
||||
pthread_create(&(xfp->thread), 0, xf_monitor_updates, (void*) client);
|
||||
}
|
||||
|
||||
static BOOL xf_peer_sleep_tsdiff(UINT32 *old_sec, UINT32 *old_usec, UINT32 new_sec, UINT32 new_usec)
|
||||
{
|
||||
INT32 sec, usec;
|
||||
|
||||
if (*old_sec == 0 && *old_usec == 0)
|
||||
{
|
||||
*old_sec = new_sec;
|
||||
*old_usec = new_usec;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
sec = new_sec - *old_sec;
|
||||
usec = new_usec - *old_usec;
|
||||
|
||||
if (sec < 0 || (sec == 0 && usec < 0))
|
||||
{
|
||||
printf("Invalid time stamp detected.\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
*old_sec = new_sec;
|
||||
*old_usec = new_usec;
|
||||
|
||||
while (usec < 0)
|
||||
{
|
||||
usec += 1000000;
|
||||
sec--;
|
||||
}
|
||||
|
||||
if (sec > 0)
|
||||
Sleep(sec * 1000);
|
||||
|
||||
if (usec > 0)
|
||||
USleep(usec);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void xf_peer_dump_rfx(freerdp_peer* client)
|
||||
{
|
||||
STREAM* s;
|
||||
UINT32 prev_seconds;
|
||||
UINT32 prev_useconds;
|
||||
rdpUpdate* update;
|
||||
rdpPcap* pcap_rfx;
|
||||
pcap_record record;
|
||||
|
||||
s = stream_new(512);
|
||||
update = client->update;
|
||||
client->update->pcap_rfx = pcap_open(xf_pcap_file, FALSE);
|
||||
pcap_rfx = client->update->pcap_rfx;
|
||||
|
||||
if (pcap_rfx == NULL)
|
||||
return;
|
||||
|
||||
prev_seconds = prev_useconds = 0;
|
||||
|
||||
while (pcap_has_next_record(pcap_rfx))
|
||||
{
|
||||
pcap_get_next_record_header(pcap_rfx, &record);
|
||||
|
||||
s->data = realloc(s->data, record.length);
|
||||
record.data = s->data;
|
||||
s->size = record.length;
|
||||
|
||||
pcap_get_next_record_content(pcap_rfx, &record);
|
||||
s->p = s->data + s->size;
|
||||
|
||||
if (xf_pcap_dump_realtime && xf_peer_sleep_tsdiff(&prev_seconds, &prev_useconds, record.header.ts_sec, record.header.ts_usec) == FALSE)
|
||||
break;
|
||||
|
||||
update->SurfaceCommand(update->context, s);
|
||||
}
|
||||
}
|
||||
|
||||
void xf_peer_rfx_update(freerdp_peer* client, int x, int y, int width, int height)
|
||||
{
|
||||
STREAM* s;
|
||||
|
@ -437,6 +358,7 @@ void xf_peer_rfx_update(freerdp_peer* client, int x, int y, int width, int heigh
|
|||
* Passing an offset source rectangle to rfx_compose_message()
|
||||
* leads to protocol errors, so offset the data pointer instead.
|
||||
*/
|
||||
|
||||
rect.x = 0;
|
||||
rect.y = 0;
|
||||
rect.width = width;
|
||||
|
@ -465,7 +387,6 @@ void xf_peer_rfx_update(freerdp_peer* client, int x, int y, int width, int heigh
|
|||
image = xf_snapshot(xfp, x, y, width, height);
|
||||
|
||||
data = (BYTE*) image->data;
|
||||
data = &data[(y * image->bytes_per_line) + (x * image->bits_per_pixel / 8)];
|
||||
|
||||
rfx_compose_message(xfp->rfx_context, s, &rect, 1, data,
|
||||
width, height, image->bytes_per_line);
|
||||
|
@ -490,12 +411,13 @@ void xf_peer_rfx_update(freerdp_peer* client, int x, int y, int width, int heigh
|
|||
|
||||
BOOL xf_peer_get_fds(freerdp_peer* client, void** rfds, int* rcount)
|
||||
{
|
||||
int fds;
|
||||
HANDLE event;
|
||||
xfPeerContext* xfp = (xfPeerContext*) client->context;
|
||||
|
||||
if (xfp->event_queue->pipe_fd[0] == -1)
|
||||
return TRUE;
|
||||
|
||||
rfds[*rcount] = (void *)(long) xfp->event_queue->pipe_fd[0];
|
||||
event = MessageQueue_Event(xfp->queue);
|
||||
fds = GetEventFileDescriptor(event);
|
||||
rfds[*rcount] = (void*) (long) fds;
|
||||
(*rcount)++;
|
||||
|
||||
return TRUE;
|
||||
|
@ -504,9 +426,8 @@ BOOL xf_peer_get_fds(freerdp_peer* client, void** rfds, int* rcount)
|
|||
BOOL xf_peer_check_fds(freerdp_peer* client)
|
||||
{
|
||||
xfInfo* xfi;
|
||||
xfEvent* event;
|
||||
wMessage message;
|
||||
xfPeerContext* xfp;
|
||||
HGDI_RGN invalid_region;
|
||||
|
||||
xfp = (xfPeerContext*) client->context;
|
||||
xfi = xfp->info;
|
||||
|
@ -514,31 +435,24 @@ BOOL xf_peer_check_fds(freerdp_peer* client)
|
|||
if (xfp->activated == FALSE)
|
||||
return TRUE;
|
||||
|
||||
event = xf_event_peek(xfp->event_queue);
|
||||
|
||||
if (event != NULL)
|
||||
if (MessageQueue_Peek(xfp->queue, &message, TRUE))
|
||||
{
|
||||
if (event->type == XF_EVENT_TYPE_REGION)
|
||||
if (message.id == MakeMessageId(PeerEvent, EncodeRegion))
|
||||
{
|
||||
xfEventRegion* region = (xfEventRegion*) xf_event_pop(xfp->event_queue);
|
||||
gdi_InvalidateRegion(xfp->hdc, region->x, region->y, region->width, region->height);
|
||||
xf_event_region_free(region);
|
||||
}
|
||||
else if (event->type == XF_EVENT_TYPE_FRAME_TICK)
|
||||
{
|
||||
event = xf_event_pop(xfp->event_queue);
|
||||
invalid_region = xfp->hdc->hwnd->invalid;
|
||||
UINT32 xy, wh;
|
||||
UINT16 x, y, w, h;
|
||||
|
||||
if (invalid_region->null == FALSE)
|
||||
{
|
||||
xf_peer_rfx_update(client, invalid_region->x, invalid_region->y,
|
||||
invalid_region->w, invalid_region->h);
|
||||
}
|
||||
xy = (UINT32) (size_t) message.wParam;
|
||||
wh = (UINT32) (size_t) message.lParam;
|
||||
|
||||
invalid_region->null = 1;
|
||||
xfp->hdc->hwnd->ninvalid = 0;
|
||||
x = ((xy & 0xFFFF0000) >> 16);
|
||||
y = (xy & 0x0000FFFF);
|
||||
|
||||
xf_event_free(event);
|
||||
w = ((wh & 0xFFFF0000) >> 16);
|
||||
h = (wh & 0x0000FFFF);
|
||||
|
||||
if (w * h > 0)
|
||||
xf_peer_rfx_update(client, x, y, w, h);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -602,15 +516,7 @@ BOOL xf_peer_activate(freerdp_peer* client)
|
|||
rfx_context_reset(xfp->rfx_context);
|
||||
xfp->activated = TRUE;
|
||||
|
||||
if (xf_pcap_file != NULL)
|
||||
{
|
||||
client->update->dump_rfx = TRUE;
|
||||
xf_peer_dump_rfx(client);
|
||||
}
|
||||
else
|
||||
{
|
||||
xf_peer_live_rfx(client);
|
||||
}
|
||||
xf_peer_live_rfx(client);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -628,7 +534,7 @@ void* xf_peer_main_loop(void* arg)
|
|||
freerdp_peer* client = (freerdp_peer*) arg;
|
||||
xfPeerContext* xfp;
|
||||
|
||||
memset(rfds, 0, sizeof(rfds));
|
||||
ZeroMemory(rfds, sizeof(rfds));
|
||||
|
||||
printf("We've got a client %s\n", client->hostname);
|
||||
|
||||
|
|
|
@ -20,6 +20,9 @@
|
|||
#ifndef __XF_PEER_H
|
||||
#define __XF_PEER_H
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/collections.h>
|
||||
|
||||
#include <freerdp/gdi/gdi.h>
|
||||
#include <freerdp/gdi/dc.h>
|
||||
#include <freerdp/gdi/region.h>
|
||||
|
@ -32,6 +35,12 @@ typedef struct xf_peer_context xfPeerContext;
|
|||
|
||||
#include "xfreerdp.h"
|
||||
|
||||
#define PeerEvent_Base 0
|
||||
|
||||
#define PeerEvent_Class (PeerEvent_Base + 1)
|
||||
|
||||
#define PeerEvent_EncodeRegion 1
|
||||
|
||||
struct xf_peer_context
|
||||
{
|
||||
rdpContext _p;
|
||||
|
@ -45,8 +54,9 @@ struct xf_peer_context
|
|||
BOOL activated;
|
||||
pthread_mutex_t mutex;
|
||||
RFX_CONTEXT* rfx_context;
|
||||
xfEventQueue* event_queue;
|
||||
pthread_t frame_rate_thread;
|
||||
|
||||
wMessageQueue* queue;
|
||||
};
|
||||
|
||||
void xf_peer_accepted(freerdp_listener* instance, freerdp_peer* client);
|
||||
|
|
|
@ -45,7 +45,7 @@ void xf_server_main_loop(freerdp_listener* instance)
|
|||
void* rfds[32];
|
||||
fd_set rfds_set;
|
||||
|
||||
memset(rfds, 0, sizeof(rfds));
|
||||
ZeroMemory(rfds, sizeof(rfds));
|
||||
|
||||
while (1)
|
||||
{
|
||||
|
|
|
@ -40,8 +40,6 @@
|
|||
|
||||
typedef struct xf_info xfInfo;
|
||||
|
||||
#include "xf_event.h"
|
||||
|
||||
struct xf_info
|
||||
{
|
||||
int bpp;
|
||||
|
|
|
@ -29,13 +29,15 @@
|
|||
|
||||
#include <winpr/synch.h>
|
||||
|
||||
typedef void (*OBJECT_EQUALS_FN)(void* objA, void* objB);
|
||||
typedef void* (*OBJECT_NEW_FN)();
|
||||
typedef void (*OBJECT_FREE_FN)(void* obj);
|
||||
typedef void (*OBJECT_EQUALS_FN)(void* objA, void* objB);
|
||||
|
||||
struct _wObject
|
||||
{
|
||||
OBJECT_EQUALS_FN fnObjectEquals;
|
||||
OBJECT_NEW_FN fnObjectNew;
|
||||
OBJECT_FREE_FN fnObjectFree;
|
||||
OBJECT_EQUALS_FN fnObjectEquals;
|
||||
};
|
||||
typedef struct _wObject wObject;
|
||||
|
||||
|
@ -250,6 +252,28 @@ WINPR_API void BufferPool_Clear(wBufferPool* pool);
|
|||
WINPR_API wBufferPool* BufferPool_New(BOOL synchronized, int fixedSize, DWORD alignment);
|
||||
WINPR_API void BufferPool_Free(wBufferPool* pool);
|
||||
|
||||
/* ObjectPool */
|
||||
|
||||
struct _wObjectPool
|
||||
{
|
||||
int size;
|
||||
int capacity;
|
||||
void** array;
|
||||
HANDLE mutex;
|
||||
wObject object;
|
||||
BOOL synchronized;
|
||||
};
|
||||
typedef struct _wObjectPool wObjectPool;
|
||||
|
||||
WINPR_API void* ObjectPool_Take(wObjectPool* pool);
|
||||
WINPR_API void ObjectPool_Return(wObjectPool* pool, void* obj);
|
||||
WINPR_API void ObjectPool_Clear(wObjectPool* pool);
|
||||
|
||||
#define ObjectPool_Object(_pool) (&_pool->object)
|
||||
|
||||
WINPR_API wObjectPool* ObjectPool_New(BOOL synchronized);
|
||||
WINPR_API void ObjectPool_Free(wObjectPool* pool);
|
||||
|
||||
/* Message Queue */
|
||||
|
||||
struct _wMessage
|
||||
|
@ -277,6 +301,7 @@ typedef struct _wMessageQueue wMessageQueue;
|
|||
|
||||
WINPR_API HANDLE MessageQueue_Event(wMessageQueue* queue);
|
||||
WINPR_API BOOL MessageQueue_Wait(wMessageQueue* queue);
|
||||
WINPR_API int MessageQueue_Size(wMessageQueue* queue);
|
||||
|
||||
WINPR_API void MessageQueue_Dispatch(wMessageQueue* queue, wMessage* message);
|
||||
WINPR_API void MessageQueue_Post(wMessageQueue* queue, void* context, UINT32 type, void* wParam, void* lParam);
|
||||
|
|
|
@ -135,9 +135,9 @@ typedef unsigned int UINT_PTR;
|
|||
|
||||
typedef struct _GUID
|
||||
{
|
||||
unsigned long Data1;
|
||||
unsigned short Data2;
|
||||
unsigned short Data3;
|
||||
UINT32 Data1;
|
||||
UINT16 Data2;
|
||||
UINT16 Data3;
|
||||
BYTE Data4[8];
|
||||
} GUID, UUID, *PGUID;
|
||||
|
||||
|
|
|
@ -41,6 +41,10 @@ set(${MODULE_PREFIX}_SRCS
|
|||
ndr_union.h
|
||||
midl.c)
|
||||
|
||||
if(MSVC AND (NOT MONOLITHIC_BUILD))
|
||||
set(${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_SRCS} module.def)
|
||||
endif()
|
||||
|
||||
add_complex_library(MODULE ${MODULE_NAME} TYPE "OBJECT"
|
||||
MONOLITHIC ${MONOLITHIC_BUILD}
|
||||
SOURCES ${${MODULE_PREFIX}_SRCS})
|
||||
|
@ -55,6 +59,7 @@ set(${MODULE_PREFIX}_LIBS
|
|||
|
||||
if(WIN32)
|
||||
set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} ws2_32)
|
||||
set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} rpcrt4)
|
||||
else()
|
||||
set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} ${ZLIB_LIBRARIES})
|
||||
endif()
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
LIBRARY "libwinpr-rpc"
|
||||
EXPORTS
|
||||
|
|
@ -26,6 +26,14 @@ BYTE test_DummyMessage[64] =
|
|||
0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD
|
||||
};
|
||||
|
||||
BYTE test_LastDummyMessage[64] =
|
||||
{
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
int schannel_send(PSecurityFunctionTable table, HANDLE hPipe, PCtxtHandle phContext, BYTE* buffer, UINT32 length)
|
||||
{
|
||||
BYTE* ioBuffer;
|
||||
|
@ -154,6 +162,9 @@ int schannel_recv(PSecurityFunctionTable table, HANDLE hPipe, PCtxtHandle phCont
|
|||
printf("Decrypted Message (%d)\n", Message.pBuffers[1].cbBuffer);
|
||||
winpr_HexDump((BYTE*) Message.pBuffers[1].pvBuffer, Message.pBuffers[1].cbBuffer);
|
||||
|
||||
if (memcmp(Message.pBuffers[1].pvBuffer, test_LastDummyMessage, sizeof(test_LastDummyMessage)) == 0)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -223,7 +234,7 @@ static void* schannel_test_server_thread(void* arg)
|
|||
|
||||
cchNameString = CertGetNameString(pCertContext, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, NULL, NULL, 0);
|
||||
|
||||
pszNameString = (LPTSTR) malloc(status * sizeof(TCHAR));
|
||||
pszNameString = (LPTSTR) malloc(cchNameString * sizeof(TCHAR));
|
||||
cchNameString = CertGetNameString(pCertContext, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, NULL, pszNameString, cchNameString);
|
||||
|
||||
_tprintf(_T("Certificate Name: %s\n"), pszNameString);
|
||||
|
@ -370,6 +381,7 @@ static void* schannel_test_server_thread(void* arg)
|
|||
|
||||
int TestSchannel(int argc, char* argv[])
|
||||
{
|
||||
int count;
|
||||
int index;
|
||||
ALG_ID algId;
|
||||
HANDLE thread;
|
||||
|
@ -604,6 +616,8 @@ int TestSchannel(int argc, char* argv[])
|
|||
}
|
||||
while(1);
|
||||
|
||||
count = 0;
|
||||
|
||||
do
|
||||
{
|
||||
if (schannel_send(table, g_ServerWritePipe, &context, test_DummyMessage, sizeof(test_DummyMessage)) < 0)
|
||||
|
@ -626,9 +640,12 @@ int TestSchannel(int argc, char* argv[])
|
|||
test_DummyMessage[index] = b;
|
||||
}
|
||||
|
||||
Sleep(1000 * 10);
|
||||
Sleep(100);
|
||||
count++;
|
||||
}
|
||||
while(1);
|
||||
while(count < 3);
|
||||
|
||||
schannel_send(table, g_ServerWritePipe, &context, test_LastDummyMessage, sizeof(test_LastDummyMessage));
|
||||
|
||||
WaitForSingleObject(thread, INFINITE);
|
||||
|
||||
|
|
|
@ -130,11 +130,13 @@ BOOL SetEvent(HANDLE hEvent)
|
|||
|
||||
#ifdef HAVE_EVENTFD_H
|
||||
eventfd_t val = 1;
|
||||
|
||||
do
|
||||
{
|
||||
length = eventfd_write(event->pipe_fd[0], val);
|
||||
}
|
||||
while(length < 0 && errno == EINTR);
|
||||
while ((length < 0) && (errno == EINTR));
|
||||
|
||||
status = (length == 0) ? TRUE : FALSE;
|
||||
#else
|
||||
if (WaitForSingleObject(hEvent, 0) != WAIT_OBJECT_0)
|
||||
|
@ -176,20 +178,20 @@ BOOL ResetEvent(HANDLE hEvent)
|
|||
{
|
||||
#ifdef HAVE_EVENTFD_H
|
||||
eventfd_t value;
|
||||
|
||||
do
|
||||
{
|
||||
length = eventfd_read(event->pipe_fd[0], &value);
|
||||
}
|
||||
while(length < 0 && errno == EINTR);
|
||||
while ((length < 0) && (errno == EINTR));
|
||||
|
||||
status = (length > 0) ? TRUE : FALSE;
|
||||
if ((length > 0) && (!status))
|
||||
status = TRUE;
|
||||
#else
|
||||
length = read(event->pipe_fd[0], &length, 1);
|
||||
if (length == 1)
|
||||
status = TRUE;
|
||||
|
||||
if (length != 1)
|
||||
break;
|
||||
if ((length == 1) && (!status))
|
||||
status = TRUE;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
@ -214,11 +216,6 @@ HANDLE CreateFileDescriptorEventW(LPSECURITY_ATTRIBUTES lpEventAttributes, BOOL
|
|||
event->bAttached = TRUE;
|
||||
event->bManualReset = bManualReset;
|
||||
|
||||
if (!event->bManualReset)
|
||||
{
|
||||
printf("CreateFileDescriptorEventW: auto-reset events not yet implemented\n");
|
||||
}
|
||||
|
||||
event->pipe_fd[0] = FileDescriptor;
|
||||
event->pipe_fd[1] = -1;
|
||||
|
||||
|
|
|
@ -65,7 +65,7 @@ DWORD WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds)
|
|||
if (status != 0)
|
||||
printf("WaitForSingleObject: pthread_join failure: %d\n", status);
|
||||
}
|
||||
if (Type == HANDLE_TYPE_MUTEX)
|
||||
else if (Type == HANDLE_TYPE_MUTEX)
|
||||
{
|
||||
if (dwMilliseconds != INFINITE)
|
||||
printf("WaitForSingleObject: timeout not implemented for mutex wait\n");
|
||||
|
@ -90,7 +90,7 @@ DWORD WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds)
|
|||
timeout.tv_usec = dwMilliseconds * 1000;
|
||||
}
|
||||
|
||||
status = select(event->pipe_fd[0] + 1, &rfds, 0, 0,
|
||||
status = select(event->pipe_fd[0] + 1, &rfds, NULL, NULL,
|
||||
(dwMilliseconds == INFINITE) ? NULL : &timeout);
|
||||
|
||||
if (status < 0)
|
||||
|
@ -146,6 +146,10 @@ DWORD WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds)
|
|||
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("WaitForSingleObject: unknown handle type %d\n", Type);
|
||||
}
|
||||
|
||||
return WAIT_OBJECT_0;
|
||||
}
|
||||
|
|
|
@ -28,6 +28,7 @@ set(${MODULE_PREFIX}_COLLECTIONS_SRCS
|
|||
collections/KeyValuePair.c
|
||||
collections/CountdownEvent.c
|
||||
collections/BufferPool.c
|
||||
collections/ObjectPool.c
|
||||
collections/MessageQueue.c)
|
||||
|
||||
set(${MODULE_PREFIX}_SRCS
|
||||
|
|
|
@ -43,6 +43,15 @@ HANDLE MessageQueue_Event(wMessageQueue* queue)
|
|||
return queue->event;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the queue size
|
||||
*/
|
||||
|
||||
int MessageQueue_Size(wMessageQueue* queue)
|
||||
{
|
||||
return queue->size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Methods
|
||||
*/
|
||||
|
@ -73,7 +82,7 @@ void MessageQueue_Dispatch(wMessageQueue* queue, wMessage* message)
|
|||
queue->array = (wMessage*) realloc(queue->array, sizeof(wMessage) * queue->capacity);
|
||||
ZeroMemory(&(queue->array[old_capacity]), old_capacity * sizeof(wMessage));
|
||||
|
||||
if (queue->tail < (old_capacity - 1))
|
||||
if (queue->tail < old_capacity)
|
||||
{
|
||||
CopyMemory(&(queue->array[old_capacity]), queue->array, queue->tail * sizeof(wMessage));
|
||||
queue->tail += old_capacity;
|
||||
|
@ -84,7 +93,8 @@ void MessageQueue_Dispatch(wMessageQueue* queue, wMessage* message)
|
|||
queue->tail = (queue->tail + 1) % queue->capacity;
|
||||
queue->size++;
|
||||
|
||||
SetEvent(queue->event);
|
||||
if (queue->size > 0)
|
||||
SetEvent(queue->event);
|
||||
|
||||
ReleaseMutex(queue->mutex);
|
||||
}
|
||||
|
@ -122,12 +132,12 @@ int MessageQueue_Get(wMessageQueue* queue, wMessage* message)
|
|||
queue->head = (queue->head + 1) % queue->capacity;
|
||||
queue->size--;
|
||||
|
||||
if (queue->size < 1)
|
||||
ResetEvent(queue->event);
|
||||
|
||||
status = (message->id != WMQ_QUIT) ? 1 : 0;
|
||||
}
|
||||
|
||||
if (queue->size < 1)
|
||||
ResetEvent(queue->event);
|
||||
|
||||
ReleaseMutex(queue->mutex);
|
||||
|
||||
return status;
|
||||
|
@ -149,6 +159,9 @@ int MessageQueue_Peek(wMessageQueue* queue, wMessage* message, BOOL remove)
|
|||
ZeroMemory(&(queue->array[queue->head]), sizeof(wMessage));
|
||||
queue->head = (queue->head + 1) % queue->capacity;
|
||||
queue->size--;
|
||||
|
||||
if (queue->size < 1)
|
||||
ResetEvent(queue->event);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -175,6 +188,7 @@ wMessageQueue* MessageQueue_New()
|
|||
|
||||
queue->capacity = 32;
|
||||
queue->array = (wMessage*) malloc(sizeof(wMessage) * queue->capacity);
|
||||
ZeroMemory(queue->array, sizeof(wMessage) * queue->capacity);
|
||||
|
||||
queue->mutex = CreateMutex(NULL, FALSE, NULL);
|
||||
queue->event = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
|
|
|
@ -0,0 +1,145 @@
|
|||
/**
|
||||
* WinPR: Windows Portable Runtime
|
||||
* Object Pool
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <winpr/crt.h>
|
||||
|
||||
#include <winpr/collections.h>
|
||||
|
||||
/**
|
||||
* C Object Pool similar to C# BufferManager Class:
|
||||
* http://msdn.microsoft.com/en-us/library/ms405814.aspx
|
||||
*/
|
||||
|
||||
/**
|
||||
* Methods
|
||||
*/
|
||||
|
||||
/**
|
||||
* Gets an object from the pool.
|
||||
*/
|
||||
|
||||
void* ObjectPool_Take(wObjectPool* pool)
|
||||
{
|
||||
void* obj = NULL;
|
||||
|
||||
if (pool->synchronized)
|
||||
WaitForSingleObject(pool->mutex, INFINITE);
|
||||
|
||||
if (pool->size > 0)
|
||||
obj = pool->array[--(pool->size)];
|
||||
|
||||
if (!obj)
|
||||
{
|
||||
if (pool->object.fnObjectNew)
|
||||
obj = pool->object.fnObjectNew();
|
||||
}
|
||||
|
||||
if (pool->synchronized)
|
||||
ReleaseMutex(pool->mutex);
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an object to the pool.
|
||||
*/
|
||||
|
||||
void ObjectPool_Return(wObjectPool* pool, void* obj)
|
||||
{
|
||||
if (pool->synchronized)
|
||||
WaitForSingleObject(pool->mutex, INFINITE);
|
||||
|
||||
if ((pool->size + 1) >= pool->capacity)
|
||||
{
|
||||
pool->capacity *= 2;
|
||||
pool->array = (void**) realloc(pool->array, sizeof(void*) * pool->capacity);
|
||||
}
|
||||
|
||||
pool->array[(pool->size)++] = obj;
|
||||
|
||||
if (pool->synchronized)
|
||||
ReleaseMutex(pool->mutex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Releases the buffers currently cached in the pool.
|
||||
*/
|
||||
|
||||
void ObjectPool_Clear(wObjectPool* pool)
|
||||
{
|
||||
if (pool->synchronized)
|
||||
WaitForSingleObject(pool->mutex, INFINITE);
|
||||
|
||||
while (pool->size > 0)
|
||||
{
|
||||
(pool->size)--;
|
||||
|
||||
if (pool->object.fnObjectFree)
|
||||
pool->object.fnObjectFree(pool->array[pool->size]);
|
||||
}
|
||||
|
||||
if (pool->synchronized)
|
||||
ReleaseMutex(pool->mutex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construction, Destruction
|
||||
*/
|
||||
|
||||
wObjectPool* ObjectPool_New(BOOL synchronized)
|
||||
{
|
||||
wObjectPool* pool = NULL;
|
||||
|
||||
pool = (wObjectPool*) malloc(sizeof(wObjectPool));
|
||||
|
||||
if (pool)
|
||||
{
|
||||
ZeroMemory(pool, sizeof(wObjectPool));
|
||||
|
||||
pool->synchronized = synchronized;
|
||||
|
||||
if (pool->synchronized)
|
||||
pool->mutex = CreateMutex(NULL, FALSE, NULL);
|
||||
|
||||
pool->size = 0;
|
||||
pool->capacity = 32;
|
||||
pool->array = (void**) malloc(sizeof(void*) * pool->capacity);
|
||||
}
|
||||
|
||||
return pool;
|
||||
}
|
||||
|
||||
void ObjectPool_Free(wObjectPool* pool)
|
||||
{
|
||||
if (pool)
|
||||
{
|
||||
ObjectPool_Clear(pool);
|
||||
|
||||
if (pool->synchronized)
|
||||
CloseHandle(pool->mutex);
|
||||
|
||||
free(pool->array);
|
||||
|
||||
free(pool);
|
||||
}
|
||||
}
|
|
@ -148,7 +148,7 @@ void Queue_Enqueue(wQueue* queue, void* obj)
|
|||
queue->array = (void**) realloc(queue->array, sizeof(void*) * queue->capacity);
|
||||
ZeroMemory(&(queue->array[old_capacity]), old_capacity * sizeof(void*));
|
||||
|
||||
if (queue->tail < (old_capacity - 1))
|
||||
if (queue->tail < old_capacity)
|
||||
{
|
||||
CopyMemory(&(queue->array[old_capacity]), queue->array, queue->tail * sizeof(void*));
|
||||
queue->tail += old_capacity;
|
||||
|
@ -241,6 +241,7 @@ wQueue* Queue_New(BOOL synchronized, int capacity, int growthFactor)
|
|||
queue->growthFactor = growthFactor;
|
||||
|
||||
queue->array = (void**) malloc(sizeof(void*) * queue->capacity);
|
||||
ZeroMemory(queue->array, sizeof(void*) * queue->capacity);
|
||||
|
||||
queue->mutex = CreateMutex(NULL, FALSE, NULL);
|
||||
queue->event = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
|
|
|
@ -29,8 +29,6 @@ int TestMessageQueue(int argc, char* argv[])
|
|||
HANDLE thread;
|
||||
wMessageQueue* queue;
|
||||
|
||||
printf("Message Queue\n");
|
||||
|
||||
queue = MessageQueue_New();
|
||||
|
||||
thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) message_queue_consumer_thread, (void*) queue, 0, NULL);
|
||||
|
|
Loading…
Reference in New Issue