1 /************************************************************************
2  ************************************************************************
3     FAUST Architecture File
4 	Copyright (C) 2006-2011 Albert Graef <Dr.Graef@t-online.de>
5     ---------------------------------------------------------------------
6     This program is free software; you can redistribute it and/or modify
7     it under the terms of the GNU Lesser General Public License as
8 	published by the Free Software Foundation; either version 2.1 of the
9 	License, or (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 Lesser General Public License for more details.
15 
16     You should have received a copy of the GNU Lesser General Public
17  	License along with the GNU C Library; if not, write to the Free
18   	Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19   	02111-1307 USA.
20  ************************************************************************
21  ************************************************************************/
22 
23 /* Pd architecture file, written by Albert Graef <Dr.Graef@t-online.de>.
24    This was derived from minimal.cpp included in the Faust distribution.
25    Please note that this is to be compiled as a shared library, which is
26    then loaded dynamically by Pd as an external. */
27 
28 #include <stdlib.h>
29 #include <math.h>
30 #include <string>
31 
32 #include "faust/misc.h"
33 #include "faust/gui/UI.h"
34 #include "faust/gui/meta.h"
35 #include "faust/dsp/dsp.h"
36 
37 /******************************************************************************
38 *******************************************************************************
39 
40 							       VECTOR INTRINSICS
41 
42 *******************************************************************************
43 *******************************************************************************/
44 
45 <<includeIntrinsic>>
46 
47 /***************************************************************************
48    Pd UI interface
49  ***************************************************************************/
50 
51 enum ui_elem_type_t {
52   UI_BUTTON, UI_CHECK_BUTTON,
53   UI_V_SLIDER, UI_H_SLIDER, UI_NUM_ENTRY,
54   UI_V_BARGRAPH, UI_H_BARGRAPH,
55   UI_END_GROUP, UI_V_GROUP, UI_H_GROUP, UI_T_GROUP
56 };
57 
58 struct ui_elem_t {
59   ui_elem_type_t type;
60   char *label;
61   float *zone;
62   float init, min, max, step;
63 };
64 
65 class PdUI : public UI
66 {
67 public:
68   const char *name;
69   int nelems, level;
70   ui_elem_t *elems;
71 
72   PdUI();
73   PdUI(const char *nm, const char *s);
74   virtual ~PdUI();
75 
76 protected:
77   std::string path;
78   void add_elem(ui_elem_type_t type, const char *label = NULL);
79   void add_elem(ui_elem_type_t type, const char *label, float *zone);
80   void add_elem(ui_elem_type_t type, const char *label, float *zone,
81 		float init, float min, float max, float step);
82   void add_elem(ui_elem_type_t type, const char *label, float *zone,
83 		float min, float max);
84 
85 public:
86   virtual void addButton(const char* label, float* zone);
87   virtual void addCheckButton(const char* label, float* zone);
88   virtual void addVerticalSlider(const char* label, float* zone, float init, float min, float max, float step);
89   virtual void addHorizontalSlider(const char* label, float* zone, float init, float min, float max, float step);
90   virtual void addNumEntry(const char* label, float* zone, float init, float min, float max, float step);
91 
92   virtual void addHorizontalBargraph(const char* label, float* zone, float min, float max);
93   virtual void addVerticalBargraph(const char* label, float* zone, float min, float max);
94 
95   virtual void openTabBox(const char* label);
96   virtual void openHorizontalBox(const char* label);
97   virtual void openVerticalBox(const char* label);
98   virtual void closeBox();
99 
100   virtual void run();
101 };
102 
mangle(const char * name,int level,const char * s)103 static std::string mangle(const char *name, int level, const char *s)
104 {
105   const char *s0 = s;
106   std::string t = "";
107   if (!s) return t;
108   // Get rid of bogus "0x00" labels in recent Faust revisions. Also, for
109   // backward compatibility with old Faust versions, make sure that default
110   // toplevel groups and explicit toplevel groups with an empty label are
111   // treated alike (these both return "0x00" labels in the latest Faust, but
112   // would be treated inconsistently in earlier versions).
113   if (!*s || strcmp(s, "0x00") == 0) {
114     if (level == 0)
115       // toplevel group with empty label, map to dsp name
116       s = name;
117     else
118       // empty label
119       s = "";
120   }
121   while (*s)
122     if (isalnum(*s))
123       t += *(s++);
124     else {
125       const char *s1 = s;
126       while (*s && !isalnum(*s)) ++s;
127       if (s1 != s0 && *s) t += "-";
128     }
129   return t;
130 }
131 
normpath(std::string path)132 static std::string normpath(std::string path)
133 {
134   path = std::string("/")+path;
135   int pos = path.find("//");
136   while (pos >= 0) {
137     path.erase(pos, 1);
138     pos = path.find("//");
139   }
140   size_t len = path.length();
141   if (len > 1 && path[len-1] == '/')
142     path.erase(len-1, 1);
143   return path;
144 }
145 
pathcat(std::string path,std::string label)146 static std::string pathcat(std::string path, std::string label)
147 {
148   if (path.empty())
149     return normpath(label);
150   else if (label.empty())
151     return normpath(path);
152   else
153     return normpath(path+"/"+label);
154 }
155 
PdUI()156 PdUI::PdUI()
157 {
158   nelems = level = 0;
159   elems = NULL;
160   name = "";
161   path = "";
162 }
163 
PdUI(const char * nm,const char * s)164 PdUI::PdUI(const char *nm, const char *s)
165 {
166   nelems = level = 0;
167   elems = NULL;
168   name = nm?nm:"";
169   path = s?s:"";
170 }
171 
~PdUI()172 PdUI::~PdUI()
173 {
174   if (elems) {
175     for (int i = 0; i < nelems; i++)
176       if (elems[i].label)
177 	free(elems[i].label);
178     free(elems);
179   }
180 }
181 
add_elem(ui_elem_type_t type,const char * label)182 inline void PdUI::add_elem(ui_elem_type_t type, const char *label)
183 {
184   ui_elem_t *elems1 = (ui_elem_t*)realloc(elems, (nelems+1)*sizeof(ui_elem_t));
185   if (elems1)
186     elems = elems1;
187   else
188     return;
189   std::string s = pathcat(path, mangle(name, level, label));
190   elems[nelems].type = type;
191   elems[nelems].label = strdup(s.c_str());
192   elems[nelems].zone = NULL;
193   elems[nelems].init = 0.0;
194   elems[nelems].min = 0.0;
195   elems[nelems].max = 0.0;
196   elems[nelems].step = 0.0;
197   nelems++;
198 }
199 
add_elem(ui_elem_type_t type,const char * label,float * zone)200 inline void PdUI::add_elem(ui_elem_type_t type, const char *label, float *zone)
201 {
202   ui_elem_t *elems1 = (ui_elem_t*)realloc(elems, (nelems+1)*sizeof(ui_elem_t));
203   if (elems1)
204     elems = elems1;
205   else
206     return;
207   std::string s = pathcat(path, mangle(name, level, label));
208   elems[nelems].type = type;
209   elems[nelems].label = strdup(s.c_str());
210   elems[nelems].zone = zone;
211   elems[nelems].init = 0.0;
212   elems[nelems].min = 0.0;
213   elems[nelems].max = 1.0;
214   elems[nelems].step = 1.0;
215   nelems++;
216 }
217 
add_elem(ui_elem_type_t type,const char * label,float * zone,float init,float min,float max,float step)218 inline void PdUI::add_elem(ui_elem_type_t type, const char *label, float *zone,
219 			  float init, float min, float max, float step)
220 {
221   ui_elem_t *elems1 = (ui_elem_t*)realloc(elems, (nelems+1)*sizeof(ui_elem_t));
222   if (elems1)
223     elems = elems1;
224   else
225     return;
226   std::string s = pathcat(path, mangle(name, level, label));
227   elems[nelems].type = type;
228   elems[nelems].label = strdup(s.c_str());
229   elems[nelems].zone = zone;
230   elems[nelems].init = init;
231   elems[nelems].min = min;
232   elems[nelems].max = max;
233   elems[nelems].step = step;
234   nelems++;
235 }
236 
add_elem(ui_elem_type_t type,const char * label,float * zone,float min,float max)237 inline void PdUI::add_elem(ui_elem_type_t type, const char *label, float *zone,
238 			  float min, float max)
239 {
240   ui_elem_t *elems1 = (ui_elem_t*)realloc(elems, (nelems+1)*sizeof(ui_elem_t));
241   if (elems1)
242     elems = elems1;
243   else
244     return;
245   std::string s = pathcat(path, mangle(name, level, label));
246   elems[nelems].type = type;
247   elems[nelems].label = strdup(s.c_str());
248   elems[nelems].zone = zone;
249   elems[nelems].init = 0.0;
250   elems[nelems].min = min;
251   elems[nelems].max = max;
252   elems[nelems].step = 0.0;
253   nelems++;
254 }
255 
addButton(const char * label,float * zone)256 void PdUI::addButton(const char* label, float* zone)
257 { add_elem(UI_BUTTON, label, zone); }
addCheckButton(const char * label,float * zone)258 void PdUI::addCheckButton(const char* label, float* zone)
259 { add_elem(UI_CHECK_BUTTON, label, zone); }
addVerticalSlider(const char * label,float * zone,float init,float min,float max,float step)260 void PdUI::addVerticalSlider(const char* label, float* zone, float init, float min, float max, float step)
261 { add_elem(UI_V_SLIDER, label, zone, init, min, max, step); }
addHorizontalSlider(const char * label,float * zone,float init,float min,float max,float step)262 void PdUI::addHorizontalSlider(const char* label, float* zone, float init, float min, float max, float step)
263 { add_elem(UI_H_SLIDER, label, zone, init, min, max, step); }
addNumEntry(const char * label,float * zone,float init,float min,float max,float step)264 void PdUI::addNumEntry(const char* label, float* zone, float init, float min, float max, float step)
265 { add_elem(UI_NUM_ENTRY, label, zone, init, min, max, step); }
266 
addHorizontalBargraph(const char * label,float * zone,float min,float max)267 void PdUI::addHorizontalBargraph(const char* label, float* zone, float min, float max)
268 { add_elem(UI_H_BARGRAPH, label, zone, min, max); }
addVerticalBargraph(const char * label,float * zone,float min,float max)269 void PdUI::addVerticalBargraph(const char* label, float* zone, float min, float max)
270 { add_elem(UI_V_BARGRAPH, label, zone, min, max); }
271 
openTabBox(const char * label)272 void PdUI::openTabBox(const char* label)
273 {
274   if (!path.empty()) path += "/";
275   path += mangle(name, level, label);
276   level++;
277 }
openHorizontalBox(const char * label)278 void PdUI::openHorizontalBox(const char* label)
279 {
280   if (!path.empty()) path += "/";
281   path += mangle(name, level, label);
282   level++;
283 }
openVerticalBox(const char * label)284 void PdUI::openVerticalBox(const char* label)
285 {
286   if (!path.empty()) path += "/";
287   path += mangle(name, level, label);
288   level++;
289 }
closeBox()290 void PdUI::closeBox()
291 {
292   int pos = path.rfind("/");
293   if (pos < 0) pos = 0;
294   path.erase(pos);
295   level--;
296 }
297 
run()298 void PdUI::run() {}
299 
300 /******************************************************************************
301 *******************************************************************************
302 
303 			    FAUST DSP
304 
305 *******************************************************************************
306 *******************************************************************************/
307 
308 //----------------------------------------------------------------------------
309 //  FAUST generated signal processor
310 //----------------------------------------------------------------------------
311 
312 <<includeclass>>
313 
314 #include <stdio.h>
315 #include <string>
316 #include "m_pd.h"
317 
318 #define sym(name) xsym(name)
319 #define xsym(name) #name
320 #define faust_setup(name) xfaust_setup(name)
321 #define xfaust_setup(name) name ## _tilde_setup(void)
322 
323 // time for "active" toggle xfades in secs
324 #define XFADE_TIME 0.1f
325 
326 static t_class *faust_class;
327 
328 struct t_faust {
329   t_object x_obj;
330 #ifdef __MINGW32__
331   /* This seems to be necessary as some as yet undetermined Pd routine seems
332      to write past the end of x_obj on Windows. */
333   int fence; /* dummy field (not used) */
334 #endif
335   mydsp *dsp;
336   PdUI *ui;
337   std::string *label;
338   int active, xfade, n_xfade, rate, n_in, n_out;
339   t_sample **inputs, **outputs, **buf;
340   t_outlet *out;
341   t_sample f;
342 };
343 
344 static t_symbol *s_button, *s_checkbox, *s_vslider, *s_hslider, *s_nentry,
345   *s_vbargraph, *s_hbargraph;
346 
zero_samples(int k,int n,t_sample ** out)347 static inline void zero_samples(int k, int n, t_sample **out)
348 {
349   for (int i = 0; i < k; i++)
350 #ifdef __STDC_IEC_559__
351     /* IEC 559 a.k.a. IEEE 754 floats can be initialized faster like this */
352     memset(out[i], 0, n*sizeof(t_sample));
353 #else
354     for (int j = 0; j < n; j++)
355       out[i][j] = 0.0f;
356 #endif
357 }
358 
copy_samples(int k,int n,t_sample ** out,t_sample ** in)359 static inline void copy_samples(int k, int n, t_sample **out, t_sample **in)
360 {
361   for (int i = 0; i < k; i++)
362     memcpy(out[i], in[i], n*sizeof(t_sample));
363 }
364 
faust_perform(t_int * w)365 static t_int *faust_perform(t_int *w)
366 {
367   t_faust *x = (t_faust *)(w[1]);
368   int n = (int)(w[2]);
369   if (!x->dsp || !x->buf) return (w+3);
370   AVOIDDENORMALS;
371   if (x->xfade > 0) {
372     float d = 1.0f/x->n_xfade, f = (x->xfade--)*d;
373     d = d/n;
374     x->dsp->compute(n, x->inputs, x->buf);
375     if (x->active)
376       if (x->n_in == x->n_out)
377 	/* xfade inputs -> buf */
378 	for (int j = 0; j < n; j++, f -= d)
379 	  for (int i = 0; i < x->n_out; i++)
380 	    x->outputs[i][j] = f*x->inputs[i][j]+(1.0f-f)*x->buf[i][j];
381       else
382 	/* xfade 0 -> buf */
383 	for (int j = 0; j < n; j++, f -= d)
384 	  for (int i = 0; i < x->n_out; i++)
385 	    x->outputs[i][j] = (1.0f-f)*x->buf[i][j];
386     else
387       if (x->n_in == x->n_out)
388 	/* xfade buf -> inputs */
389 	for (int j = 0; j < n; j++, f -= d)
390 	  for (int i = 0; i < x->n_out; i++)
391 	    x->outputs[i][j] = f*x->buf[i][j]+(1.0f-f)*x->inputs[i][j];
392       else
393 	/* xfade buf -> 0 */
394 	for (int j = 0; j < n; j++, f -= d)
395 	  for (int i = 0; i < x->n_out; i++)
396 	    x->outputs[i][j] = f*x->buf[i][j];
397   } else if (x->active) {
398     x->dsp->compute(n, x->inputs, x->buf);
399     copy_samples(x->n_out, n, x->outputs, x->buf);
400   } else if (x->n_in == x->n_out) {
401     copy_samples(x->n_out, n, x->buf, x->inputs);
402     copy_samples(x->n_out, n, x->outputs, x->buf);
403   } else
404     zero_samples(x->n_out, n, x->outputs);
405   return (w+3);
406 }
407 
faust_dsp(t_faust * x,t_signal ** sp)408 static void faust_dsp(t_faust *x, t_signal **sp)
409 {
410   int n = sp[0]->s_n, sr = (int)sp[0]->s_sr;
411   if (x->rate <= 0) {
412     /* default sample rate is whatever Pd tells us */
413     PdUI *ui = x->ui;
414     float *z = NULL;
415     if (ui->nelems > 0 &&
416 	(z = (float*)malloc(ui->nelems*sizeof(float)))) {
417       /* save the current control values */
418       for (int i = 0; i < ui->nelems; i++)
419 	if (ui->elems[i].zone)
420 	  z[i] = *ui->elems[i].zone;
421     }
422     /* set the proper sample rate; this requires reinitializing the dsp */
423     x->rate = sr;
424     x->dsp->init(sr);
425     if (z) {
426       /* restore previous control values */
427       for (int i = 0; i < ui->nelems; i++)
428 	if (ui->elems[i].zone)
429 	  *ui->elems[i].zone = z[i];
430       free(z);
431     }
432   }
433   if (n > 0)
434     x->n_xfade = (int)(x->rate*XFADE_TIME/n);
435   dsp_add(faust_perform, 2, x, n);
436   for (int i = 0; i < x->n_in; i++)
437     x->inputs[i] = sp[i+1]->s_vec;
438   for (int i = 0; i < x->n_out; i++)
439     x->outputs[i] = sp[x->n_in+i+1]->s_vec;
440   if (x->buf != NULL)
441     for (int i = 0; i < x->n_out; i++) {
442       x->buf[i] = (t_sample*)malloc(n*sizeof(t_sample));
443       if (x->buf[i] == NULL) {
444 	for (int j = 0; j < i; j++)
445 	  free(x->buf[j]);
446 	free(x->buf);
447 	x->buf = NULL;
448 	break;
449       }
450     }
451 }
452 
pathcmp(const char * s,const char * t)453 static int pathcmp(const char *s, const char *t)
454 {
455   int n = strlen(s), m = strlen(t);
456   if (n == 0 || m == 0)
457     return 0;
458   else if (t[0] == '/')
459     return strcmp(s, t);
460   else if (n <= m || s[n-m-1] != '/')
461     return strcmp(s+1, t);
462   else
463     return strcmp(s+n-m, t);
464 }
465 
faust_any(t_faust * x,t_symbol * s,int argc,t_atom * argv)466 static void faust_any(t_faust *x, t_symbol *s, int argc, t_atom *argv)
467 {
468   if (!x->dsp) return;
469   PdUI *ui = x->ui;
470   if (s == &s_bang) {
471     for (int i = 0; i < ui->nelems; i++)
472       if (ui->elems[i].label && ui->elems[i].zone) {
473 	t_atom args[6];
474 	t_symbol *_s;
475 	switch (ui->elems[i].type) {
476 	case UI_BUTTON:
477 	  _s = s_button;
478 	  break;
479 	case UI_CHECK_BUTTON:
480 	  _s = s_checkbox;
481 	  break;
482 	case UI_V_SLIDER:
483 	  _s = s_vslider;
484 	  break;
485 	case UI_H_SLIDER:
486 	  _s = s_hslider;
487 	  break;
488 	case UI_NUM_ENTRY:
489 	  _s = s_nentry;
490 	  break;
491 	case UI_V_BARGRAPH:
492 	  _s = s_vbargraph;
493 	  break;
494 	case UI_H_BARGRAPH:
495 	  _s = s_hbargraph;
496 	  break;
497 	default:
498 	  continue;
499 	}
500 	SETSYMBOL(&args[0], gensym(ui->elems[i].label));
501 	SETFLOAT(&args[1], *ui->elems[i].zone);
502 	SETFLOAT(&args[2], ui->elems[i].init);
503 	SETFLOAT(&args[3], ui->elems[i].min);
504 	SETFLOAT(&args[4], ui->elems[i].max);
505 	SETFLOAT(&args[5], ui->elems[i].step);
506 	outlet_anything(x->out, _s, 6, args);
507       }
508   } else {
509     const char *label = s->s_name;
510     int count = 0;
511     for (int i = 0; i < ui->nelems; i++)
512       if (ui->elems[i].label &&
513 	  pathcmp(ui->elems[i].label, label) == 0) {
514 	if (argc == 0) {
515 	  if (ui->elems[i].zone) {
516 	    t_atom arg;
517 	    SETFLOAT(&arg, *ui->elems[i].zone);
518 	    outlet_anything(x->out, gensym(ui->elems[i].label), 1, &arg);
519 	  }
520 	  ++count;
521 	} else if (argc == 1 &&
522 		   (argv[0].a_type == A_FLOAT ||
523 		    argv[0].a_type == A_DEFFLOAT) &&
524 		   ui->elems[i].zone) {
525 	  float f = atom_getfloat(argv);
526 	  *ui->elems[i].zone = f;
527 	  ++count;
528 	} else
529 	  pd_error(x, "[faust] %s: bad control argument: %s",
530 		   x->label->c_str(), label);
531       }
532     if (count == 0 && strcmp(label, "active") == 0) {
533       if (argc == 0) {
534 	t_atom arg;
535 	SETFLOAT(&arg, (float)x->active);
536 	outlet_anything(x->out, gensym((char*)"active"), 1, &arg);
537       } else if (argc == 1 &&
538 		 (argv[0].a_type == A_FLOAT ||
539 		  argv[0].a_type == A_DEFFLOAT)) {
540 	float f = atom_getfloat(argv);
541 	x->active = (int)f;
542 	x->xfade = x->n_xfade;
543       }
544     }
545   }
546 }
547 
faust_free(t_faust * x)548 static void faust_free(t_faust *x)
549 {
550   if (x->label) delete x->label;
551   if (x->dsp) delete x->dsp;
552   if (x->ui) delete x->ui;
553   if (x->inputs) free(x->inputs);
554   if (x->outputs) free(x->outputs);
555   if (x->buf) {
556     for (int i = 0; i < x->n_out; i++)
557       if (x->buf[i]) free(x->buf[i]);
558     free(x->buf);
559   }
560 }
561 
faust_new(t_symbol * s,int argc,t_atom * argv)562 static void *faust_new(t_symbol *s, int argc, t_atom *argv)
563 {
564   t_faust *x = (t_faust*)pd_new(faust_class);
565   int sr = -1;
566   t_symbol *id = NULL;
567   x->active = 1;
568   for (int i = 0; i < argc; i++)
569     if (argv[i].a_type == A_FLOAT || argv[i].a_type == A_DEFFLOAT)
570       sr = (int)argv[i].a_w.w_float;
571     else if (argv[i].a_type == A_SYMBOL || argv[i].a_type == A_DEFSYMBOL)
572       id = argv[i].a_w.w_symbol;
573   x->rate = sr;
574   if (sr <= 0) sr = 44100;
575   x->xfade = 0; x->n_xfade = (int)(sr*XFADE_TIME/64);
576   x->inputs = x->outputs = x->buf = NULL;
577     x->label = new std::string(sym(mydsp) "~");
578   x->dsp = new mydsp();
579   x->ui = new PdUI(sym(mydsp), id?id->s_name:NULL);
580   if (!x->dsp || !x->ui || !x->label) goto error;
581   if (id) {
582     *x->label += " ";
583     *x->label += id->s_name;
584   }
585   x->n_in = x->dsp->getNumInputs();
586   x->n_out = x->dsp->getNumOutputs();
587   if (x->n_in > 0)
588     x->inputs = (t_sample**)malloc(x->n_in*sizeof(t_sample*));
589   if (x->n_out > 0) {
590     x->outputs = (t_sample**)malloc(x->n_out*sizeof(t_sample*));
591     x->buf = (t_sample**)malloc(x->n_out*sizeof(t_sample*));
592   }
593   if ((x->n_in > 0 && x->inputs == NULL) ||
594       (x->n_out > 0 && (x->outputs == NULL || x->buf == NULL)))
595     goto error;
596   for (int i = 0; i < x->n_out; i++)
597     x->buf[i] = NULL;
598   x->dsp->init(sr);
599   x->dsp->buildUserInterface(x->ui);
600   for (int i = 0; i < x->n_in; i++)
601     inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal);
602   x->out = outlet_new(&x->x_obj, 0);
603   for (int i = 0; i < x->n_out; i++)
604     outlet_new(&x->x_obj, &s_signal);
605   return (void *)x;
606  error:
607   faust_free(x);
608   x->dsp = NULL; x->ui = NULL;
609   x->inputs = x->outputs = x->buf = NULL;
610   return (void *)x;
611 }
612 
faust_setup(mydsp)613 extern "C" void faust_setup(mydsp)
614 {
615   t_symbol *s = gensym(sym(mydsp) "~");
616   faust_class =
617     class_new(s, (t_newmethod)faust_new, (t_method)faust_free,
618 	      sizeof(t_faust), CLASS_DEFAULT,
619 	      A_GIMME, A_NULL);
620   class_addmethod(faust_class, (t_method)faust_dsp, gensym((char*)"dsp"), A_NULL);
621   class_addanything(faust_class, faust_any);
622   class_addmethod(faust_class, nullfn, &s_signal, A_NULL);
623   s_button = gensym((char*)"button");
624   s_checkbox = gensym((char*)"checkbox");
625   s_vslider = gensym((char*)"vslider");
626   s_hslider = gensym((char*)"hslider");
627   s_nentry = gensym((char*)"nentry");
628   s_vbargraph = gensym((char*)"vbargraph");
629   s_hbargraph = gensym((char*)"hbargraph");
630   /* give some indication that we're loaded and ready to go */
631   mydsp dsp = mydsp();
632   post("[faust] %s: %d inputs, %d outputs", sym(mydsp) "~",
633        dsp.getNumInputs(), dsp.getNumOutputs());
634 }
635