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: 10 сент. 2019 г. 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/plugins/para_equalizer_ui.h> 23 #include <core/files/RoomEQWizard.h> 24 25 #include <metadata/plugins.h> 26 27 namespace lsp 28 { 29 static const char *fmt_strings[] = 30 { 31 "%s_%d", 32 NULL 33 }; 34 35 static const char *fmt_strings_lr[] = 36 { 37 "%sl_%d", 38 "%sr_%d", 39 NULL 40 }; 41 42 static const char *fmt_strings_ms[] = 43 { 44 "%sm_%d", 45 "%ss_%d", 46 NULL 47 }; 48 para_equalizer_ui(const plugin_metadata_t * mdata,void * root_widget)49 para_equalizer_ui::para_equalizer_ui(const plugin_metadata_t *mdata, void *root_widget): 50 plugin_ui(mdata, root_widget) 51 { 52 pRewImport = NULL; 53 pRewPath = NULL; 54 fmtStrings = fmt_strings; 55 56 if (::strstr(mdata->lv2_uid, "_lr") != NULL) 57 fmtStrings = fmt_strings_lr; 58 else if (::strstr(mdata->lv2_uid, "_ms") != NULL) 59 fmtStrings = fmt_strings_ms; 60 } 61 ~para_equalizer_ui()62 para_equalizer_ui::~para_equalizer_ui() 63 { 64 pRewImport = NULL; // Will be automatically destroyed from list of widgets 65 } 66 slot_start_import_rew_file(LSPWidget * sender,void * ptr,void * data)67 status_t para_equalizer_ui::slot_start_import_rew_file(LSPWidget *sender, void *ptr, void *data) 68 { 69 para_equalizer_ui *_this = static_cast<para_equalizer_ui *>(ptr); 70 71 LSPFileDialog *dlg = _this->pRewImport; 72 if (dlg == NULL) 73 { 74 dlg = new LSPFileDialog(&_this->sDisplay); 75 _this->vWidgets.add(dlg); 76 _this->pRewImport = dlg; 77 78 dlg->init(); 79 dlg->set_mode(FDM_OPEN_FILE); 80 dlg->title()->set("titles.import_rew_filter_settings"); 81 dlg->action_title()->set("actions.import"); 82 83 LSPFileFilter *f = dlg->filter(); 84 { 85 LSPFileFilterItem ffi; 86 87 ffi.pattern()->set("*.req|*.txt"); 88 ffi.title()->set("files.roomeqwizard.all"); 89 ffi.set_extension(""); 90 f->add(&ffi); 91 92 ffi.pattern()->set("*.req"); 93 ffi.title()->set("files.roomeqwizard.req"); 94 ffi.set_extension(""); 95 f->add(&ffi); 96 97 ffi.pattern()->set("*.txt"); 98 ffi.title()->set("files.roomeqwizard.txt"); 99 ffi.set_extension(""); 100 f->add(&ffi); 101 102 ffi.pattern()->set("*"); 103 ffi.title()->set("files.all"); 104 ffi.set_extension(""); 105 f->add(&ffi); 106 } 107 dlg->bind_action(slot_call_import_rew_file, ptr); 108 dlg->slots()->bind(LSPSLOT_SHOW, slot_fetch_rew_path, _this); 109 dlg->slots()->bind(LSPSLOT_HIDE, slot_commit_rew_path, _this); 110 } 111 112 return dlg->show(_this->pRoot); 113 } 114 slot_call_import_rew_file(LSPWidget * sender,void * ptr,void * data)115 status_t para_equalizer_ui::slot_call_import_rew_file(LSPWidget *sender, void *ptr, void *data) 116 { 117 para_equalizer_ui *_this = static_cast<para_equalizer_ui *>(ptr); 118 LSPString path; 119 status_t res = _this->pRewImport->get_selected_file(&path); 120 if (res == STATUS_OK) 121 res = _this->import_rew_file(&path); 122 return STATUS_OK; 123 } 124 slot_fetch_rew_path(LSPWidget * sender,void * ptr,void * data)125 status_t para_equalizer_ui::slot_fetch_rew_path(LSPWidget *sender, void *ptr, void *data) 126 { 127 para_equalizer_ui *_this = static_cast<para_equalizer_ui *>(ptr); 128 if ((_this == NULL) || (_this->pRewPath == NULL)) 129 return STATUS_BAD_STATE; 130 131 LSPFileDialog *dlg = widget_cast<LSPFileDialog>(sender); 132 if (dlg == NULL) 133 return STATUS_OK; 134 135 dlg->set_path(_this->pRewPath->get_buffer<char>()); 136 return STATUS_OK; 137 } 138 slot_commit_rew_path(LSPWidget * sender,void * ptr,void * data)139 status_t para_equalizer_ui::slot_commit_rew_path(LSPWidget *sender, void *ptr, void *data) 140 { 141 para_equalizer_ui *_this = static_cast<para_equalizer_ui *>(ptr); 142 if ((_this == NULL) || (_this->pRewPath == NULL)) 143 return STATUS_BAD_STATE; 144 145 LSPFileDialog *dlg = widget_cast<LSPFileDialog>(sender); 146 if (dlg == NULL) 147 return STATUS_OK; 148 149 const char *path = dlg->path(); 150 if (path != NULL) 151 { 152 _this->pRewPath->write(path, ::strlen(path)); 153 _this->pRewPath->notify_all(); 154 } 155 156 return STATUS_OK; 157 } 158 build()159 status_t para_equalizer_ui::build() 160 { 161 status_t res = plugin_ui::build(); 162 if (res != STATUS_OK) 163 return res; 164 165 // Find REW port 166 pRewPath = port(UI_CONFIG_PORT_PREFIX UI_DLG_REW_PATH_ID); 167 168 // Add subwidgets 169 LSPMenu *menu = widget_cast<LSPMenu>(resolve(WUID_IMPORT_MENU)); 170 if (menu != NULL) 171 { 172 LSPMenuItem *child = new LSPMenuItem(&sDisplay); 173 vWidgets.add(child); 174 child->init(); 175 child->text()->set("actions.import_rew_filter_file"); 176 child->slots()->bind(LSPSLOT_SUBMIT, slot_start_import_rew_file, this); 177 menu->add(child); 178 } 179 180 return STATUS_OK; 181 } 182 set_port_value(const char * base,size_t id,float value)183 void para_equalizer_ui::set_port_value(const char *base, size_t id, float value) 184 { 185 char port_id[32]; 186 187 for (const char **fmt = fmtStrings; *fmt != NULL; ++fmt) 188 { 189 ::snprintf(port_id, sizeof(port_id)/sizeof(char), *fmt, base, int(id)); 190 CtlPort *p = port(port_id); 191 if (p != NULL) 192 { 193 p->set_value(value); 194 p->notify_all(); 195 } 196 } 197 } 198 set_filter_mode(size_t id,size_t value)199 void para_equalizer_ui::set_filter_mode(size_t id, size_t value) 200 { 201 set_port_value("fm", id, value); 202 } 203 set_filter_type(size_t id,size_t value)204 void para_equalizer_ui::set_filter_type(size_t id, size_t value) 205 { 206 set_port_value("ft", id, value); 207 } 208 set_filter_frequency(size_t id,double value)209 void para_equalizer_ui::set_filter_frequency(size_t id, double value) 210 { 211 set_port_value("f", id, value); 212 } 213 set_filter_quality(size_t id,double value)214 void para_equalizer_ui::set_filter_quality(size_t id, double value) 215 { 216 set_port_value("q", id, value); 217 } 218 set_filter_gain(size_t id,double value)219 void para_equalizer_ui::set_filter_gain(size_t id, double value) 220 { 221 double gain = expf(0.05 * value * M_LN10); 222 set_port_value("g", id, gain); 223 } 224 set_filter_slope(size_t id,size_t slope)225 void para_equalizer_ui::set_filter_slope(size_t id, size_t slope) 226 { 227 set_port_value("s", id, slope - 1); 228 } 229 set_filter_enabled(size_t id,bool enabled)230 void para_equalizer_ui::set_filter_enabled(size_t id, bool enabled) 231 { 232 set_port_value("xm", id, (enabled) ? 0.0f : 1.0f); 233 } 234 set_filter_solo(size_t id,bool solo)235 void para_equalizer_ui::set_filter_solo(size_t id, bool solo) 236 { 237 set_port_value("xs", id, (solo) ? 1.0f : 0.0f); 238 } 239 import_rew_file(const LSPString * path)240 status_t para_equalizer_ui::import_rew_file(const LSPString *path) 241 { 242 // Load settings 243 room_ew::config_t *cfg = NULL; 244 status_t res = room_ew::load(path, &cfg); 245 if (res != STATUS_OK) 246 return res; 247 248 // Apply settings 249 size_t fid = 0; 250 for (size_t i=0; i<cfg->nFilters; ++i) 251 { 252 const room_ew::filter_t *f = &cfg->vFilters[i]; 253 254 // Perform parameter translation 255 size_t mode = para_equalizer_base_metadata::EFM_APO_DR; 256 ssize_t type = -1; 257 double gain = 0.0; 258 double quality = M_SQRT1_2; 259 double freq = f->fc; 260 261 switch (f->filterType) 262 { 263 case room_ew::PK: 264 type = para_equalizer_base_metadata::EQF_BELL; 265 gain = f->gain; 266 quality = f->Q; 267 break; 268 case room_ew::LS: 269 type = para_equalizer_base_metadata::EQF_LOSHELF; 270 gain = f->gain; 271 quality = 2.0/3.0; 272 break; 273 case room_ew::HS: 274 type = para_equalizer_base_metadata::EQF_HISHELF; 275 gain = f->gain; 276 quality = 2.0/3.0; 277 break; 278 case room_ew::LP: 279 type = para_equalizer_base_metadata::EQF_LOPASS; 280 break; 281 case room_ew::HP: 282 type = para_equalizer_base_metadata::EQF_HIPASS; 283 break; 284 case room_ew::LPQ: 285 type = para_equalizer_base_metadata::EQF_LOPASS; 286 quality = f->Q; 287 break; 288 case room_ew::HPQ: 289 type = para_equalizer_base_metadata::EQF_HIPASS; 290 quality = f->Q; 291 break; 292 case room_ew::LS6: 293 type = para_equalizer_base_metadata::EQF_LOSHELF; 294 gain = f->gain; 295 quality = M_SQRT2 / 3.0; 296 freq = freq * 2.0 / 3.0; 297 break; 298 case room_ew::HS6: 299 type = para_equalizer_base_metadata::EQF_HISHELF; 300 gain = f->gain; 301 quality = M_SQRT2 / 3.0; 302 freq = freq / M_SQRT1_2; 303 break; 304 case room_ew::LS12: 305 type = para_equalizer_base_metadata::EQF_LOSHELF; 306 gain = f->gain; 307 freq = freq * 3.0 / 2.0; 308 break; 309 case room_ew::HS12: 310 type = para_equalizer_base_metadata::EQF_HISHELF; 311 gain = f->gain; 312 freq = freq * M_SQRT1_2; 313 break; 314 case room_ew::NO: 315 type = para_equalizer_base_metadata::EQF_NOTCH; 316 quality = 100.0 / 3.0; 317 break; 318 case room_ew::AP: 319 type = para_equalizer_base_metadata::EQF_ALLPASS; 320 quality = 0.0; 321 break; 322 default: // Skip other filter types 323 break; 324 } 325 326 if (type < 0) 327 continue; 328 329 // Set-up parameters 330 set_filter_mode(fid, mode); 331 set_filter_type(fid, type); 332 set_filter_slope(fid, 1); 333 set_filter_frequency(fid, freq); 334 set_filter_gain(fid, gain); 335 set_filter_quality(fid, quality); 336 set_filter_enabled(fid, f->enabled); 337 set_filter_solo(fid, false); 338 339 // Increment imported filter number 340 ++fid; 341 } 342 343 // Reset state of all other filters 344 for (; fid < 32; ++fid) 345 { 346 set_filter_type(fid, para_equalizer_base_metadata::EQF_OFF); 347 set_filter_slope(fid, 1); 348 set_filter_gain(fid, 1.0f); 349 set_filter_quality(fid, 0.0f); 350 set_filter_enabled(fid, true); 351 set_filter_solo(fid, false); 352 } 353 354 return STATUS_OK; 355 } 356 357 } /* namespace lsp */ 358