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: 27 июл. 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 CtlDot::metadata = { "CtlDot", &CtlWidget::metadata }; 29 CtlDot(CtlRegistry * src,LSPDot * dot)30 CtlDot::CtlDot(CtlRegistry *src, LSPDot *dot): CtlWidget(src, dot) 31 { 32 pClass = &metadata; 33 pTop = NULL; 34 pLeft = NULL; 35 pScroll = NULL; 36 nFlags = 0; 37 fTop = 0.0f; 38 fLeft = 0.0f; 39 bEditable = false; 40 } 41 ~CtlDot()42 CtlDot::~CtlDot() 43 { 44 } 45 init()46 void CtlDot::init() 47 { 48 CtlWidget::init(); 49 if (pWidget == NULL) 50 return; 51 52 LSPDot *dot = static_cast<LSPDot *>(pWidget); 53 54 // Initialize color controllers 55 sColor.init_hsl(pRegistry, dot, dot->color(), A_COLOR, A_HUE_ID, A_SAT_ID, A_LIGHT_ID); 56 57 // Bind slots 58 dot->slots()->bind(LSPSLOT_CHANGE, slot_change, this); 59 } 60 slot_change(LSPWidget * sender,void * ptr,void * data)61 status_t CtlDot::slot_change(LSPWidget *sender, void *ptr, void *data) 62 { 63 CtlDot *_this = static_cast<CtlDot *>(ptr); 64 if (_this != NULL) 65 _this->submit_values(); 66 return STATUS_OK; 67 } 68 submit_values()69 void CtlDot::submit_values() 70 { 71 LSPDot *dot = widget_cast<LSPDot>(pWidget); 72 if (dot == NULL) 73 return; 74 75 if (dot->x_editable()) 76 submit_value(pLeft, dot->x_value()); 77 if (dot->y_editable()) 78 submit_value(pTop, dot->y_value()); 79 if (dot->z_editable()) 80 { 81 const port_t *p = pScroll->metadata(); 82 float value = dot->z_value(); 83 84 if ((p != NULL) && (is_log_rule(p))) 85 { 86 float min = fabs(p->min); 87 88 min = (min < GAIN_AMP_M_120_DB) ? logf(GAIN_AMP_M_80_DB) : logf(min); 89 value = (value < min) ? p->min : expf(value); 90 91 } 92 93 submit_value(pScroll, value); 94 } 95 } 96 submit_value(CtlPort * port,float value)97 void CtlDot::submit_value(CtlPort *port, float value) 98 { 99 if (port == NULL) 100 return; 101 if (value == port->get_value()) 102 return; 103 104 port->set_value(value); 105 port->notify_all(); 106 } 107 set(widget_attribute_t att,const char * value)108 void CtlDot::set(widget_attribute_t att, const char *value) 109 { 110 LSPDot *dot = widget_cast<LSPDot>(pWidget); 111 112 switch (att) 113 { 114 case A_VPOS: 115 PARSE_FLOAT(value, fTop = __); 116 break; 117 case A_HPOS: 118 PARSE_FLOAT(value, fLeft = __); 119 break; 120 case A_SIZE: 121 if (dot != NULL) 122 PARSE_INT(value, dot->set_size(__)); 123 break; 124 case A_BORDER: 125 if (dot != NULL) 126 PARSE_INT(value, dot->set_border(__)); 127 break; 128 case A_PADDING: 129 if (dot != NULL) 130 PARSE_INT(value, dot->set_padding(__)); 131 break; 132 133 case A_BASIS: 134 if (dot != NULL) 135 PARSE_INT(value, dot->set_basis_id(__)); 136 break; 137 case A_PARALLEL: 138 if (dot != NULL) 139 PARSE_INT(value, dot->set_parallel_id(__)); 140 break; 141 case A_CENTER: 142 if (dot != NULL) 143 PARSE_INT(value, dot->set_center_id(__)); 144 break; 145 146 case A_SCROLL_ID: 147 BIND_PORT(pRegistry, pScroll, value); 148 break; 149 case A_VPOS_ID: 150 BIND_PORT(pRegistry, pTop, value); 151 break; 152 case A_HPOS_ID: 153 BIND_PORT(pRegistry, pLeft, value); 154 break; 155 156 case A_EDITABLE: 157 PARSE_BOOL(value, bEditable = __); 158 break; 159 case A_LED: 160 if (dot != NULL) 161 PARSE_BOOL(value, dot->set_highlight(__)); 162 break; 163 164 default: 165 { 166 bool set = sColor.set(att, value); 167 if (!set) 168 CtlWidget::set(att, value); 169 break; 170 } 171 } 172 } 173 end()174 void CtlDot::end() 175 { 176 CtlWidget::end(); 177 178 // Get widget 179 LSPDot *dot = widget_cast<LSPDot>(pWidget); 180 if (dot == NULL) 181 return; 182 183 // Tune parameters 184 const port_t *p = NULL; 185 186 if (pLeft != NULL) 187 { 188 dot->set_x_editable(bEditable); 189 fLeft = pLeft->get_value(); 190 191 p = pLeft->metadata(); 192 if (p != NULL) 193 { 194 if (p->flags & F_LOWER) 195 dot->set_x_minimum(p->min); 196 if (p->flags & F_UPPER) 197 dot->set_x_maximum(p->max); 198 if (p->flags & F_STEP) 199 dot->set_x_step(p->step); 200 } 201 } 202 else 203 { 204 dot->set_x_minimum(fLeft); 205 dot->set_x_maximum(fLeft); 206 dot->set_x_value(fLeft); 207 } 208 209 if (pTop != NULL) 210 { 211 dot->set_y_editable(bEditable); 212 fTop = pTop->get_value(); 213 214 p = pTop->metadata(); 215 if (p != NULL) 216 { 217 if (p->flags & F_LOWER) 218 dot->set_y_minimum(p->min); 219 if (p->flags & F_UPPER) 220 dot->set_y_maximum(p->max); 221 if (p->flags & F_STEP) 222 dot->set_y_step(p->step); 223 } 224 } 225 else 226 { 227 dot->set_y_minimum(fTop); 228 dot->set_y_maximum(fTop); 229 dot->set_y_value(fTop); 230 } 231 232 if (pScroll != NULL) 233 { 234 dot->set_z_editable(bEditable); 235 p = pScroll->metadata(); 236 237 if (p != NULL) 238 { 239 float min, max; 240 if (is_log_rule(p)) 241 { 242 min = fabs(p->min); 243 max = fabs(p->max); 244 245 min = (min < GAIN_AMP_M_80_DB) ? logf(GAIN_AMP_M_80_DB) - p->step : logf(min); 246 max = (max < GAIN_AMP_M_80_DB) ? logf(GAIN_AMP_M_80_DB) - p->step : logf(max); 247 } 248 else 249 { 250 min = p->min; 251 max = p->max; 252 } 253 254 if (p->flags & F_LOWER) 255 dot->set_z_minimum(min); 256 if (p->flags & F_UPPER) 257 dot->set_z_maximum(max); 258 if (p->flags & F_STEP) 259 { 260 dot->set_z_tiny_step(p->step); 261 dot->set_z_step(p->step * 10.0f); 262 dot->set_z_big_step(p->step * 100.0f); 263 } 264 } 265 } 266 267 // Update mouse pointer for dot 268 if (dot->x_editable() && dot->y_editable()) 269 dot->set_cursor(MP_DRAG); 270 else if (dot->x_editable()) 271 dot->set_cursor(MP_HSIZE); 272 else if (dot->y_editable()) 273 dot->set_cursor(MP_VSIZE); 274 else 275 dot->set_cursor(MP_DEFAULT); 276 277 notify(pLeft); 278 notify(pTop); 279 notify(pScroll); 280 } 281 notify(CtlPort * port)282 void CtlDot::notify(CtlPort *port) 283 { 284 CtlWidget::notify(port); 285 286 LSPDot *dot = widget_cast<LSPDot>(pWidget); 287 if (dot == NULL) 288 return; 289 290 if ((pLeft != NULL) && (port == pLeft)) 291 { 292 fLeft = pLeft->get_value(); 293 dot->set_x_value(fLeft); 294 } 295 if ((pTop != NULL) && (port == pTop)) 296 { 297 fTop = pTop->get_value(); 298 dot->set_y_value(fTop); 299 } 300 if ((pScroll != NULL) && (port == pScroll)) 301 { 302 const port_t *p = pScroll->metadata(); 303 float min; 304 float value = pScroll->get_value(); 305 306 if (is_log_rule(p)) 307 { 308 min = fabs(p->min); 309 // max = fabs(p->max); 310 311 min = (min < GAIN_AMP_M_80_DB) ? logf(GAIN_AMP_M_80_DB) - p->step : logf(min); 312 // max = (max < GAIN_AMP_M_80_DB) ? logf(GAIN_AMP_M_80_DB) - p->step : logf(max); 313 314 value = (value < GAIN_AMP_M_80_DB) ? min : logf(value); 315 } 316 317 dot->set_z_value(value); 318 } 319 } 320 } /* namespace ctl */ 321 } /* namespace lsp */ 322