summaryrefslogtreecommitdiff
path: root/attic/muse2-oom/muse2/muse/driver/jackmidi.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'attic/muse2-oom/muse2/muse/driver/jackmidi.cpp')
-rw-r--r--attic/muse2-oom/muse2/muse/driver/jackmidi.cpp1732
1 files changed, 0 insertions, 1732 deletions
diff --git a/attic/muse2-oom/muse2/muse/driver/jackmidi.cpp b/attic/muse2-oom/muse2/muse/driver/jackmidi.cpp
deleted file mode 100644
index d401c7e1..00000000
--- a/attic/muse2-oom/muse2/muse/driver/jackmidi.cpp
+++ /dev/null
@@ -1,1732 +0,0 @@
-//=========================================================
-// MusE
-// Linux Music Editor
-// $Id: jackmidi.cpp,v 1.1.1.1 2010/01/27 09:06:43 terminator356 Exp $
-// (C) Copyright 1999-2010 Werner Schweer (ws@seh.de)
-//=========================================================
-
-#include <QString>
-
-#include <stdio.h>
-
-#include <jack/jack.h>
-//#include <jack/midiport.h>
-
-#include "jackmidi.h"
-#include "song.h"
-#include "globals.h"
-#include "midi.h"
-#include "mididev.h"
-#include "../midiport.h"
-#include "../midiseq.h"
-#include "../midictrl.h"
-#include "../audio.h"
-#include "mpevent.h"
-//#include "sync.h"
-#include "audiodev.h"
-#include "../mplugins/midiitransform.h"
-#include "../mplugins/mitplugin.h"
-#include "xml.h"
-
-// Turn on debug messages.
-//#define JACK_MIDI_DEBUG
-
-extern unsigned int volatile lastExtMidiSyncTick;
-
-///int jackmidi_pi[2];
-///int jackmidi_po[2];
-
-//extern muse_jack_midi_buffer jack_midi_out_data[JACK_MIDI_CHANNELS];
-//extern muse_jack_midi_buffer jack_midi_in_data[JACK_MIDI_CHANNELS];
-///extern jack_port_t *midi_port_in[JACK_MIDI_CHANNELS];
-///extern jack_port_t *midi_port_out[JACK_MIDI_CHANNELS];
-
-///MidiJackDevice* gmdev = NULL;
-
-///int* jackSeq;
-//static snd_seq_addr_t musePort;
-
-//int MidiJackDevice::_nextOutIdNum = 0;
-//int MidiJackDevice::_nextInIdNum = 0;
-
-//int JackMidiPortList::_nextOutIdNum = 0;
-//int JackMidiPortList::_nextInIdNum = 0;
-
-//JackMidiPortList jackMidiClientPorts;
-
-
-/*
-//---------------------------------------------------------
-// JackMidiPortList
-//---------------------------------------------------------
-
-JackMidiPortList::JackMidiPortList()
-{
-
-}
-
-JackMidiPortList::~JackMidiPortList()
-{
-
-}
-
-iJackMidiPort JackMidiPortList::createClientPort(int flags) // 1 = writable, 2 = readable - do not mix
-{
- if(flags & 1)
- {
- char buf[80];
- snprintf(buf, 80, "muse-jack-midi-out-%d", _nextOutIdNum);
- jack_port_t* _client_jackport = (jack_port_t*)audioDevice->registerOutPort(buf, true);
- if(_client_jackport == NULL)
- {
- fprintf(stderr, "JackMidiPortList::createClientPort failed to register jack-midi-out\n");
- //return QString("Could not register jack-midi-out client port");
- return end();
- }
- else
- {
- JackMidiPort jmp(_client_jackport, QString(buf), flags);
- _nextOutIdNum++;
- return insert(begin(), std::pair<jack_port_t*, JackMidiPort>(_client_jackport, jmp));
- }
- }
- else
- if(flags & 2)
- {
- char buf[80];
- snprintf(buf, 80, "muse-jack-midi-in-%d", _nextInIdNum);
- jack_port_t* _client_jackport = (jack_port_t*)audioDevice->registerInPort(buf, true);
- if(_client_jackport == NULL)
- {
- fprintf(stderr, "JackMidiPortList::createClientPort failed to register jack-midi-in\n");
- return end();
- }
- else
- {
- JackMidiPort jmp(_client_jackport, QString(buf), flags);
- _nextInIdNum++;
- return insert(begin(), std::pair<jack_port_t*, JackMidiPort>(_client_jackport, jmp));
- }
- }
- return end();
-}
-
-// Return true if removed.
-bool JackMidiPortList::removeClientPort(jack_port_t* port)
-{
- iJackMidiPort ijp = find(port);
- if(ijp == end())
- return false;
-
- // Is output?
- if(ijp->second._flags & 1)
- _nextOutIdNum--;
- // Is input?
- if(ijp->second._flags & 2)
- _nextInIdNum--;
-
- erase(ijp);
-
- audioDevice->unregisterPort(port);
-
- return true;
-}
-*/
-
-//---------------------------------------------------------
-// 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)
-// 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;
- // 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();
-}
-
-MidiJackDevice::~MidiJackDevice()
-{
- #ifdef JACK_MIDI_DEBUG
- printf("MidiJackDevice::~MidiJackDevice()\n");
- #endif
-
- //if(_client_jackport)
- // audioDevice->unregisterPort(_client_jackport);
- // p3.3.55
-
- if(audioDevice)
- {
- if(_in_client_jackport)
- audioDevice->unregisterPort(_in_client_jackport);
- if(_out_client_jackport)
- audioDevice->unregisterPort(_out_client_jackport);
- }
-
- //close();
-}
-
-/*
-//---------------------------------------------------------
-// select[RW]fd
-//---------------------------------------------------------
-
-int MidiJackDevice::selectRfd()
-{
- return jackmidi_pi[0];
-}
-
-int MidiJackDevice::selectWfd()
-{
- return jackmidi_po[0];
-}
-*/
-
-//---------------------------------------------------------
-// createJackMidiDevice
-// If name parameter is blank, creates a new (locally) unique one.
-//---------------------------------------------------------
-
-//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) // p3.3.55 1:Writable 2: Readable 3: Writable + Readable
-{
-/// _openFlags &= _rwFlags; // restrict to available bits
-
-/// #ifdef JACK_MIDI_DEBUG
-/// printf("MidiJackDevice::open %s\n", name.toLatin1().constData());
-/// #endif
-
- //jack_port_t* jp = jack_port_by_name(_client, name().toLatin1().constData());
-/// jack_port_t* jp = (jack_port_t*)audioDevice->findPort(name().toLatin1().constData());
-
-/// if(!jp)
-/// {
-/// printf("MidiJackDevice::open: Jack midi port %s not found!\n", name().toLatin1().constData());
-/// _writeEnable = false;
-/// _readEnable = false;
-/// return QString("Jack midi port not found");
-/// }
-
-/// int pf = jack_port_flags(jp);
-
- //if(!name.isEmpty())
- //{
- // Does not work.
- // if(audioDevice->findPort(name.toLatin1().constData()))
- // {
- // fprintf(stderr, "MidiJackDevice::createJackMidiDevice failed! Given port name %s already exists!\n", name.toLatin1().constData());
- // return 0;
- // }
- //}
-
- //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)
- ///{
- /* p3.3.55 Removed.
- if(name.isEmpty())
- {
- //snprintf(buf, 80, "muse-jack-midi-out-%d", _nextOutIdNum);
- for(int i = 0; ; ++i)
- {
- //snprintf(buf, 80, "midi-out-%d", i);
- name.sprintf("midi-out-%d", i);
-
- if(!midiDevices.find(name))
- {
- // Does not work.
- //if(!audioDevice->findPort(buf))
- // break;
- //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.toLatin1().constData(), true);
- out_client_jackport = (jack_port_t*)audioDevice->registerOutPort((name + QString("_out")).toLatin1().constData(), true); // p3.3.55
- //if(client_jackport)
- if(out_client_jackport) // p3.3.55
- break;
- }
- else
- break;
- }
-
- if(i == 65535)
- {
- fprintf(stderr, "MidiJackDevice::createJackMidiDevice failed! Can't find unused output port name!\n");
- return 0;
- }
- }
- //name = QString(buf);
- }
- else
- */
-
- /*
- {
- if(audioDevice->deviceType() == AudioDevice::JACK_AUDIO) // p3.3.52
- {
- //client_jackport = (jack_port_t*)audioDevice->registerOutPort(name.toLatin1().constData(), true);
- out_client_jackport = (jack_port_t*)audioDevice->registerOutPort((name + QString(JACK_MIDI_OUT_PORT_SUFFIX)).toLatin1().constData(), 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.toLatin1().constData());
- fprintf(stderr, "MusE: createJackMidiDevice failed creating output port name %s\n", (name + QString(JACK_MIDI_OUT_PORT_SUFFIX)).toLatin1().constData()); // p3.3.55
-
- //return 0;
- rwflags &= ~1; // p3.3.55 Remove the output r/w flag, but continue on...
- }
- }
- }
- */
-
- /*
- else
- {
- client_jackport = (jack_port_t*)audioDevice->registerOutPort(name.toLatin1().constData(), true);
- if(!client_jackport)
- {
- for(int i = 0; ; ++i)
- {
- snprintf(buf, 80, "midi-out-%d", i);
- // Does not work!
- //if(!audioDevice->findPort(buf))
- // break;
- client_jackport = (jack_port_t*)audioDevice->registerOutPort(buf, true);
- if(client_jackport)
- break;
-
- if(i == 65535)
- {
- fprintf(stderr, "MidiJackDevice::createJackMidiDevice failed! Can't find unused output port name!\n");
- return 0;
- }
- }
- name = QString(buf);
- }
- }
- */
-
- //client_jackport = (jack_port_t*)audioDevice->registerOutPort(name.toLatin1().constData(), true);
- //if(client_jackport == NULL)
- //{
- // fprintf(stderr, "MidiJackDevice::createJackMidiDevice failed to register jack midi client output port %s\n", name.toLatin1().constData());
- // return 0;
- //}
- //else
- // _nextOutIdNum++;
-
- ///}
- //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)
- ///{
- /* p3.3.55 Removed.
- if(name.isEmpty())
- {
- //snprintf(buf, 80, "muse-jack-midi-in-%d", _nextInIdNum);
- for(int i = 0; ; ++i)
- {
- //snprintf(buf, 80, "midi-in-%d", i);
- name.sprintf("midi-in-%d", i);
-
- if(!midiDevices.find(name))
- {
- // Does not work.
- //if(!audioDevice->findPort(buf))
- // break;
- //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.toLatin1().constData(), true);
- in_client_jackport = (jack_port_t*)audioDevice->registerInPort(name.toLatin1().constData(), true); // p3.3.55
- //if(client_jackport)
- if(in_client_jackport) // p3.3.55
- break;
- }
- else
- break;
- }
-
- if(i == 65535)
- {
- fprintf(stderr, "MidiJackDevice::createJackMidiDevice failed! Can't find unused input port name!\n");
- return 0;
- }
- }
- //name = QString(buf);
- }
- else
- */
-
- /*
- {
- if(audioDevice->deviceType() == AudioDevice::JACK_AUDIO) // p3.3.52
- {
- //client_jackport = (jack_port_t*)audioDevice->registerInPort(name.toLatin1().constData(), true);
- in_client_jackport = (jack_port_t*)audioDevice->registerInPort((name + QString(JACK_MIDI_IN_PORT_SUFFIX)).toLatin1().constData(), 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.toLatin1().constData());
- fprintf(stderr, "MusE: createJackMidiDevice failed creating input port name %s\n", (name + QString(JACK_MIDI_IN_PORT_SUFFIX)).toLatin1().constData());
-
- //return 0;
- rwflags &= ~2; // p3.3.55 Remove the input r/w flag, but continue on...
- }
- }
- }
- */
-
- //client_jackport = (jack_port_t*)audioDevice->registerInPort(name.toLatin1().constData(), true);
-
- //if(client_jackport == NULL)
- //{
- // fprintf(stderr, "MidiJackDevice::createJackMidiDevice failed to register jack midi client input port %s\n", name.toLatin1().constData());
- //_readEnable = false;
- //return QString("Could not register jack-midi-in client port");
- // return 0;
- //}
- //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(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;
-}
-
-//---------------------------------------------------------
-// setName
-//---------------------------------------------------------
-
-void MidiJackDevice::setName(const QString& s)
-{
- #ifdef JACK_MIDI_DEBUG
- printf("MidiJackDevice::setName %s new name:%s\n", name().toLatin1().constData(), s.toLatin1().constData());
- #endif
- _name = s;
-
- //if(clientPort()) // p3.3.52 Added check.
- // audioDevice->setPortName(clientPort(), s.toLatin1().constData());
- // p3.3.55
- if(inClientPort())
- audioDevice->setPortName(inClientPort(), (s + QString(JACK_MIDI_IN_PORT_SUFFIX)).toLatin1().constData());
- if(outClientPort())
- audioDevice->setPortName(outClientPort(), (s + QString(JACK_MIDI_OUT_PORT_SUFFIX)).toLatin1().constData());
-}
-
-//---------------------------------------------------------
-// open
-//---------------------------------------------------------
-
-QString MidiJackDevice::open()
-{
- _openFlags &= _rwFlags; // restrict to available bits
-
- #ifdef JACK_MIDI_DEBUG
- printf("MidiJackDevice::open %s\n", name().toLatin1().constData());
- #endif
-
- /*
- //jack_port_t* jp = jack_port_by_name(_client, name().toLatin1().constData());
- jack_port_t* jp = (jack_port_t*)audioDevice->findPort(name().toLatin1().constData());
-
- if(!jp)
- {
- printf("MidiJackDevice::open: Jack midi port %s not found!\n", name().toLatin1().constData());
- _writeEnable = false;
- _readEnable = false;
- return QString("Jack midi port not found");
- }
-
- int pf = jack_port_flags(jp);
-
- // If Jack port can receive data from us and we actually want to...
- if((pf & JackPortIsInput) && (_openFlags & 1))
- {
- char buf[80];
- snprintf(buf, 80, "muse-jack-midi-out-%d", _nextOutIdNum);
- _client_jackport = (jack_port_t*)audioDevice->registerOutPort(buf, true);
- if(_client_jackport == NULL)
- {
- fprintf(stderr, "MidiJackDevice::open failed to register jack-midi-out\n");
- _writeEnable = false;
- return QString("Could not register jack-midi-out client port");
- }
- else
- {
- _nextOutIdNum++;
- // src, dest
- ///audioDevice->connect(_client_jackport, jp);
- _writeEnable = true;
- }
- }
- else // Note docs say it can't be both input and output.
- // If Jack port can send data to us and we actually want it...
- if((pf & JackPortIsOutput) && (_openFlags & 2))
- {
- char buf[80];
- snprintf(buf, 80, "muse-jack-midi-in-%d", _nextInIdNum);
- _client_jackport = (jack_port_t*)audioDevice->registerInPort(buf, true);
- if(_client_jackport == NULL)
- {
- fprintf(stderr, "MidiJackDevice::open failed to register jack-midi-in\n");
- _readEnable = false;
- return QString("Could not register jack-midi-in client port");
- }
- else
- {
- _nextInIdNum++;
- ///audioDevice->connect(jp, _client_jackport);
- _readEnable = true;
- }
- }
- */
-
-
- 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.toLatin1().constData(), true);
- if(!_out_client_jackport)
- {
- fprintf(stderr, "MusE: MidiJackDevice::open failed creating output port name %s\n", s.toLatin1().constData());
- _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.toLatin1().constData(), true);
- if(!_in_client_jackport)
- {
- fprintf(stderr, "MusE: MidiJackDevice::open failed creating input port name %s\n", s.toLatin1().constData());
- _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);
-
- return QString("OK");
-}
-
-//---------------------------------------------------------
-// close
-//---------------------------------------------------------
-
-void MidiJackDevice::close()
-{
- #ifdef JACK_MIDI_DEBUG
- printf("MidiJackDevice::close %s\n", name().toLatin1().constData());
- #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)
- {
- int pf = jack_port_flags(_client_jackport);
-
- if(pf & JackPortIsOutput)
- _nextOutIdNum--;
- else
- if(pf & JackPortIsInput)
- _nextInIdNum--;
- audioDevice->unregisterPort(_client_jackport);
- _client_jackport = 0;
- _writeEnable = false;
- _readEnable = false;
- return;
- }
- */
-
- _writeEnable = false;
- _readEnable = false;
-
- /*
- //jack_port_t* jp = jack_port_by_name(_client, name().toLatin1().constData());
- jack_port_t* jp = (jack_port_t*)audioDevice->findPort(name().toLatin1().constData());
-
- if(!jp)
- {
- printf("MidiJackDevice::close: Jack midi port %s not found!\n", name().toLatin1().constData());
- _writeEnable = false;
- _readEnable = false;
- return;
- }
-
- //int pf = jack_port_flags(jp);
-
- // If Jack port can receive data from us and we actually want to...
- //if((pf & JackPortIsInput) && (_openFlags & 1))
- if(jack_port_connected_to(midi_port_out[0], name().toLatin1().constData()))
- {
- // src, dest
-/// audioDevice->disconnect(midi_port_out[0], jp);
- _writeEnable = false;
- }
- else // Note docs say it can't be both input and output.
- // If Jack port can send data to us and we actually want it...
- //if((pf & JackPortIsOutput) && (_openFlags & 2))
- if(jack_port_connected_to(midi_port_in[0], name().toLatin1().constData()))
- {
-/// audioDevice->disconnect(jp, midi_port_in[0]);
- _readEnable = false;
- }
- */
-}
-
-//---------------------------------------------------------
-// writeRouting
-//---------------------------------------------------------
-
-void MidiJackDevice::writeRouting(int level, Xml& xml) const
-{
- // p3.3.45
- // If this device is not actually in use by the song, do not write any routes.
- // This prevents bogus routes from being saved and propagated in the med file.
- if(midiPort() == -1)
- return;
-
- QString s;
- if(rwFlags() & 2) // Readable
- {
- //RouteList* rl = _inRoutes;
- //for (ciRoute r = rl->begin(); r != rl->end(); ++r)
- for (ciRoute r = _inRoutes.begin(); r != _inRoutes.end(); ++r)
- {
- if(!r->name().isEmpty())
- {
- xml.tag(level++, "Route");
-
- //xml.strTag(level, "srcNode", r->name());
- //xml.tag(level, "source type=\"%d\" name=\"%s\"/", r->type, r->name().toLatin1().constData());
- s = QT_TRANSLATE_NOOP("@default", "source");
- if(r->type != Route::TRACK_ROUTE)
- s += QString(QT_TRANSLATE_NOOP("@default", " type=\"%1\"")).arg(r->type);
-
- //s += QString(QT_TRANSLATE_NOOP("@default", " name=\"%1\"/")).arg(r->name());
- s += QString(QT_TRANSLATE_NOOP("@default", " name=\"%1\"/")).arg(Xml::xmlString(r->name()));
- xml.tag(level, s.toLatin1().constData());
-
- //xml.strTag(level, "dstNode", name());
- //xml.tag(level, "dest type=\"%d\" name=\"%s\"/", Route::JACK_MIDI_ROUTE, name().toLatin1().constData());
- //xml.tag(level, "dest type=\"%d\" name=\"%s\"/", Route::MIDI_DEVICE_ROUTE, name().toLatin1().constData());
- //xml.tag(level, "dest devtype=\"%d\" name=\"%s\"/", MidiDevice::JACK_MIDI, name().toLatin1().constData());
- xml.tag(level, "dest devtype=\"%d\" name=\"%s\"/", MidiDevice::JACK_MIDI, Xml::xmlString(name()).toLatin1().constData());
-
- xml.etag(level--, "Route");
- }
- }
- }
-
- for (ciRoute r = _outRoutes.begin(); r != _outRoutes.end(); ++r)
- {
- if(!r->name().isEmpty())
- {
- s = QT_TRANSLATE_NOOP("@default", "Route");
- if(r->channel != -1)
- s += QString(QT_TRANSLATE_NOOP("@default", " channel=\"%1\"")).arg(r->channel);
-
- //xml.tag(level++, "Route");
- xml.tag(level++, s.toLatin1().constData());
-
- /*
- //xml.strTag(level, "srcNode", name());
- if(r->channel != -1)
- //xml.tag(level, "source type=\"%d\" channel=\"%d\" name=\"%s\"/", Route::JACK_MIDI_ROUTE, r->channel, name().toLatin1().constData());
- //xml.tag(level, "source type=\"%d\" channel=\"%d\" name=\"%s\"/", Route::MIDI_DEVICE_ROUTE, r->channel, name().toLatin1().constData());
- xml.tag(level, "source devtype=\"%d\" channel=\"%d\" name=\"%s\"/", MidiDevice::JACK_MIDI, r->channel, name().toLatin1().constData());
- else
- //xml.tag(level, "source type=\"%d\" name=\"%s\"/", Route::JACK_MIDI_ROUTE, name().toLatin1().constData());
- //xml.tag(level, "source type=\"%d\" name=\"%s\"/", Route::MIDI_DEVICE_ROUTE, name().toLatin1().constData());
- */
- //xml.tag(level, "source devtype=\"%d\" name=\"%s\"/", MidiDevice::JACK_MIDI, name().toLatin1().constData());
- xml.tag(level, "source devtype=\"%d\" name=\"%s\"/", MidiDevice::JACK_MIDI, Xml::xmlString(name()).toLatin1().constData());
-
- /*
- //xml.strTag(level, "dstNode", r->name());
- if(r->channel != -1)
- {
- if(r->type == Route::MIDI_DEVICE_ROUTE)
- xml.tag(level, "dest devtype=\"%d\" channel=\"%d\" name=\"%s\"/", r->device->deviceType(), r->channel, r->name().toLatin1().constData());
- else
- xml.tag(level, "dest type=\"%d\" channel=\"%d\" name=\"%s\"/", r->type, r->channel, r->name().toLatin1().constData());
- }
- else
- {
- if(r->type == Route::MIDI_DEVICE_ROUTE)
- xml.tag(level, "dest devtype=\"%d\" name=\"%s\"/", r->device->deviceType(), r->name().toLatin1().constData());
- else
- xml.tag(level, "dest type=\"%d\" name=\"%s\"/", r->type, r->name().toLatin1().constData());
- }
- */
-
- s = QT_TRANSLATE_NOOP("@default", "dest");
- if(r->type == Route::MIDI_DEVICE_ROUTE)
- s += QString(QT_TRANSLATE_NOOP("@default", " devtype=\"%1\"")).arg(r->device->deviceType());
- else
- if(r->type != Route::TRACK_ROUTE)
- s += QString(QT_TRANSLATE_NOOP("@default", " type=\"%1\"")).arg(r->type);
-
- //s += QString(QT_TRANSLATE_NOOP("@default", " name=\"%1\"/")).arg(r->name());
- s += QString(QT_TRANSLATE_NOOP("@default", " name=\"%1\"/")).arg(Xml::xmlString(r->name()));
- xml.tag(level, s.toLatin1().constData());
-
-
- xml.etag(level--, "Route");
- }
- }
-
- /*
- else
- if(rwFlags() & 1) // Writable
- {
- //RouteList* rl = _outRoutes;
- //for (ciRoute r = rl->begin(); r != rl->end(); ++r)
- for (ciRoute r = _outRoutes.begin(); r != _outRoutes.end(); ++r)
- {
- if(!r->name().isEmpty())
- {
- xml.tag(level++, "Route");
-
- //xml.strTag(level, "srcNode", name());
- //if(r->channel != -1)
- // xml.tag(level, "srcNode type=\"%d\" channel=\"%d\" name=\"%s\"", Route::JACK_MIDI_ROUTE, r->channel, name().toLatin1().constData());
- //else
- xml.tag(level, "source type=\"%d\" name=\"%s\"/", Route::JACK_MIDI_ROUTE, name().toLatin1().constData());
-
- //xml.strTag(level, "dstNode", r->name());
- xml.tag(level, "dest type=\"%d\" name=\"%s\"/", r->type, r->name().toLatin1().constData());
-
- xml.etag(level--, "Route");
- }
- }
- }
- */
-}
-
-//---------------------------------------------------------
-// putEvent
-//---------------------------------------------------------
-
-/* FIX: if we fail to transmit the event,
- * we return false (indicating OK). Otherwise
- * it seems muse will retry forever
- */
-bool MidiJackDevice::putMidiEvent(const MidiPlayEvent& /*event*/)
-{
- /*
- int give, channel = event.channel();
- int x;
-
- if(channel >= JACK_MIDI_CHANNELS) return false;
-
- // buffer up events, because jack eats them in chunks, if
- // the buffer is full, there isn't so much to do, than
- // drop the event
-
- give = jack_midi_out_data[channel].give;
- if(jack_midi_out_data[channel].buffer[give*4+3]){
- fprintf(stderr, "WARNING: muse-to-jack midi-buffer is full, channel=%u\n", channel);
- return false;
- }
- // copy event(note-on etc..), pitch and volume
- // see http://www.midi.org/techspecs/midimessages.php
- switch(event.type()){
- case ME_NOTEOFF:
- jack_midi_out_data[channel].buffer[give*4+0] = 0x80;
- jack_midi_out_data[channel].buffer[give*4+1] = event.dataA() & 0x7f;
- jack_midi_out_data[channel].buffer[give*4+2] = event.dataB() & 0x7f;
- break;
- case ME_NOTEON:
- jack_midi_out_data[channel].buffer[give*4+0] = 0x90;
- jack_midi_out_data[channel].buffer[give*4+1] = event.dataA() & 0x7f;
- jack_midi_out_data[channel].buffer[give*4+2] = event.dataB() & 0x7f;
- break;
- case ME_CONTROLLER:
- jack_midi_out_data[channel].buffer[give*4+0] = 0xb0;
- jack_midi_out_data[channel].buffer[give*4+1] = event.dataA() & 0x7f;
- jack_midi_out_data[channel].buffer[give*4+2] = event.dataB() & 0x7f;
- break;
- case ME_PROGRAM:
- jack_midi_out_data[channel].buffer[give*4+0] = 0xc0;
- jack_midi_out_data[channel].buffer[give*4+1] = event.dataA() & 0x7f;
- jack_midi_out_data[channel].buffer[give*4+2] = 0;
- break;
- case ME_PITCHBEND:
- jack_midi_out_data[channel].buffer[give*4+0] = 0xE0;
- // convert muse pitch-bend to midi standard
- x = 0x2000 + event.dataA();
- jack_midi_out_data[channel].buffer[give*4+1] = x & 0x7f;
- jack_midi_out_data[channel].buffer[give*4+2] = (x >> 8) & 0x7f;
- break;
- default:
- fprintf(stderr, "jack-midi-out %u WARNING: unknown event %x\n", channel, event.type());
- return false;
- }
- jack_midi_out_data[channel].buffer[give*4+3] = 1; // mark state of this slot
- // finally increase give position
- give++;
- if(give >= JACK_MIDI_BUFFER_SIZE){
- give = 0;
- }
- jack_midi_out_data[channel].give = give;
- return false;
- */
-
- return false;
-}
-
-/*
-//---------------------------------------------------------
-// putEvent
-// return false if event is delivered
-//---------------------------------------------------------
-
-bool MidiJackDevice::putEvent(int* event)
-{
- int *y; y = event;
- return false;
-}
-*/
-
-//---------------------------------------------------------
-// recordEvent
-//---------------------------------------------------------
-
-void MidiJackDevice::recordEvent(MidiRecordEvent& event)
- {
- // Set the loop number which the event came in at.
- //if(audio->isRecording())
- if(audio->isPlaying())
- event.setLoopNum(audio->loopCount());
-
- if (midiInputTrace) {
- printf("Jack MidiInput: ");
- event.dump();
- }
-
- int typ = event.type();
-
- if(_port != -1)
- {
- int idin = midiPorts[_port].syncInfo().idIn();
-
- //---------------------------------------------------
- // filter some SYSEX events
- //---------------------------------------------------
-
- if (typ == ME_SYSEX) {
- const unsigned char* p = event.data();
- int n = event.len();
- if (n >= 4) {
- if ((p[0] == 0x7f)
- //&& ((p[1] == 0x7f) || (p[1] == rxDeviceId))) {
- && ((p[1] == 0x7f) || (idin == 0x7f) || (p[1] == idin))) {
- if (p[2] == 0x06) {
- //mmcInput(p, n);
- midiSeq->mmcInput(_port, p, n);
- return;
- }
- if (p[2] == 0x01) {
- //mtcInputFull(p, n);
- midiSeq->mtcInputFull(_port, p, n);
- return;
- }
- }
- else if (p[0] == 0x7e) {
- //nonRealtimeSystemSysex(p, n);
- midiSeq->nonRealtimeSystemSysex(_port, p, n);
- return;
- }
- }
- }
- else
- // Trigger general activity indicator detector. Sysex has no channel, don't trigger.
- midiPorts[_port].syncInfo().trigActDetect(event.channel());
- }
-
- //
- // process midi event input filtering and
- // transformation
- //
-
- processMidiInputTransformPlugins(event);
-
- if (filterEvent(event, midiRecordType, false))
- return;
-
- if (!applyMidiInputTransformation(event)) {
- if (midiInputTrace)
- printf(" midi input transformation: event filtered\n");
- return;
- }
-
- //
- // transfer noteOn events to gui for step recording and keyboard
- // remote control
- //
- if (typ == ME_NOTEON) {
- int pv = ((event.dataA() & 0xff)<<8) + (event.dataB() & 0xff);
- song->putEvent(pv);
- }
-
- //if(_recordFifo.put(MidiPlayEvent(event)))
- // printf("MidiJackDevice::recordEvent: fifo overflow\n");
-
- // p3.3.38
- // Do not bother recording if it is NOT actually being used by a port.
- // Because from this point on, process handles things, by selected port.
- if(_port == -1)
- return;
-
- // Split the events up into channel fifos. Special 'channel' number 17 for sysex events.
- unsigned int ch = (typ == ME_SYSEX)? MIDI_CHANNELS : event.channel();
- if(_recordFifo[ch].put(MidiPlayEvent(event)))
- printf("MidiJackDevice::recordEvent: fifo channel %d overflow\n", ch);
- }
-
-//---------------------------------------------------------
-// midiReceived
-//---------------------------------------------------------
-
-void MidiJackDevice::eventReceived(jack_midi_event_t* ev)
- {
- MidiRecordEvent event;
- event.setB(0);
-
- // NOTE: From MusE-2. Not done here in Muse-1 (yet).
- // move all events 2*segmentSize into the future to get
- // jitterfree playback
- //
- // cycle n-1 n n+1
- // -+----------+----------+----------+-
- // ^ ^ ^
- // catch process play
- //
-// const SeqTime* st = audio->seqTime();
-
- //unsigned curFrame = st->startFrame() + segmentSize;
-// unsigned curFrame = st->lastFrameTime;
- //int frameOffset = audio->getFrameOffset();
- unsigned pos = audio->pos().frame();
-
- //event.setTime(pos + ev->time);
- event.setTime(extSyncFlag.value() ? lastExtMidiSyncTick : (pos + ev->time));
-
- event.setChannel(*(ev->buffer) & 0xf);
- int type = *(ev->buffer) & 0xf0;
- int a = *(ev->buffer + 1) & 0x7f;
- int b = *(ev->buffer + 2) & 0x7f;
- event.setType(type);
- switch(type) {
- case ME_NOTEON:
- case ME_NOTEOFF:
- case ME_CONTROLLER:
- event.setA(*(ev->buffer + 1));
- event.setB(*(ev->buffer + 2));
- break;
- case ME_PROGRAM:
- case ME_AFTERTOUCH:
- event.setA(*(ev->buffer + 1));
- break;
-
- case ME_PITCHBEND:
- event.setA(((b << 7) + a) - 8192);
- break;
-
- case ME_SYSEX:
- {
- int type = *(ev->buffer) & 0xff;
- switch(type)
- {
- case ME_SYSEX:
-
- // TODO: Deal with large sysex, which are broken up into chunks!
- // For now, do not accept if the last byte is not EOX, meaning it's a chunk with more chunks to follow.
- if(*(((unsigned char*)ev->buffer) + ev->size - 1) != ME_SYSEX_END)
- {
- printf("MidiJackDevice::eventReceived sysex chunks not supported!\n");
- return;
- }
-
- //event.setTime(0); // mark as used
- event.setType(ME_SYSEX);
- event.setData((unsigned char*)(ev->buffer + 1), ev->size - 2);
- break;
- case ME_MTC_QUARTER:
- if(_port != -1)
- midiSeq->mtcInputQuarter(_port, *(ev->buffer + 1));
- return;
- case ME_SONGPOS:
- if(_port != -1)
- midiSeq->setSongPosition(_port, *(ev->buffer + 1) | (*(ev->buffer + 2) >> 2 )); // LSB then MSB
- return;
- //case ME_SONGSEL:
- //case ME_TUNE_REQ:
- //case ME_SENSE:
- case ME_CLOCK:
- case ME_TICK:
- case ME_START:
- case ME_CONTINUE:
- case ME_STOP:
- if(_port != -1)
- midiSeq->realtimeSystemInput(_port, type);
- return;
- //case ME_SYSEX_END:
- //break;
- // return;
- default:
- printf("MidiJackDevice::eventReceived unsupported system event 0x%02x\n", type);
- return;
- }
- }
- //return;
- break;
- default:
- printf("MidiJackDevice::eventReceived unknown event 0x%02x\n", type);
- //printf("MidiJackDevice::eventReceived unknown event 0x%02x size:%d buf:0x%02x 0x%02x 0x%02x ...0x%02x\n", type, ev->size, *(ev->buffer), *(ev->buffer + 1), *(ev->buffer + 2), *(ev->buffer + (ev->size - 1)));
- return;
- }
-
- if (midiInputTrace) {
- printf("MidiInput<%s>: ", name().toLatin1().constData());
- event.dump();
- }
-
- #ifdef JACK_MIDI_DEBUG
- printf("MidiJackDevice::eventReceived time:%d type:%d ch:%d A:%d B:%d\n", event.time(), event.type(), event.channel(), event.dataA(), event.dataB());
- #endif
-
- // Let recordEvent handle it from here, with timestamps, filtering, gui triggering etc.
- recordEvent(event);
- }
-
-//---------------------------------------------------------
-// collectMidiEvents
-//---------------------------------------------------------
-
-void MidiJackDevice::collectMidiEvents()
-{
- if(!_readEnable)
- return;
-
- //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(_in_client_jackport, segmentSize); // p3.3.55
-
- jack_midi_event_t event;
- jack_nframes_t eventCount = jack_midi_get_event_count(port_buf);
- for (jack_nframes_t i = 0; i < eventCount; ++i)
- {
- jack_midi_event_get(&event, port_buf, i);
-
- #ifdef JACK_MIDI_DEBUG
- printf("MidiJackDevice::collectMidiEvents number:%d time:%d\n", i, event.time);
- #endif
-
- eventReceived(&event);
- }
-}
-
-//---------------------------------------------------------
-// putEvent
-// return true if event cannot be delivered
-//---------------------------------------------------------
-
-bool MidiJackDevice::putEvent(const MidiPlayEvent& ev)
-{
- if(!_writeEnable)
- //return true;
- return false;
-
- #ifdef JACK_MIDI_DEBUG
- printf("MidiJackDevice::putEvent time:%d type:%d ch:%d A:%d B:%d\n", ev.time(), ev.type(), ev.channel(), ev.dataA(), ev.dataB());
- #endif
-
- bool rv = eventFifo.put(ev);
- if(rv)
- printf("MidiJackDevice::putEvent: port overflow\n");
-
- return rv;
-}
-
-//---------------------------------------------------------
-// queueEvent
-// return true if successful
-//---------------------------------------------------------
-
-//void JackAudioDevice::putEvent(Port port, const MidiEvent& e)
-bool MidiJackDevice::queueEvent(const MidiPlayEvent& e)
-//bool MidiJackDevice::queueEvent(const MidiPlayEvent& e)
-{
- // Perhaps we can find use for this value later, together with the Jack midi MusE port(s).
- // No big deal if not. Not used for now.
- //int port = e.port();
-
- //if(port >= JACK_MIDI_CHANNELS)
- // return false;
-
- //if (midiOutputTrace) {
- // printf("MidiOut<%s>: jackMidi: ", portName(port).toLatin1().constData());
- // e.dump();
- // }
-
- //if(debugMsg)
- // printf("MidiJackDevice::queueEvent\n");
-
- //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(_out_client_jackport, segmentSize); // p3.3.55
-
- //unsigned frameCounter = ->frameTime();
- int frameOffset = audio->getFrameOffset();
- unsigned pos = audio->pos().frame();
- int ft = e.time() - frameOffset - pos;
-
- if (ft < 0)
- ft = 0;
- if (ft >= (int)segmentSize) {
- printf("MidiJackDevice::queueEvent: Event time:%d out of range. offset:%d ft:%d (seg=%d)\n", e.time(), frameOffset, ft, segmentSize);
- if (ft > (int)segmentSize)
- ft = segmentSize - 1;
- }
-
- #ifdef JACK_MIDI_DEBUG
- printf("MidiJackDevice::queueEvent time:%d type:%d ch:%d A:%d B:%d\n", e.time(), e.type(), e.channel(), e.dataA(), e.dataB());
- #endif
-
- switch(e.type()) {
- case ME_NOTEON:
- case ME_NOTEOFF:
- case ME_POLYAFTER:
- case ME_CONTROLLER:
- case ME_PITCHBEND:
- {
- #ifdef JACK_MIDI_DEBUG
- printf("MidiJackDevice::queueEvent note on/off polyafter controller or pitch\n");
- #endif
-
- unsigned char* p = jack_midi_event_reserve(pb, ft, 3);
- if (p == 0) {
- fprintf(stderr, "MidiJackDevice::queueEvent #1: buffer overflow, event lost\n");
- return false;
- }
- p[0] = e.type() | e.channel();
- p[1] = e.dataA();
- p[2] = e.dataB();
- }
- break;
-
- case ME_PROGRAM:
- case ME_AFTERTOUCH:
- {
- #ifdef JACK_MIDI_DEBUG
- printf("MidiJackDevice::queueEvent program or aftertouch\n");
- #endif
-
- unsigned char* p = jack_midi_event_reserve(pb, ft, 2);
- if (p == 0) {
- fprintf(stderr, "MidiJackDevice::queueEvent #2: buffer overflow, event lost\n");
- return false;
- }
- p[0] = e.type() | e.channel();
- p[1] = e.dataA();
- }
- break;
- case ME_SYSEX:
- {
- #ifdef JACK_MIDI_DEBUG
- printf("MidiJackDevice::queueEvent sysex\n");
- #endif
-
- const unsigned char* data = e.data();
- int len = e.len();
- unsigned char* p = jack_midi_event_reserve(pb, ft, len+2);
- if (p == 0) {
- fprintf(stderr, "MidiJackDevice::queueEvent #3: buffer overflow, event lost\n");
- return false;
- }
- p[0] = 0xf0;
- p[len+1] = 0xf7;
- memcpy(p+1, data, len);
- }
- break;
- case ME_SONGPOS:
- case ME_CLOCK:
- case ME_START:
- case ME_CONTINUE:
- case ME_STOP:
- printf("MidiJackDevice::queueEvent: event type %x not supported\n", e.type());
- return false;
- break;
- }
-
- return true;
-}
-
-//---------------------------------------------------------
-// processEvent
-//---------------------------------------------------------
-
-void MidiJackDevice::processEvent(const MidiPlayEvent& event)
-{
- //int frameOffset = audio->getFrameOffset();
- //unsigned pos = audio->pos().frame();
-
- int chn = event.channel();
- unsigned t = event.time();
- int a = event.dataA();
- int b = event.dataB();
- // Perhaps we can find use for this value later, together with the Jack midi MusE port(s).
- // No big deal if not. Not used for now.
- int port = event.port();
-
- // TODO: No sub-tick playback resolution yet, with external sync.
- // Just do this 'standard midi 64T timing thing' for now until we figure out more precise external timings.
- // Does require relatively short audio buffers, in order to catch the resolution, but buffer <= 256 should be OK...
- // Tested OK so far with 128.
- if(extSyncFlag.value())
- t = audio->getFrameOffset() + audio->pos().frame();
- //t = frameOffset + pos;
-
- #ifdef JACK_MIDI_DEBUG
- printf("MidiJackDevice::processEvent time:%d type:%d ch:%d A:%d B:%d\n", event.time(), event.type(), event.channel(), event.dataA(), event.dataB());
- #endif
-
- if(event.type() == ME_PROGRAM)
- {
- // don't output program changes for GM drum channel
- //if (!(song->mtype() == MT_GM && chn == 9)) {
- int hb = (a >> 16) & 0xff;
- int lb = (a >> 8) & 0xff;
- int pr = a & 0x7f;
-
- // p3.3.44
- //printf("MidiJackDevice::processEvent ME_PROGRAM time:%d type:%d ch:%d A:%d B:%d hb:%d lb:%d pr:%d\n",
- // event.time(), event.type(), event.channel(), event.dataA(), event.dataB(), hb, lb, pr);
-
- if (hb != 0xff)
- queueEvent(MidiPlayEvent(t, port, chn, ME_CONTROLLER, CTRL_HBANK, hb));
- if (lb != 0xff)
- queueEvent(MidiPlayEvent(t+1, port, chn, ME_CONTROLLER, CTRL_LBANK, lb));
- queueEvent(MidiPlayEvent(t+2, port, chn, ME_PROGRAM, pr, 0));
- // }
- }
- else
- if(event.type() == ME_PITCHBEND)
- {
- int v = a + 8192;
- // p3.3.44
- //printf("MidiJackDevice::processEvent ME_PITCHBEND v:%d time:%d type:%d ch:%d A:%d B:%d\n", v, event.time(), event.type(), event.channel(), event.dataA(), event.dataB());
-
- queueEvent(MidiPlayEvent(t, port, chn, ME_PITCHBEND, v & 0x7f, (v >> 7) & 0x7f));
- }
- else
- if(event.type() == ME_CONTROLLER)
- {
- //int a = event.dataA();
- //int b = event.dataB();
- // Perhaps we can find use for this value later, together with the Jack midi MusE port(s).
- // No big deal if not. Not used for now.
- //int port = event.port();
-
- int nvh = 0xff;
- int nvl = 0xff;
- if(_port != -1)
- {
- int nv = midiPorts[_port].nullSendValue();
- if(nv != -1)
- {
- nvh = (nv >> 8) & 0xff;
- nvl = nv & 0xff;
- }
- }
-
- if(a == CTRL_PITCH)
- {
- int v = b + 8192;
- // p3.3.44
- //printf("MidiJackDevice::processEvent CTRL_PITCH v:%d time:%d type:%d ch:%d A:%d B:%d\n", v, event.time(), event.type(), event.channel(), event.dataA(), event.dataB());
-
- queueEvent(MidiPlayEvent(t, port, chn, ME_PITCHBEND, v & 0x7f, (v >> 7) & 0x7f));
- }
- else if (a == CTRL_PROGRAM)
- {
- // don't output program changes for GM drum channel
- //if (!(song->mtype() == MT_GM && chn == 9)) {
- int hb = (b >> 16) & 0xff;
- int lb = (b >> 8) & 0xff;
- int pr = b & 0x7f;
-
- // p3.3.44
- //printf("MidiJackDevice::processEvent CTRL_PROGRAM time:%d type:%d ch:%d A:%d B:%d hb:%d lb:%d pr:%d\n",
- // event.time(), event.type(), event.channel(), event.dataA(), event.dataB(), hb, lb, pr);
-
- if (hb != 0xff)
- queueEvent(MidiPlayEvent(t, port, chn, ME_CONTROLLER, CTRL_HBANK, hb));
- if (lb != 0xff)
- queueEvent(MidiPlayEvent(t+1, port, chn, ME_CONTROLLER, CTRL_LBANK, lb));
- queueEvent(MidiPlayEvent(t+2, port, chn, ME_PROGRAM, pr, 0));
- // }
- }
- /*
- else if (a == CTRL_MASTER_VOLUME)
- {
- unsigned char sysex[] = {
- 0x7f, 0x7f, 0x04, 0x01, 0x00, 0x00
- };
- sysex[1] = deviceId();
- sysex[4] = b & 0x7f;
- sysex[5] = (b >> 7) & 0x7f;
- queueEvent(MidiPlayEvent(t, port, ME_SYSEX, sysex, 6));
- }
- */
- else if (a < CTRL_14_OFFSET)
- { // 7 Bit Controller
- queueEvent(event);
- //queueEvent(museport, MidiPlayEvent(t, port, chn, event));
- }
- else if (a < CTRL_RPN_OFFSET)
- { // 14 bit high resolution controller
- int ctrlH = (a >> 8) & 0x7f;
- int ctrlL = a & 0x7f;
- int dataH = (b >> 7) & 0x7f;
- int dataL = b & 0x7f;
- queueEvent(MidiPlayEvent(t, port, chn, ME_CONTROLLER, ctrlH, dataH));
- queueEvent(MidiPlayEvent(t+1, port, chn, ME_CONTROLLER, ctrlL, dataL));
- }
- else if (a < CTRL_NRPN_OFFSET)
- { // RPN 7-Bit Controller
- int ctrlH = (a >> 8) & 0x7f;
- int ctrlL = a & 0x7f;
- queueEvent(MidiPlayEvent(t, port, chn, ME_CONTROLLER, CTRL_HRPN, ctrlH));
- queueEvent(MidiPlayEvent(t+1, port, chn, ME_CONTROLLER, CTRL_LRPN, ctrlL));
- queueEvent(MidiPlayEvent(t+2, port, chn, ME_CONTROLLER, CTRL_HDATA, b));
-
- t += 3;
- // Select null parameters so that subsequent data controller events do not upset the last *RPN controller.
- //sendNullRPNParams(chn, false);
- if(nvh != 0xff)
- {
- queueEvent(MidiPlayEvent(t, port, chn, ME_CONTROLLER, CTRL_HRPN, nvh & 0x7f));
- t += 1;
- }
- if(nvl != 0xff)
- queueEvent(MidiPlayEvent(t, port, chn, ME_CONTROLLER, CTRL_LRPN, nvl & 0x7f));
- }
- //else if (a < CTRL_RPN14_OFFSET)
- else if (a < CTRL_INTERNAL_OFFSET)
- { // NRPN 7-Bit Controller
- int ctrlH = (a >> 8) & 0x7f;
- int ctrlL = a & 0x7f;
- queueEvent(MidiPlayEvent(t, port, chn, ME_CONTROLLER, CTRL_HNRPN, ctrlH));
- queueEvent(MidiPlayEvent(t+1, port, chn, ME_CONTROLLER, CTRL_LNRPN, ctrlL));
- queueEvent(MidiPlayEvent(t+2, port, chn, ME_CONTROLLER, CTRL_HDATA, b));
-
- t += 3;
- //sendNullRPNParams(chn, true);
- if(nvh != 0xff)
- {
- queueEvent(MidiPlayEvent(t, port, chn, ME_CONTROLLER, CTRL_HNRPN, nvh & 0x7f));
- t += 1;
- }
- if(nvl != 0xff)
- queueEvent(MidiPlayEvent(t, port, chn, ME_CONTROLLER, CTRL_LNRPN, nvl & 0x7f));
- }
- else if (a < CTRL_NRPN14_OFFSET)
- { // RPN14 Controller
- int ctrlH = (a >> 8) & 0x7f;
- int ctrlL = a & 0x7f;
- int dataH = (b >> 7) & 0x7f;
- int dataL = b & 0x7f;
- queueEvent(MidiPlayEvent(t, port, chn, ME_CONTROLLER, CTRL_HRPN, ctrlH));
- queueEvent(MidiPlayEvent(t+1, port, chn, ME_CONTROLLER, CTRL_LRPN, ctrlL));
- queueEvent(MidiPlayEvent(t+2, port, chn, ME_CONTROLLER, CTRL_HDATA, dataH));
- queueEvent(MidiPlayEvent(t+3, port, chn, ME_CONTROLLER, CTRL_LDATA, dataL));
-
- t += 4;
- //sendNullRPNParams(chn, false);
- if(nvh != 0xff)
- {
- queueEvent(MidiPlayEvent(t, port, chn, ME_CONTROLLER, CTRL_HRPN, nvh & 0x7f));
- t += 1;
- }
- if(nvl != 0xff)
- queueEvent(MidiPlayEvent(t, port, chn, ME_CONTROLLER, CTRL_LRPN, nvl & 0x7f));
- }
- else if (a < CTRL_NONE_OFFSET)
- { // NRPN14 Controller
- int ctrlH = (a >> 8) & 0x7f;
- int ctrlL = a & 0x7f;
- int dataH = (b >> 7) & 0x7f;
- int dataL = b & 0x7f;
- queueEvent(MidiPlayEvent(t, port, chn, ME_CONTROLLER, CTRL_HNRPN, ctrlH));
- queueEvent(MidiPlayEvent(t+1, port, chn, ME_CONTROLLER, CTRL_LNRPN, ctrlL));
- queueEvent(MidiPlayEvent(t+2, port, chn, ME_CONTROLLER, CTRL_HDATA, dataH));
- queueEvent(MidiPlayEvent(t+3, port, chn, ME_CONTROLLER, CTRL_LDATA, dataL));
-
- t += 4;
- //sendNullRPNParams(chn, true);
- if(nvh != 0xff)
- {
- queueEvent(MidiPlayEvent(t, port, chn, ME_CONTROLLER, CTRL_HNRPN, nvh & 0x7f));
- t += 1;
- }
- if(nvl != 0xff)
- queueEvent(MidiPlayEvent(t, port, chn, ME_CONTROLLER, CTRL_LNRPN, nvl & 0x7f));
- }
- else
- {
- printf("MidiJackDevice::processEvent: unknown controller type 0x%x\n", a);
- }
- }
- else
- {
- queueEvent(event);
- //queueEvent(MidiPlayEvent(t, port, chn, event));
- }
-}
-
-//---------------------------------------------------------
-// processMidi called from audio process only.
-//---------------------------------------------------------
-
-void MidiJackDevice::processMidi()
-{
- //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(_out_client_jackport, segmentSize); // p3.3.55
- jack_midi_clear_buffer(port_buf);
-
- while(!eventFifo.isEmpty())
- {
- MidiPlayEvent e(eventFifo.get());
- int evTime = e.time();
- // Is event marked to be played immediately?
- if(evTime == 0)
- {
- // Nothing to do but stamp the event to be queued for frame 0+.
- //e.setTime(frameOffset + pos);
- e.setTime(audio->getFrameOffset() + audio->pos().frame());
- }
-
- #ifdef JACK_MIDI_DEBUG
- printf("MidiJackDevice::processMidi eventFifo time:%d type:%d ch:%d A:%d B:%d\n", e.time(), e.type(), e.channel(), e.dataA(), e.dataB());
- #endif
-
- //el->insert(eventFifo.get());
- //el->insert(e);
- processEvent(e);
- }
-
- MPEventList* el = playEvents();
- if(el->empty())
- return;
-
- iMPEvent i = nextPlayEvent();
- for(; i != el->end(); ++i)
- {
- // p3.3.39 Update hardware state so knobs and boxes are updated. Optimize to avoid re-setting existing values.
- // Same code as in MidiPort::sendEvent()
- if(_port != -1)
- {
- MidiPort* mp = &midiPorts[_port];
- if(i->type() == ME_CONTROLLER)
- {
- int da = i->dataA();
- int db = i->dataB();
- db = mp->limitValToInstrCtlRange(da, db);
- if(!mp->setHwCtrlState(i->channel(), da, db))
- continue;
- //mp->setHwCtrlState(i->channel(), da, db);
- }
- else
- if(i->type() == ME_PITCHBEND)
- {
- // p3.3.44
- //printf("MidiJackDevice::processMidi playEvents ME_PITCHBEND time:%d type:%d ch:%d A:%d B:%d\n", (*i).time(), (*i).type(), (*i).channel(), (*i).dataA(), (*i).dataB());
-
- int da = mp->limitValToInstrCtlRange(CTRL_PITCH, i->dataA());
- if(!mp->setHwCtrlState(i->channel(), CTRL_PITCH, da))
- continue;
- //mp->setHwCtrlState(i->channel(), CTRL_PITCH, da);
-
- //(MidiPlayEvent(t, port, chn, ME_PITCHBEND, v & 0x7f, (v >> 7) & 0x7f));
- }
- else
- if(i->type() == ME_PROGRAM)
- {
- if(!mp->setHwCtrlState(i->channel(), CTRL_PROGRAM, i->dataA()))
- continue;
- //mp->setHwCtrlState(i->channel(), CTRL_PROGRAM, i->dataA());
- }
- }
-
- processEvent(*i);
- }
-
- setNextPlayEvent(i);
-}
-
-//---------------------------------------------------------
-// initMidiJack
-// return true on error
-//---------------------------------------------------------
-
-bool initMidiJack()
-{
- /*
- int adr = 0;
-
- memset(jack_midi_out_data, 0, JACK_MIDI_CHANNELS * sizeof(muse_jack_midi_buffer));
- memset(jack_midi_in_data, 0, JACK_MIDI_CHANNELS * sizeof(muse_jack_midi_buffer));
-
- MidiJackDevice* dev = new MidiJackDevice(adr, QString("jack-midi"));
- dev->setrwFlags(3); // set read and write flags
-
- if(pipe(jackmidi_pi) < 0){
- fprintf(stderr, "cant create midi-jack input pipe\n");
- }
- if(pipe(jackmidi_po) < 0){
- fprintf(stderr, "cant create midi-jack output pipe\n");
- }
-
- midiDevices.add(dev);
-
- gmdev = dev; // proclaim the global jack-midi instance
-
- //jackScanMidiPorts();
- */
-
- return false;
-}
-
-/*
-struct JackPort {
- int adr;
- //char* name;
- QString name;
- int flags;
- //JackPort(int a, const char* s, int f) {
- JackPort(int a, const QString& s, int f) {
- adr = a;
- //name = strdup(s);
- name = QString(s);
- flags = f;
- }
- };
-
-
-static std::list<JackPort> portList;
-
-//---------------------------------------------------------
-// jackScanMidiPorts
-//---------------------------------------------------------
-
-void jackScanMidiPorts()
-{
- int adr;
- const char* name;
-
- portList.clear();
- adr = 0;
- name = strdup("namex");
- portList.push_back(JackPort(adr, name, 0));
- //
- // check for devices to add
- //
- for (std::list<JackPort>::iterator k = portList.begin(); k != portList.end(); ++k) {
- iMidiDevice i = midiDevices.begin();
- for (;i != midiDevices.end(); ++i) {
- //MidiJackDevice* d = dynamic_cast<MidiJackDevice*>(*i);
- break;
- //if (d == 0) continue;
- //if ((k->adr.client == d->adr.client) && (k->adr.port == d->adr.port)) {
- // break;
- //}
- }
- if (i == midiDevices.end()) {
- // add device
- MidiJackDevice* dev = new MidiJackDevice(k->adr, QString(k->name));
- dev->setrwFlags(k->flags);
- midiDevices.add(dev);
- }
- }
-}
-*/
-
-/*
-//---------------------------------------------------------
-// processInput
-//---------------------------------------------------------
-static void handle_jack_midi_in(int channel)
-{
- MidiRecordEvent event;
- int t,n,v;
- t = jack_midi_in_data[channel].buffer[0];
- n = jack_midi_in_data[channel].buffer[1];
- v = jack_midi_in_data[channel].buffer[2];
-
- event.setType(0); // mark as unused
- event.setPort(gmdev->midiPort());
- event.setB(0);
-
- if(t == 0x90){ // note on
- fprintf(stderr, "jackProcessMidiInput note-on\n");
- event.setChannel(channel);
- event.setType(ME_NOTEON);
- event.setA(n);
- event.setB(v);
- }else if (t == 0x80){ // note off
- fprintf(stderr, "jackProcessMidiInput note-off\n");
- event.setChannel(channel);
- event.setType(ME_NOTEOFF);
- event.setA(n);
- event.setB(v);
- }else{
- fprintf(stderr, "WARNING: unknown midi-in on channel %d: %x,%x,%x\n",
- channel, t, n, v);
- return;
- }
- if(event.type()){
- gmdev->recordEvent(event);
- midiPorts[gmdev->midiPort()].syncInfo().trigActDetect(event.channel());
- }
-}
-
-void MidiJackDevice::processInput()
-{
- char buf;
- int i,s;
- read(gmdev->selectRfd(), &buf, 1);
-
- s = 1;
- for(i = 0; i < JACK_MIDI_CHANNELS; i++){
- if(jack_midi_in_data[i].buffer[3]){
- s = 0;
- handle_jack_midi_in(i);
- jack_midi_in_data[i].buffer[3] = 0;
- }
- }
-}
-
-*/