mirror of
https://github.com/Ylianst/MeshAgent
synced 2025-12-06 00:13:33 +00:00
Added MacOS KVM files
This commit is contained in:
257
meshcore/KVM/MacOS/mac_events.c
Normal file
257
meshcore/KVM/MacOS/mac_events.c
Normal file
@@ -0,0 +1,257 @@
|
||||
#include "mac_events.h"
|
||||
#include <assert.h>
|
||||
#include <SystemConfiguration/SystemConfiguration.h>
|
||||
#include <string.h>
|
||||
|
||||
static const int g_keymapLen = 114; // Modify this when you change anything in g_keymap.
|
||||
static int g_capsLock = 0;
|
||||
static int g_lMouseDown = 0;
|
||||
static int g_rMouseDown = 0;
|
||||
|
||||
static struct keymap_t g_keymap[] = {
|
||||
{ kVK_Space, VK_SPACE },
|
||||
{ kVK_CapsLock, VK_CAPITAL },
|
||||
{ kVK_ANSI_Q, VK_Q },
|
||||
{ kVK_ANSI_W, VK_W },
|
||||
{ kVK_ANSI_E, VK_E },
|
||||
{ kVK_ANSI_R, VK_R },
|
||||
{ kVK_ANSI_T, VK_T },
|
||||
{ kVK_ANSI_Y, VK_Y },
|
||||
{ kVK_ANSI_U, VK_U },
|
||||
{ kVK_ANSI_I, VK_I },
|
||||
{ kVK_ANSI_O, VK_O },
|
||||
{ kVK_ANSI_P, VK_P },
|
||||
{ kVK_ANSI_A, VK_A },
|
||||
{ kVK_ANSI_S, VK_S },
|
||||
{ kVK_ANSI_D, VK_D },
|
||||
{ kVK_ANSI_F, VK_F },
|
||||
{ kVK_ANSI_G, VK_G },
|
||||
{ kVK_ANSI_H, VK_H },
|
||||
{ kVK_ANSI_J, VK_J },
|
||||
{ kVK_ANSI_K, VK_K },
|
||||
{ kVK_ANSI_L, VK_L },
|
||||
{ kVK_ANSI_Z, VK_Z },
|
||||
{ kVK_ANSI_X, VK_X },
|
||||
{ kVK_ANSI_C, VK_C },
|
||||
{ kVK_ANSI_V, VK_V },
|
||||
{ kVK_ANSI_B, VK_B },
|
||||
{ kVK_ANSI_N, VK_N },
|
||||
{ kVK_ANSI_M, VK_M },
|
||||
{ kVK_ANSI_1, VK_1 },
|
||||
{ kVK_ANSI_2, VK_2 },
|
||||
{ kVK_ANSI_3, VK_3 },
|
||||
{ kVK_ANSI_4, VK_4 },
|
||||
{ kVK_ANSI_5, VK_5 },
|
||||
{ kVK_ANSI_6, VK_6 },
|
||||
{ kVK_ANSI_7, VK_7 },
|
||||
{ kVK_ANSI_8, VK_8 },
|
||||
{ kVK_ANSI_9, VK_9 },
|
||||
{ kVK_ANSI_0, VK_0 },
|
||||
{ kVK_Delete, VK_BACK },
|
||||
{ kVK_Tab, VK_TAB },
|
||||
{ kVK_ANSI_KeypadClear, VK_CLEAR },
|
||||
{ kVK_Return, VK_RETURN },
|
||||
{ kVK_Help, VK_PAUSE },
|
||||
{ kVK_Escape, VK_ESCAPE },
|
||||
{ kVK_ForwardDelete, VK_DELETE },
|
||||
{ kVK_Home, VK_HOME },
|
||||
{ kVK_LeftArrow, VK_LEFT },
|
||||
{ kVK_UpArrow, VK_UP },
|
||||
{ kVK_RightArrow, VK_RIGHT },
|
||||
{ kVK_DownArrow, VK_DOWN },
|
||||
{ kVK_PageUp, VK_PRIOR },
|
||||
{ kVK_PageDown, VK_NEXT },
|
||||
{ kVK_End, VK_END },
|
||||
{ kVK_Help, VK_SELECT },
|
||||
{ kVK_Help, VK_SNAPSHOT },
|
||||
{ kVK_Help, VK_EXECUTE },
|
||||
{ kVK_Help, VK_INSERT },
|
||||
{ kVK_Help, VK_HELP },
|
||||
{ kVK_Escape, VK_CANCEL },
|
||||
{ kVK_F1, VK_F1 },
|
||||
{ kVK_F2, VK_F2 },
|
||||
{ kVK_F3, VK_F3 },
|
||||
{ kVK_F4, VK_F4 },
|
||||
{ kVK_F5, VK_F5 },
|
||||
{ kVK_F6, VK_F6 },
|
||||
{ kVK_F7, VK_F7 },
|
||||
{ kVK_F8, VK_F8 },
|
||||
{ kVK_F9, VK_F9 },
|
||||
{ kVK_F10, VK_F10 },
|
||||
{ kVK_F11, VK_F11 },
|
||||
{ kVK_F12, VK_F12 },
|
||||
{ kVK_F13, VK_F13 },
|
||||
{ kVK_F14, VK_F14 },
|
||||
{ kVK_F15, VK_F15 },
|
||||
{ kVK_F16, VK_F16 },
|
||||
{ kVK_F17, VK_F17 },
|
||||
{ kVK_F18, VK_F18 },
|
||||
{ kVK_F19, VK_F19 },
|
||||
{ kVK_F20, VK_F20 },
|
||||
{ kVK_Home, VK_HOME },
|
||||
{ kVK_ANSI_KeypadMultiply, VK_MULTIPLY },
|
||||
{ kVK_ANSI_Equal, VK_ADD },
|
||||
{ kVK_ANSI_Comma, VK_SEPARATOR },
|
||||
{ kVK_ANSI_Minus, VK_SUBTRACT },
|
||||
{ kVK_ANSI_KeypadDecimal, VK_DECIMAL },
|
||||
{ kVK_ANSI_KeypadDivide, VK_DIVIDE },
|
||||
{ kVK_ANSI_Keypad0, VK_NUMPAD0 },
|
||||
{ kVK_ANSI_Keypad1, VK_NUMPAD1 },
|
||||
{ kVK_ANSI_Keypad2, VK_NUMPAD2 },
|
||||
{ kVK_ANSI_Keypad3, VK_NUMPAD3 },
|
||||
{ kVK_ANSI_Keypad4, VK_NUMPAD4 },
|
||||
{ kVK_ANSI_Keypad5, VK_NUMPAD5 },
|
||||
{ kVK_ANSI_Keypad6, VK_NUMPAD6 },
|
||||
{ kVK_ANSI_Keypad7, VK_NUMPAD7 },
|
||||
{ kVK_ANSI_Keypad8, VK_NUMPAD8 },
|
||||
{ kVK_ANSI_Keypad9, VK_NUMPAD9 },
|
||||
{ kVK_Shift, VK_SHIFT },
|
||||
{ kVK_Control, VK_CONTROL },
|
||||
{ kVK_Option, VK_MENU },
|
||||
{ kVK_Command, VK_RWIN },
|
||||
{ kVK_Command, VK_LWIN },
|
||||
{ kVK_Option, VK_APPS },
|
||||
{ kVK_JIS_Kana, VK_KANA },
|
||||
{ kVK_ANSI_Semicolon, VK_OEM_1 },
|
||||
{ kVK_ANSI_Equal, VK_OEM_PLUS },
|
||||
{ kVK_ANSI_Comma, VK_OEM_COMMA },
|
||||
{ kVK_ANSI_Minus, VK_OEM_MINUS },
|
||||
{ kVK_ANSI_Period, VK_OEM_PERIOD },
|
||||
{ kVK_ANSI_Slash, VK_OEM_2 },
|
||||
{ kVK_ANSI_Grave, VK_OEM_3 },
|
||||
{ kVK_ANSI_LeftBracket, VK_OEM_4 },
|
||||
{ kVK_ANSI_Backslash, VK_OEM_5 },
|
||||
{ kVK_ANSI_RightBracket, VK_OEM_6 },
|
||||
{ kVK_ANSI_Quote, VK_OEM_7 }
|
||||
};
|
||||
|
||||
char* getCurrentSession() {
|
||||
SCDynamicStoreRef store;
|
||||
CFStringRef name;
|
||||
uid_t uid;
|
||||
char *buf;
|
||||
Boolean ok;
|
||||
|
||||
buf = (char *)malloc (BUFSIZ);
|
||||
store = SCDynamicStoreCreate(NULL, CFSTR("GetConsoleUser"), NULL, NULL);
|
||||
assert(store != NULL);
|
||||
name = SCDynamicStoreCopyConsoleUser(store, &uid, NULL);
|
||||
CFRelease(store);
|
||||
|
||||
if (name != NULL) {
|
||||
ok = CFStringGetCString(name, buf, BUFSIZ, kCFStringEncodingUTF8);
|
||||
assert(ok == true);
|
||||
CFRelease(name);
|
||||
} else {
|
||||
strcpy(buf, "<none>");
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
void MouseAction(double absX, double absY, int button, short wheel)
|
||||
{
|
||||
CGPoint curPos;
|
||||
CGEventRef e;
|
||||
CGEventType event;
|
||||
CGEventSourceRef source;
|
||||
|
||||
curPos.x = absX;
|
||||
curPos.y = absY;
|
||||
|
||||
source = CGEventSourceCreate(kCGEventSourceStateHIDSystemState);
|
||||
|
||||
|
||||
if (g_lMouseDown || g_rMouseDown) {
|
||||
event = g_lMouseDown ? kCGEventLeftMouseDragged : kCGEventRightMouseDragged;
|
||||
e = CGEventCreateMouseEvent(source, event, curPos, 1);
|
||||
CGEventPost(kCGHIDEventTap, e);
|
||||
CGEventPost(kCGSessionEventTap, e);
|
||||
CFRelease(e);
|
||||
}
|
||||
else {
|
||||
CGWarpMouseCursorPosition (curPos);
|
||||
}
|
||||
|
||||
if (button != 0) {
|
||||
|
||||
switch (button) {
|
||||
case MOUSEEVENTF_LEFTDOWN:
|
||||
event = kCGEventLeftMouseDown;
|
||||
g_lMouseDown = 1;
|
||||
break;
|
||||
case MOUSEEVENTF_RIGHTDOWN:
|
||||
g_rMouseDown = 1;
|
||||
event = kCGEventRightMouseDown;
|
||||
break;
|
||||
case MOUSEEVENTF_LEFTUP:
|
||||
g_lMouseDown = 0;
|
||||
event = kCGEventLeftMouseUp;
|
||||
break;
|
||||
case MOUSEEVENTF_RIGHTUP:
|
||||
g_rMouseDown = 0;
|
||||
event = kCGEventRightMouseUp;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
if (!strcmp(getCurrentSession(), "<none>"))
|
||||
{
|
||||
// This call is deprecated in OSX 10.6
|
||||
CGPostMouseEvent(curPos, TRUE, 3, (event == kCGEventLeftMouseDown) ? TRUE : FALSE, (event == kCGEventRightMouseDown) ? TRUE : FALSE, FALSE); // mouse down
|
||||
}
|
||||
else
|
||||
{
|
||||
*/
|
||||
e = CGEventCreateMouseEvent(source, event, curPos, 1);
|
||||
CGEventPost(kCGHIDEventTap, e);
|
||||
CFRelease(e);
|
||||
/*
|
||||
}
|
||||
*/
|
||||
}
|
||||
else if (wheel != 0)
|
||||
{
|
||||
e = CGEventCreateScrollWheelEvent(source, kCGScrollEventUnitPixel, 1, wheel);
|
||||
CGEventPost(kCGHIDEventTap, e);
|
||||
CFRelease(e);
|
||||
}
|
||||
if (source != NULL) CFRelease(source);
|
||||
}
|
||||
|
||||
void KeyAction(unsigned char vk, int up) {
|
||||
int i;
|
||||
CGKeyCode keycode;
|
||||
CGEventSourceRef source;
|
||||
|
||||
source = CGEventSourceCreate(kCGEventSourceStateHIDSystemState);
|
||||
for (i = 0 ; i < g_keymapLen; i++) {
|
||||
if (g_keymap[i].vk == vk) {
|
||||
keycode = g_keymap[i].keycode;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == g_keymapLen) { return; }
|
||||
if (vk == VK_CAPITAL && up) { g_capsLock = g_capsLock ? 0 : 1; }
|
||||
|
||||
/*
|
||||
if (!strcmp(getCurrentSession(), "<none>")) {
|
||||
// This call is deprecated in OSX 10.6
|
||||
CGPostKeyboardEvent(0, keycode, !up);
|
||||
}
|
||||
else
|
||||
{
|
||||
*/
|
||||
CGEventRef key = CGEventCreateKeyboardEvent(source, keycode, !up);
|
||||
if (g_capsLock) { CGEventSetFlags(key, kCGEventFlagMaskAlphaShift); }
|
||||
CGEventPost(kCGHIDEventTap, key);
|
||||
CFRelease(key);
|
||||
/*
|
||||
}
|
||||
*/
|
||||
if (source != NULL) CFRelease(source);
|
||||
}
|
||||
380
meshcore/KVM/MacOS/mac_events.h
Normal file
380
meshcore/KVM/MacOS/mac_events.h
Normal file
@@ -0,0 +1,380 @@
|
||||
/*
|
||||
* linux_events.h
|
||||
*
|
||||
* Created on: Jul 8, 2011
|
||||
* Author: Intel
|
||||
*/
|
||||
|
||||
#ifndef LINUX_EVENTS_H_
|
||||
#define LINUX_EVENTS_H_
|
||||
|
||||
#include <Carbon/Carbon.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
enum MOUSE_EVENTS {
|
||||
MOUSEEVENTF_LEFTDOWN = 0x0002,
|
||||
MOUSEEVENTF_RIGHTDOWN = 0x0008,
|
||||
MOUSEEVENTF_MIDDLEDOWN = 0x0020,
|
||||
MOUSEEVENTF_LEFTUP = 0x0004,
|
||||
MOUSEEVENTF_RIGHTUP = 0x0010,
|
||||
MOUSEEVENTF_MIDDLEUP = 0x0040
|
||||
};
|
||||
|
||||
// VK_LBUTTON (01) Left mouse button
|
||||
#define VK_LBUTTON 0x01
|
||||
// VK_RBUTTON (02) Right mouse button
|
||||
#define VK_RBUTTON 0x02
|
||||
// VK_CANCEL (03) Control-break processing
|
||||
#define VK_CANCEL 0x03
|
||||
// VK_MBUTTON (04) Middle mouse button (three-button mouse)
|
||||
#define VK_MBUTTON 0x04
|
||||
// VK_XBUTTON1 (05)
|
||||
#define VK_XBUTTON1 0x05
|
||||
// VK_XBUTTON2 (06)
|
||||
#define VK_XBUTTON2 0x06
|
||||
// VK_BACK (08) BACKSPACE key
|
||||
#define VK_BACK 0x08
|
||||
// VK_TAB (09) TAB key
|
||||
#define VK_TAB 0x09
|
||||
// VK_CLEAR (0C) CLEAR key
|
||||
#define VK_CLEAR 0x0C
|
||||
// VK_RETURN (0D)
|
||||
#define VK_RETURN 0x0D
|
||||
// VK_SHIFT (10) SHIFT key
|
||||
#define VK_SHIFT 0x10
|
||||
// VK_CONTROL (11) CTRL key
|
||||
#define VK_CONTROL 0x11
|
||||
// VK_MENU (12) ALT key
|
||||
#define VK_MENU 0x12
|
||||
// VK_PAUSE (13) PAUSE key
|
||||
#define VK_PAUSE 0x13
|
||||
// VK_CAPITAL (14) CAPS LOCK key
|
||||
#define VK_CAPITAL 0x14
|
||||
// VK_KANA (15) Input Method Editor (IME) Kana mode
|
||||
#define VK_KANA 0x15
|
||||
// VK_HANGUEL (15) IME Hanguel mode (maintained for compatibility; use VK_HANGUL)
|
||||
// VK_HANGUL (15) IME Hangul mode
|
||||
#define VK_HANGUL 0x15
|
||||
// VK_JUNJA (17) IME Junja mode
|
||||
#define VK_JUNJA 0x17
|
||||
// VK_FINAL (18) IME final mode
|
||||
#define VK_FINAL 0x18
|
||||
// VK_HANJA (19) IME Hanja mode
|
||||
#define VK_HANJA 0x19
|
||||
// VK_KANJI (19) IME Kanji mode
|
||||
#define VK_KANJI 0x19
|
||||
// VK_ESCAPE (1B) ESC key
|
||||
#define VK_ESCAPE 0x1B
|
||||
// VK_CONVERT (1C) IME convert
|
||||
#define VK_CONVERT 0x1C
|
||||
// VK_NONCONVERT (1D) IME nonconvert
|
||||
#define VK_NONCONVERT 0x1D
|
||||
// VK_ACCEPT (1E) IME accept
|
||||
#define VK_ACCEPT 0x1E
|
||||
// VK_MODECHANGE (1F) IME mode change request
|
||||
#define VK_MODECHANGE 0x1F
|
||||
// VK_SPACE (20) SPACEBAR
|
||||
#define VK_SPACE 0x20
|
||||
// VK_PRIOR (21) PAGE UP key
|
||||
#define VK_PRIOR 0x21
|
||||
// VK_NEXT (22) PAGE DOWN key
|
||||
#define VK_NEXT 0x22
|
||||
// VK_END (23) END key
|
||||
#define VK_END 0x23
|
||||
// VK_HOME (24) HOME key
|
||||
#define VK_HOME 0x24
|
||||
// VK_LEFT (25) LEFT ARROW key
|
||||
#define VK_LEFT 0x25
|
||||
// VK_UP (26) UP ARROW key
|
||||
#define VK_UP 0x26
|
||||
// VK_RIGHT (27) RIGHT ARROW key
|
||||
#define VK_RIGHT 0x27
|
||||
// VK_DOWN (28) DOWN ARROW key
|
||||
#define VK_DOWN 0x28
|
||||
// VK_SELECT (29) SELECT key
|
||||
#define VK_SELECT 0x29
|
||||
// VK_PRINT (2A) PRINT key
|
||||
#define VK_PRINT 0x2A
|
||||
// VK_EXECUTE (2B) EXECUTE key
|
||||
#define VK_EXECUTE 0x2B
|
||||
// VK_SNAPSHOT (2C) PRINT SCREEN key
|
||||
#define VK_SNAPSHOT 0x2C
|
||||
// VK_INSERT (2D) INS key
|
||||
#define VK_INSERT 0x2D
|
||||
// VK_DELETE (2E) DEL key
|
||||
#define VK_DELETE 0x2E
|
||||
// VK_HELP (2F) HELP key
|
||||
#define VK_HELP 0x2F
|
||||
// (30) 0 key
|
||||
#define VK_0 0x30
|
||||
// (31) 1 key
|
||||
#define VK_1 0x31
|
||||
// (32) 2 key
|
||||
#define VK_2 0x32
|
||||
// (33) 3 key
|
||||
#define VK_3 0x33
|
||||
// (34) 4 key
|
||||
#define VK_4 0x34
|
||||
// (35) 5 key;
|
||||
#define VK_5 0x35
|
||||
// (36) 6 key
|
||||
#define VK_6 0x36
|
||||
// (37) 7 key
|
||||
#define VK_7 0x37
|
||||
// (38) 8 key
|
||||
#define VK_8 0x38
|
||||
// (39) 9 key
|
||||
#define VK_9 0x39
|
||||
// (41) A key
|
||||
#define VK_A 0x41
|
||||
// (42) B key
|
||||
#define VK_B 0x42
|
||||
// (43) C key
|
||||
#define VK_C 0x43
|
||||
// (44) D key
|
||||
#define VK_D 0x44
|
||||
// (45) E key
|
||||
#define VK_E 0x45
|
||||
// (46) F key
|
||||
#define VK_F 0x46
|
||||
// (47) G key
|
||||
#define VK_G 0x47
|
||||
// (48) H key
|
||||
#define VK_H 0x48
|
||||
// (49) I key
|
||||
#define VK_I 0x49
|
||||
// (4A) J key
|
||||
#define VK_J 0x4A
|
||||
// (4B) K key
|
||||
#define VK_K 0x4B
|
||||
// (4C) L key
|
||||
#define VK_L 0x4C
|
||||
// (4D) M key
|
||||
#define VK_M 0x4D
|
||||
// (4E) N key
|
||||
#define VK_N 0x4E
|
||||
// (4F) O key
|
||||
#define VK_O 0x4F
|
||||
// (50) P key
|
||||
#define VK_P 0x50
|
||||
// (51) Q key
|
||||
#define VK_Q 0x51
|
||||
// (52) R key
|
||||
#define VK_R 0x52
|
||||
// (53) S key
|
||||
#define VK_S 0x53
|
||||
// (54) T key
|
||||
#define VK_T 0x54
|
||||
// (55) U key
|
||||
#define VK_U 0x55
|
||||
// (56) V key
|
||||
#define VK_V 0x56
|
||||
// (57) W key
|
||||
#define VK_W 0x57
|
||||
// (58) X key
|
||||
#define VK_X 0x58
|
||||
// (59) Y key
|
||||
#define VK_Y 0x59
|
||||
// (5A) Z key
|
||||
#define VK_Z 0x5A
|
||||
// VK_LWIN (5B) Left Windows key (Microsoft Natural keyboard)
|
||||
#define VK_LWIN 0x5B
|
||||
// VK_RWIN (5C) Right Windows key (Natural keyboard)
|
||||
#define VK_RWIN 0x5C
|
||||
// VK_APPS (5D) Applications key (Natural keyboard)
|
||||
#define VK_APPS 0x5D
|
||||
// VK_SLEEP (5F) Computer Sleep key
|
||||
#define VK_SLEEP 0x5F
|
||||
// VK_NUMPAD0 (60) Numeric keypad 0 key
|
||||
#define VK_NUMPAD0 0x60
|
||||
// VK_NUMPAD1 (61) Numeric keypad 1 key
|
||||
#define VK_NUMPAD1 0x61
|
||||
// VK_NUMPAD2 (62) Numeric keypad 2 key
|
||||
#define VK_NUMPAD2 0x62
|
||||
// VK_NUMPAD3 (63) Numeric keypad 3 key
|
||||
#define VK_NUMPAD3 0x63
|
||||
// VK_NUMPAD4 (64) Numeric keypad 4 key
|
||||
#define VK_NUMPAD4 0x64
|
||||
// VK_NUMPAD5 (65) Numeric keypad 5 key
|
||||
#define VK_NUMPAD5 0x65
|
||||
// VK_NUMPAD6 (66) Numeric keypad 6 key
|
||||
#define VK_NUMPAD6 0x66
|
||||
// VK_NUMPAD7 (67) Numeric keypad 7 key
|
||||
#define VK_NUMPAD7 0x67
|
||||
// VK_NUMPAD8 (68) Numeric keypad 8 key
|
||||
#define VK_NUMPAD8 0x68
|
||||
// VK_NUMPAD9 (69) Numeric keypad 9 key
|
||||
#define VK_NUMPAD9 0x69
|
||||
// VK_MULTIPLY (6A) Multiply key
|
||||
#define VK_MULTIPLY 0x6A
|
||||
// VK_ADD (6B) Add key
|
||||
#define VK_ADD 0x6B
|
||||
// VK_SEPARATOR (6C) Separator key
|
||||
#define VK_SEPARATOR 0x6C
|
||||
// VK_SUBTRACT (6D) Subtract key
|
||||
#define VK_SUBTRACT 0x6D
|
||||
// VK_DECIMAL (6E) Decimal key
|
||||
#define VK_DECIMAL 0x6E
|
||||
// VK_DIVIDE (6F) Divide key
|
||||
#define VK_DIVIDE 0x6F
|
||||
// VK_F1 (70) F1 key
|
||||
#define VK_F1 0x70
|
||||
// VK_F2 (71) F2 key
|
||||
#define VK_F2 0x71
|
||||
// VK_F3 (72) F3 key
|
||||
#define VK_F3 0x72
|
||||
// VK_F4 (73) F4 key
|
||||
#define VK_F4 0x73
|
||||
// VK_F5 (74) F5 key
|
||||
#define VK_F5 0x74
|
||||
// VK_F6 (75) F6 key
|
||||
#define VK_F6 0x75
|
||||
// VK_F7 (76) F7 key
|
||||
#define VK_F7 0x76
|
||||
// VK_F8 (77) F8 key
|
||||
#define VK_F8 0x77
|
||||
// VK_F9 (78) F9 key
|
||||
#define VK_F9 0x78
|
||||
// VK_F10 (79) F10 key
|
||||
#define VK_F10 0x79
|
||||
// VK_F11 (7A) F11 key
|
||||
#define VK_F11 0x7A
|
||||
// VK_F12 (7B) F12 key
|
||||
#define VK_F12 0x7B
|
||||
// VK_F13 (7C) F13 key
|
||||
#define VK_F13 0x7C
|
||||
// VK_F14 (7D) F14 key
|
||||
#define VK_F14 0x7D
|
||||
// VK_F15 (7E) F15 key
|
||||
#define VK_F15 0x7E
|
||||
// VK_F16 (7F) F16 key
|
||||
#define VK_F16 0x7F
|
||||
// VK_F17 (80H) F17 key
|
||||
#define VK_F17 0x80
|
||||
// VK_F18 (81H) F18 key
|
||||
#define VK_F18 0x81
|
||||
// VK_F19 (82H) F19 key
|
||||
#define VK_F19 0x82
|
||||
// VK_F20 (83H) F20 key
|
||||
#define VK_F20 0x83
|
||||
// VK_F21 (84H) F21 key
|
||||
#define VK_F21 0x84
|
||||
// VK_F22 (85H) F22 key
|
||||
#define VK_F22 0x85
|
||||
// VK_F23 (86H) F23 key
|
||||
#define VK_F23 0x86
|
||||
// VK_F24 (87H) F24 key
|
||||
#define VK_F24 0x87
|
||||
// VK_NUMLOCK (90) NUM LOCK key
|
||||
#define VK_NUMLOCK 0x90
|
||||
// VK_SCROLL (91) SCROLL LOCK key
|
||||
#define VK_SCROLL 0x91
|
||||
// VK_LSHIFT (A0) Left SHIFT key
|
||||
#define VK_LSHIFT 0xA0
|
||||
// VK_RSHIFT (A1) Right SHIFT key
|
||||
#define VK_RSHIFT 0xA1
|
||||
// VK_LCONTROL (A2) Left CONTROL key
|
||||
#define VK_LCONTROL 0xA2
|
||||
// VK_RCONTROL (A3) Right CONTROL key
|
||||
#define VK_RCONTROL 0xA3
|
||||
// VK_LMENU (A4) Left MENU key
|
||||
#define VK_LMENU 0xA4
|
||||
// VK_RMENU (A5) Right MENU key
|
||||
#define VK_RMENU 0xA5
|
||||
// VK_BROWSER_BACK (A6) Windows 2000/XP: Browser Back key
|
||||
#define VK_BROWSER_BACK 0xA6
|
||||
// VK_BROWSER_FORWARD (A7) Windows 2000/XP: Browser Forward key
|
||||
#define VK_BROWSER_FORWARD 0xA7
|
||||
// VK_BROWSER_REFRESH (A8) Windows 2000/XP: Browser Refresh key
|
||||
#define VK_BROWSER_REFRESH 0xA8
|
||||
// VK_BROWSER_STOP (A9) Windows 2000/XP: Browser Stop key
|
||||
#define VK_BROWSER_STOP 0xA9
|
||||
// VK_BROWSER_SEARCH (AA) Windows 2000/XP: Browser Search key
|
||||
#define VK_BROWSER_SEARCH 0xAA
|
||||
// VK_BROWSER_FAVORITES (AB) Windows 2000/XP: Browser Favorites key
|
||||
#define VK_BROWSER_FAVORITES 0xAB
|
||||
// VK_BROWSER_HOME (AC) Windows 2000/XP: Browser Start and Home key
|
||||
#define VK_BROWSER_HOME 0xAC
|
||||
// VK_VOLUME_MUTE (AD) Windows 2000/XP: Volume Mute key
|
||||
#define VK_VOLUME_MUTE 0xAD
|
||||
// VK_VOLUME_DOWN (AE) Windows 2000/XP: Volume Down key
|
||||
#define VK_VOLUME_DOWN 0xAE
|
||||
// VK_VOLUME_UP (AF) Windows 2000/XP: Volume Up key
|
||||
#define VK_VOLUME_UP 0xAF
|
||||
// VK_MEDIA_NEXT_TRACK (B0) Windows 2000/XP: Next Track key
|
||||
#define VK_MEDIA_NEXT_TRACK 0xB0
|
||||
// VK_MEDIA_PREV_TRACK (B1) Windows 2000/XP: Previous Track key
|
||||
#define VK_MEDIA_PREV_TRACK 0xB1
|
||||
// VK_MEDIA_STOP (B2) Windows 2000/XP: Stop Media key
|
||||
#define VK_MEDIA_STOP 0xB2
|
||||
// VK_MEDIA_PLAY_PAUSE (B3) Windows 2000/XP: Play/Pause Media key
|
||||
#define VK_MEDIA_PLAY_PAUSE 0xB3
|
||||
// VK_LAUNCH_MAIL (B4) Windows 2000/XP: Start Mail key
|
||||
#define VK_MEDIA_LAUNCH_MAIL 0xB4
|
||||
// VK_LAUNCH_MEDIA_SELECT (B5) Windows 2000/XP: Select Media key
|
||||
#define VK_MEDIA_LAUNCH_MEDIA_SELECT 0xB5
|
||||
// VK_LAUNCH_APP1 (B6) Windows 2000/XP: Start Application 1 key
|
||||
#define VK_MEDIA_LAUNCH_APP1 0xB6
|
||||
// VK_LAUNCH_APP2 (B7) Windows 2000/XP: Start Application 2 key
|
||||
#define VK_MEDIA_LAUNCH_APP2 0xB7
|
||||
// VK_OEM_1 (BA) Used for miscellaneous characters; it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the ';:' key
|
||||
#define VK_OEM_1 0xBA
|
||||
// VK_OEM_PLUS (BB) Windows 2000/XP: For any country/region, the '+' key
|
||||
#define VK_OEM_PLUS 0xBB
|
||||
// VK_OEM_COMMA (BC) Windows 2000/XP: For any country/region, the ',' key
|
||||
#define VK_OEM_COMMA 0xBC
|
||||
// VK_OEM_MINUS (BD) Windows 2000/XP: For any country/region, the '-' key
|
||||
#define VK_OEM_MINUS 0xBD
|
||||
// VK_OEM_PERIOD (BE) Windows 2000/XP: For any country/region, the '.' key
|
||||
#define VK_OEM_PERIOD 0xBE
|
||||
// VK_OEM_2 (BF) Used for miscellaneous characters; it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the '/?' key
|
||||
#define VK_OEM_2 0xBF
|
||||
// VK_OEM_3 (C0) Used for miscellaneous characters; it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the '`~' key
|
||||
#define VK_OEM_3 0xC0
|
||||
// VK_OEM_4 (DB) Used for miscellaneous characters; it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the '[{' key
|
||||
#define VK_OEM_4 0xDB
|
||||
// VK_OEM_5 (DC) Used for miscellaneous characters; it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the '\|' key
|
||||
#define VK_OEM_5 0xDC
|
||||
// VK_OEM_6 (DD) Used for miscellaneous characters; it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the ']}' key
|
||||
#define VK_OEM_6 0xDD
|
||||
// VK_OEM_7 (DE) Used for miscellaneous characters; it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the 'single-quote/double-quote' key
|
||||
#define VK_OEM_7 0xDE
|
||||
// VK_OEM_8 (DF) Used for miscellaneous characters; it can vary by keyboard.
|
||||
#define VK_OEM_8 0xDF
|
||||
// VK_OEM_102 (E2) Windows 2000/XP: Either the angle bracket key or the backslash key on the RT 102-key keyboard
|
||||
#define VK_OEM_102 0xE2
|
||||
// VK_PROCESSKEY (E5) Windows 95/98/Me, Windows NT 4.0, Windows 2000/XP: IME PROCESS key
|
||||
#define VK_PROCESSKEY 0xE5
|
||||
// VK_PACKET (E7) Windows 2000/XP: Used to pass Unicode characters as if they were keystrokes. The VK_PACKET key is the low word of a 32-bit Virtual Key value used for non-keyboard input methods. For more information, see Remark in KEYBDINPUT,SendInput, WM_KEYDOWN, and WM_KEYUP
|
||||
#define VK_PACKET 0xE7
|
||||
// VK_ATTN (F6) Attn key
|
||||
#define VK_ATTN 0xF6
|
||||
// VK_CRSEL (F7) CrSel key
|
||||
#define VK_CRSEL 0xF7
|
||||
// VK_EXSEL (F8) ExSel key
|
||||
#define VK_EXSEL 0xF8
|
||||
// VK_EREOF (F9) Erase EOF key
|
||||
#define VK_EREOF 0xF9
|
||||
// VK_PLAY (FA) Play key
|
||||
#define VK_PLAY 0xFA
|
||||
// VK_ZOOM (FB) Zoom key
|
||||
#define VK_ZOOM 0xFB
|
||||
// VK_NONAME (FC) Reserved for future use
|
||||
#define VK_NONAME 0xFC
|
||||
// VK_PA1 (FD) PA1 key
|
||||
#define VK_PA1 0xFD
|
||||
// VK_OEM_CLEAR (FE) Clear key
|
||||
#define VK_OEM_CLEAR 0xFE
|
||||
#define VK_UNKNOWN 0
|
||||
|
||||
struct keymap_t {
|
||||
unsigned int keycode;
|
||||
unsigned char vk;
|
||||
};
|
||||
|
||||
extern void MouseAction(double absX, double absY, int button, short wheel);
|
||||
extern void KeyAction(unsigned char vk, int up);
|
||||
|
||||
#endif /* LINUX_EVENTS_H_ */
|
||||
691
meshcore/KVM/MacOS/mac_kvm.c
Normal file
691
meshcore/KVM/MacOS/mac_kvm.c
Normal file
@@ -0,0 +1,691 @@
|
||||
/*
|
||||
Copyright 2010 - 2018 Intel Corporation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#include "mac_kvm.h"
|
||||
#include "../../meshdefines.h"
|
||||
#include "../../meshinfo.h"
|
||||
#include "../../../microstack/ILibParsers.h"
|
||||
#include "../../../microstack/ILibAsyncSocket.h"
|
||||
#include "../../../microstack/ILibAsyncServerSocket.h"
|
||||
#include "../../../microstack/ILibProcessPipe.h"
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
|
||||
int KVM_Listener_FD = -1;
|
||||
#define KVM_Listener_Path "/usr/local/mesh_services/mesh2/kvm"
|
||||
|
||||
int KVM_AGENT_FD = -1;
|
||||
int KVM_SEND(char *buffer, int bufferLen)
|
||||
{
|
||||
int retVal = -1;
|
||||
retVal = write(KVM_AGENT_FD == -1 ? STDOUT_FILENO : KVM_AGENT_FD, buffer, bufferLen);
|
||||
if (KVM_AGENT_FD == -1) { fsync(STDOUT_FILENO); }
|
||||
else
|
||||
{
|
||||
if (retVal < 0)
|
||||
{
|
||||
char tmp[255];
|
||||
int tmpLen = sprintf_s(tmp, sizeof(tmp), "Write Error: %d on %d\n", errno, KVM_AGENT_FD);
|
||||
write(STDOUT_FILENO, tmp, tmpLen);
|
||||
fsync(STDOUT_FILENO);
|
||||
}
|
||||
}
|
||||
return(retVal);
|
||||
}
|
||||
|
||||
|
||||
|
||||
CGDirectDisplayID SCREEN_NUM = 0;
|
||||
int SH_HANDLE = 0;
|
||||
int SCREEN_WIDTH = 0;
|
||||
int SCREEN_HEIGHT = 0;
|
||||
int SCREEN_DEPTH = 0;
|
||||
int TILE_WIDTH = 0;
|
||||
int TILE_HEIGHT = 0;
|
||||
int TILE_WIDTH_COUNT = 0;
|
||||
int TILE_HEIGHT_COUNT = 0;
|
||||
int COMPRESSION_RATIO = 0;
|
||||
int FRAME_RATE_TIMER = 0;
|
||||
struct tileInfo_t **g_tileInfo = NULL;
|
||||
int g_remotepause = 0;
|
||||
int g_pause = 0;
|
||||
int g_shutdown = 0;
|
||||
int g_resetipc = 0;
|
||||
int kvm_clientProcessId = 0;
|
||||
int g_restartcount = 0;
|
||||
int g_totalRestartCount = 0;
|
||||
int restartKvm = 0;
|
||||
extern void* tilebuffer;
|
||||
pid_t g_slavekvm = 0;
|
||||
pthread_t kvmthread = (pthread_t)NULL;
|
||||
ILibProcessPipe_Process gChildProcess;
|
||||
|
||||
//int logenabled = 1;
|
||||
//FILE *logfile = NULL;
|
||||
//#define MASTERLOGFILE "/dev/null"
|
||||
//#define SLAVELOGFILE "/dev/null"
|
||||
//#define LOGFILE "/dev/null"
|
||||
|
||||
|
||||
#define KvmDebugLog(...)
|
||||
//#define KvmDebugLog(...) printf(__VA_ARGS__); //if (logfile != NULL) fprintf(logfile, __VA_ARGS__);
|
||||
//#define KvmDebugLog(x) if (logenabled) printf(x);
|
||||
//#define KvmDebugLog(x) if (logenabled) fprintf(logfile, "Writing from slave in kvm_send_resolution\n");
|
||||
|
||||
void senddebug(int val)
|
||||
{
|
||||
char buffer[8];
|
||||
|
||||
((unsigned short*)buffer)[0] = (unsigned short)htons((unsigned short)MNG_DEBUG); // Write the type
|
||||
((unsigned short*)buffer)[1] = (unsigned short)htons((unsigned short)8); // Write the size
|
||||
((int*)buffer)[1] = val;
|
||||
|
||||
KVM_SEND(buffer, 8);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void kvm_send_resolution()
|
||||
{
|
||||
char buffer[8];
|
||||
|
||||
((unsigned short*)buffer)[0] = (unsigned short)htons((unsigned short)MNG_KVM_SCREEN); // Write the type
|
||||
((unsigned short*)buffer)[1] = (unsigned short)htons((unsigned short)8); // Write the size
|
||||
((unsigned short*)buffer)[2] = (unsigned short)htons((unsigned short)SCREEN_WIDTH); // X position
|
||||
((unsigned short*)buffer)[3] = (unsigned short)htons((unsigned short)SCREEN_HEIGHT); // Y position
|
||||
|
||||
|
||||
// Write the reply to the pipe.
|
||||
KVM_SEND(buffer, 8);
|
||||
}
|
||||
|
||||
#define BUFSIZE 65535
|
||||
|
||||
int kvm_init()
|
||||
{
|
||||
int old_height_count = TILE_HEIGHT_COUNT;
|
||||
|
||||
SCREEN_NUM = CGMainDisplayID();
|
||||
SCREEN_HEIGHT = CGDisplayPixelsHigh(SCREEN_NUM);
|
||||
SCREEN_WIDTH = CGDisplayPixelsWide(SCREEN_NUM);
|
||||
|
||||
// Some magic numbers.
|
||||
TILE_WIDTH = 32;
|
||||
TILE_HEIGHT = 32;
|
||||
COMPRESSION_RATIO = 50;
|
||||
FRAME_RATE_TIMER = 100;
|
||||
|
||||
TILE_HEIGHT_COUNT = SCREEN_HEIGHT / TILE_HEIGHT;
|
||||
TILE_WIDTH_COUNT = SCREEN_WIDTH / TILE_WIDTH;
|
||||
if (SCREEN_WIDTH % TILE_WIDTH) { TILE_WIDTH_COUNT++; }
|
||||
if (SCREEN_HEIGHT % TILE_HEIGHT) { TILE_HEIGHT_COUNT++; }
|
||||
|
||||
kvm_send_resolution();
|
||||
|
||||
reset_tile_info(old_height_count);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// void CheckDesktopSwitch(int checkres) { return; }
|
||||
|
||||
int kvm_server_inputdata(char* block, int blocklen)
|
||||
{
|
||||
unsigned short type, size;
|
||||
//CheckDesktopSwitch(0);
|
||||
|
||||
//senddebug(100+blocklen);
|
||||
|
||||
// Decode the block header
|
||||
if (blocklen < 4) return 0;
|
||||
type = ntohs(((unsigned short*)(block))[0]);
|
||||
size = ntohs(((unsigned short*)(block))[1]);
|
||||
|
||||
if (size > blocklen) return 0;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case MNG_KVM_KEY: // Key
|
||||
{
|
||||
if (size != 6 || KVM_AGENT_FD != -1) { break; }
|
||||
KeyAction(block[5], block[4]);
|
||||
break;
|
||||
}
|
||||
case MNG_KVM_MOUSE: // Mouse
|
||||
{
|
||||
int x, y;
|
||||
short w = 0;
|
||||
if (KVM_AGENT_FD != -1) { break; }
|
||||
if (size == 10 || size == 12)
|
||||
{
|
||||
x = ((int)ntohs(((unsigned short*)(block))[3]));
|
||||
y = ((int)ntohs(((unsigned short*)(block))[4]));
|
||||
if (size == 12) w = ((short)ntohs(((short*)(block))[5]));
|
||||
//printf("x:%d, y:%d, b:%d, w:%d\n", x, y, block[5], w);
|
||||
MouseAction(x, y, block[5], w);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MNG_KVM_COMPRESSION: // Compression
|
||||
{
|
||||
if (size != 6) break;
|
||||
set_tile_compression((int)block[4], (int)block[5]);
|
||||
COMPRESSION_RATIO = 100;
|
||||
break;
|
||||
}
|
||||
case MNG_KVM_REFRESH: // Refresh
|
||||
{
|
||||
int row, col;
|
||||
if (size != 4) break;
|
||||
if (g_tileInfo == NULL) {
|
||||
if ((g_tileInfo = (struct tileInfo_t **) malloc(TILE_HEIGHT_COUNT * sizeof(struct tileInfo_t *))) == NULL) ILIBCRITICALEXIT(254);
|
||||
for (row = 0; row < TILE_HEIGHT_COUNT; row++) {
|
||||
if ((g_tileInfo[row] = (struct tileInfo_t *) malloc(TILE_WIDTH_COUNT * sizeof(struct tileInfo_t))) == NULL) ILIBCRITICALEXIT(254);
|
||||
}
|
||||
}
|
||||
for (row = 0; row < TILE_HEIGHT_COUNT; row++) {
|
||||
for (col = 0; col < TILE_WIDTH_COUNT; col++) {
|
||||
g_tileInfo[row][col].crc = 0xFF;
|
||||
g_tileInfo[row][col].flag = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MNG_KVM_PAUSE: // Pause
|
||||
{
|
||||
if (size != 5) break;
|
||||
g_remotepause = block[4];
|
||||
break;
|
||||
}
|
||||
case MNG_KVM_FRAME_RATE_TIMER:
|
||||
{
|
||||
//int fr = ((int)ntohs(((unsigned short*)(block))[2]));
|
||||
//if (fr > 20 && fr < 2000) FRAME_RATE_TIMER = fr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
|
||||
int kvm_relay_feeddata(char* buf, int len)
|
||||
{
|
||||
ILibProcessPipe_Process_WriteStdIn(gChildProcess, buf, len, ILibTransport_MemoryOwnership_USER);
|
||||
return(len);
|
||||
}
|
||||
|
||||
// Set the KVM pause state
|
||||
void kvm_pause(int pause)
|
||||
{
|
||||
g_pause = pause;
|
||||
}
|
||||
|
||||
|
||||
void* kvm_mainloopinput(void* param)
|
||||
{
|
||||
int ptr = 0;
|
||||
int ptr2 = 0;
|
||||
int len = 0;
|
||||
char* pchRequest2[30000];
|
||||
int cbBytesRead = 0;
|
||||
|
||||
char tmp[255];
|
||||
int tmpLen;
|
||||
|
||||
if (KVM_AGENT_FD == -1)
|
||||
{
|
||||
int flags;
|
||||
flags = fcntl(STDIN_FILENO, F_GETFL, 0);
|
||||
if (fcntl(STDIN_FILENO, F_SETFL, (O_NONBLOCK | flags) ^ O_NONBLOCK) == -1) { senddebug(-999); }
|
||||
}
|
||||
|
||||
while (!g_shutdown)
|
||||
{
|
||||
if (KVM_AGENT_FD != -1)
|
||||
{
|
||||
tmpLen = sprintf_s(tmp, sizeof(tmp), "About to read from IPC Socket\n");
|
||||
write(STDOUT_FILENO, tmp, tmpLen);
|
||||
fsync(STDOUT_FILENO);
|
||||
}
|
||||
|
||||
KvmDebugLog("Reading from master in kvm_mainloopinput\n");
|
||||
cbBytesRead = read(KVM_AGENT_FD == -1 ? STDIN_FILENO: KVM_AGENT_FD, pchRequest2 + len, 30000 - len);
|
||||
KvmDebugLog("Read %d bytes from master in kvm_mainloopinput\n", cbBytesRead);
|
||||
|
||||
if (KVM_AGENT_FD != -1)
|
||||
{
|
||||
tmpLen = sprintf_s(tmp, sizeof(tmp), "Read %d bytes from IPC-xx-Socket\n", cbBytesRead);
|
||||
write(STDOUT_FILENO, tmp, tmpLen);
|
||||
fsync(STDOUT_FILENO);
|
||||
}
|
||||
|
||||
if (cbBytesRead == -1 || cbBytesRead == 0)
|
||||
{
|
||||
/*ILIBMESSAGE("KVMBREAK-K1\r\n"); g_shutdown = 1; printf("shutdown\n");*/
|
||||
if (KVM_AGENT_FD == -1)
|
||||
{
|
||||
g_shutdown = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_resetipc = 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
len += cbBytesRead;
|
||||
ptr2 = 0;
|
||||
|
||||
if (KVM_AGENT_FD != -1)
|
||||
{
|
||||
tmpLen = sprintf_s(tmp, sizeof(tmp), "enter while\n");
|
||||
write(STDOUT_FILENO, tmp, tmpLen);
|
||||
fsync(STDOUT_FILENO);
|
||||
}
|
||||
while ((ptr2 = kvm_server_inputdata((char*)pchRequest2 + ptr, cbBytesRead - ptr)) != 0) { ptr += ptr2; }
|
||||
|
||||
if (KVM_AGENT_FD != -1)
|
||||
{
|
||||
tmpLen = sprintf_s(tmp, sizeof(tmp), "exited while\n");
|
||||
write(STDOUT_FILENO, tmp, tmpLen);
|
||||
fsync(STDOUT_FILENO);
|
||||
}
|
||||
|
||||
if (ptr == len) { len = 0; ptr = 0; }
|
||||
// TODO: else move the reminder.
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
void ExitSink(int s)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(s);
|
||||
|
||||
signal(SIGTERM, SIG_IGN);
|
||||
|
||||
if (KVM_Listener_FD > 0)
|
||||
{
|
||||
write(STDOUT_FILENO, "EXITING\n", 8);
|
||||
fsync(STDOUT_FILENO);
|
||||
close(KVM_Listener_FD);
|
||||
}
|
||||
g_shutdown = 1;
|
||||
}
|
||||
void* kvm_server_mainloop(void* param)
|
||||
{
|
||||
CGDirectDisplayID displays[10];
|
||||
int x, y, height, width, r, c = 0;
|
||||
long long desktopsize = 0;
|
||||
long long tilesize = 0;
|
||||
long long prev_timestamp = 0;
|
||||
long long cur_timestamp = 0;
|
||||
long long time_diff = 50;
|
||||
struct timeb tp;
|
||||
void *desktop = NULL;
|
||||
void *buf = NULL;
|
||||
int screen_height, screen_width, screen_num;
|
||||
int written = 0;
|
||||
struct sockaddr_un serveraddr;
|
||||
|
||||
if (param == NULL)
|
||||
{
|
||||
// This is doing I/O via StdIn/StdOut
|
||||
|
||||
int flags;
|
||||
flags = fcntl(STDOUT_FILENO, F_GETFL, 0);
|
||||
if (fcntl(STDOUT_FILENO, F_SETFL, (O_NONBLOCK | flags) ^ O_NONBLOCK) == -1) {}
|
||||
}
|
||||
else
|
||||
{
|
||||
// this is doing I/O via a Unix Domain Socket
|
||||
if ((KVM_Listener_FD = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
|
||||
{
|
||||
char tmp[255];
|
||||
int tmplen = sprintf_s(tmp, sizeof(tmp), "ERROR CREATING DOMAIN SOCKET: %d\n", errno);
|
||||
// Error creating domain socket
|
||||
written = write(STDOUT_FILENO, tmp, tmplen);
|
||||
fsync(STDOUT_FILENO);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
int flags;
|
||||
flags = fcntl(KVM_Listener_FD, F_GETFL, 0);
|
||||
if (fcntl(KVM_Listener_FD, F_SETFL, (O_NONBLOCK | flags) ^ O_NONBLOCK) == -1) { }
|
||||
|
||||
written = write(STDOUT_FILENO, "Set FCNTL2\n", 11);
|
||||
fsync(STDOUT_FILENO);
|
||||
|
||||
memset(&serveraddr, 0, sizeof(serveraddr));
|
||||
serveraddr.sun_family = AF_UNIX;
|
||||
strcpy(serveraddr.sun_path, KVM_Listener_Path);
|
||||
remove(KVM_Listener_Path);
|
||||
if (bind(KVM_Listener_FD, (struct sockaddr *)&serveraddr, SUN_LEN(&serveraddr)) < 0)
|
||||
{
|
||||
char tmp[255];
|
||||
int tmplen = sprintf_s(tmp, sizeof(tmp), "BIND ERROR on DOMAIN SOCKET: %d\n", errno);
|
||||
// Error creating domain socket
|
||||
written = write(STDOUT_FILENO, tmp, tmplen);
|
||||
fsync(STDOUT_FILENO);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
if (listen(KVM_Listener_FD, 1) < 0)
|
||||
{
|
||||
written = write(STDOUT_FILENO, "LISTEN ERROR ON DOMAIN SOCKET", 29);
|
||||
fsync(STDOUT_FILENO);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
written = write(STDOUT_FILENO, "LISTENING ON DOMAIN SOCKET\n", 27);
|
||||
fsync(STDOUT_FILENO);
|
||||
|
||||
signal(SIGTERM, ExitSink);
|
||||
|
||||
if ((KVM_AGENT_FD = accept(KVM_Listener_FD, NULL, NULL)) < 0)
|
||||
{
|
||||
written = write(STDOUT_FILENO, "ACCEPT ERROR ON DOMAIN SOCKET", 29);
|
||||
fsync(STDOUT_FILENO);
|
||||
return(NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
char tmp[255];
|
||||
int tmpLen = sprintf_s(tmp, sizeof(tmp), "ACCEPTed new connection %d on Domain Socket\n", KVM_AGENT_FD);
|
||||
written = write(STDOUT_FILENO, tmp, tmpLen);
|
||||
fsync(STDOUT_FILENO);
|
||||
|
||||
}
|
||||
}
|
||||
// Init the kvm
|
||||
if (kvm_init() != 0) { return (void*)-1; }
|
||||
|
||||
|
||||
g_shutdown = 0;
|
||||
pthread_create(&kvmthread, NULL, kvm_mainloopinput, param);
|
||||
|
||||
|
||||
if (KVM_AGENT_FD != -1)
|
||||
{
|
||||
written = write(STDOUT_FILENO, "Starting Loop []\n", 14);
|
||||
fsync(STDOUT_FILENO);
|
||||
|
||||
char stmp[255];
|
||||
int stmpLen = sprintf_s(stmp, sizeof(stmp), "TILE_HEIGHT_COUNT=%d, TILE_WIDTH_COUNT=%d\n", TILE_HEIGHT_COUNT, TILE_WIDTH_COUNT);
|
||||
written = write(STDOUT_FILENO, stmp, stmpLen);
|
||||
fsync(STDOUT_FILENO);
|
||||
}
|
||||
|
||||
while (!g_shutdown)
|
||||
{
|
||||
if (g_resetipc != 0)
|
||||
{
|
||||
g_resetipc = 0;
|
||||
close(KVM_AGENT_FD);
|
||||
|
||||
SCREEN_HEIGHT = SCREEN_WIDTH = 0;
|
||||
|
||||
char stmp[255];
|
||||
int stmpLen = sprintf_s(stmp, sizeof(stmp), "Waiting for NEXT DomainSocket, TILE_HEIGHT_COUNT=%d, TILE_WIDTH_COUNT=%d\n", TILE_HEIGHT_COUNT, TILE_WIDTH_COUNT);
|
||||
written = write(STDOUT_FILENO, stmp, stmpLen);
|
||||
fsync(STDOUT_FILENO);
|
||||
|
||||
if ((KVM_AGENT_FD = accept(KVM_Listener_FD, NULL, NULL)) < 0)
|
||||
{
|
||||
g_shutdown = 1;
|
||||
written = write(STDOUT_FILENO, "ACCEPT ERROR ON DOMAIN SOCKET", 29);
|
||||
fsync(STDOUT_FILENO);
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
char tmp[255];
|
||||
int tmpLen = sprintf_s(tmp, sizeof(tmp), "ACCEPTed new connection %d on Domain Socket\n", KVM_AGENT_FD);
|
||||
written = write(STDOUT_FILENO, tmp, tmpLen);
|
||||
fsync(STDOUT_FILENO);
|
||||
pthread_create(&kvmthread, NULL, kvm_mainloopinput, param);
|
||||
}
|
||||
}
|
||||
|
||||
for (r = 0; r < TILE_HEIGHT_COUNT; r++) {
|
||||
for (c = 0; c < TILE_WIDTH_COUNT; c++) {
|
||||
g_tileInfo[r][c].flag = TILE_TODO;
|
||||
}
|
||||
}
|
||||
//senddebug(2);
|
||||
screen_num = CGMainDisplayID();
|
||||
|
||||
if (screen_num == 0) { g_shutdown = 1; senddebug(-2); break; }
|
||||
screen_height = CGDisplayPixelsHigh(screen_num);
|
||||
screen_width = CGDisplayPixelsWide(screen_num);
|
||||
|
||||
if ((SCREEN_HEIGHT != screen_height || SCREEN_WIDTH != screen_width || SCREEN_NUM != screen_num))
|
||||
{
|
||||
kvm_init();
|
||||
continue;
|
||||
}
|
||||
|
||||
//senddebug(screen_num);
|
||||
CGImageRef image = CGDisplayCreateImage(screen_num);
|
||||
//senddebug(99);
|
||||
if (image == NULL)
|
||||
{
|
||||
g_shutdown = 1;
|
||||
senddebug(0);
|
||||
}
|
||||
else {
|
||||
//senddebug(100);
|
||||
getScreenBuffer((unsigned char **)&desktop, &desktopsize, image);
|
||||
|
||||
if (KVM_AGENT_FD != -1)
|
||||
{
|
||||
char tmp[255];
|
||||
int tmpLen = sprintf_s(tmp, sizeof(tmp), "...Enter for loop\n");
|
||||
written = write(STDOUT_FILENO, tmp, tmpLen);
|
||||
fsync(STDOUT_FILENO);
|
||||
}
|
||||
|
||||
|
||||
|
||||
for (y = 0; y < TILE_HEIGHT_COUNT; y++)
|
||||
{
|
||||
for (x = 0; x < TILE_WIDTH_COUNT; x++) {
|
||||
height = TILE_HEIGHT * y;
|
||||
width = TILE_WIDTH * x;
|
||||
if (!g_shutdown && (g_pause)) { usleep(100000); g_pause = 0; } //HACK: Change this
|
||||
|
||||
if (g_shutdown) { x = TILE_WIDTH_COUNT; y = TILE_HEIGHT_COUNT; break; }
|
||||
|
||||
if (g_tileInfo[y][x].flag == TILE_SENT || g_tileInfo[y][x].flag == TILE_DONT_SEND) {
|
||||
continue;
|
||||
}
|
||||
|
||||
getTileAt(width, height, &buf, &tilesize, desktop, desktopsize, y, x);
|
||||
|
||||
if (buf && !g_shutdown)
|
||||
{
|
||||
// Write the reply to the pipe.
|
||||
//KvmDebugLog("Writing to master in kvm_server_mainloop\n");
|
||||
|
||||
written = KVM_SEND(buf, tilesize);
|
||||
|
||||
//KvmDebugLog("Wrote %d bytes to master in kvm_server_mainloop\n", written);
|
||||
if (written == -1)
|
||||
{
|
||||
/*ILIBMESSAGE("KVMBREAK-K2\r\n");*/
|
||||
if(KVM_AGENT_FD == -1)
|
||||
{
|
||||
// This is a User Session, so if the connection fails, we exit out... We can be spawned again later
|
||||
g_shutdown = 1; height = SCREEN_HEIGHT; width = SCREEN_WIDTH; break;
|
||||
}
|
||||
}
|
||||
//else
|
||||
//{
|
||||
// char tmp[255];
|
||||
// int tmpLen = sprintf_s(tmp, sizeof(tmp), "KVM_SEND => tilesize: %d\n", tilesize);
|
||||
// written = write(STDOUT_FILENO, tmp, tmpLen);
|
||||
// fsync(STDOUT_FILENO);
|
||||
//}
|
||||
free(buf);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (KVM_AGENT_FD != -1)
|
||||
{
|
||||
char tmp[255];
|
||||
int tmpLen = sprintf_s(tmp, sizeof(tmp), "...exit for loop\n");
|
||||
written = write(STDOUT_FILENO, tmp, tmpLen);
|
||||
fsync(STDOUT_FILENO);
|
||||
}
|
||||
|
||||
}
|
||||
CGImageRelease(image);
|
||||
}
|
||||
|
||||
pthread_join(kvmthread, NULL);
|
||||
kvmthread = (pthread_t)NULL;
|
||||
|
||||
if (g_tileInfo != NULL) { for (r = 0; r < TILE_HEIGHT_COUNT; r++) { free(g_tileInfo[r]); } }
|
||||
g_tileInfo = NULL;
|
||||
if(tilebuffer != NULL) {
|
||||
free(tilebuffer);
|
||||
tilebuffer = NULL;
|
||||
}
|
||||
|
||||
if (KVM_AGENT_FD != -1)
|
||||
{
|
||||
written = write(STDOUT_FILENO, "Exiting...\n", 11);
|
||||
fsync(STDOUT_FILENO);
|
||||
}
|
||||
return (void*)0;
|
||||
}
|
||||
|
||||
void kvm_relay_ExitHandler(ILibProcessPipe_Process sender, int exitCode, void* user)
|
||||
{
|
||||
ILibKVM_WriteHandler writeHandler = (ILibKVM_WriteHandler)((void**)user)[0];
|
||||
void *reserved = ((void**)user)[1];
|
||||
void *pipeMgr = ((void**)user)[2];
|
||||
char *exePath = (char*)((void**)user)[3];
|
||||
}
|
||||
void kvm_relay_StdOutHandler(ILibProcessPipe_Process sender, char *buffer, int bufferLen, int* bytesConsumed, void* user)
|
||||
{
|
||||
unsigned short size = 0;
|
||||
UNREFERENCED_PARAMETER(sender);
|
||||
ILibKVM_WriteHandler writeHandler = (ILibKVM_WriteHandler)((void**)user)[0];
|
||||
void *reserved = ((void**)user)[1];
|
||||
|
||||
if (bufferLen > 4)
|
||||
{
|
||||
size = ntohs(((unsigned short*)(buffer))[1]);
|
||||
if (size <= bufferLen)
|
||||
{
|
||||
if (ntohs(((unsigned short*)(buffer))[0]) == MNG_DEBUG)
|
||||
{
|
||||
char tmp[255];
|
||||
int x = sprintf_s(tmp, sizeof(tmp), "DEBUG: %d\n", ((int*)buffer)[1]);
|
||||
|
||||
write(STDOUT_FILENO, tmp, x);
|
||||
}
|
||||
*bytesConsumed = size;
|
||||
writeHandler(buffer, size, reserved);
|
||||
return;
|
||||
}
|
||||
}
|
||||
*bytesConsumed = 0;
|
||||
}
|
||||
void kvm_relay_StdErrHandler(ILibProcessPipe_Process sender, char *buffer, int bufferLen, int* bytesConsumed, void* user)
|
||||
{
|
||||
//KVMDebugLog *log = (KVMDebugLog*)buffer;
|
||||
|
||||
//UNREFERENCED_PARAMETER(sender);
|
||||
//UNREFERENCED_PARAMETER(user);
|
||||
|
||||
//if (bufferLen < sizeof(KVMDebugLog) || bufferLen < log->length) { *bytesConsumed = 0; return; }
|
||||
//*bytesConsumed = log->length;
|
||||
////ILibRemoteLogging_printf(ILibChainGetLogger(gILibChain), (ILibRemoteLogging_Modules)log->logType, (ILibRemoteLogging_Flags)log->logFlags, "%s", log->logData);
|
||||
//ILibRemoteLogging_printf(ILibChainGetLogger(gILibChain), ILibRemoteLogging_Modules_Microstack_Generic, (ILibRemoteLogging_Flags)log->logFlags, "%s", log->logData);
|
||||
*bytesConsumed = bufferLen;
|
||||
}
|
||||
|
||||
|
||||
// Setup the KVM session. Return 1 if ok, 0 if it could not be setup.
|
||||
void* kvm_relay_setup(char *exePath, void *processPipeMgr, ILibKVM_WriteHandler writeHandler, void *reserved, int uid)
|
||||
{
|
||||
char * parms0[] = { "meshagent_osx64", "-kvm0", NULL };
|
||||
void **user = (void**)ILibMemory_Allocate(4 * sizeof(void*), 0, NULL, NULL);
|
||||
user[0] = writeHandler;
|
||||
user[1] = reserved;
|
||||
user[2] = processPipeMgr;
|
||||
user[3] = exePath;
|
||||
|
||||
char tmp[255];
|
||||
int x;
|
||||
|
||||
if (uid != 0)
|
||||
{
|
||||
// Spawn child kvm process into a specific user session
|
||||
|
||||
x = sprintf_s(tmp, sizeof(tmp), "Spawning Process: %d\n", uid);
|
||||
write(STDOUT_FILENO, tmp, x);
|
||||
gChildProcess = ILibProcessPipe_Manager_SpawnProcessEx3(processPipeMgr, exePath, parms0, ILibProcessPipe_SpawnTypes_DEFAULT, (void*)(uint64_t)uid, 0);
|
||||
|
||||
x = sprintf_s(tmp, sizeof(tmp), "Result: %p\n", (void*)gChildProcess);
|
||||
write(STDOUT_FILENO, tmp, x);
|
||||
|
||||
g_slavekvm = ILibProcessPipe_Process_GetPID(gChildProcess);
|
||||
ILibProcessPipe_Process_AddHandlers(gChildProcess, 65535, &kvm_relay_ExitHandler, &kvm_relay_StdOutHandler, &kvm_relay_StdErrHandler, NULL, user);
|
||||
|
||||
// Run the relay
|
||||
g_shutdown = 0;
|
||||
return(ILibProcessPipe_Process_GetStdOut(gChildProcess));
|
||||
}
|
||||
else
|
||||
{
|
||||
// No users are logged in. This is a special case for MacOS
|
||||
//int fd = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
//if (!fd < 0)
|
||||
//{
|
||||
// struct sockaddr_un serveraddr;
|
||||
// memset(&serveraddr, 0, sizeof(serveraddr));
|
||||
// serveraddr.sun_family = AF_UNIX;
|
||||
// strcpy(serveraddr.sun_path, KVM_Listener_Path);
|
||||
// if (!connect(fd, (struct sockaddr *)&serveraddr, SUN_LEN(&serveraddr)) < 0)
|
||||
// {
|
||||
// return((void*)(uint64_t)fd);
|
||||
// }
|
||||
//}
|
||||
return((void*)KVM_Listener_Path);
|
||||
}
|
||||
}
|
||||
|
||||
// Force a KVM reset & refresh
|
||||
void kvm_relay_reset()
|
||||
{
|
||||
char buffer[4];
|
||||
((unsigned short*)buffer)[0] = (unsigned short)htons((unsigned short)MNG_KVM_REFRESH); // Write the type
|
||||
((unsigned short*)buffer)[1] = (unsigned short)htons((unsigned short)4); // Write the size
|
||||
kvm_relay_feeddata(buffer, 4);
|
||||
}
|
||||
|
||||
// Clean up the KVM session.
|
||||
void kvm_cleanup()
|
||||
{
|
||||
KvmDebugLog("kvm_cleanup\n");
|
||||
g_shutdown = 1;
|
||||
}
|
||||
36
meshcore/KVM/MacOS/mac_kvm.h
Normal file
36
meshcore/KVM/MacOS/mac_kvm.h
Normal file
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* mac_kvm.h
|
||||
*
|
||||
*
|
||||
* Created by Ylian Saint-Hilaire on 8/17/11.
|
||||
* Copyright 2011 __MyCompanyName__. All rights reserved.
|
||||
*
|
||||
*/
|
||||
#ifndef LINUX_KVM_H_
|
||||
#define LINUX_KVM_H_
|
||||
|
||||
#include <ApplicationServices/ApplicationServices.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <pthread.h>
|
||||
#include <dirent.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/timeb.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "mac_tile.h"
|
||||
#include "mac_events.h"
|
||||
#include "../../../microstack/ILibParsers.h"
|
||||
|
||||
typedef ILibTransport_DoneState(*ILibKVM_WriteHandler)(char *buffer, int bufferLen, void *reserved);
|
||||
|
||||
int kvm_relay_feeddata(char* buf, int len);
|
||||
void kvm_pause(int pause);
|
||||
void* kvm_relay_setup(char *exePath, void *processPipeMgr, ILibKVM_WriteHandler writeHandler, void *reserved, int uid);
|
||||
void kvm_relay_reset();
|
||||
void kvm_cleanup();
|
||||
|
||||
#endif /* LINUX_KVM_H_ */
|
||||
|
||||
507
meshcore/KVM/MacOS/mac_tile.c
Normal file
507
meshcore/KVM/MacOS/mac_tile.c
Normal file
@@ -0,0 +1,507 @@
|
||||
/*
|
||||
* mac_tile.c
|
||||
*
|
||||
*
|
||||
* Created by Ylian Saint-Hilaire on 8/18/11.
|
||||
* Copyright 2011 __MyCompanyName__. All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mac_tile.h"
|
||||
#include "../../meshinfo.h"
|
||||
#include "../../meshdefines.h"
|
||||
|
||||
extern CGDirectDisplayID SCREEN_NUM;
|
||||
extern int SCREEN_WIDTH;
|
||||
extern int SCREEN_HEIGHT;
|
||||
extern int SCREEN_DEPTH;
|
||||
extern int TILE_WIDTH;
|
||||
extern int TILE_HEIGHT;
|
||||
extern int TILE_WIDTH_COUNT;
|
||||
extern int TILE_HEIGHT_COUNT;
|
||||
extern int COMPRESSION_RATIO;
|
||||
extern struct tileInfo_t **g_tileInfo;
|
||||
extern unsigned char *jpeg_buffer;
|
||||
extern int jpeg_buffer_length;
|
||||
|
||||
int tilebuffersize = 0;
|
||||
void* tilebuffer = NULL;
|
||||
int COMPRESSION_QUALITY = 50;
|
||||
|
||||
/******************************************************************************
|
||||
* INTERNAL FUNCTIONS
|
||||
******************************************************************************/
|
||||
|
||||
//Extracts the required tile buffer from the desktop buffer
|
||||
int get_tile_buffer(int x, int y, void **buffer, long long bufferSize, void *desktop, long long desktopsize, int tilewidth, int tileheight)
|
||||
{
|
||||
char *target = *buffer;
|
||||
int height = 0;
|
||||
|
||||
for (height = y; height < y + tileheight; height++) {
|
||||
memcpy(target, (const void *)(((char *)desktop) + (3 * ((height * adjust_screen_size(SCREEN_WIDTH)) + x))), (size_t)(tilewidth * 3));
|
||||
target = (char *) (target + (3 * tilewidth));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//This function returns 0 and *buffer != NULL if everything was good. retval = jpegsize if the captured image was too large.
|
||||
int calc_opt_compr_send(int x, int y, int captureWidth, int captureHeight, void* desktop, long long desktopsize, void ** buffer, long long *bufferSize)
|
||||
{
|
||||
|
||||
*buffer = NULL;
|
||||
*bufferSize = 0;
|
||||
|
||||
// Make sure a tile buffer is available. Most of the time, this is skipped.
|
||||
if (tilebuffersize != captureWidth * captureHeight * 3)
|
||||
{
|
||||
if (tilebuffer != NULL) free(tilebuffer);
|
||||
tilebuffersize = captureWidth * captureHeight * 3;
|
||||
if ((tilebuffer = malloc(tilebuffersize)) == NULL) return 0;
|
||||
}
|
||||
|
||||
//Get the final coalesced tile
|
||||
get_tile_buffer(x, y, &tilebuffer, tilebuffersize, desktop, desktopsize, captureWidth, captureHeight);
|
||||
|
||||
write_JPEG_buffer(tilebuffer, captureWidth, captureHeight, COMPRESSION_QUALITY);
|
||||
|
||||
if (jpeg_buffer_length > 65500) {
|
||||
return jpeg_buffer_length;
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
void dump32bit (const XImage * input)
|
||||
{
|
||||
int row, col;
|
||||
static char head[256];
|
||||
|
||||
static FILE *fp2 = NULL;
|
||||
char *ptr2, *output;
|
||||
long size;
|
||||
|
||||
register unsigned int
|
||||
rm = input->red_mask,
|
||||
gm = input->green_mask,
|
||||
bm = input->blue_mask,
|
||||
rs = 16,
|
||||
gs = 8,
|
||||
bs = 0, *p32 = (unsigned int *) input->data;
|
||||
|
||||
|
||||
printf("%x %x %x\n", rm, gm, bm);
|
||||
sprintf (head, "P6\n%d %d\n%d\n", input->width, input->height, 255);
|
||||
size = ((input->bytes_per_line * input->height) / 4) * 3;
|
||||
output = malloc (size);
|
||||
ptr2 = output;
|
||||
|
||||
for (row = 0; row < input->height; row++) {
|
||||
for (col = 0; col < input->width; col++) {
|
||||
*output++ = ((*p32 & rm) >> rs);
|
||||
*output++ = ((*p32 & gm) >> gs);
|
||||
*output++ = ((*p32 & bm) >> bs);
|
||||
p32++; // ignore alpha values
|
||||
}
|
||||
//
|
||||
// eat padded bytes, for better speed we use shifting,
|
||||
// (bytes_per_line - bits_per_pixel / 8 * width ) / 4
|
||||
//
|
||||
p32 += (input->bytes_per_line - (input->bits_per_pixel >> 3)
|
||||
* input->width) >> 2;
|
||||
}
|
||||
|
||||
fp2 = fopen ("/tmp/pic.rgb.pnm", "w");
|
||||
fwrite (head, strlen (head), 1, fp2);
|
||||
|
||||
fwrite (ptr2, size, 1, fp2);
|
||||
fclose (fp2);
|
||||
free (ptr2);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Really fast CRC-like method. Used for the KVM.
|
||||
|
||||
int util_crc(int x, int y, long long bufferSize, void *desktop, long long desktopsize, int tilewidth, int tileheight)
|
||||
{
|
||||
int hval = 0;
|
||||
int *bp = NULL;
|
||||
int *be = NULL;
|
||||
int height = 0;
|
||||
|
||||
for (height = y; height < y + tileheight; height++) {
|
||||
bp = (int *)(((char *)desktop) + (3 * ((height * adjust_screen_size(SCREEN_WIDTH)) + x)));
|
||||
be = (int *)(((char *)desktop) + (3 * ((height * adjust_screen_size(SCREEN_WIDTH)) + x + tilewidth)));
|
||||
while ((bp + 1) <= be)
|
||||
{
|
||||
//hval *= 0x01000193;
|
||||
hval += (hval<<1) + (hval<<4) + (hval<<7) + (hval<<8) + (hval<<24);
|
||||
hval ^= *bp++;
|
||||
}
|
||||
|
||||
/*if ((int)be - (int)bp >= 0) {
|
||||
hval += (hval<<1) + (hval<<4) + (hval<<7) + (hval<<8) + (hval<<24);
|
||||
hval ^= (*(int *)(((int)be) - 3));
|
||||
}*/
|
||||
}
|
||||
|
||||
return hval;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* EXTERNAL FUNCTIONS
|
||||
******************************************************************************/
|
||||
|
||||
//Adjusts the screen size(width or height) to be exactly divisible by TILE_WIDTH
|
||||
int adjust_screen_size(int pixles)
|
||||
{
|
||||
int extra = pixles % TILE_WIDTH; //Assuming tile width and height will remain the same.
|
||||
|
||||
if (extra != 0) { return pixles + TILE_WIDTH - extra; }
|
||||
|
||||
return pixles;
|
||||
}
|
||||
|
||||
// Reset the tile info structure
|
||||
int reset_tile_info(int old_height_count) {
|
||||
int row, col;
|
||||
|
||||
if (g_tileInfo != NULL)
|
||||
{
|
||||
for (row = 0; row < old_height_count; row++) { free(g_tileInfo[row]); }
|
||||
free(g_tileInfo);
|
||||
g_tileInfo = NULL;
|
||||
}
|
||||
|
||||
g_tileInfo = (struct tileInfo_t **) malloc(sizeof(struct tileInfo_t *) * TILE_HEIGHT_COUNT);
|
||||
for (row = 0; row < TILE_HEIGHT_COUNT; row++) {
|
||||
g_tileInfo[row] = (struct tileInfo_t *) calloc (TILE_WIDTH_COUNT, sizeof(struct tileInfo_t));
|
||||
for (col = 0; col < TILE_WIDTH_COUNT; col++) { g_tileInfo[row][col].crc = 0xff; }
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//Fetches the encoded jpeg tile at the given location. The neighboring tiles are coalesced to form a larger jpeg before returning.
|
||||
int getTileAt(int x, int y, void** buffer, long long *bufferSize, void *desktop, long long desktopsize, int row, int col)
|
||||
{
|
||||
int CRC, rcol, i, r, c;
|
||||
int rightcol = col; //Used in coalescing. Indicates the rightmost column to be coalesced.
|
||||
int botrow = row; //Used in coalescing. Indicates the bottom most row to be coalesced.
|
||||
int r_x = x;
|
||||
int r_y = y;
|
||||
int captureWidth = TILE_WIDTH;
|
||||
int captureHeight = TILE_HEIGHT;
|
||||
|
||||
*buffer = NULL; // If anything fails, this will be the indication.
|
||||
*bufferSize = 0;
|
||||
|
||||
if (g_tileInfo[row][col].flag == TILE_TODO) { //First check whether the tile-crc needs to be calculated or not.
|
||||
if ((CRC = util_crc(x, y, TILE_HEIGHT * TILE_WIDTH * 3, desktop, desktopsize, TILE_WIDTH, TILE_HEIGHT)) == g_tileInfo[row][col].crc) return 0;
|
||||
g_tileInfo[row][col].crc = CRC; //Update the tile CRC in the global data structure.
|
||||
}
|
||||
|
||||
g_tileInfo[row][col].flag = TILE_MARKED_NOT_SENT;
|
||||
|
||||
//COALESCING SECTION
|
||||
|
||||
// First got to the right most changed tile and record it
|
||||
while (rightcol + 1 < TILE_WIDTH_COUNT) {
|
||||
rightcol++;
|
||||
r_x = rightcol * TILE_WIDTH;
|
||||
|
||||
CRC = g_tileInfo[row][rightcol].crc;
|
||||
|
||||
if (g_tileInfo[row][rightcol].flag == TILE_TODO) {
|
||||
CRC = util_crc(r_x, y, TILE_HEIGHT * TILE_WIDTH * 3, desktop, desktopsize, TILE_WIDTH, TILE_HEIGHT);
|
||||
}
|
||||
|
||||
if (CRC != g_tileInfo[row][rightcol].crc || g_tileInfo[row][rightcol].flag == TILE_MARKED_NOT_SENT) { //If the tile has changed, increment the capturewidth.
|
||||
g_tileInfo[row][rightcol].crc = CRC;
|
||||
//Here we check whether the size of the coalesced bitmap is greater than the threshold (65500)
|
||||
if ((captureWidth + TILE_WIDTH) * TILE_HEIGHT * 3 / COMPRESSION_RATIO > 65500) {
|
||||
g_tileInfo[row][rightcol].flag = TILE_MARKED_NOT_SENT;
|
||||
--rightcol;
|
||||
break;
|
||||
}
|
||||
|
||||
g_tileInfo[row][rightcol].flag = TILE_MARKED_NOT_SENT;
|
||||
captureWidth += TILE_WIDTH;
|
||||
}
|
||||
else {
|
||||
g_tileInfo[row][rightcol].flag = TILE_DONT_SEND;
|
||||
--rightcol;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//int TOLERANCE = (rightcol - col) / 3;
|
||||
|
||||
// Now go to the bottom tiles, check if they have changed and record them
|
||||
while ((botrow + 1 < TILE_HEIGHT_COUNT) && ((captureHeight + TILE_HEIGHT) * captureWidth * 3 / COMPRESSION_RATIO <= 65500)) {
|
||||
botrow++;
|
||||
r_y = botrow * TILE_HEIGHT;
|
||||
int fail = 0;
|
||||
r_x = x;
|
||||
|
||||
//int missCount = 0;
|
||||
|
||||
for (rcol = col; rcol <= rightcol; rcol++) {
|
||||
|
||||
CRC = g_tileInfo[botrow][rcol].crc;
|
||||
if (g_tileInfo[botrow][rcol].flag == TILE_TODO) {
|
||||
CRC = util_crc(r_x, r_y, TILE_HEIGHT * TILE_WIDTH * 3, desktop, desktopsize, TILE_WIDTH, TILE_HEIGHT);
|
||||
}
|
||||
|
||||
if (CRC != g_tileInfo[botrow][rcol].crc || g_tileInfo[botrow][rcol].flag == TILE_MARKED_NOT_SENT) {
|
||||
g_tileInfo[botrow][rcol].flag = TILE_MARKED_NOT_SENT;
|
||||
g_tileInfo[botrow][rcol].crc = CRC;
|
||||
r_x += TILE_WIDTH;
|
||||
}
|
||||
else {
|
||||
/*//Keep this part commented. Adding tolerance adds to the complexity of this code.
|
||||
missCount++;
|
||||
|
||||
if (missCount > TOLERANCE) {
|
||||
fail = 1;
|
||||
for (int i = col; i < rcol; i++) {
|
||||
if (g_tileInfo[botrow][i].flag == TILE_SKIPPED) {
|
||||
g_tileInfo[botrow][i].flag = TILE_DONT_SEND;
|
||||
}
|
||||
else {
|
||||
g_tileInfo[botrow][i].flag = TILE_MARKED_NOT_SENT;
|
||||
}
|
||||
}
|
||||
g_tileInfo[botrow][rcol].flag = TILE_DONT_SEND;
|
||||
botrow--;
|
||||
break;
|
||||
}
|
||||
else {
|
||||
g_tileInfo[botrow][rcol].flag = TILE_SKIPPED;
|
||||
g_tileInfo[botrow][rcol].crc = CRC;
|
||||
r_x += TILE_WIDTH;
|
||||
}*/
|
||||
fail = 1;
|
||||
for (i = col; i < rcol; i++) {
|
||||
g_tileInfo[botrow][i].flag = TILE_MARKED_NOT_SENT;
|
||||
}
|
||||
g_tileInfo[botrow][rcol].flag = TILE_DONT_SEND;
|
||||
botrow--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!fail) {
|
||||
captureHeight += TILE_HEIGHT;
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int retval = 0;
|
||||
int firstTime = 1;
|
||||
|
||||
//This loop is used to adjust the COMPRESSION_RATIO. This loop runs only once most of the time.
|
||||
do {
|
||||
//retval here is 0 if everything was good. It is > 0 if it contains the size of the jpeg that was created and not sent.
|
||||
retval = calc_opt_compr_send(x, y, captureWidth, captureHeight, desktop, desktopsize, buffer, bufferSize);
|
||||
if (retval != 0) {
|
||||
if (firstTime) {
|
||||
//Re-adjust the compression ratio.
|
||||
COMPRESSION_RATIO = (int)(((double)COMPRESSION_RATIO/(double)retval) * 60000);//Magic number: 60000 ~= 65500
|
||||
if (COMPRESSION_RATIO <= 1) {
|
||||
COMPRESSION_RATIO = 2;
|
||||
}
|
||||
|
||||
firstTime = 0;
|
||||
}
|
||||
|
||||
if (botrow > row) { //First time, try reducing the height.
|
||||
botrow = row + ((botrow - row + 1) / 2);
|
||||
captureHeight = (botrow - row + 1) * TILE_HEIGHT;
|
||||
}
|
||||
else if (rightcol > col){ //If it is not possible, reduce the width
|
||||
rightcol = col + ((rightcol - col + 1) / 2);
|
||||
captureWidth = (rightcol - col + 1) * TILE_WIDTH;
|
||||
}
|
||||
else { //This never happens in any case.
|
||||
retval = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
} while (retval != 0);
|
||||
|
||||
//Set the flags to TILE_SENT
|
||||
if (jpeg_buffer != NULL) {
|
||||
*bufferSize = jpeg_buffer_length + 8;
|
||||
|
||||
*buffer = malloc (*bufferSize);
|
||||
((unsigned short*)*buffer)[0] = (unsigned short)htons((unsigned short)MNG_KVM_PICTURE); // Write the type
|
||||
((unsigned short*)*buffer)[1] = (unsigned short)htons((unsigned short)*bufferSize); // Write the size
|
||||
((unsigned short*)*buffer)[2] = (unsigned short)htons((unsigned short)x); // X position
|
||||
((unsigned short*)*buffer)[3] = (unsigned short)htons((unsigned short)y); // Y position
|
||||
memcpy((char *)(*buffer) + 8, jpeg_buffer, jpeg_buffer_length);
|
||||
free(jpeg_buffer);
|
||||
jpeg_buffer = NULL;
|
||||
jpeg_buffer_length = 0;
|
||||
|
||||
for (r = row; r <= botrow; r++) {
|
||||
for (c = col; c <= rightcol; c++) {
|
||||
g_tileInfo[r][c].flag = TILE_SENT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
// Get screen buffer from the CGImageRef structure
|
||||
int getScreenBuffer(unsigned char **desktop, long long *desktopsize, CGImageRef image)
|
||||
{
|
||||
unsigned int row, col, bpp, len, width_padding_size, height_padding_size, i;
|
||||
unsigned char *output;
|
||||
int height = CGImageGetHeight(image);
|
||||
int width = CGImageGetWidth(image);
|
||||
|
||||
CGImageAlphaInfo alphaInfo = CGImageGetAlphaInfo(image);
|
||||
|
||||
CFDataRef dataRef = CGDataProviderCopyData(CGImageGetDataProvider(image));
|
||||
const unsigned char *sourceBytesPtr = CFDataGetBytePtr(dataRef);
|
||||
len = CFDataGetLength(dataRef);
|
||||
|
||||
if (*desktopsize != len) {
|
||||
if (*desktop != NULL) { free(*desktop); }
|
||||
*desktopsize = len;
|
||||
*desktop = (unsigned char *) malloc (*desktopsize);
|
||||
}
|
||||
|
||||
output = *desktop;
|
||||
bpp = CGImageGetBitsPerPixel(image);
|
||||
width_padding_size = (adjust_screen_size(SCREEN_WIDTH) - width) * 3;
|
||||
|
||||
switch(bpp) {
|
||||
case 16:
|
||||
{
|
||||
const unsigned short *tmpPtr = (const unsigned short *)sourceBytesPtr;
|
||||
if(alphaInfo == kCGImageAlphaNoneSkipFirst ||
|
||||
alphaInfo == kCGImageAlphaPremultipliedFirst ||
|
||||
alphaInfo == kCGImageAlphaFirst) {
|
||||
for (row = 0; row < height; row++) {
|
||||
for (col = 0; col < width; col++) {
|
||||
*output++ = (*tmpPtr & 0x7C00) >> 7;
|
||||
*output++ = (*tmpPtr & 0x3E0) >> 2;
|
||||
*output++ = (*tmpPtr & 0x1F) << 3;
|
||||
tmpPtr++;
|
||||
}
|
||||
|
||||
if (width_padding_size != 0) {
|
||||
for (i = 0; i < width_padding_size; i++) {
|
||||
*output++ = 0;
|
||||
}
|
||||
}
|
||||
tmpPtr += (CGImageGetBytesPerRow(image) - (bpp >> 3) * width) >> 2;
|
||||
}
|
||||
}
|
||||
else if (alphaInfo == kCGImageAlphaNone ||
|
||||
alphaInfo == kCGImageAlphaNoneSkipLast ||
|
||||
alphaInfo == kCGImageAlphaPremultipliedLast ||
|
||||
alphaInfo == kCGImageAlphaLast) {
|
||||
for (row = 0; row < height; row++) {
|
||||
for (col = 0; col < width; col++) {
|
||||
*output++ = (*tmpPtr & 0xF800) >> 8;
|
||||
*output++ = (*tmpPtr & 0x7C0) >> 3;
|
||||
*output++ = (*tmpPtr & 0x3E) << 2;
|
||||
tmpPtr++;
|
||||
}
|
||||
if (width_padding_size != 0) {
|
||||
for (i = 0; i < width_padding_size; i++) {
|
||||
*output++ = 0;
|
||||
}
|
||||
}
|
||||
tmpPtr += (CGImageGetBytesPerRow(image) - (bpp >> 3) * width) >> 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 32:
|
||||
{
|
||||
const unsigned int *tmpPtr1 = (const unsigned int *)sourceBytesPtr;
|
||||
if(alphaInfo == kCGImageAlphaNoneSkipFirst ||
|
||||
alphaInfo == kCGImageAlphaPremultipliedFirst ||
|
||||
alphaInfo == kCGImageAlphaFirst) {
|
||||
for (row = 0; row < height; row++) {
|
||||
for (col = 0; col < width; col++) {
|
||||
*output++ = (*tmpPtr1 & 0x0ff0000) >> 16;
|
||||
*output++ = (*tmpPtr1 & 0x0ff00) >> 8;
|
||||
*output++ = (*tmpPtr1 & 0x0FF);
|
||||
tmpPtr1++;
|
||||
}
|
||||
if (width_padding_size != 0) {
|
||||
for (i = 0; i < width_padding_size; i++) {
|
||||
*output++ = 0;
|
||||
}
|
||||
}
|
||||
tmpPtr1 += (CGImageGetBytesPerRow(image) - (bpp >> 3) * width) >> 2;
|
||||
}
|
||||
}
|
||||
else if (alphaInfo == kCGImageAlphaNone ||
|
||||
alphaInfo == kCGImageAlphaNoneSkipLast ||
|
||||
alphaInfo == kCGImageAlphaPremultipliedLast ||
|
||||
alphaInfo == kCGImageAlphaLast) {
|
||||
for (row = 0; row < height; row++) {
|
||||
for (col = 0; col < width; col++) {
|
||||
*output++ = (*tmpPtr1 & 0xFF000000) >> 24;
|
||||
*output++ = (*tmpPtr1 & 0x0ff0000) >> 16;
|
||||
*output++ = (*tmpPtr1 & 0x0ff00) >> 8;
|
||||
tmpPtr1++;
|
||||
}
|
||||
if (width_padding_size != 0) {
|
||||
for (i = 0; i < width_padding_size; i++) {
|
||||
*output++ = 0;
|
||||
}
|
||||
}
|
||||
tmpPtr1 += (CGImageGetBytesPerRow(image) - (bpp >> 3) * width) >> 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "This image depth is not supported.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
height_padding_size = adjust_screen_size(SCREEN_HEIGHT) - height;
|
||||
|
||||
if (height_padding_size != 0) {
|
||||
for (row = 0; row < height_padding_size; row++) {
|
||||
for (col = 0; col < (width * 3) + width_padding_size; col++) {
|
||||
*output++ = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CFRelease(dataRef);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// Set the compression quality
|
||||
void set_tile_compression(int type, int level)
|
||||
{
|
||||
if (level > 0 && level <= 100) {
|
||||
COMPRESSION_QUALITY = level;
|
||||
}
|
||||
else {
|
||||
COMPRESSION_QUALITY = 60;
|
||||
}
|
||||
|
||||
// TODO Make sure the all the types are handled. We ignore the type variable for now.
|
||||
}
|
||||
|
||||
41
meshcore/KVM/MacOS/mac_tile.h
Normal file
41
meshcore/KVM/MacOS/mac_tile.h
Normal file
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* mac_tile.h
|
||||
*
|
||||
*
|
||||
* Created by Ylian Saint-Hilaire on 8/18/11.
|
||||
* Copyright 2011 __MyCompanyName__. All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LINUX_TILE_H_
|
||||
#define LINUX_TILE_H_
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <Carbon/Carbon.h>
|
||||
#include "../Linux/linux_compression.h"
|
||||
|
||||
enum TILE_FLAGS_ENUM {
|
||||
TILE_TODO, //The tile CRC needs to be calculated.
|
||||
TILE_SENT, //CRC has been calculated and the tile has been sent.
|
||||
TILE_MARKED_NOT_SENT, //CRC has been calculated, but the tile was not sent.
|
||||
TILE_DONT_SEND //CRC has been calculated, tile need not be sent.
|
||||
//TILE_SKIPPED //CRC has been calculated, tile need not be sent, but was skipped to include a greater region
|
||||
};
|
||||
|
||||
struct tileInfo_t {
|
||||
int crc;
|
||||
enum TILE_FLAGS_ENUM flag;
|
||||
};
|
||||
|
||||
extern int reset_tile_info(int old_height_count);
|
||||
extern int adjust_screen_size(int pixles);
|
||||
extern int getTileAt(int x, int y, void** buffer, long long *bufferSize, void *desktop, long long desktopsize, int row, int col);
|
||||
extern int getScreenBuffer(unsigned char **desktop, long long *desktopsize, CGImageRef image);
|
||||
extern void set_tile_compression(int type, int level);
|
||||
|
||||
|
||||
#endif /* LINUX_TILE_H_ */
|
||||
|
||||
Reference in New Issue
Block a user