X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fsurfaces%2Fmackie%2Fsurface_port.cc;h=013a0019c7e797ef9982df56412a07cd8a7fbc94;hb=2b9421fd391efcddde0be3397cb66e19b744a155;hp=77d71b1a6add74e2cfc6d4121863d180eaf642be;hpb=b31400207efae605c135ce9d7e2af31305f04da6;p=ardour.git diff --git a/libs/surfaces/mackie/surface_port.cc b/libs/surfaces/mackie/surface_port.cc index 77d71b1a6a..013a0019c7 100644 --- a/libs/surfaces/mackie/surface_port.cc +++ b/libs/surfaces/mackie/surface_port.cc @@ -23,84 +23,121 @@ #include #include +#include "pbd/failed_constructor.h" + #include "midi++/types.h" -#include "midi++/port.h" -#include "midi++/jack_midi_port.h" #include "midi++/ipmidi_port.h" -#include "midi++/manager.h" +#include "ardour/async_midi_port.h" #include "ardour/debug.h" #include "ardour/rc_configuration.h" #include "ardour/session.h" #include "ardour/audioengine.h" +#include "ardour/async_midi_port.h" +#include "ardour/midiport_manager.h" #include "controls.h" #include "mackie_control_protocol.h" #include "surface.h" #include "surface_port.h" - #include "i18n.h" using namespace std; using namespace Mackie; using namespace PBD; +using namespace ARDOUR; -/** @param input_port Input MIDI::Port; this object takes responsibility for - * adding & removing it from the MIDI::Manager and destroying it. @param - * output_port Output MIDI::Port; responsibility similarly taken. - */ SurfacePort::SurfacePort (Surface& s) : _surface (&s) - , _input_port (0) - , _output_port (0) { if (_surface->mcp().device_info().uses_ipmidi()) { - _input_port = new MIDI::IPMIDIPort (MIDI::IPMIDIPort::lowest_ipmidi_port_default+_surface->number()); + _input_port = new MIDI::IPMIDIPort (_surface->mcp().ipmidi_base() +_surface->number()); _output_port = _input_port; + } else { - jack_client_t* jack = MackieControlProtocol::instance()->get_session().engine().jack(); - - _input_port = new MIDI::JackMIDIPort (string_compose (_("%1 in"), _surface->name()), MIDI::Port::IsInput, jack); - _output_port =new MIDI::JackMIDIPort (string_compose (_("%1 out"), _surface->name()), MIDI::Port::IsOutput, jack); - - /* MackieControl has its own thread for handling input from the input - * port, and we don't want anything handling output from the output - * port. This stops the Generic MIDI UI event loop in ardour from - * attempting to handle these ports. - */ - _input_port->set_centrally_parsed (false); - _output_port->set_centrally_parsed (false); - - MIDI::Manager * mm = MIDI::Manager::instance(); - - mm->add_port (_input_port); - mm->add_port (_output_port); + _async_in = AudioEngine::instance()->register_input_port (DataType::MIDI, string_compose (_("%1 in"), _surface->name()), true); + _async_out = AudioEngine::instance()->register_output_port (DataType::MIDI, string_compose (_("%1 out"), _surface->name()), true); + + if (_async_in == 0 || _async_out == 0) { + throw failed_constructor(); + } + + _input_port = boost::dynamic_pointer_cast(_async_in).get(); + _output_port = boost::dynamic_pointer_cast(_async_out).get(); } } SurfacePort::~SurfacePort() { - if (_surface->mcp().device_info().uses_ipmidi()) { + if (dynamic_cast(_input_port)) { delete _input_port; } else { - MIDI::Manager* mm = MIDI::Manager::instance (); - - if (_input_port) { - mm->remove_port (_input_port); - delete _input_port; + if (_async_in) { + AudioEngine::instance()->unregister_port (_async_in); + _async_in.reset ((ARDOUR::Port*) 0); } - if (_output_port) { + if (_async_out) { _output_port->drain (10000); - mm->remove_port (_output_port); - delete _output_port; + AudioEngine::instance()->unregister_port (_async_out); + _async_out.reset ((ARDOUR::Port*) 0); } } } +XMLNode& +SurfacePort::get_state () +{ + XMLNode* node = new XMLNode (X_("Port")); + + if (dynamic_cast(_input_port)) { + /* no state required for IPMidi ports */ + return *node; + } + + XMLNode* child; + + child = new XMLNode (X_("Input")); + child->add_child_nocopy (_async_in->get_state()); + node->add_child_nocopy (*child); + + + child = new XMLNode (X_("Output")); + child->add_child_nocopy (_async_out->get_state()); + node->add_child_nocopy (*child); + + return *node; +} + +int +SurfacePort::set_state (const XMLNode& node, int version) +{ + if (dynamic_cast(_input_port)) { + return 0; + } + + XMLNode* child; + + if ((child = node.child (X_("Input"))) != 0) { + XMLNode* portnode = child->child (Port::state_node_name.c_str()); + if (portnode) { + _async_in->set_state (*portnode, version); + } + } + + if ((child = node.child (X_("Output"))) != 0) { + XMLNode* portnode = child->child (Port::state_node_name.c_str()); + if (portnode) { + _async_out->set_state (*portnode, version); + } + } + + return 0; +} + // wrapper for one day when strerror_r is working properly string fetch_errmsg (int error_number) { @@ -112,16 +149,25 @@ int SurfacePort::write (const MidiByteArray & mba) { if (mba.empty()) { + DEBUG_TRACE (DEBUG::MackieControl, string_compose ("port %1 asked to write an empty MBA\n", output_port().name())); return 0; } DEBUG_TRACE (DEBUG::MackieControl, string_compose ("port %1 write %2\n", output_port().name(), mba)); - int count = output_port().write (mba.bytes().get(), mba.size(), 0); + if (mba[0] != 0xf0 && mba.size() > 3) { + std::cerr << "TOO LONG WRITE: " << mba << std::endl; + } + + /* this call relies on std::vector using contiguous storage. not + * actually guaranteed by the standard, but way, way beyond likely. + */ + + int count = output_port().write (&mba[0], mba.size(), 0); - if (count != (int)mba.size()) { + if (count != (int) mba.size()) { - if (errno == 0) { + if (errno == 0) { cout << "port overflow on " << output_port().name() << ". Did not write all of " << mba << endl;