eccd5f29f902a9702e6f78388c97903fc41fa45e
[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/delivery.h"
28 #include "ardour/port_insert.h"
29 #include "ardour/plugin.h"
30 #include "ardour/port.h"
31 #include "ardour/route.h"
32 #include "ardour/buffer_set.h"
33
34 #include "ardour/audioengine.h"
35 #include "ardour/session.h"
36 #include "ardour/types.h"
37
38 #include "i18n.h"
39
40 using namespace std;
41 using namespace ARDOUR;
42 using namespace PBD;
43
44 PortInsert::PortInsert (Session& s, boost::shared_ptr<MuteMaster> mm)
45         : IOProcessor (s, true, true, string_compose (_("insert %1"), (bitslot = s.next_insert_id()) + 1), "")
46         , _out (new Delivery (s, _output, mm, _name, Delivery::Insert))
47 {
48         ProcessorCreated (this); /* EMIT SIGNAL */
49 }
50
51 PortInsert::PortInsert (Session& s, boost::shared_ptr<MuteMaster> mm, const XMLNode& node)
52         : IOProcessor (s, true, true, "unnamed port insert")
53         , _out (new Delivery (s, _output, mm, _name, Delivery::Insert))
54
55 {
56         if (set_state (node, Stateful::loading_state_version)) {
57                 throw failed_constructor();
58         }
59
60         ProcessorCreated (this); /* EMIT SIGNAL */
61 }
62
63 PortInsert::~PortInsert ()
64 {
65         GoingAway ();
66 }
67
68 void
69 PortInsert::run (BufferSet& bufs, sframes_t start_frame, sframes_t end_frame, nframes_t nframes, bool)
70 {
71         if (_output->n_ports().n_total() == 0) {
72                 return;
73         }
74
75         if (!_active && !_pending_active) {
76                 /* deliver silence */
77                 silence (nframes);
78                 goto out;
79         }
80
81         _out->run (bufs, start_frame, end_frame, nframes, true);
82         _input->collect_input (bufs, nframes, ChanCount::ZERO);
83
84   out:
85         _active = _pending_active;
86 }
87
88 XMLNode&
89 PortInsert::get_state(void)
90 {
91         return state (true);
92 }
93
94 XMLNode&
95 PortInsert::state (bool full)
96 {
97         XMLNode& node = Processor::state(full);
98         char buf[32];
99         node.add_property ("type", "port");
100         snprintf (buf, sizeof (buf), "%" PRIu32, bitslot);
101         node.add_property ("bitslot", buf);
102
103         return node;
104 }
105
106 int
107 PortInsert::set_state (const XMLNode& node, int version)
108 {
109         XMLNodeList nlist = node.children();
110         XMLNodeIterator niter;
111         XMLPropertyList plist;
112         const XMLProperty *prop;
113
114         if ((prop = node.property ("type")) == 0) {
115                 error << _("XML node describing port insert is missing the `type' field") << endmsg;
116                 return -1;
117         }
118
119         if (prop->value() != "port") {
120                 error << _("non-port insert XML used for port plugin insert") << endmsg;
121                 return -1;
122         }
123
124         if ((prop = node.property ("bitslot")) == 0) {
125                 bitslot = _session.next_insert_id();
126         } else {
127                 sscanf (prop->value().c_str(), "%" PRIu32, &bitslot);
128                 _session.mark_insert_id (bitslot);
129         }
130
131         const XMLNode* insert_node = &node;
132
133         // legacy sessions: search for child IOProcessor node
134         for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
135                 if ((*niter)->name() == "IOProcessor") {
136                         insert_node = *niter;
137                         break;
138                 }
139         }
140
141         Processor::set_state (*insert_node, version);
142
143         return 0;
144 }
145
146 ARDOUR::nframes_t
147 PortInsert::signal_latency() const
148 {
149         /* because we deliver and collect within the same cycle,
150            all I/O is necessarily delayed by at least frames_per_cycle().
151
152            if the return port for insert has its own latency, we
153            need to take that into account too.
154         */
155
156         return _session.engine().frames_per_cycle() + _input->signal_latency();
157 }
158
159 bool
160 PortInsert::configure_io (ChanCount in, ChanCount out)
161 {
162         /* for an insert, processor input corresponds to IO output, and vice versa */
163
164         if (_input->ensure_io (in, false, this) != 0) {
165                 return false;
166         }
167
168         if (_output->ensure_io (out, false, this) != 0) {
169                 return false;
170         }
171
172         return Processor::configure_io (in, out);
173 }
174
175 bool
176 PortInsert::can_support_io_configuration (const ChanCount& in, ChanCount& out) const
177 {
178         out = in;
179         return true;
180 }
181
182 bool
183 PortInsert::set_name (const std::string& name)
184 {
185         bool ret = Processor::set_name (name);
186
187         ret = (ret && _input->set_name (name) && _output->set_name (name));
188
189         return ret;
190 }
191
192 void
193 PortInsert::activate ()
194 {
195         IOProcessor::activate ();
196
197         _out->activate ();
198 }
199
200 void
201 PortInsert::deactivate ()
202 {
203         IOProcessor::deactivate ();
204
205         _out->deactivate ();
206 }