diff options
Diffstat (limited to 'attic/muse2-oom/muse2/muse/midiedit/drumedit.cpp')
-rw-r--r-- | attic/muse2-oom/muse2/muse/midiedit/drumedit.cpp | 1225 |
1 files changed, 1225 insertions, 0 deletions
diff --git a/attic/muse2-oom/muse2/muse/midiedit/drumedit.cpp b/attic/muse2-oom/muse2/muse/midiedit/drumedit.cpp new file mode 100644 index 00000000..7bdac223 --- /dev/null +++ b/attic/muse2-oom/muse2/muse/midiedit/drumedit.cpp @@ -0,0 +1,1225 @@ +//========================================================= +// MusE +// Linux Music Editor +// $Id: drumedit.cpp,v 1.22.2.21 2009/11/16 11:29:33 lunar_shuttle Exp $ +// (C) Copyright 1999 Werner Schweer (ws@seh.de) +//========================================================= + +#include <QAction> +#include <QClipboard> +#include <QCloseEvent> +#include <QGridLayout> +#include <QKeyEvent> +#include <QList> +#include <QMenu> +#include <QMenuBar> +#include <QMessageBox> +#include <QPushButton> +#include <QResizeEvent> +#include <QSignalMapper> +#include <QSizeGrip> +#include <QToolButton> +#include <QWhatsThis> + +#include "drumedit.h" +#include "mtscale.h" +#include "scrollscale.h" +#include "xml.h" +#include "dlist.h" +#include "dcanvas.h" +#include "ttoolbar.h" +#include "tb1.h" +#include "splitter.h" +#include "utils.h" +#include "../ctrl/ctrledit.h" +#include "vscale.h" +#include "swidget.h" +#include "globals.h" +#include "icons.h" +#include "filedialog.h" +#include "drummap.h" +#include "audio.h" +#include "gconfig.h" + +/* +static const char* map_file_pattern[] = { + "Presets (*.map *.map.gz *.map.bz2)", + "All Files (*)", + 0 + }; +static const char* map_file_save_pattern[] = { + "Presets (*.map)", + "gzip compressed presets (*.map.gz)", + "bzip2 compressed presets (*.map.bz2)", + "All Files (*)", + 0 + }; +*/ + +int DrumEdit::_quantInit = 96; +int DrumEdit::_rasterInit = 96; +int DrumEdit::_widthInit = 600; +int DrumEdit::_heightInit = 400; +int DrumEdit::_dlistWidthInit = 50; +int DrumEdit::_dcanvasWidthInit = 300; +int DrumEdit::_toInit = 0; + +static const int xscale = -10; +static const int yscale = 1; +static const int drumeditTools = PointerTool | PencilTool | RubberTool; + +enum DrumColumn { + COL_MUTE = 0, + COL_NAME, + COL_VOLUME, + COL_QUANT, + COL_INPUTTRIGGER, + COL_NOTELENGTH, + COL_NOTE, + COL_OUTCHANNEL, + COL_OUTPORT, + COL_LEVEL1, + COL_LEVEL2, + COL_LEVEL3, + COL_LEVEL4, + COL_NONE = -1 +}; + +//--------------------------------------------------------- +// setHeaderWhatsThis +//--------------------------------------------------------- + +void DrumEdit::setHeaderWhatsThis() + { + header->setWhatsThis(COL_MUTE, tr("mute instrument")); + header->setWhatsThis(COL_NAME, tr("sound name")); + header->setWhatsThis(COL_VOLUME, tr("volume percent")); + header->setWhatsThis(COL_QUANT, tr("quantisation")); + header->setWhatsThis(COL_INPUTTRIGGER, tr("this input note triggers the sound")); + header->setWhatsThis(COL_NOTELENGTH, tr("note length")); + header->setWhatsThis(COL_NOTE, tr("this is the note which is played")); + header->setWhatsThis(COL_OUTCHANNEL, tr("output channel (hold ctl to affect all rows)")); + header->setWhatsThis(COL_OUTPORT, tr("output port")); + header->setWhatsThis(COL_LEVEL1, tr("shift + control key: draw velocity level 1")); + header->setWhatsThis(COL_LEVEL2, tr("control key: draw velocity level 2")); + header->setWhatsThis(COL_LEVEL3, tr("shift key: draw velocity level 3")); + header->setWhatsThis(COL_LEVEL4, tr("draw velocity level 4")); + } + +//--------------------------------------------------------- +// setHeaderToolTips +//--------------------------------------------------------- + +void DrumEdit::setHeaderToolTips() + { + header->setToolTip(COL_MUTE, tr("mute instrument")); + header->setToolTip(COL_NAME, tr("sound name")); + header->setToolTip(COL_VOLUME, tr("volume percent")); + header->setToolTip(COL_QUANT, tr("quantisation")); + header->setToolTip(COL_INPUTTRIGGER, tr("this input note triggers the sound")); + header->setToolTip(COL_NOTELENGTH, tr("note length")); + header->setToolTip(COL_NOTE, tr("this is the note which is played")); + header->setToolTip(COL_OUTCHANNEL, tr("output channel (ctl: affect all rows)")); + header->setToolTip(COL_OUTPORT, tr("output port")); + header->setToolTip(COL_LEVEL1, tr("shift + control key: draw velocity level 1")); + header->setToolTip(COL_LEVEL2, tr("control key: draw velocity level 2")); + header->setToolTip(COL_LEVEL3, tr("shift key: draw velocity level 3")); + header->setToolTip(COL_LEVEL4, tr("draw velocity level 4")); + } + +//--------------------------------------------------------- +// closeEvent +//--------------------------------------------------------- + +void DrumEdit::closeEvent(QCloseEvent* e) + { + //Store values of the horizontal splitter + QList<int> sizes = split2->sizes(); + QList<int>::iterator it = sizes.begin(); + _dlistWidthInit = *it; //There are only 2 values stored in the sizelist, size of dlist widget and dcanvas widget + it++; + _dcanvasWidthInit = *it; + emit deleted((unsigned long)this); + e->accept(); + } + +//--------------------------------------------------------- +// DrumEdit +//--------------------------------------------------------- + +DrumEdit::DrumEdit(PartList* pl, QWidget* parent, const char* name, unsigned initPos) + : MidiEditor(_quantInit, _rasterInit, pl, parent, name) + { + split1w1 = 0; + resize(_widthInit, _heightInit); + selPart = 0; + _to = _toInit; + QSignalMapper *signalMapper = new QSignalMapper(this); + + //---------Pulldown Menu---------------------------- + menuFile = menuBar()->addMenu(tr("&File")); + + loadAction = menuFile->addAction(QIcon(*openIcon), tr("Load Map")); + saveAction = menuFile->addAction(QIcon(*saveIcon), tr("Save Map")); + resetAction = menuFile->addAction(tr("Reset GM Map")); + + connect(loadAction, SIGNAL(triggered()), signalMapper, SLOT(map())); + connect(saveAction, SIGNAL(triggered()), signalMapper, SLOT(map())); + connect(resetAction, SIGNAL(triggered()), signalMapper, SLOT(map())); + + signalMapper->setMapping(loadAction, DrumCanvas::CMD_LOAD); + signalMapper->setMapping(saveAction, DrumCanvas::CMD_SAVE); + signalMapper->setMapping(resetAction, DrumCanvas::CMD_RESET); + + menuEdit = menuBar()->addMenu(tr("&Edit")); + menuEdit->addActions(undoRedo->actions()); + + menuEdit->addSeparator(); + cutAction = menuEdit->addAction(QIcon(*editcutIconSet), tr("Cut")); + copyAction = menuEdit->addAction(QIcon(*editcopyIconSet), tr("Copy")); + pasteAction = menuEdit->addAction(QIcon(*editpasteIconSet), tr("Paste")); + menuEdit->addSeparator(); + deleteAction = menuEdit->addAction(tr("Delete Events")); + + connect(cutAction, SIGNAL(triggered()), signalMapper, SLOT(map())); + connect(copyAction, SIGNAL(triggered()), signalMapper, SLOT(map())); + connect(pasteAction, SIGNAL(triggered()), signalMapper, SLOT(map())); + connect(deleteAction, SIGNAL(triggered()), signalMapper, SLOT(map())); + + signalMapper->setMapping(cutAction, DrumCanvas::CMD_CUT); + signalMapper->setMapping(copyAction, DrumCanvas::CMD_COPY); + signalMapper->setMapping(pasteAction, DrumCanvas::CMD_PASTE); + signalMapper->setMapping(deleteAction, DrumCanvas::CMD_DEL); + + menuSelect = menuEdit->addMenu(QIcon(*selectIcon), tr("&Select")); + + sallAction = menuSelect->addAction(QIcon(*select_allIcon), tr("Select All")); + snoneAction = menuSelect->addAction(QIcon(*select_deselect_allIcon), tr("Select None")); + invAction = menuSelect->addAction(QIcon(*select_invert_selectionIcon), tr("Invert")); + menuSelect->addSeparator(); + inAction = menuSelect->addAction(QIcon(*select_inside_loopIcon), tr("Inside Loop")); + outAction = menuSelect->addAction(QIcon(*select_outside_loopIcon), tr("Outside Loop")); + + menuSelect->addSeparator(); + + prevAction = menuSelect->addAction(QIcon(*select_all_parts_on_trackIcon), tr("Previous Part")); + nextAction = menuSelect->addAction(QIcon(*select_all_parts_on_trackIcon), tr("Next Part")); + + connect(sallAction, SIGNAL(triggered()), signalMapper, SLOT(map())); + connect(snoneAction, SIGNAL(triggered()), signalMapper, SLOT(map())); + connect(invAction, SIGNAL(triggered()), signalMapper, SLOT(map())); + connect(inAction, SIGNAL(triggered()), signalMapper, SLOT(map())); + connect(outAction, SIGNAL(triggered()), signalMapper, SLOT(map())); + connect(prevAction, SIGNAL(triggered()), signalMapper, SLOT(map())); + connect(nextAction, SIGNAL(triggered()), signalMapper, SLOT(map())); + + signalMapper->setMapping(sallAction, DrumCanvas::CMD_SELECT_ALL); + signalMapper->setMapping(snoneAction, DrumCanvas::CMD_SELECT_NONE); + signalMapper->setMapping(invAction, DrumCanvas::CMD_SELECT_INVERT); + signalMapper->setMapping(inAction, DrumCanvas::CMD_SELECT_ILOOP); + signalMapper->setMapping(outAction, DrumCanvas::CMD_SELECT_OLOOP); + signalMapper->setMapping(prevAction, DrumCanvas::CMD_SELECT_PREV_PART); + signalMapper->setMapping(nextAction, DrumCanvas::CMD_SELECT_NEXT_PART); + + // Functions + menuFunctions = menuBar()->addMenu(tr("&Functions")); + + menuFunctions->setTearOffEnabled(true); + + fixedAction = menuFunctions->addAction(tr("Set Fixed Length")); + veloAction = menuFunctions->addAction(tr("Modify Velocity")); + + connect(fixedAction, SIGNAL(triggered()), signalMapper, SLOT(map())); + connect(veloAction, SIGNAL(triggered()), signalMapper, SLOT(map())); + + signalMapper->setMapping(fixedAction, DrumCanvas::CMD_FIXED_LEN); + signalMapper->setMapping(veloAction, DrumCanvas::CMD_MODIFY_VELOCITY); + + QMenu* menuScriptPlugins = menuBar()->addMenu(tr("&Plugins")); + song->populateScriptMenu(menuScriptPlugins, this); + + connect(signalMapper, SIGNAL(mapped(int)), SLOT(cmd(int))); + + //--------------------------------------------------- + // Toolbars + //--------------------------------------------------- + + tools = addToolBar(tr("Drum tools")); + + QToolButton *ldm = new QToolButton(); + ldm->setToolTip(tr("Load Drummap")); + ldm->setIcon(*openIcon); + connect(ldm, SIGNAL(clicked()), SLOT(load())); + tools->addWidget(ldm); + + QToolButton *sdm = new QToolButton(); + sdm->setToolTip(tr("Store Drummap")); + sdm->setIcon(*saveIcon); + connect(sdm, SIGNAL(clicked()), SLOT(save())); + tools->addWidget(sdm); + + tools->addAction(QWhatsThis::createAction()); + + tools->addSeparator(); + tools->addActions(undoRedo->actions()); + tools->addSeparator(); + + srec = new QToolButton(); + srec->setToolTip(tr("Step Record")); + srec->setIcon(*steprecIcon); + srec->setCheckable(true); + tools->addWidget(srec); + + midiin = new QToolButton(); + midiin->setToolTip(tr("Midi Input")); + midiin->setIcon(*midiinIcon); + midiin->setCheckable(true); + tools->addWidget(midiin); + + tools2 = new EditToolBar(this, drumeditTools); + addToolBar(tools2); + + QToolBar* panicToolbar = addToolBar(tr("panic")); + panicToolbar->addAction(panicAction); + + QToolBar* transport = addToolBar(tr("transport")); + transport->addActions(transportAction->actions()); + + addToolBarBreak(); + // don't show pitch value in toolbar + toolbar = new Toolbar1(this, _rasterInit, _quantInit, false); + addToolBar(toolbar); + + addToolBarBreak(); + info = new NoteInfo(this); + addToolBar(info); + + //--------------------------------------------------- + // split + //--------------------------------------------------- + + split1 = new Splitter(Qt::Vertical, mainw, "split1"); + QPushButton* ctrl = new QPushButton(tr("ctrl"), mainw); + ctrl->setObjectName("Ctrl"); + ctrl->setFont(config.fonts[3]); + hscroll = new ScrollScale(-25, -2, xscale, 20000, Qt::Horizontal, mainw); + ctrl->setFixedSize(40, hscroll->sizeHint().height()); + ctrl->setToolTip(tr("Add Controller View")); + + QSizeGrip* corner = new QSizeGrip(mainw); + corner->setFixedHeight(hscroll->sizeHint().height()); + + mainGrid->setRowStretch(0, 100); + mainGrid->setColumnStretch(1, 100); + + mainGrid->addWidget(split1, 0, 0, 1, 3); + mainGrid->addWidget(ctrl, 1, 0); + mainGrid->addWidget(hscroll, 1, 1); + mainGrid->addWidget(corner, 1, 2, Qt::AlignBottom|Qt::AlignRight); +// mainGrid->addRowSpacing(1, hscroll->sizeHint().height()); +// mainGrid->addItem(new QSpacerItem(0, hscroll->sizeHint().height()), 1, 0); + + split2 = new Splitter(Qt::Horizontal, split1, "split2"); + split1w1 = new QWidget(split2); + QWidget* split1w2 = new QWidget(split2); + QGridLayout* gridS1 = new QGridLayout(split1w1); + QGridLayout* gridS2 = new QGridLayout(split1w2); + gridS1->setContentsMargins(0, 0, 0, 0); + gridS1->setSpacing(0); + gridS2->setContentsMargins(0, 0, 0, 0); + gridS2->setSpacing(0); + time = new MTScale(&_raster, split1w2, xscale); + canvas = new DrumCanvas(this, split1w2, xscale, yscale); + vscroll = new ScrollScale(-4, 1, yscale, DRUM_MAPSIZE*TH, Qt::Vertical, split1w2); + int offset = -(config.division/4); + canvas->setOrigin(offset, 0); + canvas->setCanvasTools(drumeditTools); + canvas->setFocus(); + connect(canvas, SIGNAL(toolChanged(int)), tools2, SLOT(set(int))); + time->setOrigin(offset, 0); + + QList<int> mops; + mops.append(_dlistWidthInit); + mops.append(_dcanvasWidthInit); + split2->setSizes(mops); + // By T356. Not much choice but to disable this for now, to stop runaway resize bug. + // Can't seem to get the splitter to readjust when manually setting sizes. + //split2->setResizeMode(split1w1, QSplitter::KeepSize); + + gridS2->setRowStretch(1, 100); + gridS2->setColumnStretch(0, 100); + + gridS2->addWidget(time, 0, 0, 1, 2); + gridS2->addWidget(hLine(split1w2), 1, 0, 1, 2); + gridS2->addWidget(canvas, 2, 0); + + gridS2->addWidget(vscroll, 2, 1); + // + // Reihenfolge in dlist.c festgeschrieben ("Dcols") + // + header = new Header(split1w1, "header"); + header->setFixedHeight(31); + header->setColumnLabel(tr("M"), COL_MUTE, 20); + header->setColumnLabel(tr("Sound"), COL_NAME, 120); + header->setColumnLabel(tr("Vol"), COL_VOLUME); + header->setColumnLabel(tr("QNT"), COL_QUANT, 30); + header->setColumnLabel(tr("E-Note"), COL_INPUTTRIGGER, 50); + header->setColumnLabel(tr("Len"), COL_NOTELENGTH); + header->setColumnLabel(tr("A-Note"), COL_NOTE, 50); + header->setColumnLabel(tr("Ch"), COL_OUTCHANNEL); + header->setColumnLabel(tr("Port"), COL_OUTPORT, 70); + header->setColumnLabel(tr("LV1"), COL_LEVEL1); + header->setColumnLabel(tr("LV2"), COL_LEVEL2); + header->setColumnLabel(tr("LV3"), COL_LEVEL3); + header->setColumnLabel(tr("LV4"), COL_LEVEL4); + + setHeaderToolTips(); + setHeaderWhatsThis(); + + dlist = new DList(header, split1w1, yscale); + // p3.3.44 + setCurDrumInstrument(dlist->getSelectedInstrument()); + + connect(dlist, SIGNAL(keyPressed(int, bool)), canvas, SLOT(keyPressed(int, bool))); + connect(dlist, SIGNAL(keyReleased(int, bool)), canvas, SLOT(keyReleased(int, bool))); + connect(dlist, SIGNAL(mapChanged(int, int)), canvas, SLOT(mapChanged(int, int))); + + gridS1->setRowStretch(1, 100); + gridS1->setColumnStretch(0, 100); + gridS1->addWidget(header, 0, 0); + gridS1->addWidget(dlist, 1, 0); + + connect(canvas, SIGNAL(newWidth(int)), SLOT(newCanvasWidth(int))); + connect(canvas, SIGNAL(verticalScroll(unsigned)), vscroll, SLOT(setPos(unsigned))); + connect(canvas, SIGNAL(horizontalScroll(unsigned)),hscroll, SLOT(setPos(unsigned))); + connect(canvas, SIGNAL(horizontalScrollNoLimit(unsigned)),hscroll, SLOT(setPosNoLimit(unsigned))); + connect(song, SIGNAL(songChanged(int)), SLOT(songChanged1(int))); + connect(song, SIGNAL(songChanged(int)), dlist, SLOT(songChanged(int))); + connect(vscroll, SIGNAL(scrollChanged(int)), canvas, SLOT(setYPos(int))); + connect(vscroll, SIGNAL(scaleChanged(int)), canvas, SLOT(setYMag(int))); + connect(vscroll, SIGNAL(scaleChanged(int)), dlist, SLOT(setYMag(int))); + connect(hscroll, SIGNAL(scrollChanged(int)), canvas, SLOT(setXPos(int))); + connect(hscroll, SIGNAL(scaleChanged(int)), canvas, SLOT(setXMag(int))); + connect(srec, SIGNAL(toggled(bool)), canvas, SLOT(setSteprec(bool))); + connect(midiin, SIGNAL(toggled(bool)), canvas, SLOT(setMidiin(bool))); + + connect(vscroll, SIGNAL(scrollChanged(int)), dlist, SLOT(setYPos(int))); + connect(hscroll, SIGNAL(scrollChanged(int)), time, SLOT(setXPos(int))); + connect(hscroll, SIGNAL(scaleChanged(int)), time, SLOT(setXMag(int))); + + connect(tools2, SIGNAL(toolChanged(int)), canvas, SLOT(setTool(int))); + + connect(canvas, SIGNAL(selectionChanged(int, Event&, Part*)), this, + SLOT(setSelection(int, Event&, Part*))); + connect(canvas, SIGNAL(followEvent(int)), SLOT(follow(int))); + + connect(hscroll, SIGNAL(scaleChanged(int)), SLOT(updateHScrollRange())); + setWindowTitle(canvas->getCaption()); + + updateHScrollRange(); + + // connect toolbar + connect(canvas, SIGNAL(timeChanged(unsigned)), SLOT(setTime(unsigned))); + connect(time, SIGNAL(timeChanged(unsigned)), SLOT(setTime(unsigned))); + connect(toolbar, SIGNAL(quantChanged(int)), SLOT(setQuant(int))); + connect(toolbar, SIGNAL(rasterChanged(int)), SLOT(setRaster(int))); + connect(toolbar, SIGNAL(soloChanged(bool)), SLOT(soloChanged(bool))); + connect(info, SIGNAL(valueChanged(NoteInfo::ValType, int)), SLOT(noteinfoChanged(NoteInfo::ValType, int))); + + connect(ctrl, SIGNAL(clicked()), SLOT(addCtrl())); + + QClipboard* cb = QApplication::clipboard(); + connect(cb, SIGNAL(dataChanged()), SLOT(clipboardChanged())); + + clipboardChanged(); // enable/disable "Paste" + selectionChanged(); // enable/disable "Copy" & "Paste" + initShortcuts(); + + const Pos cpos=song->cPos(); + canvas->setPos(0, cpos.tick(), true); + canvas->selectAtTick(cpos.tick()); + //canvas->selectFirst(); + + if(canvas->track()) + toolbar->setSolo(canvas->track()->solo()); + + unsigned pos; + if(initPos >= MAXINT) + pos = song->cpos(); + else + pos = initPos; + if(pos > MAXINT) + pos = MAXINT; + hscroll->setOffset((int)pos); + } + +//--------------------------------------------------------- +// songChanged1 +//--------------------------------------------------------- + +void DrumEdit::songChanged1(int bits) + { + if (bits & SC_SOLO) + { + toolbar->setSolo(canvas->track()->solo()); + return; + } + songChanged(bits); + + } + +//--------------------------------------------------------- +// updateHScrollRange +//--------------------------------------------------------- + +void DrumEdit::updateHScrollRange() +{ + int s, e; + canvas->range(&s, &e); + // Show one more measure. + e += AL::sigmap.ticksMeasure(e); + // Show another quarter measure due to imprecise drawing at canvas end point. + e += AL::sigmap.ticksMeasure(e) / 4; + // Compensate for drum list, splitter handle, and vscroll widths. + e += canvas->rmapxDev(dlist->width() + split2->handleWidth() - vscroll->width()); + int s1, e1; + hscroll->range(&s1, &e1); + if(s != s1 || e != e1) + hscroll->setRange(s, e); +} + +//--------------------------------------------------------- +// follow +//--------------------------------------------------------- + +void DrumEdit::follow(int pos) + { + int s, e; + canvas->range(&s, &e); + + if (pos < e && pos >= s) + hscroll->setOffset(pos); + if (pos < s) + hscroll->setOffset(s); + } + +//--------------------------------------------------------- +// setTime +//--------------------------------------------------------- + +void DrumEdit::setTime(unsigned tick) + { + toolbar->setTime(tick); + time->setPos(3, tick, false); + } + +//--------------------------------------------------------- +// ~DrumEdit +//--------------------------------------------------------- + +DrumEdit::~DrumEdit() + { + //undoRedo->removeFrom(tools); // p4.0.6 Removed + } + +//--------------------------------------------------------- +// setSelection +// update Info Line +//--------------------------------------------------------- + +void DrumEdit::setSelection(int tick, Event& e, Part* p) + { + selEvent = e; + selPart = (MidiPart*)p; + selTick = tick; + info->setEnabled(!e.empty()); + if (!e.empty()) { + info->setValues(tick, + selEvent.lenTick(), + selEvent.pitch(), + selEvent.velo(), + selEvent.veloOff()); + } + selectionChanged(); + } + +//--------------------------------------------------------- +// soloChanged +//--------------------------------------------------------- + +void DrumEdit::soloChanged(bool flag) + { + audio->msgSetSolo(canvas->track(), flag); + song->update(SC_SOLO); + } + +//--------------------------------------------------------- +// setRaster +//--------------------------------------------------------- + +void DrumEdit::setRaster(int val) + { + _rasterInit = val; + MidiEditor::setRaster(val); + canvas->redrawGrid(); + } + +//--------------------------------------------------------- +// setQuant +//--------------------------------------------------------- + +void DrumEdit::setQuant(int val) + { + _quantInit = val; + MidiEditor::setQuant(val); + } + +//--------------------------------------------------------- +// edit currently selected Event +//--------------------------------------------------------- + +void DrumEdit::noteinfoChanged(NoteInfo::ValType type, int val) + { + if (selEvent.empty()) { + printf("noteinfoChanged while note is zero %d\n", type); + return; + } + 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; + } + // Indicate do undo, and do not do port controller values and clone parts. + //audio->msgChangeEvent(selEvent, event, selPart); + audio->msgChangeEvent(selEvent, event, selPart, true, false, false); + } + +//--------------------------------------------------------- +// writeStatus +//--------------------------------------------------------- + +void DrumEdit::writeStatus(int level, Xml& xml) const + { + writePartList(level, xml); + xml.tag(level++, "drumedit"); + MidiEditor::writeStatus(level, xml); + + for (std::list<CtrlEdit*>::const_iterator i = ctrlEditList.begin(); + i != ctrlEditList.end(); ++i) { + (*i)->writeStatus(level, xml); + } + + split1->writeStatus(level, xml); + split2->writeStatus(level, xml); + + header->writeStatus(level, xml); + xml.intTag(level, "steprec", canvas->steprec()); + xml.intTag(level, "midiin", canvas->midiin()); + xml.intTag(level, "xpos", hscroll->pos()); + xml.intTag(level, "xmag", hscroll->mag()); + xml.intTag(level, "ypos", vscroll->pos()); + xml.intTag(level, "ymag", vscroll->mag()); + xml.tag(level, "/drumedit"); + } + +//--------------------------------------------------------- +// readStatus +//--------------------------------------------------------- + +void DrumEdit::readStatus(Xml& xml) + { + for (;;) { + Xml::Token token = xml.parse(); + const QString& tag = xml.s1(); + switch (token) { + case Xml::Error: + case Xml::End: + return; + case Xml::TagStart: + if (tag == "steprec") { + int val = xml.parseInt(); + canvas->setSteprec(val); + srec->setChecked(val); + } + else if (tag == "midiin") { + int val = xml.parseInt(); + canvas->setMidiin(val); + midiin->setChecked(val); + } + else if (tag == "ctrledit") { + CtrlEdit* ctrl = addCtrl(); + ctrl->readStatus(xml); + } + else if (tag == split1->objectName()) + split1->readStatus(xml); + else if (tag == split2->objectName()) + split2->readStatus(xml); + else if (tag == "midieditor") + MidiEditor::readStatus(xml); + else if (tag == header->objectName()) + header->readStatus(xml); + else if (tag == "xmag") + hscroll->setMag(xml.parseInt()); + else if (tag == "xpos") + hscroll->setPos(xml.parseInt()); + else if (tag == "ymag") + vscroll->setMag(xml.parseInt()); + else if (tag == "ypos") + vscroll->setPos(xml.parseInt()); + else + xml.unknown("DrumEdit"); + break; + case Xml::TagEnd: + if (tag == "drumedit") { + _quantInit = _quant; + _rasterInit = _raster; + toolbar->setRaster(_raster); + toolbar->setQuant(_quant); + canvas->redrawGrid(); + return; + } + default: + break; + } + } + } + +//--------------------------------------------------------- +// readConfiguration +//--------------------------------------------------------- + +void DrumEdit::readConfiguration(Xml& xml) + { + for (;;) { + Xml::Token token = xml.parse(); + const QString& tag = xml.s1(); + switch (token) { + case Xml::Error: + case Xml::End: + return; + case Xml::TagStart: + if (tag == "quant") + _quantInit = xml.parseInt(); + else if (tag == "raster") + _rasterInit = xml.parseInt(); + else if (tag == "width") + _widthInit = xml.parseInt(); + else if (tag == "height") + _heightInit = xml.parseInt(); + else if (tag == "dcanvaswidth") + _dcanvasWidthInit = xml.parseInt(); + else if (tag == "dlistwidth") + _dlistWidthInit = xml.parseInt(); + else if (tag == "to") { + _toInit = xml.parseInt(); + } + else + xml.unknown("DrumEdit"); + break; + case Xml::TagEnd: + if (tag == "drumedit") { + return; + } + default: + break; + } + } + } + +//--------------------------------------------------------- +// writeConfiguration +//--------------------------------------------------------- + +void DrumEdit::writeConfiguration(int level, Xml& xml) + { + xml.tag(level++, "drumedit"); + xml.intTag(level, "quant", _quantInit); + xml.intTag(level, "raster", _rasterInit); + xml.intTag(level, "width", _widthInit); + xml.intTag(level, "height", _heightInit); + xml.intTag(level, "dlistwidth", _dlistWidthInit); + xml.intTag(level, "dcanvaswidth", _dcanvasWidthInit); + xml.intTag(level, "to", _toInit); + xml.tag(level, "/drumedit"); + } + +//--------------------------------------------------------- +// load +//--------------------------------------------------------- + +void DrumEdit::load() + { + //QString fn = getOpenFileName("drummaps", map_file_pattern, + QString fn = getOpenFileName("drummaps", drum_map_file_pattern, + this, tr("Muse: Load Drum Map"), 0); + if (fn.isEmpty()) + return; + bool popenFlag; + FILE* f = fileOpen(this, fn, QString(".map"), "r", popenFlag, true); + if (f == 0) + return; + + Xml xml(f); + int mode = 0; + for (;;) { + Xml::Token token = xml.parse(); + const QString& tag = xml.s1(); + switch (token) { + case Xml::Error: + case Xml::End: + return; + case Xml::TagStart: + if (mode == 0 && tag == "muse") + mode = 1; + else if (mode == 1 && tag == "drummap") { + readDrumMap(xml, true); + mode = 0; + } + else + xml.unknown("DrumEdit"); + break; + case Xml::Attribut: + break; + case Xml::TagEnd: + if (!mode && tag == "muse") + goto ende; + default: + break; + } + } +ende: + if (popenFlag) + pclose(f); + else + fclose(f); + dlist->redraw(); + canvas->redraw(); + } + +//--------------------------------------------------------- +// save +//--------------------------------------------------------- + +void DrumEdit::save() + { + //QString fn = getSaveFileName(QString("drummaps"), map_file_pattern, + QString fn = getSaveFileName(QString("drummaps"), drum_map_file_save_pattern, + this, tr("MusE: Store Drum Map")); + if (fn.isEmpty()) + return; + bool popenFlag; + FILE* f = fileOpen(this, fn, QString(".map"), "w", popenFlag, false, true); + if (f == 0) + return; + Xml xml(f); + xml.header(); + xml.tag(0, "muse version=\"1.0\""); + writeDrumMap(1, xml, true); + xml.tag(1, "/muse"); + + if (popenFlag) + pclose(f); + else + fclose(f); + } + +//--------------------------------------------------------- +// reset +//--------------------------------------------------------- + +void DrumEdit::reset() +{ + if(QMessageBox::warning(this, tr("Drum map"), + tr("Reset the drum map with GM defaults?"), + QMessageBox::Ok | QMessageBox::Cancel, QMessageBox::Ok) == QMessageBox::Ok) + { + resetGMDrumMap(); + dlist->redraw(); + canvas->redraw(); + } +} + +//--------------------------------------------------------- +// cmd +// pulldown menu commands +//--------------------------------------------------------- + +void DrumEdit::cmd(int cmd) + { + switch(cmd) { + case DrumCanvas::CMD_LOAD: + load(); + break; + case DrumCanvas::CMD_SAVE: + save(); + break; + case DrumCanvas::CMD_RESET: + reset(); + break; + default: + ((DrumCanvas*)(canvas))->cmd(cmd); + break; + } + } + +//--------------------------------------------------------- +// clipboardChanged +//--------------------------------------------------------- + +void DrumEdit::clipboardChanged() + { + pasteAction->setEnabled(QApplication::clipboard()->mimeData()->hasFormat(QString("text/x-muse-eventlist"))); + } + +//--------------------------------------------------------- +// selectionChanged +//--------------------------------------------------------- + +void DrumEdit::selectionChanged() + { + bool flag = canvas->selectionSize() > 0; + cutAction->setEnabled(flag); + copyAction->setEnabled(flag); + deleteAction->setEnabled(flag); + } + +//--------------------------------------------------------- +// addCtrl +//--------------------------------------------------------- + +CtrlEdit* DrumEdit::addCtrl() + { + CtrlEdit* ctrlEdit = new CtrlEdit(split1, this, xscale, true, "drumCtrlEdit"); + connect(hscroll, SIGNAL(scrollChanged(int)), ctrlEdit, SLOT(setXPos(int))); + connect(hscroll, SIGNAL(scaleChanged(int)), ctrlEdit, SLOT(setXMag(int))); + connect(ctrlEdit, SIGNAL(timeChanged(unsigned)), SLOT(setTime(unsigned))); + connect(ctrlEdit, SIGNAL(destroyedCtrl(CtrlEdit*)), SLOT(removeCtrl(CtrlEdit*))); + connect(ctrlEdit, SIGNAL(yposChanged(int)), toolbar, SLOT(setInt(int))); + connect(tools2, SIGNAL(toolChanged(int)), ctrlEdit, SLOT(setTool(int))); + connect(dlist, SIGNAL(curDrumInstrumentChanged(int)), SLOT(setCurDrumInstrument(int))); + + //printf("DrumEdit::addCtrl curDrumInstrument:%d\n", dlist->getSelectedInstrument()); + + setCurDrumInstrument(dlist->getSelectedInstrument()); + + // p3.3.44 + ctrlEdit->setTool(tools2->curTool()); + + ctrlEdit->setXPos(hscroll->pos()); + ctrlEdit->setXMag(hscroll->getScaleValue()); + + if(split1w1) + { + ///split2->setCollapsible(split1w1, false); + split2->setCollapsible(split2->indexOf(split1w1), false); + split1w1->setMinimumWidth(CTRL_PANEL_FIXED_WIDTH); + } + + int dw = vscroll->width() - 18;// 18 is the fixed width of the CtlEdit VScale widget. + if(dw < 1) + dw = 1; + ctrlEdit->setCanvasWidth(canvas->width() + dw); + + ctrlEdit->show(); + ctrlEditList.push_back(ctrlEdit); + return ctrlEdit; + } + +//--------------------------------------------------------- +// removeCtrl +//--------------------------------------------------------- + +void DrumEdit::removeCtrl(CtrlEdit* ctrl) + { + for (std::list<CtrlEdit*>::iterator i = ctrlEditList.begin(); + i != ctrlEditList.end(); ++i) { + if (*i == ctrl) { + ctrlEditList.erase(i); + break; + } + } + + if(split1w1) + { + if(ctrlEditList.empty()) + { + split1w1->setMinimumWidth(0); + ///split2->setCollapsible(split1w1, true); + split2->setCollapsible(split2->indexOf(split1w1), true); + } + } + } +//--------------------------------------------------------- +// newCanvasWidth +//--------------------------------------------------------- + +void DrumEdit::newCanvasWidth(int w) + { + int nw = w + (vscroll->width() - 18); // 18 is the fixed width of the CtlEdit VScale widget. + if(nw < 1) + nw = 1; + + for (std::list<CtrlEdit*>::iterator i = ctrlEditList.begin(); + i != ctrlEditList.end(); ++i) { + // Changed by Tim. p3.3.7 + //(*i)->setCanvasWidth(w); + (*i)->setCanvasWidth(nw); + } + + updateHScrollRange(); + } + +//--------------------------------------------------------- +// resizeEvent +//--------------------------------------------------------- + +void DrumEdit::resizeEvent(QResizeEvent* ev) + { + QWidget::resizeEvent(ev); + _widthInit = ev->size().width(); + _heightInit = ev->size().height(); + + //TODO: Make the dlist not expand/shrink, but the canvas instead + } + + +//--------------------------------------------------------- +// configChanged +//--------------------------------------------------------- + +void DrumEdit::configChanged() + { + initShortcuts(); + } + +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 + }; + +//--------------------------------------------------------- +// keyPressEvent +//--------------------------------------------------------- +void DrumEdit::keyPressEvent(QKeyEvent* event) + { + DrumCanvas* dc = (DrumCanvas*)canvas; + int index = 0; + int n = sizeof(rasterTable); + for (; index < n; ++index) + if (rasterTable[index] == raster()) + break; + int off = (index / 9) * 9; + index = index % 9; + int val; + int key = event->key(); + + if (((QInputEvent*)event)->modifiers() & Qt::ShiftModifier) + key += Qt::SHIFT; + if (((QInputEvent*)event)->modifiers() & Qt::AltModifier) + key += Qt::ALT; + if (((QInputEvent*)event)->modifiers() & Qt::ControlModifier) + key+= Qt::CTRL; + + if (key == Qt::Key_Escape) { + close(); + return; + } + else if (key == Qt::Key_Up) { + dlist->setCurDrumInstrument(dlist->getSelectedInstrument()-1); + dlist->redraw(); + return; + } + else if (key == Qt::Key_F2) { + dlist->lineEdit(dlist->getSelectedInstrument(),(int)DList::COL_NAME); + return; + } + else if (key == Qt::Key_Down) { + dlist->setCurDrumInstrument(dlist->getSelectedInstrument()+1); + dlist->redraw(); + return; + } + + else if (key == shortcuts[SHRT_POS_INC].key) { + dc->cmd(DrumCanvas::CMD_RIGHT); + return; + } + else if (key == shortcuts[SHRT_POS_DEC].key) { + dc->cmd(DrumCanvas::CMD_LEFT); + return; + } + + else if (key == shortcuts[SHRT_POS_INC_NOSNAP].key) { + dc->cmd(DrumCanvas::CMD_RIGHT_NOSNAP); + return; + } + else if (key == shortcuts[SHRT_POS_DEC_NOSNAP].key) { + dc->cmd(DrumCanvas::CMD_LEFT_NOSNAP); + return; + } + + else if (key == shortcuts[SHRT_TOOL_POINTER].key) { + tools2->set(PointerTool); + return; + } + else if (key == shortcuts[SHRT_TOOL_PENCIL].key) { + tools2->set(PencilTool); + return; + } + else if (key == shortcuts[SHRT_TOOL_RUBBER].key) { + tools2->set(RubberTool); + return; + } + else if (key == shortcuts[SHRT_ZOOM_IN].key) { + int mag = hscroll->mag(); + int zoomlvl = ScrollScale::getQuickZoomLevel(mag); + if (zoomlvl < 23) + zoomlvl++; + + int newmag = ScrollScale::convertQuickZoomLevelToMag(zoomlvl); + hscroll->setMag(newmag); + //printf("mag = %d zoomlvl = %d newmag = %d\n", mag, zoomlvl, newmag); + return; + } + else if (key == shortcuts[SHRT_ZOOM_OUT].key) { + int mag = hscroll->mag(); + int zoomlvl = ScrollScale::getQuickZoomLevel(mag); + if (zoomlvl > 1) + zoomlvl--; + + int newmag = ScrollScale::convertQuickZoomLevelToMag(zoomlvl); + hscroll->setMag(newmag); + //printf("mag = %d zoomlvl = %d newmag = %d\n", mag, zoomlvl, newmag); + return; + } + else if (key == shortcuts[SHRT_SCROLL_LEFT].key) { + int pos = hscroll->pos() - config.division; + if (pos < 0) + pos = 0; + hscroll->setPos(pos); + return; + } + else if (key == shortcuts[SHRT_SCROLL_RIGHT].key) { + int pos = hscroll->pos() + config.division; + hscroll->setPos(pos); + return; + } + + /* + else if (key == shortcuts[SHRT_INSERT_AT_LOCATION].key) { + pc->pianoCmd(CMD_INSERT); + return; + } + */ + else if (key == shortcuts[SHRT_SET_QUANT_1].key) + val = rasterTable[8 + off]; + else if (key == shortcuts[SHRT_SET_QUANT_2].key) + val = rasterTable[7 + off]; + else if (key == shortcuts[SHRT_SET_QUANT_3].key) + val = rasterTable[6 + off]; + else if (key == shortcuts[SHRT_SET_QUANT_4].key) + val = rasterTable[5 + off]; + else if (key == shortcuts[SHRT_SET_QUANT_5].key) + val = rasterTable[4 + off]; + else if (key == shortcuts[SHRT_SET_QUANT_6].key) + val = rasterTable[3 + off]; + else if (key == shortcuts[SHRT_SET_QUANT_7].key) + val = rasterTable[2 + off]; + else if (key == shortcuts[SHRT_TOGGLE_TRIOL].key) + val = rasterTable[index + ((off == 0) ? 9 : 0)]; + /* + else if (key == shortcuts[SHRT_EVENT_COLOR].key) { + if (colorMode == 0) + colorMode = 1; + else if (colorMode == 1) + colorMode = 2; + else + colorMode = 0; + setEventColorMode(colorMode); + return; + }*/ + else if (key == shortcuts[SHRT_TOGGLE_PUNCT].key) + val = rasterTable[index + ((off == 18) ? 9 : 18)]; + + else if (key == shortcuts[SHRT_TOGGLE_PUNCT2].key) {//CDW + if ((off == 18) && (index > 2)) { + val = rasterTable[index + 9 - 1]; + } + else if ((off == 9) && (index < 8)) { + val = rasterTable[index + 18 + 1]; + } + else + return; + } + else { //Default: + event->ignore(); + return; + } + setQuant(val); + setRaster(val); + toolbar->setQuant(_quant); + toolbar->setRaster(_raster); + } + + + +//--------------------------------------------------------- +// initShortcuts +//--------------------------------------------------------- + +void DrumEdit::initShortcuts() + { + loadAction->setShortcut(shortcuts[SHRT_OPEN].key); + saveAction->setShortcut(shortcuts[SHRT_SAVE].key); + + cutAction->setShortcut(shortcuts[SHRT_CUT].key); + copyAction->setShortcut(shortcuts[SHRT_COPY].key); + pasteAction->setShortcut(shortcuts[SHRT_PASTE].key); + deleteAction->setShortcut(shortcuts[SHRT_DELETE].key); + + fixedAction->setShortcut(shortcuts[SHRT_FIXED_LEN].key); + veloAction->setShortcut(shortcuts[SHRT_MODIFY_VELOCITY].key); + + sallAction->setShortcut(shortcuts[SHRT_SELECT_ALL].key); + snoneAction->setShortcut(shortcuts[SHRT_SELECT_NONE].key); + invAction->setShortcut(shortcuts[SHRT_SELECT_INVERT].key); + inAction->setShortcut(shortcuts[SHRT_SELECT_ILOOP].key); + outAction->setShortcut(shortcuts[SHRT_SELECT_OLOOP].key); + + prevAction->setShortcut(shortcuts[SHRT_SELECT_PREV_PART].key); + nextAction->setShortcut(shortcuts[SHRT_SELECT_NEXT_PART].key); + } + +//--------------------------------------------------------- +// execDeliveredScript +//--------------------------------------------------------- +void DrumEdit::execDeliveredScript(int id) +{ + //QString scriptfile = QString(INSTPREFIX) + SCRIPTSSUFFIX + deliveredScriptNames[id]; + QString scriptfile = song->getScriptPath(id, true); + song->executeScript(scriptfile.toLatin1().constData(), parts(), quant(), true); +} + +//--------------------------------------------------------- +// execUserScript +//--------------------------------------------------------- +void DrumEdit::execUserScript(int id) +{ + QString scriptfile = song->getScriptPath(id, false); + song->executeScript(scriptfile.toLatin1().constData(), parts(), quant(), true); +} + |