zynaddsubfx

ZynAddSubFX open source synthesizer
Log | Files | Refs | Submodules | LICENSE

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 };