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; } }