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)      {  | 
