|
FAUST compiler
0.9.9.6b8
|
00001 /************************************************************************ 00002 ************************************************************************ 00003 FAUST compiler 00004 Copyright (C) 2003-2004 GRAME, Centre National de Creation Musicale 00005 --------------------------------------------------------------------- 00006 This program is free software; you can redistribute it and/or modify 00007 it under the terms of the GNU General Public License as published by 00008 the Free Software Foundation; either version 2 of the License, or 00009 (at your option) any later version. 00010 00011 This program is distributed in the hope that it will be useful, 00012 but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 GNU General Public License for more details. 00015 00016 You should have received a copy of the GNU General Public License 00017 along with this program; if not, write to the Free Software 00018 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 00019 ************************************************************************ 00020 ************************************************************************/ 00021 00022 00023 00024 /***************************************************************************** 00025 ****************************************************************************** 00026 FAUST SIGNAL COMPILER 00027 Y. Orlarey, (c) Grame 2002 00028 ------------------------------------------------------------------------------ 00029 Compile a list of FAUST signals into a C++ class . 00030 00031 History : 00032 --------- 00033 2002-02-08 : First version 00034 00035 ****************************************************************************** 00036 *****************************************************************************/ 00037 00038 00039 00040 #include "timing.hh" 00041 #include "compile.hh" 00042 #include "floats.hh" 00043 #include "sigtype.hh" 00044 00045 #include <stdio.h> 00046 //#include <iostream> 00047 00048 #include "sigprint.hh" 00049 #include "ppsig.hh" 00050 00051 #include "sigtyperules.hh" 00052 #include "simplify.hh" 00053 #include "privatise.hh" 00054 //#include "factorize.hh" 00055 00056 //#include "grouper.hh" 00057 //#include "sigvisitor.hh" 00058 00059 00060 00061 00062 /***************************************************************************** 00063 ****************************************************************************** 00064 00065 API 00066 00067 ****************************************************************************** 00068 *****************************************************************************/ 00069 00070 extern int gDetailsSwitch; 00071 extern string gMasterName; 00072 00073 00074 00075 00076 /***************************************************************************** 00077 ****************************************************************************** 00078 00079 GENERAL COMPILER METHODS 00080 00081 ****************************************************************************** 00082 *****************************************************************************/ 00083 00084 00085 00086 00087 00088 00089 00090 /***************************************************************************** 00091 constructor 00092 *****************************************************************************/ 00093 00094 Compiler::Compiler(const string& name, const string& super, int numInputs, int numOutputs, bool vec) 00095 : fClass(new Klass(name, super, numInputs, numOutputs, vec)), 00096 fNeedToDeleteClass(true), 00097 fUIRoot(uiFolder(cons(tree(0), tree(subst("$0", gMasterName))))), 00098 fDescription(0) 00099 {} 00100 00101 Compiler::Compiler(Klass* k) 00102 : fClass(k), 00103 fNeedToDeleteClass(false), 00104 fUIRoot(uiFolder(cons(tree(0), tree(subst("$0", gMasterName))))), 00105 fDescription(0) 00106 {} 00107 00108 00109 Compiler::~Compiler() 00110 { 00111 if (fNeedToDeleteClass) delete fClass; 00112 } 00113 00114 00115 00116 /***************************************************************************** 00117 user interface elements 00118 *****************************************************************************/ 00119 00123 void Compiler::addUIWidget(Tree path, Tree widget) 00124 { 00125 fUIRoot = putSubFolder(fUIRoot, path, widget); 00126 } 00127 00128 00133 Tree Compiler::prepareUserInterfaceTree(Tree t) 00134 { 00135 Tree root, elems; 00136 if (isUiFolder(t, root, elems) && isList(elems) && isNil(tl(elems)) ) { 00137 Tree folder = right(hd(elems)); 00138 return (isUiFolder(folder)) ? folder : t; 00139 } 00140 return t; 00141 } 00142 00143 //================================= some string processing utilities ================================= 00144 00148 static string wdel(const string& s) 00149 { 00150 size_t i = 0; 00151 size_t j = s.size(); 00152 while (i<j && s[i]==' ') i++; 00153 while (j>i && s[j-1] == ' ') j--; 00154 return s.substr(i,j-i); 00155 } 00156 00157 00158 //================================= BUILD USER INTERFACE METHOD ================================= 00159 00164 void Compiler::generateUserInterfaceTree(Tree t) 00165 { 00166 Tree label, elements, varname, sig; 00167 00168 if (isUiFolder(t, label, elements)) { 00169 const int orient = tree2int(left(label)); 00170 const char * str = tree2str(right(label)); 00171 const char * model; 00172 00173 // extract metadata from group label str resulting in a simplifiedLabel 00174 // and metadata declarations for fictive zone at address 0 00175 string simplifiedLabel; 00176 map<string, set<string> > metadata; 00177 extractMetadata(str, simplifiedLabel, metadata); 00178 00179 // add metadata if any 00180 for (map<string, set<string> >::iterator i = metadata.begin(); i != metadata.end(); i++) { 00181 const string& key = i->first; 00182 const set<string>& values = i->second; 00183 for (set<string>::const_iterator j = values.begin(); j != values.end(); j++) { 00184 fClass->addUICode(subst("interface->declare($0, \"$1\", \"$2\");", "0", wdel(key) ,wdel(*j))); 00185 } 00186 } 00187 //----------------- 00188 00189 00190 switch (orient) { 00191 case 0 : model = "interface->openVerticalBox(\"$0\");"; break; 00192 case 1 : model = "interface->openHorizontalBox(\"$0\");"; break; 00193 case 2 : model = "interface->openTabBox(\"$0\");"; break; 00194 default : 00195 fprintf(stderr, "error in user interface generation 1\n"); 00196 exit(1); 00197 } 00198 fClass->addUICode(subst(model, simplifiedLabel)); 00199 generateUserInterfaceElements(elements); 00200 fClass->addUICode("interface->closeBox();"); 00201 00202 } else if (isUiWidget(t, label, varname, sig)) { 00203 00204 generateWidgetCode(label, varname, sig); 00205 00206 } else { 00207 00208 fprintf(stderr, "error in user interface generation 2\n"); 00209 exit(1); 00210 00211 } 00212 } 00213 00217 void Compiler::generateUserInterfaceElements(Tree elements) 00218 { 00219 while (!isNil(elements)) { 00220 generateUserInterfaceTree(right(hd(elements))); 00221 elements = tl(elements); 00222 } 00223 } 00224 00229 void Compiler::generateWidgetCode(Tree fulllabel, Tree varname, Tree sig) 00230 { 00231 Tree path, c, x, y, z; 00232 string label; 00233 map<string, set<string> > metadata; 00234 00235 extractMetadata(tree2str(fulllabel), label, metadata); 00236 00237 // add metadata if any 00238 for (map<string, set<string> >::iterator i = metadata.begin(); i != metadata.end(); i++) { 00239 const string& key = i->first; 00240 const set<string>& values = i->second; 00241 for (set<string>::const_iterator j = values.begin(); j != values.end(); j++) { 00242 fClass->addUICode(subst("interface->declare(&$0, \"$1\", \"$2\");", tree2str(varname), wdel(key) ,wdel(*j))); 00243 } 00244 } 00245 00246 if ( isSigButton(sig, path) ) { 00247 fClass->incUIActiveCount(); 00248 fClass->addUICode(subst("interface->addButton(\"$0\", &$1);", label, tree2str(varname))); 00249 00250 } else if ( isSigCheckbox(sig, path) ) { 00251 fClass->incUIActiveCount(); 00252 fClass->addUICode(subst("interface->addCheckButton(\"$0\", &$1);", label, tree2str(varname))); 00253 00254 } else if ( isSigVSlider(sig, path,c,x,y,z) ) { 00255 fClass->incUIActiveCount(); 00256 fClass->addUICode(subst("interface->addVerticalSlider(\"$0\", &$1, $2, $3, $4, $5);", 00257 label, 00258 tree2str(varname), 00259 T(tree2float(c)), 00260 T(tree2float(x)), 00261 T(tree2float(y)), 00262 T(tree2float(z)))); 00263 00264 } else if ( isSigHSlider(sig, path,c,x,y,z) ) { 00265 fClass->incUIActiveCount(); 00266 fClass->addUICode(subst("interface->addHorizontalSlider(\"$0\", &$1, $2, $3, $4, $5);", 00267 label, 00268 tree2str(varname), 00269 T(tree2float(c)), 00270 T(tree2float(x)), 00271 T(tree2float(y)), 00272 T(tree2float(z)))); 00273 00274 } else if ( isSigNumEntry(sig, path,c,x,y,z) ) { 00275 fClass->incUIActiveCount(); 00276 fClass->addUICode(subst("interface->addNumEntry(\"$0\", &$1, $2, $3, $4, $5);", 00277 label, 00278 tree2str(varname), 00279 T(tree2float(c)), 00280 T(tree2float(x)), 00281 T(tree2float(y)), 00282 T(tree2float(z)))); 00283 00284 } else if ( isSigVBargraph(sig, path,x,y,z) ) { 00285 fClass->incUIPassiveCount(); 00286 fClass->addUICode(subst("interface->addVerticalBargraph(\"$0\", &$1, $2, $3);", 00287 label, 00288 tree2str(varname), 00289 T(tree2float(x)), 00290 T(tree2float(y)))); 00291 00292 } else if ( isSigHBargraph(sig, path,x,y,z) ) { 00293 fClass->incUIPassiveCount(); 00294 fClass->addUICode(subst("interface->addHorizontalBargraph(\"$0\", &$1, $2, $3);", 00295 label, 00296 tree2str(varname), 00297 T(tree2float(x)), 00298 T(tree2float(y)))); 00299 00300 } else { 00301 fprintf(stderr, "Error in generating widget code\n"); 00302 exit(1); 00303 } 00304 } 00305 00306 //==================================== USER INTERFACE MACROS ================================== 00307 00312 void Compiler::generateMacroInterfaceTree(const string& pathname, Tree t) 00313 { 00314 Tree label, elements, varname, sig; 00315 00316 if (isUiFolder(t, label, elements)) { 00317 string pathname2 = pathname; 00318 //string str = unquote(tree2str(right(label))); 00319 string str = tree2str(right(label)); 00320 if (str.length()>0) pathname2 += str + "/"; 00321 generateMacroInterfaceElements(pathname2, elements); 00322 00323 } else if (isUiWidget(t, label, varname, sig)) { 00324 00325 generateWidgetMacro(pathname, label, varname, sig); 00326 00327 } else { 00328 00329 fprintf(stderr, "error in user interface macro generation 2\n"); 00330 exit(1); 00331 00332 } 00333 } 00334 00335 00339 void Compiler::generateMacroInterfaceElements(const string& pathname, Tree elements) 00340 { 00341 while (!isNil(elements)) { 00342 generateMacroInterfaceTree(pathname, right(hd(elements))); 00343 elements = tl(elements); 00344 } 00345 } 00346 00347 00352 void Compiler::generateWidgetMacro(const string& pathname, Tree fulllabel, Tree varname, Tree sig) 00353 { 00354 Tree path, c, x, y, z; 00355 string label; 00356 map<string, set<string> > metadata; 00357 00358 extractMetadata(tree2str(fulllabel), label, metadata); 00359 00360 //string pathlabel = pathname+unquote(label); 00361 string pathlabel = pathname+label; 00362 00363 00364 if ( isSigButton(sig, path) ) { 00365 fClass->addUIMacro(subst("FAUST_ADDBUTTON(\"$0\", $1);", pathlabel, tree2str(varname))); 00366 00367 } else if ( isSigCheckbox(sig, path) ) { 00368 fClass->addUIMacro(subst("FAUST_ADDCHECKBOX(\"$0\", $1);", pathlabel, tree2str(varname))); 00369 00370 } else if ( isSigVSlider(sig, path,c,x,y,z) ) { 00371 fClass->addUIMacro(subst("FAUST_ADDVERTICALSLIDER(\"$0\", $1, $2, $3, $4, $5);", 00372 pathlabel, 00373 tree2str(varname), 00374 T(tree2float(c)), 00375 T(tree2float(x)), 00376 T(tree2float(y)), 00377 T(tree2float(z)))); 00378 00379 } else if ( isSigHSlider(sig, path,c,x,y,z) ) { 00380 fClass->addUIMacro(subst("FAUST_ADDHORIZONTALSLIDER(\"$0\", $1, $2, $3, $4, $5);", 00381 pathlabel, 00382 tree2str(varname), 00383 T(tree2float(c)), 00384 T(tree2float(x)), 00385 T(tree2float(y)), 00386 T(tree2float(z)))); 00387 00388 } else if ( isSigNumEntry(sig, path,c,x,y,z) ) { 00389 fClass->addUIMacro(subst("FAUST_ADDNUMENTRY(\"$0\", $1, $2, $3, $4, $5);", 00390 pathlabel, 00391 tree2str(varname), 00392 T(tree2float(c)), 00393 T(tree2float(x)), 00394 T(tree2float(y)), 00395 T(tree2float(z)))); 00396 00397 } else if ( isSigVBargraph(sig, path,x,y,z) ) { 00398 fClass->addUIMacro(subst("FAUST_ADDVERTICALBARGRAPH(\"$0\", $1, $2, $3);", 00399 pathlabel, 00400 tree2str(varname), 00401 T(tree2float(x)), 00402 T(tree2float(y)))); 00403 00404 } else if ( isSigHBargraph(sig, path,x,y,z) ) { 00405 fClass->addUIMacro(subst("FAUST_ADDHORIZONTALBARGRAPH(\"$0\", $1, $2, $3);", 00406 pathlabel, 00407 tree2str(varname), 00408 T(tree2float(x)), 00409 T(tree2float(y)))); 00410 00411 } else { 00412 fprintf(stderr, "Error in generating widget code\n"); 00413 exit(1); 00414 } 00415 }
1.8.0