PyObject* createPart(PyObject*, PyObject* args) { const char* trackname; unsigned tick, tickLen; PyObject* part; if (!PyArg_ParseTuple(args, "siiO", &trackname, &tick, &tickLen, &part)) { return NULL; } QString qtrackname(trackname); MidiTrack* track = (MidiTrack*) song->findTrack(trackname); if (track == NULL) return NULL; MidiPart* npart = new MidiPart(track); npart->setTick(tick); npart->setLenTick(tickLen); addPyPartEventsToOOMidiPart(npart, part); song->addPart(npart); QPybridgeEvent* pyevent = new QPybridgeEvent(QPybridgeEvent::SONG_UPDATE, SC_TRACK_MODIFIED); QApplication::postEvent(song, pyevent); Py_INCREF(Py_None); return Py_None; }
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 LOS::processTrack(MidiTrack* track) { EventList* tevents = track->events(); if (tevents->empty()) return; //--------------------------------------------------- // Identify Parts // The MIDI tracks are broken up into parts // A new Part will be located based on track. // Events will be aligned on new track //--------------------------------------------------- PartList* pl = track->parts(); int lastTick = 0; for (iEvent i = tevents->begin(); i != tevents->end(); ++i) { Event event = i->second; int epos = event.tick() + event.lenTick(); if (epos > lastTick) lastTick = epos; } QString partname = track->name(); int len = song->roundUpBar(lastTick + 1); // p3.3.27 if (config.importMidiSplitParts) { int bar2, beat; unsigned tick; sigmap.tickValues(len, &bar2, &beat, &tick); int lastOff = 0; int st = -1; // start tick current part int x1 = 0; // start tick current measure int x2 = 0; // end tick current measure for (int bar = 0; bar < bar2; ++bar, x1 = x2) { ///x2 = sigmap.bar2tick(bar+1, 0, 0); x2 = sigmap.bar2tick(bar + 1, 0, 0); if (lastOff > x2) { // this measure is busy! continue; } iEvent i1 = tevents->lower_bound(x1); iEvent i2 = tevents->lower_bound(x2); if (i1 == i2) { // empty? if (st != -1) { MidiPart* part = new MidiPart(track); part->setTick(st); part->setLenTick(x1 - st); // printf("new part %d len: %d\n", st, x1-st); part->setName(partname); pl->add(part); st = -1; } } else { if (st == -1) st = x1; // begin new part //HACK: //lastOff: for (iEvent i = i1; i != i2; ++i) { Event event = i->second; if (event.type() == Note) { int off = event.tick() + event.lenTick(); if (off > lastOff) lastOff = off; } } } } if (st != -1) { MidiPart* part = new MidiPart(track); part->setTick(st); // printf("new part %d len: %d\n", st, x2-st); part->setLenTick(x2 - st); part->setName(partname); pl->add(part); } } else { // Just one long part... MidiPart* part = new MidiPart(track); //part->setTick(st); part->setTick(0); part->setLenTick(len); part->setName(partname); pl->add(part); } //------------------------------------------------------------- // assign events to parts //------------------------------------------------------------- for (iPart p = pl->begin(); p != pl->end(); ++p) { MidiPart* part = (MidiPart*) (p->second); int stick = part->tick(); int etick = part->tick() + part->lenTick(); iEvent r1 = tevents->lower_bound(stick); iEvent r2 = tevents->lower_bound(etick); int startTick = part->tick(); EventList* el = part->events(); for (iEvent i = r1; i != r2; ++i) { Event ev = i->second; int ntick = ev.tick() - startTick; ev.setTick(ntick); el->add(ev); } tevents->erase(r1, r2); } if (tevents->size()) printf("-----------events left: %zd\n", tevents->size()); for (iEvent i = tevents->begin(); i != tevents->end(); ++i) { printf("%d===\n", i->first); i->second.dump(); } // all events should be processed: assert(tevents->empty()); }