Giter VIP home page Giter VIP logo

nanokontroller's Introduction

nanoKontroller

A very simplistic Python app to turn the controllers on a Korg nanoKONTROL2 device into user actions on Linux.

Config is controlled via a mapping file that ties inputs on the device to various events.

LED control will not work until the magic control sequence has been sent to the device. Use the Windows control software to switch to this mode.

Features

  • Maps any button to a keypress on the host keyboard via evdev events
  • Maps sliders or knobs to the volume of any audio device, including support for volume limiting or overdrive
  • Maps any button to the mute control for any audio device
  • Maps any button to an external shell command that includes the device key and value

Requires

  • PulseAudio for audio control
  • MIDO for MIDI control
  • evdev for keyboard events

Config

By default config should be in ~/.config/nanoKontroller.ini but this can be overridden by the -c/--config command line argument.

The [audioinputs] section defines audio devices to use as inputs, such as headsets or microphones. Similarly, [audiooutputs] defines audio devices to use as outputs, such as headsets or speakers. To help finding these names there is a --list-devices command line option to print them to the console.

The [keymap] section defines what to do with each button on the device.

Bare options such as KEY_PLAYPAUSE are taken directly from evdev as a fake keypress to generate.

Options prefixed with mute such as mute/mainOutput are used to tie a button to mute an audio device. In this case, the device mainOutput which maps to alsa_output.usb-0d8c_Generic_USB_Audio_Device-00.iec958-stereo

Options prefixed with volume such as volume/mainOutput are used to tie a slider or knob to the volume of an audio device, in this case the device mainOutput. An optional third argument can be supplied like volume/mainOutput/80 to limit the maximum volume to 80% or volume/mainOutput/150 to boost the maximum volume to 150%.

Options prefixed with exec are used to tie a button to executing a shell command. The values {NK_KEY_ID} and {NK_KEY_VALUE} are substituted by the device key ID number and the value (0 for button release, 127 for button press).

Example Config

[audioinputs]
headsetInput = alsa_input.usb-Plantronics_SupraPlus_Wideband_USB-00.analog-mono

[audiooutputs]
headsetOutput = alsa_output.usb-Plantronics_SupraPlus_Wideband_USB-00.analog-stereo
mainOutput = alsa_output.usb-0d8c_Generic_USB_Audio_Device-00.iec958-stereo

[keymap]
PLAY = KEY_PLAYPAUSE
PREV = KEY_PREVIOUSSONG
NEXT = KEY_NEXTSONG
STOP = KEY_STOPCD
RECORD = KEY_RECORD
PARAM1_SLIDER = volume/mainOutput       
PARAM1_MUTE = mute/mainOutput     
PARAM2_SLIDER = volume/headsetOutput/150
PARAM2_MUTE = mute/headsetInput     
PARAM3_SOLO = exec/echo "Key {NK_KEY_ID}, value {NK_KEY_VALUE}"

nanokontroller's People

Contributors

tpneill 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  avatar  avatar  avatar  avatar  avatar

nanokontroller's Issues

Mido port name harcoded can cause crash on mismatch

I had to change the mido.open_xy(port_name) port name from nanoKONTROL2 MIDI 1 to nanoKONTROL2:nanoKONTROL2 nanoKONTROL2 _ CTR 32:0, which i obtained from running mido.get_input_names() in a python3 interpreter.
Otherwise it would crash on startup.
My mind immediatly went to a hacky string operation to dynamically grab the port name on runtime from that get_input_names() output, but i don't know whether that is appropriate.

rtmidi AttributeError: 'module' object has no attribute 'API_UNSPECIFIED'

Traceback (most recent call last):
  File "./nanoKontroller", line 307, in <module>
    inport = mido.open_input('nanoKONTROL2 MIDI 1')
  File "/home/sparr/.local/lib/python2.7/site-packages/mido/backends/backend.py", line 91, in open_input
    return self.module.Input(name, **self._add_api(kwargs))
  File "/home/sparr/.local/lib/python2.7/site-packages/mido/ports.py", line 161, in __init__
    BasePort.__init__(self, name, **kwargs)
  File "/home/sparr/.local/lib/python2.7/site-packages/mido/ports.py", line 86, in __init__
    self._open(**kwargs)
  File "/home/sparr/.local/lib/python2.7/site-packages/mido/backends/rtmidi.py", line 118, in _open
    rtapi = _get_api_id(api)
  File "/home/sparr/.local/lib/python2.7/site-packages/mido/backends/rtmidi.py", line 34, in _get_api_id
    return rtmidi.API_UNSPECIFIED
AttributeError: 'module' object has no attribute 'API_UNSPECIFIED'

not sure where to go from here to collect more info

Enhancement: Application-specific volume controls

I spent a bit of time trying to get application-specific volume controls to work with this library, but ran into a roadblock I'm not sure if I can solve, or is even solvable :)

I augmented the get_audio_devices function to also get the sink_input_list from pulsectl and then pipe it through the rest of the flow, including having it inside the config file.
It actually works too! The only issue is the way sink inputs work, possibly. In my case, I wanted it for Google Chrome specifically. Changing Chrome's volume or muting it instead of muting the entire output device. The problem is that the pulsectl library is returning the media.name property as the name from Pulse, which in the case of Chrome is "Playback". Like I mentioned, this does work successfully, however if there are multiple sink inputs with "Playback" as the media.name then it fails. This includes having more than one tab in Chrome playing audio as they're both sink inputs with the name of "Playback".

There may be an easier way to handle this, and I could share my changes if that helps point someone in the right direction for this, or if it's an interesting enough problem to solve for my use case. It definitely seems like the bigger issue is the way the pulsectl library is handling retrieval of PulseObjects as well as how sink inputs are treated, but I would love to collaborate on this, or discuss more if anyone would like to work on it :)

Thanks!

Details on magic LED control sequence?

Hi Thomas,

I'm considering picking this device up with a Raspberry Pi. I know it's been a while, but could you give more details on this line?

LED control will not work until the magic control sequence has been sent to the device. Use the Windows control software to switch to this mode.

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.