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
This commit is contained in:
Carl Hetherington 2010-07-05 15:41:05 +00:00
parent c686dee0ce
commit df2298c846
6 changed files with 71 additions and 7 deletions

View file

@ -34,6 +34,7 @@
#include "midi++/jack.h" #include "midi++/jack.h"
#include "midi++/mmc.h" #include "midi++/mmc.h"
#include "midi++/manager.h"
#include "ardour/amp.h" #include "ardour/amp.h"
#include "ardour/audio_port.h" #include "ardour/audio_port.h"
@ -1395,6 +1396,8 @@ AudioEngine::reconnect_to_jack ()
GET_PRIVATE_JACK_POINTER_RET (_jack,-1); GET_PRIVATE_JACK_POINTER_RET (_jack,-1);
MIDI::Manager::instance()->reestablish (_priv_jack);
if (_session) { if (_session) {
_session->reset_jack_connection (_priv_jack); _session->reset_jack_connection (_priv_jack);
jack_bufsize_callback (jack_get_buffer_size (_priv_jack)); jack_bufsize_callback (jack_get_buffer_size (_priv_jack));
@ -1435,6 +1438,8 @@ AudioEngine::reconnect_to_jack ()
(*i)->reconnect (); (*i)->reconnect ();
} }
MIDI::Manager::instance()->reconnect ();
Running (); /* EMIT SIGNAL*/ Running (); /* EMIT SIGNAL*/
start_metering_thread (); start_metering_thread ();

View file

@ -268,13 +268,26 @@ JACK_MidiPort::create_ports(const XMLNode& node)
assert(!_jack_input_port); assert(!_jack_input_port);
assert(!_jack_output_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; bool ret = true;
if (desc.mode == O_RDWR || desc.mode == O_WRONLY) { jack_nframes_t nframes = jack_get_buffer_size(_jack_client);
_jack_output_port = jack_port_register(_jack_client,
string(desc.tag).append("_out").c_str(), 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); JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput, 0);
if (_jack_output_port) { if (_jack_output_port) {
jack_midi_clear_buffer(jack_port_get_buffer(_jack_output_port, nframes)); 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); ret = ret && (_jack_output_port != NULL);
} }
if (desc.mode == O_RDWR || desc.mode == O_RDONLY) { if (!_jack_input_port_name.empty()) {
_jack_input_port = jack_port_register(_jack_client, _jack_input_port = jack_port_register(_jack_client, _jack_input_port_name.c_str(),
string(desc.tag).append("_in").c_str(),
JACK_DEFAULT_MIDI_TYPE, JackPortIsInput, 0); JACK_DEFAULT_MIDI_TYPE, JackPortIsInput, 0);
if (_jack_input_port) { if (_jack_input_port) {
jack_midi_clear_buffer(jack_port_get_buffer(_jack_input_port, nframes)); 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); return (pthread_self() == _process_thread);
} }
void
JACK_MidiPort::reestablish (void* jack)
{
_jack_client = static_cast<jack_client_t*> (jack);
int const r = create_ports ();
if (r) {
PBD::error << "could not reregister ports for " << name() << endmsg;
}
}
void
JACK_MidiPort::reconnect ()
{
make_connections ();
}

View file

@ -234,3 +234,21 @@ Manager::get_known_ports (vector<PortSet>& ports)
{ {
return PortFactory::get_known_ports (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 ();
}
}

View file

@ -71,6 +71,9 @@ public:
nframes_t nframes_this_cycle() const { return _nframes_this_cycle; } nframes_t nframes_this_cycle() const { return _nframes_this_cycle; }
void reestablish (void *);
void reconnect ();
static PBD::Signal0<void> MakeConnections; static PBD::Signal0<void> MakeConnections;
static PBD::Signal0<void> JackHalted; static PBD::Signal0<void> JackHalted;
@ -81,9 +84,12 @@ public:
private: private:
int create_ports(const XMLNode&); int create_ports(const XMLNode&);
int create_ports ();
jack_client_t* _jack_client; 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; 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; jack_port_t* _jack_output_port;
nframes_t _last_read_index; nframes_t _last_read_index;
timestamp_t _last_write_timestamp; timestamp_t _last_write_timestamp;

View file

@ -83,6 +83,9 @@ class Manager {
int get_known_ports (std::vector<PortSet>&); int get_known_ports (std::vector<PortSet>&);
void reestablish (void *);
void reconnect ();
PBD::Signal0<void> PortsChanged; PBD::Signal0<void> PortsChanged;
private: private:

View file

@ -157,6 +157,9 @@ class Port {
XMLNode& get_state(); XMLNode& get_state();
}; };
virtual void reestablish (void *) {}
virtual void reconnect () {}
protected: protected:
bool _ok; bool _ok;
bool _currently_in_cycle; bool _currently_in_cycle;