summaryrefslogtreecommitdiff
path: root/muse2/muse/driver
diff options
context:
space:
mode:
authorTim E. Real <termtech@rogers.com>2010-10-16 02:08:48 +0000
committerTim E. Real <termtech@rogers.com>2010-10-16 02:08:48 +0000
commit250b9712f41aacb2b5dc3660878b55b5935f2c6f (patch)
tree6fa260828dc5c5cb630b0dcb2ebd6ae592d3c372 /muse2/muse/driver
parent0e4fa958b9cab8ab68147df204abe0e33ee5e405 (diff)
See ChangeLog
Diffstat (limited to 'muse2/muse/driver')
-rw-r--r--muse2/muse/driver/alsamidi.h9
-rw-r--r--muse2/muse/driver/jack.cpp378
-rw-r--r--muse2/muse/driver/jackmidi.cpp233
-rw-r--r--muse2/muse/driver/jackmidi.h26
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(); }