Skip to content


Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?


Failed to load latest commit information.
Latest commit message
Commit time


joystick & game controller hid device event to Open Sound Control daemon and associated tools

Copyright (c) Dan Wilcox 2007 - 2021


USB joysticks & game controllers are a cheap, ubiquitous source for alternate interfaces and can be easily hacked with custom switches, buttons, and analog sensors. Furthermore, physical computing platforms such as Arduino & Teensy can be configured to appear as USB HID (Human Interface Devices). joyosc provides a quick OSC event interface for such devices into your favorite creative coding environments (Pure Data, Max MSP, Processing, OpenFrameworks, etc).

The joyosc package contains the following parts:

  1. joyosc: device event daemon
  2. lsjs: joystick & game controller info tool

This group of tools allows any OSC capable program to receive joystick & game controller event data aka button presses, axis movements, etc. Specific joysticks & game controllers can be mapped by name to specific OSC send addresses and button, axis, etc ids can be remapped or ignored.

These tools were developed for the robotcowboy project, a wearable computer music system using Pure Data in GNU/Linux. See


Download a release tarball from Do not download a release zip from Github as the submodule files will not be included.

Otherwise, if cloning this repo, you will also need to check out the submodules using then run to create the configure script:

git clone
cd joyosc
git submodule init
git submodule update

On the macOS command line, use Homebrew to install libraries, then build and install to the /usr/local prefix via:

brew install sdl2 liblo tinyxml2
make install

and the same goes for Ubuntu/Debian with the additional call to ldconfig or shared helper libraries may not be found after install*:

sudo apt-get install libsdl2-dev liblo-dev libtinyxml2-dev
sudo make install
sudo ldconfig

If everything finished successfully, you're good to go.

If you're using Pure Data, check out the joyosc abstraction library in data/pd and installed into $(prefix)/share/doc/joyosc/pd/joyosc.

*: See the "Loading shared libraries error" section for more info


The following libraries are required:

  • SDL2: input device events
  • liblo: OSC
  • tinyxml2: XML file reading


Install the required development versions of the libraries using your distro's package manager.

For Debian/Ubuntu, you can use use apt-get on the command line:

sudo apt-get libsdl2-dev liblo-dev tinyxml2-dev


On macOS, they can be installed easily using Homebrew or Macports


  • install the Homebrew environment
  • go to the Terminal and install the libs:
brew install sdl2 liblo tinyxml2


  • install the Macports binary and setup the Macports environment
  • go to the Terminal and install the libs:
sudo port install libsdl2 liblo tinyxml2

If you use the default Macports install location of /opt/local, you will need to set the Macports include and lib dirs before running ./configure:

export CXXFLAGS=-I/opt/local/include && export LDFLAGS=-L/opt/local/lib


Thanks to Fede Camara Halac for the following steps.

On Windows, it is recommended to use Msys2 to install the required build system and library dependencies. Msys2 provides both 32 and 64 MinGW and command shells.

Note: Msys2 development seems to change frequently, so some of the package names below may have changed after this document was written.

Open an Msys2 shell and install the compiler chain & autotools via:

# 32 bit
pacman -S mingw-w64-i686-toolchain mingw-w64-i686-clang \
          make pkgconfig autoconf automake libtool

# 64 bit
pacman -S mingw-w64-x86_64-toolchain mingw-w64-x86_64-clang \
          make pkgconfig autoconf automake libtool

Next install SDL2 and TinyXML2:

# 32 bit
pacman -S mingw-w64-i686-SDL2 mingw-w64-i686-tinyxml2

# 64 bit
pacman -S mingw-w64-x86_64-SDL2 mingw-w64-x86_64-tinyxml2

Msys2 does not have a package for liblo, so you need to download the source from then build & install it manually:

cd liblo-0.30
./configure --disable-debug --disable-dependency-tracking --disable-tests --disable-network-tests --disable-tools --disable-examples
make install


As this is an GNU autotools project, simply run the following on the command line:

sudo make install

Note: If you have cloned joyosc from a git repo, you may need to generate the configure script by running ./ first and you will need autoconf, automake, and libtool installed as well.

This readme, example config files, and the pd library are also installed to your doc dir, something like $(prefix)/share/doc/joyosc.

By default, the configure script installs to /usr/local. To change this behavior, specify a new dir before building the project:

./configure --prefix=/path/to/install/dir

If using Macports on macOS, it is recommended to use the Macports default prefix of /opt/local. Homebrew installs to /usr/local so you won't need to set the prefix.

lopack & tinyobject libraries

