#include "midi++/types.h"
#include "midi++/manager.h"
-#include "midi++/factory.h"
#include "midi++/channel.h"
+#include "midi++/port.h"
+#include "midi++/mmc.h"
using namespace std;
using namespace MIDI;
using namespace PBD;
-/* XXX check for strdup leaks */
-
Manager *Manager::theManager = 0;
-Manager::Manager ()
+Manager::Manager (jack_client_t* jack)
{
- inputPort = 0;
- outputPort = 0;
- inputChannelNumber = 0;
- outputChannelNumber = 0;
- api_data = 0;
+ _mmc = new MachineControl (this, jack);
+
+ _mtc_input_port = add_port (new MIDI::Port ("MTC in", Port::IsInput, jack));
+ _mtc_output_port = add_port (new MIDI::Port ("MTC out", Port::IsOutput, jack));
+ _midi_input_port = add_port (new MIDI::Port ("MIDI control in", Port::IsInput, jack));
+ _midi_output_port = add_port (new MIDI::Port ("MIDI control out", Port::IsOutput, jack));
+ _midi_clock_input_port = add_port (new MIDI::Port ("MIDI clock in", Port::IsInput, jack));
+ _midi_clock_output_port = add_port (new MIDI::Port ("MIDI clock out", Port::IsOutput, jack));
}
Manager::~Manager ()
{
- PortMap::iterator i;
-
- for (i = ports_by_device.begin(); i != ports_by_device.end(); i++) {
- delete (*i).second;
+ delete _mmc;
+
+ /* This will delete our MTC etc. ports */
+ for (PortList::iterator p = _ports.begin(); p != _ports.end(); ++p) {
+ delete *p;
}
- ports_by_device.erase (ports_by_device.begin(), ports_by_device.end());
- ports_by_tag.erase (ports_by_tag.begin(), ports_by_tag.end());
-
if (theManager == this) {
theManager = 0;
}
}
Port *
-Manager::add_port (const XMLNode& node)
+Manager::add_port (Port* p)
{
- Port::Descriptor desc (node);
- PortFactory factory;
- Port *port;
- PortMap::iterator existing;
- pair<string, Port *> newpair;
-
- if ((existing = ports_by_tag.find (desc.tag)) != ports_by_tag.end()) {
-
- port = (*existing).second;
-
- if (port->mode() == desc.mode) {
-
- /* Same mode - reuse the port, and just
- create a new tag entry.
- */
-
- newpair.first = desc.tag;
- newpair.second = port;
-
- ports_by_tag.insert (newpair);
- return port;
- }
-
- /* If the existing is duplex, and this request
- is not, then fail, because most drivers won't
- allow opening twice with duplex and non-duplex
- operation.
- */
-
- if ((desc.mode == O_RDWR && port->mode() != O_RDWR) ||
- (desc.mode != O_RDWR && port->mode() == O_RDWR)) {
- error << "MIDIManager: port tagged \""
- << desc.tag
- << "\" cannot be opened duplex and non-duplex"
- << endmsg;
- return 0;
- }
-
- /* modes must be different or complementary */
- }
-
- if (!PortFactory::ignore_duplicate_devices (desc.type)) {
+ _ports.push_back (p);
- if ((existing = ports_by_device.find (desc.device)) != ports_by_device.end()) {
-
- port = (*existing).second;
-
- if (port->mode() == desc.mode) {
-
- /* Same mode - reuse the port, and just
- create a new tag entry.
- */
-
- newpair.first = desc.tag;
- newpair.second = port;
-
- ports_by_tag.insert (newpair);
- return port;
- }
-
- /* If the existing is duplex, and this request
- is not, then fail, because most drivers won't
- allow opening twice with duplex and non-duplex
- operation.
- */
-
- if ((desc.mode == O_RDWR && port->mode() != O_RDWR) ||
- (desc.mode != O_RDWR && port->mode() == O_RDWR)) {
- error << "MIDIManager: port tagged \""
- << desc.tag
- << "\" cannot be opened duplex and non-duplex"
- << endmsg;
- return 0;
- }
-
- /* modes must be different or complementary */
- }
- }
-
- port = factory.create_port (node, api_data);
-
-
- if (port == 0) {
- return 0;
- }
+ PortsChanged (); /* EMIT SIGNAL */
- if (!port->ok()) {
- delete port;
- return 0;
- }
-
- newpair.first = port->name();
- newpair.second = port;
- ports_by_tag.insert (newpair);
-
- newpair.first = port->device();
- 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;
+ return p;
}
-int
-Manager::remove_port (Port* port)
+void
+Manager::cycle_start (pframes_t nframes)
{
- PortMap::iterator res;
-
- for (res = ports_by_device.begin(); res != ports_by_device.end(); ) {
- PortMap::iterator tmp;
- tmp = res;
- ++tmp;
- if (res->second == port) {
- ports_by_device.erase (res);
- }
- res = tmp;
- }
-
-
- for (res = ports_by_tag.begin(); res != ports_by_tag.end(); ) {
- PortMap::iterator tmp;
- tmp = res;
- ++tmp;
- if (res->second == port) {
- ports_by_tag.erase (res);
- }
- res = tmp;
+ for (PortList::iterator p = _ports.begin(); p != _ports.end(); ++p) {
+ (*p)->cycle_start (nframes);
}
-
- delete port;
-
- return 0;
}
-int
-Manager::set_input_port (string tag)
+void
+Manager::cycle_end()
{
- PortMap::iterator res;
- bool found = false;
-
- for (res = ports_by_tag.begin(); res != ports_by_tag.end(); res++) {
- if (tag == (*res).first) {
- found = true;
- break;
- }
- }
-
- if (!found) {
- return -1;
+ for (PortList::iterator p = _ports.begin(); p != _ports.end(); ++p) {
+ (*p)->cycle_end ();
}
-
- inputPort = (*res).second;
-
- return 0;
}
-int
-Manager::set_output_port (string tag)
-
+/** Re-register ports that disappear on JACK shutdown */
+void
+Manager::reestablish (jack_client_t* jack)
{
- PortMap::iterator res;
- bool found = false;
-
- for (res = ports_by_tag.begin(); res != ports_by_tag.end(); res++) {
- if (tag == (*res).first) {
- found = true;
- break;
- }
- }
-
- if (!found) {
- return -1;
- }
-
- // XXX send a signal to say we're about to change output ports
-
- if (outputPort) {
- for (channel_t chan = 0; chan < 16; chan++) {
- outputPort->channel (chan)->all_notes_off (0);
- }
+ for (PortList::const_iterator p = _ports.begin(); p != _ports.end(); ++p) {
+ (*p)->reestablish (jack);
}
- outputPort = (*res).second;
-
- // XXX send a signal to say we've changed output ports
-
- return 0;
}
-Port *
-Manager::port (string name)
+/** Re-connect ports after a reestablish () */
+void
+Manager::reconnect ()
{
- PortMap::iterator res;
-
- for (res = ports_by_tag.begin(); res != ports_by_tag.end(); res++) {
- if (name == (*res).first) {
- return (*res).second;
- }
+ for (PortList::const_iterator p = _ports.begin(); p != _ports.end(); ++p) {
+ (*p)->reconnect ();
}
-
- return 0;
}
-int
-Manager::foreach_port (int (*func)(const Port &, size_t, void *),
- void *arg)
+Port*
+Manager::port (string const & n)
{
- PortMap::const_iterator i;
- int retval;
- int n;
-
- for (n = 0, i = ports_by_device.begin();
- i != ports_by_device.end(); i++, n++) {
+ PortList::const_iterator p = _ports.begin();
+ while (p != _ports.end() && (*p)->name() != n) {
+ ++p;
+ }
- if ((retval = func (*((*i).second), n, arg)) != 0) {
- return retval;
- }
+ if (p == _ports.end()) {
+ return 0;
}
- return 0;
+ return *p;
}
void
-Manager::cycle_start(nframes_t nframes)
+Manager::create (jack_client_t* jack)
{
- for (PortMap::iterator i = ports_by_device.begin(); i != ports_by_device.end(); i++) {
- (*i).second->cycle_start (nframes);
- }
+ assert (theManager == 0);
+ theManager = new Manager (jack);
}
void
-Manager::cycle_end()
+Manager::set_port_states (list<XMLNode*> s)
{
- for (PortMap::iterator i = ports_by_device.begin(); i != ports_by_device.end(); i++) {
- (*i).second->cycle_end ();
+ for (list<XMLNode*>::iterator i = s.begin(); i != s.end(); ++i) {
+ for (PortList::const_iterator j = _ports.begin(); j != _ports.end(); ++j) {
+ (*j)->set_state (**i);
+ }
}
}
-
-
-int
-Manager::get_known_ports (vector<PortSet>& ports)
-{
- return PortFactory::get_known_ports (ports);
-}