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.

112 lines
3.4KB

  1. #pragma once
  2. #include <rtosc/ports.h>
  3. #include "Fl_Osc_Interface.h"
  4. #include <FL/Fl_Tree.H>
  5. class Fl_Osc_Tree: public Fl_Tree
  6. {
  7. public:
  8. Fl_Osc_Tree(int X, int Y, int W, int H, const char *L=0)
  9. :Fl_Tree(X,Y,W,H,L)
  10. {
  11. root_label("");
  12. add("nil");
  13. add("/nil/nil");
  14. close(first());
  15. callback(Fl_Osc_Tree::cb, NULL);
  16. }
  17. void sprout(std::string s)
  18. {
  19. if(s[s.length()-1] == '/') {
  20. attach(s);
  21. attach(s+"nil");
  22. close(s.c_str());
  23. } else
  24. attach(s);
  25. }
  26. void attach(std::string s)
  27. {
  28. if(!find_item(s.c_str()))
  29. add(s.c_str());
  30. }
  31. static void cb(Fl_Widget *w, void*)
  32. {
  33. using namespace rtosc;
  34. Fl_Osc_Tree *t=(Fl_Osc_Tree*)w;
  35. int reason = t->callback_reason();
  36. char pathname[1024];
  37. t->item_pathname(pathname, sizeof(pathname), t->callback_item());
  38. if(reason==1) {
  39. char *colon = index(pathname, ':');
  40. if(colon) {
  41. *colon = 0;
  42. t->osc->writeValue("/learn", string(pathname));
  43. }
  44. }
  45. if(reason==3) //Populate fields
  46. {
  47. const Ports &p = *Fl_Osc_Tree::subtree_lookup(t->root_ports,pathname+1);
  48. printf("ok, I got the tree\n");
  49. if(auto *i = t->find_item((std::string(pathname)+"/"+"nil").c_str()))
  50. t->remove(i);
  51. for(const Port &port : p) {
  52. printf("handling '%s'\n", port.name);
  53. const bool subnodes = index(port.name, '/');
  54. const bool enumerated = index(port.name, '#');
  55. const string path = std::string(pathname)+"/"+port.name;
  56. if(!enumerated) {
  57. t->sprout(path);
  58. } else {
  59. char tmpa[1024];
  60. char tmpb[1024];
  61. strncpy(tmpa, path.c_str(), 1024);
  62. char *pound = index(tmpa, '#');
  63. int N = atoi(pound+1);
  64. *pound = 0;
  65. char terminal = subnodes ? '/' : '\0';
  66. for(int i = 0; i < N; ++i) {
  67. snprintf(tmpb, 1024, "%s%d%c",
  68. tmpa, i, terminal);
  69. t->sprout(tmpb);
  70. }
  71. }
  72. }
  73. }
  74. }
  75. static const rtosc::Ports *subtree_lookup(const rtosc::Ports *p, std::string s)
  76. {
  77. using namespace rtosc;
  78. if(s=="")
  79. return p;
  80. if(s[s.length()-1] != '/')
  81. s += '/';
  82. for(const Port &port : *p) {
  83. const char *name = port.name;
  84. if(!index(name, '/'))//only accept objects that will have subports
  85. continue;
  86. if(rtosc_match(name, s.c_str())) {
  87. return subtree_lookup(port.ports,
  88. s.substr(index(s.c_str(), '/')-s.c_str()+1));
  89. }
  90. }
  91. //TODO else case
  92. return p;
  93. }
  94. rtosc::Ports *root_ports;
  95. Fl_Osc_Interface *osc;
  96. };