From df2298c846527e71a794b957baec7684fabe46aa Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Mon, 5 Jul 2010 15:41:05 +0000 Subject: [PATCH] Reestablish libmidi++ JACK ports on jack reconnection, so that control MIDI can still be sent after a JACK disconnect/reconnect. Fixes remainder of #3301. git-svn-id: svn://localhost/ardour2/branches/3.0@7373 d708f5d6-7413-0410-9779-e7cbd77b26cf --- libs/ardour/audioengine.cc | 5 ++++ libs/midi++2/jack_midiport.cc | 43 +++++++++++++++++++++++++++++------ libs/midi++2/manager.cc | 18 +++++++++++++++ libs/midi++2/midi++/jack.h | 6 +++++ libs/midi++2/midi++/manager.h | 3 +++ libs/midi++2/midi++/port.h | 3 +++ 6 files changed, 71 insertions(+), 7 deletions(-) diff --git a/libs/ardour/audioengine.cc b/libs/ardour/audioengine.cc index 0058acc7e2..b9ec8e465b 100644 --- a/libs/ardour/audioengine.cc +++ b/libs/ardour/audioengine.cc @@ -34,6 +34,7 @@ #include "midi++/jack.h" #include "midi++/mmc.h" +#include "midi++/manager.h" #include "ardour/amp.h" #include "ardour/audio_port.h" @@ -1395,6 +1396,8 @@ AudioEngine::reconnect_to_jack () GET_PRIVATE_JACK_POINTER_RET (_jack,-1); + MIDI::Manager::instance()->reestablish (_priv_jack); + if (_session) { _session->reset_jack_connection (_priv_jack); jack_bufsize_callback (jack_get_buffer_size (_priv_jack)); @@ -1435,6 +1438,8 @@ AudioEngine::reconnect_to_jack () (*i)->reconnect (); } + MIDI::Manager::instance()->reconnect (); + Running (); /* EMIT SIGNAL*/ start_metering_thread (); diff --git a/libs/midi++2/jack_midiport.cc b/libs/midi++2/jack_midiport.cc index 07b044f077..b55cf3adf6 100644 --- a/libs/midi++2/jack_midiport.cc +++ b/libs/midi++2/jack_midiport.cc @@ -268,13 +268,26 @@ JACK_MidiPort::create_ports(const XMLNode& node) assert(!_jack_input_port); assert(!_jack_output_port); - jack_nframes_t nframes = jack_get_buffer_size(_jack_client); + if (desc.mode == O_RDWR || desc.mode == O_WRONLY) { + _jack_output_port_name = string(desc.tag).append ("_out"); + } + if (desc.mode == O_RDWR || desc.mode == O_RDONLY) { + _jack_input_port_name = string(desc.tag).append ("_in"); + } + + return create_ports (); +} + +int +JACK_MidiPort::create_ports () +{ bool ret = true; - if (desc.mode == O_RDWR || desc.mode == O_WRONLY) { - _jack_output_port = jack_port_register(_jack_client, - string(desc.tag).append("_out").c_str(), + jack_nframes_t nframes = jack_get_buffer_size(_jack_client); + + if (!_jack_output_port_name.empty()) { + _jack_output_port = jack_port_register(_jack_client, _jack_output_port_name.c_str(), JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput, 0); if (_jack_output_port) { jack_midi_clear_buffer(jack_port_get_buffer(_jack_output_port, nframes)); @@ -282,9 +295,8 @@ JACK_MidiPort::create_ports(const XMLNode& node) ret = ret && (_jack_output_port != NULL); } - if (desc.mode == O_RDWR || desc.mode == O_RDONLY) { - _jack_input_port = jack_port_register(_jack_client, - string(desc.tag).append("_in").c_str(), + if (!_jack_input_port_name.empty()) { + _jack_input_port = jack_port_register(_jack_client, _jack_input_port_name.c_str(), JACK_DEFAULT_MIDI_TYPE, JackPortIsInput, 0); if (_jack_input_port) { jack_midi_clear_buffer(jack_port_get_buffer(_jack_input_port, nframes)); @@ -402,3 +414,20 @@ JACK_MidiPort::is_process_thread() { return (pthread_self() == _process_thread); } + +void +JACK_MidiPort::reestablish (void* jack) +{ + _jack_client = static_cast (jack); + int const r = create_ports (); + + if (r) { + PBD::error << "could not reregister ports for " << name() << endmsg; + } +} + +void +JACK_MidiPort::reconnect () +{ + make_connections (); +} diff --git a/libs/midi++2/manager.cc b/libs/midi++2/manager.cc index ffc8f4e1bc..a84b5ab68a 100644 --- a/libs/midi++2/manager.cc +++ b/libs/midi++2/manager.cc @@ -234,3 +234,21 @@ Manager::get_known_ports (vector& ports) { return PortFactory::get_known_ports (ports); } + +/** Re-register ports that disappear on JACK shutdown */ +void +Manager::reestablish (void* a) +{ + for (PortList::const_iterator p = _ports.begin(); p != _ports.end(); ++p) { + (*p)->reestablish (a); + } +} + +/** Re-connect ports after a reestablish () */ +void +Manager::reconnect () +{ + for (PortList::const_iterator p = _ports.begin(); p != _ports.end(); ++p) { + (*p)->reconnect (); + } +} diff --git a/libs/midi++2/midi++/jack.h b/libs/midi++2/midi++/jack.h index 0433e4ae45..099bc4e639 100644 --- a/libs/midi++2/midi++/jack.h +++ b/libs/midi++2/midi++/jack.h @@ -71,6 +71,9 @@ public: nframes_t nframes_this_cycle() const { return _nframes_this_cycle; } + void reestablish (void *); + void reconnect (); + static PBD::Signal0 MakeConnections; static PBD::Signal0 JackHalted; @@ -81,9 +84,12 @@ public: private: int create_ports(const XMLNode&); + int create_ports (); jack_client_t* _jack_client; + std::string _jack_input_port_name; /// input port name, or empty if there isn't one jack_port_t* _jack_input_port; + std::string _jack_output_port_name; /// output port name, or empty if there isn't one jack_port_t* _jack_output_port; nframes_t _last_read_index; timestamp_t _last_write_timestamp; diff --git a/libs/midi++2/midi++/manager.h b/libs/midi++2/midi++/manager.h index 90bdde3e70..33835a05bf 100644 --- a/libs/midi++2/midi++/manager.h +++ b/libs/midi++2/midi++/manager.h @@ -83,6 +83,9 @@ class Manager { int get_known_ports (std::vector&); + void reestablish (void *); + void reconnect (); + PBD::Signal0 PortsChanged; private: diff --git a/libs/midi++2/midi++/port.h b/libs/midi++2/midi++/port.h index 16db09f0e4..c45f5ba2fc 100644 --- a/libs/midi++2/midi++/port.h +++ b/libs/midi++2/midi++/port.h @@ -157,6 +157,9 @@ class Port { XMLNode& get_state(); }; + virtual void reestablish (void *) {} + virtual void reconnect () {} + protected: bool _ok; bool _currently_in_cycle;