summaryrefslogtreecommitdiff
path: root/attic/muse2-oom/muse2/muse/driver
diff options
context:
space:
mode:
Diffstat (limited to 'attic/muse2-oom/muse2/muse/driver')
-rw-r--r--attic/muse2-oom/muse2/muse/driver/CMakeLists.txt73
-rw-r--r--attic/muse2-oom/muse2/muse/driver/alsamidi.cpp917
-rw-r--r--attic/muse2-oom/muse2/muse/driver/alsamidi.h58
-rw-r--r--attic/muse2-oom/muse2/muse/driver/alsatimer.cpp225
-rw-r--r--attic/muse2-oom/muse2/muse/driver/alsatimer.h52
-rw-r--r--attic/muse2-oom/muse2/muse/driver/audiodev.h76
-rw-r--r--attic/muse2-oom/muse2/muse/driver/dummyaudio.cpp453
-rw-r--r--attic/muse2-oom/muse2/muse/driver/jack.cpp2217
-rw-r--r--attic/muse2-oom/muse2/muse/driver/jackaudio.h97
-rw-r--r--attic/muse2-oom/muse2/muse/driver/jackmidi.cpp1732
-rw-r--r--attic/muse2-oom/muse2/muse/driver/jackmidi.h168
-rw-r--r--attic/muse2-oom/muse2/muse/driver/rtctimer.cpp155
-rw-r--r--attic/muse2-oom/muse2/muse/driver/rtctimer.h44
-rw-r--r--attic/muse2-oom/muse2/muse/driver/timerdev.h41
14 files changed, 6308 insertions, 0 deletions
diff --git a/attic/muse2-oom/muse2/muse/driver/CMakeLists.txt b/attic/muse2-oom/muse2/muse/driver/CMakeLists.txt
new file mode 100644
index 00000000..fbac3f0b
--- /dev/null
+++ b/attic/muse2-oom/muse2/muse/driver/CMakeLists.txt
@@ -0,0 +1,73 @@
+#=============================================================================
+# 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.
+#=============================================================================
+
+##
+## List of source files to compile
+##
+file (GLOB driver_source_files
+ alsamidi.cpp
+ alsatimer.cpp
+ dummyaudio.cpp
+ jack.cpp
+ jackmidi.cpp
+ rtctimer.cpp
+ )
+
+##
+## Define target
+##
+add_library ( driver SHARED
+ # ${PROJECT_BINARY_DIR}/all.h.pch
+ ${driver_source_files}
+ )
+
+##
+## Append to the list of translations
+##
+set (FILES_TO_TRANSLATE
+ ${FILES_TO_TRANSLATE}
+ ${driver_source_files}
+ CACHE INTERNAL ""
+ )
+
+##
+## Compilation flags and target name
+##
+set_target_properties( driver
+ PROPERTIES COMPILE_FLAGS "-include ${PROJECT_BINARY_DIR}/all.h -fPIC"
+ OUTPUT_NAME muse_driver
+ )
+
+##
+## Linkage
+##
+target_link_libraries ( driver
+ ${ALSA_LIBRARIES}
+ ${JACK_LIBRARIES}
+ ${QT_LIBRARIES}
+ mplugins
+ )
+
+##
+## Install location
+##
+install(TARGETS driver
+ DESTINATION ${MusE_MODULES_DIR}
+ )
diff --git a/attic/muse2-oom/muse2/muse/driver/alsamidi.cpp b/attic/muse2-oom/muse2/muse/driver/alsamidi.cpp
new file mode 100644
index 00000000..c7ae07b5
--- /dev/null
+++ b/attic/muse2-oom/muse2/muse/driver/alsamidi.cpp
@@ -0,0 +1,917 @@
+//=========================================================
+// MusE
+// Linux Music Editor
+// $Id: alsamidi.cpp,v 1.8.2.7 2009/11/19 04:20:33 terminator356 Exp $
+// (C) Copyright 2000-2001 Werner Schweer (ws@seh.de)
+//=========================================================
+
+#include <stdio.h>
+
+#include "alsamidi.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 "utils.h"
+#include "audiodev.h"
+#include "xml.h"
+
+static int alsaSeqFdi = -1;
+static int alsaSeqFdo = -1;
+
+snd_seq_t* alsaSeq;
+static snd_seq_addr_t musePort;
+
+//---------------------------------------------------------
+// MidiAlsaDevice
+//---------------------------------------------------------
+
+MidiAlsaDevice::MidiAlsaDevice(const snd_seq_addr_t& a, const QString& n)
+ : MidiDevice(n)
+ {
+ adr = a;
+ init();
+ }
+
+//---------------------------------------------------------
+// selectWfd
+//---------------------------------------------------------
+
+int MidiAlsaDevice::selectWfd()
+ {
+ return alsaSeqFdo;
+ }
+
+//---------------------------------------------------------
+// open
+//---------------------------------------------------------
+
+QString MidiAlsaDevice::open()
+{
+ _openFlags &= _rwFlags; // restrict to available bits
+ snd_seq_port_subscribe_t* subs;
+ // Allocated on stack, no need to call snd_seq_port_subscribe_free() later.
+ snd_seq_port_subscribe_alloca(&subs);
+
+ QString estr;
+ int wer = 0;
+ int rer = 0;
+
+ // subscribe for writing
+ if (_openFlags & 1)
+ {
+ snd_seq_port_subscribe_set_sender(subs, &musePort);
+ snd_seq_port_subscribe_set_dest(subs, &adr);
+ // Not already subscribed (or error)? Then try subscribing.
+ if(snd_seq_get_port_subscription(alsaSeq, subs) < 0)
+ {
+ //int error = snd_seq_subscribe_port(alsaSeq, subs);
+ wer = snd_seq_subscribe_port(alsaSeq, subs);
+ //if (error < 0)
+ if(wer < 0)
+ //return QString("Play: ")+QString(snd_strerror(error));
+ estr += (QString("Play: ") + QString(snd_strerror(wer)) + QString(" "));
+ }
+ if(!wer)
+ _writeEnable = true;
+ }
+
+ // subscribe for reading
+ if (_openFlags & 2)
+ {
+ snd_seq_port_subscribe_set_dest(subs, &musePort);
+ snd_seq_port_subscribe_set_sender(subs, &adr);
+ // Not already subscribed (or error)? Then try subscribing.
+ if(snd_seq_get_port_subscription(alsaSeq, subs) < 0)
+ {
+ //int error = snd_seq_subscribe_port(alsaSeq, subs);
+ rer = snd_seq_subscribe_port(alsaSeq, subs);
+ //if (error < 0)
+ if(rer < 0)
+ //return QString("Rec: ") + QString(snd_strerror(error));
+ estr += (QString("Rec: ") + QString(snd_strerror(rer)));
+ }
+ if(!rer)
+ _readEnable = true;
+ }
+
+
+ if(wer < 0 || rer < 0)
+ return estr;
+
+ return QString("OK");
+}
+
+//---------------------------------------------------------
+// close
+//---------------------------------------------------------
+
+void MidiAlsaDevice::close()
+{
+ snd_seq_port_subscribe_t* subs;
+ // Allocated on stack, no need to call snd_seq_port_subscribe_free() later.
+ snd_seq_port_subscribe_alloca(&subs);
+
+ // Changed by T356. This function appears to be called only by MidiPort::setMidiDevice(),
+ // which closes then opens the device.
+ // Because the open flags are set BEFORE setMidiDevice() is called, we must ignore the flags.
+ //
+ // NOTE: Tested: The read unsubscribe works ok but not the write.
+ // As viewed in say, qjackctl, the connection is clearly lost,
+ // but strangely the events are still accepted, ie, playback notes
+ // are still heard etc. Tried an alsa midi device AND external fluidsynth inst.
+ //
+ // Also, jack running and with jack midi disabled, we get messages like
+ // MidiAlsaDevice::0x84512c0 putEvent(): midi write error: No such device
+ // dst 16:0
+ // only sometimes (not when playing notes), but with jack midi turned on,
+ // we don't get the messages. With jack stopped we get the messages
+ // no matter if jack midi is turned on or not.
+
+ //if (_openFlags & 1) {
+ //if (!(_openFlags & 1))
+ {
+ snd_seq_port_subscribe_set_sender(subs, &musePort);
+ snd_seq_port_subscribe_set_dest(subs, &adr);
+
+ // Already subscribed? Then unsubscribe.
+ if(!snd_seq_get_port_subscription(alsaSeq, subs))
+ {
+ if(!snd_seq_unsubscribe_port(alsaSeq, subs))
+ _writeEnable = false;
+ else
+ printf("MidiAlsaDevice::close Error unsubscribing alsa midi port for writing\n");
+ }
+ else
+ _writeEnable = false;
+ }
+
+ //if (_openFlags & 2) {
+ //if (!(_openFlags & 2))
+ {
+ snd_seq_port_subscribe_set_dest(subs, &musePort);
+ snd_seq_port_subscribe_set_sender(subs, &adr);
+
+ // Already subscribed? Then unsubscribe.
+ if(!snd_seq_get_port_subscription(alsaSeq, subs))
+ {
+ if(!snd_seq_unsubscribe_port(alsaSeq, subs))
+ _readEnable = false;
+ else
+ printf("MidiAlsaDevice::close Error unsubscribing alsa midi port for reading\n");
+ }
+ else
+ _readEnable = false;
+ }
+}
+
+//---------------------------------------------------------
+// writeRouting
+//---------------------------------------------------------
+
+void MidiAlsaDevice::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)
+ {
+ // Since an ALSA midi device supports read + write, this is the only way we can tell if this route is using the device as input.
+ if(r->type == Route::TRACK_ROUTE)
+ continue;
+
+ 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());
+
+ //xml.strTag(level, "dstNode", name());
+ xml.tag(level, "dest type=\"%d\" name=\"%s\"/", Route::ALSA_MIDI_ROUTE, name().toLatin1().constData());
+
+ xml.etag(level--, "Route");
+ }
+ }
+ }
+ */
+
+ for (ciRoute r = _outRoutes.begin(); r != _outRoutes.end(); ++r)
+ {
+ //if(r->type != Route::TRACK_ROUTE)
+ //{
+ // printf("MidiAlsaDevice::writeRouting Warning out route is not TRACK_ROUTE type\n");
+ // continue;
+ //}
+
+ if(!r->name().isEmpty())
+ {
+ //xml.tag(level++, "Route");
+
+ s = QT_TRANSLATE_NOOP("@default", "Route");
+ if(r->channel != -1)
+ s += QString(QT_TRANSLATE_NOOP("@default", " channel=\"%1\"")).arg(r->channel);
+ 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::ALSA_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::ALSA_MIDI, r->channel, name().toLatin1().constData());
+ else
+ //xml.tag(level, "source type=\"%d\" name=\"%s\"/", Route::ALSA_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::ALSA_MIDI, name().toLatin1().constData());
+ xml.tag(level, "source devtype=\"%d\" name=\"%s\"/", MidiDevice::ALSA_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");
+ }
+ }
+}
+
+//---------------------------------------------------------
+// putEvent
+//---------------------------------------------------------
+
+bool MidiAlsaDevice::putMidiEvent(const MidiPlayEvent& e)
+ {
+ if (midiOutputTrace) {
+ printf("MidiOut: midiAlsa: ");
+ e.dump();
+ }
+ int chn = e.channel();
+ int a = e.dataA();
+ int b = e.dataB();
+
+ snd_seq_event_t event;
+ memset(&event, 0, sizeof(event));
+ event.queue = SND_SEQ_QUEUE_DIRECT;
+ event.source = musePort;
+ event.dest = adr;
+
+ switch(e.type()) {
+ case ME_NOTEON:
+ snd_seq_ev_set_noteon(&event, chn, a, b);
+ break;
+ case ME_NOTEOFF:
+ snd_seq_ev_set_noteoff(&event, chn, a, 0);
+ break;
+ case ME_PROGRAM:
+ snd_seq_ev_set_pgmchange(&event, chn, a);
+ break;
+ case ME_CONTROLLER:
+#if 1
+ snd_seq_ev_set_controller(&event, chn, a, b);
+#else
+ {
+ int a = e.dataA();
+ int b = e.dataB();
+ int chn = e.channel();
+ // p3.3.37
+ //if (a < 0x1000) { // 7 Bit Controller
+ if (a < CTRL_14_OFFSET) { // 7 Bit Controller
+ snd_seq_ev_set_controller(&event, chn, a, b);
+ }
+ //else if (a < 0x20000) { // 14 bit high resolution controller
+ else if (a < CTRL_RPN_OFFSET) { // 14 bit high resolution controller
+ int ctrlH = (a >> 8) & 0x7f;
+ int ctrlL = a & 0x7f;
+ a = (ctrlH << 7) + ctrlL;
+ snd_seq_ev_set_controller(&event, chn, a, b);
+ event.type = SND_SEQ_EVENT_CONTROL14;
+ }
+ //else if (a < 0x30000) { // RPN 7-Bit Controller
+ else if (a < CTRL_NRPN_OFFSET) { // RPN 7-Bit Controller
+ int ctrlH = (a >> 8) & 0x7f;
+ int ctrlL = a & 0x7f;
+ a = (ctrlH << 7) + ctrlL;
+ b <<= 7;
+ snd_seq_ev_set_controller(&event, chn, a, b);
+ event.type = SND_SEQ_EVENT_REGPARAM;
+ }
+ //else if (a < 0x40000) { // NRPN 7-Bit Controller
+ else if (a < CTRL_INTERNAL_OFFSET) { // NRPN 7-Bit Controller
+ int ctrlH = (a >> 8) & 0x7f;
+ int ctrlL = a & 0x7f;
+ a = (ctrlH << 7) + ctrlL;
+ b <<= 7;
+ snd_seq_ev_set_controller(&event, chn, a, b);
+ event.type = SND_SEQ_EVENT_NONREGPARAM;
+ }
+ //else if (a < 0x60000) { // RPN14 Controller
+ else if (a < CTRL_NRPN14_OFFSET) { // RPN14 Controller
+ int ctrlH = (a >> 8) & 0x7f;
+ int ctrlL = a & 0x7f;
+ a = (ctrlH << 7) + ctrlL;
+ snd_seq_ev_set_controller(&event, chn, a, b);
+ event.type = SND_SEQ_EVENT_REGPARAM;
+ }
+ //else if (a < 0x70000) { // NRPN14 Controller
+ else if (a < CTRL_NONE_OFFSET) { // NRPN14 Controller
+ int ctrlH = (a >> 8) & 0x7f;
+ int ctrlL = a & 0x7f;
+ a = (ctrlH << 7) + ctrlL;
+ snd_seq_ev_set_controller(&event, chn, a, b);
+ event.type = SND_SEQ_EVENT_NONREGPARAM;
+ }
+ else {
+ printf("putEvent: unknown controller type 0x%x\n", a);
+ }
+ }
+#endif
+ break;
+ case ME_PITCHBEND:
+ snd_seq_ev_set_pitchbend(&event, chn, a);
+ break;
+ case ME_POLYAFTER:
+ // chnEvent2(chn, 0xa0, a, b);
+ break;
+ case ME_AFTERTOUCH:
+ snd_seq_ev_set_chanpress(&event, chn, a);
+ break;
+ case ME_SYSEX:
+ {
+ const unsigned char* p = e.data();
+ int n = e.len();
+ int len = n + sizeof(event) + 2;
+ char buf[len];
+ event.type = SND_SEQ_EVENT_SYSEX;
+ event.flags = SND_SEQ_EVENT_LENGTH_VARIABLE;
+ event.data.ext.len = n + 2;
+ event.data.ext.ptr = (void*)(buf + sizeof(event));
+ memcpy(buf, &event, sizeof(event));
+ char* pp = buf + sizeof(event);
+ *pp++ = 0xf0;
+ memcpy(pp, p, n);
+ pp += n;
+ *pp = 0xf7;
+ return putEvent(&event);
+ }
+ case ME_SONGPOS:
+ event.data.control.value = a;
+ event.type = SND_SEQ_EVENT_SONGPOS;
+ break;
+ case ME_CLOCK:
+ event.type = SND_SEQ_EVENT_CLOCK;
+ break;
+ case ME_START:
+ event.type = SND_SEQ_EVENT_START;
+ break;
+ case ME_CONTINUE:
+ event.type = SND_SEQ_EVENT_CONTINUE;
+ break;
+ case ME_STOP:
+ event.type = SND_SEQ_EVENT_STOP;
+ break;
+ default:
+ printf("MidiAlsaDevice::putEvent(): event type %d not implemented\n",
+ e.type());
+ return true;
+ }
+ return putEvent(&event);
+ }
+
+//---------------------------------------------------------
+// putEvent
+// return false if event is delivered
+//---------------------------------------------------------
+
+bool MidiAlsaDevice::putEvent(snd_seq_event_t* event)
+ {
+ int error;
+
+ do {
+ error = snd_seq_event_output_direct(alsaSeq, event);
+ int len = snd_seq_event_length(event);
+ if (error == len) {
+// printf(".");fflush(stdout);
+ return false;
+ }
+ if (error < 0) {
+ if (error == -12) {
+// printf("?");fflush(stdout);
+ return true;
+ }
+ else {
+ fprintf(stderr, "MidiAlsaDevice::%p putEvent(): midi write error: %s\n",
+ this, snd_strerror(error));
+ fprintf(stderr, " dst %d:%d\n", adr.client, adr.port);
+ //exit(-1);
+ }
+ }
+ else
+ fprintf(stderr, "MidiAlsaDevice::putEvent(): midi write returns %d, expected %d: %s\n",
+ error, len, snd_strerror(error));
+ } while (error == -12);
+ return true;
+ }
+
+//---------------------------------------------------------
+// initMidiAlsa
+// return true on error
+//---------------------------------------------------------
+
+bool initMidiAlsa()
+ {
+ if (debugMsg)
+ printf("initMidiAlsa\n");
+ int error = snd_seq_open(&alsaSeq, "hw", SND_SEQ_OPEN_DUPLEX, SND_SEQ_NONBLOCK);
+ if (error < 0) {
+ fprintf(stderr, "Could not open ALSA sequencer: %s\n",
+ snd_strerror(error));
+ return true;
+ }
+ const int inCap = SND_SEQ_PORT_CAP_SUBS_READ;
+ const int outCap = SND_SEQ_PORT_CAP_SUBS_WRITE;
+
+ snd_seq_client_info_t *cinfo;
+ snd_seq_client_info_alloca(&cinfo);
+ snd_seq_client_info_set_client(cinfo, -1);
+
+ while (snd_seq_query_next_client(alsaSeq, cinfo) >= 0) {
+ snd_seq_port_info_t *pinfo;
+ snd_seq_port_info_alloca(&pinfo);
+ snd_seq_port_info_set_client(pinfo, snd_seq_client_info_get_client(cinfo));
+ snd_seq_port_info_set_port(pinfo, -1);
+
+ while (snd_seq_query_next_port(alsaSeq, pinfo) >= 0) {
+ unsigned int capability = snd_seq_port_info_get_capability(pinfo);
+ if ((capability & outCap) == 0) {
+ const char *name = snd_seq_port_info_get_name(pinfo);
+ if (strcmp("Timer", name) == 0 ||
+ strcmp("Announce", name) == 0 ||
+ strcmp("Receiver", name) == 0)
+ continue;
+ }
+ snd_seq_addr_t adr = *snd_seq_port_info_get_addr(pinfo);
+ MidiAlsaDevice* dev = new MidiAlsaDevice(adr, QString(snd_seq_port_info_get_name(pinfo)));
+ int flags = 0;
+ if (capability & outCap)
+ flags |= 1;
+ if (capability & inCap)
+ flags |= 2;
+ dev->setrwFlags(flags);
+ if (debugMsg)
+ printf("ALSA port add: <%s>, %d:%d flags %d 0x%0x\n",
+ snd_seq_port_info_get_name(pinfo),
+ adr.client, adr.port,
+ flags, capability);
+ midiDevices.add(dev);
+
+ /*
+ // Experimental... Need to list 'sensible' devices first and ignore unwanted ones...
+ // Add instance last in midi device list.
+ for(int i = 0; i < MIDI_PORTS; ++i)
+ {
+ MidiPort* mp = &midiPorts[i];
+ if(mp->device() == 0)
+ {
+ // midiSeq might not be initialzed yet!
+ //midiSeq->msgSetMidiDevice(mp, dev);
+ mp->setMidiDevice(dev);
+
+ //muse->changeConfig(true); // save configuration file
+ //update();
+ break;
+ }
+ }
+ */
+
+ }
+ }
+
+ // p3.3.38
+ //snd_seq_set_client_name(alsaSeq, "MusE Sequencer");
+ snd_seq_set_client_name(alsaSeq, audioDevice->clientName());
+
+ int ci = snd_seq_poll_descriptors_count(alsaSeq, POLLIN);
+ int co = snd_seq_poll_descriptors_count(alsaSeq, POLLOUT);
+
+ if (ci > 1 || co > 1) {
+ printf("ALSA midi: cannot handle more than one poll fd\n");
+ abort();
+ }
+
+ struct pollfd pfdi[ci];
+ struct pollfd pfdo[co];
+ snd_seq_poll_descriptors(alsaSeq, pfdi, ci, POLLIN);
+ snd_seq_poll_descriptors(alsaSeq, pfdo, co, POLLOUT);
+ alsaSeqFdo = pfdo[0].fd;
+ alsaSeqFdi = pfdi[0].fd;
+
+ int port = snd_seq_create_simple_port(alsaSeq, "MusE Port 0",
+ inCap | outCap | SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_WRITE,
+ SND_SEQ_PORT_TYPE_APPLICATION);
+ if (port < 0) {
+ perror("create port");
+ exit(1);
+ }
+ musePort.port = port;
+ musePort.client = snd_seq_client_id(alsaSeq);
+
+ //-----------------------------------------
+ // subscribe to "Announce"
+ // this enables callbacks for any
+ // alsa port changes
+ //-----------------------------------------
+
+ snd_seq_addr_t aadr;
+ aadr.client = SND_SEQ_CLIENT_SYSTEM;
+ aadr.port = SND_SEQ_PORT_SYSTEM_ANNOUNCE;
+
+ snd_seq_port_subscribe_t* subs;
+ snd_seq_port_subscribe_alloca(&subs);
+ snd_seq_port_subscribe_set_dest(subs, &musePort);
+ snd_seq_port_subscribe_set_sender(subs, &aadr);
+ error = snd_seq_subscribe_port(alsaSeq, subs);
+ if (error < 0) {
+ printf("Alsa: Subscribe System failed: %s", snd_strerror(error));
+ return true;
+ }
+ return false;
+ }
+
+struct AlsaPort {
+ snd_seq_addr_t adr;
+ char* name;
+ int flags;
+ AlsaPort(snd_seq_addr_t a, const char* s, int f) {
+ adr = a;
+ name = strdup(s);
+ flags = f;
+ }
+ };
+
+static std::list<AlsaPort> portList;
+
+//---------------------------------------------------------
+// alsaScanMidiPorts
+//---------------------------------------------------------
+
+void alsaScanMidiPorts()
+ {
+// printf("alsa scan midi ports\n");
+ const int inCap = SND_SEQ_PORT_CAP_SUBS_READ;
+ const int outCap = SND_SEQ_PORT_CAP_SUBS_WRITE;
+
+ portList.clear();
+
+ snd_seq_client_info_t* cinfo;
+ snd_seq_client_info_alloca(&cinfo);
+ snd_seq_client_info_set_client(cinfo, 0);
+
+ while (snd_seq_query_next_client(alsaSeq, cinfo) >= 0) {
+ snd_seq_port_info_t *pinfo;
+ snd_seq_port_info_alloca(&pinfo);
+ snd_seq_port_info_set_client(pinfo, snd_seq_client_info_get_client(cinfo));
+ snd_seq_port_info_set_port(pinfo, -1);
+ while (snd_seq_query_next_port(alsaSeq, pinfo) >= 0) {
+ unsigned int capability = snd_seq_port_info_get_capability(pinfo);
+ if (((capability & outCap) == 0)
+ && ((capability & inCap) == 0))
+ continue;
+ snd_seq_addr_t adr;
+ const char* name;
+ adr = *snd_seq_port_info_get_addr(pinfo);
+ name = snd_seq_port_info_get_name(pinfo);
+ if (adr.client == musePort.client && adr.port == musePort.port)
+ continue;
+ int flags = 0;
+ if (capability & outCap)
+ flags |= 1;
+ if (capability & inCap)
+ flags |= 2;
+// printf("ALSA port add: <%s>, flags %d\n", name, flags);
+ portList.push_back(AlsaPort(adr, name, flags));
+ }
+ }
+ //
+ // check for devices to delete
+ //
+ for (iMidiDevice i = midiDevices.begin(); i != midiDevices.end();) {
+ MidiAlsaDevice* d = dynamic_cast<MidiAlsaDevice*>(*i);
+ if (d == 0) {
+ ++i;
+ continue;
+ }
+ std::list<AlsaPort>::iterator k = portList.begin();
+ for (; k != portList.end(); ++k) {
+ if (k->adr.client == d->adr.client
+ && k->adr.port == d->adr.port) {
+ break;
+ }
+ }
+ if (k == portList.end()) {
+ if (d->midiPort() != -1)
+ midiPorts[d->midiPort()].setMidiDevice(0);
+ iMidiDevice k = i;
+// printf("erase device\n");
+ ++i;
+ midiDevices.erase(k);
+ }
+ else {
+ ++i;
+ }
+ }
+ //
+ // check for devices to add
+ //
+ for (std::list<AlsaPort>::iterator k = portList.begin(); k != portList.end(); ++k) {
+ iMidiDevice i = midiDevices.begin();
+// printf("ALSA port: <%s>\n", k->name);
+ for (;i != midiDevices.end(); ++i) {
+ MidiAlsaDevice* d = dynamic_cast<MidiAlsaDevice*>(*i);
+ if (d == 0)
+ continue;
+ if ((k->adr.client == d->adr.client) && (k->adr.port == d->adr.port)) {
+ break;
+ }
+ }
+ if (i == midiDevices.end()) {
+ // add device
+ MidiAlsaDevice* dev = new MidiAlsaDevice(k->adr,
+ QString(k->name));
+ dev->setrwFlags(k->flags);
+ midiDevices.add(dev);
+// printf("add device\n");
+ }
+ }
+ }
+
+//---------------------------------------------------------
+// alsaSelectRfd
+//---------------------------------------------------------
+
+int alsaSelectRfd()
+ {
+ return alsaSeqFdi;
+ }
+
+//---------------------------------------------------------
+// alsaSelectWfd
+//---------------------------------------------------------
+
+int alsaSelectWfd()
+ {
+ return alsaSeqFdo;
+ }
+
+//---------------------------------------------------------
+// processInput
+//---------------------------------------------------------
+
+void alsaProcessMidiInput()
+{
+ MidiRecordEvent event;
+ snd_seq_event_t* ev;
+
+ for (;;)
+ {
+ int rv = snd_seq_event_input(alsaSeq, &ev);
+// printf("AlsaInput %d\n", rv);
+ if (rv < 0) {
+// printf("AlsaMidi: read error %s\n", snd_strerror(rv));
+ return;
+ }
+ switch(ev->type) {
+ case SND_SEQ_EVENT_PORT_SUBSCRIBED:
+ case SND_SEQ_EVENT_PORT_UNSUBSCRIBED:
+ return;
+ case SND_SEQ_EVENT_CLIENT_START:
+ case SND_SEQ_EVENT_CLIENT_EXIT:
+ // return;
+ // on first start of a software synthesizer we only
+ // get CLIENT_START event and no PORT_START, why?
+
+ case SND_SEQ_EVENT_PORT_START:
+ case SND_SEQ_EVENT_PORT_EXIT:
+ alsaScanMidiPorts();
+ audio->midiPortsChanged(); // signal gui
+ snd_seq_free_event(ev);
+ return;
+ }
+
+ int curPort = -1;
+ MidiAlsaDevice* mdev = 0;
+ //
+ // find real source device
+ //
+ for (iMidiDevice i = midiDevices.begin(); i != midiDevices.end(); ++i) {
+ MidiAlsaDevice* d = dynamic_cast<MidiAlsaDevice*>(*i);
+ if (d && d->adr.client == ev->source.client
+ && d->adr.port == ev->source.port) {
+ curPort = d->midiPort();
+ mdev = d;
+ }
+ }
+
+ if (mdev == 0 || curPort == -1) {
+ if (debugMsg) {
+ fprintf(stderr, "no port %d:%d found for received alsa event\n",
+ ev->source.client, ev->source.port);
+ }
+ snd_seq_free_event(ev);
+ return;
+ }
+
+ /*
+ if(curPort == -1)
+ {
+ if(mdev == 0)
+ {
+ if (debugMsg)
+ {
+ fprintf(stderr, "no port %d:%d found for received alsa event\n",
+ ev->source.client, ev->source.port);
+ }
+ }
+ else
+ {
+ // Allow the sync detect mechanisms to work, even if device is not assigned to a port.
+ if(ev->type == SND_SEQ_EVENT_CLOCK)
+ mdev->syncInfo().trigMCSyncDetect();
+ else
+ if(ev->type == SND_SEQ_EVENT_TICK)
+ mdev->syncInfo().trigTickDetect();
+ }
+ snd_seq_free_event(ev);
+ return;
+ }
+ */
+
+ event.setType(0); // mark as unused
+ event.setPort(curPort);
+ event.setB(0);
+
+ switch(ev->type)
+ {
+ case SND_SEQ_EVENT_NOTEON:
+ case SND_SEQ_EVENT_KEYPRESS:
+ event.setChannel(ev->data.note.channel);
+ event.setType(ME_NOTEON);
+ event.setA(ev->data.note.note);
+ event.setB(ev->data.note.velocity);
+ break;
+
+ case SND_SEQ_EVENT_NOTEOFF:
+ event.setChannel(ev->data.note.channel);
+ event.setType(ME_NOTEOFF);
+ event.setA(ev->data.note.note);
+ event.setB(ev->data.note.velocity);
+ break;
+
+ case SND_SEQ_EVENT_CHANPRESS:
+ event.setChannel(ev->data.control.channel);
+ event.setType(ME_AFTERTOUCH);
+ event.setA(ev->data.control.value);
+ break;
+
+ case SND_SEQ_EVENT_PGMCHANGE:
+ event.setChannel(ev->data.control.channel);
+ event.setType(ME_PROGRAM);
+ event.setA(ev->data.control.value);
+ break;
+
+ case SND_SEQ_EVENT_PITCHBEND:
+ event.setChannel(ev->data.control.channel);
+ event.setType(ME_PITCHBEND);
+ event.setA(ev->data.control.value);
+ break;
+
+ case SND_SEQ_EVENT_CONTROLLER:
+ event.setChannel(ev->data.control.channel);
+ event.setType(ME_CONTROLLER);
+ event.setA(ev->data.control.param);
+ event.setB(ev->data.control.value);
+ break;
+
+ case SND_SEQ_EVENT_CLOCK:
+ midiSeq->realtimeSystemInput(curPort, ME_CLOCK);
+ //mdev->syncInfo().trigMCSyncDetect();
+ break;
+
+ case SND_SEQ_EVENT_START:
+ midiSeq->realtimeSystemInput(curPort, ME_START);
+ break;
+
+ case SND_SEQ_EVENT_CONTINUE:
+ midiSeq->realtimeSystemInput(curPort, ME_CONTINUE);
+ break;
+
+ case SND_SEQ_EVENT_STOP:
+ midiSeq->realtimeSystemInput(curPort, ME_STOP);
+ break;
+
+ case SND_SEQ_EVENT_TICK:
+ midiSeq->realtimeSystemInput(curPort, ME_TICK);
+ //mdev->syncInfo().trigTickDetect();
+ break;
+
+ case SND_SEQ_EVENT_SYSEX:
+
+ // TODO: Deal with large sysex, which are broken up into chunks!
+ // For now, do not accept if the first byte is not SYSEX or the last byte is not EOX,
+ // meaning it's a chunk, possibly with more chunks to follow.
+ if((*((unsigned char*)ev->data.ext.ptr) != ME_SYSEX) ||
+ (*(((unsigned char*)ev->data.ext.ptr) + ev->data.ext.len - 1) != ME_SYSEX_END))
+ {
+ printf("MusE: alsaProcessMidiInput sysex chunks not supported!\n");
+ break;
+ }
+
+ event.setTime(0); // mark as used
+ event.setType(ME_SYSEX);
+ event.setData((unsigned char*)(ev->data.ext.ptr)+1,
+ ev->data.ext.len-2);
+ break;
+ case SND_SEQ_EVENT_PORT_SUBSCRIBED:
+ case SND_SEQ_EVENT_PORT_UNSUBSCRIBED: // write port is released
+ break;
+ case SND_SEQ_EVENT_SONGPOS:
+ midiSeq->setSongPosition(curPort, ev->data.control.value);
+ break;
+ case SND_SEQ_EVENT_SENSING:
+ break;
+ case SND_SEQ_EVENT_QFRAME:
+ midiSeq->mtcInputQuarter(curPort, ev->data.control.value);
+ break;
+ // case SND_SEQ_EVENT_CLIENT_START:
+ // case SND_SEQ_EVENT_CLIENT_EXIT:
+ // case SND_SEQ_EVENT_CLIENT_CHANGE:
+ // case SND_SEQ_EVENT_PORT_CHANGE:
+ // case SND_SEQ_EVENT_SONGSEL:
+ // case SND_SEQ_EVENT_TIMESIGN:
+ // case SND_SEQ_EVENT_KEYSIGN:
+ // case SND_SEQ_EVENT_SETPOS_TICK:
+ // case SND_SEQ_EVENT_SETPOS_TIME:
+ // case SND_SEQ_EVENT_TEMPO:
+ // case SND_SEQ_EVENT_TUNE_REQUEST:
+ // case SND_SEQ_EVENT_RESET:
+
+ // case SND_SEQ_EVENT_NOTE:
+ // case SND_SEQ_EVENT_CONTROL14:
+ // case SND_SEQ_EVENT_NONREGPARAM:
+ // case SND_SEQ_EVENT_REGPARAM:
+ default:
+ printf("ALSA Midi input: type %d not handled\n", ev->type);
+ break;
+ }
+ if(event.type())
+ {
+ mdev->recordEvent(event);
+ // p3.3.26 1/23/10 Moved to MidiDevice now. Anticipating Jack midi support, so don't make it ALSA specific. Tim.
+ //if(ev->type != SND_SEQ_EVENT_SYSEX)
+ // Trigger general activity indicator detector. Sysex has no channel, don't trigger.
+ // midiPorts[curPort].syncInfo().trigActDetect(event.channel());
+ }
+
+ snd_seq_free_event(ev);
+ if (rv == 0)
+ break;
+ }
+}
+
diff --git a/attic/muse2-oom/muse2/muse/driver/alsamidi.h b/attic/muse2-oom/muse2/muse/driver/alsamidi.h
new file mode 100644
index 00000000..455ab1df
--- /dev/null
+++ b/attic/muse2-oom/muse2/muse/driver/alsamidi.h
@@ -0,0 +1,58 @@
+//=========================================================
+// MusE
+// Linux Music Editor
+// $Id: alsamidi.h,v 1.2 2004/01/14 09:06:43 wschweer Exp $
+// (C) Copyright 2001 Werner Schweer (ws@seh.de)
+//=========================================================
+
+#ifndef __ALSAMIDI_H__
+#define __ALSAMIDI_H__
+
+#include <config.h>
+#include <alsa/asoundlib.h>
+
+#include "mididev.h"
+
+class Xml;
+
+//---------------------------------------------------------
+// MidiAlsaDevice
+//---------------------------------------------------------
+
+class MidiAlsaDevice : public MidiDevice {
+ public:
+ snd_seq_addr_t adr;
+
+ private:
+ virtual QString open();
+ virtual void close();
+ virtual void processInput() {}
+ virtual int selectRfd() { return -1; }
+ virtual int selectWfd();
+
+ bool putEvent(snd_seq_event_t*);
+ virtual bool putMidiEvent(const MidiPlayEvent&);
+
+ public:
+ //MidiAlsaDevice() {} // p3.3.55 Removed
+ MidiAlsaDevice(const snd_seq_addr_t&, const QString& name);
+ virtual ~MidiAlsaDevice() {}
+
+ //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; }
+ };
+
+extern bool initMidiAlsa();
+extern int alsaSelectRfd();
+extern int alsaSelectWfd();
+extern void alsaProcessMidiInput();
+extern void alsaScanMidiPorts();
+
+#endif
+
+
diff --git a/attic/muse2-oom/muse2/muse/driver/alsatimer.cpp b/attic/muse2-oom/muse2/muse/driver/alsatimer.cpp
new file mode 100644
index 00000000..d851410d
--- /dev/null
+++ b/attic/muse2-oom/muse2/muse/driver/alsatimer.cpp
@@ -0,0 +1,225 @@
+ //=========================================================
+ // MusE
+ // Linux Music Editor
+ // $Id: alsatimer.cpp,v 1.1.2.9 2009/03/28 01:46:10 terminator356 Exp $
+ //
+ // Plenty of code borrowed from timer.c example in
+ // alsalib 1.0.7
+ //
+ // (C) Copyright 2004 Robert Jonsson (rj@spamatica.se)
+ //=========================================================
+
+ #include "alsatimer.h"
+ #include <climits>
+
+#define TIMER_DEBUG 0
+
+ AlsaTimer::AlsaTimer()
+ {
+ if(TIMER_DEBUG)
+ fprintf(stderr,"AlsaTimer::AlsaTimer(this=%p) called\n",this);
+ handle = NULL;
+ id = NULL;
+ info = NULL;
+ params = NULL;
+ findBest = true;
+ }
+
+ AlsaTimer::~AlsaTimer()
+ {
+ if(TIMER_DEBUG)
+ fprintf(stderr,"AlsaTimer::~AlsaTimer(this=%p) called\n",this);
+ if (handle)
+ snd_timer_close(handle);
+ if (id) snd_timer_id_free(id);
+ if (info) snd_timer_info_free(info);
+ if (params) snd_timer_params_free(params);
+ }
+
+ signed int AlsaTimer::initTimer()
+ {
+ if(TIMER_DEBUG)
+ printf("AlsaTimer::initTimer(this=%p)\n",this);
+
+ int err;
+ int devclass = SND_TIMER_CLASS_GLOBAL;
+ int sclass = SND_TIMER_CLASS_NONE;
+ int card = 0;
+ int device = SND_TIMER_GLOBAL_SYSTEM;
+ int subdevice = 0;
+ int test_ids[] = { SND_TIMER_GLOBAL_SYSTEM
+ , SND_TIMER_GLOBAL_RTC
+#ifdef SND_TIMER_GLOBAL_HPET
+ , SND_TIMER_GLOBAL_HPET
+#endif
+ };
+ int max_ids = sizeof(test_ids) / sizeof(int);
+ long best_res = LONG_MAX;
+ //int best_dev = -1; // SND_TIMER_GLOBAL_SYSTEM;
+ int best_dev = SND_TIMER_GLOBAL_SYSTEM; // p3.3.51
+ int i;
+
+ if (id || info || params) {
+ fprintf(stderr,"AlsaTimer::initTimer(): called on initialised timer!\n");
+ return fds->fd;
+ }
+ snd_timer_id_malloc(&id);
+ snd_timer_info_malloc(&info);
+ snd_timer_params_malloc(&params);
+
+ if (findBest) {
+ for (i = 0; i < max_ids; ++i) {
+ device = test_ids[i];
+ sprintf(timername, "hw:CLASS=%i,SCLASS=%i,CARD=%i,DEV=%i,SUBDEV=%i", devclass, sclass, card, device, subdevice);
+ if ((err = snd_timer_open(&handle, timername, SND_TIMER_OPEN_NONBLOCK)) < 0) {
+ continue;
+ }
+ if ((err = snd_timer_info(handle, info)) < 0) {
+ snd_timer_close(handle);
+ continue;
+ }
+ // select a non slave timer with the lowest resolution value
+ int is_slave = snd_timer_info_is_slave(info);
+ long res = snd_timer_info_get_resolution(info);
+ if ((is_slave == 0) && (best_res > res)) {
+ best_res = res;
+ best_dev = device;
+ }
+ snd_timer_close(handle);
+ }
+ device = best_dev;
+ }
+
+ // p3.3.51 Removed.
+ //if(best_dev==-1)
+ // return -1; // no working timer found
+
+ sprintf(timername, "hw:CLASS=%i,SCLASS=%i,CARD=%i,DEV=%i,SUBDEV=%i", devclass, sclass, card, device, subdevice);
+ if ((err = snd_timer_open(&handle, timername, SND_TIMER_OPEN_NONBLOCK))<0) {
+ fprintf(stderr, "AlsaTimer::initTimer(): timer open %i (%s)\n", err, snd_strerror(err));
+ return -1; // p3.3.51
+ }
+
+ if ((err = snd_timer_info(handle, info)) < 0) {
+ fprintf(stderr, "AlsaTimer::initTimer(): timer info %i (%s)\n", err, snd_strerror(err));
+ return -1;
+ }
+
+ //if(debugMsg)
+ fprintf(stderr, "AlsaTimer::initTimer(): best available ALSA timer: %s\n", snd_timer_info_get_name(info));
+
+ snd_timer_params_set_auto_start(params, 1);
+ snd_timer_params_set_ticks(params, 1);
+
+ if ((err = snd_timer_params(handle, params)) < 0) {
+ fprintf(stderr, "AlsaTimer::initTimer(): timer params %i (%s)\n", err, snd_strerror(err));
+ return -1;
+ }
+
+ count = snd_timer_poll_descriptors_count(handle);
+ fds = (pollfd *)calloc(count, sizeof(pollfd));
+ if (fds == NULL) {
+ fprintf(stderr, "AlsaTimer::initTimer(): malloc error\n");
+ return -1;
+ }
+ if ((err = snd_timer_poll_descriptors(handle, fds, count)) < 0) {
+ fprintf(stderr, "AlsaTimer::initTimer(): snd_timer_poll_descriptors error: %s\n", snd_strerror(err));
+ return -1;
+ }
+ return fds->fd;
+ }
+
+ unsigned int AlsaTimer::setTimerResolution(unsigned int resolution)
+ {
+ if(TIMER_DEBUG)
+ printf("AlsaTimer::setTimerResolution(%d)\n",resolution);
+ /* Resolution of an AlsaTimer is fixed - it cannot be set */
+ return 0;
+ }
+
+ unsigned int AlsaTimer::setTimerFreq(unsigned int freq)
+ {
+ signed int err;
+ unsigned int setTick, actFreq;
+
+ if(TIMER_DEBUG)
+ printf("AlsaTimer::setTimerFreq(this=%p)\n",this);
+
+ setTick = (1000000000 / snd_timer_info_get_resolution(info)) / freq;
+
+ if (setTick == 0) {
+ // return, print error if freq is below 500 (timing will suffer)
+ if (((1000000000.0 / snd_timer_info_get_resolution(info)) / snd_timer_params_get_ticks(params)) < 500) {
+ fprintf(stderr,"AlsaTimer::setTimerTicks(): requested freq %u Hz too high for timer (max is %g)\n",
+ freq, 1000000000.0 / snd_timer_info_get_resolution(info));
+ fprintf(stderr," freq stays at %ld Hz\n",
+ (long int)((1000000000.0 / snd_timer_info_get_resolution(info)) / snd_timer_params_get_ticks(params)));
+ }
+
+ return 0;
+ }
+ actFreq = (1000000000 / snd_timer_info_get_resolution(info)) / setTick;
+ if (actFreq != freq) {
+ fprintf(stderr,"AlsaTimer::setTimerTicks(): warning: requested %u Hz, actual freq is %u Hz\n",
+ freq, actFreq);
+ }
+ if(TIMER_DEBUG)
+ printf("AlsaTimer::setTimerFreq(): Setting ticks (period) to %d ticks\n", setTick);
+ snd_timer_params_set_auto_start(params, 1);
+ snd_timer_params_set_ticks(params, setTick);
+ if ((err = snd_timer_params(handle, params)) < 0) {
+ fprintf(stderr, "AlsaTimer::setTimerFreq(): timer params %i (%s)\n", err, snd_strerror(err));
+ return 0;
+ }
+
+ return actFreq;
+ }
+
+ unsigned int AlsaTimer::getTimerResolution()
+ {
+ return snd_timer_info_get_resolution(info);
+ }
+
+ unsigned int AlsaTimer::getTimerFreq()
+ {
+ return (1000000000 / snd_timer_info_get_resolution(info)) / snd_timer_params_get_ticks(params);
+ }
+
+ bool AlsaTimer::startTimer()
+ {
+ if(TIMER_DEBUG)
+ printf("AlsaTimer::startTimer(this=%p): handle=%p\n",this,handle);
+ int err;
+ if ((err = snd_timer_start(handle)) < 0) {
+ fprintf(stderr, "AlsaTimer::startTimer(): timer start %i (%s)\n", err, snd_strerror(err));
+ return false;
+ }
+ return true;
+ }
+
+ bool AlsaTimer::stopTimer()
+ {
+ int err;
+ if(TIMER_DEBUG)
+ printf("AlsaTimer::stopTimer(this=%p): handle=%p\n",this,handle);
+ if ((err = snd_timer_stop(handle)) < 0) {
+ fprintf(stderr, "AlsaTimer::stopTimer(): timer stop %i (%s)\n", err, snd_strerror(err));
+ return false;
+ }
+ return true;
+ }
+
+ unsigned int AlsaTimer::getTimerTicks(bool printTicks)
+ {
+ //if(TIMER_DEBUG)
+ // printf("AlsaTimer::getTimerTicks\n");
+ snd_timer_read_t tr;
+ tr.ticks = 0;
+ while (snd_timer_read(handle, &tr, sizeof(tr)) == sizeof(tr)) {
+ if (printTicks) {
+ printf("TIMER: resolution = %uns, ticks = %u\n",
+ tr.resolution, tr.ticks);
+ }
+ }
+ return tr.ticks;
+ }
diff --git a/attic/muse2-oom/muse2/muse/driver/alsatimer.h b/attic/muse2-oom/muse2/muse/driver/alsatimer.h
new file mode 100644
index 00000000..211ba5ec
--- /dev/null
+++ b/attic/muse2-oom/muse2/muse/driver/alsatimer.h
@@ -0,0 +1,52 @@
+//=========================================================
+// MusE
+// Linux Music Editor
+// $Id: alsatimer.h,v 1.1.2.4 2009/03/09 02:05:18 terminator356 Exp $
+//
+// Plenty of code borrowed from timer.c example in
+// alsalib 1.0.7
+//
+// (C) Copyright 2004 Robert Jonsson (rj@spamatica.se)
+//=========================================================
+
+#ifndef __ALSATIMER_H__
+#define __ALSATIMER_H__
+
+#include "alsa/asoundlib.h"
+#include "timerdev.h"
+
+
+//---------------------------------------------------------
+// AlsaTimer
+//---------------------------------------------------------
+
+class AlsaTimer : public Timer{
+
+ snd_timer_t *handle;
+ snd_timer_id_t *id;
+ snd_timer_info_t *info;
+ snd_timer_params_t *params;
+ struct pollfd *fds;
+ char timername[64];
+ signed int count;
+ unsigned int ticks;
+ bool findBest;
+
+ public:
+ AlsaTimer();
+ virtual ~AlsaTimer();
+
+ virtual signed int initTimer();
+ virtual unsigned int setTimerResolution(unsigned int resolution);
+ virtual unsigned int getTimerResolution();
+ virtual unsigned int setTimerFreq(unsigned int freq);
+ virtual unsigned int getTimerFreq();
+
+ virtual bool startTimer();
+ virtual bool stopTimer();
+ virtual unsigned int getTimerTicks(bool printTicks=false);
+
+ void setFindBestTimer(bool b) { findBest = b; }
+};
+
+#endif //__ALSATIMER_H__
diff --git a/attic/muse2-oom/muse2/muse/driver/audiodev.h b/attic/muse2-oom/muse2/muse/driver/audiodev.h
new file mode 100644
index 00000000..af53d7de
--- /dev/null
+++ b/attic/muse2-oom/muse2/muse/driver/audiodev.h
@@ -0,0 +1,76 @@
+//=========================================================
+// MusE
+// Linux Music Editor
+// $Id: audiodev.h,v 1.5.2.2 2009/12/20 05:00:35 terminator356 Exp $
+//
+// (C) Copyright 1999/2000 Werner Schweer (ws@seh.de)
+//=========================================================
+
+#ifndef __AUDIODEV_H__
+#define __AUDIODEV_H__
+
+#include <list>
+
+class QString;
+
+class MidiPlayEvent;
+class Pos;
+
+//---------------------------------------------------------
+// AudioDevice
+//---------------------------------------------------------
+
+class AudioDevice {
+
+ public:
+ enum { DUMMY_AUDIO=0, JACK_AUDIO=1 }; // p3.3.52
+
+ AudioDevice() {}
+ virtual ~AudioDevice() {}
+
+ virtual int deviceType() = 0; // p3.3.52
+
+ //virtual void start() = 0;
+ virtual void start(int priority) = 0;
+
+ virtual void stop () = 0;
+ virtual int framePos() const = 0;
+ virtual unsigned frameTime() const = 0;
+
+ virtual float* getBuffer(void* port, unsigned long nframes) = 0;
+
+ virtual std::list<QString> outputPorts(bool midi = false, int aliases = -1) = 0;
+ virtual std::list<QString> inputPorts(bool midi = false, int aliases = -1) = 0;
+
+ virtual void registerClient() = 0;
+
+ virtual const char* clientName() = 0;
+
+ //virtual void* registerOutPort(const char* name) = 0;
+ //virtual void* registerInPort(const char* name) = 0;
+ virtual void* registerOutPort(const char* /*name*/, bool /*midi*/) = 0;
+ virtual void* registerInPort(const char* /*name*/, bool /*midi*/) = 0;
+
+ virtual void unregisterPort(void*) = 0;
+ virtual void connect(void*, void*) = 0;
+ virtual void disconnect(void*, void*) = 0;
+ virtual int connections(void* /*clientPort*/) = 0;
+ virtual void setPortName(void* p, const char* n) = 0;
+ virtual void* findPort(const char* name) = 0;
+ virtual QString portName(void* port) = 0;
+ virtual int getState() = 0;
+ virtual unsigned getCurFrame() = 0;
+ virtual bool isRealtime() = 0;
+ virtual int realtimePriority() const = 0; // return zero if not realtime
+ virtual void startTransport() = 0;
+ virtual void stopTransport() = 0;
+ virtual void seekTransport(unsigned frame) = 0;
+ virtual void seekTransport(const Pos &p) = 0;
+ virtual void setFreewheel(bool f) = 0;
+ virtual void graphChanged() {}
+ virtual void registrationChanged() {}
+ virtual int setMaster(bool f) = 0;
+ };
+
+#endif
+
diff --git a/attic/muse2-oom/muse2/muse/driver/dummyaudio.cpp b/attic/muse2-oom/muse2/muse/driver/dummyaudio.cpp
new file mode 100644
index 00000000..f4a00b4e
--- /dev/null
+++ b/attic/muse2-oom/muse2/muse/driver/dummyaudio.cpp
@@ -0,0 +1,453 @@
+//=========================================================
+// MusE
+// Linux Music Editor
+// $Id: dummyaudio.cpp,v 1.3.2.16 2009/12/20 05:00:35 terminator356 Exp $
+// (C) Copyright 2002-2003 Werner Schweer (ws@seh.de)
+//=========================================================
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include <errno.h>
+#include <stdarg.h>
+#include <pthread.h>
+#include <sys/poll.h>
+
+#include "config.h"
+#include "audio.h"
+#include "audiodev.h"
+#include "globals.h"
+#include "song.h"
+#include "driver/alsatimer.h"
+#include "pos.h"
+#include "gconfig.h"
+#include "utils.h"
+
+class MidiPlayEvent;
+
+#define DEBUG_DUMMY 0
+//---------------------------------------------------------
+// DummyAudioDevice
+//---------------------------------------------------------
+
+//static const unsigned dummyFrames = 1024;
+
+enum Cmd {
+trSeek,
+trStart,
+trStop
+};
+
+struct Msg {
+ enum Cmd cmd;
+ int arg;
+};
+
+
+class DummyAudioDevice : public AudioDevice {
+ pthread_t dummyThread;
+ // Changed by Tim. p3.3.15
+ //float buffer[1024];
+ float* buffer;
+ int _realTimePriority;
+
+ public:
+ std::list<Msg> cmdQueue;
+ Audio::State state;
+ int _framePos;
+ int playPos;
+ bool realtimeFlag;
+
+ DummyAudioDevice();
+ virtual ~DummyAudioDevice()
+ {
+ // Added by Tim. p3.3.15
+ free(buffer);
+ }
+
+ virtual inline int deviceType() { return DUMMY_AUDIO; } // p3.3.52
+
+ //virtual void start();
+ virtual void start(int);
+
+ virtual void stop ();
+ virtual int framePos() const {
+ if(DEBUG_DUMMY)
+ printf("DummyAudioDevice::framePos %d\n", _framePos);
+ return _framePos;
+ }
+
+ virtual float* getBuffer(void* /*port*/, unsigned long nframes)
+ {
+ // p3.3.30
+ //if (nframes > dummyFrames) {
+ //printf("error: segment size > 1024\n");
+ if (nframes > segmentSize) {
+ printf("DummyAudioDevice::getBuffer nframes > segment size\n");
+
+ exit(-1);
+ }
+ return buffer;
+ }
+
+ virtual std::list<QString> outputPorts(bool midi = false, int aliases = -1);
+ virtual std::list<QString> inputPorts(bool midi = false, int aliases = -1);
+
+ virtual void registerClient() {}
+
+ virtual const char* clientName() { return "MusE"; }
+
+ //virtual void* registerOutPort(const char*) {
+ virtual void* registerOutPort(const char*, bool) {
+ return (void*)1;
+ }
+ //virtual void* registerInPort(const char*) {
+ virtual void* registerInPort(const char*, bool) {
+ return (void*)2;
+ }
+ virtual void unregisterPort(void*) {}
+ virtual void connect(void*, void*) {}
+ virtual void disconnect(void*, void*) {}
+ virtual int connections(void* /*clientPort*/) { return 0; }
+ virtual void setPortName(void*, const char*) {}
+ virtual void* findPort(const char*) { return 0;}
+ virtual QString portName(void*) {
+ return QString("mops");
+ }
+ virtual int getState() {
+// if(DEBUG_DUMMY)
+// printf("DummyAudioDevice::getState %d\n", state);
+
+ return state; }
+ virtual unsigned getCurFrame() {
+ if(DEBUG_DUMMY)
+ printf("DummyAudioDevice::getCurFrame %d\n", _framePos);
+
+ return _framePos; }
+ virtual unsigned frameTime() const {
+ return lrint(curTime() * sampleRate);
+ }
+ virtual bool isRealtime() { return realtimeFlag; }
+ //virtual int realtimePriority() const { return 40; }
+ virtual int realtimePriority() const { return _realTimePriority; }
+ virtual void startTransport() {
+ if(DEBUG_DUMMY)
+ printf("DummyAudioDevice::startTransport playPos=%d\n", playPos);
+ Msg trcmd;
+ trcmd.cmd = trStart;
+ trcmd.arg = playPos;
+ cmdQueue.push_front(trcmd);
+/* state = Audio::START_PLAY;
+ audio->sync(state, playPos);
+ state = Audio::PLAY;*/
+ }
+ virtual void stopTransport() {
+ if(DEBUG_DUMMY)
+ printf("DummyAudioDevice::stopTransport, playPos=%d\n", playPos);
+ state = Audio::STOP;
+ }
+ virtual int setMaster(bool) { return 1; }
+
+ virtual void seekTransport(const Pos &p)
+ {
+ if(DEBUG_DUMMY)
+ printf("DummyAudioDevice::seekTransport frame=%d topos=%d\n",playPos, p.frame());
+ Msg trcmd;
+ trcmd.cmd = trSeek;
+ trcmd.arg = p.frame();
+ cmdQueue.push_front(trcmd);
+ playPos = p.frame();
+ }
+ virtual void seekTransport(unsigned pos) {
+ if(DEBUG_DUMMY)
+ printf("DummyAudioDevice::seekTransport frame=%d topos=%d\n",playPos,pos);
+ Msg trcmd;
+ trcmd.cmd = trSeek;
+ trcmd.arg = pos;
+ cmdQueue.push_front(trcmd);
+ playPos = pos;
+/*
+ Audio::State tempState = state;
+ state = Audio::START_PLAY;
+ audio->sync(state, playPos);
+ state = tempState;*/
+ }
+ virtual void setFreewheel(bool) {}
+ void setRealTime() { realtimeFlag = true; }
+ };
+
+DummyAudioDevice* dummyAudio = 0;
+
+DummyAudioDevice::DummyAudioDevice()
+ {
+ // Added by Tim. p3.3.15
+ // p3.3.30
+ //posix_memalign((void**)&buffer, 16, sizeof(float) * dummyFrames);
+ posix_memalign((void**)&buffer, 16, sizeof(float) * config.dummyAudioBufSize);
+
+ realtimeFlag = false;
+ state = Audio::STOP;
+ _framePos = 0;
+ playPos = 0;
+ cmdQueue.clear();
+ }
+
+//---------------------------------------------------------
+// exitDummyAudio
+//---------------------------------------------------------
+
+void exitDummyAudio()
+{
+ if(dummyAudio)
+ delete dummyAudio;
+ dummyAudio = NULL;
+ audioDevice = NULL;
+}
+
+//---------------------------------------------------------
+// initDummyAudio
+//---------------------------------------------------------
+
+bool initDummyAudio()
+ {
+ dummyAudio = new DummyAudioDevice();
+ audioDevice = dummyAudio;
+ return false;
+ }
+
+//---------------------------------------------------------
+// outputPorts
+//---------------------------------------------------------
+
+std::list<QString> DummyAudioDevice::outputPorts(bool midi, int /*aliases*/)
+ {
+ std::list<QString> clientList;
+ if(!midi)
+ {
+ clientList.push_back(QString("output1"));
+ clientList.push_back(QString("output2"));
+ }
+ return clientList;
+ }
+
+//---------------------------------------------------------
+// inputPorts
+//---------------------------------------------------------
+
+std::list<QString> DummyAudioDevice::inputPorts(bool midi, int /*aliases*/)
+ {
+ std::list<QString> clientList;
+ if(!midi)
+ {
+ clientList.push_back(QString("input1"));
+ clientList.push_back(QString("input2"));
+ }
+ return clientList;
+ }
+
+//---------------------------------------------------------
+// dummyLoop
+//---------------------------------------------------------
+
+static void* dummyLoop(void* ptr)
+ {
+ //unsigned int tickRate = 25;
+
+ // p3.3.30
+ //sampleRate = 25600;
+ sampleRate = config.dummyAudioSampleRate;
+ //segmentSize = dummyFrames;
+ segmentSize = config.dummyAudioBufSize;
+ //unsigned int tickRate = sampleRate / dummyFrames;
+ unsigned int tickRate = sampleRate / segmentSize;
+
+ AlsaTimer timer;
+ fprintf(stderr, "Get alsa timer for dummy driver:\n");
+ timer.setFindBestTimer(false);
+ int fd = timer.initTimer();
+ if (fd==-1) {
+ // QMessageBox::critical( 0, /*tr*/(QString("Failed to start timer for dummy audio driver!")),
+ // /*tr*/(QString("No functional timer was available.\n"
+ // "Alsa timer not available, check if module snd_timer is available and /dev/snd/timer is available")));
+ fprintf(stderr, "Failed to start timer for dummy audio driver! No functional timer was available.\n"
+ "Alsa timer not available, check if module snd_timer is available and /dev/snd/timer is available\n");
+ pthread_exit(0);
+ }
+
+ /* Depending on nature of the timer, the requested tickRate might not
+ * be available. The return value is the nearest available frequency,
+ * so use this to reset our dummpy sampleRate to keep everything
+ * consistent.
+ */
+ tickRate = timer.setTimerFreq( /*250*/ tickRate );
+
+ // p3.3.31
+ // If it didn't work, get the actual rate.
+ if(tickRate == 0)
+ tickRate = timer.getTimerFreq();
+
+ sampleRate = tickRate * segmentSize;
+ timer.startTimer();
+
+ DummyAudioDevice *drvPtr = (DummyAudioDevice *)ptr;
+
+ pollfd myPollFd;
+
+ myPollFd.fd = fd;
+ myPollFd.events = POLLIN;
+
+ /*
+ doSetuid();
+ struct sched_param rt_param;
+ int rv;
+ memset(&rt_param, 0, sizeof(sched_param));
+ int type;
+ rv = pthread_getschedparam(pthread_self(), &type, &rt_param);
+ if (rv != 0)
+ perror("get scheduler parameter");
+ if (type != SCHED_FIFO) {
+ fprintf(stderr, "Driver thread not running SCHED_FIFO, trying to set...\n");
+
+ memset(&rt_param, 0, sizeof(sched_param));
+ //rt_param.sched_priority = 1;
+ rt_param.sched_priority = realtimePriority();
+ rv = pthread_setschedparam(pthread_self(), SCHED_FIFO, &rt_param);
+ if (rv != 0)
+ perror("set realtime scheduler");
+ memset(&rt_param, 0, sizeof(sched_param));
+ rv = pthread_getschedparam(pthread_self(), &type, &rt_param);
+ if (rv != 0)
+ perror("get scheduler parameter");
+ if (type == SCHED_FIFO) {
+ drvPtr->setRealTime();
+ fprintf(stderr, "Thread succesfully set to SCHED_FIFO\n");
+ }
+ else {
+ fprintf(stderr, "Unable to set thread to SCHED_FIFO\n");
+ }
+ }
+ undoSetuid();
+ */
+
+#ifndef __APPLE__
+ doSetuid();
+ //if (realTimePriority) {
+ if (realTimeScheduling) {
+ //
+ // check if we really got realtime priviledges
+ //
+ int policy;
+ if ((policy = sched_getscheduler (0)) < 0) {
+ printf("cannot get current client scheduler for audio dummy thread: %s!\n", strerror(errno));
+ }
+ else
+ {
+ if (policy != SCHED_FIFO)
+ printf("audio dummy thread _NOT_ running SCHED_FIFO\n");
+ else if (debugMsg) {
+ struct sched_param rt_param;
+ memset(&rt_param, 0, sizeof(sched_param));
+ int type;
+ int rv = pthread_getschedparam(pthread_self(), &type, &rt_param);
+ if (rv == -1)
+ perror("get scheduler parameter");
+ printf("audio dummy thread running SCHED_FIFO priority %d\n",
+ rt_param.sched_priority);
+ }
+ }
+ }
+ undoSetuid();
+#endif
+
+ /* unsigned long tick = 0;*/ // prevent compiler warning: unused variable
+ for (;;) {
+ int _pollWait = 10; // ms
+ unsigned long count = 0;
+ while (count < 1 /*250/tickRate*/) // will loop until the next tick occurs
+ {
+ /*int n = */ poll(&myPollFd, 1 /* npfd */, _pollWait);
+ count += timer.getTimerTicks();
+ while (drvPtr->cmdQueue.size())
+ {
+ Msg &msg = drvPtr->cmdQueue.back();
+ drvPtr->cmdQueue.pop_back();
+ switch(msg.cmd) {
+ case trSeek:
+ {
+ //printf("trSeek\n");
+ drvPtr->playPos = msg.arg;
+ Audio::State tempState = drvPtr->state;
+ drvPtr->state = Audio::START_PLAY;
+ audio->sync(drvPtr->state, msg.arg);
+ drvPtr->state = tempState;
+ }
+ break;
+ case trStart:
+ {
+ //printf("trStart\n");
+ drvPtr->state = Audio::START_PLAY;
+ audio->sync(drvPtr->state, msg.arg);
+ drvPtr->state = Audio::PLAY;
+ }
+ break;
+ case trStop:
+ break;
+ default:
+ printf("dummyLoop: Unknown command!\n");
+ }
+ }
+ }
+ audio->process(segmentSize);
+ int increment = segmentSize; // 1 //tickRate / sampleRate * segmentSize;
+ drvPtr->_framePos+=increment;
+ if (drvPtr->state == Audio::PLAY)
+ {
+ drvPtr->playPos+=increment;
+ }
+ }
+ timer.stopTimer();
+ pthread_exit(0);
+ }
+
+//void DummyAudioDevice::start()
+void DummyAudioDevice::start(int priority)
+ {
+ //realTimePriority = priority;
+ _realTimePriority = priority;
+ pthread_attr_t* attributes = 0;
+
+ //if (priority) {
+ if (realTimeScheduling && priority > 0) {
+ attributes = (pthread_attr_t*) malloc(sizeof(pthread_attr_t));
+ pthread_attr_init(attributes);
+
+ if (pthread_attr_setschedpolicy(attributes, SCHED_FIFO)) {
+ printf("cannot set FIFO scheduling class for RT thread\n");
+ }
+ if (pthread_attr_setscope (attributes, PTHREAD_SCOPE_SYSTEM)) {
+ printf("Cannot set scheduling scope for RT thread\n");
+ }
+ struct sched_param rt_param;
+ memset(&rt_param, 0, sizeof(rt_param));
+ rt_param.sched_priority = priority;
+ if (pthread_attr_setschedparam (attributes, &rt_param)) {
+ printf("Cannot set scheduling priority %d for RT thread (%s)\n",
+ priority, strerror(errno));
+ }
+ }
+
+ //pthread_attr_t* attributes = (pthread_attr_t*) malloc(sizeof(pthread_attr_t));
+ //pthread_attr_init(attributes);
+ if (pthread_create(&dummyThread, attributes, ::dummyLoop, this))
+ perror("creating thread failed:");
+ if (priority)
+ pthread_attr_destroy(attributes);
+ }
+
+void DummyAudioDevice::stop ()
+ {
+ pthread_cancel(dummyThread);
+ pthread_join(dummyThread, 0);
+ dummyThread = 0;
+ }
+
diff --git a/attic/muse2-oom/muse2/muse/driver/jack.cpp b/attic/muse2-oom/muse2/muse/driver/jack.cpp
new file mode 100644
index 00000000..f70cf3d3
--- /dev/null
+++ b/attic/muse2-oom/muse2/muse/driver/jack.cpp
@@ -0,0 +1,2217 @@
+//=========================================================
+// MusE
+// Linux Music Editor
+// $Id: jack.cpp,v 1.30.2.17 2009/12/20 05:00:35 terminator356 Exp $
+// (C) Copyright 2002 Werner Schweer (ws@seh.de)
+//=========================================================
+
+#include "config.h"
+#include <string>
+#include <set>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <stdarg.h>
+//#include <time.h>
+#include <unistd.h>
+#include <jack/midiport.h>
+#include <string.h>
+
+#include "audio.h"
+#include "globals.h"
+#include "song.h"
+#include "jackaudio.h"
+#include "track.h"
+#include "pos.h"
+#include "tempo.h"
+#include "sync.h"
+#include "utils.h"
+
+#include "midi.h"
+#include "mididev.h"
+#include "mpevent.h"
+
+#include "jackmidi.h"
+
+
+#define JACK_DEBUG 0
+
+//#include "errorhandler.h"
+
+#ifndef RTCAP
+extern void doSetuid();
+extern void undoSetuid();
+#endif
+
+#ifdef VST_SUPPORT
+#include <fst.h>
+#endif
+
+//extern int jackmidi_pi[2];
+//extern int jackmidi_po[2];
+
+//jack_port_t *midi_port_in[JACK_MIDI_CHANNELS];
+//jack_port_t *midi_port_out[JACK_MIDI_CHANNELS];
+
+//muse_jack_midi_buffer jack_midi_out_data[JACK_MIDI_CHANNELS];
+//muse_jack_midi_buffer jack_midi_in_data[JACK_MIDI_CHANNELS];
+
+JackAudioDevice* jackAudio;
+
+//---------------------------------------------------------
+// checkJackClient - make sure client is valid
+//---------------------------------------------------------
+inline bool checkJackClient(jack_client_t* _client)
+ {
+ if (_client == NULL) {
+ printf("Panic! no _client!\n");
+ return false;
+ }
+ return true;
+ }
+//---------------------------------------------------------
+// checkAudioDevice - make sure audioDevice exists
+//---------------------------------------------------------
+bool checkAudioDevice()
+ {
+ if (audioDevice == NULL) {
+ printf("Muse:checkAudioDevice: no audioDevice\n");
+ return false;
+ }
+ return true;
+ }
+
+
+//---------------------------------------------------------
+// jack_thread_init
+//---------------------------------------------------------
+
+static void jack_thread_init (void* ) // data
+ {
+ doSetuid();
+ /*
+ if (jackAudio->isRealtime()) {
+ struct sched_param rt_param;
+ int rv;
+ memset(&rt_param, 0, sizeof(sched_param));
+ int type;
+ rv = pthread_getschedparam(pthread_self(), &type, &rt_param);
+ if (rv != 0)
+ perror("get scheduler parameter");
+ if (type != SCHED_FIFO) {
+ fprintf(stderr, "JACK thread not running SCHED_FIFO, try to set...\n");
+
+ memset(&rt_param, 0, sizeof(sched_param));
+ rt_param.sched_priority = 1;
+ rv = pthread_setschedparam(pthread_self(), SCHED_FIFO, &rt_param);
+ if (rv != 0)
+ perror("set realtime scheduler");
+ memset(&rt_param, 0, sizeof(sched_param));
+ rv = pthread_getschedparam(pthread_self(), &type, &rt_param);
+ if (rv != 0)
+ perror("get scheduler parameter");
+ if (type != SCHED_FIFO)
+ fprintf(stderr, "JACK still not running FIFO !?!\n"
+ "======reliable RT operation not possible!!======\n");
+ else
+ fprintf(stderr, "JACK thread succesfully set to SCHED_FIFO\n");
+ }
+ }
+ */
+#ifdef VST_SUPPORT
+ if (loadVST)
+ fst_adopt_thread();
+#endif
+ undoSetuid();
+ }
+
+/*
+//---------------------------------------------------------
+// processAudio + Midi
+// JACK callback
+//---------------------------------------------------------
+void
+print_triplet(unsigned char *data)
+{
+ int a,b,c;
+ a = b = c = 0;
+ memcpy(&a, data, 1);
+ memcpy(&b, data+1, 1);
+ memcpy(&c, data+2, 1);
+ fprintf(stderr, "%x,%x,%x", a, b, c);
+}
+*/
+
+/*
+void handle_jack_midi_in_events(jack_nframes_t frames)
+{
+ char buf = 0;
+ int i,j;
+ jack_midi_event_t midi_event;
+ unsigned char t,n,v;
+
+ for(j = 0; j < JACK_MIDI_CHANNELS; j++){
+ void *midi_buffer_in = jack_port_get_buffer(midi_port_in[j], frames);
+ int event_count = jack_midi_get_event_count(midi_buffer_in);
+
+ for(i = 0; i < event_count; i++){
+ jack_midi_event_get(&midi_event, midi_buffer_in, i);
+ t = midi_event.buffer[0];
+ n = midi_event.buffer[1];
+ v = midi_event.buffer[2];
+ if(((*(midi_event.buffer) & 0xf0)) == 0x90){
+ fprintf(stderr, "jack-midi-in-event: ON_ time=%d %u ", midi_event.time,
+ midi_event.size);
+ print_triplet(midi_event.buffer);
+ fprintf(stderr, "\n");
+ }else if(((*(midi_event.buffer)) & 0xf0) == 0x80){
+ fprintf(stderr, "jack-midi-in-event: OFF time=%d %u ", midi_event.time,
+ midi_event.size);
+ print_triplet(midi_event.buffer);
+ fprintf(stderr, "\n");
+ }else{
+ fprintf(stderr, "jack-midi-in-event: ??? time=%d %u ", midi_event.time,
+ midi_event.size);
+ print_triplet(midi_event.buffer);
+ fprintf(stderr, "\n");
+ }
+ jack_midi_in_data[j].buffer[0] = t;
+ jack_midi_in_data[j].buffer[1] = n;
+ jack_midi_in_data[j].buffer[2] = v;
+ jack_midi_in_data[j].buffer[3] = 1;
+ fprintf(stderr, "handle_jack_midi_in_events() w\n");
+ write(jackmidi_pi[1], &buf, 1);
+ fprintf(stderr, "handle_jack_midi_in_events() wd\n");
+ }
+ }
+}
+
+void handle_jack_midi_out_events(jack_nframes_t frames)
+{
+ unsigned char *data;
+ void *port_buf;
+ int i,j,n,x;
+
+ //for(i = 0; i < JACK_MIDI_CHANNELS; i++){
+ for(i = 0; i < JACK_MIDI_CHANNELS; ++i){
+ // jack-midi-clear any old events
+ while(jack_midi_out_data[i].buffer[jack_midi_out_data[i].take*4+3] == 2){
+ port_buf = jack_port_get_buffer(midi_port_out[i], frames);
+ jack_midi_clear_buffer(port_buf);
+ jack_midi_out_data[i].buffer[jack_midi_out_data[i].take*4+3] = 0;
+ // point the take to the next slot
+ jack_midi_out_data[i].take++;
+ if(jack_midi_out_data[i].take >= JACK_MIDI_BUFFER_SIZE){
+ jack_midi_out_data[i].take = 0;
+ }
+ }
+ // check if any incoming midi-events from muse
+ if(jack_midi_out_data[i].give != jack_midi_out_data[i].take){
+
+ if(jack_midi_out_data[i].give > jack_midi_out_data[i].take){
+ n = jack_midi_out_data[i].give - jack_midi_out_data[i].take;
+ }else{
+ n = jack_midi_out_data[i].give +
+ (JACK_MIDI_BUFFER_SIZE - jack_midi_out_data[i].take);
+ }
+ port_buf = jack_port_get_buffer(midi_port_out[i], frames);
+ jack_midi_clear_buffer(port_buf);
+ // FIX: midi events has different sizes, compare note-on to
+ // program-change. We should first walk over the events
+ // counting the size.
+ //data = jack_midi_event_reserve(port_buf, 0, n*3);
+ //x = jack_midi_out_data[i].take;
+ //for(j = 0; j < n; j++){
+ // data[j*3+0] = jack_midi_out_data[i].buffer[x*4+0];
+ // data[j*3+1] = jack_midi_out_data[i].buffer[x*4+1];
+ // data[j*3+2] = jack_midi_out_data[i].buffer[x*4+2];
+ // after having copied the buffer over to the jack-buffer,
+ // mark the muses midi-out buffer as 'need-cleaning'
+ // jack_midi_out_data[i].buffer[x*4+3] = 2;
+ // x++;
+ // if(x >= JACK_MIDI_BUFFER_SIZE){
+ // x = 0;
+ // }
+ //}
+
+ x = jack_midi_out_data[i].take;
+ for(j = 0; j < n; ++j)
+ {
+ data = jack_midi_event_reserve(port_buf, 0, 3);
+ if(data == 0)
+ {
+ fprintf(stderr, "handle_jack_midi_out_events: buffer overflow, event lost\n");
+ // Can do no more processing. Just return.
+ return;
+ }
+ data[0] = jack_midi_out_data[i].buffer[x*4+0];
+ data[1] = jack_midi_out_data[i].buffer[x*4+1];
+ data[2] = jack_midi_out_data[i].buffer[x*4+2];
+ // after having copied the buffer over to the jack-buffer,
+ // mark the muses midi-out buffer as 'need-cleaning'
+ jack_midi_out_data[i].buffer[x*4+3] = 2;
+ x++;
+ if(x >= JACK_MIDI_BUFFER_SIZE){
+ x = 0;
+ }
+ }
+
+ }
+ }
+}
+*/
+
+//static int processAudio(jack_nframes_t frames, void*)
+int JackAudioDevice::processAudio(jack_nframes_t frames, void*)
+{
+ jackAudio->_frameCounter += frames;
+
+/// handle_jack_midi_in_events(frames);
+/// handle_jack_midi_out_events(frames);
+
+// if (JACK_DEBUG)
+// printf("processAudio - >>>>\n");
+ segmentSize = frames;
+ if (audio->isRunning())
+ audio->process((unsigned long)frames);
+ else {
+ if (debugMsg)
+ puts("jack calling when audio is disconnected!\n");
+ }
+// if (JACK_DEBUG)
+// printf("processAudio - <<<<\n");
+ return 0;
+}
+
+//---------------------------------------------------------
+// processSync
+// return TRUE (non-zero) when ready to roll.
+//---------------------------------------------------------
+
+static int processSync(jack_transport_state_t state, jack_position_t* pos, void*)
+ {
+ if (JACK_DEBUG)
+ printf("processSync()\n");
+
+ if(!useJackTransport.value())
+ return 1;
+
+ int audioState = Audio::STOP;
+ switch (state) {
+ case JackTransportStopped:
+ audioState = Audio::STOP;
+ break;
+ case JackTransportLooping:
+ case JackTransportRolling:
+ audioState = Audio::PLAY;
+ break;
+ case JackTransportStarting:
+ //printf("processSync JackTransportStarting\n");
+
+ audioState = Audio::START_PLAY;
+ break;
+ //case JackTransportNetStarting:
+ // FIXME: Quick and dirty hack to support both Jack-1 and Jack-2
+ // Really need a config check of version...
+ case 4:
+ //printf("processSync JackTransportNetStarting\n");
+
+ audioState = Audio::START_PLAY;
+ break;
+ }
+
+ unsigned frame = pos->frame;
+ //printf("processSync valid:%d frame:%d\n", pos->valid, frame);
+
+ // p3.3.23
+ //printf("Jack processSync() before audio->sync frame:%d\n", frame);
+ //return audio->sync(audioState, frame);
+ int rv = audio->sync(audioState, frame);
+ //printf("Jack processSync() after audio->sync frame:%d\n", frame);
+ return rv;
+ }
+
+//---------------------------------------------------------
+// timebase_callback
+//---------------------------------------------------------
+
+static void timebase_callback(jack_transport_state_t /* state */,
+ jack_nframes_t /* nframes */,
+ jack_position_t* pos,
+ int /* new_pos */,
+ void*)
+ {
+ //printf("Jack timebase_callback pos->frame:%u audio->tickPos:%d song->cpos:%d\n", pos->frame, audio->tickPos(), song->cpos());
+
+ // p3.3.27
+ //Pos p(pos->frame, false);
+ Pos p(extSyncFlag.value() ? audio->tickPos() : pos->frame, extSyncFlag.value() ? true : false);
+ // Can't use song pos - it is only updated every (slow) GUI heartbeat !
+ //Pos p(extSyncFlag.value() ? song->cpos() : pos->frame, extSyncFlag.value() ? true : false);
+
+ 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:
+ //
+
+ // p3.3.26
+ //pos->beats_per_bar = 4;
+ //pos->beat_type = 4;
+ //pos->ticks_per_beat = 384;
+ //
+ /* // From example client transport.c :
+ float time_beats_per_bar = 4.0;
+ float time_beat_type = 0.25; // Huh? Inverted? From docs: "Time signature 'denominator'"
+ double time_ticks_per_beat = 1920.0; // Huh? Ticks per beat should be 24 etc. not 384 or 1920 etc. Otherwise it would be called 'frames_per_beat'.
+ double time_beats_per_minute = 120.0;
+ */
+ //
+ int z, n;
+ AL::sigmap.timesig(p.tick(), z, n);
+ pos->beats_per_bar = z;
+ pos->beat_type = n;
+ //pos->ticks_per_beat = config.division;
+ pos->ticks_per_beat = 24;
+
+ int tempo = tempomap.tempo(p.tick());
+ pos->beats_per_minute = (60000000.0 / tempo) * tempomap.globalTempo()/100.0;
+ }
+
+//---------------------------------------------------------
+// processShutdown
+//---------------------------------------------------------
+
+static void processShutdown(void*)
+ {
+ if (JACK_DEBUG)
+ printf("processShutdown()\n");
+ //printf("processShutdown\n");
+ jackAudio->nullify_client();
+ audio->shutdown();
+
+ int c=0;
+ while(midiSeqRunning == true) {
+ if(c++ >10) {
+ fprintf(stderr, "sequencer still running, something is very wrong.\n");
+ break;
+ }
+ sleep(1);
+ }
+ delete jackAudio;
+ jackAudio=0;
+ audioDevice=0;
+ }
+
+//---------------------------------------------------------
+// jackError
+//---------------------------------------------------------
+
+static void jackError(const char *s)
+ {
+ //error->logError( "JACK ERROR: %s\n", s);
+ fprintf(stderr,"JACK ERROR: %s\n", s);
+ }
+
+//---------------------------------------------------------
+// noJackError
+//---------------------------------------------------------
+
+static void noJackError(const char* /* s */)
+ {
+ }
+
+//---------------------------------------------------------
+// JackAudioDevice
+//---------------------------------------------------------
+
+JackAudioDevice::JackAudioDevice(jack_client_t* cl, char* name)
+ : AudioDevice()
+ {
+ _frameCounter = 0;
+ //JackAudioDevice::jackStarted=false;
+ strcpy(jackRegisteredName, name);
+ _client = cl;
+ dummyState = Audio::STOP;
+ dummyPos = 0;
+ }
+
+//---------------------------------------------------------
+// ~JackAudioDevice
+//---------------------------------------------------------
+
+JackAudioDevice::~JackAudioDevice()
+ {
+ if (JACK_DEBUG)
+ printf("~JackAudioDevice()\n");
+ if (_client) {
+
+ /*
+ // p3.3.35
+ for(int i = 0; i < JACK_MIDI_CHANNELS; i++)
+ {
+ if(midi_port_in[i])
+ jack_port_unregister(_client, midi_port_in[i]);
+ if(midi_port_out[i])
+ jack_port_unregister(_client, midi_port_out[i]);
+ }
+ */
+
+ if (jack_client_close(_client)) {
+ //error->logError("jack_client_close() failed: %s\n", strerror(errno));
+ fprintf(stderr,"jack_client_close() failed: %s\n", strerror(errno));
+ }
+ }
+ if (JACK_DEBUG)
+ printf("~JackAudioDevice() after jack_client_close()\n");
+ }
+
+//---------------------------------------------------------
+// realtimePriority
+// return zero if not running realtime
+// can only be called if JACK client thread is already
+// running
+//---------------------------------------------------------
+
+int JackAudioDevice::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: JackAudioDevice::realtimePriority: Error: Get jack schedule parameter");
+ return 0;
+ }
+ if (policy != SCHED_FIFO) {
+ printf("MusE: JackAudioDevice::realtimePriority: JACK is not running realtime\n");
+ return 0;
+ }
+ return param.sched_priority;
+ }
+
+/*
+//---------------------------------------------------------
+// getJackName()
+//---------------------------------------------------------
+
+char* JackAudioDevice::getJackName()
+ {
+ return jackRegisteredName;
+ }
+*/
+
+/*
+//---------------------------------------------------------
+// clientName()
+//---------------------------------------------------------
+
+const char* JackAudioDevice::clientName()
+{
+ //if(_client)
+ // return jack_get_client_name(_client);
+ //else
+ // return "MusE";
+ return jackRegisteredName;
+}
+*/
+
+//---------------------------------------------------------
+// initJackAudio
+// return true if JACK not found
+//---------------------------------------------------------
+
+bool initJackAudio()
+ {
+ /*
+ // p3.3.35
+ for(int i = 0; i < JACK_MIDI_CHANNELS; i++)
+ {
+ midi_port_in[i] = 0;
+ midi_port_out[i] = 0;
+ }
+ */
+
+ if (JACK_DEBUG)
+ printf("initJackAudio()\n");
+ if (debugMsg) {
+ fprintf(stderr,"initJackAudio()\n");
+ jack_set_error_function(jackError);
+ }
+ else
+ jack_set_error_function(noJackError);
+ doSetuid();
+
+ //jack_client_t* client = 0;
+ //int i = 0;
+ //char jackIdString[8];
+ //for (i = 0; i < 5; ++i) {
+ // sprintf(jackIdString, "MusE-%d", i+1);
+ //client = jack_client_new(jackIdString);
+ // client = jack_client_open(jackIdString, JackNoStartServer, 0);
+ // if (client)
+ // break;
+ // }
+ //if (i == 5)
+ // return true;
+ jack_status_t status;
+ jack_client_t* client = jack_client_open("MusE", JackNoStartServer, &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");
+ undoSetuid(); // p3.3.51
+ return true;
+ }
+
+ if (debugMsg)
+ fprintf(stderr, "initJackAudio(): client %s opened.\n", jack_get_client_name(client));
+ if (client) {
+ jack_set_error_function(jackError);
+ //jackAudio = new JackAudioDevice(client, jackIdString);
+ jackAudio = new JackAudioDevice(client, jack_get_client_name(client));
+ if (debugMsg)
+ fprintf(stderr, "initJackAudio(): registering client...\n");
+ jackAudio->registerClient();
+ sampleRate = jack_get_sample_rate(client);
+ segmentSize = jack_get_buffer_size(client);
+ jack_set_thread_init_callback(client, (JackThreadInitCallback) jack_thread_init, 0);
+ //jack_set_timebase_callback(client, 0, (JackTimebaseCallback) timebase_callback, 0);
+ }
+ undoSetuid();
+
+ /*
+ // setup midi input/output
+ //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));
+ if(client){
+ for(i = 0; i < JACK_MIDI_CHANNELS; i++)
+ {
+ char buf[80];
+ snprintf(buf, 80, "muse-jack-midi-in-%d", i+1);
+ midi_port_in[i] = jack_port_register(client, buf,
+ JACK_DEFAULT_MIDI_TYPE,
+ JackPortIsInput, 0);
+ if(midi_port_in[i] == NULL){
+ fprintf(stderr, "failed to register jack-midi-in\n");
+ exit(-1);
+ }
+ snprintf(buf, 80, "muse-jack-midi-out-%d", i+1);
+ midi_port_out[i] = jack_port_register(client, buf,
+ JACK_DEFAULT_MIDI_TYPE,
+ JackPortIsOutput, 0);
+ if(midi_port_out == NULL)
+ {
+ fprintf(stderr, "failed to register jack-midi-out\n");
+ exit(-1);
+ }
+ }
+ }
+ else
+ {
+ fprintf(stderr, "WARNING NO muse-jack midi connection\n");
+ }
+ */
+
+ if (client) {
+ audioDevice = jackAudio;
+ jackAudio->scanMidiPorts();
+ return false;
+ }
+ return true;
+ }
+
+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*)
+ {
+ if (debugMsg || JACK_DEBUG)
+ printf("JACK: freewheel_callback: starting%d\n", starting);
+ audio->setFreewheel(starting);
+ }
+
+static int srate_callback(jack_nframes_t n, void*)
+ {
+ if (debugMsg || JACK_DEBUG)
+ printf("JACK: sample rate changed: %d\n", n);
+ return 0;
+ }
+
+//---------------------------------------------------------
+// registration_callback
+//---------------------------------------------------------
+
+static void registration_callback(jack_port_id_t, int, void*)
+{
+ if(debugMsg || JACK_DEBUG)
+ printf("JACK: registration changed\n");
+
+ audio->sendMsgToGui('R');
+}
+
+//---------------------------------------------------------
+// JackAudioDevice::registrationChanged
+// this is called from song in gui context triggered
+// by registration_callback()
+//---------------------------------------------------------
+
+void JackAudioDevice::registrationChanged()
+{
+ if(JACK_DEBUG)
+ printf("JackAudioDevice::registrationChanged()\n");
+
+ // Rescan.
+ scanMidiPorts();
+ // Connect the Jack midi client ports to the device ports.
+ //connectJackMidiPorts();
+}
+
+//---------------------------------------------------------
+// JackAudioDevice::connectJackMidiPorts
+//---------------------------------------------------------
+
+void JackAudioDevice::connectJackMidiPorts()
+{
+ if(JACK_DEBUG)
+ printf("JackAudioDevice::connectJackMidiPorts()\n");
+
+ for (iMidiDevice i = midiDevices.begin(); i != midiDevices.end(); ++i)
+ {
+ //MidiJackDevice* mjd = dynamic_cast<MidiJackDevice*>(*i);
+ //if(!mjd)
+ MidiDevice* md = *i;
+ if(md->deviceType() != MidiDevice::JACK_MIDI)
+ continue;
+
+ //void* port = md->clientPort();
+ if(md->rwFlags() & 1)
+ {
+ 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 // p3.3.55 Removed
+
+ if(md->rwFlags() & 2)
+ {
+ 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);
+ }
+ }
+ }
+
+
+ /*
+ const char* type = JACK_DEFAULT_MIDI_TYPE;
+ const char** ports = jack_get_ports(_client, 0, type, 0);
+ for (const char** p = ports; p && *p; ++p)
+ {
+ jack_port_t* port = jack_port_by_name(_client, *p);
+ if(!port)
+ continue;
+ // Ignore our own client ports.
+ if(jack_port_is_mine(_client, port))
+ {
+ if(debugMsg)
+ printf(" ignoring own port: %s\n", *p);
+ continue;
+ }
+ int nsz = jack_port_name_size();
+ char buffer[nsz];
+ strncpy(buffer, *p, nsz);
+ // Ignore the MusE Jack port.
+ //if(strncmp(buffer, "MusE", 4) == 0)
+ // continue;
+
+ if(debugMsg)
+ printf(" found port: %s ", buffer);
+
+ // If there are aliases for this port, use the first one - much better for identifying.
+ //char a1[nsz];
+ char a2[nsz];
+ char* aliases[2];
+ //aliases[0] = a1;
+ aliases[0] = buffer;
+ aliases[1] = a2;
+ // To disable aliases, just rem this line.
+ jack_port_get_aliases(port, aliases);
+ //int na = jack_port_get_aliases(port, aliases);
+ //char* namep = (na >= 1) ? aliases[0] : buffer;
+ char* namep = aliases[0];
+
+ if(debugMsg)
+ printf("alias: %s\n", aliases[0]);
+
+ //int flags = 0;
+ int pf = jack_port_flags(port);
+ // If Jack port can send data to us...
+ //if(pf & JackPortIsOutput)
+ // Mark as input capable.
+ // flags |= 2;
+ // If Jack port can receive data from us...
+ //if(pf & JackPortIsInput)
+ // Mark as output capable.
+ // flags |= 1;
+
+ //JackPort jp(0, QString(buffer), flags);
+ //portList.append(jp);
+
+ QString name(namep);
+
+ if(JACK_DEBUG)
+ printf("JackAudioDevice::graphChanged %s\n", name.toLatin1());
+
+ for(iMidiDevice imd = midiDevices.begin(); imd != midiDevices.end(); ++imd)
+ {
+ // Is it a Jack midi device?
+ MidiJackDevice* mjd = dynamic_cast<MidiJackDevice*>(*imd);
+ if(!mjd)
+ continue;
+
+ //if(dev->name() != name)
+ // continue;
+
+ // Is this port the one created for the Jack midi device?
+ if(!mjd->clientJackPort() || (mjd->clientJackPort() != port))
+ continue;
+
+ jack_port_t* devport = jack_port_by_name(_client, mjd->name().toLatin1());
+ if(!devport)
+ continue;
+
+ int ofl = mjd->openFlags();
+
+ if(JACK_DEBUG)
+ printf("JackAudioDevice::graphChanged found MidiJackDevice:%s\n", mjd->name().toLatin1());
+
+ // Note docs say it can't be both input and output. src, dest
+ // If Jack port can receive data from us and we actually want to...
+ if((pf & JackPortIsOutput) && (ofl & 1))
+ {
+ if(JACK_DEBUG)
+ printf("JackAudioDevice::graphChanged connecting MusE output\n");
+ audioDevice->connect(port, devport);
+ }
+ else
+ // If Jack port can send data to us and we actually want it...
+ if((pf & JackPortIsInput) && (ofl & 2))
+ {
+ if(JACK_DEBUG)
+ printf("JackAudioDevice::graphChanged connecting MusE input\n");
+ audioDevice->connect(devport, port);
+ }
+
+ break;
+ }
+ }
+
+ if(ports)
+ free(ports);
+
+ */
+}
+//---------------------------------------------------------
+// client_registration_callback
+//---------------------------------------------------------
+
+static void client_registration_callback(const char *name, int isRegister, void*)
+ {
+ if (debugMsg || JACK_DEBUG)
+ printf("JACK: client registration changed:%s register:%d\n", name, isRegister);
+ }
+
+//---------------------------------------------------------
+// port_connect_callback
+//---------------------------------------------------------
+
+static void port_connect_callback(jack_port_id_t a, jack_port_id_t b, int isConnect, void*)
+ {
+ if (debugMsg || JACK_DEBUG)
+ {
+ //jack_port_t* ap = jack_port_by_id(_client, a);
+ //jack_port_t* bp = jack_port_by_id(_client, b);
+ //printf("JACK: port connections changed: A:%d:%s B:%d:%s isConnect:%d\n", a, jack_port_name(ap), b, jack_port_name(bp), isConnect);
+ printf("JACK: port connections changed: A:%d B:%d isConnect:%d\n", a, b, isConnect);
+ }
+ }
+
+//---------------------------------------------------------
+// graph_callback
+// this is called from jack when the connections
+// changed
+//---------------------------------------------------------
+
+static int graph_callback(void*)
+ {
+ if (JACK_DEBUG)
+ printf("graph_callback()\n");
+ // we cannot call JackAudioDevice::graphChanged() from this
+ // context, so we send a message to the gui thread which in turn
+ // calls graphChanged()
+ audio->sendMsgToGui('C');
+ if (debugMsg)
+ printf("JACK: graph changed\n");
+ return 0;
+ }
+
+//---------------------------------------------------------
+// JackAudioDevice::graphChanged
+// this is called from song in gui context triggered
+// by graph_callback()
+//---------------------------------------------------------
+
+void JackAudioDevice::graphChanged()
+{
+ if (JACK_DEBUG)
+ printf("graphChanged()\n");
+ if(!checkJackClient(_client)) return;
+ InputList* il = song->inputs();
+ for (iAudioInput ii = il->begin(); ii != il->end(); ++ii) {
+ AudioInput* it = *ii;
+ int channels = it->channels();
+ for (int channel = 0; channel < channels; ++channel) {
+ jack_port_t* port = (jack_port_t*)(it->jackPort(channel));
+ if (port == 0)
+ continue;
+ const char** ports = jack_port_get_all_connections(_client, port);
+ RouteList* rl = it->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();
+ QByteArray ba = name.toLatin1();
+ const char* portName = ba.constData();
+ //printf("portname=%s\n", portName);
+ 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, channel, Route::JACK_ROUTE),
+ Route(it, channel)
+ );
+ 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();
+ QByteArray ba = name.toLatin1();
+ const char* portName = ba.constData();
+ if (strcmp(*pn, portName) == 0) {
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ audio->msgAddRoute1(
+ //Route(*pn, false, channel),
+ Route(*pn, false, channel, Route::JACK_ROUTE),
+ Route(it, channel)
+ );
+ }
+ ++pn;
+ }
+
+ // p3.3.37
+ //delete ports;
+ free(ports);
+
+ ports = NULL;
+ }
+ }
+ }
+ 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 = (jack_port_t*)(it->jackPort(channel));
+ if (port == 0)
+ continue;
+ const char** ports = jack_port_get_all_connections(_client, port);
+ RouteList* rl = it->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();
+ QByteArray ba = name.toLatin1();
+ const char* portName = ba.constData();
+ 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(portName, false, channel)
+ Route(portName, false, channel, 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();
+ QByteArray ba = name.toLatin1();
+ const char* portName = ba.constData();
+ if (strcmp(*pn, portName) == 0) {
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ audio->msgAddRoute1(
+ Route(it, channel),
+ //Route(*pn, false, channel)
+ Route(*pn, false, channel, Route::JACK_ROUTE)
+ );
+ }
+ ++pn;
+ }
+
+ // p3.3.37
+ //delete ports;
+ free(ports);
+
+ ports = NULL;
+ }
+ }
+ }
+
+ for (iMidiDevice ii = midiDevices.begin(); ii != midiDevices.end(); ++ii)
+ {
+ MidiDevice* md = *ii;
+ if(md->deviceType() != MidiDevice::JACK_MIDI)
+ continue;
+
+ //MidiJackDevice* mjd = dynamic_cast<MidiJackDevice*>(*ii);
+ //if(!mjd)
+ // continue;
+ //for (int channel = 0; channel < channels; ++channel)
+ //{
+
+ // 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
+ //---------------------------------------
+
+ if(md->rwFlags() & 1) // Writable
+ {
+ // p3.3.55
+ jack_port_t* port = (jack_port_t*)md->outClientPort();
+ if(port != 0)
+ {
+ //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
+ QByteArray ba = name.toLatin1();
+ const char* portName = ba.constData();
+ 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();
+ QByteArray ba = name.toLatin1();
+ const char* portName = ba.constData();
+ 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);
+ }
+ }
+ }
+
+
+ //------------------------
+ // Inputs
+ //------------------------
+
+ if(md->rwFlags() & 2) // Readable
+ {
+ // p3.3.55
+ jack_port_t* port = (jack_port_t*)md->inClientPort();
+ if(port != 0)
+ {
+ //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();
+ QByteArray ba = name.toLatin1();
+ const char* portName = ba.constData();
+ 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();
+ QByteArray ba = name.toLatin1();
+ const char* portName = ba.constData();
+ 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);
+ }
+ }
+ }
+
+ // p3.3.55 Removed.
+ //if(ports)
+ // Done with ports. Free them.
+ //delete ports;
+ // free(ports);
+ //ports = NULL;
+ }
+}
+
+//static int xrun_callback(void*)
+// {
+// printf("JACK: xrun\n");
+// return 0;
+// }
+
+//---------------------------------------------------------
+// register
+//---------------------------------------------------------
+
+void JackAudioDevice::registerClient()
+ {
+ if (JACK_DEBUG)
+ printf("registerClient()\n");
+ if(!checkJackClient(_client)) return;
+ jack_set_process_callback(_client, processAudio, 0);
+ jack_set_sync_callback(_client, processSync, 0);
+ // FIXME: FIXME:
+ // 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.
+ // 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);
+ jack_set_sample_rate_callback(_client, srate_callback, 0);
+ jack_set_port_registration_callback(_client, registration_callback, 0);
+ // p3.3.37
+ jack_set_client_registration_callback(_client, client_registration_callback, 0);
+ jack_set_port_connect_callback(_client, port_connect_callback, 0);
+
+ jack_set_graph_order_callback(_client, graph_callback, 0);
+// jack_set_xrun_callback(client, xrun_callback, 0);
+ jack_set_freewheel_callback (_client, freewheel_callback, 0);
+ }
+
+//---------------------------------------------------------
+// registerInPort
+//---------------------------------------------------------
+
+//void* JackAudioDevice::registerInPort(const char* name)
+void* JackAudioDevice::registerInPort(const char* name, bool midi)
+ {
+ if (JACK_DEBUG)
+ printf("registerInPort()\n");
+ if(!checkJackClient(_client)) return NULL;
+ const char* type = midi ? JACK_DEFAULT_MIDI_TYPE : JACK_DEFAULT_AUDIO_TYPE;
+ //void* p = jack_port_register(_client, name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0);
+ void* p = jack_port_register(_client, name, type, JackPortIsInput, 0);
+// printf("JACK: registerInPort: <%s> %p\n", name, p);
+ return p;
+ }
+
+//---------------------------------------------------------
+// registerOutPort
+//---------------------------------------------------------
+
+//void* JackAudioDevice::registerOutPort(const char* name)
+void* JackAudioDevice::registerOutPort(const char* name, bool midi)
+ {
+ if (JACK_DEBUG)
+ printf("registerOutPort()\n");
+ if(!checkJackClient(_client)) return NULL;
+ const char* type = midi ? JACK_DEFAULT_MIDI_TYPE : JACK_DEFAULT_AUDIO_TYPE;
+ //void* p = jack_port_register(_client, name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
+ void* p = jack_port_register(_client, name, type, JackPortIsOutput, 0);
+// printf("JACK: registerOutPort: <%s> %p\n", name, p);
+ return p;
+ }
+
+//---------------------------------------------------------
+// exitJackAudio
+//---------------------------------------------------------
+
+void exitJackAudio()
+ {
+ if (JACK_DEBUG)
+ printf("exitJackAudio()\n");
+ if (jackAudio)
+ delete jackAudio;
+
+ if (JACK_DEBUG)
+ printf("exitJackAudio() after delete jackAudio\n");
+
+ // Added by Tim. p3.3.14
+ audioDevice = NULL;
+
+ }
+
+//---------------------------------------------------------
+// connect
+//---------------------------------------------------------
+
+void JackAudioDevice::connect(void* src, void* dst)
+{
+ if (JACK_DEBUG)
+ printf("JackAudioDevice::connect()\n");
+ if(!checkJackClient(_client)) 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) {
+ fprintf(stderr, "JackAudio::connect: unknown jack ports\n");
+ return;
+ }
+ int err = jack_connect(_client, sn, dn);
+ //if (jack_connect(_client, sn, dn)) {
+ if (err) {
+ fprintf(stderr, "jack connect <%s>%p - <%s>%p failed with err:%d\n",
+ sn, src, dn, dst, err);
+ }
+ else
+ if (JACK_DEBUG)
+ {
+ fprintf(stderr, "jack connect <%s>%p - <%s>%p succeeded\n",
+ sn, src, dn, dst);
+ }
+}
+
+//---------------------------------------------------------
+// disconnect
+//---------------------------------------------------------
+
+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) {
+ fprintf(stderr, "JackAudio::disconnect: unknown jack ports\n");
+ return;
+ }
+ int err = jack_disconnect(_client, sn, dn);
+ //if (jack_disconnect(_client, sn, dn)) {
+ if (err) {
+ fprintf(stderr, "jack disconnect <%s> - <%s> failed with err:%d\n",
+ sn, dn, err);
+ }
+ else
+ if (JACK_DEBUG)
+ {
+ fprintf(stderr, "jack disconnect <%s> - <%s> succeeded\n",
+ sn, dn);
+ }
+}
+
+//---------------------------------------------------------
+// start
+//---------------------------------------------------------
+
+//void JackAudioDevice::start()
+void JackAudioDevice::start(int /*priority*/)
+ {
+ if (JACK_DEBUG)
+ printf("JackAudioDevice::start()\n");
+ if(!checkJackClient(_client)) return;
+
+ doSetuid();
+
+ if (jack_activate(_client)) {
+ undoSetuid(); // p3.3.51
+ fprintf (stderr, "JACK: cannot activate client\n");
+ exit(-1);
+ }
+ /* connect the ports. Note: you can't do this before
+ the client is activated, because we can't allow
+ connections to be made to clients that aren't
+ running.
+ */
+
+ InputList* il = song->inputs();
+ for (iAudioInput i = il->begin(); i != il->end(); ++i) {
+ AudioInput* ai = *i;
+ int channel = ai->channels();
+ for (int ch = 0; ch < channel; ++ch) {
+ RouteList* rl = ai->inRoutes();
+ void* port = ai->jackPort(ch);
+ for (iRoute ir = rl->begin(); ir != rl->end(); ++ir) {
+ if (ir->channel == ch)
+ connect(ir->jackPort, port);
+ }
+ }
+ }
+ OutputList* ol = song->outputs();
+ for (iAudioOutput i = ol->begin(); i != ol->end(); ++i) {
+ AudioOutput* ai = *i;
+ int channel = ai->channels();
+ for (int ch = 0; ch < channel; ++ch) {
+ RouteList* rl = ai->outRoutes();
+ void* port = ai->jackPort(ch);
+ for (iRoute r = rl->begin(); r != rl->end(); ++r) {
+ if (r->channel == ch) {
+ connect(port, r->jackPort);
+ }
+ }
+ }
+ }
+
+ // p3.3.37
+ // Connect the Jack midi client ports to device ports.
+ connectJackMidiPorts();
+
+ undoSetuid();
+
+ //MUSE_DEBUG("JackAudioDevice::start()\n");
+ fflush(stdin);
+ //JackAudioDevice::jackStarted=true;
+ }
+
+//---------------------------------------------------------
+// stop
+//---------------------------------------------------------
+
+void JackAudioDevice::stop()
+ {
+ if (JACK_DEBUG)
+ printf("JackAudioDevice::stop()\n");
+ if(!checkJackClient(_client)) return;
+ if (jack_deactivate(_client)) {
+ fprintf (stderr, "cannot deactivate client\n");
+ }
+ //JackAudioDevice::jackStarted=false;
+ }
+
+//---------------------------------------------------------
+// transportQuery
+//---------------------------------------------------------
+
+jack_transport_state_t JackAudioDevice::transportQuery(jack_position_t* pos)
+{
+ if (JACK_DEBUG)
+ printf("JackAudioDevice::transportQuery pos:%d\n", (unsigned int)pos->frame);
+
+ // TODO: Compose and return a state if MusE is disengaged from Jack transport.
+
+ return jack_transport_query(_client, pos);
+}
+
+//---------------------------------------------------------
+// getCurFrame
+//---------------------------------------------------------
+
+unsigned int JackAudioDevice::getCurFrame()
+{
+ if (JACK_DEBUG)
+ printf("JackAudioDevice::getCurFrame pos.frame:%d\n", pos.frame);
+
+ if(!useJackTransport.value())
+ return (unsigned int)dummyPos;
+
+ return pos.frame;
+}
+
+//---------------------------------------------------------
+// framePos
+//---------------------------------------------------------
+
+int JackAudioDevice::framePos() const
+ {
+ //if(!useJackTransport.value())
+ //{
+ // if (JACK_DEBUG)
+ // printf("JackAudioDevice::framePos dummyPos:%d\n", dummyPos);
+ // return dummyPos;
+ //}
+
+ if(!checkJackClient(_client)) return 0;
+ jack_nframes_t n = jack_frame_time(_client);
+
+ //if (JACK_DEBUG)
+ // printf("JackAudioDevice::framePos jack frame:%d\n", (int)n);
+
+ return (int)n;
+ }
+
+#if 0
+//---------------------------------------------------------
+// framesSinceCycleStart
+//---------------------------------------------------------
+
+int JackAudioDevice::framesSinceCycleStart() const
+ {
+ jack_nframes_t n = jack_frames_since_cycle_start(client);
+ return (int)n;
+ }
+
+//---------------------------------------------------------
+// framesDelay
+// TODO
+//---------------------------------------------------------
+
+int JackAudioDevice::frameDelay() const
+ {
+ jack_nframes_t n = (segmentSize * (segmentCount-1)) - jack_frames_since_cycle_start(client);
+ return (int)n;
+ }
+#endif
+
+//---------------------------------------------------------
+// outputPorts
+//---------------------------------------------------------
+
+std::list<QString> JackAudioDevice::outputPorts(bool midi, int aliases)
+ {
+ if (JACK_DEBUG)
+ printf("JackAudioDevice::outputPorts()\n");
+ std::list<QString> clientList;
+ if(!checkJackClient(_client)) return clientList;
+ QString qname;
+ const char* type = midi ? JACK_DEFAULT_MIDI_TYPE : JACK_DEFAULT_AUDIO_TYPE;
+ const char** ports = jack_get_ports(_client, 0, type, JackPortIsOutput);
+ for (const char** p = ports; p && *p; ++p) {
+ jack_port_t* port = jack_port_by_name(_client, *p);
+ //int flags = jack_port_flags(port);
+ //if (!(flags & JackPortIsOutput))
+ // continue;
+ //char buffer[128];
+
+ int nsz = jack_port_name_size();
+ char buffer[nsz];
+
+ strncpy(buffer, *p, nsz);
+ //if (strncmp(buffer, "MusE", 4) == 0)
+ //{
+ // if(debugMsg)
+ // printf("JackAudioDevice::outputPorts ignoring own MusE port: %s\n", *p);
+ // continue;
+ //}
+
+ // Ignore our own client ports.
+ if(jack_port_is_mine(_client, port))
+ {
+ if(debugMsg)
+ printf("JackAudioDevice::outputPorts ignoring own port: %s\n", *p);
+ continue;
+ }
+
+ // p3.3.38
+ if((aliases == 0) || (aliases == 1))
+ {
+ //char a1[nsz];
+ char a2[nsz];
+ char* al[2];
+ //aliases[0] = a1;
+ al[0] = buffer;
+ al[1] = a2;
+ int na = jack_port_get_aliases(port, al);
+ int a = aliases;
+ if(a >= na)
+ {
+ a = na;
+ if(a > 0)
+ a--;
+ }
+ qname = QString(al[a]);
+ }
+ else
+ qname = QString(buffer);
+
+ //clientList.push_back(QString(buffer));
+ clientList.push_back(qname);
+ }
+
+ // p3.3.37
+ if(ports)
+ free(ports);
+
+ return clientList;
+ }
+
+//---------------------------------------------------------
+// inputPorts
+//---------------------------------------------------------
+
+std::list<QString> JackAudioDevice::inputPorts(bool midi, int aliases)
+ {
+ if (JACK_DEBUG)
+ printf("JackAudioDevice::inputPorts()\n");
+ std::list<QString> clientList;
+ if(!checkJackClient(_client)) return clientList;
+ QString qname;
+ const char* type = midi ? JACK_DEFAULT_MIDI_TYPE : JACK_DEFAULT_AUDIO_TYPE;
+ const char** ports = jack_get_ports(_client, 0, type, JackPortIsInput);
+ for (const char** p = ports; p && *p; ++p) {
+ jack_port_t* port = jack_port_by_name(_client, *p);
+ //int flags = jack_port_flags(port);
+ //if (!(flags & JackPortIsInput))
+ // continue;
+ //char buffer[128];
+
+ int nsz = jack_port_name_size();
+ char buffer[nsz];
+
+ strncpy(buffer, *p, nsz);
+ //if (strncmp(buffer, "MusE", 4) == 0)
+ //{
+ // if(debugMsg)
+ // printf("JackAudioDevice::inputPorts ignoring own MusE port: %s\n", *p);
+ // continue;
+ //}
+
+ // Ignore our own client ports.
+ if(jack_port_is_mine(_client, port))
+ {
+ if(debugMsg)
+ printf("JackAudioDevice::inputPorts ignoring own port: %s\n", *p);
+ continue;
+ }
+
+ // p3.3.38
+ if((aliases == 0) || (aliases == 1))
+ {
+ //char a1[nsz];
+ char a2[nsz];
+ char* al[2];
+ //aliases[0] = a1;
+ al[0] = buffer;
+ al[1] = a2;
+ int na = jack_port_get_aliases(port, al);
+ int a = aliases;
+ if(a >= na)
+ {
+ a = na;
+ if(a > 0)
+ a--;
+ }
+ qname = QString(al[a]);
+ }
+ else
+ qname = QString(buffer);
+
+ //clientList.push_back(QString(buffer));
+ clientList.push_back(qname);
+ }
+
+ // p3.3.37
+ if(ports)
+ free(ports);
+
+ return clientList;
+ }
+
+//---------------------------------------------------------
+// portName
+//---------------------------------------------------------
+
+QString JackAudioDevice::portName(void* port)
+ {
+ if (JACK_DEBUG)
+ printf("JackAudioDevice::portName(\n");
+ if(!checkJackClient(_client)) return "";
+ if (!port)
+ return "";
+
+ QString s(jack_port_name((jack_port_t*)port));
+ //printf("Jack::portName %p %s\n", port, s.toLatin1());
+ return s;
+ }
+
+//---------------------------------------------------------
+// unregisterPort
+//---------------------------------------------------------
+
+void JackAudioDevice::unregisterPort(void* p)
+ {
+ if (JACK_DEBUG)
+ printf("JackAudioDevice::unregisterPort(\n");
+ if(!checkJackClient(_client)) return;
+// printf("JACK: unregister Port\n");
+ jack_port_unregister(_client, (jack_port_t*)p);
+ }
+
+//---------------------------------------------------------
+// getState
+//---------------------------------------------------------
+
+int JackAudioDevice::getState()
+ {
+ // If we're not using Jack's transport, just return current state.
+ if(!useJackTransport.value())
+ {
+ //pos.valid = jack_position_bits_t(0);
+ //pos.frame = audio->pos().frame();
+ //return audio->getState();
+ //if (JACK_DEBUG)
+ // printf("JackAudioDevice::getState dummyState:%d\n", dummyState);
+ return dummyState;
+ }
+
+ //if (JACK_DEBUG)
+ // printf("JackAudioDevice::getState ()\n");
+ if(!checkJackClient(_client)) return 0;
+ transportState = jack_transport_query(_client, &pos);
+ //if (JACK_DEBUG)
+ // printf("JackAudioDevice::getState transportState:%d\n", transportState);
+
+ switch (transportState) {
+ case JackTransportStopped:
+ return Audio::STOP;
+ case JackTransportLooping:
+ case JackTransportRolling:
+ return Audio::PLAY;
+ case JackTransportStarting:
+ //printf("JackAudioDevice::getState JackTransportStarting\n");
+
+ return Audio::START_PLAY;
+ //case JackTransportNetStarting:
+ // FIXME: Quick and dirty hack to support both Jack-1 and Jack-2
+ // Really need a config check of version...
+ case 4:
+ //printf("JackAudioDevice::getState JackTransportNetStarting\n");
+
+ return Audio::START_PLAY;
+ break;
+ default:
+ return Audio::STOP;
+ }
+ }
+
+//---------------------------------------------------------
+// setFreewheel
+//---------------------------------------------------------
+
+void JackAudioDevice::setFreewheel(bool f)
+ {
+ if (JACK_DEBUG)
+ printf("JackAudioDevice::setFreewheel(\n");
+ if(!checkJackClient(_client)) return;
+// printf("JACK: setFreewheel %d\n", f);
+ jack_set_freewheel(_client, f);
+ }
+
+//---------------------------------------------------------
+// dummySync
+//---------------------------------------------------------
+
+bool JackAudioDevice::dummySync(int state)
+{
+ // Roughly segment time length.
+ //timespec ts = { 0, (1000000000 * segmentSize) / sampleRate }; // In nanoseconds.
+ unsigned int sl = (1000000 * segmentSize) / sampleRate; // In microseconds.
+
+ double ct = curTime();
+ // Wait for a default maximum of 5 seconds.
+ // Similar to how Jack is supposed to wait a default of 2 seconds for slow clients.
+ // TODO: Make this timeout a 'settings' option so it can be applied both to Jack and here.
+ while((curTime() - ct) < 5.0)
+ {
+ // Is MusE audio ready to roll?
+ if(audio->sync(state, dummyPos))
+ return true;
+
+ // Not ready. Wait a 'segment', try again...
+ //nanosleep(&ts, NULL);
+ usleep(sl); // usleep is supposed to be obsolete!
+ }
+
+ //if(JACK_DEBUG)
+ printf("JackAudioDevice::dummySync Sync timeout - audio not ready!\n");
+
+ return false;
+}
+
+//---------------------------------------------------------
+// startTransport
+//---------------------------------------------------------
+
+void JackAudioDevice::startTransport()
+ {
+ if (JACK_DEBUG)
+ printf("JackAudioDevice::startTransport()\n");
+
+ // If we're not using Jack's transport, just pass PLAY and current frame along
+ // as if processSync was called.
+ if(!useJackTransport.value())
+ {
+ //dummyState = Audio::START_PLAY;
+
+ // Is MusE audio ready to roll?
+ //if(dummySync(dummyState))
+ if(dummySync(Audio::START_PLAY))
+ {
+ // MusE audio is ready to roll. Let's play.
+ dummyState = Audio::PLAY;
+ return;
+ }
+
+ // Ready or not, we gotta roll. Similar to how Jack is supposed to roll anyway.
+ dummyState = Audio::PLAY;
+ return;
+ }
+
+ if(!checkJackClient(_client)) return;
+// printf("JACK: startTransport\n");
+ jack_transport_start(_client);
+ }
+
+//---------------------------------------------------------
+// stopTransport
+//---------------------------------------------------------
+
+void JackAudioDevice::stopTransport()
+ {
+ if (JACK_DEBUG)
+ printf("JackAudioDevice::stopTransport()\n");
+
+ dummyState = Audio::STOP;
+
+ if(!useJackTransport.value())
+ {
+ //dummyState = Audio::STOP;
+ return;
+ }
+
+ if(!checkJackClient(_client)) return;
+ if (transportState != JackTransportStopped) {
+ // printf("JACK: stopTransport\n");
+ jack_transport_stop(_client);
+ transportState=JackTransportStopped;
+ }
+ }
+
+//---------------------------------------------------------
+// seekTransport
+//---------------------------------------------------------
+
+void JackAudioDevice::seekTransport(unsigned frame)
+ {
+ if (JACK_DEBUG)
+ printf("JackAudioDevice::seekTransport() frame:%d\n", frame);
+
+ dummyPos = frame;
+ if(!useJackTransport.value())
+ {
+ // If we're not using Jack's transport, just pass the current state and new frame along
+ // as if processSync was called.
+ //dummyPos = frame;
+ int tempState = dummyState;
+ //dummyState = Audio::START_PLAY;
+
+ // Is MusE audio ready yet?
+ //audio->sync(dummyState, dummyPos);
+ //if(dummySync(dummyState))
+ if(dummySync(Audio::START_PLAY))
+ {
+ dummyState = tempState;
+ return;
+ }
+
+ // Not ready, resume previous state anyway.
+ // FIXME: Observed: Seek during play: Jack transport STOPs on timeout.
+ // 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;
+ }
+
+ if(!checkJackClient(_client)) return;
+// printf("JACK: seekTransport %d\n", frame);
+ jack_transport_locate(_client, frame);
+ }
+
+//---------------------------------------------------------
+// seekTransport
+//---------------------------------------------------------
+
+void JackAudioDevice::seekTransport(const Pos &p)
+ {
+ if (JACK_DEBUG)
+ printf("JackAudioDevice::seekTransport() frame:%d\n", p.frame());
+
+ dummyPos = p.frame();
+ if(!useJackTransport.value())
+ {
+ // If we're not using Jack's transport, just pass the current state and new frame along
+ // as if processSync was called.
+ //dummyPos = p.frame();
+ int tempState = dummyState;
+ //dummyState = Audio::START_PLAY;
+
+ // Is MusE audio ready yet?
+ //audio->sync(dummyState, dummyPos);
+ //if(dummySync(dummyState))
+ if(dummySync(Audio::START_PLAY))
+ {
+ dummyState = tempState;
+ return;
+ }
+
+ // Not ready, resume previous state anyway.
+ // FIXME: See fixme in other seekTransport...
+ //dummyState = tempState;
+ dummyState = Audio::STOP;
+ return;
+ }
+
+ if(!checkJackClient(_client)) return;
+
+ /*
+ jack_position_t jp;
+ jp.valid = JackPositionBBT;
+ p.mbt(&jp.bar, &jp.beat, &jp.tick);
+ jp.bar++;
+ jp.beat++;
+ jp.bar_start_tick = Pos(jp.bar, 0, 0).tick();
+ //
+ // dummy:
+ //
+ jp.beats_per_bar = 4;
+ jp.beat_type = 4;
+ jp.ticks_per_beat = 384;
+ int tempo = tempomap.tempo(p.tick());
+ jp.beats_per_minute = (60000000.0 / tempo) * tempomap.globalTempo()/100.0;
+
+ jack_transport_reposition(_client, &jp);
+ */
+ jack_transport_locate(_client, p.frame());
+ }
+
+//---------------------------------------------------------
+// findPort
+//---------------------------------------------------------
+
+void* JackAudioDevice::findPort(const char* name)
+ {
+ if (JACK_DEBUG)
+ printf("JackAudioDevice::findPort(\n");
+ if(!checkJackClient(_client)) return NULL;
+ void* p = jack_port_by_name(_client, name);
+// printf("Jack::findPort <%s>, %p\n", name, p);
+ return p;
+ }
+
+//---------------------------------------------------------
+// setMaster
+//---------------------------------------------------------
+
+int JackAudioDevice::setMaster(bool f)
+{
+ if (JACK_DEBUG)
+ printf("JackAudioDevice::setMaster val:%d\n", f);
+ if(!checkJackClient(_client))
+ return 0;
+
+ int r = 0;
+ if(f)
+ {
+ if(useJackTransport.value())
+ {
+ // Make Muse the Jack timebase master. Do it unconditionally (second param = 0).
+ r = jack_set_timebase_callback(_client, 0, (JackTimebaseCallback) timebase_callback, 0);
+ if(debugMsg || JACK_DEBUG)
+ {
+ if(r)
+ printf("JackAudioDevice::setMaster jack_set_timebase_callback failed: result:%d\n", r);
+ }
+ }
+ else
+ {
+ r = 1;
+ printf("JackAudioDevice::setMaster cannot set master because useJackTransport is false\n");
+ }
+ }
+ else
+ {
+ r = jack_release_timebase(_client);
+ if(debugMsg || JACK_DEBUG)
+ {
+ if(r)
+ printf("JackAudioDevice::setMaster jack_release_timebase failed: result:%d\n", r);
+ }
+ }
+ return r;
+}
+
+//---------------------------------------------------------
+// scanMidiPorts
+//---------------------------------------------------------
+
+void JackAudioDevice::scanMidiPorts()
+{
+ if(debugMsg)
+ printf("JackAudioDevice::scanMidiPorts:\n");
+
+/*
+ const char* type = JACK_DEFAULT_MIDI_TYPE;
+ const char** ports = jack_get_ports(_client, 0, type, 0);
+
+ std::set<std::string> names;
+ for (const char** p = ports; p && *p; ++p)
+ {
+ jack_port_t* port = jack_port_by_name(_client, *p);
+ if(!port)
+ continue;
+ // Ignore our own client ports.
+ if(jack_port_is_mine(_client, port))
+ {
+ if(debugMsg)
+ printf(" ignoring own port: %s\n", *p);
+ continue;
+ }
+
+ int nsz = jack_port_name_size();
+ char buffer[nsz];
+ strncpy(buffer, *p, nsz);
+ // Ignore the MusE Jack port.
+ //if(strncmp(buffer, "MusE", 4) == 0)
+ // continue;
+
+ if(debugMsg)
+ printf(" found port: %s ", buffer);
+
+ // If there are aliases for this port, use the first one - much better for identifying.
+ //char a1[nsz];
+ char a2[nsz];
+ char* aliases[2];
+ //aliases[0] = a1;
+ aliases[0] = buffer;
+ aliases[1] = a2;
+ // To disable aliases, just rem this line.
+ jack_port_get_aliases(port, aliases);
+ //int na = jack_port_get_aliases(port, aliases);
+ //char* namep = (na >= 1) ? aliases[0] : buffer;
+ //char* namep = aliases[0];
+ //names.insert(std::string(*p));
+ if(debugMsg)
+ printf("alias: %s\n", aliases[0]);
+
+ names.insert(std::string(aliases[0]));
+ }
+ if(ports)
+ free(ports);
+
+ std::list<MidiDevice*> to_del;
+ for(iMidiDevice imd = midiDevices.begin(); imd != midiDevices.end(); ++imd)
+ {
+ // Only Jack midi devices.
+ if(dynamic_cast<MidiJackDevice*>(*imd) == 0)
+ continue;
+ if(names.find(std::string((*imd)->name().toLatin1())) == names.end())
+ to_del.push_back(*imd);
+ }
+
+ for(std::list<MidiDevice*>::iterator imd = to_del.begin(); imd != to_del.end(); ++imd)
+ {
+ if(debugMsg)
+ printf(" removing port device:%s\n", (*imd)->name().toLatin1());
+ midiDevices.remove(*imd);
+ // This will close (and unregister) the client port.
+ delete (*imd);
+ }
+
+ //for (const char** p = ports; p && *p; ++p)
+ for(std::set<std::string>::iterator is = names.begin(); is != names.end(); ++is)
+ {
+ //jack_port_t* port = jack_port_by_name(_client, *p);
+ jack_port_t* port = jack_port_by_name(_client, is->c_str());
+ if(!port)
+ continue;
+*/
+
+ /*
+ int nsz = jack_port_name_size();
+ char buffer[nsz];
+ //strncpy(buffer, *p, nsz);
+ strncpy(buffer, is->c_str(), nsz);
+ // Ignore the MusE Jack port.
+ //if(strncmp(buffer, "MusE", 4) == 0)
+ // continue;
+
+ // If there are aliases for this port, use the first one - much better for identifying.
+ //char a1[nsz];
+ char a2[nsz];
+ char* aliases[2];
+ //aliases[0] = a1;
+ aliases[0] = buffer;
+ aliases[1] = a2;
+ // To disable aliases, just rem this line.
+ jack_port_get_aliases(port, aliases);
+ //int na = jack_port_get_aliases(port, aliases);
+ //char* namep = (na >= 1) ? aliases[0] : buffer;
+ char* namep = aliases[0];
+ QString qname(namep);
+ */
+
+/*
+ QString qname(is->c_str());
+
+ // Port already exists?
+ if(midiDevices.find(qname))
+ continue;
+
+ int flags = 0;
+ int pf = jack_port_flags(port);
+ // If Jack port can send data to us...
+ if(pf & JackPortIsOutput)
+ // Mark as input capable.
+ flags |= 2;
+ // If Jack port can receive data from us...
+ if(pf & JackPortIsInput)
+ // Mark as output capable.
+ flags |= 1;
+
+ //JackPort jp(0, QString(buffer), flags);
+ //portList.append(jp);
+
+ if(debugMsg)
+ printf(" adding port device:%s\n", qname.toLatin1());
+
+ MidiJackDevice* dev = new MidiJackDevice(0, qname);
+ dev->setrwFlags(flags);
+ midiDevices.add(dev);
+ }
+*/
+}
+
diff --git a/attic/muse2-oom/muse2/muse/driver/jackaudio.h b/attic/muse2-oom/muse2/muse/driver/jackaudio.h
new file mode 100644
index 00000000..d3132efe
--- /dev/null
+++ b/attic/muse2-oom/muse2/muse/driver/jackaudio.h
@@ -0,0 +1,97 @@
+//=========================================================
+// MusE
+// Linux Music Editor
+// $Id: jackaudio.h,v 1.20.2.4 2009/12/20 05:00:35 terminator356 Exp $
+// (C) Copyright 2002 Werner Schweer (ws@seh.de)
+//=========================================================
+
+#ifndef __JACKAUDIO_H__
+#define __JACKAUDIO_H__
+
+#include <jack/jack.h>
+#include "audiodev.h"
+
+class MidiPlayEvent;
+
+//---------------------------------------------------------
+// JackAudioDevice
+//---------------------------------------------------------
+bool checkAudioDevice();
+
+class JackAudioDevice : public AudioDevice {
+
+ jack_client_t* _client;
+ double sampleTime;
+ int samplePos;
+ jack_transport_state_t transportState;
+ jack_position_t pos;
+ char jackRegisteredName[16];
+ int dummyState;
+ int dummyPos;
+ // Free-running frame counter incremented always in process.
+ jack_nframes_t _frameCounter;
+
+ static int processAudio(jack_nframes_t frames, void*);
+
+ public:
+ JackAudioDevice(jack_client_t* cl, char * jack_id_string);
+ virtual ~JackAudioDevice();
+ virtual void nullify_client() { _client = 0; }
+
+ virtual inline int deviceType() { return JACK_AUDIO; } // p3.3.52
+
+ void scanMidiPorts();
+
+ //virtual void start();
+ virtual void start(int);
+ virtual void stop ();
+ virtual bool dummySync(int state); // Artificial sync when not using Jack transport.
+
+ virtual int framePos() const;
+ virtual unsigned frameTime() const { return _frameCounter; }
+
+ virtual float* getBuffer(void* port, unsigned long nframes) {
+ return (float*)jack_port_get_buffer((jack_port_t*)port, nframes);
+ }
+
+ virtual std::list<QString> outputPorts(bool midi = false, int aliases = -1);
+ virtual std::list<QString> inputPorts(bool midi = false, int aliases = -1);
+
+ virtual void registerClient();
+ virtual const char* clientName() { return jackRegisteredName; }
+
+ //virtual void* registerOutPort(const char* name);
+ //virtual void* registerInPort(const char* name);
+ virtual void* registerOutPort(const char* /*name*/, bool /*midi*/);
+ virtual void* registerInPort(const char* /*name*/, bool /*midi*/);
+
+ //virtual char* getJackName();
+
+ virtual void unregisterPort(void*);
+ virtual void connect(void*, void*);
+ virtual void disconnect(void*, void*);
+ virtual int connections(void* clientPort) { return jack_port_connected((jack_port_t*)clientPort); }
+ virtual void setPortName(void* p, const char* n) { jack_port_set_name((jack_port_t*)p, n); }
+ virtual void* findPort(const char* name);
+ virtual QString portName(void* port);
+ virtual int getState();
+ virtual unsigned int getCurFrame();
+ virtual bool isRealtime() { return jack_is_realtime(_client); }
+ virtual int realtimePriority() const;
+ virtual void startTransport();
+ virtual void stopTransport();
+ virtual void seekTransport(unsigned frame);
+ virtual void seekTransport(const Pos &p);
+ virtual void setFreewheel(bool f);
+ jack_transport_state_t transportQuery(jack_position_t* pos);
+ void graphChanged();
+ void registrationChanged();
+ void connectJackMidiPorts();
+
+ virtual int setMaster(bool f);
+
+ //static bool jackStarted;
+ };
+
+#endif
+
diff --git a/attic/muse2-oom/muse2/muse/driver/jackmidi.cpp b/attic/muse2-oom/muse2/muse/driver/jackmidi.cpp
new file mode 100644
index 00000000..d401c7e1
--- /dev/null
+++ b/attic/muse2-oom/muse2/muse/driver/jackmidi.cpp
@@ -0,0 +1,1732 @@
+//=========================================================
+// 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;
+ }
+ }
+}
+
+*/
diff --git a/attic/muse2-oom/muse2/muse/driver/jackmidi.h b/attic/muse2-oom/muse2/muse/driver/jackmidi.h
new file mode 100644
index 00000000..f7b5eb94
--- /dev/null
+++ b/attic/muse2-oom/muse2/muse/driver/jackmidi.h
@@ -0,0 +1,168 @@
+//=========================================================
+// MusE
+// Linux Music Editor
+// $Id: jackmidi.h,v 1.1.1.1 2010/01/27 09:06:43 terminator356 Exp $
+// (C) Copyright 1999-2010 Werner Schweer (ws@seh.de)
+//=========================================================
+
+#ifndef __JACKMIDI_H__
+#define __JACKMIDI_H__
+
+//#include <config.h>
+
+#include <map>
+
+#include <jack/jack.h>
+#include <jack/midiport.h>
+
+#include "mididev.h"
+#include "route.h"
+
+class QString;
+class MidiFifo;
+class MidiRecordEvent;
+class MidiPlayEvent;
+//class RouteList;
+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
+
+// 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
+
+/* jack-midi channels */
+//#define JACK_MIDI_CHANNELS 32
+
+/* jack-midi buffer size */
+//#define JACK_MIDI_BUFFER_SIZE 32
+
+/*
+typedef struct {
+ int give;
+ int take;
+ // 32 parallel midi events, where each event contains three
+ // midi-bytes and one busy-byte
+ char buffer[4 * JACK_MIDI_BUFFER_SIZE];
+} muse_jack_midi_buffer;
+*/
+
+/*
+struct JackMidiPort
+{
+ jack_port_t* _jackPort;
+ QString _name;
+ int _flags; // 1 = writable, 2 = readable - do not mix
+ JackMidiPort(jack_port_t* jp, const QString& s, int f)
+ {
+ _jackPort = jp;
+ _name = QString(s);
+ _flags = f;
+ }
+};
+
+typedef std::map<jack_port_t*, JackMidiPort, std::less<jack_port_t*> >::iterator iJackMidiPort;
+typedef std::map<jack_port_t*, JackMidiPort, std::less<jack_port_t*> >::const_iterator ciJackMidiPort;
+
+class JackMidiPortList : public std::map<jack_port_t*, JackMidiPort, std::less<jack_port_t*> >
+{
+ private:
+ static int _nextOutIdNum;
+ static int _nextInIdNum;
+
+ public:
+ JackMidiPortList();
+ ~JackMidiPortList();
+ iJackMidiPort createClientPort(int flags);
+ bool removeClientPort(jack_port_t* port);
+};
+
+extern JackMidiPortList jackMidiClientPorts;
+*/
+
+//---------------------------------------------------------
+// MidiJackDevice
+//---------------------------------------------------------
+
+class MidiJackDevice : public MidiDevice {
+ public:
+ //int adr;
+
+ private:
+ // fifo for midi events sent from gui
+ // direct to midi port:
+ MidiFifo eventFifo;
+
+ //static int _nextOutIdNum;
+ //static int _nextInIdNum;
+
+ //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();
+ virtual void close();
+ //bool putEvent(int*);
+
+ void processEvent(const MidiPlayEvent&);
+ // Port is not midi port, it is the port(s) created for MusE.
+ bool queueEvent(const MidiPlayEvent&);
+
+ virtual bool putMidiEvent(const MidiPlayEvent&);
+ //bool sendEvent(const MidiPlayEvent&);
+
+ void eventReceived(jack_midi_event_t*);
+
+ public:
+ //MidiJackDevice() {} // p3.3.55 Removed.
+ //MidiJackDevice(const int&, const QString& name);
+
+ //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; }
+
+ virtual void setName(const QString&);
+
+ virtual void processMidi();
+ virtual ~MidiJackDevice();
+ //virtual int selectRfd();
+ //virtual int selectWfd();
+ //virtual void processInput();
+
+ virtual void recordEvent(MidiRecordEvent&);
+
+ virtual bool putEvent(const MidiPlayEvent&);
+ virtual void collectMidiEvents();
+
+ //virtual jack_port_t* jackPort() { return _jackport; }
+ //virtual jack_port_t* clientJackPort() { return _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(); }
+ virtual void writeRouting(int, Xml&) const;
+ };
+
+extern bool initMidiJack();
+//extern int jackSelectRfd();
+//extern int jackSelectWfd();
+//extern void jackProcessMidiInput();
+//extern void jackScanMidiPorts();
+
+#endif
+
+
diff --git a/attic/muse2-oom/muse2/muse/driver/rtctimer.cpp b/attic/muse2-oom/muse2/muse/driver/rtctimer.cpp
new file mode 100644
index 00000000..1a3cefa6
--- /dev/null
+++ b/attic/muse2-oom/muse2/muse/driver/rtctimer.cpp
@@ -0,0 +1,155 @@
+ //=========================================================
+ // MusE
+ // Linux Music Editor
+ // $Id: rtctimer.cpp,v 1.1.2.11 2009/03/09 02:05:18 terminator356 Exp $
+ //
+ // Most code moved from midiseq.cpp by Werner Schweer.
+ //
+ // (C) Copyright 2004 Robert Jonsson (rj@spamatica.se)
+ // (C) Copyright -2004 Werner Schweer (werner@seh.de)
+ //=========================================================
+
+#include <linux/version.h>
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
+#include <linux/spinlock.h>
+#include <linux/mc146818rtc.h>
+#else
+#include <linux/rtc.h>
+#endif
+#include <stdio.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <poll.h>
+
+
+#include "rtctimer.h"
+#include "globals.h"
+#include "gconfig.h"
+
+
+RtcTimer::RtcTimer()
+ {
+ timerFd = -1;
+ }
+
+RtcTimer::~RtcTimer()
+ {
+ if (timerFd != -1)
+ close(timerFd);
+ }
+
+signed int RtcTimer::initTimer()
+ {
+ if(TIMER_DEBUG)
+ printf("RtcTimer::initTimer()\n");
+ if (timerFd != -1) {
+ fprintf(stderr,"RtcTimer::initTimer(): called on initialised timer!\n");
+ return -1;
+ }
+ doSetuid();
+
+ timerFd = ::open("/dev/rtc", O_RDONLY);
+ if (timerFd == -1) {
+ fprintf(stderr, "fatal error: open /dev/rtc failed: %s\n", strerror(errno));
+ fprintf(stderr, "hint: check if 'rtc' kernel module is loaded, or used by something else\n");
+ undoSetuid();
+ return timerFd;
+ }
+ if (!setTimerFreq(config.rtcTicks)) {
+ // unable to set timer frequency
+ return -1;
+ }
+ // check if timer really works, start and stop it once.
+ if (!startTimer()) {
+ return -1;
+ }
+ if (!stopTimer()) {
+ return -1;
+ }
+ return timerFd;
+ }
+
+unsigned int RtcTimer::setTimerResolution(unsigned int resolution)
+ {
+ if(TIMER_DEBUG)
+ printf("RtcTimer::setTimerResolution(%d)\n",resolution);
+ /* The RTC can take power-of-two frequencies from 2 to 8196 Hz.
+ * It doesn't really have a resolution as such.
+ */
+ return 0;
+ }
+
+unsigned int RtcTimer::setTimerFreq(unsigned int freq)
+ {
+ int rc = ioctl(timerFd, RTC_IRQP_SET, freq);
+ if (rc == -1) {
+ fprintf(stderr, "RtcTimer::setTimerFreq(): cannot set tick on /dev/rtc: %s\n",
+ strerror(errno));
+ fprintf(stderr, " precise timer not available\n");
+ return 0;
+ }
+ return freq;
+ }
+
+unsigned int RtcTimer::getTimerResolution()
+ {
+ /* The RTC doesn't really work with a set resolution as such.
+ * Not sure how this fits into things yet.
+ */
+ return 0;
+ }
+
+unsigned int RtcTimer::getTimerFreq()
+ {
+ unsigned int freq;
+ int rv = ioctl(timerFd, RTC_IRQP_READ, &freq);
+ if (rv < 1)
+ return 0;
+ return freq;
+ }
+
+bool RtcTimer::startTimer()
+ {
+ if(TIMER_DEBUG)
+ printf("RtcTimer::startTimer()\n");
+ if (timerFd == -1) {
+ fprintf(stderr, "RtcTimer::startTimer(): no timer open to start!\n");
+ return false;
+ }
+ if (ioctl(timerFd, RTC_PIE_ON, 0) == -1) {
+ perror("MidiThread: start: RTC_PIE_ON failed");
+ undoSetuid();
+ return false;
+ }
+ return true;
+ }
+
+bool RtcTimer::stopTimer()
+ {
+ if(TIMER_DEBUG)
+ printf("RtcTimer::stopTimer\n");
+ if (timerFd != -1) {
+ ioctl(timerFd, RTC_PIE_OFF, 0);
+ }
+ else {
+ fprintf(stderr,"RtcTimer::stopTimer(): no RTC to stop!\n");
+ return false;
+ }
+ return true;
+ }
+
+unsigned int RtcTimer::getTimerTicks(bool /*printTicks*/)// prevent compiler warning: unused parameter
+ {
+ if(TIMER_DEBUG)
+ printf("getTimerTicks()\n");
+ unsigned long int nn;
+ if (timerFd==-1) {
+ fprintf(stderr,"RtcTimer::getTimerTicks(): no RTC open to read!\n");
+ return 0;
+ }
+ if (read(timerFd, &nn, sizeof(unsigned long)) != sizeof(unsigned long)) {
+ fprintf(stderr,"RtcTimer::getTimerTicks(): error reading RTC\n");
+ return 0;
+ }
+ return nn;
+ }
diff --git a/attic/muse2-oom/muse2/muse/driver/rtctimer.h b/attic/muse2-oom/muse2/muse/driver/rtctimer.h
new file mode 100644
index 00000000..fa58b032
--- /dev/null
+++ b/attic/muse2-oom/muse2/muse/driver/rtctimer.h
@@ -0,0 +1,44 @@
+ //=========================================================
+ // MusE
+ // Linux Music Editor
+ // $Id: rtctimer.h,v 1.1.2.3 2005/08/21 18:11:28 spamatica Exp $
+ //
+ // Most code moved from midiseq.cpp
+ //
+ // (C) Copyright 2004 Robert Jonsson (rj@spamatica.se)
+ // (C) Copyright -2004 Werner Schweer (werner@seh.de)
+ //=========================================================
+
+#ifndef __RTCTIMER_H__
+#define __RTCTIMER_H__
+
+#include "timerdev.h"
+
+
+//---------------------------------------------------------
+// AlsaTimer
+//---------------------------------------------------------
+
+class RtcTimer : public Timer{
+
+
+ public:
+ RtcTimer();
+ virtual ~RtcTimer();
+
+ virtual signed int initTimer();
+ virtual unsigned int setTimerResolution(unsigned int resolution);
+ virtual unsigned int getTimerResolution();
+ virtual unsigned int setTimerFreq(unsigned int tick);
+ virtual unsigned int getTimerFreq();
+
+ virtual bool startTimer();
+ virtual bool stopTimer();
+ virtual unsigned int getTimerTicks(bool printTicks=false);
+
+ private:
+ int timerFd;
+
+};
+
+#endif //__ALSATIMER_H__
diff --git a/attic/muse2-oom/muse2/muse/driver/timerdev.h b/attic/muse2-oom/muse2/muse/driver/timerdev.h
new file mode 100644
index 00000000..944bc213
--- /dev/null
+++ b/attic/muse2-oom/muse2/muse/driver/timerdev.h
@@ -0,0 +1,41 @@
+//=========================================================
+// MusE
+// Linux Music Editor
+// $Id: timerdev.h,v 1.1.2.3 2005/08/21 18:11:28 spamatica Exp $
+//
+// Plenty of code borrowed from timer.c example in
+// alsalib 1.0.7
+//
+// (C) Copyright 2004 Robert Jonsson (rj@spamatica.se)
+//=========================================================
+
+#ifndef __TIMERDEV_H__
+#define __TIMERDEV_H__
+
+#include "alsa/asoundlib.h"
+
+#define TIMER_DEBUG 0
+
+//---------------------------------------------------------
+// AlsaTimer
+//---------------------------------------------------------
+
+class Timer {
+
+ public:
+ Timer() {};
+ virtual ~Timer() {};
+
+ virtual signed int initTimer() = 0;
+ virtual unsigned int setTimerResolution(unsigned int resolution) = 0;
+ virtual unsigned int getTimerResolution() = 0;
+ virtual unsigned int setTimerFreq(unsigned int freq) = 0;
+ virtual unsigned int getTimerFreq() = 0;
+
+ virtual bool startTimer() = 0;
+ virtual bool stopTimer() = 0;
+ virtual unsigned int getTimerTicks(bool printTicks = false) = 0;
+
+};
+
+#endif //__ALSATIMER_H__