Guitarix
gx_paramtable.cpp
Go to the documentation of this file.
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 
112  for (unsigned int i = 0; i < sizeof(midi_std_itab)/sizeof(midi_std_itab[0]); i++) {
113  m.insert(pair<int, modstring>(midi_std_itab[i].ctrl, modstring(midi_std_itab[i].name)));
114  }
115 }
116 
117 void MidiStandardControllers::replace(int ctr, const string& name) {
118  map<int, modstring>::iterator i = m.find(ctr);
119  if (name.empty()) {
120  if (i != m.end()) {
121  if (i->second.modified) {
122  if (i->second.std) {
123  i->second.name = m[ctr].std;
124  m[ctr].modified = false;
125  } else {
126  m.erase(i);
127  }
128  }
129  }
130  } else {
131  if (i == m.end()) {
132  m[ctr] = modstring(name, true, 0);
133  } else {
134  i->second.modified = true;
135  i->second.name = name;
136  }
137  }
138 }
139 
141  jw.begin_object(true);
142  for (map<int, modstring>::const_iterator i = m.begin(); i != m.end(); ++i) {
143  if (i->second.modified) {
144  ostringstream ostr;
145  ostr << i->first;
146  jw.write_kv(ostr.str().c_str(), i->second.name);
147  }
148  }
149  jw.end_object(true);
150 }
151 
154  while (jp.peek() == gx_system::JsonParser::value_key) {
155  jp.next();
156  istringstream istr(jp.current_value());
157  int ctl;
158  istr >> ctl;
159  if (istr.fail()) {
160  throw gx_system::JsonException(_("midi standard controllers: number expected"));
161  }
162  jp.next();
163  replace(ctl, jp.current_value());
164  }
166 }
167 
168 
169 /****************************************************************
170  ** class MidiController
171  */
172 
174  jw.begin_array();
175  jw.write(param->id());
176  if (param->getControlType() == Parameter::Continuous ||
177  param->getControlType() == Parameter::Enum) {
178  jw.write(_lower);
179  jw.write(_upper);
180  } else {
181  assert(param->getControlType() == Parameter::Switch);
182  jw.write(toggle);
183  jw.write(_toggle_behaviour);
184  }
185  jw.end_array();
186 }
187 
191  string id = jp.current_value();
192  if (!pmap.hasId(id)) {
193  gx_print_warning(_("Midi controller settings"),
194  _("unknown parameter: ") + id);
195  while (jp.next() != gx_system::JsonParser::end_array);
196  return 0;
197  }
198  Parameter& pm = pmap[id];
199  float lower = 0, upper = 0;
200  bool toggle = false;
201  int toggle_behaviour = 0;
202  bool bad = false;
203  bool chg = false;
209  // two numbers -> range
210  float pmin, pmax;
211  if (pm.hasRange()) {
212  pmin = pm.getLowerAsFloat();
213  pmax = pm.getUpperAsFloat();
214  } else {
215  bad = true;
216  pmin = pmax = 0;
217  }
218  lower = jp.current_value_float();
220  upper = jp.current_value_float();
221  if (lower > pmax) {
222  lower = pmax;
223  chg = true;
224  } else if (lower < pmin) {
225  lower = pmin;
226  chg = true;
227  }
228  if (upper > pmax) {
229  upper = pmax;
230  chg = true;
231  } else if (upper < pmin) {
232  upper = pmin;
233  chg = true;
234  }
235  } else {
236  // just one number -> switch (new format)
237  bad = true;
238  }
239  } else {
240  // no number -> switch (old format)
241  bad = true;
242  }
243  } else if (pm.getControlType() == Parameter::Switch) {
246  int _toggle = jp.current_value_int();
249  if (jp.current_value_int() < Parameter::toggle_type::_Count) {
250  toggle = _toggle;
251  toggle_behaviour = jp.current_value_int();
252  } else {
253  // two numbers -> range
254  bad = true;
255  }
256  } else {
257  toggle = _toggle;
258  }
259  }
260  } else {
261  // bad control type
262  bad = true;
263  }
264  assert(jp.peek() == gx_system::JsonParser::end_array);
265  while (jp.next() != gx_system::JsonParser::end_array); // be tolerant (non-debug mode)
266  if (bad) {
268  _("recall MIDI state"),
269  _("invalid format, Parameter skipped: ") + id);
270  return 0;
271  }
272  if (chg) {
274  _("recall MIDI state"),
275  _("Parameter range outside bounds, changed: ") + id);
276  }
277  return new MidiController(pm, lower, upper, toggle, toggle_behaviour);
278 }
279 
280 bool MidiController::set_midi(int n, int last_value) {
281  bool ret = false;
282  if (param->get_midi_blocked()) return ret;
283  if (toggle) {
284  switch (_toggle_behaviour) {
285  case Parameter::toggle_type::OnOff: {
286  bool s_o = (2*last_value > 127);
287  bool s_n = (2*n > 127);
288  if (!s_o && s_n) {
289  if (param->on_off_value()) {
290  ret = param->midi_set(0, 127, _lower, _upper);
291  } else {
292  ret = param->midi_set(127, 127, _lower, _upper);
293  }
294  }
295  break;
296  }
297  case Parameter::toggle_type::Constant: {
298  if (n == last_value || last_value == -1) {
299  if (param->on_off_value()) {
300  ret = param->midi_set(0, n, _lower, _upper);
301  } else {
302  ret = param->midi_set(127, n, _lower, _upper);
303  }
304  }
305  break;
306  }
307  }
308  } else {
309  //fprintf(stderr,"continues %s \n",param->id().c_str());
310  //fprintf(stderr,"%f \n",(127.*log10f(double(n+1.)))/2.1072);
311  //fprintf(stderr,"%f \n",double(n * double(double(n+1.)/128)));
312  ret = param->midi_set(n, 127, _lower, _upper);
313  }
314  param->trigger_changed();
315  return ret;
316 }
317 
318 bool MidiController::set_trans(int n, int last_value) {
319  bool ret = false;
320  if (param->get_blocked()) return ret;
321  if (strcmp(param->id().c_str(), "engine.mute")==0) {
322  if ( n == 0) n = 127;
323  else n = 0;
324  }
325  ret = param->midi_set(n, 127, _lower, _upper);
326  return ret;
327 }
328 
329 bool MidiController::set_bpm(int n, int last_value) {
330  bool ret = false;
331  if (param->get_blocked()) return ret;
332  if (toggle) {
333  bool s_o = (2*last_value > 360);
334  bool s_n = (2*n > 360);
335  if (!s_o && s_n) {
336  if (param->on_off_value()) {
337  ret = param->midi_set_bpm(0, 360, _lower, _upper);
338  } else {
339  ret = param->midi_set_bpm(360, 360, _lower, _upper);
340  }
341  }
342  } else {
343  ret = param->midi_set_bpm(n, 360, _lower, _upper);
344  }
345  return ret;
346 }
347 
348 /****************************************************************
349  ** class ControllerArray
350  */
351 
353  for (unsigned int n = 0; n < array_size; n++) {
354  operator[](n).clear();
355  }
357  while (jp.peek() != gx_system::JsonParser::end_array) {
359  midi_controller_list& l = operator[](jp.current_value_int());
361  while (jp.peek() != gx_system::JsonParser::end_array) {
363  if (p) {
364  l.push_back(*p);
365  delete p;
366  }
367  }
369  }
371 }
372 
374  w.begin_array(true);
375  for (unsigned int n = 0; n < array_size; n++) {
376  const midi_controller_list& cl = operator[](n);
377  if (cl.empty())
378  continue;
379  w.write(n);
380  w.begin_array();
381  for (midi_controller_list::const_iterator i = cl.begin(); i != cl.end(); ++i)
382  i->writeJSON(w);
383  w.end_array(true);
384  }
385  w.newline();
386  w.end_array(true);
387 }
388 
390  for (ControllerArray::size_type n = 0; n < size(); ++n) {
391  const midi_controller_list& cl = operator[](n);
392  for (midi_controller_list::const_iterator i = cl.begin(); i != cl.end(); ++i) {
393  if (i->hasParameter(param)) {
394  if (p) {
395  *p = &(*i);
396  }
397  return n;
398  }
399  }
400  }
401  return -1;
402 }
403 
405  for (iterator pctr = begin(); pctr != end(); ++pctr) {
406  for (midi_controller_list::iterator i = pctr->begin(); i != pctr->end(); ++i) {
407  if (i->hasParameter(p)) {
408  pctr->erase(i);
409  return true;
410  }
411  }
412  }
413  return false;
414 }
415 
416 
417 /****************************************************************
418  ** class MidiClockToBpm
419  */
420 
421 
423  : time1(0),
424  time_diff(0),
425  collect(0),
426  collect_(0),
427  bpm(0),
428  bpm_new(0),
429  ret(false) {}
430 
431 unsigned int MidiClockToBpm::rounded(float f) {
432  if (f >= 0x1.0p23) return (unsigned int) f;
433  return (unsigned int) (f + 0.49999997f);
434 }
435 
436 bool MidiClockToBpm::time_to_bpm(double time, unsigned int* bpm_) {
437  ret = false;
438  // if time drift to far, reset bpm detection.
439  if ((time-time1)> (1.05*time_diff) || (time-time1)*1.05 < (time_diff)) {
440  bpm = 0;
441  collect = 0;
442  collect_ = 0;
443  } else {
444  bpm_new = ((1000000000. / (time-time1) / 24) * 60);
445  bpm += bpm_new;
446  collect++;
447 
448  if (collect >= (bpm_new*bpm_new*0.0002)+1) {
449  bpm = (bpm/collect);
450  if (collect_>=2) {
451  (*bpm_) = rounded(min(360.,max(24.,bpm)));
452  collect_ = 0;
453  ret = true;
454  }
455  collect_++;
456  collect = 1;
457  }
458  }
459  time_diff = time-time1;
460  time1 = time;
461  return ret;
462 }
463 
464 /****************************************************************
465  ** class MidiControllerList
466  */
467 
469  : map(),
470  last_midi_control_value(),
471  last_midi_control(-2),
472  changed_midi_control_value(),
473  program_change(-1),
474  mute_change(-1),
475  bank_change(-1),
476  time0(0),
477  bpm_(9),
478  mp(),
479  pgm_chg(),
480  mute_chg(),
481  bank_chg(),
482  changed(),
483  new_program(),
484  new_mute_state(),
485  new_bank(),
486  midi_value_changed() {
487  for (int i = 0; i < ControllerArray::array_size; ++i) {
488  last_midi_control_value[i] = -1;
489  changed_midi_control_value[i] = 0;
490  }
491  pgm_chg.connect(sigc::mem_fun(*this, &MidiControllerList::on_pgm_chg));
492  mute_chg.connect(sigc::mem_fun(*this, &MidiControllerList::on_mute_chg));
493  bank_chg.connect(sigc::mem_fun(*this, &MidiControllerList::on_bank_chg));
494  Glib::signal_timeout().connect(
495  sigc::mem_fun(this, &MidiControllerList::check_midi_values), 60);
496 }
497 
498 bool MidiControllerList::check_midi_values() {
499  static int saved_values[ControllerArray::array_size];
500  for (unsigned int n = 0; n < ControllerArray::array_size; ++n) {
501  if (changed_midi_control_value[n]) {
502  changed_midi_control_value[n] = 0;
503  saved_values[n] = last_midi_control_value[n];
504  midi_value_changed(n, saved_values[n]);
505  if (!get_config_mode()) {
506  midi_controller_list& ctr_list = map[n];
507  for (midi_controller_list::iterator i = ctr_list.begin(); i != ctr_list.end(); ++i) {
508  if (i->is_toggle()
509  && i->toggle_behaviour() == Parameter::toggle_type::Constant) {
510  midi_value_changed(n, i->getParameter().on_off_value() * 127);
511  }
512  i->trigger_changed();
513  }
514  }
515  }
516  }
517  return true;
518 }
519 
522  int v = get_last_midi_control_value(ctr);
523  if (v >= 0) {
524  midi_controller_list& cl = map[ctr];
525  for (midi_controller_list::iterator i = cl.begin(); i != cl.end(); ++i) {
526  i->set_midi(v, v);
527  }
528  }
529 }
530 
532  for (unsigned int n = 0; n < map.size(); n++) {
534  }
535 }
536 
537 void MidiControllerList::on_pgm_chg() {
538  int pgm;
539  do {
540  pgm = gx_system::atomic_get(program_change);
541  } while (!gx_system::atomic_compare_and_exchange(&program_change, pgm, -1));
542  if (pgm>=0) new_program(pgm);
543 }
544 
545 void MidiControllerList::on_mute_chg() {
546  int mute;
547  do {
548  mute = gx_system::atomic_get(mute_change);
549  } while (!gx_system::atomic_compare_and_exchange(&mute_change, mute, -1));
550  new_mute_state(mute);
551 }
552 
553 void MidiControllerList::on_bank_chg() {
554  int bk;
555  do {
556  bk = gx_system::atomic_get(bank_change);
557  } while (!gx_system::atomic_compare_and_exchange(&bank_change, bk, -1));
558  if (bk>=0) new_bank(bk);
559 }
560 
561 void MidiControllerList::set_config_mode(bool mode, int ctl) {
562  assert(mode != get_config_mode());
563  if (mode) {
564  last_midi_control = ctl;
565  } else {
566  last_midi_control = -2;
567  }
568 }
569 
571  bool mode = get_config_mode();
572  if (!mode) {
573  set_config_mode(true); // keep rt thread away from table
574  }
575  if (map.deleteParameter(p)) {
576  changed();
577  }
578  if (!mode) {
579  set_config_mode(false);
580  }
581 }
582 
584  float lower, float upper, bool toggle, int toggle_behaviour) {
585  if (!get_config_mode()) {
586  assert(false);
587  return; // keep rt thread away from table
588  }
589  // maximal one controller for a zone allowed
590  deleteParameter(param);
591  if (last_midi_control < 0)
592  return;
593  // add zone to controller
594  map[last_midi_control].push_front(MidiController(param, lower, upper, toggle, toggle_behaviour));
595  update_from_controller(last_midi_control);
596  changed();
597 }
598 
600  for (unsigned int n = 0; n < ControllerArray::array_size; ++n) {
601  int v = last_midi_control_value[n];
602  midi_controller_list& ctr_list = map[n];
603  for (midi_controller_list::iterator i = ctr_list.begin(); i != ctr_list.end(); ++i) {
604  if (i->is_toggle()) {
605  v = i->getParameter().on_off_value() * 127;
606  }
607  midi_value_changed(n, v);
608  }
609  }
610 }
611 
612 void MidiControllerList::set_ctr_val(int ctr, int val) {
613  if (get_config_mode()) {
614  last_midi_control = ctr;
615  } else {
616  midi_controller_list& ctr_list = map[ctr];
617  for (midi_controller_list::iterator i = ctr_list.begin(); i != ctr_list.end(); ++i) {
618  i->set_midi(val, get_last_midi_control_value(ctr));
619  }
620  }
622 }
623 
624 void MidiControllerList::set_bpm_val(unsigned int val) {
625  if (get_config_mode()) {
626  last_midi_control = 22;
627  } else {
628  midi_controller_list& ctr_list = map[22];
629  for (midi_controller_list::iterator i = ctr_list.begin(); i != ctr_list.end(); ++i) {
630  i->set_bpm(val, get_last_midi_control_value(22));
631  }
632  }
634 }
635 
637  bool mode = get_config_mode();
638  if (!mode) {
639  set_config_mode(true); // keep rt thread away from table
640  }
641  map = m;
642  if (!mode) {
643  set_config_mode(false);
644  }
645  changed();
646 }
647 
649  const ControllerArray *new_m) {
650  std::set<Parameter*> pset;
651  for (unsigned int i = 0; i < map.size(); i++) {
652  midi_controller_list& ctr = map[i];
653  for (midi_controller_list::iterator j = ctr.begin(); j != ctr.end(); ++j) {
654  if (new_m) {
655  const midi_controller_list& ctr_new = (*new_m)[i];
656  for (midi_controller_list::const_iterator jn = ctr_new.begin();
657  jn != ctr_new.end(); ++jn) {
658  if (j->getParameter() == jn->getParameter()) {
659  pset.insert(&j->getParameter());
660  break;
661  }
662  }
663  } else {
664  pset.insert(&j->getParameter());
665  }
666  }
667  }
668  for (paramlist::iterator n = plist.begin(); n != plist.end(); ) {
669  paramlist::iterator n1 = n++;
670  if (pset.find(*n1) != pset.end()) {
671  plist.erase(n1);
672  }
673  }
674 }
675 
676 void MidiControllerList::process_trans(int transport_state) {
677  unsigned int val = 0;
678  switch (transport_state) {
679  case JackTransportStopped:
680  val = 0;
681  break;
682  case JackTransportRolling:
683  val = 127;
684  break;
685  case JackTransportStarting:
686  val = 127;
687  break;
688  default:
689  return;
690  }
691  if (get_config_mode()) {
692  last_midi_control = 24;
693  } else {
694  midi_controller_list& ctr_list = map[24];
695  for (midi_controller_list::iterator i = ctr_list.begin(); i != ctr_list.end(); ++i) {
696  i->set_trans(val, get_last_midi_control_value(24));
697  }
698  }
700 }
701 
702 // ----- jack process callback for the midi input
703 void MidiControllerList::compute_midi_in(void* midi_input_port_buf, void *arg) {
704  jack_midi_event_t in_event;
705  jack_nframes_t event_count = jack_midi_get_event_count(midi_input_port_buf);
706  unsigned int i;
707  for (i = 0; i < event_count; i++) {
708  jack_midi_event_get(&in_event, midi_input_port_buf, i);
709  if ((in_event.buffer[0] & 0xf0) == 0xc0) { // program change on any midi channel
710  gx_system::atomic_set(&program_change, in_event.buffer[1]);
711  pgm_chg();
712  } else if ((in_event.buffer[0] & 0xf0) == 0xb0) { // controller
713  if (in_event.buffer[1]== 120) { // engine mute by All Sound Off on any midi channel
714  gx_system::atomic_set(&mute_change, in_event.buffer[2]);
715  mute_chg();
716  } else if (in_event.buffer[1]== 32) { // bank change on any midi channel
717  gx_system::atomic_set(&bank_change, in_event.buffer[2]);
718  bank_chg();
719  } else {
720  set_ctr_val(in_event.buffer[1], in_event.buffer[2]);
721  }
722  } else if ((in_event.buffer[0] ) > 0xf0) { // midi clock
723  if ((in_event.buffer[0] ) == 0xf8) { // midi beat clock
724  clock_gettime(CLOCK_MONOTONIC, &ts1);
725  gx_jack::GxJack& jack = *static_cast<gx_jack::GxJack*>(arg);
726  static unsigned int sr = jack.get_jack_sr();
727  time0 = (ts1.tv_sec*1000000000.0)+(ts1.tv_nsec)+
728  (1000000000.0/(double)(sr/(double)in_event.time));
729  if (mp.time_to_bpm(time0, &bpm_)) {
730  set_bpm_val(bpm_);
731  }
732  } else if ((in_event.buffer[0] ) == 0xfa) { // midi clock start
733  set_ctr_val(23, 127);
734  } else if ((in_event.buffer[0] ) == 0xfb) { // midi clock continue
735  // set_ctr_val(23, 127);
736  } else if ((in_event.buffer[0] ) == 0xfc) { // midi clock stop
737  set_ctr_val(23, 0);
738  } else if ((in_event.buffer[0] ) == 0xf2) { // midi clock position
739  // not implemented
740  // set_ctr_val(24,(in_event.buffer[2]<<7) | in_event.buffer[1]);
741  }
742  }
743  }
744 }
745 
746 /****************************************************************
747  ** Parameter Groups
748  */
749 
751  insert("system", N_("System"));
752  insert("ui", N_("User Interface"));
753  insert("ui.amp", N_("User Interface")); // FIXME (ui.amp.tonestack)
754  insert("engine", N_("Audio Engine"));
755 }
756 
758 #ifndef NDEBUG
759  for (map<string, bool>::iterator i = used.begin(); i != used.end(); ++i) {
760  if (!i->second) {
761  gx_print_error("Debug Check", "Group not used: " + i->first);
762  }
763  }
764 #endif
765 }
766 
767 #ifndef NDEBUG
768 void ParameterGroups::group_exists(const string& id) {
769  if (groups.find(id) == groups.end()) {
770  gx_print_error("Debug Check", "Group does not exist: " + id);
771  } else {
772  used[id] = true;
773  }
774 }
775 
776 void ParameterGroups::group_is_new(const string& id) {
777  if (groups.find(id) != groups.end()) {
778  gx_print_error("Debug Check", "Group already exists: " + id);
779  }
780 }
781 
783  for (map<string, string>::iterator i = groups.begin(); i != groups.end(); ++i) {
784  printf("PG %s: %s\n", i->first.c_str(), i->second.c_str());
785  }
786 }
787 
788 #endif
789 
791  static ParameterGroups groups;
792  return groups;
793 }
794 
795 string param_group(const string& group_id, bool nowarn) {
796  static ParameterGroups& groups = get_group_table();
797  if (nowarn) {
798  return groups.get(group_id);
799  } else {
800  return groups[group_id];
801  }
802 }
803 
804 /****************************************************************
805  ** Parameter
806  */
807 
811  assert(jp.current_value() == key);
812  return jp;
813 }
814 
816  jw.begin_object();
817  jw.write_kv("id", _id);
818  jw.write_kv("name", _name);
819  jw.write_kv("group", _group);
820  jw.write_kv("desc", _desc);
821  jw.write_kv("v_type", v_type); //FIXME
822  jw.write_kv("c_type", c_type); //FIXME
823  jw.write_kv("d_flags", d_flags); //FIXME
824  if (!controllable) {
825  jw.write_key("non_controllable"); jw.write(false);
826  }
827  if (!save_in_preset) {
828  jw.write_key("non_preset"); jw.write(false);
829  }
830  jw.end_object();
831 }
832 
834  : boost::noncopyable(),
835  _id(),
836  _name(),
837  _group(),
838  _desc(),
839  v_type(tp_float),
840  c_type(Continuous),
841  d_flags(0),
842  save_in_preset(true),
843  controllable(true),
844  do_not_save(false),
845  blocked(false),
846  used(false) {
848  while (jp.peek() != gx_system::JsonParser::end_object) {
850  if (jp.read_kv("id", _id) ||
851  jp.read_kv("name", _name) ||
852  jp.read_kv("group", _group) ||
853  jp.read_kv("desc", _desc)) {
854  } else if (jp.current_value() == "v_type") {
856  v_type = static_cast<value_type>(jp.current_value_int());
857  } else if (jp.current_value() == "c_type") {
859  c_type = static_cast<ctrl_type>(jp.current_value_int());
860  } else if (jp.current_value() == "d_flags") {
862  d_flags = jp.current_value_int();
863  } else if (jp.current_value() == "non_controllable") {
865  controllable = false;
866  } else if (jp.current_value() == "non_preset") {
868  save_in_preset = false;
869  } else {
871  "Parameter", Glib::ustring::compose("%1: unknown key: %2", _id, jp.current_value()));
872  jp.skip_object();
873  }
874  }
876 }
877 
879 }
880 
881 bool Parameter::midi_set(float n, float high, float llimit, float ulimit) {
882  assert(false);
883  return false;
884 }
885 
886 bool Parameter::midi_set_bpm(float n, float high, float llimit, float ulimit) {
887  assert(false);
888  return false;
889 }
890 
891 void Parameter::trigger_changed() {
892  assert(false);
893 }
894 
895 static int get_upper(const value_pair *vn) {
896  for (int n = 0; ; n++) {
897  if (!vn[n].value_id) {
898  return n - 1;
899  }
900  }
901 }
902 
903 void Parameter::range_warning(float value, float lower, float upper) {
905  _("parameter load"),
906  Glib::ustring::compose(_("parameter %1: value %2 out of range [%3, %4]"),
907  _id, value, lower, upper));
908 }
909 
910 const char *Parameter::get_typename() const {
911  static const char *tpname[] = {
912  "float", "int", "bool", "bool", "filename", "string", "special"};
913  assert(0 <= v_type and v_type < sizeof(tpname)/sizeof(tpname[0]));
914  return tpname[v_type];
915 }
916 
917 bool Parameter::hasRange() const {
918  return false;
919 }
920 
922  return 1;
923 }
924 
926  return 0;
927 }
928 
930  return 0;
931 }
932 
934  return 0;
935 }
936 
937 #ifndef NDEBUG
938 void compare_parameter(const char *title, Parameter* p1, Parameter* p2, bool all) {
939  if (p1->_id != p2->_id) {
941  title, Glib::ustring::compose("Different ID's: %2 / %3",
942  p1->_id, p2->_id));
943  }
944  if (p1->_name != p2->_name) {
946  title, Glib::ustring::compose("[%1]: Different name: %2 / %3",
947  p1->_id, p1->_name, p2->_name));
948  }
949  if (p1->_group != p2->_group) {
951  title, Glib::ustring::compose("[%1]: Different group: %2 / %3",
952  p1->_id, p1->_group, p2->_group));
953  }
954  if (p1->_desc != p2->_desc) {
956  title, Glib::ustring::compose("[%1]: Different desc: %2 / %3",
957  p1->_id, p1->_desc, p2->_desc));
958  }
959  if (p1->save_in_preset != p2->save_in_preset) {
961  title, Glib::ustring::compose("[%1]: save_in_preset different: %2 / %3",
962  p1->_id, p1->save_in_preset, p2->save_in_preset));
963  }
964  if (p1->controllable != p2->controllable) {
966  title, Glib::ustring::compose("[%1]: controllable different: %2 / %3",
967  p1->_id, p1->controllable, p2->controllable));
968  }
969  if (p1->used != p2->used) {
971  title, Glib::ustring::compose("[%1]: used different: %2 / %3",
972  p1->_id, p1->used, p2->used));
973  }
974  if (p1->c_type != p2->c_type) {
976  title, Glib::ustring::compose("[%1]: c_type different: %2 / %3",
977  p1->_id, p1->c_type, p2->c_type));
978  }
979  if (p1->v_type != p2->v_type) {
981  title, Glib::ustring::compose("[%1]: v_type different: %2 / %3",
982  p1->_id, p1->v_type, p2->v_type));
983  return;
984  }
985  if (p1->isFloat()) {
986  FloatParameter& f1 = p1->getFloat();
987  FloatParameter& f2 = p2->getFloat();
988  if (f1.value != f2.value) {
990  title, Glib::ustring::compose("[%1]: value address different: %2 / %3",
991  p1->_id, f1.value, f2.value));
992  }
993  if (f1.lower != f2.lower) {
995 
996  title, Glib::ustring::compose("[%1]: float lower different: %2 / %3",
997  p1->_id, f1.lower, f2.lower));
998  }
999  if (f1.upper != f2.upper) {
1001  title, Glib::ustring::compose("[%1]: float upper different: %2 / %3",
1002  p1->_id, f1.upper, f2.upper));
1003  }
1004  if (f1.step != f2.step) {
1006  title, Glib::ustring::compose("[%1]: float step different: %2 / %3",
1007  p1->_id, f1.step, f2.step));
1008  }
1009  if (f1.std_value != f2.std_value) {
1011  title, Glib::ustring::compose("[%1]: float std value different: %2 / %3",
1012  p1->_id, f1.std_value, f2.std_value));
1013  }
1014  if (all) {
1015  if (f1.value != f2.value) {
1017  title, Glib::ustring::compose("[%1]: float value different: %2 / %3",
1018  p1->_id, *f1.value, *f2.value));
1019  }
1020  if (f1.json_value != f2.json_value) {
1022  title, Glib::ustring::compose("[%1]: float json value different: %2 / %3",
1023  p1->_id, f1.json_value, f2.json_value));
1024  }
1025  }
1026  return;
1027  }
1028  if (p1->isInt()) {
1029  assert(false);
1030  return;
1031  }
1032  if (p1->isBool()) {
1033  assert(false);
1034  return;
1035  }
1036  if (p1->isFile()) {
1037  assert(false);
1038  return;
1039  }
1040  assert(false);
1041 }
1042 #endif
1043 
1044 /* FloatParameter */
1045 
1047  jw.begin_object();
1048  jw.write_key("Parameter"); Parameter::serializeJSON(jw);
1049  jw.write_kv("lower", lower);
1050  jw.write_kv("upper", upper);
1051  jw.write_kv("step", step);
1052  jw.write_kv("value", *value);
1053  jw.write_kv("std_value", std_value);
1054  jw.end_object();
1055 }
1056 
1058  : Parameter(jp_next(jp, "Parameter")), json_value(0), value(&value_storage), std_value(0), lower(), upper(), step() {
1059  while (jp.peek() != gx_system::JsonParser::end_object) {
1061  if (jp.read_kv("lower", lower) ||
1062  jp.read_kv("upper", upper) ||
1063  jp.read_kv("step", step) ||
1064  jp.read_kv("value", *value) ||
1065  jp.read_kv("std_value", std_value)) {
1066  } else {
1068  "FloatParameter", Glib::ustring::compose("%1: unknown key: %2", _id, jp.current_value()));
1069  jp.skip_object();
1070  }
1071  }
1073 }
1074 
1076 }
1077 
1078 bool FloatParameter::set(float val) const {
1079  float v = min(max(val, lower), upper);
1080  if (v != *value) {
1081  *value = v;
1082  changed(v);
1083  return true;
1084  }
1085  return false;
1086 }
1087 
1089  return *value != 0;
1090 }
1091 
1092 float FloatParameter::idx_from_id(string v_id) {
1093  assert(false);
1094  return 0;
1095 }
1096 
1097 bool FloatParameter::midi_set(float n, float high, float llimit, float ulimit) {
1098  float v;
1099  switch (c_type) {
1100  case Continuous:
1101  assert(n >= 0 && n <= high);
1102  v = llimit + (n / high) * (ulimit - llimit);
1103  break;
1104  case Switch:
1105  v = (2*n > high ? 1.0 : 0.0);
1106  break;
1107  case Enum:
1108  v = lower + min(n, upper-lower);
1109  break;
1110  default:
1111  assert(false);
1112  return false;
1113  }
1114  if (v != *value) {
1115  *value = v;
1116  return true;
1117  }
1118  return false;
1119 }
1120 
1121 bool FloatParameter::midi_set_bpm(float n, float high, float llimit, float ulimit) {
1122  float v;
1123  switch (c_type) {
1124  case Continuous:
1125  assert(n >= 0 && n <= high);
1126  if (high <= ulimit) {
1127  v = max(llimit,min(ulimit,n));
1128  } else {
1129  v = llimit + (n / high) * (ulimit - llimit);
1130  }
1131  break;
1132  case Switch:
1133  v = (2*n > high ? 1.0 : 0.0);
1134  break;
1135  case Enum:
1136  v = lower + min(n, upper-lower);
1137  break;
1138  default:
1139  assert(false);
1140  return false;
1141  }
1142  if (v != *value) {
1143  *value = v;
1144  return true;
1145  }
1146  return false;
1147 }
1148 
1149 void FloatParameter::trigger_changed() {
1150  changed(*value);
1151 }
1152 
1154  json_value = std_value;
1155 }
1156 
1158  jw.write_kv(_id.c_str(), *value);
1159 }
1160 
1163  json_value = jp.current_value_float();
1164  if (json_value < lower-std::abs(5*FLT_EPSILON*lower) || json_value > upper+std::abs(5*FLT_EPSILON*upper)) {
1165  range_warning(json_value, lower, upper);
1166  json_value = std_value;
1167  }
1168 }
1169 
1171  return std::abs(json_value - *value) < 5*FLT_EPSILON;
1172 }
1173 
1175  set(json_value);
1176 }
1177 
1178 void FloatParameter::convert_from_range(float low, float up) {
1179  json_value = lower + (json_value - low) / (up - low) * (upper - lower);
1180 }
1181 
1183  return true;
1184 }
1185 
1187  return lower;
1188 }
1189 
1191  return upper;
1192 }
1193 
1195  return step;
1196 }
1197 
1198 
1199 /* FloatEnumParameter */
1200 
1201 static void serializeValueNames(gx_system::JsonWriter& jw, const value_pair *p) {
1202  jw.write_key("value_names");
1203  jw.begin_array();
1204  while (p->value_id) {
1205  jw.write(p->value_id);
1206  if (p->value_label) {
1207  jw.write(p->value_label);
1208  } else {
1209  jw.write(p->value_id);
1210  }
1211  p++;
1212  }
1213  jw.end_array();
1214 }
1215 
1217  jw.begin_object();
1218  jw.write_key("FloatParameter"); FloatParameter::serializeJSON(jw);
1219  serializeValueNames(jw, value_names);
1220  jw.end_object();
1221 }
1222 
1223 FloatEnumParameter::FloatEnumParameter(const string& id, const string& name, const value_pair* vn, bool preset,
1224  float *v, int sv, int low, bool ctrl, bool no_init):
1225  FloatParameter(id, name, Enum, preset, v, sv, low, low+get_upper(vn), 1, ctrl, no_init),
1226  value_names(vn) {}
1227 
1229  return value_names;
1230 }
1231 
1233  jw.write_key(_id.c_str());
1234  jw.write(value_names[static_cast<int>(round(*value-lower))].value_id);
1235 }
1236 
1238  int up = static_cast<int>(round(upper));
1239  int low = static_cast<int>(round(lower));
1240  int n = 0;
1241  for (; n <= up-low; n++) {
1242  if (v_id == value_names[n].value_id) {
1243  return low + n;
1244  }
1245  }
1246  return -1;
1247 }
1248 
1252  // old version compatability
1253  json_value = jp.current_value_int();
1254  return;
1255  }
1257  float n = idx_from_id(jp.current_value());
1258  if (n < 0) {
1260  _("read parameter"), (boost::format(_("parameter %1%: unknown enum value: %2%"))
1261  % _id % jp.current_value()).str());
1262  n = lower;
1263  }
1264  json_value = n;
1265 }
1266 
1267 /* IntParameter */
1268 
1270  jw.begin_object();
1271  jw.write_key("Parameter"); Parameter::serializeJSON(jw);
1272  jw.write_kv("lower", lower);
1273  jw.write_kv("upper", upper);
1274  jw.write_kv("value", *value);
1275  jw.write_kv("std_value", std_value);
1276  jw.end_object();
1277 }
1278 
1280  : Parameter(jp_next(jp, "Parameter")), json_value(0), value(&value_storage), std_value(0), lower(), upper() {
1281  while (jp.peek() != gx_system::JsonParser::end_object) {
1283  if (jp.read_kv("lower", lower) ||
1284  jp.read_kv("upper", upper) ||
1285  jp.read_kv("value", *value) ||
1286  jp.read_kv("std_value", std_value)) {
1287  } else {
1289  "IntParameter", Glib::ustring::compose("%1: unknown key: %2", _id, jp.current_value()));
1290  jp.skip_object();
1291  }
1292  }
1294 }
1295 
1297 }
1298 
1299 bool IntParameter::set(int val) const {
1300  int v = min(max(val, lower), upper);
1301  if (v != *value) {
1302  *value = v;
1303  changed(v);
1304  return true;
1305  }
1306  return false;
1307 }
1308 
1309 int IntParameter::idx_from_id(string v_id) {
1310  assert(false);
1311  return 0;
1312 }
1313 
1315  return *value != 0;
1316 }
1317 
1318 bool IntParameter::midi_set(float n, float high, float llimit, float ulimit) {
1319  int v;
1320  switch (c_type) {
1321  case Continuous:
1322  assert(false); // not implemented
1323  return false;
1324  case Switch:
1325  assert(false); // not implemented
1326  return false;
1327  case Enum:
1328  v = lower + min(static_cast<int>(n), upper-lower);
1329  break;
1330  default:
1331  assert(false);
1332  return false;
1333  }
1334  if (v != *value) {
1335  *value = v;
1336  return true;
1337  }
1338  return false;
1339 }
1340 
1341 void IntParameter::trigger_changed() {
1342  changed(*value);
1343 }
1344 
1346  json_value = std_value;
1347 }
1348 
1350  jw.write_kv(_id.c_str(), *value);
1351 }
1352 
1355  json_value = jp.current_value_int();
1356  if (json_value < lower || json_value > upper) {
1357  range_warning(json_value, lower, upper);
1358  }
1359 }
1360 
1362  return json_value == *value;
1363 }
1364 
1366  set(json_value);
1367 }
1368 
1370  return true;
1371 }
1372 
1374  return lower;
1375 }
1376 
1378  return upper;
1379 }
1380 
1381 /* EnumParameter */
1382 
1384  jw.begin_object();
1385  jw.write_key("IntParameter"); IntParameter::serializeJSON(jw);
1386  serializeValueNames(jw, value_names);
1387  jw.end_object();
1388 }
1389 
1390 EnumParameter::EnumParameter(const string& id, const string& name, const value_pair* vn, bool preset,
1391  int *v, int sv, bool ctrl):
1392  IntParameter(id, name, Enum, preset, v, sv, 0, get_upper(vn), ctrl),
1393  value_names(vn) {}
1394 
1396  return value_names;
1397 }
1398 
1399 int EnumParameter::idx_from_id(string v_id) {
1400  int n = 0;
1401  for (; n <= upper; n++) {
1402  if (v_id == value_names[n].value_id) {
1403  return n;
1404  }
1405  }
1406  return -1;
1407 }
1408 
1410  jw.write_key(_id.c_str());
1411  jw.write(value_names[*value].value_id);
1412 }
1413 
1417  // old version compatability
1418  json_value = jp.current_value_int();
1419  return;
1420  }
1422  int n = idx_from_id(jp.current_value());
1423  if (n < 0) {
1425  _("read parameter"), (boost::format(_("parameter %1%: unknown enum value: %2%"))
1426  % _id % jp.current_value()).str());
1427  n = 0;
1428  }
1429  json_value = n;
1430 }
1431 
1432 /* derived enum parameters */
1433 
1434 typedef std::pair<std::string,std::string> id_label;
1435 
1436 void enum_parameter_load_values(gx_system::JsonParser& jp, std::vector<id_label>& value_array, const value_pair **value_names) {
1437  while (jp.peek() != gx_system::JsonParser::end_object) {
1439  if (jp.current_value() == "value_names") {
1441  while (jp.peek() != gx_system::JsonParser::end_array) {
1443  std::string value_id = jp.current_value();
1445  std::string value_label = jp.current_value();
1446  value_array.push_back(id_label(value_id, value_label));
1447  }
1449  } else {
1451  "EnumValueNames", Glib::ustring::compose("unknown key: %1", jp.current_value()));
1452  jp.skip_object();
1453  }
1454  }
1456  value_pair* p = new value_pair[value_array.size()+1];
1457  *value_names = p;
1458  for (std::vector<id_label>::iterator i = value_array.begin(); i != value_array.end(); ++i) {
1459  p->value_id = i->first.c_str();
1460  p->value_label = i->second.c_str();
1461  p++;
1462  }
1463  p->value_id = p->value_label = 0;
1464 }
1465 
1467 private:
1468  std::vector<id_label> value_array;
1469 public:
1472 };
1473 
1475  : FloatEnumParameter(jp), value_array() {
1476  enum_parameter_load_values(jp, value_array, &value_names);
1477 }
1478 
1480  delete value_names;
1481 }
1482 
1484 private:
1485  std::vector<id_label> value_array;
1486 public:
1488  ~EnumParameterD();
1489 };
1490 
1492  : EnumParameter(jp), value_array() {
1493  enum_parameter_load_values(jp, value_array, &value_names);
1494 }
1495 
1497  delete value_names;
1498 }
1499 
1500 
1501 /* BoolParameter */
1502 
1504  jw.begin_object();
1505  jw.write_key("Parameter"); Parameter::serializeJSON(jw);
1506  jw.write_kv("value", *value);
1507  jw.write_kv("std_value", std_value);
1508  jw.end_object();
1509 }
1510 
1512  : Parameter(jp_next(jp, "Parameter")), json_value(0), value(&value_storage), std_value(0) {
1513  while (jp.peek() != gx_system::JsonParser::end_object) {
1515  if (jp.read_kv("value", *value) || jp.read_kv("std_value", std_value)) {
1516  } else {
1518  "BoolParameter", Glib::ustring::compose("%1: unknown key: %2", _id, jp.current_value()));
1519  jp.skip_object();
1520  }
1521  }
1523 }
1524 
1526 }
1527 
1528 bool BoolParameter::set(bool val) const {
1529  if (val != *value) {
1530  *value = val;
1531  changed(val);
1532  return true;
1533  }
1534  return false;
1535 }
1536 
1538  return *value;
1539 }
1540 
1541 bool BoolParameter::midi_set(float n, float high, float llimit, float ulimit) {
1542  bool v;
1543  switch (c_type) {
1544  case Switch:
1545  v = (2*n > high);
1546  break;
1547  default:
1548  assert(false);
1549  return false;
1550  }
1551  if (v != *value) {
1552  *value = v;
1553  return true;
1554  }
1555  return false;
1556 }
1557 
1558 void BoolParameter::trigger_changed() {
1559  changed(*value);
1560 }
1561 
1563  json_value = std_value;
1564 }
1565 
1567  jw.write_kv(_id.c_str(), *value);
1568 }
1569 
1572  if (jp.current_value_int() < 0 || jp.current_value_int() > 1) {
1573  range_warning(json_value, 0, 1);
1574  }
1575  json_value = jp.current_value_int();
1576 }
1577 
1579  return json_value == *value;
1580 }
1581 
1583  set(json_value);
1584 }
1585 
1586 
1587 /* FileParameter */
1588 
1590  jw.begin_object();
1591  jw.write_key("Parameter"); Parameter::serializeJSON(jw);
1592  jw.write_kv("value", value->get_path());
1593  jw.write_kv("std_value", std_value->get_path());
1594  jw.end_object();
1595 }
1596 
1598  : Parameter(jp_next(jp, "Parameter")), value(0), std_value(0), json_value(0) {
1599  while (jp.peek() != gx_system::JsonParser::end_object) {
1601  if (jp.current_value() == "value") {
1603  value = Gio::File::create_for_path(jp.current_value());
1604  } else if (jp.current_value() == "std_value") {
1606  std_value = Gio::File::create_for_path(jp.current_value());
1607  } else {
1609  "FileParameter", Glib::ustring::compose("%1: unknown key: %2", _id, jp.current_value()));
1610  jp.skip_object();
1611  }
1612  }
1614 }
1615 
1616 void FileParameter::set_path(const string& path) {
1617  Glib::RefPtr<Gio::File> v = Gio::File::create_for_path(path);
1618  if (is_equal(v)) {
1619  return;
1620  }
1621  value = v;
1622  changed();
1623 }
1624 
1625 bool FileParameter::set(const Glib::RefPtr<Gio::File>& val) {
1626  if (is_equal(val)) {
1627  return false;
1628  }
1629  value = val;
1630  changed();
1631  return true;
1632 }
1633 
1634 void FileParameter::set_standard(const string& filename) {
1635  std_value = Gio::File::create_for_path(filename);
1636  if (!value) {
1637  value = std_value->dup();
1638  changed();
1639  }
1640 }
1641 
1643  json_value = std_value->dup();
1644  changed();
1645 }
1646 
1648  return bool(value);
1649 }
1650 
1652  jw.write_kv(_id.c_str(), get_path());
1653 }
1654 
1657  json_value = Gio::File::create_for_path(jp.current_value());
1658 }
1659 
1661  return json_value->get_path() == value->get_path(); //FIXME
1662 }
1663 
1665  set(json_value);
1666 }
1667 
1668 static string get_file_id(const Glib::RefPtr<Gio::File>& f) {
1669  return f->query_info(G_FILE_ATTRIBUTE_ID_FILE)->get_attribute_string(G_FILE_ATTRIBUTE_ID_FILE);
1670 }
1671 
1672 bool FileParameter::is_equal(const Glib::RefPtr<Gio::File>& v) const {
1673  string id, id2;
1674  try {
1675  id = get_file_id(value);
1676  } catch(Gio::Error& ex) {
1677  return false; // FIXME check type of exception
1678  }
1679  try {
1680  id2 = get_file_id(v);
1681  } catch(Gio::Error& ex) {
1682  return false; // FIXME check type of exception
1683  }
1684  return id == id2;
1685 }
1686 
1687 string FileParameter::get_path() const {
1688  return value->get_path();
1689 }
1690 
1692  return value->get_parent()->get_path();
1693 }
1694 
1696  return value->get_parse_name();
1697 }
1698 
1700  return value->query_info(G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME)->get_display_name();
1701 }
1702 
1703 void FileParameter::copy(const string& destination) const {
1704  value->copy(Gio::File::create_for_path(destination));
1705 }
1706 
1707 
1708 /* StringParameter */
1709 
1711  jw.begin_object();
1712  jw.write_key("Parameter"); Parameter::serializeJSON(jw);
1713  jw.write_kv("value", *value);
1714  jw.write_kv("std_value", std_value);
1715  jw.end_object();
1716 }
1717 
1719  : Parameter(jp_next(jp, "Parameter")), json_value(""), value(&value_storage), std_value("") {
1720  while (jp.peek() != gx_system::JsonParser::end_object) {
1722  if (jp.read_kv("value", *value) || jp.read_kv("std_value", std_value)) {
1723  } else {
1725  "StringParameter", Glib::ustring::compose("%1: unknown key: %2", _id, jp.current_value()));
1726  jp.skip_object();
1727  }
1728  }
1730 }
1731 
1733 }
1734 
1735 bool StringParameter::set(const Glib::ustring& val) const {
1736  if (val != *value) {
1737  *value = val;
1738  changed(*value);
1739  return true;
1740  }
1741  return false;
1742 }
1743 
1745  return !value->empty();
1746 }
1747 
1749  json_value = std_value;
1750 }
1751 
1753  jw.write_kv(_id.c_str(), *value);
1754 }
1755 
1758  json_value = jp.current_value();
1759 }
1760 
1762  return json_value == *value;
1763 }
1764 
1766  set(json_value);
1767 }
1768 
1769 /****************************************************************
1770  ** Parameter Map
1771  */
1772 
1774  : id_map(),
1775  replace_mode(false) {
1776 }
1777 
1779  for (iterator i = id_map.begin(); i != id_map.end(); ++i) {
1780  delete i->second;
1781  }
1782 }
1783 
1785  if (p->isFloat()) {
1786  if (p->getControlType() == Parameter::Enum) {
1787  jw.write("FloatEnum");
1788  } else {
1789  jw.write("Float");
1790  }
1791  } else if (p->isInt()) {
1792  if (p->getControlType() == Parameter::Enum) {
1793  jw.write("Enum");
1794  } else {
1795  jw.write("Int");
1796  }
1797  } else if (p->isBool()) {
1798  jw.write("Bool");
1799  } else if (p->isFile()) {
1800  jw.write("File");
1801  } else if (p->isString()) {
1802  jw.write("String");
1803  } else if (dynamic_cast<JConvParameter*>(p) != 0) {
1804  jw.write("JConv");
1805  } else if (dynamic_cast<SeqParameter*>(p) != 0) {
1806  jw.write("Seq");
1807  } else {
1808 #ifndef NDEBUG
1809  cerr << "skipping " << p->id() << endl;
1810 #endif
1811  return;
1812  }
1813  p->serializeJSON(jw);
1814 }
1815 
1817  jw.begin_array();
1818  for (iterator i = id_map.begin(); i != id_map.end(); ++i) {
1819  writeJSON_one(jw, i->second);
1820  }
1821  jw.end_array();
1822 }
1823 
1826  if (jp.current_value() == "FloatEnum") {
1827  return insert(new FloatEnumParameterD(jp));
1828  } else if (jp.current_value() == "Float") {
1829  return insert(new FloatParameter(jp));
1830  } else if (jp.current_value() == "Enum") {
1831  return insert(new EnumParameterD(jp));
1832  } else if (jp.current_value() == "Int") {
1833  return insert(new IntParameter(jp));
1834  } else if (jp.current_value() == "Bool") {
1835  return insert(new BoolParameter(jp));
1836  } else if (jp.current_value() == "File") {
1837  return insert(new FileParameter(jp));
1838  } else if (jp.current_value() == "String") {
1839  return insert(new StringParameter(jp));
1840  } else if (jp.current_value() == "JConv") {
1841  return insert(new JConvParameter(jp));
1842  } else if (jp.current_value() == "Seq") {
1843  return insert(new SeqParameter(jp));
1844  } else {
1846  "ParamMap", Glib::ustring::compose("unknown parameter type: %1", jp.current_value()));
1847  jp.skip_object();
1848  return 0;
1849  }
1850 }
1851 
1854  while (jp.peek() != gx_system::JsonParser::end_array) {
1855  readJSON_one(jp);
1856  }
1858 }
1859 
1860 #ifndef NDEBUG
1861 void ParamMap::unique_id(Parameter* param) {
1862  if (id_map.find(param->id()) != id_map.end()) {
1863  gx_print_error("Debug Check", "id registered twice: " + param->id());
1864  }
1865 }
1866 
1867 void ParamMap::check_id(const string& id) {
1868  if (!hasId(id)) {
1869  cerr << "string-id not found: " << id << endl;
1870  }
1871 }
1872 
1873 void ParamMap::check_p(const char *p) {
1874  if (!hasId(p)) {
1875  cerr << "char-id not found: " << p << endl;
1876  }
1877 }
1878 
1879 void ParamMap::dump(const string& fmt) {
1880  gx_system::JsonWriter *p = 0;
1882  if (fmt == "json") {
1883  jw.set_stream(&cout);
1884  p = &jw;
1885  jw.begin_array();
1886  jw.newline();
1887  } else {
1888  printf("parameter map dump\n");
1889  }
1890  for (iterator i = id_map.begin(); i != id_map.end(); ++i) {
1891  i->second->dump(p);
1892  }
1893  if (p) {
1894  jw.end_array();
1895  jw.close();
1896  } else {
1897  printf("---------------------\n");
1898  }
1899 }
1900 
1902  if (jw) {
1903  jw->begin_array();
1904  jw->write(id());
1905  switch (c_type) {
1906  case None: jw->write("None"); break;
1907  case Continuous: jw->write("Cont"); break;
1908  case Switch: jw->write("Swth"); break;
1909  case Enum: jw->write("Enum"); break;
1910  default: assert(false);
1911  }
1912  if (save_in_preset) {
1913  jw->write("preset");
1914  }
1915  if (controllable) {
1916  jw->write("control");
1917  }
1918  jw->write(l_group());
1919  jw->write(l_name());
1920  /*
1921  switch (v_type) {
1922  case tp_float: jw->write("f"); jw->write(getFloat().get_value()); break;
1923  case tp_int: jw->write("i"); jw->write(getInt().get_value()); break;
1924  case tp_bool: jw->write("b"); jw->write(getBool().get_value()); break;
1925  case tp_switch: jw->write("s"); jw->write(getSwitch().get()); break;
1926  case tp_file: jw->write("F"); jw->write(getFile().get_parse_name()); break;
1927  case tp_string: jw->write("S"); jw->write(getString().get_value()); break;
1928  case tp_special: jw->write("G"); break;
1929  default: assert(false);
1930  }
1931  */
1932  jw->write(getLowerAsFloat());
1933  jw->write(getUpperAsFloat());
1934  jw->write(getStepAsFloat());
1935  const value_pair *vn = getValueNames();
1936  if (vn) {
1937  jw->begin_array();
1938  for (int n = 0; ; ++n) {
1939  if (!vn[n].value_id) {
1940  break;
1941  }
1942  jw->begin_array();
1943  jw->write(vn[n].value_id);
1944  jw->write(vn[n].value_label ? vn[n].value_label : vn[n].value_id);
1945  jw->end_array();
1946  }
1947  jw->end_array();
1948  }
1949  jw->end_array();
1950  jw->newline();
1951  } else {
1952  printf("P: %s vt=%d ct=%d c=%d\n", _id.c_str(), v_type, c_type, controllable);
1953  }
1954 }
1955 #endif
1956 
1957 Parameter *ParamMap::insert(Parameter* param) {
1958  if (replace_mode) {
1959  map<string, Parameter*>::iterator ii = id_map.find(param->id());
1960  if (ii != id_map.end()) {
1961  Parameter *p = ii->second;
1962  insert_remove(p,false);
1963  id_map.erase(ii);
1964  delete p;
1965  }
1966  }
1967  debug_check(unique_id, param);
1968  id_map.insert(pair<string, Parameter*>(param->id(), param));
1969  insert_remove(param,true);
1970  return param;
1971 }
1972 
1974  if (!p) {
1975  return;
1976  }
1977  insert_remove(p, false);
1978  id_map.erase(p->id());
1979  delete p;
1980 }
1981 
1982 void ParamMap::unregister(const string& id) {
1983  if (!hasId(id)) {
1984  return;
1985  }
1986  unregister(&(*this)[id]);
1987 }
1988 
1990  for (iterator i = id_map.begin(); i != id_map.end(); ++i) {
1991  i->second->stdJSON_value();
1992  i->second->setJSON_value();
1993  }
1994 }
1995 
1996 static inline bool compare_groups(const std::string& id, const char **groups) {
1997  if (!groups) {
1998  return false;
1999  }
2000  for (const char **g = groups; *g; g += 2) {
2001  const char *p = *g;
2002  if ((*p) != '.') {
2003  continue;
2004  }
2005  p++;
2006  int n = strlen(p);
2007  if (strncmp(id.c_str(), p, n) == 0 && id[n] == '.') {
2008  return true;
2009  }
2010  }
2011  return false;
2012 }
2013 
2014 bool ParamMap::unit_has_std_values(const PluginDef *pdef) const {
2015  std::string group_id(pdef->id);
2016  group_id += ".";
2017  std::string on_off = group_id + "on_off";
2018  std::string pp = group_id + "pp";
2019  std::string position = group_id + "position";
2020  for (iterator i = begin(); i != end(); ++i) {
2021  if (i->first.compare(0, group_id.size(), group_id) == 0 || compare_groups(i->first, pdef->groups)) {
2022  if (i->second->isInPreset()) {
2023  if (i->first != on_off && i->first != pp && i->first != position) {
2024  i->second->stdJSON_value();
2025  if (!i->second->compareJSON_value()) {
2026  return false;
2027  break;
2028  }
2029  }
2030  }
2031  }
2032  }
2033  return true;
2034 }
2035 
2036 // reset all parameters to default settings
2037 void ParamMap::reset_unit(const PluginDef *pdef) const {
2038  std::string group_id(pdef->id);
2039  group_id += ".";
2040  std::string on_off = group_id + "on_off";
2041  std::string pp = group_id + "pp";
2042  std::string position = group_id + "position";
2043  for (iterator i = begin(); i != end(); ++i) {
2044  if (i->first.compare(0, group_id.size(), group_id) == 0 || compare_groups(i->first, pdef->groups)) {
2045  if (i->second->isInPreset()) {
2046  if (i->first != on_off && i->first != pp && i->first != position) {
2047  i->second->stdJSON_value();
2048  i->second->setJSON_value();
2049  }
2050  }
2051  }
2052  }
2053 }
2054 
2055 } // namespace gx_gui
ParameterV< float > FloatParameter
Definition: gx_parameter.h:92
ParameterV< GxSeqSettings > SeqParameter
CmdConnection::msg_type end
Definition: jsonrpc.cpp:256
int get_last_midi_control_value(unsigned int n)
Definition: gx_parameter.h:775
void write_kv(const char *key, float v)
Definition: gx_json.h:81
FloatEnumParameter(gx_system::JsonParser &jp)
Definition: gx_parameter.h:278
virtual float getUpperAsFloat() const
virtual float getLowerAsFloat() const
virtual void readJSON_value(gx_system::JsonParser &jp)
bool set_bpm(int n, int last_value)
void begin_array(bool nl=false)
Definition: gx_json.cpp:184
void modifyCurrent(Parameter &param, float lower, float upper, bool toggle, int toggle_behaviour)
int param2controller(Parameter &param, const MidiController **p)
ParameterV(const string &id, const string &name, ctrl_type ctp, bool preset, int *v, int sv, int lv, int uv, bool ctrl)
Definition: gx_parameter.h:316
virtual bool hasRange() const
virtual int idx_from_id(string v_id)
void set_stream(ostream *o)
Definition: gx_json.h:70
enum ctrl_type c_type
Definition: gx_parameter.h:120
jack_nframes_t get_jack_sr()
Definition: gx_jack.h:178
MidiStandardControllers midi_std_ctr
map< string, Parameter * >::const_iterator iterator
Definition: gx_parameter.h:532
Parameter(const string &id, const string &name, value_type vtp, ctrl_type ctp, bool preset, bool ctrl)
Definition: gx_parameter.h:133
virtual void serializeJSON(gx_system::JsonWriter &jw)
virtual void readJSON_value(gx_system::JsonParser &jp)
Parameter * readJSON_one(gx_system::JsonParser &jp)
friend void compare_parameter(const char *title, Parameter *p1, Parameter *p2, bool all)
list< Parameter * > paramlist
Definition: gx_parameter.h:220
ParameterV< GxJConvSettings > JConvParameter
virtual void serializeJSON(gx_system::JsonWriter &jw)
void unregister(Parameter *p)
virtual bool hasRange() const
bool deleteParameter(Parameter &p)
void end_array(bool nl=false)
Definition: gx_json.cpp:192
void set_config_mode(bool mode, int ctl=-1)
const string & name() const
Definition: gx_parameter.h:175
void dump(const string &fmt)
virtual void readJSON_value(gx_system::JsonParser &jp)
bool isBool() const
Definition: gx_parameter.h:164
bool isFile() const
Definition: gx_parameter.h:165
void readJSON(gx_system::JsonParser &jp, ParamMap &param)
const char * value_id
Definition: gx_plugin.h:118
virtual bool compareJSON_value()
#define N_(String)
void range_warning(float value, float lower, float upper)
virtual void readJSON_value(gx_system::JsonParser &jp)
unsigned int rounded(float f)
virtual float getUpperAsFloat() const
bool set(const Glib::ustring &val) const
virtual float idx_from_id(string v_id)
virtual void writeJSON(gx_system::JsonWriter &jw) const
void writeJSON(gx_system::JsonWriter &jw)
string param_group(const string &group_id, bool nowarn=false)
bool isString() const
Definition: gx_parameter.h:166
virtual void writeJSON(gx_system::JsonWriter &jw) const
string get(const string &id)
Definition: gx_parameter.h:62
virtual float getUpperAsFloat() const
virtual float getLowerAsFloat() const
iterator end() const
Definition: gx_parameter.h:534
virtual void writeJSON(gx_system::JsonWriter &jw) const
ctrl_type getControlType() const
Definition: gx_parameter.h:167
bool isInt() const
Definition: gx_parameter.h:163
void write_key(const char *p, bool nl=false)
Definition: gx_json.cpp:200
void writeJSON(gx_system::JsonWriter &jw) const
const char ** groups
Definition: gx_plugin.h:187
int atomic_get(volatile int &p)
Definition: gx_system.h:98
Glib::RefPtr< Gio::File > std_value
Definition: gx_parameter.h:386
FloatEnumParameterD(gx_system::JsonParser &jp)
EnumParameter(gx_system::JsonParser &jp)
Definition: gx_parameter.h:333
ParameterV< int > IntParameter
Definition: gx_parameter.h:95
void compute_midi_in(void *midi_input_port_buf, void *arg)
sigc::signal< void > changed
Definition: gx_parameter.h:388
virtual void serializeJSON(gx_system::JsonWriter &jw)
ParameterV< bool > BoolParameter
Definition: gx_parameter.h:96
virtual float getStepAsFloat() const
#define debug_check(func,...)
Definition: gx_parameter.h:36
void gx_print_error(const char *, const std::string &)
Definition: gx_logging.cpp:166
bool read_kv(const char *key, float &v)
Definition: gx_json.cpp:511
virtual void readJSON_value(gx_system::JsonParser &jp)
void enum_parameter_load_values(gx_system::JsonParser &jp, std::vector< id_label > &value_array, const value_pair **value_names)
virtual float getLowerAsFloat() const
ParameterGroups & get_group_table()
bool time_to_bpm(double time, unsigned int *bpm_)
void check_expect(token expect)
Definition: gx_json.h:142
#define min(x, y)
const value_pair * value_names
Definition: gx_parameter.h:277
void set_ctr_val(int ctr, int val)
const char * id
Definition: gx_plugin.h:185
virtual void serializeJSON(gx_system::JsonWriter &jw)
std::pair< std::string, std::string > id_label
virtual void serializeJSON(gx_system::JsonWriter &jw)
bool isFloat() const
Definition: gx_parameter.h:162
bool set_trans(int n, int last_value)
bool hasId(const string &id) const
Definition: gx_parameter.h:535
#define max(x, y)
const char * get_typename() const
virtual void close()
Definition: gx_json.cpp:68
const char * value_label
Definition: gx_plugin.h:119
void begin_object(bool nl=false)
Definition: gx_json.cpp:168
const value_pair * value_names
Definition: gx_parameter.h:332
void writeJSON_one(gx_system::JsonWriter &jw, Parameter *p)
enum value_type v_type
Definition: gx_parameter.h:119
void update_from_controller(int ctr)
update all controlled parameters with last received value from MIDI controller ctr.
void set_controller_array(const ControllerArray &m)
FloatParameter & getFloat()
Definition: gx_parameter.h:452
virtual void writeJSON(gx_system::JsonWriter &jw) const
void gx_print_warning(const char *, const std::string &)
Definition: gx_logging.cpp:161
list< MidiController > midi_controller_list
Definition: gx_parameter.h:696
virtual const value_pair * getValueNames() const
virtual float getStepAsFloat() const
virtual void writeJSON(gx_system::JsonWriter &jw) const
void set_bpm_val(unsigned int val)
void writeJSON(gx_system::JsonWriter &jw) const
void atomic_set(volatile int *p, int v)
Definition: gx_system.h:90
virtual void serializeJSON(gx_system::JsonWriter &jw)
static MidiController * readJSON(gx_system::JsonParser &jp, ParamMap &param)
Glib::RefPtr< Gio::File > value
Definition: gx_parameter.h:385
string current_value() const
Definition: gx_json.h:143
iterator begin() const
Definition: gx_parameter.h:533
virtual float idx_from_id(string v_id)
virtual void readJSON_value(gx_system::JsonParser &jp)
bool atomic_compare_and_exchange(volatile int *p, int oldv, int newv)
Definition: gx_system.h:114
void readJSON(gx_system::JsonParser &jp)
EnumParameterD(gx_system::JsonParser &jp)
bool set_midi(int n, int last_value)
void process_trans(int transport_state)
static gx_system::JsonParser & jp_next(gx_system::JsonParser &jp, const char *key)
virtual int idx_from_id(string v_id)
void replace(int ctr, const string &name)
void set_standard(const string &filename)
void copy(const string &destination) const
FileParameter(const string &id, const string &filename, bool preset=false)
Definition: gx_parameter.h:400
virtual void writeJSON(gx_system::JsonWriter &jw) const
ParameterV(const string &id, const string &name, ctrl_type ctp, bool preset, float *v, float sv, float lv, float uv, float tv, bool ctrl, bool no_init)
Definition: gx_parameter.h:257
ParameterV(const string &id, const string &name, Glib::ustring *v, const Glib::ustring &sv, bool preset=false)
Definition: gx_parameter.h:439
void set_path(const string &path)
void writeJSON(gx_system::JsonWriter &jw) const
string get_directory_path() const
float current_value_float()
Definition: gx_json.h:146
static const char * value_label(const value_pair &vp)
Definition: gx_parameter.h:198
ParameterV(const string &id, const string &name, ctrl_type ctp, bool preset, bool *v, bool sv, bool ctrl)
Definition: gx_parameter.h:367
void deleteParameter(Parameter &param)
virtual void serializeJSON(gx_system::JsonWriter &jw)
token next(token expect=no_token)
Definition: gx_json.cpp:496
unsigned int d_flags
Definition: gx_parameter.h:121
ParameterV< Glib::ustring > StringParameter
Definition: gx_parameter.h:97
void write(float v, bool nl=false)
Definition: gx_json.cpp:116
bool unit_has_std_values(const PluginDef *pdef) const
Glib::RefPtr< Gio::File > json_value
Definition: gx_parameter.h:387
const string & id() const
Definition: gx_parameter.h:172
virtual const value_pair * getValueNames() const
bool is_equal(const Glib::RefPtr< Gio::File > &v) const
void set_last_midi_control_value(unsigned int n, int v)
Definition: gx_parameter.h:777
bool set(const Glib::RefPtr< Gio::File > &val)
string get_display_name() const
virtual void serializeJSON(gx_system::JsonWriter &jw)
void readJSON(gx_system::JsonParser &jp)
void convert_from_range(float low, float up)
void remove_controlled_parameters(paramlist &plist, const ControllerArray *m)
void end_object(bool nl=false)
Definition: gx_json.cpp:176
void reset_unit(const PluginDef *pdef) const
virtual void readJSON_value(gx_system::JsonParser &jp)
void dump(gx_system::JsonWriter *jw)
virtual const value_pair * getValueNames() const
virtual void writeJSON(gx_system::JsonWriter &jw) const