mfreerdp-server: merged wf_peer.c

This commit is contained in:
C-o-r-E 2012-11-14 11:05:07 -05:00
commit b5d3a493aa
13 changed files with 400 additions and 117 deletions

View File

@ -32,14 +32,100 @@
#include "wfreerdp.h" #include "wfreerdp.h"
int IDcount = 0;
BOOL CALLBACK moncb(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData)
{
printf("%d\t(%d, %d), (%d, %d)\n",
IDcount,
lprcMonitor->left,
lprcMonitor->top,
lprcMonitor->right,
lprcMonitor->bottom);
IDcount++;
return TRUE;
}
int main(int argc, char* argv[]) int main(int argc, char* argv[])
{ {
int index;
wfServer* server; wfServer* server;
server = wfreerdp_server_new(); server = wfreerdp_server_new();
if (argc == 2) set_screen_id(0);
server->port = (DWORD) atoi(argv[1]);
//handle args
index = 1;
while (index < argc)
{
//first the args that will cause the program to terminate
if (strcmp("--list-screens", argv[index]) == 0)
{
_TCHAR name[128];
int width;
int height;
int bpp;
int i;
_tprintf(_T("Detecting screens...\n"));
_tprintf(_T("\nID\tResolution\t\tName (Interface)\n\n"));
for (i=0; ; i++)
{
if (get_screen_info(i, name, &width, &height, &bpp) != 0)
{
if ( (width * height * bpp) == 0 )
continue;
_tprintf(_T("%d\t%dx%dx%d\t"), i, width, height, bpp);
_tprintf(_T("%s\n"), name);
}
else
{
break;
}
}
{
int vscreen_w;
int vscreen_h;
vscreen_w = GetSystemMetrics(SM_CXVIRTUALSCREEN);
vscreen_h = GetSystemMetrics(SM_CYVIRTUALSCREEN);
printf("\n");
EnumDisplayMonitors(NULL, NULL, moncb, 0);
IDcount = 0;
printf("\nVirtual Screen = %dx%d\n", vscreen_w, vscreen_h);
}
return 0;
}
if (strcmp("--screen", argv[index]) == 0)
{
index++;
if (index == argc)
{
printf("missing screen id parameter\n");
return 0;
}
set_screen_id(atoi(argv[index]));
index++;
}
if (index == argc - 1)
{
server->port = (DWORD) atoi(argv[index]);
break;
}
}
printf("Starting server\n"); printf("Starting server\n");

View File

@ -65,26 +65,38 @@ ID3D11Texture2D* sStage;
DXGI_OUTDUPL_FRAME_INFO FrameInfo; DXGI_OUTDUPL_FRAME_INFO FrameInfo;
int wf_dxgi_init(wfInfo* context) int wf_dxgi_init(wfInfo* wfi)
{
//not sure if needed
gAcquiredDesktopImage = NULL;
if (wf_dxgi_createDevice(wfi) != 0)
{
return 1;
}
if (wf_dxgi_getDuplication(wfi) != 0)
{
return 1;
}
return 0;
}
int wf_dxgi_createDevice(wfInfo* wfi)
{ {
HRESULT status; HRESULT status;
UINT dTop, i = 0;
DXGI_OUTPUT_DESC desc;
IDXGIOutput * pOutput;
UINT DriverTypeIndex; UINT DriverTypeIndex;
IDXGIDevice* DxgiDevice = NULL;
IDXGIAdapter* DxgiAdapter = NULL;
IDXGIOutput* DxgiOutput = NULL;
IDXGIOutput1* DxgiOutput1 = NULL;
gAcquiredDesktopImage = NULL;
for (DriverTypeIndex = 0; DriverTypeIndex < NumDriverTypes; ++DriverTypeIndex) for (DriverTypeIndex = 0; DriverTypeIndex < NumDriverTypes; ++DriverTypeIndex)
{ {
status = D3D11CreateDevice(NULL, DriverTypes[DriverTypeIndex], NULL, D3D11_CREATE_DEVICE_DEBUG, FeatureLevels, NumFeatureLevels, status = D3D11CreateDevice(NULL, DriverTypes[DriverTypeIndex], NULL, 0, FeatureLevels, NumFeatureLevels,
D3D11_SDK_VERSION, &gDevice, &FeatureLevel, &gContext); D3D11_SDK_VERSION, &gDevice, &FeatureLevel, &gContext);
if (SUCCEEDED(status)) if (SUCCEEDED(status))
break; break;
_tprintf(_T("D3D11CreateDevice returned [%d] for Driver Type %d\n"), status, DriverTypes[DriverTypeIndex]);
} }
if (FAILED(status)) if (FAILED(status))
@ -92,7 +104,21 @@ int wf_dxgi_init(wfInfo* context)
_tprintf(_T("Failed to create device in InitializeDx\n")); _tprintf(_T("Failed to create device in InitializeDx\n"));
return 1; return 1;
} }
return 0;
}
int wf_dxgi_getDuplication(wfInfo* wfi)
{
HRESULT status;
UINT dTop, i = 0;
DXGI_OUTPUT_DESC desc;
IDXGIOutput * pOutput;
IDXGIDevice* DxgiDevice = NULL;
IDXGIAdapter* DxgiAdapter = NULL;
IDXGIOutput* DxgiOutput = NULL;
IDXGIOutput1* DxgiOutput1 = NULL;
status = gDevice->lpVtbl->QueryInterface(gDevice, &IID_IDXGIDevice, (void**) &DxgiDevice); status = gDevice->lpVtbl->QueryInterface(gDevice, &IID_IDXGIDevice, (void**) &DxgiDevice);
if (FAILED(status)) if (FAILED(status))
@ -135,7 +161,7 @@ int wf_dxgi_init(wfInfo* context)
++i; ++i;
} }
dTop = 0; dTop = wfi->screenID;
status = DxgiAdapter->lpVtbl->EnumOutputs(DxgiAdapter, dTop, &DxgiOutput); status = DxgiAdapter->lpVtbl->EnumOutputs(DxgiAdapter, dTop, &DxgiOutput);
DxgiAdapter->lpVtbl->Release(DxgiAdapter); DxgiAdapter->lpVtbl->Release(DxgiAdapter);
@ -169,13 +195,14 @@ int wf_dxgi_init(wfInfo* context)
return 1; return 1;
} }
_tprintf(_T("Failed to get duplicate output\n")); _tprintf(_T("Failed to get duplicate output. Status = %#X\n"), status);
return 1; return 1;
} }
return 0; return 0;
} }
int wf_dxgi_cleanup(wfInfo* wfi) int wf_dxgi_cleanup(wfInfo* wfi)
{ {
if (wfi->framesWaiting > 0) if (wfi->framesWaiting > 0)
@ -212,7 +239,7 @@ int wf_dxgi_cleanup(wfInfo* wfi)
int wf_dxgi_nextFrame(wfInfo* wfi, UINT timeout) int wf_dxgi_nextFrame(wfInfo* wfi, UINT timeout)
{ {
HRESULT status; HRESULT status = 0;
UINT i = 0; UINT i = 0;
UINT DataBufferSize = 0; UINT DataBufferSize = 0;
BYTE* DataBuffer = NULL; BYTE* DataBuffer = NULL;
@ -238,16 +265,39 @@ int wf_dxgi_nextFrame(wfInfo* wfi, UINT timeout)
if (FAILED(status)) if (FAILED(status))
{ {
//_tprintf(_T("Failed to acquire next frame\n")); if (status == DXGI_ERROR_ACCESS_LOST)
status = gOutputDuplication->lpVtbl->ReleaseFrame(gOutputDuplication);
if (FAILED(status))
{ {
//_tprintf(_T("Failed to release frame\n")); _tprintf(_T("Failed to acquire next frame with status=%#X\n"), status);
_tprintf(_T("Trying to reinitialize due to ACCESS LOST..."));
if (gAcquiredDesktopImage)
{
gAcquiredDesktopImage->lpVtbl->Release(gAcquiredDesktopImage);
gAcquiredDesktopImage = NULL;
}
if (gOutputDuplication)
{
gOutputDuplication->lpVtbl->Release(gOutputDuplication);
gOutputDuplication = NULL;
}
wf_dxgi_getDuplication(wfi);
return 1;
} }
else
{
_tprintf(_T("Failed to acquire next frame with status=%#X\n"), status);
status = gOutputDuplication->lpVtbl->ReleaseFrame(gOutputDuplication);
if (FAILED(status))
{
_tprintf(_T("Failed to release frame with status=%d\n"), status);
}
return 1; return 1;
}
} }
status = DesktopResource->lpVtbl->QueryInterface(DesktopResource, &IID_ID3D11Texture2D, (void**) &gAcquiredDesktopImage); status = DesktopResource->lpVtbl->QueryInterface(DesktopResource, &IID_ID3D11Texture2D, (void**) &gAcquiredDesktopImage);
@ -261,10 +311,20 @@ int wf_dxgi_nextFrame(wfInfo* wfi, UINT timeout)
wfi->framesWaiting = FrameInfo.AccumulatedFrames; wfi->framesWaiting = FrameInfo.AccumulatedFrames;
if (FrameInfo.AccumulatedFrames == 0)
{
status = gOutputDuplication->lpVtbl->ReleaseFrame(gOutputDuplication);
if (FAILED(status))
{
_tprintf(_T("Failed to release frame with status=%d\n"), status);
}
}
return 0; return 0;
} }
int wf_dxgi_getPixelData(wfInfo* context, BYTE** data, int* pitch, RECT* invalid) int wf_dxgi_getPixelData(wfInfo* wfi, BYTE** data, int* pitch, RECT* invalid)
{ {
HRESULT status; HRESULT status;
D3D11_BOX Box; D3D11_BOX Box;

View File

@ -24,6 +24,10 @@
int wf_dxgi_init(wfInfo* context); int wf_dxgi_init(wfInfo* context);
int wf_dxgi_createDevice(wfInfo* context);
int wf_dxgi_getDuplication(wfInfo* context);
int wf_dxgi_cleanup(wfInfo* context); int wf_dxgi_cleanup(wfInfo* context);
int wf_dxgi_nextFrame(wfInfo* context, UINT timeout); int wf_dxgi_nextFrame(wfInfo* context, UINT timeout);

View File

@ -32,6 +32,7 @@
#include "wf_dxgi.h" #include "wf_dxgi.h"
static wfInfo* wfInfoInstance = NULL; static wfInfo* wfInfoInstance = NULL;
static int _IDcount = 0;
int wf_info_lock(wfInfo* wfi) int wf_info_lock(wfInfo* wfi)
{ {
@ -215,6 +216,10 @@ void wf_info_peer_register(wfInfo* wfi, wfPeerContext* context)
context->info = wfi; context->info = wfi;
context->updateEvent = CreateEvent(NULL, TRUE, FALSE, NULL); context->updateEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
//get the offset of the top left corner of selected screen
EnumDisplayMonitors(NULL, NULL, wf_info_monEnumCB, 0);
_IDcount = 0;
#ifdef WITH_WIN8 #ifdef WITH_WIN8
if (wfi->peerCount == 0) if (wfi->peerCount == 0)
wf_dxgi_init(wfi); wf_dxgi_init(wfi);
@ -282,7 +287,7 @@ BOOL wf_info_have_updates(wfInfo* wfi)
void wf_info_update_changes(wfInfo* wfi) void wf_info_update_changes(wfInfo* wfi)
{ {
#ifdef WITH_WIN8 #ifdef WITH_WIN8
wf_dxgi_nextFrame(wfi, wfi->framesPerSecond / 1000); wf_dxgi_nextFrame(wfi, wfi->framesPerSecond * 1000);
#else #else
GETCHANGESBUF* buf; GETCHANGESBUF* buf;
@ -303,7 +308,20 @@ void wf_info_find_invalid_region(wfInfo* wfi)
for (i = wfi->lastUpdate; i != wfi->nextUpdate; i = (i + 1) % MAXCHANGES_BUF) for (i = wfi->lastUpdate; i != wfi->nextUpdate; i = (i + 1) % MAXCHANGES_BUF)
{ {
UnionRect(&wfi->invalid, &wfi->invalid, &buf->buffer->pointrect[i].rect); LPRECT lpR = &buf->buffer->pointrect[i].rect;
//need to make sure we only get updates from the selected screen
if ( (lpR->left >= wfi->servscreen_xoffset) &&
(lpR->right <= (wfi->servscreen_xoffset + wfi->servscreen_width) ) &&
(lpR->top >= wfi->servscreen_yoffset) &&
(lpR->bottom <= (wfi->servscreen_yoffset + wfi->servscreen_height) ) )
{
UnionRect(&wfi->invalid, &wfi->invalid, lpR);
}
else
{
continue;
}
} }
#endif #endif
@ -313,11 +331,13 @@ void wf_info_find_invalid_region(wfInfo* wfi)
if (wfi->invalid.top < 0) if (wfi->invalid.top < 0)
wfi->invalid.top = 0; wfi->invalid.top = 0;
if (wfi->invalid.right >= wfi->width) if (wfi->invalid.right >= wfi->servscreen_width)
wfi->invalid.right = wfi->width - 1; wfi->invalid.right = wfi->servscreen_width - 1;
if (wfi->invalid.bottom >= wfi->height) if (wfi->invalid.bottom >= wfi->servscreen_height)
wfi->invalid.bottom = wfi->height - 1; wfi->invalid.bottom = wfi->servscreen_height - 1;
//printf("invalid region: (%d, %d), (%d, %d)\n", wfi->invalid.left, wfi->invalid.top, wfi->invalid.right, wfi->invalid.bottom);
} }
void wf_info_clear_invalid_region(wfInfo* wfi) void wf_info_clear_invalid_region(wfInfo* wfi)
@ -328,7 +348,7 @@ void wf_info_clear_invalid_region(wfInfo* wfi)
void wf_info_invalidate_full_screen(wfInfo* wfi) void wf_info_invalidate_full_screen(wfInfo* wfi)
{ {
SetRect(&wfi->invalid, 0, 0, wfi->width, wfi->height); SetRect(&wfi->invalid, 0, 0, wfi->servscreen_width, wfi->servscreen_height);
} }
BOOL wf_info_have_invalid_region(wfInfo* wfi) BOOL wf_info_have_invalid_region(wfInfo* wfi)
@ -352,9 +372,26 @@ void wf_info_getScreenData(wfInfo* wfi, long* width, long* height, BYTE** pBits,
*width += 1; *width += 1;
*height += 1; *height += 1;
offset = (4 * wfi->invalid.left) + (wfi->invalid.top * wfi->width * 4); offset = (4 * wfi->invalid.left) + (wfi->invalid.top * wfi->virtscreen_width * 4);
*pBits = ((BYTE*) (changes->Userbuffer)) + offset; *pBits = ((BYTE*) (changes->Userbuffer)) + offset;
*pitch = wfi->width * 4; *pitch = wfi->virtscreen_width * 4;
} }
#endif #endif
} }
BOOL CALLBACK wf_info_monEnumCB(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData)
{
wfInfo * wfi;
wfi = wf_info_get_instance();
if(_IDcount == wfi->screenID)
{
wfi->servscreen_xoffset = lprcMonitor->left;
wfi->servscreen_yoffset = lprcMonitor->top;
}
_IDcount++;
return TRUE;
}

View File

@ -40,5 +40,6 @@ void wf_info_clear_invalid_region(wfInfo* wfi);
void wf_info_invalidate_full_screen(wfInfo* wfi); void wf_info_invalidate_full_screen(wfInfo* wfi);
BOOL wf_info_have_invalid_region(wfInfo* wfi); BOOL wf_info_have_invalid_region(wfInfo* wfi);
void wf_info_getScreenData(wfInfo* wfi, long* width, long* height, BYTE** pBits, int* pitch); void wf_info_getScreenData(wfInfo* wfi, long* width, long* height, BYTE** pBits, int* pitch);
BOOL CALLBACK wf_info_monEnumCB(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData);
#endif /* WF_INFO_H */ #endif /* WF_INFO_H */

View File

@ -24,6 +24,7 @@
#include <winpr/windows.h> #include <winpr/windows.h>
#include "wf_input.h" #include "wf_input.h"
#include "wf_info.h"
void wf_peer_keyboard_event(rdpInput* input, UINT16 flags, UINT16 code) void wf_peer_keyboard_event(rdpInput* input, UINT16 flags, UINT16 code)
{ {
@ -82,9 +83,17 @@ void wf_peer_mouse_event(rdpInput* input, UINT16 flags, UINT16 x, UINT16 y)
} }
else else
{ {
wfInfo * wfi;
wfi = wf_info_get_instance();
//width and height of primary screen (even in multimon setups
width = (float) GetSystemMetrics(SM_CXSCREEN); width = (float) GetSystemMetrics(SM_CXSCREEN);
height = (float) GetSystemMetrics(SM_CYSCREEN); height = (float) GetSystemMetrics(SM_CYSCREEN);
x += wfi->servscreen_xoffset;
y += wfi->servscreen_yoffset;
mouse_event.mi.dx = (LONG) ((float) x * (65535.0f / width)); mouse_event.mi.dx = (LONG) ((float) x * (65535.0f / width));
mouse_event.mi.dy = (LONG) ((float) y * (65535.0f / height)); mouse_event.mi.dy = (LONG) ((float) y * (65535.0f / height));
mouse_event.mi.dwFlags = MOUSEEVENTF_ABSOLUTE; mouse_event.mi.dwFlags = MOUSEEVENTF_ABSOLUTE;
@ -138,8 +147,21 @@ void wf_peer_extended_mouse_event(rdpInput* input, UINT16 flags, UINT16 x, UINT1
if (flags & PTR_FLAGS_MOVE) if (flags & PTR_FLAGS_MOVE)
{ {
mouse_event.mi.dx = x * (0xFFFF / GetSystemMetrics(SM_CXSCREEN)); float width, height;
mouse_event.mi.dy = y * (0xFFFF / GetSystemMetrics(SM_CYSCREEN)); wfInfo * wfi;
wfi = wf_info_get_instance();
//width and height of primary screen (even in multimon setups
width = (float) GetSystemMetrics(SM_CXSCREEN);
height = (float) GetSystemMetrics(SM_CYSCREEN);
x += wfi->servscreen_xoffset;
y += wfi->servscreen_yoffset;
//mouse_event.mi.dx = x * (0xFFFF / width);
//mouse_event.mi.dy = y * (0xFFFF / height);
mouse_event.mi.dx = (LONG) ((float) x * (65535.0f / width));
mouse_event.mi.dy = (LONG) ((float) y * (65535.0f / height));
mouse_event.mi.dwFlags = MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE; mouse_event.mi.dwFlags = MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE;
SendInput(1, &mouse_event, sizeof(INPUT)); SendInput(1, &mouse_event, sizeof(INPUT));

View File

@ -36,6 +36,45 @@
cbCallback cbEvent; cbCallback cbEvent;
int get_screen_info(int id, _TCHAR* name, int* width, int* height, int* bpp)
{
DISPLAY_DEVICE dd;
memset(&dd, 0, sizeof(DISPLAY_DEVICE));
dd.cb = sizeof(DISPLAY_DEVICE);
if (EnumDisplayDevices(NULL, id, &dd, 0) != 0)
{
HDC dc;
if (name != NULL)
_stprintf(name, _T("%s (%s)"), dd.DeviceName, dd.DeviceString);
dc = CreateDC(NULL, dd.DeviceName, NULL, NULL);
*width = GetDeviceCaps(dc, HORZRES);
*height = GetDeviceCaps(dc, VERTRES);
*bpp = GetDeviceCaps(dc, BITSPIXEL);
ReleaseDC(NULL, dc);
}
else
{
return 0;
}
return 1;
}
void set_screen_id(int id)
{
wfInfo* wfi;
wfi = wf_info_get_instance();
wfi->screenID = id;
return;
}
DWORD WINAPI wf_server_main_loop(LPVOID lpParam) DWORD WINAPI wf_server_main_loop(LPVOID lpParam)
{ {
int i, fds; int i, fds;

View File

@ -29,6 +29,7 @@
#include <freerdp/freerdp.h> #include <freerdp/freerdp.h>
#include <freerdp/codec/rfx.h> #include <freerdp/codec/rfx.h>
#include <freerdp/server/rdpsnd.h> #include <freerdp/server/rdpsnd.h>
#define WF_SRV_CALLBACK_EVENT_CONNECT 1 #define WF_SRV_CALLBACK_EVENT_CONNECT 1
@ -42,8 +43,18 @@ typedef struct wf_peer_context wfPeerContext;
struct wf_info struct wf_info
{ {
STREAM* s; STREAM* s;
int width;
int height; //screen and monitor info
int screenID;
int virtscreen_width;
int virtscreen_height;
int servscreen_width;
int servscreen_height;
int servscreen_xoffset;
int servscreen_yoffset;
//int width;
//int height;
int frame_idx; int frame_idx;
int bitsPerPixel; int bitsPerPixel;
HDC driverDC; HDC driverDC;
@ -101,6 +112,9 @@ typedef struct wf_server wfServer;
typedef void (__stdcall* cbCallback) (int, UINT32); typedef void (__stdcall* cbCallback) (int, UINT32);
FREERDP_API int get_screen_info(int id, _TCHAR* name, int* w, int* h, int* b);
FREERDP_API void set_screen_id(int id);
FREERDP_API BOOL wfreerdp_server_start(wfServer* server); FREERDP_API BOOL wfreerdp_server_start(wfServer* server);
FREERDP_API BOOL wfreerdp_server_stop(wfServer* server); FREERDP_API BOOL wfreerdp_server_stop(wfServer* server);

View File

@ -26,10 +26,10 @@
/* /*
This function will iterate over the loaded display devices until it finds This function will iterate over the loaded display devices until it finds
the mirror device we want to load. If found, it will then copy the registry the mirror device we want to load. If found, it will then copy the registry
key corresponding to the device to the context and returns TRUE. Otherwise key corresponding to the device to the wfi and returns TRUE. Otherwise
the function returns FALSE. the function returns FALSE.
*/ */
BOOL wf_mirror_driver_find_display_device(wfInfo* context) BOOL wf_mirror_driver_find_display_device(wfInfo* wfi)
{ {
BOOL result; BOOL result;
BOOL devFound; BOOL devFound;
@ -52,13 +52,13 @@ BOOL wf_mirror_driver_find_display_device(wfInfo* context)
if (_tcsncmp(deviceInfo.DeviceKey, DEVICE_KEY_PREFIX, deviceKeyPrefixLength) == 0) if (_tcsncmp(deviceInfo.DeviceKey, DEVICE_KEY_PREFIX, deviceKeyPrefixLength) == 0)
{ {
deviceKeyLength = _tcslen(deviceInfo.DeviceKey) - deviceKeyPrefixLength; deviceKeyLength = _tcslen(deviceInfo.DeviceKey) - deviceKeyPrefixLength;
context->deviceKey = (LPTSTR) malloc((deviceKeyLength + 1) * sizeof(TCHAR)); wfi->deviceKey = (LPTSTR) malloc((deviceKeyLength + 1) * sizeof(TCHAR));
_tcsncpy_s(context->deviceKey, deviceKeyLength + 1, _tcsncpy_s(wfi->deviceKey, deviceKeyLength + 1,
&deviceInfo.DeviceKey[deviceKeyPrefixLength], deviceKeyLength); &deviceInfo.DeviceKey[deviceKeyPrefixLength], deviceKeyLength);
} }
_tcsncpy_s(context->deviceName, 32, deviceInfo.DeviceName, _tcslen(deviceInfo.DeviceName)); _tcsncpy_s(wfi->deviceName, 32, deviceInfo.DeviceName, _tcslen(deviceInfo.DeviceName));
return TRUE; return TRUE;
} }
@ -70,7 +70,7 @@ BOOL wf_mirror_driver_find_display_device(wfInfo* context)
/** /**
* This function will attempt to access the the windows registry using the device * This function will attempt to access the the windows registry using the device
* key stored in the current context. It will attempt to read the value of the * key stored in the current wfi. It will attempt to read the value of the
* "Attach.ToDesktop" subkey and will return TRUE if the value is already set to * "Attach.ToDesktop" subkey and will return TRUE if the value is already set to
* val. If unable to read the subkey, this function will return FALSE. If the * val. If unable to read the subkey, this function will return FALSE. If the
* subkey is not set to val it will then attempt to set it to val and return TRUE. If * subkey is not set to val it will then attempt to set it to val and return TRUE. If
@ -78,7 +78,7 @@ BOOL wf_mirror_driver_find_display_device(wfInfo* context)
* FALSE. * FALSE.
*/ */
BOOL wf_mirror_driver_display_device_attach(wfInfo* context, DWORD mode) BOOL wf_mirror_driver_display_device_attach(wfInfo* wfi, DWORD mode)
{ {
HKEY hKey; HKEY hKey;
LONG status; LONG status;
@ -86,7 +86,7 @@ BOOL wf_mirror_driver_display_device_attach(wfInfo* context, DWORD mode)
DWORD dwSize; DWORD dwSize;
DWORD dwValue; DWORD dwValue;
status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, context->deviceKey, status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, wfi->deviceKey,
0, KEY_READ | KEY_WOW64_64KEY, &hKey); 0, KEY_READ | KEY_WOW64_64KEY, &hKey);
if (status != ERROR_SUCCESS) if (status != ERROR_SUCCESS)
@ -170,7 +170,7 @@ void wf_mirror_driver_print_display_change_status(LONG status)
* If unload is nonzero then the the driver will be asked to remove itself. * If unload is nonzero then the the driver will be asked to remove itself.
*/ */
BOOL wf_mirror_driver_update(wfInfo* context, int unload) BOOL wf_mirror_driver_update(wfInfo* wfi, int unload)
{ {
HDC dc; HDC dc;
BOOL status; BOOL status;
@ -182,20 +182,25 @@ BOOL wf_mirror_driver_update(wfInfo* context, int unload)
if (!unload) if (!unload)
{ {
//first let's get the virtual screen dimentions
wfi->virtscreen_width = GetSystemMetrics(SM_CXVIRTUALSCREEN);
wfi->virtscreen_height = GetSystemMetrics(SM_CYVIRTUALSCREEN);
/* /*
* Will have to come back to this for supporting non primary displays and multimonitor setups * Will have to come back to this for supporting non primary displays and multimonitor setups
*/ */
dc = GetDC(NULL); /*dc = GetDC(NULL);
context->width = GetDeviceCaps(dc, HORZRES); wfi->servscreen_width = GetDeviceCaps(dc, HORZRES);
context->height = GetDeviceCaps(dc, VERTRES); wfi->servscreen_height = GetDeviceCaps(dc, VERTRES);
context->bitsPerPixel = GetDeviceCaps(dc, BITSPIXEL); wfi->bitsPerPixel = GetDeviceCaps(dc, BITSPIXEL);
ReleaseDC(NULL, dc); ReleaseDC(NULL, dc);*/
} }
else else
{ {
context->width = 0; wfi->servscreen_width = 0;
context->height = 0; wfi->servscreen_height = 0;
context->bitsPerPixel = 0; wfi->bitsPerPixel = 0;
} }
deviceMode = (DEVMODE*) malloc(sizeof(DEVMODE) + EXT_DEVMODE_SIZE_MAX); deviceMode = (DEVMODE*) malloc(sizeof(DEVMODE) + EXT_DEVMODE_SIZE_MAX);
@ -210,17 +215,17 @@ BOOL wf_mirror_driver_update(wfInfo* context, int unload)
deviceMode->dmSize = sizeof(DEVMODE); deviceMode->dmSize = sizeof(DEVMODE);
deviceMode->dmDriverExtra = drvExtraSaved; deviceMode->dmDriverExtra = drvExtraSaved;
deviceMode->dmPelsWidth = context->width; deviceMode->dmPelsWidth = wfi->virtscreen_width;
deviceMode->dmPelsHeight = context->height; deviceMode->dmPelsHeight = wfi->virtscreen_height;
deviceMode->dmBitsPerPel = context->bitsPerPixel; deviceMode->dmBitsPerPel = wfi->bitsPerPixel;
deviceMode->dmPosition.x = 0; deviceMode->dmPosition.x = wfi->servscreen_xoffset;
deviceMode->dmPosition.y = 0; deviceMode->dmPosition.y = wfi->servscreen_yoffset;
deviceMode->dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT | DM_POSITION; deviceMode->dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT | DM_POSITION;
_tcsncpy_s(deviceMode->dmDeviceName, 32, context->deviceName, _tcslen(context->deviceName)); _tcsncpy_s(deviceMode->dmDeviceName, 32, wfi->deviceName, _tcslen(wfi->deviceName));
disp_change_status = ChangeDisplaySettingsEx(context->deviceName, deviceMode, NULL, CDS_UPDATEREGISTRY, NULL); disp_change_status = ChangeDisplaySettingsEx(wfi->deviceName, deviceMode, NULL, CDS_UPDATEREGISTRY, NULL);
status = (disp_change_status == DISP_CHANGE_SUCCESSFUL) ? TRUE : FALSE; status = (disp_change_status == DISP_CHANGE_SUCCESSFUL) ? TRUE : FALSE;
@ -230,50 +235,50 @@ BOOL wf_mirror_driver_update(wfInfo* context, int unload)
return status; return status;
} }
BOOL wf_mirror_driver_map_memory(wfInfo* context) BOOL wf_mirror_driver_map_memory(wfInfo* wfi)
{ {
int status; int status;
GETCHANGESBUF* b; GETCHANGESBUF* b;
context->driverDC = CreateDC(context->deviceName, NULL, NULL, NULL); wfi->driverDC = CreateDC(wfi->deviceName, NULL, NULL, NULL);
if (context->driverDC == NULL) if (wfi->driverDC == NULL)
{ {
_tprintf(_T("Could not create device driver context!\n")); _tprintf(_T("Could not create device driver wfi!\n"));
return FALSE; return FALSE;
} }
context->changeBuffer = malloc(sizeof(GETCHANGESBUF)); wfi->changeBuffer = malloc(sizeof(GETCHANGESBUF));
ZeroMemory(context->changeBuffer, sizeof(GETCHANGESBUF)); ZeroMemory(wfi->changeBuffer, sizeof(GETCHANGESBUF));
status = ExtEscape(context->driverDC, dmf_esc_usm_pipe_map, 0, 0, sizeof(GETCHANGESBUF), (LPSTR) context->changeBuffer); status = ExtEscape(wfi->driverDC, dmf_esc_usm_pipe_map, 0, 0, sizeof(GETCHANGESBUF), (LPSTR) wfi->changeBuffer);
if (status <= 0) if (status <= 0)
{ {
_tprintf(_T("Failed to map shared memory from the driver! code %d\n"), status); _tprintf(_T("Failed to map shared memory from the driver! code %d\n"), status);
} }
b = (GETCHANGESBUF*) context->changeBuffer; b = (GETCHANGESBUF*) wfi->changeBuffer;
return TRUE; return TRUE;
} }
/* Unmap the shared memory and release the DC */ /* Unmap the shared memory and release the DC */
BOOL wf_mirror_driver_cleanup(wfInfo* context) BOOL wf_mirror_driver_cleanup(wfInfo* wfi)
{ {
int status; int status;
status = ExtEscape(context->driverDC, dmf_esc_usm_pipe_unmap, sizeof(GETCHANGESBUF), (LPSTR) context->changeBuffer, 0, 0); status = ExtEscape(wfi->driverDC, dmf_esc_usm_pipe_unmap, sizeof(GETCHANGESBUF), (LPSTR) wfi->changeBuffer, 0, 0);
if (status <= 0) if (status <= 0)
{ {
_tprintf(_T("Failed to unmap shared memory from the driver! code %d\n"), status); _tprintf(_T("Failed to unmap shared memory from the driver! code %d\n"), status);
} }
if (context->driverDC != NULL) if (wfi->driverDC != NULL)
{ {
status = DeleteDC(context->driverDC); status = DeleteDC(wfi->driverDC);
if (status == 0) if (status == 0)
{ {
@ -281,7 +286,7 @@ BOOL wf_mirror_driver_cleanup(wfInfo* context)
} }
} }
free(context->changeBuffer); free(wfi->changeBuffer);
return TRUE; return TRUE;
} }

View File

@ -200,11 +200,11 @@ typedef struct
ULONG nColorBmPalEntries; ULONG nColorBmPalEntries;
} Esc_dmf_pointer_shape_get_OUT; } Esc_dmf_pointer_shape_get_OUT;
BOOL wf_mirror_driver_find_display_device(wfInfo* context); BOOL wf_mirror_driver_find_display_device(wfInfo* wfi);
BOOL wf_mirror_driver_display_device_attach(wfInfo* context, DWORD mode); BOOL wf_mirror_driver_display_device_attach(wfInfo* wfi, DWORD mode);
BOOL wf_mirror_driver_update(wfInfo* context, int unload); BOOL wf_mirror_driver_update(wfInfo* wfi, int unload);
BOOL wf_mirror_driver_map_memory(wfInfo* context); BOOL wf_mirror_driver_map_memory(wfInfo* wfi);
BOOL wf_mirror_driver_cleanup(wfInfo* context); BOOL wf_mirror_driver_cleanup(wfInfo* wfi);
void wf_mirror_driver_activate(wfInfo* wfi); void wf_mirror_driver_activate(wfInfo* wfi);
void wf_mirror_driver_deactivate(wfInfo* wfi); void wf_mirror_driver_deactivate(wfInfo* wfi);

View File

@ -74,7 +74,6 @@ void wf_peer_init(freerdp_peer* client)
BOOL wf_peer_post_connect(freerdp_peer* client) BOOL wf_peer_post_connect(freerdp_peer* client)
{ {
int i; int i;
HDC hdc;
wfInfo* wfi; wfInfo* wfi;
rdpSettings* settings; rdpSettings* settings;
wfPeerContext* context = (wfPeerContext*) client->context; wfPeerContext* context = (wfPeerContext*) client->context;
@ -82,20 +81,24 @@ BOOL wf_peer_post_connect(freerdp_peer* client)
wfi = context->info; wfi = context->info;
settings = client->settings; settings = client->settings;
hdc = GetDC(NULL); if (
wfi->width = GetDeviceCaps(hdc, HORZRES); (get_screen_info(wfi->screenID, NULL, &wfi->servscreen_width, &wfi->servscreen_height, &wfi->bitsPerPixel) == 0) ||
wfi->height = GetDeviceCaps(hdc, VERTRES); (wfi->servscreen_width == 0) ||
wfi->bitsPerPixel = GetDeviceCaps(hdc, BITSPIXEL); (wfi->servscreen_height == 0) ||
ReleaseDC(NULL, hdc); (wfi->bitsPerPixel == 0) )
{
_tprintf(_T("postconnect: error getting screen info for screen %d\n"), wfi->screenID);
return FALSE;
}
if ((settings->DesktopWidth != wfi->width) || (settings->DesktopHeight != wfi->height)) if ((settings->width != wfi->servscreen_width) || (settings->height != wfi->servscreen_height))
{ {
printf("Client requested resolution %dx%d, but will resize to %dx%d\n", printf("Client requested resolution %dx%d, but will resize to %dx%d\n",
settings->DesktopWidth, settings->DesktopHeight, wfi->width, wfi->height); settings->width, settings->height, wfi->servscreen_width, wfi->servscreen_height);
settings->DesktopWidth = wfi->width; settings->width = wfi->servscreen_width;
settings->DesktopHeight = wfi->height; settings->height = wfi->servscreen_height;
settings->ColorDepth = wfi->bitsPerPixel; settings->color_depth = wfi->bitsPerPixel;
client->update->DesktopResize(client->update->context); client->update->DesktopResize(client->update->context);
} }

View File

@ -25,6 +25,8 @@
#include <stdlib.h> #include <stdlib.h>
#include <winpr\windows.h> #include <winpr\windows.h>
#include <InitGuid.h>
#define CINTERFACE #define CINTERFACE
#include <mmsystem.h> #include <mmsystem.h>
#include <dsound.h> #include <dsound.h>
@ -41,7 +43,7 @@
IDirectSoundCapture8 * cap; IDirectSoundCapture8 * cap;
IDirectSoundCaptureBuffer8* capBuf; IDirectSoundCaptureBuffer8* capBuf;
DSCBUFFERDESC dscbd; DSCBUFFERDESC dscbd;
DWORD capturePos; DWORD lastPos;
#define BYTESPERSEC 176400 #define BYTESPERSEC 176400
@ -107,7 +109,7 @@ static void wf_peer_rdpsnd_activated(rdpsnd_server_context* context)
context->SelectFormat(context, 4); context->SelectFormat(context, 4);
context->SetVolume(context, 0x7FFF, 0x7FFF); context->SetVolume(context, 0x7FFF, 0x7FFF);
capturePos = 0; lastPos = 0;
CreateThread(NULL, 0, wf_rdpsnd_thread, latestPeer, 0, NULL); CreateThread(NULL, 0, wf_rdpsnd_thread, latestPeer, 0, NULL);
@ -189,15 +191,24 @@ BOOL wf_peer_rdpsnd_init(wfPeerContext* context)
DWORD WINAPI wf_rdpsnd_thread(LPVOID lpParam) DWORD WINAPI wf_rdpsnd_thread(LPVOID lpParam)
{ {
HRESULT hr; HRESULT hr;
DWORD beg, end; DWORD beg = 0;
DWORD end = 0;
DWORD diff, rate; DWORD diff, rate;
wfPeerContext* context; wfPeerContext* context;
wfInfo* wfi; 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(); wfi = wf_info_get_instance();
context = (wfPeerContext*)lpParam; context = (wfPeerContext*)lpParam;
rate = 1000 / 5; rate = 1000 / 24;
_tprintf(_T("Trying to start capture\n")); _tprintf(_T("Trying to start capture\n"));
hr = capBuf->lpVtbl->Start(capBuf, DSCBSTART_LOOPING); hr = capBuf->lpVtbl->Start(capBuf, DSCBSTART_LOOPING);
@ -209,13 +220,15 @@ DWORD WINAPI wf_rdpsnd_thread(LPVOID lpParam)
while (1) while (1)
{ {
VOID* pbCaptureData = NULL;
DWORD dwCaptureLength; end = GetTickCount();
VOID* pbCaptureData2 = NULL; diff = end - beg;
DWORD dwCaptureLength2;
VOID* pbPlayData = NULL; if (diff < rate)
DWORD dwReadPos; {
LONG lLockSize; Sleep(rate - diff);
}
beg = GetTickCount(); beg = GetTickCount();
if (wf_rdpsnd_lock() > 0) if (wf_rdpsnd_lock() > 0)
@ -235,9 +248,11 @@ DWORD WINAPI wf_rdpsnd_thread(LPVOID lpParam)
break; break;
} }
lLockSize = dwReadPos - capturePos;//dscbd.dwBufferBytes; lLockSize = dwReadPos - lastPos;//dscbd.dwBufferBytes;
if (lLockSize < 0) lLockSize += dscbd.dwBufferBytes; if (lLockSize < 0) lLockSize += dscbd.dwBufferBytes;
//printf("Last, read, lock = [%d, %d, %d]\n", lastPos, dwReadPos, lLockSize);
if (lLockSize == 0) if (lLockSize == 0)
{ {
wf_rdpsnd_unlock(); wf_rdpsnd_unlock();
@ -245,7 +260,7 @@ DWORD WINAPI wf_rdpsnd_thread(LPVOID lpParam)
} }
hr = capBuf->lpVtbl->Lock(capBuf, capturePos, lLockSize, &pbCaptureData, &dwCaptureLength, &pbCaptureData2, &dwCaptureLength2, 0L); hr = capBuf->lpVtbl->Lock(capBuf, lastPos, lLockSize, &pbCaptureData, &dwCaptureLength, &pbCaptureData2, &dwCaptureLength2, 0L);
if (FAILED(hr)) if (FAILED(hr))
{ {
_tprintf(_T("Failed to lock sound capture buffer\n")); _tprintf(_T("Failed to lock sound capture buffer\n"));
@ -271,21 +286,15 @@ DWORD WINAPI wf_rdpsnd_thread(LPVOID lpParam)
} }
//TODO keep track of location in buffer //TODO keep track of location in buffer
capturePos += dwCaptureLength; lastPos += dwCaptureLength;
capturePos %= dscbd.dwBufferBytes; lastPos %= dscbd.dwBufferBytes;
capturePos += dwCaptureLength2; lastPos += dwCaptureLength2;
capturePos %= dscbd.dwBufferBytes; lastPos %= dscbd.dwBufferBytes;
wf_rdpsnd_unlock(); wf_rdpsnd_unlock();
} }
end = GetTickCount();
diff = end - beg;
if (diff < rate)
{
Sleep(rate - diff);
}
} }
_tprintf(_T("Trying to stop sound capture\n")); _tprintf(_T("Trying to stop sound capture\n"));
@ -295,7 +304,10 @@ DWORD WINAPI wf_rdpsnd_thread(LPVOID lpParam)
_tprintf(_T("Failed to stop capture\n")); _tprintf(_T("Failed to stop capture\n"));
} }
_tprintf(_T("Capture stopped\n")); _tprintf(_T("Capture stopped\n"));
capBuf->lpVtbl->Release(capBuf);
cap->lpVtbl->Release(cap);
lastPos = 0;
return 0; return 0;
} }

View File

@ -199,8 +199,8 @@ void wf_update_encoder_reset(wfInfo* wfi)
{ {
wfi->rfx_context = rfx_context_new(); wfi->rfx_context = rfx_context_new();
wfi->rfx_context->mode = RLGR3; wfi->rfx_context->mode = RLGR3;
wfi->rfx_context->width = wfi->width; wfi->rfx_context->width = wfi->servscreen_width;
wfi->rfx_context->height = wfi->height; wfi->rfx_context->height = wfi->servscreen_height;
rfx_context_set_pixel_format(wfi->rfx_context, RDP_PIXEL_FORMAT_B8G8R8A8); rfx_context_set_pixel_format(wfi->rfx_context, RDP_PIXEL_FORMAT_B8G8R8A8);
wfi->s = stream_new(0xFFFF); wfi->s = stream_new(0xFFFF);
} }