//============================================================================= // 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 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