Permalink
Browse files

JACK Transport timebase new feature, bugs & crashes fixed

  • Loading branch information...
Igevorse committed May 30, 2014
1 parent 122887f commit f48e901a03c1a538369800ec021272e0fc96342d
Showing with 90 additions and 13 deletions.
  1. +1 −0 mscore/driver.h
  2. +40 −1 mscore/jackaudio.cpp
  3. +3 −1 mscore/jackaudio.h
  4. +39 −11 mscore/seq.cpp
  5. +7 −0 mscore/seq.h
View
@@ -51,6 +51,7 @@ class Driver {
virtual void unregisterPort(int) {}
virtual void putEvent(const NPlayEvent&, unsigned /*framePos*/) {}
virtual void midiRead() {}
+ virtual void handleTimeSigTempoChanged() {}
};
View
@@ -19,11 +19,12 @@
//=============================================================================
#include "jackaudio.h"
-
+#include "musescore.h"
#include "libmscore/mscore.h"
#include "preferences.h"
// #include "msynth/synti.h"
#include "seq.h"
+#include "libmscore/score.h"
#include <jack/midiport.h>
@@ -313,6 +314,32 @@ static int graph_callback(void*)
return 0;
}
+void JackAudio::timebase(jack_transport_state_t state, jack_nframes_t nframes, jack_position_t *pos, int new_pos, void *arg)
+ {
+ JackAudio* audio = (JackAudio*)arg;
+ if(!audio->seq->score()) {
+ if(state==JackTransportLooping || state==JackTransportRolling)
+ audio->stopTransport();
+ }
+ else if(audio->seq->isRunning() && audio->timeSigTempoChanged) {
+ pos->valid = JackPositionBBT;
+
+ int curTick = audio->seq->getCurTick();
+ Fraction timeSig = audio->seq->score()->sigmap()->timesig(curTick).nominal();
+ pos->beats_per_bar = timeSig.numerator();
+ pos->beat_type = timeSig.denominator();
+
+ int bar,beat,tick;
+ audio->seq->score()->sigmap()->tickValues(curTick, &bar, &beat, &tick);
+ pos->ticks_per_beat = MScore::division;
+ pos->tick = tick;
+ pos->bar = bar+1;
+ pos->beat = beat+1;
+ pos->beats_per_minute = audio->seq->curTempo()*60;
+ qDebug()<<"Time signature and tempo changed: "<< pos->beats_per_minute<<", bar: "<< pos->bar<<",beat: "<<pos->beat<<", tick:"<<pos->tick<<", time sig: "<<pos->beats_per_bar<<"/"<<pos->beat_type<<endl;
+ audio->timeSigTempoChanged = false;
+ }
+ }
//---------------------------------------------------------
// processAudio
// JACK callback
@@ -321,6 +348,10 @@ static int graph_callback(void*)
int JackAudio::processAudio(jack_nframes_t frames, void* p)
{
JackAudio* audio = (JackAudio*)p;
+ // Prevent from crash if score not opened yet
+ if(!audio->seq->score())
+ return 0;
+
float* l;
float* r;
if (preferences.useJackAudio) {
@@ -412,6 +443,7 @@ bool JackAudio::init()
jack_set_error_function(noJackError);
client = 0;
+ timeSigTempoChanged = false;
strcpy(_jackName, "mscore");
jack_options_t options = (jack_options_t)0;
@@ -430,6 +462,8 @@ bool JackAudio::init()
jack_set_port_registration_callback(client, registration_callback, this);
jack_set_graph_order_callback(client, graph_callback, this);
jack_set_freewheel_callback (client, freewheel_callback, this);
+ if (jack_set_timebase_callback(client, 1, timebase, this) != 0)
+ fprintf(stderr, "Unable to take over timebase.\n");
_segmentSize = jack_get_buffer_size(client);
MScore::sampleRate = sampleRate();
@@ -603,5 +637,10 @@ void JackAudio::midiRead()
{
// midiDriver->read();
}
+
+void JackAudio::handleTimeSigTempoChanged()
+ {
+ timeSigTempoChanged = true;
+ }
}
View
@@ -41,12 +41,13 @@ class JackAudio : public Driver {
jack_client_t* client;
char _jackName[8];
+ bool timeSigTempoChanged;
QList<jack_port_t*> ports;
QList<jack_port_t*> midiOutputPorts;
QList<jack_port_t*> midiInputPorts;
static int processAudio(jack_nframes_t, void*);
-
+ static void timebase (jack_transport_state_t, jack_nframes_t, jack_position_t*, int, void *);
public:
JackAudio(Seq*);
virtual ~JackAudio();
@@ -67,6 +68,7 @@ class JackAudio : public Driver {
virtual void registerPort(const QString& name, bool input, bool midi);
virtual void unregisterPort(int);
+ virtual void handleTimeSigTempoChanged();
};
View
@@ -170,6 +170,11 @@ Seq::Seq()
noteTimer->stop();
connect(this, SIGNAL(toGui(int)), this, SLOT(seqMessage(int)), Qt::QueuedConnection);
+
+ prevTimeSig.setNumerator(0);
+ prevTempo = 0;
+ connect(this, SIGNAL(timeSigChanged()),this,SLOT(handleTimeSigTempoChanged()));
+ connect(this, SIGNAL(tempoChanged()),this,SLOT(handleTimeSigTempoChanged()));
}
//---------------------------------------------------------
@@ -325,6 +330,7 @@ void Seq::stop()
{
if (state == TRANSPORT_STOP)
return;
+
if (oggInit) {
ov_clear(&vf);
oggInit = false;
@@ -518,6 +524,8 @@ void Seq::processMessages()
}
else
cs->tempomap()->setRelTempo(msg.realVal);
+ prevTempo = curTempo();
+ emit tempoChanged();
}
break;
case SEQ_PLAY:
@@ -677,16 +685,7 @@ void Seq::process(unsigned n, float* buffer)
else if (state == TRANSPORT_PLAY && driverState == TRANSPORT_STOP) {
state = TRANSPORT_STOP;
// 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));
- }
-
+ stopNotes();
if (playPos == events.cend()) {
if (mscore->loop()) {
qDebug("Seq.cpp - Process - Loop whole score. playPos = %d cs->pos() = %d", playPos->first,cs->pos());
@@ -708,8 +707,18 @@ void Seq::process(unsigned n, float* buffer)
memset(buffer, 0, sizeof(float) * n * 2);
float* p = buffer;
+
processMessages();
+ if(cs && cs->sigmap()->timesig(getCurTick()).nominal()!=prevTimeSig) {
+ prevTimeSig = cs->sigmap()->timesig(getCurTick()).nominal();
+ emit timeSigChanged();
+ }
+ if(cs && curTempo()!=prevTempo) {
+ prevTempo = curTempo();
+ emit tempoChanged();
+ }
+
if (state == TRANSPORT_PLAY) {
if(!cs)
return;
@@ -1049,7 +1058,21 @@ void Seq::stopNoteTimer()
void Seq::stopNotes(int channel)
{
- _synti->allNotesOff(channel);
+ // Stop motes in all channels
+ if (channel == -1) {
+ for(int ch=0; ch<cs->midiMapping()->size();ch++) {
+ putEvent(NPlayEvent(ME_CONTROLLER, ch, CTRL_SUSTAIN, 0));
+ for(int i=0; i<128; i++)
+ putEvent(NPlayEvent(ME_NOTEOFF,ch,i,0));
+ }
+ }
+ else {
+ putEvent(NPlayEvent(ME_CONTROLLER, channel, CTRL_SUSTAIN, 0));
+ for(int i=0; i<128; i++)
+ putEvent(NPlayEvent(ME_NOTEOFF,channel,i,0));
+ }
+ if(preferences.useAlsaAudio || preferences.useJackAudio || preferences.usePulseAudio || preferences.usePortaudioAudio)
+ _synti->allNotesOff(channel);
}
//---------------------------------------------------------
@@ -1426,4 +1449,9 @@ void Seq::setLoopSelection()
cs->setLoopInTick(cs->selection().tickStart());
cs->setLoopOutTick(cs->selection().tickEnd());
}
+
+void Seq::handleTimeSigTempoChanged()
+ {
+ _driver->handleTimeSigTempoChanged();
+ }
}
View
@@ -22,6 +22,7 @@
#define __SEQ_H__
#include "libmscore/sequencer.h"
+#include "libmscore/fraction.h"
#include "synthesizer/event.h"
#include "driver.h"
#include "libmscore/fifo.h"
@@ -35,6 +36,7 @@ class Note;
class Score;
class Painter;
class Measure;
+class Fraction;
class Driver;
class Part;
struct Channel;
@@ -97,6 +99,8 @@ class Seq : public QObject, public Sequencer {
bool running; // true if sequencer is available
int state; // TRANSPORT_STOP, TRANSPORT_PLAY, TRANSPORT_STARTING=3
bool inCountIn;
+ Fraction prevTimeSig;
+ double prevTempo;
bool oggInit;
bool playlistChanged;
@@ -145,6 +149,7 @@ class Seq : public QObject, public Sequencer {
void heartBeatTimeout();
void midiInputReady();
void setPlaylistChanged() { playlistChanged = true; }
+ void handleTimeSigTempoChanged();
public slots:
void setRelTempo(double);
@@ -159,6 +164,8 @@ class Seq : public QObject, public Sequencer {
void stopped();
int toGui(int);
void heartBeat(int, int, int);
+ void tempoChanged();
+ void timeSigChanged();
public:
// this are also the jack audio transport states:

0 comments on commit f48e901

Please sign in to comment.