static void readSeqConfiguration(Xml& xml) { //bool updatePorts = false; for (;;) { Xml::Token token = xml.parse(); if (token == Xml::Error || token == Xml::End) break; const QString& tag = xml.s1(); switch (token) { case Xml::TagStart: if (tag == "midiport") { //updatePorts = true; readConfigMidiPort(xml); } else if (tag == "rcStop") rcStopNote = xml.parseInt(); else if (tag == "rcEnable") rcEnable = xml.parseInt(); else if (tag == "rcRecord") rcRecordNote = xml.parseInt(); else if (tag == "rcGotoLeft") rcGotoLeftMarkNote = xml.parseInt(); else if (tag == "rcPlay") rcPlayNote = xml.parseInt(); else xml.skip(tag); break; case Xml::TagEnd: if (tag == "sequencer") { //All Midiports have been read so put all the unconfigured ports in the id list //if(updatePorts) //{ for(int i = 0; i < MIDI_PORTS; ++i) { MidiPort *mp = &midiPorts[i]; if(!losMidiPorts.contains(mp->id())) losMidiPorts.insert(mp->id(), mp); } //} return; } default: break; } } }
//Midi Port Route Route::Route(int port, int ch) { track = 0; midiPort = port; channel = ch; channels = -1; remoteChannel = -1; type = MIDI_PORT_ROUTE; trackId = -1; if(midiPort >= 0 && midiPort < MIDI_PORTS) { MidiPort* mp = &midiPorts[midiPort]; midiPortId = mp->id(); } }
//Route From settings //Used mostly for restoring routes from the xml file Route::Route(const QString& s, bool dst, int ch, int rtype) { trackId = -1; midiPort = -1; midiPortId = -1; Route node(name2route(s, dst, rtype)); channel = node.channel; if (channel == -1) channel = ch; channels = node.channels; remoteChannel = node.remoteChannel; type = node.type; if (type == TRACK_ROUTE) { track = node.track; if(track) trackId = track->id(); } else if (type == JACK_ROUTE) { jackPort = node.jackPort; } else if (type == MIDI_DEVICE_ROUTE) { device = node.device; } else if (type == MIDI_PORT_ROUTE) { track = 0; midiPort = node.midiPort; if(midiPort >= 0 && midiPort < MIDI_PORTS) { MidiPort* mp = &midiPorts[midiPort]; midiPortId = mp->id(); } } }
static void writeSeqConfiguration(int level, Xml& xml, bool writePortInfo)/*{{{*/ { xml.tag(level++, "sequencer"); if (writePortInfo) { // // write information about all midi ports, their assigned // instruments and all managed midi controllers // for (int i = 0; i < MIDI_PORTS; ++i) { bool used = false; MidiPort* mport = &midiPorts[i]; // Route check by Tim. Port can now be used for routing even if no device. // Also, check for other non-defaults and save port, to preserve settings even if no device. // Dont write the config for the global inputs list they will be auto created with each startup if (mport->defaultInChannels() || mport->defaultOutChannels() || (mport->instrument() && !mport->instrument()->iname().isEmpty() && mport->instrument()->iname() != "GM") /*|| !mport->syncInfo().isDefault()*/ ) { used = true; } else {//Put the ID of this track into a list MidiTrackList* tl = song->midis(); for (iMidiTrack it = tl->begin(); it != tl->end(); ++it) { MidiTrack* t = *it; if (t->outPort() == i) { used = true; break; } } } MidiDevice* dev = mport->device(); if (!used && !dev) continue; bool isGlobal = gInputListPorts.contains(mport->portno()); xml.tag(level++, "midiport portId=\"%lld\" isGlobalInput=\"%d\"", mport->id(), isGlobal); if (mport->defaultInChannels()) xml.intTag(level, "defaultInChans", mport->defaultInChannels()); if (mport->defaultOutChannels()) xml.intTag(level, "defaultOutChans", mport->defaultOutChannels()); if (mport->instrument() && !mport->instrument()->iname().isEmpty() && (mport->instrument()->iname() != "GM")) // FIXME: TODO: Make this user configurable. { xml.strTag(level, "instrument", mport->instrument()->iname()); } if (dev) { xml.strTag(level, "name", dev->name()); xml.intTag(level, "cacheNRPN", (int)dev->cacheNRPN()); if (dev->deviceType() != MidiDevice::ALSA_MIDI) xml.intTag(level, "type", dev->deviceType()); xml.intTag(level, "openFlags", dev->openFlags()); } // write out registered controller for all channels MidiCtrlValListList* vll = mport->controller(); for (int k = 0; k < MIDI_CHANNELS; ++k) { int min = k << 24; int max = min + 0x100000; xml.tag(level++, "channel idx=\"%d\"", k); iMidiCtrlValList s = vll->lower_bound(min); iMidiCtrlValList e = vll->lower_bound(max); if (s != e) { for (iMidiCtrlValList i = s; i != e; ++i) { if(i->second->num() != 262145) { xml.tag(level++, "controller id=\"%d\"", i->second->num()); if (i->second->hwVal() != CTRL_VAL_UNKNOWN) xml.intTag(level, "val", i->second->hwVal()); xml.etag(--level, "controller"); } } } xml.etag(--level, "channel"); } QList<PatchSequence*> *patchSequences = mport->patchSequences(); if (patchSequences && !patchSequences->isEmpty()) { for (int p = 0; p < patchSequences->size(); ++p) { PatchSequence* ps = patchSequences->at(p); QString pm = ps->name.replace('\n', " "); xml.put(level, "<patchSequence id=\"%d\" name=\"%s\" checked=\"%d\" />", ps->id, pm.toLatin1().constData(), ps->selected); } } if(!mport->presets()->isEmpty()) { QHashIterator<int, QString> iter(*mport->presets()); while(iter.hasNext()) { iter.next(); xml.put(level, "<midiPreset id=\"%d\" sysex=\"%s\"/>", iter.key(), iter.value().toLatin1().constData()); } } xml.etag(--level, "midiport"); } } xml.tag(--level, "/sequencer"); }/*}}}*/
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 Route::read(Xml& xml)/*{{{*/ { QString s; int dtype = MidiDevice::ALSA_MIDI; int port = -1; unsigned char rtype = Route::TRACK_ROUTE; for (;;) { const QString& tag = xml.s1(); Xml::Token token = xml.parse(); switch (token) { case Xml::Error: case Xml::End: return; case Xml::Attribut: #ifdef ROUTE_DEBUG printf("Route::read(): attribute:%s\n", tag.toLatin1().constData()); #endif if (tag == "type") rtype = xml.s2().toInt(); else if (tag == "devtype") { dtype = xml.s2().toInt(); rtype = Route::MIDI_DEVICE_ROUTE; } else if (tag == "name") s = xml.s2(); else if(tag == "trackId") { trackId = xml.s2().toLongLong(); rtype = Route::TRACK_ROUTE; } else if (tag == "mport") // p3.3.49 { port = xml.s2().toInt(); rtype = Route::MIDI_PORT_ROUTE; } else if(tag == "mportId") { midiPortId = xml.s2().toLongLong(); rtype = Route::MIDI_PORT_ROUTE; } else printf("Route::read(): unknown attribute:%s\n", tag.toLatin1().constData()); break; case Xml::TagEnd: #ifdef ROUTE_DEBUG printf("Route::read(): tag end type:%d channel:%d name:%s\n", rtype, channel, s.toLatin1().constData()); #endif if (rtype == MIDI_PORT_ROUTE) { if(midiPortId > 0) { //qDebug("Route::read(): MIDI_PORT_ROUTE Finding midiport from id"); type = rtype; MidiPort *mp = oomMidiPorts.value(midiPortId); if(mp) { midiPort = mp->portno(); //qDebug("Route::read(): Found midiport from id: %d", midiPort); } } else if (port >= 0 && port < MIDI_PORTS) { type = rtype; midiPort = port; MidiPort *mp = &midiPorts[midiPort]; midiPortId = mp->id(); } else printf("Route::read(): midi port <%d> out of range\n", port); } else if (!s.isEmpty()) { if (rtype == TRACK_ROUTE) { if(trackId > 0) { track = song->findTrackById(trackId); type = rtype; } else { TrackList* tl = song->tracks(); iTrack i = tl->begin(); for (; i != tl->end(); ++i) { Track* t = *i; if (t->name() == s) { track = t; type = rtype; trackId = t->id(); break; } } if (i == tl->end()) printf("Route::read(): track <%s> not found\n", s.toLatin1().constData()); } } else if (rtype == JACK_ROUTE) { void* jport = 0; if (audioDevice) //Fix from Robert at muse jport = audioDevice->findPort(s.toLatin1().constData()); if (jport == 0) printf("Route::read(): jack port <%s> not found audioDevice(%p)\n", s.toLatin1().constData(), audioDevice); else { jackPort = jport; type = rtype; } } else if (rtype == MIDI_DEVICE_ROUTE) { iMidiDevice imd = midiDevices.begin(); for (; imd != midiDevices.end(); ++imd) { MidiDevice* md = *imd; if (md->name() == s && md->deviceType() == dtype) { // We found a device, but if it is not in use by the song (port is -1), ignore it. // This prevents loading and propagation of bogus routes in the oom file. if (md->midiPort() == -1) break; device = md; type = rtype; break; } } if (imd == midiDevices.end()) printf("Route::read(): midi device <%s> not found\n", s.toLatin1().constData()); } } return; default: break; } } }/*}}}*/