diff options
Diffstat (limited to 'attic/muse2-oom/muse2/muse/midiedit')
20 files changed, 9376 insertions, 0 deletions
diff --git a/attic/muse2-oom/muse2/muse/midiedit/CMakeLists.txt b/attic/muse2-oom/muse2/muse/midiedit/CMakeLists.txt new file mode 100644 index 00000000..94bed2b2 --- /dev/null +++ b/attic/muse2-oom/muse2/muse/midiedit/CMakeLists.txt @@ -0,0 +1,105 @@ +#============================================================================= +# 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. +#============================================================================= + +## +## Expand Qt macros in source files +## +QT4_WRAP_CPP ( midiedit_mocs + # gatetime.h + # midicmd.h + # midieditor.h + # miditracker.h + # trackpattern.h + # velocity.h + dcanvas.h + dlist.h + drumedit.h + ecanvas.h + piano.h + pianoroll.h + prcanvas.h + quantconfig.h + ) + +## +## List of source files to compile +## +file (GLOB midiedit_source_files + # citem.cpp + # gatetime.cpp + # midicmd.cpp + # midieditor.cpp + # miditracker.cpp + # trackpattern.cpp + # velocity.cpp + dcanvas.cpp + dlist.cpp + drumedit.cpp + drummap.cpp + ecanvas.cpp + piano.cpp + pianoroll.cpp + prcanvas.cpp + quantconfig.cpp + ) + +## +## Define target +## +add_library ( midiedit SHARED + ${midiedit_source_files} + ${midiedit_mocs} + ) + +## +## Append to the list of translations +## +set (FILES_TO_TRANSLATE + ${FILES_TO_TRANSLATE} + ${midiedit_source_files} + CACHE INTERNAL "" + ) + +## +## Compilation flags and target name +## +set_target_properties( midiedit + PROPERTIES COMPILE_FLAGS "-include ${PROJECT_BINARY_DIR}/all.h -fPIC" + OUTPUT_NAME muse_midiedit + ) + +## +## Linkage +## +target_link_libraries ( midiedit + ${QT_LIBRARIES} + al + ctrl + icons + widgets + ctrl + ) + +## +## Install location +## +install(TARGETS midiedit + DESTINATION ${MusE_MODULES_DIR} + ) diff --git a/attic/muse2-oom/muse2/muse/midiedit/cmd.h b/attic/muse2-oom/muse2/muse/midiedit/cmd.h new file mode 100644 index 00000000..8339b7ae --- /dev/null +++ b/attic/muse2-oom/muse2/muse/midiedit/cmd.h @@ -0,0 +1,28 @@ +//========================================================= +// MusE +// Linux Music Editor +// $Id: cmd.h,v 1.1.1.1 2003/10/27 18:52:20 wschweer Exp $ +// (C) Copyright 2000 Werner Schweer (ws@seh.de) +//========================================================= + +#ifndef __CMD_H__ +#define __CMD_H__ + +#define CMD_LEFT 0 +#define CMD_RIGHT 1 +#define CMD_INSERT 2 +#define CMD_DELETE 3 +#define CMD_1 4 +#define CMD_2 5 +#define CMD_3 6 +#define CMD_4 7 +#define CMD_5 8 +#define CMD_6 9 +#define CMD_7 10 +#define CMD_T 11 +#define CMD_period 12 +#define CMD_LEFT_NOSNAP 13 +#define CMD_RIGHT_NOSNAP 14 + +#endif + diff --git a/attic/muse2-oom/muse2/muse/midiedit/dcanvas.cpp b/attic/muse2-oom/muse2/muse/midiedit/dcanvas.cpp new file mode 100644 index 00000000..34622296 --- /dev/null +++ b/attic/muse2-oom/muse2/muse/midiedit/dcanvas.cpp @@ -0,0 +1,1351 @@ +//========================================================= +// 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()); + } + diff --git a/attic/muse2-oom/muse2/muse/midiedit/dcanvas.h b/attic/muse2-oom/muse2/muse/midiedit/dcanvas.h new file mode 100644 index 00000000..0b81df68 --- /dev/null +++ b/attic/muse2-oom/muse2/muse/midiedit/dcanvas.h @@ -0,0 +1,90 @@ +//========================================================= +// MusE +// Linux Music Editor +// $Id: dcanvas.h,v 1.8.2.2 2009/02/02 21:38:00 terminator356 Exp $ +// (C) Copyright 1999 Werner Schweer (ws@seh.de) +//========================================================= + +#ifndef __DCANVAS_H__ +#define __DCANVAS_H__ + +#include "ecanvas.h" +#include "song.h" + +#define TH 18 + + +class QResizeEvent; +class QDragEnterEvent; +class QDropEvent; +class QDragMoveEvent; +class QDragLeaveEvent; + +class MidiEditor; + +//--------------------------------------------------------- +// DEvent +// ''visual'' Drum Event +//--------------------------------------------------------- + +class DEvent : public CItem { + public: + DEvent(Event e, Part* p); + }; + +class ScrollScale; +class PianoRoll; + +//--------------------------------------------------------- +// DrumCanvas +//--------------------------------------------------------- + +class DrumCanvas : public EventCanvas { + + Q_OBJECT + virtual void drawCanvas(QPainter&, const QRect&); + virtual void drawItem(QPainter&, const CItem*, const QRect&); + virtual void drawMoving(QPainter&, const CItem*, const QRect&); + virtual void moveCanvasItems(CItemList&, int, int, DragType, int*); + // Changed by T356. + //virtual bool moveItem(CItem*, const QPoint&, DragType, int*); + virtual bool moveItem(CItem*, const QPoint&, DragType); + virtual CItem* newItem(const QPoint&, int); + virtual void resizeItem(CItem*, bool); + virtual void newItem(CItem*, bool); + virtual bool deleteItem(CItem*); + + int y2pitch(int y) const; + int pitch2y(int pitch) const; + void copy(); + void paste(); + void startDrag(CItem*, bool copymode); + void dragEnterEvent(QDragEnterEvent* event); + void dragMoveEvent(QDragMoveEvent*); + void dragLeaveEvent(QDragLeaveEvent*); + virtual void addItem(Part*, Event&); + virtual void resizeEvent(QResizeEvent*); + virtual void curPartChanged(); + + signals: + void newWidth(int); + + public slots: + void mapChanged(int, int); + void keyPressed(int, bool); + void keyReleased(int, bool); + + public: + enum { + CMD_CUT, CMD_COPY, CMD_PASTE, CMD_SAVE, CMD_LOAD, CMD_RESET, + CMD_SELECT_ALL, CMD_SELECT_NONE, CMD_SELECT_INVERT, + CMD_SELECT_ILOOP, CMD_SELECT_OLOOP, CMD_SELECT_PREV_PART, CMD_SELECT_NEXT_PART, + CMD_DEL, CMD_FIXED_LEN, CMD_RIGHT, CMD_LEFT, CMD_RIGHT_NOSNAP, CMD_LEFT_NOSNAP, CMD_MODIFY_VELOCITY + }; + DrumCanvas(MidiEditor*, QWidget*, int, int, + const char* name = 0); + void cmd(int); + virtual void modifySelected(NoteInfo::ValType type, int delta); + }; +#endif + diff --git a/attic/muse2-oom/muse2/muse/midiedit/dlist.cpp b/attic/muse2-oom/muse2/muse/midiedit/dlist.cpp new file mode 100644 index 00000000..ee8c8e50 --- /dev/null +++ b/attic/muse2-oom/muse2/muse/midiedit/dlist.cpp @@ -0,0 +1,752 @@ +//========================================================= +// MusE +// Linux Music Editor +// $Id: dlist.cpp,v 1.9.2.7 2009/10/16 21:50:16 terminator356 Exp $ +// (C) Copyright 1999 Werner Schweer (ws@seh.de) +//========================================================= + +#include <QCursor> +#include <QHeaderView> +#include <QMenu> +#include <QMouseEvent> +#include <QPainter> +#include <QPixmap> + +#include <stdio.h> + +#include "audio.h" +#include "pitchedit.h" +#include "midiport.h" +#include "drummap.h" +#include "icons.h" +#include "dlist.h" +#include "song.h" +#include "scrollscale.h" + +// enum DCols { COL_MUTE=0, COL_NAME, COL_QNT, COL_ENOTE, COL_LEN, +// COL_ANOTE, COL_CHANNEL, COL_PORT, +// COL_LV1, COL_LV2, COL_LV3, COL_LV4, COL_NONE=-1}; + +//--------------------------------------------------------- +// draw +//--------------------------------------------------------- + +void DList::draw(QPainter& p, const QRect& rect) + { + int x = rect.x(); + int y = rect.y(); + int w = rect.width(); + int h = rect.height(); + + //--------------------------------------------------- + // Tracks + //--------------------------------------------------- + + p.setPen(Qt::black); + + for (int i = 0; i < DRUM_MAPSIZE; ++i) { + int yy = i * TH; + if (yy+TH < y) + continue; + if (yy > y + h) + break; + DrumMap* dm = &drumMap[i]; +// if (dm->selected) + if (dm == currentlySelected) + p.fillRect(x, yy, w, TH, Qt::yellow); +// else +// p.eraseRect(x, yy, w, TH); + QHeaderView *h = header; + for (int k = 0; k < h->count(); ++k) { + int x = h->sectionPosition(k); + int w = h->sectionSize(k); + ///QRect r = p.xForm(QRect(x+2, yy, w-4, TH)); + QRect r = p.combinedTransform().mapRect(QRect(x+2, yy, w-4, TH)); + QString s; + int align = Qt::AlignVCenter | Qt::AlignHCenter; + + p.save(); + ///p.setWorldXForm(false); + p.setWorldMatrixEnabled(false); + switch (k) { + case COL_VOL: + s.setNum(dm->vol); + break; + case COL_QNT: + s.setNum(dm->quant); + break; + case COL_LEN: + s.setNum(dm->len); + break; + case COL_ANOTE: + s = pitch2string(dm->anote); + break; + case COL_ENOTE: + s = pitch2string(dm->enote); + break; + case COL_LV1: + s.setNum(dm->lv1); + break; + case COL_LV2: + s.setNum(dm->lv2); + break; + case COL_LV3: + s.setNum(dm->lv3); + break; + case COL_LV4: + s.setNum(dm->lv4); + break; + case COL_MUTE: + if (dm->mute) { + p.setPen(Qt::red); + const QPixmap& pm = *muteIcon; + p.drawPixmap( + r.x() + r.width()/2 - pm.width()/2, + r.y() + r.height()/2 - pm.height()/2, + pm); + p.setPen(Qt::black); + } + break; + case COL_NAME: + s = dm->name; + align = Qt::AlignVCenter | Qt::AlignLeft; + break; + case COL_CHANNEL: + s.setNum(dm->channel+1); + break; + case COL_PORT: + s.sprintf("%d:%s", dm->port+1, midiPorts[dm->port].portname().toLatin1().constData()); + align = Qt::AlignVCenter | Qt::AlignLeft; + break; + } + if (!s.isEmpty()) + p.drawText(r, align, s); + p.restore(); + } + } + + //--------------------------------------------------- + // horizontal lines + //--------------------------------------------------- + + p.setPen(Qt::gray); + int yy = (y / TH) * TH; + for (; yy < y + h; yy += TH) { + p.drawLine(x, yy, x + w, yy); + } + + if (drag == DRAG) { + int y = (startY/TH) * TH; + int dy = startY - y; + int yy = curY - dy; + p.setPen(Qt::green); + p.drawLine(x, yy, x + w, yy); + p.drawLine(x, yy+TH, x + w, yy+TH); + p.setPen(Qt::gray); + } + + //--------------------------------------------------- + // vertical Lines + //--------------------------------------------------- + + ///p.setWorldXForm(false); + p.setWorldMatrixEnabled(false); + int n = header->count(); + x = 0; + for (int i = 0; i < n; i++) { + //x += header->sectionSize(i); + x += header->sectionSize(header->visualIndex(i)); + p.drawLine(x, 0, x, height()); + } + ///p.setWorldXForm(true); + p.setWorldMatrixEnabled(true); + } + +//--------------------------------------------------------- +// devicesPopupMenu +//--------------------------------------------------------- + +void DList::devicesPopupMenu(DrumMap* t, int x, int y, bool changeAll) + { + QMenu* p = midiPortsPopup(); + QAction* act = p->exec(mapToGlobal(QPoint(x, y)), 0); + bool doemit = false; + if (act) { + int n = act->data().toInt(); + if (!changeAll) + { + if(n != t->port) + { + audio->msgIdle(true); + //audio->msgRemapPortDrumCtlEvents(getSelectedInstrument(), -1, -1, n); + song->remapPortDrumCtrlEvents(getSelectedInstrument(), -1, -1, n); + audio->msgIdle(false); + t->port = n; + doemit = true; + } + } + else { + audio->msgIdle(true); + // Delete all port controller events. + //audio->msgChangeAllPortDrumCtrlEvents(false); + song->changeAllPortDrumCtrlEvents(false); + + for (int i = 0; i < DRUM_MAPSIZE; i++) + drumMap[i].port = n; + // Add all port controller events. + //audio->msgChangeAllPortDrumCtrlEvents(true); + song->changeAllPortDrumCtrlEvents(true); + + audio->msgIdle(false); + doemit = true; + } + } + delete p; + if(doemit) + { + int instr = getSelectedInstrument(); + if(instr != -1) + //emit curDrumInstrumentChanged(instr); + song->update(SC_DRUMMAP); + } + } + +//--------------------------------------------------------- +// viewMousePressEvent +//--------------------------------------------------------- + +void DList::viewMousePressEvent(QMouseEvent* ev) + { + int x = ev->x(); + int y = ev->y(); + int button = ev->button(); + ///bool shift = ev->state() & Qt::ShiftButton; + bool shift = ev->modifiers() & Qt::ShiftModifier; + unsigned pitch = y / TH; + DrumMap* dm = &drumMap[pitch]; + + setCurDrumInstrument(pitch); + + startY = y; + sPitch = pitch; + drag = START_DRAG; + + DCols col = DCols(x2col(x)); + + int val; + int incVal = 0; + if (button == Qt::RightButton) + incVal = 1; + else if (button == Qt::MidButton) + incVal = -1; + + // Check if we're already editing anything and have pressed the mouse + // elsewhere + // In that case, treat it as if a return was pressed + + if (button == Qt::LeftButton) { + if (((editEntry && editEntry != dm) || col != selectedColumn) && editEntry != 0) { + returnPressed(); + } + } + + switch (col) { + case COL_NONE: + break; + case COL_MUTE: + if (button == Qt::LeftButton) + dm->mute = !dm->mute; + break; + case COL_PORT: + if (button == Qt::RightButton) { + ///bool changeAll = ev->state() & Qt::ControlButton; + bool changeAll = ev->modifiers() & Qt::ControlModifier; + devicesPopupMenu(dm, mapx(x), mapy(pitch * TH), changeAll); + } + break; + case COL_VOL: + val = dm->vol + incVal; + if (val < 0) + val = 0; + else if (val > 200) + val = 200; + dm->vol = (unsigned char)val; + break; + case COL_QNT: + dm->quant += incVal; + // ?? range + break; + case COL_ENOTE: + val = dm->enote + incVal; + if (val < 0) + val = 0; + else if (val > 127) + val = 127; + //Check if there is any other drumMap with the same inmap value (there should be one (and only one):-) + //If so, switch the inmap between the instruments + for (int i=0; i<DRUM_MAPSIZE; i++) { + if (drumMap[i].enote == val && &drumMap[i] != dm) { + drumInmap[int(dm->enote)] = i; + drumMap[i].enote = dm->enote; + break; + } + } + //TODO: Set all the notes on the track with pitch=dm->enote to pitch=val + dm->enote = val; + drumInmap[val] = pitch; + break; + case COL_LEN: + val = dm->len + incVal; + if (val < 0) + val = 0; + dm->len = val; + break; + case COL_ANOTE: + val = dm->anote + incVal; + if (val < 0) + val = 0; + else if (val > 127) + val = 127; + if(val != dm->anote) + { + audio->msgIdle(true); + //audio->msgRemapPortDrumCtlEvents(pitch, val, -1, -1); + song->remapPortDrumCtrlEvents(pitch, val, -1, -1); + audio->msgIdle(false); + dm->anote = val; + song->update(SC_DRUMMAP); + } + emit keyPressed(pitch, shift);//(dm->anote, shift); + break; + case COL_CHANNEL: + val = dm->channel + incVal; + if (val < 0) + val = 0; + else if (val > 127) + val = 127; + + ///if (ev->state() & Qt::ControlButton) { + if (ev->modifiers() & Qt::ControlModifier) { + audio->msgIdle(true); + // Delete all port controller events. + //audio->msgChangeAllPortDrumCtrlEvents(false); + song->changeAllPortDrumCtrlEvents(false, true); + + for (int i = 0; i < DRUM_MAPSIZE; i++) + drumMap[i].channel = val; + // Add all port controller events. + //audio->msgChangeAllPortDrumCtrlEvents(true); + song->changeAllPortDrumCtrlEvents(true, true); + audio->msgIdle(false); + song->update(SC_DRUMMAP); + } + else + { + if(val != dm->channel) + { + audio->msgIdle(true); + //audio->msgRemapPortDrumCtlEvents(pitch, -1, val, -1); + song->remapPortDrumCtrlEvents(pitch, -1, val, -1); + audio->msgIdle(false); + dm->channel = val; + song->update(SC_DRUMMAP); + } + } + break; + case COL_LV1: + val = dm->lv1 + incVal; + if (val < 0) + val = 0; + else if (val > 127) + val = 127; + dm->lv1 = val; + break; + case COL_LV2: + val = dm->lv2 + incVal; + if (val < 0) + val = 0; + else if (val > 127) + val = 127; + dm->lv2 = val; + break; + case COL_LV3: + val = dm->lv3 + incVal; + if (val < 0) + val = 0; + else if (val > 127) + val = 127; + dm->lv3 = val; + break; + case COL_LV4: + val = dm->lv4 + incVal; + if (val < 0) + val = 0; + else if (val > 127) + val = 127; + dm->lv4 = val; + break; + case COL_NAME: + emit keyPressed(pitch, shift); //Mapping done on other side, send index + break; +#if 0 + case COL_CHANNEL: + { + int channel = t->channel(); + if (button == Qt::RightButton) { + if (channel < 15) + ++channel; + } + else if (button == Qt::MidButton) { + if (channel > 0) + --channel; + } + if (channel != t->channel()) { + t->setChannel(channel); + emit channelChanged(); + } + } +#endif + default: + break; + } + redraw(); + } + +//--------------------------------------------------------- +// viewMouseDoubleClickEvent +//--------------------------------------------------------- + +void DList::viewMouseDoubleClickEvent(QMouseEvent* ev) + { + int x = ev->x(); + int y = ev->y(); +// int button = ev->button(); + unsigned pitch = y / TH; + + int section = header->logicalIndexAt(x); + + if ((section == COL_NAME || section == COL_VOL || section == COL_LEN || section == COL_LV1 || + section == COL_LV2 || section == COL_LV3 || section == COL_LV4) && (ev->button() == Qt::LeftButton)) + { + lineEdit(pitch, section); + } + else + viewMousePressEvent(ev); + } + + + +//--------------------------------------------------------- +// lineEdit +//--------------------------------------------------------- +void DList::lineEdit(int line, int section) + { + DrumMap* dm = &drumMap[line]; + editEntry = dm; + if (editor == 0) { + editor = new DLineEdit(this); + connect(editor, SIGNAL(returnPressed()), + SLOT(returnPressed())); + editor->setFrame(true); + } + int colx = mapx(header->sectionPosition(section)); + int colw = rmapx(header->sectionSize(section)); + int coly = mapy(line * TH); + int colh = rmapy(TH); + selectedColumn = section; //Store selected column to have an idea of which one was selected when return is pressed + switch (section) { + case COL_NAME: + editor->setText(dm->name); + break; + + case COL_VOL: { + editor->setText(QString::number(dm->vol)); + break; + } + + case COL_LEN: { + editor->setText(QString::number(dm->len)); + break; + } + + case COL_LV1: + editor->setText(QString::number(dm->lv1)); + break; + + case COL_LV2: + editor->setText(QString::number(dm->lv2)); + break; + + case COL_LV3: + editor->setText(QString::number(dm->lv3)); + break; + + case COL_LV4: + editor->setText(QString::number(dm->lv4)); + break; + } + + // editor->setText(dm->name); + editor->end(false); + editor->setGeometry(colx, coly, colw, colh); + // In all cases but the column name, select all text: + if (section != COL_NAME) + editor->selectAll(); + editor->show(); + editor->setFocus(); + + } + + +//--------------------------------------------------------- +// x2col +//--------------------------------------------------------- + +int DList::x2col(int x) const + { + int col = 0; + int w = 0; + for (; col < header->count(); col++) { + w += header->sectionSize(col); + if (x < w) + break; + } + if (col == header->count()) + return -1; + return header->logicalIndex(col); + } + +//--------------------------------------------------------- +// setCurDrumInstrument +//--------------------------------------------------------- + +void DList::setCurDrumInstrument(int instr) + { + if (instr < 0 || instr >= DRUM_MAPSIZE -1) + return; // illegal instrument + DrumMap* dm = &drumMap[instr]; + if (currentlySelected != dm) { + currentlySelected = &drumMap[instr]; + emit curDrumInstrumentChanged(instr); + song->update(SC_DRUMMAP); + } + } + +//--------------------------------------------------------- +// sizeChange +//--------------------------------------------------------- + +void DList::sizeChange(int, int, int) + { + redraw(); + } + +//--------------------------------------------------------- +// returnPressed +//--------------------------------------------------------- + +void DList::returnPressed() + { + int val = -1; + if (selectedColumn != COL_NAME) + { + ///val = atoi(editor->text().ascii()); + val = atoi(editor->text().toAscii().constData()); + if (selectedColumn != COL_LEN) + { + if(selectedColumn == COL_VOL) + { + if (val > 200) //Check bounds for volume + val = 200; + if (val < 0) + val = 0; + } + else + { + if (val > 127) //Check bounds for lv1-lv4 values + val = 127; + if (val < 0) + val = 0; + } + } + } + + switch(selectedColumn) { + case COL_NAME: + editEntry->name = editor->text(); + break; + + case COL_LEN: + ///editEntry->len = atoi(editor->text().ascii()); + editEntry->len = atoi(editor->text().toAscii().constData()); + break; + + case COL_VOL: + editEntry->vol = val; + break; + + case COL_LV1: + editEntry->lv1 = val; + break; + + case COL_LV2: + editEntry->lv2 = val; + break; + + case COL_LV3: + editEntry->lv3 = val; + break; + + case COL_LV4: + editEntry->lv4 = val; + break; + + default: + printf("Return pressed in unknown column\n"); + break; + } + selectedColumn = -1; + editor->hide(); + editEntry = 0; + setFocus(); + redraw(); + } + +//--------------------------------------------------------- +// moved +//--------------------------------------------------------- + +void DList::moved(int, int, int) + { + redraw(); + } + +//--------------------------------------------------------- +// tracklistChanged +//--------------------------------------------------------- + +void DList::tracklistChanged() + { + } + +//--------------------------------------------------------- +// songChanged +//--------------------------------------------------------- + +void DList::songChanged(int flags) + { + if (flags & SC_DRUMMAP) { + redraw(); + } + } + +//--------------------------------------------------------- +// DList +//--------------------------------------------------------- + +DList::DList(QHeaderView* h, QWidget* parent, int ymag) + : View(parent, 1, ymag) + { + setBg(Qt::white); + if (!h){ + h = new QHeaderView(Qt::Horizontal, parent);} + header = h; + scroll = 0; + //ORCAN- CHECK if really needed: header->setTracking(true); + connect(header, SIGNAL(sectionResized(int,int,int)), + SLOT(sizeChange(int,int,int))); + connect(header, SIGNAL(sectionMoved(int, int,int)), SLOT(moved(int,int,int))); + setFocusPolicy(Qt::StrongFocus); + drag = NORMAL; + editor = 0; + editEntry = 0; + // always select a drum instrument + currentlySelected = &drumMap[0]; + selectedColumn = -1; + } + +//--------------------------------------------------------- +// ~DList +//--------------------------------------------------------- + +DList::~DList() + { +// if (currentlySelected != 0) +// currentlySelected->selected = false; //Reset the global thingie + } + +//--------------------------------------------------------- +// viewMouseMoveEvent +//--------------------------------------------------------- + +void DList::viewMouseMoveEvent(QMouseEvent* ev) + { + curY = ev->y(); + int delta = curY - startY; + switch (drag) { + case START_DRAG: + if (delta < 0) + delta = -delta; + if (delta <= 2) + return; + drag = DRAG; + setCursor(QCursor(Qt::SizeVerCursor)); + redraw(); + break; + case NORMAL: + break; + case DRAG: + redraw(); + break; + } + } + +//--------------------------------------------------------- +// viewMouseReleaseEvent +//--------------------------------------------------------- + +void DList::viewMouseReleaseEvent(QMouseEvent* ev) + { + if (drag == DRAG) { + int y = ev->y(); + unsigned dPitch = y / TH; + setCursor(QCursor(Qt::ArrowCursor)); + currentlySelected = &drumMap[int(dPitch)]; + emit curDrumInstrumentChanged(dPitch); + emit mapChanged(sPitch, dPitch); //Track pitch change done in canvas + } + drag = NORMAL; +//?? redraw(); + if (editEntry) + editor->setFocus(); + int x = ev->x(); + int y = ev->y(); + ///bool shift = ev->state() & Qt::ShiftButton; + bool shift = ev->modifiers() & Qt::ShiftModifier; + unsigned pitch = y / TH; + + DCols col = DCols(x2col(x)); + + switch (col) { + case COL_NAME: + emit keyReleased(pitch, shift); + break; + case COL_ANOTE: + emit keyReleased(pitch, shift); + break; + default: + break; + } + } + +//--------------------------------------------------------- +// getSelectedInstrument +//--------------------------------------------------------- + +int DList::getSelectedInstrument() + { + if (currentlySelected == 0) + return -1; + return drumInmap[int(currentlySelected->enote)]; + } + diff --git a/attic/muse2-oom/muse2/muse/midiedit/dlist.h b/attic/muse2-oom/muse2/muse/midiedit/dlist.h new file mode 100644 index 00000000..f0dda0d4 --- /dev/null +++ b/attic/muse2-oom/muse2/muse/midiedit/dlist.h @@ -0,0 +1,106 @@ +//========================================================= +// MusE +// Linux Music Editor +// $Id: dlist.h,v 1.5.2.3 2009/10/16 21:50:16 terminator356 Exp $ +// (C) Copyright 1999 Werner Schweer (ws@seh.de) +//========================================================= + +#ifndef __DLIST_H__ +#define __DLIST_H__ + +#include <QKeyEvent> +#include <QLineEdit> + +#include "view.h" + +#define TH 18 // normal Track-hight + +class QHeaderView; +class QMouseEvent; +class QPainter; + +class ScrollScale; +class Device; +class QLineEdit; +class DrumMap; + + +//--------------------------------------------------------- +// DLineEdit +//--------------------------------------------------------- +class DLineEdit: public QLineEdit +{ + public: + DLineEdit(QWidget* parent) : QLineEdit(parent) {} + virtual ~DLineEdit() {}; + + virtual void keyPressEvent(QKeyEvent* keyItem) { + if(keyItem->key() == Qt::Key_Escape) { + parentWidget()->setFocus(); + hide(); + } + else + QLineEdit::keyPressEvent(keyItem); + + } +}; + +//--------------------------------------------------------- +// DList +//--------------------------------------------------------- + +class DList : public View { + QHeaderView* header; + ScrollScale* scroll; + QLineEdit* editor; + DrumMap* editEntry; + DrumMap* currentlySelected; + int selectedColumn; + + + int startY; + int curY; + int sPitch; + enum { NORMAL, START_DRAG, DRAG } drag; + + virtual void draw(QPainter& p, const QRect&); + virtual void viewMousePressEvent(QMouseEvent* event); + virtual void viewMouseReleaseEvent(QMouseEvent* event); + virtual void viewMouseDoubleClickEvent(QMouseEvent*); + virtual void viewMouseMoveEvent(QMouseEvent*); + + int x2col(int x) const; + void devicesPopupMenu(DrumMap* t, int x, int y, bool changeAll); + Q_OBJECT + //void setCurDrumInstrument(int n); + + private slots: + void sizeChange(int, int, int); + void returnPressed(); + void moved(int, int, int); + + signals: + void channelChanged(); + void mapChanged(int, int); + void keyPressed(int, bool); + void keyReleased(int, bool); + void curDrumInstrumentChanged(int); + + public slots: + void tracklistChanged(); + void songChanged(int); + public: + void lineEdit(int line, int section); + void setCurDrumInstrument(int n); + DList(QHeaderView*, QWidget* parent, int ymag); + ~DList(); + void setScroll(ScrollScale* s) { scroll = s; } + int getSelectedInstrument(); + +enum DCols { COL_MUTE=0, COL_NAME, COL_VOL, COL_QNT, COL_ENOTE, COL_LEN, + COL_ANOTE, COL_CHANNEL, COL_PORT, + COL_LV1, COL_LV2, COL_LV3, COL_LV4, COL_NONE=-1}; + }; + +#endif // __DLIST_H_ + 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); +} + diff --git a/attic/muse2-oom/muse2/muse/midiedit/drumedit.h b/attic/muse2-oom/muse2/muse/midiedit/drumedit.h new file mode 100644 index 00000000..5d2df9f6 --- /dev/null +++ b/attic/muse2-oom/muse2/muse/midiedit/drumedit.h @@ -0,0 +1,128 @@ +//========================================================= +// MusE +// Linux Music Editor +// $Id: drumedit.h,v 1.9.2.7 2009/11/16 11:29:33 lunar_shuttle Exp $ +// (C) Copyright 1999 Werner Schweer (ws@seh.de) +//========================================================= + +#ifndef __DRUM_EDIT_H__ +#define __DRUM_EDIT_H__ + +#include <values.h> +#include "midieditor.h" +#include "noteinfo.h" +#include "cobject.h" +#include "tools.h" +#include "header.h" +#include "shortcuts.h" +#include "event.h" + +class QCloseEvent; +class QLabel; +class QMenu; +class QKeyEvent; +class QResizeEvent; +class QToolButton; +class QWidget; + +class MidiPart; +class DrumCanvas; +class ScrollScale; +class ScoreConfig; +class MTScale; +class Splitter; +class PartList; +class Toolbar1; +class CtrlCanvas; +class Xml; +class DList; +class Header; +class CtrlEdit; +class Part; +class SNode; + +//--------------------------------------------------------- +// DrumEdit +//--------------------------------------------------------- + +class DrumEdit : public MidiEditor { + Event selEvent; + MidiPart* selPart; + int selTick; + QMenu* menuEdit, *menuFunctions, *menuFile, *menuSelect; + + NoteInfo* info; + QToolButton* srec; + QToolButton* midiin; + EditToolBar* tools2; + + Toolbar1* toolbar; + Splitter* split1; + Splitter* split2; + QWidget* split1w1; + DList* dlist; + Header* header; + QToolBar* tools; + + static int _quantInit, _rasterInit; + static int _widthInit, _heightInit; + static int _dlistWidthInit, _dcanvasWidthInit; + + static int _toInit; //Used in function dialog for applying modification to selection + + QAction *loadAction, *saveAction, *resetAction; + QAction *cutAction, *copyAction, *pasteAction, *deleteAction; + QAction *fixedAction, *veloAction; + QAction *sallAction, *snoneAction, *invAction, *inAction , *outAction; + QAction *prevAction, *nextAction; + + Q_OBJECT + void initShortcuts(); + + virtual void closeEvent(QCloseEvent*); + QWidget* genToolbar(QWidget* parent); + virtual void resizeEvent(QResizeEvent*); + virtual void keyPressEvent(QKeyEvent*); + int _to;//TODO: Make this work + void setHeaderToolTips(); + void setHeaderWhatsThis(); + + private slots: + void setRaster(int); + void setQuant(int); + void noteinfoChanged(NoteInfo::ValType type, int val); + //CtrlEdit* addCtrl(); + void removeCtrl(CtrlEdit* ctrl); + void cmd(int); + void clipboardChanged(); // enable/disable "Paste" + void selectionChanged(); // enable/disable "Copy" & "Paste" + void load(); + void save(); + void reset(); + void setTime(unsigned); + void follow(int); + void newCanvasWidth(int); + void configChanged(); + void songChanged1(int); + + public slots: + void setSelection(int, Event&, Part*); + void soloChanged(bool); // called by Solo button + void execDeliveredScript(int); + void execUserScript(int); + CtrlEdit* addCtrl(); + + virtual void updateHScrollRange(); + signals: + void deleted(unsigned long); + + public: + DrumEdit(PartList*, QWidget* parent = 0, const char* name = 0, unsigned initPos = MAXINT); + virtual ~DrumEdit(); + virtual void readStatus(Xml&); + virtual void writeStatus(int, Xml&) const; + static void readConfiguration(Xml& xml); + static void writeConfiguration(int, Xml&); + }; + +#endif diff --git a/attic/muse2-oom/muse2/muse/midiedit/drummap.cpp b/attic/muse2-oom/muse2/muse/midiedit/drummap.cpp new file mode 100644 index 00000000..46bf2057 --- /dev/null +++ b/attic/muse2-oom/muse2/muse/midiedit/drummap.cpp @@ -0,0 +1,503 @@ +//========================================================= +// MusE +// Linux Music Editor +// $Id: drummap.cpp,v 1.3.2.6 2009/10/29 02:14:37 terminator356 Exp $ +// +// (C) Copyright 1999/2000 Werner Schweer (ws@seh.de) +//========================================================= + +#include "audio.h" +#include "drummap.h" +#include "xml.h" +#include "song.h" + +char drumOutmap[DRUM_MAPSIZE]; +char drumInmap[128]; + +DrumMap drumMap[DRUM_MAPSIZE]; + +//--------------------------------------------------------- +// GM default drum map +//--------------------------------------------------------- + +const DrumMap blankdm = { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 127, 127, false }; + +const DrumMap idrumMap[DRUM_MAPSIZE] = { + { QString("Acoustic Bass Drum"), 100, 16, 32, 9, 0, 70, 90, 127, 110, 35, 35, false }, + { QString("Bass Drum 1"), 100, 16, 32, 9, 0, 70, 90, 127, 110, 36, 36, false }, + { QString("Side Stick"), 100, 16, 32, 9, 0, 70, 90, 127, 110, 37, 37, false }, + { QString("Acoustic Snare"), 100, 16, 32, 9, 0, 70, 90, 127, 110, 38, 38, false }, + { QString("Hand Clap"), 100, 16, 32, 9, 0, 70, 90, 127, 110, 39, 39, false }, + { QString("Electric Snare"), 100, 16, 32, 9, 0, 70, 90, 127, 110, 40, 40, false }, + { QString("Low Floor Tom"), 100, 16, 32, 9, 0, 70, 90, 127, 110, 41, 41, false }, + { QString("Closed Hi-Hat"), 100, 16, 32, 9, 0, 70, 90, 127, 110, 42, 42, false }, + { QString("High Floor Tom"), 100, 16, 32, 9, 0, 70, 90, 127, 110, 43, 43, false }, + { QString("Pedal Hi-Hat"), 100, 16, 32, 9, 0, 70, 90, 127, 110, 44, 44, false }, + { QString("Low Tom"), 100, 16, 32, 9, 0, 70, 90, 127, 110, 45, 45, false }, + { QString("Open Hi-Hat"), 100, 16, 32, 9, 0, 70, 90, 127, 110, 46, 46, false }, + { QString("Low-Mid Tom"), 100, 16, 32, 9, 0, 70, 90, 127, 110, 47, 47, false }, + { QString("Hi-Mid Tom"), 100, 16, 32, 9, 0, 70, 90, 127, 110, 48, 48, false }, + { QString("Crash Cymbal 1"), 100, 16, 32, 9, 0, 70, 90, 127, 110, 49, 49, false }, + { QString("High Tom"), 100, 16, 32, 9, 0, 70, 90, 127, 110, 50, 50, false }, + + { QString("Ride Cymbal 1"), 100, 16, 32, 9, 0, 70, 90, 127, 110, 51, 51, false }, + { QString("Chinese Cymbal"), 100, 16, 32, 9, 0, 70, 90, 127, 110, 52, 52, false }, + { QString("Ride Bell"), 100, 16, 32, 9, 0, 70, 90, 127, 110, 53, 53, false }, + { QString("Tambourine"), 100, 16, 32, 9, 0, 70, 90, 127, 110, 54, 54, false }, + { QString("Splash Cymbal"), 100, 16, 32, 9, 0, 70, 90, 127, 110, 55, 55, false }, + { QString("Cowbell"), 100, 16, 32, 9, 0, 70, 90, 127, 110, 56, 56, false }, + { QString("Crash Cymbal 2"), 100, 16, 32, 9, 0, 70, 90, 127, 110, 57, 57, false }, + { QString("Vibraslap"), 100, 16, 32, 9, 0, 70, 90, 127, 110, 58, 58, false }, + { QString("Ride Cymbal 2"), 100, 16, 32, 9, 0, 70, 90, 127, 110, 59, 59, false }, + { QString("Hi Bongo"), 100, 16, 32, 9, 0, 70, 90, 127, 110, 60, 60, false }, + { QString("Low Bongo"), 100, 16, 32, 9, 0, 70, 90, 127, 110, 61, 61, false }, + { QString("Mute Hi Conga"), 100, 16, 32, 9, 0, 70, 90, 127, 110, 62, 62, false }, + { QString("Open Hi Conga"), 100, 16, 32, 9, 0, 70, 90, 127, 110, 63, 63, false }, + { QString("Low Conga"), 100, 16, 32, 9, 0, 70, 90, 127, 110, 64, 64, false }, + { QString("High Timbale"), 100, 16, 32, 9, 0, 70, 90, 127, 110, 65, 65, false }, + { QString("Low Timbale"), 100, 16, 32, 9, 0, 70, 90, 127, 110, 66, 66, false }, + + { QString("High Agogo"), 100, 16, 32, 9, 0, 70, 90, 127, 110, 67, 67, false }, + { QString("Low Agogo"), 100, 16, 32, 9, 0, 70, 90, 127, 110, 68, 68, false }, + { QString("Cabasa"), 100, 16, 32, 9, 0, 70, 90, 127, 110, 69, 69, false }, + { QString("Maracas"), 100, 16, 32, 9, 0, 70, 90, 127, 110, 70, 70, false }, + { QString("Short Whistle"), 100, 16, 32, 9, 0, 70, 90, 127, 110, 71, 71, false }, + { QString("Long Whistle"), 100, 16, 32, 9, 0, 70, 90, 127, 110, 72, 72, false }, + { QString("Short Guiro"), 100, 16, 32, 9, 0, 70, 90, 127, 110, 73, 73, false }, + { QString("Long Guiro"), 100, 16, 32, 9, 0, 70, 90, 127, 110, 74, 74, false }, + { QString("Claves"), 100, 16, 32, 9, 0, 70, 90, 127, 110, 75, 75, false }, + { QString("Hi Wood Block"), 100, 16, 32, 9, 0, 70, 90, 127, 110, 76, 76, false }, + { QString("Low Wood Block"), 100, 16, 32, 9, 0, 70, 90, 127, 110, 77, 77, false }, + { QString("Mute Cuica"), 100, 16, 32, 9, 0, 70, 90, 127, 110, 78, 78, false }, + { QString("Open Cuica"), 100, 16, 32, 9, 0, 70, 90, 127, 110, 79, 79, false }, + { QString("Mute Triangle"), 100, 16, 32, 9, 0, 70, 90, 127, 110, 80, 80, false }, + { QString("Open Triangle"), 100, 16, 32, 9, 0, 70, 90, 127, 110, 81, 81, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 82, 82, false }, + + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 83, 83, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 84, 84, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 85, 85, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 86, 86, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 87, 87, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 88, 88, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 89, 89, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 90, 90, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 91, 91, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 92, 92, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 93, 93, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 94, 94, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 95, 95, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 96, 96, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 97, 97, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 98, 98, false }, + + /* + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 83, 83, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 84, 84, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 85, 85, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 86, 86, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 87, 87, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 88, 88, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 89, 89, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 90, 90, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 91, 91, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 92, 92, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 93, 93, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 94, 94, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 95, 95, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 96, 96, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 97, 97, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 98, 98, false }, + + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 83, 83, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 84, 84, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 85, 85, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 86, 86, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 87, 87, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 88, 88, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 89, 89, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 90, 90, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 91, 91, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 92, 92, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 93, 93, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 94, 94, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 95, 95, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 96, 96, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 97, 97, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 98, 98, false }, + + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 83, 83, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 84, 84, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 85, 85, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 86, 86, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 87, 87, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 88, 88, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 89, 89, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 90, 90, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 91, 91, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 92, 92, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 93, 93, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 94, 94, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 95, 95, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 96, 96, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 97, 97, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 98, 98, false }, + + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 83, 83, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 84, 84, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 85, 85, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 86, 86, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 87, 87, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 88, 88, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 89, 89, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 90, 90, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 91, 91, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 92, 92, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 93, 93, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 94, 94, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 95, 95, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 96, 96, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 97, 97, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 98, 98, false } + }; + */ + + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 99, 99, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 100, 100, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 101, 101, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 102, 102, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 103, 103, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 104, 104, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 105, 105, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 106, 106, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 107, 107, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 108, 108, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 109, 109, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 110, 110, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 111, 111, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 112, 112, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 113, 113, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 114, 114, false }, + + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 115, 115, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 116, 116, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 117, 117, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 118, 118, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 119, 119, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 120, 120, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 121, 121, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 122, 122, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 123, 123, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 124, 124, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 125, 125, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 126, 126, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 127, 127, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 0, 0, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 1, 1, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 2, 2, false }, + + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 3, 3, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 4, 4, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 5, 5, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 6, 6, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 7, 7, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 8, 8, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 9, 9, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 10, 10, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 11, 11, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 12, 12, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 13, 13, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 14, 14, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 15, 15, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 16, 16, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 17, 17, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 18, 18, false }, + + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 19, 19, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 20, 20, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 21, 21, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 22, 22, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 23, 23, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 24, 24, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 25, 25, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 26, 26, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 27, 27, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 28, 28, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 29, 29, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 30, 30, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 31, 31, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 32, 32, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 33, 33, false }, + { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 34, 34, false } + }; + + +//--------------------------------------------------------- +// initDrumMap +// populate Inmap and Outmap +//--------------------------------------------------------- + +void initDrumMap() + { + for (int i = 0; i < DRUM_MAPSIZE; ++i) { + DrumMap d = drumMap[i]; + //Make sure we're not overwriting any values loaded + //On init, all these values are zero. If so, just set the drummap entry to the initial drummap entry. + if (!(d.vol || d.len || d.channel || d.port || d.lv1 || d.lv2 || d.lv3 || d.lv4 || d.enote || d.anote || d.mute)) + drumMap[i] = idrumMap[i]; + } + //Finally, setup the inMap, outMap-values + memset(drumInmap, 0, sizeof(drumInmap)); + memset(drumOutmap, 0, sizeof(drumOutmap)); + for (int i = 0; i < DRUM_MAPSIZE; ++i) { + drumInmap[(unsigned int)(drumMap[i].enote)] = i; + drumOutmap[(unsigned int)(drumMap[i].anote)] = i; + } + } + +//--------------------------------------------------------- +// resetGMDrumMap +//--------------------------------------------------------- + +void resetGMDrumMap() + { + audio->msgIdle(true); + // Delete all port controller events. + //audio->msgChangeAllPortDrumCtrlEvents(false); + song->changeAllPortDrumCtrlEvents(false); + + for(int i = 0; i < DRUM_MAPSIZE; ++i) + drumMap[i] = idrumMap[i]; + memset(drumInmap, 0, sizeof(drumInmap)); + memset(drumOutmap, 0, sizeof(drumOutmap)); + for (int i = 0; i < DRUM_MAPSIZE; ++i) { + drumInmap[(unsigned int)(drumMap[i].enote)] = i; + drumOutmap[(unsigned int)(drumMap[i].anote)] = i; + } + // Add all port controller events. + //audio->msgChangeAllPortDrumCtrlEvents(true); + song->changeAllPortDrumCtrlEvents(true); + audio->msgIdle(false); + } + +//--------------------------------------------------------- +// operator == +//--------------------------------------------------------- + +//bool const DrumMap::operator==(const DrumMap& map) const +bool DrumMap::operator==(const DrumMap& map) const + { + return + (name == map.name) + && vol == map.vol + && quant == map.quant + && len == map.len + && channel == map.channel + && port == map.port + && lv1 == map.lv1 + && lv2 == map.lv2 + && lv3 == map.lv3 + && lv4 == map.lv4 + && enote == map.enote + && anote == map.anote + && mute == map.mute; + } + +//--------------------------------------------------------- +// writeDrumMap +//--------------------------------------------------------- + +void writeDrumMap(int level, Xml& xml, bool external) + { + xml.tag(level++, "drummap"); + for (int i = 0; i < DRUM_MAPSIZE; ++i) { + DrumMap* dm = &drumMap[i]; + const DrumMap* idm = &idrumMap[i]; + + if (external) { + xml.tag(level++, "entry"); + xml.strTag(level, "name", dm->name); + xml.intTag(level, "vol", dm->vol); + xml.intTag(level, "quant", dm->quant); + xml.intTag(level, "len", dm->len); + xml.intTag(level, "channel", dm->channel); + xml.intTag(level, "port", dm->port); + xml.intTag(level, "lv1", dm->lv1); + xml.intTag(level, "lv2", dm->lv2); + xml.intTag(level, "lv3", dm->lv3); + xml.intTag(level, "lv4", dm->lv4); + xml.intTag(level, "enote", dm->enote); + xml.intTag(level, "anote", dm->anote); + } + else { + // write only, if entry is different from initial entry + if (!external && *dm == *idm) + continue; + xml.tag(level++, "entry idx=\"%d\"", i); + if (dm->name != idm->name) + xml.strTag(level, "name", dm->name); + if (dm->vol != idm->vol) + xml.intTag(level, "vol", dm->vol); + if (dm->quant != idm->quant) + xml.intTag(level, "quant", dm->quant); + if (dm->len != idm->len) + xml.intTag(level, "len", dm->len); + if (dm->channel != idm->channel) + xml.intTag(level, "channel", dm->channel); + if (dm->port != idm->port) + xml.intTag(level, "port", dm->port); + if (dm->lv1 != idm->lv1) + xml.intTag(level, "lv1", dm->lv1); + if (dm->lv2 != idm->lv2) + xml.intTag(level, "lv2", dm->lv2); + if (dm->lv3 != idm->lv3) + xml.intTag(level, "lv3", dm->lv3); + if (dm->lv4 != idm->lv4) + xml.intTag(level, "lv4", dm->lv4); + if (dm->enote != idm->enote) + xml.intTag(level, "enote", dm->enote); + if (dm->anote != idm->anote) + xml.intTag(level, "anote", dm->anote); + if (dm->mute != idm->mute) + xml.intTag(level, "mute", dm->mute); + } + xml.tag(level--, "/entry"); + } + xml.tag(level--, "/drummap"); + } + +//--------------------------------------------------------- +// readDrummapEntry +//--------------------------------------------------------- + +static void readDrummapEntry(Xml& xml, DrumMap* dm) + { + + 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 == "name") + dm->name = xml.parse(QString("name")); + else if (tag == "vol") + dm->vol = (unsigned char)xml.parseInt(); + else if (tag == "quant") + dm->quant = xml.parseInt(); + else if (tag == "len") + dm->len = xml.parseInt(); + else if (tag == "channel") + dm->channel = xml.parseInt(); + else if (tag == "port") + dm->port = xml.parseInt(); + else if (tag == "lv1") + dm->lv1 = xml.parseInt(); + else if (tag == "lv2") + dm->lv2 = xml.parseInt(); + else if (tag == "lv3") + dm->lv3 = xml.parseInt(); + else if (tag == "lv4") + dm->lv4 = xml.parseInt(); + else if (tag == "enote") + dm->enote = xml.parseInt(); + else if (tag == "anote") + dm->anote = xml.parseInt(); + else if (tag == "mute") + dm->mute = xml.parseInt(); + else if (tag == "selected") + //; // dm->selected = xml.parseInt(); + xml.skip(tag); + else + xml.unknown("DrumMapEntry"); + break; + case Xml::Attribut: + if (tag == "idx") { + int idx = xml.s2().toInt() & 0x7f; + dm = &drumMap[idx]; + + } + break; + case Xml::TagEnd: + if (tag == "entry") + { + return; + } + default: + break; + } + } + } + +//--------------------------------------------------------- +// readDrummap +//--------------------------------------------------------- + +void readDrumMap(Xml& xml, bool external) + { + audio->msgIdle(true); + // Delete all port controller events. + //audio->msgChangeAllPortDrumCtrlEvents(false); + song->changeAllPortDrumCtrlEvents(false); + + if (external) { + for (int i = 0; i < DRUM_MAPSIZE; ++i) + drumMap[i] = blankdm; + } + else { + for (int i = 0; i < DRUM_MAPSIZE; ++i) + drumMap[i] = idrumMap[i]; + } + int i = 0; + for (;;) { + Xml::Token token = xml.parse(); + const QString& tag = xml.s1(); + switch (token) { + case Xml::Error: + case Xml::End: + audio->msgIdle(false); + return; + case Xml::TagStart: + if (tag == "entry") { + if(i >= DRUM_MAPSIZE) + { + audio->msgIdle(false); + return; + } + readDrummapEntry(xml, external ? &drumMap[i] : 0); + ++i; + } + else if (tag == "comment") + xml.parse(); + else + xml.unknown("DrumMap"); + break; + case Xml::Attribut: + break; + case Xml::TagEnd: + if (tag == "drummap") { + memset(drumInmap, 0, sizeof(drumInmap)); + memset(drumOutmap, 0, sizeof(drumOutmap)); + for (int i = 0; i < DRUM_MAPSIZE; ++i) { + drumInmap[(unsigned int)(drumMap[i].enote)] = i; + drumOutmap[(unsigned int)(drumMap[i].anote)] = i; + } + // Add all port controller events. + //audio->msgChangeAllPortDrumCtrlEvents(true); + song->changeAllPortDrumCtrlEvents(true); + + audio->msgIdle(false); + return; + } + default: + break; + } + } + // Add all port controller events. + //audio->msgChangeAllPortDrumCtrlEvents(true); + song->changeAllPortDrumCtrlEvents(true); + audio->msgIdle(false); + } + diff --git a/attic/muse2-oom/muse2/muse/midiedit/drummap.h b/attic/muse2-oom/muse2/muse/midiedit/drummap.h new file mode 100644 index 00000000..eb494c9c --- /dev/null +++ b/attic/muse2-oom/muse2/muse/midiedit/drummap.h @@ -0,0 +1,47 @@ +//========================================================= +// MusE +// Linux Music Editor +// $Id: drummap.h,v 1.3.2.3 2009/10/29 02:14:37 terminator356 Exp $ +// +// (C) Copyright 1999/2000 Werner Schweer (ws@seh.de) +//========================================================= + +#ifndef __DRUMMAP_H__ +#define __DRUMMAP_H__ + +class QString; + +class Xml; + +//--------------------------------------------------------- +// DrumMap +//--------------------------------------------------------- + +struct DrumMap { + QString name; + unsigned char vol; // playback volume, percent. + int quant; + int len; // len of event in ticks + int channel; // midi channel + int port; // midi port + char lv1, lv2, lv3, lv4; // velocities + char enote, anote; // input note - output note + bool mute; +// bool selected; + + //bool const operator==(const DrumMap& map) const; + bool operator==(const DrumMap& map) const; + }; + +#define DRUM_MAPSIZE 128 + +extern char drumOutmap[DRUM_MAPSIZE]; +extern char drumInmap[DRUM_MAPSIZE]; +extern DrumMap drumMap[DRUM_MAPSIZE]; +extern void initDrumMap(); +extern void writeDrumMap(int level, Xml& xml, bool external); +extern void readDrumMap(Xml& xml, bool external); +extern void resetGMDrumMap(); + +#endif + diff --git a/attic/muse2-oom/muse2/muse/midiedit/ecanvas.cpp b/attic/muse2-oom/muse2/muse/midiedit/ecanvas.cpp new file mode 100644 index 00000000..3a10e135 --- /dev/null +++ b/attic/muse2-oom/muse2/muse/midiedit/ecanvas.cpp @@ -0,0 +1,541 @@ +//========================================================= +// MusE +// Linux Music Editor +// $Id: ecanvas.cpp,v 1.8.2.6 2009/05/03 04:14:00 terminator356 Exp $ +// (C) Copyright 2001 Werner Schweer (ws@seh.de) +//========================================================= + +#include <errno.h> +#include <values.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <sys/mman.h> + +#include <QKeyEvent> +#include <QDropEvent> +#include <QEvent> +#include <QMimeData> +#include <QByteArray> +#include <QDrag> + +#include "xml.h" +#include "midieditor.h" +#include "ecanvas.h" +#include "song.h" +#include "event.h" +#include "shortcuts.h" +#include "audio.h" + +//--------------------------------------------------------- +// EventCanvas +//--------------------------------------------------------- + +EventCanvas::EventCanvas(MidiEditor* pr, QWidget* parent, int sx, + int sy, const char* name) + : Canvas(parent, sx, sy, name) + { + editor = pr; + _steprec = false; + _midiin = false; + _playEvents = false; + curVelo = 70; + + setBg(QColor(226,229,229)); + setAcceptDrops(true); + setFocusPolicy(Qt::StrongFocus); + setMouseTracking(true); + + curPart = (MidiPart*)(editor->parts()->begin()->second); + curPartId = curPart->sn(); + } + +//--------------------------------------------------------- +// getCaption +//--------------------------------------------------------- + +QString EventCanvas::getCaption() const + { + int bar1, bar2, xx; + unsigned x; + ///sigmap.tickValues(curPart->tick(), &bar1, &xx, &x); + AL::sigmap.tickValues(curPart->tick(), &bar1, &xx, &x); + ///sigmap.tickValues(curPart->tick() + curPart->lenTick(), &bar2, &xx, &x); + AL::sigmap.tickValues(curPart->tick() + curPart->lenTick(), &bar2, &xx, &x); + + return QString("MusE: Part <") + curPart->name() + + QString("> %1-%2").arg(bar1+1).arg(bar2+1); + } + +//--------------------------------------------------------- +// leaveEvent +//--------------------------------------------------------- + +void EventCanvas::leaveEvent(QEvent*) + { + emit pitchChanged(-1); + emit timeChanged(MAXINT); + } + +//--------------------------------------------------------- +// enterEvent +//--------------------------------------------------------- + +void EventCanvas::enterEvent(QEvent*) + { + emit enterCanvas(); + } + +//--------------------------------------------------------- +// raster +//--------------------------------------------------------- + +QPoint EventCanvas::raster(const QPoint& p) const + { + int x = p.x(); + if (x < 0) + x = 0; + x = editor->rasterVal(x); + int pitch = y2pitch(p.y()); + int y = pitch2y(pitch); + return QPoint(x, y); + } + +//--------------------------------------------------------- +// startUndo +//--------------------------------------------------------- + +void EventCanvas::startUndo(DragType) + { + song->startUndo(); + } + +//--------------------------------------------------------- +// endUndo +//--------------------------------------------------------- + +void EventCanvas::endUndo(DragType dtype, int flags) + { + song->endUndo(flags | ((dtype == MOVE_COPY || dtype == MOVE_CLONE) + ? SC_EVENT_INSERTED : SC_EVENT_MODIFIED)); + } + +//--------------------------------------------------------- +// mouseMove +//--------------------------------------------------------- + +void EventCanvas::mouseMove(const QPoint& pos) + { + emit pitchChanged(y2pitch(pos.y())); + int x = pos.x(); + emit timeChanged(editor->rasterVal(x)); + } + +//--------------------------------------------------------- +// updateSelection +//--------------------------------------------------------- + +void EventCanvas::updateSelection() + { + song->update(SC_SELECTION); + } + +//--------------------------------------------------------- +// songChanged(type) +//--------------------------------------------------------- + +void EventCanvas::songChanged(int flags) + { + // Is it simply a midi controller value adjustment? Forget it. + if(flags == SC_MIDI_CONTROLLER) + return; + + if (flags & ~SC_SELECTION) { + items.clear(); + start_tick = MAXINT; + end_tick = 0; + curPart = 0; + for (iPart p = editor->parts()->begin(); p != editor->parts()->end(); ++p) { + MidiPart* part = (MidiPart*)(p->second); + if (part->sn() == curPartId) + curPart = part; + unsigned stick = part->tick(); + unsigned len = part->lenTick(); + unsigned etick = stick + len; + if (stick < start_tick) + start_tick = stick; + if (etick > end_tick) + end_tick = etick; + + EventList* el = part->events(); + for (iEvent i = el->begin(); i != el->end(); ++i) { + Event e = i->second; + // Added by T356. Do not add events which are either past, or extend past the end of the part. + //if(e.tick() > len) + if(e.endTick() > len) + break; + + if (e.isNote()) { + addItem(part, e); + } + } + } + } + + Event event; + MidiPart* part = 0; + int x = 0; + CItem* nevent = 0; + + int n = 0; // count selections + for (iCItem k = items.begin(); k != items.end(); ++k) { + Event ev = k->second->event(); + bool selected = ev.selected(); + if (selected) { + k->second->setSelected(true); + ++n; + if (!nevent) { + nevent = k->second; + Event mi = nevent->event(); + curVelo = mi.velo(); + } + } + } + start_tick = song->roundDownBar(start_tick); + end_tick = song->roundUpBar(end_tick); + + if (n == 1) { + x = nevent->x(); + event = nevent->event(); + part = (MidiPart*)nevent->part(); + if (curPart != part) { + curPart = part; + curPartId = curPart->sn(); + curPartChanged(); + } + } + emit selectionChanged(x, event, part); + if (curPart == 0) + curPart = (MidiPart*)(editor->parts()->begin()->second); + redraw(); + } + +//--------------------------------------------------------- +// selectAtTick +//--------------------------------------------------------- +void EventCanvas::selectAtTick(unsigned int tick) + { + //Select note nearest tick, if none selected and there are any + if (!items.empty() && selectionSize() == 0) { + iCItem i = items.begin(); + CItem* nearest = i->second; + + while (i != items.end()) { + CItem* cur=i->second; + unsigned int curtk=abs(cur->x() + cur->part()->tick() - tick); + unsigned int neartk=abs(nearest->x() + nearest->part()->tick() - tick); + + if (curtk < neartk) { + nearest=cur; + } + + i++; + } + + if (!nearest->isSelected()) { + selectItem(nearest, true); + songChanged(SC_SELECTION); + } + } + } + +//--------------------------------------------------------- +// track +//--------------------------------------------------------- + +MidiTrack* EventCanvas::track() const + { + return ((MidiPart*)curPart)->track(); + } + + +//--------------------------------------------------------- +// keyPress +//--------------------------------------------------------- + +void EventCanvas::keyPress(QKeyEvent* event) + { + int key = event->key(); + ///if (event->state() & Qt::ShiftButton) + if (((QInputEvent*)event)->modifiers() & Qt::ShiftModifier) + key += Qt::SHIFT; + ///if (event->state() & Qt::AltButton) + if (((QInputEvent*)event)->modifiers() & Qt::AltModifier) + key += Qt::ALT; + ///if (event->state() & Qt::ControlButton) + if (((QInputEvent*)event)->modifiers() & Qt::ControlModifier) + key+= Qt::CTRL; + + // + // Shortcut for DrumEditor & PianoRoll + // Sets locators to selected events + // + if (key == shortcuts[SHRT_LOCATORS_TO_SELECTION].key) { + int tick_max = 0; + int tick_min = INT_MAX; + bool found = false; + + for (iCItem i= items.begin(); i != items.end(); i++) { + if (!i->second->isSelected()) + continue; + + int tick = i->second->x(); + int len = i->second->event().lenTick(); + found = true; + if (tick + len > tick_max) + tick_max = tick + len; + if (tick < tick_min) + tick_min = tick; + } + if (found) { + Pos p1(tick_min, true); + Pos p2(tick_max, true); + song->setPos(1, p1); + song->setPos(2, p2); + } + } + // Select items by key (PianoRoll & DrumEditor) + else if (key == shortcuts[SHRT_SEL_RIGHT].key || key == shortcuts[SHRT_SEL_RIGHT_ADD].key) { + iCItem i, iRightmost; + CItem* rightmost = NULL; + //Get the rightmost selected note (if any) + for (i = items.begin(); i != items.end(); ++i) { + if (i->second->isSelected()) { + iRightmost = i; rightmost = i->second; + } + } + if (rightmost) { + iCItem temp = iRightmost; temp++; + //If so, deselect current note and select the one to the right + if (temp != items.end()) { + if (key != shortcuts[SHRT_SEL_RIGHT_ADD].key) + deselectAll(); + + iRightmost++; + iRightmost->second->setSelected(true); + updateSelection(); + } + } + } + //Select items by key: (PianoRoll & DrumEditor) + else if (key == shortcuts[SHRT_SEL_LEFT].key || key == shortcuts[SHRT_SEL_LEFT_ADD].key) { + iCItem i, iLeftmost; + CItem* leftmost = NULL; + if (items.size() > 0 ) { + for (i = items.end(), i--; i != items.begin(); i--) { + if (i->second->isSelected()) { + iLeftmost = i; leftmost = i->second; + } + } + if (leftmost) { + if (iLeftmost != items.begin()) { + //Add item + if (key != shortcuts[SHRT_SEL_LEFT_ADD].key) + deselectAll(); + + iLeftmost--; + iLeftmost->second->setSelected(true); + updateSelection(); + } + } + } + } + else if (key == shortcuts[SHRT_INC_PITCH].key) { + modifySelected(NoteInfo::VAL_PITCH, 1); + } + else if (key == shortcuts[SHRT_DEC_PITCH].key) { + modifySelected(NoteInfo::VAL_PITCH, -1); + } + else if (key == shortcuts[SHRT_INC_POS].key) { + // TODO: Check boundaries + modifySelected(NoteInfo::VAL_TIME, editor->raster()); + } + else if (key == shortcuts[SHRT_DEC_POS].key) { + // TODO: Check boundaries + modifySelected(NoteInfo::VAL_TIME, 0 - editor->raster()); + } + + else if (key == shortcuts[SHRT_INCREASE_LEN].key) { + // TODO: Check boundaries + modifySelected(NoteInfo::VAL_LEN, editor->raster()); + } + else if (key == shortcuts[SHRT_DECREASE_LEN].key) { + // TODO: Check boundaries + modifySelected(NoteInfo::VAL_LEN, 0 - editor->raster()); + } + + else + event->ignore(); + } + +//--------------------------------------------------------- +// getTextDrag +//--------------------------------------------------------- + +//QDrag* EventCanvas::getTextDrag(QWidget* parent) +QMimeData* EventCanvas::getTextDrag() + { + //--------------------------------------------------- + // 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; + ///NEvent* ne = (NEvent*)(i->second); + CItem* ne = 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::getTextDrag() fopen failed: %s\n", + strerror(errno)); + return 0; + } + Xml xml(tmp); + + int level = 0; + xml.tag(level++, "eventlist"); + for (ciEvent e = el.begin(); e != el.end(); ++e) + e->second.write(level, xml, -startTick); + xml.etag(--level, "eventlist"); + + //--------------------------------------------------- + // read tmp file into drag Object + //--------------------------------------------------- + + fflush(tmp); + struct stat f_stat; + if (fstat(fileno(tmp), &f_stat) == -1) { + fprintf(stderr, "PianoCanvas::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; + + QByteArray data(fbuf); + QMimeData* md = new QMimeData(); + //QDrag* drag = new QDrag(parent); + + md->setData("text/x-muse-eventlist", data); + //drag->setMimeData(md); + + munmap(fbuf, n); + fclose(tmp); + + //return drag; + return md; + } + +//--------------------------------------------------------- +// pasteAt +//--------------------------------------------------------- + +void EventCanvas::pasteAt(const QString& pt, int pos) + { + QByteArray ba = pt.toLatin1(); + const char* p = ba.constData(); + Xml xml(p); + 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 == "eventlist") { + song->startUndo(); + EventList* el = new EventList(); + el->read(xml, "eventlist", true); + int modified = SC_EVENT_INSERTED; + for (iEvent i = el->begin(); i != el->end(); ++i) { + Event e = i->second; + int tick = e.tick() + pos - curPart->tick(); + if (tick<0) { + printf("ERROR: trying to add event before current part!\n"); + song->endUndo(SC_EVENT_INSERTED); + delete el; + return; + } + + 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); + } + song->endUndo(modified); + delete el; + return; + } + else + xml.unknown("pasteAt"); + break; + case Xml::Attribut: + case Xml::TagEnd: + default: + break; + } + } + } + +//--------------------------------------------------------- +// dropEvent +//--------------------------------------------------------- + +void EventCanvas::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()->hasFormat("text/x-muse-eventlist")) { + text = QString(event->mimeData()->data("text/x-muse-eventlist")); + + 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. + } + } + diff --git a/attic/muse2-oom/muse2/muse/midiedit/ecanvas.h b/attic/muse2-oom/muse2/muse/midiedit/ecanvas.h new file mode 100644 index 00000000..461a717a --- /dev/null +++ b/attic/muse2-oom/muse2/muse/midiedit/ecanvas.h @@ -0,0 +1,94 @@ +//========================================================= +// MusE +// Linux Music Editor +// $Id: ecanvas.h,v 1.5.2.4 2009/02/02 21:38:00 terminator356 Exp $ +// (C) Copyright 2001 Werner Schweer (ws@seh.de) +//========================================================= + +#ifndef __ECANVAS_H__ +#define __ECANVAS_H__ + +#include "canvas.h" +#include "noteinfo.h" +#include <QEvent> +#include <QKeyEvent> + +class MidiPart; +class MidiTrack; +class MidiEditor; +class Part; +class QMimeData; +class QDrag; +class QString; +class QDropEvent; + +struct PartToChange +{ + Part* npart; + int xdiff; +}; +typedef std::map<Part*, PartToChange> PartsToChangeMap; +typedef std::map<Part*, PartToChange>::iterator iPartToChange; + +//--------------------------------------------------------- +// EventCanvas +//--------------------------------------------------------- + +class EventCanvas : public Canvas { + Q_OBJECT + virtual void leaveEvent(QEvent*e); + virtual void enterEvent(QEvent*e); + // Removed by T356. + //virtual QPoint raster(const QPoint&) const; + + virtual void startUndo(DragType); + + virtual void endUndo(DragType, int flags = 0); + virtual void mouseMove(const QPoint&); + + protected: + bool _playEvents; + MidiEditor* editor; + unsigned start_tick, end_tick; + int curVelo; + bool _steprec; + bool _midiin; + + void updateSelection(); + virtual void addItem(Part*, Event&) = 0; + // Added by T356. + virtual QPoint raster(const QPoint&) const; + + public slots: + void redrawGrid() { redraw(); } + void setSteprec(bool f) { _steprec = f; } + void setMidiin(bool f) { _midiin = f; } + + signals: + void pitchChanged(int); // current cursor position + void timeChanged(unsigned); + void selectionChanged(int, Event&, Part*); + void enterCanvas(); + + public: + EventCanvas(MidiEditor*, QWidget*, int, int, const char* name = 0); + MidiTrack* track() const; + unsigned start() const { return start_tick; } + unsigned end() const { return end_tick; } + bool midiin() const { return _midiin; } + bool steprec() const { return _steprec; } + QString getCaption() const; + void songChanged(int); + void range(int* s, int* e) const { *s = start_tick; *e = end_tick; } + void playEvents(bool flag) { _playEvents = flag; } + void selectAtTick(unsigned int tick); + //QDrag* getTextDrag(QWidget* parent); + QMimeData* getTextDrag(); + void pasteAt(const QString& pt, int pos); + void viewDropEvent(QDropEvent* event); + virtual void modifySelected(NoteInfo::ValType, int) {} + virtual void keyPress(QKeyEvent*); + }; + +#endif + diff --git a/attic/muse2-oom/muse2/muse/midiedit/piano.cpp b/attic/muse2-oom/muse2/muse/midiedit/piano.cpp new file mode 100644 index 00000000..6d42556c --- /dev/null +++ b/attic/muse2-oom/muse2/muse/midiedit/piano.cpp @@ -0,0 +1,554 @@ +//========================================================= +// MusE +// Linux Music Editor +// $Id: piano.cpp,v 1.3 2004/05/31 11:48:55 lunar_shuttle Exp $ +// (C) Copyright 1999 Werner Schweer (ws@seh.de) +//========================================================= + +#include <QMouseEvent> +#include <QPainter> + +#include <stdio.h> + +#include "piano.h" + +static const char *oct_xpm[] = { +// w h colors + "40 91 2 1", + ". c #dedede", + "# c #565656", + // x + "####################################### ", + ".......................................#", + ".......................................#", + ".......................................#", + ".......................................#", + ".......................................#", // 10 + ".......................................#", + ".......................................#", + ".......................................#", + ".......................................#", //------------------------ + "#######################................#", + "########################...............#", + "########################...............#", + "####################################### ", // 7 + "########################...............#", + "########################...............#", + "#######################................#", //------------------------ + ".......................................#", + ".......................................#", + ".......................................#", // 6 + ".......................................#", + ".......................................#", + ".......................................#", //------------------------ + "#######################................#", + "########################...............#", + "########################...............#", // 7 + "####################################### ", + "########################...............#", + "########################...............#", + "#######################................#", //------------------------ + ".......................................#", + ".......................................#", + ".......................................#", // 6 + ".......................................#", + ".......................................#", + ".......................................#", //------------------------ + "#######################................#", + "########################...............#", + "########################...............#", // 7 + "####################################### ", + "########################...............#", + "########################...............#", + "#######################................#", //------------------------ + ".......................................#", + ".......................................#", + ".......................................#", + ".......................................#", // 10 + ".......................................#", + ".......................................#", + ".......................................#", + ".......................................#", + ".......................................#", + "####################################### ", //---------------------- + ".......................................#", + ".......................................#", + ".......................................#", + ".......................................#", // 9 + ".......................................#", + ".......................................#", + ".......................................#", + ".......................................#", + ".......................................#", //------------------------ + "#######################................#", + "########################...............#", + "########################...............#", + "####################################### ", // 7 + "########################...............#", + "########################...............#", + "#######################................#", //------------------------ + ".......................................#", + ".......................................#", + ".......................................#", // 6 + ".......................................#", + ".......................................#", + ".......................................#", //-------------------------- + "#######################................#", + "########################...............#", + "########################...............#", // 7 + "####################################### ", + "########################...............#", + "########################...............#", + "#######################................#", //------------------------ + ".......................................#", + "..........................###..........#", + ".........................#...#.........#", + ".........................#.............#", + ".........................#.............#", + ".........................#...#.........#", // 10 + "..........................###..........#", + ".......................................#", + ".......................................#", + ".......................................#", + }; + +static const char *mk1_xpmC1[] = { + "40 10 2 1", + ". c #dedede", + "# c #565656", + ".......................................#", + "..........................###.....#....#", + ".........................#...#...##....#", + ".........................#........#....#", + ".........................#........#....#", + ".........................#...#....#....#", // 10 + "..........................###....###...#", + ".......................................#", + ".......................................#", + ".......................................#", + }; +static const char *mk1_xpmC2[] = { + "40 10 2 1", + ". c #dedede", + "# c #565656", + ".......................................#", + "..........................###....##....#", + ".........................#...#..#..#...#", + ".........................#........#....#", + ".........................#.......#.....#", + ".........................#...#..#......#", // 10 + "..........................###...####...#", + ".......................................#", + ".......................................#", + ".......................................#", + }; +static const char *mk1_xpmC3[] = { + "40 10 2 1", + ". c #dedede", + "# c #565656", + ".......................................#", + "..........................###....##....#", + ".........................#...#..#..#...#", + ".........................#........#....#", + ".........................#.........#...#", + ".........................#...#..#..#...#", // 10 + "..........................###....##....#", + ".......................................#", + ".......................................#", + ".......................................#", + }; +static const char *mk1_xpmC4[] = { + "40 10 2 1", + ". c #dedede", + "# c #565656", + ".......................................#", + "..........................###...#..#...#", + ".........................#...#..#..#...#", + ".........................#......####...#", + ".........................#.........#...#", + ".........................#...#.....#...#", // 10 + "..........................###......#...#", + ".......................................#", + ".......................................#", + ".......................................#", + }; +static const char *mk1_xpmC5[] = { + "40 10 2 1", + ". c #dedede", + "# c #565656", + ".......................................#", + "..........................###...####...#", + ".........................#...#..#......#", + ".........................#......###....#", + ".........................#.........#...#", + ".........................#...#.....#...#", // 10 + "..........................###...###....#", + ".......................................#", + ".......................................#", + ".......................................#", + }; + +static const char *mk1_xpmC6[] = { + "40 10 2 1", + ". c #dedede", + "# c #565656", + ".......................................#", + "..........................###....###...#", + ".........................#...#..#......#", + ".........................#......###....#", + ".........................#......#..#...#", + ".........................#...#..#..#...#", // 10 + "..........................###...###....#", + ".......................................#", + ".......................................#", + ".......................................#", + }; + +static const char *mk1_xpmC7[] = { + "40 10 2 1", + ". c #dedede", + "# c #565656", + ".......................................#", + "..........................###...####...#", + ".........................#...#.....#...#", + ".........................#........#....#", + ".........................#.......#.....#", + ".........................#...#..#......#", // 10 + "..........................###...#......#", + ".......................................#", + ".......................................#", + ".......................................#", + }; +static const char *mk1_xpmC8[] = { + "40 10 2 1", + ". c #dedede", + "# c #565656", + ".......................................#", + "..........................###....##....#", + ".........................#...#..#..#....#", + ".........................#.......##....#", + ".........................#......#..#...#", + ".........................#...#..#..#...#", // 10 + "..........................###....##....#", + ".......................................#", + ".......................................#", + ".......................................#", + }; + +static const char *mk1_xpm[] = { + "40 13 2 1", + ". c #2d95b7", + "# c none", + ".......................................#", + ".......................................#", + ".......................................#", + ".......................................#", + ".......................................#", + ".......................................#", + ".......................................#", + ".......................................#", + ".......................................#", + "#######################................#", + "########################...............#", + "########################...............#", + "####################################### ", + }; + +static const char *mk2_xpm[] = { + "40 13 2 1", + ". c #2d95b7", + "# c none", + "########################...............#", + "########################...............#", + "#######################................#", //------------------------ + ".......................................#", + ".......................................#", + ".......................................#", // 6 + ".......................................#", + ".......................................#", + ".......................................#", //-------------------------- + "#######################................#", + "########################...............#", + "########################...............#", // 7 + "####################################### ", + }; + +static const char *mk3_xpm[] = { + "40 13 2 1", + ". c #2d95b7", + "# c none", + "########################...............#", + "########################...............#", + "#######################................#", + ".......................................#", + ".......................................#", + ".......................................#", + ".......................................#", + ".......................................#", + ".......................................#", + ".......................................#", + ".......................................#", + ".......................................#", + "########################################", + }; + +static const char *mk4_xpm[] = { + "40 13 2 1", + "# c #2d95b7", + ". c none", + "........................................", + "........................................", + "........................................", + "#######################.................", + "########################................", + "########################................", + "########################................", + "########################................", + "########################................", + "#######################.................", + "........................................", + "........................................", + "........................................", + }; +/* + 0 1 2 3 4 5 6 7 8 9 10 + c-2 c-1 C0 C1 C2 C3 C4 C5 C6 C7 C8 - G8 + + Grid über Oktave: + + +------------+ ------------------------------ + 11 | | + | h | 7 + +------+ | + 10 | a# +-----+ .............................. + +------+ a | + 9 | | 6 + +------+ | + 8 | g# +-----+ .............................. + +------+ g | + 7 | | 5 + +------+ | + 6 | f# +-----+ .............................. + +------+ f | + 5 | | 4 + | | + +------------+ ------------------------------ + 4 | | + | e | 3 + +------+ | + 3 | d# +-----+ .............................. + +------+ d | + 2 | | 2 + +------+ | + 1 | c# +-----+ .............................. + +------+ c | + | | 1 + 0 | | + +------------+ ------------------------------ + */ + +//--------------------------------------------------------- +// Piano +//--------------------------------------------------------- + +Piano::Piano(QWidget* parent, int ymag) + : View(parent, 1, ymag) + { + setMouseTracking(true); + curPitch = -1; + octave = new QPixmap(oct_xpm); + c_keys[0] = new QPixmap(mk1_xpmC8); + c_keys[1] = new QPixmap(mk1_xpmC7); + c_keys[2] = new QPixmap(mk1_xpmC6); + c_keys[3] = new QPixmap(mk1_xpmC5); + c_keys[4] = new QPixmap(mk1_xpmC4); + c_keys[5] = new QPixmap(mk1_xpmC3); + c_keys[6] = new QPixmap(mk1_xpmC2); + c_keys[7] = new QPixmap(mk1_xpmC1); + + mk1 = new QPixmap(mk1_xpm); + mk2 = new QPixmap(mk2_xpm); + mk3 = new QPixmap(mk3_xpm); + mk4 = new QPixmap(mk4_xpm); + keyDown = -1; + button = Qt::NoButton; + } + +//--------------------------------------------------------- +// draw +//--------------------------------------------------------- + +void Piano::draw(QPainter& p, const QRect& r) + { + QPoint offset(0, KH*2); + p.drawTiledPixmap(r, *octave, r.topLeft()+offset); + + // draw C notes + for (int drawKey = 0; drawKey < 8;drawKey++) { + int octaveSize=91; + + int drawY = octaveSize * drawKey + 81 - KH*2; + if (drawY > r.y() && drawY < r.y() + r.height()) { + //printf("drawing c %d at %d r.y %d r.x %d\n",drawKey, drawY, r.y(), r.x()); + p.drawPixmap(0,drawY,*c_keys[drawKey]); + } + } + //p.drawTiledPixmap(r, *c1, r.topLeft()+offset + coffset); + //printf("drawText KH %d %d, x %d y %d\n",KH, curPitch, r.x(), r.y()); + //p.drawText(r,Qt::AlignAuto,"A"); + if (curPitch == -1) + return; + int y = pitch2y(curPitch); + QPixmap* pm; + switch(curPitch % 12) { + case 0: + case 5: + pm = mk3; + break; + case 2: + case 7: + case 9: + pm = mk2; + break; + case 4: + case 11: + pm = mk1; + break; + default: + pm = mk4; + break; + } + p.drawPixmap(0, y, *pm); + } + +//--------------------------------------------------------- +// pitch2y +//--------------------------------------------------------- + +int Piano::pitch2y(int pitch) const + { + int tt[] = { + 12, 19, 25, 32, 38, 51, 58, 64, 71, 77, 84, 90 + }; + int y = (75 * KH) - (tt[pitch%12] + (7 * KH) * (pitch/12)); + if (y < 0) + y = 0; + return y; + } + +//--------------------------------------------------------- +// y2pitch +//--------------------------------------------------------- + +int Piano::y2pitch(int y) const + { + const int total = (10 * 7 + 5) * KH; // 75 Ganztonschritte + y = total - y; + int oct = (y / (7 * KH)) * 12; + char kt[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, + 2, 2, 2, 2, 2, 2, + 3, 3, 3, 3, 3, 3, 3, + 4, 4, 4, 4, 4, 4, 4, 4, 4, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 6, 6, 6, 6, 6, 6, 6, + 7, 7, 7, 7, 7, 7, + 8, 8, 8, 8, 8, 8, 8, + 9, 9, 9, 9, 9, 9, + 10, 10, 10, 10, 10, 10, 10, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11 + }; + return kt[y % 91] + oct; + } + +//--------------------------------------------------------- +// leaveEvent +//--------------------------------------------------------- + +void Piano::leaveEvent(QEvent*) + { + if (keyDown != -1) { + emit keyReleased(keyDown, shift); + keyDown = -1; + } + emit pitchChanged(-1); + setPitch(-1); + } + +//--------------------------------------------------------- +// setPitch +//--------------------------------------------------------- + +void Piano::setPitch(int pitch) + { + if (curPitch == pitch) + return; + curPitch = pitch; + redraw(); + } + +//--------------------------------------------------------- +// viewMouseMoveEvent +//--------------------------------------------------------- + +void Piano::viewMouseMoveEvent(QMouseEvent* event) + { + int pitch = y2pitch(event->y()); + emit pitchChanged(pitch); + setPitch(pitch); + + if (button != Qt::NoButton) { + int nk = y2pitch(event->y()); + if (nk < 0 || nk > 127) + nk = -1; + if (nk != keyDown) { + if (keyDown != -1) { + emit keyReleased(keyDown, shift); + } + keyDown = nk; + if (keyDown != -1) { + int velocity = event->x()*127/40; + //emit keyPressed(keyDown, shift); + emit keyPressed(keyDown, velocity>127 ? 127 : velocity, shift); + } + } + } + } + +//--------------------------------------------------------- +// viewMousePressEvent +//--------------------------------------------------------- + +void Piano::viewMousePressEvent(QMouseEvent* event) + { + button = event->button(); + shift = event->modifiers() & Qt::ShiftModifier; + if (keyDown != -1) { + emit keyReleased(keyDown, shift); + keyDown = -1; + } + keyDown = y2pitch(event->y()); + if (keyDown < 0 || keyDown > 127) { + keyDown = -1; + } + else { + int velocity = event->x()*127/40; + emit keyPressed(keyDown, velocity>127 ? 127 : velocity, shift); //emit keyPressed(keyDown, shift); + } + } + +//--------------------------------------------------------- +// viewMouseReleaseEvent +//--------------------------------------------------------- + +void Piano::viewMouseReleaseEvent(QMouseEvent* event) + { + button = Qt::NoButton; + shift = event->modifiers() & Qt::ShiftModifier; + if (keyDown != -1) { + emit keyReleased(keyDown, shift); + keyDown = -1; + } + } + diff --git a/attic/muse2-oom/muse2/muse/midiedit/piano.h b/attic/muse2-oom/muse2/muse/midiedit/piano.h new file mode 100644 index 00000000..35106d64 --- /dev/null +++ b/attic/muse2-oom/muse2/muse/midiedit/piano.h @@ -0,0 +1,62 @@ +//========================================================= +// MusE +// Linux Music Editor +// $Id: piano.h,v 1.2 2004/05/31 11:48:55 lunar_shuttle Exp $ +// (C) Copyright 1999 Werner Schweer (ws@seh.de) +//========================================================= + +#ifndef __PIANO_H__ +#define __PIANO_H__ + +#include "view.h" + +class QEvent; +class QMouseEvent; +class QPainter; +class QPixmap; + +#define KH 13 + +//--------------------------------------------------------- +// Piano +//--------------------------------------------------------- + +class Piano : public View + { + int curPitch; + QPixmap* octave; + QPixmap* c_keys[10]; + QPixmap* mk1; + QPixmap* mk2; + QPixmap* mk3; + QPixmap* mk4; + int keyDown; + bool shift; + int button; + + Q_OBJECT + int y2pitch(int) const; + int pitch2y(int) const; + void viewMouseMoveEvent(QMouseEvent* event); + virtual void leaveEvent(QEvent*e); + + virtual void viewMousePressEvent(QMouseEvent* event); + virtual void viewMouseReleaseEvent(QMouseEvent*); + + protected: + virtual void draw(QPainter&, const QRect&); + + signals: + void pitchChanged(int); + void keyPressed(int, int, bool); + void keyReleased(int, bool); + + public slots: + void setPitch(int); + + public: + Piano(QWidget*, int); + }; + +#endif + diff --git a/attic/muse2-oom/muse2/muse/midiedit/pianoroll.cpp b/attic/muse2-oom/muse2/muse/midiedit/pianoroll.cpp new file mode 100644 index 00000000..d2dbfca5 --- /dev/null +++ b/attic/muse2-oom/muse2/muse/midiedit/pianoroll.cpp @@ -0,0 +1,1501 @@ +//========================================================= +// MusE +// Linux Music Editor +// $Id: pianoroll.cpp,v 1.25.2.15 2009/11/16 11:29:33 lunar_shuttle Exp $ +// (C) Copyright 1999 Werner Schweer (ws@seh.de) +//========================================================= + +#include <QLayout> +#include <QSizeGrip> +#include <QLabel> +#include <QPushButton> +#include <QToolButton> +#include <QToolTip> +#include <QMenu> +#include <QSignalMapper> +#include <QMenuBar> +#include <QApplication> +#include <QClipboard> +#include <QDir> +#include <QAction> +#include <QKeySequence> +#include <QKeyEvent> +#include <QGridLayout> +#include <QResizeEvent> +#include <QCloseEvent> +#include <QMimeData> +#include <QScrollArea> + +#include <stdio.h> + +#include "xml.h" +#include "mtscale.h" +#include "pcscale.h" +#include "prcanvas.h" +#include "pianoroll.h" +#include "scrollscale.h" +#include "piano.h" +#include "../ctrl/ctrledit.h" +#include "splitter.h" +#include "ttoolbar.h" +#include "tb1.h" +#include "utils.h" +#include "globals.h" +#include "gconfig.h" +#include "icons.h" +#include "audio.h" + +#include "cmd.h" +#include "quantconfig.h" +#include "shortcuts.h" + +#include "mtrackinfo.h" + +int PianoRoll::_quantInit = 96; +int PianoRoll::_rasterInit = 96; +int PianoRoll::_widthInit = 600; +int PianoRoll::_heightInit = 400; +int PianoRoll::_quantStrengthInit = 80; // 1 - 100% +int PianoRoll::_quantLimitInit = 50; // tick value +bool PianoRoll::_quantLenInit = false; +int PianoRoll::_toInit = 0; +int PianoRoll::colorModeInit = 0; + +static const int xscale = -10; +static const int yscale = 1; +static const int pianoWidth = 40; +static int pianorollTools = PointerTool | PencilTool | RubberTool | DrawTool; + + +//--------------------------------------------------------- +// PianoRoll +//--------------------------------------------------------- + +PianoRoll::PianoRoll(PartList* pl, QWidget* parent, const char* name, unsigned initPos) + : MidiEditor(_quantInit, _rasterInit, pl, parent, name) + { + deltaMode = false; + resize(_widthInit, _heightInit); + selPart = 0; + quantConfig = 0; + _playEvents = false; + _quantStrength = _quantStrengthInit; + _quantLimit = _quantLimitInit; + _quantLen = _quantLenInit; + _to = _toInit; + colorMode = colorModeInit; + + QSignalMapper* mapper = new QSignalMapper(this); + QSignalMapper* colorMapper = new QSignalMapper(this); + + //---------Menu---------------------------------- + + menuEdit = menuBar()->addMenu(tr("&Edit")); + + menuEdit->addActions(undoRedo->actions()); + + menuEdit->addSeparator(); + + editCutAction = menuEdit->addAction(QIcon(*editcutIconSet), tr("C&ut")); + mapper->setMapping(editCutAction, PianoCanvas::CMD_CUT); + connect(editCutAction, SIGNAL(triggered()), mapper, SLOT(map())); + + editCopyAction = menuEdit->addAction(QIcon(*editcopyIconSet), tr("&Copy")); + mapper->setMapping(editCopyAction, PianoCanvas::CMD_COPY); + connect(editCopyAction, SIGNAL(triggered()), mapper, SLOT(map())); + + editPasteAction = menuEdit->addAction(QIcon(*editpasteIconSet), tr("&Paste")); + mapper->setMapping(editPasteAction, PianoCanvas::CMD_PASTE); + connect(editPasteAction, SIGNAL(triggered()), mapper, SLOT(map())); + + menuEdit->addSeparator(); + + editDelEventsAction = menuEdit->addAction(tr("Delete &Events")); + mapper->setMapping(editDelEventsAction, PianoCanvas::CMD_DEL); + connect(editDelEventsAction, SIGNAL(triggered()), mapper, SLOT(map())); + + menuEdit->addSeparator(); + + menuSelect = menuEdit->addMenu(QIcon(*selectIcon), tr("&Select")); + + selectAllAction = menuSelect->addAction(QIcon(*select_allIcon), tr("Select &All")); + mapper->setMapping(selectAllAction, PianoCanvas::CMD_SELECT_ALL); + connect(selectAllAction, SIGNAL(triggered()), mapper, SLOT(map())); + + selectNoneAction = menuSelect->addAction(QIcon(*select_deselect_allIcon), tr("&Deselect All")); + mapper->setMapping(selectNoneAction, PianoCanvas::CMD_SELECT_NONE); + connect(selectNoneAction, SIGNAL(triggered()), mapper, SLOT(map())); + + selectInvertAction = menuSelect->addAction(QIcon(*select_invert_selectionIcon), tr("Invert &Selection")); + mapper->setMapping(selectInvertAction, PianoCanvas::CMD_SELECT_INVERT); + connect(selectInvertAction, SIGNAL(triggered()), mapper, SLOT(map())); + + menuSelect->addSeparator(); + + selectInsideLoopAction = menuSelect->addAction(QIcon(*select_inside_loopIcon), tr("&Inside Loop")); + mapper->setMapping(selectInsideLoopAction, PianoCanvas::CMD_SELECT_ILOOP); + connect(selectInsideLoopAction, SIGNAL(triggered()), mapper, SLOT(map())); + + selectOutsideLoopAction = menuSelect->addAction(QIcon(*select_outside_loopIcon), tr("&Outside Loop")); + mapper->setMapping(selectOutsideLoopAction, PianoCanvas::CMD_SELECT_OLOOP); + connect(selectOutsideLoopAction, SIGNAL(triggered()), mapper, SLOT(map())); + + menuSelect->addSeparator(); + + //selectPrevPartAction = select->addAction(tr("&Previous Part")); + selectPrevPartAction = menuSelect->addAction(QIcon(*select_all_parts_on_trackIcon), tr("&Previous Part")); + mapper->setMapping(selectPrevPartAction, PianoCanvas::CMD_SELECT_PREV_PART); + connect(selectPrevPartAction, SIGNAL(triggered()), mapper, SLOT(map())); + + //selNextPartAction = select->addAction(tr("&Next Part")); + selectNextPartAction = menuSelect->addAction(QIcon(*select_all_parts_on_trackIcon), tr("&Next Part")); + mapper->setMapping(selectNextPartAction, PianoCanvas::CMD_SELECT_NEXT_PART); + connect(selectNextPartAction, SIGNAL(triggered()), mapper, SLOT(map())); + + menuConfig = menuBar()->addMenu(tr("&Config")); + + eventColor = menuConfig->addMenu(tr("&Event Color")); + + QActionGroup* actgrp = new QActionGroup(this); + actgrp->setExclusive(true); + + //evColorBlueAction = eventColor->addAction(tr("&Blue")); + evColorBlueAction = actgrp->addAction(tr("&Blue")); + evColorBlueAction->setCheckable(true); + colorMapper->setMapping(evColorBlueAction, 0); + + //evColorPitchAction = eventColor->addAction(tr("&Pitch colors")); + evColorPitchAction = actgrp->addAction(tr("&Pitch colors")); + evColorPitchAction->setCheckable(true); + colorMapper->setMapping(evColorPitchAction, 1); + + //evColorVelAction = eventColor->addAction(tr("&Velocity colors")); + evColorVelAction = actgrp->addAction(tr("&Velocity colors")); + evColorVelAction->setCheckable(true); + colorMapper->setMapping(evColorVelAction, 2); + + connect(evColorBlueAction, SIGNAL(triggered()), colorMapper, SLOT(map())); + connect(evColorPitchAction, SIGNAL(triggered()), colorMapper, SLOT(map())); + connect(evColorVelAction, SIGNAL(triggered()), colorMapper, SLOT(map())); + + eventColor->addActions(actgrp->actions()); + + connect(colorMapper, SIGNAL(mapped(int)), this, SLOT(eventColorModeChanged(int))); + + menuFunctions = menuBar()->addMenu(tr("&Functions")); + + menuFunctions->setTearOffEnabled(true); + + funcOverQuantAction = menuFunctions->addAction(tr("Over Quantize")); + mapper->setMapping(funcOverQuantAction, PianoCanvas::CMD_OVER_QUANTIZE); + connect(funcOverQuantAction, SIGNAL(triggered()), mapper, SLOT(map())); + + funcNoteOnQuantAction = menuFunctions->addAction(tr("Note On Quantize")); + mapper->setMapping(funcNoteOnQuantAction, PianoCanvas::CMD_ON_QUANTIZE); + connect(funcNoteOnQuantAction, SIGNAL(triggered()), mapper, SLOT(map())); + + funcNoteOnOffQuantAction = menuFunctions->addAction(tr("Note On/Off Quantize")); + mapper->setMapping(funcNoteOnOffQuantAction, PianoCanvas::CMD_ONOFF_QUANTIZE); + connect(funcNoteOnOffQuantAction, SIGNAL(triggered()), mapper, SLOT(map())); + + funcIterQuantAction = menuFunctions->addAction(tr("Iterative Quantize")); + mapper->setMapping(funcIterQuantAction, PianoCanvas::CMD_ITERATIVE_QUANTIZE); + connect(funcIterQuantAction, SIGNAL(triggered()), mapper, SLOT(map())); + + menuFunctions->addSeparator(); + + funcConfigQuantAction = menuFunctions->addAction(tr("Config Quant...")); + connect(funcConfigQuantAction, SIGNAL(triggered()), this, SLOT(configQuant())); + + menuFunctions->addSeparator(); + + funcGateTimeAction = menuFunctions->addAction(tr("Modify Gate Time")); + mapper->setMapping(funcGateTimeAction, PianoCanvas::CMD_MODIFY_GATE_TIME); + connect(funcGateTimeAction, SIGNAL(triggered()), mapper, SLOT(map())); + + funcModVelAction = menuFunctions->addAction(tr("Modify Velocity")); + mapper->setMapping(funcModVelAction, PianoCanvas::CMD_MODIFY_VELOCITY); + connect(funcModVelAction, SIGNAL(triggered()), mapper, SLOT(map())); + + funcCrescendoAction = menuFunctions->addAction(tr("Crescendo")); + mapper->setMapping(funcCrescendoAction, PianoCanvas::CMD_CRESCENDO); + funcCrescendoAction->setEnabled(false); + connect(funcCrescendoAction, SIGNAL(triggered()), mapper, SLOT(map())); + + funcTransposeAction = menuFunctions->addAction(tr("Transpose")); + mapper->setMapping(funcTransposeAction, PianoCanvas::CMD_TRANSPOSE); + funcTransposeAction->setEnabled(false); + connect(funcTransposeAction, SIGNAL(triggered()), mapper, SLOT(map())); + + funcThinOutAction = menuFunctions->addAction(tr("Thin Out")); + mapper->setMapping(funcThinOutAction, PianoCanvas::CMD_THIN_OUT); + funcThinOutAction->setEnabled(false); + connect(funcThinOutAction, SIGNAL(triggered()), mapper, SLOT(map())); + + funcEraseEventAction = menuFunctions->addAction(tr("Erase Event")); + mapper->setMapping(funcEraseEventAction, PianoCanvas::CMD_ERASE_EVENT); + funcEraseEventAction->setEnabled(false); + connect(funcEraseEventAction, SIGNAL(triggered()), mapper, SLOT(map())); + + funcNoteShiftAction = menuFunctions->addAction(tr("Note Shift")); + mapper->setMapping(funcNoteShiftAction, PianoCanvas::CMD_NOTE_SHIFT); + funcNoteShiftAction->setEnabled(false); + connect(funcNoteShiftAction, SIGNAL(triggered()), mapper, SLOT(map())); + + funcMoveClockAction = menuFunctions->addAction(tr("Move Clock")); + mapper->setMapping(funcMoveClockAction, PianoCanvas::CMD_MOVE_CLOCK); + funcMoveClockAction->setEnabled(false); + connect(funcMoveClockAction, SIGNAL(triggered()), mapper, SLOT(map())); + + funcCopyMeasureAction = menuFunctions->addAction(tr("Copy Measure")); + mapper->setMapping(funcCopyMeasureAction, PianoCanvas::CMD_COPY_MEASURE); + funcCopyMeasureAction->setEnabled(false); + connect(funcCopyMeasureAction, SIGNAL(triggered()), mapper, SLOT(map())); + + funcEraseMeasureAction = menuFunctions->addAction(tr("Erase Measure")); + mapper->setMapping(funcEraseMeasureAction, PianoCanvas::CMD_ERASE_MEASURE); + funcEraseMeasureAction->setEnabled(false); + connect(funcEraseMeasureAction, SIGNAL(triggered()), mapper, SLOT(map())); + + funcDelMeasureAction = menuFunctions->addAction(tr("Delete Measure")); + mapper->setMapping(funcDelMeasureAction, PianoCanvas::CMD_DELETE_MEASURE); + funcDelMeasureAction->setEnabled(false); + connect(funcDelMeasureAction, SIGNAL(triggered()), mapper, SLOT(map())); + + funcCreateMeasureAction = menuFunctions->addAction(tr("Create Measure")); + mapper->setMapping(funcCreateMeasureAction, PianoCanvas::CMD_CREATE_MEASURE); + funcCreateMeasureAction->setEnabled(false); + connect(funcCreateMeasureAction, SIGNAL(triggered()), mapper, SLOT(map())); + + funcSetFixedLenAction = menuFunctions->addAction(tr("Set Fixed Length")); + mapper->setMapping(funcSetFixedLenAction, PianoCanvas::CMD_FIXED_LEN); + connect(funcSetFixedLenAction, SIGNAL(triggered()), mapper, SLOT(map())); + + funcDelOverlapsAction = menuFunctions->addAction(tr("Delete Overlaps")); + mapper->setMapping(funcDelOverlapsAction, PianoCanvas::CMD_DELETE_OVERLAPS); + connect(funcDelOverlapsAction, SIGNAL(triggered()), mapper, SLOT(map())); + + menuPlugins = menuBar()->addMenu(tr("&Plugins")); + song->populateScriptMenu(menuPlugins, this); + + connect(mapper, SIGNAL(mapped(int)), this, SLOT(cmd(int))); + + //---------ToolBar---------------------------------- + tools = addToolBar(tr("Pianoroll tools")); + tools->addActions(undoRedo->actions()); + tools->addSeparator(); + tools->setIconSize(QSize(22,22)); + + srec = new QToolButton(); + srec->setToolTip(tr("Step Record")); + srec->setIcon(*steprecIcon); + srec->setCheckable(true); + //srec->setObjectName("StepRecord"); + tools->addWidget(srec); + + midiin = new QToolButton(); + midiin->setToolTip(tr("Midi Input")); + midiin->setIcon(*midiinIcon); + midiin->setCheckable(true); + //tools->addWidget(midiin); + + speaker = new QToolButton(); + speaker->setToolTip(tr("Play Events")); + speaker->setIcon(*speakerIcon); + speaker->setCheckable(true); + tools->addWidget(speaker); + + tools2 = new EditToolBar(this, pianorollTools); + tools2->setIconSize(QSize(22,22)); + addToolBar(tools2); + + QToolBar* panicToolbar = new QToolBar(tr("panic")); + panicToolbar->addAction(panicAction); + panicToolbar->setAllowedAreas(Qt::BottomToolBarArea); + + //------------------------------------------------------------- + // Transport Bar + QToolBar* transport = new QToolBar(tr("transport")); + addToolBar(Qt::BottomToolBarArea, transport); + transport->addActions(transportAction->actions()); + transport->setAllowedAreas(Qt::BottomToolBarArea); + transport->setIconSize(QSize(22,22)); + addToolBar(Qt::BottomToolBarArea, panicToolbar); + + //addToolBarBreak(); + toolbar = new Toolbar1(this, _rasterInit, _quantInit); + addToolBar(toolbar); + + //addToolBarBreak(); + info = new NoteInfo(this); + addToolBar(Qt::BottomToolBarArea, info); + info->setAllowedAreas(Qt::BottomToolBarArea); + + //--------------------------------------------------- + // split + //--------------------------------------------------- + + splitter = new Splitter(Qt::Vertical, mainw, "splitter"); + splitter->setHandleWidth(2); + + hsplitter = new Splitter(Qt::Horizontal, mainw, "hsplitter"); + hsplitter->setChildrenCollapsible(true); + hsplitter->setHandleWidth(2); + + QPushButton* ctrl = new QPushButton(tr("ctrl"), mainw); + //QPushButton* ctrl = new QPushButton(tr("C"), mainw); // Tim. + ctrl->setObjectName("Ctrl"); + ctrl->setFont(config.fonts[3]); + ctrl->setToolTip(tr("Add Controller View")); + hscroll = new ScrollScale(-25, -2, xscale, 20000, Qt::Horizontal, mainw); + ctrl->setFixedSize(pianoWidth, hscroll->sizeHint().height()); + //ctrl->setFixedSize(pianoWidth / 2, hscroll->sizeHint().height()); // Tim. + + // Tim. + /* + QPushButton* trackInfoButton = new QPushButton(tr("T"), mainw); + trackInfoButton->setObjectName("TrackInfo"); + trackInfoButton->setFont(config.fonts[3]); + trackInfoButton->setToolTip(tr("Show track info")); + trackInfoButton->setFixedSize(pianoWidth / 2, hscroll->sizeHint().height()); + */ + + QSizeGrip* corner = new QSizeGrip(mainw); + + midiTrackInfo = new MidiTrackInfo(mainw); + midiTrackInfo->setObjectName("prTrackInfo"); + int mtiw = 280;//midiTrackInfo->width(); // Save this. + midiTrackInfo->setMinimumWidth(100); + //midiTrackInfo->setMaximumWidth(300); + connect(hsplitter, SIGNAL(splitterMoved(int, int)), midiTrackInfo, SLOT(updateSize())); + + //midiTrackInfo->setSizePolicy(QSizePolicy(/*QSizePolicy::Ignored*/QSizePolicy::Preferred, QSizePolicy::Expanding)); + infoScroll = new QScrollArea; + infoScroll->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + infoScroll->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); + //infoScroll->setMaximumWidth(300); + infoScroll->setMinimumWidth(100); + //infoScroll->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding)); + infoScroll->setWidget(midiTrackInfo); + infoScroll->setWidgetResizable(true); + //infoScroll->setObjectName("trackInfoScroll"); + //infoScroller->setAttribute(Qt::WA_NoBackground); + //infoScroll->setVisible(false); + //infoScroll->setEnabled(false); + + //hsplitter->addWidget(midiTrackInfo); + hsplitter->addWidget(infoScroll); // Tim. + hsplitter->addWidget(splitter); + + mainGrid->setRowStretch(0, 100); + mainGrid->setColumnStretch(1, 100); + mainGrid->addWidget(hsplitter, 0, 1, 1, 3); + + // Original. + /* + mainGrid->setColumnStretch(1, 100); + mainGrid->addWidget(splitter, 0, 0, 1, 3); + mainGrid->addWidget(ctrl, 1, 0); + mainGrid->addWidget(hscroll, 1, 1); + mainGrid->addWidget(corner, 1, 2, Qt::AlignBottom|Qt::AlignRight); + */ + + + // Tim. + /* + mainGrid->setColumnStretch(2, 100); + mainGrid->addWidget(splitter, 0, 0, 1, 4); + mainGrid->addWidget(trackInfoButton, 1, 0); + mainGrid->addWidget(ctrl, 1, 1); + mainGrid->addWidget(hscroll, 1, 2); + mainGrid->addWidget(corner, 1, 3, Qt::AlignBottom|Qt::AlignRight); + */ + + //mainGrid->addRowSpacing(1, hscroll->sizeHint().height()); + //mainGrid->addItem(new QSpacerItem(0, hscroll->sizeHint().height()), 1, 0); // Orig + Tim. + + QWidget* split1 = new QWidget(splitter); + split1->setObjectName("split1"); + QGridLayout* gridS1 = new QGridLayout(split1); + gridS1->setContentsMargins(0, 0, 0, 0); + gridS1->setSpacing(0); + //Defined and configure your program change bar here. + //This may well be a copy of MTScale extended for our needs + pcbar = new PCScale(&_raster, split1, this, xscale); + pcbar->setAudio(audio); + //pcbar->setEditor(this); + time = new MTScale(&_raster, split1, xscale); + Piano* piano = new Piano(split1, yscale); + canvas = new PianoCanvas(this, split1, xscale, yscale); + vscroll = new ScrollScale(-3, 7, yscale, KH * 75, Qt::Vertical, split1); + + //setFocusProxy(canvas); // Tim. + + int offset = -(config.division/4); + canvas->setOrigin(offset, 0); + canvas->setCanvasTools(pianorollTools); + canvas->setFocus(); + connect(canvas, SIGNAL(toolChanged(int)), tools2, SLOT(set(int))); + time->setOrigin(offset, 0); + pcbar->setOrigin(offset, 0); + + gridS1->setRowStretch(2, 100); + gridS1->setColumnStretch(1, 100); + //gridS1->setColumnStretch(2, 100); // Tim. + + gridS1->addWidget(pcbar, 0, 1, 1, 2); + gridS1->addWidget(time, 1, 1, 1, 2); + gridS1->addWidget(hLine(split1), 2, 0, 1, 3); + gridS1->addWidget(piano, 3, 0); + gridS1->addWidget(canvas, 3, 1); + gridS1->addWidget(vscroll, 3, 2); + + // Tim. + /* + gridS1->addWidget(time, 0, 2, 1, 3); + gridS1->addWidget(hLine(split1), 1, 1, 1, 4); + //gridS1->addWidget(infoScroll, 2, 0); + gridS1->addWidget(infoScroll, 0, 0, 3, 1); + gridS1->addWidget(piano, 2, 1); + gridS1->addWidget(canvas, 2, 2); + gridS1->addWidget(vscroll, 2, 3); + */ + + ctrlLane = new Splitter(Qt::Vertical, splitter, "ctrllane"); + QWidget* split2 = new QWidget(splitter); + split2->setMaximumHeight(hscroll->sizeHint().height()); + split2->setMinimumHeight(hscroll->sizeHint().height()); + QGridLayout* gridS2 = new QGridLayout(split2); + gridS2->setContentsMargins(0, 0, 0, 0); + gridS2->setSpacing(0); + gridS2->setRowStretch(0, 100); + gridS2->setColumnStretch(1, 100); + gridS2->addWidget(ctrl, 0, 0); + gridS2->addWidget(hscroll, 0, 1); + gridS2->addWidget(corner, 0, 2, Qt::AlignBottom|Qt::AlignRight); + //splitter->setCollapsible(0, true); + + piano->setFixedWidth(pianoWidth); + + // Tim. + QList<int> mops; + mops.append(mtiw); // 30 for possible scrollbar + mops.append(width() - mtiw); + hsplitter->setSizes(mops); + hsplitter->setStretchFactor(0, 0); + hsplitter->setStretchFactor(1, 15); + + connect(tools2, SIGNAL(toolChanged(int)), canvas, SLOT(setTool(int))); + + //connect(midiTrackInfo, SIGNAL(outputPortChanged(int)), list, SLOT(redraw())); + connect(ctrl, SIGNAL(clicked()), SLOT(addCtrl())); + //connect(trackInfoButton, SIGNAL(clicked()), SLOT(toggleTrackInfo())); Tim. + connect(info, SIGNAL(valueChanged(NoteInfo::ValType, int)), SLOT(noteinfoChanged(NoteInfo::ValType, int))); + connect(vscroll, SIGNAL(scrollChanged(int)), piano, SLOT(setYPos(int))); + connect(vscroll, SIGNAL(scrollChanged(int)), canvas, SLOT(setYPos(int))); + connect(vscroll, SIGNAL(scaleChanged(int)), canvas, SLOT(setYMag(int))); + connect(vscroll, SIGNAL(scaleChanged(int)), piano, SLOT(setYMag(int))); + + connect(hscroll, SIGNAL(scrollChanged(int)), canvas, SLOT(setXPos(int))); + connect(hscroll, SIGNAL(scrollChanged(int)), time, SLOT(setXPos(int))); + connect(hscroll, SIGNAL(scrollChanged(int)), pcbar, SLOT(setXPos(int))); + + connect(hscroll, SIGNAL(scaleChanged(int)), canvas, SLOT(setXMag(int))); + connect(hscroll, SIGNAL(scaleChanged(int)), time, SLOT(setXMag(int))); + connect(hscroll, SIGNAL(scaleChanged(int)), pcbar, SLOT(setXMag(int))); + + connect(canvas, SIGNAL(newWidth(int)), SLOT(newCanvasWidth(int))); + connect(canvas, SIGNAL(pitchChanged(int)), piano, SLOT(setPitch(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(canvas, SIGNAL(selectionChanged(int, Event&, Part*)), this, + SLOT(setSelection(int, Event&, Part*))); + + connect(piano, SIGNAL(keyPressed(int, int, bool)), canvas, SLOT(pianoPressed(int, int, bool))); + connect(piano, SIGNAL(keyReleased(int, bool)), canvas, SLOT(pianoReleased(int, bool))); + connect(srec, SIGNAL(toggled(bool)), SLOT(setSteprec(bool))); + //connect(midiin, SIGNAL(toggled(bool)), canvas, SLOT(setMidiin(bool))); + connect(speaker, SIGNAL(toggled(bool)), SLOT(setSpeaker(bool))); + connect(canvas, SIGNAL(followEvent(int)), SLOT(follow(int))); + + connect(hscroll, SIGNAL(scaleChanged(int)), SLOT(updateHScrollRange())); + piano->setYPos(KH * 30); + canvas->setYPos(KH * 30); + vscroll->setPos(KH * 30); + //setSelection(0, 0, 0); //Really necessary? Causes segfault when only 1 item selected, replaced by the following: + info->setEnabled(false); + + connect(song, SIGNAL(songChanged(int)), SLOT(songChanged1(int))); + + setWindowTitle(canvas->getCaption()); + + updateHScrollRange(); + // connect to toolbar + connect(canvas, SIGNAL(pitchChanged(int)), toolbar, SLOT(setPitch(int))); + connect(canvas, SIGNAL(timeChanged(unsigned)), SLOT(setTime(unsigned))); + connect(piano, SIGNAL(pitchChanged(int)), toolbar, SLOT(setPitch(int))); + connect(time, SIGNAL(timeChanged(unsigned)), SLOT(setTime(unsigned))); + connect(pcbar, SIGNAL(selectInstrument()), midiTrackInfo, SLOT(instrPopup())); + connect(pcbar, SIGNAL(addProgramChange()), midiTrackInfo, SLOT(progRecClicked())); + connect(toolbar, SIGNAL(quantChanged(int)), SLOT(setQuant(int))); + connect(toolbar, SIGNAL(rasterChanged(int)),SLOT(setRaster(int))); + connect(toolbar, SIGNAL(toChanged(int)), SLOT(setTo(int))); + connect(toolbar, SIGNAL(soloChanged(bool)), SLOT(soloChanged(bool))); + + setFocusPolicy(Qt::StrongFocus); + setEventColorMode(colorMode); + canvas->setMidiin(true); + midiin->setChecked(true); + canvas->playEvents(true); + speaker->setChecked(true); + + QClipboard* cb = QApplication::clipboard(); + connect(cb, SIGNAL(dataChanged()), SLOT(clipboardChanged())); + + clipboardChanged(); // enable/disable "Paste" + selectionChanged(); // enable/disable "Copy" & "Paste" + initShortcuts(); // initialize shortcuts + + const Pos cpos=song->cPos(); + canvas->setPos(0, cpos.tick(), true); + canvas->selectAtTick(cpos.tick()); + //canvas->selectFirst(); +// + if(canvas->track()) + { + updateTrackInfo(); + toolbar->setSolo(canvas->track()->solo()); + } + + unsigned pos; + if(initPos >= MAXINT) + pos = song->cpos(); + else + pos = initPos; + if(pos > MAXINT) + pos = MAXINT; + + // At this point in time the range of the canvas hasn't + // been calculated right ? + // Also, why wanting to restore some initPos, what is initPos? + // To me, it seems to make a lot more sense to use the actual + // current song cpos. + // This is now done via the showEvent(); + +// hscroll->setOffset((int)pos); // changed that to: +} + +//--------------------------------------------------------- +// songChanged1 +//--------------------------------------------------------- + +void PianoRoll::songChanged1(int bits) + { + + if (bits & SC_SOLO) + { + toolbar->setSolo(canvas->track()->solo()); + return; + } + songChanged(bits); + //trackInfo->songChanged(bits); + // We'll receive SC_SELECTION if a different part is selected. + if (bits & SC_SELECTION) + updateTrackInfo(); + } + +//--------------------------------------------------------- +// configChanged +//--------------------------------------------------------- + +void PianoRoll::configChanged() + { + initShortcuts(); + //trackInfo->updateTrackInfo(); + } + +//--------------------------------------------------------- +// updateHScrollRange +//--------------------------------------------------------- + +void PianoRoll::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 the fixed piano and vscroll widths. + e += canvas->rmapxDev(pianoWidth - vscroll->width()); + int s1, e1; + hscroll->range(&s1, &e1); + if(s != s1 || e != e1) + hscroll->setRange(s, e); +} + +void PianoRoll::updateTrackInfo() +{ + selected = curCanvasPart()->track(); + if (selected->isMidiTrack()) { + midiTrackInfo->setTrack(selected); + ///midiTrackInfo->updateTrackInfo(-1); + } +} + +//--------------------------------------------------------- +// follow +//--------------------------------------------------------- + +void PianoRoll::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 PianoRoll::setTime(unsigned tick) + { + toolbar->setTime(tick); + time->setPos(3, tick, false); + pcbar->setPos(3, tick, false); + } + +//--------------------------------------------------------- +// ~Pianoroll +//--------------------------------------------------------- + +PianoRoll::~PianoRoll() + { + // undoRedo->removeFrom(tools); // p4.0.6 Removed + } + +//--------------------------------------------------------- +// cmd +// pulldown menu commands +//--------------------------------------------------------- + +void PianoRoll::cmd(int cmd) + { + ((PianoCanvas*)canvas)->cmd(cmd, _quantStrength, _quantLimit, _quantLen, _to); + } + +//--------------------------------------------------------- +// setSelection +// update Info Line +//--------------------------------------------------------- + +void PianoRoll::setSelection(int tick, Event& e, Part* p) + { + int selections = canvas->selectionSize(); + + selEvent = e; + selPart = (MidiPart*)p; + selTick = tick; + + if (selections > 1) { + info->setEnabled(true); + info->setDeltaMode(true); + if (!deltaMode) { + deltaMode = true; + info->setValues(0, 0, 0, 0, 0); + tickOffset = 0; + lenOffset = 0; + pitchOffset = 0; + veloOnOffset = 0; + veloOffOffset = 0; + } + } + else if (selections == 1) { + deltaMode = false; + info->setEnabled(true); + info->setDeltaMode(false); + info->setValues(tick, + selEvent.lenTick(), + selEvent.pitch(), + selEvent.velo(), + selEvent.veloOff()); + } + else { + deltaMode = false; + info->setEnabled(false); + } + selectionChanged(); + } + +//--------------------------------------------------------- +// edit currently selected Event +//--------------------------------------------------------- + +void PianoRoll::noteinfoChanged(NoteInfo::ValType type, int val) + { + int selections = canvas->selectionSize(); + + if (selections == 0) { + printf("noteinfoChanged while nothing selected\n"); + } + else if (selections == 1) { + Event event = selEvent.clone(); + switch(type) { + case NoteInfo::VAL_TIME: + event.setTick(val - selPart->tick()); + break; + case NoteInfo::VAL_LEN: + event.setLenTick(val); + break; + case NoteInfo::VAL_VELON: + event.setVelo(val); + break; + case NoteInfo::VAL_VELOFF: + event.setVeloOff(val); + break; + case NoteInfo::VAL_PITCH: + event.setPitch(val); + break; + } + // 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); + } + else { + // multiple events are selected; treat noteinfo values + // as offsets to event values + + int delta = 0; + switch (type) { + case NoteInfo::VAL_TIME: + delta = val - tickOffset; + tickOffset = val; + break; + case NoteInfo::VAL_LEN: + delta = val - lenOffset; + lenOffset = val; + break; + case NoteInfo::VAL_VELON: + delta = val - veloOnOffset; + veloOnOffset = val; + break; + case NoteInfo::VAL_VELOFF: + delta = val - veloOffOffset; + veloOffOffset = val; + break; + case NoteInfo::VAL_PITCH: + delta = val - pitchOffset; + pitchOffset = val; + break; + } + if (delta) + canvas->modifySelected(type, delta); + } + } + +//--------------------------------------------------------- +// addCtrl +//--------------------------------------------------------- + +CtrlEdit* PianoRoll::addCtrl() + { + ///CtrlEdit* ctrlEdit = new CtrlEdit(splitter, this, xscale, false, "pianoCtrlEdit"); + CtrlEdit* ctrlEdit = new CtrlEdit(ctrlLane/*splitter*/, this, xscale, false, "pianoCtrlEdit"); // ccharrett + connect(tools2, SIGNAL(toolChanged(int)), ctrlEdit, SLOT(setTool(int))); + 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))); + + ctrlEdit->setTool(tools2->curTool()); + ctrlEdit->setXPos(hscroll->pos()); + ctrlEdit->setXMag(hscroll->getScaleValue()); + + ctrlEdit->show(); + ctrlEditList.push_back(ctrlEdit); + return ctrlEdit; + } + +//--------------------------------------------------------- +// removeCtrl +//--------------------------------------------------------- + +void PianoRoll::removeCtrl(CtrlEdit* ctrl) + { + for (std::list<CtrlEdit*>::iterator i = ctrlEditList.begin(); + i != ctrlEditList.end(); ++i) { + if (*i == ctrl) { + ctrlEditList.erase(i); + break; + } + } + } + +//--------------------------------------------------------- +// closeEvent +//--------------------------------------------------------- + +void PianoRoll::closeEvent(QCloseEvent* e) + { + emit deleted((unsigned long)this); + e->accept(); + } + +//--------------------------------------------------------- +// readConfiguration +//--------------------------------------------------------- + +void PianoRoll::readConfiguration(Xml& xml) + { + for (;;) { + Xml::Token token = xml.parse(); + if (token == Xml::Error || token == Xml::End) + break; + const QString& tag = xml.s1(); + switch (token) { + case Xml::TagStart: + if (tag == "quant") + _quantInit = xml.parseInt(); + else if (tag == "raster") + _rasterInit = xml.parseInt(); + else if (tag == "quantStrength") + _quantStrengthInit = xml.parseInt(); + else if (tag == "quantLimit") + _quantLimitInit = xml.parseInt(); + else if (tag == "quantLen") + _quantLenInit = xml.parseInt(); + else if (tag == "to") + _toInit = xml.parseInt(); + else if (tag == "colormode") + colorModeInit = xml.parseInt(); + else if (tag == "width") + _widthInit = xml.parseInt(); + else if (tag == "height") + _heightInit = xml.parseInt(); + else + xml.unknown("PianoRoll"); + break; + case Xml::TagEnd: + if (tag == "pianoroll") + return; + default: + break; + } + } + } + +//--------------------------------------------------------- +// writeConfiguration +//--------------------------------------------------------- + +void PianoRoll::writeConfiguration(int level, Xml& xml) + { + xml.tag(level++, "pianoroll"); + xml.intTag(level, "quant", _quantInit); + xml.intTag(level, "raster", _rasterInit); + xml.intTag(level, "quantStrength", _quantStrengthInit); + xml.intTag(level, "quantLimit", _quantLimitInit); + xml.intTag(level, "quantLen", _quantLenInit); + xml.intTag(level, "to", _toInit); + xml.intTag(level, "width", _widthInit); + xml.intTag(level, "height", _heightInit); + xml.intTag(level, "colormode", colorModeInit); + xml.etag(level, "pianoroll"); + } + +//--------------------------------------------------------- +// soloChanged +// signal from solo button +//--------------------------------------------------------- + +void PianoRoll::soloChanged(bool flag) + { + audio->msgSetSolo(canvas->track(), flag); + song->update(SC_SOLO); + } + +//--------------------------------------------------------- +// setRaster +//--------------------------------------------------------- + +void PianoRoll::setRaster(int val) + { + _rasterInit = val; + MidiEditor::setRaster(val); + canvas->redrawGrid(); + canvas->setFocus(); // give back focus after kb input + } + +//--------------------------------------------------------- +// setQuant +//--------------------------------------------------------- + +void PianoRoll::setQuant(int val) + { + _quantInit = val; + MidiEditor::setQuant(val); + canvas->setFocus(); + } + +//--------------------------------------------------------- +// writeStatus +//--------------------------------------------------------- + +void PianoRoll::writeStatus(int level, Xml& xml) const + { + writePartList(level, xml); + xml.tag(level++, "pianoroll"); + MidiEditor::writeStatus(level, xml); + splitter->writeStatus(level, xml); + hsplitter->writeStatus(level, xml); + + for (std::list<CtrlEdit*>::const_iterator i = ctrlEditList.begin(); + i != ctrlEditList.end(); ++i) { + (*i)->writeStatus(level, xml); + } + + xml.intTag(level, "steprec", canvas->steprec()); + xml.intTag(level, "midiin", canvas->midiin()); + xml.intTag(level, "tool", int(canvas->tool())); + xml.intTag(level, "quantStrength", _quantStrength); + xml.intTag(level, "quantLimit", _quantLimit); + xml.intTag(level, "quantLen", _quantLen); + xml.intTag(level, "playEvents", _playEvents); + 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, "/pianoroll"); + } + +//--------------------------------------------------------- +// readStatus +//--------------------------------------------------------- + +void PianoRoll::readStatus(Xml& xml) + { + for (;;) { + Xml::Token token = xml.parse(); + if (token == Xml::Error || token == Xml::End) + break; + const QString& tag = xml.s1(); + switch (token) { + 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 == "tool") { + int tool = xml.parseInt(); + canvas->setTool(tool); + tools2->set(tool); + } + else if (tag == "midieditor") + MidiEditor::readStatus(xml); + else if (tag == "ctrledit") { + CtrlEdit* ctrl = addCtrl(); + ctrl->readStatus(xml); + } + else if (tag == splitter->objectName()) + splitter->readStatus(xml); + else if (tag == hsplitter->objectName()) + hsplitter->readStatus(xml); + else if (tag == "quantStrength") + _quantStrength = xml.parseInt(); + else if (tag == "quantLimit") + _quantLimit = xml.parseInt(); + else if (tag == "quantLen") + _quantLen = xml.parseInt(); + else if (tag == "playEvents") { + _playEvents = xml.parseInt(); + canvas->playEvents(_playEvents); + speaker->setChecked(_playEvents); + } + 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("PianoRoll"); + break; + case Xml::TagEnd: + if (tag == "pianoroll") { + _quantInit = _quant; + _rasterInit = _raster; + toolbar->setRaster(_raster); + toolbar->setQuant(_quant); + canvas->redrawGrid(); + return; + } + default: + break; + } + } + } + +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 + }; + +//--------------------------------------------------------- +// viewKeyPressEvent +//--------------------------------------------------------- + +void PianoRoll::keyPressEvent(QKeyEvent* event) + { + if (info->hasFocus()) { + event->ignore(); + return; + } + + int index; + int n = sizeof(rasterTable)/sizeof(*rasterTable); + for (index = 0; index < n; ++index) + if (rasterTable[index] == raster()) + break; + if (index == n) { + index = 0; + // raster 1 is not in table + } + int off = (index / 9) * 9; + index = index % 9; + + int val = 0; + + PianoCanvas* pc = (PianoCanvas*)canvas; + int key = event->key(); + + //if (event->state() & Qt::ShiftButton) + if (((QInputEvent*)event)->modifiers() & Qt::ShiftModifier) + key += Qt::SHIFT; + //if (event->state() & Qt::AltButton) + if (((QInputEvent*)event)->modifiers() & Qt::AltModifier) + key += Qt::ALT; + //if (event->state() & Qt::ControlButton) + if (((QInputEvent*)event)->modifiers() & Qt::ControlModifier) + key+= Qt::CTRL; + + if (key == Qt::Key_Escape) { + close(); + 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_TOOL_LINEDRAW].key) { + tools2->set(DrawTool); + return; + } + else if (key == shortcuts[SHRT_POS_INC].key) { + pc->pianoCmd(CMD_RIGHT); + return; + } + else if (key == shortcuts[SHRT_POS_DEC].key) { + pc->pianoCmd(CMD_LEFT); + return; + } + else if (key == shortcuts[SHRT_POS_INC_NOSNAP].key) { + pc->pianoCmd(CMD_RIGHT_NOSNAP); + return; + } + else if (key == shortcuts[SHRT_POS_DEC_NOSNAP].key) { + pc->pianoCmd(CMD_LEFT_NOSNAP); + return; + } + else if (key == shortcuts[SHRT_INSERT_AT_LOCATION].key) { + pc->pianoCmd(CMD_INSERT); + return; + } + else if (key == Qt::Key_Delete) { + pc->pianoCmd(CMD_DELETE); + 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_GOTO_CPOS].key) { + PartList* p = this->parts(); + Part* first = p->begin()->second; + hscroll->setPos(song->cpos() - first->tick() ); + 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_SEL_INSTRUMENT].key) { + midiTrackInfo->instrPopup(); + return; + } + else if (key == shortcuts[SHRT_ADD_PROGRAM].key) { + midiTrackInfo->insertMatrixEvent();//progRecClicked(); + return; + } + else if (key == shortcuts[SHRT_DEL_PROGRAM].key) { + //printf("Delete KeyStroke recieved\n"); + int x = song->cpos(); + Track* track = song->findTrack(curCanvasPart());/*{{{*/ + PartList* parts = track->parts(); + for (iPart p = parts->begin(); p != parts->end(); ++p) + { + Part* mprt = p->second; + EventList* eventList = mprt->events();//m->second.events(); + for(iEvent evt = eventList->begin(); evt != eventList->end(); ++evt) + { + //Get event type. + Event pcevt = evt->second; + //printf("Found events %d \n", pcevt.type()); + if(!pcevt.isNote()) + { + //printf("Found none Note events of type: %d with dataA: %d\n", pcevt.type(), pcevt.dataA()); + if(pcevt.type() == Controller && pcevt.dataA() == CTRL_PROGRAM) + { + //printf("Found Program Change event type\n"); + //printf("Pos x: %d\n", x); + int xp = pcevt.tick()+mprt->tick(); + //printf("Event x: %d\n", xp); + if(xp >= x && xp <= (x+50)) + { + //printf("Found Program Change to delete at: %d\n", x); + song->startUndo(); + audio->msgDeleteEvent(evt->second, p->second, true, true, true); + song->endUndo(SC_EVENT_MODIFIED); + } + } + } + } + }/*}}}*/ + //pcbar->deleteProgram(); + 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); +} + +//--------------------------------------------------------- +// configQuant +//--------------------------------------------------------- + +void PianoRoll::configQuant() + { + if (!quantConfig) { + quantConfig = new QuantConfig(_quantStrength, _quantLimit, _quantLen); + connect(quantConfig, SIGNAL(setQuantStrength(int)), SLOT(setQuantStrength(int))); + connect(quantConfig, SIGNAL(setQuantLimit(int)), SLOT(setQuantLimit(int))); + connect(quantConfig, SIGNAL(setQuantLen(bool)), SLOT(setQuantLen(bool))); + } + quantConfig->show(); + } + +//--------------------------------------------------------- +// setSteprec +//--------------------------------------------------------- + +void PianoRoll::setSteprec(bool flag) +{ + canvas->setSteprec(flag); + //if (flag == false) + // midiin->setChecked(flag); +} + +//--------------------------------------------------------- +// eventColorModeChanged +//--------------------------------------------------------- + +void PianoRoll::eventColorModeChanged(int mode) + { + colorMode = mode; + colorModeInit = colorMode; + + ((PianoCanvas*)(canvas))->setColorMode(colorMode); + } + +//--------------------------------------------------------- +// setEventColorMode +//--------------------------------------------------------- + +void PianoRoll::setEventColorMode(int mode) + { + colorMode = mode; + colorModeInit = colorMode; + + ///eventColor->setItemChecked(0, mode == 0); + ///eventColor->setItemChecked(1, mode == 1); + ///eventColor->setItemChecked(2, mode == 2); + evColorBlueAction->setChecked(mode == 0); + evColorPitchAction->setChecked(mode == 1); + evColorVelAction->setChecked(mode == 2); + + ((PianoCanvas*)(canvas))->setColorMode(colorMode); + } + +//--------------------------------------------------------- +// clipboardChanged +//--------------------------------------------------------- + +void PianoRoll::clipboardChanged() + { + editPasteAction->setEnabled(QApplication::clipboard()->mimeData()->hasFormat(QString("text/x-muse-eventlist"))); + } + +//--------------------------------------------------------- +// selectionChanged +//--------------------------------------------------------- + +void PianoRoll::selectionChanged() + { + bool flag = canvas->selectionSize() > 0; + editCutAction->setEnabled(flag); + editCopyAction->setEnabled(flag); + editDelEventsAction->setEnabled(flag); + } + +//--------------------------------------------------------- +// setSpeaker +//--------------------------------------------------------- + +void PianoRoll::setSpeaker(bool val) + { + _playEvents = val; + canvas->playEvents(_playEvents); + } + +//--------------------------------------------------------- +// resizeEvent +//--------------------------------------------------------- + +void PianoRoll::resizeEvent(QResizeEvent* ev) + { + QWidget::resizeEvent(ev); + _widthInit = ev->size().width(); + _heightInit = ev->size().height(); + } + +//--------------------------------------------------------- +// showEvent +// Now that every gui element is created, including +// the scroll bars, what about updating the scrollbars +// so that the play cursor is in the center of the viewport? +//--------------------------------------------------------- + +void PianoRoll::showEvent(QShowEvent *) +{ + // maybe add a bool flag to follow: centered ? + // couldn't find a function that does that directly. + follow(song->cpos()); + // now that the cursor is in the view, move the view + // half the canvas width so the cursor is centered. + hscroll->setPos(hscroll->pos() - (canvas->width()/2)); +} + +/* +//--------------------------------------------------------- +// trackInfoScroll +//--------------------------------------------------------- + +void PianoRoll::trackInfoScroll(int y) + { + if (trackInfo->visibleWidget()) + trackInfo->visibleWidget()->move(0, -y); + } +*/ + +//--------------------------------------------------------- +// initShortcuts +//--------------------------------------------------------- + +void PianoRoll::initShortcuts() + { + editCutAction->setShortcut(shortcuts[SHRT_CUT].key); + editCopyAction->setShortcut(shortcuts[SHRT_COPY].key); + editPasteAction->setShortcut(shortcuts[SHRT_PASTE].key); + editDelEventsAction->setShortcut(shortcuts[SHRT_DELETE].key); + + selectAllAction->setShortcut(shortcuts[SHRT_SELECT_ALL].key); + selectNoneAction->setShortcut(shortcuts[SHRT_SELECT_NONE].key); + selectInvertAction->setShortcut(shortcuts[SHRT_SELECT_INVERT].key); + selectInsideLoopAction->setShortcut(shortcuts[SHRT_SELECT_ILOOP].key); + selectOutsideLoopAction->setShortcut(shortcuts[SHRT_SELECT_OLOOP].key); + selectPrevPartAction->setShortcut(shortcuts[SHRT_SELECT_PREV_PART].key); + selectNextPartAction->setShortcut(shortcuts[SHRT_SELECT_NEXT_PART].key); + + eventColor->menuAction()->setShortcut(shortcuts[SHRT_EVENT_COLOR].key); + //evColorBlueAction->setShortcut(shortcuts[ ].key); + //evColorPitchAction->setShortcut(shortcuts[ ].key); + //evColorVelAction->setShortcut(shortcuts[ ].key); + + funcOverQuantAction->setShortcut(shortcuts[SHRT_OVER_QUANTIZE].key); + funcNoteOnQuantAction->setShortcut(shortcuts[SHRT_ON_QUANTIZE].key); + funcNoteOnOffQuantAction->setShortcut(shortcuts[SHRT_ONOFF_QUANTIZE].key); + funcIterQuantAction->setShortcut(shortcuts[SHRT_ITERATIVE_QUANTIZE].key); + + funcConfigQuantAction->setShortcut(shortcuts[SHRT_CONFIG_QUANT].key); + + funcGateTimeAction->setShortcut(shortcuts[SHRT_MODIFY_GATE_TIME].key); + funcModVelAction->setShortcut(shortcuts[SHRT_MODIFY_VELOCITY].key); + funcCrescendoAction->setShortcut(shortcuts[SHRT_CRESCENDO].key); + funcTransposeAction->setShortcut(shortcuts[SHRT_TRANSPOSE].key); + funcThinOutAction->setShortcut(shortcuts[SHRT_THIN_OUT].key); + funcEraseEventAction->setShortcut(shortcuts[SHRT_ERASE_EVENT].key); + funcNoteShiftAction->setShortcut(shortcuts[SHRT_NOTE_SHIFT].key); + funcMoveClockAction->setShortcut(shortcuts[SHRT_MOVE_CLOCK].key); + funcCopyMeasureAction->setShortcut(shortcuts[SHRT_COPY_MEASURE].key); + funcEraseMeasureAction->setShortcut(shortcuts[SHRT_ERASE_MEASURE].key); + funcDelMeasureAction->setShortcut(shortcuts[SHRT_DELETE_MEASURE].key); + funcCreateMeasureAction->setShortcut(shortcuts[SHRT_CREATE_MEASURE].key); + funcSetFixedLenAction->setShortcut(shortcuts[SHRT_FIXED_LEN].key); + funcDelOverlapsAction->setShortcut(shortcuts[SHRT_DELETE_OVERLAPS].key); + + } + +//--------------------------------------------------------- +// execDeliveredScript +//--------------------------------------------------------- +void PianoRoll::execDeliveredScript(int id) +{ + //QString scriptfile = QString(INSTPREFIX) + SCRIPTSSUFFIX + deliveredScriptNames[id]; + QString scriptfile = song->getScriptPath(id, true); + song->executeScript(scriptfile.toAscii().data(), parts(), quant(), true); +} + +//--------------------------------------------------------- +// execUserScript +//--------------------------------------------------------- +void PianoRoll::execUserScript(int id) +{ + QString scriptfile = song->getScriptPath(id, false); + song->executeScript(scriptfile.toAscii().data(), parts(), quant(), true); +} + +//--------------------------------------------------------- +// newCanvasWidth +//--------------------------------------------------------- + +void PianoRoll::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(); +*/ + } + +//--------------------------------------------------------- +// toggleTrackInfo +//--------------------------------------------------------- + +void PianoRoll::toggleTrackInfo() +{ + bool vis = midiTrackInfo->isVisible(); + infoScroll->setVisible(!vis); + infoScroll->setEnabled(!vis); +} diff --git a/attic/muse2-oom/muse2/muse/midiedit/pianoroll.h b/attic/muse2-oom/muse2/muse/midiedit/pianoroll.h new file mode 100644 index 00000000..f7469ec6 --- /dev/null +++ b/attic/muse2-oom/muse2/muse/midiedit/pianoroll.h @@ -0,0 +1,204 @@ +//========================================================= +// MusE +// Linux Music Editor +// $Id: pianoroll.h,v 1.5.2.4 2009/11/16 11:29:33 lunar_shuttle Exp $ +// (C) Copyright 1999 Werner Schweer (ws@seh.de) +//========================================================= + +#ifndef __PIANOROLL_H__ +#define __PIANOROLL_H__ + +#include <QCloseEvent> +#include <QResizeEvent> +#include <QLabel> +#include <QKeyEvent> + +#include <values.h> +#include "noteinfo.h" +#include "cobject.h" +#include "midieditor.h" +#include "tools.h" +#include "event.h" + +class MidiPart; +class TimeLabel; +class PitchLabel; +class QLabel; +class PianoCanvas; +class MTScale; +class PCScale; +class Track; +class QToolButton; +class QToolBar; +class QPushButton; +class CtrlEdit; +class Splitter; +class PartList; +class Toolbar1; +class Xml; +class QuantConfig; +class ScrollScale; +class Part; +class SNode; +class QMenu; +class QAction; +class QWidget; +class QScrollBar; +class MidiTrackInfo; +class QScrollArea; + +//--------------------------------------------------------- +// PianoRoll +//--------------------------------------------------------- + +class PianoRoll : public MidiEditor { + Event selEvent; + MidiPart* selPart; + int selTick; + + //enum { CMD_EVENT_COLOR, CMD_CONFIG_QUANT, CMD_LAST }; + //int menu_ids[CMD_LAST]; + //Q3PopupMenu *menuEdit, *menuFunctions, *menuSelect, *menuConfig, *menuPlugins; + + + QMenu *menuEdit, *menuFunctions, *menuSelect, *menuConfig, *eventColor, *menuPlugins; + MidiTrackInfo *midiTrackInfo; + Track* selected; + PCScale* pcbar; + + QAction* editCutAction; + QAction* editCopyAction; + QAction* editPasteAction; + QAction* editDelEventsAction; + + QAction* selectAllAction; + QAction* selectNoneAction; + QAction* selectInvertAction; + QAction* selectInsideLoopAction; + QAction* selectOutsideLoopAction; + QAction* selectPrevPartAction; + QAction* selectNextPartAction; + + QAction* evColorBlueAction; + QAction* evColorPitchAction; + QAction* evColorVelAction; + + QAction* funcOverQuantAction; + QAction* funcNoteOnQuantAction; + QAction* funcNoteOnOffQuantAction; + QAction* funcIterQuantAction; + QAction* funcConfigQuantAction; + QAction* funcGateTimeAction; + QAction* funcModVelAction; + QAction* funcCrescendoAction; + QAction* funcTransposeAction; + QAction* funcThinOutAction; + QAction* funcEraseEventAction; + QAction* funcNoteShiftAction; + QAction* funcMoveClockAction; + QAction* funcCopyMeasureAction; + QAction* funcEraseMeasureAction; + QAction* funcDelMeasureAction; + QAction* funcCreateMeasureAction; + QAction* funcSetFixedLenAction; + QAction* funcDelOverlapsAction; + + + int tickOffset; + int lenOffset; + int pitchOffset; + int veloOnOffset; + int veloOffOffset; + bool deltaMode; + + NoteInfo* info; + QToolButton* srec; + QToolButton* midiin; + + Toolbar1* toolbar; + Splitter* splitter; + Splitter* hsplitter; + Splitter* ctrlLane; + + QToolButton* speaker; + QToolBar* tools; + EditToolBar* tools2; + + int colorMode; + + static int _quantInit, _rasterInit; + static int _widthInit, _heightInit; + + static int _quantStrengthInit; + static int _quantLimitInit; + static bool _quantLenInit; + static int _toInit; + static int colorModeInit; + + int _quantStrength; + int _quantLimit; + int _to; + bool _quantLen; + QuantConfig* quantConfig; + bool _playEvents; + + //QScrollBar* infoScroll; + QScrollArea* infoScroll; + + Q_OBJECT + void initShortcuts(); + void setEventColorMode(int); + QWidget* genToolbar(QWidget* parent); + virtual void closeEvent(QCloseEvent*); + virtual void keyPressEvent(QKeyEvent*); + virtual void resizeEvent(QResizeEvent*); + virtual void showEvent(QShowEvent *); + + private slots: + void setSelection(int, Event&, Part*); + void noteinfoChanged(NoteInfo::ValType, int); + //CtrlEdit* addCtrl(); + void removeCtrl(CtrlEdit* ctrl); + void soloChanged(bool flag); + //void trackInfoScroll(int); + void setRaster(int); + void setQuant(int); + void configQuant(); + void setQuantStrength(int val) { _quantStrength = val; } + void setQuantLimit(int val) { _quantLimit = val; } + void setQuantLen(bool val) { _quantLen = val; } + void cmd(int); + void setSteprec(bool); + void setTo(int val) { _to = val; } + void eventColorModeChanged(int); + void clipboardChanged(); // enable/disable "Paste" + void selectionChanged(); // enable/disable "Copy" & "Paste" + void setSpeaker(bool); + void setTime(unsigned); + void follow(int pos); + void songChanged1(int); + void configChanged(); + void newCanvasWidth(int); + void toggleTrackInfo(); + void updateTrackInfo(); + + signals: + void deleted(unsigned long); + + public slots: + virtual void updateHScrollRange(); + void execDeliveredScript(int id); + void execUserScript(int id); + CtrlEdit* addCtrl(); + + public: + PianoRoll(PartList*, QWidget* parent = 0, const char* name = 0, unsigned initPos = MAXINT); + ~PianoRoll(); + virtual void readStatus(Xml&); + virtual void writeStatus(int, Xml&) const; + static void readConfiguration(Xml&); + static void writeConfiguration(int, Xml&); + }; + +#endif + diff --git a/attic/muse2-oom/muse2/muse/midiedit/prcanvas.cpp b/attic/muse2-oom/muse2/muse/midiedit/prcanvas.cpp new file mode 100644 index 00000000..28d0d049 --- /dev/null +++ b/attic/muse2-oom/muse2/muse/midiedit/prcanvas.cpp @@ -0,0 +1,1864 @@ +//========================================================= +// MusE +// Linux Music Editor +// $Id: prcanvas.cpp,v 1.20.2.19 2009/11/16 11:29:33 lunar_shuttle Exp $ +// (C) Copyright 1999-2004 Werner Schweer (ws@seh.de) +//========================================================= + +#include <QApplication> +#include <QClipboard> +#include <QPainter> +#include <QDrag> +#include <QDragLeaveEvent> +#include <QDragEnterEvent> +#include <QDragMoveEvent> +#include <QDropEvent> +#include <QMouseEvent> + +#include <values.h> +#include <stdio.h> +#include <math.h> +#include <errno.h> +//#include <sys/stat.h> +//#include <sys/types.h> +//#include <sys/mman.h> +//#include <fcntl.h> +//#include <dirent.h> + +#include "xml.h" +#include "prcanvas.h" +#include "midiport.h" +#include "event.h" +#include "mpevent.h" +#include "globals.h" +#include "cmd.h" +#include "gatetime.h" +#include "velocity.h" +#include "song.h" +#include "audio.h" + +//--------------------------------------------------------- +// NEvent +//--------------------------------------------------------- + +NEvent::NEvent(Event& e, Part* p, int y) : CItem(e, p) + { + y = y - KH/4; + unsigned tick = e.tick() + p->tick(); + setPos(QPoint(tick, y)); + setBBox(QRect(tick, y, e.lenTick(), KH/2)); + } + +//--------------------------------------------------------- +// addItem +//--------------------------------------------------------- + +void PianoCanvas::addItem(Part* part, Event& event) + { + if (signed(event.tick())<0) { + printf("ERROR: trying to add event before current part!\n"); + return; + } + + NEvent* ev = new NEvent(event, part, pitch2y(event.pitch())); + 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); + } + } + +//--------------------------------------------------------- +// PianoCanvas +//--------------------------------------------------------- + +PianoCanvas::PianoCanvas(MidiEditor* pr, QWidget* parent, int sx, int sy) + : EventCanvas(pr, parent, sx, sy) + { + colorMode = 0; + cmdRange = 0; // all Events + playedPitch = -1; + + songChanged(SC_TRACK_INSERTED); + connect(song, SIGNAL(midiNote(int, int)), SLOT(midiNote(int,int))); + } + +//--------------------------------------------------------- +// pitch2y +//--------------------------------------------------------- + +int PianoCanvas::pitch2y(int pitch) const + { + int tt[] = { + 5, 12, 19, 26, 33, 44, 51, 58, 64, 71, 78, 85 + }; + int y = (75 * KH) - (tt[pitch%12] + (7 * KH) * (pitch/12)); + if (y < 0) + y = 0; + return y; + } + +//--------------------------------------------------------- +// y2pitch +//--------------------------------------------------------- + +int PianoCanvas::y2pitch(int y) const + { + const int total = (10 * 7 + 5) * KH; // 75 Ganztonschritte + y = total - y; + int oct = (y / (7 * KH)) * 12; + char kt[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 5 + 1, 1, 1, 1, 1, 1, 1, // 13 + 2, 2, 2, 2, 2, 2, // 19 + 3, 3, 3, 3, 3, 3, 3, // 26 + 4, 4, 4, 4, 4, 4, 4, 4, 4, // 34 + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, // 43 + 6, 6, 6, 6, 6, 6, 6, // 52 + 7, 7, 7, 7, 7, 7, // 58 + 8, 8, 8, 8, 8, 8, 8, // 65 + 9, 9, 9, 9, 9, 9, // 71 + 10, 10, 10, 10, 10, 10, 10, // 78 + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11 // 87 + }; + return kt[y % 91] + oct; + } + +//--------------------------------------------------------- +// drawEvent +// draws a note +//--------------------------------------------------------- + +void PianoCanvas::drawItem(QPainter& p, const CItem* item, + const QRect& rect) +{ + QRect r = item->bbox(); + if(!virt()) + r.moveCenter(map(item->pos())); + r = r.intersected(rect); + if(!r.isValid()) + return; + p.setPen(Qt::black); + struct Triple + { + int r, g, b; + }; + + static Triple myColors /*Qt::color1*/[12] = + { // ddskrjp + { 0xff, 0x3d, 0x39 }, + { 0x39, 0xff, 0x39 }, + { 0x39, 0x3d, 0xff }, + { 0xff, 0xff, 0x39 }, + { 0xff, 0x3d, 0xff }, + { 0x39, 0xff, 0xff }, + { 0xff, 0x7e, 0x7a }, + { 0x7a, 0x7e, 0xff }, + { 0x7a, 0xff, 0x7a }, + { 0xff, 0x7e, 0xbf }, + { 0x7a, 0xbf, 0xff }, + { 0xff, 0xbf, 0x7a } + }; + + QPen mainPen(Qt::black, 1, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin); + p.setPen(mainPen); + + QColor colMoving; + colMoving.setRgb(220, 220, 120, 127); + + QPen movingPen(Qt::darkGray, 1, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin); + + QColor colSelected; + colSelected.setRgb(243, 206, 105, 127); + + NEvent* nevent = (NEvent*) item; + Event event = nevent->event(); + if (nevent->part() != curPart) + { + if(item->isMoving()) + { + p.setPen(movingPen); + p.setBrush(colMoving); + } + else if(item->isSelected()) + { + p.setPen(mainPen); + p.setBrush(colSelected); + } + else + { + p.setPen(movingPen); + p.setBrush(QColor(192,192,192,127)); + } + } + else { + if (item->isMoving()) + { + p.setPen(movingPen); + p.setBrush(colMoving); + //p.setBrush(Qt::gray); + } + else if (item->isSelected()) + { + p.setPen(mainPen); + p.setBrush(colSelected); + } + else + { + QColor color; + //color.setRgb(80, 102, 143); + color.setRgb(13,124,151,127); + switch(colorMode) + { + case 0: + break; + case 1: // pitch + { + Triple* c = &myColors/*Qt::color1*/[event.pitch() % 12]; + color.setRgb(c->r, c->g, c->b, 127); + } + break; + case 2: // velocity + { + int velo = event.velo(); + /* + if (velo < 64) + color.setRgb(velo*4, 0, 0xff); + else + color.setRgb(0xff, 0, (127-velo) * 4); + */ + /* + if(velo <= 11) + color.setRgb(75,145,47); + else if(velo <= 22) + color.setRgb(56,145,79); + else if(velo <= 33) + color.setRgb(64,139,84); + else if(velo <= 44) + color.setRgb(60,137,99); + else if(velo <= 55) + color.setRgb(55,134,113); + else if(velo <= 66) + color.setRgb(51,132,127); + else if(velo <= 77) + color.setRgb(48,130,141); + else if(velo <= 88) + color.setRgb(57,121,144); + else if(velo <= 99) + color.setRgb(72,108,143); + else if(velo <= 110) + color.setRgb(86,96,142); + else if(velo <= 121) + color.setRgb(101,84,141); + else + color.setRgb(116,72,140); + */ + + if(velo <= 11) + color.setRgb(147,186,195,127); + else if(velo <= 22) + color.setRgb(119,169,181,127); + else if(velo <= 33) + color.setRgb(85,157,175,127); + else if(velo <= 44) + color.setRgb(58,152,176,127); + else if(velo <= 55) + color.setRgb(33,137,163,127); + else if(velo <= 66) + color.setRgb(30,136,162,127); + else if(velo <= 77) + color.setRgb(13,124,151,127); + else if(velo <= 88) + color.setRgb(0,110,138,127); + else if(velo <= 99) + color.setRgb(0,99,124,127); + else if(velo <= 110) + color.setRgb(0,77,96,127); + else if(velo <= 121) + color.setRgb(0,69,86,127); + else + color.setRgb(0,58,72,127); + + } + break; + } + p.setBrush(color); + } + } + p.drawRect(r); +} + + +//--------------------------------------------------------- +// drawMoving +// draws moving items +//--------------------------------------------------------- + +void PianoCanvas::drawMoving(QPainter& p, const CItem* item, const QRect& rect) + { + //if(((NEvent*)item)->part() != curPart) + // return; + //if(!item->isMoving()) + // return; + QRect mr = QRect(item->mp().x(), item->mp().y() - item->height()/2, item->width(), item->height()); + mr = mr.intersected(rect); + if(!mr.isValid()) + return; + p.setPen(Qt::black); + p.setBrush(Qt::NoBrush); + p.drawRect(mr); + } + +//--------------------------------------------------------- +// viewMouseDoubleClickEvent +//--------------------------------------------------------- + +void PianoCanvas::viewMouseDoubleClickEvent(QMouseEvent* event) + { + if ((_tool != PointerTool) && (event->button() != Qt::LeftButton)) { + mousePress(event); + return; + } + } + +//--------------------------------------------------------- +// moveCanvasItems +//--------------------------------------------------------- + +void PianoCanvas::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... + NEvent* nevent = (NEvent*) 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, 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 +// called after moving an object +//--------------------------------------------------------- + +// Changed by T356. +//bool PianoCanvas::moveItem(CItem* item, const QPoint& pos, DragType dtype, int* pflags) +bool PianoCanvas::moveItem(CItem* item, const QPoint& pos, DragType dtype) + { + NEvent* nevent = (NEvent*) item; + Event event = nevent->event(); + int npitch = y2pitch(pos.y()); + Event newEvent = event.clone(); + int x = pos.x(); + if (x < 0) + x = 0; + if (event.pitch() != npitch && _playEvents) { + int port = track()->outPort(); + int channel = track()->outChannel(); + // release note: + MidiPlayEvent ev1(0, port, channel, 0x90, event.pitch() + track()->transposition, 0); + audio->msgPlayMidiEvent(&ev1); + MidiPlayEvent ev2(0, port, channel, 0x90, npitch + track()->transposition, event.velo()); + audio->msgPlayMidiEvent(&ev2); + } + + // Changed by T356. + Part* part = nevent->part(); // + //Part * part = Canvas::part(); // part can be dynamically recreated, ask the authority + + newEvent.setPitch(npitch); + int ntick = editor->rasterVal(x) - part->tick(); + if (ntick < 0) + ntick = 0; + newEvent.setTick(ntick); + newEvent.setLenTick(event.lenTick()); + + // Removed 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(); + Part* newPart = Canvas::part()->clone(); + + newPart->setLenTick(newPart->lenTick()+diff); + audio->msgChangePart(Canvas::part(), newPart,false); + + modified = SC_PART_MODIFIED; + part = newPart; // reassign + + // BUG FIX: #1650953 + // Added by T356. + // Fixes posted "select and drag past end of part - crashing" bug + 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("PianoCanvas::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); + //song->endUndo(modified); + + // Removed by T356. + //if(pflags) + // *pflags = modified; + + return true; + } + +//--------------------------------------------------------- +// newItem(p, state) +//--------------------------------------------------------- + +CItem* PianoCanvas::newItem(const QPoint& p, int) + { + //printf("newItem point\n"); + int pitch = y2pitch(p.y()); + int tick = editor->rasterVal1(p.x()); + int len = p.x() - tick; + tick -= curPart->tick(); + if (tick < 0) + tick=0; + Event e = Event(Note); + e.setTick(tick); + e.setPitch(pitch); + e.setVelo(curVelo); + e.setLenTick(len); + return new NEvent(e, curPart, pitch2y(pitch)); + } + +void PianoCanvas::newItem(CItem* item, bool noSnap) + { + //printf("newItem citem\n"); + NEvent* nevent = (NEvent*) item; + Event event = nevent->event(); + int x = item->x(); + if (x<0) + x=0; + int w = item->width(); + + if (!noSnap) { + x = editor->rasterVal1(x); //round down + w = editor->rasterVal(x + w) - x; + if (w == 0) + w = editor->raster(); + } + Part* part = nevent->part(); + event.setTick(x - part->tick()); + event.setLenTick(w); + event.setPitch(y2pitch(item->y())); + + 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); + } + +//--------------------------------------------------------- +// resizeItem +//--------------------------------------------------------- + +void PianoCanvas::resizeItem(CItem* item, bool noSnap) // experimental changes to try dynamically extending parts + { + //printf("resizeItem!\n"); + NEvent* nevent = (NEvent*) item; + Event event = nevent->event(); + Event newEvent = event.clone(); + int len; + + Part* part = nevent->part(); + + if (noSnap) + len = nevent->width(); + else { + //Part* part = nevent->part(); + unsigned tick = event.tick() + part->tick(); + len = editor->rasterVal(tick + nevent->width()) - tick; + if (len <= 0) + len = editor->raster(); + } + song->startUndo(); + int modified=SC_EVENT_MODIFIED; + //printf("event.tick()=%d len=%d part->lenTick()=%d\n",event.endTick(),len,part->lenTick()); + int diff = event.tick()+len-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 + } + + newEvent.setLenTick(len); + // Indicate no undo, and do not do port controller values and clone parts. + //audio->msgChangeEvent(event, newEvent, nevent->part(),false); + audio->msgChangeEvent(event, newEvent, nevent->part(), false, false, false); + song->endUndo(modified); + } + +//--------------------------------------------------------- +// deleteItem +//--------------------------------------------------------- + +bool PianoCanvas::deleteItem(CItem* item) + { + NEvent* nevent = (NEvent*) item; + if (nevent->part() == curPart) { + Event ev = nevent->event(); + // Indicate do undo, and do not do port controller values and clone parts. + //audio->msgDeleteEvent(ev, curPart); + audio->msgDeleteEvent(ev, curPart, true, false, false); + return true; + } + return false; + } + +//--------------------------------------------------------- +// pianoCmd +//--------------------------------------------------------- + +void PianoCanvas::pianoCmd(int cmd) + { + switch(cmd) { + 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_INSERT: + { + if (pos[0] < start() || pos[0] >= end()) + break; + MidiPart* part = (MidiPart*)curPart; + + if (part == 0) + break; + song->startUndo(); + EventList* el = part->events(); + + std::list <Event> elist; + for (iEvent e = el->lower_bound(pos[0] - part->tick()); e != el->end(); ++e) + elist.push_back((Event)e->second); + for (std::list<Event>::iterator i = elist.begin(); i != elist.end(); ++i) { + Event event = *i; + Event newEvent = event.clone(); + newEvent.setTick(event.tick() + editor->raster());// - part->tick()); + // 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); + } + song->endUndo(SC_EVENT_MODIFIED); + Pos p(editor->rasterVal(pos[0] + editor->rasterStep(pos[0])), true); + song->setPos(0, p, true, false, true); + } + return; + case CMD_DELETE: + if (pos[0] < start() || pos[0] >= end()) + break; + { + MidiPart* part = (MidiPart*)curPart; + if (part == 0) + break; + song->startUndo(); + EventList* el = part->events(); + + std::list<Event> elist; + for (iEvent e = el->lower_bound(pos[0]); e != el->end(); ++e) + elist.push_back((Event)e->second); + for (std::list<Event>::iterator i = elist.begin(); i != elist.end(); ++i) { + Event event = *i; + Event newEvent = event.clone(); + newEvent.setTick(event.tick() - editor->raster() - part->tick()); + // 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); + } + song->endUndo(SC_EVENT_MODIFIED); + Pos p(editor->rasterVal(pos[0] - editor->rasterStep(pos[0])), true); + song->setPos(0, p, true, false, true); + } + break; + } + } + +//--------------------------------------------------------- +// pianoPressed +//--------------------------------------------------------- + +void PianoCanvas::pianoPressed(int pitch, int velocity, bool shift) + { + int port = track()->outPort(); + int channel = track()->outChannel(); + pitch += track()->transposition; + + // play note: + //MidiPlayEvent e(0, port, channel, 0x90, pitch, 127); + MidiPlayEvent e(0, port, channel, 0x90, pitch, velocity); + audio->msgPlayMidiEvent(&e); + + if (_steprec && pos[0] >= start_tick && pos[0] < end_tick) { + if (curPart == 0) + return; + int len = editor->raster(); + unsigned tick = pos[0] - curPart->tick(); //CDW + if (shift) + tick -= editor->rasterStep(tick); + Event e(Note); + e.setTick(tick); + e.setPitch(pitch); + e.setVelo(127); + e.setLenTick(len); + // Indicate do undo, and do not do port controller values and clone parts. + //audio->msgAddEvent(e, curPart); + audio->msgAddEvent(e, curPart, true, false, false); + tick += editor->rasterStep(tick) + curPart->tick(); + if (tick != song->cpos()) { + Pos p(tick, true); + song->setPos(0, p, true, false, true); + } + } + } + +//--------------------------------------------------------- +// pianoReleased +//--------------------------------------------------------- + +void PianoCanvas::pianoReleased(int pitch, bool) + { + int port = track()->outPort(); + int channel = track()->outChannel(); + pitch += track()->transposition; + + // release key: + MidiPlayEvent e(0, port, channel, 0x90, pitch, 0); + audio->msgPlayMidiEvent(&e); + } + +//--------------------------------------------------------- +// drawTickRaster +//--------------------------------------------------------- + +void drawTickRaster(QPainter& p, int x, int y, int w, int h, int raster) +{ + + QColor colBeat; + colBeat.setRgb(210, 216, 219); + QColor colBar1; + colBar1.setRgb(82,85,87); + QColor colBar2; + colBar2.setRgb(150,160,167); + + + int bar1, bar2, beat; + unsigned tick; + AL::sigmap.tickValues(x, &bar1, &beat, &tick); + AL::sigmap.tickValues(x+w, &bar2, &beat, &tick); + ++bar2; + int y2 = y + h; + for (int bar = bar1; bar < bar2; ++bar) { + unsigned x = AL::sigmap.bar2tick(bar, 0, 0); + p.setPen(colBar1); + p.drawLine(x, y, x, y2); + int z, n; + AL::sigmap.timesig(x, z, n); + ///int q = p.xForm(QPoint(raster, 0)).x() - p.xForm(QPoint(0, 0)).x(); + int q = p.combinedTransform().map(QPoint(raster, 0)).x() - p.combinedTransform().map(QPoint(0, 0)).x(); + int qq = raster; + if (q < 8) // grid too dense + qq *= 2; + //switch (quant) { + // case 32: + // case 48: + // case 64: + // case 96: + // case 192: // 8tel + // case 128: // 8tel Triolen + // case 288: + p.setPen(colBeat); + if (raster>=4) + { + int xx = x + qq; + int xxx = AL::sigmap.bar2tick(bar, z, 0); + while (xx <= xxx) { + p.drawLine(xx, y, xx, y2); + xx += qq; + } + xx = xxx; + } + // break; + // default: + // break; + // } + p.setPen(colBar2); + for (int beat = 1; beat < z; beat++) + { + int xx = AL::sigmap.bar2tick(bar, beat, 0); + p.drawLine(xx, y, xx, y2); + } + + } +} + +//--------------------------------------------------------- +// draw +//--------------------------------------------------------- + +void PianoCanvas::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) / KH) * KH + KH; + int key = 75 - (yy / KH); + for (; yy < y + h; yy += KH) + { + switch (key % 7) + { + case 0: + case 3: + p.setPen(QColor(213,220,213)); + p.drawLine(x, yy, x + w, yy); + break; + default: + //p.setPen(lightGray); + //p.fillRect(x, yy-3, w, 6, QBrush(QColor(230,230,230))); + p.fillRect(x, yy-3, w, 6, QBrush(QColor(209,213,209))); + //p.drawLine(x, yy, x + w, yy); + break; + } + --key; + } + + //--------------------------------------------------- + // vertical lines + //--------------------------------------------------- + + drawTickRaster(p, x, y, w, h, editor->raster()); +} + +//--------------------------------------------------------- +// cmd +// pulldown menu commands +//--------------------------------------------------------- + +void PianoCanvas::cmd(int cmd, int quantStrength, + int quantLimit, bool quantLen, int range) + { + cmdRange = range; + printf("PianoCanvas cmd called with command: %d\n\n", cmd); + switch (cmd) { + case CMD_CUT: + copy(); + song->startUndo(); + for (iCItem i = items.begin(); i != items.end(); ++i) { + if (!(i->second->isSelected())) + continue; + NEvent* e = (NEvent*)(i->second); + Event ev = e->event(); + // Indicate no undo, and do not do port controller values and clone parts. + //audio->msgDeleteEvent(ev, e->part(), false); + audio->msgDeleteEvent(ev, e->part(), false, false, false); + } + song->endUndo(SC_EVENT_REMOVED); + break; + case CMD_COPY: + copy(); + break; + case CMD_PASTE: + paste(); + 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_OVER_QUANTIZE: // over quantize + quantize(100, 1, quantLen); + break; + case CMD_ON_QUANTIZE: // note on quantize + quantize(50, 1, false); + break; + case CMD_ONOFF_QUANTIZE: // note on/off quantize + quantize(50, 1, true); + break; + case CMD_ITERATIVE_QUANTIZE: // Iterative Quantize + quantize(quantStrength, quantLimit, quantLen); + 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) { + NEvent* nevent = (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); + } + break; + case CMD_SELECT_OLOOP: // select outside loop + for (iCItem k = items.begin(); k != items.end(); ++k) { + NEvent* nevent = (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); + } + 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_MODIFY_GATE_TIME: + { + GateTime w(this); + w.setRange(range); + 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) { + NEvent* nevent =(NEvent*)(k->second); + Event event = nevent->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)) { + unsigned int len = event.lenTick(); //prevent compiler warning: comparison singed/unsigned + + len = rate ? (len * 100) / rate : 1; + len += offset; + if (len < 1) + len = 1; + + if (event.lenTick() != len) { + Event newEvent = event.clone(); + newEvent.setLenTick(len); + // Indicate no undo, and do not do port controller values and clone parts. + //audio->msgChangeEvent(event, newEvent, nevent->part(), false); + audio->msgChangeEvent(event, newEvent, nevent->part(), false, false, false); + } + } + } + song->endUndo(SC_EVENT_MODIFIED); + } + break; + + case CMD_MODIFY_VELOCITY: + { + Velocity w; + w.setRange(range); + 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) { + NEvent* nevent = (NEvent*)(k->second); + Event event = nevent->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, nevent->part(), false); + audio->msgChangeEvent(event, newEvent, nevent->part(), false, false, false); + } + } + } + song->endUndo(SC_EVENT_MODIFIED); + } + 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()) { + NEvent* nevent = (NEvent*)(k->second); + Event event = nevent->event(); + Event newEvent = event.clone(); + newEvent.setLenTick(editor->raster()); + // Indicate no undo, and do not do port controller values and clone parts. + //audio->msgChangeEvent(event, newEvent, nevent->part() , false); + audio->msgChangeEvent(event, newEvent, nevent->part(), false, false, false); + } + } + song->endUndo(SC_EVENT_MODIFIED); + break; + + case CMD_DELETE_OVERLAPS: + if (!selectionSize()) + break; + + song->startUndo(); + for (iCItem k = items.begin(); k != items.end(); k++) { + if (k->second->isSelected() == false) + continue; + + NEvent* e1 = (NEvent*) (k->second); // first note + NEvent* e2 = NULL; // ptr to next selected note (which will be checked for overlap) + Event ce1 = e1->event(); + Event ce2; + + if (ce1.type() != Note) + continue; + + // Find next selected item on the same pitch + iCItem l = k; l++; + for (; l != items.end(); l++) { + if (l->second->isSelected() == false) + continue; + + e2 = (NEvent*) l->second; + ce2 = e2->event(); + + // Same pitch? + if (ce1.dataA() == ce2.dataA()) + break; + + // If the note has the same len and place we treat it as a duplicate note and not a following note + // The best thing to do would probably be to delete the duplicate note, we just want to avoid + // matching against the same note + if ( ce1.tick() + e1->part()->tick() == ce2.tick() + e2->part()->tick() + && ce1.lenTick() + e1->part()->tick() == ce2.lenTick() + e2->part()->tick()) + { + e2 = NULL; // this wasn't what we were looking for + continue; + } + + } + + if (e2 == NULL) // None found + break; + + Part* part1 = e1->part(); + Part* part2 = e2->part(); + if (ce2.type() != Note) + continue; + + + unsigned event1pos = ce1.tick() + part1->tick(); + unsigned event1end = event1pos + ce1.lenTick(); + unsigned event2pos = ce2.tick() + part2->tick(); + + //printf("event1pos %u event1end %u event2pos %u\n", event1pos, event1end, event2pos); + if (event1end > event2pos) { + Event newEvent = ce1.clone(); + unsigned newlen = ce1.lenTick() - (event1end - event2pos); + //printf("newlen: %u\n", newlen); + newEvent.setLenTick(newlen); + // Indicate no undo, and do not do port controller values and clone parts. + //audio->msgChangeEvent(ce1, newEvent, e1->part(), false); + audio->msgChangeEvent(ce1, newEvent, e1->part(), false, false, false); + } + } + song->endUndo(SC_EVENT_MODIFIED); + break; + + + case CMD_CRESCENDO: + case CMD_TRANSPOSE: + case CMD_THIN_OUT: + case CMD_ERASE_EVENT: + case CMD_NOTE_SHIFT: + case CMD_MOVE_CLOCK: + case CMD_COPY_MEASURE: + case CMD_ERASE_MEASURE: + case CMD_DELETE_MEASURE: + case CMD_CREATE_MEASURE: + break; + default: +// printf("unknown ecanvas cmd %d\n", cmd); + break; + } + updateSelection(); + redraw(); + } + +//--------------------------------------------------------- +// quantize +//--------------------------------------------------------- + +void PianoCanvas::quantize(int strength, int limit, bool quantLen) + { + song->startUndo(); + for (iCItem k = items.begin(); k != items.end(); ++k) { + NEvent* nevent = (NEvent*)(k->second); + Event event = nevent->event(); + Part* part = nevent->part(); + if (event.type() != Note) + continue; + + if ((cmdRange & CMD_RANGE_SELECTED) && !k->second->isSelected()) + continue; + + unsigned tick = event.tick() + part->tick(); + + if ((cmdRange & CMD_RANGE_LOOP) + && ((tick < song->lpos() || tick >= song->rpos()))) + continue; + + unsigned int len = event.lenTick(); //prevent compiler warning: comparison singed/unsigned + int tick2 = tick + len; + + // quant start position + int diff = AL::sigmap.raster(tick, editor->quant()) - tick; + if (abs(diff) > limit) + tick += ((diff * strength) / 100); + + // quant len + diff = AL::sigmap.raster(tick2, editor->quant()) - tick2; + if (quantLen && (abs(diff) > limit)) + len += ((diff * strength) / 100); + + // something changed? + if (((event.tick() + part->tick()) != tick) || (event.lenTick() != len)) { + Event newEvent = event.clone(); + newEvent.setTick(tick - part->tick()); + newEvent.setLenTick(len); + // 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); + } + } + song->endUndo(SC_EVENT_MODIFIED); + } + +//--------------------------------------------------------- +// midiNote +//--------------------------------------------------------- + +void PianoCanvas::midiNote(int pitch, int velo) + { + if (_midiin && _steprec && curPart + && !audio->isPlaying() && velo && pos[0] >= start_tick + && pos[0] < end_tick + && !(globalKeyState & Qt::AltModifier)) { + unsigned int len = editor->quant();//prevent compiler warning: comparison singed/unsigned + unsigned tick = pos[0]; //CDW + unsigned starttick = tick; + if (globalKeyState & Qt::ShiftModifier) + tick -= editor->rasterStep(tick); + + // + // extend len of last note? + // + EventList* events = curPart->events(); + if (globalKeyState & Qt::ControlModifier) { + for (iEvent i = events->begin(); i != events->end(); ++i) { + Event ev = i->second; + if (!ev.isNote()) + continue; + if (ev.pitch() == pitch && ((ev.tick() + ev.lenTick()) == /*(int)*/starttick)) { + Event e = ev.clone(); + e.setLenTick(ev.lenTick() + editor->rasterStep(starttick)); + // Indicate do undo, and do not do port controller values and clone parts. + //audio->msgChangeEvent(ev, e, curPart); + audio->msgChangeEvent(ev, e, curPart, true, false, false); + tick += editor->rasterStep(tick); + if (tick != song->cpos()) { + Pos p(tick, true); + song->setPos(0, p, true, false, true); + } + return; + } + } + } + + // + // if we already entered the note, delete it + // + EventRange range = events->equal_range(tick); + for (iEvent i = range.first; i != range.second; ++i) { + Event ev = i->second; + if (ev.isNote() && ev.pitch() == pitch) { + // Indicate do undo, and do not do port controller values and clone parts. + //audio->msgDeleteEvent(ev, curPart); + audio->msgDeleteEvent(ev, curPart, true, false, false); + if (globalKeyState & Qt::ShiftModifier) + tick += editor->rasterStep(tick); + return; + } + } + Event e(Note); + e.setTick(tick - curPart->tick()); + e.setPitch(pitch); + e.setVelo(velo); + e.setLenTick(len); + // Indicate do undo, and do not do port controller values and clone parts. + //audio->msgAddEvent(e, curPart); + audio->msgAddEvent(e, curPart, true, false, false); + tick += editor->rasterStep(tick); + if (tick != song->cpos()) { + Pos p(tick, true); + song->setPos(0, p, true, false, true); + } + } + } + +/* +//--------------------------------------------------------- +// getTextDrag +//--------------------------------------------------------- + +Q3TextDrag* PianoCanvas::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; + NEvent* ne = (NEvent*)(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, "PianoCanvas::copy() fopen failed: %s\n", + strerror(errno)); + return 0; + } + Xml xml(tmp); + + int level = 0; + xml.tag(level++, "eventlist"); + for (ciEvent e = el.begin(); e != el.end(); ++e) + e->second.write(level, xml, -startTick); + xml.etag(--level, "eventlist"); + + //--------------------------------------------------- + // read tmp file into QTextDrag Object + //--------------------------------------------------- + + fflush(tmp); + struct stat f_stat; + if (fstat(fileno(tmp), &f_stat) == -1) { + fprintf(stderr, "PianoCanvas::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 PianoCanvas::copy() + { + //QDrag* drag = getTextDrag(); + QMimeData* drag = getTextDrag(); + + if (drag) + QApplication::clipboard()->setMimeData(drag, QClipboard::Clipboard); + } + +/* +//--------------------------------------------------------- +// pasteAt +//--------------------------------------------------------- + +void PianoCanvas::pasteAt(const QString& pt, int pos) + { + QByteArray ba = pt.toLatin1(); + const char* p = ba.constData(); + Xml xml(p); + 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 == "eventlist") { + song->startUndo(); + EventList* el = new EventList(); + el->read(xml, "eventlist", true); + int modified = SC_EVENT_INSERTED; + for (iEvent i = el->begin(); i != el->end(); ++i) { + Event e = i->second; + int tick = e.tick() + pos - curPart->tick(); + if (tick<0) { + printf("ERROR: trying to add event before current part!\n"); + song->endUndo(SC_EVENT_INSERTED); + delete el; + return; + } + + 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); + } + song->endUndo(modified); + delete el; + return; + } + else + xml.unknown("pasteAt"); + break; + case Xml::Attribut: + case Xml::TagEnd: + default: + break; + } + } + } +*/ + +//--------------------------------------------------------- +// paste +// paste events +//--------------------------------------------------------- + +void PianoCanvas::paste() + { +/* + //Q3CString subtype("eventlist"); ddskrjo + QString subtype("eventlist"); + QMimeSource* ms = QApplication::clipboard()->data(QClipboard::Clipboard); + 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 PianoCanvas::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 PianoCanvas::dragEnterEvent(QDragEnterEvent* event) + { + ///event->accept(Q3TextDrag::canDecode(event)); + event->acceptProposedAction(); // TODO CHECK Tim. + } + +//--------------------------------------------------------- +// dragMoveEvent +//--------------------------------------------------------- + +void PianoCanvas::dragMoveEvent(QDragMoveEvent*) + { + //printf("drag move %x\n", this); + //event->acceptProposedAction(); + } + +//--------------------------------------------------------- +// dragLeaveEvent +//--------------------------------------------------------- + +void PianoCanvas::dragLeaveEvent(QDragLeaveEvent*) + { + //printf("drag leave\n"); + //event->acceptProposedAction(); + } + +/* +//--------------------------------------------------------- +// dropEvent +//--------------------------------------------------------- + +void PianoCanvas::viewDropEvent(QDropEvent* event) + { + QString text; + if (event->source() == this) { + printf("local DROP\n"); // REMOVE Tim + //event->acceptProposedAction(); + //event->ignore(); // TODO CHECK Tim. + return; + } + ///if (Q3TextDrag::decode(event, text)) { + //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")); + + 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. + } + } +*/ + +//--------------------------------------------------------- +// itemPressed +//--------------------------------------------------------- + +void PianoCanvas::itemPressed(const CItem* item) + { + if (!_playEvents) + return; + + int port = track()->outPort(); + int channel = track()->outChannel(); + NEvent* nevent = (NEvent*) item; + Event event = nevent->event(); + playedPitch = event.pitch() + track()->transposition; + int velo = event.velo(); + + // play note: + MidiPlayEvent e(0, port, channel, 0x90, playedPitch, velo); + audio->msgPlayMidiEvent(&e); + } + +//--------------------------------------------------------- +// itemReleased +//--------------------------------------------------------- + +void PianoCanvas::itemReleased(const CItem*, const QPoint&) + { + if (!_playEvents) + return; + int port = track()->outPort(); + int channel = track()->outChannel(); + + // release note: + MidiPlayEvent ev(0, port, channel, 0x90, playedPitch, 0); + audio->msgPlayMidiEvent(&ev); + playedPitch = -1; + } + +//--------------------------------------------------------- +// itemMoved +//--------------------------------------------------------- + +void PianoCanvas::itemMoved(const CItem* item, const QPoint& pos) + { + int npitch = y2pitch(pos.y()); + if ((playedPitch != -1) && (playedPitch != npitch)) { + int port = track()->outPort(); + int channel = track()->outChannel(); + NEvent* nevent = (NEvent*) item; + Event event = nevent->event(); + + // release note: + MidiPlayEvent ev1(0, port, channel, 0x90, playedPitch, 0); + audio->msgPlayMidiEvent(&ev1); + // play note: + MidiPlayEvent e2(0, port, channel, 0x90, npitch + track()->transposition, event.velo()); + audio->msgPlayMidiEvent(&e2); + playedPitch = npitch + track()->transposition; + } + } + +//--------------------------------------------------------- +// curPartChanged +//--------------------------------------------------------- + +void PianoCanvas::curPartChanged() + { + editor->setWindowTitle(getCaption()); + } + +//--------------------------------------------------------- +// modifySelected +//--------------------------------------------------------- + +void PianoCanvas::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; + NEvent* e = (NEvent*)(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); + } + break; + case NoteInfo::VAL_VELON: + { + int velo = event.velo() + delta; + if (velo > 127) + velo = 127; + else if (velo < 0) + velo = 0; + newEvent.setVelo(velo); + } + break; + case NoteInfo::VAL_VELOFF: + { + int velo = event.veloOff() + delta; + if (velo > 127) + velo = 127; + else if (velo < 0) + velo = 0; + newEvent.setVeloOff(velo); + } + break; + case NoteInfo::VAL_PITCH: + { + int pitch = event.pitch() + delta; + 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); + } + +//--------------------------------------------------------- +// resizeEvent +//--------------------------------------------------------- + +void PianoCanvas::resizeEvent(QResizeEvent* ev) + { + if (ev->size().width() != ev->oldSize().width()) + emit newWidth(ev->size().width()); + EventCanvas::resizeEvent(ev); + } + diff --git a/attic/muse2-oom/muse2/muse/midiedit/prcanvas.h b/attic/muse2-oom/muse2/muse/midiedit/prcanvas.h new file mode 100644 index 00000000..81acf426 --- /dev/null +++ b/attic/muse2-oom/muse2/muse/midiedit/prcanvas.h @@ -0,0 +1,110 @@ +//========================================================= +// MusE +// Linux Music Editor +// $Id: prcanvas.h,v 1.5.2.6 2009/11/16 11:29:33 lunar_shuttle Exp $ +// (C) Copyright 1999 Werner Schweer (ws@seh.de) +//========================================================= + +#ifndef __PRCANVAS_H__ +#define __PRCANVAS_H__ + +#include "ecanvas.h" +#include "pianoroll.h" +#include <QDragEnterEvent> +#include <QDropEvent> +#include <QMouseEvent> +#include <QDragMoveEvent> +#include <QDragLeaveEvent> + +#define KH 13 + +//--------------------------------------------------------- +// NEvent +// ''visual'' Note Event +//--------------------------------------------------------- + +class NEvent : public CItem { + public: + NEvent(Event& e, Part* p, int y); + }; + +class ScrollScale; +class PianoRoll; +class QRect; + +//--------------------------------------------------------- +// PianoCanvas +//--------------------------------------------------------- + +class PianoCanvas : public EventCanvas { + int cmdRange; + int colorMode; + int playedPitch; + + Q_OBJECT + virtual void viewMouseDoubleClickEvent(QMouseEvent*); + virtual void drawItem(QPainter&, const CItem*, const QRect&); + virtual void drawMoving(QPainter&, const CItem*, const QRect&); + virtual void moveCanvasItems(CItemList&, int, int, DragType, int*); + // Changed by T356. + //virtual bool moveItem(CItem*, const QPoint&, DragType, int*); + virtual bool moveItem(CItem*, const QPoint&, DragType); + virtual CItem* newItem(const QPoint&, int); + virtual void resizeItem(CItem*, bool noSnap); + virtual void newItem(CItem*, bool noSnap); + virtual bool deleteItem(CItem*); + virtual void startDrag(CItem* item, bool copymode); + virtual void dragEnterEvent(QDragEnterEvent* event); + virtual void dragMoveEvent(QDragMoveEvent*); + virtual void dragLeaveEvent(QDragLeaveEvent*); + virtual void addItem(Part*, Event&); + + int y2pitch(int) const; + int pitch2y(int) const; + virtual void drawCanvas(QPainter&, const QRect&); + void quantize(int, int, bool); + void copy(); + void paste(); + virtual void itemPressed(const CItem*); + virtual void itemReleased(const CItem*, const QPoint&); + virtual void itemMoved(const CItem*, const QPoint&); + virtual void curPartChanged(); + virtual void resizeEvent(QResizeEvent*); + + private slots: + void midiNote(int pitch, int velo); + + signals: + void quantChanged(int); + void rasterChanged(int); + void newWidth(int); + + public slots: + void pianoCmd(int); + void pianoPressed(int pitch, int velocity, bool shift); + void pianoReleased(int pitch, bool); + + public: + enum { + CMD_CUT, CMD_COPY, CMD_PASTE, CMD_DEL, + CMD_OVER_QUANTIZE, CMD_ON_QUANTIZE, CMD_ONOFF_QUANTIZE, + CMD_ITERATIVE_QUANTIZE, + CMD_SELECT_ALL, CMD_SELECT_NONE, CMD_SELECT_INVERT, + CMD_SELECT_ILOOP, CMD_SELECT_OLOOP, CMD_SELECT_PREV_PART, CMD_SELECT_NEXT_PART, + CMD_MODIFY_GATE_TIME, CMD_MODIFY_VELOCITY, + CMD_CRESCENDO, CMD_TRANSPOSE, CMD_THIN_OUT, CMD_ERASE_EVENT, + CMD_NOTE_SHIFT, CMD_MOVE_CLOCK, CMD_COPY_MEASURE, + CMD_ERASE_MEASURE, CMD_DELETE_MEASURE, CMD_CREATE_MEASURE, + CMD_FIXED_LEN, CMD_DELETE_OVERLAPS + }; + + PianoCanvas(MidiEditor*, QWidget*, int, int); + void cmd(int, int, int, bool, int); + void setColorMode(int mode) { + colorMode = mode; + redraw(); + } + virtual void modifySelected(NoteInfo::ValType type, int delta); + }; +#endif + diff --git a/attic/muse2-oom/muse2/muse/midiedit/quantconfig.cpp b/attic/muse2-oom/muse2/muse/midiedit/quantconfig.cpp new file mode 100644 index 00000000..2f413e6a --- /dev/null +++ b/attic/muse2-oom/muse2/muse/midiedit/quantconfig.cpp @@ -0,0 +1,79 @@ +//========================================================= +// MusE +// Linux Music Editor +// $Id: quantconfig.cpp,v 1.2 2004/04/24 14:58:52 wschweer Exp $ +// +// (C) Copyright 1999/2003 Werner Schweer (ws@seh.de) +//========================================================= + +#include <QCheckBox> +#include <QGroupBox> +#include <QLabel> +#include <QSpinBox> +#include <QVBoxLayout> + +#include "quantconfig.h" + +const char* wtStrengthTxt = QT_TRANSLATE_NOOP("@default", "sets amount of quantization:\n" + "0 - no quantization\n" + "100 - full quantization"); +const char* wtQLimitTxt = QT_TRANSLATE_NOOP("@default", "don't quantize notes above this tick limit"); +const char* wtQLenTxt = QT_TRANSLATE_NOOP("@default", "quantize also note len as default"); + +//--------------------------------------------------------- +// QuantConfig +//--------------------------------------------------------- + +QuantConfig::QuantConfig(int s, int l, bool lenFlag) + : QDialog() + { + setWindowTitle(tr("MusE: Config Quantize")); + QVBoxLayout *mainlayout = new QVBoxLayout; + + QGridLayout* layout = new QGridLayout; + QGroupBox* gb = new QGroupBox(tr("Config Quantize")); + + QLabel* l1 = new QLabel(tr("Strength")); + layout->addWidget(l1, 0, 0); + QSpinBox* sb1 = new QSpinBox; + sb1->setMinimum(0); + sb1->setMaximum(100); + sb1->setSingleStep(1); + sb1->setSuffix(QString("%")); + sb1->setValue(s); + layout->addWidget(sb1, 0, 1); + + QLabel* l2 = new QLabel(tr("Donīt Quantize")); + layout->addWidget(l2, 1, 0); + QSpinBox* sb2 = new QSpinBox; + sb2->setMinimum(0); + sb2->setMaximum(500); + sb2->setSingleStep(1); + sb2->setValue(l); + layout->addWidget(sb2, 1, 1); + + QLabel* l3 = new QLabel(tr("Quant Len")); + layout->addWidget(l3, 2, 0); + QCheckBox* but = new QCheckBox; + but->setChecked(lenFlag); + layout->addWidget(but, 2, 1); + + connect(sb1, SIGNAL(valueChanged(int)), SIGNAL(setQuantStrength(int))); + connect(sb2, SIGNAL(valueChanged(int)), SIGNAL(setQuantLimit(int))); + connect(but, SIGNAL(toggled(bool)), SIGNAL(setQuantLen(bool))); + + gb->setLayout(layout); + mainlayout->addWidget(gb); + setLayout(mainlayout); + + l1->setWhatsThis(tr(wtStrengthTxt)); + l1->setToolTip(tr(wtStrengthTxt)); + sb1->setWhatsThis(tr(wtStrengthTxt)); + l2->setWhatsThis(tr(wtQLimitTxt)); + l2->setToolTip(tr(wtQLimitTxt)); + sb2->setWhatsThis(tr(wtQLimitTxt)); + l3->setWhatsThis(tr(wtQLenTxt)); + l3->setToolTip(tr(wtQLenTxt)); + but->setWhatsThis(tr(wtQLenTxt)); + } + diff --git a/attic/muse2-oom/muse2/muse/midiedit/quantconfig.h b/attic/muse2-oom/muse2/muse/midiedit/quantconfig.h new file mode 100644 index 00000000..4466cdf0 --- /dev/null +++ b/attic/muse2-oom/muse2/muse/midiedit/quantconfig.h @@ -0,0 +1,32 @@ +//========================================================= +// MusE +// Linux Music Editor +// $Id: quantconfig.h,v 1.1.1.1 2003/10/27 18:52:23 wschweer Exp $ +// +// (C) Copyright 1999/2000 Werner Schweer (ws@seh.de) +//========================================================= + +#ifndef __QCONFIG_H__ +#define __QCONFIG_H__ + +#include <QDialog> + +//--------------------------------------------------------- +// QuantConfig +//--------------------------------------------------------- + +class QuantConfig : public QDialog { + Q_OBJECT + + signals: + void setQuantStrength(int); + void setQuantLimit(int); + void setQuantLen(bool); + + public: + QuantConfig(int, int, bool); + }; + + +#endif + |