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