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.

452 lines
16KB

  1. /*
  2. ZynAddSubFX - a software synthesizer
  3. CarlaConfig.cpp - CarlaConfiguration 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 CarlaConfig
  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. CarlaConfig &c = *(CarlaConfig*)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. CarlaConfig &c = *(CarlaConfig*)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. CarlaConfig &c = *(CarlaConfig*)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. {"add-favorite:s", rDoc("Add favorite directory"), 0,
  122. [](const char *msg, rtosc::RtData &d)
  123. {
  124. CarlaConfig &c = *(CarlaConfig*)d.obj;
  125. for(int i=0; i<MAX_BANK_ROOT_DIRS; ++i) {
  126. if(c.cfg.favoriteList[i].empty()) {
  127. c.cfg.favoriteList[i] = rtosc_argument(msg, 0).s;
  128. return;
  129. }
  130. }
  131. }},
  132. {"favorites:", rProp(parameter), 0,
  133. [](const char *msg, rtosc::RtData &d)
  134. {
  135. CarlaConfig &c = *(CarlaConfig*)d.obj;
  136. char *argt = new char[MAX_BANK_ROOT_DIRS+1];
  137. rtosc_arg_t *args = new rtosc_arg_t[MAX_BANK_ROOT_DIRS];
  138. memset(argt, 0, MAX_BANK_ROOT_DIRS+1);
  139. int j = 0;
  140. for(int i=0; i<MAX_BANK_ROOT_DIRS; ++i) {
  141. if(!c.cfg.favoriteList[i].empty()) {
  142. argt[j] = 's';
  143. args[j].s = c.cfg.favoriteList[i].c_str();
  144. j++;
  145. }
  146. }
  147. d.replyArray(d.loc, argt, args);
  148. delete [] argt;
  149. delete [] args;
  150. }},
  151. };
  152. const rtosc::Ports &CarlaConfig::ports = ::ports;
  153. #endif
  154. CarlaConfig::CarlaConfig()
  155. {}
  156. void CarlaConfig::init()
  157. {
  158. maxstringsize = MAX_STRING_SIZE; //for ui
  159. //defaults
  160. cfg.SampleRate = 44100;
  161. cfg.SoundBufferSize = 256;
  162. cfg.OscilSize = 1024;
  163. cfg.SwapStereo = 0;
  164. cfg.oss_devs.linux_wave_out = new char[MAX_STRING_SIZE];
  165. snprintf(cfg.oss_devs.linux_wave_out, MAX_STRING_SIZE, "/dev/dsp");
  166. cfg.oss_devs.linux_seq_in = new char[MAX_STRING_SIZE];
  167. snprintf(cfg.oss_devs.linux_seq_in, MAX_STRING_SIZE, "/dev/sequencer");
  168. cfg.WindowsWaveOutId = 0;
  169. cfg.WindowsMidiInId = 0;
  170. cfg.BankUIAutoClose = 0;
  171. cfg.GzipCompression = 3;
  172. cfg.Interpolation = 0;
  173. cfg.CheckPADsynth = 1;
  174. cfg.IgnoreProgramChange = 0;
  175. cfg.UserInterfaceMode = 0;
  176. cfg.VirKeybLayout = 1;
  177. winwavemax = 1;
  178. winmidimax = 1;
  179. //try to find out how many input midi devices are there
  180. winmididevices = new winmidionedevice[winmidimax];
  181. for(int i = 0; i < winmidimax; ++i) {
  182. winmididevices[i].name = new char[MAX_STRING_SIZE];
  183. for(int j = 0; j < MAX_STRING_SIZE; ++j)
  184. winmididevices[i].name[j] = '\0';
  185. }
  186. //get the midi input devices name
  187. cfg.currentBankDir = "./testbnk";
  188. char filename[MAX_STRING_SIZE];
  189. getConfigFileName(filename, MAX_STRING_SIZE);
  190. readConfig(filename);
  191. if(cfg.bankRootDirList[0].empty()) {
  192. //banks
  193. cfg.bankRootDirList[0] = "~/banks";
  194. cfg.bankRootDirList[1] = "./";
  195. cfg.bankRootDirList[2] = "/usr/share/zynaddsubfx/banks";
  196. cfg.bankRootDirList[3] = "/usr/local/share/zynaddsubfx/banks";
  197. #ifdef __APPLE__
  198. cfg.bankRootDirList[4] = "../Resources/banks";
  199. #else
  200. cfg.bankRootDirList[4] = "../banks";
  201. #endif
  202. cfg.bankRootDirList[5] = "banks";
  203. }
  204. if(cfg.presetsDirList[0].empty()) {
  205. //presets
  206. cfg.presetsDirList[0] = "./";
  207. #ifdef __APPLE__
  208. cfg.presetsDirList[1] = "../Resources/presets";
  209. #else
  210. cfg.presetsDirList[1] = "../presets";
  211. #endif
  212. cfg.presetsDirList[2] = "presets";
  213. cfg.presetsDirList[3] = "/usr/share/zynaddsubfx/presets";
  214. cfg.presetsDirList[4] = "/usr/local/share/zynaddsubfx/presets";
  215. }
  216. cfg.LinuxALSAaudioDev = "default";
  217. cfg.nameTag = "";
  218. }
  219. CarlaConfig::~CarlaConfig()
  220. {
  221. delete [] cfg.oss_devs.linux_wave_out;
  222. delete [] cfg.oss_devs.linux_seq_in;
  223. for(int i = 0; i < winmidimax; ++i)
  224. delete [] winmididevices[i].name;
  225. delete [] winmididevices;
  226. }
  227. void CarlaConfig::save() const
  228. {
  229. char filename[MAX_STRING_SIZE];
  230. getConfigFileName(filename, MAX_STRING_SIZE);
  231. saveConfig(filename);
  232. }
  233. void CarlaConfig::clearbankrootdirlist()
  234. {
  235. for(int i = 0; i < MAX_BANK_ROOT_DIRS; ++i)
  236. cfg.bankRootDirList[i].clear();
  237. }
  238. void CarlaConfig::clearpresetsdirlist()
  239. {
  240. for(int i = 0; i < MAX_BANK_ROOT_DIRS; ++i)
  241. cfg.presetsDirList[i].clear();
  242. }
  243. void CarlaConfig::readConfig(const char *filename)
  244. {
  245. XMLwrapper xmlcfg;
  246. if(xmlcfg.loadXMLfile(filename) < 0)
  247. return;
  248. if(xmlcfg.enterbranch("CONFIGURATION")) {
  249. cfg.SampleRate = xmlcfg.getpar("sample_rate",
  250. cfg.SampleRate,
  251. 4000,
  252. 1024000);
  253. cfg.SoundBufferSize = xmlcfg.getpar("sound_buffer_size",
  254. cfg.SoundBufferSize,
  255. 16,
  256. 8192);
  257. cfg.OscilSize = xmlcfg.getpar("oscil_size",
  258. cfg.OscilSize,
  259. MAX_AD_HARMONICS * 2,
  260. 131072);
  261. cfg.SwapStereo = xmlcfg.getpar("swap_stereo",
  262. cfg.SwapStereo,
  263. 0,
  264. 1);
  265. cfg.BankUIAutoClose = xmlcfg.getpar("bank_window_auto_close",
  266. cfg.BankUIAutoClose,
  267. 0,
  268. 1);
  269. cfg.GzipCompression = xmlcfg.getpar("gzip_compression",
  270. cfg.GzipCompression,
  271. 0,
  272. 9);
  273. cfg.currentBankDir = xmlcfg.getparstr("bank_current", "");
  274. cfg.Interpolation = xmlcfg.getpar("interpolation",
  275. cfg.Interpolation,
  276. 0,
  277. 1);
  278. cfg.CheckPADsynth = xmlcfg.getpar("check_pad_synth",
  279. cfg.CheckPADsynth,
  280. 0,
  281. 1);
  282. cfg.IgnoreProgramChange = xmlcfg.getpar("ignore_program_change",
  283. cfg.IgnoreProgramChange,
  284. 0,
  285. 1);
  286. cfg.UserInterfaceMode = xmlcfg.getpar("user_interface_mode",
  287. cfg.UserInterfaceMode,
  288. 0,
  289. 2);
  290. cfg.VirKeybLayout = xmlcfg.getpar("virtual_keyboard_layout",
  291. cfg.VirKeybLayout,
  292. 0,
  293. 10);
  294. //get bankroot dirs
  295. for(int i = 0; i < MAX_BANK_ROOT_DIRS; ++i)
  296. if(xmlcfg.enterbranch("BANKROOT", i)) {
  297. cfg.bankRootDirList[i] = xmlcfg.getparstr("bank_root", "");
  298. xmlcfg.exitbranch();
  299. }
  300. //get preset root dirs
  301. for(int i = 0; i < MAX_BANK_ROOT_DIRS; ++i)
  302. if(xmlcfg.enterbranch("PRESETSROOT", i)) {
  303. cfg.presetsDirList[i] = xmlcfg.getparstr("presets_root", "");
  304. xmlcfg.exitbranch();
  305. }
  306. //Get favs
  307. for(int i = 0; i < MAX_BANK_ROOT_DIRS; ++i)
  308. if(xmlcfg.enterbranch("FAVSROOT", i)) {
  309. cfg.favoriteList[i] = xmlcfg.getparstr("favoirtes_root", "");
  310. xmlcfg.exitbranch();
  311. }
  312. //linux stuff
  313. xmlcfg.getparstr("linux_oss_wave_out_dev",
  314. cfg.oss_devs.linux_wave_out,
  315. MAX_STRING_SIZE);
  316. xmlcfg.getparstr("linux_oss_seq_in_dev",
  317. cfg.oss_devs.linux_seq_in,
  318. MAX_STRING_SIZE);
  319. //windows stuff
  320. cfg.WindowsWaveOutId = xmlcfg.getpar("windows_wave_out_id",
  321. cfg.WindowsWaveOutId,
  322. 0,
  323. winwavemax);
  324. cfg.WindowsMidiInId = xmlcfg.getpar("windows_midi_in_id",
  325. cfg.WindowsMidiInId,
  326. 0,
  327. winmidimax);
  328. xmlcfg.exitbranch();
  329. }
  330. cfg.OscilSize = (int) powf(2, ceil(logf(cfg.OscilSize - 1.0f) / logf(2.0f)));
  331. }
  332. void CarlaConfig::saveConfig(const char *filename) const
  333. {
  334. XMLwrapper *xmlcfg = new XMLwrapper();
  335. xmlcfg->beginbranch("CONFIGURATION");
  336. xmlcfg->addpar("sample_rate", cfg.SampleRate);
  337. xmlcfg->addpar("sound_buffer_size", cfg.SoundBufferSize);
  338. xmlcfg->addpar("oscil_size", cfg.OscilSize);
  339. xmlcfg->addpar("swap_stereo", cfg.SwapStereo);
  340. xmlcfg->addpar("bank_window_auto_close", cfg.BankUIAutoClose);
  341. xmlcfg->addpar("gzip_compression", cfg.GzipCompression);
  342. xmlcfg->addpar("check_pad_synth", cfg.CheckPADsynth);
  343. xmlcfg->addpar("ignore_program_change", cfg.IgnoreProgramChange);
  344. xmlcfg->addparstr("bank_current", cfg.currentBankDir);
  345. xmlcfg->addpar("user_interface_mode", cfg.UserInterfaceMode);
  346. xmlcfg->addpar("virtual_keyboard_layout", cfg.VirKeybLayout);
  347. for(int i = 0; i < MAX_BANK_ROOT_DIRS; ++i)
  348. if(!cfg.bankRootDirList[i].empty()) {
  349. xmlcfg->beginbranch("BANKROOT", i);
  350. xmlcfg->addparstr("bank_root", cfg.bankRootDirList[i]);
  351. xmlcfg->endbranch();
  352. }
  353. for(int i = 0; i < MAX_BANK_ROOT_DIRS; ++i)
  354. if(!cfg.presetsDirList[i].empty()) {
  355. xmlcfg->beginbranch("PRESETSROOT", i);
  356. xmlcfg->addparstr("presets_root", cfg.presetsDirList[i]);
  357. xmlcfg->endbranch();
  358. }
  359. for(int i = 0; i < MAX_BANK_ROOT_DIRS; ++i)
  360. if(!cfg.favoriteList[i].empty()) {
  361. xmlcfg->beginbranch("FAVSROOT", i);
  362. xmlcfg->addparstr("favoirtes_root", cfg.favoriteList[i]);
  363. xmlcfg->endbranch();
  364. }
  365. xmlcfg->addpar("interpolation", cfg.Interpolation);
  366. //linux stuff
  367. xmlcfg->addparstr("linux_oss_wave_out_dev", cfg.oss_devs.linux_wave_out);
  368. xmlcfg->addparstr("linux_oss_seq_in_dev", cfg.oss_devs.linux_seq_in);
  369. //windows stuff
  370. xmlcfg->addpar("windows_wave_out_id", cfg.WindowsWaveOutId);
  371. xmlcfg->addpar("windows_midi_in_id", cfg.WindowsMidiInId);
  372. xmlcfg->endbranch();
  373. // for some reason (which one?), the gzip compression is bashed to 0
  374. xmlcfg->saveXMLfile(filename, 0);
  375. delete (xmlcfg);
  376. }
  377. void CarlaConfig::getConfigFileName(char *name, int namesize) const
  378. {
  379. name[0] = 0;
  380. snprintf(name, namesize, "%s%s", getenv("HOME"), "/.zynaddsubfxXML.cfg");
  381. }