void initMidiPorts() { //TODO: Remove the need for this code //We should populate the losMidiPort hash with ports as we create them for (int i = 0; i < kMaxMidiPorts; ++i) { MidiPort* port = &midiPorts[i]; ///port->setInstrument(genericMidiInstrument); port->setInstrument(registerMidiInstrument("GM")); // Changed by Tim. } }
void initMidiPorts() { //TODO: Remove the need for this code //We should populate the oomMidiPort hash with ports as we create them for (int i = 0; i < MIDI_PORTS; ++i) { MidiPort* port = &midiPorts[i]; ///port->setInstrument(genericMidiInstrument); port->setInstrument(registerMidiInstrument("GM")); // Changed by Tim. port->syncInfo().setPort(i); } }
void MidiPort::setMidiDevice(MidiDevice* dev) { // close old device if (_device) { if (_device->isSynthPlugin()) { _instrument = genericMidiInstrument; } _device->setPort(-1); _device->close(); } // set-up new device if (dev) { for (int i = 0; i < MIDI_PORTS; ++i) { MidiPort* mp = &midiPorts[i]; if (mp->device() == dev) { if (dev->isSynthPlugin()) mp->setInstrument(genericMidiInstrument); // move device _state = mp->state(); mp->clearDevice(); break; } } _device = dev; if (_device->isSynthPlugin()) { SynthPluginDevice* s = (SynthPluginDevice*) _device; _instrument = s; //_instrument = genericMidiInstrument; } _state = _device->open(); _device->setPort(portno()); } else // dev is null, clear this device clearDevice(); }
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; } } }/*}}}*/
void MPConfig::rbClicked(QTableWidgetItem* item) { if (item == 0) return; QString id = item->tableWidget()->item(item->row(), DEVCOL_NO)->text(); int no = atoi(id.toLatin1().constData()) - 1; if (no < 0 || no >= kMaxMidiPorts) return; int n; MidiPort* port = &midiPorts[no]; MidiDevice* dev = port->device(); int rwFlags = dev ? dev->rwFlags() : 0; int openFlags = dev ? dev->openFlags() : 0; QTableWidget* listView = item->tableWidget(); QPoint ppt = listView->visualItemRect(item).bottomLeft(); QPoint mousepos = QCursor::pos(); int col = item->column(); ppt += QPoint(0, listView->horizontalHeader()->height()); ppt = listView->mapToGlobal(ppt); switch (col) { case DEVCOL_GUI: if (dev == 0) //break; return; // falkTX, we don't want this in the connections manager //if (port->hasGui()) //{ // port->instrument()->showGui(!port->guiVisible()); // item->setIcon(port->guiVisible() ? QIcon(*dotIcon) : QIcon(*dothIcon)); //} //break; return; case DEVCOL_CACHE_NRPN: if (!dev) return; dev->setCacheNRPN(!dev->cacheNRPN()); item->setIcon(dev->cacheNRPN() ? QIcon(*dotIcon) : QIcon(*dothIcon)); return; case DEVCOL_REC: if (dev == 0 || !(rwFlags & 2)) return; openFlags ^= 0x2; dev->setOpenFlags(openFlags); midiSeq->msgSetMidiDevice(port, dev); // reopen device item->setIcon(openFlags & 2 ? QIcon(*dotIcon) : QIcon(*dothIcon)); if (dev->deviceType() == MidiDevice::JACK_MIDI) { if (dev->openFlags() & 2) { item->tableWidget()->item(item->row(), DEVCOL_INROUTES)->setText(tr("in")); } else { item->tableWidget()->item(item->row(), DEVCOL_INROUTES)->setText(""); } } return; case DEVCOL_PLAY: if (dev == 0 || !(rwFlags & 1)) return; openFlags ^= 0x1; dev->setOpenFlags(openFlags); midiSeq->msgSetMidiDevice(port, dev); // reopen device item->setIcon(openFlags & 1 ? QIcon(*dotIcon) : QIcon(*dothIcon)); if (dev->deviceType() == MidiDevice::JACK_MIDI) { if (dev->openFlags() & 1) { item->tableWidget()->item(item->row(), DEVCOL_OUTROUTES)->setText(tr("out")); } else { item->tableWidget()->item(item->row(), DEVCOL_OUTROUTES)->setText(""); } } return; case DEVCOL_INROUTES: case DEVCOL_OUTROUTES: { if (!checkAudioDevice()) return; if (audioDevice->deviceType() != AudioDevice::JACK_AUDIO) //Only if Jack is running. return; if (!dev) return; // Only Jack midi devices. if (dev->deviceType() != MidiDevice::JACK_MIDI) return; if (!(dev->openFlags() & ((col == DEVCOL_OUTROUTES) ? 1 : 2))) return; RouteList* rl = (col == DEVCOL_OUTROUTES) ? dev->outRoutes() : dev->inRoutes(); // p3.3.55 QMenu* pup = 0; int gid = 0; std::list<QString> sl; pup = new QMenu(this); //A temporary Route to us for matching later QString currentRoute(""); bool routeSelected = false; _redisplay: pup->clear(); gid = 0; // Jack input ports if device is writable, and jack output ports if device is readable. sl = (col == DEVCOL_OUTROUTES) ? audioDevice->inputPorts(true, _showAliases) : audioDevice->outputPorts(true, _showAliases); QAction* act; act = pup->addAction(tr("Show first aliases")); act->setData(gid); act->setCheckable(true); act->setChecked(_showAliases == 0); ++gid; act = pup->addAction(tr("Show second aliases")); act->setData(gid); act->setCheckable(true); act->setChecked(_showAliases == 1); ++gid; pup->addSeparator(); for (std::list<QString>::iterator ip = sl.begin(); ip != sl.end(); ++ip) { act = pup->addAction(*ip); act->setData(gid); act->setCheckable(true); Route rt(*ip, (col == DEVCOL_OUTROUTES), -1, Route::JACK_ROUTE); for (iRoute ir = rl->begin(); ir != rl->end(); ++ir) { if (*ir == rt) { currentRoute = (*ir).name(); act->setChecked(true); routeSelected = true; break; } } ++gid; } act = pup->exec(ppt); if (act) { n = act->data().toInt(); if (n == 0) // Show first aliases { if (_showAliases == 0) _showAliases = -1; else _showAliases = 0; goto _redisplay; // Go back } else if (n == 1) // Show second aliases { if (_showAliases == 1) _showAliases = -1; else _showAliases = 1; goto _redisplay; // Go back } QString s(act->text()); if (col == DEVCOL_OUTROUTES) // Writable { Route srcRoute(dev, -1); Route dstRoute(s, true, -1, Route::JACK_ROUTE); if(routeSelected && currentRoute == s) { //it will alread be handled by an unchecked operation routeSelected = false; } iRoute iir = rl->begin(); for (; iir != rl->end(); ++iir) { if (*iir == dstRoute) break; } if (iir != rl->end()) { // disconnect audio->msgRemoveRoute(srcRoute, dstRoute); } else { // connect audio->msgAddRoute(srcRoute, dstRoute); } if(routeSelected) { iRoute selr = rl->begin(); for (; selr != rl->end(); ++selr) { //clean up the routing list as something was selected that was not the current so delete the old route if((*selr).name() == currentRoute) { audio->msgRemoveRoute(srcRoute, (*selr)); break; } } } } else { Route srcRoute(s, false, -1, Route::JACK_ROUTE); Route dstRoute(dev, -1); iRoute iir = rl->begin(); for (; iir != rl->end(); ++iir) { if (*iir == srcRoute) break; } if (iir != rl->end()) // disconnect audio->msgRemoveRoute(srcRoute, dstRoute); else // connect audio->msgAddRoute(srcRoute, dstRoute); } audio->msgUpdateSoloStates(); song->update(SC_ROUTE); } delete pup; } return; case DEVCOL_DEF_IN_CHANS: case DEVCOL_DEF_OUT_CHANS: { } //break; return; case DEVCOL_NAME: { //printf("MPConfig::rbClicked DEVCOL_NAME\n"); // Did we click in the text area? // NOTE: this needs the +15 pixels to make up for padding in the stylesheet. if ((mousepos.x() - (ppt.x() + 15)) > buttondownIcon->width()) { // Start the renaming of the cell... QModelIndex current = item->tableWidget()->currentIndex(); if (item->flags() & Qt::ItemIsEditable) item->tableWidget()->edit(current.sibling(current.row(), DEVCOL_NAME)); return; } else {// We clicked the 'down' button. QMenu* pup = new QMenu(this); QAction* act; act = pup->addAction(tr("Create") + QT_TRANSLATE_NOOP("@default", " Jack") + tr(" device")); act->setData(0); typedef std::map<std::string, int > asmap; typedef std::map<std::string, int >::iterator imap; asmap mapALSA; asmap mapJACK; int aix = 0x10000000; int jix = 0x20000000; for (iMidiDevice i = midiDevices.begin(); i != midiDevices.end(); ++i) { if ((*i)->deviceType() == MidiDevice::ALSA_MIDI) { mapALSA.insert(std::pair<std::string, int> (std::string((*i)->name().toLatin1().constData()), aix)); ++aix; } else if ((*i)->deviceType() == MidiDevice::JACK_MIDI) { mapJACK.insert(std::pair<std::string, int> (std::string((*i)->name().toLatin1().constData()), jix)); ++jix; } else printf("MPConfig::rbClicked unknown midi device: %s\n", (*i)->name().toLatin1().constData()); } pup->addSeparator(); pup->addAction(new MenuTitleItem(QT_TRANSLATE_NOOP("@default", "ALSA:"), pup)); for (imap i = mapALSA.begin(); i != mapALSA.end(); ++i) { int idx = i->second; QString s(i->first.c_str()); MidiDevice* md = midiDevices.find(s, MidiDevice::ALSA_MIDI); if (md) { if (md->deviceType() != MidiDevice::ALSA_MIDI) continue; act = pup->addAction(QT_TRANSLATE_NOOP("@default", md->name())); act->setData(idx); act->setCheckable(true); act->setChecked(md == dev); } } pup->addSeparator(); pup->addAction(new MenuTitleItem(QT_TRANSLATE_NOOP("@default", "JACK:"), pup)); for (imap i = mapJACK.begin(); i != mapJACK.end(); ++i) { int idx = i->second; QString s(i->first.c_str()); MidiDevice* md = midiDevices.find(s, MidiDevice::JACK_MIDI); if (md) { if (md->deviceType() != MidiDevice::JACK_MIDI) continue; act = pup->addAction(QT_TRANSLATE_NOOP("@default", md->name())); act->setData(idx); act->setCheckable(true); act->setChecked(md == dev); } } act = pup->exec(ppt); if (!act) { delete pup; return; } n = act->data().toInt(); //printf("MPConfig::rbClicked n:%d\n", n); MidiDevice* sdev = 0; if (n < 0x10000000) { delete pup; if (n <= 2) { sdev = MidiJackDevice::createJackMidiDevice(); if (sdev) { int of = 3; switch (n) { case 0: of = 0; //3; Set the open flags of the midiDevice this should be off by default break; case 1: of = 2; break; case 2: of = 1; break; } sdev->setOpenFlags(of); } } } else { int typ; if (n < 0x20000000) typ = MidiDevice::ALSA_MIDI; else if (n < 0x30000000) typ = MidiDevice::JACK_MIDI; else typ = MidiDevice::UNKNOWN_MIDI; sdev = midiDevices.find(act->text(), typ); delete pup; // Is it the current device? Reset it to <none>. // falkTX, handle synths properly here if (sdev == dev) { sdev = 0; } else { } } midiSeq->msgSetMidiDevice(port, sdev); los->changeConfig(true); // save configuration file song->update(); } } //break; return; case DEVCOL_INSTR: { if (instrPopup == 0) instrPopup = new QMenu(this); instrPopup->clear(); for (iMidiInstrument i = midiInstruments.begin(); i != midiInstruments.end(); ++i) { instrPopup->addAction((*i)->iname()); } QAction* act = instrPopup->exec(ppt, 0); if (!act) return; QString s = act->text(); item->tableWidget()->item(item->row(), DEVCOL_INSTR)->setText(s); for (iMidiInstrument i = midiInstruments.begin(); i != midiInstruments.end(); ++i) { if ((*i)->iname() == s) { port->setInstrument(*i); break; } } song->update(); } return; } }
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) // 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 // 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; }/*}}}*/
void GlobalSettingsConfig::apply() { int rtcticks = rtcResolutionSelect->currentIndex(); config.guiRefresh = guiRefreshSelect->value(); config.rtcTicks = rtcResolutions[rtcticks]; config.userInstrumentsDir = userInstrumentsPath->text(); config.startSong = startSongEntry->text(); config.startMode = startSongGroup->checkedId(); int div = midiDivisionSelect->currentIndex(); if (div < 0 || div > 9) div = 3; config.division = divisions[div]; config.useOldStyleStopShortCut = oldStyleStopCheckBox->isChecked(); config.moveArmedCheckBox = moveArmedCheckBox->isChecked(); config.useProjectSaveDialog = projectSaveCheckBox->isChecked(); losUserInstruments = config.userInstrumentsDir; //QList<QPair<int, QString> > oldList(gInputList); bool hasPorts = !gInputListPorts.isEmpty(); gInputList.clear(); for(int i = 0; i < m_inputsModel->rowCount(); ++i) { QStandardItem* item = m_inputsModel->item(i); if(item) { bool checked = (item->checkState() == Qt::Checked); QPair<int, QString> pinfo = qMakePair(item->data(Qt::UserRole+2).toInt(), item->data(Qt::UserRole+1).toString()); if(hasPorts) { bool found = false; int p = 0; MidiPort* mp = 0; for(p = 0;p < gInputListPorts.size(); p++) { mp = &midiPorts[gInputListPorts.at(p)]; if(mp && mp->device()->name() == pinfo.second) { found = true; break; } } if(!checked) {//Unconfigure if(found && mp) { //TODO:Clear routing list mp->setInstrument(registerMidiInstrument("GM")); midiSeq->msgSetMidiDevice(mp, 0); gInputListPorts.takeAt(p); } } else { if(!found) los->addGlobalInput(pinfo); gInputList.append(pinfo); } } else if(checked) { los->addGlobalInput(pinfo); gInputList.append(pinfo); } } } los->setHeartBeat(); // set guiRefresh midiSeq->msgSetRtc(); // set midi tick rate los->changeConfig(true); // save settings }