summaryrefslogtreecommitdiff
path: root/libs
diff options
context:
space:
mode:
authorPaul Davis <paul@linuxaudiosystems.com>2009-06-16 14:58:33 +0000
committerPaul Davis <paul@linuxaudiosystems.com>2009-06-16 14:58:33 +0000
commit86f24d20e1616ffaafc97de65db49fd6a91270f8 (patch)
tree17f4ac15f4ec6124e82482624f57ed2ceb8f81ca /libs
parent9c8ee46c764f036707f45ebfa8f6696a9a6e56c6 (diff)
first pass (ok, third really) at internal send+return - audio routing inside ardour without JACK. lots still to do, but at least the obvious works
git-svn-id: svn://localhost/ardour2/branches/3.0@5202 d708f5d6-7413-0410-9779-e7cbd77b26cf
Diffstat (limited to 'libs')
-rw-r--r--libs/ardour/ardour/ardour.h1
-rw-r--r--libs/ardour/ardour/audio_buffer.h7
-rw-r--r--libs/ardour/ardour/buffer.h1
-rw-r--r--libs/ardour/ardour/buffer_set.h2
-rw-r--r--libs/ardour/ardour/delivery.h6
-rw-r--r--libs/ardour/ardour/internal_return.h60
-rw-r--r--libs/ardour/ardour/internal_send.h57
-rw-r--r--libs/ardour/ardour/io_processor.h3
-rw-r--r--libs/ardour/ardour/meter.h1
-rw-r--r--libs/ardour/ardour/midi_buffer.h1
-rw-r--r--libs/ardour/ardour/processor.h3
-rw-r--r--libs/ardour/ardour/rc_configuration_vars.h2
-rw-r--r--libs/ardour/ardour/region.h6
-rw-r--r--libs/ardour/ardour/return.h4
-rw-r--r--libs/ardour/ardour/route.h25
-rw-r--r--libs/ardour/ardour/send.h4
-rw-r--r--libs/ardour/ardour/session.h13
-rw-r--r--libs/ardour/audioengine.cc30
-rw-r--r--libs/ardour/audioregion.cc8
-rw-r--r--libs/ardour/buffer_set.cc27
-rw-r--r--libs/ardour/delivery.cc61
-rw-r--r--libs/ardour/enums.cc2
-rw-r--r--libs/ardour/globals.cc6
-rw-r--r--libs/ardour/internal_return.cc136
-rw-r--r--libs/ardour/internal_send.cc192
-rw-r--r--libs/ardour/io_processor.cc46
-rw-r--r--libs/ardour/meter.cc5
-rw-r--r--libs/ardour/midi_buffer.cc11
-rw-r--r--libs/ardour/panner.cc4
-rw-r--r--libs/ardour/processor.cc14
-rw-r--r--libs/ardour/region.cc18
-rw-r--r--libs/ardour/region_factory.cc12
-rw-r--r--libs/ardour/return.cc9
-rw-r--r--libs/ardour/route.cc367
-rw-r--r--libs/ardour/send.cc10
-rw-r--r--libs/ardour/session.cc164
-rw-r--r--libs/ardour/session_state.cc1
-rw-r--r--libs/ardour/wscript4
38 files changed, 972 insertions, 351 deletions
diff --git a/libs/ardour/ardour/ardour.h b/libs/ardour/ardour/ardour.h
index 630bde675c..892df2eb50 100644
--- a/libs/ardour/ardour/ardour.h
+++ b/libs/ardour/ardour/ardour.h
@@ -47,6 +47,7 @@ namespace ARDOUR {
int init (bool with_vst, bool try_optimization);
int cleanup ();
+ bool no_auto_connect ();
std::string get_ardour_revision ();
diff --git a/libs/ardour/ardour/audio_buffer.h b/libs/ardour/ardour/audio_buffer.h
index ca1b36e0b1..be1af03061 100644
--- a/libs/ardour/ardour/audio_buffer.h
+++ b/libs/ardour/ardour/audio_buffer.h
@@ -56,6 +56,13 @@ public:
}
_written = true;
}
+
+ /** Acumulate (add) @a len frames @a src starting at @a src_offset into self starting at @ dst_offset*/
+ void merge_from (const Buffer& src, nframes_t len, nframes_t dst_offset = 0, nframes_t src_offset = 0) {
+ const AudioBuffer* ab = dynamic_cast<const AudioBuffer*>(&src);
+ assert (ab);
+ accumulate_from (*ab, len, dst_offset, src_offset);
+ }
/** Acumulate (add) @a len frames @a src starting at @a src_offset into self starting at @ dst_offset*/
void accumulate_from (const AudioBuffer& src, nframes_t len, nframes_t dst_offset = 0, nframes_t src_offset = 0) {
diff --git a/libs/ardour/ardour/buffer.h b/libs/ardour/ardour/buffer.h
index da75556877..8ed054923b 100644
--- a/libs/ardour/ardour/buffer.h
+++ b/libs/ardour/ardour/buffer.h
@@ -76,6 +76,7 @@ public:
virtual void clear() { silence(_capacity, 0); }
virtual void read_from (const Buffer& src, nframes_t len, nframes_t dst_offset = 0, nframes_t src_offset = 0) = 0;
+ virtual void merge_from (const Buffer& src, nframes_t len, nframes_t dst_offset = 0, nframes_t src_offset = 0) = 0;
protected:
Buffer(DataType type, size_t capacity)
diff --git a/libs/ardour/ardour/buffer_set.h b/libs/ardour/ardour/buffer_set.h
index 3f10929fe8..ecd4e4ab72 100644
--- a/libs/ardour/ardour/buffer_set.h
+++ b/libs/ardour/ardour/buffer_set.h
@@ -68,6 +68,7 @@ public:
void is_silent(bool yn) { _is_silent = yn; }
bool is_silent() const { return _is_silent; }
+ void silence (nframes_t nframes, nframes_t offset);
void set_count(const ChanCount& count) { assert(count <= _available); _count = count; }
@@ -94,6 +95,7 @@ public:
#endif
void read_from(BufferSet& in, nframes_t nframes);
+ void merge_from(BufferSet& in, nframes_t nframes);
// ITERATORS
// FIXME: possible to combine these? templates?
diff --git a/libs/ardour/ardour/delivery.h b/libs/ardour/ardour/delivery.h
index c875f23fcc..32ecc98215 100644
--- a/libs/ardour/ardour/delivery.h
+++ b/libs/ardour/ardour/delivery.h
@@ -40,7 +40,13 @@ public:
Main = 0x8
};
+ /* Delivery to an existing output */
+
Delivery (Session& s, boost::shared_ptr<IO> io, boost::shared_ptr<MuteMaster> mm, const std::string& name, Role);
+ Delivery (Session& s, boost::shared_ptr<IO> io, boost::shared_ptr<MuteMaster> mm, const XMLNode&);
+
+ /* Delivery to a new output owned by this object */
+
Delivery (Session& s, boost::shared_ptr<MuteMaster> mm, const std::string& name, Role);
Delivery (Session&, boost::shared_ptr<MuteMaster> mm, const XMLNode&);
diff --git a/libs/ardour/ardour/internal_return.h b/libs/ardour/ardour/internal_return.h
new file mode 100644
index 0000000000..6aa8bfe7b4
--- /dev/null
+++ b/libs/ardour/ardour/internal_return.h
@@ -0,0 +1,60 @@
+/*
+ Copyright (C) 2009 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#ifndef __ardour_internal_return_h__
+#define __ardour_internal_return_h__
+
+#include <sigc++/signal.h>
+
+#include "ardour/ardour.h"
+#include "ardour/return.h"
+#include "ardour/buffer_set.h"
+
+namespace ARDOUR {
+
+class InternalReturn : public Return
+{
+ public:
+ InternalReturn (Session&);
+ InternalReturn (Session&, const XMLNode&);
+
+ XMLNode& state(bool full);
+ XMLNode& get_state(void);
+ int set_state(const XMLNode& node);
+
+ void run (BufferSet& bufs, sframes_t start_frame, sframes_t end_frame, nframes_t nframes);
+ bool configure_io (ChanCount in, ChanCount out);
+ bool can_support_io_configuration (const ChanCount& in, ChanCount& out) const;
+ void set_block_size (nframes_t);
+
+ BufferSet* get_buffers();
+ void release_buffers();
+
+ static sigc::signal<void,nframes_t> CycleStart;
+
+ private:
+ BufferSet buffers;
+ uint32_t user_count;
+ void allocate_buffers (nframes_t);
+ void cycle_start (nframes_t);
+};
+
+} // namespace ARDOUR
+
+#endif /* __ardour_internal_return_h__ */
diff --git a/libs/ardour/ardour/internal_send.h b/libs/ardour/ardour/internal_send.h
new file mode 100644
index 0000000000..0bbb75d685
--- /dev/null
+++ b/libs/ardour/ardour/internal_send.h
@@ -0,0 +1,57 @@
+/*
+ Copyright (C) 2009 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#ifndef __ardour_internal_send_h__
+#define __ardour_internal_send_h__
+
+#include "ardour/ardour.h"
+#include "ardour/send.h"
+
+namespace ARDOUR {
+
+class InternalSend : public Send
+{
+ public:
+ InternalSend (Session&, boost::shared_ptr<MuteMaster>, boost::shared_ptr<Route> send_to);
+ InternalSend (Session&, boost::shared_ptr<MuteMaster>, const XMLNode&);
+ virtual ~InternalSend ();
+
+ XMLNode& state(bool full);
+ XMLNode& get_state(void);
+ int set_state(const XMLNode& node);
+
+ void run (BufferSet& bufs, sframes_t start_frame, sframes_t end_frame, nframes_t nframes);
+ bool feeds (boost::shared_ptr<Route> other) const;
+ bool can_support_io_configuration (const ChanCount& in, ChanCount& out) const;
+
+ boost::shared_ptr<Route> target_route() const { return _send_to; }
+
+ private:
+ BufferSet* target;
+ boost::shared_ptr<Route> _send_to;
+ PBD::ID _send_to_id;
+ sigc::connection connect_c;
+
+ void send_to_going_away ();
+ int connect_when_legal ();
+};
+
+} // namespace ARDOUR
+
+#endif /* __ardour_send_h__ */
diff --git a/libs/ardour/ardour/io_processor.h b/libs/ardour/ardour/io_processor.h
index 14d88d6b44..430f54d46d 100644
--- a/libs/ardour/ardour/io_processor.h
+++ b/libs/ardour/ardour/io_processor.h
@@ -37,6 +37,7 @@ namespace ARDOUR {
class Session;
class IO;
+class Route;
/** A mixer strip element (Processor) with 1 or 2 IO elements.
*/
@@ -66,6 +67,8 @@ class IOProcessor : public Processor
void silence (nframes_t nframes);
+ virtual bool feeds (boost::shared_ptr<Route> other) const;
+
sigc::signal<void,IOProcessor*,bool> AutomationPlaybackChanged;
sigc::signal<void,IOProcessor*,uint32_t> AutomationChanged;
diff --git a/libs/ardour/ardour/meter.h b/libs/ardour/ardour/meter.h
index 57afcc39ca..414b559de0 100644
--- a/libs/ardour/ardour/meter.h
+++ b/libs/ardour/ardour/meter.h
@@ -51,6 +51,7 @@ class Metering {
class PeakMeter : public Processor {
public:
PeakMeter(Session& s) : Processor(s, "Meter") {}
+ PeakMeter(Session&s, const XMLNode& node);
void meter();
diff --git a/libs/ardour/ardour/midi_buffer.h b/libs/ardour/ardour/midi_buffer.h
index 64417cae26..4e27e33235 100644
--- a/libs/ardour/ardour/midi_buffer.h
+++ b/libs/ardour/ardour/midi_buffer.h
@@ -39,6 +39,7 @@ public:
void silence (nframes_t nframes, nframes_t offset = 0);
void read_from (const Buffer& src, nframes_t nframes, nframes_t dst_offset = 0, nframes_t src_offset = 0);
+ void merge_from (const Buffer& src, nframes_t nframes, nframes_t dst_offset = 0, nframes_t src_offset = 0);
void copy(const MidiBuffer& copy);
diff --git a/libs/ardour/ardour/processor.h b/libs/ardour/ardour/processor.h
index 06fcb81ce7..f91e9a6863 100644
--- a/libs/ardour/ardour/processor.h
+++ b/libs/ardour/ardour/processor.h
@@ -50,7 +50,8 @@ class Processor : public SessionObject, public AutomatableControls, public Laten
static const std::string state_node_name;
Processor(Session&, const std::string& name);
-
+ Processor(Session&, const XMLNode& node);
+
virtual ~Processor() { }
virtual bool visible() const { return true; }
diff --git a/libs/ardour/ardour/rc_configuration_vars.h b/libs/ardour/ardour/rc_configuration_vars.h
index 7387e5d001..3f063f4692 100644
--- a/libs/ardour/ardour/rc_configuration_vars.h
+++ b/libs/ardour/ardour/rc_configuration_vars.h
@@ -19,7 +19,7 @@
/* IO connection */
-CONFIG_VARIABLE (bool, auto_connect_master, "auto-connect-master", true)
+CONFIG_VARIABLE (bool, auto_connect_standard_busses, "auto-connect-standard-busses", true)
CONFIG_VARIABLE (AutoConnectOption, output_auto_connect, "output-auto-connect", AutoConnectOption (0))
CONFIG_VARIABLE (AutoConnectOption, input_auto_connect, "input-auto-connect", AutoConnectOption (0))
diff --git a/libs/ardour/ardour/region.h b/libs/ardour/ardour/region.h
index aa768e269f..d2cc252d61 100644
--- a/libs/ardour/ardour/region.h
+++ b/libs/ardour/ardour/region.h
@@ -74,7 +74,7 @@ class Region
LeftOfSplit = 0x4000,
RightOfSplit = 0x8000,
Hidden = 0x10000,
- DoNotSaveState = 0x20000,
+ DoNotSendPropertyChanges = 0x20000,
PositionLocked = 0x40000,
//
range_guarantoor = USHRT_MAX
@@ -97,6 +97,8 @@ class Region
sigc::signal<void,Change> StateChanged;
static sigc::signal<void,boost::shared_ptr<ARDOUR::Region> > RegionPropertyChanged;
+ void unlock_property_changes () { _flags = Flag (_flags & ~DoNotSendPropertyChanges); }
+ void block_property_changes () { _flags = Flag (_flags | DoNotSendPropertyChanges); }
virtual ~Region();
@@ -160,8 +162,6 @@ class Region
void set_position_lock_style (PositionLockStyle ps);
void recompute_position_from_lock_style ();
- virtual bool should_save_state () const { return !(_flags & DoNotSaveState); };
-
void freeze ();
void thaw (const std::string& why);
diff --git a/libs/ardour/ardour/return.h b/libs/ardour/ardour/return.h
index 3f75cc57b7..8f8a84f321 100644
--- a/libs/ardour/ardour/return.h
+++ b/libs/ardour/ardour/return.h
@@ -38,8 +38,8 @@ class PeakMeter;
class Return : public IOProcessor
{
public:
- Return (Session&);
- Return (Session&, const XMLNode&);
+ Return (Session&, bool internal = false);
+ Return (Session&, const XMLNode&, bool internal = false);
virtual ~Return ();
uint32_t bit_slot() const { return _bitslot; }
diff --git a/libs/ardour/ardour/route.h b/libs/ardour/ardour/route.h
index 2a3580b187..339f18ef3f 100644
--- a/libs/ardour/ardour/route.h
+++ b/libs/ardour/ardour/route.h
@@ -52,6 +52,7 @@ class Panner;
class Processor;
class RouteGroup;
class Send;
+class InternalReturn;
class Route : public SessionObject, public AutomatableControls
{
@@ -183,18 +184,17 @@ class Route : public SessionObject, public AutomatableControls
}
}
- ProcessorList::iterator prefader_iterator();
-
ChanCount max_processor_streams () const { return processor_max_streams; }
- ChanCount pre_fader_streams() const;
/* special processors */
- boost::shared_ptr<Delivery> control_outs() const { return _control_outs; }
- boost::shared_ptr<Delivery> main_outs() const { return _main_outs; }
-
- boost::shared_ptr<Send> send_for (boost::shared_ptr<const IO> target) const;
-
+ boost::shared_ptr<Delivery> control_outs() const { return _control_outs; }
+ boost::shared_ptr<Delivery> main_outs() const { return _main_outs; }
+ boost::shared_ptr<InternalReturn> internal_return() const { return _intreturn; }
+ boost::shared_ptr<Send> internal_send_for (boost::shared_ptr<const Route> target) const;
+ BufferSet* get_return_buffer () const;
+ void release_return_buffer () const;
+
/** A record of the stream configuration at some point in the processor list.
* Used to return where and why an processor list configuration request failed.
*/
@@ -262,10 +262,10 @@ class Route : public SessionObject, public AutomatableControls
sigc::signal<void,void*> SelectedChanged;
- int listen_via (boost::shared_ptr<IO>, const std::string& name);
- void drop_listen (boost::shared_ptr<IO>);
+ int listen_via (boost::shared_ptr<Route>, const std::string& name);
+ void drop_listen (boost::shared_ptr<Route>);
- bool feeds (boost::shared_ptr<IO>);
+ bool feeds (boost::shared_ptr<Route>);
std::set<boost::shared_ptr<Route> > fed_by;
/* Controls (not all directly owned by the Route */
@@ -341,6 +341,7 @@ class Route : public SessionObject, public AutomatableControls
mutable Glib::RWLock _processor_lock;
boost::shared_ptr<Delivery> _main_outs;
boost::shared_ptr<Delivery> _control_outs; // XXX to be removed/generalized by listen points
+ boost::shared_ptr<InternalReturn> _intreturn;
Flag _flags;
int _pending_declick;
@@ -381,8 +382,6 @@ class Route : public SessionObject, public AutomatableControls
virtual int _set_state (const XMLNode&, bool call_base);
- boost::shared_ptr<Delivery> add_listener (boost::shared_ptr<IO>, const std::string&);
-
boost::shared_ptr<Amp> _amp;
boost::shared_ptr<PeakMeter> _meter;
sigc::connection _meter_connection;
diff --git a/libs/ardour/ardour/send.h b/libs/ardour/ardour/send.h
index 3a0eae21e5..37d56e2abd 100644
--- a/libs/ardour/ardour/send.h
+++ b/libs/ardour/ardour/send.h
@@ -37,8 +37,8 @@ class Amp;
class Send : public Delivery
{
public:
- Send (Session&, boost::shared_ptr<MuteMaster>);
- Send (Session&, boost::shared_ptr<MuteMaster>, const XMLNode&);
+ Send (Session&, boost::shared_ptr<MuteMaster>, bool internal = false);
+ Send (Session&, boost::shared_ptr<MuteMaster>, const XMLNode&, bool internal = false);
virtual ~Send ();
uint32_t bit_slot() const { return _bitslot; }
diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h
index 2e161ff776..e970d6e9e4 100644
--- a/libs/ardour/ardour/session.h
+++ b/libs/ardour/ardour/session.h
@@ -747,12 +747,6 @@ class Session : public PBD::StatefulDestructible, public boost::noncopyable
boost::shared_ptr<Route> control_out() const { return _control_out; }
boost::shared_ptr<Route> master_out() const { return _master_out; }
- /* insert/send management */
-
- uint32_t n_port_inserts() const { return _port_inserts.size(); }
- uint32_t n_plugin_inserts() const { return _plugin_inserts.size(); }
- uint32_t n_sends() const { return _sends.size(); }
-
static void set_disable_all_loaded_plugins (bool yn) {
_disable_all_loaded_plugins = yn;
}
@@ -1558,16 +1552,9 @@ class Session : public PBD::StatefulDestructible, public boost::noncopyable
/* INSERT AND SEND MANAGEMENT */
- std::list<PortInsert *> _port_inserts;
- std::list<PluginInsert *> _plugin_inserts;
- std::list<Send *> _sends;
- std::list<Return *> _returns;
boost::dynamic_bitset<uint32_t> send_bitset;
boost::dynamic_bitset<uint32_t> return_bitset;
boost::dynamic_bitset<uint32_t> insert_bitset;
- uint32_t send_cnt;
- uint32_t insert_cnt;
-
void add_processor (Processor *);
void remove_processor (Processor *);
diff --git a/libs/ardour/audioengine.cc b/libs/ardour/audioengine.cc
index 4e2d97f718..4143cb109a 100644
--- a/libs/ardour/audioengine.cc
+++ b/libs/ardour/audioengine.cc
@@ -31,23 +31,23 @@
#include "midi++/jack.h"
+#include "ardour/amp.h"
+#include "ardour/audio_port.h"
#include "ardour/audioengine.h"
#include "ardour/buffer.h"
-#include "ardour/delivery.h"
-#include "ardour/port.h"
-#include "ardour/audio_port.h"
-#include "ardour/midi_port.h"
-#include "ardour/meter.h"
-#include "ardour/session.h"
+#include "ardour/buffer_set.h"
#include "ardour/cycle_timer.h"
-#include "ardour/utils.h"
+#include "ardour/delivery.h"
#include "ardour/event_type_map.h"
+#include "ardour/internal_return.h"
#include "ardour/io.h"
-#include "ardour/amp.h"
+#include "ardour/meter.h"
+#include "ardour/midi_port.h"
+#include "ardour/port.h"
#include "ardour/port_set.h"
-#include "ardour/buffer_set.h"
-
+#include "ardour/session.h"
#include "ardour/timestamps.h"
+#include "ardour/utils.h"
#include "i18n.h"
@@ -364,6 +364,7 @@ AudioEngine::process_callback (nframes_t nframes)
Delivery::CycleStart (nframes);
Port::set_port_offset (0);
+ InternalReturn::CycleStart (nframes);
/* tell all Ports that we're starting a new cycle */
@@ -822,10 +823,15 @@ AudioEngine::frames_per_cycle ()
Port *
AudioEngine::get_port_by_name (const string& portname)
{
- assert (portname.find_first_of (':') != string::npos);
+ string s;
+ if (portname.find_first_of (':') == string::npos) {
+ s = make_port_name_non_relative (portname);
+ } else {
+ s = portname;
+ }
Glib::Mutex::Lock lm (_process_lock);
- return get_port_by_name_locked (portname);
+ return get_port_by_name_locked (s);
}
Port *
diff --git a/libs/ardour/audioregion.cc b/libs/ardour/audioregion.cc
index 25948e595c..5743bae935 100644
--- a/libs/ardour/audioregion.cc
+++ b/libs/ardour/audioregion.cc
@@ -655,6 +655,14 @@ AudioRegion::set_live_state (const XMLNode& node, Change& what_changed, bool sen
_flags = Flag (_flags & ~Region::RightOfSplit);
}
+ /* leave this flag setting in place, no matter what */
+
+ if ((old_flags & DoNotSendPropertyChanges)) {
+ _flags = Flag (_flags | DoNotSendPropertyChanges);
+ }
+
+ /* find out if any flags changed that we signal about */
+
if ((old_flags ^ _flags) & Muted) {
what_changed = Change (what_changed|MuteChanged);
}
diff --git a/libs/ardour/buffer_set.cc b/libs/ardour/buffer_set.cc
index 005a4dae65..319444e1b9 100644
--- a/libs/ardour/buffer_set.cc
+++ b/libs/ardour/buffer_set.cc
@@ -225,5 +225,32 @@ BufferSet::read_from (BufferSet& in, nframes_t nframes)
set_count(in.count());
}
+// FIXME: make 'in' const
+void
+BufferSet::merge_from (BufferSet& in, nframes_t nframes)
+{
+ assert(available() >= in.count());
+
+ /* merge all input buffers into out existing buffers */
+ for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
+ BufferSet::iterator o = begin(*t);
+ for (BufferSet::iterator i = in.begin(*t); i != in.end(*t); ++i, ++o) {
+ o->merge_from (*i, nframes);
+ }
+ }
+
+ set_count (in.count());
+}
+
+void
+BufferSet::silence (nframes_t nframes, nframes_t offset)
+{
+ for (std::vector<BufferVec>::iterator i = _buffers.begin(); i != _buffers.end(); ++i) {
+ for (BufferVec::iterator b = i->begin(); b != i->end(); ++b) {
+ (*b)->silence (nframes, offset);
+ }
+ }
+}
+
} // namespace ARDOUR
diff --git a/libs/ardour/delivery.cc b/libs/ardour/delivery.cc
index 0a49a47a7f..a4a76c37ae 100644
--- a/libs/ardour/delivery.cc
+++ b/libs/ardour/delivery.cc
@@ -47,7 +47,7 @@ bool Delivery::panners_legal = false;
/* deliver to an existing IO object */
Delivery::Delivery (Session& s, boost::shared_ptr<IO> io, boost::shared_ptr<MuteMaster> mm, const string& name, Role r)
- : IOProcessor(s, boost::shared_ptr<IO>(), io, name)
+ : IOProcessor(s, boost::shared_ptr<IO>(), (r == Listen ? boost::shared_ptr<IO>() : io), name)
, _role (r)
, _output_buffers (new BufferSet())
, _solo_level (0)
@@ -58,13 +58,15 @@ Delivery::Delivery (Session& s, boost::shared_ptr<IO> io, boost::shared_ptr<Mute
_current_gain = 1.0;
_panner = boost::shared_ptr<Panner>(new Panner (_name, _session));
- _output->changed.connect (mem_fun (*this, &Delivery::output_changed));
+ if (_output) {
+ _output->changed.connect (mem_fun (*this, &Delivery::output_changed));
+ }
}
/* deliver to a new IO object */
Delivery::Delivery (Session& s, boost::shared_ptr<MuteMaster> mm, const string& name, Role r)
- : IOProcessor(s, false, true, name)
+ : IOProcessor(s, false, (r == Listen ? false : true), name)
, _role (r)
, _output_buffers (new BufferSet())
, _solo_level (0)
@@ -75,7 +77,9 @@ Delivery::Delivery (Session& s, boost::shared_ptr<MuteMaster> mm, const string&
_current_gain = 1.0;
_panner = boost::shared_ptr<Panner>(new Panner (_name, _session));
- _output->changed.connect (mem_fun (*this, &Delivery::output_changed));
+ if (_output) {
+ _output->changed.connect (mem_fun (*this, &Delivery::output_changed));
+ }
}
/* deliver to a new IO object, reconstruct from XML */
@@ -96,7 +100,32 @@ Delivery::Delivery (Session& s, boost::shared_ptr<MuteMaster> mm, const XMLNode&
throw failed_constructor ();
}
- _output->changed.connect (mem_fun (*this, &Delivery::output_changed));
+ if (_output) {
+ _output->changed.connect (mem_fun (*this, &Delivery::output_changed));
+ }
+}
+
+/* deliver to an existing IO object, reconstruct from XML */
+
+Delivery::Delivery (Session& s, boost::shared_ptr<IO> out, boost::shared_ptr<MuteMaster> mm, const XMLNode& node)
+ : IOProcessor (s, boost::shared_ptr<IO>(), out, "reset")
+ , _role (Role (0))
+ , _output_buffers (new BufferSet())
+ , _solo_level (0)
+ , _solo_isolated (false)
+ , _mute_master (mm)
+{
+ _output_offset = 0;
+ _current_gain = 1.0;
+ _panner = boost::shared_ptr<Panner>(new Panner (_name, _session));
+
+ if (set_state (node)) {
+ throw failed_constructor ();
+ }
+
+ if (_output) {
+ _output->changed.connect (mem_fun (*this, &Delivery::output_changed));
+ }
}
void
@@ -265,7 +294,16 @@ Delivery::reset_panner ()
{
if (panners_legal) {
if (!no_panner_reset) {
- _panner->reset (_output->n_ports().n_audio(), pans_required());
+
+ uint32_t ntargets;
+
+ if (_output) {
+ ntargets = _output->n_ports().n_audio();
+ } else {
+ ntargets = _configured_output.n_audio();
+ }
+
+ _panner->reset (ntargets, pans_required());
}
} else {
panner_legal_c.disconnect ();
@@ -276,7 +314,15 @@ Delivery::reset_panner ()
int
Delivery::panners_became_legal ()
{
- _panner->reset (_output->n_ports().n_audio(), pans_required());
+ uint32_t ntargets;
+
+ if (_output) {
+ ntargets = _output->n_ports().n_audio();
+ } else {
+ ntargets = _configured_output.n_audio();
+ }
+
+ _panner->reset (ntargets, pans_required());
_panner->load (); // automation
panner_legal_c.disconnect ();
return 0;
@@ -441,3 +487,4 @@ Delivery::output_changed (IOChange change, void* src)
reset_panner ();
}
}
+
diff --git a/libs/ardour/enums.cc b/libs/ardour/enums.cc
index 6e98fdf5a7..43fb4e4014 100644
--- a/libs/ardour/enums.cc
+++ b/libs/ardour/enums.cc
@@ -396,7 +396,7 @@ setup_enum_writer ()
REGISTER_CLASS_ENUM (Region, LeftOfSplit);
REGISTER_CLASS_ENUM (Region, RightOfSplit);
REGISTER_CLASS_ENUM (Region, Hidden);
- REGISTER_CLASS_ENUM (Region, DoNotSaveState);
+ REGISTER_CLASS_ENUM (Region, DoNotSendPropertyChanges);
REGISTER_BITS (_Region_Flag);
REGISTER_CLASS_ENUM (Region, AudioTime);
diff --git a/libs/ardour/globals.cc b/libs/ardour/globals.cc
index a501e65931..0ce024c31e 100644
--- a/libs/ardour/globals.cc
+++ b/libs/ardour/globals.cc
@@ -430,6 +430,12 @@ ARDOUR::find_bindings_files (map<string,string>& files)
}
}
+bool
+ARDOUR::no_auto_connect()
+{
+ return getenv ("ARDOUR_NO_AUTOCONNECT") != 0;
+}
+
ARDOUR::LocaleGuard::LocaleGuard (const char* str)
{
old = strdup (setlocale (LC_NUMERIC, NULL));
diff --git a/libs/ardour/internal_return.cc b/libs/ardour/internal_return.cc
new file mode 100644
index 0000000000..409c87d93c
--- /dev/null
+++ b/libs/ardour/internal_return.cc
@@ -0,0 +1,136 @@
+/*
+ Copyright (C) 2009 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include <glibmm/thread.h>
+
+#include "pbd/failed_constructor.h"
+
+#include "ardour/internal_return.h"
+#include "ardour/mute_master.h"
+#include "ardour/session.h"
+
+using namespace std;
+using namespace ARDOUR;
+
+sigc::signal<void,nframes_t> InternalReturn::CycleStart;
+
+InternalReturn::InternalReturn (Session& s)
+ : Return (s, true)
+ , user_count (0)
+{
+ CycleStart.connect (mem_fun (*this, &InternalReturn::cycle_start));
+}
+
+InternalReturn::InternalReturn (Session& s, const XMLNode& node)
+ : Return (s, node, true)
+ , user_count (0)
+{
+ CycleStart.connect (mem_fun (*this, &InternalReturn::cycle_start));
+}
+
+void
+InternalReturn::run (BufferSet& bufs, sframes_t start_frame, sframes_t end_frame, nframes_t nframes)
+{
+ if (user_count == 0) {
+ /* nothing to do - nobody is feeding us anything */
+ return;
+ }
+
+ /* XXX this should be merge() */
+
+ bufs.merge_from (buffers, nframes);
+}
+
+bool
+InternalReturn::configure_io (ChanCount in, ChanCount out)
+{
+ IOProcessor::configure_io (in, out);
+ allocate_buffers (_session.get_block_size());
+ return true;
+}
+
+void
+InternalReturn::set_block_size (nframes_t nframes)
+{
+ allocate_buffers (nframes);
+}
+
+void
+InternalReturn::allocate_buffers (nframes_t nframes)
+{
+ buffers.ensure_buffers (DataType::AUDIO, _configured_input.n_audio(), nframes);
+ buffers.ensure_buffers (DataType::MIDI, _configured_input.n_midi(), nframes);
+}
+
+BufferSet*
+InternalReturn::get_buffers ()
+{
+ Glib::Mutex::Lock lm (_session.engine().process_lock());
+ user_count++;
+ return &buffers;
+}
+
+void
+InternalReturn::release_buffers ()
+{
+ Glib::Mutex::Lock lm (_session.engine().process_lock());
+ if (user_count) {
+ user_count--;
+ }
+}
+
+void
+InternalReturn::cycle_start (nframes_t nframes)
+{
+ /* called from process cycle - no lock necessary */
+ if (user_count) {
+ /* don't bother with this if nobody is going to feed us anything */
+ buffers.silence (nframes, 0);
+ }
+}
+
+XMLNode&
+InternalReturn::state (bool full)
+{
+ XMLNode& node (Return::state (full));
+ /* override type */
+ node.add_property("type", "intreturn");
+ return node;
+}
+
+XMLNode&
+InternalReturn::get_state()
+{
+ return state (true);
+}
+
+int
+InternalReturn::set_state (const XMLNode& node)
+{
+ return Return::set_state (node);
+}
+
+bool
+InternalReturn::can_support_io_configuration (const ChanCount& in, ChanCount& out) const
+{
+ out = in;
+ return true;
+}
+
+
+
diff --git a/libs/ardour/internal_send.cc b/libs/ardour/internal_send.cc
new file mode 100644
index 0000000000..398dbca08d
--- /dev/null
+++ b/libs/ardour/internal_send.cc
@@ -0,0 +1,192 @@
+/*
+ Copyright (C) 2009 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include <iostream>
+
+#include "pbd/error.h"
+#include "pbd/failed_constructor.h"
+
+#include "ardour/amp.h"
+#include "ardour/internal_send.h"
+#include "ardour/meter.h"
+#include "ardour/route.h"
+#include "ardour/session.h"
+
+#include "i18n.h"
+
+using namespace PBD;
+using namespace ARDOUR;
+
+InternalSend::InternalSend (Session& s, boost::shared_ptr<MuteMaster> mm, boost::shared_ptr<Route> sendto)
+ : Send (s, mm, true)
+ , _send_to (sendto)
+{
+ if ((target = _send_to->get_return_buffer ()) == 0) {
+ throw failed_constructor();
+ }
+
+ _send_to->GoingAway.connect (mem_fun (*this, &InternalSend::send_to_going_away));
+}
+
+InternalSend::InternalSend (Session& s, boost::shared_ptr<MuteMaster> mm, const XMLNode& node)
+ : Send (s, mm, node, true)
+{
+ set_state (node);
+}
+
+InternalSend::~InternalSend ()
+{
+ if (_send_to) {
+ _send_to->release_return_buffer ();
+ }
+
+ connect_c.disconnect ();
+}
+
+void
+InternalSend::send_to_going_away ()
+{
+ target = 0;
+ _send_to.reset ();
+ _send_to_id = "0";
+}
+
+void
+InternalSend::run (BufferSet& bufs, sframes_t start_frame, sframes_t end_frame, nframes_t nframes)
+{
+ if (!_active || !target || !_send_to) {
+ _meter->reset ();
+ return;
+ }
+
+ // we have to copy the input, because we may alter the buffers with the amp
+ // in-place, which a send must never do.
+
+ BufferSet& sendbufs = _session.get_mix_buffers (bufs.count());
+ sendbufs.read_from (bufs, nframes);
+ assert(sendbufs.count() == bufs.count());
+
+ /* gain control */
+
+ // Can't automate gain for sends or returns yet because we need different buffers
+ // so that we don't overwrite the main automation data for the route amp
+ // _amp->setup_gain_automation (start_frame, end_frame, nframes);
+ _amp->run (sendbufs, start_frame, end_frame, nframes);
+
+ /* consider metering */
+
+ if (_metering) {
+ if (_amp->gain_control()->get_value() == 0) {
+ _meter->reset();
+ } else {
+ _meter->run (sendbufs, start_frame, end_frame, nframes);
+ }
+ }
+
+ /* deliver to target */
+
+ target->merge_from (sendbufs, nframes);
+}
+
+bool
+InternalSend::feeds (boost::shared_ptr<Route> other) const
+{
+ return _send_to == other;
+}
+
+XMLNode&
+InternalSend::state (bool full)
+{
+ XMLNode& node (Send::state (full));
+
+ /* this replaces any existing property */
+
+ node.add_property ("type", "intsend");
+
+ if (_send_to) {
+ node.add_property ("target", _send_to->id().to_s());
+ }
+
+ return node;
+}
+
+XMLNode&
+InternalSend::get_state()
+{
+ return state (true);
+}
+
+int
+InternalSend::set_state (const XMLNode& node)
+{
+ const XMLProperty* prop;
+
+ if ((prop = node.property ("target")) != 0) {
+
+ _send_to_id = prop->value();
+
+ /* if we're loading a session, the target route may not have been
+ create yet. make sure we defer till we are sure that it should
+ exist.
+ */
+
+ if (!IO::connecting_legal) {
+ connect_c = IO::ConnectingLegal.connect (mem_fun (*this, &InternalSend::connect_when_legal));
+ std::cerr << "connect later!\n";
+ } else {
+ std::cerr << "connect NOW!\n";
+ connect_when_legal ();
+ }
+ }
+
+ return 0;
+}
+
+int
+InternalSend::connect_when_legal ()
+{
+ std::cerr << "IOP/send connecting now that its legal\n";
+
+ connect_c.disconnect ();
+
+ if (_send_to_id == "0") {
+ /* it vanished before we could connect */
+ return 0;
+ }
+
+ if ((_send_to = _session.route_by_id (_send_to_id)) == 0) {
+ error << X_("cannot find route to connect to") << endmsg;
+ std::cerr << "cannot find route with ID " << _send_to_id << std::endl;
+ } else {
+ std::cerr << "got target send as " << _send_to << std::endl;
+ }
+
+ if ((target = _send_to->get_return_buffer ()) == 0) {
+ error << X_("target for internal send has no return buffer") << endmsg;
+ }
+
+ return 0;
+}
+
+bool
+InternalSend::can_support_io_configuration (const ChanCount& in, ChanCount& out) const
+{
+ out = in;
+ return true;
+}
diff --git a/libs/ardour/io_processor.cc b/libs/ardour/io_processor.cc
index 7e0d4a771c..cfa2b4c689 100644
--- a/libs/ardour/io_processor.cc
+++ b/libs/ardour/io_processor.cc
@@ -64,6 +64,8 @@ IOProcessor::IOProcessor (Session& s, bool with_input, bool with_output,
if (with_output) {
_output.reset (new IO(s, io_name.empty() ? proc_name : io_name, IO::Output, dtype));
}
+
+ cerr << "fresh create IOP name = " << proc_name << " in = " << _input << " out = " << _output << endl;
}
/* create an IOProcessor that proxies to an existing IO object */
@@ -74,8 +76,18 @@ IOProcessor::IOProcessor (Session& s, boost::shared_ptr<IO> in, boost::shared_pt
, _input (in)
, _output (out)
{
- _own_input = false;
- _own_output = false;
+ cerr << "XML create IOP name = " << proc_name << " in = " << in << " out = " << out << endl;
+ if (in) {
+ _own_input = false;
+ } else {
+ _own_input = true;
+ }
+
+ if (out) {
+ _own_output = false;
+ } else {
+ _own_output = true;
+ }
}
IOProcessor::~IOProcessor ()
@@ -107,10 +119,12 @@ IOProcessor::state (bool full_state)
XMLNode& node (Processor::state (full_state));
if (_own_input) {
- XMLNode& i (_input->state (full_state));
- // i.name() = X_("output");
- node.add_child_nocopy (i);
node.add_property ("own-input", "yes");
+ if (_input) {
+ XMLNode& i (_input->state (full_state));
+ // i.name() = X_("output");
+ node.add_child_nocopy (i);
+ }
} else {
node.add_property ("own-input", "no");
if (_input) {
@@ -119,10 +133,12 @@ IOProcessor::state (bool full_state)
}
if (_own_output) {
- XMLNode& o (_output->state (full_state));
- // o.name() = X_("output");
- node.add_child_nocopy (o);
node.add_property ("own-output", "yes");
+ if (_output) {
+ XMLNode& o (_output->state (full_state));
+ // o.name() = X_("output");
+ node.add_child_nocopy (o);
+ }
} else {
node.add_property ("own-output", "no");
if (_output) {
@@ -173,9 +189,9 @@ IOProcessor::set_state (const XMLNode& node)
}
} else {
- error << _("XML node describing an IOProcessor is missing an IO node") << endmsg;
- return -1;
+ /* no input */
}
+
}
if (_own_output) {
@@ -193,7 +209,9 @@ IOProcessor::set_state (const XMLNode& node)
if ((prop = node.property ("name")) == 0) {
set_name (_output->name());
}
- }
+ } else {
+ /* no output */
+ }
}
return 0;
@@ -246,3 +264,9 @@ IOProcessor::set_name (const std::string& name)
return ret;
}
+
+bool
+IOProcessor::feeds (boost::shared_ptr<Route> other) const
+{
+ return _output && _output->connected_to (other->input());
+}
diff --git a/libs/ardour/meter.cc b/libs/ardour/meter.cc
index 0675e14cef..50bd290754 100644
--- a/libs/ardour/meter.cc
+++ b/libs/ardour/meter.cc
@@ -109,6 +109,11 @@ PeakMeter::run (BufferSet& bufs, sframes_t start_frame, sframes_t end_frame, nfr
}
}
+PeakMeter::PeakMeter (Session& s, const XMLNode& node)
+ : Processor (s, node)
+{
+}
+
void
PeakMeter::reset ()
{
diff --git a/libs/ardour/midi_buffer.cc b/libs/ardour/midi_buffer.cc
index bce47411cd..887545c662 100644
--- a/libs/ardour/midi_buffer.cc
+++ b/libs/ardour/midi_buffer.cc
@@ -99,6 +99,17 @@ MidiBuffer::read_from (const Buffer& src, nframes_t nframes, nframes_t dst_offse
_silent = src.silent();
}
+void
+MidiBuffer::merge_from (const Buffer& src, nframes_t nframes, nframes_t dst_offset, nframes_t src_offset)
+{
+ const MidiBuffer* mbuf = dynamic_cast<const MidiBuffer*>(&src);
+ assert (mbuf);
+ assert (mbuf != this);
+
+ /* XXX use nframes, and possible offsets */
+ merge_in_place (*mbuf);
+}
+
/** Push an event into the buffer.
*
* Note that the raw MIDI pointed to by ev will be COPIED and unmodified.
diff --git a/libs/ardour/panner.cc b/libs/ardour/panner.cc
index bd6d05a0b4..be72f65593 100644
--- a/libs/ardour/panner.cc
+++ b/libs/ardour/panner.cc
@@ -1379,7 +1379,7 @@ Panner::distribute_no_automation (BufferSet& inbufs, BufferSet& outbufs, nframes
if (inbufs.count().n_audio() > 0) {
BufferSet::audio_iterator i = inbufs.audio_begin();
for (++i; i != inbufs.audio_end(); ++i) {
- dst.accumulate_from(*i, nframes);
+ dst.merge_from(*i, nframes);
}
}
@@ -1456,7 +1456,7 @@ Panner::run (BufferSet& inbufs, BufferSet& outbufs, sframes_t start_frame, sfram
// accumulate starting with the second
BufferSet::audio_iterator i = inbufs.audio_begin();
for (++i; i != inbufs.audio_end(); ++i) {
- dst.accumulate_from(*i, nframes);
+ dst.merge_from(*i, nframes);
}
return;
diff --git a/libs/ardour/processor.cc b/libs/ardour/processor.cc
index 2e39c52d67..ab5902efa5 100644
--- a/libs/ardour/processor.cc
+++ b/libs/ardour/processor.cc
@@ -68,6 +68,17 @@ Processor::Processor(Session& session, const string& name)
{
}
+Processor::Processor (Session& session, const XMLNode& node)
+ : SessionObject(session, "renameMe")
+ , AutomatableControls(session)
+ , _active(false)
+ , _next_ab_is_active(false)
+ , _configured(false)
+ , _gui(0)
+{
+ set_state (node);
+}
+
XMLNode&
Processor::get_state (void)
{
@@ -141,6 +152,9 @@ Processor::set_state (const XMLNode& node)
// may not exist for legacy 3.0 sessions
if ((prop = node.property ("id")) != 0) {
_id = prop->value();
+ cerr << "---------------- ID for processor " << name() << " = " << _id << endl;
+ } else {
+ cerr << "---------------- NO ID for processor " << name() << endl;
}
XMLNodeList nlist = node.children();
diff --git a/libs/ardour/region.cc b/libs/ardour/region.cc
index fb662beca3..1754e24b5e 100644
--- a/libs/ardour/region.cc
+++ b/libs/ardour/region.cc
@@ -61,7 +61,7 @@ sigc::signal<void,boost::shared_ptr<ARDOUR::Region> > Region::RegionPropertyChan
Region::Region (Session& s, nframes_t start, nframes_t length, const string& name, DataType type, layer_t layer, Region::Flag flags)
: SessionObject(s, name)
, _type(type)
- , _flags(flags)
+ , _flags(Flag (flags|DoNotSendPropertyChanges))
, _start(start)
, _length(length)
, _position(0)
@@ -86,7 +86,7 @@ Region::Region (Session& s, nframes_t start, nframes_t length, const string& nam
Region::Region (boost::shared_ptr<Source> src, nframes_t start, nframes_t length, const string& name, DataType type, layer_t layer, Region::Flag flags)
: SessionObject(src->session(), name)
, _type(type)
- , _flags(flags)
+ , _flags(Flag (flags|DoNotSendPropertyChanges))
, _start(start)
, _length(length)
, _position(0)
@@ -119,7 +119,7 @@ Region::Region (boost::shared_ptr<Source> src, nframes_t start, nframes_t length
Region::Region (const SourceList& srcs, nframes_t start, nframes_t length, const string& name, DataType type, layer_t layer, Region::Flag flags)
: SessionObject(srcs.front()->session(), name)
, _type(type)
- , _flags(flags)
+ , _flags(Flag (flags|DoNotSendPropertyChanges))
, _start(start)
, _length(length)
, _position(0)
@@ -150,6 +150,8 @@ Region::Region (boost::shared_ptr<const Region> other, nframes_t offset, nframes
_start = other->_start + offset;
copy_stuff (other, offset, length, name, layer, flags);
+ _flags = Flag (_flags | DoNotSendPropertyChanges);
+
/* if the other region had a distinct sync point
set, then continue to use it as best we can.
otherwise, reset sync point back to start.
@@ -188,6 +190,8 @@ Region::Region (boost::shared_ptr<const Region> other, nframes_t length, const s
_start = 0;
copy_stuff (other, 0, length, name, layer, flags);
+ _flags = Flag (_flags | DoNotSendPropertyChanges);
+
/* sync pos is relative to start of file. our start-in-file is now zero,
so set our sync position to whatever the the difference between
_start and _sync_pos was in the other region.
@@ -253,6 +257,8 @@ Region::Region (boost::shared_ptr<const Region> other)
, _pending_changed(Change(0))
, _last_layer_op(other->_last_layer_op)
{
+ _flags = Flag (_flags | DoNotSendPropertyChanges);
+
other->_first_edit = EditChangesName;
if (other->_extra_xml) {
@@ -268,7 +274,7 @@ Region::Region (boost::shared_ptr<const Region> other)
Region::Region (const SourceList& srcs, const XMLNode& node)
: SessionObject(srcs.front()->session(), X_("error: XML did not reset this"))
, _type(DataType::NIL) // to be loaded from XML
- , _flags(Flag(0))
+ , _flags(DoNotSendPropertyChanges)
, _start(0)
, _length(0)
, _position(0)
@@ -297,7 +303,7 @@ Region::Region (const SourceList& srcs, const XMLNode& node)
Region::Region (boost::shared_ptr<Source> src, const XMLNode& node)
: SessionObject(src->session(), X_("error: XML did not reset this"))
, _type(DataType::NIL)
- , _flags(Flag(0))
+ , _flags(DoNotSendPropertyChanges)
, _start(0)
, _length(0)
, _position(0)
@@ -1400,7 +1406,7 @@ Region::send_change (Change what_changed)
StateChanged (what_changed);
- if (!(_flags & DoNotSaveState)) {
+ if (!(_flags & DoNotSendPropertyChanges)) {
/* Try and send a shared_pointer unless this is part of the constructor.
If so, do nothing.
diff --git a/libs/ardour/region_factory.cc b/libs/ardour/region_factory.cc
index a6bf4e0870..004321fa9e 100644
--- a/libs/ardour/region_factory.cc
+++ b/libs/ardour/region_factory.cc
@@ -47,6 +47,7 @@ RegionFactory::create (boost::shared_ptr<Region> region, nframes_t start,
AudioRegion* ar = new AudioRegion (other_a, start, length, name, layer, flags);
boost::shared_ptr<AudioRegion> arp (ar);
boost::shared_ptr<Region> ret (boost::static_pointer_cast<Region> (arp));
+ ret->unlock_property_changes ();
if (announce) {
CheckNewRegion (ret);
}
@@ -55,6 +56,7 @@ RegionFactory::create (boost::shared_ptr<Region> region, nframes_t start,
MidiRegion* ar = new MidiRegion (other_m, start, length, name, layer, flags);
boost::shared_ptr<MidiRegion> arp (ar);
boost::shared_ptr<Region> ret (boost::static_pointer_cast<Region> (arp));
+ ret->unlock_property_changes ();
if (announce) {
CheckNewRegion (ret);
}
@@ -75,10 +77,12 @@ RegionFactory::create (boost::shared_ptr<const Region> region)
if ((ar = boost::dynamic_pointer_cast<const AudioRegion>(region)) != 0) {
boost::shared_ptr<Region> ret (new AudioRegion (ar));
+ ret->unlock_property_changes ();
/* pure copy constructor - no CheckNewRegion emitted */
return ret;
} else if ((mr = boost::dynamic_pointer_cast<const MidiRegion>(region)) != 0) {
boost::shared_ptr<Region> ret (new MidiRegion (mr));
+ ret->unlock_property_changes ();
/* pure copy constructor - no CheckNewRegion emitted */
return ret;
} else {
@@ -112,6 +116,7 @@ RegionFactory::create (boost::shared_ptr<Region> region, const SourceList& srcs,
AudioRegion* ar = new AudioRegion (other, srcs, srcs.front()->length(srcs.front()->timeline_position()), name, layer, flags);
boost::shared_ptr<AudioRegion> arp (ar);
boost::shared_ptr<Region> ret (boost::static_pointer_cast<Region> (arp));
+ ret->unlock_property_changes ();
if (announce) {
CheckNewRegion (ret);
}
@@ -128,6 +133,7 @@ boost::shared_ptr<Region>
RegionFactory::create (Session& session, XMLNode& node, bool yn)
{
boost::shared_ptr<Region> r = session.XMLRegionFactory (node, yn);
+ r->unlock_property_changes ();
if (r) {
CheckNewRegion (r);
@@ -148,6 +154,7 @@ RegionFactory::create (const SourceList& srcs, nframes_t start, nframes_t length
AudioRegion* ar = new AudioRegion (srcs, start, length, name, layer, flags);
boost::shared_ptr<AudioRegion> arp (ar);
boost::shared_ptr<Region> ret (boost::static_pointer_cast<Region> (arp));
+ ret->unlock_property_changes ();
if (announce) {
CheckNewRegion (ret);
}
@@ -158,6 +165,7 @@ RegionFactory::create (const SourceList& srcs, nframes_t start, nframes_t length
MidiRegion* ar = new MidiRegion (srcs, start, length, name, layer, flags);
boost::shared_ptr<MidiRegion> mrp (ar);
boost::shared_ptr<Region> ret (boost::static_pointer_cast<Region> (mrp));
+ ret->unlock_property_changes ();
if (announce) {
CheckNewRegion (ret);
}
@@ -177,10 +185,12 @@ RegionFactory::create (SourceList& srcs, const XMLNode& node)
if (srcs[0]->type() == DataType::AUDIO) {
boost::shared_ptr<Region> ret (new AudioRegion (srcs, node));
+ ret->unlock_property_changes ();
CheckNewRegion (ret);
return ret;
} else if (srcs[0]->type() == DataType::MIDI) {
boost::shared_ptr<Region> ret (new MidiRegion (srcs, node));
+ ret->unlock_property_changes ();
CheckNewRegion (ret);
return ret;
}
@@ -196,12 +206,14 @@ RegionFactory::create (boost::shared_ptr<Source> src, nframes_t start, nframes_t
if ((as = boost::dynamic_pointer_cast<AudioSource>(src)) != 0) {
boost::shared_ptr<Region> ret (new AudioRegion (as, start, length, name, layer, flags));
+ ret->unlock_property_changes ();
if (announce) {
CheckNewRegion (ret);
}
return ret;
} else if ((ms = boost::dynamic_pointer_cast<MidiSource>(src)) != 0) {
boost::shared_ptr<Region> ret (new MidiRegion (ms, start, length, name, layer, flags));
+ ret->unlock_property_changes ();
if (announce) {
CheckNewRegion (ret);
}
diff --git a/libs/ardour/return.cc b/libs/ardour/return.cc
index 574b6736a0..5a44d3f6e6 100644
--- a/libs/ardour/return.cc
+++ b/libs/ardour/return.cc
@@ -36,8 +36,9 @@
using namespace ARDOUR;
using namespace PBD;
-Return::Return (Session& s)
- : IOProcessor (s, true, false, string_compose (_("return %1"), (_bitslot = s.next_return_id()) + 1))
+Return::Return (Session& s, bool internal)
+ : IOProcessor (s, (internal ? false : true), false,
+ string_compose (_("return %1"), (_bitslot = s.next_return_id()) + 1))
, _metering (false)
{
/* never muted */
@@ -48,8 +49,8 @@ Return::Return (Session& s)
ProcessorCreated (this); /* EMIT SIGNAL */
}
-Return::Return (Session& s, const XMLNode& node)
- : IOProcessor (s, true, false, "return")
+Return::Return (Session& s, const XMLNode& node, bool internal)
+ : IOProcessor (s, (internal ? false : true), false, "return")
, _metering (false)
{
/* never muted */
diff --git a/libs/ardour/route.cc b/libs/ardour/route.cc
index 36b0a6bf68..0b6c3c48ca 100644
--- a/libs/ardour/route.cc
+++ b/libs/ardour/route.cc
@@ -38,6 +38,8 @@
#include "ardour/configuration.h"
#include "ardour/cycle_timer.h"
#include "ardour/dB.h"
+#include "ardour/internal_send.h"
+#include "ardour/internal_return.h"
#include "ardour/ladspa_plugin.h"
#include "ardour/meter.h"
#include "ardour/mix.h"
@@ -73,6 +75,24 @@ Route::Route (Session& sess, string name, Flag flg, DataType default_type)
{
init ();
+
+ /* add standard processors other than amp (added by ::init()) */
+
+ _meter.reset (new PeakMeter (_session));
+ add_processor (_meter, PreFader);
+
+ if (_flags & ControlOut) {
+ /* where we listen to tracks */
+ _intreturn.reset (new InternalReturn (_session));
+ add_processor (_intreturn, PreFader);
+ }
+
+ _main_outs.reset (new Delivery (_session, _output, _mute_master, _name, Delivery::Main));
+ add_processor (_main_outs, PostFader);
+
+ /* now that we have _meter, its safe to connect to this */
+
+ _meter_connection = Metering::connect (mem_fun (*this, &Route::meter));
}
Route::Route (Session& sess, const XMLNode& node, DataType default_type)
@@ -83,7 +103,12 @@ Route::Route (Session& sess, const XMLNode& node, DataType default_type)
, _default_type (default_type)
{
init ();
+
_set_state (node, false);
+
+ /* now that we have _meter, its safe to connect to this */
+
+ _meter_connection = Metering::connect (mem_fun (*this, &Route::meter));
}
void
@@ -123,20 +148,10 @@ Route::init ()
_input->changed.connect (mem_fun (this, &Route::input_change_handler));
_output->changed.connect (mem_fun (this, &Route::output_change_handler));
- /* add standard processors */
+ /* add amp processor */
_amp.reset (new Amp (_session, _mute_master));
add_processor (_amp, PostFader);
-
- _meter.reset (new PeakMeter (_session));
- add_processor (_meter, PreFader);
-
- _main_outs.reset (new Delivery (_session, _output, _mute_master, _name, Delivery::Main));
- add_processor (_main_outs, PostFader);
-
- /* now we can meter */
-
- _meter_connection = Metering::connect (mem_fun (*this, &Route::meter));
}
Route::~Route ()
@@ -316,7 +331,7 @@ Route::process_output_buffers (BufferSet& bufs,
switch (Config->get_monitoring_model()) {
case HardwareMonitoring:
case ExternalMonitoring:
- monitor = record_enabled() && (_session.config.get_auto_input() || _session.actively_recording());
+ monitor = !record_enabled() || (_session.config.get_auto_input() && !_session.actively_recording());
break;
default:
monitor = true;
@@ -327,13 +342,13 @@ Route::process_output_buffers (BufferSet& bufs,
}
/* figure out if we're going to use gain automation */
-
_amp->setup_gain_automation (start_frame, end_frame, nframes);
- /* tell main outs what to do about monitoring */
+ /* tell main outs what to do about monitoring */
_main_outs->no_outs_cuz_we_no_monitor (!monitor);
+
/* -------------------------------------------------------------------------------------------
GLOBAL DECLICK (for transport changes etc.)
----------------------------------------------------------------------------------------- */
@@ -520,25 +535,16 @@ Route::muted() const
return _mute_master->muted ();
}
-#if DEFINE_IF_YOU_NEED_THIS
static void
dump_processors(const string& name, const list<boost::shared_ptr<Processor> >& procs)
{
cerr << name << " {" << endl;
for (list<boost::shared_ptr<Processor> >::const_iterator p = procs.begin();
p != procs.end(); ++p) {
- cerr << "\t" << (*p)->name() << endl;
+ cerr << "\t" << (*p)->name() << " ID = " << (*p)->id() << endl;
}
cerr << "}" << endl;
}
-#endif
-
-Route::ProcessorList::iterator
-Route::prefader_iterator()
-{
- Glib::RWLock::ReaderLock lm (_processor_lock);
- return find (_processors.begin(), _processors.end(), _amp);
-}
int
Route::add_processor (boost::shared_ptr<Processor> processor, Placement placement, ProcessorStreams* err)
@@ -615,6 +621,8 @@ Route::add_processor (boost::shared_ptr<Processor> processor, ProcessorList::ite
loc = iter;
}
+ cerr << "Adding " << processor->name() << " @ " << processor << endl;
+
_processors.insert (loc, processor);
// Set up processor list channels. This will set processor->[input|output]_streams(),
@@ -626,6 +634,7 @@ Route::add_processor (boost::shared_ptr<Processor> processor, ProcessorList::ite
--ploc;
_processors.erase(ploc);
configure_processors_unlocked (0); // it worked before we tried to add it ...
+ cerr << "configure failed\n";
return -1;
}
@@ -660,6 +669,7 @@ bool
Route::add_processor_from_xml (const XMLNode& node, Placement placement)
{
ProcessorList::iterator loc;
+
if (placement == PreFader) {
/* generic pre-fader: insert immediately before the amp */
loc = find(_processors.begin(), _processors.end(), _amp);
@@ -699,7 +709,6 @@ Route::add_processor_from_xml (const XMLNode& node, ProcessorList::iterator iter
cerr << _name << " : got processor type " << prop->value() << endl;
boost::shared_ptr<Processor> processor;
- bool have_insert = false;
if (prop->value() == "ladspa" || prop->value() == "Ladspa" ||
prop->value() == "lv2" ||
@@ -707,7 +716,6 @@ Route::add_processor_from_xml (const XMLNode& node, ProcessorList::iterator iter
prop->value() == "audiounit") {
processor.reset (new PluginInsert(_session, node));
- have_insert = true;
} else if (prop->value() == "port") {
@@ -716,32 +724,66 @@ Route::add_processor_from_xml (const XMLNode& node, ProcessorList::iterator iter
} else if (prop->value() == "send") {
processor.reset (new Send (_session, _mute_master, node));
- have_insert = true;
-
+
} else if (prop->value() == "meter") {
+ if (_meter) {
+ if (_meter->set_state (node)) {
+ return false;
+ } else {
+ return true;
+ }
+ }
+
+ _meter.reset (new PeakMeter (_session, node));
processor = _meter;
- processor->set_state (node);
} else if (prop->value() == "amp") {
+
+ /* amp always exists */
processor = _amp;
- processor->set_state (node);
+ if (processor->set_state (node)) {
+ return false;
+ } else {
+ /* never any reason to add it */
+ return true;
+ }
} else if (prop->value() == "listen" || prop->value() == "deliver") {
/* XXX need to generalize */
- processor = _control_outs;
- processor->set_state (node);
+ } else if (prop->value() == "intsend") {
+
+ processor.reset (new InternalSend (_session, _mute_master, node));
+
+ } else if (prop->value() == "intreturn") {
+ if (_intreturn) {
+ if (_intreturn->set_state (node)) {
+ return false;
+ } else {
+ return true;
+ }
+ }
+ _intreturn.reset (new InternalReturn (_session, node));
+ processor = _intreturn;
+
} else if (prop->value() == "main-outs") {
+ if (_main_outs) {
+ if (_main_outs->set_state (node)) {
+ return false;
+ } else {
+ return true;
+ }
+ }
+
+ _main_outs.reset (new Delivery (_session, _output, _mute_master, node));
processor = _main_outs;
- processor->set_state (node);
} else {
-
error << string_compose(_("unknown Processor type \"%1\"; ignored"), prop->value()) << endmsg;
}
@@ -997,31 +1039,6 @@ Route::ab_plugins (bool forward)
}
-/* Figure out the streams that will feed into PreFader */
-ChanCount
-Route::pre_fader_streams() const
-{
- boost::shared_ptr<Processor> processor;
-
- /* Find the last pre-fader redirect that isn't a send; sends don't affect the number
- * of streams. */
- for (ProcessorList::const_iterator i = _processors.begin(); i != _processors.end(); ++i) {
- if ((*i) == _amp) {
- break;
- }
- if (boost::dynamic_pointer_cast<Send> (*i) == 0) {
- processor = *i;
- }
- }
-
- if (processor) {
- return processor->output_streams();
- } else {
- return _input->n_ports ();
- }
-}
-
-
/** Remove processors with a given placement.
* @param p Placement of processors to remove.
*/
@@ -1195,7 +1212,11 @@ Route::configure_processors_unlocked (ProcessorStreams* err)
ChanCount out;
list< pair<ChanCount,ChanCount> > configuration;
uint32_t index = 0;
+
+ cerr << "Processor check with " << _processors.size() << endl;
+
for (ProcessorList::iterator p = _processors.begin(); p != _processors.end(); ++p, ++index) {
+ cerr << "Checking out " << (*p)->name() << " type = " << endl;
if ((*p)->can_support_io_configuration(in, out)) {
configuration.push_back(make_pair(in, out));
in = out;
@@ -1488,6 +1509,34 @@ Route::_set_state (const XMLNode& node, bool call_base)
} else {
_flags = Flag (0);
}
+
+ /* add all processors (except amp, which is always present) */
+
+ nlist = node.children();
+ XMLNode processor_state (X_("processor_state"));
+
+ for (niter = nlist.begin(); niter != nlist.end(); ++niter){
+
+ child = *niter;
+
+ if (child->name() == IO::state_node_name) {
+ if ((prop = child->property (X_("direction"))) == 0) {
+ continue;
+ }
+
+ if (prop->value() == "Input") {
+ _input->set_state (*child);
+ } else if (prop->value() == "Output") {
+ _output->set_state (*child);
+ }
+ }
+
+ if (child->name() == X_("Processor")) {
+ processor_state.add_child_copy (*child);
+ }
+ }
+
+ set_processor_state (processor_state);
if ((prop = node.property (X_("phase-invert"))) != 0) {
set_phase_invert (prop->value()=="yes"?true:false);
@@ -1555,32 +1604,6 @@ Route::_set_state (const XMLNode& node, bool call_base)
}
}
- nlist = node.children();
- XMLNode processor_state (X_("processor_state"));
-
- for (niter = nlist.begin(); niter != nlist.end(); ++niter){
-
- child = *niter;
-
- if (child->name() == IO::state_node_name) {
- if ((prop = child->property (X_("direction"))) == 0) {
- continue;
- }
-
- if (prop->value() == "Input") {
- _input->set_state (*child);
- } else if (prop->value() == "Output") {
- _output->set_state (*child);
- }
- }
-
- if (child->name() == X_("Processor")) {
- processor_state.add_child_copy (*child);
- }
- }
-
- set_processor_state (processor_state);
-
for (niter = nlist.begin(); niter != nlist.end(); ++niter){
child = *niter;
@@ -1642,21 +1665,30 @@ Route::set_processor_state (const XMLNode& node)
{
const XMLNodeList &nlist = node.children();
XMLNodeConstIterator niter;
- bool has_meter_processor = false; // legacy sessions don't
ProcessorList::iterator i, o;
- cerr << _name << " _set_processor_states\n";
+ dump_processors ("set processor states", _processors);
// Iterate through existing processors, remove those which are not in the state list
+
for (i = _processors.begin(); i != _processors.end(); ) {
+
+ /* leave amp alone, always */
+
+ if ((*i) == _amp) {
+ ++i;
+ continue;
+ }
+
ProcessorList::iterator tmp = i;
++tmp;
bool processorInStateList = false;
-
+
for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
XMLProperty* id_prop = (*niter)->property(X_("id"));
+ cerr << "\tchecking " << id_prop->value() << endl;
if (id_prop && (*i)->id() == id_prop->value()) {
processorInStateList = true;
break;
@@ -1672,26 +1704,24 @@ Route::set_processor_state (const XMLNode& node)
// Iterate through state list and make sure all processors are on the track and in the correct order,
// set the state of existing processors according to the new state on the same go
+
i = _processors.begin();
for (niter = nlist.begin(); niter != nlist.end(); ++niter, ++i) {
XMLProperty* prop = (*niter)->property ("type");
- if (prop && prop->value() == "meter") {
- has_meter_processor = true;
- }
-
o = i;
- if (prop->value() != "meter" && prop->value() != "amp" && prop->value() != "main-outs") {
-
- // Check whether the next processor in the list
-
+ // Check whether the next processor in the list is the right one,
+ // except for "amp" which is always there and may not have the
+ // old ID since it is always created anew in every Route
+
+ if (prop->value() != "amp") {
while (o != _processors.end()) {
XMLProperty* id_prop = (*niter)->property(X_("id"));
if (id_prop && (*o)->id() == id_prop->value()) {
- break;
+ break;
}
++o;
@@ -1700,6 +1730,7 @@ Route::set_processor_state (const XMLNode& node)
// If the processor (*niter) is not on the route,
// create it and move it to the correct location
+
if (o == _processors.end()) {
if (add_processor_from_xml (**niter, i)) {
@@ -1708,10 +1739,11 @@ Route::set_processor_state (const XMLNode& node)
cerr << "Error restoring route: unable to restore processor" << endl;
}
- // Otherwise, the processor already exists; just
- // ensure it is at the location provided in the XML state
} else {
+ // Otherwise, the processor already exists; just
+ // ensure it is at the location provided in the XML state
+
if (i != o) {
boost::shared_ptr<Processor> tmp = (*o);
_processors.erase (o); // remove the old copy
@@ -1719,6 +1751,8 @@ Route::set_processor_state (const XMLNode& node)
--i; // move iterator to the correct processor
}
+ // and make it (just) so
+
(*i)->set_state (**niter);
}
}
@@ -1727,10 +1761,6 @@ Route::set_processor_state (const XMLNode& node)
the XML state represents a working signal route.
*/
- if (!has_meter_processor) {
- set_meter_point (_meter_point, NULL);
- }
-
processors_changed ();
}
@@ -1772,33 +1802,38 @@ Route::silence (nframes_t nframes)
}
}
-boost::shared_ptr<Delivery>
-Route::add_listener (boost::shared_ptr<IO> io, const string& listen_name)
+BufferSet*
+Route::get_return_buffer () const
{
- string name = _name;
- name += '[';
- name += listen_name;
- name += ']';
-
- boost::shared_ptr<Delivery> listener (new Delivery (_session, _mute_master, name, Delivery::Listen));
-
- /* As an IO, our control outs need as many IO outputs as we have outputs
- * (we track the changes in ::output_change_handler()).
- * As a processor, the listener is an identity processor
- * (i.e. it does not modify its input buffers whatsoever)
- */
-
- if (listener->output()->ensure_io (n_outputs(), true, this)) {
- return boost::shared_ptr<Delivery>();
+ Glib::RWLock::ReaderLock rm (_processor_lock);
+
+ for (ProcessorList::const_iterator x = _processors.begin(); x != _processors.end(); ++x) {
+ boost::shared_ptr<InternalReturn> d = boost::dynamic_pointer_cast<InternalReturn>(*x);
+
+ if (d) {
+ return d->get_buffers ();
+ }
}
- add_processor (listener, PostFader);
+ return 0;
+}
- return listener;
+void
+Route::release_return_buffer () const
+{
+ Glib::RWLock::ReaderLock rm (_processor_lock);
+
+ for (ProcessorList::const_iterator x = _processors.begin(); x != _processors.end(); ++x) {
+ boost::shared_ptr<InternalReturn> d = boost::dynamic_pointer_cast<InternalReturn>(*x);
+
+ if (d) {
+ return d->release_buffers ();
+ }
+ }
}
int
-Route::listen_via (boost::shared_ptr<IO> io, const string& listen_name)
+Route::listen_via (boost::shared_ptr<Route> route, const string& listen_name)
{
vector<string> ports;
vector<string>::const_iterator i;
@@ -1807,71 +1842,58 @@ Route::listen_via (boost::shared_ptr<IO> io, const string& listen_name)
Glib::RWLock::ReaderLock rm (_processor_lock);
for (ProcessorList::const_iterator x = _processors.begin(); x != _processors.end(); ++x) {
- boost::shared_ptr<const Delivery> d = boost::dynamic_pointer_cast<const Delivery>(*x);
+ boost::shared_ptr<const InternalSend> d = boost::dynamic_pointer_cast<const InternalSend>(*x);
- if (d && d->output() == io) {
+ if (d && d->target_route() == route) {
/* already listening via the specified IO: do nothing */
return 0;
}
}
}
-
- uint32_t ni = io->n_ports().n_total();
-
- for (uint32_t n = 0; n < ni; ++n) {
- ports.push_back (io->nth (n)->name());
- }
-
- if (ports.empty()) {
- return 0;
- }
- boost::shared_ptr<Delivery> listen_point = add_listener (io, listen_name);
-
- /* XXX hack for now .... until we can generalize listen points */
+ boost::shared_ptr<InternalSend> listener;
- _control_outs = listen_point;
+ try {
+ listener.reset (new InternalSend (_session, _mute_master, route));
- /* now connect to the named ports */
-
- ni = listen_point->output()->n_ports().n_total();
- size_t psize = ports.size();
+ } catch (failed_constructor& err) {
- for (size_t n = 0; n < ni; ++n) {
- if (listen_point->output()->connect (listen_point->output()->nth (n), ports[n % psize], this)) {
- error << string_compose (_("could not connect %1 to %2"),
- listen_point->output()->nth (n)->name(), ports[n % psize]) << endmsg;
- return -1;
- }
+ return -1;
}
+ add_processor (listener, PreFader);
return 0;
}
void
-Route::drop_listen (boost::shared_ptr<IO> io)
+Route::drop_listen (boost::shared_ptr<Route> route)
{
ProcessorStreams err;
ProcessorList::iterator tmp;
- Glib::RWLock::ReaderLock rm (_processor_lock);
+ Glib::RWLock::ReaderLock rl(_processor_lock);
+ rl.acquire ();
+ again:
for (ProcessorList::iterator x = _processors.begin(); x != _processors.end(); ) {
- tmp = x;
- ++tmp;
-
- boost::shared_ptr<Delivery> d = boost::dynamic_pointer_cast<Delivery>(*x);
+ boost::shared_ptr<InternalSend> d = boost::dynamic_pointer_cast<InternalSend>(*x);
- if (d && d->output() == io) {
- /* already listening via the specified IO: do nothing */
+ if (d && d->target_route() == route) {
+ rl.release ();
remove_processor (*x, &err);
-
+ rl.acquire ();
+
+ /* list could have been demolished while we dropped the lock
+ so start over.
+ */
+
+ goto again;
}
-
- x = tmp;
}
+
+ rl.release ();
}
void
@@ -1939,25 +1961,30 @@ Route::set_comment (string cmt, void *src)
}
bool
-Route::feeds (boost::shared_ptr<IO> other)
+Route::feeds (boost::shared_ptr<Route> other)
{
- if (_output->connected_to (other)) {
+ // cerr << _name << endl;
+
+ if (_output->connected_to (other->input())) {
+ // cerr << "\tdirect FEEDS " << other->name() << endl;
return true;
}
- /* check IOProcessors which may also interconnect Routes */
-
for (ProcessorList::iterator r = _processors.begin(); r != _processors.end(); r++) {
-
+
boost::shared_ptr<IOProcessor> iop;
if ((iop = boost::dynamic_pointer_cast<IOProcessor>(*r)) != 0) {
- if (iop->output() && iop->output()->connected_to (other)) {
+ if (iop->feeds (other)) {
+ // cerr << "\tIOP " << iop->name() << " feeds " << other->name() << endl;
return true;
+ } else {
+ // cerr << "\tIOP " << iop->name() << " does NOT feeds " << other->name() << endl;
}
}
}
+ // cerr << "\tdoes NOT FEED " << other->name() << endl;
return false;
}
@@ -2418,15 +2445,15 @@ Route::set_name (const string& str)
}
boost::shared_ptr<Send>
-Route::send_for (boost::shared_ptr<const IO> target) const
+Route::internal_send_for (boost::shared_ptr<const Route> target) const
{
Glib::RWLock::ReaderLock lm (_processor_lock);
for (ProcessorList::const_iterator i = _processors.begin(); i != _processors.end(); ++i) {
- boost::shared_ptr<Send> send;
+ boost::shared_ptr<InternalSend> send;
- if ((send = boost::dynamic_pointer_cast<Send>(*i)) != 0) {
- if (send->output()->connected_to (target)) {
+ if ((send = boost::dynamic_pointer_cast<InternalSend>(*i)) != 0) {
+ if (send->target_route() == target) {
return send;
}
}
diff --git a/libs/ardour/send.cc b/libs/ardour/send.cc
index ad66f73796..71685e1b88 100644
--- a/libs/ardour/send.cc
+++ b/libs/ardour/send.cc
@@ -36,8 +36,9 @@
using namespace ARDOUR;
using namespace PBD;
-Send::Send (Session& s, boost::shared_ptr<MuteMaster> mm)
- : Delivery (s, mm, string_compose (_("send %1"), (_bitslot = s.next_send_id()) + 1), Delivery::Send)
+Send::Send (Session& s, boost::shared_ptr<MuteMaster> mm, bool internal)
+ : Delivery (s, mm, string_compose (_("send %1"), (_bitslot = s.next_send_id()) + 1),
+ (internal ? Delivery::Listen : Delivery::Send))
, _metering (false)
{
_amp.reset (new Amp (_session, _mute_master));
@@ -46,8 +47,8 @@ Send::Send (Session& s, boost::shared_ptr<MuteMaster> mm)
ProcessorCreated (this); /* EMIT SIGNAL */
}
-Send::Send (Session& s, boost::shared_ptr<MuteMaster> mm, const XMLNode& node)
- : Delivery (s, mm, "send", Delivery::Send)
+Send::Send (Session& s, boost::shared_ptr<MuteMaster> mm, const XMLNode& node, bool internal)
+ : Delivery (s, mm, "send", (internal ? Delivery::Listen : Delivery::Send))
, _metering (false)
{
_amp.reset (new Amp (_session, _mute_master));
@@ -113,6 +114,7 @@ Send::state(bool full)
{
XMLNode& node = IOProcessor::state(full);
char buf[32];
+
node.add_property ("type", "send");
snprintf (buf, sizeof (buf), "%" PRIu32, _bitslot);
node.add_property ("bitslot", buf);
diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc
index 394193e8b2..db30fea021 100644
--- a/libs/ardour/session.cc
+++ b/libs/ardour/session.cc
@@ -294,6 +294,11 @@ Session::Session (AudioEngine &eng,
}
+ if (no_auto_connect()) {
+ input_ac = AutoConnectOption (0);
+ output_ac = AutoConnectOption (0);
+ }
+
Config->set_input_auto_connect (input_ac);
Config->set_output_auto_connect (output_ac);
@@ -607,6 +612,8 @@ Session::when_engine_running ()
it doesn't really scale that well to higher channel counts
*/
+ /* mono output bundles */
+
for (uint32_t np = 0; np < n_physical_outputs; ++np) {
char buf[32];
snprintf (buf, sizeof (buf), _("out %" PRIu32), np+1);
@@ -618,6 +625,8 @@ Session::when_engine_running ()
add_bundle (c);
}
+ /* stereo output bundles */
+
for (uint32_t np = 0; np < n_physical_outputs; np += 2) {
if (np + 1 < n_physical_outputs) {
char buf[32];
@@ -632,6 +641,8 @@ Session::when_engine_running ()
}
}
+ /* mono input bundles */
+
for (uint32_t np = 0; np < n_physical_inputs; ++np) {
char buf[32];
snprintf (buf, sizeof (buf), _("in %" PRIu32), np+1);
@@ -643,6 +654,8 @@ Session::when_engine_running ()
add_bundle (c);
}
+ /* stereo input bundles */
+
for (uint32_t np = 0; np < n_physical_inputs; np += 2) {
if (np + 1 < n_physical_inputs) {
char buf[32];
@@ -658,16 +671,15 @@ Session::when_engine_running ()
}
}
- /* create master/control ports */
-
- if (_master_out) {
+ if (Config->get_auto_connect_standard_busses() && !no_auto_connect()) {
- /* if requested auto-connect the outputs to the first N physical ports.
- */
+ if (_master_out) {
+
+ /* if requested auto-connect the outputs to the first N physical ports.
+ */
- if (Config->get_auto_connect_master()) {
uint32_t limit = _master_out->n_outputs().n_total();
-
+
for (uint32_t n = 0; n < limit; ++n) {
Port* p = _master_out->output()->nth (n);
string connect_to = _engine.get_nth_physical_output (DataType (p->type()), n);
@@ -681,40 +693,31 @@ Session::when_engine_running ()
}
}
}
- }
-
- BootMessage (_("Setup signal flow and plugins"));
- hookup_io ();
+ if (_control_out) {
- /* catch up on send+insert cnts */
-
- BootMessage (_("Catch up with send/insert state"));
-
- insert_cnt = 0;
-
- for (list<PortInsert*>::iterator i = _port_inserts.begin(); i != _port_inserts.end(); ++i) {
- uint32_t id;
-
- if (sscanf ((*i)->name().c_str(), "%*s %u", &id) == 1) {
- if (id > insert_cnt) {
- insert_cnt = id;
+ uint32_t limit = _control_out->n_outputs().n_total();
+
+ for (uint32_t n = 0; n < limit; ++n) {
+ Port* p = _control_out->output()->nth (n);
+ string connect_to = _engine.get_nth_physical_output (DataType (p->type()), n);
+
+ if (!connect_to.empty()) {
+ if (_control_out->output()->connect (p, connect_to, this)) {
+ error << string_compose (_("cannot connect control output %1 to %2"), n, connect_to)
+ << endmsg;
+ break;
+ }
+ }
}
}
}
- send_cnt = 0;
-
- for (list<Send*>::iterator i = _sends.begin(); i != _sends.end(); ++i) {
- uint32_t id;
+ BootMessage (_("Setup signal flow and plugins"));
- if (sscanf ((*i)->name().c_str(), "%*s %u", &id) == 1) {
- if (id > send_cnt) {
- send_cnt = id;
- }
- }
- }
+ hookup_io ();
+ /* catch up on send+insert cnts */
_state_of_the_state = StateOfTheState (_state_of_the_state & ~(CannotSave|Dirty));
@@ -751,24 +754,6 @@ Session::hookup_io ()
}
}
- /* Connect track to listen/solo etc. busses XXX generalize this beyond control_out */
-
- if (_control_out) {
-
- // _control_out->ensure_io (_control_out->input_minimum(), _control_out->output_minimum(), false, this);
-
- boost::shared_ptr<RouteList> r = routes.reader ();
-
- for (RouteList::iterator x = r->begin(); x != r->end(); ++x) {
-
- boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track> (*x);
-
- if (t) {
- t->listen_via (_control_out->input(), X_("listen"));
- }
- }
- }
-
/* load bundles, which we may have postponed earlier on */
if (_bundle_xml_node) {
load_bundles (*_bundle_xml_node);
@@ -783,6 +768,22 @@ Session::hookup_io ()
Delivery::reset_panners ();
+ /* Connect tracks to listen/solo etc. busses XXX generalize this beyond control_out */
+
+ if (_control_out) {
+
+ boost::shared_ptr<RouteList> r = routes.reader ();
+
+ for (RouteList::iterator x = r->begin(); x != r->end(); ++x) {
+
+ boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track> (*x);
+
+ if (t) {
+ t->listen_via (_control_out, X_("listen"));
+ }
+ }
+ }
+
/* Anyone who cares about input state, wake up and do something */
IOConnectionsComplete (); /* EMIT SIGNAL */
@@ -1455,7 +1456,7 @@ Session::resort_routes_using (shared_ptr<RouteList> r)
continue;
}
- if ((*j)->feeds ((*i)->input())) {
+ if ((*j)->feeds (*i)) {
(*i)->fed_by.insert (*j);
}
}
@@ -2064,7 +2065,10 @@ Session::add_routes (RouteList& new_routes, bool save)
RCUWriter<RouteList> writer (routes);
shared_ptr<RouteList> r = writer.get_copy ();
r->insert (r->end(), new_routes.begin(), new_routes.end());
- resort_routes_using (r);
+
+ if (!_control_out && IO::connecting_legal) {
+ resort_routes_using (r);
+ }
}
for (RouteList::iterator x = new_routes.begin(); x != new_routes.end(); ++x) {
@@ -2088,8 +2092,10 @@ Session::add_routes (RouteList& new_routes, bool save)
if (_control_out && IO::connecting_legal) {
for (RouteList::iterator x = new_routes.begin(); x != new_routes.end(); ++x) {
- (*x)->listen_via (_control_out->input(), "control");
+ (*x)->listen_via (_control_out, "control");
}
+
+ resort_routes ();
}
set_dirty();
@@ -2145,13 +2151,14 @@ Session::remove_route (shared_ptr<Route> route)
}
if (route == _control_out) {
+
/* cancel control outs for all routes */
for (RouteList::iterator r = rs->begin(); r != rs->end(); ++r) {
- (*r)->drop_listen (_control_out->input());
+ (*r)->drop_listen (_control_out);
}
- _control_out = shared_ptr<Route> ();
+ _control_out.reset ();
}
update_route_solo_state ();
@@ -2238,7 +2245,7 @@ Session::route_solo_changed (void* src, boost::weak_ptr<Route> wpr)
solo_update_disabled = true;
for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
- if ((*i)->feeds (route->input())) {
+ if ((*i)->feeds (route)) {
/* do it */
(*i)->main_outs()->mod_solo_level (delta);
@@ -3533,26 +3540,7 @@ Session::record_enable_change_all (bool yn)
void
Session::add_processor (Processor* processor)
{
- Send* send;
- Return* retrn;
- PortInsert* port_insert;
- PluginInsert* plugin_insert;
-
- if ((port_insert = dynamic_cast<PortInsert *> (processor)) != 0) {
- _port_inserts.insert (_port_inserts.begin(), port_insert);
- } else if ((plugin_insert = dynamic_cast<PluginInsert *> (processor)) != 0) {
- _plugin_inserts.insert (_plugin_inserts.begin(), plugin_insert);
- } else if ((send = dynamic_cast<Send *> (processor)) != 0) {
- _sends.insert (_sends.begin(), send);
- } else if ((retrn = dynamic_cast<Return *> (processor)) != 0) {
- _returns.insert (_returns.begin(), retrn);
- } else {
- fatal << _("programming error: unknown type of Insert created!") << endmsg;
- /*NOTREACHED*/
- }
-
processor->GoingAway.connect (sigc::bind (mem_fun (*this, &Session::remove_processor), processor));
-
set_dirty();
}
@@ -3562,31 +3550,13 @@ Session::remove_processor (Processor* processor)
Send* send;
Return* retrn;
PortInsert* port_insert;
- PluginInsert* plugin_insert;
if ((port_insert = dynamic_cast<PortInsert *> (processor)) != 0) {
- list<PortInsert*>::iterator x = find (_port_inserts.begin(), _port_inserts.end(), port_insert);
- if (x != _port_inserts.end()) {
- insert_bitset[port_insert->bit_slot()] = false;
- _port_inserts.erase (x);
- }
- } else if ((plugin_insert = dynamic_cast<PluginInsert *> (processor)) != 0) {
- _plugin_inserts.remove (plugin_insert);
+ insert_bitset[port_insert->bit_slot()] = false;
} else if ((send = dynamic_cast<Send *> (processor)) != 0) {
- list<Send*>::iterator x = find (_sends.begin(), _sends.end(), send);
- if (x != _sends.end()) {
- send_bitset[send->bit_slot()] = false;
- _sends.erase (x);
- }
+ send_bitset[send->bit_slot()] = false;
} else if ((retrn = dynamic_cast<Return *> (processor)) != 0) {
- list<Return*>::iterator x = find (_returns.begin(), _returns.end(), retrn);
- if (x != _returns.end()) {
- return_bitset[send->bit_slot()] = false;
- _returns.erase (x);
- }
- } else {
- fatal << _("programming error: unknown type of Insert deleted!") << endmsg;
- /*NOTREACHED*/
+ return_bitset[send->bit_slot()] = false;
}
set_dirty();
diff --git a/libs/ardour/session_state.cc b/libs/ardour/session_state.cc
index 5d622f95a7..f11342a0fd 100644
--- a/libs/ardour/session_state.cc
+++ b/libs/ardour/session_state.cc
@@ -153,7 +153,6 @@ Session::first_stage_init (string fullpath, string snapshot_name)
_non_soloed_outs_muted = false;
g_atomic_int_set (&processing_prohibited, 0);
- insert_cnt = 0;
_transport_speed = 0;
_last_transport_speed = 0;
_target_transport_speed = 0;
diff --git a/libs/ardour/wscript b/libs/ardour/wscript
index 89a7e06c04..fc08dfde0d 100644
--- a/libs/ardour/wscript
+++ b/libs/ardour/wscript
@@ -136,8 +136,10 @@ def build(bld):
gdither.cc
globals.cc
import.cc
+ internal_return.cc
+ internal_send.cc
interpolation.cc
- io.cc
+ io.cc
io_processor.cc
jack_slave.cc
ladspa_plugin.cc