Added device configs.

master
Pacman Ghost 8 years ago
parent 3eff0610c4
commit d692463d20
  1. 140
      MainApp/AppConfig.cs
  2. 24
      MainApp/MouseDll.cs
  3. 43
      MainApp/Utils.cs
  4. 114
      MouseDll/actions.cpp
  5. 77
      MouseDll/actions.hpp
  6. 29
      MouseDll/api.cpp
  7. 37
      MouseDll/api.hpp
  8. 76
      MouseDll/appProfile.cpp
  9. 45
      MouseDll/appProfile.hpp
  10. 89
      MouseDll/core.cpp
  11. 38
      MouseDll/device.cpp
  12. 10
      MouseDll/device.hpp
  13. 77
      MouseDll/deviceConfig.cpp
  14. 45
      MouseDll/deviceConfig.hpp
  15. 67
      MouseDll/event.cpp
  16. 47
      MouseDll/event.hpp
  17. 32
      MouseDll/mouse.vcproj
  18. 38
      MouseDll/utils.cpp
  19. 52
      MouseDll/utils.hpp

@ -10,15 +10,25 @@ namespace MouseInterception
{
// IMPORTANT! The definitions here must be kept in sync with their C equivalents in api.hpp
// FUDGE: Marshaling multiple levels of nested arrays of struct's proved to be tricky. C# seems to be
// able to handle it, but unpacking it on the C++ side was fiddly. Since we can't simply get
// a plain old pointer to an array (since they're managed objects), and we have to marshal arrays ByVal,
// defining C-struct's was impossible (one level of nesting was OK, but no deeper). We could have maybe
// done some trickery by manipulating pointers and using sizeof(), but it's risky since there are
// alignment issues. It's safer to send through a separate array for each type of struct, and then
// elements specify which ones they want via a start index and item count. Sigh...
// --- SETTINGS: application settings ---
[StructLayout( LayoutKind.Sequential , CharSet=CharSet.Unicode , Pack=1 )]
public struct ApiSettings
{
}
private ApiSettings mSettings ;
public ApiSettings settings { get { return mSettings ; } }
// --- DEVICE: device attributes ---
[StructLayout( LayoutKind.Sequential , CharSet=CharSet.Unicode , Pack=1 )]
public struct ApiDevice
{
@ -28,19 +38,82 @@ namespace MouseInterception
public string mDisplayName ;
public bool mIsEnabled ;
}
private ApiDevice[] mDevices ;
public ApiDevice[] devices { get { return mDevices ; } }
// --- DEVICE CONFIG: device configuration ---
// A DeviceConfig is associated with a single Device. We have 2 struct's to keep separate
// the configuration of the device itself, and how the user wants it to behave.
// A device can be configured to respond differently depending on which application is active.
// Each one is managed by an AppProfile object.
[StructLayout( LayoutKind.Sequential , CharSet=CharSet.Unicode , Pack=1 )]
public struct ApiDeviceConfig
{
public int mDeviceId ;
public int mAppProfileStartIndex ;
public int mAppProfileCount ;
}
private ApiDeviceConfig[] mDeviceConfigs ;
public ApiDeviceConfig[] deviceConfigs { get { return mDeviceConfigs ; } }
// --- APP PROFILE: device configuration for an application ---
// This holds the configuration for how the user wants a device to behave, for a specific application e.g.
// Alt + mouseLeft => scrollLeft
[StructLayout( LayoutKind.Sequential , CharSet=CharSet.Unicode , Pack=1 )]
public struct ApiAppProfile
{
public string mApp ;
public int mEventStartIndex ;
public int mEventCount ;
}
private ApiAppProfile[] mAppProfiles ;
public ApiAppProfile[] appProfiles { get { return mAppProfiles ; } }
// --- API EVENT: device event ---
// Represents an event that can be generated by a device e.g. mouse was moved left, button 3 was pressed.
// It also holds a list of Action's to be executed when the event happens.
[StructLayout( LayoutKind.Sequential , CharSet=CharSet.Unicode , Pack=1 )]
public struct ApiEvent
{
public enum EventType { mouseLeft=1 , mouseRight=2 , mouseUp=3 , mouseDown=4 }
public enum KeyModifiers { ctrl=0x0001 , alt=0x0002 , shift=0x0004 }
public int mEventType ;
public int mKeyModifiers ;
public int mActionStartIndex ;
public int mActionCount ;
}
private ApiEvent[] mEvents ;
public ApiEvent[] events { get { return mEvents ; } }
// --- API ACTION: action to perform in response to a device event ---
[StructLayout( LayoutKind.Sequential , CharSet=CharSet.Unicode , Pack=1 )]
public struct ApiAction
{
public enum ActionType { mouseLeft=1 , mouseRight=2 , mouseUp=3 , mouseDown=4 }
public int mActionType ;
}
public ApiAction[] mActions ;
public ApiAction[] actions { get { return mActions ; } }
// ------------------------------------------------------------
public AppConfig( string fname )
{
// initialize
mSettings = new ApiSettings() ;
mDevices = new ApiDevice[ 0 ] ;
mDeviceConfigs = new ApiDeviceConfig[ 0 ] ;
mAppProfiles = new ApiAppProfile[ 0 ] ;
mEvents = new ApiEvent[ 0 ] ;
mActions = new ApiAction[ 0 ] ;
// load the AppConfig
if ( ! File.Exists( fname ) )
return ;
return ; // FIXME! can't do this - we have to notify the DLL
XmlReaderSettings xmlReaderSettings = new XmlReaderSettings() ;
xmlReaderSettings.IgnoreComments = true ;
xmlReaderSettings.IgnoreProcessingInstructions = true ;
@ -54,17 +127,72 @@ namespace MouseInterception
// parse the devices
List<ApiDevice> devices = new List<ApiDevice>() ;
foreach ( XmlNode xn in configXmlNode.SelectNodes("device") )
foreach( XmlNode xn in configXmlNode.SelectNodes("device") )
{
ApiDevice device = new ApiDevice() ;
device.mDeviceId = Int32.Parse( xn.Attributes["id"].Value ) ;
device.mHID = xn.SelectSingleNode("hid").InnerText.Trim() ;
device.mDeviceNumber = Int32.Parse( xn.SelectSingleNode("deviceNumber").InnerText ) ;
device.mDisplayName = Utils.getXmlChildNodeVal( xn , "displayName" ) ;
device.mIsEnabled = Utils.getXmlChildNodeVal( xn , "enabled" , false ) ;
device.mDisplayName = Utils.getXmlChildVal( xn , "displayName" ) ;
device.mIsEnabled = Utils.getXmlChildVal( xn , "enabled" , false ) ;
devices.Add( device ) ;
}
mDevices = devices.ToArray() ;
// parse the device configs
List<ApiDeviceConfig> deviceConfigs = new List<ApiDeviceConfig>() ;
List<ApiAppProfile> appProfiles = new List<ApiAppProfile>() ;
List<ApiEvent> events = new List<ApiEvent>() ;
List<ApiAction> actions = new List<ApiAction>() ;
foreach( XmlNode deviceConfigXmlNode in configXmlNode.SelectNodes("deviceConfig") )
{
ApiDeviceConfig deviceConfig = new ApiDeviceConfig() ;
deviceConfig.mDeviceId = Int32.Parse( deviceConfigXmlNode.Attributes["id"].Value ) ;
deviceConfig.mAppProfileStartIndex = appProfiles.Count ;
deviceConfig.mAppProfileCount = 0 ;
// parse the app profiles
foreach( XmlNode appProfileXmlNode in deviceConfigXmlNode.SelectNodes("appProfile") )
{
ApiAppProfile appProfile = new ApiAppProfile() ;
appProfile.mApp = Utils.getXmlAttr( appProfileXmlNode , "app" ) ;
appProfile.mEventStartIndex = events.Count ;
appProfile.mEventCount = 0 ;
// parse the events
foreach( XmlNode eventXmlNode in appProfileXmlNode.SelectNodes("event" ) )
{
ApiEvent evt = new ApiEvent() ;
evt.mEventType = (int) Enum.Parse( typeof(ApiEvent.EventType) , eventXmlNode.Attributes["type"].Value , true ) ;
evt.mKeyModifiers = 0 ;
foreach( string km in Enum.GetNames(typeof(ApiEvent.KeyModifiers)) )
{
bool? keyState = Utils.getKeyState( eventXmlNode , km ) ;
if ( keyState.HasValue && (bool)keyState )
evt.mKeyModifiers += (int) Enum.Parse( typeof(ApiEvent.KeyModifiers) , km , true ) ;
}
// parse the actions
evt.mActionStartIndex = actions.Count ;
evt.mActionCount = 0 ;
foreach( XmlNode actionXmlNode in eventXmlNode.SelectNodes("action") )
{
ApiAction action = new ApiAction() ;
action.mActionType = (int) Enum.Parse( typeof(ApiAction.ActionType) , actionXmlNode.Attributes["type"].Value , true ) ;
actions.Add( action ) ;
evt.mActionCount ++ ;
}
events.Add( evt ) ;
appProfile.mEventCount ++ ;
}
// add the app profile to the table
appProfiles.Add( appProfile ) ;
deviceConfig.mAppProfileCount ++ ;
}
// add the device config to the table
deviceConfigs.Add( deviceConfig ) ;
}
mDeviceConfigs = deviceConfigs.ToArray() ;
mAppProfiles = appProfiles.ToArray() ;
mEvents = events.ToArray() ;
mActions = actions.ToArray() ;
}
}

