Basic JACK MIDI In support

This commit is contained in:
Igevorse 2014-05-25 00:30:33 +05:00
parent e5812556a7
commit 122887f471
5 changed files with 49 additions and 13 deletions

View file

@ -25,6 +25,7 @@ namespace Ms {
class Seq;
class Event;
class NPlayEvent;
//---------------------------------------------------------
// Driver
@ -48,7 +49,7 @@ class Driver {
virtual int sampleRate() const = 0;
virtual void registerPort(const QString& /*name*/, bool /*input*/, bool /*midi*/) {}
virtual void unregisterPort(int) {}
virtual void putEvent(const Event&, unsigned /*framePos*/) {}
virtual void putEvent(const NPlayEvent&, unsigned /*framePos*/) {}
virtual void midiRead() {}
};

View file

@ -46,6 +46,7 @@ JackAudio::JackAudio(Seq* s)
JackAudio::~JackAudio()
{
if (client) {
stop();
if (jack_client_close(client)) {
qDebug("jack_client_close() failed: %s",
strerror(errno));
@ -226,7 +227,7 @@ bool JackAudio::stop()
{
if (preferences.useJackMidi && preferences.rememberLastMidiConnections) {
QSettings settings;
settings.setValue("midiPorts", midiOutputPorts.size());
//settings.setValue("midiPorts", midiOutputPorts.size());
int port = 0;
foreach(jack_port_t* mp, midiOutputPorts) {
const char** cc = jack_port_get_connections(mp);
@ -243,7 +244,8 @@ bool JackAudio::stop()
free((void*)cc);
++port;
}
settings.setValue("midiInputPorts", midiInputPorts.size());
// We don't use it now
//settings.setValue("midiInputPorts", midiInputPorts.size());
port = 0;
foreach(jack_port_t* mp, midiInputPorts) {
const char** cc = jack_port_get_connections(mp);
@ -374,6 +376,11 @@ int JackAudio::processAudio(jack_nframes_t frames, void* p)
*r++ = *sp++;
}
}
else {
// JACK MIDI only
float buffer[frames * 2];
audio->seq->process((unsigned)frames, buffer);
}
return 0;
}
@ -390,8 +397,9 @@ static void jackError(const char *s)
// noJackError
//---------------------------------------------------------
static void noJackError(const char* /* s */)
static void noJackError(const char* s )
{
qDebug("noJACK ERROR: %s", s);
}
//---------------------------------------------------------
@ -504,7 +512,7 @@ int JackAudio::getState()
// putEvent
//---------------------------------------------------------
void JackAudio::putEvent(const Event& e, unsigned framePos)
void JackAudio::putEvent(const NPlayEvent& e, unsigned framePos)
{
if (!preferences.useJackMidi)
return;
@ -562,7 +570,8 @@ void JackAudio::putEvent(const Event& e, unsigned framePos)
p[1] = e.dataA();
}
break;
case ME_SYSEX:
// Do we really need to handle ME_SYSEX?
/* case ME_SYSEX:
{
const unsigned char* data = e.edata();
int len = e.len();
@ -575,7 +584,7 @@ void JackAudio::putEvent(const Event& e, unsigned framePos)
p[len+1] = 0xf7;
memcpy(p+1, data, len);
}
break;
break;*/
case ME_SONGPOS:
case ME_CLOCK:
case ME_START:

View file

@ -62,7 +62,7 @@ class JackAudio : public Driver {
virtual void stopTransport();
virtual int getState();
virtual int sampleRate() const { return jack_get_sample_rate(client); }
virtual void putEvent(const Event&, unsigned framePos);
virtual void putEvent(const NPlayEvent&, unsigned framePos);
virtual void midiRead();
virtual void registerPort(const QString& name, bool input, bool midi);

View file

@ -827,6 +827,7 @@ void PreferenceDialog::updateValues()
portaudioDriver->setChecked(prefs.usePortaudioAudio);
pulseaudioDriver->setChecked(prefs.usePulseAudio);
useJackMidi->setChecked(prefs.useJackMidi);
useSynthesizer->setChecked(prefs.useAlsaAudio || prefs.useJackAudio || prefs.usePortaudioAudio || prefs.usePulseAudio);
alsaDevice->setText(prefs.alsaDevice);

View file

@ -650,20 +650,43 @@ void Seq::process(unsigned n, float* buffer)
int driverState = _driver->getState();
if (driverState != state) {
// Got a message from JACK Transport panel: Play
if (state == TRANSPORT_STOP && driverState == TRANSPORT_PLAY) {
if((preferences.useJackMidi || preferences.useJackAudio) && !getAction("play")->isChecked()) {
// Do not play while editing elements
if(mscore->state()==STATE_NORMAL && isRunning() && canStart()) {
if (playlistChanged)
collectEvents();
getAction("play")->setChecked(true);
getAction("play")->triggered(true);
}
else {
return;
}
}
// Need to change state after calling collectEvents()
state = TRANSPORT_PLAY;
if (mscore->countIn() && cs->playMode() == PlayMode::SYNTHESIZER) {
if (mscore->countIn() && cs->playMode() == PLAYMODE_SYNTHESIZER) {
countInEvents.clear();
inCountIn = true;
}
emit toGui('1');
}
// Got a message from JACK Transport panel: Stop
else if (state == TRANSPORT_PLAY && driverState == TRANSPORT_STOP) {
state = TRANSPORT_STOP;
stopNotes();
// send sustain off
// TODO: channel?
putEvent(NPlayEvent(ME_CONTROLLER, 0, CTRL_SUSTAIN, 0));
// Muting all notes
if(preferences.useAlsaAudio || preferences.useJackAudio || preferences.usePulseAudio || preferences.usePortaudioAudio || preferences.useOsc)
stopNotes();
if(preferences.useJackMidi)
for(int ch=0; ch<cs->midiMapping()->size();ch++) {
// send sustain off
putEvent(NPlayEvent(ME_CONTROLLER, ch, CTRL_SUSTAIN, 0));
for(int i=0; i<128; i++)
putEvent(NPlayEvent(ME_NOTEOFF,ch,i,0));
}
if (playPos == events.cend()) {
if (mscore->loop()) {
qDebug("Seq.cpp - Process - Loop whole score. playPos = %d cs->pos() = %d", playPos->first,cs->pos());
@ -1237,6 +1260,8 @@ void Seq::putEvent(const NPlayEvent& event)
}
int syntiIdx= _synti->index(cs->midiMapping(channel)->articulation->synti);
_synti->play(event, syntiIdx);
if (preferences.useJackMidi)
driver()->putEvent(event,0);
}
//---------------------------------------------------------