Merge branch 'master' of https://scm.cri.ensmp.fr/git/Faustine
[Faustine.git] / interpretor / faust-0.9.47mr3 / compiler / generator / description.cpp
1 //------------------------------------
2 // generation of an xml description
3 //------------------------------------
4 #include <map>
5 #include <set>
6 #include <string>
7
8 #include "description.hh"
9 #include "Text.hh"
10
11 /**
12 * Extracts metdata from a label : 'vol [unit: dB]' -> 'vol' + metadata
13 */
14 void extractMetadata(const string& fulllabel, string& label, map<string, set<string> >& metadata)
15 {
16 enum {kLabel, kEscape1, kEscape2, kEscape3, kKey, kValue};
17 int state = kLabel; int deep = 0;
18 string key, value;
19
20 for (size_t i=0; i < fulllabel.size(); i++) {
21 char c = fulllabel[i];
22 switch (state) {
23 case kLabel :
24 assert (deep == 0);
25 switch (c) {
26 case '\\' : state = kEscape1; break;
27 case '[' : state = kKey; deep++; break;
28 default : label += c;
29 }
30 break;
31
32 case kEscape1 :
33 label += c;
34 state = kLabel;
35 break;
36
37 case kEscape2 :
38 key += c;
39 state = kKey;
40 break;
41
42 case kEscape3 :
43 value += c;
44 state = kValue;
45 break;
46
47 case kKey :
48 assert (deep > 0);
49 switch (c) {
50 case '\\' : state = kEscape2;
51 break;
52
53 case '[' : deep++;
54 key += c;
55 break;
56
57 case ':' : if (deep == 1) {
58 state = kValue;
59 } else {
60 key += c;
61 }
62 break;
63 case ']' : deep--;
64 if (deep < 1) {
65 metadata[rmWhiteSpaces(key)].insert("");
66 state = kLabel;
67 key="";
68 value="";
69 } else {
70 key += c;
71 }
72 break;
73 default : key += c;
74 }
75 break;
76
77 case kValue :
78 assert (deep > 0);
79 switch (c) {
80 case '\\' : state = kEscape3;
81 break;
82
83 case '[' : deep++;
84 value += c;
85 break;
86
87 case ']' : deep--;
88 if (deep < 1) {
89 metadata[rmWhiteSpaces(key)].insert(rmWhiteSpaces(value));
90 state = kLabel;
91 key="";
92 value="";
93 } else {
94 value += c;
95 }
96 break;
97 default : value += c;
98 }
99 break;
100
101 default :
102 cerr << "ERROR unrecognized state " << state << endl;
103 }
104 }
105 label = rmWhiteSpaces(label);
106 }
107
108 //------------------------ specific schema -------------------------
109
110 string extractName(Tree fulllabel)
111 {
112 string name;
113 map<string, set<string> > metadata;
114
115 extractMetadata(tree2str(fulllabel), name, metadata);
116 return name;
117 }
118
119
120 /**
121 * removes enclosing quotes and transforms '<', '>' and '&' characters
122 */
123 static string xmlize(const string& fullsrc)
124 {
125 map<string, set<string> > metadata;
126 string dst;
127 string src;
128
129 extractMetadata(fullsrc, src, metadata);
130
131 for (size_t i=0; i<src.size(); i++) {
132 if (src[i] == '"' & (i==0 | i==src.size()-1)) {
133 // nothing to do just skip the quotes
134 } else {
135 switch (src[i]) {
136 case '<' : dst += "&lt;"; break;
137 case '>' : dst += "&gt;"; break;
138 case '&' : dst += "&amp;"; break;
139 default : dst += src[i];
140 }
141 }
142 }
143 return dst;
144 }
145
146 void Description::print(int n, ostream& fout)
147 {
148 list<string>::iterator s;
149 list<int>::iterator t;
150
151 tab(n,fout); fout << "<faust>";
152
153 tab(n+1,fout); fout << "<name>" << xmlize(fName) << "</name>";
154 tab(n+1,fout); fout << "<author>" << xmlize(fAuthor) << "</author>";
155 tab(n+1,fout); fout << "<copyright>" << xmlize(fCopyright) << "</copyright>";
156 tab(n+1,fout); fout << "<license>" << xmlize(fLicense) << "</license>";
157 tab(n+1,fout); fout << "<version>" << xmlize(fVersion) << "</version>";
158 tab(n+1,fout); fout << "<inputs>" << fInputs << "</inputs>";
159 tab(n+1,fout); fout << "<outputs>" << fOutputs << "</outputs>";
160
161 tab(n+1,fout); fout << "<ui>";
162
163 // active widget list
164 tab(n+2,fout); fout << "<activewidgets>";
165 tab(n+3,fout); fout << "<count>" << fActiveWidgetCount << "</count>";
166 for (s = fActiveLines.begin(); s != fActiveLines.end(); s++) {
167 tab(n+3, fout); fout << *s;
168 }
169 tab(n+2,fout); fout << "</activewidgets>";
170
171 tab(n+2,fout);
172
173 // passive widget list
174 tab(n+2,fout); fout << "<passivewidgets>";
175 tab(n+3,fout); fout << "<count>" << fPassiveWidgetCount << "</count>";
176 for (s = fPassiveLines.begin(); s != fPassiveLines.end(); s++) {
177 tab(n+3, fout); fout << *s;
178 }
179 tab(n+2,fout); fout << "</passivewidgets>";
180
181
182 tab(n+2,fout);
183
184 // widget layout
185 tab(n+2,fout); fout << "<layout>";
186 for ( t = fLayoutTabs.begin(), s = fLayoutLines.begin();
187 s != fLayoutLines.end(); t++, s++) {
188 tab(n+3+*t, fout); fout << *s;
189 }
190 tab(n+2,fout); fout << "</layout>";
191
192 tab(n+1,fout); fout << "</ui>";
193
194
195 tab(n,fout); fout << "</faust>" << endl;
196
197 }
198
199 void Description::ui(Tree t)
200 {
201 addGroup(0,t);
202 }
203
204
205 void Description::addGroup(int level, Tree t)
206 {
207 Tree label, elements, varname, sig;
208 const char* groupnames[] = {"vgroup", "hgroup", "tgroup"};
209
210 if (isUiFolder(t, label, elements)) {
211
212 const int orient = tree2int(left(label));
213 const char * str = tree2str(right(label));
214
215 addLayoutLine(level, subst("<group type=\"$0\">", groupnames[orient]));
216 addLayoutLine(level+1, subst("<label>$0</label>", xmlize(str)));
217 while (!isNil(elements)) {
218 addGroup(level+1, right(hd(elements)));
219 elements = tl(elements);
220 }
221 addLayoutLine(level, "</group>");
222
223 } else if (isUiWidget(t, label, varname, sig)) {
224
225 int w = addWidget(label, varname, sig);
226 addLayoutLine(level, subst("<widgetref id=\"$0\" />", T(w)));
227
228 } else {
229
230 fprintf(stderr, "error in user interface generation 2\n");
231 exit(1);
232
233 }
234 }
235
236 void Description::tab (int n, ostream& fout)
237 {
238 fout << '\n';
239 while (n--) fout << '\t';
240 }
241
242 int Description::addWidget(Tree label, Tree varname, Tree sig)
243 {
244 Tree path, c, x, y, z;
245
246 // add an active widget description
247
248 if ( isSigButton(sig, path) ) {
249
250 fWidgetID++;
251 fActiveWidgetCount++;
252 addActiveLine(subst("<widget type=\"button\" id=\"$0\">", T(fWidgetID)));
253 addActiveLine(subst("\t<label>$0</label>", xmlize(tree2str(label))));
254 addActiveLine(subst("\t<varname>$0</varname>", tree2str(varname)));
255 addActiveLine("</widget>");
256
257 } else if ( isSigCheckbox(sig, path) ) {
258
259 fWidgetID++;
260 fActiveWidgetCount++;
261 addActiveLine(subst("<widget type=\"checkbox\" id=\"$0\">", T(fWidgetID)));
262 addActiveLine(subst("\t<label>$0</label>", xmlize(tree2str(label))));
263 addActiveLine(subst("\t<varname>$0</varname>", tree2str(varname)));
264 addActiveLine("</widget>");
265
266 } else if ( isSigVSlider(sig, path,c,x,y,z) ) {
267
268 fWidgetID++;
269 fActiveWidgetCount++;
270 addActiveLine(subst("<widget type=\"vslider\" id=\"$0\">", T(fWidgetID)));
271 addActiveLine(subst("\t<label>$0</label>", xmlize(tree2str(label))));
272 addActiveLine(subst("\t<varname>$0</varname>", tree2str(varname)));
273 addActiveLine(subst("\t<init>$0</init>", T(tree2double(c))));
274 addActiveLine(subst("\t<min>$0</min>", T(tree2double(x))));
275 addActiveLine(subst("\t<max>$0</max>", T(tree2double(y))));
276 addActiveLine(subst("\t<step>$0</step>", T(tree2double(z))));
277 addActiveLine("</widget>");
278
279 } else if ( isSigHSlider(sig, path,c,x,y,z) ) {
280
281 fWidgetID++;
282 fActiveWidgetCount++;
283 addActiveLine(subst("<widget type=\"hslider\" id=\"$0\">", T(fWidgetID)));
284 addActiveLine(subst("\t<label>$0</label>", xmlize(tree2str(label))));
285 addActiveLine(subst("\t<varname>$0</varname>", tree2str(varname)));
286 addActiveLine(subst("\t<init>$0</init>", T(tree2double(c))));
287 addActiveLine(subst("\t<min>$0</min>", T(tree2double(x))));
288 addActiveLine(subst("\t<max>$0</max>", T(tree2double(y))));
289 addActiveLine(subst("\t<step>$0</step>", T(tree2double(z))));
290 addActiveLine("</widget>");
291
292 } else if ( isSigNumEntry(sig, path,c,x,y,z) ) {
293
294 fWidgetID++;
295 fActiveWidgetCount++;
296 addActiveLine(subst("<widget type=\"nentry\" id=\"$0\">", T(fWidgetID)));
297 addActiveLine(subst("\t<label>$0</label>", xmlize(tree2str(label))));
298 addActiveLine(subst("\t<varname>$0</varname>", tree2str(varname)));
299 addActiveLine(subst("\t<init>$0</init>", T(tree2double(c))));
300 addActiveLine(subst("\t<min>$0</min>", T(tree2double(x))));
301 addActiveLine(subst("\t<max>$0</max>", T(tree2double(y))));
302 addActiveLine(subst("\t<step>$0</step>", T(tree2double(z))));
303 addActiveLine("</widget>");
304
305
306 // add a passive widget description
307
308 } else if ( isSigVBargraph(sig,path,x,y,z) ) {
309
310 fWidgetID++;
311 fPassiveWidgetCount++;
312 addPassiveLine(subst("<widget type=\"vbargraph\" id=\"$0\">", T(fWidgetID)));
313 addPassiveLine(subst("\t<label>$0</label>", xmlize(tree2str(label))));
314 addPassiveLine(subst("\t<varname>$0</varname>", tree2str(varname)));
315 addPassiveLine(subst("\t<min>$0</min>", T(tree2double(x))));
316 addPassiveLine(subst("\t<max>$0</max>", T(tree2double(y))));
317 addPassiveLine("</widget>");
318
319 } else if ( isSigHBargraph(sig,path,x,y,z) ) {
320
321 fWidgetID++;
322 fPassiveWidgetCount++;
323 addPassiveLine(subst("<widget type=\"hbargraph\" id=\"$0\">", T(fWidgetID)));
324 addPassiveLine(subst("\t<label>$0</label>", xmlize(tree2str(label))));
325 addPassiveLine(subst("\t<varname>$0</varname>", tree2str(varname)));
326 addPassiveLine(subst("\t<min>$0</min>", T(tree2double(x))));
327 addPassiveLine(subst("\t<max>$0</max>", T(tree2double(y))));
328 addPassiveLine("</widget>");
329
330 } else {
331 fprintf(stderr, "Error describing widget : unrecognized expression\n");
332 exit(1);
333 }
334
335 return fWidgetID;
336 }
337
338
339