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); MidiTrack* t = p->track(); if (t) { 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]; 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; } } }/*}}}*/
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) { MidiTrack* t = p->track(); if (t) { 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]; 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; } } }/*}}}*/
void chainTrackParts(MidiTrack* 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... { 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; } } // 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); } }/*}}}*/