summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--muse/muse/CMakeLists.txt2
-rw-r--r--muse/muse/arranger/tlwidget.cpp9
-rw-r--r--muse/muse/arranger/trackinfo.cpp34
-rw-r--r--muse/muse/audio.cpp32
-rw-r--r--muse/muse/audio.h1
-rw-r--r--muse/muse/audiogroup.h3
-rw-r--r--muse/muse/audioinput.cpp2
-rw-r--r--muse/muse/audioinput.h1
-rw-r--r--muse/muse/audiooutput.cpp2
-rw-r--r--muse/muse/audiooutput.h1
-rw-r--r--muse/muse/audiotrack.cpp4
-rw-r--r--muse/muse/audiotrack.h2
-rw-r--r--muse/muse/ctrl/configmidictrl.cpp7
-rw-r--r--muse/muse/midi.cpp35
-rw-r--r--muse/muse/midichannel.cpp11
-rw-r--r--muse/muse/midichannel.h9
-rw-r--r--muse/muse/midiedit/ctrledit.cpp5
-rw-r--r--muse/muse/midiinport.cpp2
-rw-r--r--muse/muse/midiinport.h1
-rw-r--r--muse/muse/midiout.cpp389
-rw-r--r--muse/muse/midiout.h74
-rw-r--r--muse/muse/midioutport.cpp305
-rw-r--r--muse/muse/midioutport.h47
-rw-r--r--muse/muse/midisynti.cpp2
-rw-r--r--muse/muse/midisynti.h2
-rw-r--r--muse/muse/miditrack.cpp2
-rw-r--r--muse/muse/miditrack.h5
-rw-r--r--muse/muse/mixer/astrip.cpp26
-rw-r--r--muse/muse/mixer/mstrip.cpp264
-rw-r--r--muse/muse/mixer/mstrip.h2
-rw-r--r--muse/muse/muse.cpp5
-rw-r--r--muse/muse/song.cpp9
-rw-r--r--muse/muse/synth.cpp81
-rw-r--r--muse/muse/synth.h15
-rw-r--r--muse/muse/track.cpp43
-rw-r--r--muse/muse/track.h24
-rw-r--r--muse/muse/wavetrack.cpp2
-rw-r--r--muse/muse/wavetrack.h2
38 files changed, 872 insertions, 590 deletions
diff --git a/muse/muse/CMakeLists.txt b/muse/muse/CMakeLists.txt
index 54b6146e..3d038136 100644
--- a/muse/muse/CMakeLists.txt
+++ b/muse/muse/CMakeLists.txt
@@ -71,6 +71,7 @@ QT4_WRAP_CPP ( muse_moc_headers
audiooutput.h
audioinput.h
audiogroup.h
+ synth.h
exportmidi.h
importmidi.h
midichannel.h
@@ -129,6 +130,7 @@ add_executable ( muse
midioutport.cpp
midiinport.cpp
midichannel.cpp
+ midiout.cpp
projectpropsdialog.cpp
projectdialog.cpp
diff --git a/muse/muse/arranger/tlwidget.cpp b/muse/muse/arranger/tlwidget.cpp
index 8249b22b..267e3b7b 100644
--- a/muse/muse/arranger/tlwidget.cpp
+++ b/muse/muse/arranger/tlwidget.cpp
@@ -36,6 +36,7 @@
#include "audio.h"
#include "midioutport.h"
#include "midichannel.h"
+#include "instruments/minstrument.h"
//---------------------------------------------------------
// TLWidget
@@ -159,12 +160,12 @@ void TLWidget::mousePressEvent(QMouseEvent* ev)
{
int idx = song->tracks()->index(_track);
if (_track->type() == Track::MIDI) {
- MidiTrack* t = new MidiTrack;
- t->clone((MidiTrack*)_track);
+ MidiTrack* t = new MidiTrack();
+ t->clone((MidiTrack*)_track);
song->insertTrack(t, idx);
}
else {
- WaveTrack* t = new WaveTrack;
+ WaveTrack* t = new WaveTrack();
t->clone((WaveTrack*)_track);
song->insertTrack(t, idx);
}
@@ -530,7 +531,7 @@ void TLWidget::outChannelChanged(int n)
MidiChannel* mc = ((MidiTrack*)_track)->channel();
if (mc == 0) // no route to port?
return;
- MidiOutPort* mp = mc->port();
+ MidiOut* mp = mc->port();
int id = mc->channelNo();
if (id == n)
return;
diff --git a/muse/muse/arranger/trackinfo.cpp b/muse/muse/arranger/trackinfo.cpp
index c9dc7d1b..cba5a891 100644
--- a/muse/muse/arranger/trackinfo.cpp
+++ b/muse/muse/arranger/trackinfo.cpp
@@ -204,7 +204,7 @@ void MidiTrackInfo::init(Track* t)
portIndex = k + 1;
}
if (midic) {
- MidiOutPort* op = midic->port();
+ MidiOut* op = midic->port();
for (int i = 0; i < MIDI_CHANNELS; ++i) {
MidiChannel* c = op->channel(i);
if (midic == c)
@@ -212,7 +212,7 @@ void MidiTrackInfo::init(Track* t)
channel->addItem(c->name(), i);
}
connect(midic, SIGNAL(controllerChanged(int)), SLOT(controllerChanged(int)));
- connect(op, SIGNAL(instrumentChanged()), SLOT(instrumentChanged()));
+//TODO connect(op, SIGNAL(instrumentChanged()), SLOT(instrumentChanged()));
channel->setCurrentIndex(channelIndex);
port->setCurrentIndex(portIndex);
MidiInstrument* mi = op->instrument();
@@ -224,7 +224,7 @@ void MidiTrackInfo::init(Track* t)
curIdx = idx;
}
mp.instrument->setCurrentIndex(curIdx);
- mp.deviceId->setValue(op->deviceId());
+//TODO mp.deviceId->setValue(op->deviceId());
autoChanged(midic, false); // update enable
int val = midic->ctrlVal(CTRL_PROGRAM).i;
int channelno = midic->channelNo();
@@ -277,7 +277,7 @@ void MidiTrackInfo::channelSelected(int ch)
--ch;
Route srcRoute(track);
MidiChannel* midic = ((MidiTrack*)track)->channel();
- MidiOutPort* midip = midic->port();
+ MidiOut* midip = midic->port();
if (midic) {
Route odstRoute(midic);
audio->msgRemoveRoute(srcRoute, odstRoute);
@@ -299,7 +299,7 @@ void MidiTrackInfo::controllerChanged(int id)
if (id == CTRL_PROGRAM) {
MidiChannel* midic = ((MidiTrack*)track)->channel();
if (midic) {
- MidiOutPort* op = midic->port();
+ MidiOut* op = midic->port();
MidiInstrument* mi = op->instrument();
int val = midic->ctrlVal(id).i;
mc.patch->setText(mi->getPatchName(midic->channelNo(), val));
@@ -315,7 +315,7 @@ void MidiTrackInfo::instrumentChanged()
{
MidiChannel* midic = ((MidiTrack*)track)->channel();
if (midic) {
- MidiOutPort* op = midic->port();
+ MidiOut* op = midic->port();
MidiInstrument* mi = op->instrument();
int idx = 0;
for (iMidiInstrument i = midiInstruments.begin(); i != midiInstruments.end(); ++i, ++idx) {
@@ -365,7 +365,7 @@ void MidiTrackInfo::patchClicked()
if (!midic)
return;
- MidiOutPort* op = midic->port();
+ MidiOut* op = midic->port();
MidiInstrument* mi = op->instrument();
mi->populatePatchPopup(pop, 0);
@@ -387,7 +387,7 @@ void MidiTrackInfo::instrumentSelected(int n)
MidiChannel* midic = ((MidiTrack*)track)->channel();
if (midic == 0)
return;
- MidiOutPort* op = midic->port();
+ MidiOut* op = midic->port();
op->setInstrument(midiInstruments[n]);
}
@@ -436,8 +436,8 @@ void MidiTrackInfo::deviceIdChanged(int val)
MidiChannel* midic = ((MidiTrack*)track)->channel();
if (midic == 0)
return;
- MidiOutPort* op = midic->port();
- op->setDeviceId(val);
+// MidiOut* op = midic->port();
+//TODO op->setDeviceId(val);
}
//---------------------------------------------------------
@@ -643,10 +643,10 @@ void MidiChannelInfo::init(Track* t)
{
TrackInfo::init(t);
MidiChannel* midic = (MidiChannel*)t;
- MidiOutPort* op = midic->port();
- connect(op, SIGNAL(instrumentChanged()), SLOT(instrumentChanged()));
+ MidiOut* op = midic->port();
+//TODO connect(op, SIGNAL(instrumentChanged()), SLOT(instrumentChanged()));
connect(midic, SIGNAL(controllerChanged(int)), SLOT(controllerChanged(int)));
- portName->setText(op->name());
+ portName->setText(op->track->name());
MidiInstrument* mi = op->instrument();
int idx = 0;
int curIdx = 0;
@@ -666,7 +666,7 @@ void MidiChannelInfo::init(Track* t)
void MidiChannelInfo::instrumentSelected(int n)
{
MidiChannel* midic = (MidiChannel*)track;
- MidiOutPort* op = midic->port();
+ MidiOut* op = midic->port();
op->setInstrument(midiInstruments[n]);
}
@@ -677,7 +677,7 @@ void MidiChannelInfo::instrumentSelected(int n)
void MidiChannelInfo::instrumentChanged()
{
MidiChannel* midic = (MidiChannel*)track;
- MidiOutPort* op = midic->port();
+ MidiOut* op = midic->port();
MidiInstrument* mi = op->instrument();
int idx = 0;
for (iMidiInstrument i = midiInstruments.begin(); i != midiInstruments.end(); ++i, ++idx) {
@@ -695,7 +695,7 @@ void MidiChannelInfo::instrumentChanged()
void MidiChannelInfo::patchClicked()
{
MidiChannel* midic = (MidiChannel*)track;
- MidiOutPort* op = midic->port();
+ MidiOut* op = midic->port();
MidiInstrument* mi = op->instrument();
mi->populatePatchPopup(pop, 0);
@@ -715,7 +715,7 @@ void MidiChannelInfo::controllerChanged(int id)
{
if (id == CTRL_PROGRAM) {
MidiChannel* midic = (MidiChannel*)track;
- MidiOutPort* op = midic->port();
+ MidiOut* op = midic->port();
MidiInstrument* mi = op->instrument();
int val = midic->ctrlVal(id).i;
patch->setText(mi->getPatchName(midic->channelNo(), val));
diff --git a/muse/muse/audio.cpp b/muse/muse/audio.cpp
index 864f221d..beab01b8 100644
--- a/muse/muse/audio.cpp
+++ b/muse/muse/audio.cpp
@@ -345,9 +345,9 @@ void Audio::process(unsigned frames, int jackState)
startRolling();
}
- OutputList* ol = song->outputs();
if (idle || state == START_PLAY) {
// deliver silence
+ OutputList* ol = song->outputs();
for (iAudioOutput i = ol->begin(); i != ol->end(); ++i)
(*i)->silence(frames);
return;
@@ -433,14 +433,32 @@ void Audio::process(unsigned frames, int jackState)
}
}
- MidiOutPortList* mol = song->midiOutPorts();
- for (iMidiOutPort i = mol->begin(); i != mol->end(); ++i)
+ //-----------------------------------------
+ // process midi
+ //-----------------------------------------
+
+ SynthIList* sl = song->syntis();
+ {
+ MidiOutPortList* ol = song->midiOutPorts();
+ MidiInPortList* mil = song->midiInPorts();
+
+ for (iMidiOutPort i = ol->begin(); i != ol->end(); ++i)
audioDriver->startMidiCycle((*i)->jackPort(0));
+ for (iMidiInPort i = mil->begin(); i != mil->end(); ++i)
+ (*i)->beforeProcess();
+ for (iMidiOutPort i = ol->begin(); i != ol->end(); ++i)
+ (*i)->processMidi(_curTickPos, _nextTickPos, _pos.frame(), _pos.frame() + segmentSize);
+ for (iSynthI i = sl->begin(); i != sl->end(); ++i)
+ (*i)->processMidi(_curTickPos, _nextTickPos, _pos.frame(), _pos.frame() + segmentSize);
+ for (iMidiInPort i = mil->begin(); i != mil->end(); ++i)
+ (*i)->afterProcess();
+ }
- processMidi();
+ //-----------------------------------------
+ // process audio
+ //-----------------------------------------
GroupList* gl = song->groups();
- SynthIList* sl = song->syntis();
InputList* il = song->inputs();
WaveTrackList* wl = song->waves();
@@ -486,7 +504,9 @@ void Audio::process(unsigned frames, int jackState)
}
for (iAudioGroup i = gl->begin(); i != gl->end(); ++i)
(*i)->process();
- for (iAudioOutput i = ol->begin(); i != ol->end(); ++i)
+
+ OutputList* aol = song->outputs();
+ for (iAudioOutput i = aol->begin(); i != aol->end(); ++i)
(*i)->process();
if (_bounce == 1 && song->bounceTrack && song->bounceTrack->type() == Track::WAVE)
diff --git a/muse/muse/audio.h b/muse/muse/audio.h
index 19f76b9b..c6fef4c2 100644
--- a/muse/muse/audio.h
+++ b/muse/muse/audio.h
@@ -194,7 +194,6 @@ class Audio {
Pos endRecordPos;
void process(unsigned frames, int jackState);
- void processMidi();
bool sync(int state, unsigned frame);
void shutdown();
diff --git a/muse/muse/audiogroup.h b/muse/muse/audiogroup.h
index 6436ebd1..709166f5 100644
--- a/muse/muse/audiogroup.h
+++ b/muse/muse/audiogroup.h
@@ -31,7 +31,8 @@ class AudioGroup : public AudioTrack {
Q_OBJECT
public:
- AudioGroup() : AudioTrack(AUDIO_GROUP) {}
+ AudioGroup() : AudioTrack() {}
+ virtual TrackType type() const { return AUDIO_GROUP; }
virtual void read(QDomNode);
virtual void write(Xml&) const;
virtual bool hasAuxSend() const { return true; }
diff --git a/muse/muse/audioinput.cpp b/muse/muse/audioinput.cpp
index d4c6a12e..4ff3449b 100644
--- a/muse/muse/audioinput.cpp
+++ b/muse/muse/audioinput.cpp
@@ -28,7 +28,7 @@
//---------------------------------------------------------
AudioInput::AudioInput()
- : AudioTrack(AUDIO_INPUT)
+ : AudioTrack()
{
// set Default for Input Ports:
_mute = true;
diff --git a/muse/muse/audioinput.h b/muse/muse/audioinput.h
index 71998e13..ba8af1f6 100644
--- a/muse/muse/audioinput.h
+++ b/muse/muse/audioinput.h
@@ -35,6 +35,7 @@ class AudioInput : public AudioTrack {
public:
AudioInput();
virtual ~AudioInput();
+ virtual TrackType type() const { return AUDIO_INPUT; }
virtual void read(QDomNode);
virtual void write(Xml&) const;
diff --git a/muse/muse/audiooutput.cpp b/muse/muse/audiooutput.cpp
index 2899cf7d..dbf61af9 100644
--- a/muse/muse/audiooutput.cpp
+++ b/muse/muse/audiooutput.cpp
@@ -30,7 +30,7 @@
//---------------------------------------------------------
AudioOutput::AudioOutput()
- : AudioTrack(AUDIO_OUTPUT)
+ : AudioTrack()
{
_channels = 0;
setChannels(2);
diff --git a/muse/muse/audiooutput.h b/muse/muse/audiooutput.h
index cb7980f3..384b5bde 100644
--- a/muse/muse/audiooutput.h
+++ b/muse/muse/audiooutput.h
@@ -33,6 +33,7 @@ class AudioOutput : public AudioTrack {
public:
AudioOutput();
virtual ~AudioOutput();
+ virtual TrackType type() const { return AUDIO_OUTPUT; }
virtual void read(QDomNode);
virtual void write(Xml&) const;
diff --git a/muse/muse/audiotrack.cpp b/muse/muse/audiotrack.cpp
index e486b4b5..62fde5ca 100644
--- a/muse/muse/audiotrack.cpp
+++ b/muse/muse/audiotrack.cpp
@@ -34,8 +34,8 @@
// AudioTrack
//---------------------------------------------------------
-AudioTrack::AudioTrack(TrackType t)
- : Track(t)
+AudioTrack::AudioTrack()
+ : Track()
{
_tt = AL::FRAMES;
_prefader = false;
diff --git a/muse/muse/audiotrack.h b/muse/muse/audiotrack.h
index f6f5a89d..1dc77d65 100644
--- a/muse/muse/audiotrack.h
+++ b/muse/muse/audiotrack.h
@@ -63,7 +63,7 @@ class AudioTrack : public Track {
virtual void setAutoWrite(bool);
public:
- AudioTrack(TrackType t);
+ AudioTrack();
virtual ~AudioTrack();
bool readProperties(QDomNode);
diff --git a/muse/muse/ctrl/configmidictrl.cpp b/muse/muse/ctrl/configmidictrl.cpp
index 5aefcba3..9e01e029 100644
--- a/muse/muse/ctrl/configmidictrl.cpp
+++ b/muse/muse/ctrl/configmidictrl.cpp
@@ -23,6 +23,7 @@
#include "midioutport.h"
#include "midichannel.h"
#include "midictrl.h"
+#include "midiout.h"
#include "instruments/minstrument.h"
//---------------------------------------------------------
@@ -52,8 +53,8 @@ ConfigMidiCtrl::ConfigMidiCtrl(MidiTrack* t)
else if (track->type() == Track::MIDI_CHANNEL)
mc = (MidiChannel*)track;
if (mc) {
- MidiOutPort* mp = mc->port();
- portName->setText(mp->name());
+ MidiOut* mp = mc->port();
+ portName->setText(mp->track->name());
//
// populate popup with all controllers available for
// current instrument
@@ -148,7 +149,7 @@ void ConfigMidiCtrl::done(int code)
mc = (MidiChannel*)track;
if (mc) {
- MidiOutPort* port = mc->port();
+ MidiOut* port = mc->port();
ControllerNameList* cn = track->controllerNames();
MidiInstrument* instr = port->instrument();
MidiControllerList* mcl = instr->controller();
diff --git a/muse/muse/midi.cpp b/muse/muse/midi.cpp
index 0eaeceb4..fe9984d6 100644
--- a/muse/muse/midi.cpp
+++ b/muse/muse/midi.cpp
@@ -41,6 +41,7 @@
#include "midiinport.h"
#include "midioutport.h"
#include "midichannel.h"
+#include "instruments/minstrument.h"
extern void dump(const unsigned char* p, int n);
@@ -630,37 +631,3 @@ void Audio::initDevices()
}
}
-//---------------------------------------------------------
-// processMidi
-// - called from midiseq thread,
-// executed in audio thread
-// Process one time slice of midi events
-//---------------------------------------------------------
-
-void Audio::processMidi()
- {
- MidiInPortList* il = song->midiInPorts();
- for (iMidiInPort id = il->begin(); id != il->end(); ++id)
- (*id)->beforeProcess();
-
- MidiOutPortList* ol = song->midiOutPorts();
- for (iMidiOutPort id = ol->begin(); id != ol->end(); ++id) {
- (*id)->process(_curTickPos, _nextTickPos, _pos.frame(), _pos.frame() + segmentSize);
- }
- for (iMidiInPort id = il->begin(); id != il->end(); ++id) {
- MidiInPort* port = *id;
- //
- // process routing to synti
- //
- RouteList* rl = port->outRoutes();
- for (iRoute i = rl->begin(); i != rl->end(); ++i) {
- if (i->track->type() != Track::AUDIO_SOFTSYNTH)
- continue;
- SynthI* s = (SynthI*)(i->track);
- MPEventList* dl = s->playEvents();
- port->getEvents(0, 0, -1, dl);
- }
- port->afterProcess();
- }
- }
-
diff --git a/muse/muse/midichannel.cpp b/muse/muse/midichannel.cpp
index afec354c..40294b2a 100644
--- a/muse/muse/midichannel.cpp
+++ b/muse/muse/midichannel.cpp
@@ -25,13 +25,14 @@
#include "midichannel.h"
#include "midioutport.h"
#include "miditrack.h"
+#include "instruments/minstrument.h"
//---------------------------------------------------------
// MidiChannel
//---------------------------------------------------------
-MidiChannel::MidiChannel(MidiOutPort* p, int ch)
- : MidiTrackBase(MIDI_CHANNEL)
+MidiChannel::MidiChannel(MidiOut* p, int ch)
+ : MidiTrackBase()
{
_port = p;
_channelNo = ch;
@@ -88,7 +89,7 @@ void MidiChannel::read(QDomNode node)
printf("MusE:MidiChannel: unknown tag %s\n", tag.toLatin1().data());
node = node.nextSibling();
}
- MidiOutPort* op = port();
+ MidiOut* op = port();
if (op) {
MidiInstrument* mi = op->instrument();
int val = ctrlVal(CTRL_PROGRAM).i;
@@ -121,7 +122,7 @@ void MidiChannel::setUseDrumMap(bool val)
_useDrumMap = val;
if (_useDrumMap) {
int val = ctrlVal(CTRL_PROGRAM).i;
- MidiOutPort* op = port();
+ MidiOut* op = port();
MidiInstrument* mi = op->instrument();
DrumMap* dm = mi->getDrumMap(val);
if (dm == 0)
@@ -146,7 +147,7 @@ void MidiChannel::emitControllerChanged(int id)
{
if (id == CTRL_PROGRAM && _useDrumMap) {
int val = ctrlVal(id).i;
- MidiOutPort* op = port();
+ MidiOut* op = port();
MidiInstrument* mi = op->instrument();
DrumMap* dm = mi->getDrumMap(val);
if (dm == 0)
diff --git a/muse/muse/midichannel.h b/muse/muse/midichannel.h
index b4688375..8644c15e 100644
--- a/muse/muse/midichannel.h
+++ b/muse/muse/midichannel.h
@@ -23,6 +23,8 @@
#include "track.h"
+class MidiOut;
+
//---------------------------------------------------------
// MidiChannel
//---------------------------------------------------------
@@ -34,7 +36,7 @@ class MidiChannel : public MidiTrackBase {
DrumMap* _drumMap;
bool _useDrumMap;
- MidiOutPort* _port;
+ MidiOut* _port;
int _channelNo;
void clearDevice();
@@ -43,10 +45,11 @@ class MidiChannel : public MidiTrackBase {
void useDrumMapChanged(bool);
public:
- MidiChannel(MidiOutPort*, int);
+ MidiChannel(MidiOut*, int);
~MidiChannel();
+ virtual TrackType type() const { return MIDI_CHANNEL; }
- MidiOutPort* port() const { return _port; }
+ MidiOut* port() const { return _port; }
int channelNo() const { return _channelNo; }
virtual void write(Xml&) const;
diff --git a/muse/muse/midiedit/ctrledit.cpp b/muse/muse/midiedit/ctrledit.cpp
index 08c3a5c1..925f0247 100644
--- a/muse/muse/midiedit/ctrledit.cpp
+++ b/muse/muse/midiedit/ctrledit.cpp
@@ -91,8 +91,9 @@ void CtrlEdit::setCtrl(int id)
MidiChannel* mc = mt->channel();
if (mc) {
_ctrl = mc->getController(id);
- if (!_ctrl)
- _ctrl = mc->port()->getController(id);
+ if (!_ctrl) {
+ _ctrl = mc->port()->track->getController(id);
+ }
}
}
}
diff --git a/muse/muse/midiinport.cpp b/muse/muse/midiinport.cpp
index 42fe2677..ac55a813 100644
--- a/muse/muse/midiinport.cpp
+++ b/muse/muse/midiinport.cpp
@@ -34,7 +34,7 @@
//---------------------------------------------------------
MidiInPort::MidiInPort()
- : MidiTrackBase(MIDI_IN)
+ : MidiTrackBase()
{
_channels = 1;
recordRead = 0;
diff --git a/muse/muse/midiinport.h b/muse/muse/midiinport.h
index 5d0d8464..760ed7fe 100644
--- a/muse/muse/midiinport.h
+++ b/muse/muse/midiinport.h
@@ -40,6 +40,7 @@ class MidiInPort : public MidiTrackBase {
public:
MidiInPort();
~MidiInPort();
+ virtual TrackType type() const { return MIDI_IN; }
virtual void setName(const QString& s);
virtual void write(Xml&) const;
diff --git a/muse/muse/midiout.cpp b/muse/muse/midiout.cpp
new file mode 100644
index 00000000..c499ba6b
--- /dev/null
+++ b/muse/muse/midiout.cpp
@@ -0,0 +1,389 @@
+//=============================================================================
+// MusE
+// Linux Music Editor
+// $Id:$
+//
+// Copyright (C) 2006 by 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.
+//=============================================================================
+
+#include "midiout.h"
+#include "midictrl.h"
+#include "track.h"
+#include "al/tempo.h"
+#include "event.h"
+#include "midichannel.h"
+#include "sync.h"
+#include "audio.h"
+#include "gconfig.h"
+
+static const unsigned char mmcDeferredPlayMsg[] = { 0x7f, 0x7f, 0x06, 0x03 };
+
+//---------------------------------------------------------
+// sendGmOn
+// send GM-On message to midi device and keep track
+// of device state
+//---------------------------------------------------------
+
+void MidiOut::sendGmOn()
+ {
+ sendSysex(gmOnMsg, gmOnMsgLen);
+ track->setHwCtrlState(CTRL_PROGRAM, 0);
+ track->setHwCtrlState(CTRL_PITCH, 0);
+ track->setHwCtrlState(CTRL_VOLUME, 100);
+ track->setHwCtrlState(CTRL_PANPOT, 64);
+ track->setHwCtrlState(CTRL_REVERB_SEND, 40);
+ track->setHwCtrlState(CTRL_CHORUS_SEND, 0);
+ track->setMeter(0, 0.0);
+ }
+
+//---------------------------------------------------------
+// sendGsOn
+// send Roland GS-On message to midi device and keep track
+// of device state
+//---------------------------------------------------------
+
+void MidiOut::sendGsOn()
+ {
+ static unsigned char data2[] = { 0x41, 0x10, 0x42, 0x12, 0x40, 0x01, 0x33, 0x50, 0x3c };
+ static unsigned char data3[] = { 0x41, 0x10, 0x42, 0x12, 0x40, 0x01, 0x34, 0x50, 0x3b };
+
+ sendSysex(data2, sizeof(data2));
+ sendSysex(data3, sizeof(data3));
+ }
+
+//---------------------------------------------------------
+// sendXgOn
+// send Yamaha XG-On message to midi device and keep track
+// of device state
+//---------------------------------------------------------
+
+void MidiOut::sendXgOn()
+ {
+ sendSysex(xgOnMsg, xgOnMsgLen);
+ track->setHwCtrlState(CTRL_PROGRAM, 0);
+ track->setHwCtrlState(CTRL_MODULATION, 0);
+ track->setHwCtrlState(CTRL_PORTAMENTO_TIME, 0);
+ track->setHwCtrlState(CTRL_VOLUME, 0x64);
+ track->setHwCtrlState(CTRL_PANPOT, 0x40);
+ track->setHwCtrlState(CTRL_EXPRESSION, 0x7f);
+ track->setHwCtrlState(CTRL_SUSTAIN, 0x0);
+ track->setHwCtrlState(CTRL_PORTAMENTO, 0x0);
+ track->setHwCtrlState(CTRL_SOSTENUTO, 0x0);
+ track->setHwCtrlState(CTRL_SOFT_PEDAL, 0x0);
+ track->setHwCtrlState(CTRL_HARMONIC_CONTENT, 0x40);
+ track->setHwCtrlState(CTRL_RELEASE_TIME, 0x40);
+ track->setHwCtrlState(CTRL_ATTACK_TIME, 0x40);
+ track->setHwCtrlState(CTRL_BRIGHTNESS, 0x40);
+ track->setHwCtrlState(CTRL_REVERB_SEND, 0x28);
+ track->setHwCtrlState(CTRL_CHORUS_SEND, 0x0);
+ track->setHwCtrlState(CTRL_VARIATION_SEND, 0x0);
+ track->setMeter(0, 0.0);
+ }
+
+//---------------------------------------------------------
+// sendSysex
+// send SYSEX message to midi device
+//---------------------------------------------------------
+
+void MidiOut::sendSysex(const unsigned char* p, int n)
+ {
+ MidiEvent event(0, ME_SYSEX, p, n);
+ track->routeEvent(event);
+ }
+
+//---------------------------------------------------------
+// sendStart
+//---------------------------------------------------------
+
+void MidiOut::sendStart()
+ {
+ MidiEvent event(0, 0, ME_START, 0, 0);
+ track->routeEvent(event);
+ }
+
+//---------------------------------------------------------
+// sendStop
+//---------------------------------------------------------
+
+void MidiOut::sendStop()
+ {
+ MidiEvent event(0, 0, ME_STOP, 0, 0);
+ track->routeEvent(event);
+ }
+
+//---------------------------------------------------------
+// sendClock
+//---------------------------------------------------------
+
+void MidiOut::sendClock()
+ {
+ MidiEvent event(0, 0, ME_CLOCK, 0, 0);
+ track->routeEvent(event);
+ }
+
+//---------------------------------------------------------
+// sendContinue
+//---------------------------------------------------------
+
+void MidiOut::sendContinue()
+ {
+ MidiEvent event(0, 0, ME_CONTINUE, 0, 0);
+ track->routeEvent(event);
+ }
+
+//---------------------------------------------------------
+// sendSongpos
+//---------------------------------------------------------
+
+void MidiOut::sendSongpos(int pos)
+ {
+ MidiEvent event(0, 0, ME_SONGPOS, pos, 0);
+ track->routeEvent(event);
+ }
+
+//---------------------------------------------------------
+// playMidiEvent
+// called from GUI
+//---------------------------------------------------------
+
+void MidiOut::playMidiEvent(MidiEvent* ev)
+ {
+ if (eventFifo.put(*ev))
+ printf("MidiPort::playMidiEvent(): port overflow, drop event\n");
+ }
+
+//---------------------------------------------------------
+// seek
+//---------------------------------------------------------
+
+void MidiOut::seek(unsigned tickPos, unsigned framePos)
+ {
+ if (genMCSync && track->sendSync()) {
+ int beat = (tickPos * 4) / config.division;
+ sendStop();
+ sendSongpos(beat);
+ sendContinue();
+ }
+ if (track->mute())
+ return;
+
+// if (pos == 0 && !song->record())
+// audio->initDevices();
+
+ //---------------------------------------------------
+ // stop all notes
+ //---------------------------------------------------
+
+ for (iMPEvent i = _schedEvents.begin(); i != _schedEvents.end(); ++i) {
+ MidiEvent ev = *i;
+ if (ev.isNoteOff()) {
+ ev.setTime(framePos);
+ track->routeEvent(ev);
+ }
+ }
+ _schedEvents.clear();
+
+ //---------------------------------------------------
+ // set all controller
+ //---------------------------------------------------
+
+ for (int ch = 0; ch < MIDI_CHANNELS; ++ch) {
+ MidiChannel* mc = channel(ch);
+ if (mc->mute() || mc->noInRoute() || !mc->autoRead())
+ continue;
+ CtrlList* cll = mc->controller();
+ for (iCtrl ivl = cll->begin(); ivl != cll->end(); ++ivl) {
+ Ctrl* c = ivl->second;
+ int val = c->value(tickPos).i;
+ if (val != CTRL_VAL_UNKNOWN && val != c->curVal().i) {
+ track->routeEvent(MidiEvent(0, ch, ME_CONTROLLER, c->id(), val));
+ }
+ }
+ }
+ }
+
+//---------------------------------------------------------
+// stop
+//---------------------------------------------------------
+
+void MidiOut::stop()
+ {
+ int frame = AL::tempomap.tick2frame(audio->curTickPos());
+
+ //---------------------------------------------------
+ // stop all notes
+ //---------------------------------------------------
+
+ for (iMPEvent i = _schedEvents.begin(); i != _schedEvents.end(); ++i) {
+ MidiEvent ev = *i;
+ if (ev.isNoteOff()) {
+ ev.setTime(frame);
+ track->routeEvent(ev);
+ }
+ }
+ _schedEvents.clear();
+
+ //---------------------------------------------------
+ // reset sustain
+ //---------------------------------------------------
+
+ for (int ch = 0; ch < MIDI_CHANNELS; ++ch) {
+ MidiChannel* mc = channel(ch);
+ if (mc->noInRoute())
+ continue;
+ if (mc->hwCtrlState(CTRL_SUSTAIN) != CTRL_VAL_UNKNOWN) {
+ MidiEvent ev(0, 0, ME_CONTROLLER, CTRL_SUSTAIN, 0);
+ ev.setChannel(mc->channelNo());
+ track->routeEvent(ev);
+ }
+ }
+ if (track->sendSync()) {
+ if (genMMC) {
+ unsigned char mmcPos[] = {
+ 0x7f, 0x7f, 0x06, 0x44, 0x06, 0x01,
+ 0, 0, 0, 0, 0
+ };
+ MTC mtc(double(frame) / double(AL::sampleRate));
+ mmcPos[6] = mtc.h() | (AL::mtcType << 5);
+ mmcPos[7] = mtc.m();
+ mmcPos[8] = mtc.s();
+ mmcPos[9] = mtc.f();
+ mmcPos[10] = mtc.sf();
+//TODO sendSysex(mmcStopMsg, sizeof(mmcStopMsg));
+ sendSysex(mmcPos, sizeof(mmcPos));
+ }
+ if (genMCSync) { // Midi Clock
+ // send STOP and
+ // "set song position pointer"
+ sendStop();
+ sendSongpos(audio->curTickPos() * 4 / config.division);
+ }
+ }
+ }
+
+//---------------------------------------------------------
+// start
+//---------------------------------------------------------
+
+void MidiOut::start()
+ {
+ if (!(genMMC || genMCSync || track->sendSync()))
+ return;
+ if (genMMC)
+ sendSysex(mmcDeferredPlayMsg, sizeof(mmcDeferredPlayMsg));
+ if (genMCSync) {
+ if (audio->curTickPos())
+ sendContinue();
+ else
+ sendStart();
+ }
+ }
+
+//---------------------------------------------------------
+// reset
+//---------------------------------------------------------
+
+void MidiOut::reset()
+ {
+/* TODO
+ MidiEvent ev;
+ ev.setType(0x90);
+ for (int chan = 0; chan < MIDI_CHANNELS; ++chan) {
+ ev.setChannel(chan);
+ for (int pitch = 0; pitch < 128; ++pitch) {
+ ev.setA(pitch);
+ ev.setB(0);
+ mp->putEvent(ev);
+ }
+ }
+*/
+ }
+
+//-------------------------------------------------------------------
+// process
+// Collect all midi events for the current process cycle and put
+// into _schedEvents queue. For note on events create the proper
+// note off events. The note off events maybe played after the
+// current process cycle.
+// From _schedEvents queue copy all events for the current cycle
+// to all output routes. Events routed to ALSA go into the
+// _playEvents queue which is processed by the MidiSeq thread.
+//-------------------------------------------------------------------
+
+void MidiOut::processMidi(MPEventList& el, unsigned fromTick, unsigned toTick, unsigned fromFrame, unsigned toFrame)
+ {
+ while (!eventFifo.isEmpty())
+ el.add(eventFifo.get());
+
+ // collect port controller
+ if (fromTick != toTick) { // if rolling
+ CtrlList* cl = track->controller();
+ for (iCtrl ic = cl->begin(); ic != cl->end(); ++ic) {
+ Ctrl* c = ic->second;
+ iCtrlVal is = c->lower_bound(fromTick);
+ iCtrlVal ie = c->lower_bound(toTick);
+ for (iCtrlVal ic = is; ic != ie; ++ic) {
+ unsigned frame = AL::tempomap.tick2frame(ic->first);
+ Event ev(Controller);
+ ev.setA(c->id());
+ ev.setB(ic->second.i);
+ el.add(MidiEvent(frame, -1, ev));
+ }
+ }
+ }
+
+ for (int ch = 0; ch < MIDI_CHANNELS; ++ch) {
+ MidiChannel* mc = channel(ch);
+
+ if (mc->mute() || mc->noInRoute())
+ continue;
+ // collect channel controller
+ if (fromTick != toTick) {
+ CtrlList* cl = mc->controller();
+ for (iCtrl ic = cl->begin(); ic != cl->end(); ++ic) {
+ Ctrl* c = ic->second;
+ iCtrlVal is = c->lower_bound(fromTick);
+ iCtrlVal ie = c->lower_bound(toTick);
+ for (; is != ie; ++is) {
+ unsigned frame = AL::tempomap.tick2frame(is->first);
+ Event ev(Controller);
+ ev.setA(c->id());
+ ev.setB(is->second.i);
+ el.add(MidiEvent(frame, ch, ev));
+ }
+ }
+ }
+
+ // Collect midievents from all input tracks for outport
+ RouteList* rl = mc->inRoutes();
+ for (iRoute i = rl->begin(); i != rl->end(); ++i) {
+ MidiTrackBase* track = (MidiTrackBase*)i->track;
+ if (track->isMute())
+ continue;
+ MPEventList ell;
+ track->getEvents(fromTick, toTick, 0, &ell);
+ int velo = 0;
+ for (iMPEvent i = ell.begin(); i != ell.end(); ++i) {
+ MidiEvent ev(*i);
+ ev.setChannel(ch);
+ el.insert(ev);
+ if (ev.type() == ME_NOTEON)
+ velo += ev.dataB();
+ }
+ mc->addMidiMeter(velo);
+ }
+ }
+ }
+
diff --git a/muse/muse/midiout.h b/muse/muse/midiout.h
new file mode 100644
index 00000000..8fffb8fe
--- /dev/null
+++ b/muse/muse/midiout.h
@@ -0,0 +1,74 @@
+//=============================================================================
+// MusE
+// Linux Music Editor
+// $Id:$
+//
+// Copyright (C) 2006 by 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 __MIDIOUT_H__
+#define __MIDIOUT_H__
+
+#include "al/al.h"
+#include "globaldefs.h"
+#include "midievent.h"
+#include "midififo.h"
+
+class Track;
+class MidiInstrument;
+class MidiChannel;
+
+//---------------------------------------------------------
+// MidiOut
+//---------------------------------------------------------
+
+class MidiOut
+ {
+ public:
+ Track* track;
+ MidiInstrument* _instrument;
+ MidiChannel* _channel[MIDI_CHANNELS];
+ MPEventList _schedEvents; // scheduled events by process()
+
+ // fifo for midi events send from gui
+ // direct to midi port:
+
+ MidiFifo eventFifo;
+
+ void processMidi(MPEventList& el, unsigned fromTick, unsigned toTick,
+ unsigned fromFrame, unsigned toFrame);
+ MidiChannel* channel(int n) { return _channel[n]; }
+ MidiInstrument* instrument() { return _instrument; }
+ void setInstrument(MidiInstrument* i) { _instrument = i; }
+
+ void seek(unsigned, unsigned);
+ void stop();
+ void start();
+ void reset();
+
+ void sendSysex(const unsigned char*, int);
+ void sendSongpos(int);
+ void sendGmOn();
+ void sendGsOn();
+ void sendXgOn();
+ void sendStart();
+ void sendStop();
+ void sendContinue();
+ void sendClock();
+ void playMidiEvent(MidiEvent* ev);
+ };
+
+#endif
+
diff --git a/muse/muse/midioutport.cpp b/muse/muse/midioutport.cpp
index 471eed3d..3b5a8ba1 100644
--- a/muse/muse/midioutport.cpp
+++ b/muse/muse/midioutport.cpp
@@ -32,21 +32,20 @@
#include "midiseq.h"
#include "sync.h"
#include "gconfig.h"
-
-static const unsigned char mmcDeferredPlayMsg[] = { 0x7f, 0x7f, 0x06, 0x03 };
+#include "instruments/minstrument.h"
//---------------------------------------------------------
// MidiOutPort
//---------------------------------------------------------
MidiOutPort::MidiOutPort()
- : MidiTrackBase(MIDI_OUT)
+ : MidiTrackBase()
{
+ track = this;
_instrument = genericMidiInstrument;
for (int ch = 0; ch < MIDI_CHANNELS; ++ch)
_channel[ch] = new MidiChannel(this, ch);
- _sendSync = false;
- _deviceId = 127; // all
+ setDeviceId(127); // all
addMidiController(_instrument, CTRL_MASTER_VOLUME);
_channels = 1;
}
@@ -90,8 +89,8 @@ void MidiOutPort::write(Xml& xml) const
if (!_channel[i]->noInRoute())
_channel[i]->write(xml);
}
- xml.intTag("sendSync", _sendSync);
- xml.intTag("deviceId", _deviceId);
+ xml.intTag("sendSync", sendSync());
+ xml.intTag("deviceId", deviceId());
xml.etag("MidiOutPort");
}
@@ -113,247 +112,15 @@ void MidiOutPort::read(QDomNode node)
_instrument = registerMidiInstrument(iname);
}
else if (tag == "sendSync")
- _sendSync = e.text().toInt();
+ setSendSync(e.text().toInt());
else if (tag == "deviceId")
- _deviceId = e.text().toInt();
+ setDeviceId(e.text().toInt());
else if (MidiTrackBase::readProperties(node))
printf("MusE:MidiOutPort: unknown tag %s\n", tag.toLatin1().data());
}
}
//---------------------------------------------------------
-// sendGmOn
-// send GM-On message to midi device and keep track
-// of device state
-//---------------------------------------------------------
-
-void MidiOutPort::sendGmOn()
- {
- sendSysex(gmOnMsg, gmOnMsgLen);
- setHwCtrlState(CTRL_PROGRAM, 0);
- setHwCtrlState(CTRL_PITCH, 0);
- setHwCtrlState(CTRL_VOLUME, 100);
- setHwCtrlState(CTRL_PANPOT, 64);
- setHwCtrlState(CTRL_REVERB_SEND, 40);
- setHwCtrlState(CTRL_CHORUS_SEND, 0);
- _meter[0] = 0.0f;
- }
-
-//---------------------------------------------------------
-// sendGsOn
-// send Roland GS-On message to midi device and keep track
-// of device state
-//---------------------------------------------------------
-
-void MidiOutPort::sendGsOn()
- {
- static unsigned char data2[] = { 0x41, 0x10, 0x42, 0x12, 0x40, 0x01, 0x33, 0x50, 0x3c };
- static unsigned char data3[] = { 0x41, 0x10, 0x42, 0x12, 0x40, 0x01, 0x34, 0x50, 0x3b };
-
- sendSysex(data2, sizeof(data2));
- sendSysex(data3, sizeof(data3));
- }
-
-//---------------------------------------------------------
-// sendXgOn
-// send Yamaha XG-On message to midi device and keep track
-// of device state
-//---------------------------------------------------------
-
-void MidiOutPort::sendXgOn()
- {
- sendSysex(xgOnMsg, xgOnMsgLen);
- setHwCtrlState(CTRL_PROGRAM, 0);
- setHwCtrlState(CTRL_MODULATION, 0);
- setHwCtrlState(CTRL_PORTAMENTO_TIME, 0);
- setHwCtrlState(CTRL_VOLUME, 0x64);
- setHwCtrlState(CTRL_PANPOT, 0x40);
- setHwCtrlState(CTRL_EXPRESSION, 0x7f);
- setHwCtrlState(CTRL_SUSTAIN, 0x0);
- setHwCtrlState(CTRL_PORTAMENTO, 0x0);
- setHwCtrlState(CTRL_SOSTENUTO, 0x0);
- setHwCtrlState(CTRL_SOFT_PEDAL, 0x0);
- setHwCtrlState(CTRL_HARMONIC_CONTENT, 0x40);
- setHwCtrlState(CTRL_RELEASE_TIME, 0x40);
- setHwCtrlState(CTRL_ATTACK_TIME, 0x40);
- setHwCtrlState(CTRL_BRIGHTNESS, 0x40);
- setHwCtrlState(CTRL_REVERB_SEND, 0x28);
- setHwCtrlState(CTRL_CHORUS_SEND, 0x0);
- setHwCtrlState(CTRL_VARIATION_SEND, 0x0);
- _meter[0] = 0.0f;
- }
-
-//---------------------------------------------------------
-// sendSysex
-// send SYSEX message to midi device
-//---------------------------------------------------------
-
-void MidiOutPort::sendSysex(const unsigned char* p, int n)
- {
- MidiEvent event(0, ME_SYSEX, p, n);
- routeEvent(event);
- }
-
-//---------------------------------------------------------
-// sendStart
-//---------------------------------------------------------
-
-void MidiOutPort::sendStart()
- {
- MidiEvent event(0, 0, ME_START, 0, 0);
- routeEvent(event);
- }
-
-//---------------------------------------------------------
-// sendStop
-//---------------------------------------------------------
-
-void MidiOutPort::sendStop()
- {
- MidiEvent event(0, 0, ME_STOP, 0, 0);
- routeEvent(event);
- }
-
-//---------------------------------------------------------
-// sendClock
-//---------------------------------------------------------
-
-void MidiOutPort::sendClock()
- {
- MidiEvent event(0, 0, ME_CLOCK, 0, 0);
- routeEvent(event);
- }
-
-//---------------------------------------------------------
-// sendContinue
-//---------------------------------------------------------
-
-void MidiOutPort::sendContinue()
- {
- MidiEvent event(0, 0, ME_CONTINUE, 0, 0);
- routeEvent(event);
- }
-
-//---------------------------------------------------------
-// sendSongpos
-//---------------------------------------------------------
-
-void MidiOutPort::sendSongpos(int pos)
- {
- MidiEvent event(0, 0, ME_SONGPOS, pos, 0);
- routeEvent(event);
- }
-
-//---------------------------------------------------------
-// playMidiEvent
-// called from GUI
-//---------------------------------------------------------
-
-void MidiOutPort::playMidiEvent(MidiEvent* ev)
- {
- if (eventFifo.put(*ev))
- printf("MidiPort::playMidiEvent(): port overflow, drop event\n");
- }
-
-//-------------------------------------------------------------------
-// process
-// Collect all midi events for the current process cycle and put
-// into _schedEvents queue. For note on events create the proper
-// note off events. The note off events maybe played after the
-// current process cycle.
-// From _schedEvents queue copy all events for the current cycle
-// to all output routes. Events routed to ALSA go into the
-// _playEvents queue which is processed by the MidiSeq thread.
-//-------------------------------------------------------------------
-
-void MidiOutPort::process(unsigned fromTick, unsigned toTick, unsigned fromFrame, unsigned toFrame)
- {
- if (mute())
- return;
-
- MPEventList el;
- while (!eventFifo.isEmpty())
- el.add(eventFifo.get());
-
- // collect port controller
- if (fromTick != toTick) { // if rolling
- CtrlList* cl = controller();
- for (iCtrl ic = cl->begin(); ic != cl->end(); ++ic) {
- Ctrl* c = ic->second;
- iCtrlVal is = c->lower_bound(fromTick);
- iCtrlVal ie = c->lower_bound(toTick);
- for (iCtrlVal ic = is; ic != ie; ++ic) {
- unsigned frame = AL::tempomap.tick2frame(ic->first);
- Event ev(Controller);
- ev.setA(c->id());
- ev.setB(ic->second.i);
- el.add(MidiEvent(frame, -1, ev));
- }
- }
- }
-
- for (int ch = 0; ch < MIDI_CHANNELS; ++ch) {
- MidiChannel* mc = channel(ch);
-
- if (mc->mute() || mc->noInRoute())
- continue;
- // collect channel controller
- if (fromTick != toTick) {
- CtrlList* cl = mc->controller();
- for (iCtrl ic = cl->begin(); ic != cl->end(); ++ic) {
- Ctrl* c = ic->second;
- iCtrlVal is = c->lower_bound(fromTick);
- iCtrlVal ie = c->lower_bound(toTick);
- for (; is != ie; ++is) {
- unsigned frame = AL::tempomap.tick2frame(is->first);
- Event ev(Controller);
- ev.setA(c->id());
- ev.setB(is->second.i);
- el.add(MidiEvent(frame, ch, ev));
-printf("add controller %d %d %d\n", fromFrame, frame, toFrame);
- }
- }
- }
-
- // Collect midievents from all input tracks for outport
- RouteList* rl = mc->inRoutes();
- for (iRoute i = rl->begin(); i != rl->end(); ++i) {
- MidiTrackBase* track = (MidiTrackBase*)i->track;
- if (track->isMute())
- continue;
- MPEventList ell;
- track->getEvents(fromTick, toTick, 0, &ell);
- int velo = 0;
- for (iMPEvent i = ell.begin(); i != ell.end(); ++i) {
- MidiEvent ev(*i);
- ev.setChannel(ch);
- el.insert(ev);
- if (ev.type() == ME_NOTEON)
- velo += ev.dataB();
- }
- mc->addMidiMeter(velo);
- }
- }
- pipeline()->apply(fromTick, toTick, &el, &_schedEvents);
-
- //
- // route events to destination
- //
-
- int portVelo = 0;
- iMPEvent i = _schedEvents.begin();
- for (; i != _schedEvents.end(); ++i) {
- if (i->time() >= toFrame)
- break;
- routeEvent(*i);
- if (i->type() == ME_NOTEON)
- portVelo += i->dataB();
- }
- _schedEvents.erase(_schedEvents.begin(), i);
- addMidiMeter(portVelo);
- }
-
-//---------------------------------------------------------
// routeEvent
//---------------------------------------------------------
@@ -389,10 +156,12 @@ void MidiOutPort::routeEvent(const MidiEvent& event)
case Route::MIDIPORT:
queueAlsaEvent(event);
break;
+#if 0
case Route::SYNTIPORT:
case Route::TRACK:
((SynthI*)(r->track))->playEvents()->insert(event);
break;
+#endif
case Route::JACKMIDIPORT:
queueJackEvent(event);
break;
@@ -434,7 +203,7 @@ void MidiOutPort::queueAlsaEvent(const MidiEvent& ev)
unsigned char sysex[] = {
0x7f, 0x7f, 0x04, 0x01, 0x00, 0x00
};
- sysex[1] = _deviceId;
+ sysex[1] = deviceId();
sysex[4] = b & 0x7f;
sysex[5] = (b >> 7) & 0x7f;
_playEvents.insert(MidiEvent(t, ME_SYSEX, sysex, 6));
@@ -524,7 +293,7 @@ void MidiOutPort::queueJackEvent(const MidiEvent& ev)
unsigned char sysex[] = {
0x7f, 0x7f, 0x04, 0x01, 0x00, 0x00
};
- sysex[1] = _deviceId;
+ sysex[1] = deviceId();
sysex[4] = b & 0x7f;
sysex[5] = (b >> 7) & 0x7f;
JO(MidiEvent(t, ME_SYSEX, sysex, 6));
@@ -604,16 +373,7 @@ void MidiOutPort::setInstrument(MidiInstrument* i)
emit instrumentChanged();
}
-//---------------------------------------------------------
-// setSendSync
-//---------------------------------------------------------
-
-void MidiOutPort::setSendSync(bool val)
- {
- _sendSync = val;
- emit sendSyncChanged(val);
- }
-
+#if 0 //TODO
//---------------------------------------------------------
// seek
//---------------------------------------------------------
@@ -763,6 +523,7 @@ void MidiOutPort::reset()
}
*/
}
+#endif
#if 0
//---------------------------------------------------------
@@ -798,4 +559,42 @@ void MidiSeq::processMidiClock()
}
#endif
+//-------------------------------------------------------------------
+// process
+// Collect all midi events for the current process cycle and put
+// into _schedEvents queue. For note on events create the proper
+// note off events. The note off events maybe played after the
+// current process cycle.
+// From _schedEvents queue copy all events for the current cycle
+// to all output routes. Events routed to ALSA go into the
+// _playEvents queue which is processed by the MidiSeq thread.
+//-------------------------------------------------------------------
+
+void MidiOutPort::processMidi(unsigned fromTick, unsigned toTick, unsigned fromFrame, unsigned toFrame)
+ {
+ if (track->mute())
+ return;
+
+ MPEventList el;
+ MidiOut::processMidi(el, fromTick, toTick, fromFrame, toFrame);
+
+ pipeline()->apply(fromTick, toTick, &el, &_schedEvents);
+
+ //
+ // route events to destination
+ //
+
+ int portVelo = 0;
+ iMPEvent i = _schedEvents.begin();
+ for (; i != _schedEvents.end(); ++i) {
+ if (i->time() >= toFrame)
+ break;
+ routeEvent(*i);
+ if (i->type() == ME_NOTEON)
+ portVelo += i->dataB();
+ }
+ _schedEvents.erase(_schedEvents.begin(), i);
+ addMidiMeter(portVelo);
+ }
+
diff --git a/muse/muse/midioutport.h b/muse/muse/midioutport.h
index bb9552df..0d28c923 100644
--- a/muse/muse/midioutport.h
+++ b/muse/muse/midioutport.h
@@ -22,39 +22,28 @@
#define __MIDIOUTPORT_H__
#include "track.h"
+#include "midiout.h"
//---------------------------------------------------------
// MidiOutPort
//---------------------------------------------------------
-class MidiOutPort : public MidiTrackBase {
+class MidiOutPort : public MidiTrackBase, public MidiOut {
Q_OBJECT
- MidiInstrument* _instrument;
- MidiChannel* _channel[MIDI_CHANNELS];
-
- bool _sendSync; // this port sends mtc/mmc events
- int _deviceId; // 0-126; 127 == all
-
- MPEventList _schedEvents; // scheduled events by process()
MPEventList _playEvents; // event queue for MidiSeq
- // fifo for midi events send from gui
- // direct to midi port:
-
- MidiFifo eventFifo;
-
void routeEvent(const MidiEvent&);
void queueAlsaEvent(const MidiEvent& event);
void queueJackEvent(const MidiEvent& event);
signals:
void instrumentChanged();
- void sendSyncChanged(bool);
public:
MidiOutPort();
~MidiOutPort();
+ virtual TrackType type() const { return MIDI_OUT; }
MidiChannel* channel(int n) { return _channel[n]; }
@@ -64,42 +53,16 @@ class MidiOutPort : public MidiTrackBase {
virtual bool isMute() const { return _mute; }
virtual Part* newPart(Part*, bool) { return 0; }
- MidiInstrument* instrument() const { return _instrument; }
+ MidiInstrument* instrument() const { return _instrument; }
void setInstrument(MidiInstrument* i);
bool guiVisible() const;
bool hasGui() const;
-// void putEvent(const MidiEvent&);
-
MPEventList* playEvents() { return &_playEvents; }
- void process(unsigned fromTick, unsigned toTick, unsigned fromFrame, unsigned toFrame);
-
- void playMidiEvent(MidiEvent*);
-
- void sendSysex(const unsigned char*, int);
- void sendSongpos(int);
- void sendGmOn();
- void sendGsOn();
- void sendXgOn();
- void sendStart();
- void sendStop();
- void sendContinue();
- void sendClock();
-
- bool sendSync() const { return _sendSync; }
- void setSendSync(bool val);
-
- int deviceId() const { return _deviceId; }
- void setDeviceId(int val) { _deviceId = val; }
-
- void seek(unsigned, unsigned);
- void stop();
- void start();
- void reset();
-
void playAlsaEvent(const MidiEvent& event) const;
+ void processMidi(unsigned fromTick, unsigned toTick, unsigned fromFrame, unsigned toFrame);
};
#endif
diff --git a/muse/muse/midisynti.cpp b/muse/muse/midisynti.cpp
index 9a420da3..d8b8191b 100644
--- a/muse/muse/midisynti.cpp
+++ b/muse/muse/midisynti.cpp
@@ -30,7 +30,7 @@
//---------------------------------------------------------
MidiSynti::MidiSynti()
- : MidiTrackBase(MIDI_SYNTI)
+ : MidiTrackBase()
{
_synti = 0;
init();
diff --git a/muse/muse/midisynti.h b/muse/muse/midisynti.h
index 95eac83c..4e3afe62 100644
--- a/muse/muse/midisynti.h
+++ b/muse/muse/midisynti.h
@@ -35,6 +35,8 @@ class MidiSynti : public MidiTrackBase {
public:
MidiSynti();
virtual ~MidiSynti();
+ virtual TrackType type() const { return MIDI_SYNTI; }
+
void init();
virtual void read(QDomNode);
diff --git a/muse/muse/miditrack.cpp b/muse/muse/miditrack.cpp
index 6f621dc8..f1c7c7c2 100644
--- a/muse/muse/miditrack.cpp
+++ b/muse/muse/miditrack.cpp
@@ -34,7 +34,7 @@
//---------------------------------------------------------
MidiTrack::MidiTrack()
- : MidiTrackBase(MIDI)
+ : MidiTrackBase()
{
init();
_events = new EventList;
diff --git a/muse/muse/miditrack.h b/muse/muse/miditrack.h
index 6f15831c..e0ade62d 100644
--- a/muse/muse/miditrack.h
+++ b/muse/muse/miditrack.h
@@ -53,8 +53,11 @@ class MidiTrack : public MidiTrackBase {
public:
MidiTrack();
virtual ~MidiTrack();
- void init();
+ virtual TrackType type() const { return MIDI; }
+
void clone(MidiTrack*);
+
+ void init();
MidiChannel* channel() const;
void changeDrumMap() const;
diff --git a/muse/muse/mixer/astrip.cpp b/muse/muse/mixer/astrip.cpp
index c6c2ec52..c7a6c071 100644
--- a/muse/muse/mixer/astrip.cpp
+++ b/muse/muse/mixer/astrip.cpp
@@ -193,14 +193,20 @@ AudioStrip::AudioStrip(Mixer* m, AudioTrack* t, bool align)
//---------------------------------------------------
QHBoxLayout* rBox = new QHBoxLayout(0);
- iR = new QToolButton(this);
- iR->setFont(config.fonts[1]);
- iR->setFixedWidth((STRIP_WIDTH-4)/2);
- iR->setText(tr("iR"));
- iR->setCheckable(false);
- iR->setToolTip(tr("input routing"));
- rBox->addWidget(iR);
- connect(iR, SIGNAL(pressed()), SLOT(iRoutePressed()));
+
+ if (track->type() == Track::AUDIO_SOFTSYNTH) {
+ rBox->addStretch(100);
+ }
+ else {
+ iR = new QToolButton(this);
+ iR->setFont(config.fonts[1]);
+ iR->setFixedWidth((STRIP_WIDTH-4)/2);
+ iR->setText(tr("iR"));
+ iR->setCheckable(false);
+ iR->setToolTip(tr("input routing"));
+ rBox->addWidget(iR);
+ connect(iR, SIGNAL(pressed()), SLOT(iRoutePressed()));
+ }
oR = new QToolButton(this);
oR->setFont(config.fonts[1]);
oR->setFixedWidth((STRIP_WIDTH-4)/2);
@@ -717,10 +723,6 @@ void AudioStrip::iRoutePressed()
addGroupPorts(t, &pup, irl);
addSyntiPorts(t, &pup, irl);
break;
- case Track::AUDIO_SOFTSYNTH:
- addMidiOutPorts(t, &pup, irl);
- addMidiInPorts(t, &pup, irl);
- break;
}
if (pup.isEmpty())
return;
diff --git a/muse/muse/mixer/mstrip.cpp b/muse/muse/mixer/mstrip.cpp
index 23b873c2..bb6a0d34 100644
--- a/muse/muse/mixer/mstrip.cpp
+++ b/muse/muse/mixer/mstrip.cpp
@@ -32,6 +32,95 @@
enum { KNOB_PAN, KNOB_CHOR_SEND, KNOB_VAR_SEND, KNOB_REV_SEND };
//---------------------------------------------------------
+// addSyntiPorts
+//---------------------------------------------------------
+
+static void addSyntiPorts(QMenu* menu, RouteList* r, int channel)
+ {
+ SynthIList* sl = song->syntis();
+ for (iSynthI i = sl->begin(); i != sl->end(); ++i) {
+ SynthI* track = *i;
+ QAction* oa = menu->addAction(track->name());
+ oa->setCheckable(true);
+ Route dst(track, channel, Route::SYNTIPORT);
+ oa->setData(QVariant::fromValue(dst));
+
+ for (iRoute ir = r->begin(); ir != r->end(); ++ir) {
+ if (*ir == dst) {
+ oa->setChecked(true);
+ break;
+ }
+ }
+ }
+ }
+
+//---------------------------------------------------------
+// addMidiTracks
+//---------------------------------------------------------
+
+static void addMidiTracks(QMenu* menu, RouteList* r, int channel)
+ {
+ MidiTrackList* tl = song->midis();
+ for (iMidiTrack i = tl->begin();i != tl->end(); ++i) {
+ MidiTrack* track = *i;
+ QAction* action = menu->addAction(track->name());
+ action->setCheckable(true);
+ Route src(track, channel, Route::TRACK);
+ action->setData(QVariant::fromValue(src));
+ for (iRoute ir = r->begin(); ir != r->end(); ++ir) {
+ if (*ir == src) {
+ action->setChecked(true);
+ break;
+ }
+ }
+ }
+ }
+
+//---------------------------------------------------------
+// addMidiOutPorts
+//---------------------------------------------------------
+
+static void addMidiOutPorts(QMenu* menu, RouteList* r, int channel)
+ {
+ MidiOutPortList* tl = song->midiOutPorts();
+ for (iMidiOutPort i = tl->begin();i != tl->end(); ++i) {
+ MidiChannel* track = (*i)->channel(channel);
+ QAction* action = menu->addAction(track->name());
+ action->setCheckable(true);
+ Route src(track, -1, Route::TRACK);
+ action->setData(QVariant::fromValue(src));
+ for (iRoute ir = r->begin(); ir != r->end(); ++ir) {
+ if (*ir == src) {
+ action->setChecked(true);
+ break;
+ }
+ }
+ }
+ }
+
+//---------------------------------------------------------
+// addMidiInPorts
+//---------------------------------------------------------
+
+static void addMidiInPorts(QMenu* menu, RouteList* r, int channel)
+ {
+ MidiInPortList* tl = song->midiInPorts();
+ for (iMidiInPort i = tl->begin();i != tl->end(); ++i) {
+ MidiInPort* track = *i;
+ QAction* action = menu->addAction(track->name());
+ action->setCheckable(true);
+ Route src(track, channel, Route::TRACK);
+ action->setData(QVariant::fromValue(src));
+ for (iRoute ir = r->begin(); ir != r->end(); ++ir) {
+ if (*ir == src) {
+ action->setChecked(true);
+ break;
+ }
+ }
+ }
+ }
+
+//---------------------------------------------------------
// addKnob
//---------------------------------------------------------
@@ -357,21 +446,9 @@ void MidiChannelStrip::iRoutePressed()
MidiChannel* t = (MidiChannel*)track;
RouteList* irl = t->inRoutes();
- MidiTrackList* tl = song->midis();
- int tn = 0;
- for (iMidiTrack i = tl->begin();i != tl->end(); ++i, ++tn) {
- MidiTrack* track = *i;
- QAction* action = pup.addAction(track->name());
- action->setCheckable(true);
- Route src(track, -1, Route::TRACK);
- action->setData(QVariant::fromValue(src));
- for (iRoute ir = irl->begin(); ir != irl->end(); ++ir) {
- if (*ir == src) {
- action->setChecked(true);
- break;
- }
- }
- }
+ addMidiTracks(&pup, irl, -1); // add midi tracks to menu
+ addMidiInPorts(&pup, irl, -1); // add midi inputs to menu
+
if (pup.isEmpty())
return;
QAction* n = pup.exec(QCursor::pos());
@@ -624,10 +701,32 @@ void MidiStrip::oRoutePressed()
RouteList* orl = track->outRoutes();
MidiOutPortList* mpl = song->midiOutPorts();
- int pn = 0;
- for (iMidiOutPort i = mpl->begin(); i != mpl->end(); ++i, ++pn) {
+ for (iMidiOutPort i = mpl->begin(); i != mpl->end(); ++i) {
MidiOutPort* op = *i;
QMenu* m = pup.addMenu(op->name());
+ m->setSeparatorsCollapsible(false);
+ m->addSeparator()->setText(tr("Channel"));
+ for (int channel = 0; channel < MIDI_CHANNELS; ++channel) {
+ QString s;
+ s.setNum(channel+1);
+ QAction* action = m->addAction(s);
+ action->setCheckable(true);
+ MidiChannel* mc = op->channel(channel);
+ Route dst(mc, -1, Route::TRACK);
+ action->setData(QVariant::fromValue(dst));
+ for (iRoute ir = orl->begin(); ir != orl->end(); ++ir) {
+ if (dst == *ir) {
+ action->setChecked(true);
+ break;
+ }
+ }
+ }
+ }
+ SynthIList* sl = song->syntis();
+ for (iSynthI i = sl->begin(); i != sl->end(); ++i) {
+ SynthI* op = *i;
+ QMenu* m = pup.addMenu(op->name());
+ m->setSeparatorsCollapsible(false);
m->addSeparator()->setText(tr("Channel"));
for (int channel = 0; channel < MIDI_CHANNELS; ++channel) {
QString s;
@@ -911,6 +1010,9 @@ void MidiOutPortStrip::oRoutePressed()
pup.addSeparator()->setText(tr("MidiDevices"));
RouteList* orl = track->outRoutes();
+ //
+ // add ALSA midi ports to list
+ //
QList<PortName> ol = midiDriver->outputPorts(true);
foreach (PortName ip, ol) {
QAction* oa = pup.addAction(ip.name);
@@ -927,26 +1029,7 @@ void MidiOutPortStrip::oRoutePressed()
}
//
- // add software synthesizer to list
- //
- SynthIList* sl = song->syntis();
- for (iSynthI i = sl->begin(); i != sl->end(); ++i) {
- SynthI* track = *i;
- QAction* oa = pup.addAction(track->name());
- oa->setCheckable(true);
- Route dst(track, -1, Route::SYNTIPORT);
- oa->setData(QVariant::fromValue(dst));
-
- for (iRoute ir = orl->begin(); ir != orl->end(); ++ir) {
- if (*ir == dst) {
- oa->setChecked(true);
- break;
- }
- }
- }
-
- //
- // add JACK midi port to list
+ // add JACK midi ports to list
//
ol = audioDriver->inputPorts(true);
foreach (PortName ip, ol) {
@@ -1132,114 +1215,27 @@ void MidiInPortStrip::oRoutePressed()
pup.setSeparatorsCollapsible(false);
pup.addSeparator()->setText(tr("Channel"));
- MidiTrackList* tl = song->midis();
- MidiSyntiList* sl = song->midiSyntis();
- RouteList* orl = track->outRoutes();
- SynthIList* asl = song->syntis();
-
- int sn = 0;
- for (iSynthI i = asl->begin(); i != asl->end(); ++i,++sn) {
- QAction* action = pup.addAction((*i)->name());
-
- QMap<QString, QVariant> data;
- data["id"] = QVariant(0x20000 + sn);
- data["was_checked"] = false;
- action->setData(data);
+ RouteList* orl = track->outRoutes();
- Route dst(*i, -1, Route::SYNTIPORT);
- for (iRoute ir = orl->begin(); ir != orl->end(); ++ir) {
- if (*ir == dst) {
- action->setCheckable(true);
- action->setChecked(true);
- data["was_checked"] = true;
- action->setData(data);
- break;
- }
- }
- }
for (int channel = 0; channel < MIDI_CHANNELS; ++channel) {
QMenu* m = pup.addMenu(QString(tr("Channel %1")).arg(channel + 1));
m->addSeparator()->setText(tr("Tracks"));
- //
- // route to midi track for recording
- // and monitoring
- //
- int tn = 0;
- for (iMidiTrack i = tl->begin(); i != tl->end(); ++i, ++tn) {
- QAction* trackno_action = m->addAction((*i)->name());
-
- QMap<QString, QVariant> data;
- data["id"] = tn * 16 + channel;
- data["was_checked"] = false;
- trackno_action->setData(data);
-
- Route dst(*i, channel, Route::TRACK);
- for (iRoute ir = orl->begin(); ir != orl->end(); ++ir) {
- if (*ir == dst) {
- trackno_action->setCheckable(true);
- trackno_action->setChecked(true);
- data["was_checked"] = true;
- trackno_action->setData(data);
- break;
- }
- }
- }
- //
- // route to midi synthesizer (arpeggiator etc.)
- //
- tn = 0;
- for (iMidiSynti i = sl->begin(); i != sl->end(); ++i, ++tn) {
- QAction* trackno_action = m->addAction((*i)->name());
-
- QMap<QString, QVariant> data;
- data["id"] = 0x10000 + tn * 16 + channel;
- data["was_checked"] = false;
- trackno_action->setData(data);
-
- Route dst(*i, channel, Route::TRACK);
- for (iRoute ir = orl->begin(); ir != orl->end(); ++ir) {
- if (*ir == dst) {
- trackno_action->setCheckable(true);
- trackno_action->setChecked(true);
- data["was_checked"] = true;
- trackno_action->setData(data);
- break;
- }
- }
- }
+ addMidiTracks(m, orl, channel);
+ addSyntiPorts(m, orl, channel);
+ addMidiOutPorts(m, orl, channel);
}
+
if (pup.isEmpty())
return;
QAction* action = pup.exec(QCursor::pos());
if (action) {
- int n = action->data().toMap()["id"].toInt();
- int was_checked = action->data().toMap()["was_checked"].toInt();
Route srcRoute(track, -1, Route::TRACK);
- Route dstRoute;
- if (n >= 0x20000) {
- dstRoute.track = asl->index(n - 0x20000);
- dstRoute.channel = -1;
- dstRoute.type = Route::SYNTIPORT;
- }
- else if (n >= 0x10000) {
- int channel = (n-0x10000) & 0xf;
- srcRoute.channel = channel;
- dstRoute.track = sl->index((n - 0x10000) >> 4);
- dstRoute.channel = channel;
- dstRoute.type = Route::TRACK;
- }
- else {
- int channel = n & 0xf;
- srcRoute.channel = channel;
- dstRoute.track = tl->index(n >> 4);
- dstRoute.channel = channel;
- dstRoute.type = Route::TRACK;
- }
- if (was_checked)
- audio->msgRemoveRoute(srcRoute, dstRoute);
- else
+ Route dstRoute = action->data().value<Route>();
+ if (action->isChecked())
audio->msgAddRoute(srcRoute, dstRoute);
+ else
+ audio->msgRemoveRoute(srcRoute, dstRoute);
song->update(SC_ROUTE);
}
oR->setDown(false); // pup->exec() catches mouse release event
@@ -1397,6 +1393,7 @@ MidiSyntiStrip::MidiSyntiStrip(Mixer* m, MidiSynti* t, bool align)
connect(iR, SIGNAL(pressed()), SLOT(iRoutePressed()));
oR = new QToolButton(this);
+ rBox->addWidget(oR);
oR->setFont(config.fonts[1]);
oR->setFixedWidth((STRIP_WIDTH-4)/2);
oR->setText(tr("oR"));
@@ -1604,7 +1601,6 @@ void MidiSyntiStrip::oRoutePressed()
}
oR->setDown(false); // pup->exec() catches mouse release event
}
-
//---------------------------------------------------------
// iRoutePressed
//---------------------------------------------------------
diff --git a/muse/muse/mixer/mstrip.h b/muse/muse/mixer/mstrip.h
index cfec0183..41afcd5e 100644
--- a/muse/muse/mixer/mstrip.h
+++ b/muse/muse/mixer/mstrip.h
@@ -161,8 +161,8 @@ class MidiSyntiStrip : public Strip {
void sliderReleased(int);
void autoReadToggled(bool);
void autoWriteToggled(bool);
- void iRoutePressed();
void oRoutePressed();
+ void iRoutePressed();
protected slots:
virtual void heartBeat();
diff --git a/muse/muse/muse.cpp b/muse/muse/muse.cpp
index 25a0a1ff..36e25c06 100644
--- a/muse/muse/muse.cpp
+++ b/muse/muse/muse.cpp
@@ -68,6 +68,8 @@
#include "projectpropsdialog.h"
#include "midichannel.h"
+extern void initMidiInstruments();
+
static pthread_t watchdogThread;
static const char* fileOpenText =
@@ -538,8 +540,6 @@ MusE::MusE()
panicAction->setWhatsThis(tr(infoPanicButton));
connect(panicAction, SIGNAL(triggered()), song, SLOT(panic()));
- initMidiInstruments();
-
#ifdef __APPLE__
if (coreMidi.init()) {
QMessageBox::critical(NULL, "MusE fatal error.",
@@ -2851,6 +2851,7 @@ int main(int argc, char* argv[])
srand(time(0)); // initialize random number generator
initMidiController();
+ initMidiInstruments();
MuseApplication app(argc, argv);
config.fonts[0] = QFont(QString("arial"), 10, QFont::Normal);
diff --git a/muse/muse/song.cpp b/muse/muse/song.cpp
index 66fa6aea..0875a106 100644
--- a/muse/muse/song.cpp
+++ b/muse/muse/song.cpp
@@ -44,6 +44,7 @@
#include "midichannel.h"
#include "midioutport.h"
#include "midiinport.h"
+#include "instruments/minstrument.h"
Song* song;
@@ -592,6 +593,7 @@ void Song::update(int flags)
//
// remove unconnected channels
//
+// printf("update tracks %d %d\n", _tracks.size(), _midiChannel.size());
bool again;
do {
again = false;
@@ -1472,7 +1474,6 @@ Track* Song::addTrack(QAction* action)
switch (type) {
case Track::MIDI:
track = new MidiTrack();
- track->setType(Track::MIDI);
break;
case Track::MIDI_OUT:
track = new MidiOutPort();
@@ -1687,8 +1688,12 @@ void Song::insertTrack2(Track* track)
case Track::AUDIO_SOFTSYNTH:
{
SynthI* s = (SynthI*)track;
- midiInstruments.push_back(s);
+ midiInstruments.push_back(s->instrument());
_synthIs.push_back(s);
+ for (int i = 0; i < MIDI_CHANNELS; ++i) {
+ MidiChannel* mc = ((SynthI*)track)->channel(i);
+ _midiChannel.push_back(mc);
+ }
}
break;
default:
diff --git a/muse/muse/synth.cpp b/muse/muse/synth.cpp
index 4e941ced..12c3ba21 100644
--- a/muse/muse/synth.cpp
+++ b/muse/muse/synth.cpp
@@ -21,18 +21,21 @@
#include <dlfcn.h>
#include "al/al.h"
+#include "al/xml.h"
+#include "al/tempo.h"
#include "muse.h"
#include "synth.h"
-#include "al/xml.h"
#include "midi.h"
#include "synti/libsynti/mess.h"
#include "song.h"
#include "audio.h"
#include "event.h"
#include "midievent.h"
+#include "midichannel.h"
#include "audio.h"
#include "midiseq.h"
#include "midictrl.h"
+#include "instruments/minstrument.h"
std::vector<Synth*> synthis; // array of available synthis
@@ -178,12 +181,39 @@ void* MessSynth::instantiate(const QString& instanceName)
//---------------------------------------------------------
SynthI::SynthI()
- : AudioTrack(AUDIO_SOFTSYNTH)
+ : AudioTrack()
{
+ track = this;
synthesizer = 0;
_sif = 0;
// setVolume(1.0);
// setPan(0.0);
+ _instrument = genericMidiInstrument; //TODO
+ for (int ch = 0; ch < MIDI_CHANNELS; ++ch)
+ _channel[ch] = new MidiChannel(this, ch);
+ }
+
+//---------------------------------------------------------
+// ~SynthI
+//---------------------------------------------------------
+
+SynthI::~SynthI()
+ {
+ deactivate2();
+ deactivate3();
+ for (int ch = 0; ch < MIDI_CHANNEL; ++ch)
+ delete _channel[ch];
+ }
+
+//---------------------------------------------------------
+// setName
+//---------------------------------------------------------
+
+void SynthI::setName(const QString& s)
+ {
+ Track::setName(s);
+ for (int ch = 0; ch < MIDI_CHANNELS; ++ch)
+ _channel[ch]->setDefaultName();
}
//---------------------------------------------------------
@@ -226,7 +256,7 @@ bool SynthI::initInstance(Synth* s)
synthesizer = s;
_sif = s->createSIF(this);
- setIName(name()); // set instrument name
+ _instrument->setIName(name()); // set instrument name
AudioTrack::setChannels(_sif->channels());
//---------------------------------------------------
@@ -234,7 +264,7 @@ bool SynthI::initInstance(Synth* s)
//---------------------------------------------------
int id = 0;
- MidiControllerList* cl = MidiInstrument::controller();
+ MidiControllerList* cl = _instrument->controller();
for (;;) {
const char* name;
int ctrl;
@@ -247,7 +277,7 @@ bool SynthI::initInstance(Synth* s)
cl->push_back(c);
}
- EventList* iel = midiState();
+ EventList* iel = _instrument->midiState();
if (!iel->empty()) {
for (iEvent i = iel->begin(); i != iel->end(); ++i) {
Event ev = i->second;
@@ -291,7 +321,7 @@ int MessSynthIF::getControllerInfo(int id, const char** name, int* ctrl, int* mi
void SynthI::deactivate2()
{
- removeMidiInstrument(this);
+ removeMidiInstrument(_instrument);
}
//---------------------------------------------------------
@@ -319,16 +349,6 @@ MessSynthIF::~MessSynthIF()
}
//---------------------------------------------------------
-// ~SynthI
-//---------------------------------------------------------
-
-SynthI::~SynthI()
- {
- deactivate2();
- deactivate3();
- }
-
-//---------------------------------------------------------
// initMidiSynth
// search for software synthis and advertise
//---------------------------------------------------------
@@ -433,7 +453,7 @@ void SynthI::read(QDomNode node)
else if (e.tagName() == "guiVisible")
startGui = e.text().toInt();
else if (e.tagName() == "midistate")
- readMidiState(node.firstChild());
+ _instrument->readMidiState(node.firstChild());
else if (e.tagName() == "param") {
float val = e.text().toFloat();
initParams.push_back(val);
@@ -572,11 +592,28 @@ bool MessSynthIF::putEvent(const MidiEvent& ev)
void SynthI::collectInputData()
{
bufferEmpty = false;
- while (!_eventFifo.isEmpty())
- _playEvents.add(_eventFifo.get());
- iMPEvent ie = _playEvents.begin();
+ while (!eventFifo.isEmpty())
+ _schedEvents.add(eventFifo.get());
+ iMPEvent ie = _schedEvents.begin();
unsigned pos = audio->pos().frame();
- _sif->getData(&_playEvents, ie, pos, channels(), segmentSize, buffer);
- _playEvents.clear();
+ _sif->getData(&_schedEvents, ie, pos, channels(), segmentSize, buffer);
+ _schedEvents.clear();
}
+//-------------------------------------------------------------------
+// process
+// Collect all midi events for the current process cycle and put
+// into _schedEvents queue. For note on events create the proper
+// note off events. The note off events maybe played after the
+// current process cycle.
+// From _schedEvents queue copy all events for the current cycle
+// to all output routes. Events routed to ALSA go into the
+// _playEvents queue which is processed by the MidiSeq thread.
+//-------------------------------------------------------------------
+
+void SynthI::processMidi(unsigned fromTick, unsigned toTick, unsigned fromFrame, unsigned toFrame)
+ {
+ if (mute())
+ return;
+ MidiOut::processMidi(_schedEvents, fromTick, toTick, fromFrame, toFrame);
+ }
diff --git a/muse/muse/synth.h b/muse/muse/synth.h
index c4c469de..460cee2f 100644
--- a/muse/muse/synth.h
+++ b/muse/muse/synth.h
@@ -22,8 +22,9 @@
#define __SYNTH_H__
#include "globals.h"
-#include "instruments/minstrument.h"
+// #include "instruments/minstrument.h"
#include "audiotrack.h"
+#include "midiout.h"
class Mess;
struct MESS;
@@ -114,11 +115,11 @@ class SynthIF {
// MidiInstrument
//---------------------------------------------------------
-class SynthI : public AudioTrack, public MidiInstrument
+class SynthI : public AudioTrack, public MidiOut
{
+ Q_OBJECT
+
SynthIF* _sif;
- MPEventList _playEvents;
- MidiFifo _eventFifo;
protected:
Synth* synthesizer;
@@ -135,6 +136,9 @@ class SynthI : public AudioTrack, public MidiInstrument
public:
SynthI();
virtual ~SynthI();
+ virtual TrackType type() const { return AUDIO_SOFTSYNTH; }
+
+ virtual void setName(const QString& s);
SynthIF* sif() const { return _sif; }
bool initInstance(Synth* s);
@@ -169,8 +173,7 @@ class SynthI : public AudioTrack, public MidiInstrument
void deactivate3();
bool isActivated() const { return synthesizer && _sif; }
virtual bool hasAuxSend() const { return _sif->hasAuxSend(); }
- MPEventList* playEvents() { return &_playEvents; }
- MidiFifo* eventFifo() { return &_eventFifo; }
+ void processMidi(unsigned fromTick, unsigned toTick, unsigned fromFrame, unsigned toFrame);
};
//---------------------------------------------------------
diff --git a/muse/muse/track.cpp b/muse/muse/track.cpp
index 276585c8..d3e18ee3 100644
--- a/muse/muse/track.cpp
+++ b/muse/muse/track.cpp
@@ -68,7 +68,7 @@ ArrangerTrack::ArrangerTrack()
QColor Track::ccolor() const
{
- return config.trackBg[_type];
+ return config.trackBg[type()];
}
//---------------------------------------------------------
@@ -92,10 +92,10 @@ QPixmap* Track::pixmap(TrackType t)
}
//---------------------------------------------------------
-// Track::init
+// Track
//---------------------------------------------------------
-void Track::init()
+Track::Track()
{
_tt = AL::TICKS;
_recordFlag = false;
@@ -114,16 +114,8 @@ void Track::init()
_peak[i] = 0.0f;
_peakTimer[i] = 0;
}
- }
-
-//---------------------------------------------------------
-// Track
-//---------------------------------------------------------
-
-Track::Track(Track::TrackType t)
- {
- init();
- _type = t;
+ _sendSync = false;
+ _deviceId = 127;
_parts = new PartList;
}
@@ -152,16 +144,16 @@ Track::~Track()
void Track::setDefaultName()
{
QString base;
- switch(_type) {
+ switch(type()) {
case MIDI:
case WAVE:
base = QString("Track");
break;
case MIDI_CHANNEL:
{
- MidiOutPort* mop = ((MidiChannel*)this)->port();
+ MidiOut* mop = ((MidiChannel*)this)->port();
int no = ((MidiChannel*)this)->channelNo();
- base.sprintf("%s:%d", mop->name().toLatin1().data(), no + 1);
+ base = QString("%1:%2").arg(mop->track->name()).arg(no + 1);
setName(base);
return;
}
@@ -212,7 +204,7 @@ void Track::setDefaultName()
break;
}
}
- if (_type == MIDI_OUT) {
+ if (type() == MIDI_OUT) {
MidiOutPort* mop = (MidiOutPort*) this;
for (int i = 0; i < MIDI_CHANNELS; ++i)
mop->channel(i)->setDefaultName();
@@ -226,7 +218,7 @@ void Track::setDefaultName()
void Track::dump() const
{
printf("Track <%s>: typ %d, parts %zd sel %d\n",
- _name.toLatin1().data(), _type, _parts->size(), _selected);
+ _name.toLatin1().data(), type(), _parts->size(), _selected);
}
//---------------------------------------------------------
@@ -723,8 +715,8 @@ void Track::writeRouting(Xml& xml) const
// MidiTrackBase
//---------------------------------------------------------
-MidiTrackBase::MidiTrackBase(TrackType t)
- : Track(t)
+MidiTrackBase::MidiTrackBase()
+ : Track()
{
_pipeline = new MidiPipeline();
}
@@ -1102,3 +1094,14 @@ void Track::deactivate()
}
}
+//---------------------------------------------------------
+// setSendSync
+//---------------------------------------------------------
+
+void Track::setSendSync(bool val)
+ {
+ _sendSync = val;
+ emit sendSyncChanged(val);
+ }
+
+
diff --git a/muse/muse/track.h b/muse/muse/track.h
index f07a3282..3eb248ef 100644
--- a/muse/muse/track.h
+++ b/muse/muse/track.h
@@ -109,12 +109,11 @@ class Track : public QObject {
};
private:
- TrackType _type;
QString _comment;
PartList* _parts;
Port _alsaPort[MAX_CHANNELS], _jackPort[MAX_CHANNELS];
-
- void init();
+ bool _sendSync; // this port sends mtc/mmc events
+ int _deviceId; // midi device id: 0-126; 127 == all
protected:
TType _tt; // time type
@@ -160,6 +159,7 @@ class Track : public QObject {
void partsChanged();
void nameChanged(const QString&);
void routeChanged();
+ void sendSyncChanged(bool);
private slots:
void setAutoRead(bool);
@@ -167,7 +167,6 @@ class Track : public QObject {
public:
Track();
- Track(TrackType);
virtual ~Track();
static const char* _cname[];
@@ -178,8 +177,8 @@ class Track : public QObject {
TType timeType() const { return _tt; }
void setTimeType(TType t) { _tt = t; }
- QString cname() const { return QString(_cname[_type]); }
- QString clname() const { return QString(_clname[_type]); }
+ QString cname() const { return QString(_cname[type()]); }
+ QString clname() const { return QString(_clname[type()]); }
//
// called before and after use
@@ -225,7 +224,7 @@ class Track : public QObject {
//----------------------------------------------------------
QColor ccolor() const;
- QPixmap* pixmap() const { return pixmap(_type); }
+ QPixmap* pixmap() const { return pixmap(type()); }
static QPixmap* pixmap(TrackType);
bool selected() const { return _selected; }
@@ -237,8 +236,7 @@ class Track : public QObject {
const QString name() const { return _name; }
virtual void setName(const QString& s);
- TrackType type() const { return _type; }
- void setType(TrackType t) { _type = t; }
+ virtual TrackType type() const = 0;
PartList* parts() { return _parts; }
const PartList* cparts() const { return _parts; }
@@ -326,6 +324,12 @@ class Track : public QObject {
ArrangerTrackList subtracks;
friend class Song;
+
+ virtual void routeEvent(const MidiEvent&) {}
+ bool sendSync() const { return _sendSync; }
+ void setSendSync(bool val);
+ int deviceId() const { return _deviceId; }
+ void setDeviceId(int val) { _deviceId = val; }
};
//---------------------------------------------------------
@@ -338,7 +342,7 @@ class MidiTrackBase : public Track {
MidiPipeline* _pipeline;
public:
- MidiTrackBase(TrackType t);
+ MidiTrackBase();
virtual ~MidiTrackBase();
bool readProperties(QDomNode);
diff --git a/muse/muse/wavetrack.cpp b/muse/muse/wavetrack.cpp
index 1f964789..65b91ceb 100644
--- a/muse/muse/wavetrack.cpp
+++ b/muse/muse/wavetrack.cpp
@@ -37,7 +37,7 @@ bool WaveTrack::firstWaveTrack = true;
//---------------------------------------------------------
WaveTrack::WaveTrack()
- : AudioTrack(Track::WAVE)
+ : AudioTrack()
{
//
// allocate prefetch buffer
diff --git a/muse/muse/wavetrack.h b/muse/muse/wavetrack.h
index 519a0692..c766e9b1 100644
--- a/muse/muse/wavetrack.h
+++ b/muse/muse/wavetrack.h
@@ -51,6 +51,8 @@ class WaveTrack : public AudioTrack {
WaveTrack();
~WaveTrack();
+ virtual TrackType type() const { return WAVE; }
+
void clone(WaveTrack*);
virtual Part* newPart(Part*p=0, bool clone=false);