Пример #1
0
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;
}
Пример #2
0
void Song::cmdResizePart(Track* track, Part* oPart, unsigned int len)/*{{{*/
{
        {
            startUndo();

            MidiPart* nPart = new MidiPart(*(MidiPart*) oPart);
            nPart->setLenTick(len);
            // Indicate no undo, and do port controller values but not clone parts.
            audio->msgChangePart(oPart, nPart, false, true, false);

            // cut Events in nPart
            // Changed by T356. Don't delete events if this is a clone part.
            // The other clones might be longer than this one and need these events.
            if (nPart->cevents()->arefCount() <= 1)
            {
                if (oPart->lenTick() > len)
                {
                    EventList* el = nPart->events();
                    iEvent ie = el->lower_bound(len);
                    for (; ie != el->end();)
                    {
                        iEvent i = ie;
                        ++ie;
                        // Indicate no undo, and do port controller values and clone parts.
                        audio->msgDeleteEvent(i->second, nPart, false, true, true);
                    }
                }
            }

            /*
            // cut Events in nPart
            // Changed by T356. Don't delete events if this is a clone part.
            // The other clones might be longer than this one and need these events.
            if(oPart->cevents()->arefCount() <= 1)
            {
              if (oPart->lenTick() > len) {
                    EventList* el = nPart->events();
                    iEvent ie = el->lower_bound(len);
                    for (; ie != el->end();) {
                          iEvent i = ie;
                          ++ie;
                          // Indicate no undo, and do not do port controller values and clone parts.
                          //audio->msgDeleteEvent(i->second, nPart, false);
                          audio->msgDeleteEvent(i->second, nPart, false, false, 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);
        }
}/*}}}*/
Пример #3
0
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;
}
Пример #4
0
 virtual bool operator<(const QTreeWidgetItem & other) const
 {
     int col = other.treeWidget()->sortColumn();
     EventListItem* eli = (EventListItem*) & other;
     switch (col)
     {
         case 0:
             return event.tick() < eli->event.tick();
             break;
         case 1:
             return part->tick() + event.tick() < (eli->part->tick() + eli->event.tick());
             break;
         case 2:
             return text(col).localeAwareCompare(other.text(col)) < 0;
             break;
         case 3:
             return part->track()->outChannel() < eli->part->track()->outChannel();
             break;
         case 4:
             return event.dataA() < eli->event.dataA();
             break;
         case 5:
             return event.dataB() < eli->event.dataB();
             break;
         case 6:
             return event.dataC() < eli->event.dataC();
             break;
         case 7:
             return event.lenTick() < eli->event.lenTick();
             break;
         case 8:
             return text(col).localeAwareCompare(other.text(col)) < 0;
             break;
         default:
             break;
     }
     return 0;
 }
Пример #5
0
void EventCanvas::songChanged(int flags)/*{{{*/
{
    // Is it simply a midi controller value adjustment? Forget it.
    if (flags == SC_MIDI_CONTROLLER)
        return;

    if (flags & ~SC_SELECTION)
    {
        _items.clear();
        start_tick = MAXINT;
        end_tick = 0;
    _curPart = 0;

        for (iPart p = editor->parts()->begin(); p != editor->parts()->end(); ++p)
        {
            MidiPart* part = (MidiPart*) (p->second);
        if (part->sn() == _curPartId)
        _curPart = part;
            unsigned stick = part->tick();
            unsigned len = part->lenTick();
            unsigned etick = stick + len;
            if (stick < start_tick)
                start_tick = stick;
            if (etick > end_tick)
                end_tick = etick;

            EventList* el = part->events();
            for (iEvent i = el->begin(); i != el->end(); ++i)
            {
                Event e = i->second;
                if (e.isNote())
                {
                    addItem(part, e);
                }
            }
        }
    }

    Event event;
    MidiPart* part = 0;
    int x = 0;
    CItem* nevent = 0;

    int n = 0; // count selections
    for (iCItem k = _items.begin(); k != _items.end(); ++k)
    {
        Event ev = k->second->event();
        bool selected = ev.selected();
        if (selected)
        {
            k->second->setSelected(true);
            ++n;
            if (!nevent)
            {
                nevent = k->second;
                Event mi = nevent->event();
                curVelo = mi.velo();
            }
        }
    }
    start_tick = song->roundDownBar(start_tick);
    end_tick = song->roundUpBar(end_tick);

    if (n == 1)
    {
        x = nevent->x();
        event = nevent->event();
        part = (MidiPart*) nevent->part();
    if (_curPart != part)
        {
        _curPart = part;
        _curPartId = _curPart->sn();
            curPartChanged();
        }
    }
    emit selectionChanged(x, event, part);
    if (_curPart == 0)
    {
        _curPart = (MidiPart*) (editor->parts()->begin()->second);
        if(_curPart)
        {
            editor->setCurCanvasPart(_curPart);
        }
    }

    updateCItemsZValues();

    redraw();
}/*}}}*/
Пример #6
0
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());
}
Пример #7
0
void Audio::collectEvents(MidiTrack* track, unsigned int cts, unsigned int nts)
{
	int port = track->outPort();
	int channel = track->outChannel();
	int defaultPort = port;

	MidiDevice* md = midiPorts[port].device();
	MPEventList* playEvents = md->playEvents();
	MPEventList* stuckNotes = md->stuckNotes();

	PartList* pl = track->parts();
	for (iPart p = pl->begin(); p != pl->end(); ++p)
	{
		MidiPart* part = (MidiPart*) (p->second);
		// dont play muted parts
		if (part->mute())
			continue;
		EventList* events = part->events();
		unsigned partTick = part->tick();
		unsigned partLen = part->lenTick();
		int delay = track->delay;

		if (cts > nts)
		{
			printf("processMidi: FATAL: cur > next %d > %d\n",
					cts, nts);
			return;
		}
		unsigned offset = delay + partTick;
		if (offset > nts)
			continue;
		unsigned stick = (offset > cts) ? 0 : cts - offset;
		unsigned etick = nts - offset;
		// By T356. Do not play events which are past the end of this part.
		if (etick > partLen)
			continue;

		iEvent ie = events->lower_bound(stick);
		iEvent iend = events->lower_bound(etick);

		for (; ie != iend; ++ie)
		{
			Event ev = ie->second;
			port = defaultPort; //Reset each loop
			//
			//  dont play any meta events
			//
			if (ev.type() == Meta)
				continue;
			if (track->type() == Track::DRUM)
			{
				int instr = ev.pitch();
				// ignore muted drums
				if (ev.isNote() && drumMap[instr].mute)
					continue;
			}
			unsigned tick = ev.tick() + offset;
			unsigned frame = tempomap.tick2frame(tick) + frameOffset;
			switch (ev.type())
			{
				case Note:
				{
					int len = ev.lenTick();
					int pitch = ev.pitch();
					int velo = ev.velo();
					if (track->type() == Track::DRUM)
					{
						//
						// Map drum-notes to the drum-map values
						//
						int instr = ev.pitch();
						pitch = drumMap[instr].anote;
						port = drumMap[instr].port; //This changes to non-default port
						channel = drumMap[instr].channel;
						velo = int(double(velo) * (double(drumMap[instr].vol) / 100.0));
					}
					else
					{
						//
						// transpose non drum notes
						//
						pitch += (track->transposition + song->globalPitchShift());
					}

					if (pitch > 127)
						pitch = 127;
					if (pitch < 0)
						pitch = 0;
					velo += track->velocity;
					velo = (velo * track->compression) / 100;
					if (velo > 127)
						velo = 127;
					if (velo < 1) // no off event
						velo = 1;
					len = (len * track->len) / 100;
					if (len <= 0) // dont allow zero length
						len = 1;
					int veloOff = ev.veloOff();

					if (port == defaultPort)
					{
						//printf("Adding event normally: frame=%d port=%d channel=%d pitch=%d velo=%d\n",frame, port, channel, pitch, velo);

						// p3.3.25
						// If syncing to external midi sync, we cannot use the tempo map.
						// Therefore we cannot get sub-tick resolution. Just use ticks instead of frames.
						if (extSyncFlag.value())
							playEvents->add(MidiPlayEvent(tick, port, channel, 0x90, pitch, velo));
						else

							playEvents->add(MidiPlayEvent(frame, port, channel, 0x90, pitch, velo));

						stuckNotes->add(MidiPlayEvent(tick + len, port, channel,
								veloOff ? 0x80 : 0x90, pitch, veloOff));
					}
					else
					{ //Handle events to different port than standard.
						MidiDevice* mdAlt = midiPorts[port].device();
						if (mdAlt)
						{

							// p3.3.25
							if (extSyncFlag.value())
								mdAlt->playEvents()->add(MidiPlayEvent(tick, port, channel, 0x90, pitch, velo));
							else

								mdAlt->playEvents()->add(MidiPlayEvent(frame, port, channel, 0x90, pitch, velo));

							mdAlt->stuckNotes()->add(MidiPlayEvent(tick + len, port, channel,
									veloOff ? 0x80 : 0x90, pitch, veloOff));
						}
					}

					if (velo > track->activity())
						track->setActivity(velo);
				}
					break;

					// Added by T356.
				case Controller:
				{
					//int len   = ev.lenTick();
					//int pitch = ev.pitch();
					if (track->type() == Track::DRUM)
					{
						int ctl = ev.dataA();
						// Is it a drum controller event, according to the track port's instrument?
						MidiController *mc = midiPorts[defaultPort].drumController(ctl);
						if (mc)
						{
							int instr = ctl & 0x7f;
							ctl &= ~0xff;
							int pitch = drumMap[instr].anote & 0x7f;
							port = drumMap[instr].port; //This changes to non-default port
							channel = drumMap[instr].channel;
							MidiDevice* mdAlt = midiPorts[port].device();
							if (mdAlt)
							{
								// p3.3.25
								// If syncing to external midi sync, we cannot use the tempo map.
								// Therefore we cannot get sub-tick resolution. Just use ticks instead of frames.
								if (extSyncFlag.value())
									mdAlt->playEvents()->add(MidiPlayEvent(tick, port, channel,
										ME_CONTROLLER, ctl | pitch, ev.dataB()));
								else

									//playEvents->add(MidiPlayEvent(frame, port, channel, ev));
									mdAlt->playEvents()->add(MidiPlayEvent(frame, port, channel,
										ME_CONTROLLER, ctl | pitch, ev.dataB()));

							}
							break;
						}
					}
					// p3.3.25
					if (extSyncFlag.value())
						playEvents->add(MidiPlayEvent(tick, port, channel, ev));
					else

						playEvents->add(MidiPlayEvent(frame, port, channel, ev));
				}
					break;


				default:
					// p3.3.25
					if (extSyncFlag.value())
						playEvents->add(MidiPlayEvent(tick, port, channel, ev));
					else

						playEvents->add(MidiPlayEvent(frame, port, channel, ev));

					break;
			}
		}
	}
}
Пример #8
0
void Audio::preloadControllers()/*{{{*/
{
	midiBusy = true;

	MidiTrackList* tracks = song->midis();
	for (iMidiTrack it = tracks->begin(); it != tracks->end(); ++it)
	{
		MidiTrack* track = *it;
		//activePorts[track->outPort()] = true;
		QList<ProcessList*> pcevents;

		int port = track->outPort();
		int channel = track->outChannel();
		int defaultPort = port;

		MidiDevice* md = midiPorts[port].device();
		if (!md)
		{
			continue;
		}
		MPEventList* playEvents = md->playEvents();
		playEvents->erase(playEvents->begin(), playEvents->end());

		PartList* pl = track->parts();
		for (iPart p = pl->begin(); p != pl->end(); ++p)
		{
			MidiPart* part = (MidiPart*) (p->second);
			EventList* events = part->events();
			unsigned partTick = part->tick();
			//unsigned partLen = part->lenTick();
			int delay = track->delay;

			unsigned offset = delay + partTick;

			for (iEvent ie = events->begin(); ie != events->end(); ++ie)
			{
				Event ev = ie->second;
				port = defaultPort;
				unsigned tick = ev.tick() + offset;
				//unsigned frame = tempomap.tick2frame(tick) + frameOffset;
				switch (ev.dataA())
				{
					case CTRL_PROGRAM:
					{
						ProcessList *pl = new ProcessList;
						pl->port = port;
						pl->channel = channel;
						pl->dataB = ev.dataB();
						bool addEvent = true;
						for(int i = 0; i < pcevents.size(); ++i)
						{
							ProcessList* ipl = pcevents.at(i);
							if(ipl->port == pl->port && ipl->channel == pl->channel && ipl->dataB == pl->dataB)
							{
								addEvent = false;
								break;
							}
						}
						if(addEvent)
						{
							printf("Audio::preloadControllers() Loading event @ tick: %d - on channel: %d - on port: %d - dataA: %d - dataB: %d\n",
								tick, channel, port, ev.dataA(), ev.dataB());
							pcevents.append(pl);
							playEvents->add(MidiPlayEvent(tick, port, channel, ev));
						}
					}
						break;
					default:
						break;
				}
			}
		}
		md->setNextPlayEvent(playEvents->begin());
	}
	midiBusy = false;
}/*}}}*/
Пример #9
0
void Song::cmdResizePart(Track* track, Part* oPart, unsigned int len)
{
	switch (track->type())
	{
		case Track::WAVE:
		{
			WavePart* nPart = new WavePart(*(WavePart*) oPart);
			EventList* el = nPart->events();
			unsigned new_partlength = tempomap.deltaTick2frame(oPart->tick(), oPart->tick() + len);
			//printf("new partlength in frames: %d\n", new_partlength);

			// If new nr of frames is less than previous what can happen is:
			// -   0 or more events are beginning after the new final position. Those are removed from the part
			// -   The last event begins before new final position and ends after it. If so, it will be resized to end at new part length
			if (new_partlength < oPart->lenFrame())
			{
				startUndo();

				for (iEvent i = el->begin(); i != el->end(); i++)
				{
					Event e = i->second;
					unsigned event_startframe = e.frame();
					unsigned event_endframe = event_startframe + e.lenFrame();
					//printf("Event frame=%d, length=%d\n", event_startframe, event_length);
					if (event_endframe < new_partlength)
						continue;
					if (event_startframe > new_partlength)
					{ // If event start was after the new length, remove it from part
						// Indicate no undo, and do not do port controller values and clone parts.
						//audio->msgDeleteEvent(e, nPart, false);
						audio->msgDeleteEvent(e, nPart, false, false, false);
						continue;
					}
					if (event_endframe > new_partlength)
					{ // If this event starts before new length and ends after, shrink it
						Event newEvent = e.clone();
						newEvent.setLenFrame(new_partlength - event_startframe);
						// Indicate no undo, and do not do port controller values and clone parts.
						//audio->msgChangeEvent(e, newEvent, nPart, false);
						audio->msgChangeEvent(e, newEvent, nPart, false, false, false);
					}
				}
				nPart->setLenFrame(new_partlength);
				// Indicate no undo, and do not do port controller values and clone parts.
				//audio->msgChangePart(oPart, nPart, false);
				audio->msgChangePart(oPart, nPart, false, false, false);

				endUndo(SC_PART_MODIFIED);
			}
				// If the part is expanded there can be no additional events beginning after the previous final position
				// since those are removed if the part has been shrunk at some time (see above)
				// The only thing we need to check is the final event: If it has data after the previous final position,
				// we'll expand that event
			else
			{
				if (!el->empty())
				{
					iEvent i = el->end();
					i--;
					Event last = i->second;
					unsigned last_start = last.frame();
					SndFileR file = last.sndFile();
					if (file.isNull())
						return;

					unsigned clipframes = (file.samples() - last.spos()); // / file.channels();
					Event newEvent = last.clone();
					//printf("SndFileR samples=%d channels=%d event samplepos=%d clipframes=%d\n", file.samples(), file.channels(), last.spos(), clipframes);

					unsigned new_eventlength = new_partlength - last_start;
					if (new_eventlength > clipframes) // Shrink event length if new partlength exceeds last clip
						new_eventlength = clipframes;

					newEvent.setLenFrame(new_eventlength);
					startUndo();
					// Indicate no undo, and do not do port controller values and clone parts.
					//audio->msgChangeEvent(last, newEvent, nPart, false);
					audio->msgChangeEvent(last, newEvent, nPart, false, false, false);
				}
				else
				{
					startUndo();
				}

				nPart->setLenFrame(new_partlength);
				// Indicate no undo, and do not do port controller values and clone parts.
				//audio->msgChangePart(oPart, nPart, false);
				audio->msgChangePart(oPart, nPart, false, false, false);
				endUndo(SC_PART_MODIFIED);
			}
		}
			break;
		case Track::MIDI:
		case Track::DRUM:
		{
			startUndo();

			MidiPart* nPart = new MidiPart(*(MidiPart*) oPart);
			nPart->setLenTick(len);
			// Indicate no undo, and do port controller values but not clone parts.
			audio->msgChangePart(oPart, nPart, false, true, false);

			// cut Events in nPart
			// Changed by T356. Don't delete events if this is a clone part.
			// The other clones might be longer than this one and need these events.
			if (nPart->cevents()->arefCount() <= 1)
			{
				if (oPart->lenTick() > len)
				{
					EventList* el = nPart->events();
					iEvent ie = el->lower_bound(len);
					for (; ie != el->end();)
					{
						iEvent i = ie;
						++ie;
						// Indicate no undo, and do port controller values and clone parts.
						audio->msgDeleteEvent(i->second, nPart, false, true, true);
					}
				}
			}

			/*
			// cut Events in nPart
			// Changed by T356. Don't delete events if this is a clone part.
			// The other clones might be longer than this one and need these events.
			if(oPart->cevents()->arefCount() <= 1)
			{
			  if (oPart->lenTick() > len) {
					EventList* el = nPart->events();
					iEvent ie = el->lower_bound(len);
					for (; ie != el->end();) {
						  iEvent i = ie;
						  ++ie;
						  // Indicate no undo, and do not do port controller values and clone parts.
						  //audio->msgDeleteEvent(i->second, nPart, false);
						  audio->msgDeleteEvent(i->second, nPart, false, false, 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);
			break;
		}
		default:
			break;
	}
}
Пример #10
0
PyObject* getParts(PyObject*, PyObject* args)
{
	TrackList* tracks = song->tracks();
	const char* trackname;
	if (!PyArg_ParseTuple(args, "s", &trackname))
	{
		return NULL;
	}

	PyObject* pyparts = Py_BuildValue("[]");
	for (ciTrack t = tracks->begin(); t != tracks->end(); ++t)
	{
		Track* track = *t;
		if (track->name() != trackname)
			continue;

		PartList* parts = track->parts();
		for (ciPart p = parts->begin(); p != parts->end(); p++)
		{
			Part* part = p->second;

			MidiPart* mpart = (MidiPart*) part;
			PyObject* pypart = PyDict_New();
			int tick = mpart->tick();
			int lentick = mpart->lenTick();
			int serialnr = mpart->sn();
			PyObject* pstrtick = Py_BuildValue("s", "tick");
			PyObject* pitick = Py_BuildValue("i", tick);
			PyObject* pstrid = Py_BuildValue("s", "id");
			PyObject* pstrserial = Py_BuildValue("i", serialnr);
			PyObject* pstrlen = Py_BuildValue("s", "len");
			PyObject* pstrtick2 = Py_BuildValue("i", lentick);

			PyDict_SetItem(pypart, pstrtick, pitick);
			PyDict_SetItem(pypart, pstrid, pstrserial);
			PyDict_SetItem(pypart, pstrlen, pstrtick2);

			Py_DECREF(pstrtick);
			Py_DECREF(pitick);
			Py_DECREF(pstrid);
			Py_DECREF(pstrserial);
			Py_DECREF(pstrlen);
			Py_DECREF(pstrtick2);

			// Pack midi events into list before wrapping it all up
			EventList* events = mpart->events();
			PyObject* pyevents = Py_BuildValue("[]");
			for (ciEvent e = events->begin(); e != events->end(); e++)
			{
				PyObject* pyevent = PyDict_New(); // The event structure - a dictionary with keys 'type','tick','data'

				const Event& event = e->second;
				unsigned tick = e->first;
				PyObject* eventdata = Py_BuildValue("[i,i,i]", event.dataA(), event.dataB(), event.dataC());
				PyObject* pstrdata = Py_BuildValue("s", "data");
				pstrtick = Py_BuildValue("s", "tick");
				PyObject* pitickval = Py_BuildValue("i", tick);
				PyDict_SetItem(pyevent, pstrdata, eventdata);
				PyDict_SetItem(pyevent, pstrtick, pitickval);
				Py_DECREF(eventdata);
				Py_DECREF(pstrdata);
				Py_DECREF(pstrtick);
				Py_DECREF(pitickval);

				switch (event.type())
				{
					case Note:
					{
						PyObject* pstrtype = Py_BuildValue("s", "type");
						PyObject* pstrnote = Py_BuildValue("s", "note");
						PyObject* pstrlen = Py_BuildValue("s", "len");
						PyObject* pilentick = Py_BuildValue("i", event.lenTick());
						PyDict_SetItem(pyevent, pstrtype, pstrnote);
						PyDict_SetItem(pyevent, pstrlen, pilentick);
						Py_DECREF(pstrtype);
						Py_DECREF(pstrnote);
						Py_DECREF(pstrlen);
						Py_DECREF(pilentick);
						break;
					}
					case Controller:
					{
						PyObject* pstrtype = Py_BuildValue("s", "type");
						PyObject* pstrctrl = Py_BuildValue("s", "ctrl");
						PyDict_SetItem(pyevent, pstrtype, pstrctrl);
						Py_DECREF(pstrtype);
						Py_DECREF(pstrctrl);
						break;
					}
					default:
						printf("Event type not supported yet: %d\n", event.type());
						break;
				}
				PyList_Append(pyevents, pyevent);
				Py_DECREF(pyevent);
			}
			Py_DECREF(pyevents);
			// Add the event list to the pypart dictionary
			PyObject* pystrevents = Py_BuildValue("s", "events");
			PyDict_SetItem(pypart, pystrevents, pyevents);
			Py_DECREF(pystrevents);
			PyList_Append(pyparts, pypart);
			Py_DECREF(pypart);
		}

		return pyparts;
	}

	return NULL;
}
Пример #11
0
QString EventListItem::text(int col) const
{
    QString s;
    QString commentLabel;
    switch (col)
    {
        case 0:
            s.setNum(event.tick());
            break;
        case 1:
        {
            int t = event.tick() + part->tick();
            int bar, beat;
            unsigned tick;
            sigmap.tickValues(t, &bar, &beat, &tick);
            s.sprintf("%04d.%02d.%03d", bar + 1, beat + 1, tick);
        }
            break;
        case 2:
            switch (event.type())
            {
                case Note:
                    s = QString("Note");
                    break;
                case Controller:
                {
                    const char* cs;
                    switch (midiControllerType(event.dataA()))
                    {
                        case MidiController::Controller7: cs = "Ctrl7";
                            break;
                        case MidiController::Controller14: cs = "Ctrl14";
                            break;
                        case MidiController::RPN: cs = "RPN";
                            break;
                        case MidiController::NRPN: cs = "NRPN";
                            break;
                        case MidiController::Pitch: cs = "Pitch";
                            break;
                        case MidiController::Program: cs = "Program";
                            break;
                        case MidiController::RPN14: cs = "RPN14";
                            break;
                        case MidiController::NRPN14: cs = "NRPN14";
                            break;
                        default: cs = "Ctrl?";
                            break;
                    }
                    s = QString(cs);
                }
                    break;
                case Sysex:
                {
                    commentLabel = QString("len ");
                    QString k;
                    k.setNum(event.dataLen());
                    commentLabel += k;
                    commentLabel += QString(" ");

                    commentLabel += nameSysex(event.dataLen(), event.data());
                    int i;
                    for (i = 0; i < 10; ++i)
                    {
                        if (i >= event.dataLen())
                            break;
                        commentLabel += QString(" 0x");
                        QString k;
                        k.setNum(event.data()[i] & 0xff, 16);
                        commentLabel += k;
                    }
                    if (i == 10)
                        commentLabel += QString("...");
                }
                    s = QString("SysEx");
                    break;
                case PAfter:
                    s = QString("PoAT");
                    break;
                case CAfter:
                    s = QString("ChAT");
                    break;
                case Meta:
                    commentLabel = midiMetaComment(event);
                    s = QString("Meta");
                    break;
                default:
                    printf("unknown event type %d\n", event.type());
            }
            break;
        case 3:
            s.setNum(part->track()->outChannel() + 1);
            break;
        case 4:
            if (event.isNote() || event.type() == PAfter)
                s = pitch2string(event.dataA());
            else if (event.type() == Controller)
                s.setNum(event.dataA() & 0xffff); // mask off type bits
            else
                s.setNum(event.dataA());
            break;
        case 5:
            if (event.type() == Controller &&
                    midiControllerType(event.dataA()) == MidiController::Program)
            {
                int val = event.dataB();
                int hb = ((val >> 16) & 0xff) + 1;
                if (hb == 0x100)
                    hb = 0;
                int lb = ((val >> 8) & 0xff) + 1;
                if (lb == 0x100)
                    lb = 0;
                int pr = (val & 0xff) + 1;
                if (pr == 0x100)
                    pr = 0;
                s.sprintf("%d-%d-%d", hb, lb, pr);
            }
            else
Пример #12
0
void ListEdit::songChanged(int type)
{
    if (type == 0)
        return;
    if (type & (SC_PART_REMOVED | SC_PART_MODIFIED
            | SC_PART_INSERTED | SC_EVENT_REMOVED | SC_EVENT_MODIFIED
            | SC_EVENT_INSERTED | SC_SELECTION))
    {
        if (type & (SC_PART_REMOVED | SC_PART_INSERTED))
            genPartlist();
        // close window if editor has no parts anymore
        if (parts()->empty())
        {
            close();
            return;
        }
        liste->setSortingEnabled(false);
        if (type == SC_SELECTION)
        {
            bool update = false;
            QTreeWidgetItem* ci = 0;
            liste->blockSignals(true);
            for (int row = 0; row < liste->topLevelItemCount(); ++row)
            {
                QTreeWidgetItem* i = liste->topLevelItem(row);
                if (i->isSelected() ^ ((EventListItem*) i)->event.selected())
                {
                    i->setSelected(((EventListItem*) i)->event.selected());
                    if (i->isSelected())
                        ci = i;
                    update = true;
                }
            }
            if (update)
            {
                if (ci)
                {
                    liste->setCurrentItem(ci);
                    liste->scrollToItem(ci, QAbstractItemView::EnsureVisible);
                }
                //liste->update();
            }
            liste->blockSignals(false);
        }
        else
        {
            curPart = 0;
            curTrack = 0;
            liste->clear();
            for (iPart p = parts()->begin(); p != parts()->end(); ++p)
            {
                MidiPart* part = (MidiPart*) (p->second);
                if (part->sn() == curPartId)
                    curPart = part;
                EventList* el = part->events();
                for (iEvent i = el->begin(); i != el->end(); ++i)
                {
                    EventListItem* item = new EventListItem(liste, i->second, part);
                    for (int col = 0; col < liste->columnCount(); ++col)
                        item->setText(col, item->text(col));
                    item->setSelected(i->second.selected());
                    if (item->event.tick() == (unsigned) selectedTick)
                    { //prevent compiler warning: comparison of signed/unsigned)
                        liste->setCurrentItem(item);
                        item->setSelected(true);
                        liste->scrollToItem(item, QAbstractItemView::EnsureVisible);
                    }
                }
            }
        }

        // p3.3.34
        //if (curPart == 0)
        //      curPart  = (MidiPart*)(parts()->begin()->second);
        //curTrack = curPart->track();
        if (!curPart)
        {
            if (!parts()->empty())
            {
                curPart = (MidiPart*) (parts()->begin()->second);
                if (curPart)
                    curTrack = curPart->track();
                else
                    curPart = 0;
            }
        }
    }
    liste->setSortingEnabled(true);
}