Joystick handling


#1

I’ve started making a Joystick class for use with Juce. It’s going to be windows only, but I’m trying to keep the class declarations platform independant like the rest of Juce so that someone could modify the .cpp files for a mac/linux implementation (i don’t use either of those platforms so alas i’ll never be likely to do them myself).

It’s not finished yet, but I’ve made a test application that demonstrates responding to the first four buttons of the first detected gamepad.

joystick basic test

The classes aren’t finished yet, but it hopefully shouldn’t take me too long. I’ll be sure to share them here when they’re done!

FWIW, it works in a cross between the Juce::MidiInput and mouse handling systems. You open a joystick device like the midi input, and give it a JoystickListener, which has callbacks like the mouse ones, which recieve a JoystickEvent. So far I’ve got the callbacks for buttonPressed and buttonReleased, but there will also be axisMoved and stuff like that.

Just thought I’d post this in case anyone was interested :slight_smile:


#2

the test app now uses all available buttons on the first device, as well as the main XY axis


#3

Updated again, now the test app shows usage of the buttons, pov hat and first two axes of movement. There is support for up to 16 buttons, a pov hat and up to 6 axes.

It’s actually quite a pretty app too!

If anyone has a gamepad/joystick connected to their pc, i’d really like to hear a description of what happens when you use the various controls. It will help a great deal in coming up with a good flexible way of making a remappable joystick event response system.


#4

actually the latest demo is crashing on startup


#5

good to know :slight_smile: it’s worked for someone else already, so i guess i need to find out what might cause such an incompatibility. thanks for testing it at least, i still have quite a lot of work to do on it til it’s finished.

at present it’s only really going to work properly with a PS2 gamepad connected with an adaptor, as that’s all i have to design the configuration. i’m trying to abstract things a bit tho.


#6

sounds cool - wish I had any kind of joystick I could try it with!


#7

I may give it a download. And yea, I assume you are using DInput, which is the best by far for windows as it supports Forcefeedback and such. SDL, although horrible to use, is a multiplatform library for many things, including an input library, could use it to allow multi-platform support.

Also, look up OIS (Open Input System), far easier to use, but it is tied a bit to the OGRE rendering engine, you could see how it does things (It uses sdl, dinput, another or two, to get best results for everything).


#8

actually i’m not currently using DInput. I want to, and tried to at first but literally didn’t know where to start. I need to learn how to make use of directX features, and that will of course involve reinstalling the DXSDK :slight_smile: it’s not been reinstalled since my last reformat as the newer juce doesn’t need the headers anymore. I’m currently using the winmm system, and have a polling thread that makes use of JOYINFOEX structures for state data.

The way it’s coded though, it shouldn’t be a problem to change to a directX implementation when i figure out how. I’ve got it working fine with the winmm set on my joypad- every feature except vibration is implemented and functional. my main issue is compatibility with other controllers, specifically getting general things like axes and digital directions operate in the same way across controls (some use axes for their dpads, others use a POV hat representation, etc). I have a feeling that directX will help eliminate such compatibility woes.

I’ve got a little midi plugin working with it on my pad. Midi notes are triggered by button presses, and the pov hat (which is a d-pad on the PS2 controllers) transposes the note value of any buttons that are held when pressing up or down. This makes it really quick to select notes that you want to play, without using any other interface than the one in your hand. A bit like a keyboard, but easier to play. And the XY sticks control CCs. I’m going to add a LEFT/RIGHT feature to cycle thru programs of button/note assignment groups, so you can quickly build your own scales and flick between them while playing over a song.

So far it doesn’t have a GUI, and doesn’t need one yet.

To show you the sort of way the Joystick classes are currently used (and how easy it is), here’s the code for the main app class that drives the plugin (and sits inside a totally basic JuceAudioPlugin Filter). I.e. to make use of joysticks, this is all you need to do:

[code]

MidiJoystickSystem::MidiJoystickSystem (MidiBuffer& output)
: midiOutput (output)
{
joystick = 0;
}

MidiJoystickSystem::~MidiJoystickSystem ()
{
if (joystick) deleteAndZero (joystick);
}

//===================================================================
void MidiJoystickSystem::openJoystick (int id)
{
joystick = Joystick::openJoystick (id, this);
}

void MidiJoystickSystem::start ()
{
if (joystick) joystick->start ();
}

void MidiJoystickSystem::start ()
{
if (joystick) joystick->stop ();
}

//===================================================================
void MidiJoystickSystem::sendMidiMessage (const MidiMessage& msg)
{
midiOutput.addEvent (msg, 0);
}

//===================================================================
void MidiJoystickSystem::buttonPressed (const JoystickEvent& j)
{
for (int i=0; i<buttonAssignments.getNumberOfButtons (); i++)
{
JoystickMidiButton* button = buttonAssignments.getButton (i);
if (j.buttonPressed (button->getAssignedJoystickButton ()))
{
sendMidiMessage (button->getNoteOn ());
}
}
}

void MidiJoystickSystem::buttonReleased (const JoystickEvent& j)
{
for (int i=0; i<buttonAssignments.getNumberOfButtons (); i++)
{
JoystickMidiButton* button = buttonAssignments.getButton (i);
if (j.buttonReleased (button->getAssignedJoystickButton ()))
{
sendMidiMessage (button->getNoteOff ());
}
}
}

void MidiJoystickSystem::axisMoved (const JoystickEvent& j)
{
for (int i=0; i<axisAssignments.getNumberOfAxes(); i++)
{
JoystickMidiAxis* axis = axisAssignments.getAxis (i);
Joystick::AxisID id = axis->getAssignedJoystickAxis ();
if (j.axisHasChanged (id))
{
sendMidiMessage (axis->getMessage (j.getAxisProportion(id)*127));
}
}
}

void MidiJoystickSystem::povMoved (const JoystickEvent &j)
{
if (j.getPovDirection () == up)
{
DBG (T(“UP pressed”));
// pressed D-Pad up… any buttons held?
for (int i=0; i<buttonAssignments.getNumberOfButtons (); i++)
{
JoystickMidiButton* button = buttonAssignments.getButton (i);
if (button)
{
if (j.isButtonDown (button->getAssignedJoystickButton ()))
{
sendMidiMessage (button->getNoteOff ());
button->incrementNoteNumber ();
sendMidiMessage (button->getNoteOn ());
}
}
}
}
else if (j.getPovDirection () == down)
{
DBG (T(“DOWN pressed”));
// pressed D-Pad up… any buttons held?
for (int i=0; i<buttonAssignments.getNumberOfButtons (); i++)
{
JoystickMidiButton* button = buttonAssignments.getButton (i);
if (button)
{
if (j.isButtonDown (button->getAssignedJoystickButton ()))
{
sendMidiMessage (button->getNoteOff ());
button->decrementNoteNumber ();
sendMidiMessage (button->getNoteOn ());
}
}
}
}
}[/code]


#9

Just realised I’ve not posted the code for this! :-o

http://haydxn.net/content/juce/code/windows/joystick_v1.zip

All you need to do is include Joystick.h, the header should hopefully be fairly self explanatory


#10