32 #define SCHED_IDLE SCHED_OTHER // non-linux systems
53 rack_units(rack_units_) {
60 void PresetIO::clear() {
66 bool PresetIO::midi_in_preset() {
67 const char *i =
"system.midi_in_preset";
69 return param[i].getBool().get_value();
78 if (i->second->isInPreset() && i->second->isSavable()) {
79 i->second->stdJSON_value();
80 plist.push_back(i->second);
83 read_intern(jp, 0, head);
87 assert(param.
hasId(
"jconv.wet_dry"));
92 if (param.
hasId(
"jconv.wet_dry")) {
101 static std::string replaced_id(
const std::string& s) {
102 const char *old_new[][2] = {
103 {
"beat_detector.stepper",
"midi_out.beat_detector.stepper" },
104 {
"beat_detector.note_off",
"midi_out.beat_detector.note_off" },
105 {
"beat_detector.atack_gain",
"midi_out.beat_detector.atack_gain" },
106 {
"beat_detector.beat_gain",
"midi_out.beat_detector.beat_gain" },
107 {
"beat_detector.midi_gain",
"midi_out.beat_detector.midi_gain" },
110 {
"ui.3 Band EQ",
"ui.tonemodul" },
111 {
"ui.BiQuad Filter",
"ui.biquad" },
112 {
"ui.Cabinet",
"ui.cab" },
113 {
"ui.Preamp",
"ui.pre" },
114 {
"ui.Chorus",
"ui.chorus" },
115 {
"ui.Chorus Mono",
"ui.chorus_mono" },
116 {
"ui.Compressor",
"ui.compressor" },
117 {
"ui.Convolver",
"ui.jconv" },
118 {
"ui.Crybaby",
"ui.crybaby" },
119 {
"ui.Delay",
"ui.delay" },
120 {
"ui.Echo",
"ui.echo" },
121 {
"ui.Feedback",
"ui.feedback" },
122 {
"ui.Flanger",
"ui.flanger" },
123 {
"ui.Flanger Mono",
"ui.flanger_mono" },
124 {
"ui.Freeverb",
"ui.freeverb" },
125 {
"ui.ImpulseResponse",
"ui.IR" },
126 {
"ui.Midi Out",
"ui.midi_out" },
127 {
"ui.Moog Filter",
"ui.moog" },
128 {
"ui.Multi Band Distortion",
"ui.gx_distortion" },
129 {
"ui.Oscilloscope",
"ui.oscilloscope" },
130 {
"ui.Overdrive",
"ui.overdrive" },
131 {
"ui.Phaser",
"ui.phaser" },
132 {
"ui.Phaser Mono",
"ui.phaser_mono" },
133 {
"ui.Postamp",
"ui.ampmodul" },
134 {
"ui.Scaleable EQ",
"ui.eqs" },
135 {
"ui.Stereo Delay",
"ui.stereodelay" },
136 {
"ui.Stereo Echo",
"ui.stereoecho" },
137 {
"ui.Stereo Verb",
"ui.stereoverb" },
138 {
"ui.Tonestack",
"ui.amp.tonestack" },
139 {
"ui.Tremolo",
"ui.tremolo" },
140 {
"ui.Vibe",
"ui.univibe" },
141 {
"ui.Vibe Mono",
"ui.univibe_mono" },
142 {
"ui.Zita Rev1",
"ui.zita_rev1" },
143 {
"ui.abGate",
"ui.abgate" },
144 {
"ui.low high pass",
"ui.low_highpass" },
145 {
"Rev.Rocket.s_h",
"rev_rocket.s_h"},
146 {
"Rev.Rocket.position",
"rev_rocket.position"},
147 {
"Rev.Rocket.pp",
"rev_rocket.pp"},
148 {
"ui.Rev.Rocket",
"ui.rev_rocket"},
151 for (
const char *(*p)[2] = old_new; (*p)[0]; ++p) {
170 weight(position - 1000 * pp) {
174 std::vector<UnitPositionID> v;
175 for (std::map<std::string,UnitPosition>::iterator i = m.begin(); i != m.end(); ++i) {
176 if (i->first ==
"jconv" && i->second.position < 0) {
177 i->second.position = 99;
181 param[i->first+
".position"].readJSON_value(jp);
183 if (i->first ==
"cab") {
184 if (i->second.position < 0) {
185 i->second.position = 98;
189 param[i->first+
".position"].readJSON_value(jp);
191 if (i->second.pp < 0) {
196 param[i->first+
".pp"].readJSON_value(jp);
199 if (i->second.position >= 0 && i->second.show) {
200 if ((stereo && i->second.pp < 0) || (!stereo && i->second.pp >= 0)) {
201 if (!i->second.visible) {
202 i->second.visible =
true;
206 param[
"ui."+i->first].readJSON_value(jp);
213 std::sort(v.begin(), v.end());
215 for (std::vector<UnitPositionID>::iterator j = v.begin(); j != v.end(); ++j) {
216 if (!stereo && j->pp != pp) {
218 l.push_back(
"ampstack");
223 l.push_back(
"ampstack");
236 if (s ==
"system.mainwin_x") {
241 if (s ==
"system.mainwin_y") {
246 if (s ==
"system.mainwin_height") {
251 if (s ==
"system.mainwin_rack_height") {
256 if (s ==
"system.preset_window_height") {
261 if (s ==
"oscilloscope.bufferset") {
266 if (s ==
"ui.skin_name") {
271 if (s ==
"ui.latency_nowarn") {
276 if (s ==
"system.order_rack_h") {
281 if (s ==
"system.show_value") {
286 if (s ==
"system.show_tooltips") {
291 if (s ==
"system.animations") {
296 if (s ==
"system.show_presets") {
301 if (s ==
"system.show_toolbar") {
306 if (s ==
"system.show_rack") {
315 static inline bool endswith(
const std::string& s,
int n,
const char *t) {
316 return s.compare(std::max<int>(0, s.size()-n), n, t) == 0;
319 static inline bool startswith(
const std::string& s,
int n,
const char *t) {
320 return s.compare(0, n, t) == 0;
324 const std::string& s = p->
id();
325 if (startswith(s, 3,
"ui.")) {
327 std::string ss = s.substr(3);
328 u.set_visible(ss,
true);
329 u.set_show(ss,
true);
331 }
else if (endswith(s, 7,
".on_off")) {
333 u.set_show(s.substr(0, s.size()-7),
true);
335 }
else if (endswith(s, 9,
".position")) {
337 }
else if (endswith(s, 3,
".pp")) {
338 u.set_pp(s.substr(0, s.size()-3), (jp.
current_value() ==
"pre" ? 1 : 0));
349 if (convert_old(jp)) {
355 _(
"recall settings"),
366 _(
"recall settings"),
367 _(
"preset-parameter ")+p->
id()+_(
" in settings"));
372 _(
"recall settings"),
373 _(
"non preset-parameter ")+p->
id()+_(
" in preset"));
378 _(
"recall settings"),
379 _(
"non saveable parameter ")+p->
id()+_(
" in settings"));
383 if (p->
id() ==
"amp2.stage1.Pregain" || p->
id() ==
"gxdistortion.drive") {
389 collectRackOrder(p, jp, u);
392 u.get_list(rack_units.
mono,
false, param);
393 u.get_list(rack_units.
stereo,
true, param);
401 for (std::vector<std::string>::iterator j = mono_rack_units.begin(); j != mono_rack_units.end(); ++j) {
402 if (*j ==
"ampstack") {
416 i != param.
end(); ++i) {
437 if (!is.fail() && !os.fail()) {
448 jp.
read_kv(
"description", INFO_);
453 INFO_ +=
"Author : " + AUTHOR_;
455 os <<
"\n<<NAME>> \n" << NAME_ <<
"\n<<FILE>> \n" << FILE_ <<
"\n<<INFO>> \n" << INFO_ <<
"\n<<END>> \n" <<
"\n";
464 cerr <<
"JsonException: " << e.
what() <<
": '" << jp.
current_value() <<
"'" << endl;
475 bool use_midi = (has_midi != 0) || midi_in_preset();
483 read_parameters(jp,
true);
485 dynamic_cast<gx_engine::JConvParameter*>(¶m[
"jconv.convolver"])->readJSON_value(jp);
487 dynamic_cast<gx_engine::SeqParameter*>(¶m[
"seq.sequencer"])->readJSON_value(jp);
501 _(
"recall settings"),
507 fixup_parameters(head);
511 for (gx_engine::paramlist::iterator i = plist.begin(); i != plist.end(); ++i) {
512 (*i)->setJSON_value();
524 write_parameters(w,
true);
534 write_intern(jw, midi_in_preset());
539 param.set_init_values();
542 read_intern(jp, &has_midi, head);
544 write_intern(jw, has_midi);
555 :
PresetIO(mctrl, cvr, param, opt_, rack_units),
556 midi_std_control(mstdctr),
566 if (i->second->isSavable()) {
567 i->second->stdJSON_value();
568 plist.push_back(i->second);
574 read_parameters(jp,
false);
576 read_intern(jp, 0, head);
579 m->readJSON(jp, param);
586 _(
"recall settings"),
598 jw.
write(
"settings");
599 write_parameters(jw,
false);
601 jw.
write(
"midi_controller");
604 jw.
write(
"midi_ctrl_names");
608 jw.
write(
"current_preset");
609 write_intern(jw,
false);
612 jw.
write(
"jack_connections");
625 : filename(fname), pmap(pmap_), mctrl(mctrl_), is(), jp(&is) {
630 is.open(filename.c_str());
667 _(
"recall plugin settings"),
721 for (gx_engine::paramlist::iterator i = plist.begin(); i != plist.end(); ++i) {
722 (*i)->setJSON_value();
727 static const int GX_PLUGIN_VERSION = 1;
729 static inline bool compare_groups(
const std::string&
id,
const char **groups) {
733 for (
const char **g = groups; *g; g += 2) {
740 if (strncmp(
id.c_str(), p, n) == 0 &&
id[n] ==
'.') {
747 void PluginPresetList::write_values(
gx_system::JsonWriter& jw, std::string
id,
const char **groups) {
749 string on_off =
id +
"on_off";
750 string pp =
id +
"pp";
751 std::string position =
id +
"position";
754 if (i->first.compare(0,
id.size(), id) == 0 || compare_groups(i->first, groups)) {
755 if (i->second->isInPreset() && i->second->isSavable()) {
756 if (i->first != on_off && i->first != pp && i->first != position) {
757 i->second->writeJSON(jw);
768 std::string tmpfile(filename +
"_tmp");
769 ofstream os(tmpfile.c_str());
772 jw.write(
"gx_plugin_version");
773 jw.write(GX_PLUGIN_VERSION,
true);
781 write_values(jw,
id, groups);
790 write_values(jw,
id, groups);
797 boost::format(_(
"couldn't write %1%")) % tmpfile);
800 int rc = rename(tmpfile.c_str(), filename.c_str());
803 boost::format(_(
"couldn't rename %1% to %2%"))
804 % tmpfile % filename);
815 std::string tmpfile(filename +
"_tmp");
816 ofstream os(tmpfile.c_str());
819 jw.write(
"gx_plugin_version");
820 jw.write(GX_PLUGIN_VERSION,
true);
838 boost::format(_(
"couldn't write %1%")) % tmpfile);
841 int rc = rename(tmpfile.c_str(), filename.c_str());
844 boost::format(_(
"couldn't rename %1% to %2%"))
845 % tmpfile % filename);
862 static const char *scratchpad_name =
N_(
"Scratchpad");
863 static const char *scratchpad_file =
"scratchpad.gx";
864 static const char *statename_postfix =
"_rc";
865 static const char *bank_list =
"banklist.js";
871 GxSettingsBase(seq_),
872 param(seq_.get_param()),
873 preset_io(mctrl_, cvr, param, opt, rack_units),
874 state_io(mctrl_, cvr, param, mstdctr, jack_, opt, rack_units),
880 preset_parameter(*param.reg_string(
"system.current_preset",
"?", ¤t_name,
"")),
881 bank_parameter(*param.reg_string(
"system.current_bank",
"?", ¤t_bank,
"")),
887 set_io(&state_io, &preset_io);
890 scratchpad_name, scratchpad_file);
893 sigc::mem_fun(*
this, &GxSettings::exit_handler));
895 sigc::mem_fun(*
this, &GxSettings::jack_client_changed));
896 set_preset.connect(sigc::mem_fun(*
this, &GxSettings::preset_sync_set));
897 get_sequencer_p.connect(sigc::mem_fun(*
this, &GxSettings::on_get_sequencer_pos));
922 void GxSettings::exit_handler(
bool otherthread) {
929 void GxSettings::jack_client_changed() {
930 string fn = make_state_filename();
935 if (!state_loaded && access(fn.c_str(), R_OK|W_OK) != 0) {
936 string defname = make_default_state_filename();
937 if (access(defname.c_str(), R_OK) == 0) {
946 string GxSettings::make_default_state_filename() {
953 if (access(s.c_str(), R_OK|W_OK) == 0) {
961 string GxSettings::make_state_filename() {
969 bool GxSettings::check_create_config_dir(
const Glib::ustring& dir) {
970 if (access((Glib::build_filename(dir,
".")).c_str(), R_OK|W_OK|X_OK) != 0) {
971 if (errno != ENOENT) {
973 boost::format(_(
"no read/write access in guitarix config dir '%1%'"))
976 if (mkdir(dir.c_str(), 0777) != 0) {
978 boost::format(_(
"can't create guitarix config dir '%1%'"))
990 static inline std::vector<std::string>::iterator find_unit(std::vector<std::string>& r,
const std::string& unit) {
991 std::vector<std::string>::iterator i = r.begin();
992 for (; i != r.end(); ++i) {
1001 std::vector<std::string>& r = stereo ? rack_units.
stereo : rack_units.
mono;
1002 std::vector<std::string>::iterator i = find_unit(r, unit);
1011 std::vector<std::string>& r = stereo ? rack_units.
stereo : rack_units.
mono;
1013 if (before.empty()) {
1016 r.insert(find_unit(r, before), unit);
1021 Glib::RefPtr<Gio::File> rem = Gio::File::create_for_uri(uri);
1022 filename = rem->get_basename();
1032 std::string filename;
1034 Glib::RefPtr<Gio::File> dest = Gio::File::create_for_path(filename);
1037 }
catch (Gio::Error& e) {
1048 }
catch (Gio::Error& e) {
1049 gx_print_error(e.what().c_str(), _(
"can't remove copied file!?"));
1056 }
catch (Gio::Error& e) {
1057 gx_print_error(e.what().c_str(), _(
"can't move; file has been copied"));
1065 std::string filename;
1067 Glib::RefPtr<Gio::File> dest = Gio::File::create_for_path(filename);
1069 Glib::RefPtr<Gio::FileOutputStream> s = dest->create_file();
1072 }
catch (Gio::Error& e) {
1083 }
catch (Gio::Error& e) {
1084 gx_print_error(e.what().c_str(), _(
"can't remove copied file!?"));
1092 Glib::ustring newname = name;
1093 std::string newfile;
1106 std::string newfile;
1108 return GxSettingsBase::rename_bank(oldname, newname, newfile);
1113 bool copied_from_old =
false;
1114 std::string oldpreset;
1115 *need_new_preset =
false;
1125 if (access(Glib::build_filename(opt.
get_old_user_dir(), fname).c_str(), R_OK) == 0) {
1126 copied_from_old =
true;
1127 Glib::RefPtr<Gio::File> f = Gio::File::create_for_path(
1131 }
catch (Gio::Error& e) {
1132 gx_print_error(e.what().c_str(), _(
"can't copy to new config dir"));
1135 fname = Glib::build_filename(
1138 if (access(fname.c_str(), R_OK) == 0) {
1139 Glib::RefPtr<Gio::File> f = Gio::File::create_for_path(fname);
1142 f->copy(Gio::File::create_for_path(oldpreset));
1143 }
catch (Gio::Error& e) {
1144 gx_print_error(e.what().c_str(), _(
"can't copy to new config preset dir"));
1158 if (access(fname.c_str(), R_OK) != 0) {
1161 boost::format(_(
"can't create file in '%1%' !!??")) % opt.
get_preset_dir());
1163 *need_new_preset =
true;
1166 if (access(fname.c_str(), R_OK) != 0) {
1167 ofstream f(fname.c_str());
1170 boost::format(_(
"can't create '%1%' in directory '%2%'"))
1185 return copied_from_old;
1189 GxSettingsBase::loadstate();
1216 state_loaded =
true;
1224 while (l.
next(name, &is_set)) {
1225 presetnames.push_back(PluginPresetEntry(name, is_set));
1232 add_plugin_preset_list(lv2sets, presetnames);
1234 add_plugin_preset_list(user, presetnames);
1235 presetnames.push_back(PluginPresetEntry(
"",
false));
1237 add_plugin_preset_list(factory, presetnames);
1240 void GxSettings::preset_sync_set() {
1244 void GxSettings::on_get_sequencer_pos() {
1248 void *GxSettings::sync_run() {
1260 void *GxSettings::preset_sync_run(
void *p) {
1261 struct sched_param spar;
1262 spar.sched_priority = 0;
1263 pthread_setschedparam(pthread_self(),
SCHED_IDLE, &spar);
1264 (reinterpret_cast< GxSettings*>(p))->sync_run();
1270 if(strcmp(pdef->
id,
"seq")==0) {
1274 if (pthread_create(&pthr, NULL, preset_sync_run, reinterpret_cast<void*>(
this))) {
1291 if(strcmp(pdef->
id,
"dubber")==0) {
1294 std::remove((pPath +
"1.wav").c_str());
1295 std::remove((pPath +
"2.wav").c_str());
1296 std::remove((pPath +
"3.wav").c_str());
1297 std::remove((pPath +
"4.wav").c_str());