On 12/04/2015 at 9:17 PM, TK. said:
Hi,
it isn’t impossible, but difficult to implement.
Looking at my backlog for various projects, it could take several months until I will find the time to implement such a challenging feature.
So: better don’t wait for this and search for alternative solutions.
Best Regards, Thorsten.
Hey
Long time I don’t look at this, but I’m somehow forced to make the moving fader system natively compatible with protool (HUI only…)
I ended today with modification at mbng_event.c alowing NRPN event to handle the dual CC (not in NRPN format)
and it work both way, sending end receiving fader data to/from DAW
As I’m far from good programmer and C expert
here is what I do, input and comment welcome about method I use to achieve this, in case it was completely bad strategy.
to send:
///////////////////////////////////////////////////////////////////////////// //! Sends a NRPN event. Skips address bytes if they already have been sent! ///////////////////////////////////////////////////////////////////////////// s32 MBNG\_EVENT\_SendOptimizedNRPN(mios32\_midi\_port\_t port, mios32\_midi\_chn\_t chn, u16 nrpn\_address, u16 nrpn\_value, u8 msb\_only) { u8 nrpn\_address\_msb = (nrpn\_address \>\> 7) & 0x7f; u8 nrpn\_address\_lsb = (nrpn\_address \>\> 0) & 0x7f; u8 nrpn\_value\_msb = (nrpn\_value \>\> 7) & 0x7f; u8 nrpn\_value\_lsb = (nrpn\_value \>\> 0) & 0x7f; // create MIDI package mios32\_midi\_package\_t p; p.ALL = 0; p.type = CC; p.event = CC; p.chn = chn; // quick&dirty #if MBNG\_EVENT\_NRPN\_SEND\_PORTS\_MASK != 0x00f0 # error "Please adapt MBNG\_EVENT\_SendOptimizedNRPN!" #endif #if MBNG\_EVENT\_NRPN\_SEND\_PORTS\_OFFSET != 4 # error "Please adapt MBNG\_EVENT\_SendOptimizedNRPN!" #endif // NRPN special handling for HUI fader data // FADER 1 if( nrpn\_address == 0 ) { p.cc\_number = 0x00; // Data MSB p.value = nrpn\_value\_msb; MIOS32\_MIDI\_SendPackage(port, p); p.cc\_number = 0x20; // Data LSB p.value = nrpn\_value\_lsb; MIOS32\_MIDI\_SendPackage(port, p); } // FADER 2 if( nrpn\_address == 1 ) { p.cc\_number = 0x01; // Data MSB p.value = nrpn\_value\_msb; MIOS32\_MIDI\_SendPackage(port, p); p.cc\_number = 0x21; // Data LSB p.value = nrpn\_value\_lsb; MIOS32\_MIDI\_SendPackage(port, p); } // FADER 3 if( nrpn\_address == 2 ) { p.cc\_number = 0x02; // Data MSB p.value = nrpn\_value\_msb; MIOS32\_MIDI\_SendPackage(port, p); p.cc\_number = 0x22; // Data LSB p.value = nrpn\_value\_lsb; MIOS32\_MIDI\_SendPackage(port, p); } // FADER 4 if( nrpn\_address == 3 ) { p.cc\_number = 0x03; // Data MSB p.value = nrpn\_value\_msb; MIOS32\_MIDI\_SendPackage(port, p); p.cc\_number = 0x23; // Data LSB p.value = nrpn\_value\_lsb; MIOS32\_MIDI\_SendPackage(port, p); } // FADER 5 if( nrpn\_address == 4 ) { p.cc\_number = 0x04; // Data MSB p.value = nrpn\_value\_msb; MIOS32\_MIDI\_SendPackage(port, p); p.cc\_number = 0x24; // Data LSB p.value = nrpn\_value\_lsb; MIOS32\_MIDI\_SendPackage(port, p); } // FADER 6 if( nrpn\_address == 5 ) { p.cc\_number = 0x05; // Data MSB p.value = nrpn\_value\_msb; MIOS32\_MIDI\_SendPackage(port, p); p.cc\_number = 0x25; // Data LSB p.value = nrpn\_value\_lsb; MIOS32\_MIDI\_SendPackage(port, p); } // FADER 7 if( nrpn\_address == 6 ) { p.cc\_number = 0x06; // Data MSB p.value = nrpn\_value\_msb; MIOS32\_MIDI\_SendPackage(port, p); p.cc\_number = 0x26; // Data LSB p.value = nrpn\_value\_lsb; MIOS32\_MIDI\_SendPackage(port, p); } // FADER 8 if( nrpn\_address == 7 ) { p.cc\_number = 0x07; // Data MSB p.value = nrpn\_value\_msb; MIOS32\_MIDI\_SendPackage(port, p); p.cc\_number = 0x27; // Data LSB p.value = nrpn\_value\_lsb; MIOS32\_MIDI\_SendPackage(port, p); } return 0; // no error }
to receive:
// track NRPN event if( port\_mask & MBNG\_EVENT\_NRPN\_RECEIVE\_PORTS\_MASK ) { int port\_ix = (port\_class | (port & 3)) - MBNG\_EVENT\_NRPN\_RECEIVE\_PORTS\_OFFSET; if( port\_ix \>= 0 && port\_ix \< MBNG\_EVENT\_NRPN\_RECEIVE\_PORTS ) { // NRPN special handling for HUI fader data switch( midi\_package.cc\_number ) { case 0x00: { // Address MSB FADER 1 nrpn\_received\_value[port\_ix][midi\_package.chn] &= ~0x3f80; nrpn\_received\_value[port\_ix][midi\_package.chn] |= ((midi\_package.value \<\< 7) & 0x3f80); nrpn\_value = nrpn\_received\_value[port\_ix][midi\_package.chn]; // pass to parser nrpn\_address = 0; nrpn\_msb\_only = 1; // for the MsbOnly format #if 0 // MEMO: it's better to update only when LSB has been received if( port != midi\_learn\_nrpn\_port || midi\_package.chn != (midi\_learn\_nrpn\_chn-1) ) { midi\_learn\_nrpn\_port = port; midi\_learn\_nrpn\_chn = midi\_package.chn + 1; midi\_learn\_nrpn\_valid = 0; } else { // only if valid address has been parsed midi\_learn\_nrpn\_valid |= 0x04; } #endif } break; case 0x20: { // Address LSB nrpn\_received\_value[port\_ix][midi\_package.chn] &= ~0x007f; nrpn\_received\_value[port\_ix][midi\_package.chn] |= (midi\_package.value & 0x007f); nrpn\_value = nrpn\_received\_value[port\_ix][midi\_package.chn]; // pass to parser nrpn\_address = 0; if( port != midi\_learn\_nrpn\_port || midi\_package.chn != (midi\_learn\_nrpn\_chn-1) ) { midi\_learn\_nrpn\_port = port; midi\_learn\_nrpn\_chn = midi\_package.chn + 1; midi\_learn\_nrpn\_valid = 0; } else { // only if valid address has been parsed // use same valid flag like Data MSB (complete NRPN is valid with 0x07) midi\_learn\_nrpn\_valid |= 0x04; } } break; case 0x01: { // Address MSB FADER 2 nrpn\_received\_value[port\_ix][midi\_package.chn] &= ~0x3f80; nrpn\_received\_value[port\_ix][midi\_package.chn] |= ((midi\_package.value \<\< 7) & 0x3f80); nrpn\_value = nrpn\_received\_value[port\_ix][midi\_package.chn]; // pass to parser nrpn\_address = 1; nrpn\_msb\_only = 1; // for the MsbOnly format #if 0 // MEMO: it's better to update only when LSB has been received if( port != midi\_learn\_nrpn\_port || midi\_package.chn != (midi\_learn\_nrpn\_chn-1) ) { midi\_learn\_nrpn\_port = port; midi\_learn\_nrpn\_chn = midi\_package.chn + 1; midi\_learn\_nrpn\_valid = 0; } else { // only if valid address has been parsed midi\_learn\_nrpn\_valid |= 0x04; } #endif } break; case 0x21: { // Address LSB nrpn\_received\_value[port\_ix][midi\_package.chn] &= ~0x007f; nrpn\_received\_value[port\_ix][midi\_package.chn] |= (midi\_package.value & 0x007f); nrpn\_value = nrpn\_received\_value[port\_ix][midi\_package.chn]; // pass to parser nrpn\_address = 1; if( port != midi\_learn\_nrpn\_port || midi\_package.chn != (midi\_learn\_nrpn\_chn-1) ) { midi\_learn\_nrpn\_port = port; midi\_learn\_nrpn\_chn = midi\_package.chn + 1; midi\_learn\_nrpn\_valid = 0; } else { // only if valid address has been parsed // use same valid flag like Data MSB (complete NRPN is valid with 0x07) midi\_learn\_nrpn\_valid |= 0x04; } } break; case 0x02: { // Address MSB FADER 3 nrpn\_received\_value[port\_ix][midi\_package.chn] &= ~0x3f80; nrpn\_received\_value[port\_ix][midi\_package.chn] |= ((midi\_package.value \<\< 7) & 0x3f80); nrpn\_value = nrpn\_received\_value[port\_ix][midi\_package.chn]; // pass to parser nrpn\_address = 2; nrpn\_msb\_only = 1; // for the MsbOnly format #if 0 // MEMO: it's better to update only when LSB has been received if( port != midi\_learn\_nrpn\_port || midi\_package.chn != (midi\_learn\_nrpn\_chn-1) ) { midi\_learn\_nrpn\_port = port; midi\_learn\_nrpn\_chn = midi\_package.chn + 1; midi\_learn\_nrpn\_valid = 0; } else { // only if valid address has been parsed midi\_learn\_nrpn\_valid |= 0x04; } #endif } break; case 0x22: { // Address LSB nrpn\_received\_value[port\_ix][midi\_package.chn] &= ~0x007f; nrpn\_received\_value[port\_ix][midi\_package.chn] |= (midi\_package.value & 0x007f); nrpn\_value = nrpn\_received\_value[port\_ix][midi\_package.chn]; // pass to parser nrpn\_address = 2; if( port != midi\_learn\_nrpn\_port || midi\_package.chn != (midi\_learn\_nrpn\_chn-1) ) { midi\_learn\_nrpn\_port = port; midi\_learn\_nrpn\_chn = midi\_package.chn + 1; midi\_learn\_nrpn\_valid = 0; } else { // only if valid address has been parsed // use same valid flag like Data MSB (complete NRPN is valid with 0x07) midi\_learn\_nrpn\_valid |= 0x04; } } break; case 0x03: { // Address MSB FADER 4 nrpn\_received\_value[port\_ix][midi\_package.chn] &= ~0x3f80; nrpn\_received\_value[port\_ix][midi\_package.chn] |= ((midi\_package.value \<\< 7) & 0x3f80); nrpn\_value = nrpn\_received\_value[port\_ix][midi\_package.chn]; // pass to parser nrpn\_address = 3; nrpn\_msb\_only = 1; // for the MsbOnly format #if 0 // MEMO: it's better to update only when LSB has been received if( port != midi\_learn\_nrpn\_port || midi\_package.chn != (midi\_learn\_nrpn\_chn-1) ) { midi\_learn\_nrpn\_port = port; midi\_learn\_nrpn\_chn = midi\_package.chn + 1; midi\_learn\_nrpn\_valid = 0; } else { // only if valid address has been parsed midi\_learn\_nrpn\_valid |= 0x04; } #endif } break; case 0x23: { // Address LSB nrpn\_received\_value[port\_ix][midi\_package.chn] &= ~0x007f; nrpn\_received\_value[port\_ix][midi\_package.chn] |= (midi\_package.value & 0x007f); nrpn\_value = nrpn\_received\_value[port\_ix][midi\_package.chn]; // pass to parser nrpn\_address = 3; if( port != midi\_learn\_nrpn\_port || midi\_package.chn != (midi\_learn\_nrpn\_chn-1) ) { midi\_learn\_nrpn\_port = port; midi\_learn\_nrpn\_chn = midi\_package.chn + 1; midi\_learn\_nrpn\_valid = 0; } else { // only if valid address has been parsed // use same valid flag like Data MSB (complete NRPN is valid with 0x07) midi\_learn\_nrpn\_valid |= 0x04; } } break; case 0x04: { // Address MSB FADER 5 nrpn\_received\_value[port\_ix][midi\_package.chn] &= ~0x3f80; nrpn\_received\_value[port\_ix][midi\_package.chn] |= ((midi\_package.value \<\< 7) & 0x3f80); nrpn\_value = nrpn\_received\_value[port\_ix][midi\_package.chn]; // pass to parser nrpn\_address = 4; nrpn\_msb\_only = 1; // for the MsbOnly format #if 0 // MEMO: it's better to update only when LSB has been received if( port != midi\_learn\_nrpn\_port || midi\_package.chn != (midi\_learn\_nrpn\_chn-1) ) { midi\_learn\_nrpn\_port = port; midi\_learn\_nrpn\_chn = midi\_package.chn + 1; midi\_learn\_nrpn\_valid = 0; } else { // only if valid address has been parsed midi\_learn\_nrpn\_valid |= 0x04; } #endif } break; case 0x24: { // Address LSB nrpn\_received\_value[port\_ix][midi\_package.chn] &= ~0x007f; nrpn\_received\_value[port\_ix][midi\_package.chn] |= (midi\_package.value & 0x007f); nrpn\_value = nrpn\_received\_value[port\_ix][midi\_package.chn]; // pass to parser nrpn\_address = 4; if( port != midi\_learn\_nrpn\_port || midi\_package.chn != (midi\_learn\_nrpn\_chn-1) ) { midi\_learn\_nrpn\_port = port; midi\_learn\_nrpn\_chn = midi\_package.chn + 1; midi\_learn\_nrpn\_valid = 0; } else { // only if valid address has been parsed // use same valid flag like Data MSB (complete NRPN is valid with 0x07) midi\_learn\_nrpn\_valid |= 0x04; } } break; case 0x05: { // Address MSB FADER 6 nrpn\_received\_value[port\_ix][midi\_package.chn] &= ~0x3f80; nrpn\_received\_value[port\_ix][midi\_package.chn] |= ((midi\_package.value \<\< 7) & 0x3f80); nrpn\_value = nrpn\_received\_value[port\_ix][midi\_package.chn]; // pass to parser nrpn\_address = 5; nrpn\_msb\_only = 1; // for the MsbOnly format #if 0 // MEMO: it's better to update only when LSB has been received if( port != midi\_learn\_nrpn\_port || midi\_package.chn != (midi\_learn\_nrpn\_chn-1) ) { midi\_learn\_nrpn\_port = port; midi\_learn\_nrpn\_chn = midi\_package.chn + 1; midi\_learn\_nrpn\_valid = 0; } else { // only if valid address has been parsed midi\_learn\_nrpn\_valid |= 0x04; } #endif } break; case 0x25: { // Address LSB nrpn\_received\_value[port\_ix][midi\_package.chn] &= ~0x007f; nrpn\_received\_value[port\_ix][midi\_package.chn] |= (midi\_package.value & 0x007f); nrpn\_value = nrpn\_received\_value[port\_ix][midi\_package.chn]; // pass to parser nrpn\_address = 5; if( port != midi\_learn\_nrpn\_port || midi\_package.chn != (midi\_learn\_nrpn\_chn-1) ) { midi\_learn\_nrpn\_port = port; midi\_learn\_nrpn\_chn = midi\_package.chn + 1; midi\_learn\_nrpn\_valid = 0; } else { // only if valid address has been parsed // use same valid flag like Data MSB (complete NRPN is valid with 0x07) midi\_learn\_nrpn\_valid |= 0x04; } } break; case 0x06: { // Address MSB FADER 7 nrpn\_received\_value[port\_ix][midi\_package.chn] &= ~0x3f80; nrpn\_received\_value[port\_ix][midi\_package.chn] |= ((midi\_package.value \<\< 7) & 0x3f80); nrpn\_value = nrpn\_received\_value[port\_ix][midi\_package.chn]; // pass to parser nrpn\_address = 6; nrpn\_msb\_only = 1; // for the MsbOnly format #if 0 // MEMO: it's better to update only when LSB has been received if( port != midi\_learn\_nrpn\_port || midi\_package.chn != (midi\_learn\_nrpn\_chn-1) ) { midi\_learn\_nrpn\_port = port; midi\_learn\_nrpn\_chn = midi\_package.chn + 1; midi\_learn\_nrpn\_valid = 0; } else { // only if valid address has been parsed midi\_learn\_nrpn\_valid |= 0x04; } #endif } break; case 0x26: { // Address LSB nrpn\_received\_value[port\_ix][midi\_package.chn] &= ~0x007f; nrpn\_received\_value[port\_ix][midi\_package.chn] |= (midi\_package.value & 0x007f); nrpn\_value = nrpn\_received\_value[port\_ix][midi\_package.chn]; // pass to parser nrpn\_address = 6; if( port != midi\_learn\_nrpn\_port || midi\_package.chn != (midi\_learn\_nrpn\_chn-1) ) { midi\_learn\_nrpn\_port = port; midi\_learn\_nrpn\_chn = midi\_package.chn + 1; midi\_learn\_nrpn\_valid = 0; } else { // only if valid address has been parsed // use same valid flag like Data MSB (complete NRPN is valid with 0x07) midi\_learn\_nrpn\_valid |= 0x04; } } break; case 0x07: { // Address MSB FADER 8 nrpn\_received\_value[port\_ix][midi\_package.chn] &= ~0x3f80; nrpn\_received\_value[port\_ix][midi\_package.chn] |= ((midi\_package.value \<\< 7) & 0x3f80); nrpn\_value = nrpn\_received\_value[port\_ix][midi\_package.chn]; // pass to parser nrpn\_address = 7; nrpn\_msb\_only = 1; // for the MsbOnly format #if 0 // MEMO: it's better to update only when LSB has been received if( port != midi\_learn\_nrpn\_port || midi\_package.chn != (midi\_learn\_nrpn\_chn-1) ) { midi\_learn\_nrpn\_port = port; midi\_learn\_nrpn\_chn = midi\_package.chn + 1; midi\_learn\_nrpn\_valid = 0; } else { // only if valid address has been parsed midi\_learn\_nrpn\_valid |= 0x04; } #endif } break; case 0x27: { // Address LSB nrpn\_received\_value[port\_ix][midi\_package.chn] &= ~0x007f; nrpn\_received\_value[port\_ix][midi\_package.chn] |= (midi\_package.value & 0x007f); nrpn\_value = nrpn\_received\_value[port\_ix][midi\_package.chn]; // pass to parser nrpn\_address = 7; if( port != midi\_learn\_nrpn\_port || midi\_package.chn != (midi\_learn\_nrpn\_chn-1) ) { midi\_learn\_nrpn\_port = port; midi\_learn\_nrpn\_chn = midi\_package.chn + 1; midi\_learn\_nrpn\_valid = 0; } else { // only if valid address has been parsed // use same valid flag like Data MSB (complete NRPN is valid with 0x07) midi\_learn\_nrpn\_valid |= 0x04; } } break; } } }
Best
Zam