summaryrefslogtreecommitdiff
path: root/attic/muse2-oom/muse2/muse/part.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'attic/muse2-oom/muse2/muse/part.cpp')
-rw-r--r--attic/muse2-oom/muse2/muse/part.cpp1433
1 files changed, 0 insertions, 1433 deletions
diff --git a/attic/muse2-oom/muse2/muse/part.cpp b/attic/muse2-oom/muse2/muse/part.cpp
deleted file mode 100644
index 99f070b2..00000000
--- a/attic/muse2-oom/muse2/muse/part.cpp
+++ /dev/null
@@ -1,1433 +0,0 @@
-//=========================================================
-// MusE
-// Linux Music Editor
-// $Id: part.cpp,v 1.12.2.17 2009/06/25 05:13:02 terminator356 Exp $
-//
-// (C) Copyright 1999/2000 Werner Schweer (ws@seh.de)
-//=========================================================
-
-#include <stdio.h>
-#include <assert.h>
-#include <cmath>
-
-#include "song.h"
-#include "part.h"
-#include "track.h"
-#include "globals.h"
-#include "event.h"
-#include "audio.h"
-#include "wave.h"
-#include "midiport.h"
-#include "drummap.h"
-//#include "midiedit/drummap.h" // p4.0.2
-
-int Part::snGen;
-
-//---------------------------------------------------------
-// unchainClone
-//---------------------------------------------------------
-
-void unchainClone(Part* p)
-{
- chainCheckErr(p);
-
- // Unchain the part.
- p->prevClone()->setNextClone(p->nextClone());
- p->nextClone()->setPrevClone(p->prevClone());
-
- // 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);
-
- // Make sure the part to be chained is unchained first.
- p2->prevClone()->setNextClone(p2->nextClone());
- p2->nextClone()->setPrevClone(p2->prevClone());
-
- // Link the part to be chained.
- p2->setPrevClone(p1);
- p2->setNextClone(p1->nextClone());
-
- // Re-link the existing part.
- p1->nextClone()->setPrevClone(p2);
- p1->setNextClone(p2);
-}
-
-//---------------------------------------------------------
-// chainCloneInternal
-// No error check, so it can be called by replaceClone()
-//---------------------------------------------------------
-
-void chainCloneInternal(Part* p)
-{
- Track* t = p->track();
- 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 = 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)
- {
- // Added by Tim. p3.3.6
- //printf("chainCloneInternal track %p %s part %p %s evlist %p\n", (*imt), (*imt)->name().toLatin1().constData(), ip->second, ip->second->name().toLatin1().constData(), ip->second->cevents());
-
- 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))
- {
- WaveTrack* wt = 0;
- WaveTrackList* wtl = song->waves();
- for(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)
- return;
-
- // 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);
-}
-
-//---------------------------------------------------------
-// chainClone
-// The slow way - if part to chain to is not known...
-//---------------------------------------------------------
-
-void chainClone(Part* p)
-{
- chainCheckErr(p);
- chainCloneInternal(p);
-}
-
-//---------------------------------------------------------
-// replaceClone
-//---------------------------------------------------------
-
-void replaceClone(Part* p1, Part* p2)
-{
- 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,
- // 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;
- ret = true;
- }
-
- // If the replacement part is a single uncloned part,
- // 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);
- //return;
- 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);
-
- // Link the replacement...
- //p2->setPrevClone(p1->prevClone());
- //p2->setNextClone(p1->nextClone());
-
- // Isolate the replaced part.
- p1->setNextClone(p1);
- p1->setPrevClone(p1);
- // Added by Tim. p3.3.6
- //printf("replaceClone p1: %s %p arefs:%d p2: %s %p arefs:%d\n", p1->name().toLatin1().constData(), p1, );
-
-}
-
-//---------------------------------------------------------
-// unchainTrackParts
-//---------------------------------------------------------
-
-void unchainTrackParts(Track* t, bool decRefCount)
-{
- 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);
- }
-}
-
-//---------------------------------------------------------
-// chainTrackParts
-//---------------------------------------------------------
-
-void chainTrackParts(Track* t, bool incRefCount)
-{
- 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);
-
- // Added by Tim. p3.3.6
- //printf("chainTrackParts track %p %s part %p %s evlist %p\n", t, t->name().toLatin1().constData(), p, p->name().toLatin1().constData(), p->cevents());
-
- 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 = 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)
- {
- // Added by Tim. p3.3.6
- //printf("chainTrackParts track %p %s part %p %s evlist %p\n", mt, mt->name().toLatin1().constData(), ip->second, ip->second->name().toLatin1().constData(), ip->second->cevents());
-
- 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))
- {
- WaveTrack* wt = 0;
- WaveTrackList* wtl = song->waves();
- for(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);
- }
-}
-
-//---------------------------------------------------------
-// chainCheckErr
-//---------------------------------------------------------
-
-void chainCheckErr(Part* p)
-{
- // At all times these must be true...
- if(p->nextClone()->prevClone() != p)
- printf("chainCheckErr: Next clone:%s %p prev clone:%s %p != %s %p\n", p->nextClone()->name().toLatin1().constData(), p->nextClone(), p->nextClone()->prevClone()->name().toLatin1().constData(), p->nextClone()->prevClone(), p->name().toLatin1().constData(), p);
- if(p->prevClone()->nextClone() != p)
- printf("chainCheckErr: Prev clone:%s %p next clone:%s %p != %s %p\n", p->prevClone()->name().toLatin1().constData(), p->prevClone(), p->prevClone()->nextClone()->name().toLatin1().constData(), p->prevClone()->nextClone(), p->name().toLatin1().constData(), p);
-}
-
-//---------------------------------------------------------
-// addPortCtrlEvents
-//---------------------------------------------------------
-
-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;
- //int j = doClones ? p->cevents()->arefCount() : 1;
- //if(j > 0)
- {
- //for(int i = 0; i < j; ++i)
- while(1)
- {
- // Added by Tim. p3.3.6
- //printf("addPortCtrlEvents i:%d %s %p events %p refs:%d arefs:%d\n", i, p->name().toLatin1().constData(), p, part->cevents(), part->cevents()->refCount(), j);
-
- Track* t = p->track();
- if(t && t->isMidiTrack())
- {
- MidiTrack* mt = (MidiTrack*)t;
- int port = mt->outPort();
- //const EventList* el = p->cevents();
- unsigned len = p->lenTick();
- //for(ciEvent ie = el->begin(); ie != el->end(); ++ie)
- //{
- //const Event& ev = ie->second;
- // Added by Tim. p3.3.6
- //printf("addPortCtrlEvents %s len:%d end:%d etick:%d\n", p->name().toLatin1().constData(), p->lenTick(), p->endTick(), event.tick());
-
- // Do not add events which are past the end of the part.
- if(event.tick() >= len)
- break;
-
- if(event.type() == Controller)
- {
- int ch = mt->outChannel();
- int tck = event.tick() + p->tick();
- int cntrl = event.dataA();
- int val = event.dataB();
- MidiPort* mp = &midiPorts[port];
-
- // Is it a drum controller event, according to the track port's instrument?
- if(mt->type() == Track::DRUM)
- {
- MidiController* mc = mp->drumController(cntrl);
- if(mc)
- {
- int note = cntrl & 0x7f;
- cntrl &= ~0xff;
- ch = drumMap[note].channel;
- mp = &midiPorts[drumMap[note].port];
- cntrl |= drumMap[note].anote;
- }
- }
-
- mp->setControllerVal(ch, tck, cntrl, val, p);
- }
- //}
- }
-
- if(!doClones)
- break;
- // Get the next clone in the chain ring.
- p = p->nextClone();
- // Same as original part? Finished.
- if(p == part)
- break;
- }
- }
-}
-
-//---------------------------------------------------------
-// addPortCtrlEvents
-//---------------------------------------------------------
-
-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;
- //int j = doClones ? p->cevents()->arefCount() : 1;
- //if(j > 0)
- {
- //for(int i = 0; i < j; ++i)
- while(1)
- {
- // Added by Tim. p3.3.6
- //printf("addPortCtrlEvents i:%d %s %p events %p refs:%d arefs:%d\n", i, p->name().toLatin1().constData(), p, part->cevents(), part->cevents()->refCount(), j);
-
- Track* t = p->track();
- if(t && t->isMidiTrack())
- {
- MidiTrack* mt = (MidiTrack*)t;
- int port = mt->outPort();
- const EventList* el = p->cevents();
- unsigned len = p->lenTick();
- for(ciEvent ie = el->begin(); ie != el->end(); ++ie)
- {
- const Event& ev = ie->second;
- // Added by T356. Do not add events which are past the end of the part.
- if(ev.tick() >= len)
- break;
-
- if(ev.type() == Controller)
- {
- int ch = mt->outChannel();
- int tck = ev.tick() + p->tick();
- int cntrl = ev.dataA();
- int val = ev.dataB();
- MidiPort* mp = &midiPorts[port];
-
- // Is it a drum controller event, according to the track port's instrument?
- if(mt->type() == Track::DRUM)
- {
- MidiController* mc = mp->drumController(cntrl);
- if(mc)
- {
- int note = cntrl & 0x7f;
- cntrl &= ~0xff;
- ch = drumMap[note].channel;
- mp = &midiPorts[drumMap[note].port];
- cntrl |= drumMap[note].anote;
- }
- }
-
- mp->setControllerVal(ch, tck, cntrl, val, p);
- }
- }
- }
- if(!doClones)
- break;
- // Get the next clone in the chain ring.
- p = p->nextClone();
- // Same as original part? Finished.
- if(p == part)
- break;
- }
- }
-}
-
-//---------------------------------------------------------
-// removePortCtrlEvents
-//---------------------------------------------------------
-
-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;
- //int j = doClones ? p->cevents()->arefCount() : 1;
- //if(j > 0)
- {
- //for(int i = 0; i < j; ++i)
- while(1)
- {
- Track* t = p->track();
- if(t && t->isMidiTrack())
- {
- MidiTrack* mt = (MidiTrack*)t;
- int port = mt->outPort();
- //const EventList* el = p->cevents();
- //unsigned len = p->lenTick();
- //for(ciEvent ie = el->begin(); ie != el->end(); ++ie)
- //{
- //const Event& ev = ie->second;
- // Added by T356. Do not remove events which are past the end of the part.
- // 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(event.type() == Controller)
- {
- int ch = mt->outChannel();
- int tck = event.tick() + p->tick();
- int cntrl = event.dataA();
- MidiPort* mp = &midiPorts[port];
-
- // Is it a drum controller event, according to the track port's instrument?
- if(mt->type() == Track::DRUM)
- {
- MidiController* mc = mp->drumController(cntrl);
- if(mc)
- {
- int note = cntrl & 0x7f;
- cntrl &= ~0xff;
- ch = drumMap[note].channel;
- mp = &midiPorts[drumMap[note].port];
- cntrl |= drumMap[note].anote;
- }
- }
-
- mp->deleteController(ch, tck, cntrl, p);
- }
- //}
- }
-
- if(!doClones)
- break;
- // Get the next clone in the chain ring.
- p = p->nextClone();
- // Same as original part? Finished.
- if(p == part)
- break;
- }
- }
-}
-
-//---------------------------------------------------------
-// removePortCtrlEvents
-//---------------------------------------------------------
-
-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;
- //int j = doClones ? p->cevents()->arefCount() : 1;
- //if(j > 0)
- {
- //for(int i = 0; i < j; ++i)
- while(1)
- {
- Track* t = p->track();
- if(t && t->isMidiTrack())
- {
- MidiTrack* mt = (MidiTrack*)t;
- int port = mt->outPort();
- const EventList* el = p->cevents();
- //unsigned len = p->lenTick();
- for(ciEvent ie = el->begin(); ie != el->end(); ++ie)
- {
- const Event& ev = ie->second;
- // Added by T356. Do not remove events which are past the end of the part.
- // 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)
- {
- int ch = mt->outChannel();
- int tck = ev.tick() + p->tick();
- int cntrl = ev.dataA();
- MidiPort* mp = &midiPorts[port];
-
- // Is it a drum controller event, according to the track port's instrument?
- if(mt->type() == Track::DRUM)
- {
- MidiController* mc = mp->drumController(cntrl);
- if(mc)
- {
- int note = cntrl & 0x7f;
- cntrl &= ~0xff;
- ch = drumMap[note].channel;
- mp = &midiPorts[drumMap[note].port];
- cntrl |= drumMap[note].anote;
- }
- }
-
- mp->deleteController(ch, tck, cntrl, p);
- }
- }
- }
-
- if(!doClones)
- break;
- // Get the next clone in the chain ring.
- p = p->nextClone();
- // Same as original part? Finished.
- if(p == part)
- break;
- }
- }
-}
-
-//---------------------------------------------------------
-// addEvent
-//---------------------------------------------------------
-
-iEvent Part::addEvent(Event& p)
- {
- return _events->add(p);
- }
-
-//---------------------------------------------------------
-// index
-//---------------------------------------------------------
-
-int PartList::index(Part* part)
- {
- int index = 0;
- for (iPart i = begin(); i != end(); ++i, ++index)
- if (i->second == part) {
- return index;
- }
- if(debugMsg)
- printf("PartList::index(): not found!\n");
- //return 0;
- return -1;
- }
-
-//---------------------------------------------------------
-// find
-//---------------------------------------------------------
-
-Part* PartList::find(int idx)
- {
- int index = 0;
- for (iPart i = begin(); i != end(); ++i, ++index)
- if (index == idx)
- return i->second;
- return 0;
- }
-
-//---------------------------------------------------------
-// Part
-//---------------------------------------------------------
-
-Part::Part(Track* t)
- {
- _prevClone = this;
- _nextClone = this;
- setSn(newSn());
- _track = t;
- _selected = false;
- _mute = false;
- _colorIndex = 0;
- _events = new EventList;
- _events->incRef(1);
- _events->incARef(1);
- }
-
-//---------------------------------------------------------
-// Part
-//---------------------------------------------------------
-
-Part::Part(Track* t, EventList* ev)
- {
- _prevClone = this;
- _nextClone = this;
- setSn(newSn());
- _track = t;
- _selected = false;
- _mute = false;
- _colorIndex = 0;
- _events = ev;
- _events->incRef(1);
- _events->incARef(1);
- }
-
-//---------------------------------------------------------
-// MidiPart
-// copy constructor
-//---------------------------------------------------------
-
-MidiPart::MidiPart(const MidiPart& p) : Part(p)
-{
- _prevClone = this;
- _nextClone = this;
- //setSn(newSn());
- //_sn = p._sn;
- //_name = p._name;
- //_selected = p._selected;
- //_mute = p._mute;
- //_colorIndex = p._colorIndex;
- //_track = p._track;
- //_events = p._events;
-}
-
-//---------------------------------------------------------
-// WavePart
-//---------------------------------------------------------
-
-WavePart::WavePart(WaveTrack* t)
- : Part(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;
- //setSn(newSn());
- //_sn = p._sn;
- //_name = p._name;
- //_selected = p._selected;
- //_mute = p._mute;
- //_colorIndex = p._colorIndex;
- //_track = p._track;
- //_events = p._events;
-}
-
-//---------------------------------------------------------
-// Part
-//---------------------------------------------------------
-
-Part::~Part()
- {
- _events->incRef(-1);
- if (_events->refCount() <= 0)
- delete _events;
- }
-
-/*
-//---------------------------------------------------------
-// unchainClone
-//---------------------------------------------------------
-
-void Part::unchainClone()
-{
- chainCheckErr();
-
- _prevClone->setNextClone(_nextClone);
- _nextClone->setPrevClone(_prevClone);
-
- _prevClone = this;
- _nextClone = this;
-}
-
-//---------------------------------------------------------
-// chainClone
-// The quick way - if part to chain to is known...
-//---------------------------------------------------------
-
-void Part::chainClone(const Part* p)
-{
- chainCheckErr();
-
- // Make sure the part is unchained first.
- p->prevClone()->setNextClone(p->nextClone());
- p->nextClone()->setPrevClone(p->prevClone());
-
- p->setPrevClone(this);
- p->setNextClone(_nextClone->prevClone());
-
- _nextClone->setPrevClone(p);
- _nextClone = (Part*)p;
-}
-
-//---------------------------------------------------------
-// chainClone
-// The slow way - if part to chain to is not known...
-//---------------------------------------------------------
-
-void Part::chainClone()
-{
- chainCheckErr();
-
- // Look for a part with the same event list, that we can chain to...
- Part* p = 0;
- if(!_track || (_track && _track->isMidiTrack()))
- {
- MidiTrackList* mtl = song->midis();
- for(ciMidiTrack imt = mtl->begin(); imt != mtl->end(); ++imt)
- {
- const PartList* pl = (*imt)->cparts();
- for(ciPart ip = pl->begin(); ip != pl->end(); ++ip)
- {
- if(ip->second != this && ip->second->events() == _events)
- {
- p = ip->second;
- break;
- }
- }
- }
- }
-
- if((!p && !_track) || (_track && _track->type() == Track::WAVE))
- {
- WaveTrackList* wtl = song->waves();
- for(ciWaveTrack iwt = wtl->begin(); iwt != wtl->end(); ++iwt)
- {
- const PartList* pl = (*iwt)->cparts();
- for(ciPart ip = pl->begin(); ip != pl->end(); ++ip)
- {
- if(ip->second != this && ip->second->events() == _events)
- {
- p = ip->second;
- break;
- }
- }
- }
- }
-
- // No part found with same event list? Done.
- if(!p)
- return;
-
- // Make sure this part is unchained first.
- _prevClone->setNextClone(_nextClone);
- _nextClone->setPrevClone(_prevClone);
-
- _prevClone = p;
- _nextClone = p->nextClone();
-
- p->nextClone()->setPrevClone(this);
- p->setNextClone(this);
-}
-
-//---------------------------------------------------------
-// replaceClone
-//---------------------------------------------------------
-
-void Part::replaceClone(const Part* p)
-{
- chainCheckErr();
-
- // Make sure the part is unchained first.
- p->prevClone()->setNextClone(p->nextClone());
- p->nextClone()->setPrevClone(p->prevClone());
-
- // If this part is a clone, not a single lone part...
- if(_prevClone != this)
- _prevClone->setNextClone(p);
- if(_nextClone != this)
- _nextClone->setPrevClone(p);
-
- p->setPrevClone(_prevClone);
- p->setNextClone(_nextClone);
-
- _nextClone = this;
- _prevClone = this;
-}
-
-//---------------------------------------------------------
-// chainCheckErr
-//---------------------------------------------------------
-
-void Part::chainCheckErr()
-{
- if(_nextClone->prevClone() != this)
- printf("Part::chainCheckErr Error! Next clone:%s %x prev clone:%s %x != this:%s %x\n", _nextClone->name().toLatin1().constData(), _nextClone, _nextClone->prevClone()->name().toLatin1().constData(), _nextClone->prevClone(), name().toLatin1().constData(), this);
- if(_prevClone->nextClone() != this)
- printf("Part::chainCheckErr Error! Prev clone:%s %x next clone:%s %x != this:%s %x\n", _prevClone->name().toLatin1().constData(), _prevClone, _prevClone->nextClone()->name().toLatin1().constData(), _prevClone->nextClone(), name().toLatin1().constData(), this);
-}
-*/
-
-//---------------------------------------------------------
-// findPart
-//---------------------------------------------------------
-
-iPart PartList::findPart(unsigned tick)
- {
- iPart i;
- for (i = begin(); i != end(); ++i)
- if (i->second->tick() == tick)
- break;
- return i;
- }
-
-//---------------------------------------------------------
-// add
-//---------------------------------------------------------
-
-iPart PartList::add(Part* part)
- {
- // Added by T356. A part list containing wave parts should be sorted by
- // frames. WaveTrack::fetchData() relies on the sorting order, and
- // there was a bug that waveparts were sometimes muted because of
- // incorrect sorting order (by ticks).
- // Also, when the tempo map is changed, every wavepart would have to be
- // re-added to the part list so that the proper sorting order (by ticks)
- // could be achieved.
- // Note that in a med file, the tempo list is loaded AFTER all the tracks.
- // There was a bug that all the wave parts' tick values were not correct,
- // since they were computed BEFORE the tempo map was loaded.
- if(part->type() == Pos::FRAMES)
- return insert(std::pair<const int, Part*> (part->frame(), part));
- else
- return insert(std::pair<const int, Part*> (part->tick(), part));
- }
-
-//---------------------------------------------------------
-// remove
-//---------------------------------------------------------
-
-void PartList::remove(Part* part)
- {
- iPart i;
- for (i = begin(); i != end(); ++i) {
- if (i->second == part) {
- erase(i);
- break;
- }
- }
- assert(i != end());
- }
-
-//---------------------------------------------------------
-// addPart
-//---------------------------------------------------------
-
-void Song::addPart(Part* part)
- {
- // adjust song len:
- unsigned epos = part->tick() + part->lenTick();
-
- if (epos > len())
- _len = epos;
- part->track()->addPart(part);
-
- //part->addPortCtrlEvents();
- // Indicate do not do clones.
- addPortCtrlEvents(part, false);
- }
-
-//---------------------------------------------------------
-// removePart
-//---------------------------------------------------------
-
-void Song::removePart(Part* part)
- {
- //part->removePortCtrlEvents();
- // Indicate do not do clones.
- //removePortCtrlEvents(part);
- removePortCtrlEvents(part, false);
- Track* track = part->track();
- track->parts()->remove(part);
- }
-
-//---------------------------------------------------------
-// cmdResizePart
-//---------------------------------------------------------
-
-void Song::cmdResizePart(Track* track, Part* oPart, unsigned int len)
- {
- switch(track->type()) {
- case Track::WAVE:
- {
- WavePart* nPart = new WavePart(*(WavePart*)oPart);
- EventList* el = nPart->events();
- unsigned new_partlength = tempomap.deltaTick2frame(oPart->tick(), oPart->tick() + len);
- //printf("new partlength in frames: %d\n", new_partlength);
-
- // 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()) {
- startUndo();
-
- 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();
- //printf("Event frame=%d, length=%d\n", event_startframe, event_length);
- if (event_endframe < new_partlength)
- continue;
- if (event_startframe > new_partlength) { // If event start was after the new length, remove it from part
- // Indicate no undo, and do not do port controller values and clone parts.
- //audio->msgDeleteEvent(e, nPart, false);
- audio->msgDeleteEvent(e, nPart, false, false, false);
- continue;
- }
- if (event_endframe > new_partlength) { // If this event starts before new length and ends after, shrink it
- Event newEvent = e.clone();
- newEvent.setLenFrame(new_partlength - event_startframe);
- // Indicate no undo, and do not do port controller values and clone parts.
- //audio->msgChangeEvent(e, newEvent, nPart, false);
- audio->msgChangeEvent(e, newEvent, nPart, false, false, false);
- }
- }
- nPart->setLenFrame(new_partlength);
- // Indicate no undo, and do not do port controller values and clone parts.
- //audio->msgChangePart(oPart, nPart, false);
- audio->msgChangePart(oPart, nPart, false, false, false);
-
- endUndo(SC_PART_MODIFIED);
- }
- // 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 {
- if(!el->empty())
- {
- iEvent i = el->end();
- i--;
- Event last = i->second;
- unsigned last_start = last.frame();
- SndFileR file = last.sndFile();
- if (file.isNull())
- return;
-
- unsigned clipframes = (file.samples() - last.spos());// / file.channels();
- Event newEvent = last.clone();
- //printf("SndFileR samples=%d channels=%d event samplepos=%d clipframes=%d\n", file.samples(), file.channels(), last.spos(), clipframes);
-
- unsigned new_eventlength = new_partlength - last_start;
- if (new_eventlength > clipframes) // Shrink event length if new partlength exceeds last clip
- new_eventlength = clipframes;
-
- newEvent.setLenFrame(new_eventlength);
- startUndo();
- // Indicate no undo, and do not do port controller values and clone parts.
- //audio->msgChangeEvent(last, newEvent, nPart, false);
- audio->msgChangeEvent(last, newEvent, nPart, false, false, false);
- }
- else
- {
- startUndo();
- }
-
- nPart->setLenFrame(new_partlength);
- // Indicate no undo, and do not do port controller values and clone parts.
- //audio->msgChangePart(oPart, nPart, false);
- audio->msgChangePart(oPart, nPart, false, false, false);
- endUndo(SC_PART_MODIFIED);
- }
- }
- break;
- case Track::MIDI:
- case Track::DRUM:
- {
- startUndo();
-
- MidiPart* nPart = new MidiPart(*(MidiPart*)oPart);
- nPart->setLenTick(len);
- // Indicate no undo, and do port controller values but not clone parts.
- audio->msgChangePart(oPart, nPart, false, true, false);
-
- // cut Events in nPart
- // Changed by T356. Don't delete events if this is a clone part.
- // The other clones might be longer than this one and need these events.
- if(nPart->cevents()->arefCount() <= 1)
- {
- if(oPart->lenTick() > len) {
- EventList* el = nPart->events();
- iEvent ie = el->lower_bound(len);
- for (; ie != el->end();) {
- iEvent i = ie;
- ++ie;
- // Indicate no undo, and do port controller values and clone parts.
- audio->msgDeleteEvent(i->second, nPart, false, true, true);
- }
- }
- }
-
- /*
- // cut Events in nPart
- // Changed by T356. Don't delete events if this is a clone part.
- // The other clones might be longer than this one and need these events.
- if(oPart->cevents()->arefCount() <= 1)
- {
- if (oPart->lenTick() > len) {
- EventList* el = nPart->events();
- iEvent ie = el->lower_bound(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 but not clone parts.
- //audio->msgChangePart(oPart, nPart, false);
- audio->msgChangePart(oPart, nPart, false, true, false);
- */
-
- endUndo(SC_PART_MODIFIED);
- break;
- }
- default:
- break;
- }
- }
-
-//---------------------------------------------------------
-// splitPart
-// split part "part" at "tick" position
-// create two new parts p1 and p2
-//---------------------------------------------------------
-
-void Track::splitPart(Part* part, int tickpos, Part*& p1, Part*& p2)
- {
- int l1 = 0; // len of first new part (ticks or samples)
- int l2 = 0; // len of second new part
-
- int samplepos = tempomap.tick2frame(tickpos);
-
- switch (type()) {
- case WAVE:
- l1 = samplepos - part->frame();
- l2 = part->lenFrame() - l1;
- break;
- case MIDI:
- case DRUM:
- l1 = tickpos - part->tick();
- l2 = part->lenTick() - l1;
- break;
- default:
- return;
- }
-
- if (l1 <= 0 || l2 <= 0)
- return;
-
- p1 = newPart(part); // new left part
- p2 = newPart(part); // new right part
-
- // Added by Tim. p3.3.6
- //printf("Track::splitPart part ev %p sz:%d ref:%d p1 %p sz:%d ref:%d p2 %p sz:%d ref:%d\n", part->events(), part->events()->size(), part->events()->arefCount(), p1->events(), p1->events()->size(), p1->events()->arefCount(), p2->events(), p2->events()->size(), p2->events()->arefCount());
-
- switch (type()) {
- case WAVE:
- p1->setLenFrame(l1);
- p2->setFrame(samplepos);
- p2->setLenFrame(l2);
- break;
- case MIDI:
- case DRUM:
- p1->setLenTick(l1);
- p2->setTick(tickpos);
- p2->setLenTick(l2);
- break;
- default:
- break;
- }
-
- p2->setSn(p2->newSn());
-
- EventList* se = part->events();
- EventList* de1 = p1->events();
- EventList* de2 = p2->events();
-
- if (type() == WAVE) {
- int ps = part->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;
- 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);
- }
- if ((s2 > d1p2) && (s1 < d2p2)) {
- Event si = event.mid(d1p2 - ps, d2p2 - ps);
- de2->add(si);
- }
- }
- }
- else {
- for (iEvent ie = se->begin(); ie != se->end(); ++ie) {
- Event event = ie->second.clone();
- int t = event.tick();
- if (t >= l1) {
- event.move(-l1);
- de2->add(event);
- }
- else
- de1->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);
-
- startUndo();
- // 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);
- 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();
-
- // Added by Tim. p3.3.6
- //printf("Song::changePart before oPart->removePortCtrlEvents oldPart refs:%d Arefs:%d newPart refs:%d Arefs:%d\n", oPart->events()->refCount(), oPart->events()->arefCount(), nPart->events()->refCount(), nPart->events()->arefCount());
-
- // Removed. Port controller events will have to be add/removed separately from this routine.
- //oPart->removePortCtrlEvents();
- //removePortCtrlEvents(oPart);
-
- // Added by Tim. p3.3.6
- //printf("Song::changePart after oPart->removePortCtrlEvents oldPart refs:%d Arefs:%d newPart refs:%d Arefs:%d\n", oPart->events()->refCount(), oPart->events()->arefCount(), nPart->events()->refCount(), nPart->events()->arefCount());
-
- oTrack->parts()->remove(oPart);
- nTrack->parts()->add(nPart);
-
- // Added by Tim. p3.3.6
- //printf("Song::changePart after add(nPart) oldPart refs:%d Arefs:%d newPart refs:%d Arefs:%d\n", oPart->events()->refCount(), oPart->events()->arefCount(), nPart->events()->refCount(), nPart->events()->arefCount());
-
- //nPart->addPortCtrlEvents();
- //addPortCtrlEvents(nPart);
-
- // Added by Tim. p3.3.6
- //printf("Song::changePart after nPart->addPortCtrlEvents() oldPart refs:%d Arefs:%d newPart refs:%d Arefs:%d\n", oPart->events()->refCount(), oPart->events()->arefCount(), nPart->events()->refCount(), nPart->events()->arefCount());
-
- // Added by T356.
- // adjust song len:
- unsigned epos = nPart->tick() + nPart->lenTick();
- if (epos > len())
- _len = epos;
-
- // Added by Tim. p3.3.6
- //printf("Song::changePart after len adjust oldPart refs:%d Arefs:%d newPart refs:%d Arefs:%d\n", oPart->events()->refCount(), oPart->events()->arefCount(), nPart->events()->refCount(), nPart->events()->arefCount());
-
- }
-
-//---------------------------------------------------------
-// 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();
-
- //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);
- // }
- // p3.3.54 Changed.
- 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();
- audio->msgRemovePart(nextPart, false);
- // Indicate no undo, and do port controller values but not clone parts.
- //audio->msgChangePart(oPart, nPart, false);
- audio->msgChangePart(oPart, nPart, false, true, false);
- endUndo(SC_PART_MODIFIED | SC_PART_REMOVED);
- }
-
-//---------------------------------------------------------
-// dump
-//---------------------------------------------------------
-
-void Part::dump(int n) const
- {
- for (int i = 0; i < n; ++i)
- putchar(' ');
- printf("Part: <%s> ", _name.toLatin1().constData());
- for (int i = 0; i < n; ++i)
- putchar(' ');
- PosLen::dump();
- }
-
-void WavePart::dump(int n) const
- {
- Part::dump(n);
- for (int i = 0; i < n; ++i)
- putchar(' ');
- printf("WavePart\n");
- }
-
-void MidiPart::dump(int n) const
- {
- Part::dump(n);
- for (int i = 0; i < n; ++i)
- putchar(' ');
- printf("MidiPart\n");
- }
-
-//---------------------------------------------------------
-// clone
-//---------------------------------------------------------
-
-MidiPart* MidiPart::clone() const
- {
- return new MidiPart(*this);
- }
-
-WavePart* WavePart::clone() const
- {
- return new WavePart(*this);
- }
-