MuseScore/mscore/seq.h

252 lines
7.7 KiB
C++

//=============================================================================
// MusE Score
// Linux Music Score Editor
// $Id: seq.h 5660 2012-05-22 14:17:39Z wschweer $
//
// Copyright (C) 2002-2009 Werner Schweer and others
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//=============================================================================
#ifndef __SEQ_H__
#define __SEQ_H__
#include "libmscore/sequencer.h"
#include "libmscore/fraction.h"
#include "synthesizer/event.h"
#include "driver.h"
#include "libmscore/fifo.h"
#include "libmscore/tempo.h"
class QTimer;
namespace Ms {
class Note;
class Score;
class Painter;
class Measure;
class Fraction;
class Driver;
class Part;
struct Channel;
class ScoreView;
class MasterSynthesizer;
class Segment;
enum class POS : char;
//---------------------------------------------------------
// SeqMsg
// message format for gui -> sequencer messages
//---------------------------------------------------------
enum class SeqMsgId : char {
NO_MESSAGE,
TEMPO_CHANGE,
PLAY, SEEK,
MIDI_INPUT_EVENT
};
struct SeqMsg {
SeqMsgId id;
union {
int intVal;
qreal realVal;
};
NPlayEvent event;
SeqMsg() {}
SeqMsg(SeqMsgId _id, int val) : id(_id), intVal(val) {}
SeqMsg(SeqMsgId _id, qreal val) : id(_id), realVal(val) {}
SeqMsg(SeqMsgId _id, const NPlayEvent& e) : id(_id), event(e) {}
};
//---------------------------------------------------------
// SeqMsgFifo
//---------------------------------------------------------
static const int SEQ_MSG_FIFO_SIZE = 1024*8;
class SeqMsgFifo : public FifoBase {
SeqMsg messages[SEQ_MSG_FIFO_SIZE];
public:
SeqMsgFifo();
virtual ~SeqMsgFifo() {}
void enqueue(const SeqMsg&); // put object on fifo
SeqMsg dequeue(); // remove object from fifo
};
// this are also the jack audio transport states:
enum class Transport : char {
STOP=0,
PLAY=1,
STARTING=3,
NET_STARTING=4
};
//---------------------------------------------------------
// Seq
// sequencer
//---------------------------------------------------------
class Seq : public QObject, public Sequencer {
Q_OBJECT
mutable QMutex mutex;
Score* cs;
ScoreView* cv;
bool running; // true if sequencer is available
Transport state; // STOP, PLAY, STARTING=3
bool inCountIn;
// When we begin playing count in, JACK should play the ticks, but shouldn't run
// JACK Transport to prevent playing in other applications. Before playing
// count in we have to disconnect from JACK Transport by switching to the fake transport.
// Also we save current preferences.useJackTransport value to useJackTransportSavedFlag
// to restore it when count in ends. After this all applications start playing in sync.
bool useJackTransportSavedFlag;
int maxMidiOutPort; // Maximum count of midi out ports in all opened scores
Fraction prevTimeSig;
double prevTempo;
bool oggInit;
bool playlistChanged;
SeqMsgFifo toSeq;
SeqMsgFifo fromSeq;
Driver* _driver;
MasterSynthesizer* _synti;
double meterValue[2];
double meterPeakValue[2];
int peakTimer[2];
EventMap events; // playlist
EventMap countInEvents;
int playTime; // current play position in samples
int countInPlayTime;
int endTick;
EventMap::const_iterator playPos; // moved in real time thread
EventMap::const_iterator countInPlayPos;
EventMap::const_iterator guiPos; // moved in gui thread
QList<const Note*> markedNotes; // notes marked as sounding
uint tackRest; // metronome state
uint tickRest;
qreal metronomeVolume;
QTimer* heartBeatTimer;
QTimer* noteTimer;
void collectMeasureEvents(Measure*, int staffIdx);
void setPos(int);
void playEvent(const NPlayEvent&, unsigned framePos);
void guiToSeq(const SeqMsg& msg);
void metronome(unsigned n, float* l, bool force);
void seekCommon(int utick);
void unmarkNotes();
void updateSynthesizerState(int tick1, int tick2);
void addCountInClicks();
private slots:
void seqMessage(int msg, int arg = 0);
void heartBeatTimeout();
void midiInputReady();
void setPlaylistChanged() { playlistChanged = true; }
void handleTimeSigTempoChanged();
public slots:
void setRelTempo(double);
void seek(int utick);
void seekRT(int utick);
void stopNotes(int channel = -1, bool realTime = false);
void start();
void stop();
void setPos(POS, unsigned);
void setMetronomeGain(float val) { metronomeVolume = val; }
signals:
void started();
void stopped();
int toGui(int, int arg = 0);
void heartBeat(int, int, int);
void tempoChanged();
void timeSigChanged();
public:
Seq();
~Seq();
bool canStart();
void rewindStart();
void loopStart();
void seekEnd();
void nextMeasure();
void nextChord();
void prevMeasure();
void prevChord();
void collectEvents();
void guiStop();
void stopWait();
void setLoopIn();
void setLoopOut();
void setLoopSelection();
bool init(bool hotPlug = false);
void exit();
bool isRunning() const { return running; }
bool isPlaying() const { return state == Transport::PLAY; }
bool isStopped() const { return state == Transport::STOP; }
void processMessages();
void process(unsigned, float*);
int getEndTick() const { return endTick; }
bool isRealtime() const { return true; }
void sendMessage(SeqMsg&) const;
void setController(int, int, int);
virtual void sendEvent(const NPlayEvent&);
void setScoreView(ScoreView*);
Score* score() const { return cs; }
ScoreView* viewer() const { return cv; }
void initInstruments(bool realTime = false);
Driver* driver() { return _driver; }
void setDriver(Driver* d) { _driver = d; }
MasterSynthesizer* synti() const { return _synti; }
void setMasterSynthesizer(MasterSynthesizer* ms) { _synti = ms; }
int getCurTick();
double curTempo() const;
void putEvent(const NPlayEvent&, unsigned framePos = 0);
void startNoteTimer(int duration);
virtual void startNote(int channel, int, int, double nt) override;
virtual void startNote(int channel, int, int, int, double nt) override;
void eventToGui(NPlayEvent);
void stopNoteTimer();
void recomputeMaxMidiOutPort();
float metronomeGain() const { return metronomeVolume; }
};
extern Seq* seq;
extern void initSequencer();
extern bool initMidi();
} // namespace Ms
#endif