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 
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 
122 string MidiStandardControllers::ctr_desc(int ctr) {
123  string p = midi_to_note(ctr-200);
124  return "Note On ( " + p + " )";
125  }
126 
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 
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 
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 
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  }
186 }
187 
188 
189 /****************************************************************
190  ** class MidiController
191  */
192 
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 
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;
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();
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) {
266  int _toggle = jp.current_value_int();
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) {
288  _("recall MIDI state"),
289  _("invalid format, Parameter skipped: ") + id);
290  return 0;
291  }
292  if (chg) {
294  _("recall MIDI state"),
295  _("Parameter range outside bounds, changed: ") + id);
296  }
297  return new MidiController(pm, lower, upper, toggle, toggle_behaviour);
298 }
299 
300 bool MidiController::set_midi(int n, int last_value) {
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  } else {
312  ret = param->midi_set(127, 127, _lower, _upper);
313  }
314  }
315  break;
316  }
317  case Parameter::toggle_type::Constant: {
318  if (n == last_value || last_value == -1) {
319  if (param->on_off_value()) {
320  ret = param->midi_set(0, n, _lower, _upper);
321  } else {
322  ret = param->midi_set(127, n, _lower, _upper);
323  }
324  }
325  break;
326  }
327  }
328  } else {
329  //fprintf(stderr,"continues %s \n",param->id().c_str());
330  //fprintf(stderr,"%f \n",(127.*log10f(double(n+1.)))/2.1072);
331  //fprintf(stderr,"%f \n",double(n * double(double(n+1.)/128)));
332  ret = param->midi_set(n, 127, _lower, _upper);
333  }
334  param->trigger_changed();
335  return ret;
336 }
337 
338 bool MidiController::set_trans(int n, int last_value) {
339  bool ret = false;
340  if (param->get_blocked()) return ret;
341  if (strcmp(param->id().c_str(), "engine.mute")==0) {
342  if ( n == 0) n = 127;
343  else n = 0;
344  }
345  ret = param->midi_set(n, 127, _lower, _upper);
346  return ret;
347 }
348 
349 bool MidiController::set_bpm(int n, int last_value) {
350  bool ret = false;
351  if (param->get_blocked()) return ret;
352  if (toggle) {
353  bool s_o = (2*last_value > 360);
354  bool s_n = (2*n > 360);
355  if (!s_o && s_n) {
356  if (param->on_off_value()) {
357  ret = param->midi_set_bpm(0, 360, _lower, _upper);
358  } else {
359  ret = param->midi_set_bpm(360, 360, _lower, _upper);
360  }
361  }
362  } else {
363  ret = param->midi_set_bpm(n, 360, _lower, _upper);
364  }
365  return ret;
366 }
367 
368 /****************************************************************
369  ** class ControllerArray
370  */
371 
373  for (unsigned int n = 0; n < array_size; n++) {
374  operator[](n).clear();
375  }
377  while (jp.peek() != gx_system::JsonParser::end_array) {
379  midi_controller_list& l = operator[](jp.current_value_int());
381  while (jp.peek() != gx_system::JsonParser::end_array) {
383  if (p) {
384  l.push_back(*p);
385  delete p;
386  }
387  }
389  }
391 }
392 
394  w.begin_array(true);
395  for (unsigned int n = 0; n < array_size; n++) {
396  const midi_controller_list& cl = operator[](n);
397  if (cl.empty())
398  continue;
399  w.write(n);
400  w.begin_array();
401  for (midi_controller_list::const_iterator i = cl.begin(); i != cl.end(); ++i)
402  i->writeJSON(w);
403  w.end_array(true);
404  }
405  w.newline();
406  w.end_array(true);
407 }
408 
410  for (ControllerArray::size_type n = 0; n < size(); ++n) {
411  const midi_controller_list& cl = operator[](n);
412  for (midi_controller_list::const_iterator i = cl.begin(); i != cl.end(); ++i) {
413  if (i->hasParameter(param)) {
414  if (p) {
415  *p = &(*i);
416  }
417  return n;
418  }
419  }
420  }
421  return -1;
422 }
423 
425  for (iterator pctr = begin(); pctr != end(); ++pctr) {
426  for (midi_controller_list::iterator i = pctr->begin(); i != pctr->end(); ++i) {
427  if (i->hasParameter(p)) {
428  pctr->erase(i);
429  return true;
430  }
431  }
432  }
433  return false;
434 }
435 
436 
437 /****************************************************************
438  ** class MidiClockToBpm
439  */
440 
441 
443  : time1(0),
444  time_diff(0),
445  collect(0),
446  collect_(0),
447  bpm(0),
448  bpm_new(0),
449  ret(false) {}
450 
451 unsigned int MidiClockToBpm::rounded(float f) {
452  if (f >= 0x1.0p23) return (unsigned int) f;
453  return (unsigned int) (f + 0.49999997f);
454 }
455 
456 bool MidiClockToBpm::time_to_bpm(double time, unsigned int* bpm_) {
457  ret = false;
458  // if time drift to far, reset bpm detection.
459  if ((time-time1)> (1.05*time_diff) || (time-time1)*1.05 < (time_diff)) {
460  bpm = 0;
461  collect = 0;
462  collect_ = 0;
463  } else {
464  bpm_new = ((1000000000. / (time-time1) / 24) * 60);
465  bpm += bpm_new;
466  collect++;
467 
468  if (collect >= (bpm_new*bpm_new*0.0002)+1) {
469  bpm = (bpm/collect);
470  if (collect_>=2) {
471  (*bpm_) = rounded(min(360.,max(24.,bpm)));
472  collect_ = 0;
473  ret = true;
474  }
475  collect_++;
476  collect = 1;
477  }
478  }
479  time_diff = time-time1;
480  time1 = time;
481  return ret;
482 }
483 
484 /****************************************************************
485  ** class MidiControllerList
486  */
487 
489  : map(),
490  last_midi_control_value(),
491  last_midi_control(-2),
492  changed_midi_control_value(),
493  program_change(-1),
494  mute_change(-1),
495  bank_change(-1),
496  time0(0),
497  bpm_(9),
498  mp(),
499  pgm_chg(),
500  mute_chg(),
501  bank_chg(),
502  val_chg(),
503  changed(),
504  new_program(),
505  new_mute_state(),
506  new_bank(),
507  midi_value_changed() {
508  for (int i = 0; i < ControllerArray::array_size; ++i) {
509  last_midi_control_value[i] = -1;
510  changed_midi_control_value[i] = 0;
511  }
512  pgm_chg.connect(sigc::mem_fun(*this, &MidiControllerList::on_pgm_chg));
513  mute_chg.connect(sigc::mem_fun(*this, &MidiControllerList::on_mute_chg));
514  bank_chg.connect(sigc::mem_fun(*this, &MidiControllerList::on_bank_chg));
515  val_chg.connect(sigc::mem_fun(*this, &MidiControllerList::on_val_chg));
516  // Glib::signal_timeout().connect(
517  // sigc::mem_fun(this, &MidiControllerList::check_midi_values), 60);
518 }
519 
520 bool MidiControllerList::check_midi_values() {
521  static int saved_values[ControllerArray::array_size];
522  for (unsigned int n = 0; n < ControllerArray::array_size; ++n) {
523  if (changed_midi_control_value[n]) {
524  changed_midi_control_value[n] = 0;
525  saved_values[n] = last_midi_control_value[n];
526  midi_value_changed(n, saved_values[n]);
527  if (!get_config_mode()) {
528  midi_controller_list& ctr_list = map[n];
529  for (midi_controller_list::iterator i = ctr_list.begin(); i != ctr_list.end(); ++i) {
530  if (i->is_toggle()
531  && i->toggle_behaviour() == Parameter::toggle_type::Constant) {
532  midi_value_changed(n, i->getParameter().on_off_value() * 127);
533  }
534  i->trigger_changed();
535  }
536  }
537  }
538  }
539  return true;
540 }
541 
542 void MidiControllerList::on_val_chg() {
543  static int saved_values[ControllerArray::array_size];
544  for (unsigned int n = 0; n < ControllerArray::array_size; ++n) {
545  if (changed_midi_control_value[n]) {
546  changed_midi_control_value[n] = 0;
547  saved_values[n] = last_midi_control_value[n];
548  midi_value_changed(n, saved_values[n]);
549  if (!get_config_mode()) {
550  midi_controller_list& ctr_list = map[n];
551  for (midi_controller_list::iterator i = ctr_list.begin(); i != ctr_list.end(); ++i) {
552  if (i->is_toggle()
553  && i->toggle_behaviour() == Parameter::toggle_type::Constant) {
554  midi_value_changed(n, i->getParameter().on_off_value() * 127);
555  }
556  i->trigger_changed();
557  }
558  }
559  }
560  }
561 }
562 
565  int v = get_last_midi_control_value(ctr);
566  if (v >= 0) {
567  midi_controller_list& cl = map[ctr];
568  for (midi_controller_list::iterator i = cl.begin(); i != cl.end(); ++i) {
569  i->set_midi(v, v);
570  }
571  }
572 }
573 
575  for (unsigned int n = 0; n < map.size(); n++) {
577  }
578 }
579 
580 void MidiControllerList::on_pgm_chg() {
581  int pgm;
582  do {
583  pgm = gx_system::atomic_get(program_change);
584  } while (!gx_system::atomic_compare_and_exchange(&program_change, pgm, -1));
585  if (pgm>=0) new_program(pgm);
586 }
587 
588 void MidiControllerList::on_mute_chg() {
589  int mute;
590  do {
591  mute = gx_system::atomic_get(mute_change);
592  } while (!gx_system::atomic_compare_and_exchange(&mute_change, mute, -1));
593  new_mute_state(mute);
594 }
595 
596 void MidiControllerList::on_bank_chg() {
597  int bk;
598  do {
599  bk = gx_system::atomic_get(bank_change);
600  } while (!gx_system::atomic_compare_and_exchange(&bank_change, bk, -1));
601  if (bk>=0) new_bank(bk);
602 }
603 
604 void MidiControllerList::set_config_mode(bool mode, int ctl) {
605  assert(mode != get_config_mode());
606  if (mode) {
607  last_midi_control = ctl;
608  } else {
609  last_midi_control = -2;
610  }
611 }
612 
614  bool mode = get_config_mode();
615  if (!mode) {
616  set_config_mode(true); // keep rt thread away from table
617  }
618  if (map.deleteParameter(p)) {
619  changed();
620  }
621  if (!mode) {
622  set_config_mode(false);
623  }
624 }
625 
627  float lower, float upper, bool toggle, int toggle_behaviour) {
628  if (!get_config_mode()) {
629  assert(false);
630  return; // keep rt thread away from table
631  }
632  // maximal one controller for a zone allowed
633  deleteParameter(param);
634  if (last_midi_control < 0)
635  return;
636  // add zone to controller
637  map[last_midi_control].push_front(MidiController(param, lower, upper, toggle, toggle_behaviour));
638  update_from_controller(last_midi_control);
639  changed();
640 }
641 
643  for (unsigned int n = 0; n < ControllerArray::array_size; ++n) {
644  int v = last_midi_control_value[n];
645  midi_controller_list& ctr_list = map[n];
646  for (midi_controller_list::iterator i = ctr_list.begin(); i != ctr_list.end(); ++i) {
647  if (i->is_toggle()) {
648  v = i->getParameter().on_off_value() * 127;
649  }
650  midi_value_changed(n, v);
651  }
652  }
653 }
654 
655 void MidiControllerList::set_ctr_val(int ctr, int val) {
656  if (get_config_mode()) {
657  last_midi_control = ctr;
658  } else {
659  midi_controller_list& ctr_list = map[ctr];
660  for (midi_controller_list::iterator i = ctr_list.begin(); i != ctr_list.end(); ++i) {
661  i->set_midi(val, get_last_midi_control_value(ctr));
662  }
663  }
665 }
666 
667 void MidiControllerList::set_bpm_val(unsigned int val) {
668  if (get_config_mode()) {
669  last_midi_control = 22;
670  } else {
671  midi_controller_list& ctr_list = map[22];
672  for (midi_controller_list::iterator i = ctr_list.begin(); i != ctr_list.end(); ++i) {
673  i->set_bpm(val, get_last_midi_control_value(22));
674  }
675  }
677 }
678 
680  bool mode = get_config_mode();
681  if (!mode) {
682  set_config_mode(true); // keep rt thread away from table
683  }
684  map = m;
685  if (!mode) {
686  set_config_mode(false);
687  }
688  changed();
689 }
690 
692  const ControllerArray *new_m) {
693  std::set<Parameter*> pset;
694  for (unsigned int i = 0; i < map.size(); i++) {
695  midi_controller_list& ctr = map[i];
696  for (midi_controller_list::iterator j = ctr.begin(); j != ctr.end(); ++j) {
697  if (new_m) {
698  const midi_controller_list& ctr_new = (*new_m)[i];
699  for (midi_controller_list::const_iterator jn = ctr_new.begin();
700  jn != ctr_new.end(); ++jn) {
701  if (j->getParameter() == jn->getParameter()) {
702  pset.insert(&j->getParameter());
703  break;
704  }
705  }
706  } else {
707  pset.insert(&j->getParameter());
708  }
709  }
710  }
711  for (paramlist::iterator n = plist.begin(); n != plist.end(); ) {
712  paramlist::iterator n1 = n++;
713  if (pset.find(*n1) != pset.end()) {
714  plist.erase(n1);
715  }
716  }
717 }
718 
719 void MidiControllerList::process_trans(int transport_state) {
720  unsigned int val = 0;
721  switch (transport_state) {
722  case JackTransportStopped:
723  val = 0;
724  break;
725  case JackTransportRolling:
726  val = 127;
727  break;
728  case JackTransportStarting:
729  val = 127;
730  break;
731  default:
732  return;
733  }
734  if (get_config_mode()) {
735  last_midi_control = 24;
736  } else {
737  midi_controller_list& ctr_list = map[24];
738  for (midi_controller_list::iterator i = ctr_list.begin(); i != ctr_list.end(); ++i) {
739  i->set_trans(val, get_last_midi_control_value(24));
740  }
741  }
743  val_chg();
744 }
745 
746 // ----- jack process callback for the midi input
747 void MidiControllerList::compute_midi_in(void* midi_input_port_buf, void *arg) {
748  jack_midi_event_t in_event;
749  jack_nframes_t event_count = jack_midi_get_event_count(midi_input_port_buf);
750  unsigned int i;
751  for (i = 0; i < event_count; i++) {
752  jack_midi_event_get(&in_event, midi_input_port_buf, i);
753  if ((in_event.buffer[0] & 0xf0) == 0xc0) { // program change on any midi channel
754  gx_system::atomic_set(&program_change, in_event.buffer[1]);
755  pgm_chg();
756  } else if ((in_event.buffer[0] & 0xf0) == 0xb0) { // controller
757  if (in_event.buffer[1]== 120) { // engine mute by All Sound Off on any midi channel
758  gx_system::atomic_set(&mute_change, in_event.buffer[2]);
759  mute_chg();
760  } else if (in_event.buffer[1]== 32) { // bank change on any midi channel
761  gx_system::atomic_set(&bank_change, in_event.buffer[2]);
762  bank_chg();
763  } else {
764  set_ctr_val(in_event.buffer[1], in_event.buffer[2]);
765  val_chg();
766  }
767  } else if ((in_event.buffer[0] & 0xf0) == 0x90) { // Note On
768  set_ctr_val(in_event.buffer[1]+200, 1);
769  val_chg();
770  //fprintf(stderr,"Note On %i", (int)in_event.buffer[1]);
771  } else if ((in_event.buffer[0] ) > 0xf0) { // midi clock
772  if ((in_event.buffer[0] ) == 0xf8) { // midi beat clock
773  clock_gettime(CLOCK_MONOTONIC, &ts1);
774  gx_jack::GxJack& jack = *static_cast<gx_jack::GxJack*>(arg);
775  static unsigned int sr = jack.get_jack_sr();
776  time0 = (ts1.tv_sec*1000000000.0)+(ts1.tv_nsec)+
777  (1000000000.0/(double)(sr/(double)in_event.time));
778  if (mp.time_to_bpm(time0, &bpm_)) {
779  set_bpm_val(bpm_);
780  val_chg();
781  }
782  } else if ((in_event.buffer[0] ) == 0xfa) { // midi clock start
783  set_ctr_val(23, 127);
784  val_chg();
785  } else if ((in_event.buffer[0] ) == 0xfb) { // midi clock continue
786  // set_ctr_val(23, 127);
787  } else if ((in_event.buffer[0] ) == 0xfc) { // midi clock stop
788  set_ctr_val(23, 0);
789  val_chg();
790  } else if ((in_event.buffer[0] ) == 0xf2) { // midi clock position
791  // not implemented
792  // set_ctr_val(24,(in_event.buffer[2]<<7) | in_event.buffer[1]);
793  }
794  }
795  }
796 }
797 
798 /****************************************************************
799  ** Parameter Groups
800  */
801 
803  insert("system", N_("System"));
804  insert("ui", N_("User Interface"));
805  insert("ui.amp", N_("User Interface")); // FIXME (ui.amp.tonestack)
806  insert("engine", N_("Audio Engine"));
807 }
808 
810 #ifndef NDEBUG
811  for (map<string, bool>::iterator i = used.begin(); i != used.end(); ++i) {
812  if (!i->second) {
813  gx_print_error("Debug Check", "Group not used: " + i->first);
814  }
815  }
816 #endif
817 }
818 
819 #ifndef NDEBUG
820 void ParameterGroups::group_exists(const string& id) {
821  if (groups.find(id) == groups.end()) {
822  gx_print_error("Debug Check", "Group does not exist: " + id);
823  } else {
824  used[id] = true;
825  }
826 }
827 
828 void ParameterGroups::group_is_new(const string& id) {
829  if (groups.find(id) != groups.end()) {
830  gx_print_error("Debug Check", "Group already exists: " + id);
831  }
832 }
833 
835  for (map<string, string>::iterator i = groups.begin(); i != groups.end(); ++i) {
836  printf("PG %s: %s\n", i->first.c_str(), i->second.c_str());
837  }
838 }
839 
840 #endif
841 
843  static ParameterGroups groups;
844  return groups;
845 }
846 
847 string param_group(const string& group_id, bool nowarn) {
848  static ParameterGroups& groups = get_group_table();
849  if (nowarn) {
850  return groups.get(group_id);
851  } else {
852  return groups[group_id];
853  }
854 }
855 
856 bool ParameterGroups::group_exist(const string& id) {
857  if (groups.find(id) == groups.end()) {
858  return false;
859  } else {
860  return true;
861  }
862 }
863 
864 /****************************************************************
865  ** Parameter
866  */
867 
871  assert(jp.current_value() == key);
872  return jp;
873 }
874 
876  jw.begin_object();
877  jw.write_kv("id", _id);
878  jw.write_kv("name", _name);
879  jw.write_kv("group", _group);
880  jw.write_kv("desc", _desc);
881  jw.write_kv("v_type", v_type); //FIXME
882  jw.write_kv("c_type", c_type); //FIXME
883  jw.write_kv("d_flags", d_flags); //FIXME
884  if (!controllable) {
885  jw.write_key("non_controllable"); jw.write(false);
886  }
887  if (!save_in_preset) {
888  jw.write_key("non_preset"); jw.write(false);
889  }
890  jw.end_object();
891 }
892 
894  : boost::noncopyable(),
895  _id(),
896  _name(),
897  _group(),
898  _desc(),
899  v_type(tp_float),
900  c_type(Continuous),
901  d_flags(0),
902  save_in_preset(true),
903  controllable(true),
904  do_not_save(false),
905  blocked(false),
906  used(false) {
908  while (jp.peek() != gx_system::JsonParser::end_object) {
910  if (jp.read_kv("id", _id) ||
911  jp.read_kv("name", _name) ||
912  jp.read_kv("group", _group) ||
913  jp.read_kv("desc", _desc)) {
914  } else if (jp.current_value() == "v_type") {
916  v_type = static_cast<value_type>(jp.current_value_int());
917  } else if (jp.current_value() == "c_type") {
919  c_type = static_cast<ctrl_type>(jp.current_value_int());
920  } else if (jp.current_value() == "d_flags") {
922  d_flags = jp.current_value_int();
923  } else if (jp.current_value() == "non_controllable") {
925  controllable = false;
926  } else if (jp.current_value() == "non_preset") {
928  save_in_preset = false;
929  } else {
931  "Parameter", Glib::ustring::compose("%1: unknown key: %2", _id, jp.current_value()));
932  jp.skip_object();
933  }
934  }
936 }
937 
939 }
940 
941 bool Parameter::midi_set(float n, float high, float llimit, float ulimit) {
942  assert(false);
943  return false;
944 }
945 
946 bool Parameter::midi_set_bpm(float n, float high, float llimit, float ulimit) {
947  assert(false);
948  return false;
949 }
950 
951 void Parameter::trigger_changed() {
952  assert(false);
953 }
954 
955 static int get_upper(const value_pair *vn) {
956  for (int n = 0; ; n++) {
957  if (!vn[n].value_id) {
958  return n - 1;
959  }
960  }
961 }
962 
963 void Parameter::range_warning(float value, float lower, float upper) {
965  _("parameter load"),
966  Glib::ustring::compose(_("parameter %1: value %2 out of range [%3, %4]"),
967  _id, value, lower, upper));
968 }
969 
970 const char *Parameter::get_typename() const {
971  static const char *tpname[] = {
972  "float", "int", "bool", "bool", "filename", "string", "special"};
973  assert(0 <= v_type and v_type < sizeof(tpname)/sizeof(tpname[0]));
974  return tpname[v_type];
975 }
976 
977 bool Parameter::hasRange() const {
978  return false;
979 }
980 
982  return 1;
983 }
984 
986  return 0;
987 }
988 
990  return 0;
991 }
992 
994  return 0;
995 }
996 
997 #ifndef NDEBUG
998 void compare_parameter(const char *title, Parameter* p1, Parameter* p2, bool all) {
999  if (p1->_id != p2->_id) {
1001  title, Glib::ustring::compose("Different ID's: %2 / %3",
1002  p1->_id, p2->_id));
1003  }
1004  if (p1->_name != p2->_name) {
1006  title, Glib::ustring::compose("[%1]: Different name: %2 / %3",
1007  p1->_id, p1->_name, p2->_name));
1008  }
1009  if (p1->_group != p2->_group) {
1011  title, Glib::ustring::compose("[%1]: Different group: %2 / %3",
1012  p1->_id, p1->_group, p2->_group));
1013  }
1014  if (p1->_desc != p2->_desc) {
1016  title, Glib::ustring::compose("[%1]: Different desc: %2 / %3",
1017  p1->_id, p1->_desc, p2->_desc));
1018  }
1019  if (p1->save_in_preset != p2->save_in_preset) {
1021  title, Glib::ustring::compose("[%1]: save_in_preset different: %2 / %3",
1022  p1->_id, p1->save_in_preset, p2->save_in_preset));
1023  }
1024  if (p1->controllable != p2->controllable) {
1026  title, Glib::ustring::compose("[%1]: controllable different: %2 / %3",
1027  p1->_id, p1->controllable, p2->controllable));
1028  }
1029  if (p1->used != p2->used) {
1031  title, Glib::ustring::compose("[%1]: used different: %2 / %3",
1032  p1->_id, p1->used, p2->used));
1033  }
1034  if (p1->c_type != p2->c_type) {
1036  title, Glib::ustring::compose("[%1]: c_type different: %2 / %3",
1037  p1->_id, p1->c_type, p2->c_type));
1038  }
1039  if (p1->v_type != p2->v_type) {
1041  title, Glib::ustring::compose("[%1]: v_type different: %2 / %3",
1042  p1->_id, p1->v_type, p2->v_type));
1043  return;
1044  }
1045  if (p1->isFloat()) {
1046  FloatParameter& f1 = p1->getFloat();
1047  FloatParameter& f2 = p2->getFloat();
1048  if (f1.value != f2.value) {
1050  title, Glib::ustring::compose("[%1]: value address different: %2 / %3",
1051  p1->_id, f1.value, f2.value));
1052  }
1053  if (f1.lower != f2.lower) {
1055 
1056  title, Glib::ustring::compose("[%1]: float lower different: %2 / %3",
1057  p1->_id, f1.lower, f2.lower));
1058  }
1059  if (f1.upper != f2.upper) {
1061  title, Glib::ustring::compose("[%1]: float upper different: %2 / %3",
1062  p1->_id, f1.upper, f2.upper));
1063  }
1064  if (f1.step != f2.step) {
1066  title, Glib::ustring::compose("[%1]: float step different: %2 / %3",
1067  p1->_id, f1.step, f2.step));
1068  }
1069  if (f1.std_value != f2.std_value) {
1071  title, Glib::ustring::compose("[%1]: float std value different: %2 / %3",
1072  p1->_id, f1.std_value, f2.std_value));
1073  }
1074  if (all) {
1075  if (f1.value != f2.value) {
1077  title, Glib::ustring::compose("[%1]: float value different: %2 / %3",
1078  p1->_id, *f1.value, *f2.value));
1079  }
1080  if (f1.json_value != f2.json_value) {
1082  title, Glib::ustring::compose("[%1]: float json value different: %2 / %3",
1083  p1->_id, f1.json_value, f2.json_value));
1084  }
1085  }
1086  return;
1087  }
1088  if (p1->isInt()) {
1089  assert(false);
1090  return;
1091  }
1092  if (p1->isBool()) {
1093  assert(false);
1094  return;
1095  }
1096  if (p1->isFile()) {
1097  assert(false);
1098  return;
1099  }
1100  assert(false);
1101 }
1102 #endif
1103 
1104 /* FloatParameter */
1105 
1107  jw.begin_object();
1108  jw.write_key("Parameter"); Parameter::serializeJSON(jw);
1109  jw.write_kv("lower", lower);
1110  jw.write_kv("upper", upper);
1111  jw.write_kv("step", step);
1112  jw.write_kv("value", *value);
1113  jw.write_kv("std_value", std_value);
1114  jw.end_object();
1115 }
1116 
1118  : Parameter(jp_next(jp, "Parameter")), json_value(0), value(&value_storage), std_value(0), lower(), upper(), step() {
1119  while (jp.peek() != gx_system::JsonParser::end_object) {
1121  if (jp.read_kv("lower", lower) ||
1122  jp.read_kv("upper", upper) ||
1123  jp.read_kv("step", step) ||
1124  jp.read_kv("value", *value) ||
1125  jp.read_kv("std_value", std_value)) {
1126  } else {
1128  "FloatParameter", Glib::ustring::compose("%1: unknown key: %2", _id, jp.current_value()));
1129  jp.skip_object();
1130  }
1131  }
1133 }
1134 
1136 }
1137 
1138 bool FloatParameter::set(float val) const {
1139  float v = min(max(val, lower), upper);
1140  if (v != *value) {
1141  *value = v;
1142  changed(v);
1143  return true;
1144  }
1145  return false;
1146 }
1147 
1149  return *value != 0;
1150 }
1151 
1152 float FloatParameter::idx_from_id(string v_id) {
1153  assert(false);
1154  return 0;
1155 }
1156 
1157 bool FloatParameter::midi_set(float n, float high, float llimit, float ulimit) {
1158  float v;
1159  switch (c_type) {
1160  case Continuous:
1161  assert(n >= 0 && n <= high);
1162  v = llimit + (n / high) * (ulimit - llimit);
1163  break;
1164  case Switch:
1165  v = (2*n > high ? 1.0 : 0.0);
1166  break;
1167  case Enum:
1168  v = lower + min(n, upper-lower);
1169  break;
1170  default:
1171  assert(false);
1172  return false;
1173  }
1174  if (v != *value) {
1175  *value = v;
1176  return true;
1177  }
1178  return false;
1179 }
1180 
1181 bool FloatParameter::midi_set_bpm(float n, float high, float llimit, float ulimit) {
1182  float v;
1183  switch (c_type) {
1184  case Continuous:
1185  assert(n >= 0 && n <= high);
1186  if (high <= ulimit) {
1187  v = max(llimit,min(ulimit,n));
1188  } else {
1189  v = llimit + (n / high) * (ulimit - llimit);
1190  }
1191  break;
1192  case Switch:
1193  v = (2*n > high ? 1.0 : 0.0);
1194  break;
1195  case Enum:
1196  v = lower + min(n, upper-lower);
1197  break;
1198  default:
1199  assert(false);
1200  return false;
1201  }
1202  if (v != *value) {
1203  *value = v;
1204  return true;
1205  }
1206  return false;
1207 }
1208 
1209 void FloatParameter::trigger_changed() {
1210  changed(*value);
1211 }
1212 
1214  json_value = std_value;
1215 }
1216 
1218  jw.write_kv(_id.c_str(), *value);
1219 }
1220 
1223  json_value = jp.current_value_float();
1224  if (json_value < lower-std::abs(5*FLT_EPSILON*lower) || json_value > upper+std::abs(5*FLT_EPSILON*upper)) {
1225  range_warning(json_value, lower, upper);
1226  json_value = std_value;
1227  }
1228 }
1229 
1231  return std::abs(json_value - *value) < 5*FLT_EPSILON;
1232 }
1233 
1235  set(json_value);
1236 }
1237 
1238 void FloatParameter::convert_from_range(float low, float up) {
1239  json_value = lower + (json_value - low) / (up - low) * (upper - lower);
1240 }
1241 
1243  return true;
1244 }
1245 
1247  return lower;
1248 }
1249 
1251  return upper;
1252 }
1253 
1255  return step;
1256 }
1257 
1258 
1259 /* FloatEnumParameter */
1260 
1261 static void serializeValueNames(gx_system::JsonWriter& jw, const value_pair *p) {
1262  jw.write_key("value_names");
1263  jw.begin_array();
1264  while (p->value_id) {
1265  jw.write(p->value_id);
1266  if (p->value_label) {
1267  jw.write(p->value_label);
1268  } else {
1269  jw.write(p->value_id);
1270  }
1271  p++;
1272  }
1273  jw.end_array();
1274 }
1275 
1277  jw.begin_object();
1278  jw.write_key("FloatParameter"); FloatParameter::serializeJSON(jw);
1279  serializeValueNames(jw, value_names);
1280  jw.end_object();
1281 }
1282 
1283 FloatEnumParameter::FloatEnumParameter(const string& id, const string& name, const value_pair* vn, bool preset,
1284  float *v, int sv, int low, bool ctrl, bool no_init):
1285  FloatParameter(id, name, Enum, preset, v, sv, low, low+get_upper(vn), 1, ctrl, no_init),
1286  value_names(vn) {}
1287 
1289  return value_names;
1290 }
1291 
1293  jw.write_key(_id.c_str());
1294  jw.write(value_names[static_cast<int>(round(*value-lower))].value_id);
1295 }
1296 
1298  int up = static_cast<int>(round(upper));
1299  int low = static_cast<int>(round(lower));
1300  int n = 0;
1301  for (; n <= up-low; n++) {
1302  if (v_id == value_names[n].value_id) {
1303  return low + n;
1304  }
1305  }
1306  return -1;
1307 }
1308 
1312  // old version compatability
1313  json_value = jp.current_value_int();
1314  return;
1315  }
1317  float n = idx_from_id(jp.current_value());
1318  if (n < 0) {
1320  _("read parameter"), (boost::format(_("parameter %1%: unknown enum value: %2%"))
1321  % _id % jp.current_value()).str());
1322  n = lower;
1323  }
1324  json_value = n;
1325 }
1326 
1327 /* IntParameter */
1328 
1330  jw.begin_object();
1331  jw.write_key("Parameter"); Parameter::serializeJSON(jw);
1332  jw.write_kv("lower", lower);
1333  jw.write_kv("upper", upper);
1334  jw.write_kv("value", *value);
1335  jw.write_kv("std_value", std_value);
1336  jw.end_object();
1337 }
1338 
1340  : Parameter(jp_next(jp, "Parameter")), json_value(0), value(&value_storage), std_value(0), lower(), upper() {
1341  while (jp.peek() != gx_system::JsonParser::end_object) {
1343  if (jp.read_kv("lower", lower) ||
1344  jp.read_kv("upper", upper) ||
1345  jp.read_kv("value", *value) ||
1346  jp.read_kv("std_value", std_value)) {
1347  } else {
1349  "IntParameter", Glib::ustring::compose("%1: unknown key: %2", _id, jp.current_value()));
1350  jp.skip_object();
1351  }
1352  }
1354 }
1355 
1357 }
1358 
1359 bool IntParameter::set(int val) const {
1360  int v = min(max(val, lower), upper);
1361  if (v != *value) {
1362  *value = v;
1363  changed(v);
1364  return true;
1365  }
1366  return false;
1367 }
1368 
1369 int IntParameter::idx_from_id(string v_id) {
1370  assert(false);
1371  return 0;
1372 }
1373 
1375  return *value != 0;
1376 }
1377 
1378 bool IntParameter::midi_set(float n, float high, float llimit, float ulimit) {
1379  int v;
1380  switch (c_type) {
1381  case Continuous:
1382  assert(false); // not implemented
1383  return false;
1384  case Switch:
1385  assert(false); // not implemented
1386  return false;
1387  case Enum:
1388  v = lower + min(static_cast<int>(n), upper-lower);
1389  break;
1390  default:
1391  assert(false);
1392  return false;
1393  }
1394  if (v != *value) {
1395  *value = v;
1396  return true;
1397  }
1398  return false;
1399 }
1400 
1401 void IntParameter::trigger_changed() {
1402  changed(*value);
1403 }
1404 
1406  json_value = std_value;
1407 }
1408 
1410  jw.write_kv(_id.c_str(), *value);
1411 }
1412 
1415  json_value = jp.current_value_int();
1416  if (json_value < lower || json_value > upper) {
1417  range_warning(json_value, lower, upper);
1418  }
1419 }
1420 
1422  return json_value == *value;
1423 }
1424 
1426  set(json_value);
1427 }
1428 
1430  return true;
1431 }
1432 
1434  return lower;
1435 }
1436 
1438  return upper;
1439 }
1440 
1441 /* EnumParameter */
1442 
1444  jw.begin_object();
1445  jw.write_key("IntParameter"); IntParameter::serializeJSON(jw);
1446  serializeValueNames(jw, value_names);
1447  jw.end_object();
1448 }
1449 
1450 EnumParameter::EnumParameter(const string& id, const string& name, const value_pair* vn, bool preset,
1451  int *v, int sv, bool ctrl):
1452  IntParameter(id, name, Enum, preset, v, sv, 0, get_upper(vn), ctrl),
1453  value_names(vn) {}
1454 
1456  return value_names;
1457 }
1458 
1459 int EnumParameter::idx_from_id(string v_id) {
1460  int n = 0;
1461  for (; n <= upper; n++) {
1462  if (v_id == value_names[n].value_id) {
1463  return n;
1464  }
1465  }
1466  return -1;
1467 }
1468 
1470  jw.write_key(_id.c_str());
1471  jw.write(value_names[*value].value_id);
1472 }
1473 
1477  // old version compatability
1478  json_value = jp.current_value_int();
1479  return;
1480  }
1482  int n = idx_from_id(jp.current_value());
1483  if (n < 0) {
1485  _("read parameter"), (boost::format(_("parameter %1%: unknown enum value: %2%"))
1486  % _id % jp.current_value()).str());
1487  n = 0;
1488  }
1489  json_value = n;
1490 }
1491 
1492 /* derived enum parameters */
1493 
1494 typedef std::pair<std::string,std::string> id_label;
1495 
1496 void enum_parameter_load_values(gx_system::JsonParser& jp, std::vector<id_label>& value_array, const value_pair **value_names) {
1497  while (jp.peek() != gx_system::JsonParser::end_object) {
1499  if (jp.current_value() == "value_names") {
1501  while (jp.peek() != gx_system::JsonParser::end_array) {
1503  std::string value_id = jp.current_value();
1505  std::string value_label = jp.current_value();
1506  value_array.push_back(id_label(value_id, value_label));
1507  }
1509  } else {
1511  "EnumValueNames", Glib::ustring::compose("unknown key: %1", jp.current_value()));
1512  jp.skip_object();
1513  }
1514  }
1516  value_pair* p = new value_pair[value_array.size()+1];
1517  *value_names = p;
1518  for (std::vector<id_label>::iterator i = value_array.begin(); i != value_array.end(); ++i) {
1519  p->value_id = i->first.c_str();
1520  p->value_label = i->second.c_str();
1521  p++;
1522  }
1523  p->value_id = p->value_label = 0;
1524 }
1525 
1527 private:
1528  std::vector<id_label> value_array;
1529 public:
1532 };
1533 
1535  : FloatEnumParameter(jp), value_array() {
1536  enum_parameter_load_values(jp, value_array, &value_names);
1537 }
1538 
1540  delete value_names;
1541 }
1542 
1544 private:
1545  std::vector<id_label> value_array;
1546 public:
1548  ~EnumParameterD();
1549 };
1550 
1552  : EnumParameter(jp), value_array() {
1553  enum_parameter_load_values(jp, value_array, &value_names);
1554 }
1555 
1557  delete value_names;
1558 }
1559 
1560 
1561 /* BoolParameter */
1562 
1564  jw.begin_object();
1565  jw.write_key("Parameter"); Parameter::serializeJSON(jw);
1566  jw.write_kv("value", *value);
1567  jw.write_kv("std_value", std_value);
1568  jw.end_object();
1569 }
1570 
1572  : Parameter(jp_next(jp, "Parameter")), json_value(0), value(&value_storage), std_value(0) {
1573  while (jp.peek() != gx_system::JsonParser::end_object) {
1575  if (jp.read_kv("value", *value) || jp.read_kv("std_value", std_value)) {
1576  } else {
1578  "BoolParameter", Glib::ustring::compose("%1: unknown key: %2", _id, jp.current_value()));
1579  jp.skip_object();
1580  }
1581  }
1583 }
1584 
1586 }
1587 
1588 bool BoolParameter::set(bool val) const {
1589  if (val != *value) {
1590  *value = val;
1591  changed(val);
1592  return true;
1593  }
1594  return false;
1595 }
1596 
1598  return *value;
1599 }
1600 
1601 bool BoolParameter::midi_set(float n, float high, float llimit, float ulimit) {
1602  bool v;
1603  switch (c_type) {
1604  case Switch:
1605  v = (2*n > high);
1606  break;
1607  default:
1608  assert(false);
1609  return false;
1610  }
1611  if (v != *value) {
1612  *value = v;
1613  return true;
1614  }
1615  return false;
1616 }
1617 
1618 void BoolParameter::trigger_changed() {
1619  changed(*value);
1620 }
1621 
1623  json_value = std_value;
1624 }
1625 
1627  jw.write_kv(_id.c_str(), *value);
1628 }
1629 
1632  if (jp.current_value_int() < 0 || jp.current_value_int() > 1) {
1633  range_warning(json_value, 0, 1);
1634  }
1635  json_value = jp.current_value_int();
1636 }
1637 
1639  return json_value == *value;
1640 }
1641 
1643  set(json_value);
1644 }
1645 
1646 
1647 /* FileParameter */
1648 
1650  jw.begin_object();
1651  jw.write_key("Parameter"); Parameter::serializeJSON(jw);
1652  jw.write_kv("value", value->get_path());
1653  jw.write_kv("std_value", std_value->get_path());
1654  jw.end_object();
1655 }
1656 
1658  : Parameter(jp_next(jp, "Parameter")), value(0), std_value(0), json_value(0) {
1659  while (jp.peek() != gx_system::JsonParser::end_object) {
1661  if (jp.current_value() == "value") {
1663  value = Gio::File::create_for_path(jp.current_value());
1664  } else if (jp.current_value() == "std_value") {
1666  std_value = Gio::File::create_for_path(jp.current_value());
1667  } else {
1669  "FileParameter", Glib::ustring::compose("%1: unknown key: %2", _id, jp.current_value()));
1670  jp.skip_object();
1671  }
1672  }
1674 }
1675 
1676 void FileParameter::set_path(const string& path) {
1677  Glib::RefPtr<Gio::File> v = Gio::File::create_for_path(path);
1678  if (is_equal(v)) {
1679  return;
1680  }
1681  value = v;
1682  changed();
1683 }
1684 
1685 bool FileParameter::set(const Glib::RefPtr<Gio::File>& val) {
1686  if (is_equal(val)) {
1687  return false;
1688  }
1689  value = val;
1690  changed();
1691  return true;
1692 }
1693 
1694 void FileParameter::set_standard(const string& filename) {
1695  std_value = Gio::File::create_for_path(filename);
1696  if (!value) {
1697  value = std_value->dup();
1698  changed();
1699  }
1700 }
1701 
1703  json_value = std_value->dup();
1704  changed();
1705 }
1706 
1708  return bool(value);
1709 }
1710 
1712  jw.write_kv(_id.c_str(), get_path());
1713 }
1714 
1717  json_value = Gio::File::create_for_path(jp.current_value());
1718 }
1719 
1721  return json_value->get_path() == value->get_path(); //FIXME
1722 }
1723 
1725  set(json_value);
1726 }
1727 
1728 static string get_file_id(const Glib::RefPtr<Gio::File>& f) {
1729  return f->query_info(G_FILE_ATTRIBUTE_ID_FILE)->get_attribute_string(G_FILE_ATTRIBUTE_ID_FILE);
1730 }
1731 
1732 bool FileParameter::is_equal(const Glib::RefPtr<Gio::File>& v) const {
1733  string id, id2;
1734  try {
1735  id = get_file_id(value);
1736  } catch(Gio::Error& ex) {
1737  return false; // FIXME check type of exception
1738  }
1739  try {
1740  id2 = get_file_id(v);
1741  } catch(Gio::Error& ex) {
1742  return false; // FIXME check type of exception
1743  }
1744  return id == id2;
1745 }
1746 
1747 string FileParameter::get_path() const {
1748  return value->get_path();
1749 }
1750 
1752  return value->get_parent()->get_path();
1753 }
1754 
1756  return value->get_parse_name();
1757 }
1758 
1760  return value->query_info(G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME)->get_display_name();
1761 }
1762 
1763 void FileParameter::copy(const string& destination) const {
1764  value->copy(Gio::File::create_for_path(destination));
1765 }
1766 
1767 
1768 /* StringParameter */
1769 
1771  jw.begin_object();
1772  jw.write_key("Parameter"); Parameter::serializeJSON(jw);
1773  jw.write_kv("value", *value);
1774  jw.write_kv("std_value", std_value);
1775  jw.end_object();
1776 }
1777 
1779  : Parameter(jp_next(jp, "Parameter")), json_value(""), value(&value_storage), std_value("") {
1780  while (jp.peek() != gx_system::JsonParser::end_object) {
1782  if (jp.read_kv("value", *value) || jp.read_kv("std_value", std_value)) {
1783  } else {
1785  "StringParameter", Glib::ustring::compose("%1: unknown key: %2", _id, jp.current_value()));
1786  jp.skip_object();
1787  }
1788  }
1790 }
1791 
1793 }
1794 
1795 bool StringParameter::set(const Glib::ustring& val) const {
1796  if (val != *value) {
1797  *value = val;
1798  changed(*value);
1799  return true;
1800  }
1801  return false;
1802 }
1803 
1805  return !value->empty();
1806 }
1807 
1809  json_value = std_value;
1810 }
1811 
1813  jw.write_kv(_id.c_str(), *value);
1814 }
1815 
1818  json_value = jp.current_value();
1819 }
1820 
1822  return json_value == *value;
1823 }
1824 
1826  set(json_value);
1827 }
1828 
1829 /****************************************************************
1830  ** Parameter Map
1831  */
1832 
1834  : id_map(),
1835  replace_mode(false) {
1836 }
1837 
1839  for (iterator i = id_map.begin(); i != id_map.end(); ++i) {
1840  delete i->second;
1841  }
1842 }
1843 
1845  if (p->isFloat()) {
1846  if (p->getControlType() == Parameter::Enum) {
1847  jw.write("FloatEnum");
1848  } else {
1849  jw.write("Float");
1850  }
1851  } else if (p->isInt()) {
1852  if (p->getControlType() == Parameter::Enum) {
1853  jw.write("Enum");
1854  } else {
1855  jw.write("Int");
1856  }
1857  } else if (p->isBool()) {
1858  jw.write("Bool");
1859  } else if (p->isFile()) {
1860  jw.write("File");
1861  } else if (p->isString()) {
1862  jw.write("String");
1863  } else if (dynamic_cast<JConvParameter*>(p) != 0) {
1864  jw.write("JConv");
1865  } else if (dynamic_cast<SeqParameter*>(p) != 0) {
1866  jw.write("Seq");
1867  } else {
1868 #ifndef NDEBUG
1869  cerr << "skipping " << p->id() << endl;
1870 #endif
1871  return;
1872  }
1873  p->serializeJSON(jw);
1874 }
1875 
1877  jw.begin_array();
1878  for (iterator i = id_map.begin(); i != id_map.end(); ++i) {
1879  writeJSON_one(jw, i->second);
1880  }
1881  jw.end_array();
1882 }
1883 
1886  if (jp.current_value() == "FloatEnum") {
1887  return insert(new FloatEnumParameterD(jp));
1888  } else if (jp.current_value() == "Float") {
1889  return insert(new FloatParameter(jp));
1890  } else if (jp.current_value() == "Enum") {
1891  return insert(new EnumParameterD(jp));
1892  } else if (jp.current_value() == "Int") {
1893  return insert(new IntParameter(jp));
1894  } else if (jp.current_value() == "Bool") {
1895  return insert(new BoolParameter(jp));
1896  } else if (jp.current_value() == "File") {
1897  return insert(new FileParameter(jp));
1898  } else if (jp.current_value() == "String") {
1899  return insert(new StringParameter(jp));
1900  } else if (jp.current_value() == "JConv") {
1901  return insert(new JConvParameter(jp));
1902  } else if (jp.current_value() == "Seq") {
1903  return insert(new SeqParameter(jp));
1904  } else {
1906  "ParamMap", Glib::ustring::compose("unknown parameter type: %1", jp.current_value()));
1907  jp.skip_object();
1908  return 0;
1909  }
1910 }
1911 
1914  while (jp.peek() != gx_system::JsonParser::end_array) {
1915  readJSON_one(jp);
1916  }
1918 }
1919 
1920 #ifndef NDEBUG
1921 void ParamMap::unique_id(Parameter* param) {
1922  if (id_map.find(param->id()) != id_map.end()) {
1923  gx_print_error("Debug Check", "id registered twice: " + param->id());
1924  }
1925 }
1926 
1927 void ParamMap::check_id(const string& id) {
1928  if (!hasId(id)) {
1929  cerr << "string-id not found: " << id << endl;
1930  }
1931 }
1932 
1933 void ParamMap::check_p(const char *p) {
1934  if (!hasId(p)) {
1935  cerr << "char-id not found: " << p << endl;
1936  }
1937 }
1938 
1939 void ParamMap::dump(const string& fmt) {
1940  gx_system::JsonWriter *p = 0;
1942  if (fmt == "json") {
1943  jw.set_stream(&cout);
1944  p = &jw;
1945  jw.begin_array();
1946  jw.newline();
1947  } else {
1948  printf("parameter map dump\n");
1949  }
1950  for (iterator i = id_map.begin(); i != id_map.end(); ++i) {
1951  i->second->dump(p);
1952  }
1953  if (p) {
1954  jw.end_array();
1955  jw.close();
1956  } else {
1957  printf("---------------------\n");
1958  }
1959 }
1960 
1962  if (jw) {
1963  jw->begin_array();
1964  jw->write(id());
1965  switch (c_type) {
1966  case None: jw->write("None"); break;
1967  case Continuous: jw->write("Cont"); break;
1968  case Switch: jw->write("Swth"); break;
1969  case Enum: jw->write("Enum"); break;
1970  default: assert(false);
1971  }
1972  if (save_in_preset) {
1973  jw->write("preset");
1974  }
1975  if (controllable) {
1976  jw->write("control");
1977  }
1978  jw->write(l_group());
1979  jw->write(l_name());
1980  /*
1981  switch (v_type) {
1982  case tp_float: jw->write("f"); jw->write(getFloat().get_value()); break;
1983  case tp_int: jw->write("i"); jw->write(getInt().get_value()); break;
1984  case tp_bool: jw->write("b"); jw->write(getBool().get_value()); break;
1985  case tp_switch: jw->write("s"); jw->write(getSwitch().get()); break;
1986  case tp_file: jw->write("F"); jw->write(getFile().get_parse_name()); break;
1987  case tp_string: jw->write("S"); jw->write(getString().get_value()); break;
1988  case tp_special: jw->write("G"); break;
1989  default: assert(false);
1990  }
1991  */
1992  jw->write(getLowerAsFloat());
1993  jw->write(getUpperAsFloat());
1994  jw->write(getStepAsFloat());
1995  const value_pair *vn = getValueNames();
1996  if (vn) {
1997  jw->begin_array();
1998  for (int n = 0; ; ++n) {
1999  if (!vn[n].value_id) {
2000  break;
2001  }
2002  jw->begin_array();
2003  jw->write(vn[n].value_id);
2004  jw->write(vn[n].value_label ? vn[n].value_label : vn[n].value_id);
2005  jw->end_array();
2006  }
2007  jw->end_array();
2008  }
2009  jw->end_array();
2010  jw->newline();
2011  } else {
2012  printf("P: %s vt=%d ct=%d c=%d\n", _id.c_str(), v_type, c_type, controllable);
2013  }
2014 }
2015 #endif
2016 
2017 Parameter *ParamMap::insert(Parameter* param) {
2018  if (replace_mode) {
2019  map<string, Parameter*>::iterator ii = id_map.find(param->id());
2020  if (ii != id_map.end()) {
2021  Parameter *p = ii->second;
2022  insert_remove(p,false);
2023  id_map.erase(ii);
2024  delete p;
2025  }
2026  }
2027  debug_check(unique_id, param);
2028  id_map.insert(pair<string, Parameter*>(param->id(), param));
2029  insert_remove(param,true);
2030  return param;
2031 }
2032 
2034  if (!p) {
2035  return;
2036  }
2037  insert_remove(p, false);
2038  id_map.erase(p->id());
2039  delete p;
2040 }
2041 
2042 void ParamMap::unregister(const string& id) {
2043  if (!hasId(id)) {
2044  return;
2045  }
2046  unregister(&(*this)[id]);
2047 }
2048 
2050  for (iterator i = id_map.begin(); i != id_map.end(); ++i) {
2051  i->second->stdJSON_value();
2052  i->second->setJSON_value();
2053  }
2054 }
2055 
2056 static inline bool compare_groups(const std::string& id, const char **groups) {
2057  if (!groups) {
2058  return false;
2059  }
2060  for (const char **g = groups; *g; g += 2) {
2061  const char *p = *g;
2062  if ((*p) != '.') {
2063  continue;
2064  }
2065  p++;
2066  int n = strlen(p);
2067  if (strncmp(id.c_str(), p, n) == 0 && id[n] == '.') {
2068  return true;
2069  }
2070  }
2071  return false;
2072 }
2073 
2074 bool ParamMap::unit_has_std_values(const PluginDef *pdef) const {
2075  std::string group_id(pdef->id);
2076  group_id += ".";
2077  std::string on_off = group_id + "on_off";
2078  std::string pp = group_id + "pp";
2079  std::string position = group_id + "position";
2080  for (iterator i = begin(); i != end(); ++i) {
2081  if (i->first.compare(0, group_id.size(), group_id) == 0 || compare_groups(i->first, pdef->groups)) {
2082  if (i->second->isInPreset()) {
2083  if (i->first != on_off && i->first != pp && i->first != position) {
2084  i->second->stdJSON_value();
2085  if (!i->second->compareJSON_value()) {
2086  return false;
2087  break;
2088  }
2089  }
2090  }
2091  }
2092  }
2093  return true;
2094 }
2095 
2096 // reset all parameters to default settings
2097 void ParamMap::reset_unit(const PluginDef *pdef) const {
2098  std::string group_id(pdef->id);
2099  group_id += ".";
2100  std::string on_off = group_id + "on_off";
2101  std::string pp = group_id + "pp";
2102  std::string position = group_id + "position";
2103  for (iterator i = begin(); i != end(); ++i) {
2104  if (i->first.compare(0, group_id.size(), group_id) == 0 || compare_groups(i->first, pdef->groups)) {
2105  if (i->second->isInPreset()) {
2106  if (i->first != on_off && i->first != pp && i->first != position) {
2107  i->second->stdJSON_value();
2108  i->second->setJSON_value();
2109  }
2110  }
2111  }
2112  }
2113 }
2114 
2115 } // namespace gx_gui
ParameterV< float > FloatParameter
Definition: gx_parameter.h:93
ParameterV< GxSeqSettings > SeqParameter
CmdConnection::msg_type end
Definition: jsonrpc.cpp:256
int get_last_midi_control_value(unsigned int n)
Definition: gx_parameter.h:779
void write_kv(const char *key, float v)
Definition: gx_json.h:81
FloatEnumParameter(gx_system::JsonParser &jp)
Definition: gx_parameter.h:279
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:317
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:121
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:533
Parameter(const string &id, const string &name, value_type vtp, ctrl_type ctp, bool preset, bool ctrl)
Definition: gx_parameter.h:134
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:221
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:176
void dump(const string &fmt)
virtual void readJSON_value(gx_system::JsonParser &jp)
bool isBool() const
Definition: gx_parameter.h:165
bool isFile() const
Definition: gx_parameter.h:166
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:167
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:535
virtual void writeJSON(gx_system::JsonWriter &jw) const
ctrl_type getControlType() const
Definition: gx_parameter.h:168
bool isInt() const
Definition: gx_parameter.h:164
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:189
int atomic_get(volatile int &p)
Definition: gx_system.h:98
Glib::RefPtr< Gio::File > std_value
Definition: gx_parameter.h:387
FloatEnumParameterD(gx_system::JsonParser &jp)
EnumParameter(gx_system::JsonParser &jp)
Definition: gx_parameter.h:334
ParameterV< int > IntParameter
Definition: gx_parameter.h:96
void compute_midi_in(void *midi_input_port_buf, void *arg)
sigc::signal< void > changed
Definition: gx_parameter.h:389
virtual void serializeJSON(gx_system::JsonWriter &jw)
ParameterV< bool > BoolParameter
Definition: gx_parameter.h:97
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:278
void set_ctr_val(int ctr, int val)
const char * id
Definition: gx_plugin.h:187
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:163
bool set_trans(int n, int last_value)
bool hasId(const string &id) const
Definition: gx_parameter.h:536
#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:333
void writeJSON_one(gx_system::JsonWriter &jw, Parameter *p)
enum value_type v_type
Definition: gx_parameter.h:120
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:453
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:698
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:386
string current_value() const
Definition: gx_json.h:143
iterator begin() const
Definition: gx_parameter.h:534
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:401
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:258
bool group_exist(const string &id)
ParameterV(const string &id, const string &name, Glib::ustring *v, const Glib::ustring &sv, bool preset=false)
Definition: gx_parameter.h:440
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:199
ParameterV(const string &id, const string &name, ctrl_type ctp, bool preset, bool *v, bool sv, bool ctrl)
Definition: gx_parameter.h:368
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:122
ParameterV< Glib::ustring > StringParameter
Definition: gx_parameter.h:98
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:388
const string & id() const
Definition: gx_parameter.h:173
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:781
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