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 "guitarix.h"
20 #include <sys/mman.h>
21 #include "jsonrpc_methods.h"
22 #include <netinet/in.h>
23 #include <netinet/tcp.h>
24 #include <sys/ioctl.h>
25 #include <sys/types.h>
26 #include <sys/socket.h>
27 #ifdef HAVE_BLUEZ
28 #include <bluetooth/bluetooth.h>
29 #include <bluetooth/rfcomm.h>
30 #endif
31 
32 #if !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(__DragonFly__)
33 #include <malloc.h>
34 
set_memory_allocation()35 void set_memory_allocation() {
36     if (mlockall(MCL_CURRENT | MCL_FUTURE))
37         gx_print_error("system init", "mlockall failed:");
38 #if defined(M_TRIM_THRESHOLD) && defined(M_MMAP_MAX)
39     mallopt(M_TRIM_THRESHOLD, -1);
40     mallopt(M_MMAP_MAX, 0);
41 #endif
42 }
43 
44 #else
45 
set_memory_allocation()46 void set_memory_allocation() {}
47 
48 #endif
49 
lock_rt_memory()50 void lock_rt_memory() {
51 #if !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(__DragonFly__)
52     extern char __rt_text__start[], __rt_text__end[];
53     extern char __rt_data__start[], __rt_data__end[];
54     struct {
55 	char *start;
56 	long len;
57     } regions[] = {
58 	{ __rt_text__start, __rt_text__end - __rt_text__start },
59 	{ __rt_data__start, __rt_data__end - __rt_data__start },
60     };
61     long int total_size = 0;
62     set_memory_allocation();
63     for (unsigned int i = 0; i < sizeof(regions)/sizeof(regions[0]); i++) {
64         total_size +=regions[i].len;
65         if (mlock(regions[i].start, regions[i].len) != 0) {
66             gx_print_error(
67             "system init",
68             boost::format(_("failed to lock memory: %1%")) % strerror(errno));
69         }
70     }
71 #ifndef NDEBUG
72     fprintf(stderr,"mlock %ld bytes\n",total_size);
73 #endif
74 #endif
75 }
76 
unlock_rt_memory()77 void unlock_rt_memory() {
78 #ifndef __APPLE__
79     extern char __rt_text__start[], __rt_text__end[];
80     extern char __rt_data__start[], __rt_data__end[];
81     struct {
82     char *start;
83     long len;
84     } regions[] = {
85     { __rt_text__start, __rt_text__end - __rt_text__start },
86     { __rt_data__start, __rt_data__end - __rt_data__start },
87     };
88     long int total_size = 0;
89     for (unsigned int i = 0; i < sizeof(regions)/sizeof(regions[0]); i++) {
90         total_size +=regions[i].len;
91         if (munlock(regions[i].start, regions[i].len) != 0) {
92             gx_print_error(
93             "system init",
94             boost::format(_("failed to unlock memory: %1%")) % strerror(errno));
95         }
96     }
97 #ifndef NDEBUG
98     fprintf(stderr,"munlock %ld bytes\n",total_size);
99 #endif
100 #endif
101 }
102 
103 namespace gx_engine {
104 
GxMachineBase()105 GxMachineBase::GxMachineBase()
106     : impresp_list() {
107 }
108 
~GxMachineBase()109 GxMachineBase::~GxMachineBase() {
110 }
111 
set_update_parameter(void * control,const string & id,bool on)112 void GxMachineBase::set_update_parameter(void *control, const string& id, bool on) {
113     if (on) {
114 	update_map[id].insert(control);
115 	if (!update_timeout.connected()) {
116 	    update_timeout = Glib::signal_timeout().connect(
117 		sigc::mem_fun(*this, &GxMachineBase::update_parameter), 60);
118 	}
119     } else {
120 	output_listen_map::iterator i = update_map.find(id);
121 	if (i != update_map.end()) {
122 	    i->second.erase(control);
123 	    if (i->second.empty()) {
124 		update_map.erase(id);
125 	    }
126 	}
127 	if (update_map.empty()) {
128 	    update_timeout.disconnect();
129 	}
130     }
131 }
132 
133 
134 /****************************************************************
135  ** GxMachine
136  */
137 
set_engine_mute(GxEngineState s,BoolParameter & p)138 void set_engine_mute(GxEngineState s, BoolParameter& p) {
139     p.set(s == kEngineOff);
140 }
141 
on_engine_mute_changed(bool s,GxEngine & engine)142 void on_engine_mute_changed(bool s, GxEngine& engine) {
143     if (s) {
144 	engine.set_state(kEngineOff);
145     } else {
146 	if (engine.get_state() == kEngineOff) {
147 	    engine.set_state(kEngineOn);
148 	}
149     }
150 }
151 
on_engine_bypass_changed(bool s,GxEngine & engine)152 void on_engine_bypass_changed(bool s, GxEngine& engine) {
153     if (s) {
154 	engine.set_state(kEngineBypass);
155     } else {
156 	if (engine.get_state() == kEngineBypass) {
157 	    engine.set_state(kEngineOn);
158 	}
159     }
160 }
161 
process_cmdline_bank_preset()162 void GxMachine::process_cmdline_bank_preset() {
163     Glib::ustring sbank = options.get_setbank();
164     if (sbank.empty()) {
165         return;
166     }
167     sbank = sbank.lowercase();
168     if (sbank.size() < 2) {
169         return;
170     }
171     Glib::ustring bank = settings.banks.get_name(
172         KeySwitcher::key_offset_to_bank_idx(sbank[0]-'a', bank_size()));
173     int i = (sbank[1] == ':' ? 2 : 1);
174     Glib::ustring preset = get_bank_file(bank)->get_name(
175         KeySwitcher::key_offset_to_idx(std::stoi(sbank.substr(i))));
176     options.set_bank_preset(bank, preset);
177 }
178 
GxMachine(gx_system::CmdlineOptions & options_)179 GxMachine::GxMachine(gx_system::CmdlineOptions& options_):
180     GxMachineBase(),
181     options(options_),
182     engine(options.get_plugin_dir(), gx_engine::get_group_table(), options),
183     jack(engine),
184     settings(options, jack, engine.stereo_convolver, gx_engine::midi_std_ctr,
185 	     engine.controller_map, engine),
186     tuner_switcher(settings, engine),
187     sock(0),
188 #ifdef HAVE_AVAHI
189     avahi_service(0),
190 #endif
191     pmap(engine.get_param()),
192     switch_bank() {
193     engine.oscilloscope.set_jack(jack);
194     process_cmdline_bank_preset();
195 
196     /*
197     ** setup parameters
198     */
199 
200     static value_pair starter[] = {
201 	{ "other", "other" },
202 	{ "qjackctl", "qjackctl" },
203 	{ "autostart", "autostart" },
204 	{0}
205     };
206     pmap.reg_non_midi_enum_par(
207 	"ui.jack_starter_idx", "", starter, static_cast<int*>(0), false, 1);
208     pmap.reg_non_midi_par("ui.ask_for_jack_starter", (bool*)0, false, true);
209     pmap.reg_string("ui.jack_starter", "", 0, "");
210 
211     // rack tuner
212     gx_engine::get_group_table().insert("racktuner", N_("Rack Tuner"));
213     static const value_pair streaming_labels[] = {{"scale"}, {"stream"}, {0}};
214     pmap.reg_non_midi_enum_par("racktuner.streaming", "Streaming Mode", streaming_labels, (int*)0, false, 1);
215     static const value_pair tuning_labels[] = {{"(Chromatic)"},{"Standard"}, {"Standard/Es"}, {"Open E"},
216         {"Drop D"},{"Half Step Down"},{"Full Step Down"},{"1 and 1/2 Steps Down"},{"Double Drop D"},{"Drop C"},
217         {"Drop C#"},{"Drop B"},{"Drop A#"},{"Drop A"},{"Open D"},{"Open D Minor"}, {"Open G"},{"Open G Minor"},
218         {"Open C"},{"Open C#"},{"Open C Minor"},{"Open E7"},{"Open E Minor7"},{"Open G Major7"},{"Open A Minor"},
219         {"Open A Minor7"},{"Open A"},{"C Tuning"},{"C# Tuning"},{"Bb Tuning"},{"A to A (Baritone)"},{"Open Dsus2"},
220         {"Open Gsus2"},{"G6"},{"Modal G"},{"Overtone"},{"Pentatonic"},{"Minor Third"},{"Major Third"},{"All Fourths"},
221         {"Augmented Fourths"},{"Slow Motion"},{"Admiral"},{"Buzzard"},{"Face"},{"Four and Twenty"},{"Ostrich"},{"Capo 200"},
222         {"Balalaika"},{"Cittern One"},{"Cittern Two"},{"Dobro"},{"Lefty"},{"Mandoguitar"},{"Rusty Cage"},{"Hardcore"}, {0}};
223     pmap.reg_non_midi_enum_par("racktuner.tuning", "Tuning", tuning_labels, (int*)0, false, 0);
224     static const value_pair tuning_temperament[] = {{"12-ET"},{"19-ET"},{"24-ET"},{"31-ET"},{"41-ET"},{"53-ET"}, {0}};
225     pmap.reg_non_midi_enum_par("racktuner.temperament", "Temperament", tuning_temperament, (int*)0, false, 0);
226     pmap.reg_par_non_preset("racktuner.scale_lim", "Limit", 0, 3.0, 1.0, 10.0, 1.0);
227     pmap.reg_par_non_preset("ui.tuner_reference_pitch", "?Tuner Reference Pitch", 0, 440, 225, 453, 0.1);
228     //pmap.reg_par("racktuner.scale_lim", "Limit", &scale_lim, 3.0, 1.0, 10.0, 1.0); FIXME add in detail view?
229 
230     static const value_pair midi_channels[] = {{"--"},{"1"},{"2"},{"3"},{"4"},{"5"},{"6"},{"7"},{"8"},{"9"},{"10"},
231         {"11"},{"12"},{"13"},{"14"},{"15"},{"16"}, {0}};
232     EnumParameter* ep = pmap.reg_non_midi_enum_par("system.midi_channel", "Midichannel", midi_channels, (int*)0, false, 0);
233     ep->signal_changed_int().connect(sigc::mem_fun(this, &GxMachineBase::set_midi_channel));
234 
235     pmap.reg_par("ui.live_play_switcher", "Liveplay preset mode" , (bool*)0, false, false)->setSavable(false);
236     BoolParameter& up = pmap.reg_par("ui.racktuner", N_("Tuner on/off"), (bool*)0, false, false)->getBool();
237     up.signal_changed().connect(
238         sigc::mem_fun(this, &GxMachineBase::tuner_switch));
239     pmap.reg_non_midi_par("system.show_tuner", (bool*)0, false);
240     pmap.reg_non_midi_par("system.stick_tuner", (bool*)0, false);
241     BoolParameter& mp = pmap.reg_par("system.midiout_tuner", "Tuner midi output",(bool*)0, false, false)->getBool();
242     mp.signal_changed().connect(
243         sigc::mem_fun(this, &GxMachineBase::tuner_used_by_midi));
244 
245     pmap.reg_non_midi_par("system.midi_in_preset", (bool*)0, false, false);
246     pmap.reg_par_non_preset("ui.liveplay_brightness", "?liveplay_brightness", 0, 1.0, 0.5, 1.0, 0.01);
247     pmap.reg_par_non_preset("ui.liveplay_background", "?liveplay_background", 0, 0.8, 0.0, 1.0, 0.01);
248     pmap.reg_par("engine.next_preset", "Switch to next preset" , (bool*)0, false, false)->setSavable(false);
249     pmap.reg_par("engine.previus_preset", "Switch to previous preset" , (bool*)0, false, false)->setSavable(false);
250     BoolParameter& p = pmap.reg_par(
251 	"engine.mute", "Mute", 0, engine.get_state() == gx_engine::kEngineOff
252 	)->getBool();
253     p.setSavable(false);
254     engine.signal_state_change().connect(
255 	sigc::bind(sigc::ptr_fun(set_engine_mute), sigc::ref(p)));
256     p.signal_changed().connect(
257 	sigc::bind(sigc::ptr_fun(on_engine_mute_changed), sigc::ref(engine)));
258     BoolParameter& pb = pmap.reg_par(
259 	"engine.bypass", "Bypass", 0, engine.get_state() == gx_engine::kEngineBypass
260 	)->getBool();
261     pb.setSavable(false);
262     pb.signal_changed().connect(
263 	sigc::bind(sigc::ptr_fun(on_engine_bypass_changed), sigc::ref(engine)));
264     pmap.reg_non_midi_par("ui.mp_s_h", (bool*)0, false);
265     pmap.reg_non_midi_par("ui.all_s_h", (bool*)0, false);
266     BoolParameter& ip = pmap.reg_par(
267       "engine.insert", N_("switch insert ports on/off"), (bool*)0, false, false)->getBool();
268     ip.signal_changed().connect(
269 	sigc::mem_fun(this, &GxMachineBase::set_jack_insert));
270 
271     gx_preset::UnitPresetList presetnames;
272     plugin_preset_list_load(pluginlist_lookup_plugin("seq")->get_pdef(), presetnames);
273     for (gx_preset::UnitPresetList::iterator i = presetnames.begin(); i != presetnames.end(); ++i) {
274         if (!i->name.empty()) {
275             Glib::ustring id = "seq." + i->name;
276             Glib::ustring tb = "switch to preset " + i->name;
277             BoolParameter& sp = pmap.reg_par(
278               id, tb, (bool*)0, false, false)->getBool();
279             sp.setSavable(false);
280             sp.signal_changed().connect(sigc::hide(
281                sigc::bind(sigc::bind(sigc::bind(sigc::mem_fun(this, &GxMachine::plugin_preset_list_set_on_idle), i->name), false),pluginlist_lookup_plugin("seq")->get_pdef())));
282         }
283     }
284 
285 #ifndef NDEBUG
286     // ------ time measurement (debug) ------
287     gx_system::add_time_measurement();
288 #endif
289     lock_rt_memory();
290 
291     engine.controller_map.signal_new_program().connect(
292 	sigc::mem_fun(this, &GxMachine::do_program_change));
293     engine.controller_map.signal_new_mute_state().connect(
294 	sigc::mem_fun(this, &GxMachine::set_mute_state));
295     engine.controller_map.signal_new_bank().connect(
296 	sigc::mem_fun(this, &GxMachine::do_bank_change));
297     pmap["ui.live_play_switcher"].signal_changed_bool().connect(
298 	sigc::mem_fun(this, &GxMachine::edge_toggle_tuner));
299     switch_bank = settings.get_current_bank();
300     pmap["engine.next_preset"].signal_changed_bool().connect(
301 	sigc::mem_fun(this, &GxMachine::process_next_preset_switch));
302     pmap["engine.previus_preset"].signal_changed_bool().connect(
303 	sigc::mem_fun(this, &GxMachine::process_previus_preset_switch));
304     engine.controller_map.signal_trigger_midi_feedback().connect(
305         sigc::mem_fun(this, &GxMachine::midi_feedback));
306     engine.tuner.signal_freq_changed().connect(
307         sigc::mem_fun(this, &GxMachine::on_tuner_freq_changed));
308 }
309 
~GxMachine()310 GxMachine::~GxMachine() {
311     stop_socket();
312     unlock_rt_memory();
313 #ifndef NDEBUG
314     if (options.dump_parameter) {
315 	pmap.dump("json");
316     }
317 #endif
318 }
319 
insert_param(Glib::ustring group,Glib::ustring name)320 void GxMachine::insert_param(Glib::ustring group, Glib::ustring name) {
321 
322     Glib::ustring tb = "switch to preset " + name;
323     Glib::ustring id = group + "." + name;
324     BoolParameter& sp = pmap.reg_par(
325       id, tb, (bool*)0, false, false)->getBool();
326     sp.setSavable(false);
327     sp.signal_changed().connect(sigc::hide(
328       sigc::bind(sigc::bind(sigc::bind(sigc::mem_fun(this, &GxMachine::plugin_preset_list_set_on_idle), name), false),pluginlist_lookup_plugin("seq")->get_pdef())));
329 }
330 
edge_toggle_tuner(bool v)331 void GxMachine::edge_toggle_tuner(bool v) {
332     if (v) {
333 	tuner_switcher.toggle(engine.tuner.used_for_display());
334     }
335 }
336 
next_preset_switch()337 void GxMachine::next_preset_switch() {
338     gx_system::PresetFileGui *f= get_current_bank_file();
339     int idx = f->get_index(get_current_name());
340     if (idx+1 < f->size()) load_preset(f, f->get_name(idx+1));
341     else load_preset(f, f->get_name(0));
342 }
343 
previus_preset_switch()344 void GxMachine::previus_preset_switch() {
345     gx_system::PresetFileGui *f= get_current_bank_file();
346     int idx = f->get_index(get_current_name());
347     if (idx-1 > -1) load_preset(f, f->get_name(idx-1));
348     else load_preset(f, f->get_name(f->size()-1));
349 }
350 
process_next_preset_switch(bool s)351 void GxMachine::process_next_preset_switch(bool s) {
352     if(s) {
353         Glib::signal_idle().connect_once(
354           sigc::mem_fun(this, &GxMachine::next_preset_switch));
355         set_parameter_value("engine.next_preset",false);
356     }
357 }
358 
process_previus_preset_switch(bool s)359 void GxMachine::process_previus_preset_switch(bool s) {
360     if(s) {
361         Glib::signal_idle().connect_once(
362           sigc::mem_fun(this, &GxMachine::previus_preset_switch));
363         set_parameter_value("engine.previus_preset",false);
364     }
365 }
366 
do_program_change(int pgm)367 void GxMachine::do_program_change(int pgm) {
368     Glib::ustring bank = settings.get_current_bank();
369     if ((bank != switch_bank) && !switch_bank.empty()) {
370         bank = switch_bank;
371 	}
372     bool in_preset = !bank.empty();
373     gx_system::PresetFile *f;
374     if (in_preset) {
375         f = settings.banks.get_file(bank);
376         in_preset = pgm < f->size();
377     }
378     if (in_preset) {
379         settings.load_preset(f, f->get_name(pgm));
380         set_parameter_value("system.current_bank",bank);
381 	if (engine.get_state() == gx_engine::kEngineBypass) {
382 	    engine.set_state(gx_engine::kEngineOn);
383 	}
384     } // do nothing when bank/preset is out of range
385     // else if (engine.get_state() == gx_engine::kEngineOn) {
386 	// engine.set_state(gx_engine::kEngineBypass);
387     //}
388 }
389 
reset_switch_bank()390 void GxMachine::reset_switch_bank() {
391 	switch_bank = settings.get_current_bank();
392 }
393 
do_bank_change(int pgm)394 void GxMachine::do_bank_change(int pgm) {
395 	if (!get_bank_name(pgm).empty()) {
396 		switch_bank = get_bank_name(pgm);
397 		Glib::signal_timeout().connect_once(
398 		    sigc::mem_fun(this,&GxMachine::reset_switch_bank), 50);
399 	} else {
400 		switch_bank = settings.get_current_bank();
401 	}
402 }
403 
set_mute_state(int mute)404 void GxMachine::set_mute_state(int mute) {
405 	if (mute == 0) {
406 		engine.set_state(gx_engine::kEngineOn);
407 	} else  {
408 		engine.set_state(gx_engine::kEngineOff);
409 	}
410 }
411 
set_state(GxEngineState state)412 void GxMachine::set_state(GxEngineState state) {
413     engine.set_state(state);
414 }
415 
get_state()416 GxEngineState GxMachine::get_state() {
417     return engine.get_state();
418 }
419 
load_ladspalist(std::vector<std::string> & old_not_found,ladspa::LadspaPluginList & pluginlist)420 void GxMachine::load_ladspalist(std::vector<std::string>& old_not_found, ladspa::LadspaPluginList& pluginlist) {
421     pluginlist.load(options, old_not_found);
422 }
423 
save_ladspalist(ladspa::LadspaPluginList & pluginlist)424 void GxMachine::save_ladspalist(ladspa::LadspaPluginList& pluginlist) {
425     pluginlist.save(options);
426 }
427 
commit_ladspa_changes()428 void GxMachine::commit_ladspa_changes() {
429     if (sock) {
430 	sock->ladspaloader_update_plugins(0, 0);
431     } else {
432 	engine.ladspaloader_update_plugins();
433     }
434 }
435 
signal_plugin_changed()436 sigc::signal<void,Plugin*,PluginChange::pc>& GxMachine::signal_plugin_changed() {
437     return engine.signal_plugin_changed();
438 }
439 
pluginlist_lookup_plugin(const std::string & id) const440 Plugin *GxMachine::pluginlist_lookup_plugin(const std::string& id) const {
441     return engine.pluginlist.lookup_plugin(id);
442 }
443 
load_unit(gx_gui::UiBuilderImpl & builder,PluginDef * pdef)444 bool GxMachine::load_unit(gx_gui::UiBuilderImpl& builder, PluginDef* pdef) {
445     return builder.load_unit(pdef);
446 }
447 
pluginlist_append_rack(UiBuilderBase & ui)448 void GxMachine::pluginlist_append_rack(UiBuilderBase& ui) {
449     engine.pluginlist.append_rack(ui);
450 }
451 
get_tuner_freq()452 float GxMachine::get_tuner_freq() {
453     return engine.tuner.get_freq();
454 }
455 
get_tuner_note()456 float GxMachine::get_tuner_note() {
457     return engine.tuner.get_note();
458 }
459 
set_oscilloscope_mul_buffer(int a)460 void GxMachine::set_oscilloscope_mul_buffer(int a) {
461     engine.oscilloscope.set_mul_buffer(a, jack.get_jack_bs());
462 }
463 
get_oscilloscope_mul_buffer()464 int GxMachine::get_oscilloscope_mul_buffer() {
465     return engine.oscilloscope.get_mul_buffer();
466 }
467 
get_options() const468 gx_system::CmdlineOptions& GxMachine::get_options() const {
469     return options;
470 }
471 
exit_handler(bool otherthread)472 void GxMachine::exit_handler(bool otherthread) {
473     if (!otherthread) {
474 	delete sock;
475 	sock = 0;
476     }
477 }
478 
stop_socket()479 void GxMachine::stop_socket() {
480 #ifdef HAVE_AVAHI
481     delete avahi_service;
482     avahi_service = 0;
483 #endif
484     delete sock;
485     sock = 0;
486 }
487 
start_socket(sigc::slot<void> quit_mainloop,const Glib::ustring & host,int port)488 void GxMachine::start_socket(sigc::slot<void> quit_mainloop, const Glib::ustring& host, int port) {
489     if (sock) {
490 	return;
491     }
492     sock = new GxService(settings, jack, tuner_switcher, quit_mainloop, host, &port);
493     sock->start();
494     GxExit::get_instance().signal_exit().connect(
495 	sigc::mem_fun(*this, &GxMachine::exit_handler));
496 #ifdef HAVE_AVAHI
497     if (port > 0) {
498 	std::string name = "Guitarix";
499 	if (jack.get_default_instancename() != jack.get_instancename()) {
500 	    name += ": " + jack.get_instancename();
501 	}
502 	avahi_service = new AvahiService;
503 	avahi_service->register_service(name, port);
504     }
505 #endif
506 }
507 
tuner_switcher_signal_display()508 sigc::signal<void,const Glib::ustring&,const Glib::ustring&>& GxMachine::tuner_switcher_signal_display() {
509     return tuner_switcher.signal_display();
510 }
511 
tuner_switcher_signal_set_state()512 sigc::signal<void,TunerSwitcher::SwitcherState>& GxMachine::tuner_switcher_signal_set_state() {
513     return tuner_switcher.signal_set_state();
514 }
515 
tuner_switcher_signal_selection_done()516 sigc::signal<void, bool>& GxMachine::tuner_switcher_signal_selection_done() {
517     return tuner_switcher.signal_selection_done();
518 }
519 
signal_state_change()520 sigc::signal<void,GxEngineState>& GxMachine::signal_state_change() {
521     return engine.signal_state_change();
522 }
523 
tuner_used_for_display(bool on)524 void GxMachine::tuner_used_for_display(bool on) {
525     engine.tuner.used_for_display(on);
526 }
527 
tuner_used_by_midi(bool on)528 void GxMachine::tuner_used_by_midi(bool on) {
529     if ((on && get_parameter("ui.racktuner").getBool().get_value()) || !on) {
530         engine.tuner.used_by_midi(on);
531     }
532 }
533 
tuner_switch(bool on)534 void GxMachine::tuner_switch(bool on) {
535     if (!on && get_parameter("system.midiout_tuner").getBool().get_value()) {
536         engine.tuner.used_by_midi(false);
537     } else if (on && get_parameter("system.midiout_tuner").getBool().get_value()) {
538         engine.tuner.used_by_midi(true);
539     }
540 }
541 
get_rack_unit_order(PluginType type)542 const std::vector<std::string>& GxMachine::get_rack_unit_order(PluginType type) {
543     return settings.get_rack_unit_order(type == PLUGIN_TYPE_STEREO);
544 }
545 
signal_rack_unit_order_changed()546 sigc::signal<void,bool>& GxMachine::signal_rack_unit_order_changed() {
547     return settings.signal_rack_unit_order_changed();
548 }
549 
remove_rack_unit(const std::string & unit,PluginType type)550 void GxMachine::remove_rack_unit(const std::string& unit, PluginType type) {
551     if (!settings.remove_rack_unit(unit, type == PLUGIN_TYPE_STEREO)) {
552 	return;
553     }
554     settings.signal_rack_unit_order_changed()(type == PLUGIN_TYPE_STEREO);
555 }
556 
insert_rack_unit(const std::string & unit,const std::string & before,PluginType type)557 void GxMachine::insert_rack_unit(const std::string& unit, const std::string& before, PluginType type) {
558     settings.insert_rack_unit(unit, before, type == PLUGIN_TYPE_STEREO);
559     settings.signal_rack_unit_order_changed()(type == PLUGIN_TYPE_STEREO);
560 }
561 
562 // tuner_switcher
get_tuner_switcher_active()563 bool GxMachine::get_tuner_switcher_active() {
564     return tuner_switcher.get_active();
565 }
566 
tuner_switcher_activate(bool v)567 void GxMachine::tuner_switcher_activate(bool v) {
568     tuner_switcher.activate(v);
569 }
570 
tuner_switcher_deactivate()571 void GxMachine::tuner_switcher_deactivate() {
572     tuner_switcher.deactivate();
573 }
574 
tuner_switcher_toggle(bool v)575 void GxMachine::tuner_switcher_toggle(bool v) {
576     tuner_switcher.toggle(v);
577 }
578 
579 
on_tuner_freq_changed()580 void GxMachine::on_tuner_freq_changed() {
581 #ifdef USE_MIDI_CC_OUT
582     if (get_parameter("system.midiout_tuner").getBool().get_value()) {
583         float fnote = engine.tuner.get_note();
584         if (fnote < 999.0) {
585             //float tet = get_parameter("racktuner.temperament").getFloat().get_value();
586             int note = static_cast<int>(round(fnote));
587             uint8_t midi_note = static_cast<uint8_t>(note+69);
588             uint8_t vel = static_cast<uint8_t>(((fnote - note) * 127) +63);
589 
590             msend_midi_cc(0x90, midi_note,vel, 3);
591         } else {
592             msend_midi_cc(0xB0, 123, 0, 3);
593         }
594     }
595 #endif
596 }
597 
598 
599 // preset
setting_is_preset()600 bool GxMachine::setting_is_preset() {
601     return settings.setting_is_preset();
602 }
603 
604 
get_current_bank()605 const Glib::ustring& GxMachine::get_current_bank() {
606     return settings.get_current_bank();
607 }
608 
get_current_bank_file()609 gx_system::PresetFileGui *GxMachine::get_current_bank_file() {
610     return settings.get_current_bank_file()->get_guiwrapper();
611 }
612 
get_current_name()613 const Glib::ustring& GxMachine::get_current_name() {
614     return settings.get_current_name();
615 }
616 
get_bank_file(const Glib::ustring & bank) const617 gx_system::PresetFileGui* GxMachine::get_bank_file(const Glib::ustring& bank) const {
618     return settings.banks.get_file(bank)->get_guiwrapper();
619 }
620 
get_bank_name(int n)621 Glib::ustring GxMachine::get_bank_name(int n) {
622     return settings.banks.get_name(n);
623 }
624 
msend_midi_cc(int cc,int pgn,int bgn,int num)625 bool GxMachine::msend_midi_cc(int cc, int pgn, int bgn, int num) {
626 	return jack.send_midi_cc(cc, pgn, bgn, num);
627 }
628 
load_preset(gx_system::PresetFileGui * pf,const Glib::ustring & name)629 void GxMachine::load_preset(gx_system::PresetFileGui *pf, const Glib::ustring& name) {
630     int n = get_bank_index(get_current_bank());
631     settings.load_preset(pf, name);
632 #ifdef USE_MIDI_CC_OUT
633     bool cc_ok = true;
634     if (get_bank_index(pf->get_name()) != n) {
635         cc_ok = msend_midi_cc(0xB0, 32, get_bank_index(pf->get_name()),3);
636     }
637     if (cc_ok) { // don't send program change if bank switch failed
638         msend_midi_cc(0xC0, pf->get_index(name),0,2);
639     }
640 #endif
641 }
642 
loadstate()643 void GxMachine::loadstate() {
644     settings.loadstate();
645 }
646 
bank_size()647 int GxMachine::bank_size() {
648     return settings.banks.size();
649 }
650 
get_bank_index(const Glib::ustring & bank)651 int GxMachine::get_bank_index(const Glib::ustring& bank) {
652     return settings.banks.get_index(bank);
653 }
654 
create_default_scratch_preset()655 void GxMachine::create_default_scratch_preset() {
656     settings.create_default_scratch_preset();
657 }
658 
set_statefilename(const std::string & fn)659 void GxMachine::set_statefilename(const std::string& fn) {
660     settings.set_statefilename(fn);
661 }
662 
save_to_state(bool preserve_preset)663 void GxMachine::save_to_state(bool preserve_preset) {
664     settings.save_to_state(preserve_preset);
665 }
666 
plugin_preset_list_load(const PluginDef * pdef,gx_preset::UnitPresetList & presetnames)667 void GxMachine::plugin_preset_list_load(const PluginDef *pdef, gx_preset::UnitPresetList &presetnames) {
668     settings.plugin_preset_list_load(pdef, presetnames);
669 }
670 
plugin_preset_list_set(const PluginDef * pdef,bool factory,const Glib::ustring & name)671 void GxMachine::plugin_preset_list_set(const PluginDef *pdef, bool factory, const Glib::ustring& name) {
672     settings.plugin_preset_list_set(pdef, factory, name);
673 }
674 
plugin_preset_list_sync_set(const PluginDef * pdef,bool factory,const Glib::ustring & name)675 void GxMachine::plugin_preset_list_sync_set(const PluginDef *pdef, bool factory, const Glib::ustring& name) {
676     settings.plugin_preset_list_sync_set(pdef, factory, name);
677 }
678 
plugin_preset_list_set_on_idle(const PluginDef * pdef,bool factory,const Glib::ustring & name)679 void GxMachine::plugin_preset_list_set_on_idle(const PluginDef *pdef, bool factory, const Glib::ustring& name) {
680     Glib::signal_idle().connect_once(
681       sigc::bind(sigc::bind(sigc::bind(sigc::mem_fun(this, &GxMachine::plugin_preset_list_sync_set),name),factory),pdef));
682 
683 }
684 
plugin_preset_list_save(const PluginDef * pdef,const Glib::ustring & name)685 void GxMachine::plugin_preset_list_save(const PluginDef *pdef, const Glib::ustring& name) {
686     settings.plugin_preset_list_save(pdef, name);
687 }
688 
plugin_preset_list_remove(const PluginDef * pdef,const Glib::ustring & name)689 void GxMachine::plugin_preset_list_remove(const PluginDef *pdef, const Glib::ustring& name) {
690     settings.plugin_preset_list_remove(pdef, name);
691 }
692 
disable_autosave(bool v)693 void GxMachine::disable_autosave(bool v) {
694     settings.disable_autosave(v);
695 }
696 
signal_selection_changed()697 sigc::signal<void>& GxMachine::signal_selection_changed() {
698     return settings.signal_selection_changed();
699 }
700 
signal_presetlist_changed()701 sigc::signal<void>& GxMachine::signal_presetlist_changed() {
702     return settings.signal_presetlist_changed();
703 }
704 
bank_insert_uri(const Glib::ustring & uri,bool move,int position)705 gx_system::PresetFileGui* GxMachine::bank_insert_uri(const Glib::ustring& uri, bool move, int position) {
706     gx_system::PresetFile *f = settings.bank_insert_uri(uri, move, position);
707     if (f) {
708 	return f->get_guiwrapper();
709     } else {
710 	return 0;
711     }
712 }
713 
bank_insert_new(const Glib::ustring & name)714 gx_system::PresetFileGui *GxMachine::bank_insert_new(const Glib::ustring& name) {
715     gx_system::PresetFile *f = settings.bank_insert_new(name);
716     if (f) {
717 	return f->get_guiwrapper();
718     } else {
719 	return 0;
720     }
721 }
722 
rename_bank(const Glib::ustring & oldname,Glib::ustring & newname)723 bool GxMachine::rename_bank(const Glib::ustring& oldname, Glib::ustring& newname) {
724     return settings.rename_bank(oldname, newname);
725 }
726 
rename_preset(gx_system::PresetFileGui & pf,const Glib::ustring & oldname,const Glib::ustring & newname)727 bool GxMachine::rename_preset(gx_system::PresetFileGui& pf, const Glib::ustring& oldname, const Glib::ustring& newname) {
728     return settings.rename_preset(pf, oldname, newname);
729 }
730 
bank_reorder(const std::vector<Glib::ustring> & neworder)731 void GxMachine::bank_reorder(const std::vector<Glib::ustring>& neworder) {
732     settings.banks.reorder(neworder);
733 }
734 
reorder_preset(gx_system::PresetFileGui & pf,const std::vector<Glib::ustring> & neworder)735 void GxMachine::reorder_preset(gx_system::PresetFileGui& pf, const std::vector<Glib::ustring>& neworder) {
736     settings.reorder_preset(pf, neworder);
737 }
738 
bank_check_reparse()739 bool GxMachine::bank_check_reparse() {
740     return settings.banks.check_reparse();
741 }
742 
erase_preset(gx_system::PresetFileGui & pf,const Glib::ustring & name)743 void GxMachine::erase_preset(gx_system::PresetFileGui& pf, const Glib::ustring& name) {
744     settings.erase_preset(pf, name);
745 }
746 
bank_set_flag(gx_system::PresetFileGui * pf,int flag,bool v)747 void GxMachine::bank_set_flag(gx_system::PresetFileGui *pf, int flag, bool v) {
748     static_cast<gx_system::PresetFile*>(pf)->set_flag(flag, v);
749     settings.banks.save();
750     signal_presetlist_changed()();
751 }
752 
bank_get_filename(const Glib::ustring & bank)753 std::string GxMachine::bank_get_filename(const Glib::ustring& bank) {
754     return settings.banks.get_file(bank)->get_filename();
755 }
756 
bank_drag_begin()757 void GxMachine::bank_drag_begin() {
758 }
759 
bank_get_file(const Glib::ustring & bank) const760 gx_system::PresetFileGui *GxMachine::bank_get_file(const Glib::ustring& bank) const {
761     return settings.banks.get_file(bank)->get_guiwrapper();
762 }
763 
bank_begin()764 bank_iterator GxMachine::bank_begin() {
765     return bank_iterator(settings.banks.begin());
766 }
767 
bank_end()768 bank_iterator GxMachine::bank_end() {
769     return bank_iterator(settings.banks.end());
770 }
771 
pf_append(gx_system::PresetFileGui & pf,const Glib::ustring & src,gx_system::PresetFileGui & pftgt,const Glib::ustring & name)772 void GxMachine::pf_append(gx_system::PresetFileGui& pf, const Glib::ustring& src, gx_system::PresetFileGui& pftgt, const Glib::ustring& name) {
773     settings.append(pf, src, pftgt, name);
774 }
775 
pf_insert_before(gx_system::PresetFileGui & pf,const Glib::ustring & src,gx_system::PresetFileGui & pftgt,const Glib::ustring & pos,const Glib::ustring & name)776 void GxMachine::pf_insert_before(gx_system::PresetFileGui& pf, const Glib::ustring& src, gx_system::PresetFileGui& pftgt, const Glib::ustring& pos, const Glib::ustring& name) {
777     settings.insert_before(pf, src, pftgt, pos, name);
778 }
779 
pf_insert_after(gx_system::PresetFileGui & pf,const Glib::ustring & src,gx_system::PresetFileGui & pftgt,const Glib::ustring & pos,const Glib::ustring & name)780 void GxMachine::pf_insert_after(gx_system::PresetFileGui& pf, const Glib::ustring& src, gx_system::PresetFileGui& pftgt, const Glib::ustring& pos, const Glib::ustring& name) {
781     settings.insert_after(pf, src, pftgt, pos, name);
782 }
783 
convert_preset(gx_system::PresetFileGui & pf)784 bool GxMachine::convert_preset(gx_system::PresetFileGui& pf) {
785     return settings.convert_preset(pf);
786 }
787 
bank_remove(const Glib::ustring & bank)788 bool GxMachine::bank_remove(const Glib::ustring& bank) {
789     return settings.remove_bank(bank);
790 }
791 
bank_save()792 void GxMachine::bank_save() {
793     settings.banks.save();
794 }
795 
pf_save(gx_system::PresetFileGui & pf,const Glib::ustring & name)796 void GxMachine::pf_save(gx_system::PresetFileGui& pf, const Glib::ustring& name) {
797     settings.save(pf, name);
798 }
799 
800 
801 // jack
get_jack()802 gx_jack::GxJack *GxMachine::get_jack() {
803     return &jack;
804 }
805 
set_jack_insert(bool v)806 void GxMachine::set_jack_insert(bool v) {
807     return jack.set_jack_insert(v);
808 }
809 
810 // pmap
get_parameter(const char * p)811 Parameter& GxMachine::get_parameter(const char *p) {
812     return pmap[p];
813 }
814 
get_parameter(const std::string & id)815 Parameter& GxMachine::get_parameter(const std::string& id) {
816     return pmap[id];
817 }
818 
set_init_values()819 void GxMachine::set_init_values() {
820     pmap.set_init_values();
821 }
822 
update_parameter()823 bool GxMachine::update_parameter() {
824     for (output_listen_map::const_iterator i = update_map.cbegin(); i != update_map.cend(); ++i) {
825 	Parameter& p = pmap[i->first];
826 	if (p.isMaxlevel()) {
827 	    float*f = p.getFloat().value;
828 	    if (sock) {
829 		*f = sock->update_maxlevel(i->first, true);
830 		}
831 	    p.trigger_changed();
832 	    *f = 0.0;
833 	} else {
834 	    p.trigger_changed();
835 	}
836     }
837     return true;
838 }
839 
parameter_hasId(const char * p)840 bool GxMachine::parameter_hasId(const char *p) {
841     return pmap.hasId(p);
842 }
843 
parameter_hasId(const std::string & id)844 bool GxMachine::parameter_hasId(const std::string& id) {
845     return pmap.hasId(id);
846 }
847 
reset_unit(const PluginDef * pdef) const848 void GxMachine::reset_unit(const PluginDef *pdef) const {
849     pmap.reset_unit(pdef);
850 }
851 
parameter_unit_has_std_values(const PluginDef * pdef) const852 bool GxMachine::parameter_unit_has_std_values(const PluginDef *pdef) const {
853     return pmap.unit_has_std_values(pdef);
854 }
855 
set_parameter_value(const std::string & id,int value)856 void GxMachine::set_parameter_value(const std::string& id, int value) {
857 #ifdef USE_MIDI_CC_OUT
858     if (options.system_midiout) {
859         const gx_engine::MidiController *pctrl;
860         IntParameter& p = get_parameter(id).getInt();
861         if (p.get_value() != value) {
862             int nctl = midi_param2controller(p, &pctrl);
863             if (nctl > -1 && nctl < 128) {
864                 int state = int(((float(value) - p.getLowerAsFloat()) /
865                     (p.getUpperAsFloat() - p.getLowerAsFloat())) * 127.0);
866                 msend_midi_cc(0xB0, nctl, state, 3);
867                 if (pctrl->toggle_behaviour() != Parameter::toggle_type::OnOff) {
868                     engine.controller_map.set_last_midi_control_value(nctl, state);
869                 } else {
870                     engine.controller_map.set_last_midi_control_value(nctl, p.get_value()*127);
871                 }
872             }
873         }
874     }
875 #endif
876     pmap[id].getInt().set(value);
877 }
878 
set_parameter_value(const std::string & id,bool value)879 void GxMachine::set_parameter_value(const std::string& id, bool value) {
880 #ifdef USE_MIDI_CC_OUT
881     if (options.system_midiout) {
882         const gx_engine::MidiController *pctrl;
883         BoolParameter& p = get_parameter(id).getBool();
884         if (p.get_value() != value) {
885             int nctl = midi_param2controller(p, &pctrl);
886             if (nctl > -1 && nctl < 128) {
887                 int state = int(value * 127);
888                 msend_midi_cc(0xB0, nctl,state, 3);
889                 if (pctrl->toggle_behaviour() != Parameter::toggle_type::OnOff) {
890                     engine.controller_map.set_last_midi_control_value(nctl, state);
891                 } else {
892                     engine.controller_map.set_last_midi_control_value(nctl, p.get_value()*127);
893                 }
894             }
895         }
896     }
897 #endif
898     pmap[id].getBool().set(value);
899 }
900 
set_parameter_value(const std::string & id,float value)901 void GxMachine::set_parameter_value(const std::string& id, float value) {
902 #ifdef USE_MIDI_CC_OUT
903     if (options.system_midiout) {
904         const gx_engine::MidiController *pctrl;
905         FloatParameter& p = get_parameter(id).getFloat();
906         if ( std::fabs(p.get_value() - value) > 0.00001) {
907             int nctl = midi_param2controller(p, &pctrl);
908             if (nctl > -1 && nctl < 128) {
909                 int state = int(((float(value) - p.getLowerAsFloat()) /
910                     (p.getUpperAsFloat() - p.getLowerAsFloat())) * 127.0);
911                 msend_midi_cc(0xB0, nctl, state, 3);
912                // if (pctrl->toggle_behaviour() != Parameter::toggle_type::OnOff) {
913                //     engine.controller_map.set_last_midi_control_value(nctl, state);
914                // } else {
915                //      engine.controller_map.set_last_midi_control_value(nctl, p.get_value()*127);
916                // }
917             }
918         }
919     }
920 #endif
921     pmap[id].getFloat().set(value);
922 }
923 
set_parameter_value(const std::string & id,const std::string & value)924 void GxMachine::set_parameter_value(const std::string& id, const std::string& value) {
925     pmap[id].getString().set(value);
926 }
927 
_get_parameter_value_int(const std::string & id)928 int GxMachine::_get_parameter_value_int(const std::string& id) {
929     return pmap[id].getInt().get_value();
930 }
931 
_get_parameter_value_bool(const std::string & id)932 int GxMachine::_get_parameter_value_bool(const std::string& id) {
933     return pmap[id].getBool().get_value();
934 }
935 
_get_parameter_value_float(const std::string & id)936 float GxMachine::_get_parameter_value_float(const std::string& id) {
937     return pmap[id].getFloat().get_value();
938 }
939 
_get_parameter_value_string(const std::string & id)940 std::string GxMachine::_get_parameter_value_string(const std::string& id) {
941     return pmap[id].getString().get_value();
942 }
943 
_signal_parameter_value_int(const std::string & id)944 sigc::signal<void, int>& GxMachine::_signal_parameter_value_int(const std::string& id) {
945     return pmap[id].signal_changed_int();
946 }
947 
_signal_parameter_value_bool(const std::string & id)948 sigc::signal<void, bool>& GxMachine::_signal_parameter_value_bool(const std::string& id) {
949     return pmap[id].signal_changed_bool();
950 }
951 
_signal_parameter_value_float(const std::string & id)952 sigc::signal<void, float>& GxMachine::_signal_parameter_value_float(const std::string& id) {
953     return pmap[id].signal_changed_float();
954 }
955 
956 // MidiControllerList
midi_get_config_mode(int * ctl)957 bool GxMachine::midi_get_config_mode(int *ctl) {
958     if (engine.controller_map.get_config_mode()) {
959 	*ctl = engine.controller_map.get_current_control();
960 	return true;
961     }
962     return false;
963 }
964 
midi_set_config_mode(bool v,int ctl)965 void GxMachine::midi_set_config_mode(bool v, int ctl) {
966     engine.controller_map.set_config_mode(v, ctl);
967 }
968 
signal_midi_changed()969 sigc::signal<void>& GxMachine::signal_midi_changed() {
970     return engine.controller_map.signal_changed();
971 }
972 
signal_midi_value_changed()973 sigc::signal<void, int, int>& GxMachine::signal_midi_value_changed() {
974     return engine.controller_map.signal_midi_value_changed();
975 }
976 
request_midi_value_update()977 void GxMachine::request_midi_value_update() {
978     engine.controller_map.request_midi_value_update();
979 }
980 
midi_size()981 int GxMachine::midi_size() {
982     return engine.controller_map.size();
983 }
984 
midi_get(int n)985 midi_controller_list& GxMachine::midi_get(int n) {
986     return engine.controller_map[n];
987 }
988 
midi_deleteParameter(Parameter & param)989 void GxMachine::midi_deleteParameter(Parameter& param) {
990     engine.controller_map.deleteParameter(param);
991 }
992 
midi_set_current_control(int v)993 void GxMachine::midi_set_current_control(int v) {
994     engine.controller_map.set_current_control(v);
995 }
996 
midi_modifyCurrent(Parameter & param,float lower,float upper,bool toggle,int toggle_behaviour)997 void GxMachine::midi_modifyCurrent(Parameter& param, float lower, float upper,
998                                    bool toggle, int toggle_behaviour) {
999     engine.controller_map.modifyCurrent(param, lower, upper, toggle, toggle_behaviour);
1000 }
1001 
midi_param2controller(Parameter & param,const MidiController ** p)1002 int GxMachine::midi_param2controller(Parameter& param, const MidiController** p) {
1003     return engine.controller_map.param2controller(param, p);
1004 }
1005 
set_midi_channel(int s)1006 void GxMachine::set_midi_channel(int s) {
1007     return engine.controller_map.set_midi_channel(s);
1008 }
1009 
midi_feedback(int c,int v)1010 void GxMachine::midi_feedback(int c, int v) {
1011 #ifdef USE_MIDI_CC_OUT
1012     if (options.system_midiout) {
1013         // Don't send midi feedback for bpm / jack_transport and not on/off events
1014         if ( c !=22 && c != 24 && c < 128) {
1015             msend_midi_cc(0xB0, c,v, 3);
1016         }
1017     }
1018 #endif
1019 }
1020 
get_midi_feedback()1021 bool GxMachine::get_midi_feedback() {
1022     return options.system_midiout;
1023 }
1024 
set_midi_feedback(int v)1025 void GxMachine::set_midi_feedback(int v) {
1026     options.system_midiout = v;
1027 }
1028 
1029 // Convolver
1030 
on_impresp(const std::string & path)1031 void GxMachine::on_impresp(const std::string& path) {
1032     gx_system::IRFileListing l(path);
1033     impresp_list(path, l.get_listing());
1034 }
1035 
reload_impresp_list(const std::string & path)1036 void GxMachine::reload_impresp_list(const std::string& path) {
1037     Glib::signal_idle().connect_once(
1038 	sigc::bind(
1039 	    sigc::mem_fun(this, &GxMachine::on_impresp), path));
1040 }
1041 
load_impresp_dirs(std::vector<gx_system::FileName> & dirs)1042 void GxMachine::load_impresp_dirs(std::vector<gx_system::FileName>& dirs) {
1043     assert(false);
1044 }
1045 
read_audio(const std::string & filename,unsigned int * audio_size,int * audio_chan,int * audio_type,int * audio_form,int * audio_rate,float ** buffer)1046 bool GxMachine::read_audio(const std::string& filename, unsigned int *audio_size, int *audio_chan,
1047 			   int *audio_type, int *audio_form, int *audio_rate, float **buffer) {
1048     return gx_engine::read_audio(filename, audio_size, audio_chan, audio_type, audio_form, audio_rate, buffer);
1049 }
1050 
1051 
1052 /****************************************************************
1053  ** GxMachineRemote
1054  */
1055 
1056 #ifdef NDEBUG
1057 #define START_NOTIFY(m)  { start_call(RPNM_##m)
1058 #else
1059 #define START_NOTIFY(m)  { const jsonrpc_method_def& _md = start_call(RPNM_##m)
1060 #endif
1061 
1062 #define SEND()           assert(!_md.has_result); send(); }
1063 
1064 #define START_CALL(m)    { const jsonrpc_method_def& _md = start_call(RPCM_##m)
1065 
1066 #define START_RECEIVE(s) assert(_md.has_result); send(); { \
1067                            gx_system::JsonStringParser *jp = receive();\
1068                            if (!jp) { return s; }\
1069 			   try {
1070 
1071 #define END_RECEIVE(s)     } catch (const gx_system::JsonException& e) { report_rpc_error(jp, e, _md.name); } \
1072 			 delete jp; s; }}
1073 
1074 
GxMachineRemote(gx_system::CmdlineOptions & options_)1075 GxMachineRemote::GxMachineRemote(gx_system::CmdlineOptions& options_)
1076     : GxMachineBase(),
1077       options(options_),
1078       pmap(),
1079       pluginlist(),
1080       banks(),
1081       engine_state_change(),
1082       selection_changed(),
1083       presetlist_changed(),
1084       socket(),
1085       writebuf(),
1086       os(),
1087       jw(0),
1088       notify_list(),
1089       idle_conn(),
1090       rack_units(),
1091       midi_changed(),
1092       midi_value_changed(),
1093       current_bank(),
1094       current_preset(),
1095       bank_drag_get_counter(),
1096       bank_drag_get_path(),
1097       tuner_switcher_display(),
1098       tuner_switcher_set_state(),
1099       tuner_switcher_selection_done() {
1100     if (options.get_rpcaddress().compare(0, 3, "BT:") == 0) {
1101 	create_bluetooth_socket(options.get_rpcaddress().substr(3));
1102     } else {
1103 	create_tcp_socket();
1104     }
1105     socket->set_blocking(true);
1106     //writebuf = new __gnu_cxx::stdio_filebuf<char>(socket->get_fd(), std::ios::out);
1107     writebuf = new  boost::iostreams::file_descriptor_sink;
1108     writebuf->open(socket->get_fd(),boost::iostreams::never_close_handle);
1109 
1110     // os = new ostream(writebuf);
1111     os = new boost::iostreams::stream<boost::iostreams::file_descriptor_sink>(*writebuf);
1112 
1113     jw = new gx_system::JsonWriter(os, false);
1114 
1115     START_CALL(parameterlist);
1116     START_RECEIVE();
1117     pmap.readJSON(*jp);
1118     END_RECEIVE();
1119     current_bank = pmap["system.current_bank"].getString().get_value();
1120     current_preset = pmap["system.current_preset"].getString().get_value();
1121     START_CALL(pluginlist);
1122     START_RECEIVE();
1123     pluginlist.readJSON(*jp, pmap);
1124     END_RECEIVE();
1125     START_CALL(banks);
1126     START_RECEIVE();
1127     banks.readJSON_remote(*jp);
1128     END_RECEIVE();
1129     START_CALL(get_midi_controller_map);
1130     START_RECEIVE();
1131     midi_controller_map.readJSON(*jp, pmap);
1132     END_RECEIVE();
1133     START_NOTIFY(listen);
1134     jw->write("preset");
1135     jw->write("state");
1136     //we don't need "freq"
1137     jw->write("display");
1138     jw->write("tuner");
1139     jw->write("presetlist_changed");
1140     jw->write("logger");
1141     jw->write("midi");
1142     jw->write("param");
1143     jw->write("plugins_changed");
1144     jw->write("misc");
1145     jw->write("units_changed");
1146     SEND();
1147 }
1148 
~GxMachineRemote()1149 GxMachineRemote::~GxMachineRemote() {
1150     jw->close();
1151     delete jw;
1152     writebuf->close();
1153     delete os;
1154     delete writebuf;
1155 }
1156 
1157 #ifdef NDEBUG
debug_trace_param(Parameter * p)1158 inline void debug_trace_param(Parameter *p) {}
1159 #else
debug_trace_param(Parameter * p)1160 inline void debug_trace_param(Parameter *p) {
1161     const char *q = getenv("GUITARIX_TRACE");
1162     if (!q) {
1163 	return;
1164     }
1165     if (*q && q != p->id()) {
1166 	return;
1167     }
1168     cerr << "set " << p->id() << " = ";
1169     if (p->isInt()) {
1170 	cerr << p->getInt().get_value();
1171     } else if (p->isBool()) {
1172 	cerr << p->getBool().get_value();
1173     } else if (p->isFloat()) {
1174 	cerr << p->getFloat().get_value();
1175     } else if (p->isString()) {
1176 	cerr << p->getString().get_value();
1177     } else if (dynamic_cast<JConvParameter*>(p) != 0) {
1178 	cerr << dynamic_cast<JConvParameter*>(p)->get_value().getFullIRPath();
1179     } else if (dynamic_cast<SeqParameter*>(p) != 0) {
1180 	cerr << "SeqParameter";
1181     } else {
1182 	assert(false);
1183     }
1184     if (p->get_blocked()) {
1185 	cerr << " (blocked)";
1186     }
1187     cerr << endl;
1188 }
1189 #endif
1190 
1191 #if HAVE_BLUEZ
create_bluetooth_socket(const Glib::ustring & bdaddr)1192 void GxMachineRemote::create_bluetooth_socket(const Glib::ustring& bdaddr) {
1193     struct sockaddr_rc addr = { 0 };
1194     addr.rc_family = AF_BLUETOOTH;
1195     str2ba(bdaddr.c_str(), &addr.rc_bdaddr);
1196     int error = EBUSY;
1197     for (int channel = 1; channel <= 9; channel++) {
1198 	addr.rc_channel = (uint8_t)channel;
1199 	int s = ::socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
1200 	if (connect(s, (const struct sockaddr *)&addr, sizeof(addr)) < 0) {
1201 	    error = errno;
1202 	    close(s);
1203 	    if (error != EBUSY) {
1204 		break;
1205 	    }
1206 	} else {
1207 	    socket = Gio::Socket::create_from_fd(s);
1208 	    return;
1209 	}
1210     }
1211     char buf[100];
1212     throw GxFatalError(
1213 	Glib::ustring::compose(
1214 	    _("Remote Connection: cannot connect to bluetooth %1: %2"),
1215 	    bdaddr, strerror_r(error, buf, sizeof(buf))));
1216 }
1217 #else // !HAVE_BLUEZ
create_bluetooth_socket(const Glib::ustring & bdaddr)1218 void GxMachineRemote::create_bluetooth_socket(const Glib::ustring& bdaddr) {
1219     gx_print_fatal(
1220 	_("frontend"),
1221 	_("Bluetooth not available; rebuild Guitarix with Bluetooth support"));
1222 }
1223 #endif // HAVE_BLUEZ
1224 
create_tcp_socket()1225 void GxMachineRemote::create_tcp_socket() {
1226     socket = Gio::Socket::create(Gio::SOCKET_FAMILY_IPV4, Gio::SOCKET_TYPE_STREAM, Gio::SOCKET_PROTOCOL_TCP);
1227     int flag = 1;
1228     if (setsockopt(socket->get_fd(), IPPROTO_TCP, TCP_NODELAY, &flag, sizeof(int)))
1229         gx_print_error("GxMachineRemote","setsockopt(IPPROTO_TCP, TCP_NODELAY) failed");
1230     typedef std::vector< Glib::RefPtr<Gio::InetAddress> > adr_list;
1231     adr_list al;
1232     try {
1233 	al = Gio::Resolver::get_default()->lookup_by_name(options.get_rpcaddress());
1234     } catch (Glib::Error& e) {
1235 	gx_print_fatal(_("Remote Connection"), e.what());
1236     }
1237     Glib::ustring msg;
1238     bool error = true;
1239     for (adr_list::iterator i = al.begin(); i != al.end(); ++i) {
1240 	try {
1241 	    socket->connect(Gio::InetSocketAddress::create(*i, options.get_rpcport()));
1242 	    error = false;
1243 	} catch (Gio::Error& e) {
1244 	    msg = e.what();
1245 	    error = true;
1246 	}
1247     }
1248     if (error) {
1249 	gx_print_fatal(_("Remote Connection"), msg);
1250     }
1251 }
1252 
param_signal(Parameter * p)1253 void GxMachineRemote::param_signal(Parameter *p) {
1254     debug_trace_param(p);
1255     if (p->get_blocked()) {
1256 	return;
1257     }
1258     START_NOTIFY(set);
1259     jw->write(p->id());
1260     if (p->isInt()) {
1261 	jw->write(p->getInt().get_value());
1262     } else if (p->isBool()) {
1263 	jw->write(p->getBool().get_value());
1264     } else if (p->isFloat()) {
1265 	jw->write(p->getFloat().get_value());
1266     } else if (p->isString()) {
1267 	jw->write(p->getString().get_value());
1268     } else if (dynamic_cast<JConvParameter*>(p) != 0) {
1269 	dynamic_cast<JConvParameter*>(p)->get_value().writeJSON(*jw);
1270     } else if (dynamic_cast<SeqParameter*>(p) != 0) {
1271 	dynamic_cast<SeqParameter*>(p)->get_value().writeJSON(*jw);
1272     } else {
1273 	assert(false);
1274     }
1275     SEND();
1276 }
1277 
parameter_changed(gx_system::JsonStringParser * jp)1278 void GxMachineRemote::parameter_changed(gx_system::JsonStringParser *jp) {
1279     Parameter& p = pmap[jp->current_value()];
1280     p.set_blocked(true);
1281     if (p.isFloat()) {
1282 	float v;
1283 	switch (jp->next()) {
1284 	case gx_system::JsonParser::value_string:
1285 	    v = dynamic_cast<FloatEnumParameter*>(&p)->idx_from_id(jp->current_value());
1286 	    break;
1287 	case gx_system::JsonParser::value_number:
1288 	    v = jp->current_value_float();
1289 	    break;
1290 	default:
1291 	    assert(false);
1292 	    v = 0;
1293 	}
1294 	p.getFloat().set(v);
1295     } else if (p.isInt()) {
1296 	int v;
1297 	switch (jp->next()) {
1298 	case gx_system::JsonParser::value_string:
1299 	    v = p.getEnum().idx_from_id(jp->current_value());
1300 	    break;
1301 	case gx_system::JsonParser::value_number:
1302 	    v = jp->current_value_int();
1303 	    break;
1304 	default:
1305 	    assert(false);
1306 	    v = 0;
1307 	}
1308 	p.getInt().set(v);
1309     } else if (p.isBool()) {
1310 	jp->next(gx_system::JsonParser::value_number);
1311 	p.getBool().set(jp->current_value_int());
1312     } else if (p.isString()) {
1313 	jp->next(gx_system::JsonParser::value_string);
1314 	p.getString().set(jp->current_value());
1315     } else if (p.isFile()) {
1316 	cerr << "change file parameter " << p.id() << endl;
1317     } else if (dynamic_cast<JConvParameter*>(&p) != 0) {
1318 	JConvParameter* pj = dynamic_cast<JConvParameter*>(&p);
1319 	pj->readJSON_value(*jp);
1320 	pj->setJSON_value();
1321     } else if (dynamic_cast<SeqParameter*>(&p) != 0) {
1322 	SeqParameter* pj = dynamic_cast<SeqParameter*>(&p);
1323 	pj->readJSON_value(*jp);
1324 	pj->setJSON_value();
1325     } else if (dynamic_cast<OscParameter*>(&p) != 0) {
1326 	OscParameter* po = dynamic_cast<OscParameter*>(&p);
1327 	po->readJSON_value(*jp);
1328 	po->setJSON_value();
1329     } else {
1330 	cerr << "change special type parameter " << p.id() << endl;
1331     }
1332     p.set_blocked(false);
1333 }
1334 
handle_notify(gx_system::JsonStringParser * jp)1335 void GxMachineRemote::handle_notify(gx_system::JsonStringParser *jp) {
1336     jp->next(gx_system::JsonParser::value_string);
1337     std::string method = jp->current_value();
1338     jp->next(gx_system::JsonParser::value_key); // "params"
1339     jp->next(gx_system::JsonParser::begin_array);
1340     if (method == "state_changed") {
1341 	jp->next(gx_system::JsonParser::value_string);
1342 	engine_state_change(string_to_engine_state(jp->current_value()));
1343     } else if (method == "message") {
1344 	jp->next(gx_system::JsonParser::value_string);
1345 	GxLogger::MsgType msgtype = GxLogger::kError;
1346 	if (jp->current_value() == "info") {
1347 	    msgtype = GxLogger::kInfo;
1348 	} else if (jp->current_value() == "warning") {
1349 	    msgtype = GxLogger::kWarning;
1350 	}
1351 	jp->next(gx_system::JsonParser::value_string);
1352 	GxLogger::get_logger().print(jp->current_value(), msgtype);
1353     } else if (method == "preset_changed") {
1354 	jp->next();
1355 	Glib::ustring new_bank = jp->current_value();
1356 	jp->next(gx_system::JsonParser::value_string);
1357 	Glib::ustring new_preset = jp->current_value();
1358 	jp->next(gx_system::JsonParser::end_array);
1359 	current_bank = new_bank;
1360 	current_preset = new_preset;
1361 	selection_changed();
1362     } else if (method == "presetlist_changed") {
1363 	START_CALL(banks);
1364 	START_RECEIVE();
1365 	banks.readJSON_remote(*jp);
1366 	END_RECEIVE();
1367 	presetlist_changed();
1368     } else if (method == "set") {
1369 	while (jp->peek() != gx_system::JsonParser::end_array) {
1370 	    jp->next(gx_system::JsonParser::value_string);
1371 	    parameter_changed(jp);
1372 	}
1373     } else if (method == "rack_units_changed") {
1374 	jp->next(gx_system::JsonParser::begin_array);
1375 	jp->next(gx_system::JsonParser::value_number);
1376 	bool stereo = jp->current_value_int();
1377 	std::vector<std::string>& l = (stereo ? rack_units.stereo : rack_units.mono);
1378 	l.clear();
1379 	while (jp->peek() != gx_system::JsonParser::end_array) {
1380 	    jp->next(gx_system::JsonParser::value_string);
1381 	    l.push_back(jp->current_value());
1382 	}
1383 	jp->next(gx_system::JsonParser::end_array);
1384 	rack_units.rack_unit_order_changed(stereo);
1385     } else if (method == "midi_changed") {
1386 	midi_controller_map.readJSON(*jp, pmap);
1387 	midi_changed();
1388     } else if (method == "midi_value_changed") {
1389 	jp->next(gx_system::JsonParser::begin_array);
1390 	jp->next(gx_system::JsonParser::value_number);
1391 	int ctl = jp->current_value_int();
1392 	jp->next(gx_system::JsonParser::value_number);
1393 	int value = jp->current_value_int();
1394 	jp->next(gx_system::JsonParser::end_array);
1395 	midi_value_changed(ctl, value);
1396     } else if (method == "show_tuner") {
1397 	jp->next(gx_system::JsonParser::value_number);
1398 	tuner_switcher_selection_done(jp->current_value_int());
1399     } else if (method == "set_display_state") {
1400 	jp->next(gx_system::JsonParser::value_string);
1401 	TunerSwitcher::SwitcherState state = TunerSwitcher::normal_mode;
1402 	if (jp->current_value() == "normal_mode") {
1403 	    state = TunerSwitcher::normal_mode;
1404 	} else if (jp->current_value() == "wait_start") {
1405 	    state = TunerSwitcher::wait_start;
1406 	} else if (jp->current_value() == "listening") {
1407 	    state = TunerSwitcher::listening;
1408 	} else if (jp->current_value() == "wait_stop") {
1409 	    state = TunerSwitcher::wait_stop;
1410 	} else {
1411 	    assert(false);
1412 	}
1413 	tuner_switcher_set_state(state);
1414     } else if (method == "display_bank_preset") {
1415 	jp->next(gx_system::JsonParser::value_string);
1416 	Glib::ustring bank = jp->current_value();
1417 	jp->next(gx_system::JsonParser::value_string);
1418 	tuner_switcher_display(bank, jp->current_value());
1419     } else if (method == "impresp_list") {
1420 	std::vector<gx_system::FileName> l;
1421 	jp->next(gx_system::JsonParser::value_string);
1422 	std::string path = jp->current_value();
1423 	while (jp->peek() == gx_system::JsonParser::begin_array) {
1424 	    jp->next(gx_system::JsonParser::begin_array);
1425 	    jp->next(gx_system::JsonParser::value_string);
1426 	    std::string filename = jp->current_value();
1427 	    jp->next(gx_system::JsonParser::value_string);
1428 	    l.push_back(gx_system::FileName(filename, jp->current_value()));
1429 	    jp->next(gx_system::JsonParser::end_array);
1430 	}
1431 	impresp_list(path, l);
1432     } else if (method == "plugins_changed") {
1433 	update_plugins(jp);
1434     } else if (method == "server_shutdown") {
1435 	Gtk::Main::quit();
1436     } else {
1437 	cerr << "> " << jp->get_string() << endl;
1438     }
1439 }
1440 
socket_get_available_bytes(const Glib::RefPtr<Gio::Socket> & socket)1441 static int socket_get_available_bytes(const Glib::RefPtr<Gio::Socket>& socket) {
1442     // return socket->get_available_bytes();  // Glib 2.32
1443     int avail;
1444     ioctl(socket->get_fd(), FIONREAD, &avail);
1445     int ret = ioctl(socket->get_fd(), FIONREAD, &avail);
1446     if (ret != 0) {
1447 	return -1;
1448     }
1449     return avail;
1450 }
1451 
socket_input_handler(Glib::IOCondition cond)1452 bool GxMachineRemote::socket_input_handler(Glib::IOCondition cond) {
1453     if (cond & (Glib::IO_HUP|Glib::IO_ERR|Glib::IO_NVAL)) {
1454 	socket_error(0);
1455 	return false;
1456     }
1457     int n = socket_get_available_bytes(socket);
1458     if (n == 0) {
1459 	return true;
1460     } else if (n < 0) {
1461 	socket_error(1);
1462     }
1463     char buf[10000];
1464     gx_system::JsonStringParser *jp = new gx_system::JsonStringParser;
1465     while (true) {
1466 	try {
1467 	    n = socket->receive(buf, sizeof(buf));
1468 	} catch(Glib::Error& e) {
1469 	    delete jp;
1470 	    socket_error(2);
1471 	    return false;
1472 	}
1473 	if (n <= 0) {
1474 	    delete jp;
1475 	    socket_error(3);
1476 	    return false;
1477 	}
1478 	char *p = buf;
1479 	while (n-- > 0) {
1480 	    jp->put(*p);
1481 	    if (*p == '\n') {
1482 		jp->start_parser();
1483 		try {
1484 		    jp->next(gx_system::JsonParser::begin_object);
1485 		    jp->next(gx_system::JsonParser::value_key); // "jsonrpc"
1486 		    jp->next(gx_system::JsonParser::value_string); // "2.0"
1487 		    jp->next(gx_system::JsonParser::value_key); // "method"
1488 		    handle_notify(jp);
1489 		} catch (gx_system::JsonException& e) {
1490 		    cerr << "JsonException: " << e.what() << ": '" << jp->get_string() << "'" << endl;
1491 		    assert(false);
1492 		}
1493 		if (n == 0) {
1494 		    int avail = socket_get_available_bytes(socket);
1495 		    if (avail == 0) {
1496 			delete jp;
1497 			return true;
1498 		    } else if (avail < 0) {
1499 			socket_error(4);
1500 		    }
1501 		}
1502 		delete jp;
1503 		jp = new gx_system::JsonStringParser;
1504 	    }
1505 	    p++;
1506 	}
1507     }
1508 }
1509 
start_call(jsonrpc_method m)1510 const jsonrpc_method_def& GxMachineRemote::start_call(jsonrpc_method m) {
1511     const jsonrpc_method_def& md = jsonrpc_method_list[m];
1512     jw->begin_object();
1513     jw->write_kv("jsonrpc", "2.0");
1514     if (md.has_result) {
1515 	jw->write_kv("id", "1");
1516     }
1517     jw->write_kv("method", md.name);
1518     jw->write_key("params");
1519     jw->begin_array();
1520     return md;
1521 }
1522 
send()1523 void GxMachineRemote::send() {
1524     jw->end_array();
1525     jw->end_object();
1526     *os << endl;
1527     if (os->fail()) {
1528 	socket_error(5);
1529     }
1530     jw->reset();
1531 }
1532 
report_rpc_error(gx_system::JsonStringParser * jp,const gx_system::JsonException & e,const char * method)1533 void GxMachineRemote::report_rpc_error(gx_system::JsonStringParser *jp, const gx_system::JsonException& e, const char *method) {
1534     if (method) {
1535 	cerr << "RPC Error in " << method << "(): ";
1536     } else {
1537 	cerr << "RPC Error: ";
1538     }
1539     cerr << e.what() << ": '" << jp->get_string() << "'" << endl;
1540     assert(false);
1541 }
1542 
idle_notify_handler()1543 bool GxMachineRemote::idle_notify_handler() {
1544     for (unsigned int i = 0; i < notify_list.size(); ++i) {
1545 	gx_system::JsonStringParser *jp = notify_list[i];
1546 	handle_notify(jp);
1547 	delete jp;
1548     }
1549     notify_list.clear();
1550     return false;
1551 }
1552 
add_idle_handler()1553 void GxMachineRemote::add_idle_handler() {
1554     if (!idle_conn.connected()) {
1555 	idle_conn = Glib::signal_idle().connect(
1556 	    sigc::mem_fun(this, &GxMachineRemote::idle_notify_handler));
1557     }
1558 }
1559 
throw_error(gx_system::JsonStringParser * jp)1560 void GxMachineRemote::throw_error(gx_system::JsonStringParser *jp) {
1561     jp->next(gx_system::JsonParser::begin_object);
1562     int code = 0;
1563     Glib::ustring message;
1564     while (jp->peek() != gx_system::JsonParser::end_object) {
1565 	jp->next(gx_system::JsonParser::value_key);
1566 	if (jp->current_value() == "code") {
1567 	    jp->next(gx_system::JsonParser::value_number);
1568 	    code = jp->current_value_int();
1569 	} else if (jp->current_value() == "message") {
1570 	    jp->next(gx_system::JsonParser::value_string);
1571 	    message = jp->current_value();
1572 	}
1573     }
1574     jp->next(gx_system::JsonParser::end_object);
1575     cerr << jp->get_string() << std::flush;
1576     throw gx_system::JsonException(
1577 	Glib::ustring::compose("RPC error %1 : %2", code, message));
1578 }
1579 
socket_error(int loc)1580 void GxMachineRemote::socket_error(int loc) {
1581     if (!socket->is_closed()) {
1582 	socket->close();
1583     }
1584     gx_print_fatal("Network", Glib::ustring::compose("Server has closed connection (%1)", loc));
1585 }
1586 
receive()1587 gx_system::JsonStringParser *GxMachineRemote::receive() {
1588     char buf[10000];
1589     bool error = false;
1590     gx_system::JsonStringParser *jp_ret = 0;
1591     gx_system::JsonStringParser *jp = new gx_system::JsonStringParser;
1592     try {
1593 	while (true) {
1594 	    int n;
1595 	    try {
1596 		n = socket->receive(buf, sizeof(buf));
1597 	    } catch(Glib::Error& e) {
1598 		cerr << "Glib receive error: " << e.what() << endl;
1599 		return 0;
1600 	    }
1601 	    if (n <= 0) {
1602 		socket_error(6);
1603 		return 0;
1604 	    }
1605 	    char *p = buf;
1606 	    while (n-- > 0) {
1607 		jp->put(*p);
1608 		if (*p == '\n') {
1609 		    jp->start_parser();
1610 		    jp->next(gx_system::JsonParser::begin_object);
1611 		    jp->next(gx_system::JsonParser::value_key); // "jsonrpc"
1612 		    jp->next(gx_system::JsonParser::value_string); // "2.0"
1613 		    jp->next(gx_system::JsonParser::value_key);
1614 		    if (jp->current_value() == "id") {
1615 			jp->next(); // id or null
1616 			jp->next(gx_system::JsonParser::value_key);
1617 			if (jp->current_value() == "error") {
1618 			    error = true;
1619 			}
1620 			assert(jp_ret == 0);
1621 			jp_ret = jp;
1622 		    } else {
1623 			assert(jp->current_value() == "method");
1624 			notify_list.push_back(jp);
1625 			add_idle_handler();
1626 		    }
1627 		    if (n == 0 && jp_ret) {
1628 			if (error) {
1629 			    throw_error(jp_ret);
1630 			}
1631 			return jp_ret;
1632 		    }
1633 		    jp = new gx_system::JsonStringParser;
1634 		}
1635 		p++;
1636 	    }
1637 	}
1638     } catch (const gx_system::JsonException& e) {
1639 	report_rpc_error(jp, e);
1640 	delete jp;
1641 	return 0;
1642     }
1643 }
1644 
get_bool(gx_system::JsonStringParser * jp)1645 bool GxMachineRemote::get_bool(gx_system::JsonStringParser *jp) {
1646     jp->next(gx_system::JsonParser::value_number);
1647     return bool(jp->current_value_int());
1648 }
1649 
set_state(GxEngineState state)1650 void GxMachineRemote::set_state(GxEngineState state) {
1651     START_NOTIFY(setstate);
1652     jw->write(engine_state_to_string(state));
1653     SEND();
1654 }
1655 
get_state()1656 GxEngineState GxMachineRemote::get_state() {
1657     START_CALL(getstate);
1658     START_RECEIVE(gx_engine::kEngineOff);
1659     jp->next(gx_system::JsonParser::value_string);
1660     return string_to_engine_state(jp->current_value());
1661     END_RECEIVE(return gx_engine::kEngineOff);
1662 }
1663 
1664 
1665 /*
1666 ** LadspaLoader
1667 */
1668 
load_ladspalist(std::vector<std::string> & old_not_found,ladspa::LadspaPluginList & pluginlist)1669 void GxMachineRemote::load_ladspalist(std::vector<std::string>& old_not_found, ladspa::LadspaPluginList& pluginlist) {
1670     START_CALL(load_ladspalist);
1671     START_RECEIVE();
1672     jp->next(gx_system::JsonParser::begin_array);
1673     while (jp->peek() != gx_system::JsonParser::end_array) {
1674 	jp->next(gx_system::JsonParser::value_number);
1675 	old_not_found.push_back(jp->current_value());
1676     }
1677     jp->next(gx_system::JsonParser::end_array);
1678     pluginlist.readJSON(*jp);
1679     END_RECEIVE();
1680 }
1681 
save_ladspalist(ladspa::LadspaPluginList & pluginlist)1682 void GxMachineRemote::save_ladspalist(ladspa::LadspaPluginList& pluginlist) {
1683     START_NOTIFY(save_ladspalist);
1684     pluginlist.writeJSON(*jw);
1685     SEND();
1686 }
1687 
update_plugins(gx_system::JsonParser * jp)1688 void GxMachineRemote::update_plugins(gx_system::JsonParser *jp) {
1689     // deleted parameters
1690     jp->next(gx_system::JsonParser::begin_array);
1691     while (jp->peek() != gx_system::JsonParser::end_array) {
1692 	jp->next(gx_system::JsonParser::value_string);
1693 	pmap.unregister(jp->current_value());
1694     }
1695     jp->next(gx_system::JsonParser::end_array);
1696     // inserted parameters
1697     jp->next(gx_system::JsonParser::begin_array);
1698     pmap.set_replace_mode(true);
1699     while (jp->peek() != gx_system::JsonParser::end_array) {
1700 	pmap.readJSON_one(*jp);
1701     }
1702     pmap.set_replace_mode(false);
1703     jp->next(gx_system::JsonParser::end_array);
1704     // updated plugins
1705     jp->next(gx_system::JsonParser::begin_array);
1706     while (jp->peek() != gx_system::JsonParser::end_array) {
1707 	jp->next(gx_system::JsonParser::begin_array);
1708 	jp->next(gx_system::JsonParser::value_number);
1709 	PluginChange::pc c = static_cast<PluginChange::pc>(jp->current_value_int());
1710 	if (c == PluginChange::remove) {
1711 	    jp->next(gx_system::JsonParser::value_string);
1712 	    Plugin *p = pluginlist.lookup_plugin(jp->current_value());
1713 	    plugin_changed(p, c);
1714 	    pluginlist.delete_module(p);
1715 	} else {
1716 	    Plugin *p = new Plugin(*jp, pmap);
1717 	    if (c == PluginChange::add) {
1718 		pluginlist.insert_plugin(p);
1719 	    } else {
1720 		pluginlist.update_plugin(p);
1721 	    }
1722 	    plugin_changed(p, c);
1723 	}
1724 	jp->next(gx_system::JsonParser::end_array);
1725     }
1726     jp->next(gx_system::JsonParser::end_array);
1727     plugin_changed(0, PluginChange::update);
1728 }
1729 
commit_ladspa_changes()1730 void GxMachineRemote::commit_ladspa_changes() {
1731     START_CALL(ladspaloader_update_plugins);
1732     START_RECEIVE();
1733     jp->next(gx_system::JsonParser::begin_array);
1734     update_plugins(jp);
1735     jp->next(gx_system::JsonParser::end_array);
1736     END_RECEIVE();
1737 }
1738 
signal_plugin_changed()1739 sigc::signal<void,Plugin*,PluginChange::pc>& GxMachineRemote::signal_plugin_changed() {
1740     return plugin_changed;
1741 }
1742 
1743 
1744 /*
1745 ** PluginList
1746 */
1747 
pluginlist_lookup_plugin(const std::string & id) const1748 Plugin *GxMachineRemote::pluginlist_lookup_plugin(const std::string& id) const {
1749     return pluginlist.lookup_plugin(id);
1750 }
1751 
pluginlist_append_rack(UiBuilderBase & ui)1752 void GxMachineRemote::pluginlist_append_rack(UiBuilderBase& ui) {
1753     pluginlist.append_rack(ui);
1754 }
1755 
1756 /*
1757 // unused now,
1758 static const char *next_char_pointer(gx_system::JsonParser *jp) {
1759     switch (jp->next()) {
1760     case gx_system::JsonParser::value_string: return jp->current_value().c_str();
1761     case gx_system::JsonParser::value_null: return 0;
1762     default: jp->throw_unexpected(gx_system::JsonParser::value_string); return 0;
1763     }
1764 }
1765 */
1766 
next_string(gx_system::JsonParser * jp)1767 static const std::string next_string(gx_system::JsonParser *jp) {
1768     if (jp->next() != gx_system::JsonParser::value_string) {
1769 	jp->throw_unexpected(gx_system::JsonParser::value_string);
1770     }
1771     return jp->current_value();
1772 }
1773 
load_remote_ui(const UiBuilder & builder,int form)1774 int GxMachineRemote::load_remote_ui(const UiBuilder& builder, int form) {
1775     START_CALL(plugin_load_ui);
1776     jw->write(builder.plugin->id);
1777     jw->write(form);
1778     START_RECEIVE(-1);
1779     jp->next(gx_system::JsonParser::begin_array);
1780     while (jp->peek() != gx_system::JsonParser::end_array) {
1781 	jp->next(gx_system::JsonParser::begin_array);
1782 	jp->next(gx_system::JsonParser::value_string);
1783 	if (jp->current_value() == "openTabBox") {
1784 	    builder.openTabBox(next_string(jp).c_str());
1785 	} else if (jp->current_value() == "openVerticalBox") {
1786 	    builder.openVerticalBox(next_string(jp).c_str());
1787 	} else if (jp->current_value() == "openVerticalBox1") {
1788 	    builder.openVerticalBox1(next_string(jp).c_str());
1789 	} else if (jp->current_value() == "openVerticalBox2") {
1790 	    builder.openVerticalBox2(next_string(jp).c_str());
1791 	} else if (jp->current_value() == "openHorizontalhideBox") {
1792 	    builder.openHorizontalhideBox(next_string(jp).c_str());
1793 	} else if (jp->current_value() == "openHorizontalTableBox") {
1794 	    builder.openHorizontalTableBox(next_string(jp).c_str());
1795 	} else if (jp->current_value() == "openFrameBox") {
1796 	    builder.openFrameBox(next_string(jp).c_str());
1797 	} else if (jp->current_value() == "openFlipLabelBox") {
1798 	    builder.openFlipLabelBox(next_string(jp).c_str());
1799 	} else if (jp->current_value() == "openpaintampBox") {
1800 	    builder.openpaintampBox(next_string(jp).c_str());
1801 	} else if (jp->current_value() == "openHorizontalBox") {
1802 	    builder.openHorizontalBox(next_string(jp).c_str());
1803 	} else if (jp->current_value() == "insertSpacer") {
1804 	    builder.insertSpacer();
1805 	} else if (jp->current_value() == "set_next_flags") {
1806 	    jp->next(gx_system::JsonParser::value_number);
1807 	    builder.set_next_flags(jp->current_value_int());
1808 	} else if (jp->current_value() == "create_mid_rackknob") {
1809 	    std::string id = next_string(jp);
1810 	    std::string lab = next_string(jp);
1811 	    builder.create_mid_rackknob(id.c_str(), lab.c_str());
1812 	} else if (jp->current_value() == "create_small_rackknob") {
1813 	    std::string id = next_string(jp);
1814 	    std::string lab = next_string(jp);
1815 	    builder.create_small_rackknob(id.c_str(), lab.c_str());
1816 	} else if (jp->current_value() == "create_small_rackknobr") {
1817 	    std::string id = next_string(jp);
1818 	    std::string lab = next_string(jp);
1819 	    builder.create_small_rackknobr(id.c_str(), lab.c_str());
1820 	} else if (jp->current_value() == "create_big_rackknob") {
1821 	    std::string id = next_string(jp);
1822 	    std::string lab = next_string(jp);
1823 	    builder.create_big_rackknob(id.c_str(), lab.c_str());
1824 	} else if (jp->current_value() == "create_master_slider") {
1825 	    std::string id = next_string(jp);
1826 	    std::string lab = next_string(jp);
1827 	    builder.create_master_slider(id.c_str(), lab.c_str());
1828 	} else if (jp->current_value() == "create_feedback_slider") {
1829 	    std::string id = next_string(jp);
1830 	    std::string lab = next_string(jp);
1831 	    builder.create_feedback_slider(id.c_str(), lab.c_str());
1832 	} else if (jp->current_value() == "create_selector_no_caption") {
1833 	    std::string id = next_string(jp);
1834 	    builder.create_selector_no_caption(id.c_str());
1835 	} else if (jp->current_value() == "create_selector") {
1836 	    std::string id = next_string(jp);
1837 	    std::string lab = next_string(jp);
1838 	    builder.create_selector(id.c_str(), lab.c_str());
1839 	} else if (jp->current_value() == "create_simple_meter") {
1840 		std::string id = next_string(jp);
1841         builder.create_simple_meter(id.c_str());
1842 	} else if (jp->current_value() == "create_simple_c_meter") {
1843         std::string id = next_string(jp);
1844 	    std::string idl = next_string(jp);
1845 	    std::string lab = next_string(jp);
1846 	    builder.create_simple_c_meter(id.c_str(),idl.c_str(), lab.c_str());
1847 	} else if (jp->current_value() == "create_spin_value") {
1848 	    std::string id = next_string(jp);
1849 	    std::string lab = next_string(jp);
1850 	    builder.create_spin_value(id.c_str(), lab.c_str());
1851 	} else if (jp->current_value() == "create_switch_no_caption") {
1852 	    std::string sw_type = next_string(jp);
1853 	    std::string id = next_string(jp);
1854 	    builder.create_switch_no_caption(sw_type.c_str(), id.c_str());
1855 	} else if (jp->current_value() == "create_feedback_switch") {
1856 	    std::string sw_type = next_string(jp);
1857 	    std::string id = next_string(jp);
1858 	    builder.create_feedback_switch(sw_type.c_str(), id.c_str());
1859 	} else if (jp->current_value() == "create_fload_switch") {
1860 	    std::string sw_type = next_string(jp);
1861 	    std::string id = next_string(jp);
1862 	    std::string idf = next_string(jp);
1863 	    builder.create_fload_switch(sw_type.c_str(), id.c_str(), idf.c_str());
1864 	} else if (jp->current_value() == "create_switch") {
1865 	    std::string sw_type = next_string(jp);
1866 	    std::string id = next_string(jp);
1867 	    std::string lab = next_string(jp);
1868 	    builder.create_switch(sw_type.c_str(), id.c_str(), lab.c_str());
1869 	} else if (jp->current_value() == "create_wheel") {
1870 	    std::string id = next_string(jp);
1871 	    std::string lab = next_string(jp);
1872 	    builder.create_wheel(id.c_str(), lab.c_str());
1873 	} else if (jp->current_value() == "create_port_display") {
1874 	    std::string id = next_string(jp);
1875 	    std::string lab = next_string(jp);
1876 	    builder.create_port_display(id.c_str(), lab.c_str());
1877 	} else if (jp->current_value() == "create_p_display") {
1878         std::string id = next_string(jp);
1879 	    std::string idl = next_string(jp);
1880 	    std::string idh = next_string(jp);
1881 	    builder.create_p_display(id.c_str(),idl.c_str(),idh.c_str());
1882 	} else if (jp->current_value() == "create_simple_spin_value") {
1883 		std::string id = next_string(jp);
1884 	    builder.create_simple_spin_value(id.c_str());
1885 	} else if (jp->current_value() == "create_eq_rackslider_no_caption") {
1886 		std::string id = next_string(jp);
1887 	    builder.create_eq_rackslider_no_caption(id.c_str());
1888 	} else if (jp->current_value() == "closeBox") {
1889 	    builder.closeBox();
1890 	} else if (jp->current_value() == "load_glade") {
1891 	    jp->next(gx_system::JsonParser::value_string);
1892 	    builder.load_glade(jp->current_value().c_str());
1893 	} else {
1894 	    cerr << "unknown uiBuilder function " << jp->current_value() << endl;
1895 	    jp->skip_object();
1896 	}
1897 	jp->next(gx_system::JsonParser::end_array);
1898     }
1899     jp->next(gx_system::JsonParser::end_array);
1900     return 0;
1901     END_RECEIVE(return -1);
1902 }
1903 
load_unit(gx_gui::UiBuilderImpl & builder,PluginDef * pdef)1904 bool GxMachineRemote::load_unit(gx_gui::UiBuilderImpl& builder, PluginDef* pdef) {
1905     pdef->load_ui = [](const UiBuilder& builder, int form) {
1906                         GxMachineRemote *m = dynamic_cast<GxMachineRemote*>(
1907                             &static_cast<const gx_gui::UiBuilderImpl*>(
1908                                 &builder)->plugin_dict.get_machine());
1909                         return m->load_remote_ui(builder, form);
1910                     };
1911     return builder.load_unit(pdef);
1912 }
1913 
1914 
1915 /*
1916 ** Oscilloscope
1917 */
1918 
set_oscilloscope_mul_buffer(int a)1919 void GxMachineRemote::set_oscilloscope_mul_buffer(int a) {
1920     START_NOTIFY(set_oscilloscope_mul_buffer);
1921     jw->write(a);
1922     SEND();
1923 }
1924 
get_oscilloscope_mul_buffer()1925 int GxMachineRemote::get_oscilloscope_mul_buffer() {
1926     START_CALL(get_oscilloscope_mul_buffer);
1927     START_RECEIVE(1);
1928     return get_bool(jp);
1929     END_RECEIVE(return 1);
1930 }
1931 
get_tuner_freq()1932 float GxMachineRemote::get_tuner_freq() {
1933     START_CALL(get_tuner_freq);
1934     START_RECEIVE(0);
1935     jp->next(gx_system::JsonParser::value_number);
1936     return jp->current_value_float();
1937     END_RECEIVE(return 0);
1938 }
1939 
get_tuner_note()1940 float GxMachineRemote::get_tuner_note() {
1941     START_CALL(get_tuner_note);
1942     START_RECEIVE(0);
1943     jp->next(gx_system::JsonParser::value_number);
1944     return jp->current_value_float();
1945     END_RECEIVE(return 0);
1946 }
1947 
get_options() const1948 gx_system::CmdlineOptions& GxMachineRemote::get_options() const {
1949     return options;
1950 }
1951 
start_socket(sigc::slot<void> quit_mainloop,const Glib::ustring & host,int port)1952 void GxMachineRemote::start_socket(sigc::slot<void> quit_mainloop, const Glib::ustring& host, int port) {
1953     assert(false);
1954 }
1955 
stop_socket()1956 void GxMachineRemote::stop_socket() {
1957 }
1958 
tuner_switcher_signal_display()1959 sigc::signal<void,const Glib::ustring&,const Glib::ustring&>& GxMachineRemote::tuner_switcher_signal_display() {
1960     return tuner_switcher_display;
1961 }
1962 
tuner_switcher_signal_set_state()1963 sigc::signal<void,TunerSwitcher::SwitcherState>& GxMachineRemote::tuner_switcher_signal_set_state() {
1964     return tuner_switcher_set_state;
1965 }
1966 
tuner_switcher_signal_selection_done()1967 sigc::signal<void, bool>& GxMachineRemote::tuner_switcher_signal_selection_done() {
1968     return tuner_switcher_selection_done;
1969 }
1970 
signal_state_change()1971 sigc::signal<void,GxEngineState>& GxMachineRemote::signal_state_change() {
1972     return engine_state_change;
1973 }
1974 
tuner_used_for_display(bool on)1975 void GxMachineRemote::tuner_used_for_display(bool on) {
1976     START_NOTIFY(tuner_used_for_display);
1977     jw->write(on);
1978     SEND();
1979 }
1980 
tuner_used_by_midi(bool on)1981 void GxMachineRemote::tuner_used_by_midi(bool on) {
1982     if ((on && get_parameter("ui.racktuner").getBool().get_value()) || !on) {
1983         START_NOTIFY(tuner_used_by_midi);
1984         jw->write(on);
1985         SEND();
1986     }
1987 }
1988 
tuner_switch(bool on)1989 void GxMachineRemote::tuner_switch(bool on) {
1990     if (!on && get_parameter("system.midiout_tuner").getBool().get_value()) {
1991         tuner_used_by_midi(false);
1992     } else if (on && get_parameter("system.midiout_tuner").getBool().get_value()) {
1993         tuner_used_by_midi(true);
1994     }
1995 }
1996 
get_rack_unit_order(PluginType type)1997 const std::vector<std::string>& GxMachineRemote::get_rack_unit_order(PluginType type) {
1998     bool stereo = (type == PLUGIN_TYPE_STEREO);
1999     std::vector<std::string>& l = (stereo ? rack_units.stereo : rack_units.mono);
2000     l.clear();
2001     START_CALL(get_rack_unit_order);
2002     jw->write(stereo);
2003     START_RECEIVE(l);
2004     try {
2005 	jp->next(gx_system::JsonParser::begin_array);
2006 	while (jp->peek() != gx_system::JsonParser::end_array) {
2007 	    jp->next(gx_system::JsonParser::value_string);
2008 	    l.push_back(jp->current_value());
2009 	}
2010 	jp->next(gx_system::JsonParser::end_array);
2011     } catch (gx_system::JsonException& e) {
2012 	cerr << "JsonException: " << e.what() << ": '" << jp->get_string() << "'" << endl;
2013 	assert(false);
2014     }
2015     return l;
2016     END_RECEIVE(return l);
2017 }
2018 
signal_rack_unit_order_changed()2019 sigc::signal<void,bool>& GxMachineRemote::signal_rack_unit_order_changed() {
2020     return rack_units.rack_unit_order_changed;
2021 }
2022 
remove_rack_unit(const std::string & unit,PluginType type)2023 void GxMachineRemote::remove_rack_unit(const std::string& unit, PluginType type) {
2024     START_NOTIFY(remove_rack_unit);
2025     jw->write(unit);
2026     jw->write(type == PLUGIN_TYPE_STEREO);
2027     SEND();
2028     rack_units.rack_unit_order_changed(type == PLUGIN_TYPE_STEREO);
2029 }
2030 
insert_rack_unit(const std::string & unit,const std::string & before,PluginType type)2031 void GxMachineRemote::insert_rack_unit(const std::string& unit, const std::string& before, PluginType type) {
2032     START_NOTIFY(insert_rack_unit);
2033     jw->write(unit);
2034     jw->write(before);
2035     jw->write(type == PLUGIN_TYPE_STEREO);
2036     SEND();
2037     rack_units.rack_unit_order_changed(type == PLUGIN_TYPE_STEREO);
2038 }
2039 
2040 // tuner_switcher
get_tuner_switcher_active()2041 bool GxMachineRemote::get_tuner_switcher_active() {
2042     START_CALL(get_tuner_switcher_active);
2043     START_RECEIVE(false);
2044     return get_bool(jp);
2045     END_RECEIVE(return false);
2046 }
2047 
tuner_switcher_activate(bool v)2048 void GxMachineRemote::tuner_switcher_activate(bool v) {
2049     START_NOTIFY(tuner_switcher_activate);
2050     jw->write(v);
2051     SEND();
2052 }
2053 
tuner_switcher_deactivate()2054 void GxMachineRemote::tuner_switcher_deactivate() {
2055     START_NOTIFY(tuner_switcher_deactivate);
2056     SEND();
2057 }
2058 
tuner_switcher_toggle(bool v)2059 void GxMachineRemote::tuner_switcher_toggle(bool v) {
2060     START_NOTIFY(tuner_switcher_toggle);
2061     jw->write(v);
2062     SEND();
2063 }
2064 
on_tuner_freq_changed()2065 void GxMachineRemote::on_tuner_freq_changed() {
2066 #ifdef USE_MIDI_CC_OUT
2067     if (get_parameter("system.midiout_tuner").getBool().get_value()) {
2068         float fnote = get_tuner_note();
2069         if (fnote < 999.0) {
2070             int note = static_cast<int>(round(fnote));
2071             uint8_t midi_note = static_cast<uint8_t>(note+69);
2072             uint8_t vel = static_cast<uint8_t>(((fnote - note) * 127) +63);
2073 
2074             msend_midi_cc(0x90, midi_note,vel, 3);
2075         } else {
2076             msend_midi_cc(0xB0, 123, 0, 3);
2077         }
2078     }
2079 #endif
2080 }
2081 
2082 // preset
2083 
next_preset_switch()2084 void GxMachineRemote::next_preset_switch() {
2085     gx_system::PresetFileGui *f= get_current_bank_file();
2086     int idx = f->get_index(get_current_name());
2087     if (idx+1 < f->size()) load_preset(f, f->get_name(idx+1));
2088     else load_preset(f, f->get_name(0));
2089 }
2090 
previus_preset_switch()2091 void GxMachineRemote::previus_preset_switch() {
2092     gx_system::PresetFileGui *f= get_current_bank_file();
2093     int idx = f->get_index(get_current_name());
2094     if (idx-1 > -1) load_preset(f, f->get_name(idx-1));
2095     else load_preset(f, f->get_name(f->size()-1));
2096 }
2097 
process_next_preset_switch(bool s)2098 void GxMachineRemote::process_next_preset_switch(bool s) {
2099     if(s) {
2100         Glib::signal_idle().connect_once(
2101           sigc::mem_fun(this, &GxMachineRemote::next_preset_switch));
2102         set_parameter_value("engine.next_preset",false);
2103     }
2104 }
2105 
process_previus_preset_switch(bool s)2106 void GxMachineRemote::process_previus_preset_switch(bool s) {
2107     if(s) {
2108         Glib::signal_idle().connect_once(
2109           sigc::mem_fun(this, &GxMachineRemote::previus_preset_switch));
2110         set_parameter_value("engine.previus_preset",false);
2111     }
2112 }
2113 
2114 
setting_is_preset()2115 bool GxMachineRemote::setting_is_preset() {
2116     return (!get_current_bank().empty());
2117 }
2118 
2119 static const Glib::ustring empty_string;
2120 
get_current_bank()2121 const Glib::ustring& GxMachineRemote::get_current_bank() {
2122     return current_bank;
2123 }
2124 
get_current_bank_file()2125 gx_system::PresetFileGui *GxMachineRemote::get_current_bank_file() {
2126     return get_bank_file(get_current_bank());
2127 }
2128 
get_current_name()2129 const Glib::ustring& GxMachineRemote::get_current_name() {
2130     return current_preset;
2131 }
2132 
get_bank_file(const Glib::ustring & bank) const2133 gx_system::PresetFileGui* GxMachineRemote::get_bank_file(const Glib::ustring& bank) const { //FIXME
2134     return banks.get_file(bank)->get_guiwrapper();
2135 }
2136 
get_bank_name(int n)2137 Glib::ustring GxMachineRemote::get_bank_name(int n) {
2138     return banks.get_name(n);
2139 }
2140 
msend_midi_cc(int cc,int pgn,int bgn,int num)2141 bool GxMachineRemote::msend_midi_cc(int cc, int pgn, int bgn, int num) {
2142 	START_NOTIFY(sendcc);
2143     jw->write(cc);
2144     jw->write(pgn);
2145     jw->write(bgn);
2146     jw->write(num);
2147     SEND();
2148     return true;
2149 }
2150 
load_preset(gx_system::PresetFileGui * pf,const Glib::ustring & name)2151 void GxMachineRemote::load_preset(gx_system::PresetFileGui *pf, const Glib::ustring& name) {
2152     int n = get_bank_index(get_current_bank());
2153     START_NOTIFY(setpreset);
2154     jw->write(pf->get_name());
2155     jw->write(name);
2156     SEND();
2157 #ifdef USE_MIDI_CC_OUT
2158     if (get_bank_index(pf->get_name()) != n) {
2159         msend_midi_cc(0xB0, 32, get_bank_index(pf->get_name()),3);
2160     }
2161     msend_midi_cc(0xC0, pf->get_index(name),0,2);
2162 #endif
2163 }
2164 
loadstate()2165 void GxMachineRemote::loadstate() {
2166     /* noop */
2167 }
2168 
bank_size()2169 int GxMachineRemote::bank_size() {
2170     return banks.size();
2171 }
2172 
get_bank_index(const Glib::ustring & bank)2173 int GxMachineRemote::get_bank_index(const Glib::ustring& bank) {
2174     return banks.get_index(bank);
2175 }
2176 
create_default_scratch_preset()2177 void GxMachineRemote::create_default_scratch_preset() {
2178     START_NOTIFY(create_default_scratch_preset);
2179     SEND();
2180 }
2181 
set_statefilename(const std::string & fn)2182 void GxMachineRemote::set_statefilename(const std::string& fn) {
2183     //FIXME move jack session handling inside machine
2184     /* noop */
2185 }
2186 
save_to_state(bool preserve_preset)2187 void GxMachineRemote::save_to_state(bool preserve_preset) {
2188     //FIXME move jack session handling inside machine
2189     /* noop */
2190 }
2191 
plugin_preset_list_load(const PluginDef * pdef,gx_preset::UnitPresetList & presetnames)2192 void GxMachineRemote::plugin_preset_list_load(const PluginDef *pdef, gx_preset::UnitPresetList &presetnames) {
2193     START_CALL(plugin_preset_list_load);
2194     jw->write(pdef->id);
2195     START_RECEIVE();
2196     jp->next(gx_system::JsonParser::begin_array);
2197     while (jp->peek() != gx_system::JsonParser::end_array) {
2198 	jp->next(gx_system::JsonParser::begin_array);
2199 	jp->next(gx_system::JsonParser::value_string);
2200 	Glib::ustring name = jp->current_value();
2201 	jp->next(gx_system::JsonParser::value_number);
2202 	presetnames.push_back(gx_preset::PluginPresetEntry(name, jp->current_value_int()));
2203 	jp->next(gx_system::JsonParser::end_array);
2204     }
2205     jp->next(gx_system::JsonParser::end_array);
2206     END_RECEIVE();
2207 }
2208 
plugin_preset_list_set(const PluginDef * pdef,bool factory,const Glib::ustring & name)2209 void GxMachineRemote::plugin_preset_list_set(const PluginDef *pdef, bool factory, const Glib::ustring& name) {
2210     START_NOTIFY(plugin_preset_list_set);
2211     jw->write(pdef->id);
2212     jw->write(factory);
2213     jw->write(name);
2214     SEND();
2215 }
2216 
plugin_preset_list_sync_set(const PluginDef * pdef,bool factory,const Glib::ustring & name)2217 void GxMachineRemote::plugin_preset_list_sync_set(const PluginDef *pdef, bool factory, const Glib::ustring& name) {
2218     START_NOTIFY(plugin_preset_list_sync_set);
2219     jw->write(pdef->id);
2220     jw->write(factory);
2221     jw->write(name);
2222     SEND();
2223 }
2224 
plugin_preset_list_set_on_idle(const PluginDef * pdef,bool factory,const Glib::ustring & name)2225 void GxMachineRemote::plugin_preset_list_set_on_idle(const PluginDef *pdef, bool factory, const Glib::ustring& name) {
2226     Glib::signal_idle().connect_once(
2227       sigc::bind(sigc::bind(sigc::bind(sigc::mem_fun(this, &GxMachineRemote::plugin_preset_list_sync_set),name),factory),pdef));
2228 }
2229 
plugin_preset_list_save(const PluginDef * pdef,const Glib::ustring & name)2230 void GxMachineRemote::plugin_preset_list_save(const PluginDef *pdef, const Glib::ustring& name) {
2231     START_NOTIFY(plugin_preset_list_save);
2232     jw->write(pdef->id);
2233     jw->write(name);
2234     SEND();
2235 }
2236 
plugin_preset_list_remove(const PluginDef * pdef,const Glib::ustring & name)2237 void GxMachineRemote::plugin_preset_list_remove(const PluginDef *pdef, const Glib::ustring& name) {
2238     START_NOTIFY(plugin_preset_list_remove);
2239     jw->write(pdef->id);
2240     jw->write(name);
2241     SEND();
2242 }
2243 
disable_autosave(bool v)2244 void GxMachineRemote::disable_autosave(bool v) {
2245     //FIXME: move inside machine
2246     /* noop */
2247 }
2248 
signal_selection_changed()2249 sigc::signal<void>& GxMachineRemote::signal_selection_changed() {
2250     return selection_changed;
2251 }
2252 
signal_presetlist_changed()2253 sigc::signal<void>& GxMachineRemote::signal_presetlist_changed() {
2254     return presetlist_changed;
2255 }
2256 
bank_insert_uri(const Glib::ustring & uri,bool move,int position)2257 gx_system::PresetFileGui *GxMachineRemote::bank_insert_uri(const Glib::ustring& uri, bool move, int position) {
2258     START_CALL(bank_insert_content);
2259     jw->write(uri);
2260     Glib::RefPtr<Gio::File> rem = Gio::File::create_for_uri(uri);
2261     fstream f(rem->get_path().c_str());
2262     stringstream s;
2263     s << f.rdbuf();
2264     jw->write(s.str());
2265     jw->write(position);
2266     START_RECEIVE(0);
2267     if (jp->peek() != gx_system::JsonParser::begin_object) {
2268 	return 0;
2269     }
2270     gx_system::PresetFile *pf = new gx_system::PresetFile();
2271     pf->readJSON_remote(*jp);
2272     banks.insert(pf, position);
2273     return pf->get_guiwrapper();
2274     END_RECEIVE(return 0);
2275 }
2276 
bank_insert_new(const Glib::ustring & newname)2277 gx_system::PresetFileGui *GxMachineRemote::bank_insert_new(const Glib::ustring& newname) {
2278     START_CALL(bank_insert_new);
2279     jw->write(newname);
2280     START_RECEIVE(0);
2281     gx_system::PresetFile *pf = new gx_system::PresetFile();
2282     pf->readJSON_remote(*jp);
2283     banks.insert(pf);
2284     return pf->get_guiwrapper();
2285     END_RECEIVE(return 0);
2286 }
2287 
rename_bank(const Glib::ustring & oldname,Glib::ustring & newname)2288 bool GxMachineRemote::rename_bank(const Glib::ustring& oldname, Glib::ustring& newname) {
2289     START_CALL(rename_bank);
2290     jw->write(oldname);
2291     jw->write(newname);
2292     START_RECEIVE(false);
2293     jp->next(gx_system::JsonParser::begin_array);
2294     jp->next(gx_system::JsonParser::value_number);
2295     bool ret = jp->current_value_int();
2296     jp->next(gx_system::JsonParser::value_string);
2297     newname = jp->current_value();
2298     jp->next(gx_system::JsonParser::end_array);
2299     if (ret) {
2300 	banks.get_file(oldname)->name = newname;
2301     }
2302     return ret;
2303     END_RECEIVE(return false);
2304 }
2305 
rename_preset(gx_system::PresetFileGui & pf,const Glib::ustring & oldname,const Glib::ustring & newname)2306 bool GxMachineRemote::rename_preset(gx_system::PresetFileGui& pf, const Glib::ustring& oldname, const Glib::ustring& newname) {
2307     START_CALL(rename_preset);
2308     jw->write(pf.get_name());
2309     jw->write(oldname);
2310     jw->write(newname);
2311     START_RECEIVE(false);
2312     bool ret = get_bool(jp);
2313     if (ret) {
2314 	int idx = pf.get_index(oldname);
2315 	assert(idx >= 0);
2316 	pf.entries[idx].name = newname;
2317     }
2318     return ret;
2319     END_RECEIVE(return false);
2320 }
2321 
bank_reorder(const std::vector<Glib::ustring> & neworder)2322 void GxMachineRemote::bank_reorder(const std::vector<Glib::ustring>& neworder) {
2323     START_NOTIFY(bank_reorder);
2324     for (std::vector<Glib::ustring>::const_iterator i = neworder.begin(); i != neworder.end(); ++i) {
2325 	jw->write(*i);
2326     }
2327     SEND();
2328     banks.reorder(neworder);
2329 }
2330 
reorder_preset(gx_system::PresetFileGui & pf,const std::vector<Glib::ustring> & neworder)2331 void GxMachineRemote::reorder_preset(gx_system::PresetFileGui& pf, const std::vector<Glib::ustring>& neworder) {
2332     START_NOTIFY(reorder_preset);
2333     jw->write(pf.get_name());
2334     for (std::vector<Glib::ustring>::const_iterator i = neworder.begin(); i != neworder.end(); ++i) {
2335 	jw->write(*i);
2336     }
2337     SEND();
2338     int n = 0;
2339     for (std::vector<Glib::ustring>::const_iterator i = neworder.begin(); i != neworder.end(); ++i) {
2340 	pf.entries[n++].name = *i;
2341     }
2342     presetlist_changed();
2343 }
2344 
bank_check_reparse()2345 bool GxMachineRemote::bank_check_reparse() {
2346     START_CALL(bank_check_reparse);
2347     START_RECEIVE(false);
2348     return get_bool(jp);
2349     END_RECEIVE(return false);
2350 }
2351 
erase_preset(gx_system::PresetFileGui & pf,const Glib::ustring & name)2352 void GxMachineRemote::erase_preset(gx_system::PresetFileGui& pf, const Glib::ustring& name) {
2353     START_NOTIFY(erase_preset);
2354     jw->write(pf.get_name());
2355     jw->write(name);
2356     SEND();
2357     for (gx_system::PresetFile::iterator i = pf.begin(); i != pf.end(); ++i) {
2358 	if (i->name == name) {
2359 	    pf.entries.erase(i);
2360 	    break;
2361 	}
2362     }
2363 }
2364 
bank_set_flag(gx_system::PresetFileGui * pf,int flag,bool v)2365 void GxMachineRemote::bank_set_flag(gx_system::PresetFileGui *pf, int flag, bool v) {
2366     START_NOTIFY(bank_set_flag);
2367     jw->write(pf->get_name());
2368     jw->write(flag);
2369     jw->write(v);
2370     SEND();
2371     pf->set_flag(flag, v);
2372 }
2373 
bank_get_filename(const Glib::ustring & bank)2374 std::string GxMachineRemote::bank_get_filename(const Glib::ustring& bank) {
2375     // FIXME Gtk3: bank_get_filename is used in DnD bank operation, and the
2376     // first request is due to an internal window of the DnD mechanism but
2377     // there seems to be no way to detect this. Skip this first request so
2378     // that no contents is send for a DnD reorder operation. Recheck for Gtk3
2379     switch (bank_drag_get_counter) {
2380     case 0:
2381 	bank_drag_get_counter++;
2382 	return "";
2383     case 1:
2384 	bank_drag_get_counter++;
2385 	START_CALL(bank_get_contents);
2386 	jw->write(bank);
2387 	START_RECEIVE(empty_string);
2388 	jp->next(gx_system::JsonParser::begin_array);
2389 	jp->next(gx_system::JsonParser::value_string);
2390 	Glib::RefPtr<Gio::File> target = Gio::File::create_for_path(
2391 	    options.get_temp_filepath(
2392 		Gio::File::create_for_path(jp->current_value())->get_basename()));
2393 	jp->next(gx_system::JsonParser::value_string);
2394 	Glib::RefPtr<Gio::FileOutputStream> s = target->replace(
2395 	    "", false, Gio::FILE_CREATE_REPLACE_DESTINATION);
2396 	s->write(jp->current_value());
2397 	s->close();
2398 	jp->next(gx_system::JsonParser::end_array);
2399 	bank_drag_get_path = target->get_path();
2400 	END_RECEIVE(return empty_string);
2401     }
2402     return bank_drag_get_path;
2403 }
2404 
bank_drag_begin()2405 void GxMachineRemote::bank_drag_begin() {
2406     bank_drag_get_counter = 0;
2407     bank_drag_get_path.clear();
2408 }
2409 
bank_get_file(const Glib::ustring & bank) const2410 gx_system::PresetFileGui *GxMachineRemote::bank_get_file(const Glib::ustring& bank) const {
2411     return banks.get_file(bank)->get_guiwrapper();
2412 }
2413 
bank_begin()2414 bank_iterator GxMachineRemote::bank_begin() {
2415     return banks.begin();
2416 }
2417 
bank_end()2418 bank_iterator GxMachineRemote::bank_end() {
2419     return banks.end();
2420 }
2421 
pf_append(gx_system::PresetFileGui & pf,const Glib::ustring & src,gx_system::PresetFileGui & pftgt,const Glib::ustring & name)2422 void GxMachineRemote::pf_append(gx_system::PresetFileGui& pf, const Glib::ustring& src, gx_system::PresetFileGui& pftgt, const Glib::ustring& name) {
2423     START_NOTIFY(pf_append);
2424     jw->write(pf.get_name());
2425     jw->write(src);
2426     jw->write(pftgt.get_name());
2427     jw->write(name);
2428     SEND();
2429     pftgt.entries.push_back(gx_system::PresetFile::Position(name,0));
2430 }
2431 
pf_insert_before(gx_system::PresetFileGui & pf,const Glib::ustring & src,gx_system::PresetFileGui & pftgt,const Glib::ustring & pos,const Glib::ustring & name)2432 void GxMachineRemote::pf_insert_before(gx_system::PresetFileGui& pf, const Glib::ustring& src, gx_system::PresetFileGui& pftgt, const Glib::ustring& pos, const Glib::ustring& name) {
2433     START_NOTIFY(pf_insert_before);
2434     jw->write(pf.get_name());
2435     jw->write(src);
2436     jw->write(pftgt.get_name());
2437     jw->write(pos);
2438     jw->write(name);
2439     SEND();
2440     for (gx_system::PresetFile::iterator i = pftgt.begin(); i != pftgt.end(); ++i) {
2441 	if (i->name == pos) {
2442 	    pftgt.entries.insert(i, gx_system::PresetFile::Position(name, 0));
2443 	    break;
2444 	}
2445     }
2446 }
2447 
pf_insert_after(gx_system::PresetFileGui & pf,const Glib::ustring & src,gx_system::PresetFileGui & pftgt,const Glib::ustring & pos,const Glib::ustring & name)2448 void GxMachineRemote::pf_insert_after(gx_system::PresetFileGui& pf, const Glib::ustring& src, gx_system::PresetFileGui& pftgt, const Glib::ustring& pos, const Glib::ustring& name) {
2449     START_NOTIFY(pf_insert_after);
2450     jw->write(pf.get_name());
2451     jw->write(src);
2452     jw->write(pftgt.get_name());
2453     jw->write(pos);
2454     jw->write(name);
2455     SEND();
2456     for (gx_system::PresetFile::iterator i = pftgt.begin(); i != pftgt.end(); ++i) {
2457 	if (i->name == pos) {
2458 	    pftgt.entries.insert(++i, gx_system::PresetFile::Position(name, 0));
2459 	    break;
2460 	}
2461     }
2462 }
2463 
convert_preset(gx_system::PresetFileGui & pf)2464 bool GxMachineRemote::convert_preset(gx_system::PresetFileGui& pf) {
2465     START_CALL(convert_preset);
2466     jw->write(pf.get_name());
2467     START_RECEIVE(false);
2468     bool ret = get_bool(jp);
2469     if (ret) {
2470 	pf.set_flag(gx_system::PRESET_FLAG_VERSIONDIFF, false);
2471     }
2472     return ret;
2473     END_RECEIVE(return false);
2474 }
2475 
bank_remove(const Glib::ustring & bank)2476 bool GxMachineRemote::bank_remove(const Glib::ustring& bank) {
2477     gx_system::PresetFile *f = banks.get_file(bank);
2478     START_CALL(bank_remove);
2479     jw->write(bank);
2480     START_RECEIVE(false);
2481     bool ret = get_bool(jp);
2482     if (ret) {
2483 	banks.banklist.remove(f);
2484 	delete f;
2485     }
2486     return ret;
2487     END_RECEIVE(return false);
2488 }
2489 
bank_save()2490 void GxMachineRemote::bank_save() {
2491     START_NOTIFY(bank_save);
2492     SEND();
2493 }
2494 
pf_save(gx_system::PresetFileGui & pf,const Glib::ustring & name)2495 void GxMachineRemote::pf_save(gx_system::PresetFileGui& pf, const Glib::ustring& name) {
2496     START_NOTIFY(pf_save);
2497     jw->write(pf.get_name());
2498     jw->write(name);
2499     SEND();
2500 }
2501 
2502 
2503 // jack
get_jack()2504 gx_jack::GxJack *GxMachineRemote::get_jack() {
2505     return 0;
2506 }
2507 
set_jack_insert(bool v)2508 void GxMachineRemote::set_jack_insert(bool v) {
2509     START_NOTIFY(set_jack_insert);
2510     jw->write(v);
2511     SEND();
2512 }
2513 
2514 // pmap
get_parameter(const char * p)2515 Parameter& GxMachineRemote::get_parameter(const char *p) {
2516     return pmap[p];
2517 }
2518 
get_parameter(const std::string & id)2519 Parameter& GxMachineRemote::get_parameter(const std::string& id) {
2520     return pmap[id];
2521 }
2522 
2523 // special case for DrumSequencer: register parameter for midi cc connection
insert_param(Glib::ustring group,Glib::ustring name)2524 void GxMachineRemote::insert_param(Glib::ustring group, Glib::ustring name) {
2525     Glib::ustring id = group + "." + name;
2526     Glib::ustring tb = "switch to preset " + name;
2527     START_NOTIFY(insert_param);
2528     jw->write(id);
2529     jw->write(tb);
2530     SEND();
2531     if (!pmap.hasId(id)) {
2532         if (!gx_engine::get_group_table().group_exist(group))
2533             gx_engine::get_group_table().insert(group,"Drumsequencer");
2534         BoolParameter& sp = pmap.reg_par(
2535           id, tb, (bool*)0, false, false)->getBool();
2536         sp.setSavable(false);
2537     }
2538     if (pmap.hasId(id))
2539         pmap[id].signal_changed_bool().connect(sigc::hide(
2540           sigc::bind(sigc::bind(sigc::bind(sigc::mem_fun(this, &GxMachineRemote::plugin_preset_list_set_on_idle), name), false),pluginlist_lookup_plugin("seq")->get_pdef())));
2541 }
2542 
set_init_values()2543 void GxMachineRemote::set_init_values() {
2544     for (ParamMap::iterator i = pmap.begin(); i != pmap.end(); ++i) {
2545 	Parameter *p = i->second;
2546 	if (p->isFloat()) {
2547 	    FloatParameter& pf = p->getFloat();
2548 	    pf.signal_changed()(pf.get_value());
2549 	} else if (p->isInt()) {
2550 	    IntParameter& pi = p->getInt();
2551 	    pi.signal_changed()(pi.get_value());
2552 	} else if (p->isBool()) {
2553 	    BoolParameter& pb = p->getBool();
2554 	    pb.signal_changed()(pb.get_value());
2555 	} else if (p->isString()) {
2556 	    StringParameter& ps = p->getString();
2557 	    ps.signal_changed()(ps.get_value());
2558 	} else if (p->isFile()) {
2559 	    FileParameter& fp = p->getFile();
2560 	    fp.signal_changed()();
2561 	} else if (dynamic_cast<JConvParameter*>(i->second) != 0) {
2562 	    JConvParameter* pj = dynamic_cast<JConvParameter*>(i->second);
2563 	    pj->signal_changed()(&pj->get_value());
2564 	} else if (dynamic_cast<SeqParameter*>(i->second) != 0) {
2565 	    SeqParameter* pj = dynamic_cast<SeqParameter*>(i->second);
2566 	    pj->signal_changed()(&pj->get_value());
2567 	}
2568     }
2569     selection_changed(); // give preset window a chance to catch up on current preset
2570     Glib::signal_io().connect(
2571 	sigc::mem_fun(this, &GxMachineRemote::socket_input_handler),
2572 	socket->get_fd(), Glib::IO_IN);
2573     for (ParamMap::iterator i = pmap.begin(); i != pmap.end(); ++i) {
2574 	if (i->second->isInt()) {
2575 	    i->second->getInt().signal_changed().connect(
2576 		sigc::hide(
2577 		    sigc::bind(
2578 			sigc::mem_fun(this, &GxMachineRemote::param_signal), i->second)));
2579 	} else if (i->second->isBool()) {
2580 	    i->second->getBool().signal_changed().connect(
2581 		sigc::hide(
2582 		    sigc::bind(
2583 			sigc::mem_fun(this, &GxMachineRemote::param_signal), i->second)));
2584 	} else if (i->second->isFloat()) {
2585 	    i->second->getFloat().signal_changed().connect(
2586 		sigc::hide(
2587 		    sigc::bind(
2588 			sigc::mem_fun(this, &GxMachineRemote::param_signal), i->second)));
2589 	} else if (i->second->isString()) {
2590 	    i->second->getString().signal_changed().connect(
2591 		sigc::hide(
2592 		    sigc::bind(
2593 			sigc::mem_fun(this, &GxMachineRemote::param_signal), i->second)));
2594 	} else if (dynamic_cast<JConvParameter*>(i->second) != 0) {
2595 	    dynamic_cast<JConvParameter*>(i->second)->signal_changed().connect(
2596 		sigc::hide(
2597 		    sigc::bind(
2598 			sigc::mem_fun(this, &GxMachineRemote::param_signal), i->second)));
2599 	} else if (dynamic_cast<SeqParameter*>(i->second) != 0) {
2600 	    dynamic_cast<SeqParameter*>(i->second)->signal_changed().connect(
2601 		sigc::hide(
2602 		    sigc::bind(
2603 			sigc::mem_fun(this, &GxMachineRemote::param_signal), i->second)));
2604 	}
2605     }
2606 }
2607 
update_parameter()2608 bool GxMachineRemote::update_parameter() {
2609     START_NOTIFY(get_updates);
2610     for (output_listen_map::const_iterator i = update_map.cbegin(); i != update_map.cend(); ++i) {
2611 	jw->write(i->first);
2612     }
2613     SEND();
2614     return true;
2615 }
2616 
parameter_hasId(const char * p)2617 bool GxMachineRemote::parameter_hasId(const char *p) {
2618     return pmap.hasId(p);
2619 }
2620 
parameter_hasId(const std::string & id)2621 bool GxMachineRemote::parameter_hasId(const std::string& id) {
2622     return pmap.hasId(id);
2623 }
2624 
reset_unit(const PluginDef * pdef) const2625 void GxMachineRemote::reset_unit(const PluginDef *pdef) const {
2626     pmap.reset_unit(pdef);
2627 }
2628 
parameter_unit_has_std_values(const PluginDef * pdef) const2629 bool GxMachineRemote::parameter_unit_has_std_values(const PluginDef *pdef) const {
2630     return pmap.unit_has_std_values(pdef);
2631 }
2632 
set_parameter_value(const std::string & id,int value)2633 void GxMachineRemote::set_parameter_value(const std::string& id, int value) {
2634 #ifdef USE_MIDI_CC_OUT
2635     if (options.system_midiout) {
2636         const gx_engine::MidiController *pctrl;
2637         IntParameter& p = get_parameter(id).getInt();
2638         if (p.get_value() != value) {
2639             int nctl = midi_param2controller(p, &pctrl);
2640             if (nctl > -1 && nctl < 128) {
2641                 int state = int(((float(value) - p.getLowerAsFloat()) /
2642                     (p.getUpperAsFloat() - p.getLowerAsFloat())) * 127.0);
2643                 msend_midi_cc(0xB0, nctl, state, 3);
2644                 if (pctrl->toggle_behaviour() != Parameter::toggle_type::OnOff) {
2645                     midi_set_last_controller_value(nctl, state);
2646                 } else {
2647                      midi_set_last_controller_value(nctl, p.get_value()*127);
2648                 }
2649             }
2650         }
2651     }
2652 #endif
2653     pmap[id].getInt().set(value);
2654 }
2655 
set_parameter_value(const std::string & id,bool value)2656 void GxMachineRemote::set_parameter_value(const std::string& id, bool value) {
2657 #ifdef USE_MIDI_CC_OUT
2658     if (options.system_midiout) {
2659         const gx_engine::MidiController *pctrl;
2660         BoolParameter& p = get_parameter(id).getBool();
2661         if (p.get_value() != value) {
2662             int nctl = midi_param2controller(p, &pctrl);
2663             if (nctl > -1 && nctl < 128) {
2664                 int state = int(value * 127);
2665                 msend_midi_cc(0xB0, nctl,state, 3);
2666                 if (pctrl->toggle_behaviour() != Parameter::toggle_type::OnOff) {
2667                     midi_set_last_controller_value(nctl, state);
2668                 } else {
2669                      midi_set_last_controller_value(nctl, p.get_value()*127);
2670                 }
2671             }
2672         }
2673     }
2674 #endif
2675     pmap[id].getBool().set(value);
2676 }
2677 
set_parameter_value(const std::string & id,float value)2678 void GxMachineRemote::set_parameter_value(const std::string& id, float value) {
2679 #ifdef USE_MIDI_CC_OUT
2680     if (options.system_midiout) {
2681         const gx_engine::MidiController *pctrl;
2682         FloatParameter& p = get_parameter(id).getFloat();
2683         if ( std::fabs(p.get_value() - value) > 0.00001) {
2684             int nctl = midi_param2controller(p, &pctrl);
2685             if (nctl > -1 && nctl < 128) {
2686                 int state = int(((float(value) - p.getLowerAsFloat()) /
2687                     (p.getUpperAsFloat() - p.getLowerAsFloat())) * 127.0);
2688                 msend_midi_cc(0xB0, nctl, state, 3);
2689                // if (pctrl->toggle_behaviour() != Parameter::toggle_type::OnOff) {
2690                //     midi_set_last_controller_value(nctl, state);
2691                // } else {
2692                //      midi_set_last_controller_value(nctl, p.get_value()*127);
2693                // }
2694             }
2695         }
2696     }
2697 #endif
2698     pmap[id].getFloat().set(value);
2699 }
2700 
set_parameter_value(const std::string & id,const std::string & value)2701 void GxMachineRemote::set_parameter_value(const std::string& id, const std::string& value) {
2702     if (!pmap[id].getString().set(value)) {
2703 	return;
2704     }
2705     START_NOTIFY(set);
2706     jw->write(id);
2707     jw->write(value);
2708     SEND();
2709 }
2710 
_get_parameter_value_int(const std::string & id)2711 int GxMachineRemote::_get_parameter_value_int(const std::string& id) {
2712     START_CALL(get);
2713     jw->write(id);
2714     START_RECEIVE(0);
2715     jp->next(gx_system::JsonParser::begin_object);
2716     jp->next(gx_system::JsonParser::value_key);
2717     int v;
2718     switch (jp->next()) {
2719     case gx_system::JsonParser::value_string:
2720 	v = pmap[id].getEnum().idx_from_id(jp->current_value());
2721 	break;
2722     case gx_system::JsonParser::value_number:
2723 	v = jp->current_value_int();
2724 	break;
2725     default:
2726 	assert(false);
2727 	return 0;
2728     }
2729     return v;
2730     END_RECEIVE(return 0);
2731 }
2732 
_get_parameter_value_bool(const std::string & id)2733 int GxMachineRemote::_get_parameter_value_bool(const std::string& id) {
2734     START_CALL(get);
2735     jw->write(id);
2736     START_RECEIVE(false);
2737     jp->next(gx_system::JsonParser::begin_object);
2738     jp->next(gx_system::JsonParser::value_key);
2739     jp->next(gx_system::JsonParser::value_number);
2740     return jp->current_value_int();
2741     END_RECEIVE(return false);
2742 }
2743 
_get_parameter_value_float(const std::string & id)2744 float GxMachineRemote::_get_parameter_value_float(const std::string& id) {
2745     START_CALL(get);
2746     jw->write(id);
2747     START_RECEIVE(0);
2748     jp->next(gx_system::JsonParser::begin_object);
2749     jp->next(gx_system::JsonParser::value_key);
2750     float v;
2751     switch (jp->next()) {
2752     case gx_system::JsonParser::value_string:
2753 	v = dynamic_cast<FloatEnumParameter*>(&pmap[id])->idx_from_id(jp->current_value());
2754 	break;
2755     case gx_system::JsonParser::value_number:
2756 	v = jp->current_value_float();
2757 	break;
2758     default:
2759 	assert(false);
2760 	return 0;
2761     }
2762     return v;
2763     END_RECEIVE(return 0);
2764 }
2765 
_get_parameter_value_string(const std::string & id)2766 std::string GxMachineRemote::_get_parameter_value_string(const std::string& id) {
2767     START_CALL(get);
2768     jw->write(id);
2769     START_RECEIVE(empty_string);
2770     jp->next(gx_system::JsonParser::begin_object);
2771     jp->next(gx_system::JsonParser::value_key);
2772     jp->next(gx_system::JsonParser::value_string);
2773     return jp->current_value();
2774     END_RECEIVE(return empty_string);
2775 }
2776 
_signal_parameter_value_int(const std::string & id)2777 sigc::signal<void, int>& GxMachineRemote::_signal_parameter_value_int(const std::string& id) {
2778     return pmap[id].signal_changed_int();
2779 }
2780 
_signal_parameter_value_bool(const std::string & id)2781 sigc::signal<void, bool>& GxMachineRemote::_signal_parameter_value_bool(const std::string& id) {
2782     return pmap[id].signal_changed_bool();
2783 }
2784 
_signal_parameter_value_float(const std::string & id)2785 sigc::signal<void, float>& GxMachineRemote::_signal_parameter_value_float(const std::string& id) {
2786     return pmap[id].signal_changed_float();
2787 }
2788 
2789 // MidiControllerList
midi_get_config_mode(int * ctl)2790 bool GxMachineRemote::midi_get_config_mode(int *ctl) {
2791     START_CALL(midi_get_config_mode);
2792     START_RECEIVE(false);
2793     jp->next(gx_system::JsonParser::begin_array);
2794     bool ret = get_bool(jp);
2795     jp->next(gx_system::JsonParser::value_number);
2796     if (ret && ctl) {
2797 	*ctl = jp->current_value_int();
2798     }
2799     jp->next(gx_system::JsonParser::end_array);
2800     return ret;
2801     END_RECEIVE(return false);
2802 }
2803 
midi_set_config_mode(bool v,int ctl)2804 void GxMachineRemote::midi_set_config_mode(bool v, int ctl) {
2805     START_NOTIFY(midi_set_config_mode);
2806     jw->write(v);
2807     jw->write(ctl);
2808     SEND();
2809 }
2810 
signal_midi_changed()2811 sigc::signal<void>& GxMachineRemote::signal_midi_changed() {
2812     return midi_changed;
2813 }
2814 
signal_midi_value_changed()2815 sigc::signal<void, int, int>& GxMachineRemote::signal_midi_value_changed() {
2816     return midi_value_changed;
2817 }
2818 
request_midi_value_update()2819 void GxMachineRemote::request_midi_value_update() {
2820     START_NOTIFY(request_midi_value_update);
2821     SEND();
2822 }
2823 
midi_size()2824 int GxMachineRemote::midi_size() {
2825     return midi_controller_map.size();
2826 }
2827 
midi_get(int n)2828 midi_controller_list& GxMachineRemote::midi_get(int n) {
2829     return midi_controller_map[n];
2830 }
2831 
midi_deleteParameter(Parameter & param)2832 void GxMachineRemote::midi_deleteParameter(Parameter& param) {
2833     START_NOTIFY(midi_deleteParameter);
2834     jw->write(param.id());
2835     SEND();
2836 }
2837 
midi_set_current_control(int v)2838 void GxMachineRemote::midi_set_current_control(int v) {
2839     START_NOTIFY(midi_set_current_control);
2840     jw->write(v);
2841     SEND();
2842 }
2843 
midi_modifyCurrent(Parameter & param,float lower,float upper,bool toggle,int toggle_behaviour)2844 void GxMachineRemote::midi_modifyCurrent(Parameter& param, float lower, float upper, bool toggle, int toggle_behaviour) {
2845     START_NOTIFY(midi_modifyCurrent);
2846     jw->write(param.id());
2847     jw->write(lower);
2848     jw->write(upper);
2849     jw->write(toggle);
2850     jw->write(toggle_behaviour);
2851     SEND();
2852 }
2853 
midi_param2controller(Parameter & param,const MidiController ** p)2854 int GxMachineRemote::midi_param2controller(Parameter& param, const MidiController** p) {
2855     return midi_controller_map.param2controller(param, p);
2856 }
2857 
set_midi_channel(int s)2858 void GxMachineRemote::set_midi_channel(int s) {
2859     START_NOTIFY(set_midi_channel);
2860     jw->write(s);
2861     SEND();
2862 }
2863 
midi_get_last_controller_value(int ctl)2864 int GxMachineRemote::midi_get_last_controller_value(int ctl) {
2865     START_CALL(get_last_midi_control_value);
2866     jw->write(ctl);
2867     START_RECEIVE(false);
2868     jp->next(gx_system::JsonParser::begin_object);
2869     jp->next(gx_system::JsonParser::value_number);
2870     return jp->current_value_int();
2871     END_RECEIVE(return false);
2872 
2873 }
2874 
midi_set_last_controller_value(int ctl,int v)2875 void GxMachineRemote::midi_set_last_controller_value(int ctl, int v) {
2876     START_NOTIFY(set_last_midi_control_value);
2877     jw->write(ctl);
2878     jw->write(v);
2879     SEND();
2880 
2881 }
2882 
midi_feedback(int c,int v)2883 void GxMachineRemote::midi_feedback(int c, int v) {
2884 #ifdef USE_MIDI_CC_OUT
2885     if (options.system_midiout) {
2886         // Don't send midi feedback for bpm / jack_transport and not on/off events
2887         if ( c !=22 && c != 24 && c < 128) {
2888             msend_midi_cc(0xB0, c,v, 3);
2889         }
2890     }
2891 #endif
2892 }
2893 
get_midi_feedback()2894 bool GxMachineRemote::get_midi_feedback() {
2895     START_CALL(get_midi_feedback);
2896     START_RECEIVE(false);
2897     jp->next(gx_system::JsonParser::begin_object);
2898     jp->next(gx_system::JsonParser::value_number);
2899     return jp->current_value_int();
2900     END_RECEIVE(return false);
2901 
2902 }
2903 
set_midi_feedback(int v)2904 void GxMachineRemote::set_midi_feedback(int v) {
2905     START_NOTIFY(set_midi_feedback);
2906     jw->write(v);
2907     SEND();
2908 }
2909 
2910 // Convolver
2911 
reload_impresp_list(const std::string & path)2912 void GxMachineRemote::reload_impresp_list(const std::string& path) {
2913     START_NOTIFY(reload_impresp_list);
2914     jw->write(path);
2915     SEND();
2916 }
2917 
load_impresp_dirs(std::vector<gx_system::FileName> & dirs)2918 void GxMachineRemote::load_impresp_dirs(std::vector<gx_system::FileName>& dirs) {
2919     START_CALL(load_impresp_dirs);
2920     START_RECEIVE();
2921     jp->next(gx_system::JsonParser::begin_array);
2922     while (jp->peek() != gx_system::JsonParser::end_array) {
2923 	jp->next(gx_system::JsonParser::begin_array);
2924 	jp->next(gx_system::JsonParser::value_string);
2925 	std::string filename = jp->current_value();
2926 	jp->next(gx_system::JsonParser::value_string);
2927 	dirs.push_back(gx_system::FileName(filename, jp->current_value()));
2928 	jp->next(gx_system::JsonParser::end_array);
2929     }
2930     jp->next(gx_system::JsonParser::end_array);
2931     END_RECEIVE();
2932 }
2933 
read_audio(const std::string & filename,unsigned int * audio_size,int * audio_chan,int * audio_type,int * audio_form,int * audio_rate,float ** buffer)2934 bool GxMachineRemote::read_audio(const std::string& filename, unsigned int *audio_size, int *audio_chan,
2935 				 int *audio_type, int *audio_form, int *audio_rate, float **buffer) {
2936     START_CALL(read_audio);
2937     jw->write(filename);
2938     START_RECEIVE(false);
2939     if (jp->peek() != gx_system::JsonParser::begin_array) {
2940 	*audio_size = 0;
2941 	*audio_chan = *audio_type = *audio_form = *audio_rate = 0;
2942 	*buffer = 0;
2943         return false;
2944     }
2945     jp->next(gx_system::JsonParser::begin_array);
2946     jp->next(gx_system::JsonParser::value_number);
2947     *audio_size = jp->current_value_int();
2948     jp->next(gx_system::JsonParser::value_number);
2949     *audio_chan = jp->current_value_int();
2950     jp->next(gx_system::JsonParser::value_number);
2951     *audio_type = jp->current_value_int();
2952     jp->next(gx_system::JsonParser::value_number);
2953     *audio_form = jp->current_value_int();
2954     jp->next(gx_system::JsonParser::value_number);
2955     *audio_rate = jp->current_value_int();
2956     jp->next(gx_system::JsonParser::begin_array);
2957     *buffer = new float[*audio_size * *audio_chan];
2958     float *p = *buffer;
2959     while (jp->peek() != gx_system::JsonParser::end_array) {
2960 	jp->next(gx_system::JsonParser::value_number);
2961 	*p++ = jp->current_value_float();
2962     }
2963     jp->next(gx_system::JsonParser::end_array);
2964     jp->next(gx_system::JsonParser::end_array);
2965     return true;
2966     END_RECEIVE(return false);
2967 }
2968 
2969 } // namespace gx_engine
2970