summaryrefslogtreecommitdiff
path: root/muse_qt4_evolution/muse/arranger.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'muse_qt4_evolution/muse/arranger.cpp')
-rw-r--r--muse_qt4_evolution/muse/arranger.cpp1382
1 files changed, 1382 insertions, 0 deletions
diff --git a/muse_qt4_evolution/muse/arranger.cpp b/muse_qt4_evolution/muse/arranger.cpp
new file mode 100644
index 00000000..82c859cb
--- /dev/null
+++ b/muse_qt4_evolution/muse/arranger.cpp
@@ -0,0 +1,1382 @@
+//=============================================================================
+// 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 "muse.h"
+#include "arranger.h"
+#include "tlwidget.h"
+#include "tlswidget.h"
+#include "icons.h"
+#include "widgets/simplebutton.h"
+#include "configtrack.h"
+#include "canvas.h"
+#include "widgets/utils.h"
+#include "widgets/splitter.h"
+#include "astrip.h"
+#include "mstrip.h"
+#include "audio.h"
+#include "shortcuts.h"
+#include "trackinfo.h"
+#include "midictrl.h"
+#include "gconfig.h"
+#include "part.h"
+
+//---------------------------------------------------------
+// TrElement elements
+// list of available track gui elements
+//---------------------------------------------------------
+
+const TrElement trElements[] = {
+ TrElement(TR_NAME, 1, "trackname", -1),
+ TrElement(TR_RECORD, 0, "record",
+ Track::M_MIDI | Track::M_AUDIO_OUTPUT | Track::M_WAVE),
+ TrElement(TR_OFF, 2, "off",
+ Track::M_AUDIO_OUTPUT
+ | Track::M_AUDIO_GROUP
+ | Track::M_WAVE
+ | Track::M_AUDIO_INPUT
+ | Track::M_AUDIO_SOFTSYNTH),
+ TrElement(TR_DRUMMAP, 2, "use drum map", Track::M_MIDI),
+ TrElement(TR_MUTE, 3, "mute", -1),
+ TrElement(TR_SOLO, 3, "solo", -1),
+ TrElement(TR_MONITOR, 3, "monitor",
+ Track::M_MIDI | Track::M_WAVE),
+ TrElement(TR_AREAD, 4, "automation read",
+ -1 & ~(Track::M_MIDI_IN | Track::M_MIDI)),
+ TrElement(TR_AWRITE, 4, "automation write",
+ -1 & ~(Track::M_MIDI_IN | Track::M_MIDI)),
+ TrElement(TR_OCHANNEL, 5, "output channel", Track::M_MIDI),
+ TrElement(TR_INSTRUMENT, 6, "instrument", Track::M_MIDI_OUT),
+ TrElement(TR_PATCH, 7, "patch", Track::M_MIDI),
+ };
+
+const int nTrElements = sizeof(trElements)/sizeof(*trElements);
+
+TrGroupList glist[Track::TRACK_TYPES];
+
+extern void populateAddTrack(QMenu*);
+
+//---------------------------------------------------------
+// sizeHint
+//---------------------------------------------------------
+
+QSize InfoStack::sizeHint() const
+ {
+ return QSize(infoWidth, height());
+ }
+
+//---------------------------------------------------------
+// TLayout
+// simple layout for trackList
+//---------------------------------------------------------
+
+class TLayout : public QLayout {
+ QList<QLayoutItem*> itemList;
+
+ public:
+ TLayout() {}
+ ~TLayout();
+
+ void addItem(QLayoutItem* item);
+ void insertWidget(int index, QWidget* item);
+ Qt::Orientations expandingDirections() const { return 0; }
+ bool hasHeightForWidth() const { return false; }
+ int count() const { return itemList.size(); }
+ void setGeometry(const QRect &rect);
+ QSize sizeHint() const { return ((QWidget*)parent())->size(); }
+ QLayoutItem *itemAt(int index) const { return itemList.value(index); }
+ QLayoutItem *takeAt(int idx) {
+ return idx >= 0 && idx < itemList.size() ? itemList.takeAt(idx) : 0;
+ }
+ void clear() {
+ QLayoutItem* child;
+ while ((child = takeAt(0)) != 0) {
+ delete child;
+ }
+ }
+ };
+
+//---------------------------------------------------------
+// TLayout
+//---------------------------------------------------------
+
+TLayout::~TLayout()
+ {
+ QLayoutItem* child;
+ while ((child = takeAt(0)) != 0)
+ delete child;
+ }
+
+//---------------------------------------------------------
+// insertWidget
+//---------------------------------------------------------
+
+void TLayout::insertWidget(int index, QWidget* item)
+ {
+ if (item->parent() == 0)
+ item->setParent((QWidget*)parent());
+ itemList.insert(index, new QWidgetItem(item));
+ update();
+ }
+
+//---------------------------------------------------------
+// addItem
+//---------------------------------------------------------
+
+void TLayout::addItem(QLayoutItem* item)
+ {
+ itemList.append(item);
+ update();
+ }
+
+//---------------------------------------------------------
+// setGeometry
+//---------------------------------------------------------
+
+void TLayout::setGeometry(const QRect& r)
+ {
+ int y = r.y();
+ int n = itemList.size();
+ int width = r.width(); // ((QWidget*)parent())->width();
+ for (int i = 0; i < n; ++i) {
+ QLayoutItem *item = itemList.at(i);
+ QWidget* w = item->widget();
+ int h = w->height();
+ w->setGeometry(0, y, width, h);
+ y += h;
+ }
+ }
+
+//---------------------------------------------------------
+// TlsvLayout
+//---------------------------------------------------------
+
+class TlsvLayout : public QLayout {
+ QList<QLayoutItem*> itemList;
+ int dx, dy;
+
+ public:
+ TlsvLayout() {
+ dx = 0;
+ dy = 0;
+ }
+ ~TlsvLayout();
+
+ void setOffset(int x, int y) {
+ dx = x;
+ dy = y;
+ }
+ void addItem(QLayoutItem* item);
+ void insertWidget(int index, QWidget* item);
+ Qt::Orientations expandingDirections() const { return 0; }
+ bool hasHeightForWidth() const { return false; }
+ int count() const { return itemList.size(); }
+ void setGeometry(const QRect &rect);
+ QSize sizeHint() const { return ((QWidget*)parent())->size(); }
+ QLayoutItem *itemAt(int index) const { return itemList.value(index); }
+ QLayoutItem *takeAt(int idx) {
+ return idx >= 0 && idx < itemList.size() ? itemList.takeAt(idx) : 0;
+ }
+ };
+
+//---------------------------------------------------------
+// TlsvLayout
+//---------------------------------------------------------
+
+TlsvLayout::~TlsvLayout()
+ {
+ QLayoutItem* child;
+ while ((child = takeAt(0)) != 0)
+ delete child;
+ }
+
+//---------------------------------------------------------
+// insertWidget
+//---------------------------------------------------------
+
+void TlsvLayout::insertWidget(int index, QWidget* item)
+ {
+ if (item->parent() == 0)
+ item->setParent((QWidget*)parent());
+ itemList.insert(index, new QWidgetItem(item));
+ update();
+ }
+
+//---------------------------------------------------------
+// addItem
+//---------------------------------------------------------
+
+void TlsvLayout::addItem(QLayoutItem* item)
+ {
+ itemList.append(item);
+ update();
+ }
+
+//---------------------------------------------------------
+// setGeometry
+//---------------------------------------------------------
+
+void TlsvLayout::setGeometry(const QRect& r)
+ {
+ QLayoutItem *item = itemList.at(0);
+ QWidget* w = item->widget();
+ w->setGeometry(dx, dy, r.width(), w->height());
+ }
+
+//---------------------------------------------------------
+// newAddTrackMenu
+//---------------------------------------------------------
+
+QMenu* newAddTrackMenu(QWidget* parent)
+ {
+ QMenu* menu = new QMenu(parent);
+ populateAddTrack(menu);
+ return menu;
+ }
+
+//---------------------------------------------------------
+// Arranger
+//---------------------------------------------------------
+
+Arranger::Arranger(QMainWindow* parent)
+ : QWidget(parent)
+ {
+// setFocusPolicy(Qt::StrongFocus);
+ setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
+
+ for (int i = 0; i < Track::TRACK_TYPES; ++i)
+ trackInfos[i] = 0;
+
+ zeroTrackInfo = 0;
+ _curTrack = 0;
+ strip = 0;
+ info = 0;
+ tool = PointerTool;
+
+ for (int tt = 0; tt < Track::TRACK_TYPES; ++tt) {
+ int gn = 0;
+ TrElementList group;
+ for (int i = 0; i < nTrElements; ++i) {
+ if (!(trElements[i].trackMask & (1<<tt)))
+ continue;
+ if (trElements[i].grp != gn) {
+ glist[tt].push_back(group);
+ group.clear();
+ gn = trElements[i].grp;
+ }
+ group.push_back(&trElements[i]);
+ }
+ if (!group.empty())
+ glist[tt].push_back(group);
+ }
+
+ configTrackEditor = 0;
+ QLayout* ml = new QHBoxLayout;
+ ml->setSpacing(0);
+ ml->setMargin(0);
+ setLayout(ml);
+
+ infoDock = new QDockWidget(tr("TrackInfo"));
+ infoDock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
+ infoDockAction = infoDock->toggleViewAction();
+
+ mixerDock = new QDockWidget(tr(""));
+ mixerDock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
+ mixerDockAction = mixerDock->toggleViewAction();
+
+ parent->setDockNestingEnabled(true);
+
+ parent->addDockWidget(Qt::LeftDockWidgetArea, infoDock, Qt::Horizontal);
+ parent->addDockWidget(Qt::LeftDockWidgetArea, mixerDock, Qt::Horizontal);
+
+ infoView = new QScrollArea;
+ infoView->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding);
+
+ infoDock->setWidget(infoView);
+ infoView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+
+ trackInfo = new InfoStack();
+ infoView->setWidget(trackInfo);
+ infoView->setWidgetResizable(true);
+
+ trackInfoVisible = false;
+ mixerStripVisible = false;
+
+ infoDock->setVisible(false);
+ mixerDock->setVisible(false);
+
+ connect(infoDockAction, SIGNAL(toggled(bool)), SLOT(toggleTrackInfo(bool)));
+ connect(mixerDockAction, SIGNAL(toggled(bool)), SLOT(toggleMixerStrip(bool)));
+
+ tlsv = new TrackListWidget;
+ tlsv->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
+ tlsvLayout = new TlsvLayout;
+ tlsv->setLayout(tlsvLayout);
+ trackList = new QWidget;
+ trackList->setAttribute(Qt::WA_StaticContents);
+ trackList->setMouseTracking(true);
+
+ tlsv->layout()->addWidget(trackList);
+ tl = new TLayout;
+ trackList->setLayout(tl);
+
+ //
+ // Toolbox
+ //
+ QHBoxLayout* ttoolsLayout = new QHBoxLayout;
+ ttoolsLayout->setMargin(1);
+ ttoolsLayout->setSpacing(1);
+
+ SimpleButton* configButton = new SimpleButton(configIcon, configIcon);
+ configButton->setAutoRaise(true);
+ configButton->setToolTip(tr("Config Tracklist"));
+ configButton->setFixedHeight(rulerHeight-4);
+ connect(configButton, SIGNAL(clicked()), SLOT(configTrackList()));
+ ttoolsLayout->addWidget(configButton);
+ ttoolsLayout->addStretch(100);
+
+ gmute = newMuteButton();
+ gmute->setFixedWidth(rulerHeight);
+ gmute->setToolTip(tr("all mute off"));
+ gmute->setFixedHeight(rulerHeight-4);
+ ttoolsLayout->addWidget(gmute);
+ setGMute();
+ connect(song, SIGNAL(muteChanged(Track*,bool)), SLOT(setGMute()));
+ connect(gmute, SIGNAL(clicked(bool)), SLOT(offGMute()));
+
+ gsolo = newSoloButton();
+ gsolo->setFixedWidth(rulerHeight);
+ gsolo->setToolTip(tr("all solo off"));
+ gsolo->setFixedHeight(rulerHeight-4);
+ ttoolsLayout->addWidget(gsolo);
+ setGSolo();
+ connect(song, SIGNAL(soloChanged(Track*,bool)), SLOT(setGSolo()));
+ connect(gsolo, SIGNAL(clicked(bool)), SLOT(offGSolo()));
+
+ gar = newAutoReadButton();
+ gar->setFixedWidth(rulerHeight);
+ gar->setToolTip(tr("all autoRead off"));
+ gar->setFixedHeight(rulerHeight-4);
+ ttoolsLayout->addWidget(gar);
+ setGar();
+ connect(song, SIGNAL(autoReadChanged(Track*,bool)), SLOT(setGar()));
+ connect(gar, SIGNAL(clicked(bool)), SLOT(offGar()));
+
+ gaw = newAutoWriteButton();
+ gaw->setFixedWidth(rulerHeight);
+ gaw->setToolTip(tr("all autoWrite off"));
+ gaw->setFixedHeight(rulerHeight-4);
+ ttoolsLayout->addWidget(gaw);
+ setGaw();
+ connect(song, SIGNAL(autoWriteChanged(Track*,bool)), SLOT(setGaw()));
+ connect(gaw, SIGNAL(clicked(bool)), SLOT(offGaw()));
+
+ QHBoxLayout* infoboxLayout = new QHBoxLayout;
+ infoboxLayout->setMargin(1);
+ infoboxLayout->setSpacing(1);
+
+ SimpleButton* tifButton = new SimpleButton(QString());
+ tifButton->setCheckable(true);
+ tifButton->setFixedSize(infoHeight-2, infoHeight);
+ tifButton->setDefaultAction(infoDockAction);
+ infoDockAction->setText(tr("i"));
+ infoDockAction->setToolTip(tr("Show Track Info"));
+ infoboxLayout->addWidget(tifButton);
+
+ SimpleButton* mstButton = new SimpleButton(QString());
+ mstButton->setCheckable(true);
+ mstButton->setFixedSize(infoHeight-2, infoHeight);
+ mstButton->setDefaultAction(mixerDockAction);
+ mixerDockAction->setText(tr("m"));
+ mixerDockAction->setToolTip(tr("Show Mixer Strip"));
+ infoboxLayout->addWidget(mstButton);
+
+ infoboxLayout->addStretch(100);
+
+ split = new Splitter(Qt::Horizontal);
+ split->setOpaqueResize(true);
+ split->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
+ QWidget* tw = new QWidget;
+ split->addWidget(tw);
+ QVBoxLayout* trackListGrid = new QVBoxLayout;
+ trackListGrid->setMargin(0);
+ trackListGrid->setSpacing(0);
+ tw->setLayout(trackListGrid);
+
+ trackListGrid->addLayout(ttoolsLayout);
+ QFrame* ruler = hLine(0);
+ ruler->setLineWidth(2);
+ trackListGrid->addWidget(ruler);
+ trackListGrid->addWidget(tlsv, 100);
+ trackListGrid->addLayout(infoboxLayout);
+
+ //
+ // canvas widget
+ //
+ canvas = new PartCanvas;
+ canvas->setCornerWidget(new QSizeGrip(canvas));
+ split->addWidget(canvas);
+ split->setStretchFactor(1, 100);
+ canvas->setTool(tool);
+ canvas->verticalScrollBar()->setSingleStep(minTrackHeight/2);
+
+ connect(tlsv, SIGNAL(mouseWheel(QWheelEvent*)), SLOT(mouseWheel(QWheelEvent*)));
+ connect(song, SIGNAL(posChanged(int,const AL::Pos&,bool)), canvas, SLOT(setLocatorPos(int,const AL::Pos&,bool)));
+ connect(song, SIGNAL(lenChanged(const AL::Pos&)), canvas, SLOT(setEndPos(const AL::Pos&)));
+ connect(song, SIGNAL(tempoChanged()), canvas, SLOT(tempoChanged()));
+ connect(canvas, SIGNAL(kbdMovementUpdate(Track*, Part*)), SLOT(kbdMovementUpdate(Track*, Part*)));
+ connect(muse, SIGNAL(rasterChanged(int)), canvas, SLOT(setRaster(int)));
+ connect(canvas, SIGNAL(cursorPos(const AL::Pos&,bool)), SIGNAL(cursorPos(const AL::Pos&,bool)));
+ 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(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(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&)));
+
+ layout()->addWidget(split);
+
+ connect(muse, SIGNAL(configChanged()), SLOT(updateConfiguration()));
+ connect(song, SIGNAL(trackSelectionChanged(Track*)), SLOT(setSelectedTrack(Track*)));
+ connect(song, SIGNAL(trackRemoved(Track*)), SLOT(removeTrack(Track*)));
+ connect(song, SIGNAL(trackAdded(Track*,int)), SLOT(insertTrack(Track*)));
+ connect(muse, SIGNAL(startLoadSong()), SLOT(startLoadSong()));
+ }
+
+//---------------------------------------------------------
+// setPos
+//---------------------------------------------------------
+
+void Arranger::setPos(int idx, const AL::Pos& pos)
+ {
+ song->setPos(idx, pos.snaped(muse->raster()));
+ }
+
+//---------------------------------------------------------
+// setTLViewPos
+//---------------------------------------------------------
+
+void Arranger::setTLViewPos(int /*x*/, int y)
+ {
+#if 1
+ int dy = y + trackList->y();
+ tlsv->scroll(0, -dy);
+#else
+ trackList->setGeometry(0, -y, trackList->width(), trackList->height());
+#endif
+ tlsvLayout->setOffset(0, -y);
+ }
+
+//---------------------------------------------------------
+// tlIndex
+//---------------------------------------------------------
+
+int Arranger::tlIndex(Track* t) const
+ {
+ const TrackList* stl = song->tracks();
+
+ int idx = 0;
+ for (ciTrack i = stl->begin(); i != stl->end(); ++i, ++idx) {
+ if (*i == t)
+ break;
+ ArrangerTrack* at = &(*i)->arrangerTrack;
+ if (at->tw == 0)
+ continue;
+ idx += (*i)->subtracks.size();
+ }
+ return idx;
+ }
+
+int Arranger::tlIndex(ArrangerTrack* t) const
+ {
+ TrackList* stl = song->tracks();
+
+ int idx = 0;
+ for (ciTrack i = stl->begin(); i != stl->end(); ++i, ++idx) {
+ ArrangerTrack* at = &(*i)->arrangerTrack;
+ if (at->tw == 0)
+ continue;
+ ArrangerTrackList& atl = (*i)->subtracks;
+ for (iArrangerTrack k = atl.begin(); k != atl.end(); ++k) {
+ ++idx;
+ if (*k == t)
+ return idx;
+ }
+ }
+ return -1; // crash
+ }
+
+//---------------------------------------------------------
+// insertTrack
+//---------------------------------------------------------
+
+void Arranger::insertTrack1(Track* t)
+ {
+ int idx = tlIndex(t);
+ //-------------------------
+ // track list widget
+ //-------------------------
+
+ TLWidget* tw = new TLWidget(t, &glist[t->type()]);
+ tw->setFixedHeight(t->arrangerTrack.h);
+ tl->insertWidget(idx, tw);
+ tw->show(); // needed if song is reloaded
+
+ connect(tw, SIGNAL(plusClicked(TLWidget*)), SLOT(appendSubtrack(TLWidget*)));
+ connect(tw, SIGNAL(moveTrack(Track*,Track*)), SLOT(moveTrack(Track*,Track*)));
+ connect(this, SIGNAL(configChanged()), tw, SLOT(configChanged()));
+ connect(tw, SIGNAL(drag(int, int)), SLOT(drag(int,int)));
+ connect(tw, SIGNAL(startDrag(int)), SLOT(startDrag(int)));
+ connect(t, SIGNAL(partsChanged()), canvas->widget(), SLOT(update()));
+
+ ArrangerTrack* at = &(t->arrangerTrack);
+ at->tw = tw;
+ }
+
+void Arranger::insertTrack(Track* t)
+ {
+ insertTrack1(t);
+ t->arrangerTrack.tw->show();
+ updateIndex();
+ if (_curTrack == 0)
+ setSelectedTrack(_curTrack);
+ }
+
+//---------------------------------------------------------
+// removeTrack
+//---------------------------------------------------------
+
+void Arranger::removeTrack(Track* t)
+ {
+ ArrangerTrack* at = &t->arrangerTrack;
+ if (at->tw == 0)
+ return;
+
+ tl->removeWidget(at->tw);
+
+ at->tw->close();
+ at->tw = 0;
+
+ for (iArrangerTrack i = t->subtracks.begin(); i != t->subtracks.end(); ++i) {
+ ArrangerTrack* at = *i;
+ tl->removeWidget(at->tw);
+ at->tw->close();
+ }
+ t->subtracks.clear();
+
+ if (t == _curTrack) {
+ if (!song->tracks()->isEmpty())
+ song->selectTrack(song->tracks()->front());
+ }
+ updateIndex();
+ }
+
+//---------------------------------------------------------
+// drag
+//---------------------------------------------------------
+
+void Arranger::drag(int trackIdx, int delta)
+ {
+ int h = startH + delta;
+ if (h < minTrackHeight)
+ h = minTrackHeight;
+ ArrangerTrack* at = atrack(trackIdx);
+ at->tw->setFixedHeight(h);
+ updateIndex();
+ }
+
+//---------------------------------------------------------
+// startDrag
+//---------------------------------------------------------
+
+void Arranger::startDrag(int trackIdx)
+ {
+ ArrangerTrack* at = atrack(trackIdx);
+ startH = at->tw->height();
+ }
+
+//---------------------------------------------------------
+// TrackListWidget
+//---------------------------------------------------------
+
+TrackListWidget::TrackListWidget(QWidget* parent)
+ : QWidget(parent)
+ {
+ setAttribute(Qt::WA_NoSystemBackground);
+ setAttribute(Qt::WA_StaticContents);
+ }
+
+//---------------------------------------------------------
+// paintEvent
+//---------------------------------------------------------
+
+void TrackListWidget::paintEvent(QPaintEvent* ev)
+ {
+ QPainter p(this);
+ p.eraseRect(ev->rect());
+ }
+
+//---------------------------------------------------------
+// mousePressEvent
+//---------------------------------------------------------
+
+void TrackListWidget::mousePressEvent(QMouseEvent* ev)
+ {
+ if (ev->button() == Qt::RightButton) {
+ QMenu* menu = newAddTrackMenu(this);
+ menu->exec(ev->globalPos());
+ }
+ }
+
+//---------------------------------------------------------
+// wheelEvent
+//---------------------------------------------------------
+
+void TrackListWidget::wheelEvent(QWheelEvent* e)
+ {
+ emit mouseWheel(e);
+ }
+
+//---------------------------------------------------------
+// mouseWheel
+// get redirected mouse wheel events from TrackListWidget
+//---------------------------------------------------------
+
+void Arranger::mouseWheel(QWheelEvent* e)
+ {
+ if (e->orientation() != Qt::Vertical)
+ return;
+ QScrollBar* sb = canvas->verticalScrollBar();
+ int step = qMin(QApplication::wheelScrollLines() * sb->singleStep(), sb->pageStep());
+ if ((e->modifiers() & Qt::ControlModifier) || (e->modifiers() & Qt::ShiftModifier))
+ step = sb->pageStep();
+ int offset = e->delta() * step / 120;
+ if (sb->invertedControls())
+ offset = -offset;
+ if (qAbs(offset) < 1)
+ return;
+ sb->setValue(sb->value() + offset);
+ e->accept();
+ }
+
+//---------------------------------------------------------
+// appendSubtrack
+// the user requests a new controller subtrack
+//---------------------------------------------------------
+
+void Arranger::appendSubtrack(TLWidget* trackWidget)
+ {
+ Track* t = trackWidget->track();
+
+ ArrangerTrack* at = new ArrangerTrack;
+ at->h = minTrackHeight;
+ at->ctrl = CTRL_NO_CTRL;
+ t->subtracks.push_back(at);
+ if(initSubtrack(t, at)==true) {
+ updateIndex();
+ }
+ else {
+ t->subtracks.remove(at);
+ delete at;
+ }
+ }
+
+//---------------------------------------------------------
+// initSubtrack
+//---------------------------------------------------------
+
+bool Arranger::initSubtrack(Track* t, ArrangerTrack* at)
+ {
+ TLSWidget* tw = new TLSWidget(t, at, canvas);
+ tw->setFixedHeight(at->h);
+
+ if(tw->setCtrl(at->ctrl) == true) {
+ tl->insertWidget(tlIndex(at), tw);
+ at->tw = tw;
+ connect(tw, SIGNAL(minusClicked(TLSWidget*)), SLOT(removeSubtrack(TLSWidget*)));
+ connect(tw, SIGNAL(controllerChanged(int)), canvas->widget(), SLOT(update()));
+ connect(tw, SIGNAL(drag(int, int)), SLOT(drag(int,int)));
+ connect(tw, SIGNAL(startDrag(int)), SLOT(startDrag(int)));
+ tw->show();
+ }
+ else {
+ delete tw;
+ return false;
+ }
+ return true;
+ }
+
+//---------------------------------------------------------
+// removeSubtrack
+//---------------------------------------------------------
+
+void Arranger::removeSubtrack(TLSWidget* w)
+ {
+ Track* t = w->track();
+ for (iArrangerTrack it = t->subtracks.begin(); it != t->subtracks.end(); ++it) {
+ ArrangerTrack* at = *it;
+ if (at->tw == w) {
+ tl->removeWidget(at->tw);
+// at->tw->close();
+ delete at->tw;
+ t->subtracks.erase(it);
+ delete at;
+ break;
+ }
+ }
+ updateIndex();
+ }
+
+//---------------------------------------------------------
+// configTrackList
+//---------------------------------------------------------
+
+void Arranger::configTrackList()
+ {
+ if (configTrackEditor == 0) {
+ configTrackEditor = new ConfigTrackList(this);
+ connect(configTrackEditor, SIGNAL(trackConfigChanged()), SIGNAL(configChanged()));
+ }
+ configTrackEditor->show();
+ }
+
+//---------------------------------------------------------
+// atrack
+//---------------------------------------------------------
+
+ArrangerTrack* Arranger::atrack(int idx)
+ {
+ int k = 0;
+ TrackList* stl = song->tracks();
+ for (iTrack i = stl->begin(); i != stl->end(); ++i) {
+ ArrangerTrack* at = &(*i)->arrangerTrack;
+ if (idx == k)
+ return at;
+ ++k;
+ for (iArrangerTrack it = (*i)->subtracks.begin(); it != (*i)->subtracks.end(); ++it) {
+ ArrangerTrack* t = *it;
+ if (idx == k)
+ return t;
+ ++k;
+ }
+ }
+ return 0;
+ }
+
+//---------------------------------------------------------
+// updateIndex
+// update vertical scrollbar & index values
+//---------------------------------------------------------
+
+void Arranger::updateIndex()
+ {
+ int idx = 0;
+ int h = 2 * defaultTrackHeight; // always show room for at least two
+ // tracks at end of list
+
+ TrackList* stl = song->tracks();
+ for (iTrack i = stl->begin(); i != stl->end(); ++i) {
+ ArrangerTrack* at = &(*i)->arrangerTrack;
+ if (at->tw == 0)
+ continue;
+ ((TLWidget*)at->tw)->setIdx(idx);
+ h += at->tw->height();
+ ++idx;
+ for (iArrangerTrack it = (*i)->subtracks.begin(); it != (*i)->subtracks.end(); ++it) {
+ ArrangerTrack* t = *it;
+ if (t->tw == 0)
+ continue;
+ ((TLSWidget*)t->tw)->setIdx(idx);
+ h += t->tw->height();
+ ++idx;
+ }
+ }
+ setGMute();
+ setGSolo();
+ setGar();
+ setGaw();
+ canvas->setVSize(h);
+ trackList->setFixedHeight(h + 32);
+ canvas->widget()->update();
+ QPoint p(canvas->getWPos());
+ setTLViewPos(0, p.y());
+ }
+
+//---------------------------------------------------------
+// toggleTrackInfo
+//---------------------------------------------------------
+
+void Arranger::toggleTrackInfo(bool val)
+ {
+ trackInfoVisible = val;
+ if (trackInfoVisible) {
+ if (_curTrack == 0) {
+ if (zeroTrackInfo == 0) {
+ zeroTrackInfo = new QWidget(this);
+ trackInfo->addWidget(zeroTrackInfo);
+ }
+ trackInfo->setCurrentWidget(zeroTrackInfo);
+
+ return;
+ }
+ Track::TrackType t = _curTrack->type();
+ TrackInfo* w = trackInfos[t];
+ if (w == 0) {
+ w = trackInfos[t] = createTrackInfo();
+ trackInfo->addWidget(w);
+ }
+ w->init(_curTrack);
+ trackInfo->setCurrentWidget(w);
+ }
+// infoDock->layout()->invalidate();
+// infoDock->layout()->update();
+ }
+
+//---------------------------------------------------------
+// toggleMixerStrip
+//---------------------------------------------------------
+
+void Arranger::toggleMixerStrip(bool val)
+ {
+ mixerStripVisible = val;
+ if (mixerStripVisible && _curTrack) {
+ if (strip && _curTrack != strip->getTrack()) {
+ strip->close();
+ strip = 0;
+ }
+ if (!strip) {
+ switch(_curTrack->type()) {
+ case Track::MIDI_IN:
+ strip = new MidiInPortStrip(0, (MidiInPort*)_curTrack, false);
+ break;
+ case Track::MIDI_OUT:
+ strip = new MidiOutPortStrip(0, (MidiOutPort*)_curTrack, false);
+ break;
+ case Track::MIDI_SYNTI:
+ strip = new MidiSyntiStrip(0, (MidiSynti*)_curTrack, false);
+ break;
+ case Track::MIDI:
+ strip = new MidiStrip(0, (MidiTrack*)_curTrack, false);
+ break;
+ default:
+ strip = new AudioStrip(0, (AudioTrack*)_curTrack, false);
+ break;
+ }
+ //
+ // it looks like the dock widget has a minimum
+ // width
+ strip->setFixedWidth(STRIP_WIDTH + 10);
+ mixerDock->setWidget(strip);
+ }
+ }
+ else {
+ if (strip) {
+ strip->close();
+ strip = 0;
+ }
+ }
+ }
+
+//---------------------------------------------------------
+// startLoadSong
+//---------------------------------------------------------
+
+void Arranger::startLoadSong()
+ {
+ if (strip)
+ strip->close();
+ strip = 0;
+
+ TrackList* stl = song->tracks();
+ for (iTrack i = stl->begin(); i != stl->end(); ++i) {
+ ArrangerTrack* at = &(*i)->arrangerTrack;
+ tl->removeWidget(at->tw);
+ at->tw->close();
+ delete at->tw;
+ at->tw = 0;
+ for (iArrangerTrack it = (*i)->subtracks.begin(); it != (*i)->subtracks.end(); ++it) {
+ ArrangerTrack* at = *it;
+ tl->removeWidget(at->tw);
+ at->tw->close();
+ delete at->tw;
+ }
+ (*i)->subtracks.clear();
+ }
+ _curTrack = 0;
+ }
+
+//---------------------------------------------------------
+// endLoadSong
+// create track list widgets
+//---------------------------------------------------------
+
+void Arranger::endLoadSong()
+ {
+ TrackList* stl = song->tracks();
+
+ for (iTrack i = stl->begin(); i != stl->end(); ++i) {
+ Track* t = *i;
+ insertTrack1(t);
+ for (iArrangerTrack i = t->subtracks.begin(); i != t->subtracks.end(); ++i) {
+ initSubtrack(t, *i);
+ }
+ }
+ updateIndex();
+ setSelectedTrack(song->selectedTrack());
+ infoDock->setVisible(trackInfoVisible);
+ mixerDock->setVisible(mixerStripVisible);
+ }
+
+//---------------------------------------------------------
+// updateConfiguration
+//---------------------------------------------------------
+
+void Arranger::updateConfiguration()
+ {
+ if (config.canvasUseBgPixmap) {
+ canvas->setCanvasBackground(QPixmap(config.canvasBgPixmap));
+ }
+ else
+ canvas->setCanvasBackground(config.canvasBgColor);
+//TD canvas->setShowGrid(config.canvasShowGrid);
+//TD update();
+ }
+
+//---------------------------------------------------------
+// readStatus
+//---------------------------------------------------------
+
+void Arranger::readStatus(QDomNode node)
+ {
+ TrackList* tl = song->tracks();
+ iTrack it = tl->begin();
+
+ QPoint wpos;
+ double xmag = 0.05;
+ double ymag = 1.0;
+
+ for (; !node.isNull(); node = node.nextSibling()) {
+ QDomElement e = node.toElement();
+ QString tag(e.tagName());
+ QString s = e.text();
+ int i = s.toInt();
+ if (tag == "info")
+ trackInfoVisible = i;
+ else if (tag == "strip")
+ mixerStripVisible = i;
+ else if (tag == "TrackConf") {
+ }
+ else if (tag == "hmag")
+ xmag = s.toDouble();
+ else if (tag == "vmag")
+ ymag = s.toDouble();
+ else if (tag == "hpos")
+ wpos.setX(i);
+ else if (tag == "vpos")
+ wpos.setY(i);
+ else if (tag == "raster") {
+ muse->initRaster(i);
+ canvas->setRaster(i);
+ }
+ else if (tag == "splitter") {
+ split->readStatus(node);
+ QList<int> sizes = split->sizes();
+ split->setSizes(sizes);
+ }
+ else
+ printf("Arranger: unknown tag %s\n", tag.toLatin1().data());
+ }
+ canvas->setMag(xmag, ymag);
+ canvas->setWPos(wpos);
+ }
+
+//---------------------------------------------------------
+// writeStatus
+//---------------------------------------------------------
+
+void Arranger::writeStatus(Xml& xml)
+ {
+ xml.stag("arranger");
+
+ for (int i = 0; i < Track::TRACK_TYPES; ++i) {
+ TrGroupList* gl = &glist[i];
+ xml.stag(QString("TrackConf type=\"%1\"").arg(i));
+ for (iTrGroup ig = gl->begin(); ig != gl->end(); ++ig) {
+ TrElementList& el = *ig;
+ xml.stag("group");
+ for (iTrElement ie = el.begin(); ie != el.end(); ++ie)
+ xml.tagE(QString("element id=\"%1\"").arg((*ie)->id));
+ xml.etag("group");
+ }
+ xml.etag("TrackConf");
+ }
+ xml.tag("info", trackInfoVisible);
+ xml.tag("strip", mixerStripVisible);
+ xml.tag("hmag", canvas->xmag());
+ xml.tag("vmag", canvas->ymag());
+ xml.tag("hpos", canvas->getWPos().x());
+ xml.tag("vpos", canvas->getWPos().y());
+ xml.tag("raster", muse->raster());
+ split->writeStatus("splitter", xml);
+ xml.etag("arranger");
+ }
+
+//---------------------------------------------------------
+// setGMute
+//---------------------------------------------------------
+
+void Arranger::setGMute()
+ {
+ TrackList* tl = song->tracks();
+ bool mute = false;
+ for (iTrack i = tl->begin(); i != tl->end(); ++i) {
+ if ((*i)->mute()) {
+ mute = true;
+ break;
+ }
+ }
+ gmute->setChecked(mute);
+ }
+
+//---------------------------------------------------------
+// setGSolo
+//---------------------------------------------------------
+
+void Arranger::setGSolo()
+ {
+ TrackList* tl = song->tracks();
+ bool solo = false;
+ for (iTrack i = tl->begin(); i != tl->end(); ++i) {
+ if ((*i)->solo()) {
+ solo = true;
+ break;
+ }
+ }
+ gsolo->setChecked(solo);
+ }
+
+//---------------------------------------------------------
+// setGar
+//---------------------------------------------------------
+
+void Arranger::setGar()
+ {
+ TrackList* tl = song->tracks();
+ bool ar = false;
+ for (iTrack i = tl->begin(); i != tl->end(); ++i) {
+ if ((*i)->autoRead()) {
+ ar = true;
+ break;
+ }
+ }
+ if (ar == false) {
+ MidiTrackList* cl = song->midis();
+ for (iMidiTrack i = cl->begin(); i != cl->end(); ++i) {
+ if ((*i)->autoRead()) {
+ ar = true;
+ break;
+ }
+ }
+ }
+ gar->setChecked(ar);
+ }
+
+//---------------------------------------------------------
+// setGaw
+//---------------------------------------------------------
+
+void Arranger::setGaw()
+ {
+ TrackList*tl = song->tracks();
+ bool aw = false;
+ for (iTrack i = tl->begin(); i != tl->end(); ++i) {
+ if ((*i)->autoWrite())
+ aw = true;
+ }
+ if (aw == false) {
+ MidiTrackList* cl = song->midis();
+ for (iMidiTrack i = cl->begin(); i != cl->end(); ++i) {
+ if ((*i)->autoWrite()) {
+ aw = true;
+ break;
+ }
+ }
+ }
+ gaw->setChecked(aw);
+ }
+
+//---------------------------------------------------------
+// offGMute
+//---------------------------------------------------------
+
+void Arranger::offGMute()
+ {
+ TrackList*tl = song->tracks();
+ for (iTrack i = tl->begin(); i != tl->end(); ++i)
+ song->setMute(*i,false);
+ gmute->setChecked(false);
+ }
+
+//---------------------------------------------------------
+// offGSolo
+//---------------------------------------------------------
+
+void Arranger::offGSolo()
+ {
+ TrackList*tl = song->tracks();
+ for (iTrack i = tl->begin(); i != tl->end(); ++i)
+ song->setSolo(*i, false);
+ gsolo->setChecked(false);
+ }
+
+//---------------------------------------------------------
+// offGar
+//---------------------------------------------------------
+
+void Arranger::offGar()
+ {
+ TrackList*tl = song->tracks();
+ for (iTrack i = tl->begin(); i != tl->end(); ++i)
+ song->setAutoRead(*i, false);
+ MidiTrackList* cl = song->midis();
+ for (iMidiTrack i = cl->begin(); i != cl->end(); ++i)
+ song->setAutoRead(*i, false);
+ gar->setChecked(false);
+ }
+
+//---------------------------------------------------------
+// offGaw
+//---------------------------------------------------------
+
+void Arranger::offGaw()
+ {
+ TrackList*tl = song->tracks();
+ for (iTrack i = tl->begin(); i != tl->end(); ++i)
+ song->setAutoWrite(*i, false);
+ MidiTrackList* cl = song->midis();
+ for (iMidiTrack i = cl->begin(); i != cl->end(); ++i)
+ song->setAutoWrite(*i, false);
+ gaw->setChecked(false);
+ }
+
+//---------------------------------------------------------
+// setTool
+//---------------------------------------------------------
+
+void Arranger::setTool(int t)
+ {
+ tool = Tool(t);
+ canvas->setTool(tool);
+ }
+
+//---------------------------------------------------------
+// setSelectedTrack
+//---------------------------------------------------------
+
+void Arranger::setSelectedTrack(Track* t)
+ {
+ _curTrack = t;
+ toggleTrackInfo(trackInfoVisible);
+ toggleMixerStrip(mixerStripVisible);
+ }
+
+//---------------------------------------------------------
+// moveTrack
+// move src before dst
+//---------------------------------------------------------
+
+void Arranger::moveTrack(Track* src, Track* dst)
+ {
+ audio->msgMoveTrack(src, dst);
+ tl->clear();
+ TrackList* stl = song->tracks();
+ for (iTrack i = stl->begin(); i != stl->end(); ++i) {
+ tl->addWidget((*i)->arrangerTrack.tw);
+ for (iArrangerTrack it = (*i)->subtracks.begin(); it != (*i)->subtracks.end(); ++it)
+ tl->addWidget((*it)->tw);
+ }
+ tl->setGeometry(((QWidget*)tl->parent())->geometry());
+ updateIndex();
+ }
+
+//---------------------------------------------------------
+//! \fn Arranger::keyPressEvent(QKeyEvent* e)
+//! \brief Called when a key is pressed
+//! @param e The key event
+//---------------------------------------------------------
+
+void Arranger::keyPressEvent(QKeyEvent* /*e*/)
+ {
+ printf("Arranger::keyPressEvent\n");
+#if 0 //TODOB
+ int key = e->key();
+ bool keypress_handled = false;
+
+ if (e->modifiers() & Qt::ShiftModifier)
+ key += Qt::SHIFT;
+ if (e->modifiers() & Qt::AltModifier)
+ key += Qt::ALT;
+ if (e->modifiers() & Qt::ControlModifier)
+ key += Qt::CTRL;
+
+ if (shortcutsKbdMovement.isValid()) {
+ if (key == shortcuts[SHRT_SEL_LEFT].key || key == shortcuts[SHRT_SEL_LEFT_ADD].key) {
+ keypress_handled = true;
+ bool add = (key == shortcuts[SHRT_SEL_LEFT_ADD].key);
+ PartList* parts = shortcutsKbdMovement.track()->parts();
+ Part* nextLeft = 0;
+
+ for (iPart i = parts->begin(); i != parts->end(); i++) {
+ Part* tmp = i->second;
+ if (!nextLeft) {
+ if (tmp->tick() < shortcutsKbdMovement.getLpos())
+ nextLeft = tmp;
+ }
+ else {
+ if (tmp->tick() > nextLeft->tick() && tmp->tick() < shortcutsKbdMovement.getLpos() )
+ nextLeft = tmp;
+ }
+ }
+ if (nextLeft) {
+ song->selectPart(nextLeft, add);
+ shortcutsKbdMovement.setPart(nextLeft);
+ shortcutsKbdMovement.setPos(nextLeft->tick(), nextLeft->tick() + nextLeft->lenTick());
+ }
+ }
+ else if (key == shortcuts[SHRT_SEL_RIGHT].key || key == shortcuts[SHRT_SEL_RIGHT_ADD].key) {
+ keypress_handled = true;
+ bool add = (key == shortcuts[SHRT_SEL_RIGHT_ADD].key);
+ PartList* parts = shortcutsKbdMovement.track()->parts();
+ Part* nextRight = 0;
+
+ for (iPart i = parts->begin(); i != parts->end(); i++) {
+ Part* tmp = i->second;
+ if (!nextRight) {
+ if (tmp->tick() > shortcutsKbdMovement.getLpos())
+ nextRight = tmp;
+ }
+ else {
+ if (tmp->tick() < nextRight->tick() && tmp->tick() > shortcutsKbdMovement.getLpos() )
+ nextRight = tmp;
+ }
+ }
+ if (nextRight) {
+ song->selectPart(nextRight, add);
+ shortcutsKbdMovement.setPart(nextRight);
+ shortcutsKbdMovement.setPos(nextRight->tick(), nextRight->tick() + nextRight->lenTick());
+ }
+ }
+
+ else if (key == shortcuts[SHRT_SEL_ABOVE].key) {
+ // TODO
+ }
+ else if (key == shortcuts[SHRT_SEL_BELOW].key) {
+ // TODO
+ }
+ } // -- end movement
+ else {
+ if (key == shortcuts[SHRT_TOOL_POINTER].key) {
+ emit toolChanged(PointerTool);
+ return;
+ }
+ else if (key == shortcuts[SHRT_TOOL_PENCIL].key) {
+ emit toolChanged(PencilTool);
+ return;
+ }
+ else if (key == shortcuts[SHRT_TOOL_RUBBER].key) {
+ emit toolChanged(RubberTool);
+ return;
+ }
+ else if (key == shortcuts[SHRT_TOOL_LINEDRAW].key) {
+ emit toolChanged(DrawTool);
+ return;
+ }
+ }
+ // If we haven't dealt with the keypress, pass it along
+ if (!keypress_handled) {
+ e->ignore();
+ }
+#endif
+// e->ignore();
+ }
+
+
+/*!
+ \fn Arranger::kbdMovementUpdate(Track* t, Part* p)
+ \brief Slot connected to canvaswidget, called when a part is selected
+ @param t Track the selected part belongs to (null if no part selected)
+ @param p The selected Part (null if no part selected)
+ */
+void Arranger::kbdMovementUpdate(Track*, Part*)
+ {
+ printf("kbdMovementUpdate\n");
+// if (t && p ) {
+// // If other track selected:
+// if (t != shortcutsKbdMovement.track()) {
+// TrackList* stl = song->tracks();
+// for (iTrack i = stl->begin(); i != stl->end(); ++i) {
+// if (*i == t) {
+// // Set focus and select current track
+// t->arrangerTrack.tw->setFocus();
+// song->selectTrack(t);
+// }
+// }
+// }
+// shortcutsKbdMovement.setTrack(t);
+// shortcutsKbdMovement.setPart(p);
+// shortcutsKbdMovement.setPos(p->tick(), p->tick() + p->lenTick());
+// }
+// else { // Deselected
+// shortcutsKbdMovement.reset();
+// }
+ }
+
+//---------------------------------------------------------
+// addMarker
+//---------------------------------------------------------
+
+void Arranger::addMarker(const AL::Pos& pos)
+ {
+ song->addMarker(QString(), pos);
+ canvas->widget()->update();
+ }
+
+//---------------------------------------------------------
+// removeMarker
+//---------------------------------------------------------
+
+void Arranger::removeMarker(const AL::Pos& pos)
+ {
+ AL::MarkerList* ml = song->marker();
+ for (AL::iMarker i = ml->begin(); i != ml->end(); ++i) {
+ AL::iMarker ni = i;
+ ++ni;
+ if (i->second <= pos && (ni == ml->end() || ni->second > pos)) {
+ song->removeMarker(&(i->second));
+ canvas->widget()->update();
+ return;
+ }
+ }
+ printf("marker not found\n");
+ }