mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-20 13:46:30 +01:00
auto-re-connect ALSA seq ports at startup, if they were connected; may break OS X compilation till tomorrow morning (US Eastern TZ)
git-svn-id: svn://localhost/ardour2/branches/2.0-ongoing@2489 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
parent
0fe9b63100
commit
e79a7e8ff9
28 changed files with 326 additions and 399 deletions
|
|
@ -712,12 +712,15 @@ OptionEditor::add_midi_port ()
|
||||||
smod = "duplex";
|
smod = "duplex";
|
||||||
}
|
}
|
||||||
|
|
||||||
MIDI::PortRequest req (X_("ardour"),
|
|
||||||
dialog.port_name.get_text(),
|
|
||||||
smod,
|
|
||||||
MIDI::PortFactory::default_port_type());
|
|
||||||
|
|
||||||
if (MIDI::Manager::instance()->add_port (req) != 0) {
|
XMLNode node (X_("MIDI-port"));
|
||||||
|
|
||||||
|
node.add_property ("tag", dialog.port_name.get_text());
|
||||||
|
node.add_property ("device", X_("ardour")); // XXX this can't be right for all types
|
||||||
|
node.add_property ("type", MIDI::PortFactory::default_port_type());
|
||||||
|
node.add_property ("mode", smod);
|
||||||
|
|
||||||
|
if (MIDI::Manager::instance()->add_port (node) != 0) {
|
||||||
redisplay_midi_ports ();
|
redisplay_midi_ports ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -42,17 +42,7 @@ class Configuration : public Stateful
|
||||||
Configuration();
|
Configuration();
|
||||||
virtual ~Configuration();
|
virtual ~Configuration();
|
||||||
|
|
||||||
struct MidiPortDescriptor {
|
std::map<std::string,XMLNode> midi_ports;
|
||||||
std::string tag;
|
|
||||||
std::string device;
|
|
||||||
std::string type;
|
|
||||||
std::string mode;
|
|
||||||
|
|
||||||
MidiPortDescriptor (const XMLNode&);
|
|
||||||
XMLNode& get_state();
|
|
||||||
};
|
|
||||||
|
|
||||||
std::map<std::string,MidiPortDescriptor *> midi_ports;
|
|
||||||
|
|
||||||
void map_parameters (sigc::slot<void,const char*> theSlot);
|
void map_parameters (sigc::slot<void,const char*> theSlot);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -217,10 +217,12 @@ Configuration::set_state (const XMLNode& root)
|
||||||
if (node->name() == "MIDI-port") {
|
if (node->name() == "MIDI-port") {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
pair<string,MidiPortDescriptor*> newpair;
|
MIDI::Port::Descriptor desc (*node);
|
||||||
newpair.second = new MidiPortDescriptor (*node);
|
map<string,XMLNode>::iterator x;
|
||||||
newpair.first = newpair.second->tag;
|
if ((x = midi_ports.find (desc.tag)) != midi_ports.end()) {
|
||||||
midi_ports.insert (newpair);
|
midi_ports.erase (x);
|
||||||
|
}
|
||||||
|
midi_ports.insert (pair<string,XMLNode>(desc.tag,*node));
|
||||||
}
|
}
|
||||||
|
|
||||||
catch (failed_constructor& err) {
|
catch (failed_constructor& err) {
|
||||||
|
|
@ -263,52 +265,6 @@ Configuration::set_variables (const XMLNode& node, ConfigVariableBase::Owner own
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Configuration::MidiPortDescriptor::MidiPortDescriptor (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 = prop->value();
|
|
||||||
have_type = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((prop = node.property ("mode")) != 0) {
|
|
||||||
mode = prop->value();
|
|
||||||
have_mode = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!have_tag || !have_device || !have_type || !have_mode) {
|
|
||||||
throw failed_constructor();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
XMLNode&
|
|
||||||
Configuration::MidiPortDescriptor::get_state()
|
|
||||||
{
|
|
||||||
XMLNode* root = new XMLNode("MIDI-port");
|
|
||||||
|
|
||||||
root->add_property("tag", tag);
|
|
||||||
root->add_property("device", device);
|
|
||||||
root->add_property("type", type);
|
|
||||||
root->add_property("mode", mode);
|
|
||||||
|
|
||||||
return *root;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
Configuration::map_parameters (sigc::slot<void,const char*> theSlot)
|
Configuration::map_parameters (sigc::slot<void,const char*> theSlot)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,8 @@
|
||||||
#include <xmmintrin.h>
|
#include <xmmintrin.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <glibmm/fileutils.h>
|
||||||
|
|
||||||
#include <lrdf.h>
|
#include <lrdf.h>
|
||||||
|
|
||||||
#include <pbd/error.h>
|
#include <pbd/error.h>
|
||||||
|
|
@ -40,7 +42,6 @@
|
||||||
#include <pbd/fpu.h>
|
#include <pbd/fpu.h>
|
||||||
|
|
||||||
#include <midi++/port.h>
|
#include <midi++/port.h>
|
||||||
#include <midi++/port_request.h>
|
|
||||||
#include <midi++/manager.h>
|
#include <midi++/manager.h>
|
||||||
#include <midi++/mmc.h>
|
#include <midi++/mmc.h>
|
||||||
|
|
||||||
|
|
@ -110,29 +111,13 @@ setup_osc ()
|
||||||
static int
|
static int
|
||||||
setup_midi ()
|
setup_midi ()
|
||||||
{
|
{
|
||||||
std::map<string,Configuration::MidiPortDescriptor*>::iterator i;
|
|
||||||
|
|
||||||
if (Config->midi_ports.size() == 0) {
|
if (Config->midi_ports.size() == 0) {
|
||||||
warning << _("no MIDI ports specified: no MMC or MTC control possible") << endmsg;
|
warning << _("no MIDI ports specified: no MMC or MTC control possible") << endmsg;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = Config->midi_ports.begin(); i != Config->midi_ports.end(); ++i) {
|
for (std::map<string,XMLNode>::iterator i = Config->midi_ports.begin(); i != Config->midi_ports.end(); ++i) {
|
||||||
Configuration::MidiPortDescriptor* port_descriptor;
|
MIDI::Manager::instance()->add_port (i->second);
|
||||||
|
|
||||||
port_descriptor = (*i).second;
|
|
||||||
|
|
||||||
MIDI::PortRequest request (port_descriptor->device,
|
|
||||||
port_descriptor->tag,
|
|
||||||
port_descriptor->mode,
|
|
||||||
port_descriptor->type);
|
|
||||||
|
|
||||||
if (request.status != MIDI::PortRequest::OK) {
|
|
||||||
error << string_compose(_("MIDI port specifications for \"%1\" are not understandable."), port_descriptor->tag) << endmsg;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
MIDI::Manager::instance()->add_port (request);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MIDI::Port* first;
|
MIDI::Port* first;
|
||||||
|
|
@ -144,8 +129,6 @@ setup_midi ()
|
||||||
|
|
||||||
/* More than one port, so try using specific names for each port */
|
/* More than one port, so try using specific names for each port */
|
||||||
|
|
||||||
map<string,Configuration::MidiPortDescriptor *>::iterator i;
|
|
||||||
|
|
||||||
if (Config->get_mmc_port_name() != N_("default")) {
|
if (Config->get_mmc_port_name() != N_("default")) {
|
||||||
default_mmc_port = MIDI::Manager::instance()->port (Config->get_mmc_port_name());
|
default_mmc_port = MIDI::Manager::instance()->port (Config->get_mmc_port_name());
|
||||||
}
|
}
|
||||||
|
|
@ -443,7 +426,7 @@ find_file (string name, string dir, string subdir = "")
|
||||||
for (vector<string>::iterator i = split_path.begin(); i != split_path.end(); ++i) {
|
for (vector<string>::iterator i = split_path.begin(); i != split_path.end(); ++i) {
|
||||||
path = *i;
|
path = *i;
|
||||||
path += "/" + name;
|
path += "/" + name;
|
||||||
if (access (path.c_str(), R_OK) == 0) {
|
if (Glib::file_test (path, Glib::FILE_TEST_EXISTS)) {
|
||||||
// cerr << "Using file " << path << " found in ARDOUR_PATH." << endl;
|
// cerr << "Using file " << path << " found in ARDOUR_PATH." << endl;
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,7 @@
|
||||||
#include <pbd/error.h>
|
#include <pbd/error.h>
|
||||||
#include <pbd/pathscanner.h>
|
#include <pbd/pathscanner.h>
|
||||||
#include <pbd/xml++.h>
|
#include <pbd/xml++.h>
|
||||||
|
#include <pbd/stacktrace.h>
|
||||||
|
|
||||||
#include <ardour/ardour.h>
|
#include <ardour/ardour.h>
|
||||||
#include <ardour/session.h>
|
#include <ardour/session.h>
|
||||||
|
|
@ -112,7 +113,7 @@ Plugin::get_nth_control (uint32_t n, bool do_not_create)
|
||||||
Plugin::ParameterDescriptor desc;
|
Plugin::ParameterDescriptor desc;
|
||||||
|
|
||||||
get_parameter_descriptor (n, desc);
|
get_parameter_descriptor (n, desc);
|
||||||
|
|
||||||
controls[n] = new PortControllable (describe_parameter (n), *this, n,
|
controls[n] = new PortControllable (describe_parameter (n), *this, n,
|
||||||
desc.lower, desc.upper, desc.toggled, desc.logarithmic);
|
desc.lower, desc.upper, desc.toggled, desc.logarithmic);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,6 @@ midiparser.cc
|
||||||
midiport.cc
|
midiport.cc
|
||||||
mmc.cc
|
mmc.cc
|
||||||
mtc.cc
|
mtc.cc
|
||||||
port_request.cc
|
|
||||||
version.cc
|
version.cc
|
||||||
""")
|
""")
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -23,10 +23,12 @@
|
||||||
|
|
||||||
#include <pbd/failed_constructor.h>
|
#include <pbd/failed_constructor.h>
|
||||||
#include <pbd/error.h>
|
#include <pbd/error.h>
|
||||||
|
#include <pbd/xml++.h>
|
||||||
|
|
||||||
#include <midi++/types.h>
|
#include <midi++/types.h>
|
||||||
#include <midi++/alsa_sequencer.h>
|
#include <midi++/alsa_sequencer.h>
|
||||||
#include <midi++/port_request.h>
|
|
||||||
|
#include "i18n.h"
|
||||||
|
|
||||||
//#define DOTRACE 1
|
//#define DOTRACE 1
|
||||||
|
|
||||||
|
|
@ -44,31 +46,31 @@ using namespace PBD;
|
||||||
|
|
||||||
snd_seq_t* ALSA_SequencerMidiPort::seq = 0;
|
snd_seq_t* ALSA_SequencerMidiPort::seq = 0;
|
||||||
|
|
||||||
ALSA_SequencerMidiPort::ALSA_SequencerMidiPort (PortRequest &req)
|
ALSA_SequencerMidiPort::ALSA_SequencerMidiPort (const XMLNode& node)
|
||||||
: Port (req)
|
: Port (node)
|
||||||
, decoder (0)
|
, decoder (0)
|
||||||
, encoder (0)
|
, encoder (0)
|
||||||
, port_id (-1)
|
, port_id (-1)
|
||||||
{
|
{
|
||||||
TR_FN();
|
TR_FN();
|
||||||
int err;
|
int err;
|
||||||
|
Descriptor desc (node);
|
||||||
|
|
||||||
if (!seq && init_client (req.devname) < 0) {
|
if (!seq && init_client (desc.device) < 0) {
|
||||||
_ok = false;
|
_ok = false;
|
||||||
|
|
||||||
} else {
|
} 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 (1024, &decoder)) && // Length taken from ARDOUR::Session::midi_read ()
|
||||||
0 <= (err = snd_midi_event_new (64, &encoder))) { // Length taken from ARDOUR::Session::mmc_buffer
|
0 <= (err = snd_midi_event_new (64, &encoder))) { // Length taken from ARDOUR::Session::mmc_buffer
|
||||||
snd_midi_event_init (decoder);
|
snd_midi_event_init (decoder);
|
||||||
snd_midi_event_init (encoder);
|
snd_midi_event_init (encoder);
|
||||||
_ok = true;
|
_ok = true;
|
||||||
req.status = PortRequest::OK;
|
}
|
||||||
} else {
|
|
||||||
req.status = PortRequest::Unknown;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
set_state (node);
|
||||||
}
|
}
|
||||||
|
|
||||||
ALSA_SequencerMidiPort::~ALSA_SequencerMidiPort ()
|
ALSA_SequencerMidiPort::~ALSA_SequencerMidiPort ()
|
||||||
|
|
@ -160,17 +162,17 @@ ALSA_SequencerMidiPort::read (byte *buf, size_t max)
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
ALSA_SequencerMidiPort::CreatePorts (PortRequest &req)
|
ALSA_SequencerMidiPort::create_ports (const Port::Descriptor& desc)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
unsigned int caps = 0;
|
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;
|
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;
|
caps |= SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SUBS_READ;
|
||||||
|
|
||||||
if (0 <= (err = snd_seq_create_simple_port (seq, req.tagname, caps,
|
if (0 <= (err = snd_seq_create_simple_port (seq, desc.tag.c_str(), caps,
|
||||||
(SND_SEQ_PORT_TYPE_MIDI_GENERIC|
|
(SND_SEQ_PORT_TYPE_MIDI_GENERIC|
|
||||||
SND_SEQ_PORT_TYPE_SOFTWARE|
|
SND_SEQ_PORT_TYPE_SOFTWARE|
|
||||||
SND_SEQ_PORT_TYPE_APPLICATION)))) {
|
SND_SEQ_PORT_TYPE_APPLICATION)))) {
|
||||||
|
|
@ -259,23 +261,165 @@ ALSA_SequencerMidiPort::discover (vector<PortSet>& ports)
|
||||||
|
|
||||||
if (port_capability & SND_SEQ_PORT_CAP_READ) {
|
if (port_capability & SND_SEQ_PORT_CAP_READ) {
|
||||||
if (port_capability & SND_SEQ_PORT_CAP_WRITE) {
|
if (port_capability & SND_SEQ_PORT_CAP_WRITE) {
|
||||||
mode = "duplex";
|
mode = "duplex";
|
||||||
} else {
|
} else {
|
||||||
mode = "output";
|
mode = "output";
|
||||||
}
|
}
|
||||||
} else if (port_capability & SND_SEQ_PORT_CAP_WRITE) {
|
} else if (port_capability & SND_SEQ_PORT_CAP_WRITE) {
|
||||||
if (port_capability & SND_SEQ_PORT_CAP_READ) {
|
if (port_capability & SND_SEQ_PORT_CAP_READ) {
|
||||||
mode = "duplex";
|
mode = "duplex";
|
||||||
} else {
|
} else {
|
||||||
mode = "input";
|
mode = "input";
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
ports.back().ports.push_back (PortRequest (client, port, mode, "alsa/sequencer"));
|
|
||||||
++n;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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;
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,6 @@
|
||||||
|
|
||||||
#include <midi++/coremidi_midiport.h>
|
#include <midi++/coremidi_midiport.h>
|
||||||
#include <midi++/types.h>
|
#include <midi++/types.h>
|
||||||
#include <midi++/port_request.h>
|
|
||||||
#include <mach/mach_time.h>
|
#include <mach/mach_time.h>
|
||||||
|
|
||||||
#include <pbd/pthread_utils.h>
|
#include <pbd/pthread_utils.h>
|
||||||
|
|
@ -36,15 +35,15 @@ MIDITimeStamp CoreMidi_MidiPort::MIDIGetCurrentHostTime()
|
||||||
return mach_absolute_time();
|
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;
|
firstrecv = true;
|
||||||
int err;
|
int err;
|
||||||
if (0 == (err = Open(req))) {
|
if (0 == (err = Open(desc))) {
|
||||||
_ok = true;
|
_ok = true;
|
||||||
req.status = PortRequest::OK;
|
}
|
||||||
} else
|
|
||||||
req.status = PortRequest::Unknown;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CoreMidi_MidiPort::~CoreMidi_MidiPort () {Close();}
|
CoreMidi_MidiPort::~CoreMidi_MidiPort () {Close();}
|
||||||
|
|
@ -77,21 +76,21 @@ int CoreMidi_MidiPort::write (byte *msg, size_t msglen)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int CoreMidi_MidiPort::Open (PortRequest &req)
|
int CoreMidi_MidiPort::Open (const Descriptor& desc)
|
||||||
{
|
{
|
||||||
OSStatus err;
|
OSStatus err;
|
||||||
CFStringRef coutputStr;
|
CFStringRef coutputStr;
|
||||||
string str;
|
string str;
|
||||||
|
|
||||||
coutputStr = CFStringCreateWithCString(0, req.devname, CFStringGetSystemEncoding());
|
coutputStr = CFStringCreateWithCString(0, desc.device.c_str(), CFStringGetSystemEncoding());
|
||||||
err = MIDIClientCreate(coutputStr, 0, 0, &midi_client);
|
err = MIDIClientCreate(coutputStr, 0, 0, &midi_client);
|
||||||
CFRelease(coutputStr);
|
CFRelease(coutputStr);
|
||||||
if (!midi_client) {
|
if (!midi_client) {
|
||||||
//error << "Cannot open CoreMidi client : " << err << endmsg.
|
//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());
|
coutputStr = CFStringCreateWithCString(0, str.c_str(), CFStringGetSystemEncoding());
|
||||||
err = MIDIDestinationCreate(midi_client, coutputStr, read_proc, this, &midi_destination);
|
err = MIDIDestinationCreate(midi_client, coutputStr, read_proc, this, &midi_destination);
|
||||||
CFRelease(coutputStr);
|
CFRelease(coutputStr);
|
||||||
|
|
@ -100,7 +99,7 @@ int CoreMidi_MidiPort::Open (PortRequest &req)
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
str = req.tagname + string("_out");
|
str = desc.tag + string("_out");
|
||||||
coutputStr = CFStringCreateWithCString(0, str.c_str(), CFStringGetSystemEncoding());
|
coutputStr = CFStringCreateWithCString(0, str.c_str(), CFStringGetSystemEncoding());
|
||||||
err = MIDISourceCreate(midi_client, coutputStr, &midi_source);
|
err = MIDISourceCreate(midi_client, coutputStr, &midi_source);
|
||||||
CFRelease(coutputStr);
|
CFRelease(coutputStr);
|
||||||
|
|
|
||||||
|
|
@ -34,40 +34,38 @@ using namespace PBD;
|
||||||
string *FD_MidiPort::midi_dirpath = 0;
|
string *FD_MidiPort::midi_dirpath = 0;
|
||||||
string *FD_MidiPort::midi_filename_pattern = 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 &dirpath,
|
||||||
const string &pattern)
|
const string &pattern)
|
||||||
: Port (req)
|
: Port (node)
|
||||||
{
|
{
|
||||||
open (req);
|
Descriptor desc (node);
|
||||||
|
|
||||||
|
open (desc);
|
||||||
|
|
||||||
if (_fd < 0) {
|
if (_fd < 0) {
|
||||||
switch (errno) {
|
switch (errno) {
|
||||||
case EBUSY:
|
case EBUSY:
|
||||||
error << "MIDI: port device in use" << endmsg;
|
error << "MIDI: port device in use" << endmsg;
|
||||||
req.status = PortRequest::Busy;
|
|
||||||
break;
|
break;
|
||||||
case ENOENT:
|
case ENOENT:
|
||||||
error << "MIDI: no such port device" << endmsg;
|
error << "MIDI: no such port device" << endmsg;
|
||||||
req.status = PortRequest::NoSuchFile;
|
|
||||||
break;
|
break;
|
||||||
case EACCES:
|
case EACCES:
|
||||||
error << "MIDI: access to port denied" << endmsg;
|
error << "MIDI: access to port denied" << endmsg;
|
||||||
req.status = PortRequest::NotAllowed;
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
req.status = PortRequest::Unknown;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
_ok = true;
|
_ok = true;
|
||||||
req.status = PortRequest::OK;
|
|
||||||
|
|
||||||
if (midi_dirpath == 0) {
|
if (midi_dirpath == 0) {
|
||||||
midi_dirpath = new string (dirpath);
|
midi_dirpath = new string (dirpath);
|
||||||
midi_filename_pattern = new string (pattern);
|
midi_filename_pattern = new string (pattern);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (req.mode & O_NONBLOCK == 0) {
|
if (desc.mode & O_NONBLOCK == 0) {
|
||||||
/* we unconditionally set O_NONBLOCK during
|
/* we unconditionally set O_NONBLOCK during
|
||||||
open, but the request didn't ask for it,
|
open, but the request didn't ask for it,
|
||||||
so remove it.
|
so remove it.
|
||||||
|
|
@ -80,11 +78,11 @@ FD_MidiPort::FD_MidiPort (PortRequest &req,
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
FD_MidiPort::open (PortRequest &req)
|
FD_MidiPort::open (const Descriptor& desc)
|
||||||
|
|
||||||
{
|
{
|
||||||
int mode = req.mode | O_NONBLOCK;
|
int mode = desc.mode | O_NONBLOCK;
|
||||||
_fd = ::open (req.devname, mode);
|
_fd = ::open (desc.device.c_str(), mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
vector<string *> *
|
vector<string *> *
|
||||||
|
|
|
||||||
|
|
@ -26,19 +26,19 @@
|
||||||
|
|
||||||
using namespace MIDI;
|
using namespace MIDI;
|
||||||
|
|
||||||
FIFO_MidiPort::FIFO_MidiPort (PortRequest &req)
|
FIFO_MidiPort::FIFO_MidiPort (const XMLNode& node)
|
||||||
: FD_MidiPort (req, ".", "midi")
|
: FD_MidiPort (node, ".", "midi")
|
||||||
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
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
|
/* This is a placeholder for the fun-and-games I think we will
|
||||||
need to do with FIFO's.
|
need to do with FIFO's.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
_fd = ::open (req.devname, req.mode|O_NDELAY);
|
_fd = ::open (desc.device.c_str(), desc.mode|O_NDELAY);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -34,8 +34,8 @@ class ALSA_RawMidiPort : public MIDI::FD_MidiPort
|
||||||
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ALSA_RawMidiPort (MIDI::PortRequest &req)
|
ALSA_RawMidiPort (const XMLNode& node)
|
||||||
: FD_MidiPort (req, "/dev/snd", "midi") {}
|
: FD_MidiPort (node, "/dev/snd", "midi") {}
|
||||||
virtual ~ALSA_RawMidiPort () {}
|
virtual ~ALSA_RawMidiPort () {}
|
||||||
|
|
||||||
static std::string typestring;
|
static std::string typestring;
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,6 @@
|
||||||
|
|
||||||
#include <alsa/asoundlib.h>
|
#include <alsa/asoundlib.h>
|
||||||
#include <midi++/port.h>
|
#include <midi++/port.h>
|
||||||
#include <midi++/port_request.h>
|
|
||||||
|
|
||||||
namespace MIDI {
|
namespace MIDI {
|
||||||
|
|
||||||
|
|
@ -35,7 +34,7 @@ class ALSA_SequencerMidiPort : public Port
|
||||||
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ALSA_SequencerMidiPort (PortRequest &req);
|
ALSA_SequencerMidiPort (const XMLNode&);
|
||||||
virtual ~ALSA_SequencerMidiPort ();
|
virtual ~ALSA_SequencerMidiPort ();
|
||||||
|
|
||||||
/* select(2)/poll(2)-based I/O */
|
/* select(2)/poll(2)-based I/O */
|
||||||
|
|
@ -45,6 +44,9 @@ class ALSA_SequencerMidiPort : public Port
|
||||||
static int discover (std::vector<PortSet>&);
|
static int discover (std::vector<PortSet>&);
|
||||||
static std::string typestring;
|
static std::string typestring;
|
||||||
|
|
||||||
|
XMLNode& get_state() const;
|
||||||
|
void set_state (const XMLNode&);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/* Direct I/O */
|
/* Direct I/O */
|
||||||
|
|
||||||
|
|
@ -60,10 +62,13 @@ class ALSA_SequencerMidiPort : public Port
|
||||||
int port_id;
|
int port_id;
|
||||||
snd_seq_event_t SEv;
|
snd_seq_event_t SEv;
|
||||||
|
|
||||||
int CreatePorts(PortRequest &req);
|
int create_ports (const Port::Descriptor&);
|
||||||
|
|
||||||
static int init_client (std::string name);
|
static int init_client (std::string name);
|
||||||
static snd_seq_t* seq;
|
static snd_seq_t* seq;
|
||||||
|
|
||||||
|
typedef std::pair<int,int> SequencerPortAddress;
|
||||||
|
void get_connections (std::vector<SequencerPortAddress>&, int dir) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
}; /* namespace MIDI */
|
}; /* namespace MIDI */
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,6 @@
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include <midi++/port.h>
|
#include <midi++/port.h>
|
||||||
#include <midi++/port_request.h>
|
|
||||||
|
|
||||||
#include <CoreMIDI/CoreMIDI.h>
|
#include <CoreMIDI/CoreMIDI.h>
|
||||||
|
|
||||||
|
|
@ -36,7 +35,7 @@ namespace MIDI {
|
||||||
|
|
||||||
class CoreMidi_MidiPort:public Port {
|
class CoreMidi_MidiPort:public Port {
|
||||||
public:
|
public:
|
||||||
CoreMidi_MidiPort(PortRequest & req);
|
CoreMidi_MidiPort(const XMLNode& node);
|
||||||
virtual ~ CoreMidi_MidiPort();
|
virtual ~ CoreMidi_MidiPort();
|
||||||
|
|
||||||
virtual int selectable() const {
|
virtual int selectable() const {
|
||||||
|
|
@ -68,7 +67,7 @@ namespace MIDI {
|
||||||
MIDIEndpointRef midi_destination;
|
MIDIEndpointRef midi_destination;
|
||||||
MIDIEndpointRef midi_source;
|
MIDIEndpointRef midi_source;
|
||||||
|
|
||||||
int Open(PortRequest & req);
|
int Open(const Port::Descriptor&);
|
||||||
void Close();
|
void Close();
|
||||||
static MIDITimeStamp MIDIGetCurrentHostTime();
|
static MIDITimeStamp MIDIGetCurrentHostTime();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -23,13 +23,12 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include <midi++/port.h>
|
#include <midi++/port.h>
|
||||||
#include <midi++/port_request.h>
|
|
||||||
|
|
||||||
namespace MIDI {
|
namespace MIDI {
|
||||||
|
|
||||||
class PortFactory {
|
class PortFactory {
|
||||||
public:
|
public:
|
||||||
Port *create_port (PortRequest &req);
|
Port *create_port (const XMLNode&);
|
||||||
|
|
||||||
static bool ignore_duplicate_devices (Port::Type);
|
static bool ignore_duplicate_devices (Port::Type);
|
||||||
static int get_known_ports (std::vector<PortSet>&);
|
static int get_known_ports (std::vector<PortSet>&);
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,6 @@
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include <midi++/port.h>
|
#include <midi++/port.h>
|
||||||
#include <midi++/port_request.h>
|
|
||||||
|
|
||||||
namespace MIDI {
|
namespace MIDI {
|
||||||
|
|
||||||
|
|
@ -37,7 +36,7 @@ class FD_MidiPort : public Port
|
||||||
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
FD_MidiPort (PortRequest &req,
|
FD_MidiPort (const XMLNode& node,
|
||||||
const std::string &dirpath,
|
const std::string &dirpath,
|
||||||
const std::string &pattern);
|
const std::string &pattern);
|
||||||
|
|
||||||
|
|
@ -51,7 +50,7 @@ class FD_MidiPort : public Port
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
int _fd;
|
int _fd;
|
||||||
virtual void open (PortRequest &req);
|
virtual void open (const Port::Descriptor&);
|
||||||
|
|
||||||
virtual int write (byte *msg, size_t msglen) {
|
virtual int write (byte *msg, size_t msglen) {
|
||||||
int nwritten;
|
int nwritten;
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,6 @@
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include <midi++/port.h>
|
#include <midi++/port.h>
|
||||||
#include <midi++/port_request.h>
|
|
||||||
#include <midi++/fd_midiport.h>
|
#include <midi++/fd_midiport.h>
|
||||||
|
|
||||||
namespace MIDI {
|
namespace MIDI {
|
||||||
|
|
@ -34,7 +33,7 @@ class FIFO_MidiPort : public MIDI::FD_MidiPort
|
||||||
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
FIFO_MidiPort (PortRequest &req);
|
FIFO_MidiPort (const XMLNode&);
|
||||||
~FIFO_MidiPort () {};
|
~FIFO_MidiPort () {};
|
||||||
|
|
||||||
static std::string typestring;
|
static std::string typestring;
|
||||||
|
|
@ -45,7 +44,7 @@ class FIFO_MidiPort : public MIDI::FD_MidiPort
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void open (PortRequest &req);
|
void open (const Port::Descriptor&);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace MIDI
|
} // namespace MIDI
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,6 @@
|
||||||
|
|
||||||
#include <midi++/types.h>
|
#include <midi++/types.h>
|
||||||
#include <midi++/port.h>
|
#include <midi++/port.h>
|
||||||
#include <midi++/port_request.h>
|
|
||||||
|
|
||||||
namespace MIDI {
|
namespace MIDI {
|
||||||
|
|
||||||
|
|
@ -35,7 +34,7 @@ class Manager {
|
||||||
public:
|
public:
|
||||||
~Manager ();
|
~Manager ();
|
||||||
|
|
||||||
Port *add_port (PortRequest &);
|
Port *add_port (const XMLNode& node);
|
||||||
int remove_port (Port*);
|
int remove_port (Port*);
|
||||||
|
|
||||||
Port *port (std::string name);
|
Port *port (std::string name);
|
||||||
|
|
@ -68,8 +67,6 @@ class Manager {
|
||||||
return theManager;
|
return theManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int parse_port_request (std::string str, Port::Type type);
|
|
||||||
|
|
||||||
int get_known_ports (std::vector<PortSet>&);
|
int get_known_ports (std::vector<PortSet>&);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,6 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include <midi++/port.h>
|
#include <midi++/port.h>
|
||||||
#include <midi++/port_request.h>
|
|
||||||
|
|
||||||
namespace MIDI {
|
namespace MIDI {
|
||||||
|
|
||||||
|
|
@ -32,8 +31,8 @@ class Null_MidiPort : public Port
|
||||||
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Null_MidiPort (PortRequest &req)
|
Null_MidiPort (const XMLNode& node)
|
||||||
: Port (req) {
|
: Port (node) {
|
||||||
|
|
||||||
/* reset devname and tagname */
|
/* reset devname and tagname */
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -23,12 +23,11 @@
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
#include <sigc++/sigc++.h>
|
#include <sigc++/sigc++.h>
|
||||||
|
#include <pbd/xml++.h>
|
||||||
|
|
||||||
#include <midi++/types.h>
|
#include <midi++/types.h>
|
||||||
#include <midi++/parser.h>
|
#include <midi++/parser.h>
|
||||||
|
|
||||||
class XMLNode;
|
|
||||||
|
|
||||||
namespace MIDI {
|
namespace MIDI {
|
||||||
|
|
||||||
class Channel;
|
class Channel;
|
||||||
|
|
@ -46,10 +45,11 @@ class Port : public sigc::trackable {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
Port (PortRequest &);
|
Port (const XMLNode&);
|
||||||
virtual ~Port ();
|
virtual ~Port ();
|
||||||
|
|
||||||
virtual XMLNode& get_state () const;
|
virtual XMLNode& get_state () const;
|
||||||
|
virtual void set_state (const XMLNode&);
|
||||||
|
|
||||||
/* Direct I/O */
|
/* Direct I/O */
|
||||||
|
|
||||||
|
|
@ -124,6 +124,16 @@ class Port : public sigc::trackable {
|
||||||
int mode () const { return _mode; }
|
int mode () const { return _mode; }
|
||||||
bool ok () const { return _ok; }
|
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:
|
protected:
|
||||||
bool _ok;
|
bool _ok;
|
||||||
Type _type;
|
Type _type;
|
||||||
|
|
@ -144,6 +154,13 @@ class Port : public sigc::trackable {
|
||||||
static size_t nports;
|
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 );
|
std::ostream & operator << ( std::ostream & os, const Port & port );
|
||||||
|
|
||||||
} // namespace MIDI
|
} // namespace MIDI
|
||||||
|
|
|
||||||
|
|
@ -1,67 +0,0 @@
|
||||||
/*
|
|
||||||
Copyright (C) 1999-2007 Paul 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 <list>
|
|
||||||
#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__
|
|
||||||
|
|
||||||
|
|
@ -52,43 +52,40 @@ using namespace MIDI;
|
||||||
using namespace PBD;
|
using namespace PBD;
|
||||||
|
|
||||||
Port *
|
Port *
|
||||||
PortFactory::create_port (PortRequest &req)
|
PortFactory::create_port (const XMLNode& node)
|
||||||
|
|
||||||
{
|
{
|
||||||
|
Port::Descriptor desc (node);
|
||||||
Port *port;
|
Port *port;
|
||||||
|
|
||||||
switch (req.type) {
|
switch (desc.type) {
|
||||||
#ifdef WITH_ALSA
|
#ifdef WITH_ALSA
|
||||||
case Port::ALSA_RawMidi:
|
case Port::ALSA_RawMidi:
|
||||||
port = new ALSA_RawMidiPort (req);
|
port = new ALSA_RawMidiPort (node);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Port::ALSA_Sequencer:
|
case Port::ALSA_Sequencer:
|
||||||
port = new ALSA_SequencerMidiPort (req);
|
port = new ALSA_SequencerMidiPort (node);
|
||||||
break;
|
break;
|
||||||
#endif // WITH_ALSA
|
#endif // WITH_ALSA
|
||||||
|
|
||||||
#if WITH_COREMIDI
|
#if WITH_COREMIDI
|
||||||
case Port::CoreMidi_MidiPort:
|
case Port::CoreMidi_MidiPort:
|
||||||
port = new CoreMidi_MidiPort (req);
|
port = new CoreMidi_MidiPort (node);
|
||||||
break;
|
break;
|
||||||
#endif // WITH_COREMIDI
|
#endif // WITH_COREMIDI
|
||||||
|
|
||||||
case Port::Null:
|
case Port::Null:
|
||||||
port = new Null_MidiPort (req);
|
port = new Null_MidiPort (node);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Port::FIFO:
|
case Port::FIFO:
|
||||||
port = new FIFO_MidiPort (req);
|
port = new FIFO_MidiPort (node);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
req.status = PortRequest::TypeUnsupported;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
req.status = PortRequest::OK;
|
|
||||||
|
|
||||||
return port;
|
return port;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,6 @@
|
||||||
#include <midi++/manager.h>
|
#include <midi++/manager.h>
|
||||||
#include <midi++/factory.h>
|
#include <midi++/factory.h>
|
||||||
#include <midi++/channel.h>
|
#include <midi++/channel.h>
|
||||||
#include <midi++/port_request.h>
|
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace MIDI;
|
using namespace MIDI;
|
||||||
|
|
@ -64,27 +63,27 @@ Manager::~Manager ()
|
||||||
}
|
}
|
||||||
|
|
||||||
Port *
|
Port *
|
||||||
Manager::add_port (PortRequest &req)
|
Manager::add_port (const XMLNode& node)
|
||||||
|
|
||||||
{
|
{
|
||||||
|
Port::Descriptor desc (node);
|
||||||
PortFactory factory;
|
PortFactory factory;
|
||||||
Port *port;
|
Port *port;
|
||||||
PortMap::iterator existing;
|
PortMap::iterator existing;
|
||||||
pair<string, Port *> newpair;
|
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;
|
port = (*existing).second;
|
||||||
|
|
||||||
if (port->mode() == req.mode) {
|
if (port->mode() == desc.mode) {
|
||||||
|
|
||||||
/* Same mode - reuse the port, and just
|
/* Same mode - reuse the port, and just
|
||||||
create a new tag entry.
|
create a new tag entry.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
newpair.first = req.tagname;
|
newpair.first = desc.tag;
|
||||||
newpair.second = port;
|
newpair.second = port;
|
||||||
|
|
||||||
ports_by_tag.insert (newpair);
|
ports_by_tag.insert (newpair);
|
||||||
|
|
@ -97,10 +96,10 @@ Manager::add_port (PortRequest &req)
|
||||||
operation.
|
operation.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if ((req.mode == O_RDWR && port->mode() != O_RDWR) ||
|
if ((desc.mode == O_RDWR && port->mode() != O_RDWR) ||
|
||||||
(req.mode != O_RDWR && port->mode() == O_RDWR)) {
|
(desc.mode != O_RDWR && port->mode() == O_RDWR)) {
|
||||||
error << "MIDIManager: port tagged \""
|
error << "MIDIManager: port tagged \""
|
||||||
<< req.tagname
|
<< desc.tag
|
||||||
<< "\" cannot be opened duplex and non-duplex"
|
<< "\" cannot be opened duplex and non-duplex"
|
||||||
<< endmsg;
|
<< endmsg;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -110,7 +109,7 @@ Manager::add_port (PortRequest &req)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
port = factory.create_port (req);
|
port = factory.create_port (node);
|
||||||
|
|
||||||
if (port == 0) {
|
if (port == 0) {
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -262,90 +261,6 @@ Manager::foreach_port (int (*func)(const Port &, size_t, void *),
|
||||||
return 0;
|
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;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Port specifications look like:
|
|
||||||
|
|
||||||
devicename
|
|
||||||
devicename:tagname
|
|
||||||
devicename:tagname:mode
|
|
||||||
|
|
||||||
where
|
|
||||||
|
|
||||||
"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.
|
|
||||||
|
|
||||||
"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 (':');
|
|
||||||
|
|
||||||
if (colon != string::npos) {
|
|
||||||
req->devname = strdup (str.substr (0, colon).c_str());
|
|
||||||
} else {
|
|
||||||
req->devname = strdup (str.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (colon < str.length()) {
|
|
||||||
|
|
||||||
tag = str.substr (colon+1);
|
|
||||||
|
|
||||||
/* see if there is a mode specification in the tag part */
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
req->tagname = strdup (tag.c_str());
|
|
||||||
req->mode = O_RDWR;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
// check when tagname is freed
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
int
|
||||||
Manager::get_known_ports (vector<PortSet>& ports)
|
Manager::get_known_ports (vector<PortSet>& ports)
|
||||||
|
|
|
||||||
|
|
@ -17,26 +17,27 @@
|
||||||
|
|
||||||
$Id$
|
$Id$
|
||||||
*/
|
*/
|
||||||
|
#include <iostream>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
|
||||||
#include <pbd/xml++.h>
|
#include <pbd/xml++.h>
|
||||||
|
#include <pbd/failed_constructor.h>
|
||||||
|
|
||||||
#include <midi++/types.h>
|
#include <midi++/types.h>
|
||||||
#include <midi++/port.h>
|
#include <midi++/port.h>
|
||||||
#include <midi++/channel.h>
|
#include <midi++/channel.h>
|
||||||
#include <midi++/port_request.h>
|
|
||||||
#include <midi++/factory.h>
|
#include <midi++/factory.h>
|
||||||
|
|
||||||
//using namespace Select;
|
|
||||||
using namespace MIDI;
|
using namespace MIDI;
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
size_t Port::nports = 0;
|
size_t Port::nports = 0;
|
||||||
|
|
||||||
Port::Port (PortRequest &req)
|
Port::Port (const XMLNode& node)
|
||||||
|
|
||||||
{
|
{
|
||||||
|
Descriptor desc (node);
|
||||||
|
|
||||||
_ok = false; /* derived class must set to true if constructor
|
_ok = false; /* derived class must set to true if constructor
|
||||||
succeeds.
|
succeeds.
|
||||||
*/
|
*/
|
||||||
|
|
@ -47,9 +48,9 @@ Port::Port (PortRequest &req)
|
||||||
output_parser = 0;
|
output_parser = 0;
|
||||||
slowdown = 0;
|
slowdown = 0;
|
||||||
|
|
||||||
_devname = req.devname;
|
_devname = desc.device;
|
||||||
_tagname = req.tagname;
|
_tagname = desc.tag;
|
||||||
_mode = req.mode;
|
_mode = desc.mode;
|
||||||
|
|
||||||
if (_mode == O_RDONLY || _mode == O_RDWR) {
|
if (_mode == O_RDONLY || _mode == O_RDWR) {
|
||||||
input_parser = new Parser (*this);
|
input_parser = new Parser (*this);
|
||||||
|
|
@ -97,6 +98,12 @@ Port::get_state () const
|
||||||
return *node;
|
return *node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Port::set_state (const XMLNode& node)
|
||||||
|
{
|
||||||
|
// relax
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
Port::clock ()
|
Port::clock ()
|
||||||
|
|
||||||
|
|
@ -163,3 +170,36 @@ std::ostream & MIDI::operator << ( std::ostream & os, const MIDI::Port & port )
|
||||||
return 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,6 @@ Transmitter fatal (Transmitter::Fatal);
|
||||||
TextReceiver text_receiver ("mmctest");
|
TextReceiver text_receiver ("mmctest");
|
||||||
|
|
||||||
#include "midi++/port.h"
|
#include "midi++/port.h"
|
||||||
#include "midi++/port_request.h"
|
|
||||||
#include "midi++/manager.h"
|
#include "midi++/manager.h"
|
||||||
|
|
||||||
using namespace MIDI;
|
using namespace MIDI;
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,6 @@ Transmitter fatal (Transmitter::Fatal);
|
||||||
TextReceiver text_receiver ("mmctest");
|
TextReceiver text_receiver ("mmctest");
|
||||||
|
|
||||||
#include "midi++/port.h"
|
#include "midi++/port.h"
|
||||||
#include "midi++/port_request.h"
|
|
||||||
#include "midi++/manager.h"
|
#include "midi++/manager.h"
|
||||||
#include "midi++/mmc.h"
|
#include "midi++/mmc.h"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,41 +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 <midi++/port.h>
|
|
||||||
#include <midi++/port_request.h>
|
|
||||||
#include <midi++/factory.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());
|
|
||||||
mode = PortFactory::string_to_mode (xmode);
|
|
||||||
type = PortFactory::string_to_type (xtype);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -24,7 +24,6 @@
|
||||||
|
|
||||||
#include <midi++/port.h>
|
#include <midi++/port.h>
|
||||||
#include <midi++/manager.h>
|
#include <midi++/manager.h>
|
||||||
#include <midi++/port_request.h>
|
|
||||||
|
|
||||||
#include <ardour/route.h>
|
#include <ardour/route.h>
|
||||||
#include <ardour/session.h>
|
#include <ardour/session.h>
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,6 @@
|
||||||
#include <midi++/types.h>
|
#include <midi++/types.h>
|
||||||
#include <midi++/port.h>
|
#include <midi++/port.h>
|
||||||
#include <midi++/manager.h>
|
#include <midi++/manager.h>
|
||||||
#include <midi++/port_request.h>
|
|
||||||
#include "i18n.h"
|
#include "i18n.h"
|
||||||
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue