Config.cpp (17190B)
1 /* 2 ZynAddSubFX - a software synthesizer 3 4 Config.cpp - Configuration file functions 5 Copyright (C) 2003-2005 Nasca Octavian Paul 6 Author: Nasca Octavian Paul 7 8 This program is free software; you can redistribute it and/or 9 modify it under the terms of the GNU General Public License 10 as published by the Free Software Foundation; either version 2 11 of the License, or (at your option) any later version. 12 */ 13 #include <cstdio> 14 #include <cmath> 15 #include <cstdlib> 16 #include <cstring> 17 18 #include <rtosc/ports.h> 19 #include <rtosc/port-sugar.h> 20 21 #include "Config.h" 22 #include "../globals.h" 23 #include "XMLwrapper.h" 24 25 namespace zyn { 26 27 #define rStdString(name, len, ...) \ 28 {STRINGIFY(name) "::s", rMap(length, len) rProp(parameter) DOC(__VA_ARGS__), NULL, rStringCb(name,len)} 29 #define rStdStringCb(name, length) rBOIL_BEGIN \ 30 if(!strcmp("", args)) {\ 31 data.reply(loc, "s", obj->name); \ 32 } else { \ 33 fast_strcpy(obj->name, rtosc_argument(msg, 0).s, length); \ 34 data.broadcast(loc, "s", obj->name);\ 35 rChangeCb \ 36 } rBOIL_END 37 38 39 40 41 #if 1 42 #define rObject Config 43 static const rtosc::Ports ports = { 44 //rString(cfg.LinuxOSSWaveOutDev), 45 //rString(cfg.LinuxOSSSeqInDev), 46 rParamI(cfg.SampleRate, "samples of audio per second"), 47 rParamI(cfg.SoundBufferSize, "Size of processed audio buffer"), 48 rParamI(cfg.OscilSize, "Size Of Oscillator Wavetable"), 49 rToggle(cfg.SwapStereo, "Swap Left And Right Channels"), 50 rToggle(cfg.AudioOutputCompressor, "Apply Compressor to Audio Output"), 51 rToggle(cfg.BankUIAutoClose, "Automatic Closing of BackUI After Patch Selection"), 52 rParamI(cfg.GzipCompression, "Level of Gzip Compression For Save Files"), 53 rParamI(cfg.Interpolation, "Level of Interpolation, Linear/Cubic"), 54 rToggle(cfg.SaveFullXml, "Include Disabled parts in save"), 55 {"cfg.presetsDirList", rDoc("list of preset search directories"), 0, 56 [](const char *msg, rtosc::RtData &d) 57 { 58 Config &c = *(Config*)d.obj; 59 if(rtosc_narguments(msg) != 0) { 60 std::string args = rtosc_argument_string(msg); 61 62 //clear everything 63 c.clearpresetsdirlist(); 64 for(int i=0; i<(int)args.size(); ++i) 65 if(args[i] == 's') 66 c.cfg.presetsDirList[i] = rtosc_argument(msg, i).s; 67 } 68 69 char types[MAX_BANK_ROOT_DIRS+1]; 70 rtosc_arg_t args[MAX_BANK_ROOT_DIRS]; 71 size_t pos = 0; 72 73 //zero out data 74 memset(types, 0, sizeof(types)); 75 memset(args, 0, sizeof(args)); 76 77 for(int i=0; i<MAX_BANK_ROOT_DIRS; ++i) { 78 if(!c.cfg.presetsDirList[i].empty()) { 79 types[pos] = 's'; 80 args[pos].s = c.cfg.presetsDirList[i].c_str(); 81 pos++; 82 } 83 } 84 char buffer[1024*5]; 85 rtosc_amessage(buffer, sizeof(buffer), d.loc, types, args); 86 d.reply(buffer); 87 }}, 88 {"cfg.bankRootDirList", rDoc("list of bank search directories"), 0, 89 [](const char *msg, rtosc::RtData &d) 90 { 91 Config &c = *(Config*)d.obj; 92 if(rtosc_narguments(msg) != 0) { 93 std::string args = rtosc_argument_string(msg); 94 95 //clear everything 96 c.clearbankrootdirlist(); 97 for(int i=0; i<(int)args.size(); ++i) 98 if(args[i] == 's') 99 c.cfg.bankRootDirList[i] = rtosc_argument(msg, i).s; 100 } 101 102 char types[MAX_BANK_ROOT_DIRS+1]; 103 rtosc_arg_t args[MAX_BANK_ROOT_DIRS]; 104 size_t pos = 0; 105 106 //zero out data 107 memset(types, 0, sizeof(types)); 108 memset(args, 0, sizeof(args)); 109 110 for(int i=0; i<MAX_BANK_ROOT_DIRS; ++i) { 111 if(!c.cfg.bankRootDirList[i].empty()) { 112 types[pos] = 's'; 113 args[pos].s = c.cfg.bankRootDirList[i].c_str(); 114 pos++; 115 } 116 } 117 char buffer[1024*5]; 118 rtosc_amessage(buffer, sizeof(buffer), d.loc, types, args); 119 d.reply(buffer); 120 }}, 121 122 //rArrayS(cfg.bankRootDirList,MAX_BANK_ROOT_DIRS), 123 //rString(cfg.currentBankDir), 124 //rArrayS(cfg.presetsDirList,MAX_BANK_ROOT_DIRS), 125 rToggle(cfg.CheckPADsynth, "Old Check For PADsynth functionality within a patch"), 126 rToggle(cfg.IgnoreProgramChange, "Ignore MIDI Program Change Events"), 127 rParamI(cfg.UserInterfaceMode, "Beginner/Advanced Mode Select"), 128 rParamI(cfg.VirKeybLayout, "Keyboard Layout For Virtual Piano Keyboard"), 129 //rParamS(cfg.LinuxALSAaudioDev), 130 //rParamS(cfg.nameTag) 131 {"cfg.OscilPower::i", rProp(parameter) rDoc("Size Of Oscillator Wavetable"), 0, 132 [](const char *msg, rtosc::RtData &d) 133 { 134 Config &c = *(Config*)d.obj; 135 if(rtosc_narguments(msg) == 0) { 136 d.reply(d.loc, "i", (int)(log(c.cfg.OscilSize*1.0)/log(2.0))); 137 return; 138 } 139 float val = powf(2.0, rtosc_argument(msg, 0).i); 140 c.cfg.OscilSize = val; 141 d.broadcast(d.loc, "i", (int)(log(c.cfg.OscilSize*1.0)/log(2.0))); 142 }}, 143 {"clear-favorites:", rDoc("Clear favorite directories"), 0, 144 [](const char *, rtosc::RtData &d) { 145 Config &c = *(Config*)d.obj; 146 for(int i=0; i<MAX_BANK_ROOT_DIRS; ++i) 147 c.cfg.favoriteList[i] = ""; 148 }}, 149 {"add-favorite:s", rDoc("Add favorite directory"), 0, 150 [](const char *msg, rtosc::RtData &d) 151 { 152 Config &c = *(Config*)d.obj; 153 const char *path = rtosc_argument(msg, 0).s; 154 for(int i=0; i<MAX_BANK_ROOT_DIRS; ++i) { 155 if(c.cfg.favoriteList[i].empty() || c.cfg.favoriteList[i] == path) { 156 c.cfg.favoriteList[i] = path; 157 return; 158 } 159 } 160 161 }}, 162 {"favorites:", /*rProp(parameter)*/ 0, 0, 163 [](const char *, rtosc::RtData &d) 164 { 165 Config &c = *(Config*)d.obj; 166 char *argt = new char[MAX_BANK_ROOT_DIRS+1]; 167 rtosc_arg_t *args = new rtosc_arg_t[MAX_BANK_ROOT_DIRS]; 168 memset(argt, 0, MAX_BANK_ROOT_DIRS+1); 169 int j = 0; 170 for(int i=0; i<MAX_BANK_ROOT_DIRS; ++i) { 171 if(!c.cfg.favoriteList[i].empty()) { 172 argt[j] = 's'; 173 args[j].s = c.cfg.favoriteList[i].c_str(); 174 j++; 175 } 176 } 177 d.replyArray(d.loc, argt, args); 178 delete [] argt; 179 delete [] args; 180 }}, 181 }; 182 const rtosc::Ports &Config::ports = zyn::ports; 183 #endif 184 185 Config::Config() 186 { 187 init(); 188 } 189 190 void Config::init() 191 { 192 maxstringsize = MAX_STRING_SIZE; //for ui 193 //defaults 194 cfg.SampleRate = 44100; 195 cfg.SoundBufferSize = 256; 196 cfg.OscilSize = 1024; 197 cfg.SwapStereo = 0; 198 cfg.AudioOutputCompressor = 0; 199 200 cfg.oss_devs.linux_wave_out = new char[MAX_STRING_SIZE]; 201 snprintf(cfg.oss_devs.linux_wave_out, MAX_STRING_SIZE, "/dev/dsp"); 202 cfg.oss_devs.linux_seq_in = new char[MAX_STRING_SIZE]; 203 snprintf(cfg.oss_devs.linux_seq_in, MAX_STRING_SIZE, "/dev/sequencer"); 204 205 cfg.WindowsWaveOutId = 0; 206 cfg.WindowsMidiInId = 0; 207 208 cfg.BankUIAutoClose = 0; 209 210 cfg.GzipCompression = 3; 211 212 cfg.Interpolation = 0; 213 cfg.SaveFullXml = 0; 214 cfg.CheckPADsynth = 1; 215 cfg.IgnoreProgramChange = 0; 216 217 cfg.UserInterfaceMode = 0; 218 cfg.VirKeybLayout = 1; 219 winwavemax = 1; 220 winmidimax = 1; 221 //try to find out how many input midi devices are there 222 winmididevices = new winmidionedevice[winmidimax]; 223 for(int i = 0; i < winmidimax; ++i) { 224 winmididevices[i].name = new char[MAX_STRING_SIZE]; 225 for(int j = 0; j < MAX_STRING_SIZE; ++j) 226 winmididevices[i].name[j] = '\0'; 227 } 228 229 230 //get the midi input devices name 231 cfg.currentBankDir = "./testbnk"; 232 233 char filename[MAX_STRING_SIZE]; 234 getConfigFileName(filename, MAX_STRING_SIZE); 235 readConfig(filename); 236 237 if(cfg.bankRootDirList[0].empty()) { 238 //banks 239 cfg.bankRootDirList[0] = "~/banks"; 240 cfg.bankRootDirList[1] = "./"; 241 #ifdef __APPLE__ 242 cfg.bankRootDirList[2] = "../Resources/banks"; 243 #else 244 cfg.bankRootDirList[2] = "../banks"; 245 #endif 246 cfg.bankRootDirList[3] = "banks"; 247 #ifdef ZYN_DATADIR 248 cfg.bankRootDirList[4] = "$ZYN_DATADIR/banks"; 249 #else 250 cfg.bankRootDirList[4] = "/usr/share/zynaddsubfx/banks"; 251 cfg.bankRootDirList[5] = "/usr/local/share/zynaddsubfx/banks"; 252 #endif 253 } 254 255 if(cfg.presetsDirList[0].empty()) { 256 //presets 257 cfg.presetsDirList[0] = "./"; 258 #ifdef __APPLE__ 259 cfg.presetsDirList[1] = "../Resources/presets"; 260 #else 261 cfg.presetsDirList[1] = "../presets"; 262 #endif 263 cfg.presetsDirList[2] = "presets"; 264 #ifdef ZYN_DATADIR 265 cfg.presetsDirList[3] = "$ZYN_DATADIR/presets"; 266 #else 267 cfg.presetsDirList[3] = "/usr/share/zynaddsubfx/presets"; 268 cfg.presetsDirList[4] = "/usr/local/share/zynaddsubfx/presets"; 269 #endif 270 } 271 cfg.LinuxALSAaudioDev = "default"; 272 cfg.nameTag = ""; 273 } 274 275 Config::~Config() 276 { 277 delete [] cfg.oss_devs.linux_wave_out; 278 delete [] cfg.oss_devs.linux_seq_in; 279 280 for(int i = 0; i < winmidimax; ++i) 281 delete [] winmididevices[i].name; 282 delete [] winmididevices; 283 } 284 285 286 void Config::save() const 287 { 288 char filename[MAX_STRING_SIZE]; 289 getConfigFileName(filename, MAX_STRING_SIZE); 290 saveConfig(filename); 291 } 292 293 void Config::clearbankrootdirlist() 294 { 295 for(int i = 0; i < MAX_BANK_ROOT_DIRS; ++i) 296 cfg.bankRootDirList[i].clear(); 297 } 298 299 void Config::clearpresetsdirlist() 300 { 301 for(int i = 0; i < MAX_BANK_ROOT_DIRS; ++i) 302 cfg.presetsDirList[i].clear(); 303 } 304 305 void Config::readConfig(const char *filename) 306 { 307 XMLwrapper xmlcfg; 308 if(xmlcfg.loadXMLfile(filename) < 0) 309 return; 310 if(xmlcfg.enterbranch("CONFIGURATION")) { 311 cfg.SampleRate = xmlcfg.getpar("sample_rate", 312 cfg.SampleRate, 313 4000, 314 1024000); 315 cfg.SoundBufferSize = xmlcfg.getpar("sound_buffer_size", 316 cfg.SoundBufferSize, 317 16, 318 8192); 319 cfg.OscilSize = xmlcfg.getpar("oscil_size", 320 cfg.OscilSize, 321 MAX_AD_HARMONICS * 2, 322 131072); 323 cfg.SwapStereo = xmlcfg.getpar("swap_stereo", 324 cfg.SwapStereo, 325 0, 326 1); 327 cfg.AudioOutputCompressor = xmlcfg.getpar("audio_output_compressor", 328 cfg.AudioOutputCompressor, 329 0, 330 1); 331 cfg.BankUIAutoClose = xmlcfg.getpar("bank_window_auto_close", 332 cfg.BankUIAutoClose, 333 0, 334 1); 335 336 cfg.GzipCompression = xmlcfg.getpar("gzip_compression", 337 cfg.GzipCompression, 338 0, 339 9); 340 341 cfg.currentBankDir = xmlcfg.getparstr("bank_current", ""); 342 cfg.Interpolation = xmlcfg.getpar("interpolation", 343 cfg.Interpolation, 344 0, 345 1); 346 347 cfg.SaveFullXml = xmlcfg.getpar("SaveFullXml", 348 cfg.SaveFullXml, 349 0, 350 1); 351 352 cfg.CheckPADsynth = xmlcfg.getpar("check_pad_synth", 353 cfg.CheckPADsynth, 354 0, 355 1); 356 357 cfg.IgnoreProgramChange = xmlcfg.getpar("ignore_program_change", 358 cfg.IgnoreProgramChange, 359 0, 360 1); 361 362 363 cfg.UserInterfaceMode = xmlcfg.getpar("user_interface_mode", 364 cfg.UserInterfaceMode, 365 0, 366 2); 367 cfg.VirKeybLayout = xmlcfg.getpar("virtual_keyboard_layout", 368 cfg.VirKeybLayout, 369 0, 370 10); 371 372 //get bankroot dirs 373 for(int i = 0; i < MAX_BANK_ROOT_DIRS; ++i) 374 if(xmlcfg.enterbranch("BANKROOT", i)) { 375 cfg.bankRootDirList[i] = xmlcfg.getparstr("bank_root", ""); 376 xmlcfg.exitbranch(); 377 } 378 379 //get preset root dirs 380 for(int i = 0; i < MAX_BANK_ROOT_DIRS; ++i) 381 if(xmlcfg.enterbranch("PRESETSROOT", i)) { 382 cfg.presetsDirList[i] = xmlcfg.getparstr("presets_root", ""); 383 xmlcfg.exitbranch(); 384 } 385 386 //Get favs 387 for(int i = 0; i < MAX_BANK_ROOT_DIRS; ++i) 388 if(xmlcfg.enterbranch("FAVSROOT", i)) { 389 cfg.favoriteList[i] = xmlcfg.getparstr("favoirtes_root", ""); 390 xmlcfg.exitbranch(); 391 } 392 393 //linux stuff 394 xmlcfg.getparstr("linux_oss_wave_out_dev", 395 cfg.oss_devs.linux_wave_out, 396 MAX_STRING_SIZE); 397 xmlcfg.getparstr("linux_oss_seq_in_dev", 398 cfg.oss_devs.linux_seq_in, 399 MAX_STRING_SIZE); 400 401 //windows stuff 402 cfg.WindowsWaveOutId = xmlcfg.getpar("windows_wave_out_id", 403 cfg.WindowsWaveOutId, 404 0, 405 winwavemax); 406 cfg.WindowsMidiInId = xmlcfg.getpar("windows_midi_in_id", 407 cfg.WindowsMidiInId, 408 0, 409 winmidimax); 410 411 xmlcfg.exitbranch(); 412 } 413 414 cfg.OscilSize = (int) powf(2, ceil(logf(cfg.OscilSize - 1.0f) / logf(2.0f))); 415 } 416 417 void Config::saveConfig(const char *filename) const 418 { 419 XMLwrapper *xmlcfg = new XMLwrapper(); 420 421 xmlcfg->beginbranch("CONFIGURATION"); 422 423 xmlcfg->addpar("sample_rate", cfg.SampleRate); 424 xmlcfg->addpar("sound_buffer_size", cfg.SoundBufferSize); 425 xmlcfg->addpar("oscil_size", cfg.OscilSize); 426 xmlcfg->addpar("swap_stereo", cfg.SwapStereo); 427 xmlcfg->addpar("audio_output_compressor", cfg.AudioOutputCompressor); 428 xmlcfg->addpar("bank_window_auto_close", cfg.BankUIAutoClose); 429 430 xmlcfg->addpar("gzip_compression", cfg.GzipCompression); 431 432 xmlcfg->addpar("check_pad_synth", cfg.CheckPADsynth); 433 xmlcfg->addpar("ignore_program_change", cfg.IgnoreProgramChange); 434 435 xmlcfg->addparstr("bank_current", cfg.currentBankDir); 436 437 xmlcfg->addpar("user_interface_mode", cfg.UserInterfaceMode); 438 xmlcfg->addpar("virtual_keyboard_layout", cfg.VirKeybLayout); 439 440 441 for(int i = 0; i < MAX_BANK_ROOT_DIRS; ++i) 442 if(!cfg.bankRootDirList[i].empty()) { 443 xmlcfg->beginbranch("BANKROOT", i); 444 xmlcfg->addparstr("bank_root", cfg.bankRootDirList[i]); 445 xmlcfg->endbranch(); 446 } 447 448 for(int i = 0; i < MAX_BANK_ROOT_DIRS; ++i) 449 if(!cfg.presetsDirList[i].empty()) { 450 xmlcfg->beginbranch("PRESETSROOT", i); 451 xmlcfg->addparstr("presets_root", cfg.presetsDirList[i]); 452 xmlcfg->endbranch(); 453 } 454 455 for(int i = 0; i < MAX_BANK_ROOT_DIRS; ++i) 456 if(!cfg.favoriteList[i].empty()) { 457 xmlcfg->beginbranch("FAVSROOT", i); 458 xmlcfg->addparstr("favoirtes_root", cfg.favoriteList[i]); 459 xmlcfg->endbranch(); 460 } 461 462 xmlcfg->addpar("interpolation", cfg.Interpolation); 463 xmlcfg->addpar("SaveFullXml", cfg.SaveFullXml); 464 465 //linux stuff 466 xmlcfg->addparstr("linux_oss_wave_out_dev", cfg.oss_devs.linux_wave_out); 467 xmlcfg->addparstr("linux_oss_seq_in_dev", cfg.oss_devs.linux_seq_in); 468 469 //windows stuff 470 xmlcfg->addpar("windows_wave_out_id", cfg.WindowsWaveOutId); 471 xmlcfg->addpar("windows_midi_in_id", cfg.WindowsMidiInId); 472 473 xmlcfg->endbranch(); 474 475 // for some reason (which one?), the gzip compression is bashed to 0 476 xmlcfg->saveXMLfile(filename, 0); 477 478 delete (xmlcfg); 479 } 480 481 void Config::getConfigFileName(char *name, int namesize) const 482 { 483 name[0] = 0; 484 snprintf(name, namesize, "%s%s", getenv("HOME"), "/.zynaddsubfxXML.cfg"); 485 } 486 487 }