diff options
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); | 
