new port design, probably about 90% done (i.e it mostly works and this commit is...
authorPaul Davis <paul@linuxaudiosystems.com>
Wed, 31 Oct 2007 18:24:43 +0000 (18:24 +0000)
committerPaul Davis <paul@linuxaudiosystems.com>
Wed, 31 Oct 2007 18:24:43 +0000 (18:24 +0000)
git-svn-id: svn://localhost/ardour2/trunk@2579 d708f5d6-7413-0410-9779-e7cbd77b26cf

28 files changed:
gtk2_ardour/ardour_ui.cc
gtk2_ardour/io_selector.cc
libs/ardour/SConscript
libs/ardour/ardour/audio_buffer.h
libs/ardour/ardour/audio_port.h
libs/ardour/ardour/audioengine.h
libs/ardour/ardour/io.h
libs/ardour/ardour/jack_audio_port.h
libs/ardour/ardour/jack_midi_port.h
libs/ardour/ardour/jack_port.h
libs/ardour/ardour/midi_buffer.h
libs/ardour/ardour/midi_port.h
libs/ardour/ardour/port.h
libs/ardour/ardour/types.h
libs/ardour/audio_buffer.cc
libs/ardour/audio_diskstream.cc
libs/ardour/audio_port.cc
libs/ardour/audioengine.cc
libs/ardour/auditioner.cc
libs/ardour/io.cc
libs/ardour/jack_audio_port.cc
libs/ardour/jack_midi_port.cc
libs/ardour/jack_port.cc
libs/ardour/midi_buffer.cc
libs/ardour/midi_port.cc
libs/ardour/panner.cc
libs/ardour/port.cc
libs/ardour/source_factory.cc

index c2f9a1d533991a11eff39af2ad8b74dbcd1fc095..4e0ed989a312f0a1e5d5c69b97230c1b22352c6c 100644 (file)
@@ -1815,6 +1815,8 @@ ARDOUR_UI::name_io_setup (AudioEngine& engine,
                          IO& io,
                          bool in)
 {
+       vector<string> connections;
+
        if (in) {
                if (io.n_inputs().n_total() == 0) {
                        buf = _("none");
@@ -1823,16 +1825,12 @@ ARDOUR_UI::name_io_setup (AudioEngine& engine,
                
                /* XXX we're not handling multiple ports yet. */
 
-               const char **connections = io.input(0)->get_connections();
-               
-               if (connections == 0 || connections[0] == '\0') {
+               if (io.input(0)->get_connections(connections) == 0) {
                        buf = _("off");
                } else {
-                       buf = connections[0];
+                       buf = connections.front();
                }
 
-               free (connections);
-
        } else {
 
                if (io.n_outputs().n_total() == 0) {
@@ -1842,15 +1840,11 @@ ARDOUR_UI::name_io_setup (AudioEngine& engine,
                
                /* XXX we're not handling multiple ports yet. */
 
-               const char **connections = io.output(0)->get_connections();
-               
-               if (connections == 0 || connections[0] == '\0') {
+               if (io.output(0)->get_connections(connections) == 0) {
                        buf = _("off");
                } else {
-                       buf = connections[0];
+                       buf = connections.front();
                }
-
-               free (connections);
        }
 }
 
index b8598659d7c6ba7614093c33bfdfd9336175aaa2..cecea984709ca703d8c50e447840649ee7c9af1c 100644 (file)
@@ -79,14 +79,22 @@ IOSelector::set_state (int r, std::string const & p, bool s)
 bool
 IOSelector::get_state (int r, std::string const & p) const
 {
-       const char **connections = _offer_inputs ? _io->output(r)->get_connections() : _io->input(r)->get_connections();
+       vector<string> connections;
+
+       if (_offer_inputs) {
+               _io->output(r)->get_connections (connections);
+       } else {
+               _io->input(r)->get_connections (connections);
+       }
 
        int k = 0;
-       while (connections && connections[k]) {
-               if (std::string (connections[k]) == p) {
+
+       for (vector<string>::iterator i = connections.begin(); i != connections.end(); ++i) {
+
+               if ((*i)== p) {
                        return true;
                }
-
+               
                ++k;
        }
 
index bcbc7c78acfb2f951ede484f904a2128bb9cb10b..f40752167d7f605a80c75aa7dbab851903317036 100644 (file)
@@ -45,6 +45,8 @@ automatable.cc
 automation.cc
 automation_control.cc
 automation_event.cc
+base_audio_port.cc
+base_midi_port.cc
 buffer.cc
 buffer_set.cc
 chan_count.cc
@@ -66,8 +68,6 @@ gain.cc
 gdither.cc
 globals.cc
 import.cc
-internal_port.cc
-internal_audio_port.cc
 io.cc
 io_processor.cc
 jack_port.cc
index 8f0df4419cc1127097dd00311d9f4ad684d98af9..09bf5946fa40a853af0421866712d99b5998cca9 100644 (file)
@@ -23,8 +23,6 @@
 
 namespace ARDOUR {
 
-
-/** Buffer containing 32-bit floating point (audio) data. */
 class AudioBuffer : public Buffer
 {
 public:
@@ -32,8 +30,7 @@ public:
        
        ~AudioBuffer();
 
-       void silence(nframes_t len, nframes_t offset=0)
-       {
+       void silence(nframes_t len, nframes_t offset = 0) {
                if (!_silent) {
                        assert(_capacity > 0);
                        assert(offset + len <= _capacity);
@@ -45,8 +42,7 @@ public:
        }
        
        /** Read @a len frames FROM THE START OF @a src into self at @a offset */
-       void read_from(const Buffer& src, nframes_t len, nframes_t offset)
-       {
+       void read_from(const Buffer& src, nframes_t len, nframes_t offset) {
                assert(_capacity > 0);
                assert(src.type() == DataType::AUDIO);
                assert(offset + len <= _capacity);
@@ -55,8 +51,7 @@ public:
        }
        
        /** Accumulate (add)@a len frames FROM THE START OF @a src into self at @a offset */
-       void accumulate_from(const AudioBuffer& src, nframes_t len, nframes_t offset)
-       {
+       void accumulate_from(const AudioBuffer& src, nframes_t len, nframes_t offset) {
                assert(_capacity > 0);
                assert(offset + len <= _capacity);
 
@@ -70,8 +65,7 @@ public:
        
        /** Accumulate (add) @a len frames FROM THE START OF @a src into self at @a offset
         * scaling by @a gain_coeff */
-       void accumulate_with_gain_from(const AudioBuffer& src, nframes_t len, nframes_t offset, gain_t gain_coeff)
-       {
+       void accumulate_with_gain_from(const AudioBuffer& src, nframes_t len, nframes_t offset, gain_t gain_coeff) {
                assert(_capacity > 0);
                assert(offset + len <= _capacity);
 
@@ -91,8 +85,7 @@ public:
         * 
         * Constructor MUST have been passed capacity=0 or this will die (to prevent mem leaks).
         */
-       void set_data(Sample* data, size_t size)
-       {
+       void set_data (Sample* data, size_t size) {
                assert(!_owns_data); // prevent leaks
                _capacity = size;
                _size = size;
index ce544aa7bc4d9d40e41b21f14e59006de8524a0a..874f842d835e9a346080468b7df58a3387d581bb 100644 (file)
 #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
index 503b8166f0789cda21f0ff35f9fdd439101104a2..dc7ae8e000818285f2d756e4839a1c6e4b508d1b 100644 (file)
@@ -114,8 +114,8 @@ class AudioEngine : public sigc::trackable
                virtual const char *what() const throw() { return "could not connect to engine backend"; }
        };
 
-       Port *register_input_port (PortType, DataType, const std::string& portname);
-       Port *register_output_port (PortType, DataType, const std::string& portname);
+       Port *register_input_port (DataType, const std::string& portname, bool publish);
+       Port *register_output_port (DataType, const std::string& portname, bool publish);
        int   unregister_port (Port &);
        
        int connect (const std::string& source, const std::string& destination);
@@ -220,12 +220,12 @@ class AudioEngine : public sigc::trackable
 
        SerializedRCUManager<Ports> ports;
 
-       Port *register_port (PortType ptype, DataType type, const std::string& portname, bool input);
+       Port *register_port (DataType type, const std::string& portname, bool input, bool publish);
 
        int    process_callback (nframes_t nframes);
        void   remove_all_ports ();
 
-       InternalPort* get_internal_port (const std::string& short_name);
+       Port* get_port (const std::string& short_name);
 
        typedef std::pair<std::string,std::string> PortConnection;
        typedef std::list<PortConnection> PortConnections;
index 888b770250cb72de4de29ac730f6e4199c2b60c7..0ae9cef55aed6c80d05ea8e445bdd29c3021f0aa 100644 (file)
@@ -78,7 +78,8 @@ class IO : public Automatable, public Latent
        IO (Session&, const string& name, 
            int input_min = -1, int input_max = -1, 
            int output_min = -1, int output_max = -1,
-           DataType default_type = DataType::AUDIO);
+           DataType default_type = DataType::AUDIO,
+           bool public_ports = true);
        
        IO (Session&, const XMLNode&, DataType default_type = DataType::AUDIO);
        
@@ -270,7 +271,7 @@ class IO : public Automatable, public Latent
        gain_t              _gain;
        gain_t              _effective_gain;
        gain_t              _desired_gain;
-       Glib::Mutex         declick_lock;
+       Glib::Mutex          declick_lock;
        PortSet             _outputs;
        PortSet             _inputs;
        PeakMeter*          _meter;
@@ -279,7 +280,8 @@ class IO : public Automatable, public Latent
        bool                _denormal_protection;
        XMLNode*             deferred_state;
        DataType            _default_type;
-       
+       bool                _public_ports;
+
        virtual void set_deferred_state() {}
 
        void reset_panner ();
index 8a636bb7aa017d4b0dcc7eada1e7c553ba78e0bd..703fb81fa3cc8afaeee649fc561241557cb89106 100644 (file)
 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
index 5508ae2b170dcbc7c23d10e6b40eae29425b85e9..d1fb5cc4fb4ea3622b0613146b5e121da290bb7a 100644 (file)
 #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
index d973ed2cab76c0ff3cdfc2a1bd8c17bc4f7606a3..3fa0008e17ca664d9dee03c5e793c3628d5ece58 100644 (file)
@@ -32,30 +32,44 @@ class Buffer;
 
 /** Abstract class representing JACK ports
  */
-class JackPort : public virtual Port {
+class JackPort : public virtual Port, public PortConnectableByName {
    public:
 
        ~JackPort();
 
-       std::string short_name() { 
+       std::string short_name() const 
                return jack_port_short_name (_port);
        }
        
-       int set_name (std::string str);
+       int set_name (const std::string& str);
        
-       int connected () const {
+       bool connected () const {
                return jack_port_connected (_port);
        }
        
        int reestablish ();
-       
+       int reconnect ();
+
+       int connect (Port& other) {
+               return connect (other.name());
+       }
+
+       int disconnect (Port& other) {
+               return disconnect (other.name());
+       }
+
+       int disconnect_all ();
+
+       // connect-by-name API
+
+       int connect (const std::string& other_name);
+       int disconnect (const std::string& other_name);
+
        bool connected_to (const std::string& portname) const {
                return jack_port_connected_to (_port, portname.c_str());
        }
 
-       const char ** get_connections () const {
-               return jack_port_get_connections (_port);
-       }
+       int get_connections (std::vector<std::string>& names) const;
        
        bool monitoring_input () const {
                return jack_port_monitoring_input (_port);
@@ -90,8 +104,7 @@ class JackPort : public virtual Port {
        int disconnect ();
        void recompute_total_latency() const;
 
-       static void set_engine (AudioEngine*);
-       static AudioEngine* engine;
+       std::set<std::string> _named_connections;
 };
  
 } // namespace ARDOUR
index 953d424296a8f1930099aef2387850f28817e403..b35264217adb44e12f3a29b112e1caf501684d46 100644 (file)
@@ -44,7 +44,7 @@ public:
        Byte* reserve(double time, size_t size);
 
        void resize(size_t);
-       
+
        bool merge(const MidiBuffer& a, const MidiBuffer& b);
        
        struct iterator {
index 0787f66494e479bd3371152333049de36f0ac3cc..c9bcb056f44412fb6de789d7f1186fa8241fc1e4 100644 (file)
 #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
index e9179ae326b64a01a5480f8cd00bbff040704970..93c34da16d9c28d3e0dd915354b268856c7022b6 100644 (file)
 #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__ */
index 8dd9ccc211518f21f3c643850432da8d63a7e47b..0d32d35c7d8ab5afb8e329336b8f3cd89f038f4e 100644 (file)
@@ -379,11 +379,6 @@ namespace ARDOUR {
                SrcFastest
        };
 
-       enum PortType {
-               Jack,
-               Internal
-       };
-
 } // namespace ARDOUR
 
 std::istream& operator>>(std::istream& o, ARDOUR::SampleFormat& sf);
index b07f70be1f8aa99f7afdca4875b645375a58e130..4871035e80cb11cf0d56a7489c80c8dbb6106ccb 100644 (file)
@@ -48,9 +48,7 @@ AudioBuffer::~AudioBuffer()
 void
 AudioBuffer::resize (size_t size)
 {
-       assert (_owns_data);
-
-       if (size < _capacity) {
+       if (!_owns_data || (size < _capacity)) {
                return;
        }
 
index fbe12e6bf5c8936ee7ea8c91128b1ee1e9196aef..c4b2c06e159320beca3d58c051c39797913d4c57 100644 (file)
@@ -212,13 +212,14 @@ AudioDiskstream::get_input_sources ()
        uint32_t n;
        ChannelList::iterator chan;
        uint32_t ni = _io->n_inputs().n_audio();
+       vector<string> connections;
 
        for (n = 0, chan = c->begin(); chan != c->end() && n < ni; ++chan, ++n) {
                
-               const char **connections = _io->input(n)->get_connections ();
+               connections.clear ();
+
+               if (_io->input(n)->get_connections (connections) == 0) {
                
-               if (connections == 0 || connections[0] == 0) {
-                       
                        if ((*chan)->source) {
                                // _source->disable_metering ();
                        }
@@ -226,12 +227,7 @@ AudioDiskstream::get_input_sources ()
                        (*chan)->source = 0;
                        
                } else {
-                       (*chan)->source = dynamic_cast<AudioPort*>(
-                               _session.engine().get_port_by_name (connections[0]) );
-               }
-               
-               if (connections) {
-                       free (connections);
+                       (*chan)->source = dynamic_cast<AudioPort*>(_session.engine().get_port_by_name (connections[0]) );
                }
        }
 }              
index 13dad9b8e054f46c962b7082eeb5621ac232eb61..66d31c63fecef177d507e5f43dbef264014f16f7 100644 (file)
 
 #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)
+{
+}
index 2e1b790848d90fbe8fbcc250bdc8402af5f65f97..c77f1b9fd8f84aa2c72367117a0203534c94163c 100644 (file)
@@ -32,8 +32,8 @@
 #include <ardour/buffer.h>
 #include <ardour/port.h>
 #include <ardour/jack_audio_port.h>
-#include <ardour/internal_audio_port.h>
 #include <ardour/jack_midi_port.h>
+#include <ardour/audio_port.h>
 #include <ardour/session.h>
 #include <ardour/cycle_timer.h>
 #include <ardour/utils.h>
@@ -84,7 +84,7 @@ AudioEngine::AudioEngine (string client_name)
 
        start_metering_thread();
 
-       JackPort::set_engine (this);
+       Port::set_engine (this);
 }
 
 AudioEngine::~AudioEngine ()
@@ -330,7 +330,7 @@ AudioEngine::process_callback (nframes_t nframes)
 
        // Prepare ports (ie read data if necessary)
        for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
-               (*i)->cycle_start (nframes);
+               (*i)->cycle_start (nframes, 0);
        }
        
        if (session) {
@@ -343,8 +343,9 @@ AudioEngine::process_callback (nframes_t nframes)
        }
        
        // Finalize ports (ie write data if necessary)
+
        for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
-               (*i)->cycle_end ();
+               (*i)->cycle_end (nframes, 0);
        }
 
        if (last_monitor_check + monitor_check_interval < next_processed_frames) {
@@ -471,8 +472,9 @@ AudioEngine::set_session (Session *s)
                
                boost::shared_ptr<Ports> p = ports.reader();
 
-               for (Ports::iterator i = p->begin(); i != p->end(); ++i)
-                       (*i)->cycle_start (blocksize);
+               for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
+                       (*i)->cycle_start (blocksize, 0);
+               }
 
                s->process (blocksize);
                s->process (blocksize);
@@ -483,9 +485,9 @@ AudioEngine::set_session (Session *s)
                s->process (blocksize);
                s->process (blocksize);
 
-               for (Ports::iterator i = p->begin(); i != p->end(); ++i)
-                       (*i)->cycle_end ();
-
+               for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
+                       (*i)->cycle_end (blocksize, 0);
+               }
        }
 }
 
@@ -509,41 +511,24 @@ AudioEngine::remove_session ()
 }
 
 Port *
-AudioEngine::register_port (PortType ptype, DataType dtype, const string& portname, bool input)
+AudioEngine::register_port (DataType dtype, const string& portname, bool input, bool publish)
 {
        Port* newport = 0;
 
        try {
-               switch (ptype) {
-               case Jack:
-                       if (dtype == DataType::AUDIO) {
-                               newport = new JackAudioPort (portname, (input ? Port::IsInput : Port::IsOutput));
-                       } else if (dtype == DataType::MIDI) {
-                               newport = new JackMidiPort (portname, (input ? Port::IsInput : Port::IsOutput));
-                       } else {
-                               throw unknown_type();
-                       }
-                       break;
-
-               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*/
index c509997b2ef7e8a1f826c78619137720792b9b3a..6085501470a581fc2a13fd54cd99040a766a73e7 100644 (file)
@@ -194,29 +194,27 @@ Auditioner::output_changed (IOChange change, void* src)
        string phys;
 
        if (change & ConnectionsChanged) {
-               const char ** connections;
-               connections =  output (0)->get_connections ();
-               if (connections) {
+               vector<string> connections;
+               if (output (0)->get_connections (connections)) {
                        phys = _session.engine().get_nth_physical_output (DataType::AUDIO, 0);
                        if (phys != connections[0]) {
                                Config->set_auditioner_output_left (connections[0]);
                        } else {
                                Config->set_auditioner_output_left ("default");
                        }
-                       free (connections);
                } else {
                        Config->set_auditioner_output_left ("");
                }
                
-               connections = output (1)->get_connections ();
-               if (connections) {
+               connections.clear ();
+
+               if (output (1)->get_connections (connections)) {
                        phys = _session.engine().get_nth_physical_output (DataType::AUDIO, 1);
                        if (phys != connections[0]) {
                                Config->set_auditioner_output_right (connections[0]);
                        } else {
                                Config->set_auditioner_output_right ("default");
                        }
-                       free (connections);
                } else {
                        Config->set_auditioner_output_right ("");
                }
index d0a233a3567f29e0a8cf41dec71bfd762186630e..f64528aa52337d369d5c199454fb91c4113efa6f 100644 (file)
@@ -99,10 +99,11 @@ static double direct_gain_to_control (gain_t gain) {
  */
 IO::IO (Session& s, const string& name,
        int input_min, int input_max, int output_min, int output_max,
-       DataType default_type)
+       DataType default_type, bool public_ports)
        : Automatable (s, name),
-      _output_buffers (new BufferSet()),
+         _output_buffers (new BufferSet()),
          _default_type (default_type),
+         _public_ports (public_ports),
          _input_minimum (ChanCount::ZERO),
          _input_maximum (ChanCount::INFINITE),
          _output_minimum (ChanCount::ZERO),
@@ -162,7 +163,7 @@ IO::IO (Session& s, const XMLNode& node, DataType dt)
          _default_type (dt)
 {
        _meter = new PeakMeter (_session);
-
+       _public_ports = true; // XXX get this from node
        _panner = 0;
        deferred_state = 0;
        no_panner_reset = false;
@@ -229,7 +230,7 @@ IO::silence (nframes_t nframes, nframes_t offset)
        }
 }
 
-/** Deliver bufs to the IO's Jack outputs.
+/** Deliver bufs to the IO's output ports
  *
  * This function should automatically do whatever it necessary to correctly deliver bufs
  * to the outputs, eg applying gain or pan or whatever else needs to be done.
@@ -636,7 +637,7 @@ IO::add_output_port (string destination, void* src, DataType type)
                                snprintf (name, sizeof (name), _("%s/out %u"), _name.c_str(), find_output_port_hole());
                        }
                        
-                       if ((our_port = _session.engine().register_output_port (Jack, type, name)) == 0) {
+                       if ((our_port = _session.engine().register_output_port (type, name, _public_ports)) == 0) {
                                error << string_compose(_("IO: cannot register output port %1"), name) << endmsg;
                                return -1;
                        }
@@ -714,7 +715,7 @@ IO::remove_input_port (Port* port, void* src)
 
 /** Add an input port.
  *
- * @param type Data type of port.  The appropriate Jack port type, and @ref Port will be created.
+ * @param type Data type of port.  The appropriate port type, and @ref Port will be created.
  * @param destination Name of input port to connect new port to.
  * @param src Source for emitted ConfigurationChanged signal.
  */
@@ -746,7 +747,7 @@ IO::add_input_port (string source, void* src, DataType type)
                                snprintf (name, sizeof (name), _("%s/in %u"), _name.c_str(), find_input_port_hole());
                        }
 
-                       if ((our_port = _session.engine().register_input_port (Jack, type, name)) == 0) {
+                       if ((our_port = _session.engine().register_input_port (type, name, _public_ports)) == 0) {
                                error << string_compose(_("IO: cannot register input port %1"), name) << endmsg;
                                return -1;
                        }
@@ -854,7 +855,7 @@ IO::ensure_inputs_locked (ChanCount count, bool clear, void* src)
 
                        try {
 
-                               if ((input_port = _session.engine().register_input_port (Jack, *t, buf)) == 0) {
+                               if ((input_port = _session.engine().register_input_port (*t, buf, _public_ports)) == 0) {
                                        error << string_compose(_("IO: cannot register input port %1"), buf) << endmsg;
                                        return -1;
                                }
@@ -970,7 +971,7 @@ IO::ensure_io (ChanCount in, ChanCount out, bool clear, void* src)
                                }
 
                                try {
-                                       if ((port = _session.engine().register_input_port (Jack, *t, buf)) == 0) {
+                                       if ((port = _session.engine().register_input_port (*t, buf, _public_ports)) == 0) {
                                                error << string_compose(_("IO: cannot register input port %1"), buf) << endmsg;
                                                return -1;
                                        }
@@ -1002,7 +1003,7 @@ IO::ensure_io (ChanCount in, ChanCount out, bool clear, void* src)
                                }
 
                                try { 
-                                       if ((port = _session.engine().register_output_port (Jack, *t, buf)) == 0) {
+                                       if ((port = _session.engine().register_output_port (*t, buf, _public_ports)) == 0) {
                                                error << string_compose(_("IO: cannot register output port %1"), buf) << endmsg;
                                                return -1;
                                        }
@@ -1122,7 +1123,7 @@ IO::ensure_outputs_locked (ChanCount count, bool clear, void* src)
                                snprintf (buf, sizeof (buf), _("%s/out %u"), _name.c_str(), find_output_port_hole());
                        }
 
-                       if ((output_port = _session.engine().register_output_port (Jack, *t, buf)) == 0) {
+                       if ((output_port = _session.engine().register_output_port (*t, buf, _public_ports)) == 0) {
                                error << string_compose(_("IO: cannot register output port %1"), buf) << endmsg;
                                return -1;
                        }
@@ -1241,6 +1242,8 @@ IO::state (bool full_state)
        XMLNode* node = new XMLNode (state_node_name);
        char buf[64];
        string str;
+       vector<string>::iterator ci;
+       int n;
        LocaleGuard lg (X_("POSIX"));
        Glib::Mutex::Lock lm (io_lock);
 
@@ -1274,12 +1277,13 @@ IO::state (bool full_state)
 
        for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
                        
-               const char **connections = i->get_connections();
-               
-               if (connections && connections[0]) {
+               vector<string> connections;
+
+               if (i->get_connections (connections)) {
+
                        str += '{';
                        
-                       for (int n = 0; connections && connections[n]; ++n) {
+                       for (n = 0, ci = connections.begin(); ci != connections.end(); ++ci, ++n) {
                                if (n) {
                                        str += ',';
                                }
@@ -1291,14 +1295,12 @@ IO::state (bool full_state)
                                   client name is different.
                                */
                                
-                               str += _session.engine().make_port_name_relative (connections[n]);
+                               str += _session.engine().make_port_name_relative (*ci);
                        }       
                        
                        str += '}';
-                       
-                       free (connections);
-               }
-               else {
+
+               } else {
                        str += "{}";
                }
        }
@@ -1309,25 +1311,23 @@ IO::state (bool full_state)
        
        for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
                
-               const char **connections = i->get_connections();
-               
-               if (connections && connections[0]) {
+               vector<string> connections;
+
+               if (i->get_connections (connections)) {
                        
                        str += '{';
                        
-                       for (int n = 0; connections[n]; ++n) {
+                       for (n = 0, ci = connections.begin(); ci != connections.end(); ++ci, ++n) {
                                if (n) {
                                        str += ',';
                                }
                                
-                               str += _session.engine().make_port_name_relative (connections[n]);
+                               str += _session.engine().make_port_name_relative (*ci);
                        }
                        
                        str += '}';
-                       
-                       free (connections);
-               }
-               else {
+
+               } else {
                        str += "{}";
                }
        }
index e4bdcb5d720baa4f9666d9cc3f4db18c6711f314..3a0b34ab195a5e95d2f15fec781e3d2c016da49a 100644 (file)
 
 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;
 }
+
index ed999f187af9d5ef7a8eb6eefe708740ffe86723..e943a6a190ac2270ea8f997410743f2871324a51 100644 (file)
 #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;
 }
index c7d737ca0f5987db99fa16728efa9fb254bd6250..c4705816e9a08d0e3865ce5020ec5982686775f4 100644 (file)
@@ -28,10 +28,8 @@ using namespace ARDOUR;
 using namespace PBD;
 using namespace std;
 
-AudioEngine* JackPort::engine = 0;
-
 JackPort::JackPort (const std::string& name, DataType type, Flags flgs) 
-       : Port (type, flgs), _port (0)
+       : Port (name, flgs), _port (0)
 {
        _port = jack_port_register (engine->jack(), name.c_str(), type.to_jack_type(), flgs, 0);
 
@@ -39,6 +37,8 @@ JackPort::JackPort (const std::string& name, DataType type, Flags flgs)
                throw failed_constructor();
        }
        
+       _flags = flgs;
+       _type  = type;
        _name = jack_port_name (_port);
 }
 
@@ -50,7 +50,7 @@ JackPort::~JackPort ()
 }
 
 int 
-JackPort::set_name (string str)
+JackPort::set_name (const string& str)
 {
        int ret;
 
@@ -67,12 +67,6 @@ JackPort::disconnect ()
        return jack_port_disconnect (engine->jack(), _port);
 }      
 
-void
-JackPort::set_engine (AudioEngine* e)
-{
-       engine = e;
-}
-
 nframes_t
 JackPort::total_latency () const
 {
@@ -107,4 +101,79 @@ JackPort::recompute_total_latency () const
 #endif
 }
 
+int
+JackPort::reconnect ()
+{
+       /* caller must hold process lock; intended to be used only after reestablish() */
+
+       for (set<string>::iterator i = _named_connections.begin(); i != _named_connections.end(); ++i) {
+               if (connect (*i)) {
+                       return -1;
+               }
+       }
+
+       return 0;
+}
+
+int
+JackPort::connect (const std::string& other)
+{
+       int ret;
+
+       if (_flags & IsOutput) {
+               /* this is the source */
+               ret = jack_connect (engine->jack(), _name.c_str(), other.c_str());
+       } else {
+               ret = jack_connect (engine->jack(), other.c_str(), _name.c_str());
+       }
+
+       if (ret == 0) {
+               _named_connections.insert (other);
+       }
+       
+       return ret;
+}
+
+int
+JackPort::disconnect (const std::string& other)
+{
+       int ret;
+
+       if (_flags & IsInput) {
+               ret = jack_disconnect (engine->jack(), _name.c_str(), other.c_str());
+       } else {
+               ret = jack_disconnect (engine->jack(), other.c_str(), _name.c_str());
+       }
+
+       set<string>::iterator i = _named_connections.find (other);
+
+       if (i != _named_connections.end()) {
+               _named_connections.erase (i);
+       }
+
+       return ret;
+}
+
+int
+JackPort::disconnect_all ()
+{
+       _named_connections.clear ();
+       return jack_port_disconnect (engine->jack(), _port);
+}
+
+int
+JackPort::get_connections (vector<string>& names) const
+{
+       const char** cstrs =  jack_port_get_connections (_port);
+       int i;
+       
+       if (!cstrs) {
+               return 0;
+       }
+       
+       for (i = 0; cstrs[i]; ++i) {
+               names.push_back (string (cstrs[i]));
+       }
 
+       return i;
+}
index 52f04eaf910a9162ee6fa1d2aefd9ee75e0d30aa..a629fe458f4855e31354d81578fd2bacf85e1162 100644 (file)
@@ -27,20 +27,30 @@ static const int CPU_CACHE_ALIGN = 16; /* arguably 32 on most arches, but it mat
 #endif
 
 using namespace std;
-
-namespace ARDOUR {
+using namespace ARDOUR;
 
 
 // FIXME: mirroring for MIDI buffers?
 MidiBuffer::MidiBuffer(size_t capacity)
        : Buffer(DataType::MIDI, capacity)
-//     , _owns_data(true)
-       , _events(NULL)
-       , _data(NULL)
+       , _events(0)
+       , _data(0)
+//     , _owns_data(false)
+{
+       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
-
index 661df2ce546477389db9097409f4f7ab5983b3fc..8fb66255d81350b54fdcf614edfb287cd142f725 100644 (file)
 #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);
+       }
+}
index 3e57037d6fb66a449425fab092a2d42c14500ee5..ac8e4d05e32b81783cf0178107c5c0b04ed8013b 100644 (file)
@@ -269,7 +269,7 @@ BaseStereoPanner::distribute (AudioBuffer& srcbuf, BufferSet& obufs, gain_t gain
                
                pan = left * gain_coeff;
 
-               mix_buffers_with_gain(dst+n,src+n,nframes-n,pan);
+               mix_buffers_with_gain (dst+n,src+n,nframes-n,pan);
                
        } else {
                
index 1a31124c735bb261962c6d8f748af8b8a4d16091..1c79e0c4388cada25e5a51698ac685c588044469 100644 (file)
 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 ();
+       }
+}
index 3a657bc0e2fdf1b2eb23fcbf4b52c3c3928b756a..89d4e3ed79fb3143547c95d6ef5be76048ea2522 100644 (file)
@@ -250,7 +250,7 @@ SourceFactory::createWritable (DataType type, Session& s, std::string path, bool
                                                (destructive ? AudioFileSource::Flag (SndFileSource::default_writable_flags | AudioFileSource::Destructive) :
                                                 SndFileSource::default_writable_flags)));      
 
-               if (setup_peakfile (ret, false)) {
+               if (setup_peakfile (ret, defer_peaks)) {
                        return boost::shared_ptr<Source>();
                }