diff options
Diffstat (limited to 'attic/muse_qt4_evolution/muse/midiedit/dcanvas.cpp')
-rw-r--r-- | attic/muse_qt4_evolution/muse/midiedit/dcanvas.cpp | 723 |
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); + } + + |