summaryrefslogtreecommitdiff
path: root/attic/muse_qt4_evolution/muse/midioutport.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'attic/muse_qt4_evolution/muse/midioutport.cpp')
-rw-r--r--attic/muse_qt4_evolution/muse/midioutport.cpp262
1 files changed, 262 insertions, 0 deletions
diff --git a/attic/muse_qt4_evolution/muse/midioutport.cpp b/attic/muse_qt4_evolution/muse/midioutport.cpp
new file mode 100644
index 00000000..695f51a6
--- /dev/null
+++ b/attic/muse_qt4_evolution/muse/midioutport.cpp
@@ -0,0 +1,262 @@
+//=============================================================================
+// MusE
+// Linux Music Editor
+// $Id:$
+//
+// Copyright (C) 2002-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 "song.h"
+#include "midiplugin.h"
+#include "midictrl.h"
+#include "al/al.h"
+#include "al/tempo.h"
+#include "al/xml.h"
+#include "audiodev.h"
+#include "audio.h"
+#include "midioutport.h"
+#include "sync.h"
+#include "gconfig.h"
+#include "instruments/minstrument.h"
+
+//---------------------------------------------------------
+// MidiOutPort
+//---------------------------------------------------------
+
+MidiOutPort::MidiOutPort()
+ : MidiTrackBase()
+ {
+ track = this;
+ _instrument = genericMidiInstrument;
+ setDeviceId(127); // all
+ addMidiController(_instrument, CTRL_MASTER_VOLUME);
+ _channels = 1;
+ }
+
+//---------------------------------------------------------
+// MidiOutPort
+//---------------------------------------------------------
+
+MidiOutPort::~MidiOutPort()
+ {
+ }
+
+//---------------------------------------------------------
+// setName
+//---------------------------------------------------------
+
+void MidiOutPort::setName(const QString& s)
+ {
+ Track::setName(s);
+ if (!jackPort().isZero())
+ audioDriver->setPortName(jackPort(), s);
+ }
+
+//---------------------------------------------------------
+// MidiOutPort::write
+//---------------------------------------------------------
+
+void MidiOutPort::write(Xml& xml) const
+ {
+ xml.stag("MidiOutPort");
+ MidiTrackBase::writeProperties(xml);
+ if (_instrument)
+ xml.tag("instrument", _instrument->iname());
+ xml.tag("sendSync", sendSync());
+ xml.tag("deviceId", deviceId());
+ xml.etag("MidiOutPort");
+ }
+
+//---------------------------------------------------------
+// MidiOutPort::read
+//---------------------------------------------------------
+
+void MidiOutPort::read(QDomNode node)
+ {
+ for (; !node.isNull(); node = node.nextSibling()) {
+ QDomElement e = node.toElement();
+ QString tag(e.tagName());
+ if (tag == "instrument") {
+ QString iname = e.text();
+ _instrument = registerMidiInstrument(iname);
+ }
+ else if (tag == "sendSync")
+ setSendSync(e.text().toInt());
+ else if (tag == "deviceId")
+ setDeviceId(e.text().toInt());
+ else if (MidiTrackBase::readProperties(node))
+ printf("MusE:MidiOutPort: unknown tag %s\n", tag.toLatin1().data());
+ }
+ }
+
+//---------------------------------------------------------
+// routeEvent
+//---------------------------------------------------------
+
+void MidiOutPort::routeEvent(const MidiEvent& event)
+ {
+ for (iRoute r = _outRoutes.begin(); r != _outRoutes.end(); ++r) {
+ if (r->dst.type == RouteNode::JACKMIDIPORT)
+ queueJackEvent(event);
+ else
+ fprintf(stderr, "MidiOutPort::process(): invalid routetype\n");
+ }
+ }
+
+//---------------------------------------------------------
+// queueJackEvent
+// called from MidiSeq
+//---------------------------------------------------------
+
+#define JO(e) audioDriver->putEvent(jackPort(0), e);
+
+void MidiOutPort::queueJackEvent(const MidiEvent& ev)
+ {
+ if (ev.type() == ME_CONTROLLER) {
+ int a = ev.dataA();
+ int b = ev.dataB();
+ int chn = ev.channel();
+ unsigned t = ev.time();
+
+ if (a == CTRL_PITCH) {
+ int v = b + 8192;
+ audioDriver->putEvent(jackPort(0), MidiEvent(t, chn, ME_PITCHBEND, v & 0x7f, (v >> 7) & 0x7f));
+ }
+ else if (a == CTRL_PROGRAM) {
+ // don't output program changes for GM drum channel
+// if (!(song->mtype() == MT_GM && chn == 9)) {
+ int hb = (b >> 16) & 0xff;
+ int lb = (b >> 8) & 0xff;
+ int pr = b & 0x7f;
+ if (hb != 0xff)
+ JO(MidiEvent(t, chn, ME_CONTROLLER, CTRL_HBANK, hb));
+ if (lb != 0xff)
+ JO(MidiEvent(t+1, chn, ME_CONTROLLER, CTRL_LBANK, lb));
+ JO(MidiEvent(t+2, chn, ME_PROGRAM, pr, 0));
+// }
+ }
+ else if (a == CTRL_MASTER_VOLUME) {
+ unsigned char sysex[] = {
+ 0x7f, 0x7f, 0x04, 0x01, 0x00, 0x00
+ };
+ sysex[1] = deviceId();
+ sysex[4] = b & 0x7f;
+ sysex[5] = (b >> 7) & 0x7f;
+ JO(MidiEvent(t, ME_SYSEX, sysex, 6));
+ }
+ else if (a < CTRL_14_OFFSET) { // 7 Bit Controller
+ JO(ev);
+ }
+ else if (a < CTRL_RPN_OFFSET) { // 14 bit high resolution controller
+ int ctrlH = (a >> 8) & 0x7f;
+ int ctrlL = a & 0x7f;
+ int dataH = (b >> 7) & 0x7f;
+ int dataL = b & 0x7f;
+ JO(MidiEvent(t, chn, ME_CONTROLLER, ctrlH, dataH));
+ JO(MidiEvent(t+1, chn, ME_CONTROLLER, ctrlL, dataL));
+ }
+ else if (a < CTRL_NRPN_OFFSET) { // RPN 7-Bit Controller
+ int ctrlH = (a >> 8) & 0x7f;
+ int ctrlL = a & 0x7f;
+ JO(MidiEvent(t, chn, ME_CONTROLLER, CTRL_HRPN, ctrlH));
+ JO(MidiEvent(t+1, chn, ME_CONTROLLER, CTRL_LRPN, ctrlL));
+ JO(MidiEvent(t+2, chn, ME_CONTROLLER, CTRL_HDATA, b));
+ }
+ else if (a < CTRL_RPN14_OFFSET) { // NRPN 7-Bit Controller
+ int ctrlH = (a >> 8) & 0x7f;
+ int ctrlL = a & 0x7f;
+ JO(MidiEvent(t, chn, ME_CONTROLLER, CTRL_HNRPN, ctrlH));
+ JO(MidiEvent(t+1, chn, ME_CONTROLLER, CTRL_LNRPN, ctrlL));
+ JO(MidiEvent(t+2, chn, ME_CONTROLLER, CTRL_HDATA, b));
+ }
+ else if (a < CTRL_NRPN14_OFFSET) { // RPN14 Controller
+ int ctrlH = (a >> 8) & 0x7f;
+ int ctrlL = a & 0x7f;
+ int dataH = (b >> 7) & 0x7f;
+ int dataL = b & 0x7f;
+ JO(MidiEvent(t, chn, ME_CONTROLLER, CTRL_HRPN, ctrlH));
+ JO(MidiEvent(t+1, chn, ME_CONTROLLER, CTRL_LRPN, ctrlL));
+ JO(MidiEvent(t+2, chn, ME_CONTROLLER, CTRL_HDATA, dataH));
+ JO(MidiEvent(t+3, chn, ME_CONTROLLER, CTRL_LDATA, dataL));
+ }
+ else if (a < CTRL_NONE_OFFSET) { // NRPN14 Controller
+ int ctrlH = (a >> 8) & 0x7f;
+ int ctrlL = a & 0x7f;
+ int dataH = (b >> 7) & 0x7f;
+ int dataL = b & 0x7f;
+ JO(MidiEvent(t, chn, ME_CONTROLLER, CTRL_HNRPN, ctrlH));
+ JO(MidiEvent(t+1, chn, ME_CONTROLLER, CTRL_LNRPN, ctrlL));
+ JO(MidiEvent(t+2, chn, ME_CONTROLLER, CTRL_HDATA, dataH));
+ JO(MidiEvent(t+3, chn, ME_CONTROLLER, CTRL_LDATA, dataL));
+ }
+ else {
+ printf("putEvent: unknown controller type 0x%x\n", a);
+ }
+ }
+ else {
+ JO(ev);
+ }
+ }
+#undef JO
+
+//---------------------------------------------------------
+// setInstrument
+//---------------------------------------------------------
+
+void MidiOutPort::setInstrument(MidiInstrument* i)
+ {
+ _instrument = i;
+ emit instrumentChanged();
+ }
+
+//-------------------------------------------------------------------
+// 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.
+//-------------------------------------------------------------------
+
+void MidiOutPort::processMidi(const SeqTime* t)
+ {
+ if (track->mute())
+ return;
+
+ MidiEventList el;
+ MidiOut::processMidi(el, t);
+
+ pipeline()->apply(t->curTickPos, t->nextTickPos, &el, &_schedEvents);
+
+ //
+ // route events to destination
+ //
+
+ int portVelo = 0;
+ unsigned endFrame = t->lastFrameTime + segmentSize;
+ iMidiEvent i = _schedEvents.begin();
+
+ for (; i != _schedEvents.end(); ++i) {
+ if (i->time() >= endFrame)
+ break;
+ routeEvent(*i);
+ if (i->type() == ME_NOTEON)
+ portVelo += i->dataB();
+ }
+ _schedEvents.erase(_schedEvents.begin(), i);
+ addMidiMeter(portVelo);
+ }
+