summaryrefslogtreecommitdiff
path: root/libs/midi++2
diff options
context:
space:
mode:
authorPaul Davis <paul@linuxaudiosystems.com>2009-12-09 03:05:14 +0000
committerPaul Davis <paul@linuxaudiosystems.com>2009-12-09 03:05:14 +0000
commitc38e02285fda1fd7966c9e4ad85994445247e6a6 (patch)
treea5f46d4350b8df3e0a74558169c696cbb837ce7f /libs/midi++2
parent90f95df20707995e267bd624b28980cfd9200bed (diff)
major design changes: use glib event loop for MIDI thread/UI; rework design of BaseUI and AbstractUI; solo & mute are both temporarily broken; OSC control up next; may segfault during exit
git-svn-id: svn://localhost/ardour2/branches/3.0@6328 d708f5d6-7413-0410-9779-e7cbd77b26cf
Diffstat (limited to 'libs/midi++2')
-rw-r--r--libs/midi++2/coremidi_midiport.cc31
-rw-r--r--libs/midi++2/jack_midiport.cc65
-rw-r--r--libs/midi++2/manager.cc7
-rw-r--r--libs/midi++2/midi++/jack.h25
-rw-r--r--libs/midi++2/midi++/manager.h2
-rw-r--r--libs/midi++2/midi++/port.h1
6 files changed, 85 insertions, 46 deletions
diff --git a/libs/midi++2/coremidi_midiport.cc b/libs/midi++2/coremidi_midiport.cc
index e950da2949..4349ea45f4 100644
--- a/libs/midi++2/coremidi_midiport.cc
+++ b/libs/midi++2/coremidi_midiport.cc
@@ -122,22 +122,29 @@ void CoreMidi_MidiPort::read_proc (const MIDIPacketList *pktlist, void *refCon,
if (driver->firstrecv) {
driver->firstrecv = false;
- PBD::notify_gui_about_thread_creation (pthread_self(), "COREMIDI");
+ PBD::notify_gui_about_thread_creation ("gui", pthread_self(), "COREMIDI", 256);
}
for (unsigned int i = 0; i < pktlist->numPackets; ++i) {
-
- driver->bytes_read += packet->length;
-
+
+ driver->bytes_read += packet->length;
+
if (driver->input_parser) {
- driver->input_parser->raw_preparse (*driver->input_parser, packet->data, packet->length);
- for (int i = 0; i < packet->length; i++) {
- driver->input_parser->scanner (packet->data[i]);
- }
- driver->input_parser->raw_postparse (*driver->input_parser, packet->data, packet->length);
- }
-
- packet = MIDIPacketNext(packet);
+ //driver->input_parser->raw_preparse (*driver->input_parser, packet->data, packet->length);
+
+ /* XXX This is technically the wrong timebase, since it is based on
+ host time.
+ */
+ driver->input_parser->set_timestamp (packet->timestamp);
+
+ for (int i = 0; i < packet->length; i++) {
+ driver->input_parser->scanner (packet->data[i]);
+ }
+
+ //driver->input_parser->raw_postparse (*driver->input_parser, packet->data, packet->length);
+ }
+
+ packet = MIDIPacketNext(packet);
}
}
diff --git a/libs/midi++2/jack_midiport.cc b/libs/midi++2/jack_midiport.cc
index ada72f1be6..9b96155b88 100644
--- a/libs/midi++2/jack_midiport.cc
+++ b/libs/midi++2/jack_midiport.cc
@@ -20,9 +20,11 @@
#include <fcntl.h>
#include <cerrno>
#include <cassert>
+#include <cstring>
#include <cstdlib>
#include "pbd/error.h"
+#include "pbd/compose.h"
#include "midi++/types.h"
#include "midi++/jack.h"
@@ -39,11 +41,10 @@ JACK_MidiPort::JACK_MidiPort(const XMLNode& node, jack_client_t* jack_client)
, _jack_input_port(NULL)
, _jack_output_port(NULL)
, _last_read_index(0)
- , non_process_thread_fifo (512)
+ , output_fifo (512)
+ , input_fifo (1024)
{
- int err = create_ports (node);
-
- if (!err) {
+ if (!create_ports (node)) {
_ok = true;
}
}
@@ -82,19 +83,16 @@ JACK_MidiPort::cycle_start (nframes_t nframes)
const nframes_t event_count = jack_midi_get_event_count(jack_buffer);
jack_midi_event_t ev;
- nframes_t cycle_start_frame = jack_last_frame_time (_jack_client);
-
- for (nframes_t i=0; i < event_count; ++i) {
+ timestamp_t cycle_start_frame = jack_last_frame_time (_jack_client);
+ for (nframes_t i = 0; i < event_count; ++i) {
jack_midi_event_get (&ev, jack_buffer, i);
-
- if (input_parser) {
- for (size_t i = 0; i < ev.size; i++) {
- input_parser->set_timestamp (cycle_start_frame + ev.time);
- input_parser->scanner (ev.buffer[i]);
- }
- }
+ input_fifo.write (cycle_start_frame + ev.time, (Evoral::EventType) 0, ev.size, ev.buffer);
}
+
+ if (event_count) {
+ xthread.wakeup ();
+ }
}
}
@@ -104,6 +102,8 @@ JACK_MidiPort::cycle_end ()
if (_jack_output_port != 0) {
flush (jack_port_get_buffer (_jack_output_port, _nframes_this_cycle));
}
+
+ Port::cycle_end();
}
int
@@ -113,10 +113,10 @@ JACK_MidiPort::write(byte * msg, size_t msglen, timestamp_t timestamp)
if (!is_process_thread()) {
- Glib::Mutex::Lock lm (non_process_thread_fifo_lock);
+ Glib::Mutex::Lock lm (output_fifo_lock);
RingBuffer< Evoral::Event<double> >::rw_vector vec;
- non_process_thread_fifo.get_write_vector (&vec);
+ output_fifo.get_write_vector (&vec);
if (vec.len[0] + vec.len[1] < 1) {
error << "no space in FIFO for non-process thread MIDI write" << endmsg;
@@ -129,10 +129,10 @@ JACK_MidiPort::write(byte * msg, size_t msglen, timestamp_t timestamp)
vec.buf[1]->set (msg, msglen, timestamp);
}
- non_process_thread_fifo.increment_write_idx (1);
+ output_fifo.increment_write_idx (1);
ret = msglen;
-
+
} else {
assert(_jack_output_port);
@@ -164,11 +164,13 @@ JACK_MidiPort::write(byte * msg, size_t msglen, timestamp_t timestamp)
}
if (ret > 0 && output_parser) {
- output_parser->raw_preparse (*output_parser, msg, ret);
+ // ardour doesn't care about this and neither should your app, probably
+ // output_parser->raw_preparse (*output_parser, msg, ret);
for (int i = 0; i < ret; i++) {
output_parser->scanner (msg[i]);
}
- output_parser->raw_postparse (*output_parser, msg, ret);
+ // ardour doesn't care about this and neither should your app, probably
+ // output_parser->raw_postparse (*output_parser, msg, ret);
}
return ret;
@@ -180,7 +182,7 @@ JACK_MidiPort::flush (void* jack_port_buffer)
RingBuffer< Evoral::Event<double> >::rw_vector vec;
size_t written;
- non_process_thread_fifo.get_read_vector (&vec);
+ output_fifo.get_read_vector (&vec);
if (vec.len[0] + vec.len[1]) {
// cerr << "Flush " << vec.len[0] + vec.len[1] << " events from non-process FIFO\n";
@@ -205,15 +207,28 @@ JACK_MidiPort::flush (void* jack_port_buffer)
}
if ((written = vec.len[0] + vec.len[1]) != 0) {
- non_process_thread_fifo.increment_read_idx (written);
+ output_fifo.increment_read_idx (written);
}
}
int
-JACK_MidiPort::read(byte * buf, size_t bufsize)
+JACK_MidiPort::read (byte * buf, size_t bufsize)
{
- cerr << "This program is improperly written. JACK_MidiPort::read() should never be called\n";
- abort ();
+ timestamp_t time;
+ Evoral::EventType type;
+ uint32_t size;
+ byte buffer[input_fifo.capacity()];
+
+ while (input_fifo.read (&time, &type, &size, buffer)) {
+ if (input_parser) {
+ input_parser->set_timestamp (time);
+ for (uint32_t i = 0; i < size; ++i) {
+ input_parser->scanner (buffer[i]);
+ }
+ }
+ }
+
+ return 0;
}
int
diff --git a/libs/midi++2/manager.cc b/libs/midi++2/manager.cc
index b6bbd40b0b..ffc8f4e1bc 100644
--- a/libs/midi++2/manager.cc
+++ b/libs/midi++2/manager.cc
@@ -115,6 +115,8 @@ Manager::add_port (const XMLNode& node)
outputPort = port;
}
+ PortsChanged (); /* EMIT SIGNAL */
+
return port;
}
@@ -124,11 +126,16 @@ Manager::remove_port (Port* port)
if (inputPort == port) {
inputPort = 0;
}
+
if (outputPort == port) {
outputPort = 0;
}
+
_ports.remove (port);
delete port;
+
+ PortsChanged (); /* EMIT SIGNAL */
+
return 0;
}
diff --git a/libs/midi++2/midi++/jack.h b/libs/midi++2/midi++/jack.h
index a449a8c554..18a6f3df68 100644
--- a/libs/midi++2/midi++/jack.h
+++ b/libs/midi++2/midi++/jack.h
@@ -30,9 +30,13 @@
#include <glibmm/thread.h>
-#include "pbd/ringbuffer.h"
#include <jack/jack.h>
#include <jack/midiport.h>
+
+#include "pbd/ringbuffer.h"
+#include "pbd/crossthread.h"
+#include "evoral/EventRingBuffer.hpp"
+
#include "midi++/port.h"
#include "midi++/event.h"
@@ -49,16 +53,16 @@ public:
int write(byte *msg, size_t msglen, timestamp_t timestamp);
int read(byte *buf, size_t max);
- /* No select(2)/poll(2)-based I/O */
- virtual int selectable() const { return -1; }
+ int selectable() const { return xthread.selectable(); }
+ bool must_drain_selectable() const { return true; }
- virtual void cycle_start(nframes_t nframes);
- virtual void cycle_end();
+ void cycle_start(nframes_t nframes);
+ void cycle_end();
static std::string typestring;
- virtual XMLNode& get_state () const;
- virtual void set_state (const XMLNode&);
+ XMLNode& get_state () const;
+ void set_state (const XMLNode&);
static void set_process_thread (pthread_t);
static pthread_t get_process_thread () { return _process_thread; }
@@ -79,13 +83,16 @@ private:
jack_port_t* _jack_output_port;
nframes_t _last_read_index;
timestamp_t _last_write_timestamp;
+ CrossThreadChannel xthread;
void flush (void* jack_port_buffer);
static pthread_t _process_thread;
- RingBuffer< Evoral::Event<double> > non_process_thread_fifo;
- Glib::Mutex non_process_thread_fifo_lock;
+ RingBuffer< Evoral::Event<double> > output_fifo;
+ Evoral::EventRingBuffer<timestamp_t> input_fifo;
+
+ Glib::Mutex output_fifo_lock;
};
diff --git a/libs/midi++2/midi++/manager.h b/libs/midi++2/midi++/manager.h
index 0698e969c0..8c665d0086 100644
--- a/libs/midi++2/midi++/manager.h
+++ b/libs/midi++2/midi++/manager.h
@@ -83,6 +83,8 @@ class Manager {
int get_known_ports (std::vector<PortSet>&);
+ sigc::signal<void> PortsChanged;
+
private:
/* This is a SINGLETON pattern */
diff --git a/libs/midi++2/midi++/port.h b/libs/midi++2/midi++/port.h
index 1bab068f85..23a9a01200 100644
--- a/libs/midi++2/midi++/port.h
+++ b/libs/midi++2/midi++/port.h
@@ -112,6 +112,7 @@ class Port : public sigc::trackable {
* @return File descriptor, or -1 if not selectable.
*/
virtual int selectable() const = 0;
+ virtual bool must_drain_selectable() const { return false; }
static void gtk_read_callback (void *ptr, int fd, int cond);
static void write_callback (byte *msg, unsigned int len, void *);