-MidiObserver MIDI handling update, now registers custom MIDI port and interacts just with that. Scales to multiple controllers
This commit is contained in:
parent
9fbca5146a
commit
c9bbc9bb48
6 changed files with 109 additions and 40 deletions
|
@ -16,15 +16,17 @@ AkaiAPC::AkaiAPC() :
|
|||
footpedalTrack(0),
|
||||
footpedalScene(0)
|
||||
{
|
||||
_port = port();
|
||||
}
|
||||
|
||||
|
||||
void AkaiAPC::recordArm(int t, bool enabled)
|
||||
{
|
||||
unsigned char data[3];
|
||||
data[0] = 144 + t;
|
||||
data[1] = 48; // record enable LED
|
||||
data[2] = enabled ? 127 : 0;
|
||||
jack->writeApcOutput( &data[0] );
|
||||
jack->midiObserverWriteMIDI( _port, &data[0] );
|
||||
}
|
||||
|
||||
void AkaiAPC::progress(int t, int s, float f)
|
||||
|
@ -34,7 +36,7 @@ void AkaiAPC::progress(int t, int s, float f)
|
|||
data[0] = 176;
|
||||
data[1] = 48; // record enable LED
|
||||
data[2] = 127 * f;
|
||||
jack->writeApcOutput( &data[0] );
|
||||
jack->midiObserverWriteMIDI( _port, &data[0] );
|
||||
*/
|
||||
}
|
||||
|
||||
|
@ -67,7 +69,7 @@ void AkaiAPC::trackSend(int t, int send, float v)
|
|||
data[2] = 127 * v;
|
||||
}
|
||||
|
||||
jack->writeApcOutput( &data[0] );
|
||||
jack->midiObserverWriteMIDI( _port, &data[0] );
|
||||
}
|
||||
|
||||
void AkaiAPC::setSceneState(int t, int clip, GridLogic::State s)
|
||||
|
@ -87,7 +89,7 @@ void AkaiAPC::setSceneState(int t, int clip, GridLogic::State s)
|
|||
case GridLogic::STATE_STOP_QUEUED: data[2] = 6; break;
|
||||
}
|
||||
|
||||
jack->writeApcOutput( &data[0] );
|
||||
jack->midiObserverWriteMIDI( _port, &data[0] );
|
||||
}
|
||||
|
||||
void AkaiAPC::launchScene( int s )
|
||||
|
@ -99,13 +101,13 @@ void AkaiAPC::launchScene( int s )
|
|||
data[0] = 128;
|
||||
data[1] = 82 + i; // scene play
|
||||
data[2] = 0;
|
||||
jack->writeApcOutput( &data[0] );
|
||||
jack->midiObserverWriteMIDI( _port, &data[0] );
|
||||
}
|
||||
|
||||
data[0] = 144;
|
||||
data[1] = 82 + s;
|
||||
data[2] = 127;
|
||||
jack->writeApcOutput( &data[0] );
|
||||
jack->midiObserverWriteMIDI( _port, &data[0] );
|
||||
}
|
||||
|
||||
void AkaiAPC::mute(int t, bool b)
|
||||
|
@ -225,6 +227,10 @@ void AkaiAPC::ccChange( int track, int cc, float value )
|
|||
jack->getLogic()->trackVolume( -1, value );
|
||||
break; }
|
||||
|
||||
/// X-Fader
|
||||
case 15: {
|
||||
jack->getTimeManager()->setBpm( 60 + value * 180 );
|
||||
break; }
|
||||
|
||||
/// Device Control
|
||||
case 16: {
|
||||
|
@ -237,6 +243,7 @@ void AkaiAPC::ccChange( int track, int cc, float value )
|
|||
jack->getLogic()->trackSend( track, SEND_REV, value );
|
||||
break; }
|
||||
|
||||
|
||||
case 64: { // FootSwitch 1
|
||||
if ( value > 0.5 )
|
||||
{
|
||||
|
@ -294,6 +301,6 @@ void AkaiAPC::reset()
|
|||
data[0] = 176 + i;
|
||||
data[1] = 0x19;
|
||||
data[2] = 2;
|
||||
jack->writeApcOutput( &data[0] );
|
||||
jack->midiObserverWriteMIDI( _port, &data[0] );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,6 +30,8 @@ class AkaiAPC : public Controller, public MidiObserver
|
|||
void midi(unsigned char* data);
|
||||
|
||||
private:
|
||||
int _port;
|
||||
|
||||
bool shiftPressed;
|
||||
|
||||
int footpedalTrack;
|
||||
|
|
89
src/jack.cxx
89
src/jack.cxx
|
@ -32,9 +32,6 @@ Jack::Jack() :
|
|||
logic = new Logic();
|
||||
gridLogic = new GridLogic();
|
||||
|
||||
Controller* c = new AkaiAPC();
|
||||
Controller* g = new LupppGUI();
|
||||
|
||||
|
||||
buffers.nframes = jack_get_buffer_size( client );
|
||||
buffers.samplerate = jack_get_sample_rate( client );
|
||||
|
@ -66,18 +63,6 @@ Jack::Jack() :
|
|||
JackPortIsInput,
|
||||
0 );
|
||||
|
||||
apcMidiInput = jack_port_register( client,
|
||||
"apc_in",
|
||||
JACK_DEFAULT_MIDI_TYPE,
|
||||
JackPortIsInput,
|
||||
0 );
|
||||
|
||||
apcMidiOutput = jack_port_register( client,
|
||||
"apc_out",
|
||||
JACK_DEFAULT_MIDI_TYPE,
|
||||
JackPortIsOutput,
|
||||
0 );
|
||||
|
||||
masterVol = 0.77;
|
||||
|
||||
/// prepare internal buffers
|
||||
|
@ -128,6 +113,9 @@ Jack::Jack() :
|
|||
|
||||
void Jack::activate()
|
||||
{
|
||||
Controller* c = new AkaiAPC();
|
||||
Controller* g = new LupppGUI();
|
||||
|
||||
/*
|
||||
// move to "settings" class or so
|
||||
Controller* c = new AkaiAPC();
|
||||
|
@ -175,9 +163,39 @@ Looper* Jack::getLooper(int t)
|
|||
}
|
||||
|
||||
|
||||
void Jack::registerMidiObserver( MidiObserver* mo )
|
||||
void Jack::registerMidiObserver( MidiObserver* mo, std::string name )
|
||||
{
|
||||
cout << "Jack::registerMidiObserver() " << name << endl;
|
||||
|
||||
// register the observer
|
||||
midiObservers.push_back( mo );
|
||||
|
||||
//set the index of the MIDI controller port on the MidiObserver
|
||||
midiObservers.back()->port( midiObservers.size() - 1 );
|
||||
|
||||
// register new MIDI I/O ports for this controller
|
||||
stringstream s;
|
||||
s << name << "_in";
|
||||
jack_port_t* tmp = jack_port_register(client,
|
||||
s.str().c_str(),
|
||||
JACK_DEFAULT_MIDI_TYPE,
|
||||
JackPortIsInput,
|
||||
0 );
|
||||
|
||||
midiObserverInputBuffers.push_back( 0 );
|
||||
midiObserverInputPorts.push_back( tmp );
|
||||
|
||||
stringstream s2;
|
||||
s2 << name << "_out";
|
||||
cout << s2.str() << endl;
|
||||
tmp = jack_port_register( client,
|
||||
s2.str().c_str(),
|
||||
JACK_DEFAULT_MIDI_TYPE,
|
||||
JackPortIsOutput,
|
||||
0 );
|
||||
|
||||
midiObserverOutputBuffers.push_back( 0 );
|
||||
midiObserverOutputPorts.push_back( tmp );
|
||||
}
|
||||
|
||||
|
||||
|
@ -189,8 +207,6 @@ int Jack::process (jack_nframes_t nframes)
|
|||
buffers.audio[Buffers::JACK_MASTER_OUT_L] = (float*)jack_port_get_buffer( masterOutputL , nframes );
|
||||
buffers.audio[Buffers::JACK_MASTER_OUT_R] = (float*)jack_port_get_buffer( masterOutputR , nframes );
|
||||
buffers.midi [Buffers::MASTER_MIDI_INPUT] = (void*) jack_port_get_buffer( masterMidiInput, nframes );
|
||||
buffers.midi [Buffers::APC_INPUT] = (void*) jack_port_get_buffer( apcMidiInput , nframes );
|
||||
buffers.midi [Buffers::APC_OUTPUT] = (void*) jack_port_get_buffer( apcMidiOutput , nframes );
|
||||
|
||||
memset( buffers.audio[Buffers::JACK_MASTER_OUT_L] , 0, sizeof(float) * nframes );
|
||||
memset( buffers.audio[Buffers::JACK_MASTER_OUT_R] , 0, sizeof(float) * nframes );
|
||||
|
@ -200,8 +216,6 @@ int Jack::process (jack_nframes_t nframes)
|
|||
memset( buffers.audio[Buffers::SIDECHAIN] , 0, sizeof(float) * nframes );
|
||||
memset( buffers.audio[Buffers::POST_SIDECHAIN] , 0, sizeof(float) * nframes );
|
||||
|
||||
jack_midi_clear_buffer( buffers.midi[Buffers::APC_OUTPUT] );
|
||||
|
||||
/// do events from the ringbuffer
|
||||
handleDspEvents();
|
||||
|
||||
|
@ -218,15 +232,32 @@ int Jack::process (jack_nframes_t nframes)
|
|||
EventGuiPrint e( buffer );
|
||||
writeToGuiRingbuffer( &e );
|
||||
|
||||
// run each event trought the midiObservers vector
|
||||
for(unsigned int i = 0; i < midiObservers.size(); i++ )
|
||||
{
|
||||
midiObservers.at(i)->midi( (unsigned char*) &in_event.buffer[0] );
|
||||
}
|
||||
|
||||
masterMidiInputIndex++;
|
||||
}
|
||||
|
||||
/// process each MidiObserver registered MIDI port
|
||||
for(unsigned int i = 0; i < midiObservers.size(); i++ )
|
||||
{
|
||||
midiObserverInputBuffers.at( i ) =
|
||||
(void*) jack_port_get_buffer( midiObserverInputPorts.at(i), nframes );
|
||||
|
||||
midiObserverOutputBuffers.at( i ) =
|
||||
(void*) jack_port_get_buffer( midiObserverOutputPorts.at(i), nframes );
|
||||
jack_midi_clear_buffer( midiObserverOutputBuffers.at( i ) );
|
||||
|
||||
|
||||
jack_midi_event_t in_event;
|
||||
int index = 0;
|
||||
int event_count = (int) jack_midi_get_event_count( midiObserverInputBuffers.at( i ) );
|
||||
while ( index < event_count )
|
||||
{
|
||||
jack_midi_event_get(&in_event, midiObserverInputBuffers.at( i ), index);
|
||||
midiObservers.at(i)->midi( (unsigned char*) &in_event.buffer[0] );
|
||||
printf( "APC MIDI %i %i %i\n", int(in_event.buffer[0]), int(in_event.buffer[1]), int(in_event.buffer[2]) );
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
/// process each track, starting at output and working up signal path
|
||||
for(unsigned int i = 0; i < NTRACKS; i++)
|
||||
{
|
||||
|
@ -320,12 +351,12 @@ int Jack::getSamplerate()
|
|||
return jack_get_sample_rate( client );
|
||||
}
|
||||
|
||||
void Jack::writeApcOutput( unsigned char* data )
|
||||
void Jack::midiObserverWriteMIDI( int portIndex, unsigned char* data )
|
||||
{
|
||||
// FIXME: MIDI output needs a QUEUE structure, so we can send more data to the APC "at once"
|
||||
void* apcOutput = buffers.midi[Buffers::APC_OUTPUT];
|
||||
void* portBuffer = midiObserverOutputBuffers.at(portIndex);
|
||||
|
||||
unsigned char* buf = jack_midi_event_reserve( apcOutput, 0, 3);
|
||||
unsigned char* buf = jack_midi_event_reserve( portBuffer, 0, 3);
|
||||
if( buf != 0 )
|
||||
{
|
||||
memcpy( buf, data, sizeof( unsigned char ) * 3);
|
||||
|
|
14
src/jack.hxx
14
src/jack.hxx
|
@ -52,15 +52,17 @@ class Jack
|
|||
|
||||
/// register MIDI observers: they're called when a MIDI message arrives on
|
||||
/// a port they're watching
|
||||
void registerMidiObserver( MidiObserver* mo );
|
||||
void registerMidiObserver( MidiObserver* mo, std::string name );
|
||||
|
||||
/// writes MIDI messages to a MidiObserver's port
|
||||
void midiObserverWriteMIDI( int portIndex, unsigned char* data );
|
||||
|
||||
|
||||
void masterVolume( float vol ){masterVol = vol;}
|
||||
|
||||
/// sets reverb bus parameters
|
||||
void setReverb( bool e, float d, float s );
|
||||
|
||||
/// writes MIDI messages to APC port
|
||||
void writeApcOutput( unsigned char* data );
|
||||
|
||||
private:
|
||||
jack_client_t* client;
|
||||
|
@ -75,7 +77,13 @@ class Jack
|
|||
|
||||
vector<Looper*> loopers;
|
||||
vector<TrackOutput*> trackOutputs;
|
||||
|
||||
// FIXME: refactor MidiObserver ports / buffers into one class, single vector
|
||||
vector<MidiObserver*> midiObservers;
|
||||
vector<jack_port_t*> midiObserverInputPorts;
|
||||
vector<jack_port_t*> midiObserverOutputPorts;
|
||||
vector<void*> midiObserverInputBuffers;
|
||||
vector<void*> midiObserverOutputBuffers;
|
||||
|
||||
// FX
|
||||
Reverb* reverb;
|
||||
|
|
|
@ -7,5 +7,15 @@ extern Jack* jack;
|
|||
|
||||
MidiObserver::MidiObserver( std::string portName )
|
||||
{
|
||||
jack->registerMidiObserver( this );
|
||||
jack->registerMidiObserver( this, portName );
|
||||
}
|
||||
|
||||
void MidiObserver::port(int index)
|
||||
{
|
||||
portIndex = index;
|
||||
}
|
||||
|
||||
int MidiObserver::port()
|
||||
{
|
||||
return portIndex;
|
||||
}
|
||||
|
|
|
@ -20,6 +20,17 @@ class MidiObserver
|
|||
/// gets called with each MIDI message from the controller. Deal with its
|
||||
/// input here, and route to the appropriate function in Luppp
|
||||
virtual void midi(unsigned char* data) = 0;
|
||||
|
||||
/// sets the port number for this instance. Used when writing MIDI messages
|
||||
/// to identify the port, using Jack::midiObserverWriteMIDI()
|
||||
void port(int index);
|
||||
|
||||
/// returns the port index to the subclass when needed
|
||||
int port();
|
||||
|
||||
private:
|
||||
int portIndex;
|
||||
|
||||
};
|
||||
|
||||
#endif // LUPPP_MIDI_OBSERVER_H
|
||||
|
|
Loading…
Reference in a new issue