summaryrefslogtreecommitdiff
path: root/attic/muse_qt4_evolution/muse/jack.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'attic/muse_qt4_evolution/muse/jack.cpp')
-rw-r--r--attic/muse_qt4_evolution/muse/jack.cpp886
1 files changed, 886 insertions, 0 deletions
diff --git a/attic/muse_qt4_evolution/muse/jack.cpp b/attic/muse_qt4_evolution/muse/jack.cpp
new file mode 100644
index 00000000..bc372357
--- /dev/null
+++ b/attic/muse_qt4_evolution/muse/jack.cpp
@@ -0,0 +1,886 @@
+//=============================================================================
+// MusE
+// Linux Music Editor
+// $Id:$
+//
+// Copyright (C) 2002-2006 by Werner Schweer and others
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//=============================================================================
+
+#include "config.h"
+#include "al/al.h"
+#include "al/tempo.h"
+#include "audio.h"
+#include "globals.h"
+#include "song.h"
+#include "jackaudio.h"
+#include "track.h"
+#include "midiinport.h"
+
+#ifdef VST_SUPPORT
+#include <fst.h>
+#endif
+
+JackAudio* jackAudio;
+
+//---------------------------------------------------------
+// init
+//---------------------------------------------------------
+
+bool JackAudio::init()
+ {
+ return true;
+ }
+
+//---------------------------------------------------------
+// jack_thread_init
+//---------------------------------------------------------
+
+static void jack_thread_init (void* /*data*/)
+ {
+#ifdef VST_SUPPORT
+ if (loadVST)
+ fst_adopt_thread();
+#endif
+ }
+
+//---------------------------------------------------------
+// timebase_callback
+//---------------------------------------------------------
+
+static void timebase_callback(jack_transport_state_t /* state */,
+ jack_nframes_t /* nframes */,
+ jack_position_t* pos,
+ int /* new_pos */,
+ void*)
+ {
+ AL::Pos p(pos->frame, AL::FRAMES);
+ pos->valid = JackPositionBBT;
+ p.mbt(&pos->bar, &pos->beat, &pos->tick);
+ pos->bar++;
+ pos->beat++;
+ pos->bar_start_tick = Pos(pos->bar, 0, 0).tick();
+ //
+ // dummy:
+ //
+ pos->beats_per_bar = 4;
+ pos->beat_type = 4;
+ pos->ticks_per_beat = 384;
+ int tempo = AL::tempomap.tempo(p.tick());
+ pos->beats_per_minute = (60000000.0 / tempo) * AL::tempomap.globalTempo()/100.0;
+ }
+
+//---------------------------------------------------------
+// processAudio
+// JACK callback
+//---------------------------------------------------------
+
+int JackAudio::processAudio(jack_nframes_t frames, void*)
+ {
+ jackAudio->_frameCounter += frames;
+
+ int jackState = jackAudio->getTransportState();
+ segmentSize = frames;
+ if (audioState == AUDIO_RUNNING)
+ audio->process((unsigned long)frames, jackState);
+ else if (audioState == AUDIO_STOP) {
+ if (debugMsg)
+ puts("jack calling when audio is stopped!\n");
+ }
+ else if (audioState == AUDIO_START1)
+ audioState = AUDIO_START2;
+ return 0;
+ }
+
+//---------------------------------------------------------
+// getTransportState
+//---------------------------------------------------------
+
+int JackAudio::getTransportState()
+ {
+ int jackState;
+ transportState = jack_transport_query(_client, &pos);
+ switch (jackAudio->transportState) {
+ case JackTransportStopped:
+ jackState = Audio::STOP;
+ break;
+ case JackTransportLooping:
+ case JackTransportRolling:
+ jackState = Audio::PLAY;
+ break;
+ case JackTransportStarting:
+ jackState = Audio::START_PLAY;
+ break;
+ default:
+ jackState = Audio::STOP;
+ break;
+ }
+ return jackState;
+ }
+
+//---------------------------------------------------------
+// processSync
+// return TRUE (non-zero) when ready to roll.
+//---------------------------------------------------------
+
+static int processSync(jack_transport_state_t state, jack_position_t* pos, void*)
+ {
+ int audioState = Audio::STOP;
+ switch (state) {
+ case JackTransportStopped:
+ audioState = Audio::STOP;
+ break;
+ case JackTransportLooping:
+ case JackTransportRolling:
+ audioState = Audio::PLAY;
+ break;
+ case JackTransportStarting:
+ audioState = Audio::START_PLAY;
+ break;
+ }
+ unsigned frame = pos->frame;
+ return audio->sync(audioState, frame);
+ }
+
+//---------------------------------------------------------
+// processShutdown
+//---------------------------------------------------------
+
+static void processShutdown(void*)
+ {
+ audio->shutdown();
+
+ for (int i = 0; i < 10; ++i) {
+ if (audioState == AUDIO_STOP)
+ break;
+ sleep(1);
+ }
+ if (audioState == AUDIO_RUNNING)
+ fprintf(stderr, "MusE: sequencer still running, something is very wrong.\n");
+ jackAudio->zeroClientPtr(); // jack disconnect client no longer valid
+ }
+
+//---------------------------------------------------------
+// jackError
+//---------------------------------------------------------
+
+static void jackError(const char* s)
+ {
+ fprintf(stderr, "JACK ERROR: %s\n", s);
+ }
+
+//---------------------------------------------------------
+// noJackError
+//---------------------------------------------------------
+
+static void noJackError(const char* /* s */)
+ {
+ }
+
+//---------------------------------------------------------
+// JackAudio
+//---------------------------------------------------------
+
+JackAudio::JackAudio(jack_client_t* cl, char* name)
+ : AudioDriver()
+ {
+ strcpy(jackRegisteredName, name);
+ _client = cl;
+ _frameCounter = 0;
+ }
+
+//---------------------------------------------------------
+// ~JackAudio
+//---------------------------------------------------------
+
+JackAudio::~JackAudio()
+ {
+ if (_client) {
+ if (jack_client_close(_client)) {
+ fprintf(stderr, "jack_client_close() failed: %s\n",
+ strerror(errno));
+ }
+ }
+ _client = 0;
+ }
+
+//---------------------------------------------------------
+// getJackName()
+//---------------------------------------------------------
+
+char* JackAudio::getJackName()
+ {
+ return jackRegisteredName;
+ }
+
+//---------------------------------------------------------
+// restart
+//---------------------------------------------------------
+
+bool JackAudio::restart()
+ {
+ printf("JackAudio::restart\n");
+ _client = jack_client_new(jackRegisteredName);
+ if (!_client)
+ return true;
+ registerClient();
+ return false;
+ }
+
+//---------------------------------------------------------
+// bufsize_callback
+//---------------------------------------------------------
+
+static int bufsize_callback(jack_nframes_t n, void*)
+ {
+ printf("JACK: buffersize changed %d\n", n);
+ return 0;
+ }
+
+//---------------------------------------------------------
+// freewheel_callback
+//---------------------------------------------------------
+
+static void freewheel_callback(int starting, void*)
+ {
+ audio->setFreewheel(starting);
+ }
+
+//---------------------------------------------------------
+// srate_callback
+//---------------------------------------------------------
+
+static int srate_callback(jack_nframes_t n, void*)
+ {
+ if (debugMsg)
+ printf("JACK: sample rate changed: %d\n", n);
+ return 0;
+ }
+
+//---------------------------------------------------------
+// registration_callback
+//---------------------------------------------------------
+
+static void registration_callback(jack_port_id_t, int, void*)
+ {
+ if (debugMsg)
+ printf("JACK: registration changed\n");
+ }
+
+//---------------------------------------------------------
+// graph_callback
+// this is called from jack when the connections
+// changed
+//---------------------------------------------------------
+
+static int graph_callback(void*)
+ {
+ // we cannot call JackAudio::graphChanged() from this
+ // context, so we send a message to the gui thread which in turn
+ // calls graphChanged()
+
+ audio->sendMsgToGui(MSG_GRAPH_CHANGED);
+ if (debugMsg)
+ printf("JACK: graph changed!\n");
+ return 0;
+ }
+
+//---------------------------------------------------------
+// JackAudio::graphChanged
+// this is called from song in gui context triggered
+// by graph_callback()
+//---------------------------------------------------------
+
+void JackAudio::graphChanged()
+ {
+ RouteList rr, ra;
+
+ InputList* il = song->inputs();
+ for (iAudioInput ii = il->begin(); ii != il->end(); ++ii) {
+ AudioInput* it = *ii;
+ int channels = it->channels();
+ RouteList* irl = it->inRoutes();
+
+ for (int channel = 0; channel < channels; ++channel) {
+ jack_port_t* port = it->jackPort(channel).jackPort();
+ if (port == 0)
+ continue;
+ const char** ports = jack_port_get_all_connections(_client, port);
+
+ //---------------------------------------
+ // check for disconnects
+ //---------------------------------------
+
+ foreach (const Route& r, *irl) {
+ if (r.dst.channel != channel)
+ continue;
+ const char* name = jack_port_name(r.src.port.jackPort());
+ bool found = false;
+ for (const char** pn = ports; pn && *pn; ++pn) {
+ if (strcmp(*pn, name) == 0) {
+ found = true;
+ break;
+ }
+ }
+ if (!found)
+ rr.append(r);
+ }
+
+ //---------------------------------------
+ // check for connects
+ //---------------------------------------
+
+ if (ports) {
+ for (const char** pn = ports; *pn; ++pn) {
+ bool found = false;
+ foreach(const Route& r, *irl) {
+ if (r.dst.channel != channel)
+ continue;
+ const char* name = jack_port_name(r.src.port.jackPort());
+ if (strcmp(*pn, name) == 0) {
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ Route a;
+ Port port(jack_port_by_name(_client, *pn));
+ a.src = RouteNode(port, -1, RouteNode::AUDIOPORT);
+ a.dst = RouteNode(it, channel);
+ ra.append(a);
+ }
+ }
+ free(ports);
+ }
+ }
+ }
+
+// printf(" input: remove %d add %d routes\n", rr.size(), ra.size());
+ foreach(Route r, rr)
+ audio->msgRemoveRoute1(r);
+ foreach(Route r, ra)
+ audio->msgAddRoute1(r);
+ rr.clear();
+ ra.clear();
+
+ OutputList* ol = song->outputs();
+ for (iAudioOutput ii = ol->begin(); ii != ol->end(); ++ii) {
+ AudioOutput* it = *ii;
+ int channels = it->channels();
+ for (int channel = 0; channel < channels; ++channel) {
+ jack_port_t* port = it->jackPort(channel).jackPort();
+ if (port == 0)
+ continue;
+ const char** ports = jack_port_get_all_connections(_client, port);
+ RouteList* rl = it->outRoutes();
+
+ //---------------------------------------
+ // check for disconnects
+ //---------------------------------------
+
+ foreach(const Route& r, *rl) {
+ if (r.src.channel != channel)
+ continue;
+ const char* name = jack_port_name(r.dst.port.jackPort());
+ bool found = false;
+ const char** pn = ports;
+ while (pn && *pn) {
+ if (strcmp(*pn, name) == 0) {
+ found = true;
+ break;
+ }
+ ++pn;
+ }
+ if (!found)
+ rr.append(r);
+ }
+
+ //---------------------------------------
+ // check for connects
+ //---------------------------------------
+
+ if (ports) {
+ const char** pn = ports;
+ while (*pn) {
+ bool found = false;
+ foreach (const Route& r, *rl) {
+ if (r.src.channel != channel)
+ continue;
+ const char* name = jack_port_name(r.dst.port.jackPort());
+ if (strcmp(*pn, name) == 0) {
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ Route a;
+ Port port(jack_port_by_name(_client, *pn));
+ a.src = RouteNode(it, channel, RouteNode::TRACK);
+ a.dst = RouteNode(port, -1, RouteNode::AUDIOPORT);
+ ra.append(a);
+ }
+ ++pn;
+ }
+ free(ports);
+ }
+ }
+ }
+// printf(" output: remove %d add %d routes\n", rr.size(), ra.size());
+ foreach(Route r, rr)
+ audio->msgRemoveRoute1(r);
+ foreach(Route r, ra)
+ audio->msgAddRoute1(r);
+ }
+
+//---------------------------------------------------------
+// register
+//---------------------------------------------------------
+
+void JackAudio::registerClient()
+ {
+ jack_set_process_callback(_client, processAudio, 0);
+ jack_set_sync_callback(_client, processSync, 0);
+ jack_on_shutdown(_client, processShutdown, 0);
+ jack_set_buffer_size_callback(_client, bufsize_callback, 0);
+ jack_set_sample_rate_callback(_client, srate_callback, 0);
+ jack_set_port_registration_callback(_client, registration_callback, 0);
+ jack_set_graph_order_callback(_client, graph_callback, 0);
+ jack_set_freewheel_callback (_client, freewheel_callback, 0);
+ jack_set_thread_init_callback(_client, (JackThreadInitCallback) jack_thread_init, 0);
+ jack_set_timebase_callback(_client, 0, timebase_callback, 0);
+ }
+
+//---------------------------------------------------------
+// registerInPort
+//---------------------------------------------------------
+
+Port JackAudio::registerInPort(const QString& name, bool midi)
+ {
+ const char* type = midi ? JACK_DEFAULT_MIDI_TYPE : JACK_DEFAULT_AUDIO_TYPE;
+ Port p(jack_port_register(_client, name.toLatin1().data(), type, JackPortIsInput, 0));
+// printf("JACK: registerInPort<%s>: <%s> %p\n", type, name.toLatin1().data(), p.jackPort());
+ if (!p.jackPort())
+ p.setZero();
+ return p;
+ }
+
+//---------------------------------------------------------
+// registerOutPort
+//---------------------------------------------------------
+
+Port JackAudio::registerOutPort(const QString& name, bool midi)
+ {
+ const char* type = midi ? JACK_DEFAULT_MIDI_TYPE : JACK_DEFAULT_AUDIO_TYPE;
+ Port p(jack_port_register(_client, name.toLatin1().data(), type, JackPortIsOutput, 0));
+// printf("JACK: registerOutPort<%s>: <%s> %p\n", type, name.toLatin1().data(), p.jackPort());
+ if (!p.jackPort())
+ p.setZero();
+ return p;
+ }
+
+//---------------------------------------------------------
+// exitJackAudio
+//---------------------------------------------------------
+
+void exitJackAudio()
+ {
+ if (jackAudio)
+ delete jackAudio;
+ }
+
+//---------------------------------------------------------
+// connect
+// return false on error
+//---------------------------------------------------------
+
+bool JackAudio::connect(Port src, Port dst)
+ {
+ if (src.isZero() || dst.isZero()) {
+ fprintf(stderr, "JackAudio::connect(1): unknown jack ports (%d-%d)\n",
+ src.isZero(), dst.isZero());
+ return false;
+ }
+ const char* sn = jack_port_name(src.jackPort());
+ const char* dn = jack_port_name(dst.jackPort());
+
+ if (debugMsg)
+ printf("jack connect <%s>%p - <%s>%p\n", sn, src.jackPort(), dn, dst.jackPort());
+
+ if (sn == 0 || dn == 0) {
+ fprintf(stderr, "JackAudio::connect(2): unknown jack ports\n");
+ return false;
+ }
+ int rv = jack_connect(_client, sn, dn);
+ if (rv) {
+ fprintf(stderr, "%d: jack connect <%s> - <%s> failed\n",
+ rv, sn, dn);
+ if (rv == EEXIST)
+ fprintf(stderr, " connection already made\n");
+ else {
+ int pf = jack_port_flags(src.jackPort());
+ if (!(pf & JackPortIsOutput))
+ fprintf(stderr, " src is not an output port\n");
+ pf = jack_port_flags(dst.jackPort());
+ if (!(pf & JackPortIsInput))
+ fprintf(stderr, " dst is not an input port\n");
+ }
+ return false;
+ }
+ return true;
+ }
+
+//---------------------------------------------------------
+// disconnect
+//---------------------------------------------------------
+
+bool JackAudio::disconnect(Port src, Port dst)
+ {
+ const char* sn = jack_port_name(src.jackPort());
+ const char* dn = jack_port_name(dst.jackPort());
+
+ if (debugMsg)
+ printf("jack disconnect <%s>%p - <%s>%p\n", sn, src.jackPort(), dn, dst.jackPort());
+
+ if (sn == 0 || dn == 0) {
+ fprintf(stderr, "JackAudio::disconnect: unknown jack ports\n");
+ return false;
+ }
+ if (jack_disconnect(_client, sn, dn)) {
+ fprintf(stderr, "jack disconnect <%s> - <%s> failed\n",
+ sn, dn);
+ return false;
+ }
+ return true;
+ }
+
+//---------------------------------------------------------
+// start
+//---------------------------------------------------------
+
+void JackAudio::start(int)
+ {
+ if (jack_activate(_client)) {
+ fprintf (stderr, "JACK: cannot activate client\n");
+ exit(-1);
+ }
+ }
+
+//---------------------------------------------------------
+// stop
+//---------------------------------------------------------
+
+void JackAudio::stop()
+ {
+ if (_client == 0)
+ return;
+ if (jack_deactivate(_client))
+ fprintf (stderr, "JACK: cannot deactivate client\n");
+ }
+
+//---------------------------------------------------------
+// outputPorts
+//---------------------------------------------------------
+
+QList<PortName> JackAudio::outputPorts(bool midi)
+ {
+ const char* type = midi ? JACK_DEFAULT_MIDI_TYPE : JACK_DEFAULT_AUDIO_TYPE;
+ const char** ports = jack_get_ports(_client, 0, type, JackPortIsOutput);
+ QList<PortName> clientList;
+ for (const char** p = ports; p && *p; ++p) {
+ jack_port_t* port = jack_port_by_name(_client, *p);
+ char buffer[128];
+ strncpy(buffer, *p, 128);
+ if (strncmp(buffer, "MusE", 4) == 0)
+ continue;
+ PortName pn;
+ pn.name = QString(buffer);
+ pn.port = Port(port);
+ clientList.append(pn);
+ }
+ return clientList;
+ }
+
+//---------------------------------------------------------
+// inputPorts
+//---------------------------------------------------------
+
+QList<PortName> JackAudio::inputPorts(bool midi)
+ {
+ const char* type = midi ? JACK_DEFAULT_MIDI_TYPE : JACK_DEFAULT_AUDIO_TYPE;
+ const char** ports = jack_get_ports(_client, 0, type, JackPortIsInput);
+ QList<PortName> clientList;
+ for (const char** p = ports; p && *p; ++p) {
+ jack_port_t* port = jack_port_by_name(_client, *p);
+ char buffer[128];
+ strncpy(buffer, *p, 128);
+ if (strncmp(buffer, "MusE", 4) == 0)
+ continue;
+ PortName pn;
+ pn.name = QString(buffer);
+ pn.port = Port(port);
+ clientList.append(pn);
+ }
+ return clientList;
+ }
+
+//---------------------------------------------------------
+// portName
+//---------------------------------------------------------
+
+QString JackAudio::portName(Port port)
+ {
+ const char* nameStrPtr = jack_port_name(port.jackPort());
+ QString s(nameStrPtr);
+ return s;
+ }
+
+//---------------------------------------------------------
+// unregisterPort
+//---------------------------------------------------------
+
+void JackAudio::unregisterPort(Port p)
+ {
+ if (_client) {
+// printf("JACK: unregister Port %p\n", p);
+ if (jack_port_unregister(_client, p.jackPort()))
+ fprintf(stderr, "jack unregister port %p failed\n", p.jackPort());
+ }
+ }
+
+//---------------------------------------------------------
+// setFreewheel
+//---------------------------------------------------------
+
+void JackAudio::setFreewheel(bool f)
+ {
+// printf("JACK: setFreewheel %d\n", f);
+ jack_set_freewheel(_client, f);
+ }
+
+//---------------------------------------------------------
+// startTransport
+//---------------------------------------------------------
+
+void JackAudio::startTransport()
+ {
+ jack_transport_start(_client);
+ }
+
+//---------------------------------------------------------
+// stopTransport
+//---------------------------------------------------------
+
+void JackAudio::stopTransport()
+ {
+ if (_client)
+ jack_transport_stop(_client);
+ }
+
+//---------------------------------------------------------
+// seekTransport
+//---------------------------------------------------------
+
+void JackAudio::seekTransport(unsigned frame)
+ {
+ jack_transport_locate(_client, frame);
+ }
+
+//---------------------------------------------------------
+// findPort
+//---------------------------------------------------------
+
+Port JackAudio::findPort(const QString& name)
+ {
+ if (_client == 0) {
+ printf("JackAudio(%p)::findPort(%s): _client==0\n", this, qPrintable(name));
+ return Port();
+ }
+ jack_port_t* port = jack_port_by_name(_client, name.toLatin1().data());
+ return (port == 0) ? Port() : Port(port);
+ }
+
+//---------------------------------------------------------
+// realtimePriority
+// return zero if not running realtime
+// can only be called if JACK client thread is already
+// running
+//---------------------------------------------------------
+
+int JackAudio::realtimePriority() const
+ {
+ pthread_t t = jack_client_thread_id(_client);
+ int policy;
+ struct sched_param param;
+ memset(&param, 0, sizeof(param));
+ int rv = pthread_getschedparam(t, &policy, &param);
+ if (rv) {
+ perror("MusE: get jack schedule parameter");
+ return 0;
+ }
+ if (policy != SCHED_FIFO) {
+ printf("JACK is not running realtime\n");
+ return 0;
+ }
+ return param.sched_priority;
+ }
+
+//---------------------------------------------------------
+// initJackAudio
+// return true if JACK not found
+//---------------------------------------------------------
+
+bool initJackAudio()
+ {
+ if (debugMsg) {
+ fprintf(stderr, "init Jack Audio\n");
+ jack_set_error_function(jackError);
+ }
+ else
+ jack_set_error_function(noJackError);
+
+ jack_client_t* client = 0;
+ jack_status_t status;
+ jack_options_t options = JackNullOption;
+ client = jack_client_open("MusE", options, &status);
+ if (!client) {
+ if (status & JackServerStarted)
+ printf("jack server started...\n");
+ if (status & JackServerFailed)
+ printf("cannot connect to jack server\n");
+ if (status & JackServerError)
+ printf("communication with jack server failed\n");
+ if (status & JackShmFailure)
+ printf("jack cannot access shared memory\n");
+ if (status & JackVersionError)
+ printf("jack server has wrong version\n");
+ printf("cannot create jack client\n");
+ return true;
+ }
+
+ if (debugMsg)
+ fprintf(stderr, "init Jack Audio: register device\n");
+
+ jack_set_error_function(jackError);
+ if (debugMsg)
+ fprintf(stderr, "init Jack Audio: register device\n");
+
+ jackAudio = new JackAudio(client, jack_get_client_name(client));
+ if (debugMsg)
+ fprintf(stderr, "init Jack Audio: register client\n");
+ jackAudio->registerClient();
+ AL::sampleRate = jack_get_sample_rate(client);
+ segmentSize = jack_get_buffer_size(client);
+ audioDriver = jackAudio;
+ return false;
+ }
+
+//---------------------------------------------------------
+// putEvent
+//---------------------------------------------------------
+
+void JackAudio::putEvent(Port port, const MidiEvent& e)
+ {
+ if (midiOutputTrace) {
+ printf("MidiOut<%s>: jackMidi: ", portName(port).toLatin1().data());
+ e.dump();
+ }
+ void* pb = jack_port_get_buffer(port.jackPort(), segmentSize);
+ int ft = e.time() - _frameCounter;
+ if (ft < 0)
+ ft = 0;
+ if (ft >= (int)segmentSize) {
+ printf("JackAudio::putEvent: time out of range %d(seg=%d)\n", ft, segmentSize);
+ if (ft > (int)segmentSize)
+ ft = segmentSize - 1;
+ }
+ switch(e.type()) {
+ case ME_NOTEON:
+ case ME_NOTEOFF:
+ case ME_POLYAFTER:
+ case ME_CONTROLLER:
+ case ME_PITCHBEND:
+ {
+ unsigned char* p = jack_midi_event_reserve(pb, ft, 3);
+ if (p == 0) {
+ fprintf(stderr, "JackMidi: buffer overflow, event lost\n");
+ return;
+ }
+ p[0] = e.type() | e.channel();
+ p[1] = e.dataA();
+ p[2] = e.dataB();
+ }
+ break;
+
+ case ME_PROGRAM:
+ case ME_AFTERTOUCH:
+ {
+ unsigned char* p = jack_midi_event_reserve(pb, ft, 2);
+ if (p == 0) {
+ fprintf(stderr, "JackMidi: buffer overflow, event lost\n");
+ return;
+ }
+ p[0] = e.type() | e.channel();
+ p[1] = e.dataA();
+ }
+ break;
+ case ME_SYSEX:
+ {
+ 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, "JackMidi: buffer overflow, event lost\n");
+ return;
+ }
+ 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("JackMidi: event type %x not supported\n", e.type());
+ break;
+ }
+ }
+
+//---------------------------------------------------------
+// startMidiCycle
+//---------------------------------------------------------
+
+void JackAudio::startMidiCycle(Port port)
+ {
+ void* port_buf = jack_port_get_buffer(port.jackPort(), segmentSize);
+ jack_midi_clear_buffer(port_buf);
+ }
+
+//---------------------------------------------------------
+// collectMidiEvents
+//---------------------------------------------------------
+
+void JackAudio::collectMidiEvents(MidiInPort* track, Port port)
+ {
+ void* port_buf = jack_port_get_buffer(port.jackPort(), segmentSize);
+ 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);
+ track->eventReceived(&event);
+ }
+ }
+
+