/[svn]/gigedit/trunk/src/gigedit/Settings.cpp
ViewVC logotype

Contents of /gigedit/trunk/src/gigedit/Settings.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3157 - (show annotations) (download)
Mon May 8 17:30:10 2017 UTC (6 years, 11 months ago) by schoenebeck
File size: 12911 byte(s)
* Fixed potentially unhandled exceptions when app is loading
  its config file.
* WIP: Introduced user configurable list of macros which are
  auto assigned to keyboard accelerators (F1 ... F12) and
  saved along with the app's config file (added under new
  main menu bar section "Macro").
* Bumped version (1.0.0.svn38).

1 /*
2 Copyright (c) 2014-2017 Christian Schoenebeck
3
4 This file is part of "gigedit" and released under the terms of the
5 GNU General Public License version 2.
6 */
7
8 #include "Settings.h"
9 #include <glib.h>
10 #include "global.h"
11 #include <glibmm/keyfile.h>
12 #include <iostream>
13 #include <stdio.h>
14 #include <fstream>
15 #include <string.h>
16
17 #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 40) || GTKMM_MAJOR_VERSION < 2
18 # define HAS_GLIB_KEYFILE_SAVE_TO_FILE 0
19 #else
20 # define HAS_GLIB_KEYFILE_SAVE_TO_FILE 1
21 #endif
22
23 static std::string configDir() {
24 //printf("configDir '%s'\n", g_get_user_config_dir());
25 return g_get_user_config_dir();
26 }
27
28 static std::string dirSep() {
29 //printf("sep '%s'\n", G_DIR_SEPARATOR_S);
30 return G_DIR_SEPARATOR_S;
31 }
32
33 static std::string configFile() {
34 return configDir() + dirSep() + "gigedit.conf";
35 }
36
37 static std::string groupName(Settings::Group_t group) {
38 switch (group) {
39 case Settings::GLOBAL: return "Global";
40 case Settings::MAIN_WINDOW: return "MainWindow";
41 case Settings::SCRIPT_EDITOR: return "ScriptEditor";
42 case Settings::DIMENSION_MANAGER: return "DimensionManager";
43 case Settings::SCRIPT_SLOTS: return "ScriptSlots";
44 case Settings::COMBINE_INSTRUMENTS: return "CombineInstruments";
45 case Settings::MIDI_RULES: return "MidiRules";
46 case Settings::FILE_PROPS: return "FileProps";
47 case Settings::INSTR_PROPS: return "InstrProps";
48 case Settings::SAMPLE_REFS: return "SampleRefs";
49 case Settings::MACRO_EDITOR: return "MacroEditor";
50 case Settings::MACROS_SETUP: return "MacrosSetup";
51 case Settings::MACROS: return "Macros";
52 }
53 return "Global";
54 }
55
56 #if !HAS_GLIB_KEYFILE_SAVE_TO_FILE
57
58 static bool saveToFile(Glib::KeyFile* keyfile, std::string filename) {
59 Glib::ustring s = keyfile->to_data();
60 std::ofstream out;
61 out.open(filename.c_str(), std::ios_base::out | std::ios_base::trunc);
62 out << s;
63 out.close();
64 return true;
65 }
66
67 #endif // ! HAS_GLIB_KEYFILE_SAVE_TO_FILE
68
69 static Settings* _instance = NULL;
70
71 Settings* Settings::singleton() {
72 if (!_instance) {
73 _instance = new Settings;
74 _instance->load();
75 }
76 return _instance;
77 }
78
79 Settings::Settings() : Glib::ObjectBase(typeid(Settings)),
80 warnUserOnExtensions(*this, GLOBAL, "warnUserOnExtensions", true),
81 syncSamplerInstrumentSelection(*this, GLOBAL, "syncSamplerInstrumentSelection", true),
82 moveRootNoteWithRegionMoved(*this, GLOBAL, "moveRootNoteWithRegionMoved", true),
83 autoRestoreWindowDimension(*this, GLOBAL, "autoRestoreWindowDimension", false),
84 saveWithTemporaryFile(*this, GLOBAL, "saveWithTemporaryFile", false),
85 mainWindowX(*this, MAIN_WINDOW, "x", -1),
86 mainWindowY(*this, MAIN_WINDOW, "y", -1),
87 mainWindowW(*this, MAIN_WINDOW, "w", -1),
88 mainWindowH(*this, MAIN_WINDOW, "h", -1),
89 scriptEditorWindowX(*this, SCRIPT_EDITOR, "x", -1),
90 scriptEditorWindowY(*this, SCRIPT_EDITOR, "y", -1),
91 scriptEditorWindowW(*this, SCRIPT_EDITOR, "w", -1),
92 scriptEditorWindowH(*this, SCRIPT_EDITOR, "h", -1),
93 scriptEditorFontSize(*this, SCRIPT_EDITOR, "fontSize", -1),
94 dimensionManagerWindowX(*this, DIMENSION_MANAGER, "x", -1),
95 dimensionManagerWindowY(*this, DIMENSION_MANAGER, "y", -1),
96 dimensionManagerWindowW(*this, DIMENSION_MANAGER, "w", -1),
97 dimensionManagerWindowH(*this, DIMENSION_MANAGER, "h", -1),
98 scriptSlotsWindowX(*this, SCRIPT_SLOTS, "x", -1),
99 scriptSlotsWindowY(*this, SCRIPT_SLOTS, "y", -1),
100 scriptSlotsWindowW(*this, SCRIPT_SLOTS, "w", -1),
101 scriptSlotsWindowH(*this, SCRIPT_SLOTS, "h", -1),
102 combineInstrumentsWindowX(*this, COMBINE_INSTRUMENTS, "x", -1),
103 combineInstrumentsWindowY(*this, COMBINE_INSTRUMENTS, "y", -1),
104 combineInstrumentsWindowW(*this, COMBINE_INSTRUMENTS, "w", -1),
105 combineInstrumentsWindowH(*this, COMBINE_INSTRUMENTS, "h", -1),
106 midiRulesWindowX(*this, MIDI_RULES, "x", -1),
107 midiRulesWindowY(*this, MIDI_RULES, "y", -1),
108 midiRulesWindowW(*this, MIDI_RULES, "w", -1),
109 midiRulesWindowH(*this, MIDI_RULES, "h", -1),
110 filePropsWindowX(*this, FILE_PROPS, "x", -1),
111 filePropsWindowY(*this, FILE_PROPS, "y", -1),
112 filePropsWindowW(*this, FILE_PROPS, "w", -1),
113 filePropsWindowH(*this, FILE_PROPS, "h", -1),
114 instrPropsWindowX(*this, INSTR_PROPS, "x", -1),
115 instrPropsWindowY(*this, INSTR_PROPS, "y", -1),
116 instrPropsWindowW(*this, INSTR_PROPS, "w", -1),
117 instrPropsWindowH(*this, INSTR_PROPS, "h", -1),
118 sampleRefsWindowX(*this, SAMPLE_REFS, "x", -1),
119 sampleRefsWindowY(*this, SAMPLE_REFS, "y", -1),
120 sampleRefsWindowW(*this, SAMPLE_REFS, "w", -1),
121 sampleRefsWindowH(*this, SAMPLE_REFS, "h", -1),
122 macroEditorWindowX(*this, MACRO_EDITOR, "x", -1),
123 macroEditorWindowY(*this, MACRO_EDITOR, "y", -1),
124 macroEditorWindowW(*this, MACRO_EDITOR, "w", -1),
125 macroEditorWindowH(*this, MACRO_EDITOR, "h", -1),
126 macrosSetupWindowX(*this, MACROS_SETUP, "x", -1),
127 macrosSetupWindowY(*this, MACROS_SETUP, "y", -1),
128 macrosSetupWindowW(*this, MACROS_SETUP, "w", -1),
129 macrosSetupWindowH(*this, MACROS_SETUP, "h", -1),
130 m_ignoreNotifies(false)
131 {
132 m_boolProps.push_back(&warnUserOnExtensions);
133 m_boolProps.push_back(&syncSamplerInstrumentSelection);
134 m_boolProps.push_back(&moveRootNoteWithRegionMoved);
135 m_boolProps.push_back(&autoRestoreWindowDimension);
136 m_boolProps.push_back(&saveWithTemporaryFile);
137 m_intProps.push_back(&mainWindowX);
138 m_intProps.push_back(&mainWindowY);
139 m_intProps.push_back(&mainWindowW);
140 m_intProps.push_back(&mainWindowH);
141 m_intProps.push_back(&scriptEditorWindowX);
142 m_intProps.push_back(&scriptEditorWindowY);
143 m_intProps.push_back(&scriptEditorWindowW);
144 m_intProps.push_back(&scriptEditorWindowH);
145 m_intProps.push_back(&scriptEditorFontSize);
146 m_intProps.push_back(&dimensionManagerWindowX);
147 m_intProps.push_back(&dimensionManagerWindowY);
148 m_intProps.push_back(&dimensionManagerWindowW);
149 m_intProps.push_back(&dimensionManagerWindowH);
150 m_intProps.push_back(&scriptSlotsWindowX);
151 m_intProps.push_back(&scriptSlotsWindowY);
152 m_intProps.push_back(&scriptSlotsWindowW);
153 m_intProps.push_back(&scriptSlotsWindowH);
154 m_intProps.push_back(&combineInstrumentsWindowX);
155 m_intProps.push_back(&combineInstrumentsWindowY);
156 m_intProps.push_back(&combineInstrumentsWindowW);
157 m_intProps.push_back(&combineInstrumentsWindowH);
158 m_intProps.push_back(&midiRulesWindowX);
159 m_intProps.push_back(&midiRulesWindowY);
160 m_intProps.push_back(&midiRulesWindowW);
161 m_intProps.push_back(&midiRulesWindowH);
162 m_intProps.push_back(&filePropsWindowX);
163 m_intProps.push_back(&filePropsWindowY);
164 m_intProps.push_back(&filePropsWindowW);
165 m_intProps.push_back(&filePropsWindowH);
166 m_intProps.push_back(&instrPropsWindowX);
167 m_intProps.push_back(&instrPropsWindowY);
168 m_intProps.push_back(&instrPropsWindowW);
169 m_intProps.push_back(&instrPropsWindowH);
170 m_intProps.push_back(&sampleRefsWindowX);
171 m_intProps.push_back(&sampleRefsWindowY);
172 m_intProps.push_back(&sampleRefsWindowW);
173 m_intProps.push_back(&sampleRefsWindowH);
174 m_intProps.push_back(&macroEditorWindowX);
175 m_intProps.push_back(&macroEditorWindowY);
176 m_intProps.push_back(&macroEditorWindowW);
177 m_intProps.push_back(&macroEditorWindowH);
178 m_intProps.push_back(&macrosSetupWindowX);
179 m_intProps.push_back(&macrosSetupWindowY);
180 m_intProps.push_back(&macrosSetupWindowW);
181 m_intProps.push_back(&macrosSetupWindowH);
182 }
183
184 void Settings::onPropertyChanged(Glib::PropertyBase* pProperty, RawValueType_t type, Group_t group) {
185 if (m_ignoreNotifies) return;
186
187 //printf("Settings::onPropertyChanged(%s)\n", pProperty->get_name().c_str());
188
189 Glib::KeyFile file;
190 try {
191 bool ok = file.load_from_file(configFile());
192 if (!ok) {
193 std::cerr << "Could not load '" << configFile() << "'\n" << std::flush;
194 }
195 } catch (...) {
196 std::cerr << "Could not load '" << configFile() << "'\n" << std::flush;
197 }
198
199 switch (type) {
200 case BOOLEAN: {
201 Property<bool>* prop = static_cast<Property<bool>*>(pProperty);
202 //std::cout << "Saving bool setting '" << prop->get_name() << "'\n" << std::flush;
203 file.set_boolean(groupName(prop->group()), prop->get_name(), prop->get_value());
204 break;
205 }
206 case INTEGER: {
207 Property<int>* prop = static_cast<Property<int>*>(pProperty);
208 //std::cout << "Saving int setting '" << prop->get_name() << "'\n" << std::flush;
209 file.set_integer(groupName(prop->group()), prop->get_name(), prop->get_value());
210 break;
211 }
212 case UNKNOWN:
213 std::cerr << "BUG: Unknown setting raw type of property '" << pProperty->get_name() << "'\n" << std::flush;
214 return;
215 }
216
217 try {
218 #if HAS_GLIB_KEYFILE_SAVE_TO_FILE
219 bool ok = file.save_to_file(configFile());
220 #else
221 bool ok = saveToFile(&file, configFile());
222 #endif
223 if (!ok) {
224 std::cerr << "Failed saving gigedit config to '" << configFile() << "'\n" << std::flush;
225 } else {
226 //std::cout <<"gigedit CONFIG SAVED\n";
227 }
228 } catch (...) {
229 std::cerr << "Failed saving gigedit config to '" << configFile() << "'\n" << std::flush;
230 }
231 }
232
233 void Settings::load() {
234 Glib::KeyFile file;
235 try {
236 bool ok = file.load_from_file(configFile());
237 if (!ok) return;
238 } catch (...) {
239 std::cerr << "Could not load gigedit config file '" << configFile() << "'\n" << std::flush;
240 return;
241 }
242
243 // ignore onPropertyChanged() calls during updating the property values below
244 m_ignoreNotifies = true;
245
246 for (int i = 0; i < m_boolProps.size(); ++i) {
247 Property<bool>* prop = static_cast<Property<bool>*>(m_boolProps[i]);
248 try {
249 const std::string group = groupName(prop->group());
250 if (!file.has_group(group)) continue;
251 if (!file.has_key(group, prop->get_name())) continue;
252 const bool value = file.get_boolean(group, prop->get_name());
253 prop->set_value(value);
254 } catch (...) {
255 continue;
256 }
257 }
258
259 for (int i = 0; i < m_intProps.size(); ++i) {
260 Property<int>* prop = static_cast<Property<int>*>(m_intProps[i]);
261 try {
262 const std::string group = groupName(prop->group());
263 if (!file.has_group(group)) continue;
264 if (!file.has_key(group, prop->get_name())) continue;
265 const int value = file.get_integer(group, prop->get_name());
266 prop->set_value(value);
267 } catch (...) {
268 continue;
269 }
270 }
271
272 m_ignoreNotifies = false;
273 }
274
275 #define MACRO_LIST_NAME "srlzl"
276
277 void Settings::loadMacros(std::vector<Serialization::Archive>& macros) {
278 const std::string group = groupName(MACROS);
279 macros.clear();
280 Glib::KeyFile file;
281 try {
282 bool ok = file.load_from_file(configFile());
283 if (!ok) return;
284 } catch (...) {
285 std::cerr << "Could not load gigedit config file '" << configFile() << "'\n" << std::flush;
286 return;
287 }
288 if (!file.has_group(group)) return;
289 if (!file.has_key(group, MACRO_LIST_NAME))
290 return;
291 std::vector<Glib::ustring> v = file.get_string_list(group, MACRO_LIST_NAME);
292 for (int i = 0; i < v.size(); ++i) {
293 Serialization::Archive macro;
294 macro.decode((const uint8_t*)v[i].c_str(), v[i].length());
295 macros.push_back(macro);
296 }
297 }
298
299 void Settings::saveMacros(const std::vector<Serialization::Archive>& macros) {
300 const std::string group = groupName(MACROS);
301 Glib::KeyFile file;
302 try {
303 bool ok = file.load_from_file(configFile());
304 if (!ok) {
305 std::cerr << "Could not load '" << configFile() << "'\n" << std::flush;
306 }
307 } catch (...) {
308 std::cerr << "Could not load '" << configFile() << "'\n" << std::flush;
309 return;
310 }
311
312 std::vector<Glib::ustring> v;
313 for (int i = 0; i < macros.size(); ++i) {
314 const Serialization::RawData& rawData = const_cast<Serialization::Archive&>(macros[i]).rawData();
315 std::string s((const char*)&rawData[0], rawData.size());
316 v.push_back(s);
317 }
318
319 file.set_string_list(group, MACRO_LIST_NAME, v);
320
321 try {
322 #if HAS_GLIB_KEYFILE_SAVE_TO_FILE
323 bool ok = file.save_to_file(configFile());
324 #else
325 bool ok = saveToFile(&file, configFile());
326 #endif
327 if (!ok) {
328 std::cerr << "Failed saving gigedit config to '" << configFile() << "'\n" << std::flush;
329 } else {
330 //std::cout <<"gigedit CONFIG SAVED\n";
331 }
332 } catch (...) {
333 std::cerr << "Failed saving gigedit config to '" << configFile() << "'\n" << std::flush;
334 }
335
336 }

  ViewVC Help
Powered by ViewVC