Beispiel #1
0
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);
}
Beispiel #2
0
    InputImpl(OEngine::Render::OgreRenderer &_ogre,
              MWRender::PlayerPos &_player,
              MWGui::WindowManager &_windows,
              bool debug)
        : ogre(_ogre),
          exit(ogre.getWindow()),
          input(ogre.getWindow(), !debug),
          poller(input),
          player(_player),
          windows(_windows),
          shotCount(0)
    {
        using namespace OEngine::Input;
        using namespace OEngine::Render;
        using namespace OEngine::GUI;
        using namespace Mangle::Input;
        using namespace OIS;

        disp = DispatcherPtr(new Dispatcher(A_LAST));

        // Bind MW-specific functions
        disp->funcs.bind(A_Quit, boost::bind(&InputImpl::exitNow, this),
                         "Quit program");
        disp->funcs.bind(A_Screenshot, boost::bind(&InputImpl::screenshot, this),
                         "Screenshot");
        disp->funcs.bind(A_Inventory, boost::bind(&InputImpl::toggleInventory, this),
                         "Toggle inventory screen");
        disp->funcs.bind(A_Console, boost::bind(&InputImpl::toggleConsole, this),
                         "Toggle console");


        // Add the exit listener
        ogre.getRoot()->addFrameListener(&exit);
        // Add ourselves as a frame listener to catch movement keys
        ogre.getRoot()->addFrameListener(this);

        // Set up the mouse handler and tell it about the player camera
        mouse = MouseLookEventPtr(new MouseLookEvent(player.getCamera()));

        // This event handler pumps events into MyGUI
        guiEvents = EventInjectorPtr(new EventInjector(windows.getGui()));

        // Hook 'mouse' and 'disp' up as event handlers into 'input'
        // (the OIS driver and event source.) We do this through an
        // EventList which dispatches the event to multiple handlers for
        // us.
        {
            EventList *lst = new EventList;
            input.setEvent(EventPtr(lst));
            lst->add(mouse,Event::EV_MouseMove);
            lst->add(disp,Event::EV_KeyDown);
            lst->add(guiEvents,Event::EV_ALL);
        }

        // Start out in game mode
        setGuiMode(MWGui::GM_Game);

        /**********************************
          Key binding section

          The rest of this function has hard coded key bindings, and is
          intended to be replaced by user defined bindings later.
         **********************************/

        // Key bindings for keypress events

        disp->bind(A_Quit, KC_Q);
        disp->bind(A_Quit, KC_ESCAPE);
        disp->bind(A_Screenshot, KC_SYSRQ);
        disp->bind(A_Inventory, KC_I);
        disp->bind(A_Console, KC_F1);

        // Key bindings for polled keys

        // Arrow keys
        poller.bind(A_MoveLeft, KC_LEFT);
        poller.bind(A_MoveRight, KC_RIGHT);
        poller.bind(A_MoveForward, KC_UP);
        poller.bind(A_MoveBackward, KC_DOWN);

        // WASD keys
        poller.bind(A_MoveLeft, KC_A);
        poller.bind(A_MoveRight, KC_D);
        poller.bind(A_MoveForward, KC_W);
        poller.bind(A_MoveBackward, KC_S);

        // Use shift and ctrl for up and down
        poller.bind(A_MoveUp, KC_LSHIFT);
        poller.bind(A_MoveDown, KC_LCONTROL);
    }
