1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252
|
//=============================================================================
// 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
|