From b6d84790d5bedbf17edc0538187379523033f12d Mon Sep 17 00:00:00 2001 From: Werner Schweer Date: Wed, 18 Oct 2006 17:13:58 +0000 Subject: updates --- muse/muse/CMakeLists.txt | 7 +- muse/muse/arranger/arranger.cpp | 1 + muse/muse/arranger/canvas.cpp | 3 +- muse/muse/arranger/tlswidget.cpp | 1 + muse/muse/arranger/tlwidget.cpp | 2 + muse/muse/arranger/trackinfo.cpp | 3 + muse/muse/audio.cpp | 2 + muse/muse/ctrl/configmidictrl.cpp | 3 +- muse/muse/ctrl/ctrldialog.cpp | 1 + muse/muse/driver/alsamidi.cpp | 2 + muse/muse/driver/dummyaudio.cpp | 4 +- muse/muse/exportmidi.cpp | 2 +- muse/muse/importmidi.cpp | 2 + muse/muse/instruments/minstrument.cpp | 2 +- muse/muse/midi.cpp | 3 + muse/muse/midichannel.cpp | 178 +++++++ muse/muse/midichannel.h | 72 +++ muse/muse/midiedit/ctrledit.cpp | 2 + muse/muse/midiinport.cpp | 272 ++++++++++ muse/muse/midiinport.h | 62 +++ muse/muse/midioutport.cpp | 493 +++++++++++++++++++ muse/muse/midioutport.h | 109 +++++ muse/muse/midiport.cpp | 899 ---------------------------------- muse/muse/midiseq.cpp | 3 + muse/muse/miditrack.cpp | 3 +- muse/muse/mixer/astrip.cpp | 2 + muse/muse/mixer/mixer.cpp | 3 + muse/muse/mixer/mstrip.cpp | 3 + muse/muse/muse.cpp | 2 +- muse/muse/route.cpp | 1 + muse/muse/seqmsg.cpp | 3 + muse/muse/song.cpp | 3 + muse/muse/songfile.cpp | 3 + muse/muse/track.cpp | 2 + muse/muse/track.h | 168 +------ muse/muse/widgets/outportcombo.cpp | 1 + 36 files changed, 1249 insertions(+), 1073 deletions(-) create mode 100644 muse/muse/midichannel.cpp create mode 100644 muse/muse/midichannel.h create mode 100644 muse/muse/midiinport.cpp create mode 100644 muse/muse/midiinport.h create mode 100644 muse/muse/midioutport.cpp create mode 100644 muse/muse/midioutport.h delete mode 100644 muse/muse/midiport.cpp diff --git a/muse/muse/CMakeLists.txt b/muse/muse/CMakeLists.txt index 74020594..e01af72f 100644 --- a/muse/muse/CMakeLists.txt +++ b/muse/muse/CMakeLists.txt @@ -73,6 +73,9 @@ QT4_WRAP_CPP ( muse_moc_headers audiogroup.h exportmidi.h importmidi.h + midichannel.h + midiinport.h + midioutport.h ) QT4_ADD_RESOURCES (muse_qrc_files muse.qrc) @@ -123,7 +126,9 @@ add_executable ( muse gconfig.cpp midirc.cpp midififo.cpp - midiport.cpp + midioutport.cpp + midiinport.cpp + midichannel.cpp projectpropsdialog.cpp projectdialog.cpp diff --git a/muse/muse/arranger/arranger.cpp b/muse/muse/arranger/arranger.cpp index 53afff1a..a8912705 100644 --- a/muse/muse/arranger/arranger.cpp +++ b/muse/muse/arranger/arranger.cpp @@ -37,6 +37,7 @@ #include "midictrl.h" #include "gconfig.h" #include "part.h" +#include "midichannel.h" int Arranger::trackNameWidth = 80; diff --git a/muse/muse/arranger/canvas.cpp b/muse/muse/arranger/canvas.cpp index 6a2332e0..b3c56a6c 100644 --- a/muse/muse/arranger/canvas.cpp +++ b/muse/muse/arranger/canvas.cpp @@ -31,6 +31,7 @@ #include "tlswidget.h" #include "part.h" #include "gui.h" +#include "midichannel.h" #include @@ -254,7 +255,7 @@ void PartCanvas::paint(QPainter& p, QRect r) continue; TLSWidget* tls = (TLSWidget*)(at->tw); int y = tls->y(); - int h = tls->height(); + // int h = tls->height(); p.setPen(QPen(Qt::lightGray, trackSeparator, Qt::SolidLine)); p.drawLine(from, y + yTrackOffset, to, y + yTrackOffset); QPoint off(0, y); diff --git a/muse/muse/arranger/tlswidget.cpp b/muse/muse/arranger/tlswidget.cpp index 6e20c3b4..fed37f0c 100644 --- a/muse/muse/arranger/tlswidget.cpp +++ b/muse/muse/arranger/tlswidget.cpp @@ -20,6 +20,7 @@ #include "song.h" #include "track.h" +#include "midichannel.h" #include "tlswidget.h" #include "tlwlayout.h" #include "icons.h" diff --git a/muse/muse/arranger/tlwidget.cpp b/muse/muse/arranger/tlwidget.cpp index 13d77398..8249b22b 100644 --- a/muse/muse/arranger/tlwidget.cpp +++ b/muse/muse/arranger/tlwidget.cpp @@ -34,6 +34,8 @@ #include "synth.h" #include "widgets/outportcombo.h" #include "audio.h" +#include "midioutport.h" +#include "midichannel.h" //--------------------------------------------------------- // TLWidget diff --git a/muse/muse/arranger/trackinfo.cpp b/muse/muse/arranger/trackinfo.cpp index 36a14692..6e79b56c 100644 --- a/muse/muse/arranger/trackinfo.cpp +++ b/muse/muse/arranger/trackinfo.cpp @@ -29,6 +29,9 @@ #include "tllineedit.h" #include "audio.h" #include "gui.h" +#include "midioutport.h" +#include "midiinport.h" +#include "midichannel.h" //--------------------------------------------------------- // createTrackInfo diff --git a/muse/muse/audio.cpp b/muse/muse/audio.cpp index 4e637278..6d74f02e 100644 --- a/muse/muse/audio.cpp +++ b/muse/muse/audio.cpp @@ -36,6 +36,8 @@ #include "al/tempo.h" #include "widgets/utils.h" #include "synth.h" +#include "midioutport.h" +#include "midiinport.h" extern double curTime(); extern bool initJackAudio(); diff --git a/muse/muse/ctrl/configmidictrl.cpp b/muse/muse/ctrl/configmidictrl.cpp index 4efadef4..5aefcba3 100644 --- a/muse/muse/ctrl/configmidictrl.cpp +++ b/muse/muse/ctrl/configmidictrl.cpp @@ -19,8 +19,9 @@ //============================================================================= #include "configmidictrl.h" -#include "track.h" #include "miditrack.h" +#include "midioutport.h" +#include "midichannel.h" #include "midictrl.h" #include "instruments/minstrument.h" diff --git a/muse/muse/ctrl/ctrldialog.cpp b/muse/muse/ctrl/ctrldialog.cpp index 23eec660..c9b4e7a7 100644 --- a/muse/muse/ctrl/ctrldialog.cpp +++ b/muse/muse/ctrl/ctrldialog.cpp @@ -22,6 +22,7 @@ #include "midictrl.h" #include "track.h" #include "miditrack.h" +#include "midichannel.h" #include "audiotrack.h" #include "plugin.h" #include "pipeline.h" diff --git a/muse/muse/driver/alsamidi.cpp b/muse/muse/driver/alsamidi.cpp index 48001261..7a90b99d 100644 --- a/muse/muse/driver/alsamidi.cpp +++ b/muse/muse/driver/alsamidi.cpp @@ -21,6 +21,8 @@ #include "alsamidi.h" #include "globals.h" #include "midi.h" +#include "midiinport.h" +#include "midioutport.h" #include "../midiseq.h" #include "../song.h" #include "al/pos.h" diff --git a/muse/muse/driver/dummyaudio.cpp b/muse/muse/driver/dummyaudio.cpp index 768e3d04..2aa5a709 100644 --- a/muse/muse/driver/dummyaudio.cpp +++ b/muse/muse/driver/dummyaudio.cpp @@ -73,11 +73,11 @@ class DummyAudio : public AudioDriver { virtual void registerClient() {} - virtual void* registerOutPort(const QString& s, bool midi = false) { + virtual void* registerOutPort(const QString& s, bool) { iPorts.push_back(QString(s)); return (void*)(iPorts.size() + 3000); } - virtual void* registerInPort(const QString& s, bool midi = false) { + virtual void* registerInPort(const QString& s, bool) { oPorts.push_back(QString(s)); return (void*)(oPorts.size() + 4000); } diff --git a/muse/muse/exportmidi.cpp b/muse/muse/exportmidi.cpp index d8b90e63..86592a68 100644 --- a/muse/muse/exportmidi.cpp +++ b/muse/muse/exportmidi.cpp @@ -24,7 +24,6 @@ #include "midictrl.h" #include "globals.h" #include "widgets/filedialog.h" -#include "track.h" #include "song.h" #include "mpevent.h" #include "event.h" @@ -35,6 +34,7 @@ #include "al/marker.h" #include "part.h" #include "exportmidi.h" +#include "midichannel.h" //--------------------------------------------------------- // addController diff --git a/muse/muse/importmidi.cpp b/muse/muse/importmidi.cpp index ed78c6c0..09d5a11f 100644 --- a/muse/muse/importmidi.cpp +++ b/muse/muse/importmidi.cpp @@ -39,6 +39,8 @@ #include "mixer/mixer.h" #include "arranger/arranger.h" #include "midictrl.h" +#include "midichannel.h" +#include "midioutport.h" //--------------------------------------------------------- // ImportMidiDialog diff --git a/muse/muse/instruments/minstrument.cpp b/muse/muse/instruments/minstrument.cpp index e669d6b5..ce1bcdd7 100644 --- a/muse/muse/instruments/minstrument.cpp +++ b/muse/muse/instruments/minstrument.cpp @@ -19,7 +19,7 @@ //============================================================================= #include "minstrument.h" -#include "track.h" +#include "midioutport.h" #include "globals.h" #include "event.h" #include "mpevent.h" diff --git a/muse/muse/midi.cpp b/muse/muse/midi.cpp index 11989a7e..9cc71249 100644 --- a/muse/muse/midi.cpp +++ b/muse/muse/midi.cpp @@ -37,6 +37,9 @@ #include "al/sig.h" #include "part.h" #include "midiplugin.h" +#include "midiinport.h" +#include "midioutport.h" +#include "midichannel.h" extern void dump(const unsigned char* p, int n); diff --git a/muse/muse/midichannel.cpp b/muse/muse/midichannel.cpp new file mode 100644 index 00000000..afec354c --- /dev/null +++ b/muse/muse/midichannel.cpp @@ -0,0 +1,178 @@ +//============================================================================= +// 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 "midictrl.h" +#include "al/xml.h" +#include "midiedit/drummap.h" +#include "midichannel.h" +#include "midioutport.h" +#include "miditrack.h" + +//--------------------------------------------------------- +// MidiChannel +//--------------------------------------------------------- + +MidiChannel::MidiChannel(MidiOutPort* p, int ch) + : MidiTrackBase(MIDI_CHANNEL) + { + _port = p; + _channelNo = ch; + _drumMap = 0; + _useDrumMap = false; + initMidiController(); + + // + // create minimum set of managed controllers + // to make midi mixer operational + // + MidiInstrument* mi = port()->instrument(); + addMidiController(mi, CTRL_PROGRAM); + addMidiController(mi, CTRL_VOLUME); + addMidiController(mi, CTRL_PANPOT); + addMidiController(mi, CTRL_REVERB_SEND); + addMidiController(mi, CTRL_CHORUS_SEND); + addMidiController(mi, CTRL_VARIATION_SEND); + } + +//--------------------------------------------------------- +// MidiChannel +//--------------------------------------------------------- + +MidiChannel::~MidiChannel() + { + } + +//--------------------------------------------------------- +// MidiChannel::write +//--------------------------------------------------------- + +void MidiChannel::write(Xml& xml) const + { + xml.tag("MidiChannel idx=\"%d\"", _channelNo); + MidiTrackBase::writeProperties(xml); + xml.intTag("useDrumMap", _useDrumMap); + xml.etag("MidiChannel"); + } + +//--------------------------------------------------------- +// MidiChannel::read +//--------------------------------------------------------- + +void MidiChannel::read(QDomNode node) + { + QString drumMapName; + while (!node.isNull()) { + QDomElement e = node.toElement(); + QString tag(e.tagName()); + if (tag == "useDrumMap") + _useDrumMap = e.text().toInt(); + else if (MidiTrackBase::readProperties(node)) + printf("MusE:MidiChannel: unknown tag %s\n", tag.toLatin1().data()); + node = node.nextSibling(); + } + MidiOutPort* op = port(); + if (op) { + MidiInstrument* mi = op->instrument(); + int val = ctrlVal(CTRL_PROGRAM).i; + _drumMap = mi->getDrumMap(val); + } + } + +//--------------------------------------------------------- +// playMidiEvent +//--------------------------------------------------------- + +void MidiChannel::playMidiEvent(MidiEvent* ev) + { + if (ev->type() == ME_NOTEON) { + _meter[0] += ev->dataB()/2; + if (_meter[0] > 127.0f) + _meter[0] = 127.0f; + } + ev->setChannel(_channelNo); + _port->playMidiEvent(ev); + } + +//--------------------------------------------------------- +// setUseDrumMap +//--------------------------------------------------------- + +void MidiChannel::setUseDrumMap(bool val) + { + if (_useDrumMap != val) { + _useDrumMap = val; + if (_useDrumMap) { + int val = ctrlVal(CTRL_PROGRAM).i; + MidiOutPort* op = port(); + MidiInstrument* mi = op->instrument(); + DrumMap* dm = mi->getDrumMap(val); + if (dm == 0) + dm = &gmDrumMap; + _drumMap = dm; + } + else + _drumMap = &noDrumMap; + for (iRoute i = _inRoutes.begin(); i != _inRoutes.end(); ++i) { + MidiTrack* mt = (MidiTrack*)(i->track); + mt->changeDrumMap(); + } + emit useDrumMapChanged(_useDrumMap); + } + } + +//--------------------------------------------------------- +// emitControllerChanged +//--------------------------------------------------------- + +void MidiChannel::emitControllerChanged(int id) + { + if (id == CTRL_PROGRAM && _useDrumMap) { + int val = ctrlVal(id).i; + MidiOutPort* op = port(); + MidiInstrument* mi = op->instrument(); + DrumMap* dm = mi->getDrumMap(val); + if (dm == 0) + dm = &gmDrumMap; + if (dm != _drumMap) { + _drumMap = dm; + for (iRoute i = _inRoutes.begin(); i != _inRoutes.end(); ++i) { + MidiTrack* mt = (MidiTrack*)(i->track); + mt->changeDrumMap(); + } + } + } + emit controllerChanged(id); + } + +//--------------------------------------------------------- +// isMute +//--------------------------------------------------------- + +bool MidiChannel::isMute() const + { + if (_solo) + return false; + if (song->solo()) + return true; + return _mute; + } + + diff --git a/muse/muse/midichannel.h b/muse/muse/midichannel.h new file mode 100644 index 00000000..f0718da8 --- /dev/null +++ b/muse/muse/midichannel.h @@ -0,0 +1,72 @@ +//============================================================================= +// 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. +//============================================================================= + +#ifndef __MIDICHANNEL_H__ +#define __MIDICHANNEL_H__ + +#include "track.h" + +//--------------------------------------------------------- +// MidiChannel +//--------------------------------------------------------- + +class MidiOutPort; + +class MidiChannel : public MidiTrackBase { + Q_OBJECT + + DrumMap* _drumMap; + bool _useDrumMap; + MidiOutPort* _port; + int _channelNo; + + void clearDevice(); + + signals: + void useDrumMapChanged(bool); + + public: + MidiChannel(MidiOutPort*, int); + ~MidiChannel(); + + MidiOutPort* port() const { return _port; } + int channelNo() const { return _channelNo; } + + virtual void write(Xml&) const; + virtual void read(QDomNode); + virtual Track* newTrack() const { return 0; } + virtual bool isMute() const; + virtual Part* newPart(Part*, bool) { return 0; } + + bool guiVisible() const; + bool hasGui() const; + + // void putEvent(const MidiEvent&); + void playMidiEvent(MidiEvent* ev); + + bool useDrumMap() const { return _useDrumMap; } + void setUseDrumMap(bool val); + DrumMap* drumMap() const { return _drumMap; } + + virtual void emitControllerChanged(int id); + }; + +#endif + diff --git a/muse/muse/midiedit/ctrledit.cpp b/muse/muse/midiedit/ctrledit.cpp index 7f8fce99..08c3a5c1 100644 --- a/muse/muse/midiedit/ctrledit.cpp +++ b/muse/muse/midiedit/ctrledit.cpp @@ -26,6 +26,8 @@ #include "ctrl/ctrldialog.h" #include "widgets/tools.h" #include "miditrack.h" +#include "midioutport.h" +#include "midichannel.h" static Ctrl veloList(CTRL_VELOCITY, "velocity", Ctrl::DISCRETE |Ctrl::INT, 0.0, 127.0); // dummy static Ctrl sveloList(CTRL_SVELOCITY, "single velocity", Ctrl::DISCRETE |Ctrl::INT, 0.0, 127.0); // dummy diff --git a/muse/muse/midiinport.cpp b/muse/muse/midiinport.cpp new file mode 100644 index 00000000..ca49d97b --- /dev/null +++ b/muse/muse/midiinport.cpp @@ -0,0 +1,272 @@ +//============================================================================= +// 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 "midi.h" +#include "al/xml.h" +#include "driver/mididev.h" +#include "driver/audiodev.h" +#include "audio.h" + +#include "midiinport.h" + +//--------------------------------------------------------- +// MidiInPort +//--------------------------------------------------------- + +MidiInPort::MidiInPort() + : MidiTrackBase(MIDI_IN) + { + _alsaPort = 0; + _jackPort = 0; + } + +//--------------------------------------------------------- +// MidiInPort +//--------------------------------------------------------- + +MidiInPort::~MidiInPort() + { + if (_alsaPort) + midiDriver->unregisterPort(_alsaPort); + if (_jackPort) + audioDriver->unregisterPort(_jackPort); + } + +//--------------------------------------------------------- +// setName +//--------------------------------------------------------- + +void MidiInPort::setName(const QString& s) + { + Track::setName(s); + if (_alsaPort) + midiDriver->setPortName(_alsaPort, s); + if (_jackPort) + audioDriver->setPortName(_jackPort, s); + } + +//--------------------------------------------------------- +// MidiInPort::write +//--------------------------------------------------------- + +void MidiInPort::write(Xml& xml) const + { + xml.tag("MidiInPort"); + MidiTrackBase::writeProperties(xml); + xml.etag("MidiInPort"); + } + +//--------------------------------------------------------- +// MidiInPort::read +//--------------------------------------------------------- + +void MidiInPort::read(QDomNode node) + { + while (!node.isNull()) { + QDomElement e = node.toElement(); + QString tag(e.tagName()); + if (MidiTrackBase::readProperties(node)) + printf("MusE:MidiInPort: unknown tag %s\n", tag.toLatin1().data()); + node = node.nextSibling(); + } + } + +//--------------------------------------------------------- +// activate +//--------------------------------------------------------- + +void MidiInPort::activate1() + { + if (_alsaPort) + printf("MidiInPort::activate1(): alsa port already active!\n"); + else + _alsaPort = midiDriver->registerOutPort(_name, true); + if (_jackPort) + printf("MidiInPort::activate1(): jack port already active!\n"); + else + _jackPort = audioDriver->registerInPort(_name, true); + } + +//--------------------------------------------------------- +// activate2 +// connect all routes to jack; can only be done if +// jack is activ running +//--------------------------------------------------------- + +void MidiInPort::activate2() + { + if (audioState != AUDIO_RUNNING) { + printf("MidiInPort::activate2(): no audio running !\n"); + abort(); + } + for (iRoute i = _inRoutes.begin(); i != _inRoutes.end(); ++i) { + if (i->type == Route::JACKMIDIPORT) + audioDriver->connect(i->port, _jackPort); + else if (i->type == Route::MIDIPORT) + midiDriver->connect(i->port, _alsaPort); + else + printf("MidiInPort::activate2(): bad route type\n"); + } + } + +//--------------------------------------------------------- +// deactivate +//--------------------------------------------------------- + +void MidiInPort::deactivate() + { + for (ciRoute i = _inRoutes.begin(); i != _inRoutes.end(); ++i) { + if (i->type == Route::JACKMIDIPORT) + audioDriver->disconnect(i->port, _jackPort); + else if (i->type == Route::MIDIPORT) + midiDriver->disconnect(i->port, _alsaPort); + else + printf("MidiInPort::deactivate(): bad route type\n"); + } + if (_jackPort) { + audioDriver->unregisterPort(_jackPort); + _jackPort = 0; + } + else + printf("MidiInPort::deactivate(): jack port not active!\n"); + if (_alsaPort) { + audioDriver->unregisterPort(_alsaPort); + _alsaPort = 0; + } + else + printf("MidiInPort::deactivate(): alsa port not active!\n"); + } + +//--------------------------------------------------------- +// midiReceived +//--------------------------------------------------------- +#ifndef __APPLE__ +void MidiInPort::eventReceived(snd_seq_event_t* ev) + { + MidiEvent event; + event.setB(0); + event.setTime(audio->timestamp()); + + switch(ev->type) { + case SND_SEQ_EVENT_NOTEON: + event.setChannel(ev->data.note.channel); + event.setType(ME_NOTEON); + event.setA(ev->data.note.note); + event.setB(ev->data.note.velocity); + break; + + case SND_SEQ_EVENT_KEYPRESS: + event.setChannel(ev->data.note.channel); + event.setType(ME_POLYAFTER); + event.setA(ev->data.note.note); + event.setB(ev->data.note.velocity); + break; + + case SND_SEQ_EVENT_SYSEX: + event.setTime(0); // mark as used + event.setType(ME_SYSEX); + event.setData((unsigned char*)(ev->data.ext.ptr)+1, + ev->data.ext.len-2); + break; + + case SND_SEQ_EVENT_NOTEOFF: + event.setChannel(ev->data.note.channel); + event.setType(ME_NOTEOFF); + event.setA(ev->data.note.note); + event.setB(ev->data.note.velocity); + break; + + case SND_SEQ_EVENT_CHANPRESS: + event.setChannel(ev->data.control.channel); + event.setType(ME_AFTERTOUCH); + event.setA(ev->data.control.value); + break; + + case SND_SEQ_EVENT_PGMCHANGE: + event.setChannel(ev->data.control.channel); + event.setType(ME_PROGRAM); + event.setA(ev->data.control.value); + break; + + case SND_SEQ_EVENT_PITCHBEND: + event.setChannel(ev->data.control.channel); + event.setType(ME_PITCHBEND); + event.setA(ev->data.control.value); + break; + + case SND_SEQ_EVENT_CONTROLLER: + event.setChannel(ev->data.control.channel); + event.setType(ME_CONTROLLER); + event.setA(ev->data.control.param); + event.setB(ev->data.control.value); + break; + } + + if (midiInputTrace) { + printf("MidiInput<%s>: ", name().toLatin1().data()); + event.dump(); + } + // + // process midi filter pipeline and add event to + // _recordEvents + // + + MPEventList il, ol; + il.insert(event); + pipeline()->apply(audio->curTickPos(), audio->nextTickPos(), &il, &ol); + + // + // update midi meter + // notify gui of new events + // + for (iMPEvent i = ol.begin(); i != ol.end(); ++i) { + if (i->type() == ME_NOTEON) + addMidiMeter(i->dataB()); + song->putEvent(*i); + _recordEvents.add(*i); + } + } +#endif + +//--------------------------------------------------------- +// afterProcess +// clear all recorded events after a process cycle +//--------------------------------------------------------- + +void MidiInPort::afterProcess() + { + _recordEvents.clear(); + } + +//--------------------------------------------------------- +// getEvents +//--------------------------------------------------------- + +void MidiInPort::getEvents(unsigned, unsigned, int ch, MPEventList* dst) + { + for (iMPEvent i = _recordEvents.begin(); i != _recordEvents.end(); ++i) { + if (i->channel() == ch || ch == -1) + dst->insert(*i); + } + } + + diff --git a/muse/muse/midiinport.h b/muse/muse/midiinport.h new file mode 100644 index 00000000..a19393f9 --- /dev/null +++ b/muse/muse/midiinport.h @@ -0,0 +1,62 @@ +//============================================================================= +// 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. +//============================================================================= + +#ifndef __MIDIINPORT_H__ +#define __MIDIINPORT_H__ + +#include "track.h" + +//--------------------------------------------------------- +// MidiInPort +//--------------------------------------------------------- + +class MidiInPort : public MidiTrackBase { + Q_OBJECT + + Port _alsaPort; + Port _jackPort; + + MPEventList _recordEvents; + + public: + MidiInPort(); + ~MidiInPort(); + + virtual void activate1(); + virtual void activate2(); + virtual void deactivate(); + virtual void setName(const QString& s); + virtual void write(Xml&) const; + virtual void read(QDomNode); + virtual Track* newTrack() const { return new MidiInPort(); } + virtual bool isMute() const { return _mute; } + virtual Part* newPart(Part*, bool) { return 0; } + Port alsaPort() const { return _alsaPort; } + Port jackPort() const { return _jackPort; } + +#ifndef __APPLE__ + void eventReceived(snd_seq_event_t*); +#endif + virtual void getEvents(unsigned from, unsigned to, int channel, MPEventList* dst); + void afterProcess(); + }; + +#endif + diff --git a/muse/muse/midioutport.cpp b/muse/muse/midioutport.cpp new file mode 100644 index 00000000..23e079de --- /dev/null +++ b/muse/muse/midioutport.cpp @@ -0,0 +1,493 @@ +//============================================================================= +// 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/xml.h" +#include "driver/mididev.h" +#include "driver/audiodev.h" +#include "audio.h" +#include "midioutport.h" +#include "midichannel.h" + +//--------------------------------------------------------- +// MidiOutPort +//--------------------------------------------------------- + +MidiOutPort::MidiOutPort() + : MidiTrackBase(MIDI_OUT) + { + _instrument = genericMidiInstrument; + for (int ch = 0; ch < MIDI_CHANNELS; ++ch) + _channel[ch] = new MidiChannel(this, ch); + _alsaPort = 0; + _jackPort = 0; + _nextPlayEvent = _playEvents.end(); + _sendSync = false; + _deviceId = 127; // all + addMidiController(_instrument, CTRL_MASTER_VOLUME); + } + +//--------------------------------------------------------- +// playFifo +//--------------------------------------------------------- + +void MidiOutPort::playFifo() + { + while (!eventFifo.isEmpty()) + putEvent(eventFifo.get()); + } + +//--------------------------------------------------------- +// MidiOutPort +//--------------------------------------------------------- + +MidiOutPort::~MidiOutPort() + { + if (_alsaPort) + midiDriver->unregisterPort(_alsaPort); + if (_jackPort) + audioDriver->unregisterPort(_jackPort); + for (int ch = 0; ch < MIDI_CHANNEL; ++ch) + delete _channel[ch]; + } + +//--------------------------------------------------------- +// setName +//--------------------------------------------------------- + +void MidiOutPort::setName(const QString& s) + { + Track::setName(s); + if (_alsaPort) + midiDriver->setPortName(_alsaPort, s); + if (_jackPort) + audioDriver->setPortName(_jackPort, s); + for (int ch = 0; ch < MIDI_CHANNELS; ++ch) + _channel[ch]->setDefaultName(); + } + +//--------------------------------------------------------- +// MidiOutPort::write +//--------------------------------------------------------- + +void MidiOutPort::write(Xml& xml) const + { + xml.tag("MidiOutPort"); + MidiTrackBase::writeProperties(xml); + if (_instrument) + xml.strTag("instrument", _instrument->iname()); + for (int i = 0; i < MIDI_CHANNELS; ++i) { + if (!_channel[i]->noInRoute()) + _channel[i]->write(xml); + } + xml.intTag("sendSync", _sendSync); + xml.intTag("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 == "MidiChannel") { + int idx = e.attribute("idx", "0").toInt(); + _channel[idx]->read(node.firstChild()); + } + else if (tag == "instrument") { + QString iname = e.text(); + _instrument = registerMidiInstrument(iname); + } + else if (tag == "sendSync") + _sendSync = e.text().toInt(); + else if (tag == "deviceId") + _deviceId = e.text().toInt(); + else if (MidiTrackBase::readProperties(node)) + printf("MusE:MidiOutPort: unknown tag %s\n", tag.toLatin1().data()); + } + } + +//--------------------------------------------------------- +// activate +//--------------------------------------------------------- + +void MidiOutPort::activate1() + { + if (_jackPort) + printf("MidiOutPort::activate1(): jack port already active!\n"); + else + _jackPort = audioDriver->registerOutPort(_name, true); + if (_alsaPort) + printf("MidiOutPort::activate1(): alsa port already active!\n"); + else + _alsaPort = midiDriver->registerInPort(_name, true); + } + +//--------------------------------------------------------- +// activate2 +// connect all routes to jack; can only be done if +// jack is activ running +//--------------------------------------------------------- + +void MidiOutPort::activate2() + { + if (audioState != AUDIO_RUNNING) { + printf("MidiOutPort::activate2(): no audio running !\n"); + abort(); + } + for (iRoute i = _outRoutes.begin(); i != _outRoutes.end(); ++i) { + if (i->type == Route::JACKMIDIPORT) + audioDriver->connect(_jackPort, i->port); + else if (i->type == Route::MIDIPORT) + midiDriver->connect(_alsaPort, i->port); + else + printf("MidiOutPort::activate2(): bad route type\n"); + } + } + +//--------------------------------------------------------- +// deactivate +//--------------------------------------------------------- + +void MidiOutPort::deactivate() + { + for (ciRoute i = _outRoutes.begin(); i != _outRoutes.end(); ++i) { + if (i->type ==Route::JACKMIDIPORT) + audioDriver->disconnect(_jackPort, i->port); + else if (i->type == Route::MIDIPORT) + midiDriver->disconnect(_alsaPort, i->port); + } + if (_jackPort) { + audioDriver->unregisterPort(_jackPort); + _jackPort = 0; + } + else + printf("MidiInPort::deactivate(): jack port not active!\n"); + if (_alsaPort) { + midiDriver->unregisterPort(_alsaPort); + _alsaPort = 0; + } + else + printf("MidiInPort::deactivate(): alsa port not active!\n"); + } + +//--------------------------------------------------------- +// putEvent +// send event to midi driver +//--------------------------------------------------------- + +void MidiOutPort::putEvent(const MidiEvent& ev) + { + if (ev.type() == ME_CONTROLLER) { + int a = ev.dataA(); + int b = ev.dataB(); + int chn = ev.channel(); + if (chn == 255) { + // port controller + if (hwCtrlState(a) == ev.dataB()) + return; + setHwCtrlState(a, b); + } + else { + MidiChannel* mc = channel(chn); + // + // optimize controller settings + // + if (mc->hwCtrlState(a) == ev.dataB()) + return; + mc->setHwCtrlState(a, b); + } + + if (a == CTRL_PITCH) { + midiDriver->putEvent(_alsaPort, MidiEvent(0, chn, ME_PITCHBEND, b, 0)); + return; + } + 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) + midiDriver->putEvent(_alsaPort, MidiEvent(0, chn, ME_CONTROLLER, CTRL_HBANK, hb)); + if (lb != 0xff) + midiDriver->putEvent(_alsaPort, MidiEvent(0, chn, ME_CONTROLLER, CTRL_LBANK, lb)); + midiDriver->putEvent(_alsaPort, MidiEvent(0, chn, ME_PROGRAM, pr, 0)); + return; +// } + } + 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; + MidiEvent e(ev.time(), ME_SYSEX, sysex, 6); + midiDriver->putEvent(_alsaPort, e); + return; + } + +#if 1 // if ALSA cannot handle RPN NRPN etc. + if (a < 0x1000) { // 7 Bit Controller + //putMidiEvent(MidiEvent(0, chn, ME_CONTROLLER, a, b)); + midiDriver->putEvent(_alsaPort, ev); + } + else if (a < 0x20000) { // 14 bit high resolution controller + int ctrlH = (a >> 8) & 0x7f; + int ctrlL = a & 0x7f; + int dataH = (b >> 7) & 0x7f; + int dataL = b & 0x7f; + midiDriver->putEvent(_alsaPort, MidiEvent(0, chn, ME_CONTROLLER, ctrlH, dataH)); + midiDriver->putEvent(_alsaPort, MidiEvent(0, chn, ME_CONTROLLER, ctrlL, dataL)); + } + else if (a < 0x30000) { // RPN 7-Bit Controller + int ctrlH = (a >> 8) & 0x7f; + int ctrlL = a & 0x7f; + midiDriver->putEvent(_alsaPort, MidiEvent(0, chn, ME_CONTROLLER, CTRL_HRPN, ctrlH)); + midiDriver->putEvent(_alsaPort, MidiEvent(0, chn, ME_CONTROLLER, CTRL_LRPN, ctrlL)); + midiDriver->putEvent(_alsaPort, MidiEvent(0, chn, ME_CONTROLLER, CTRL_HDATA, b)); + } + else if (a < 0x40000) { // NRPN 7-Bit Controller + int ctrlH = (a >> 8) & 0x7f; + int ctrlL = a & 0x7f; + midiDriver->putEvent(_alsaPort, MidiEvent(0, chn, ME_CONTROLLER, CTRL_HNRPN, ctrlH)); + midiDriver->putEvent(_alsaPort, MidiEvent(0, chn, ME_CONTROLLER, CTRL_LNRPN, ctrlL)); + midiDriver->putEvent(_alsaPort, MidiEvent(0, chn, ME_CONTROLLER, CTRL_HDATA, b)); + } + else if (a < 0x60000) { // RPN14 Controller + int ctrlH = (a >> 8) & 0x7f; + int ctrlL = a & 0x7f; + int dataH = (b >> 7) & 0x7f; + int dataL = b & 0x7f; + midiDriver->putEvent(_alsaPort, MidiEvent(0, chn, ME_CONTROLLER, CTRL_HRPN, ctrlH)); + midiDriver->putEvent(_alsaPort, MidiEvent(0, chn, ME_CONTROLLER, CTRL_LRPN, ctrlL)); + midiDriver->putEvent(_alsaPort, MidiEvent(0, chn, ME_CONTROLLER, CTRL_HDATA, dataH)); + midiDriver->putEvent(_alsaPort, MidiEvent(0, chn, ME_CONTROLLER, CTRL_LDATA, dataL)); + } + else if (a < 0x70000) { // NRPN14 Controller + int ctrlH = (a >> 8) & 0x7f; + int ctrlL = a & 0x7f; + int dataH = (b >> 7) & 0x7f; + int dataL = b & 0x7f; + midiDriver->putEvent(_alsaPort, MidiEvent(0, chn, ME_CONTROLLER, CTRL_HNRPN, ctrlH)); + midiDriver->putEvent(_alsaPort, MidiEvent(0, chn, ME_CONTROLLER, CTRL_LNRPN, ctrlL)); + midiDriver->putEvent(_alsaPort, MidiEvent(0, chn, ME_CONTROLLER, CTRL_HDATA, dataH)); + midiDriver->putEvent(_alsaPort, MidiEvent(0, chn, ME_CONTROLLER, CTRL_LDATA, dataL)); + } + else { + printf("putEvent: unknown controller type 0x%x\n", a); + } +#endif + } + midiDriver->putEvent(_alsaPort, ev); + } + +//--------------------------------------------------------- +// playEventList +//--------------------------------------------------------- + +void MidiOutPort::playEventList() + { + for (; _nextPlayEvent != _playEvents.end(); ++_nextPlayEvent) + midiDriver->putEvent(_alsaPort, *_nextPlayEvent); + } + +//--------------------------------------------------------- +// 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); + putEvent(event); + } + +//--------------------------------------------------------- +// sendStart +//--------------------------------------------------------- + +void MidiOutPort::sendStart() + { + MidiEvent event(0, 0, ME_START, 0, 0); + putEvent(event); + } + +//--------------------------------------------------------- +// sendStop +//--------------------------------------------------------- + +void MidiOutPort::sendStop() + { + MidiEvent event(0, 0, ME_STOP, 0, 0); + putEvent(event); + } + +//--------------------------------------------------------- +// sendClock +//--------------------------------------------------------- + +void MidiOutPort::sendClock() + { + MidiEvent event(0, 0, ME_CLOCK, 0, 0); + putEvent(event); + } + +//--------------------------------------------------------- +// sendContinue +//--------------------------------------------------------- + +void MidiOutPort::sendContinue() + { + MidiEvent event(0, 0, ME_CONTINUE, 0, 0); + putEvent(event); + } + +//--------------------------------------------------------- +// sendSongpos +//--------------------------------------------------------- + +void MidiOutPort::sendSongpos(int pos) + { + MidiEvent event(0, 0, ME_SONGPOS, pos, 0); + putEvent(event); + } + +//--------------------------------------------------------- +// playMidiEvent +// called from GUI +//--------------------------------------------------------- + +void MidiOutPort::playMidiEvent(MidiEvent* ev) + { + if (ev->type() == ME_NOTEON) { + _meter[0] += ev->dataB()/2; + if (_meter[0] > 127.0f) + _meter[0] = 127.0f; + } + RouteList* orl = outRoutes(); + bool sendToFifo = false; + for (iRoute i = orl->begin(); i != orl->end(); ++i) { + if (i->type == Route::MIDIPORT) + sendToFifo = true; + else if (i->type == Route::SYNTIPORT) { + SynthI* synti = (SynthI*)i->track; + if (synti->eventFifo()->put(*ev)) + printf("MidiOut::playMidiEvent(): synti overflow, drop event\n"); + } + else + printf("MidiOutPort::playMidiEvent: bad route type\n"); + } + if (sendToFifo) { + if (eventFifo.put(*ev)) + printf("MidiPort::playMidiEvent(): port overflow, drop event\n"); + } + } + +//--------------------------------------------------------- +// setInstrument +//--------------------------------------------------------- + +void MidiOutPort::setInstrument(MidiInstrument* i) + { + _instrument = i; + emit instrumentChanged(); + } + +//--------------------------------------------------------- +// setSendSync +//--------------------------------------------------------- + +void MidiOutPort::setSendSync(bool val) + { + _sendSync = val; + emit sendSyncChanged(val); + } + + diff --git a/muse/muse/midioutport.h b/muse/muse/midioutport.h new file mode 100644 index 00000000..311b2bff --- /dev/null +++ b/muse/muse/midioutport.h @@ -0,0 +1,109 @@ +//============================================================================= +// 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. +//============================================================================= + +#ifndef __MIDIOUTPORT_H__ +#define __MIDIOUTPORT_H__ + +#include "track.h" + +//--------------------------------------------------------- +// MidiOutPort +//--------------------------------------------------------- + +class MidiOutPort : public MidiTrackBase { + Q_OBJECT + + MidiInstrument* _instrument; + MidiChannel* _channel[MIDI_CHANNELS]; + Port _alsaPort; + Port _jackPort; + + bool _sendSync; // this port sends mtc mmc events + int _deviceId; // 0-126; 127 == all + + MPEventList _playEvents; // scheduled events to play + iMPEvent _nextPlayEvent; + + // fifo for midi events send from gui + // direct to midi port: + + MidiFifo eventFifo; + + signals: + void instrumentChanged(); + void sendSyncChanged(bool); + + public: + MidiOutPort(); + ~MidiOutPort(); + + virtual void activate1(); + virtual void activate2(); + virtual void deactivate(); + + MidiChannel* channel(int n) { return _channel[n]; } + + virtual void setName(const QString& s); + virtual void write(Xml&) const; + virtual void read(QDomNode); + virtual Track* newTrack() const { return new MidiOutPort(); } + virtual bool isMute() const { return _mute; } + virtual Part* newPart(Part*, bool) { return 0; } + + MidiInstrument* instrument() const { return _instrument; } + void setInstrument(MidiInstrument* i); + + bool guiVisible() const; + bool hasGui() const; + + Port alsaPort() const { return _alsaPort; } + Port jackPort() const { return _jackPort; } + void putEvent(const MidiEvent&); + + MPEventList* playEvents() { return &_playEvents; } + iMPEvent nextPlayEvent() { return _nextPlayEvent; } + + void process(unsigned from, unsigned to, const AL::Pos&, unsigned frames); + + void setNextPlayEvent(iMPEvent i) { _nextPlayEvent = i; } + void playFifo(); + 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(); + + void playEventList(); + + bool sendSync() const { return _sendSync; } + void setSendSync(bool val); + + int deviceId() const { return _deviceId; } + void setDeviceId(int val) { _deviceId = val; } + }; + +#endif + diff --git a/muse/muse/midiport.cpp b/muse/muse/midiport.cpp deleted file mode 100644 index 5b7245cf..00000000 --- a/muse/muse/midiport.cpp +++ /dev/null @@ -1,899 +0,0 @@ -//============================================================================= -// 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 "globals.h" -#include "midi.h" -#include "instruments/minstrument.h" -#include "al/xml.h" -#include "driver/mididev.h" -#include "driver/audiodev.h" -#include "audio.h" -#include "midiedit/drummap.h" - -//--------------------------------------------------------- -// midiPortsPopup -//--------------------------------------------------------- - -QMenu* midiPortsPopup(QWidget* parent) - { - QMenu* p = new QMenu(parent); - MidiOutPortList* mpl = song->midiOutPorts(); - for (iMidiOutPort i = mpl->begin(); i != mpl->end(); ++i) { - MidiOutPort* port = *i; - p->addAction(port->name()); - } - return p; - } - -//--------------------------------------------------------- -// MidiOutPort -//--------------------------------------------------------- - -MidiOutPort::MidiOutPort() - : MidiTrackBase(MIDI_OUT) - { - _instrument = genericMidiInstrument; - for (int ch = 0; ch < MIDI_CHANNELS; ++ch) - _channel[ch] = new MidiChannel(this, ch); - _alsaPort = 0; - _jackPort = 0; - _nextPlayEvent = _playEvents.end(); - _sendSync = false; - _deviceId = 127; // all - addMidiController(_instrument, CTRL_MASTER_VOLUME); - } - -//--------------------------------------------------------- -// playFifo -//--------------------------------------------------------- - -void MidiOutPort::playFifo() - { - while (!eventFifo.isEmpty()) - putEvent(eventFifo.get()); - } - -//--------------------------------------------------------- -// MidiOutPort -//--------------------------------------------------------- - -MidiOutPort::~MidiOutPort() - { - if (_alsaPort) - midiDriver->unregisterPort(_alsaPort); - if (_jackPort) - audioDriver->unregisterPort(_jackPort); - for (int ch = 0; ch < MIDI_CHANNEL; ++ch) - delete _channel[ch]; - } - -//--------------------------------------------------------- -// setName -//--------------------------------------------------------- - -void MidiOutPort::setName(const QString& s) - { - Track::setName(s); - if (_alsaPort) - midiDriver->setPortName(_alsaPort, s); - if (_jackPort) - audioDriver->setPortName(_jackPort, s); - for (int ch = 0; ch < MIDI_CHANNELS; ++ch) - _channel[ch]->setDefaultName(); - } - -//--------------------------------------------------------- -// MidiOutPort::write -//--------------------------------------------------------- - -void MidiOutPort::write(Xml& xml) const - { - xml.tag("MidiOutPort"); - MidiTrackBase::writeProperties(xml); - if (_instrument) - xml.strTag("instrument", _instrument->iname()); - for (int i = 0; i < MIDI_CHANNELS; ++i) { - if (!_channel[i]->noInRoute()) - _channel[i]->write(xml); - } - xml.intTag("sendSync", _sendSync); - xml.intTag("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 == "MidiChannel") { - int idx = e.attribute("idx", "0").toInt(); - _channel[idx]->read(node.firstChild()); - } - else if (tag == "instrument") { - QString iname = e.text(); - _instrument = registerMidiInstrument(iname); - } - else if (tag == "sendSync") - _sendSync = e.text().toInt(); - else if (tag == "deviceId") - _deviceId = e.text().toInt(); - else if (MidiTrackBase::readProperties(node)) - printf("MusE:MidiOutPort: unknown tag %s\n", tag.toLatin1().data()); - } - } - -//--------------------------------------------------------- -// activate -//--------------------------------------------------------- - -void MidiOutPort::activate1() - { - if (_jackPort) - printf("MidiOutPort::activate1(): jack port already active!\n"); - else - _jackPort = audioDriver->registerOutPort(_name, true); - if (_alsaPort) - printf("MidiOutPort::activate1(): alsa port already active!\n"); - else - _alsaPort = midiDriver->registerInPort(_name, true); - } - -//--------------------------------------------------------- -// activate2 -// connect all routes to jack; can only be done if -// jack is activ running -//--------------------------------------------------------- - -void MidiOutPort::activate2() - { - if (audioState != AUDIO_RUNNING) { - printf("MidiOutPort::activate2(): no audio running !\n"); - abort(); - } - for (iRoute i = _outRoutes.begin(); i != _outRoutes.end(); ++i) { - if (i->type == Route::JACKMIDIPORT) - audioDriver->connect(_jackPort, i->port); - else if (i->type == Route::MIDIPORT) - midiDriver->connect(_alsaPort, i->port); - else - printf("MidiOutPort::activate2(): bad route type\n"); - } - } - -//--------------------------------------------------------- -// deactivate -//--------------------------------------------------------- - -void MidiOutPort::deactivate() - { - for (ciRoute i = _outRoutes.begin(); i != _outRoutes.end(); ++i) { - if (i->type ==Route::JACKMIDIPORT) - audioDriver->disconnect(_jackPort, i->port); - else if (i->type == Route::MIDIPORT) - midiDriver->disconnect(_alsaPort, i->port); - } - if (_jackPort) { - audioDriver->unregisterPort(_jackPort); - _jackPort = 0; - } - else - printf("MidiInPort::deactivate(): jack port not active!\n"); - if (_alsaPort) { - midiDriver->unregisterPort(_alsaPort); - _alsaPort = 0; - } - else - printf("MidiInPort::deactivate(): alsa port not active!\n"); - } - -//--------------------------------------------------------- -// putEvent -// send event to midi driver -//--------------------------------------------------------- - -void MidiOutPort::putEvent(const MidiEvent& ev) - { - if (ev.type() == ME_CONTROLLER) { - int a = ev.dataA(); - int b = ev.dataB(); - int chn = ev.channel(); - if (chn == 255) { - // port controller - if (hwCtrlState(a) == ev.dataB()) - return; - setHwCtrlState(a, b); - } - else { - MidiChannel* mc = channel(chn); - // - // optimize controller settings - // - if (mc->hwCtrlState(a) == ev.dataB()) - return; - mc->setHwCtrlState(a, b); - } - - if (a == CTRL_PITCH) { - midiDriver->putEvent(_alsaPort, MidiEvent(0, chn, ME_PITCHBEND, b, 0)); - return; - } - 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) - midiDriver->putEvent(_alsaPort, MidiEvent(0, chn, ME_CONTROLLER, CTRL_HBANK, hb)); - if (lb != 0xff) - midiDriver->putEvent(_alsaPort, MidiEvent(0, chn, ME_CONTROLLER, CTRL_LBANK, lb)); - midiDriver->putEvent(_alsaPort, MidiEvent(0, chn, ME_PROGRAM, pr, 0)); - return; -// } - } - 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; - MidiEvent e(ev.time(), ME_SYSEX, sysex, 6); - midiDriver->putEvent(_alsaPort, e); - return; - } - -#if 1 // if ALSA cannot handle RPN NRPN etc. - if (a < 0x1000) { // 7 Bit Controller - //putMidiEvent(MidiEvent(0, chn, ME_CONTROLLER, a, b)); - midiDriver->putEvent(_alsaPort, ev); - } - else if (a < 0x20000) { // 14 bit high resolution controller - int ctrlH = (a >> 8) & 0x7f; - int ctrlL = a & 0x7f; - int dataH = (b >> 7) & 0x7f; - int dataL = b & 0x7f; - midiDriver->putEvent(_alsaPort, MidiEvent(0, chn, ME_CONTROLLER, ctrlH, dataH)); - midiDriver->putEvent(_alsaPort, MidiEvent(0, chn, ME_CONTROLLER, ctrlL, dataL)); - } - else if (a < 0x30000) { // RPN 7-Bit Controller - int ctrlH = (a >> 8) & 0x7f; - int ctrlL = a & 0x7f; - midiDriver->putEvent(_alsaPort, MidiEvent(0, chn, ME_CONTROLLER, CTRL_HRPN, ctrlH)); - midiDriver->putEvent(_alsaPort, MidiEvent(0, chn, ME_CONTROLLER, CTRL_LRPN, ctrlL)); - midiDriver->putEvent(_alsaPort, MidiEvent(0, chn, ME_CONTROLLER, CTRL_HDATA, b)); - } - else if (a < 0x40000) { // NRPN 7-Bit Controller - int ctrlH = (a >> 8) & 0x7f; - int ctrlL = a & 0x7f; - midiDriver->putEvent(_alsaPort, MidiEvent(0, chn, ME_CONTROLLER, CTRL_HNRPN, ctrlH)); - midiDriver->putEvent(_alsaPort, MidiEvent(0, chn, ME_CONTROLLER, CTRL_LNRPN, ctrlL)); - midiDriver->putEvent(_alsaPort, MidiEvent(0, chn, ME_CONTROLLER, CTRL_HDATA, b)); - } - else if (a < 0x60000) { // RPN14 Controller - int ctrlH = (a >> 8) & 0x7f; - int ctrlL = a & 0x7f; - int dataH = (b >> 7) & 0x7f; - int dataL = b & 0x7f; - midiDriver->putEvent(_alsaPort, MidiEvent(0, chn, ME_CONTROLLER, CTRL_HRPN, ctrlH)); - midiDriver->putEvent(_alsaPort, MidiEvent(0, chn, ME_CONTROLLER, CTRL_LRPN, ctrlL)); - midiDriver->putEvent(_alsaPort, MidiEvent(0, chn, ME_CONTROLLER, CTRL_HDATA, dataH)); - midiDriver->putEvent(_alsaPort, MidiEvent(0, chn, ME_CONTROLLER, CTRL_LDATA, dataL)); - } - else if (a < 0x70000) { // NRPN14 Controller - int ctrlH = (a >> 8) & 0x7f; - int ctrlL = a & 0x7f; - int dataH = (b >> 7) & 0x7f; - int dataL = b & 0x7f; - midiDriver->putEvent(_alsaPort, MidiEvent(0, chn, ME_CONTROLLER, CTRL_HNRPN, ctrlH)); - midiDriver->putEvent(_alsaPort, MidiEvent(0, chn, ME_CONTROLLER, CTRL_LNRPN, ctrlL)); - midiDriver->putEvent(_alsaPort, MidiEvent(0, chn, ME_CONTROLLER, CTRL_HDATA, dataH)); - midiDriver->putEvent(_alsaPort, MidiEvent(0, chn, ME_CONTROLLER, CTRL_LDATA, dataL)); - } - else { - printf("putEvent: unknown controller type 0x%x\n", a); - } -#endif - } - midiDriver->putEvent(_alsaPort, ev); - } - -//--------------------------------------------------------- -// playEventList -//--------------------------------------------------------- - -void MidiOutPort::playEventList() - { - for (; _nextPlayEvent != _playEvents.end(); ++_nextPlayEvent) - midiDriver->putEvent(_alsaPort, *_nextPlayEvent); - } - -//--------------------------------------------------------- -// 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); - putEvent(event); - } - -//--------------------------------------------------------- -// sendStart -//--------------------------------------------------------- - -void MidiOutPort::sendStart() - { - MidiEvent event(0, 0, ME_START, 0, 0); - putEvent(event); - } - -//--------------------------------------------------------- -// sendStop -//--------------------------------------------------------- - -void MidiOutPort::sendStop() - { - MidiEvent event(0, 0, ME_STOP, 0, 0); - putEvent(event); - } - -//--------------------------------------------------------- -// sendClock -//--------------------------------------------------------- - -void MidiOutPort::sendClock() - { - MidiEvent event(0, 0, ME_CLOCK, 0, 0); - putEvent(event); - } - -//--------------------------------------------------------- -// sendContinue -//--------------------------------------------------------- - -void MidiOutPort::sendContinue() - { - MidiEvent event(0, 0, ME_CONTINUE, 0, 0); - putEvent(event); - } - -//--------------------------------------------------------- -// sendSongpos -//--------------------------------------------------------- - -void MidiOutPort::sendSongpos(int pos) - { - MidiEvent event(0, 0, ME_SONGPOS, pos, 0); - putEvent(event); - } - -//--------------------------------------------------------- -// playMidiEvent -// called from GUI -//--------------------------------------------------------- - -void MidiOutPort::playMidiEvent(MidiEvent* ev) - { - if (ev->type() == ME_NOTEON) { - _meter[0] += ev->dataB()/2; - if (_meter[0] > 127.0f) - _meter[0] = 127.0f; - } - RouteList* orl = outRoutes(); - bool sendToFifo = false; - for (iRoute i = orl->begin(); i != orl->end(); ++i) { - if (i->type == Route::MIDIPORT) - sendToFifo = true; - else if (i->type == Route::SYNTIPORT) { - SynthI* synti = (SynthI*)i->track; - if (synti->eventFifo()->put(*ev)) - printf("MidiOut::playMidiEvent(): synti overflow, drop event\n"); - } - else - printf("MidiOutPort::playMidiEvent: bad route type\n"); - } - if (sendToFifo) { - if (eventFifo.put(*ev)) - printf("MidiPort::playMidiEvent(): port overflow, drop event\n"); - } - } - -//--------------------------------------------------------- -// setInstrument -//--------------------------------------------------------- - -void MidiOutPort::setInstrument(MidiInstrument* i) - { - _instrument = i; - emit instrumentChanged(); - } - -//--------------------------------------------------------- -// setSendSync -//--------------------------------------------------------- - -void MidiOutPort::setSendSync(bool val) - { - _sendSync = val; - emit sendSyncChanged(val); - } - -//--------------------------------------------------------- -// MidiInPort -//--------------------------------------------------------- - -MidiInPort::MidiInPort() - : MidiTrackBase(MIDI_IN) - { - _alsaPort = 0; - _jackPort = 0; - } - -//--------------------------------------------------------- -// MidiInPort -//--------------------------------------------------------- - -MidiInPort::~MidiInPort() - { - if (_alsaPort) - midiDriver->unregisterPort(_alsaPort); - if (_jackPort) - audioDriver->unregisterPort(_jackPort); - } - -//--------------------------------------------------------- -// setName -//--------------------------------------------------------- - -void MidiInPort::setName(const QString& s) - { - Track::setName(s); - if (_alsaPort) - midiDriver->setPortName(_alsaPort, s); - if (_jackPort) - audioDriver->setPortName(_jackPort, s); - } - -//--------------------------------------------------------- -// MidiInPort::write -//--------------------------------------------------------- - -void MidiInPort::write(Xml& xml) const - { - xml.tag("MidiInPort"); - MidiTrackBase::writeProperties(xml); - xml.etag("MidiInPort"); - } - -//--------------------------------------------------------- -// MidiInPort::read -//--------------------------------------------------------- - -void MidiInPort::read(QDomNode node) - { - while (!node.isNull()) { - QDomElement e = node.toElement(); - QString tag(e.tagName()); - if (MidiTrackBase::readProperties(node)) - printf("MusE:MidiInPort: unknown tag %s\n", tag.toLatin1().data()); - node = node.nextSibling(); - } - } - -//--------------------------------------------------------- -// activate -//--------------------------------------------------------- - -void MidiInPort::activate1() - { - if (_alsaPort) - printf("MidiInPort::activate1(): alsa port already active!\n"); - else - _alsaPort = midiDriver->registerOutPort(_name, true); - if (_jackPort) - printf("MidiInPort::activate1(): jack port already active!\n"); - else - _jackPort = audioDriver->registerInPort(_name, true); - } - -//--------------------------------------------------------- -// activate2 -// connect all routes to jack; can only be done if -// jack is activ running -//--------------------------------------------------------- - -void MidiInPort::activate2() - { - if (audioState != AUDIO_RUNNING) { - printf("MidiInPort::activate2(): no audio running !\n"); - abort(); - } - for (iRoute i = _inRoutes.begin(); i != _inRoutes.end(); ++i) { - if (i->type == Route::JACKMIDIPORT) - audioDriver->connect(i->port, _jackPort); - else if (i->type == Route::MIDIPORT) - midiDriver->connect(i->port, _alsaPort); - else - printf("MidiInPort::activate2(): bad route type\n"); - } - } - -//--------------------------------------------------------- -// deactivate -//--------------------------------------------------------- - -void MidiInPort::deactivate() - { - for (ciRoute i = _inRoutes.begin(); i != _inRoutes.end(); ++i) { - if (i->type == Route::JACKMIDIPORT) - audioDriver->disconnect(i->port, _jackPort); - else if (i->type == Route::MIDIPORT) - midiDriver->disconnect(i->port, _alsaPort); - else - printf("MidiInPort::deactivate(): bad route type\n"); - } - if (_jackPort) { - audioDriver->unregisterPort(_jackPort); - _jackPort = 0; - } - else - printf("MidiInPort::deactivate(): jack port not active!\n"); - if (_alsaPort) { - audioDriver->unregisterPort(_alsaPort); - _alsaPort = 0; - } - else - printf("MidiInPort::deactivate(): alsa port not active!\n"); - } - -//--------------------------------------------------------- -// midiReceived -//--------------------------------------------------------- -#ifndef __APPLE__ -void MidiInPort::eventReceived(snd_seq_event_t* ev) - { - MidiEvent event; - event.setB(0); - event.setTime(audio->timestamp()); - - switch(ev->type) { - case SND_SEQ_EVENT_NOTEON: - event.setChannel(ev->data.note.channel); - event.setType(ME_NOTEON); - event.setA(ev->data.note.note); - event.setB(ev->data.note.velocity); - break; - - case SND_SEQ_EVENT_KEYPRESS: - event.setChannel(ev->data.note.channel); - event.setType(ME_POLYAFTER); - event.setA(ev->data.note.note); - event.setB(ev->data.note.velocity); - break; - - case SND_SEQ_EVENT_SYSEX: - event.setTime(0); // mark as used - event.setType(ME_SYSEX); - event.setData((unsigned char*)(ev->data.ext.ptr)+1, - ev->data.ext.len-2); - break; - - case SND_SEQ_EVENT_NOTEOFF: - event.setChannel(ev->data.note.channel); - event.setType(ME_NOTEOFF); - event.setA(ev->data.note.note); - event.setB(ev->data.note.velocity); - break; - - case SND_SEQ_EVENT_CHANPRESS: - event.setChannel(ev->data.control.channel); - event.setType(ME_AFTERTOUCH); - event.setA(ev->data.control.value); - break; - - case SND_SEQ_EVENT_PGMCHANGE: - event.setChannel(ev->data.control.channel); - event.setType(ME_PROGRAM); - event.setA(ev->data.control.value); - break; - - case SND_SEQ_EVENT_PITCHBEND: - event.setChannel(ev->data.control.channel); - event.setType(ME_PITCHBEND); - event.setA(ev->data.control.value); - break; - - case SND_SEQ_EVENT_CONTROLLER: - event.setChannel(ev->data.control.channel); - event.setType(ME_CONTROLLER); - event.setA(ev->data.control.param); - event.setB(ev->data.control.value); - break; - } - - if (midiInputTrace) { - printf("MidiInput<%s>: ", name().toLatin1().data()); - event.dump(); - } - // - // process midi filter pipeline and add event to - // _recordEvents - // - - MPEventList il, ol; - il.insert(event); - pipeline()->apply(audio->curTickPos(), audio->nextTickPos(), &il, &ol); - - // - // update midi meter - // notify gui of new events - // - for (iMPEvent i = ol.begin(); i != ol.end(); ++i) { - if (i->type() == ME_NOTEON) - addMidiMeter(i->dataB()); - song->putEvent(*i); - _recordEvents.add(*i); - } - } -#endif - -//--------------------------------------------------------- -// afterProcess -// clear all recorded events after a process cycle -//--------------------------------------------------------- - -void MidiInPort::afterProcess() - { - _recordEvents.clear(); - } - -//--------------------------------------------------------- -// getEvents -//--------------------------------------------------------- - -void MidiInPort::getEvents(unsigned, unsigned, int ch, MPEventList* dst) - { - for (iMPEvent i = _recordEvents.begin(); i != _recordEvents.end(); ++i) { - if (i->channel() == ch || ch == -1) - dst->insert(*i); - } - } - -//--------------------------------------------------------- -// MidiChannel -//--------------------------------------------------------- - -MidiChannel::MidiChannel(MidiOutPort* p, int ch) - : MidiTrackBase(MIDI_CHANNEL) - { - _port = p; - _channelNo = ch; - _drumMap = 0; - _useDrumMap = false; - initMidiController(); - - // - // create minimum set of managed controllers - // to make midi mixer operational - // - MidiInstrument* mi = port()->instrument(); - addMidiController(mi, CTRL_PROGRAM); - addMidiController(mi, CTRL_VOLUME); - addMidiController(mi, CTRL_PANPOT); - addMidiController(mi, CTRL_REVERB_SEND); - addMidiController(mi, CTRL_CHORUS_SEND); - addMidiController(mi, CTRL_VARIATION_SEND); - } - -//--------------------------------------------------------- -// MidiChannel -//--------------------------------------------------------- - -MidiChannel::~MidiChannel() - { - } - -//--------------------------------------------------------- -// MidiChannel::write -//--------------------------------------------------------- - -void MidiChannel::write(Xml& xml) const - { - xml.tag("MidiChannel idx=\"%d\"", _channelNo); - MidiTrackBase::writeProperties(xml); - xml.intTag("useDrumMap", _useDrumMap); - xml.etag("MidiChannel"); - } - -//--------------------------------------------------------- -// MidiChannel::read -//--------------------------------------------------------- - -void MidiChannel::read(QDomNode node) - { - QString drumMapName; - while (!node.isNull()) { - QDomElement e = node.toElement(); - QString tag(e.tagName()); - if (tag == "useDrumMap") - _useDrumMap = e.text().toInt(); - else if (MidiTrackBase::readProperties(node)) - printf("MusE:MidiChannel: unknown tag %s\n", tag.toLatin1().data()); - node = node.nextSibling(); - } - MidiOutPort* op = port(); - if (op) { - MidiInstrument* mi = op->instrument(); - int val = ctrlVal(CTRL_PROGRAM).i; - _drumMap = mi->getDrumMap(val); - } - } - -//--------------------------------------------------------- -// playMidiEvent -//--------------------------------------------------------- - -void MidiChannel::playMidiEvent(MidiEvent* ev) - { - if (ev->type() == ME_NOTEON) { - _meter[0] += ev->dataB()/2; - if (_meter[0] > 127.0f) - _meter[0] = 127.0f; - } - ev->setChannel(_channelNo); - _port->playMidiEvent(ev); - } - -//--------------------------------------------------------- -// setUseDrumMap -//--------------------------------------------------------- - -void MidiChannel::setUseDrumMap(bool val) - { - if (_useDrumMap != val) { - _useDrumMap = val; - if (_useDrumMap) { - int val = ctrlVal(CTRL_PROGRAM).i; - MidiOutPort* op = port(); - MidiInstrument* mi = op->instrument(); - DrumMap* dm = mi->getDrumMap(val); - if (dm == 0) - dm = &gmDrumMap; - _drumMap = dm; - } - else - _drumMap = &noDrumMap; - for (iRoute i = _inRoutes.begin(); i != _inRoutes.end(); ++i) { - MidiTrack* mt = (MidiTrack*)(i->track); - mt->changeDrumMap(); - } - emit useDrumMapChanged(_useDrumMap); - } - } - -//--------------------------------------------------------- -// emitControllerChanged -//--------------------------------------------------------- - -void MidiChannel::emitControllerChanged(int id) - { - if (id == CTRL_PROGRAM && _useDrumMap) { - int val = ctrlVal(id).i; - MidiOutPort* op = port(); - MidiInstrument* mi = op->instrument(); - DrumMap* dm = mi->getDrumMap(val); - if (dm == 0) - dm = &gmDrumMap; - if (dm != _drumMap) { - _drumMap = dm; - for (iRoute i = _inRoutes.begin(); i != _inRoutes.end(); ++i) { - MidiTrack* mt = (MidiTrack*)(i->track); - mt->changeDrumMap(); - } - } - } - emit controllerChanged(id); - } - -//--------------------------------------------------------- -// isMute -//--------------------------------------------------------- - -bool MidiChannel::isMute() const - { - if (_solo) - return false; - if (song->solo()) - return true; - return _mute; - } - diff --git a/muse/muse/midiseq.cpp b/muse/muse/midiseq.cpp index 83391629..892db5c6 100644 --- a/muse/muse/midiseq.cpp +++ b/muse/muse/midiseq.cpp @@ -39,6 +39,9 @@ #include "al/tempo.h" #include "al/al.h" #include "instruments/minstrument.h" +#include "midichannel.h" +#include "midiinport.h" +#include "midioutport.h" MidiSeq* midiSeq; static const unsigned char mmcStopMsg[] = { 0x7f, 0x7f, 0x06, 0x01 }; diff --git a/muse/muse/miditrack.cpp b/muse/muse/miditrack.cpp index fe4a6768..da7b02cd 100644 --- a/muse/muse/miditrack.cpp +++ b/muse/muse/miditrack.cpp @@ -27,6 +27,7 @@ #include "part.h" #include "al/tempo.h" #include "midiedit/drummap.h" +#include "midichannel.h" //--------------------------------------------------------- // MidiTrack @@ -546,7 +547,7 @@ void MidiTrack::getEvents(unsigned from, unsigned to, int, MPEventList* dst) if (velo < 1) // no off event velo = 1; int elen = (ev.lenTick() * len)/100; - if (elen <= 0) // donīt allow zero length + if (elen <= 0) // donī allow zero length elen = 1; int veloOff = ev.veloOff(); diff --git a/muse/muse/mixer/astrip.cpp b/muse/muse/mixer/astrip.cpp index bbaf5189..fa145a31 100644 --- a/muse/muse/mixer/astrip.cpp +++ b/muse/muse/mixer/astrip.cpp @@ -29,6 +29,8 @@ #include "widgets/simplebutton.h" #include "widgets/utils.h" #include "auxplugin.h" +#include "midiinport.h" +#include "midioutport.h" #include "awl/volknob.h" #include "awl/panknob.h" diff --git a/muse/muse/mixer/mixer.cpp b/muse/muse/mixer/mixer.cpp index 8424f817..3a84ca12 100644 --- a/muse/muse/mixer/mixer.cpp +++ b/muse/muse/mixer/mixer.cpp @@ -14,6 +14,9 @@ #include "mstrip.h" #include "routedialog.h" #include "synth.h" +#include "midiinport.h" +#include "midichannel.h" +#include "midioutport.h" extern void populateAddTrack(QMenu* addTrack); diff --git a/muse/muse/mixer/mstrip.cpp b/muse/muse/mixer/mstrip.cpp index d0cd4c85..50b412c0 100644 --- a/muse/muse/mixer/mstrip.cpp +++ b/muse/muse/mixer/mstrip.cpp @@ -18,6 +18,9 @@ #include "synth.h" #include "midirack.h" #include "midiplugin.h" +#include "midiinport.h" +#include "midioutport.h" +#include "midichannel.h" #include "awl/midimslider.h" #include "awl/midimeter.h" diff --git a/muse/muse/muse.cpp b/muse/muse/muse.cpp index 0ac714c9..c6cfd79f 100644 --- a/muse/muse/muse.cpp +++ b/muse/muse/muse.cpp @@ -41,7 +41,6 @@ #include "marker/markerview.h" #include "transpose.h" #include "preferences.h" -// #include "widgets/gatetime.h" #include "audio.h" #include "midiseq.h" #include "audioprefetch.h" @@ -67,6 +66,7 @@ #include "templatedialog.h" #include "midiedit/miditracker.h" #include "projectpropsdialog.h" +#include "midichannel.h" static pthread_t watchdogThread; diff --git a/muse/muse/route.cpp b/muse/muse/route.cpp index f30355f0..2a90db9e 100644 --- a/muse/muse/route.cpp +++ b/muse/muse/route.cpp @@ -27,6 +27,7 @@ #include "driver/mididev.h" #include "al/xml.h" #include "auxplugin.h" +#include "midichannel.h" //--------------------------------------------------------- // Route diff --git a/muse/muse/seqmsg.cpp b/muse/muse/seqmsg.cpp index 4692b488..5a66c5f0 100644 --- a/muse/muse/seqmsg.cpp +++ b/muse/muse/seqmsg.cpp @@ -34,6 +34,9 @@ #include "midictrl.h" #include "midiplugin.h" #include "part.h" +#include "midichannel.h" +#include "midioutport.h" +#include "midiinport.h" //--------------------------------------------------------- // sendMsg diff --git a/muse/muse/song.cpp b/muse/muse/song.cpp index 8b339cfc..44c58bc7 100644 --- a/muse/muse/song.cpp +++ b/muse/muse/song.cpp @@ -41,6 +41,9 @@ #include "midirc.h" #include "part.h" #include "conf.h" +#include "midichannel.h" +#include "midioutport.h" +#include "midiinport.h" Song* song; diff --git a/muse/muse/songfile.cpp b/muse/muse/songfile.cpp index e7b96182..00977794 100644 --- a/muse/muse/songfile.cpp +++ b/muse/muse/songfile.cpp @@ -38,6 +38,9 @@ #include "midiedit/pianoroll.h" #include "part.h" #include "marker/markerview.h" +#include "midioutport.h" +#include "midiinport.h" +// #include "midichannel.h" //--------------------------------------------------------- // readPart diff --git a/muse/muse/track.cpp b/muse/muse/track.cpp index 938a202c..bead0655 100644 --- a/muse/muse/track.cpp +++ b/muse/muse/track.cpp @@ -31,6 +31,8 @@ #include "instruments/minstrument.h" #include "part.h" #include "gui.h" +#include "midioutport.h" +#include "midichannel.h" // synchronize with TrackType!: diff --git a/muse/muse/track.h b/muse/muse/track.h index 6de6a19b..6d2bff17 100644 --- a/muse/muse/track.h +++ b/muse/muse/track.h @@ -45,9 +45,11 @@ class SynthI; class MidiPlugin; class MidiPluginI; class MidiInstrument; -class MidiChannel; class PartList; class Part; +class MidiOutPort; +class MidiInPort; +class MidiChannel; #ifndef __APPLE__ // actually it should check for ALSA but I don't know how to do that @@ -338,168 +340,6 @@ class MidiTrackBase : public Track { virtual void getEvents(unsigned /*from*/, unsigned /*to*/, int /*channel*/, MPEventList* /*dst*/) {} }; -//--------------------------------------------------------- -// MidiInPort -//--------------------------------------------------------- - -class MidiInPort : public MidiTrackBase { - Q_OBJECT - - Port _alsaPort; - Port _jackPort; - - MPEventList _recordEvents; - - public: - MidiInPort(); - ~MidiInPort(); - - virtual void activate1(); - virtual void activate2(); - virtual void deactivate(); - virtual void setName(const QString& s); - virtual void write(Xml&) const; - virtual void read(QDomNode); - virtual Track* newTrack() const { return new MidiInPort(); } - virtual bool isMute() const { return _mute; } - virtual Part* newPart(Part*, bool) { return 0; } - Port alsaPort() const { return _alsaPort; } - Port jackPort() const { return _jackPort; } - -#ifndef __APPLE__ - void eventReceived(snd_seq_event_t*); -#endif - virtual void getEvents(unsigned from, unsigned to, int channel, MPEventList* dst); - void afterProcess(); - }; - -//--------------------------------------------------------- -// MidiChannel -//--------------------------------------------------------- - -class MidiOutPort; - -class MidiChannel : public MidiTrackBase { - Q_OBJECT - - DrumMap* _drumMap; - bool _useDrumMap; - MidiOutPort* _port; - int _channelNo; - - void clearDevice(); - - signals: - void useDrumMapChanged(bool); - - public: - MidiChannel(MidiOutPort*, int); - ~MidiChannel(); - - MidiOutPort* port() const { return _port; } - int channelNo() const { return _channelNo; } - - virtual void write(Xml&) const; - virtual void read(QDomNode); - virtual Track* newTrack() const { return 0; } - virtual bool isMute() const; - virtual Part* newPart(Part*, bool) { return 0; } - - bool guiVisible() const; - bool hasGui() const; - - // void putEvent(const MidiEvent&); - void playMidiEvent(MidiEvent* ev); - - bool useDrumMap() const { return _useDrumMap; } - void setUseDrumMap(bool val); - DrumMap* drumMap() const { return _drumMap; } - - virtual void emitControllerChanged(int id); - }; - -//--------------------------------------------------------- -// MidiOutPort -//--------------------------------------------------------- - -class MidiOutPort : public MidiTrackBase { - Q_OBJECT - - MidiInstrument* _instrument; - MidiChannel* _channel[MIDI_CHANNELS]; - Port _alsaPort; - Port _jackPort; - - bool _sendSync; // this port sends mtc mmc events - int _deviceId; // 0-126; 127 == all - - MPEventList _playEvents; // scheduled events to play - iMPEvent _nextPlayEvent; - - // fifo for midi events send from gui - // direct to midi port: - - MidiFifo eventFifo; - - signals: - void instrumentChanged(); - void sendSyncChanged(bool); - - public: - MidiOutPort(); - ~MidiOutPort(); - - virtual void activate1(); - virtual void activate2(); - virtual void deactivate(); - - MidiChannel* channel(int n) { return _channel[n]; } - - virtual void setName(const QString& s); - virtual void write(Xml&) const; - virtual void read(QDomNode); - virtual Track* newTrack() const { return new MidiOutPort(); } - virtual bool isMute() const { return _mute; } - virtual Part* newPart(Part*, bool) { return 0; } - - MidiInstrument* instrument() const { return _instrument; } - void setInstrument(MidiInstrument* i); - - bool guiVisible() const; - bool hasGui() const; - - Port alsaPort() const { return _alsaPort; } - Port jackPort() const { return _jackPort; } - void putEvent(const MidiEvent&); - - MPEventList* playEvents() { return &_playEvents; } - iMPEvent nextPlayEvent() { return _nextPlayEvent; } - - void process(unsigned from, unsigned to, const AL::Pos&, unsigned frames); - - void setNextPlayEvent(iMPEvent i) { _nextPlayEvent = i; } - void playFifo(); - 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(); - - void playEventList(); - - bool sendSync() const { return _sendSync; } - void setSendSync(bool val); - - int deviceId() const { return _deviceId; } - void setDeviceId(int val) { _deviceId = val; } - }; - //--------------------------------------------------------- // TrackList //--------------------------------------------------------- @@ -613,7 +453,5 @@ typedef tracklist::iterator iMidiChannel; typedef tracklist::const_iterator ciMidiChannel; typedef tracklist MidiChannelList; -extern QMenu* midiPortsPopup(QWidget*); - #endif diff --git a/muse/muse/widgets/outportcombo.cpp b/muse/muse/widgets/outportcombo.cpp index 0145ec66..a3e55adc 100644 --- a/muse/muse/widgets/outportcombo.cpp +++ b/muse/muse/widgets/outportcombo.cpp @@ -20,6 +20,7 @@ #include "outportcombo.h" #include "song.h" +#include "midioutport.h" //--------------------------------------------------------- // OutportCombo -- cgit v1.2.3