Beispiel #3
0
    InputImpl(OEngine::Render::OgreRenderer &_ogre,
              MWWorld::Player &_player,
              MWGui::WindowManager &_windows,
              bool debug,
              OMW::Engine& engine)
        : ogre(_ogre),
          exit(ogre.getWindow()),
          input(ogre.getWindow(), !debug),
          poller(input),
          player(_player),
          windows(_windows),
          mEngine (engine),
          shotCount(0)
    {
        using namespace OEngine::Input;
        using namespace OEngine::Render;
        using namespace OEngine::GUI;
        using namespace Mangle::Input;
        using namespace OIS;

        disp = DispatcherPtr(new Dispatcher(A_LAST));

        // Bind MW-specific functions
        disp->funcs.bind(A_Quit, boost::bind(&InputImpl::exitNow, this),
                         "Quit program");
        disp->funcs.bind(A_Screenshot, boost::bind(&InputImpl::screenshot, this),
                         "Screenshot");
        disp->funcs.bind(A_Inventory, boost::bind(&InputImpl::toggleInventory, this),
                         "Toggle inventory screen");
        disp->funcs.bind(A_Console, boost::bind(&InputImpl::toggleConsole, this),
                         "Toggle console");
        disp->funcs.bind(A_Activate, boost::bind(&InputImpl::activate, this),
                         "Activate");
        disp->funcs.bind(A_AutoMove, boost::bind(&InputImpl::toggleAutoMove, this),
                         "Auto Move");
        disp->funcs.bind(A_ToggleWalk, boost::bind(&InputImpl::toggleWalking, this),
                         "Toggle Walk/Run");

        // Add the exit listener
        ogre.getRoot()->addFrameListener(&exit);
        // Add ourselves as a frame listener to catch movement keys
        ogre.getRoot()->addFrameListener(this);

        // Set up the mouse handler and tell it about the player camera
        mouse = MouseLookEventPtr(new MouseLookEvent(player.getRenderer()->getCamera()));

        // This event handler pumps events into MyGUI
        guiEvents = EventInjectorPtr(new EventInjector(windows.getGui()));

        // Hook 'mouse' and 'disp' up as event handlers into 'input'
        // (the OIS driver and event source.) We do this through an
        // EventList which dispatches the event to multiple handlers for
        // us.
        {
            EventList *lst = new EventList;
            input.setEvent(EventPtr(lst));
            lst->add(mouse,Event::EV_MouseMove);
            lst->add(disp,Event::EV_KeyDown);
            lst->add(guiEvents,Event::EV_ALL);
        }

        // Start out in game mode
        setGuiMode(MWGui::GM_Game);

        /**********************************
          Key binding section

          The rest of this function has hard coded key bindings, and is
          intended to be replaced by user defined bindings later.
         **********************************/

        // Key bindings for keypress events
        // NOTE: These keys do not require constant polling - use in conjuction with variables in loops.

        disp->bind(A_Quit, KC_Q);
        disp->bind(A_Quit, KC_ESCAPE);
        disp->bind(A_Screenshot, KC_SYSRQ);
        disp->bind(A_Inventory, KC_I);
        disp->bind(A_Console, KC_F1);
        disp->bind(A_Activate, KC_SPACE);
        disp->bind(A_AutoMove, KC_Z);
        disp->bind(A_ToggleSneak, KC_X);
        disp->bind(A_ToggleWalk, KC_C);

        // Key bindings for polled keys
        // NOTE: These keys are constantly being polled. Only add keys that must be checked each frame.

        // Arrow keys
        poller.bind(A_MoveLeft, KC_LEFT);
        poller.bind(A_MoveRight, KC_RIGHT);
        poller.bind(A_MoveForward, KC_UP);
        poller.bind(A_MoveBackward, KC_DOWN);

        // WASD keys
        poller.bind(A_MoveLeft, KC_A);
        poller.bind(A_MoveRight, KC_D);
        poller.bind(A_MoveForward, KC_W);
        poller.bind(A_MoveBackward, KC_S);
    }
