Returns (i.e. sidechains).
[ardour.git] / libs / ardour / port_insert.cc
1 /*
2     Copyright (C) 2000,2007 Paul Davis 
3
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.
8
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.
13
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.
17
18 */
19
20 #include <string>
21
22 #include <sigc++/bind.h>
23
24 #include "pbd/failed_constructor.h"
25 #include "pbd/xml++.h"
26
27 #include "ardour/port_insert.h"
28 #include "ardour/plugin.h"
29 #include "ardour/port.h"
30 #include "ardour/route.h"
31 #include "ardour/buffer_set.h"
32
33 #include "ardour/audioengine.h"
34 #include "ardour/session.h"
35 #include "ardour/types.h"
36
37 #include "i18n.h"
38
39 using namespace std;
40 using namespace ARDOUR;
41 using namespace PBD;
42
43 PortInsert::PortInsert (Session& s)
44         : IOProcessor (s, string_compose (_("insert %1"), (bitslot = s.next_insert_id()) + 1), "")
45 {
46         init ();
47         ProcessorCreated (this); /* EMIT SIGNAL */
48 }
49
50 PortInsert::PortInsert (Session& s, const XMLNode& node)
51         : IOProcessor (s, "unnamed port insert")
52 {
53         if (set_state (node)) {
54                 throw failed_constructor();
55         }
56
57         ProcessorCreated (this); /* EMIT SIGNAL */
58 }
59
60 PortInsert::~PortInsert ()
61 {
62         GoingAway ();
63 }
64
65 void
66 PortInsert::init ()
67 {
68         if (_io->ensure_io(output_streams(), input_streams(), false, this)) { // sic
69                 error << _("PortInsert: cannot create ports") << endmsg;
70                 throw failed_constructor();
71         }
72 }
73
74 void
75 PortInsert::run_in_place (BufferSet& bufs, nframes_t start_frame, nframes_t end_frame, nframes_t nframes)
76 {
77         if (_io->n_outputs().n_total() == 0) {
78                 return;
79         }
80
81         if (!active()) {
82                 /* deliver silence */
83                 _io->silence (nframes);
84                 return;
85         }
86
87         _io->deliver_output (bufs, start_frame, end_frame, nframes);
88         _io->collect_input (bufs, nframes);
89 }
90
91 XMLNode&
92 PortInsert::get_state(void)
93 {
94         return state (true);
95 }
96
97 XMLNode&
98 PortInsert::state (bool full)
99 {
100         XMLNode& node = IOProcessor::state(full);
101         char buf[32];
102         node.add_property ("type", "port");
103         snprintf (buf, sizeof (buf), "%" PRIu32, bitslot);
104         node.add_property ("bitslot", buf);
105
106         return node;
107 }
108
109 int
110 PortInsert::set_state(const XMLNode& node)
111 {
112         XMLNodeList nlist = node.children();
113         XMLNodeIterator niter;
114         XMLPropertyList plist;
115         const XMLProperty *prop;
116
117         if ((prop = node.property ("type")) == 0) {
118                 error << _("XML node describing port insert is missing the `type' field") << endmsg;
119                 return -1;
120         }
121         
122         if (prop->value() != "port") {
123                 error << _("non-port insert XML used for port plugin insert") << endmsg;
124                 return -1;
125         }
126
127         if ((prop = node.property ("bitslot")) == 0) {
128                 bitslot = _session.next_insert_id();
129         } else {
130                 sscanf (prop->value().c_str(), "%" PRIu32, &bitslot);
131                 _session.mark_insert_id (bitslot);
132         }
133
134         const XMLNode* insert_node = &node;
135
136         // legacy sessions: search for child IOProcessor node
137         for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
138                 if ((*niter)->name() == "IOProcessor") {
139                         insert_node = *niter;
140                         break;
141                 }
142         }
143         
144         IOProcessor::set_state (*insert_node);
145
146         return 0;
147 }
148
149 ARDOUR::nframes_t 
150 PortInsert::signal_latency() const
151 {
152         /* because we deliver and collect within the same cycle,
153            all I/O is necessarily delayed by at least frames_per_cycle().
154
155            if the return port for insert has its own latency, we
156            need to take that into account too.
157         */
158
159         return _session.engine().frames_per_cycle() + _io->input_latency();
160 }
161
162 bool
163 PortInsert::configure_io (ChanCount in, ChanCount out)
164 {
165         /* for an insert, processor input corresponds to IO output, and vice versa */
166
167         if (_io->ensure_io (out, in, false, this) != 0) {
168                 return false;
169         }
170
171         return Processor::configure_io (in, out);
172 }
173
174 bool
175 PortInsert::can_support_io_configuration (const ChanCount& in, ChanCount& out) const
176 {
177         out = in;
178         return true;
179 }
180