X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fmidi%2B%2B2%2Fmanager.cc;h=822c74e1254ae1d5d48daebfe59345c78d3807d4;hb=daffec502e634b812b306f6dce60955ed5b2a467;hp=ab37073afd59d9e2f4dafacb863b6689b9c0d6cd;hpb=498dfebcca3b97cdd7b83444040042fe06626241;p=ardour.git diff --git a/libs/midi++2/manager.cc b/libs/midi++2/manager.cc index ab37073afd..822c74e125 100644 --- a/libs/midi++2/manager.cc +++ b/libs/midi++2/manager.cc @@ -25,296 +25,159 @@ #include "midi++/types.h" #include "midi++/manager.h" -#include "midi++/factory.h" #include "midi++/channel.h" +#include "midi++/port.h" +#include "midi++/jack_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) + : _ports (new PortList) { - inputPort = 0; - outputPort = 0; - inputChannelNumber = 0; - outputChannelNumber = 0; - api_data = 0; + _mmc = new MachineControl (this, jack); + + _mtc_input_port = add_port (new MIDI::JackMIDIPort ("MTC in", Port::IsInput, jack)); + _mtc_output_port = add_port (new MIDI::JackMIDIPort ("MTC out", Port::IsOutput, jack)); + _midi_input_port = add_port (new MIDI::JackMIDIPort ("MIDI control in", Port::IsInput, jack)); + _midi_output_port = add_port (new MIDI::JackMIDIPort ("MIDI control out", Port::IsOutput, jack)); + _midi_clock_input_port = add_port (new MIDI::JackMIDIPort ("MIDI clock in", Port::IsInput, jack)); + _midi_clock_output_port = add_port (new MIDI::JackMIDIPort ("MIDI clock out", Port::IsOutput, jack)); } Manager::~Manager () { - PortMap::iterator i; + delete _mmc; + + /* This will delete our MTC etc. ports */ - for (i = ports_by_device.begin(); i != ports_by_device.end(); i++) { - delete (*i).second; + boost::shared_ptr pr = _ports.reader (); + for (PortList::iterator p = pr->begin(); p != pr->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 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 */ + { + RCUWriter writer (_ports); + boost::shared_ptr pw = writer.get_copy (); + pw->push_back (p); } - if (!PortFactory::ignore_duplicate_devices (desc.type)) { - - 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::remove_port (Port* p) { - 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; + { + RCUWriter writer (_ports); + boost::shared_ptr pw = writer.get_copy (); + pw->remove (p); } - - 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; - } - - delete port; - - return 0; + PortsChanged (); /* EMIT SIGNAL */ } -int -Manager::set_input_port (string tag) +void +Manager::cycle_start (pframes_t nframes) { - 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; - } - } + boost::shared_ptr pr = _ports.reader (); - if (!found) { - return -1; + for (PortList::iterator p = pr->begin(); p != pr->end(); ++p) { + (*p)->cycle_start (nframes); } - - inputPort = (*res).second; - - return 0; } -int -Manager::set_output_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; - } - } + boost::shared_ptr pr = _ports.reader (); - if (!found) { - return -1; + for (PortList::iterator p = pr->begin(); p != pr->end(); ++p) { + (*p)->cycle_end (); } +} - // XXX send a signal to say we're about to change output ports +/** Re-register ports that disappear on JACK shutdown */ +void +Manager::reestablish (jack_client_t* jack) +{ + boost::shared_ptr pr = _ports.reader (); - if (outputPort) { - for (channel_t chan = 0; chan < 16; chan++) { - outputPort->channel (chan)->all_notes_off (0); + for (PortList::const_iterator p = pr->begin(); p != pr->end(); ++p) { + JackMIDIPort* pp = dynamic_cast (*p); + if (pp) { + pp->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; + boost::shared_ptr pr = _ports.reader (); - for (res = ports_by_tag.begin(); res != ports_by_tag.end(); res++) { - if (name == (*res).first) { - return (*res).second; + for (PortList::const_iterator p = pr->begin(); p != pr->end(); ++p) { + JackMIDIPort* pp = dynamic_cast (*p); + if (pp) { + pp->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++) { + boost::shared_ptr pr = _ports.reader (); + + PortList::const_iterator p = pr->begin(); + while (p != pr->end() && (*p)->name() != n) { + ++p; + } - if ((retval = func (*((*i).second), n, arg)) != 0) { - return retval; - } + if (p == pr->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 s) { - for (PortMap::iterator i = ports_by_device.begin(); i != ports_by_device.end(); i++) { - (*i).second->cycle_end (); + boost::shared_ptr pr = _ports.reader (); + + for (list::iterator i = s.begin(); i != s.end(); ++i) { + for (PortList::const_iterator j = pr->begin(); j != pr->end(); ++j) { + (*j)->set_state (**i); + } } } - -int -Manager::get_known_ports (vector& ports) +void +Manager::destroy () { - return PortFactory::get_known_ports (ports); + delete theManager; + theManager = 0; }