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:
parent
1b0f6b1d69
commit
8ab17e9631
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 ();
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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__ */
|
||||
|
|
|
@ -379,11 +379,6 @@ namespace ARDOUR {
|
|||
SrcFastest
|
||||
};
|
||||
|
||||
enum PortType {
|
||||
Jack,
|
||||
Internal
|
||||
};
|
||||
|
||||
} // namespace ARDOUR
|
||||
|
||||
std::istream& operator>>(std::istream& o, ARDOUR::SampleFormat& sf);
|
||||
|
|
|
@ -48,9 +48,7 @@ AudioBuffer::~AudioBuffer()
|
|||
void
|
||||
AudioBuffer::resize (size_t size)
|
||||
{
|
||||
assert (_owns_data);
|
||||
|
||||
if (size < _capacity) {
|
||||
if (!_owns_data || (size < _capacity)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -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]) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
}
|
||||
|
|
|
@ -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*/
|
||||
|
|
|
@ -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 ("");
|
||||
}
|
||||
|
|
|
@ -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 += "{}";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
||||
|
|
|
@ -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 ();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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>();
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue