Merge branch 'master' of https://scm.cri.ensmp.fr/git/Faustine
[Faustine.git] / interpretor / preprocessor / faust-0.9.47mr3 / architecture / snd-rt-gtk.cpp
1 /************************************************************************
2 ************************************************************************
3 FAUST Architecture File
4 Copyright (C) 2008-2011 Kjetil Matheussen <k.s.matheussen@notam02.no>
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 /* link with */
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <string.h>
27 #include <limits.h>
28 #include <math.h>
29 #include <errno.h>
30 #include <time.h>
31
32 #ifdef MAKE_GUI
33
34 #include <sys/ioctl.h>
35 #include <unistd.h>
36 #include <fcntl.h>
37 #include <pwd.h>
38 #include <sys/types.h>
39 #include <assert.h>
40 #include <gtk/gtk.h>
41 #include <pthread.h>
42 #include <sys/wait.h>
43 #include <vector>
44
45 #include <iostream>
46 #include <fstream>
47
48 #include <libgen.h>
49
50 #endif
51
52 #include <list>
53 #include <map>
54
55 #include <rt-various.h> // realtime memory allocation in Snd.
56
57
58
59 using namespace std;
60
61 struct Meta : map<const char*, const char*>
62 {
63 void declare (const char* key, const char* value) { (*this)[key]=value; }
64 };
65
66
67
68 //inline void *aligned_calloc(size_t nmemb, size_t size) { return (void*)((unsigned)(calloc((nmemb*size)+15,sizeof(char)))+15 & 0xfffffff0); }
69 inline void *aligned_calloc(size_t nmemb, size_t size) { return (void*)((size_t)(calloc((nmemb*size)+15,sizeof(char)))+15 & ~15); }
70
71 // g++ -O3 -lm -ljack `gtk-config --cflags --libs` ex2.cpp
72
73
74
75 #define max(x,y) (((x)>(y)) ? (x) : (y))
76 #define min(x,y) (((x)<(y)) ? (x) : (y))
77
78
79 // abs is now predefined
80 //template<typename T> T abs (T a) { return (a<T(0)) ? -a : a; }
81
82
83 inline int lsr (int x, int n) { return int(((unsigned int)x) >> n); }
84
85 inline int int2pow2 (int x) { int r=0; while ((1<<r)<x) r++; return r; }
86
87
88
89 /******************************************************************************
90 *******************************************************************************
91
92 VECTOR INTRINSICS
93
94 *******************************************************************************
95 *******************************************************************************/
96
97 //inline void *aligned_calloc(size_t nmemb, size_t size) { return (void*)((unsigned)(calloc((nmemb*size)+15,sizeof(char)))+15 & 0xfffffff0); }
98
99
100 <<includeIntrinsic>>
101
102
103
104
105
106
107 /******************************************************************************
108 *******************************************************************************
109
110 GRAPHIC USER INTERFACE (v2)
111 abstract interfaces
112
113 *******************************************************************************
114 *******************************************************************************/
115
116 #include <map>
117 #include <list>
118
119 using namespace std;
120
121 struct uiItem;
122 typedef void (*uiCallback)(float val, void* data);
123
124
125 #ifdef MAKE_GUI // It's enough to compile GUI code once.
126
127 /**
128 * Graphic User Interface : abstract definition
129 */
130
131 class UI
132 {
133 typedef list<uiItem*> clist;
134 typedef map<float*, clist*> zmap;
135
136 private:
137 static list<UI*> fGuiList;
138 zmap fZoneMap;
139 bool fStopped;
140
141 public:
142
143 UI() : fStopped(false) {
144 fGuiList.push_back(this);
145 }
146
147 virtual ~UI() {
148 // suppression de this dans fGuiList
149 }
150
151 // -- registerZone(z,c) : zone management
152
153 bool containsUI;
154 void registerZone(float* z, uiItem* c)
155 {
156 containsUI=true;
157 if (fZoneMap.find(z) == fZoneMap.end()) fZoneMap[z] = new clist();
158 fZoneMap[z]->push_back(c);
159 }
160
161 // -- saveState(filename) : save the value of every zone to a file
162
163 void saveState(const char* filename)
164 {
165 ofstream f(filename);
166
167 for (zmap::iterator i=fZoneMap.begin(); i!=fZoneMap.end(); i++) {
168 f << *(i->first) << ' ';
169 }
170
171 f << endl;
172 f.close();
173 }
174
175 // -- recallState(filename) : load the value of every zone from a file
176
177 void recallState(const char* filename)
178 {
179 ifstream f(filename);
180 if (f.good()) {
181 for (zmap::iterator i=fZoneMap.begin(); i!=fZoneMap.end(); i++) {
182 f >> *(i->first);
183 }
184 }
185 f.close();
186 }
187
188 void updateAllZones();
189
190 void updateZone(float* z);
191
192 static void updateAllGuis()
193 {
194 list<UI*>::iterator g;
195 for (g = fGuiList.begin(); g != fGuiList.end(); g++) {
196 (*g)->updateAllZones();
197 }
198 }
199
200 // -- active widgets
201
202 virtual void addButton(const char* label, float* zone) = 0;
203 virtual void addToggleButton(const char* label, float* zone) = 0;
204 virtual void addCheckButton(const char* label, float* zone) = 0;
205 virtual void addVerticalSlider(const char* label, float* zone, float init, float min, float max, float step) = 0;
206 virtual void addHorizontalSlider(const char* label, float* zone, float init, float min, float max, float step) = 0;
207 virtual void addNumEntry(const char* label, float* zone, float init, float min, float max, float step) = 0;
208
209 // -- passive widgets
210
211 virtual void addNumDisplay(const char* label, float* zone, int precision) = 0;
212 virtual void addTextDisplay(const char* label, float* zone, const char* names[], float min, float max) = 0;
213 virtual void addHorizontalBargraph(const char* label, float* zone, float min, float max) = 0;
214 virtual void addVerticalBargraph(const char* label, float* zone, float min, float max) = 0;
215
216 void addCallback(float* zone, uiCallback foo, void* data);
217
218 // -- widget's layouts
219
220 virtual void openFrameBox(const char* label) = 0;
221 virtual void openTabBox(const char* label) = 0;
222 virtual void openHorizontalBox(const char* label) = 0;
223 virtual void openVerticalBox(const char* label) = 0;
224 virtual void closeBox() = 0;
225
226 virtual void show() = 0;
227 virtual void run() = 0;
228
229 virtual void declare(float* zone, const char* key, const char* value) {}
230
231 void stop() { fStopped = true; }
232 bool stopped() { return fStopped; }
233 };
234
235
236 /**
237 * User Interface Item: abstract definition
238 */
239
240 class uiItem
241 {
242 protected :
243
244 UI* fGUI;
245 float* fZone;
246 float fCache;
247
248 uiItem (UI* ui, float* zone) : fGUI(ui), fZone(zone), fCache(-123456.654321)
249 {
250 ui->registerZone(zone, this);
251 }
252
253
254 public :
255 virtual ~uiItem() {}
256
257 void modifyZone(float v)
258 {
259 fCache = v;
260 if (*fZone != v) {
261 *fZone = v;
262 fGUI->updateZone(fZone);
263 }
264 }
265
266 float cache() { return fCache; }
267 virtual void reflectZone() = 0;
268 };
269
270
271 /**
272 * Callback Item
273 */
274
275 struct uiCallbackItem : public uiItem
276 {
277 uiCallback fCallback;
278 void* fData;
279
280 uiCallbackItem(UI* ui, float* zone, uiCallback foo, void* data)
281 : uiItem(ui, zone), fCallback(foo), fData(data) {}
282
283 virtual void reflectZone() {
284 float v = *fZone;
285 fCache = v;
286 fCallback(v, fData);
287 }
288 };
289
290 // en cours d'installation de call back. a finir!!!!!
291
292 /**
293 * Update all user items reflecting zone z
294 */
295
296 inline void UI::updateZone(float* z)
297 {
298 float v = *z;
299 clist* l = fZoneMap[z];
300 for (clist::iterator c = l->begin(); c != l->end(); c++) {
301 if ((*c)->cache() != v) (*c)->reflectZone();
302 }
303 }
304
305
306 /**
307 * Update all user items not up to date
308 */
309
310 inline void UI::updateAllZones()
311 {
312 for (zmap::iterator m = fZoneMap.begin(); m != fZoneMap.end(); m++) {
313 float* z = m->first;
314 clist* l = m->second;
315 float v = *z;
316 for (clist::iterator c = l->begin(); c != l->end(); c++) {
317 if ((*c)->cache() != v) (*c)->reflectZone();
318 }
319 }
320 }
321
322 inline void UI::addCallback(float* zone, uiCallback foo, void* data)
323 {
324 new uiCallbackItem(this, zone, foo, data);
325 };
326
327
328 /******************************************************************************
329 *******************************************************************************
330
331 GRAPHIC USER INTERFACE
332 gtk interface
333
334 *******************************************************************************
335 *******************************************************************************/
336
337 #include <gtk/gtk.h>
338
339 #define stackSize 256
340
341 // Insertion modes
342
343 #define kSingleMode 0
344 #define kBoxMode 1
345 #define kTabMode 2
346
347
348 class GTKUI : public UI
349 {
350 private :
351 static bool fInitialized;
352 static list<UI*> fGuiList;
353
354 protected :
355 GtkWidget* fWindow;
356 int fTop;
357 GtkWidget* fBox[stackSize];
358 int fMode[stackSize];
359 bool fStopped;
360
361 GtkWidget* addWidget(const char* label, GtkWidget* w);
362 virtual void pushBox(int mode, GtkWidget* w);
363
364
365 public :
366
367 static const gboolean expand = TRUE;
368 static const gboolean fill = TRUE;
369 static const gboolean homogene = FALSE;
370
371 GTKUI(char * name, int* pargc, char*** pargv);
372 GTKUI(){}
373
374 // -- layout groups
375
376 virtual void openFrameBox(const char* label);
377 virtual void openTabBox(const char* label = "");
378 virtual void openHorizontalBox(const char* label = "");
379 virtual void openVerticalBox(const char* label = "");
380
381 virtual void closeBox();
382
383 // -- active widgets
384
385 virtual void addButton(const char* label, float* zone);
386 virtual void addToggleButton(const char* label, float* zone);
387 virtual void addCheckButton(const char* label, float* zone);
388 virtual void addVerticalSlider(const char* label, float* zone, float init, float min, float max, float step);
389 virtual void addHorizontalSlider(const char* label, float* zone, float init, float min, float max, float step);
390 virtual void addNumEntry(const char* label, float* zone, float init, float min, float max, float step);
391
392 // -- passive display widgets
393
394 virtual void addNumDisplay(const char* label, float* zone, int precision);
395 virtual void addTextDisplay(const char* label, float* zone, const char* names[], float min, float max);
396 virtual void addHorizontalBargraph(const char* label, float* zone, float min, float max);
397 virtual void addVerticalBargraph(const char* label, float* zone, float min, float max);
398
399 virtual void show();
400 virtual void run();
401
402 virtual void declare(float* zone, const char* key, const char* value) {}
403
404 };
405
406
407
408 /******************************************************************************
409 *******************************************************************************
410
411 GRAPHIC USER INTERFACE (v2)
412 gtk implementation
413
414 *******************************************************************************
415 *******************************************************************************/
416
417 // global static fields
418
419 bool GTKUI::fInitialized = false;
420 list<UI*> UI::fGuiList;
421
422
423
424 static gint delete_event( GtkWidget *widget, GdkEvent *event, gpointer data )
425 {
426 return FALSE;
427 }
428
429 static void destroy_event( GtkWidget *widget, gpointer data )
430 {
431 gtk_main_quit ();
432 }
433
434
435 GTKUI::GTKUI(char * name, int* pargc, char*** pargv)
436 {
437 if (!fInitialized){
438 gtk_init(pargc, pargv);
439 fInitialized = true;
440 }
441
442 fWindow = gtk_window_new (GTK_WINDOW_TOPLEVEL);
443 //gtk_container_set_border_width (GTK_CONTAINER (fWindow), 10);
444 gtk_window_set_title (GTK_WINDOW (fWindow), name);
445 gtk_signal_connect (GTK_OBJECT (fWindow), "delete_event", GTK_SIGNAL_FUNC (delete_event), NULL);
446 gtk_signal_connect (GTK_OBJECT (fWindow), "destroy", GTK_SIGNAL_FUNC (destroy_event), NULL);
447
448 fTop = 0;
449 fBox[fTop] = gtk_vbox_new (homogene, 4);
450 fMode[fTop] = kBoxMode;
451 gtk_container_add (GTK_CONTAINER (fWindow), fBox[fTop]);
452 fStopped = false;
453 }
454
455 // empilement des boites
456
457 void GTKUI::pushBox(int mode, GtkWidget* w)
458 {
459 ++fTop;
460 assert(fTop < stackSize);
461 fMode[fTop] = mode;
462 fBox[fTop] = w;
463 }
464
465 void GTKUI::closeBox()
466 {
467 --fTop;
468 assert(fTop >= 0);
469 }
470
471
472 // les differentes boites
473
474 void GTKUI::openFrameBox(const char* label)
475 {
476 GtkWidget * box = gtk_frame_new (label);
477 //gtk_container_set_border_width (GTK_CONTAINER (box), 10);
478
479 pushBox(kSingleMode, addWidget(label, box));
480 }
481
482 void GTKUI::openTabBox(const char* label)
483 {
484 pushBox(kTabMode, addWidget(label, gtk_notebook_new ()));
485 }
486
487 void GTKUI::openHorizontalBox(const char* label)
488 {
489 GtkWidget * box = gtk_hbox_new (homogene, 4);
490 gtk_container_set_border_width (GTK_CONTAINER (box), 10);
491
492 if (fMode[fTop] != kTabMode && label[0] != 0) {
493 GtkWidget * frame = addWidget(label, gtk_frame_new (label));
494 gtk_container_add (GTK_CONTAINER(frame), box);
495 gtk_widget_show(box);
496 pushBox(kBoxMode, box);
497 } else {
498 pushBox(kBoxMode, addWidget(label, box));
499 }
500 }
501
502 void GTKUI::openVerticalBox(const char* label)
503 {
504 GtkWidget * box = gtk_vbox_new (homogene, 4);
505 gtk_container_set_border_width (GTK_CONTAINER (box), 10);
506
507 if (fMode[fTop] != kTabMode && label[0] != 0) {
508 GtkWidget * frame = addWidget(label, gtk_frame_new (label));
509 gtk_container_add (GTK_CONTAINER(frame), box);
510 gtk_widget_show(box);
511 pushBox(kBoxMode, box);
512 } else {
513 pushBox(kBoxMode, addWidget(label, box));
514 }
515 }
516
517 GtkWidget* GTKUI::addWidget(const char* label, GtkWidget* w)
518 {
519 switch (fMode[fTop]) {
520 case kSingleMode : gtk_container_add (GTK_CONTAINER(fBox[fTop]), w); break;
521 case kBoxMode : gtk_box_pack_start (GTK_BOX(fBox[fTop]), w, expand, fill, 0); break;
522 case kTabMode : gtk_notebook_append_page (GTK_NOTEBOOK(fBox[fTop]), w, gtk_label_new(label)); break;
523 }
524 gtk_widget_show (w);
525 return w;
526 }
527
528 // --------------------------- Press button ---------------------------
529
530 struct uiButton : public uiItem
531 {
532 GtkButton* fButton;
533
534 uiButton (UI* ui, float* zone, GtkButton* b) : uiItem(ui, zone), fButton(b) {}
535
536 static void pressed( GtkWidget *widget, gpointer data )
537 {
538 uiItem* c = (uiItem*) data;
539 c->modifyZone(1.0);
540 }
541
542 static void released( GtkWidget *widget, gpointer data )
543 {
544 uiItem* c = (uiItem*) data;
545 c->modifyZone(0.0);
546 }
547
548 virtual void reflectZone()
549 {
550 float v = *fZone;
551 fCache = v;
552 if (v > 0.0) gtk_button_pressed(fButton); else gtk_button_released(fButton);
553 }
554 };
555
556 void GTKUI::addButton(const char* label, float* zone)
557 {
558 *zone = 0.0;
559 GtkWidget* button = gtk_button_new_with_label (label);
560 addWidget(label, button);
561
562 uiButton* c = new uiButton(this, zone, GTK_BUTTON(button));
563
564 gtk_signal_connect (GTK_OBJECT (button), "pressed", GTK_SIGNAL_FUNC (uiButton::pressed), (gpointer) c);
565 gtk_signal_connect (GTK_OBJECT (button), "released", GTK_SIGNAL_FUNC (uiButton::released), (gpointer) c);
566
567 }
568
569 // --------------------------- Toggle Buttons ---------------------------
570
571 struct uiToggleButton : public uiItem
572 {
573 GtkToggleButton* fButton;
574
575 uiToggleButton(UI* ui, float* zone, GtkToggleButton* b) : uiItem(ui, zone), fButton(b) {}
576
577 static void toggled (GtkWidget *widget, gpointer data)
578 {
579 float v = (GTK_TOGGLE_BUTTON (widget)->active) ? 1.0 : 0.0;
580 ((uiItem*)data)->modifyZone(v);
581 }
582
583 virtual void reflectZone()
584 {
585 float v = *fZone;
586 fCache = v;
587 gtk_toggle_button_set_active(fButton, v > 0.0);
588 }
589 };
590
591 void GTKUI::addToggleButton(const char* label, float* zone)
592 {
593 *zone = 0.0;
594 GtkWidget* button = gtk_toggle_button_new_with_label (label);
595 addWidget(label, button);
596
597 uiToggleButton* c = new uiToggleButton(this, zone, GTK_TOGGLE_BUTTON(button));
598 gtk_signal_connect (GTK_OBJECT (button), "toggled", GTK_SIGNAL_FUNC (uiToggleButton::toggled), (gpointer) c);
599 }
600
601
602 // --------------------------- Check Button ---------------------------
603
604 struct uiCheckButton : public uiItem
605 {
606 GtkToggleButton* fButton;
607
608 uiCheckButton(UI* ui, float* zone, GtkToggleButton* b) : uiItem(ui, zone), fButton(b) {}
609
610 static void toggled (GtkWidget *widget, gpointer data)
611 {
612 float v = (GTK_TOGGLE_BUTTON (widget)->active) ? 1.0 : 0.0;
613 ((uiItem*)data)->modifyZone(v);
614 }
615
616 virtual void reflectZone()
617 {
618 float v = *fZone;
619 fCache = v;
620 gtk_toggle_button_set_active(fButton, v > 0.0);
621 }
622 };
623
624 void GTKUI::addCheckButton(const char* label, float* zone)
625 {
626 *zone = 0.0;
627 GtkWidget* button = gtk_check_button_new_with_label (label);
628 addWidget(label, button);
629
630 uiCheckButton* c = new uiCheckButton(this, zone, GTK_TOGGLE_BUTTON(button));
631 gtk_signal_connect (GTK_OBJECT (button), "toggled", GTK_SIGNAL_FUNC(uiCheckButton::toggled), (gpointer) c);
632 }
633
634
635 // --------------------------- Adjustmenty based widgets ---------------------------
636
637 struct uiAdjustment : public uiItem
638 {
639 GtkAdjustment* fAdj;
640
641 uiAdjustment(UI* ui, float* zone, GtkAdjustment* adj) : uiItem(ui, zone), fAdj(adj) {}
642
643 static void changed (GtkWidget *widget, gpointer data)
644 {
645 float v = GTK_ADJUSTMENT (widget)->value;
646 ((uiItem*)data)->modifyZone(v);
647 }
648
649 virtual void reflectZone()
650 {
651 float v = *fZone;
652 fCache = v;
653 gtk_adjustment_set_value(fAdj, v);
654 }
655 };
656
657 static int precision(double n)
658 {
659 if (n < 0.009999) return 3;
660 else if (n < 0.099999) return 2;
661 else if (n < 0.999999) return 1;
662 else return 0;
663 }
664
665 // -------------------------- Vertical Slider -----------------------------------
666
667 void GTKUI::addVerticalSlider(const char* label, float* zone, float init, float min, float max, float step)
668 {
669 *zone = init;
670 GtkObject* adj = gtk_adjustment_new(init, min, max, step, 10*step, 0);
671
672 uiAdjustment* c = new uiAdjustment(this, zone, GTK_ADJUSTMENT(adj));
673
674 gtk_signal_connect (GTK_OBJECT (adj), "value-changed", GTK_SIGNAL_FUNC (uiAdjustment::changed), (gpointer) c);
675
676 GtkWidget* slider = gtk_vscale_new (GTK_ADJUSTMENT(adj));
677 gtk_range_set_inverted (GTK_RANGE(slider), TRUE);
678 gtk_scale_set_digits(GTK_SCALE(slider), precision(step));
679 gtk_widget_set_usize(slider, -1, 160);
680
681 openFrameBox(label);
682 addWidget(label, slider);
683 closeBox();
684 }
685
686 // -------------------------- Horizontal Slider -----------------------------------
687
688 void GTKUI::addHorizontalSlider(const char* label, float* zone, float init, float min, float max, float step)
689 {
690 *zone = init;
691 GtkObject* adj = gtk_adjustment_new(init, min, max, step, 10*step, 0);
692
693 uiAdjustment* c = new uiAdjustment(this, zone, GTK_ADJUSTMENT(adj));
694
695 gtk_signal_connect (GTK_OBJECT (adj), "value-changed", GTK_SIGNAL_FUNC (uiAdjustment::changed), (gpointer) c);
696
697 GtkWidget* slider = gtk_hscale_new (GTK_ADJUSTMENT(adj));
698 gtk_scale_set_digits(GTK_SCALE(slider), precision(step));
699 gtk_widget_set_usize(slider, 160, -1);
700
701 openFrameBox(label);
702 addWidget(label, slider);
703 closeBox();
704 }
705
706
707 // ------------------------------ Num Entry -----------------------------------
708
709 void GTKUI::addNumEntry(const char* label, float* zone, float init, float min, float max, float step)
710 {
711 *zone = init;
712 GtkObject* adj = gtk_adjustment_new(init, min, max, step, 10*step, step);
713
714 uiAdjustment* c = new uiAdjustment(this, zone, GTK_ADJUSTMENT(adj));
715
716 gtk_signal_connect (GTK_OBJECT (adj), "value-changed", GTK_SIGNAL_FUNC (uiAdjustment::changed), (gpointer) c);
717
718 GtkWidget* spinner = gtk_spin_button_new (GTK_ADJUSTMENT(adj), 0.005, precision(step));
719
720 //gtk_widget_set_usize(slider, 160, -1);
721 openFrameBox(label);
722 addWidget(label, spinner);
723 closeBox();
724 }
725
726
727 // ========================== passive widgets ===============================
728
729
730 // ------------------------------ Progress Bar -----------------------------------
731
732 struct uiBargraph : public uiItem
733 {
734 GtkProgressBar* fProgressBar;
735 float fMin;
736 float fMax;
737
738 uiBargraph(UI* ui, float* zone, GtkProgressBar* pbar, float lo, float hi)
739 : uiItem(ui, zone), fProgressBar(pbar), fMin(lo), fMax(hi) {}
740
741 float scale(float v) { return (v-fMin)/(fMax-fMin); }
742
743 virtual void reflectZone()
744 {
745 float v = *fZone;
746 fCache = v;
747 gtk_progress_bar_set_fraction(fProgressBar, scale(v));
748 }
749 };
750
751
752
753 void GTKUI::addVerticalBargraph(const char* label, float* zone, float lo, float hi)
754 {
755 GtkWidget* pb = gtk_progress_bar_new();
756 gtk_progress_bar_set_orientation(GTK_PROGRESS_BAR(pb), GTK_PROGRESS_BOTTOM_TO_TOP);
757 gtk_widget_set_size_request(pb, 8, -1);
758 new uiBargraph(this, zone, GTK_PROGRESS_BAR(pb), lo, hi);
759 openFrameBox(label);
760 addWidget(label, pb);
761 closeBox();
762 }
763
764
765 void GTKUI::addHorizontalBargraph(const char* label, float* zone, float lo, float hi)
766 {
767 GtkWidget* pb = gtk_progress_bar_new();
768 gtk_progress_bar_set_orientation(GTK_PROGRESS_BAR(pb), GTK_PROGRESS_LEFT_TO_RIGHT);
769 gtk_widget_set_size_request(pb, -1, 8);
770 new uiBargraph(this, zone, GTK_PROGRESS_BAR(pb), lo, hi);
771 openFrameBox(label);
772 addWidget(label, pb);
773 closeBox();
774 }
775
776
777 // ------------------------------ Num Display -----------------------------------
778
779 struct uiNumDisplay : public uiItem
780 {
781 GtkLabel* fLabel;
782 int fPrecision;
783
784 uiNumDisplay(UI* ui, float* zone, GtkLabel* label, int precision)
785 : uiItem(ui, zone), fLabel(label), fPrecision(precision) {}
786
787 virtual void reflectZone()
788 {
789 float v = *fZone;
790 fCache = v;
791 char s[64];
792 if (fPrecision <= 0) {
793 snprintf(s, 63, "%d", int(v));
794 } else if (fPrecision>3) {
795 snprintf(s, 63, "%f", v);
796 } else {
797 const char* format[] = {"%.1f", "%.2f", "%.3f"};
798 snprintf(s, 63, format[fPrecision-1], v);
799 }
800 gtk_label_set_text(fLabel, s);
801 }
802 };
803
804
805 void GTKUI::addNumDisplay(const char* label, float* zone, int precision )
806 {
807 GtkWidget* lw = gtk_label_new("");
808 new uiNumDisplay(this, zone, GTK_LABEL(lw), precision);
809 openFrameBox(label);
810 addWidget(label, lw);
811 closeBox();
812 }
813
814
815 // ------------------------------ Text Display -----------------------------------
816
817 struct uiTextDisplay : public uiItem
818 {
819 GtkLabel* fLabel;
820 const char** fNames;
821 float fMin;
822 float fMax;
823 int fNum;
824
825
826 uiTextDisplay (UI* ui, float* zone, GtkLabel* label, const char* names[], float lo, float hi)
827 : uiItem(ui, zone), fLabel(label), fNames(names), fMin(lo), fMax(hi)
828 {
829 fNum = 0;
830 while (fNames[fNum] != 0) fNum++;
831 }
832
833 virtual void reflectZone()
834 {
835 float v = *fZone;
836 fCache = v;
837
838 int idx = int(fNum*(v-fMin)/(fMax-fMin));
839
840 if (idx < 0) idx = 0;
841 else if (idx >= fNum) idx = fNum-1;
842
843 gtk_label_set_text(fLabel, fNames[idx]);
844 }
845 };
846
847
848 void GTKUI::addTextDisplay(const char* label, float* zone, const char* names[], float lo, float hi )
849 {
850 GtkWidget* lw = gtk_label_new("");
851 new uiTextDisplay (this, zone, GTK_LABEL(lw), names, lo, hi);
852 openFrameBox(label);
853 addWidget(label, lw);
854 closeBox();
855 }
856
857
858
859 void GTKUI::show()
860 {
861 assert(fTop == 0);
862 gtk_widget_show (fBox[0]);
863 gtk_widget_show (fWindow);
864 }
865
866
867 /**
868 * Update all user items reflecting zone z
869 */
870
871 static gboolean callUpdateAllGuis(gpointer)
872 {
873 UI::updateAllGuis();
874 return TRUE;
875 }
876
877
878 void GTKUI::run()
879 {
880 assert(fTop == 0);
881 gtk_widget_show (fBox[0]);
882 gtk_widget_show (fWindow);
883 gtk_timeout_add(40, callUpdateAllGuis, 0);
884 gtk_main ();
885 stop();
886 }
887
888
889 #else // MAKE_GUI
890
891 class UI
892 {
893 typedef list<uiItem*> clist;
894 typedef map<float*, clist*> zmap;
895
896 private:
897 static list<UI*> fGuiList;
898 zmap fZoneMap;
899 bool fStopped;
900
901 public:
902
903 UI() : fStopped(false) {
904 fGuiList.push_back(this);
905 }
906
907 virtual ~UI() {
908 // suppression de this dans fGuiList
909 }
910
911 // -- zone management
912
913 void registerZone(float* z, uiItem* c)
914 {
915 if (fZoneMap.find(z) == fZoneMap.end()) fZoneMap[z] = new clist();
916 fZoneMap[z]->push_back(c);
917 }
918
919 void updateAllZones();
920
921 void updateZone(float* z);
922
923 static void updateAllGuis()
924 {
925 list<UI*>::iterator g;
926 for (g = fGuiList.begin(); g != fGuiList.end(); g++) {
927 (*g)->updateAllZones();
928 }
929 }
930
931 // -- active widgets
932
933 virtual void addButton(const char* label, float* zone) = 0;
934 virtual void addToggleButton(const char* label, float* zone) = 0;
935 virtual void addCheckButton(const char* label, float* zone) = 0;
936 virtual void addVerticalSlider(const char* label, float* zone, float init, float min, float max, float step) = 0;
937 virtual void addHorizontalSlider(const char* label, float* zone, float init, float min, float max, float step) = 0;
938 virtual void addNumEntry(const char* label, float* zone, float init, float min, float max, float step) = 0;
939
940 // -- passive widgets
941
942 virtual void addNumDisplay(const char* label, float* zone, int precision) = 0;
943 virtual void addTextDisplay(const char* label, float* zone, char* names[], float min, float max) = 0;
944 virtual void addHorizontalBargraph(const char* label, float* zone, float min, float max) = 0;
945 virtual void addVerticalBargraph(const char* label, float* zone, float min, float max) = 0;
946
947 void addCallback(float* zone, uiCallback foo, void* data);
948
949 // -- widget's layouts
950
951 virtual void openFrameBox(const char* label) = 0;
952 virtual void openTabBox(const char* label) = 0;
953 virtual void openHorizontalBox(const char* label) = 0;
954 virtual void openVerticalBox(const char* label) = 0;
955 virtual void closeBox() = 0;
956
957 virtual void show() = 0;
958 virtual void run() = 0;
959
960 void stop() { fStopped = true; }
961 bool stopped() { return fStopped; }
962 };
963
964
965 /**
966 * User Interface Item: abstract definition
967 */
968
969 class uiItem
970 {
971 protected :
972
973 UI* fGUI;
974 float* fZone;
975 float fCache;
976
977 uiItem (UI* ui, float* zone) : fGUI(ui), fZone(zone), fCache(-123456.654321)
978 {
979 ui->registerZone(zone, this);
980 }
981
982
983 public :
984
985 virtual ~uiItem() {}
986
987 void modifyZone(float v)
988 {
989 fCache = v;
990 if (*fZone != v) {
991 *fZone = v;
992 fGUI->updateZone(fZone);
993 }
994 }
995
996 float cache() { return fCache; }
997 virtual void reflectZone() = 0;
998 };
999
1000
1001 /**
1002 * Callback Item
1003 */
1004
1005 struct uiCallbackItem : public uiItem
1006 {
1007 uiCallback fCallback;
1008 void* fData;
1009
1010 uiCallbackItem(UI* ui, float* zone, uiCallback foo, void* data)
1011 : uiItem(ui, zone), fCallback(foo), fData(data) {}
1012
1013 virtual void reflectZone() {
1014 float v = *fZone;
1015 fCache = v;
1016 fCallback(v, fData);
1017 }
1018 };
1019
1020
1021 /**
1022 * Update all user items reflecting zone z
1023 */
1024
1025 inline void UI::updateZone(float* z)
1026 {
1027 float v = *z;
1028 clist* l = fZoneMap[z];
1029 for (clist::iterator c = l->begin(); c != l->end(); c++) {
1030 if ((*c)->cache() != v) (*c)->reflectZone();
1031 }
1032 }
1033
1034
1035 /**
1036 * Update all user items not up to date
1037 */
1038
1039 inline void UI::updateAllZones()
1040 {
1041 for (zmap::iterator m = fZoneMap.begin(); m != fZoneMap.end(); m++) {
1042 float* z = m->first;
1043 clist* l = m->second;
1044 float v = *z;
1045 for (clist::iterator c = l->begin(); c != l->end(); c++) {
1046 if ((*c)->cache() != v) (*c)->reflectZone();
1047 }
1048 }
1049 }
1050
1051 inline void UI::addCallback(float* zone, uiCallback foo, void* data)
1052 {
1053 new uiCallbackItem(this, zone, foo, data);
1054 };
1055
1056 #endif // MAKE_GUI
1057
1058
1059 /******************************************************************************
1060 *******************************************************************************
1061
1062 FAUST DSP
1063
1064 *******************************************************************************
1065 *******************************************************************************/
1066
1067
1068
1069
1070
1071 //----------------------------------------------------------------
1072 // définition du processeur de signal
1073 //----------------------------------------------------------------
1074
1075 class dsp {
1076 protected:
1077 int fSamplingFreq;
1078 public:
1079 dsp() {}
1080 virtual ~dsp() {}
1081
1082 virtual int getNumInputs() = 0;
1083 virtual int getNumOutputs() = 0;
1084 virtual void buildUserInterface(UI* interface) = 0;
1085 virtual void init(int samplingRate) = 0;
1086 virtual void compute(int len, float** inputs, float** outputs) = 0;
1087 virtual void conclude() {}
1088
1089 void* operator new(size_t size){
1090 return clm_malloc_atomic(size,"faust new");
1091 }
1092
1093 };
1094
1095
1096 //----------------------------------------------------------------------------
1097 // FAUST generated code
1098 //----------------------------------------------------------------------------
1099
1100 <<includeclass>>
1101
1102
1103 #ifdef MAKE_GUI
1104
1105 class SNDRTGTKUI : public GTKUI{
1106 public:
1107
1108 SNDRTGTKUI(char * name, GtkDialog *window);
1109 void localRun();
1110 /*
1111 bool containUI;
1112 void registerZone(float* z, uiItem* c){
1113 containUI=true;
1114 GTKUI:registerZone(z,c);
1115 }
1116 */
1117 };
1118
1119 SNDRTGTKUI::SNDRTGTKUI(char * name, GtkDialog *window)
1120 {
1121 containsUI=false;
1122
1123 fWindow = GTK_WIDGET(GTK_WINDOW(window));
1124 fTop = 0;
1125 fBox[fTop] = window->vbox;
1126 fMode[fTop] = kBoxMode;
1127 fStopped = false;
1128 }
1129
1130 void SNDRTGTKUI::localRun(){
1131 assert(fTop == 0);
1132
1133 if(!containsUI)
1134 return;
1135
1136 gtk_widget_show (fBox[0]);
1137 gtk_widget_show (fWindow);
1138 gtk_timeout_add(40, callUpdateAllGuis, 0);
1139
1140 }
1141
1142 extern "C" SNDRTGTKUI* newGTKUI(char *name, void* window){
1143 return new SNDRTGTKUI(name,(GtkDialog*)window);
1144 }
1145
1146 extern "C" void runGTKUI(SNDRTGTKUI* ui){
1147 ui->localRun();
1148 }
1149
1150 extern "C" int containsUI(SNDRTGTKUI* ui){
1151 return ui->containsUI==true?1:0;
1152 }
1153
1154 #endif
1155
1156
1157
1158 extern "C" dsp* newDsp() { return new mydsp(); }
1159 extern "C" void deleteDsp(dsp* self) { delete self; }
1160
1161 extern "C" int getNumInputs(dsp* self) { return self->getNumInputs(); }
1162 extern "C" int getNumOutputs(dsp* self) { return self->getNumOutputs(); }
1163 extern "C" void buildUserInterface(dsp* self,UI* interface) { self->buildUserInterface(interface); }
1164 extern "C" void init(dsp* self, int freq) { self->init(freq); }
1165 extern "C" void compute(dsp* self, int len, float** inputs, float** outputs) { self->compute(len, inputs, outputs); }
1166 extern "C" void conclude(dsp* self) { self->conclude(); }
1167