reinstate Ye Olde MIDI (input) thread; fix up a few startup warnings

git-svn-id: svn://localhost/ardour2/branches/3.0@3156 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
Paul Davis 2008-03-19 17:25:37 +00:00
parent eb4a1fdbb8
commit 3a29796405
19 changed files with 98 additions and 286 deletions

View file

@ -375,10 +375,6 @@
<separator/>
<menuitem action='ToggleTapeMachineMode'/>
</menu>
<menu action='Plugins'>
<menuitem action='DisableAllPlugins'/>
<menuitem action='ABAllPlugins'/>
</menu>
<menu action='Metering'>
<menu action='MeteringFallOffRate'>
<menuitem action='MeterFalloffOff'/>

View file

@ -620,8 +620,6 @@ Editor::update_ruler_visibility ()
frames_ruler->signal_motion_notify_event().connect (mem_fun(*this, &Editor::ruler_mouse_motion));
minsec_ruler->signal_motion_notify_event().connect (mem_fun(*this, &Editor::ruler_mouse_motion));
ruler_children.insert (canvaspos, Element(*_ruler_separator, PACK_SHRINK, PACK_START));
smpte_ruler->signal_scroll_event().connect (mem_fun(*this, &Editor::ruler_scroll));
bbt_ruler->signal_scroll_event().connect (mem_fun(*this, &Editor::ruler_scroll));
frames_ruler->signal_scroll_event().connect (mem_fun(*this, &Editor::ruler_scroll));

View file

@ -771,10 +771,6 @@ class Session : public PBD::StatefulDestructible
bool get_trace_midi_input(MIDI::Port *port = 0);
bool get_trace_midi_output(MIDI::Port *port = 0);
void send_midi_message (MIDI::Port * port, MIDI::eventType ev, MIDI::channel_t, MIDI::EventTwoBytes);
void deliver_midi (MIDI::Port*, MIDI::byte*, int32_t size);
void set_mmc_receive_device_id (uint32_t id);
void set_mmc_send_device_id (uint32_t id);
@ -1255,7 +1251,7 @@ class Session : public PBD::StatefulDestructible
void remove_empty_sounds ();
void setup_midi_control ();
//int midi_read (MIDI::Port *);
int midi_read (MIDI::Port *);
void enable_record ();
@ -1286,8 +1282,6 @@ class Session : public PBD::StatefulDestructible
/* MIDI Machine Control */
void deliver_mmc (MIDI::MachineControl::Command, nframes_t);
//void deliver_midi_message (MIDI::Port * port, MIDI::eventType ev, MIDI::channel_t, MIDI::EventTwoBytes);
//void deliver_data (MIDI::Port* port, MIDI::byte*, int32_t size);
void spp_start (MIDI::Parser&);
void spp_continue (MIDI::Parser&);
@ -1353,52 +1347,29 @@ class Session : public PBD::StatefulDestructible
struct MIDIRequest {
enum Type {
SendFullMTC,
SendMTC,
SendMMC,
PortChange,
SendMessage,
Deliver,
Quit
};
Type type;
MIDI::MachineControl::Command mmc_cmd;
nframes_t locate_frame;
// for SendMessage type
MIDI::Port * port;
MIDI::channel_t chan;
union {
MIDI::EventTwoBytes data;
MIDI::byte* buf;
};
union {
MIDI::eventType ev;
int32_t size;
};
MIDIRequest () {}
void *operator new(size_t ignored) {
return pool.alloc ();
};
void operator delete(void *ptr, size_t size) {
pool.release (ptr);
}
private:
static MultiAllocSingleReleasePool pool;
};
mutable gint butler_active;
Glib::Mutex midi_lock;
pthread_t midi_thread;
int midi_request_pipe[2];
RingBuffer<MIDIRequest*> midi_requests;
int start_midi_thread ();
void terminate_midi_thread ();
void poke_midi_thread ();
static void *_midi_thread_work (void *arg);
void midi_thread_work ();
void change_midi_ports ();
int use_config_midi_ports ();
mutable gint butler_active;
bool waiting_to_start;
void set_play_loop (bool yn);

View file

