Skip to content

Commit

Permalink
Add midi connect controller action
Browse files Browse the repository at this point in the history
  • Loading branch information
wvengen committed Jun 12, 2020
1 parent 48fc078 commit c2895e2
Show file tree
Hide file tree
Showing 13 changed files with 161 additions and 17 deletions.
11 changes: 10 additions & 1 deletion src/controller/binding.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,16 @@ class Binding
{
public:
Binding() : status(0), data(0), action(0), active(1),
track(-2),scene(-1),send(-1)
track(-2),scene(-1),send(-1),dataList(0),dataListSize(0)
{
ID = privateID++;
}

~Binding()
{
if (dataList) delete dataList;
}

int ID;

unsigned char status;
Expand All @@ -52,6 +57,10 @@ public:
/// maps from Gridlogic::State to MIDI output value from binding
std::map<int,int> clipStateMap;

/// arbitrary-length data (TODO use this instead of data)
unsigned char *dataList;
unsigned int dataListSize;

private:
/// static int counter to allow deleting this specific instance
static int privateID;
Expand Down
4 changes: 4 additions & 0 deletions src/controller/controller.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,10 @@ public:
/// reset controller
virtual void reset();

/// Jack MIDI (dis)connect
virtual void midiConnect( jack_port_t* a, jack_port_t *b ) {}
virtual void midiDisconnect( jack_port_t* a, jack_port_t *b ) {}

private:
static int privateID;
int ID;
Expand Down
49 changes: 43 additions & 6 deletions src/controller/genericmidi.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ void GenericMIDI::recordArm(int t, bool enabled)
data[0] = b->status;
data[1] = b->data;
data[2] = enabled ? 127 : 0;
writeMidi( data );
writeMidi( data, 3 );
return;
}
}
Expand All @@ -154,7 +154,7 @@ void GenericMIDI::metronomeEnable(bool enabled)
data[0] = b->status;
data[1] = b->data;
data[2] = enabled ? 127 : 0;
writeMidi( data );
writeMidi( data, 3 );
return;
}
}
Expand All @@ -171,7 +171,7 @@ void GenericMIDI::trackSend(int t, int send, float v)
data[0] = b->status;
data[1] = b->data;
data[2] = v * 127;
writeMidi( data );
writeMidi( data, 3 );
return;
}
}
Expand All @@ -187,7 +187,7 @@ void GenericMIDI::trackSendActive(int t, int send, bool a)
data[0] = b->status;
data[1] = b->data;
data[2] = a ? 127 : 0;
writeMidi( data );
writeMidi( data, 3 );
return;
}
}
Expand Down Expand Up @@ -352,7 +352,7 @@ void GenericMIDI::setSceneState(int t, int scene, GridLogic::State s)
data[2] = it->second;

//LUPPP_NOTE("GenericMIDI::sceneState() writing event %i, %i, %i", data[0],data[1],data[2] );
writeMidi( data );
writeMidi( data, 3 );
}
}
}
Expand Down Expand Up @@ -388,12 +388,28 @@ void GenericMIDI::launchScene( int scene )
data[2] = (i == scene) * 127;

//LUPPP_NOTE("this = %i GenericMIDI::launchScene()", this );
writeMidi( data );
writeMidi( data, 3 );
}
}

}

void GenericMIDI::midiConnect(jack_port_t* a, jack_port_t *b)
{
// skip unless this controller's output port is connected
if (!isMyOutput(a) && !isMyOutput(b)) {
return;
}

for(unsigned int i = 0; i < actionToMidi.size(); i++) {
Binding* b = actionToMidi.at(i);

if ( b->action == MIDI_CONNECT && b->dataListSize > 0 ) {
writeMidi( b->dataList, b->dataListSize );
}
}

}

int GenericMIDI::loadController( std::string file )
{
Expand Down Expand Up @@ -560,6 +576,27 @@ Binding* GenericMIDI::setupBinding( cJSON* binding )
return 0;
}

