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 }