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;
MIDIDM* _mididm;
LatencyMeasurement _measuring_latency;
PortEngine::PortHandle _latency_input_port;
PortEngine::PortHandle _latency_output_port;
PortEngine::PortPtr _latency_input_port;
PortEngine::PortPtr _latency_output_port;
samplecnt_t _latency_flush_samples;
std::string _latency_input_name;
std::string _latency_output_name;

View File

@ -159,7 +159,7 @@ protected:
Port (std::string const &, DataType, PortFlags);
PortEngine::PortHandle _port_handle;
PortEngine::PortPtr _port_handle;
static bool _connecting_blocked;
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.
*/
class LIBARDOUR_API ProtoPort {
public:
ProtoPort() {}
virtual ~ProtoPort () {}
};
class LIBARDOUR_API PortEngine
{
public:
@ -88,14 +94,24 @@ public:
/** 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
* PortHandle as T, but this complicates the desired inheritance
* pattern in which FooPortEngine handles things for the Foo API,
* 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
* when naming ports.
@ -164,7 +180,7 @@ public:
* @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.
*/
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
* specified values, place the names of each port into \p ports .
@ -194,7 +210,7 @@ public:
* @param flags flags of the port to create
* @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
* 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
*/
virtual void unregister_port (PortHandle port) = 0;
virtual void unregister_port (PortHandle port) = 0;
/* Connection management */

View File

@ -39,25 +39,28 @@ namespace ARDOUR {
class PortEngineSharedImpl;
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);
public:
public:
virtual ~BackendPort ();
const std::string& name () const { return _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;
return 0;
}
int set_pretty_name (const std::string& name)
{
int set_pretty_name (const std::string& name) {
_pretty_name = name;
return 0;
}
@ -71,17 +74,16 @@ public:
bool is_terminal () const { return flags () & IsTerminal; }
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;
const std::set<BackendPort*>& get_connections () const
{
const std::set<BackendPortPtr>& get_connections () const {
return _connections;
}
int connect (BackendPort* port);
int disconnect (BackendPort* port);
void disconnect_all ();
int connect (BackendPortHandle port, BackendPortHandle self);
int disconnect (BackendPortHandle port, BackendPortHandle self);
void disconnect_all (BackendPortHandle self);
virtual void* get_buffer (pframes_t nframes) = 0;
@ -103,10 +105,10 @@ private:
const PortFlags _flags;
LatencyRange _capture_latency_range;
LatencyRange _playback_latency_range;
std::set<BackendPort*> _connections;
std::set<BackendPortPtr> _connections;
void _connect (BackendPort*, bool);
void _disconnect (BackendPort*, bool);
void store_connection (BackendPortHandle);
void remove_connection (BackendPortHandle);
}; // class BackendPort
@ -129,7 +131,7 @@ public:
int set_port_name (PortEngine::PortHandle, const std::string&);
std::string get_port_name (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 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;
PortEngine::PortHandle register_port (const std::string& shortname, ARDOUR::DataType, ARDOUR::PortFlags);
virtual void unregister_port (PortEngine::PortHandle);
PortEngine::PortPtr register_port (const std::string& shortname, ARDOUR::DataType, ARDOUR::PortFlags);
virtual void unregister_port (PortEngine::PortHandle);
int connect (const std::string& src, const std::string& dst);
int disconnect (const std::string& src, const std::string& dst);
@ -158,36 +160,35 @@ public:
protected:
std::string _instance_name;
std::vector<BackendPort*> _system_inputs;
std::vector<BackendPort*> _system_outputs;
std::vector<BackendPort*> _system_midi_in;
std::vector<BackendPort*> _system_midi_out;
std::vector<BackendPortPtr> _system_inputs;
std::vector<BackendPortPtr> _system_outputs;
std::vector<BackendPortPtr> _system_midi_in;
std::vector<BackendPortPtr> _system_midi_out;
virtual void update_system_port_latencies ();
void clear_ports ();
PortEngine::PortHandle add_port (const std::string& shortname, ARDOUR::DataType, ARDOUR::PortFlags);
void unregister_ports (bool system_only = false);
BackendPortPtr add_port (const std::string& shortname, ARDOUR::DataType, ARDOUR::PortFlags);
void unregister_ports (bool system_only = false);
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 ());
}
};
typedef std::map<std::string, BackendPort*> PortMap; // fast lookup in _ports
typedef std::set<BackendPort*, SortByPortName> PortIndex; // fast lookup in _ports
typedef std::map<std::string, BackendPortPtr> PortMap; // fast lookup in _ports
typedef std::set<BackendPortPtr, SortByPortName> PortIndex; // fast lookup in _ports
SerializedRCUManager<PortMap> _portmap;
SerializedRCUManager<PortIndex> _ports;
bool valid_port (PortEngine::PortHandle port) const
{
bool valid_port (BackendPortHandle port) const {
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 ();
PortMap::const_iterator it = p->find (port_name);
if (it == p->end ()) {

View File

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

View File

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

View File

@ -76,7 +76,7 @@ Port::Port (std::string const & n, DataType t, PortFlags f)
if (!port_manager->running ()) {
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) {
cerr << "Failed to register port \"" << _name << "\", reason is unknown from here\n";
throw failed_constructor ();

View File

@ -40,10 +40,11 @@ BackendPort::BackendPort (PortEngineSharedImpl &b, const std::string& name, Port
BackendPort::~BackendPort ()
{
disconnect_all ();
assert (_connections.empty());
}
int BackendPort::connect (BackendPort *port)
int
BackendPort::connect (BackendPortHandle port, BackendPortHandle self)
{
if (!port) {
PBD::error << _("BackendPort::connect (): invalid (null) port") << endmsg;
@ -65,7 +66,7 @@ int BackendPort::connect (BackendPort *port)
return -1;
}
if (this == port) {
if (this == port.get()) {
PBD::error << _("BackendPort::connect (): cannot self-connect ports.") << endmsg;
return -1;
}
@ -79,20 +80,22 @@ int BackendPort::connect (BackendPort *port)
return -1;
}
_connect (port, true);
store_connection (port);
port->store_connection (self);
_backend.port_connect_callback (name(), port->name(), true);
return 0;
}
void BackendPort::_connect (BackendPort *port, bool callback)
void
BackendPort::store_connection (BackendPortHandle 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) {
PBD::error << _("BackendPort::disconnect (): invalid (null) port") << endmsg;
@ -105,41 +108,41 @@ int BackendPort::disconnect (BackendPort *port)
<< endmsg;
return -1;
}
_disconnect (port, true);
remove_connection (port);
port->remove_connection (self);
_backend.port_connect_callback (name(), port->name(), false);
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 ());
_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 ()) {
std::set<BackendPort*>::iterator it = _connections.begin ();
(*it)->_disconnect (this, false);
std::set<BackendPortPtr>::iterator it = _connections.begin ();
(*it)->remove_connection (self);
_backend.port_connect_callback (name(), (*it)->name(), false);
_connections.erase (it);
}
}
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
{
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 ()) {
return true;
}
@ -156,7 +159,7 @@ BackendPort::set_latency_range (const LatencyRange &latency_range, bool for_play
_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 ()) {
(*it)->update_connected_latency (is_input ());
}
@ -168,7 +171,7 @@ BackendPort::update_connected_latency (bool for_playback)
{
LatencyRange lr;
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;
l = (*it)->latency_range (for_playback);
lr.min = std::max (lr.min, l.min);
@ -208,7 +211,7 @@ PortEngineSharedImpl::get_ports (
boost::shared_ptr<PortIndex> p = _ports.reader ();
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 (!use_regexp || !regexec (&port_regex, port->name ().c_str (), 0, NULL, 0)) {
port_names.push_back (port->name ());
@ -227,11 +230,11 @@ PortEngineSharedImpl::get_ports (
bool
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;
return false;
}
return static_cast<BackendPort*>(port)->is_physical ();
return boost::dynamic_pointer_cast<BackendPort>(port)->is_physical ();
}
void
@ -240,7 +243,7 @@ PortEngineSharedImpl::get_physical_outputs (DataType type, std::vector<std::stri
boost::shared_ptr<PortIndex> p = _ports.reader();
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 ()) {
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();
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 ()) {
port_names.push_back (port->name ());
}
@ -269,7 +272,7 @@ PortEngineSharedImpl::n_physical_outputs () const
boost::shared_ptr<PortIndex> p = _ports.reader();
for (PortIndex::const_iterator i = p->begin (); i != p->end (); ++i) {
BackendPort* port = *i;
BackendPortPtr port = *i;
if (port->is_output () && port->is_physical ()) {
switch (port->type ()) {
case DataType::AUDIO: ++n_audio; break;
@ -293,7 +296,7 @@ PortEngineSharedImpl::n_physical_inputs () const
boost::shared_ptr<PortIndex> p = _ports.reader();
for (PortIndex::const_iterator i = p->begin (); i != p->end (); ++i) {
BackendPort* port = *i;
BackendPortPtr port = *i;
if (port->is_input () && port->is_physical ()) {
switch (port->type ()) {
case DataType::AUDIO: ++n_audio; break;
@ -308,22 +311,20 @@ PortEngineSharedImpl::n_physical_inputs () const
return cc;
}
PortEngine::PortHandle
PortEngineSharedImpl::add_port (
const std::string& name,
ARDOUR::DataType type,
ARDOUR::PortFlags flags)
BackendPortPtr
PortEngineSharedImpl::add_port (const std::string& name, ARDOUR::DataType type, ARDOUR::PortFlags flags)
{
assert(name.size ());
if (find_port (name)) {
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) {
return 0;
return BackendPortPtr ();
}
{
@ -343,7 +344,7 @@ PortEngineSharedImpl::add_port (
void
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);
@ -352,20 +353,18 @@ PortEngineSharedImpl::unregister_port (PortEngine::PortHandle port_handle)
boost::shared_ptr<PortIndex> ps = index_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 ()) {
PBD::error << string_compose (_("%1::unregister_port: Failed to find port"), _instance_name) << endmsg;
return;
}
disconnect_all(port_handle);
disconnect_all (port_handle);
pm->erase (port->name());
ps->erase (i);
}
delete port;
}
@ -386,11 +385,10 @@ PortEngineSharedImpl::unregister_ports (bool system_only)
for (PortIndex::iterator i = ps->begin (); i != ps->end ();) {
PortIndex::iterator cur = i++;
BackendPort* port = *cur;
BackendPortPtr port = *cur;
if (! system_only || (port->is_physical () && port->is_terminal ())) {
port->disconnect_all ();
port->disconnect_all (port);
pm->erase (port->name());
delete port;
ps->erase (cur);
}
}
@ -423,9 +421,10 @@ PortEngineSharedImpl::port_name_size () const
}
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);
BackendPortPtr port = boost::dynamic_pointer_cast<BackendPort>(port_handle);
if (!valid_port (port)) {
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;
}
BackendPort* p = static_cast<BackendPort*>(port);
int ret = port->set_name (newname);
if (ret == 0) {
{
RCUWriter<PortMap> map_writer (_portmap);
boost::shared_ptr<PortMap> pm = map_writer.get_copy ();
pm->erase (p->name());
pm->insert (make_pair (newname, p));
pm->erase (port->name());
pm->insert (make_pair (newname, port));
}
return p->set_name (newname);
return ret;
}
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)) {
PBD::warning << string_compose (_("AlsaBackend::get_port_name: Invalid Port(s)"), _instance_name) << endmsg;
return std::string ();
}
return static_cast<BackendPort*>(port)->name ();
return port->name ();
}
PortFlags
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;
return PortFlags (0);
}
return static_cast<BackendPort*>(port)->flags ();
return boost::static_pointer_cast<BackendPort>(port)->flags ();
}
int
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;
return -1;
}
if (key == "http://jackaudio.org/metadata/pretty-name") {
type = "";
value = static_cast<BackendPort*>(port)->pretty_name ();
value = boost::static_pointer_cast<BackendPort>(port)->pretty_name ();
if (!value.empty()) {
return 0;
}
@ -490,50 +493,51 @@ PortEngineSharedImpl::get_port_property (PortEngine::PortHandle port, const std:
int
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;
return -1;
}
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 -1;
}
PortEngine::PortHandle
PortEngine::PortPtr
PortEngineSharedImpl::get_port_by_name (const std::string& name) const
{
PortEngine::PortHandle port = (PortEngine::PortHandle) find_port (name);
return port;
return find_port (name);
}
DataType
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 static_cast<BackendPort*>(port)->type ();
return p->type ();
}
PortEngine::PortHandle
PortEngine::PortPtr
PortEngineSharedImpl::register_port (
const std::string& name,
ARDOUR::DataType type,
ARDOUR::PortFlags flags)
{
if (name.size () == 0) { return 0; }
if (flags & IsPhysical) { return 0; }
if (name.size () == 0) { return PortEngine::PortPtr(); }
if (flags & IsPhysical) { return PortEngine::PortPtr(); }
return add_port (_instance_name + ":" + name, type, flags);
}
int
PortEngineSharedImpl::connect (const std::string& src, const std::string& dst)
{
BackendPort* src_port = find_port (src);
BackendPort* dst_port = find_port (dst);
BackendPortPtr src_port = find_port (src);
BackendPortPtr dst_port = find_port (dst);
if (!src_port) {
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;
return -1;
}
return src_port->connect (dst_port);
src_port->connect (dst_port, src_port);
return 0;
}
int
PortEngineSharedImpl::disconnect (const std::string& src, const std::string& dst)
{
BackendPort* src_port = find_port (src);
BackendPort* dst_port = find_port (dst);
BackendPortPtr src_port = find_port (src);
BackendPortPtr dst_port = find_port (dst);
if (!src_port || !dst_port) {
PBD::error << string_compose (_("%1::disconnect: Invalid Port(s)"), _instance_name) << endmsg;
return -1;
}
return src_port->disconnect (dst_port);
return src_port->disconnect (dst_port, src_port);
}
int
PortEngineSharedImpl::connect (PortEngine::PortHandle src, const std::string& dst)
{
BackendPort* dst_port = find_port (dst);
if (!valid_port (src)) {
BackendPortPtr src_port = boost::dynamic_pointer_cast<BackendPort> (src);
if (!valid_port (src_port)) {
PBD::error << string_compose (_("%1::connect: Invalid Source Port Handle"), _instance_name) << endmsg;
return -1;
}
BackendPortPtr dst_port = find_port (dst);
if (!dst_port) {
PBD::error << string_compose (_("%1::connect: Invalid Destination Port: (%2)"), _instance_name, dst) << endmsg;
return -1;
}
return static_cast<BackendPort*>(src)->connect (dst_port);
src_port->connect (dst_port, src_port);
return 0;
}
int
PortEngineSharedImpl::disconnect (PortEngine::PortHandle src, const std::string& dst)
{
BackendPort* dst_port = find_port (dst);
if (!valid_port (src) || !dst_port) {
BackendPortPtr src_port = boost::dynamic_pointer_cast<BackendPort>(src);
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;
return -1;
}
return static_cast<BackendPort*>(src)->disconnect (dst_port);
return src_port->disconnect (dst_port, src_port);
}
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)) {
PBD::error << string_compose (_("%1::disconnect_all: Invalid Port"), _instance_name) << endmsg;
return -1;
}
static_cast<BackendPort*>(port)->disconnect_all ();
port->disconnect_all (port);
return 0;
}
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)) {
PBD::error << string_compose (_("%1::disconnect_all: Invalid Port"), _instance_name) << endmsg;
return false;
}
return static_cast<BackendPort*>(port)->is_connected ();
return port->is_connected ();
}
bool
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
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;
return false;
}
#endif
return static_cast<BackendPort*>(src)->is_connected (dst_port);
return boost::static_pointer_cast<BackendPort>(src)->is_connected (dst_port);
}
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)) {
PBD::error << string_compose (_("%1::physically_connected: Invalid Port"), _instance_name) << endmsg;
return false;
}
return static_cast<BackendPort*>(port)->is_physically_connected ();
return port->is_physically_connected ();
}
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)) {
PBD::error << string_compose (_("%1::get_connections: Invalid Port"), _instance_name) << endmsg;
return -1;
@ -639,11 +666,29 @@ PortEngineSharedImpl::get_connections (PortEngine::PortHandle port, std::vector<
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 ());
}
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;
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);
}
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);
}
update_latencies ();
@ -480,18 +480,18 @@ AlsaAudioBackend::update_systemic_midi_latencies ()
{
pthread_mutex_lock (&_device_port_mutex);
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);
AlsaMidiOut *rm = _rmidi_out.at(i);
struct AlsaMidiDeviceInfo * nfo = midi_device_info (rm->name());
assert (nfo);
LatencyRange lr;
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;
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);
AlsaMidiIO *rm = _rmidi_in.at(i);
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
pthread_mutex_lock (&_device_port_mutex);
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);
AlsaMidiOut *rm = _rmidi_out.at(i);
if (rm->name () != device) { ++it; ++i; continue; }
@ -698,7 +698,7 @@ AlsaAudioBackend::set_midi_device_enabled (std::string const device, bool enable
}
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);
AlsaMidiIn *rm = _rmidi_in.at(i);
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));
if (!p) return -1;
set_latency_range (p, false, lr);
BackendPort *ap = static_cast<BackendPort*>(p);
BackendPortPtr ap = boost::dynamic_pointer_cast<BackendPort>(p);
//ap->set_pretty_name ("")
_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));
if (!p) return -1;
set_latency_range (p, true, lr);
BackendPort *ap = static_cast<BackendPort*>(p);
BackendPortPtr ap = boost::dynamic_pointer_cast<BackendPort>(p);
//ap->set_pretty_name ("")
_system_outputs.push_back (ap);
}
@ -1351,32 +1351,25 @@ AlsaAudioBackend::stop_listen_for_midi_device_changes ()
* and capture-latency for _system_outputs
*/
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);
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);
}
PortEngineSharedImpl::update_system_port_latencies ();
pthread_mutex_unlock (&_device_port_mutex);
for (AudioSlaves::iterator s = _slaves.begin (); s != _slaves.end (); ++s) {
if ((*s)->dead) {
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);
}
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);
}
}
@ -1472,8 +1465,8 @@ AlsaAudioBackend::register_system_midi_ports(const std::string device)
LatencyRange lr;
lr.min = lr.max = (nfo->systemic_output_latency);
set_latency_range (p, true, lr);
static_cast<AlsaMidiPort*>(p)->set_n_periods(_periods_per_cycle); // TODO check MIDI alignment
BackendPort *ap = static_cast<BackendPort*>(p);
boost::dynamic_pointer_cast<AlsaMidiPort>(p)->set_n_periods(_periods_per_cycle); // TODO check MIDI alignment
BackendPortPtr ap = boost::dynamic_pointer_cast<BackendPort>(p);
ap->set_pretty_name (replace_name_io (i->first, false));
pthread_mutex_lock (&_device_port_mutex);
_system_midi_out.push_back (ap);
@ -1520,7 +1513,7 @@ AlsaAudioBackend::register_system_midi_ports(const std::string device)
LatencyRange lr;
lr.min = lr.max = (nfo->systemic_input_latency);
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));
pthread_mutex_lock (&_device_port_mutex);
_system_midi_in.push_back (ap);
@ -1619,38 +1612,40 @@ AlsaAudioBackend::monitoring_input (PortEngine::PortHandle)
/* Latency management */
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)) {
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
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;
if (!valid_port (port)) {
PBD::error << _("AlsaPort::get_latency_range (): invalid port.") << endmsg;
r.min = 0;
r.max = 0;
return r;
}
BackendPort *p = static_cast<BackendPort*>(port);
assert(p);
r = p->latency_range (for_playback);
if (p->is_physical() && p->is_terminal()) {
if (p->is_input() && for_playback) {
r = port->latency_range (for_playback);
if (port->is_physical() && port->is_terminal()) {
if (port->is_input() && for_playback) {
r.min += _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.max += _samples_per_period;
}
}
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 */
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 (valid_port (port));
return static_cast<BackendPort*>(port)->get_buffer (nframes);
return port->get_buffer (nframes);
}
/* Engine Process */
@ -1710,7 +1706,7 @@ AlsaAudioBackend::main_process_thread ()
/* warm up */
int cnt = std::max (8, (int)(_samplerate / _samples_per_period) / 2);
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));
}
if (engine.process_callback (_samples_per_period)) {
@ -1767,10 +1763,10 @@ AlsaAudioBackend::main_process_thread ()
if ((*s)->halt) {
/* slave died, unregister its ports (not rt-safe, but no matter) */
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);
}
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);
}
(*s)->inputs.clear ();
@ -1810,8 +1806,8 @@ AlsaAudioBackend::main_process_thread ()
no_proc_errors = 0;
_pcmi->capt_init (_samples_per_period);
for (std::vector<BackendPort*>::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);
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_done (_samples_per_period);
@ -1820,8 +1816,8 @@ AlsaAudioBackend::main_process_thread ()
continue;
}
i = 0;
for (std::vector<BackendPort*>::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);
for (std::vector<BackendPortPtr>::const_iterator it = (*s)->inputs.begin (); it != (*s)->inputs.end (); ++it, ++i) {
(*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);
/* de-queue incoming midi*/
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);
AlsaMidiIn *rm = _rmidi_in.at(i);
void *bptr = (*it)->get_buffer(0);
@ -1845,7 +1841,7 @@ AlsaAudioBackend::main_process_thread ()
}
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));
}
@ -1859,15 +1855,15 @@ AlsaAudioBackend::main_process_thread ()
/* only used when adding/removing MIDI device/system ports */
pthread_mutex_lock (&_device_port_mutex);
for (std::vector<BackendPort*>::iterator it = _system_midi_out.begin (); it != _system_midi_out.end (); ++it) {
static_cast<AlsaMidiPort*>(*it)->next_period();
for (std::vector<BackendPortPtr>::iterator it = _system_midi_out.begin (); it != _system_midi_out.end (); ++it) {
boost::dynamic_pointer_cast<AlsaMidiPort>(*it)->next_period();
}
/* queue outgoing midi */
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);
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);
rm->sync_time (clock1);
for (AlsaMidiBuffer::const_iterator mit = src->begin (); mit != src->end (); ++mit) {
@ -1879,7 +1875,7 @@ AlsaAudioBackend::main_process_thread ()
/* write back audio */
i = 0;
_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);
}
for (; i < _pcmi->nplay (); ++i) {
@ -1892,8 +1888,8 @@ AlsaAudioBackend::main_process_thread ()
continue;
}
i = 0;
for (std::vector<BackendPort*>::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);
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)->cycle_end ();
}
@ -1920,14 +1916,14 @@ AlsaAudioBackend::main_process_thread ()
// Freewheelin'
// 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));
}
clock1 = g_get_monotonic_time();
uint32_t i = 0;
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 ();
AlsaMidiIn *rm = _rmidi_in.at(i);
void *bptr = (*it)->get_buffer(0);
@ -1953,7 +1949,7 @@ AlsaAudioBackend::main_process_thread ()
// drop all outgoing MIDI messages
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);
midi_clear(bptr);
}
@ -1989,7 +1985,7 @@ AlsaAudioBackend::main_process_thread ()
manager.graph_order_callback();
}
if (connections_changed || ports_changed) {
update_system_port_latecies (); // flush, clear
update_system_port_latencies (); // flush, clear
engine.latency_callback(false);
engine.latency_callback(true);
}
@ -2031,10 +2027,9 @@ AlsaAudioBackend::add_slave (const char* device,
break;
}
} 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;
BackendPort *ap = static_cast<BackendPort*>(p);
s->inputs.push_back (ap);
s->inputs.push_back (boost::dynamic_pointer_cast<BackendPort>(p));
}
for (uint32_t i = 0, n = 1; i < s->nplay (); ++i) {
@ -2047,10 +2042,9 @@ AlsaAudioBackend::add_slave (const char* device,
break;
}
} 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;
BackendPort *ap = static_cast<BackendPort*>(p);
s->outputs.push_back (ap);
s->outputs.push_back (boost::dynamic_pointer_cast<BackendPort> (p));
}
if (!s->start ()) {
@ -2105,12 +2099,12 @@ AlsaAudioBackend::AudioSlave::update_latencies (uint32_t play, uint32_t capt)
{
LatencyRange lr;
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);
}
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);
}
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)
{
memset (_buffer, 0, sizeof (_buffer));
mlock(_buffer, sizeof (_buffer));
mlock (_buffer, sizeof (_buffer));
}
AlsaAudioPort::~AlsaAudioPort () { }
void* AlsaAudioPort::get_buffer (pframes_t n_samples)
void*
AlsaAudioPort::get_buffer (pframes_t n_samples)
{
if (is_input ()) {
const std::set<BackendPort *>& connections = get_connections ();
std::set<BackendPort*>::const_iterator it = connections.begin ();
const std::set<BackendPortPtr>& connections = get_connections ();
std::set<BackendPortPtr>::const_iterator it = connections.begin ();
if (it == connections.end ()) {
memset (_buffer, 0, n_samples * sizeof (Sample));
} 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 ());
memcpy (_buffer, source->const_buffer (), n_samples * sizeof (Sample));
while (++it != connections.end ()) {
source = static_cast<const AlsaAudioPort*>(*it);
source = boost::dynamic_pointer_cast<const AlsaAudioPort>(*it);
assert (source && source->is_output ());
Sample* dst = buffer ();
const Sample* src = source->const_buffer ();
@ -2241,11 +2236,11 @@ void* AlsaMidiPort::get_buffer (pframes_t /* nframes */)
{
if (is_input ()) {
(_buffer[_bufperiod]).clear ();
const std::set<BackendPort*>& connections = get_connections ();
for (std::set<BackendPort*>::const_iterator i = connections.begin ();
const std::set<BackendPortPtr>& connections = get_connections ();
for (std::set<BackendPortPtr>::const_iterator i = connections.begin ();
i != connections.end ();
++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) {
(_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); }
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); }
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 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); }
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); }
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); }
@ -366,7 +366,7 @@ class AlsaAudioBackend : public AudioBackend, public PortEngineSharedImpl
int register_system_audio_ports ();
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<AlsaMidiIn *> _rmidi_in;
@ -422,8 +422,8 @@ class AlsaAudioBackend : public AudioBackend, public PortEngineSharedImpl
bool halt;
bool dead;
std::vector<BackendPort *> inputs;
std::vector<BackendPort *> outputs;
std::vector<BackendPortPtr> inputs;
std::vector<BackendPortPtr> outputs;
PBD::Signal0<void> UpdateLatency;
PBD::ScopedConnection latency_connection;