@ -15,6 +15,10 @@ namespace MouseInterception
private static extern string open_api(
ref AppConfig.ApiSettings pAppSettings ,
[MarshalAs(UnmanagedType.LPArray)] AppConfig.ApiDevice[] pDevices , int nDevices ,
[MarshalAs(UnmanagedType.LPArray)] AppConfig.ApiDeviceConfig[] pDeviceConfigs , int nDeviceConfigs ,
[MarshalAs(UnmanagedType.LPArray)] AppConfig.ApiAppProfile[] pAppProfiles , int nAppProfiles ,
[MarshalAs(UnmanagedType.LPArray)] AppConfig.ApiEvent[] pEvents , int nEvents ,
[MarshalAs(UnmanagedType.LPArray)] AppConfig.ApiAction[] pActions , int nActions ,
ref DebugConfig.ApiSettings pDebugSettings ,
int initConsole
) ;
@ -28,6 +32,10 @@ namespace MouseInterception
private static extern string reload_config(
ref AppConfig.ApiSettings pAppSettings ,
[MarshalAs(UnmanagedType.LPArray)] AppConfig.ApiDevice[] pDevices , int nDevices ,
[MarshalAs(UnmanagedType.LPArray)] AppConfig.ApiDeviceConfig[] pDeviceConfigs , int nDeviceConfigs ,
[MarshalAs(UnmanagedType.LPArray)] AppConfig.ApiAppProfile[] pAppProfiles , int nAppProfiles ,
[MarshalAs(UnmanagedType.LPArray)] AppConfig.ApiEvent[] pEvents , int nEvents ,
[MarshalAs(UnmanagedType.LPArray)] AppConfig.ApiAction[] pActions , int nActions ,
ref DebugConfig.ApiSettings pDebugSettings
) ;
@ -36,10 +44,18 @@ namespace MouseInterception
// open the mouse API
AppConfig.ApiSettings appSettings = Program.appConfig.settings ;
AppConfig.ApiDevice[] devices = Program.appConfig.devices ;
AppConfig.ApiDeviceConfig[] deviceConfigs = Program.appConfig.deviceConfigs ;
AppConfig.ApiAppProfile[] appProfiles = Program.appConfig.appProfiles ;
AppConfig.ApiEvent[] events = Program.appConfig.events ;
AppConfig.ApiAction[] actions = Program.appConfig.actions ;
DebugConfig.ApiSettings debugSettings = Program.debugConfig.settings ;
string errorMsg = open_api(
ref appSettings ,
devices , devices.Length ,
deviceConfigs , deviceConfigs.Length ,
appProfiles , appProfiles.Length ,
events , events.Length ,
actions , actions.Length ,
ref debugSettings ,
initConsole ? 1 : 0
) ;
@ -60,10 +76,18 @@ namespace MouseInterception
// reload the config
AppConfig.ApiSettings appSettings = Program.appConfig.settings ;
AppConfig.ApiDevice[] devices = Program.appConfig.devices ;
AppConfig.ApiDeviceConfig[] deviceConfigs = Program.appConfig.deviceConfigs ;
AppConfig.ApiAppProfile[] appProfiles = Program.appConfig.appProfiles ;
AppConfig.ApiEvent[] events = Program.appConfig.events ;
AppConfig.ApiAction[] actions = Program.appConfig.actions ;
DebugConfig.ApiSettings debugSettings = Program.debugConfig.settings ;
string errorMsg = reload_config(
ref appSettings ,
devices , devices.Length ,
deviceConfigs , deviceConfigs.Length ,
appProfiles , appProfiles.Length ,
events , events.Length ,
actions , actions.Length ,
ref debugSettings
) ;
if ( errorMsg != null )

