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 
722  channel_select = s;
723 }
724 
725 void MidiControllerList::process_trans(int transport_state) {
726  unsigned int val = 0;
727  switch (transport_state) {
728  case JackTransportStopped:
729  val = 0;
730  break;
731  case JackTransportRolling:
732  val = 127;
733  break;
734  case JackTransportStarting:
735  val = 127;
736  break;
737  default:
738  return;
739  }
740  if (get_config_mode()) {
741  last_midi_control = 24;
742  } else {
743  midi_controller_list& ctr_list = map[24];
744  for (midi_controller_list::iterator i = ctr_list.begin(); i != ctr_list.end(); ++i) {
745  i->set_trans(val, get_last_midi_control_value(24));
746  }
747  }
749  val_chg();
750 }
751 
752 // ----- jack process callback for the midi input
753 void MidiControllerList::compute_midi_in(void* midi_input_port_buf, void *arg) {
754  jack_midi_event_t in_event;
755  jack_nframes_t event_count = jack_midi_get_event_count(midi_input_port_buf);
756  unsigned int i;
757  for (i = 0; i < event_count; i++) {
758  jack_midi_event_get(&in_event, midi_input_port_buf, i);
759  bool ch = true;
760  if (channel_select>0) {
761  if ((channel_select) != (int(in_event.buffer[0]&0x0f)+1)) {
762  ch = false;
763  }
764  }
765  if ((in_event.buffer[0] & 0xf0) == 0xc0 && ch) { // program change on any midi channel
766  gx_system::atomic_set(&program_change, in_event.buffer[1]);
767  pgm_chg();
768  } else if ((in_event.buffer[0] & 0xf0) == 0xb0 && ch) { // controller
769  if (in_event.buffer[1]== 120) { // engine mute by All Sound Off on any midi channel
770  gx_system::atomic_set(&mute_change, in_event.buffer[2]);
771  mute_chg();
772  } else if (in_event.buffer[1]== 32 && ch) { // bank change on any midi channel
773  gx_system::atomic_set(&bank_change, in_event.buffer[2]);
774  bank_chg();
775  } else {
776  set_ctr_val(in_event.buffer[1], in_event.buffer[2]);
777  val_chg();
778  }
779  } else if ((in_event.buffer[0] & 0xf0) == 0x90 && ch) { // Note On
780  set_ctr_val(in_event.buffer[1]+200, 1);
781  val_chg();
782  //fprintf(stderr,"Note On %i", (int)in_event.buffer[1]);
783  } else if ((in_event.buffer[0] ) > 0xf0) { // midi clock
784  if ((in_event.buffer[0] ) == 0xf8) { // midi beat clock
785  clock_gettime(CLOCK_MONOTONIC, &ts1);
786  gx_jack::GxJack& jack = *static_cast<gx_jack::GxJack*>(arg);
787  static unsigned int sr = jack.get_jack_sr();
788  time0 = (ts1.tv_sec*1000000000.0)+(ts1.tv_nsec)+
789  (1000000000.0/(double)(sr/(double)in_event.time));
790  if (mp.time_to_bpm(time0, &bpm_)) {
791  set_bpm_val(bpm_);
792  val_chg();
793  }
794  } else if ((in_event.buffer[0] ) == 0xfa) { // midi clock start
795  set_ctr_val(23, 127);
796  val_chg();
797  } else if ((in_event.buffer[0] ) == 0xfb) { // midi clock continue
798  // set_ctr_val(23, 127);
799  } else if ((in_event.buffer[0] ) == 0xfc) { // midi clock stop
800  set_ctr_val(23, 0);
801  val_chg();
802  } else if ((in_event.buffer[0] ) == 0xf2) { // midi clock position
803  // not implemented
804  // set_ctr_val(24,(in_event.buffer[2]<<7) | in_event.buffer[1]);
805  }
806  }
807  }
808 }
809 
810 /****************************************************************
811  ** Parameter Groups
812  */
813 
815  insert("system", N_("System"));
816  insert("ui", N_("User Interface"));
817  insert("ui.amp", N_("User Interface")); // FIXME (ui.amp.tonestack)
818  insert("engine", N_("Audio Engine"));
819 }
820 
822 #ifndef NDEBUG
823  for (map<string, bool>::iterator i = used.begin(); i != used.end(); ++i) {
824  if (!i->second) {
825  gx_print_error("Debug Check", "Group not used: " + i->first);
826  }
827  }
828 #endif
829 }
830 
831 #ifndef NDEBUG
832 void ParameterGroups::group_exists(const string& id) {
833  if (groups.find(id) == groups.end()) {
834  gx_print_error("Debug Check", "Group does not exist: " + id);
835  } else {
836  used[id] = true;
837  }
838 }
839 
840 void ParameterGroups::group_is_new(const string& id) {
841  if (groups.find(id) != groups.end()) {
842  gx_print_error("Debug Check", "Group already exists: " + id);
843  }
844 }
845 
847  for (map<string, string>::iterator i = groups.begin(); i != groups.end(); ++i) {
848  printf("PG %s: %s\n", i->first.c_str(), i->second.c_str());
849  }
850 }
851 
852 #endif
853 
855  static ParameterGroups groups;
856  return groups;
857 }
858 
859 string param_group(const string& group_id, bool nowarn) {
860  static ParameterGroups& groups = get_group_table();
861  if (nowarn) {
862  return groups.get(group_id);
863  } else {
864  return groups[group_id];
865  }
866 }
867 
868 bool ParameterGroups::group_exist(const string& id) {
869  if (groups.find(id) == groups.end()) {
870  return false;
871  } else {
872  return true;
873  }
874 }
875 
876 /****************************************************************
877  ** Parameter
878  */
879 
883  assert(jp.current_value() == key);
884  return jp;
885 }
886 
888  jw.begin_object();
889  jw.write_kv("id", _id);
890  jw.write_kv("name", _name);
891  jw.write_kv("group", _group);
892  jw.write_kv("desc", _desc);
893  jw.write_kv("v_type", v_type); //FIXME
894  jw.write_kv("c_type", c_type); //FIXME
895  jw.write_kv("d_flags", d_flags); //FIXME
896  if (!controllable) {
897  jw.write_key("non_controllable"); jw.write(false);
898  }
899  if (!save_in_preset) {
900  jw.write_key("non_preset"); jw.write(false);
901  }
902  jw.end_object();
903 }
904 
906  : boost::noncopyable(),
907  _id(),
908  _name(),
909  _group(),
910  _desc(),
911  v_type(tp_float),
912  c_type(Continuous),
913  d_flags(0),
914  save_in_preset(true),
915  controllable(true),
916  do_not_save(false),
917  blocked(false),
918  used(false) {
920  while (jp.peek() != gx_system::JsonParser::end_object) {
922  if (jp.read_kv("id", _id) ||
923  jp.read_kv("name", _name) ||
924  jp.read_kv("group", _group) ||
925  jp.read_kv("desc", _desc)) {
926  } else if (jp.current_value() == "v_type") {
928  v_type = static_cast<value_type>(jp.current_value_int());
929  } else if (jp.current_value() == "c_type") {
931  c_type = static_cast<ctrl_type>(jp.current_value_int());
932  } else if (jp.current_value() == "d_flags") {
934  d_flags = jp.current_value_int();
935  } else if (jp.current_value() == "non_controllable") {
937  controllable = false;
938  } else if (jp.current_value() == "non_preset") {
940  save_in_preset = false;
941  } else {
943  "Parameter", Glib::ustring::compose("%1: unknown key: %2", _id, jp.current_value()));
944  jp.skip_object();
945  }
946  }
948 }
949 
951 }
952 
953 bool Parameter::midi_set(float n, float high, float llimit, float ulimit) {
954  assert(false);
955  return false;
956 }
957 
958 bool Parameter::midi_set_bpm(float n, float high, float llimit, float ulimit) {
959  assert(false);
960  return false;
961 }
962 
963 void Parameter::trigger_changed() {
964  assert(false);
965 }
966 
967 static int get_upper(const value_pair *vn) {
968  for (int n = 0; ; n++) {
969  if (!vn[n].value_id) {
970  return n - 1;
971  }
972  }
973 }
974 
975 void Parameter::range_warning(float value, float lower, float upper) {
977  _("parameter load"),
978  Glib::ustring::compose(_("parameter %1: value %2 out of range [%3, %4]"),
979  _id, value, lower, upper));
980 }
981 
982 const char *Parameter::get_typename() const {
983  static const char *tpname[] = {
984  "float", "int", "bool", "bool", "filename", "string", "special"};
985  assert(0 <= v_type and v_type < sizeof(tpname)/sizeof(tpname[0]));
986  return tpname[v_type];
987 }
988 
989 bool Parameter::hasRange() const {
990  return false;
991 }
992 
994  return 1;
995 }
996 
998  return 0;
999 }
1000 
1002  return 0;
1003 }
1004 
1006  return 0;
1007 }
1008 
1009 #ifndef NDEBUG
1010 void compare_parameter(const char *title, Parameter* p1, Parameter* p2, bool all) {
1011  if (p1->_id != p2->_id) {
1013  title, Glib::ustring::compose("Different ID's: %2 / %3",
1014  p1->_id, p2->_id));
1015  }
1016  if (p1->_name != p2->_name) {
1018  title, Glib::ustring::compose("[%1]: Different name: %2 / %3",
1019  p1->_id, p1->_name, p2->_name));
1020  }
1021  if (p1->_group != p2->_group) {
1023  title, Glib::ustring::compose("[%1]: Different group: %2 / %3",
1024  p1->_id, p1->_group, p2->_group));
1025  }
1026  if (p1->_desc != p2->_desc) {
1028  title, Glib::ustring::compose("[%1]: Different desc: %2 / %3",
1029  p1->_id, p1->_desc, p2->_desc));
1030  }
1031  if (p1->save_in_preset != p2->save_in_preset) {
1033  title, Glib::ustring::compose("[%1]: save_in_preset different: %2 / %3",
1034  p1->_id, p1->save_in_preset, p2->save_in_preset));
1035  }
1036  if (p1->controllable != p2->controllable) {
1038  title, Glib::ustring::compose("[%1]: controllable different: %2 / %3",
1039  p1->_id, p1->controllable, p2->controllable));
1040  }
1041  if (p1->used != p2->used) {
1043  title, Glib::ustring::compose("[%1]: used different: %2 / %3",
1044  p1->_id, p1->used, p2->used));
1045  }
1046  if (p1->c_type != p2->c_type) {
1048  title, Glib::ustring::compose("[%1]: c_type different: %2 / %3",
1049  p1->_id, p1->c_type, p2->c_type));
1050  }
1051  if (p1->v_type != p2->v_type) {
1053  title, Glib::ustring::compose("[%1]: v_type different: %2 / %3",
1054  p1->_id, p1->v_type, p2->v_type));
1055  return;
1056  }
1057  if (p1->isFloat()) {
1058  FloatParameter& f1 = p1->getFloat();
1059  FloatParameter& f2 = p2->getFloat();
1060  if (f1.value != f2.value) {
1062  title, Glib::ustring::compose("[%1]: value address different: %2 / %3",
1063  p1->_id, f1.value, f2.value));
1064  }
1065  if (f1.lower != f2.lower) {
1067 
1068  title, Glib::ustring::compose("[%1]: float lower different: %2 / %3",
1069  p1->_id, f1.lower, f2.lower));
1070  }
1071  if (f1.upper != f2.upper) {
1073  title, Glib::ustring::compose("[%1]: float upper different: %2 / %3",
1074  p1->_id, f1.upper, f2.upper));
1075  }
1076  if (f1.step != f2.step) {
1078  title, Glib::ustring::compose("[%1]: float step different: %2 / %3",
1079  p1->_id, f1.step, f2.step));
1080  }
1081  if (f1.std_value != f2.std_value) {
1083  title, Glib::ustring::compose("[%1]: float std value different: %2 / %3",
1084  p1->_id, f1.std_value, f2.std_value));
1085  }
1086  if (all) {
1087  if (f1.value != f2.value) {
1089  title, Glib::ustring::compose("[%1]: float value different: %2 / %3",
1090  p1->_id, *f1.value, *f2.value));
1091  }
1092  if (f1.json_value != f2.json_value) {
1094  title, Glib::ustring::compose("[%1]: float json value different: %2 / %3",
1095  p1->_id, f1.json_value, f2.json_value));
1096  }
1097  }
1098  return;
1099  }
1100  if (p1->isInt()) {
1101  assert(false);
1102  return;
1103  }
1104  if (p1->isBool()) {
1105  assert(false);
1106  return;
1107  }
1108  if (p1->isFile()) {
1109  assert(false);
1110  return;
1111  }
1112  assert(false);
1113 }
1114 #endif
1115 
1116 /* FloatParameter */
1117 
1119  jw.begin_object();
1120  jw.write_key("Parameter"); Parameter::serializeJSON(jw);
1121  jw.write_kv("lower", lower);
1122  jw.write_kv("upper", upper);
1123  jw.write_kv("step", step);
1124  jw.write_kv("value", *value);
1125  jw.write_kv("std_value", std_value);
1126  jw.end_object();
1127 }
1128 
1130  : Parameter(jp_next(jp, "Parameter")), json_value(0), value(&value_storage), std_value(0), lower(), upper(), step() {
1131  while (jp.peek() != gx_system::JsonParser::end_object) {
1133  if (jp.read_kv("lower", lower) ||
1134  jp.read_kv("upper", upper) ||
1135  jp.read_kv("step", step) ||
1136  jp.read_kv("value", *value) ||
1137  jp.read_kv("std_value", std_value)) {
1138  } else {
1140  "FloatParameter", Glib::ustring::compose("%1: unknown key: %2", _id, jp.current_value()));
1141  jp.skip_object();
1142  }
1143  }
1145 }
1146 
1148 }
1149 
1150 bool FloatParameter::set(float val) const {
1151  float v = min(max(val, lower), upper);
1152  if (v != *value) {
1153  *value = v;
1154  changed(v);
1155  return true;
1156  }
1157  return false;
1158 }
1159 
1161  return *value != 0;
1162 }
1163 
1164 float FloatParameter::idx_from_id(string v_id) {
1165  assert(false);
1166  return 0;
1167 }
1168 
1169 bool FloatParameter::midi_set(float n, float high, float llimit, float ulimit) {
1170  float v;
1171  switch (c_type) {
1172  case Continuous:
1173  assert(n >= 0 && n <= high);
1174  v = llimit + (n / high) * (ulimit - llimit);
1175  break;
1176  case Switch:
1177  v = (2*n > high ? 1.0 : 0.0);
1178  break;
1179  case Enum:
1180  v = lower + min(n, upper-lower);
1181  break;
1182  default:
1183  assert(false);
1184  return false;
1185  }
1186  if (v != *value) {
1187  *value = v;
1188  return true;
1189  }
1190  return false;
1191 }
1192 
1193 bool FloatParameter::midi_set_bpm(float n, float high, float llimit, float ulimit) {
1194  float v;
1195  switch (c_type) {
1196  case Continuous:
1197  assert(n >= 0 && n <= high);
1198  if (high <= ulimit) {
1199  v = max(llimit,min(ulimit,n));
1200  } else {
1201  v = llimit + (n / high) * (ulimit - llimit);
1202  }
1203  break;
1204  case Switch:
1205  v = (2*n > high ? 1.0 : 0.0);
1206  break;
1207  case Enum:
1208  v = lower + min(n, upper-lower);
1209  break;
1210  default:
1211  assert(false);
1212  return false;
1213  }
1214  if (v != *value) {
1215  *value = v;
1216  return true;
1217  }
1218  return false;
1219 }
1220 
1221 void FloatParameter::trigger_changed() {
1222  changed(*value);
1223 }
1224 
1226  json_value = std_value;
1227 }
1228 
1230  jw.write_kv(_id.c_str(), *value);
1231 }
1232 
1235  json_value = jp.current_value_float();
1236  if (json_value < lower-std::abs(5*FLT_EPSILON*lower) || json_value > upper+std::abs(5*FLT_EPSILON*upper)) {
1237  range_warning(json_value, lower, upper);
1238  json_value = std_value;
1239  }
1240 }
1241 
1243  return std::abs(json_value - *value) < 5*FLT_EPSILON;
1244 }
1245 
1247  set(json_value);
1248 }
1249 
1250 void FloatParameter::convert_from_range(float low, float up) {
1251  json_value = lower + (json_value - low) / (up - low) * (upper - lower);
1252 }
1253 
1255  return true;
1256 }
1257 
1259  return lower;
1260 }
1261 
1263  return upper;
1264 }
1265 
1267  return step;
1268 }
1269 
1270 
1271 /* FloatEnumParameter */
1272 
1273 static void serializeValueNames(gx_system::JsonWriter& jw, const value_pair *p) {
1274  jw.write_key("value_names");
1275  jw.begin_array();
1276  while (p->value_id) {
1277  jw.write(p->value_id);
1278  if (p->value_label) {
1279  jw.write(p->value_label);
1280  } else {
1281  jw.write(p->value_id);
1282  }
1283  p++;
1284  }
1285  jw.end_array();
1286 }
1287 
1289  jw.begin_object();
1290  jw.write_key("FloatParameter"); FloatParameter::serializeJSON(jw);
1291  serializeValueNames(jw, value_names);
1292  jw.end_object();
1293 }
1294 
1295 FloatEnumParameter::FloatEnumParameter(const string& id, const string& name, const value_pair* vn, bool preset,
1296  float *v, int sv, int low, bool ctrl, bool no_init):
1297  FloatParameter(id, name, Enum, preset, v, sv, low, low+get_upper(vn), 1, ctrl, no_init),
1298  value_names(vn) {}
1299 
1301  return value_names;
1302 }
1303 
1305  jw.write_key(_id.c_str());
1306  jw.write(value_names[static_cast<int>(round(*value-lower))].value_id);
1307 }
1308 
1310  int up = static_cast<int>(round(upper));
1311  int low = static_cast<int>(round(lower));
1312  int n = 0;
1313  for (; n <= up-low; n++) {
1314  if (v_id == value_names[n].value_id) {
1315  return low + n;
1316  }
1317  }
1318  return -1;
1319 }
1320 
1324  // old version compatability
1325  json_value = jp.current_value_int();
1326  return;
1327  }
1329  float n = idx_from_id(jp.current_value());
1330  if (n < 0) {
1332  _("read parameter"), (boost::format(_("parameter %1%: unknown enum value: %2%"))
1333  % _id % jp.current_value()).str());
1334  n = lower;
1335  }
1336  json_value = n;
1337 }
1338 
1339 /* IntParameter */
1340 
1342  jw.begin_object();
1343  jw.write_key("Parameter"); Parameter::serializeJSON(jw);
1344  jw.write_kv("lower", lower);
1345  jw.write_kv("upper", upper);
1346  jw.write_kv("value", *value);
1347  jw.write_kv("std_value", std_value);
1348  jw.end_object();
1349 }
1350 
1352  : Parameter(jp_next(jp, "Parameter")), json_value(0), value(&value_storage), std_value(0), lower(), upper() {
1353  while (jp.peek() != gx_system::JsonParser::end_object) {
1355  if (jp.read_kv("lower", lower) ||
1356  jp.read_kv("upper", upper) ||
1357  jp.read_kv("value", *value) ||
1358  jp.read_kv("std_value", std_value)) {
1359  } else {
1361  "IntParameter", Glib::ustring::compose("%1: unknown key: %2", _id, jp.current_value()));
1362  jp.skip_object();
1363  }
1364  }
1366 }
1367 
1369 }
1370 
1371 bool IntParameter::set(int val) const {
1372  int v = min(max(val, lower), upper);
1373  if (v != *value) {
1374  *value = v;
1375  changed(v);
1376  return true;
1377  }
1378  return false;
1379 }
1380 
1381 int IntParameter::idx_from_id(string v_id) {
1382  assert(false);
1383  return 0;
1384 }
1385 
1387  return *value != 0;
1388 }
1389 
1390 bool IntParameter::midi_set(float n, float high, float llimit, float ulimit) {
1391  int v;
1392  switch (c_type) {
1393  case Continuous:
1394  assert(false); // not implemented
1395  return false;
1396  case Switch:
1397  assert(false); // not implemented
1398  return false;
1399  case Enum:
1400  v = lower + min(static_cast<int>(n), upper-lower);
1401  break;
1402  default:
1403  assert(false);
1404  return false;
1405  }
1406  if (v != *value) {
1407  *value = v;
1408  return true;
1409  }
1410  return false;
1411 }
1412 
1413 void IntParameter::trigger_changed() {
1414  changed(*value);
1415 }
1416 
1418  json_value = std_value;
1419 }
1420 
1422  jw.write_kv(_id.c_str(), *value);
1423 }
1424 
1427  json_value = jp.current_value_int();
1428  if (json_value < lower || json_value > upper) {
1429  range_warning(json_value, lower, upper);
1430  }
1431 }
1432 
1434  return json_value == *value;
1435 }
1436 
1438  set(json_value);
1439 }
1440 
1442  return true;
1443 }
1444 
1446  return lower;
1447 }
1448 
1450  return upper;
1451 }
1452 
1453 /* EnumParameter */
1454 
1456  jw.begin_object();
1457  jw.write_key("IntParameter"); IntParameter::serializeJSON(jw);
1458  serializeValueNames(jw, value_names);
1459  jw.end_object();
1460 }
1461 
1462 EnumParameter::EnumParameter(const string& id, const string& name, const value_pair* vn, bool preset,
1463  int *v, int sv, bool ctrl):
1464  IntParameter(id, name, Enum, preset, v, sv, 0, get_upper(vn), ctrl),
1465  value_names(vn) {}
1466 
1468  return value_names;
1469 }
1470 
1471 int EnumParameter::idx_from_id(string v_id) {
1472  int n = 0;
1473  for (; n <= upper; n++) {
1474  if (v_id == value_names[n].value_id) {
1475  return n;
1476  }
1477  }
1478  return -1;
1479 }
1480 
1482  jw.write_key(_id.c_str());
1483  jw.write(value_names[*value].value_id);
1484 }
1485 
1489  // old version compatability
1490  json_value = jp.current_value_int();
1491  return;
1492  }
1494  int n = idx_from_id(jp.current_value());
1495  if (n < 0) {
1497  _("read parameter"), (boost::format(_("parameter %1%: unknown enum value: %2%"))
1498  % _id % jp.current_value()).str());
1499  n = 0;
1500  }
1501  json_value = n;
1502 }
1503 
1504 /* derived enum parameters */
1505 
1506 typedef std::pair<std::string,std::string> id_label;
1507 
1508 void enum_parameter_load_values(gx_system::JsonParser& jp, std::vector<id_label>& value_array, const value_pair **value_names) {
1509  while (jp.peek() != gx_system::JsonParser::end_object) {
1511  if (jp.current_value() == "value_names") {
1513  while (jp.peek() != gx_system::JsonParser::end_array) {
1515  std::string value_id = jp.current_value();
1517  std::string value_label = jp.current_value();
1518  value_array.push_back(id_label(value_id, value_label));
1519  }
1521  } else {
1523  "EnumValueNames", Glib::ustring::compose("unknown key: %1", jp.current_value()));
1524  jp.skip_object();
1525  }
1526  }
1528  value_pair* p = new value_pair[value_array.size()+1];
1529  *value_names = p;
1530  for (std::vector<id_label>::iterator i = value_array.begin(); i != value_array.end(); ++i) {
1531  p->value_id = i->first.c_str();
1532  p->value_label = i->second.c_str();
1533  p++;
1534  }
1535  p->value_id = p->value_label = 0;
1536 }
1537 
1539 private:
1540  std::vector<id_label> value_array;
1541 public:
1544 };
1545 
1547  : FloatEnumParameter(jp), value_array() {
1548  enum_parameter_load_values(jp, value_array, &value_names);
1549 }
1550 
1552  delete value_names;
1553 }
1554 
1556 private:
1557  std::vector<id_label> value_array;
1558 public:
1560  ~EnumParameterD();
1561 };
1562 
1564  : EnumParameter(jp), value_array() {
1565  enum_parameter_load_values(jp, value_array, &value_names);
1566 }
1567 
1569  delete value_names;
1570 }
1571 
1572 
1573 /* BoolParameter */
1574 
1576  jw.begin_object();
1577  jw.write_key("Parameter"); Parameter::serializeJSON(jw);
1578  jw.write_kv("value", *value);
1579  jw.write_kv("std_value", std_value);
1580  jw.end_object();
1581 }
1582 
1584  : Parameter(jp_next(jp, "Parameter")), json_value(0), value(&value_storage), std_value(0) {
1585  while (jp.peek() != gx_system::JsonParser::end_object) {
1587  if (jp.read_kv("value", *value) || jp.read_kv("std_value", std_value)) {
1588  } else {
1590  "BoolParameter", Glib::ustring::compose("%1: unknown key: %2", _id, jp.current_value()));
1591  jp.skip_object();
1592  }
1593  }
1595 }
1596 
1598 }
1599 
1600 bool BoolParameter::set(bool val) const {
1601  if (val != *value) {
1602  *value = val;
1603  changed(val);
1604  return true;
1605  }
1606  return false;
1607 }
1608 
1610  return *value;
1611 }
1612 
1613 bool BoolParameter::midi_set(float n, float high, float llimit, float ulimit) {
1614  bool v;
1615  switch (c_type) {
1616  case Switch:
1617  v = (2*n > high);
1618  break;
1619  default:
1620  assert(false);
1621  return false;
1622  }
1623  if (v != *value) {
1624  *value = v;
1625  return true;
1626  }
1627  return false;
1628 }
1629 
1630 void BoolParameter::trigger_changed() {
1631  changed(*value);
1632 }
1633 
1635  json_value = std_value;
1636 }
1637 
1639  jw.write_kv(_id.c_str(), *value);
1640 }
1641 
1644  if (jp.current_value_int() < 0 || jp.current_value_int() > 1) {
1645  range_warning(json_value, 0, 1);
1646  }
1647  json_value = jp.current_value_int();
1648 }
1649 
1651  return json_value == *value;
1652 }
1653 
1655  set(json_value);
1656 }
1657 
1658 
1659 /* FileParameter */
1660 
1662  jw.begin_object();
1663  jw.write_key("Parameter"); Parameter::serializeJSON(jw);
1664  jw.write_kv("value", value->get_path());
1665  jw.write_kv("std_value", std_value->get_path());
1666  jw.end_object();
1667 }
1668 
1670  : Parameter(jp_next(jp, "Parameter")), value(0), std_value(0), json_value(0) {
1671  while (jp.peek() != gx_system::JsonParser::end_object) {
1673  if (jp.current_value() == "value") {
1675  value = Gio::File::create_for_path(jp.current_value());
1676  } else if (jp.current_value() == "std_value") {
1678  std_value = Gio::File::create_for_path(jp.current_value());
1679  } else {
1681  "FileParameter", Glib::ustring::compose("%1: unknown key: %2", _id, jp.current_value()));
1682  jp.skip_object();
1683  }
1684  }
1686 }
1687 
1688 void FileParameter::set_path(const string& path) {
1689  Glib::RefPtr<Gio::File> v = Gio::File::create_for_path(path);
1690  if (is_equal(v)) {
1691  return;
1692  }
1693  value = v;
1694  changed();
1695 }
1696 
1697 bool FileParameter::set(const Glib::RefPtr<Gio::File>& val) {
1698  if (is_equal(val)) {
1699  return false;
1700  }
1701  value = val;
1702  changed();
1703  return true;
1704 }
1705 
1706 void FileParameter::set_standard(const string& filename) {
1707  std_value = Gio::File::create_for_path(filename);
1708  if (!value) {
1709  value = std_value->dup();
1710  changed();
1711  }
1712 }
1713 
1715  json_value = std_value->dup();
1716  changed();
1717 }
1718 
1720  return bool(value);
1721 }
1722 
1724  jw.write_kv(_id.c_str(), get_path());
1725 }
1726 
1729  json_value = Gio::File::create_for_path(jp.current_value());
1730 }
1731 
1733  return json_value->get_path() == value->get_path(); //FIXME
1734 }
1735 
1737  set(json_value);
1738 }
1739 
1740 static string get_file_id(const Glib::RefPtr<Gio::File>& f) {
1741  return f->query_info(G_FILE_ATTRIBUTE_ID_FILE)->get_attribute_string(G_FILE_ATTRIBUTE_ID_FILE);
1742 }
1743 
1744 bool FileParameter::is_equal(const Glib::RefPtr<Gio::File>& v) const {
1745  string id, id2;
1746  try {
1747  id = get_file_id(value);
1748  } catch(Gio::Error& ex) {
1749  return false; // FIXME check type of exception
1750  }
1751  try {
1752  id2 = get_file_id(v);
1753  } catch(Gio::Error& ex) {
1754  return false; // FIXME check type of exception
1755  }
1756  return id == id2;
1757 }
1758 
1759 string FileParameter::get_path() const {
1760  return value->get_path();
1761 }
1762 
1764  return value->get_parent()->get_path();
1765 }
1766 
1768  return value->get_parse_name();
1769 }
1770 
1772  return value->query_info(G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME)->get_display_name();
1773 }
1774 
1775 void FileParameter::copy(const string& destination) const {
1776  value->copy(Gio::File::create_for_path(destination));
1777 }
1778 
1779 
1780 /* StringParameter */
1781 
1783  jw.begin_object();
1784  jw.write_key("Parameter"); Parameter::serializeJSON(jw);
1785  jw.write_kv("value", *value);
1786  jw.write_kv("std_value", std_value);
1787  jw.end_object();
1788 }
1789 
1791  : Parameter(jp_next(jp, "Parameter")), json_value(""), value(&value_storage), std_value("") {
1792  while (jp.peek() != gx_system::JsonParser::end_object) {
1794  if (jp.read_kv("value", *value) || jp.read_kv("std_value", std_value)) {
1795  } else {
1797  "StringParameter", Glib::ustring::compose("%1: unknown key: %2", _id, jp.current_value()));
1798  jp.skip_object();
1799  }
1800  }
1802 }
1803 
1805 }
1806 
1807 bool StringParameter::set(const Glib::ustring& val) const {
1808  if (val != *value) {
1809  *value = val;
1810  changed(*value);
1811  return true;
1812  }
1813  return false;
1814 }
1815 
1817  return !value->empty();
1818 }
1819 
1821  json_value = std_value;
1822 }
1823 
1825  jw.write_kv(_id.c_str(), *value);
1826 }
1827 
1830  json_value = jp.current_value();
1831 }
1832 
1834  return json_value == *value;
1835 }
1836 
1838  set(json_value);
1839 }
1840 
1841 /****************************************************************
1842  ** Parameter Map
1843  */
1844 
1846  : id_map(),
1847  replace_mode(false) {
1848 }
1849 
1851  for (iterator i = id_map.begin(); i != id_map.end(); ++i) {
1852  delete i->second;
1853  }
1854 }
1855 
1857  if (p->isFloat()) {
1858  if (p->getControlType() == Parameter::Enum) {
1859  jw.write("FloatEnum");
1860  } else {
1861  jw.write("Float");
1862  }
1863  } else if (p->isInt()) {
1864  if (p->getControlType() == Parameter::Enum) {
1865  jw.write("Enum");
1866  } else {
1867  jw.write("Int");
1868  }
1869  } else if (p->isBool()) {
1870  jw.write("Bool");
1871  } else if (p->isFile()) {
1872  jw.write("File");
1873  } else if (p->isString()) {
1874  jw.write("String");
1875  } else if (dynamic_cast<JConvParameter*>(p) != 0) {
1876  jw.write("JConv");
1877  } else if (dynamic_cast<SeqParameter*>(p) != 0) {
1878  jw.write("Seq");
1879  } else {
1880 #ifndef NDEBUG
1881  cerr << "skipping " << p->id() << endl;
1882 #endif
1883  return;
1884  }
1885  p->serializeJSON(jw);
1886 }
1887 
1889  jw.begin_array();
1890  for (iterator i = id_map.begin(); i != id_map.end(); ++i) {
1891  writeJSON_one(jw, i->second);
1892  }
1893  jw.end_array();
1894 }
1895 
1898  if (jp.current_value() == "FloatEnum") {
1899  return insert(new FloatEnumParameterD(jp));
1900  } else if (jp.current_value() == "Float") {
1901  return insert(new FloatParameter(jp));
1902  } else if (jp.current_value() == "Enum") {
1903  return insert(new EnumParameterD(jp));
1904  } else if (jp.current_value() == "Int") {
1905  return insert(new IntParameter(jp));
1906  } else if (jp.current_value() == "Bool") {
1907  return insert(new BoolParameter(jp));
1908  } else if (jp.current_value() == "File") {
1909  return insert(new FileParameter(jp));
1910  } else if (jp.current_value() == "String") {
1911  return insert(new StringParameter(jp));
1912  } else if (jp.current_value() == "JConv") {
1913  return insert(new JConvParameter(jp));
1914  } else if (jp.current_value() == "Seq") {
1915  return insert(new SeqParameter(jp));
1916  } else {
1918  "ParamMap", Glib::ustring::compose("unknown parameter type: %1", jp.current_value()));
1919  jp.skip_object();
1920  return 0;
1921  }
1922 }
1923 
1926  while (jp.peek() != gx_system::JsonParser::end_array) {
1927  readJSON_one(jp);
1928  }
1930 }
1931 
1932 #ifndef NDEBUG
1933 void ParamMap::unique_id(Parameter* param) {
1934  if (id_map.find(param->id()) != id_map.end()) {
1935  gx_print_error("Debug Check", "id registered twice: " + param->id());
1936  }
1937 }
1938 
1939 void ParamMap::check_id(const string& id) {
1940  if (!hasId(id)) {
1941  cerr << "string-id not found: " << id << endl;
1942  }
1943 }
1944 
1945 void ParamMap::check_p(const char *p) {
1946  if (!hasId(p)) {
1947  cerr << "char-id not found: " << p << endl;
1948  }
1949 }
1950 
1951 void ParamMap::dump(const string& fmt) {
1952  gx_system::JsonWriter *p = 0;
1954  if (fmt == "json") {
1955  jw.set_stream(&cout);
1956  p = &jw;
1957  jw.begin_array();
1958  jw.newline();
1959  } else {
1960  printf("parameter map dump\n");
1961  }
1962  for (iterator i = id_map.begin(); i != id_map.end(); ++i) {
1963  i->second->dump(p);
1964  }
1965  if (p) {
1966  jw.end_array();
1967  jw.close();
1968  } else {
1969  printf("---------------------\n");
1970  }
1971 }
1972 
1974  if (jw) {
1975  jw->begin_array();
1976  jw->write(id());
1977  switch (c_type) {
1978  case None: jw->write("None"); break;
1979  case Continuous: jw->write("Cont"); break;
1980  case Switch: jw->write("Swth"); break;
1981  case Enum: jw->write("Enum"); break;
1982  default: assert(false);
1983  }
1984  if (save_in_preset) {
1985  jw->write("preset");
1986  }
1987  if (controllable) {
1988  jw->write("control");
1989  }
1990  jw->write(l_group());
1991  jw->write(l_name());
1992  /*
1993  switch (v_type) {
1994  case tp_float: jw->write("f"); jw->write(getFloat().get_value()); break;
1995  case tp_int: jw->write("i"); jw->write(getInt().get_value()); break;
1996  case tp_bool: jw->write("b"); jw->write(getBool().get_value()); break;
1997  case tp_switch: jw->write("s"); jw->write(getSwitch().get()); break;
1998  case tp_file: jw->write("F"); jw->write(getFile().get_parse_name()); break;
1999  case tp_string: jw->write("S"); jw->write(getString().get_value()); break;
2000  case tp_special: jw->write("G"); break;
2001  default: assert(false);
2002  }
2003  */
2004  jw->write(getLowerAsFloat());
2005  jw->write(getUpperAsFloat());
2006  jw->write(getStepAsFloat());
2007  const value_pair *vn = getValueNames();
2008  if (vn) {
2009  jw->begin_array();
2010  for (int n = 0; ; ++n) {
2011  if (!vn[n].value_id) {
2012  break;
2013  }
2014  jw->begin_array();
2015  jw->write(vn[n].value_id);
2016  jw->write(vn[n].value_label ? vn[n].value_label : vn[n].value_id);
2017  jw->end_array();
2018  }
2019  jw->end_array();
2020  }
2021  jw->end_array();
2022  jw->newline();
2023  } else {
2024  printf("P: %s vt=%d ct=%d c=%d\n", _id.c_str(), v_type, c_type, controllable);
2025  }
2026 }
2027 #endif
2028 
2029 Parameter *ParamMap::insert(Parameter* param) {
2030  if (replace_mode) {
2031  map<string, Parameter*>::iterator ii = id_map.find(param->id());
2032  if (ii != id_map.end()) {
2033  Parameter *p = ii->second;
2034  insert_remove(p,false);
2035  id_map.erase(ii);
2036  delete p;
2037  }
2038  }
2039  debug_check(unique_id, param);
2040  id_map.insert(pair<string, Parameter*>(param->id(), param));
2041  insert_remove(param,true);
2042  return param;
2043 }
2044 
2046  if (!p) {
2047  return;
2048  }
2049  insert_remove(p, false);
2050  id_map.erase(p->id());
2051  delete p;
2052 }
2053 
2054 void ParamMap::unregister(const string& id) {
2055  if (!hasId(id)) {
2056  return;
2057  }
2058  unregister(&(*this)[id]);
2059 }
2060 
2062  for (iterator i = id_map.begin(); i != id_map.end(); ++i) {
2063  i->second->stdJSON_value();
2064  i->second->setJSON_value();
2065  }
2066 }
2067 
2068 static inline bool compare_groups(const std::string& id, const char **groups) {
2069  if (!groups) {
2070  return false;
2071  }
2072  for (const char **g = groups; *g; g += 2) {
2073  const char *p = *g;
2074  if ((*p) != '.') {
2075  continue;
2076  }
2077  p++;
2078  int n = strlen(p);
2079  if (strncmp(id.c_str(), p, n) == 0 && id[n] == '.') {
2080  return true;
2081  }
2082  }
2083  return false;
2084 }
2085 
2086 bool ParamMap::unit_has_std_values(const PluginDef *pdef) const {
2087  std::string group_id(pdef->id);
2088  group_id += ".";
2089  std::string on_off = group_id + "on_off";
2090  std::string pp = group_id + "pp";
2091  std::string position = group_id + "position";
2092  for (iterator i = begin(); i != end(); ++i) {
2093  if (i->first.compare(0, group_id.size(), group_id) == 0 || compare_groups(i->first, pdef->groups)) {
2094  if (i->second->isInPreset()) {
2095  if (i->first != on_off && i->first != pp && i->first != position) {
2096  i->second->stdJSON_value();
2097  if (!i->second->compareJSON_value()) {
2098  return false;
2099  break;
2100  }
2101  }
2102  }
2103  }
2104  }
2105  return true;
2106 }
2107 
2108 // reset all parameters to default settings
2109 void ParamMap::reset_unit(const PluginDef *pdef) const {
2110  std::string group_id(pdef->id);
2111  group_id += ".";
2112  std::string on_off = group_id + "on_off";
2113  std::string pp = group_id + "pp";
2114  std::string position = group_id + "position";
2115  for (iterator i = begin(); i != end(); ++i) {
2116  if (i->first.compare(0, group_id.size(), group_id) == 0 || compare_groups(i->first, pdef->groups)) {
2117  if (i->second->isInPreset()) {
2118  if (i->first != on_off && i->first != pp && i->first != position) {
2119  i->second->stdJSON_value();
2120  i->second->setJSON_value();
2121  }
2122  }
2123  }
2124  }
2125 }
2126 
2127 } // namespace gx_gui
ParameterV< float > FloatParameter
Definition: gx_parameter.h:93
ParameterV< GxSeqSettings > SeqParameter
CmdConnection::msg_type end
Definition: jsonrpc.cpp:258
int get_last_midi_control_value(unsigned int n)
Definition: gx_parameter.h:780
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:782
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