コード例 #1
0
ファイル: importmidi.cpp プロジェクト: peter1000/los
bool LOS::importMidi(const QString name, bool merge)/*{{{*/
{
    bool popenFlag;
    FILE* fp = fileOpen(this, name, QString(".mid"), "r", popenFlag);
    if (fp == 0)
        return true;
    MidiFile mf(fp);
    bool rv = mf.read();
    popenFlag ? pclose(fp) : fclose(fp);
    if (rv)
    {
        QString s(tr("reading midifile\n  "));
        s += name;
        s += tr("\nfailed: ");
        s += mf.error();
        QMessageBox::critical(this, QString("LOS"), s);
        return rv;
    }
    //
    //  evaluate song Type (GM, XG, GS, unknown)
    //
    MidiType t = song->midiType();
    if (!merge)
    {
        t = mf.midiType();
        song->setMidiType(t);
    }
    MidiInstrument* instr = 0;
    for (iMidiInstrument i = midiInstruments.begin(); i != midiInstruments.end(); ++i)
    {
        MidiInstrument* mi = *i;
        if ((mi->iname() == "GM" && ((t == MIDI_TYPE_NULL) || (t == MIDI_TYPE_GM))) ||
            (mi->iname() == "GS" &&   t == MIDI_TYPE_GS) ||
            (mi->iname() == "XG" &&   t == MIDI_TYPE_XG))
        {
            instr = mi;
            break;
        }
    }
    if (instr == 0)
    {
        // the standard instrument files (GM, GS, XG) must be present
        printf("no instrument, type %d\n", t);
        return true;
        //abort();
    }

    MidiFileTrackList* etl = mf.trackList();
    int division = mf.division();

    //
    // create MidiTrack and copy events to ->events()
    //    - combine note on/off events
    //    - calculate tick value for internal resolution
    //
    int mPort = getFreeMidiPort();
    for (iMidiFileTrack t = etl->begin(); t != etl->end(); ++t)
    {
        MPEventList* el = &((*t)->events);
        if (el->empty())
            continue;
        //
        // if we split the track, SYSEX and META events go into
        // the first target track

        bool first = true;
        QList<QPair<int, int> > portChannelList;
        iMPEvent i;
        for(i = el->begin(); i != el->end(); i++)
        {
            if (i->type() != ME_SYSEX && i->type() != ME_META)
            {
                int chan = i->channel();
                int port = i->port();
                if(portChannelList.isEmpty() || !portChannelList.contains(qMakePair(chan, port)))
                {
                    portChannelList.append(qMakePair(chan, port));

                    MidiTrack* track = new MidiTrack();
                    track->setDefaultName();
                    track->setMasterFlag(true);

                    if(config.partColorNames[lastTrackPartColorIndex].contains("menu:", Qt::CaseSensitive))
                        lastTrackPartColorIndex ++;

                    track->setDefaultPartColor(lastTrackPartColorIndex);
                    lastTrackPartColorIndex ++;

                    if(lastTrackPartColorIndex == NUM_PARTCOLORS)
                        lastTrackPartColorIndex = 1;

                    //Set track channel so buildMidiEventList can match the event to a channel
                    track->setOutChannel(chan);
                    track->setOutPort(mPort);

                    MidiPort* mport = &midiPorts[track->outPort()];
                    // this overwrites any instrument set for this port:
                    mport->setInstrument(instr);

                    EventList* mel = track->events();
                    buildMidiEventList(mel, el, track, division, first, false, false);

                    first = false;

                    processTrack(track);

                    //Update track to channel 1
                    //99% of all midi we import will be alien to our setup anyway,
                    //so I'm making it easy for the user to just set the Instrument and go
                    track->setOutChannel(0);

                    song->insertTrack(track, -1);
                    mPort++;
                    //FIXME: Provice a non-iterative way to do this using the new losMidiPorts hash
                    //Or maintain a list of configured or inuse ports
                    while((&midiPorts[mPort])->device() && mPort < kMaxMidiPorts)
                        mPort++;//Just incase we have a configured port after an empty one
                }
            }
        }
        if (first)
        {
            //
            // track does only contain non-channel messages
            // (SYSEX or META)
            //
            MidiTrack* track = new MidiTrack();
            track->setDefaultName();
            track->setMasterFlag(true);
            track->setOutChannel(0);
            track->setOutPort(mPort);

            if(config.partColorNames[lastTrackPartColorIndex].contains("menu:", Qt::CaseSensitive))
                lastTrackPartColorIndex ++;

            track->setDefaultPartColor(lastTrackPartColorIndex);
            lastTrackPartColorIndex ++;

            if(lastTrackPartColorIndex == NUM_PARTCOLORS)
                lastTrackPartColorIndex = 1;

            EventList* mel = track->events();
            // Do SysexMeta. Don't do loops.
            // TODO: Properly support sysex dumps
            buildMidiEventList(mel, el, track, division, true, false, false);
            processTrack(track);
            song->insertTrack(track, -1);
            mPort++;
            while((&midiPorts[mPort])->device() && mPort < kMaxMidiPorts)
                mPort++;
        }
    }

    if (!merge)
    {
        MidiTrackList* tl = song->tracks();
        if (!tl->empty())
        {
            MidiTrack* track = tl->front();
            track->setSelected(true);
        }
        song->initLen();

        int z, n;
        sigmap.timesig(0, z, n);

        int tempo = tempomap.tempo(0);
        transport->setTimesig(z, n);
        transport->setTempo(tempo);

        bool masterF = !tempomap.empty();
        song->setMasterFlag(masterF);
        transport->setMasterFlag(masterF);

        song->updatePos();

        composer->reset();
    }
    else
    {
        song->initLen();
    }

    return false;
}/*}}}*/
コード例 #2
0
ファイル: conf.cpp プロジェクト: Adamiko/los
static void readConfigMidiPort(Xml& xml)/*{{{*/
{
    int idx = 0;
    qint64 id = -1;
    QString device;
    bool isGlobal = false;

    QString instrument("GM");

    QList<PatchSequence*> patchSequences;
    QList<QPair<int, QString> > presets;

    int openFlags = 1;
    int dic = 0;
    int doc = 0;
    int type = MidiDevice::ALSA_MIDI;
    bool cachenrpn = false;

    MidiDevice* dev = 0;

    for (;;)
    {
        Xml::Token token = xml.parse();
        if (token == Xml::Error || token == Xml::End)
            break;
        QString tag = xml.s1();
        switch (token)
        {
            case Xml::TagStart:
                if (tag == "name")
                {
                    device = xml.parse1();
                    if (!dev)//Look for it as an alsa or already created device
                        dev = midiDevices.find(device);
                }
                else if (tag == "type")
                {
                    type = xml.parseInt();
                }
                else if (tag == "record")
                {   // old
                    bool f = xml.parseInt();
                    if (f)
                        openFlags |= 2;
                }
                else if (tag == "openFlags")
                    openFlags = xml.parseInt();
                else if (tag == "defaultInChans")
                    dic = xml.parseInt();
                else if (tag == "defaultOutChans")
                    doc = xml.parseInt();
                else if (tag == "instrument")
                {
                    instrument = xml.parse1();
                }
                else if (tag == "channel")
                {
                    readPortChannel(xml, idx);
                }
                else if (tag == "preset" || tag == "patchSequence")
                {
                    PatchSequence* p = readMidiPortPatchSequences(xml);
                    if (p)
                        patchSequences.append(p);
                }
                else if(tag == "midiPreset")
                {
                    presets.append(readMidiPortPreset(xml));
                }
                else if(tag == "cacheNRPN")
                {
                    cachenrpn = xml.parseInt();
                }
                else
                    xml.skip(tag);
                break;
            case Xml::Attribut:
                if (tag == "idx")
                {//Check to see if this port is already used, and bump if so
                    idx = xml.s2().toInt();
                    int freePort = getFreeMidiPort();
                    if(freePort != idx)
                    {//Set a flag here so we know when loading tracks later that we are dealing with an old file or global inputs changed
                        idx = freePort;
                    }
                }
                else if(tag == "portId")
                {//New style
                    id = xml.s2().toLongLong();
                    idx = getFreeMidiPort();
                }
                else if(tag == "isGlobalInput")
                {//Find the matching input if posible and set our index to it
                    isGlobal = xml.s2().toInt();
                }
                break;
            case Xml::TagEnd:
                if (tag == "midiport")
                {
                    if(isGlobal)
                    {//Find the global input that matches
                        //
                        if(gInputListPorts.size())
                        {
                            int myport = -1;
                            for(int i = 0; i < gInputListPorts.size(); ++i)
                            {
                                myport =  gInputListPorts.at(i);

                                MidiPort* inport = &midiPorts[i];
                                if(inport && inport->device() && inport->device()->name() == device)
                                {
                                    idx = myport;
                                    break;
                                }
                            }
                        }
                    }

                    if (idx < 0 || idx >= MIDI_PORTS)
                    {
                        fprintf(stderr, "bad midi port %d (>%d)\n",
                                idx, MIDI_PORTS);
                        idx = 0;
                    }

                    if (!dev)
                    {
                        if (type == MidiDevice::JACK_MIDI)
                        {
                            dev = MidiJackDevice::createJackMidiDevice(device); // p3.3.55

                            if (debugMsg)
                                fprintf(stderr, "readConfigMidiPort: creating jack midi device %s\n", device.toLatin1().constData());
                        }
                        else
                            dev = midiDevices.find(device);
                    }

                    if (debugMsg && !dev)
                        fprintf(stderr, "readConfigMidiPort: device not found %s\n", device.toLatin1().constData());

                    MidiPort* mp = &midiPorts[idx];
                    if(id)
                        mp->setPortId(id);

                    mp->setInstrument(registerMidiInstrument(instrument));
                    mp->setDefaultInChannels(dic);
                    mp->setDefaultOutChannels(doc);

                    //Indicate the port was found in the song file, even if no device is assigned to it.
                    mp->setFoundInSongFile(true);

                    if (!patchSequences.isEmpty())
                    {
                        for (int i = 0; i < patchSequences.size(); ++i)
                        {
                            mp->appendPatchSequence(patchSequences.at(i));
                        }
                    }
                    if(!presets.isEmpty())
                    {
                        for(int i = 0; i < presets.size(); ++i)
                        {
                            QPair<int, QString> pair = presets.at(i);
                            mp->addPreset(pair.first, pair.second);
                        }
                    }

                    if (dev)
                    {
                        dev->setOpenFlags(openFlags);
                        midiSeq->msgSetMidiDevice(mp, dev);
                        dev->setCacheNRPN(cachenrpn);
                    }
                    losMidiPorts.insert(mp->id(), mp);
                    return;
                }
            default:
                break;
        }
    }
}/*}}}*/
コード例 #3
0
ファイル: importmidi.cpp プロジェクト: peter1000/los
bool LOS::importMidi(const QString name, bool merge)/*{{{*/
{
    bool popenFlag;
    FILE* fp = fileOpen(this, name, QString(".mid"), "r", popenFlag);
    if (fp == 0)
        return true;
    MidiFile mf(fp);
    bool rv = mf.read();
    popenFlag ? pclose(fp) : fclose(fp);
    if (rv)
    {
        QString s(tr("reading midifile\n  "));
        s += name;
        s += tr("\nfailed: ");
        s += mf.error();
        QMessageBox::critical(this, QString("LOS"), s);
        return rv;
    }
    //
    //  evaluate song Type (GM, XG, GS, unknown)
    //
    MType t = song->midiType();
    if (!merge)
    {
        t = mf.mtype();
        song->setMType(t);
    }
    MidiInstrument* instr = 0;
    for (iMidiInstrument i = midiInstruments.begin(); i != midiInstruments.end(); ++i)
    {
        MidiInstrument* mi = *i;
        if ((mi->iname() == "GM" && ((t == MT_UNKNOWN) || (t == MIDI_TYPE_GM)))
                || ((mi->iname() == "GS") && (t == MT_GS))
                || ((mi->iname() == "XG") && (t == MT_XG)))
        {
            instr = mi;
            break;
        }
    }
    if (instr == 0)
    {
        // the standard instrument files (GM, GS, XG) must be present
        printf("no instrument, type %d\n", t);
        return true;
        //abort();
    }

    MidiFileTrackList* etl = mf.trackList();
    int division = mf.division();

    //
    // create MidiTrack and copy events to ->events()
    //    - combine note on/off events
    //    - calculate tick value for internal resolution
    //
    int mPort = getFreeMidiPort();
    for (iMidiFileTrack t = etl->begin(); t != etl->end(); ++t)
    {
        MPEventList* el = &((*t)->events);
        if (el->empty())
            continue;
        //
        // if we split the track, SYSEX and META events go into
        // the first target track

        bool first = true;
        // somewhat silly and slooow:
        QList<QPair<int, int> > eventChannelList;
        if(mPort >= 0 && mPort < kMaxMidiPorts)
        {
            for (int channel = 0; channel < kMaxMidiChannels; ++channel)
            {
                //
                // check if there are any events for port/channel in track:
                //
                iMPEvent i;
                for (i = el->begin(); i != el->end(); ++i)
                {
                    MidiPlayEvent ev = *i;
                    if (ev.type() != ME_SYSEX && ev.type() != ME_META && ev.channel() == channel)
                        break;
                }
                if (i == el->end())
                    continue;
                MidiTrack* track = new MidiTrack();
                track->setDefaultName();
                track->setMasterFlag(true);

                track->setOutChannel(channel);
                track->setOutPort(mPort);

                MidiPort* mport = &midiPorts[track->outPort()];
                // this overwrites any instrument set for this port:
                mport->setInstrument(instr);

                EventList* mel = track->events();
                buildMidiEventList(mel, el, track, division, first, false, false);

                first = false;

                processTrack(track);

                song->insertTrack(track, -1);
                //Create the Audio input side of the track
                Track* input = song->addTrackByName(QString("i").append(track->name()), Track::AUDIO_INPUT, -1, false, false);
                if(input)
                {
                    input->setMasterFlag(false);
                    input->setChainMaster(track->id());
                    track->addManagedTrack(input->id());
                }
            }
        }
        if (first)
        {
            //
            // track does only contain non-channel messages
            // (SYSEX or META)
            //
            MidiTrack* track = new MidiTrack();
            track->setDefaultName();
            track->setMasterFlag(true);
            track->setOutChannel(0);
            track->setOutPort(mPort);
            EventList* mel = track->events();
            //buildMidiEventList(mel, el, track, division, true);
            // Do SysexMeta. Don't do loops.
            buildMidiEventList(mel, el, track, division, true, false, false);
            processTrack(track);
            song->insertTrack(track, -1);
            //Create the Audio input side of the track
            Track* input = song->addTrackByName(QString("i").append(track->name()), Track::AUDIO_INPUT, -1, false, false);
            if(input)
            {
                input->setMasterFlag(false);
                input->setChainMaster(track->id());
                track->addManagedTrack(input->id());
            }
        }
        mPort++;
        //FIXME: Provice a non-iterative way to do this using the new losMidiPorts hash
        //Or maintain a list of configured or inuse ports
        while((&midiPorts[mPort])->device() && mPort < kMaxMidiPorts)
            mPort++;//Just incase we have a configured port after an empty one
    }

    if (!merge)
    {
        TrackList* tl = song->tracks();
        if (!tl->empty())
        {
            Track* track = tl->front();
            track->setSelected(true);
        }
        song->initLen();

        int z, n;
        sigmap.timesig(0, z, n);

        int tempo = tempomap.tempo(0);
        transport->setTimesig(z, n);
        transport->setTempo(tempo);

        bool masterF = !tempomap.empty();
        song->setMasterFlag(masterF);
        transport->setMasterFlag(masterF);

        song->updatePos();

        composer->reset();
    }
    else
    {
        song->initLen();
    }

    return false;
}/*}}}*/