use shared_ptr to manage backend port lifetimes (Pulse,ALSA,Dummy,JACK)

JACK is not yet finished.

Changes also include minor reformatting and a spelling correction (latecies to latencies)
This commit is contained in:
Paul Davis 2020-04-07 10:18:16 -06:00
parent 1eb98316a3
commit b9cb306e8b
21 changed files with 446 additions and 425 deletions

View file

@ -284,8 +284,8 @@ class LIBARDOUR_API AudioEngine : public PortManager, public SessionHandlePtr
MTDM* _mtdm; MTDM* _mtdm;
MIDIDM* _mididm; MIDIDM* _mididm;
LatencyMeasurement _measuring_latency; LatencyMeasurement _measuring_latency;
PortEngine::PortHandle _latency_input_port; PortEngine::PortPtr _latency_input_port;
PortEngine::PortHandle _latency_output_port; PortEngine::PortPtr _latency_output_port;
samplecnt_t _latency_flush_samples; samplecnt_t _latency_flush_samples;
std::string _latency_input_name; std::string _latency_input_name;
std::string _latency_output_name; std::string _latency_output_name;

View file

@ -159,7 +159,7 @@ protected:
Port (std::string const &, DataType, PortFlags); Port (std::string const &, DataType, PortFlags);
PortEngine::PortHandle _port_handle; PortEngine::PortPtr _port_handle;
static bool _connecting_blocked; static bool _connecting_blocked;
static pframes_t _cycle_nframes; /* access only from process() tree */ static pframes_t _cycle_nframes; /* access only from process() tree */

View file

