summaryrefslogtreecommitdiff
path: root/libs/ardour
diff options
context:
space:
mode:
authorPaul Davis <paul@linuxaudiosystems.com>2007-10-31 18:24:43 +0000
committerPaul Davis <paul@linuxaudiosystems.com>2007-10-31 18:24:43 +0000
commit8ab17e96312f1a61c014c50687e15430d5ae786b (patch)
treeeefb889cd64d48058a608f0c19185b2a56d73399 /libs/ardour
parent1b0f6b1d69bcad74c6127690cebc1c14486e8c1d (diff)
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
Diffstat (limited to 'libs/ardour')
-rw-r--r--libs/ardour/SConscript4
-rw-r--r--libs/ardour/ardour/audio_buffer.h17
-rw-r--r--libs/ardour/ardour/audio_port.h59
-rw-r--r--libs/ardour/ardour/audioengine.h8
-rw-r--r--libs/ardour/ardour/io.h8
-rw-r--r--libs/ardour/ardour/jack_audio_port.h12
-rw-r--r--libs/ardour/ardour/jack_midi_port.h15
-rw-r--r--libs/ardour/ardour/jack_port.h33
-rw-r--r--libs/ardour/ardour/midi_buffer.h2
-rw-r--r--libs/ardour/ardour/midi_port.h31
-rw-r--r--libs/ardour/ardour/port.h98
-rw-r--r--libs/ardour/ardour/types.h5
-rw-r--r--libs/ardour/audio_buffer.cc4
-rw-r--r--libs/ardour/audio_diskstream.cc14
-rw-r--r--libs/ardour/audio_port.cc105
-rw-r--r--libs/ardour/audioengine.cc221
-rw-r--r--libs/ardour/auditioner.cc12
-rw-r--r--libs/ardour/io.cc58
-rw-r--r--libs/ardour/jack_audio_port.cc20
-rw-r--r--libs/ardour/jack_midi_port.cc68
-rw-r--r--libs/ardour/jack_port.cc89
-rw-r--r--libs/ardour/midi_buffer.cc50
-rw-r--r--libs/ardour/midi_port.cc65
-rw-r--r--libs/ardour/panner.cc2
-rw-r--r--libs/ardour/port.cc348
-rw-r--r--libs/ardour/source_factory.cc2
26 files changed, 947 insertions, 403 deletions
diff --git a/libs/ardour/SConscript b/libs/ardour/SConscript
index bcbc7c78ac..f40752167d 100644
--- a/libs/ardour/SConscript
+++ b/libs/ardour/SConscript
@@ -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
diff --git a/libs/ardour/ardour/audio_buffer.h b/libs/ardour/ardour/audio_buffer.h
index 8f0df4419c..09bf5946fa 100644
--- a/libs/ardour/ardour/audio_buffer.h
+++ b/libs/ardour/ardour/audio_buffer.h
@@ -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;
diff --git a/libs/ardour/ardour/audio_port.h b/libs/ardour/ardour/audio_port.h
index ce544aa7bc..874f842d83 100644
--- a/libs/ardour/ardour/audio_port.h
+++ b/libs/ardour/ardour/audio_port.h
@@ -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;
- }
-
- 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 ();
- }
+ ~AudioPort();
- float peak_db() const { return _peak_db; }
- Sample peak() const { return _peak; }
+ void reset ();
- uint32_t short_overs () const { return _short_overs; }
- uint32_t long_overs () const { return _long_overs; }
+ void cycle_start (nframes_t nframes, nframes_t offset);
+ void cycle_end (nframes_t nframes, nframes_t offset);
- 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
diff --git a/libs/ardour/ardour/audioengine.h b/libs/ardour/ardour/audioengine.h
index 503b8166f0..dc7ae8e000 100644
--- a/libs/ardour/ardour/audioengine.h
+++ b/libs/ardour/ardour/audioengine.h
@@ -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;
diff --git a/libs/ardour/ardour/io.h b/libs/ardour/ardour/io.h
index 888b770250..0ae9cef55a 100644
--- a/libs/ardour/ardour/io.h
+++ b/libs/ardour/ardour/io.h
@@ -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 ();
diff --git a/libs/ardour/ardour/jack_audio_port.h b/libs/ardour/ardour/jack_audio_port.h
index 8a636bb7aa..703fb81fa3 100644
--- a/libs/ardour/ardour/jack_audio_port.h
+++ b/libs/ardour/ardour/jack_audio_port.h
@@ -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
diff --git a/libs/ardour/ardour/jack_midi_port.h b/libs/ardour/ardour/jack_midi_port.h
index 5508ae2b17..d1fb5cc4fb 100644
--- a/libs/ardour/ardour/jack_midi_port.h
+++ b/libs/ardour/ardour/jack_midi_port.h
@@ -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
diff --git a/libs/ardour/ardour/jack_port.h b/libs/ardour/ardour/jack_port.h
index d973ed2cab..3fa0008e17 100644
--- a/libs/ardour/ardour/jack_port.h
+++ b/libs/ardour/ardour/jack_port.h
@@ -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
diff --git a/libs/ardour/ardour/midi_buffer.h b/libs/ardour/ardour/midi_buffer.h
index 953d424296..b35264217a 100644
--- a/libs/ardour/ardour/midi_buffer.h
+++ b/libs/ardour/ardour/midi_buffer.h
@@ -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 {
diff --git a/libs/ardour/ardour/midi_port.h b/libs/ardour/ardour/midi_port.h
index 0787f66494..c9bcb056f4 100644
--- a/libs/ardour/ardour/midi_port.h
+++ b/libs/ardour/ardour/midi_port.h
@@ -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;
- }
-
- MidiBuffer& get_midi_buffer() {
- return _buffer;
- }
-
- size_t capacity() { return _buffer.capacity(); }
- size_t size() { return _buffer.size(); }
+ ~MidiPort();
+
+ 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
diff --git a/libs/ardour/ardour/port.h b/libs/ardour/ardour/port.h
index e9179ae326..93c34da16d 100644
--- a/libs/ardour/ardour/port.h
+++ b/libs/ardour/ardour/port.h
@@ -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__ */
diff --git a/libs/ardour/ardour/types.h b/libs/ardour/ardour/types.h
index 8dd9ccc211..0d32d35c7d 100644
--- a/libs/ardour/ardour/types.h
+++ b/libs/ardour/ardour/types.h
@@ -379,11 +379,6 @@ namespace ARDOUR {
SrcFastest
};
- enum PortType {
- Jack,
- Internal
- };
-
} // namespace ARDOUR
std::istream& operator>>(std::istream& o, ARDOUR::SampleFormat& sf);
diff --git a/libs/ardour/audio_buffer.cc b/libs/ardour/audio_buffer.cc
index b07f70be1f..4871035e80 100644
--- a/libs/ardour/audio_buffer.cc
+++ b/libs/ardour/audio_buffer.cc
@@ -48,9 +48,7 @@ AudioBuffer::~AudioBuffer()
void
AudioBuffer::resize (size_t size)
{
- assert (_owns_data);
-
- if (size < _capacity) {
+ if (!_owns_data || (size < _capacity)) {
return;
}
diff --git a/libs/ardour/audio_diskstream.cc b/libs/ardour/audio_diskstream.cc
index fbe12e6bf5..c4b2c06e15 100644
--- a/libs/ardour/audio_diskstream.cc
+++ b/libs/ardour/audio_diskstream.cc
@@ -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]) );
}
}
}
diff --git a/libs/ardour/audio_port.cc b/libs/ardour/audio_port.cc
index 13dad9b8e0..66d31c63fe 100644
--- a/libs/ardour/audio_port.cc
+++ b/libs/ardour/audio_port.cc
@@ -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)
+{
+}
diff --git a/libs/ardour/audioengine.cc b/libs/ardour/audioengine.cc
index 2e1b790848..c77f1b9fd8 100644
--- a/libs/ardour/audioengine.cc
+++ b/libs/ardour/audioengine.cc
@@ -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;
-
- 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 */
+ 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 */
+
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);
+
+ 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;
- InternalPort::connect (*src, *dst);
- ret = 0;
+ 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*/
diff --git a/libs/ardour/auditioner.cc b/libs/ardour/auditioner.cc
index c509997b2e..6085501470 100644
--- a/libs/ardour/auditioner.cc
+++ b/libs/ardour/auditioner.cc
@@ -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 ("");
}
diff --git a/libs/ardour/io.cc b/libs/ardour/io.cc
index d0a233a356..f64528aa52 100644
--- a/libs/ardour/io.cc
+++ b/libs/ardour/io.cc
@@ -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 += "{}";
}
}
diff --git a/libs/ardour/jack_audio_port.cc b/libs/ardour/jack_audio_port.cc
index e4bdcb5d72..3a0b34ab19 100644
--- a/libs/ardour/jack_audio_port.cc
+++ b/libs/ardour/jack_audio_port.cc
@@ -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;
}
+
diff --git a/libs/ardour/jack_midi_port.cc b/libs/ardour/jack_midi_port.cc
index ed999f187a..e943a6a190 100644
--- a/libs/ardour/jack_midi_port.cc
+++ b/libs/ardour/jack_midi_port.cc
@@ -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);
-
- _nframes_this_cycle = nframes;
+ _buffer->clear();
+ assert(_buffer->size() == 0);
- 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;
}
diff --git a/libs/ardour/jack_port.cc b/libs/ardour/jack_port.cc
index c7d737ca0f..c4705816e9 100644
--- a/libs/ardour/jack_port.cc
+++ b/libs/ardour/jack_port.cc
@@ -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;
+}
diff --git a/libs/ardour/midi_buffer.cc b/libs/ardour/midi_buffer.cc
index 52f04eaf91..a629fe458f 100644
--- a/libs/ardour/midi_buffer.cc
+++ b/libs/ardour/midi_buffer.cc
@@ -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)
+{
+ if (capacity) {
+ resize (_capacity);
+ silence(_capacity);
+ }
+}
+
+MidiBuffer::~MidiBuffer()
{
- _data = 0;
- resize (_capacity);
- silence(_capacity);
+ 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
-
diff --git a/libs/ardour/midi_port.cc b/libs/ardour/midi_port.cc
index 661df2ce54..8fb66255d8 100644
--- a/libs/ardour/midi_port.cc
+++ b/libs/ardour/midi_port.cc
@@ -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);
+ }
+}
diff --git a/libs/ardour/panner.cc b/libs/ardour/panner.cc
index 3e57037d6f..ac8e4d05e3 100644
--- a/libs/ardour/panner.cc
+++ b/libs/ardour/panner.cc
@@ -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 {
diff --git a/libs/ardour/port.cc b/libs/ardour/port.cc
index 1a31124c73..1c79e0c438 100644
--- a/libs/ardour/port.cc
+++ b/libs/ardour/port.cc
@@ -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 ();
+ }
+}
diff --git a/libs/ardour/source_factory.cc b/libs/ardour/source_factory.cc
index 3a657bc0e2..89d4e3ed79 100644
--- a/libs/ardour/source_factory.cc
+++ b/libs/ardour/source_factory.cc
@@ -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>();
}