@ -129,8 +129,8 @@ Session::Session (AudioEngine &eng,
_midi_port (default_midi_port),
_session_dir (new SessionDirectory(fullpath)),
pending_events (2048),
//midi_requests (128), // the size of this should match the midi request pool size
post_transport_work((PostTransportWork)0),
midi_requests (128),
_send_smpte_update (false),
diskstreams (new DiskstreamList),
routes (new RouteList),
@ -199,7 +199,8 @@ Session::Session (AudioEngine &eng,
_midi_port (default_midi_port),
_session_dir ( new SessionDirectory(fullpath)),
pending_events (2048),
//midi_requests (16),
post_transport_work((PostTransportWork)0),
midi_requests (16),
_send_smpte_update (false),
diskstreams (new DiskstreamList),
routes (new RouteList),

View file

@ -52,8 +52,6 @@ using namespace MIDI;
MachineControl::CommandSignature MMC_CommandSignature;
MachineControl::ResponseSignature MMC_ResponseSignature;
MultiAllocSingleReleasePool Session::MIDIRequest::pool ("midi", sizeof (Session::MIDIRequest), 1024);
int
Session::use_config_midi_ports ()
{
@ -262,7 +260,6 @@ Session::set_midi_port (string port_tag)
void
Session::set_trace_midi_input (bool yn, MIDI::Port* port)
{
#if 0
MIDI::Parser* input_parser;
if (port) {
@ -289,7 +286,6 @@ Session::set_trace_midi_input (bool yn, MIDI::Port* port)
}
}
}
#endif
Config->set_trace_midi_input (yn);
}
@ -297,7 +293,6 @@ Session::set_trace_midi_input (bool yn, MIDI::Port* port)
void
Session::set_trace_midi_output (bool yn, MIDI::Port* port)
{
#if 0
MIDI::Parser* output_parser;
if (port) {
@ -324,7 +319,6 @@ Session::set_trace_midi_output (bool yn, MIDI::Port* port)
}
}
#endif
Config->set_trace_midi_output (yn);
}
@ -332,7 +326,6 @@ Session::set_trace_midi_output (bool yn, MIDI::Port* port)
bool
Session::get_trace_midi_input(MIDI::Port *port)
{
#if 0
MIDI::Parser* input_parser;
if (port) {
if ((input_parser = port->input()) != 0) {
@ -358,7 +351,6 @@ Session::get_trace_midi_input(MIDI::Port *port)
}
}
}
#endif
return false;
}
@ -366,7 +358,6 @@ Session::get_trace_midi_input(MIDI::Port *port)
bool
Session::get_trace_midi_output(MIDI::Port *port)
{
#if 0
MIDI::Parser* output_parser;
if (port) {
if ((output_parser = port->output()) != 0) {
@ -392,7 +383,6 @@ Session::get_trace_midi_output(MIDI::Port *port)
}
}
}
#endif
return false;
@ -423,46 +413,6 @@ Session::setup_midi_control ()
mtc_msg[14] = 0xf1;
}
#if 0
int
Session::midi_read (MIDI::Port* port)
{
MIDI::byte buf[512];
/* reading from the MIDI port activates the Parser
that in turn generates signals that we care
about. the port is already set to NONBLOCK so that
can read freely here.
*/
while (1) {
// cerr << "+++ READ ON " << port->name() << endl;
int nread = port->read (buf, sizeof (buf));
// cerr << "-- READ (" << nread << " ON " << port->name() << endl;
if (nread > 0) {
if ((size_t) nread < sizeof (buf)) {
break;
} else {
continue;
}
} else if (nread == 0) {
break;
} else if (errno == EAGAIN) {
break;
} else {
fatal << string_compose(_("Error reading from MIDI port %1"), port->name()) << endmsg;
/*NOTREACHED*/
}
}
return 0;
}
#endif
void
Session::spp_start (Parser& ignored)
{
@ -712,26 +662,21 @@ Session::mmc_record_enable (MIDI::MachineControl &mmc, size_t trk, bool enabled)
}
}
void
Session::change_midi_ports ()
{
/*
MIDIRequest* request = new MIDIRequest;
request->type = MIDIRequest::PortChange;
midi_requests.write (&request, 1);
poke_midi_thread ();
*/
}
/** Send MTC Full Frame message (complete SMPTE time) for the start of this cycle.
* This resets the MTC code, the next quarter frame message that is sent will be
* the first one with the beginning of this cycle as the new start point.
*
* Audio thread only, realtime safe. MIDI::Manager::cycle_start must
* have been called with the appropriate nframes parameter this cycle.
*/
int
Session::send_full_time_code(nframes_t nframes)
{
@ -905,25 +850,6 @@ Session::send_midi_time_code_for_cycle(nframes_t nframes)
/***********************************************************************
OUTBOUND MMC STUFF
**********************************************************************/
/*
void
Session::send_mmc_in_another_thread (MIDI::MachineControl::Command cmd, nframes_t target_frame)
{
MIDIRequest* request;
if (_mtc_port == 0 || !session_send_mmc) {
return;
}
request = new MIDIRequest;
request->type = MIDIRequest::SendMMC;
request->mmc_cmd = cmd;
request->locate_frame = target_frame;
midi_requests.write (&request, 1);
poke_midi_thread ();
}
*/
/** Send an MMC command at the given absolute timestamp (@a where).
*
@ -990,8 +916,7 @@ Session::deliver_mmc (MIDI::MachineControl::Command cmd, nframes_t where)
assert(where >= _transport_frame);
// FIXME: timestamp correct? [DR]
if (!_mmc_port->midimsg (mmc_buffer, sizeof (mmc_buffer), where - _transport_frame)) {
if (!_mmc_port->midimsg (mmc_buffer, sizeof (mmc_buffer), 0)) {
error << string_compose(_("MMC: cannot send command %1%2%3"), &hex, cmd, &dec) << endmsg;
} /*else {
cerr << "Sending MMC\n";
@ -1028,80 +953,10 @@ Session::mmc_step_timeout ()
return true;
}
void
Session::send_midi_message (MIDI::Port * port, MIDI::eventType ev, MIDI::channel_t ch, MIDI::EventTwoBytes data)
{
// in another thread, really
/*
MIDIRequest* request = new MIDIRequest;
request->type = MIDIRequest::SendMessage;
request->port = port;
request->ev = ev;
request->chan = ch;
request->data = data;
midi_requests.write (&request, 1);
poke_midi_thread ();
*/
}
void
Session::deliver_midi (MIDI::Port * port, MIDI::byte* buf, int32_t bufsize)
{
// in another thread, really
/*
MIDIRequest* request = new MIDIRequest;
request->type = MIDIRequest::Deliver;
request->port = port;
request->buf = buf;
request->size = bufsize;
midi_requests.write (&request, 1);
poke_midi_thread ();
*/
}
#if 0
This is aaalll gone.
void
Session::deliver_midi_message (MIDI::Port * port, MIDI::eventType ev, MIDI::channel_t ch, MIDI::EventTwoBytes data)
{
if (port == 0 || ev == MIDI::none) {
return;
}
midi_msg[0] = (ev & 0xF0) | (ch & 0xF);
midi_msg[1] = data.controller_number;
midi_msg[2] = data.value;
port->write (midi_msg, 3);
}
void
Session::deliver_data (MIDI::Port * port, MIDI::byte* buf, int32_t size)
{
if (port) {
port->write (buf, size);
}
/* this is part of the semantics of the Deliver request */
delete [] buf;
}
#endif
/*---------------------------------------------------------------------------
MIDI THREAD
---------------------------------------------------------------------------*/
#if 0
int
Session::start_midi_thread ()
{
@ -1125,8 +980,6 @@ Session::start_midi_thread ()
return -1;
}
// pthread_detach (midi_thread);
return 0;
}
@ -1134,6 +987,7 @@ void
Session::terminate_midi_thread ()
{
if (midi_thread) {
MIDIRequest* request = new MIDIRequest;
void* status;
@ -1190,10 +1044,7 @@ Session::midi_thread_work ()
/* set up the port vector; 4 is the largest possible size for now */
ports.push_back (0);
ports.push_back (0);
ports.push_back (0);
ports.push_back (0);
ports.assign (4, (MIDI::Port*) 0);
while (1) {
@ -1203,10 +1054,6 @@ Session::midi_thread_work ()
pfd[nfds].events = POLLIN|POLLHUP|POLLERR;
nfds++;
/* if we are using MMC control, we obviously have to listen
on the appropriate port.
*/
if (Config->get_mmc_control() && _mmc_port && _mmc_port->selectable() >= 0) {
pfd[nfds].fd = _mmc_port->selectable();
pfd[nfds].events = POLLIN|POLLHUP|POLLERR;
@ -1226,6 +1073,10 @@ Session::midi_thread_work ()
nfds++;
}
/* if we are using MMC control, we obviously have to listen
the relevant port.
*/
if (_midi_port && (_midi_port != _mmc_port || !Config->get_mmc_control()) && (_midi_port != _mtc_port) && _midi_port->selectable() >= 0) {
pfd[nfds].fd = _midi_port->selectable();
pfd[nfds].events = POLLIN|POLLHUP|POLLERR;
@ -1254,7 +1105,6 @@ Session::midi_thread_work ()
// cerr << "MIDI thread wakes at " << get_cycles () << endl;
fds_ready = 0;
restart = false;
/* check the transport request pipe */
@ -1294,37 +1144,6 @@ Session::midi_thread_work ()
while (midi_requests.read (&request, 1) == 1) {
switch (request->type) {
case MIDIRequest::SendFullMTC:
// cerr << "send full MTC\n";
send_full_time_code ();
// cerr << "... done\n";
break;
case MIDIRequest::SendMTC:
// cerr << "send qtr MTC\n";
send_midi_time_code ();
// cerr << "... done\n";
break;
case MIDIRequest::SendMMC:
// cerr << "send MMC\n";
deliver_mmc (request->mmc_cmd, request->locate_frame);
// cerr << "... done\n";
break;
case MIDIRequest::SendMessage:
// cerr << "send Message\n";
deliver_midi_message (request->port, request->ev, request->chan, request->data);
// cerr << "... done\n";
break;
case MIDIRequest::Deliver:
// cerr << "deliver\n";
deliver_data (_midi_port, request->buf, request->size);
// cerr << "... done\n";
break;
case MIDIRequest::PortChange:
/* restart poll with new ports */
// cerr << "rebind\n";
@ -1361,7 +1180,7 @@ Session::midi_thread_work ()
if (pfd[p].revents & POLLIN) {
fds_ready++;
midi_read (ports[p]);
ports[p]->parse ();
}
}
@ -1384,5 +1203,4 @@ Session::midi_thread_work ()
}
}
}
#endif

View file

@ -296,9 +296,9 @@ Session::second_stage_init (bool new_session)
return -1;
}
/*if (start_midi_thread ()) {
if (start_midi_thread ()) {
return -1;
}*/
}
// set_state() will call setup_raid_path(), but if it's a new session we need
// to call setup_raid_path() here.

