mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-10 08:36:32 +01:00
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
This commit is contained in:
parent
9c8ee46c76
commit
86f24d20e1
43 changed files with 992 additions and 360 deletions
|
|
@ -1,4 +1,5 @@
|
|||
#!/bin/sh
|
||||
. `dirname "$0"`/../build/default/gtk2_ardour/ardev_common_waf.sh
|
||||
LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH
|
||||
export ARDOUR_RUNNING_UNDER_VALGRIND=TRUE
|
||||
exec valgrind --num-callers=50 --tool=memcheck $TOP/$EXECUTABLE --novst "$@"
|
||||
|
|
|
|||
|
|
@ -497,8 +497,9 @@ AudioStreamView::setup_rec_box ()
|
|||
}
|
||||
|
||||
boost::shared_ptr<AudioRegion> region (boost::dynamic_pointer_cast<AudioRegion>
|
||||
(RegionFactory::create (sources, start, 1 , "", 0, (Region::Flag)(Region::DefaultFlags | Region::DoNotSaveState), false)));
|
||||
(RegionFactory::create (sources, start, 1 , "", 0, (Region::Flag)(Region::DefaultFlags), false)));
|
||||
assert(region);
|
||||
region->block_property_changes ();
|
||||
region->set_position (_trackview.session().transport_frame(), this);
|
||||
rec_regions.push_back (make_pair(region, (RegionView*)0));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -415,8 +415,9 @@ MidiStreamView::setup_rec_box ()
|
|||
}
|
||||
|
||||
boost::shared_ptr<MidiRegion> region (boost::dynamic_pointer_cast<MidiRegion>
|
||||
(RegionFactory::create (sources, start, 1 , "", 0, (Region::Flag)(Region::DefaultFlags | Region::DoNotSaveState), false)));
|
||||
(RegionFactory::create (sources, start, 1 , "", 0, Region::DefaultFlags, false)));
|
||||
assert(region);
|
||||
region->block_property_changes ();
|
||||
region->set_position (_trackview.session().transport_frame(), this);
|
||||
rec_regions.push_back (make_pair(region, (RegionView*)0));
|
||||
|
||||
|
|
|
|||
|
|
@ -1438,7 +1438,7 @@ MixerStrip::switch_io (boost::shared_ptr<Route> target)
|
|||
send->set_metering (false);
|
||||
}
|
||||
|
||||
_current_delivery = _route->send_for (target->input());
|
||||
_current_delivery = _route->internal_send_for (target);
|
||||
|
||||
if (_current_delivery) {
|
||||
send = boost::dynamic_pointer_cast<Send>(_current_delivery);
|
||||
|
|
|
|||
|
|
@ -1143,6 +1143,14 @@ RCOptionEditor::RCOptionEditor ()
|
|||
|
||||
add_option (_("Audio"), new OptionEditorHeading (_("Connection of tracks and busses")));
|
||||
|
||||
add_option (_("Audio"),
|
||||
new BoolOption (
|
||||
"auto-connect-standard-busses",
|
||||
_("Auto-connect master/monitor busses"),
|
||||
mem_fun (*_rc_config, &RCConfiguration::get_auto_connect_standard_busses),
|
||||
mem_fun (*_rc_config, &RCConfiguration::set_auto_connect_standard_busses)
|
||||
));
|
||||
|
||||
ComboOption<AutoConnectOption>* iac = new ComboOption<AutoConnectOption> (
|
||||
"input-auto-connect",
|
||||
_("Connect track and bus inputs"),
|
||||
|
|
|
|||
|
|
@ -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 ();
|
||||
|
||||
|
|
|
|||
|
|
@ -57,6 +57,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) {
|
||||
assert(_capacity > 0);
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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?
|
||||
|
|
|
|||
|
|
@ -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&);
|
||||
|
||||
|
|
|
|||
60
libs/ardour/ardour/internal_return.h
Normal file
60
libs/ardour/ardour/internal_return.h
Normal file
|
|
@ -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__ */
|
||||
57
libs/ardour/ardour/internal_send.h
Normal file
57
libs/ardour/ardour/internal_send.h
Normal file
|
|
@ -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__ */
|
||||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@ 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() { }
|
||||
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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; }
|
||||
|
|
|
|||
|
|
@ -52,6 +52,7 @@ class Panner;
|
|||
class Processor;
|
||||
class RouteGroup;
|
||||
class Send;
|
||||
class InternalReturn;
|
||||
|
||||
class Route : public SessionObject, public AutomatableControls
|
||||
{
|
||||
|
|
@ -183,17 +184,16 @@ 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;
|
||||
|
|
|
|||
|
|
@ -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; }
|
||||
|
|
|
|||
|
|
@ -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 *);
|
||||
|
|
|
|||
|
|
@ -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/cycle_timer.h"
|
||||
#include "ardour/utils.h"
|
||||
#include "ardour/event_type_map.h"
|
||||
#include "ardour/io.h"
|
||||
#include "ardour/amp.h"
|
||||
#include "ardour/port_set.h"
|
||||
#include "ardour/buffer_set.h"
|
||||
|
||||
#include "ardour/cycle_timer.h"
|
||||
#include "ardour/delivery.h"
|
||||
#include "ardour/event_type_map.h"
|
||||
#include "ardour/internal_return.h"
|
||||
#include "ardour/io.h"
|
||||
#include "ardour/meter.h"
|
||||
#include "ardour/midi_port.h"
|
||||
#include "ardour/port.h"
|
||||
#include "ardour/port_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 *
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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 ();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
|
|||
136
libs/ardour/internal_return.cc
Normal file
136
libs/ardour/internal_return.cc
Normal file
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
192
libs/ardour/internal_send.cc
Normal file
192
libs/ardour/internal_send.cc
Normal file
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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,6 +209,8 @@ IOProcessor::set_state (const XMLNode& node)
|
|||
if ((prop = node.property ("name")) == 0) {
|
||||
set_name (_output->name());
|
||||
}
|
||||
} else {
|
||||
/* no output */
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -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());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 ()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
@ -1489,6 +1510,34 @@ Route::_set_state (const XMLNode& node, bool call_base)
|
|||
_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,13 +1665,21 @@ 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;
|
||||
|
||||
|
|
@ -1657,6 +1688,7 @@ Route::set_processor_state (const XMLNode& node)
|
|||
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 += ']';
|
||||
Glib::RWLock::ReaderLock rm (_processor_lock);
|
||||
|
||||
boost::shared_ptr<Delivery> listener (new Delivery (_session, _mute_master, name, Delivery::Listen));
|
||||
for (ProcessorList::const_iterator x = _processors.begin(); x != _processors.end(); ++x) {
|
||||
boost::shared_ptr<InternalReturn> d = boost::dynamic_pointer_cast<InternalReturn>(*x);
|
||||
|
||||
/* 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>();
|
||||
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();
|
||||
boost::shared_ptr<InternalSend> listener;
|
||||
|
||||
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 */
|
||||
|
||||
_control_outs = listen_point;
|
||||
|
||||
/* now connect to the named ports */
|
||||
|
||||
ni = listen_point->output()->n_ports().n_total();
|
||||
size_t psize = ports.size();
|
||||
|
||||
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;
|
||||
}
|
||||
try {
|
||||
listener.reset (new InternalSend (_session, _mute_master, route));
|
||||
|
||||
} catch (failed_constructor& err) {
|
||||
|
||||
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<InternalSend> d = boost::dynamic_pointer_cast<InternalSend>(*x);
|
||||
|
||||
boost::shared_ptr<Delivery> d = boost::dynamic_pointer_cast<Delivery>(*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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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,14 +671,13 @@ Session::when_engine_running ()
|
|||
}
|
||||
}
|
||||
|
||||
/* create master/control ports */
|
||||
if (Config->get_auto_connect_standard_busses() && !no_auto_connect()) {
|
||||
|
||||
if (_master_out) {
|
||||
if (_master_out) {
|
||||
|
||||
/* if requested auto-connect the outputs to the first N physical ports.
|
||||
*/
|
||||
/* 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) {
|
||||
|
|
@ -681,6 +693,24 @@ Session::when_engine_running ()
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (_control_out) {
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BootMessage (_("Setup signal flow and plugins"));
|
||||
|
|
@ -689,33 +719,6 @@ Session::when_engine_running ()
|
|||
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
send_cnt = 0;
|
||||
|
||||
for (list<Send*>::iterator i = _sends.begin(); i != _sends.end(); ++i) {
|
||||
uint32_t id;
|
||||
|
||||
if (sscanf ((*i)->name().c_str(), "%*s %u", &id) == 1) {
|
||||
if (id > send_cnt) {
|
||||
send_cnt = id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
_state_of_the_state = StateOfTheState (_state_of_the_state & ~(CannotSave|Dirty));
|
||||
|
||||
/* hook us up to the engine */
|
||||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue