Git Product home page Git Product logo

midijoystick's Introduction

MidiJoystick (VERSION 1.1.0)

WARNING: THIS IS NOT COMPATIBLE WITH GAMBIT 4.2.X But feel free to hack away anyways.

MidiJoystick is a client for the Jack Audio Connection Kit on Linux (and maybe other unixlikes) which lets you use your joystick as a midicontroller.

All inputs are freely configurable and multiple MIDI Messages can be bound to the same input.

See supplied configuration file for an example configuration for a XBOX 360 Controller.

MidiJoystick uses a configuration file to read your input mapping, syntax is described further down. You’ll need to know the index of each of your inputs (axes and buttons) which you can test with the program jstest.

On start ‘midijoystick’ will parse your configuration file, telling you about problematic lines.

If not supplied as commandline arguments, Midijoystick will default to following files:

input filepath
joystick/dev/input/js0
configuration./input.conf

If you need help on MIDI see the included MIDI Compendium.

Commandline Arguments

flagcommentdefault
-jpath to joystick/dev/input/js0
-cpath to configuration file./input.conf
-dinteger denoting deadzone radius for axesno deadzone
-vif given prints midi messages-
-hprints usage information

You may want to use ‘-d 3000’ or a similar value, when your axes don’t emit a zero value when released.

Configuration Syntax

A Configuration entry:

((t i) ((CMD [CH]) [PARAM*])+)

(brackets denote optional elements; a ‘+’ denotes one or more of the preceeding list/element; a * denotes zero or more of the preceedint list/elemnt;)

In the configuration you can use numbers of the base 10 or of the base 16. As MIDI is a byte oriented protocol it’s easier to use base 16 (hexadecimal) numbers.

NOTE: In the configuration file you have to write hexadecimal numbers with the prefix '#x' instead of the common prefix '0x'. So instead of writing '0xE0' you would write '#xE0'.

A entry is consists of two parts on the toplevel:

  1. One Inputidentifier
  2. One or more Commandbindings

Inputidentifier:

The Inputidentifier tells the program which joystick inputs should emit a MIDI message.

(t i)

A Inputidentifier consists of a token t and an index i. The token t specifies if the input is a axis or a button, the index i specifies the index of the axis or button. Allowed values for token t are ‘a’ for axis and ‘b’ for button. Allowed values for index i are any positive integers.

To determine the index of any axis or button please use the unix tool ‘jstest’.

Commandbindings:

Commandbindings tell the program which MIDI messages should be emitted when a input (specified by the Inputidentifier) is recognized.

((CMD [CH]) [PARAM+])

A Commandbinding consists of two parts:

  1. The MIDI Command CMD and a MIDI Channel CH. The later is ignored (therefor optional) if the MIDI Command is a SysEx (CMD := 0xF0) message. Channels are counted from zero.
  2. A list of zero or more integers PARAM, which are supplied as aditional parameters for the MIDI Command CMD.

Allowed values for CMD are contained in this list: [0x80, 0x90, 0xA0, 0xB0, 0xC0, 0xD0, 0xE0, 0xF0]

Allowed values for PARAM are in the range of 0x00 - 0x7F.

So a Commandbinding can be viewed as a template, it represents quite closely the real MIDI message on the byte level. It’s a template cause dependeing, on the specified CMD, the joystick input is appended to or insert into the byte stream.

Bind multiple Commandbindings to one Inputidentifier

To bind multiple Commandbindings to one Inputidentifier you just add more Commandbindings to your entry.

See this example how you can bind two different messages to one axis:

