JACK audio/MIDI backend: finalize (?) transition from looking up jack ports via port handle to lookup by name

Add an additional callback for the JACK registration/unregistration callback so we can keep _jack_ports current
This commit is contained in:
Paul Davis 2021-06-10 15:24:14 -06:00
parent 439bf215de
commit ecc64ab766
2 changed files with 71 additions and 14 deletions

View file

@ -303,7 +303,12 @@ class JACKAudioBackend : public AudioBackend {
static void _registration_callback (jack_port_id_t, int, void *);
static void _connect_callback (jack_port_id_t, jack_port_id_t, int, void *);
typedef std::map<void*,boost::shared_ptr<JackPort> > JackPorts;
/* used to manage _jack_ports, specifically for ports belonging to the
JACK backend or other clients.
*/
void jack_registration_callback (jack_port_id_t, int);
typedef std::map<std::string,boost::shared_ptr<JackPort> > JackPorts;
mutable SerializedRCUManager<JackPorts> _jack_ports; /* can be modified in ::get_port_by_name () */
void connect_callback (jack_port_id_t, jack_port_id_t, int);

View file

@ -175,28 +175,32 @@ JACKAudioBackend::set_port_property (PortHandle port, const std::string& key, co
PortEngine::PortPtr
JACKAudioBackend::get_port_by_name (const std::string& name) const
{
{
boost::shared_ptr<JackPorts> ports = _jack_ports.reader ();
JackPorts::iterator p = ports->find (name);
if (p != ports->end()) {
return p->second;
}
}
/* Port not known to us yet, so look it up via JACK (slow) */
GET_PRIVATE_JACK_POINTER_RET (_priv_jack, PortEngine::PortPtr());
jack_port_t * jack_port = jack_port_by_name (_priv_jack, name.c_str());
if (!jack_port) {
/* No such port ... return nothering */
return PortEngine::PortPtr();
}
boost::shared_ptr<JackPorts> ports = _jack_ports.reader ();
JackPorts::const_iterator i = ports->find (jack_port);
if (i != ports->end()) {
return i->second;
}
boost::shared_ptr<JackPort> jp;
{
RCUWriter<JackPorts> writer (_jack_ports);
boost::shared_ptr<JackPorts> ports = writer.get_copy();
jp.reset (new JackPort (jack_port));
ports->insert (std::make_pair (jack_port, jp));
ports->insert (std::make_pair (name, jp));
}
_jack_ports.flush ();
@ -205,13 +209,61 @@ JACKAudioBackend::get_port_by_name (const std::string& name) const
}
void
JACKAudioBackend::_registration_callback (jack_port_id_t /*id*/, int /*reg*/, void* arg)
JACKAudioBackend::_registration_callback (jack_port_id_t id, int reg, void* arg)
{
/* we don't use a virtual method for the registration callback, because
JACK is the only backend that delivers the arguments shown above. So
call our own JACK-centric registration callback, then the generic
one.
*/
static_cast<JACKAudioBackend*> (arg)->jack_registration_callback (id, reg);
static_cast<JACKAudioBackend*> (arg)->manager.registration_callback ();
static_cast<JACKAudioBackend*> (arg)->engine.latency_callback (false);
static_cast<JACKAudioBackend*> (arg)->engine.latency_callback (true);
}
void
JACKAudioBackend::jack_registration_callback (jack_port_id_t id, int reg)
{
GET_PRIVATE_JACK_POINTER (_priv_jack);
jack_port_t* jack_port = jack_port_by_id (_priv_jack, id);
if (!jack_port) {
return;
}
const char* name = jack_port_name (jack_port);
/* We only need to care about ports that we do not register/unregister
* ourselves. Those will be added/removed from _jack_ports at the
* appropriate time. But if someone disconnects a USB MIDI device and
* the corresponding JACK port vanishes, we need to make sure that
* _jack_ports can be used to look it up by name for use in run_input_meters()
*/
if (!jack_port_is_mine (_priv_jack, jack_port)) {
boost::shared_ptr<JackPorts> ports = _jack_ports.write_copy();
if (!reg) {
if (ports->erase (name)) {
_jack_ports.update (ports);
}
} else {
if (ports->find (name) != ports->end()) {
/* hmmm, we already have this port */
std::cout << "re-registration of JACK port named " << name << std::endl;
ports->erase (name);
}
boost::shared_ptr<JackPort> jp (new JackPort (jack_port));
ports->insert (std::make_pair (name, jp));
_jack_ports.update (ports);
}
}
}
int
JACKAudioBackend::_graph_order_callback (void *arg)
{
@ -523,7 +575,7 @@ JACKAudioBackend::register_port (const std::string& shortname, ARDOUR::DataType
jp.reset (new JackPort (jack_port));
ports->insert (std::make_pair (jack_port, jp));
ports->insert (std::make_pair (jack_port_name (jack_port), jp));
}
_jack_ports.flush();
@ -536,12 +588,12 @@ JACKAudioBackend::unregister_port (PortHandle port)
{
GET_PRIVATE_JACK_POINTER (_priv_jack);
boost::shared_ptr<JackPort> jp = boost::dynamic_pointer_cast<JackPort>(port);
const std::string name = jack_port_name (jp->jack_ptr);
{
RCUWriter<JackPorts> writer (_jack_ports);
boost::shared_ptr<JackPorts> ports = writer.get_copy();
ports->erase (jp->jack_ptr);
ports->erase (name);
}
_jack_ports.flush ();