Beispiel #4
0
int runFishhook(int argc, char** argv) {

  parseFishOptions(argc, argv);

  if (opt::verbose) {
    std::cerr << "FishHook Params: " << std::endl 
	      << "\tWidth: " << SeqLib::AddCommas(opt::width) << std::endl
	      << "\tEvents: " << opt::events << std::endl
	      << "\tCoverage Mask: " << opt::coverage << std::endl
	      << "\tSlop: " << SeqLib::AddCommas(opt::slop) << std::endl
	      << "\tInterval Tracks: " << std::endl;
    for (auto& i : opt::interval_files)
      std::cerr << "\t-- " << i << std::endl;
    std::cerr << "\tScored Tracks: " << std::endl;
    for (auto& i : opt::scored_files)
      std::cerr << "\t-- " << i << std::endl;
    std::cerr << "\tSequence Features: " << std::endl;
    for (auto& i : opt::seq_features)
      std::cerr << "\t-- " << i << std::endl;

  }

  // read in the covariate tracks
  SeqHashMap<std::string, Fractions> intervals;
  
  // read a header for info
  SeqLib::BamReader rdr;
  if (!rdr.Open(opt::bam)) {
    std::cerr << "Error: Could not read BAM supplied by -b: " << opt::bam << std::endl;
    exit(EXIT_FAILURE);
  }
  hdr = rdr.Header();
  
  // read in the reference genome
  SeqLib::RefGenome ref;
  if (!ref.LoadIndex(opt::refgenome)) {
      if (opt::seq_features.size()) {
	std::cerr << "Error: Could not read referene genome supplied by -G: " << opt::refgenome << std::endl;
	exit(EXIT_FAILURE);
      }
  }

  // read in the events
  if (opt::verbose) std::cerr << "...reading events " << opt::events << std::endl;
  EventList events;
  if (!events.readFromBed(opt::events, hdr)) {
    std::cerr << "Error: Could not read events BED: " << opt::events << std::endl;
    exit(EXIT_FAILURE);
  }
  if (opt::verbose) std::cerr << "...read in " << SeqLib::AddCommas(events.size()) << " events" << std::endl;
  events.CreateTreeMap();
  
  // create the tiled regions
  FishHookTiles fish(opt::width, opt::slop, hdr.GetHeaderSequenceVector());
  if (opt::verbose)
    std::cerr << "...constructed " << SeqLib::AddCommas(fish.size()) << " fishhook intervals" << std::endl;
  fish.CreateTreeMap();

  // read the coverage mask
  SeqLib::GRC cov;
  if (!opt::coverage.empty()) {
    if (opt::verbose) std::cerr << "...reading coverage mask " << opt::coverage << std::endl;
    cov.ReadBED(opt::coverage, hdr);
    if (opt::verbose) std::cerr << "...read in " << SeqLib::AddCommas(cov.size()) << " covered regions " << std::endl;
    if (!cov.size()) {
      std::cerr << "Non-empty coverage track read with 0 regions. Check that is non-empty BED" << std::endl;
      exit(EXIT_FAILURE);
    }
    if (opt::verbose) std::cerr << "...creating interval tree map on covered regions and overlapping with tiles" << std::endl;
    cov.CreateTreeMap();

    // find covered amount per tile
    std::vector<int32_t> q, s;
    SeqLib::GRC ovlp;
    // fish is subject
    if (fish.size() > cov.size()) // do in most efficient order
      ovlp = cov.FindOverlaps(fish, q, s, false);
    else
      ovlp = fish.FindOverlaps(cov, s, q, false);
    if (opt::verbose) std::cerr << "..." << SeqLib::AddCommas(ovlp.size()) << " regions are covered" << std::endl;

    // set the amount covered by each
    for (size_t i = 0; i < ovlp.size(); ++i) {
      fish[s[i]].covered += (double)ovlp[i].Width() / fish[s[i]].Width();
    }

    // mask the events
    q.clear(); s.clear(); ovlp.clear();
    // events is subject
    if (events.size() > cov.size()) // do in most efficient order
      ovlp = cov.FindOverlaps(events, q, s, false);
    else
      ovlp = events.FindOverlaps(cov, s, q, false);

    EventList newe;
    // set the amount covered by each
    for (size_t i = 0; i < ovlp.size(); ++i) {
      newe.add(Event(ovlp[i], events.at(s[i]).id));
    }
    events = newe;
    events.CreateTreeMap();

    if (opt::verbose) std::cerr << "...kept " << SeqLib::AddCommas(events.size()) << " events after mask" << std::endl;
    
  } else {
    for (auto& i : fish)
      i.covered = 1; // the entire thing is covered if no mask provided
  }

  // read in the interval tracks
  for (auto& i : opt::interval_files)
    read_track(i, intervals, cov, false);
  for (auto& i : opt::scored_files)
    read_track(i, intervals, cov, true);

  // count events per tile (also de-dupes on patient per bin)
  fish.CountEvents(events);
  // overlap the covariates with the tiles
  for (auto& i : intervals) {
    fish.AddIntervalCovariate(i.first, i.second);
  }

  // make the matrix
  FishModel fm;
  fm.AddTiles(fish);
  
  fm.SetNumThreads(opt::num_threads);
  fm.EstimateOLS();
  fm.CooksDistance(fm.GetOLS());

  // write the covariates
  fish.PrintBEDHeader(std::cout);
  fish.PrintBED(std::cout, hdr);

  

  return 0;
}
Beispiel #5
0
QMimeData* EventCanvas::getTextDrag()
{
    //---------------------------------------------------
    //   generate event list from selected events
    //---------------------------------------------------

    EventList el;
    unsigned startTick = MAXINT;
    for (iCItem i = _items.begin(); i != _items.end(); ++i)
    {
        if (!i->second->isSelected())
            continue;
        ///NEvent* ne = (NEvent*)(i->second);
        CItem* ne = i->second;
        Event e = ne->event();
        if (startTick == MAXINT)
            startTick = e.tick();
        el.add(e);
    }

    //---------------------------------------------------
    //    write events as XML into tmp file
    //---------------------------------------------------

    FILE* tmp = tmpfile();
    if (tmp == 0)
    {
        fprintf(stderr, "EventCanvas::getTextDrag() fopen failed: %s\n",
                strerror(errno));
        return 0;
    }
    Xml xml(tmp);

    int level = 0;
    xml.tag(level++, "eventlist");
    for (ciEvent e = el.begin(); e != el.end(); ++e)
        e->second.write(level, xml, -startTick);
    xml.etag(--level, "eventlist");

    //---------------------------------------------------
    //    read tmp file into drag Object
    //---------------------------------------------------

    fflush(tmp);
    struct stat f_stat;
    if (fstat(fileno(tmp), &f_stat) == -1)
    {
        fprintf(stderr, "PianorollCanvas::copy() fstat failes:<%s>\n",
                strerror(errno));
        fclose(tmp);
        return 0;
    }
    int n = f_stat.st_size;
    char* fbuf = (char*) mmap(0, n + 1, PROT_READ | PROT_WRITE,
                              MAP_PRIVATE, fileno(tmp), 0);
    fbuf[n] = 0;

    QByteArray data(fbuf);
    QMimeData* md = new QMimeData();
    //QDrag* drag = new QDrag(parent);

    md->setData("text/x-los-eventlist", data);
    //drag->setMimeData(md);

    munmap(fbuf, n);
    fclose(tmp);

    //return drag;
    return md;
}
Beispiel #6
0
    InputImpl(OEngine::Render::OgreRenderer &_ogre,
                   MWWorld::Player &_player,
                   MWBase::WindowManager &_windows,
                   bool debug,
                   OMW::Engine& engine)
      : ogre(_ogre),
        input(ogre.getWindow(), !debug),
        poller(input),
        player(_player),
        windows(_windows),
        mEngine (engine),
        mDragDrop(false),
        mPreviewPOVDelay(0.f),
        mTimeIdle(0.f)
    {
      using namespace OEngine::Input;
      using namespace OEngine::Render;
      using namespace OEngine::GUI;
      using namespace Mangle::Input;
      using namespace OIS;

      disp = DispatcherPtr(new Dispatcher(A_LAST));

      // Bind MW-specific functions
      disp->funcs.bind(A_Quit, boost::bind(&InputImpl::exitNow, this),
                      "Quit program");
      disp->funcs.bind(A_Screenshot, boost::bind(&InputImpl::screenshot, this),
                      "Screenshot");
      disp->funcs.bind(A_Inventory, boost::bind(&InputImpl::toggleInventory, this),
                       "Toggle inventory screen");
      disp->funcs.bind(A_Console, boost::bind(&InputImpl::toggleConsole, this),
                       "Toggle console");
      disp->funcs.bind(A_Journal, boost::bind(&InputImpl::toggleJournal, this),
                       "Toggle journal");
      disp->funcs.bind(A_Activate, boost::bind(&InputImpl::activate, this),
                       "Activate");
      disp->funcs.bind(A_AutoMove, boost::bind(&InputImpl::toggleAutoMove, this),
                      "Auto Move");
      disp->funcs.bind(A_ToggleWalk, boost::bind(&InputImpl::toggleWalking, this),
                      "Toggle Walk/Run");
      disp->funcs.bind(A_ToggleWeapon,boost::bind(&InputImpl::toggleWeapon,this),
                      "Draw Weapon");
      disp->funcs.bind(A_ToggleSpell,boost::bind(&InputImpl::toggleSpell,this),
                      "Ready hands");
      disp->funcs.bind(A_GameMenu, boost::bind(&InputImpl::toggleMainMenu, this),
                      "Toggle main menu");

      mouse = MouseLookEventPtr(new MouseLookEvent());

      // This event handler pumps events into MyGUI
      guiEvents = EventInjectorPtr(new EventInjector(windows.getGui()));

      // Hook 'mouse' and 'disp' up as event handlers into 'input'
      // (the OIS driver and event source.) We do this through an
      // EventList which dispatches the event to multiple handlers for
      // us.
      {
        EventList *lst = new EventList;
        input.setEvent(EventPtr(lst));
        lst->add(mouse,Event::EV_MouseMove);
        lst->add(disp,Event::EV_KeyDown);
        lst->add(guiEvents,Event::EV_ALL);
      }

      mControlSwitch["playercontrols"]      = true;
      mControlSwitch["playerfighting"]      = true;
      mControlSwitch["playerjumping"]       = true;
      mControlSwitch["playerlooking"]       = true;
      mControlSwitch["playermagic"]         = true;
      mControlSwitch["playerviewswitch"]    = true;
      mControlSwitch["vanitymode"]          = true;

      changeInputMode(false);

      /**********************************
        Key binding section

        The rest of this function has hard coded key bindings, and is
        intended to be replaced by user defined bindings later.
       **********************************/

      // Key bindings for keypress events
      // NOTE: These keys do not require constant polling - use in conjuction with variables in loops.

      disp->bind(A_Quit, KC_Q);
      disp->bind(A_GameMenu, KC_ESCAPE);
      disp->bind(A_Screenshot, KC_SYSRQ);
      disp->bind(A_Inventory, KC_I);
      disp->bind(A_Console, KC_F1);
      disp->bind(A_Journal, KC_J);
      disp->bind(A_Activate, KC_SPACE);
      disp->bind(A_AutoMove, KC_Z);
      disp->bind(A_ToggleSneak, KC_X);
      disp->bind(A_ToggleWalk, KC_C);
      disp->bind(A_ToggleWeapon,KC_F);
      disp->bind(A_ToggleSpell,KC_R);

      // Key bindings for polled keys
      // NOTE: These keys are constantly being polled. Only add keys that must be checked each frame.

      // Arrow keys
      poller.bind(A_MoveLeft, KC_LEFT);
      poller.bind(A_MoveRight, KC_RIGHT);
      poller.bind(A_MoveForward, KC_UP);
      poller.bind(A_MoveBackward, KC_DOWN);

      // WASD keys
      poller.bind(A_MoveLeft, KC_A);
      poller.bind(A_MoveRight, KC_D);
      poller.bind(A_MoveForward, KC_W);
      poller.bind(A_MoveBackward, KC_S);

      poller.bind(A_Jump, KC_E);
      poller.bind(A_Crouch, KC_LCONTROL);

      poller.bind(A_TogglePOV, KC_TAB);
    }