View File

@ -973,24 +973,6 @@ CoreAudioBackend::register_system_audio_ports()
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
CoreAudioBackend::coremidi_rediscover()
{
@ -1275,7 +1257,7 @@ CoreAudioBackend::pre_process ()
manager.graph_order_callback();
}
if (connections_changed || ports_changed) {
update_system_port_latecies ();
update_system_port_latencies ();
engine.latency_callback(false);
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); }
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); }
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 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); }
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); }
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); }
@ -396,7 +396,6 @@ class CoreAudioBackend : public AudioBackend, public PortEngineSharedImpl {
/* port engine */
int register_system_audio_ports ();
void update_system_port_latecies ();
struct PortConnectData {
std::string a;

View File

@ -263,18 +263,18 @@ DummyAudioBackend::set_buffer_size (uint32_t bs)
*/
LatencyRange lr;
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);
}
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);
}
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);
}
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);
}
@ -689,13 +689,18 @@ DummyAudioBackend::register_system_ports()
for (int i = 1; i <= a_ins; ++i) {
char tmp[64];
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;
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 ()) {
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) {
char tmp[64];
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;
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 */
@ -714,20 +719,24 @@ DummyAudioBackend::register_system_ports()
for (int i = 0; i < m_ins; ++i) {
char tmp[64];
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;
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) {
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 ()) {
static_cast<DummyMidiPort*>(p)->set_pretty_name (name);
dp->set_pretty_name (name);
}
}
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 ()) {
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));
if (!p) return -1;
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) {
std::stringstream ss;
@ -749,30 +760,12 @@ DummyAudioBackend::register_system_ports()
ss << " >" << (apc + 1);
}
}
static_cast<DummyMidiPort*>(p)->set_pretty_name (ss.str());
dp->set_pretty_name (ss.str());
}
}
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*
DummyAudioBackend::port_factory (std::string const & name, ARDOUR::DataType type, ARDOUR::PortFlags flags)
{
@ -881,35 +874,35 @@ DummyAudioBackend::monitoring_input (PortEngine::PortHandle)
/* Latency management */
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)) {
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
DummyAudioBackend::get_latency_range (PortEngine::PortHandle port, bool for_playback)
DummyAudioBackend::get_latency_range (PortEngine::PortHandle port_handle, bool for_playback)
{
LatencyRange r;
BackendPortPtr port = boost::dynamic_pointer_cast<BackendPort> (port_handle);
if (!valid_port (port)) {
PBD::error << _("DummyPort::get_latency_range (): invalid port.") << endmsg;
r.min = 0;
r.max = 0;
return r;
}
DummyPort *p = static_cast<DummyPort*>(port);
assert(p);
r = p->latency_range (for_playback);
if (p->is_physical() && p->is_terminal()) {
if (p->is_input() && for_playback) {
r = port->latency_range (for_playback);
if (port->is_physical() && port->is_terminal()) {
if (port->is_input() && for_playback) {
const size_t l_in = _samples_per_period * .25;
r.min += 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; */
const size_t l_in = _samples_per_period * .25;
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 */
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 (valid_port (port));
return static_cast<DummyPort*>(port)->get_buffer (nframes);
return port->get_buffer (nframes);
}
/* Engine Process */
@ -952,11 +946,11 @@ DummyAudioBackend::main_process_thread ()
}
// re-set input buffers, generate on demand.
for (std::vector<BackendPort*>::const_iterator it = _system_inputs.begin (); it != _system_inputs.end (); ++it) {
static_cast<DummyPort*>(*it)->next_period();
for (std::vector<BackendPortPtr>::const_iterator it = _system_inputs.begin (); it != _system_inputs.end (); ++it) {
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) {
static_cast<DummyPort*>(*it)->next_period();
for (std::vector<BackendPortPtr>::const_iterator it = _system_midi_in.begin (); it != _system_midi_in.end (); ++it) {
boost::dynamic_pointer_cast<DummyPort>(*it)->next_period ();
}
if (engine.process_callback (samples_per_period)) {
@ -967,28 +961,28 @@ DummyAudioBackend::main_process_thread ()
if (_device == _("Loopback") && _midi_mode != MidiToAudio) {
int opn = 0;
int opc = _system_outputs.size();
for (std::vector<BackendPort*>::const_iterator it = _system_inputs.begin (); it != _system_inputs.end (); ++it, ++opn) {
DummyAudioPort* op = static_cast<DummyAudioPort*> (_system_outputs[(opn % opc)]);
static_cast<DummyAudioPort*>(*it)->fill_wavetable ((const float*)op->get_buffer (samples_per_period), samples_per_period);
for (std::vector<BackendPortPtr>::const_iterator it = _system_inputs.begin (); it != _system_inputs.end (); ++it, ++opn) {
BackendPortPtr op = _system_outputs[(opn % opc)];
boost::dynamic_pointer_cast<DummyAudioPort>(*it)->fill_wavetable ((const float*)op->get_buffer (samples_per_period), samples_per_period);
}
}
if (_midi_mode == MidiLoopback) {
int opn = 0;
int opc = _system_midi_out.size();
for (std::vector<BackendPort*>::const_iterator it = _system_midi_in.begin (); it != _system_midi_in.end (); ++it, ++opn) {
DummyMidiPort* op = static_cast<DummyMidiPort*> (_system_midi_out[(opn % opc)]);
for (std::vector<BackendPortPtr>::const_iterator it = _system_midi_in.begin (); it != _system_midi_in.end (); ++it, ++opn) {
boost::shared_ptr<DummyMidiPort> op = boost::dynamic_pointer_cast<DummyMidiPort> (_system_midi_out[(opn % opc)]);
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) {
int opn = 0;
int opc = _system_midi_out.size();
for (std::vector<BackendPort*>::const_iterator it = _system_inputs.begin (); it != _system_inputs.end (); ++it, ++opn) {
DummyMidiPort* op = static_cast<DummyMidiPort*> (_system_midi_out[(opn % opc)]);
for (std::vector<BackendPortPtr>::const_iterator it = _system_inputs.begin (); it != _system_inputs.end (); ++it, ++opn) {
boost::shared_ptr<DummyMidiPort> op = boost::dynamic_pointer_cast<DummyMidiPort> (_system_midi_out[(opn % opc)]);
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();
}
if (connections_changed || ports_changed) {
update_system_port_latecies ();
update_system_port_latencies ();
engine.latency_callback(false);
engine.latency_callback(true);
}
@ -1622,22 +1616,23 @@ void DummyAudioPort::generate (const pframes_t n_samples)
_gen_cycle = true;
}
void* DummyAudioPort::get_buffer (pframes_t n_samples)
void*
DummyAudioPort::get_buffer (pframes_t n_samples)
{
if (is_input ()) {
const std::set<BackendPort *>& connections = get_connections ();
std::set<BackendPort*>::const_iterator it = connections.begin ();
const std::set<BackendPortPtr>& connections = get_connections ();
std::set<BackendPortPtr>::const_iterator it = connections.begin ();
if (it == connections.end ()) {
memset (_buffer, 0, n_samples * sizeof (Sample));
} else {
DummyAudioPort * source = static_cast<DummyAudioPort*>(*it);
boost::shared_ptr<DummyAudioPort> source = boost::dynamic_pointer_cast<DummyAudioPort>(*it);
assert (source && source->is_output ());
if (source->is_physical() && source->is_terminal()) {
source->get_buffer(n_samples); // generate signal.
}
memcpy (_buffer, source->const_buffer (), n_samples * sizeof (Sample));
while (++it != connections.end ()) {
source = static_cast<DummyAudioPort*>(*it);
source = boost::dynamic_pointer_cast<DummyAudioPort>(*it);
assert (source && source->is_output ());
Sample* dst = buffer ();
if (source->is_physical() && source->is_terminal()) {
@ -1761,11 +1756,11 @@ void* DummyMidiPort::get_buffer (pframes_t n_samples)
{
if (is_input ()) {
_buffer.clear ();
const std::set<BackendPort*>& connections = get_connections ();
for (std::set<BackendPort*>::const_iterator i = connections.begin ();
const std::set<BackendPortPtr>& connections = get_connections ();
for (std::set<BackendPortPtr>::const_iterator i = connections.begin ();
i != connections.end ();
++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()) {
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); }
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); }
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 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); }
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); }
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); }
@ -403,8 +403,6 @@ class DummyAudioBackend : public AudioBackend, public PortEngineSharedImpl {
/* port engine */
int register_system_ports ();
void update_system_port_latecies ();
struct PortConnectData {
std::string a;

View File

@ -1086,7 +1086,8 @@ JACKAudioBackend::n_physical (unsigned long flags) const
if (ports) {
for (uint32_t i = 0; ports[i]; ++i) {
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) {
c.set (t, c.get (t) + 1);
}

View File

@ -39,6 +39,16 @@ namespace ARDOUR {
class JackConnection;
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 {
public:
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&);
std::string get_port_name (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 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;
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);
bool connected (PortHandle, bool process_callback_safe);
@ -310,4 +320,3 @@ class JACKAudioBackend : public AudioBackend {
} // namespace
#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
jack_client_t* client = _jack_connection->jack();
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 {
return -1;
}
#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
}
string
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
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
@ -138,8 +138,8 @@ JACKAudioBackend::get_port_property (PortHandle port, const std::string& key, st
char *cvalue = NULL;
char *ctype = NULL;
jack_uuid_t uuid = jack_port_uuid((jack_port_t*) port);
rv = jack_get_property(uuid, key.c_str(), &cvalue, &ctype);
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);
if (0 == rv && 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.
int rv = -1;
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 rv;
#else
@ -172,11 +172,11 @@ JACKAudioBackend::set_port_property (PortHandle port, const std::string& key, co
#endif
}
PortEngine::PortHandle
PortEngine::PortPtr
JACKAudioBackend:: get_port_by_name (const std::string& name) const
{
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
@ -213,17 +213,17 @@ JACKAudioBackend::connect_callback (jack_port_id_t id_a, jack_port_id_t id_b, in
}
bool
JACKAudioBackend::connected (PortHandle port, bool process_callback_safe)
JACKAudioBackend::connected (PortHandle p, bool process_callback_safe)
{
bool ret = false;
jack_port_t* port = boost::dynamic_pointer_cast<JackPort>(p)->jack_ptr;
const char** ports;
if (process_callback_safe) {
ports = jack_port_get_connections ((jack_port_t*)port);
ports = jack_port_get_connections (port);
} else {
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) {
@ -236,16 +236,17 @@ JACKAudioBackend::connected (PortHandle port, bool process_callback_safe)
}
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;
const char** ports;
jack_port_t* port = boost::dynamic_pointer_cast<JackPort>(p)->jack_ptr;
if (process_callback_safe) {
ports = jack_port_get_connections ((jack_port_t*)port);
ports = jack_port_get_connections (port);
} else {
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) {
@ -264,7 +265,7 @@ bool
JACKAudioBackend::physically_connected (PortHandle p, bool process_callback_safe)
{
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;
@ -295,7 +296,7 @@ bool
JACKAudioBackend::externally_connected (PortHandle p, bool process_callback_safe)
{
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;
@ -325,15 +326,16 @@ JACKAudioBackend::externally_connected (PortHandle p, bool process_callback_safe
}
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;
jack_port_t* port = boost::dynamic_pointer_cast<JackPort>(p)->jack_ptr;
if (process_callback_safe) {
ports = jack_port_get_connections ((jack_port_t*)port);
ports = jack_port_get_connections (port);
} else {
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) {
@ -347,9 +349,9 @@ JACKAudioBackend::get_connections (PortHandle port, vector<string>& s, bool proc
}
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&
@ -359,13 +361,13 @@ JACKAudioBackend::my_name() const
}
bool
JACKAudioBackend::port_is_physical (PortHandle ph) const
JACKAudioBackend::port_is_physical (PortHandle port) const
{
if (!ph) {
if (!port) {
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
@ -461,41 +463,46 @@ JACKAudioBackend::can_monitor_input () const
int
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
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
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)
{
GET_PRIVATE_JACK_POINTER_RET (_priv_jack, 0);
return jack_port_register (_priv_jack, shortname.c_str(),
ardour_data_type_to_jack_port_type (type),
ardour_port_flags_to_jack_flags (flags),
0);
jack_port_t* p = jack_port_register (_priv_jack, shortname.c_str(),
ardour_data_type_to_jack_port_type (type),
ardour_port_flags_to_jack_flags (flags),
0);
if (!p) {
return PortEngine::PortPtr();
}
return boost::shared_ptr<ProtoPort> (new JackPort (p));
}
void
JACKAudioBackend::unregister_port (PortHandle port)
{
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
JACKAudioBackend::connect (PortHandle port, const std::string& other)
{
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
JACKAudioBackend::connect (const std::string& src, const std::string& dst)
@ -510,7 +517,7 @@ int
JACKAudioBackend::disconnect (PortHandle port, const std::string& other)
{
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
@ -524,7 +531,7 @@ int
JACKAudioBackend::disconnect_all (PortHandle port)
{
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
@ -568,7 +575,7 @@ JACKAudioBackend::set_latency_range (PortHandle port, bool for_playback, Latency
range.min = r.min;
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
@ -577,7 +584,7 @@ JACKAudioBackend::get_latency_range (PortHandle port, bool for_playback)
jack_latency_range_t range;
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.max = range.max;
@ -588,7 +595,7 @@ JACKAudioBackend::get_latency_range (PortHandle port, bool for_playback)
void*
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

View File

@ -1303,24 +1303,6 @@ PortAudioBackend::register_system_midi_ports()
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*
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();
}
if (connections_changed || ports_changed) {
update_system_port_latecies ();
update_system_port_latencies ();
engine.latency_callback(false);
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); }
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); }
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 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); }
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); }
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); }
@ -371,7 +371,6 @@ class PortAudioBackend : public AudioBackend, public PortEngineSharedImpl {
int register_system_audio_ports ();
int register_system_midi_ports ();
void update_system_port_latecies ();
struct PortConnectData {
std::string a;

View File

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