zynaddsubfx

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

Schema.cpp (7703B)


      1 #include <cstring>
      2 #include <ostream>
      3 #include <rtosc/ports.h>
      4 #include <set>
      5 #include <string>
      6 using namespace rtosc;
      7 
      8 namespace zyn {
      9 
     10 static const char *escape_string(const char *msg)
     11 {
     12     if(!msg)
     13         return NULL;
     14     char *out = (char*)malloc(strlen(msg)*2+1);
     15     memset(out, 0, strlen(msg)*2+1);
     16     char *itr = out;
     17     while(*msg) {
     18         if(*msg == '"') {
     19             *itr++ = '\\';
     20             *itr++ = '\"';
     21         } else if(*msg == '\\') {
     22             *itr++ = '\\';
     23             *itr++ = '\\';
     24         } else {
     25             *itr++ = *msg;
     26         }
     27 
     28         msg++;
     29 
     30     }
     31     return out;
     32 }
     33 
     34 /*
     35  * root :
     36  *   - 'parameters' : [parameter...]
     37  *   - 'actions'    : [action...]
     38  * parameter :
     39  *   - 'path'      : path-id
     40  *   - 'name'      : string
     41  *   - 'shortname' : string [OPTIONAL]
     42  *   - 'tooltip'   : string [OPTIONAL]
     43  *   - 'type'      : type
     44  *   - 'units'     : unit-type
     45  *   - 'scale'     : scale-type
     46  *   - 'domain'    : range [OPTIONAL]
     47  *   - 'options'   : [option...] [OPTIONAL]
     48  *   - 'default'   : string
     49  *   - 'defaults'  : defaults
     50  * type : {'int', 'float', 'boolean'}
     51  * action :
     52  *   - 'path' : path-id
     53  *   - 'args' : [arg...]
     54  * arg :
     55  *   - 'type'   : type
     56  *   - 'domain' : range [OPTIONAL]
     57  * option :
     58  *   - 'id'    : id-number
     59  *   - 'value' : string-rep
     60  * defaults :
     61  *   - 'id'    : id-number
     62  *   - 'value' : string-rep
     63  */
     64 
     65 using std::ostream;
     66 using std::string;
     67 #if 0
     68 static int enum_min(Port::MetaContainer meta)
     69 {
     70     int min = 0;
     71     for(auto m:meta)
     72         if(strstr(m.title, "map "))
     73             min = atoi(m.title+4);
     74 
     75     for(auto m:meta)
     76         if(strstr(m.title, "map "))
     77             min = min>atoi(m.title+4) ? atoi(m.title+4) : min;
     78 
     79     return min;
     80 }
     81 
     82 static int enum_max(Port::MetaContainer meta)
     83 {
     84     int max = 0;
     85     for(auto m:meta)
     86         if(strstr(m.title, "map "))
     87             max = atoi(m.title+4);
     88 
     89     for(auto m:meta)
     90         if(strstr(m.title, "map "))
     91             max = max<atoi(m.title+4) ? atoi(m.title+4) : max;
     92 
     93     return max;
     94 }
     95 
     96 static ostream &add_options(ostream &o, Port::MetaContainer meta)
     97 {
     98     string sym_names = "xyzabcdefghijklmnopqrstuvw";
     99     int sym_idx = 0;
    100     bool has_options = false;
    101     for(auto m:meta)
    102         if(strstr(m.title, "map "))
    103             has_options = true;
    104     for(auto m:meta)
    105         if(strcmp(m.title, "documentation") &&
    106                 strcmp(m.title, "parameter") &&
    107                 strcmp(m.title, "max") &&
    108                 strcmp(m.title, "min") &&
    109                 strcmp(m.title, "logmin"))
    110         printf("m.title = <%s>\n", m.title);
    111 
    112     if(!has_options)
    113         return o;
    114 
    115     o << "    <hints>\n";
    116     for(auto m:meta) {
    117         if(strstr(m.title, "map ")) {
    118             o << "      <point symbol=\"" << sym_names[sym_idx++] << "\" value=\"";
    119             o << m.title+4 << "\">" << m.value << "</point>\n";
    120         }
    121     }
    122     o << "    </hints>\n";
    123 
    124     return o;
    125 }
    126 #endif
    127 
    128 /*
    129  * parameter :
    130  *   - 'path'      : path-id
    131  *   - 'name'      : string
    132  *   - 'shortname' : string [OPTIONAL]
    133  *   - 'tooltip'   : string [OPTIONAL]
    134  *   - 'type'      : type
    135  *   - 'domain'    : range [OPTIONAL]
    136  */
    137 static bool first = true;
    138 static bool do_dump(const rtosc::Port *p, const char *full_name, void *v)
    139 {
    140     typedef std::vector<std::pair<int,string>> opts;
    141     std::ostream &o  = *(std::ostream*)v;
    142     auto meta        = p->meta();
    143     const char *args = strchr(p->name, ':');
    144     auto mparameter  = meta.find("parameter");
    145     auto mdoc        = meta.find("documentation");
    146     auto msname      = meta.find("shortname");
    147     auto units       = meta.find("unit");
    148     auto scale       = meta.find("scale");
    149 
    150     opts options;
    151     string doc;
    152     string name      = p->name;;
    153 
    154     {
    155         size_t pos = 0;
    156         if((pos = name.find_first_of(":")) != string::npos)
    157             name = name.substr(0, pos);
    158     }
    159 
    160     //Escape Characters
    161     if(mdoc != p->meta().end()) {
    162         while(*mdoc.value) {
    163             if(*mdoc.value == '\n')
    164                 doc += "\\n";
    165             else if(*mdoc.value == '\"')
    166                 doc += "\\\"";
    167             else
    168                 doc += *mdoc.value;
    169             mdoc.value++;
    170         }
    171     }
    172     if(meta.find("internal") != meta.end())
    173         return false;
    174 
    175     char type = 0;
    176     if(mparameter != p->meta().end()) {
    177         if(args) {
    178             if(strchr(args, 'f'))
    179                 type = 'f';
    180             else if(strchr(args, 'i'))
    181                 type = 'i';
    182             else if(strchr(args, 'c'))
    183                 type = 'c';
    184             else if(strchr(args, 'T'))
    185                 type = 't';
    186             else if(strchr(args, 's'))
    187                 type = 's';
    188         }
    189 
    190         if(!type) {
    191             fprintf(stderr, "rtosc port dumper: Cannot handle '%s'\n", full_name);
    192             fprintf(stderr, "    args = <%s>\n", args);
    193             return false;
    194         }
    195     } else {
    196         //fprintf(stderr, "Skipping \"%s\"\n", name);
    197         //if(args) {
    198         //    fprintf(stderr, "    type = %s\n", args);
    199         //}
    200         return false;
    201     }
    202 
    203     const char *min = meta["min"];
    204     const char *max = meta["max"];
    205     const char *logmin = meta["logmin"];
    206     const char *def = meta["default"];
    207     def = escape_string(def);
    208 
    209     for(auto m:meta) {
    210         if(strlen(m.title) >= 5 && !memcmp(m.title, "map ", 4)) {
    211             int id = atoi(m.title+4);
    212             std::string val = m.value;
    213             options.push_back(std::make_pair(id, val));
    214         }
    215     }
    216 
    217     if(!first)
    218         o << ",\n";
    219     else
    220         first = false;
    221 
    222     o << "    {\n";
    223     o << "        \"path\"     : \"" << full_name << "\",\n";
    224     if(msname != meta.end())
    225         o << "        \"shortname\": \"" << msname.value << "\",\n";
    226     o << "        \"name\"     : \"" << name << "\",\n";
    227     o << "        \"tooltip\"  : \"" << doc  << "\",\n";
    228     if(units != meta.end())
    229         o << "        \"units\"    : \"" << units.value << "\",\n";
    230     if(scale != meta.end())
    231         o << "        \"scale\"    : \"" << scale.value << "\",\n";
    232     o << "        \"type\"     : \"" << type  << "\"";
    233     if(min && max)
    234     {
    235         o << ",\n        \"range\"    : [" << min << "," << max;
    236         if(logmin)
    237             o << "," << logmin << "]";
    238         else
    239             o << "]";
    240     }
    241     if(def)
    242         o << ",\n        \"default\"  : \"" << def << "\"\n";
    243     if(!options.empty()) {
    244         o << ",\n        \"options\"  : [\n";
    245         int N = options.size();
    246         for(int i=0; i<N; ++i) {
    247             o << "        {\n";
    248             o << "            \"id\"     : "   << options[i].first << ",\n";
    249             o << "            \"value\"  : \"" << options[i].second << "\"\n";
    250             o << "        }";
    251             if(i != N-1)
    252                 o << ",";
    253             o << "\n";
    254         }
    255         o << "        ]";
    256     }
    257     o << "\n    }";
    258     return true;
    259 }
    260 
    261 static void dump_param_cb(const rtosc::Port *p, const char *full_name, const char*,
    262                           const Ports&,void *v, void*)
    263 {
    264     static std::set<std::pair<std::string, std::string>> already_dumped;
    265     if(already_dumped.find(std::make_pair(full_name, p->name)) == already_dumped.end())
    266     {
    267         bool dumped = do_dump(p, full_name, v);
    268         if(dumped)
    269             already_dumped.emplace(full_name, p->name);
    270     }
    271 }
    272 
    273 void dump_json(std::ostream &o, const rtosc::Ports &p)
    274 {
    275     first = true;
    276     o << "{\n";
    277     o << "    \"parameter\" : [\n";
    278     char buffer[1024];
    279     memset(buffer, 0, sizeof(buffer));
    280     walk_ports(&p, buffer, 1024, &o, dump_param_cb, true, nullptr, true);
    281     o << "\n    ],\n";
    282     o << "    \"actions\" : [\n";
    283     //walk_ports2(formatter.p, buffer, 1024, &o, dump_action_cb);
    284     o << "    ]\n";
    285     o << "}";
    286 }
    287 
    288 }