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