1 /* B.Oops 2 * Glitch effect sequencer LV2 plugin 3 * 4 * Copyright (C) 2020 by Sven Jähnichen 5 * 6 * This program is free software: you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation, either version 3 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program. If not, see <https://www.gnu.org/licenses/>. 18 */ 19 20 #ifndef OPTIONPHASER_HPP_ 21 #define OPTIONPHASER_HPP_ 22 23 #include <new> 24 #include "OptionWidget.hpp" 25 #include "BWidgets/Label.hpp" 26 #include "DialRange.hpp" 27 28 class OptionPhaser : public OptionWidget 29 { 30 public: OptionPhaser()31 OptionPhaser () : OptionPhaser (0.0, 0.0, 0.0, 0.0, "widget") {} OptionPhaser(const double x,const double y,const double width,const double height,const std::string & name)32 OptionPhaser (const double x, const double y, const double width, const double height, const std::string& name) : 33 OptionWidget (x, y, width, height, name), 34 loFreqLabel (10, 100, 60, 20, "ctlabel", BOOPS_LABEL_LOW_FREQ), 35 hiFreqLabel (90, 100, 60, 20, "ctlabel", BOOPS_LABEL_HIGH_FREQ), 36 modRateLabel (160, 100, 80, 20, "ctlabel", BOOPS_LABEL_MODULATION), 37 modPhaseLabel (240, 100, 80, 20, "ctlabel", BOOPS_LABEL_STEREO_PHASE), 38 stepsLabel (330, 100, 60, 20, "ctlabel", BOOPS_LABEL_STEPS), 39 feedbackLabel (410, 100, 60, 20, "ctlabel", BOOPS_LABEL_FEEDBACK) 40 { 41 try 42 { 43 options[0] = new DialRange (10, 20, 60, 60, "pad0", 0.5, 0.0, 1.0, 0.0, BIDIRECTIONAL, "%1.0f", BOOPS_LABEL_HZ, [] (double x) {return 20.0 + 19980.0 * pow (x, 3.0);}, [] (double x) {return pow ((LIMIT (x, 20, 20000) - 20.0) / 19980.0, 1.0 / 3.0);}); 44 options[1] = new BWidgets::ValueWidget (0, 0, 0, 0, "widget", 0.0); 45 options[2] = new DialRange (90, 20, 60, 60, "pad0", 0.5, 0.0, 1.0, 0.0, BIDIRECTIONAL, "%1.0f", BOOPS_LABEL_HZ, [] (double x) {return 20.0 + 19980.0 * pow (x, 3.0);}, [] (double x) {return pow ((LIMIT (x, 20, 20000) - 20.0) / 19980.0, 1.0 / 3.0);}); 46 options[3] = new BWidgets::ValueWidget (0, 0, 0, 0, "widget", 0.0); 47 options[4] = new DialRange (170, 20, 60, 60, "pad0", 0.5, 0.0, 1.0, 0.0, BIDIRECTIONAL, "%1.2f", BOOPS_LABEL_HZ, [] (double x) {return 10.0 * pow (x, 3.0);}, [] (double x) {return pow (LIMIT (x, 0.0, 10.0) / 10.0, 1.0 / 3.0);}); 48 options[5] = new BWidgets::ValueWidget (0, 0, 0, 0, "widget", 0.0); 49 options[6] = new DialRange (250, 20, 60, 60, "pad0", 0.5, 0.0, 1.0, 0.0, BIDIRECTIONAL, "%1.1f", "°", [] (double x) {return 360.0 * x;}, [] (double x) {return LIMIT (x, 0.0, 360.0) / 360.0;}); 50 options[7] = new BWidgets::ValueWidget (0, 0, 0, 0, "widget", 0.0); 51 options[8] = new DialRange (410, 20, 60, 60, "pad0", 0.5, 0.0, 1.0, 0.0, BIDIRECTIONAL, "%1.2f", "", [] (double x) {return 2.0 * x - 1.0;}, [] (double x) {return (LIMIT (x, -1.0, 1.0) + 1.0) / 2.0;}); 52 options[9] = new BWidgets::ValueWidget (0, 0, 0, 0, "widget", 0.0); 53 options[10] = new Dial (330, 20, 60, 60, "pad0", 0.5, 0.0, 1.0, 0.0, "%1.0f", "", [] (double x) {return floor (1.0 + LIMIT (x * 10.0, 0, 9));}, [] (double x) {return (LIMIT (x, 1.0, 10.0) - 0.99999) / 10.0;}); 54 } 55 catch (std::bad_alloc& ba) {throw ba;} 56 57 for (int i = 0; i < 10; i += 2) 58 { 59 options[i]->setCallbackFunction (BEvents::VALUE_CHANGED_EVENT, valueChangedCallback); 60 ((DialRange*)options[i])->range.setCallbackFunction (BEvents::VALUE_CHANGED_EVENT, rangeChangedCallback); 61 options[i + 1]->setCallbackFunction (BEvents::VALUE_CHANGED_EVENT, valueChangedCallback); 62 } 63 options[10]->setCallbackFunction (BEvents::VALUE_CHANGED_EVENT, valueChangedCallback); 64 65 add (loFreqLabel); 66 add (hiFreqLabel); 67 add (modRateLabel); 68 add (modPhaseLabel); 69 add (stepsLabel); 70 add (feedbackLabel); 71 for (int i = 0; i < 11; ++i) add (*options[i]); 72 } 73 OptionPhaser(const OptionPhaser & that)74 OptionPhaser (const OptionPhaser& that) : 75 OptionWidget (that), 76 loFreqLabel (that.loFreqLabel), hiFreqLabel (that.hiFreqLabel), 77 modRateLabel (that.modRateLabel), modPhaseLabel (that.modPhaseLabel), 78 stepsLabel (that.stepsLabel), feedbackLabel (that.feedbackLabel) 79 { 80 add (loFreqLabel); 81 add (hiFreqLabel); 82 add (modRateLabel); 83 add (modPhaseLabel); 84 add (stepsLabel); 85 add (feedbackLabel); 86 } 87 operator =(const OptionPhaser & that)88 OptionPhaser& operator= (const OptionPhaser& that) 89 { 90 release (&loFreqLabel); 91 release (&hiFreqLabel); 92 release (&modRateLabel); 93 release (&modPhaseLabel); 94 release (&stepsLabel); 95 release (&feedbackLabel); 96 OptionWidget::operator= (that); 97 loFreqLabel = that.loFreqLabel; 98 hiFreqLabel = that.hiFreqLabel; 99 modRateLabel = that.modRateLabel; 100 modPhaseLabel = that.modPhaseLabel; 101 stepsLabel = that.stepsLabel; 102 feedbackLabel = that.feedbackLabel; 103 add (loFreqLabel); 104 add (hiFreqLabel); 105 add (modRateLabel); 106 add (modPhaseLabel); 107 add (stepsLabel); 108 add (feedbackLabel); 109 110 return *this; 111 } 112 clone() const113 virtual Widget* clone () const override {return new OptionPhaser (*this);} 114 applyTheme(BStyles::Theme & theme)115 virtual void applyTheme (BStyles::Theme& theme) override {applyTheme (theme, name_);} 116 applyTheme(BStyles::Theme & theme,const std::string & name)117 virtual void applyTheme (BStyles::Theme& theme, const std::string& name) override 118 { 119 OptionWidget::applyTheme (theme, name); 120 loFreqLabel.applyTheme (theme); 121 hiFreqLabel.applyTheme (theme); 122 modRateLabel.applyTheme (theme); 123 modPhaseLabel.applyTheme (theme); 124 feedbackLabel.applyTheme (theme); 125 } 126 valueChangedCallback(BEvents::Event * event)127 static void valueChangedCallback(BEvents::Event* event) 128 { 129 if (!event) return; 130 BWidgets::Widget* widget = event->getWidget (); 131 if (!widget) return; 132 OptionWidget* p = (OptionWidget*) widget->getParent(); 133 if (!p) return; 134 BOopsGUI* ui = (BOopsGUI*) widget->getMainWindow(); 135 if (!ui) return; 136 137 // options[i + 1] changed ? Send to range 138 for (int i = 0; i < 10; i += 2) 139 { 140 if (widget == p->getWidget(i + 1)) 141 { 142 ((DialRange*)p->getWidget(i))->range.setValue (((BWidgets::ValueWidget*)widget)->getValue()); 143 break; 144 } 145 } 146 147 // Forward all changed options to ui 148 ui->optionChangedCallback (event); 149 } 150 rangeChangedCallback(BEvents::Event * event)151 static void rangeChangedCallback(BEvents::Event* event) 152 { 153 if (!event) return; 154 BWidgets::Widget* widget = event->getWidget (); 155 if (!widget) return; 156 DialRange* p = (DialRange*) widget->getParent(); 157 if (!p) return; 158 OptionWidget* pp = (OptionWidget*) p->getParent(); 159 if (!pp) return; 160 161 // Send changed range to options[i + 1] 162 for (int i = 0; i < 10; i += 2) 163 { 164 if ((p == (DialRange*)pp->getWidget(i)) && (widget == (BWidgets::Widget*)&p->range)) 165 { 166 p->update(); 167 ((BWidgets::ValueWidget*)pp->getWidget(i + 1))->setValue (p->range.getValue ()); 168 } 169 } 170 } 171 172 protected: 173 BWidgets::Label loFreqLabel; 174 BWidgets::Label hiFreqLabel; 175 BWidgets::Label modRateLabel; 176 BWidgets::Label modPhaseLabel; 177 BWidgets::Label stepsLabel; 178 BWidgets::Label feedbackLabel; 179 }; 180 181 #endif /* OPTIONPHASER_HPP_ */ 182