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