zynaddsubfx

ZynAddSubFX open source synthesizer
Log | Files | Refs | Submodules | LICENSE

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 }