summaryrefslogtreecommitdiff
path: root/muse2/muse/driver/jackmidi.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'muse2/muse/driver/jackmidi.cpp')
-rw-r--r--muse2/muse/driver/jackmidi.cpp233
1 files changed, 199 insertions, 34 deletions
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())