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(), &current_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