3 * Copyright (C) 2008-2019 Adam Williams <broadcast at earthling dot net>
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.
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.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 #include "bcsignals.h"
25 #include "comprmultigui.h"
28 #include "edlsession.h"
37 ComprMultiWindow::ComprMultiWindow(ComprMultiEffect *plugin)
38 : PluginClientWindow(plugin, xS(650),yS(560), xS(650),yS(560), 0)
40 this->plugin = plugin;
41 char string[BCTEXTLEN];
42 // set the default directory
43 sprintf(string, "%s/compressormulti.rc", File::get_config_path());
44 defaults = new BC_Hash(string);
46 plugin->config.current_band = defaults->get("CURRENT_BAND", plugin->config.current_band);
51 ComprMultiWindow::~ComprMultiWindow()
53 defaults->update("CURRENT_BAND", plugin->config.current_band);
68 void ComprMultiWindow::create_objects()
70 int margin = client->get_theme()->widget_border;
71 int x = margin, y = margin;
72 int control_margin = xS(150);
73 int canvas_y2 = get_h() * 2 / 3;
75 add_subwindow(title = new BC_Title(x, y, "In:"));
76 int y2 = y + title->get_h() + margin;
77 EDL *edl = plugin->get_edl();
78 add_subwindow(in = new BC_Meter(x, y2, METER_VERT,
80 edl->session->min_meter_db,
81 edl->session->max_meter_db,
82 edl->session->meter_format,
85 x += in->get_w() + margin;
87 add_subwindow(title = new BC_Title(x, y, "Gain:"));
88 add_subwindow(gain_change = new BC_Meter(x, y2, METER_VERT,
96 1)); // is_gain_change
97 x += gain_change->get_w() + xS(35);
99 add_subwindow(title = new BC_Title(x, y, _("Current band:")));
101 int x1 = title->get_x() + title->get_w() + margin;
102 char string[BCTEXTLEN];
103 for( int i = 0; i < TOTAL_BANDS; i++ ) {
104 sprintf(string, "%d", i + 1);
105 add_subwindow(band[i] = new ComprMultiBand(this, plugin,
107 x1 += band[i]->get_w() + margin;
109 y += band[0]->get_h() + 1;
112 add_subwindow(title = new BC_Title(x, y,
113 _("Sound level (Press shift to snap to grid):")));
114 y += title->get_h() + 1;
115 add_subwindow(canvas = new ComprMultiCanvas(plugin, this,
116 x, y, get_w() - x - control_margin - xS(10), canvas_y2 - y));
117 y += canvas->get_h() + yS(30);
119 add_subwindow(title = new BC_Title(margin, y, _("Bandwidth:")));
121 eqcanvas = new EQCanvas(this, margin, y,
122 canvas->get_w() + x - margin, get_h() - y - margin,
123 plugin->config.min_db, 0.0);
124 eqcanvas->freq_divisions = 10;
125 eqcanvas->initialize();
127 x = get_w() - control_margin;
129 add_subwindow(title = new BC_Title(x, y, _("Attack secs:")));
131 reaction = new ComprMultiReaction(plugin, this, x, y);
132 reaction->create_objects();
133 y += reaction->get_h() + margin;
135 add_subwindow(title = new BC_Title(x, y, _("Release secs:")));
137 decay = new ComprMultiDecay(plugin, this, x, y);
138 decay->create_objects();
139 y += decay->get_h() + margin;
141 add_subwindow(solo = new ComprMultiSolo(plugin, x, y));
142 y += solo->get_h() + margin;
143 add_subwindow(bypass = new ComprMultiBypass(plugin, x, y));
144 y += bypass->get_h() + margin;
145 add_subwindow(title = new BC_Title(x, y, _("Output:")));
148 y_text = new ComprMultiY(plugin, this, x, y);
149 y_text->create_objects();
150 y += y_text->get_h() + margin;
152 add_subwindow(title = new BC_Title(x, y, _("Input:")));
154 x_text = new ComprMultiX(plugin, this, x, y);
155 x_text->create_objects();
156 y += x_text->get_h() + margin;
158 add_subwindow(clear = new ComprMultiClear(plugin, this, x, y));
159 y += clear->get_h() + margin;
161 add_subwindow(title = new BC_Title(x, y, _("Gain:")));
163 int x2 = get_w() - (margin + BC_Pot::calculate_w()) * 2;
164 int x3 = get_w() - (margin + BC_Pot::calculate_w());
165 add_subwindow(title = new BC_Title(x2, y, _("Freq range:")));
166 y += title->get_h() + margin;
168 add_subwindow(mkup_gain = new ComprMultiMkupGain(plugin, this, x, y,
169 &plugin->config.bands[plugin->config.current_band].mkup_gain,
171 // the previous high frequency
172 add_subwindow(freq1 = new ComprMultiQPot(this, plugin, x2, y,
173 plugin->config.current_band == 0 ? 0 :
174 &plugin->config.bands[plugin->config.current_band-1].freq));
175 // the current high frequency
176 add_subwindow(freq2 = new ComprMultiQPot(this, plugin, x3, y,
177 plugin->config.current_band!=TOTAL_BANDS-1 ? 0 :
178 &plugin->config.bands[plugin->config.current_band].freq));
179 y += freq1->get_h() + margin;
182 add_subwindow(bar = new BC_Bar(x, y, get_w() - x - margin));
183 y += bar->get_h() + margin;
185 add_subwindow(title = new BC_Title(x, y, _("Trigger Type:")));
187 add_subwindow(input = new ComprMultiInput(plugin, this, x, y));
188 input->create_objects();
189 y += input->get_h() + margin;
190 add_subwindow(title = new BC_Title(x, y, _("Channel:")));
193 trigger = new ComprMultiTrigger(plugin, this, x, y);
194 trigger->create_objects();
195 if( plugin->config.input != ComprMultiConfig::TRIGGER ) trigger->disable();
196 y += trigger->get_h() + margin;
198 add_subwindow(smooth = new ComprMultiSmooth(plugin, x, y));
199 y += smooth->get_h() + margin;
201 add_subwindow(title = new BC_Title(x, y, _("Steepness:")));
202 add_subwindow(q = new ComprMultiFPot(this, plugin,
203 get_w() - margin - BC_Pot::calculate_w(), y,
204 &plugin->config.q, 0, 1));
205 y += q->get_h() + margin;
207 add_subwindow(title = new BC_Title(x, y, _("Window size:")));
209 add_subwindow(size = new ComprMultiSize(this, plugin, x, y));
210 size->create_objects();
211 size->update(plugin->config.window_size);
212 y += size->get_h() + margin;
214 add_subwindow(reset = new ComprMultiReset(plugin, this, x, y));
216 canvas->create_objects();
221 // called when the user selects a different band
222 void ComprMultiWindow::update()
224 int curr_band = plugin->config.current_band;
225 for( int i = 0; i < TOTAL_BANDS; i++ )
226 band[i]->update(curr_band == i);
228 int *ptr1 = !curr_band ? 0 :
229 &plugin->config.bands[curr_band-1].freq;
230 freq1->output = ptr1;
232 freq1->update(*ptr1);
240 // top band edits the penultimate band
241 int *ptr2 = curr_band == TOTAL_BANDS-1 ? 0 :
242 &plugin->config.bands[curr_band].freq;
243 freq2->output = ptr2;
245 freq2->update(*ptr2);
253 q->update(plugin->config.q);
254 BandConfig *band_config = &plugin->config.bands[curr_band];
255 double *ptr3 = &band_config->mkup_gain;
256 mkup_gain->output = ptr3;
257 mkup_gain->update(*ptr3);
258 solo->update(band_config->solo);
259 bypass->update(band_config->bypass);
260 size->update(plugin->config.window_size);
262 if( atol(trigger->get_text()) != plugin->config.trigger ) {
263 trigger->update((int64_t)plugin->config.trigger);
266 if( strcmp(input->get_text(), ComprMultiInput::value_to_text(plugin->config.input)) ) {
267 input->set_text(ComprMultiInput::value_to_text(plugin->config.input));
270 if( plugin->config.input != ComprMultiConfig::TRIGGER && trigger->get_enabled() ) {
274 if( plugin->config.input == ComprMultiConfig::TRIGGER && !trigger->get_enabled() ) {
278 if( !EQUIV(atof(reaction->get_text()), band_config->attack_len) ) {
279 reaction->update((float)band_config->attack_len);
282 if( !EQUIV(atof(decay->get_text()), band_config->release_len) ) {
283 decay->update((float)band_config->release_len);
286 smooth->update(plugin->config.smoothing_only);
287 if( canvas->current_operation == ComprMultiCanvas::DRAG ) {
288 x_text->update((float)band_config->levels.values[canvas->current_point].x);
289 y_text->update((float)band_config->levels.values[canvas->current_point].y);
299 void ComprMultiWindow::update_eqcanvas()
301 plugin->calculate_envelope();
302 // filter GUI frames by band & data type
304 CompressorClientFrame *frame = 0;
305 // gdb plugin->dump_frames();
306 double tracking_position = plugin->get_tracking_position();
307 int dir = plugin->get_tracking_direction() == PLAY_REVERSE ? -1 : 1;
308 while( (frame = (CompressorClientFrame*)plugin->next_gui_frame()) ) {
309 if( dir*(frame->position - tracking_position) > 0 ) break;
310 if( frame->band == plugin->config.current_band ) {
311 // only frames for desired band
312 switch( frame->type ) {
313 case FREQ_COMPRESSORFRAME: {
315 freq_frame = (CompressorFreqFrame *)
316 plugin->get_gui_frame(0, 0);
318 case GAIN_COMPRESSORFRAME: {
320 gain_frame = (CompressorGainFrame *)
321 plugin->get_gui_frame(0, 0);
326 delete plugin->get_gui_frame(0, 0);
329 gain_change->update(gain_frame->gain, 0);
330 in->update(gain_frame->level, 0);
333 #ifndef DRAW_AFTER_BANDPASS
334 eqcanvas->update_spectrogram(freq_frame);
336 eqcanvas->update_spectrogram(freq_frame,
337 plugin->config.current_band * plugin->config.window_size / 2,
338 TOTAL_BANDS * plugin->config.window_size / 2,
339 plugin->config.window_size);
342 // draw the active band on top of the others
343 for( int pass = 0; pass < 2; pass++ ) {
344 for( int band = 0; band < TOTAL_BANDS; band++ ) {
345 if( band == plugin->config.current_band && pass == 0 ||
346 band != plugin->config.current_band && pass == 1 ) {
350 eqcanvas->draw_envelope(plugin->band_states[band]->envelope,
351 plugin->PluginAClient::project_sample_rate,
352 plugin->config.window_size,
353 band == plugin->config.current_band,
357 eqcanvas->canvas->flash(1);
360 int ComprMultiWindow::resize_event(int w, int h)
366 ComprMultiFPot::ComprMultiFPot(ComprMultiWindow *gui, ComprMultiEffect *plugin,
367 int x, int y, double *output, double min, double max)
368 : BC_FPot(x, y, *output, min, max)
371 this->plugin = plugin;
372 this->output = output;
376 int ComprMultiFPot::handle_event()
378 *output = get_value();
379 plugin->send_configure_change();
380 gui->update_eqcanvas();
385 ComprMultiQPot::ComprMultiQPot(ComprMultiWindow *gui, ComprMultiEffect *plugin,
386 int x, int y, int *output)
387 : BC_QPot(x, y, output ? *output : 0)
390 this->plugin = plugin;
391 this->output = output;
395 int ComprMultiQPot::handle_event()
398 *output = get_value();
399 plugin->send_configure_change();
400 gui->update_eqcanvas();
406 ComprMultiSize::ComprMultiSize(ComprMultiWindow *gui,
407 ComprMultiEffect *plugin, int x, int y)
408 : BC_PopupMenu(x, y, xS(100), "4096", 1)
411 this->plugin = plugin;
414 int ComprMultiSize::handle_event()
416 plugin->config.window_size = atoi(get_text());
417 plugin->send_configure_change();
418 gui->update_eqcanvas();
422 void ComprMultiSize::create_objects()
424 add_item(new BC_MenuItem("2048"));
425 add_item(new BC_MenuItem("4096"));
426 add_item(new BC_MenuItem("8192"));
427 add_item(new BC_MenuItem("16384"));
428 add_item(new BC_MenuItem("32768"));
429 add_item(new BC_MenuItem("65536"));
430 add_item(new BC_MenuItem("131072"));
431 add_item(new BC_MenuItem("262144"));
434 void ComprMultiSize::update(int size)
436 char string[BCTEXTLEN];
437 sprintf(string, "%d", size);
442 ComprMultiMkupGain::ComprMultiMkupGain(ComprMultiEffect *plugin,
443 ComprMultiWindow *window, int x, int y,
444 double *output, double min, double max)
445 : BC_FPot(x, y, *output, min, max)
447 this->window = window;
448 this->plugin = plugin;
449 this->output = output;
453 int ComprMultiMkupGain::handle_event()
455 *output = get_value();
456 plugin->send_configure_change();
457 window->canvas->update();
462 ComprMultiCanvas::ComprMultiCanvas(ComprMultiEffect *plugin,
463 ComprMultiWindow *window, int x, int y, int w, int h)
464 : CompressorCanvasBase(&plugin->config, plugin, window, x, y, w, h)
468 void ComprMultiCanvas::update_window()
470 ((ComprMultiWindow*)window)->update();
474 ComprMultiReaction::ComprMultiReaction(ComprMultiEffect *plugin,
475 ComprMultiWindow *window, int x, int y)
476 : BC_TumbleTextBox(window,
477 (float)plugin->config.bands[plugin->config.current_band].attack_len,
478 (float)MIN_ATTACK, (float)MAX_ATTACK, x, y, xS(100))
480 this->plugin = plugin;
485 int ComprMultiReaction::handle_event()
487 plugin->config.bands[plugin->config.current_band].attack_len = atof(get_text());
488 plugin->send_configure_change();
494 ComprMultiDecay::ComprMultiDecay(ComprMultiEffect *plugin,
495 ComprMultiWindow *window, int x, int y)
496 : BC_TumbleTextBox(window,
497 (float)plugin->config.bands[plugin->config.current_band].release_len,
498 (float)MIN_DECAY, (float)MAX_DECAY, x, y, xS(100))
500 this->plugin = plugin;
504 int ComprMultiDecay::handle_event()
506 plugin->config.bands[plugin->config.current_band].release_len = atof(get_text());
507 plugin->send_configure_change();
512 ComprMultiX::ComprMultiX(ComprMultiEffect *plugin,
513 ComprMultiWindow *window, int x, int y)
514 : BC_TumbleTextBox(window, (float)0.0,
515 plugin->config.min_db, plugin->config.max_db, x, y, xS(100))
517 this->plugin = plugin;
518 this->window = window;
522 int ComprMultiX::handle_event()
524 BandConfig *band_config = &plugin->config.bands[plugin->config.current_band];
526 int current_point = window->canvas->current_point;
527 if( current_point < band_config->levels.total ) {
528 band_config->levels.values[current_point].x = atof(get_text());
529 window->canvas->update();
530 plugin->send_configure_change();
536 ComprMultiY::ComprMultiY(ComprMultiEffect *plugin,
537 ComprMultiWindow *window, int x, int y)
538 : BC_TumbleTextBox(window, (float)0.0,
539 plugin->config.min_db, plugin->config.max_db, x, y, xS(100))
541 this->plugin = plugin;
542 this->window = window;
546 int ComprMultiY::handle_event()
548 BandConfig *band_config = &plugin->config.bands[plugin->config.current_band];
550 int current_point = window->canvas->current_point;
551 if( current_point < band_config->levels.total ) {
552 band_config->levels.values[current_point].y = atof(get_text());
553 window->canvas->update();
554 plugin->send_configure_change();
560 ComprMultiTrigger::ComprMultiTrigger(ComprMultiEffect *plugin,
561 ComprMultiWindow *window, int x, int y)
562 : BC_TumbleTextBox(window, (int)plugin->config.trigger,
563 MIN_TRIGGER, MAX_TRIGGER, x, y, xS(100))
565 this->plugin = plugin;
567 int ComprMultiTrigger::handle_event()
569 plugin->config.trigger = atol(get_text());
570 plugin->send_configure_change();
575 ComprMultiInput::ComprMultiInput(ComprMultiEffect *plugin,
576 ComprMultiWindow *window, int x, int y)
577 : BC_PopupMenu(x, y, xS(100),
578 ComprMultiInput::value_to_text(plugin->config.input), 1)
580 this->plugin = plugin;
581 this->window = window;
583 int ComprMultiInput::handle_event()
585 plugin->config.input = text_to_value(get_text());
587 plugin->send_configure_change();
591 void ComprMultiInput::create_objects()
593 for( int i = 0; i < 3; i++ ) {
594 add_item(new BC_MenuItem(value_to_text(i)));
598 const char* ComprMultiInput::value_to_text(int value)
601 case ComprMultiConfig::TRIGGER: return "Trigger";
602 case ComprMultiConfig::MAX: return "Maximum";
603 case ComprMultiConfig::SUM: return "Total";
609 int ComprMultiInput::text_to_value(char *text)
611 for( int i = 0; i < 3; i++ ) {
612 if( !strcmp(value_to_text(i), text) ) return i;
615 return ComprMultiConfig::TRIGGER;
619 ComprMultiClear::ComprMultiClear(ComprMultiEffect *plugin,
620 ComprMultiWindow *window, int x, int y)
621 : BC_GenericButton(x, y, _("Clear"))
623 this->plugin = plugin;
624 this->window = window;
627 int ComprMultiClear::handle_event()
629 BandConfig *band_config = &plugin->config.bands[plugin->config.current_band];
630 band_config->mkup_gain = 0.0;
631 band_config->levels.remove_all();
632 //plugin->config.dump();
634 plugin->send_configure_change();
638 ComprMultiReset::ComprMultiReset(ComprMultiEffect *plugin,
639 ComprMultiWindow *window, int x, int y)
640 : BC_GenericButton(x, y, _("Reset"))
642 this->plugin = plugin;
643 this->window = window;
646 int ComprMultiReset::handle_event()
648 plugin->config.q = 1.0;
649 plugin->config.window_size = 4096;
650 plugin->config.reset_bands();
651 plugin->config.reset_base();
652 //plugin->config.dump();
654 plugin->send_configure_change();
659 ComprMultiSmooth::ComprMultiSmooth(ComprMultiEffect *plugin, int x, int y)
660 : BC_CheckBox(x, y, plugin->config.smoothing_only, _("Smooth only"))
662 this->plugin = plugin;
665 int ComprMultiSmooth::handle_event()
667 plugin->config.smoothing_only = get_value();
668 plugin->send_configure_change();
673 ComprMultiSolo::ComprMultiSolo(ComprMultiEffect *plugin, int x, int y)
674 : BC_CheckBox(x, y, plugin->config.bands[plugin->config.current_band].solo, _("Solo band"))
676 this->plugin = plugin;
679 int ComprMultiSolo::handle_event()
681 plugin->config.bands[plugin->config.current_band].solo = get_value();
682 for( int i = 0; i < TOTAL_BANDS; i++ ) {
683 if( i != plugin->config.current_band ) {
684 plugin->config.bands[i].solo = 0;
687 plugin->send_configure_change();
692 ComprMultiBypass::ComprMultiBypass(ComprMultiEffect *plugin, int x, int y)
693 : BC_CheckBox(x, y, plugin->config.bands[plugin->config.current_band].bypass, _("Bypass band"))
695 this->plugin = plugin;
698 int ComprMultiBypass::handle_event()
700 plugin->config.bands[plugin->config.current_band].bypass = get_value();
701 plugin->send_configure_change();
706 ComprMultiBand::ComprMultiBand(ComprMultiWindow *window,
707 ComprMultiEffect *plugin, int x, int y, int number,
709 : BC_Radial(x, y, plugin->config.current_band == number, text)
711 this->window = window;
712 this->plugin = plugin;
713 this->number = number;
716 int ComprMultiBand::handle_event()
718 if( plugin->config.current_band != number ) {
719 plugin->config.current_band = number;
726 // printf("ComprMultiWindow::update_eqcanvas %d\n", __LINE__);
727 // for( int i = 0; i < plugin->config.window_size / 2; i++ )
730 // for( int band = 0; band < TOTAL_BANDS; band++ )
732 // sum += plugin->engines[band]->envelope[i];
735 // printf("%f ", sum);
736 // for( int band = 0; band < TOTAL_BANDS; band++ )
738 // printf("%f ", plugin->engines[band]->envelope[i]);