Merge branch 'master' of https://scm.cri.ensmp.fr/git/Faustine
[Faustine.git] / interpretor / faust-0.9.47mr3 / architecture / osclib / faust / src / nodes / FaustFactory.cpp
1 /*
2
3 Copyright (C) 2011 Grame
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
19 Grame Research Laboratory, 9 rue du Garet, 69001 Lyon - France
20 research@grame.fr
21
22 */
23
24 #include <iostream>
25 #include <sstream>
26
27 #include "FaustFactory.h"
28 #include "FaustNode.h"
29 #include "RootNode.h"
30 #include "MessageDriven.h"
31 #include "OSCAddress.h"
32
33 using namespace std;
34
35 namespace oscfaust
36 {
37
38
39 /**
40 * Add a node to the OSC UI tree in the current group at the top of the stack
41 */
42 void FaustFactory::addnode (const char* label, float* zone, float init, float min, float max)
43 {
44 SMessageDriven top = fNodes.size() ? fNodes.top() : fRoot;
45 if (top) {
46 string prefix = top->getOSCAddress();
47 top->add( FaustNode::create (label, zone, init, min, max, prefix.c_str()) );
48 }
49 }
50
51 /**
52 * Add a node to the OSC UI tree using its fullpath directly from the root and bypassing the current group.
53 * The argument fullpath = "/foo/fii/faa [imin [imax]]" can contain optional imin and imax values
54 */
55 void FaustFactory::addfullpathnode (const string& fullpath, float* zone, float imin, float imax, float init, float min, float max)
56 {
57 istringstream ss(fullpath);
58 string realpath;
59 string remainingpath;
60
61 // Extract realpath and optional imin and imax fields. Note that if no values for imin and imax
62 // are specified in the fullpath string, the values passed as parameters will be used.
63 ss >> realpath >> imin >> imax;
64 // Note that realpath is prefixed before being added in the tree : /root/alias/realpath
65 SMessageDriven node = followPath(fRoot, string("/alias") + realpath, remainingpath);
66 createNodeChain(node, remainingpath, zone, imin, imax, init, min, max);
67 }
68
69
70 /**
71 * Follows fullpath as much as possible. Return the deepest node reached and
72 * the remaining path. We have path(node)++remainingpath = fullpath
73 */
74 SMessageDriven FaustFactory::followPath(SMessageDriven node, const string& fullpath, string& remainingpath)
75 {
76 if (fullpath.size()>0) {
77 string label = OSCAddress::addressFirst (fullpath);
78 for (int i = 0; i < node->size(); i++) {
79 if (node->subnode(i)->name() == label) {
80 return followPath(node->subnode(i), OSCAddress::addressTail(fullpath), remainingpath);
81 }
82 }
83 }
84 remainingpath = fullpath;
85 return node;
86 }
87
88
89 /**
90 * Creates a chain of nodes starting at node and following pathtoleaf
91 */
92 void FaustFactory::createNodeChain(SMessageDriven node, const string& pathtoleaf, float* zone, float imin, float imax, float init, float min, float max)
93 {
94 if (pathtoleaf.size() > 0) {
95 string label = OSCAddress::addressFirst (pathtoleaf);
96 string tail = OSCAddress::addressTail (pathtoleaf);
97 if (tail.size() == 0) {
98 string prefix = node->getOSCAddress();
99 node->add( FaustNode::create (label.c_str(), zone, imin, imax, init, min, max, prefix.c_str()) );
100 } else {
101 SMessageDriven group = MessageDriven::create (label.c_str(), node->getOSCAddress().c_str());
102 node->add(group);
103 createNodeChain(group, tail, zone, imin, imax, init, min, max);
104 }
105 } else {
106 cerr << "osc address too short" << endl;
107 }
108 }
109
110
111 /**
112 * Open a group in the current group and place it on the top of the stack.
113 * Takes into account that due to alias, a group can been previously created.
114 */
115 void FaustFactory::opengroup (const char* label)
116 {
117 if (fNodes.size() == 0) {
118 // the stack is empty: creates a root node
119 // and gives the root node a possible OSCIO controler
120 fRoot = RootNode::create (label, fIO);
121 fNodes.push (fRoot);
122
123 } else {
124 // only create a group if not previously created
125 SMessageDriven node = fNodes.top();
126 int i=0; while ( (i < node->size()) && (node->subnode(i)->name() != label) ) i++;
127
128 if (i < node->size()) {
129 // found, make it top of stack
130 fNodes.push(node->subnode(i));
131 } else {
132 // not found, create a new group and make it top of stack
133 SMessageDriven group = MessageDriven::create (label, node->getOSCAddress().c_str());
134 node->add( group );
135 fNodes.push (group);
136 }
137
138 }
139 }
140
141 //--------------------------------------------------------------------------
142 void FaustFactory::closegroup ()
143 {
144 fNodes.pop ();
145 }
146
147 } // end namespoace