Пример #1
0
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);
	}
}
Пример #2
0
void chainClone(Part* p)/*{{{*/
{
    chainCheckErr(p);
    chainCloneInternal(p);
}
Пример #3
0
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 oom. 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, );

}