new design (inherited from softwerk) to properly handle I/O via ALSA sequencer, where multiple ports are multiplexed via one selectable/pollable fd; fix failure to save an entire class of ALSA sequencer port connections, which helps save/restore control surface sate
git-svn-id: svn://localhost/ardour2/branches/2.0-ongoing@13202 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
parent
da96d01950
commit
f5a5889f18
|
@ -27,6 +27,7 @@
|
|||
|
||||
#include <midi++/types.h>
|
||||
#include <midi++/alsa_sequencer.h>
|
||||
#include <midi++/manager.h>
|
||||
|
||||
#include "i18n.h"
|
||||
|
||||
|
@ -45,6 +46,9 @@ using namespace MIDI;
|
|||
using namespace PBD;
|
||||
|
||||
snd_seq_t* ALSA_SequencerMidiPort::seq = 0;
|
||||
ALSA_SequencerMidiPort::AllPorts ALSA_SequencerMidiPort::_all_ports;
|
||||
bool ALSA_SequencerMidiPort::_read_done = false;
|
||||
bool ALSA_SequencerMidiPort::_read_signal_connected = false;
|
||||
|
||||
ALSA_SequencerMidiPort::ALSA_SequencerMidiPort (const XMLNode& node)
|
||||
: Port (node)
|
||||
|
@ -67,6 +71,13 @@ ALSA_SequencerMidiPort::ALSA_SequencerMidiPort (const XMLNode& node)
|
|||
snd_midi_event_init (decoder);
|
||||
snd_midi_event_init (encoder);
|
||||
_ok = true;
|
||||
|
||||
if (!_read_signal_connected) {
|
||||
/* we need to do some magic just before a read is initiated
|
||||
*/
|
||||
Manager::PreRead.connect (sigc::ptr_fun (ALSA_SequencerMidiPort::prepare_read));
|
||||
_read_signal_connected = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -75,6 +86,8 @@ ALSA_SequencerMidiPort::ALSA_SequencerMidiPort (const XMLNode& node)
|
|||
|
||||
ALSA_SequencerMidiPort::~ALSA_SequencerMidiPort ()
|
||||
{
|
||||
_all_ports.erase (port_id);
|
||||
|
||||
if (decoder) {
|
||||
snd_midi_event_free (decoder);
|
||||
}
|
||||
|
@ -136,31 +149,65 @@ ALSA_SequencerMidiPort::write (byte *msg, size_t msglen)
|
|||
return totwritten;
|
||||
}
|
||||
|
||||
void
|
||||
ALSA_SequencerMidiPort::prepare_read ()
|
||||
{
|
||||
_read_done = false;
|
||||
}
|
||||
|
||||
int
|
||||
ALSA_SequencerMidiPort::read (byte *buf, size_t max)
|
||||
{
|
||||
if (!_read_done) {
|
||||
read_all_ports (buf, max);
|
||||
_read_done = true;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
ALSA_SequencerMidiPort::read_all_ports (byte *buf, size_t max)
|
||||
{
|
||||
TR_FN();
|
||||
int err;
|
||||
snd_seq_event_t *ev;
|
||||
if (0 <= (err = snd_seq_event_input (seq, &ev))) {
|
||||
TR_VAL(err);
|
||||
err = snd_midi_event_decode (decoder, buf, max, ev);
|
||||
}
|
||||
|
||||
err = snd_seq_event_input (seq, &ev);
|
||||
|
||||
if (err > 0) {
|
||||
bytes_read += err;
|
||||
|
||||
if (input_parser) {
|
||||
input_parser->raw_preparse (*input_parser, buf, err);
|
||||
for (int i = 0; i < err; i++) {
|
||||
input_parser->scanner (buf[i]);
|
||||
}
|
||||
input_parser->raw_postparse (*input_parser, buf, err);
|
||||
}
|
||||
}
|
||||
AllPorts::iterator p = _all_ports.find (ev->dest.port);
|
||||
|
||||
if (p == _all_ports.end()) {
|
||||
/* no error reading but port does not exist */
|
||||
return 0;
|
||||
}
|
||||
|
||||
return p->second->read_self (buf, max, ev);
|
||||
}
|
||||
|
||||
return -ENOENT == err ? 0 : err;
|
||||
}
|
||||
|
||||
int
|
||||
ALSA_SequencerMidiPort::read_self (byte* buf, size_t max, snd_seq_event_t* ev)
|
||||
{
|
||||
int evsize = snd_midi_event_decode (decoder, buf, max, ev);
|
||||
|
||||
bytes_read += evsize;
|
||||
|
||||
if (input_parser) {
|
||||
input_parser->raw_preparse (*input_parser, buf, evsize);
|
||||
|
||||
for (int i = 0; i < evsize; i++) {
|
||||
input_parser->scanner (buf[i]);
|
||||
}
|
||||
input_parser->raw_postparse (*input_parser, buf, evsize);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
ALSA_SequencerMidiPort::create_ports (const Port::Descriptor& desc)
|
||||
{
|
||||
|
@ -184,6 +231,8 @@ ALSA_SequencerMidiPort::create_ports (const Port::Descriptor& desc)
|
|||
snd_seq_ev_set_subs (&SEv);
|
||||
snd_seq_ev_set_direct (&SEv);
|
||||
|
||||
_all_ports.insert (make_pair (port_id, this));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -311,16 +360,12 @@ ALSA_SequencerMidiPort::get_connections (vector<SequencerPortAddress>& connectio
|
|||
|
||||
while (snd_seq_query_port_subscribers(seq, subs) >= 0) {
|
||||
|
||||
if (snd_seq_query_subscribe_get_time_real (subs)) {
|
||||
/* interesting connection */
|
||||
|
||||
seq_addr = *snd_seq_query_subscribe_get_addr (subs);
|
||||
|
||||
connections.push_back (SequencerPortAddress (seq_addr.client,
|
||||
seq_addr = *snd_seq_query_subscribe_get_addr (subs);
|
||||
|
||||
connections.push_back (SequencerPortAddress (seq_addr.client,
|
||||
seq_addr.port));
|
||||
}
|
||||
|
||||
snd_seq_query_subscribe_set_index(subs, snd_seq_query_subscribe_get_index(subs) + 1);
|
||||
snd_seq_query_subscribe_set_index (subs, snd_seq_query_subscribe_get_index(subs) + 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -47,6 +47,11 @@ class ALSA_SequencerMidiPort : public Port
|
|||
XMLNode& get_state() const;
|
||||
void set_state (const XMLNode&);
|
||||
|
||||
static int read_all_ports (byte* buf, size_t max);
|
||||
static void prepare_read ();
|
||||
|
||||
int read_self (byte* buf, size_t max, snd_seq_event_t* ev);
|
||||
|
||||
protected:
|
||||
/* Direct I/O */
|
||||
|
||||
|
@ -64,6 +69,11 @@ class ALSA_SequencerMidiPort : public Port
|
|||
|
||||
int create_ports (const Port::Descriptor&);
|
||||
|
||||
typedef std::map<int,ALSA_SequencerMidiPort*> AllPorts;
|
||||
static AllPorts _all_ports;
|
||||
static bool _read_done;
|
||||
static bool _read_signal_connected;
|
||||
|
||||
static int init_client (std::string name);
|
||||
static snd_seq_t* seq;
|
||||
|
||||
|
|
|
@ -69,6 +69,8 @@ class Manager {
|
|||
|
||||
int get_known_ports (std::vector<PortSet>&);
|
||||
|
||||
static sigc::signal0<void> PreRead;
|
||||
|
||||
private:
|
||||
/* This is a SINGLETON pattern */
|
||||
|
||||
|
|
|
@ -36,8 +36,9 @@ using namespace PBD;
|
|||
|
||||
Manager *Manager::theManager = 0;
|
||||
|
||||
sigc::signal0<void> Manager::PreRead;
|
||||
|
||||
Manager::Manager ()
|
||||
|
||||
{
|
||||
inputPort = 0;
|
||||
outputPort = 0;
|
||||
|
|
Loading…
Reference in New Issue