summaryrefslogtreecommitdiff
path: root/muse_qt4_evolution/muse/midiedit/pianoroll.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'muse_qt4_evolution/muse/midiedit/pianoroll.cpp')
-rw-r--r--muse_qt4_evolution/muse/midiedit/pianoroll.cpp526
1 files changed, 526 insertions, 0 deletions
diff --git a/muse_qt4_evolution/muse/midiedit/pianoroll.cpp b/muse_qt4_evolution/muse/midiedit/pianoroll.cpp
new file mode 100644
index 00000000..c9be06e9
--- /dev/null
+++ b/muse_qt4_evolution/muse/midiedit/pianoroll.cpp
@@ -0,0 +1,526 @@
+//=============================================================================
+// 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 "pianoroll.h"
+#include "song.h"
+#include "icons.h"
+#include "cmd.h"
+#include "muse.h"
+#include "widgets/tools.h"
+#include "quantconfig.h"
+#include "shortcuts.h"
+#include "audio.h"
+#include "part.h"
+
+static int pianorollTools = PointerTool | PencilTool | RubberTool | DrawTool;
+int PianoRoll::initWidth = PianoRoll::INIT_WIDTH;
+int PianoRoll::initHeight = PianoRoll::INIT_HEIGHT;
+int PianoRoll::initRaster = PianoRoll::INIT_RASTER;
+int PianoRoll::initQuant = PianoRoll::INIT_QUANT;
+int PianoRoll::initColorMode = PianoRoll::INIT_COLOR_MODE;
+bool PianoRoll::initFollow = PianoRoll::INIT_FOLLOW;
+bool PianoRoll::initSpeaker = PianoRoll::INIT_SPEAKER;
+bool PianoRoll::initMidiin = PianoRoll::INIT_MIDIIN;
+double PianoRoll::initXmag = 0.08; // PianoRoll::INIT_XMAG; (compiler problem?)
+int PianoRoll::initApplyTo = PianoRoll::INIT_APPLY_TO;
+int PianoRoll::initQuantStrength = PianoRoll::INIT_QUANT_STRENGTH;
+int PianoRoll::initQuantLimit = PianoRoll::INIT_QUANT_LIMIT;
+bool PianoRoll::initQuantLen = PianoRoll::INIT_QUANT_LEN;
+
+//---------------------------------------------------------
+// PianoRoll
+//---------------------------------------------------------
+
+PianoRoll::PianoRoll(PartList* pl, bool init)
+ : MidiEditor(pl)
+ {
+ _applyTo = initApplyTo;
+ _colorMode = initColorMode;
+ _quantStrength = initQuantStrength;
+ _quantLimit = initQuantLimit;
+ _quantLen = initQuantLen;
+
+ deltaMode = false;
+ quantConfig = 0;
+
+ tcanvas = new PianoCanvas(this);
+ QMenuBar* mb = menuBar();
+
+ menu_ids[CMD_EVENT_COLOR] = getAction("change_event_color", this);
+ menu_ids[CMD_CONFIG_QUANT] = getAction("config_quant", this);
+
+ //---------Menu----------------------------------
+ menuEdit->addSeparator();
+
+ QAction* a = getAction("delete", this);
+ menuEdit->addAction(a);
+
+ menuEdit->addSeparator();
+
+ menuSelect = menuEdit->addMenu(QIcon(*selectIcon),tr("&Select"));
+
+ menuSelect->addAction(getAction("sel_all", this));
+ menuSelect->addAction(getAction("sel_none", this));
+ menuSelect->addAction(getAction("sel_inv", this));
+ menuSelect->addAction(getAction("sel_ins_loc", this));
+ menuSelect->addAction(getAction("sel_out_loc", this));
+
+ menuConfig = mb->addMenu(tr("&Config"));
+ eventColor = menuConfig->addMenu(tr("event color"));
+ menu_ids[CMD_EVENT_COLOR] = eventColor->menuAction();
+
+ colorModeAction[0] = eventColor->addAction(tr("blue"));
+ colorModeAction[0]->setData(0);
+ colorModeAction[0]->setCheckable(true);
+ colorModeAction[1] = eventColor->addAction(tr("pitch colors"));
+ colorModeAction[1]->setData(1);
+ colorModeAction[1]->setCheckable(true);
+ colorModeAction[2] = eventColor->addAction(tr("velocity colors"));
+ colorModeAction[2]->setData(2);
+ colorModeAction[2]->setCheckable(true);
+ connect(eventColor, SIGNAL(triggered(QAction*)), SLOT(setEventColorMode(QAction*)));
+
+ menuFunctions = mb->addMenu(tr("&Functions"));
+
+ menuFunctions->addAction(getAction("midi_over_quant", this));
+ menuFunctions->addAction(getAction("midi_quant_noteon", this));
+ menuFunctions->addAction(getAction("midi_quant_noteoff", this));
+ menuFunctions->addAction(getAction("midi_quant_iterative", this));
+
+ menuFunctions->addSeparator();
+
+ menu_ids[CMD_CONFIG_QUANT] = menuFunctions->addAction(tr("Config Quant..."));
+ connect(menu_ids[CMD_CONFIG_QUANT], SIGNAL(triggered()), this, SLOT(configQuant()));
+
+ menuFunctions->addSeparator();
+
+ menuFunctions->addAction(getAction("midi_mod_gate_time", this));
+ menuFunctions->addAction(getAction("midi_mod_velo", this));
+
+#if 0 // TODO
+ menuFunctions->addAction(getAction("midi_crescendo", this));
+ menuFunctions->addAction(getAction("midi_transpose", this));
+ menuFunctions->addAction(getAction("midi_thin_out", this));
+ menuFunctions->addAction(getAction("midi_erase_event", this));
+ menuFunctions->addAction(getAction("midi_note_shift", this));
+ menuFunctions->addAction(getAction("midi_move_clock", this));
+ menuFunctions->addAction(getAction("midi_copy_measure", this));
+ menuFunctions->addAction(getAction("midi_erase_measure", this));
+ menuFunctions->addAction(getAction("midi_delete_measure", this));
+ menuFunctions->addAction(getAction("midi_create_measure", this));
+#endif
+
+ connect(menuSelect, SIGNAL(triggered(QAction*)), SLOT(cmd(QAction*)));
+ connect(menuFunctions, SIGNAL(triggered(QAction*)), SLOT(cmd(QAction*)));
+
+ //---------ToolBar----------------------------------
+ tools = addToolBar(tr("Pianoroll Tools"));
+ tools->addAction(undoAction);
+ tools->addAction(redoAction);
+ tools->addSeparator();
+
+ tools->addAction(stepRecAction);
+ stepRecAction->setChecked(INIT_SREC);
+
+ tools->addAction(midiInAction);
+ midiInAction->setChecked(INIT_MIDIIN);
+
+ tools->addAction(speaker);
+ speaker->setChecked(INIT_SPEAKER);
+
+ tools->addAction(followSongAction);
+ followSongAction->setChecked(INIT_FOLLOW);
+ tcanvas->setFollow(INIT_FOLLOW);
+
+ tools2 = new EditToolBar(this, pianorollTools);
+ addToolBar(tools2);
+
+ QToolBar* panicToolbar = addToolBar(tr("Panic"));
+ panicToolbar->addAction(panicAction);
+
+ //-------------------------------------------------------------
+ // Transport Bar
+
+ QToolBar* transport = addToolBar(tr("Transport"));
+ muse->setupTransportToolbar(transport);
+
+ addToolBarBreak();
+ toolbar = new Toolbar1(initRaster, initQuant);
+ addToolBar(toolbar);
+
+ addToolBarBreak();
+ info = new NoteInfo(this);
+ addToolBar(info);
+
+ setCentralWidget(tcanvas);
+ tcanvas->setCornerWidget(new QSizeGrip(tcanvas));
+
+ connect(song, SIGNAL(posChanged(int,const AL::Pos&,bool)), canvas(), SLOT(setLocatorPos(int,const AL::Pos&,bool)));
+ connect(canvas(), SIGNAL(posChanged(int,const AL::Pos&)), SLOT(setPos(int,const AL::Pos&)));
+
+ connect(canvas(), SIGNAL(toolChanged(int)), tools2, SLOT(set(int)));
+ connect(tools2, SIGNAL(toolChanged(int)), canvas(), SLOT(setTool(int)));
+
+ connect(info, SIGNAL(valueChanged(NoteInfo::ValType, int)), SLOT(noteinfoChanged(NoteInfo::ValType, int)));
+
+ connect(canvas(), SIGNAL(selectionChanged(int, Event&, Part*)), this,
+ SLOT(setSelection(int, Event&, Part*)));
+
+ info->setEnabled(false);
+
+ setWindowTitle(canvas()->getCaption());
+ Pos p1(0, AL::TICKS), p2(0, AL::TICKS);
+ canvas()->range(p1, p2);
+ p2 += AL::sigmap.ticksMeasure(p2.tick()); // show one more measure
+ canvas()->setTimeRange(p1, p2);
+
+ // connect to toolbar
+ connect(canvas(), SIGNAL(pitchChanged(int)), toolbar, SLOT(setPitch(int)));
+ connect(canvas(), SIGNAL(yChanged(int)), toolbar, SLOT(setInt(int)));
+ connect(canvas(), SIGNAL(cursorPos(const AL::Pos&,bool)), toolbar, SLOT(setTime(const AL::Pos&,bool)));
+ connect(toolbar, SIGNAL(quantChanged(int)), SLOT(setQuant(int)));
+ connect(toolbar, SIGNAL(rasterChanged(int)),SLOT(setRaster(int)));
+ connect(toolbar, SIGNAL(toChanged(int)), SLOT(setApplyTo(int)));
+ connect(toolbar, SIGNAL(soloChanged(bool)), SLOT(soloChanged(bool)));
+
+ setEventColorMode(_colorMode);
+
+ clipboardChanged(); // enable/disable "Paste"
+ selectionChanged(); // enable/disable "Copy" & "Paste"
+
+ //
+ // install misc shortcuts
+ //
+ QShortcut* sc = new QShortcut(Qt::Key_Escape, this);
+ sc->setContext(Qt::WindowShortcut);
+ connect(sc, SIGNAL(activated()), SLOT(close()));
+
+ QSignalMapper* cmdMap = new QSignalMapper(this);
+ static const char* actions[] = {
+ "curpos_increase", "curpos_decrease",
+ "midi_insert_at_loc",
+ "midi_quant_1", "midi_quant_2", "midi_quant_3", "midi_quant_4",
+ "midi_quant_5", "midi_quant_6", "midi_quant_7",
+ "midi_quant_punct", "midi_quant_punct2", "midi_quant_triol",
+ };
+ for (unsigned i = 0; i < sizeof(actions)/sizeof(*actions); ++i) {
+ a = getAction(actions[i], this);
+ addAction(a);
+ cmdMap->setMapping(a, a);
+ connect(a, SIGNAL(triggered()), cmdMap, SLOT(map()));
+ }
+ connect(cmdMap, SIGNAL(mapped(QObject*)), SLOT(pianoCmd(QObject*)));
+
+ connect(song, SIGNAL(songChanged(int)), canvas(), SLOT(songChanged(int)));
+ connect(followSongAction, SIGNAL(toggled(bool)), canvas(), SLOT(setFollow(bool)));
+ canvas()->selectFirst();
+
+ Part* part = canvas()->part();
+ setRaster(part->raster() != -1 ? part->raster() : initRaster);
+ setQuant(part->quant() != -1 ? part->quant() : initQuant);
+ setXmag(part->xmag() != -1.0 ? part->xmag() : initXmag);
+
+ if (init)
+ initFromPart();
+ else {
+ resize(initWidth, initHeight);
+ }
+ }
+
+//---------------------------------------------------------
+// cmd
+// pulldown menu commands
+//---------------------------------------------------------
+
+void PianoRoll::cmd(QAction* a)
+ {
+ canvas()->cmd(a, _quantStrength, _quantLimit, _quantLen);
+ }
+
+//---------------------------------------------------------
+// setSelection
+// update Info Line
+//---------------------------------------------------------
+
+void PianoRoll::setSelection(int tick, Event& e, Part* p)
+ {
+ int selections = canvas()->selectionSize();
+
+ selEvent = e;
+ selPart = p;
+
+ if (selections > 1) {
+ info->setEnabled(true);
+ info->setDeltaMode(true);
+ if (!deltaMode) {
+ deltaMode = true;
+ info->setValues(0, 0, 0, 0, 0);
+ tickOffset = 0;
+ lenOffset = 0;
+ pitchOffset = 0;
+ veloOnOffset = 0;
+ veloOffOffset = 0;
+ }
+ }
+ else if (selections == 1) {
+ deltaMode = false;
+ info->setEnabled(true);
+ info->setDeltaMode(false);
+ info->setValues(tick,
+ selEvent.lenTick(),
+ selEvent.pitch(),
+ selEvent.velo(),
+ selEvent.veloOff());
+ }
+ else {
+ deltaMode = false;
+ info->setEnabled(false);
+ }
+ selectionChanged();
+ }
+
+//---------------------------------------------------------
+// edit currently selected Event
+//---------------------------------------------------------
+
+void PianoRoll::noteinfoChanged(NoteInfo::ValType type, int val)
+ {
+ int selections = canvas()->selectionSize();
+
+ if (selections == 0) {
+ printf("noteinfoChanged while nothing selected\n");
+ }
+ else if (selections == 1) {
+ Event event = selEvent.clone();
+ switch(type) {
+ case NoteInfo::VAL_TIME:
+ event.setTick(val - selPart->tick());
+ break;
+ case NoteInfo::VAL_LEN:
+ event.setLenTick(val);
+ break;
+ case NoteInfo::VAL_VELON:
+ event.setVelo(val);
+ break;
+ case NoteInfo::VAL_VELOFF:
+ event.setVeloOff(val);
+ break;
+ case NoteInfo::VAL_PITCH:
+ event.setPitch(val);
+ break;
+ }
+ audio->msgChangeEvent(selEvent, event, selPart);
+ }
+ else {
+ // multiple events are selected; treat noteinfo values
+ // as offsets to event values
+
+ int delta = 0;
+ switch (type) {
+ case NoteInfo::VAL_TIME:
+ delta = val - tickOffset;
+ tickOffset = val;
+ break;
+ case NoteInfo::VAL_LEN:
+ delta = val - lenOffset;
+ lenOffset = val;
+ break;
+ case NoteInfo::VAL_VELON:
+ delta = val - veloOnOffset;
+ veloOnOffset = val;
+ break;
+ case NoteInfo::VAL_VELOFF:
+ delta = val - veloOffOffset;
+ veloOffOffset = val;
+ break;
+ case NoteInfo::VAL_PITCH:
+ delta = val - pitchOffset;
+ pitchOffset = val;
+ break;
+ }
+ if (delta)
+ canvas()->modifySelected(type, delta);
+ }
+ }
+
+//---------------------------------------------------------
+// soloChanged
+// signal from solo button
+//---------------------------------------------------------
+
+void PianoRoll::soloChanged(bool flag)
+ {
+ song->setSolo(canvas()->track(), flag);
+ }
+
+//---------------------------------------------------------
+// pianoCmd
+//---------------------------------------------------------
+
+void PianoRoll::pianoCmd(QObject* object)
+ {
+ QAction* a = (QAction*)object;
+ QString cmd(a->data().toString());
+
+ static int rasterTable[] = {
+ //-9----8- 7 6 5 4 3(1/4) 2 1
+ 4, 8, 16, 32, 64, 128, 256, 512, 1024, // triple
+ 6, 12, 24, 48, 96, 192, 384, 768, 1536,
+ 9, 18, 36, 72, 144, 288, 576, 1152, 2304 // dot
+ };
+
+ int index;
+ int n = sizeof(rasterTable)/sizeof(*rasterTable);
+ for (index = 0; index < n; ++index)
+ if (rasterTable[index] == raster())
+ break;
+ if (index == n) {
+ index = 0;
+ // raster 1 is not in table
+ }
+ int off = (index / 9) * 9;
+ index = index % 9;
+
+ int val = 0;
+
+ PianoCanvas* pc = canvas();
+
+ if (cmd == "curpos_increase")
+ canvas()->pianoCmd(MCMD_LEFT);
+ else if (cmd == "curpos_decrease")
+ canvas()->pianoCmd(MCMD_RIGHT);
+ else if (cmd == "midi_insert_at_loc") {
+ pc->pianoCmd(MCMD_INSERT);
+ return;
+ }
+ else if (cmd == "midi_quant_1")
+ val = rasterTable[8 + off];
+ else if (cmd == "midi_quant_2")
+ val = rasterTable[7 + off];
+ else if (cmd == "midi_quant_3")
+ val = rasterTable[6 + off];
+ else if (cmd == "midi_quant_4")
+ val = rasterTable[5 + off];
+ else if (cmd == "midi_quant_5")
+ val = rasterTable[4 + off];
+ else if (cmd == "midi_quant_6")
+ val = rasterTable[3 + off];
+ else if (cmd == "midi_quant_7")
+ val = rasterTable[2 + off];
+ else if (cmd == "midi_quant_triol")
+ val = rasterTable[index + ((off == 0) ? 9 : 0)];
+ else if (cmd == "change_event_color") {
+ _colorMode = (_colorMode + 1) % 3;
+ setEventColorMode(_colorMode);
+ return;
+ }
+ else if (cmd == "midi_quant_punct")
+ val = rasterTable[index + ((off == 18) ? 9 : 18)];
+ else if (cmd == "midi_quant_punct2") {
+ if ((off == 18) && (index > 2)) {
+ val = rasterTable[index + 9 - 1];
+ }
+ else if ((off == 9) && (index < 8)) {
+ val = rasterTable[index + 18 + 1];
+ }
+ else
+ return;
+ }
+ else
+ printf("unknown cmd <%s>\n", cmd.toLatin1().data());
+ setQuant(val);
+ setRaster(val);
+ toolbar->setQuant(quant());
+ toolbar->setRaster(raster());
+ }
+
+//---------------------------------------------------------
+// configQuant
+//---------------------------------------------------------
+
+void PianoRoll::configQuant()
+ {
+ QuantConfig quantConfig(_quantStrength, _quantLimit, _quantLen, this);
+ if (!quantConfig.exec())
+ return;
+ _quantStrength = quantConfig.quantStrength();
+ _quantLimit = quantConfig.quantLimit();
+ _quantLen = quantConfig.doQuantLen();
+ }
+
+//---------------------------------------------------------
+// setEventColorMode
+//---------------------------------------------------------
+
+void PianoRoll::setEventColorMode(QAction* a)
+ {
+ setEventColorMode(a->data().toInt());
+ }
+
+void PianoRoll::setEventColorMode(int mode)
+ {
+ _colorMode = mode;
+ for (int i = 0; i < 3; ++i)
+ colorModeAction[i]->setChecked(mode == i);
+ canvas()->setColorMode(mode);
+ }
+
+//---------------------------------------------------------
+// readConfiguration
+// read static init values
+//---------------------------------------------------------
+
+void PianoRoll::readConfiguration(QDomNode node)
+ {
+ for (node = node.firstChild(); !node.isNull(); node = node.nextSibling()) {
+ QDomElement e = node.toElement();
+ QString tag(e.tagName());
+ int i = e.text().toInt();
+ if (tag == "width")
+ PianoRoll::initWidth = i;
+ else if (tag == "height")
+ PianoRoll::initHeight = i;
+ else if (tag == "raster")
+ PianoRoll::initRaster = i;
+ else if (tag == "quant")
+ PianoRoll::initQuant = i;
+ else
+ printf("MusE:PianoRoll: unknown tag %s\n", tag.toLatin1().data());
+ }
+ }
+
+//---------------------------------------------------------
+// writeConfiguration
+// write static init values
+//---------------------------------------------------------
+
+void PianoRoll::writeConfiguration(Xml& xml)
+ {
+ xml.stag("PianoRoll");
+ if (PianoRoll::initWidth != PianoRoll::INIT_WIDTH)
+ xml.tag("width", PianoRoll::initWidth);
+ if (PianoRoll::initHeight != PianoRoll::INIT_HEIGHT)
+ xml.tag("height", PianoRoll::initHeight);
+ if (PianoRoll::initRaster != PianoRoll::INIT_RASTER)
+ xml.tag("raster", PianoRoll::initRaster);
+ if (PianoRoll::initQuant != PianoRoll::INIT_QUANT)
+ xml.tag("quant", PianoRoll::initQuant);
+ xml.etag("PianoRoll");
+ }