Skip to content

Commit

Permalink
Added Matlab/Octave bindings, thanks to Thomas Weibel.
Browse files Browse the repository at this point in the history
  • Loading branch information
icculus committed Jan 2, 2013
1 parent 5d2a053 commit 3b905ff
Show file tree
Hide file tree
Showing 6 changed files with 258 additions and 0 deletions.
11 changes: 11 additions & 0 deletions README.txt
Expand Up @@ -102,6 +102,17 @@ Java bindings:
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
Expand Down
33 changes: 33 additions & 0 deletions contrib/matlab/ManyMouse.m
@@ -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

40 changes: 40 additions & 0 deletions contrib/matlab/compile_manymouse_mex.m
@@ -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

25 changes: 25 additions & 0 deletions contrib/matlab/demo_class.m
@@ -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();
24 changes: 24 additions & 0 deletions contrib/matlab/demo_mex.m
@@ -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' );
125 changes: 125 additions & 0 deletions contrib/matlab/manymouse_mex.cpp
@@ -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." );
}

0 comments on commit 3b905ff

Please sign in to comment.