how about that ... a monitor/main section .. GUI is still unfinished .. several small...
[ardour.git] / libs / ardour / monitor_processor.cc
1 #include "pbd/xml++.h"
2
3 #include "ardour/amp.h"
4 #include "ardour/dB.h"
5 #include "ardour/monitor_processor.h"
6 #include "ardour/session.h"
7
8 #include "i18n.h"
9
10 using namespace ARDOUR;
11 using namespace std;
12
13 MonitorProcessor::MonitorProcessor (Session& s)
14         : Processor (s, X_("MonitorOut"))
15 {
16         solo_cnt = 0;
17         _cut_all = false;
18         _dim_all = false;
19         _dim_level = 0.2;
20         _solo_boost_level = 1.0;
21 }
22
23 MonitorProcessor::MonitorProcessor (Session& s, const XMLNode& node)
24         : Processor (s, node)
25 {
26         set_state (node, Stateful::loading_state_version);
27 }
28
29 int
30 MonitorProcessor::set_state (const XMLNode& node, int version)
31 {
32         return Processor::set_state (node, version);
33 }
34
35 XMLNode&
36 MonitorProcessor::state (bool full)
37 {
38         XMLNode& node (Processor::state (full));
39
40         /* this replaces any existing "type" property */
41
42         node.add_property (X_("type"), X_("monitor"));
43
44         return node;
45 }
46
47 void
48 MonitorProcessor::run (BufferSet& bufs, sframes_t /*start_frame*/, sframes_t /*end_frame*/, nframes_t nframes, bool /*result_required*/)
49 {
50         uint32_t chn = 0;
51         gain_t target_gain;
52         gain_t dim_level_this_time = _dim_level;
53         gain_t global_cut = (_cut_all ? 0.0f : 1.0f);
54         gain_t global_dim = (_dim_all ? dim_level_this_time : 1.0f);
55         gain_t solo_boost;
56
57         if (_session.listening() || _session.soloing()) {
58                 solo_boost = _solo_boost_level;
59         } else {
60                 solo_boost = 1.0;
61         }
62
63         for (BufferSet::audio_iterator b = bufs.audio_begin(); b != bufs.audio_end(); ++b) {
64
65                 /* don't double-scale by both track dim and global dim coefficients */
66
67                 gain_t dim_level = (global_dim == 1.0 ? (_dim[chn] ? dim_level_this_time : 1.0) : 1.0);
68
69                 if (_soloed[chn]) {
70                         target_gain = _polarity[chn] * _cut[chn] * dim_level * global_cut * global_dim * solo_boost;
71                 } else {
72                         if (solo_cnt == 0) {
73                                 target_gain = _polarity[chn] * _cut[chn] * dim_level * global_cut * global_dim * solo_boost;
74                         } else {
75                                 target_gain = 0.0;
76                         }
77                 }
78
79                 if (target_gain != current_gain[chn] || target_gain != 1.0f) {
80
81                         Amp::apply_gain (*b, nframes, current_gain[chn], target_gain);
82                         current_gain[chn] = target_gain;
83                 }
84
85                 ++chn;
86         }
87 }
88
89 bool
90 MonitorProcessor::configure_io (ChanCount in, ChanCount out)
91 {
92         uint32_t needed = in.n_audio();
93
94         while (current_gain.size() > needed) {
95                 current_gain.pop_back ();
96                 _dim.pop_back ();
97                 _cut.pop_back ();
98                 _polarity.pop_back ();
99
100                 if (_soloed.back()) {
101                         if (solo_cnt > 0) {
102                                 --solo_cnt;
103                         }
104                 }
105
106                 _soloed.pop_back ();
107         }
108         
109         while (current_gain.size() < needed) {
110                 current_gain.push_back (1.0);
111                 _dim.push_back (false);
112                 _cut.push_back (1.0);
113                 _polarity.push_back (1.0);
114                 _soloed.push_back (false);
115         }
116
117         return Processor::configure_io (in, out);
118 }
119
120 bool 
121 MonitorProcessor::can_support_io_configuration (const ChanCount& in, ChanCount& out) const
122 {
123         return in == out;
124 }
125
126 void
127 MonitorProcessor::set_polarity (uint32_t chn, bool invert)
128 {
129         if (invert) {
130                 _polarity[chn] = -1.0f;
131         } else {
132                 _polarity[chn] = 1.0f;
133         }
134 }       
135
136 void
137 MonitorProcessor::set_dim (uint32_t chn, bool yn)
138 {
139         _dim[chn] = yn;
140 }
141
142 void
143 MonitorProcessor::set_cut (uint32_t chn, bool yn)
144 {
145         if (yn) {
146                 _cut[chn] = 0.0f;
147         } else {
148                 _cut[chn] = 1.0f;
149         }
150 }
151
152 void
153 MonitorProcessor::set_solo (uint32_t chn, bool solo)
154 {
155         _soloed[chn] = solo;
156
157         if (solo) {
158                 solo_cnt++;
159         } else {
160                 if (solo_cnt > 0) {
161                         solo_cnt--;
162                 }
163         }
164 }
165
166 void
167 MonitorProcessor::set_cut_all (bool yn)
168 {
169         _cut_all = yn;
170 }
171
172 void
173 MonitorProcessor::set_dim_all (bool yn)
174 {
175         _dim_all = yn;
176 }
177
178 bool
179 MonitorProcessor::display_to_user () const
180 {
181         return false;
182 }
183
184 void
185 MonitorProcessor::set_dim_level (gain_t val)
186 {
187         _dim_level = val;
188 }
189
190 void
191 MonitorProcessor::set_solo_boost_level (gain_t val)
192 {
193         _solo_boost_level = val;
194 }
195
196 bool 
197 MonitorProcessor::soloed (uint32_t chn) const
198 {
199         return _soloed[chn];
200 }
201
202
203 bool 
204 MonitorProcessor::inverted (uint32_t chn) const
205 {
206         return _polarity[chn] < 0.0f;
207 }
208
209
210 bool 
211 MonitorProcessor::cut (uint32_t chn) const
212 {
213         return _cut[chn] == 0.0f;
214 }
215
216 bool 
217 MonitorProcessor::dimmed (uint32_t chn) const
218 {
219         return _dim[chn];
220 }
221