diff options
author | Paul Davis <paul@linuxaudiosystems.com> | 2007-10-31 18:24:43 +0000 |
---|---|---|
committer | Paul Davis <paul@linuxaudiosystems.com> | 2007-10-31 18:24:43 +0000 |
commit | 8ab17e96312f1a61c014c50687e15430d5ae786b (patch) | |
tree | eefb889cd64d48058a608f0c19185b2a56d73399 /libs/ardour | |
parent | 1b0f6b1d69bcad74c6127690cebc1c14486e8c1d (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')
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>(); } |