new port design, probably about 90% done (i.e it mostly works and this commit is to stop anyone else from stomping on my changes :)

git-svn-id: svn://localhost/ardour2/trunk@2579 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
Paul Davis 2007-10-31 18:24:43 +00:00
parent 1b0f6b1d69
commit 8ab17e9631
28 changed files with 966 additions and 420 deletions

View File

@ -1815,6 +1815,8 @@ ARDOUR_UI::name_io_setup (AudioEngine& engine,
IO& io,
bool in)
{
vector<string> connections;
if (in) {
if (io.n_inputs().n_total() == 0) {
buf = _("none");
@ -1823,16 +1825,12 @@ ARDOUR_UI::name_io_setup (AudioEngine& engine,
/* XXX we're not handling multiple ports yet. */
const char **connections = io.input(0)->get_connections();
if (connections == 0 || connections[0] == '\0') {
if (io.input(0)->get_connections(connections) == 0) {
buf = _("off");
} else {
buf = connections[0];
buf = connections.front();
}
free (connections);
} else {
if (io.n_outputs().n_total() == 0) {
@ -1842,15 +1840,11 @@ ARDOUR_UI::name_io_setup (AudioEngine& engine,
/* XXX we're not handling multiple ports yet. */
const char **connections = io.output(0)->get_connections();
if (connections == 0 || connections[0] == '\0') {
if (io.output(0)->get_connections(connections) == 0) {
buf = _("off");
} else {
buf = connections[0];
buf = connections.front();
}
free (connections);
}
}

View File

@ -79,14 +79,22 @@ IOSelector::set_state (int r, std::string const & p, bool s)
bool
IOSelector::get_state (int r, std::string const & p) const
{
const char **connections = _offer_inputs ? _io->output(r)->get_connections() : _io->input(r)->get_connections();
vector<string> connections;
if (_offer_inputs) {
_io->output(r)->get_connections (connections);
} else {
_io->input(r)->get_connections (connections);
}
int k = 0;
while (connections && connections[k]) {
if (std::string (connections[k]) == p) {
for (vector<string>::iterator i = connections.begin(); i != connections.end(); ++i) {
if ((*i)== p) {
return true;
}
++k;
}

View File

@ -45,6 +45,8 @@ automatable.cc
automation.cc
automation_control.cc
automation_event.cc
base_audio_port.cc
base_midi_port.cc
buffer.cc
buffer_set.cc
chan_count.cc
@ -66,8 +68,6 @@ gain.cc
gdither.cc
globals.cc
import.cc
internal_port.cc
internal_audio_port.cc
io.cc
io_processor.cc
jack_port.cc

View File

@ -23,8 +23,6 @@
namespace ARDOUR {
/** Buffer containing 32-bit floating point (audio) data. */
class AudioBuffer : public Buffer
{
public:
@ -32,8 +30,7 @@ public:
~AudioBuffer();
void silence(nframes_t len, nframes_t offset=0)
{
void silence(nframes_t len, nframes_t offset = 0) {
if (!_silent) {
assert(_capacity > 0);
assert(offset + len <= _capacity);
@ -45,8 +42,7 @@ public:
}
/** Read @a len frames FROM THE START OF @a src into self at @a offset */
void read_from(const Buffer& src, nframes_t len, nframes_t offset)
{
void read_from(const Buffer& src, nframes_t len, nframes_t offset) {
assert(_capacity > 0);
assert(src.type() == DataType::AUDIO);
assert(offset + len <= _capacity);
@ -55,8 +51,7 @@ public:
}
/** Accumulate (add)@a len frames FROM THE START OF @a src into self at @a offset */
void accumulate_from(const AudioBuffer& src, nframes_t len, nframes_t offset)
{
void accumulate_from(const AudioBuffer& src, nframes_t len, nframes_t offset) {
assert(_capacity > 0);
assert(offset + len <= _capacity);
@ -70,8 +65,7 @@ public:
/** Accumulate (add) @a len frames FROM THE START OF @a src into self at @a offset
* scaling by @a gain_coeff */
void accumulate_with_gain_from(const AudioBuffer& src, nframes_t len, nframes_t offset, gain_t gain_coeff)
{
void accumulate_with_gain_from(const AudioBuffer& src, nframes_t len, nframes_t offset, gain_t gain_coeff) {
assert(_capacity > 0);
assert(offset + len <= _capacity);
@ -91,8 +85,7 @@ public:
*
* Constructor MUST have been passed capacity=0 or this will die (to prevent mem leaks).
*/
void set_data(Sample* data, size_t size)
{
void set_data (Sample* data, size_t size) {
assert(!_owns_data); // prevent leaks
_capacity = size;
_size = size;

View File

@ -21,69 +21,24 @@
#ifndef __ardour_audio_port_h__
#define __ardour_audio_port_h__
#include <sigc++/signal.h>
#include <pbd/failed_constructor.h>
#include <ardour/ardour.h>
#include <ardour/port.h>
#include <ardour/audio_buffer.h>
#include <ardour/base_audio_port.h>
namespace ARDOUR {
class AudioEngine;
class AudioPort : public BaseAudioPort, public PortFacade {
class AudioPort : public virtual Port {
public:
virtual Buffer& get_buffer () {
return _buffer;
}
~AudioPort();
void reset ();
void cycle_start (nframes_t nframes, nframes_t offset);
void cycle_end (nframes_t nframes, nframes_t offset);
virtual AudioBuffer& get_audio_buffer() {
return _buffer;
}
void reset_overs () {
_short_overs = 0;
_long_overs = 0;
_overlen = 0;
}
void reset_peak_meter () {
_peak = 0;
}
void reset_meters () {
reset_peak_meter ();
reset_overs ();
}
float peak_db() const { return _peak_db; }
Sample peak() const { return _peak; }
uint32_t short_overs () const { return _short_overs; }
uint32_t long_overs () const { return _long_overs; }
static void set_short_over_length (nframes_t);
static void set_long_over_length (nframes_t);
protected:
friend class AudioEngine;
AudioPort (Flags); // data buffer comes from elsewhere (e.g. JACK)
AudioPort (Flags, nframes_t); // data buffer owned by ardour
void reset ();
/* engine isn't supposed to access below here */
AudioBuffer _buffer;
nframes_t _overlen;
Sample _peak;
float _peak_db;
uint32_t _short_overs;
uint32_t _long_overs;
static nframes_t _long_over_length;
static nframes_t _short_over_length;
AudioPort (const std::string&, Flags, bool external, nframes_t);
};
} // namespace ARDOUR

View File

@ -114,8 +114,8 @@ class AudioEngine : public sigc::trackable
virtual const char *what() const throw() { return "could not connect to engine backend"; }
};
Port *register_input_port (PortType, DataType, const std::string& portname);
Port *register_output_port (PortType, DataType, const std::string& portname);
Port *register_input_port (DataType, const std::string& portname, bool publish);
Port *register_output_port (DataType, const std::string& portname, bool publish);
int unregister_port (Port &);
int connect (const std::string& source, const std::string& destination);
@ -220,12 +220,12 @@ class AudioEngine : public sigc::trackable
SerializedRCUManager<Ports> ports;
Port *register_port (PortType ptype, DataType type, const std::string& portname, bool input);
Port *register_port (DataType type, const std::string& portname, bool input, bool publish);
int process_callback (nframes_t nframes);
void remove_all_ports ();
InternalPort* get_internal_port (const std::string& short_name);
Port* get_port (const std::string& short_name);
typedef std::pair<std::string,std::string> PortConnection;
typedef std::list<PortConnection> PortConnections;

View File

@ -78,7 +78,8 @@ class IO : public Automatable, public Latent
IO (Session&, const string& name,
int input_min = -1, int input_max = -1,
int output_min = -1, int output_max = -1,
DataType default_type = DataType::AUDIO);
DataType default_type = DataType::AUDIO,
bool public_ports = true);
IO (Session&, const XMLNode&, DataType default_type = DataType::AUDIO);
@ -270,7 +271,7 @@ class IO : public Automatable, public Latent
gain_t _gain;
gain_t _effective_gain;
gain_t _desired_gain;
Glib::Mutex declick_lock;
Glib::Mutex declick_lock;
PortSet _outputs;
PortSet _inputs;
PeakMeter* _meter;
@ -279,7 +280,8 @@ class IO : public Automatable, public Latent
bool _denormal_protection;
XMLNode* deferred_state;
DataType _default_type;
bool _public_ports;
virtual void set_deferred_state() {}
void reset_panner ();

View File

@ -30,18 +30,20 @@
namespace ARDOUR {
class AudioEngine;
class JackAudioPort : public AudioPort, public JackPort {
class JackAudioPort : public JackPort, public BaseAudioPort {
public:
void cycle_start(nframes_t nframes) {
_buffer.set_data ((Sample*) jack_port_get_buffer (_port, nframes), nframes);
void cycle_start (nframes_t nframes, nframes_t offset) {
_buffer->set_data ((Sample*) jack_port_get_buffer (_port, nframes) + offset, nframes);
}
int reestablish ();
protected:
friend class AudioEngine;
friend class AudioPort;
JackAudioPort (const std::string& name, Flags flags);
JackAudioPort (const std::string& name, Flags flags, AudioBuffer* buf);
AudioBuffer* _source_buffer;
};
} // namespace ARDOUR

View File

@ -28,24 +28,23 @@
#include <jack/midiport.h>
#include <ardour/port.h>
#include <ardour/jack_port.h>
#include <ardour/midi_port.h>
#include <ardour/base_midi_port.h>
#include <ardour/midi_buffer.h>
namespace ARDOUR {
class MidiEngine;
class JackMidiPort : public JackPort, public MidiPort {
class JackMidiPort : public JackPort, public BaseMidiPort {
public:
void cycle_start(nframes_t nframes);
void cycle_end();
void cycle_start (nframes_t nframes, nframes_t offset);
void cycle_end (nframes_t nframes, nframes_t offset);
void set_buffer (MidiBuffer& buf);
protected:
friend class AudioEngine;
friend class MidiPort;
JackMidiPort (const std::string&, Flags);
nframes_t _nframes_this_cycle;
JackMidiPort (const std::string&, Flags, MidiBuffer*);
};
} // namespace ARDOUR

View File

@ -32,30 +32,44 @@ class Buffer;
/** Abstract class representing JACK ports
*/
class JackPort : public virtual Port {
class JackPort : public virtual Port, public PortConnectableByName {
public:
~JackPort();
std::string short_name() {
std::string short_name() const {
return jack_port_short_name (_port);
}
int set_name (std::string str);
int set_name (const std::string& str);
int connected () const {
bool connected () const {
return jack_port_connected (_port);
}
int reestablish ();
int reconnect ();
int connect (Port& other) {
return connect (other.name());
}
int disconnect (Port& other) {
return disconnect (other.name());
}
int disconnect_all ();
// connect-by-name API
int connect (const std::string& other_name);
int disconnect (const std::string& other_name);
bool connected_to (const std::string& portname) const {
return jack_port_connected_to (_port, portname.c_str());
}
const char ** get_connections () const {
return jack_port_get_connections (_port);
}
int get_connections (std::vector<std::string>& names) const;
bool monitoring_input () const {
return jack_port_monitoring_input (_port);
@ -90,8 +104,7 @@ class JackPort : public virtual Port {
int disconnect ();
void recompute_total_latency() const;
static void set_engine (AudioEngine*);
static AudioEngine* engine;
std::set<std::string> _named_connections;
};
} // namespace ARDOUR

View File

@ -44,7 +44,7 @@ public:
Byte* reserve(double time, size_t size);
void resize(size_t);
bool merge(const MidiBuffer& a, const MidiBuffer& b);
struct iterator {

View File

@ -21,39 +21,24 @@
#ifndef __ardour_midi_port_h__
#define __ardour_midi_port_h__
#include <sigc++/signal.h>
#include <pbd/failed_constructor.h>
#include <ardour/ardour.h>
#include <ardour/port.h>
#include <ardour/midi_buffer.h>
#include <ardour/base_midi_port.h>
namespace ARDOUR {
class MidiEngine;
class MidiPort : public virtual Port {
class MidiPort : public BaseMidiPort, public PortFacade {
public:
virtual ~MidiPort();
Buffer& get_buffer() {
return _buffer;
}
~MidiPort();
MidiBuffer& get_midi_buffer() {
return _buffer;
}
size_t capacity() { return _buffer.capacity(); }
size_t size() { return _buffer.size(); }
void reset ();
void cycle_start (nframes_t nframes, nframes_t offset);
protected:
friend class AudioEngine;
MidiPort (Flags, nframes_t bufsize);
/* engine isn't supposed to access below here */
MidiBuffer _buffer;
MidiPort (const std::string& name, Flags, bool external, nframes_t bufsize);
};
} // namespace ARDOUR

View File

@ -20,6 +20,10 @@
#ifndef __ardour_port_h__
#define __ardour_port_h__
#include <set>
#include <vector>
#include <string>
#include <sigc++/signal.h>
#include <pbd/failed_constructor.h>
#include <ardour/ardour.h>
@ -43,13 +47,12 @@ class Port : public virtual sigc::trackable {
CanMonitor = JackPortCanMonitor
};
virtual ~Port() {}
virtual ~Port();
std::string name() const {
return _name;
}
Flags flags() const {
return _flags;
}
@ -59,7 +62,7 @@ class Port : public virtual sigc::trackable {
}
bool sends_output () const {
return _flags & JackPortIsOutput;
return _flags & IsOutput;
}
bool can_monitor () const {
@ -73,18 +76,30 @@ class Port : public virtual sigc::trackable {
void disable_metering () {
if (_metering) { _metering--; }
}
DataType type() const { return _type; }
virtual void cycle_start(nframes_t nframes) {}
virtual void cycle_end() {}
virtual void cycle_start (nframes_t nframes, nframes_t offset) {}
virtual void cycle_end (nframes_t nframes, nframes_t offset) {}
virtual DataType type() const = 0;
virtual Buffer& get_buffer() = 0;
virtual std::string short_name() = 0;
virtual int set_name (std::string str) = 0;
virtual int reestablish () = 0;
virtual int connected () const = 0;
virtual bool connected_to (const std::string& portname) const = 0;
virtual const char ** get_connections () const = 0;
virtual bool connected () const;
virtual bool connected_to (const std::string& portname) const;
virtual int get_connections (std::vector<std::string>&) const;
virtual int connect (Port& other);
virtual int disconnect (Port& other);
virtual int disconnect_all ();
virtual void reset ();
virtual int reestablish () {return 0; }
virtual int reconnect () { return 0; }
virtual int set_name (const std::string& str) {
_name = str;
return 0;
}
virtual std::string short_name() const = 0;
virtual bool monitoring_input () const = 0;
virtual void ensure_monitor_input (bool yn) = 0;
virtual void request_monitor_input (bool yn) = 0;
@ -95,24 +110,71 @@ class Port : public virtual sigc::trackable {
sigc::signal<void,bool> MonitorInputChanged;
sigc::signal<void,bool> ClockSyncChanged;
static void set_engine (AudioEngine*);
protected:
friend class AudioEngine;
Port (DataType, Flags);
Port (const std::string& name, Flags flgs);
virtual int disconnect () = 0;
virtual void recompute_total_latency() const = 0;
virtual void reset ();
virtual void recompute_total_latency() const {}
/* engine isn't supposed to access below here */
Flags _flags;
const DataType _type;
std::string _type;
std::string _name;
unsigned short _metering;
bool _last_monitor;
nframes_t _latency;
std::set<Port*> _connections;
static AudioEngine* engine;
};
class PortConnectableByName {
public:
PortConnectableByName() {}
virtual ~PortConnectableByName() {}
virtual int connect (const std::string& other_name) = 0;
virtual int disconnect (const std::string& other_name) = 0;
};
class PortFacade : public virtual Port, public PortConnectableByName {
public:
PortFacade (const std::string& name, Flags flgs) : Port (name, flgs), _ext_port (0) {}
~PortFacade() {}
void reset ();
int reestablish ();
int reconnect ();
int connect (Port& other);
int disconnect (Port& other);
int disconnect_all ();
int connect (const std::string& other_name);
int disconnect (const std::string& other_name);
bool connected () const;
bool connected_to (const std::string& portname) const;
int get_connections (std::vector<std::string>&) const;
std::string short_name() const;
int set_name (const std::string& str);
bool monitoring_input () const;
void ensure_monitor_input (bool yn);
void request_monitor_input (bool yn);
nframes_t latency () const;
nframes_t total_latency () const;
void set_latency (nframes_t nframes);
protected:
Port* _ext_port;
};
} // namespace ARDOUR
#endif /* __ardour_port_h__ */

View File

@ -379,11 +379,6 @@ namespace ARDOUR {
SrcFastest
};
enum PortType {
Jack,
Internal
};
} // namespace ARDOUR
std::istream& operator>>(std::istream& o, ARDOUR::SampleFormat& sf);

View File

@ -48,9 +48,7 @@ AudioBuffer::~AudioBuffer()
void
AudioBuffer::resize (size_t size)
{
assert (_owns_data);
if (size < _capacity) {
if (!_owns_data || (size < _capacity)) {
return;
}

View File

@ -212,13 +212,14 @@ AudioDiskstream::get_input_sources ()
uint32_t n;
ChannelList::iterator chan;
uint32_t ni = _io->n_inputs().n_audio();
vector<string> connections;
for (n = 0, chan = c->begin(); chan != c->end() && n < ni; ++chan, ++n) {
const char **connections = _io->input(n)->get_connections ();
connections.clear ();
if (_io->input(n)->get_connections (connections) == 0) {
if (connections == 0 || connections[0] == 0) {
if ((*chan)->source) {
// _source->disable_metering ();
}
@ -226,12 +227,7 @@ AudioDiskstream::get_input_sources ()
(*chan)->source = 0;
} else {
(*chan)->source = dynamic_cast<AudioPort*>(
_session.engine().get_port_by_name (connections[0]) );
}
if (connections) {
free (connections);
(*chan)->source = dynamic_cast<AudioPort*>(_session.engine().get_port_by_name (connections[0]) );
}
}
}

View File

@ -18,39 +18,108 @@
#include <cassert>
#include <ardour/audio_port.h>
#include <ardour/jack_audio_port.h>
#include <ardour/audioengine.h>
#include <ardour/data_type.h>
using namespace ARDOUR;
using namespace std;
nframes_t AudioPort::_short_over_length = 2;
nframes_t AudioPort::_long_over_length = 10;
AudioPort::AudioPort(Flags flags)
: Port (DataType::AUDIO, flags), _buffer (0)
AudioPort::AudioPort (const std::string& name, Flags flgs, bool external, nframes_t capacity)
: Port (name, flgs)
, BaseAudioPort (name, flgs)
, PortFacade (name, flgs)
{
reset();
if (!external || receives_input()) {
/* internal-only and input ports need their own buffers.
external output ports use the external port buffer.
*/
_buffer = new AudioBuffer (capacity);
_own_buffer = true;
}
if (!external) {
_ext_port = 0;
} else {
/* make the JackAudioPort create its own buffer. For input,
we will copy from it during cycle_start(). For output,
we will set up our buffer to point to its buffer, which
will in turn be using the JACK port buffer for data.
*/
_ext_port = new JackAudioPort (name, flgs, 0);
if (sends_output()) {
_buffer = &dynamic_cast<JackAudioPort*>(_ext_port)->get_audio_buffer();
}
Port::set_name (_ext_port->name());
}
reset ();
}
AudioPort::AudioPort(Flags flags, nframes_t nframes)
: Port (DataType::AUDIO, flags), _buffer (nframes)
AudioPort::~AudioPort()
{
reset();
if (_ext_port) {
delete _ext_port;
_ext_port = 0;
}
}
void
AudioPort::reset()
{
Port::reset();
if (_flags & IsOutput) {
if (_buffer.capacity() > 0) {
_buffer.clear();
}
assert(_buffer.silent());
BaseAudioPort::reset();
if (_ext_port) {
_ext_port->reset ();
}
_metering = 0;
reset_meters ();
}
void
AudioPort::cycle_start (nframes_t nframes, nframes_t offset)
{
/* caller must hold process lock */
if (_ext_port) {
_ext_port->cycle_start (nframes, offset);
}
if (_flags & IsInput) {
if (_ext_port) {
_buffer->read_from (dynamic_cast<BaseAudioPort*>(_ext_port)->get_audio_buffer(), nframes, offset);
if (!_connections.empty()) {
(*_mixdown) (_connections, _buffer, nframes, offset, false);
}
} else {
if (_connections.empty()) {
_buffer->silence (nframes, offset);
} else {
(*_mixdown) (_connections, _buffer, nframes, offset, true);
}
}
} else {
// XXX if we could get the output stage to not purely mix into, but also
// to initially overwrite the buffer, we could avoid this silence step.
_buffer->silence (nframes, offset);
}
}
void
AudioPort::cycle_end (nframes_t nframes, nframes_t offset)
{
}

View File

@ -32,8 +32,8 @@
#include <ardour/buffer.h>
#include <ardour/port.h>
#include <ardour/jack_audio_port.h>
#include <ardour/internal_audio_port.h>
#include <ardour/jack_midi_port.h>
#include <ardour/audio_port.h>
#include <ardour/session.h>
#include <ardour/cycle_timer.h>
#include <ardour/utils.h>
@ -84,7 +84,7 @@ AudioEngine::AudioEngine (string client_name)
start_metering_thread();
JackPort::set_engine (this);
Port::set_engine (this);
}
AudioEngine::~AudioEngine ()
@ -330,7 +330,7 @@ AudioEngine::process_callback (nframes_t nframes)
// Prepare ports (ie read data if necessary)
for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
(*i)->cycle_start (nframes);
(*i)->cycle_start (nframes, 0);
}
if (session) {
@ -343,8 +343,9 @@ AudioEngine::process_callback (nframes_t nframes)
}
// Finalize ports (ie write data if necessary)
for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
(*i)->cycle_end ();
(*i)->cycle_end (nframes, 0);
}
if (last_monitor_check + monitor_check_interval < next_processed_frames) {
@ -471,8 +472,9 @@ AudioEngine::set_session (Session *s)
boost::shared_ptr<Ports> p = ports.reader();
for (Ports::iterator i = p->begin(); i != p->end(); ++i)
(*i)->cycle_start (blocksize);
for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
(*i)->cycle_start (blocksize, 0);
}
s->process (blocksize);
s->process (blocksize);
@ -483,9 +485,9 @@ AudioEngine::set_session (Session *s)
s->process (blocksize);
s->process (blocksize);
for (Ports::iterator i = p->begin(); i != p->end(); ++i)
(*i)->cycle_end ();
for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
(*i)->cycle_end (blocksize, 0);
}
}
}
@ -509,41 +511,24 @@ AudioEngine::remove_session ()
}
Port *
AudioEngine::register_port (PortType ptype, DataType dtype, const string& portname, bool input)
AudioEngine::register_port (DataType dtype, const string& portname, bool input, bool publish)
{
Port* newport = 0;
try {
switch (ptype) {
case Jack:
if (dtype == DataType::AUDIO) {
newport = new JackAudioPort (portname, (input ? Port::IsInput : Port::IsOutput));
} else if (dtype == DataType::MIDI) {
newport = new JackMidiPort (portname, (input ? Port::IsInput : Port::IsOutput));
} else {
throw unknown_type();
}
break;
if (dtype == DataType::AUDIO) {
newport = new AudioPort (portname, (input ? Port::IsInput : Port::IsOutput), publish, frames_per_cycle());
} else if (dtype == DataType::MIDI) {
newport = new MidiPort (portname, (input ? Port::IsInput : Port::IsOutput), publish, frames_per_cycle());
} else {
throw unknown_type();
}
RCUWriter<Ports> writer (ports);
boost::shared_ptr<Ports> ps = writer.get_copy ();
ps->insert (ps->begin(), newport);
/* writer goes out of scope, forces update */
case Internal:
if (dtype == DataType::AUDIO) {
newport = new InternalAudioPort (portname, (input ? Port::IsInput : Port::IsOutput));
} else if (dtype == DataType::MIDI) {
error << _("Internal MIDI ports are not implemented yet!") << endmsg;
throw unknown_type();
} else {
throw unknown_type();
}
break;
}
if (newport != 0) {
RCUWriter<Ports> writer (ports);
boost::shared_ptr<Ports> ps = writer.get_copy ();
ps->insert (ps->begin(), newport);
/* writer goes out of scope, forces update */
}
return newport;
}
@ -552,14 +537,14 @@ AudioEngine::register_port (PortType ptype, DataType dtype, const string& portna
}
}
InternalPort*
AudioEngine::get_internal_port (const std::string& short_name)
Port*
AudioEngine::get_port (const std::string& full_name)
{
boost::shared_ptr<Ports> p = ports.reader();
for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
if ((*i)->short_name() == short_name) {
return dynamic_cast<InternalPort*> (*i);
if ((*i)->name() == full_name) {
return *i;
}
}
return 0;
@ -567,15 +552,15 @@ AudioEngine::get_internal_port (const std::string& short_name)
Port *
AudioEngine::register_input_port (PortType ptype, DataType type, const string& portname)
AudioEngine::register_input_port (DataType type, const string& portname, bool publish)
{
return register_port (ptype, type, portname, true);
return register_port (type, portname, true, publish);
}
Port *
AudioEngine::register_output_port (PortType ptype, DataType type, const string& portname)
AudioEngine::register_output_port (DataType type, const string& portname, bool publish)
{
return register_port (ptype, type, portname, false);
return register_port (type, portname, false, publish);
}
int
@ -595,7 +580,6 @@ AudioEngine::unregister_port (Port& port)
for (Ports::iterator i = ps->begin(); i != ps->end(); ++i) {
if ((*i) == &port) {
remove_connections_for (port);
delete *i;
ps->erase (i);
break;
@ -625,33 +609,53 @@ AudioEngine::connect (const string& source, const string& destination)
string s = make_port_name_non_relative (source);
string d = make_port_name_non_relative (destination);
if (source.substr (0, 9) == "internal:") {
if (destination.substr (0, 9) == "internal:") {
InternalPort* src = get_internal_port (source);
InternalPort* dst = get_internal_port (destination);
Port* src = get_port (s);
Port* dst = get_port (d);
InternalPort::connect (*src, *dst);
ret = 0;
if (src && dst) {
/* both ports are known to us, so do the internal connect stuff */
if ((ret = src->connect (*dst)) == 0) {
ret = dst->connect (*src);
}
} else if (src || dst) {
/* one port is known to us, try to connect it to something external */
PortConnectableByName* pcn;
string other;
if (src) {
pcn = dynamic_cast<PortConnectableByName*>(src);
other = d;
} else {
pcn = dynamic_cast<PortConnectableByName*>(dst);
other = s;
}
if (pcn) {
ret = pcn->connect (other);
} else {
ret = -1;
}
} else {
ret = jack_connect (_jack, s.c_str(), d.c_str());
}
if (ret == 0) {
pair<string,string> c (s, d);
port_connections.push_back (c);
} else if (ret == EEXIST) {
/* neither port is known to us, and this API isn't intended for use as a general patch bay */
ret = -1;
}
if (ret > 0) {
error << string_compose(_("AudioEngine: connection already exists: %1 (%2) to %3 (%4)"),
source, s, destination, d)
source, s, destination, d)
<< endmsg;
} else {
} else if (ret < 0) {
error << string_compose(_("AudioEngine: cannot connect %1 (%2) to %3 (%4)"),
source, s, destination, d)
source, s, destination, d)
<< endmsg;
}
@ -675,31 +679,47 @@ AudioEngine::disconnect (const string& source, const string& destination)
string s = make_port_name_non_relative (source);
string d = make_port_name_non_relative (destination);
if (source.substr (0, 9) == "internal:") {
if (destination.substr (0, 9) == "internal:") {
InternalPort* src = get_internal_port (source);
InternalPort* dst = get_internal_port (destination);
Port* src = get_port (s);
Port* dst = get_port (d);
InternalPort::disconnect (*src, *dst);
ret = 0;
if (src && dst) {
/* both ports are known to us, so do the internal connect stuff */
if ((ret = src->disconnect (*dst)) == 0) {
ret = dst->disconnect (*src);
}
} else if (src || dst) {
/* one port is known to us, try to connect it to something external */
PortConnectableByName* pcn;
string other;
if (src) {
pcn = dynamic_cast<PortConnectableByName*>(src);
other = d;
} else {
pcn = dynamic_cast<PortConnectableByName*>(dst);
other = s;
}
if (pcn) {
ret = pcn->disconnect (other);
} else {
ret = -1;
}
} else {
ret = jack_disconnect (_jack, s.c_str(), d.c_str());
}
if (ret == 0) {
pair<string,string> c (s, d);
PortConnections::iterator i;
/* neither port is known to us, and this API isn't intended for use as a general patch bay */
ret = -1;
if ((i = find (port_connections.begin(), port_connections.end(), c)) != port_connections.end()) {
port_connections.erase (i);
}
}
return ret;
}
@ -715,14 +735,7 @@ AudioEngine::disconnect (Port& port)
}
}
int ret = port.disconnect ();
if (ret == 0) {
remove_connections_for (port);
}
return ret;
return port.disconnect_all ();
}
ARDOUR::nframes_t
@ -1037,26 +1050,8 @@ AudioEngine::remove_all_ports ()
boost::shared_ptr<Ports> ps = writer.get_copy ();
ps->clear ();
}
port_connections.clear ();
}
void
AudioEngine::remove_connections_for (Port& port)
{
for (PortConnections::iterator i = port_connections.begin(); i != port_connections.end(); ) {
PortConnections::iterator tmp;
tmp = i;
++tmp;
if ((*i).first == port.name()) {
port_connections.erase (i);
}
i = tmp;
}
}
#ifdef HAVE_JACK_CLIENT_OPEN
@ -1150,7 +1145,6 @@ AudioEngine::reconnect_to_jack ()
boost::shared_ptr<Ports> p = ports.reader ();
for (i = p->begin(); i != p->end(); ++i) {
if ((*i)->reestablish ()) {
break;
}
@ -1195,17 +1189,8 @@ AudioEngine::reconnect_to_jack ()
/* re-establish connections */
for (PortConnections::iterator i = port_connections.begin(); i != port_connections.end(); ++i) {
int err;
if ((err = jack_connect (_jack, (*i).first.c_str(), (*i).second.c_str())) != 0) {
if (err != EEXIST) {
error << string_compose (_("could not reconnect %1 and %2 (err = %3)"),
(*i).first, (*i).second, err)
<< endmsg;
}
}
for (i = p->begin(); i != p->end(); ++i) {
(*i)->reconnect ();
}
Running (); /* EMIT SIGNAL*/

View File

@ -194,29 +194,27 @@ Auditioner::output_changed (IOChange change, void* src)
string phys;
if (change & ConnectionsChanged) {
const char ** connections;
connections = output (0)->get_connections ();
if (connections) {
vector<string> connections;
if (output (0)->get_connections (connections)) {
phys = _session.engine().get_nth_physical_output (DataType::AUDIO, 0);
if (phys != connections[0]) {
Config->set_auditioner_output_left (connections[0]);
} else {
Config->set_auditioner_output_left ("default");
}
free (connections);
} else {
Config->set_auditioner_output_left ("");
}
connections = output (1)->get_connections ();
if (connections) {
connections.clear ();
if (output (1)->get_connections (connections)) {
phys = _session.engine().get_nth_physical_output (DataType::AUDIO, 1);
if (phys != connections[0]) {
Config->set_auditioner_output_right (connections[0]);
} else {
Config->set_auditioner_output_right ("default");
}
free (connections);
} else {
Config->set_auditioner_output_right ("");
}

View File

@ -99,10 +99,11 @@ static double direct_gain_to_control (gain_t gain) {
*/
IO::IO (Session& s, const string& name,
int input_min, int input_max, int output_min, int output_max,
DataType default_type)
DataType default_type, bool public_ports)
: Automatable (s, name),
_output_buffers (new BufferSet()),
_output_buffers (new BufferSet()),
_default_type (default_type),
_public_ports (public_ports),
_input_minimum (ChanCount::ZERO),
_input_maximum (ChanCount::INFINITE),
_output_minimum (ChanCount::ZERO),
@ -162,7 +163,7 @@ IO::IO (Session& s, const XMLNode& node, DataType dt)
_default_type (dt)
{
_meter = new PeakMeter (_session);
_public_ports = true; // XXX get this from node
_panner = 0;
deferred_state = 0;
no_panner_reset = false;
@ -229,7 +230,7 @@ IO::silence (nframes_t nframes, nframes_t offset)
}
}
/** Deliver bufs to the IO's Jack outputs.
/** Deliver bufs to the IO's output ports
*
* This function should automatically do whatever it necessary to correctly deliver bufs
* to the outputs, eg applying gain or pan or whatever else needs to be done.
@ -636,7 +637,7 @@ IO::add_output_port (string destination, void* src, DataType type)
snprintf (name, sizeof (name), _("%s/out %u"), _name.c_str(), find_output_port_hole());
}
if ((our_port = _session.engine().register_output_port (Jack, type, name)) == 0) {
if ((our_port = _session.engine().register_output_port (type, name, _public_ports)) == 0) {
error << string_compose(_("IO: cannot register output port %1"), name) << endmsg;
return -1;
}
@ -714,7 +715,7 @@ IO::remove_input_port (Port* port, void* src)
/** Add an input port.
*
* @param type Data type of port. The appropriate Jack port type, and @ref Port will be created.
* @param type Data type of port. The appropriate port type, and @ref Port will be created.
* @param destination Name of input port to connect new port to.
* @param src Source for emitted ConfigurationChanged signal.
*/
@ -746,7 +747,7 @@ IO::add_input_port (string source, void* src, DataType type)
snprintf (name, sizeof (name), _("%s/in %u"), _name.c_str(), find_input_port_hole());
}
if ((our_port = _session.engine().register_input_port (Jack, type, name)) == 0) {
if ((our_port = _session.engine().register_input_port (type, name, _public_ports)) == 0) {
error << string_compose(_("IO: cannot register input port %1"), name) << endmsg;
return -1;
}
@ -854,7 +855,7 @@ IO::ensure_inputs_locked (ChanCount count, bool clear, void* src)
try {
if ((input_port = _session.engine().register_input_port (Jack, *t, buf)) == 0) {
if ((input_port = _session.engine().register_input_port (*t, buf, _public_ports)) == 0) {
error << string_compose(_("IO: cannot register input port %1"), buf) << endmsg;
return -1;
}
@ -970,7 +971,7 @@ IO::ensure_io (ChanCount in, ChanCount out, bool clear, void* src)
}
try {
if ((port = _session.engine().register_input_port (Jack, *t, buf)) == 0) {
if ((port = _session.engine().register_input_port (*t, buf, _public_ports)) == 0) {
error << string_compose(_("IO: cannot register input port %1"), buf) << endmsg;
return -1;
}
@ -1002,7 +1003,7 @@ IO::ensure_io (ChanCount in, ChanCount out, bool clear, void* src)
}
try {
if ((port = _session.engine().register_output_port (Jack, *t, buf)) == 0) {
if ((port = _session.engine().register_output_port (*t, buf, _public_ports)) == 0) {
error << string_compose(_("IO: cannot register output port %1"), buf) << endmsg;
return -1;
}
@ -1122,7 +1123,7 @@ IO::ensure_outputs_locked (ChanCount count, bool clear, void* src)
snprintf (buf, sizeof (buf), _("%s/out %u"), _name.c_str(), find_output_port_hole());
}
if ((output_port = _session.engine().register_output_port (Jack, *t, buf)) == 0) {
if ((output_port = _session.engine().register_output_port (*t, buf, _public_ports)) == 0) {
error << string_compose(_("IO: cannot register output port %1"), buf) << endmsg;
return -1;
}
@ -1241,6 +1242,8 @@ IO::state (bool full_state)
XMLNode* node = new XMLNode (state_node_name);
char buf[64];
string str;
vector<string>::iterator ci;
int n;
LocaleGuard lg (X_("POSIX"));
Glib::Mutex::Lock lm (io_lock);
@ -1274,12 +1277,13 @@ IO::state (bool full_state)
for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
const char **connections = i->get_connections();
if (connections && connections[0]) {
vector<string> connections;
if (i->get_connections (connections)) {
str += '{';
for (int n = 0; connections && connections[n]; ++n) {
for (n = 0, ci = connections.begin(); ci != connections.end(); ++ci, ++n) {
if (n) {
str += ',';
}
@ -1291,14 +1295,12 @@ IO::state (bool full_state)
client name is different.
*/
str += _session.engine().make_port_name_relative (connections[n]);
str += _session.engine().make_port_name_relative (*ci);
}
str += '}';
free (connections);
}
else {
} else {
str += "{}";
}
}
@ -1309,25 +1311,23 @@ IO::state (bool full_state)
for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
const char **connections = i->get_connections();
if (connections && connections[0]) {
vector<string> connections;
if (i->get_connections (connections)) {
str += '{';
for (int n = 0; connections[n]; ++n) {
for (n = 0, ci = connections.begin(); ci != connections.end(); ++ci, ++n) {
if (n) {
str += ',';
}
str += _session.engine().make_port_name_relative (connections[n]);
str += _session.engine().make_port_name_relative (*ci);
}
str += '}';
free (connections);
}
else {
} else {
str += "{}";
}
}

View File

@ -22,10 +22,23 @@
using namespace ARDOUR;
JackAudioPort::JackAudioPort(const std::string& name, Flags flgs)
: Port (DataType::AUDIO, flgs), AudioPort (flgs), JackPort (name, DataType::AUDIO, flgs)
JackAudioPort::JackAudioPort (const std::string& name, Flags flgs, AudioBuffer* buf)
: Port (name, flgs)
, JackPort (name, DataType::AUDIO, flgs)
, BaseAudioPort (name, flgs)
{
if (buf) {
_buffer = buf;
_own_buffer = false;
} else {
/* data space will be provided by JACK */
_buffer = new AudioBuffer (0);
_own_buffer = true;
}
}
int
@ -34,8 +47,9 @@ JackAudioPort::reestablish ()
int ret = JackPort::reestablish ();
if (ret == 0 && _flags & IsOutput) {
_buffer.silence (jack_get_buffer_size (engine->jack()));
_buffer->clear ();
}
return ret;
}

View File

@ -20,76 +20,76 @@
#include <ardour/jack_midi_port.h>
using namespace ARDOUR;
JackMidiPort::JackMidiPort (const std::string& name, Flags flgs)
: Port (DataType::MIDI, flgs)
JackMidiPort::JackMidiPort (const std::string& name, Flags flgs, MidiBuffer* buf)
: Port (name, flgs)
, JackPort (name, DataType::MIDI, flgs)
, MidiPort (flgs, 4096) // FIXME FIXME FIXME Jack needs to tell us this
, _nframes_this_cycle(0)
, BaseMidiPort (name, flgs)
{
if (buf) {
_buffer = buf;
_own_buffer = false;
} else {
/* data space will be provided by JACK */
_buffer = new MidiBuffer (0);
_own_buffer = true;
}
}
void
JackMidiPort::cycle_start (nframes_t nframes)
JackMidiPort::cycle_start (nframes_t nframes, nframes_t offset_ignored_but_probably_should_not_be)
{
_buffer.clear();
assert(_buffer.size() == 0);
_buffer->clear();
assert(_buffer->size() == 0);
_nframes_this_cycle = nframes;
if (_flags & JackPortIsOutput) {
_buffer.silence(nframes);
assert(_buffer.size() == 0);
if (_flags & IsOutput) {
// no buffer, nothing to do
return;
}
// We're an input - copy Jack events to internal buffer
void* jack_buffer = jack_port_get_buffer(_port, nframes);
const nframes_t event_count
= jack_midi_get_event_count(jack_buffer);
const nframes_t event_count = jack_midi_get_event_count(jack_buffer);
assert(event_count < _buffer.capacity());
assert(event_count < _buffer->capacity());
jack_midi_event_t ev;
for (nframes_t i=0; i < event_count; ++i) {
jack_midi_event_get(&ev, jack_buffer, i);
jack_midi_event_get (&ev, jack_buffer, i);
_buffer.push_back(ev);
_buffer->push_back (ev);
}
assert(_buffer.size() == event_count);
assert(_buffer->size() == event_count);
//if (_buffer.size() > 0)
//if (_buffer->size() > 0)
// cerr << "MIDIPort got " << event_count << " events." << endl;
}
void
JackMidiPort::cycle_end()
JackMidiPort::cycle_end (nframes_t nframes, nframes_t offset_ignored_but_probably_should_not_be)
{
if (_flags & JackPortIsInput) {
_nframes_this_cycle = 0;
if (_flags & IsInput) {
return;
}
// We're an output - copy events from internal buffer to Jack buffer
// We're an output - copy events from source buffer to Jack buffer
void* jack_buffer = jack_port_get_buffer(_port, _nframes_this_cycle);
void* jack_buffer = jack_port_get_buffer (_port, nframes);
//const nframes_t event_count = _buffer.size();
//if (event_count > 0)
// cerr << "MIDIPort writing " << event_count << " events." << endl;
jack_midi_clear_buffer (jack_buffer);
jack_midi_clear_buffer(jack_buffer);
for (MidiBuffer::iterator i = _buffer.begin(); i != _buffer.end(); ++i) {
for (MidiBuffer::iterator i = _buffer->begin(); i != _buffer->end(); ++i) {
const MidiEvent& ev = *i;
// event times should be frames, relative to cycle start
assert(ev.time() >= 0);
assert(ev.time() < _nframes_this_cycle);
jack_midi_event_write(jack_buffer, (jack_nframes_t)ev.time(), ev.buffer(), ev.size());
assert(ev.time() < nframes);
jack_midi_event_write (jack_buffer, (jack_nframes_t) ev.time(), ev.buffer(), ev.size());
}
_nframes_this_cycle = 0;
}

View File

@ -28,10 +28,8 @@ using namespace ARDOUR;
using namespace PBD;
using namespace std;
AudioEngine* JackPort::engine = 0;
JackPort::JackPort (const std::string& name, DataType type, Flags flgs)
: Port (type, flgs), _port (0)
: Port (name, flgs), _port (0)
{
_port = jack_port_register (engine->jack(), name.c_str(), type.to_jack_type(), flgs, 0);
@ -39,6 +37,8 @@ JackPort::JackPort (const std::string& name, DataType type, Flags flgs)
throw failed_constructor();
}
_flags = flgs;
_type = type;
_name = jack_port_name (_port);
}
@ -50,7 +50,7 @@ JackPort::~JackPort ()
}
int
JackPort::set_name (string str)
JackPort::set_name (const string& str)
{
int ret;
@ -67,12 +67,6 @@ JackPort::disconnect ()
return jack_port_disconnect (engine->jack(), _port);
}
void
JackPort::set_engine (AudioEngine* e)
{
engine = e;
}
nframes_t
JackPort::total_latency () const
{
@ -107,4 +101,79 @@ JackPort::recompute_total_latency () const
#endif
}
int
JackPort::reconnect ()
{
/* caller must hold process lock; intended to be used only after reestablish() */
for (set<string>::iterator i = _named_connections.begin(); i != _named_connections.end(); ++i) {
if (connect (*i)) {
return -1;
}
}
return 0;
}
int
JackPort::connect (const std::string& other)
{
int ret;
if (_flags & IsOutput) {
/* this is the source */
ret = jack_connect (engine->jack(), _name.c_str(), other.c_str());
} else {
ret = jack_connect (engine->jack(), other.c_str(), _name.c_str());
}
if (ret == 0) {
_named_connections.insert (other);
}
return ret;
}
int
JackPort::disconnect (const std::string& other)
{
int ret;
if (_flags & IsInput) {
ret = jack_disconnect (engine->jack(), _name.c_str(), other.c_str());
} else {
ret = jack_disconnect (engine->jack(), other.c_str(), _name.c_str());
}
set<string>::iterator i = _named_connections.find (other);
if (i != _named_connections.end()) {
_named_connections.erase (i);
}
return ret;
}
int
JackPort::disconnect_all ()
{
_named_connections.clear ();
return jack_port_disconnect (engine->jack(), _port);
}
int
JackPort::get_connections (vector<string>& names) const
{
const char** cstrs = jack_port_get_connections (_port);
int i;
if (!cstrs) {
return 0;
}
for (i = 0; cstrs[i]; ++i) {
names.push_back (string (cstrs[i]));
}
return i;
}

View File

@ -27,20 +27,30 @@ static const int CPU_CACHE_ALIGN = 16; /* arguably 32 on most arches, but it mat
#endif
using namespace std;
namespace ARDOUR {
using namespace ARDOUR;
// FIXME: mirroring for MIDI buffers?
MidiBuffer::MidiBuffer(size_t capacity)
: Buffer(DataType::MIDI, capacity)
// , _owns_data(true)
, _events(NULL)
, _data(NULL)
, _events(0)
, _data(0)
// , _owns_data(false)
{
_data = 0;
resize (_capacity);
silence(_capacity);
if (capacity) {
resize (_capacity);
silence(_capacity);
}
}
MidiBuffer::~MidiBuffer()
{
if (_events) {
free(_events);
}
if (_data) {
free(_data);
}
}
void
@ -48,12 +58,21 @@ MidiBuffer::resize (size_t size)
{
assert(size > 0);
if (size < _capacity) {
return;
}
if (_data) {
free (_data);
}
if (_events) {
free (_events);
}
_size = 0;
_capacity = size;
#ifdef NO_POSIX_MEMALIGN
_events = (MidiEvent *) malloc(sizeof(MidiEvent) * _capacity);
_data = (Byte *) malloc(sizeof(Byte) * _capacity * MAX_EVENT_SIZE);
@ -71,16 +90,10 @@ MidiBuffer::copy(const MidiBuffer& copy)
assert(_capacity >= copy._capacity);
_size = 0;
for (size_t i=0; i < copy.size(); ++i)
for (size_t i = 0; i < copy.size(); ++i)
push_back(copy[i]);
}
MidiBuffer::~MidiBuffer()
{
free(_events);
free(_data);
}
/** Read events from @a src starting at time @a offset into the START of this buffer, for
* time direction @a nframes. Relative time, where 0 = start of buffer.
@ -173,7 +186,7 @@ MidiBuffer::push_back(const jack_midi_event_t& ev)
/** Reserve space for a new event in the buffer.
*
* This call is for copying MIDI directly into the buffer, the data location
* (of sufficient size to write \a size bytes) is returned, or NULL on failure.
* (of sufficient size to write \a size bytes) is returned, or 0 on failure.
* This call MUST be immediately followed by a write to the returned data
* location, or the buffer will be corrupted and very nasty things will happen.
*/
@ -183,7 +196,7 @@ MidiBuffer::reserve(double time, size_t size)
assert(size <= MAX_EVENT_SIZE);
if (_size == _capacity)
return NULL;
return 0;
Byte* const write_loc = _data + (_size * MAX_EVENT_SIZE);
@ -264,6 +277,3 @@ MidiBuffer::merge(const MidiBuffer& a, const MidiBuffer& b)
return true;
}
} // namespace ARDOUR

View File

@ -20,19 +20,76 @@
#include <iostream>
#include <ardour/midi_port.h>
#include <ardour/jack_midi_port.h>
#include <ardour/data_type.h>
using namespace ARDOUR;
using namespace std;
MidiPort::MidiPort (Flags flags, nframes_t bufsize)
: Port (DataType::MIDI, flags)
, _buffer (bufsize)
MidiPort::MidiPort (const std::string& name, Flags flags, bool publish, nframes_t bufsize)
: Port (name, flags)
, BaseMidiPort (name, flags)
, PortFacade (name, flags)
{
reset();
set_name (name);
_buffer = new MidiBuffer (bufsize);
if (!publish) {
_ext_port = 0;
} else {
_ext_port = new JackMidiPort (name, flags, _buffer);
}
reset ();
}
MidiPort::~MidiPort()
{
if (_ext_port) {
delete _ext_port;
_ext_port = 0;
}
}
void
MidiPort::reset()
{
BaseMidiPort::reset();
if (_ext_port) {
_ext_port->reset ();
}
}
void
MidiPort::cycle_start (nframes_t nframes, nframes_t offset)
{
/* caller must hold process lock */
if (_ext_port) {
_ext_port->cycle_start (nframes, offset);
}
if (_flags & IsInput) {
if (_ext_port) {
_buffer->read_from (dynamic_cast<BaseMidiPort*>(_ext_port)->get_midi_buffer(), nframes, offset);
if (!_connections.empty()) {
(*_mixdown) (_connections, _buffer, nframes, offset, false);
}
} else {
if (_connections.empty()) {
_buffer->silence (nframes, offset);
} else {
(*_mixdown) (_connections, _buffer, nframes, offset, true);
}
}
} else {
_buffer->silence (nframes, offset);
}
}

View File

@ -269,7 +269,7 @@ BaseStereoPanner::distribute (AudioBuffer& srcbuf, BufferSet& obufs, gain_t gain
pan = left * gain_coeff;
mix_buffers_with_gain(dst+n,src+n,nframes-n,pan);
mix_buffers_with_gain (dst+n,src+n,nframes-n,pan);
} else {

View File

@ -22,16 +22,358 @@
using namespace ARDOUR;
using namespace std;
Port::Port (DataType type, Flags flags)
: _flags (flags)
, _type (type)
AudioEngine* Port::engine = 0;
Port::Port (const std::string& name, Flags flgs)
: _flags (flgs)
, _name (name)
, _metering (0)
, _last_monitor (false)
{
}
Port::~Port ()
{
disconnect_all ();
}
void
Port::reset ()
{
_last_monitor = false;
}
void
Port::set_engine (AudioEngine* e)
{
engine = e;
}
int
Port::connect (Port& other)
{
/* caller must hold process lock */
pair<set<Port*>::iterator,bool> result;
result = _connections.insert (&other);
if (result.second) {
return 0;
} else {
return 1;
}
}
int
Port::disconnect (Port& other)
{
/* caller must hold process lock */
for (set<Port*>::iterator i = _connections.begin(); i != _connections.end(); ++i) {
if ((*i) == &other) {
_connections.erase (i);
return 0;
}
}
return -1;
}
int
Port::disconnect_all ()
{
/* caller must hold process lock */
_connections.clear ();
return 0;
}
void
Port::set_latency (nframes_t val)
{
_latency = val;
}
bool
Port::connected() const
{
/* caller must hold process lock */
return !_connections.empty();
}
bool
Port::connected_to (const string& portname) const
{
/* caller must hold process lock */
for (set<Port*>::const_iterator p = _connections.begin(); p != _connections.end(); ++p) {
if ((*p)->name() == portname) {
return true;
}
}
return false;
}
int
Port::get_connections (vector<string>& names) const
{
/* caller must hold process lock */
int i = 0;
set<Port*>::const_iterator p;
for (i = 0, p = _connections.begin(); p != _connections.end(); ++p, ++i) {
names.push_back ((*p)->name());
}
return i;
}
//-------------------------------------
int
PortFacade::set_name (const std::string& str)
{
int ret;
if (_ext_port) {
if ((ret = _ext_port->set_name (str)) == 0) {
_name = _ext_port->name();
}
} else {
_name = str;
ret = 0;
}
return ret;
}
string
PortFacade::short_name () const
{
if (_ext_port) {
return _ext_port->short_name();
} else {
return _name;
}
}
int
PortFacade::reestablish ()
{
if (_ext_port) {
return _ext_port->reestablish ();
} else {
return 0;
}
}
int
PortFacade::reconnect()
{
if (_ext_port) {
return _ext_port->reconnect ();
} else {
return 0;
}
}
void
PortFacade::set_latency (nframes_t val)
{
if (_ext_port) {
_ext_port->set_latency (val);
} else {
_latency = val;
}
}
nframes_t
PortFacade::latency() const
{
if (_ext_port) {
return _ext_port->latency();
} else {
return _latency;
}
}
nframes_t
PortFacade::total_latency() const
{
if (_ext_port) {
return _ext_port->total_latency();
} else {
return _latency;
}
}
bool
PortFacade::monitoring_input() const
{
if (_ext_port) {
return _ext_port->monitoring_input ();
} else {
return false;
}
}
void
PortFacade::ensure_monitor_input (bool yn)
{
if (_ext_port) {
_ext_port->ensure_monitor_input (yn);
}
}
void
PortFacade::request_monitor_input (bool yn)
{
if (_ext_port) {
_ext_port->request_monitor_input (yn);
}
}
int
PortFacade::connect (Port& other)
{
int ret;
if (_ext_port) {
ret = _ext_port->connect (other);
} else {
ret = 0;
}
if (ret == 0) {
ret = Port::connect (other);
}
return ret;
}
int
PortFacade::connect (const std::string& other)
{
PortConnectableByName* pcn;
if (!_ext_port) {
return -1;
}
pcn = dynamic_cast<PortConnectableByName*>(_ext_port);
if (pcn) {
return pcn->connect (other);
} else {
return -1;
}
}
int
PortFacade::disconnect (Port& other)
{
int reta;
int retb;
if (_ext_port) {
reta = _ext_port->disconnect (other);
} else {
reta = 0;
}
retb = Port::disconnect (other);
return reta || retb;
}
int
PortFacade::disconnect_all ()
{
int reta;
int retb;
if (_ext_port) {
reta = _ext_port->disconnect_all ();
}
retb = Port::disconnect_all ();
return reta || retb;
}
int
PortFacade::disconnect (const std::string& other)
{
PortConnectableByName* pcn;
if (!_ext_port) {
return -1;
}
pcn = dynamic_cast<PortConnectableByName*>(_ext_port);
if (pcn) {
return pcn->disconnect (other);
} else {
return -1;
}
}
bool
PortFacade::connected () const
{
if (Port::connected()) {
return true;
}
if (_ext_port) {
return _ext_port->connected();
}
return false;
}
bool
PortFacade::connected_to (const std::string& portname) const
{
if (Port::connected_to (portname)) {
return true;
}
if (_ext_port) {
return _ext_port->connected_to (portname);
}
return false;
}
int
PortFacade::get_connections (vector<string>& names) const
{
int i = 0;
if (_ext_port) {
i = _ext_port->get_connections (names);
}
i += Port::get_connections (names);
return i;
}
void
PortFacade::reset ()
{
Port::reset ();
if (_ext_port) {
_ext_port->reset ();
}
}

View File

@ -250,7 +250,7 @@ SourceFactory::createWritable (DataType type, Session& s, std::string path, bool
(destructive ? AudioFileSource::Flag (SndFileSource::default_writable_flags | AudioFileSource::Destructive) :
SndFileSource::default_writable_flags)));
if (setup_peakfile (ret, false)) {
if (setup_peakfile (ret, defer_peaks)) {
return boost::shared_ptr<Source>();
}