summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--muse/ChangeLog10
-rw-r--r--muse/muse/arranger/pcanvas.cpp2
-rw-r--r--muse/muse/audio.cpp6
-rw-r--r--muse/muse/driver/audiodev.h2
-rw-r--r--muse/muse/driver/dummyaudio.cpp4
-rw-r--r--muse/muse/driver/jack.cpp289
-rw-r--r--muse/muse/driver/jackaudio.h5
-rw-r--r--muse/muse/driver/jackmidi.cpp570
-rw-r--r--muse/muse/driver/jackmidi.h48
-rw-r--r--muse/muse/dssihost.cpp1
-rw-r--r--muse/muse/midi.cpp83
-rw-r--r--muse/muse/midictrl.h1
-rw-r--r--muse/muse/mididev.cpp2
-rw-r--r--muse/muse/midiseq.cpp14
14 files changed, 817 insertions, 220 deletions
diff --git a/muse/ChangeLog b/muse/ChangeLog
index e4d60b27..a44ae038 100644
--- a/muse/ChangeLog
+++ b/muse/ChangeLog
@@ -1,3 +1,13 @@
+13.02.2010
+ * Fixed: Jack midi output should now be frame-accurate, support variable length events (like sysex),
+ and most controllers should work. (T356)
+ - TODO: No record yet. Just playback.
+ - TODO: I have code in place for multiple device listing (like ALSA) with auto-connect,
+ instead of single 'jackmidi' device, but it doesn't seem to want to actually connect.
+ Simply enable the #define JACK_MIDI_SHOW_MULTIPLE_DEVICES in driver/jackmidi.h
+ and it will magically switch. Shows port names as their alias #1 (with a rem'able line to
+ revert to non-alias names - to be made configurable later). I swear it was working,
+ then intermittent, then not at all. Hmm...
06.02.2010
* Fixed: MusE hanging on close, with Jack driver. (T356)
- Unregister Jack midi ports on destruction of JackAudioDevice.
diff --git a/muse/muse/arranger/pcanvas.cpp b/muse/muse/arranger/pcanvas.cpp
index 4cb3db1a..080bf9bf 100644
--- a/muse/muse/arranger/pcanvas.cpp
+++ b/muse/muse/arranger/pcanvas.cpp
@@ -1446,7 +1446,6 @@ void PartCanvas::drawItem(QPainter& p, const CItem* item, const QRect& rect)
p.setPen(darkGray);
EventList* events = mp->events();
iEvent ito(events->lower_bound(to));
- // Added by Tim. P3.3.6
//printf("PartCanvas::drawItem pTick:%d from:%d to:%d part len:%d\n", pTick, from, to, part->lenTick());
for (iEvent i = events->begin(); i != ito; ++i) {
@@ -1455,7 +1454,6 @@ void PartCanvas::drawItem(QPainter& p, const CItem* item, const QRect& rect)
if (t > (to + pTick))
{
- // Added by Tim. P3.3.6
printf("PartCanvas::drawItem t:%d > to:%d + pTick:%d i->first:%d\n", t, to, pTick, i->first);
break;
diff --git a/muse/muse/audio.cpp b/muse/muse/audio.cpp
index 1fb53bc8..d8c12331 100644
--- a/muse/muse/audio.cpp
+++ b/muse/muse/audio.cpp
@@ -462,7 +462,7 @@ void Audio::process(unsigned frames)
}
- // P3.3.25
+ // p3.3.25
if(extSyncFlag.value())
{
nextTickPos = curTickPos + midiExtSyncTicks;
@@ -1204,7 +1204,7 @@ void Audio::stopRolling()
mp->sendMMCStop();
//mp->sendSysex(mmcPos, sizeof(mmcPos));
- // P3.3.31
+ // p3.3.31
// Added check of option send continue not start.
// Hmm, is this required? Seems to make other devices unhappy.
/*
@@ -1223,7 +1223,7 @@ void Audio::stopRolling()
// "set song position pointer"
mp->sendStop();
- // P3.3.31
+ // p3.3.31
// Added check of option send continue not start.
// Hmm, is this required? Seems to make other devices unhappy.
/*
diff --git a/muse/muse/driver/audiodev.h b/muse/muse/driver/audiodev.h
index 437b1eee..e0ddb3b9 100644
--- a/muse/muse/driver/audiodev.h
+++ b/muse/muse/driver/audiodev.h
@@ -57,8 +57,6 @@ class AudioDevice {
virtual void setFreewheel(bool f) = 0;
virtual void graphChanged() {}
virtual int setMaster(bool f) = 0;
-
- virtual bool putEvent(int port, const MidiPlayEvent&) = 0;
};
#endif
diff --git a/muse/muse/driver/dummyaudio.cpp b/muse/muse/driver/dummyaudio.cpp
index bd95647d..e22c44da 100644
--- a/muse/muse/driver/dummyaudio.cpp
+++ b/muse/muse/driver/dummyaudio.cpp
@@ -167,8 +167,6 @@ class DummyAudioDevice : public AudioDevice {
}
virtual void setFreewheel(bool) {}
void setRealTime() { realtimeFlag = true; }
-
- virtual bool putEvent(int /*port*/, const MidiPlayEvent&) { return true;};
};
DummyAudioDevice* dummyAudio = 0;
@@ -242,7 +240,7 @@ static void* dummyLoop(void* ptr)
{
//unsigned int tickRate = 25;
- // P3.3.30
+ // p3.3.30
//sampleRate = 25600;
sampleRate = config.dummyAudioSampleRate;
//segmentSize = dummyFrames;
diff --git a/muse/muse/driver/jack.cpp b/muse/muse/driver/jack.cpp
index 4cd471b0..ee15c4b3 100644
--- a/muse/muse/driver/jack.cpp
+++ b/muse/muse/driver/jack.cpp
@@ -43,18 +43,35 @@ extern void undoSetuid();
#include <fst.h>
#endif
-extern int jackmidi_pi[2];
-extern int jackmidi_po[2];
+//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];
+//muse_jack_midi_buffer jack_midi_out_data[JACK_MIDI_CHANNELS];
+//muse_jack_midi_buffer jack_midi_in_data[JACK_MIDI_CHANNELS];
-// p3.3.32
//jack_port_t *jackMidiInPort = 0;
//jack_port_t *jackMidiOutPort = 0;
+/*
+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;
+*/
JackAudioDevice* jackAudio;
@@ -140,6 +157,7 @@ print_triplet(unsigned char *data)
fprintf(stderr, "%x,%x,%x", a, b, c);
}
+/*
void handle_jack_midi_in_events(jack_nframes_t frames)
{
char buf = 0;
@@ -191,18 +209,18 @@ void handle_jack_midi_out_events(jack_nframes_t frames)
//for(i = 0; i < JACK_MIDI_CHANNELS; i++){
for(i = 0; i < JACK_MIDI_CHANNELS; ++i){
- /* jack-midi-clear any old events */
+ // 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 */
+ // 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 */
+ // 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){
@@ -213,25 +231,23 @@ void handle_jack_midi_out_events(jack_nframes_t frames)
}
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];
+ // 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;
- }
- }
- */
+ // 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)
@@ -258,14 +274,15 @@ void handle_jack_midi_out_events(jack_nframes_t frames)
}
}
}
+*/
//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);
+/// handle_jack_midi_in_events(frames);
+/// handle_jack_midi_out_events(frames);
// if (JACK_DEBUG)
// printf("processAudio - >>>>\n");
@@ -346,7 +363,7 @@ static void timebase_callback(jack_transport_state_t /* state */,
// p3.3.29
//printf("Jack timebase_callback pos->frame:%u audio->tickPos:%d song->cpos:%d\n", pos->frame, audio->tickPos(), song->cpos());
- // P3.3.27
+ // 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 !
@@ -558,56 +575,40 @@ bool initJackAudio()
}
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);
+ // 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");
- }
-
- /*
- 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;
@@ -1451,6 +1452,10 @@ void* JackAudioDevice::findPort(const char* name)
return p;
}
+//---------------------------------------------------------
+// setMaster
+//---------------------------------------------------------
+
int JackAudioDevice::setMaster(bool f)
{
if (JACK_DEBUG)
@@ -1489,90 +1494,60 @@ int JackAudioDevice::setMaster(bool f)
return r;
}
-
//---------------------------------------------------------
-// putEvent
-// return true if successful
+// scanMidiPorts
//---------------------------------------------------------
-//void JackAudioDevice::putEvent(Port port, const MidiEvent& e)
-bool JackAudioDevice::putEvent(int port, const MidiPlayEvent& e)
- {
- if(port >= JACK_MIDI_CHANNELS)
- return false;
-
- //if (midiOutputTrace) {
- // printf("MidiOut<%s>: jackMidi: ", portName(port).toLatin1().data());
- // e.dump();
- // }
-
- //void* pb = jack_port_get_buffer(port.jackPort(), segmentSize);
- void* pb = jack_port_get_buffer(midi_port_out[port], segmentSize);
-
- int ft = e.time() - _frameCounter;
-
- if (ft < 0)
- ft = 0;
- if (ft >= (int)segmentSize) {
- printf("JackAudio::putEvent: time out of range %d(seg=%d)\n", ft, segmentSize);
- if (ft > (int)segmentSize)
- ft = segmentSize - 1;
- }
- switch(e.type()) {
- case ME_NOTEON:
- case ME_NOTEOFF:
- case ME_POLYAFTER:
- case ME_CONTROLLER:
- case ME_PITCHBEND:
- {
- unsigned char* p = jack_midi_event_reserve(pb, ft, 3);
- if (p == 0) {
- fprintf(stderr, "JackMidi: buffer overflow, event lost\n");
- return false;
- }
- p[0] = e.type() | e.channel();
- p[1] = e.dataA();
- p[2] = e.dataB();
- }
- break;
-
- case ME_PROGRAM:
- case ME_AFTERTOUCH:
- {
- unsigned char* p = jack_midi_event_reserve(pb, ft, 2);
- if (p == 0) {
- fprintf(stderr, "JackMidi: buffer overflow, event lost\n");
- return false;
- }
- p[0] = e.type() | e.channel();
- p[1] = e.dataA();
- }
- break;
- case ME_SYSEX:
- {
- const unsigned char* data = e.data();
- int len = e.len();
- unsigned char* p = jack_midi_event_reserve(pb, ft, len+2);
- if (p == 0) {
- fprintf(stderr, "JackMidi: buffer overflow, event lost\n");
- return 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("JackMidi: event type %x not supported\n", e.type());
- return false;
- break;
- }
-
- return true;
- }
-
+void JackAudioDevice::scanMidiPorts()
+{
+ #ifdef JACK_MIDI_SHOW_MULTIPLE_DEVICES
+
+ 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;
+ 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 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];
+
+ 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);
+
+ MidiJackDevice* dev = new MidiJackDevice(0, QString(namep));
+ dev->setrwFlags(flags);
+ midiDevices.add(dev);
+ }
+ #endif
+
+}
diff --git a/muse/muse/driver/jackaudio.h b/muse/muse/driver/jackaudio.h
index 76753eec..e8a74ac1 100644
--- a/muse/muse/driver/jackaudio.h
+++ b/muse/muse/driver/jackaudio.h
@@ -38,6 +38,8 @@ class JackAudioDevice : public AudioDevice {
virtual ~JackAudioDevice();
virtual void nullify_client() { _client = 0; }
+ void scanMidiPorts();
+
//virtual void start();
virtual void start(int);
virtual void stop ();
@@ -79,9 +81,6 @@ class JackAudioDevice : public AudioDevice {
void graphChanged();
virtual int setMaster(bool f);
- // Port is not midi port, it is the port(s) created for MusE.
- virtual bool putEvent(int port, const MidiPlayEvent&);
-
//static bool jackStarted;
};
diff --git a/muse/muse/driver/jackmidi.cpp b/muse/muse/driver/jackmidi.cpp
index 52a696f0..cc400fd9 100644
--- a/muse/muse/driver/jackmidi.cpp
+++ b/muse/muse/driver/jackmidi.cpp
@@ -5,6 +5,7 @@
// (C) Copyright 1999-2010 Werner Schweer (ws@seh.de)
//=========================================================
+#include <qstring.h>
#include <stdio.h>
#include <jack/jack.h>
@@ -20,12 +21,18 @@
#include "../audio.h"
#include "mpevent.h"
//#include "sync.h"
+#include "audiodev.h"
+
+// Turn on debug messages.
+//#define JACK_MIDI_DEBUG
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 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;
@@ -43,6 +50,7 @@ MidiJackDevice::MidiJackDevice(const int& a, const QString& n)
init();
}
+/*
//---------------------------------------------------------
// select[RW]fd
//---------------------------------------------------------
@@ -56,6 +64,7 @@ int MidiJackDevice::selectWfd()
{
return jackmidi_po[0];
}
+*/
//---------------------------------------------------------
// open
@@ -63,10 +72,40 @@ int MidiJackDevice::selectWfd()
QString MidiJackDevice::open()
{
- _readEnable = true;
+ #ifdef JACK_MIDI_SHOW_MULTIPLE_DEVICES
+ _openFlags &= _rwFlags; // restrict to available bits
+
+ //jack_port_t* jp = jack_port_by_name(_client, name().latin1());
+ jack_port_t* jp = (jack_port_t*)audioDevice->findPort(name().latin1());
+
+ if(!jp)
+ {
+ printf("MidiJackDevice::open: Jack midi port %s not found!\n", name().latin1());
+ 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))
+ {
+ // src, dest
+ //TODO: Having trouble here, may need to coordinate or move to graphChanged.
+ audioDevice->connect(midi_port_out[0], jp);
+ _writeEnable = true;
+ }
+
+ // If Jack port can send data to us and we actually want it...
+ if((pf & JackPortIsOutput) && (_openFlags & 2))
+ {
+ audioDevice->connect(jp, midi_port_in[0]);
+ _readEnable = true;
+ }
+ #else
_writeEnable = true;
-
-
+ _readEnable = true;
+ #endif
+
return QString("OK");
}
@@ -76,8 +115,39 @@ QString MidiJackDevice::open()
void MidiJackDevice::close()
{
- _readEnable = false;
+ #ifdef JACK_MIDI_SHOW_MULTIPLE_DEVICES
+
+ //jack_port_t* jp = jack_port_by_name(_client, name().latin1());
+ jack_port_t* jp = (jack_port_t*)audioDevice->findPort(name().latin1());
+
+ if(!jp)
+ {
+ printf("MidiJackDevice::close: Jack midi port %s not found!\n", name().latin1());
+ 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().latin1()))
+ {
+ // src, dest
+ audioDevice->disconnect(midi_port_out[0], jp);
+ _writeEnable = false;
+ }
+
+ // 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().latin1()))
+ {
+ audioDevice->disconnect(jp, midi_port_in[0]);
+ _readEnable = false;
+ }
+ #else
_writeEnable = false;
+ _readEnable = false;
+ #endif
}
//---------------------------------------------------------
@@ -88,8 +158,9 @@ void MidiJackDevice::close()
* we return false (indicating OK). Otherwise
* it seems muse will retry forever
*/
-bool MidiJackDevice::putMidiEvent(const MidiPlayEvent& event)
+bool MidiJackDevice::putMidiEvent(const MidiPlayEvent& /*event*/)
{
+ /*
int give, channel = event.channel();
int x;
@@ -146,6 +217,7 @@ bool MidiJackDevice::putMidiEvent(const MidiPlayEvent& event)
}
jack_midi_out_data[channel].give = give;
return false;
+ */
/*
//
@@ -153,6 +225,7 @@ bool MidiJackDevice::putMidiEvent(const MidiPlayEvent& event)
// or select other MusE ports. MusE ALSA midi only creates one port as well.
//
const int museport = 0;
+
if(event.type() == ME_CONTROLLER)
{
int a = event.dataA();
@@ -249,13 +322,11 @@ bool MidiJackDevice::putMidiEvent(const MidiPlayEvent& event)
{
audioDriver->putEvent(museport, event);
}
-
- // Just return OK for now.
- return false;
*/
-
+ return false;
}
+/*
//---------------------------------------------------------
// putEvent
// return false if event is delivered
@@ -266,6 +337,455 @@ bool MidiJackDevice::putEvent(int* event)
int *y; y = event;
return false;
}
+*/
+
+//---------------------------------------------------------
+// queueEvent
+// 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(int port, 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().data());
+ // e.dump();
+ // }
+
+ //if(debugMsg)
+ // printf("MidiJackDevice::queueEvent\n");
+
+
+ //void* pb = jack_port_get_buffer(port.jackPort(), segmentSize);
+ void* pb = jack_port_get_buffer(midi_port_out[port], segmentSize);
+
+ //jack_port_t* jp = (jack_port_t*)audioDevice->findPort(name().latin1());
+ //if(!jp)
+ // printf("MidiJackDevice::queueEvent: Jack midi port %s not found!\n", name().latin1());
+ //void* pb = jack_port_get_buffer(jp ? jp : midi_port_out[port], segmentSize);
+
+ //unsigned frameCounter = ->frameTime();
+ int frameOffset = audio->getFrameOffset();
+ unsigned pos = audio->pos().frame();
+ //int ft = e.time() - _frameCounter;
+ //int ft = e.time() - frameOffset - frameCounter;
+ 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(int museport, const MidiPlayEvent& event)
+{
+ //int frameOffset = audio->getFrameOffset();
+ //unsigned pos = audio->pos().frame();
+
+ int chn = event.channel();
+ unsigned t = event.time();
+
+ // 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_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();
+
+ if(a == CTRL_PITCH)
+ {
+ int v = b + 8192;
+ queueEvent(museport, 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;
+ if (hb != 0xff)
+ queueEvent(museport, MidiPlayEvent(t, port, chn, ME_CONTROLLER, CTRL_HBANK, hb));
+ if (lb != 0xff)
+ queueEvent(museport, MidiPlayEvent(t+1, port, chn, ME_CONTROLLER, CTRL_LBANK, lb));
+ queueEvent(museport, 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(museport, MidiPlayEvent(t, port, ME_SYSEX, sysex, 6));
+ }
+ */
+ else if (a < CTRL_14_OFFSET)
+ { // 7 Bit Controller
+ queueEvent(museport, 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(museport, MidiPlayEvent(t, port, chn, ME_CONTROLLER, ctrlH, dataH));
+ queueEvent(museport, 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(museport, MidiPlayEvent(t, port, chn, ME_CONTROLLER, CTRL_HRPN, ctrlH));
+ queueEvent(museport, MidiPlayEvent(t+1, port, chn, ME_CONTROLLER, CTRL_LRPN, ctrlL));
+ queueEvent(museport, MidiPlayEvent(t+2, port, chn, ME_CONTROLLER, CTRL_HDATA, b));
+ }
+ else if (a < CTRL_RPN14_OFFSET)
+ { // NRPN 7-Bit Controller
+ int ctrlH = (a >> 8) & 0x7f;
+ int ctrlL = a & 0x7f;
+ queueEvent(museport, MidiPlayEvent(t, port, chn, ME_CONTROLLER, CTRL_HNRPN, ctrlH));
+ queueEvent(museport, MidiPlayEvent(t+1, port, chn, ME_CONTROLLER, CTRL_LNRPN, ctrlL));
+ queueEvent(museport, MidiPlayEvent(t+2, port, chn, ME_CONTROLLER, CTRL_HDATA, b));
+ }
+ 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(museport, MidiPlayEvent(t, port, chn, ME_CONTROLLER, CTRL_HRPN, ctrlH));
+ queueEvent(museport, MidiPlayEvent(t+1, port, chn, ME_CONTROLLER, CTRL_LRPN, ctrlL));
+ queueEvent(museport, MidiPlayEvent(t+2, port, chn, ME_CONTROLLER, CTRL_HDATA, dataH));
+ queueEvent(museport, MidiPlayEvent(t+3, port, chn, ME_CONTROLLER, CTRL_LDATA, dataL));
+ }
+ 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(museport, MidiPlayEvent(t, port, chn, ME_CONTROLLER, CTRL_HNRPN, ctrlH));
+ queueEvent(museport, MidiPlayEvent(t+1, port, chn, ME_CONTROLLER, CTRL_LNRPN, ctrlL));
+ queueEvent(museport, MidiPlayEvent(t+2, port, chn, ME_CONTROLLER, CTRL_HDATA, dataH));
+ queueEvent(museport, MidiPlayEvent(t+3, port, chn, ME_CONTROLLER, CTRL_LDATA, dataL));
+ }
+ else
+ {
+ printf("MidiJackDevice::processEvent: unknown controller type 0x%x\n", a);
+ }
+ }
+ else
+ {
+ queueEvent(museport, event);
+ //queueEvent(museport, MidiPlayEvent(t, port, chn, event));
+ }
+}
+
+//---------------------------------------------------------
+// processMidi called from audio process only.
+//---------------------------------------------------------
+
+void MidiJackDevice::processMidi()
+{
+ //
+ // NOTICE: Only one MusE port (port 0) is supported for now ! MusE has no mechanism to create
+ // or select other MusE ports. MusE ALSA midi only creates one port as well.
+ //
+ const int museport = 0;
+ void* port_buf = jack_port_get_buffer(midi_port_out[museport], segmentSize);
+ jack_midi_clear_buffer(port_buf);
+
+ //int frameOffset = audio->getFrameOffset();
+ //unsigned pos = audio->pos().frame();
+ //MPEventList* el = playEvents();
+
+ 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(museport, e);
+ }
+
+ MPEventList* el = playEvents();
+ if(el->empty())
+ return;
+
+ //if(debugMsg)
+ // printf("MidiJackDevice::processMidi\n");
+
+ //int port = midiPort();
+ //MidiPort* mp = port != -1 ? &midiPorts[port] : 0;
+ iMPEvent i = nextPlayEvent();
+ //int tickpos = audio->tickPos();
+ //bool extsync = extSyncFlag.value();
+
+
+ for(; i != el->end(); ++i)
+ {
+ processEvent(museport, *i);
+
+ /*
+ const MidiPlayEvent& event = *i;
+ int chn = event.channel();
+ unsigned t = event.time();
+
+ // No sub-tick playback resolution yet, with external sync.
+ // Just do this for now until we figure out more precise external timings. Tested OK so far !
+ if(extSyncFlag.value())
+ t = frameOffset + pos;
+
+ #ifdef JACK_MIDI_DEBUG
+ printf("MidiJackDevice::processMidi 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_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();
+
+ if(a == CTRL_PITCH)
+ {
+ int v = b + 8192;
+ queueEvent(museport, 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;
+ if (hb != 0xff)
+ queueEvent(museport, MidiPlayEvent(t, port, chn, ME_CONTROLLER, CTRL_HBANK, hb));
+ if (lb != 0xff)
+ queueEvent(museport, MidiPlayEvent(t+1, port, chn, ME_CONTROLLER, CTRL_LBANK, lb));
+ queueEvent(museport, 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(museport, MidiPlayEvent(t, port, ME_SYSEX, sysex, 6));
+ //}
+ else if (a < CTRL_14_OFFSET)
+ { // 7 Bit Controller
+ queueEvent(museport, 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(museport, MidiPlayEvent(t, port, chn, ME_CONTROLLER, ctrlH, dataH));
+ queueEvent(museport, 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(museport, MidiPlayEvent(t, port, chn, ME_CONTROLLER, CTRL_HRPN, ctrlH));
+ queueEvent(museport, MidiPlayEvent(t+1, port, chn, ME_CONTROLLER, CTRL_LRPN, ctrlL));
+ queueEvent(museport, MidiPlayEvent(t+2, port, chn, ME_CONTROLLER, CTRL_HDATA, b));
+ }
+ else if (a < CTRL_RPN14_OFFSET)
+ { // NRPN 7-Bit Controller
+ int ctrlH = (a >> 8) & 0x7f;
+ int ctrlL = a & 0x7f;
+ queueEvent(museport, MidiPlayEvent(t, port, chn, ME_CONTROLLER, CTRL_HNRPN, ctrlH));
+ queueEvent(museport, MidiPlayEvent(t+1, port, chn, ME_CONTROLLER, CTRL_LNRPN, ctrlL));
+ queueEvent(museport, MidiPlayEvent(t+2, port, chn, ME_CONTROLLER, CTRL_HDATA, b));
+ }
+ 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(museport, MidiPlayEvent(t, port, chn, ME_CONTROLLER, CTRL_HRPN, ctrlH));
+ queueEvent(museport, MidiPlayEvent(t+1, port, chn, ME_CONTROLLER, CTRL_LRPN, ctrlL));
+ queueEvent(museport, MidiPlayEvent(t+2, port, chn, ME_CONTROLLER, CTRL_HDATA, dataH));
+ queueEvent(museport, MidiPlayEvent(t+3, port, chn, ME_CONTROLLER, CTRL_LDATA, dataL));
+ }
+ 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(museport, MidiPlayEvent(t, port, chn, ME_CONTROLLER, CTRL_HNRPN, ctrlH));
+ queueEvent(museport, MidiPlayEvent(t+1, port, chn, ME_CONTROLLER, CTRL_LNRPN, ctrlL));
+ queueEvent(museport, MidiPlayEvent(t+2, port, chn, ME_CONTROLLER, CTRL_HDATA, dataH));
+ queueEvent(museport, MidiPlayEvent(t+3, port, chn, ME_CONTROLLER, CTRL_LDATA, dataL));
+ }
+ else
+ {
+ printf("MidiJackDevice::processMidi: unknown controller type 0x%x\n", a);
+ }
+ }
+ else
+ {
+ queueEvent(museport, event);
+ //queueEvent(museport, MidiPlayEvent(t, port, chn, event));
+ }
+ */
+
+ }
+ //md->setNextPlayEvent(i);
+ setNextPlayEvent(i);
+
+}
//---------------------------------------------------------
// initMidiJack
@@ -276,8 +796,9 @@ 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));
+// Removed p3.3.36
+/// 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 */
@@ -290,23 +811,33 @@ bool initMidiJack()
/// fprintf(stderr, "cant create midi-jack output pipe\n");
/// }
+ #ifndef JACK_MIDI_SHOW_MULTIPLE_DEVICES
midiDevices.add(dev);
+ #endif
+
gmdev = dev; /* proclaim the global jack-midi instance */
+ //jackScanMidiPorts();
+
return false;
}
+/*
struct JackPort {
int adr;
- char* name;
+ //char* name;
+ QString name;
int flags;
- JackPort(int a, const char* s, int f) {
+ //JackPort(int a, const char* s, int f) {
+ JackPort(int a, const QString& s, int f) {
adr = a;
- name = strdup(s);
+ //name = strdup(s);
+ name = QString(s);
flags = f;
}
};
+
static std::list<JackPort> portList;
//---------------------------------------------------------
@@ -343,7 +874,9 @@ void jackScanMidiPorts()
}
}
}
+*/
+/*
//---------------------------------------------------------
// processInput
//---------------------------------------------------------
@@ -359,13 +892,13 @@ static void handle_jack_midi_in(int channel)
event.setPort(gmdev->midiPort());
event.setB(0);
- if(t == 0x90){ /* note on */
+ 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 */
+ }else if (t == 0x80){ // note off
fprintf(stderr, "jackProcessMidiInput note-off\n");
event.setChannel(channel);
event.setType(ME_NOTEOFF);
@@ -398,3 +931,4 @@ void MidiJackDevice::processInput()
}
}
+*/ \ No newline at end of file
diff --git a/muse/muse/driver/jackmidi.h b/muse/muse/driver/jackmidi.h
index cf651714..2758ae89 100644
--- a/muse/muse/driver/jackmidi.h
+++ b/muse/muse/driver/jackmidi.h
@@ -11,19 +11,29 @@
#include <config.h>
#include "mididev.h"
+class MidiFifo;
+
+// Turn on to show multiple devices, work in progress,
+// not working fully yet, can't seem to connect...
+/// #define JACK_MIDI_SHOW_MULTIPLE_DEVICES
/* jack-midi channels */
-#define JACK_MIDI_CHANNELS 32
+// Sorry, only one MusE Jack midi port for now.
+//#define JACK_MIDI_CHANNELS 32
+#define JACK_MIDI_CHANNELS 1
+
/* jack-midi buffer size */
-#define JACK_MIDI_BUFFER_SIZE 32
+//#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 */
+ // 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;
+*/
//---------------------------------------------------------
// MidiJackDevice
@@ -34,25 +44,39 @@ class MidiJackDevice : public MidiDevice {
int adr;
private:
+ // fifo for midi events sent from gui
+ // direct to midi port:
+ MidiFifo eventFifo;
+
virtual QString open();
virtual void close();
- bool putEvent(int*);
+ //bool putEvent(int*);
+
+ void processEvent(int /*port*/, const MidiPlayEvent&);
+ // Port is not midi port, it is the port(s) created for MusE.
+ bool queueEvent(int /*port*/, const MidiPlayEvent&);
+ //bool queueEvent(const MidiPlayEvent&);
+
virtual bool putMidiEvent(const MidiPlayEvent&);
+ //bool sendEvent(const MidiPlayEvent&);
public:
MidiJackDevice() {}
MidiJackDevice(const int&, const QString& name);
+ void processMidi();
virtual ~MidiJackDevice() {}
- virtual int selectRfd();
- virtual int selectWfd();
- virtual void processInput();
+ //virtual int selectRfd();
+ //virtual int selectWfd();
+ //virtual void processInput();
+
+ virtual bool putEvent(const MidiPlayEvent&);
};
extern bool initMidiJack();
-extern int jackSelectRfd();
-extern int jackSelectWfd();
-extern void jackProcessMidiInput();
-extern void jackScanMidiPorts();
+//extern int jackSelectRfd();
+//extern int jackSelectWfd();
+//extern void jackProcessMidiInput();
+//extern void jackScanMidiPorts();
#endif
diff --git a/muse/muse/dssihost.cpp b/muse/muse/dssihost.cpp
index f66ea4c3..b9825a83 100644
--- a/muse/muse/dssihost.cpp
+++ b/muse/muse/dssihost.cpp
@@ -28,6 +28,7 @@
#include <signal.h>
#include <dlfcn.h>
#include <stdlib.h>
+#include <sys/stat.h>
//#include <dssi.h>
//#include <alsa/asoundlib.h>
#include <qdir.h>
diff --git a/muse/muse/midi.cpp b/muse/muse/midi.cpp
index ffb40ba2..dc14a3bf 100644
--- a/muse/muse/midi.cpp
+++ b/muse/muse/midi.cpp
@@ -23,6 +23,7 @@
#include "audio.h"
#include "mididev.h"
#include "driver/alsamidi.h"
+#include "driver/jackmidi.h"
#include "wave.h"
#include "synth.h"
#include "sync.h"
@@ -825,7 +826,7 @@ void Audio::collectEvents(MidiTrack* track, unsigned int cts, unsigned int nts)
if (port == defaultPort) {
//printf("Adding event normally: frame=%d port=%d channel=%d pitch=%d velo=%d\n",frame, port, channel, pitch, velo);
- // P3.3.25
+ // p3.3.25
// If syncing to external midi sync, we cannot use the tempo map.
// Therefore we cannot get sub-tick resolution. Just use ticks instead of frames.
if(extSyncFlag.value())
@@ -841,7 +842,7 @@ void Audio::collectEvents(MidiTrack* track, unsigned int cts, unsigned int nts)
MidiDevice* mdAlt = midiPorts[port].device();
if (mdAlt) {
- // P3.3.25
+ // p3.3.25
if(extSyncFlag.value())
mdAlt->playEvents()->add(MidiPlayEvent(tick, port, channel, 0x90, pitch, velo));
else
@@ -878,7 +879,7 @@ void Audio::collectEvents(MidiTrack* track, unsigned int cts, unsigned int nts)
MidiDevice* mdAlt = midiPorts[port].device();
if(mdAlt)
{
- // P3.3.25
+ // p3.3.25
// If syncing to external midi sync, we cannot use the tempo map.
// Therefore we cannot get sub-tick resolution. Just use ticks instead of frames.
if(extSyncFlag.value())
@@ -894,7 +895,7 @@ void Audio::collectEvents(MidiTrack* track, unsigned int cts, unsigned int nts)
break;
}
}
- // P3.3.25
+ // p3.3.25
if(extSyncFlag.value())
playEvents->add(MidiPlayEvent(tick, port, channel, ev));
else
@@ -905,7 +906,7 @@ void Audio::collectEvents(MidiTrack* track, unsigned int cts, unsigned int nts)
default:
- // P3.3.25
+ // p3.3.25
if(extSyncFlag.value())
playEvents->add(MidiPlayEvent(tick, port, channel, ev));
else
@@ -957,7 +958,7 @@ void Audio::processMidi()
iMPEvent nextPlayEvent = metronome->nextPlayEvent();
playEvents->erase(playEvents->begin(), nextPlayEvent);
- // P3.3.25
+ // p3.3.25
bool extsync = extSyncFlag.value();
for (iMidiTrack t = song->midis()->begin(); t != song->midis()->end(); ++t)
@@ -1111,8 +1112,9 @@ void Audio::processMidi()
// p3.3.35
// If ext sync, events are now time-stamped with last tick in MidiDevice::recordEvent().
// TODO: Tested, but record resolution not so good. Switch to wall clock based separate list in MidiDevice.
- if(!extsync)
- event.setTime(event.time() + segmentSize*(segmentCount-1));
+ // p3.3.36
+ //if(!extsync)
+ // event.setTime(event.time() + segmentSize*(segmentCount-1));
// dont't echo controller changes back to software
// synthesizer:
@@ -1233,7 +1235,7 @@ void Audio::processMidi()
break;
MidiPlayEvent ev(*k);
- // P3.3.25
+ // p3.3.25
//int frame = tempomap.tick2frame(k->time()) + frameOffset;
if(extsync)
{
@@ -1245,7 +1247,7 @@ void Audio::processMidi()
ev.setTime(frame);
}
- // P3.3.25
+ // p3.3.25
//ev.setTime(frame);
playEvents->add(ev);
@@ -1279,17 +1281,17 @@ void Audio::processMidi()
else if (state == PRECOUNT) {
isMeasure = (clickno % clicksMeasure) == 0;
}
- // P3.3.25
+ // p3.3.25
//int frame = tempomap.tick2frame(midiClick) + frameOffset;
int evtime = extsync ? midiClick : tempomap.tick2frame(midiClick) + frameOffset;
- // P3.3.25
+ // p3.3.25
//MidiPlayEvent ev(frame, clickPort, clickChan, ME_NOTEON,
MidiPlayEvent ev(evtime, clickPort, clickChan, ME_NOTEON,
beatClickNote, beatClickVelo);
if (md) {
- // P3.3.25
+ // p3.3.25
//MidiPlayEvent ev(frame, clickPort, clickChan, ME_NOTEON,
MidiPlayEvent ev(evtime, clickPort, clickChan, ME_NOTEON,
beatClickNote, beatClickVelo);
@@ -1301,7 +1303,7 @@ void Audio::processMidi()
playEvents->add(ev);
}
if (audioClickFlag) {
- // P3.3.25
+ // p3.3.25
//MidiPlayEvent ev1(frame, 0, 0, ME_NOTEON, 0, 0);
MidiPlayEvent ev1(evtime, 0, 0, ME_NOTEON, 0, 0);
@@ -1310,7 +1312,7 @@ void Audio::processMidi()
}
if (md) {
ev.setB(0);
- // P3.3.25
+ // p3.3.25
// Removed. Why was this here?
//frame = tempomap.tick2frame(midiClick+20) + frameOffset;
//
@@ -1355,6 +1357,57 @@ void Audio::processMidi()
stuckNotes->clear();
}
}
+
+
+ // p3.3.36
+ //int tickpos = audio->tickPos();
+ //bool extsync = extSyncFlag.value();
+ //
+ // Special for Jack midi devices: Play all Jack midi events up to curFrame.
+ //
+ for(iMidiDevice id = midiDevices.begin(); id != midiDevices.end(); ++id)
+ {
+ MidiDevice* md = *id;
+ // Is it a Jack midi device?
+ MidiJackDevice* mjd = dynamic_cast<MidiJackDevice*>(md);
+ if(!mjd)
+ continue;
+
+ mjd->processMidi();
+
+ /*
+ int port = md->midiPort();
+ MidiPort* mp = port != -1 ? &midiPorts[port] : 0;
+ MPEventList* el = md->playEvents();
+ if (el->empty())
+ continue;
+ iMPEvent i = md->nextPlayEvent();
+ for(; i != el->end(); ++i)
+ {
+ // If syncing to external midi sync, we cannot use the tempo map.
+ // Therefore we cannot get sub-tick resolution. Just use ticks instead of frames.
+ //if(i->time() > curFrame)
+ if(i->time() > (extsync ? tickpos : curFrame))
+ {
+ //printf(" curT %d frame %d\n", i->time(), curFrame);
+ break; // skip this event
+ }
+
+ if(mp)
+ {
+ if(mp->sendEvent(*i))
+ break;
+ }
+ else
+ {
+ if(md->putEvent(*i))
+ break;
+ }
+ }
+ md->setNextPlayEvent(i);
+ */
+ }
+
midiBusy=false;
}
diff --git a/muse/muse/midictrl.h b/muse/muse/midictrl.h
index eb4c06bd..45e4255b 100644
--- a/muse/muse/midictrl.h
+++ b/muse/muse/midictrl.h
@@ -69,6 +69,7 @@ const int CTRL_RPN_OFFSET = 0x20000;
const int CTRL_NRPN_OFFSET = 0x30000;
const int CTRL_RPN14_OFFSET = 0x50000;
const int CTRL_NRPN14_OFFSET = 0x60000;
+const int CTRL_NONE_OFFSET = 0x70000;
class Xml;
class Part;
diff --git a/muse/muse/mididev.cpp b/muse/muse/mididev.cpp
index 7d02cc74..4d9f425c 100644
--- a/muse/muse/mididev.cpp
+++ b/muse/muse/mididev.cpp
@@ -166,6 +166,8 @@ void MidiDevice::recordEvent(MidiRecordEvent& event)
//event.setTime(audio->timestamp());
event.setTime(extSyncFlag.value() ? lastExtMidiSyncTick : audio->timestamp());
+ //printf("MidiDevice::recordEvent event time:%d\n", event.time());
+
// Added by Tim. p3.3.8
// By T356. Set the loop number which the event came in at.
diff --git a/muse/muse/midiseq.cpp b/muse/muse/midiseq.cpp
index e10427e5..c597573a 100644
--- a/muse/muse/midiseq.cpp
+++ b/muse/muse/midiseq.cpp
@@ -22,7 +22,7 @@
#include "midictrl.h"
#include "audio.h"
#include "driver/alsamidi.h"
-//#include "driver/jackmidi.h"
+#include "driver/jackmidi.h"
#include "sync.h"
#include "synth.h"
#include "song.h"
@@ -676,7 +676,7 @@ void MidiSeq::processTimerTick()
// printf("Midi Time Code Sync generation not impl.\n");
// }
- // P3.3.25
+ // p3.3.25
int tickpos = audio->tickPos();
bool extsync = extSyncFlag.value();
//
@@ -684,16 +684,20 @@ void MidiSeq::processTimerTick()
//
for (iMidiDevice id = midiDevices.begin(); id != midiDevices.end(); ++id) {
MidiDevice* md = *id;
- int port = md->midiPort();
- MidiPort* mp = port != -1 ? &midiPorts[port] : 0;
+ // Is it a Jack midi device? p3.3.36
+ MidiJackDevice* mjd = dynamic_cast<MidiJackDevice*>(md);
+ if(mjd)
+ continue;
if (md->isSynti()) // syntis are handled by audio thread
continue;
+ int port = md->midiPort();
+ MidiPort* mp = port != -1 ? &midiPorts[port] : 0;
MPEventList* el = md->playEvents();
if (el->empty())
continue;
iMPEvent i = md->nextPlayEvent();
for (; i != el->end(); ++i) {
- // P3.3.25
+ // p3.3.25
// If syncing to external midi sync, we cannot use the tempo map.
// Therefore we cannot get sub-tick resolution. Just use ticks instead of frames.
//if (i->time() > curFrame) {