From 250b9712f41aacb2b5dc3660878b55b5935f2c6f Mon Sep 17 00:00:00 2001 From: "Tim E. Real" Date: Sat, 16 Oct 2010 02:08:48 +0000 Subject: See ChangeLog --- muse2/ChangeLog | 11 + muse2/muse/audio.cpp | 5 +- muse2/muse/audio.h | 4 +- muse2/muse/conf.cpp | 3 +- muse2/muse/confmport.cpp | 178 +++++++++++++---- muse2/muse/driver/alsamidi.h | 9 +- muse2/muse/driver/jack.cpp | 378 +++++++++++++++++++---------------- muse2/muse/driver/jackmidi.cpp | 233 +++++++++++++++++---- muse2/muse/driver/jackmidi.h | 26 ++- muse2/muse/globals.h | 4 + muse2/muse/mididev.cpp | 5 +- muse2/muse/mididev.h | 6 +- muse2/muse/route.cpp | 58 +++++- muse2/muse/route.h | 1 + muse2/muse/seqmsg.cpp | 92 ++++++++- muse2/muse/widgets/mtrackinfobase.ui | 2 +- 16 files changed, 747 insertions(+), 268 deletions(-) diff --git a/muse2/ChangeLog b/muse2/ChangeLog index a5cd7d5e..dc967e0f 100644 --- a/muse2/ChangeLog +++ b/muse2/ChangeLog @@ -1,3 +1,14 @@ +15.10.2010 + * Feature: Unified Jack midi devices in midi ports list. Can be both input and output, just like ALSA devices. (T356) + - Marked as p3.3.55 + * Corrected: Three things which did not compile in conversion to new muse-2: (T356) + - true -> true in mtrackinfobase.ui, for recEchoButton toggleButton property. (T356) + - Surround with QString(): "strerror(errno)" in MusE::save(), and "incstr" in MidiDeviceList::add(). (T356) +14.10.2010 + ======================================= + * muse2 branch (Conversion to QT4, QT3 compatibility mode for now) checked in (rj) (T356) + ======================================= + 09.10.2010 * Fixed: Gluing of midi track parts, over tempo changes, caused incorrect note times and lengths. (T356) - Fixed Song::cmdGluePart(). diff --git a/muse2/muse/audio.cpp b/muse2/muse/audio.cpp index 9a7029db..f38bcc9c 100644 --- a/muse2/muse/audio.cpp +++ b/muse2/muse/audio.cpp @@ -64,7 +64,7 @@ const char* seqMsgList[] = { "SEQM_UPDATE_SOLO_STATES", "MIDI_SHOW_INSTR_GUI", "AUDIO_RECORD", - "AUDIO_ROUTEADD", "AUDIO_ROUTEREMOVE", + "AUDIO_ROUTEADD", "AUDIO_ROUTEREMOVE", "AUDIO_REMOVEROUTES", "AUDIO_VOL", "AUDIO_PAN", "AUDIO_ADDPLUGIN", "AUDIO_SET_SEG_SIZE", @@ -625,6 +625,9 @@ void Audio::processMsg(AudioMsg* msg) case AUDIO_ROUTEREMOVE: removeRoute(msg->sroute, msg->droute); break; + case AUDIO_REMOVEROUTES: // p3.3.55 + removeAllRoutes(msg->sroute, msg->droute); + break; case AUDIO_VOL: msg->snode->setVolume(msg->dval); break; diff --git a/muse2/muse/audio.h b/muse2/muse/audio.h index fb51ca03..ba188f8a 100644 --- a/muse2/muse/audio.h +++ b/muse2/muse/audio.h @@ -59,7 +59,7 @@ enum { SEQM_UPDATE_SOLO_STATES, MIDI_SHOW_INSTR_GUI, AUDIO_RECORD, - AUDIO_ROUTEADD, AUDIO_ROUTEREMOVE, + AUDIO_ROUTEADD, AUDIO_ROUTEREMOVE, AUDIO_REMOVEROUTES, AUDIO_VOL, AUDIO_PAN, AUDIO_ADDPLUGIN, AUDIO_SET_SEG_SIZE, @@ -223,6 +223,8 @@ class Audio { bool sendMessage(AudioMsg* m, bool doUndo); void msgRemoveRoute(Route, Route); void msgRemoveRoute1(Route, Route); + void msgRemoveRoutes(Route, Route); // p3.3.55 + void msgRemoveRoutes1(Route, Route); // p3.3.55 void msgAddRoute(Route, Route); void msgAddRoute1(Route, Route); void msgAddPlugin(AudioTrack*, int idx, PluginI* plugin); diff --git a/muse2/muse/conf.cpp b/muse2/muse/conf.cpp index c44665e1..c3552bd9 100644 --- a/muse2/muse/conf.cpp +++ b/muse2/muse/conf.cpp @@ -276,7 +276,8 @@ static void readConfigMidiPort(Xml& xml) { if(debugMsg) fprintf(stderr, "readConfigMidiPort: creating jack midi device %s\n", device.latin1()); - dev = MidiJackDevice::createJackMidiDevice(device, openFlags); + //dev = MidiJackDevice::createJackMidiDevice(device, openFlags); + dev = MidiJackDevice::createJackMidiDevice(device); // p3.3.55 } if(debugMsg && !dev) diff --git a/muse2/muse/confmport.cpp b/muse2/muse/confmport.cpp index bea2e714..422de8cd 100644 --- a/muse2/muse/confmport.cpp +++ b/muse2/muse/confmport.cpp @@ -57,7 +57,8 @@ extern std::vector synthis; enum { DEVCOL_NO = 0, DEVCOL_GUI, DEVCOL_REC, DEVCOL_PLAY, DEVCOL_INSTR, DEVCOL_NAME, //DEVCOL_STATE }; - DEVCOL_ROUTES, DEVCOL_STATE }; + //DEVCOL_ROUTES, DEVCOL_STATE }; + DEVCOL_INROUTES, DEVCOL_OUTROUTES, DEVCOL_STATE }; // p3.3.55 //--------------------------------------------------------- // mdevViewItemRenamed @@ -156,6 +157,22 @@ void MPConfig::rbClicked(Q3ListViewItem* item, const QPoint& cpt, int col) dev->setOpenFlags(openFlags); midiSeq->msgSetMidiDevice(port, dev); // reopen device item->setPixmap(DEVCOL_REC, openFlags & 2 ? *dotIcon : *dothIcon); + + // p3.3.55 + if(dev->deviceType() == MidiDevice::JACK_MIDI) + { + if(dev->openFlags() & 2) + { + //item->setPixmap(DEVCOL_INROUTES, *buttondownIcon); + item->setText(DEVCOL_INROUTES, tr("in")); + } + else + { + //item->setPixmap(DEVCOL_INROUTES, *buttondownIcon); + item->setText(DEVCOL_INROUTES, ""); + } + } + //break; return; @@ -167,10 +184,28 @@ void MPConfig::rbClicked(Q3ListViewItem* item, const QPoint& cpt, int col) dev->setOpenFlags(openFlags); midiSeq->msgSetMidiDevice(port, dev); // reopen device item->setPixmap(DEVCOL_PLAY, openFlags & 1 ? *dotIcon : *dothIcon); + + // p3.3.55 + if(dev->deviceType() == MidiDevice::JACK_MIDI) + { + if(dev->openFlags() & 1) + { + //item->setPixmap(DEVCOL_OUTROUTES, *buttondownIcon); + item->setText(DEVCOL_OUTROUTES, tr("out")); + } + else + { + //item->setPixmap(DEVCOL_OUTROUTES, *buttondownIcon); + item->setText(DEVCOL_OUTROUTES, ""); + } + } + //break; return; - case DEVCOL_ROUTES: + //case DEVCOL_ROUTES: + case DEVCOL_INROUTES: // p3.3.55 + case DEVCOL_OUTROUTES: { if(!checkAudioDevice()) return; @@ -187,10 +222,13 @@ void MPConfig::rbClicked(Q3ListViewItem* item, const QPoint& cpt, int col) if(dev->deviceType() != MidiDevice::JACK_MIDI) return; - if(!dev->rwFlags() & 3) + //if(!(dev->rwFlags() & 3)) + //if(!(dev->rwFlags() & ((col == DEVCOL_OUTROUTES) ? 1 : 2))) // p3.3.55 + if(!(dev->openFlags() & ((col == DEVCOL_OUTROUTES) ? 1 : 2))) return; - RouteList* rl = (dev->rwFlags() & 1) ? dev->outRoutes() : dev->inRoutes(); + //RouteList* rl = (dev->rwFlags() & 1) ? dev->outRoutes() : dev->inRoutes(); + RouteList* rl = (col == DEVCOL_OUTROUTES) ? dev->outRoutes() : dev->inRoutes(); // p3.3.55 Q3PopupMenu* pup = 0; int gid = 0; @@ -204,7 +242,9 @@ void MPConfig::rbClicked(Q3ListViewItem* item, const QPoint& cpt, int col) gid = 0; // Jack input ports if device is writable, and jack output ports if device is readable. - sl = (dev->rwFlags() & 1) ? audioDevice->inputPorts(true, _showAliases) : audioDevice->outputPorts(true, _showAliases); + //sl = (dev->rwFlags() & 1) ? audioDevice->inputPorts(true, _showAliases) : audioDevice->outputPorts(true, _showAliases); + // p3.3.55 + sl = (col == DEVCOL_OUTROUTES) ? audioDevice->inputPorts(true, _showAliases) : audioDevice->outputPorts(true, _showAliases); //for (int i = 0; i < channel; ++i) //{ @@ -226,7 +266,8 @@ void MPConfig::rbClicked(Q3ListViewItem* item, const QPoint& cpt, int col) //int id = pup->insertItem(*ip, gid); pup->insertItem(*ip, gid); //Route dst(*ip, true, i); - Route rt(*ip, (dev->rwFlags() & 1), -1, Route::JACK_ROUTE); + //Route rt(*ip, (dev->rwFlags() & 1), -1, Route::JACK_ROUTE); + Route rt(*ip, (col == DEVCOL_OUTROUTES), -1, Route::JACK_ROUTE); // p3.3.55 for(iRoute ir = rl->begin(); ir != rl->end(); ++ir) { if (*ir == rt) @@ -267,7 +308,8 @@ void MPConfig::rbClicked(Q3ListViewItem* item, const QPoint& cpt, int col) QString s(pup->text(n)); - if(dev->rwFlags() & 1) // Writable + //if(dev->rwFlags() & 1) // Writable + if(col == DEVCOL_OUTROUTES) // Writable p3.3.55 { Route srcRoute(dev, -1); Route dstRoute(s, true, -1, Route::JACK_ROUTE); @@ -286,7 +328,8 @@ void MPConfig::rbClicked(Q3ListViewItem* item, const QPoint& cpt, int col) audio->msgAddRoute(srcRoute, dstRoute); } else - if(dev->rwFlags() & 2) // Readable + //if(dev->rwFlags() & 2) // Readable + //if(col == DEVCOL_INROUTES) // Readable p3.3.55 { Route srcRoute(s, false, -1, Route::JACK_ROUTE); Route dstRoute(dev, -1); @@ -344,8 +387,12 @@ void MPConfig::rbClicked(Q3ListViewItem* item, const QPoint& cpt, int col) pup->setCheckable(true); - pup->insertItem(tr("Create") + QT_TR_NOOP(" Jack") + tr(" input"), 0); - pup->insertItem(tr("Create") + QT_TR_NOOP(" Jack") + tr(" output"), 1); + // Could do it this way... + //pup->insertItem(tr("Create") + QT_TR_NOOP(" Jack") + tr(" input"), 1); + //pup->insertItem(tr("Create") + QT_TR_NOOP(" Jack") + tr(" output"), 2); + //pup->insertItem(tr("Create") + QT_TR_NOOP(" Jack") + tr(" combo"), 0); // p3.3.55 + // ... or keep it simple and let the user click on the green lights instead. + pup->insertItem(tr("Create") + QT_TR_NOOP(" Jack") + tr(" device"), 0); // typedef std::map asmap; typedef std::map::iterator imap; @@ -354,9 +401,9 @@ void MPConfig::rbClicked(Q3ListViewItem* item, const QPoint& cpt, int col) asmap mapJACK; asmap mapSYNTH; - int aix = 2; - int jix = 0x10000000; - int six = 0x20000000; + int aix = 0x10000000; + int jix = 0x20000000; + int six = 0x30000000; for(iMidiDevice i = midiDevices.begin(); i != midiDevices.end(); ++i) { //devALSA = dynamic_cast(*i); @@ -387,7 +434,7 @@ void MPConfig::rbClicked(Q3ListViewItem* item, const QPoint& cpt, int col) } //int sz = midiDevices.size(); - if(!mapALSA.empty()) + //if(!mapALSA.empty()) { pup->insertSeparator(); // pup->insertItem(new MenuTitleItem(QT_TR_NOOP("ALSA:"))); ddskrjo @@ -424,22 +471,22 @@ void MPConfig::rbClicked(Q3ListViewItem* item, const QPoint& cpt, int col) } } - if(!mapJACK.empty()) + if(!mapSYNTH.empty()) { pup->insertSeparator(); - //pup->insertItem(new MenuTitleItem(QT_TR_NOOP("JACK:"))); ddskrjo + //pup->insertItem(new MenuTitleItem(QT_TR_NOOP("SYNTH:"))); ddskrjo - for(imap i = mapJACK.begin(); i != mapJACK.end(); ++i) + for(imap i = mapSYNTH.begin(); i != mapSYNTH.end(); ++i) { int idx = i->second; //if(idx > sz) // continue; QString s(i->first.c_str()); - MidiDevice* md = midiDevices.find(s, MidiDevice::JACK_MIDI); + MidiDevice* md = midiDevices.find(s, MidiDevice::SYNTH_MIDI); if(md) { //if(!dynamic_cast(md)) - if(md->deviceType() != MidiDevice::JACK_MIDI) + if(md->deviceType() != MidiDevice::SYNTH_MIDI) continue; //pup->insertItem(QT_TR_NOOP(md->name()), idx + 3); @@ -461,22 +508,27 @@ void MPConfig::rbClicked(Q3ListViewItem* item, const QPoint& cpt, int col) } } - if(!mapSYNTH.empty()) + //if(!mapJACK.empty()) { pup->insertSeparator(); - //pup->insertItem(new MenuTitleItem(QT_TR_NOOP("SYNTH:"))); ddskrjo + //pup->insertItem(new MenuTitleItem(QT_TR_NOOP("JACK:"))); ddskrjo - for(imap i = mapSYNTH.begin(); i != mapSYNTH.end(); ++i) + //pup->insertItem(tr(""), 1); + //pup->insertItem(tr(""), 2); + //pup->insertItem(tr(""), 0); // p3.3.55 + //pup->insertSeparator(); + + for(imap i = mapJACK.begin(); i != mapJACK.end(); ++i) { int idx = i->second; //if(idx > sz) // continue; QString s(i->first.c_str()); - MidiDevice* md = midiDevices.find(s, MidiDevice::SYNTH_MIDI); + MidiDevice* md = midiDevices.find(s, MidiDevice::JACK_MIDI); if(md) { //if(!dynamic_cast(md)) - if(md->deviceType() != MidiDevice::SYNTH_MIDI) + if(md->deviceType() != MidiDevice::JACK_MIDI) continue; //pup->insertItem(QT_TR_NOOP(md->name()), idx + 3); @@ -496,7 +548,7 @@ void MPConfig::rbClicked(Q3ListViewItem* item, const QPoint& cpt, int col) //} } } - } + } n = pup->exec(ppt, 0); if(n == -1) @@ -509,21 +561,43 @@ void MPConfig::rbClicked(Q3ListViewItem* item, const QPoint& cpt, int col) //printf("MPConfig::rbClicked n:%d\n", n); MidiDevice* sdev = 0; - if(n < 2) + if(n < 0x10000000) { delete pup; - if(n == 0) - sdev = MidiJackDevice::createJackMidiDevice(QString(), 2); // 2: Readable. - else - if(n == 1) - sdev = MidiJackDevice::createJackMidiDevice(QString(), 1); // 1:Writable. + //if(n == 0) // p3.3.55 + // sdev = MidiJackDevice::createJackMidiDevice(QString(), 3); // 3:Readable/Writable. + //else + //if(n == 1) + // sdev = MidiJackDevice::createJackMidiDevice(QString(), 2); // 2: Readable. + //else + //if(n == 2) + // sdev = MidiJackDevice::createJackMidiDevice(QString(), 1); // 1:Writable. + if(n <= 2) // p3.3.55 + { + sdev = MidiJackDevice::createJackMidiDevice(); + if(sdev) + { + int of = 3; + switch(n) + { + case 0: of = 3; break; + case 1: of = 2; break; + case 2: of = 1; break; + } + sdev->setOpenFlags(of); + } + } } else { - int typ = MidiDevice::ALSA_MIDI; - if(n >= 0x10000000) + int typ; + if(n < 0x20000000) + typ = MidiDevice::ALSA_MIDI; + else + if(n < 0x30000000) typ = MidiDevice::JACK_MIDI; - if(n >= 0x20000000) + else + //if(n < 0x40000000) typ = MidiDevice::SYNTH_MIDI; sdev = midiDevices.find(pup->text(n), typ); @@ -603,7 +677,9 @@ void MPHeaderTip::maybeTip(const QPoint &pos) case DEVCOL_PLAY: p = Q3Header::tr("Enable writing"); break; case DEVCOL_INSTR: p = Q3Header::tr("Port instrument"); break; case DEVCOL_NAME: p = Q3Header::tr("Midi device name. Click to edit (Jack)"); break; - case DEVCOL_ROUTES: p = Q3Header::tr("Jack midi ports"); break; + //case DEVCOL_ROUTES: p = Q3Header::tr("Jack midi ports"); break; + case DEVCOL_INROUTES: p = Q3Header::tr("Connections from Jack Midi outputs"); break; + case DEVCOL_OUTROUTES: p = Q3Header::tr("Connections to Jack Midi inputs"); break; case DEVCOL_STATE: p = Q3Header::tr("Device state"); break; default: return; } @@ -634,8 +710,12 @@ QString MPWhatsThis::text(const QPoint& pos) " this port number. Click to edit Jack midi name."); case DEVCOL_INSTR: return Q3Header::tr("Instrument connected to port"); - case DEVCOL_ROUTES: - return Q3Header::tr("Jack midi ports"); + //case DEVCOL_ROUTES: + // return Q3Header::tr("Jack midi ports"); + case DEVCOL_INROUTES: + return Q3Header::tr("Connections from Jack Midi output ports"); + case DEVCOL_OUTROUTES: + return Q3Header::tr("Connections to Jack Midi input ports"); case DEVCOL_STATE: return Q3Header::tr("State: result of opening the device"); default: @@ -665,7 +745,9 @@ MPConfig::MPConfig(QWidget* parent, char* name) mdevView->addColumn(tr("O")); mdevView->addColumn(tr("Instrument"), 120); mdevView->addColumn(tr("Device Name"), 120); - mdevView->addColumn(tr("Routing"), 80); + //mdevView->addColumn(tr("Routing"), 80); + mdevView->addColumn(tr("In routes"), 80); + mdevView->addColumn(tr("Out routes"), 80); mdevView->addColumn(tr("State")); mdevView->setFocusPolicy(Qt::NoFocus); @@ -784,8 +866,24 @@ void MPConfig::songChanged(int flags) //if(dev && dynamic_cast(dev)) if(dev && dev->deviceType() == MidiDevice::JACK_MIDI) { - item->setPixmap(DEVCOL_ROUTES, *buttondownIcon); - item->setText(DEVCOL_ROUTES, tr("routes")); + //item->setPixmap(DEVCOL_ROUTES, *buttondownIcon); + //item->setText(DEVCOL_ROUTES, tr("routes")); + + // p3.3.55 + if(dev->rwFlags() & 1) + //if(dev->openFlags() & 1) + { + item->setPixmap(DEVCOL_OUTROUTES, *buttondownIcon); + if(dev->openFlags() & 1) + item->setText(DEVCOL_OUTROUTES, tr("out")); + } + if(dev->rwFlags() & 2) + //if(dev->openFlags() & 2) + { + item->setPixmap(DEVCOL_INROUTES, *buttondownIcon); + if(dev->openFlags() & 2) + item->setText(DEVCOL_INROUTES, tr("in")); + } } mdevView->insertItem(item); diff --git a/muse2/muse/driver/alsamidi.h b/muse2/muse/driver/alsamidi.h index 6c19ff0d..455ab1df 100644 --- a/muse2/muse/driver/alsamidi.h +++ b/muse2/muse/driver/alsamidi.h @@ -34,10 +34,15 @@ class MidiAlsaDevice : public MidiDevice { virtual bool putMidiEvent(const MidiPlayEvent&); public: - MidiAlsaDevice() {} + //MidiAlsaDevice() {} // p3.3.55 Removed MidiAlsaDevice(const snd_seq_addr_t&, const QString& name); virtual ~MidiAlsaDevice() {} - virtual void* clientPort() { return (void*)&adr; } + + //virtual void* clientPort() { return (void*)&adr; } + // p3.3.55 + virtual void* inClientPort() { return (void*)&adr; } // For ALSA midi, in/out client ports are the same. + virtual void* outClientPort() { return (void*)&adr; } // That is, ALSA midi client ports can be both r/w. + virtual void writeRouting(int, Xml&) const; virtual inline int deviceType() { return ALSA_MIDI; } }; diff --git a/muse2/muse/driver/jack.cpp b/muse2/muse/driver/jack.cpp index 2c5081fc..e23f2de8 100644 --- a/muse2/muse/driver/jack.cpp +++ b/muse2/muse/driver/jack.cpp @@ -704,19 +704,29 @@ void JackAudioDevice::connectJackMidiPorts() if(md->deviceType() != MidiDevice::JACK_MIDI) continue; - void* port = md->clientPort(); + //void* port = md->clientPort(); if(md->rwFlags() & 1) { - RouteList* rl = md->outRoutes(); - for (iRoute r = rl->begin(); r != rl->end(); ++r) - connect(port, r->jackPort); + void* port = md->outClientPort(); // p3.3.55 + if(port) // + { + RouteList* rl = md->outRoutes(); + for (iRoute r = rl->begin(); r != rl->end(); ++r) + connect(port, r->jackPort); + } } - else + + // else // p3.3.55 Removed + if(md->rwFlags() & 2) { - RouteList* rl = md->inRoutes(); - for (iRoute r = rl->begin(); r != rl->end(); ++r) - connect(r->jackPort, port); + void* port = md->inClientPort(); // p3.3.55 + if(port) // + { + RouteList* rl = md->inRoutes(); + for (iRoute r = rl->begin(); r != rl->end(); ++r) + connect(r->jackPort, port); + } } } @@ -1066,10 +1076,12 @@ void JackAudioDevice::graphChanged() // continue; //for (int channel = 0; channel < channels; ++channel) //{ - jack_port_t* port = (jack_port_t*)md->clientPort(); - if (port == 0) - continue; - const char** ports = jack_port_get_all_connections(_client, port); + + // p3.3.55 Removed + //jack_port_t* port = (jack_port_t*)md->clientPort(); + //if (port == 0) + // continue; + //const char** ports = jack_port_get_all_connections(_client, port); //--------------------------------------- // outputs @@ -1077,87 +1089,95 @@ void JackAudioDevice::graphChanged() if(md->rwFlags() & 1) // Writable { - RouteList* rl = md->outRoutes(); - - //--------------------------------------- - // check for disconnects - //--------------------------------------- - - bool erased; - // limit set to 20 iterations for disconnects, don't know how to make it go - // the "right" amount - for (int i = 0; i < 20 ; i++) - { - erased = false; - for (iRoute irl = rl->begin(); irl != rl->end(); ++irl) { - //if (irl->channel != channel) - // continue; - QString name = irl->name(); - const char* portName = name.latin1(); - bool found = false; - const char** pn = ports; - while (pn && *pn) { - if (strcmp(*pn, portName) == 0) { - found = true; - break; - } - ++pn; - } - if (!found) { - audio->msgRemoveRoute1( - //Route(it, channel), - //Route(mjd), - Route(md, -1), - //Route(portName, false, channel) - //Route(portName, false, -1) - Route(portName, false, -1, Route::JACK_ROUTE) - ); - erased = true; - break; - } - } - if (!erased) - break; - } - - //--------------------------------------- - // check for connects - //--------------------------------------- - - if (ports) + // p3.3.55 + jack_port_t* port = (jack_port_t*)md->outClientPort(); + if(port != 0) { - const char** pn = ports; - while (*pn) { - bool found = false; - for (iRoute irl = rl->begin(); irl != rl->end(); ++irl) { - //if (irl->channel != channel) - // continue; - QString name = irl->name(); - const char* portName = name.latin1(); - if (strcmp(*pn, portName) == 0) { - found = true; - break; - } - } - if (!found) { - audio->msgAddRoute1( - //Route(it, channel), - //Route(mjd), - Route(md, -1), - //Route(*pn, false, channel) - //Route(*pn, false, -1) - Route(*pn, false, -1, Route::JACK_ROUTE) - ); - } - ++pn; - } - - // p3.3.37 - //delete ports; - //free(ports); - - //ports = NULL; - } + //printf("graphChanged() valid out client port\n"); // p3.3.55 + + const char** ports = jack_port_get_all_connections(_client, port); + + RouteList* rl = md->outRoutes(); + + //--------------------------------------- + // check for disconnects + //--------------------------------------- + + bool erased; + // limit set to 20 iterations for disconnects, don't know how to make it go + // the "right" amount + for (int i = 0; i < 20 ; i++) + { + erased = false; + for (iRoute irl = rl->begin(); irl != rl->end(); ++irl) { + //if (irl->channel != channel) + // continue; + QString name = irl->name(); + //name += QString(JACK_MIDI_OUT_PORT_SUFFIX); // p3.3.55 + const char* portName = name.latin1(); + bool found = false; + const char** pn = ports; + while (pn && *pn) { + if (strcmp(*pn, portName) == 0) { + found = true; + break; + } + ++pn; + } + if (!found) { + audio->msgRemoveRoute1( + //Route(it, channel), + //Route(mjd), + Route(md, -1), + //Route(portName, false, channel) + //Route(portName, false, -1) + Route(portName, false, -1, Route::JACK_ROUTE) + ); + erased = true; + break; + } + } + if (!erased) + break; + } + + //--------------------------------------- + // check for connects + //--------------------------------------- + + if (ports) + { + const char** pn = ports; + while (*pn) { + bool found = false; + for (iRoute irl = rl->begin(); irl != rl->end(); ++irl) { + //if (irl->channel != channel) + // continue; + QString name = irl->name(); + const char* portName = name.latin1(); + if (strcmp(*pn, portName) == 0) { + found = true; + break; + } + } + if (!found) { + audio->msgAddRoute1( + //Route(it, channel), + //Route(mjd), + Route(md, -1), + //Route(*pn, false, channel) + //Route(*pn, false, -1) + Route(*pn, false, -1, Route::JACK_ROUTE) + ); + } + ++pn; + } + + // p3.3.55 + // Done with ports. Free them. + free(ports); + } + } } @@ -1167,88 +1187,100 @@ void JackAudioDevice::graphChanged() if(md->rwFlags() & 2) // Readable { - RouteList* rl = md->inRoutes(); - - //--------------------------------------- - // check for disconnects - //--------------------------------------- - - bool erased; - // limit set to 20 iterations for disconnects, don't know how to make it go - // the "right" amount - for (int i = 0; i < 20 ; i++) + // p3.3.55 + jack_port_t* port = (jack_port_t*)md->inClientPort(); + if(port != 0) { - erased = false; - for (iRoute irl = rl->begin(); irl != rl->end(); ++irl) { - //if (irl->channel != channel) - // continue; - QString name = irl->name(); - const char* portName = name.latin1(); - bool found = false; - const char** pn = ports; - while (pn && *pn) { - if (strcmp(*pn, portName) == 0) { - found = true; - break; - } - ++pn; - } - if (!found) { - audio->msgRemoveRoute1( - //Route(portName, false, channel), - //Route(portName, false, -1), - Route(portName, false, -1, Route::JACK_ROUTE), - //Route(it, channel) - //Route(mjd) - Route(md, -1) - ); - erased = true; - break; - } - } - if (!erased) - break; - } - - //--------------------------------------- - // check for connects - //--------------------------------------- - - if (ports) - { - const char** pn = ports; - while (*pn) { - bool found = false; - for (iRoute irl = rl->begin(); irl != rl->end(); ++irl) { - //if (irl->channel != channel) - // continue; - QString name = irl->name(); - const char* portName = name.latin1(); - if (strcmp(*pn, portName) == 0) { - found = true; - break; - } - } - if (!found) { - audio->msgAddRoute1( - //Route(*pn, false, channel), - //Route(*pn, false, -1), - Route(*pn, false, -1, Route::JACK_ROUTE), - //Route(it, channel) - //Route(mjd) - Route(md, -1) - ); - } - ++pn; - } - } + //printf("graphChanged() valid in client port\n"); // p3.3.55 + const char** ports = jack_port_get_all_connections(_client, port); + + RouteList* rl = md->inRoutes(); + + //--------------------------------------- + // check for disconnects + //--------------------------------------- + + bool erased; + // limit set to 20 iterations for disconnects, don't know how to make it go + // the "right" amount + for (int i = 0; i < 20 ; i++) + { + erased = false; + for (iRoute irl = rl->begin(); irl != rl->end(); ++irl) { + //if (irl->channel != channel) + // continue; + QString name = irl->name(); + const char* portName = name.latin1(); + bool found = false; + const char** pn = ports; + while (pn && *pn) { + if (strcmp(*pn, portName) == 0) { + found = true; + break; + } + ++pn; + } + if (!found) { + audio->msgRemoveRoute1( + //Route(portName, false, channel), + //Route(portName, false, -1), + Route(portName, false, -1, Route::JACK_ROUTE), + //Route(it, channel) + //Route(mjd) + Route(md, -1) + ); + erased = true; + break; + } + } + if (!erased) + break; + } + + //--------------------------------------- + // check for connects + //--------------------------------------- + + if (ports) + { + const char** pn = ports; + while (*pn) { + bool found = false; + for (iRoute irl = rl->begin(); irl != rl->end(); ++irl) { + //if (irl->channel != channel) + // continue; + QString name = irl->name(); + const char* portName = name.latin1(); + if (strcmp(*pn, portName) == 0) { + found = true; + break; + } + } + if (!found) { + audio->msgAddRoute1( + //Route(*pn, false, channel), + //Route(*pn, false, -1), + Route(*pn, false, -1, Route::JACK_ROUTE), + //Route(it, channel) + //Route(mjd) + Route(md, -1) + ); + } + ++pn; + } + // p3.3.55 + // Done with ports. Free them. + free(ports); + } + } } - if(ports) + + // p3.3.55 Removed. + //if(ports) // Done with ports. Free them. //delete ports; - free(ports); - - ports = NULL; + // free(ports); + //ports = NULL; } } @@ -1273,7 +1305,8 @@ void JackAudioDevice::registerClient() // Added by Tim. p3.3.20 // Did not help. Seek during play: Jack keeps switching to STOP state after about 1-2 seconds timeout if sync is holding it up. // Nothing in MusE seems to be telling it to stop. - jack_set_sync_timeout(_client, 5000000); // Change default 2 to 5 second sync timeout because prefetch may be very slow esp. with resampling ! + // NOTE: Update: It was a bug in QJackCtl. Fixed now. + //jack_set_sync_timeout(_client, 5000000); // Change default 2 to 5 second sync timeout because prefetch may be very slow esp. with resampling ! jack_on_shutdown(_client, processShutdown, 0); jack_set_buffer_size_callback(_client, bufsize_callback, 0); @@ -1379,6 +1412,8 @@ void JackAudioDevice::disconnect(void* src, void* dst) if (JACK_DEBUG) printf("JackAudioDevice::disconnect()\n"); if(!checkJackClient(_client)) return; + if(!src || !dst) // p3.3.55 + return; const char* sn = jack_port_name((jack_port_t*) src); const char* dn = jack_port_name((jack_port_t*) dst); if (sn == 0 || dn == 0) { @@ -1907,6 +1942,7 @@ void JackAudioDevice::seekTransport(unsigned frame) // Docs say when starting play, transport will roll anyway, ready or not (observed), // but don't mention what should happen on seek during play. // And setting the slow-sync timeout doesn't seem to do anything! + // NOTE: Update: It was a bug with QJackCtl. Fixed now. //dummyState = tempState; dummyState = Audio::STOP; return; diff --git a/muse2/muse/driver/jackmidi.cpp b/muse2/muse/driver/jackmidi.cpp index 4e871a2f..d10712eb 100644 --- a/muse2/muse/driver/jackmidi.cpp +++ b/muse2/muse/driver/jackmidi.cpp @@ -135,14 +135,25 @@ bool JackMidiPortList::removeClientPort(jack_port_t* port) //--------------------------------------------------------- // MidiJackDevice +// in_jack_port or out_jack_port can be null //--------------------------------------------------------- //MidiJackDevice::MidiJackDevice(const int& a, const QString& n) -MidiJackDevice::MidiJackDevice(jack_port_t* jack_port, const QString& n) +//MidiJackDevice::MidiJackDevice(jack_port_t* jack_port, const QString& n) +// p3.3.55 +//MidiJackDevice::MidiJackDevice(jack_port_t* in_jack_port, jack_port_t* out_jack_port, const QString& n) +MidiJackDevice::MidiJackDevice(const QString& n) : MidiDevice(n) { //_client_jackport = 0; - _client_jackport = jack_port; + + //_client_jackport = jack_port; + // p3.3.55 + //_in_client_jackport = in_jack_port; + //_out_client_jackport = out_jack_port; + _in_client_jackport = NULL; + _out_client_jackport = NULL; + //adr = a; init(); } @@ -152,8 +163,15 @@ MidiJackDevice::~MidiJackDevice() #ifdef JACK_MIDI_DEBUG printf("MidiJackDevice::~MidiJackDevice()\n"); #endif - if(_client_jackport) - audioDevice->unregisterPort(_client_jackport); + + //if(_client_jackport) + // audioDevice->unregisterPort(_client_jackport); + // p3.3.55 + if(_in_client_jackport) + audioDevice->unregisterPort(_in_client_jackport); + if(_out_client_jackport) + audioDevice->unregisterPort(_out_client_jackport); + //close(); } @@ -179,7 +197,8 @@ int MidiJackDevice::selectWfd() //--------------------------------------------------------- //QString MidiJackDevice::createJackMidiDevice(int rwflags) // 1:Writable 2: Readable. Do not mix. -MidiDevice* MidiJackDevice::createJackMidiDevice(QString name, int rwflags) // 1:Writable 2: Readable. Do not mix. +//MidiDevice* MidiJackDevice::createJackMidiDevice(QString name, int rwflags) // 1:Writable 2: Readable. Do not mix. +MidiDevice* MidiJackDevice::createJackMidiDevice(QString name, int rwflags) // p3.3.55 1:Writable 2: Readable 3: Writable + Readable { /// _openFlags &= _rwFlags; // restrict to available bits @@ -210,14 +229,36 @@ MidiDevice* MidiJackDevice::createJackMidiDevice(QString name, int rwflags) // 1 // } //} - jack_port_t* client_jackport = NULL; + //jack_port_t* client_jackport = NULL; + // p3.3.55 + ///jack_port_t* in_client_jackport = NULL; + ///jack_port_t* out_client_jackport = NULL; + //char buf[80]; + + // p3.3.55 + int ni = 0; + if(name.isEmpty()) + { + for( ; ni < 65536; ++ni) + { + name.sprintf("jack-midi-%d", ni); + if(!midiDevices.find(name)) + break; + } + } + if(ni >= 65536) + { + fprintf(stderr, "MusE: createJackMidiDevice failed! Can't find an unused midi device name 'jack-midi-[0-65535]'.\n"); + return 0; + } // If Jack port can receive data from us and we actually want to... //if((pf & JackPortIsInput) && (_openFlags & 1)) - if(rwflags & 1) - { + ///if(rwflags & 1) + ///{ + /* p3.3.55 Removed. if(name.isEmpty()) { //snprintf(buf, 80, "muse-jack-midi-out-%d", _nextOutIdNum); @@ -234,8 +275,10 @@ MidiDevice* MidiJackDevice::createJackMidiDevice(QString name, int rwflags) // 1 //client_jackport = (jack_port_t*)audioDevice->registerOutPort(buf, true); if(audioDevice->deviceType() == AudioDevice::JACK_AUDIO) // p3.3.52 { - client_jackport = (jack_port_t*)audioDevice->registerOutPort(name.latin1(), true); - if(client_jackport) + //client_jackport = (jack_port_t*)audioDevice->registerOutPort(name.latin1(), true); + out_client_jackport = (jack_port_t*)audioDevice->registerOutPort((name + QString("_out")).latin1(), true); // p3.3.55 + //if(client_jackport) + if(out_client_jackport) // p3.3.55 break; } else @@ -251,17 +294,27 @@ MidiDevice* MidiJackDevice::createJackMidiDevice(QString name, int rwflags) // 1 //name = QString(buf); } else + */ + + /* { if(audioDevice->deviceType() == AudioDevice::JACK_AUDIO) // p3.3.52 { - client_jackport = (jack_port_t*)audioDevice->registerOutPort(name.latin1(), true); - if(!client_jackport) + //client_jackport = (jack_port_t*)audioDevice->registerOutPort(name.latin1(), true); + out_client_jackport = (jack_port_t*)audioDevice->registerOutPort((name + QString(JACK_MIDI_OUT_PORT_SUFFIX)).latin1(), true); // p3.3.55 + //if(!client_jackport) + if(!out_client_jackport) // p3.3.55 { - fprintf(stderr, "MidiJackDevice::createJackMidiDevice failed creating output port name %s\n", name.latin1()); - return 0; + //fprintf(stderr, "MidiJackDevice::createJackMidiDevice failed creating output port name %s\n", name.latin1()); + fprintf(stderr, "MusE: createJackMidiDevice failed creating output port name %s\n", (name + QString(JACK_MIDI_OUT_PORT_SUFFIX)).latin1()); // p3.3.55 + + //return 0; + rwflags &= ~1; // p3.3.55 Remove the output r/w flag, but continue on... } } } + */ + /* else { @@ -298,12 +351,14 @@ MidiDevice* MidiJackDevice::createJackMidiDevice(QString name, int rwflags) // 1 //else // _nextOutIdNum++; - } - else // Note docs say it can't be both input and output. + ///} + //else // Note docs say it can't be both input and output. // p3.3.55 Removed + // If Jack port can send data to us and we actually want it... //if((pf & JackPortIsOutput) && (_openFlags & 2)) - if(rwflags & 2) - { + ///if(rwflags & 2) + ///{ + /* p3.3.55 Removed. if(name.isEmpty()) { //snprintf(buf, 80, "muse-jack-midi-in-%d", _nextInIdNum); @@ -320,8 +375,10 @@ MidiDevice* MidiJackDevice::createJackMidiDevice(QString name, int rwflags) // 1 //client_jackport = (jack_port_t*)audioDevice->registerInPort(buf, true); if(audioDevice->deviceType() == AudioDevice::JACK_AUDIO) // p3.3.52 { - client_jackport = (jack_port_t*)audioDevice->registerInPort(name.latin1(), true); - if(client_jackport) + //client_jackport = (jack_port_t*)audioDevice->registerInPort(name.latin1(), true); + in_client_jackport = (jack_port_t*)audioDevice->registerInPort(name.latin1(), true); // p3.3.55 + //if(client_jackport) + if(in_client_jackport) // p3.3.55 break; } else @@ -337,17 +394,26 @@ MidiDevice* MidiJackDevice::createJackMidiDevice(QString name, int rwflags) // 1 //name = QString(buf); } else + */ + + /* { if(audioDevice->deviceType() == AudioDevice::JACK_AUDIO) // p3.3.52 { - client_jackport = (jack_port_t*)audioDevice->registerInPort(name.latin1(), true); - if(!client_jackport) + //client_jackport = (jack_port_t*)audioDevice->registerInPort(name.latin1(), true); + in_client_jackport = (jack_port_t*)audioDevice->registerInPort((name + QString(JACK_MIDI_IN_PORT_SUFFIX)).latin1(), true); // p3.3.55 + //if(!client_jackport) + if(!in_client_jackport) // p3.3.55 { - fprintf(stderr, "MidiJackDevice::createJackMidiDevice failed creating input port name %s\n", name.latin1()); - return 0; + //fprintf(stderr, "MidiJackDevice::createJackMidiDevice failed creating input port name %s\n", name.latin1()); + fprintf(stderr, "MusE: createJackMidiDevice failed creating input port name %s\n", (name + QString(JACK_MIDI_IN_PORT_SUFFIX)).latin1()); + + //return 0; + rwflags &= ~2; // p3.3.55 Remove the input r/w flag, but continue on... } } } + */ //client_jackport = (jack_port_t*)audioDevice->registerInPort(name.latin1(), true); @@ -361,12 +427,15 @@ MidiDevice* MidiJackDevice::createJackMidiDevice(QString name, int rwflags) // 1 //else // _nextInIdNum++; - } + ///} //if(client_jackport == NULL) // p3.3.52 Removed. Allow the device to be created even if Jack isn't running. // return 0; - MidiJackDevice* dev = new MidiJackDevice(client_jackport, name); + //MidiJackDevice* dev = new MidiJackDevice(client_jackport, name); + //MidiJackDevice* dev = new MidiJackDevice(in_client_jackport, out_client_jackport, name); // p3.3.55 + //MidiJackDevice* dev = new MidiJackDevice(NULL, NULL, name); // p3.3.55 + MidiJackDevice* dev = new MidiJackDevice(name); // p3.3.55 dev->setrwFlags(rwflags); midiDevices.add(dev); return dev; @@ -382,8 +451,14 @@ void MidiJackDevice::setName(const QString& s) printf("MidiJackDevice::setName %s new name:%s\n", name().latin1(), s.latin1()); #endif _name = s; - if(clientPort()) // p3.3.52 Added check. - audioDevice->setPortName(clientPort(), s.latin1()); + + //if(clientPort()) // p3.3.52 Added check. + // audioDevice->setPortName(clientPort(), s.latin1()); + // p3.3.55 + if(inClientPort()) + audioDevice->setPortName(inClientPort(), (s + QString(JACK_MIDI_IN_PORT_SUFFIX)).latin1()); + if(outClientPort()) + audioDevice->setPortName(outClientPort(), (s + QString(JACK_MIDI_OUT_PORT_SUFFIX)).latin1()); } //--------------------------------------------------------- @@ -454,6 +529,84 @@ QString MidiJackDevice::open() } */ + + QString s; + // p3.3.55 Moved from createJackMidiDevice() + if(_openFlags & 1) + { + if(!_out_client_jackport) + { + if(audioDevice->deviceType() == AudioDevice::JACK_AUDIO) + { + s = name() + QString(JACK_MIDI_OUT_PORT_SUFFIX); + _out_client_jackport = (jack_port_t*)audioDevice->registerOutPort(s.latin1(), true); + if(!_out_client_jackport) + { + fprintf(stderr, "MusE: MidiJackDevice::open failed creating output port name %s\n", s.latin1()); + _openFlags &= ~1; // Remove the flag, but continue on... + } + } + } + } + else + { + if(_out_client_jackport) + { + // We want to unregister the port (which will also disconnect it), AND remove Routes, and then NULL-ify _out_client_jackport. + // We could let our graph change callback (the gui thread one) remove the Routes (which it would anyway). + // But that happens later (gui thread) and it needs a valid _out_client_jackport, + // so use of a registration callback would be required to finally NULL-ify _out_client_jackport, + // and that would require some MidiDevice setter or re-scanner function. + // So instead, manually remove the Routes (in the audio thread), then unregister the port, then immediately NULL-ify _out_client_jackport. + // Our graph change callback (the gui thread one) will see a NULL _out_client_jackport + // so it cannot possibly remove the Routes, but that won't matter - we are removing them manually. + // This is the same technique that is used for audio elsewhere in the code, like Audio::msgSetChannels() + // (but not Song::connectJackRoutes() which keeps the Routes for when undoing deletion of a track). + // + // NOTE: TESTED: Possibly a bug in QJackCtl, with Jack-1 (not Jack-2 !): + // After toggling the input/output green lights in the midi ports list (which gets us here), intermittently + // qjackctl refuses to draw connections. It allows them to be made (MusE responds) but blanks them out immediately + // and does not show 'disconnect', as if it is not properly aware of the connections. + // But ALL else is OK - the connection is fine in MusE, verbose Jack messages show all went OK. + // Yes, there's no doubt the connections are being made. + // When I toggle the lights again (which kills, then recreates the ports here), the problem can disappear or come back again. + // Also once observed a weird double connection from the port to two different Jack ports but one of + // the connections should not have been there and kept toggling along with the other (like a 'ghost' connection). + audio->msgRemoveRoutes(Route(this, 0), Route()); // New function msgRemoveRoutes simply uses Routes, for their pointers. + audioDevice->unregisterPort(_out_client_jackport); + } + _out_client_jackport = NULL; + } + + if(_openFlags & 2) + { + if(!_in_client_jackport) + { + if(audioDevice->deviceType() == AudioDevice::JACK_AUDIO) + { + s = name() + QString(JACK_MIDI_IN_PORT_SUFFIX); + _in_client_jackport = (jack_port_t*)audioDevice->registerInPort(s.latin1(), true); + if(!_in_client_jackport) + { + fprintf(stderr, "MusE: MidiJackDevice::open failed creating input port name %s\n", s.latin1()); + _openFlags &= ~2; // Remove the flag, but continue on... + } + } + } + } + else + { + if(_in_client_jackport) + { + audio->msgRemoveRoutes(Route(), Route(this, 0)); + audioDevice->unregisterPort(_in_client_jackport); + } + _in_client_jackport = NULL; + } + + //if(client_jackport == NULL) // p3.3.52 Removed. Allow the device to be created even if Jack isn't running. + // return 0; + _writeEnable = bool(_openFlags & 1); _readEnable = bool(_openFlags & 2); @@ -470,6 +623,11 @@ void MidiJackDevice::close() printf("MidiJackDevice::close %s\n", name().latin1()); #endif + // p3.3.55 TODO: I don't really want to unregister the + // Jack midi ports because then we lose the connections + // to Jack every time we click the read/write lights + // or change a port's device. + /* if(_client_jackport) { @@ -960,9 +1118,12 @@ void MidiJackDevice::collectMidiEvents() if(!_readEnable) return; - if(!_client_jackport) + //if(!_client_jackport) + if(!_in_client_jackport) // p3.3.55 return; - void* port_buf = jack_port_get_buffer(_client_jackport, segmentSize); + + //void* port_buf = jack_port_get_buffer(_client_jackport, segmentSize); + void* port_buf = jack_port_get_buffer(_in_client_jackport, segmentSize); // p3.3.55 jack_midi_event_t event; jack_nframes_t eventCount = jack_midi_get_event_count(port_buf); @@ -1024,9 +1185,11 @@ bool MidiJackDevice::queueEvent(const MidiPlayEvent& e) //if(debugMsg) // printf("MidiJackDevice::queueEvent\n"); - if(!_client_jackport) + //if(!_client_jackport) + if(!_out_client_jackport) // p3.3.55 return false; - void* pb = jack_port_get_buffer(_client_jackport, segmentSize); + //void* pb = jack_port_get_buffer(_client_jackport, segmentSize); + void* pb = jack_port_get_buffer(_out_client_jackport, segmentSize); // p3.3.55 //unsigned frameCounter = ->frameTime(); int frameOffset = audio->getFrameOffset(); @@ -1343,9 +1506,11 @@ void MidiJackDevice::processEvent(const MidiPlayEvent& event) void MidiJackDevice::processMidi() { - if(!_client_jackport) + //if(!_client_jackport) + if(!_out_client_jackport) // p3.3.55 return; - void* port_buf = jack_port_get_buffer(_client_jackport, segmentSize); + //void* port_buf = jack_port_get_buffer(_client_jackport, segmentSize); + void* port_buf = jack_port_get_buffer(_out_client_jackport, segmentSize); // p3.3.55 jack_midi_clear_buffer(port_buf); while(!eventFifo.isEmpty()) diff --git a/muse2/muse/driver/jackmidi.h b/muse2/muse/driver/jackmidi.h index 12b967a9..f7b5eb94 100644 --- a/muse2/muse/driver/jackmidi.h +++ b/muse2/muse/driver/jackmidi.h @@ -27,11 +27,11 @@ class Xml; // Turn on to show multiple devices, work in progress, // not working fully yet, can't seem to connect... -#define JACK_MIDI_SHOW_MULTIPLE_DEVICES +//#define JACK_MIDI_SHOW_MULTIPLE_DEVICES // It appears one client port per remote port will be necessary. // Jack doesn't seem to like manipulation of non-local ports buffers. -#define JACK_MIDI_USE_MULTIPLE_CLIENT_PORTS +//#define JACK_MIDI_USE_MULTIPLE_CLIENT_PORTS /* jack-midi channels */ //#define JACK_MIDI_CHANNELS 32 @@ -98,7 +98,11 @@ class MidiJackDevice : public MidiDevice { //static int _nextOutIdNum; //static int _nextInIdNum; - jack_port_t* _client_jackport; + //jack_port_t* _client_jackport; + // p3.3.55 + jack_port_t* _in_client_jackport; + jack_port_t* _out_client_jackport; + //RouteList _routes; virtual QString open(); @@ -115,11 +119,15 @@ class MidiJackDevice : public MidiDevice { void eventReceived(jack_midi_event_t*); public: - MidiJackDevice() {} + //MidiJackDevice() {} // p3.3.55 Removed. //MidiJackDevice(const int&, const QString& name); - MidiJackDevice(jack_port_t* jack_port, const QString& name); - static MidiDevice* createJackMidiDevice(QString /*name*/, int /*rwflags*/); // 1:Writable 2: Readable. Do not mix. + //MidiJackDevice(jack_port_t* jack_port, const QString& name); + //MidiJackDevice(jack_port_t* in_jack_port, jack_port_t* out_jack_port, const QString& name); // p3.3.55 In or out port can be null. + MidiJackDevice(const QString& name); + + //static MidiDevice* createJackMidiDevice(QString /*name*/, int /*rwflags*/); // 1:Writable 2: Readable. Do not mix. + static MidiDevice* createJackMidiDevice(QString name = "", int rwflags = 3); // p3.3.55 1:Writable 2: Readable 3: Writable + Readable virtual inline int deviceType() { return JACK_MIDI; } @@ -138,7 +146,11 @@ class MidiJackDevice : public MidiDevice { //virtual jack_port_t* jackPort() { return _jackport; } //virtual jack_port_t* clientJackPort() { return _client_jackport; } - virtual void* clientPort() { return (void*)_client_jackport; } + + //virtual void* clientPort() { return (void*)_client_jackport; } + // p3.3.55 + virtual void* inClientPort() { return (void*) _in_client_jackport; } + virtual void* outClientPort() { return (void*) _out_client_jackport; } //RouteList* routes() { return &_routes; } //bool noRoute() const { return _routes.empty(); } diff --git a/muse2/muse/globals.h b/muse2/muse/globals.h index 5fdaf754..d7e3ac70 100644 --- a/muse2/muse/globals.h +++ b/muse2/muse/globals.h @@ -184,6 +184,10 @@ extern RouteMenuMap gRoutingMenuMap; // Whether the routes popup was shown by clicking the output routes button, or input routes button. extern bool gIsOutRoutingPopupMenu; +// p3.3.55 +#define JACK_MIDI_OUT_PORT_SUFFIX "_out" +#define JACK_MIDI_IN_PORT_SUFFIX "_in" + extern uid_t euid, ruid; extern void doSetuid(); extern void undoSetuid(); diff --git a/muse2/muse/mididev.cpp b/muse2/muse/mididev.cpp index 7f52fc2e..cda7b9f3 100644 --- a/muse2/muse/mididev.cpp +++ b/muse2/muse/mididev.cpp @@ -385,8 +385,9 @@ void MidiDeviceList::add(MidiDevice* dev) if (s == dev->name()) { char incstr[4]; - sprintf(incstr,"_%d",++increment);; - dev->setName(origname + incstr); + sprintf(incstr,"_%d",++increment); + //dev->setName(origname + incstr); + dev->setName(origname + QString(incstr)); // p4.0.0 gotUniqueName = false; } } diff --git a/muse2/muse/mididev.h b/muse2/muse/mididev.h index 1b2cf055..2bb5d727 100644 --- a/muse2/muse/mididev.h +++ b/muse2/muse/mididev.h @@ -71,7 +71,11 @@ class MidiDevice { virtual int deviceType() = 0; - virtual void* clientPort() { return 0; } + //virtual void* clientPort() { return 0; } + // p3.3.55 + virtual void* inClientPort() { return 0; } + virtual void* outClientPort() { return 0; } + virtual QString open() = 0; virtual void close() = 0; virtual void writeRouting(int, Xml&) const { }; diff --git a/muse2/muse/route.cpp b/muse2/muse/route.cpp index 090134ec..0f9eb318 100644 --- a/muse2/muse/route.cpp +++ b/muse2/muse/route.cpp @@ -921,6 +921,36 @@ void removeRoute(Route src, Route dst) } } +//--------------------------------------------------------- +// removeAllRoutes +// If src is valid, disconnects all output routes from it. +// If dst is valid, disconnects all input routes to it. +// src and dst Route are used SIMPLY because Route provides convenient way to +// specify the different pointer types (track, port, jack) +// This routine will ONLY look at the pointer, not the channel or port etc... +// So far it only works with MidiDevice <-> Jack. +//--------------------------------------------------------- + +// p3.3.55 +void removeAllRoutes(Route src, Route dst) +{ + if(src.isValid()) + { + if(src.type == Route::MIDI_DEVICE_ROUTE) + src.device->outRoutes()->clear(); + else + printf("removeAllRoutes: source is not midi device\n"); + } + + if(dst.isValid()) + { + if(dst.type == Route::MIDI_DEVICE_ROUTE) + dst.device->inRoutes()->clear(); + else + printf("removeAllRoutes: dest is not midi device\n"); + } +} + //--------------------------------------------------------- // track2name // create string name representation for audio node @@ -955,9 +985,14 @@ QString Route::name() const { if(device) { + // p3.3.55 Removed for unified jack in/out devices, the actual port names are now different from device name. + // Like this: device: "MyJackDevice1" -> inport: "MyJackDevice1_in" outport: "MyJackDevice1_out" + /* if(device->deviceType() == MidiDevice::JACK_MIDI) return audioDevice->portName(device->clientPort()); else + */ + //if(device->deviceType() == MidiDevice::ALSA_MIDI) return device->name(); } @@ -1553,7 +1588,17 @@ void Route::dump() const if(device->deviceType() == MidiDevice::JACK_MIDI) { if(checkAudioDevice()) - printf("jack midi port device <%s> ", audioDevice->portName(device->clientPort()).latin1()); + //printf("jack midi port device <%s> ", audioDevice->portName(device->clientPort()).latin1()); + // p3.3.55 + { + printf("jack midi device <%s> ", device->name().latin1()); + if(device->inClientPort()) + printf("input port <%s> ", + audioDevice->portName(device->inClientPort()).latin1()); + if(device->outClientPort()) + printf("output port <%s> ", + audioDevice->portName(device->outClientPort()).latin1()); + } } else if(device->deviceType() == MidiDevice::ALSA_MIDI) @@ -1599,8 +1644,10 @@ bool Route::operator==(const Route& a) const { if (type == JACK_ROUTE) { - if (!checkAudioDevice()) return false; - return audioDevice->portName(jackPort) == audioDevice->portName(a.jackPort); + //if (!checkAudioDevice()) return false; + //return audioDevice->portName(jackPort) == audioDevice->portName(a.jackPort); + // p3.3.55 Simplified. + return jackPort == a.jackPort; } else if (type == MIDI_PORT_ROUTE) // p3.3.49 @@ -1610,6 +1657,9 @@ bool Route::operator==(const Route& a) const else if (type == MIDI_DEVICE_ROUTE) { + // p3.3.55 Changed for unified jack in/out devices, the actual port names are now different from device name. + // Like this: device: "MyJackDevice1" -> inport: "MyJackDevice1_in" outport: "MyJackDevice1_out" + /* if(device && a.device && device->deviceType() == a.device->deviceType()) { if(device->deviceType() == MidiDevice::JACK_MIDI) @@ -1625,6 +1675,8 @@ bool Route::operator==(const Route& a) const if(device->deviceType() == MidiDevice::SYNTH_MIDI) return device->name() == a.device->name(); } + */ + return device == a.device; } } } diff --git a/muse2/muse/route.h b/muse2/muse/route.h index 4cacac88..2f29bcf8 100644 --- a/muse2/muse/route.h +++ b/muse2/muse/route.h @@ -85,6 +85,7 @@ typedef RouteList::const_iterator ciRoute; extern void addRoute(Route, Route); extern void removeRoute(Route, Route); +extern void removeAllRoutes(Route, Route); // p3.3.55 extern Route name2route(const QString&, bool dst, int rtype = -1); extern bool checkRoute(const QString&, const QString&); diff --git a/muse2/muse/seqmsg.cpp b/muse2/muse/seqmsg.cpp index 58944552..83161996 100644 --- a/muse2/muse/seqmsg.cpp +++ b/muse2/muse/seqmsg.cpp @@ -89,7 +89,8 @@ void Audio::msgRemoveRoute(Route src, Route dst) if(dst.device) { if(dst.device->deviceType() == MidiDevice::JACK_MIDI) - audioDevice->disconnect(src.jackPort, dst.device->clientPort()); + //audioDevice->disconnect(src.jackPort, dst.device->clientPort()); + audioDevice->disconnect(src.jackPort, dst.device->inClientPort()); // p3.3.55 //else //{ // TODO... @@ -113,7 +114,8 @@ void Audio::msgRemoveRoute(Route src, Route dst) if(src.device) { if(src.device->deviceType() == MidiDevice::JACK_MIDI) - audioDevice->disconnect(src.device->clientPort(), dst.jackPort); + //audioDevice->disconnect(src.device->clientPort(), dst.jackPort); + audioDevice->disconnect(src.device->outClientPort(), dst.jackPort); // p3.3.55 //else //{ // TODO... @@ -140,6 +142,86 @@ void Audio::msgRemoveRoute1(Route src, Route dst) sendMsg(&msg); } +//--------------------------------------------------------- +// msgRemoveRoutes +//--------------------------------------------------------- + +// p3.3.55 +void Audio::msgRemoveRoutes(Route src, Route dst) +{ + msgRemoveRoutes1(src, dst); + + // TODO + /* + //if (!checkAudioDevice()) return; + if (src.type == Route::JACK_ROUTE) + { + if (!checkAudioDevice()) return; + + //if(dst.type == Route::JACK_MIDI_ROUTE) + if(dst.type == Route::MIDI_DEVICE_ROUTE) + { + //MidiJackDevice* jmd = dynamic_cast(dst.device); + //if(jmd) + if(dst.device) + { + if(dst.device->deviceType() == MidiDevice::JACK_MIDI) + //audioDevice->disconnect(src.jackPort, dst.device->clientPort()); + audioDevice->disconnect(src.jackPort, dst.device->inClientPort()); + //else + //{ + // TODO... + //MidiAlsaDevice* amd = dynamic_cast(dst.device); + //if(amd) + //} + } + } + else + audioDevice->disconnect(src.jackPort, ((AudioInput*)dst.track)->jackPort(dst.channel)); + } + else if (dst.type == Route::JACK_ROUTE) + { + if (!checkAudioDevice()) return; + + //if(src.type == Route::JACK_MIDI_ROUTE) + if(src.type == Route::MIDI_DEVICE_ROUTE) + { + //MidiJackDevice* jmd = dynamic_cast(src.device); + //if(jmd) + if(src.device) + { + if(src.device->deviceType() == MidiDevice::JACK_MIDI) + //audioDevice->disconnect(src.device->clientPort(), dst.jackPort); + audioDevice->disconnect(src.device->outClientPort(), dst.jackPort); + //else + //{ + // TODO... + //MidiAlsaDevice* amd = dynamic_cast(src.device); + //if(amd) + //} + } + } + else + audioDevice->disconnect(((AudioOutput*)src.track)->jackPort(src.channel), dst.jackPort); + } + + */ +} + +//--------------------------------------------------------- +// msgRemoveRoutes1 +//--------------------------------------------------------- + +// p3.3.55 +void Audio::msgRemoveRoutes1(Route src, Route dst) + { + AudioMsg msg; + msg.id = AUDIO_REMOVEROUTES; + msg.sroute = src; + msg.droute = dst; + sendMsg(&msg); + } + //--------------------------------------------------------- // msgAddRoute //--------------------------------------------------------- @@ -159,7 +241,8 @@ void Audio::msgAddRoute(Route src, Route dst) if(dst.device) { if(dst.device->deviceType() == MidiDevice::JACK_MIDI) - audioDevice->connect(src.jackPort, dst.device->clientPort()); + //audioDevice->connect(src.jackPort, dst.device->clientPort()); + audioDevice->connect(src.jackPort, dst.device->inClientPort()); // p3.3.55 //else //{ // TODO... @@ -185,7 +268,8 @@ void Audio::msgAddRoute(Route src, Route dst) if(src.device) { if(src.device->deviceType() == MidiDevice::JACK_MIDI) - audioDevice->connect(src.device->clientPort(), dst.jackPort); + //audioDevice->connect(src.device->clientPort(), dst.jackPort); + audioDevice->connect(src.device->outClientPort(), dst.jackPort); // p3.3.55 //else //{ // TODO... diff --git a/muse2/muse/widgets/mtrackinfobase.ui b/muse2/muse/widgets/mtrackinfobase.ui index 3d2b274a..06e881d5 100644 --- a/muse2/muse/widgets/mtrackinfobase.ui +++ b/muse2/muse/widgets/mtrackinfobase.ui @@ -446,7 +446,7 @@ - true + true Echo recording events to output. -- cgit v1.2.3