You are here

Latch and Transport Functionality

Hello Rui,

First off, I want to say that Qtractor is an outstanding feat of coding. The workflow fits perfectly with my usage, which is composing jazz backing tracks (piano, bass, drums) that I can practice with. It's so much easier and productive to practice chord voicings and improvisation when there is a constant tempo backing track I need to follow. You sir, are to be commended. Good job!

Now that I've buttered you up :), let me explain a couple of problems I am having. First, I am trying to control Qtractor with a Novation Launchkey MIDI controller, which exclusively sends CC events for the controls. The sliders and pan controls work great, but it appears that the Latch checkbox doesn't actually do anything, specifically with the toggled UI elements (MUTE, SOLO, Monitor, etc.). For example, the button beneath channel 1's fader sends a CC,51,127 event when pressed and CC,51,0 when released. If I map the button to the channel 1 monitor button, the green indicator on the UI dutifully follows those commands, lighting up when the button is pressed and going dark when it is released, regardless of the state of the Latch checkbox setting. I also see these CC events in the debug transcript window, so I know the events are making into the system. This appears to be the same issue as the one raised on ticket #135, which resulted in the Latch functionality being added. I've slogged through the code a bit and can't find where the latched property is used to filter events. I noticed in the changelog for version 0.7.0 that non-continuous MIDI Controllers had the Latch option disabled and wonder if that might be the source of what I am seeing. I'm sure it's probably user error, and any help you could give me would be greatly appreciated.

The second issue is that the 6 transport buttons on the Launchkey also send CC events, while the transport controls in Qtractor are hardwired for MMC. What I'd love to see is the same hooks for the MIDI controller mapping be added to the transport control buttons on the UI. I would think it would (simply? probably not) be a matter of adding the same right-click actions to the transport buttons and re-use the same signal/slot registration code for those buttons. I saw once where you made an offer of "let me help you help me" to someone and would absolutely take you up on that offer, if it still exists.

Sorry for the long missive, but adding these two features would turn Qtractor up to 11.

Bruce

Forums: 
rncbc's picture

three things:
1. thanks (for all your words and praise, really and profoundly appreciated).
2. discrete MIDI controllers have this "Latch" option alright, but that is kinda suited for foot-pedal controllers (momentary/latch); for normal 0(off) and 127(on) toggle controllers you're better stay with that "Hook" thingy ;)
3. MMC is hard-wired alright so it's not an option to turn it something else, sorry. but you have an alternative: custom MIDI controller shortcuts: check them out from menu Help/Shortcuts...

hth.
cheers

bereiden's picture

Hello again Rui,

Wow! You rock! I was able to map my transport controls to the transport menu items and things work. It looks like the mods are permanent (not per session), which is what I want. Funny thing: I was going to suggest that MIDI controls be mappable to any UI element as a general purpose idea, but was afraid to suggest it because I thought it would take too much time to put into the existing code AND YOU DID IT ALREADY!

Now for the bad news: Button releases on the Launchkey still cause the mapped action to turn off. I hacked together a mididings script that swallows CC events with an event value of 0, which results in the action I want:

from mididings       import *
from mididings.event import *

buttonState = [0] * 128;

####################################################################################################
# buttonCtrl:  Toggle outgoing CC event value when the incoming value is non-zero
####################################################################################################
#
# Convert the momentary on/off buttons to mode toggle events when the button press occurs
#

def buttonCtrl (event):
  button = event.ctrl;
  value  = event.value;

  if (value != 0):
    state = buttonState [button] = value if (buttonState [button] == 0) else 0;
    event = CtrlEvent (event.port, event.channel, button, state);
    print (" - Ctrl (%d, %d) => Ctrl (%d, %d)" % (button, value, button, state));
    return event;
  else:
    print (" - Ctrl (%d, %d) => *IGNORED*" % (button, value));
    return None;

####################################################################################################
# midiCtrl:  Route the incoming MIDI messages to the event filter
####################################################################################################

def midiCtrl (event):
  button = event.ctrl;
  if   (button >=  51 and button <=  59):  return (buttonCtrl (event));
  elif (button == 104 or  button == 105):  return (buttonCtrl (event));
  elif (button >= 112 and button <= 117):  return (buttonCtrl (event));
  return event;

