void Song::cmdGluePart(Track* track, Part* oPart) { 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. { 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); }
PyObject* modifyPart(PyObject*, PyObject* part) { int id = getPythonPartId(part); Part* opart = NULL; // Verify a part with that id actually exists, then get it TrackList* tracks = song->tracks(); for (ciTrack t = tracks->begin(); t != tracks->end(); ++t) { Track* track = *t; for (ciPart p = track->parts()->begin(); p != track->parts()->end(); p++) { if (p->second->sn() == id) { opart = p->second; break; } } } if (opart == NULL) { printf("Part doesn't exist!\n"); return NULL; } // Remove all note and controller events from current part eventlist std::list< std::pair<const unsigned, Event> > elist; MidiPart* npart = new MidiPart((MidiTrack*) opart->track()); npart->setTick(opart->tick()); npart->setLenTick(opart->lenTick()); npart->setSn(opart->sn()); for (iEvent e = opart->events()->begin(); e != opart->events()->end(); e++) { Event& event = e->second; if (event.type() == Note || event.type() == Controller) continue; npart->events()->add(event); } addPyPartEventsToOOMidiPart(npart, part); //song->startUndo(); song->changePart(opart, npart); //song->endUndo(SC_TRACK_MODIFIED | SC_PART_MODIFIED | SC_PART_INSERTED); // Crash! Probably since the call ends up in Qt GUI thread from this thread QPybridgeEvent* pyevent = new QPybridgeEvent(QPybridgeEvent::SONG_UPDATE, SC_TRACK_MODIFIED | SC_PART_MODIFIED | SC_PART_INSERTED); QApplication::postEvent(song, pyevent); Py_INCREF(Py_None); return Py_None; }
void unchainTrackParts(MidiTrack* 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); } }/*}}}*/
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); } }/*}}}*/
void globalCut(bool onlySelectedTracks) { int lpos = MusEGlobal::song->lpos(); int rpos = MusEGlobal::song->rpos(); if ((lpos - rpos) >= 0) return; Undo operations; TrackList* tracks = MusEGlobal::song->tracks(); for (iTrack it = tracks->begin(); it != tracks->end(); ++it) { Track* track = *it; if (track == 0 || (onlySelectedTracks && !track->selected())) continue; PartList* pl = track->parts(); for (iPart p = pl->begin(); p != pl->end(); ++p) { Part* part = p->second; int t = part->tick(); int l = part->lenTick(); if (t + l <= lpos) continue; if ((t >= lpos) && ((t+l) <= rpos)) { operations.push_back(UndoOp(UndoOp::DeletePart,part)); } else if ((t < lpos) && ((t+l) > lpos) && ((t+l) <= rpos)) { // remove part tail int len = lpos - t; if (part->nextClone()==part) // no clones { // cut Events const EventList& el = part->events(); for (ciEvent ie = el.lower_bound(len); ie != el.end(); ++ie) operations.push_back(UndoOp(UndoOp::DeleteEvent,ie->second, part, false, false)); } operations.push_back(UndoOp(UndoOp::ModifyPartLength, part, part->lenTick(), len, true, true)); } else if ((t < lpos) && ((t+l) > lpos) && ((t+l) > rpos)) { //---------------------- // remove part middle //---------------------- Part* p1; Part* p2; Part* p3; part->splitPart(lpos, p1, p2); delete p2; part->splitPart(rpos, p2, p3); delete p2; p3->setTick(lpos); MusEGlobal::song->informAboutNewParts(part,p1,p3); operations.push_back(UndoOp(UndoOp::DeletePart,part)); operations.push_back(UndoOp(UndoOp::AddPart,p1)); operations.push_back(UndoOp(UndoOp::AddPart,p3)); } else if ((t >= lpos) && (t < rpos) && (t+l) > rpos) { // remove part head Part* p1; Part* p2; part->splitPart(rpos, p1, p2); delete p1; p2->setTick(lpos); MusEGlobal::song->informAboutNewParts(part,p2); operations.push_back(UndoOp(UndoOp::DeletePart,part)); operations.push_back(UndoOp(UndoOp::AddPart,p2)); } else if (t >= rpos) { // move part to the left int nt = part->tick(); operations.push_back(UndoOp(UndoOp::ModifyPartTick,part,part->tick(), nt - (rpos -lpos) )); } } } int diff = lpos - rpos; adjustGlobalLists(operations, lpos, diff); MusEGlobal::song->applyOperationGroup(operations); }