if ( strcmp( actionJson->valuestring, "midi:connect" ) == 0 ) {
tmp->action = Event::MIDI_CONNECT;

cJSON* dataList = cJSON_GetObjectItem( binding, "dataList" );
if ( !dataList ) {
LUPPP_WARN("Binding midi connect: doesn't have dataList field");
delete tmp;
return 0;
}

tmp->dataListSize = cJSON_GetArraySize( dataList );
tmp->dataList = new unsigned char[tmp->dataListSize];

for(int i = 0; i < tmp->dataListSize; i++ ) {
cJSON* dataListItem = cJSON_GetArrayItem( dataList, i );
tmp->dataList[i] = dataListItem->valueint;
}

return tmp;
}

cJSON* statusJson = cJSON_GetObjectItem( binding, "status" );
cJSON* dataJson = cJSON_GetObjectItem( binding, "data" );
if ( !statusJson || !dataJson ) {
Expand Down
2 changes: 2 additions & 0 deletions src/controller/genericmidi.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,8 @@ public:
void setupBinding( LupppAction eventType, int midiStatus, int midiData, int track, int scene, int send, int active );
void removeBinding( int bindingID );

void midiConnect(jack_port_t* a, jack_port_t* b);

private:
STATUS stat;

Expand Down
4 changes: 2 additions & 2 deletions src/controller/nonseq.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ void NonSeq::launchScene( int scene )
data[2] = scene;

//LUPPP_NOTE("NonSeq::launchScene() %i, %i, %i\n", data[0],data[1],data[2] );
writeMidi( data );
writeMidi( data, 3 );
}

std::string NonSeq::getName()
Expand All @@ -65,7 +65,7 @@ void NonSeq::setSceneState(int track, int scene, GridLogic::State s)
data[2] = track;

//LUPPP_NOTE("NonSeq::setSceneState() %i, %i, %i\n", data[0],data[1],data[2] );
writeMidi( data );
writeMidi( data, 3 );
}


Expand Down
10 changes: 10 additions & 0 deletions src/controllerupdater.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -186,3 +186,13 @@ void ControllerUpdater::metronomeEnable(bool b)
{
for(unsigned int i = 0; i < c.size(); i++) c.at(i)->metronomeEnable(b);
}

void ControllerUpdater::midiConnect(jack_port_t *a, jack_port_t *b)
{
for(unsigned int i = 0; i < c.size(); i++) c.at(i)->midiConnect(a, b);
}

void ControllerUpdater::midiDisconnect(jack_port_t *a, jack_port_t *b)
{
for(unsigned int i = 0; i < c.size(); i++) c.at(i)->midiDisconnect(a, b);
}
4 changes: 4 additions & 0 deletions src/controllerupdater.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

#include <vector>
#include <iostream>
#include <jack/jack.h>

#include "controller/controller.hxx"

Expand Down Expand Up @@ -87,6 +88,9 @@ public:

void metronomeEnable(bool b);

void midiConnect(jack_port_t* a, jack_port_t* b);
void midiDisconnect(jack_port_t* a, jack_port_t* b);

private:
std::vector<Controller*> c;
};
Expand Down
27 changes: 27 additions & 0 deletions src/event.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,8 @@ enum EVENT_TYPE {
CONTROLLER_BINDING_MADE,
CONTROLLER_BINDING_REMOVE,

MIDI_CONNECT,

QUIT,

// for keeping loop index's inside the enum
Expand Down Expand Up @@ -1170,6 +1172,31 @@ public:
}
};

class EventMidiConnect : public EventBase
{
public:
int type()
{
return int(MIDI_CONNECT);
}
uint32_t size()
{
return sizeof(EventMidiConnect);
}

jack_port_id_t a;
jack_port_id_t b;
bool connect;

EventMidiConnect() {}
EventMidiConnect(jack_port_id_t a, jack_port_id_t b, int connect)
{
this->a = a;
this->b = b;
this->connect = connect;
}
};


#endif // LUPPP_EVENT_H

20 changes: 20 additions & 0 deletions src/eventhandlerdsp.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -454,6 +454,26 @@ void handleDspEvents()
break;
}

case Event::MIDI_CONNECT: {
if ( availableRead >= sizeof(EventMidiConnect) ) {
EventMidiConnect ev;
jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventMidiConnect) );

