mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-06 14:54:56 +01:00
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:
parent
439bf215de
commit
ecc64ab766
2 changed files with 71 additions and 14 deletions
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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 ();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue