summaryrefslogtreecommitdiff
path: root/attic/muse_qt4_evolution/muse/midiedit/dcanvas.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'attic/muse_qt4_evolution/muse/midiedit/dcanvas.cpp')
-rw-r--r--attic/muse_qt4_evolution/muse/midiedit/dcanvas.cpp723
1 files changed, 723 insertions, 0 deletions
diff --git a/attic/muse_qt4_evolution/muse/midiedit/dcanvas.cpp b/attic/muse_qt4_evolution/muse/midiedit/dcanvas.cpp
new file mode 100644
index 00000000..20d8170d
--- /dev/null
+++ b/attic/muse_qt4_evolution/muse/midiedit/dcanvas.cpp
@@ -0,0 +1,723 @@
+//=============================================================================
+// 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 "dcanvas.h"
+#include "song.h"
+#include "midieditor.h"
+#include "drummap.h"
+#include "audio.h"
+#include "velocity.h"
+#include "gconfig.h"
+#include "part.h"
+
+#define CARET 12
+#define CARET2 6
+
+//---------------------------------------------------------
+// drumMap
+//---------------------------------------------------------
+
+DrumMap* DrumCanvas::drumMap() const
+ {
+ DrumMap* drumMap = track()->drumMap();
+ if (drumMap == 0)
+ drumMap = &noDrumMap;
+ return drumMap;
+ }
+
+//---------------------------------------------------------
+// y2pitch
+//---------------------------------------------------------
+
+int DrumCanvas::y2pitch(int y) const
+ {
+ return drumMap()->anote(EventCanvas::y2pitch(y));
+ }
+
+//---------------------------------------------------------
+// pitch2y
+//---------------------------------------------------------
+
+int DrumCanvas::pitch2y(int pitch) const
+ {
+ return EventCanvas::pitch2y(drumMap()->outmap(pitch));
+ }
+
+//---------------------------------------------------------
+// DrumCanvas
+//---------------------------------------------------------
+
+DrumCanvas::DrumCanvas(MidiEditor* pr)
+ : EventCanvas(pr, TIME_CANVAS_DRUMEDIT)
+ {
+ singlePitch = -1;
+ verticalScrollBar()->setSingleStep(drumHeight/2);
+ canvasTools = PointerTool | PencilTool | RubberTool;
+ songChanged(SC_TRACK_INSERTED);
+ connect(track(), SIGNAL(drumMapChanged()), widget(), SLOT(update()));
+ }
+
+//---------------------------------------------------------
+// addItem
+//---------------------------------------------------------
+
+void DrumCanvas::addItem(Part* part, const Event& event)
+ {
+ CItem* item = new CItem(event, part);
+ unsigned tick = event.tick() + part->tick();
+ item->pos = Pos(tick);
+ items.add(item);
+ }
+
+//---------------------------------------------------------
+// paint
+//---------------------------------------------------------
+
+void DrumCanvas::paint(QPainter& p, QRect r)
+ {
+ p.setPen(QPen(Qt::black, 0.0));
+
+ QPainterPath pa;
+ pa.moveTo(-CARET2, 0);
+ pa.lineTo(0, - CARET2);
+ pa.lineTo(CARET2, 0);
+ pa.lineTo(0, CARET2);
+ pa.closeSubpath();
+
+ Pos p1(pix2pos(r.x() - CARET2));
+ Pos p2(pix2pos(r.x() + r.width() + CARET2));
+ iCItem from(items.lower_bound(p1.tick()));
+ iCItem to(items.upper_bound(p2.tick()));
+
+ for (iCItem i = from; i != to; ++i) {
+ CItem* e = i->second;
+ int x = pos2pix(AL::Pos(i->first));
+ int y = pitch2y(e->event.pitch()) + drumHeight/2;
+ QPoint pt(x, y);
+ Event me(e->event);
+
+ DrumMapEntry* dm = drumMap()->entry(me.pitch()); //Get the drum item
+ QColor color;
+ int velo = me.velo();
+ if (velo < dm->lv1)
+ color.setRgb(240, 240, 255);
+ else if (velo < dm->lv2)
+ color.setRgb(200, 200, 255);
+ else if (velo < dm->lv3)
+ color.setRgb(170, 170, 255);
+ else
+ color.setRgb(0, 0, 255);
+
+ if (e->part != curPart)
+ p.setBrush(Qt::lightGray);
+ else if (e->isMoving) {
+ p.setBrush(Qt::gray);
+ p.translate(pt);
+ p.drawPath(pa);
+ p.translate(-pt);
+ p.setBrush(Qt::black);
+
+ int x = pos2pix(e->moving);
+ int y = e->my + drumHeight/2;
+ pt = QPoint(x, y);
+ }
+ else if (e->isSelected())
+ p.setBrush(Qt::black);
+ else
+ p.setBrush(color);
+ p.translate(pt);
+ p.drawPath(pa);
+ p.translate(-pt);
+ }
+
+ //---------------------------------------------------
+ // draw lasso
+ //---------------------------------------------------
+
+ if (drag == DRAG_LASSO) {
+ p.setPen(Qt::blue);
+ p.setBrush(Qt::NoBrush);
+ p.drawRect(lasso);
+ }
+ }
+
+//---------------------------------------------------------
+// moveItem
+//---------------------------------------------------------
+
+void DrumCanvas::moveItem(CItem* nevent, DragType dtype)
+ {
+ Part* part = nevent->part;
+ Event event = nevent->event;
+ int npitch = y2pitch(nevent->my);
+
+ Event newEvent = event.clone();
+ newEvent.setPitch(npitch);
+ newEvent.setPos(nevent->moving - *(nevent->part));
+ if (dtype == MOVE_COPY)
+ audio->msgAddEvent(newEvent, part, false);
+ else
+ audio->msgChangeEvent(event, newEvent, part, false);
+ }
+
+//---------------------------------------------------------
+// newItem
+//---------------------------------------------------------
+
+CItem* DrumCanvas::newItem(const QPoint& p, int state)
+ {
+ AL::Pos pos(pix2pos(p.x()));
+ pos.snap(raster());
+ if (pos < partPos1 || pos >= partPos2) {
+ return 0;
+ }
+
+ int pitch = y2pitch(p.y());
+ int instr = drumMap()->outmap(pitch);
+ DrumMapEntry* dm = drumMap()->entry(instr);
+ int velo = dm->lv4;
+ if (state == Qt::ShiftModifier)
+ velo = dm->lv3;
+ else if (state == Qt::ControlModifier)
+ velo = dm->lv2;
+ else if (state == (Qt::ControlModifier | Qt::ShiftModifier))
+ velo = dm->lv1;
+
+ Event e(Note);
+ e.setPos(pos - *curPart);
+ e.setPitch(drumMap()->anote(instr));
+ e.setVelo(velo);
+ e.setLenTick(dm->len);
+ return new CItem(e, curPart);
+ }
+
+//---------------------------------------------------------
+// resizeItem
+//---------------------------------------------------------
+
+void DrumCanvas::resizeItem(CItem* nevent, bool)
+ {
+ Event ev = nevent->event;
+ audio->msgDeleteEvent(ev, nevent->part);
+ }
+
+//---------------------------------------------------------
+// newItem
+//---------------------------------------------------------
+
+void DrumCanvas::newItem(CItem* nevent, bool noSnap)
+ {
+ Event event = nevent->event;
+ Pos pos(nevent->pos);
+ if (!noSnap)
+ pos.snap(editor->raster());
+ event.setPos(pos - *(nevent->part));
+ int npitch = event.pitch();
+ event.setPitch(npitch);
+
+ //
+ // check for existing event
+ // if found change command semantic from insert to delete
+ //
+ EventList* el = nevent->part->events();
+ iEvent lower = el->lower_bound(event.tick());
+ iEvent upper = el->upper_bound(event.tick());
+
+ for (iEvent i = lower; i != upper; ++i) {
+ Event ev = i->second;
+ if (ev.pitch() == npitch) {
+ audio->msgDeleteEvent(ev, nevent->part);
+ return;
+ }
+ }
+
+ audio->msgAddEvent(event, nevent->part);
+ }
+
+//---------------------------------------------------------
+// deleteItem
+//---------------------------------------------------------
+
+bool DrumCanvas::deleteItem(CItem* item)
+ {
+ Event ev = item->event;
+ audio->msgDeleteEvent(ev, item->part);
+ return false;
+ }
+
+//---------------------------------------------------------
+// cmd
+//---------------------------------------------------------
+
+void DrumCanvas::cmd(QAction* a)
+ {
+ QString cmd(a->data().toString());
+
+ if (cmd == "paste")
+ paste();
+ else if (cmd == "sel_all") {
+ for (iCItem k = items.begin(); k != items.end(); ++k) {
+ if (!k->second->isSelected())
+ selectItem(k->second, true);
+ }
+ }
+ else if (cmd == "sel_none")
+ deselectAll();
+ else if (cmd == "sel_inv") {
+ for (iCItem k = items.begin(); k != items.end(); ++k)
+ selectItem(k->second, !k->second->isSelected());
+ }
+ else if (cmd == "sel_ins_loc") {
+ for (iCItem k = items.begin(); k != items.end(); ++k) {
+ CItem* nevent = k->second;
+ Part* part = nevent->part;
+ Event event = nevent->event;
+ unsigned tick = event.tick() + part->tick();
+ if (tick < song->lpos() || tick >= song->rpos())
+ selectItem(k->second, false);
+ else
+ selectItem(k->second, true);
+ }
+ }
+ else if (cmd == "sel_out_loc") {
+ for (iCItem k = items.begin(); k != items.end(); ++k) {
+ CItem* nevent = k->second;
+ Part* part = nevent->part;
+ Event event = nevent->event;
+ unsigned tick = event.tick() + part->tick();
+ if (tick < song->lpos() || tick >= song->rpos())
+ selectItem(k->second, true);
+ else
+ selectItem(k->second, false);
+ }
+ }
+ else if (cmd == "delete") {
+ if (selectionSize()) {
+ song->startUndo();
+ for (iCItem i = items.begin(); i != items.end(); ++i) {
+ if (!i->second->isSelected())
+ continue;
+ Event ev = i->second->event;
+ audio->msgDeleteEvent(ev, i->second->part, false);
+ }
+ song->endUndo(SC_EVENT_REMOVED);
+ }
+ return;
+ }
+ else if (cmd == "midi_fixed_len") {
+ if (selectionSize()) {
+ song->startUndo();
+ for (iCItem k = items.begin(); k != items.end(); ++k) {
+ if (k->second->isSelected()) {
+ CItem* devent = k->second;
+ Event event = devent->event;
+ Event newEvent = event.clone();
+ newEvent.setLenTick(drumMap()->entry(event.pitch())->len);
+ audio->msgChangeEvent(event, newEvent, devent->part, false);
+ }
+ }
+ song->endUndo(SC_EVENT_MODIFIED);
+ }
+ }
+ else if (cmd == "goto_left") {
+ int frames = pos[0].tick() - editor->rasterStep(pos[0].tick());
+ if (frames < 0)
+ frames = 0;
+ Pos p(frames, AL::TICKS);
+ song->setPos(0, p, true, true, true);
+ }
+ else if (cmd == "goto_right") {
+ Pos p(pos[0].tick() + editor->rasterStep(pos[0].tick()), AL::TICKS);
+ song->setPos(0, p, true, true, true);
+ }
+ else if (cmd == "mid_mod_velo") {
+ Velocity w(this);
+ w.setRange(editor->applyTo());
+ if (w.exec()) {
+ editor->setApplyTo(w.range());
+ int rate = w.rateVal();
+ int offset = w.offsetVal();
+
+ song->startUndo();
+ for (iCItem k = items.begin(); k != items.end(); ++k) {
+ CItem* devent = k->second;
+ Event event = devent->event;
+ if (event.type() != Note)
+ continue;
+ unsigned tick = event.tick();
+ bool selected = devent->isSelected();
+ bool inLoop = (tick >= song->lpos()) && (tick < song->rpos());
+
+ int range = editor->applyTo();
+ if ((range == RANGE_ALL)
+ || (range == RANGE_SELECTED && selected)
+ || (range == RANGE_LOOPED && inLoop)
+ || (range == (RANGE_LOOPED | RANGE_SELECTED) && selected && inLoop)) {
+ int velo = event.velo();
+
+ //velo = rate ? (velo * 100) / rate : 64;
+ velo = (velo * rate) / 100;
+ velo += offset;
+
+ if (velo <= 0)
+ velo = 1;
+ if (velo > 127)
+ velo = 127;
+ if (event.velo() != velo) {
+ Event newEvent = event.clone();
+ newEvent.setVelo(velo);
+ audio->msgChangeEvent(event, newEvent, devent->part, false);
+ }
+ }
+ }
+ song->endUndo(SC_EVENT_MODIFIED);
+ }
+ }
+ widget()->update();
+ }
+
+//---------------------------------------------------------
+// paste
+// paste events
+//---------------------------------------------------------
+
+void DrumCanvas::paste()
+ {
+ QString stype("x-muse-eventlist");
+ QString s = QApplication::clipboard()->text(stype, QClipboard::Selection);
+ pasteAt(s, song->cpos());
+ }
+
+//---------------------------------------------------------
+// startDrag
+//---------------------------------------------------------
+
+void DrumCanvas::startDrag(CItem* /* item*/, bool /*copymode*/)
+ {
+printf("DrumCanvas: startDrag\n");
+#if 0 //TD
+ QMimeData* drag = getTextDrag();
+ if (drag) {
+ QApplication::clipboard()->setMimeData(drag, QClipboard::Selection);
+ if (copymode)
+ drag->dragCopy();
+ else
+ drag->dragMove();
+ }
+#endif
+ }
+
+//---------------------------------------------------------
+// dragEnterEvent
+//---------------------------------------------------------
+
+void DrumCanvas::dragEnterEvent(QDragEnterEvent* /*event*/)
+ {
+printf("DrumCanvas: dragEnterEvent\n");
+//TD event->accept(Q3TextDrag::canDecode(event));
+ }
+
+//---------------------------------------------------------
+// dragMoveEvent
+//---------------------------------------------------------
+
+void DrumCanvas::dragMoveEvent(QDragMoveEvent*)
+ {
+ printf("drag move %p\n", this);
+ }
+
+//---------------------------------------------------------
+// dragLeaveEvent
+//---------------------------------------------------------
+
+void DrumCanvas::dragLeaveEvent(QDragLeaveEvent*)
+ {
+ printf("drag leave\n");
+ }
+
+//---------------------------------------------------------
+// dropEvent
+//---------------------------------------------------------
+
+void DrumCanvas::viewDropEvent(QDropEvent* /*event*/)
+ {
+printf("DrumCanvas: viewDropEvent\n");
+#if 0 //TD
+ QString text;
+ if (event->source() == this) {
+ printf("local DROP\n");
+ return;
+ }
+ if (Q3TextDrag::decode(event, text)) {
+// printf("drop <%s>\n", text.ascii());
+ int x = editor->rasterVal(event->pos().x());
+ if (x < 0)
+ x = 0;
+ pasteAt(text, x);
+ }
+#endif
+ }
+
+//---------------------------------------------------------
+// keyPressed
+//---------------------------------------------------------
+
+void DrumCanvas::keyPressed(int index, bool)
+ {
+ int pitch = drumMap()->entry(index)->anote;
+
+ // play note:
+ MidiEvent e(0, 0, 0x90, pitch, 127);
+ track()->playMidiEvent(&e);
+ }
+
+//---------------------------------------------------------
+// keyReleased
+//---------------------------------------------------------
+
+void DrumCanvas::keyReleased(int index, bool)
+ {
+ int pitch = drumMap()->entry(index)->anote;
+
+ // release note:
+ MidiEvent e(0, 0, 0x90, pitch, 0);
+ track()->playMidiEvent(&e);
+ }
+
+//---------------------------------------------------------
+// resizeEvent
+//---------------------------------------------------------
+
+void DrumCanvas::resizeEvent(QResizeEvent* ev)
+ {
+ if (ev->size().width() != ev->oldSize().width())
+ emit newWidth(ev->size().width());
+ EventCanvas::resizeEvent(ev);
+ }
+
+
+//---------------------------------------------------------
+// modifySelected
+//---------------------------------------------------------
+
+void DrumCanvas::modifySelected(NoteInfo::ValType type, int delta)
+ {
+ audio->msgIdle(true);
+ song->startUndo();
+ for (iCItem i = items.begin(); i != items.end(); ++i) {
+ if (!(i->second->isSelected()))
+ continue;
+ CItem* e = i->second;
+ Event event = e->event;
+ if (event.type() != Note)
+ continue;
+
+ Part* part = e->part;
+ Event newEvent = event.clone();
+
+ switch (type) {
+ case NoteInfo::VAL_TIME:
+ {
+ int newTime = event.tick() + delta;
+ if (newTime < 0)
+ newTime = 0;
+ newEvent.setTick(newTime);
+ }
+ break;
+ case NoteInfo::VAL_LEN:
+ /*
+ {
+ int len = event.lenTick() + delta;
+ if (len < 1)
+ len = 1;
+ newEvent.setLenTick(len);
+ }
+ */
+ printf("DrumCanvas::modifySelected - NoteInfo::VAL_LEN not implemented\n");
+ break;
+ case NoteInfo::VAL_VELON:
+ /*
+ {
+ int velo = event->velo() + delta;
+ if (velo > 127)
+ velo = 127;
+ else if (velo < 0)
+ velo = 0;
+ newEvent.setVelo(velo);
+ }
+ */
+ printf("DrumCanvas::modifySelected - NoteInfo::VAL_VELON not implemented\n");
+ break;
+ case NoteInfo::VAL_VELOFF:
+ /*
+ {
+ int velo = event.veloOff() + delta;
+ if (velo > 127)
+ velo = 127;
+ else if (velo < 0)
+ velo = 0;
+ newEvent.setVeloOff(velo);
+ }
+ */
+ printf("DrumCanvas::modifySelected - NoteInfo::VAL_VELOFF not implemented\n");
+ break;
+ case NoteInfo::VAL_PITCH:
+ {
+ int pitch = event.pitch() - delta; // Reversing order since the drumlist is displayed in increasing order
+ if (pitch > 127)
+ pitch = 127;
+ else if (pitch < 0)
+ pitch = 0;
+ newEvent.setPitch(pitch);
+ }
+ break;
+ }
+ song->changeEvent(event, newEvent, part);
+ song->undoOp(UndoOp::ModifyEvent, newEvent, event, part);
+ }
+ song->endUndo(SC_EVENT_MODIFIED);
+ audio->msgIdle(false);
+ }
+
+//---------------------------------------------------------
+// paintDrumList
+//---------------------------------------------------------
+
+void DrumCanvas::paintDrumList(QPainter& p, QRect r)
+ {
+ p.fillRect(r, QColor(0xe0, 0xe0, 0xe0));
+ paintVLine(p, 0, rPanelB.y(), rPanelA.x() + rPanelA.width());
+// p.setFont(config.fonts[1]);
+
+ int yoff = wpos.y() - rPanelA.y();
+ int i = (r.y() + yoff) / drumHeight;
+ if (i < 0)
+ i = 0;
+ if (i > 127)
+ return;
+ int y = i * drumHeight - yoff;
+ DrumMap* dm = drumMap();
+
+ for (; i < 128; ++i, y += drumHeight) {
+ if (y > r.y() + r.height())
+ break;
+ QRect r(3, y, drumWidth-4, drumHeight);
+ if (dm->anote(i) == curPitch || dm->anote(i) == singlePitch)
+ p.fillRect(0, y, drumWidth-4, drumHeight, Qt::white);
+ DrumMapEntry* de = dm->entry(i);
+ if (de->mute) {
+ p.setPen(Qt::red);
+ p.drawText(r, Qt::AlignVCenter | Qt::AlignLeft, "m");
+ p.setPen(Qt::darkGray);
+ p.drawText(r.adjusted(16, 0, 0, 0), Qt::AlignVCenter | Qt::AlignLeft, de->name);
+ }
+ else {
+ p.setPen(Qt::black);
+ p.drawText(r, Qt::AlignVCenter | Qt::AlignLeft, "m");
+ p.drawText(r.adjusted(16, 0, 0, 0), Qt::AlignVCenter | Qt::AlignLeft, de->name);
+ }
+ if (i != 0)
+ p.drawLine(0, y, drumWidth-3, y);
+ }
+ p.setPen(QPen(Qt::darkGray, 1));
+ p.drawLine(17, r.y(), 17, r.y() + r.height());
+ }
+
+//---------------------------------------------------------
+// searchItem
+//---------------------------------------------------------
+
+CItem* DrumCanvas::searchItem(const QPoint& p) const
+ {
+ Pos p1(pix2pos(p.x() - CARET2));
+ Pos p2(pix2pos(p.x() + CARET2));
+
+ ciCItem from(items.lower_bound(p1.tick()));
+ ciCItem to(items.upper_bound(p2.tick()));
+
+ int pitch = y2pitch(p.y());
+ for (ciCItem i = from; i != to; ++i) {
+ if (pitch == i->second->event.pitch())
+ return i->second;
+ }
+ return 0;
+ }
+
+//---------------------------------------------------------
+// selectLasso
+//---------------------------------------------------------
+
+void DrumCanvas::selectLasso(bool toggle)
+ {
+ Pos p1(pix2pos(lasso.x()));
+ Pos p2(pix2pos(lasso.x() + lasso.width()));
+
+ iCItem from(items.lower_bound(p1.tick()));
+ iCItem to(items.upper_bound(p2.tick()));
+ int y = lasso.y();
+ int pitch1 = y2pitch(y);
+ int pitch2 = y2pitch(y + lasso.height());
+
+ int n = 0;
+ for (iCItem i = from; i != to; ++i) {
+ CItem* item = i->second;
+ int pitch = item->event.pitch();
+ if (pitch >= pitch1 && pitch <= pitch2) {
+ selectItem(item, !(toggle && item->isSelected()));
+ ++n;
+ }
+ }
+ if (n) {
+ updateSelection();
+ widget()->update();
+ }
+ }
+
+//---------------------------------------------------------
+// mousePress
+//---------------------------------------------------------
+
+void DrumCanvas::mousePress(QMouseEvent* ev)
+ {
+ QPoint r(ev->pos());
+ int pitch = y2pitch(r.y() - rPanelA.y() - wpos.y());
+ if (r.x() < 20) {
+ //
+ // "mute" button click
+ //
+ DrumMap* dm = drumMap();
+ int idx = dm->outmap(pitch);
+ DrumMapEntry* de = dm->entry(idx);
+ de->mute = !de->mute;
+ widget()->update(rPanelA);
+ return;
+ }
+ else if (r.x() < rCanvasA.x()) {
+ if (pitch != singlePitch) {
+ singlePitch = pitch;
+ for (iCtrlEdit i = ctrlEditList.begin(); i != ctrlEditList.end(); ++i)
+ (*i)->setSinglePitch(singlePitch);
+ widget()->update();
+ }
+ }
+ EventCanvas::mousePress(ev);
+ }
+
+