summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--muse2/muse/midiedit/dcanvas.cpp4
-rw-r--r--muse2/muse/midiedit/prcanvas.cpp7
-rw-r--r--muse2/muse/midiedit/scoreedit.cpp4
-rw-r--r--muse2/muse/steprec.cpp248
4 files changed, 144 insertions, 119 deletions
diff --git a/muse2/muse/midiedit/dcanvas.cpp b/muse2/muse/midiedit/dcanvas.cpp
index 4b5c3ea9..b9ff5a20 100644
--- a/muse2/muse/midiedit/dcanvas.cpp
+++ b/muse2/muse/midiedit/dcanvas.cpp
@@ -731,7 +731,7 @@ void DrumCanvas::keyPressed(int index, int velocity)
MidiPlayEvent e(0, port, channel, 0x90, pitch, velocity);
audio->msgPlayMidiEvent(&e);
- if (_steprec && pos[0] >= start_tick && pos[0] < end_tick && curPart)
+ if (_steprec && pos[0] >= start_tick /* && pos[0] < end_tick [removed by flo93: this is handled in steprec->record] */ && curPart)
steprec->record(curPart,index,drumMap[index].len,editor->raster(),velocity,globalKeyState&Qt::ControlModifier,globalKeyState&Qt::ShiftModifier);
}
@@ -1120,7 +1120,7 @@ void DrumCanvas::midiNote(int pitch, int velo)
if (_midiin && _steprec && curPart
&& !audio->isPlaying() && velo && pos[0] >= start_tick
- && pos[0] < end_tick
+ /* && pos[0] < end_tick [removed by flo93: this is handled in steprec->record] */
&& !(globalKeyState & Qt::AltModifier)) {
steprec->record(curPart,drumInmap[pitch],drumMap[(int)drumInmap[pitch]].len,editor->raster(),velo,globalKeyState&Qt::ControlModifier,globalKeyState&Qt::ShiftModifier);
}
diff --git a/muse2/muse/midiedit/prcanvas.cpp b/muse2/muse/midiedit/prcanvas.cpp
index a659ad26..73e70e84 100644
--- a/muse2/muse/midiedit/prcanvas.cpp
+++ b/muse2/muse/midiedit/prcanvas.cpp
@@ -66,7 +66,7 @@ void PianoCanvas::addItem(Part* part, Event& event)
NEvent* ev = new NEvent(event, part, pitch2y(event.pitch()));
items.add(ev);
- int diff = event.endTick()-part->lenTick();
+ int diff = event.tick()-part->lenTick();
if (diff > 0) {// too short part? extend it
//printf("addItem - this code should not be run!\n");
//Part* newPart = part->clone();
@@ -655,9 +655,8 @@ void PianoCanvas::pianoPressed(int pitch, int velocity, bool shift)
MidiPlayEvent e(0, port, channel, 0x90, pitch, velocity);
audio->msgPlayMidiEvent(&e);
- if (_steprec && pos[0] >= start_tick && pos[0] < end_tick && curPart) {
+ if (_steprec && pos[0] >= start_tick /* && pos[0] < end_tick [removed by flo93: this is handled in steprec->record] */ && curPart)
steprec->record(curPart,pitch,editor->raster(),editor->raster(),velocity,globalKeyState&Qt::ControlModifier,shift);
- }
}
//---------------------------------------------------------
@@ -881,7 +880,7 @@ void PianoCanvas::midiNote(int pitch, int velo)
if (_midiin && _steprec && curPart
&& !audio->isPlaying() && velo && pos[0] >= start_tick
- && pos[0] < end_tick
+ /* && pos[0] < end_tick [removed by flo93: this is handled in steprec->record] */
&& !(globalKeyState & Qt::AltModifier)) {
steprec->record(curPart,pitch,editor->raster(),editor->raster(),velo,globalKeyState&Qt::ControlModifier,globalKeyState&Qt::ShiftModifier);
}
diff --git a/muse2/muse/midiedit/scoreedit.cpp b/muse2/muse/midiedit/scoreedit.cpp
index c2380539..d7131db9 100644
--- a/muse2/muse/midiedit/scoreedit.cpp
+++ b/muse2/muse/midiedit/scoreedit.cpp
@@ -4456,7 +4456,8 @@ void staff_t::update_part_indices()
* between, for example, when a cis is tied to a des
*
* CURRENT TODO
- * o do autoexpand in steprec.cpp and scoreedit.cpp
+ * o do autoexpand in scoreedit.cpp
+ * o draw the edge of parts hiding notes "jagged" (hasHiddenNotes() is interesting for this)
*
* IMPORTANT TODO
* o shrink a part from its beginning as well! watch out for clones!
@@ -4477,6 +4478,7 @@ void staff_t::update_part_indices()
* o transpose etc. must also transpose key-pressure events
* o transpose: support in-key-transpose
* o thin out: remove unneeded ctrl messages
+ * o make muse usable without the middle mouse button
*
* less important stuff
* o quantize-templates (everything is forced into a specified
diff --git a/muse2/muse/steprec.cpp b/muse2/muse/steprec.cpp
index 29cb9540..c1fc23b1 100644
--- a/muse2/muse/steprec.cpp
+++ b/muse2/muse/steprec.cpp
@@ -9,6 +9,7 @@
#include "part.h"
#include "event.h"
#include "globals.h"
+#include "functions.h"
#include "song.h"
#include "audio.h"
@@ -39,121 +40,144 @@ void StepRec::timeout()
void StepRec::record(Part* part, int pitch, int len, int step, int velo, bool ctrl, bool shift)
{
- unsigned tick = song->cpos();
-
- if (pitch!=rcSteprecNote) {
- chord_timer->stop();
-
-
- //
- // extend len of last note?
- //
- EventList* events = part->events();
- if (ctrl) {
- 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()) == tick)) {
- Event e = ev.clone();
- e.setLenTick(ev.lenTick() + len);
- // Indicate do undo, and do not do port controller values and clone parts.
- audio->msgChangeEvent(ev, e, part, true, false, false);
-
- if (!shift) {
- chord_timer_set_to_tick = tick + step;
- chord_timer->start();
- }
- return;
- }
- }
- }
+ unsigned tick = song->cpos();
+ unsigned lasttick=0;
+ Undo operations;
+
+ if (pitch!=rcSteprecNote)
+ {
+ chord_timer->stop();
+
+ // extend len of last note?
+ EventList* events = part->events();
+ if (ctrl)
+ {
+ for (iEvent i = events->begin(); i != events->end(); ++i)
+ {
+ Event ev = i->second;
+ if (ev.isNote() && ev.pitch() == pitch && ((ev.tick() + ev.lenTick() + part->tick()) == tick))
+ {
+ Event e = ev.clone();
+ e.setLenTick(ev.lenTick() + len);
+ operations.push_back(UndoOp(UndoOp::ModifyEvent, e,ev, part, false, false));
+
+ if (!shift)
+ {
+ chord_timer_set_to_tick = tick + step;
+ chord_timer->start();
+ }
+
+ lasttick=tick+len - part->tick();
+ goto steprec_record_foot;
+ }
+ }
+ }
- //
- // 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, part);
- audio->msgDeleteEvent(ev, part, true, false, false);
+ if (tick<=part->endTick())
+ {
+ // if we already entered the note, delete it
+ // if we would find a note after part->lenTick(), the above "if"
+ // avoids this. this has to be avoided because then part->hasHiddenNotes() is true
+ // which results in forbidding any action beyond its end
+ EventRange range = events->equal_range(tick - part->tick());
+ for (iEvent i = range.first; i != range.second; ++i)
+ {
+ Event ev = i->second;
+ if (ev.isNote() && ev.pitch() == pitch)
+ {
+ audio->msgDeleteEvent(ev, part, true, false, false);
- if (!shift) {
- chord_timer_set_to_tick = tick + step;
- chord_timer->start();
- }
-
- return;
- }
- }
-
- Event e(Note);
- e.setTick(tick - part->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, part);
- audio->msgAddEvent(e, part, true, false, false);
-
- if (! (globalKeyState & Qt::ShiftModifier)) {
- chord_timer_set_to_tick = tick + step;
- chord_timer->start();
- }
- }
- else { // equals if (pitch==rcSteprecNote)
- bool held_notes=false;
- if (note_held_down!=NULL)
- {
- for (int i=0;i<128;i++)
- if (note_held_down[i]) { held_notes=true; break; }
- }
- else
- held_notes=false;
-
-
- if (held_notes)
- {
- chord_timer->stop();
-
- // extend len of last note(s)
- using std::set;
-
- set<Event*> extend_set;
- EventList* events = part->events();
- for (iEvent i = events->begin(); i != events->end(); ++i) {
- Event& ev = i->second;
- if (!ev.isNote())
- continue;
+ if (!shift)
+ {
+ chord_timer_set_to_tick = tick + step;
+ chord_timer->start();
+ }
+
+ return;
+ }
+ }
+ }
+
+
+ Event e(Note);
+ e.setTick(tick - part->tick());
+ e.setPitch(pitch);
+ e.setVelo(velo);
+ e.setLenTick(len);
+ operations.push_back(UndoOp(UndoOp::AddEvent, e, part, false, false));
+ lasttick=e.endTick();
+
+ if (! (globalKeyState & Qt::ShiftModifier))
+ {
+ chord_timer_set_to_tick = tick + step;
+ chord_timer->start();
+ }
+
+ goto steprec_record_foot; // this is actually unneccessary, but for clarity
+ }
+ else // equals if (pitch==rcSteprecNote)
+ {
+ bool held_notes=false;
+ if (note_held_down!=NULL)
+ {
+ for (int i=0;i<128;i++)
+ if (note_held_down[i]) { held_notes=true; break; }
+ }
+ else
+ held_notes=false;
+
- if (note_held_down[ev.pitch()] && ((ev.tick() + ev.lenTick()) == tick))
- extend_set.insert(&ev);
- }
- for (set<Event*>::iterator it=extend_set.begin(); it!=extend_set.end(); it++)
- {
- Event& ev=**it;
- Event e = ev.clone();
- e.setLenTick(ev.lenTick() + len);
- // Indicate do undo, and do not do port controller values and clone parts.
- audio->msgChangeEvent(ev, e, part, true, false, false);
- }
+ if (held_notes)
+ {
+ chord_timer->stop();
+
+ // extend len of last note(s)
+ using std::set;
+
+ set<Event*> extend_set;
+ EventList* events = part->events();
+ for (iEvent i = events->begin(); i != events->end(); ++i)
+ {
+ Event& ev = i->second;
+ if (ev.isNote() && note_held_down[ev.pitch()] && ((ev.tick() + ev.lenTick() + part->tick()) == tick))
+ extend_set.insert(&ev);
+ }
+
+ for (set<Event*>::iterator it=extend_set.begin(); it!=extend_set.end(); it++)
+ {
+ Event& ev=**it;
+ Event e = ev.clone();
+ e.setLenTick(ev.lenTick() + len);
+ operations.push_back(UndoOp(UndoOp::ModifyEvent,e, ev, part, false, false));
+ }
- if (!shift) {
- chord_timer_set_to_tick = tick + step;
- chord_timer->start();
- }
- return;
-
- }
- else // equals if (!held_notes)
- {
- chord_timer->stop();
+ if (!shift)
+ {
+ chord_timer_set_to_tick = tick + step;
+ chord_timer->start();
+ }
+
+ lasttick=tick+len - part->tick();
+ goto steprec_record_foot; // this is actually unneccessary, but for clarity
+ }
+ else // equals if (!held_notes)
+ {
+ chord_timer->stop();
- //simply proceed, inserting a rest
- Pos p(song->cpos() + step, true);
- song->setPos(0, p, true, false, true);
- }
- }
+ // simply proceed, inserting a rest
+ Pos p(song->cpos() + step, true);
+ song->setPos(0, p, true, false, true);
+
+ return;
+ }
+ }
+
+ steprec_record_foot:
+ if (!((lasttick > part->lenTick()) && part->hasHiddenNotes())) // allowed?
+ {
+ if (lasttick > part->lenTick()) // we have to expand the part?
+ schedule_resize_all_same_len_clone_parts(part, lasttick, operations);
+
+ song->applyOperationGroup(operations);
+ }
}