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