1 /************************************************************************
2  ************************************************************************
3     FAUST compiler
4     Copyright (C) 2003-2014 GRAME, Centre National de Creation Musicale
5     ---------------------------------------------------------------------
6     This program is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10 
11     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15 
16     You should have received a copy of the GNU General Public License
17     along with this program; if not, write to the Free Software
18     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19  ************************************************************************
20  ************************************************************************/
21 
22 #ifdef WIN32
23 #pragma warning(disable : 4251 4275 4800)
24 #endif
25 
26 #include "wasm_dynamic_dsp_aux.hh"
27 #include "Text.hh"
28 #include "compatibility.hh"
29 
30 #ifdef WIN32
31 #define strdup _strdup
32 #endif
33 
34 #ifdef EMCC
35 #include <emscripten.h>
36 #include <emscripten/bind.h>
37 using namespace emscripten;
38 #endif
39 
createWasmDSPFactoryFromString2(const string & name_app,const string & dsp_content,const vector<string> & argv,bool internal_memory)40 wasm_dsp_factory* wasm_dynamic_dsp_factory::createWasmDSPFactoryFromString2(const string&         name_app,
41                                                                             const string&         dsp_content,
42                                                                             const vector<string>& argv,
43                                                                             bool                  internal_memory)
44 {
45     int         argc1 = 0;
46     const char* argv1[64];
47     for (size_t i = 0; i < argv.size(); i++) {
48         argv1[argc1++] = argv[i].c_str();
49     }
50     argv1[argc1] = nullptr;  // NULL terminated argv
51 
52     return createWasmDSPFactoryFromString(name_app, dsp_content, argc1, argv1,
53                                                                wasm_dsp_factory::gErrorMessage, internal_memory);
54 }
55 
generateWasmFromString2(const std::string & name_app,const std::string & dsp_content,const std::vector<std::string> & argv,bool internal_memory)56 std::string wasm_dynamic_dsp_factory::generateWasmFromString2(const std::string&           name_app,
57                                                             const std::string&              dsp_content,
58                                                             const std::vector<std::string>& argv,
59                                                             bool                            internal_memory)
60 {
61     int         argc1 = 0;
62     const char* argv1[64];
63     for (size_t i = 0; i < argv.size(); i++) {
64         argv1[argc1++] = argv[i].c_str();
65     }
66     argv1[argc1] = nullptr;  // NULL terminated argv
67 
68     return generateWasmFromString(name_app, dsp_content, argc1, argv1,wasm_dsp_factory::gErrorMessage, internal_memory);
69 }
70 
71 // C++ API
72 
createWasmDSPFactoryFromFile(const string & filename,int argc,const char * argv[],string & error_msg,bool internal_memory)73 EXPORT wasm_dsp_factory* createWasmDSPFactoryFromFile(const string& filename, int argc, const char* argv[],
74                                                       string& error_msg, bool internal_memory)
75 {
76     string base = basename((char*)filename.c_str());
77     size_t pos  = filename.find(".dsp");
78 
79     if (pos != string::npos) {
80         return createWasmDSPFactoryFromString(base.substr(0, pos), pathToContent(filename), argc, argv, error_msg,
81                                               internal_memory);
82     } else {
83         error_msg = "ERROR : file extension is not the one expected (.dsp expected)\n";
84         return nullptr;
85     }
86 }
87 
createWasmDSPFactoryFromString(const string & name_app,const string & dsp_content,int argc,const char * argv[],string & error_msg,bool internal_memory)88 EXPORT wasm_dsp_factory* createWasmDSPFactoryFromString(const string& name_app, const string& dsp_content, int argc,
89                                                         const char* argv[], string& error_msg, bool internal_memory)
90 {
91     string expanded_dsp_content, sha_key;
92 
93     if ((expanded_dsp_content = sha1FromDSP(name_app, dsp_content, argc, argv, sha_key)) == "") {
94         return nullptr;
95     } else {
96         int         argc1 = 0;
97         const char* argv1[64];
98         argv1[argc1++] = "faust";
99         argv1[argc1++] = "-lang";
100         // argv1[argc1++] = (internal_memory) ? "wasm-i" : "wasm-e";
101         argv1[argc1++] = (internal_memory) ? "wasm-ib" : "wasm-eb";
102         argv1[argc1++] = "-o";
103         argv1[argc1++] = "binary";
104         // Copy argument
105         for (int i = 0; i < argc; i++) {
106             argv1[argc1++] = argv[i];
107         }
108         argv1[argc1] = nullptr;  // NULL terminated argv
109 
110         dsp_factory_base* dsp_factory_aux = createFactory(name_app.c_str(), dsp_content.c_str(), argc1, argv1, error_msg, true);
111         if (dsp_factory_aux) {
112             dsp_factory_aux->setName(name_app);
113             wasm_dsp_factory* factory = new wasm_dsp_factory(dsp_factory_aux);
114             wasm_dsp_factory::gWasmFactoryTable.setFactory(factory);
115             factory->setSHAKey(sha_key);
116             factory->setDSPCode(expanded_dsp_content);
117             return factory;
118         } else {
119             return nullptr;
120         }
121     }
122 }
123 
createWasmDSPFactoryFromSignals(const std::string & name_app,tvec signals,int argc,const char * argv[],std::string & error_msg,bool internal_memory)124 EXPORT wasm_dsp_factory* createWasmDSPFactoryFromSignals(const std::string& name_app, tvec signals,
125                                                          int argc, const char* argv[], std::string& error_msg,
126                                                          bool internal_memory)
127 {
128     int         argc1 = 0;
129     const char* argv1[64];
130     argv1[argc1++] = "faust";
131     argv1[argc1++] = "-lang";
132     // argv1[argc1++] = (internal_memory) ? "wasm-i" : "wasm-e";
133     argv1[argc1++] = (internal_memory) ? "wasm-ib" : "wasm-eb";
134     argv1[argc1++] = "-o";
135     argv1[argc1++] = "binary";
136     // Copy argument
137     for (int i = 0; i < argc; i++) {
138         argv1[argc1++] = argv[i];
139     }
140     argv1[argc1] = nullptr;  // NULL terminated argv
141 
142     dsp_factory_base* dsp_factory_aux = createFactory(name_app.c_str(), signals, argc1, argv1, error_msg);
143     if (dsp_factory_aux) {
144         dsp_factory_aux->setName(name_app);
145         wasm_dsp_factory* factory = new wasm_dsp_factory(dsp_factory_aux);
146         wasm_dsp_factory::gWasmFactoryTable.setFactory(factory);
147         return factory;
148     } else {
149         return nullptr;
150     }
151 }
152 
generateWasmFromString(const string & name_app,const string & dsp_content,int argc,const char * argv[],string & error_msg,bool internal_memory)153 EXPORT std::string generateWasmFromString(const string& name_app, const string& dsp_content, int argc,
154                                          const char* argv[], string& error_msg, bool internal_memory)
155 {
156     int         argc1 = 0;
157     const char* argv1[64];
158     argv1[argc1++] = "faust";
159     argv1[argc1++] = "-lang";
160     // argv1[argc1++] = (internal_memory) ? "wasm-i" : "wasm-e";
161     argv1[argc1++] = (internal_memory) ? "wasm-ib" : "wasm-eb";
162     argv1[argc1++] = "-o";
163     argv1[argc1++] = "binary";
164     for (int i = 0; i < argc; i++) {
165         argv1[argc1++] = argv[i];
166     }
167     argv1[argc1] = nullptr;  // NULL terminated argv
168 
169     dsp_factory_base* dsp_factory_aux = createFactory(name_app.c_str(), dsp_content.c_str(), argc1, argv1, error_msg, true);
170     return (dsp_factory_aux) ? dsp_factory_aux->getBinaryCode() : "";
171 }
172 
173 #ifdef __cplusplus
174 extern "C" {
175 #endif
176 
deleteAllWasmCDSPFactories()177 EXPORT void deleteAllWasmCDSPFactories()
178 {
179     deleteAllWasmDSPFactories();
180 }
181 
createWasmCDSPFactoryFromFile2(const char * filename,int argc,const char * argv[],char * error_msg,bool internal_memory)182 EXPORT wasm_dsp_factory* createWasmCDSPFactoryFromFile2(const char* filename, int argc, const char* argv[],
183                                                         char* error_msg, bool internal_memory)
184 {
185     string error_msg_aux;
186     wasm_dsp_factory* factory = createWasmDSPFactoryFromFile(filename, argc, argv, error_msg_aux, internal_memory);
187     strncpy(error_msg, error_msg_aux.c_str(), 4096);
188     return factory;
189 }
190 
createWasmCDSPFactoryFromString2(const char * name_app,const char * dsp_content,int argc,const char * argv[],char * error_msg,bool internal_memory)191 EXPORT wasm_dsp_factory* createWasmCDSPFactoryFromString2(const char* name_app, const char* dsp_content, int argc,
192                                                           const char* argv[], char* error_msg, bool internal_memory)
193 {
194     string error_msg_aux;
195     wasm_dsp_factory* factory =
196         createWasmDSPFactoryFromString(name_app, dsp_content, argc, argv, error_msg_aux, internal_memory);
197     strncpy(error_msg, error_msg_aux.c_str(), 4096);
198     return factory;
199 }
200 
createWasmCDSPFactoryFromSignals2(const char * name_app,tvec signals,int argc,const char * argv[],char * error_msg,bool internal_memory)201 EXPORT wasm_dsp_factory* createWasmCDSPFactoryFromSignals2(const char* name_app, tvec signals,
202                                                            int argc, const char* argv[], char* error_msg,
203                                                            bool internal_memory)
204 {
205     string error_msg_aux;
206     wasm_dsp_factory* factory =
207         createWasmDSPFactoryFromSignals(name_app, signals, argc, argv, error_msg_aux, internal_memory);
208     strncpy(error_msg, error_msg_aux.c_str(), 4096);
209     return factory;
210 }
211 
createWasmCDSPFactoryAux(wasm_dsp_factory * factory,const string & error_msg_aux,char * error_msg)212 static WasmModule* createWasmCDSPFactoryAux(wasm_dsp_factory* factory, const string& error_msg_aux, char* error_msg)
213 {
214     strncpy(error_msg, error_msg_aux.c_str(), 4096);
215     if (factory) {
216         WasmModule* res = static_cast<WasmModule*>(calloc(1, sizeof(WasmModule)));
217 
218         // 'Binary' string, so directly copy its raw content
219         string code = factory->getBinaryCode();
220         res->fWASMCodeSize = (int)code.size();
221         res->fWASMCode     = (char*)malloc(res->fWASMCodeSize);
222         memcpy(res->fWASMCode, code.c_str(), res->fWASMCodeSize);
223 
224         stringstream dst2;
225         factory->writeHelper(&dst2, false, false);
226         res->fJSHelpers = strdup(flatten(dst2.str()).c_str());
227 
228         return res;
229         // And keep factory...
230     } else {
231         return nullptr;
232     }
233 }
234 
createWasmCDSPFactoryFromFile(const char * filename,int argc,const char * argv[],char * error_msg,bool internal_memory)235 EXPORT WasmModule* createWasmCDSPFactoryFromFile(const char* filename, int argc, const char* argv[], char* error_msg,
236                                                  bool internal_memory)
237 {
238     string            error_msg_aux;
239     wasm_dsp_factory* factory = createWasmDSPFactoryFromFile(filename, argc, argv, error_msg_aux, internal_memory);
240     return createWasmCDSPFactoryAux(factory, error_msg_aux, error_msg);
241 }
242 
createWasmCDSPFactoryFromString(const char * name_app,const char * dsp_content,int argc,const char * argv[],char * error_msg,bool internal_memory)243 EXPORT WasmModule* createWasmCDSPFactoryFromString(const char* name_app, const char* dsp_content, int argc,
244                                                    const char* argv[], char* error_msg, bool internal_memory)
245 {
246     string            error_msg_aux;
247     wasm_dsp_factory* factory =
248         createWasmDSPFactoryFromString(name_app, dsp_content, argc, argv, error_msg_aux, internal_memory);
249     return createWasmCDSPFactoryAux(factory, error_msg_aux, error_msg);
250 }
251 
getWasmCModule(WasmModule * module)252 EXPORT const char* getWasmCModule(WasmModule* module)
253 {
254     return module->fWASMCode;
255 }
256 
getWasmCModuleSize(WasmModule * module)257 EXPORT int getWasmCModuleSize(WasmModule* module)
258 {
259     return module->fWASMCodeSize;
260 }
261 
getWasmCHelpers(WasmModule * module)262 EXPORT const char* getWasmCHelpers(WasmModule* module)
263 {
264     return module->fJSHelpers;
265 }
266 
freeWasmCModule(WasmModule * module)267 EXPORT void freeWasmCModule(WasmModule* module)
268 {
269     free((void*)module->fWASMCode);
270     free((void*)module->fJSHelpers);
271     free(module);
272 }
273 
274 #ifdef __cplusplus
275 }
276 #endif
277 
278 #ifdef EMCC
279 
makeStringVector()280 vector<string> makeStringVector()
281 {
282     return vector<string>();
283 }
284 
EMSCRIPTEN_BINDINGS(CLASS_wasm_dynamic_dsp_factory)285 EMSCRIPTEN_BINDINGS(CLASS_wasm_dynamic_dsp_factory)
286 {
287     emscripten::function("makeStringVector", &makeStringVector);
288     register_vector<string>("vector<string>");
289     class_<wasm_dynamic_dsp_factory>("wasm_dynamic_dsp_factory")
290         .constructor()
291         .class_function("createWasmDSPFactoryFromString2", &wasm_dynamic_dsp_factory::createWasmDSPFactoryFromString2,
292                         allow_raw_pointers())
293         .class_function("generateWasmFromString2", &wasm_dynamic_dsp_factory::createWasmDSPFactoryFromString2,
294                     allow_raw_pointers());
295 }
296 
297 #endif
298