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); } }
void chainClone(Part* p)/*{{{*/ { chainCheckErr(p); chainCloneInternal(p); }
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, ); }