Beispiel #7
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());
}
Beispiel #8
0
void buildMidiEventList(EventList* del, const MPEventList* el, MidiTrack* track,
		int div, bool addSysexMeta, bool doLoops)
{
	int hbank = 0xff;
	int lbank = 0xff;
	int rpnh = -1;
	int rpnl = -1;
	int datah = 0;
	int datal = 0;
	int dataType = 0; // 0 : disabled, 0x20000 : rpn, 0x30000 : nrpn

	EventList mel;

	for (iMPEvent i = el->begin(); i != el->end(); ++i)
	{
		MidiPlayEvent ev = *i;
		if (!addSysexMeta && (ev.type() == ME_SYSEX || ev.type() == ME_META))
			continue;
		if (!(ev.type() == ME_SYSEX || ev.type() == ME_META
				|| ((ev.channel() == track->outChannel()) && (ev.port() == track->outPort()))))
			continue;
		unsigned tick = ev.time();
		// Added by Tim. p3.3.8

		// Added by T356.
		if (doLoops)
		{
			if (tick >= song->lPos().tick() && tick < song->rPos().tick())
			{
				int loopn = ev.loopNum();
				int loopc = audio->loopCount();
				int cmode = song->cycleMode(); // CYCLE_NORMAL, CYCLE_MIX, CYCLE_REPLACE
				// If we want REPLACE and the event was recorded in a previous loop,
				//  just ignore it. This will effectively ignore ALL previous loop events inside
				//  the left and right markers, regardless of where recording was started or stopped.
				// We want to keep any loop 0 note-offs from notes which crossed over the left marker.
				// To avoid more searching here, just keep ALL note-offs from loop 0, and let code below
				//  sort out and keep which ones had note-ons.
				if (!(ev.isNoteOff() && loopn == 0))
				{
					if (cmode == Song::CYCLE_REPLACE && loopn < loopc)
					{
						// Added by Tim. p3.3.8
						//printf("buildMidiEventList: CYCLE_REPLACE t:%d type:%d A:%d B:%d ln:%d lc:%d\n", tick, ev.type(), ev.dataA(), ev.dataB(), loopn, loopc);

						continue;
					}
					// If we want NORMAL, same as REPLACE except keep all events from the previous loop
					//  from rec stop position to right marker (and beyond).
					if (cmode == Song::CYCLE_NORMAL)
					{
						// Not sure of accuracy here. Adjust? Adjusted when used elsewhere?
						unsigned endRec = audio->getEndRecordPos().tick();
						if ((tick < endRec && loopn < loopc) || (tick >= endRec && loopn < (loopc - 1)))
						{
							// Added by Tim. p3.3.8
							//printf("buildMidiEventList: CYCLE_NORMAL t:%d type:%d A:%d B:%d ln:%d lc:%d\n", tick, ev.type(), ev.dataA(), ev.dataB(), loopn, loopc);

							continue;
						}
					}
				}
			}
		}

		Event e;
		switch (ev.type())
		{
			case ME_NOTEON:
				e.setType(Note);

				if (track->type() == Track::DRUM)
				{
					int instr = drumInmap[ev.dataA()];
					e.setPitch(instr);
				}
				else
				{
					e.setPitch(ev.dataA());
				}

				e.setVelo(ev.dataB());
				e.setLenTick(0);
				break;
			case ME_NOTEOFF:
				e.setType(Note);
				if (track->type() == Track::DRUM)
				{
					int instr = drumInmap[ev.dataA()];
					e.setPitch(instr);
				}
				else
					e.setPitch(ev.dataA());
				e.setVelo(0);
				e.setVeloOff(ev.dataB());
				e.setLenTick(0);
				break;
			case ME_POLYAFTER:
				e.setType(PAfter);
				e.setA(ev.dataA());
				e.setB(ev.dataB());
				break;
			case ME_CONTROLLER:
			{
				int val = ev.dataB();
				switch (ev.dataA())
				{
					case CTRL_HBANK:
						hbank = val;
						break;

					case CTRL_LBANK:
						lbank = val;
						break;

					case CTRL_HDATA:
						datah = val;
						// check if a CTRL_LDATA follows
						// e.g. wie have a 14 bit controller:
					{
						iMPEvent ii = i;
						++ii;
						bool found = false;
						for (; ii != el->end(); ++ii)
						{
							MidiPlayEvent ev = *ii;
							if (ev.type() == ME_CONTROLLER)
							{
								if (ev.dataA() == CTRL_LDATA)
								{
									// handle later
									found = true;
								}
								break;
							}
						}
						if (!found)
						{
							if (rpnh == -1 || rpnl == -1)
							{
								printf("parameter number not defined, data 0x%x\n", datah);
							}
							else
							{
								int ctrl = dataType | (rpnh << 8) | rpnl;
								e.setType(Controller);
								e.setA(ctrl);
								e.setB(datah);
							}
						}
					}
						break;

					case CTRL_LDATA:
						datal = val;

						if (rpnh == -1 || rpnl == -1)
						{
							printf("parameter number not defined, data 0x%x 0x%x, tick %d, channel %d\n",
									datah, datal, tick, track->outChannel());
							break;
						}
						// assume that the sequence is always
						//    CTRL_HDATA - CTRL_LDATA
						// eg. that LDATA is always send last

						e.setType(Controller);
						// 14 Bit RPN/NRPN
						e.setA((dataType + 0x30000) | (rpnh << 8) | rpnl);
						e.setB((datah << 7) | datal);
						break;

					case CTRL_HNRPN:
						rpnh = val;
						dataType = 0x30000;
						break;

					case CTRL_LNRPN:
						rpnl = val;
						dataType = 0x30000;
						break;

					case CTRL_HRPN:
						rpnh = val;
						dataType = 0x20000;
						break;

					case CTRL_LRPN:
						rpnl = val;
						dataType = 0x20000;
						break;

					default:
						e.setType(Controller);
						int ctl = ev.dataA();
						e.setA(ctl);

						if (track->type() == Track::DRUM)
						{
							// Is it a drum controller event, according to the track port's instrument?
							MidiController *mc = midiPorts[track->outPort()].drumController(ctl);
							if (mc)
								// Store an index into the drum map.
								e.setA((ctl & ~0xff) | drumInmap[ctl & 0x7f]);
						}

						e.setB(val);
						break;
				}
			}
				break;

			case ME_PROGRAM:
				e.setType(Controller);
				e.setA(CTRL_PROGRAM);
				e.setB((hbank << 16) | (lbank << 8) | ev.dataA());
				break;

			case ME_AFTERTOUCH:
				e.setType(CAfter);
				e.setA(ev.dataA());
				break;

			case ME_PITCHBEND:
				e.setType(Controller);
				e.setA(CTRL_PITCH);
				e.setB(ev.dataA());
				break;

			case ME_SYSEX:
				e.setType(Sysex);
				e.setData(ev.data(), ev.len());
				break;

			case ME_META:
			{
				const unsigned char* data = ev.data();
				switch (ev.dataA())
				{
					case 0x01: // Text
						if (track->comment().isEmpty())
							track->setComment(QString((const char*) data));
						else
							track->setComment(track->comment() + "\n" + QString((const char*) data));
						break;
					case 0x03: // Sequence-/TrackName
						track->setName(QString((char*) data));
						break;
					case 0x6: // Marker
					{
						unsigned ltick = CALC_TICK(tick); //(tick * config.division + div/2) / div;
						song->addMarker(QString((const char*) (data)), ltick, false);
					}
						break;
					case 0x5: // Lyrics
					case 0x8: // text
					case 0x9:
					case 0xa:
						break;

					case 0x0f: // Track Comment
						track->setComment(QString((char*) data));
						break;
					case 0x51: // Tempo
					{
						unsigned tempo = data[2] + (data[1] << 8) + (data[0] << 16);
						unsigned ltick = CALC_TICK(tick); // (unsigned(tick) * unsigned(config.division) + unsigned(div/2)) / unsigned(div);
						// After ca 10 mins 32 bits will not be enough... This expression has to be changed/factorized or so in some "sane" way...
						tempomap.addTempo(ltick, tempo);
					}
						break;
					case 0x58: // Time Signature
					{
						int timesig_z = data[0];
						int n = data[1];
						int timesig_n = 1;
						for (int i = 0; i < n; i++)
							timesig_n *= 2;
						int ltick = CALC_TICK(tick); //(tick * config.division + div/2) / div;
						///sigmap.add(ltick, timesig_z, timesig_n);
						AL::sigmap.add(ltick, AL::TimeSignature(timesig_z, timesig_n));
					}
						break;
					case 0x59: // Key Signature
						// track->scale.set(data[0]);
						// track->scale.setMajorMinor(data[1]);
						break;
					default:
						printf("unknown Meta 0x%x %d\n", ev.dataA(), ev.dataA());
				}
			}
				break;
		} // switch(ev.type()
		if (!e.empty())
		{
			e.setTick(tick);
			// Added by Tim. p3.3.8
			//printf("buildMidiEventList: mel adding t:%d type:%d A:%d B:%d C:%d\n", tick, e.type(), e.dataA(), e.dataB(), e.dataC());

			mel.add(e);
		}
	} // i != el->end()

	//---------------------------------------------------
	//    resolve NoteOff events
	//---------------------------------------------------

	//      for (iEvent i = mel.begin(); i != mel.end(); ++i) {
	//            Event event = i->second;
	//            if (event.isNote())
	//                  event.setLenTick(0);
	//            }

	// Added by Tim. p3.3.8

	// The loop is a safe way to delete while iterating.
	bool loop;
	do
	{
		loop = false;

		for (iEvent i = mel.begin(); i != mel.end(); ++i)
		{
			Event ev = i->second;
			if (ev.isNote())
			{
				if (ev.isNoteOff())
				{
					iEvent k;
					bool found = false;
					for (k = i; k != mel.end(); ++k)
					{
						Event event = k->second;
						if (event.tick() > ev.tick())
							break;
						if (event.isNoteOff(ev))
						{
							ev.setLenTick(1);
							ev.setVelo(event.velo());
							ev.setVeloOff(0);
							// Added by Tim. p3.3.8
							//printf("buildMidiEventList: found note off: event t:%d len:%d type:%d A:%d B:%d C:%d  ev t:%d len:%d type:%d A:%d B:%d C:%d\n", event.tick(), event.lenTick(), event.type(), event.dataA(), event.dataB(), event.dataC(), ev.tick(), ev.lenTick(), ev.type(), ev.dataA(), ev.dataB(), ev.dataC());

							found = true;
							break;
						}
					}
					if (!found)
					{
						printf("NOTE OFF without Note ON tick %d type %d  %d %d\n",
								ev.tick(), ev.type(), ev.pitch(), ev.velo());
					}
					else
					{
						mel.erase(k);

						// Changed by Tim. p3.3.8
						//continue;
						loop = true;
						break;

					}
				}
				// Added by Tim. p3.3.8

				// If the event length is not zero, it means the event and its
				//  note on/off have already been taken care of. So ignore it.
				if (ev.lenTick() != 0)
				{
					continue;
				}

				iEvent k;
				for (k = mel.lower_bound(ev.tick()); k != mel.end(); ++k)
				{
					Event event = k->second;
					if (ev.isNoteOff(event))
					{
						int t = k->first - i->first;
						if (t <= 0)
						{
							if (debugMsg)
							{
								printf("Note len is (%d-%d)=%d, set to 1\n",
										k->first, i->first, k->first - i->first);
								ev.dump();
								event.dump();
							}
							t = 1;
						}
						ev.setLenTick(t);
						ev.setVeloOff(event.veloOff());
						// Added by Tim. p3.3.8
						//printf("buildMidiEventList: set len and velOff: event t:%d len:%d type:%d A:%d B:%d C:%d  ev t:%d len:%d type:%d A:%d B:%d C:%d\n", event.tick(), event.lenTick(), event.type(), event.dataA(), event.dataB(), event.dataC(), ev.tick(), ev.lenTick(), ev.type(), ev.dataA(), ev.dataB(), ev.dataC());

						break;
					}
				}
				if (k == mel.end())
				{
					printf("-no note-off! %d pitch %d velo %d\n",
							ev.tick(), ev.pitch(), ev.velo());
					//
					// switch off at end of measure
					//
					int endTick = song->roundUpBar(ev.tick() + 1);
					ev.setLenTick(endTick - ev.tick());
				}
				else
				{
					mel.erase(k);
					// Added by Tim. p3.3.8
					loop = true;
					break;

				}
			}
		}
	} while (loop);

	// DEBUG: any note offs left?

	// Removed by Tim. p3.3.8
	//for (iEvent i = mel.begin(); i != mel.end(); ++i) {
	//      Event ev  = i->second;
	//      if (ev.isNoteOff()) {
	//            printf("+extra note-off! %d pitch %d velo %d\n",
	//                     i->first, ev.pitch(), ev.velo());
	//                  ev.dump();
	//            }
	//      }

	for (iEvent i = mel.begin(); i != mel.end(); ++i)
	{
		Event ev = i->second;
		if (ev.isNoteOff())
		{
			printf("+extra note-off! %d pitch %d velo %d\n",
					i->first, ev.pitch(), ev.velo());
			//                  ev.dump();
			continue;
		}
		int tick = CALC_TICK(ev.tick()); //(ev.tick() * config.division + div/2) / div;
		if (ev.isNote())
		{
			int lenTick = CALC_TICK(ev.lenTick()); //(ev.lenTick() * config.division + div/2) / div;
			ev.setLenTick(lenTick);
		}
		ev.setTick(tick);
		del->add(ev);
	}
}