diff options
Diffstat (limited to 'attic/muse2-oom/muse2/muse/midiedit/dcanvas.cpp')
-rw-r--r-- | attic/muse2-oom/muse2/muse/midiedit/dcanvas.cpp | 1351 |
1 files changed, 0 insertions, 1351 deletions
diff --git a/attic/muse2-oom/muse2/muse/midiedit/dcanvas.cpp b/attic/muse2-oom/muse2/muse/midiedit/dcanvas.cpp deleted file mode 100644 index 34622296..00000000 --- a/attic/muse2-oom/muse2/muse/midiedit/dcanvas.cpp +++ /dev/null @@ -1,1351 +0,0 @@ -//========================================================= -// MusE -// Linux Music Editor -// $Id: dcanvas.cpp,v 1.16.2.10 2009/10/15 22:45:50 terminator356 Exp $ -// (C) Copyright 1999 Werner Schweer (ws@seh.de) -//========================================================= - -#include <QPainter> -#include <QApplication> -#include <QClipboard> -#include <QDrag> -#include <QDragLeaveEvent> -#include <QPolygon> -#include <QDragEnterEvent> -#include <QDragMoveEvent> -#include <QDropEvent> -#include <QResizeEvent> - -#include <stdio.h> -#include <values.h> -#include <errno.h> -//#include <sys/stat.h> -//#include <sys/mman.h> - -#include "dcanvas.h" -#include "midieditor.h" -#include "drummap.h" -#include "event.h" -#include "mpevent.h" -#include "xml.h" -#include "globals.h" -#include "midiport.h" -#include "audio.h" -#include "velocity.h" - -#define CARET 10 -#define CARET2 5 - -//--------------------------------------------------------- -// DEvent -//--------------------------------------------------------- - -DEvent::DEvent(Event e, Part* p) - : CItem(e, p) - { - int instr = e.pitch(); - int y = instr * TH + TH/2; - int tick = e.tick() + p->tick(); - setPos(QPoint(tick, y)); - setBBox(QRect(-CARET2, -CARET2, CARET, CARET)); - } - -//--------------------------------------------------------- -// addItem -//--------------------------------------------------------- - -void DrumCanvas::addItem(Part* part, Event& event) - { - if (signed(event.tick())<0) { - printf("ERROR: trying to add event before current part!\n"); - return; - } - - DEvent* ev = new DEvent(event, part); - items.add(ev); - - int diff = event.endTick()-part->lenTick(); - if (diff > 0) {// too short part? extend it - //printf("addItem - this code should not be run!\n"); - //Part* newPart = part->clone(); - //newPart->setLenTick(newPart->lenTick()+diff); - //audio->msgChangePart(part, newPart,false); - //part = newPart; - part->setLenTick(part->lenTick()+diff); - } - } - -//--------------------------------------------------------- -// DrumCanvas -//--------------------------------------------------------- - -DrumCanvas::DrumCanvas(MidiEditor* pr, QWidget* parent, int sx, - int sy, const char* name) - : EventCanvas(pr, parent, sx, sy, name) - { - setVirt(false); - songChanged(SC_TRACK_INSERTED); - } - -//--------------------------------------------------------- -// moveCanvasItems -//--------------------------------------------------------- - -void DrumCanvas::moveCanvasItems(CItemList& items, int dp, int dx, DragType dtype, int* pflags) -{ - if(editor->parts()->empty()) - return; - - PartsToChangeMap parts2change; - - int modified = 0; - for(iPart ip = editor->parts()->begin(); ip != editor->parts()->end(); ++ip) - { - Part* part = ip->second; - if(!part) - continue; - - int npartoffset = 0; - for(iCItem ici = items.begin(); ici != items.end(); ++ici) - { - CItem* ci = ici->second; - if(ci->part() != part) - continue; - - int x = ci->pos().x() + dx; - int y = pitch2y(y2pitch(ci->pos().y()) + dp); - QPoint newpos = raster(QPoint(x, y)); - - // Test moving the item... - DEvent* nevent = (DEvent*) ci; - Event event = nevent->event(); - x = newpos.x(); - if(x < 0) - x = 0; - int ntick = editor->rasterVal(x) - part->tick(); - if(ntick < 0) - ntick = 0; - int diff = ntick + event.lenTick() - part->lenTick(); - - // If moving the item would require a new part size... - if(diff > npartoffset) - npartoffset = diff; - } - - if(npartoffset > 0) - { - // Create new part... - // if there are several events that are moved outside the part, it will be recreated for each - // so the part _in_ the event will not be valid, ask the authority. -// Part* newPart = part->clone(); - //Part* newPart = Canvas::part()->clone(); - -// newPart->setLenTick(newPart->lenTick() + npartoffset); - //audio->msgChangePart(part, newPart,false); - -// modified = SC_PART_MODIFIED; - - // BUG FIX: #1650953 - // Added by T356. - // Fixes posted "select and drag past end of part - crashing" bug -// for(iPart ip = editor->parts()->begin(); ip != editor->parts()->end(); ++ip) -// { -// if(ip->second == part) -// { -// editor->parts()->erase(ip); -// break; -// } -// } - -// editor->parts()->add(newPart); -// audio->msgChangePart(part, newPart,false); - -// if(parts2change.find(part) == parts2change.end()) -// parts2change.insert(std::pair<Part*, Part*> (part, newPart)); - iPartToChange ip2c = parts2change.find(part); - if(ip2c == parts2change.end()) - { - PartToChange p2c = {0, npartoffset}; - parts2change.insert(std::pair<Part*, PartToChange> (part, p2c)); - } - else - ip2c->second.xdiff = npartoffset; - - - //part = newPart; // reassign - //item->setPart(part); - //item->setEvent(newEvent); - //curPart = part; - //curPartId = curPart->sn(); - - } - } - - for(iPartToChange ip2c = parts2change.begin(); ip2c != parts2change.end(); ++ip2c) - { - Part* opart = ip2c->first; - int diff = ip2c->second.xdiff; - - Part* newPart = opart->clone(); - - newPart->setLenTick(newPart->lenTick() + diff); - - modified = SC_PART_MODIFIED; - - // BUG FIX: #1650953 - // Added by T356. - // Fixes posted "select and drag past end of part - crashing" bug - for(iPart ip = editor->parts()->begin(); ip != editor->parts()->end(); ++ip) - { - if(ip->second == opart) - { - editor->parts()->erase(ip); - break; - } - } - - editor->parts()->add(newPart); - // Indicate no undo, and do port controller values but not clone parts. - //audio->msgChangePart(opart, newPart, false); - audio->msgChangePart(opart, newPart, false, true, false); - - ip2c->second.npart = newPart; - - } - - iPartToChange icp = parts2change.find(curPart); - if(icp != parts2change.end()) - { - curPart = icp->second.npart; - curPartId = curPart->sn(); - } - - std::vector< CItem* > doneList; - typedef std::vector< CItem* >::iterator iDoneList; - - for(iCItem ici = items.begin(); ici != items.end(); ++ici) - { - CItem* ci = ici->second; - - // If this item's part is in the parts2change list, change the item's part to the new part. - Part* pt = ci->part(); - iPartToChange ip2c = parts2change.find(pt); - if(ip2c != parts2change.end()) - ci->setPart(ip2c->second.npart); - - int x = ci->pos().x(); - int y = ci->pos().y(); - int nx = x + dx; - int ny = pitch2y(y2pitch(y) + dp); - QPoint newpos = raster(QPoint(nx, ny)); - selectItem(ci, true); - - iDoneList idl; - for(idl = doneList.begin(); idl != doneList.end(); ++idl) - // This compares EventBase pointers to see if they're the same... - if((*idl)->event() == ci->event()) - break; - - // Do not process if the event has already been processed (meaning it's an event in a clone part)... - //if(moveItem(ci, newpos, dtype)) - if(idl != doneList.end()) - // Just move the canvas item. - ci->move(newpos); - else - { - // Currently moveItem always returns true. - if(moveItem(ci, newpos, dtype)) - { - // Add the canvas item to the list of done items. - doneList.push_back(ci); - // Move the canvas item. - ci->move(newpos); - } - } - - if(moving.size() == 1) { - itemReleased(curItem, newpos); - } - if(dtype == MOVE_COPY || dtype == MOVE_CLONE) - selectItem(ci, false); - } - - if(pflags) - *pflags = modified; -} - -//--------------------------------------------------------- -// moveItem -//--------------------------------------------------------- - -// Changed by T356. -//bool DrumCanvas::moveItem(CItem* item, const QPoint& pos, DragType dtype, int* pflags) -bool DrumCanvas::moveItem(CItem* item, const QPoint& pos, DragType dtype) - { - DEvent* nevent = (DEvent*) item; - - // Changed by T356. - //MidiPart* part = (MidiPart*)Canvas::part(); // part can be dynamically recreated, ask the authority - MidiPart* part = (MidiPart*)nevent->part(); - - Event event = nevent->event(); - int x = pos.x(); - if (x < 0) - x = 0; - int ntick = editor->rasterVal(x) - part->tick(); - if (ntick < 0) - ntick = 0; - int npitch = y2pitch(pos.y()); - Event newEvent = event.clone(); - - newEvent.setPitch(npitch); - newEvent.setTick(ntick); - - // Removed by T356. - /* - // Added by T356. - int modified = 0; - //song->startUndo(); - int diff = newEvent.endTick()-part->lenTick(); - if (diff > 0) // too short part? extend it - { - // if there are several events that are moved outside the part, it will be recreated for each - // so the part _in_ the event will not be valid, ask the authority. - //Part* newPart = part->clone(); - MidiPart* newPart = (MidiPart*)Canvas::part()->clone(); - newPart->setLenTick(newPart->lenTick()+diff); - audio->msgChangePart(Canvas::part(), newPart,false); - - modified = SC_PART_MODIFIED; - part = newPart; // reassign - for(iPart i = editor->parts()->begin(); i != editor->parts()->end(); ++i) - { - if(i->second == Canvas::part()) - { - editor->parts()->erase(i); - break; - } - } - editor->parts()->add(part); - item->setPart(part); - item->setEvent(newEvent); - curPart = part; - curPartId = curPart->sn(); - } - */ - - // Added by T356. - // msgAddEvent and msgChangeEvent (below) will set these, but set them here first? - //item->setPart(part); - item->setEvent(newEvent); - - // Added by T356. - if(((int)newEvent.endTick() - (int)part->lenTick()) > 0) - printf("DrumCanvas::moveItem Error! New event end:%d exceeds length:%d of part:%s\n", newEvent.endTick(), part->lenTick(), part->name().toLatin1().constData()); - - if (dtype == MOVE_COPY || dtype == MOVE_CLONE) { - // Indicate no undo, and do not do port controller values and clone parts. - //audio->msgAddEvent(newEvent, part, false); - audio->msgAddEvent(newEvent, part, false, false, false); - } - else { - // Indicate no undo, and do not do port controller values and clone parts. - //audio->msgChangeEvent(event, newEvent, part, false); - audio->msgChangeEvent(event, newEvent, part, false, false, false); - } - - // Removed by T356. - //if(pflags) - // *pflags = modified; - - return true; - } - -//--------------------------------------------------------- -// newItem -//--------------------------------------------------------- - -CItem* DrumCanvas::newItem(const QPoint& p, int state) - { - int instr = y2pitch(p.y()); //drumInmap[y2pitch(p.y())]; - int velo = drumMap[instr].lv4; - if (state == Qt::ShiftModifier) - velo = drumMap[instr].lv3; - else if (state == Qt::ControlModifier) - velo = drumMap[instr].lv2; - else if (state == (Qt::ControlModifier | Qt::ShiftModifier)) - velo = drumMap[instr].lv1; - int tick = editor->rasterVal(p.x()); - tick -= curPart->tick(); - Event e(Note); - e.setTick(tick); - e.setPitch(instr); - e.setVelo(velo); - e.setLenTick(drumMap[instr].len); - return new DEvent(e, curPart); - } - -//--------------------------------------------------------- -// resizeItem -//--------------------------------------------------------- - -void DrumCanvas::resizeItem(CItem* item, bool) - { - DEvent* nevent = (DEvent*) item; - Event ev = nevent->event(); - // Indicate do undo, and do not do port controller values and clone parts. - //audio->msgDeleteEvent(ev, nevent->part()); - audio->msgDeleteEvent(ev, nevent->part(), true, false, false); - } - -//--------------------------------------------------------- -// newItem -//--------------------------------------------------------- - -void DrumCanvas::newItem(CItem* item, bool noSnap) - { - DEvent* nevent = (DEvent*) item; - Event event = nevent->event(); - int x = item->x(); - if (!noSnap) - x = editor->rasterVal(x); - event.setTick(x - nevent->part()->tick()); - //int npitch = drumMap[y2pitch(item->y())].enote; - 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; - // Added by T356. Only do notes. - if(!ev.isNote()) - continue; - - if (ev.pitch() == npitch) { - // Indicate do undo, and do not do port controller values and clone parts. - //audio->msgDeleteEvent(ev, nevent->part()); - audio->msgDeleteEvent(ev, nevent->part(), true, false, false); - return; - } - } - - // Added by T356. - Part* part = nevent->part(); - song->startUndo(); - int modified=SC_EVENT_MODIFIED; - int diff = event.endTick()-part->lenTick(); - if (diff > 0) {// too short part? extend it - //printf("extend Part!\n"); - Part* newPart = part->clone(); - newPart->setLenTick(newPart->lenTick()+diff); - // Indicate no undo, and do port controller values but not clone parts. - //audio->msgChangePart(part, newPart,false); - audio->msgChangePart(part, newPart, false, true, false); - modified=modified|SC_PART_MODIFIED; - part = newPart; // reassign - } - // Indicate no undo, and do not do port controller values and clone parts. - //audio->msgAddEvent(event, part,false); - audio->msgAddEvent(event, part, false, false, false); - song->endUndo(modified); - - //audio->msgAddEvent(event, nevent->part()); - } - -//--------------------------------------------------------- -// deleteItem -//--------------------------------------------------------- - -bool DrumCanvas::deleteItem(CItem* item) - { - Event ev = ((DEvent*)item)->event(); - // Indicate do undo, and do not do port controller values and clone parts. - //audio->msgDeleteEvent(ev, ((DEvent*)item)->part()); - audio->msgDeleteEvent(ev, ((DEvent*)item)->part(), true, false, false); - return false; - } - -//--------------------------------------------------------- -// drawItem -//--------------------------------------------------------- - -void DrumCanvas::drawItem(QPainter&p, const CItem*item, const QRect& rect) - { - DEvent* e = (DEvent*) item; - int x = 0, y = 0; - x = mapx(item->pos().x()); - y = mapy(item->pos().y()); - QPolygon pa(4); - pa.setPoint(0, x - CARET2, y); - pa.setPoint(1, x, y - CARET2); - pa.setPoint(2, x + CARET2, y); - pa.setPoint(3, x, y + CARET2); - QRect r(pa.boundingRect()); - r = r.intersect(rect); - if(!r.isValid()) - return; - - p.setPen(Qt::black); - - if (e->part() != curPart) - { - if(item->isMoving()) - p.setBrush(Qt::gray); - else if(item->isSelected()) - p.setBrush(Qt::black); - else - p.setBrush(Qt::lightGray); - } - else if (item->isMoving()) { - p.setBrush(Qt::gray); - } - else if (item->isSelected()) - { - p.setBrush(Qt::black); - } - else - { - int velo = e->event().velo(); - DrumMap* dm = &drumMap[y2pitch(y)]; //Get the drum item - QColor color; - 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); - p.setBrush(color); - } - - p.drawPolygon(pa); - } - -//--------------------------------------------------------- -// drawMoving -// draws moving items -//--------------------------------------------------------- - -void DrumCanvas::drawMoving(QPainter& p, const CItem* item, const QRect& rect) - { - //if(((DEvent*)item)->part() != curPart) - // return; - //if(!item->isMoving()) - // return; - QPolygon pa(4); - QPoint pt = map(item->mp()); - int x = pt.x(); - int y = pt.y(); - pa.setPoint(0, x-CARET2, y + TH/2); - pa.setPoint(1, x, y + TH/2+CARET2); - pa.setPoint(2, x+CARET2, y + TH/2); - pa.setPoint(3, x, y + (TH-CARET)/2); - QRect mr(pa.boundingRect()); - mr = mr.intersect(rect); - if(!mr.isValid()) - return; - p.setPen(Qt::black); - p.setBrush(Qt::black); - p.drawPolygon(pa); - } - -//--------------------------------------------------------- -// drawCanvas -//--------------------------------------------------------- - -extern void drawTickRaster(QPainter& p, int, int, int, int, int); - -void DrumCanvas::drawCanvas(QPainter& p, const QRect& rect) - { - int x = rect.x(); - int y = rect.y(); - int w = rect.width(); - int h = rect.height(); - - //--------------------------------------------------- - // horizontal lines - //--------------------------------------------------- - - int yy = ((y-1) / TH) * TH + TH; - for (; yy < y + h; yy += TH) { - p.setPen(Qt::gray); - p.drawLine(x, yy, x + w, yy); - } - - //--------------------------------------------------- - // vertical lines - //--------------------------------------------------- - - drawTickRaster(p, x, y, w, h, editor->raster()); - } - -//--------------------------------------------------------- -// y2pitch -//--------------------------------------------------------- - -int DrumCanvas::y2pitch(int y) const - { - int pitch = y/TH; - if (pitch >= DRUM_MAPSIZE) - pitch = DRUM_MAPSIZE-1; - return pitch; - } - -//--------------------------------------------------------- -// pitch2y -//--------------------------------------------------------- - -int DrumCanvas::pitch2y(int pitch) const - { - return pitch * TH; - } - -//--------------------------------------------------------- -// cmd -//--------------------------------------------------------- - -void DrumCanvas::cmd(int cmd) - { - switch(cmd) { - case CMD_CUT: - copy(); - song->startUndo(); - for (iCItem i = items.begin(); i != items.end(); ++i) { - if (!i->second->isSelected()) - continue; - DEvent* e = (DEvent*)(i->second); - Event event = e->event(); - // Indicate no undo, and do not do port controller values and clone parts. - //audio->msgDeleteEvent(event, e->part(), false); - audio->msgDeleteEvent(event, e->part(), false, false, false); - } - song->endUndo(SC_EVENT_REMOVED); - break; - case CMD_COPY: - copy(); - break; - case CMD_PASTE: - paste(); - break; - case CMD_SELECT_ALL: // select all - for (iCItem k = items.begin(); k != items.end(); ++k) { - if (!k->second->isSelected()) - selectItem(k->second, true); - } - break; - case CMD_SELECT_NONE: // select none - deselectAll(); - break; - case CMD_SELECT_INVERT: // invert selection - for (iCItem k = items.begin(); k != items.end(); ++k) { - selectItem(k->second, !k->second->isSelected()); - } - break; - case CMD_SELECT_ILOOP: // select inside loop - for (iCItem k = items.begin(); k != items.end(); ++k) { - DEvent* nevent =(DEvent*)(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); - } - break; - case CMD_SELECT_OLOOP: // select outside loop - for (iCItem k = items.begin(); k != items.end(); ++k) { - DEvent* nevent = (DEvent*)(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); - } - break; - case CMD_SELECT_PREV_PART: // select previous part - { - Part* pt = editor->curCanvasPart(); - Part* newpt = pt; - PartList* pl = editor->parts(); - for(iPart ip = pl->begin(); ip != pl->end(); ++ip) - if(ip->second == pt) - { - if(ip == pl->begin()) - ip = pl->end(); - --ip; - newpt = ip->second; - break; - } - if(newpt != pt) - editor->setCurCanvasPart(newpt); - } - break; - case CMD_SELECT_NEXT_PART: // select next part - { - Part* pt = editor->curCanvasPart(); - Part* newpt = pt; - PartList* pl = editor->parts(); - for(iPart ip = pl->begin(); ip != pl->end(); ++ip) - if(ip->second == pt) - { - ++ip; - if(ip == pl->end()) - ip = pl->begin(); - newpt = ip->second; - break; - } - if(newpt != pt) - editor->setCurCanvasPart(newpt); - } - break; - case CMD_DEL: - if (selectionSize()) { - song->startUndo(); - for (iCItem i = items.begin(); i != items.end(); ++i) { - if (!i->second->isSelected()) - continue; - Event ev = i->second->event(); - // Indicate no undo, and do not do port controller values and clone parts. - //audio->msgDeleteEvent(ev, i->second->part(), false); - audio->msgDeleteEvent(ev, i->second->part(), false, false, false); - } - song->endUndo(SC_EVENT_REMOVED); - } - return; - - case CMD_SAVE: - case CMD_LOAD: - printf("DrumCanvas:: cmd not implemented %d\n", cmd); - break; - - case CMD_FIXED_LEN: //Set notes to the length specified in the drummap - if (!selectionSize()) - break; - song->startUndo(); - for (iCItem k = items.begin(); k != items.end(); ++k) { - if (k->second->isSelected()) { - DEvent* devent = (DEvent*)(k->second); - Event event = devent->event(); - Event newEvent = event.clone(); - newEvent.setLenTick(drumMap[event.pitch()].len); - // Indicate no undo, and do not do port controller values and clone parts. - //audio->msgChangeEvent(event, newEvent, devent->part() , false); - audio->msgChangeEvent(event, newEvent, devent->part(), false, false, false); - } - } - song->endUndo(SC_EVENT_MODIFIED); - break; - case CMD_LEFT: - { - int spos = pos[0]; - if(spos > 0) - { - spos -= 1; // Nudge by -1, then snap down with raster1. - spos = AL::sigmap.raster1(spos, editor->rasterStep(pos[0])); - } - if(spos < 0) - spos = 0; - Pos p(spos,true); - song->setPos(0, p, true, true, true); - } - break; - case CMD_RIGHT: - { - int spos = AL::sigmap.raster2(pos[0] + 1, editor->rasterStep(pos[0])); // Nudge by +1, then snap up with raster2. - Pos p(spos,true); - song->setPos(0, p, true, true, true); - } - break; - case CMD_LEFT_NOSNAP: - { - int spos = pos[0] - editor->rasterStep(pos[0]); - if (spos < 0) - spos = 0; - Pos p(spos,true); - song->setPos(0, p, true, true, true); //CDW - } - break; - case CMD_RIGHT_NOSNAP: - { - Pos p(pos[0] + editor->rasterStep(pos[0]), true); - //if (p > part->tick()) - // p = part->tick(); - song->setPos(0, p, true, true, true); //CDW - } - break; - case CMD_MODIFY_VELOCITY: - { - Velocity w; - w.setRange(0); //TODO: Make this work! Probably put _to & _toInit in ecanvas instead - if (!w.exec()) - break; - int range = w.range(); // all, selected, looped, sel+loop - int rate = w.rateVal(); - int offset = w.offsetVal(); - - song->startUndo(); - for (iCItem k = items.begin(); k != items.end(); ++k) { - DEvent* devent = (DEvent*)(k->second); - Event event = devent->event(); - if (event.type() != Note) - continue; - unsigned tick = event.tick(); - bool selected = k->second->isSelected(); - bool inLoop = (tick >= song->lpos()) && (tick < song->rpos()); - - if ((range == 0) - || (range == 1 && selected) - || (range == 2 && inLoop) - || (range == 3 && 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); - // Indicate no undo, and do not do port controller values and clone parts. - //audio->msgChangeEvent(event, newEvent, devent->part(), false); - audio->msgChangeEvent(event, newEvent, devent->part(), false, false, false); - } - } - } - song->endUndo(SC_EVENT_MODIFIED); - } - break; - } - updateSelection(); - redraw(); - } - -/* -//--------------------------------------------------------- -// getTextDrag -//--------------------------------------------------------- - -Q3TextDrag* DrumCanvas::getTextDrag(QWidget* parent) - { - //--------------------------------------------------- - // generate event list from selected events - //--------------------------------------------------- - - EventList el; - unsigned startTick = MAXINT; - for (iCItem i = items.begin(); i != items.end(); ++i) { - if (!i->second->isSelected()) - continue; - DEvent* ne = (DEvent*)(i->second); - Event e = ne->event(); - if (startTick == MAXINT) - startTick = e.tick(); - el.add(e); - } - - //--------------------------------------------------- - // write events as XML into tmp file - //--------------------------------------------------- - - FILE* tmp = tmpfile(); - if (tmp == 0) { - fprintf(stderr, "EventCanvas::copy() fopen failed: %s\n", - strerror(errno)); - return 0; - } - Xml xml(tmp); - - int level = 0; - for (ciEvent e = el.begin(); e != el.end(); ++e) - e->second.write(level, xml, -startTick); - - //--------------------------------------------------- - // read tmp file into QTextDrag Object - //--------------------------------------------------- - - fflush(tmp); - struct stat f_stat; - if (fstat(fileno(tmp), &f_stat) == -1) { - fprintf(stderr, "EventCanvas::copy() fstat failes:<%s>\n", - strerror(errno)); - fclose(tmp); - return 0; - } - int n = f_stat.st_size; - char* fbuf = (char*)mmap(0, n+1, PROT_READ|PROT_WRITE, - MAP_PRIVATE, fileno(tmp), 0); - fbuf[n] = 0; - Q3TextDrag* drag = new Q3TextDrag(QString(fbuf), parent); - drag->setSubtype("eventlist"); - munmap(fbuf, n); - fclose(tmp); - return drag; - } -*/ - -//--------------------------------------------------------- -// copy -// cut copy paste -//--------------------------------------------------------- - -void DrumCanvas::copy() - { - //QDrag* drag = getTextDrag(); - QMimeData* md = getTextDrag(); - - if (md) - QApplication::clipboard()->setMimeData(md, QClipboard::Clipboard); - } - -/* -//--------------------------------------------------------- -// paste -//--------------------------------------------------------- - -int DrumCanvas::pasteAt(const QString& pt, int pos) - { - QByteArray ba = pt.toLatin1(); - const char* p = ba.constData(); - Xml xml(p); - - // Added by T356. - int modified = SC_EVENT_INSERTED; - - song->startUndo(); - for (;;) { - Xml::Token token = xml.parse(); - QString tag = xml.s1(); - switch (token) { - case Xml::Error: - case Xml::End: - song->endUndo(modified); - return pos; - case Xml::TagStart: - if (tag == "event") { - Event e(Note); - e.read(xml); - - // Added by T356. - int tick = e.tick() + pos - curPart->tick(); - if (tick<0) { - printf("DrumCanvas::pasteAt ERROR: trying to add event before current part!\n"); - song->endUndo(SC_EVENT_INSERTED); - //delete el; - return pos; - } - e.setTick(tick); - int diff = e.endTick() - curPart->lenTick(); - if (diff > 0) {// too short part? extend it - Part* newPart = curPart->clone(); - newPart->setLenTick(newPart->lenTick()+diff); - // Indicate no undo, and do port controller values but not clone parts. - audio->msgChangePart(curPart, newPart, false, true, false); - - modified=modified|SC_PART_MODIFIED; - curPart = newPart; // reassign - } - - // Indicate no undo, and do not do port controller values and clone parts. - audio->msgAddEvent(e, curPart, false, false, false); - } - else - xml.unknown("DCanvas::pasteAt"); - break; - case Xml::TagEnd: - default: - break; - } - } - } -*/ - -//--------------------------------------------------------- -// paste -// paste events -//--------------------------------------------------------- - -void DrumCanvas::paste() - { -/* -// Q3CString subtype("eventlist"); // ddskrjo - QString subtype("eventlist"); - QMimeSource* ms = QApplication::clipboard()->data(); - QString pt; - if (!Q3TextDrag::decode(ms, pt, subtype)) { - printf("cannot paste: bad data type\n"); - return; - } - pasteAt(pt, song->cpos()); -*/ - QString stype("x-muse-eventlist"); - - //QString s = QApplication::clipboard()->text(stype, QClipboard::Selection); - QString s = QApplication::clipboard()->text(stype, QClipboard::Clipboard); // TODO CHECK Tim. - - pasteAt(s, song->cpos()); - } - -//--------------------------------------------------------- -// startDrag -//--------------------------------------------------------- - -void DrumCanvas::startDrag(CItem* /* item*/, bool copymode) - { - QMimeData* md = getTextDrag(); - //QDrag* drag = getTextDrag(); - - if (md) { -// QApplication::clipboard()->setData(drag, QClipboard::Clipboard); // This line NOT enabled in muse-1 - //QApplication::clipboard()->setMimeData(md); // TODO CHECK Tim. - //QApplication::clipboard()->setMimeData(drag->mimeData()); // - - // "Note that setMimeData() assigns ownership of the QMimeData object to the QDrag object. - // The QDrag must be constructed on the heap with a parent QWidget to ensure that Qt can - // clean up after the drag and drop operation has been completed. " - QDrag* drag = new QDrag(this); - drag->setMimeData(md); - - if (copymode) - drag->exec(Qt::CopyAction); - else - drag->exec(Qt::MoveAction); - } - } - -//--------------------------------------------------------- -// dragEnterEvent -//--------------------------------------------------------- - -void DrumCanvas::dragEnterEvent(QDragEnterEvent* event) - { - ///event->accept(Q3TextDrag::canDecode(event)); - event->acceptProposedAction(); // TODO CHECK Tim. - } - -//--------------------------------------------------------- -// dragMoveEvent -//--------------------------------------------------------- - -void DrumCanvas::dragMoveEvent(QDragMoveEvent*) - { - //printf("drag move %x\n", this); // REMOVE Tim - //event->acceptProposedAction(); - } - -//--------------------------------------------------------- -// dragLeaveEvent -//--------------------------------------------------------- - -void DrumCanvas::dragLeaveEvent(QDragLeaveEvent*) - { - //printf("drag leave\n"); // REMOVE Tim - //event->acceptProposedAction(); - } - -/* -//--------------------------------------------------------- -// dropEvent -//--------------------------------------------------------- - -void DrumCanvas::viewDropEvent(QDropEvent* event) - { - QString text; - if (event->source() == this) { - printf("local DROP\n"); // REMOVE Tim - //event->acceptProposedAction(); - //event->ignore(); // TODO CHECK Tim. - return; - } - //if (event->mimeData()->hasText()) { - if (event->mimeData()->hasFormat("text/x-muse-eventlist")) { - - //text = event->mimeData()->text(); - text = QString(event->mimeData()->data("text/x-muse-eventlist")); - -// printf("drop <%s>\n", text.ascii()); - int x = editor->rasterVal(event->pos().x()); - if (x < 0) - x = 0; - pasteAt(text, x); - //event->accept(); // TODO - } - else { - printf("cannot decode drop\n"); - //event->acceptProposedAction(); - //event->ignore(); // TODO CHECK Tim. - } - } -*/ - -//--------------------------------------------------------- -// keyPressed -//--------------------------------------------------------- - -void DrumCanvas::keyPressed(int index, bool) - { - int port = drumMap[index].port; - int channel = drumMap[index].channel; - int pitch = drumMap[index].anote; - - // play note: - MidiPlayEvent e(0, port, channel, 0x90, pitch, 127); - audio->msgPlayMidiEvent(&e); - } - -//--------------------------------------------------------- -// keyReleased -//--------------------------------------------------------- - -void DrumCanvas::keyReleased(int index, bool) - { - int port = drumMap[index].port; - int channel = drumMap[index].channel; - int pitch = drumMap[index].anote; - - // release note: - MidiPlayEvent e(0, port, channel, 0x90, pitch, 0); - audio->msgPlayMidiEvent(&e); - } - -//--------------------------------------------------------- -// mapChanged -//--------------------------------------------------------- - -void DrumCanvas::mapChanged(int spitch, int dpitch) - { - //TODO: Circumvent undo behaviour, since this isn't really a true change of the events, - // but merely a change in pitch because the pitch relates to the order of the dlist. - // Right now the sequencer spits out internalError: undoOp without startUndo() if start/stopundo is there, which is misleading - // If start/stopundo is there, undo misbehaves since it doesn't undo but messes things up - // Other solution: implement a specific undo-event for this (SC_DRUMMAP_MODIFIED or something) which undoes movement of - // dlist-items (ml) - - std::vector< std::pair<Part*, Event*> > delete_events; - std::vector< std::pair<Part*, Event> > add_events; - - typedef std::vector< std::pair<Part*, Event*> >::iterator idel_ev; - typedef std::vector< std::pair<Part*, Event> >::iterator iadd_ev; - - /* - class delete_events : public std::vector< Part*, Event* > - { - public: - idel_ev find(Part* p, Event* e) - { - - }; - }; - class add_events : public std::vector< Part*, Event > - { - public: - iadd_ev find(Part* p, Event& e) - { - - }; - }; - */ - - MidiTrackList* tracks = song->midis(); - for (ciMidiTrack t = tracks->begin(); t != tracks->end(); t++) { - MidiTrack* curTrack = *t; - if (curTrack->type() != Track::DRUM) - continue; - - MidiPort* mp = &midiPorts[curTrack->outPort()]; - PartList* parts= curTrack->parts(); - for (iPart part = parts->begin(); part != parts->end(); ++part) { - EventList* events = part->second->events(); - Part* thePart = part->second; - for (iEvent i = events->begin(); i != events->end(); ++i) { - Event event = i->second; - if(event.type() != Controller && event.type() != Note) - continue; - int pitch = event.pitch(); - bool drc = false; - // Is it a drum controller event, according to the track port's instrument? - if(event.type() == Controller && mp->drumController(event.dataA())) - { - drc = true; - pitch = event.dataA() & 0x7f; - } - - if (pitch == spitch) { - Event* spitch_event = &(i->second); - delete_events.push_back(std::pair<Part*, Event*>(thePart, spitch_event)); - Event newEvent = spitch_event->clone(); - if(drc) - newEvent.setA((newEvent.dataA() & ~0xff) | dpitch); - else - newEvent.setPitch(dpitch); - add_events.push_back(std::pair<Part*, Event>(thePart, newEvent)); - } - else if (pitch == dpitch) { - Event* dpitch_event = &(i->second); - delete_events.push_back(std::pair<Part*, Event*>(thePart, dpitch_event)); - Event newEvent = dpitch_event->clone(); - if(drc) - newEvent.setA((newEvent.dataA() & ~0xff) | spitch); - else - newEvent.setPitch(spitch); - add_events.push_back(std::pair<Part*, Event>(thePart, newEvent)); - } - } - } - } - - song->startUndo(); - for (idel_ev i = delete_events.begin(); i != delete_events.end(); i++) { - //std::pair<Part*, Event*> pair = *i; - //Part* thePart = pair.first; - //Event* theEvent = pair.second; - Part* thePart = (*i).first; - Event* theEvent = (*i).second; - // Indicate no undo, and do port controller values but not clone parts. - //audio->msgDeleteEvent(*theEvent, thePart, false); - audio->msgDeleteEvent(*theEvent, thePart, false, true, false); - } - - DrumMap dm = drumMap[spitch]; - drumMap[spitch] = drumMap[dpitch]; - drumMap[dpitch] = dm; - drumInmap[int(drumMap[spitch].enote)] = spitch; - drumOutmap[int(drumMap[int(spitch)].anote)] = spitch; - drumInmap[int(drumMap[int(dpitch)].enote)] = dpitch; - drumOutmap[int(drumMap[int(dpitch)].anote)] = dpitch; - - for (iadd_ev i = add_events.begin(); i != add_events.end(); i++) { - //std::pair<Part*, Event> pair = *i; - //Part* thePart = pair.first; - //Event& theEvent = pair.second; - Part* thePart = (*i).first; - Event& theEvent = (*i).second; - // Indicate no undo, and do port controller values but not clone parts. - //audio->msgAddEvent(theEvent, thePart, false); - audio->msgAddEvent(theEvent, thePart, false, true, false); - } - - song->endUndo(SC_EVENT_MODIFIED); - song->update(SC_DRUMMAP); - } - -//--------------------------------------------------------- -// 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; - DEvent* e = (DEvent*)(i->second); - Event event = e->event(); - if (event.type() != Note) - continue; - - MidiPart* part = (MidiPart*)(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); - // Indicate do not do port controller values and clone parts. - //song->undoOp(UndoOp::ModifyEvent, newEvent, event, part); - song->undoOp(UndoOp::ModifyEvent, newEvent, event, part, false, false); - } - song->endUndo(SC_EVENT_MODIFIED); - audio->msgIdle(false); - } - -//--------------------------------------------------------- -// curPartChanged -//--------------------------------------------------------- - -void DrumCanvas::curPartChanged() - { - editor->setWindowTitle(getCaption()); - } - |