On Fri, Jul 13, 2012 at 08:50:18AM +0200, Atte André Jensen wrote:
On 2012-07-12 23:02, Fons Adriaensen wrote:
That is because the LP sends MIDI using running
status, and there
is no way to reset it (i.e. force a status byte on the next message),
except a power cycle. The top row uses controller events while the
rest uses key up/down. After re-opening the device the driver code
needs a status byte, and usually using the top row will provide one
(assuming the last event in the previous session was a key one).
Ok, thanks, that sounds like a sane explanation. However it
surprises me a bit (maybe it shouldn't), since I read this in the
"Launchpad programmers reference" (pdf released by novation
http://d19ulaff0trnck.cloudfront.net/cdn/farfuture/zJMvGWWVN-T4_9ocxl0S-99M…):
"Hence a Launchpad MIDI message is always three bytes long. (For
good reasons, the driver does
not support running status.)"
That seems to apply only to messages sent *to* the LP: it wants
a status byte in each one. But doesn't do the same in the LP->
app direction.
I also tried the reset command, but it too does not clear the
running status. AFAIK only a power cycle will.
Is there anyway to get a status byte to the
driver/launchpad from my
code, so I don't have to rely on presses after opening a new batch
of chuck code? Could I for instance emulate "unplug" and "plug in"
the launchpad or it's driver from code?
You'd have to switch the power on the USB socket... It's not the
USB drivers failing to reset, but the LP firware.
I've been using the launcpad a bit with renoise,
esp the duplex
tool, and somehow the launchpad works perfectly normal there, so
something tells me there is a way.
It is possible if you have LP-specific driver code. Only two keys
are ambiguous without a status byte: both have 0x68 as the first
data byte (the second is press/release, encoded the same way in
all cases). For all others you can infer the status byte form the
data.
When I got my LP I wrote a python extension and class that uses
it directly via libusb, without going via ALSA, and it solves
the problem, except if the first event has data byte 0x68.
This is part of the code, with _cstat being the current status,
initialised to 0, and p is an array of n received bytes:
i = 0;
while (i < n)
{
t = p [i++];
if (t & 0x80) // First byte is status ?
{
_cstat = t & 0xF0;
t = p [i++];
}
v = p [i++] ? 1 : 0;
// If we don't have status, find it from the data.
if (! _cstat && (t != 0x68))
{
_cstat = ((t & 0x0F) > 8) ? 0xB0 : 0x90;
}
// Keys are encoded with x,y = 0...8.
// x == 8 means the right column.
// y == 8 means the top row.
if (_cstat == 0x90) rx_action (v, t & 0x0F, t >> 4);
if (_cstat == 0xB0) rx_action (v, t & 0x07, 8);
}.
Ciao,
--
FA
A world of exhaustive, reliable metadata would be an utopia.
It's also a pipe-dream, founded on self-delusion, nerd hubris
and hysterically inflated market opportunities. (Cory Doctorow)