@ -6,24 +6,47 @@ namespace MouseInterception
static class Utils
{
public static string getXmlChildNodeVal( XmlNode xmlNode , string childNodeName , string defaultVal )
public static string getXmlChildVal( XmlNode xmlNode , string childNodeName , string defaultVal )
{
// get the child node's value
XmlNode childNode = xmlNode.SelectSingleNode( childNodeName ) ;
if ( childNode == null )
return defaultVal ;
return childNode.InnerText.Trim() ;
if ( childNode != null )
return childNode.InnerText.Trim() ;
return defaultVal ;
}
public static string getXmlChildNodeVal( XmlNode xn , string s ) { return getXmlChildNodeVal(xn,s,"") ; }
public static string getXmlChildVal( XmlNode xn , string s ) { return getXmlChildVal(xn,s,"") ; }
public static bool getXmlChildNodeVal( XmlNode xmlNode , string childNodeName , bool defaultVal )
public static bool getXmlChildVal( XmlNode xmlNode , string childNodeName , bool defaultVal )
{
// get the child node's value
string val = getXmlChildNodeVal( xmlNode , childNodeName , null ) ;
if ( val == null )
return defaultVal ;
return Boolean.Parse( val ) ;
string val = getXmlChildVal( xmlNode , childNodeName , null ) ;
if ( val != null )
return Boolean.Parse( val ) ;
return defaultVal ;
}
public static string getXmlAttr( XmlNode xmlNode , string attrName , string defaultVal )
{
// get the attribute value
XmlAttribute xmlAttr = xmlNode.Attributes[ attrName ] ;
if ( xmlAttr != null )
return xmlAttr.Value ;
return defaultVal ;
}
public static string getXmlAttr( XmlNode xn , string s ) { return getXmlAttr(xn,s,"") ; }
public static bool? getKeyState( XmlNode xmlNode , string attrName )
{
// get the key state
XmlAttribute xmlAttr = xmlNode.Attributes[ attrName ] ;
if ( xmlAttr == null )
return null ;
string attrVal = xmlAttr.Value.Trim() ;
if ( attrVal == "down" )
return true ;
if ( attrVal == "up" )
return false ;
throw new Exception( "Invalid key state: " + attrVal ) ;
}
}
}

