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