diff options
| -rw-r--r-- | muse/TODO | 22 | ||||
| -rw-r--r-- | muse/doc/man/de/man-de.tex | 3 | ||||
| -rw-r--r-- | muse/doc/man/de/midirecording.tex | 1 | ||||
| -rw-r--r-- | muse/muse/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | muse/muse/arranger/arranger.cpp | 4 | ||||
| -rw-r--r-- | muse/muse/audio.cpp | 2 | ||||
| -rw-r--r-- | muse/muse/ctrl.h | 6 | ||||
| -rw-r--r-- | muse/muse/ctrl/ctrleditor.cpp | 27 | ||||
| -rw-r--r-- | muse/muse/liste/ctrllistedit.cpp | 129 | ||||
| -rw-r--r-- | muse/muse/liste/ctrllistedit.h | 2 | ||||
| -rw-r--r-- | muse/muse/midiout.cpp | 71 | ||||
| -rw-r--r-- | muse/muse/midioutport.cpp | 27 | ||||
| -rw-r--r-- | muse/muse/miditrack.cpp | 33 | ||||
| -rw-r--r-- | muse/muse/mixer/mstrip.cpp | 3 | ||||
| -rw-r--r-- | muse/muse/song.cpp | 654 | ||||
| -rw-r--r-- | muse/muse/song.h | 6 | ||||
| -rw-r--r-- | muse/muse/songtrack.cpp | 662 | ||||
| -rw-r--r-- | muse/muse/track.cpp | 8 | ||||
| -rw-r--r-- | muse/muse/track.h | 3 | 
19 files changed, 873 insertions, 791 deletions
| @@ -3,6 +3,11 @@  ----------------------------------------------------------------------------        - dont allow for overlapping parts +      - move shortcuts to Muse() class +      - add shortcuts as QAction +      - extend Shortcut with ShortcutContext +      - extend shortcuts with Help Text, Icons etc. +  BUGS        - make sure all track names are unique @@ -14,17 +19,15 @@ BUGS        - Do not allow switch track recording on/off during recording -      ? audio prefetching is not stable -        - looping does not work sample accurate due to jack transport          limitations; looping should be implemented internally to work          around this +	- make export midi work +  FEATURES  	- wave editor is completely broken -	- list editor is missing -  	- missing time signature ruler in master editor        - If events recorded outside part ask after recording what to do: @@ -43,22 +46,15 @@ FEATURES          - actual thread state and priorities          - actual used timer resource -	- export midi -  	- Import MusE 0.7 song files +      - use *.svg icons +      - click free mute function  CLEANUPS  	- Cleanup the icon/pixmap handling using Qt resource file: -      	- rename xpm directory to resources/images              - remove all unreferenced files              - transform *.xpm into *.pnm or *.jpg files and move into                resource file              - redirect all *xpm program references to resource file              - remove icon.cpp icon.h - -Wishlist -	- it should be possible to show controller events in the -        tracklist for tracktypes which cannot contain -        Parts to make better use of screen real estate. -        GUI-wise a "Add Controller" button is needed. diff --git a/muse/doc/man/de/man-de.tex b/muse/doc/man/de/man-de.tex index a1dc0eae..2970276a 100644 --- a/muse/doc/man/de/man-de.tex +++ b/muse/doc/man/de/man-de.tex @@ -168,6 +168,9 @@  \chapter{\M\ Quickstart}  \component midirecording.tex +\section{Audio Playback} +\section{Audio Recording} +  \component projekte.tex  \component struktur.tex  \component miditracks.tex diff --git a/muse/doc/man/de/midirecording.tex b/muse/doc/man/de/midirecording.tex index 8036ba66..45490a44 100644 --- a/muse/doc/man/de/midirecording.tex +++ b/muse/doc/man/de/midirecording.tex @@ -34,5 +34,4 @@        Zunächst erzeugen wir einen ''MidiInput'' Track und checken,        ob das Keyboard richtig angeschlossen ist: - diff --git a/muse/muse/CMakeLists.txt b/muse/muse/CMakeLists.txt index e61c4a8f..eabd5590 100644 --- a/muse/muse/CMakeLists.txt +++ b/muse/muse/CMakeLists.txt @@ -140,6 +140,7 @@ add_executable ( muse        muse.cpp        song.cpp        songpart.cpp +      songtrack.cpp        transport.cpp        conf.cpp        editor.cpp diff --git a/muse/muse/arranger/arranger.cpp b/muse/muse/arranger/arranger.cpp index d3d2b560..6dedc0bb 100644 --- a/muse/muse/arranger/arranger.cpp +++ b/muse/muse/arranger/arranger.cpp @@ -455,11 +455,11 @@ Arranger::Arranger(QMainWindow* parent)        connect(canvas, SIGNAL(contentsMoving(int,int)),  SLOT(setTLViewPos(int,int)));        connect(canvas, SIGNAL(posChanged(int,const AL::Pos&)), SLOT(setPos(int,const AL::Pos&))); -      connect(canvas, SIGNAL(createLRPart(Track*)),   song, SLOT(createLRPart(Track*))); +      connect(canvas, SIGNAL(createLRPart(Track*)),   song, SLOT(cmdCreateLRPart(Track*)));        connect(canvas, SIGNAL(doubleClickPart(Part*)), SIGNAL(editPart(Part*)));        connect(canvas, SIGNAL(startEditor(Part*,int)), muse, SLOT(startEditor(Part*,int)));        connect(canvas, SIGNAL(partChanged(Part*,unsigned,unsigned)), -         song, SLOT(changePart(Part*,unsigned,unsigned))); +         song, SLOT(cmdChangePart(Part*,unsigned,unsigned)));        connect(canvas, SIGNAL(addMarker(const AL::Pos&)), SLOT(addMarker(const AL::Pos&)));        connect(canvas, SIGNAL(removeMarker(const AL::Pos&)), SLOT(removeMarker(const AL::Pos&))); diff --git a/muse/muse/audio.cpp b/muse/muse/audio.cpp index 543dcdf4..a6d34cd2 100644 --- a/muse/muse/audio.cpp +++ b/muse/muse/audio.cpp @@ -637,8 +637,6 @@ void Audio::startRolling()              for (iTrack i = tracks->begin(); i != tracks->end(); ++i) {                    if ((*i)->isMidiTrack())                          continue; -                  if ((*i)->type() == Track::WAVE) -                        ((WaveTrack*)(*i))->resetMeter();                    ((AudioTrack*)(*i))->recEvents()->clear();                    }              } diff --git a/muse/muse/ctrl.h b/muse/muse/ctrl.h index 6426f5e8..f4f0922a 100644 --- a/muse/muse/ctrl.h +++ b/muse/muse/ctrl.h @@ -180,9 +180,9 @@ class Ctrl : public CTRL {        void setDefault(int val)       { _default.i = val;  }        const CVal& curVal() const     { return _curVal;  } -      void setCurVal(CVal v)         { _curVal   = v; } -      void setCurVal(float v)        { _curVal.f = v; } -      void setCurVal(int v)          { _curVal.i = v; } +      void setCurVal(CVal v)         { _curVal   = v; _changed = true; } +      void setCurVal(float v)        { _curVal.f = v; _changed = true; } +      void setCurVal(int v)          { _curVal.i = v; _changed = true; }        int id() const                 { return _id;      }        void setId(int i)              { _id = i;         } diff --git a/muse/muse/ctrl/ctrleditor.cpp b/muse/muse/ctrl/ctrleditor.cpp index bd6ea03c..4a6f1e81 100644 --- a/muse/muse/ctrl/ctrleditor.cpp +++ b/muse/muse/ctrl/ctrleditor.cpp @@ -92,8 +92,7 @@ void CtrlEditor::paint(QPainter& p, const QRect& r)        TType tt = track()->timeType(); -      MidiController::ControllerType type = midiControllerType(ctrl()->id()); -      if (type == MidiController::Velo) { +      if (ctrl()->id() == CTRL_VELOCITY) {              p.setPen(QPen(Qt::blue, veloWidth));              PartList* pl = track()->parts();              for (iPart ip = pl->begin(); ip != pl->end(); ++ip) { @@ -133,7 +132,8 @@ void CtrlEditor::paint(QPainter& p, const QRect& r)                    }              else {                    int x1, y1, x2, y2; - +                  int hx = -1; +                  int hy;                    Pos pos1 = tc()->pix2pos(from);                    ciCtrlVal i = ctrl()->lowerBound(pos1.time(tt)); @@ -154,7 +154,8 @@ void CtrlEditor::paint(QPainter& p, const QRect& r)                                --i;                                x1 = tc()->pos2pix(Pos(i.key(), tt));                                y1 = ctrlY(x1, i.value()); -                              drawHandle(p, x1, y1, lselected); +                              hx = x1; +                              hy = y1;                                ++i;                                }                          do { @@ -168,14 +169,18 @@ void CtrlEditor::paint(QPainter& p, const QRect& r)                                      p.drawLine(x1, y1, x2, y2);                                if (x2 >= to)                                      break; -                              drawHandle(p, x2, y2, lselected); +                              if (hx != -1) +                                    drawHandle(p, hx, hy, lselected); +                              hx = x2; +                              hy = y2;                                x1 = x2;                                y1 = y2;                                ++i;                                } while (i != ctrl()->end()); -                        if (x2 < to) { +                        if (x2 < to)                                p.drawLine(x2, y1, to, y1); -                              } +                        if (hx != -1) +                              drawHandle(p, hx, hy, lselected);                          }                    }              if (!aR) { @@ -257,7 +262,7 @@ void CtrlEditor::mousePress(const QPoint& pos, int button, Qt::KeyboardModifiers              else {                    // add controller:                    CVal val = ctrl()->pixel2val(dragy, wh); -                  song->addControllerVal(track(), ctrl(), selected, val); +                  song->cmdAddControllerVal(track(), ctrl(), selected, val);                    tc()->widget()->update();                    }              } @@ -285,7 +290,7 @@ void CtrlEditor::mousePress(const QPoint& pos, int button, Qt::KeyboardModifiers                          lselected = tc()->pos2pix(selected);                          if (tool == RubberTool || button == Qt::RightButton                            || modifiers & Qt::ControlModifier) { -                              song->removeControllerVal(track(), ctrl()->id(), i.key()); +                              song->cmdRemoveControllerVal(track(), ctrl()->id(), i.key());                                dragy = -1;                                }                          else { @@ -374,7 +379,7 @@ void CtrlEditor::mouseRelease()                    int wh   = cheight();                    CVal val = ctrl()->pixel2val(dragy, wh);                    // modify controller: -                  song->addControllerVal(track(), ctrl(), selected, val); +                  song->cmdAddControllerVal(track(), ctrl(), selected, val);                    }              dragy = -1;              } @@ -461,7 +466,7 @@ void CtrlEditor::mouseMove(const QPoint& pos)                                else                                      selected.setFrame(i.key());                                lselected = tc()->pos2pix(selected); -                              song->removeControllerVal(track(), ctrl()->id(), i.key()); +                              song->cmdRemoveControllerVal(track(), ctrl()->id(), i.key());                                dragy = -1;                                break;                                } diff --git a/muse/muse/liste/ctrllistedit.cpp b/muse/muse/liste/ctrllistedit.cpp index 9c4a05eb..695fe9a1 100644 --- a/muse/muse/liste/ctrllistedit.cpp +++ b/muse/muse/liste/ctrllistedit.cpp @@ -56,8 +56,6 @@ CtrlListEditor::CtrlListEditor(ListEdit* e, QWidget* parent)        track = 0;        connect(le.ctrlList, SIGNAL(itemActivated(QTreeWidgetItem*, int)),           SLOT(itemActivated(QTreeWidgetItem*,int))); -      connect(le.ctrlList, SIGNAL(itemDoubleClicked(QTreeWidgetItem*, int)), -         SLOT(itemDoubleClicked(QTreeWidgetItem*,int)));        connect(le.ctrlList, SIGNAL(itemChanged(QTreeWidgetItem*, int)),           SLOT(itemChanged(QTreeWidgetItem*, int)));        connect(le.ctrlList, SIGNAL(currentItemChanged(QTreeWidgetItem*, QTreeWidgetItem*)), @@ -114,12 +112,25 @@ void CtrlListEditor::setup(const ListType& lt)              le.defaultValue->setValue(c->getDefault().i);              }        else { -            le.minValue->setDecimals(1); -            le.minValue->setValue(c->minVal().f); -            le.maxValue->setDecimals(1); -            le.maxValue->setValue(c->maxVal().f); -            le.defaultValue->setDecimals(1); -            le.defaultValue->setValue(c->getDefault().f); +            if (c->type() & Ctrl::LOG) { +                  le.minValue->setDecimals(0); +                  le.minValue->setValue(c->minVal().f * 20.0); +                  le.minValue->setSuffix(tr("dB")); +                  le.maxValue->setDecimals(0); +                  le.maxValue->setValue(c->maxVal().f * 20.0); +                  le.maxValue->setSuffix(tr("dB")); +                  le.defaultValue->setDecimals(0); +                  le.defaultValue->setValue(c->getDefault().f * 20.0); +                  le.defaultValue->setSuffix(tr("dB")); +                  } +            else { +                  le.minValue->setDecimals(1); +                  le.minValue->setValue(c->minVal().f); +                  le.maxValue->setDecimals(1); +                  le.maxValue->setValue(c->maxVal().f); +                  le.defaultValue->setDecimals(1); +                  le.defaultValue->setValue(c->getDefault().f); +                  }              }        updateList();        } @@ -221,8 +232,8 @@ void CtrlListEditor::itemChanged(QTreeWidgetItem* item, int column)                    int otick = item->data(TIME_COL, Qt::DisplayRole).toInt();                    int tick = item->data(TICK_COL, Qt::DisplayRole).toInt();                    item->setData(TIME_COL, Qt::DisplayRole, tick); -                  song->removeControllerVal(track, c->id(), otick); -                  song->addControllerVal(track, c, tick, val); +                  song->cmdRemoveControllerVal(track, c->id(), otick); +                  song->cmdAddControllerVal(track, c, tick, val);                    }                    break;              case TIME_COL: @@ -230,12 +241,12 @@ void CtrlListEditor::itemChanged(QTreeWidgetItem* item, int column)                    int otick = item->data(TICK_COL, Qt::DisplayRole).toInt();                    int tick = item->data(TIME_COL, Qt::DisplayRole).toInt();                    item->setData(TICK_COL, Qt::DisplayRole, tick); -                  song->removeControllerVal(track, c->id(), otick); -                  song->addControllerVal(track, c, tick, val); +                  song->cmdRemoveControllerVal(track, c->id(), otick); +                  song->cmdAddControllerVal(track, c, tick, val);                    }                    break;              case VAL_COL: -                  song->addControllerVal(track, c, listEdit->pos(), val); +                  song->cmdAddControllerVal(track, c, listEdit->pos(), val);                    break;              }        updateListDisabled = false; @@ -266,8 +277,10 @@ void CtrlListEditor::currentItemChanged(QTreeWidgetItem* cur, QTreeWidgetItem* p              le.ctrlList->closePersistentEditor(prev, TIME_COL);              le.ctrlList->closePersistentEditor(prev, VAL_COL);              } -      if (cur) -            listEdit->pos().setTick(cur->data(TICK_COL, Qt::DisplayRole).toInt()); +      if (cur) { +            Pos pos(cur->data(TICK_COL, Qt::DisplayRole).toInt(), track->timeType()); +            listEdit->pos() = pos; +            }        le.deleteButton->setEnabled(cur);        } @@ -290,7 +303,7 @@ void CtrlListEditor::insertClicked()              else                    val.f = cur->data(VAL_COL, Qt::DisplayRole).toDouble();              }             -      song->addControllerVal(track, c, listEdit->pos(), val); +      song->cmdAddControllerVal(track, c, listEdit->pos(), val);        }  //--------------------------------------------------------- @@ -303,7 +316,7 @@ void CtrlListEditor::deleteClicked()        if (cur == 0)              return;        int tick = cur->data(TICK_COL, Qt::DisplayRole).toInt(); -      song->removeControllerVal(track, c->id(), tick); +      song->cmdRemoveControllerVal(track, c->id(), tick);        }  //--------------------------------------------------------- @@ -324,8 +337,11 @@ void CtrlListEditor::minValChanged(double v)        CVal val;        if (c->type() & Ctrl::INT)              val.i = int(v); -      else +      else { +            if (c->type() & Ctrl::LOG) +                  v /= 20.0;              val.f = v; +            }        c->setRange(val, c->maxVal());        } @@ -338,8 +354,11 @@ void CtrlListEditor::maxValChanged(double v)        CVal val;        if (c->type() & Ctrl::INT)              val.i = int(v); -      else +      else { +            if (c->type() & Ctrl::LOG) +                  v /= 20.0;              val.f = v; +            }        c->setRange(c->minVal(), val);        } @@ -389,7 +408,9 @@ QWidget* MidiTimeDelegate::createEditor(QWidget* pw,                          return w;                          }                    QDoubleSpinBox* w = new QDoubleSpinBox(pw); -                  w->setRange(c->minVal().f, c->maxVal().f); +                  if (c->type() & Ctrl::LOG) +                        w->setSuffix(tr("dB")); +//                  w->setRange(c->minVal().f, c->maxVal().f);                    w->installEventFilter(const_cast<MidiTimeDelegate*>(this));                    return w;                    } @@ -423,7 +444,11 @@ void MidiTimeDelegate::setEditorData(QWidget* editor,                          }                    else {                          QDoubleSpinBox* w = static_cast<QDoubleSpinBox*>(editor); -                        w->setValue(index.data().toDouble()); +                        double v = index.data().toDouble(); +printf("type %x\n", c->type()); +                        if (c->type() & Ctrl::LOG) +                              v *= 20.0; +                        w->setValue(v);                          }                    }                    return; @@ -457,7 +482,10 @@ void MidiTimeDelegate::setModelData(QWidget* editor, QAbstractItemModel* model,                          }                    else {                          QDoubleSpinBox* w = static_cast<QDoubleSpinBox*>(editor); -                        model->setData(index, w->value(), Qt::DisplayRole); +                        double v = w->value(); +                        if (c->type() & Ctrl::LOG) +                              v /= 20.0; +                        model->setData(index, v, Qt::DisplayRole);                          }                    }                    break; @@ -472,15 +500,47 @@ void MidiTimeDelegate::setModelData(QWidget* editor, QAbstractItemModel* model,  void MidiTimeDelegate::paint(QPainter* painter,      const QStyleOptionViewItem& option, const QModelIndex& index) const        { -      if (index.column() != CtrlListEditor::TIME_COL) { -            QItemDelegate::paint(painter, option, index); -            return; -            } -      AL::Pos pos(index.data().toInt()); -      int measure, beat, tick; -      pos.mbt(&measure, &beat, &tick);        QString text; -      text.sprintf("%04d.%02d.%03u", measure+1, beat+1, tick); +      CtrlListEditor* ce = static_cast<CtrlListEditor*>(parent()); + +      switch(index.column()) { +            case CtrlListEditor::TICK_COL: +                  { +                  Track* track = ce->getTrack(); +                  AL::Pos pos(index.data().toInt(), track->timeType()); +                  text = QString("%1").arg(pos.tick()); +                  } +                  break; +            case CtrlListEditor::TIME_COL: +                  { +                  Track* track = ce->getTrack(); +                  AL::Pos pos(index.data().toInt(), track->timeType()); +                  int measure, beat, tick; +                  pos.mbt(&measure, &beat, &tick); +                  text.sprintf("%04d.%02d.%03u", measure+1, beat+1, tick); +                  } +                  break; +            case CtrlListEditor::VAL_COL: +                  { +                  Ctrl* c = ce->ctrl(); +                  if (c->type() & Ctrl::INT) { +                        text = QString("%1").arg(index.data().toInt()); +                        } +                  else { +                        if (c->type() & Ctrl::LOG) { +                              double f = index.data().toDouble(); +                              if (f <= -1000.0f) +                                    text = tr("off"); +                              else +                                    text = QString("%1 dB").arg(f * 20.0); +                              } +                        else { +                              text = QString("%1").arg(index.data().toDouble()); +                              } +                        } +                  } +                  break; +            }        QStyleOptionViewItemV2 opt = setOptions(index, option);        const QStyleOptionViewItemV2 *v2 = qstyleoption_cast<const QStyleOptionViewItemV2 *>(&option); @@ -506,13 +566,4 @@ void MidiTimeDelegate::paint(QPainter* painter,        painter->restore();        } -//--------------------------------------------------------- -//   itemDoubleClicked -//--------------------------------------------------------- - -void CtrlListEditor::itemDoubleClicked(QTreeWidgetItem* item, int column) -      { -      printf("double clicked\n"); -      } - diff --git a/muse/muse/liste/ctrllistedit.h b/muse/muse/liste/ctrllistedit.h index a6384321..74b0749d 100644 --- a/muse/muse/liste/ctrllistedit.h +++ b/muse/muse/liste/ctrllistedit.h @@ -75,7 +75,6 @@ class CtrlListEditor : public ListWidget {     private slots:        void controllerChanged(int id);        void itemActivated(QTreeWidgetItem*,int); -      void itemDoubleClicked(QTreeWidgetItem*,int);        void itemChanged(QTreeWidgetItem*,int);        void currentItemChanged(QTreeWidgetItem*, QTreeWidgetItem*);        void insertClicked(); @@ -90,6 +89,7 @@ class CtrlListEditor : public ListWidget {        virtual void setup(const ListType&);        void sendEscape();        Ctrl* ctrl() const { return c; } +      Track* getTrack() const { return track; }        enum { TICK_COL, TIME_COL, VAL_COL };        }; diff --git a/muse/muse/midiout.cpp b/muse/muse/midiout.cpp index 31ed904d..0f0af9d7 100644 --- a/muse/muse/midiout.cpp +++ b/muse/muse/midiout.cpp @@ -29,6 +29,7 @@  #include "gconfig.h"  static const unsigned char mmcDeferredPlayMsg[] = { 0x7f, 0x7f, 0x06, 0x03 }; +static const unsigned char mmcStopMsg[]         = { 0x7f, 0x7f, 0x06, 0x01 };  //---------------------------------------------------------  //   MidiOut @@ -208,21 +209,34 @@ void MidiOut::seek(unsigned tickPos, unsigned framePos)        //    set all controller        //--------------------------------------------------- -#if 0 -      for (int ch = 0; ch < MIDI_CHANNELS; ++ch) { -            MidiChannel* mc = channel(ch); -            if (mc->mute() || mc->noInRoute() || !mc->autoRead()) +      if (track->autoRead()) { +            CtrlList* cl = track->controller(); +            for (iCtrl ic = cl->begin(); ic != cl->end(); ++ic) { +                  Ctrl* c = ic->second; +                  int val = c->value(tickPos).i; +                  if ((val != CTRL_VAL_UNKNOWN) && (c->curVal().i != val)) { +                        MidiEvent ev(0, -1, ME_CONTROLLER, c->id(), val); +                        track->routeEvent(ev); +                        c->setCurVal(val); +                        } +                  } +            } +      foreach (const Route& r, *track->inRoutes()) { +            MidiTrackBase* t = (MidiTrackBase*)r.src.track; +            int dstChannel = r.dst.channel; +            if (t->isMute() || !t->autoRead())                    continue; -            CtrlList* cll = mc->controller(); -            for (iCtrl ivl = cll->begin(); ivl != cll->end(); ++ivl) { -                  Ctrl* c   = ivl->second; +            CtrlList* cl = t->controller(); +            for (iCtrl ic = cl->begin(); ic != cl->end(); ++ic) { +                  Ctrl* c = ic->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)); +                  if ((val != CTRL_VAL_UNKNOWN) && (c->curVal().i != val)) { +                        MidiEvent ev(0, dstChannel, ME_CONTROLLER, c->id(), val); +                        track->routeEvent(ev); +                        c->setCurVal(val);                          }                    }              } -#endif        }  //--------------------------------------------------------- @@ -250,18 +264,24 @@ void MidiOut::stop()        //    reset sustain        //--------------------------------------------------- -#if 0 -      for (int ch = 0; ch < MIDI_CHANNELS; ++ch) { -            MidiChannel* mc = channel(ch); -            if (mc->noInRoute()) +      foreach (const Route& r, *track->inRoutes()) { +            MidiTrackBase* t = (MidiTrackBase*)r.src.track; +            int dstChannel = r.dst.channel; +            if (t->isMute() || !t->autoRead())                    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); +            CtrlList* cl = t->controller(); +            for (iCtrl ic = cl->begin(); ic != cl->end(); ++ic) { +                  Ctrl* c = ic->second; +                  if (c->id() == CTRL_SUSTAIN) { +                        if (c->curVal().i > 0) { +                              MidiEvent ev(0, dstChannel, ME_CONTROLLER, c->id(), 0); +                              track->routeEvent(ev); +                              c->setCurVal(0); +                              } +                        }                    }              } -#endif +        if (track->sendSync()) {              if (genMMC) {                    unsigned char mmcPos[] = { @@ -274,7 +294,7 @@ void MidiOut::stop()                    mmcPos[8] = mtc.s();                    mmcPos[9] = mtc.f();                    mmcPos[10] = mtc.sf(); -//TODO                  sendSysex(mmcStopMsg, sizeof(mmcStopMsg)); +                  sendSysex(mmcStopMsg, sizeof(mmcStopMsg));                    sendSysex(mmcPos, sizeof(mmcPos));                    }              if (genMCSync) {         // Midi Clock @@ -292,6 +312,8 @@ void MidiOut::stop()  void MidiOut::start()        { +      // TODO: set sustain to old value? +        if (!(genMMC || genMCSync || track->sendSync()))              return;        if (genMMC) @@ -342,7 +364,7 @@ void MidiOut::processMidi(MidiEventList& el, unsigned fromTick, unsigned toTick,              el.insert(eventFifo.get());        // collect port controller -      if (fromTick != toTick) {     // if rolling +      if (track->autoRead() && (fromTick != toTick)) {  // if rolling              CtrlList* cl = track->controller();              for (iCtrl ic = cl->begin(); ic != cl->end(); ++ic) {                    Ctrl* c = ic->second; @@ -350,10 +372,9 @@ void MidiOut::processMidi(MidiEventList& el, unsigned fromTick, unsigned toTick,                    iCtrlVal ie = c->lowerBound(toTick);                    for (iCtrlVal ic = is; ic != ie; ++ic) {                          unsigned frame = AL::tempomap.tick2frame(ic.key()); -                        Event ev(Controller); -                        ev.setA(c->id()); -                        ev.setB(ic.value().i); -                        el.insert(MidiEvent(frame, -1, ev)); +                        MidiEvent ev(frame, -1, ME_CONTROLLER, c->id(), ic.value().i); +                        el.insert(ev); +                        c->setCurVal(ic.value().i);                          }                    }              } diff --git a/muse/muse/midioutport.cpp b/muse/muse/midioutport.cpp index 698970a8..247af147 100644 --- a/muse/muse/midioutport.cpp +++ b/muse/muse/midioutport.cpp @@ -123,33 +123,6 @@ void MidiOutPort::read(QDomNode node)  void MidiOutPort::routeEvent(const MidiEvent& event)        { -      if (event.type() == ME_CONTROLLER) { -            int a   = event.dataA(); -            int b   = event.dataB(); -            int chn = event.channel(); -            if (chn == 255) { -                  // port controller -                  if (hwCtrlState(a) == b) { -// printf(" controller change optimized away 1\n"); -                        return; -                        } -                  setHwCtrlState(a, b); -                  } -#if 0 -            else { -                  MidiChannel* mc = channel(chn); -                  // -                  //  optimize controller settings -                  // -                  if (mc->hwCtrlState(a) == b) { -// printf(" controller %02x change optimized away: value %02x\n", a, b); -                        return; -                        } -                  mc->setHwCtrlState(a, b); -                  } -#endif -            } -        for (iRoute r = _outRoutes.begin(); r != _outRoutes.end(); ++r) {              switch (r->dst.type) {                    case RouteNode::MIDIPORT: diff --git a/muse/muse/miditrack.cpp b/muse/muse/miditrack.cpp index 3f380ba4..57a4830b 100644 --- a/muse/muse/miditrack.cpp +++ b/muse/muse/miditrack.cpp @@ -535,6 +535,24 @@ void MidiTrack::processMidi(unsigned from, unsigned to, unsigned, unsigned)                                }                          }                    } +            // +            // collect controller +            // +            if (autoRead()) { +                  for (iCtrl ic = controller()->begin(); ic != controller()->end(); ++ic) { +                        Ctrl* c = ic->second; +                        iCtrlVal is = c->lowerBound(from); +                        iCtrlVal ie = c->lowerBound(to); +                        for (iCtrlVal ic = is; ic != ie; ++ic) { +                              unsigned frame = AL::tempomap.tick2frame(ic.key()); +                              Event ev(Controller); +                              ev.setA(c->id()); +                              ev.setB(ic.value().i); +                              schedEvents.insert(MidiEvent(frame, -1, ev)); +                              c->setCurVal(ic.value().i); +                              } +                        } +                  }              }        // @@ -582,21 +600,6 @@ void MidiTrack::processMidi(unsigned from, unsigned to, unsigned, unsigned)                          }                    }              } -      // -      // collect controller -      // -      for (iCtrl ic = controller()->begin(); ic != controller()->end(); ++ic) { -            Ctrl* c = ic->second; -            iCtrlVal is = c->lowerBound(from); -            iCtrlVal ie = c->lowerBound(to); -            for (iCtrlVal ic = is; ic != ie; ++ic) { -                  unsigned frame = AL::tempomap.tick2frame(ic.key()); -                  Event ev(Controller); -                  ev.setA(c->id()); -                  ev.setB(ic.value().i); -                  schedEvents.insert(MidiEvent(frame, -1, ev)); -                  } -            }        }  //--------------------------------------------------------- diff --git a/muse/muse/mixer/mstrip.cpp b/muse/muse/mixer/mstrip.cpp index c0ce56d9..2dd68cd9 100644 --- a/muse/muse/mixer/mstrip.cpp +++ b/muse/muse/mixer/mstrip.cpp @@ -346,7 +346,8 @@ void MidiStrip::heartBeat()  void MidiStrip::controllerChanged(int id)        { -      double val = double(track->ctrlVal(id).i); +      CVal cv = track->ctrlVal(id); +      double val = double(cv.i);        switch (id) {              case CTRL_VOLUME: diff --git a/muse/muse/song.cpp b/muse/muse/song.cpp index 70906a54..c907ebe6 100644 --- a/muse/muse/song.cpp +++ b/muse/muse/song.cpp @@ -105,53 +105,6 @@ void Song::setSig(const AL::TimeSignature& sig)        }  //--------------------------------------------------------- -//   deselectTracks -//--------------------------------------------------------- - -void Song::deselectTracks() -      { -      for (iTrack t = _tracks.begin(); t != _tracks.end(); ++t) -            (*t)->setSelected(false); -      } - -//--------------------------------------------------------- -//   selectTrack -//--------------------------------------------------------- - -void Song::selectTrack(Track* track) -      { -      bool changed = false; -      for (iTrack t = _tracks.begin(); t != _tracks.end(); ++t) { -            bool select = *t == track; -            if ((*t)->selected() != select) { -                  (*t)->setSelected(select); -                  changed = true; -                  } -            } -      if (changed) { -            updateSelectedTrack(); -            trackSelectionChanged(_selectedTrack); -            } -      } - -//--------------------------------------------------------- -//   updateSelectedTrack -//    set _selectedTrack to first selected track -//--------------------------------------------------------- - -void Song::updateSelectedTrack() -      { -      _selectedTrack = 0; -      for (iTrack t = _tracks.begin(); t != _tracks.end(); ++t) { -            bool select = (*t)->selected(); -            if (select) { -                  _selectedTrack = *t; -                  break; -                  } -            } -      } - -//---------------------------------------------------------  //  addEvent  //    return true if event was added  //--------------------------------------------------------- @@ -1295,570 +1248,33 @@ void Song::stopRolling()        }  //--------------------------------------------------------- -//    addTrack -//    called from GUI context -//--------------------------------------------------------- - -Track* Song::addTrack(QAction* action) -      { -      int t = action->data().toInt(); - -      deselectTracks(); -      Track* track = 0; - -      Track::TrackType type = (Track::TrackType) t; -      if (t >= 5000) { -            int idx = t - 5000; -            type = Track::MIDI_SYNTI; -            int k = 0; -            iMidiPlugin i; -            for (i = midiPlugins.begin(); i != midiPlugins.end(); ++i) { -                  if ((*i)->type() != MEMPI_GENERATOR) -                        continue; -                  if (k == idx) -                        break; -                  ++k; -                  } -            if (i == midiPlugins.end()) { -                  fprintf(stderr, "Song::addTrack: midi synti not found\n"); -                  return 0; -                  } -            MidiPlugin* s = *i; -            MidiSynti* si = new MidiSynti(); -            QString sName(s->name()); -            for (k = s->instances(); k < 1000; ++k) { -                  QString instanceName = (k == 0) ?  -                     sName : instanceName.arg(sName).arg(k); - -                  MidiSyntiList* sl = midiSyntis(); -                  iMidiSynti sii; -                  for (sii = sl->begin(); sii != sl->end(); ++sii) { -                        if ((*sii)->name() == instanceName) -                              break; -                        } -                  if (sii == sl->end()) { -                        si->setName(instanceName); -                        break; -                        } -                  } -            if (si->initInstance(s)) { -                  delete si; -                  return 0; -                  } -            track = si; -            } -      else if (t >= 1000) { -            type = Track::AUDIO_SOFTSYNTH; -            QString sclass = synthis[t-1000]->name(); - -            Synth* s = findSynth(sclass); -            if (s == 0) { -                  fprintf(stderr, "synthi class <%s> not found\n", sclass.toLatin1().data()); -                  return 0; -                  } - -            SynthI* si = new SynthI(); -            int i; -            for (i = s->instances(); i < 1000; ++i) { -                  QString instanceName = (i == 0) ?  -                     s->name() : QString("%1-%2").arg(s->name()).arg(i); - -                  SynthIList* sl = syntis(); -                  iSynthI sii; -                  for (sii = sl->begin(); sii != sl->end(); ++sii) { -                        if ((*sii)->name() == instanceName) -                              break; -                        } -                  if (sii == sl->end()) { -                        si->setName(instanceName); -                        break; -                        } -                  } -            if (si->initInstance(s)) { -                  delete si; -                  return 0; -                  } -            track = si; -            } -      else { -            switch (type) { -                  case Track::MIDI: -                        track = new MidiTrack(); -                        break; -                  case Track::MIDI_OUT: -                        track = new MidiOutPort(); -                        break; -                  case Track::MIDI_IN: -                        track = new MidiInPort(); -                        break; -                  case Track::WAVE: -                        track = new WaveTrack(); -                        break; -                  case Track::AUDIO_OUTPUT: -                        track = new AudioOutput(); -                        break; -                  case Track::AUDIO_GROUP: -                        track = new AudioGroup(); -                        break; -                  case Track::AUDIO_INPUT: -                        track = new AudioInput(); -                        break; -                  case Track::AUDIO_SOFTSYNTH: -                  case Track::TRACK_TYPES: -                  default: -                        printf("Song::addTrack() illegal type %d\n", type); -                        abort(); -                  } -            if (track == 0) -                  return 0; -            } -      track->setDefaultName(); -      insertTrack(track, -1); -      return track; -      } - -//--------------------------------------------------------- -//   insertTrack -//--------------------------------------------------------- - -void Song::insertTrack(Track* track, int idx) -      { -      // -      //  add default routes -      // -      OutputList* ol = outputs(); -      AudioOutput* ao = 0; -      if (!ol->empty()) -            ao = ol->front(); -      MidiOutPortList* mol = midiOutPorts(); -      MidiOutPort* mo = 0; -      if (!mol->empty()) -            mo = mol->front(); - -      switch (track->type()) { -            case Track::TRACK_TYPES: -            case Track::MIDI_OUT: -            case Track::MIDI_IN: -            case Track::MIDI_SYNTI: -                  break; -            case Track::MIDI: -                  // -                  // connect to all midi inputs, if there is not already -                  // a route -                  // -                  if (!track->noInRoute()) { -                        MidiInPortList* mi = midiInPorts(); -                        for (iMidiInPort i = mi->begin(); i != mi->end(); ++i) { -                              for (int ch = 0; ch < MIDI_CHANNELS; ++ch) { -                                    RouteNode src(*i, ch, RouteNode::TRACK); -                                    RouteNode dst(track, -1, RouteNode::TRACK); -                                    Route r = Route(src, dst); -                                    track->inRoutes()->push_back(r); -                                    } -                              } -                        } -                  break; -            case Track::AUDIO_SOFTSYNTH: -            case Track::WAVE: -            case Track::AUDIO_GROUP: -                  if (ao) -                        track->outRoutes()->push_back(Route(RouteNode(track), RouteNode(ao))); -                  break; - -            case Track::AUDIO_INPUT: -                  { -                  // connect first input channel to first available jack output -                  // etc. -                  QList<PortName> op = audioDriver->outputPorts(false); -                  QList<PortName>::iterator is = op.begin(); -                  for (int ch = 0; ch < track->channels(); ++ch) { -                        if (is != op.end()) { -                              RouteNode src(is->port, -1, RouteNode::AUDIOPORT); -                              RouteNode dst(track, ch, RouteNode::TRACK); -                              Route r = Route(src, dst); -                              track->inRoutes()->push_back(r); -                              ++is; -                              } -                        } -//                  if (ao) -//                        track->outRoutes()->push_back(Route(ao)); -                  } -                  break; -            case Track::AUDIO_OUTPUT: -                  { -                  QList<PortName> op = audioDriver->inputPorts(false); -                  QList<PortName>::iterator is = op.begin(); -                  for (int ch = 0; ch < track->channels(); ++ch) { -                        if (is != op.end()) { -                              RouteNode src(track, ch, RouteNode::TRACK); -                              RouteNode dst(is->port, -1, RouteNode::AUDIOPORT); -                              Route r = Route(src, dst); -                              track->outRoutes()->push_back(r); -                              ++is; -                              } -                        } -                  } -                  break; -            } -      insertTrack1(track, idx); - -      startUndo(); -      undoOp(UndoOp::AddTrack, idx, track); -      AudioMsg msg; -      msg.id    = SEQM_ADD_TRACK; -      msg.track = track; -      msg.ival  = idx; -      audio->sendMsg(&msg); -      endUndo(SC_TRACK_INSERTED | SC_ROUTE); - -      emit trackAdded(track, idx); -      selectTrack(track); -      } - -//--------------------------------------------------------- -//   insertTrack0 -//    can only be called if sequencer is idle -//    (during song load) -//--------------------------------------------------------- - -void Song::insertTrack0(Track* track, int idx) -      { -      insertTrack1(track, idx); -      insertTrack2(track); -      } - -//--------------------------------------------------------- -//   insertTrack1 -//    non realtime part of insertTrack -//--------------------------------------------------------- - -void Song::insertTrack1(Track* track, int idx) -      { -      if (idx == -1) -            idx = _tracks.size(); -      _tracks.insert(idx, track); -      if (track->type() == Track::AUDIO_SOFTSYNTH) { -            SynthI* s = (SynthI*)track; -            Synth* sy = s->synth(); -            if (!s->isActivated()) -                  s->initInstance(sy); -            } -      if (audioState == AUDIO_RUNNING) { -            track->activate1(); -            track->activate2(); -            } -      } - -//--------------------------------------------------------- -//   insertTrack2 -//    realtime part -//--------------------------------------------------------- - -void Song::insertTrack2(Track* track) -      { -      switch(track->type()) { -            case Track::MIDI_SYNTI: -                  _midiSyntis.push_back((MidiSynti*)track); -                  break; -            case Track::MIDI: -                  _midis.push_back((MidiTrack*)track); -                  break; -            case Track::MIDI_OUT: -                  _midiOutPorts.push_back((MidiOutPort*)track); -                  break; -            case Track::MIDI_IN: -                  _midiInPorts.push_back((MidiInPort*)track); -                  break; -            case Track::WAVE: -                  _waves.push_back((WaveTrack*)track); -                  break; -            case Track::AUDIO_OUTPUT: -                  _outputs.push_back((AudioOutput*)track); -                  break; -            case Track::AUDIO_GROUP: -                  _groups.push_back((AudioGroup*)track); -                  break; -            case Track::AUDIO_INPUT: -                  _inputs.push_back((AudioInput*)track); -                  break; -            case Track::AUDIO_SOFTSYNTH: -                  { -                  SynthI* s = (SynthI*)track; -                  midiInstruments.push_back(s->instrument()); -                  _synthIs.push_back(s); -                  } -                  break; -            default: -                  fprintf(stderr, "insertTrack2: unknown track type %d\n", track->type()); -                  // abort(); -                  return; -            } - -      // -      //  connect routes -      // -      if (track->type() == Track::AUDIO_OUTPUT || track->type() == Track::MIDI_OUT) { -            foreach(Route r, *(track->inRoutes())) { -                  if (r.src.type != RouteNode::AUXPLUGIN) { -                        r.src.track->outRoutes()->push_back(r); -                        } -                  } -            } -      else if (track->type() == Track::AUDIO_INPUT || track->type() == Track::MIDI_IN) { -            foreach(Route r, *(track->outRoutes())) { -                  if (r.dst.type != RouteNode::AUXPLUGIN) { -                        r.dst.track->inRoutes()->push_back(r); -                        } -                  } -            } -      else { -            foreach(Route r, *(track->inRoutes())) { -                  if (r.src.type != RouteNode::AUXPLUGIN) { -                        r.src.track->outRoutes()->push_back(r); -                        } -                  } -            foreach(Route r, *(track->outRoutes())) { -                  if (r.dst.type != RouteNode::AUXPLUGIN) { -                        r.dst.track->inRoutes()->push_back(r); -                        } -                  } -            } -      } - -//--------------------------------------------------------- -//   removeTrack -//    called from gui context -//--------------------------------------------------------- - -void Song::removeTrack(Track* track) -      { -      startUndo(); -      int idx = _tracks.indexOf(track); -      undoOp(UndoOp::DeleteTrack, idx, track); -      removeTrack1(track); -      audio->msgRemoveTrack(track); -      removeTrack3(track); - -      endUndo(SC_TRACK_REMOVED | SC_ROUTE); -      } - -//--------------------------------------------------------- -//   removeTrack1 -//    non realtime part of removeTrack -//--------------------------------------------------------- - -void Song::removeTrack1(Track* track) -      { -      track->deactivate(); -      _tracks.removeAt(_tracks.indexOf(track)); -      } - -//--------------------------------------------------------- -//   removeTrack2 -//    called from RT context -//--------------------------------------------------------- - -void Song::removeTrack2(Track* track) -      { -      switch (track->type()) { -            case Track::MIDI_SYNTI: -                  _midiSyntis.removeAt(_midiSyntis.indexOf((MidiSynti*)track)); -                  break; -            case Track::MIDI: -                  _midis.removeAt(_midis.indexOf((MidiTrack*)track)); -                  break; -            case Track::MIDI_OUT: -                  _midiOutPorts.removeAt(_midiOutPorts.indexOf((MidiOutPort*)track)); -                  break; -            case Track::MIDI_IN: -                  _midiInPorts.removeAt(_midiInPorts.indexOf((MidiInPort*)track)); -                  break; -            case Track::WAVE: -                  _waves.removeAt(_waves.indexOf((WaveTrack*)track)); -                  break; -            case Track::AUDIO_OUTPUT: -                  _outputs.removeAt(_outputs.indexOf((AudioOutput*)track)); -                  break; -            case Track::AUDIO_INPUT: -                  _inputs.removeAt(_inputs.indexOf((AudioInput*)track)); -                  break; -            case Track::AUDIO_GROUP: -                  _groups.removeAt(_groups.indexOf((AudioGroup*)track)); -                  break; -            case Track::AUDIO_SOFTSYNTH: -                  { -                  SynthI* s = (SynthI*) track; -                  s->deactivate2(); -                  _synthIs.removeAt(_synthIs.indexOf(s)); -                  } -                  break; -            case Track::TRACK_TYPES: -                  return; -            } -      // -      //  remove routes -      // -      foreach (const Route r, *(track->inRoutes())) { -            if (r.src.type != RouteNode::TRACK) -                  continue; -            int idx = r.src.track->outRoutes()->indexOf(r); -            if (idx != -1) -                  r.src.track->outRoutes()->removeAt(idx); -            else -                  printf("Song::removeTrack2(): input route not found\n"); -            } -      foreach (const Route r, *(track->outRoutes())) { -            if (r.dst.type != RouteNode::TRACK) -                  continue; -            int idx = r.dst.track->inRoutes()->indexOf(r); -            if (idx != -1) -                  r.dst.track->inRoutes()->removeAt(idx); -            else { -                  printf("Song::removeTrack2(): output route not found\n"); -                  } -            } -      } - -//--------------------------------------------------------- -//   removeTrack3 -//    non realtime part of removeTrack -//--------------------------------------------------------- - -void Song::removeTrack3(Track* track) -      { -      if (track->type() == Track::AUDIO_SOFTSYNTH) { -            SynthI* s = (SynthI*) track; -            s->deactivate3(); -            } -      emit trackRemoved(track); -      } - -//--------------------------------------------------------- -//   synthesizer -//--------------------------------------------------------- - -std::vector<QString>* Song::synthesizer() const -      { -      std::vector<QString>* l = new std::vector<QString>; - -      for (std::vector<Synth*>::const_iterator i = synthis.begin(); -         i != synthis.end(); ++i) { -            l->push_back((*i)->name()); -            } -      return l; -      } - -//--------------------------------------------------------- -//   setRecordFlag -//--------------------------------------------------------- - -void Song::setRecordFlag(Track* track, bool val) -      { -      if (track->type() == Track::AUDIO_OUTPUT) { -            if (!val && track->recordFlag() == false) { -                  muse->bounceToFile(); -                  } -            } -      track->setRecordFlag(val); -      } - -//--------------------------------------------------------- -//   setMute -//--------------------------------------------------------- - -void Song::setMute(Track* track, bool val) -      { -      track->setMute(val); -      emit muteChanged(track, track->mute()); -      } - -//--------------------------------------------------------- -//   setMonitor -//--------------------------------------------------------- - -void Song::setMonitor(Track* track, bool val) -      { -      track->setMonitor(val); -//      emit monitorChanged(track, track->mute()); -      } - -//--------------------------------------------------------- -//   setOff -//--------------------------------------------------------- - -void Song::setOff(Track* track, bool val) -      { -      track->setOff(val); -      emit offChanged(track, track->off()); -      } - -//--------------------------------------------------------- -//   setAutoRead -//--------------------------------------------------------- - -void Song::setAutoRead(Track* track, bool val) -      { -      track->setAutoRead(val); -      emit autoReadChanged(track, track->autoRead()); -      } - -//--------------------------------------------------------- -//   setAutoWrite -//--------------------------------------------------------- - -void Song::setAutoWrite(Track* track, bool val) -      { -      track->setAutoWrite(val); -      emit autoWriteChanged(track, track->autoRead()); -      } - -//--------------------------------------------------------- -//   setSolo -//--------------------------------------------------------- - -void Song::setSolo(Track* track, bool val) -      { -      if (!track->setSolo(val)) -            return; -      emit soloChanged(track, track->solo()); -      soloFlag = false; -      for (iTrack i = _tracks.begin(); i != _tracks.end(); ++i) { -            if ((*i)->solo()) { -                  soloFlag = true; -                  break; -                  } -            } -      for (iTrack i = _tracks.begin(); i != _tracks.end(); ++i) { -            (*i)->updateMute(); -            } -      } - -//---------------------------------------------------------  //   addControllerVal  //    GUI context  //--------------------------------------------------------- -void Song::addControllerVal(Track* t, int id, const Pos& pos, CVal val) +void Song::cmdAddControllerVal(Track* t, int id, const Pos& pos, CVal val)        {        Ctrl* c = t->getController(id);        if (c == 0) {              printf("Song::addControllerVal:: no controller %d found\n", id);              return;              } -      addControllerVal(t, c, pos, val); +      cmdAddControllerVal(t, c, pos, val);        } -void Song::addControllerVal(Track* t, Ctrl* c, const Pos& p, CVal val) +void Song::cmdAddControllerVal(Track* t, Ctrl* c, const Pos& p, CVal val)        {        unsigned time = t->timeType() == AL::FRAMES ? p.frame() : p.tick();        iCtrlVal e    = c->find(time);        if (e == c->end()) { -            // schedule new controller event +            // add new controller event              audio->msgAddController(t, c->id(), time, val);              }        else { +            // +            // change controller is handled inline: +            //              CVal oval = c->value(time); -// printf("change controller %f -  %f\n", oval.f, val.f);              startUndo();              undoOp(UndoOp::ModifyCtrl, t, c->id(), time, val, oval);              c->add(time, val); @@ -1929,7 +1345,7 @@ void Song::setControllerVal(Track* t, Ctrl* c, CVal val)              else {                    iCtrlVal e = c->find(time);                    if (e == c->end()) { -                        // schedule new controller event +                        // add new controller event                          audio->msgAddController(t, c->id(), time, val);                          }                    else { @@ -1945,66 +1361,16 @@ void Song::setControllerVal(Track* t, Ctrl* c, CVal val)        }  //--------------------------------------------------------- -//   removeControllerVal +//   cmdRemoveControllerVal  //--------------------------------------------------------- -void Song::removeControllerVal(Track* t, int id, unsigned time) +void Song::cmdRemoveControllerVal(Track* t, int id, unsigned time)        {        audio->msgRemoveController(t, id, time);        t->emitControllerChanged(id);        }  //--------------------------------------------------------- -//   moveTrack -//--------------------------------------------------------- - -void Song::moveTrack(Track* src, Track* dst) -      { -      iTrack si = qFind(_tracks.begin(), _tracks.end(), src); -      iTrack di = qFind(_tracks.begin(), _tracks.end(), dst); -      if (si == _tracks.end() || di == _tracks.end()) { -            printf("Song::moveTrack() track not found\n"); -            return; -            } -      _tracks.erase(si); -      _tracks.insert(di, src); -      } - -//--------------------------------------------------------- -//   changeTrackName -//--------------------------------------------------------- - -void Song::changeTrackName(Track* t, const QString& s) -      { -      startUndo(); -      undoOp(UndoOp::RenameTrack, t, t->name(), s); -      t->setName(s); -      endUndo(SC_TRACK_MODIFIED); -      } - -//--------------------------------------------------------- -//   trackExists -//--------------------------------------------------------- - -bool Song::trackExists(Track* t) const -      { -      return findTrack(t->name()) != 0; -      } - -//--------------------------------------------------------- -//   findTrack -//--------------------------------------------------------- - -Track* Song::findTrack(const QString& name) const -      { -      for (int i = 0; i < _tracks.size(); ++i) { -            if (_tracks[i]->name() == name) -                  return _tracks[i]; -            } -      return 0; -      } - -//---------------------------------------------------------  //   absoluteProjectPath  //--------------------------------------------------------- diff --git a/muse/muse/song.h b/muse/muse/song.h index 1813dab8..62925d49 100644 --- a/muse/muse/song.h +++ b/muse/muse/song.h @@ -362,12 +362,12 @@ class Song : public QObject {        //   Controller        //----------------------------------------- -      void addControllerVal(Track*, Ctrl*, const Pos&, CVal); -      void addControllerVal(Track*, int, const Pos&, CVal); +      void cmdAddControllerVal(Track*, Ctrl*, const Pos&, CVal); +      void cmdAddControllerVal(Track*, int, const Pos&, CVal);        void setControllerVal(Track*, Ctrl*, CVal);        void setControllerVal(Track*, int, CVal); -      void removeControllerVal(Track*,int,unsigned); +      void cmdRemoveControllerVal(Track*,int,unsigned);        void setAutoRead(Track*,bool);        void setAutoWrite(Track*,bool); diff --git a/muse/muse/songtrack.cpp b/muse/muse/songtrack.cpp new file mode 100644 index 00000000..e345da0a --- /dev/null +++ b/muse/muse/songtrack.cpp @@ -0,0 +1,662 @@ +//============================================================================= +//  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 "audio.h" +#include "midiplugin.h" +#include "driver/audiodev.h" +#include "muse.h" + +//--------------------------------------------------------- +//   deselectTracks +//--------------------------------------------------------- + +void Song::deselectTracks() +      { +      for (iTrack t = _tracks.begin(); t != _tracks.end(); ++t) +            (*t)->setSelected(false); +      } + +//--------------------------------------------------------- +//   selectTrack +//--------------------------------------------------------- + +void Song::selectTrack(Track* track) +      { +      bool changed = false; +      for (iTrack t = _tracks.begin(); t != _tracks.end(); ++t) { +            bool select = *t == track; +            if ((*t)->selected() != select) { +                  (*t)->setSelected(select); +                  changed = true; +                  } +            } +      if (changed) { +            updateSelectedTrack(); +            trackSelectionChanged(_selectedTrack); +            } +      } + +//--------------------------------------------------------- +//   updateSelectedTrack +//    set _selectedTrack to first selected track +//--------------------------------------------------------- + +void Song::updateSelectedTrack() +      { +      _selectedTrack = 0; +      for (iTrack t = _tracks.begin(); t != _tracks.end(); ++t) { +            bool select = (*t)->selected(); +            if (select) { +                  _selectedTrack = *t; +                  break; +                  } +            } +      } + +//--------------------------------------------------------- +//    addTrack +//    called from GUI context +//--------------------------------------------------------- + +Track* Song::addTrack(QAction* action) +      { +      int t = action->data().toInt(); + +      deselectTracks(); +      Track* track = 0; + +      Track::TrackType type = (Track::TrackType) t; +      if (t >= 5000) { +            int idx = t - 5000; +            type = Track::MIDI_SYNTI; +            int k = 0; +            iMidiPlugin i; +            for (i = midiPlugins.begin(); i != midiPlugins.end(); ++i) { +                  if ((*i)->type() != MEMPI_GENERATOR) +                        continue; +                  if (k == idx) +                        break; +                  ++k; +                  } +            if (i == midiPlugins.end()) { +                  fprintf(stderr, "Song::addTrack: midi synti not found\n"); +                  return 0; +                  } +            MidiPlugin* s = *i; +            MidiSynti* si = new MidiSynti(); +            QString sName(s->name()); +            for (k = s->instances(); k < 1000; ++k) { +                  QString instanceName = (k == 0) ?  +                     sName : instanceName.arg(sName).arg(k); + +                  MidiSyntiList* sl = midiSyntis(); +                  iMidiSynti sii; +                  for (sii = sl->begin(); sii != sl->end(); ++sii) { +                        if ((*sii)->name() == instanceName) +                              break; +                        } +                  if (sii == sl->end()) { +                        si->setName(instanceName); +                        break; +                        } +                  } +            if (si->initInstance(s)) { +                  delete si; +                  return 0; +                  } +            track = si; +            } +      else if (t >= 1000) { +            type = Track::AUDIO_SOFTSYNTH; +            QString sclass = synthis[t-1000]->name(); + +            Synth* s = findSynth(sclass); +            if (s == 0) { +                  fprintf(stderr, "synthi class <%s> not found\n", sclass.toLatin1().data()); +                  return 0; +                  } + +            SynthI* si = new SynthI(); +            int i; +            for (i = s->instances(); i < 1000; ++i) { +                  QString instanceName = (i == 0) ?  +                     s->name() : QString("%1-%2").arg(s->name()).arg(i); + +                  SynthIList* sl = syntis(); +                  iSynthI sii; +                  for (sii = sl->begin(); sii != sl->end(); ++sii) { +                        if ((*sii)->name() == instanceName) +                              break; +                        } +                  if (sii == sl->end()) { +                        si->setName(instanceName); +                        break; +                        } +                  } +            if (si->initInstance(s)) { +                  delete si; +                  return 0; +                  } +            track = si; +            } +      else { +            switch (type) { +                  case Track::MIDI: +                        track = new MidiTrack(); +                        break; +                  case Track::MIDI_OUT: +                        track = new MidiOutPort(); +                        break; +                  case Track::MIDI_IN: +                        track = new MidiInPort(); +                        break; +                  case Track::WAVE: +                        track = new WaveTrack(); +                        break; +                  case Track::AUDIO_OUTPUT: +                        track = new AudioOutput(); +                        break; +                  case Track::AUDIO_GROUP: +                        track = new AudioGroup(); +                        break; +                  case Track::AUDIO_INPUT: +                        track = new AudioInput(); +                        break; +                  case Track::AUDIO_SOFTSYNTH: +                  case Track::TRACK_TYPES: +                  default: +                        printf("Song::addTrack() illegal type %d\n", type); +                        abort(); +                  } +            if (track == 0) +                  return 0; +            } +      track->setDefaultName(); +      insertTrack(track, -1); +      return track; +      } + +//--------------------------------------------------------- +//   insertTrack +//--------------------------------------------------------- + +void Song::insertTrack(Track* track, int idx) +      { +      // +      //  add default routes +      // +      OutputList* ol = outputs(); +      AudioOutput* ao = 0; +      if (!ol->empty()) +            ao = ol->front(); +      MidiOutPortList* mol = midiOutPorts(); +      MidiOutPort* mo = 0; +      if (!mol->empty()) +            mo = mol->front(); + +      switch (track->type()) { +            case Track::TRACK_TYPES: +            case Track::MIDI_OUT: +            case Track::MIDI_IN: +            case Track::MIDI_SYNTI: +                  break; +            case Track::MIDI: +                  // +                  // connect to all midi inputs, if there is not already +                  // a route +                  // +                  if (!track->noInRoute()) { +                        MidiInPortList* mi = midiInPorts(); +                        for (iMidiInPort i = mi->begin(); i != mi->end(); ++i) { +                              for (int ch = 0; ch < MIDI_CHANNELS; ++ch) { +                                    RouteNode src(*i, ch, RouteNode::TRACK); +                                    RouteNode dst(track, -1, RouteNode::TRACK); +                                    Route r = Route(src, dst); +                                    track->inRoutes()->push_back(r); +                                    } +                              } +                        } +                  break; +            case Track::AUDIO_SOFTSYNTH: +            case Track::WAVE: +            case Track::AUDIO_GROUP: +                  if (ao) +                        track->outRoutes()->push_back(Route(RouteNode(track), RouteNode(ao))); +                  break; + +            case Track::AUDIO_INPUT: +                  { +                  // connect first input channel to first available jack output +                  // etc. +                  QList<PortName> op = audioDriver->outputPorts(false); +                  QList<PortName>::iterator is = op.begin(); +                  for (int ch = 0; ch < track->channels(); ++ch) { +                        if (is != op.end()) { +                              RouteNode src(is->port, -1, RouteNode::AUDIOPORT); +                              RouteNode dst(track, ch, RouteNode::TRACK); +                              Route r = Route(src, dst); +                              track->inRoutes()->push_back(r); +                              ++is; +                              } +                        } +//                  if (ao) +//                        track->outRoutes()->push_back(Route(ao)); +                  } +                  break; +            case Track::AUDIO_OUTPUT: +                  { +                  QList<PortName> op = audioDriver->inputPorts(false); +                  QList<PortName>::iterator is = op.begin(); +                  for (int ch = 0; ch < track->channels(); ++ch) { +                        if (is != op.end()) { +                              RouteNode src(track, ch, RouteNode::TRACK); +                              RouteNode dst(is->port, -1, RouteNode::AUDIOPORT); +                              Route r = Route(src, dst); +                              track->outRoutes()->push_back(r); +                              ++is; +                              } +                        } +                  } +                  break; +            } +      insertTrack1(track, idx); + +      startUndo(); +      undoOp(UndoOp::AddTrack, idx, track); +      AudioMsg msg; +      msg.id    = SEQM_ADD_TRACK; +      msg.track = track; +      msg.ival  = idx; +      audio->sendMsg(&msg); +      endUndo(SC_TRACK_INSERTED | SC_ROUTE); + +      emit trackAdded(track, idx); +      selectTrack(track); +      } + +//--------------------------------------------------------- +//   insertTrack0 +//    can only be called if sequencer is idle +//    (during song load) +//--------------------------------------------------------- + +void Song::insertTrack0(Track* track, int idx) +      { +      insertTrack1(track, idx); +      insertTrack2(track); +      } + +//--------------------------------------------------------- +//   insertTrack1 +//    non realtime part of insertTrack +//--------------------------------------------------------- + +void Song::insertTrack1(Track* track, int idx) +      { +      if (idx == -1) +            idx = _tracks.size(); +      _tracks.insert(idx, track); +      if (track->type() == Track::AUDIO_SOFTSYNTH) { +            SynthI* s = (SynthI*)track; +            Synth* sy = s->synth(); +            if (!s->isActivated()) +                  s->initInstance(sy); +            } +      if (audioState == AUDIO_RUNNING) { +            track->activate1(); +            track->activate2(); +            } +      } + +//--------------------------------------------------------- +//   insertTrack2 +//    realtime part +//--------------------------------------------------------- + +void Song::insertTrack2(Track* track) +      { +      switch(track->type()) { +            case Track::MIDI_SYNTI: +                  _midiSyntis.push_back((MidiSynti*)track); +                  break; +            case Track::MIDI: +                  _midis.push_back((MidiTrack*)track); +                  break; +            case Track::MIDI_OUT: +                  _midiOutPorts.push_back((MidiOutPort*)track); +                  break; +            case Track::MIDI_IN: +                  _midiInPorts.push_back((MidiInPort*)track); +                  break; +            case Track::WAVE: +                  _waves.push_back((WaveTrack*)track); +                  break; +            case Track::AUDIO_OUTPUT: +                  _outputs.push_back((AudioOutput*)track); +                  break; +            case Track::AUDIO_GROUP: +                  _groups.push_back((AudioGroup*)track); +                  break; +            case Track::AUDIO_INPUT: +                  _inputs.push_back((AudioInput*)track); +                  break; +            case Track::AUDIO_SOFTSYNTH: +                  { +                  SynthI* s = (SynthI*)track; +                  midiInstruments.push_back(s->instrument()); +                  _synthIs.push_back(s); +                  } +                  break; +            default: +                  fprintf(stderr, "insertTrack2: unknown track type %d\n", track->type()); +                  // abort(); +                  return; +            } + +      // +      //  connect routes +      // +      if (track->type() == Track::AUDIO_OUTPUT || track->type() == Track::MIDI_OUT) { +            foreach(Route r, *(track->inRoutes())) { +                  if (r.src.type != RouteNode::AUXPLUGIN) { +                        r.src.track->outRoutes()->push_back(r); +                        } +                  } +            } +      else if (track->type() == Track::AUDIO_INPUT || track->type() == Track::MIDI_IN) { +            foreach(Route r, *(track->outRoutes())) { +                  if (r.dst.type != RouteNode::AUXPLUGIN) { +                        r.dst.track->inRoutes()->push_back(r); +                        } +                  } +            } +      else { +            foreach(Route r, *(track->inRoutes())) { +                  if (r.src.type != RouteNode::AUXPLUGIN) { +                        r.src.track->outRoutes()->push_back(r); +                        } +                  } +            foreach(Route r, *(track->outRoutes())) { +                  if (r.dst.type != RouteNode::AUXPLUGIN) { +                        r.dst.track->inRoutes()->push_back(r); +                        } +                  } +            } +      } + +//--------------------------------------------------------- +//   removeTrack +//    called from gui context +//--------------------------------------------------------- + +void Song::removeTrack(Track* track) +      { +      startUndo(); +      int idx = _tracks.indexOf(track); +      undoOp(UndoOp::DeleteTrack, idx, track); +      removeTrack1(track); +      audio->msgRemoveTrack(track); +      removeTrack3(track); + +      endUndo(SC_TRACK_REMOVED | SC_ROUTE); +      } + +//--------------------------------------------------------- +//   removeTrack1 +//    non realtime part of removeTrack +//--------------------------------------------------------- + +void Song::removeTrack1(Track* track) +      { +      track->deactivate(); +      _tracks.removeAt(_tracks.indexOf(track)); +      } + +//--------------------------------------------------------- +//   removeTrack2 +//    called from RT context +//--------------------------------------------------------- + +void Song::removeTrack2(Track* track) +      { +      switch (track->type()) { +            case Track::MIDI_SYNTI: +                  _midiSyntis.removeAt(_midiSyntis.indexOf((MidiSynti*)track)); +                  break; +            case Track::MIDI: +                  _midis.removeAt(_midis.indexOf((MidiTrack*)track)); +                  break; +            case Track::MIDI_OUT: +                  _midiOutPorts.removeAt(_midiOutPorts.indexOf((MidiOutPort*)track)); +                  break; +            case Track::MIDI_IN: +                  _midiInPorts.removeAt(_midiInPorts.indexOf((MidiInPort*)track)); +                  break; +            case Track::WAVE: +                  _waves.removeAt(_waves.indexOf((WaveTrack*)track)); +                  break; +            case Track::AUDIO_OUTPUT: +                  _outputs.removeAt(_outputs.indexOf((AudioOutput*)track)); +                  break; +            case Track::AUDIO_INPUT: +                  _inputs.removeAt(_inputs.indexOf((AudioInput*)track)); +                  break; +            case Track::AUDIO_GROUP: +                  _groups.removeAt(_groups.indexOf((AudioGroup*)track)); +                  break; +            case Track::AUDIO_SOFTSYNTH: +                  { +                  SynthI* s = (SynthI*) track; +                  s->deactivate2(); +                  _synthIs.removeAt(_synthIs.indexOf(s)); +                  } +                  break; +            case Track::TRACK_TYPES: +                  return; +            } +      // +      //  remove routes +      // +      foreach (const Route r, *(track->inRoutes())) { +            if (r.src.type != RouteNode::TRACK) +                  continue; +            int idx = r.src.track->outRoutes()->indexOf(r); +            if (idx != -1) +                  r.src.track->outRoutes()->removeAt(idx); +            else +                  printf("Song::removeTrack2(): input route not found\n"); +            } +      foreach (const Route r, *(track->outRoutes())) { +            if (r.dst.type != RouteNode::TRACK) +                  continue; +            int idx = r.dst.track->inRoutes()->indexOf(r); +            if (idx != -1) +                  r.dst.track->inRoutes()->removeAt(idx); +            else { +                  printf("Song::removeTrack2(): output route not found\n"); +                  } +            } +      } + +//--------------------------------------------------------- +//   removeTrack3 +//    non realtime part of removeTrack +//--------------------------------------------------------- + +void Song::removeTrack3(Track* track) +      { +      if (track->type() == Track::AUDIO_SOFTSYNTH) { +            SynthI* s = (SynthI*) track; +            s->deactivate3(); +            } +      emit trackRemoved(track); +      } + +//--------------------------------------------------------- +//   synthesizer +//--------------------------------------------------------- + +std::vector<QString>* Song::synthesizer() const +      { +      std::vector<QString>* l = new std::vector<QString>; + +      for (std::vector<Synth*>::const_iterator i = synthis.begin(); +         i != synthis.end(); ++i) { +            l->push_back((*i)->name()); +            } +      return l; +      } + +//--------------------------------------------------------- +//   setRecordFlag +//--------------------------------------------------------- + +void Song::setRecordFlag(Track* track, bool val) +      { +      if (track->type() == Track::AUDIO_OUTPUT) { +            if (!val && track->recordFlag() == false) { +                  muse->bounceToFile(); +                  } +            } +      track->setRecordFlag(val); +      } + +//--------------------------------------------------------- +//   setMute +//--------------------------------------------------------- + +void Song::setMute(Track* track, bool val) +      { +      track->setMute(val); +      emit muteChanged(track, track->mute()); +      } + +//--------------------------------------------------------- +//   setMonitor +//--------------------------------------------------------- + +void Song::setMonitor(Track* track, bool val) +      { +      track->setMonitor(val); +//      emit monitorChanged(track, track->mute()); +      } + +//--------------------------------------------------------- +//   setOff +//--------------------------------------------------------- + +void Song::setOff(Track* track, bool val) +      { +      track->setOff(val); +      emit offChanged(track, track->off()); +      } + +//--------------------------------------------------------- +//   setAutoRead +//--------------------------------------------------------- + +void Song::setAutoRead(Track* track, bool val) +      { +      track->setAutoRead(val); +      emit autoReadChanged(track, track->autoRead()); +      } + +//--------------------------------------------------------- +//   setAutoWrite +//--------------------------------------------------------- + +void Song::setAutoWrite(Track* track, bool val) +      { +      track->setAutoWrite(val); +      emit autoWriteChanged(track, track->autoRead()); +      } + +//--------------------------------------------------------- +//   setSolo +//--------------------------------------------------------- + +void Song::setSolo(Track* track, bool val) +      { +      if (!track->setSolo(val)) +            return; +      emit soloChanged(track, track->solo()); +      soloFlag = false; +      for (iTrack i = _tracks.begin(); i != _tracks.end(); ++i) { +            if ((*i)->solo()) { +                  soloFlag = true; +                  break; +                  } +            } +      for (iTrack i = _tracks.begin(); i != _tracks.end(); ++i) { +            (*i)->updateMute(); +            } +      } + +//--------------------------------------------------------- +//   moveTrack +//--------------------------------------------------------- + +void Song::moveTrack(Track* src, Track* dst) +      { +      iTrack si = qFind(_tracks.begin(), _tracks.end(), src); +      iTrack di = qFind(_tracks.begin(), _tracks.end(), dst); +      if (si == _tracks.end() || di == _tracks.end()) { +            printf("Song::moveTrack() track not found\n"); +            return; +            } +      _tracks.erase(si); +      _tracks.insert(di, src); +      } + +//--------------------------------------------------------- +//   changeTrackName +//--------------------------------------------------------- + +void Song::changeTrackName(Track* t, const QString& s) +      { +      startUndo(); +      undoOp(UndoOp::RenameTrack, t, t->name(), s); +      t->setName(s); +      endUndo(SC_TRACK_MODIFIED); +      } + +//--------------------------------------------------------- +//   trackExists +//--------------------------------------------------------- + +bool Song::trackExists(Track* t) const +      { +      return findTrack(t->name()) != 0; +      } + +//--------------------------------------------------------- +//   findTrack +//--------------------------------------------------------- + +Track* Song::findTrack(const QString& name) const +      { +      for (int i = 0; i < _tracks.size(); ++i) { +            if (_tracks[i]->name() == name) +                  return _tracks[i]; +            } +      return 0; +      } + diff --git a/muse/muse/track.cpp b/muse/muse/track.cpp index ca457ad6..af2b2a3d 100644 --- a/muse/muse/track.cpp +++ b/muse/muse/track.cpp @@ -105,8 +105,8 @@ Track::Track()        _channels      = 0;           // 1 - mono, 2 - stereo        _selected      = false;        _locked        = false; -      _autoRead      = false; -      _autoWrite     = false; +      _autoRead      = autoReadDefault(); +      _autoWrite     = autoWriteDefault();        for (int i = 0; i < MAX_CHANNELS; ++i) {              _meter[i]     = 0.0f; @@ -245,9 +245,9 @@ void Track::writeProperties(Xml& xml) const              xml.intTag("locked", _locked);        if (_monitor)              xml.intTag("monitor", _monitor); -      if (!_autoRead) +      if (_autoRead != autoReadDefault())              xml.intTag("autoRead", _autoRead); -      if (_autoWrite) +      if (_autoWrite != autoWriteDefault())              xml.intTag("autoWrite", _autoWrite);        if (_selected)              xml.intTag("selected", _selected); diff --git a/muse/muse/track.h b/muse/muse/track.h index c7a68d8e..fa21b016 100644 --- a/muse/muse/track.h +++ b/muse/muse/track.h @@ -326,6 +326,9 @@ class Track : public QObject {        void setDeviceId(int val) { _deviceId = val; }        virtual bool muteDefault() const { return false; } +      virtual bool autoReadDefault() const { return false; } +      virtual bool autoWriteDefault() const { return false; } +        virtual MidiOut* midiOut() { return 0;     }        virtual MidiInstrument* instrument() { return 0; }        }; | 