@ -75,6 +75,12 @@ class PortManager;
* documentation, on which this entire object is based. * documentation, on which this entire object is based.
*/ */
class LIBARDOUR_API ProtoPort {
public:
ProtoPort() {}
virtual ~ProtoPort () {}
};
class LIBARDOUR_API PortEngine class LIBARDOUR_API PortEngine
{ {
public: public:
@ -88,14 +94,24 @@ public:
/** Opaque handle to use as reference for Ports /** Opaque handle to use as reference for Ports
* *
* We use void* here so that the API can be defined for any implementation. * The handle needs to be lifetime managed (i.e. a shared_ptr type)
* in order to allow RCU to provide lock-free cross-thread operations
* on ports and ports containers.
* *
* We could theoretically use a template (PortEngine\<T\>) and define * We could theoretically use a template (PortEngine\<T\>) and define
* PortHandle as T, but this complicates the desired inheritance * PortHandle as T, but this complicates the desired inheritance
* pattern in which FooPortEngine handles things for the Foo API, * pattern in which FooPortEngine handles things for the Foo API,
* rather than being a derivative of PortEngine\<Foo\>. * rather than being a derivative of PortEngine\<Foo\>.
*
* We use this to declare return values and members of structures.
*/ */
typedef void* PortHandle; typedef boost::shared_ptr<ProtoPort> PortPtr;
/* We use this to declare arguments to methods/functions, in order to
* avoid copying shared_ptr<ProtoPort> every time (a practice we use in
* other contexts where we pass shared_ptr<T>).
*/
typedef PortPtr const & PortHandle;
/** Return the name of this process as used by the port manager /** Return the name of this process as used by the port manager
* when naming ports. * when naming ports.
@ -164,7 +180,7 @@ public:
* @param name Full port-name to lookup * @param name Full port-name to lookup
* @return PortHandle if lookup was successful, or an "empty" PortHandle (analogous to a null pointer) if no such port exists. * @return PortHandle if lookup was successful, or an "empty" PortHandle (analogous to a null pointer) if no such port exists.
*/ */
virtual PortHandle get_port_by_name (const std::string& name) const = 0; virtual PortPtr get_port_by_name (const std::string& name) const = 0;
/** Find the set of ports whose names, types and flags match /** Find the set of ports whose names, types and flags match
* specified values, place the names of each port into \p ports . * specified values, place the names of each port into \p ports .
@ -194,7 +210,7 @@ public:
* @param flags flags of the port to create * @param flags flags of the port to create
* @return a reference to the port, otherwise return a null pointer. * @return a reference to the port, otherwise return a null pointer.
*/ */
virtual PortHandle register_port (const std::string& shortname, ARDOUR::DataType type, ARDOUR::PortFlags flags) = 0; virtual PortPtr register_port (const std::string& shortname, ARDOUR::DataType type, ARDOUR::PortFlags flags) = 0;
/* Destroy the port referred to by \p port, including all resources /* Destroy the port referred to by \p port, including all resources
* associated with it. This will also disconnect \p port from any ports it * associated with it. This will also disconnect \p port from any ports it
@ -202,7 +218,7 @@ public:
* *
* @param port \ref PortHandle of the port to destroy * @param port \ref PortHandle of the port to destroy
*/ */
virtual void unregister_port (PortHandle port) = 0; virtual void unregister_port (PortHandle port) = 0;
/* Connection management */ /* Connection management */

View file

@ -39,25 +39,28 @@ namespace ARDOUR {
class PortEngineSharedImpl; class PortEngineSharedImpl;
class PortManager; class PortManager;
class LIBARDOUR_API BackendPort class BackendPort;
typedef boost::shared_ptr<BackendPort> BackendPortPtr;
typedef boost::shared_ptr<BackendPort> const & BackendPortHandle;
class LIBARDOUR_API BackendPort : public ProtoPort
{ {
protected: protected:
BackendPort (PortEngineSharedImpl& b, const std::string&, PortFlags); BackendPort (PortEngineSharedImpl& b, const std::string&, PortFlags);
public: public:
virtual ~BackendPort (); virtual ~BackendPort ();
const std::string& name () const { return _name; } const std::string& name () const { return _name; }
const std::string& pretty_name () const { return _pretty_name; } const std::string& pretty_name () const { return _pretty_name; }
int set_name (const std::string& name) int set_name (const std::string& name) {
{
_name = name; _name = name;
return 0; return 0;
} }
int set_pretty_name (const std::string& name) int set_pretty_name (const std::string& name) {
{
_pretty_name = name; _pretty_name = name;
return 0; return 0;
} }
@ -71,17 +74,16 @@ public:
bool is_terminal () const { return flags () & IsTerminal; } bool is_terminal () const { return flags () & IsTerminal; }
bool is_connected () const { return _connections.size () != 0; } bool is_connected () const { return _connections.size () != 0; }
bool is_connected (const BackendPort* port) const; bool is_connected (BackendPortHandle port) const;
bool is_physically_connected () const; bool is_physically_connected () const;
const std::set<BackendPort*>& get_connections () const const std::set<BackendPortPtr>& get_connections () const {
{
return _connections; return _connections;
} }
int connect (BackendPort* port); int connect (BackendPortHandle port, BackendPortHandle self);
int disconnect (BackendPort* port); int disconnect (BackendPortHandle port, BackendPortHandle self);
void disconnect_all (); void disconnect_all (BackendPortHandle self);
virtual void* get_buffer (pframes_t nframes) = 0; virtual void* get_buffer (pframes_t nframes) = 0;
@ -103,10 +105,10 @@ private:
const PortFlags _flags; const PortFlags _flags;
LatencyRange _capture_latency_range; LatencyRange _capture_latency_range;
LatencyRange _playback_latency_range; LatencyRange _playback_latency_range;
std::set<BackendPort*> _connections; std::set<BackendPortPtr> _connections;
void _connect (BackendPort*, bool); void store_connection (BackendPortHandle);
void _disconnect (BackendPort*, bool); void remove_connection (BackendPortHandle);
}; // class BackendPort }; // class BackendPort
@ -129,7 +131,7 @@ public:
int set_port_name (PortEngine::PortHandle, const std::string&); int set_port_name (PortEngine::PortHandle, const std::string&);
std::string get_port_name (PortEngine::PortHandle) const; std::string get_port_name (PortEngine::PortHandle) const;
PortFlags get_port_flags (PortEngine::PortHandle) const; PortFlags get_port_flags (PortEngine::PortHandle) const;
PortEngine::PortHandle get_port_by_name (const std::string&) const; PortEngine::PortPtr get_port_by_name (const std::string&) const;
int get_port_property (PortEngine::PortHandle, const std::string& key, std::string& value, std::string& type) const; int get_port_property (PortEngine::PortHandle, const std::string& key, std::string& value, std::string& type) const;
int set_port_property (PortEngine::PortHandle, const std::string& key, const std::string& value, const std::string& type); int set_port_property (PortEngine::PortHandle, const std::string& key, const std::string& value, const std::string& type);
@ -138,8 +140,8 @@ public:
DataType port_data_type (PortEngine::PortHandle) const; DataType port_data_type (PortEngine::PortHandle) const;
PortEngine::PortHandle register_port (const std::string& shortname, ARDOUR::DataType, ARDOUR::PortFlags); PortEngine::PortPtr register_port (const std::string& shortname, ARDOUR::DataType, ARDOUR::PortFlags);
virtual void unregister_port (PortEngine::PortHandle); virtual void unregister_port (PortEngine::PortHandle);
int connect (const std::string& src, const std::string& dst); int connect (const std::string& src, const std::string& dst);
int disconnect (const std::string& src, const std::string& dst); int disconnect (const std::string& src, const std::string& dst);
@ -158,36 +160,35 @@ public:
protected: protected:
std::string _instance_name; std::string _instance_name;
std::vector<BackendPort*> _system_inputs; std::vector<BackendPortPtr> _system_inputs;
std::vector<BackendPort*> _system_outputs; std::vector<BackendPortPtr> _system_outputs;
std::vector<BackendPort*> _system_midi_in; std::vector<BackendPortPtr> _system_midi_in;
std::vector<BackendPort*> _system_midi_out; std::vector<BackendPortPtr> _system_midi_out;
virtual void update_system_port_latencies ();
void clear_ports (); void clear_ports ();
PortEngine::PortHandle add_port (const std::string& shortname, ARDOUR::DataType, ARDOUR::PortFlags); BackendPortPtr add_port (const std::string& shortname, ARDOUR::DataType, ARDOUR::PortFlags);
void unregister_ports (bool system_only = false); void unregister_ports (bool system_only = false);
struct SortByPortName { struct SortByPortName {
bool operator() (const BackendPort* lhs, const BackendPort* rhs) const bool operator() (BackendPortHandle lhs, BackendPortHandle rhs) const {
{
return PBD::naturally_less (lhs->name ().c_str (), rhs->name ().c_str ()); return PBD::naturally_less (lhs->name ().c_str (), rhs->name ().c_str ());
} }
}; };
typedef std::map<std::string, BackendPort*> PortMap; // fast lookup in _ports typedef std::map<std::string, BackendPortPtr> PortMap; // fast lookup in _ports
typedef std::set<BackendPort*, SortByPortName> PortIndex; // fast lookup in _ports typedef std::set<BackendPortPtr, SortByPortName> PortIndex; // fast lookup in _ports
SerializedRCUManager<PortMap> _portmap; SerializedRCUManager<PortMap> _portmap;
SerializedRCUManager<PortIndex> _ports; SerializedRCUManager<PortIndex> _ports;
bool valid_port (PortEngine::PortHandle port) const bool valid_port (BackendPortHandle port) const {
{
boost::shared_ptr<PortIndex> p = _ports.reader (); boost::shared_ptr<PortIndex> p = _ports.reader ();
return std::find (p->begin (), p->end (), static_cast<BackendPort*> (port)) != p->end (); return std::find (p->begin (), p->end (), port) != p->end ();
} }
BackendPort* find_port (const std::string& port_name) const BackendPortPtr find_port (const std::string& port_name) const {
{
boost::shared_ptr<PortMap> p = _portmap.reader (); boost::shared_ptr<PortMap> p = _portmap.reader ();
PortMap::const_iterator it = p->find (port_name); PortMap::const_iterator it = p->find (port_name);
if (it == p->end ()) { if (it == p->end ()) {

View file

@ -92,8 +92,6 @@ AudioEngine::AudioEngine ()
, _mtdm (0) , _mtdm (0)
, _mididm (0) , _mididm (0)
, _measuring_latency (MeasureNone) , _measuring_latency (MeasureNone)
, _latency_input_port (0)
, _latency_output_port (0)
, _latency_flush_samples (0) , _latency_flush_samples (0)
, _latency_signal_latency (0) , _latency_signal_latency (0)
, _stopped_for_latency (false) , _stopped_for_latency (false)

View file

@ -826,11 +826,8 @@ DiskWriter::do_flush (RunContext ctxt, bool force_flush)
uint32_t to_write; uint32_t to_write;
int32_t ret = 0; int32_t ret = 0;
RingBufferNPT<Sample>::rw_vector vector; RingBufferNPT<Sample>::rw_vector vector;
RingBufferNPT<CaptureTransition>::rw_vector transvec;
samplecnt_t total; samplecnt_t total;
transvec.buf[0] = 0;
transvec.buf[1] = 0;
vector.buf[0] = 0; vector.buf[0] = 0;
vector.buf[1] = 0; vector.buf[1] = 0;
@ -1205,8 +1202,6 @@ DiskWriter::transport_stopped_wallclock (struct tm& when, time_t twhen, bool abo
out: out:
reset_write_sources (mark_write_completed); reset_write_sources (mark_write_completed);
outout:
for (ci = capture_info.begin(); ci != capture_info.end(); ++ci) { for (ci = capture_info.begin(); ci != capture_info.end(); ++ci) {
delete *ci; delete *ci;
} }

View file

@ -76,7 +76,7 @@ Port::Port (std::string const & n, DataType t, PortFlags f)
if (!port_manager->running ()) { if (!port_manager->running ()) {
DEBUG_TRACE (DEBUG::Ports, string_compose ("port-engine n/a postpone registering %1\n", name())); DEBUG_TRACE (DEBUG::Ports, string_compose ("port-engine n/a postpone registering %1\n", name()));
_port_handle = 0; // created during ::reestablish() later _port_handle.reset (); // created during ::reestablish() later
} else if ((_port_handle = port_engine.register_port (_name, t, _flags)) == 0) { } else if ((_port_handle = port_engine.register_port (_name, t, _flags)) == 0) {
cerr << "Failed to register port \"" << _name << "\", reason is unknown from here\n"; cerr << "Failed to register port \"" << _name << "\", reason is unknown from here\n";
throw failed_constructor (); throw failed_constructor ();

View file

@ -40,10 +40,11 @@ BackendPort::BackendPort (PortEngineSharedImpl &b, const std::string& name, Port
BackendPort::~BackendPort () BackendPort::~BackendPort ()
{ {
disconnect_all (); assert (_connections.empty());
} }
int BackendPort::connect (BackendPort *port) int
BackendPort::connect (BackendPortHandle port, BackendPortHandle self)
{ {
if (!port) { if (!port) {
PBD::error << _("BackendPort::connect (): invalid (null) port") << endmsg; PBD::error << _("BackendPort::connect (): invalid (null) port") << endmsg;
@ -65,7 +66,7 @@ int BackendPort::connect (BackendPort *port)
return -1; return -1;
} }
if (this == port) { if (this == port.get()) {
PBD::error << _("BackendPort::connect (): cannot self-connect ports.") << endmsg; PBD::error << _("BackendPort::connect (): cannot self-connect ports.") << endmsg;
return -1; return -1;
} }
@ -79,20 +80,22 @@ int BackendPort::connect (BackendPort *port)
return -1; return -1;
} }
_connect (port, true); store_connection (port);
port->store_connection (self);
_backend.port_connect_callback (name(), port->name(), true);
return 0; return 0;
} }
void BackendPort::_connect (BackendPort *port, bool callback) void
BackendPort::store_connection (BackendPortHandle port)
{ {
_connections.insert (port); _connections.insert (port);
if (callback) {
port->_connect (this, false);
_backend.port_connect_callback (name(), port->name(), true);
}
} }
int BackendPort::disconnect (BackendPort *port) int
BackendPort::disconnect (BackendPortHandle port, BackendPortHandle self)
{ {
if (!port) { if (!port) {
PBD::error << _("BackendPort::disconnect (): invalid (null) port") << endmsg; PBD::error << _("BackendPort::disconnect (): invalid (null) port") << endmsg;
@ -105,41 +108,41 @@ int BackendPort::disconnect (BackendPort *port)
<< endmsg; << endmsg;
return -1; return -1;
} }
_disconnect (port, true);
remove_connection (port);
port->remove_connection (self);
_backend.port_connect_callback (name(), port->name(), false);
return 0; return 0;
} }
void BackendPort::_disconnect (BackendPort *port, bool callback) void BackendPort::remove_connection (BackendPortHandle port)
{ {
std::set<BackendPort*>::iterator it = _connections.find (port); std::set<BackendPortPtr>::iterator it = _connections.find (port);
assert (it != _connections.end ()); assert (it != _connections.end ());
_connections.erase (it); _connections.erase (it);
if (callback) {
port->_disconnect (this, false);
_backend.port_connect_callback (name(), port->name(), false);
}
} }
void BackendPort::disconnect_all () void BackendPort::disconnect_all (BackendPortHandle self)
{ {
while (!_connections.empty ()) { while (!_connections.empty ()) {
std::set<BackendPort*>::iterator it = _connections.begin (); std::set<BackendPortPtr>::iterator it = _connections.begin ();
(*it)->_disconnect (this, false); (*it)->remove_connection (self);
_backend.port_connect_callback (name(), (*it)->name(), false); _backend.port_connect_callback (name(), (*it)->name(), false);
_connections.erase (it); _connections.erase (it);
} }
} }
bool bool
BackendPort::is_connected (const BackendPort *port) const BackendPort::is_connected (BackendPortHandle port) const
{ {
return _connections.find (const_cast<BackendPort *>(port)) != _connections.end (); return _connections.find (port) != _connections.end ();
} }
bool BackendPort::is_physically_connected () const bool BackendPort::is_physically_connected () const
{ {
for (std::set<BackendPort*>::const_iterator it = _connections.begin (); it != _connections.end (); ++it) { for (std::set<BackendPortPtr>::const_iterator it = _connections.begin (); it != _connections.end (); ++it) {
if ((*it)->is_physical ()) { if ((*it)->is_physical ()) {
return true; return true;
} }
@ -156,7 +159,7 @@ BackendPort::set_latency_range (const LatencyRange &latency_range, bool for_play
_capture_latency_range = latency_range; _capture_latency_range = latency_range;
} }
for (std::set<BackendPort*>::const_iterator it = _connections.begin (); it != _connections.end (); ++it) { for (std::set<BackendPortPtr>::const_iterator it = _connections.begin (); it != _connections.end (); ++it) {
if ((*it)->is_physical ()) { if ((*it)->is_physical ()) {
(*it)->update_connected_latency (is_input ()); (*it)->update_connected_latency (is_input ());
} }
@ -168,7 +171,7 @@ BackendPort::update_connected_latency (bool for_playback)
{ {
LatencyRange lr; LatencyRange lr;
lr.min = lr.max = 0; lr.min = lr.max = 0;
for (std::set<BackendPort*>::const_iterator it = _connections.begin (); it != _connections.end (); ++it) { for (std::set<BackendPortPtr>::const_iterator it = _connections.begin (); it != _connections.end (); ++it) {
LatencyRange l; LatencyRange l;
l = (*it)->latency_range (for_playback); l = (*it)->latency_range (for_playback);
lr.min = std::max (lr.min, l.min); lr.min = std::max (lr.min, l.min);
@ -208,7 +211,7 @@ PortEngineSharedImpl::get_ports (
boost::shared_ptr<PortIndex> p = _ports.reader (); boost::shared_ptr<PortIndex> p = _ports.reader ();
for (PortIndex::const_iterator i = p->begin (); i != p->end (); ++i) { for (PortIndex::const_iterator i = p->begin (); i != p->end (); ++i) {
BackendPort* port = *i; BackendPortPtr port = *i;
if ((port->type () == type) && flags == (port->flags () & flags)) { if ((port->type () == type) && flags == (port->flags () & flags)) {
if (!use_regexp || !regexec (&port_regex, port->name ().c_str (), 0, NULL, 0)) { if (!use_regexp || !regexec (&port_regex, port->name ().c_str (), 0, NULL, 0)) {
port_names.push_back (port->name ()); port_names.push_back (port->name ());
@ -227,11 +230,11 @@ PortEngineSharedImpl::get_ports (
bool bool
PortEngineSharedImpl::port_is_physical (PortEngine::PortHandle port) const PortEngineSharedImpl::port_is_physical (PortEngine::PortHandle port) const
{ {
if (!valid_port (port)) { if (!valid_port (boost::dynamic_pointer_cast<BackendPort>(port))) {
PBD::error << _("BackendPort::port_is_physical (): invalid port.") << endmsg; PBD::error << _("BackendPort::port_is_physical (): invalid port.") << endmsg;
return false; return false;
} }
return static_cast<BackendPort*>(port)->is_physical (); return boost::dynamic_pointer_cast<BackendPort>(port)->is_physical ();
} }
void void
@ -240,7 +243,7 @@ PortEngineSharedImpl::get_physical_outputs (DataType type, std::vector<std::stri
boost::shared_ptr<PortIndex> p = _ports.reader(); boost::shared_ptr<PortIndex> p = _ports.reader();
for (PortIndex::iterator i = p->begin (); i != p->end (); ++i) { for (PortIndex::iterator i = p->begin (); i != p->end (); ++i) {
BackendPort* port = *i; BackendPortPtr port = *i;
if ((port->type () == type) && port->is_input () && port->is_physical ()) { if ((port->type () == type) && port->is_input () && port->is_physical ()) {
port_names.push_back (port->name ()); port_names.push_back (port->name ());
} }
@ -253,7 +256,7 @@ PortEngineSharedImpl::get_physical_inputs (DataType type, std::vector<std::strin
boost::shared_ptr<PortIndex> p = _ports.reader(); boost::shared_ptr<PortIndex> p = _ports.reader();
for (PortIndex::iterator i = p->begin (); i != p->end (); ++i) { for (PortIndex::iterator i = p->begin (); i != p->end (); ++i) {
BackendPort* port = *i; BackendPortPtr port = *i;
if ((port->type () == type) && port->is_output () && port->is_physical ()) { if ((port->type () == type) && port->is_output () && port->is_physical ()) {
port_names.push_back (port->name ()); port_names.push_back (port->name ());
} }
@ -269,7 +272,7 @@ PortEngineSharedImpl::n_physical_outputs () const
boost::shared_ptr<PortIndex> p = _ports.reader(); boost::shared_ptr<PortIndex> p = _ports.reader();
for (PortIndex::const_iterator i = p->begin (); i != p->end (); ++i) { for (PortIndex::const_iterator i = p->begin (); i != p->end (); ++i) {
BackendPort* port = *i; BackendPortPtr port = *i;
if (port->is_output () && port->is_physical ()) { if (port->is_output () && port->is_physical ()) {
switch (port->type ()) { switch (port->type ()) {
case DataType::AUDIO: ++n_audio; break; case DataType::AUDIO: ++n_audio; break;
@ -293,7 +296,7 @@ PortEngineSharedImpl::n_physical_inputs () const
boost::shared_ptr<PortIndex> p = _ports.reader(); boost::shared_ptr<PortIndex> p = _ports.reader();
for (PortIndex::const_iterator i = p->begin (); i != p->end (); ++i) { for (PortIndex::const_iterator i = p->begin (); i != p->end (); ++i) {
BackendPort* port = *i; BackendPortPtr port = *i;
if (port->is_input () && port->is_physical ()) { if (port->is_input () && port->is_physical ()) {
switch (port->type ()) { switch (port->type ()) {
case DataType::AUDIO: ++n_audio; break; case DataType::AUDIO: ++n_audio; break;
@ -308,22 +311,20 @@ PortEngineSharedImpl::n_physical_inputs () const
return cc; return cc;
} }
PortEngine::PortHandle BackendPortPtr
PortEngineSharedImpl::add_port ( PortEngineSharedImpl::add_port (const std::string& name, ARDOUR::DataType type, ARDOUR::PortFlags flags)
const std::string& name,
ARDOUR::DataType type,
ARDOUR::PortFlags flags)
{ {
assert(name.size ()); assert(name.size ());
if (find_port (name)) { if (find_port (name)) {
PBD::error << string_compose (_("%1::register_port: Port already exists: (%2)"), _instance_name, name) << endmsg; PBD::error << string_compose (_("%1::register_port: Port already exists: (%2)"), _instance_name, name) << endmsg;
return 0; return BackendPortPtr();
} }
BackendPort* port = port_factory (name, type, flags); BackendPortPtr port (port_factory (name, type, flags));
if (!port) { if (!port) {
return 0; return BackendPortPtr ();
} }
{ {
@ -343,7 +344,7 @@ PortEngineSharedImpl::add_port (
void void
PortEngineSharedImpl::unregister_port (PortEngine::PortHandle port_handle) PortEngineSharedImpl::unregister_port (PortEngine::PortHandle port_handle)
{ {
BackendPort* port = static_cast<BackendPort*>(port_handle); BackendPortPtr port = boost::dynamic_pointer_cast<BackendPort>(port_handle);
{ {
RCUWriter<PortIndex> index_writer (_ports); RCUWriter<PortIndex> index_writer (_ports);
@ -352,20 +353,18 @@ PortEngineSharedImpl::unregister_port (PortEngine::PortHandle port_handle)
boost::shared_ptr<PortIndex> ps = index_writer.get_copy (); boost::shared_ptr<PortIndex> ps = index_writer.get_copy ();
boost::shared_ptr<PortMap> pm = map_writer.get_copy (); boost::shared_ptr<PortMap> pm = map_writer.get_copy ();
PortIndex::iterator i = std::find (ps->begin(), ps->end(), static_cast<BackendPort*>(port_handle)); PortIndex::iterator i = std::find (ps->begin(), ps->end(), boost::dynamic_pointer_cast<BackendPort> (port_handle));
if (i == ps->end ()) { if (i == ps->end ()) {
PBD::error << string_compose (_("%1::unregister_port: Failed to find port"), _instance_name) << endmsg; PBD::error << string_compose (_("%1::unregister_port: Failed to find port"), _instance_name) << endmsg;
return; return;
} }
disconnect_all(port_handle); disconnect_all (port_handle);
pm->erase (port->name()); pm->erase (port->name());
ps->erase (i); ps->erase (i);
} }
delete port;
} }
@ -386,11 +385,10 @@ PortEngineSharedImpl::unregister_ports (bool system_only)
for (PortIndex::iterator i = ps->begin (); i != ps->end ();) { for (PortIndex::iterator i = ps->begin (); i != ps->end ();) {
PortIndex::iterator cur = i++; PortIndex::iterator cur = i++;
BackendPort* port = *cur; BackendPortPtr port = *cur;
if (! system_only || (port->is_physical () && port->is_terminal ())) { if (! system_only || (port->is_physical () && port->is_terminal ())) {
port->disconnect_all (); port->disconnect_all (port);
pm->erase (port->name()); pm->erase (port->name());
delete port;
ps->erase (cur); ps->erase (cur);
} }
} }
@ -423,9 +421,10 @@ PortEngineSharedImpl::port_name_size () const
} }
int int
PortEngineSharedImpl::set_port_name (PortEngine::PortHandle port, const std::string& name) PortEngineSharedImpl::set_port_name (PortEngine::PortHandle port_handle, const std::string& name)
{ {
std::string newname (_instance_name + ":" + name); std::string newname (_instance_name + ":" + name);
BackendPortPtr port = boost::dynamic_pointer_cast<BackendPort>(port_handle);
if (!valid_port (port)) { if (!valid_port (port)) {
PBD::error << string_compose (_("%1::set_port_name: Invalid Port"), _instance_name) << endmsg; PBD::error << string_compose (_("%1::set_port_name: Invalid Port"), _instance_name) << endmsg;
@ -437,49 +436,53 @@ PortEngineSharedImpl::set_port_name (PortEngine::PortHandle port, const std::str
return -1; return -1;
} }
BackendPort* p = static_cast<BackendPort*>(port); int ret = port->set_name (newname);
if (ret == 0) {
{
RCUWriter<PortMap> map_writer (_portmap); RCUWriter<PortMap> map_writer (_portmap);
boost::shared_ptr<PortMap> pm = map_writer.get_copy (); boost::shared_ptr<PortMap> pm = map_writer.get_copy ();
pm->erase (p->name()); pm->erase (port->name());
pm->insert (make_pair (newname, p)); pm->insert (make_pair (newname, port));
} }
return p->set_name (newname); return ret;
} }
std::string std::string
PortEngineSharedImpl::get_port_name (PortEngine::PortHandle port) const PortEngineSharedImpl::get_port_name (PortEngine::PortHandle port_handle) const
{ {
BackendPortPtr port = boost::dynamic_pointer_cast<BackendPort>(port_handle);
if (!valid_port (port)) { if (!valid_port (port)) {
PBD::warning << string_compose (_("AlsaBackend::get_port_name: Invalid Port(s)"), _instance_name) << endmsg; PBD::warning << string_compose (_("AlsaBackend::get_port_name: Invalid Port(s)"), _instance_name) << endmsg;
return std::string (); return std::string ();
} }
return static_cast<BackendPort*>(port)->name ();
return port->name ();
} }
PortFlags PortFlags
PortEngineSharedImpl::get_port_flags (PortEngine::PortHandle port) const PortEngineSharedImpl::get_port_flags (PortEngine::PortHandle port) const
{ {
if (!valid_port (port)) { if (!valid_port (boost::dynamic_pointer_cast<BackendPort>(port))) {
PBD::warning << string_compose (_("%1::get_port_flags: Invalid Port(s)"), _instance_name) << endmsg; PBD::warning << string_compose (_("%1::get_port_flags: Invalid Port(s)"), _instance_name) << endmsg;
return PortFlags (0); return PortFlags (0);
} }
return static_cast<BackendPort*>(port)->flags (); return boost::static_pointer_cast<BackendPort>(port)->flags ();
} }
int int
PortEngineSharedImpl::get_port_property (PortEngine::PortHandle port, const std::string& key, std::string& value, std::string& type) const PortEngineSharedImpl::get_port_property (PortEngine::PortHandle port, const std::string& key, std::string& value, std::string& type) const
{ {
if (!valid_port (port)) { if (!valid_port (boost::dynamic_pointer_cast<BackendPort>(port))) {
PBD::warning << string_compose (_("%1::get_port_property: Invalid Port(s)"), _instance_name) << endmsg; PBD::warning << string_compose (_("%1::get_port_property: Invalid Port(s)"), _instance_name) << endmsg;
return -1; return -1;
} }
if (key == "http://jackaudio.org/metadata/pretty-name") { if (key == "http://jackaudio.org/metadata/pretty-name") {
type = ""; type = "";
value = static_cast<BackendPort*>(port)->pretty_name (); value = boost::static_pointer_cast<BackendPort>(port)->pretty_name ();
if (!value.empty()) { if (!value.empty()) {
return 0; return 0;
} }
@ -490,50 +493,51 @@ PortEngineSharedImpl::get_port_property (PortEngine::PortHandle port, const std:
int int
PortEngineSharedImpl::set_port_property (PortEngine::PortHandle port, const std::string& key, const std::string& value, const std::string& type) PortEngineSharedImpl::set_port_property (PortEngine::PortHandle port, const std::string& key, const std::string& value, const std::string& type)
{ {
if (!valid_port (port)) { if (!valid_port (boost::dynamic_pointer_cast<BackendPort>(port))) {
PBD::warning << string_compose (_("%1::set_port_property: Invalid Port(s)"), _instance_name) << endmsg; PBD::warning << string_compose (_("%1::set_port_property: Invalid Port(s)"), _instance_name) << endmsg;
return -1; return -1;
} }
if (key == "http://jackaudio.org/metadata/pretty-name" && type.empty ()) { if (key == "http://jackaudio.org/metadata/pretty-name" && type.empty ()) {
static_cast<BackendPort*>(port)->set_pretty_name (value); boost::static_pointer_cast<BackendPort>(port)->set_pretty_name (value);
return 0; return 0;
} }
return -1; return -1;
} }
PortEngine::PortHandle PortEngine::PortPtr
PortEngineSharedImpl::get_port_by_name (const std::string& name) const PortEngineSharedImpl::get_port_by_name (const std::string& name) const
{ {
PortEngine::PortHandle port = (PortEngine::PortHandle) find_port (name); return find_port (name);
return port;
} }
DataType DataType
PortEngineSharedImpl::port_data_type (PortEngine::PortHandle port) const PortEngineSharedImpl::port_data_type (PortEngine::PortHandle port) const
{ {
if (!valid_port (port)) { BackendPortPtr p = boost::dynamic_pointer_cast<BackendPort> (port);
if (!valid_port (p)) {
return DataType::NIL; return DataType::NIL;
} }
return static_cast<BackendPort*>(port)->type ();
return p->type ();
} }
PortEngine::PortHandle PortEngine::PortPtr
PortEngineSharedImpl::register_port ( PortEngineSharedImpl::register_port (
const std::string& name, const std::string& name,
ARDOUR::DataType type, ARDOUR::DataType type,
ARDOUR::PortFlags flags) ARDOUR::PortFlags flags)
{ {
if (name.size () == 0) { return 0; } if (name.size () == 0) { return PortEngine::PortPtr(); }
if (flags & IsPhysical) { return 0; } if (flags & IsPhysical) { return PortEngine::PortPtr(); }
return add_port (_instance_name + ":" + name, type, flags); return add_port (_instance_name + ":" + name, type, flags);
} }
int int
PortEngineSharedImpl::connect (const std::string& src, const std::string& dst) PortEngineSharedImpl::connect (const std::string& src, const std::string& dst)
{ {
BackendPort* src_port = find_port (src); BackendPortPtr src_port = find_port (src);
BackendPort* dst_port = find_port (dst); BackendPortPtr dst_port = find_port (dst);
if (!src_port) { if (!src_port) {
PBD::error << string_compose (_("%1::connect: Invalid Source port: (%2)"), _instance_name, src) << endmsg; PBD::error << string_compose (_("%1::connect: Invalid Source port: (%2)"), _instance_name, src) << endmsg;
@ -543,95 +547,118 @@ PortEngineSharedImpl::connect (const std::string& src, const std::string& dst)
PBD::error << string_compose (_("%1::connect: Invalid Destination port: (%2)"), _instance_name, dst) << endmsg; PBD::error << string_compose (_("%1::connect: Invalid Destination port: (%2)"), _instance_name, dst) << endmsg;
return -1; return -1;
} }
return src_port->connect (dst_port);
src_port->connect (dst_port, src_port);
return 0;
} }
int int
PortEngineSharedImpl::disconnect (const std::string& src, const std::string& dst) PortEngineSharedImpl::disconnect (const std::string& src, const std::string& dst)
{ {
BackendPort* src_port = find_port (src); BackendPortPtr src_port = find_port (src);
BackendPort* dst_port = find_port (dst); BackendPortPtr dst_port = find_port (dst);
if (!src_port || !dst_port) { if (!src_port || !dst_port) {
PBD::error << string_compose (_("%1::disconnect: Invalid Port(s)"), _instance_name) << endmsg; PBD::error << string_compose (_("%1::disconnect: Invalid Port(s)"), _instance_name) << endmsg;
return -1; return -1;
} }
return src_port->disconnect (dst_port); return src_port->disconnect (dst_port, src_port);
} }
int int
PortEngineSharedImpl::connect (PortEngine::PortHandle src, const std::string& dst) PortEngineSharedImpl::connect (PortEngine::PortHandle src, const std::string& dst)
{ {
BackendPort* dst_port = find_port (dst); BackendPortPtr src_port = boost::dynamic_pointer_cast<BackendPort> (src);
if (!valid_port (src)) {
if (!valid_port (src_port)) {
PBD::error << string_compose (_("%1::connect: Invalid Source Port Handle"), _instance_name) << endmsg; PBD::error << string_compose (_("%1::connect: Invalid Source Port Handle"), _instance_name) << endmsg;
return -1; return -1;
} }
BackendPortPtr dst_port = find_port (dst);
if (!dst_port) { if (!dst_port) {
PBD::error << string_compose (_("%1::connect: Invalid Destination Port: (%2)"), _instance_name, dst) << endmsg; PBD::error << string_compose (_("%1::connect: Invalid Destination Port: (%2)"), _instance_name, dst) << endmsg;
return -1; return -1;
} }
return static_cast<BackendPort*>(src)->connect (dst_port);
src_port->connect (dst_port, src_port);
return 0;
} }
int int
PortEngineSharedImpl::disconnect (PortEngine::PortHandle src, const std::string& dst) PortEngineSharedImpl::disconnect (PortEngine::PortHandle src, const std::string& dst)
{ {
BackendPort* dst_port = find_port (dst); BackendPortPtr src_port = boost::dynamic_pointer_cast<BackendPort>(src);
if (!valid_port (src) || !dst_port) { BackendPortPtr dst_port = find_port (dst);
if (!valid_port (src_port) || !dst_port) {
PBD::error << string_compose (_("%1::disconnect: Invalid Port(s)"), _instance_name) << endmsg; PBD::error << string_compose (_("%1::disconnect: Invalid Port(s)"), _instance_name) << endmsg;
return -1; return -1;
} }
return static_cast<BackendPort*>(src)->disconnect (dst_port); return src_port->disconnect (dst_port, src_port);
} }
int int
PortEngineSharedImpl::disconnect_all (PortEngine::PortHandle port) PortEngineSharedImpl::disconnect_all (PortEngine::PortHandle port_handle)
{ {
BackendPortPtr port = boost::dynamic_pointer_cast<BackendPort> (port_handle);
if (!valid_port (port)) { if (!valid_port (port)) {
PBD::error << string_compose (_("%1::disconnect_all: Invalid Port"), _instance_name) << endmsg; PBD::error << string_compose (_("%1::disconnect_all: Invalid Port"), _instance_name) << endmsg;
return -1; return -1;
} }
static_cast<BackendPort*>(port)->disconnect_all ();
port->disconnect_all (port);
return 0; return 0;
} }
bool bool
PortEngineSharedImpl::connected (PortEngine::PortHandle port, bool /* process_callback_safe*/) PortEngineSharedImpl::connected (PortEngine::PortHandle port_handle, bool /* process_callback_safe*/)
{ {
BackendPortPtr port = boost::dynamic_pointer_cast<BackendPort> (port_handle);
if (!valid_port (port)) { if (!valid_port (port)) {
PBD::error << string_compose (_("%1::disconnect_all: Invalid Port"), _instance_name) << endmsg; PBD::error << string_compose (_("%1::disconnect_all: Invalid Port"), _instance_name) << endmsg;
return false; return false;
} }
return static_cast<BackendPort*>(port)->is_connected (); return port->is_connected ();
} }
bool bool
PortEngineSharedImpl::connected_to (PortEngine::PortHandle src, const std::string& dst, bool /*process_callback_safe*/) PortEngineSharedImpl::connected_to (PortEngine::PortHandle src, const std::string& dst, bool /*process_callback_safe*/)
{ {
BackendPort* dst_port = find_port (dst); BackendPortPtr src_port = boost::dynamic_pointer_cast<BackendPort> (src);
BackendPortPtr dst_port = find_port (dst);
#ifndef NDEBUG #ifndef NDEBUG
if (!valid_port (src) || !dst_port) { if (!valid_port (src_port) || !dst_port) {
PBD::error << string_compose (_("%1::connected_to: Invalid Port"), _instance_name) << endmsg; PBD::error << string_compose (_("%1::connected_to: Invalid Port"), _instance_name) << endmsg;
return false; return false;
} }
#endif #endif
return static_cast<BackendPort*>(src)->is_connected (dst_port); return boost::static_pointer_cast<BackendPort>(src)->is_connected (dst_port);
} }
bool bool
PortEngineSharedImpl::physically_connected (PortEngine::PortHandle port, bool /*process_callback_safe*/) PortEngineSharedImpl::physically_connected (PortEngine::PortHandle port_handle, bool /*process_callback_safe*/)
{ {
BackendPortPtr port = boost::dynamic_pointer_cast<BackendPort> (port_handle);
if (!valid_port (port)) { if (!valid_port (port)) {
PBD::error << string_compose (_("%1::physically_connected: Invalid Port"), _instance_name) << endmsg; PBD::error << string_compose (_("%1::physically_connected: Invalid Port"), _instance_name) << endmsg;
return false; return false;
} }
return static_cast<BackendPort*>(port)->is_physically_connected (); return port->is_physically_connected ();
} }
int int
PortEngineSharedImpl::get_connections (PortEngine::PortHandle port, std::vector<std::string>& names, bool /*process_callback_safe*/) PortEngineSharedImpl::get_connections (PortEngine::PortHandle port_handle, std::vector<std::string>& names, bool /*process_callback_safe*/)
{ {
BackendPortPtr port = boost::dynamic_pointer_cast<BackendPort> (port_handle);
if (!valid_port (port)) { if (!valid_port (port)) {
PBD::error << string_compose (_("%1::get_connections: Invalid Port"), _instance_name) << endmsg; PBD::error << string_compose (_("%1::get_connections: Invalid Port"), _instance_name) << endmsg;
return -1; return -1;
@ -639,11 +666,29 @@ PortEngineSharedImpl::get_connections (PortEngine::PortHandle port, std::vector<
assert (0 == names.size ()); assert (0 == names.size ());
const std::set<BackendPort*>& connected_ports = static_cast<BackendPort*>(port)->get_connections (); const std::set<BackendPortPtr>& connected_ports = port->get_connections ();
for (std::set<BackendPort*>::const_iterator i = connected_ports.begin (); i != connected_ports.end (); ++i) { for (std::set<BackendPortPtr>::const_iterator i = connected_ports.begin (); i != connected_ports.end (); ++i) {
names.push_back ((*i)->name ()); names.push_back ((*i)->name ());
} }
return (int)names.size (); return (int)names.size ();
} }
void
PortEngineSharedImpl::update_system_port_latencies ()
{
for (std::vector<BackendPortPtr>::const_iterator it = _system_inputs.begin (); it != _system_inputs.end (); ++it) {
(*it)->update_connected_latency (true);
}
for (std::vector<BackendPortPtr>::const_iterator it = _system_outputs.begin (); it != _system_outputs.end (); ++it) {
(*it)->update_connected_latency (false);
}
for (std::vector<BackendPortPtr>::const_iterator it = _system_midi_in.begin (); it != _system_midi_in.end (); ++it) {
(*it)->update_connected_latency (true);
}
for (std::vector<BackendPortPtr>::const_iterator it = _system_midi_out.begin (); it != _system_midi_out.end (); ++it) {
(*it)->update_connected_latency (false);
}
}

View file

@ -464,12 +464,12 @@ AlsaAudioBackend::update_systemic_audio_latencies ()
LatencyRange lr; LatencyRange lr;
lr.min = lr.max = lcpp + (_measure_latency ? 0 : _systemic_audio_input_latency); lr.min = lr.max = lcpp + (_measure_latency ? 0 : _systemic_audio_input_latency);
for (std::vector<BackendPort*>::const_iterator it = _system_outputs.begin (); it != _system_outputs.end (); ++it) { for (std::vector<BackendPortPtr>::const_iterator it = _system_outputs.begin (); it != _system_outputs.end (); ++it) {
set_latency_range (*it, true, lr); set_latency_range (*it, true, lr);
} }
lr.min = lr.max = (_measure_latency ? 0 : _systemic_audio_output_latency); lr.min = lr.max = (_measure_latency ? 0 : _systemic_audio_output_latency);
for (std::vector<BackendPort*>::const_iterator it = _system_inputs.begin (); it != _system_inputs.end (); ++it) { for (std::vector<BackendPortPtr>::const_iterator it = _system_inputs.begin (); it != _system_inputs.end (); ++it) {
set_latency_range (*it, false, lr); set_latency_range (*it, false, lr);
} }
update_latencies (); update_latencies ();
@ -480,18 +480,18 @@ AlsaAudioBackend::update_systemic_midi_latencies ()
{ {
pthread_mutex_lock (&_device_port_mutex); pthread_mutex_lock (&_device_port_mutex);
uint32_t i = 0; uint32_t i = 0;
for (std::vector<BackendPort*>::iterator it = _system_midi_out.begin (); it != _system_midi_out.end (); ++it, ++i) { for (std::vector<BackendPortPtr>::iterator it = _system_midi_out.begin (); it != _system_midi_out.end (); ++it, ++i) {
assert (_rmidi_out.size() > i); assert (_rmidi_out.size() > i);
AlsaMidiOut *rm = _rmidi_out.at(i); AlsaMidiOut *rm = _rmidi_out.at(i);
struct AlsaMidiDeviceInfo * nfo = midi_device_info (rm->name()); struct AlsaMidiDeviceInfo * nfo = midi_device_info (rm->name());
assert (nfo); assert (nfo);
LatencyRange lr; LatencyRange lr;
lr.min = lr.max = (_measure_latency ? 0 : nfo->systemic_output_latency); lr.min = lr.max = (_measure_latency ? 0 : nfo->systemic_output_latency);
set_latency_range (*it, true, lr); set_latency_range (boost::dynamic_pointer_cast<AlsaAudioPort>(*it), true, lr);
} }
i = 0; i = 0;
for (std::vector<BackendPort*>::const_iterator it = _system_midi_in.begin (); it != _system_midi_in.end (); ++it, ++i) { for (std::vector<BackendPortPtr>::const_iterator it = _system_midi_in.begin (); it != _system_midi_in.end (); ++it, ++i) {
assert (_rmidi_in.size() > i); assert (_rmidi_in.size() > i);
AlsaMidiIO *rm = _rmidi_in.at(i); AlsaMidiIO *rm = _rmidi_in.at(i);
struct AlsaMidiDeviceInfo * nfo = midi_device_info (rm->name()); struct AlsaMidiDeviceInfo * nfo = midi_device_info (rm->name());
@ -685,7 +685,7 @@ AlsaAudioBackend::set_midi_device_enabled (std::string const device, bool enable
// remove all ports provided by the given device // remove all ports provided by the given device
pthread_mutex_lock (&_device_port_mutex); pthread_mutex_lock (&_device_port_mutex);
uint32_t i = 0; uint32_t i = 0;
for (std::vector<BackendPort*>::iterator it = _system_midi_out.begin (); it != _system_midi_out.end ();) { for (std::vector<BackendPortPtr>::iterator it = _system_midi_out.begin (); it != _system_midi_out.end ();) {
assert (_rmidi_out.size() > i); assert (_rmidi_out.size() > i);
AlsaMidiOut *rm = _rmidi_out.at(i); AlsaMidiOut *rm = _rmidi_out.at(i);
if (rm->name () != device) { ++it; ++i; continue; } if (rm->name () != device) { ++it; ++i; continue; }
@ -698,7 +698,7 @@ AlsaAudioBackend::set_midi_device_enabled (std::string const device, bool enable
} }
i = 0; i = 0;
for (std::vector<BackendPort*>::iterator it = _system_midi_in.begin (); it != _system_midi_in.end ();) { for (std::vector<BackendPortPtr>::iterator it = _system_midi_in.begin (); it != _system_midi_in.end ();) {
assert (_rmidi_in.size() > i); assert (_rmidi_in.size() > i);
AlsaMidiIn *rm = _rmidi_in.at(i); AlsaMidiIn *rm = _rmidi_in.at(i);
if (rm->name () != device) { ++it; ++i; continue; } if (rm->name () != device) { ++it; ++i; continue; }
@ -1192,7 +1192,7 @@ AlsaAudioBackend::register_system_audio_ports()
PortHandle p = add_port(std::string(tmp), DataType::AUDIO, static_cast<PortFlags>(IsOutput | IsPhysical | IsTerminal)); PortHandle p = add_port(std::string(tmp), DataType::AUDIO, static_cast<PortFlags>(IsOutput | IsPhysical | IsTerminal));
if (!p) return -1; if (!p) return -1;
set_latency_range (p, false, lr); set_latency_range (p, false, lr);
BackendPort *ap = static_cast<BackendPort*>(p); BackendPortPtr ap = boost::dynamic_pointer_cast<BackendPort>(p);
//ap->set_pretty_name ("") //ap->set_pretty_name ("")
_system_inputs.push_back (ap); _system_inputs.push_back (ap);
} }
@ -1204,7 +1204,7 @@ AlsaAudioBackend::register_system_audio_ports()
PortHandle p = add_port(std::string(tmp), DataType::AUDIO, static_cast<PortFlags>(IsInput | IsPhysical | IsTerminal)); PortHandle p = add_port(std::string(tmp), DataType::AUDIO, static_cast<PortFlags>(IsInput | IsPhysical | IsTerminal));
if (!p) return -1; if (!p) return -1;
set_latency_range (p, true, lr); set_latency_range (p, true, lr);
BackendPort *ap = static_cast<BackendPort*>(p); BackendPortPtr ap = boost::dynamic_pointer_cast<BackendPort>(p);
//ap->set_pretty_name ("") //ap->set_pretty_name ("")
_system_outputs.push_back (ap); _system_outputs.push_back (ap);
} }
@ -1351,32 +1351,25 @@ AlsaAudioBackend::stop_listen_for_midi_device_changes ()
* and capture-latency for _system_outputs * and capture-latency for _system_outputs
*/ */
void void
AlsaAudioBackend::update_system_port_latecies () AlsaAudioBackend::update_system_port_latencies ()
{ {
for (std::vector<BackendPort*>::const_iterator it = _system_inputs.begin (); it != _system_inputs.end (); ++it) {
(*it)->update_connected_latency (true);
}
for (std::vector<BackendPort*>::const_iterator it = _system_outputs.begin (); it != _system_outputs.end (); ++it) {
(*it)->update_connected_latency (false);
}
pthread_mutex_lock (&_device_port_mutex); pthread_mutex_lock (&_device_port_mutex);
for (std::vector<BackendPort*>::const_iterator it = _system_midi_in.begin (); it != _system_midi_in.end (); ++it) {
(*it)->update_connected_latency (true); PortEngineSharedImpl::update_system_port_latencies ();
}
for (std::vector<BackendPort*>::const_iterator it = _system_midi_out.begin (); it != _system_midi_out.end (); ++it) {
(*it)->update_connected_latency (false);
}
pthread_mutex_unlock (&_device_port_mutex); pthread_mutex_unlock (&_device_port_mutex);
for (AudioSlaves::iterator s = _slaves.begin (); s != _slaves.end (); ++s) { for (AudioSlaves::iterator s = _slaves.begin (); s != _slaves.end (); ++s) {
if ((*s)->dead) { if ((*s)->dead) {
continue; continue;
} }
for (std::vector<BackendPort*>::const_iterator it = (*s)->inputs.begin (); it != (*s)->inputs.end (); ++it) {
for (std::vector<BackendPortPtr>::const_iterator it = (*s)->inputs.begin (); it != (*s)->inputs.end (); ++it) {
(*it)->update_connected_latency (true); (*it)->update_connected_latency (true);
} }
for (std::vector<BackendPort*>::const_iterator it = (*s)->outputs.begin (); it != (*s)->outputs.end (); ++it) {
for (std::vector<BackendPortPtr>::const_iterator it = (*s)->outputs.begin (); it != (*s)->outputs.end (); ++it) {
(*it)->update_connected_latency (false); (*it)->update_connected_latency (false);
} }
} }
@ -1472,8 +1465,8 @@ AlsaAudioBackend::register_system_midi_ports(const std::string device)
LatencyRange lr; LatencyRange lr;
lr.min = lr.max = (nfo->systemic_output_latency); lr.min = lr.max = (nfo->systemic_output_latency);
set_latency_range (p, true, lr); set_latency_range (p, true, lr);
static_cast<AlsaMidiPort*>(p)->set_n_periods(_periods_per_cycle); // TODO check MIDI alignment boost::dynamic_pointer_cast<AlsaMidiPort>(p)->set_n_periods(_periods_per_cycle); // TODO check MIDI alignment
BackendPort *ap = static_cast<BackendPort*>(p); BackendPortPtr ap = boost::dynamic_pointer_cast<BackendPort>(p);
ap->set_pretty_name (replace_name_io (i->first, false)); ap->set_pretty_name (replace_name_io (i->first, false));
pthread_mutex_lock (&_device_port_mutex); pthread_mutex_lock (&_device_port_mutex);
_system_midi_out.push_back (ap); _system_midi_out.push_back (ap);
@ -1520,7 +1513,7 @@ AlsaAudioBackend::register_system_midi_ports(const std::string device)
LatencyRange lr; LatencyRange lr;
lr.min = lr.max = (nfo->systemic_input_latency); lr.min = lr.max = (nfo->systemic_input_latency);
set_latency_range (p, false, lr); set_latency_range (p, false, lr);
BackendPort *ap = static_cast<BackendPort*>(p); BackendPortPtr ap = boost::dynamic_pointer_cast<BackendPort>(p);
ap->set_pretty_name (replace_name_io (i->first, true)); ap->set_pretty_name (replace_name_io (i->first, true));
pthread_mutex_lock (&_device_port_mutex); pthread_mutex_lock (&_device_port_mutex);
_system_midi_in.push_back (ap); _system_midi_in.push_back (ap);
@ -1619,38 +1612,40 @@ AlsaAudioBackend::monitoring_input (PortEngine::PortHandle)
/* Latency management */ /* Latency management */
void void
AlsaAudioBackend::set_latency_range (PortEngine::PortHandle port, bool for_playback, LatencyRange latency_range) AlsaAudioBackend::set_latency_range (PortEngine::PortHandle port_handle, bool for_playback, LatencyRange latency_range)
{ {
BackendPortPtr port = boost::dynamic_pointer_cast<BackendPort> (port_handle);
if (!valid_port (port)) { if (!valid_port (port)) {
PBD::error << _("AlsaPort::set_latency_range (): invalid port.") << endmsg; PBD::error << _("AlsaPort::set_latency_range (): invalid port.") << endmsg;
} }
static_cast<BackendPort*>(port)->set_latency_range (latency_range, for_playback); port->set_latency_range (latency_range, for_playback);
} }
LatencyRange LatencyRange
AlsaAudioBackend::get_latency_range (PortEngine::PortHandle port, bool for_playback) AlsaAudioBackend::get_latency_range (PortEngine::PortHandle port_handle, bool for_playback)
{ {
BackendPortPtr port = boost::dynamic_pointer_cast<BackendPort> (port_handle);
LatencyRange r; LatencyRange r;
if (!valid_port (port)) { if (!valid_port (port)) {
PBD::error << _("AlsaPort::get_latency_range (): invalid port.") << endmsg; PBD::error << _("AlsaPort::get_latency_range (): invalid port.") << endmsg;
r.min = 0; r.min = 0;
r.max = 0; r.max = 0;
return r; return r;
} }
BackendPort *p = static_cast<BackendPort*>(port);
assert(p);
r = p->latency_range (for_playback); r = port->latency_range (for_playback);
if (p->is_physical() && p->is_terminal()) { if (port->is_physical() && port->is_terminal()) {
if (p->is_input() && for_playback) { if (port->is_input() && for_playback) {
r.min += _samples_per_period; r.min += _samples_per_period;
r.max += _samples_per_period; r.max += _samples_per_period;
} }
if (p->is_output() && !for_playback) { if (port->is_output() && !for_playback) {
r.min += _samples_per_period; r.min += _samples_per_period;
r.max += _samples_per_period; r.max += _samples_per_period;
} }
} }
return r; return r;
} }
@ -1677,11 +1672,12 @@ AlsaAudioBackend::port_factory (std::string const & name, ARDOUR::DataType type,
/* Getting access to the data buffer for a port */ /* Getting access to the data buffer for a port */
void* void*
AlsaAudioBackend::get_buffer (PortEngine::PortHandle port, pframes_t nframes) AlsaAudioBackend::get_buffer (PortEngine::PortHandle port_handle, pframes_t nframes)
{ {
BackendPortPtr port = boost::dynamic_pointer_cast<BackendPort> (port_handle);
assert (port); assert (port);
assert (valid_port (port)); assert (valid_port (port));
return static_cast<BackendPort*>(port)->get_buffer (nframes); return port->get_buffer (nframes);
} }
/* Engine Process */ /* Engine Process */
@ -1710,7 +1706,7 @@ AlsaAudioBackend::main_process_thread ()
/* warm up */ /* warm up */
int cnt = std::max (8, (int)(_samplerate / _samples_per_period) / 2); int cnt = std::max (8, (int)(_samplerate / _samples_per_period) / 2);
for (int w = 0; w < cnt; ++w) { for (int w = 0; w < cnt; ++w) {
for (std::vector<BackendPort*>::const_iterator it = _system_inputs.begin (); it != _system_inputs.end (); ++it) { for (std::vector<BackendPortPtr>::const_iterator it = _system_inputs.begin (); it != _system_inputs.end (); ++it) {
memset ((*it)->get_buffer (_samples_per_period), 0, _samples_per_period * sizeof (Sample)); memset ((*it)->get_buffer (_samples_per_period), 0, _samples_per_period * sizeof (Sample));
} }
if (engine.process_callback (_samples_per_period)) { if (engine.process_callback (_samples_per_period)) {
@ -1767,10 +1763,10 @@ AlsaAudioBackend::main_process_thread ()
if ((*s)->halt) { if ((*s)->halt) {
/* slave died, unregister its ports (not rt-safe, but no matter) */ /* slave died, unregister its ports (not rt-safe, but no matter) */
PBD::error << _("ALSA Slave device halted") << endmsg; PBD::error << _("ALSA Slave device halted") << endmsg;
for (std::vector<BackendPort*>::const_iterator it = (*s)->inputs.begin (); it != (*s)->inputs.end (); ++it) { for (std::vector<BackendPortPtr>::const_iterator it = (*s)->inputs.begin (); it != (*s)->inputs.end (); ++it) {
unregister_port (*it); unregister_port (*it);
} }
for (std::vector<BackendPort*>::const_iterator it = (*s)->outputs.begin (); it != (*s)->outputs.end (); ++it) { for (std::vector<BackendPortPtr>::const_iterator it = (*s)->outputs.begin (); it != (*s)->outputs.end (); ++it) {
unregister_port (*it); unregister_port (*it);
} }
(*s)->inputs.clear (); (*s)->inputs.clear ();
@ -1810,8 +1806,8 @@ AlsaAudioBackend::main_process_thread ()
no_proc_errors = 0; no_proc_errors = 0;
_pcmi->capt_init (_samples_per_period); _pcmi->capt_init (_samples_per_period);
for (std::vector<BackendPort*>::const_iterator it = _system_inputs.begin (); it != _system_inputs.end (); ++it, ++i) { for (std::vector<BackendPortPtr>::const_iterator it = _system_inputs.begin (); it != _system_inputs.end (); ++it, ++i) {
_pcmi->capt_chan (i, (float*)((*it)->get_buffer(_samples_per_period)), _samples_per_period); _pcmi->capt_chan (i, (float*)(*it)->get_buffer(_samples_per_period), _samples_per_period);
} }
_pcmi->capt_done (_samples_per_period); _pcmi->capt_done (_samples_per_period);
@ -1820,8 +1816,8 @@ AlsaAudioBackend::main_process_thread ()
continue; continue;
} }
i = 0; i = 0;
for (std::vector<BackendPort*>::const_iterator it = (*s)->inputs.begin (); it != (*s)->inputs.end (); ++it, ++i) { for (std::vector<BackendPortPtr>::const_iterator it = (*s)->inputs.begin (); it != (*s)->inputs.end (); ++it, ++i) {
(*s)->capt_chan (i, (float*)((*it)->get_buffer(_samples_per_period)), _samples_per_period); (*s)->capt_chan (i, (float*)(boost::dynamic_pointer_cast<BackendPort>(*it)->get_buffer(_samples_per_period)), _samples_per_period);
} }
} }
@ -1829,7 +1825,7 @@ AlsaAudioBackend::main_process_thread ()
pthread_mutex_lock (&_device_port_mutex); pthread_mutex_lock (&_device_port_mutex);
/* de-queue incoming midi*/ /* de-queue incoming midi*/
i = 0; i = 0;
for (std::vector<BackendPort*>::const_iterator it = _system_midi_in.begin (); it != _system_midi_in.end (); ++it, ++i) { for (std::vector<BackendPortPtr>::const_iterator it = _system_midi_in.begin (); it != _system_midi_in.end (); ++it, ++i) {
assert (_rmidi_in.size() > i); assert (_rmidi_in.size() > i);
AlsaMidiIn *rm = _rmidi_in.at(i); AlsaMidiIn *rm = _rmidi_in.at(i);
void *bptr = (*it)->get_buffer(0); void *bptr = (*it)->get_buffer(0);
@ -1845,7 +1841,7 @@ AlsaAudioBackend::main_process_thread ()
} }
pthread_mutex_unlock (&_device_port_mutex); pthread_mutex_unlock (&_device_port_mutex);
for (std::vector<BackendPort*>::const_iterator it = _system_outputs.begin (); it != _system_outputs.end (); ++it) { for (std::vector<BackendPortPtr>::const_iterator it = _system_outputs.begin (); it != _system_outputs.end (); ++it) {
memset ((*it)->get_buffer (_samples_per_period), 0, _samples_per_period * sizeof (Sample)); memset ((*it)->get_buffer (_samples_per_period), 0, _samples_per_period * sizeof (Sample));
} }
@ -1859,15 +1855,15 @@ AlsaAudioBackend::main_process_thread ()
/* only used when adding/removing MIDI device/system ports */ /* only used when adding/removing MIDI device/system ports */
pthread_mutex_lock (&_device_port_mutex); pthread_mutex_lock (&_device_port_mutex);
for (std::vector<BackendPort*>::iterator it = _system_midi_out.begin (); it != _system_midi_out.end (); ++it) { for (std::vector<BackendPortPtr>::iterator it = _system_midi_out.begin (); it != _system_midi_out.end (); ++it) {
static_cast<AlsaMidiPort*>(*it)->next_period(); boost::dynamic_pointer_cast<AlsaMidiPort>(*it)->next_period();
} }
/* queue outgoing midi */ /* queue outgoing midi */
i = 0; i = 0;
for (std::vector<BackendPort*>::const_iterator it = _system_midi_out.begin (); it != _system_midi_out.end (); ++it, ++i) { for (std::vector<BackendPortPtr>::const_iterator it = _system_midi_out.begin (); it != _system_midi_out.end (); ++it, ++i) {
assert (_rmidi_out.size() > i); assert (_rmidi_out.size() > i);
const AlsaMidiBuffer * src = static_cast<const AlsaMidiPort*>(*it)->const_buffer(); AlsaMidiBuffer const * src = boost::dynamic_pointer_cast<const AlsaMidiPort>(*it)->const_buffer();
AlsaMidiOut *rm = _rmidi_out.at(i); AlsaMidiOut *rm = _rmidi_out.at(i);
rm->sync_time (clock1); rm->sync_time (clock1);
for (AlsaMidiBuffer::const_iterator mit = src->begin (); mit != src->end (); ++mit) { for (AlsaMidiBuffer::const_iterator mit = src->begin (); mit != src->end (); ++mit) {
@ -1879,7 +1875,7 @@ AlsaAudioBackend::main_process_thread ()
/* write back audio */ /* write back audio */
i = 0; i = 0;
_pcmi->play_init (_samples_per_period); _pcmi->play_init (_samples_per_period);
for (std::vector<BackendPort*>::const_iterator it = _system_outputs.begin (); it != _system_outputs.end (); ++it, ++i) { for (std::vector<BackendPortPtr>::const_iterator it = _system_outputs.begin (); it != _system_outputs.end (); ++it, ++i) {
_pcmi->play_chan (i, (const float*)(*it)->get_buffer (_samples_per_period), _samples_per_period); _pcmi->play_chan (i, (const float*)(*it)->get_buffer (_samples_per_period), _samples_per_period);
} }
for (; i < _pcmi->nplay (); ++i) { for (; i < _pcmi->nplay (); ++i) {
@ -1892,8 +1888,8 @@ AlsaAudioBackend::main_process_thread ()
continue; continue;
} }
i = 0; i = 0;
for (std::vector<BackendPort*>::const_iterator it = (*s)->outputs.begin (); it != (*s)->outputs.end (); ++it, ++i) { for (std::vector<BackendPortPtr>::const_iterator it = (*s)->outputs.begin (); it != (*s)->outputs.end (); ++it, ++i) {
(*s)->play_chan (i, (float*)((*it)->get_buffer(_samples_per_period)), _samples_per_period); (*s)->play_chan (i, (float*)(*it)->get_buffer(_samples_per_period), _samples_per_period);
} }
(*s)->cycle_end (); (*s)->cycle_end ();
} }
@ -1920,14 +1916,14 @@ AlsaAudioBackend::main_process_thread ()
// Freewheelin' // Freewheelin'
// zero audio input buffers // zero audio input buffers
for (std::vector<BackendPort*>::const_iterator it = _system_inputs.begin (); it != _system_inputs.end (); ++it) { for (std::vector<BackendPortPtr>::const_iterator it = _system_inputs.begin (); it != _system_inputs.end (); ++it) {
memset ((*it)->get_buffer (_samples_per_period), 0, _samples_per_period * sizeof (Sample)); memset ((*it)->get_buffer (_samples_per_period), 0, _samples_per_period * sizeof (Sample));
} }
clock1 = g_get_monotonic_time(); clock1 = g_get_monotonic_time();
uint32_t i = 0; uint32_t i = 0;
pthread_mutex_lock (&_device_port_mutex); pthread_mutex_lock (&_device_port_mutex);
for (std::vector<BackendPort*>::const_iterator it = _system_midi_in.begin (); it != _system_midi_in.end (); ++it, ++i) { for (std::vector<BackendPortPtr>::const_iterator it = _system_midi_in.begin (); it != _system_midi_in.end (); ++it, ++i) {
static_cast<AlsaMidiBuffer*>((*it)->get_buffer(0))->clear (); static_cast<AlsaMidiBuffer*>((*it)->get_buffer(0))->clear ();
AlsaMidiIn *rm = _rmidi_in.at(i); AlsaMidiIn *rm = _rmidi_in.at(i);
void *bptr = (*it)->get_buffer(0); void *bptr = (*it)->get_buffer(0);
@ -1953,7 +1949,7 @@ AlsaAudioBackend::main_process_thread ()
// drop all outgoing MIDI messages // drop all outgoing MIDI messages
pthread_mutex_lock (&_device_port_mutex); pthread_mutex_lock (&_device_port_mutex);
for (std::vector<BackendPort*>::const_iterator it = _system_midi_out.begin (); it != _system_midi_out.end (); ++it) { for (std::vector<BackendPortPtr>::const_iterator it = _system_midi_out.begin (); it != _system_midi_out.end (); ++it) {
void *bptr = (*it)->get_buffer(0); void *bptr = (*it)->get_buffer(0);
midi_clear(bptr); midi_clear(bptr);
} }
@ -1989,7 +1985,7 @@ AlsaAudioBackend::main_process_thread ()
manager.graph_order_callback(); manager.graph_order_callback();
} }
if (connections_changed || ports_changed) { if (connections_changed || ports_changed) {
update_system_port_latecies (); // flush, clear update_system_port_latencies (); // flush, clear
engine.latency_callback(false); engine.latency_callback(false);
engine.latency_callback(true); engine.latency_callback(true);
} }
@ -2031,10 +2027,9 @@ AlsaAudioBackend::add_slave (const char* device,
break; break;
} }
} while (1); } while (1);
PortHandle p = add_port(std::string(tmp), DataType::AUDIO, static_cast<PortFlags>(IsOutput | IsPhysical | IsTerminal)); PortPtr p = add_port(std::string(tmp), DataType::AUDIO, static_cast<PortFlags>(IsOutput | IsPhysical | IsTerminal));
if (!p) goto errout; if (!p) goto errout;
BackendPort *ap = static_cast<BackendPort*>(p); s->inputs.push_back (boost::dynamic_pointer_cast<BackendPort>(p));
s->inputs.push_back (ap);
} }
for (uint32_t i = 0, n = 1; i < s->nplay (); ++i) { for (uint32_t i = 0, n = 1; i < s->nplay (); ++i) {
@ -2047,10 +2042,9 @@ AlsaAudioBackend::add_slave (const char* device,
break; break;
} }
} while (1); } while (1);
PortHandle p = add_port(std::string(tmp), DataType::AUDIO, static_cast<PortFlags>(IsInput | IsPhysical | IsTerminal)); PortPtr p = add_port(std::string(tmp), DataType::AUDIO, static_cast<PortFlags>(IsInput | IsPhysical | IsTerminal));
if (!p) goto errout; if (!p) goto errout;
BackendPort *ap = static_cast<BackendPort*>(p); s->outputs.push_back (boost::dynamic_pointer_cast<BackendPort> (p));
s->outputs.push_back (ap);
} }
if (!s->start ()) { if (!s->start ()) {
@ -2105,12 +2099,12 @@ AlsaAudioBackend::AudioSlave::update_latencies (uint32_t play, uint32_t capt)
{ {
LatencyRange lr; LatencyRange lr;
lr.min = lr.max = (capt); lr.min = lr.max = (capt);
for (std::vector<BackendPort*>::const_iterator it = inputs.begin (); it != inputs.end (); ++it) { for (std::vector<BackendPortPtr>::const_iterator it = inputs.begin (); it != inputs.end (); ++it) {
(*it)->set_latency_range (lr, false); (*it)->set_latency_range (lr, false);
} }
lr.min = lr.max = play; lr.min = lr.max = play;
for (std::vector<BackendPort*>::const_iterator it = outputs.begin (); it != outputs.end (); ++it) { for (std::vector<BackendPortPtr>::const_iterator it = outputs.begin (); it != outputs.end (); ++it) {
(*it)->set_latency_range (lr, true); (*it)->set_latency_range (lr, true);
} }
printf (" ----- SLAVE LATENCY play=%d capt=%d\n", play, capt); // XXX DEBUG printf (" ----- SLAVE LATENCY play=%d capt=%d\n", play, capt); // XXX DEBUG
@ -2184,24 +2178,25 @@ AlsaAudioPort::AlsaAudioPort (AlsaAudioBackend &b, const std::string& name, Port
: BackendPort (b, name, flags) : BackendPort (b, name, flags)
{ {
memset (_buffer, 0, sizeof (_buffer)); memset (_buffer, 0, sizeof (_buffer));
mlock(_buffer, sizeof (_buffer)); mlock (_buffer, sizeof (_buffer));
} }
AlsaAudioPort::~AlsaAudioPort () { } AlsaAudioPort::~AlsaAudioPort () { }
void* AlsaAudioPort::get_buffer (pframes_t n_samples) void*
AlsaAudioPort::get_buffer (pframes_t n_samples)
{ {
if (is_input ()) { if (is_input ()) {
const std::set<BackendPort *>& connections = get_connections (); const std::set<BackendPortPtr>& connections = get_connections ();
std::set<BackendPort*>::const_iterator it = connections.begin (); std::set<BackendPortPtr>::const_iterator it = connections.begin ();
if (it == connections.end ()) { if (it == connections.end ()) {
memset (_buffer, 0, n_samples * sizeof (Sample)); memset (_buffer, 0, n_samples * sizeof (Sample));
} else { } else {
AlsaAudioPort const * source = static_cast<const AlsaAudioPort*>(*it); boost::shared_ptr<const AlsaAudioPort> source = boost::dynamic_pointer_cast<const AlsaAudioPort>(*it);
assert (source && source->is_output ()); assert (source && source->is_output ());
memcpy (_buffer, source->const_buffer (), n_samples * sizeof (Sample)); memcpy (_buffer, source->const_buffer (), n_samples * sizeof (Sample));
while (++it != connections.end ()) { while (++it != connections.end ()) {
source = static_cast<const AlsaAudioPort*>(*it); source = boost::dynamic_pointer_cast<const AlsaAudioPort>(*it);
assert (source && source->is_output ()); assert (source && source->is_output ());
Sample* dst = buffer (); Sample* dst = buffer ();
const Sample* src = source->const_buffer (); const Sample* src = source->const_buffer ();
@ -2241,11 +2236,11 @@ void* AlsaMidiPort::get_buffer (pframes_t /* nframes */)
{ {
if (is_input ()) { if (is_input ()) {
(_buffer[_bufperiod]).clear (); (_buffer[_bufperiod]).clear ();
const std::set<BackendPort*>& connections = get_connections (); const std::set<BackendPortPtr>& connections = get_connections ();
for (std::set<BackendPort*>::const_iterator i = connections.begin (); for (std::set<BackendPortPtr>::const_iterator i = connections.begin ();
i != connections.end (); i != connections.end ();
++i) { ++i) {
const AlsaMidiBuffer * src = static_cast<const AlsaMidiPort*>(*i)->const_buffer (); const AlsaMidiBuffer * src = boost::dynamic_pointer_cast<const AlsaMidiPort>(*i)->const_buffer ();
for (AlsaMidiBuffer::const_iterator it = src->begin (); it != src->end (); ++it) { for (AlsaMidiBuffer::const_iterator it = src->begin (); it != src->end (); ++it) {
(_buffer[_bufperiod]).push_back (*it); (_buffer[_bufperiod]).push_back (*it);
} }

View file

@ -232,12 +232,12 @@ class AlsaAudioBackend : public AudioBackend, public PortEngineSharedImpl
int set_port_name (PortEngine::PortHandle ph, const std::string& name) { return PortEngineSharedImpl::set_port_name (ph, name); } int set_port_name (PortEngine::PortHandle ph, const std::string& name) { return PortEngineSharedImpl::set_port_name (ph, name); }
std::string get_port_name (PortEngine::PortHandle ph) const { return PortEngineSharedImpl::get_port_name (ph); } std::string get_port_name (PortEngine::PortHandle ph) const { return PortEngineSharedImpl::get_port_name (ph); }
PortFlags get_port_flags (PortEngine::PortHandle ph) const { return PortEngineSharedImpl::get_port_flags (ph); } PortFlags get_port_flags (PortEngine::PortHandle ph) const { return PortEngineSharedImpl::get_port_flags (ph); }
PortEngine::PortHandle get_port_by_name (std::string const & name) const { return PortEngineSharedImpl::get_port_by_name (name); } PortEngine::PortPtr get_port_by_name (std::string const & name) const { return PortEngineSharedImpl::get_port_by_name (name); }
int get_port_property (PortEngine::PortHandle ph, const std::string& key, std::string& value, std::string& type) const { return PortEngineSharedImpl::get_port_property (ph, key, value, type); } int get_port_property (PortEngine::PortHandle ph, const std::string& key, std::string& value, std::string& type) const { return PortEngineSharedImpl::get_port_property (ph, key, value, type); }
int set_port_property (PortEngine::PortHandle ph, const std::string& key, const std::string& value, const std::string& type) { return PortEngineSharedImpl::set_port_property (ph, key, value, type); } int set_port_property (PortEngine::PortHandle ph, const std::string& key, const std::string& value, const std::string& type) { return PortEngineSharedImpl::set_port_property (ph, key, value, type); }
int get_ports (const std::string& port_name_pattern, DataType type, PortFlags flags, std::vector<std::string>& results) const { return PortEngineSharedImpl::get_ports (port_name_pattern, type, flags, results); } int get_ports (const std::string& port_name_pattern, DataType type, PortFlags flags, std::vector<std::string>& results) const { return PortEngineSharedImpl::get_ports (port_name_pattern, type, flags, results); }
DataType port_data_type (PortEngine::PortHandle ph) const { return PortEngineSharedImpl::port_data_type (ph); } DataType port_data_type (PortEngine::PortHandle ph) const { return PortEngineSharedImpl::port_data_type (ph); }
PortEngine::PortHandle register_port (const std::string& shortname, ARDOUR::DataType type, ARDOUR::PortFlags flags) { return PortEngineSharedImpl::register_port (shortname, type, flags); } PortEngine::PortPtr register_port (const std::string& shortname, ARDOUR::DataType type, ARDOUR::PortFlags flags) { return PortEngineSharedImpl::register_port (shortname, type, flags); }
void unregister_port (PortHandle ph) { if (!_run) return; PortEngineSharedImpl::unregister_port (ph); } void unregister_port (PortHandle ph) { if (!_run) return; PortEngineSharedImpl::unregister_port (ph); }
int connect (const std::string& src, const std::string& dst) { return PortEngineSharedImpl::connect (src, dst); } int connect (const std::string& src, const std::string& dst) { return PortEngineSharedImpl::connect (src, dst); }
int disconnect (const std::string& src, const std::string& dst) { return PortEngineSharedImpl::disconnect (src, dst); } int disconnect (const std::string& src, const std::string& dst) { return PortEngineSharedImpl::disconnect (src, dst); }
@ -366,7 +366,7 @@ class AlsaAudioBackend : public AudioBackend, public PortEngineSharedImpl
int register_system_audio_ports (); int register_system_audio_ports ();
int register_system_midi_ports (const std::string device = ""); int register_system_midi_ports (const std::string device = "");
void update_system_port_latecies (); void update_system_port_latencies ();
std::vector<AlsaMidiOut *> _rmidi_out; std::vector<AlsaMidiOut *> _rmidi_out;
std::vector<AlsaMidiIn *> _rmidi_in; std::vector<AlsaMidiIn *> _rmidi_in;
@ -422,8 +422,8 @@ class AlsaAudioBackend : public AudioBackend, public PortEngineSharedImpl
bool halt; bool halt;
bool dead; bool dead;
std::vector<BackendPort *> inputs; std::vector<BackendPortPtr> inputs;
std::vector<BackendPort *> outputs; std::vector<BackendPortPtr> outputs;
PBD::Signal0<void> UpdateLatency; PBD::Signal0<void> UpdateLatency;
PBD::ScopedConnection latency_connection; PBD::ScopedConnection latency_connection;

View file

@ -973,24 +973,6 @@ CoreAudioBackend::register_system_audio_ports()
return 0; return 0;
} }
void
CoreAudioBackend::update_system_port_latecies ()
{
for (std::vector<BackendPort*>::const_iterator it = _system_inputs.begin (); it != _system_inputs.end (); ++it) {
(*it)->update_connected_latency (true);
}
for (std::vector<BackendPort*>::const_iterator it = _system_outputs.begin (); it != _system_outputs.end (); ++it) {
(*it)->update_connected_latency (false);
}
for (std::vector<BackendPort*>::const_iterator it = _system_midi_in.begin (); it != _system_midi_in.end (); ++it) {
(*it)->update_connected_latency (true);
}
for (std::vector<BackendPort*>::const_iterator it = _system_midi_out.begin (); it != _system_midi_out.end (); ++it) {
(*it)->update_connected_latency (false);
}
}
void void
CoreAudioBackend::coremidi_rediscover() CoreAudioBackend::coremidi_rediscover()
{ {
@ -1275,7 +1257,7 @@ CoreAudioBackend::pre_process ()
manager.graph_order_callback(); manager.graph_order_callback();
} }
if (connections_changed || ports_changed) { if (connections_changed || ports_changed) {
update_system_port_latecies (); update_system_port_latencies ();
engine.latency_callback(false); engine.latency_callback(false);
engine.latency_callback(true); engine.latency_callback(true);
} }

View file

@ -278,12 +278,12 @@ class CoreAudioBackend : public AudioBackend, public PortEngineSharedImpl {
int set_port_name (PortEngine::PortHandle ph, const std::string& name) { return PortEngineSharedImpl::set_port_name (ph, name); } int set_port_name (PortEngine::PortHandle ph, const std::string& name) { return PortEngineSharedImpl::set_port_name (ph, name); }
std::string get_port_name (PortEngine::PortHandle ph) const { return PortEngineSharedImpl::get_port_name (ph); } std::string get_port_name (PortEngine::PortHandle ph) const { return PortEngineSharedImpl::get_port_name (ph); }
PortFlags get_port_flags (PortEngine::PortHandle ph) const { return PortEngineSharedImpl::get_port_flags (ph); } PortFlags get_port_flags (PortEngine::PortHandle ph) const { return PortEngineSharedImpl::get_port_flags (ph); }
PortEngine::PortHandle get_port_by_name (std::string const & name) const { return PortEngineSharedImpl::get_port_by_name (name); } PortEngine::PortPtr get_port_by_name (std::string const & name) const { return PortEngineSharedImpl::get_port_by_name (name); }
int get_port_property (PortEngine::PortHandle ph, const std::string& key, std::string& value, std::string& type) const { return PortEngineSharedImpl::get_port_property (ph, key, value, type); } int get_port_property (PortEngine::PortHandle ph, const std::string& key, std::string& value, std::string& type) const { return PortEngineSharedImpl::get_port_property (ph, key, value, type); }
int set_port_property (PortEngine::PortHandle ph, const std::string& key, const std::string& value, const std::string& type) { return PortEngineSharedImpl::set_port_property (ph, key, value, type); } int set_port_property (PortEngine::PortHandle ph, const std::string& key, const std::string& value, const std::string& type) { return PortEngineSharedImpl::set_port_property (ph, key, value, type); }
int get_ports (const std::string& port_name_pattern, DataType type, PortFlags flags, std::vector<std::string>& results) const { return PortEngineSharedImpl::get_ports (port_name_pattern, type, flags, results); } int get_ports (const std::string& port_name_pattern, DataType type, PortFlags flags, std::vector<std::string>& results) const { return PortEngineSharedImpl::get_ports (port_name_pattern, type, flags, results); }
DataType port_data_type (PortEngine::PortHandle ph) const { return PortEngineSharedImpl::port_data_type (ph); } DataType port_data_type (PortEngine::PortHandle ph) const { return PortEngineSharedImpl::port_data_type (ph); }
PortEngine::PortHandle register_port (const std::string& shortname, ARDOUR::DataType type, ARDOUR::PortFlags flags) { return PortEngineSharedImpl::register_port (shortname, type, flags); } PortEngine::PortPtr register_port (const std::string& shortname, ARDOUR::DataType type, ARDOUR::PortFlags flags) { return PortEngineSharedImpl::register_port (shortname, type, flags); }
void unregister_port (PortHandle ph) { if (!_run) return; PortEngineSharedImpl::unregister_port (ph); } void unregister_port (PortHandle ph) { if (!_run) return; PortEngineSharedImpl::unregister_port (ph); }
int connect (const std::string& src, const std::string& dst) { return PortEngineSharedImpl::connect (src, dst); } int connect (const std::string& src, const std::string& dst) { return PortEngineSharedImpl::connect (src, dst); }
int disconnect (const std::string& src, const std::string& dst) { return PortEngineSharedImpl::disconnect (src, dst); } int disconnect (const std::string& src, const std::string& dst) { return PortEngineSharedImpl::disconnect (src, dst); }
@ -396,7 +396,6 @@ class CoreAudioBackend : public AudioBackend, public PortEngineSharedImpl {
/* port engine */ /* port engine */
int register_system_audio_ports (); int register_system_audio_ports ();
void update_system_port_latecies ();
struct PortConnectData { struct PortConnectData {
std::string a; std::string a;

View file

@ -263,18 +263,18 @@ DummyAudioBackend::set_buffer_size (uint32_t bs)
*/ */
LatencyRange lr; LatencyRange lr;
lr.min = lr.max = _systemic_input_latency; lr.min = lr.max = _systemic_input_latency;
for (std::vector<BackendPort*>::const_iterator it = _system_inputs.begin (); it != _system_inputs.end (); ++it) { for (std::vector<BackendPortPtr>::const_iterator it = _system_inputs.begin (); it != _system_inputs.end (); ++it) {
set_latency_range (*it, false, lr); set_latency_range (*it, false, lr);
} }
for (std::vector<BackendPort*>::const_iterator it = _system_midi_in.begin (); it != _system_midi_in.end (); ++it) { for (std::vector<BackendPortPtr>::const_iterator it = _system_midi_in.begin (); it != _system_midi_in.end (); ++it) {
set_latency_range (*it, false, lr); set_latency_range (*it, false, lr);
} }
lr.min = lr.max = _systemic_output_latency; lr.min = lr.max = _systemic_output_latency;
for (std::vector<BackendPort*>::const_iterator it = _system_outputs.begin (); it != _system_outputs.end (); ++it) { for (std::vector<BackendPortPtr>::const_iterator it = _system_outputs.begin (); it != _system_outputs.end (); ++it) {
set_latency_range (*it, true, lr); set_latency_range (*it, true, lr);
} }
for (std::vector<BackendPort*>::const_iterator it = _system_midi_out.begin (); it != _system_midi_out.end (); ++it) { for (std::vector<BackendPortPtr>::const_iterator it = _system_midi_out.begin (); it != _system_midi_out.end (); ++it) {
set_latency_range (*it, true, lr); set_latency_range (*it, true, lr);
} }
@ -689,13 +689,18 @@ DummyAudioBackend::register_system_ports()
for (int i = 1; i <= a_ins; ++i) { for (int i = 1; i <= a_ins; ++i) {
char tmp[64]; char tmp[64];
snprintf(tmp, sizeof(tmp), "system:capture_%d", i); snprintf(tmp, sizeof(tmp), "system:capture_%d", i);
PortHandle p = add_port(std::string(tmp), DataType::AUDIO, static_cast<PortFlags>(IsOutput | IsPhysical | IsTerminal)); PortPtr p = add_port(std::string(tmp), DataType::AUDIO, static_cast<PortFlags>(IsOutput | IsPhysical | IsTerminal));
if (!p) return -1; if (!p) return -1;
set_latency_range (p, false, lr); set_latency_range (p, false, lr);
_system_inputs.push_back (static_cast<DummyAudioPort*>(p));
std::string name = static_cast<DummyAudioPort*>(p)->setup_generator (gt, _samplerate, i - 1, a_ins); boost::shared_ptr<DummyAudioPort> dp = boost::dynamic_pointer_cast<DummyAudioPort>(p);
_system_inputs.push_back (dp);
std::string name = dp->setup_generator (gt, _samplerate, i - 1, a_ins);
if (!name.empty ()) { if (!name.empty ()) {
static_cast<DummyAudioPort*>(p)->set_pretty_name (name); dp->set_pretty_name (name);
} }
} }
@ -703,10 +708,10 @@ DummyAudioBackend::register_system_ports()
for (int i = 1; i <= a_out; ++i) { for (int i = 1; i <= a_out; ++i) {
char tmp[64]; char tmp[64];
snprintf(tmp, sizeof(tmp), "system:playback_%d", i); snprintf(tmp, sizeof(tmp), "system:playback_%d", i);
PortHandle p = add_port(std::string(tmp), DataType::AUDIO, static_cast<PortFlags>(IsInput | IsPhysical | IsTerminal)); PortPtr p = add_port(std::string(tmp), DataType::AUDIO, static_cast<PortFlags>(IsInput | IsPhysical | IsTerminal));
if (!p) return -1; if (!p) return -1;
set_latency_range (p, true, lr); set_latency_range (p, true, lr);
_system_outputs.push_back (static_cast<DummyAudioPort*>(p)); _system_outputs.push_back (boost::dynamic_pointer_cast<BackendPort>(p));
} }
/* midi ports */ /* midi ports */
@ -714,20 +719,24 @@ DummyAudioBackend::register_system_ports()
for (int i = 0; i < m_ins; ++i) { for (int i = 0; i < m_ins; ++i) {
char tmp[64]; char tmp[64];
snprintf(tmp, sizeof(tmp), "system:midi_capture_dummy_%d", i+1); snprintf(tmp, sizeof(tmp), "system:midi_capture_dummy_%d", i+1);
PortHandle p = add_port(std::string(tmp), DataType::MIDI, static_cast<PortFlags>(IsOutput | IsPhysical | IsTerminal)); PortPtr p = add_port(std::string(tmp), DataType::MIDI, static_cast<PortFlags>(IsOutput | IsPhysical | IsTerminal));
if (!p) return -1; if (!p) return -1;
set_latency_range (p, false, lr); set_latency_range (p, false, lr);
_system_midi_in.push_back (static_cast<DummyMidiPort*>(p));
boost::shared_ptr<DummyMidiPort> dp = boost::dynamic_pointer_cast<DummyMidiPort>(p);
_system_midi_in.push_back (dp);
if (_midi_mode == MidiGenerator) { if (_midi_mode == MidiGenerator) {
std::string name = static_cast<DummyMidiPort*>(p)->setup_generator (i % NUM_MIDI_EVENT_GENERATORS, _samplerate); std::string name = dp->setup_generator (i % NUM_MIDI_EVENT_GENERATORS, _samplerate);
if (!name.empty ()) { if (!name.empty ()) {
static_cast<DummyMidiPort*>(p)->set_pretty_name (name); dp->set_pretty_name (name);
} }
} }
else if (_midi_mode == MidiOneHz) { else if (_midi_mode == MidiOneHz) {
std::string name = static_cast<DummyMidiPort*>(p)->setup_generator (-1, _samplerate); std::string name = dp->setup_generator (-1, _samplerate);
if (!name.empty ()) { if (!name.empty ()) {
static_cast<DummyMidiPort*>(p)->set_pretty_name (name); dp->set_pretty_name (name);
} }
} }
} }
@ -739,7 +748,9 @@ DummyAudioBackend::register_system_ports()
PortHandle p = add_port(std::string(tmp), DataType::MIDI, static_cast<PortFlags>(IsInput | IsPhysical | IsTerminal)); PortHandle p = add_port(std::string(tmp), DataType::MIDI, static_cast<PortFlags>(IsInput | IsPhysical | IsTerminal));
if (!p) return -1; if (!p) return -1;
set_latency_range (p, true, lr); set_latency_range (p, true, lr);
_system_midi_out.push_back (static_cast<DummyMidiPort*>(p));
boost::shared_ptr<DummyMidiPort> dp = boost::dynamic_pointer_cast<DummyMidiPort>(p);
_system_midi_out.push_back (dp);
if (_device == _("Loopback") && _midi_mode == MidiToAudio) { if (_device == _("Loopback") && _midi_mode == MidiToAudio) {
std::stringstream ss; std::stringstream ss;
@ -749,30 +760,12 @@ DummyAudioBackend::register_system_ports()
ss << " >" << (apc + 1); ss << " >" << (apc + 1);
} }
} }
static_cast<DummyMidiPort*>(p)->set_pretty_name (ss.str()); dp->set_pretty_name (ss.str());
} }
} }
return 0; return 0;
} }
void
DummyAudioBackend::update_system_port_latecies ()
{
for (std::vector<BackendPort*>::const_iterator it = _system_inputs.begin (); it != _system_inputs.end (); ++it) {
(*it)->update_connected_latency (true);
}
for (std::vector<BackendPort*>::const_iterator it = _system_outputs.begin (); it != _system_outputs.end (); ++it) {
(*it)->update_connected_latency (false);
}
for (std::vector<BackendPort*>::const_iterator it = _system_midi_in.begin (); it != _system_midi_in.end (); ++it) {
(*it)->update_connected_latency (true);
}
for (std::vector<BackendPort*>::const_iterator it = _system_midi_out.begin (); it != _system_midi_out.end (); ++it) {
(*it)->update_connected_latency (false);
}
}
BackendPort* BackendPort*
DummyAudioBackend::port_factory (std::string const & name, ARDOUR::DataType type, ARDOUR::PortFlags flags) DummyAudioBackend::port_factory (std::string const & name, ARDOUR::DataType type, ARDOUR::PortFlags flags)
{ {
@ -881,35 +874,35 @@ DummyAudioBackend::monitoring_input (PortEngine::PortHandle)
/* Latency management */ /* Latency management */
void void
DummyAudioBackend::set_latency_range (PortEngine::PortHandle port, bool for_playback, LatencyRange latency_range) DummyAudioBackend::set_latency_range (PortEngine::PortHandle port_handle, bool for_playback, LatencyRange latency_range)
{ {
BackendPortPtr port = boost::dynamic_pointer_cast<BackendPort> (port_handle);
if (!valid_port (port)) { if (!valid_port (port)) {
PBD::error << _("DummyPort::set_latency_range (): invalid port.") << endmsg; PBD::error << _("DummyPort::set_latency_range (): invalid port.") << endmsg;
} }
static_cast<DummyPort*>(port)->set_latency_range (latency_range, for_playback); port->set_latency_range (latency_range, for_playback);
} }
LatencyRange LatencyRange
DummyAudioBackend::get_latency_range (PortEngine::PortHandle port, bool for_playback) DummyAudioBackend::get_latency_range (PortEngine::PortHandle port_handle, bool for_playback)
{ {
LatencyRange r; LatencyRange r;
BackendPortPtr port = boost::dynamic_pointer_cast<BackendPort> (port_handle);
if (!valid_port (port)) { if (!valid_port (port)) {
PBD::error << _("DummyPort::get_latency_range (): invalid port.") << endmsg; PBD::error << _("DummyPort::get_latency_range (): invalid port.") << endmsg;
r.min = 0; r.min = 0;
r.max = 0; r.max = 0;
return r; return r;
} }
DummyPort *p = static_cast<DummyPort*>(port);
assert(p);
r = p->latency_range (for_playback); r = port->latency_range (for_playback);
if (p->is_physical() && p->is_terminal()) { if (port->is_physical() && port->is_terminal()) {
if (p->is_input() && for_playback) { if (port->is_input() && for_playback) {
const size_t l_in = _samples_per_period * .25; const size_t l_in = _samples_per_period * .25;
r.min += l_in; r.min += l_in;
r.max += l_in; r.max += l_in;
} }
if (p->is_output() && !for_playback) { if (port->is_output() && !for_playback) {
/* with 'Loopback' there is exactly once cycle latency, divide it between In + Out; */ /* with 'Loopback' there is exactly once cycle latency, divide it between In + Out; */
const size_t l_in = _samples_per_period * .25; const size_t l_in = _samples_per_period * .25;
const size_t l_out = _samples_per_period - l_in; const size_t l_out = _samples_per_period - l_in;
@ -923,11 +916,12 @@ DummyAudioBackend::get_latency_range (PortEngine::PortHandle port, bool for_play
/* Getting access to the data buffer for a port */ /* Getting access to the data buffer for a port */
void* void*
DummyAudioBackend::get_buffer (PortEngine::PortHandle port, pframes_t nframes) DummyAudioBackend::get_buffer (PortEngine::PortHandle port_handle, pframes_t nframes)
{ {
BackendPortPtr port = boost::dynamic_pointer_cast<BackendPort> (port_handle);
assert (port); assert (port);
assert (valid_port (port)); assert (valid_port (port));
return static_cast<DummyPort*>(port)->get_buffer (nframes); return port->get_buffer (nframes);
} }
/* Engine Process */ /* Engine Process */
@ -952,11 +946,11 @@ DummyAudioBackend::main_process_thread ()
} }
// re-set input buffers, generate on demand. // re-set input buffers, generate on demand.
for (std::vector<BackendPort*>::const_iterator it = _system_inputs.begin (); it != _system_inputs.end (); ++it) { for (std::vector<BackendPortPtr>::const_iterator it = _system_inputs.begin (); it != _system_inputs.end (); ++it) {
static_cast<DummyPort*>(*it)->next_period(); boost::dynamic_pointer_cast<DummyPort>(*it)->next_period ();
} }
for (std::vector<BackendPort*>::const_iterator it = _system_midi_in.begin (); it != _system_midi_in.end (); ++it) { for (std::vector<BackendPortPtr>::const_iterator it = _system_midi_in.begin (); it != _system_midi_in.end (); ++it) {
static_cast<DummyPort*>(*it)->next_period(); boost::dynamic_pointer_cast<DummyPort>(*it)->next_period ();
} }
if (engine.process_callback (samples_per_period)) { if (engine.process_callback (samples_per_period)) {
@ -967,28 +961,28 @@ DummyAudioBackend::main_process_thread ()
if (_device == _("Loopback") && _midi_mode != MidiToAudio) { if (_device == _("Loopback") && _midi_mode != MidiToAudio) {
int opn = 0; int opn = 0;
int opc = _system_outputs.size(); int opc = _system_outputs.size();
for (std::vector<BackendPort*>::const_iterator it = _system_inputs.begin (); it != _system_inputs.end (); ++it, ++opn) { for (std::vector<BackendPortPtr>::const_iterator it = _system_inputs.begin (); it != _system_inputs.end (); ++it, ++opn) {
DummyAudioPort* op = static_cast<DummyAudioPort*> (_system_outputs[(opn % opc)]); BackendPortPtr op = _system_outputs[(opn % opc)];
static_cast<DummyAudioPort*>(*it)->fill_wavetable ((const float*)op->get_buffer (samples_per_period), samples_per_period); boost::dynamic_pointer_cast<DummyAudioPort>(*it)->fill_wavetable ((const float*)op->get_buffer (samples_per_period), samples_per_period);
} }
} }
if (_midi_mode == MidiLoopback) { if (_midi_mode == MidiLoopback) {
int opn = 0; int opn = 0;
int opc = _system_midi_out.size(); int opc = _system_midi_out.size();
for (std::vector<BackendPort*>::const_iterator it = _system_midi_in.begin (); it != _system_midi_in.end (); ++it, ++opn) { for (std::vector<BackendPortPtr>::const_iterator it = _system_midi_in.begin (); it != _system_midi_in.end (); ++it, ++opn) {
DummyMidiPort* op = static_cast<DummyMidiPort*> (_system_midi_out[(opn % opc)]); boost::shared_ptr<DummyMidiPort> op = boost::dynamic_pointer_cast<DummyMidiPort> (_system_midi_out[(opn % opc)]);
op->get_buffer(0); // mix-down op->get_buffer(0); // mix-down
static_cast<DummyMidiPort*>(*it)->set_loopback (op->const_buffer()); boost::dynamic_pointer_cast<DummyMidiPort>(*it)->set_loopback (op->const_buffer());
} }
} }
else if (_midi_mode == MidiToAudio) { else if (_midi_mode == MidiToAudio) {
int opn = 0; int opn = 0;
int opc = _system_midi_out.size(); int opc = _system_midi_out.size();
for (std::vector<BackendPort*>::const_iterator it = _system_inputs.begin (); it != _system_inputs.end (); ++it, ++opn) { for (std::vector<BackendPortPtr>::const_iterator it = _system_inputs.begin (); it != _system_inputs.end (); ++it, ++opn) {
DummyMidiPort* op = static_cast<DummyMidiPort*> (_system_midi_out[(opn % opc)]); boost::shared_ptr<DummyMidiPort> op = boost::dynamic_pointer_cast<DummyMidiPort> (_system_midi_out[(opn % opc)]);
op->get_buffer(0); // mix-down op->get_buffer(0); // mix-down
static_cast<DummyAudioPort*>(*it)->midi_to_wavetable (op->const_buffer(), samples_per_period); boost::dynamic_pointer_cast<DummyAudioPort>(*it)->midi_to_wavetable (op->const_buffer(), samples_per_period);
} }
} }
@ -1039,7 +1033,7 @@ DummyAudioBackend::main_process_thread ()
manager.graph_order_callback(); manager.graph_order_callback();
} }
if (connections_changed || ports_changed) { if (connections_changed || ports_changed) {
update_system_port_latecies (); update_system_port_latencies ();
engine.latency_callback(false); engine.latency_callback(false);
engine.latency_callback(true); engine.latency_callback(true);
} }
@ -1622,22 +1616,23 @@ void DummyAudioPort::generate (const pframes_t n_samples)
_gen_cycle = true; _gen_cycle = true;
} }
void* DummyAudioPort::get_buffer (pframes_t n_samples) void*
DummyAudioPort::get_buffer (pframes_t n_samples)
{ {
if (is_input ()) { if (is_input ()) {
const std::set<BackendPort *>& connections = get_connections (); const std::set<BackendPortPtr>& connections = get_connections ();
std::set<BackendPort*>::const_iterator it = connections.begin (); std::set<BackendPortPtr>::const_iterator it = connections.begin ();
if (it == connections.end ()) { if (it == connections.end ()) {
memset (_buffer, 0, n_samples * sizeof (Sample)); memset (_buffer, 0, n_samples * sizeof (Sample));
} else { } else {
DummyAudioPort * source = static_cast<DummyAudioPort*>(*it); boost::shared_ptr<DummyAudioPort> source = boost::dynamic_pointer_cast<DummyAudioPort>(*it);
assert (source && source->is_output ()); assert (source && source->is_output ());
if (source->is_physical() && source->is_terminal()) { if (source->is_physical() && source->is_terminal()) {
source->get_buffer(n_samples); // generate signal. source->get_buffer(n_samples); // generate signal.
} }
memcpy (_buffer, source->const_buffer (), n_samples * sizeof (Sample)); memcpy (_buffer, source->const_buffer (), n_samples * sizeof (Sample));
while (++it != connections.end ()) { while (++it != connections.end ()) {
source = static_cast<DummyAudioPort*>(*it); source = boost::dynamic_pointer_cast<DummyAudioPort>(*it);
assert (source && source->is_output ()); assert (source && source->is_output ());
Sample* dst = buffer (); Sample* dst = buffer ();
if (source->is_physical() && source->is_terminal()) { if (source->is_physical() && source->is_terminal()) {
@ -1761,11 +1756,11 @@ void* DummyMidiPort::get_buffer (pframes_t n_samples)
{ {
if (is_input ()) { if (is_input ()) {
_buffer.clear (); _buffer.clear ();
const std::set<BackendPort*>& connections = get_connections (); const std::set<BackendPortPtr>& connections = get_connections ();
for (std::set<BackendPort*>::const_iterator i = connections.begin (); for (std::set<BackendPortPtr>::const_iterator i = connections.begin ();
i != connections.end (); i != connections.end ();
++i) { ++i) {
DummyMidiPort * source = static_cast<DummyMidiPort*>(*i); boost::shared_ptr<DummyMidiPort> source = boost::dynamic_pointer_cast<DummyMidiPort>(*i);
if (source->is_physical() && source->is_terminal()) { if (source->is_physical() && source->is_terminal()) {
source->get_buffer(n_samples); // generate signal. source->get_buffer(n_samples); // generate signal.
} }

View file

@ -297,12 +297,12 @@ class DummyAudioBackend : public AudioBackend, public PortEngineSharedImpl {
int set_port_name (PortEngine::PortHandle ph, const std::string& name) { return PortEngineSharedImpl::set_port_name (ph, name); } int set_port_name (PortEngine::PortHandle ph, const std::string& name) { return PortEngineSharedImpl::set_port_name (ph, name); }
std::string get_port_name (PortEngine::PortHandle ph) const { return PortEngineSharedImpl::get_port_name (ph); } std::string get_port_name (PortEngine::PortHandle ph) const { return PortEngineSharedImpl::get_port_name (ph); }
PortFlags get_port_flags (PortEngine::PortHandle ph) const { return PortEngineSharedImpl::get_port_flags (ph); } PortFlags get_port_flags (PortEngine::PortHandle ph) const { return PortEngineSharedImpl::get_port_flags (ph); }
PortEngine::PortHandle get_port_by_name (std::string const & name) const { return PortEngineSharedImpl::get_port_by_name (name); } PortEngine::PortPtr get_port_by_name (std::string const & name) const { return PortEngineSharedImpl::get_port_by_name (name); }
int get_port_property (PortEngine::PortHandle ph, const std::string& key, std::string& value, std::string& type) const { return PortEngineSharedImpl::get_port_property (ph, key, value, type); } int get_port_property (PortEngine::PortHandle ph, const std::string& key, std::string& value, std::string& type) const { return PortEngineSharedImpl::get_port_property (ph, key, value, type); }
int set_port_property (PortEngine::PortHandle ph, const std::string& key, const std::string& value, const std::string& type) { return PortEngineSharedImpl::set_port_property (ph, key, value, type); } int set_port_property (PortEngine::PortHandle ph, const std::string& key, const std::string& value, const std::string& type) { return PortEngineSharedImpl::set_port_property (ph, key, value, type); }
int get_ports (const std::string& port_name_pattern, DataType type, PortFlags flags, std::vector<std::string>& results) const { return PortEngineSharedImpl::get_ports (port_name_pattern, type, flags, results); } int get_ports (const std::string& port_name_pattern, DataType type, PortFlags flags, std::vector<std::string>& results) const { return PortEngineSharedImpl::get_ports (port_name_pattern, type, flags, results); }
DataType port_data_type (PortEngine::PortHandle ph) const { return PortEngineSharedImpl::port_data_type (ph); } DataType port_data_type (PortEngine::PortHandle ph) const { return PortEngineSharedImpl::port_data_type (ph); }
PortEngine::PortHandle register_port (const std::string& shortname, ARDOUR::DataType type, ARDOUR::PortFlags flags) { return PortEngineSharedImpl::register_port (shortname, type, flags); } PortEngine::PortPtr register_port (const std::string& shortname, ARDOUR::DataType type, ARDOUR::PortFlags flags) { return PortEngineSharedImpl::register_port (shortname, type, flags); }
void unregister_port (PortHandle ph) { if (!_running) return; PortEngineSharedImpl::unregister_port (ph); } void unregister_port (PortHandle ph) { if (!_running) return; PortEngineSharedImpl::unregister_port (ph); }
int connect (const std::string& src, const std::string& dst) { return PortEngineSharedImpl::connect (src, dst); } int connect (const std::string& src, const std::string& dst) { return PortEngineSharedImpl::connect (src, dst); }
int disconnect (const std::string& src, const std::string& dst) { return PortEngineSharedImpl::disconnect (src, dst); } int disconnect (const std::string& src, const std::string& dst) { return PortEngineSharedImpl::disconnect (src, dst); }
@ -403,8 +403,6 @@ class DummyAudioBackend : public AudioBackend, public PortEngineSharedImpl {
/* port engine */ /* port engine */
int register_system_ports (); int register_system_ports ();
void update_system_port_latecies ();
struct PortConnectData { struct PortConnectData {
std::string a; std::string a;

View file

@ -1086,7 +1086,8 @@ JACKAudioBackend::n_physical (unsigned long flags) const
if (ports) { if (ports) {
for (uint32_t i = 0; ports[i]; ++i) { for (uint32_t i = 0; ports[i]; ++i) {
if (!strstr (ports[i], "Midi-Through")) { if (!strstr (ports[i], "Midi-Through")) {
DataType t = port_data_type (jack_port_by_name (_priv_jack, ports[i])); boost::shared_ptr<JackPort> jp (new JackPort (jack_port_by_name (_priv_jack, ports[i])));
DataType t = port_data_type (jp);
if (t != DataType::NIL) { if (t != DataType::NIL) {
c.set (t, c.get (t) + 1); c.set (t, c.get (t) + 1);
} }

View file

@ -39,6 +39,16 @@ namespace ARDOUR {
class JackConnection; class JackConnection;
class JACKSession; class JACKSession;
class JackPort : public ProtoPort
{
public:
JackPort (jack_port_t* p) : jack_ptr (p) {}
private:
friend class JACKAudioBackend;
jack_port_t* jack_ptr;
};
class JACKAudioBackend : public AudioBackend { class JACKAudioBackend : public AudioBackend {
public: public:
JACKAudioBackend (AudioEngine& e, AudioBackendInfo& info, boost::shared_ptr<JackConnection>); JACKAudioBackend (AudioEngine& e, AudioBackendInfo& info, boost::shared_ptr<JackConnection>);
@ -133,7 +143,7 @@ class JACKAudioBackend : public AudioBackend {
int set_port_name (PortHandle, const std::string&); int set_port_name (PortHandle, const std::string&);
std::string get_port_name (PortHandle) const; std::string get_port_name (PortHandle) const;
PortFlags get_port_flags (PortHandle) const; PortFlags get_port_flags (PortHandle) const;
PortHandle get_port_by_name (const std::string&) const; PortPtr get_port_by_name (const std::string&) const;
int get_port_property (PortHandle, const std::string& key, std::string& value, std::string& type) const; int get_port_property (PortHandle, const std::string& key, std::string& value, std::string& type) const;
int set_port_property (PortHandle, const std::string& key, const std::string& value, const std::string& type); int set_port_property (PortHandle, const std::string& key, const std::string& value, const std::string& type);
@ -141,7 +151,7 @@ class JACKAudioBackend : public AudioBackend {
DataType port_data_type (PortHandle) const; DataType port_data_type (PortHandle) const;
PortHandle register_port (const std::string& shortname, ARDOUR::DataType, ARDOUR::PortFlags); PortPtr register_port (const std::string& shortname, ARDOUR::DataType, ARDOUR::PortFlags);
void unregister_port (PortHandle); void unregister_port (PortHandle);
bool connected (PortHandle, bool process_callback_safe); bool connected (PortHandle, bool process_callback_safe);
@ -310,4 +320,3 @@ class JACKAudioBackend : public AudioBackend {
} // namespace } // namespace
#endif /* __ardour_audiobackend_h__ */ #endif /* __ardour_audiobackend_h__ */

View file

@ -109,25 +109,25 @@ JACKAudioBackend::set_port_name (PortHandle port, const std::string& name)
#if HAVE_JACK_PORT_RENAME #if HAVE_JACK_PORT_RENAME
jack_client_t* client = _jack_connection->jack(); jack_client_t* client = _jack_connection->jack();
if (client) { if (client) {
return jack_port_rename (client, (jack_port_t*) port, name.c_str()); return jack_port_rename (client, boost::dynamic_pointer_cast<JackPort>(port)->jack_ptr, name.c_str());
} else { } else {
return -1; return -1;
} }
#else #else
return jack_port_set_name ((jack_port_t*) port, name.c_str()); return jack_port_set_name (boost::dynamic_pointer_cast<JackPort>(port)->jack_ptr, name.c_str());
#endif #endif
} }
string string
JACKAudioBackend::get_port_name (PortHandle port) const JACKAudioBackend::get_port_name (PortHandle port) const
{ {
return jack_port_name ((jack_port_t*) port); return jack_port_name (boost::dynamic_pointer_cast<JackPort>(port)->jack_ptr);
} }
PortFlags PortFlags
JACKAudioBackend::get_port_flags (PortHandle port) const JACKAudioBackend::get_port_flags (PortHandle port) const
{ {
return PortFlags (jack_port_flags ((jack_port_t*) port)); return PortFlags (jack_port_flags (boost::dynamic_pointer_cast<JackPort>(port)->jack_ptr));
} }
int int
@ -138,8 +138,8 @@ JACKAudioBackend::get_port_property (PortHandle port, const std::string& key, st
char *cvalue = NULL; char *cvalue = NULL;
char *ctype = NULL; char *ctype = NULL;
jack_uuid_t uuid = jack_port_uuid((jack_port_t*) port); jack_uuid_t uuid = jack_port_uuid (boost::dynamic_pointer_cast<JackPort>(port)->jack_ptr);
rv = jack_get_property(uuid, key.c_str(), &cvalue, &ctype); rv = jack_get_property (uuid, key.c_str(), &cvalue, &ctype);
if (0 == rv && cvalue) { if (0 == rv && cvalue) {
value = cvalue; value = cvalue;
@ -164,7 +164,7 @@ JACKAudioBackend::set_port_property (PortHandle port, const std::string& key, co
#ifdef HAVE_JACK_METADATA // really everyone ought to have this by now. #ifdef HAVE_JACK_METADATA // really everyone ought to have this by now.
int rv = -1; int rv = -1;
jack_client_t* client = _jack_connection->jack(); jack_client_t* client = _jack_connection->jack();
jack_uuid_t uuid = jack_port_uuid((jack_port_t*) port); jack_uuid_t uuid = jack_port_uuid (boost::dynamic_pointer_cast<JackPort>(port)->jack_ptr);
return jack_set_property(client, uuid, key.c_str(), value.c_str(), type.c_str()); return jack_set_property(client, uuid, key.c_str(), value.c_str(), type.c_str());
return rv; return rv;
#else #else
@ -172,11 +172,11 @@ JACKAudioBackend::set_port_property (PortHandle port, const std::string& key, co
#endif #endif
} }
PortEngine::PortHandle PortEngine::PortPtr
JACKAudioBackend:: get_port_by_name (const std::string& name) const JACKAudioBackend:: get_port_by_name (const std::string& name) const
{ {
GET_PRIVATE_JACK_POINTER_RET (_priv_jack, 0); GET_PRIVATE_JACK_POINTER_RET (_priv_jack, 0);
return (PortHandle) jack_port_by_name (_priv_jack, name.c_str()); return boost::shared_ptr<ProtoPort> (new JackPort (jack_port_by_name (_priv_jack, name.c_str())));
} }
void void
@ -213,17 +213,17 @@ JACKAudioBackend::connect_callback (jack_port_id_t id_a, jack_port_id_t id_b, in
} }
bool bool
JACKAudioBackend::connected (PortHandle port, bool process_callback_safe) JACKAudioBackend::connected (PortHandle p, bool process_callback_safe)
{ {
bool ret = false; bool ret = false;
jack_port_t* port = boost::dynamic_pointer_cast<JackPort>(p)->jack_ptr;
const char** ports; const char** ports;
if (process_callback_safe) { if (process_callback_safe) {
ports = jack_port_get_connections ((jack_port_t*)port); ports = jack_port_get_connections (port);
} else { } else {
GET_PRIVATE_JACK_POINTER_RET (_priv_jack, false); GET_PRIVATE_JACK_POINTER_RET (_priv_jack, false);
ports = jack_port_get_all_connections (_priv_jack, (jack_port_t*)port); ports = jack_port_get_all_connections (_priv_jack, port);
} }
if (ports) { if (ports) {
@ -236,16 +236,17 @@ JACKAudioBackend::connected (PortHandle port, bool process_callback_safe)
} }
bool bool
JACKAudioBackend::connected_to (PortHandle port, const std::string& other, bool process_callback_safe) JACKAudioBackend::connected_to (PortHandle p, const std::string& other, bool process_callback_safe)
{ {
bool ret = false; bool ret = false;
const char** ports; const char** ports;
jack_port_t* port = boost::dynamic_pointer_cast<JackPort>(p)->jack_ptr;
if (process_callback_safe) { if (process_callback_safe) {
ports = jack_port_get_connections ((jack_port_t*)port); ports = jack_port_get_connections (port);
} else { } else {
GET_PRIVATE_JACK_POINTER_RET (_priv_jack, false); GET_PRIVATE_JACK_POINTER_RET (_priv_jack, false);
ports = jack_port_get_all_connections (_priv_jack, (jack_port_t*)port); ports = jack_port_get_all_connections (_priv_jack, port);
} }
if (ports) { if (ports) {
@ -264,7 +265,7 @@ bool
JACKAudioBackend::physically_connected (PortHandle p, bool process_callback_safe) JACKAudioBackend::physically_connected (PortHandle p, bool process_callback_safe)
{ {
GET_PRIVATE_JACK_POINTER_RET (_priv_jack, false); GET_PRIVATE_JACK_POINTER_RET (_priv_jack, false);
jack_port_t* port = (jack_port_t*) p; jack_port_t* port = boost::dynamic_pointer_cast<JackPort>(p)->jack_ptr;
const char** ports; const char** ports;
@ -295,7 +296,7 @@ bool
JACKAudioBackend::externally_connected (PortHandle p, bool process_callback_safe) JACKAudioBackend::externally_connected (PortHandle p, bool process_callback_safe)
{ {
GET_PRIVATE_JACK_POINTER_RET (_priv_jack, false); GET_PRIVATE_JACK_POINTER_RET (_priv_jack, false);
jack_port_t* port = (jack_port_t*) p; jack_port_t* port = boost::dynamic_pointer_cast<JackPort>(p)->jack_ptr;
const char** ports; const char** ports;
@ -325,15 +326,16 @@ JACKAudioBackend::externally_connected (PortHandle p, bool process_callback_safe
} }
int int
JACKAudioBackend::get_connections (PortHandle port, vector<string>& s, bool process_callback_safe) JACKAudioBackend::get_connections (PortHandle p, vector<string>& s, bool process_callback_safe)
{ {
const char** ports; const char** ports;
jack_port_t* port = boost::dynamic_pointer_cast<JackPort>(p)->jack_ptr;
if (process_callback_safe) { if (process_callback_safe) {
ports = jack_port_get_connections ((jack_port_t*)port); ports = jack_port_get_connections (port);
} else { } else {
GET_PRIVATE_JACK_POINTER_RET (_priv_jack, 0); GET_PRIVATE_JACK_POINTER_RET (_priv_jack, 0);
ports = jack_port_get_all_connections (_priv_jack, (jack_port_t*)port); ports = jack_port_get_all_connections (_priv_jack, port);
} }
if (ports) { if (ports) {
@ -347,9 +349,9 @@ JACKAudioBackend::get_connections (PortHandle port, vector<string>& s, bool proc
} }
DataType DataType
JACKAudioBackend::port_data_type (PortHandle p) const JACKAudioBackend::port_data_type (PortHandle port) const
{ {
return jack_port_type_to_ardour_data_type (jack_port_type ((jack_port_t*) p)); return jack_port_type_to_ardour_data_type (jack_port_type (boost::dynamic_pointer_cast<JackPort>(port)->jack_ptr));
} }
const string& const string&
@ -359,13 +361,13 @@ JACKAudioBackend::my_name() const
} }
bool bool
JACKAudioBackend::port_is_physical (PortHandle ph) const JACKAudioBackend::port_is_physical (PortHandle port) const
{ {
if (!ph) { if (!port) {
return false; return false;
} }
return jack_port_flags ((jack_port_t*) ph) & JackPortIsPhysical; return jack_port_flags (boost::dynamic_pointer_cast<JackPort>(port)->jack_ptr) & JackPortIsPhysical;
} }
int int
@ -461,41 +463,46 @@ JACKAudioBackend::can_monitor_input () const
int int
JACKAudioBackend::request_input_monitoring (PortHandle port, bool yn) JACKAudioBackend::request_input_monitoring (PortHandle port, bool yn)
{ {
return jack_port_request_monitor ((jack_port_t*) port, yn); return jack_port_request_monitor (boost::dynamic_pointer_cast<JackPort>(port)->jack_ptr, yn);
} }
int int
JACKAudioBackend::ensure_input_monitoring (PortHandle port, bool yn) JACKAudioBackend::ensure_input_monitoring (PortHandle port, bool yn)
{ {
return jack_port_ensure_monitor ((jack_port_t*) port, yn); return jack_port_ensure_monitor (boost::dynamic_pointer_cast<JackPort>(port)->jack_ptr, yn);
} }
bool bool
JACKAudioBackend::monitoring_input (PortHandle port) JACKAudioBackend::monitoring_input (PortHandle port)
{ {
return jack_port_monitoring_input ((jack_port_t*) port); return jack_port_monitoring_input (boost::dynamic_pointer_cast<JackPort>(port)->jack_ptr);
} }
PortEngine::PortHandle PortEngine::PortPtr
JACKAudioBackend::register_port (const std::string& shortname, ARDOUR::DataType type, ARDOUR::PortFlags flags) JACKAudioBackend::register_port (const std::string& shortname, ARDOUR::DataType type, ARDOUR::PortFlags flags)
{ {
GET_PRIVATE_JACK_POINTER_RET (_priv_jack, 0); GET_PRIVATE_JACK_POINTER_RET (_priv_jack, 0);
return jack_port_register (_priv_jack, shortname.c_str(), jack_port_t* p = jack_port_register (_priv_jack, shortname.c_str(),
ardour_data_type_to_jack_port_type (type), ardour_data_type_to_jack_port_type (type),
ardour_port_flags_to_jack_flags (flags), ardour_port_flags_to_jack_flags (flags),
0); 0);
if (!p) {
return PortEngine::PortPtr();
}
return boost::shared_ptr<ProtoPort> (new JackPort (p));
} }
void void
JACKAudioBackend::unregister_port (PortHandle port) JACKAudioBackend::unregister_port (PortHandle port)
{ {
GET_PRIVATE_JACK_POINTER (_priv_jack); GET_PRIVATE_JACK_POINTER (_priv_jack);
(void) jack_port_unregister (_priv_jack, (jack_port_t*) port); (void) jack_port_unregister (_priv_jack, boost::dynamic_pointer_cast<JackPort>(port)->jack_ptr);
} }
int int
JACKAudioBackend::connect (PortHandle port, const std::string& other) JACKAudioBackend::connect (PortHandle port, const std::string& other)
{ {
GET_PRIVATE_JACK_POINTER_RET (_priv_jack, -1); GET_PRIVATE_JACK_POINTER_RET (_priv_jack, -1);
return jack_connect (_priv_jack, jack_port_name ((jack_port_t*) port), other.c_str()); return jack_connect (_priv_jack, jack_port_name (boost::dynamic_pointer_cast<JackPort>(port)->jack_ptr), other.c_str());
} }
int int
JACKAudioBackend::connect (const std::string& src, const std::string& dst) JACKAudioBackend::connect (const std::string& src, const std::string& dst)
@ -510,7 +517,7 @@ int
JACKAudioBackend::disconnect (PortHandle port, const std::string& other) JACKAudioBackend::disconnect (PortHandle port, const std::string& other)
{ {
GET_PRIVATE_JACK_POINTER_RET (_priv_jack, -1); GET_PRIVATE_JACK_POINTER_RET (_priv_jack, -1);
return jack_disconnect (_priv_jack, jack_port_name ((jack_port_t*) port), other.c_str()); return jack_disconnect (_priv_jack, jack_port_name (boost::dynamic_pointer_cast<JackPort>(port)->jack_ptr), other.c_str());
} }
int int
@ -524,7 +531,7 @@ int
JACKAudioBackend::disconnect_all (PortHandle port) JACKAudioBackend::disconnect_all (PortHandle port)
{ {
GET_PRIVATE_JACK_POINTER_RET (_priv_jack, -1); GET_PRIVATE_JACK_POINTER_RET (_priv_jack, -1);
return jack_port_disconnect (_priv_jack, (jack_port_t*) port); return jack_port_disconnect (_priv_jack, boost::dynamic_pointer_cast<JackPort>(port)->jack_ptr);
} }
int int
@ -568,7 +575,7 @@ JACKAudioBackend::set_latency_range (PortHandle port, bool for_playback, Latency
range.min = r.min; range.min = r.min;
range.max = r.max; range.max = r.max;
jack_port_set_latency_range ((jack_port_t*) port, for_playback ? JackPlaybackLatency : JackCaptureLatency, &range); jack_port_set_latency_range (boost::dynamic_pointer_cast<JackPort>(port)->jack_ptr, for_playback ? JackPlaybackLatency : JackCaptureLatency, &range);
} }
LatencyRange LatencyRange
@ -577,7 +584,7 @@ JACKAudioBackend::get_latency_range (PortHandle port, bool for_playback)
jack_latency_range_t range; jack_latency_range_t range;
LatencyRange ret; LatencyRange ret;
jack_port_get_latency_range ((jack_port_t*) port, for_playback ? JackPlaybackLatency : JackCaptureLatency, &range); jack_port_get_latency_range (boost::dynamic_pointer_cast<JackPort>(port)->jack_ptr, for_playback ? JackPlaybackLatency : JackCaptureLatency, &range);
ret.min = range.min; ret.min = range.min;
ret.max = range.max; ret.max = range.max;
@ -588,7 +595,7 @@ JACKAudioBackend::get_latency_range (PortHandle port, bool for_playback)
void* void*
JACKAudioBackend::get_buffer (PortHandle port, pframes_t nframes) JACKAudioBackend::get_buffer (PortHandle port, pframes_t nframes)
{ {
return jack_port_get_buffer ((jack_port_t*) port, nframes); return jack_port_get_buffer (boost::dynamic_pointer_cast<JackPort>(port)->jack_ptr, nframes);
} }
uint32_t uint32_t

View file

@ -1303,24 +1303,6 @@ PortAudioBackend::register_system_midi_ports()
return 0; return 0;
} }
void
PortAudioBackend::update_system_port_latecies ()
{
for (std::vector<BackendPort*>::const_iterator it = _system_inputs.begin (); it != _system_inputs.end (); ++it) {
(*it)->update_connected_latency (true);
}
for (std::vector<BackendPort*>::const_iterator it = _system_outputs.begin (); it != _system_outputs.end (); ++it) {
(*it)->update_connected_latency (false);
}
for (std::vector<BackendPort*>::const_iterator it = _system_midi_in.begin (); it != _system_midi_in.end (); ++it) {
(*it)->update_connected_latency (true);
}
for (std::vector<BackendPort*>::const_iterator it = _system_midi_out.begin (); it != _system_midi_out.end (); ++it) {
(*it)->update_connected_latency (false);
}
}
BackendPort* BackendPort*
PortAudioBackend::port_factory (std::string const & name, ARDOUR::DataType type, ARDOUR::PortFlags flags) PortAudioBackend::port_factory (std::string const & name, ARDOUR::DataType type, ARDOUR::PortFlags flags)
{ {
@ -1775,7 +1757,7 @@ PortAudioBackend::process_port_connection_changes ()
manager.graph_order_callback(); manager.graph_order_callback();
} }
if (connections_changed || ports_changed) { if (connections_changed || ports_changed) {
update_system_port_latecies (); update_system_port_latencies ();
engine.latency_callback(false); engine.latency_callback(false);
engine.latency_callback(true); engine.latency_callback(true);
} }

View file

@ -211,12 +211,12 @@ class PortAudioBackend : public AudioBackend, public PortEngineSharedImpl {
int set_port_name (PortEngine::PortHandle ph, const std::string& name) { return PortEngineSharedImpl::set_port_name (ph, name); } int set_port_name (PortEngine::PortHandle ph, const std::string& name) { return PortEngineSharedImpl::set_port_name (ph, name); }
std::string get_port_name (PortEngine::PortHandle ph) const { return PortEngineSharedImpl::get_port_name (ph); } std::string get_port_name (PortEngine::PortHandle ph) const { return PortEngineSharedImpl::get_port_name (ph); }
PortFlags get_port_flags (PortEngine::PortHandle ph) const { return PortEngineSharedImpl::get_port_flags (ph); } PortFlags get_port_flags (PortEngine::PortHandle ph) const { return PortEngineSharedImpl::get_port_flags (ph); }
PortEngine::PortHandle get_port_by_name (std::string const & name) const { return PortEngineSharedImpl::get_port_by_name (name); } PortEngine::PortPtr get_port_by_name (std::string const & name) const { return PortEngineSharedImpl::get_port_by_name (name); }
int get_port_property (PortEngine::PortHandle ph, const std::string& key, std::string& value, std::string& type) const { return PortEngineSharedImpl::get_port_property (ph, key, value, type); } int get_port_property (PortEngine::PortHandle ph, const std::string& key, std::string& value, std::string& type) const { return PortEngineSharedImpl::get_port_property (ph, key, value, type); }
int set_port_property (PortEngine::PortHandle ph, const std::string& key, const std::string& value, const std::string& type) { return PortEngineSharedImpl::set_port_property (ph, key, value, type); } int set_port_property (PortEngine::PortHandle ph, const std::string& key, const std::string& value, const std::string& type) { return PortEngineSharedImpl::set_port_property (ph, key, value, type); }
int get_ports (const std::string& port_name_pattern, DataType type, PortFlags flags, std::vector<std::string>& results) const { return PortEngineSharedImpl::get_ports (port_name_pattern, type, flags, results); } int get_ports (const std::string& port_name_pattern, DataType type, PortFlags flags, std::vector<std::string>& results) const { return PortEngineSharedImpl::get_ports (port_name_pattern, type, flags, results); }
DataType port_data_type (PortEngine::PortHandle ph) const { return PortEngineSharedImpl::port_data_type (ph); } DataType port_data_type (PortEngine::PortHandle ph) const { return PortEngineSharedImpl::port_data_type (ph); }
PortEngine::PortHandle register_port (const std::string& shortname, ARDOUR::DataType type, ARDOUR::PortFlags flags) { return PortEngineSharedImpl::register_port (shortname, type, flags); } PortEngine::PortPtr register_port (const std::string& shortname, ARDOUR::DataType type, ARDOUR::PortFlags flags) { return PortEngineSharedImpl::register_port (shortname, type, flags); }
void unregister_port (PortHandle ph) { if (!_run) return; PortEngineSharedImpl::unregister_port (ph); } void unregister_port (PortHandle ph) { if (!_run) return; PortEngineSharedImpl::unregister_port (ph); }
int connect (const std::string& src, const std::string& dst) { return PortEngineSharedImpl::connect (src, dst); } int connect (const std::string& src, const std::string& dst) { return PortEngineSharedImpl::connect (src, dst); }
int disconnect (const std::string& src, const std::string& dst) { return PortEngineSharedImpl::disconnect (src, dst); } int disconnect (const std::string& src, const std::string& dst) { return PortEngineSharedImpl::disconnect (src, dst); }
@ -371,7 +371,6 @@ class PortAudioBackend : public AudioBackend, public PortEngineSharedImpl {
int register_system_audio_ports (); int register_system_audio_ports ();
int register_system_midi_ports (); int register_system_midi_ports ();
void update_system_port_latecies ();
struct PortConnectData { struct PortConnectData {
std::string a; std::string a;

View file

@ -829,25 +829,17 @@ PulseAudioBackend::register_system_ports ()
for (int i = 1; i <= N_CHANNELS; ++i) { for (int i = 1; i <= N_CHANNELS; ++i) {
char tmp[64]; char tmp[64];
snprintf (tmp, sizeof (tmp), "system:playback_%d", i); snprintf (tmp, sizeof (tmp), "system:playback_%d", i);
PortHandle p = add_port (std::string (tmp), DataType::AUDIO, static_cast<PortFlags> (IsInput | IsPhysical | IsTerminal)); BackendPortPtr p = add_port (std::string (tmp), DataType::AUDIO, static_cast<PortFlags> (IsInput | IsPhysical | IsTerminal));
if (!p) if (!p) {
return -1; return -1;
}
set_latency_range (p, true, lr); set_latency_range (p, true, lr);
BackendPort* ap = static_cast<BackendPort*> (p); //p->set_pretty_name ("")
//ap->set_pretty_name ("") _system_outputs.push_back (p);
_system_outputs.push_back (ap);
} }
return 0; return 0;
} }
void
PulseAudioBackend::update_system_port_latecies ()
{
for (std::vector<BackendPort*>::const_iterator it = _system_outputs.begin (); it != _system_outputs.end (); ++it) {
(*it)->update_connected_latency (false);
}
}
BackendPort* BackendPort*
PulseAudioBackend::port_factory (std::string const & name, ARDOUR::DataType type, ARDOUR::PortFlags flags) PulseAudioBackend::port_factory (std::string const & name, ARDOUR::DataType type, ARDOUR::PortFlags flags)
{ {
@ -946,49 +938,55 @@ bool
/* Latency management */ /* Latency management */
void void
PulseAudioBackend::set_latency_range (PortEngine::PortHandle port, bool for_playback, LatencyRange latency_range) PulseAudioBackend::set_latency_range (PortEngine::PortHandle port_handle, bool for_playback, LatencyRange latency_range)
{ {
BackendPortPtr port = boost::dynamic_pointer_cast<BackendPort> (port_handle);
if (!valid_port (port)) { if (!valid_port (port)) {
PBD::error << _("PulsePort::set_latency_range (): invalid port.") << endmsg; PBD::error << _("PulsePort::set_latency_range (): invalid port.") << endmsg;
} }
static_cast<BackendPort*> (port)->set_latency_range (latency_range, for_playback); port->set_latency_range (latency_range, for_playback);
} }
LatencyRange LatencyRange
PulseAudioBackend::get_latency_range (PortEngine::PortHandle port, bool for_playback) PulseAudioBackend::get_latency_range (PortEngine::PortHandle port_handle, bool for_playback)
{ {
BackendPortPtr port = boost::dynamic_pointer_cast<BackendPort> (port_handle);
LatencyRange r; LatencyRange r;
if (!valid_port (port)) { if (!valid_port (port)) {
PBD::error << _("PulsePort::get_latency_range (): invalid port.") << endmsg; PBD::error << _("PulsePort::get_latency_range (): invalid port.") << endmsg;
r.min = 0; r.min = 0;
r.max = 0; r.max = 0;
return r; return r;
} }
BackendPort* p = static_cast<BackendPort*> (port);
assert (p);
r = p->latency_range (for_playback); r = port->latency_range (for_playback);
if (p->is_physical () && p->is_terminal ()) {
if (p->is_input () && for_playback) { if (port->is_physical () && port->is_terminal ()) {
if (port->is_input () && for_playback) {
r.min += _samples_per_period + _systemic_audio_output_latency; r.min += _samples_per_period + _systemic_audio_output_latency;
r.max += _samples_per_period + _systemic_audio_output_latency; r.max += _samples_per_period + _systemic_audio_output_latency;
} }
if (p->is_output () && !for_playback) { if (port->is_output () && !for_playback) {
r.min += _samples_per_period; r.min += _samples_per_period;
r.max += _samples_per_period; r.max += _samples_per_period;
} }
} }
return r; return r;
} }
/* Getting access to the data buffer for a port */ /* Getting access to the data buffer for a port */
void* void*
PulseAudioBackend::get_buffer (PortEngine::PortHandle port, pframes_t nframes) PulseAudioBackend::get_buffer (PortEngine::PortHandle port_handle, pframes_t nframes)
{ {
BackendPortPtr port = boost::dynamic_pointer_cast<BackendPort> (port_handle);
assert (port); assert (port);
assert (valid_port (port)); assert (valid_port (port));
return static_cast<BackendPort*> (port)->get_buffer (nframes);
return port->get_buffer (nframes);
} }
/* Engine Process */ /* Engine Process */
@ -1073,8 +1071,9 @@ PulseAudioBackend::main_process_thread ()
assert (_system_outputs.size () == N_CHANNELS); assert (_system_outputs.size () == N_CHANNELS);
/* interleave */ /* interleave */
for (std::vector<BackendPort *>::const_iterator it = _system_outputs.begin (); it != _system_outputs.end (); ++it, ++i) { for (std::vector<BackendPortPtr>::const_iterator it = _system_outputs.begin (); it != _system_outputs.end (); ++it, ++i) {
const float* src = (const float*)(*it)->get_buffer (_samples_per_period); BackendPortPtr port = boost::dynamic_pointer_cast<BackendPort> (*it);
const float* src = (const float*) port->get_buffer (_samples_per_period);
for (size_t n = 0; n < _samples_per_period; ++n) { for (size_t n = 0; n < _samples_per_period; ++n) {
buf[N_CHANNELS * n + i] = src[n]; buf[N_CHANNELS * n + i] = src[n];
} }
@ -1129,7 +1128,7 @@ PulseAudioBackend::main_process_thread ()
manager.graph_order_callback (); manager.graph_order_callback ();
} }
if (connections_changed || ports_changed) { if (connections_changed || ports_changed) {
update_system_port_latecies (); update_system_port_latencies ();
engine.latency_callback (false); engine.latency_callback (false);
engine.latency_callback (true); engine.latency_callback (true);
} }
@ -1222,16 +1221,17 @@ void*
PulseAudioPort::get_buffer (pframes_t n_samples) PulseAudioPort::get_buffer (pframes_t n_samples)
{ {
if (is_input ()) { if (is_input ()) {
const std::set<BackendPort*>& connections = get_connections (); const std::set<BackendPortPtr>& connections = get_connections ();
std::set<BackendPort*>::const_iterator it = connections.begin (); std::set<BackendPortPtr>::const_iterator it = connections.begin ();
if (it == connections.end ()) { if (it == connections.end ()) {
memset (_buffer, 0, n_samples * sizeof (Sample)); memset (_buffer, 0, n_samples * sizeof (Sample));
} else { } else {
PulseAudioPort* source = static_cast<PulseAudioPort*> (*it); boost::shared_ptr<PulseAudioPort> source = boost::dynamic_pointer_cast<PulseAudioPort> (*it);
assert (source && source->is_output ()); assert (source && source->is_output ());
memcpy (_buffer, source->const_buffer (), n_samples * sizeof (Sample)); memcpy (_buffer, source->const_buffer (), n_samples * sizeof (Sample));
while (++it != connections.end ()) { while (++it != connections.end ()) {
source = static_cast<PulseAudioPort*> (*it); source = boost::dynamic_pointer_cast<PulseAudioPort> (*it);
assert (source && source->is_output ()); assert (source && source->is_output ());
Sample* dst = buffer (); Sample* dst = buffer ();
const Sample* src = source->const_buffer (); const Sample* src = source->const_buffer ();
@ -1269,11 +1269,11 @@ void* PulseMidiPort::get_buffer (pframes_t /*n_samples*/)
{ {
if (is_input ()) { if (is_input ()) {
_buffer.clear (); _buffer.clear ();
const std::set<BackendPort*>& connections = get_connections (); const std::set<BackendPortPtr>& connections = get_connections ();
for (std::set<BackendPort*>::const_iterator i = connections.begin (); for (std::set<BackendPortPtr>::const_iterator i = connections.begin ();
i != connections.end (); i != connections.end ();
++i) { ++i) {
const PulseMidiBuffer* src = static_cast<PulseMidiPort*> (*i)->const_buffer (); const PulseMidiBuffer* src = boost::dynamic_pointer_cast<PulseMidiPort> (*i)->const_buffer ();
for (PulseMidiBuffer::const_iterator it = src->begin (); it != src->end (); ++it) { for (PulseMidiBuffer::const_iterator it = src->begin (); it != src->end (); ++it) {
_buffer.push_back (*it); _buffer.push_back (*it);
} }

View file

@ -195,12 +195,12 @@ public:
int set_port_name (PortEngine::PortHandle ph, const std::string& name) { return PortEngineSharedImpl::set_port_name (ph, name); } int set_port_name (PortEngine::PortHandle ph, const std::string& name) { return PortEngineSharedImpl::set_port_name (ph, name); }
std::string get_port_name (PortEngine::PortHandle ph) const { return PortEngineSharedImpl::get_port_name (ph); } std::string get_port_name (PortEngine::PortHandle ph) const { return PortEngineSharedImpl::get_port_name (ph); }
PortFlags get_port_flags (PortEngine::PortHandle ph) const { return PortEngineSharedImpl::get_port_flags (ph); } PortFlags get_port_flags (PortEngine::PortHandle ph) const { return PortEngineSharedImpl::get_port_flags (ph); }
PortEngine::PortHandle get_port_by_name (std::string const & name) const { return PortEngineSharedImpl::get_port_by_name (name); } PortEngine::PortPtr get_port_by_name (std::string const & name) const { return PortEngineSharedImpl::get_port_by_name (name); }
int get_port_property (PortEngine::PortHandle ph, const std::string& key, std::string& value, std::string& type) const { return PortEngineSharedImpl::get_port_property (ph, key, value, type); } int get_port_property (PortEngine::PortHandle ph, const std::string& key, std::string& value, std::string& type) const { return PortEngineSharedImpl::get_port_property (ph, key, value, type); }
int set_port_property (PortEngine::PortHandle ph, const std::string& key, const std::string& value, const std::string& type) { return PortEngineSharedImpl::set_port_property (ph, key, value, type); } int set_port_property (PortEngine::PortHandle ph, const std::string& key, const std::string& value, const std::string& type) { return PortEngineSharedImpl::set_port_property (ph, key, value, type); }
int get_ports (const std::string& port_name_pattern, DataType type, PortFlags flags, std::vector<std::string>& results) const { return PortEngineSharedImpl::get_ports (port_name_pattern, type, flags, results); } int get_ports (const std::string& port_name_pattern, DataType type, PortFlags flags, std::vector<std::string>& results) const { return PortEngineSharedImpl::get_ports (port_name_pattern, type, flags, results); }
DataType port_data_type (PortEngine::PortHandle ph) const { return PortEngineSharedImpl::port_data_type (ph); } DataType port_data_type (PortEngine::PortHandle ph) const { return PortEngineSharedImpl::port_data_type (ph); }
PortEngine::PortHandle register_port (const std::string& shortname, ARDOUR::DataType type, ARDOUR::PortFlags flags) { return PortEngineSharedImpl::register_port (shortname, type, flags); } PortEngine::PortPtr register_port (const std::string& shortname, ARDOUR::DataType type, ARDOUR::PortFlags flags) { return PortEngineSharedImpl::register_port (shortname, type, flags); }
void unregister_port (PortHandle ph) { if (!_run) return; PortEngineSharedImpl::unregister_port (ph); } void unregister_port (PortHandle ph) { if (!_run) return; PortEngineSharedImpl::unregister_port (ph); }
int connect (const std::string& src, const std::string& dst) { return PortEngineSharedImpl::connect (src, dst); } int connect (const std::string& src, const std::string& dst) { return PortEngineSharedImpl::connect (src, dst); }
int disconnect (const std::string& src, const std::string& dst) { return PortEngineSharedImpl::disconnect (src, dst); } int disconnect (const std::string& src, const std::string& dst) { return PortEngineSharedImpl::disconnect (src, dst); }
@ -294,7 +294,6 @@ private:
/* port engine */ /* port engine */
BackendPort* port_factory (std::string const & name, ARDOUR::DataType dt, ARDOUR::PortFlags flags); BackendPort* port_factory (std::string const & name, ARDOUR::DataType dt, ARDOUR::PortFlags flags);
int register_system_ports (); int register_system_ports ();
void update_system_port_latecies ();
struct PortConnectData { struct PortConnectData {
std::string a; std::string a;