Two helper libraries are included with joysoc in the lib folder: lopack & tinyobject. By default, these libraries are built and installed along with joyosc. If you happen to have either installed separately (not likely), you can disable the use of the local library when building via:

./configure --without-local-lopack --without-local-tinyobject

Loading shared libraries error

On some Linux systems, the install may finish successfully, but running joyosc will fail with the following error:

$ joyosc
joyosc: error while loading shared libraries: cannot open shared object file: No such file or directory

This can happen if installing to /usr/local and can be fixed by regenerating the system's lib cache by running:

sudo ldconfig


All applications have a full help usage printout, use -h or --help.


% joyosc

Starts device daemon with the default settings.

Config File

% joyosc config_file.xml

Starts device daemon using the given config file.

The config file sets the OSC connection information as well as device to OSC device name address mappings. A custom config file will allow you to specify:

  • setup info such as listening and sending ports
  • OSC device name addresses for specific device names
  • axis dead zone values for jittery thumb sticks
  • button, axis, hat, & trackball re-mappings
  • which button, axis, hat, & trackball events to ignore
  • custom SDL2 game controller mapping strings for devices only detected as joysticks

Look at the example_config.xml file installed to the doc folder or in the data folder of the source distribution for details.


You can also specify values on the command line which override values in the config file:

  -l, --listening-port Listening port (default: 7770)
  -m, --multicast      Multicast listening group address (off by default)
  -i, --ip             IP address, hostname, or multicast group to send to
  -p, --port           Port to send to (default: 8880)
  -e, --events         Print incoming events, useful for debugging
  -j, --joysticks-only Disable game controller support, joystick interface only
  -s, --sleep          Sleep time in usecs (default: 10000)

Note: Enabling event printing is useful when debugging:

% joyosc -e
/js2 Saitek P990 Dual Analog Pad axis: 0 32767
/js2 Saitek P990 Dual Analog Pad axis: 1 -32768
/js2 Saitek P990 Dual Analog Pad axis: 2 -32768
/js2 Saitek P990 Dual Analog Pad axis: 3 -32768
/js2 Saitek P990 Dual Analog Pad button: 8 1
/js2 Saitek P990 Dual Analog Pad button: 9 1
/js2 Saitek P990 Dual Analog Pad button: 10 1
/js2 Saitek P990 Dual Analog Pad button: 11 1
/js2 Saitek P990 Dual Analog Pad button: 0 1
/js2 Saitek P990 Dual Analog Pad button: 3 1
/js2 Saitek P990 Dual Analog Pad button: 0 0
/js2 Saitek P990 Dual Analog Pad button: 3 0
/js2 Saitek P990 Dual Analog Pad button: 0 1
/js2 Saitek P990 Dual Analog Pad button: 3 1
/js2 Saitek P990 Dual Analog Pad button: 0 0
/js2 Saitek P990 Dual Analog Pad button: 3 0
/js2 Saitek P990 Dual Analog Pad button: 3 1
/js2 Saitek P990 Dual Analog Pad button: 3 0
/js2 Saitek P990 Dual Analog Pad button: 0 1

A similar printout for a game controller:

% joyosc -e
/gc0 Logitech F510 Gamepad (DInput) button: a 1
/gc0 Logitech F510 Gamepad (DInput) button: a 0
/gc0 Logitech F510 Gamepad (DInput) button: b 1
/gc0 Logitech F510 Gamepad (DInput) button: b 0
/gc0 Logitech F510 Gamepad (DInput) button: x 1
/gc0 Logitech F510 Gamepad (DInput) button: x 0
/gc0 Logitech F510 Gamepad (DInput) axis: righty 3469
/gc0 Logitech F510 Gamepad (DInput) axis: rightx 5782
/gc0 Logitech F510 Gamepad (DInput) axis: righty 7324
/gc0 Logitech F510 Gamepad (DInput) axis: leftx -3470

Game Controllers vs. Joysticks

As of SDL 2, there are two joystick event interfaces:

  1. Joystick: original low level HID interface with buttons, axes, hats, & balls (aka trackballs)
  2. Game Controller: higher level interface that maps button, axis, etc ids to generic button & axis names

Joystick devices report all input events with a numeric button, axis, hat, & trackball id which may vary between devices.

Game Controllers map underlying joystick inputs to generic button and axis name strings if the device is detected by SDL as having a game controller mapping. If a device is not detected, you can add a custom SDL mapping string via the xml config file or an external text file. See the following for more info: SDL_GameControllerAddMapping & SDL Game Controller DB.

