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.

273 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. #if 0
  65. static int enum_min(Port::MetaContainer meta)
  66. {
  67. int min = 0;
  68. for(auto m:meta)
  69. if(strstr(m.title, "map "))
  70. min = atoi(m.title+4);
  71. for(auto m:meta)
  72. if(strstr(m.title, "map "))
  73. min = min>atoi(m.title+4) ? atoi(m.title+4) : min;
  74. return min;
  75. }
  76. static int enum_max(Port::MetaContainer meta)
  77. {
  78. int max = 0;
  79. for(auto m:meta)
  80. if(strstr(m.title, "map "))
  81. max = atoi(m.title+4);
  82. for(auto m:meta)
  83. if(strstr(m.title, "map "))
  84. max = max<atoi(m.title+4) ? atoi(m.title+4) : max;
  85. return max;
  86. }
  87. static ostream &add_options(ostream &o, Port::MetaContainer meta)
  88. {
  89. string sym_names = "xyzabcdefghijklmnopqrstuvw";
  90. int sym_idx = 0;
  91. bool has_options = false;
  92. for(auto m:meta)
  93. if(strstr(m.title, "map "))
  94. has_options = true;
  95. for(auto m:meta)
  96. if(strcmp(m.title, "documentation") &&
  97. strcmp(m.title, "parameter") &&
  98. strcmp(m.title, "max") &&
  99. strcmp(m.title, "min"))
  100. printf("m.title = <%s>\n", m.title);
  101. if(!has_options)
  102. return o;
  103. o << " <hints>\n";
  104. for(auto m:meta) {
  105. if(strstr(m.title, "map ")) {
  106. o << " <point symbol=\"" << sym_names[sym_idx++] << "\" value=\"";
  107. o << m.title+4 << "\">" << m.value << "</point>\n";
  108. }
  109. }
  110. o << " </hints>\n";
  111. return o;
  112. }
  113. #endif
  114. /*
  115. * parameter :
  116. * - 'path' : path-id
  117. * - 'name' : string
  118. * - 'shortname' : string [OPTIONAL]
  119. * - 'tooltip' : string [OPTIONAL]
  120. * - 'type' : type
  121. * - 'domain' : range [OPTIONAL]
  122. */
  123. static bool first = true;
  124. void dump_param_cb(const rtosc::Port *p, const char *full_name, const char*,
  125. const Ports&,void *v, void*)
  126. {
  127. typedef std::vector<std::pair<int,string>> opts;
  128. std::ostream &o = *(std::ostream*)v;
  129. auto meta = p->meta();
  130. const char *args = strchr(p->name, ':');
  131. auto mparameter = meta.find("parameter");
  132. auto mdoc = meta.find("documentation");
  133. auto msname = meta.find("shortname");
  134. auto units = meta.find("unit");
  135. auto scale = meta.find("scale");
  136. opts options;
  137. string doc;
  138. string name = p->name;;
  139. {
  140. size_t pos = 0;
  141. if((pos = name.find_first_of(":")) != string::npos)
  142. name = name.substr(0, pos);
  143. }
  144. //Escape Characters
  145. if(mdoc != p->meta().end()) {
  146. while(*mdoc.value) {
  147. if(*mdoc.value == '\n')
  148. doc += "\\n";
  149. else if(*mdoc.value == '\"')
  150. doc += "\\\"";
  151. else
  152. doc += *mdoc.value;
  153. mdoc.value++;
  154. }
  155. }
  156. if(meta.find("internal") != meta.end())
  157. return;
  158. char type = 0;
  159. if(mparameter != p->meta().end()) {
  160. if(args) {
  161. if(strchr(args, 'f'))
  162. type = 'f';
  163. else if(strchr(args, 'i'))
  164. type = 'i';
  165. else if(strchr(args, 'c'))
  166. type = 'c';
  167. else if(strchr(args, 'T'))
  168. type = 't';
  169. else if(strchr(args, 's'))
  170. type = 's';
  171. }
  172. if(!type) {
  173. fprintf(stderr, "rtosc port dumper: Cannot handle '%s'\n", full_name);
  174. fprintf(stderr, " args = <%s>\n", args);
  175. return;
  176. }
  177. } else {
  178. //fprintf(stderr, "Skipping \"%s\"\n", name);
  179. //if(args) {
  180. // fprintf(stderr, " type = %s\n", args);
  181. //}
  182. return;
  183. }
  184. const char *min = meta["min"];
  185. const char *max = meta["max"];
  186. const char *def = meta["default"];
  187. def = escape_string(def);
  188. for(auto m:meta) {
  189. if(strlen(m.title) >= 5 && !memcmp(m.title, "map ", 4)) {
  190. int id = atoi(m.title+4);
  191. std::string val = m.value;
  192. options.push_back(std::make_pair(id, val));
  193. }
  194. }
  195. if(!first)
  196. o << ",\n";
  197. else
  198. first = false;
  199. o << " {\n";
  200. o << " \"path\" : \"" << full_name << "\",\n";
  201. if(msname != meta.end())
  202. o << " \"shortname\": \"" << msname.value << "\",\n";
  203. o << " \"name\" : \"" << name << "\",\n";
  204. o << " \"tooltip\" : \"" << doc << "\",\n";
  205. if(units != meta.end())
  206. o << " \"units\" : \"" << units.value << "\",\n";
  207. if(scale != meta.end())
  208. o << " \"scale\" : \"" << scale.value << "\",\n";
  209. o << " \"type\" : \"" << type << "\"";
  210. if(min && max)
  211. o << ",\n \"range\" : [" << min << "," << max << "]";
  212. if(def)
  213. o << ",\n \"default\" : \"" << def << "\"\n";
  214. if(!options.empty()) {
  215. o << ",\n \"options\" : [\n";
  216. int N = options.size();
  217. for(int i=0; i<N; ++i) {
  218. o << " {\n";
  219. o << " \"id\" : " << options[i].first << ",\n";
  220. o << " \"value\" : \"" << options[i].second << "\"\n";
  221. o << " }";
  222. if(i != N-1)
  223. o << ",";
  224. o << "\n";
  225. }
  226. o << " ]";
  227. }
  228. o << "\n }";
  229. }
  230. void dump_json(std::ostream &o, const rtosc::Ports &p)
  231. {
  232. first = true;
  233. o << "{\n";
  234. o << " \"parameter\" : [\n";
  235. char buffer[1024];
  236. memset(buffer, 0, sizeof(buffer));
  237. walk_ports2(&p, buffer, 1024, &o, dump_param_cb);
  238. o << "\n ],\n";
  239. o << " \"actions\" : [\n";
  240. //walk_ports2(formatter.p, buffer, 1024, &o, dump_action_cb);
  241. o << " ]\n";
  242. o << "}";
  243. }
  244. }