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