diff options
author | Tim E. Real <termtech@rogers.com> | 2010-10-16 02:08:48 +0000 |
---|---|---|
committer | Tim E. Real <termtech@rogers.com> | 2010-10-16 02:08:48 +0000 |
commit | 250b9712f41aacb2b5dc3660878b55b5935f2c6f (patch) | |
tree | 6fa260828dc5c5cb630b0dcb2ebd6ae592d3c372 /muse2/muse/driver | |
parent | 0e4fa958b9cab8ab68147df204abe0e33ee5e405 (diff) |
See ChangeLog
Diffstat (limited to 'muse2/muse/driver')
-rw-r--r-- | muse2/muse/driver/alsamidi.h | 9 | ||||
-rw-r--r-- | muse2/muse/driver/jack.cpp | 378 | ||||
-rw-r--r-- | muse2/muse/driver/jackmidi.cpp | 233 | ||||
-rw-r--r-- | muse2/muse/driver/jackmidi.h | 26 |
4 files changed, 432 insertions, 214 deletions
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(); } |