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"
33 #include "transportque.inc"
38 ComprMultiWindow::ComprMultiWindow(ComprMultiEffect *plugin)
39 : PluginClientWindow(plugin, xS(650),yS(560), xS(650),yS(560), 0)
41 this->plugin = plugin;
42 char string[BCTEXTLEN];
43 // set the default directory
44 sprintf(string, "%s/compressormulti.rc", File::get_config_path());
45 defaults = new BC_Hash(string);
47 plugin->config.current_band = defaults->get("CURRENT_BAND", plugin->config.current_band);
52 ComprMultiWindow::~ComprMultiWindow()
54 defaults->update("CURRENT_BAND", plugin->config.current_band);
69 void ComprMultiWindow::create_objects()
71 int margin = client->get_theme()->widget_border;
72 int x = margin, y = margin;
73 int control_margin = xS(150);
74 int canvas_y2 = get_h() * 2 / 3;
76 add_subwindow(title = new BC_Title(x, y, "In:"));
77 int y2 = y + title->get_h() + margin;
78 EDL *edl = plugin->get_edl();
79 add_subwindow(in = new BC_Meter(x, y2, METER_VERT,
81 edl->session->min_meter_db,
82 edl->session->max_meter_db,
83 edl->session->meter_format,
86 x += in->get_w() + margin;
88 add_subwindow(title = new BC_Title(x, y, "Gain:"));
89 add_subwindow(gain_change = new BC_Meter(x, y2, METER_VERT,
97 1)); // is_gain_change
98 x += gain_change->get_w() + xS(35);
100 add_subwindow(title = new BC_Title(x, y, _("Current band:")));
102 int x1 = title->get_x() + title->get_w() + margin;
103 char string[BCTEXTLEN];
104 for( int i = 0; i < TOTAL_BANDS; i++ ) {
105 sprintf(string, "%d", i + 1);
106 add_subwindow(band[i] = new ComprMultiBand(this, plugin,
108 x1 += band[i]->get_w() + margin;
110 y += band[0]->get_h() + 1;
113 add_subwindow(title = new BC_Title(x, y,
114 _("Sound level (Press shift to snap to grid):")));
115 y += title->get_h() + 1;
116 add_subwindow(canvas = new ComprMultiCanvas(plugin, this,
117 x, y, get_w() - x - control_margin - xS(10), canvas_y2 - y));
118 y += canvas->get_h() + yS(30);
120 add_subwindow(title = new BC_Title(margin, y, _("Bandwidth:")));
122 eqcanvas = new EQCanvas(this, margin, y,
123 canvas->get_w() + x - margin, get_h() - y - margin,
124 plugin->config.min_db, 0.0);
125 eqcanvas->freq_divisions = 10;
126 eqcanvas->initialize();
128 x = get_w() - control_margin;
130 add_subwindow(title = new BC_Title(x, y, _("Attack secs:")));
132 reaction = new ComprMultiReaction(plugin, this, x, y);
133 reaction->create_objects();
134 y += reaction->get_h() + margin;
136 add_subwindow(title = new BC_Title(x, y, _("Release secs:")));
138 decay = new ComprMultiDecay(plugin, this, x, y);
139 decay->create_objects();
140 y += decay->get_h() + margin;
142 add_subwindow(solo = new ComprMultiSolo(plugin, x, y));
143 y += solo->get_h() + margin;
144 add_subwindow(bypass = new ComprMultiBypass(plugin, x, y));
145 y += bypass->get_h() + margin;
146 add_subwindow(title = new BC_Title(x, y, _("Output:")));
149 y_text = new ComprMultiY(plugin, this, x, y);
150 y_text->create_objects();
151 y += y_text->get_h() + margin;
153 add_subwindow(title = new BC_Title(x, y, _("Input:")));
155 x_text = new ComprMultiX(plugin, this, x, y);
156 x_text->create_objects();
157 y += x_text->get_h() + margin;
159 add_subwindow(clear = new ComprMultiClear(plugin, this, x, y));
160 y += clear->get_h() + margin;
162 add_subwindow(title = new BC_Title(x, y, _("Gain:")));
164 int x2 = get_w() - (margin + BC_Pot::calculate_w()) * 2;
165 int x3 = get_w() - (margin + BC_Pot::calculate_w());
166 add_subwindow(title = new BC_Title(x2, y, _("Freq range:")));
167 y += title->get_h() + margin;
169 add_subwindow(mkup_gain = new ComprMultiMkupGain(plugin, this, x, y,
170 &plugin->config.bands[plugin->config.current_band].mkup_gain,
172 // the previous high frequency
173 add_subwindow(freq1 = new ComprMultiQPot(this, plugin, x2, y,
174 plugin->config.current_band == 0 ? 0 :
175 &plugin->config.bands[plugin->config.current_band-1].freq));
176 // the current high frequency
177 add_subwindow(freq2 = new ComprMultiQPot(this, plugin, x3, y,
178 plugin->config.current_band!=TOTAL_BANDS-1 ? 0 :
179 &plugin->config.bands[plugin->config.current_band].freq));
180 y += freq1->get_h() + margin;
183 add_subwindow(bar = new BC_Bar(x, y, get_w() - x - margin));
184 y += bar->get_h() + margin;
186 add_subwindow(title = new BC_Title(x, y, _("Trigger Type:")));
188 add_subwindow(input = new ComprMultiInput(plugin, this, x, y));
189 input->create_objects();
190 y += input->get_h() + margin;
191 add_subwindow(title = new BC_Title(x, y, _("Channel:")));
194 trigger = new ComprMultiTrigger(plugin, this, x, y);
195 trigger->create_objects();
196 if( plugin->config.input != ComprMultiConfig::TRIGGER ) trigger->disable();
197 y += trigger->get_h() + margin;
199 add_subwindow(smooth = new ComprMultiSmooth(plugin, x, y));
200 y += smooth->get_h() + margin;
202 add_subwindow(title = new BC_Title(x, y, _("Steepness:")));
203 add_subwindow(q = new ComprMultiFPot(this, plugin,
204 get_w() - margin - BC_Pot::calculate_w(), y,
205 &plugin->config.q, 0, 1));
206 y += q->get_h() + margin;
208 add_subwindow(title = new BC_Title(x, y, _("Window size:")));
210 add_subwindow(size = new ComprMultiSize(this, plugin, x, y));
211 size->create_objects();
212 size->update(plugin->config.window_size);
213 y += size->get_h() + margin;
215 add_subwindow(reset = new ComprMultiReset(plugin, this, x, y));
217 canvas->create_objects();
222 // called when the user selects a different band
223 void ComprMultiWindow::update()
225 int curr_band = plugin->config.current_band;
226 for( int i = 0; i < TOTAL_BANDS; i++ )
227 band[i]->update(curr_band == i);
229 int *ptr1 = !curr_band ? 0 :
230 &plugin->config.bands[curr_band-1].freq;
231 freq1->output = ptr1;
233 freq1->update(*ptr1);
241 // top band edits the penultimate band
242 int *ptr2 = curr_band == TOTAL_BANDS-1 ? 0 :
243 &plugin->config.bands[curr_band].freq;
244 freq2->output = ptr2;
246 freq2->update(*ptr2);
254 q->update(plugin->config.q);
255 BandConfig *band_config = &plugin->config.bands[curr_band];
256 double *ptr3 = &band_config->mkup_gain;
257 mkup_gain->output = ptr3;
258 mkup_gain->update(*ptr3);
259 solo->update(band_config->solo);
260 bypass->update(band_config->bypass);
261 size->update(plugin->config.window_size);
263 if( atol(trigger->get_text()) != plugin->config.trigger ) {
264 trigger->update((int64_t)plugin->config.trigger);
267 if( strcmp(input->get_text(), ComprMultiInput::value_to_text(plugin->config.input)) ) {
268 input->set_text(ComprMultiInput::value_to_text(plugin->config.input));
271 if( plugin->config.input != ComprMultiConfig::TRIGGER && trigger->get_enabled() ) {
275 if( plugin->config.input == ComprMultiConfig::TRIGGER && !trigger->get_enabled() ) {
279 if( !EQUIV(atof(reaction->get_text()), band_config->attack_len) ) {
280 reaction->update((float)band_config->attack_len);
283 if( !EQUIV(atof(decay->get_text()), band_config->release_len) ) {
284 decay->update((float)band_config->release_len);
287 smooth->update(plugin->config.smoothing_only);
288 if( canvas->current_operation == ComprMultiCanvas::DRAG ) {
289 x_text->update((float)band_config->levels.values[canvas->current_point].x);
290 y_text->update((float)band_config->levels.values[canvas->current_point].y);
300 void ComprMultiWindow::update_eqcanvas()
302 plugin->calculate_envelope();
303 // filter GUI frames by band & data type
305 CompressorClientFrame *frame = 0;
306 // gdb plugin->dump_frames();
307 double tracking_position = plugin->get_tracking_position();
308 int dir = plugin->get_tracking_direction() == PLAY_REVERSE ? -1 : 1;
309 while( (frame = (CompressorClientFrame*)plugin->next_gui_frame()) ) {
310 if( dir*(frame->position - tracking_position) > 0 ) break;
311 if( frame->band == plugin->config.current_band ) {
312 // only frames for desired band
313 switch( frame->type ) {
314 case FREQ_COMPRESSORFRAME: {
316 freq_frame = (CompressorFreqFrame *)
317 plugin->get_gui_frame(0, 0);
319 case GAIN_COMPRESSORFRAME: {
321 gain_frame = (CompressorGainFrame *)
322 plugin->get_gui_frame(0, 0);
327 delete plugin->get_gui_frame(0, 0);
330 gain_change->update(gain_frame->gain, 0);
331 in->update(gain_frame->level, 0);
334 #ifndef DRAW_AFTER_BANDPASS
335 eqcanvas->update_spectrogram(freq_frame);
337 eqcanvas->update_spectrogram(freq_frame,
338 plugin->config.current_band * plugin->config.window_size / 2,
339 TOTAL_BANDS * plugin->config.window_size / 2,
340 plugin->config.window_size);
343 // draw the active band on top of the others
344 for( int pass = 0; pass < 2; pass++ ) {
345 for( int band = 0; band < TOTAL_BANDS; band++ ) {
346 if( band == plugin->config.current_band && pass == 0 ||
347 band != plugin->config.current_band && pass == 1 ) {
351 eqcanvas->draw_envelope(plugin->band_states[band]->envelope,
352 plugin->PluginAClient::project_sample_rate,
353 plugin->config.window_size,
354 band == plugin->config.current_band,
358 eqcanvas->canvas->flash(1);
361 int ComprMultiWindow::resize_event(int w, int h)
367 ComprMultiFPot::ComprMultiFPot(ComprMultiWindow *gui, ComprMultiEffect *plugin,
368 int x, int y, double *output, double min, double max)
369 : BC_FPot(x, y, *output, min, max)
372 this->plugin = plugin;
373 this->output = output;
377 int ComprMultiFPot::handle_event()
379 *output = get_value();
380 plugin->send_configure_change();
381 gui->update_eqcanvas();
386 ComprMultiQPot::ComprMultiQPot(ComprMultiWindow *gui, ComprMultiEffect *plugin,
387 int x, int y, int *output)
388 : BC_QPot(x, y, output ? *output : 0)
391 this->plugin = plugin;
392 this->output = output;
396 int ComprMultiQPot::handle_event()
399 *output = get_value();
400 plugin->send_configure_change();
401 gui->update_eqcanvas();
407 ComprMultiSize::ComprMultiSize(ComprMultiWindow *gui,
408 ComprMultiEffect *plugin, int x, int y)
409 : BC_PopupMenu(x, y, xS(100), "4096", 1)
412 this->plugin = plugin;
415 int ComprMultiSize::handle_event()
417 plugin->config.window_size = atoi(get_text());
418 plugin->send_configure_change();
419 gui->update_eqcanvas();
423 void ComprMultiSize::create_objects()
425 add_item(new BC_MenuItem("2048"));
426 add_item(new BC_MenuItem("4096"));
427 add_item(new BC_MenuItem("8192"));
428 add_item(new BC_MenuItem("16384"));
429 add_item(new BC_MenuItem("32768"));
430 add_item(new BC_MenuItem("65536"));
431 add_item(new BC_MenuItem("131072"));
432 add_item(new BC_MenuItem("262144"));
435 void ComprMultiSize::update(int size)
437 char string[BCTEXTLEN];
438 sprintf(string, "%d", size);
443 ComprMultiMkupGain::ComprMultiMkupGain(ComprMultiEffect *plugin,
444 ComprMultiWindow *window, int x, int y,
445 double *output, double min, double max)
446 : BC_FPot(x, y, *output, min, max)
448 this->window = window;
449 this->plugin = plugin;
450 this->output = output;
454 int ComprMultiMkupGain::handle_event()
456 *output = get_value();
457 plugin->send_configure_change();
458 window->canvas->update();
463 ComprMultiCanvas::ComprMultiCanvas(ComprMultiEffect *plugin,
464 ComprMultiWindow *window, int x, int y, int w, int h)
465 : CompressorCanvasBase(&plugin->config, plugin, window, x, y, w, h)
469 void ComprMultiCanvas::update_window()
471 ((ComprMultiWindow*)window)->update();
475 ComprMultiReaction::ComprMultiReaction(ComprMultiEffect *plugin,
476 ComprMultiWindow *window, int x, int y)
477 : BC_TumbleTextBox(window,
478 (float)plugin->config.bands[plugin->config.current_band].attack_len,
479 (float)MIN_ATTACK, (float)MAX_ATTACK, x, y, xS(100))
481 this->plugin = plugin;
486 int ComprMultiReaction::handle_event()
488 plugin->config.bands[plugin->config.current_band].attack_len = atof(get_text());
489 plugin->send_configure_change();
495 ComprMultiDecay::ComprMultiDecay(ComprMultiEffect *plugin,
496 ComprMultiWindow *window, int x, int y)
497 : BC_TumbleTextBox(window,
498 (float)plugin->config.bands[plugin->config.current_band].release_len,
499 (float)MIN_DECAY, (float)MAX_DECAY, x, y, xS(100))
501 this->plugin = plugin;
505 int ComprMultiDecay::handle_event()
507 plugin->config.bands[plugin->config.current_band].release_len = atof(get_text());
508 plugin->send_configure_change();
513 ComprMultiX::ComprMultiX(ComprMultiEffect *plugin,
514 ComprMultiWindow *window, int x, int y)
515 : BC_TumbleTextBox(window, (float)0.0,
516 plugin->config.min_db, plugin->config.max_db, x, y, xS(100))
518 this->plugin = plugin;
519 this->window = window;
523 int ComprMultiX::handle_event()
525 BandConfig *band_config = &plugin->config.bands[plugin->config.current_band];
527 int current_point = window->canvas->current_point;
528 if( current_point < band_config->levels.total ) {
529 band_config->levels.values[current_point].x = atof(get_text());
530 window->canvas->update();
531 plugin->send_configure_change();
537 ComprMultiY::ComprMultiY(ComprMultiEffect *plugin,
538 ComprMultiWindow *window, int x, int y)
539 : BC_TumbleTextBox(window, (float)0.0,
540 plugin->config.min_db, plugin->config.max_db, x, y, xS(100))
542 this->plugin = plugin;
543 this->window = window;
547 int ComprMultiY::handle_event()
549 BandConfig *band_config = &plugin->config.bands[plugin->config.current_band];
551 int current_point = window->canvas->current_point;
552 if( current_point < band_config->levels.total ) {
553 band_config->levels.values[current_point].y = atof(get_text());
554 window->canvas->update();
555 plugin->send_configure_change();
561 ComprMultiTrigger::ComprMultiTrigger(ComprMultiEffect *plugin,
562 ComprMultiWindow *window, int x, int y)
563 : BC_TumbleTextBox(window, (int)plugin->config.trigger,
564 MIN_TRIGGER, MAX_TRIGGER, x, y, xS(100))
566 this->plugin = plugin;
568 int ComprMultiTrigger::handle_event()
570 plugin->config.trigger = atol(get_text());
571 plugin->send_configure_change();
576 ComprMultiInput::ComprMultiInput(ComprMultiEffect *plugin,
577 ComprMultiWindow *window, int x, int y)
578 : BC_PopupMenu(x, y, xS(100),
579 ComprMultiInput::value_to_text(plugin->config.input), 1)
581 this->plugin = plugin;
582 this->window = window;
584 int ComprMultiInput::handle_event()
586 plugin->config.input = text_to_value(get_text());
588 plugin->send_configure_change();
592 void ComprMultiInput::create_objects()
594 for( int i = 0; i < 3; i++ ) {
595 add_item(new BC_MenuItem(value_to_text(i)));
599 const char* ComprMultiInput::value_to_text(int value)
602 case ComprMultiConfig::TRIGGER: return "Trigger";
603 case ComprMultiConfig::MAX: return "Maximum";
604 case ComprMultiConfig::SUM: return "Total";
610 int ComprMultiInput::text_to_value(char *text)
612 for( int i = 0; i < 3; i++ ) {
613 if( !strcmp(value_to_text(i), text) ) return i;
616 return ComprMultiConfig::TRIGGER;
620 ComprMultiClear::ComprMultiClear(ComprMultiEffect *plugin,
621 ComprMultiWindow *window, int x, int y)
622 : BC_GenericButton(x, y, _("Clear"))
624 this->plugin = plugin;
625 this->window = window;
628 int ComprMultiClear::handle_event()
630 BandConfig *band_config = &plugin->config.bands[plugin->config.current_band];
631 band_config->mkup_gain = 0.0;
632 band_config->levels.remove_all();
633 //plugin->config.dump();
635 plugin->send_configure_change();
639 ComprMultiReset::ComprMultiReset(ComprMultiEffect *plugin,
640 ComprMultiWindow *window, int x, int y)
641 : BC_GenericButton(x, y, _("Reset"))
643 this->plugin = plugin;
644 this->window = window;
647 int ComprMultiReset::handle_event()
649 plugin->config.q = 1.0;
650 plugin->config.window_size = 4096;
651 plugin->config.reset_bands();
652 plugin->config.reset_base();
653 //plugin->config.dump();
655 plugin->send_configure_change();
660 ComprMultiSmooth::ComprMultiSmooth(ComprMultiEffect *plugin, int x, int y)
661 : BC_CheckBox(x, y, plugin->config.smoothing_only, _("Smooth only"))
663 this->plugin = plugin;
666 int ComprMultiSmooth::handle_event()
668 plugin->config.smoothing_only = get_value();
669 plugin->send_configure_change();
674 ComprMultiSolo::ComprMultiSolo(ComprMultiEffect *plugin, int x, int y)
675 : BC_CheckBox(x, y, plugin->config.bands[plugin->config.current_band].solo, _("Solo band"))
677 this->plugin = plugin;
680 int ComprMultiSolo::handle_event()
682 plugin->config.bands[plugin->config.current_band].solo = get_value();
683 for( int i = 0; i < TOTAL_BANDS; i++ ) {
684 if( i != plugin->config.current_band ) {
685 plugin->config.bands[i].solo = 0;
688 plugin->send_configure_change();
693 ComprMultiBypass::ComprMultiBypass(ComprMultiEffect *plugin, int x, int y)
694 : BC_CheckBox(x, y, plugin->config.bands[plugin->config.current_band].bypass, _("Bypass band"))
696 this->plugin = plugin;
699 int ComprMultiBypass::handle_event()
701 plugin->config.bands[plugin->config.current_band].bypass = get_value();
702 plugin->send_configure_change();
707 ComprMultiBand::ComprMultiBand(ComprMultiWindow *window,
708 ComprMultiEffect *plugin, int x, int y, int number,
710 : BC_Radial(x, y, plugin->config.current_band == number, text)
712 this->window = window;
713 this->plugin = plugin;
714 this->number = number;
717 int ComprMultiBand::handle_event()
719 if( plugin->config.current_band != number ) {
720 plugin->config.current_band = number;
727 // printf("ComprMultiWindow::update_eqcanvas %d\n", __LINE__);
728 // for( int i = 0; i < plugin->config.window_size / 2; i++ )
731 // for( int band = 0; band < TOTAL_BANDS; band++ )
733 // sum += plugin->engines[band]->envelope[i];
736 // printf("%f ", sum);
737 // for( int band = 0; band < TOTAL_BANDS; band++ )
739 // printf("%f ", plugin->engines[band]->envelope[i]);