Audio plugin host https://kx.studio/carla
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

Config.cpp 16KB

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