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.

407 lines
14KB

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