((a 1) ;; bind to axis #1
 ((#xB0 #x02) #x01) ;; Continous Controller #1 on Channel 3
 ((#xB0 #x01) #x01)) ;; Continous Controller #1 on Channel 2

Here we bind the input from axis number 1 to two Continous Controller with the ID 1. One for Channel 3 and one for Channel 2.

((b 7) ;; bind to button #7
 ((#xF0) #x7F #x7F #x06 #x02 #xF7) ;; Send SysEx to send MMC Start
 ((#xF0) #x7F #x7F #x06 #x01 #xF7)) ;; Send SysEx to send MMC Stop

Here we bind two SysEx messages (so called ‘MIDI Real-Time Universal System Exclusive Messages’; more in the Midicompendium) to the button number 7.

There is one difference how buttons and axis act when multiple Commands are bound to one input:

Axis: All Commands are send when a input is recogniced. They are issued in the order in which they are specified. This should be semi-simultan.

Buttons: When a button is pressed the first MIDI Command is issued, on the second press the second Command is issued, and so on. If the last Command in the list is send, the next press will issue the first Command again. A endless cycle…

In the example above that would mean:

first press: Send SysEx to send MMC Start is issued

second press: Send SysEx to send MMC Stop is issued

third press: Send SysEx to send MMC Start is issued

Buttons:

Since version 1.1.0 you can specify a value which gets emitted when a button is pressed. This means on all supported MIDI messages (CC, Note-On/Off, Pitch Bend) a button press can emit another value then 0x7F. This change allows to play one defined note, using CCs which act more like a switch (see Midicompendium) or applying a defined Pitch Bend value.

Take note that no bound checking is done. The values you supply must be in the range [0x00, 0x7F] ([0x0000, 0x3FFF] for Pitch Bend).

The format for this new configuration feature is:

((t i)
  ((CMD CH) PARAM BUTTON_VALUE))

An example:

((b 5)  ;; bind button 5
 ((#xB0 #x04) #x40 #x7F)    ;; CC 0x40 (Damper/Sustain) on Channel 5 with the value 0x7F (ON)
 ((#xB0 #x04) #x40 #x00))  ;; CC 0x40 (Damper/Sustain) on Channel 5 with the value 0x00 (OFF)

As you can see the rules for buttons as explained above still apply: You have to supply two lines with different `BUTTON_VALUE` to toggle between two states.

If you ommit `BUTTON_VALUE` a value of 0x7F is used. Which means you can write the example above as:

((b 5)  ;; bind button 5
 ((#xB0 #x04) #x40)    ;; CC 0x40 (Damper/Sustain) on Channel 5 with the _implicit_ value 0x7F (ON)
 ((#xB0 #x04) #x40 #x00))  ;; CC 0x40 (Damper/Sustain) on Channel 5 with the value 0x00 (OFF)

Examples:

Here are some examples how a configuration entry can look like:

  1. Channel 3 Pitch Bend on Axis 1
;; Bind axis with index 1 to Pitch-Bend on Channel 3
((a 1) ((#xE0 #x02))
  1. Channel 16 Continous Controller number 1 on axis 3
;; Bind axis with index 3 to Continous Controller number 1 on channel 16
((a 3) ((#xB0 #xF0) #x01))
  1. Send a MIDI Real-Time Universal System Exclusive Message when button 1 is pressed
((b 1) ;; Bind to input 'Button with index 1'
  ((#xF0) ;; denote that this is a System Exclusive Message
     #x7F #x7F #x06 #02 #xF7)) ;; the SysEx Message which will be send (here: MIDI Machine Control to start playing)

Aditional Notes:

A configuration entry can be split to multiple lines:

((t i) 
       ((CMD CH) 
         PARAM))

Comments are denoted with ‘;’. Comments can appear between entries on their own or last in a line

((t i) 
; A nice comment 
       ((CMD ;; another comment 
            CH) PARAM))

Remember to enclose all your entries with parantheses:

( ;; <- this paranthesis is needed
  ((t i) ((CMD CH) PARAM))
  ((t i) ((CMD) PARAM))
  ((t i) ((CMD CH)))
) ;; <- this one too

see supplied configuration file for more examples of a complete config file

Overview Table

tokennotevalues
tspecifies input type: a for axis; b buttons[ab]
ispecifies index of the input type[0-9]+
CMDMidi command identifier as two digit hex number (see table below)#x[89a-fA-F]0
CHMidi channel for the command as a two digit hex number (0x00 - > 0x0F) so 0x00 is Channel 1#x0[0-9a-fA-F]
PARAMoptional parameter as a two digit hex number (0x00 -> 0x7F), no default if omitted command; Meaning of PARAM is special to CMD -> see table below[0-7][0-9a-fA-F]
;indicates a Comment

Implemented Midi Commands

To use Note-On/Off messages you should follow the following example configuration:

;; bind note-off and note-on to axis 1 for channel 1
((a 1) 
 (#x80 #x00) ; first send note-off, the value for note off is the last read value from axis 1
 (#x90 #x00)) ; then send note-on, the value for note on is the current read value from axis 2

So on two inputs on the same axis following MIDI Messages are generated:

# First Input: we start off with a 'last-value' of 0x00 which translates to MIDI note 64
0: 80 40 7f note off (channel  0): pitch  64, velocity 127
1: 90 40 7f note on  (channel  0): pitch  64, velocity 127

# Second Input: Last played note gets muted (compare msg 2 vs 1), new note sounds until next input
2: 80 40 7f note off (channel  0): pitch  64, velocity 127
3: 90 45 7f note on  (channel  0): pitch  69, velocity 127

Any other use of Note-on/off is not tested, but you are free to experiment. See the example configuration, where a button is bound to CC 0x7B which mutes all sounding notes of a Channel.

CommandMeaningjoystick read valueconfigcomment
0x80Note-Off--note value is the value of the event bevore
0x90Note-OnNote value
0xB0Continous Controller (CC)controller valueCC IDsee table of CC IDs in the MIDI Compendium
0xC0Patch Changenot usedpatch number
0xD0Channel Pressurepressure amountnot used
0xE0Pitch Bendbend amountnot used
0xF0SysEx Messagesnot usedthe SysEx Message which should be send

For further information see the included MIDI Compendium

TODOs

  • TODO Support System Realtime Messages (Start, Stop, Reset )
  • TODO allow to configure midi value emitted when button is pressed (instead of hardcoded 0x7F) fixed in 1.1.0
  • TODO maybe find a way to configure buttons as mod keys for axis events (e.g. axis mapped to Pitch Bend, hold a button and axis now emits CC )

How to build

$ make all

will build:

  • midijoystick: main program

Dependencies:

Tested Version numbers taken from the Arch Linux Packages.

Additional Notes

The joystick api maps axes values to a int16_t (positive and negative) range. While midi data bytes range from 0x00 to 0x7F. So we’re mapping the axis values to uint16_t and then to the midi data range (0x00 - 0x7F), thus the real axis value of 0x00 is a midi value of 0x40. A real axis value of 0x00 occures when the axis controler is at center position.

Source Code Map

file(s)comments
midijoystick.scmmain program
glue.{c,h}glue.c gets included into midijoystick.scm it holds some helper functions
joystick.{c,h}for talking with the joystick device file
midijack.{c,h}for talking with jackaudio server

License

MIT

midijoystick's People

Contributors

osune avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

midijoystick's Issues

Compilation on Linux failed: unknown type name ‘sigset_t’

Compilation finished.
gcc  -O1 -g -O2 -ffile-prefix-map=/build/gambc-YYEQDb/gambc-4.9.3=. -flto=auto -ffat-lto-objects -fstack-protector-strong -Wformat -Werror=format-security   -Wno-unused -Wno-write-strings -Wdisabled-optimization -fwrapv -fno-strict-aliasing -fno-trapping-math -fno-math-errno -fschedule-insns2 -fomit-frame-pointer -fPIC -fno-common -mpc64   -D___SINGLE_HOST  -I"/usr/include" -c -o "midijoystick.o" -std=c11 -Wall -g -O0 midijoystick.c
In file included from midijoystick.c:452:
/usr/include/gambit.h:8493:5: error: unknown type name ‘sigset_t’
 8493 |     ___sigset_type sigset[3]; /* increase if other interrupts are added */
      |     ^~~~~~~~~~~~~~
*** ERROR IN ##main -- target compilation or link failed while compiling "/home/guru/src/MidiJoystick/midijoystick.c"
make: *** [Makefile:5: midijoystick] Error 70

Ubuntu 22.04

reproducible.

Am I missing some #defines?

Introduce "keywords" (read: functions) in input.conf file

Enhance the configuration syntax with 'keywords' which are scheme functions.

Here two objectives are important:

  1. Readability / Comprehensibility / Edit-ability should be improved at least preserved
  2. Code for parsing configuration should shrink / get less complex

Add support for OSC

(this comes from reddit user 'nosepol' in this thread

"For years I've been using SuperCollider's GeneralHID class to generate midi out of various stuff, and I'd love to have something less overkill. Oh and while you're at it add possibility for OSC output :P "

Can not compile (Gambit 4.2.x)

$ make all
gsc-script -debug -warnings -verbose -cc-options "-std=c11 -Wall -g -O0"  -ld-options -ljack  -exe -o midijoystick midijack.c joystick.c midijoystick.scm
*** WARNING -- Unknown or improperly placed option: "debug"
*** WARNING -- Unknown or improperly placed option: "warnings"
*** WARNING -- Unknown or improperly placed option: "verbose"
*** WARNING -- Unknown or improperly placed option: "cc-options"
*** WARNING -- Unknown or improperly placed option: "std=c11 -Wall -g -O0"
*** WARNING -- Unknown or improperly placed option: "ld-options"
*** WARNING -- Unknown or improperly placed option: "ljack"
*** WARNING -- Unknown or improperly placed option: "exe"
*** WARNING -- Unknown or improperly placed option: "o"
*** ERROR IN "midijoystick.scm"@1.1 -- Interpreter does not support ##c-declare

Ubuntu 16.04
Gambit v4.2.8

Suggestions?

Move from 'legacy' joystick api to 'new' evdev api

MidiJoystick currently uses the old joystick api, which restricts its uses to only joystick like input devices. By moving to the 'new' evdev api MidiJoystick could support Joysticks and any HID inpu device.

On/Off CC Messages (e.g. 0x40) don't work with buttons

Hi,
I'm interesting by your projet. I'm newbie on GitHub, I cannot find how contact you but by this issue :-(

I really want to use button to activate some effects in guitarix. I never learn Scheme, so I try some test and I can detect Release button but cannot catch them in your function. In fact, button send 64 (0x40) to MIDI, no 127 (0x7F) like you said in your README.

I deleted all, and starting with a C program (Haaaaaa, so easy).
Some hours after testing, I have a little program. This program is useful for buttons and axes. He is very ugly, specially about configuration.
If you are interresting by, I can send you my C program and .scm modify to print release event.

Bye

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.