summaryrefslogtreecommitdiff
path: root/libs/midi++2
diff options
context:
space:
mode:
Diffstat (limited to 'libs/midi++2')
-rw-r--r--libs/midi++2/SConscript3
-rw-r--r--libs/midi++2/alsa_sequencer_midiport.cc250
-rw-r--r--libs/midi++2/coremidi_midiport.cc38
-rw-r--r--libs/midi++2/fd_midiport.cc24
-rw-r--r--libs/midi++2/fifomidi.cc8
-rw-r--r--libs/midi++2/jack_midiport.cc47
-rw-r--r--libs/midi++2/midi++/alsa_rawmidi.h6
-rw-r--r--libs/midi++2/midi++/alsa_sequencer.h24
-rw-r--r--libs/midi++2/midi++/coremidi_midiport.h65
-rw-r--r--libs/midi++2/midi++/factory.h3
-rw-r--r--libs/midi++2/midi++/fd_midiport.h21
-rw-r--r--libs/midi++2/midi++/fifomidi.h5
-rw-r--r--libs/midi++2/midi++/jack.h7
-rw-r--r--libs/midi++2/midi++/manager.h26
-rw-r--r--libs/midi++2/midi++/nullmidi.h1
-rw-r--r--libs/midi++2/midi++/port.h101
-rw-r--r--libs/midi++2/midi++/port_request.h66
-rw-r--r--libs/midi++2/midifactory.cc26
-rw-r--r--libs/midi++2/midimanager.cc196
-rw-r--r--libs/midi++2/midiport.cc105
-rw-r--r--libs/midi++2/miditrace.cc1
-rw-r--r--libs/midi++2/mmctest.cc1
-rw-r--r--libs/midi++2/port_request.cc83
23 files changed, 651 insertions, 456 deletions
diff --git a/libs/midi++2/SConscript b/libs/midi++2/SConscript
index 04b027b6a3..769d888903 100644
--- a/libs/midi++2/SConscript
+++ b/libs/midi++2/SConscript
@@ -7,7 +7,7 @@ import glob
Import('env libraries install_prefix')
midi2 = env.Copy()
-midi2.Merge([ libraries['sigc2'], libraries['xml'], libraries['glib2'], libraries['pbd'], libraries['jack'] ])
+midi2.Merge([ libraries['sigc2'], libraries['xml'], libraries['glibmm2'], libraries['glib2'], libraries['pbd'], libraries['jack'] ])
domain = 'midipp'
@@ -24,7 +24,6 @@ midiparser.cc
midiport.cc
mmc.cc
mtc.cc
-port_request.cc
version.cc
""")
diff --git a/libs/midi++2/alsa_sequencer_midiport.cc b/libs/midi++2/alsa_sequencer_midiport.cc
index bf891108c6..bae8aff2ab 100644
--- a/libs/midi++2/alsa_sequencer_midiport.cc
+++ b/libs/midi++2/alsa_sequencer_midiport.cc
@@ -23,10 +23,12 @@
#include <pbd/failed_constructor.h>
#include <pbd/error.h>
+#include <pbd/xml++.h>
#include <midi++/types.h>
#include <midi++/alsa_sequencer.h>
-#include <midi++/port_request.h>
+
+#include "i18n.h"
//#define DOTRACE 1
@@ -44,31 +46,31 @@ using namespace PBD;
snd_seq_t* ALSA_SequencerMidiPort::seq = 0;
-ALSA_SequencerMidiPort::ALSA_SequencerMidiPort (PortRequest &req)
- : Port (req)
+ALSA_SequencerMidiPort::ALSA_SequencerMidiPort (const XMLNode& node)
+ : Port (node)
, decoder (0)
, encoder (0)
, port_id (-1)
{
TR_FN();
int err;
+ Descriptor desc (node);
- if (!seq && init_client (req.devname) < 0) {
+ if (!seq && init_client (desc.device) < 0) {
_ok = false;
} else {
- if (0 <= (err = CreatePorts (req)) &&
+ if (0 <= (err = create_ports (desc)) &&
0 <= (err = snd_midi_event_new (1024, &decoder)) && // Length taken from ARDOUR::Session::midi_read ()
0 <= (err = snd_midi_event_new (64, &encoder))) { // Length taken from ARDOUR::Session::mmc_buffer
snd_midi_event_init (decoder);
snd_midi_event_init (encoder);
_ok = true;
- req.status = PortRequest::OK;
- } else {
- req.status = PortRequest::Unknown;
- }
+ }
}
+
+ set_state (node);
}
ALSA_SequencerMidiPort::~ALSA_SequencerMidiPort ()
@@ -94,7 +96,8 @@ ALSA_SequencerMidiPort::selectable () const
return -1;
}
-int ALSA_SequencerMidiPort::write (byte *msg, size_t msglen, timestamp_t timestamp)
+int
+ALSA_SequencerMidiPort::write (byte *msg, size_t msglen, timestamp_t ignored)
{
TR_FN ();
int R;
@@ -133,7 +136,8 @@ int ALSA_SequencerMidiPort::write (byte *msg, size_t msglen, timestamp_t timesta
return totwritten;
}
-int ALSA_SequencerMidiPort::read (byte *buf, size_t max, timestamp_t timestamp)
+int
+ALSA_SequencerMidiPort::read (byte *buf, size_t max, timestamp_t ignored)
{
TR_FN();
int err;
@@ -158,17 +162,20 @@ int ALSA_SequencerMidiPort::read (byte *buf, size_t max, timestamp_t timestamp)
}
int
-ALSA_SequencerMidiPort::CreatePorts (PortRequest &req)
+ALSA_SequencerMidiPort::create_ports (const Port::Descriptor& desc)
{
int err;
unsigned int caps = 0;
- if (req.mode == O_WRONLY || req.mode == O_RDWR)
+ if (desc.mode == O_WRONLY || desc.mode == O_RDWR)
caps |= SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE;
- if (req.mode == O_RDONLY || req.mode == O_RDWR)
+ if (desc.mode == O_RDONLY || desc.mode == O_RDWR)
caps |= SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SUBS_READ;
- if (0 <= (err = snd_seq_create_simple_port (seq, req.tagname, caps, SND_SEQ_PORT_TYPE_MIDI_GENERIC))) {
+ if (0 <= (err = snd_seq_create_simple_port (seq, desc.tag.c_str(), caps,
+ (SND_SEQ_PORT_TYPE_MIDI_GENERIC|
+ SND_SEQ_PORT_TYPE_SOFTWARE|
+ SND_SEQ_PORT_TYPE_APPLICATION)))) {
port_id = err;
@@ -203,3 +210,216 @@ ALSA_SequencerMidiPort::init_client (std::string name)
return -1;
}
}
+
+int
+ALSA_SequencerMidiPort::discover (vector<PortSet>& ports)
+{
+ int n = 0;
+
+ snd_seq_client_info_t *client_info;
+ snd_seq_port_info_t *port_info;
+
+ snd_seq_client_info_alloca (&client_info);
+ snd_seq_port_info_alloca (&port_info);
+ snd_seq_client_info_set_client (client_info, -1);
+
+ while (snd_seq_query_next_client(seq, client_info) >= 0) {
+
+ int alsa_client;
+
+ if ((alsa_client = snd_seq_client_info_get_client(client_info)) <= 0) {
+ break;
+ }
+
+ snd_seq_port_info_set_client(port_info, alsa_client);
+ snd_seq_port_info_set_port(port_info, -1);
+
+ char client[256];
+ snprintf (client, sizeof (client), "%d:%s", alsa_client, snd_seq_client_info_get_name(client_info));
+
+ ports.push_back (PortSet (client));
+
+ while (snd_seq_query_next_port(seq, port_info) >= 0) {
+
+#if 0
+ int type = snd_seq_port_info_get_type(pinfo);
+ if (!(type & SND_SEQ_PORT_TYPE_PORT)) {
+ continue;
+ }
+#endif
+
+ unsigned int port_capability = snd_seq_port_info_get_capability(port_info);
+
+ if ((port_capability & SND_SEQ_PORT_CAP_NO_EXPORT) == 0) {
+
+ int alsa_port = snd_seq_port_info_get_port(port_info);
+
+ char port[256];
+ snprintf (port, sizeof (port), "%d:%s", alsa_port, snd_seq_port_info_get_name(port_info));
+
+ std::string mode;
+
+ if (port_capability & SND_SEQ_PORT_CAP_READ) {
+ if (port_capability & SND_SEQ_PORT_CAP_WRITE) {
+ mode = "duplex";
+ } else {
+ mode = "output";
+ }
+ } else if (port_capability & SND_SEQ_PORT_CAP_WRITE) {
+ if (port_capability & SND_SEQ_PORT_CAP_READ) {
+ mode = "duplex";
+ } else {
+ mode = "input";
+ }
+ }
+
+ XMLNode node (X_("MIDI-port"));
+ node.add_property ("device", client);
+ node.add_property ("tag", port);
+ node.add_property ("mode", mode);
+ node.add_property ("type", "alsa/sequencer");
+
+ ports.back().ports.push_back (node);
+ ++n;
+ }
+ }
+ }
+
+ return n;
+}
+
+void
+ALSA_SequencerMidiPort::get_connections (vector<SequencerPortAddress>& connections, int dir) const
+{
+ snd_seq_query_subscribe_t *subs;
+ snd_seq_addr_t seq_addr;
+
+ snd_seq_query_subscribe_alloca (&subs);
+
+ // Get port connections...
+
+ if (dir) {
+ snd_seq_query_subscribe_set_type(subs, SND_SEQ_QUERY_SUBS_WRITE);
+ } else {
+ snd_seq_query_subscribe_set_type(subs, SND_SEQ_QUERY_SUBS_READ);
+ }
+
+ snd_seq_query_subscribe_set_index(subs, 0);
+ seq_addr.client = snd_seq_client_id (seq);
+ seq_addr.port = port_id;
+ snd_seq_query_subscribe_set_root(subs, &seq_addr);
+
+ while (snd_seq_query_port_subscribers(seq, subs) >= 0) {
+
+ 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);
+ }
+}
+
+XMLNode&
+ALSA_SequencerMidiPort::get_state () const
+{
+ XMLNode& root (Port::get_state ());
+ vector<SequencerPortAddress> connections;
+ XMLNode* sub = 0;
+ char buf[256];
+
+ get_connections (connections, 1);
+
+ if (!connections.empty()) {
+ if (!sub) {
+ sub = new XMLNode (X_("connections"));
+ }
+ for (vector<SequencerPortAddress>::iterator i = connections.begin(); i != connections.end(); ++i) {
+ XMLNode* cnode = new XMLNode (X_("read"));
+ snprintf (buf, sizeof (buf), "%d:%d", i->first, i->second);
+ cnode->add_property ("dest", buf);
+ sub->add_child_nocopy (*cnode);
+ }
+ }
+
+ connections.clear ();
+ get_connections (connections, 0);
+
+ if (!connections.empty()) {
+ if (!sub) {
+ sub = new XMLNode (X_("connections"));
+ }
+ for (vector<SequencerPortAddress>::iterator i = connections.begin(); i != connections.end(); ++i) {
+ XMLNode* cnode = new XMLNode (X_("write"));
+ snprintf (buf, sizeof (buf), "%d:%d", i->first, i->second);
+ cnode->add_property ("dest", buf);
+ sub->add_child_nocopy (*cnode);
+ }
+ }
+
+ if (sub) {
+ root.add_child_nocopy (*sub);
+ }
+
+ return root;
+}
+
+void
+ALSA_SequencerMidiPort::set_state (const XMLNode& node)
+{
+ Port::set_state (node);
+
+ XMLNodeList children (node.children());
+ XMLNodeIterator iter;
+
+ for (iter = children.begin(); iter != children.end(); ++iter) {
+
+ if ((*iter)->name() == X_("connections")) {
+
+ XMLNodeList gchildren ((*iter)->children());
+ XMLNodeIterator gciter;
+
+ for (gciter = gchildren.begin(); gciter != gchildren.end(); ++gciter) {
+ XMLProperty* prop;
+
+ if ((prop = (*gciter)->property ("dest")) != 0) {
+ int client;
+ int port;
+
+ if (sscanf (prop->value().c_str(), "%d:%d", &client, &port) == 2) {
+
+ snd_seq_port_subscribe_t *sub;
+ snd_seq_addr_t seq_addr;
+
+ snd_seq_port_subscribe_alloca(&sub);
+
+ if ((*gciter)->name() == X_("write")) {
+
+ seq_addr.client = snd_seq_client_id (seq);
+ seq_addr.port = port_id;
+ snd_seq_port_subscribe_set_sender(sub, &seq_addr);
+
+ seq_addr.client = client;
+ seq_addr.port = port;
+ snd_seq_port_subscribe_set_dest(sub, &seq_addr);
+
+ } else {
+
+ seq_addr.client = snd_seq_client_id (seq);
+ seq_addr.port = port_id;
+ snd_seq_port_subscribe_set_dest(sub, &seq_addr);
+
+ seq_addr.client = client;
+ seq_addr.port = port;
+ snd_seq_port_subscribe_set_sender(sub, &seq_addr);
+ }
+
+ snd_seq_subscribe_port (seq, sub);
+ }
+ }
+ }
+
+ break;
+ }
+ }
+}
diff --git a/libs/midi++2/coremidi_midiport.cc b/libs/midi++2/coremidi_midiport.cc
index 2cd98239ec..14020a6f35 100644
--- a/libs/midi++2/coremidi_midiport.cc
+++ b/libs/midi++2/coremidi_midiport.cc
@@ -23,7 +23,6 @@
#include <midi++/coremidi_midiport.h>
#include <midi++/types.h>
-#include <midi++/port_request.h>
#include <mach/mach_time.h>
#include <pbd/pthread_utils.h>
@@ -36,15 +35,15 @@ MIDITimeStamp CoreMidi_MidiPort::MIDIGetCurrentHostTime()
return mach_absolute_time();
}
-CoreMidi_MidiPort::CoreMidi_MidiPort (PortRequest &req) : Port (req)
+CoreMidi_MidiPort::CoreMidi_MidiPort (const XMLNode& node) : Port (node)
{
+ Descriptor desc (node);
+
firstrecv = true;
int err;
- if (0 == (err = Open(req))) {
+ if (0 == (err = Open(desc))) {
_ok = true;
- req.status = PortRequest::OK;
- } else
- req.status = PortRequest::Unknown;
+ }
}
CoreMidi_MidiPort::~CoreMidi_MidiPort () {Close();}
@@ -56,10 +55,10 @@ void CoreMidi_MidiPort::Close ()
if (midi_client) MIDIClientDispose(midi_client);
}
-int CoreMidi_MidiPort::write (byte *msg, size_t msglen, timestamp_t timestamp)
+int CoreMidi_MidiPort::write (byte *msg, size_t msglen, timestamp_t ignored)
{
OSStatus err;
- MIDIPacketList* pktlist = (MIDIPacketList*)midi_buffer;
+ MIDIPacketList* pktlist = (MIDIPacketList*)midi_buffer;
MIDIPacket* packet = MIDIPacketListInit(pktlist);
packet = MIDIPacketListAdd(pktlist,sizeof(midi_buffer),packet,MIDIGetCurrentHostTime(),msglen,msg);
@@ -77,21 +76,21 @@ int CoreMidi_MidiPort::write (byte *msg, size_t msglen, timestamp_t timestamp)
}
}
-int CoreMidi_MidiPort::Open (PortRequest &req)
+int CoreMidi_MidiPort::Open (const Descriptor& desc)
{
OSStatus err;
CFStringRef coutputStr;
string str;
-
- coutputStr = CFStringCreateWithCString(0, req.devname, CFStringGetSystemEncoding());
+
+ coutputStr = CFStringCreateWithCString(0, desc.device.c_str(), CFStringGetSystemEncoding());
err = MIDIClientCreate(coutputStr, 0, 0, &midi_client);
CFRelease(coutputStr);
- if (!midi_client) {
+ if (!midi_client) {
//error << "Cannot open CoreMidi client : " << err << endmsg.
- goto error;
- }
+ goto error;
+ }
- str = req.tagname + string("_in");
+ str = desc.tag + string("_in");
coutputStr = CFStringCreateWithCString(0, str.c_str(), CFStringGetSystemEncoding());
err = MIDIDestinationCreate(midi_client, coutputStr, read_proc, this, &midi_destination);
CFRelease(coutputStr);
@@ -100,7 +99,7 @@ int CoreMidi_MidiPort::Open (PortRequest &req)
goto error;
}
- str = req.tagname + string("_out");
+ str = desc.tag + string("_out");
coutputStr = CFStringCreateWithCString(0, str.c_str(), CFStringGetSystemEncoding());
err = MIDISourceCreate(midi_client, coutputStr, &midi_source);
CFRelease(coutputStr);
@@ -142,3 +141,10 @@ void CoreMidi_MidiPort::read_proc (const MIDIPacketList *pktlist, void *refCon,
}
}
+int
+CoreMidi_MidiPort::discover (vector<PortSet>& ports)
+{
+ /* XXX do dynamic port discovery here */
+
+ return 0;
+}
diff --git a/libs/midi++2/fd_midiport.cc b/libs/midi++2/fd_midiport.cc
index 81d81c8558..17a7eff367 100644
--- a/libs/midi++2/fd_midiport.cc
+++ b/libs/midi++2/fd_midiport.cc
@@ -34,40 +34,38 @@ using namespace PBD;
string *FD_MidiPort::midi_dirpath = 0;
string *FD_MidiPort::midi_filename_pattern = 0;
-FD_MidiPort::FD_MidiPort (PortRequest &req,
+FD_MidiPort::FD_MidiPort (const XMLNode& node,
const string &dirpath,
const string &pattern)
- : Port (req)
+ : Port (node)
{
- open (req);
+ Descriptor desc (node);
+
+ open (desc);
if (_fd < 0) {
switch (errno) {
case EBUSY:
error << "MIDI: port device in use" << endmsg;
- req.status = PortRequest::Busy;
break;
case ENOENT:
error << "MIDI: no such port device" << endmsg;
- req.status = PortRequest::NoSuchFile;
break;
case EACCES:
error << "MIDI: access to port denied" << endmsg;
- req.status = PortRequest::NotAllowed;
break;
default:
- req.status = PortRequest::Unknown;
+ break;
}
} else {
_ok = true;
- req.status = PortRequest::OK;
if (midi_dirpath == 0) {
midi_dirpath = new string (dirpath);
midi_filename_pattern = new string (pattern);
}
- if (req.mode & O_NONBLOCK == 0) {
+ if (desc.mode & O_NONBLOCK == 0) {
/* we unconditionally set O_NONBLOCK during
open, but the request didn't ask for it,
so remove it.
@@ -80,11 +78,11 @@ FD_MidiPort::FD_MidiPort (PortRequest &req,
}
void
-FD_MidiPort::open (PortRequest &req)
+FD_MidiPort::open (const Descriptor& desc)
{
- int mode = req.mode | O_NONBLOCK;
- _fd = ::open (req.devname, mode);
+ int mode = desc.mode | O_NONBLOCK;
+ _fd = ::open (desc.device.c_str(), mode);
}
vector<string *> *
@@ -152,7 +150,7 @@ FD_MidiPort::do_slow_write (byte *msg, unsigned int msglen)
}
int
-FD_MidiPort::read (byte* buf, size_t max, timestamp_t timestamp)
+FD_MidiPort::read (byte* buf, size_t max, timestamp_t ignored)
{
int nread;
diff --git a/libs/midi++2/fifomidi.cc b/libs/midi++2/fifomidi.cc
index 7bb126ddeb..a81520bb95 100644
--- a/libs/midi++2/fifomidi.cc
+++ b/libs/midi++2/fifomidi.cc
@@ -26,19 +26,19 @@
using namespace MIDI;
-FIFO_MidiPort::FIFO_MidiPort (PortRequest &req)
- : FD_MidiPort (req, ".", "midi")
+FIFO_MidiPort::FIFO_MidiPort (const XMLNode& node)
+ : FD_MidiPort (node, ".", "midi")
{
}
void
-FIFO_MidiPort::open (PortRequest &req)
+FIFO_MidiPort::open (const Port::Descriptor& desc)
{
/* This is a placeholder for the fun-and-games I think we will
need to do with FIFO's.
*/
- _fd = ::open (req.devname, req.mode|O_NDELAY);
+ _fd = ::open (desc.device.c_str(), desc.mode|O_NDELAY);
}
diff --git a/libs/midi++2/jack_midiport.cc b/libs/midi++2/jack_midiport.cc
index 4b2808a698..11cd70a051 100644
--- a/libs/midi++2/jack_midiport.cc
+++ b/libs/midi++2/jack_midiport.cc
@@ -23,26 +23,22 @@
#include <midi++/types.h>
#include <midi++/jack.h>
-#include <midi++/port_request.h>
using namespace std;
using namespace MIDI;
-JACK_MidiPort::JACK_MidiPort(PortRequest & req, jack_client_t* jack_client)
- : Port(req)
+JACK_MidiPort::JACK_MidiPort(const XMLNode& node, jack_client_t* jack_client)
+ : Port(node)
, _jack_client(jack_client)
, _jack_input_port(NULL)
, _jack_output_port(NULL)
, _last_read_index(0)
{
- int err = create_ports(req);
+ int err = create_ports (node);
if (!err) {
- req.status = PortRequest::OK;
_ok = true;
- } else {
- req.status = PortRequest::Unknown;
- }
+ }
}
JACK_MidiPort::~JACK_MidiPort()
@@ -94,8 +90,10 @@ JACK_MidiPort::read(byte * buf, size_t max, timestamp_t timestamp)
}
int
-JACK_MidiPort::create_ports(PortRequest & req)
+JACK_MidiPort::create_ports(const XMLNode& node)
{
+ Descriptor desc (node);
+
assert(!_jack_input_port);
assert(!_jack_output_port);
@@ -103,24 +101,33 @@ JACK_MidiPort::create_ports(PortRequest & req)
bool ret = true;
- if (req.mode == O_RDWR || req.mode == O_WRONLY) {
+ if (desc.mode == O_RDWR || desc.mode == O_WRONLY) {
_jack_output_port = jack_port_register(_jack_client,
- string(req.tagname).append("_out").c_str(),
- JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput, 0);
- jack_midi_clear_buffer(
- jack_port_get_buffer(_jack_output_port, nframes));
+ string(desc.tag).append("_out").c_str(),
+ JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput, 0);
+ jack_midi_clear_buffer(jack_port_get_buffer(_jack_output_port, nframes));
ret = ret && (_jack_output_port != NULL);
}
-
- if (req.mode == O_RDWR || req.mode == O_RDONLY) {
+
+ if (desc.mode == O_RDWR || desc.mode == O_RDONLY) {
_jack_input_port = jack_port_register(_jack_client,
- string(req.tagname).append("_in").c_str(),
- JACK_DEFAULT_MIDI_TYPE, JackPortIsInput, 0);
- jack_midi_clear_buffer(
- jack_port_get_buffer(_jack_input_port, nframes));
+ string(desc.tag).append("_in").c_str(),
+ JACK_DEFAULT_MIDI_TYPE, JackPortIsInput, 0);
+ jack_midi_clear_buffer(jack_port_get_buffer(_jack_input_port, nframes));
ret = ret && (_jack_input_port != NULL);
}
return ret ? 0 : -1;
}
+XMLNode&
+JACK_MidiPort::get_state () const
+{
+ XMLNode& root (Port::get_state ());
+ return root;
+}
+
+void
+JACK_MidiPort::set_state (const XMLNode& node)
+{
+}
diff --git a/libs/midi++2/midi++/alsa_rawmidi.h b/libs/midi++2/midi++/alsa_rawmidi.h
index 54b86edd70..e5abc2832f 100644
--- a/libs/midi++2/midi++/alsa_rawmidi.h
+++ b/libs/midi++2/midi++/alsa_rawmidi.h
@@ -34,8 +34,8 @@ class ALSA_RawMidiPort : public MIDI::FD_MidiPort
{
public:
- ALSA_RawMidiPort (MIDI::PortRequest &req)
- : FD_MidiPort (req, "/dev/snd", "midi") {}
+ ALSA_RawMidiPort (const XMLNode& node)
+ : FD_MidiPort (node, "/dev/snd", "midi") {}
virtual ~ALSA_RawMidiPort () {}
static std::string typestring;
@@ -46,7 +46,7 @@ class ALSA_RawMidiPort : public MIDI::FD_MidiPort
}
};
-} // namespace MIDI
+}
#endif // __alsa_rawmidi_h__
diff --git a/libs/midi++2/midi++/alsa_sequencer.h b/libs/midi++2/midi++/alsa_sequencer.h
index b54486416a..a95f9c476f 100644
--- a/libs/midi++2/midi++/alsa_sequencer.h
+++ b/libs/midi++2/midi++/alsa_sequencer.h
@@ -30,39 +30,45 @@
namespace MIDI {
-class PortRequest;
-
class ALSA_SequencerMidiPort : public Port
+
{
public:
- ALSA_SequencerMidiPort (PortRequest &req);
+ ALSA_SequencerMidiPort (const XMLNode&);
virtual ~ALSA_SequencerMidiPort ();
/* select(2)/poll(2)-based I/O */
virtual int selectable() const;
-
+
+ static int discover (std::vector<PortSet>&);
static std::string typestring;
- protected:
- std::string get_typestring () const {
- return typestring;
- }
+ XMLNode& get_state() const;
+ 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;
+ }
+
private:
snd_midi_event_t *decoder, *encoder;
int port_id;
snd_seq_event_t SEv;
- int CreatePorts(PortRequest &req);
+ int create_ports (const Port::Descriptor&);
static int init_client (std::string name);
static snd_seq_t* seq;
+
+ typedef std::pair<int,int> SequencerPortAddress;
+ void get_connections (std::vector<SequencerPortAddress>&, int dir) const;
};
}; /* namespace MIDI */
diff --git a/libs/midi++2/midi++/coremidi_midiport.h b/libs/midi++2/midi++/coremidi_midiport.h
index 91eccea4a5..d5d3c23ede 100644
--- a/libs/midi++2/midi++/coremidi_midiport.h
+++ b/libs/midi++2/midi++/coremidi_midiport.h
@@ -22,6 +22,7 @@
#include <list>
#include <string>
+#include <vector>
#include <fcntl.h>
#include <unistd.h>
@@ -32,45 +33,47 @@
namespace MIDI {
-namespace PortRequest;
+ class CoreMidi_MidiPort:public Port {
+ public:
+ CoreMidi_MidiPort(const XMLNode& node);
+ virtual ~ CoreMidi_MidiPort();
-class CoreMidi_MidiPort:public Port
-{
- public:
- CoreMidi_MidiPort(PortRequest & req);
- virtual ~ CoreMidi_MidiPort();
-
- virtual int selectable() const {
- return -1;
- }
- static std::string typestring;
+ virtual int selectable() const {
+ return -1;
+ }
+
+ static int discover (std::vector<PortSet>&);
+ static std::string typestring;
+
+ protected:
+ /* Direct I/O */
+ int write (byte * msg, size_t msglen, timestamp_t timestamp);
- protected:
+ int read (byte * buf, size_t max, timestamp_t timestamp) {
+ return 0;
+ }
+
+ /* CoreMidi callback */
+ static void read_proc(const MIDIPacketList * pktlist,
+ void *refCon, void *connRefCon);
+
std::string get_typestring () const {
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);
-
- /* CoreMidi callback */
- static void read_proc(const MIDIPacketList * pktlist,
- void *refCon, void *connRefCon);
-
- private:
- byte midi_buffer[1024];
- MIDIClientRef midi_client;
- MIDIEndpointRef midi_destination;
- MIDIEndpointRef midi_source;
+ private:
+ byte midi_buffer[1024];
+ MIDIClientRef midi_client;
+ MIDIEndpointRef midi_destination;
+ MIDIEndpointRef midi_source;
- int Open(PortRequest & req);
- void Close();
- static MIDITimeStamp MIDIGetCurrentHostTime();
+ int Open(const Port::Descriptor&);
+ void Close();
+ static MIDITimeStamp MIDIGetCurrentHostTime();
- bool firstrecv;
-};
+ bool firstrecv;
+
+ };
} // namespace MIDI
diff --git a/libs/midi++2/midi++/factory.h b/libs/midi++2/midi++/factory.h
index 9954ea72fe..f3402546e9 100644
--- a/libs/midi++2/midi++/factory.h
+++ b/libs/midi++2/midi++/factory.h
@@ -23,13 +23,12 @@
#include <string>
#include <midi++/port.h>
-#include <midi++/port_request.h>
namespace MIDI {
class PortFactory {
public:
- Port *create_port (PortRequest &req, void* data);
+ Port *create_port (const XMLNode&, void* data);
static bool ignore_duplicate_devices (Port::Type);
static int get_known_ports (std::vector<PortSet>&);
diff --git a/libs/midi++2/midi++/fd_midiport.h b/libs/midi++2/midi++/fd_midiport.h
index 34e2e27a1a..ec5a9f8af4 100644
--- a/libs/midi++2/midi++/fd_midiport.h
+++ b/libs/midi++2/midi++/fd_midiport.h
@@ -29,7 +29,6 @@
#include <unistd.h>
#include <midi++/port.h>
-#include <midi++/port_request.h>
namespace MIDI {
@@ -37,7 +36,7 @@ class FD_MidiPort : public Port
{
public:
- FD_MidiPort (PortRequest &req,
+ FD_MidiPort (const XMLNode& node,
const std::string &dirpath,
const std::string &pattern);
@@ -46,23 +45,14 @@ class FD_MidiPort : public Port
}
virtual int selectable() const;
- static std::vector<std::string *> *list_devices ();
-
- static std::string typestring;
- protected:
- std::string get_typestring () const {
- return typestring;
- }
+ static std::vector<std::string *> *list_devices ();
protected:
int _fd;
- virtual void open (PortRequest &req);
+ virtual void open (const Port::Descriptor&);
- /* Direct I/O */
-
- virtual int write (byte *msg, size_t msglen,
- timestamp_t timestamp) {
+ virtual int write (byte *msg, size_t msglen, timestamp_t ignored) {
int nwritten;
if ((_mode & O_ACCMODE) == O_RDONLY) {
@@ -89,8 +79,7 @@ class FD_MidiPort : public Port
return nwritten;
}
- virtual int read (byte *buf, size_t max,
- timestamp_t timestamp);
+ virtual int read (byte *buf, size_t max, timestamp_t ignored);
private:
static std::string *midi_dirpath;
diff --git a/libs/midi++2/midi++/fifomidi.h b/libs/midi++2/midi++/fifomidi.h
index ea644dde06..3439c27dcf 100644
--- a/libs/midi++2/midi++/fifomidi.h
+++ b/libs/midi++2/midi++/fifomidi.h
@@ -25,7 +25,6 @@
#include <unistd.h>
#include <midi++/port.h>
-#include <midi++/port_request.h>
#include <midi++/fd_midiport.h>
namespace MIDI {
@@ -34,7 +33,7 @@ class FIFO_MidiPort : public MIDI::FD_MidiPort
{
public:
- FIFO_MidiPort (PortRequest &req);
+ FIFO_MidiPort (const XMLNode&);
~FIFO_MidiPort () {};
static std::string typestring;
@@ -45,7 +44,7 @@ class FIFO_MidiPort : public MIDI::FD_MidiPort
}
private:
- void open (PortRequest &req);
+ void open (const Port::Descriptor&);
};
} // namespace MIDI
diff --git a/libs/midi++2/midi++/jack.h b/libs/midi++2/midi++/jack.h
index 1f25609aac..845dd0c229 100644
--- a/libs/midi++2/midi++/jack.h
+++ b/libs/midi++2/midi++/jack.h
@@ -39,7 +39,7 @@ namespace MIDI
class JACK_MidiPort : public Port
{
public:
- JACK_MidiPort (PortRequest &req, jack_client_t* jack_client);
+ JACK_MidiPort (const XMLNode& node, jack_client_t* jack_client);
virtual ~JACK_MidiPort ();
/* No select(2)/poll(2)-based I/O */
@@ -49,6 +49,9 @@ public:
static std::string typestring;
+ virtual XMLNode& get_state () const;
+ virtual void set_state (const XMLNode&);
+
protected:
std::string get_typestring () const {
return typestring;
@@ -60,7 +63,7 @@ protected:
int read(byte *buf, size_t max, timestamp_t timestamp);
private:
- int create_ports(PortRequest &req);
+ int create_ports(const XMLNode&);
jack_client_t* _jack_client;
jack_port_t* _jack_input_port;
diff --git a/libs/midi++2/midi++/manager.h b/libs/midi++2/midi++/manager.h
index eef52abe52..bb3bf9b999 100644
--- a/libs/midi++2/midi++/manager.h
+++ b/libs/midi++2/midi++/manager.h
@@ -21,6 +21,8 @@
#define __midi_manager_h__
#include <map>
+#include <vector>
+
#include <string>
#include <midi++/types.h>
@@ -28,20 +30,18 @@
namespace MIDI {
-/** Creates, stores, and manages system MIDI ports.
- */
class Manager {
public:
~Manager ();
void set_api_data(void* data) { api_data = data; }
-
+
/** Signal the start of an audio cycle.
* This MUST be called before any reading/writing for this cycle.
* Realtime safe.
*/
void cycle_start(nframes_t nframes);
-
+
/** Signal the end of an audio cycle.
* This signifies that the cycle began with @ref cycle_start has ended.
* This MUST be called at the end of each cycle.
@@ -49,13 +49,25 @@ class Manager {
*/
void cycle_end();
- Port *add_port (PortRequest &);
+ Port *add_port (const XMLNode& node);
int remove_port (Port*);
Port *port (std::string name);
size_t nports () { return ports_by_device.size(); }
+ /* defaults for clients who are not picky */
+
+ Port *inputPort;
+ Port *outputPort;
+ channel_t inputChannelNumber;
+ channel_t outputChannelNumber;
+
+ int set_input_port (std::string);
+ int set_output_port (std::string);
+ int set_input_channel (channel_t);
+ int set_output_channel (channel_t);
+
int foreach_port (int (*func)(const Port &, size_t n, void *),
void *arg);
@@ -70,7 +82,7 @@ class Manager {
return theManager;
}
- static int parse_port_request (std::string str, Port::Type type);
+ int get_known_ports (std::vector<PortSet>&);
private:
/* This is a SINGLETON pattern */
@@ -81,7 +93,7 @@ class Manager {
PortMap ports_by_device; /* canonical */
PortMap ports_by_tag; /* may contain duplicate Ports */
- void *api_data;
+ void* api_data;
void close_ports ();
};
diff --git a/libs/midi++2/midi++/nullmidi.h b/libs/midi++2/midi++/nullmidi.h
index 6ed94db71c..8f36e6aed8 100644
--- a/libs/midi++2/midi++/nullmidi.h
+++ b/libs/midi++2/midi++/nullmidi.h
@@ -24,7 +24,6 @@
#include <string>
#include <midi++/port.h>
-#include <midi++/port_request.h>
namespace MIDI {
diff --git a/libs/midi++2/midi++/port.h b/libs/midi++2/midi++/port.h
index e4338cf952..dcae446c42 100644
--- a/libs/midi++2/midi++/port.h
+++ b/libs/midi++2/midi++/port.h
@@ -20,10 +20,11 @@
#define __libmidi_port_h__
#include <string>
+#include <iostream>
#include <sigc++/sigc++.h>
+#include <pbd/xml++.h>
-#include <pbd/selectable.h>
#include <midi++/types.h>
#include <midi++/parser.h>
@@ -44,64 +45,82 @@ class Port : public sigc::trackable {
FIFO
};
- Port (PortRequest &);
+
+ Port (const XMLNode&);
virtual ~Port ();
+ virtual XMLNode& get_state () const;
+ virtual void set_state (const XMLNode&);
+
// FIXME: make Manager a friend of port so these can be hidden?
-
+
/* Only for use by MidiManager. Don't ever call this. */
virtual void cycle_start(nframes_t nframes);
-
/* Only for use by MidiManager. Don't ever call this. */
virtual void cycle_end();
- /* Direct I/O */
-
- /** 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
- */
- virtual int read(byte *buf, size_t max, timestamp_t timestamp) = 0;
-
/** Write a message to port.
* @param msg Raw MIDI message to send
* @param msglen Size of @a msg
* @param timestamp Time stamp in frames of this message (relative to cycle start)
* @return number of bytes successfully written
*/
- virtual int write(byte *msg, size_t msglen, timestamp_t timestamp) = 0;
+ 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
+ */
+ virtual int read (byte *buf, size_t max, timestamp_t timestamp) = 0;
/** Write a message to port.
* @return true on success.
* FIXME: describe semantics here
*/
- bool midimsg (byte *msg, size_t len, timestamp_t timestamp) {
+ int midimsg (byte *msg, size_t len, timestamp_t timestamp) {
return !(write (msg, len, timestamp) == (int) len);
- }
+ }
+
+ int three_byte_msg (byte a, byte b, byte c, timestamp_t timestamp) {
+ byte msg[3];
+ msg[0] = a;
+ msg[1] = b;
+ msg[2] = c;
+
+ return !(write (msg, 3, timestamp) == 3);
+ }
+
bool clock (timestamp_t timestamp);
+
+ /* slowdown i/o to a loop of single byte emissions
+ interspersed with a busy loop of 10000 * this value.
+
+ This may be ignored by a particular instance
+ of this virtual class. See FD_MidiPort for an
+ example of where it used.
+ */
- /** Slow down I/O to a loop of single byte emissions
- * interspersed with a busy loop of 10000 * this value.
- *
- * This may be ignored by a particular instance of this virtual
- * class. See FD_MidiPort for an example of where it used. */
void set_slowdown (size_t n) { slowdown = n; }
/* select(2)/poll(2)-based I/O */
/** Get the file descriptor for port.
- * @return File descriptor, or -1 if not selectable. */
+ * @return File descriptor, or -1 if not selectable.
+ */
virtual int selectable() const = 0;
+ static void gtk_read_callback (void *ptr, int fd, int cond);
+ static void write_callback (byte *msg, unsigned int len, void *);
+
Channel *channel (channel_t chn) {
return _channel[chn&0x7F];
}
- Parser *input() { return input_parser; }
- Parser *output() { return output_parser; }
+ Parser *input() { return input_parser; }
+ Parser *output() { return output_parser; }
void iostat (int *written, int *read,
const size_t **in_counts,
@@ -121,14 +140,21 @@ class Port : public sigc::trackable {
}
}
- bool clock ();
-
const char *device () const { return _devname.c_str(); }
- const char *name () const { return _tagname.c_str(); }
- Type type () const { return _type; }
- int mode () const { return _mode; }
- bool ok () const { return _ok; }
- size_t number () const { return _number; }
+ const char *name () const { return _tagname.c_str(); }
+ Type type () const { return _type; }
+ int mode () const { return _mode; }
+ bool ok () const { return _ok; }
+
+ struct Descriptor {
+ std::string tag;
+ std::string device;
+ int mode;
+ Port::Type type;
+
+ Descriptor (const XMLNode&);
+ XMLNode& get_state();
+ };
protected:
bool _ok;
@@ -147,10 +173,21 @@ class Port : public sigc::trackable {
Parser *output_parser;
size_t slowdown;
+ virtual std::string get_typestring () const = 0;
+
private:
static size_t nports;
};
+struct PortSet {
+ PortSet (std::string str) : owner (str) { }
+
+ std::string owner;
+ std::list<XMLNode> ports;
+};
+
+std::ostream & operator << ( std::ostream & os, const Port & port );
+
} // namespace MIDI
#endif // __libmidi_port_h__
diff --git a/libs/midi++2/midi++/port_request.h b/libs/midi++2/midi++/port_request.h
deleted file mode 100644
index dfde87a63c..0000000000
--- a/libs/midi++2/midi++/port_request.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- Copyright (C) 1999 Paul Barton-Davis
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- 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.
-
-*/
-
-#ifndef __midi_port_request_h__
-#define __midi_port_request_h__
-
-#include <string>
-
-namespace MIDI {
-
-struct PortRequest {
- enum Status {
- Unknown,
- OK,
- Busy,
- NoSuchFile,
- TypeUnsupported,
- NotAllowed
- };
- const char *devname;
- const char *tagname;
- int mode;
- Port::Type type;
- Status status;
-
- PortRequest () {
- devname = 0;
- tagname = 0;
- mode = 0;
- type = Port::Unknown;
- status = Unknown;
- }
-
- PortRequest (const std::string &xdev,
- const std::string &xtag,
- const std::string &xmode,
- const std::string &xtype);
-};
-
-struct PortSet {
- PortSet (std::string str) : owner (str) { }
-
- std::string owner;
- std::list<PortRequest> ports;
-};
-
-} // namespace MIDI
-
-#endif // __midi_port_request_h__
-
diff --git a/libs/midi++2/midifactory.cc b/libs/midi++2/midifactory.cc
index 9d98d9f6a7..d893cc9f47 100644
--- a/libs/midi++2/midifactory.cc
+++ b/libs/midi++2/midifactory.cc
@@ -24,7 +24,6 @@
#include <midi++/types.h>
#include <midi++/factory.h>
-#include <midi++/nullmidi.h>
#include <midi++/fifomidi.h>
#ifdef WITH_JACK_MIDI
@@ -33,7 +32,6 @@
std::string MIDI::JACK_MidiPort::typestring = "jack";
#endif // WITH_JACK_MIDI
-std::string MIDI::Null_MidiPort::typestring = "null";
std::string MIDI::FIFO_MidiPort::typestring = "fifo";
#ifdef WITH_ALSA
@@ -58,50 +56,44 @@ using namespace PBD;
// FIXME: void* data pointer, filthy
Port *
-PortFactory::create_port (PortRequest &req, void* data)
+PortFactory::create_port (const XMLNode& node, void* data)
{
+ Port::Descriptor desc (node);
Port *port;
- switch (req.type) {
+ switch (desc.type) {
#ifdef WITH_JACK_MIDI
case Port::JACK_Midi:
assert(data != NULL);
- port = new JACK_MidiPort (req, (jack_client_t*)data);
+ port = new JACK_MidiPort (node, (jack_client_t*) data);
break;
#endif // WITH_JACK_MIDI
#ifdef WITH_ALSA
case Port::ALSA_RawMidi:
- port = new ALSA_RawMidiPort (req);
+ port = new ALSA_RawMidiPort (node);
break;
case Port::ALSA_Sequencer:
- port = new ALSA_SequencerMidiPort (req);
+ port = new ALSA_SequencerMidiPort (node);
break;
#endif // WITH_ALSA
#if WITH_COREMIDI
case Port::CoreMidi_MidiPort:
- port = new CoreMidi_MidiPort (req);
+ port = new CoreMidi_MidiPort (node);
break;
#endif // WITH_COREMIDI
- case Port::Null:
- port = new Null_MidiPort (req);
- break;
-
case Port::FIFO:
- port = new FIFO_MidiPort (req);
+ port = new FIFO_MidiPort (node);
break;
default:
- req.status = PortRequest::TypeUnsupported;
return 0;
}
- req.status = PortRequest::OK;
-
return port;
}
@@ -179,8 +171,6 @@ PortFactory::string_to_type (const string& xtype)
} else if (strings_equal_ignore_case (xtype, CoreMidi_MidiPort::typestring)) {
return Port::CoreMidi_MidiPort;
#endif
- } else if (strings_equal_ignore_case (xtype, Null_MidiPort::typestring)) {
- return Port::Null;
} else if (strings_equal_ignore_case (xtype, FIFO_MidiPort::typestring)) {
return Port::FIFO;
#ifdef WITH_JACK_MIDI
diff --git a/libs/midi++2/midimanager.cc b/libs/midi++2/midimanager.cc
index ee73bdad86..8a358c3183 100644
--- a/libs/midi++2/midimanager.cc
+++ b/libs/midi++2/midimanager.cc
@@ -27,21 +27,25 @@
#include <midi++/manager.h>
#include <midi++/factory.h>
#include <midi++/channel.h>
-#include <midi++/port_request.h>
using namespace std;
using namespace MIDI;
using namespace PBD;
+/* XXX check for strdup leaks */
+
Manager *Manager::theManager = 0;
Manager::Manager ()
- : api_data(NULL)
{
+ inputPort = 0;
+ outputPort = 0;
+ inputChannelNumber = 0;
+ outputChannelNumber = 0;
+ api_data = 0;
}
Manager::~Manager ()
-
{
PortMap::iterator i;
@@ -58,27 +62,27 @@ Manager::~Manager ()
}
Port *
-Manager::add_port (PortRequest &req)
-
+Manager::add_port (const XMLNode& node)
{
+ Port::Descriptor desc (node);
PortFactory factory;
Port *port;
PortMap::iterator existing;
pair<string, Port *> newpair;
- if (!PortFactory::ignore_duplicate_devices (req.type)) {
+ if (!PortFactory::ignore_duplicate_devices (desc.type)) {
- if ((existing = ports_by_device.find (req.devname)) != ports_by_device.end()) {
+ if ((existing = ports_by_device.find (desc.device)) != ports_by_device.end()) {
port = (*existing).second;
- if (port->mode() == req.mode) {
+ if (port->mode() == desc.mode) {
/* Same mode - reuse the port, and just
create a new tag entry.
*/
- newpair.first = req.tagname;
+ newpair.first = desc.tag;
newpair.second = port;
ports_by_tag.insert (newpair);
@@ -91,10 +95,10 @@ Manager::add_port (PortRequest &req)
operation.
*/
- if ((req.mode == O_RDWR && port->mode() != O_RDWR) ||
- (req.mode != O_RDWR && port->mode() == O_RDWR)) {
+ if ((desc.mode == O_RDWR && port->mode() != O_RDWR) ||
+ (desc.mode != O_RDWR && port->mode() == O_RDWR)) {
error << "MIDIManager: port tagged \""
- << req.tagname
+ << desc.tag
<< "\" cannot be opened duplex and non-duplex"
<< endmsg;
return 0;
@@ -103,7 +107,8 @@ Manager::add_port (PortRequest &req)
/* modes must be different or complementary */
}
}
- port = factory.create_port (req, api_data);
+
+ port = factory.create_port (node, api_data);
if (port == 0) {
return 0;
@@ -122,6 +127,18 @@ Manager::add_port (PortRequest &req)
newpair.second = port;
ports_by_device.insert (newpair);
+ /* first port added becomes the default input
+ port.
+ */
+
+ if (inputPort == 0) {
+ inputPort = port;
+ }
+
+ if (outputPort == 0) {
+ outputPort = port;
+ }
+
return port;
}
@@ -156,119 +173,88 @@ Manager::remove_port (Port* port)
return 0;
}
-Port *
-Manager::port (string name)
+int
+Manager::set_input_port (string tag)
{
PortMap::iterator res;
+ bool found = false;
for (res = ports_by_tag.begin(); res != ports_by_tag.end(); res++) {
- if (name == (*res).first) {
- return (*res).second;
+ if (tag == (*res).first) {
+ found = true;
+ break;
}
}
+
+ if (!found) {
+ return -1;
+ }
+
+ inputPort = (*res).second;
return 0;
}
int
-Manager::foreach_port (int (*func)(const Port &, size_t, void *),
- void *arg)
+Manager::set_output_port (string tag)
{
- PortMap::const_iterator i;
- int retval;
- int n;
-
- for (n = 0, i = ports_by_device.begin();
- i != ports_by_device.end(); i++, n++) {
+ PortMap::iterator res;
+ bool found = false;
- if ((retval = func (*((*i).second), n, arg)) != 0) {
- return retval;
+ for (res = ports_by_tag.begin(); res != ports_by_tag.end(); res++) {
+ if (tag == (*res).first) {
+ found = true;
+ break;
}
}
-
- return 0;
-}
-
-int
-Manager::parse_port_request (string str, Port::Type type)
-{
- PortRequest *req;
- string::size_type colon;
- string tag;
-
- if (str.length() == 0) {
- error << "MIDI: missing port specification" << endmsg;
+
+ if (!found) {
return -1;
}
- /* Port specifications look like:
+ // XXX send a signal to say we're about to change output ports
- devicename
- devicename:tagname
- devicename:tagname:mode
+ if (outputPort) {
+ for (channel_t chan = 0; chan < 16; chan++) {
+ outputPort->channel (chan)->all_notes_off (0);
+ }
+ }
+ outputPort = (*res).second;
- where
+ // XXX send a signal to say we've changed output ports
- "devicename" is the full path to the requested file
-
- "tagname" (optional) is the name used to refer to the
- port. If not given, g_path_get_basename (devicename)
- will be used.
+ return 0;
+}
- "mode" (optional) is either "r" or "w" or something else.
- if it is "r", the port will be opened
- read-only, if "w", the port will be opened
- write-only. Any other value, or no mode
- specification at all, will cause the port to
- be opened for reading and writing.
- */
-
- req = new PortRequest;
- colon = str.find_first_of (':');
+Port *
+Manager::port (string name)
+{
+ PortMap::iterator res;
- if (colon != string::npos) {
- req->devname = strdup (str.substr (0, colon).c_str());
- } else {
- req->devname = strdup (str.c_str());
+ for (res = ports_by_tag.begin(); res != ports_by_tag.end(); res++) {
+ if (name == (*res).first) {
+ return (*res).second;
+ }
}
- if (colon < str.length()) {
-
- tag = str.substr (colon+1);
+ return 0;
+}
- /* see if there is a mode specification in the tag part */
+int
+Manager::foreach_port (int (*func)(const Port &, size_t, void *),
+ void *arg)
+{
+ PortMap::const_iterator i;
+ int retval;
+ int n;
- colon = tag.find_first_of (':');
-
- if (colon != string::npos) {
- string modestr;
-
- req->tagname = strdup (tag.substr (0, colon).c_str());
-
- modestr = tag.substr (colon+1);
- if (modestr == "r") {
- req->mode = O_RDONLY;
- } else if (modestr == "w") {
- req->mode = O_WRONLY;
- } else {
- req->mode = O_RDWR;
- }
+ for (n = 0, i = ports_by_device.begin();
+ i != ports_by_device.end(); i++, n++) {
- } else {
- req->tagname = strdup (tag.c_str());
- req->mode = O_RDWR;
+ if ((retval = func (*((*i).second), n, arg)) != 0) {
+ return retval;
}
-
- } else {
- req->tagname = g_path_get_basename (req->devname);
- req->mode = O_RDWR;
- }
-
- req->type = type;
-
- if (MIDI::Manager::instance()->add_port (*req) == 0) {
- return -1;
}
return 0;
@@ -277,16 +263,22 @@ Manager::parse_port_request (string str, Port::Type type)
void
Manager::cycle_start(nframes_t nframes)
{
- for (PortMap::iterator i = ports_by_device.begin();
- i != ports_by_device.end(); i++)
- (*i).second->cycle_start(nframes);
+ for (PortMap::iterator i = ports_by_device.begin(); i != ports_by_device.end(); i++) {
+ (*i).second->cycle_start (nframes);
+ }
}
void
Manager::cycle_end()
{
- for (PortMap::iterator i = ports_by_device.begin();
- i != ports_by_device.end(); i++)
- (*i).second->cycle_end();
+ for (PortMap::iterator i = ports_by_device.begin(); i != ports_by_device.end(); i++) {
+ (*i).second->cycle_end ();
+ }
}
+
+int
+Manager::get_known_ports (vector<PortSet>& ports)
+{
+ return PortFactory::get_known_ports (ports);
+}
diff --git a/libs/midi++2/midiport.cc b/libs/midi++2/midiport.cc
index 7f31b909d3..2e3d36c19c 100644
--- a/libs/midi++2/midiport.cc
+++ b/libs/midi++2/midiport.cc
@@ -17,24 +17,29 @@
$Id$
*/
-
+#include <iostream>
#include <cstdio>
#include <fcntl.h>
+#include <pbd/xml++.h>
+#include <pbd/failed_constructor.h>
+
#include <midi++/types.h>
#include <midi++/port.h>
#include <midi++/channel.h>
-#include <midi++/port_request.h>
+#include <midi++/factory.h>
-using namespace Select;
using namespace MIDI;
+using namespace std;
size_t Port::nports = 0;
-Port::Port (PortRequest &req)
+Port::Port (const XMLNode& node)
: _currently_in_cycle(false)
, _nframes_this_cycle(0)
{
+ Descriptor desc (node);
+
_ok = false; /* derived class must set to true if constructor
succeeds.
*/
@@ -45,10 +50,9 @@ Port::Port (PortRequest &req)
output_parser = 0;
slowdown = 0;
- _devname = req.devname;
- _tagname = req.tagname;
- _mode = req.mode;
- _number = nports++;
+ _devname = desc.device;
+ _tagname = desc.tag;
+ _mode = desc.mode;
if (_mode == O_RDONLY || _mode == O_RDWR) {
input_parser = new Parser (*this);
@@ -77,7 +81,6 @@ Port::Port (PortRequest &req)
Port::~Port ()
-
{
for (int i = 0; i < 16; i++) {
delete _channel[i];
@@ -113,3 +116,87 @@ Port::cycle_end ()
_nframes_this_cycle = 0;
}
+XMLNode&
+Port::get_state () const
+{
+ XMLNode* node = new XMLNode ("MIDI-port");
+ node->add_property ("tag", _tagname);
+ node->add_property ("device", _devname);
+ node->add_property ("mode", PortFactory::mode_to_string (_mode));
+ node->add_property ("type", get_typestring());
+
+ return *node;
+}
+
+void
+Port::set_state (const XMLNode& node)
+{
+ // relax
+}
+
+void
+Port::gtk_read_callback (void *ptr, int fd, int cond)
+{
+ byte buf[64];
+
+ ((Port *)ptr)->read (buf, sizeof (buf), 0);
+}
+
+void
+Port::write_callback (byte *msg, unsigned int len, void *ptr)
+
+{
+ ((Port *)ptr)->write (msg, len, 0);
+}
+
+std::ostream & MIDI::operator << ( std::ostream & os, const MIDI::Port & port )
+{
+ using namespace std;
+ os << "MIDI::Port { ";
+ os << "device: " << port.device();
+ os << "; ";
+ os << "name: " << port.name();
+ os << "; ";
+ os << "type: " << port.type();
+ os << "; ";
+ os << "mode: " << port.mode();
+ os << "; ";
+ os << "ok: " << port.ok();
+ os << "; ";
+ os << " }";
+ return os;
+}
+
+Port::Descriptor::Descriptor (const XMLNode& node)
+{
+ const XMLProperty *prop;
+ bool have_tag = false;
+ bool have_device = false;
+ bool have_type = false;
+ bool have_mode = false;
+
+ if ((prop = node.property ("tag")) != 0) {
+ tag = prop->value();
+ have_tag = true;
+ }
+
+ if ((prop = node.property ("device")) != 0) {
+ device = prop->value();
+ have_device = true;
+ }
+
+ if ((prop = node.property ("type")) != 0) {
+ type = PortFactory::string_to_type (prop->value());
+ have_type = true;
+ }
+
+ if ((prop = node.property ("mode")) != 0) {
+ mode = PortFactory::string_to_mode (prop->value());
+ have_mode = true;
+ }
+
+ if (!have_tag || !have_device || !have_type || !have_mode) {
+ throw failed_constructor();
+ }
+}
+
diff --git a/libs/midi++2/miditrace.cc b/libs/midi++2/miditrace.cc
index d7c65d9f29..fafe822f82 100644
--- a/libs/midi++2/miditrace.cc
+++ b/libs/midi++2/miditrace.cc
@@ -11,7 +11,6 @@ Transmitter fatal (Transmitter::Fatal);
TextReceiver text_receiver ("mmctest");
#include "midi++/port.h"
-#include "midi++/port_request.h"
#include "midi++/manager.h"
using namespace MIDI;
diff --git a/libs/midi++2/mmctest.cc b/libs/midi++2/mmctest.cc
index 36fbd61124..062f6e8d32 100644
--- a/libs/midi++2/mmctest.cc
+++ b/libs/midi++2/mmctest.cc
@@ -11,7 +11,6 @@ Transmitter fatal (Transmitter::Fatal);
TextReceiver text_receiver ("mmctest");
#include "midi++/port.h"
-#include "midi++/port_request.h"
#include "midi++/manager.h"
#include "midi++/mmc.h"
diff --git a/libs/midi++2/port_request.cc b/libs/midi++2/port_request.cc
deleted file mode 100644
index d209f02574..0000000000
--- a/libs/midi++2/port_request.cc
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- Copyright (C) 2000 Paul Barton-Davis
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- 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.
-
- $Id$
-*/
-
-#include <fcntl.h>
-#include <string.h>
-#include <midi++/port.h>
-#include <midi++/port_request.h>
-
-using namespace std;
-using namespace MIDI;
-
-PortRequest::PortRequest (const string &xdev,
- const string &xtag,
- const string &xmode,
- const string &xtype)
-
-{
- status = OK;
-
- devname = strdup (xdev.c_str());
- tagname = strdup (xtag.c_str());
-
- if (xmode == "output" ||
- xmode == "out" ||
- xmode == "OUTPUT" ||
- xmode == "OUT") {
- mode = O_WRONLY;
-
- } else if (xmode == "input" ||
- xmode == "in" ||
- xmode == "INPUT" ||
- xmode == "IN") {
- mode = O_RDONLY;
-
- } else if (xmode == "duplex" ||
- xmode == "DUPLEX" ||
- xmode == "inout" ||
- xmode == "INOUT") {
- mode = O_RDWR;
- } else {
- status = Unknown;
- }
-
- if (xtype == "JACK" ||
- xtype == "jack") {
- type = Port::JACK_Midi;
- } else if (xtype == "ALSA/RAW" ||
- xtype == "alsa/raw") {
- type = Port::ALSA_RawMidi;
- } else if (xtype == "ALSA/SEQUENCER" ||
- xtype == "alsa/sequencer") {
- type = Port::ALSA_Sequencer;
- } else if (xtype == "COREMIDI" ||
- xtype == "coremidi") {
- type = Port::CoreMidi_MidiPort;
- } else if (xtype == "NULL" ||
- xtype == "null") {
- type = Port::Null;
- } else if (xtype == "FIFO" ||
- xtype == "fifo") {
- type = Port::FIFO;
- } else {
- status = Unknown;
- }
-}
-