1 /************************************************************************ 2 IMPORTANT NOTE : this file contains two clearly delimited sections : 3 the ARCHITECTURE section (in two parts) and the USER section. Each section 4 is governed by its own copyright and license. Please check individually 5 each section for license and copyright information. 6 *************************************************************************/ 7 8 /*******************BEGIN ARCHITECTURE SECTION (part 1/2)****************/ 9 10 /************************************************************************ 11 FAUST Architecture File 12 Copyright (C) 2003-2011 GRAME, Centre National de Creation Musicale 13 --------------------------------------------------------------------- 14 This Architecture section is free software; you can redistribute it 15 and/or modify it under the terms of the GNU General Public License 16 as published by the Free Software Foundation; either version 3 of 17 the License, or (at your option) any later version. 18 19 This program is distributed in the hope that it will be useful, 20 but WITHOUT ANY WARRANTY; without even the implied warranty of 21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 GNU General Public License for more details. 23 24 You should have received a copy of the GNU General Public License 25 along with this program; If not, see <http://www.gnu.org/licenses/>. 26 27 EXCEPTION : As a special exception, you may create a larger work 28 that contains this FAUST architecture section and distribute 29 that work under terms of your choice, so long as this FAUST 30 architecture section is not modified. 31 32 ************************************************************************ 33 ************************************************************************/ 34 35 #ifndef __proxy_dsp__ 36 #define __proxy_dsp__ 37 38 #include <vector> 39 #include <map> 40 41 #include "faust/dsp/dsp.h" 42 #include "faust/gui/SimpleParser.h" 43 #include "faust/gui/JSONUI.h" 44 45 #ifdef _WIN32 46 #include <windows.h> 47 #define snprintf _snprintf 48 #endif 49 50 inline FAUSTFLOAT STR2REAL(const std::string& s) { return (strtod(s.c_str(), NULL)); } 51 52 //------------------------------------------------------------------- 53 // Decode a dsp JSON description and implement 'buildUserInterface' 54 //------------------------------------------------------------------- 55 56 struct JSONUIDecoder { 57 58 std::string fName; 59 60 std::map<std::string, std::string> fMetadatas; 61 std::vector<itemInfo*> fUiItems; 62 63 FAUSTFLOAT* fInControl; 64 FAUSTFLOAT* fOutControl; 65 66 std::string fJSON; 67 68 int fNumInputs, fNumOutputs; 69 int fInputItems, fOutputItems; 70 71 JSONUIDecoder(const std::string& json) 72 { 73 fJSON = json; 74 const char* p = fJSON.c_str(); 75 parseJson(p, fMetadatas, fUiItems); 76 77 // fMetadatas will contain the "meta" section as well as <name : val>, <inputs : val>, <ouputs : val> pairs 78 if (fMetadatas.find("name") != fMetadatas.end()) { 79 fName = fMetadatas["name"]; 80 fMetadatas.erase("name"); 81 } else { 82 fName = ""; 83 } 84 85 if (fMetadatas.find("inputs") != fMetadatas.end()) { 86 fNumInputs = atoi(fMetadatas["inputs"].c_str()); 87 fMetadatas.erase("inputs"); 88 } else { 89 fNumInputs = -1; 90 } 91 92 if (fMetadatas.find("outputs") != fMetadatas.end()) { 93 fNumOutputs = atoi(fMetadatas["outputs"].c_str()); 94 fMetadatas.erase("outputs"); 95 } else { 96 fNumOutputs = -1; 97 } 98 99 vector<itemInfo*>::iterator it; 100 fInputItems = 0; 101 fOutputItems = 0; 102 103 for (it = fUiItems.begin(); it != fUiItems.end(); it++) { 104 string type = (*it)->type; 105 if (type == "vslider" || type == "hslider" || type == "nentry" || type == "button") { 106 fInputItems++; 107 } else if (type == "hbargraph" || type == "vbargraph") { 108 fOutputItems++; 109 } 110 } 111 112 fInControl = new FAUSTFLOAT[fInputItems]; 113 fOutControl = new FAUSTFLOAT[fOutputItems]; 114 } 115 116 virtual ~JSONUIDecoder() 117 { 118 vector<itemInfo*>::iterator it; 119 for (it = fUiItems.begin(); it != fUiItems.end(); it++) { 120 delete(*it); 121 } 122 delete [] fInControl; 123 delete [] fOutControl; 124 } 125 126 void metadata(Meta* m) 127 { 128 std::map<std::string, std::string>::iterator it; 129 for (it = fMetadatas.begin(); it != fMetadatas.end(); it++) { 130 m->declare((*it).first.c_str(), (*it).second.c_str()); 131 } 132 } 133 134 void buildUserInterface(UI* ui) 135 { 136 // To be sure the floats are correctly encoded 137 char* tmp_local = setlocale(LC_ALL, NULL); 138 setlocale(LC_ALL, "C"); 139 140 int counterIn = 0; 141 int counterOut = 0; 142 vector<itemInfo*>::iterator it; 143 144 for (it = fUiItems.begin(); it != fUiItems.end(); it++) { 145 146 bool isInItem = false; 147 bool isOutItem = false; 148 string type = (*it)->type; 149 150 FAUSTFLOAT init = STR2REAL((*it)->init); 151 FAUSTFLOAT min = STR2REAL((*it)->min); 152 FAUSTFLOAT max = STR2REAL((*it)->max); 153 FAUSTFLOAT step = STR2REAL((*it)->step); 154 155 if (type == "vslider" || type == "hslider" || type == "nentry" || type == "button") { 156 isInItem = true; 157 } else if (type == "hbargraph" || type == "vbargraph") { 158 isOutItem = true; 159 } 160 161 // Meta data declaration for input items 162 if ((*it)->type.find("group") == string::npos && (*it)->type.find("bargraph") == string::npos && (*it)->type != "close") { 163 fInControl[counterIn] = init; 164 for (int i = 0; i < (*it)->meta.size(); i++) { 165 ui->declare(&fInControl[counterIn], (*it)->meta[i].first.c_str(), (*it)->meta[i].second.c_str()); 166 } 167 } 168 // Meta data declaration for output items 169 else if ((*it)->type.find("bargraph") != string::npos) { 170 fOutControl[counterOut] = init; 171 for (int i = 0; i < (*it)->meta.size(); i++) { 172 ui->declare(&fOutControl[counterOut], (*it)->meta[i].first.c_str(), (*it)->meta[i].second.c_str()); 173 } 174 } 175 // Meta data declaration for group opening or closing 176 else { 177 for (int i = 0; i < (*it)->meta.size(); i++) { 178 ui->declare(0, (*it)->meta[i].first.c_str(), (*it)->meta[i].second.c_str()); 179 } 180 } 181 182 if (type == "hgroup") { 183 ui->openHorizontalBox((*it)->label.c_str()); 184 } else if (type == "vgroup") { 185 ui->openVerticalBox((*it)->label.c_str()); 186 } else if (type == "tgroup") { 187 ui->openTabBox((*it)->label.c_str()); 188 } else if (type == "vslider") { 189 ui->addVerticalSlider((*it)->label.c_str(), &fInControl[counterIn], init, min, max, step); 190 } else if (type == "hslider") { 191 ui->addHorizontalSlider((*it)->label.c_str(), &fInControl[counterIn], init, min, max, step); 192 } else if (type == "checkbox") { 193 ui->addCheckButton((*it)->label.c_str(), &fInControl[counterIn]); 194 } else if (type == "hbargraph") { 195 ui->addHorizontalBargraph((*it)->label.c_str(), &fOutControl[counterOut], min, max); 196 } else if (type == "vbargraph") { 197 ui->addVerticalBargraph((*it)->label.c_str(), &fOutControl[counterOut], min, max); 198 } else if (type == "nentry") { 199 ui->addNumEntry((*it)->label.c_str(), &fInControl[counterIn], init, min, max, step); 200 } else if (type == "button") { 201 ui->addButton((*it)->label.c_str(), &fInControl[counterIn]); 202 } else if (type == "close") { 203 ui->closeBox(); 204 } 205 206 if (isInItem) { 207 counterIn++; 208 } 209 210 if (isOutItem) { 211 counterOut++; 212 } 213 } 214 215 setlocale(LC_ALL, tmp_local); 216 } 217 218 }; 219 220 //---------------------------------------------------------------- 221 // Proxy dsp definition created from the DSP JSON description 222 // This class allows a 'proxy' dsp to control a real dsp 223 // possibly running somewhere else. 224 //---------------------------------------------------------------- 225 226 class proxy_dsp : public dsp { 227 228 private: 229 230 int fSamplingFreq; 231 JSONUIDecoder* fDecoder; 232 233 public: 234 235 proxy_dsp(const string& json) 236 { 237 fDecoder = new JSONUIDecoder(json); 238 fSamplingFreq = -1; 239 } 240 241 proxy_dsp(dsp* dsp) 242 { 243 JSONUI builder(dsp->getNumInputs(), dsp->getNumOutputs()); 244 dsp->metadata(&builder); 245 dsp->buildUserInterface(&builder); 246 fSamplingFreq = dsp->getSampleRate(); 247 fDecoder = new JSONUIDecoder(builder.JSON()); 248 } 249 250 virtual ~proxy_dsp() 251 { 252 delete fDecoder; 253 } 254 255 virtual int getNumInputs() { return fDecoder->fNumInputs; } 256 virtual int getNumOutputs() { return fDecoder->fNumOutputs; } 257 258 virtual void buildUserInterface(UI* ui) { fDecoder->buildUserInterface(ui); } 259 260 // To possibly implement in a concrete proxy dsp 261 virtual void init(int samplingRate) { fSamplingFreq = samplingRate; } 262 virtual void instanceInit(int samplingRate) {} 263 virtual void instanceConstants(int samplingRate) {} 264 virtual void instanceResetUserInterface() {} 265 virtual void instanceClear() {} 266 267 virtual int getSampleRate() { return fSamplingFreq; } 268 269 virtual proxy_dsp* clone() { return new proxy_dsp(fDecoder->fJSON); } 270 virtual void metadata(Meta* m) { fDecoder->metadata(m); } 271 272 virtual void compute(int count, FAUSTFLOAT** inputs, FAUSTFLOAT** outputs) {} 273 virtual void compute(double date_usec, int count, FAUSTFLOAT** inputs, FAUSTFLOAT** outputs) {} 274 275 }; 276 277 #endif 278