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.

Fl_Osc_Tree.H 3.8KB

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