SDL Game Controller button names: a, b, x, y, start, back, guide, leftshoudler, lefttrigger, rightshoulder, righttrigger, leftstick, rightstick, dpup, dpdown, dpleft, dpright (dp = digital pad)

SDL Game Controller axis names: leftx, lefty, rightx, righty

Note: Game Controller names seem to follow the general Playstation DualShock layout. Devices with more than 4 axes and ~20 buttons are probably best used as Joysticks.

If you do not want to use the Game Controller interface and stick with Joysticks only, use the --joysticks-only commandline option.

Event Streaming

See the Pure Data patches installed to the system doc folder or the data/pd folder of the source distribution for info on how to receive events from joyosc, although any software that can receive Open Sound Control messages will work.

joyosc streams device event information in the following OSC address format:

  • DEVICE_NAME is the mapped name to the device as specified in the config file, otherwise it is "gc#" or "js#" with # being the current device id
  • INPUT_TYPE can be button, axis, ball, or hat for joysticks and button or axis for game controllers
  • ID is the joystick id number or game controller name string for the control (aka joystick button 1, axis 2, etc / game controller button x, axis lefty, etc); these are likely different between joystick devices but largely the same between game controllers
  • VALUE is the current value of the control:
    • button state values are 1 or 0 for pressed & released
    • axis values are -32767 to 32767 (signed 16 bit)
    • hat values are binary bits representing the hat button aka: 0, 2, 4, 8
    • (track)ball values are relative x & y movement in pixels (I think, SDL docs don't go into details)

Example joystick messages:

/joyosc/devices/js2/button 2 1
/joyosc/devices/js2/button 2 0
/joyosc/devices/js2/axis 0 32767

Example game controller messages:

/joyosc/devices/gc0/button lefttrigger 1
/joyosc/devices/gc0/button lefttrigger 0
/joyosc/devices/gc0/axis righty 32767


joyosc also sends status notification messages:

/joyosc/notifications/open devType\* deviceID
/joyosc/notifications/close devType\* deviceID

* devType is either "joystick" or "controller"

Control Messages

joyosc also listens for osc control messages on a specified listening port (default: 7770).

The current messages are:


Note: This capability may be expanded in the future.


The lsjs tool lists the names of currently plugged in joysticks & game controllers, which you can then use to create your device mappings.

Example output:

% lsjs
0 Controller: "Logitech F510 Gamepad (DInput)" 6d0400000000000018c2000000000000

You can also print detailed info using the -d or --details flags.

% lsjs -d

0 Controller: "Logitech F510 Gamepad (DInput)" 6d0400000000000018c2000000000000
  num axes: 4
  num buttons: 12

Here is the same device as a joystick when disabling the game controller interface:

% lsjs -dj

0 Joystick: "Logitech RumblePad 2 USB" 6d0400000000000018c2000000000000
  num axes: 4
  num buttons: 12
  num balls: 0
  num hats: 1

If you want to customize an SDL game controller mapping, you can print the default mapping string for a plugged in device:

% lsjs -m
0 Controller: "Logitech F510 Gamepad (DInput)" 6d0400000000000018c2000000000000

6d0400000000000018c2000000000000,Logitech F510 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,


  -d, --details        Print device details (buttons, axes, GUIDs, etc)
  -m, --mappings       Print game controller mappings
  -j, --joysticks-only Disable game controller support, joystick interface only

Console Error

As joyosc & lsjs use SDL, they will not work over a SSH connection and you'll get the following error:

Error: could not init SDL: Unable to open a console terminal

Run them from a real terminal on the machine.


A small library of Pure Data abstractions is provided in the data/pd folder for OSC message parsing when using the Pd 0.46+ oscparse object. This library set is also installed to share/doc/joyosc/pd/joyosc.


A Premake4 script and IDE files can be found in the prj folder. Premake4 can generate IDE files from a given lua script. Download Premake4 from

Make sure the external libraries are built by calling make in the lib directory.

You can enable a debug build using:

./configure --enable-debug

I develop using an IDE, then update the autotools files when the sources are finished. I run make distcheck to make sure the distributable package can be built successfully.


  • add support for SDL2 haptic/force feedback interfaces, to be triggerable over OSC
  • add built in osc -> MIDI and other mapping capabilities (ala junXion or Osculator)


Note: joyosc was originally named "rc-unitd" (the robotcowboy unit daemon) in versions prior to 0.4.0

How to connect PS3 controller on macOS, PC, etc

Use Osculator + HID extension for Wiimote support on macOS


(maintained) hid device to osc event daemon used in the robotcowboy project







No packages published