1 /************************************************************************
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 *************************************************************************/
9 /*******************BEGIN ARCHITECTURE SECTION (part 1/2)****************/
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.
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.
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/>.
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.
34 ************************************************************************
35 ************************************************************************/
45 #include <sys/ioctl.h>
49 #include <sys/types.h>
61 #include <jack/jack.h>
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); }
69 // g++ -O3 -lm -ljack `gtk-config --cflags --libs` ex2.cpp
73 #define max(x,y) (((x)>(y)) ? (x) : (y))
74 #define min(x,y) (((x)<(y)) ? (x) : (y))
77 // abs is now predefined
78 //template<typename T> T abs (T a) { return (a<T(0)) ? -a : a; }
81 inline int lsr (int x
, int n
) { return int(((unsigned int)x
) >> n
); }
83 inline int int2pow2 (int x
) { int r
=0; while ((1<<r
)<x
) r
++; return r
; }
87 /******************************************************************************
88 *******************************************************************************
92 *******************************************************************************
93 *******************************************************************************/
95 //inline void *alloc(size_t nmemb, size_t size) { return (void*)((unsigned)(calloc((nmemb*size)+15,sizeof(char)))+15 & 0xfffffff0); }
105 /******************************************************************************
106 *******************************************************************************
108 GRAPHIC USER INTERFACE (v2)
111 *******************************************************************************
112 *******************************************************************************/
119 struct Meta
: map
<const char*, const char*>
121 void declare (const char* key
, const char* value
) { (*this)[key
]=value
; }
125 typedef void (*uiCallback
)(float val
, void* data
);
128 * Graphic User Interface : abstract definition
133 typedef list
<uiItem
*> clist
;
134 typedef map
<float*, clist
*> zmap
;
137 static list
<UI
*> fGuiList
;
143 UI() : fStopped(false) {
144 fGuiList
.push_back(this);
148 // suppression de this dans fGuiList
151 // -- registerZone(z,c) : zone management
153 void registerZone(float* z
, uiItem
* c
)
155 if (fZoneMap
.find(z
) == fZoneMap
.end()) fZoneMap
[z
] = new clist();
156 fZoneMap
[z
]->push_back(c
);
159 // -- saveState(filename) : save the value of every zone to a file
161 void saveState(const char* filename
)
163 ofstream
f(filename
);
165 for (zmap::iterator i
=fZoneMap
.begin(); i
!=fZoneMap
.end(); i
++) {
166 f
<< *(i
->first
) << ' ';
173 // -- recallState(filename) : load the value of every zone from a file
175 void recallState(const char* filename
)
177 ifstream
f(filename
);
179 for (zmap::iterator i
=fZoneMap
.begin(); i
!=fZoneMap
.end(); i
++) {
186 void updateAllZones();
188 void updateZone(float* z
);
190 static void updateAllGuis()
192 list
<UI
*>::iterator g
;
193 for (g
= fGuiList
.begin(); g
!= fGuiList
.end(); g
++) {
194 (*g
)->updateAllZones();
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
) {};
207 // -- passive widgets
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
) {};
214 void addCallback(float* zone
, uiCallback foo
, void* data
);
216 // -- widget's layouts
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() {};
224 virtual void show() {};
225 virtual void run() {};
227 void stop() { fStopped
= true; }
228 bool stopped() { return fStopped
; }
230 virtual void declare(float* zone
, const char* key
, const char* value
) {}
235 * User Interface Item: abstract definition
246 uiItem (UI
* ui
, float* zone
) : fGUI(ui
), fZone(zone
), fCache(-123456.654321)
248 ui
->registerZone(zone
, this);
255 void modifyZone(float v
)
260 fGUI
->updateZone(fZone
);
264 float cache() { return fCache
; }
265 virtual void reflectZone() = 0;
273 struct uiCallbackItem
: public uiItem
275 uiCallback fCallback
;
278 uiCallbackItem(UI
* ui
, float* zone
, uiCallback foo
, void* data
)
279 : uiItem(ui
, zone
), fCallback(foo
), fData(data
) {}
281 virtual void reflectZone() {
288 // en cours d'installation de call back. a finir!!!!!
291 * Update all user items reflecting zone z
294 inline void UI::updateZone(float* z
)
297 clist
* l
= fZoneMap
[z
];
298 for (clist::iterator c
= l
->begin(); c
!= l
->end(); c
++) {
299 if ((*c
)->cache() != v
) (*c
)->reflectZone();
305 * Update all user items not up to date
308 inline void UI::updateAllZones()
310 for (zmap::iterator m
= fZoneMap
.begin(); m
!= fZoneMap
.end(); m
++) {
312 clist
* l
= m
->second
;
314 for (clist::iterator c
= l
->begin(); c
!= l
->end(); c
++) {
315 if ((*c
)->cache() != v
) (*c
)->reflectZone();
320 inline void UI::addCallback(float* zone
, uiCallback foo
, void* data
)
322 new uiCallbackItem(this, zone
, foo
, data
);
325 /******************************************************************************
326 *******************************************************************************
330 *******************************************************************************
335 DSP.buildUserInterface(&midi);
338 *******************************************************************************
339 *******************************************************************************/
342 #include <MidiShare.h>
344 class MidiShareUI
: public UI
350 ctrl(float* z
, float lo
, float hi
) : fZone(z
), fMin(lo
), fMax(hi
) {}
353 int fRefnum
; ///< MidiShare reference number
354 map
<float*, ctrl
*> fZoneCtrl
; ///< zone -> ctrl mapping
355 ctrl
* fMidiCtrl
[128]; ///< midi controller number -> zone ctrl
359 MidiShareUI() : fRefnum(-1) { for (int i
=0; i
<128; i
++) fMidiCtrl
[i
]=0; }
360 virtual ~MidiShareUI() { close(); }
362 // -- user interface part
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
); }
376 virtual void declare(float* zone
, const char* key
, const char* value
) {
378 if (strcmp(key
, "midictrl") == 0 && fZoneCtrl
[zone
] != 0 && n
>= 0 && n
<= 127)
379 fMidiCtrl
[n
] = fZoneCtrl
[zone
];
383 // -- MidiShare session
385 virtual void open(const char* name
) {
386 fRefnum
= MidiOpen((char*)name
);
387 MidiSetInfo(fRefnum
, this);
388 MidiSetRcvAlarm(fRefnum
, midiCallback
);
391 virtual void close() { MidiClose(fRefnum
); fRefnum
=-1; }
394 // -- MidiShare event processing
396 static void midiCallback(short refnum
)
398 MidiShareUI
* self
= (MidiShareUI
*)MidiGetInfo(refnum
);
399 for (MidiEvPtr e
=MidiGetEv(refnum
); e
!=0; e
=MidiGetEv(refnum
)) {
400 self
->processEvent(e
);
405 virtual void processEvent(MidiEvPtr e
)
408 if ( (EvType(e
)==typeCtrlChange
) && (c
=fMidiCtrl
[Pitch(e
)]) )
409 *(c
->fZone
) = c
->fMin
+ (c
->fMax
-c
->fMin
)*Vel(e
)/127;
416 /******************************************************************************
417 *******************************************************************************
419 GRAPHIC USER INTERFACE
422 *******************************************************************************
423 *******************************************************************************/
427 #define stackSize 256
431 #define kSingleMode 0
436 class GTKUI
: public UI
439 static bool fInitialized
;
440 static list
<UI
*> fGuiList
;
445 GtkWidget
* fBox
[stackSize
];
446 int fMode
[stackSize
];
449 GtkWidget
* addWidget(const char* label
, GtkWidget
* w
);
450 virtual void pushBox(int mode
, GtkWidget
* w
);
455 static const gboolean expand
= TRUE
;
456 static const gboolean fill
= TRUE
;
457 static const gboolean homogene
= FALSE
;
459 GTKUI(char * name
, int* pargc
, char*** pargv
);
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
= "");
468 virtual void closeBox();
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
);
479 // -- passive display widgets
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
);
493 /******************************************************************************
494 *******************************************************************************
496 GRAPHIC USER INTERFACE (v2)
499 *******************************************************************************
500 *******************************************************************************/
502 // global static fields
504 bool GTKUI::fInitialized
= false;
505 list
<UI
*> UI::fGuiList
;
509 static gint
delete_event( GtkWidget
*widget
, GdkEvent
*event
, gpointer data
)
514 static void destroy_event( GtkWidget
*widget
, gpointer data
)
520 GTKUI::GTKUI(char * name
, int* pargc
, char*** pargv
)
523 gtk_init(pargc
, pargv
);
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
);
534 fBox
[fTop
] = gtk_vbox_new (homogene
, 4);
535 fMode
[fTop
] = kBoxMode
;
536 gtk_container_add (GTK_CONTAINER (fWindow
), fBox
[fTop
]);
540 // empilement des boites
542 void GTKUI::pushBox(int mode
, GtkWidget
* w
)
545 assert(fTop
< stackSize
);
550 void GTKUI::closeBox()
557 // les differentes boites
559 void GTKUI::openFrameBox(const char* label
)
561 GtkWidget
* box
= gtk_frame_new (label
);
562 //gtk_container_set_border_width (GTK_CONTAINER (box), 10);
564 pushBox(kSingleMode
, addWidget(label
, box
));
567 void GTKUI::openTabBox(const char* label
)
569 pushBox(kTabMode
, addWidget(label
, gtk_notebook_new ()));
572 void GTKUI::openHorizontalBox(const char* label
)
574 GtkWidget
* box
= gtk_hbox_new (homogene
, 4);
575 gtk_container_set_border_width (GTK_CONTAINER (box
), 10);
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
);
583 pushBox(kBoxMode
, addWidget(label
, box
));
587 void GTKUI::openVerticalBox(const char* label
)
589 GtkWidget
* box
= gtk_vbox_new (homogene
, 4);
590 gtk_container_set_border_width (GTK_CONTAINER (box
), 10);
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
);
598 pushBox(kBoxMode
, addWidget(label
, box
));
602 GtkWidget
* GTKUI::addWidget(const char* label
, GtkWidget
* w
)
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;
613 // --------------------------- Press button ---------------------------
615 struct uiButton
: public uiItem
619 uiButton (UI
* ui
, float* zone
, GtkButton
* b
) : uiItem(ui
, zone
), fButton(b
) {}
621 static void pressed( GtkWidget
*widget
, gpointer data
)
623 uiItem
* c
= (uiItem
*) data
;
627 static void released( GtkWidget
*widget
, gpointer data
)
629 uiItem
* c
= (uiItem
*) data
;
633 virtual void reflectZone()
637 if (v
> 0.0) gtk_button_pressed(fButton
); else gtk_button_released(fButton
);
641 void GTKUI::addButton(const char* label
, float* zone
)
644 GtkWidget
* button
= gtk_button_new_with_label (label
);
645 addWidget(label
, button
);
647 uiButton
* c
= new uiButton(this, zone
, GTK_BUTTON(button
));
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
);
654 // --------------------------- Toggle Buttons ---------------------------
656 struct uiToggleButton
: public uiItem
658 GtkToggleButton
* fButton
;
660 uiToggleButton(UI
* ui
, float* zone
, GtkToggleButton
* b
) : uiItem(ui
, zone
), fButton(b
) {}
662 static void toggled (GtkWidget
*widget
, gpointer data
)
664 float v
= (GTK_TOGGLE_BUTTON (widget
)->active
) ? 1.0 : 0.0;
665 ((uiItem
*)data
)->modifyZone(v
);
668 virtual void reflectZone()
672 gtk_toggle_button_set_active(fButton
, v
> 0.0);
676 void GTKUI::addToggleButton(const char* label
, float* zone
)
679 GtkWidget
* button
= gtk_toggle_button_new_with_label (label
);
680 addWidget(label
, button
);
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
);
687 // --------------------------- Check Button ---------------------------
689 struct uiCheckButton
: public uiItem
691 GtkToggleButton
* fButton
;
693 uiCheckButton(UI
* ui
, float* zone
, GtkToggleButton
* b
) : uiItem(ui
, zone
), fButton(b
) {}
695 static void toggled (GtkWidget
*widget
, gpointer data
)
697 float v
= (GTK_TOGGLE_BUTTON (widget
)->active
) ? 1.0 : 0.0;
698 ((uiItem
*)data
)->modifyZone(v
);
701 virtual void reflectZone()
705 gtk_toggle_button_set_active(fButton
, v
> 0.0);
709 void GTKUI::addCheckButton(const char* label
, float* zone
)
712 GtkWidget
* button
= gtk_check_button_new_with_label (label
);
713 addWidget(label
, button
);
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
);
720 // --------------------------- Adjustmenty based widgets ---------------------------
722 struct uiAdjustment
: public uiItem
726 uiAdjustment(UI
* ui
, float* zone
, GtkAdjustment
* adj
) : uiItem(ui
, zone
), fAdj(adj
) {}
728 static void changed (GtkWidget
*widget
, gpointer data
)
730 float v
= GTK_ADJUSTMENT (widget
)->value
;
731 ((uiItem
*)data
)->modifyZone(v
);
734 virtual void reflectZone()
738 gtk_adjustment_set_value(fAdj
, v
);
742 static int precision(double n
)
744 if (n
< 0.009999) return 3;
745 else if (n
< 0.099999) return 2;
746 else if (n
< 0.999999) return 1;
750 // -------------------------- Vertical Slider -----------------------------------
752 void GTKUI::addVerticalSlider(const char* label
, float* zone
, float init
, float min
, float max
, float step
)
755 GtkObject
* adj
= gtk_adjustment_new(init
, min
, max
, step
, 10*step
, 0);
757 uiAdjustment
* c
= new uiAdjustment(this, zone
, GTK_ADJUSTMENT(adj
));
759 gtk_signal_connect (GTK_OBJECT (adj
), "value-changed", GTK_SIGNAL_FUNC (uiAdjustment::changed
), (gpointer
) c
);
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);
767 addWidget(label
, slider
);
771 // -------------------------- Horizontal Slider -----------------------------------
773 void GTKUI::addHorizontalSlider(const char* label
, float* zone
, float init
, float min
, float max
, float step
)
776 GtkObject
* adj
= gtk_adjustment_new(init
, min
, max
, step
, 10*step
, 0);
778 uiAdjustment
* c
= new uiAdjustment(this, zone
, GTK_ADJUSTMENT(adj
));
780 gtk_signal_connect (GTK_OBJECT (adj
), "value-changed", GTK_SIGNAL_FUNC (uiAdjustment::changed
), (gpointer
) c
);
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);
787 addWidget(label
, slider
);
792 // ------------------------------ Num Entry -----------------------------------
794 void GTKUI::addNumEntry(const char* label
, float* zone
, float init
, float min
, float max
, float step
)
797 GtkObject
* adj
= gtk_adjustment_new(init
, min
, max
, step
, 10*step
, step
);
799 uiAdjustment
* c
= new uiAdjustment(this, zone
, GTK_ADJUSTMENT(adj
));
801 gtk_signal_connect (GTK_OBJECT (adj
), "value-changed", GTK_SIGNAL_FUNC (uiAdjustment::changed
), (gpointer
) c
);
803 GtkWidget
* spinner
= gtk_spin_button_new (GTK_ADJUSTMENT(adj
), 0.005, precision(step
));
805 //gtk_widget_set_usize(slider, 160, -1);
807 addWidget(label
, spinner
);
812 // ========================== passive widgets ===============================
815 // ------------------------------ Progress Bar -----------------------------------
817 struct uiBargraph
: public uiItem
819 GtkProgressBar
* fProgressBar
;
823 uiBargraph(UI
* ui
, float* zone
, GtkProgressBar
* pbar
, float lo
, float hi
)
824 : uiItem(ui
, zone
), fProgressBar(pbar
), fMin(lo
), fMax(hi
) {}
826 float scale(float v
) { return (v
-fMin
)/(fMax
-fMin
); }
828 virtual void reflectZone()
832 gtk_progress_bar_set_fraction(fProgressBar
, scale(v
));
838 void GTKUI::addVerticalBargraph(const char* label
, float* zone
, float lo
, float hi
)
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
);
845 addWidget(label
, pb
);
850 void GTKUI::addHorizontalBargraph(const char* label
, float* zone
, float lo
, float hi
)
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
);
857 addWidget(label
, pb
);
862 // ------------------------------ Num Display -----------------------------------
864 struct uiNumDisplay
: public uiItem
869 uiNumDisplay(UI
* ui
, float* zone
, GtkLabel
* label
, int precision
)
870 : uiItem(ui
, zone
), fLabel(label
), fPrecision(precision
) {}
872 virtual void reflectZone()
877 if (fPrecision
<= 0) {
878 snprintf(s
, 63, "%d", int(v
));
879 } else if (fPrecision
>3) {
880 snprintf(s
, 63, "%f", v
);
882 const char* format
[] = {"%.1f", "%.2f", "%.3f"};
883 snprintf(s
, 63, format
[fPrecision
-1], v
);
885 gtk_label_set_text(fLabel
, s
);
890 void GTKUI::addNumDisplay(const char* label
, float* zone
, int precision
)
892 GtkWidget
* lw
= gtk_label_new("");
893 new uiNumDisplay(this, zone
, GTK_LABEL(lw
), precision
);
895 addWidget(label
, lw
);
900 // ------------------------------ Text Display -----------------------------------
902 struct uiTextDisplay
: public uiItem
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
)
915 while (fNames
[fNum
] != 0) fNum
++;
918 virtual void reflectZone()
923 int idx
= int(fNum
*(v
-fMin
)/(fMax
-fMin
));
925 if (idx
< 0) idx
= 0;
926 else if (idx
>= fNum
) idx
= fNum
-1;
928 gtk_label_set_text(fLabel
, fNames
[idx
]);
933 void GTKUI::addTextDisplay(const char* label
, float* zone
, const char* names
[], float lo
, float hi
)
935 GtkWidget
* lw
= gtk_label_new("");
936 new uiTextDisplay (this, zone
, GTK_LABEL(lw
), names
, lo
, hi
);
938 addWidget(label
, lw
);
947 gtk_widget_show (fBox
[0]);
948 gtk_widget_show (fWindow
);
953 * Update all user items reflecting zone z
956 static gboolean
callUpdateAllGuis(gpointer
)
966 gtk_widget_show (fBox
[0]);
967 gtk_widget_show (fWindow
);
968 gtk_timeout_add(40, callUpdateAllGuis
, 0);
974 /******************************************************************************
975 *******************************************************************************
979 *******************************************************************************
980 *******************************************************************************/
986 //----------------------------------------------------------------
987 // définition du processeur de signal
988 //----------------------------------------------------------------
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;
1004 /********************END ARCHITECTURE SECTION (part 1/2)****************/
1006 /**************************BEGIN USER SECTION **************************/
1010 /***************************END USER SECTION ***************************/
1012 /*******************BEGIN ARCHITECTURE SECTION (part 2/2)***************/
1020 /******************************************************************************
1021 *******************************************************************************
1023 JACK AUDIO INTERFACE
1025 *******************************************************************************
1026 *******************************************************************************/
1030 //----------------------------------------------------------------------------
1031 // number of input and output channels
1032 //----------------------------------------------------------------------------
1038 //----------------------------------------------------------------------------
1040 //----------------------------------------------------------------------------
1042 jack_port_t
*input_ports
[256];
1043 jack_port_t
*output_ports
[256];
1045 //----------------------------------------------------------------------------
1046 // tables of noninterleaved input and output channels for FAUST
1047 //----------------------------------------------------------------------------
1049 float* gInChannel
[256];
1050 float* gOutChannel
[256];
1052 //----------------------------------------------------------------------------
1054 //----------------------------------------------------------------------------
1056 int srate(jack_nframes_t nframes
, void *arg
)
1058 printf("the sample rate is now %u/sec\n", nframes
);
1062 void jack_shutdown(void *arg
)
1067 int process (jack_nframes_t nframes
, void *arg
)
1069 for (int i
= 0; i
< gNumInChans
; i
++) {
1070 gInChannel
[i
] = (float *)jack_port_get_buffer(input_ports
[i
], nframes
);
1072 for (int i
= 0; i
< gNumOutChans
; i
++) {
1073 gOutChannel
[i
] = (float *)jack_port_get_buffer(output_ports
[i
], nframes
);
1075 DSP
.compute(nframes
, gInChannel
, gOutChannel
);
1080 /******************************************************************************
1081 *******************************************************************************
1085 *******************************************************************************
1086 *******************************************************************************/
1089 //-------------------------------------------------------------------------
1091 //-------------------------------------------------------------------------
1093 int main(int argc
, char *argv
[] )
1096 jack_client_t
* client
;
1098 char rcfilename
[256];
1099 jack_status_t jackstat
;
1105 jname
= basename (argv
[0]);
1106 client
= jack_client_open (jname
, (jack_options_t
) 0, &jackstat
);
1108 fprintf (stderr
, "Can't connect to JACK, is the server running ?\n");
1111 if (jackstat
& JackNameNotUnique
) {
1112 jname
= jack_get_client_name (client
);
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);
1119 gNumInChans
= DSP
.getNumInputs();
1120 gNumOutChans
= DSP
.getNumOutputs();
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);
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);
1131 DSP
.buildUserInterface(&midi
);
1134 interface
= new GTKUI (jname
, &argc
, &argv
);
1135 DSP
.init(jack_get_sample_rate(client
));
1136 DSP
.buildUserInterface(interface
);
1138 home
= getenv ("HOME");
1139 if (home
== 0) home
= ".";
1140 snprintf(rcfilename
, 256, "%s/.%src", home
, jname
);
1141 interface
->recallState(rcfilename
);
1143 if (jack_activate(client
)) {
1144 fprintf(stderr
, "Can't activate JACK client\n");
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
]));
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
);
1165 jack_deactivate(client
);
1167 for (int i
= 0; i
< gNumInChans
; i
++) {
1168 jack_port_unregister(client
, input_ports
[i
]);
1170 for (int i
= 0; i
< gNumOutChans
; i
++) {
1171 jack_port_unregister(client
, output_ports
[i
]);
1174 jack_client_close(client
);
1175 interface
->saveState(rcfilename
);
1180 /********************END ARCHITECTURE SECTION (part 2/2)****************/