1 /***************************************************************************
2  *   Copyright (C) 2009 by Pere Ràfols Soler                               *
3  *   sapista2@gmail.com                                                    *
4  *                                                                         *
5  *   This program is free software; you can redistribute it and/or modify  *
6  *   it under the terms of the GNU General Public License as published by  *
7  *   the Free Software Foundation; either version 2 of the License, or     *
8  *   (at your option) any later version.                                   *
9  *                                                                         *
10  *   This program is distributed in the hope that it will be useful,       *
11  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
12  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
13  *   GNU General Public License for more details.                          *
14  *                                                                         *
15  *   You should have received a copy of the GNU General Public License     *
16  *   along with this program; if not, write to the                         *
17  *   Free Software Foundation, Inc.,                                       *
18  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
19  ***************************************************************************/
20 
21 #include <stdlib.h>
22 #include <iostream>
23 
24 #include <cstring>
25 #include "dynamicswindow.h"
26 #include "guiconstants.h"
27 #include "setwidgetcolors.h"
28 
29 #define KNOB_ICON_FILE "/knobs/knob2_32px.png"
30 #define KNOB_SIZE_X 75
31 #define KNOB_SIZE_Y 72
32 #define WIDGET_BORDER 3
33 #define LOGO_PATH "icons/logodynamics.png"
34 
35 
DynMainWindow(const char * uri,std::string bundlePath,std::string title,bool isCompressor,bool hasSideChain)36 DynMainWindow::DynMainWindow(const char *uri, std::string bundlePath, std::string title, bool isCompressor, bool hasSideChain)
37   :m_pluginUri(uri),
38   m_bundlePath(bundlePath),
39   m_bIsCompressor(isCompressor)
40 {
41   m_InGainFader = Gtk::manage(new KnobWidget2(-20.0, 20.0, "In Gain", "dB", (m_bundlePath + KNOB_ICON_FILE).c_str(), KNOB_TYPE_LIN, true ));
42   m_InputVu = Gtk::manage(new VUWidget(1, -48.0, 6.0, "In", false, true));
43   m_GainReductionVu = Gtk::manage(new VUWidget(1, 0.0, 20.0, "GR", true));
44   m_Attack = Gtk::manage(new KnobWidget2(0.01, 500.0, "Attack", "ms", (m_bundlePath + KNOB_ICON_FILE).c_str() , KNOB_TYPE_TIME ));
45   m_Release = Gtk::manage(new KnobWidget2(5.0, 4000.0, "Release", "ms", (m_bundlePath + KNOB_ICON_FILE).c_str() , KNOB_TYPE_TIME ));
46   m_Punch = Gtk::manage(new KnobWidget2(0.0, 100.0, "Punch", "%", (m_bundlePath + KNOB_ICON_FILE).c_str(), KNOB_TYPE_LIN ));
47   m_HPF = Gtk::manage(new KnobWidget2(20.0, 20000.0, "Key HPF", "Hz",  (m_bundlePath + KNOB_ICON_FILE).c_str() , KNOB_TYPE_FREQ));
48   m_LPF = Gtk::manage(new KnobWidget2(20.0, 20000.0, "Key LPF", "Hz",  (m_bundlePath + KNOB_ICON_FILE).c_str() , KNOB_TYPE_FREQ));
49   m_DryWet = Gtk::manage(new KnobWidget2(0.0, 100.0, "Dry/Wet", "%", (m_bundlePath + KNOB_ICON_FILE).c_str(), KNOB_TYPE_LIN ));
50   m_Ratio = Gtk::manage(new KnobWidget2(1.0, 100.0, "Ratio", "dB", (m_bundlePath + KNOB_ICON_FILE).c_str(), KNOB_TYPE_TIME ));
51   m_Knee = Gtk::manage(new KnobWidget2(0.0, 20.0, "Knee", "dB", (m_bundlePath + KNOB_ICON_FILE).c_str() ));
52 
53   if(m_bIsCompressor)
54   {
55     //Is Compressor
56     m_Hold_Makeup = Gtk::manage(new KnobWidget2(0.0, 20.0, "Makeup", "dB", (m_bundlePath + KNOB_ICON_FILE).c_str() ));
57   }
58   else
59   {
60     //Is Gate
61     m_Hold_Makeup = Gtk::manage(new KnobWidget2(0.01, 3000.0, "Hold", "ms", (m_bundlePath + KNOB_ICON_FILE).c_str() , KNOB_TYPE_TIME ));
62     m_Range = Gtk::manage(new KnobWidget2(-90.0, -1.0, "Range", "dB", (m_bundlePath + KNOB_ICON_FILE).c_str() ));
63   }
64 
65   m_Plot = Gtk::manage(new PlotDynCurve(m_bIsCompressor));
66 
67   m_KeyButton.set_label("Key Listen");
68   m_KeyButton.set_size_request(-1,20);
69   m_KeyButtonAlign.add(m_KeyButton);
70   m_KeyButtonAlign.set_padding(0,0, 10, 10);
71 
72   if(hasSideChain)
73   {
74     m_FeedBackMode_SideChainActive.set_label("SC Active");
75   }
76   else
77   {
78     m_FeedBackMode_SideChainActive.set_label("Feedback");
79   }
80   m_FeedBackMode_SideChainActive.set_size_request(-1,20);
81   m_FeedBackModeAlign.add(m_FeedBackMode_SideChainActive);
82   m_FeedBackModeAlign.set_padding(0,0, 10, 10);
83 
84 
85   m_OptoMode.set_label("S-Release");
86   m_OptoMode.set_size_request(-1,20);
87   m_OptoModeAlign.add(m_OptoMode);
88   m_OptoModeAlign.set_padding(0,0, 10, 10);
89 
90 
91   m_LTitle.set_use_markup(true);
92   m_LTitle.set_markup( "<span font_weight=\"bold\" font=\"12px\" font_family=\"Monospace\">"  + title + "</span>");
93   m_LTitle.set_size_request(-1, 25);
94   m_TitleAlign.add(m_LTitle);
95   m_TitleAlign.set_padding(0,0, 60, 0);
96 
97   //load image logo
98   image_logo = new Gtk::Image(m_bundlePath + "/" + LOGO_PATH);
99 
100   m_VuBox.pack_start(*m_InputVu, Gtk::PACK_SHRINK);
101   m_VuBox.pack_start(*m_GainReductionVu, Gtk::PACK_SHRINK);
102   m_VuBox.set_border_width(4);
103   m_VuBox.show_all_children();
104 
105   m_SideChain2Box.set_border_width(WIDGET_BORDER);
106   m_SideChain2Box.set_spacing(WIDGET_BORDER);
107   m_SideChain2Box.pack_start(*m_LPF, Gtk::PACK_EXPAND_WIDGET);
108   m_SideChain2Box.pack_start(*m_HPF, Gtk::PACK_EXPAND_WIDGET);
109 
110   m_SideChainBox.set_border_width(WIDGET_BORDER);
111   m_SideChainBox.set_spacing(WIDGET_BORDER);
112   m_SideChainBox.pack_start(m_KeyButtonAlign,Gtk::PACK_SHRINK);
113   if(m_bIsCompressor)
114   {
115     m_SideChainBox.pack_start(m_FeedBackModeAlign,Gtk::PACK_SHRINK);
116     m_SideChainBox.pack_start(m_OptoModeAlign,Gtk::PACK_SHRINK);
117   }
118   m_SideChainBox.pack_start(m_SideChain2Box,Gtk::PACK_SHRINK);
119   m_SideChainBox.show_all_children();
120   m_keyPadding.add(m_SideChainBox);
121   m_keyPadding.set_padding(30,0, 0, 0);
122 
123   m_SCBox.add(m_keyPadding);
124   m_sidchianAlign.set_padding(0, 3, 0, 0);
125   m_sidchianAlign.add(m_SCBox);
126 
127   m_DynBox.set_border_width(WIDGET_BORDER);
128   m_DynBox.set_spacing(WIDGET_BORDER);
129   m_DynBox.pack_start(*m_InGainFader, Gtk::PACK_SHRINK);
130   m_DynBox.pack_start(*m_Ratio, Gtk::PACK_SHRINK);
131   m_DynBox.pack_start(*m_Knee, Gtk::PACK_SHRINK);
132 
133   m_DynBox.pack_start(*m_DryWet, Gtk::PACK_SHRINK);
134   m_DynBox.show_all_children();
135 
136   m_BalBox.set_border_width(WIDGET_BORDER);
137   m_BalBox.set_spacing(WIDGET_BORDER);
138   m_BalBox.pack_start(*m_Attack, Gtk::PACK_SHRINK);
139   m_BalBox.pack_start(*m_Release, Gtk::PACK_SHRINK);
140   if(m_bIsCompressor)
141   {
142     m_BalBox.pack_start(*m_Punch, Gtk::PACK_SHRINK);
143   }
144   m_BalBox.pack_start(*m_Hold_Makeup, Gtk::PACK_SHRINK);
145   if(!m_bIsCompressor)
146   {
147     m_BalBox.pack_start(*m_Range, Gtk::PACK_SHRINK);
148   }
149   m_BalBox.show_all_children();
150 
151   m_PlotBox.pack_start(m_DynBox, Gtk::PACK_SHRINK);
152   m_PlotBox.pack_start(*m_Plot, Gtk::PACK_SHRINK);
153   m_PlotBox.show_all_children();
154 
155   m_PlotLabelBox.pack_start(m_TitleAlign, Gtk::PACK_SHRINK);
156   m_PlotLabelBox.pack_start(m_PlotBox, Gtk::PACK_SHRINK);
157   m_PlotLabelBox.show_all_children();
158 
159   m_TitleBox.pack_start(m_BalBox, Gtk::PACK_SHRINK);
160   m_TitleBox.pack_start(*image_logo, Gtk::PACK_SHRINK);
161   m_TitleBox.show_all_children();
162 
163   m_BotBox.pack_start(m_TitleBox, Gtk::PACK_SHRINK);
164   m_BotBox.pack_start(m_sidchianAlign, Gtk::PACK_EXPAND_PADDING);
165 
166   m_Main2Box.pack_start(m_PlotLabelBox, Gtk::PACK_SHRINK);
167   m_Main2Box.pack_start(m_BotBox, Gtk::PACK_SHRINK);
168 
169   m_MainBox.pack_start(m_Main2Box, Gtk::PACK_SHRINK);
170   m_MainBox.pack_start(m_VuBox, Gtk::PACK_SHRINK);
171 
172   show_all();
173   add(m_MainBox);
174 
175   //Set cutom theme color:
176   Gdk::Color m_WinBgColor;
177   SetWidgetColors m_WidgetColors;
178   m_WidgetColors.setGenericWidgetColors(&m_LTitle);
179 
180   //Connect signals
181   m_InGainFader->signal_changed().connect(sigc::mem_fun(*this, &DynMainWindow::onGainChange));
182   m_InputVu->signal_changed().connect(sigc::mem_fun(*this, &DynMainWindow::onThresholdChange));
183   m_Ratio->signal_changed().connect(sigc::mem_fun(*this, &DynMainWindow::onRatioChange));
184   m_Attack->signal_changed().connect(sigc::mem_fun(*this, &DynMainWindow::onAttackChange));
185   m_Hold_Makeup->signal_changed().connect(sigc::mem_fun(*this, &DynMainWindow::onHoldChange));
186   m_Release->signal_changed().connect(sigc::mem_fun(*this, &DynMainWindow::onReleaseChange));
187   m_LPF->signal_changed().connect(sigc::mem_fun(*this, &DynMainWindow::onLPFChange));
188   m_HPF->signal_changed().connect(sigc::mem_fun(*this, &DynMainWindow::onHPFChange));
189   m_DryWet->signal_changed().connect(sigc::mem_fun(*this, &DynMainWindow::onDryWetChange));
190   m_KeyButton.signal_clicked().connect(sigc::mem_fun(*this, &DynMainWindow::onKeyListenChange));
191   m_Knee->signal_changed().connect(sigc::mem_fun(*this, &DynMainWindow::onKneeChange));
192 
193   if(m_bIsCompressor)
194   {
195     m_FeedBackMode_SideChainActive.signal_clicked().connect(sigc::mem_fun(*this, &DynMainWindow::onFeedbackModeChange));
196     m_OptoMode.signal_clicked().connect(sigc::mem_fun(*this, &DynMainWindow::onModeCompressorChange));
197     m_Punch->signal_changed().connect(sigc::mem_fun(*this, &DynMainWindow::onPunchChange));
198   }
199   else
200   {
201     m_Range->signal_changed().connect(sigc::mem_fun(*this, &DynMainWindow::onRangeChange));
202   }
203 }
204 
~DynMainWindow()205 DynMainWindow::~DynMainWindow()
206 {
207   delete m_InputVu;
208   delete m_GainReductionVu;
209   delete m_InGainFader;
210   delete m_Attack;
211   delete m_Hold_Makeup;
212   delete m_Release;
213   delete m_Ratio;
214   delete m_Knee;
215   delete m_Punch;
216   if(!m_bIsCompressor)
217   {
218     delete m_Range;
219   }
220   delete m_HPF;
221   delete m_LPF;
222   delete m_DryWet;
223   delete image_logo;
224 }
225 
onGainChange()226 void DynMainWindow::onGainChange()
227 {
228   //Write to LV2 port
229   float aux;
230   aux = m_InGainFader->get_value();
231   write_function(controller, PORT_GAIN, sizeof(float), 0, &aux);
232 }
233 
onThresholdChange()234 void DynMainWindow::onThresholdChange()
235 {
236   //Write to LV2 port
237   float aux;
238   aux = m_InputVu->get_value_th();
239   m_Plot->set_threshold(aux);
240   write_function(controller, PORT_THRESHOLD, sizeof(float), 0, &aux);
241 }
242 
onRangeChange()243 void DynMainWindow::onRangeChange()
244 {
245   //Write to LV2 port
246   float aux;
247   aux = m_Range->get_value();
248 
249   m_Plot->set_range(aux);
250   write_function(controller, PORT_FEEDBACK_RANGE_SCACTIVE, sizeof(float), 0, &aux);
251 }
252 
onRatioChange()253 void DynMainWindow::onRatioChange()
254 {
255   //Write to LV2 port
256   float aux;
257   aux = m_Ratio->get_value();
258   m_Plot->set_ratio(aux);
259 
260   write_function(controller, PORT_RATIO, sizeof(float), 0, &aux);
261 }
262 
onAttackChange()263 void DynMainWindow::onAttackChange()
264 {
265   //Write to LV2 port
266   float aux;
267   aux = m_Attack->get_value();
268   write_function(controller, PORT_ATACK, sizeof(float), 0, &aux);
269 }
270 
onHoldChange()271 void DynMainWindow::onHoldChange()
272 {
273   //Write to LV2 port
274   float aux;
275   aux = m_Hold_Makeup->get_value();
276   if(m_bIsCompressor)
277   {
278     m_Plot->set_makeup(aux);
279   }
280   write_function(controller, PORT_HOLD_MAKEUP, sizeof(float), 0, &aux);
281 }
282 
onReleaseChange()283 void DynMainWindow::onReleaseChange()
284 {
285   //Write to LV2 port
286   float aux;
287   aux = m_Release->get_value();
288   write_function(controller, PORT_DECAY, sizeof(float), 0, &aux);
289 }
290 
onPunchChange()291 void DynMainWindow::onPunchChange()
292 {
293   //Write to LV2 port
294   float aux;
295   aux = 0.01*m_Punch->get_value(); //Div by 100 to get 0% to 100% in range 0 to 1
296   write_function(controller, PORT_PUNCH, sizeof(float), 0, &aux);
297 }
298 
onKneeChange()299 void DynMainWindow::onKneeChange()
300 {
301   //Write to LV2 port
302   float aux;
303   aux = m_Knee->get_value();
304   m_Plot->set_knee(aux);
305   write_function(controller, PORT_KNEE, sizeof(float), 0, &aux);
306 }
307 
onHPFChange()308 void DynMainWindow::onHPFChange()
309 {
310   //Write to LV2 port
311   float aux;
312   aux = m_HPF->get_value();
313   write_function(controller, PORT_HPFFREQ, sizeof(float), 0, &aux);
314 }
315 
onLPFChange()316 void DynMainWindow::onLPFChange()
317 {
318   //Write to LV2 port
319   float aux;
320   aux = m_LPF->get_value();
321   write_function(controller, PORT_LPFFREQ, sizeof(float), 0, &aux);
322 }
323 
onDryWetChange()324 void DynMainWindow::onDryWetChange()
325 {
326   //Write to LV2 port
327   float aux;
328   aux = 0.01*m_DryWet->get_value(); //Div by 100 to get 0% to 100% in range 0 to 1
329   write_function(controller, PORT_DRY_WET, sizeof(float), 0, &aux);
330 }
331 
onKeyListenChange()332 void DynMainWindow::onKeyListenChange()
333 {
334   //Write to LV2 port
335   float aux;
336   aux = m_KeyButton.get_active() ? 1.0 : 0.0;
337   write_function(controller, PORT_KEY_LISTEN, sizeof(float), 0, &aux);
338 }
339 
onFeedbackModeChange()340 void DynMainWindow::onFeedbackModeChange()
341 {
342   //Write to LV2 port
343   float aux;
344   aux = m_FeedBackMode_SideChainActive.get_active() ? 1.0 : 0.0;
345   write_function(controller, PORT_FEEDBACK_RANGE_SCACTIVE, sizeof(float), 0, &aux);
346 }
347 
onModeCompressorChange()348 void DynMainWindow::onModeCompressorChange()
349 {
350   //Write to LV2 port
351   float aux;
352   aux = m_OptoMode.get_active() ? 1.0 : 0.0;
353   write_function(controller, PORT_COMP_MODE, sizeof(float), 0, &aux);
354 }
355 
356