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 BandConfig *band_config = &plugin->config.bands[plugin->config.current_band];
76 BandConfig *prev_band = 0;
77 if( plugin->config.current_band > 0 ) {
78 prev_band = &plugin->config.bands[plugin->config.current_band - 1];
81 add_subwindow(title = new BC_Title(x, y, "In:"));
82 int y2 = y + title->get_h() + margin;
83 EDL *edl = plugin->get_edl();
84 add_subwindow(in = new BC_Meter(x, y2, METER_VERT,
86 edl->session->min_meter_db,
87 edl->session->max_meter_db,
88 edl->session->meter_format,
91 x += in->get_w() + margin;
93 add_subwindow(title = new BC_Title(x, y, "Gain:"));
94 add_subwindow(gain_change = new BC_Meter(x, y2, METER_VERT,
102 1)); // is_gain_change
103 x += gain_change->get_w() + xS(35);
105 add_subwindow(title = new BC_Title(x, y, _("Current band:")));
107 int x1 = title->get_x() + title->get_w() + margin;
108 char string[BCTEXTLEN];
109 for( int i = 0; i < TOTAL_BANDS; i++ ) {
110 sprintf(string, "%d", i + 1);
111 add_subwindow(band[i] = new ComprMultiBand(this, plugin,
113 x1 += band[i]->get_w() + margin;
115 y += band[0]->get_h() + 1;
118 add_subwindow(title = new BC_Title(x, y,
119 _("Sound level (Press shift to snap to grid):")));
120 y += title->get_h() + 1;
121 add_subwindow(canvas = new ComprMultiCanvas(plugin, this,
122 x, y, get_w() - x - control_margin - xS(10), canvas_y2 - y));
123 y += canvas->get_h() + yS(30);
125 add_subwindow(title = new BC_Title(margin, y, _("Bandwidth:")));
127 eqcanvas = new EQCanvas(this, margin, y,
128 canvas->get_w() + x - margin, get_h() - y - margin,
129 plugin->config.min_db, 0.0);
130 eqcanvas->freq_divisions = 10;
131 eqcanvas->initialize();
133 x = get_w() - control_margin;
135 add_subwindow(title = new BC_Title(x, y, _("Attack secs:")));
137 reaction = new ComprMultiReaction(plugin, this, x, y);
138 reaction->create_objects();
139 y += reaction->get_h() + margin;
141 add_subwindow(title = new BC_Title(x, y, _("Release secs:")));
143 decay = new ComprMultiDecay(plugin, this, x, y);
144 decay->create_objects();
145 y += decay->get_h() + margin;
147 add_subwindow(solo = new ComprMultiSolo(plugin, x, y));
148 y += solo->get_h() + margin;
149 add_subwindow(bypass = new ComprMultiBypass(plugin, x, y));
150 y += bypass->get_h() + margin;
151 add_subwindow(title = new BC_Title(x, y, _("Output:")));
154 y_text = new ComprMultiY(plugin, this, x, y);
155 y_text->create_objects();
156 y += y_text->get_h() + margin;
158 add_subwindow(title = new BC_Title(x, y, _("Input:")));
160 x_text = new ComprMultiX(plugin, this, x, y);
161 x_text->create_objects();
162 y += x_text->get_h() + margin;
164 add_subwindow(clear = new ComprMultiClear(plugin, x, y));
165 y += clear->get_h() + margin;
167 add_subwindow(title = new BC_Title(x, y, _("Freq range:")));
170 // the previous high frequency
173 ptr = &prev_band->freq;
176 add_subwindow(freq1 = new ComprMultiQPot(this,
178 get_w() - (margin + BC_Pot::calculate_w()) * 2,
182 // the current high frequency
183 ptr = &band_config->freq;
184 if( plugin->config.current_band == TOTAL_BANDS - 1 ) {
188 add_subwindow(freq2 = new ComprMultiQPot(this,
190 get_w() - margin - BC_Pot::calculate_w(),
193 y += freq1->get_h() + margin;
196 add_subwindow(bar = new BC_Bar(x, y, get_w() - x - margin));
197 y += bar->get_h() + margin;
199 add_subwindow(title = new BC_Title(x, y, _("Trigger Type:")));
201 add_subwindow(input = new ComprMultiInput(plugin, x, y));
202 input->create_objects();
203 y += input->get_h() + margin;
204 add_subwindow(title = new BC_Title(x, y, _("Trigger:")));
207 trigger = new ComprMultiTrigger(plugin, this, x, y);
208 trigger->create_objects();
209 if( plugin->config.input != ComprMultiConfig::TRIGGER ) trigger->disable();
210 y += trigger->get_h() + margin;
212 add_subwindow(smooth = new ComprMultiSmooth(plugin, x, y));
213 y += smooth->get_h() + margin;
215 add_subwindow(title = new BC_Title(x, y, _("Steepness:")));
216 add_subwindow(q = new ComprMultiFPot(this, plugin,
217 get_w() - margin - BC_Pot::calculate_w(), y,
218 &plugin->config.q, 0, 1));
219 y += q->get_h() + margin;
221 add_subwindow(title = new BC_Title(x, y, _("Window size:")));
223 add_subwindow(size = new ComprMultiSize(this,
227 size->create_objects();
228 size->update(plugin->config.window_size);
229 y += size->get_h() + margin;
231 canvas->create_objects();
236 // called when the user selects a different band
237 void ComprMultiWindow::update()
239 BandConfig *band_config = &plugin->config.bands[plugin->config.current_band];
241 for( int i = 0; i < TOTAL_BANDS; i++ ) {
242 if( plugin->config.current_band == i ) {
251 if( plugin->config.current_band > 0 ) {
252 ptr = &plugin->config.bands[plugin->config.current_band - 1].freq;
268 // top band edits the penultimate band
269 if( plugin->config.current_band < TOTAL_BANDS - 1 ) {
270 ptr = &band_config->freq;
286 q->update(plugin->config.q);
287 solo->update(band_config->solo);
288 bypass->update(band_config->bypass);
289 size->update(plugin->config.window_size);
291 if( atol(trigger->get_text()) != plugin->config.trigger ) {
292 trigger->update((int64_t)plugin->config.trigger);
295 if( strcmp(input->get_text(), ComprMultiInput::value_to_text(plugin->config.input)) ) {
296 input->set_text(ComprMultiInput::value_to_text(plugin->config.input));
299 if( plugin->config.input != ComprMultiConfig::TRIGGER && trigger->get_enabled() ) {
303 if( plugin->config.input == ComprMultiConfig::TRIGGER && !trigger->get_enabled() ) {
307 if( !EQUIV(atof(reaction->get_text()), band_config->attack_len) ) {
308 reaction->update((float)band_config->attack_len);
311 if( !EQUIV(atof(decay->get_text()), band_config->release_len) ) {
312 decay->update((float)band_config->release_len);
315 smooth->update(plugin->config.smoothing_only);
316 if( canvas->current_operation == ComprMultiCanvas::DRAG ) {
317 x_text->update((float)band_config->levels.values[canvas->current_point].x);
318 y_text->update((float)band_config->levels.values[canvas->current_point].y);
328 void ComprMultiWindow::update_eqcanvas()
330 plugin->calculate_envelope();
331 // filter GUI frames by band & data type
333 CompressorClientFrame *frame = 0;
334 // gdb plugin->dump_frames();
335 double tracking_position = plugin->get_tracking_position();
336 int dir = plugin->get_tracking_direction() == PLAY_REVERSE ? -1 : 1;
337 while( (frame = (CompressorClientFrame*)plugin->next_gui_frame()) ) {
338 if( dir*(frame->position - tracking_position) > 0 ) break;
339 if( frame->band == plugin->config.current_band ) {
340 // only frames for desired band
341 switch( frame->type ) {
342 case FREQ_COMPRESSORFRAME: {
344 freq_frame = (CompressorFreqFrame *)
345 plugin->get_gui_frame(0, 0);
347 case GAIN_COMPRESSORFRAME: {
349 gain_frame = (CompressorGainFrame *)
350 plugin->get_gui_frame(0, 0);
355 delete plugin->get_gui_frame(0, 0);
358 gain_change->update(gain_frame->gain, 0);
359 in->update(gain_frame->level, 0);
362 #ifndef DRAW_AFTER_BANDPASS
363 eqcanvas->update_spectrogram(freq_frame);
365 eqcanvas->update_spectrogram(freq_frame,
366 plugin->config.current_band * plugin->config.window_size / 2,
367 TOTAL_BANDS * plugin->config.window_size / 2,
368 plugin->config.window_size);
371 // draw the active band on top of the others
372 for( int pass = 0; pass < 2; pass++ ) {
373 for( int band = 0; band < TOTAL_BANDS; band++ ) {
374 if( band == plugin->config.current_band && pass == 0 ||
375 band != plugin->config.current_band && pass == 1 ) {
379 eqcanvas->draw_envelope(plugin->band_states[band]->envelope,
380 plugin->PluginAClient::project_sample_rate,
381 plugin->config.window_size,
382 band == plugin->config.current_band,
386 eqcanvas->canvas->flash(1);
389 int ComprMultiWindow::resize_event(int w, int h)
395 ComprMultiFPot::ComprMultiFPot(ComprMultiWindow *gui, ComprMultiEffect *plugin,
396 int x, int y, double *output, double min, double max)
397 : BC_FPot(x, y, *output, min, max)
400 this->plugin = plugin;
401 this->output = output;
405 int ComprMultiFPot::handle_event()
407 *output = get_value();
408 plugin->send_configure_change();
409 gui->update_eqcanvas();
414 ComprMultiQPot::ComprMultiQPot(ComprMultiWindow *gui, ComprMultiEffect *plugin,
415 int x, int y, int *output)
416 : BC_QPot(x, y, output ? *output : 0)
419 this->plugin = plugin;
420 this->output = output;
424 int ComprMultiQPot::handle_event()
427 *output = get_value();
428 plugin->send_configure_change();
429 gui->update_eqcanvas();
435 ComprMultiSize::ComprMultiSize(ComprMultiWindow *gui,
436 ComprMultiEffect *plugin, int x, int y)
437 : BC_PopupMenu(x, y, xS(100), "4096", 1)
440 this->plugin = plugin;
443 int ComprMultiSize::handle_event()
445 plugin->config.window_size = atoi(get_text());
446 plugin->send_configure_change();
447 gui->update_eqcanvas();
452 void ComprMultiSize::create_objects()
454 add_item(new BC_MenuItem("2048"));
455 add_item(new BC_MenuItem("4096"));
456 add_item(new BC_MenuItem("8192"));
457 add_item(new BC_MenuItem("16384"));
458 add_item(new BC_MenuItem("32768"));
459 add_item(new BC_MenuItem("65536"));
460 add_item(new BC_MenuItem("131072"));
461 add_item(new BC_MenuItem("262144"));
465 void ComprMultiSize::update(int size)
467 char string[BCTEXTLEN];
468 sprintf(string, "%d", size);
473 ComprMultiCanvas::ComprMultiCanvas(ComprMultiEffect *plugin,
474 ComprMultiWindow *window, int x, int y, int w, int h)
475 : CompressorCanvasBase(&plugin->config, plugin, window, x, y, w, h)
479 void ComprMultiCanvas::update_window()
481 ((ComprMultiWindow*)window)->update();
485 ComprMultiReaction::ComprMultiReaction(ComprMultiEffect *plugin,
486 ComprMultiWindow *window, int x, int y)
487 : BC_TumbleTextBox(window,
488 (float)plugin->config.bands[plugin->config.current_band].attack_len,
489 (float)MIN_ATTACK, (float)MAX_ATTACK, x, y, xS(100))
491 this->plugin = plugin;
496 int ComprMultiReaction::handle_event()
498 plugin->config.bands[plugin->config.current_band].attack_len = atof(get_text());
499 plugin->send_configure_change();
505 ComprMultiDecay::ComprMultiDecay(ComprMultiEffect *plugin,
506 ComprMultiWindow *window, int x, int y)
507 : BC_TumbleTextBox(window,
508 (float)plugin->config.bands[plugin->config.current_band].release_len,
509 (float)MIN_DECAY, (float)MAX_DECAY, x, y, xS(100))
511 this->plugin = plugin;
515 int ComprMultiDecay::handle_event()
517 plugin->config.bands[plugin->config.current_band].release_len = atof(get_text());
518 plugin->send_configure_change();
523 ComprMultiX::ComprMultiX(ComprMultiEffect *plugin,
524 ComprMultiWindow *window, int x, int y)
525 : BC_TumbleTextBox(window, (float)0.0,
526 plugin->config.min_db, plugin->config.max_db, x, y, xS(100))
528 this->plugin = plugin;
532 int ComprMultiX::handle_event()
534 BandConfig *band_config = &plugin->config.bands[plugin->config.current_band];
536 int current_point = ((ComprMultiWindow*)plugin->thread->window)->canvas->current_point;
537 if( current_point < band_config->levels.total ) {
538 band_config->levels.values[current_point].x = atof(get_text());
539 ((ComprMultiWindow*)plugin->thread->window)->canvas->update();
540 plugin->send_configure_change();
546 ComprMultiY::ComprMultiY(ComprMultiEffect *plugin,
547 ComprMultiWindow *window,
550 : BC_TumbleTextBox(window, (float)0.0,
551 plugin->config.min_db, plugin->config.max_db, x, y, xS(100))
553 this->plugin = plugin;
557 int ComprMultiY::handle_event()
559 BandConfig *band_config = &plugin->config.bands[plugin->config.current_band];
561 int current_point = ((ComprMultiWindow*)plugin->thread->window)->canvas->current_point;
562 if( current_point < band_config->levels.total ) {
563 band_config->levels.values[current_point].y = atof(get_text());
564 ((ComprMultiWindow*)plugin->thread->window)->canvas->update();
565 plugin->send_configure_change();
571 ComprMultiTrigger::ComprMultiTrigger(ComprMultiEffect *plugin,
572 ComprMultiWindow *window,
575 : BC_TumbleTextBox(window, (int)plugin->config.trigger,
576 MIN_TRIGGER, MAX_TRIGGER, x, y, xS(100))
578 this->plugin = plugin;
580 int ComprMultiTrigger::handle_event()
582 plugin->config.trigger = atol(get_text());
583 plugin->send_configure_change();
588 ComprMultiInput::ComprMultiInput(ComprMultiEffect *plugin, int x, int y)
589 : BC_PopupMenu(x, y, xS(100),
590 ComprMultiInput::value_to_text(plugin->config.input), 1)
592 this->plugin = plugin;
594 int ComprMultiInput::handle_event()
596 plugin->config.input = text_to_value(get_text());
597 ((ComprMultiWindow*)plugin->thread->window)->update();
598 plugin->send_configure_change();
602 void ComprMultiInput::create_objects()
604 for( int i = 0; i < 3; i++ ) {
605 add_item(new BC_MenuItem(value_to_text(i)));
609 const char* ComprMultiInput::value_to_text(int value)
612 case ComprMultiConfig::TRIGGER: return "Trigger";
613 case ComprMultiConfig::MAX: return "Maximum";
614 case ComprMultiConfig::SUM: return "Total";
620 int ComprMultiInput::text_to_value(char *text)
622 for( int i = 0; i < 3; i++ ) {
623 if( !strcmp(value_to_text(i), text) ) return i;
626 return ComprMultiConfig::TRIGGER;
630 ComprMultiClear::ComprMultiClear(ComprMultiEffect *plugin, int x, int y)
631 : BC_GenericButton(x, y, _("Clear"))
633 this->plugin = plugin;
636 int ComprMultiClear::handle_event()
638 BandConfig *band_config = &plugin->config.bands[plugin->config.current_band];
640 band_config->levels.remove_all();
641 //plugin->config.dump();
642 ((ComprMultiWindow*)plugin->thread->window)->update();
643 plugin->send_configure_change();
648 ComprMultiSmooth::ComprMultiSmooth(ComprMultiEffect *plugin, int x, int y)
649 : BC_CheckBox(x, y, plugin->config.smoothing_only, _("Smooth only"))
651 this->plugin = plugin;
654 int ComprMultiSmooth::handle_event()
656 plugin->config.smoothing_only = get_value();
657 plugin->send_configure_change();
662 ComprMultiSolo::ComprMultiSolo(ComprMultiEffect *plugin, int x, int y)
663 : BC_CheckBox(x, y, plugin->config.bands[plugin->config.current_band].solo, _("Solo band"))
665 this->plugin = plugin;
668 int ComprMultiSolo::handle_event()
670 plugin->config.bands[plugin->config.current_band].solo = get_value();
671 for( int i = 0; i < TOTAL_BANDS; i++ ) {
672 if( i != plugin->config.current_band ) {
673 plugin->config.bands[i].solo = 0;
676 plugin->send_configure_change();
681 ComprMultiBypass::ComprMultiBypass(ComprMultiEffect *plugin, int x, int y)
682 : BC_CheckBox(x, y, plugin->config.bands[plugin->config.current_band].bypass, _("Bypass band"))
684 this->plugin = plugin;
687 int ComprMultiBypass::handle_event()
689 plugin->config.bands[plugin->config.current_band].bypass = get_value();
690 plugin->send_configure_change();
695 ComprMultiBand::ComprMultiBand(ComprMultiWindow *window,
696 ComprMultiEffect *plugin, int x, int y, int number,
698 : BC_Radial(x, y, plugin->config.current_band == number, text)
700 this->window = window;
701 this->plugin = plugin;
702 this->number = number;
705 int ComprMultiBand::handle_event()
707 if( plugin->config.current_band != number ) {
708 plugin->config.current_band = number;
715 // printf("ComprMultiWindow::update_eqcanvas %d\n", __LINE__);
716 // for( int i = 0; i < plugin->config.window_size / 2; i++ )
719 // for( int band = 0; band < TOTAL_BANDS; band++ )
721 // sum += plugin->engines[band]->envelope[i];
724 // printf("%f ", sum);
725 // for( int band = 0; band < TOTAL_BANDS; band++ )
727 // printf("%f ", plugin->engines[band]->envelope[i]);