diff options
34 files changed, 1175 insertions, 606 deletions
diff --git a/muse2/muse/CMakeLists.txt b/muse2/muse/CMakeLists.txt index d89bb007..d9ca7e3c 100644 --- a/muse2/muse/CMakeLists.txt +++ b/muse2/muse/CMakeLists.txt @@ -89,6 +89,7 @@ file (GLOB core_source_files event.cpp eventlist.cpp exportmidi.cpp + functions.cpp gconfig.cpp globals.cpp help.cpp diff --git a/muse2/muse/app.cpp b/muse2/muse/app.cpp index 59993911..62651cc9 100644 --- a/muse2/muse/app.cpp +++ b/muse2/muse/app.cpp @@ -31,7 +31,6 @@ #include "didyouknow.h" #include "drumedit.h" #include "filedialog.h" -#include "gatetime.h" #include "gconfig.h" #include "gui.h" #include "icons.h" @@ -4190,8 +4189,7 @@ void MusE::transpose() void MusE::modifyGateTime() { - GateTime* w = new GateTime(this); - w->show(); + printf("not implemented\n"); } //--------------------------------------------------------- diff --git a/muse2/muse/arranger/pcanvas.cpp b/muse2/muse/arranger/pcanvas.cpp index 35de93ee..599e90a0 100644 --- a/muse2/muse/arranger/pcanvas.cpp +++ b/muse2/muse/arranger/pcanvas.cpp @@ -231,9 +231,9 @@ void PartCanvas::viewMouseDoubleClickEvent(QMouseEvent* event) } QPoint cpos = event->pos(); curItem = items.find(cpos); - bool shift = event->modifiers() & Qt::ShiftModifier; + bool ctrl = event->modifiers() & Qt::ControlModifier; if (curItem) { - if (event->button() == Qt::LeftButton && shift) { + if (event->button() == Qt::LeftButton && ctrl) { editPart = (NPart*)curItem; QRect r = map(curItem->bbox()); if (lineEditor == 0) { @@ -1002,7 +1002,7 @@ void PartCanvas::itemPopup(CItem* item, int n, const QPoint& pt) void PartCanvas::mousePress(QMouseEvent* event) { - if (event->modifiers() & Qt::ShiftModifier) { + if (event->modifiers() & Qt::ControlModifier) { return; } QPoint pt = event->pos(); @@ -1059,7 +1059,7 @@ void PartCanvas::mouseMove(QMouseEvent* event) x = 0; if (_tool == AutomationTool) - processAutomationMovements(event->pos(), event->modifiers() & Qt::ControlModifier); + processAutomationMovements(event->pos(), event->modifiers() & Qt::ShiftModifier); emit timeChanged(AL::sigmap.raster(x, *_raster)); } @@ -1665,7 +1665,7 @@ void PartCanvas::drawMoving(QPainter& p, const CItem* item, const QRect&) // pr - part rectangle //--------------------------------------------------------- -void PartCanvas::drawMidiPart(QPainter& p, const QRect& bb, EventList* events, MidiTrack *mt, MidiPart *pt, const QRect& r, int pTick, int from, int to) +void PartCanvas::drawMidiPart(QPainter& p, const QRect&, EventList* events, MidiTrack *mt, MidiPart *pt, const QRect& r, int pTick, int from, int to) { //printf("x=%d y=%d h=%d w=%d\n",r.x(),r.y(),r.height(),r.width()); diff --git a/muse2/muse/arranger/tlist.cpp b/muse2/muse/arranger/tlist.cpp index b907b555..2a397a4e 100644 --- a/muse2/muse/arranger/tlist.cpp +++ b/muse2/muse/arranger/tlist.cpp @@ -348,7 +348,7 @@ void TList::paint(const QRect& r) if (cl->isVisible()) countVisible++; } - int count = ((AudioTrack*)track)->controller()->size(); + //int count = ((AudioTrack*)track)->controller()->size(); //commented out by flo: gives a "unused variable" warning s.sprintf(" %d(%d) visible",countVisible, countAll); } @@ -914,7 +914,7 @@ void TList::mousePressEvent(QMouseEvent* ev) int x = ev->x(); int y = ev->y(); int button = ev->button(); - bool shift = ((QInputEvent*)ev)->modifiers() & Qt::ShiftModifier; + bool ctrl = ((QInputEvent*)ev)->modifiers() & Qt::ControlModifier; Track* t = y2Track(y + ypos); @@ -1152,7 +1152,7 @@ void TList::mousePressEvent(QMouseEvent* ev) break; case COL_MUTE: // p3.3.29 - if ((button == Qt::RightButton) || (((QInputEvent*)ev)->modifiers() & Qt::ControlModifier)) + if ((button == Qt::RightButton) || (((QInputEvent*)ev)->modifiers() & Qt::ShiftModifier)) t->setOff(!t->off()); else { @@ -1170,7 +1170,7 @@ void TList::mousePressEvent(QMouseEvent* ev) case COL_NAME: if (button == Qt::LeftButton) { - if (!shift) { + if (!ctrl) { song->deselectTracks(); t->setSelected(true); @@ -1463,7 +1463,7 @@ void TList::wheelEvent(QWheelEvent* ev) break; case COL_MUTE: // p3.3.29 - if (((QInputEvent*)ev)->modifiers() & Qt::ControlModifier) + if (((QInputEvent*)ev)->modifiers() & Qt::ShiftModifier) t->setOff(!t->off()); else { diff --git a/muse2/muse/ctrl/ctrlcanvas.cpp b/muse2/muse/ctrl/ctrlcanvas.cpp index 56f19384..70d1ad63 100644 --- a/muse2/muse/ctrl/ctrlcanvas.cpp +++ b/muse2/muse/ctrl/ctrlcanvas.cpp @@ -743,7 +743,7 @@ void CtrlCanvas::viewMousePressEvent(QMouseEvent* event) start = event->pos(); Tool activeTool = tool; - bool shift = event->modifiers() & Qt::ShiftModifier; + bool ctrlKey = event->modifiers() & Qt::ControlModifier; int xpos = start.x(); int ypos = start.y(); @@ -755,7 +755,7 @@ void CtrlCanvas::viewMousePressEvent(QMouseEvent* event) { bool do_redraw = false; - if (!shift) + if (!ctrlKey) { deselectAll(); do_redraw = true; @@ -780,7 +780,7 @@ void CtrlCanvas::viewMousePressEvent(QMouseEvent* event) break; if (ev->intersects(_controller, r, tickstep, h)) { - if (shift && ev->selected()) + if (ctrlKey && ev->selected()) deselectItem(ev); else selectItem(ev); @@ -797,7 +797,7 @@ void CtrlCanvas::viewMousePressEvent(QMouseEvent* event) break; case PencilTool: - if (shift) { + if (ctrlKey) { if (type != MidiController::Velo) { drag = DRAG_NEW; song->startUndo(); @@ -824,7 +824,7 @@ void CtrlCanvas::viewMousePressEvent(QMouseEvent* event) if (drawLineMode) { line2x = xpos; line2y = ypos; - if (shift) + if (ctrlKey) newValRamp(line1x, line1y, line2x, line2y); else changeValRamp(line1x, line1y, line2x, line2y); @@ -899,7 +899,7 @@ void CtrlCanvas::viewMouseMoveEvent(QMouseEvent* event) void CtrlCanvas::viewMouseReleaseEvent(QMouseEvent* event) { - bool shift = event->modifiers() & Qt::ShiftModifier; + bool ctrlKey = event->modifiers() & Qt::ControlModifier; switch (drag) { ///case DRAG_RESIZE: @@ -922,7 +922,7 @@ void CtrlCanvas::viewMouseReleaseEvent(QMouseEvent* event) case DRAG_LASSO: { - ///if (!shift) + ///if (!ctrlKey) /// deselectAll(); lasso = lasso.normalized(); int h = height(); @@ -932,9 +932,9 @@ void CtrlCanvas::viewMouseReleaseEvent(QMouseEvent* event) if((*i)->part() != curPart) continue; if ((*i)->intersects(_controller, lasso, tickstep, h)) { - if (shift && (*i)->selected()) + if (ctrlKey && (*i)->selected()) { - //if (!shift) // Shift p4.0.18 + //if (!ctrlKey) // ctrlKey p4.0.18 { ///deselectItem(*i); //do_redraw = true; diff --git a/muse2/muse/functions.cpp b/muse2/muse/functions.cpp new file mode 100644 index 00000000..6a3af374 --- /dev/null +++ b/muse2/muse/functions.cpp @@ -0,0 +1,262 @@ +//========================================================= +// MusE +// Linux Music Editor +// $Id: functions.cpp,v 1.20.2.19 2011/05/05 20:10 flo93 Exp $ +// (C) Copyright 2011 Florian Jung (flo93@sourceforge.net) +//========================================================= + +#include "functions.h" +#include "song.h" + +#include "event.h" +#include "audio.h" +#include "gconfig.h" + +#include <iostream> + +using namespace std; + +GateTime* gatetime_dialog=NULL; +Velocity* velocity_dialog=NULL; +Quantize* quantize_dialog=NULL; + +void init_function_dialogs(QWidget* parent) +{ + gatetime_dialog = new GateTime(parent); + velocity_dialog = new Velocity(parent); + quantize_dialog = new Quantize(parent); +} + +set<Part*> partlist_to_set(PartList* pl) +{ + set<Part*> result; + + for (PartList::iterator it=pl->begin(); it!=pl->end(); it++) + result.insert(it->second); + + return result; +} + +bool is_relevant(const Event& event, const Part* part, int range) +{ + unsigned tick; + + if (event.type()!=Note) return false; + + switch (range) + { + case 0: return true; + case 1: return event.selected(); + case 2: tick=event.tick()+part->tick(); return (tick >= song->lpos()) && (tick < song->rpos()); + case 3: return is_relevant(event,part,1) && is_relevant(event,part,2); + default: cout << "ERROR: ILLEGAL FUNCTION CALL in is_relevant: range is illegal: "<<range<<endl; + return false; + } +} + + +map<Event*, Part*> get_events(const set<Part*>& parts, int range) +{ + map<Event*, Part*> events; + + for (set<Part*>::iterator part=parts.begin(); part!=parts.end(); part++) + for (iEvent event=(*part)->events()->begin(); event!=(*part)->events()->end(); event++) + if (is_relevant(event->second, *part, range)) + events.insert(pair<Event*, Part*>(&event->second, *part)); + + return events; +} + + +bool modify_notelen(const set<Part*>& parts) +{ + if (!gatetime_dialog->exec()) + return false; + + modify_notelen(parts,gatetime_dialog->range,gatetime_dialog->rateVal,gatetime_dialog->offsetVal); + + return true; +} + +bool modify_velocity(const set<Part*>& parts) +{ + if (!velocity_dialog->exec()) + return false; + + modify_velocity(parts,velocity_dialog->range,velocity_dialog->rateVal,velocity_dialog->offsetVal); + + return true; +} + +bool quantize_notes(const set<Part*>& parts) +{ + if (!quantize_dialog->exec()) + return false; + + quantize_notes(parts, quantize_dialog->range, (config.division*4)/(1<<quantize_dialog->raster_power2), + quantize_dialog->strength, quantize_dialog->swing, quantize_dialog->threshold); + + return true; +} + + + +void modify_velocity(const set<Part*>& parts, int range, int rate, int offset) +{ + map<Event*, Part*> events = get_events(parts, range); + + if (!events.empty()) + { + song->startUndo(); + + for (map<Event*, Part*>::iterator it=events.begin(); it!=events.end(); it++) + { + Event& event=*(it->first); + Part* part=it->second; + + int velo = event.velo(); + + velo = (velo * rate) / 100; + velo += offset; + + if (velo <= 0) + velo = 1; + else 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, part, false, false, false); + } + } + + song->endUndo(SC_EVENT_MODIFIED); + } +} + +void modify_notelen(const set<Part*>& parts, int range, int rate, int offset) +{ + map<Event*, Part*> events = get_events(parts, range); + + if (!events.empty()) + { + song->startUndo(); + + for (map<Event*, Part*>::iterator it=events.begin(); it!=events.end(); it++) + { + Event& event=*(it->first); + Part* part=it->second; + + unsigned int len = event.lenTick(); //prevent compiler warning: comparison singed/unsigned + + len = (len * rate) / 100; + len += offset; + + if (len <= 0) + 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, part, false, false, false); + } + } + + song->endUndo(SC_EVENT_MODIFIED); + } +} + +unsigned quantize_tick(unsigned tick, unsigned raster, int swing) +{ + //find out the nearest tick and the distance to it: + //this is so complicated because this function supports + //swing: if swing is 50, the resulting rhythm is not + //"daa daa daa daa" but "daaaa da daaaa da"... + int tick_dest1 = AL::sigmap.raster1(tick, raster*2); //round down + int tick_dest2 = tick_dest1 + raster + raster*swing/100; + int tick_dest3 = tick_dest1 + raster*2; + + int tick_diff1 = tick_dest1 - tick; + int tick_diff2 = tick_dest2 - tick; + int tick_diff3 = tick_dest3 - tick; + + if ((abs(tick_diff1) <= abs(tick_diff2)) && (abs(tick_diff1) <= abs(tick_diff3))) //tick_dest1 is the nearest tick + return tick_dest1; + else if ((abs(tick_diff2) <= abs(tick_diff1)) && (abs(tick_diff2) <= abs(tick_diff3))) //tick_dest2 is the nearest tick + return tick_dest2; + else + return tick_dest3; +} + +void quantize_notes(const set<Part*>& parts, int range, int raster, int strength, int swing, int threshold) +{ + map<Event*, Part*> events = get_events(parts, range); + + if (!events.empty()) + { + song->startUndo(); + + for (map<Event*, Part*>::iterator it=events.begin(); it!=events.end(); it++) + { + Event& event=*(it->first); + Part* part=it->second; + + unsigned begin_tick = event.tick() + part->tick(); + int begin_diff = quantize_tick(begin_tick, raster, swing) - begin_tick; + + if (abs(begin_diff) > threshold) + begin_tick = begin_tick + begin_diff*strength/100; + + + unsigned len=event.lenTick(); + + unsigned end_tick = begin_tick + len; + int len_diff = quantize_tick(end_tick, raster, swing) - end_tick; + + if (abs(len_diff) > threshold) + len = len + len_diff*strength/100; + + if (len <= 0) + len = 1; + + + if ( (event.lenTick() != len) || (event.tick() + part->tick() != begin_tick) ) + { + Event newEvent = event.clone(); + newEvent.setTick(begin_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, false, false); + } + } + + song->endUndo(SC_EVENT_MODIFIED); + } +} + +void erase_notes(const set<Part*>& parts, int range) +{ + map<Event*, Part*> events = get_events(parts, range); + + if (!events.empty()) + { + song->startUndo(); + + for (map<Event*, Part*>::iterator it=events.begin(); it!=events.end(); it++) + { + Event& event=*(it->first); + Part* part=it->second; + + audio->msgDeleteEvent(event, part, false, false, false); + } + + song->endUndo(SC_EVENT_REMOVED); + } +} + + diff --git a/muse2/muse/functions.h b/muse2/muse/functions.h new file mode 100644 index 00000000..03d0ba88 --- /dev/null +++ b/muse2/muse/functions.h @@ -0,0 +1,41 @@ +//========================================================= +// MusE +// Linux Music Editor +// $Id: functions.h,v 1.20.2.19 2011/05/05 20:10 flo93 Exp $ +// (C) Copyright 2011 Florian Jung (flo93@sourceforge.net) +//========================================================= + +#ifndef __FUNCTIONS_H__ +#define __FUNCTIONS_H__ + +#include "velocity.h" +#include "quantize.h" +#include "gatetime.h" + +#include <set> +#include "part.h" + + +extern GateTime* gatetime_dialog; +extern Velocity* velocity_dialog; +extern Quantize* quantize_dialog; + +void init_function_dialogs(QWidget* parent); + + +std::set<Part*> partlist_to_set(PartList* pl); + +//these functions simply do their job, non-interactively +void modify_velocity(const std::set<Part*>& parts, int range, int rate, int offset=0); +void modify_notelen(const std::set<Part*>& parts, int range, int rate, int offset=0); +void quantize_notes(const std::set<Part*>& parts, int range, int raster, int strength=100, int swing=0, int threshold=0); +void erase_notes(const std::set<Part*>& parts, int range); + +//the below functions automatically open the dialog +//they return true if you click "ok" and false if "abort" +bool modify_velocity(const std::set<Part*>& parts); +bool modify_notelen(const std::set<Part*>& parts); +bool quantize_notes(const std::set<Part*>& parts); + + +#endif diff --git a/muse2/muse/globals.cpp b/muse2/muse/globals.cpp index 6c0bbbc6..f8ae4454 100644 --- a/muse2/muse/globals.cpp +++ b/muse2/muse/globals.cpp @@ -174,10 +174,12 @@ const char* med_file_save_pattern[] = { */ const QStringList med_file_pattern = QT_TRANSLATE_NOOP("@default", + QString("all known files (*.med *.med.gz *.med.bz2 *.mid *.midi *.kar);;") + QString("med Files (*.med *.med.gz *.med.bz2);;") + QString("Uncompressed med Files (*.med);;") + QString("gzip compressed med Files (*.med.gz);;") + QString("bzip2 compressed med Files (*.med.bz2);;") + + QString("mid Files (*.mid *.midi *.kar);;") + QString("All Files (*)")).split(";;"); const QStringList med_file_save_pattern = QT_TRANSLATE_NOOP("@default", diff --git a/muse2/muse/main.cpp b/muse2/muse/main.cpp index 53f8961b..6481f4cb 100644 --- a/muse2/muse/main.cpp +++ b/muse2/muse/main.cpp @@ -27,6 +27,7 @@ #include "globals.h" #include "icons.h" #include "sync.h" +#include "functions.h" extern bool initDummyAudio(); extern void initIcons(); @@ -470,6 +471,9 @@ int main(int argc, char* argv[]) muse = new MusE(argc, &argv[optind]); app.setMuse(muse); muse->setWindowIcon(*museIcon); + + init_function_dialogs(muse); + // Added by Tim. p3.3.22 if (!debugMode) { diff --git a/muse2/muse/midiedit/CMakeLists.txt b/muse2/muse/midiedit/CMakeLists.txt index 7e973aaa..a52d1844 100644 --- a/muse2/muse/midiedit/CMakeLists.txt +++ b/muse2/muse/midiedit/CMakeLists.txt @@ -35,7 +35,6 @@ QT4_WRAP_CPP ( midiedit_mocs piano.h pianoroll.h prcanvas.h - quantconfig.h scoreedit.h ) @@ -58,7 +57,6 @@ file (GLOB midiedit_source_files piano.cpp pianoroll.cpp prcanvas.cpp - quantconfig.cpp scoreedit.cpp ) diff --git a/muse2/muse/midiedit/dcanvas.cpp b/muse2/muse/midiedit/dcanvas.cpp index 1303c189..a21f04c0 100644 --- a/muse2/muse/midiedit/dcanvas.cpp +++ b/muse2/muse/midiedit/dcanvas.cpp @@ -31,7 +31,6 @@ #include "globals.h" #include "midiport.h" #include "audio.h" -#include "velocity.h" #include "shortcuts.h" #include "icons.h" @@ -608,7 +607,7 @@ void DrumCanvas::drawCanvas(QPainter& p, const QRect& rect) //--------------------------------------------------------- // drawTopItem //--------------------------------------------------------- -void DrumCanvas::drawTopItem(QPainter &p, const QRect &r) +void DrumCanvas::drawTopItem(QPainter& p, const QRect&) { // draw cursor if (_tool == CursorTool) { @@ -819,52 +818,6 @@ void DrumCanvas::cmd(int cmd) 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(); @@ -1399,13 +1352,10 @@ void DrumCanvas::keyPress(QKeyEvent* event) if (_tool == CursorTool) { 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; diff --git a/muse2/muse/midiedit/dlist.cpp b/muse2/muse/midiedit/dlist.cpp index 3736d6aa..3b8670db 100644 --- a/muse2/muse/midiedit/dlist.cpp +++ b/muse2/muse/midiedit/dlist.cpp @@ -220,8 +220,6 @@ 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]; @@ -259,7 +257,6 @@ void DList::viewMousePressEvent(QMouseEvent* ev) 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); } @@ -328,7 +325,6 @@ void DList::viewMousePressEvent(QMouseEvent* ev) else if (val > 127) val = 127; - ///if (ev->state() & Qt::ControlButton) { if (ev->modifiers() & Qt::ControlModifier) { audio->msgIdle(true); // Delete all port controller events. @@ -724,7 +720,6 @@ void DList::viewMouseReleaseEvent(QMouseEvent* ev) 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; diff --git a/muse2/muse/midiedit/drumedit.cpp b/muse2/muse/midiedit/drumedit.cpp index ed3cd0e8..d9029969 100644 --- a/muse2/muse/midiedit/drumedit.cpp +++ b/muse2/muse/midiedit/drumedit.cpp @@ -43,6 +43,7 @@ #include "drummap.h" #include "audio.h" #include "gconfig.h" +#include "functions.h" /* static const char* map_file_pattern[] = { @@ -905,6 +906,9 @@ void DrumEdit::cmd(int cmd) case DrumCanvas::CMD_RESET: reset(); break; + case DrumCanvas::CMD_MODIFY_VELOCITY: + modify_velocity(partlist_to_set(parts())); + break; default: ((DrumCanvas*)(canvas))->cmd(cmd); break; diff --git a/muse2/muse/midiedit/pianoroll.cpp b/muse2/muse/midiedit/pianoroll.cpp index 2778d8b9..6b0e37cb 100644 --- a/muse2/muse/midiedit/pianoroll.cpp +++ b/muse2/muse/midiedit/pianoroll.cpp @@ -44,9 +44,10 @@ #include "gconfig.h" #include "icons.h" #include "audio.h" +#include "functions.h" + #include "cmd.h" -#include "quantconfig.h" #include "shortcuts.h" #include "mtrackinfo.h" @@ -77,7 +78,6 @@ PianoRoll::PianoRoll(PartList* pl, QWidget* parent, const char* name, unsigned i deltaMode = false; resize(_widthInit, _heightInit); selPart = 0; - quantConfig = 0; _playEvents = false; _quantStrength = _quantStrengthInit; _quantLimit = _quantLimitInit; @@ -186,30 +186,11 @@ PianoRoll::PianoRoll(PartList* pl, QWidget* parent, const char* name, unsigned i 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())); + funcQuantizeAction = menuFunctions->addAction(tr("Quantize")); + mapper->setMapping(funcQuantizeAction, PianoCanvas::CMD_QUANTIZE); + connect(funcQuantizeAction, 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")); + funcGateTimeAction = menuFunctions->addAction(tr("Modify Note Length")); mapper->setMapping(funcGateTimeAction, PianoCanvas::CMD_MODIFY_GATE_TIME); connect(funcGateTimeAction, SIGNAL(triggered()), mapper, SLOT(map())); @@ -655,7 +636,14 @@ PianoRoll::~PianoRoll() void PianoRoll::cmd(int cmd) { - ((PianoCanvas*)canvas)->cmd(cmd, _quantStrength, _quantLimit, _quantLen, _to); + switch (cmd) + { + case PianoCanvas::CMD_MODIFY_GATE_TIME: modify_notelen(partlist_to_set(parts())); break; + case PianoCanvas::CMD_MODIFY_VELOCITY: modify_velocity(partlist_to_set(parts())); break; + case PianoCanvas::CMD_QUANTIZE: quantize_notes(partlist_to_set(parts())); break; + + default: ((PianoCanvas*)canvas)->cmd(cmd); + } } //--------------------------------------------------------- @@ -1057,13 +1045,10 @@ void PianoRoll::keyPressEvent(QKeyEvent* event) 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; @@ -1201,21 +1186,6 @@ void PianoRoll::keyPressEvent(QKeyEvent* event) } //--------------------------------------------------------- -// 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 //--------------------------------------------------------- @@ -1336,12 +1306,7 @@ void PianoRoll::initShortcuts() //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); + funcQuantizeAction->setShortcut(shortcuts[SHRT_OVER_QUANTIZE].key); //FINDMICH TODO FLO funcGateTimeAction->setShortcut(shortcuts[SHRT_MODIFY_GATE_TIME].key); funcModVelAction->setShortcut(shortcuts[SHRT_MODIFY_VELOCITY].key); diff --git a/muse2/muse/midiedit/pianoroll.h b/muse2/muse/midiedit/pianoroll.h index 2bfa9324..87bf52b6 100644 --- a/muse2/muse/midiedit/pianoroll.h +++ b/muse2/muse/midiedit/pianoroll.h @@ -35,7 +35,6 @@ class Splitter; class PartList; class Toolbar1; class Xml; -class QuantConfig; class ScrollScale; class Part; class SNode; @@ -81,11 +80,7 @@ class PianoRoll : public MidiEditor { QAction* evColorPitchAction; QAction* evColorVelAction; - QAction* funcOverQuantAction; - QAction* funcNoteOnQuantAction; - QAction* funcNoteOnOffQuantAction; - QAction* funcIterQuantAction; - QAction* funcConfigQuantAction; + QAction* funcQuantizeAction; QAction* funcGateTimeAction; QAction* funcModVelAction; QAction* funcCrescendoAction; @@ -137,7 +132,6 @@ class PianoRoll : public MidiEditor { int _quantLimit; int _to; bool _quantLen; - QuantConfig* quantConfig; bool _playEvents; //QScrollBar* infoScroll; @@ -160,7 +154,6 @@ class PianoRoll : public MidiEditor { //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; } diff --git a/muse2/muse/midiedit/prcanvas.cpp b/muse2/muse/midiedit/prcanvas.cpp index a0ffdcaf..2966cf71 100644 --- a/muse2/muse/midiedit/prcanvas.cpp +++ b/muse2/muse/midiedit/prcanvas.cpp @@ -32,8 +32,6 @@ #include "mpevent.h" #include "globals.h" #include "cmd.h" -#include "gatetime.h" -#include "velocity.h" #include "song.h" #include "audio.h" @@ -82,7 +80,6 @@ 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); @@ -907,10 +904,8 @@ void PianoCanvas::drawCanvas(QPainter& p, const QRect& rect) // pulldown menu commands //--------------------------------------------------------- -void PianoCanvas::cmd(int cmd, int quantStrength, - int quantLimit, bool quantLen, int range) +void PianoCanvas::cmd(int cmd) { - cmdRange = range; switch (cmd) { case CMD_CUT: copy(); @@ -946,18 +941,7 @@ void PianoCanvas::cmd(int cmd, int quantStrength, 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()) @@ -1032,96 +1016,6 @@ void PianoCanvas::cmd(int cmd, int quantStrength, 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()) @@ -1231,55 +1125,6 @@ void PianoCanvas::cmd(int cmd, int quantStrength, } //--------------------------------------------------------- -// 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 //--------------------------------------------------------- diff --git a/muse2/muse/midiedit/prcanvas.h b/muse2/muse/midiedit/prcanvas.h index bda22fc3..39506a13 100644 --- a/muse2/muse/midiedit/prcanvas.h +++ b/muse2/muse/midiedit/prcanvas.h @@ -37,7 +37,6 @@ class QRect; //--------------------------------------------------------- class PianoCanvas : public EventCanvas { - int cmdRange; int colorMode; int playedPitch; @@ -63,7 +62,6 @@ class PianoCanvas : public EventCanvas { 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*); @@ -88,8 +86,7 @@ class PianoCanvas : public EventCanvas { public: enum { CMD_CUT, CMD_COPY, CMD_PASTE, CMD_DEL, - CMD_OVER_QUANTIZE, CMD_ON_QUANTIZE, CMD_ONOFF_QUANTIZE, - CMD_ITERATIVE_QUANTIZE, + CMD_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, @@ -100,7 +97,7 @@ class PianoCanvas : public EventCanvas { }; PianoCanvas(MidiEditor*, QWidget*, int, int); - void cmd(int, int, int, bool, int); + void cmd(int cmd); void setColorMode(int mode) { colorMode = mode; redraw(); diff --git a/muse2/muse/midiedit/quantconfig.cpp b/muse2/muse/midiedit/quantconfig.cpp deleted file mode 100644 index 2f413e6a..00000000 --- a/muse2/muse/midiedit/quantconfig.cpp +++ /dev/null @@ -1,79 +0,0 @@ -//========================================================= -// 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/muse2/muse/midiedit/quantconfig.h b/muse2/muse/midiedit/quantconfig.h deleted file mode 100644 index 4466cdf0..00000000 --- a/muse2/muse/midiedit/quantconfig.h +++ /dev/null @@ -1,32 +0,0 @@ -//========================================================= -// 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 - diff --git a/muse2/muse/midiedit/scoreedit.cpp b/muse2/muse/midiedit/scoreedit.cpp index 31f0f325..e70e5310 100644 --- a/muse2/muse/midiedit/scoreedit.cpp +++ b/muse2/muse/midiedit/scoreedit.cpp @@ -43,25 +43,20 @@ using namespace std; #include "mtscale.h" #include "prcanvas.h" #include "scoreedit.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 "functions.h" #include "cmd.h" -#include "quantconfig.h" -#include "shortcuts.h" - -#include "mtrackinfo.h" - #include "sig.h" +#include "song.h" + +//#include "../ctrl/ctrledit.h" +//#include "shortcuts.h" string IntToStr(int i); @@ -109,6 +104,10 @@ QString IntToQStr(int i); #define STAFF_DISTANCE (10*YLEN) #define GRANDSTAFF_DISTANCE (8*YLEN) +#define NOTE_YDIST 20 +//NOTE_YDIST is the number of pixels which are between two notes +//which exceed their staves' y-boundaries, so that these boundaries +//must be expanded. QString create_random_string(int len=8) { @@ -331,12 +330,18 @@ ScoreEdit::ScoreEdit(QWidget* parent, const char* name, unsigned initPos) QAction* set_name_action = settings_menu->addAction(tr("Set Score &name"), menu_mapper, SLOT(map())); menu_mapper->setMapping(set_name_action, CMD_SET_NAME); - - + QMenu* functions_menu = menuBar()->addMenu(tr("&Functions")); + + QAction* func_quantize_action = functions_menu->addAction(tr("&Quantize"), menu_mapper, SLOT(map())); + QAction* func_notelen_action = functions_menu->addAction(tr("Change note &length"), menu_mapper, SLOT(map())); + QAction* func_velocity_action = functions_menu->addAction(tr("Change note &velocity"), menu_mapper, SLOT(map())); + menu_mapper->setMapping(func_quantize_action, CMD_QUANTIZE); + menu_mapper->setMapping(func_notelen_action, CMD_NOTELEN); + menu_mapper->setMapping(func_velocity_action, CMD_VELOCITY); - score_canvas->song_changed(SC_EVENT_INSERTED); + score_canvas->fully_recalculate(); score_canvas->goto_tick(initPos,true); if (name!=NULL) @@ -474,16 +479,19 @@ void ScoreEdit::menu_command(int cmd) } break; + case CMD_QUANTIZE: quantize_notes(score_canvas->get_all_parts()); break; + case CMD_VELOCITY: modify_velocity(score_canvas->get_all_parts()); break; + case CMD_NOTELEN: modify_notelen(score_canvas->get_all_parts()); break; + default: score_canvas->menu_command(cmd); } } -//--------------------------------------------------------- -// readPart -//--------------------------------------------------------- -Part* readPart(Xml& xml, QString tag_name="part") //TODO FINDMICH: duplicated from songfile.cpp; only difference: "none" is supported +//duplicated from songfile.cpp's MusE::readPart(); the only differences: +//"none" is supported and tag_name is settable +Part* read_part(Xml& xml, QString tag_name="part") { Part* part = 0; @@ -514,7 +522,7 @@ Part* readPart(Xml& xml, QString tag_name="part") //TODO FINDMICH: duplicated fr break; case Xml::TagStart: - xml.unknown("readPart"); + xml.unknown("read_part"); break; case Xml::TagEnd: @@ -546,7 +554,7 @@ void staff_t::read_status(Xml& xml) clef = clef_t(xml.parseInt()); else if (tag == "part") { - Part* part=readPart(xml); + Part* part=read_part(xml); if (part) parts.insert(part); else @@ -741,7 +749,7 @@ void ScoreEdit::readStatus(Xml& xml) else if (tag == "topwin") TopWin::readStatus(xml); else if (tag == "selectedPart") - score_canvas->set_selected_part(readPart(xml, "selectedPart")); + score_canvas->set_selected_part(read_part(xml, "selectedPart")); else if (tag == "staff") { staff_t staff(score_canvas); @@ -853,8 +861,8 @@ void ScoreCanvas::add_staves(PartList* pl, bool all_in_one) } cleanup_staves(); + fully_recalculate(); recalc_staff_pos(); - song_changed(SC_EVENT_INSERTED); } @@ -872,9 +880,14 @@ ScoreCanvas::ScoreCanvas(ScoreEdit* pr, QWidget* parent_widget, x_pos=0; x_left=0; y_pos=0; + have_lasso=false; dragging=false; + drag_cursor_changed=false; mouse_erases_notes=false; mouse_inserts_notes=true; + + undo_started=false; + undo_flags=0; selected_part=NULL; @@ -986,8 +999,8 @@ void ScoreCanvas::set_staffmode(list<staff_t>::iterator it, staff_mode_t mode) cerr << "ERROR: ILLEGAL FUNCTION CALL: invalid mode in set_staffmode" << endl; } + fully_recalculate(); recalc_staff_pos(); - song_changed(SC_EVENT_INSERTED); } void ScoreCanvas::remove_staff(list<staff_t>::iterator it) @@ -1012,8 +1025,8 @@ void ScoreCanvas::remove_staff(list<staff_t>::iterator it) } maybe_close_if_empty(); + fully_recalculate(); recalc_staff_pos(); - song_changed(SC_EVENT_INSERTED); } void ScoreCanvas::merge_staves(list<staff_t>::iterator dest, list<staff_t>::iterator src) @@ -1048,8 +1061,8 @@ void ScoreCanvas::merge_staves(list<staff_t>::iterator dest, list<staff_t>::iter remove_staff(src); + fully_recalculate(); recalc_staff_pos(); - song_changed(SC_EVENT_INSERTED); } void ScoreCanvas::move_staff_above(list<staff_t>::iterator dest, list<staff_t>::iterator src) @@ -1079,8 +1092,8 @@ void ScoreCanvas::move_staff_above(list<staff_t>::iterator dest, list<staff_t>:: staves.splice(dest, staves, src, src_end); + fully_recalculate(); recalc_staff_pos(); - song_changed(SC_EVENT_INSERTED); } void ScoreCanvas::move_staff_below(list<staff_t>::iterator dest, list<staff_t>::iterator src) @@ -1097,6 +1110,20 @@ void ScoreCanvas::move_staff_below(list<staff_t>::iterator dest, list<staff_t>:: move_staff_above(dest, src); } +set<Part*> ScoreCanvas::get_all_parts() +{ + set<Part*> result; + + for (list<staff_t>::iterator it=staves.begin(); it!=staves.end(); it++) + result.insert(it->parts.begin(), it->parts.end()); + + return result; +} + +void ScoreCanvas::fully_recalculate() +{ + song_changed(SC_EVENT_MODIFIED); +} void ScoreCanvas::song_changed(int flags) { @@ -1108,6 +1135,8 @@ void ScoreCanvas::song_changed(int flags) for (list<staff_t>::iterator it=staves.begin(); it!=staves.end(); it++) it->recalculate(); + + recalc_staff_pos(); redraw(); emit canvas_width_changed(canvas_width()); @@ -1124,11 +1153,17 @@ void ScoreCanvas::song_changed(int flags) } cleanup_staves(); - recalc_staff_pos(); for (list<staff_t>::iterator it=staves.begin(); it!=staves.end(); it++) it->recalculate(); + recalc_staff_pos(); + + redraw(); + } + + if (flags & SC_SELECTION) + { redraw(); } } @@ -1209,6 +1244,7 @@ void ScoreCanvas::init_pixmaps() mycolors[i]=config.partColors[i]; mycolors[BLACK_PIXMAP]=Qt::black; mycolors[HIGHLIGHTED_PIXMAP]=Qt::red; + mycolors[SELECTED_PIXMAP]=QColor(255,160,0); for (int i=0; i<64; i++) mycolors[i+VELO_PIXMAP_BEGIN]=QColor(i*4,0,0xff); @@ -1301,15 +1337,15 @@ bool operator< (const note_pos_t& a, const note_pos_t& b) } - + int flo_quantize(int tick, int quant_ticks) { - return int(nearbyint((float)tick / quant_ticks))*quant_ticks; + return AL::sigmap.raster(tick, quant_ticks); } int flo_quantize_floor(int tick, int quant_ticks) { - return int(tick / quant_ticks) * quant_ticks; + return AL::sigmap.raster1(tick, quant_ticks); } @@ -2419,6 +2455,9 @@ void staff_t::calc_item_pos() //key signature is properly drawn. int pos_add=0; + max_y_coord=0; + min_y_coord=0; + for (ScoreItemList::iterator it2=itemlist.begin(); it2!=itemlist.end(); it2++) { for (set<FloItem, floComp>::iterator it=it2->second.begin(); it!=it2->second.end();it++) @@ -2429,6 +2468,9 @@ void staff_t::calc_item_pos() if (it->type==FloItem::NOTE) { + if (it->y > max_y_coord) max_y_coord=it->y; + if (it->y < min_y_coord) min_y_coord=it->y; + it->x+=parent->note_x_indent() + it->shift*NOTE_SHIFT; switch (it->len) @@ -2502,6 +2544,9 @@ void staff_t::calc_item_pos() } } } + + max_y_coord+= (pix_quarter->height()/2 +NOTE_YDIST/2); + min_y_coord-= (pix_quarter->height()/2 +NOTE_YDIST/2); } void ScoreCanvas::calc_pos_add_list() @@ -2684,9 +2729,14 @@ void ScoreCanvas::draw_items(QPainter& p, int y_offset, staff_t& staff, ScoreIte color_index=VELO_PIXMAP_BEGIN + it->source_event->velo(); break; } + + if (it->source_event->selected()) + color_index=SELECTED_PIXMAP; + if (audio->isPlaying() && it->is_active) color_index=HIGHLIGHTED_PIXMAP; + draw_pixmap(p,it->x -x_pos+x_left,y_offset + it->y,it->pix[color_index]); //draw dots @@ -3007,7 +3057,14 @@ void ScoreCanvas::draw(QPainter& p, const QRect&) draw_items(p,it->y_draw - y_pos, *it); p.setClipping(false); } - + + if (have_lasso) + { + p.setPen(Qt::blue); + p.setBrush(Qt::NoBrush); + p.drawRect(lasso); + } + if (debugMsg) cout << "drawing done." << endl; } @@ -3149,6 +3206,10 @@ int ScoreCanvas::y_to_pitch(int y, int t, clef_t clef) void ScoreCanvas::mousePressEvent (QMouseEvent* event) { + keystate=((QInputEvent*)event)->modifiers(); + + bool ctrl=keystate & Qt::ControlModifier; + // den errechneten tick immer ABrunden! // denn der "bereich" eines schlags geht von schlag_begin bis nächsterschlag_begin-1 // noten werden aber genau in die mitte dieses bereiches gezeichnet @@ -3158,6 +3219,10 @@ void ScoreCanvas::mousePressEvent (QMouseEvent* event) int y=event->y() + y_pos - staff_it->y_draw; int x=event->x()+x_pos-x_left; int tick=flo_quantize_floor(x_to_tick(x), quant_ticks()); + + if (event->button()==Qt::LeftButton) + if (!ctrl) + deselect_all(); if (staff_it!=staves.end()) { @@ -3258,83 +3323,100 @@ void ScoreCanvas::mousePressEvent (QMouseEvent* event) } else if (event->button()==Qt::LeftButton) //edit? { + set_it->source_event->setSelected(!set_it->source_event->selected()); + song_changed(SC_SELECTION); + setMouseTracking(true); dragging=true; - setCursor(Qt::SizeAllCursor); - song->startUndo(); + drag_cursor_changed=false; + undo_started=false; + undo_flags=SC_EVENT_MODIFIED; } } else //we found nothing? - { - if ((event->button()==Qt::LeftButton) && (mouse_inserts_notes)) + if (event->button()==Qt::LeftButton) { - Part* curr_part = NULL; - set<Part*> possible_dests=staff_it->parts_at_tick(tick); - - if (!possible_dests.empty()) + if (mouse_inserts_notes) { - if (possible_dests.size()==1) - curr_part=*possible_dests.begin(); - else + Part* curr_part = NULL; + set<Part*> possible_dests=staff_it->parts_at_tick(tick); + + if (!possible_dests.empty()) { - if (possible_dests.find(selected_part)!=possible_dests.end()) - curr_part=selected_part; + if (possible_dests.size()==1) + curr_part=*possible_dests.begin(); else - QMessageBox::information(this, tr("Ambiguous part"), tr("There are two or more possible parts you could add the note to, but none matches the selected part. Please select the destination part by clicking on any note belonging to it and try again, or add a new stave containing only the destination part.")); - } - } - else - QMessageBox::information(this, tr("No part"), tr("There are no parts you could add the note to.")); - - if (curr_part!=NULL) - { - signed int relative_tick=(signed) tick - curr_part->tick(); - if (relative_tick<0) - cerr << "ERROR: THIS SHOULD NEVER HAPPEN: relative_tick is negative!" << endl; - song->startUndo(); - //stopping undo at the end of this function is unneccessary - //because we'll begin a drag right after it. finishing - //this drag will stop undo as well (in mouseReleaseEvent) - - Event newevent(Note); - newevent.setPitch(y_to_pitch(y,tick, staff_it->clef)); - newevent.setVelo(newnote_velo); - newevent.setVeloOff(newnote_velo_off); - newevent.setTick(relative_tick); - newevent.setLenTick((new_len>0)?new_len:last_len); - - if (flo_quantize(newevent.lenTick(), quant_ticks()) <= 0) - { - newevent.setLenTick(quant_ticks()); - if (debugMsg) cout << "inserted note's length would be invisible after quantisation (too short)." << endl << - " setting it to " << newevent.lenTick() << endl; + { + if (possible_dests.find(selected_part)!=possible_dests.end()) + curr_part=selected_part; + else + QMessageBox::information(this, tr("Ambiguous part"), tr("There are two or more possible parts you could add the note to, but none matches the selected part. Please select the destination part by clicking on any note belonging to it and try again, or add a new stave containing only the destination part.")); + } } + else + QMessageBox::information(this, tr("No part"), tr("There are no parts you could add the note to.")); - if (newevent.endTick() > curr_part->lenTick()) + if (curr_part!=NULL) { - if (debugMsg) cout << "clipping inserted note from len="<<newevent.endTick()<<" to len="<<(curr_part->lenTick() - newevent.tick())<<endl; - newevent.setLenTick(curr_part->lenTick() - newevent.tick()); - } - - audio->msgAddEvent(newevent, curr_part, false, false, false); - - dragged_event_part=curr_part; - dragged_event=newevent; - dragged_event_original_pitch=newevent.pitch(); + signed int relative_tick=(signed) tick - curr_part->tick(); + if (relative_tick<0) + cerr << "ERROR: THIS SHOULD NEVER HAPPEN: relative_tick is negative!" << endl; + song->startUndo(); + undo_started=true; + undo_flags=SC_EVENT_INSERTED | SC_EVENT_MODIFIED; + //stopping undo at the end of this function is unneccessary + //because we'll begin a drag right after it. finishing + //this drag will stop undo as well (in mouseReleaseEvent) + + Event newevent(Note); + newevent.setPitch(y_to_pitch(y,tick, staff_it->clef)); + newevent.setVelo(newnote_velo); + newevent.setVeloOff(newnote_velo_off); + newevent.setTick(relative_tick); + newevent.setLenTick((new_len>0)?new_len:last_len); + newevent.setSelected(true); + + if (flo_quantize(newevent.lenTick(), quant_ticks()) <= 0) + { + newevent.setLenTick(quant_ticks()); + if (debugMsg) cout << "inserted note's length would be invisible after quantisation (too short)." << endl << + " setting it to " << newevent.lenTick() << endl; + } + + if (newevent.endTick() > curr_part->lenTick()) + { + if (debugMsg) cout << "clipping inserted note from len="<<newevent.endTick()<<" to len="<<(curr_part->lenTick() - newevent.tick())<<endl; + newevent.setLenTick(curr_part->lenTick() - newevent.tick()); + } + + audio->msgAddEvent(newevent, curr_part, false, false, false); + + dragged_event_part=curr_part; + dragged_event=newevent; + dragged_event_original_pitch=newevent.pitch(); - mouse_down_pos=event->pos(); - mouse_operation=NO_OP; - mouse_x_drag_operation=LENGTH; + mouse_down_pos=event->pos(); + mouse_operation=NO_OP; + mouse_x_drag_operation=LENGTH; - song_changed(SC_EVENT_INSERTED); + fully_recalculate(); - setMouseTracking(true); - dragging=true; - setCursor(Qt::SizeAllCursor); - //song->startUndo(); unneccessary because we have started it already above + setMouseTracking(true); + dragging=true; + drag_cursor_changed=true; + setCursor(Qt::SizeAllCursor); + //song->startUndo(); unneccessary because we have started it already above + } } - } - } + else // !mouse_inserts_notes. open a lasso + { + have_lasso=true; + lasso_start=event->pos(); + lasso=QRect(lasso_start, lasso_start); + + setMouseTracking(true); + } + } } } } @@ -3356,10 +3438,13 @@ void ScoreCanvas::mouseReleaseEvent (QMouseEvent* event) } } - song->endUndo(SC_EVENT_MODIFIED); + if (undo_started) + song->endUndo(undo_flags); + setMouseTracking(false); unsetCursor(); dragging=false; + drag_cursor_changed=false; x_scroll_speed=0; x_scroll_pos=0; } @@ -3386,6 +3471,19 @@ void ScoreCanvas::mouseReleaseEvent (QMouseEvent* event) y_scroll_speed=0; y_scroll_pos=0; } + + if (have_lasso && event->button()==Qt::LeftButton) + { + set<Event*> already_processed; + + for (list<staff_t>::iterator it=staves.begin(); it!=staves.end(); it++) + it->apply_lasso(lasso.translated(x_pos-x_left, y_pos - it->y_draw), already_processed); + + song->update(SC_SELECTION); + + have_lasso=false; + redraw(); + } } #define PITCH_DELTA 5 @@ -3402,6 +3500,13 @@ void ScoreCanvas::mouseMoveEvent (QMouseEvent* event) int tick=flo_quantize_floor(x_to_tick(x), quant_ticks()); + + if ((drag_cursor_changed==false) && ((dx!=0) || (dy!=0))) + { + setCursor(Qt::SizeAllCursor); + drag_cursor_changed=true; + } + if (mouse_operation==NO_OP) { if ((abs(dx)>DRAG_INIT_DISTANCE) && (mouse_x_drag_operation!=NO_OP)) @@ -3428,16 +3533,25 @@ void ScoreCanvas::mouseMoveEvent (QMouseEvent* event) case PITCH: if (debugMsg) cout << "changing pitch, delta="<<nearbyint((float)dy/PITCH_DELTA)<<endl; new_pitch=dragged_event_original_pitch - nearbyint((float)dy/PITCH_DELTA); - + + if (new_pitch < 0) new_pitch=0; + if (new_pitch > 127) new_pitch=127; + if (dragged_event.pitch()!=new_pitch) { + if (!undo_started) + { + song->startUndo(); + undo_started=true; + } + Event tmp=dragged_event.clone(); tmp.setPitch(new_pitch); audio->msgChangeEvent(dragged_event, tmp, dragged_event_part, false, false, false); dragged_event=tmp; - song_changed(SC_EVENT_INSERTED); + fully_recalculate(); } break; @@ -3445,6 +3559,12 @@ void ScoreCanvas::mouseMoveEvent (QMouseEvent* event) case BEGIN: if (dragged_event.tick()+dragged_event_part->tick() != unsigned(tick)) { + if (!undo_started) + { + song->startUndo(); + undo_started=true; + } + Event tmp=dragged_event.clone(); signed relative_tick=tick-signed(dragged_event_part->tick()); @@ -3474,7 +3594,7 @@ void ScoreCanvas::mouseMoveEvent (QMouseEvent* event) audio->msgChangeEvent(dragged_event, tmp, dragged_event_part, false, false, false); dragged_event=tmp; - song_changed(SC_EVENT_INSERTED); + fully_recalculate(); } break; @@ -3483,6 +3603,12 @@ void ScoreCanvas::mouseMoveEvent (QMouseEvent* event) tick+=quant_ticks(); if (dragged_event.tick()+dragged_event.lenTick() + dragged_event_part->tick() != unsigned(tick)) { + if (!undo_started) + { + song->startUndo(); + undo_started=true; + } + Event tmp=dragged_event.clone(); signed relative_tick=tick-signed(dragged_event_part->tick()); signed new_len=relative_tick-dragged_event.tick(); @@ -3504,7 +3630,7 @@ void ScoreCanvas::mouseMoveEvent (QMouseEvent* event) audio->msgChangeEvent(dragged_event, tmp, dragged_event_part, false, false, false); dragged_event=tmp; - song_changed(SC_EVENT_INSERTED); + fully_recalculate(); } break; @@ -3555,6 +3681,12 @@ void ScoreCanvas::mouseMoveEvent (QMouseEvent* event) { y_scroll_speed=0; } + + if (have_lasso) + { + lasso=QRect(lasso_start, event->pos()).normalized(); + redraw(); + } } void ScoreCanvas::heartbeat_timer_event() @@ -3685,16 +3817,33 @@ void ScoreCanvas::recalc_staff_pos() { case NORMAL: it->y_draw = it->y_top + STAFF_DISTANCE/2; + if (it->min_y_coord < -STAFF_DISTANCE/2) + it->y_draw+= (-it->min_y_coord - STAFF_DISTANCE/2); + it->y_bottom = it->y_draw + STAFF_DISTANCE/2; + if (it->max_y_coord > STAFF_DISTANCE/2) + it->y_bottom+= (it->max_y_coord - STAFF_DISTANCE/2); + break; + case GRAND_TOP: it->y_draw = it->y_top + STAFF_DISTANCE/2; + if (it->min_y_coord < -STAFF_DISTANCE/2) + it->y_draw+= (-it->min_y_coord - STAFF_DISTANCE/2); + it->y_bottom = it->y_draw + GRANDSTAFF_DISTANCE/2; + break; + case GRAND_BOTTOM: it->y_draw = it->y_top + GRANDSTAFF_DISTANCE/2; + it->y_bottom = it->y_draw + STAFF_DISTANCE/2; + if (it->max_y_coord > STAFF_DISTANCE/2) + it->y_bottom+= (it->max_y_coord - STAFF_DISTANCE/2); + break; + default: cerr << "ERROR: THIS SHOULD NEVER HAPPEN: invalid staff type!" << endl; } @@ -3777,7 +3926,7 @@ void ScoreCanvas::set_quant(int val) set_pixels_per_whole(pixels_per_whole() * quant_len() / old_len ); - song_changed(SC_EVENT_INSERTED); + fully_recalculate(); } else { @@ -3785,7 +3934,7 @@ void ScoreCanvas::set_quant(int val) } } -void ScoreCanvas::set_pixels_per_whole(int val) //FINDMICH passt das? +void ScoreCanvas::set_pixels_per_whole(int val) { if (debugMsg) cout << "setting px per whole to " << val << endl; @@ -3848,6 +3997,25 @@ void ScoreCanvas::set_newnote_velo_off(int velo) newnote_velo_off=velo; } +void ScoreCanvas::deselect_all() +{ + set<Part*> all_parts=get_all_parts(); + + for (set<Part*>::iterator part=all_parts.begin(); part!=all_parts.end(); part++) + for (iEvent event=(*part)->events()->begin(); event!=(*part)->events()->end(); event++) + event->second.setSelected(false); + + song->update(SC_SELECTION); +} + +void ScoreCanvas::keyPressEvent(QKeyEvent* event) +{ + if (event->key()==Qt::Key_Delete) + { + erase_notes(get_all_parts(), 1); // 1 means "all selected" + } +} + bool staff_t::cleanup_parts() { bool did_something=false; @@ -3893,6 +4061,22 @@ set<Part*> staff_t::parts_at_tick(unsigned tick) return result; } +void staff_t::apply_lasso(QRect rect, set<Event*>& already_processed) +{ + for (ScoreItemList::iterator it=itemlist.begin(); it!=itemlist.end(); it++) + for (set<FloItem>::iterator it2=it->second.begin(); it2!=it->second.end(); it2++) + if (it2->type==FloItem::NOTE) + { + if (rect.contains(it2->x, it2->y)) + if (already_processed.find(it2->source_event)==already_processed.end()) + { + it2->source_event->setSelected(!it2->source_event->selected()); + already_processed.insert(it2->source_event); + } + } +} + + //the following assertions are made: // pix_quarter.width() == pix_half.width() @@ -3904,7 +4088,6 @@ set<Part*> staff_t::parts_at_tick(unsigned tick) - //hint: recalculating event- and itemlists "from zero" // could happen in realtime, as it is pretty fast. // however, this adds unneccessary cpu usage. @@ -3919,10 +4102,7 @@ set<Part*> staff_t::parts_at_tick(unsigned tick) * between, for example, when a cis is tied to a des * * CURRENT TODO - * o offer functions like in the pianoroll: quantize etc. - * o support selections - * o let the user select the distance between staves, or do this - * automatically? + * x nothing atm * * IMPORTANT TODO * o add a select-clef-toolbox for tracks @@ -3931,10 +4111,10 @@ set<Part*> staff_t::parts_at_tick(unsigned tick) * (0,5 sec) when displaying a whole song in scores * o save toolbar position also in the global window settings * and provide sane defaults + * o support edge-scrolling when opening a lasso * * less important stuff * o deal with expanding parts - * o do all the song_changed(SC_EVENT_INSERTED) properly * o use bars instead of flags over groups of 8ths / 16ths etc * o support different keys in different tracks at the same time * calc_pos_add_list and calc_item_pos will be affected by this @@ -3944,7 +4124,6 @@ set<Part*> staff_t::parts_at_tick(unsigned tick) * o save more configuration stuff (quant, color, to_init) * * really unimportant nice-to-haves - * o clean up code (find TODOs) * o support in-song clef-changes * o draw measure numbers * o use timesig_t in all timesig-stuff @@ -3954,6 +4133,10 @@ set<Part*> staff_t::parts_at_tick(unsigned tick) * * * stuff for the other muse developers + * o update translations + * o remove ambiguous translation: "offset"="zeitversatz" + * this is ambigous in mod. note len and WRONG in mod. velo dialogs + * * o process accurate timesignatures from muse's list (has to be implemented first in muse) * ( (2+2+3)/4 or (3+2+2)/4 instead of 7/4 ) * o maybe do expanding parts inside the msgChangeEvent or @@ -3967,35 +4150,6 @@ set<Part*> staff_t::parts_at_tick(unsigned tick) */ -/* how to use the score editor with multiple tracks - * ================================================ - * - * select parts, right-click, "display in new score window" or "display per-track in new score window" - * or "display in existing window -> 1,2,3,4" or "display per-track in existing..." - * - * ScoreCanvas has a list of note systems, consisting of the following: - * * all parts included in that view - * * eventlist, itemlist - * * used clef, transposing/octave settings - * * enum { NOT_GROUPED, I_AM_TOP, I_AM_BOTTOM } group_state - * NOT_GROUPED means "single note system" - * I_AM_TOP and I_AM_BOTTOM mean that the two systems belong - * together - * - * when redrawing, we iterate through all systems. - * we add a distance according to group_state - * then we draw the system. if group_state is I_AM_BOTTOM, we - * draw our beams longer/higher, and we draw a bracket - * - * when clicking around, we first determine which system has been clicked in - * (the systems have enough space in between, so there won't be notes - * from sys1 in sys2. if there are, they're ignored for simplicity) - * then we proceed as usual (adding, removing, changing notes) - * - * - * pos_add_list stays the same for each staff, so we only need one - */ - /* R O A D M A P * ============= * diff --git a/muse2/muse/midiedit/scoreedit.h b/muse2/muse/midiedit/scoreedit.h index 111a4f47..d664f139 100644 --- a/muse2/muse/midiedit/scoreedit.h +++ b/muse2/muse/midiedit/scoreedit.h @@ -20,12 +20,13 @@ #include <QSignalMapper> #include <QAction> #include <QActionGroup> +#include <QGridLayout> #include <values.h> #include "noteinfo.h" #include "cobject.h" -#include "midieditor.h" -#include "tools.h" +//#include "midieditor.h" +//#include "tools.h" #include "event.h" #include "view.h" #include "gconfig.h" @@ -55,9 +56,12 @@ using std::string; enum {CMD_COLOR_BLACK, CMD_COLOR_VELO, CMD_COLOR_PART, CMD_SET_NAME, CMD_NOTELEN_1, CMD_NOTELEN_2, CMD_NOTELEN_4, CMD_NOTELEN_8, - CMD_NOTELEN_16, CMD_NOTELEN_32, CMD_NOTELEN_LAST }; + CMD_NOTELEN_16, CMD_NOTELEN_32, CMD_NOTELEN_LAST, + + CMD_QUANTIZE, CMD_VELOCITY, CMD_NOTELEN }; class ScoreCanvas; +class EditToolBar; //--------------------------------------------------------- // ScoreEdit @@ -436,8 +440,9 @@ struct cumulative_t #define BLACK_PIXMAP (NUM_PARTCOLORS) #define HIGHLIGHTED_PIXMAP (NUM_PARTCOLORS+1) -#define NUM_MYCOLORS (NUM_PARTCOLORS+2 + 128) -#define VELO_PIXMAP_BEGIN (NUM_PARTCOLORS+2) +#define SELECTED_PIXMAP (NUM_PARTCOLORS+2) +#define NUM_MYCOLORS (NUM_PARTCOLORS+3 + 128) +#define VELO_PIXMAP_BEGIN (NUM_PARTCOLORS+3) struct timesig_t { @@ -469,6 +474,9 @@ struct staff_t int y_draw; int y_bottom; + int min_y_coord; + int max_y_coord; + staff_type_t type; clef_t clef; @@ -479,6 +487,8 @@ struct staff_t void process_itemlist(); void calc_item_pos(); + void apply_lasso(QRect rect, set<Event*>& already_processed); + void recalculate() { create_appropriate_eventlist(); @@ -619,6 +629,7 @@ class ScoreCanvas : public View int last_len; int new_len; //when zero or negative, last_len is used + Qt::KeyboardModifiers keystate; QPoint mouse_down_pos; bool mouse_down; enum operation_t @@ -634,11 +645,19 @@ class ScoreCanvas : public View bool mouse_inserts_notes; bool dragging; + bool drag_cursor_changed; Part* dragged_event_part; Event dragged_event; int dragged_event_original_pitch; + + bool have_lasso; + QPoint lasso_start; + QRect lasso; - + bool undo_started; + int undo_flags; + + enum {COLOR_MODE_BLACK, COLOR_MODE_PART, COLOR_MODE_VELO} coloring_mode; bool preamble_contains_keysig; @@ -664,11 +683,14 @@ class ScoreCanvas : public View void play_changed(bool); void config_changed(); + + void deselect_all(); public slots: void x_scroll_event(int); void y_scroll_event(int); void song_changed(int); + void fully_recalculate(); void goto_tick(int,bool); void pos_changed(int i, unsigned u, bool b); void heartbeat_timer_event(); @@ -700,6 +722,7 @@ class ScoreCanvas : public View virtual void mouseMoveEvent (QMouseEvent* event); virtual void mouseReleaseEvent (QMouseEvent* event); virtual void resizeEvent(QResizeEvent*); + virtual void keyPressEvent(QKeyEvent* event); public: ScoreCanvas(ScoreEdit*, QWidget*, int, int); @@ -725,6 +748,8 @@ class ScoreCanvas : public View Part* get_selected_part() {return selected_part;} void set_selected_part(Part* p) {selected_part=p;} + set<Part*> get_all_parts(); + void write_staves(int level, Xml& xml) const; }; diff --git a/muse2/muse/midifile.cpp b/muse2/muse/midifile.cpp index 319152d7..21e3e882 100644 --- a/muse2/muse/midifile.cpp +++ b/muse2/muse/midifile.cpp @@ -60,7 +60,7 @@ MidiFile::MidiFile(FILE* f) { fp = f; curPos = 0; - _mtype = MT_UNKNOWN; + _mtype = MT_GM; _error = MF_NO_ERROR; _tracks = new MidiFileTrackList; } @@ -325,7 +325,7 @@ int MidiFile::readEvent(MidiPlayEvent* event, MidiFileTrack* t) } if (buffer[len-1] != 0xf7) { printf("SYSEX endet nicht mit 0xf7!\n"); - // Forstsetzung folgt? + // Fortsetzung folgt? } else --len; // don't count 0xf7 diff --git a/muse2/muse/shortcuts.h b/muse2/muse/shortcuts.h index 1098be49..ede91d22 100644 --- a/muse2/muse/shortcuts.h +++ b/muse2/muse/shortcuts.h @@ -22,7 +22,7 @@ #define DEDIT_SHRT 2 // Drumedit shortcut #define LEDIT_SHRT 4 // Listedit shortcut #define SCORE_SHRT 8 // Score shortcut -#define ARRANG_SHRT 16 // Arrenger shortcut +#define ARRANG_SHRT 16 // Arranger shortcut #define TRANSP_SHRT 32 // Transport shortcut #define WAVE_SHRT 64 // Waveedit shortcut #define GLOBAL_SHRT 128 // Global shortcuts diff --git a/muse2/muse/widgets/CMakeLists.txt b/muse2/muse/widgets/CMakeLists.txt index 261c27a2..ee4af793 100644 --- a/muse2/muse/widgets/CMakeLists.txt +++ b/muse2/muse/widgets/CMakeLists.txt @@ -76,6 +76,7 @@ QT4_WRAP_CPP (widget_mocs # ttoolbar.h ttoolbutton.h velocity.h + quantize.h verticalmeter.h view.h vscale.h @@ -111,6 +112,7 @@ file (GLOB widgets_ui_files transformbase.ui transposebase.ui velocitybase.ui + quantbase.ui ) QT4_WRAP_UI (widget_ui_headers ${widgets_ui_files}) @@ -177,6 +179,7 @@ file (GLOB widgets_source_files ttoolbutton.cpp utils.cpp velocity.cpp + quantize.cpp verticalmeter.cpp view.cpp vscale.cpp diff --git a/muse2/muse/widgets/canvas.cpp b/muse2/muse/widgets/canvas.cpp index 14f414b7..c12ac956 100644 --- a/muse2/muse/widgets/canvas.cpp +++ b/muse2/muse/widgets/canvas.cpp @@ -538,11 +538,11 @@ void Canvas::viewMousePressEvent(QMouseEvent* event) updateSelection(); redraw(); } - startDrag(curItem, shift); + startDrag(curItem, ctrl); } else if (event->button() == Qt::RightButton) { if (curItem) { - if (shift) { + if (ctrl) { drag = DRAG_RESIZE; setCursor(); int dx = start.x() - curItem->x(); @@ -586,15 +586,14 @@ void Canvas::viewMousePressEvent(QMouseEvent* event) // Changed by T356. Alt is default reserved for moving the whole window in KDE. Changed to Shift-Alt. // Hmm, nope, shift-alt is also reserved sometimes. Must find a way to bypass, // why make user turn off setting? Left alone for now... - if (shift && !ctrl) + if (ctrl && !shift) drag = DRAG_COPY_START; else if (alt) { drag = DRAG_CLONE_START; } - else if (ctrl) { //Select all on the same pitch (e.g. same y-value) - if (!shift) + else if (shift) { //Select all on the same pitch (e.g. same y-value) + if (!ctrl) deselectAll(); - //printf("Yes, ctrl and press\n"); for (iCItem i = items.begin(); i != items.end(); ++i) { if (i->second->y() == curItem->y() ) selectItem(i->second, true); @@ -1046,32 +1045,26 @@ void Canvas::viewMouseMoveEvent(QMouseEvent* event) void Canvas::viewMouseReleaseEvent(QMouseEvent* event) { -// printf("release %x %x\n", event->state(), event->button()); - doScroll = false; canScrollLeft = true; canScrollRight = true; canScrollUp = true; canScrollDown = true; - ///if (event->state() & (Qt::LeftButton|Qt::RightButton|Qt::MidButton) & ~(event->button())) { if (event->buttons() & (Qt::LeftButton|Qt::RightButton|Qt::MidButton) & ~(event->button())) { - ///printf("ignore %x %x\n", keyState, event->button()); - //printf("viewMouseReleaseEvent ignore buttons:%x mods:%x button:%x\n", (int)event->buttons(), (int)keyState, event->button()); return; } QPoint pos = event->pos(); - ///bool shift = event->state() & Qt::ShiftModifier; - bool shift = ((QInputEvent*)event)->modifiers() & Qt::ShiftModifier; + bool ctrl = ((QInputEvent*)event)->modifiers() & Qt::ControlModifier; bool redrawFlag = false; switch (drag) { case DRAG_MOVE_START: case DRAG_COPY_START: case DRAG_CLONE_START: - if (!shift) + if (!ctrl) deselectAll(); - selectItem(curItem, !(shift && curItem->isSelected())); + selectItem(curItem, !(ctrl && curItem->isSelected())); updateSelection(); redrawFlag = true; itemReleased(curItem, curItem->pos()); @@ -1114,17 +1107,17 @@ void Canvas::viewMouseReleaseEvent(QMouseEvent* event) break; case DRAG_LASSO_START: lasso.setRect(-1, -1, -1, -1); - if (!shift) + if (!ctrl) deselectAll(); updateSelection(); redrawFlag = true; break; case DRAG_LASSO: - if (!shift) + if (!ctrl) deselectAll(); lasso = lasso.normalized(); - selectLasso(shift); + selectLasso(ctrl); updateSelection(); redrawFlag = true; break; diff --git a/muse2/muse/widgets/gatetime.cpp b/muse2/muse/widgets/gatetime.cpp index f1804c35..c64411a0 100644 --- a/muse2/muse/widgets/gatetime.cpp +++ b/muse2/muse/widgets/gatetime.cpp @@ -26,6 +26,8 @@ GateTime::GateTime(QWidget* parent) rangeGroup->addButton(loopButton, 2); rangeGroup->addButton(sloopButton, 3); rangeGroup->setExclusive(true); + + pullValues(); } //--------------------------------------------------------- @@ -34,18 +36,30 @@ GateTime::GateTime(QWidget* parent) void GateTime::accept() { - _range = rangeGroup->checkedId(); - _rateVal = rate->value(); - _offsetVal = offset->value(); + pullValues(); QDialog::accept(); } //--------------------------------------------------------- -// setRange +// pullValues //--------------------------------------------------------- -void GateTime::setRange(int id) +void GateTime::pullValues() { - rangeGroup->button(id)->setChecked(true); + range = rangeGroup->checkedId(); + rateVal = rate->value(); + offsetVal = offset->value(); } +//--------------------------------------------------------- +// exec +//--------------------------------------------------------- + +int GateTime::exec() + { + rangeGroup->button(range)->setChecked(true); + rate->setValue(rateVal); + offset->setValue(offsetVal); + + return QDialog::exec(); + } diff --git a/muse2/muse/widgets/gatetime.h b/muse2/muse/widgets/gatetime.h index dcb1827c..5585d6ad 100644 --- a/muse2/muse/widgets/gatetime.h +++ b/muse2/muse/widgets/gatetime.h @@ -18,22 +18,24 @@ class QDialog; //--------------------------------------------------------- class GateTime : public QDialog, public Ui::GateTimeBase { + private: Q_OBJECT - int _range; - int _rateVal; - int _offsetVal; QButtonGroup *rangeGroup; protected slots: void accept(); + void pullValues(); public: GateTime(QWidget* parent=0); - void setRange(int id); - int range() const { return _range; } - int rateVal() const { return _rateVal; } - int offsetVal() const { return _offsetVal; } + + int range; + int rateVal; + int offsetVal; + + public slots: + int exec(); }; #endif diff --git a/muse2/muse/widgets/gatetimebase.ui b/muse2/muse/widgets/gatetimebase.ui index babf5f02..e804de17 100644 --- a/muse2/muse/widgets/gatetimebase.ui +++ b/muse2/muse/widgets/gatetimebase.ui @@ -11,7 +11,7 @@ </rect> </property> <property name="windowTitle"> - <string>MusE: Modify Gate Time</string> + <string>MusE: Modify Note Length</string> </property> <layout class="QVBoxLayout"> <property name="spacing"> @@ -59,7 +59,7 @@ <item> <widget class="QRadioButton" name="sloopButton"> <property name="text"> - <string>Selected & Looped</string> + <string>Selected Looped</string> </property> </widget> </item> @@ -104,7 +104,7 @@ <string>%</string> </property> <property name="maximum"> - <number>200</number> + <number>1000</number> </property> <property name="value"> <number>100</number> @@ -124,6 +124,13 @@ </property> </widget> </item> + <item row="2" column="0" colspan="2"> + <widget class="QLabel" name="label"> + <property name="text"> + <string>lenNew = (lenOld * rate) + offset</string> + </property> + </widget> + </item> </layout> </widget> </item> diff --git a/muse2/muse/widgets/quantbase.ui b/muse2/muse/widgets/quantbase.ui new file mode 100644 index 00000000..6a88c86f --- /dev/null +++ b/muse2/muse/widgets/quantbase.ui @@ -0,0 +1,308 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>QuantBase</class> + <widget class="QDialog" name="QuantBase"> + <property name="enabled"> + <bool>true</bool> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>279</width> + <height>486</height> + </rect> + </property> + <property name="windowTitle"> + <string>MusE: Quantize</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout_2"> + <property name="spacing"> + <number>6</number> + </property> + <property name="margin"> + <number>11</number> + </property> + <item> + <widget class="QGroupBox" name="rangeBox"> + <property name="title"> + <string>Range</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <property name="spacing"> + <number>6</number> + </property> + <property name="margin"> + <number>11</number> + </property> + <item> + <widget class="QRadioButton" name="all_events_button"> + <property name="text"> + <string>All Events</string> + </property> + </widget> + </item> + <item> + <widget class="QRadioButton" name="selected_events_button"> + <property name="text"> + <string>Selected Events</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="QRadioButton" name="looped_events_button"> + <property name="text"> + <string>Looped Events</string> + </property> + </widget> + </item> + <item> + <widget class="QRadioButton" name="selected_looped_button"> + <property name="text"> + <string>Selected Looped</string> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QGroupBox" name="groupBox_2"> + <property name="title"> + <string>Values</string> + </property> + <layout class="QGridLayout" name="gridLayout"> + <property name="margin"> + <number>11</number> + </property> + <property name="spacing"> + <number>6</number> + </property> + <item row="1" column="0"> + <widget class="QLabel" name="TextLabel3"> + <property name="text"> + <string>Strength:</string> + </property> + <property name="wordWrap"> + <bool>false</bool> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QSpinBox" name="strength_spinbox"> + <property name="suffix"> + <string>%</string> + </property> + <property name="maximum"> + <number>100</number> + </property> + <property name="value"> + <number>80</number> + </property> + </widget> + </item> + <item row="2" column="0"> + <widget class="QLabel" name="TextLabel4"> + <property name="text"> + <string>Threshold (ticks):</string> + </property> + <property name="wordWrap"> + <bool>false</bool> + </property> + </widget> + </item> + <item row="2" column="1"> + <widget class="QSpinBox" name="threshold_spinbox"> + <property name="minimum"> + <number>0</number> + </property> + <property name="maximum"> + <number>10000</number> + </property> + <property name="singleStep"> + <number>1</number> + </property> + </widget> + </item> + <item row="4" column="0"> + <widget class="QLabel" name="label"> + <property name="text"> + <string>Quantize Len</string> + </property> + </widget> + </item> + <item row="4" column="1"> + <widget class="QCheckBox" name="len_checkbox"> + <property name="text"> + <string/> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + </item> + <item row="0" column="0"> + <widget class="QLabel" name="label_2"> + <property name="text"> + <string>Raster</string> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QComboBox" name="raster_combobox"> + <property name="editable"> + <bool>false</bool> + </property> + <property name="currentIndex"> + <number>3</number> + </property> + <property name="frame"> + <bool>true</bool> + </property> + <item> + <property name="text"> + <string>Whole</string> + </property> + </item> + <item> + <property name="text"> + <string>Half</string> + </property> + </item> + <item> + <property name="text"> + <string>Quarter</string> + </property> + </item> + <item> + <property name="text"> + <string>8th</string> + </property> + </item> + <item> + <property name="text"> + <string>16th</string> + </property> + </item> + <item> + <property name="text"> + <string>32th</string> + </property> + </item> + </widget> + </item> + <item row="3" column="0"> + <widget class="QLabel" name="label_3"> + <property name="text"> + <string>Swing:</string> + </property> + </widget> + </item> + <item row="3" column="1"> + <widget class="QSpinBox" name="swing_spinbox"> + <property name="minimum"> + <number>-99</number> + </property> + </widget> + </item> + <item row="5" column="0" colspan="2"> + <widget class="QLabel" name="label_4"> + <property name="text"> + <string>If the proposed change in tick or length is smaller than threshold, nothing is done. +If swing=0, this is normal +If swing is 33, you get a 2:1-rhythm. +If swing is -33, you get a 1:2-rhythm.</string> + </property> + <property name="wordWrap"> + <bool>true</bool> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout"> + <property name="spacing"> + <number>6</number> + </property> + <item> + <spacer name="Spacer1"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Expanding</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QPushButton" name="ok_button"> + <property name="text"> + <string>OK</string> + </property> + <property name="autoDefault"> + <bool>false</bool> + </property> + <property name="default"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="cancel_button"> + <property name="text"> + <string>Cancel</string> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + <layoutdefault spacing="6" margin="11"/> + <resources/> + <connections> + <connection> + <sender>ok_button</sender> + <signal>clicked()</signal> + <receiver>QuantBase</receiver> + <slot>accept()</slot> + <hints> + <hint type="sourcelabel"> + <x>20</x> + <y>20</y> + </hint> + <hint type="destinationlabel"> + <x>20</x> + <y>20</y> + </hint> + </hints> + </connection> + <connection> + <sender>cancel_button</sender> + <signal>clicked()</signal> + <receiver>QuantBase</receiver> + <slot>reject()</slot> + <hints> + <hint type="sourcelabel"> + <x>20</x> + <y>20</y> + </hint> + <hint type="destinationlabel"> + <x>20</x> + <y>20</y> + </hint> + </hints> + </connection> + </connections> +</ui> diff --git a/muse2/muse/widgets/quantize.cpp b/muse2/muse/widgets/quantize.cpp new file mode 100644 index 00000000..734f3d5d --- /dev/null +++ b/muse2/muse/widgets/quantize.cpp @@ -0,0 +1,54 @@ +//========================================================= +// MusE +// Linux Music Editor +// $Id: quantize.cpp,v 1.1.1.1 2011/05/05 18:51:04 flo93 Exp $ +// (C) Copyright 2011 Florian Jung (flo93@sourceforge.net) +//========================================================= + +#include <QButtonGroup> +#include "quantize.h" + + +Quantize::Quantize(QWidget* parent) + : QDialog(parent) +{ + setupUi(this); + range_group = new QButtonGroup; + range_group->addButton(all_events_button,0); + range_group->addButton(selected_events_button,1); + range_group->addButton(looped_events_button,2); + range_group->addButton(selected_looped_button,3); + + pull_values(); +} + +void Quantize::pull_values() +{ + range = range_group->checkedId(); + strength = strength_spinbox->value(); + threshold = threshold_spinbox->value(); + raster_power2 = raster_combobox->currentIndex(); + quant_len = len_checkbox->isChecked(); + swing = swing_spinbox->value(); +} + +void Quantize::accept() +{ + pull_values(); + QDialog::accept(); +} + +int Quantize::exec() +{ + if ((range < 0) || (range > 3)) range=0; + + range_group->button(range)->setChecked(true); + strength_spinbox->setValue(strength); + threshold_spinbox->setValue(threshold); + raster_combobox->setCurrentIndex(raster_power2); + len_checkbox->setChecked(quant_len); + swing_spinbox->setValue(swing); + + return QDialog::exec(); +} + diff --git a/muse2/muse/widgets/quantize.h b/muse2/muse/widgets/quantize.h new file mode 100644 index 00000000..3f54bc09 --- /dev/null +++ b/muse2/muse/widgets/quantize.h @@ -0,0 +1,40 @@ +//========================================================= +// MusE +// Linux Music Editor +// $Id: quantize.h,v 1.1.1.1 2011/05/05 18:51:04 flo93 Exp $ +// (C) Copyright 2011 Florian Jung (flo93@sourceforge.net) +//========================================================= + +#ifndef __QUANTIZE_H__ +#define __QUANTIZE_H__ + +#include "ui_quantbase.h" + +class QButtonGroup; + +class Quantize : public QDialog, public Ui::QuantBase +{ + private: + Q_OBJECT + QButtonGroup* range_group; + + protected slots: + void accept(); + void pull_values(); + + public: + Quantize(QWidget* parent = 0); + + int range; + int strength; + int threshold; + int raster_power2; + int swing; + bool quant_len; + + public slots: + int exec(); +}; + +#endif + diff --git a/muse2/muse/widgets/velocity.cpp b/muse2/muse/widgets/velocity.cpp index 309beb4d..ad9bbfe4 100644 --- a/muse2/muse/widgets/velocity.cpp +++ b/muse2/muse/widgets/velocity.cpp @@ -12,7 +12,7 @@ // Velocity //--------------------------------------------------------- -Velocity::Velocity(QDialog* parent) +Velocity::Velocity(QWidget* parent) : QDialog(parent) { setupUi(this); @@ -21,6 +21,8 @@ Velocity::Velocity(QDialog* parent) rangeGroup->addButton(selectedEvents,1); rangeGroup->addButton(loopedEvents,2); rangeGroup->addButton(selectedLooped,3); + + pullValues(); } //--------------------------------------------------------- @@ -29,18 +31,30 @@ Velocity::Velocity(QDialog* parent) void Velocity::accept() { - _range = rangeGroup->checkedId(); - _rateVal = rate->value(); - _offsetVal = offset->value(); + pullValues(); QDialog::accept(); } //--------------------------------------------------------- -// setRange +// pullValues //--------------------------------------------------------- -void Velocity::setRange(int id) +void Velocity::pullValues() { - rangeGroup->button(id)->setChecked(true); + range = rangeGroup->checkedId(); + rateVal = rate->value(); + offsetVal = offset->value(); } +//--------------------------------------------------------- +// exec +//--------------------------------------------------------- + +int Velocity::exec() + { + rangeGroup->button(range)->setChecked(true); + rate->setValue(rateVal); + offset->setValue(offsetVal); + + return QDialog::exec(); + } diff --git a/muse2/muse/widgets/velocity.h b/muse2/muse/widgets/velocity.h index cf5b2779..448b3e5b 100644 --- a/muse2/muse/widgets/velocity.h +++ b/muse2/muse/widgets/velocity.h @@ -17,22 +17,23 @@ class QButtonGroup; //--------------------------------------------------------- class Velocity : public QDialog, public Ui::VelocityBase { - int _range; - int _rateVal; - int _offsetVal; - + private: Q_OBJECT QButtonGroup* rangeGroup; protected slots: void accept(); + void pullValues(); public: - Velocity(QDialog* parent = 0); - void setRange(int id); - int range() const { return _range; } - int rateVal() const { return _rateVal; } - int offsetVal() const { return _offsetVal; } + Velocity(QWidget* parent = 0); + + int range; + int rateVal; + int offsetVal; + + public slots: + int exec(); }; #endif diff --git a/muse2/muse/widgets/velocitybase.ui b/muse2/muse/widgets/velocitybase.ui index 1e386e11..40fe625f 100644 --- a/muse2/muse/widgets/velocitybase.ui +++ b/muse2/muse/widgets/velocitybase.ui @@ -59,7 +59,7 @@ <item> <widget class="QRadioButton" name="selectedLooped"> <property name="text"> - <string>Selected & Looped</string> + <string>Selected Looped</string> </property> </widget> </item> @@ -114,7 +114,7 @@ <item row="1" column="1"> <widget class="QSpinBox" name="offset"> <property name="minimum"> - <number>1</number> + <number>-127</number> </property> <property name="maximum"> <number>127</number> @@ -122,6 +122,16 @@ <property name="singleStep"> <number>1</number> </property> + <property name="value"> + <number>0</number> + </property> + </widget> + </item> + <item row="2" column="0" colspan="2"> + <widget class="QLabel" name="label"> + <property name="text"> + <string>veloNew = (veloOld * rate) + offset</string> + </property> </widget> </item> </layout> |