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
|
#!/bin/sh
|
||||||
. `dirname "$0"`/../build/default/gtk2_ardour/ardev_common_waf.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
|
export ARDOUR_RUNNING_UNDER_VALGRIND=TRUE
|
||||||
exec valgrind --num-callers=50 --tool=memcheck $TOP/$EXECUTABLE --novst "$@"
|
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>
|
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);
|
assert(region);
|
||||||
|
region->block_property_changes ();
|
||||||
region->set_position (_trackview.session().transport_frame(), this);
|
region->set_position (_trackview.session().transport_frame(), this);
|
||||||
rec_regions.push_back (make_pair(region, (RegionView*)0));
|
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>
|
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);
|
assert(region);
|
||||||
|
region->block_property_changes ();
|
||||||
region->set_position (_trackview.session().transport_frame(), this);
|
region->set_position (_trackview.session().transport_frame(), this);
|
||||||
rec_regions.push_back (make_pair(region, (RegionView*)0));
|
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);
|
send->set_metering (false);
|
||||||
}
|
}
|
||||||
|
|
||||||
_current_delivery = _route->send_for (target->input());
|
_current_delivery = _route->internal_send_for (target);
|
||||||
|
|
||||||
if (_current_delivery) {
|
if (_current_delivery) {
|
||||||
send = boost::dynamic_pointer_cast<Send>(_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 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> (
|
ComboOption<AutoConnectOption>* iac = new ComboOption<AutoConnectOption> (
|
||||||
"input-auto-connect",
|
"input-auto-connect",
|
||||||
_("Connect track and bus inputs"),
|
_("Connect track and bus inputs"),
|
||||||
|
|
|
||||||
|
|
@ -47,6 +47,7 @@ namespace ARDOUR {
|
||||||
|
|
||||||
int init (bool with_vst, bool try_optimization);
|
int init (bool with_vst, bool try_optimization);
|
||||||
int cleanup ();
|
int cleanup ();
|
||||||
|
bool no_auto_connect ();
|
||||||
|
|
||||||
std::string get_ardour_revision ();
|
std::string get_ardour_revision ();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -57,6 +57,13 @@ public:
|
||||||
_written = true;
|
_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*/
|
/** 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) {
|
void accumulate_from (const AudioBuffer& src, nframes_t len, nframes_t dst_offset = 0, nframes_t src_offset = 0) {
|
||||||
assert(_capacity > 0);
|
assert(_capacity > 0);
|
||||||
|
|
|
||||||
|
|
@ -76,6 +76,7 @@ public:
|
||||||
virtual void clear() { silence(_capacity, 0); }
|
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 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:
|
protected:
|
||||||
Buffer(DataType type, size_t capacity)
|
Buffer(DataType type, size_t capacity)
|
||||||
|
|
|
||||||
|
|
@ -68,6 +68,7 @@ public:
|
||||||
|
|
||||||
void is_silent(bool yn) { _is_silent = yn; }
|
void is_silent(bool yn) { _is_silent = yn; }
|
||||||
bool is_silent() const { return _is_silent; }
|
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; }
|
void set_count(const ChanCount& count) { assert(count <= _available); _count = count; }
|
||||||
|
|
||||||
|
|
@ -94,6 +95,7 @@ public:
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void read_from(BufferSet& in, nframes_t nframes);
|
void read_from(BufferSet& in, nframes_t nframes);
|
||||||
|
void merge_from(BufferSet& in, nframes_t nframes);
|
||||||
|
|
||||||
// ITERATORS
|
// ITERATORS
|
||||||
// FIXME: possible to combine these? templates?
|
// FIXME: possible to combine these? templates?
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,13 @@ public:
|
||||||
Main = 0x8
|
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 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& s, boost::shared_ptr<MuteMaster> mm, const std::string& name, Role);
|
||||||
Delivery (Session&, boost::shared_ptr<MuteMaster> mm, const XMLNode&);
|
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 Session;
|
||||||
class IO;
|
class IO;
|
||||||
|
class Route;
|
||||||
|
|
||||||
/** A mixer strip element (Processor) with 1 or 2 IO elements.
|
/** A mixer strip element (Processor) with 1 or 2 IO elements.
|
||||||
*/
|
*/
|
||||||
|
|
@ -66,6 +67,8 @@ class IOProcessor : public Processor
|
||||||
|
|
||||||
void silence (nframes_t nframes);
|
void silence (nframes_t nframes);
|
||||||
|
|
||||||
|
virtual bool feeds (boost::shared_ptr<Route> other) const;
|
||||||
|
|
||||||
sigc::signal<void,IOProcessor*,bool> AutomationPlaybackChanged;
|
sigc::signal<void,IOProcessor*,bool> AutomationPlaybackChanged;
|
||||||
sigc::signal<void,IOProcessor*,uint32_t> AutomationChanged;
|
sigc::signal<void,IOProcessor*,uint32_t> AutomationChanged;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -51,6 +51,7 @@ class Metering {
|
||||||
class PeakMeter : public Processor {
|
class PeakMeter : public Processor {
|
||||||
public:
|
public:
|
||||||
PeakMeter(Session& s) : Processor(s, "Meter") {}
|
PeakMeter(Session& s) : Processor(s, "Meter") {}
|
||||||
|
PeakMeter(Session&s, const XMLNode& node);
|
||||||
|
|
||||||
void meter();
|
void meter();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -39,6 +39,7 @@ public:
|
||||||
|
|
||||||
void silence (nframes_t nframes, nframes_t offset = 0);
|
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 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);
|
void copy(const MidiBuffer& copy);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -50,6 +50,7 @@ class Processor : public SessionObject, public AutomatableControls, public Laten
|
||||||
static const std::string state_node_name;
|
static const std::string state_node_name;
|
||||||
|
|
||||||
Processor(Session&, const std::string& name);
|
Processor(Session&, const std::string& name);
|
||||||
|
Processor(Session&, const XMLNode& node);
|
||||||
|
|
||||||
virtual ~Processor() { }
|
virtual ~Processor() { }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@
|
||||||
|
|
||||||
/* IO connection */
|
/* 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, output_auto_connect, "output-auto-connect", AutoConnectOption (0))
|
||||||
CONFIG_VARIABLE (AutoConnectOption, input_auto_connect, "input-auto-connect", AutoConnectOption (0))
|
CONFIG_VARIABLE (AutoConnectOption, input_auto_connect, "input-auto-connect", AutoConnectOption (0))
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -74,7 +74,7 @@ class Region
|
||||||
LeftOfSplit = 0x4000,
|
LeftOfSplit = 0x4000,
|
||||||
RightOfSplit = 0x8000,
|
RightOfSplit = 0x8000,
|
||||||
Hidden = 0x10000,
|
Hidden = 0x10000,
|
||||||
DoNotSaveState = 0x20000,
|
DoNotSendPropertyChanges = 0x20000,
|
||||||
PositionLocked = 0x40000,
|
PositionLocked = 0x40000,
|
||||||
//
|
//
|
||||||
range_guarantoor = USHRT_MAX
|
range_guarantoor = USHRT_MAX
|
||||||
|
|
@ -97,6 +97,8 @@ class Region
|
||||||
|
|
||||||
sigc::signal<void,Change> StateChanged;
|
sigc::signal<void,Change> StateChanged;
|
||||||
static sigc::signal<void,boost::shared_ptr<ARDOUR::Region> > RegionPropertyChanged;
|
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();
|
virtual ~Region();
|
||||||
|
|
||||||
|
|
@ -160,8 +162,6 @@ class Region
|
||||||
void set_position_lock_style (PositionLockStyle ps);
|
void set_position_lock_style (PositionLockStyle ps);
|
||||||
void recompute_position_from_lock_style ();
|
void recompute_position_from_lock_style ();
|
||||||
|
|
||||||
virtual bool should_save_state () const { return !(_flags & DoNotSaveState); };
|
|
||||||
|
|
||||||
void freeze ();
|
void freeze ();
|
||||||
void thaw (const std::string& why);
|
void thaw (const std::string& why);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -38,8 +38,8 @@ class PeakMeter;
|
||||||
class Return : public IOProcessor
|
class Return : public IOProcessor
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Return (Session&);
|
Return (Session&, bool internal = false);
|
||||||
Return (Session&, const XMLNode&);
|
Return (Session&, const XMLNode&, bool internal = false);
|
||||||
virtual ~Return ();
|
virtual ~Return ();
|
||||||
|
|
||||||
uint32_t bit_slot() const { return _bitslot; }
|
uint32_t bit_slot() const { return _bitslot; }
|
||||||
|
|
|
||||||
|
|
@ -52,6 +52,7 @@ class Panner;
|
||||||
class Processor;
|
class Processor;
|
||||||
class RouteGroup;
|
class RouteGroup;
|
||||||
class Send;
|
class Send;
|
||||||
|
class InternalReturn;
|
||||||
|
|
||||||
class Route : public SessionObject, public AutomatableControls
|
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 max_processor_streams () const { return processor_max_streams; }
|
||||||
ChanCount pre_fader_streams() const;
|
|
||||||
|
|
||||||
/* special processors */
|
/* special processors */
|
||||||
|
|
||||||
boost::shared_ptr<Delivery> control_outs() const { return _control_outs; }
|
boost::shared_ptr<Delivery> control_outs() const { return _control_outs; }
|
||||||
boost::shared_ptr<Delivery> main_outs() const { return _main_outs; }
|
boost::shared_ptr<Delivery> main_outs() const { return _main_outs; }
|
||||||
|
boost::shared_ptr<InternalReturn> internal_return() const { return _intreturn; }
|
||||||
boost::shared_ptr<Send> send_for (boost::shared_ptr<const IO> target) const;
|
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.
|
/** 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.
|
* 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;
|
sigc::signal<void,void*> SelectedChanged;
|
||||||
|
|
||||||
int listen_via (boost::shared_ptr<IO>, const std::string& name);
|
int listen_via (boost::shared_ptr<Route>, const std::string& name);
|
||||||
void drop_listen (boost::shared_ptr<IO>);
|
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;
|
std::set<boost::shared_ptr<Route> > fed_by;
|
||||||
|
|
||||||
/* Controls (not all directly owned by the Route */
|
/* Controls (not all directly owned by the Route */
|
||||||
|
|
@ -341,6 +341,7 @@ class Route : public SessionObject, public AutomatableControls
|
||||||
mutable Glib::RWLock _processor_lock;
|
mutable Glib::RWLock _processor_lock;
|
||||||
boost::shared_ptr<Delivery> _main_outs;
|
boost::shared_ptr<Delivery> _main_outs;
|
||||||
boost::shared_ptr<Delivery> _control_outs; // XXX to be removed/generalized by listen points
|
boost::shared_ptr<Delivery> _control_outs; // XXX to be removed/generalized by listen points
|
||||||
|
boost::shared_ptr<InternalReturn> _intreturn;
|
||||||
|
|
||||||
Flag _flags;
|
Flag _flags;
|
||||||
int _pending_declick;
|
int _pending_declick;
|
||||||
|
|
@ -381,8 +382,6 @@ class Route : public SessionObject, public AutomatableControls
|
||||||
|
|
||||||
virtual int _set_state (const XMLNode&, bool call_base);
|
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<Amp> _amp;
|
||||||
boost::shared_ptr<PeakMeter> _meter;
|
boost::shared_ptr<PeakMeter> _meter;
|
||||||
sigc::connection _meter_connection;
|
sigc::connection _meter_connection;
|
||||||
|
|
|
||||||
|
|
@ -37,8 +37,8 @@ class Amp;
|
||||||
class Send : public Delivery
|
class Send : public Delivery
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Send (Session&, boost::shared_ptr<MuteMaster>);
|
Send (Session&, boost::shared_ptr<MuteMaster>, bool internal = false);
|
||||||
Send (Session&, boost::shared_ptr<MuteMaster>, const XMLNode&);
|
Send (Session&, boost::shared_ptr<MuteMaster>, const XMLNode&, bool internal = false);
|
||||||
virtual ~Send ();
|
virtual ~Send ();
|
||||||
|
|
||||||
uint32_t bit_slot() const { return _bitslot; }
|
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> control_out() const { return _control_out; }
|
||||||
boost::shared_ptr<Route> master_out() const { return _master_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) {
|
static void set_disable_all_loaded_plugins (bool yn) {
|
||||||
_disable_all_loaded_plugins = yn;
|
_disable_all_loaded_plugins = yn;
|
||||||
}
|
}
|
||||||
|
|
@ -1558,16 +1552,9 @@ class Session : public PBD::StatefulDestructible, public boost::noncopyable
|
||||||
|
|
||||||
/* INSERT AND SEND MANAGEMENT */
|
/* 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> send_bitset;
|
||||||
boost::dynamic_bitset<uint32_t> return_bitset;
|
boost::dynamic_bitset<uint32_t> return_bitset;
|
||||||
boost::dynamic_bitset<uint32_t> insert_bitset;
|
boost::dynamic_bitset<uint32_t> insert_bitset;
|
||||||
uint32_t send_cnt;
|
|
||||||
uint32_t insert_cnt;
|
|
||||||
|
|
||||||
|
|
||||||
void add_processor (Processor *);
|
void add_processor (Processor *);
|
||||||
void remove_processor (Processor *);
|
void remove_processor (Processor *);
|
||||||
|
|
|
||||||
|
|
@ -31,23 +31,23 @@
|
||||||
|
|
||||||
#include "midi++/jack.h"
|
#include "midi++/jack.h"
|
||||||
|
|
||||||
|
#include "ardour/amp.h"
|
||||||
|
#include "ardour/audio_port.h"
|
||||||
#include "ardour/audioengine.h"
|
#include "ardour/audioengine.h"
|
||||||
#include "ardour/buffer.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/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/timestamps.h"
|
||||||
|
#include "ardour/utils.h"
|
||||||
|
|
||||||
#include "i18n.h"
|
#include "i18n.h"
|
||||||
|
|
||||||
|
|
@ -364,6 +364,7 @@ AudioEngine::process_callback (nframes_t nframes)
|
||||||
|
|
||||||
Delivery::CycleStart (nframes);
|
Delivery::CycleStart (nframes);
|
||||||
Port::set_port_offset (0);
|
Port::set_port_offset (0);
|
||||||
|
InternalReturn::CycleStart (nframes);
|
||||||
|
|
||||||
/* tell all Ports that we're starting a new cycle */
|
/* tell all Ports that we're starting a new cycle */
|
||||||
|
|
||||||
|
|
@ -822,10 +823,15 @@ AudioEngine::frames_per_cycle ()
|
||||||
Port *
|
Port *
|
||||||
AudioEngine::get_port_by_name (const string& portname)
|
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);
|
Glib::Mutex::Lock lm (_process_lock);
|
||||||
return get_port_by_name_locked (portname);
|
return get_port_by_name_locked (s);
|
||||||
}
|
}
|
||||||
|
|
||||||
Port *
|
Port *
|
||||||
|
|
|
||||||
|
|
@ -655,6 +655,14 @@ AudioRegion::set_live_state (const XMLNode& node, Change& what_changed, bool sen
|
||||||
_flags = Flag (_flags & ~Region::RightOfSplit);
|
_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) {
|
if ((old_flags ^ _flags) & Muted) {
|
||||||
what_changed = Change (what_changed|MuteChanged);
|
what_changed = Change (what_changed|MuteChanged);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -225,5 +225,32 @@ BufferSet::read_from (BufferSet& in, nframes_t nframes)
|
||||||
set_count(in.count());
|
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
|
} // namespace ARDOUR
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,7 @@ bool Delivery::panners_legal = false;
|
||||||
/* deliver to an existing IO object */
|
/* 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)
|
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)
|
, _role (r)
|
||||||
, _output_buffers (new BufferSet())
|
, _output_buffers (new BufferSet())
|
||||||
, _solo_level (0)
|
, _solo_level (0)
|
||||||
|
|
@ -58,13 +58,15 @@ Delivery::Delivery (Session& s, boost::shared_ptr<IO> io, boost::shared_ptr<Mute
|
||||||
_current_gain = 1.0;
|
_current_gain = 1.0;
|
||||||
_panner = boost::shared_ptr<Panner>(new Panner (_name, _session));
|
_panner = boost::shared_ptr<Panner>(new Panner (_name, _session));
|
||||||
|
|
||||||
|
if (_output) {
|
||||||
_output->changed.connect (mem_fun (*this, &Delivery::output_changed));
|
_output->changed.connect (mem_fun (*this, &Delivery::output_changed));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* deliver to a new IO object */
|
/* deliver to a new IO object */
|
||||||
|
|
||||||
Delivery::Delivery (Session& s, boost::shared_ptr<MuteMaster> mm, const string& name, Role r)
|
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)
|
, _role (r)
|
||||||
, _output_buffers (new BufferSet())
|
, _output_buffers (new BufferSet())
|
||||||
, _solo_level (0)
|
, _solo_level (0)
|
||||||
|
|
@ -75,8 +77,10 @@ Delivery::Delivery (Session& s, boost::shared_ptr<MuteMaster> mm, const string&
|
||||||
_current_gain = 1.0;
|
_current_gain = 1.0;
|
||||||
_panner = boost::shared_ptr<Panner>(new Panner (_name, _session));
|
_panner = boost::shared_ptr<Panner>(new Panner (_name, _session));
|
||||||
|
|
||||||
|
if (_output) {
|
||||||
_output->changed.connect (mem_fun (*this, &Delivery::output_changed));
|
_output->changed.connect (mem_fun (*this, &Delivery::output_changed));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* deliver to a new IO object, reconstruct from XML */
|
/* deliver to a new IO object, reconstruct from XML */
|
||||||
|
|
||||||
|
|
@ -96,8 +100,33 @@ Delivery::Delivery (Session& s, boost::shared_ptr<MuteMaster> mm, const XMLNode&
|
||||||
throw failed_constructor ();
|
throw failed_constructor ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_output) {
|
||||||
_output->changed.connect (mem_fun (*this, &Delivery::output_changed));
|
_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
|
void
|
||||||
Delivery::cycle_start (nframes_t nframes)
|
Delivery::cycle_start (nframes_t nframes)
|
||||||
|
|
@ -265,7 +294,16 @@ Delivery::reset_panner ()
|
||||||
{
|
{
|
||||||
if (panners_legal) {
|
if (panners_legal) {
|
||||||
if (!no_panner_reset) {
|
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 {
|
} else {
|
||||||
panner_legal_c.disconnect ();
|
panner_legal_c.disconnect ();
|
||||||
|
|
@ -276,7 +314,15 @@ Delivery::reset_panner ()
|
||||||
int
|
int
|
||||||
Delivery::panners_became_legal ()
|
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->load (); // automation
|
||||||
panner_legal_c.disconnect ();
|
panner_legal_c.disconnect ();
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -441,3 +487,4 @@ Delivery::output_changed (IOChange change, void* src)
|
||||||
reset_panner ();
|
reset_panner ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -396,7 +396,7 @@ setup_enum_writer ()
|
||||||
REGISTER_CLASS_ENUM (Region, LeftOfSplit);
|
REGISTER_CLASS_ENUM (Region, LeftOfSplit);
|
||||||
REGISTER_CLASS_ENUM (Region, RightOfSplit);
|
REGISTER_CLASS_ENUM (Region, RightOfSplit);
|
||||||
REGISTER_CLASS_ENUM (Region, Hidden);
|
REGISTER_CLASS_ENUM (Region, Hidden);
|
||||||
REGISTER_CLASS_ENUM (Region, DoNotSaveState);
|
REGISTER_CLASS_ENUM (Region, DoNotSendPropertyChanges);
|
||||||
REGISTER_BITS (_Region_Flag);
|
REGISTER_BITS (_Region_Flag);
|
||||||
|
|
||||||
REGISTER_CLASS_ENUM (Region, AudioTime);
|
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)
|
ARDOUR::LocaleGuard::LocaleGuard (const char* str)
|
||||||
{
|
{
|
||||||
old = strdup (setlocale (LC_NUMERIC, NULL));
|
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) {
|
if (with_output) {
|
||||||
_output.reset (new IO(s, io_name.empty() ? proc_name : io_name, IO::Output, dtype));
|
_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 */
|
/* 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)
|
, _input (in)
|
||||||
, _output (out)
|
, _output (out)
|
||||||
{
|
{
|
||||||
|
cerr << "XML create IOP name = " << proc_name << " in = " << in << " out = " << out << endl;
|
||||||
|
if (in) {
|
||||||
_own_input = false;
|
_own_input = false;
|
||||||
|
} else {
|
||||||
|
_own_input = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (out) {
|
||||||
_own_output = false;
|
_own_output = false;
|
||||||
|
} else {
|
||||||
|
_own_output = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
IOProcessor::~IOProcessor ()
|
IOProcessor::~IOProcessor ()
|
||||||
|
|
@ -107,10 +119,12 @@ IOProcessor::state (bool full_state)
|
||||||
XMLNode& node (Processor::state (full_state));
|
XMLNode& node (Processor::state (full_state));
|
||||||
|
|
||||||
if (_own_input) {
|
if (_own_input) {
|
||||||
|
node.add_property ("own-input", "yes");
|
||||||
|
if (_input) {
|
||||||
XMLNode& i (_input->state (full_state));
|
XMLNode& i (_input->state (full_state));
|
||||||
// i.name() = X_("output");
|
// i.name() = X_("output");
|
||||||
node.add_child_nocopy (i);
|
node.add_child_nocopy (i);
|
||||||
node.add_property ("own-input", "yes");
|
}
|
||||||
} else {
|
} else {
|
||||||
node.add_property ("own-input", "no");
|
node.add_property ("own-input", "no");
|
||||||
if (_input) {
|
if (_input) {
|
||||||
|
|
@ -119,10 +133,12 @@ IOProcessor::state (bool full_state)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_own_output) {
|
if (_own_output) {
|
||||||
|
node.add_property ("own-output", "yes");
|
||||||
|
if (_output) {
|
||||||
XMLNode& o (_output->state (full_state));
|
XMLNode& o (_output->state (full_state));
|
||||||
// o.name() = X_("output");
|
// o.name() = X_("output");
|
||||||
node.add_child_nocopy (o);
|
node.add_child_nocopy (o);
|
||||||
node.add_property ("own-output", "yes");
|
}
|
||||||
} else {
|
} else {
|
||||||
node.add_property ("own-output", "no");
|
node.add_property ("own-output", "no");
|
||||||
if (_output) {
|
if (_output) {
|
||||||
|
|
@ -173,9 +189,9 @@ IOProcessor::set_state (const XMLNode& node)
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
error << _("XML node describing an IOProcessor is missing an IO node") << endmsg;
|
/* no input */
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_own_output) {
|
if (_own_output) {
|
||||||
|
|
@ -193,6 +209,8 @@ IOProcessor::set_state (const XMLNode& node)
|
||||||
if ((prop = node.property ("name")) == 0) {
|
if ((prop = node.property ("name")) == 0) {
|
||||||
set_name (_output->name());
|
set_name (_output->name());
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
/* no output */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -246,3 +264,9 @@ IOProcessor::set_name (const std::string& name)
|
||||||
|
|
||||||
return ret;
|
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
|
void
|
||||||
PeakMeter::reset ()
|
PeakMeter::reset ()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -99,6 +99,17 @@ MidiBuffer::read_from (const Buffer& src, nframes_t nframes, nframes_t dst_offse
|
||||||
_silent = src.silent();
|
_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.
|
/** Push an event into the buffer.
|
||||||
*
|
*
|
||||||
* Note that the raw MIDI pointed to by ev will be COPIED and unmodified.
|
* 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) {
|
if (inbufs.count().n_audio() > 0) {
|
||||||
BufferSet::audio_iterator i = inbufs.audio_begin();
|
BufferSet::audio_iterator i = inbufs.audio_begin();
|
||||||
for (++i; i != inbufs.audio_end(); ++i) {
|
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
|
// accumulate starting with the second
|
||||||
BufferSet::audio_iterator i = inbufs.audio_begin();
|
BufferSet::audio_iterator i = inbufs.audio_begin();
|
||||||
for (++i; i != inbufs.audio_end(); ++i) {
|
for (++i; i != inbufs.audio_end(); ++i) {
|
||||||
dst.accumulate_from(*i, nframes);
|
dst.merge_from(*i, nframes);
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
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&
|
XMLNode&
|
||||||
Processor::get_state (void)
|
Processor::get_state (void)
|
||||||
{
|
{
|
||||||
|
|
@ -141,6 +152,9 @@ Processor::set_state (const XMLNode& node)
|
||||||
// may not exist for legacy 3.0 sessions
|
// may not exist for legacy 3.0 sessions
|
||||||
if ((prop = node.property ("id")) != 0) {
|
if ((prop = node.property ("id")) != 0) {
|
||||||
_id = prop->value();
|
_id = prop->value();
|
||||||
|
cerr << "---------------- ID for processor " << name() << " = " << _id << endl;
|
||||||
|
} else {
|
||||||
|
cerr << "---------------- NO ID for processor " << name() << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
XMLNodeList nlist = node.children();
|
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)
|
Region::Region (Session& s, nframes_t start, nframes_t length, const string& name, DataType type, layer_t layer, Region::Flag flags)
|
||||||
: SessionObject(s, name)
|
: SessionObject(s, name)
|
||||||
, _type(type)
|
, _type(type)
|
||||||
, _flags(flags)
|
, _flags(Flag (flags|DoNotSendPropertyChanges))
|
||||||
, _start(start)
|
, _start(start)
|
||||||
, _length(length)
|
, _length(length)
|
||||||
, _position(0)
|
, _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)
|
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)
|
: SessionObject(src->session(), name)
|
||||||
, _type(type)
|
, _type(type)
|
||||||
, _flags(flags)
|
, _flags(Flag (flags|DoNotSendPropertyChanges))
|
||||||
, _start(start)
|
, _start(start)
|
||||||
, _length(length)
|
, _length(length)
|
||||||
, _position(0)
|
, _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)
|
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)
|
: SessionObject(srcs.front()->session(), name)
|
||||||
, _type(type)
|
, _type(type)
|
||||||
, _flags(flags)
|
, _flags(Flag (flags|DoNotSendPropertyChanges))
|
||||||
, _start(start)
|
, _start(start)
|
||||||
, _length(length)
|
, _length(length)
|
||||||
, _position(0)
|
, _position(0)
|
||||||
|
|
@ -150,6 +150,8 @@ Region::Region (boost::shared_ptr<const Region> other, nframes_t offset, nframes
|
||||||
_start = other->_start + offset;
|
_start = other->_start + offset;
|
||||||
copy_stuff (other, offset, length, name, layer, flags);
|
copy_stuff (other, offset, length, name, layer, flags);
|
||||||
|
|
||||||
|
_flags = Flag (_flags | DoNotSendPropertyChanges);
|
||||||
|
|
||||||
/* if the other region had a distinct sync point
|
/* if the other region had a distinct sync point
|
||||||
set, then continue to use it as best we can.
|
set, then continue to use it as best we can.
|
||||||
otherwise, reset sync point back to start.
|
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;
|
_start = 0;
|
||||||
copy_stuff (other, 0, length, name, layer, flags);
|
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,
|
/* 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
|
so set our sync position to whatever the the difference between
|
||||||
_start and _sync_pos was in the other region.
|
_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))
|
, _pending_changed(Change(0))
|
||||||
, _last_layer_op(other->_last_layer_op)
|
, _last_layer_op(other->_last_layer_op)
|
||||||
{
|
{
|
||||||
|
_flags = Flag (_flags | DoNotSendPropertyChanges);
|
||||||
|
|
||||||
other->_first_edit = EditChangesName;
|
other->_first_edit = EditChangesName;
|
||||||
|
|
||||||
if (other->_extra_xml) {
|
if (other->_extra_xml) {
|
||||||
|
|
@ -268,7 +274,7 @@ Region::Region (boost::shared_ptr<const Region> other)
|
||||||
Region::Region (const SourceList& srcs, const XMLNode& node)
|
Region::Region (const SourceList& srcs, const XMLNode& node)
|
||||||
: SessionObject(srcs.front()->session(), X_("error: XML did not reset this"))
|
: SessionObject(srcs.front()->session(), X_("error: XML did not reset this"))
|
||||||
, _type(DataType::NIL) // to be loaded from XML
|
, _type(DataType::NIL) // to be loaded from XML
|
||||||
, _flags(Flag(0))
|
, _flags(DoNotSendPropertyChanges)
|
||||||
, _start(0)
|
, _start(0)
|
||||||
, _length(0)
|
, _length(0)
|
||||||
, _position(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)
|
Region::Region (boost::shared_ptr<Source> src, const XMLNode& node)
|
||||||
: SessionObject(src->session(), X_("error: XML did not reset this"))
|
: SessionObject(src->session(), X_("error: XML did not reset this"))
|
||||||
, _type(DataType::NIL)
|
, _type(DataType::NIL)
|
||||||
, _flags(Flag(0))
|
, _flags(DoNotSendPropertyChanges)
|
||||||
, _start(0)
|
, _start(0)
|
||||||
, _length(0)
|
, _length(0)
|
||||||
, _position(0)
|
, _position(0)
|
||||||
|
|
@ -1400,7 +1406,7 @@ Region::send_change (Change what_changed)
|
||||||
|
|
||||||
StateChanged (what_changed);
|
StateChanged (what_changed);
|
||||||
|
|
||||||
if (!(_flags & DoNotSaveState)) {
|
if (!(_flags & DoNotSendPropertyChanges)) {
|
||||||
|
|
||||||
/* Try and send a shared_pointer unless this is part of the constructor.
|
/* Try and send a shared_pointer unless this is part of the constructor.
|
||||||
If so, do nothing.
|
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);
|
AudioRegion* ar = new AudioRegion (other_a, start, length, name, layer, flags);
|
||||||
boost::shared_ptr<AudioRegion> arp (ar);
|
boost::shared_ptr<AudioRegion> arp (ar);
|
||||||
boost::shared_ptr<Region> ret (boost::static_pointer_cast<Region> (arp));
|
boost::shared_ptr<Region> ret (boost::static_pointer_cast<Region> (arp));
|
||||||
|
ret->unlock_property_changes ();
|
||||||
if (announce) {
|
if (announce) {
|
||||||
CheckNewRegion (ret);
|
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);
|
MidiRegion* ar = new MidiRegion (other_m, start, length, name, layer, flags);
|
||||||
boost::shared_ptr<MidiRegion> arp (ar);
|
boost::shared_ptr<MidiRegion> arp (ar);
|
||||||
boost::shared_ptr<Region> ret (boost::static_pointer_cast<Region> (arp));
|
boost::shared_ptr<Region> ret (boost::static_pointer_cast<Region> (arp));
|
||||||
|
ret->unlock_property_changes ();
|
||||||
if (announce) {
|
if (announce) {
|
||||||
CheckNewRegion (ret);
|
CheckNewRegion (ret);
|
||||||
}
|
}
|
||||||
|
|
@ -75,10 +77,12 @@ RegionFactory::create (boost::shared_ptr<const Region> region)
|
||||||
|
|
||||||
if ((ar = boost::dynamic_pointer_cast<const AudioRegion>(region)) != 0) {
|
if ((ar = boost::dynamic_pointer_cast<const AudioRegion>(region)) != 0) {
|
||||||
boost::shared_ptr<Region> ret (new AudioRegion (ar));
|
boost::shared_ptr<Region> ret (new AudioRegion (ar));
|
||||||
|
ret->unlock_property_changes ();
|
||||||
/* pure copy constructor - no CheckNewRegion emitted */
|
/* pure copy constructor - no CheckNewRegion emitted */
|
||||||
return ret;
|
return ret;
|
||||||
} else if ((mr = boost::dynamic_pointer_cast<const MidiRegion>(region)) != 0) {
|
} else if ((mr = boost::dynamic_pointer_cast<const MidiRegion>(region)) != 0) {
|
||||||
boost::shared_ptr<Region> ret (new MidiRegion (mr));
|
boost::shared_ptr<Region> ret (new MidiRegion (mr));
|
||||||
|
ret->unlock_property_changes ();
|
||||||
/* pure copy constructor - no CheckNewRegion emitted */
|
/* pure copy constructor - no CheckNewRegion emitted */
|
||||||
return ret;
|
return ret;
|
||||||
} else {
|
} 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);
|
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<AudioRegion> arp (ar);
|
||||||
boost::shared_ptr<Region> ret (boost::static_pointer_cast<Region> (arp));
|
boost::shared_ptr<Region> ret (boost::static_pointer_cast<Region> (arp));
|
||||||
|
ret->unlock_property_changes ();
|
||||||
if (announce) {
|
if (announce) {
|
||||||
CheckNewRegion (ret);
|
CheckNewRegion (ret);
|
||||||
}
|
}
|
||||||
|
|
@ -128,6 +133,7 @@ boost::shared_ptr<Region>
|
||||||
RegionFactory::create (Session& session, XMLNode& node, bool yn)
|
RegionFactory::create (Session& session, XMLNode& node, bool yn)
|
||||||
{
|
{
|
||||||
boost::shared_ptr<Region> r = session.XMLRegionFactory (node, yn);
|
boost::shared_ptr<Region> r = session.XMLRegionFactory (node, yn);
|
||||||
|
r->unlock_property_changes ();
|
||||||
|
|
||||||
if (r) {
|
if (r) {
|
||||||
CheckNewRegion (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);
|
AudioRegion* ar = new AudioRegion (srcs, start, length, name, layer, flags);
|
||||||
boost::shared_ptr<AudioRegion> arp (ar);
|
boost::shared_ptr<AudioRegion> arp (ar);
|
||||||
boost::shared_ptr<Region> ret (boost::static_pointer_cast<Region> (arp));
|
boost::shared_ptr<Region> ret (boost::static_pointer_cast<Region> (arp));
|
||||||
|
ret->unlock_property_changes ();
|
||||||
if (announce) {
|
if (announce) {
|
||||||
CheckNewRegion (ret);
|
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);
|
MidiRegion* ar = new MidiRegion (srcs, start, length, name, layer, flags);
|
||||||
boost::shared_ptr<MidiRegion> mrp (ar);
|
boost::shared_ptr<MidiRegion> mrp (ar);
|
||||||
boost::shared_ptr<Region> ret (boost::static_pointer_cast<Region> (mrp));
|
boost::shared_ptr<Region> ret (boost::static_pointer_cast<Region> (mrp));
|
||||||
|
ret->unlock_property_changes ();
|
||||||
if (announce) {
|
if (announce) {
|
||||||
CheckNewRegion (ret);
|
CheckNewRegion (ret);
|
||||||
}
|
}
|
||||||
|
|
@ -177,10 +185,12 @@ RegionFactory::create (SourceList& srcs, const XMLNode& node)
|
||||||
|
|
||||||
if (srcs[0]->type() == DataType::AUDIO) {
|
if (srcs[0]->type() == DataType::AUDIO) {
|
||||||
boost::shared_ptr<Region> ret (new AudioRegion (srcs, node));
|
boost::shared_ptr<Region> ret (new AudioRegion (srcs, node));
|
||||||
|
ret->unlock_property_changes ();
|
||||||
CheckNewRegion (ret);
|
CheckNewRegion (ret);
|
||||||
return ret;
|
return ret;
|
||||||
} else if (srcs[0]->type() == DataType::MIDI) {
|
} else if (srcs[0]->type() == DataType::MIDI) {
|
||||||
boost::shared_ptr<Region> ret (new MidiRegion (srcs, node));
|
boost::shared_ptr<Region> ret (new MidiRegion (srcs, node));
|
||||||
|
ret->unlock_property_changes ();
|
||||||
CheckNewRegion (ret);
|
CheckNewRegion (ret);
|
||||||
return 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) {
|
if ((as = boost::dynamic_pointer_cast<AudioSource>(src)) != 0) {
|
||||||
boost::shared_ptr<Region> ret (new AudioRegion (as, start, length, name, layer, flags));
|
boost::shared_ptr<Region> ret (new AudioRegion (as, start, length, name, layer, flags));
|
||||||
|
ret->unlock_property_changes ();
|
||||||
if (announce) {
|
if (announce) {
|
||||||
CheckNewRegion (ret);
|
CheckNewRegion (ret);
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
} else if ((ms = boost::dynamic_pointer_cast<MidiSource>(src)) != 0) {
|
} else if ((ms = boost::dynamic_pointer_cast<MidiSource>(src)) != 0) {
|
||||||
boost::shared_ptr<Region> ret (new MidiRegion (ms, start, length, name, layer, flags));
|
boost::shared_ptr<Region> ret (new MidiRegion (ms, start, length, name, layer, flags));
|
||||||
|
ret->unlock_property_changes ();
|
||||||
if (announce) {
|
if (announce) {
|
||||||
CheckNewRegion (ret);
|
CheckNewRegion (ret);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -36,8 +36,9 @@
|
||||||
using namespace ARDOUR;
|
using namespace ARDOUR;
|
||||||
using namespace PBD;
|
using namespace PBD;
|
||||||
|
|
||||||
Return::Return (Session& s)
|
Return::Return (Session& s, bool internal)
|
||||||
: IOProcessor (s, true, false, string_compose (_("return %1"), (_bitslot = s.next_return_id()) + 1))
|
: IOProcessor (s, (internal ? false : true), false,
|
||||||
|
string_compose (_("return %1"), (_bitslot = s.next_return_id()) + 1))
|
||||||
, _metering (false)
|
, _metering (false)
|
||||||
{
|
{
|
||||||
/* never muted */
|
/* never muted */
|
||||||
|
|
@ -48,8 +49,8 @@ Return::Return (Session& s)
|
||||||
ProcessorCreated (this); /* EMIT SIGNAL */
|
ProcessorCreated (this); /* EMIT SIGNAL */
|
||||||
}
|
}
|
||||||
|
|
||||||
Return::Return (Session& s, const XMLNode& node)
|
Return::Return (Session& s, const XMLNode& node, bool internal)
|
||||||
: IOProcessor (s, true, false, "return")
|
: IOProcessor (s, (internal ? false : true), false, "return")
|
||||||
, _metering (false)
|
, _metering (false)
|
||||||
{
|
{
|
||||||
/* never muted */
|
/* never muted */
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,8 @@
|
||||||
#include "ardour/configuration.h"
|
#include "ardour/configuration.h"
|
||||||
#include "ardour/cycle_timer.h"
|
#include "ardour/cycle_timer.h"
|
||||||
#include "ardour/dB.h"
|
#include "ardour/dB.h"
|
||||||
|
#include "ardour/internal_send.h"
|
||||||
|
#include "ardour/internal_return.h"
|
||||||
#include "ardour/ladspa_plugin.h"
|
#include "ardour/ladspa_plugin.h"
|
||||||
#include "ardour/meter.h"
|
#include "ardour/meter.h"
|
||||||
#include "ardour/mix.h"
|
#include "ardour/mix.h"
|
||||||
|
|
@ -73,6 +75,24 @@ Route::Route (Session& sess, string name, Flag flg, DataType default_type)
|
||||||
|
|
||||||
{
|
{
|
||||||
init ();
|
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)
|
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)
|
, _default_type (default_type)
|
||||||
{
|
{
|
||||||
init ();
|
init ();
|
||||||
|
|
||||||
_set_state (node, false);
|
_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
|
void
|
||||||
|
|
@ -123,20 +148,10 @@ Route::init ()
|
||||||
_input->changed.connect (mem_fun (this, &Route::input_change_handler));
|
_input->changed.connect (mem_fun (this, &Route::input_change_handler));
|
||||||
_output->changed.connect (mem_fun (this, &Route::output_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));
|
_amp.reset (new Amp (_session, _mute_master));
|
||||||
add_processor (_amp, PostFader);
|
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 ()
|
Route::~Route ()
|
||||||
|
|
@ -316,7 +331,7 @@ Route::process_output_buffers (BufferSet& bufs,
|
||||||
switch (Config->get_monitoring_model()) {
|
switch (Config->get_monitoring_model()) {
|
||||||
case HardwareMonitoring:
|
case HardwareMonitoring:
|
||||||
case ExternalMonitoring:
|
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;
|
break;
|
||||||
default:
|
default:
|
||||||
monitor = true;
|
monitor = true;
|
||||||
|
|
@ -327,13 +342,13 @@ Route::process_output_buffers (BufferSet& bufs,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* figure out if we're going to use gain automation */
|
/* figure out if we're going to use gain automation */
|
||||||
|
|
||||||
_amp->setup_gain_automation (start_frame, end_frame, nframes);
|
_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);
|
_main_outs->no_outs_cuz_we_no_monitor (!monitor);
|
||||||
|
|
||||||
|
|
||||||
/* -------------------------------------------------------------------------------------------
|
/* -------------------------------------------------------------------------------------------
|
||||||
GLOBAL DECLICK (for transport changes etc.)
|
GLOBAL DECLICK (for transport changes etc.)
|
||||||
----------------------------------------------------------------------------------------- */
|
----------------------------------------------------------------------------------------- */
|
||||||
|
|
@ -520,25 +535,16 @@ Route::muted() const
|
||||||
return _mute_master->muted ();
|
return _mute_master->muted ();
|
||||||
}
|
}
|
||||||
|
|
||||||
#if DEFINE_IF_YOU_NEED_THIS
|
|
||||||
static void
|
static void
|
||||||
dump_processors(const string& name, const list<boost::shared_ptr<Processor> >& procs)
|
dump_processors(const string& name, const list<boost::shared_ptr<Processor> >& procs)
|
||||||
{
|
{
|
||||||
cerr << name << " {" << endl;
|
cerr << name << " {" << endl;
|
||||||
for (list<boost::shared_ptr<Processor> >::const_iterator p = procs.begin();
|
for (list<boost::shared_ptr<Processor> >::const_iterator p = procs.begin();
|
||||||
p != procs.end(); ++p) {
|
p != procs.end(); ++p) {
|
||||||
cerr << "\t" << (*p)->name() << endl;
|
cerr << "\t" << (*p)->name() << " ID = " << (*p)->id() << endl;
|
||||||
}
|
}
|
||||||
cerr << "}" << endl;
|
cerr << "}" << endl;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
Route::ProcessorList::iterator
|
|
||||||
Route::prefader_iterator()
|
|
||||||
{
|
|
||||||
Glib::RWLock::ReaderLock lm (_processor_lock);
|
|
||||||
return find (_processors.begin(), _processors.end(), _amp);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
int
|
||||||
Route::add_processor (boost::shared_ptr<Processor> processor, Placement placement, ProcessorStreams* err)
|
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;
|
loc = iter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cerr << "Adding " << processor->name() << " @ " << processor << endl;
|
||||||
|
|
||||||
_processors.insert (loc, processor);
|
_processors.insert (loc, processor);
|
||||||
|
|
||||||
// Set up processor list channels. This will set processor->[input|output]_streams(),
|
// 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;
|
--ploc;
|
||||||
_processors.erase(ploc);
|
_processors.erase(ploc);
|
||||||
configure_processors_unlocked (0); // it worked before we tried to add it ...
|
configure_processors_unlocked (0); // it worked before we tried to add it ...
|
||||||
|
cerr << "configure failed\n";
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -660,6 +669,7 @@ bool
|
||||||
Route::add_processor_from_xml (const XMLNode& node, Placement placement)
|
Route::add_processor_from_xml (const XMLNode& node, Placement placement)
|
||||||
{
|
{
|
||||||
ProcessorList::iterator loc;
|
ProcessorList::iterator loc;
|
||||||
|
|
||||||
if (placement == PreFader) {
|
if (placement == PreFader) {
|
||||||
/* generic pre-fader: insert immediately before the amp */
|
/* generic pre-fader: insert immediately before the amp */
|
||||||
loc = find(_processors.begin(), _processors.end(), _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;
|
cerr << _name << " : got processor type " << prop->value() << endl;
|
||||||
|
|
||||||
boost::shared_ptr<Processor> processor;
|
boost::shared_ptr<Processor> processor;
|
||||||
bool have_insert = false;
|
|
||||||
|
|
||||||
if (prop->value() == "ladspa" || prop->value() == "Ladspa" ||
|
if (prop->value() == "ladspa" || prop->value() == "Ladspa" ||
|
||||||
prop->value() == "lv2" ||
|
prop->value() == "lv2" ||
|
||||||
|
|
@ -707,7 +716,6 @@ Route::add_processor_from_xml (const XMLNode& node, ProcessorList::iterator iter
|
||||||
prop->value() == "audiounit") {
|
prop->value() == "audiounit") {
|
||||||
|
|
||||||
processor.reset (new PluginInsert(_session, node));
|
processor.reset (new PluginInsert(_session, node));
|
||||||
have_insert = true;
|
|
||||||
|
|
||||||
} else if (prop->value() == "port") {
|
} 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") {
|
} else if (prop->value() == "send") {
|
||||||
|
|
||||||
processor.reset (new Send (_session, _mute_master, node));
|
processor.reset (new Send (_session, _mute_master, node));
|
||||||
have_insert = true;
|
|
||||||
|
|
||||||
} else if (prop->value() == "meter") {
|
} 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 = _meter;
|
||||||
processor->set_state (node);
|
|
||||||
|
|
||||||
} else if (prop->value() == "amp") {
|
} else if (prop->value() == "amp") {
|
||||||
|
|
||||||
|
/* amp always exists */
|
||||||
|
|
||||||
processor = _amp;
|
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") {
|
} else if (prop->value() == "listen" || prop->value() == "deliver") {
|
||||||
|
|
||||||
/* XXX need to generalize */
|
/* XXX need to generalize */
|
||||||
|
|
||||||
processor = _control_outs;
|
} else if (prop->value() == "intsend") {
|
||||||
processor->set_state (node);
|
|
||||||
|
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") {
|
} 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 = _main_outs;
|
||||||
processor->set_state (node);
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
error << string_compose(_("unknown Processor type \"%1\"; ignored"), prop->value()) << endmsg;
|
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.
|
/** Remove processors with a given placement.
|
||||||
* @param p Placement of processors to remove.
|
* @param p Placement of processors to remove.
|
||||||
*/
|
*/
|
||||||
|
|
@ -1195,7 +1212,11 @@ Route::configure_processors_unlocked (ProcessorStreams* err)
|
||||||
ChanCount out;
|
ChanCount out;
|
||||||
list< pair<ChanCount,ChanCount> > configuration;
|
list< pair<ChanCount,ChanCount> > configuration;
|
||||||
uint32_t index = 0;
|
uint32_t index = 0;
|
||||||
|
|
||||||
|
cerr << "Processor check with " << _processors.size() << endl;
|
||||||
|
|
||||||
for (ProcessorList::iterator p = _processors.begin(); p != _processors.end(); ++p, ++index) {
|
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)) {
|
if ((*p)->can_support_io_configuration(in, out)) {
|
||||||
configuration.push_back(make_pair(in, out));
|
configuration.push_back(make_pair(in, out));
|
||||||
in = out;
|
in = out;
|
||||||
|
|
@ -1489,6 +1510,34 @@ Route::_set_state (const XMLNode& node, bool call_base)
|
||||||
_flags = Flag (0);
|
_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) {
|
if ((prop = node.property (X_("phase-invert"))) != 0) {
|
||||||
set_phase_invert (prop->value()=="yes"?true:false);
|
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){
|
for (niter = nlist.begin(); niter != nlist.end(); ++niter){
|
||||||
child = *niter;
|
child = *niter;
|
||||||
|
|
||||||
|
|
@ -1642,13 +1665,21 @@ Route::set_processor_state (const XMLNode& node)
|
||||||
{
|
{
|
||||||
const XMLNodeList &nlist = node.children();
|
const XMLNodeList &nlist = node.children();
|
||||||
XMLNodeConstIterator niter;
|
XMLNodeConstIterator niter;
|
||||||
bool has_meter_processor = false; // legacy sessions don't
|
|
||||||
ProcessorList::iterator i, o;
|
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
|
// Iterate through existing processors, remove those which are not in the state list
|
||||||
|
|
||||||
for (i = _processors.begin(); i != _processors.end(); ) {
|
for (i = _processors.begin(); i != _processors.end(); ) {
|
||||||
|
|
||||||
|
/* leave amp alone, always */
|
||||||
|
|
||||||
|
if ((*i) == _amp) {
|
||||||
|
++i;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
ProcessorList::iterator tmp = i;
|
ProcessorList::iterator tmp = i;
|
||||||
++tmp;
|
++tmp;
|
||||||
|
|
||||||
|
|
@ -1657,6 +1688,7 @@ Route::set_processor_state (const XMLNode& node)
|
||||||
for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
|
for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
|
||||||
|
|
||||||
XMLProperty* id_prop = (*niter)->property(X_("id"));
|
XMLProperty* id_prop = (*niter)->property(X_("id"));
|
||||||
|
cerr << "\tchecking " << id_prop->value() << endl;
|
||||||
if (id_prop && (*i)->id() == id_prop->value()) {
|
if (id_prop && (*i)->id() == id_prop->value()) {
|
||||||
processorInStateList = true;
|
processorInStateList = true;
|
||||||
break;
|
break;
|
||||||
|
|
@ -1672,22 +1704,20 @@ 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,
|
// 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
|
// set the state of existing processors according to the new state on the same go
|
||||||
|
|
||||||
i = _processors.begin();
|
i = _processors.begin();
|
||||||
|
|
||||||
for (niter = nlist.begin(); niter != nlist.end(); ++niter, ++i) {
|
for (niter = nlist.begin(); niter != nlist.end(); ++niter, ++i) {
|
||||||
|
|
||||||
XMLProperty* prop = (*niter)->property ("type");
|
XMLProperty* prop = (*niter)->property ("type");
|
||||||
|
|
||||||
if (prop && prop->value() == "meter") {
|
|
||||||
has_meter_processor = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
o = i;
|
o = i;
|
||||||
|
|
||||||
if (prop->value() != "meter" && prop->value() != "amp" && prop->value() != "main-outs") {
|
// Check whether the next processor in the list is the right one,
|
||||||
|
// except for "amp" which is always there and may not have the
|
||||||
// Check whether the next processor in the list
|
// old ID since it is always created anew in every Route
|
||||||
|
|
||||||
|
if (prop->value() != "amp") {
|
||||||
while (o != _processors.end()) {
|
while (o != _processors.end()) {
|
||||||
XMLProperty* id_prop = (*niter)->property(X_("id"));
|
XMLProperty* id_prop = (*niter)->property(X_("id"));
|
||||||
if (id_prop && (*o)->id() == id_prop->value()) {
|
if (id_prop && (*o)->id() == id_prop->value()) {
|
||||||
|
|
@ -1700,6 +1730,7 @@ Route::set_processor_state (const XMLNode& node)
|
||||||
|
|
||||||
// If the processor (*niter) is not on the route,
|
// If the processor (*niter) is not on the route,
|
||||||
// create it and move it to the correct location
|
// create it and move it to the correct location
|
||||||
|
|
||||||
if (o == _processors.end()) {
|
if (o == _processors.end()) {
|
||||||
|
|
||||||
if (add_processor_from_xml (**niter, i)) {
|
if (add_processor_from_xml (**niter, i)) {
|
||||||
|
|
@ -1708,9 +1739,10 @@ Route::set_processor_state (const XMLNode& node)
|
||||||
cerr << "Error restoring route: unable to restore processor" << endl;
|
cerr << "Error restoring route: unable to restore processor" << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
// Otherwise, the processor already exists; just
|
// Otherwise, the processor already exists; just
|
||||||
// ensure it is at the location provided in the XML state
|
// ensure it is at the location provided in the XML state
|
||||||
} else {
|
|
||||||
|
|
||||||
if (i != o) {
|
if (i != o) {
|
||||||
boost::shared_ptr<Processor> tmp = (*o);
|
boost::shared_ptr<Processor> tmp = (*o);
|
||||||
|
|
@ -1719,6 +1751,8 @@ Route::set_processor_state (const XMLNode& node)
|
||||||
--i; // move iterator to the correct processor
|
--i; // move iterator to the correct processor
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// and make it (just) so
|
||||||
|
|
||||||
(*i)->set_state (**niter);
|
(*i)->set_state (**niter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1727,10 +1761,6 @@ Route::set_processor_state (const XMLNode& node)
|
||||||
the XML state represents a working signal route.
|
the XML state represents a working signal route.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (!has_meter_processor) {
|
|
||||||
set_meter_point (_meter_point, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
processors_changed ();
|
processors_changed ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1772,33 +1802,38 @@ Route::silence (nframes_t nframes)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::shared_ptr<Delivery>
|
BufferSet*
|
||||||
Route::add_listener (boost::shared_ptr<IO> io, const string& listen_name)
|
Route::get_return_buffer () const
|
||||||
{
|
{
|
||||||
string name = _name;
|
Glib::RWLock::ReaderLock rm (_processor_lock);
|
||||||
name += '[';
|
|
||||||
name += listen_name;
|
|
||||||
name += ']';
|
|
||||||
|
|
||||||
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
|
if (d) {
|
||||||
* (we track the changes in ::output_change_handler()).
|
return d->get_buffers ();
|
||||||
* 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>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
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> ports;
|
||||||
vector<string>::const_iterator i;
|
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);
|
Glib::RWLock::ReaderLock rm (_processor_lock);
|
||||||
|
|
||||||
for (ProcessorList::const_iterator x = _processors.begin(); x != _processors.end(); ++x) {
|
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 */
|
/* already listening via the specified IO: do nothing */
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t ni = io->n_ports().n_total();
|
boost::shared_ptr<InternalSend> listener;
|
||||||
|
|
||||||
for (uint32_t n = 0; n < ni; ++n) {
|
try {
|
||||||
ports.push_back (io->nth (n)->name());
|
listener.reset (new InternalSend (_session, _mute_master, route));
|
||||||
}
|
|
||||||
|
|
||||||
if (ports.empty()) {
|
} catch (failed_constructor& err) {
|
||||||
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;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
add_processor (listener, PreFader);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Route::drop_listen (boost::shared_ptr<IO> io)
|
Route::drop_listen (boost::shared_ptr<Route> route)
|
||||||
{
|
{
|
||||||
ProcessorStreams err;
|
ProcessorStreams err;
|
||||||
ProcessorList::iterator tmp;
|
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(); ) {
|
for (ProcessorList::iterator x = _processors.begin(); x != _processors.end(); ) {
|
||||||
|
|
||||||
tmp = x;
|
boost::shared_ptr<InternalSend> d = boost::dynamic_pointer_cast<InternalSend>(*x);
|
||||||
++tmp;
|
|
||||||
|
|
||||||
boost::shared_ptr<Delivery> d = boost::dynamic_pointer_cast<Delivery>(*x);
|
if (d && d->target_route() == route) {
|
||||||
|
rl.release ();
|
||||||
if (d && d->output() == io) {
|
|
||||||
/* already listening via the specified IO: do nothing */
|
|
||||||
remove_processor (*x, &err);
|
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
|
void
|
||||||
|
|
@ -1939,25 +1961,30 @@ Route::set_comment (string cmt, void *src)
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* check IOProcessors which may also interconnect Routes */
|
|
||||||
|
|
||||||
for (ProcessorList::iterator r = _processors.begin(); r != _processors.end(); r++) {
|
for (ProcessorList::iterator r = _processors.begin(); r != _processors.end(); r++) {
|
||||||
|
|
||||||
boost::shared_ptr<IOProcessor> iop;
|
boost::shared_ptr<IOProcessor> iop;
|
||||||
|
|
||||||
if ((iop = boost::dynamic_pointer_cast<IOProcessor>(*r)) != 0) {
|
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;
|
return true;
|
||||||
|
} else {
|
||||||
|
// cerr << "\tIOP " << iop->name() << " does NOT feeds " << other->name() << endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// cerr << "\tdoes NOT FEED " << other->name() << endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2418,15 +2445,15 @@ Route::set_name (const string& str)
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::shared_ptr<Send>
|
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);
|
Glib::RWLock::ReaderLock lm (_processor_lock);
|
||||||
|
|
||||||
for (ProcessorList::const_iterator i = _processors.begin(); i != _processors.end(); ++i) {
|
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 = boost::dynamic_pointer_cast<InternalSend>(*i)) != 0) {
|
||||||
if (send->output()->connected_to (target)) {
|
if (send->target_route() == target) {
|
||||||
return send;
|
return send;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -36,8 +36,9 @@
|
||||||
using namespace ARDOUR;
|
using namespace ARDOUR;
|
||||||
using namespace PBD;
|
using namespace PBD;
|
||||||
|
|
||||||
Send::Send (Session& s, boost::shared_ptr<MuteMaster> mm)
|
Send::Send (Session& s, boost::shared_ptr<MuteMaster> mm, bool internal)
|
||||||
: Delivery (s, mm, string_compose (_("send %1"), (_bitslot = s.next_send_id()) + 1), Delivery::Send)
|
: Delivery (s, mm, string_compose (_("send %1"), (_bitslot = s.next_send_id()) + 1),
|
||||||
|
(internal ? Delivery::Listen : Delivery::Send))
|
||||||
, _metering (false)
|
, _metering (false)
|
||||||
{
|
{
|
||||||
_amp.reset (new Amp (_session, _mute_master));
|
_amp.reset (new Amp (_session, _mute_master));
|
||||||
|
|
@ -46,8 +47,8 @@ Send::Send (Session& s, boost::shared_ptr<MuteMaster> mm)
|
||||||
ProcessorCreated (this); /* EMIT SIGNAL */
|
ProcessorCreated (this); /* EMIT SIGNAL */
|
||||||
}
|
}
|
||||||
|
|
||||||
Send::Send (Session& s, boost::shared_ptr<MuteMaster> mm, const XMLNode& node)
|
Send::Send (Session& s, boost::shared_ptr<MuteMaster> mm, const XMLNode& node, bool internal)
|
||||||
: Delivery (s, mm, "send", Delivery::Send)
|
: Delivery (s, mm, "send", (internal ? Delivery::Listen : Delivery::Send))
|
||||||
, _metering (false)
|
, _metering (false)
|
||||||
{
|
{
|
||||||
_amp.reset (new Amp (_session, _mute_master));
|
_amp.reset (new Amp (_session, _mute_master));
|
||||||
|
|
@ -113,6 +114,7 @@ Send::state(bool full)
|
||||||
{
|
{
|
||||||
XMLNode& node = IOProcessor::state(full);
|
XMLNode& node = IOProcessor::state(full);
|
||||||
char buf[32];
|
char buf[32];
|
||||||
|
|
||||||
node.add_property ("type", "send");
|
node.add_property ("type", "send");
|
||||||
snprintf (buf, sizeof (buf), "%" PRIu32, _bitslot);
|
snprintf (buf, sizeof (buf), "%" PRIu32, _bitslot);
|
||||||
node.add_property ("bitslot", buf);
|
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_input_auto_connect (input_ac);
|
||||||
Config->set_output_auto_connect (output_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
|
it doesn't really scale that well to higher channel counts
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* mono output bundles */
|
||||||
|
|
||||||
for (uint32_t np = 0; np < n_physical_outputs; ++np) {
|
for (uint32_t np = 0; np < n_physical_outputs; ++np) {
|
||||||
char buf[32];
|
char buf[32];
|
||||||
snprintf (buf, sizeof (buf), _("out %" PRIu32), np+1);
|
snprintf (buf, sizeof (buf), _("out %" PRIu32), np+1);
|
||||||
|
|
@ -618,6 +625,8 @@ Session::when_engine_running ()
|
||||||
add_bundle (c);
|
add_bundle (c);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* stereo output bundles */
|
||||||
|
|
||||||
for (uint32_t np = 0; np < n_physical_outputs; np += 2) {
|
for (uint32_t np = 0; np < n_physical_outputs; np += 2) {
|
||||||
if (np + 1 < n_physical_outputs) {
|
if (np + 1 < n_physical_outputs) {
|
||||||
char buf[32];
|
char buf[32];
|
||||||
|
|
@ -632,6 +641,8 @@ Session::when_engine_running ()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* mono input bundles */
|
||||||
|
|
||||||
for (uint32_t np = 0; np < n_physical_inputs; ++np) {
|
for (uint32_t np = 0; np < n_physical_inputs; ++np) {
|
||||||
char buf[32];
|
char buf[32];
|
||||||
snprintf (buf, sizeof (buf), _("in %" PRIu32), np+1);
|
snprintf (buf, sizeof (buf), _("in %" PRIu32), np+1);
|
||||||
|
|
@ -643,6 +654,8 @@ Session::when_engine_running ()
|
||||||
add_bundle (c);
|
add_bundle (c);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* stereo input bundles */
|
||||||
|
|
||||||
for (uint32_t np = 0; np < n_physical_inputs; np += 2) {
|
for (uint32_t np = 0; np < n_physical_inputs; np += 2) {
|
||||||
if (np + 1 < n_physical_inputs) {
|
if (np + 1 < n_physical_inputs) {
|
||||||
char buf[32];
|
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();
|
uint32_t limit = _master_out->n_outputs().n_total();
|
||||||
|
|
||||||
for (uint32_t n = 0; n < limit; ++n) {
|
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"));
|
BootMessage (_("Setup signal flow and plugins"));
|
||||||
|
|
@ -689,33 +719,6 @@ Session::when_engine_running ()
|
||||||
|
|
||||||
/* catch up on send+insert cnts */
|
/* 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));
|
_state_of_the_state = StateOfTheState (_state_of_the_state & ~(CannotSave|Dirty));
|
||||||
|
|
||||||
/* hook us up to the engine */
|
/* 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 */
|
/* load bundles, which we may have postponed earlier on */
|
||||||
if (_bundle_xml_node) {
|
if (_bundle_xml_node) {
|
||||||
load_bundles (*_bundle_xml_node);
|
load_bundles (*_bundle_xml_node);
|
||||||
|
|
@ -783,6 +768,22 @@ Session::hookup_io ()
|
||||||
|
|
||||||
Delivery::reset_panners ();
|
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 */
|
/* Anyone who cares about input state, wake up and do something */
|
||||||
|
|
||||||
IOConnectionsComplete (); /* EMIT SIGNAL */
|
IOConnectionsComplete (); /* EMIT SIGNAL */
|
||||||
|
|
@ -1455,7 +1456,7 @@ Session::resort_routes_using (shared_ptr<RouteList> r)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((*j)->feeds ((*i)->input())) {
|
if ((*j)->feeds (*i)) {
|
||||||
(*i)->fed_by.insert (*j);
|
(*i)->fed_by.insert (*j);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -2064,8 +2065,11 @@ Session::add_routes (RouteList& new_routes, bool save)
|
||||||
RCUWriter<RouteList> writer (routes);
|
RCUWriter<RouteList> writer (routes);
|
||||||
shared_ptr<RouteList> r = writer.get_copy ();
|
shared_ptr<RouteList> r = writer.get_copy ();
|
||||||
r->insert (r->end(), new_routes.begin(), new_routes.end());
|
r->insert (r->end(), new_routes.begin(), new_routes.end());
|
||||||
|
|
||||||
|
if (!_control_out && IO::connecting_legal) {
|
||||||
resort_routes_using (r);
|
resort_routes_using (r);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (RouteList::iterator x = new_routes.begin(); x != new_routes.end(); ++x) {
|
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) {
|
if (_control_out && IO::connecting_legal) {
|
||||||
|
|
||||||
for (RouteList::iterator x = new_routes.begin(); x != new_routes.end(); ++x) {
|
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();
|
set_dirty();
|
||||||
|
|
@ -2145,13 +2151,14 @@ Session::remove_route (shared_ptr<Route> route)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (route == _control_out) {
|
if (route == _control_out) {
|
||||||
|
|
||||||
/* cancel control outs for all routes */
|
/* cancel control outs for all routes */
|
||||||
|
|
||||||
for (RouteList::iterator r = rs->begin(); r != rs->end(); ++r) {
|
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 ();
|
update_route_solo_state ();
|
||||||
|
|
@ -2238,7 +2245,7 @@ Session::route_solo_changed (void* src, boost::weak_ptr<Route> wpr)
|
||||||
solo_update_disabled = true;
|
solo_update_disabled = true;
|
||||||
for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
|
for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
|
||||||
|
|
||||||
if ((*i)->feeds (route->input())) {
|
if ((*i)->feeds (route)) {
|
||||||
/* do it */
|
/* do it */
|
||||||
|
|
||||||
(*i)->main_outs()->mod_solo_level (delta);
|
(*i)->main_outs()->mod_solo_level (delta);
|
||||||
|
|
@ -3533,26 +3540,7 @@ Session::record_enable_change_all (bool yn)
|
||||||
void
|
void
|
||||||
Session::add_processor (Processor* processor)
|
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));
|
processor->GoingAway.connect (sigc::bind (mem_fun (*this, &Session::remove_processor), processor));
|
||||||
|
|
||||||
set_dirty();
|
set_dirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3562,31 +3550,13 @@ Session::remove_processor (Processor* processor)
|
||||||
Send* send;
|
Send* send;
|
||||||
Return* retrn;
|
Return* retrn;
|
||||||
PortInsert* port_insert;
|
PortInsert* port_insert;
|
||||||
PluginInsert* plugin_insert;
|
|
||||||
|
|
||||||
if ((port_insert = dynamic_cast<PortInsert *> (processor)) != 0) {
|
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;
|
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);
|
|
||||||
} else if ((send = dynamic_cast<Send *> (processor)) != 0) {
|
} 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;
|
send_bitset[send->bit_slot()] = false;
|
||||||
_sends.erase (x);
|
|
||||||
}
|
|
||||||
} else if ((retrn = dynamic_cast<Return *> (processor)) != 0) {
|
} 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;
|
return_bitset[send->bit_slot()] = false;
|
||||||
_returns.erase (x);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
fatal << _("programming error: unknown type of Insert deleted!") << endmsg;
|
|
||||||
/*NOTREACHED*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
set_dirty();
|
set_dirty();
|
||||||
|
|
|
||||||
|
|
@ -153,7 +153,6 @@ Session::first_stage_init (string fullpath, string snapshot_name)
|
||||||
|
|
||||||
_non_soloed_outs_muted = false;
|
_non_soloed_outs_muted = false;
|
||||||
g_atomic_int_set (&processing_prohibited, 0);
|
g_atomic_int_set (&processing_prohibited, 0);
|
||||||
insert_cnt = 0;
|
|
||||||
_transport_speed = 0;
|
_transport_speed = 0;
|
||||||
_last_transport_speed = 0;
|
_last_transport_speed = 0;
|
||||||
_target_transport_speed = 0;
|
_target_transport_speed = 0;
|
||||||
|
|
|
||||||
|
|
@ -136,6 +136,8 @@ def build(bld):
|
||||||
gdither.cc
|
gdither.cc
|
||||||
globals.cc
|
globals.cc
|
||||||
import.cc
|
import.cc
|
||||||
|
internal_return.cc
|
||||||
|
internal_send.cc
|
||||||
interpolation.cc
|
interpolation.cc
|
||||||
io.cc
|
io.cc
|
||||||
io_processor.cc
|
io_processor.cc
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue