Added Matlab/Octave bindings, thanks to Thomas Weibel. default tip
authorRyan C. Gordon <icculus@icculus.org>
Wed, 02 Jan 2013 15:41:29 -0500
changeset 124 2e0dbebdbd28
parent 123 8228b0663045
Added Matlab/Octave bindings, thanks to Thomas Weibel.
README.txt
contrib/matlab/ManyMouse.m
contrib/matlab/compile_manymouse_mex.m
contrib/matlab/demo_class.m
contrib/matlab/demo_mex.m
contrib/matlab/manymouse_mex.cpp
--- a/README.txt	Thu Aug 09 10:59:23 2012 -0400
+++ b/README.txt	Wed Jan 02 15:41:29 2013 -0500
@@ -102,6 +102,17 @@
   gave me the rundown on getting this to work with Cygwin.
 
 
+Matlab/Octave bindings:
+  There's a little Matlab/Octave wrapper in contrib/matlab. It can be compiled
+  using the function "compile_manymouse_mex.m". Tested under Windows 7
+  (Matlab 2010b) and Ubuntu 12.04 (Octave 3.2.4 and Matlab 2011a).
+
+  Demo scripts for Octave compatible function call ('demo_mex.m') as well as
+  Matlab's class Interface ('ManyMouse.m', 'demo_class.m') are also included.
+
+  Thanks to Thomas Weibel for the Matlab work.
+
+
 Some general ManyMouse usage notes:
  - If a mouse is disconnected, it will not return future events, even if you
    plug it right back in. You will be alerted of disconnects programmatically
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/matlab/ManyMouse.m	Wed Jan 02 15:41:29 2013 -0500
@@ -0,0 +1,33 @@
+classdef ManyMouse
+
+    properties
+    end
+    
+    methods (Static)
+        
+      
+        function availableMice = init(  )
+            availableMice = manymouse_mex( 'ManyMouse_Init' );
+        end
+        
+        function quit( )
+            manymouse_mex( 'ManyMouse_Quit' );
+        end
+        
+        function sDriverName = driverName(  )
+            sDriverName = manymouse_mex( 'ManyMouse_DriverName' );
+        end
+        
+        function sDeviceNames = deviceName(  )
+            sDeviceNames = manymouse_mex( 'ManyMouse_DeviceName' );
+        end
+        
+        function event = pollEvent(  )
+            event = manymouse_mex( 'ManyMouse_PollEvent' );
+        end
+        
+        
+    end
+    
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/matlab/compile_manymouse_mex.m	Wed Jan 02 15:41:29 2013 -0500
@@ -0,0 +1,40 @@
+function compile_manymouse_mex
+
+    if isOctave()
+
+        % The file 'mkoctfile' (/usr/bin/mkoctfile on Ubuntu 12.04) should have these flags added to CXXFLAGS: 
+        % -std=c++0x -fpermissive -fPIC -DNDEBUG
+        % While Matlab allows to add these flags when calling mex() (see below) , Octave doesn't ...
+        mex( '-I../..', '-lX11', '-ldl', ...
+            'manymouse_mex.cpp', ...
+            '../../manymouse.c', ...
+            '../../linux_evdev.c', ...
+            '../../macosx_hidmanager.c', ...
+            '../../macosx_hidutilities.c', ...
+            '../../windows_wminput.c', ...
+            '../../x11_xinput2.c' );
+
+    else
+        mex( '-I../..', '-lX11', '-ldl', 'CXXFLAGS=$CXXFLAGS -std=c++0x -fpermissive -fPIC -DNDEBUG', ...
+            'manymouse_mex.cpp', ...
+            '../../manymouse.c', ...
+            '../../linux_evdev.c', ...
+            '../../macosx_hidmanager.c', ...
+            '../../macosx_hidutilities.c', ...
+            '../../windows_wminput.c', ...
+            '../../x11_xinput2.c' );
+    end
+
+end
+
+
+function isOct = isOctave()
+    v = ver;
+    ret = strcmpi(v(1).Name,'Octave');
+    if ret 
+        isOct = true;
+    else
+        isOct = false; 
+    end
+end 
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/matlab/demo_class.m	Wed Jan 02 15:41:29 2013 -0500
@@ -0,0 +1,25 @@
+%% Example for Matlab's class interface
+
+%  Demo script for the Matlab/Octave MEX wrapper for ManyMouse.
+%  Please see the file LICENSE.txt in the source's root directory.
+%  Thomas Weibel, 2012/12/20
+ 
+
+clear all
+mm = ManyMouse();
+
+availableMice = mm.init()
+driverName = mm.driverName()
+deviceNames = mm.deviceName()
+
+i = 0;
+while i < 100
+    event = mm.pollEvent();
+    if ~ strcmp( event.event, 'MANYMOUSE_NO_EVENT' )
+       disp( event ); i = i+1;
+   end
+end
+% If this isn't called on Windows before calling 'ManyMouse_Init' again,
+% only restarting Matlab will make it work again. So always call
+% 'ManyMouse_Quit' on Windows ...
+mm.quit();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/matlab/demo_mex.m	Wed Jan 02 15:41:29 2013 -0500
@@ -0,0 +1,24 @@
+%% Example for mex function call. Should work both in Octave and Matlab.
+
+%  Demo script for the Matlab/Octave MEX wrapper for ManyMouse.
+%  Please see the file LICENSE.txt in the source's root directory.
+%  Thomas Weibel, 2012/12/20
+
+clear all
+more off;
+
+availableMice = manymouse_mex( 'ManyMouse_Init' )
+driverName = manymouse_mex( 'ManyMouse_DriverName' )
+deviceNames = manymouse_mex( 'ManyMouse_DeviceName' )
+
+i = 0;
+while i < 100
+   event = manymouse_mex( 'ManyMouse_PollEvent' );
+   if ~ strcmp( event.event, 'MANYMOUSE_NO_EVENT' )
+       disp( event ); i = i+1;
+   end
+end
+% If this isn't called on Windows before calling 'ManyMouse_Init' again,
+% only restarting Matlab will make it work again. So always call
+% 'ManyMouse_Quit' on Windows ...
+manymouse_mex( 'ManyMouse_Quit' );
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/matlab/manymouse_mex.cpp	Wed Jan 02 15:41:29 2013 -0500
@@ -0,0 +1,125 @@
+/*
+ * A Matlab / Octave MEX wrapper for ManyMouse.
+ *
+ * Please see the file LICENSE.txt in the source's root directory.
+ *
+ *  Thomas Weibel, 2012/12/20
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string>
+
+#include "manymouse.h"
+
+#include <mex.h>
+#include <stdint.h>
+
+
+// Convert mxArray* to an std::string
+void convert( const mxArray* ma, std::string& sString )
+{
+    if( !mxIsChar( ma ) )
+        mexErrMsgTxt( "!mxIsChar" );
+    char *str = mxArrayToString( ma );
+    sString = std::string( str );
+}
+
+//! Converts a double (or int, ...) scalar to mxArray
+mxArray* convert( const double& scalar, mxArray*& ma )
+{
+    ma = mxCreateDoubleScalar( (double) scalar );
+    return ma;
+}
+
+// MEX gateway function
+void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
+{
+    if( nrhs != 1 )
+        mexErrMsgTxt( "manymouse_mex: nrhs != 1.\n" );
+    
+    std::string sMethod;
+    convert( prhs[0], sMethod );
+    static ManyMouseEvent event;
+    static int available_mice;
+    
+    if( sMethod == "ManyMouse_Init" )
+    {
+        ManyMouse_Quit(); 
+        available_mice = ManyMouse_Init();
+        if( available_mice == 0 )
+        {
+            ManyMouse_Quit();
+            mexErrMsgTxt( "manymouse_mex: Found no mice ...\n" );
+        }
+        else if (available_mice < 0)
+        {
+            ManyMouse_Quit();
+            mexErrMsgTxt( "Error initializing ManyMouse!\n" );          
+        }        
+        convert( available_mice, plhs[0] );
+    }
+    else if( sMethod == "ManyMouse_Quit" )
+    {
+        ManyMouse_Quit(); 
+    }
+    else if( sMethod == "ManyMouse_DriverName" )
+    {
+        plhs[0] = mxCreateString(  ManyMouse_DriverName() );
+    }
+    else if( sMethod == "ManyMouse_DeviceName" )
+    {
+        plhs[0] = mxCreateCellMatrix( available_mice, 1 );
+        for (int i = 0; i < available_mice; i++)
+            mxSetCell( plhs[0], i, mxCreateString( ManyMouse_DeviceName(i) ) );
+    }
+    else if( sMethod == "ManyMouse_PollEvent" )
+    {            
+        if( ManyMouse_PollEvent(&event) )
+        {
+            const char* fieldnames[] = {"device", "event", "item", "value" };
+            plhs[0] = mxCreateStructMatrix(1,1,4,fieldnames);
+        
+            mxSetField( plhs[0], 0, "device", mxCreateDoubleScalar( (double) event.device ) );
+            // Could also return item as integer ...
+            //mxSetField( plhs[0], 0, "event", mxCreateDoubleScalar( (double) event.type ) );
+            mxSetField( plhs[0], 0, "item", mxCreateDoubleScalar( (double) event.item ) );
+            mxSetField( plhs[0], 0, "value", mxCreateDoubleScalar( (double) event.value ) );
+            
+            if (event.type == MANYMOUSE_EVENT_RELMOTION)
+            {
+                mxSetField( plhs[0], 0, "event", mxCreateString( "MANYMOUSE_EVENT_RELMOTION" ) );        
+            }
+            else if (event.type == MANYMOUSE_EVENT_ABSMOTION)
+            {
+                mxSetField( plhs[0], 0, "event", mxCreateString( "MANYMOUSE_EVENT_ABSMOTION" ) );        
+            }
+            else if (event.type == MANYMOUSE_EVENT_BUTTON)
+            {
+                mxSetField( plhs[0], 0, "event", mxCreateString( "MANYMOUSE_EVENT_BUTTON" ) );
+            }
+            else if (event.type == MANYMOUSE_EVENT_SCROLL)
+            {
+                mxSetField( plhs[0], 0, "event", mxCreateString( "MANYMOUSE_EVENT_SCROLL" ) );            
+            }
+            else if (event.type == MANYMOUSE_EVENT_DISCONNECT)
+                mxSetField( plhs[0], 0, "event", mxCreateString( "MANYMOUSE_EVENT_DISCONNECT" ) ); 
+            else
+            {
+                mxSetField( plhs[0], 0, "event", mxCreateString( "MANYMOUSE_UNHANDLED_EVENT" ) ); 
+            }     
+        }   
+        else
+        {
+            const char* fieldnames[] = {"device", "event", "item", "value" };
+            plhs[0] = mxCreateStructMatrix(1,1,4,fieldnames);     
+            mxSetField( plhs[0], 0, "device", mxCreateDoubleScalar( -1 ) );
+            mxSetField( plhs[0], 0, "event", mxCreateString( "MANYMOUSE_NO_EVENT" ) ); 
+            mxSetField( plhs[0], 0, "item", mxCreateDoubleScalar( -1 ) );
+            mxSetField( plhs[0], 0, "value", mxCreateDoubleScalar( -1 ) );
+        }
+    }   
+    else
+        mexErrMsgTxt( "manymouse_mex: Not a supported method." );    
+}
+