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; }/*}}}*/
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 // 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: for (int port = 0; port < kMaxMidiPorts; ++port) { 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 && ev.port() == port) break; } if (i == el->end()) continue; MidiTrack* track = new MidiTrack(); if ((*t)->isDrumTrack) { track->setType(Track::DRUM); } track->setOutChannel(channel); track->setOutPort(port); 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); // Don't do loops. buildMidiEventList(mel, el, track, division, first, false); first = false; // Hmm. buildMidiEventList already takes care of this. // But it seems to work. How? Must test. if (channel == 9 && song->midiType() != MT_UNKNOWN) { track->setType(Track::DRUM); // // remap drum pitch with drumInmap // EventList* tevents = track->events(); for (iEvent i = tevents->begin(); i != tevents->end(); ++i) { Event ev = i->second; if (ev.isNote()) { int pitch = drumInmap[ev.pitch()]; ev.setPitch(pitch); } else if (ev.type() == Controller) { int ctl = ev.dataA(); MidiController *mc = mport->drumController(ctl); if (mc) ev.setA((ctl & ~0xff) | drumInmap[ctl & 0x7f]); } } } processTrack(track); song->insertTrack(track, -1); } } if (first) { // // track does only contain non-channel messages // (SYSEX or META) // MidiTrack* track = new MidiTrack(); track->setOutChannel(0); track->setOutPort(0); EventList* mel = track->events(); //buildMidiEventList(mel, el, track, division, true); // Do SysexMeta. Don't do loops. buildMidiEventList(mel, el, track, division, true, false); processTrack(track); song->insertTrack(track, -1); } } 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); 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(); ///composer->setMode(int(song->midiType())); // p4.0.7 Tim } else { song->initLen(); } return false; }/*}}}*/
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; }/*}}}*/