@ -0,0 +1,114 @@
#include "actions.hpp"
#include "api.hpp"
#include "utils.hpp"
using namespace std ;
// --- Action ---------------------------------------------------------
Action::Action( const ApiAction* pAction )
{
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Action*
Action::allocAction( const ApiAction* pAction )
{
switch( pAction->mActionType )
{
case Action::atMouseLeft: return new MouseLeftAction(pAction) ;
case Action::atMouseRight: return new MouseRightAction(pAction) ;
case Action::atMouseUp: return new MouseUpAction(pAction) ;
case Action::atMouseDown: return new MouseDownAction(pAction) ;
default:
assert( false ) ;
return NULL ;
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ostream&
operator<<( ostream& os , const Action& action )
{
// insert the Action
os << action.asString() ;
return os ;
}
// --- MouseLeftAction ------------------------------------------------
MouseLeftAction::MouseLeftAction( const ApiAction* pAction )
: Action( pAction )
{
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void
MouseLeftAction::doAction() const
{
assert(0);//FIXME
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
string MouseLeftAction::asString() const { return "<MouseLeftAction>" ; }
// --- MouseRightAction -----------------------------------------------
MouseRightAction::MouseRightAction( const ApiAction* pAction )
: Action( pAction )
{
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void
MouseRightAction::doAction() const
{
assert(0);//FIXME
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
string MouseRightAction::asString() const { return "<MouseRightAction>" ; }
// --- MouseUpAction --------------------------------------------------
MouseUpAction::MouseUpAction( const ApiAction* pAction )
: Action( pAction )
{
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void
MouseUpAction::doAction() const
{
assert(0);//FIXME
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
string MouseUpAction::asString() const { return "<MouseUpAction>" ; }
// --- MouseDownAction ------------------------------------------------
MouseDownAction::MouseDownAction( const ApiAction* pAction )
: Action( pAction )
{
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void
MouseDownAction::doAction() const
{
assert(0);//FIXME
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
string MouseDownAction::asString() const { return "<MouseDownAction>" ; }

@ -0,0 +1,77 @@
#ifndef ACTIONS_HPP
#define ACTIONS_HPP
#include "utils.hpp"
struct ApiAction ;
// ---------------------------------------------------------------------
class Action
{
// data types:
public:
enum eActionType { atMouseLeft=1 , atMouseRight=2 , atMouseUp=3 , atMouseDown=4 } ;
// constructors/destructor:
public:
static Action* allocAction( const ApiAction* pAction ) ;
protected:
Action( const ApiAction* pAction ) ;
DISABLE_COPY_ASSIGNMENT( Action ) ;
// action methods:
virtual void doAction() const = 0 ;
// access methods:
public:
virtual std::string asString() const = 0 ;
} ;
typedef PtrVector<Action> ActionPtrVector ;
// inserter
std::ostream& operator<<( std::ostream& , const Action& ) ;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
#define DEFINE_ACTION_CLASS( ClassName ) \
public: \
ClassName( const ApiAction* pAction ) ; \
public: \
virtual std::string asString() const ; \
virtual void doAction() const ;
// ---------------------------------------------------------------------
class MouseLeftAction : public Action
{
DEFINE_ACTION_CLASS( MouseLeftAction ) ;
} ;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
class MouseRightAction : public Action
{
DEFINE_ACTION_CLASS( MouseRightAction ) ;
} ;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
class MouseUpAction : public Action
{
DEFINE_ACTION_CLASS( MouseUpAction ) ;
} ;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
class MouseDownAction : public Action
{
DEFINE_ACTION_CLASS( MouseDownAction ) ;
} ;
// ---------------------------------------------------------------------
#endif // ACTIONS_HPP

@ -11,6 +11,10 @@ extern "C" __declspec(dllexport) BSTR
open_api(
const ApiAppConfig* pAppConfig ,
const ApiDevice* pDevices , int nDevices ,
const ApiDeviceConfig* pDeviceConfigs , int nDeviceConfigs ,
const ApiAppProfile* pAppProfiles , int nAppProfiles ,
const ApiEvent* pEvents , int nEvents ,
const ApiAction* pActions , int nActions ,
const ApiDebugConfig* pDebugConfig ,
int initConsole
)
@ -18,7 +22,16 @@ open_api(
// open the API
try
{
openApi( pAppConfig , pDevices , nDevices , pDebugConfig , initConsole != 0 ) ;
openApi(
pAppConfig ,
pDevices , nDevices ,
pDeviceConfigs , nDeviceConfigs ,
pAppProfiles , nAppProfiles ,
pEvents , nEvents ,
pActions , nActions ,
pDebugConfig ,
initConsole != 0
) ;
return NULL ;
}
catch ( exception& xcptn )
@ -50,13 +63,25 @@ extern "C" __declspec(dllexport) BSTR
reload_config(
const ApiAppConfig* pAppConfig ,
const ApiDevice* pDevices , int nDevices ,
const ApiDeviceConfig* pDeviceConfigs , int nDeviceConfigs ,
const ApiAppProfile* pAppProfiles , int nAppProfiles ,
const ApiEvent* pEvents , int nEvents ,
const ApiAction* pActions , int nActions ,
const ApiDebugConfig* pDebugConfig
)
{
// reload the config
try
{
reloadConfig( pAppConfig , pDevices , nDevices , pDebugConfig ) ;
reloadConfig(
pAppConfig ,
pDevices , nDevices ,
pDeviceConfigs , nDeviceConfigs ,
pAppProfiles , nAppProfiles ,
pEvents , nEvents ,
pActions , nActions ,
pDebugConfig
) ;
return NULL ;
}
catch ( exception& xcptn )

@ -18,6 +18,33 @@ struct ApiDevice
bool mIsEnabled ;
} ;
struct ApiDeviceConfig
{
int mDeviceId ;
int mAppProfileStartIndex ;
int mAppProfileCount ;
} ;
struct ApiAppProfile
{
const wchar_t* mpApp ;
int mEventStartIndex ;
int mEventCount ;
} ;
struct ApiEvent
{
int mEventType ;
int mKeyModifiers ;
int mActionStartIndex ;
int mActionCount ;
} ;
struct ApiAction
{
int mActionType ;
} ;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
struct ApiDebugConfig
@ -30,8 +57,12 @@ struct ApiDebugConfig
// IMPORTANT! The definitions here must be kept in sync with their C# equivalents in MouseDll.cs.
extern void openApi(
const ApiAppConfig* pAppConfig ,
const ApiAppConfig* pAppConfig ,
const ApiDevice* pDevices , int nDevices ,
const ApiDeviceConfig* pDeviceConfigs , int nDeviceConfigs ,
const ApiAppProfile* pAppProfiles , int nAppProfiles ,
const ApiEvent* pEvents , int nEvents ,
const ApiAction* pActions , int nActions ,
const ApiDebugConfig* pDebugConfig ,
bool initConsole
) ;
@ -40,6 +71,10 @@ extern void closeApi() ;
extern void reloadConfig(
const ApiAppConfig* pAppConfig ,
const ApiDevice* pDevices , int nDevices ,
const ApiDeviceConfig* pDeviceConfigs , int nDeviceConfigs ,
const ApiAppProfile* pAppProfiles , int nAppProfiles ,
const ApiEvent* pEvents , int nEvents ,
const ApiAction* pActions , int nActions ,
const ApiDebugConfig* pDebugConfig
) ;

@ -0,0 +1,76 @@
#include "appProfile.hpp"
#include "api.hpp"
using namespace std ;
// --- CONSTRUCTORS ----------------------------------------------------
AppProfile::AppProfile(
const ApiAppProfile* pAppProfile ,
const ApiEvent* pEvents , int nEvents ,
const ApiAction* pActions , int nActions
)
{
// initialize the Device
mApp = toUtf8( pAppProfile->mpApp ) ;
// initialize the Device
for ( int i=0 ; i < nEvents ; ++i )
{
const ApiEvent* pEvent = pEvents + i ;
// validate the Action index/count
if ( pEvent->mActionStartIndex < 0 || pEvent->mActionStartIndex >= nActions )
{
throw runtime_error(
MAKE_STRING(
"Invalid Action start index: " << pEvent->mActionStartIndex
<< " (#=" << nActions << ")"
)
) ;
}
if ( pEvent->mActionCount < 0 || pEvent->mActionStartIndex + pEvent->mActionCount > nActions )
{
throw runtime_error(
MAKE_STRING(
"Invalid Action count: " << pEvent->mActionCount
<< " (s=" << pEvent->mActionStartIndex << ", #=" << nActions << ")"
)
) ;
}
// add the next Event
mEvents.push_back(
new Event(
pEvent ,
pActions+pEvent->mActionStartIndex , pEvent->mActionCount
)
) ;
}
}
// ---------------------------------------------------------------------
void
AppProfile::dumpAppProfile( ostream& os , const char* pPrefix ) const
{
// dump the AppProfile
if ( pPrefix == NULL )
pPrefix = "" ;
os << pPrefix << "AppProfile: \"" << app() << "\"" << endl ;
for ( EventPtrVector::const_iterator it=events().begin() ; it != events().end() ; ++it )
(*it)->dumpEvent( os , MAKE_CSTRING(pPrefix << " ") ) ;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ostream&
operator<<( ostream& os , const AppProfile& appProfile )
{
// insert the AppProfile
os << "[AppProfile:" << appProfile.app() << "]" ;
return os ;
}
// ---------------------------------------------------------------------
const string& AppProfile::app() const { return mApp ; }
const EventPtrVector& AppProfile::events() const { return mEvents ; }

@ -0,0 +1,45 @@
#ifndef APPPROFILE_HPP
#define APPPROFILE_HPP
#include "event.hpp"
#include "utils.hpp"
struct ApiAppProfile ;
// ---------------------------------------------------------------------
class AppProfile
{
// constructors/destructor:
public:
AppProfile(
const ApiAppProfile* pAppProfile ,
const ApiEvent* pEvents , int nEvents ,
const ApiAction* pActions , int nActions
) ;
DISABLE_COPY_ASSIGNMENT( AppProfile ) ;
// access methods:
public:
const std::string& app() const ;
const EventPtrVector& events() const ;
// miscellaneous methods:
public:
void dumpAppProfile( std::ostream& os , const char* pPrefix="" ) const ;
// data members:
private:
std::string mApp ;
EventPtrVector mEvents ;
} ;
typedef PtrVector<AppProfile> AppProfilePtrVector ;
// inserter
std::ostream& operator<<( std::ostream& , const AppProfile& ) ;
// ---------------------------------------------------------------------
#endif // APPPROFILE_HPP

@ -2,11 +2,11 @@
#include <iostream>
#include <fstream>
#include <stdexcept>
#include <cassert>
#include <map>
#include "device.hpp"
#include "api.hpp"
#include "device.hpp"
#include "deviceConfig.hpp"
#include "utils.hpp"
using namespace std ;
@ -17,9 +17,12 @@ static HMODULE ghInterceptionDll = NULL ;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
typedef map< int , Device > DeviceTable ;
typedef IntPtrMap<Device> DeviceTable ;
static DeviceTable gDeviceTable ;
typedef IntPtrMap<DeviceConfig> DeviceConfigTable ;
static DeviceConfigTable gDeviceConfigTable ;
// --- LOCAL DATA ------------------------------------------------------
static bool gEnableConsole = false ;
@ -46,6 +49,10 @@ void
openApi(
const ApiAppConfig* pAppConfig ,
const ApiDevice* pDevices , int nDevices ,
const ApiDeviceConfig* pDeviceConfigs , int nDeviceConfigs ,
const ApiAppProfile* pAppProfiles , int nAppProfiles ,
const ApiEvent* pEvents , int nEvents ,
const ApiAction* pActions , int nActions ,
const ApiDebugConfig* pDebugConfig ,
bool initConsole
)
@ -56,7 +63,15 @@ openApi(
// initialize
gEnableConsole = initConsole ;
reloadConfig( pAppConfig , pDevices , nDevices , pDebugConfig ) ;
reloadConfig(
pAppConfig ,
pDevices , nDevices ,
pDeviceConfigs , nDeviceConfigs ,
pAppProfiles , nAppProfiles ,
pEvents , nEvents ,
pActions , nActions ,
pDebugConfig
) ;
// load Interception
wchar_t buf[ _MAX_PATH+1 ] ;
@ -96,6 +111,10 @@ void
reloadConfig(
const ApiAppConfig* pAppConfig ,
const ApiDevice* pDevices , int nDevices ,
const ApiDeviceConfig* pDeviceConfigs , int nDeviceConfigs ,
const ApiAppProfile* pAppProfiles , int nAppProfiles ,
const ApiEvent* pEvents , int nEvents ,
const ApiAction* pActions , int nActions ,
const ApiDebugConfig* pDebugConfig
)
{
@ -105,7 +124,23 @@ reloadConfig(
if ( pDevices == NULL )
throw runtime_error( "Missing Device's." ) ;
if ( nDevices < 0 )
throw runtime_error( "Invalid device count." ) ;
throw runtime_error( "Invalid Device count." ) ;
if ( pDeviceConfigs == NULL )
throw runtime_error( "Missing DeviceConfig's." ) ;
if ( nDeviceConfigs < 0 )
throw runtime_error( "Invalid DeviceConfig count." ) ;
if ( pAppProfiles == NULL )
throw runtime_error( "Missing AppProfile's." ) ;
if ( nAppProfiles < 0 )
throw runtime_error( "Invalid AppProfile count." ) ;
if ( pEvents == NULL )
throw runtime_error( "Missing Event's." ) ;
if ( nEvents < 0 )
throw runtime_error( "Invalid Event count." ) ;
if ( pActions == NULL )
throw runtime_error( "Missing Action's." ) ;
if ( nActions < 0 )
throw runtime_error( "Invalid Action count." ) ;
if ( pDebugConfig == NULL )
throw runtime_error( "Missing DebugConfig." ) ;
const wchar_t* pLogFilename = pDebugConfig->mpLogFilename ;
@ -125,15 +160,53 @@ reloadConfig(
}
// load the Device's
gDeviceTable.clear() ;
gDeviceTable.deleteAll() ;
for ( int i=0 ; i < nDevices ; ++i )
{
const ApiDevice* pDevice = pDevices+i ;
gDeviceTable[ pDevice->mDeviceId ] = Device( pDevice ) ;
gDeviceTable[ pDevice->mDeviceId ] = new Device( pDevice ) ;
}
#if 1 // FIXME!
LOG_MSG( "Loaded devices:" ) ;
for ( DeviceTable::const_iterator it=gDeviceTable.begin() ; it != gDeviceTable.end() ; ++it )
(*it).second.dumpDevice( cout , " " ) ;
(*it).second->dumpDevice( cout , " " ) ;
#endif
// load the DeviceConfig's
gDeviceConfigTable.deleteAll() ;
for ( int i=0 ; i < nDeviceConfigs ; ++i )
{
const ApiDeviceConfig* pDeviceConfig = pDeviceConfigs + i ;
// validate the AppProfile index/count
if ( pDeviceConfig->mAppProfileStartIndex < 0 || pDeviceConfig->mAppProfileStartIndex >= nAppProfiles )
{
throw runtime_error(
MAKE_STRING(
"Invalid AppProfile start index: " << pDeviceConfig->mAppProfileStartIndex
<< " (#=" << nAppProfiles << ")"
)
) ;
}
if ( pDeviceConfig->mAppProfileCount < 0 || pDeviceConfig->mAppProfileStartIndex + pDeviceConfig->mAppProfileCount > nAppProfiles )
{
throw runtime_error(
MAKE_STRING(
"Invalid AppProfile count: " << pDeviceConfig->mAppProfileCount
<< " (s=" << pDeviceConfig->mAppProfileStartIndex << ", #=" << nAppProfiles << ")"
)
) ;
}
// add the next DeviceConfig
gDeviceConfigTable[ pDeviceConfig->mDeviceId ] = new DeviceConfig(
pDeviceConfig ,
pAppProfiles+pDeviceConfig->mAppProfileStartIndex , pDeviceConfig->mAppProfileCount ,
pEvents , nEvents ,
pActions , nActions
) ;
}
#if 1 // FIXME!
LOG_MSG( "Loaded device configs:" ) ;
for ( DeviceConfigTable::const_iterator it=gDeviceConfigTable.begin() ; it != gDeviceConfigTable.end() ; ++it )
(*it).second->dumpDeviceConfig( cout , " " ) ;
#endif
}

@ -16,43 +16,19 @@ Device::Device( const ApiDevice* pDevice )
mIsEnabled = pDevice->mIsEnabled ;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Device::Device()
: mDeviceId(-1)
, mHID() , mDeviceNumber(-1)
, mDisplayName() , mIsEnabled(false)
{
}
// --- COPY/ASSIGNMENT -------------------------------------------------
Device& Device::operator=( const Device& rhs )
{
// copy the Device
mDeviceId = rhs.deviceId() ;
mHID = rhs.hid() ;
mDeviceNumber = rhs.deviceNumber() ;
mDisplayName = rhs.displayName() ;
mIsEnabled = rhs.isEnabled() ;
return *this ;
}
Device::Device( const Device& rhs ) { operator=(rhs) ; }
// ---------------------------------------------------------------------
void
Device::dumpDevice( ostream& os , const char* pPrefix ) const
{
// dump the device
// dump the Device
if ( pPrefix == NULL )
pPrefix = "" ;
os << pPrefix << "Device (id=" << deviceId() << "):" << endl ;
os << pPrefix << "- hid = \"" << hid() << "\"" << endl ;
os << pPrefix << "- deviceNumber = " << deviceNumber() << endl ;
os << pPrefix << "- displayName = \"" << displayName() << "\"" << endl ;
os << pPrefix << "- isEnabled = " << isEnabled() << endl ;
os << pPrefix << *this << ":" << endl ;
os << pPrefix << " hid = \"" << hid() << "\"" << endl ;
os << pPrefix << " deviceNumber = " << deviceNumber() << endl ;
os << pPrefix << " displayName = \"" << displayName() << "\"" << endl ;
os << pPrefix << " isEnabled = " << isEnabled() << endl ;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -61,7 +37,7 @@ ostream&
operator<<( ostream& os , const Device& device )
{
// insert the Device
os << "[" << device.deviceId() << ":" << device.hid() << "/" << device.deviceNumber() << "]" ;
os << "[Device-" << device.deviceId() << ":" << device.hid() << "/" << device.deviceNumber() << "]" ;
return os ;
}

@ -1,8 +1,7 @@
#ifndef DEVICE_HPP
#define DEVICE_HPP
#include <string>
#include <ostream>
#include "utils.hpp"
struct ApiDevice ;
@ -14,11 +13,7 @@ class Device
// constructors/destructor:
public:
Device( const ApiDevice* pDevice ) ;
Device() ;
// copy/assignment:
public:
Device( const Device& rhs ) ;
Device& operator=( const Device& rhs ) ;
DISABLE_COPY_ASSIGNMENT( Device ) ;
// access methods:
public:
@ -42,6 +37,7 @@ private:
} ;
// inserter
std::ostream& operator<<( std::ostream& , const Device& ) ;
// ---------------------------------------------------------------------

@ -0,0 +1,77 @@
#include "deviceConfig.hpp"
#include "api.hpp"
using namespace std ;
// --- CONSTRUCTORS ----------------------------------------------------
DeviceConfig::DeviceConfig(
const ApiDeviceConfig* pDeviceConfig ,
const ApiAppProfile* pAppProfiles , int nAppProfiles ,
const ApiEvent* pEvents , int nEvents ,
const ApiAction* pActions , int nActions
)
{
// initialize the DeviceConfig
mDeviceId = pDeviceConfig->mDeviceId ;
for ( int i=0 ; i < nAppProfiles ; ++i )
{
const ApiAppProfile* pAppProfile = pAppProfiles + i ;
// validate the Event index/count
if ( pAppProfile->mEventStartIndex < 0 || pAppProfile->mEventStartIndex >= nEvents )
{
throw runtime_error(
MAKE_STRING(
"Invalid Event start index: " << pAppProfile->mEventStartIndex
<< " (#=" << nEvents << ")"
)
) ;
}
if ( pAppProfile->mEventCount < 0 || pAppProfile->mEventStartIndex + pAppProfile->mEventCount > nEvents )
{
throw runtime_error(
MAKE_STRING(
"Invalid Event count: " << pAppProfile->mEventCount
<< " (s=" << pAppProfile->mEventStartIndex << ", #=" << nEvents << ")"
)
) ;
}
// add the next Event
mAppProfiles.push_back(
new AppProfile(
pAppProfile ,
pEvents+pAppProfile->mEventStartIndex , pAppProfile->mEventCount ,
pActions , nActions
)
) ;
}
}
// ---------------------------------------------------------------------
void
DeviceConfig::dumpDeviceConfig( ostream& os , const char* pPrefix ) const
{
// dump the DeviceConfig
if ( pPrefix == NULL )
pPrefix = "" ;
os << pPrefix << *this << ":" << endl ;
os << pPrefix << " deviceId = " << deviceId() << endl ;
for ( AppProfilePtrVector::const_iterator it=appProfiles().begin() ; it != appProfiles().end() ; ++it )
(*it)->dumpAppProfile( os , MAKE_CSTRING(pPrefix << " ") ) ;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ostream&
operator<<( ostream& os , const DeviceConfig& deviceConfig )
{
// insert the DeviceConfig
os << "[DeviceConfig:" << deviceConfig.deviceId() << "]" ;
return os ;
}
// ---------------------------------------------------------------------
int DeviceConfig::deviceId() const { return mDeviceId ; }
const AppProfilePtrVector& DeviceConfig::appProfiles() const { return mAppProfiles ; }

@ -0,0 +1,45 @@
#ifndef DEVICECONFIG_HPP
#define DEVICECONFIG_HPP
#include "appProfile.hpp"
#include "utils.hpp"
struct ApiDeviceConfig ;
// ---------------------------------------------------------------------
class DeviceConfig
{
// constructors/destructor:
public:
DeviceConfig(
const ApiDeviceConfig* pDeviceConfig ,
const ApiAppProfile* pAppProfiles , int nAppProfiles ,
const ApiEvent* pEvents , int nEvents ,
const ApiAction* pActions , int nActions
) ;
DISABLE_COPY_ASSIGNMENT( DeviceConfig ) ;
// access methods:
public:
int deviceId() const ;
const AppProfilePtrVector& appProfiles() const ;
// miscellaneous methods:
public:
void dumpDeviceConfig( std::ostream& os , const char* pPrefix="" ) const ;
// data members:
private:
int mDeviceId ;
AppProfilePtrVector mAppProfiles ;
} ;
// inserter
std::ostream& operator<<( std::ostream& , const DeviceConfig& ) ;
// ---------------------------------------------------------------------
#endif // DEVICECONFIG_HPP

@ -0,0 +1,67 @@
#include "event.hpp"
#include "api.hpp"
#include "utils.hpp"
using namespace std ;
// --- LOCAL DATA ------------------------------------------------------
static EnumStringInfo gEventTypeStringTable[] =
{
{ Event::etMouseLeft , "mouseLeft" } ,
{ Event::etMouseRight , "mouseRight" } ,
{ Event::etMouseUp , "mouseUp" } ,
{ Event::etMouseDown , "mouseDown" } ,
{ -1 , NULL }
} ;
static BitFlagsInfo gKeyModifiersStringTable[] =
{
{ Event::kmCtrl , "Ctrl" } ,
{ Event::kmAlt , "Alt" } ,
{ Event::kmShift , "Shift" } ,
{ -1 , NULL } ,
} ;
// --- CONSTRUCTORS ----------------------------------------------------
Event::Event( const ApiEvent* pEvent , const ApiAction* pActions , int nActions )
{
// initialize the Event
mEventType = pEvent->mEventType ;
mKeyModifiers = pEvent->mKeyModifiers ;
// initialize the Event
for ( int i=0 ; i < nActions ; ++i )
mActions.push_back( Action::allocAction( pActions+i ) ) ;
}
// ---------------------------------------------------------------------
void
Event::dumpEvent( ostream& os , const char* pPrefix ) const
{
// dump the Event
os << pPrefix << *this << ":" << endl ;
for ( ActionPtrVector::const_iterator it=actions().begin() ; it != actions().end() ; ++it )
os << pPrefix << " " << *(*it) << endl ;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ostream&
operator<<( ostream& os , const Event& evt )
{
// insert the Event
os << "{Event:" << enumString(gEventTypeStringTable,evt.eventType()) ;
if ( evt.keyModifiers() != 0 )
os << ":" << bitFlagsString(gKeyModifiersStringTable,evt.keyModifiers(),'+') ;
os << "}" ;
return os ;
}
// ---------------------------------------------------------------------
int Event::eventType() const { return mEventType ; }
int Event::keyModifiers() const { return mKeyModifiers ; }
const ActionPtrVector& Event::actions() const { return mActions ; }

@ -0,0 +1,47 @@
#ifndef EVENT_HPP
#define EVENT_HPP
#include "actions.hpp"
#include "utils.hpp"
struct ApiEvent ;
// ---------------------------------------------------------------------
class Event
{
// data types:
public:
enum eEventType { etMouseLeft=1 , etMouseRight=2 , etMouseUp=3 , etMouseDown=4 } ;
enum eKeyModifiers { kmCtrl=0x0001 , kmAlt=0x0002 , kmShift=0x0004 } ;
// constructors/destructor:
public:
Event( const ApiEvent* pEvent , const ApiAction* pActions , int nActions ) ;
DISABLE_COPY_ASSIGNMENT( Event ) ;
// access methods:
public:
int eventType() const ;
int keyModifiers() const ;
const ActionPtrVector& actions() const ;
public:
void dumpEvent( std::ostream& os , const char* pPrefix="" ) const ;
// data members:
private:
int mEventType ;
int mKeyModifiers ;
ActionPtrVector mActions ;
} ;
typedef PtrVector<Event> EventPtrVector ;
// inserter
std::ostream& operator<<( std::ostream& , const Event& ) ;
// ---------------------------------------------------------------------
#endif // EVENT_HPP

@ -176,10 +176,18 @@
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
>
<File
RelativePath=".\actions.cpp"
>
</File>
<File
RelativePath=".\api.cpp"
>
</File>
<File
RelativePath=".\appProfile.cpp"
>
</File>
<File
RelativePath=".\core.cpp"
>
@ -188,10 +196,18 @@
RelativePath=".\device.cpp"
>
</File>
<File
RelativePath=".\deviceConfig.cpp"
>
</File>
<File
RelativePath=".\dllMain.cpp"
>
</File>
<File
RelativePath=".\event.cpp"
>
</File>
<File
RelativePath=".\utils.cpp"
>
@ -202,14 +218,30 @@
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
>
<File
RelativePath=".\actions.hpp"
>
</File>
<File
RelativePath=".\api.hpp"
>
</File>
<File
RelativePath=".\appProfile.hpp"
>
</File>
<File
RelativePath=".\device.hpp"
>
</File>
<File
RelativePath=".\deviceConfig.hpp"
>
</File>
<File
RelativePath=".\event.hpp"
>
</File>
<File
RelativePath=".\utils.hpp"
>

@ -1,11 +1,47 @@
#include <windows.h>
#include <cassert>
#include "utils.hpp"
using namespace std ;
// ---------------------------------------------------------------------
const char*
enumString( const EnumStringInfo* pEnumStringTable , int val )
{
// return the enum value's name
for ( const EnumStringInfo* pInfo=pEnumStringTable ; pInfo->mpName != NULL ; ++pInfo )
{
if ( pInfo->mVal == val )
return pInfo->mpName ;
}
assert( false ) ;
return "???" ;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
string
bitFlagsString( const BitFlagsInfo* pBitFlagsTable , int val , char sep )
{
// convert the bit flags to a string
vector<const char*> bitFlags ;
for ( const BitFlagsInfo* pInfo=pBitFlagsTable ; pInfo->mpName != NULL ; ++pInfo )
{
if ( val & pInfo->mFlag )
bitFlags.push_back( pInfo->mpName ) ;
}
stringstream buf ;
for ( size_t i=0 ; i < bitFlags.size() ; ++i )
{
if ( i > 0 )
buf << sep ;
buf << bitFlags[i] ;
}
return buf.str() ;
}
// ---------------------------------------------------------------------
string
getErrorString( int errorCode )
{

@ -1,11 +1,22 @@
#ifndef UTILS_HPP
#define UTILS_HPP
#include <vector>
#include <map>
#include <string>
#include <sstream>
#include <cassert>
// ---------------------------------------------------------------------
struct EnumStringInfo { int mVal ; const char* mpName ; } ;
extern const char* enumString( const EnumStringInfo* pEnumStringTable , int val ) ;
struct BitFlagsInfo { int mFlag ; const char* mpName ; } ;
extern std::string bitFlagsString( const BitFlagsInfo* pBitFlagsTable , int val , char sep ) ;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
extern std::string getLastErrorString() ;
extern std::string getErrorString( int errorCode ) ;
@ -26,12 +37,49 @@ extern std::ostream& operator<<( std::ostream& , const std::wstring& ) ;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
#define MAKE_STRING( msg ) ( ((std::ostringstream&)((std::ostream&)std::ostringstream() << msg)).str() )
#define MAKE_STRING( msg ) ( ((std::ostringstream&)((std::ostream&)std::ostringstream() << msg)).str() )
#define MAKE_CSTRING( msg ) ( MAKE_STRING( msg ).c_str() )
// ---------------------------------------------------------------------
// NOTE: These classes are not 100% correct (e.g. if an item is replaced with a new one,
// the old object won't get delete'd), but they will suffice for our purposes.
template< typename T >
class PtrVector : public std::vector<T*>
{
public:
~PtrVector()
{
// clean up
for ( iterator it=begin() ; it != end() ; ++it )
delete *it ;
}
} ;
template< typename T >
class IntPtrMap : public std::map<int,T*>
{
public:
~IntPtrMap() { deleteAll() ; }
void deleteAll()
{
// delete all items
for ( iterator it=begin() ; it != end() ; ++it )
delete (*it).second ;
clear() ;
}
} ;
// ---------------------------------------------------------------------
#define ARRAY_SIZE( arr ) ( sizeof(arr) / sizeof((arr)[0]) )
#define DISABLE_COPY_ASSIGNMENT( ClassName ) \
private: \
ClassName( const ClassName& rhs ) ; \
ClassName& operator=( const ClassName& rhs ) ;
// ---------------------------------------------------------------------
#endif // UTILS_HPP
#endif // UTILS_HPP

Loading…
Cancel
Save