2 Copyright (C) 2009 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 #include "pbd/error.h"
21 #include "pbd/failed_constructor.h"
23 #include "ardour/amp.h"
24 #include "ardour/internal_send.h"
25 #include "ardour/meter.h"
26 #include "ardour/route.h"
27 #include "ardour/session.h"
32 using namespace ARDOUR
;
35 InternalSend::InternalSend (Session
& s
, boost::shared_ptr
<Pannable
> p
, boost::shared_ptr
<MuteMaster
> mm
, boost::shared_ptr
<Route
> sendto
, Delivery::Role role
)
36 : Send (s
, p
, mm
, role
)
39 if (use_target (sendto
)) {
40 throw failed_constructor();
44 _amp
->set_gain (0, this);
47 InternalSend::~InternalSend ()
50 _send_to
->remove_send_from_internal_return (this);
55 InternalSend::use_target (boost::shared_ptr
<Route
> sendto
)
58 _send_to
->remove_send_from_internal_return (this);
63 _send_to
->add_send_to_internal_return (this);
65 set_name (sendto
->name());
66 _send_to_id
= _send_to
->id();
68 target_connections
.drop_connections ();
70 _send_to
->DropReferences
.connect_same_thread (target_connections
, boost::bind (&InternalSend::send_to_going_away
, this));
71 _send_to
->PropertyChanged
.connect_same_thread (target_connections
, boost::bind (&InternalSend::send_to_property_changed
, this, _1
));;
78 InternalSend::send_to_going_away ()
80 target_connections
.drop_connections ();
86 InternalSend::run (BufferSet
& bufs
, framepos_t start_frame
, framepos_t end_frame
, pframes_t nframes
, bool)
88 if ((!_active
&& !_pending_active
) || !_send_to
) {
93 // we have to copy the input, because we may alter the buffers with the amp
94 // in-place, which a send must never do.
96 assert(mixbufs
.available() >= bufs
.count());
97 mixbufs
.read_from (bufs
, nframes
);
101 gain_t tgain
= target_gain ();
103 if (tgain
!= _current_gain
) {
105 /* target gain has changed */
107 Amp::apply_gain (mixbufs
, nframes
, _current_gain
, tgain
);
108 _current_gain
= tgain
;
110 } else if (tgain
== 0.0) {
112 /* we were quiet last time, and we're still supposed to be quiet.
116 Amp::apply_simple_gain (mixbufs
, nframes
, 0.0);
119 } else if (tgain
!= 1.0) {
121 /* target gain has not changed, but is not zero or unity */
122 Amp::apply_simple_gain (mixbufs
, nframes
, tgain
);
125 // Can't automate gain for sends or returns yet because we need different buffers
126 // so that we don't overwrite the main automation data for the route amp
127 // _amp->setup_gain_automation (start_frame, end_frame, nframes);
129 _amp
->run (mixbufs
, start_frame
, end_frame
, nframes
, true);
131 /* XXX NEED TO PAN */
133 /* consider metering */
136 if (_amp
->gain_control()->get_value() == 0) {
139 _meter
->run (mixbufs
, start_frame
, end_frame
, nframes
, true);
143 /* target will pick up our output when it is ready */
146 _active
= _pending_active
;
150 InternalSend::set_block_size (pframes_t nframes
)
152 mixbufs
.ensure_buffers (_configured_input
, nframes
);
157 InternalSend::feeds (boost::shared_ptr
<Route
> other
) const
159 return _send_to
== other
;
163 InternalSend::state (bool full
)
165 XMLNode
& node (Send::state (full
));
167 /* this replaces any existing "type" property */
169 node
.add_property ("type", "intsend");
172 node
.add_property ("target", _send_to
->id().to_s());
179 InternalSend::get_state()
185 InternalSend::set_our_state (const XMLNode
& node
, int /*version*/)
187 const XMLProperty
* prop
;
189 if ((prop
= node
.property ("target")) != 0) {
191 _send_to_id
= prop
->value();
193 /* if we're loading a session, the target route may not have been
194 create yet. make sure we defer till we are sure that it should
198 if (!IO::connecting_legal
) {
199 IO::ConnectingLegal
.connect_same_thread (connect_c
, boost::bind (&InternalSend::connect_when_legal
, this));
201 connect_when_legal ();
209 InternalSend::set_state (const XMLNode
& node
, int version
)
211 Send::set_state (node
, version
);
212 return set_our_state (node
, version
);
216 InternalSend::connect_when_legal ()
218 connect_c
.disconnect ();
220 if (_send_to_id
== "0") {
221 /* it vanished before we could connect */
225 boost::shared_ptr
<Route
> sendto
;
227 if ((sendto
= _session
.route_by_id (_send_to_id
)) == 0) {
228 error
<< X_("cannot find route to connect to") << endmsg
;
232 return use_target (sendto
);
236 InternalSend::can_support_io_configuration (const ChanCount
& in
, ChanCount
& out
) const
243 InternalSend::configure_io (ChanCount in
, ChanCount out
)
245 bool ret
= Send::configure_io (in
, out
);
246 set_block_size (_session
.engine().frames_per_cycle());
251 InternalSend::set_name (const string
& str
)
253 /* rules for external sends don't apply to us */
254 return IOProcessor::set_name (str
);
258 InternalSend::display_name () const
261 return string_compose (X_("aux-%1"), _name
);
268 InternalSend::visible () const
278 InternalSend::send_to_property_changed (const PropertyChange
& what_changed
)
280 if (what_changed
.contains (Properties::name
)) {
281 set_name (_send_to
->name ());