// get the jack ports, and notify controllers

jack_client_t* c = jack->getJackClientPointer();
jack_port_t* portA = jack_port_by_id( c, ev.a );
jack_port_t* portB = jack_port_by_id( c, ev.b );

if ( ev.connect > 0 ) {
jack->getControllerUpdater()->midiConnect( portA, portB );
} else {
jack->getControllerUpdater()->midiDisconnect( portA, portB );
}
}
break;
}

default: {
cout << "DSP: Unkown message!! Will clog ringbuffer" << endl;
// just do nothing
Expand Down
17 changes: 17 additions & 0 deletions src/jack.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,12 @@ Jack::Jack( std::string name ) :
LUPPP_ERROR("%s","Error setting timebase callback");
}

if ( jack_set_port_connect_callback(client,
static_connect,
static_cast<void*>(this)) ) {
LUPPP_ERROR("%s","Error setting JACK connect callback");
}

//Controller* m = new AkaiAPC();

// TODO: Add GUI dialog to add controllers, and insert them into the controller map.
Expand Down Expand Up @@ -758,6 +764,12 @@ int Jack::timebase(jack_transport_state_t state,
return 0;
}

void Jack::connect(jack_port_id_t a, jack_port_id_t b, int connect)
{
EventMidiConnect e(a, b, connect);
writeToDspRingbuffer( &e );
}

int Jack::static_process(jack_nframes_t nframes, void *instance)
{
return static_cast<Jack*>(instance)->process(nframes);
Expand All @@ -771,3 +783,8 @@ int Jack::static_timebase(jack_transport_state_t state,
{
return static_cast<Jack*>(instance)->timebase(state,nframes, pos, newPos );
}

void Jack::static_connect(jack_port_id_t a, jack_port_id_t b, int connect, void *instance)
{
static_cast<Jack*>(instance)->connect(a, b, connect);
}
4 changes: 4 additions & 0 deletions src/jack.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,8 @@ private:
jack_position_t*,
int );

void connect(jack_port_id_t, jack_port_id_t, int);

// static JACK callbacks
static int static_process (jack_nframes_t, void *);

Expand All @@ -231,6 +233,8 @@ private:
int,
void* );

static void static_connect (jack_port_id_t, jack_port_id_t, int, void *);

// UI update variables
int uiUpdateCounter;
int uiUpdateConstant;
Expand Down
20 changes: 13 additions & 7 deletions src/observer/midi.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -42,20 +42,16 @@ MidiIO::~MidiIO()
}


void MidiIO::writeMidi( unsigned char* data )
void MidiIO::writeMidi( unsigned char* data, unsigned int length )
{
void* portBuffer = jack_port_get_buffer( jackOutputPort, jack->getBuffersize() );

unsigned char* buffer = jack_midi_event_reserve( portBuffer, 0, 3);
unsigned char* buffer = jack_midi_event_reserve( portBuffer, 0, sizeof(unsigned char)*length );
if( buffer == 0 ) {
return;
} else {
//memcpy( buffer, data, sizeof(unsigned char)*3 );
buffer[0] = data[0];
buffer[1] = data[1];
buffer[2] = data[2];
memcpy( buffer, data, sizeof(unsigned char)*length );
}

}

int MidiIO::registerMidiPorts(std::string name)
Expand Down Expand Up @@ -123,3 +119,13 @@ void MidiIO::process(int nframes)
}

}

bool MidiIO::isMyOutput(jack_port_t* port)
{
return port == jackOutputPort;
}

bool MidiIO::isMyInput(jack_port_t* port)
{
return port == jackInputPort;
}
6 changes: 5 additions & 1 deletion src/observer/midi.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,11 @@ public:

virtual void midi(unsigned char* /*data*/) {};

void writeMidi( unsigned char* /*data*/ );
void writeMidi(unsigned char* /*data*/, unsigned int length);

protected:
bool isMyOutput(jack_port_t*);
bool isMyInput(jack_port_t*);

private:
bool portsRegistered;
Expand Down

0 comments on commit c2895e2

Please sign in to comment.