public void Init() { bool RemoteConfigured = false; using (Settings xmlreader = new MPSettings()) { RemoteConfigured = xmlreader.GetValueAsBool("remote", "Centarea", false); _verboseLogging = xmlreader.GetValueAsBool("remote", "CentareaVerbose", false); _mapMouseButton = xmlreader.GetValueAsBool("remote", "CentareaMouseOkMap", true); _mapJoystick = xmlreader.GetValueAsBool("remote", "CentareaJoystickMap", false); } if (!RemoteConfigured) { return; } Log.Debug("Centarea: Initializing Centarea HID remote"); _inputHandler = new InputHandler("Centarea HID"); if (!_inputHandler.IsLoaded) { Log.Error("Centarea: Error loading default mapping file - please reinstall MediaPortal"); DeInit(); return; } else { Log.Info("Centarea: Centarea HID mapping loaded successfully"); _remoteActive = true; } }
/// <summary> /// Translates a mouse movement into a direction /// </summary> /// <param name="p">The new cursor coordinates</param> /// <returns>None for minimal movement, else up/down/left/right</returns> private MouseDirection OnMouseMoved(Point p) { MouseDirection direction = MouseDirection.None; int xMove = GetPointDeviation(false, p.X); int yMove = GetPointDeviation(true, p.Y); // using the pythagoras theorem to get the total movement length double TotalWay = Math.Sqrt(((double)((Math.Abs(xMove) * Math.Abs(xMove))) + (double)((Math.Abs(yMove) * Math.Abs(yMove))))); // set a direction only if movement exceeds a minimum limit // usually pushing the joystick knob once results in a one pixel movement. if (TotalWay > 0.9) { direction = GetDirection(xMove, yMove); } if (_verboseLogging) { Log.Debug("Centarea: Mouse movement of {0} pixels heading {1}", TotalWay, direction); } return(direction); }
/// <summary> /// Let everybody know that this HID message may not be handled by anyone else /// </summary> /// <param name="msg">System.Windows.Forms.Message</param> /// <returns>Command handled</returns> public bool WndProc(ref Message msg) { if (_remoteActive) { if (msg.Msg == WM_KEYDOWN || msg.Msg == WM_SYSKEYDOWN || msg.Msg == WM_APPCOMMAND || msg.Msg == WM_LBUTTONDOWN || msg.Msg == WM_RBUTTONDOWN || msg.Msg == WM_MOUSEMOVE) { switch ((Keys)msg.WParam) { case Keys.ControlKey: break; case Keys.ShiftKey: break; case Keys.Menu: break; default: int keycode = (int)msg.WParam; AppCommands appCommand = (AppCommands)((msg.LParam.ToInt32() >> 16) & ~0xF000); // find out which request the MCE remote handled last if ((appCommand == InputDevices.LastHidRequest) && (appCommand != AppCommands.VolumeDown) && (appCommand != AppCommands.VolumeUp)) { if (Enum.IsDefined(typeof(AppCommands), InputDevices.LastHidRequest)) { // possible that it is the same request mapped to an app command? if (Environment.TickCount - InputDevices.LastHidRequestTick < 500) { return(true); } } } InputDevices.LastHidRequest = appCommand; // Due to the non-perfect placement of the OK button we allow the user to remap the joystick to okay. if (_mapMouseButton) { if (msg.Msg == WM_LBUTTONDOWN) { if (_verboseLogging) { Log.Debug("Centarea: Command \"{0}\" mapped for left mouse button", keycode); } keycode = 13; } if (msg.Msg == WM_RBUTTONDOWN) { if (_verboseLogging) { Log.Debug("Centarea: Command \"{0}\" mapped for right mouse button", keycode); } keycode = 10069; } } // Since mouse support is semi optimal we have this option to use the joystick like cursor keys if (_mapJoystick && GUIGraphicsContext.Fullscreen) { if (msg.Msg == WM_MOUSEMOVE) { Point p = new Point(msg.LParam.ToInt32()); _ignoreDupMsg++; // since our ResetCursor() triggers a mouse move MSG as well we ignore every second event if (_ignoreDupMsg % 2 == 0) { GUIGraphicsContext.ResetCursor(false); } // we ignore double actions for the configured time if (Environment.TickCount - _lastMouseTick < 400) { return(false); } MouseDirection mmove = OnMouseMoved(p); _lastMouseTick = Environment.TickCount; _ignoreDupMsg = 0; switch (mmove) { case MouseDirection.Up: keycode = 38; break; case MouseDirection.Right: keycode = 39; break; case MouseDirection.Down: keycode = 40; break; case MouseDirection.Left: keycode = 37; break; } if (mmove != MouseDirection.None) { GUIGraphicsContext.ResetCursor(false); if (_verboseLogging) { Log.Debug("Centarea: Command \"{0}\" mapped for mouse movement", mmove.ToString()); } } } } // The Centarea Remote sends key combos. Therefore we use this trick to get a 1:1 mapping if ((Control.ModifierKeys & Keys.Shift) == Keys.Shift) { keycode += 1000; } if ((Control.ModifierKeys & Keys.Control) == Keys.Control) { keycode += 10000; } if ((Control.ModifierKeys & Keys.Alt) == Keys.Alt) { keycode += 100000; } try { // Get & execute Mapping if (_inputHandler.MapAction(keycode)) { if (_verboseLogging) { Log.Debug("Centarea: Command \"{0}\" mapped", keycode); } } else { if (keycode > 0) { Log.Debug("Centarea: Command \"{0}\" not mapped", keycode); } return(false); } } catch (ApplicationException) { return(false); } msg.Result = new IntPtr(1); break; } return(true); } } return(false); }
/// <summary> /// Map a WndProc message and optionally execute it /// </summary> /// <param name="msg"></param> /// <returns></returns> private Mapping MapWndProcMessage(Message msg, bool shouldRaiseAction = true) { Mapping result = null; if (msg.Msg == WM_KEYDOWN || msg.Msg == WM_SYSKEYDOWN || msg.Msg == Win32.Const.WM_APPCOMMAND || msg.Msg == WM_LBUTTONDOWN || msg.Msg == WM_RBUTTONDOWN || msg.Msg == WM_MOUSEMOVE) { switch ((Keys)msg.WParam) { case Keys.ControlKey: break; case Keys.ShiftKey: break; case Keys.Menu: break; default: int keycode = (int)msg.WParam; AppCommands appCommand = (AppCommands)Win32.Macro.GET_APPCOMMAND_LPARAM(msg.LParam); InputDevices.LastHidRequest = appCommand; // Due to the non-perfect placement of the OK button we allow the user to remap the joystick to okay. if (_mapMouseButton) { if (msg.Msg == WM_LBUTTONDOWN) { if (_verboseLogging) { Log.Debug("Centarea: Command \"{0}\" mapped for left mouse button", keycode); } keycode = 13; } if (msg.Msg == WM_RBUTTONDOWN) { if (_verboseLogging) { Log.Debug("Centarea: Command \"{0}\" mapped for right mouse button", keycode); } keycode = 10069; } } // Since mouse support is semi optimal we have this option to use the joystick like cursor keys if (_mapJoystick && GUIGraphicsContext.Fullscreen) { if (msg.Msg == WM_MOUSEMOVE) { Point p = new Point(msg.LParam.ToInt32()); _ignoreDupMsg++; // since our ResetCursor() triggers a mouse move MSG as well we ignore every second event if (_ignoreDupMsg % 2 == 0) { GUIGraphicsContext.ResetCursor(false); } // we ignore double actions for the configured time if (Environment.TickCount - _lastMouseTick < 400) { return(null); } MouseDirection mmove = OnMouseMoved(p); _lastMouseTick = Environment.TickCount; _ignoreDupMsg = 0; switch (mmove) { case MouseDirection.Up: keycode = 38; break; case MouseDirection.Right: keycode = 39; break; case MouseDirection.Down: keycode = 40; break; case MouseDirection.Left: keycode = 37; break; } if (mmove != MouseDirection.None) { GUIGraphicsContext.ResetCursor(false); if (_verboseLogging) { Log.Debug("Centarea: Command \"{0}\" mapped for mouse movement", mmove.ToString()); } } } } // The Centarea Remote sends key combos. Therefore we use this trick to get a 1:1 mapping if ((Control.ModifierKeys & Keys.Shift) == Keys.Shift) { keycode += 1000; } if ((Control.ModifierKeys & Keys.Control) == Keys.Control) { keycode += 10000; } if ((Control.ModifierKeys & Keys.Alt) == Keys.Alt) { keycode += 100000; } try { result = _inputHandler.GetMapping(keycode.ToString()); if (shouldRaiseAction) { // Get & execute Mapping if (_inputHandler.MapAction(keycode)) { if (_verboseLogging) { Log.Debug("Centarea: Command \"{0}\" mapped", keycode); } } else { if (keycode > 0) { Log.Debug("Centarea: Command \"{0}\" not mapped", keycode); } return(null); } } } catch (ApplicationException ex) { Log.Error("CentAreaRemote:MapWndProcMessage: {0}", ex.Message); return(null); } msg.Result = new IntPtr(1); break; } } return(result); }