1 /* 2 * Copyright (C) 2020 Linux Studio Plugins Project <https://lsp-plug.in/> 3 * (C) 2020 Vladimir Sadovnikov <sadko4u@gmail.com> 4 * 5 * This file is part of lsp-plugins 6 * Created on: 11 июл. 2017 г. 7 * 8 * lsp-plugins is free software: you can redistribute it and/or modify 9 * it under the terms of the GNU Lesser General Public License as published by 10 * the Free Software Foundation, either version 3 of the License, or 11 * any later version. 12 * 13 * lsp-plugins is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU Lesser General Public License for more details. 17 * 18 * You should have received a copy of the GNU Lesser General Public License 19 * along with lsp-plugins. If not, see <https://www.gnu.org/licenses/>. 20 */ 21 22 #include <ui/ctl/ctl.h> 23 24 namespace lsp 25 { 26 namespace ctl 27 { 28 const ctl_class_t CtlKnob::metadata = { "CtlKnob", &CtlWidget::metadata }; 29 CtlKnob(CtlRegistry * src,LSPKnob * widget)30 CtlKnob::CtlKnob(CtlRegistry *src, LSPKnob *widget): CtlWidget(src, widget) 31 { 32 pClass = &metadata; 33 pPort = NULL; 34 bLog = false; 35 bLogSet = false; 36 bCyclingSet = false; 37 fDefaultValue = 0.0f; 38 bBalanceSet = false; 39 fBalance = 0.0f; 40 } 41 ~CtlKnob()42 CtlKnob::~CtlKnob() 43 { 44 } 45 slot_change(LSPWidget * sender,void * ptr,void * data)46 status_t CtlKnob::slot_change(LSPWidget *sender, void *ptr, void *data) 47 { 48 CtlKnob *_this = static_cast<CtlKnob *>(ptr); 49 if (_this != NULL) 50 _this->submit_value(); 51 return STATUS_OK; 52 } 53 slot_dbl_click(LSPWidget * sender,void * ptr,void * data)54 status_t CtlKnob::slot_dbl_click(LSPWidget *sender, void *ptr, void *data) 55 { 56 CtlKnob *_this = static_cast<CtlKnob *>(ptr); 57 if (_this != NULL) 58 _this->set_default_value(); 59 return STATUS_OK; 60 } 61 submit_value()62 void CtlKnob::submit_value() 63 { 64 if (pPort == NULL) 65 return; 66 if (pWidget == NULL) 67 return; 68 69 LSPKnob *knob = widget_cast<LSPKnob>(pWidget); 70 float value = knob->value(); 71 72 const port_t *p = pPort->metadata(); 73 if (p == NULL) 74 { 75 pPort->set_value(value); 76 pPort->notify_all(); 77 return; 78 } 79 80 if (is_gain_unit(p->unit)) // Gain 81 { 82 double base = (p->unit == U_GAIN_AMP) ? M_LN10 * 0.05 : M_LN10 * 0.1; 83 value = exp(value * base); 84 float min = (p->flags & F_LOWER) ? p->min : 0.0f; 85 if ((min <= 0.0f) && (value < GAIN_AMP_M_80_DB)) 86 value = 0.0f; 87 } 88 else if (is_discrete_unit(p->unit)) // Integer type 89 { 90 value = truncf(value); 91 } 92 else if (bLog) // Float and other values, logarithmic 93 { 94 value = exp(value); 95 float min = (p->flags & F_LOWER) ? p->min : 0.0f; 96 if ((min <= 0.0f) && (value < log(GAIN_AMP_M_80_DB))) 97 value = 0.0f; 98 } 99 100 pPort->set_value(value); 101 pPort->notify_all(); 102 } 103 set_default_value()104 void CtlKnob::set_default_value() 105 { 106 LSPKnob *knob = widget_cast<LSPKnob>(pWidget); 107 if (knob == NULL) 108 return; 109 110 const port_t *p = pPort->metadata(); 111 float dfl = (p != NULL) ? pPort->get_default_value() : fDefaultValue; 112 float value = dfl; 113 114 if (p != NULL) 115 { 116 if (is_gain_unit(p->unit)) // Decibels 117 { 118 double base = (p->unit == U_GAIN_AMP) ? 20.0 / M_LN10 : 10.0 / M_LN10; 119 120 if (value < GAIN_AMP_M_120_DB) 121 value = GAIN_AMP_M_120_DB; 122 123 value = base * log(value); 124 } 125 else if (bLog) 126 { 127 if (value < GAIN_AMP_M_120_DB) 128 value = GAIN_AMP_M_120_DB; 129 value = log(value); 130 } 131 } 132 133 knob->set_value(value); 134 pPort->set_value(dfl); 135 pPort->notify_all(); 136 } 137 commit_value(float value)138 void CtlKnob::commit_value(float value) 139 { 140 if (pWidget == NULL) 141 return; 142 143 LSPKnob *knob = widget_cast<LSPKnob>(pWidget); 144 if (knob == NULL) 145 return; 146 147 const port_t *p = pPort->metadata(); 148 if (p == NULL) 149 return; 150 151 if (is_gain_unit(p->unit)) // Decibels 152 { 153 double base = (p->unit == U_GAIN_AMP) ? 20.0 / M_LN10 : 10.0 / M_LN10; 154 155 if (value < GAIN_AMP_M_120_DB) 156 value = GAIN_AMP_M_120_DB; 157 158 knob->set_value(base * log(value)); 159 } 160 else if (is_discrete_unit(p->unit)) // Integer type 161 knob->set_value(truncf(value)); 162 else if (bLog) 163 { 164 if (value < GAIN_AMP_M_120_DB) 165 value = GAIN_AMP_M_120_DB; 166 knob->set_value(log(value)); 167 } 168 else 169 knob->set_value(value); 170 } 171 init()172 void CtlKnob::init() 173 { 174 CtlWidget::init(); 175 176 LSPKnob *knob = widget_cast<LSPKnob>(pWidget); 177 if (knob == NULL) 178 return; 179 180 // Initialize color controllers 181 sColor.init_hsl(pRegistry, knob, knob->color(), A_COLOR, A_HUE_ID, A_SAT_ID, A_LIGHT_ID); 182 sScaleColor.init_hsl(pRegistry, knob, knob->scale_color(), A_SCALE_COLOR, A_SCALE_HUE_ID, A_SCALE_SAT_ID, A_SCALE_LIGHT_ID); 183 sScaleColor.map_static_hsl(A_SCALE_HUE, -1, -1); 184 185 // Bind slots 186 knob->slots()->bind(LSPSLOT_CHANGE, slot_change, this); 187 knob->slots()->bind(LSPSLOT_MOUSE_DBL_CLICK, slot_dbl_click, this); 188 } 189 set(widget_attribute_t att,const char * value)190 void CtlKnob::set(widget_attribute_t att, const char *value) 191 { 192 LSPKnob *knob = widget_cast<LSPKnob>(pWidget); 193 194 switch (att) 195 { 196 case A_ID: 197 BIND_PORT(pRegistry, pPort, value); 198 break; 199 case A_SIZE: 200 if (knob != NULL) 201 PARSE_INT(value, knob->set_size(__)); 202 break; 203 case A_VALUE: 204 if (knob != NULL) 205 PARSE_FLOAT(value, knob->set_value(__)); 206 break; 207 case A_DEFAULT: 208 if (knob != NULL) 209 PARSE_FLOAT(value, fDefaultValue = __); 210 break; 211 case A_MIN: 212 if (knob != NULL) 213 PARSE_FLOAT(value, knob->set_min_value(__)); 214 break; 215 case A_MAX: 216 if (knob != NULL) 217 PARSE_FLOAT(value, knob->set_max_value(__)); 218 break; 219 case A_LOGARITHMIC: 220 PARSE_BOOL(value, bLog = __); 221 bLogSet = true; 222 break; 223 case A_STEP: 224 if (knob != NULL) 225 PARSE_FLOAT(value, knob->set_step(__)); 226 break; 227 case A_TINY_STEP: 228 if (knob != NULL) 229 PARSE_FLOAT(value, knob->set_tiny_step(__)); 230 break; 231 case A_BALANCE: 232 bBalanceSet = true; 233 if (knob != NULL) 234 PARSE_FLOAT(value, knob->set_balance(fBalance = __)); 235 break; 236 case A_CYCLE: 237 bCyclingSet = true; 238 if (knob != NULL) 239 PARSE_BOOL(value, knob->set_cycling(__); ); 240 break; 241 default: 242 { 243 sColor.set(att, value); 244 sScaleColor.set(att, value); 245 CtlWidget::set(att, value); 246 break; 247 } 248 } 249 } 250 notify(CtlPort * port)251 void CtlKnob::notify(CtlPort *port) 252 { 253 CtlWidget::notify(port); 254 255 if (port == pPort) 256 commit_value(pPort->get_value()); 257 } 258 limit(float v,float min,float max)259 static inline float limit(float v, float min, float max) 260 { 261 if (min < max) 262 { 263 if (v < min) 264 return min; 265 return (v > max) ? max : v; 266 } 267 else 268 { 269 if (v < max) 270 return max; 271 return (v > min) ? min : v; 272 } 273 } 274 end()275 void CtlKnob::end() 276 { 277 // Call parent controller 278 CtlWidget::end(); 279 280 // Ensure that widget is set 281 if (pWidget == NULL) 282 return; 283 LSPKnob *knob = widget_cast<LSPKnob>(pWidget); 284 285 // Ensure that port is set 286 const port_t *p = (pPort != NULL) ? pPort->metadata() : NULL; 287 if (p == NULL) 288 { 289 knob->set_value(fDefaultValue); 290 return; 291 } 292 293 // Update logarithmic flag 294 if (!bLogSet) 295 bLog = (p->flags & F_LOG); 296 297 if (is_gain_unit(p->unit)) // Gain 298 { 299 double base = (p->unit == U_GAIN_AMP) ? 20.0 / M_LN10 : 10.0 / M_LN10; 300 301 float min = (p->flags & F_LOWER) ? p->min : 0.0f; 302 float max = (p->flags & F_UPPER) ? p->max : GAIN_AMP_P_12_DB; 303 float dfl = (bBalanceSet) ? fBalance : min; 304 305 double step = base * log((p->flags & F_STEP) ? p->step + 1.0f : 1.01f) * 0.1f; 306 double thresh = ((p->flags & F_EXT) ? GAIN_AMP_M_140_DB : GAIN_AMP_M_80_DB); 307 308 double db_min = (fabs(min) < thresh) ? (base * log(thresh) - step) : (base * log(min)); 309 double db_max = (fabs(max) < thresh) ? (base * log(thresh) - step) : (base * log(max)); 310 double db_dfl = (fabs(max) < thresh) ? (base * log(thresh) - step) : (base * log(dfl)); 311 float balance = limit(db_dfl, db_min, db_max); 312 313 knob->set_min_value(db_min); 314 knob->set_max_value(db_max); 315 knob->set_balance(balance); 316 knob->set_step(step * 10.0f); 317 knob->set_tiny_step(step); 318 fDefaultValue = base * log(p->start); 319 } 320 else if (is_discrete_unit(p->unit)) // Integer type 321 { 322 float min = (p->flags & F_LOWER) ? p->min : 0.0f; 323 float max = (p->unit == U_ENUM) ? min + list_size(p->items) - 1.0f : 324 (p->flags & F_UPPER) ? p->max : 1.0f; 325 float dfl = (bBalanceSet) ? fBalance : p->min; 326 float balance = limit(dfl, min, max); 327 ssize_t step = (p->flags & F_STEP) ? p->step : 1; 328 step = (step == 0) ? 1 : step; 329 330 knob->set_min_value(min); 331 knob->set_max_value(max); 332 knob->set_balance(balance); 333 knob->set_step(step); 334 knob->set_tiny_step(step); 335 fDefaultValue = p->start; 336 if (!bCyclingSet) 337 knob->set_cycling(p->flags & F_CYCLIC); 338 } 339 else if (bLog) // Float and other values, logarithmic 340 { 341 float min = (p->flags & F_LOWER) ? p->min : 0.0f; 342 float max = (p->flags & F_UPPER) ? p->max : GAIN_AMP_P_12_DB; 343 float dfl = (bBalanceSet) ? fBalance : min; 344 345 double step = log((p->flags & F_STEP) ? p->step + 1.0f : 1.01f); 346 double l_min = (fabs(min) < GAIN_AMP_M_80_DB) ? log(GAIN_AMP_M_80_DB) - step : log(min); 347 double l_max = (fabs(max) < GAIN_AMP_M_80_DB) ? log(GAIN_AMP_M_80_DB) - step : log(max); 348 double l_dfl = (fabs(dfl) < GAIN_AMP_M_80_DB) ? log(GAIN_AMP_M_80_DB) - step : log(dfl); 349 float balance = limit(l_dfl, l_min, l_max); 350 351 knob->set_min_value(l_min); 352 knob->set_max_value(l_max); 353 knob->set_balance(balance); 354 knob->set_step(step * 10.0f); 355 knob->set_tiny_step(step); 356 fDefaultValue = log(p->start); 357 } 358 else // Float and other values, non-logarithmic 359 { 360 float min = (p->flags & F_LOWER) ? p->min : 0.0f; 361 float max = (p->flags & F_UPPER) ? p->max : 1.0f; 362 float dfl = (bBalanceSet) ? fBalance : min; 363 float balance = limit(dfl, min, max); 364 365 knob->set_min_value(min); 366 knob->set_max_value(max); 367 knob->set_balance(balance); 368 knob->set_tiny_step((p->flags & F_STEP) ? p->step : (max - min) * 0.01f); 369 knob->set_step(knob->tiny_step() * 10.0f); 370 fDefaultValue = p->start; 371 if (!bCyclingSet) 372 knob->set_cycling(p->flags & F_CYCLIC); 373 } 374 375 // Set default value to the knob 376 knob->set_value(fDefaultValue); 377 } 378 379 } /* namespace ctl */ 380 } /* namespace lsp */ 381