diff options
Diffstat (limited to 'muse2/muse/part.cpp')
-rw-r--r-- | muse2/muse/part.cpp | 743 |
1 files changed, 169 insertions, 574 deletions
diff --git a/muse2/muse/part.cpp b/muse2/muse/part.cpp index 5f3aa8ee..1d246c50 100644 --- a/muse2/muse/part.cpp +++ b/muse2/muse/part.cpp @@ -22,6 +22,7 @@ // //========================================================= +#include <assert.h> #include <stdio.h> #include <cmath> @@ -39,316 +40,97 @@ namespace MusECore { int Part::snGen=0; -//--------------------------------------------------------- -// unchainClone -//--------------------------------------------------------- -void unchainClone(Part* p) +void Part::unchainClone() { - chainCheckErr(p); + chainCheckErr(this); // FIXME proper assert! - // Unchain the part. - p->prevClone()->setNextClone(p->nextClone()); - p->nextClone()->setPrevClone(p->prevClone()); + if (_backupClone) printf("THIS SHOULD NEVER HAPPEN: Part::unchainClone() called, but _backupClone was non-NULL\n"); - // Isolate the part. - p->setPrevClone(p); - p->setNextClone(p); -} - -//--------------------------------------------------------- -// chainClone -// The quick way - if part to chain to is known... -//--------------------------------------------------------- - -void chainClone(Part* p1, Part* p2) -{ - chainCheckErr(p1); + _backupClone=_prevClone; - // Make sure the part to be chained is unchained first. - p2->prevClone()->setNextClone(p2->nextClone()); - p2->nextClone()->setPrevClone(p2->prevClone()); + // Unchain the part. + _prevClone->_nextClone = _nextClone; + _nextClone->_prevClone = _prevClone; - // Link the part to be chained. - p2->setPrevClone(p1); - p2->setNextClone(p1->nextClone()); + // Isolate the part. + _prevClone = this; + _nextClone = this; - // Re-link the existing part. - p1->nextClone()->setPrevClone(p2); - p1->setNextClone(p2); + _clonemaster_sn = this->_sn; } -//--------------------------------------------------------- -// chainCloneInternal -// No error check, so it can be called by replaceClone() -//--------------------------------------------------------- - -void chainCloneInternal(Part* p) +void Part::chainClone(Part* p) { - Track* t = p->track(); - Part* p1 = 0; + // FIXME assertion + assert(p); - // Look for a part with the same event list, that we can chain to. - // It's faster if track type is known... - - if(!t || (t && t->isMidiTrack())) + if (! (_prevClone==this && _nextClone==this)) // the part is still part of a clone chain! { - MidiTrack* mt = 0; - MidiTrackList* mtl = MusEGlobal::song->midis(); - for(ciMidiTrack imt = mtl->begin(); imt != mtl->end(); ++imt) - { - mt = *imt; - const PartList* pl = mt->cparts(); - for(ciPart ip = pl->begin(); ip != pl->end(); ++ip) - { - if(ip->second != p && ip->second->cevents() == p->cevents()) - { - p1 = ip->second; - break; - } - } - // If a suitable part was found on a different track, we're done. We will chain to it. - // Otherwise keep looking for parts on another track. If no others found, then we - // chain to any suitable part which was found on the same given track t. - if(p1 && mt != t) - break; - } - } - if((!p1 && !t) || (t && t->type() == Track::WAVE)) - { - MusECore::WaveTrack* wt = 0; - MusECore::WaveTrackList* wtl = MusEGlobal::song->waves(); - for(MusECore::ciWaveTrack iwt = wtl->begin(); iwt != wtl->end(); ++iwt) - { - wt = *iwt; - const PartList* pl = wt->cparts(); - for(ciPart ip = pl->begin(); ip != pl->end(); ++ip) - { - if(ip->second != p && ip->second->cevents() == p->cevents()) - { - p1 = ip->second; - break; - } - } - if(p1 && wt != t) - break; - } + printf("ERROR: THIS SHOULD NEVER HAPPEN: Part::chainClone() called, but part is already chained! I'll unchain for now, but better fix that!\n"); + this->unchainClone(); } + + // Make our links to the chain + this->_prevClone = p; + this->_nextClone = p->_nextClone; - // No part found with same event list? Done. - if(!p1) - return; - - // Make sure the part to be chained is unchained first. - p->prevClone()->setNextClone(p->nextClone()); - p->nextClone()->setPrevClone(p->prevClone()); + // Make the chain's links to us + this->_nextClone->_prevClone = this; + p->_nextClone = this; - // Link the part to be chained. - p->setPrevClone(p1); - p->setNextClone(p1->nextClone()); + // we only chain clones. we must trust in the GUI thread that the eventlist is consistent. - // Re-link the existing part. - p1->nextClone()->setPrevClone(p); - p1->setNextClone(p); + this->_clonemaster_sn = p->_sn; } -//--------------------------------------------------------- -// chainClone -// The slow way - if part to chain to is not known... -//--------------------------------------------------------- - -void chainClone(Part* p) +void Part::rechainClone() { - chainCheckErr(p); - chainCloneInternal(p); + if(_backupClone) + { + this->chainClone(_backupClone); + _backupClone = NULL; + } } -//--------------------------------------------------------- -// replaceClone -//--------------------------------------------------------- +bool Part::isCloneOf(const Part* other) const +{ + return this->_clonemaster_sn == other->_clonemaster_sn; +} -// this replaces p1 by p2. p1 is isolated, and p2 takes its place instead. -void replaceClone(Part* p1, Part* p2) +int Part::nClones() const { - chainCheckErr(p1); - - // Make sure the replacement part is unchained first. - p2->prevClone()->setNextClone(p2->nextClone()); - p2->nextClone()->setPrevClone(p2->prevClone()); - - // If the two parts share the same event list, then this MUST - // be a straight forward replacement operation. Continue on. - // If not, and either part has more than one ref count, then do this... - if(p1->cevents() != p2->cevents()) - { - bool ret = false; - // If the part to be replaced is a single uncloned part, [DELETETHIS 4 this seems outdated=wrong to me] - // and the replacement part is not, then this operation - // MUST be an undo of a de-cloning of a cloned part. - //if(p1->cevents()->refCount() <= 1 && p2->cevents()->refCount() > 1) - if(p2->cevents()->refCount() > 1) - { - // Chain the replacement part. We don't know the chain it came from, - // so we use the slow method. - chainCloneInternal(p2); - //return; DELETETHIS - ret = true; - } - - // If the replacement part is a single uncloned part, DELETETHIS same as above - // and the part to be replaced is not, then this operation - // MUST be a de-cloning of a cloned part. - //if(p1->cevents()->refCount() > 1 && p2->cevents()->refCount() <= 1) - if(p1->cevents()->refCount() > 1) - { - // Unchain the part to be replaced. - p1->prevClone()->setNextClone(p1->nextClone()); - p1->nextClone()->setPrevClone(p1->prevClone()); - // Isolate the part. - p1->setPrevClone(p1); - p1->setNextClone(p1); - ret = true; - } - - // Was the operation handled? - if(ret) - return; - // Note that two parts here with different event lists, each with more than one - // reference count, would be an error. It's not done anywhere in muse. But just - // to be sure, four lines above were changed to allow that condition. - // If each of the two different event lists, has only one ref count, we - // handle it like a regular replacement, below... - } - - // If the part to be replaced is a clone not a single lone part, re-link its neighbours to the replacement part... - if(p1->prevClone() != p1) - { - p1->prevClone()->setNextClone(p2); - p2->setPrevClone(p1->prevClone()); - } - else - p2->setPrevClone(p2); - - if(p1->nextClone() != p1) - { - p1->nextClone()->setPrevClone(p2); - p2->setNextClone(p1->nextClone()); - } - else - p2->setNextClone(p2); - - // Isolate the replaced part. - p1->setNextClone(p1); - p1->setPrevClone(p1); + int n=1; + + for(const Part* it = this->_nextClone; it!=this; it=it->_nextClone) + n++; + + return n; } + +// FIXME FINDMICHJETZT TODO: weg damit! + //--------------------------------------------------------- // unchainTrackParts //--------------------------------------------------------- -void unchainTrackParts(Track* t, bool decRefCount) +void unchainTrackParts(Track* t) { PartList* pl = t->parts(); for(iPart ip = pl->begin(); ip != pl->end(); ++ip) - { - Part* p = ip->second; - chainCheckErr(p); - - // Do we want to decrease the reference count? - if(decRefCount) - p->events()->incARef(-1); - - // Unchain the part. - p->prevClone()->setNextClone(p->nextClone()); - p->nextClone()->setPrevClone(p->prevClone()); - - // Isolate the part. - p->setPrevClone(p); - p->setNextClone(p); - } + ip->second->unchainClone(); } //--------------------------------------------------------- // chainTrackParts //--------------------------------------------------------- -void chainTrackParts(Track* t, bool incRefCount) +void chainTrackParts(Track* t) { PartList* pl = t->parts(); - for(iPart ip = pl->begin(); ip != pl->end(); ++ip) - { - Part* p = ip->second; - chainCheckErr(p); - - // Do we want to increase the reference count? - if(incRefCount) - p->events()->incARef(1); - - Part* p1 = 0; - - // Look for a part with the same event list, that we can chain to. - // It's faster if track type is known... - - if(!t || (t && t->isMidiTrack())) - { - MidiTrack* mt = 0; - MidiTrackList* mtl = MusEGlobal::song->midis(); - for(ciMidiTrack imt = mtl->begin(); imt != mtl->end(); ++imt) - { - mt = *imt; - const PartList* pl = mt->cparts(); - for(ciPart ip = pl->begin(); ip != pl->end(); ++ip) - { - if(ip->second != p && ip->second->cevents() == p->cevents()) - { - p1 = ip->second; - break; - } - } - // If a suitable part was found on a different track, we're done. We will chain to it. - // Otherwise keep looking for parts on another track. If no others found, then we - // chain to any suitable part which was found on the same given track t. - if(p1 && mt != t) - break; - } - } - if((!p1 && !t) || (t && t->type() == Track::WAVE)) - { - MusECore::WaveTrack* wt = 0; - MusECore::WaveTrackList* wtl = MusEGlobal::song->waves(); - for(MusECore::ciWaveTrack iwt = wtl->begin(); iwt != wtl->end(); ++iwt) - { - wt = *iwt; - const PartList* pl = wt->cparts(); - for(ciPart ip = pl->begin(); ip != pl->end(); ++ip) - { - if(ip->second != p && ip->second->cevents() == p->cevents()) - { - p1 = ip->second; - break; - } - } - if(p1 && wt != t) - break; - } - } - - // No part found with same event list? Done. - if(!p1) - continue; - - // Make sure the part to be chained is unchained first. - p->prevClone()->setNextClone(p->nextClone()); - p->nextClone()->setPrevClone(p->prevClone()); - - // Link the part to be chained. - p->setPrevClone(p1); - p->setNextClone(p1->nextClone()); - - // Re-link the existing part. - p1->nextClone()->setPrevClone(p); - p1->setNextClone(p); - } + for(riPart ip = pl->rbegin(); ip != pl->rend(); ++ip) // walk through in opposite direction than we unchained them. + ip->second->rechainClone(); } //--------------------------------------------------------- @@ -372,8 +154,6 @@ void addPortCtrlEvents(Event& event, Part* part, bool doClones) { // Traverse and process the clone chain ring until we arrive at the same part again. // The loop is a safety net. - // Update: Due to the varying calls, and order of, incARefcount, (msg)ChangePart, replaceClone, and remove/addPortCtrlEvents, - // we can not rely on the reference count as a safety net in these routines. We will just have to trust the clone chain. Part* p = part; while(1) { @@ -434,8 +214,6 @@ void addPortCtrlEvents(Part* part, bool doClones) { // Traverse and process the clone chain ring until we arrive at the same part again. // The loop is a safety net. - // Update: Due to the varying calls, and order of, incARefcount, (msg)ChangePart, replaceClone, and remove/addPortCtrlEvents, - // we can not rely on the reference count as a safety net in these routines. We will just have to trust the clone chain. Part* p = part; while(1) { @@ -445,9 +223,8 @@ void addPortCtrlEvents(Part* part, bool doClones) MidiTrack* mt = (MidiTrack*)t; MidiPort* mp = &MusEGlobal::midiPorts[mt->outPort()]; int ch = mt->outChannel(); - const EventList* el = p->cevents(); unsigned len = p->lenTick(); - for(ciEvent ie = el->begin(); ie != el->end(); ++ie) + for(ciEvent ie = p->events().begin(); ie != p->events().end(); ++ie) { const Event& ev = ie->second; // Added by T356. Do not add events which are past the end of the part. @@ -499,8 +276,6 @@ void removePortCtrlEvents(Event& event, Part* part, bool doClones) { // Traverse and process the clone chain ring until we arrive at the same part again. // The loop is a safety net. - // Update: Due to the varying calls, and order of, incARefcount, (msg)ChangePart, replaceClone, and remove/addPortCtrlEvents, - // we can not rely on the reference count as a safety net in these routines. We will just have to trust the clone chain. Part* p = part; while(1) { @@ -555,8 +330,6 @@ void removePortCtrlEvents(Part* part, bool doClones) { // Traverse and process the clone chain ring until we arrive at the same part again. // The loop is a safety net. - // Update: Due to the varying calls, and order of, incARefcount, (msg)ChangePart, replaceClone, and remove/addPortCtrlEvents, - // we can not rely on the reference count as a safety net in these routines. We will just have to trust the clone chain. Part* p = part; while(1) { @@ -566,16 +339,9 @@ void removePortCtrlEvents(Part* part, bool doClones) MidiTrack* mt = (MidiTrack*)t; MidiPort* mp = &MusEGlobal::midiPorts[mt->outPort()]; int ch = mt->outChannel(); - const EventList* el = p->cevents(); - //unsigned len = p->lenTick(); - for(ciEvent ie = el->begin(); ie != el->end(); ++ie) + for(ciEvent ie = p->events().begin(); ie != p->events().end(); ++ie) { const Event& ev = ie->second; - // Added by T356. Do not remove events which are past the end of the part. DELETETHIS 5 - // No, actually, do remove ALL of them belonging to the part. - // Just in case there are stray values left after the part end. - //if(ev.tick() >= len) - // break; if(ev.type() == Controller) { @@ -620,17 +386,18 @@ void removePortCtrlEvents(Part* part, bool doClones) iEvent Part::addEvent(Event& p) { - return _events->add(p); + assert(!hasClones()); + return _events.add(p); } //--------------------------------------------------------- // index //--------------------------------------------------------- -int PartList::index(Part* part) +int PartList::index(const Part* part) const { int index = 0; - for (iPart i = begin(); i != end(); ++i, ++index) + for (ciPart i = begin(); i != end(); ++i, ++index) if (i->second == part) { return index; } @@ -652,65 +419,81 @@ Part* PartList::find(int idx) return 0; } -//--------------------------------------------------------- -// Part -//--------------------------------------------------------- - -Part::Part(const Part& p) : PosLen(p) -{ - _sn=p._sn; - _name=p._name; - _selected=p._selected; - _mute=p._mute; - _colorIndex=p._colorIndex; - _hiddenEvents=p._hiddenEvents; - _track=p._track; - _events=p._events; - _prevClone=p._prevClone; - _nextClone=p._nextClone; - - _events->incRef(1); -} - Part::Part(Track* t) { _hiddenEvents = NoEventsHidden; _prevClone = this; _nextClone = this; - setSn(newSn()); + _backupClone = NULL; + _sn = newSn(); + _clonemaster_sn = _sn; _track = t; _selected = false; _mute = false; _colorIndex = 0; - _events = new EventList; - _events->incRef(1); - _events->incARef(1); } -Part::Part(Track* t, EventList* ev) - { - _hiddenEvents = NoEventsHidden; - _prevClone = this; - _nextClone = this; - setSn(newSn()); - _track = t; - _selected = false; - _mute = false; - _colorIndex = 0; - _events = ev; - _events->incRef(1); - _events->incARef(1); - } +WavePart* WavePart::duplicateEmpty() const +{ + WavePart* part = new WavePart((WaveTrack*)this->_track); + part->setName(name()); + part->setColorIndex(colorIndex()); + + *(PosLen*)part = *(PosLen*)this; + part->setMute(mute()); + + return part; +} -//--------------------------------------------------------- -// MidiPart -// copy constructor -//--------------------------------------------------------- +WavePart* WavePart::duplicate() const +{ + return (WavePart*)Part::duplicate(); +} -MidiPart::MidiPart(const MidiPart& p) : Part(p) +WavePart* WavePart::createNewClone() const { - _prevClone = this; - _nextClone = this; + return (WavePart*)Part::createNewClone(); +} + +MidiPart* MidiPart::duplicateEmpty() const +{ + MidiPart* part = new MidiPart((MidiTrack*)this->_track); + part->setName(name()); + part->setColorIndex(colorIndex()); + + *(PosLen*)part = *(PosLen*)this; + part->setMute(mute()); + + return part; +} + +MidiPart* MidiPart::duplicate() const +{ + return (MidiPart*)Part::duplicate(); +} + +MidiPart* MidiPart::createNewClone() const +{ + return (MidiPart*)Part::createNewClone(); +} + + +Part* Part::createNewClone() const +{ + Part* clone = duplicate(); + clone->_backupClone=const_cast<Part*>(this); + return clone; +} + +Part* Part::duplicate() const +{ + Part* dup = duplicateEmpty(); + + // copy the eventlist; duplicate each Event(Ptr!). + for (MusECore::ciEvent i = _events.begin(); i != _events.end(); ++i) + dup->_events.add(i->second.clone()); + + return dup; } @@ -724,42 +507,21 @@ WavePart::WavePart(WaveTrack* t) setType(FRAMES); } -WavePart::WavePart(WaveTrack* t, EventList* ev) - : Part(t, ev) - { - setType(FRAMES); - } - -//--------------------------------------------------------- -// WavePart -// copy constructor -//--------------------------------------------------------- - -WavePart::WavePart(const WavePart& p) : Part(p) -{ - _prevClone = this; - _nextClone = this; -} - //--------------------------------------------------------- // Part //--------------------------------------------------------- Part::~Part() - { +{ if (_prevClone!=this || _nextClone!=this) { if (MusEGlobal::debugMsg) { fprintf(stderr, "Part isn't unchained in ~Part()! Unchaining now...\n"); } - unchainClone(this); - } - - _events->incRef(-1); - if (_events->refCount() <= 0) - delete _events; - } + unchainClone(); + } +} //--------------------------------------------------------- @@ -852,55 +614,24 @@ void Song::cmdResizePart(Track* track, Part* oPart, unsigned int len, bool doClo switch(track->type()) { case Track::WAVE: { - MusECore::WavePart* nPart = new MusECore::WavePart(*(MusECore::WavePart*)oPart); - EventList* el = nPart->events(); - unsigned new_partlength = MusEGlobal::tempomap.deltaTick2frame(oPart->tick(), oPart->tick() + len); - - // If new nr of frames is less than previous what can happen is: - // - 0 or more events are beginning after the new final position. Those are removed from the part - // - The last event begins before new final position and ends after it. If so, it will be resized to end at new part length - if (new_partlength < oPart->lenFrame()) { - Undo operations; - - for (iEvent i = el->begin(); i != el->end(); i++) { - Event e = i->second; - unsigned event_startframe = e.frame(); - unsigned event_endframe = event_startframe + e.lenFrame(); - if (event_endframe < new_partlength) - continue; - } - nPart->setLenFrame(new_partlength); - // Do not do port controller values and clone parts. - operations.push_back(UndoOp(UndoOp::ModifyPart, oPart, nPart, false, false)); - - MusEGlobal::song->applyOperationGroup(operations); - } - // If the part is expanded there can be no additional events beginning after the previous final position - // since those are removed if the part has been shrunk at some time (see above) - // The only thing we need to check is the final event: If it has data after the previous final position, - // we'll expand that event - else { - Undo operations; - if(!el->empty()) - { - iEvent i = el->end(); - i--; - Event last = i->second; - MusECore::SndFileR file = last.sndFile(); - if (file.isNull()) - return; - Event newEvent = last.clone(); - // Do not do port controller values and clone parts. - operations.push_back(UndoOp(UndoOp::ModifyEvent, newEvent, last, nPart, false, false)); - } - - nPart->setLenFrame(new_partlength); - // Do not do port controller values and clone parts. - operations.push_back(UndoOp(UndoOp::ModifyPart, oPart, nPart, false, false)); - MusEGlobal::song->applyOperationGroup(operations); - } - } + Undo operations; + + unsigned orig_len=oPart->lenFrame(); + WavePart* part_it=(WavePart*)oPart; + do + { + if (part_it->lenFrame()==orig_len) + { + // Do port controller values but not clone parts. + operations.push_back(UndoOp(UndoOp::ModifyPartLengthFrames, part_it, part_it->lenFrame(), len, true, false)); + } + + part_it=(WavePart*)part_it->nextClone(); + } while (doClones && (part_it != (WavePart*)oPart)); + + MusEGlobal::song->applyOperationGroup(operations); break; + } case Track::MIDI: case Track::DRUM: case Track::NEW_DRUM: @@ -913,10 +644,8 @@ void Song::cmdResizePart(Track* track, Part* oPart, unsigned int len, bool doClo { if (part_it->lenTick()==orig_len) { - MidiPart* newPart = new MidiPart(*part_it); - newPart->setLenTick(len); // Do port controller values but not clone parts. - operations.push_back(UndoOp(UndoOp::ModifyPart, part_it, newPart, true, false)); + operations.push_back(UndoOp(UndoOp::ModifyPartLength, part_it, part_it->lenTick(), len, true, false)); } part_it=(MidiPart*)part_it->nextClone(); @@ -936,23 +665,23 @@ void Song::cmdResizePart(Track* track, Part* oPart, unsigned int len, bool doClo // create two new parts p1 and p2 //--------------------------------------------------------- -void Track::splitPart(Part* part, int tickpos, Part*& p1, Part*& p2) +void Part::splitPart(int tickpos, Part*& p1, Part*& p2) const { int l1 = 0; // len of first new part (ticks or samples) int l2 = 0; // len of second new part int samplepos = MusEGlobal::tempomap.tick2frame(tickpos); - switch (type()) { - case WAVE: - l1 = samplepos - part->frame(); - l2 = part->lenFrame() - l1; + switch (track()->type()) { + case Track::WAVE: + l1 = samplepos - frame(); + l2 = lenFrame() - l1; break; - case MIDI: - case DRUM: - case NEW_DRUM: - l1 = tickpos - part->tick(); - l2 = part->lenTick() - l1; + case Track::MIDI: + case Track::DRUM: + case Track::NEW_DRUM: + l1 = tickpos - tick(); + l2 = lenTick() - l1; break; default: return; @@ -961,20 +690,18 @@ void Track::splitPart(Part* part, int tickpos, Part*& p1, Part*& p2) if (l1 <= 0 || l2 <= 0) return; - p1 = newPart(part); // new left part - p2 = newPart(part); // new right part + p1 = this->duplicateEmpty(); // new left part + p2 = this->duplicateEmpty(); // new right part - // Added by Tim. p3.3.6 - - switch (type()) { - case WAVE: + switch (track()->type()) { + case Track::WAVE: p1->setLenFrame(l1); p2->setFrame(samplepos); p2->setLenFrame(l2); break; - case MIDI: - case DRUM: - case NEW_DRUM: + case Track::MIDI: + case Track::DRUM: + case Track::NEW_DRUM: p1->setLenTick(l1); p2->setTick(tickpos); p2->setLenTick(l2); @@ -983,158 +710,41 @@ void Track::splitPart(Part* part, int tickpos, Part*& p1, Part*& p2) break; } - p2->setSn(p2->newSn()); - - EventList* se = part->events(); - EventList* de1 = p1->events(); - EventList* de2 = p2->events(); - - if (type() == WAVE) { - int ps = part->frame(); + if (track()->type() == Track::WAVE) { + int ps = this->frame(); int d1p1 = p1->frame(); int d2p1 = p1->endFrame(); int d1p2 = p2->frame(); int d2p2 = p2->endFrame(); - for (iEvent ie = se->begin(); ie != se->end(); ++ie) { - Event event = ie->second; + for (ciEvent ie = _events.begin(); ie != _events.end(); ++ie) { + const Event& event = ie->second; int s1 = event.frame() + ps; int s2 = event.endFrame() + ps; if ((s2 > d1p1) && (s1 < d2p1)) { Event si = event.mid(d1p1 - ps, d2p1 - ps); - de1->add(si); + p1->_events.add(si); } if ((s2 > d1p2) && (s1 < d2p2)) { Event si = event.mid(d1p2 - ps, d2p2 - ps); - de2->add(si); + p2->_events.add(si); } } } else { - for (iEvent ie = se->begin(); ie != se->end(); ++ie) { + for (ciEvent ie = _events.begin(); ie != _events.end(); ++ie) { Event event = ie->second.clone(); int t = event.tick(); if (t >= l1) { event.move(-l1); - de2->add(event); + p2->_events.add(event); } else - de1->add(event); + p1->_events.add(event); } } } -//--------------------------------------------------------- -// cmdSplitPart -//--------------------------------------------------------- - -void Song::cmdSplitPart(Track* track, Part* part, int tick) - { - int l1 = tick - part->tick(); - int l2 = part->lenTick() - l1; - if (l1 <= 0 || l2 <= 0) - return; - Part* p1; - Part* p2; - track->splitPart(part, tick, p1, p2); - - //MusEGlobal::song->informAboutNewParts(part, p1); // is unneccessary because of ChangePart below - MusEGlobal::song->informAboutNewParts(part, p2); - - startUndo(); - // Indicate no undo, and do port controller values but not clone parts. - MusEGlobal::audio->msgChangePart(part, p1, false, true, false); - MusEGlobal::audio->msgAddPart(p2, false); - endUndo(SC_TRACK_MODIFIED | SC_PART_MODIFIED | SC_PART_INSERTED); - } - -//--------------------------------------------------------- -// changePart -//--------------------------------------------------------- - -void Song::changePart(Part* oPart, Part* nPart) - { - nPart->setSn(oPart->sn()); - - Track* oTrack = oPart->track(); - Track* nTrack = nPart->track(); - - oTrack->parts()->remove(oPart); - nTrack->parts()->add(nPart); - - - // Added by T356. - // adjust song len: - unsigned epos = nPart->tick() + nPart->lenTick(); - if (epos > len()) - _len = epos; - - } - -//--------------------------------------------------------- -// cmdGluePart -//--------------------------------------------------------- - -void Song::cmdGluePart(Track* track, Part* oPart) - { - // p3.3.54 - if(track->type() != Track::WAVE && !track->isMidiTrack()) - return; - - PartList* pl = track->parts(); - Part* nextPart = 0; - - for (iPart ip = pl->begin(); ip != pl->end(); ++ip) { - if (ip->second == oPart) { - ++ip; - if (ip == pl->end()) - return; - nextPart = ip->second; - break; - } - } - - Part* nPart = track->newPart(oPart); - nPart->setLenTick(nextPart->tick() + nextPart->lenTick() - oPart->tick()); - - // populate nPart with Events from oPart and nextPart - - EventList* sl1 = oPart->events(); - EventList* dl = nPart->events(); - - for (iEvent ie = sl1->begin(); ie != sl1->end(); ++ie) - dl->add(ie->second); - - EventList* sl2 = nextPart->events(); - - if(track->type() == Track::WAVE) - { - int frameOffset = nextPart->frame() - oPart->frame(); - for (iEvent ie = sl2->begin(); ie != sl2->end(); ++ie) - { - Event event = ie->second.clone(); - event.setFrame(event.frame() + frameOffset); - dl->add(event); - } - } - else - if(track->isMidiTrack()) - { - int tickOffset = nextPart->tick() - oPart->tick(); - for (iEvent ie = sl2->begin(); ie != sl2->end(); ++ie) - { - Event event = ie->second.clone(); - event.setTick(event.tick() + tickOffset); - dl->add(event); - } - } - - startUndo(); - MusEGlobal::audio->msgRemovePart(nextPart, false); - // Indicate no undo, and do port controller values but not clone parts. - MusEGlobal::audio->msgChangePart(oPart, nPart, false, true, false); - endUndo(SC_PART_MODIFIED | SC_PART_REMOVED); - } //--------------------------------------------------------- // dump @@ -1169,21 +779,6 @@ void MidiPart::dump(int n) const } //--------------------------------------------------------- -// clone -//--------------------------------------------------------- - -MidiPart* MidiPart::clone() const - { - return new MidiPart(*this); - } - - -WavePart* WavePart::clone() const - { - return new WavePart(*this); - } - -//--------------------------------------------------------- // hasHiddenEvents // Returns combination of HiddenEventsType enum. //--------------------------------------------------------- @@ -1193,7 +788,7 @@ int MidiPart::hasHiddenEvents() unsigned len = lenTick(); // TODO: For now, we don't support events before the left border, only events past the right border. - for(iEvent ev=events()->begin(); ev!=events()->end(); ev++) + for(ciEvent ev=_events.begin(); ev!=_events.end(); ev++) { if(ev->second.endTick() > len) { @@ -1215,7 +810,7 @@ int WavePart::hasHiddenEvents() unsigned len = lenFrame(); // TODO: For now, we don't support events before the left border, only events past the right border. - for(iEvent ev=events()->begin(); ev!=events()->end(); ev++) + for(ciEvent ev=_events.begin(); ev!=_events.end(); ev++) { if(ev->second.endFrame() > len) { |