View file

@ -459,12 +459,6 @@ Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
_requested_return_frame = -1;
}
/* MISSING IN 3.0 ... move into realtime_stop() */
// send_full_time_code ();
// deliver_mmc (MIDI::MachineControl::cmdStop, 0);
// deliver_mmc (MIDI::MachineControl::cmdLocate, _transport_frame);
/* END WHY */
if (did_record) {
/* XXX its a little odd that we're doing this here

View file

@ -137,7 +137,7 @@ ALSA_SequencerMidiPort::write (byte *msg, size_t msglen, timestamp_t ignored)
}
int
ALSA_SequencerMidiPort::read (byte *buf, size_t max, timestamp_t ignored)
ALSA_SequencerMidiPort::read (byte *buf, size_t max)
{
TR_FN();
int err;

View file

@ -150,7 +150,7 @@ FD_MidiPort::do_slow_write (byte *msg, unsigned int msglen)
}
int
FD_MidiPort::read (byte* buf, size_t max, timestamp_t ignored)
FD_MidiPort::read (byte* buf, size_t max)
{
int nread;

View file

@ -140,10 +140,9 @@ JACK_MidiPort::flush (void* jack_port_buffer)
}
int
JACK_MidiPort::read(byte * buf, size_t max, timestamp_t timestamp)
JACK_MidiPort::read(byte * buf, size_t bufsize)
{
assert(_currently_in_cycle);
assert(timestamp < _nframes_this_cycle);
assert(_jack_input_port);
jack_midi_event_t ev;
@ -152,9 +151,12 @@ JACK_MidiPort::read(byte * buf, size_t max, timestamp_t timestamp)
jack_port_get_buffer(_jack_input_port, _nframes_this_cycle),
_last_read_index++);
// XXX this doesn't handle ev.size > max
if (!err) {
memcpy(buf, ev.buffer, ev.size);
return ev.size;
size_t limit = min (bufsize, ev.size);
memcpy(buf, ev.buffer, limit);
return limit;
} else {
return 0;
}

View file

@ -37,6 +37,9 @@ class ALSA_SequencerMidiPort : public Port
ALSA_SequencerMidiPort (const XMLNode&);
virtual ~ALSA_SequencerMidiPort ();
int write (byte *msg, size_t msglen, timestamp_t timestamp);
int read (byte *buf, size_t max);
/* select(2)/poll(2)-based I/O */
virtual int selectable() const;
@ -48,10 +51,6 @@ class ALSA_SequencerMidiPort : public Port
void set_state (const XMLNode&);
protected:
/* Direct I/O */
int write (byte *msg, size_t msglen, timestamp_t timestamp);
int read (byte *buf, size_t max, timestamp_t timestamp);
std::string get_typestring () const {
return typestring;

View file

@ -38,6 +38,11 @@ namespace MIDI {
CoreMidi_MidiPort(const XMLNode& node);
virtual ~ CoreMidi_MidiPort();
int write (byte * msg, size_t msglen, timestamp_t timestamp);
int read (byte * buf, size_t max) {
return 0;
}
virtual int selectable() const {
return -1;
}
@ -46,12 +51,6 @@ namespace MIDI {
static std::string typestring;
protected:
/* Direct I/O */
int write (byte * msg, size_t msglen, timestamp_t timestamp);
int read (byte * buf, size_t max, timestamp_t timestamp) {
return 0;
}
/* CoreMidi callback */
static void read_proc(const MIDIPacketList * pktlist,

View file

@ -79,7 +79,7 @@ class FD_MidiPort : public Port
return nwritten;
}
virtual int read (byte *buf, size_t max, timestamp_t ignored);
int read (byte *buf, size_t max);
private:
static std::string *midi_dirpath;

View file

@ -46,6 +46,9 @@ public:
JACK_MidiPort (const XMLNode& node, jack_client_t* jack_client);
virtual ~JACK_MidiPort ();
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; }
@ -63,11 +66,6 @@ public:
return typestring;
}
protected:
/* Direct I/O */
int write(byte *msg, size_t msglen, timestamp_t timestamp);
int read(byte *buf, size_t max, timestamp_t timestamp);
private:
int create_ports(const XMLNode&);

View file

@ -49,7 +49,7 @@ class Null_MidiPort : public Port
return msglen;
}
int read (byte *buf, size_t max, timestamp_t timestamp) {
int read (byte *buf, size_t max) {
return 0;
}

View file

@ -67,13 +67,14 @@ class Port : public sigc::trackable {
*/
virtual int write (byte *msg, size_t msglen, timestamp_t timestamp) = 0;
/** Read a message from port.
* @param buf Raw MIDI message to send
* @param max Max size to write to @a buf
* @param timestamp Time stamp in frames of this message (relative to cycle start)
* @return number of bytes successfully written to \a buf
/** Read raw bytes from a port.
* @param buf memory to store read data in
* @param bufsize size of @a buf
* @return number of bytes successfully read, negative if error
*/
virtual int read (byte *buf, size_t max, timestamp_t timestamp) = 0;
virtual int read (byte *buf, size_t bufsize) = 0;
void parse ();
/** Write a message to port.
* @return true on success.

View file

@ -20,8 +20,10 @@
#include <iostream>
#include <cstdio>
#include <fcntl.h>
#include <errno.h>
#include <pbd/xml++.h>
#include <pbd/error.h>
#include <pbd/failed_constructor.h>
#include <midi++/types.h>
@ -31,6 +33,7 @@
using namespace MIDI;
using namespace std;
using namespace PBD;
size_t Port::nports = 0;
@ -87,6 +90,40 @@ Port::~Port ()
}
}
void
Port::parse ()
{
byte buf[512];
/* parsing is done (if at all) by initiating a read from
the port.
*/
while (1) {
// cerr << "+++ READ ON " << name() << endl;
int nread = read (buf, sizeof (buf));
// cerr << "-- READ (" << nread << " ON " << name() << endl;
if (nread > 0) {
if ((size_t) nread < sizeof (buf)) {
break;
} else {
continue;
}
} else if (nread == 0) {
break;
} else if (errno == EAGAIN) {
break;
} else {
fatal << "Error reading from MIDI port " << name() << endmsg;
/*NOTREACHED*/
}
}
}
/** Send a clock tick message.
* \return true on success.
*/
@ -138,13 +175,11 @@ void
Port::gtk_read_callback (void *ptr, int fd, int cond)
{
byte buf[64];
((Port *)ptr)->read (buf, sizeof (buf), 0);
((Port *)ptr)->read (buf, sizeof (buf));
}
void
Port::write_callback (byte *msg, unsigned int len, void *ptr)
{
((Port *)ptr)->write (msg, len, 0);
}

View file

@ -79,7 +79,7 @@ MidiByteArray SurfacePort::read()
if ( !active() ) return retval;
// read port and copy to return value
int nread = port().read( buf, sizeof (buf), 0 );
int nread = port().read (buf, sizeof (buf));
if (nread >= 0) {
retval.copy( nread, buf );