module.cpp (6312B)
1 2 #include "module.hpp" 3 #include "bogaudio.hpp" 4 5 using namespace bogaudio; 6 7 #define SKIN "skin" 8 9 void BGModule::onRemove() { 10 while (_channels >= 1) { 11 removeChannel(_channels - 1); 12 --_channels; 13 } 14 } 15 16 void BGModule::onReset() { 17 _steps = _modulationSteps; 18 reset(); 19 } 20 21 void BGModule::onSampleRateChange() { 22 _modulationSteps = APP->engine->getSampleRate() * (2.5f / 1000.0f); // modulate every ~2.5ms regardless of sample rate. 23 _steps = _modulationSteps; 24 sampleRateChange(); 25 } 26 27 json_t* BGModule::dataToJson() { 28 json_t* root = json_object(); 29 if (_skinnable && _skin != "default") { 30 json_object_set_new(root, SKIN, json_string(_skin.c_str())); 31 } 32 return saveToJson(root); 33 } 34 35 void BGModule::dataFromJson(json_t* root) { 36 if (_skinnable) { 37 json_t* s = json_object_get(root, SKIN); 38 if (s) { 39 setSkin(json_string_value(s)); 40 } 41 else { 42 setSkin(_skin); 43 } 44 } 45 46 loadFromJson(root); 47 } 48 49 void BGModule::process(const ProcessArgs& args) { 50 if (!_initialized) { 51 _initialized = true; 52 onReset(); 53 onSampleRateChange(); 54 } 55 56 bool modulateNow = false; 57 ++_steps; 58 if (_steps >= _modulationSteps) { 59 _steps = 0; 60 modulateNow = true; 61 modulateAlways(); 62 } 63 64 processAlways(args); 65 if (active()) { 66 if (modulateNow) { 67 int channelsBefore = _channels; 68 int channelsNow = std::max(1, channels()); 69 if (channelsBefore != channelsNow) { 70 _channels = channelsNow; 71 _inverseChannels = 1.0f / (float)_channels; 72 channelsChanged(channelsBefore, channelsNow); 73 if (channelsBefore < channelsNow) { 74 while (channelsBefore < channelsNow) { 75 addChannel(channelsBefore); 76 ++channelsBefore; 77 } 78 } 79 else { 80 while (channelsNow < channelsBefore) { 81 removeChannel(channelsBefore - 1); 82 --channelsBefore; 83 } 84 } 85 } 86 87 modulate(); 88 for (int i = 0; i < _channels; ++i) { 89 modulateChannel(i); 90 } 91 } 92 93 processAll(args); 94 for (int i = 0; i < _channels; ++i) { 95 processChannel(args, i); 96 } 97 postProcess(args); 98 } 99 postProcessAlways(args); 100 } 101 102 void BGModule::setSkin(std::string skin) { 103 if (skin == "default" || Skins::skins().validKey(skin)) { 104 _skin = skin; 105 for (auto scl : _skinChangeListeners) { 106 scl->skinChanged(skin); 107 } 108 } 109 } 110 111 void BGModule::addSkinChangeListener(SkinChangeListener* listener) { 112 _skinChangeListeners.push_back(listener); 113 listener->skinChanged(_skin); 114 } 115 116 117 BGModuleWidget::BGModuleWidget() { 118 Skins::skins().registerDefaultSkinChangeListener(this); 119 } 120 121 BGModuleWidget::~BGModuleWidget() { 122 Skins::skins().deregisterDefaultSkinChangeListener(this); 123 } 124 125 void BGModuleWidget::addParam(ParamWidget* param) { 126 ModuleWidget::addParam(param); 127 if (module) { 128 auto l = dynamic_cast<SkinChangeListener*>(param); 129 if (l) { 130 auto m = dynamic_cast<BGModule*>(module); 131 assert(m); 132 m->addSkinChangeListener(l); 133 } 134 } 135 } 136 137 void BGModuleWidget::addInput(PortWidget* input) { 138 ModuleWidget::addInput(input); 139 if (module) { 140 auto l = dynamic_cast<SkinChangeListener*>(input); 141 if (l) { 142 auto m = dynamic_cast<BGModule*>(module); 143 assert(m); 144 m->addSkinChangeListener(l); 145 } 146 } 147 } 148 149 void BGModuleWidget::addOutput(PortWidget* output) { 150 ModuleWidget::addOutput(output); 151 if (module) { 152 auto l = dynamic_cast<SkinChangeListener*>(output); 153 if (l) { 154 auto m = dynamic_cast<BGModule*>(module); 155 assert(m); 156 m->addSkinChangeListener(l); 157 } 158 } 159 } 160 161 void BGModuleWidget::appendContextMenu(Menu* menu) { 162 auto m = dynamic_cast<BGModule*>(module); 163 assert(m); 164 if (m->_skinnable) { 165 Skins* skins = &Skins::skins(); 166 if (skins->available().size() > 0) { 167 menu->addChild(new MenuLabel()); 168 OptionsMenuItem* s = new OptionsMenuItem("Panel"); 169 170 s->addItem(OptionMenuItem("Default", [m]() { return m->_skin == "default"; }, [m]() { m->setSkin("default"); })); 171 for (auto skin : skins->available()) { 172 std::string key = skin.key; 173 s->addItem(OptionMenuItem( 174 skin.display.c_str(), 175 [m, key]() { return m->_skin == key; }, 176 [m, key]() { m->setSkin(key); } 177 )); 178 } 179 180 s->addSpacer(); 181 for (auto skin : skins->available()) { 182 std::string key = skin.key; 183 s->addItem(OptionMenuItem( 184 (std::string("Default to ") + skin.display).c_str(), 185 [key, skins]() { return skins->defaultKey() == key; }, 186 [key, skins]() { skins->setDefaultSkin(key); } 187 )); 188 } 189 190 OptionsMenuItem::addToMenu(s, menu); 191 } 192 } 193 194 contextMenu(menu); 195 } 196 197 void BGModuleWidget::skinChanged(const std::string& skin) { 198 updatePanel(); 199 } 200 201 void BGModuleWidget::defaultSkinChanged(const std::string& skin) { 202 if (module) { 203 auto m = dynamic_cast<BGModule*>(module); 204 assert(m); 205 if (m->_skin == "default") { 206 m->setSkin("default"); 207 } 208 } 209 else { 210 updatePanel(); 211 } 212 } 213 214 void BGModuleWidget::setPanel(Vec size, std::string slug, bool skinnable) { 215 _size = size; 216 _slug = slug; 217 _skinnable = skinnable; 218 if (module && _skinnable) { 219 auto m = dynamic_cast<BGModule*>(module); 220 assert(m); 221 m->addSkinChangeListener(this); 222 } 223 updatePanel(); 224 } 225 226 void BGModuleWidget::updatePanel() { 227 const Skins& skins = Skins::skins(); 228 std::string skin = skins.defaultKey(); 229 if (!_skinnable) { 230 skin = "light"; 231 } 232 else if (module) { 233 auto m = dynamic_cast<BGModule*>(module); 234 assert(m); 235 skin = m->_skin; 236 if (skin == "default") { 237 skin = skins.defaultKey(); 238 } 239 } 240 241 if (_loadedSkin == skin) { 242 return; 243 } 244 _loadedSkin = skin; 245 if (_panel) { 246 _panel->requestDelete(); 247 _panel = NULL; 248 } 249 250 std::string svg = "res/" + _slug; 251 if (skin != "light") { 252 svg += "-"; 253 svg += skin; 254 } 255 svg += ".svg"; 256 _panel = new SvgPanel(); 257 _panel->box.size = _size; 258 addChildBottom(_panel); 259 _panel->setBackground(APP->window->loadSvg(asset::plugin(pluginInstance, svg))); 260 } 261 262 void BGModuleWidget::createScrews() { 263 int hp = box.size.x / RACK_GRID_WIDTH; 264 BGModule* m = NULL; 265 if (_skinnable && module) { 266 m = dynamic_cast<BGModule*>(module); 267 assert(m); 268 } 269 auto screw = [m, this](Vec v) { 270 auto w = createWidget<Screw>(v); 271 if (m) { 272 m->addSkinChangeListener(w); 273 } 274 this->addChild(w); 275 }; 276 277 if (hp > 13) { 278 screw(Vec(15, 0)); 279 screw(Vec(box.size.x - 30, 0)); 280 screw(Vec(15, 365)); 281 screw(Vec(box.size.x - 30, 365)); 282 } 283 else if (hp > 8) { 284 screw(Vec(0, 0)); 285 screw(Vec(box.size.x - 15, 0)); 286 screw(Vec(0, 365)); 287 screw(Vec(box.size.x - 15, 365)); 288 } 289 else { 290 screw(Vec(0, 0)); 291 screw(Vec(box.size.x - 15, 365)); 292 } 293 }