1 /*
2 * Copyright (C) 2009, 2010 Hermann Meyer, James Warden, Andreas Degert
3 * Copyright (C) 2011 Pete Shorthose
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 * ---------------------------------------------------------------------------
19 *
20 * parameter and midi data
21 *
22 * ----------------------------------------------------------------------------
23 */
24
25 #ifndef NDEBUG
26 #include <iostream>
27 #endif
28
29 #include "engine.h" // NOLINT
30
31 namespace gx_engine {
32
33 /****************************************************************
34 ** Global Variables
35 */
36
37 /* Midi */
38 MidiStandardControllers midi_std_ctr; // map ctrl num -> standard name
39
40
41 /****************************************************************
42 ** class MidiStandardControllers
43 */
44
45 static struct midi_std_init {
46 int ctrl;
47 const char *name;
48 } midi_std_itab[] = {
49 { 0, "Bank Select MSB"},
50 { 1, "Modulation MSB"},
51 { 2, "Breath Controller"},
52
53 { 4, "Foot Controller MSB"},
54 { 5, "Portamento Time MSB"},
55 { 6, "Data Entry MSB"},
56 { 7, "Main Volume"},
57 { 8, "Balance"},
58
59 {10, "Pan"},
60 {11, "Expression"},
61 {12, "Effect Control 1"},
62 {13, "Effect Control 2"},
63
64 {22, "Midi Beat Clock"},
65 {23, "Clock start/stop"},
66 {24, "Jack Transport"},
67
68 {32, "Bank Select LSB"},
69
70 {64, "Sustain"},
71 {65, "Portamento"},
72 {66, "Sostenuto"},
73 {67, "Soft Pedal"},
74 {68, "Legato Footswitch"},
75 {69, "Hold 2"},
76 {70, "Sound Contr. 1"}, // default: Sound Variation
77 {71, "Sound Contr. 2"}, // default: Timbre/Harmonic Content
78 {72, "Sound Contr. 3"}, // default: Release Time
79 {73, "Sound Contr. 4"}, // default: Attack Time
80 {74, "Sound Contr. 5"}, // default: Brightness
81 {75, "Sound Contr. 6"},
82 {76, "Sound Contr. 7"},
83 {77, "Sound Contr. 8"},
84 {78, "Sound Contr. 9"},
85 {79, "Sound Contr. 10"},
86
87 {84, "Portamento Control"},
88
89 {91, "Eff. 1 Depth"},
90 {92, "Eff. 2 Depth"},
91 {93, "Eff. 3 Depth"},
92 {94, "Eff. 4 Depth"},
93 {95, "Eff. 5 Depth"},
94 {96, "Data Inc"},
95 {97, "Data Dec"},
96 {98, "NRPN LSB"},
97 {99, "NRPN MSB"},
98 {100, "RPN LSB"},
99 {101, "RPN MSB"},
100
101 {120, "All Sounds Off"},
102 {121, "Controller Reset"},
103 {122, "Local Control"},
104 {123, "All Notes Off"},
105 {124, "Omni Off"},
106 {125, "Omni On"},
107 {126, "Mono On (Poly Off)"},
108 {127, "Poly On (Mono Off)"},
109 };
110
midi_to_note(int ctr)111 string MidiStandardControllers::midi_to_note(int ctr) {
112 static const char* notes[12] = {"C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B" };
113 int octave = (ctr / 12) - 1;
114 ostringstream b;
115 b << octave;
116 string p = b.str().substr(0, 1);
117 int index = (ctr % 12);
118 string note = notes[index];
119 return note + p;
120 }
121
ctr_desc(int ctr)122 string MidiStandardControllers::ctr_desc(int ctr) {
123 string p = midi_to_note(ctr-200);
124 return "Note On ( " + p + " )";
125 }
126
MidiStandardControllers()127 MidiStandardControllers::MidiStandardControllers() {
128 for (unsigned int i = 0; i < sizeof(midi_std_itab)/sizeof(midi_std_itab[0]); i++) {
129 m.insert(pair<int, modstring>(midi_std_itab[i].ctrl, modstring(midi_std_itab[i].name)));
130 }
131 for (unsigned int i = 0; i < 127; i++) {
132 const int mm = i + 200;
133 m.insert(pair<int, modstring>(mm, modstring(ctr_desc(mm).c_str())));
134 }
135 }
136
replace(int ctr,const string & name)137 void MidiStandardControllers::replace(int ctr, const string& name) {
138 map<int, modstring>::iterator i = m.find(ctr);
139 if (name.empty()) {
140 if (i != m.end()) {
141 if (i->second.modified) {
142 if (i->second.std) {
143 i->second.name = m[ctr].std;
144 m[ctr].modified = false;
145 } else {
146 m.erase(i);
147 }
148 }
149 }
150 } else {
151 if (i == m.end()) {
152 m[ctr] = modstring(name, true, 0);
153 } else {
154 i->second.modified = true;
155 i->second.name = name;
156 }
157 }
158 }
159
writeJSON(gx_system::JsonWriter & jw) const160 void MidiStandardControllers::writeJSON(gx_system::JsonWriter& jw) const {
161 jw.begin_object(true);
162 for (map<int, modstring>::const_iterator i = m.begin(); i != m.end(); ++i) {
163 if (i->second.modified) {
164 ostringstream ostr;
165 ostr << i->first;
166 jw.write_kv(ostr.str().c_str(), i->second.name);
167 }
168 }
169 jw.end_object(true);
170 }
171
readJSON(gx_system::JsonParser & jp)172 void MidiStandardControllers::readJSON(gx_system::JsonParser& jp) {
173 jp.next(gx_system::JsonParser::begin_object);
174 while (jp.peek() == gx_system::JsonParser::value_key) {
175 jp.next();
176 istringstream istr(jp.current_value());
177 int ctl;
178 istr >> ctl;
179 if (istr.fail()) {
180 throw gx_system::JsonException(_("midi standard controllers: number expected"));
181 }
182 jp.next();
183 replace(ctl, jp.current_value());
184 }
185 jp.next(gx_system::JsonParser::end_object);
186 }
187
188
189 /****************************************************************
190 ** class MidiController
191 */
192
writeJSON(gx_system::JsonWriter & jw) const193 void MidiController::writeJSON(gx_system::JsonWriter& jw) const {
194 jw.begin_array();
195 jw.write(param->id());
196 if (param->getControlType() == Parameter::Continuous ||
197 param->getControlType() == Parameter::Enum) {
198 jw.write(_lower);
199 jw.write(_upper);
200 } else {
201 assert(param->getControlType() == Parameter::Switch);
202 jw.write(toggle);
203 jw.write(_toggle_behaviour);
204 }
205 jw.end_array();
206 }
207
readJSON(gx_system::JsonParser & jp,ParamMap & pmap)208 MidiController *MidiController::readJSON(gx_system::JsonParser& jp, ParamMap& pmap) {
209 jp.next(gx_system::JsonParser::begin_array);
210 jp.next(gx_system::JsonParser::value_string);
211 string id = jp.current_value();
212 if (!pmap.hasId(id)) {
213 gx_print_warning(_("Midi controller settings"),
214 _("unknown parameter: ") + id);
215 while (jp.next() != gx_system::JsonParser::end_array);
216 return 0;
217 }
218 Parameter& pm = pmap[id];
219 float lower = 0, upper = 0;
220 bool toggle = false;
221 int toggle_behaviour = 0;
222 bool bad = false;
223 bool chg = false;
224 if (pm.getControlType() == Parameter::Continuous ||
225 pm.getControlType() == Parameter::Enum) {
226 if (jp.peek() == gx_system::JsonParser::value_number) {
227 jp.next(gx_system::JsonParser::value_number);
228 if (jp.peek() == gx_system::JsonParser::value_number) {
229 // two numbers -> range
230 float pmin, pmax;
231 if (pm.hasRange()) {
232 pmin = pm.getLowerAsFloat();
233 pmax = pm.getUpperAsFloat();
234 } else {
235 bad = true;
236 pmin = pmax = 0;
237 }
238 lower = jp.current_value_float();
239 jp.next(gx_system::JsonParser::value_number);
240 upper = jp.current_value_float();
241 if (lower > pmax) {
242 lower = pmax;
243 chg = true;
244 } else if (lower < pmin) {
245 lower = pmin;
246 chg = true;
247 }
248 if (upper > pmax) {
249 upper = pmax;
250 chg = true;
251 } else if (upper < pmin) {
252 upper = pmin;
253 chg = true;
254 }
255 } else {
256 // just one number -> switch (new format)
257 bad = true;
258 }
259 } else {
260 // no number -> switch (old format)
261 bad = true;
262 }
263 } else if (pm.getControlType() == Parameter::Switch) {
264 if (jp.peek() == gx_system::JsonParser::value_number) {
265 jp.next(gx_system::JsonParser::value_number);
266 int _toggle = jp.current_value_int();
267 if (jp.peek() == gx_system::JsonParser::value_number) {
268 jp.next(gx_system::JsonParser::value_number);
269 if (jp.current_value_int() < Parameter::toggle_type::_Count) {
270 toggle = _toggle;
271 toggle_behaviour = jp.current_value_int();
272 } else {
273 // two numbers -> range
274 bad = true;
275 }
276 } else {
277 toggle = _toggle;
278 }
279 }
280 } else {
281 // bad control type
282 bad = true;
283 }
284 assert(jp.peek() == gx_system::JsonParser::end_array);
285 while (jp.next() != gx_system::JsonParser::end_array); // be tolerant (non-debug mode)
286 if (bad) {
287 gx_print_warning(
288 _("recall MIDI state"),
289 _("invalid format, Parameter skipped: ") + id);
290 return 0;
291 }
292 if (chg) {
293 gx_print_warning(
294 _("recall MIDI state"),
295 _("Parameter range outside bounds, changed: ") + id);
296 }
297 return new MidiController(pm, lower, upper, toggle, toggle_behaviour);
298 }
299
set_midi(int n,int last_value,int * value_set,bool update)300 bool MidiController::set_midi(int n, int last_value, int *value_set, bool update) {
301 bool ret = false;
302 if (param->get_midi_blocked()) return ret;
303 if (toggle) {
304 switch (_toggle_behaviour) {
305 case Parameter::toggle_type::OnOff: {
306 bool s_o = (2*last_value > 127);
307 bool s_n = (2*n > 127);
308 if (!s_o && s_n) {
309 if (param->on_off_value()) {
310 ret = param->midi_set(0, 127, _lower, _upper);
311 *value_set = 0;
312 } else {
313 ret = param->midi_set(127, 127, _lower, _upper);
314 *value_set = 127;
315 }
316 }
317 break;
318 }
319 case Parameter::toggle_type::Constant: {
320 if (n == last_value || last_value == -1) {
321 if (param->on_off_value()) {
322 if (!update) {
323 ret = param->midi_set(0, n, _lower, _upper);
324 *value_set = 0;
325 } else {
326 ret = param->midi_set(127, n, _lower, _upper);
327 *value_set = 127;
328 }
329 } else {
330 if (!update) {
331 ret = param->midi_set(127, n, _lower, _upper);
332 *value_set = 127;
333 } else {
334 ret = param->midi_set(0, n, _lower, _upper);
335 *value_set = 0;
336 }
337 }
338 }
339 break;
340 }
341 case Parameter::toggle_type::Toggle: {
342 if (n !=last_value) {
343 if (param->on_off_value() && !n) {
344 ret = param->midi_set(0, 127, _lower, _upper);
345 *value_set = 0;
346 } else if (last_value != -1) {
347 ret = param->midi_set(127, 127, _lower, _upper);
348 *value_set = 127;
349 }
350 }
351 break;
352 }
353 case Parameter::toggle_type::Commander: {
354 if (!update) {
355 if (param->on_off_value()) {
356 ret = param->midi_set(0, 127, _lower, _upper);
357 *value_set = 0;
358 } else {
359 ret = param->midi_set(127, 127, _lower, _upper);
360 *value_set = 127;
361 }
362 }
363 break;
364 }
365 }
366 } else {
367 //fprintf(stderr,"continues %s \n",param->id().c_str());
368 //fprintf(stderr,"%f \n",(127.*log10f(double(n+1.)))/2.1072);
369 //fprintf(stderr,"%f \n",double(n * double(double(n+1.)/128)));
370 ret = param->midi_set(n, 127, _lower, _upper);
371 *value_set = n;
372 }
373 return ret;
374 }
375
set_trans(int n,int last_value)376 bool MidiController::set_trans(int n, int last_value) {
377 bool ret = false;
378 if (param->get_blocked()) return ret;
379 if (strcmp(param->id().c_str(), "engine.mute")==0) {
380 if ( n == 0) n = 127;
381 else n = 0;
382 }
383 ret = param->midi_set(n, 127, _lower, _upper);
384 if (ret) param->trigger_changed();
385 return ret;
386 }
387
set_bpm(int n,int last_value)388 bool MidiController::set_bpm(int n, int last_value) {
389 bool ret = false;
390 if (param->get_blocked()) return ret;
391 if (toggle) {
392 bool s_o = (2*last_value > 360);
393 bool s_n = (2*n > 360);
394 if (!s_o && s_n) {
395 if (param->on_off_value()) {
396 ret = param->midi_set_bpm(0, 360, _lower, _upper);
397 } else {
398 ret = param->midi_set_bpm(360, 360, _lower, _upper);
399 }
400 }
401 } else {
402 ret = param->midi_set_bpm(n, 360, _lower, _upper);
403 }
404 if (ret) param->trigger_changed();
405 return ret;
406 }
407
408 /****************************************************************
409 ** class ControllerArray
410 */
411
readJSON(gx_system::JsonParser & jp,ParamMap & param)412 void ControllerArray::readJSON(gx_system::JsonParser& jp, ParamMap& param) {
413 for (unsigned int n = 0; n < array_size; n++) {
414 operator[](n).clear();
415 }
416 jp.next(gx_system::JsonParser::begin_array);
417 while (jp.peek() != gx_system::JsonParser::end_array) {
418 jp.next(gx_system::JsonParser::value_number);
419 midi_controller_list& l = operator[](jp.current_value_int());
420 jp.next(gx_system::JsonParser::begin_array);
421 while (jp.peek() != gx_system::JsonParser::end_array) {
422 MidiController *p = MidiController::readJSON(jp, param);
423 if (p) {
424 l.push_back(*p);
425 delete p;
426 }
427 }
428 jp.next(gx_system::JsonParser::end_array);
429 }
430 jp.next(gx_system::JsonParser::end_array);
431 }
432
writeJSON(gx_system::JsonWriter & w) const433 void ControllerArray::writeJSON(gx_system::JsonWriter& w) const {
434 w.begin_array(true);
435 for (unsigned int n = 0; n < array_size; n++) {
436 const midi_controller_list& cl = operator[](n);
437 if (cl.empty())
438 continue;
439 w.write(n);
440 w.begin_array();
441 for (midi_controller_list::const_iterator i = cl.begin(); i != cl.end(); ++i)
442 i->writeJSON(w);
443 w.end_array(true);
444 }
445 w.newline();
446 w.end_array(true);
447 }
448
param2controller(Parameter & param,const MidiController ** p)449 int ControllerArray::param2controller(Parameter& param, const MidiController** p) {
450 for (ControllerArray::size_type n = 0; n < size(); ++n) {
451 const midi_controller_list& cl = operator[](n);
452 for (midi_controller_list::const_iterator i = cl.begin(); i != cl.end(); ++i) {
453 if (i->hasParameter(param)) {
454 if (p) {
455 *p = &(*i);
456 }
457 return n;
458 }
459 }
460 }
461 return -1;
462 }
463
deleteParameter(Parameter & p)464 bool ControllerArray::deleteParameter(Parameter& p) {
465 for (iterator pctr = begin(); pctr != end(); ++pctr) {
466 for (midi_controller_list::iterator i = pctr->begin(); i != pctr->end(); ++i) {
467 if (i->hasParameter(p)) {
468 pctr->erase(i);
469 return true;
470 }
471 }
472 }
473 return false;
474 }
475
476
477 /****************************************************************
478 ** class MidiClockToBpm
479 */
480
481
MidiClockToBpm()482 MidiClockToBpm::MidiClockToBpm()
483 : time1(0),
484 time_diff(0),
485 collect(0),
486 collect_(0),
487 bpm(0),
488 bpm_new(0),
489 ret(false) {}
490
rounded(float f)491 unsigned int MidiClockToBpm::rounded(float f) {
492 if (f >= 0x1.0p23) return (unsigned int) f;
493 return (unsigned int) (f + 0.49999997f);
494 }
495
time_to_bpm(double time,unsigned int * bpm_)496 bool MidiClockToBpm::time_to_bpm(double time, unsigned int* bpm_) {
497 ret = false;
498 // if time drift to far, reset bpm detection.
499 if ((time-time1)> (1.05*time_diff) || (time-time1)*1.05 < (time_diff)) {
500 bpm = 0;
501 collect = 0;
502 collect_ = 0;
503 } else {
504 bpm_new = ((1000000000. / (time-time1) / 24) * 60);
505 bpm += bpm_new;
506 collect++;
507
508 if (collect >= (bpm_new*bpm_new*0.0002)+1) {
509 bpm = (bpm/collect);
510 if (collect_>=2) {
511 (*bpm_) = rounded(min(360.,max(24.,bpm)));
512 collect_ = 0;
513 ret = true;
514 }
515 collect_++;
516 collect = 1;
517 }
518 }
519 time_diff = time-time1;
520 time1 = time;
521 return ret;
522 }
523
524 /****************************************************************
525 ** class MidiControllerList
526 */
527
MidiControllerList()528 MidiControllerList::MidiControllerList()
529 : map(),
530 last_midi_control_value(),
531 last_midi_control(-2),
532 changed_midi_control_value(),
533 program_change(-1),
534 mute_change(-1),
535 bank_change(-1),
536 bank_changed(0),
537 time0(0),
538 bpm_(9),
539 mp(),
540 pgm_chg(),
541 mute_chg(),
542 bank_chg(),
543 val_chg(),
544 changed(),
545 new_program(),
546 new_mute_state(),
547 new_bank(),
548 midi_value_changed(),
549 trigger_midi_feedback() {
550 for (int i = 0; i < ControllerArray::array_size; ++i) {
551 last_midi_control_value[i] = -1;
552 changed_midi_control_value[i] = 0;
553 }
554 pgm_chg.connect(sigc::mem_fun(*this, &MidiControllerList::on_pgm_chg));
555 mute_chg.connect(sigc::mem_fun(*this, &MidiControllerList::on_mute_chg));
556 bank_chg.connect(sigc::mem_fun(*this, &MidiControllerList::on_bank_chg));
557 // val_chg.connect(sigc::mem_fun(*this, &MidiControllerList::on_val_chg));
558 Glib::signal_timeout().connect(
559 sigc::mem_fun(this, &MidiControllerList::check_midi_values), 60);
560 }
561
check_midi_values()562 bool MidiControllerList::check_midi_values() {
563 static int saved_values[ControllerArray::array_size];
564 for (unsigned int n = 0; n < ControllerArray::array_size; ++n) {
565 if (changed_midi_control_value[n]) {
566 changed_midi_control_value[n] = 0;
567 saved_values[n] = last_midi_control_value[n];
568 midi_value_changed(n, saved_values[n]);
569 if (!get_config_mode()) {
570 midi_controller_list& ctr_list = map[n];
571 for (midi_controller_list::iterator i = ctr_list.begin(); i != ctr_list.end(); ++i) {
572 if (i->is_toggle()
573 && i->toggle_behaviour() == Parameter::toggle_type::Constant) {
574 midi_value_changed(n, i->getParameter().on_off_value() * 127);
575 }
576 if (!i->getParameter().get_blocked()) i->trigger_changed();
577 }
578 }
579 }
580 }
581 return true;
582 }
583
on_val_chg()584 void MidiControllerList::on_val_chg() {
585 static int saved_values[ControllerArray::array_size];
586 for (unsigned int n = 0; n < ControllerArray::array_size; ++n) {
587 if (changed_midi_control_value[n]) {
588 changed_midi_control_value[n] = 0;
589 saved_values[n] = last_midi_control_value[n];
590 midi_value_changed(n, saved_values[n]);
591 if (!get_config_mode()) {
592 midi_controller_list& ctr_list = map[n];
593 for (midi_controller_list::iterator i = ctr_list.begin(); i != ctr_list.end(); ++i) {
594 if (i->is_toggle()
595 && i->toggle_behaviour() == Parameter::toggle_type::Constant) {
596 midi_value_changed(n, i->getParameter().on_off_value() * 127);
597 }
598 }
599 }
600 }
601 }
602 }
603
604 /** update all controlled parameters with last received value from MIDI controller ctr. */
update_from_controller(int ctr)605 void MidiControllerList::update_from_controller(int ctr) {
606 int v = get_last_midi_control_value(ctr);
607 if (v >= 0) {
608 midi_controller_list& cl = map[ctr];
609 for (midi_controller_list::iterator i = cl.begin(); i != cl.end(); ++i) {
610 int value_set = -1;
611 i->set_midi(v, v, &value_set, true);
612 }
613 }
614 }
615
update_from_controllers()616 void MidiControllerList::update_from_controllers() {
617 for (unsigned int n = 0; n < map.size(); n++) {
618 update_from_controller(n);
619 }
620 }
621
on_pgm_chg()622 void MidiControllerList::on_pgm_chg() {
623 int pgm;
624 do {
625 pgm = gx_system::atomic_get(program_change);
626 } while (!gx_system::atomic_compare_and_exchange(&program_change, pgm, -1));
627 if (pgm>=0 || bank_changed) {
628 new_program(pgm);
629 bank_changed = 0;
630 }
631 }
632
on_mute_chg()633 void MidiControllerList::on_mute_chg() {
634 int mute;
635 do {
636 mute = gx_system::atomic_get(mute_change);
637 } while (!gx_system::atomic_compare_and_exchange(&mute_change, mute, -1));
638 new_mute_state(mute);
639 }
640
on_bank_chg()641 void MidiControllerList::on_bank_chg() {
642 int bk;
643 do {
644 bk = gx_system::atomic_get(bank_change);
645 } while (!gx_system::atomic_compare_and_exchange(&bank_change, bk, -1));
646 if (bk>=0) {
647 new_bank(bk);
648 bank_changed = 1;
649 }
650 }
651
set_config_mode(bool mode,int ctl)652 void MidiControllerList::set_config_mode(bool mode, int ctl) {
653 assert(mode != get_config_mode());
654 if (mode) {
655 last_midi_control = ctl;
656 } else {
657 last_midi_control = -2;
658 }
659 }
660
deleteParameter(Parameter & p)661 void MidiControllerList::deleteParameter(Parameter& p) {
662 bool mode = get_config_mode();
663 if (!mode) {
664 set_config_mode(true); // keep rt thread away from table
665 }
666 if (map.deleteParameter(p)) {
667 changed();
668 }
669 if (!mode) {
670 set_config_mode(false);
671 }
672 }
673
modifyCurrent(Parameter & param,float lower,float upper,bool toggle,int toggle_behaviour)674 void MidiControllerList::modifyCurrent(Parameter ¶m,
675 float lower, float upper, bool toggle, int toggle_behaviour) {
676 if (!get_config_mode()) {
677 assert(false);
678 return; // keep rt thread away from table
679 }
680 // maximal one controller for a zone allowed
681 deleteParameter(param);
682 if (last_midi_control < 0)
683 return;
684 // add zone to controller
685 map[last_midi_control].push_front(MidiController(param, lower, upper, toggle, toggle_behaviour));
686 update_from_controller(last_midi_control);
687 changed();
688 }
689
request_midi_value_update()690 void MidiControllerList::request_midi_value_update() {
691 for (unsigned int n = 0; n < ControllerArray::array_size; ++n) {
692 int v = last_midi_control_value[n];
693 midi_controller_list& ctr_list = map[n];
694 for (midi_controller_list::iterator i = ctr_list.begin(); i != ctr_list.end(); ++i) {
695 if (i->is_toggle()) {
696 v = i->getParameter().on_off_value() * 127;
697 }
698 midi_value_changed(n, v);
699 }
700 }
701 }
702
set_ctr_val(int ctr,int val)703 void MidiControllerList::set_ctr_val(int ctr, int val) {
704 if (get_config_mode()) {
705 last_midi_control = ctr;
706 } else {
707 midi_controller_list& ctr_list = map[ctr];
708 for (midi_controller_list::iterator i = ctr_list.begin(); i != ctr_list.end(); ++i) {
709 int value_set = -1;
710 if( i->set_midi(val, get_last_midi_control_value(ctr), &value_set, false)) {
711 trigger_midi_feedback(ctr,value_set);
712
713 }
714 }
715 }
716 MidiControllerList::set_last_midi_control_value(ctr, val);
717 }
718
set_bpm_val(unsigned int val)719 void MidiControllerList::set_bpm_val(unsigned int val) {
720 if (get_config_mode()) {
721 last_midi_control = 22;
722 } else {
723 midi_controller_list& ctr_list = map[22];
724 for (midi_controller_list::iterator i = ctr_list.begin(); i != ctr_list.end(); ++i) {
725 i->set_bpm(val, get_last_midi_control_value(22));
726 }
727 }
728 MidiControllerList::set_last_midi_control_value(22, val);
729 }
730
set_controller_array(const ControllerArray & m)731 void MidiControllerList::set_controller_array(const ControllerArray& m) {
732 bool mode = get_config_mode();
733 if (!mode) {
734 set_config_mode(true); // keep rt thread away from table
735 }
736 map = m;
737 if (!mode) {
738 set_config_mode(false);
739 }
740 changed();
741 }
742
remove_controlled_parameters(paramlist & plist,const ControllerArray * new_m)743 void MidiControllerList::remove_controlled_parameters(paramlist& plist,
744 const ControllerArray *new_m) {
745 std::set<Parameter*> pset;
746 for (unsigned int i = 0; i < map.size(); i++) {
747 midi_controller_list& ctr = map[i];
748 for (midi_controller_list::iterator j = ctr.begin(); j != ctr.end(); ++j) {
749 if (new_m) {
750 const midi_controller_list& ctr_new = (*new_m)[i];
751 for (midi_controller_list::const_iterator jn = ctr_new.begin();
752 jn != ctr_new.end(); ++jn) {
753 if (j->getParameter() == jn->getParameter()) {
754 pset.insert(&j->getParameter());
755 break;
756 }
757 }
758 } else {
759 pset.insert(&j->getParameter());
760 }
761 }
762 }
763 for (paramlist::iterator n = plist.begin(); n != plist.end(); ) {
764 paramlist::iterator n1 = n++;
765 if (pset.find(*n1) != pset.end()) {
766 plist.erase(n1);
767 }
768 }
769 }
770
set_midi_channel(int s)771 void MidiControllerList::set_midi_channel(int s) {
772 channel_select = s;
773 }
774
process_trans(int transport_state)775 void MidiControllerList::process_trans(int transport_state) {
776 unsigned int val = 0;
777 switch (transport_state) {
778 case JackTransportStopped:
779 val = 0;
780 break;
781 case JackTransportRolling:
782 val = 127;
783 break;
784 case JackTransportStarting:
785 val = 127;
786 break;
787 default:
788 return;
789 }
790 if (get_config_mode()) {
791 last_midi_control = 24;
792 } else {
793 midi_controller_list& ctr_list = map[24];
794 for (midi_controller_list::iterator i = ctr_list.begin(); i != ctr_list.end(); ++i) {
795 i->set_trans(val, get_last_midi_control_value(24));
796 }
797 }
798 MidiControllerList::set_last_midi_control_value(24, val);
799 val_chg();
800 }
801
802 // ----- jack process callback for the midi input
compute_midi_in(void * midi_input_port_buf,void * arg)803 void MidiControllerList::compute_midi_in(void* midi_input_port_buf, void *arg) {
804 jack_midi_event_t in_event;
805 jack_nframes_t event_count = jack_midi_get_event_count(midi_input_port_buf);
806 unsigned int i;
807 for (i = 0; i < event_count; i++) {
808 jack_midi_event_get(&in_event, midi_input_port_buf, i);
809 bool ch = true;
810 if (channel_select>0) {
811 if ((channel_select) != (int(in_event.buffer[0]&0x0f)+1)) {
812 ch = false;
813 }
814 }
815 if ((in_event.buffer[0] & 0xf0) == 0xc0 && ch) { // program change on any midi channel
816 gx_system::atomic_set(&program_change, in_event.buffer[1]);
817 pgm_chg();
818 } else if ((in_event.buffer[0] & 0xf0) == 0xb0 && ch) { // controller
819 if (in_event.buffer[1]== 120) { // engine mute by All Sound Off on any midi channel
820 gx_system::atomic_set(&mute_change, in_event.buffer[2]);
821 mute_chg();
822 } else if ((in_event.buffer[1]== 32 ||
823 in_event.buffer[1]== 0) && ch) { // bank change (LSB/MSB) on any midi channel
824 gx_system::atomic_set(&bank_change, in_event.buffer[2]);
825 bank_chg();
826 } else {
827 set_ctr_val(in_event.buffer[1], in_event.buffer[2]);
828 val_chg();
829 }
830 } else if ((in_event.buffer[0] & 0xf0) == 0x90 && ch) { // Note On
831 set_ctr_val(in_event.buffer[1]+200, 1);
832 val_chg();
833 //fprintf(stderr,"Note On %i", (int)in_event.buffer[1]);
834 } else if ((in_event.buffer[0] ) > 0xf0) { // midi clock
835 if ((in_event.buffer[0] ) == 0xf8) { // midi beat clock
836 clock_gettime(CLOCK_MONOTONIC, &ts1);
837 gx_jack::GxJack& jack = *static_cast<gx_jack::GxJack*>(arg);
838 static unsigned int sr = jack.get_jack_sr();
839 time0 = (ts1.tv_sec*1000000000.0)+(ts1.tv_nsec)+
840 (1000000000.0/(double)(sr/(double)in_event.time));
841 if (mp.time_to_bpm(time0, &bpm_)) {
842 set_bpm_val(bpm_);
843 val_chg();
844 }
845 } else if ((in_event.buffer[0] ) == 0xfa) { // midi clock start
846 set_ctr_val(23, 127);
847 val_chg();
848 } else if ((in_event.buffer[0] ) == 0xfb) { // midi clock continue
849 // set_ctr_val(23, 127);
850 } else if ((in_event.buffer[0] ) == 0xfc) { // midi clock stop
851 set_ctr_val(23, 0);
852 val_chg();
853 } else if ((in_event.buffer[0] ) == 0xf2) { // midi clock position
854 // not implemented
855 // set_ctr_val(24,(in_event.buffer[2]<<7) | in_event.buffer[1]);
856 }
857 }
858 }
859 }
860
861 /****************************************************************
862 ** Parameter Groups
863 */
864
ParameterGroups()865 ParameterGroups::ParameterGroups() {
866 insert("system", N_("System"));
867 insert("ui", N_("User Interface"));
868 insert("ui.amp", N_("User Interface")); // FIXME (ui.amp.tonestack)
869 insert("engine", N_("Audio Engine"));
870 }
871
~ParameterGroups()872 ParameterGroups::~ParameterGroups() {
873 #ifndef NDEBUG
874 for (map<string, bool>::iterator i = used.begin(); i != used.end(); ++i) {
875 if (!i->second) {
876 gx_print_error("Debug Check", "Group not used: " + i->first);
877 }
878 }
879 #endif
880 }
881
882 #ifndef NDEBUG
group_exists(const string & id)883 void ParameterGroups::group_exists(const string& id) {
884 if (groups.find(id) == groups.end()) {
885 gx_print_error("Debug Check", "Group does not exist: " + id);
886 } else {
887 used[id] = true;
888 }
889 }
890
group_is_new(const string & id)891 void ParameterGroups::group_is_new(const string& id) {
892 if (groups.find(id) != groups.end()) {
893 gx_print_error("Debug Check", "Group already exists: " + id);
894 }
895 }
896
dump()897 void ParameterGroups::dump() {
898 for (map<string, string>::iterator i = groups.begin(); i != groups.end(); ++i) {
899 printf("PG %s: %s\n", i->first.c_str(), i->second.c_str());
900 }
901 }
902
903 #endif
904
get_group_table()905 ParameterGroups& get_group_table() {
906 static ParameterGroups groups;
907 return groups;
908 }
909
param_group(const string & group_id,bool nowarn)910 string param_group(const string& group_id, bool nowarn) {
911 static ParameterGroups& groups = get_group_table();
912 if (nowarn) {
913 return groups.get(group_id);
914 } else {
915 return groups[group_id];
916 }
917 }
918
group_exist(const string & id)919 bool ParameterGroups::group_exist(const string& id) {
920 if (groups.find(id) == groups.end()) {
921 return false;
922 } else {
923 return true;
924 }
925 }
926
927 /****************************************************************
928 ** Parameter
929 */
930
jp_next(gx_system::JsonParser & jp,const char * key)931 gx_system::JsonParser& Parameter::jp_next(gx_system::JsonParser& jp, const char *key) {
932 jp.next(gx_system::JsonParser::begin_object);
933 jp.next(gx_system::JsonParser::value_key);
934 assert(jp.current_value() == key);
935 return jp;
936 }
937
serializeJSON(gx_system::JsonWriter & jw)938 void Parameter::serializeJSON(gx_system::JsonWriter& jw) {
939 jw.begin_object();
940 jw.write_kv("id", _id);
941 jw.write_kv("name", _name);
942 jw.write_kv("group", _group);
943 jw.write_kv("desc", _desc);
944 jw.write_kv("v_type", v_type); //FIXME
945 jw.write_kv("c_type", c_type); //FIXME
946 jw.write_kv("d_flags", d_flags); //FIXME
947 if (!controllable) {
948 jw.write_key("non_controllable"); jw.write(false);
949 }
950 if (!save_in_preset) {
951 jw.write_key("non_preset"); jw.write(false);
952 }
953 if (do_not_save) {
954 jw.write_key("do_not_save"); jw.write(true);
955 }
956 if (output) {
957 jw.write_key("output"); jw.write(true);
958 }
959 if (maxlevel) {
960 jw.write_key("maxlevel"); jw.write(true);
961 }
962 jw.end_object();
963 }
964
Parameter(gx_system::JsonParser & jp)965 Parameter::Parameter(gx_system::JsonParser& jp)
966 : boost::noncopyable(),
967 _id(),
968 _name(),
969 _group(),
970 _desc(),
971 v_type(tp_float),
972 c_type(Continuous),
973 d_flags(0),
974 save_in_preset(true),
975 controllable(true),
976 do_not_save(false),
977 blocked(false),
978 midi_blocked(false),
979 output(false),
980 maxlevel(false),
981 used(false) {
982 jp.next(gx_system::JsonParser::begin_object);
983 while (jp.peek() != gx_system::JsonParser::end_object) {
984 jp.next(gx_system::JsonParser::value_key);
985 if (jp.read_kv("id", _id) ||
986 jp.read_kv("name", _name) ||
987 jp.read_kv("group", _group) ||
988 jp.read_kv("desc", _desc)) {
989 } else if (jp.current_value() == "v_type") {
990 jp.next(gx_system::JsonParser::value_number);
991 v_type = static_cast<value_type>(jp.current_value_int());
992 } else if (jp.current_value() == "c_type") {
993 jp.next(gx_system::JsonParser::value_number);
994 c_type = static_cast<ctrl_type>(jp.current_value_int());
995 } else if (jp.current_value() == "d_flags") {
996 jp.next(gx_system::JsonParser::value_number);
997 d_flags = jp.current_value_int();
998 } else if (jp.current_value() == "non_controllable") {
999 jp.next(gx_system::JsonParser::value_number);
1000 controllable = false;
1001 } else if (jp.current_value() == "non_preset") {
1002 jp.next(gx_system::JsonParser::value_number);
1003 save_in_preset = false;
1004 } else if (jp.current_value() == "do_not_save") {
1005 jp.next(gx_system::JsonParser::value_number);
1006 do_not_save = true;
1007 } else if (jp.current_value() == "output") {
1008 jp.next(gx_system::JsonParser::value_number);
1009 output = true;
1010 } else if (jp.current_value() == "maxlevel") {
1011 jp.next(gx_system::JsonParser::value_number);
1012 maxlevel = true;
1013 } else {
1014 gx_print_warning(
1015 "Parameter", Glib::ustring::compose("%1: unknown key: %2", _id, jp.current_value()));
1016 jp.skip_object();
1017 }
1018 }
1019 jp.next(gx_system::JsonParser::end_object);
1020 }
1021
~Parameter()1022 Parameter::~Parameter() {
1023 }
1024
midi_set(float n,float high,float llimit,float ulimit)1025 bool Parameter::midi_set(float n, float high, float llimit, float ulimit) {
1026 assert(false);
1027 return false;
1028 }
1029
midi_set_bpm(float n,float high,float llimit,float ulimit)1030 bool Parameter::midi_set_bpm(float n, float high, float llimit, float ulimit) {
1031 assert(false);
1032 return false;
1033 }
1034
trigger_changed()1035 void Parameter::trigger_changed() {
1036 assert(false);
1037 }
1038
get_upper(const value_pair * vn)1039 static int get_upper(const value_pair *vn) {
1040 for (int n = 0; ; n++) {
1041 if (!vn[n].value_id) {
1042 return n - 1;
1043 }
1044 }
1045 }
1046
range_warning(float value,float lower,float upper)1047 void Parameter::range_warning(float value, float lower, float upper) {
1048 gx_print_warning(_("parameter load"),
1049 Glib::ustring::compose(_("parameter %1: value %2 out of range [%3, %4]"),
1050 _id, value, lower, upper));
1051 }
1052
get_typename() const1053 const char *Parameter::get_typename() const {
1054 static const char *tpname[] = {
1055 "float", "int", "bool", "bool", "filename", "string", "special"};
1056 assert(0 <= v_type and v_type < sizeof(tpname)/sizeof(tpname[0]));
1057 return tpname[v_type];
1058 }
1059
hasRange() const1060 bool Parameter::hasRange() const {
1061 return false;
1062 }
1063
getStepAsFloat() const1064 float Parameter::getStepAsFloat() const {
1065 return 1;
1066 }
1067
getLowerAsFloat() const1068 float Parameter::getLowerAsFloat() const {
1069 return 0;
1070 }
1071
getUpperAsFloat() const1072 float Parameter::getUpperAsFloat() const {
1073 return 0;
1074 }
1075
getValueNames() const1076 const value_pair *Parameter::getValueNames() const {
1077 return 0;
1078 }
1079
1080 #ifndef NDEBUG
compare_parameter(const char * title,Parameter * p1,Parameter * p2,bool all)1081 void compare_parameter(const char *title, Parameter* p1, Parameter* p2, bool all) {
1082 if (p1->_id != p2->_id) {
1083 gx_print_warning(
1084 title, Glib::ustring::compose("Different ID's: %2 / %3",
1085 p1->_id, p2->_id));
1086 }
1087 if (p1->_name != p2->_name) {
1088 gx_print_warning(
1089 title, Glib::ustring::compose("[%1]: Different name: %2 / %3",
1090 p1->_id, p1->_name, p2->_name));
1091 }
1092 if (p1->_group != p2->_group) {
1093 gx_print_warning(
1094 title, Glib::ustring::compose("[%1]: Different group: %2 / %3",
1095 p1->_id, p1->_group, p2->_group));
1096 }
1097 if (p1->_desc != p2->_desc) {
1098 gx_print_warning(
1099 title, Glib::ustring::compose("[%1]: Different desc: %2 / %3",
1100 p1->_id, p1->_desc, p2->_desc));
1101 }
1102 if (p1->save_in_preset != p2->save_in_preset) {
1103 gx_print_warning(
1104 title, Glib::ustring::compose("[%1]: save_in_preset different: %2 / %3",
1105 p1->_id, p1->save_in_preset, p2->save_in_preset));
1106 }
1107 if (p1->controllable != p2->controllable) {
1108 gx_print_warning(
1109 title, Glib::ustring::compose("[%1]: controllable different: %2 / %3",
1110 p1->_id, p1->controllable, p2->controllable));
1111 }
1112 if (p1->used != p2->used) {
1113 gx_print_warning(
1114 title, Glib::ustring::compose("[%1]: used different: %2 / %3",
1115 p1->_id, p1->used, p2->used));
1116 }
1117 if (p1->c_type != p2->c_type) {
1118 gx_print_warning(
1119 title, Glib::ustring::compose("[%1]: c_type different: %2 / %3",
1120 p1->_id, p1->c_type, p2->c_type));
1121 }
1122 if (p1->v_type != p2->v_type) {
1123 gx_print_warning(
1124 title, Glib::ustring::compose("[%1]: v_type different: %2 / %3",
1125 p1->_id, p1->v_type, p2->v_type));
1126 return;
1127 }
1128 if (p1->isFloat()) {
1129 FloatParameter& f1 = p1->getFloat();
1130 FloatParameter& f2 = p2->getFloat();
1131 if (f1.value != f2.value) {
1132 gx_print_warning(
1133 title, Glib::ustring::compose("[%1]: value address different: %2 / %3",
1134 p1->_id, f1.value, f2.value));
1135 }
1136 if (f1.lower != f2.lower) {
1137 gx_print_warning(
1138
1139 title, Glib::ustring::compose("[%1]: float lower different: %2 / %3",
1140 p1->_id, f1.lower, f2.lower));
1141 }
1142 if (f1.upper != f2.upper) {
1143 gx_print_warning(
1144 title, Glib::ustring::compose("[%1]: float upper different: %2 / %3",
1145 p1->_id, f1.upper, f2.upper));
1146 }
1147 if (f1.step != f2.step) {
1148 gx_print_warning(
1149 title, Glib::ustring::compose("[%1]: float step different: %2 / %3",
1150 p1->_id, f1.step, f2.step));
1151 }
1152 if (f1.std_value != f2.std_value) {
1153 gx_print_warning(
1154 title, Glib::ustring::compose("[%1]: float std value different: %2 / %3",
1155 p1->_id, f1.std_value, f2.std_value));
1156 }
1157 if (all) {
1158 if (f1.value != f2.value) {
1159 gx_print_warning(
1160 title, Glib::ustring::compose("[%1]: float value different: %2 / %3",
1161 p1->_id, *f1.value, *f2.value));
1162 }
1163 if (f1.json_value != f2.json_value) {
1164 gx_print_warning(
1165 title, Glib::ustring::compose("[%1]: float json value different: %2 / %3",
1166 p1->_id, f1.json_value, f2.json_value));
1167 }
1168 }
1169 return;
1170 }
1171 if (p1->isInt()) {
1172 assert(false);
1173 return;
1174 }
1175 if (p1->isBool()) {
1176 assert(false);
1177 return;
1178 }
1179 if (p1->isFile()) {
1180 assert(false);
1181 return;
1182 }
1183 assert(false);
1184 }
1185 #endif
1186
1187 /* FloatParameter */
1188
serializeJSON(gx_system::JsonWriter & jw)1189 void FloatParameter::serializeJSON(gx_system::JsonWriter& jw) {
1190 jw.begin_object();
1191 jw.write_key("Parameter"); Parameter::serializeJSON(jw);
1192 jw.write_kv("lower", lower);
1193 jw.write_kv("upper", upper);
1194 jw.write_kv("step", step);
1195 jw.write_kv("value", *value);
1196 jw.write_kv("std_value", std_value);
1197 jw.end_object();
1198 }
1199
ParameterV(gx_system::JsonParser & jp)1200 FloatParameter::ParameterV(gx_system::JsonParser& jp)
1201 : Parameter(jp_next(jp, "Parameter")), json_value(0), value(&value_storage), std_value(0), lower(), upper(), step() {
1202 while (jp.peek() != gx_system::JsonParser::end_object) {
1203 jp.next(gx_system::JsonParser::value_key);
1204 if (jp.read_kv("lower", lower) ||
1205 jp.read_kv("upper", upper) ||
1206 jp.read_kv("step", step) ||
1207 jp.read_kv("value", *value) ||
1208 jp.read_kv("std_value", std_value)) {
1209 } else {
1210 gx_print_warning(
1211 "FloatParameter", Glib::ustring::compose("%1: unknown key: %2", _id, jp.current_value()));
1212 jp.skip_object();
1213 }
1214 }
1215 jp.next(gx_system::JsonParser::end_object);
1216 }
1217
~ParameterV()1218 FloatParameter::~ParameterV() {
1219 }
1220
set(float val) const1221 bool FloatParameter::set(float val) const {
1222 float v = min(max(val, lower), upper);
1223 if (std::fabs(v - *value) >= step) {
1224 *value = v;
1225 changed(v);
1226 return true;
1227 }
1228 return false;
1229 }
1230
on_off_value()1231 bool FloatParameter::on_off_value() {
1232 return *value != 0;
1233 }
1234
idx_from_id(string v_id)1235 float FloatParameter::idx_from_id(string v_id) {
1236 assert(false);
1237 return 0;
1238 }
1239
midi_set(float n,float high,float llimit,float ulimit)1240 bool FloatParameter::midi_set(float n, float high, float llimit, float ulimit) {
1241 float v;
1242 switch (c_type) {
1243 case Continuous:
1244 assert(n >= 0 && n <= high);
1245 v = llimit + (n / high) * (ulimit - llimit);
1246 break;
1247 case Switch:
1248 v = (2*n > high ? 1.0 : 0.0);
1249 break;
1250 case Enum:
1251 v = lower + min(n, upper-lower);
1252 break;
1253 default:
1254 assert(false);
1255 return false;
1256 }
1257 if (std::fabs(v - *value) >= step) {
1258 *value = v;
1259 return true;
1260 }
1261 return false;
1262 }
1263
midi_set_bpm(float n,float high,float llimit,float ulimit)1264 bool FloatParameter::midi_set_bpm(float n, float high, float llimit, float ulimit) {
1265 float v;
1266 switch (c_type) {
1267 case Continuous:
1268 assert(n >= 0 && n <= high);
1269 if (high <= ulimit) {
1270 v = max(llimit,min(ulimit,n));
1271 } else {
1272 v = llimit + (n / high) * (ulimit - llimit);
1273 }
1274 break;
1275 case Switch:
1276 v = (2*n > high ? 1.0 : 0.0);
1277 break;
1278 case Enum:
1279 v = lower + min(n, upper-lower);
1280 break;
1281 default:
1282 assert(false);
1283 return false;
1284 }
1285 if (std::fabs(v - *value) >= step) {
1286 *value = v;
1287 return true;
1288 }
1289 return false;
1290 }
1291
trigger_changed()1292 void FloatParameter::trigger_changed() {
1293 changed(*value);
1294 }
1295
stdJSON_value()1296 void FloatParameter::stdJSON_value() {
1297 json_value = std_value;
1298 }
1299
writeJSON(gx_system::JsonWriter & jw) const1300 void FloatParameter::writeJSON(gx_system::JsonWriter& jw) const {
1301 jw.write_kv(_id.c_str(), *value);
1302 }
1303
ramp_value(float val)1304 bool FloatParameter::ramp_value(float val) {
1305 if (std::abs(json_value - val) < 10*FLT_EPSILON || std::abs(json_value )> std::abs(val)) {
1306 json_value = val;
1307 setJSON_value();
1308 return false;
1309 } else if (val<=std_value) {
1310 json_value = val;
1311 setJSON_value();
1312 return false;
1313 }
1314 float v = val * 0.1;
1315 json_value += v;
1316 setJSON_value();
1317 //fprintf(stderr, "set value %f of %f\n",json_value, val);
1318 return true;
1319 }
1320
rampJSON_value(gx_system::JsonParser & jp)1321 void FloatParameter::rampJSON_value(gx_system::JsonParser& jp) {
1322 jp.next(gx_system::JsonParser::value_number);
1323 json_value = std_value;
1324 Glib::signal_timeout().connect(sigc::bind<float>(
1325 sigc::mem_fun (*this, &FloatParameter::ramp_value),jp.current_value_float()), 10);
1326 }
1327
readJSON_value(gx_system::JsonParser & jp)1328 void FloatParameter::readJSON_value(gx_system::JsonParser& jp) {
1329 jp.next(gx_system::JsonParser::value_number);
1330 json_value = jp.current_value_float();
1331 if (json_value < lower-std::abs(5*FLT_EPSILON*lower) || json_value > upper+std::abs(5*FLT_EPSILON*upper)) {
1332 range_warning(json_value, lower, upper);
1333 json_value = std_value;
1334 }
1335 }
1336
compareJSON_value()1337 bool FloatParameter::compareJSON_value() {
1338 return std::abs(json_value - *value) < 5*FLT_EPSILON;
1339 }
1340
setJSON_value()1341 void FloatParameter::setJSON_value() {
1342 set(json_value);
1343 }
1344
convert_from_range(float low,float up)1345 void FloatParameter::convert_from_range(float low, float up) {
1346 json_value = lower + (json_value - low) / (up - low) * (upper - lower);
1347 }
1348
hasRange() const1349 bool FloatParameter::hasRange() const {
1350 return true;
1351 }
1352
getLowerAsFloat() const1353 float FloatParameter::getLowerAsFloat() const {
1354 return lower;
1355 }
1356
getUpperAsFloat() const1357 float FloatParameter::getUpperAsFloat() const {
1358 return upper;
1359 }
1360
getStepAsFloat() const1361 float FloatParameter::getStepAsFloat() const {
1362 return step;
1363 }
1364
1365
1366 /* FloatEnumParameter */
1367
serializeValueNames(gx_system::JsonWriter & jw,const value_pair * p)1368 static void serializeValueNames(gx_system::JsonWriter& jw, const value_pair *p) {
1369 jw.write_key("value_names");
1370 jw.begin_array();
1371 while (p->value_id) {
1372 jw.write(p->value_id);
1373 if (p->value_label) {
1374 jw.write(p->value_label);
1375 } else {
1376 jw.write(p->value_id);
1377 }
1378 p++;
1379 }
1380 jw.end_array();
1381 }
1382
serializeJSON(gx_system::JsonWriter & jw)1383 void FloatEnumParameter::serializeJSON(gx_system::JsonWriter& jw) {
1384 jw.begin_object();
1385 jw.write_key("FloatParameter"); FloatParameter::serializeJSON(jw);
1386 serializeValueNames(jw, value_names);
1387 jw.end_object();
1388 }
1389
FloatEnumParameter(const string & id,const string & name,const value_pair * vn,bool preset,float * v,int sv,int low,bool ctrl,bool no_init)1390 FloatEnumParameter::FloatEnumParameter(const string& id, const string& name, const value_pair* vn, bool preset,
1391 float *v, int sv, int low, bool ctrl, bool no_init):
1392 FloatParameter(id, name, Enum, preset, v, sv, low, low+get_upper(vn), 1, ctrl, no_init),
1393 value_names(vn) {}
1394
getValueNames() const1395 const value_pair *FloatEnumParameter::getValueNames() const {
1396 return value_names;
1397 }
1398
writeJSON(gx_system::JsonWriter & jw) const1399 void FloatEnumParameter::writeJSON(gx_system::JsonWriter& jw) const {
1400 jw.write_key(_id.c_str());
1401 jw.write(value_names[static_cast<int>(round(*value-lower))].value_id);
1402 }
1403
idx_from_id(string v_id)1404 float FloatEnumParameter::idx_from_id(string v_id) {
1405 int up = static_cast<int>(round(upper));
1406 int low = static_cast<int>(round(lower));
1407 int n = 0;
1408 for (; n <= up-low; n++) {
1409 if (v_id == value_names[n].value_id) {
1410 return low + n;
1411 }
1412 }
1413 return -1;
1414 }
1415
readJSON_value(gx_system::JsonParser & jp)1416 void FloatEnumParameter::readJSON_value(gx_system::JsonParser& jp) {
1417 gx_system::JsonParser::token tok = jp.next();
1418 if (tok == gx_system::JsonParser::value_number) {
1419 // old version compatibility
1420 json_value = jp.current_value_int();
1421 return;
1422 }
1423 jp.check_expect(gx_system::JsonParser::value_string);
1424 float n = idx_from_id(jp.current_value());
1425 if (n < 0) {
1426 #ifndef NEW_LADSPA
1427 bool found;
1428 string v_id = gx_preset::PresetIO::try_replace_param_value(id(), jp.current_value(), found);
1429 if (found) {
1430 n = idx_from_id(v_id);
1431 }
1432 #endif
1433 if (n < 0) {
1434 gx_print_warning(
1435 _("read parameter"), (boost::format(_("parameter %1%: unknown enum value: %2%"))
1436 % _id % jp.current_value()).str());
1437 n = lower;
1438 }
1439 }
1440 json_value = n;
1441 }
1442
1443 /* IntParameter */
1444
serializeJSON(gx_system::JsonWriter & jw)1445 void IntParameter::serializeJSON(gx_system::JsonWriter& jw) {
1446 jw.begin_object();
1447 jw.write_key("Parameter"); Parameter::serializeJSON(jw);
1448 jw.write_kv("lower", lower);
1449 jw.write_kv("upper", upper);
1450 jw.write_kv("value", *value);
1451 jw.write_kv("std_value", std_value);
1452 jw.end_object();
1453 }
1454
ParameterV(gx_system::JsonParser & jp)1455 IntParameter::ParameterV(gx_system::JsonParser& jp)
1456 : Parameter(jp_next(jp, "Parameter")), json_value(0), value(&value_storage), std_value(0), lower(), upper() {
1457 while (jp.peek() != gx_system::JsonParser::end_object) {
1458 jp.next(gx_system::JsonParser::value_key);
1459 if (jp.read_kv("lower", lower) ||
1460 jp.read_kv("upper", upper) ||
1461 jp.read_kv("value", *value) ||
1462 jp.read_kv("std_value", std_value)) {
1463 } else {
1464 gx_print_warning(
1465 "IntParameter", Glib::ustring::compose("%1: unknown key: %2", _id, jp.current_value()));
1466 jp.skip_object();
1467 }
1468 }
1469 jp.next(gx_system::JsonParser::end_object);
1470 }
1471
~ParameterV()1472 IntParameter::~ParameterV() {
1473 }
1474
set(int val) const1475 bool IntParameter::set(int val) const {
1476 int v = min(max(val, lower), upper);
1477 if (v != *value) {
1478 *value = v;
1479 changed(v);
1480 return true;
1481 }
1482 return false;
1483 }
1484
idx_from_id(string v_id)1485 int IntParameter::idx_from_id(string v_id) {
1486 assert(false);
1487 return 0;
1488 }
1489
on_off_value()1490 bool IntParameter::on_off_value() {
1491 return *value != 0;
1492 }
1493
midi_set(float n,float high,float llimit,float ulimit)1494 bool IntParameter::midi_set(float n, float high, float llimit, float ulimit) {
1495 int v;
1496 switch (c_type) {
1497 case Continuous:
1498 assert(false); // not implemented
1499 return false;
1500 case Switch:
1501 assert(false); // not implemented
1502 return false;
1503 case Enum:
1504 v = lower + min(static_cast<int>(n), upper-lower);
1505 break;
1506 default:
1507 assert(false);
1508 return false;
1509 }
1510 if (v != *value) {
1511 *value = v;
1512 return true;
1513 }
1514 return false;
1515 }
1516
trigger_changed()1517 void IntParameter::trigger_changed() {
1518 changed(*value);
1519 }
1520
stdJSON_value()1521 void IntParameter::stdJSON_value() {
1522 json_value = std_value;
1523 }
1524
writeJSON(gx_system::JsonWriter & jw) const1525 void IntParameter::writeJSON(gx_system::JsonWriter& jw) const {
1526 jw.write_kv(_id.c_str(), *value);
1527 }
1528
readJSON_value(gx_system::JsonParser & jp)1529 void IntParameter::readJSON_value(gx_system::JsonParser& jp) {
1530 jp.next(gx_system::JsonParser::value_number);
1531 json_value = jp.current_value_int();
1532 if (json_value < lower || json_value > upper) {
1533 range_warning(json_value, lower, upper);
1534 }
1535 }
1536
compareJSON_value()1537 bool IntParameter::compareJSON_value() {
1538 return json_value == *value;
1539 }
1540
setJSON_value()1541 void IntParameter::setJSON_value() {
1542 set(json_value);
1543 }
1544
hasRange() const1545 bool IntParameter::hasRange() const {
1546 return true;
1547 }
1548
getLowerAsFloat() const1549 float IntParameter::getLowerAsFloat() const {
1550 return lower;
1551 }
1552
getUpperAsFloat() const1553 float IntParameter::getUpperAsFloat() const {
1554 return upper;
1555 }
1556
1557 /* EnumParameter */
1558
serializeJSON(gx_system::JsonWriter & jw)1559 void EnumParameter::serializeJSON(gx_system::JsonWriter& jw) {
1560 jw.begin_object();
1561 jw.write_key("IntParameter"); IntParameter::serializeJSON(jw);
1562 serializeValueNames(jw, value_names);
1563 jw.end_object();
1564 }
1565
EnumParameter(const string & id,const string & name,const value_pair * vn,bool preset,int * v,int sv,bool ctrl)1566 EnumParameter::EnumParameter(const string& id, const string& name, const value_pair* vn, bool preset,
1567 int *v, int sv, bool ctrl):
1568 IntParameter(id, name, Enum, preset, v, sv, 0, get_upper(vn), ctrl),
1569 value_names(vn) {}
1570
getValueNames() const1571 const value_pair *EnumParameter::getValueNames() const {
1572 return value_names;
1573 }
1574
idx_from_id(string v_id)1575 int EnumParameter::idx_from_id(string v_id) {
1576 int n = 0;
1577 for (; n <= upper; n++) {
1578 if (v_id == value_names[n].value_id) {
1579 return n;
1580 }
1581 }
1582 return -1;
1583 }
1584
writeJSON(gx_system::JsonWriter & jw) const1585 void EnumParameter::writeJSON(gx_system::JsonWriter& jw) const {
1586 jw.write_key(_id.c_str());
1587 jw.write(value_names[*value].value_id);
1588 }
1589
readJSON_value(gx_system::JsonParser & jp)1590 void EnumParameter::readJSON_value(gx_system::JsonParser& jp) {
1591 gx_system::JsonParser::token tok = jp.next();
1592 if (tok == gx_system::JsonParser::value_number) {
1593 // old version compatibility
1594 json_value = jp.current_value_int();
1595 return;
1596 }
1597 jp.check_expect(gx_system::JsonParser::value_string);
1598 int n = idx_from_id(jp.current_value());
1599 if (n < 0) {
1600 gx_print_warning(
1601 _("read parameter"), (boost::format(_("parameter %1%: unknown enum value: %2%"))
1602 % _id % jp.current_value()).str());
1603 n = 0;
1604 }
1605 json_value = n;
1606 }
1607
1608 /* derived enum parameters */
1609
1610 typedef std::pair<std::string,std::string> id_label;
1611
enum_parameter_load_values(gx_system::JsonParser & jp,std::vector<id_label> & value_array,const value_pair ** value_names)1612 void enum_parameter_load_values(gx_system::JsonParser& jp, std::vector<id_label>& value_array, const value_pair **value_names) {
1613 while (jp.peek() != gx_system::JsonParser::end_object) {
1614 jp.next(gx_system::JsonParser::value_key);
1615 if (jp.current_value() == "value_names") {
1616 jp.next(gx_system::JsonParser::begin_array);
1617 while (jp.peek() != gx_system::JsonParser::end_array) {
1618 jp.next(gx_system::JsonParser::value_string);
1619 std::string value_id = jp.current_value();
1620 jp.next(gx_system::JsonParser::value_string);
1621 std::string value_label = jp.current_value();
1622 value_array.push_back(id_label(value_id, value_label));
1623 }
1624 jp.next(gx_system::JsonParser::end_array);
1625 } else {
1626 gx_print_warning(
1627 "EnumValueNames", Glib::ustring::compose("unknown key: %1", jp.current_value()));
1628 jp.skip_object();
1629 }
1630 }
1631 jp.next(gx_system::JsonParser::end_object);
1632 value_pair* p = new value_pair[value_array.size()+1];
1633 *value_names = p;
1634 for (std::vector<id_label>::iterator i = value_array.begin(); i != value_array.end(); ++i) {
1635 p->value_id = i->first.c_str();
1636 p->value_label = i->second.c_str();
1637 p++;
1638 }
1639 p->value_id = p->value_label = 0;
1640 }
1641
1642 class FloatEnumParameterD: public FloatEnumParameter {
1643 private:
1644 std::vector<id_label> value_array;
1645 public:
1646 FloatEnumParameterD(gx_system::JsonParser& jp);
1647 ~FloatEnumParameterD();
1648 };
1649
FloatEnumParameterD(gx_system::JsonParser & jp)1650 FloatEnumParameterD::FloatEnumParameterD(gx_system::JsonParser& jp)
1651 : FloatEnumParameter(jp), value_array() {
1652 enum_parameter_load_values(jp, value_array, &value_names);
1653 }
1654
~FloatEnumParameterD()1655 FloatEnumParameterD::~FloatEnumParameterD() {
1656 delete value_names;
1657 }
1658
1659 class EnumParameterD: public EnumParameter {
1660 private:
1661 std::vector<id_label> value_array;
1662 public:
1663 EnumParameterD(gx_system::JsonParser& jp);
1664 ~EnumParameterD();
1665 };
1666
EnumParameterD(gx_system::JsonParser & jp)1667 EnumParameterD::EnumParameterD(gx_system::JsonParser& jp)
1668 : EnumParameter(jp), value_array() {
1669 enum_parameter_load_values(jp, value_array, &value_names);
1670 }
1671
~EnumParameterD()1672 EnumParameterD::~EnumParameterD() {
1673 delete value_names;
1674 }
1675
1676
1677 /* BoolParameter */
1678
serializeJSON(gx_system::JsonWriter & jw)1679 void BoolParameter::serializeJSON(gx_system::JsonWriter& jw) {
1680 jw.begin_object();
1681 jw.write_key("Parameter"); Parameter::serializeJSON(jw);
1682 jw.write_kv("value", *value);
1683 jw.write_kv("std_value", std_value);
1684 jw.end_object();
1685 }
1686
ParameterV(gx_system::JsonParser & jp)1687 BoolParameter::ParameterV(gx_system::JsonParser& jp)
1688 : Parameter(jp_next(jp, "Parameter")), json_value(0), value(&value_storage), std_value(0) {
1689 while (jp.peek() != gx_system::JsonParser::end_object) {
1690 jp.next(gx_system::JsonParser::value_key);
1691 if (jp.read_kv("value", *value) || jp.read_kv("std_value", std_value)) {
1692 } else {
1693 gx_print_warning(
1694 "BoolParameter", Glib::ustring::compose("%1: unknown key: %2", _id, jp.current_value()));
1695 jp.skip_object();
1696 }
1697 }
1698 jp.next(gx_system::JsonParser::end_object);
1699 }
1700
~ParameterV()1701 BoolParameter::~ParameterV() {
1702 }
1703
set(bool val) const1704 bool BoolParameter::set(bool val) const {
1705 if (val != *value) {
1706 *value = val;
1707 changed(val);
1708 return true;
1709 }
1710 return false;
1711 }
1712
on_off_value()1713 bool BoolParameter::on_off_value() {
1714 return *value;
1715 }
1716
midi_set(float n,float high,float llimit,float ulimit)1717 bool BoolParameter::midi_set(float n, float high, float llimit, float ulimit) {
1718 bool v;
1719 switch (c_type) {
1720 case Switch:
1721 v = (2*n > high);
1722 break;
1723 default:
1724 assert(false);
1725 return false;
1726 }
1727 if (v != *value) {
1728 *value = v;
1729 return true;
1730 }
1731 return false;
1732 }
1733
trigger_changed()1734 void BoolParameter::trigger_changed() {
1735 changed(*value);
1736 }
1737
stdJSON_value()1738 void BoolParameter::stdJSON_value() {
1739 json_value = std_value;
1740 }
1741
writeJSON(gx_system::JsonWriter & jw) const1742 void BoolParameter::writeJSON(gx_system::JsonWriter& jw) const {
1743 jw.write_kv(_id.c_str(), *value);
1744 }
1745
readJSON_value(gx_system::JsonParser & jp)1746 void BoolParameter::readJSON_value(gx_system::JsonParser& jp) {
1747 jp.next(gx_system::JsonParser::value_number);
1748 if (jp.current_value_int() < 0 || jp.current_value_int() > 1) {
1749 range_warning(json_value, 0, 1);
1750 }
1751 json_value = jp.current_value_int();
1752 }
1753
compareJSON_value()1754 bool BoolParameter::compareJSON_value() {
1755 return json_value == *value;
1756 }
1757
setJSON_value()1758 void BoolParameter::setJSON_value() {
1759 set(json_value);
1760 }
1761
1762
1763 /* FileParameter */
1764
serializeJSON(gx_system::JsonWriter & jw)1765 void FileParameter::serializeJSON(gx_system::JsonWriter& jw) {
1766 jw.begin_object();
1767 jw.write_key("Parameter"); Parameter::serializeJSON(jw);
1768 jw.write_kv("value", value->get_path());
1769 jw.write_kv("std_value", std_value->get_path());
1770 jw.end_object();
1771 }
1772
FileParameter(gx_system::JsonParser & jp)1773 FileParameter::FileParameter(gx_system::JsonParser& jp)
1774 : Parameter(jp_next(jp, "Parameter")), value(0), std_value(0), json_value(0) {
1775 while (jp.peek() != gx_system::JsonParser::end_object) {
1776 jp.next(gx_system::JsonParser::value_key);
1777 if (jp.current_value() == "value") {
1778 jp.next(gx_system::JsonParser::value_string);
1779 value = Gio::File::create_for_path(jp.current_value());
1780 } else if (jp.current_value() == "std_value") {
1781 jp.next(gx_system::JsonParser::value_string);
1782 std_value = Gio::File::create_for_path(jp.current_value());
1783 } else {
1784 gx_print_warning(
1785 "FileParameter", Glib::ustring::compose("%1: unknown key: %2", _id, jp.current_value()));
1786 jp.skip_object();
1787 }
1788 }
1789 jp.next(gx_system::JsonParser::end_object);
1790 }
1791
set_path(const string & path)1792 void FileParameter::set_path(const string& path) {
1793 Glib::RefPtr<Gio::File> v = Gio::File::create_for_path(path);
1794 if (is_equal(v)) {
1795 return;
1796 }
1797 value = v;
1798 changed();
1799 }
1800
set(const Glib::RefPtr<Gio::File> & val)1801 bool FileParameter::set(const Glib::RefPtr<Gio::File>& val) {
1802 if (is_equal(val)) {
1803 return false;
1804 }
1805 value = val;
1806 changed();
1807 return true;
1808 }
1809
set_standard(const string & filename)1810 void FileParameter::set_standard(const string& filename) {
1811 std_value = Gio::File::create_for_path(filename);
1812 if (!value) {
1813 value = std_value->dup();
1814 changed();
1815 }
1816 }
1817
stdJSON_value()1818 void FileParameter::stdJSON_value() {
1819 json_value = std_value->dup();
1820 changed();
1821 }
1822
on_off_value()1823 bool FileParameter::on_off_value() {
1824 return bool(value);
1825 }
1826
writeJSON(gx_system::JsonWriter & jw) const1827 void FileParameter::writeJSON(gx_system::JsonWriter& jw) const {
1828 jw.write_kv(_id.c_str(), get_path());
1829 }
1830
readJSON_value(gx_system::JsonParser & jp)1831 void FileParameter::readJSON_value(gx_system::JsonParser& jp) {
1832 jp.next(gx_system::JsonParser::value_string);
1833 json_value = Gio::File::create_for_path(jp.current_value());
1834 }
1835
compareJSON_value()1836 bool FileParameter::compareJSON_value() {
1837 return json_value->get_path() == value->get_path(); //FIXME
1838 }
1839
setJSON_value()1840 void FileParameter::setJSON_value() {
1841 set(json_value);
1842 }
1843
get_file_id(const Glib::RefPtr<Gio::File> & f)1844 static string get_file_id(const Glib::RefPtr<Gio::File>& f) {
1845 return f->query_info(G_FILE_ATTRIBUTE_ID_FILE)->get_attribute_string(G_FILE_ATTRIBUTE_ID_FILE);
1846 }
1847
is_equal(const Glib::RefPtr<Gio::File> & v) const1848 bool FileParameter::is_equal(const Glib::RefPtr<Gio::File>& v) const {
1849 string id, id2;
1850 try {
1851 id = get_file_id(value);
1852 } catch(Gio::Error& ex) {
1853 return false; // FIXME check type of exception
1854 }
1855 try {
1856 id2 = get_file_id(v);
1857 } catch(Gio::Error& ex) {
1858 return false; // FIXME check type of exception
1859 }
1860 return id == id2;
1861 }
1862
get_path() const1863 string FileParameter::get_path() const {
1864 return value->get_path();
1865 }
1866
get_directory_path() const1867 string FileParameter::get_directory_path() const {
1868 return value->get_parent()->get_path();
1869 }
1870
get_parse_name() const1871 string FileParameter::get_parse_name() const {
1872 return value->get_parse_name();
1873 }
1874
get_display_name() const1875 string FileParameter::get_display_name() const {
1876 return value->query_info(G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME)->get_display_name();
1877 }
1878
copy(const string & destination) const1879 void FileParameter::copy(const string& destination) const {
1880 value->copy(Gio::File::create_for_path(destination));
1881 }
1882
1883
1884 /* StringParameter */
1885
serializeJSON(gx_system::JsonWriter & jw)1886 void StringParameter::serializeJSON(gx_system::JsonWriter& jw) {
1887 jw.begin_object();
1888 jw.write_key("Parameter"); Parameter::serializeJSON(jw);
1889 jw.write_kv("value", *value);
1890 jw.write_kv("std_value", std_value);
1891 jw.end_object();
1892 }
1893
ParameterV(gx_system::JsonParser & jp)1894 StringParameter::ParameterV(gx_system::JsonParser& jp)
1895 : Parameter(jp_next(jp, "Parameter")), json_value(""), value(&value_storage), std_value("") {
1896 while (jp.peek() != gx_system::JsonParser::end_object) {
1897 jp.next(gx_system::JsonParser::value_key);
1898 if (jp.read_kv("value", *value) || jp.read_kv("std_value", std_value)) {
1899 } else {
1900 gx_print_warning(
1901 "StringParameter", Glib::ustring::compose("%1: unknown key: %2", _id, jp.current_value()));
1902 jp.skip_object();
1903 }
1904 }
1905 jp.next(gx_system::JsonParser::end_object);
1906 }
1907
~ParameterV()1908 StringParameter::~ParameterV() {
1909 }
1910
set(const Glib::ustring & val) const1911 bool StringParameter::set(const Glib::ustring& val) const {
1912 if (val != *value) {
1913 *value = val;
1914 changed(*value);
1915 return true;
1916 }
1917 return false;
1918 }
1919
on_off_value()1920 bool StringParameter::on_off_value() {
1921 return !value->empty();
1922 }
1923
stdJSON_value()1924 void StringParameter::stdJSON_value() {
1925 json_value = std_value;
1926 }
1927
writeJSON(gx_system::JsonWriter & jw) const1928 void StringParameter::writeJSON(gx_system::JsonWriter& jw) const {
1929 jw.write_kv(_id.c_str(), *value);
1930 }
1931
readJSON_value(gx_system::JsonParser & jp)1932 void StringParameter::readJSON_value(gx_system::JsonParser& jp) {
1933 jp.next(gx_system::JsonParser::value_string);
1934 json_value = jp.current_value();
1935 }
1936
compareJSON_value()1937 bool StringParameter::compareJSON_value() {
1938 return json_value == *value;
1939 }
1940
setJSON_value()1941 void StringParameter::setJSON_value() {
1942 set(json_value);
1943 }
1944
1945 /****************************************************************
1946 ** Parameter Map
1947 */
1948
ParamMap()1949 ParamMap::ParamMap()
1950 : id_map(),
1951 replace_mode(false) {
1952 }
1953
~ParamMap()1954 ParamMap::~ParamMap() {
1955 for (iterator i = id_map.begin(); i != id_map.end(); ++i) {
1956 delete i->second;
1957 }
1958 }
1959
writeJSON_one(gx_system::JsonWriter & jw,Parameter * p)1960 void ParamMap::writeJSON_one(gx_system::JsonWriter& jw, Parameter *p) {
1961 if (p->isFloat()) {
1962 if (p->getControlType() == Parameter::Enum) {
1963 jw.write("FloatEnum");
1964 } else {
1965 jw.write("Float");
1966 }
1967 } else if (p->isInt()) {
1968 if (p->getControlType() == Parameter::Enum) {
1969 jw.write("Enum");
1970 } else {
1971 jw.write("Int");
1972 }
1973 } else if (p->isBool()) {
1974 jw.write("Bool");
1975 } else if (p->isFile()) {
1976 jw.write("File");
1977 } else if (p->isString()) {
1978 jw.write("String");
1979 } else if (dynamic_cast<JConvParameter*>(p) != 0) {
1980 jw.write("JConv");
1981 } else if (dynamic_cast<SeqParameter*>(p) != 0) {
1982 jw.write("Seq");
1983 #ifndef NEW_LADSPA
1984 } else if (dynamic_cast<OscParameter*>(p) != 0) {
1985 jw.write("Osc");
1986 #endif
1987 } else {
1988 #ifndef NDEBUG
1989 cerr << "skipping " << p->id() << endl;
1990 #endif
1991 return;
1992 }
1993 p->serializeJSON(jw);
1994 }
1995
writeJSON(gx_system::JsonWriter & jw)1996 void ParamMap::writeJSON(gx_system::JsonWriter& jw) {
1997 jw.begin_array();
1998 for (iterator i = id_map.begin(); i != id_map.end(); ++i) {
1999 writeJSON_one(jw, i->second);
2000 }
2001 jw.end_array();
2002 }
2003
readJSON_one(gx_system::JsonParser & jp)2004 Parameter *ParamMap::readJSON_one(gx_system::JsonParser& jp) {
2005 jp.next(gx_system::JsonParser::value_string);
2006 if (jp.current_value() == "FloatEnum") {
2007 return insert(new FloatEnumParameterD(jp));
2008 } else if (jp.current_value() == "Float") {
2009 return insert(new FloatParameter(jp));
2010 } else if (jp.current_value() == "Enum") {
2011 return insert(new EnumParameterD(jp));
2012 } else if (jp.current_value() == "Int") {
2013 return insert(new IntParameter(jp));
2014 } else if (jp.current_value() == "Bool") {
2015 return insert(new BoolParameter(jp));
2016 } else if (jp.current_value() == "File") {
2017 return insert(new FileParameter(jp));
2018 } else if (jp.current_value() == "String") {
2019 return insert(new StringParameter(jp));
2020 } else if (jp.current_value() == "JConv") {
2021 return insert(new JConvParameter(jp));
2022 } else if (jp.current_value() == "Seq") {
2023 return insert(new SeqParameter(jp));
2024 #ifndef NEW_LADSPA
2025 } else if (jp.current_value() == "Osc") {
2026 return insert(new OscParameter(jp));
2027 #endif
2028 } else {
2029 gx_print_warning(
2030 "ParamMap", Glib::ustring::compose("unknown parameter type: %1", jp.current_value()));
2031 jp.skip_object();
2032 return 0;
2033 }
2034 }
2035
readJSON(gx_system::JsonParser & jp)2036 void ParamMap::readJSON(gx_system::JsonParser& jp) {
2037 jp.next(gx_system::JsonParser::begin_array);
2038 while (jp.peek() != gx_system::JsonParser::end_array) {
2039 readJSON_one(jp);
2040 }
2041 jp.next(gx_system::JsonParser::end_array);
2042 }
2043
2044 #ifndef NDEBUG
unique_id(Parameter * param)2045 void ParamMap::unique_id(Parameter* param) {
2046 if (id_map.find(param->id()) != id_map.end()) {
2047 gx_print_error("Debug Check", "id registered twice: " + param->id());
2048 }
2049 }
2050
check_id(const string & id)2051 void ParamMap::check_id(const string& id) {
2052 if (!hasId(id)) {
2053 cerr << "string-id not found: " << id << endl;
2054 }
2055 }
2056
check_p(const char * p)2057 void ParamMap::check_p(const char *p) {
2058 if (!hasId(p)) {
2059 cerr << "char-id not found: " << p << endl;
2060 }
2061 }
2062
dump(const string & fmt)2063 void ParamMap::dump(const string& fmt) {
2064 gx_system::JsonWriter *p = 0;
2065 gx_system::JsonWriter jw;
2066 if (fmt == "json") {
2067 jw.set_stream(&cout);
2068 p = &jw;
2069 jw.begin_array();
2070 jw.newline();
2071 } else {
2072 printf("parameter map dump\n");
2073 }
2074 for (iterator i = id_map.begin(); i != id_map.end(); ++i) {
2075 i->second->dump(p);
2076 }
2077 if (p) {
2078 jw.end_array();
2079 jw.close();
2080 } else {
2081 printf("---------------------\n");
2082 }
2083 }
2084
dump(gx_system::JsonWriter * jw)2085 void Parameter::dump(gx_system::JsonWriter *jw) {
2086 if (jw) {
2087 jw->begin_array();
2088 jw->write(id());
2089 switch (c_type) {
2090 case None: jw->write("None"); break;
2091 case Continuous: jw->write("Cont"); break;
2092 case Switch: jw->write("Swth"); break;
2093 case Enum: jw->write("Enum"); break;
2094 default: assert(false);
2095 }
2096 if (save_in_preset) {
2097 jw->write("preset");
2098 }
2099 if (controllable) {
2100 jw->write("control");
2101 }
2102 jw->write(l_group());
2103 jw->write(l_name());
2104 /*
2105 switch (v_type) {
2106 case tp_float: jw->write("f"); jw->write(getFloat().get_value()); break;
2107 case tp_int: jw->write("i"); jw->write(getInt().get_value()); break;
2108 case tp_bool: jw->write("b"); jw->write(getBool().get_value()); break;
2109 case tp_switch: jw->write("s"); jw->write(getSwitch().get()); break;
2110 case tp_file: jw->write("F"); jw->write(getFile().get_parse_name()); break;
2111 case tp_string: jw->write("S"); jw->write(getString().get_value()); break;
2112 case tp_special: jw->write("G"); break;
2113 default: assert(false);
2114 }
2115 */
2116 jw->write(getLowerAsFloat());
2117 jw->write(getUpperAsFloat());
2118 jw->write(getStepAsFloat());
2119 const value_pair *vn = getValueNames();
2120 if (vn) {
2121 jw->begin_array();
2122 for (int n = 0; ; ++n) {
2123 if (!vn[n].value_id) {
2124 break;
2125 }
2126 jw->begin_array();
2127 jw->write(vn[n].value_id);
2128 jw->write(vn[n].value_label ? vn[n].value_label : vn[n].value_id);
2129 jw->end_array();
2130 }
2131 jw->end_array();
2132 }
2133 jw->end_array();
2134 jw->newline();
2135 } else {
2136 printf("P: %s vt=%d ct=%d c=%d\n", _id.c_str(), v_type, c_type, controllable);
2137 }
2138 }
2139 #endif
2140
insert(Parameter * param)2141 Parameter *ParamMap::insert(Parameter* param) {
2142 if (replace_mode) {
2143 map<string, Parameter*>::iterator ii = id_map.find(param->id());
2144 if (ii != id_map.end()) {
2145 Parameter *p = ii->second;
2146 insert_remove(p,false);
2147 id_map.erase(ii);
2148 delete p;
2149 }
2150 }
2151 debug_check(unique_id, param);
2152 id_map.insert(pair<string, Parameter*>(param->id(), param));
2153 insert_remove(param,true);
2154 return param;
2155 }
2156
unregister(Parameter * p)2157 void ParamMap::unregister(Parameter *p) {
2158 if (!p) {
2159 return;
2160 }
2161 insert_remove(p, false);
2162 id_map.erase(p->id());
2163 delete p;
2164 }
2165
unregister(const string & id)2166 void ParamMap::unregister(const string& id) {
2167 if (!hasId(id)) {
2168 return;
2169 }
2170 unregister(&(*this)[id]);
2171 }
2172
set_init_values()2173 void ParamMap::set_init_values() {
2174 for (iterator i = id_map.begin(); i != id_map.end(); ++i) {
2175 i->second->stdJSON_value();
2176 i->second->setJSON_value();
2177 }
2178 }
2179
compare_groups(const std::string & id,const char ** groups)2180 static inline bool compare_groups(const std::string& id, const char **groups) {
2181 if (!groups) {
2182 return false;
2183 }
2184 for (const char **g = groups; *g; g += 2) {
2185 const char *p = *g;
2186 if ((*p) != '.') {
2187 continue;
2188 }
2189 p++;
2190 int n = strlen(p);
2191 if (strncmp(id.c_str(), p, n) == 0 && id[n] == '.') {
2192 return true;
2193 }
2194 }
2195 return false;
2196 }
2197
unit_has_std_values(const PluginDef * pdef) const2198 bool ParamMap::unit_has_std_values(const PluginDef *pdef) const {
2199 std::string group_id(pdef->id);
2200 group_id += ".";
2201 std::string on_off = group_id + "on_off";
2202 std::string pp = group_id + "pp";
2203 std::string position = group_id + "position";
2204 for (iterator i = begin(); i != end(); ++i) {
2205 if (i->first.compare(0, group_id.size(), group_id) == 0 || compare_groups(i->first, pdef->groups)) {
2206 if (i->second->isInPreset() && !i->second->isOutput()) {
2207 if (i->first != on_off && i->first != pp && i->first != position) {
2208 i->second->stdJSON_value();
2209 if (!i->second->compareJSON_value()) {
2210 return false;
2211 break;
2212 }
2213 }
2214 }
2215 }
2216 }
2217 return true;
2218 }
2219
2220 // reset all parameters to default settings
reset_unit(const PluginDef * pdef) const2221 void ParamMap::reset_unit(const PluginDef *pdef) const {
2222 std::string group_id(pdef->id);
2223 group_id += ".";
2224 std::string on_off = group_id + "on_off";
2225 std::string pp = group_id + "pp";
2226 std::string position = group_id + "position";
2227 for (iterator i = begin(); i != end(); ++i) {
2228 if (i->first.compare(0, group_id.size(), group_id) == 0 || compare_groups(i->first, pdef->groups)) {
2229 if (i->second->isInPreset()) {
2230 if (i->first != on_off && i->first != pp && i->first != position) {
2231 i->second->stdJSON_value();
2232 i->second->setJSON_value();
2233 }
2234 }
2235 }
2236 }
2237 }
2238
2239 } // namespace gx_gui
2240