diff options
author | Florian Jung <flo@windfisch.org> | 2011-05-11 16:41:11 +0000 |
---|---|---|
committer | Florian Jung <flo@windfisch.org> | 2011-05-11 16:41:11 +0000 |
commit | 1c431bd67567104ba9e026ae75ba479f56d387a2 (patch) | |
tree | 953f7f708eefd8fbac23937a987ad2cce667dd19 /muse2/muse/structure.cpp | |
parent | 56b1d339a4176c07d4d995bd8912f1eccddc5539 (diff) | |
parent | 4f2e54561260eb8382953d5723d5d111353a22c9 (diff) |
some housekeeping:
- merged with trunk
- removed note to myself
- some code-cleanups
Diffstat (limited to 'muse2/muse/structure.cpp')
-rw-r--r-- | muse2/muse/structure.cpp | 368 |
1 files changed, 368 insertions, 0 deletions
diff --git a/muse2/muse/structure.cpp b/muse2/muse/structure.cpp new file mode 100644 index 00000000..f0a4308a --- /dev/null +++ b/muse2/muse/structure.cpp @@ -0,0 +1,368 @@ +//========================================================= +// MusE +// Linux Music Editor +// $Id: app.cpp,v 1.113.2.68 2009/12/21 14:51:51 spamatica Exp $ +// +// (C) Copyright 1999-2004 Werner Schweer (ws@seh.de) +// (C) Copyright 2011 Robert Jonsson (rj@spamatica.se) +//========================================================= + +#include <qmessagebox.h> +#include "app.h" +#include "track.h" +#include "song.h" +#include "tempo.h" +#include "al/sig.h" +#include "keyevent.h" +#include "audio.h" +#include "marker/marker.h" + + +//--------------------------------------------------------- +// adjustGlobalLists +// helper that adjusts tempo, sig, key and marker +// lists everything from startPos is adjusted +// 'diff' number of ticks. +// function requires undo to be handled outside +//--------------------------------------------------------- + +void MusE::adjustGlobalLists(int startPos, int diff) +{ + const TempoList* t = &tempomap; + const AL::SigList* s = &AL::sigmap; + const KeyList* k = &keymap; + + criTEvent it = t->rbegin(); + AL::criSigEvent is = s->rbegin(); + criKeyEvent ik = k->rbegin(); + + // key + for (; ik != k->rend(); ik++) { + const KeyEvent &ev = (KeyEvent)ik->second; + int tick = ev.tick; + int key = ev.key; + if (tick < startPos ) + break; + + if (tick > startPos && tick +diff < startPos ) { // remove + audio->msgRemoveKey(tick, key, false); + } + else { + audio->msgRemoveKey(tick, key, false); + audio->msgAddKey(tick+diff, key, false); + } + } + + // tempo + for (; it != t->rend(); it++) { + const TEvent* ev = (TEvent*)it->second; + int tick = ev->tick; + int tempo = ev->tempo; + if (tick < startPos ) + break; + + if (tick > startPos && tick +diff < startPos ) { // remove + audio->msgDeleteTempo(tick, tempo, false); + } + else { + audio->msgDeleteTempo(tick, tempo, false); + audio->msgAddTempo(tick+diff, tempo, false); + } + } + + // sig + for (; is != s->rend(); is++) { + const AL::SigEvent* ev = (AL::SigEvent*)is->second; + int tick = ev->tick; + if (tick < startPos ) + break; + + int z = ev->sig.z; + int n = ev->sig.n; + if (tick > startPos && tick +diff < startPos ) { // remove + audio->msgRemoveSig(tick, z, n, false); + } + else { + audio->msgRemoveSig(tick, z, n, false); + audio->msgAddSig(tick+diff, z, n, false); + } + } + + MarkerList *markerlist = song->marker(); + for(iMarker i = markerlist->begin(); i != markerlist->end(); ++i) + { + Marker* m = &i->second; + int tick = m->tick(); + if (tick > startPos) + { + if (tick + diff < startPos ) { // these ticks should be removed + Marker *oldMarker = new Marker(); + *oldMarker = *m; + markerlist->remove(m); + song->undoOp(UndoOp::ModifyMarker,oldMarker, 0); + } else { + Marker *oldMarker = new Marker(); + *oldMarker = *m; + m->setTick(tick + diff); + song->undoOp(UndoOp::ModifyMarker,oldMarker, m); + } + } + } + +} + +//--------------------------------------------------------- +// globalCut +// - remove area between left and right locator +// - do not touch muted track +// - cut master track +//--------------------------------------------------------- + +void MusE::globalCut() + { + int lpos = song->lpos(); + int rpos = song->rpos(); + if ((lpos - rpos) >= 0) + return; + + song->startUndo(); + TrackList* tracks = song->tracks(); + for (iTrack it = tracks->begin(); it != tracks->end(); ++it) { + MidiTrack* track = dynamic_cast<MidiTrack*>(*it); + if (track == 0 || track->mute()) + continue; + PartList* pl = track->parts(); + for (iPart p = pl->begin(); p != pl->end(); ++p) { + Part* part = p->second; + int t = part->tick(); + int l = part->lenTick(); + if (t + l <= lpos) + continue; + if ((t >= lpos) && ((t+l) <= rpos)) { + audio->msgRemovePart(part, false); + } + else if ((t < lpos) && ((t+l) > lpos) && ((t+l) <= rpos)) { + // remove part tail + int len = lpos - t; + MidiPart* nPart = new MidiPart(*(MidiPart*)part); + nPart->setLenTick(len); + // + // cut Events in nPart + EventList* el = nPart->events(); + iEvent ie = el->lower_bound(t + len); + for (; ie != el->end();) { + iEvent i = ie; + ++ie; + // Indicate no undo, and do not do port controller values and clone parts. + //audio->msgDeleteEvent(i->second, nPart, false); + audio->msgDeleteEvent(i->second, nPart, false, false, false); + } + // Indicate no undo, and do port controller values and clone parts. + //audio->msgChangePart(part, nPart, false); + audio->msgChangePart(part, nPart, false, true, true); + } + else if ((t < lpos) && ((t+l) > lpos) && ((t+l) > rpos)) { + //---------------------- + // remove part middle + //---------------------- + + MidiPart* nPart = new MidiPart(*(MidiPart*)part); + EventList* el = nPart->events(); + iEvent is = el->lower_bound(lpos); + iEvent ie = el->upper_bound(rpos); + for (iEvent i = is; i != ie;) { + iEvent ii = i; + ++i; + // Indicate no undo, and do not do port controller values and clone parts. + //audio->msgDeleteEvent(ii->second, nPart, false); + audio->msgDeleteEvent(ii->second, nPart, false, false, false); + } + + ie = el->lower_bound(rpos); + for (; ie != el->end();) { + iEvent i = ie; + ++ie; + Event event = i->second; + Event nEvent = event.clone(); + nEvent.setTick(nEvent.tick() - (rpos-lpos)); + // Indicate no undo, and do not do port controller values and clone parts. + //audio->msgChangeEvent(event, nEvent, nPart, false); + audio->msgChangeEvent(event, nEvent, nPart, false, false, false); + } + nPart->setLenTick(l - (rpos-lpos)); + // Indicate no undo, and do port controller values and clone parts. + //audio->msgChangePart(part, nPart, false); + audio->msgChangePart(part, nPart, false, true, true); + } + else if ((t >= lpos) && (t < rpos) && (t+l) > rpos) { + // TODO: remove part head + } + else if (t >= rpos) { + MidiPart* nPart = new MidiPart(*(MidiPart*)part); + int nt = part->tick(); + nPart->setTick(nt - (rpos -lpos)); + // Indicate no undo, and do port controller values but not clone parts. + //audio->msgChangePart(part, nPart, false); + audio->msgChangePart(part, nPart, false, true, false); + } + } + } + int diff = lpos - rpos; + adjustGlobalLists(lpos, diff); + + song->endUndo(SC_TRACK_MODIFIED | SC_PART_MODIFIED | SC_PART_REMOVED | SC_TEMPO | SC_KEY | SC_SIG); + } + +//--------------------------------------------------------- +// globalInsert +// - insert empty space at left locator position upto +// right locator +// - do not touch muted track +// - insert in master track +//--------------------------------------------------------- + +void MusE::globalInsert() + { + unsigned lpos = song->lpos(); + unsigned rpos = song->rpos(); + if (lpos >= rpos) + return; + + song->startUndo(); + TrackList* tracks = song->tracks(); + for (iTrack it = tracks->begin(); it != tracks->end(); ++it) { + MidiTrack* track = dynamic_cast<MidiTrack*>(*it); + // + // process only non muted midi tracks + // + if (track == 0 || track->mute()) + continue; + PartList* pl = track->parts(); + for (riPart p = pl->rbegin(); p != pl->rend(); ++p) { + Part* part = p->second; + unsigned t = part->tick(); + int l = part->lenTick(); + if (t + l <= lpos) + continue; + if (lpos >= t && lpos < (t+l)) { + MidiPart* nPart = new MidiPart(*(MidiPart*)part); + nPart->setLenTick(l + (rpos-lpos)); + EventList* el = nPart->events(); + + iEvent i = el->end(); + while (i != el->begin()) { + --i; + if (i->first < lpos) + break; + Event event = i->second; + Event nEvent = i->second.clone(); + nEvent.setTick(nEvent.tick() + (rpos-lpos)); + // Indicate no undo, and do not do port controller values and clone parts. + //audio->msgChangeEvent(event, nEvent, nPart, false); + audio->msgChangeEvent(event, nEvent, nPart, false, false, false); + } + // Indicate no undo, and do port controller values and clone parts. + //audio->msgChangePart(part, nPart, false); + audio->msgChangePart(part, nPart, false, true, true); + } + else if (t > lpos) { + MidiPart* nPart = new MidiPart(*(MidiPart*)part); + nPart->setTick(t + (rpos -lpos)); + // Indicate no undo, and do port controller values but not clone parts. + //audio->msgChangePart(part, nPart, false); + audio->msgChangePart(part, nPart, false, true, false); + } + } + } + + int diff = rpos - lpos; + adjustGlobalLists(lpos, diff); + + song->endUndo(SC_TRACK_MODIFIED | SC_PART_MODIFIED | SC_PART_REMOVED | SC_TEMPO | SC_KEY | SC_SIG ); + } + + +//--------------------------------------------------------- +// globalSplit +// - split all parts at the song position pointer +// - do not touch muted track +//--------------------------------------------------------- + +void MusE::globalSplit() + { + int pos = song->cpos(); + song->startUndo(); + TrackList* tracks = song->tracks(); + for (iTrack it = tracks->begin(); it != tracks->end(); ++it) { + Track* track = *it; + PartList* pl = track->parts(); + for (iPart p = pl->begin(); p != pl->end(); ++p) { + Part* part = p->second; + int p1 = part->tick(); + int l0 = part->lenTick(); + if (pos > p1 && pos < (p1+l0)) { + Part* p1; + Part* p2; + track->splitPart(part, pos, p1, p2); + // Indicate no undo, and do port controller values but not clone parts. + //audio->msgChangePart(part, p1, false); + audio->msgChangePart(part, p1, false, true, false); + audio->msgAddPart(p2, false); + break; + } + } + } + song->endUndo(SC_TRACK_MODIFIED | SC_PART_MODIFIED | SC_PART_INSERTED); + } + +//--------------------------------------------------------- +// copyRange +// - copy space between left and right locator position +// to song position pointer +// - dont process muted tracks +// - create a new part for every track containing the +// copied events +//--------------------------------------------------------- + +void MusE::copyRange() + { + QMessageBox::critical(this, + tr("MusE: Copy Range"), + tr("not implemented") + ); + } + +//--------------------------------------------------------- +// cutEvents +// - make sure that all events in a part end where the +// part ends +// - process only marked parts +//--------------------------------------------------------- + +void MusE::cutEvents() + { + QMessageBox::critical(this, + tr("MusE: Cut Events"), + tr("not implemented") + ); + } + +//--------------------------------------------------------- +// checkRegionNotNull +// return true if (rPos - lPos) <= 0 +//--------------------------------------------------------- + +bool MusE::checkRegionNotNull() + { + int start = song->lPos().frame(); + int end = song->rPos().frame(); + if (end - start <= 0) { + QMessageBox::critical(this, + tr("MusE: Bounce"), + tr("set left/right marker for bounce range") + ); + return true; + } + return false; + } + |