Tuesday, 14 June 2016

Keyboard Controller working!

Last week I have been working on making the keyboard controller functional, and I have made some good progress. Although the controls are still set in the keyboard event filter (which will be moved to the keyboard controller very soon), the mapping info is not owned by the keyboard event filter anymore. It's now owned by the keyboard controller preset, which stores the key combinations with the actions that it should trigger. As soon as a new preset is loaded, the keyboard event filter is sent a signal and gets updated about the new preset.

Keyboard preset format

The presets the keyboard controller uses are instances of KeyboardControllerPreset, which rely on *.kbd.xml files. These XML files start of with an info block.
<?xml version="1.0" encoding="utf-8"?>

<MixxxKeyboardPreset schemaVersion="1" mixxxVersion="2.0.0+">
  <info>
    <name>Keyboard Default</name>
    <author>Mixxx</author>
    <description>Default keyboard mapping.</description>
    <wiki>mixxx.org/.../appendix.html#appendix-keyboard</wiki>
  </info>
This <infoblock is required, otherwise it won't even get enumerated and thus will not be listed as a legitimate preset. The block's format is basically the same as for each preset of each other controller type. Though some presets also include <forumsand <devices>, I believe that that information doesn't apply for keyboard presets. However, if I'm proven wrong and we do need those, it can be added really easily.

The data where it all goes about is in the <controllerblock, which contains <groupnodes, listing <controlnodes holding information about which key sequence triggers what action.
<controller>
    <group name="[AutoDJ]">
      <control action="shuffle_playlist" keyseq="Shift+F9" />
      <control action="skip_next" keyseq="Shift+F10" />
      <control action="fade_now" keyseq="Shift+F11" />
      <control action="enabled" keyseq="Shift+F12" />
    </group>

    <group name="[Master]">
      <control action="crossfader_up" keyseq="h" />
      <control action="crossfader_down" keyseq="g" />
      <control action="crossfader_up_small" keyseq="Shift+h" />
      <control action="crossfader_down_small" keyseq="Shift+g" />
    </group>

    <group name="[Microphone]">
      <control action="talkover" keyseq="`" />
    </group>

    <group name="[PreviewDeck1]">
      <control action="LoadSelectedAndPlay" keyseq="Alt+Return" />
      <control action="start_stop" keyseq="Return" />
      <control action="back" keyseq="Alt+Left" />
      <control action="fwd" keyseq="" />
    </group>

    <group name="[Channel1]">
      <control action="play" keyseq="d" />
      <control action="cue_set" keyseq="Shift+d" />
      <control action="cue_default" keyseq="f" />
      <control action="cue_gotoandstop" keyseq="Shift+f" />
    </group>

    <!-- etc... -->

Keyboard preset file handler

The XML file is firstly enumerated by PresetInfoEnumerator, which was added the new preset extension. Then, when the user navigates to the keyboard controller in controller preferences and then selects a preset, the XML document is parsed by KeyboardPresetFileHandler. Each action is read and is stored in a multihash, from which the key is the key sequence (ConfigValueKbd), and the values are the bound actions (ConfigKey). The keyboard preset file handler is not only responsible for loading,  but also for saving presets, where it does basically the same task, but then in reverse.

Tuesday, 31 May 2016

Keyboard Controller

Last week I started making the new controller type; KeyboardController. It is already recognized by Mixxx as a legit Controller and listed under Controllers in the Mixxx preferences window. It is not functional yet, though.

KeyboardController

This class subclasses Controller, which it implements all the pure virtual methods from. It's mostly boilerplate code yet. Just enough to make it compile.
Using as EventFilter?
I also started migrating all the methods and fields from KeyboardEventFilter to KeyboardController, with the idea that we could use it as event filter on all the widgets that have currently the KeyboardEventFilter installed on. It turns out though that we couldn't use the KeyboardController as event filter, because it lives in another thread. We could make it thread-save, but that could make Mixxx seem unresponsive.

The new approach is to let the KeyboardEventFilter live, but let it emit signals of what key sequence was pressed instead of setting controls directly. That will be done by the KeyboardController.

KeyboardEnumerator

Every controller type needs a enumerator. This ControllerEnumerator handles discovery and enumeration of controllers. For instance, the MidiController lists all connected MIDI devices, and the HidController does that with HID devices. Since we only support one keyboard, the KeyboardEnumerator returns a list with just one KeyboardController. If we are ever going to support multiple keyboards, this list could be larger.

KeyboardControllerPreset

The KeyboardControllerPreset subclasses ControllerPreset and implements all its pure virtual methods. Just like KeyboardController, this class consists entirely of boilerplate code. It was needed to be able to implement KeyboardController::visit(KeyboardControllerPreset *) : void, which I BTW also implemented in HidController MidiController and BulkController.

Monday, 23 May 2016

Let the coding begin!

Today is the official coding start date for the GSoC. According to the planning I made in the proposal, I will spend the first two weeks making the API for the keyboard controller. As with many other software projects though, the unexpected is the rule rather than the exception. The unforseen, which in this case is supporting the possibility to script the keyboard, is in my opinion too important to postpone. As a consequence to this, the planned two weeks will be stretched a little bit. It would be great to have the keyboard completely migrated to the controller variant before the midterm evaluation, and after the midterm focus on the GUI for the newly created controller. Time will tell if this is realistic or not.

But for this week, I will be making the base for the new controller. That is, making a unfunctional controller that Mixxx can detect.

Wednesday, 11 May 2016

Keymapping GUI for Mixxx

This year I can proudly say that I have been given a chance to contribute to Mixxx, the most advanced free DJ software available. In the first instance I will be developing from May 23th till August 29th, as part of the GSoC 2016 program. Although the main work will be done this summer, I do not rule out further contributions to Mixxx after the GSoC.

Project

The goal of this project is to make it as easy as possible for the users of Mixxx to customize the keyboard mapping to their taste, without having to modify a *.cfg file and having to restart Mixxx, which is currently a real pain. In order to achieve that, the idea is to make a GUI for the keyboard mapping. There are now two main controller types: MIDI and HID. This project is about developing the third one: Keyboard.

PROJECT PROPOSAL


I will be posting further details this weekend!