run (
  Filter (CTRL) % Process (midiCtrl)
)

But what would be nice is if Qtractor could somehow do this natively. I also looked into the hook function, but I don't think it does what I want. Perhaps I'm being daft.

Hope I'm not being a pain about this.

Bruce

rncbc's picture

a bit late perhaps but now i see what the problem is with that novation launchkeys: it sends MIDI CC when you press and when you release the key or button. i'm afraid this behavior is not well coped for toggle subjects (eg. mute, solo, etc) not matter the "Latch" or "Hook" options are set: the target subject will turn on on press and off immediately when you release the (launch)key.

are you sure it isn't possible to change this behavior on the MIDI controller side? i mean some configuration option or else that you can set appropriately? maybe make it send MIDI note-on and note-off events instead of CC's which is I believe is the most appropriate for the kind of key press (note-on) and release (note-off) operation? if yes, you could set it to note-on only and set the "Latch" mode giving it the way to toggle the subject on each key press.

hth.
byee

bereiden's picture

Unfortunately, the Launchkey cannot be configured. It is relying on the DAW to do all the heavy lifting. I like the unit, but I think this is a definite drawback, and probably would have reconsidered my purchase had I know this.

I'm starting to wonder whether mididings might be the way to go after all. One thing that always greatly enhances software tools is the ability to use scripts for automated control and mididings gives us that ability. The only annoyance at this point is that the script is not synced to the initial state of the software controls, since it assumes everything is off at startup. Thus, if the monitor (or mute, or solo) is selected at startup, the first keypress keeps it in the on state. After that, it is in sync.

How exactly does latch mode work and what is it expecting? Is it:

   keypress   => CC,#,127 => "On"
   keyrelease => (nothing)
   keypress   => CC,#,0   => "Off"

or is it:

   keypress   => CC,#,127 => "On"
   keyrelease => (nothing)
   keypress   => CC,#,127 => "Off"

Note that the Launchkey does this:

   keypress   => CC,#,127 => "On"
   keyrelease => CC,#,0   => (ignore)
   keypress   => CC,#,127 => "Off"
   keyrelease => CC,#,0   => (ignore)
rncbc's picture

let me explain the "Hook" and "Latch" options as follows:
- it is quite normal to the state of a MIDI control value to be out-of-sync to the software control or subject to which it is mapped;
- qtractor also features this so called catch-up behavior by default which means that the control values will only sync when the MIDI control and the subject value do match each other state and value;
- the "Hook" option disables the normal catch-up behavior, so that any MIDI controller value will set the target subject's state and value immediately;
- the "Latch" option is specific to toggling subjects and when turned off, which is then said to be a momentary control, will trigger an unconditional toggle of the target subject whenever its MIDI control value changes in full-swing or toggles in either direction, from on to off or vice-versa.

hth.
cheers

bereiden's picture

Hi again Rui,

Thanks for your responses. I was able to use the Hook option successfully with the sliders/faders on the Launchkey, which is exactly what I wanted out those buggers. I'm still a little unclear about how latch works, but no matter, the mididings script fixes things up quite nicely for me.

As I mentioned before, and after having even *more* time to think about it, I think integrating mididings into Qtractor would be a really nice feature. Here's my proposal: How about adding a "Run mididings script" options to the General tab of the View/Options menu? If a file is specified, and it exists, spawn a mididings process using QProcess. I'm not sure if I would rather have the user connect the mididings output to the Qtractor input via Qjackctl, or have it done automagically (I'm leaning more toward having the user perform the connections). What's nice about this is that mididings can be used a shim between various pieces of hardware and Qtractor and probably saves you some time in the long run: "Hey Rui, I have a SoundBlaster 3000 combination MIDI controller/latte machine and can't get button XYZ to work. Fix it!"

If it's OK with you, I'd like to open a feature request ticket on GitHub just so that we have a record of the request. And again, I'm willing to help with coding.

I hope you and your family had a wonderful Christmas, and I wish you a Happy New Year.

Bruce

Add new comment