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.

271 lines
7.1KB

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