Guitarix
jsonrpc.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2013 Andreas Degert
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17  */
18 
19 #include "jsonrpc.h"
20 #include <netinet/in.h>
21 #include <netinet/tcp.h>
22 #if HAVE_BLUEZ
23 #include <bluetooth/bluetooth.h>
24 #include <bluetooth/rfcomm.h>
25 #endif
26 
27 #include "jsonrpc_methods.cc"
28 
30  switch (s) {
31  case gx_engine::kEngineOff: return "stopped";
32  case gx_engine::kEngineOn: return "running";
33  case gx_engine::kEngineBypass: return "bypassed";
34  }
35  assert(false);
36  return 0;
37 }
38 
40  if (s == "stopped") {
41  return gx_engine::kEngineOff;
42  }
43  if (s == "running") {
44  return gx_engine::kEngineOn;
45  }
46  if (s == "bypassed") {
48  }
49  assert(false);
50  return gx_engine::kEngineOff;
51 }
52 
53 class RpcError: public exception {
54 public:
55  int code;
56  Glib::ustring message;
57 public:
58  RpcError(int code_, Glib::ustring message_): code(code_), message(message_) {}
59  ~RpcError() throw() { }
60  virtual const char* what() const throw() { return message.c_str(); }
61 };
62 
63 
64 class JsonString: public JsonValue {
65 private:
66  Glib::ustring string;
67  JsonString(Glib::ustring s): JsonValue(), string(s) {}
68  ~JsonString() {}
69  friend class JsonArray;
70  virtual const Glib::ustring& getString() const;
71 };
72 
73 class JsonFloat: public JsonValue {
74 private:
75  double value;
76  JsonFloat(double v): value(v) {}
77  ~JsonFloat() {}
78  friend class JsonArray;
79  virtual double getFloat() const;
80 };
81 
82 class JsonInt: public JsonValue {
83 private:
84  int value;
85  JsonInt(int v): value(v) {}
86  ~JsonInt() {}
87  friend class JsonArray;
88  virtual double getFloat() const;
89  virtual int getInt() const;
90 };
91 
92 class JsonObject: public JsonValue {
93 private:
94  streampos position;
96  JsonObject(gx_system::JsonParser& jp_): JsonValue(), position(jp_.get_streampos()), jp(jp_) {}
97  ~JsonObject() {}
98  friend class JsonArray;
99  virtual gx_system::JsonSubParser getSubParser() const;
100 };
101 
103  for (iterator i = begin(); i != end(); ++i) {
104  delete *i;
105  }
106 }
107 
109  if (i >= size()) {
110  throw RpcError(-32602, "Invalid param -- wrong argument count");
111  }
112  return std::vector<JsonValue*>::operator[](i);
113 }
114 
117  jp.next();
118  push_back(new JsonString(jp.current_value()));
119  } else if (jp.peek() == gx_system::JsonParser::value_number) {
120  jp.next();
121  const char *str = jp.current_value().c_str();
122  char *endptr;
123  int n = strtol(str, &endptr, 10);
124  if (*endptr == '\0') {
125  push_back(new JsonInt(n));
126  } else {
127  istringstream b(str);
128  float f;
129  b >> f;
130  push_back(new JsonFloat(f));
131  }
133  push_back(new JsonObject(jp));
134  jp.skip_object();
135  } else {
136  throw gx_system::JsonException("unexpected token");
137  }
138 }
139 
140 double JsonValue::getFloat() const {
141  throw RpcError(-32602, "Invalid param -- float expected");
142 }
143 
144 int JsonValue::getInt() const {
145  throw RpcError(-32602, "Invalid param -- int expected");
146 }
147 
148 const Glib::ustring& JsonValue::getString() const {
149  throw RpcError(-32602, "Invalid param -- string expected");
150 }
151 
153  throw RpcError(-32602, "Invalid param -- object expected");
154 }
155 
156 double JsonFloat::getFloat() const {
157  return value;
158 }
159 
160 double JsonInt::getFloat() const {
161  return value;
162 }
163 
164 int JsonInt::getInt() const {
165  return value;
166 }
167 
168 const Glib::ustring& JsonString::getString() const {
169  return string;
170 }
171 
172 gx_system::JsonSubParser JsonObject::getSubParser() const {
173  return gx_system::JsonSubParser(jp, position);
174 }
175 
176 
177 /****************************************************************
178  ** class UiBuilderVirt
179  */
180 
181 class CmdConnection;
182 
183 class UiBuilderVirt: public UiBuilder {
184 private:
185  static gx_system::JsonWriter *jw;
186  static const gx_system::CmdlineOptions *options;
187  static void openTabBox_(const char* label);
188  static void openVerticalBox_(const char* label);
189  static void openVerticalBox1_(const char* label);
190  static void openVerticalBox2_(const char* label);
191  static void openHorizontalBox_(const char* label);
192  static void openHorizontalhideBox_(const char* label);
193  static void openHorizontalTableBox_(const char* label);
194  static void openFrameBox_(const char* label);
195  static void openFlipLabelBox_(const char* label);
196  static void openpaintampBox_(const char* label);
197  static void insertSpacer_();
198  static void set_next_flags_(int flags);
199  static void create_big_rackknob_(const char *id, const char *label);
200  static void create_mid_rackknob_(const char *id, const char *label);
201  static void create_small_rackknob_(const char *id, const char *label);
202  static void create_small_rackknobr_(const char *id, const char *label);
203  static void create_master_slider_(const char *id, const char *label);
204  static void create_feedback_slider_(const char *id, const char *label);
205  static void create_selector_no_caption_(const char *id);
206  static void create_selector_(const char *id, const char *label);
207  static void create_simple_meter_(const char *id);
208  static void create_simple_c_meter_(const char *id,const char *idl, const char *label);
209  static void create_spin_value_(const char *id, const char *label);
210  static void create_switch_no_caption_(const char *sw_type,const char * id);
211  static void create_feedback_switch_(const char *sw_type,const char * id);
212  static void create_fload_switch_(const char *sw_type,const char * id,const char * idf);
213  static void create_switch_(const char *sw_type,const char * id, const char *label);
214  static void create_wheel_(const char * id, const char *label);
215  static void create_port_display_(const char *id, const char *label);
216  static void create_p_display_(const char *id, const char *idl, const char *idh);
217  static void create_simple_spin_value_(const char *id);
218  static void create_eq_rackslider_no_caption_(const char *id);
219  static void closeBox_();
220  static void load_glade_(const char *data);
221  static void load_glade_file_(const char *fname);
222 public:
224  ~UiBuilderVirt();
225 };
226 
227 
228 /****************************************************************
229  ** class CmdConnection
230  */
231 
232 const static int InterfaceVersionMajor = 1;
233 const static int InterfaceVersionMinor = 0;
234 
235 CmdConnection::CmdConnection(GxService& serv_, const Glib::RefPtr<Gio::SocketConnection>& connection_)
236  : serv(serv_),
237  connection(connection_),
238  outgoing(),
239  current_offset(0),
240  midi_config_mode(false),
241  flags(),
242  maxlevel() {
243  jp.start_parser();
244 }
245 
247  if (midi_config_mode) {
248  serv.jack.get_engine().controller_map.set_config_mode(false, -1);
249  }
250 
251 }
252 
253 static struct {
254  const char *token;
257 } token_range[] = {
273 };
274 
275 bool CmdConnection::find_token(const Glib::ustring& token, msg_type *start, msg_type *end) {
276  for (unsigned int i = 0; i < sizeof(token_range) / sizeof(token_range[0]); ++i) {
277  if (token == token_range[i].token) {
278  *start = token_range[i].start;
279  *end = token_range[i].end;
280  return true;
281  }
282  }
283  return false;
284 }
285 
286 void CmdConnection::listen(const Glib::ustring& tp) {
287  msg_type start, end;
288  if (!find_token(tp, &start, &end)) {
289  cerr << "unknown listen token: " << tp << endl;
290  return;
291  }
292  for (int i = start; i <= end; i++) {
293  activate(i, true);
294  }
295 }
296 
297 void CmdConnection::unlisten(const Glib::ustring& tp) {
298  msg_type start, end;
299  if (!find_token(tp, &start, &end)) {
300  cerr << "unknown listen token: " << tp << endl;
301  return;
302  }
303  for (int i = start; i <= end; i++) {
304  activate(i, false);
305  }
306 }
307 
308 void CmdConnection::send_notify_end(gx_system::JsonStringWriter& jw, bool send_out) {
309  jw.send_notify_end();
310  if (send_out) {
311  jw.finish();
312  send(jw);
313  }
314 }
315 
316 static void write_plugin_state(gx_system::JsonWriter& jw, gx_engine::Plugin *i) {
317  jw.begin_object();
318  jw.write_kv("id", i->get_pdef()->id);
319  jw.write_kv("on_off", i->get_on_off());
320  jw.write_kv("box_visible", i->get_box_visible());
321  jw.write_kv("position", i->get_position());
322  jw.write_kv("post_pre", i->get_effect_post_pre());
323  jw.write_kv("stereo", (i->get_pdef()->flags & PGN_STEREO) == PGN_STEREO);
324  const char *p;
325  p = i->get_pdef()->category;
326  if (p) {
327  jw.write_kv("category", p);
328  }
329  p = i->get_pdef()->name;
330  if (p) {
331  jw.write_kv("name", p);
332  }
333  p = i->get_pdef()->shortname;
334  if (p) {
335  jw.write_kv("shortname", p);
336  }
337  p = i->get_pdef()->description;
338  if (p) {
339  jw.write_kv("description", p);
340  }
341  jw.end_object();
342 }
343 
344 static void write_parameter_state(gx_system::JsonWriter& jw, const gx_engine::Parameter& p) {
345  jw.begin_object();
346  if (p.hasRange()) {
347  jw.write_kv("lower_bound", p.getLowerAsFloat());
348  jw.write_kv("upper_bound", p.getUpperAsFloat());
349  jw.write_kv("step", p.getStepAsFloat());
350  }
351  const value_pair *pairs = p.getValueNames();
352  if (pairs) {
353  jw.write_key("value_names");
354  jw.begin_array();
355  for (; pairs->value_id; pairs++) {
356  jw.begin_array();
357  jw.write(pairs->value_id);
358  jw.write(p.value_label(*pairs));
359  jw.end_array();
360  }
361  jw.end_array();
362  }
363  jw.write_kv("name", p.l_name());
364  jw.write_kv("group", p.l_group());
365  jw.write_kv("type", p.get_typename());
368  jw.write_key("ctl_continous");
369  jw.write(1);
370  } else if (t == gx_engine::Parameter::Switch) {
371  jw.write_key("ctl_switch");
372  jw.write(1);
373  } else if (t == gx_engine::Parameter::Enum) {
374  jw.write_key("ctl_enum");
375  jw.write(1);
376  }
377  jw.write_key("value");
378  jw.begin_object();
379  p.writeJSON(jw);
380  jw.end_object();
381  jw.end_object();
382 }
383 
384 static inline bool unit_match(const Glib::ustring& id, const Glib::ustring& prefix, const char** gl) {
385  if (id.compare(0, prefix.size(), prefix) == 0) {
386  return true;
387  }
388  if (!gl) {
389  return false;
390  }
391  while (*gl) {
392  const char *p = *gl;
393  if (p[0] == '.') {
394  p += 1;
395  int n = strlen(p);
396  if (strncmp(id.c_str(), p, n) == 0 && id[n] == '.') {
397  return true;
398  }
399  }
400  gl += 2;
401  }
402  return false;
403 }
404 
405 #define START_FUNCTION_SWITCH(v) switch (v) {
406 #define FUNCTION(n) break; case RPCM_##n:
407 #define PROCEDURE(n) break; case RPNM_##n:
408 #define END_FUNCTION_SWITCH(s) break; default: s; }
409 
410 void CmdConnection::call(gx_system::JsonWriter& jw, const methodnames *mn, JsonArray& params) {
411  START_FUNCTION_SWITCH(mn->m_id);
412 
413  FUNCTION(get) {
414  gx_engine::ParamMap& param = serv.settings.get_param();
415  jw.begin_object();
416  for (JsonArray::iterator i = params.begin(); i != params.end(); ++i) {
417  const Glib::ustring& attr = (*i)->getString();
418  if (!param.hasId(attr)) {
419  jw.write_key(attr);
420  if (attr == "sys.active_mono_plugins") {
421  list<gx_engine::Plugin*> l;
422  serv.jack.get_engine().pluginlist.ordered_mono_list(l, PGN_MODE_NORMAL);
423  jw.begin_array();
424  for (list<gx_engine::Plugin*>::iterator i = l.begin(); i != l.end(); ++i) {
425  write_plugin_state(jw, *i);
426  }
427  jw.end_array();
428  } else if (attr == "sys.active_stereo_plugins") {
429  list<gx_engine::Plugin*> l;
430  serv.jack.get_engine().pluginlist.ordered_stereo_list(l, PGN_MODE_NORMAL);
431  jw.begin_array();
432  for (list<gx_engine::Plugin*>::iterator i = l.begin(); i != l.end(); ++i) {
433  write_plugin_state(jw, *i);
434  }
435  jw.end_array();
436  } else if (attr == "sys.visible_mono_plugins") {
437  list<gx_engine::Plugin*> l;
438  const int bits = (PGN_GUI|gx_engine::PGNI_DYN_POSITION);
439  serv.jack.get_engine().pluginlist.ordered_list(l, false, bits, bits);
440  jw.begin_array();
441  for (list<gx_engine::Plugin*>::iterator i = l.begin(); i != l.end(); ++i) {
442  write_plugin_state(jw, *i);
443  }
444  jw.end_array();
445  } else if (attr == "sys.visible_stereo_plugins") {
446  list<gx_engine::Plugin*> l;
447  const int bits = (PGN_GUI|gx_engine::PGNI_DYN_POSITION);
448  serv.jack.get_engine().pluginlist.ordered_list(l, true, bits, bits);
449  jw.begin_array();
450  for (list<gx_engine::Plugin*>::iterator i = l.begin(); i != l.end(); ++i) {
451  write_plugin_state(jw, *i);
452  }
453  jw.end_array();
454  } else {
455  jw.write("unknown");
456  }
457  continue;
458  }
459  param[attr].writeJSON(jw);
460  }
461  jw.end_object();
462  }
463 
464  FUNCTION(parameterlist) {
465  serv.settings.get_param().writeJSON(jw);
466  }
467 
468  FUNCTION(pluginlist) {
469  serv.jack.get_engine().pluginlist.writeJSON(jw);
470  }
471 
472  FUNCTION(plugin_load_ui) {
473  PluginDef *pd = serv.jack.get_engine().pluginlist.lookup_plugin(params[0]->getString())->get_pdef();
474  if (!pd->load_ui) {
475  jw.write_null();
476  } else {
477  UiBuilderVirt bld(&jw, &serv.settings.get_options(), pd);
478  jw.begin_array();
479  pd->load_ui(bld, params[1]->getInt());
480  jw.end_array();
481  }
482  }
483 
484  FUNCTION(get_rack_unit_order) {
485  std::vector<std::string>& ul = serv.settings.get_rack_unit_order(params[0]->getInt());
486  jw.begin_array();
487  for (std::vector<std::string>::iterator i = ul.begin(); i != ul.end(); ++i) {
488  jw.write(*i);
489  }
490  jw.end_array();
491  }
492 
493  FUNCTION(get_parameter) {
494  gx_engine::ParamMap& param = serv.settings.get_param();
495  jw.begin_object();
496  if (params.size() == 0) {
497  for (gx_engine::ParamMap::iterator i = param.begin(); i != param.end(); ++i) {
498  jw.write_key(i->first);
499  write_parameter_state(jw, *i->second);
500  }
501  } else {
502  for (JsonArray::iterator i = params.begin(); i != params.end(); ++i) {
503  const Glib::ustring& attr = (*i)->getString();
504  if (param.hasId(attr)) {
505  jw.write_key(attr);
506  write_parameter_state(jw, param[attr]);
507  }
508  }
509  }
510  jw.end_object();
511  }
512 
513  FUNCTION(get_parameter_value) {
514  gx_engine::ParamMap& param = serv.settings.get_param();
515  const Glib::ustring& id = params[0]->getString();
516  float f = 0.0;
517  if (param[id.substr(0,id.find_last_of(".")+1)+"on_off"].getInt().get_value())
518  f = param[id].getFloat().get_value();
519  jw.begin_array();
520  jw.write(f);
521  jw.end_array();
522  }
523 
524  FUNCTION(get_bank) {
525  gx_system::PresetFile* pf = serv.settings.banks.get_file(params[0]->getString());
526  if (!pf) {
527  throw RpcError(-32602, "Invalid params -- unknown bank");
528  }
529  pf->writeJSON_remote(jw);
530  }
531 
532  FUNCTION(banks) {
533  gx_system::PresetBanks& banks = serv.settings.banks;
534  jw.begin_array();
535  for (gx_system::PresetBanks::iterator i = banks.begin(); i != banks.end(); ++i) {
536  (*i)->writeJSON_remote(jw);
537  }
538  jw.end_array();
539  }
540 
541  FUNCTION(presets) {
542  gx_system::PresetFile* pf = serv.settings.banks.get_file(params[0]->getString());
543  if (!pf) {
544  throw RpcError(-32602, "Invalid params -- unknown bank");
545  }
546  jw.begin_array();
547  for (gx_system::PresetFile::iterator i = pf->begin(); i != pf->end(); ++i) {
548  jw.write(i->name);
549  }
550  jw.end_array();
551  }
552 
553  FUNCTION(bank_insert_content) {
554  gx_system::PresetFile *f = serv.settings.bank_insert_content(params[0]->getString(), params[1]->getString());
555  if (f) {
556  f->writeJSON_remote(jw);
557  }
558  }
559 
560  FUNCTION(bank_insert_new) {
561  gx_system::PresetFile *f = serv.settings.bank_insert_new(params[0]->getString());
562  f->writeJSON_remote(jw);
563  }
564 
565  FUNCTION(rename_bank) {
566  Glib::ustring newname = params[1]->getString();
567  jw.begin_array();
568  jw.write(serv.settings.rename_bank(params[0]->getString(), newname));
569  jw.write(newname);
570  jw.end_array();
571  }
572 
573  FUNCTION(rename_preset) {
574  jw.write(
575  serv.settings.rename_preset(
576  *serv.settings.banks.get_file(params[0]->getString()), params[1]->getString(), params[2]->getString()));
577  }
578 
579  FUNCTION(bank_check_reparse) {
580  jw.write(serv.settings.banks.check_reparse());
581  }
582 
583  FUNCTION(bank_get_filename) {
584  jw.write(serv.settings.banks.get_file(params[0]->getString())->get_filename());
585  }
586 
587  FUNCTION(bank_get_contents) {
588  const std::string& fname = serv.settings.banks.get_file(params[0]->getString())->get_filename();
589  jw.begin_array();
590  jw.write(fname);
591  stringstream s;
592  s << ifstream(fname.c_str()).rdbuf();
593  jw.write(s.str());
594  jw.end_array();
595  }
596 
597  FUNCTION(convert_preset) {
598  jw.write(serv.settings.convert_preset(*serv.settings.banks.get_file(params[0]->getString())));
599  }
600 
601  FUNCTION(bank_remove) {
602  jw.write(serv.settings.remove_bank(params[0]->getString()));
603  }
604 
605  FUNCTION(get_midi_controller_map) {
606  serv.jack.get_engine().controller_map.writeJSON(jw);
607  }
608 
609  FUNCTION(midi_get_config_mode) {
610  bool mode = serv.jack.get_engine().controller_map.get_config_mode();
611  jw.begin_array();
612  jw.write(mode);
613  jw.write(mode ? serv.jack.get_engine().controller_map.get_current_control() : -1);
614  jw.end_array();
615  }
616 
617  FUNCTION(midi_size) {
618  jw.write(serv.jack.get_engine().controller_map.size());
619  }
620 
621  FUNCTION(getstate) {
622  gx_engine::GxEngineState s = serv.jack.get_engine().get_state();
624  }
625 
626  FUNCTION(getversion) {
627  jw.begin_array();
628  jw.write(InterfaceVersionMajor);
629  jw.write(InterfaceVersionMinor);
630  jw.write(GX_VERSION);
631  jw.end_array();
632  }
633 
634  FUNCTION(get_tuning) {
635  jw.begin_object();
636  jw.write_kv("frequency", serv.jack.get_engine().tuner.get_freq());
637  jw.write_kv("note", serv.jack.get_engine().tuner.get_note());
638  jw.end_object();
639  }
640 
641  FUNCTION(get_max_input_level) {
642  jw.write(0.0);
643  }
644 
645  FUNCTION(get_max_output_level) {
646  serv.update_maxlevel();
647  unsigned int n = params[0]->getInt();
648  jw.begin_array();
649  for (unsigned int i = 0; i < n; i++) {
651  jw.write(maxlevel[i]);
652  maxlevel[i] = 0.0;
653  } else {
654  jw.write(0.0);
655  }
656  }
657  jw.end_array();
658  }
659 
660  FUNCTION(get_tuner_freq) {
661  jw.write(serv.jack.get_engine().tuner.get_freq());
662  }
663 
664  FUNCTION(get_oscilloscope_info) {
665  jw.begin_array();
666  jw.write(static_cast<int>(round(serv.jack.get_jcpu_load())));
667  jw.write(serv.jack.get_time_is()/100000);
668  jw.write(serv.jack.get_is_rt());
669  jw.write(serv.jack.get_jack_bs());
670  unsigned int sz = serv.jack.get_engine().oscilloscope.get_size();
671  float *p = serv.jack.get_engine().oscilloscope.get_buffer();
672  jw.write(sz);
673  jw.begin_array();
674  for (unsigned int i = 0; i < sz; i++) {
675  jw.write(*p++);
676  }
677  jw.end_array();
678  jw.end_array();
679  }
680 
681  FUNCTION(get_oscilloscope_mul_buffer) {
682  jw.write(serv.jack.get_engine().oscilloscope.get_mul_buffer());
683  }
684 
685  FUNCTION(get_tuner_switcher_active) {
686  jw.write(serv.tuner_switcher.get_active());
687  }
688 
689  FUNCTION(jack_cpu_load) {
690  jw.write(serv.jack.get_jcpu_load());
691  }
692 
693  FUNCTION(get_jack_load_status) {
694  jw.write(serv.jack.get_engine().midiaudiobuffer.jack_load_status());
695  }
696 
697  FUNCTION(load_impresp_dirs) {
698  std::vector<gx_system::FileName> dirs;
699  gx_system::list_subdirs(serv.settings.get_options().get_IR_pathlist(), dirs);
700  jw.begin_array();
701  for (std::vector<gx_system::FileName>::iterator i = dirs.begin(); i != dirs.end(); ++i) {
702  jw.begin_array();
703  jw.write(i->filename);
704  jw.write(i->displayname);
705  jw.end_array();
706  }
707  jw.end_array();
708  }
709 
711  unsigned int audio_size;
712  int audio_chan, audio_type, audio_form, audio_rate;
713  float *buffer;
714  bool ret = gx_engine::read_audio(params[0]->getString(), &audio_size, &audio_chan,
715  &audio_type, &audio_form, &audio_rate, &buffer);
716  if (!ret) {
717  return;
718  }
719  jw.begin_array();
720  jw.write(audio_size);
721  jw.write(audio_chan);
722  jw.write(audio_type);
723  jw.write(audio_form);
724  jw.write(audio_rate);
725  jw.begin_array();
726  for (unsigned int i = 0; i < audio_size*audio_chan; i++) {
727  jw.write(buffer[i]);
728  }
729  jw.end_array();
730  jw.end_array();
731  delete[] buffer;
732  }
733 
734  FUNCTION(load_ladspalist) {
735  std::vector<std::string> old_not_found;
736  ladspa::LadspaPluginList pluginlist;
737  pluginlist.load(serv.settings.get_options(), old_not_found);
738  jw.begin_array();
739  for (std::vector<std::string>::iterator i = old_not_found.begin(); i != old_not_found.end(); ++i) {
740  jw.write(*i);
741  }
742  jw.end_array();
743  pluginlist.writeJSON(jw);
744  }
745 
746  FUNCTION(ladspaloader_update_plugins) {
747  serv.ladspaloader_update_plugins(&jw, this);
748  }
749 
750  FUNCTION(plugin_preset_list_load) {
751  gx_preset::UnitPresetList presetnames;
752  serv.settings.plugin_preset_list_load(
753  serv.jack.get_engine().pluginlist.find_plugin(params[0]->getString())->get_pdef(),
754  presetnames);
755  jw.begin_array();
756  for (gx_preset::UnitPresetList::iterator i = presetnames.begin(); i != presetnames.end(); ++i) {
757  jw.begin_array();
758  jw.write(i->name);
759  jw.write(i->is_set);
760  jw.end_array();
761  }
762  jw.end_array();
763  }
764 
765  FUNCTION(queryunit) {
766  if (params.size() != 1) {
767  throw RpcError(-32602, "Invalid params -- 1 parameter expected");
768  }
769  gx_engine::Plugin *p = serv.jack.get_engine().pluginlist.find_plugin(params[0]->getString());
770  if (!p) {
771  throw RpcError(-32602, "Invalid params -- plugin not found");
772  }
773  Glib::ustring unitprefix = p->get_pdef()->id;
774  unitprefix += ".";
775  const char **gl = p->get_pdef()->groups;
776  gx_engine::ParamMap& param = serv.settings.get_param();
777  jw.begin_object();
778  for (gx_engine::ParamMap::iterator i = param.begin(); i != param.end(); ++i) {
779  if (unit_match(i->first, unitprefix, gl)) {
780  jw.write_key(i->first);
781  write_parameter_state(jw, *i->second);
782  }
783  }
784  jw.end_object();
785  }
786 
787  FUNCTION(desc) {
788  gx_engine::ParamMap& param = serv.settings.get_param();
789  jw.begin_object();
790  for (JsonArray::iterator i = params.begin(); i != params.end(); ++i) {
791  const Glib::ustring& attr = (*i)->getString();
792  jw.write_key(attr);
793  if (!param.hasId(attr)) {
794  jw.write("unknown");
795  continue;
796  }
797  write_parameter_state(jw, param[attr]);
798  }
799  jw.end_object();
800  }
801 
802  FUNCTION(list) {
803  const Glib::ustring& prefix = params[0]->getString();
804  gx_engine::ParamMap& param = serv.settings.get_param();
805  jw.begin_array();
806  for (gx_engine::ParamMap::iterator i = param.begin(); i != param.end(); ++i) {
807  if (i->first.compare(0, prefix.size(), prefix) == 0) {
808  jw.write(i->first);
809  }
810  }
811  jw.end_array();
812  }
813 
814  END_FUNCTION_SWITCH(cerr << "Method not found: " << mn->name << endl; assert(false));
815 }
816 
817 static void save_preset(gx_preset::GxSettings& settings, const Glib::ustring& bank,
818  const Glib::ustring& preset) {
819  gx_system::PresetFile *pf = settings.banks.get_file(bank);
820  if (!pf) {
821  Glib::ustring newbank = bank;
822  std::string newfile;
823  settings.banks.make_bank_unique(newbank, &newfile);
824  pf = new gx_system::PresetFile();
825  if (pf->create_file(newbank, newfile, gx_system::PresetFile::PRESET_FILE, 0)) {
826  settings.banks.insert(pf);
827  } else {
828  delete pf;
829  throw RpcError(-32001, "bank not found");
830  }
831  }
832  if (!pf->is_mutable()) {
833  throw RpcError(-32001, "bank is immutable");
834  }
835  settings.save(*pf, preset);
836 }
837 
838 void CmdConnection::notify(gx_system::JsonStringWriter& jw, const methodnames *mn, JsonArray& params) {
839  START_FUNCTION_SWITCH(mn->m_id);
840 
841  PROCEDURE(insert_rack_unit) {
842  Glib::ustring unit = params[0]->getString();
843  gx_engine::Plugin *pl = serv.jack.get_engine().pluginlist.find_plugin(unit);
844  if (!pl) {
845  throw RpcError(-32602, Glib::ustring::compose("Invalid param -- unit %1 unknown", unit));
846  }
847  bool stereo = params[2]->getInt();
848  serv.settings.insert_rack_unit(unit, params[1]->getString(), stereo);
849  gx_engine::Parameter& p = serv.settings.get_param()[pl->id_box_visible()];
850  p.set_blocked(true);
851  pl->set_box_visible(true);
852  p.set_blocked(false);
853  serv.send_rack_changed(stereo, this);
854  }
855 
856  PROCEDURE(remove_rack_unit) {
857  Glib::ustring unit = params[0]->getString();
858  gx_engine::Plugin *pl = serv.jack.get_engine().pluginlist.find_plugin(unit);
859  if (!pl) {
860  throw RpcError(-32602, Glib::ustring::compose("Invalid param -- unit %1 unknown", unit));
861  }
862  bool stereo = params[1]->getInt();
863  if (serv.settings.remove_rack_unit(params[0]->getString(), stereo)) {
865  p = &serv.settings.get_param()[pl->id_box_visible()];
866  p->set_blocked(true);
867  pl->set_box_visible(false);
868  p->set_blocked(false);
869  p = &serv.settings.get_param()[pl->id_on_off()];
870  p->set_blocked(true);
871  pl->set_on_off(false);
872  p->set_blocked(false);
873  serv.send_rack_changed(stereo, this);
874  }
875  }
876 
877  PROCEDURE(bank_reorder) {
878  std::vector<Glib::ustring> neworder;
879  for (JsonArray::iterator i = params.begin(); i != params.end(); ++i) {
880  neworder.push_back((*i)->getString());
881  }
882  serv.settings.banks.reorder(neworder);
883  }
884 
885  PROCEDURE(reorder_preset) {
886  std::vector<Glib::ustring> neworder;
887  for (JsonArray::iterator i = params.begin()+1; i != params.end(); ++i) {
888  neworder.push_back((*i)->getString());
889  }
890  serv.settings.reorder_preset(*serv.settings.banks.get_file(params[0]->getString()), neworder);
891  }
892 
893  PROCEDURE(erase_preset) {
894  serv.settings.erase_preset(*serv.settings.banks.get_file(params[0]->getString()), params[1]->getString());
895  }
896 
897  PROCEDURE(bank_set_flag) {
898  serv.settings.banks.get_file(params[0]->getString())->set_flag(params[1]->getInt(), params[2]->getInt());
899  }
900 
901  PROCEDURE(pf_append) {
902  serv.settings.append(
903  *serv.settings.banks.get_file(params[0]->getString()), params[1]->getString(),
904  *serv.settings.banks.get_file(params[2]->getString()), params[3]->getString());
905  }
906 
907  PROCEDURE(pf_insert_before) {
908  serv.settings.insert_before(
909  *serv.settings.banks.get_file(params[0]->getString()), params[1]->getString(),
910  *serv.settings.banks.get_file(params[2]->getString()), params[3]->getString(),
911  params[4]->getString());
912  }
913 
914  PROCEDURE(pf_insert_after) {
915  serv.settings.insert_after(
916  *serv.settings.banks.get_file(params[0]->getString()), params[1]->getString(),
917  *serv.settings.banks.get_file(params[2]->getString()), params[3]->getString(),
918  params[4]->getString());
919  }
920 
921  PROCEDURE(bank_save) {
922  serv.settings.banks.save();
923  }
924 
925  PROCEDURE(pf_save) {
926  serv.settings.save(*serv.settings.banks.get_file(params[0]->getString()), params[1]->getString());
927  }
928 
929  PROCEDURE(plugin_preset_list_sync_set) {
931  serv.jwc = &jw;
932  send_notify_begin(jw, "set");
933  serv.settings.plugin_preset_list_sync_set(
934  serv.jack.get_engine().pluginlist.find_plugin(params[0]->getString())->get_pdef(),
935  params[1]->getInt(), params[2]->getString());
936  serv.jwc = 0;
937  serv.broadcast(jw, f_parameter_change_notify);
938  }
939 
940  PROCEDURE(plugin_preset_list_set) {
942  serv.jwc = &jw;
943  send_notify_begin(jw, "set");
944  serv.settings.plugin_preset_list_set(
945  serv.jack.get_engine().pluginlist.find_plugin(params[0]->getString())->get_pdef(),
946  params[1]->getInt(), params[2]->getString());
947  serv.jwc = 0;
948  serv.broadcast(jw, f_parameter_change_notify);
949  }
950 
951  PROCEDURE(plugin_preset_list_save) {
952  serv.settings.plugin_preset_list_save(
953  serv.jack.get_engine().pluginlist.find_plugin(params[0]->getString())->get_pdef(),
954  params[1]->getString());
955  }
956 
957  PROCEDURE(plugin_preset_list_remove) {
958  serv.settings.plugin_preset_list_remove(
959  serv.jack.get_engine().pluginlist.find_plugin(params[0]->getString())->get_pdef(),
960  params[1]->getString());
961  }
962 
963  PROCEDURE(midi_set_config_mode) {
964  midi_config_mode = params[0]->getInt();
965  serv.jack.get_engine().controller_map.set_config_mode(midi_config_mode, params[1]->getInt());
966  }
967 
968  PROCEDURE(request_midi_value_update) {
969  serv.jack.get_engine().controller_map.request_midi_value_update();
970  }
971 
972  PROCEDURE(midi_deleteParameter) {
973  serv.jack.get_engine().controller_map.deleteParameter(
974  serv.settings.get_param()[params[0]->getString()]);
975  }
976 
977  PROCEDURE(midi_set_current_control) {
978  serv.jack.get_engine().controller_map.set_current_control(params[0]->getInt());
979  }
980 
981  PROCEDURE(midi_modifyCurrent) {
982  serv.jack.get_engine().controller_map.modifyCurrent(
983  serv.settings.get_param()[params[0]->getString()], params[1]->getFloat(),
984  params[2]->getFloat(), params[3]->getInt(), params[4]->getInt());
985  }
986 
987  PROCEDURE(set) {
988  if (params.size() & 1) {
989  throw RpcError(-32602, "Invalid param -- array length must be even");
990  }
991  gx_engine::ParamMap& param = serv.settings.get_param();
992  for (unsigned int i = 0; i < params.size(); i += 2) {
993  const Glib::ustring& attr = params[i]->getString();
994  if (param.hasId(attr)) {
995  gx_engine::Parameter& p = param[attr];
996  p.set_blocked(true);
997  JsonValue *v = params[i+1];
998  if (p.isFloat()) {
1000  float f;
1001  if (p.getControlType() == gx_engine::Parameter::Enum && dynamic_cast<JsonString*>(v)) {
1002  f = pf.idx_from_id(v->getString());
1003  } else {
1004  f = v->getFloat();
1005  }
1006  pf.set(f);
1007  } else if (p.isInt()) {
1008  gx_engine::IntParameter& pi = p.getInt();
1009  int i;
1010  if (p.getControlType() == gx_engine::Parameter::Enum && dynamic_cast<JsonString*>(v)) {
1011  i = pi.idx_from_id(v->getString());
1012  } else {
1013  i = v->getInt();
1014  }
1015  pi.set(i);
1016  } else if (p.isBool()) {
1017  p.getBool().set(v->getInt());
1018  } else if (p.isFile()) {
1019  p.getFile().set(Gio::File::create_for_path(v->getString()));
1020  } else if (p.isString()) {
1021  p.getString().set(v->getString());
1022  } else if (dynamic_cast<gx_engine::JConvParameter*>(&p) != 0) {
1025  s.readJSON(jps);
1026  dynamic_cast<gx_engine::JConvParameter*>(&p)->set(s);
1027  } else if (dynamic_cast<gx_engine::SeqParameter*>(&p) != 0) {
1030  s.readJSON(jps);
1031  dynamic_cast<gx_engine::SeqParameter*>(&p)->set(s);
1032  } else {
1033  throw RpcError(-32602, "Invalid param -- unknown variable");
1034  }
1035  p.set_blocked(false);
1036  }
1037  }
1038  if (serv.broadcast_listeners(f_parameter_change_notify, this)) {
1040  send_notify_begin(jw, "set");
1041  for (unsigned int i = 0; i < params.size(); i += 2) {
1042  jw.write(params[i]->getString());
1043  JsonValue *v = params[i+1];
1044  if (dynamic_cast<JsonFloat*>(v)) {
1045  jw.write(v->getFloat());
1046  } else if (dynamic_cast<JsonInt*>(v)) {
1047  jw.write(v->getInt());
1048  } else if (dynamic_cast<JsonString*>(v)) {
1049  jw.write(v->getString());
1050  } else if (dynamic_cast<JsonObject*>(v)) {
1051  v->getSubParser().copy_object(jw);
1052  }
1053  }
1054  serv.broadcast(jw, f_parameter_change_notify, this);
1055  }
1056  serv.save_state();
1057  }
1058 
1059  PROCEDURE(setpreset) {
1060  gx_system::PresetFile* pf = serv.settings.banks.get_file(params[0]->getString());
1061  serv.settings.load_preset(pf, params[1]->getString());
1062  serv.save_state();
1063  }
1064 
1065  PROCEDURE(set_online_presets) {
1066  serv.settings.load_online_presets();
1067  }
1068 
1069  PROCEDURE(create_default_scratch_preset) {
1070  serv.settings.create_default_scratch_preset();
1071  }
1072 
1073  PROCEDURE(sendcc) {
1074  serv.jack.send_midi_cc(params[0]->getInt(),params[1]->getInt(),params[2]->getInt(),params[3]->getInt());
1075  }
1076 
1077  PROCEDURE(setstate) {
1078  serv.jack.get_engine().set_state(string_to_engine_state(params[0]->getString()));
1079  serv.jack.get_engine().check_module_lists();
1080  }
1081 
1082  PROCEDURE(switch_tuner) {
1083  serv.jack.get_engine().tuner.used_for_display(params[0]->getInt());
1084  serv.jack.get_engine().check_module_lists();
1085  }
1086 
1087  PROCEDURE(tuner_switcher_activate) {
1088  serv.tuner_switcher.activate(params[0]->getInt());
1089  }
1090 
1091  PROCEDURE(tuner_switcher_deactivate) {
1092  serv.tuner_switcher.deactivate();
1093  }
1094 
1095  PROCEDURE(tuner_switcher_toggle) {
1096  serv.tuner_switcher.toggle(params[0]->getInt());
1097  }
1098 
1099  PROCEDURE(reload_impresp_list) {
1101  std::string path = params[0]->getString();
1102  gx_system::IRFileListing l(path);
1103  send_notify_begin(jw, "impresp_list");
1104  jw.write(path);
1105  for (std::vector<gx_system::FileName>::iterator i = l.get_listing().begin(); i != l.get_listing().end(); ++i) {
1106  jw.begin_array();
1107  jw.write(i->filename);
1108  jw.write(i->displayname);
1109  jw.end_array();
1110  }
1111  send_notify_end(jw);
1112  }
1113 
1114  PROCEDURE(set_jack_insert) {
1115  serv.jack.set_jack_insert(params[0]->getInt());
1116  }
1117 
1118  PROCEDURE(save_ladspalist) {
1119  gx_system::JsonSubParser jps = params[0]->getSubParser();
1120  ladspa::LadspaPluginList pluginlist;
1121  pluginlist.readJSON(jps);
1122  pluginlist.save(serv.settings.get_options());
1123  }
1124 
1125  PROCEDURE(shutdown) {
1126  connection->close();
1127  serv.quit_mainloop();
1128  }
1129 
1130  PROCEDURE(listen) {
1131  for (JsonArray::iterator i = params.begin(); i != params.end(); ++i) {
1132  CmdConnection::listen((*i)->getString());
1133  }
1134  }
1135 
1136  PROCEDURE(unlisten) {
1137  for (JsonArray::iterator i = params.begin(); i != params.end(); ++i) {
1138  CmdConnection::unlisten((*i)->getString());
1139  }
1140  }
1141 
1142  PROCEDURE(save_current) {
1143  if (!serv.settings.setting_is_preset()) {
1144  throw RpcError(-32001, "no current preset");
1145  }
1146  save_preset(serv.settings, serv.settings.get_current_bank(), serv.settings.get_current_name());
1147  }
1148 
1149  PROCEDURE(save_preset) {
1150  save_preset(serv.settings, params[0]->getString(), params[1]->getString());
1151  }
1152 
1153  PROCEDURE(tuner_used_for_display) {
1154  serv.jack.get_engine().tuner.used_for_display(params[0]->getInt());
1155  }
1156 
1157  PROCEDURE(clear_oscilloscope_buffer) {
1158  serv.jack.get_engine().oscilloscope.clear_buffer();
1159  }
1160 
1161  PROCEDURE(set_oscilloscope_mul_buffer) {
1162  serv.jack.get_engine().oscilloscope.set_mul_buffer(
1163  params[0]->getInt(), serv.jack.get_jack_bs());
1164  }
1165 
1166  PROCEDURE(insert_param) {
1167  gx_engine::ParamMap& param = serv.settings.get_param();
1168  const Glib::ustring& id = params[0]->getString();
1169  const Glib::ustring& tb = params[1]->getString();
1170  if (!param.hasId(id)) {
1171  gx_engine::BoolParameter& sp = param.reg_par(
1172  id, tb, (bool*)0, false, false)->getBool();
1173  sp.setSavable(false);
1174  }
1175  }
1176 
1177  END_FUNCTION_SWITCH(cerr << "Method not found: " << mn->name << endl; assert(false));
1178 }
1179 
1180 void CmdConnection::write_error(gx_system::JsonWriter& jw, int code, const char *message) {
1181  jw.write_key("error");
1182  jw.begin_object();
1183  jw.write_kv("code", code);
1184  jw.write_kv("message", message);
1185  jw.end_object();
1186 }
1187 
1188 bool CmdConnection::request(gx_system::JsonStringParser& jp, gx_system::JsonStringWriter& jw, bool batch_start) {
1189  Glib::ustring method;
1190  JsonArray params;
1191  Glib::ustring id;
1193  while (jp.peek() != gx_system::JsonParser::end_object) {
1195  if (jp.current_value() == "jsonrpc") {
1197  if (jp.current_value() != "2.0") {
1198  throw RpcError(-32600,"Invalid Request");
1199  }
1200  } else if (jp.current_value() == "method") {
1202  method = jp.current_value();
1203  } else if (jp.current_value() == "params") {
1206  while (jp.peek() != gx_system::JsonParser::end_array) {
1207  params.append(jp);
1208  }
1210  } else if (jp.peek() == gx_system::JsonParser::begin_object) {
1211  throw RpcError(-32000,"by-name parameters not implemented");
1212  } else {
1213  throw RpcError(-32600,"Invalid Request");
1214  }
1215  } else if (jp.current_value() == "id") {
1218  throw RpcError(-32600,"Invalid Request");
1219  }
1220  jp.next();
1221  id = jp.current_value();
1222  } else {
1223  throw RpcError(-32600,"Invalid Request");
1224  }
1225  }
1227  const methodnames *p = Perfect_Hash::in_word_set(method.c_str(), method.size());
1228  if (!p) {
1229  throw RpcError(-32601, Glib::ustring::compose("Method not found -- '%1'", method));
1230  }
1231  try {
1232  if (id.empty()) {
1233  notify(jw, p, params);
1234  return false;
1235  } else {
1236  if (batch_start) {
1237  jw.begin_array();
1238  }
1239  jw.begin_object();
1240  jw.write_kv("jsonrpc", "2.0");
1241  jw.write_kv("id", id);
1242  jw.write_key("result");
1243  call(jw, p, params);
1244  jw.end_object();
1245  return true;
1246  }
1247  } catch(const RpcError& e) {
1248  throw RpcError(e.code, Glib::ustring(p->name) + ": " + e.message);
1249  }
1250 }
1251 
1252 void CmdConnection::error_response(gx_system::JsonWriter& jw, int code, const char *message) {
1253  jw.begin_object();
1254  jw.write_kv("jsonrpc", "2.0");
1255  jw.write_key("id");
1256  jw.write_null();
1257  write_error(jw, code, message);
1258  jw.end_object();
1259 }
1260 
1261 static bool sendbytes(int fd, const std::string& s, unsigned int *off) {
1262  unsigned int len = s.size() - *off;
1263  int n = write(fd, s.c_str() + *off, len);
1264  if (n <= 0) {
1265  return false;
1266  }
1267  len -= n;
1268  if (len > 0) {
1269  *off += n;
1270  } else {
1271  *off = 0;
1272  }
1273  return true;
1274 }
1275 
1276 bool CmdConnection::on_data_out(Glib::IOCondition cond) {
1277  int fd = connection->get_socket()->get_fd();
1278  while (outgoing.size() > 0) {
1279  if (!sendbytes(fd, outgoing.front(), &current_offset)) {
1280  return true;
1281  }
1282  if (current_offset == 0) {
1283  outgoing.pop_front();
1284  }
1285  }
1286  return false;
1287 }
1288 
1289 bool CmdConnection::on_data_in(Glib::IOCondition cond) {
1290  Glib::RefPtr<Gio::Socket> sock = connection->get_socket();
1291  char buf[1000];
1292  while (true) {
1293  int n;
1294  try {
1295  n = sock->receive(buf, sizeof(buf));
1296  } catch(Glib::Error e) {
1297  if (e.code() == Gio::Error::WOULD_BLOCK) {
1298  return true;
1299  }
1300  serv.remove_connection(this);
1301  return false;
1302  }
1303  if (n <= 0) {
1304  serv.remove_connection(this);
1305  return false;
1306  }
1307  char *p = buf;
1308  while (n-- > 0) {
1309  jp.put(*p);
1310  if (*p == '\n') {
1311  process(jp);
1312  jp.reset();
1313  }
1314  p++;
1315  }
1316  }
1317 }
1318 
1320  std::string s = jw.get_string();
1321  if (outgoing.size() == 0) {
1322  assert(current_offset == 0);
1323  ssize_t len = s.size();
1324  ssize_t n = write(connection->get_socket()->get_fd(), s.c_str(), len);
1325  if (n == len) {
1326  return;
1327  }
1328  current_offset = max<ssize_t>(0, n);
1329  }
1330  outgoing.push_back(s);
1331  Glib::signal_io().connect(
1332  sigc::mem_fun(this, &CmdConnection::on_data_out),
1333  connection->get_socket()->get_fd(), Glib::IO_OUT);
1334 }
1335 
1336 void CmdConnection::process(gx_system::JsonStringParser& jp) {
1337  try {
1339  bool resp = false;
1340  // jp.peek() doesn't work at start of stream
1341  if (jp.peek_first_char() == '[') {
1343  while (jp.peek() != gx_system::JsonParser::end_array) {
1344  resp = request(jp, jw, !resp) || resp;
1345  }
1346  if (resp) {
1347  jw.end_array();
1348  }
1350  } else {
1351  resp = request(jp, jw, false);
1352  }
1353  if (!resp) {
1354  return;
1355  }
1356  jw.finish();
1357  send(jw);
1358  } catch (gx_system::JsonException& e) {
1360  "JSON-RPC", Glib::ustring::compose("error: %1, request: '%2'",
1361  e.what(), jp.get_string()));
1363  error_response(jw, -32700, "Parse Error");
1364  jw.finish();
1365  send(jw);
1366  } catch (RpcError& e) {
1368  error_response(jw, e.code, e.message);
1369  jw.finish();
1370  send(jw);
1371  }
1372 }
1373 
1374 
1375 /****************************************************************
1376  ** class UiBuilderVirt implementation
1377  */
1378 
1379 gx_system::JsonWriter *UiBuilderVirt::jw = 0;
1380 const gx_system::CmdlineOptions *UiBuilderVirt::options = 0;
1381 
1383  : UiBuilder() {
1384  plugin = pd;
1385  jw = jw_;
1386  options = options_;
1387  openTabBox = openTabBox_;
1388  openVerticalBox = openVerticalBox_;
1389  openVerticalBox1 = openVerticalBox1_;
1390  openVerticalBox2 = openVerticalBox2_;
1391  openHorizontalBox = openHorizontalBox_;
1392  openHorizontalhideBox = openHorizontalhideBox_;
1393  openHorizontalTableBox = openHorizontalTableBox_;
1394  openFrameBox = openFrameBox_;
1395  openFlipLabelBox = openFlipLabelBox_;
1396  openpaintampBox = openpaintampBox_;
1397  closeBox = closeBox_;
1398  load_glade = load_glade_;
1399  load_glade_file = load_glade_file_;
1400  create_master_slider = create_master_slider_;
1401  create_feedback_slider = create_feedback_slider_;
1402  create_big_rackknob = create_big_rackknob_;
1403  create_mid_rackknob = create_mid_rackknob_;
1404  create_small_rackknob = create_small_rackknob_;
1405  create_small_rackknobr = create_small_rackknobr_;
1406  create_simple_meter = create_simple_meter_;
1407  create_simple_c_meter = create_simple_c_meter_;
1408  create_spin_value = create_spin_value_;
1409  create_switch = create_switch_;
1410  create_wheel = create_wheel_;
1411  create_switch_no_caption = create_switch_no_caption_;
1412  create_feedback_switch = create_feedback_switch_;
1413  create_selector = create_selector_;
1414  create_selector_no_caption = create_selector_no_caption_;
1415  create_port_display = create_port_display_;
1416  create_p_display = create_p_display_;
1417  create_simple_spin_value = create_simple_spin_value_;
1418  create_eq_rackslider_no_caption = create_eq_rackslider_no_caption_;
1419  create_fload_switch = create_fload_switch_;
1420  insertSpacer = insertSpacer_;
1421  set_next_flags = set_next_flags_;
1422 }
1423 
1425 }
1426 
1427 void UiBuilderVirt::openTabBox_(const char* label) {
1428  jw->begin_array();
1429  jw->write("openTabBox");
1430  jw->write(label);
1431  jw->end_array();
1432 }
1433 
1434 void UiBuilderVirt::openVerticalBox_(const char* label) {
1435  jw->begin_array();
1436  jw->write("openVerticalBox");
1437  jw->write(label);
1438  jw->end_array();
1439 }
1440 
1441 void UiBuilderVirt::openVerticalBox1_(const char* label) {
1442  jw->begin_array();
1443  jw->write("openVerticalBox1");
1444  jw->write(label);
1445  jw->end_array();
1446 }
1447 
1448 void UiBuilderVirt::openVerticalBox2_(const char* label) {
1449  jw->begin_array();
1450  jw->write("openVerticalBox2");
1451  jw->write(label);
1452  jw->end_array();
1453 }
1454 
1455 void UiBuilderVirt::openHorizontalhideBox_(const char* label) {
1456  jw->begin_array();
1457  jw->write("openHorizontalhideBox");
1458  jw->write(label);
1459  jw->end_array();
1460 }
1461 
1462 void UiBuilderVirt::openHorizontalTableBox_(const char* label) {
1463  jw->begin_array();
1464  jw->write("openHorizontalTableBox");
1465  jw->write(label);
1466  jw->end_array();
1467 }
1468 
1469 void UiBuilderVirt::openFrameBox_(const char* label) {
1470  jw->begin_array();
1471  jw->write("openFrameBox");
1472  jw->write(label);
1473  jw->end_array();
1474 }
1475 
1476 void UiBuilderVirt::openFlipLabelBox_(const char* label) {
1477  jw->begin_array();
1478  jw->write("openFlipLabelBox");
1479  jw->write(label);
1480  jw->end_array();
1481 }
1482 
1483 void UiBuilderVirt::openpaintampBox_(const char* label) {
1484  jw->begin_array();
1485  jw->write("openpaintampBox");
1486  jw->write(label);
1487  jw->end_array();
1488 }
1489 
1490 void UiBuilderVirt::openHorizontalBox_(const char* label) {
1491  jw->begin_array();
1492  jw->write("openHorizontalBox");
1493  jw->write(label);
1494  jw->end_array();
1495 }
1496 
1497 void UiBuilderVirt::insertSpacer_() {
1498  jw->begin_array();
1499  jw->write("insertSpacer");
1500  jw->end_array();
1501 }
1502 
1503 void UiBuilderVirt::set_next_flags_(int flags) {
1504  jw->begin_array();
1505  jw->write("set_next_flags");
1506  jw->write(flags);
1507  jw->end_array();
1508 }
1509 
1510 void UiBuilderVirt::create_big_rackknob_(const char *id, const char *label) {
1511  jw->begin_array();
1512  jw->write("create_big_rackknob");
1513  jw->write(id);
1514  jw->write(label);
1515  jw->end_array();
1516 }
1517 
1518 void UiBuilderVirt::create_mid_rackknob_(const char *id, const char *label) {
1519  jw->begin_array();
1520  jw->write("create_mid_rackknob");
1521  jw->write(id);
1522  jw->write(label);
1523  jw->end_array();
1524 }
1525 
1526 void UiBuilderVirt::create_small_rackknob_(const char *id, const char *label) {
1527  jw->begin_array();
1528  jw->write("create_small_rackknob");
1529  jw->write(id);
1530  jw->write(label);
1531  jw->end_array();
1532 }
1533 
1534 void UiBuilderVirt::create_small_rackknobr_(const char *id, const char *label) {
1535  jw->begin_array();
1536  jw->write("create_small_rackknobr");
1537  jw->write(id);
1538  jw->write(label);
1539  jw->end_array();
1540 }
1541 
1542 void UiBuilderVirt::create_feedback_slider_(const char *id, const char *label) {
1543  jw->begin_array();
1544  jw->write("create_feedback_slider");
1545  jw->write(id);
1546  jw->write(label);
1547  jw->end_array();
1548 }
1549 
1550 void UiBuilderVirt::create_master_slider_(const char *id, const char *label) {
1551  jw->begin_array();
1552  jw->write("create_master_slider");
1553  jw->write(id);
1554  jw->write(label);
1555  jw->end_array();
1556 }
1557 
1558 void UiBuilderVirt::create_selector_no_caption_(const char *id) {
1559  jw->begin_array();
1560  jw->write("create_selector_no_caption");
1561  jw->write(id);
1562  jw->end_array();
1563 }
1564 
1565 void UiBuilderVirt::create_selector_(const char *id, const char *label) {
1566  jw->begin_array();
1567  jw->write("create_selector");
1568  jw->write(id);
1569  jw->write(label);
1570  jw->end_array();
1571 }
1572 
1573 void UiBuilderVirt::create_simple_meter_(const char *id) {
1574  jw->begin_array();
1575  jw->write("create_simple_meter");
1576  jw->write(id);
1577  jw->end_array();
1578 }
1579 void UiBuilderVirt::create_simple_c_meter_(const char *id, const char *idl, const char *label) {
1580  jw->begin_array();
1581  jw->write("create_simple_c_meter");
1582  jw->write(id);
1583  jw->write(idl);
1584  jw->write(label);
1585  jw->end_array();
1586 }
1587 
1588 void UiBuilderVirt::create_spin_value_(const char *id, const char *label) {
1589  jw->begin_array();
1590  jw->write("create_spin_value");
1591  jw->write(id);
1592  jw->write(label);
1593  jw->end_array();
1594 }
1595 
1596 void UiBuilderVirt::create_switch_no_caption_(const char *sw_type, const char * id) {
1597  jw->begin_array();
1598  jw->write("create_switch_no_caption");
1599  jw->write(sw_type);
1600  jw->write(id);
1601  jw->end_array();
1602 }
1603 
1604 void UiBuilderVirt::create_feedback_switch_(const char *sw_type, const char * id) {
1605  jw->begin_array();
1606  jw->write("create_feedback_switch");
1607  jw->write(sw_type);
1608  jw->write(id);
1609  jw->end_array();
1610 }
1611 
1612 void UiBuilderVirt::create_fload_switch_(const char *sw_type, const char * id, const char * idf) {
1613  jw->begin_array();
1614  jw->write("create_fload_switch");
1615  jw->write(sw_type);
1616  jw->write(id);
1617  jw->write(idf);
1618  jw->end_array();
1619 }
1620 
1621 void UiBuilderVirt::create_switch_(const char *sw_type, const char * id, const char *label) {
1622  jw->begin_array();
1623  jw->write("create_switch");
1624  jw->write(sw_type);
1625  jw->write(id);
1626  jw->write(label);
1627  jw->end_array();
1628 }
1629 
1630 void UiBuilderVirt::create_wheel_(const char * id, const char *label) {
1631  jw->begin_array();
1632  jw->write("create_wheel");
1633  jw->write(id);
1634  jw->write(label);
1635  jw->end_array();
1636 }
1637 
1638 void UiBuilderVirt::create_port_display_(const char *id, const char *label) {
1639  jw->begin_array();
1640  jw->write("create_port_display");
1641  jw->write(id);
1642  jw->write(label);
1643  jw->end_array();
1644 }
1645 
1646 void UiBuilderVirt::create_p_display_(const char *id, const char *idl, const char *idh) {
1647  jw->begin_array();
1648  jw->write("create_p_display");
1649  jw->write(id);
1650  jw->write(idl);
1651  jw->write(idh);
1652  jw->end_array();
1653 }
1654 
1655 void UiBuilderVirt::create_simple_spin_value_(const char *id) {
1656  jw->begin_array();
1657  jw->write("create_simple_spin_value");
1658  jw->write(id);
1659  jw->end_array();
1660 }
1661 
1662 void UiBuilderVirt::create_eq_rackslider_no_caption_(const char *id) {
1663  jw->begin_array();
1664  jw->write("create_eq_rackslider_no_caption");
1665  jw->write(id);
1666  jw->end_array();
1667 }
1668 
1669 void UiBuilderVirt::closeBox_() {
1670  jw->begin_array();
1671  jw->write("closeBox");
1672  jw->end_array();
1673 }
1674 
1675 void UiBuilderVirt::load_glade_(const char *data) {
1676  jw->begin_array();
1677  jw->write("load_glade");
1678  jw->write(data);
1679  jw->end_array();
1680 }
1681 
1682 void UiBuilderVirt::load_glade_file_(const char *fname) {
1683  std::string path = options->get_builder_filepath(fname);
1684  std::string data(
1685  std::istreambuf_iterator<char>(std::ifstream(path.c_str()).rdbuf()),
1686  std::istreambuf_iterator<char>());
1687  jw->begin_array();
1688  jw->write("load_glade");
1689  jw->write(data);
1690  jw->end_array();
1691 }
1692 
1693 
1694 /****************************************************************
1695  ** class GxService
1696  */
1697 
1699  TunerSwitcher& tunerswitcher_, sigc::slot<void> quit_mainloop_,
1700  const Glib::ustring& host, int *port)
1701  : Gio::SocketService(),
1702  settings(settings_),
1703  jack(jack_),
1704  tuner_switcher(tunerswitcher_),
1705  quit_mainloop(quit_mainloop_),
1706  oldest_unsaved(0),
1707  last_change(0),
1708  save_conn(),
1709  connection_list(),
1710  jwc(0),
1711  preg_map(0),
1712  maxlevel() {
1713  if (*port == 0) {
1714  *port = add_any_inet_port();
1715  } else {
1716  add_inet_port(*port);
1717  }
1718  if (host.compare(0, 3, "BT:") == 0) {
1719  create_bluetooth_sockets(host.substr(3));
1720  }
1721  settings.signal_selection_changed().connect(
1722  sigc::mem_fun(*this, &GxService::preset_changed));
1723  jack.get_engine().signal_state_change().connect(
1724  sigc::mem_fun(*this, &GxService::on_engine_state_change));
1725  jack.get_engine().tuner.signal_freq_changed().connect(
1726  sigc::mem_fun(this, &GxService::on_tuner_freq_changed));
1727  tuner_switcher.signal_display().connect(
1728  sigc::mem_fun(this, &GxService::display));
1729  tuner_switcher.signal_set_state().connect(
1730  sigc::mem_fun(this, &GxService::set_display_state));
1731  tuner_switcher.signal_selection_done().connect(
1732  sigc::mem_fun(this, &GxService::on_selection_done));
1733  settings.signal_presetlist_changed().connect(
1734  sigc::mem_fun(this, &GxService::on_presetlist_changed));
1736  sigc::mem_fun(this, &GxService::on_log_message));
1738  jack.get_engine().controller_map.signal_changed().connect(
1739  sigc::mem_fun(this, &GxService::on_midi_changed));
1740  jack.get_engine().controller_map.signal_midi_value_changed().connect(
1741  sigc::mem_fun(this, &GxService::on_midi_value_changed));
1742  jack.get_engine().oscilloscope.size_change.connect(
1743  sigc::mem_fun(this, &GxService::on_osc_size_changed));
1744  jack.get_engine().oscilloscope.activation.connect(
1745  sigc::mem_fun(this, &GxService::on_osc_activation));
1746  jack.get_engine().midiaudiobuffer.signal_jack_load_change().connect(
1747  sigc::mem_fun(this, &GxService::on_jack_load_changed));
1748  settings.signal_rack_unit_order_changed().connect(
1749  sigc::mem_fun(this, &GxService::on_rack_unit_changed));
1750  gx_engine::ParamMap& pmap = settings.get_param();
1751  pmap.signal_insert_remove().connect(
1752  sigc::mem_fun(this, &GxService::on_param_insert_remove));
1753  for (gx_engine::ParamMap::iterator i = pmap.begin(); i != pmap.end(); ++i) {
1754  connect_value_changed_signal(i->second);
1755  }
1756 }
1757 
1760  jws.send_notify_begin("server_shutdown");
1761  broadcast(jws, CmdConnection::f_misc_msg);
1762  for (std::list<CmdConnection*>::iterator i = connection_list.begin(); i != connection_list.end(); ++i) {
1763  delete *i;
1764  }
1765 }
1766 
1767 #if HAVE_BLUEZ
1768 static Glib::RefPtr<Gio::Socket> create_one_bluetooth_socket(
1769  const Glib::ustring& device, int channel) {
1770  sockaddr_rc loc_addr = { 0 };
1771  int s = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
1772  loc_addr.rc_family = AF_BLUETOOTH;
1773  // bind socket to the first available local bluetooth adapter
1774  bdaddr_t bdaddr = {{0, 0, 0, 0, 0, 0}}; //*BDADDR_ANY;
1775  loc_addr.rc_bdaddr = bdaddr;
1776  loc_addr.rc_channel = (uint8_t)channel;
1777  bind(s, (struct sockaddr *)&loc_addr, sizeof(loc_addr));
1778  listen(s, 1);
1779  return Gio::Socket::create_from_fd(s);
1780 }
1781 
1782 void GxService::create_bluetooth_sockets(const Glib::ustring& host) {
1783  int channels = 1;
1784  if (host.size() > 3) {
1785  channels = host[3] - '0';
1786  if (channels < 1) {
1787  channels = 1;
1788  } else if (channels > 9) {
1789  channels = 9;
1790  }
1791  }
1792  for (int i = 1; i <= channels; i++) {
1793  add_socket(create_one_bluetooth_socket(host, i));
1794  }
1795  gx_print_info(
1796  _("server"),
1797  Glib::ustring::compose(
1798  _("listening on bluetooth socket (%1 channel)"),
1799  channels));
1800 }
1801 #else // !HAVE_BLUEZ
1802 void GxService::create_bluetooth_sockets(const Glib::ustring& host) {
1804  _("server"),
1805  _("Bluetooth not available; rebuild Guitarix with Bluetooth support"));
1806 }
1807 #endif // HAVE_BLUEZ
1808 
1809 void GxService::ladspaloader_write_changes(gx_system::JsonWriter& jw, std::vector<ChangedPlugin>& changed_plugins) {
1810  serialize_parameter_change(jw);
1811  // updated plugins
1812  jw.begin_array();
1813  for (std::vector<ChangedPlugin>::iterator i = changed_plugins.begin(); i != changed_plugins.end(); ++i) {
1814  jw.begin_array();
1815  jw.write(i->status);
1816  if (i->status == gx_engine::PluginChange::remove) {
1817  jw.write(i->id);
1818  } else {
1819  jack.get_engine().pluginlist.lookup_plugin(i->id)->writeJSON(jw);
1820  }
1821  jw.end_array();
1822  }
1823  jw.end_array();
1824 }
1825 
1826 //static
1827 void GxService::add_changed_plugin(gx_engine::Plugin* pl, gx_engine::PluginChange::pc v, std::vector<ChangedPlugin>& vec) {
1828  if (pl) {
1829  vec.push_back(ChangedPlugin(pl->get_pdef()->id, v));
1830  }
1831 }
1832 
1834  preg_map = new std::map<std::string,bool>;
1835  std::vector<ChangedPlugin> changed_plugins;
1836  sigc::connection conn = jack.get_engine().signal_plugin_changed().connect(
1837  sigc::bind(sigc::ptr_fun(add_changed_plugin), sigc::ref(changed_plugins)));
1838  gx_system::JsonStringWriter jwp; /* capture parameter changes and ignore them;
1839  they are already sent as part of changed parameter data */
1840  jwc = &jwp;
1841  jack.get_engine().ladspaloader_update_plugins();
1842  jwc = 0;
1843  conn.disconnect();
1844  if (jw) {
1845  jw->begin_array();
1846  ladspaloader_write_changes(*jw, changed_plugins);
1847  jw->end_array();
1848  }
1849  if (broadcast_listeners(CmdConnection::f_plugins_changed, cmd)) {
1851  jws.send_notify_begin("plugins_changed");
1852  ladspaloader_write_changes(jws, changed_plugins);
1853  broadcast(jws, CmdConnection::f_plugins_changed, cmd);
1854  }
1855  delete preg_map;
1856  preg_map = 0;
1857 }
1858 
1860  static bool rack_unit_change_blocked = false;
1861  if (rack_unit_change_blocked) {
1862  return;
1863  }
1864  if (cmd) {
1865  rack_unit_change_blocked = true;
1866  settings.signal_rack_unit_order_changed()(stereo);
1867  rack_unit_change_blocked = false;
1868  }
1869  if (!broadcast_listeners(CmdConnection::f_units_changed, cmd)) {
1870  return;
1871  }
1873  jw.send_notify_begin("rack_units_changed");
1874  std::vector<std::string>& ul = settings.get_rack_unit_order(stereo);
1875  jw.begin_array();
1876  jw.write(stereo);
1877  for (std::vector<std::string>::iterator i = ul.begin(); i != ul.end(); ++i) {
1878  jw.write(*i);
1879  }
1880  jw.end_array();
1881  broadcast(jw, CmdConnection::f_units_changed, cmd);
1882 }
1883 
1884 void GxService::on_rack_unit_changed(bool stereo) {
1885  send_rack_changed(stereo, 0);
1886 }
1887 
1888 void GxService::connect_value_changed_signal(gx_engine::Parameter *p) {
1889  if (p->isInt()) {
1890  p->getInt().signal_changed().connect(
1891  sigc::hide(
1892  sigc::bind(
1893  sigc::mem_fun(this, &GxService::on_param_value_changed), p)));
1894  } else if (p->isBool()) {
1895  p->getBool().signal_changed().connect(
1896  sigc::hide(
1897  sigc::bind(
1898  sigc::mem_fun(this, &GxService::on_param_value_changed), p)));
1899  } else if (p->isFloat()) {
1900  p->getFloat().signal_changed().connect(
1901  sigc::hide(
1902  sigc::bind(
1903  sigc::mem_fun(this, &GxService::on_param_value_changed), p)));
1904  } else if (p->isString()) {
1905  p->getString().signal_changed().connect(
1906  sigc::hide(
1907  sigc::bind(
1908  sigc::mem_fun(this, &GxService::on_param_value_changed), p)));
1909  } else if (dynamic_cast<gx_engine::JConvParameter*>(p) != 0) {
1910  dynamic_cast<gx_engine::JConvParameter*>(p)->signal_changed().connect(
1911  sigc::hide(
1912  sigc::bind(
1913  sigc::mem_fun(this, &GxService::on_param_value_changed), p)));
1914  } else if (dynamic_cast<gx_engine::SeqParameter*>(p) != 0) {
1915  dynamic_cast<gx_engine::SeqParameter*>(p)->signal_changed().connect(
1916  sigc::hide(
1917  sigc::bind(
1918  sigc::mem_fun(this, &GxService::on_param_value_changed), p)));
1919  }
1920 }
1921 
1922 void GxService::on_param_insert_remove(gx_engine::Parameter *p, bool inserted) {
1923  if (preg_map) {
1924  (*preg_map)[p->id()] = inserted;
1925  }
1926  if (inserted) {
1927  connect_value_changed_signal(p);
1928  }
1929 }
1930 
1931 void GxService::on_param_value_changed(gx_engine::Parameter *p) {
1934  if (jwc) {
1935  jw = jwc;
1936  } else {
1937  if (p->get_blocked()) {
1938  return;
1939  }
1940  jwp.send_notify_begin("set");
1941  jw = &jwp;
1942  }
1943  jw->write(p->id());
1944  if (p->isInt()) {
1945  jw->write(p->getInt().get_value());
1946  } else if (p->isBool()) {
1947  jw->write(p->getBool().get_value());
1948  } else if (p->isFloat()) {
1949  jw->write(p->getFloat().get_value());
1950  } else if (p->isString()) {
1951  jw->write(p->getString().get_value());
1952  } else if (dynamic_cast<gx_engine::JConvParameter*>(p) != 0) {
1953  dynamic_cast<gx_engine::JConvParameter*>(p)->get_value().writeJSON(*jw);
1954  } else if (dynamic_cast<gx_engine::SeqParameter*>(p) != 0) {
1955  dynamic_cast<gx_engine::SeqParameter*>(p)->get_value().writeJSON(*jw);
1956  } else {
1957  assert(false);
1958  }
1959  if (!jwc) {
1961  }
1962 }
1963 
1964 void GxService::on_jack_load_changed() {
1965  if (!broadcast_listeners(CmdConnection::f_jack_load_changed)) {
1966  return;
1967  }
1969  jw.send_notify_begin("jack_load_changed");
1970  gx_engine::MidiAudioBuffer::Load l = jack.get_engine().midiaudiobuffer.jack_load_status();
1971  if (l == gx_engine::MidiAudioBuffer::load_low && !jack.get_engine().midiaudiobuffer.get_midistat()) {
1973  }
1974  jw.write(l);
1975  broadcast(jw, CmdConnection::f_jack_load_changed);
1976 }
1977 
1978 void GxService::on_osc_size_changed(unsigned int sz) {
1979  if (!broadcast_listeners(CmdConnection::f_osc_size_changed)) {
1980  return;
1981  }
1983  jw.send_notify_begin("osc_size_changed");
1984  jw.write(sz);
1985  broadcast(jw, CmdConnection::f_osc_size_changed);
1986 }
1987 
1988 int GxService::on_osc_activation(bool start) {
1989  if (!broadcast_listeners(CmdConnection::f_osc_activation)) {
1990  return 0;
1991  }
1993  jw.send_notify_begin("osc_activation");
1994  jw.write(start);
1995  broadcast(jw, CmdConnection::f_osc_activation);
1996  return 0;
1997 }
1998 
1999 void GxService::on_midi_changed() {
2000  if (!broadcast_listeners(CmdConnection::f_midi_changed)) {
2001  return;
2002  }
2004  jw.send_notify_begin("midi_changed");
2005  jack.get_engine().controller_map.writeJSON(jw);
2006  broadcast(jw, CmdConnection::f_midi_changed);
2007 }
2008 
2009 void GxService::on_midi_value_changed(int ctl, int value) {
2010  if (!broadcast_listeners(CmdConnection::f_midi_value_changed)) {
2011  return;
2012  }
2014  jw.send_notify_begin("midi_value_changed");
2015  jw.begin_array();
2016  jw.write(ctl);
2017  jw.write(value);
2018  jw.end_array();
2019  broadcast(jw, CmdConnection::f_midi_value_changed);
2020 }
2021 
2022 void GxService::on_log_message(const string& msg, GxLogger::MsgType tp, bool plugged) {
2023  if (plugged || !broadcast_listeners(CmdConnection::f_log_message)) {
2024  return;
2025  }
2026  const char *tpname;
2027  switch (tp) {
2028  case GxLogger::kInfo: tpname = "info"; break;
2029  case GxLogger::kWarning: tpname = "warning"; break;
2030  case GxLogger::kError: tpname = "error"; break;
2031  default: tpname = "unknown"; break;
2032  }
2034  jw.send_notify_begin("message");
2035  jw.write(tpname);
2036  jw.write(msg);
2037  broadcast(jw, CmdConnection::f_log_message);
2038 }
2039 
2040 void GxService::on_selection_done(bool v) {
2041  if (!broadcast_listeners(CmdConnection::f_selection_done)) {
2042  return;
2043  }
2045  jw.send_notify_begin("show_tuner");
2046  jw.write(v);
2047  broadcast(jw, CmdConnection::f_selection_done);
2048 }
2049 
2050 void GxService::on_presetlist_changed() {
2051  if (!broadcast_listeners(CmdConnection::f_presetlist_changed)) {
2052  return;
2053  }
2055  jw.send_notify_begin("presetlist_changed");
2056  broadcast(jw, CmdConnection::f_presetlist_changed);
2057 }
2058 
2059 void GxService::on_engine_state_change(gx_engine::GxEngineState state) {
2060  if (!broadcast_listeners(CmdConnection::f_state_changed)) {
2061  return;
2062  }
2064  jw.send_notify_begin("state_changed");
2065  jw.write(engine_state_to_string(state));
2066  broadcast(jw, CmdConnection::f_state_changed);
2067 }
2068 
2069 void GxService::preset_changed() {
2070  if (!broadcast_listeners(CmdConnection::f_preset_changed)) {
2071  return;
2072  }
2074  jw.send_notify_begin("preset_changed");
2075  if (settings.setting_is_preset()) {
2076  jw.write(settings.get_current_bank());
2077  jw.write(settings.get_current_name());
2078  } else {
2079  jw.write("");
2080  jw.write("");
2081  }
2082  broadcast(jw, CmdConnection::f_preset_changed);
2083 }
2084 
2085 void GxService::on_tuner_freq_changed() {
2086  if (!broadcast_listeners(CmdConnection::f_freq_changed)) {
2087  return;
2088  }
2090  jw.send_notify_begin("tuner_changed");
2091  //jw.write_key("frequency");
2092  jw.write(jack.get_engine().tuner.get_freq());
2093  //jw.write_key("note");
2094  jw.write(jack.get_engine().tuner.get_note());
2095  broadcast(jw, CmdConnection::f_freq_changed);
2096 }
2097 
2098 void GxService::display(const Glib::ustring& bank, const Glib::ustring& preset) {
2099  if (!broadcast_listeners(CmdConnection::f_display)) {
2100  return;
2101  }
2103  jw.send_notify_begin("display_bank_preset");
2104  jw.write(bank);
2105  jw.write(preset);
2106  broadcast(jw, CmdConnection::f_display);
2107 }
2108 
2109 void GxService::set_display_state(TunerSwitcher::SwitcherState state) {
2110  if (!broadcast_listeners(CmdConnection::f_display_state)) {
2111  return;
2112  }
2114  jw.send_notify_begin("set_display_state");
2115  switch (state) {
2116  case TunerSwitcher::normal_mode: jw.write("normal_mode"); break;
2117  case TunerSwitcher::wait_start: jw.write("wait_start"); break;
2118  case TunerSwitcher::listening: jw.write("listening"); break;
2119  case TunerSwitcher::wait_stop: jw.write("wait_stop"); break;
2120  default: assert(false); break;
2121  }
2122  broadcast(jw, CmdConnection::f_display_state);
2123 }
2124 
2125 void GxService::remove_connection(CmdConnection *p) {
2126  for (std::list<CmdConnection*>::iterator i = connection_list.begin(); i != connection_list.end(); ++i) {
2127  if (*i == p) {
2128  connection_list.erase(i);
2129  delete p;
2130  return;
2131  }
2132  }
2133  assert(false);
2134 }
2135 
2136 //FIXME: this belongs into GxSettings
2137 void GxService::save_state() {
2138  if (!settings.get_options().get_opt_autosave()) {
2139  return;
2140  }
2141  static const int min_idle = 10; // seconds; after this idle time save state
2142  static const int max_delay = 30; // seconds; maximum age of unsaved data
2143  time_t now = time(NULL);
2144  if (oldest_unsaved == 0) {
2145  oldest_unsaved = last_change = now;
2146  save_conn = Glib::signal_timeout().connect(sigc::bind_return(sigc::mem_fun(this, &GxService::save_state),false), 1000*min_idle);
2147  return;
2148  }
2149  if (now - oldest_unsaved >= max_delay || now - last_change >= min_idle) {
2150  settings.save_to_state();
2151  sync();
2152  oldest_unsaved = 0;
2153  save_conn.disconnect();
2154  } else {
2155  last_change = now;
2156  if (oldest_unsaved == 0) {
2157  oldest_unsaved = now;
2158  }
2159  save_conn.disconnect();
2160  save_conn = Glib::signal_timeout().connect(sigc::bind_return(sigc::mem_fun(this, &GxService::save_state),false), 1000*min_idle);
2161  }
2162 }
2163 
2164 bool GxService::on_incoming(const Glib::RefPtr<Gio::SocketConnection>& connection,
2165  const Glib::RefPtr<Glib::Object>& source_object) {
2166  CmdConnection *cc = new CmdConnection(*this, connection);
2167  connection_list.push_back(cc);
2168  Glib::RefPtr<Gio::Socket> sock = connection->get_socket();
2169  sock->set_blocking(false);
2170  int flag = 1;
2171  setsockopt(sock->get_fd(), IPPROTO_TCP, TCP_NODELAY, &flag, sizeof(int));
2172  Glib::signal_io().connect(
2173  sigc::mem_fun(cc, &CmdConnection::on_data_in),
2174  sock->get_fd(), Glib::IO_IN);
2175  return true;
2176 }
2177 
2178 void GxService::serialize_parameter_change(gx_system::JsonWriter& jw) {
2179  jw.begin_array();
2180  for (std::map<std::string,bool>::iterator i = preg_map->begin(); i != preg_map->end(); ++i) {
2181  if (!i->second) {
2182  jw.write(i->first);
2183  }
2184  }
2185  jw.end_array();
2186  jw.begin_array();
2187  for (std::map<std::string,bool>::iterator i = preg_map->begin(); i != preg_map->end(); ++i) {
2188  if (i->second) {
2189  settings.get_param().writeJSON_one(jw, &settings.get_param()[i->first]);
2190  }
2191  }
2192  jw.end_array();
2193 }
2194 
2195 bool GxService::broadcast_listeners(CmdConnection::msg_type n, CmdConnection *sender) {
2196  for (std::list<CmdConnection*>::iterator p = connection_list.begin(); p != connection_list.end(); ++p) {
2197  if (*p != sender && (*p)->is_activated(n)) {
2198  return true;
2199  }
2200  }
2201  return false;
2202 }
2203 
2204 void GxService::broadcast(gx_system::JsonStringWriter& jw, CmdConnection::msg_type n, CmdConnection *sender) {
2205  jw.send_notify_end();
2206  jw.finish();
2207  for (std::list<CmdConnection*>::iterator p = connection_list.begin(); p != connection_list.end(); ++p) {
2208  if (*p != sender && (*p)->is_activated(n)) {
2209  (*p)->send(jw);
2210  }
2211  }
2212 }
2213 
2215  gx_engine::MaxLevel& m = jack.get_engine().maxlevel;
2216  for (unsigned int i = 0; i < m.channelcount; i++) {
2217  float v = m.get(i);
2218  maxlevel[i] = max(maxlevel[i], v);
2219  for (std::list<CmdConnection*>::iterator p = connection_list.begin(); p != connection_list.end(); ++p) {
2220  (*p)->update_maxlevel(i, v);
2221  }
2222  }
2223 }
iterator end()
Definition: gx_json.h:366
CmdConnection::msg_type end
Definition: jsonrpc.cpp:256
void write_kv(const char *key, float v)
Definition: gx_json.h:81
void gx_print_info(const char *, const std::string &)
Definition: gx_logging.cpp:183
CmdConnection::msg_type start
Definition: jsonrpc.cpp:255
void begin_array(bool nl=false)
Definition: gx_json.cpp:184
void save(PresetFile &pf, const Glib::ustring &name)
Definition: gx_json.cpp:1891
UiBuilderVirt(gx_system::JsonWriter *jw, const gx_system::CmdlineOptions *options, PluginDef *pd)
Definition: jsonrpc.cpp:1382
bool rename_preset(PresetFile &pf, const Glib::ustring &oldname, const Glib::ustring &newname)
Definition: gx_json.cpp:2009
~JsonArray()
Definition: jsonrpc.cpp:102
PluginDef * get_pdef()
void make_bank_unique(Glib::ustring &name, std::string *file=0)
Definition: gx_json.cpp:1458
bool remove_rack_unit(const std::string &unit, bool stereo)
Definition: gx_preset.cpp:995
void readJSON(gx_system::JsonParser &jp)
void writeJSON(gx_system::JsonWriter &jw)
void(* insertSpacer)()
Definition: gx_plugin.h:78
bool is_activated(msg_type n)
Definition: jsonrpc.h:112
map< string, Parameter * >::const_iterator iterator
Definition: gx_parameter.h:533
void setSavable(bool v)
Definition: gx_parameter.h:172
sigc::signal< void, SwitcherState > & signal_set_state()
Definition: tunerswitcher.h:71
void create_default_scratch_preset()
Definition: gx_preset.cpp:981
PluginDef * plugin
Definition: gx_plugin.h:64
std::vector< std::string > & get_rack_unit_order(bool stereo)
Definition: gx_preset.h:187
void insert(PresetFile *f)
Definition: gx_json.h:449
void(* create_fload_switch)(const char *sw_type, const char *id, const char *idf)
Definition: gx_plugin.h:102
void(* load_glade)(const char *data)
Definition: gx_plugin.h:65
std::string get_builder_filepath(const std::string &basename) const
Definition: gx_system.h:373
const std::string & id_on_off() const
virtual bool hasRange() const
void end_array(bool nl=false)
Definition: gx_json.cpp:192
bool get_is_rt()
Definition: gx_jack.h:181
bool isBool() const
Definition: gx_parameter.h:165
void activate(bool tuner_active)
bool isFile() const
Definition: gx_parameter.h:166
void send(gx_system::JsonStringWriter &jw)
Definition: jsonrpc.cpp:1319
void(* openFlipLabelBox)(const char *label)
Definition: gx_plugin.h:75
const char * value_id
Definition: gx_plugin.h:118
std::vector< PluginPresetEntry > UnitPresetList
Definition: gx_preset.h:135
const char * name
Definition: gx_plugin.h:188
static const unsigned int channelcount
std::string get_string()
Definition: gx_json.h:108
bool remove_bank(const Glib::ustring &bank)
Definition: gx_json.cpp:1999
PresetFile * get_file(const Glib::ustring &bank) const
Definition: gx_json.cpp:1623
static const struct CmdConnection::methodnames * in_word_set(const char *str, size_t len)
void list_subdirs(PathList pl, std::vector< FileName > &dirs)
Definition: gx_system.cpp:367
void(* openTabBox)(const char *label)
Definition: gx_plugin.h:67
void(* create_feedback_switch)(const char *sw_type, const char *id)
Definition: gx_plugin.h:90
void reorder(const std::vector< Glib::ustring > &neworder)
Definition: gx_json.cpp:1669
bool set(const Glib::ustring &val) const
bool get_on_off() const
virtual void writeJSON(gx_system::JsonWriter &jw) const =0
FileParameter & getFile()
Definition: gx_parameter.h:474
void writeJSON(gx_system::JsonWriter &jw)
bool isString() const
Definition: gx_parameter.h:167
void(* create_switch_no_caption)(const char *sw_type, const char *id)
Definition: gx_plugin.h:89
void set_flag(int flag, bool v)
Definition: gx_json.h:360
sigc::signal< void, bool > & signal_selection_done()
Definition: tunerswitcher.h:72
#define PROCEDURE(n)
Definition: jsonrpc.cpp:407
const char * description
Definition: gx_plugin.h:191
jack_nframes_t get_jack_bs()
Definition: gx_jack.h:179
void append(PresetFile &pf, const Glib::ustring &src, PresetFile &pftgt, const Glib::ustring &name)
Definition: gx_json.cpp:1844
std::vector< Position >::iterator iterator
Definition: gx_json.h:321
bool rename_bank(const Glib::ustring &oldname, Glib::ustring &newname)
Definition: gx_preset.cpp:1100
bool read_audio(const std::string &filename, unsigned int *audio_size, int *audio_chan, int *audio_type, int *audio_form, int *audio_rate, float **buffer)
virtual float getUpperAsFloat() const
bool get_box_visible() const
iterator end() const
Definition: gx_parameter.h:535
void load(gx_system::CmdlineOptions &options, std::vector< std::string > &old_not_found)
void(* create_p_display)(const char *id, const char *idl, const char *idh)
Definition: gx_plugin.h:93
void(* closeBox)()
Definition: gx_plugin.h:77
ctrl_type getControlType() const
Definition: gx_parameter.h:168
bool get_opt_autosave() const
Definition: gx_system.h:503
bool isInt() const
Definition: gx_parameter.h:164
void write_key(const char *p, bool nl=false)
Definition: gx_json.cpp:200
void set_jack_insert(bool v)
Definition: gx_jack.h:191
void update_maxlevel(CmdConnection *cmd=0)
Definition: jsonrpc.cpp:2214
void ladspaloader_update_plugins(gx_system::JsonWriter *jw, CmdConnection *cmd)
Definition: jsonrpc.cpp:1833
const char ** groups
Definition: gx_plugin.h:189
void(* load_glade_file)(const char *fname)
Definition: gx_plugin.h:66
bool on_data_out(Glib::IOCondition cond)
Definition: jsonrpc.cpp:1276
virtual double getFloat() const
Definition: jsonrpc.cpp:140
void writeJSON_remote(JsonWriter &jw)
Definition: gx_json.cpp:920
void gx_print_fatal(const char *, const std::string &)
Definition: gx_logging.cpp:177
const char * shortname
Definition: gx_plugin.h:193
sigc::signal< void, float > & signal_changed()
Definition: gx_parameter.h:271
float get_jcpu_load()
Definition: gx_jack.h:180
bool is_mutable() const
Definition: gx_json.h:367
bool get_active()
Definition: tunerswitcher.h:66
sigc::signal< void > & signal_selection_changed()
Definition: gx_json.h:476
#define FUNCTION(n)
Definition: jsonrpc.cpp:406
const char * category
Definition: gx_plugin.h:192
virtual float getStepAsFloat() const
void gx_print_error(const char *, const std::string &)
Definition: gx_logging.cpp:166
static GxLogger & get_logger()
Definition: gx_logging.cpp:50
gx_system::PresetFile * bank_insert_new(const Glib::ustring &name)
Definition: gx_preset.cpp:1086
virtual float getLowerAsFloat() const
void(* create_wheel)(const char *id, const char *label)
Definition: gx_plugin.h:99
void plugin_preset_list_load(const PluginDef *pdef, UnitPresetList &presetnames)
Definition: gx_preset.cpp:1225
void(* create_selector)(const char *id, const char *label)
Definition: gx_plugin.h:95
Glib::ustring message
Definition: jsonrpc.cpp:56
const char * engine_state_to_string(gx_engine::GxEngineState s)
Definition: jsonrpc.cpp:29
void(* openHorizontalBox)(const char *label)
Definition: gx_plugin.h:71
const std::string & id_box_visible() const
virtual gx_system::JsonSubParser getSubParser() const
Definition: jsonrpc.cpp:152
const char * id
Definition: gx_plugin.h:187
gx_system::CmdlineOptions & get_options() const
Definition: gx_preset.h:175
void send_midi_cc(int cc_num, int pgm_num, int bgn, int num)
Definition: gx_jack.cpp:846
GxService(gx_preset::GxSettings &settings_, gx_jack::GxJack &jack_, TunerSwitcher &tunerswitcher, sigc::slot< void > quit_mainloop_, const Glib::ustring &host, int *port)
Definition: jsonrpc.cpp:1698
bool isFloat() const
Definition: gx_parameter.h:163
bool hasId(const string &id) const
Definition: gx_parameter.h:536
void send_rack_changed(bool stereo, CmdConnection *cmd)
Definition: jsonrpc.cpp:1859
void readJSON(gx_system::JsonParser &jp)
void plugin_preset_list_save(const PluginDef *pdef, const Glib::ustring &name)
Definition: gx_preset.cpp:1280
#define max(x, y)
const char * get_typename() const
string l_group() const
Definition: gx_parameter.h:175
void(* create_port_display)(const char *id, const char *label)
Definition: gx_plugin.h:92
int get_effect_post_pre() const
~RpcError()
Definition: jsonrpc.cpp:59
RpcError(int code_, Glib::ustring message_)
Definition: jsonrpc.cpp:58
sigc::signal< void, bool > & signal_changed()
Definition: gx_parameter.h:377
friend class CmdConnection
Definition: jsonrpc.h:170
StringParameter & getString()
Definition: gx_parameter.h:479
void save(gx_system::CmdlineOptions &options)
void insert_rack_unit(const std::string &unit, const std::string &before, bool stereo)
Definition: gx_preset.cpp:1005
bool convert_preset(PresetFile &pf)
Definition: gx_json.cpp:1954
void(* openFrameBox)(const char *label)
Definition: gx_plugin.h:74
void begin_object(bool nl=false)
Definition: gx_json.cpp:168
void plugin_preset_list_sync_set(const PluginDef *pdef, bool factory, const Glib::ustring &name)
Definition: gx_preset.cpp:1264
void(* create_small_rackknobr)(const char *id, const char *label)
Definition: gx_plugin.h:98
void insert_after(PresetFile &pf, const Glib::ustring &src, PresetFile &pftgt, const Glib::ustring &pos, const Glib::ustring &name)
Definition: gx_json.cpp:1882
sigc::signal< void > & signal_presetlist_changed()
Definition: gx_json.h:478
void writeJSON_one(gx_system::JsonWriter &jw, Parameter *p)
void(* create_simple_spin_value)(const char *id)
Definition: gx_plugin.h:100
void(* create_simple_meter)(const char *id)
Definition: gx_plugin.h:96
void write_null(bool nl=false)
Definition: gx_json.h:94
string l_name() const
Definition: gx_parameter.h:177
virtual int getInt() const
Definition: jsonrpc.cpp:144
JsonValue * operator[](unsigned int i)
Definition: jsonrpc.cpp:108
void load_preset(PresetFile *pf, const Glib::ustring &name)
Definition: gx_json.cpp:1770
msg_signal & signal_message()
Definition: gx_logging.cpp:77
void(* create_mid_rackknob)(const char *id, const char *label)
Definition: gx_plugin.h:103
int flags
Definition: gx_plugin.h:185
sigc::signal< void, Parameter *, bool > signal_insert_remove()
Definition: gx_parameter.h:550
void(* openVerticalBox2)(const char *label)
Definition: gx_plugin.h:70
virtual void writeJSON(gx_system::JsonWriter &jw) const
void copy_object(JsonWriter &jw)
Definition: gx_json.cpp:580
virtual const char * what() const
Definition: gx_json.h:46
FloatParameter * reg_par(const string &id, const string &name, float *var, float std, float lower, float upper, float step)
Definition: gx_parameter.h:553
gx_engine::GxEngineState string_to_engine_state(const std::string &s)
Definition: jsonrpc.cpp:39
const PathList & get_IR_pathlist() const
Definition: gx_system.h:377
std::string get_string()
Definition: gx_json.h:210
sigc::signal< void, bool > & signal_rack_unit_order_changed()
Definition: gx_preset.h:188
void(* create_small_rackknob)(const char *id, const char *label)
Definition: gx_plugin.h:86
bool on_data_in(Glib::IOCondition cond)
Definition: jsonrpc.cpp:1289
void send_notify_begin(const char *method)
Definition: gx_json.cpp:226
streampos get_streampos()
Definition: gx_json.h:140
#define END_FUNCTION_SWITCH(s)
Definition: jsonrpc.cpp:408
void(* openpaintampBox)(const char *label)
Definition: gx_plugin.h:76
std::vector< FileName > & get_listing()
Definition: gx_system.h:341
int code
Definition: jsonrpc.cpp:55
FloatParameter & getFloat()
Definition: gx_parameter.h:453
void(* openHorizontalhideBox)(const char *label)
Definition: gx_plugin.h:72
static float get(unsigned int channel)
virtual const char * what() const
Definition: jsonrpc.cpp:60
const Glib::ustring & get_current_name()
Definition: gx_json.h:484
void(* create_feedback_slider)(const char *id, const char *label)
Definition: gx_plugin.h:85
void set_blocked(bool v)
Definition: gx_parameter.h:183
void(* create_spin_value)(const char *id, const char *label)
Definition: gx_plugin.h:91
void readJSON(gx_system::JsonParser &jp)
string current_value() const
Definition: gx_json.h:143
IntParameter & getInt()
Definition: gx_parameter.h:458
void append(gx_system::JsonParser &jp)
Definition: jsonrpc.cpp:115
iterator begin() const
Definition: gx_parameter.h:534
void(* create_big_rackknob)(const char *id, const char *label)
Definition: gx_plugin.h:87
void(* openHorizontalTableBox)(const char *label)
Definition: gx_plugin.h:73
void(* set_next_flags)(int flags)
Definition: gx_plugin.h:79
virtual float idx_from_id(string v_id)
void set_box_visible(bool v) const
const char * token
Definition: jsonrpc.cpp:254
void plugin_preset_list_remove(const PluginDef *pdef, const Glib::ustring &name)
Definition: gx_preset.cpp:1284
sigc::signal< void, const Glib::ustring & > & signal_changed()
Definition: gx_parameter.h:447
void set_on_off(bool v) const
virtual int idx_from_id(string v_id)
int flag
Definition: ladspaback.cpp:55
const Glib::ustring & get_value() const
Definition: gx_parameter.h:433
static const char * value_label(const value_pair &vp)
Definition: gx_parameter.h:199
sigc::signal< void, const Glib::ustring &, const Glib::ustring & > & signal_display()
Definition: tunerswitcher.h:70
#define START_FUNCTION_SWITCH(v)
Definition: jsonrpc.cpp:405
void(* create_simple_c_meter)(const char *id, const char *idl, const char *label)
Definition: gx_plugin.h:97
token next(token expect=no_token)
Definition: gx_json.cpp:496
BoolParameter & getBool()
Definition: gx_parameter.h:469
void write(float v, bool nl=false)
Definition: gx_json.cpp:116
void(* create_eq_rackslider_no_caption)(const char *id)
Definition: gx_plugin.h:101
CmdConnection(GxService &serv, const Glib::RefPtr< Gio::SocketConnection > &connection_)
Definition: jsonrpc.cpp:235
int get_position() const
const string & id() const
Definition: gx_parameter.h:173
void insert_before(PresetFile &pf, const Glib::ustring &src, PresetFile &pftgt, const Glib::ustring &pos, const Glib::ustring &name)
Definition: gx_json.cpp:1862
void(* create_switch)(const char *sw_type, const char *id, const char *label)
Definition: gx_plugin.h:94
gx_engine::ParamMap & get_param() const
Definition: gx_preset.h:174
iterator begin()
Definition: gx_json.h:443
uiloader load_ui
Definition: gx_plugin.h:203
void toggle(bool tuner_active)
bool create_file(const Glib::ustring &name, const std::string &path, int tp, int flags)
Definition: gx_json.cpp:994
const std::string & get_filename() const
Definition: gx_json.h:337
void(* openVerticalBox1)(const char *label)
Definition: gx_plugin.h:69
void unplug_queue()
Definition: gx_logging.cpp:82
gx_system::PresetFile * bank_insert_content(const Glib::ustring &uri, const std::string content)
Definition: gx_preset.cpp:1058
bool set(const Glib::RefPtr< Gio::File > &val)
sigc::signal< void, int > & signal_changed()
Definition: gx_parameter.h:326
void(* create_master_slider)(const char *id, const char *label)
Definition: gx_plugin.h:84
jack_nframes_t get_time_is()
Definition: gx_jack.h:182
void end_object(bool nl=false)
Definition: gx_json.cpp:176
const Glib::ustring & get_current_bank()
Definition: gx_json.h:482
void save_to_state(bool preserve_preset=false)
Definition: gx_json.cpp:1830
void(* create_selector_no_caption)(const char *id)
Definition: gx_plugin.h:88
void(* openVerticalBox)(const char *label)
Definition: gx_plugin.h:68
virtual const Glib::ustring & getString() const
Definition: jsonrpc.cpp:148
void plugin_preset_list_set(const PluginDef *pdef, bool factory, const Glib::ustring &name)
Definition: gx_preset.cpp:1275
void reorder_preset(PresetFile &pf, const std::vector< Glib::ustring > &neworder)
Definition: gx_json.cpp:1916
virtual void writeJSON(gx_system::JsonWriter &jw) const
virtual const value_pair * getValueNames() const
void erase_preset(const Glib::ustring &name)