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>
48 #include <sys/soundcard.h>
50 #include <sys/types.h>
66 struct Meta
: map
<const char*, const char*>
68 void declare (const char* key
, const char* value
) { (*this)[key
]=value
; }
72 // g++ -O3 -lm -lpthread `gtk-config --cflags --libs` ex2.cpp
75 // On Intel set FZ (Flush to Zero) and DAZ (Denormals Are Zero)
76 // flags to avoid costly denormals
78 #include <xmmintrin.h>
80 #define AVOIDDENORMALS _mm_setcsr(_mm_getcsr() | 0x8040)
82 #define AVOIDDENORMALS _mm_setcsr(_mm_getcsr() | 0x8000)
85 #define AVOIDDENORMALS
88 //#define BENCHMARKMODE
90 //-------------------------------------------------------------------
91 // Generic min and max using c++ inline
92 //-------------------------------------------------------------------
94 inline int max (unsigned int a
, unsigned int b
) { return (a
>b
) ? a
: b
; }
95 inline int max (int a
, int b
) { return (a
>b
) ? a
: b
; }
97 inline long max (long a
, long b
) { return (a
>b
) ? a
: b
; }
98 inline long max (int a
, long b
) { return (a
>b
) ? a
: b
; }
99 inline long max (long a
, int b
) { return (a
>b
) ? a
: b
; }
101 inline float max (float a
, float b
) { return (a
>b
) ? a
: b
; }
102 inline float max (int a
, float b
) { return (a
>b
) ? a
: b
; }
103 inline float max (float a
, int b
) { return (a
>b
) ? a
: b
; }
104 inline float max (long a
, float b
) { return (a
>b
) ? a
: b
; }
105 inline float max (float a
, long b
) { return (a
>b
) ? a
: b
; }
107 inline double max (double a
, double b
) { return (a
>b
) ? a
: b
; }
108 inline double max (int a
, double b
) { return (a
>b
) ? a
: b
; }
109 inline double max (double a
, int b
) { return (a
>b
) ? a
: b
; }
110 inline double max (long a
, double b
) { return (a
>b
) ? a
: b
; }
111 inline double max (double a
, long b
) { return (a
>b
) ? a
: b
; }
112 inline double max (float a
, double b
) { return (a
>b
) ? a
: b
; }
113 inline double max (double a
, float b
) { return (a
>b
) ? a
: b
; }
116 inline int min (int a
, int b
) { return (a
<b
) ? a
: b
; }
118 inline long min (long a
, long b
) { return (a
<b
) ? a
: b
; }
119 inline long min (int a
, long b
) { return (a
<b
) ? a
: b
; }
120 inline long min (long a
, int b
) { return (a
<b
) ? a
: b
; }
122 inline float min (float a
, float b
) { return (a
<b
) ? a
: b
; }
123 inline float min (int a
, float b
) { return (a
<b
) ? a
: b
; }
124 inline float min (float a
, int b
) { return (a
<b
) ? a
: b
; }
125 inline float min (long a
, float b
) { return (a
<b
) ? a
: b
; }
126 inline float min (float a
, long b
) { return (a
<b
) ? a
: b
; }
128 inline double min (double a
, double b
) { return (a
<b
) ? a
: b
; }
129 inline double min (int a
, double b
) { return (a
<b
) ? a
: b
; }
130 inline double min (double a
, int b
) { return (a
<b
) ? a
: b
; }
131 inline double min (long a
, double b
) { return (a
<b
) ? a
: b
; }
132 inline double min (double a
, long b
) { return (a
<b
) ? a
: b
; }
133 inline double min (float a
, double b
) { return (a
<b
) ? a
: b
; }
134 inline double min (double a
, float b
) { return (a
<b
) ? a
: b
; }
137 inline int lsr (int x
, int n
) { return int(((unsigned int)x
) >> n
); }
139 inline int int2pow2 (int x
) { int r
=0; while ((1<<r
)<x
) r
++; return r
; }
142 void setRealtimePriority ()
147 struct sched_param param
;
150 pw
= getpwnam ("root");
152 param
.sched_priority
= 50; /* 0 to 99 */
153 err
= sched_setscheduler(0, SCHED_RR
, ¶m
);
156 printf("OK : Running with realtime priority\n");
158 printf("Warning : running with non-realtime priority\n");
165 /******************************************************************************
166 *******************************************************************************
170 *******************************************************************************
171 *******************************************************************************/
173 //inline void *aligned_calloc(size_t nmemb, size_t size) { return (void*)((unsigned)(calloc((nmemb*size)+15,sizeof(char)))+15 & 0xfffffff0); }
174 //inline void *aligned_calloc(size_t nmemb, size_t size) { return (void*)((size_t)(calloc((nmemb*size)+15,sizeof(char)))+15 & ~15); }
180 // mesuring jack performances
181 static __inline__
unsigned long long int rdtsc(void)
183 unsigned long long int x
;
184 __asm__
volatile (".byte 0x0f, 0x31" : "=A" (x
));
191 unsigned long long int starts
[KMESURE
];
192 unsigned long long int stops
[KMESURE
];
194 #define STARTMESURE starts[mesure%KMESURE] = rdtsc();
195 #define STOPMESURE stops[mesure%KMESURE] = rdtsc(); mesure = mesure+1;
199 unsigned long long int low
, hi
, tot
;
200 low
= hi
= tot
= (stops
[KSKIP
] - starts
[KSKIP
]);
202 if (mesure
< KMESURE
) {
204 for (int i
= KSKIP
+1; i
<mesure
; i
++) {
205 unsigned long long int m
= stops
[i
] - starts
[i
];
210 cout
<< low
<< ' ' << tot
/(mesure
-KSKIP
) << ' ' << hi
<< endl
;
214 for (int i
= KSKIP
+1; i
<KMESURE
; i
++) {
215 unsigned long long int m
= stops
[i
] - starts
[i
];
220 cout
<< low
<< ' ' << tot
/(KMESURE
-KSKIP
) << ' ' << hi
<< endl
;
232 /******************************************************************************
233 *******************************************************************************
237 *******************************************************************************
238 *******************************************************************************/
240 enum { kRead
= 1, kWrite
= 2, kReadWrite
= 3 };
242 // AudioParam : a convenient class to pass parameters to the AudioInterface
245 const char* fDeviceName
;
246 int fSamplingFrequency
;
249 int fFramesPerBuffer
;
252 fDeviceName("/dev/dsp"),
253 fSamplingFrequency(44100),
255 fSampleFormat(AFMT_S16_LE
),
256 fFramesPerBuffer(512)
259 AudioParam
& device(const char * n
) { fDeviceName
= n
; return *this; }
260 AudioParam
& frequency(int f
) { fSamplingFrequency
= f
; return *this; }
261 AudioParam
& mode(int m
) { fRWMode
= m
; return *this; }
262 AudioParam
& format(int f
) { fSampleFormat
= f
; return *this; }
263 AudioParam
& buffering(int fpb
) { fFramesPerBuffer
= fpb
; return *this; }
272 int fNumOfOutputChannels
;
273 int fNumOfInputChannels
;
274 int fInputBufferSize
;
276 int fOutputBufferSize
;
277 short* fOutputBuffer
;
282 const char* getDeviceName() { return fParam
.fDeviceName
; }
283 int getSamplingFrequency() { return fParam
.fSamplingFrequency
; }
284 int getRWMode() { return fParam
.fRWMode
; }
285 int getSampleFormat() { return fParam
.fSampleFormat
; }
286 int getFramesPerBuffer() { return fParam
.fFramesPerBuffer
; }
288 int getNumOutputs() { return fNumOfOutputChannels
; }
289 int getNumInputs() { return fNumOfInputChannels
; }
290 int getInputBufferSize() { return fInputBufferSize
; }
291 int getOutputBufferSize() { return fOutputBufferSize
; }
294 AudioInterface(const AudioParam
& ap
= AudioParam()) : fParam(ap
)
298 fNumOfOutputChannels
= 0;
299 fNumOfInputChannels
= 0;
300 fInputBufferSize
= 0;
302 fOutputBufferSize
= 0;
307 void openInputAudioDev ()
309 assert( (fInputDevice
= ::open(fParam
.fDeviceName
, O_RDONLY
, 0)) > 0);
310 assert( ioctl(fInputDevice
, SNDCTL_DSP_SETFMT
, &fParam
.fSampleFormat
) != -1);
311 assert( ioctl(fInputDevice
, SNDCTL_DSP_CHANNELS
, &fNumOfInputChannels
) != -1);
312 assert( ioctl(fInputDevice
, SNDCTL_DSP_SPEED
, &fParam
.fSamplingFrequency
) != -1);
314 int gFragFormat
= (1 << 16) + int2pow2(fParam
.fFramesPerBuffer
* 2 * fNumOfInputChannels
);
315 assert( ioctl(fInputDevice
, SNDCTL_DSP_SETFRAGMENT
, &gFragFormat
) != -1);
317 fInputBufferSize
= 0;
318 assert( ioctl(fInputDevice
, SNDCTL_DSP_GETBLKSIZE
, &fInputBufferSize
) != -1);
319 assert( fInputBufferSize
== fParam
.fFramesPerBuffer
* 2 * fNumOfInputChannels
);
321 fInputBuffer
= (short*) calloc(fInputBufferSize
, 1);
325 void openOutputAudioDev ()
327 assert( (fOutputDevice
= ::open(fParam
.fDeviceName
, O_WRONLY
, 0)) > 0);
328 assert( ioctl(fOutputDevice
, SNDCTL_DSP_SETFMT
, &fParam
.fSampleFormat
) != -1);
329 assert( ioctl(fOutputDevice
, SNDCTL_DSP_CHANNELS
,&fNumOfOutputChannels
)!= -1);
330 assert( ioctl(fOutputDevice
, SNDCTL_DSP_SPEED
, &fParam
.fSamplingFrequency
) != -1);
332 int gFragFormat
= (1 << 16) + int2pow2(fParam
.fFramesPerBuffer
* 2 * fNumOfOutputChannels
);
333 assert( ioctl(fOutputDevice
, SNDCTL_DSP_SETFRAGMENT
, &gFragFormat
) != -1);
335 fOutputBufferSize
= 0;
336 assert( ioctl(fOutputDevice
, SNDCTL_DSP_GETBLKSIZE
, &fOutputBufferSize
) != -1);
337 assert( fOutputBufferSize
== fParam
.fFramesPerBuffer
* 2 * fNumOfOutputChannels
);
339 fOutputBuffer
= (short*)calloc(fOutputBufferSize
, 1);
345 if (fParam
.fRWMode
& kRead
) openInputAudioDev();
346 if (fParam
.fRWMode
& kWrite
) openOutputAudioDev();
352 if (fParam
.fRWMode
& kRead
) ::close(fOutputDevice
);
353 if (fParam
.fRWMode
& kWrite
) ::close(fInputDevice
);
358 //----------------------------------------------------------------
359 // allocChanGroup() : allocate a group of audio buffers
360 // chan[] : is an array of buffer pointers
361 // n : is the number of buffers to allocate
362 // len : is the length of each buffer
363 //----------------------------------------------------------------
365 void allocChanGroup(float* chan
[], int n
, int len
)
367 for (int c
= 0; c
< n
; c
++) {
368 chan
[c
] = (float*) calloc (len
, sizeof(float));
373 //----------------------------------------------------------------
374 // info() : print information on the audio device
375 //----------------------------------------------------------------
381 printf("Audio Interface Description :\n");
382 printf("Sampling Frequency : %d, Sample Format : %d, Mode : %d\n", getSamplingFrequency(), getSampleFormat(), getRWMode());
384 if (getRWMode() & kWrite
) {
385 assert( ioctl(fOutputDevice
, SNDCTL_DSP_GETOSPACE
, &info
) != -1);
386 printf("output space info: fragments=%d, fragstotal=%d, fragsize=%d, bytes=%d\n", info
.fragments
, info
.fragstotal
,
387 info
.fragsize
, info
.bytes
);
389 assert( ioctl(fOutputDevice
,SNDCTL_DSP_GETCAPS
, &cap
) != -1);
390 printf("Output capabilities - %d channels : ", fNumOfOutputChannels
);
392 if (cap
& DSP_CAP_DUPLEX
) printf(" DSP_CAP_DUPLEX");
393 if (cap
& DSP_CAP_REALTIME
) printf(" DSP_CAP_REALTIME");
394 if (cap
& DSP_CAP_DUPLEX
) printf(" DSP_CAP_DUPLEX");
395 if (cap
& DSP_CAP_BATCH
) printf(" DSP_CAP_BATCH");
396 if (cap
& DSP_CAP_COPROC
) printf(" DSP_CAP_COPROC");
397 if (cap
& DSP_CAP_TRIGGER
) printf(" DSP_CAP_TRIGGER");
398 if (cap
& DSP_CAP_MMAP
) printf(" DSP_CAP_MMAP");
399 if (cap
& DSP_CAP_MULTI
) printf(" DSP_CAP_MULTI");
400 if (cap
& DSP_CAP_BIND
) printf(" DSP_CAP_BIND");
402 printf("Output block size = %d\n", fOutputBufferSize
);
406 if (getRWMode() & kRead
) {
407 assert( ioctl(fInputDevice
, SNDCTL_DSP_GETISPACE
, &info
) != -1);
408 printf("input space info: fragments=%d, fragstotal=%d, fragsize=%d, bytes=%d\n", info
.fragments
, info
.fragstotal
,
409 info
.fragsize
, info
.bytes
);
412 assert( ioctl(fInputDevice
,SNDCTL_DSP_GETCAPS
, &cap
) != -1);
413 printf("Input capabilities - %d channels : ", fNumOfInputChannels
);
414 if (cap
& DSP_CAP_DUPLEX
) printf(" DSP_CAP_DUPLEX");
415 if (cap
& DSP_CAP_REALTIME
) printf(" DSP_CAP_REALTIME");
416 if (cap
& DSP_CAP_DUPLEX
) printf(" DSP_CAP_DUPLEX");
417 if (cap
& DSP_CAP_BATCH
) printf(" DSP_CAP_BATCH");
418 if (cap
& DSP_CAP_COPROC
) printf(" DSP_CAP_COPROC");
419 if (cap
& DSP_CAP_TRIGGER
) printf(" DSP_CAP_TRIGGER");
420 if (cap
& DSP_CAP_MMAP
) printf(" DSP_CAP_MMAP");
421 if (cap
& DSP_CAP_MULTI
) printf(" DSP_CAP_MULTI");
422 if (cap
& DSP_CAP_BIND
) printf(" DSP_CAP_BIND");
424 printf("Input block size = %d\n", fInputBufferSize
);
429 //----------------------------------------------------------------
431 //----------------------------------------------------------------
433 bool read(int frames
, float* channel
[])
435 int bytes
= frames
* 2 * fNumOfInputChannels
; assert(bytes
<= fInputBufferSize
);
436 int count
= ::read(fInputDevice
, fInputBuffer
, bytes
);
437 //assert (bytes == count);
439 for (int s
= 0; s
< frames
; s
++) {
440 for (int c
= 0; c
< fNumOfInputChannels
; c
++) {
441 channel
[c
][s
] = float(fInputBuffer
[c
+ s
*fNumOfInputChannels
])*(1.0/float(SHRT_MAX
));
444 return bytes
== count
;
448 bool write(int frames
, float* channel
[])
450 int bytes
= frames
* 2 * fNumOfOutputChannels
; assert(bytes
<= fOutputBufferSize
);
452 for (int f
= 0; f
< frames
; f
++) {
453 for (int c
= 0; c
< fNumOfOutputChannels
; c
++) {
454 float x
= channel
[c
][f
];
455 fOutputBuffer
[c
+ f
*fNumOfOutputChannels
] = short( max(min(x
,1.0),-1.0) * float(SHRT_MAX
) ) ;
459 int count
= ::write(fOutputDevice
, fOutputBuffer
, bytes
);
460 assert (bytes
== count
);
462 return bytes
== count
;
471 /******************************************************************************
472 *******************************************************************************
474 GRAPHIC USER INTERFACE (v2)
477 *******************************************************************************
478 *******************************************************************************/
487 typedef void (*uiCallback
)(float val
, void* data
);
490 * Graphic User Interface : abstract definition
495 typedef list
<uiItem
*> clist
;
496 typedef map
<float*, clist
*> zmap
;
499 static list
<UI
*> fGuiList
;
505 UI() : fStopped(false) {
506 fGuiList
.push_back(this);
510 // suppression de this dans fGuiList
513 // -- registerZone(z,c) : zone management
515 void registerZone(float* z
, uiItem
* c
)
517 if (fZoneMap
.find(z
) == fZoneMap
.end()) fZoneMap
[z
] = new clist();
518 fZoneMap
[z
]->push_back(c
);
521 // -- saveState(filename) : save the value of every zone to a file
523 void saveState(char* filename
)
525 ofstream
f(filename
);
527 for (zmap::iterator i
=fZoneMap
.begin(); i
!=fZoneMap
.end(); i
++) {
528 f
<< *(i
->first
) << ' ';
535 // -- recallState(filename) : load the value of every zone from a file
537 void recallState(char* filename
)
539 ifstream
f(filename
);
541 for (zmap::iterator i
=fZoneMap
.begin(); i
!=fZoneMap
.end(); i
++) {
548 void updateAllZones();
550 void updateZone(float* z
);
552 static void updateAllGuis()
554 list
<UI
*>::iterator g
;
555 for (g
= fGuiList
.begin(); g
!= fGuiList
.end(); g
++) {
556 (*g
)->updateAllZones();
562 virtual void addButton(const char* label
, float* zone
) = 0;
563 virtual void addToggleButton(const char* label
, float* zone
) = 0;
564 virtual void addCheckButton(const char* label
, float* zone
) = 0;
565 virtual void addVerticalSlider(const char* label
, float* zone
, float init
, float min
, float max
, float step
) = 0;
566 virtual void addHorizontalSlider(const char* label
, float* zone
, float init
, float min
, float max
, float step
) = 0;
567 virtual void addNumEntry(const char* label
, float* zone
, float init
, float min
, float max
, float step
) = 0;
569 // -- passive widgets
571 virtual void addNumDisplay(const char* label
, float* zone
, int precision
) = 0;
572 virtual void addTextDisplay(const char* label
, float* zone
, const char* names
[], float min
, float max
) = 0;
573 virtual void addHorizontalBargraph(const char* label
, float* zone
, float min
, float max
) = 0;
574 virtual void addVerticalBargraph(const char* label
, float* zone
, float min
, float max
) = 0;
576 void addCallback(float* zone
, uiCallback foo
, void* data
);
578 // -- widget's layouts
580 virtual void openFrameBox(const char* label
) = 0;
581 virtual void openTabBox(const char* label
) = 0;
582 virtual void openHorizontalBox(const char* label
) = 0;
583 virtual void openVerticalBox(const char* label
) = 0;
584 virtual void closeBox() = 0;
586 virtual void show() = 0;
587 virtual void run() = 0;
589 void stop() { fStopped
= true; }
590 bool stopped() { return fStopped
; }
592 virtual void declare(float* zone
, const char* key
, const char* value
) {}
597 * User Interface Item: abstract definition
608 uiItem (UI
* ui
, float* zone
) : fGUI(ui
), fZone(zone
), fCache(-123456.654321)
610 ui
->registerZone(zone
, this);
617 void modifyZone(float v
)
622 fGUI
->updateZone(fZone
);
626 float cache() { return fCache
; }
627 virtual void reflectZone() = 0;
635 struct uiCallbackItem
: public uiItem
637 uiCallback fCallback
;
640 uiCallbackItem(UI
* ui
, float* zone
, uiCallback foo
, void* data
)
641 : uiItem(ui
, zone
), fCallback(foo
), fData(data
) {}
643 virtual void reflectZone() {
650 // en cours d'installation de call back. a finir!!!!!
653 * Update all user items reflecting zone z
656 inline void UI::updateZone(float* z
)
659 clist
* l
= fZoneMap
[z
];
660 for (clist::iterator c
= l
->begin(); c
!= l
->end(); c
++) {
661 if ((*c
)->cache() != v
) (*c
)->reflectZone();
667 * Update all user items not up to date
670 inline void UI::updateAllZones()
672 for (zmap::iterator m
= fZoneMap
.begin(); m
!= fZoneMap
.end(); m
++) {
674 clist
* l
= m
->second
;
676 for (clist::iterator c
= l
->begin(); c
!= l
->end(); c
++) {
677 if ((*c
)->cache() != v
) (*c
)->reflectZone();
682 inline void UI::addCallback(float* zone
, uiCallback foo
, void* data
)
684 new uiCallbackItem(this, zone
, foo
, data
);
687 /******************************************************************************
688 *******************************************************************************
690 GRAPHIC USER INTERFACE
693 *******************************************************************************
694 *******************************************************************************/
698 #define stackSize 256
702 #define kSingleMode 0
708 * rmWhiteSpaces(): Remove the leading and trailing white spaces of a string
709 * (but not those in the middle of the string)
711 static string
rmWhiteSpaces(const string
& s
)
713 size_t i
= s
.find_first_not_of(" \t");
714 size_t j
= s
.find_last_not_of(" \t");
716 if (i
!= string::npos
& j
!= string::npos
) {
717 return s
.substr(i
, 1+j
-i
);
725 * Extracts metdata from a label : 'vol [unit: dB]' -> 'vol' + metadata
727 static void extractMetadata(const string
& fulllabel
, string
& label
, map
<string
, string
>& metadata
)
729 enum {kLabel
, kEscape1
, kEscape2
, kEscape3
, kKey
, kValue
};
730 int state
= kLabel
; int deep
= 0;
733 for (unsigned int i
=0; i
< fulllabel
.size(); i
++) {
734 char c
= fulllabel
[i
];
739 case '\\' : state
= kEscape1
; break;
740 case '[' : state
= kKey
; deep
++; break;
741 default : label
+= c
;
763 case '\\' : state
= kEscape2
;
770 case ':' : if (deep
== 1) {
778 metadata
[rmWhiteSpaces(key
)] = "";
793 case '\\' : state
= kEscape3
;
802 metadata
[rmWhiteSpaces(key
)]=rmWhiteSpaces(value
);
810 default : value
+= c
;
815 cerr
<< "ERROR unrecognized state " << state
<< endl
;
818 label
= rmWhiteSpaces(label
);
822 class GTKUI
: public UI
825 static bool fInitialized
;
826 static list
<UI
*> fGuiList
;
827 static map
<float*, float> fGuiSize
; // map widget zone with widget size coef
828 static map
<float*, string
> fTooltip
; // map widget zone with tooltip strings
833 GtkWidget
* fBox
[stackSize
];
834 int fMode
[stackSize
];
837 GtkWidget
* addWidget(const char* label
, GtkWidget
* w
);
838 virtual void pushBox(int mode
, GtkWidget
* w
);
843 static const gboolean expand
= TRUE
;
844 static const gboolean fill
= TRUE
;
845 static const gboolean homogene
= FALSE
;
847 GTKUI(char * name
, int* pargc
, char*** pargv
);
849 // -- Labels and metadata
851 virtual void declare (float* zone
, const char* key
, const char* value
);
852 virtual int checkLabelOptions (GtkWidget
* widget
, const string
& fullLabel
, string
& simplifiedLabel
);
853 virtual void checkForTooltip (float* zone
, GtkWidget
* widget
);
857 virtual void openFrameBox(const char* label
);
858 virtual void openTabBox(const char* label
= "");
859 virtual void openHorizontalBox(const char* label
= "");
860 virtual void openVerticalBox(const char* label
= "");
862 // -- extra widget's layouts
864 virtual void openDialogBox(const char* label
, float* zone
);
865 virtual void openEventBox(const char* label
= "");
866 virtual void openHandleBox(const char* label
= "");
867 virtual void openExpanderBox(const char* label
, float* zone
);
869 virtual void closeBox();
870 virtual void adjustStack(int n
);
874 virtual void addButton(const char* label
, float* zone
);
875 virtual void addToggleButton(const char* label
, float* zone
);
876 virtual void addCheckButton(const char* label
, float* zone
);
877 virtual void addVerticalSlider(const char* label
, float* zone
, float init
, float min
, float max
, float step
);
878 virtual void addHorizontalSlider(const char* label
, float* zone
, float init
, float min
, float max
, float step
);
879 virtual void addNumEntry(const char* label
, float* zone
, float init
, float min
, float max
, float step
);
881 // -- passive display widgets
883 virtual void addNumDisplay(const char* label
, float* zone
, int precision
);
884 virtual void addTextDisplay(const char* label
, float* zone
, const char* names
[], float min
, float max
);
885 virtual void addHorizontalBargraph(const char* label
, float* zone
, float min
, float max
);
886 virtual void addVerticalBargraph(const char* label
, float* zone
, float min
, float max
);
895 /******************************************************************************
896 *******************************************************************************
898 GRAPHIC USER INTERFACE (v2)
901 *******************************************************************************
902 *******************************************************************************/
904 // global static fields
906 list
<UI
*> UI::fGuiList
;
908 bool GTKUI::fInitialized
= false;
909 map
<float*, float> GTKUI::fGuiSize
;
910 map
<float*, string
> GTKUI::fTooltip
;
914 static gint
delete_event( GtkWidget
*widget
, GdkEvent
*event
, gpointer data
)
919 static void destroy_event( GtkWidget
*widget
, gpointer data
)
925 GTKUI::GTKUI(char * name
, int* pargc
, char*** pargv
)
928 gtk_init(pargc
, pargv
);
932 fWindow
= gtk_window_new (GTK_WINDOW_TOPLEVEL
);
933 //gtk_container_set_border_width (GTK_CONTAINER (fWindow), 10);
934 gtk_window_set_title (GTK_WINDOW (fWindow
), name
);
935 gtk_signal_connect (GTK_OBJECT (fWindow
), "delete_event", GTK_SIGNAL_FUNC (delete_event
), NULL
);
936 gtk_signal_connect (GTK_OBJECT (fWindow
), "destroy", GTK_SIGNAL_FUNC (destroy_event
), NULL
);
939 fBox
[fTop
] = gtk_vbox_new (homogene
, 4);
940 fMode
[fTop
] = kBoxMode
;
941 gtk_container_add (GTK_CONTAINER (fWindow
), fBox
[fTop
]);
945 // empilement des boites
947 void GTKUI::pushBox(int mode
, GtkWidget
* w
)
950 assert(fTop
< stackSize
);
957 * Remove n levels from the stack S before the top level
958 * adjustStack(n): S -> S' with S' = S(0),S(n+1),S(n+2),...
960 void GTKUI::adjustStack(int n
)
966 fMode
[fTop
] = fMode
[fTop
+n
];
967 fBox
[fTop
] = fBox
[fTop
+n
];
971 void GTKUI::closeBox()
979 * Analyses the widget zone metadata declarations and takes
980 * appropriate actions
982 void GTKUI::declare(float* zone
, const char* key
, const char* value
)
984 if (strcmp(key
,"size")==0) {
985 fGuiSize
[zone
]=atof(value
);
987 else if (strcmp(key
,"tooltip")==0) {
988 fTooltip
[zone
] = value
;
995 * Analyses a full label and activates the relevant options. returns a simplified
996 * label (without options) and an amount of stack adjustement (in case additional
997 * containers were pushed on the stack).
1000 int GTKUI::checkLabelOptions(GtkWidget
* widget
, const string
& fullLabel
, string
& simplifiedLabel
)
1002 map
<string
, string
> metadata
;
1003 extractMetadata(fullLabel
, simplifiedLabel
, metadata
);
1005 if (metadata
.count("tooltip")) {
1006 gtk_tooltips_set_tip (gtk_tooltips_new (), widget
, metadata
["tooltip"].c_str(), NULL
);
1008 if (metadata
["option"] == "detachable") {
1009 openHandleBox(simplifiedLabel
.c_str());
1013 // no adjustement of the stack needed
1018 * Check if a tooltip is associated to a zone and add it to the corresponding widget
1020 void GTKUI::checkForTooltip(float* zone
, GtkWidget
* widget
)
1022 if (fTooltip
.count(zone
)) {
1023 gtk_tooltips_set_tip (gtk_tooltips_new (), widget
, fTooltip
[zone
].c_str(), NULL
);
1028 // les differentes boites
1030 void GTKUI::openFrameBox(const char* label
)
1032 GtkWidget
* box
= gtk_frame_new (label
);
1033 //gtk_container_set_border_width (GTK_CONTAINER (box), 10);
1035 pushBox(kSingleMode
, addWidget(label
, box
));
1039 void GTKUI::openTabBox(const char* fullLabel
)
1042 GtkWidget
* widget
= gtk_notebook_new();
1044 int adjust
= checkLabelOptions(widget
, fullLabel
, label
);
1046 pushBox(kTabMode
, addWidget(label
.c_str(), widget
));
1048 // adjust stack because otherwise Handlebox will remain open
1049 adjustStack(adjust
);
1053 void GTKUI::openHorizontalBox(const char* fullLabel
)
1056 GtkWidget
* box
= gtk_hbox_new (homogene
, 4);
1057 int adjust
= checkLabelOptions(box
, fullLabel
, label
);
1059 gtk_container_set_border_width (GTK_CONTAINER (box
), 10);
1061 if (fMode
[fTop
] != kTabMode
&& label
[0] != 0) {
1062 GtkWidget
* frame
= addWidget(label
.c_str(), gtk_frame_new (label
.c_str()));
1063 gtk_container_add (GTK_CONTAINER(frame
), box
);
1064 gtk_widget_show(box
);
1065 pushBox(kBoxMode
, box
);
1067 pushBox(kBoxMode
, addWidget(label
.c_str(), box
));
1070 // adjust stack because otherwise Handlebox will remain open
1071 adjustStack(adjust
);
1075 void GTKUI::openVerticalBox(const char* fullLabel
)
1078 GtkWidget
* box
= gtk_vbox_new (homogene
, 4);
1079 int adjust
= checkLabelOptions(box
, fullLabel
, label
);
1081 gtk_container_set_border_width (GTK_CONTAINER (box
), 10);
1083 if (fMode
[fTop
] != kTabMode
&& label
[0] != 0) {
1084 GtkWidget
* frame
= addWidget(label
.c_str(), gtk_frame_new (label
.c_str()));
1085 gtk_container_add (GTK_CONTAINER(frame
), box
);
1086 gtk_widget_show(box
);
1087 pushBox(kBoxMode
, box
);
1089 pushBox(kBoxMode
, addWidget(label
.c_str(), box
));
1092 // adjust stack because otherwise Handlebox will remain open
1093 adjustStack(adjust
);
1097 void GTKUI::openHandleBox(const char* label
)
1099 GtkWidget
* box
= gtk_hbox_new (homogene
, 4);
1100 gtk_container_set_border_width (GTK_CONTAINER (box
), 2);
1101 if (fMode
[fTop
] != kTabMode
&& label
[0] != 0)
1103 GtkWidget
* frame
= addWidget(label
, gtk_handle_box_new ());
1104 gtk_container_add (GTK_CONTAINER(frame
), box
);
1105 gtk_widget_show(box
);
1106 pushBox(kBoxMode
, box
);
1110 pushBox(kBoxMode
, addWidget(label
, box
));
1115 void GTKUI::openEventBox(const char* label
)
1117 GtkWidget
* box
= gtk_hbox_new (homogene
, 4);
1118 gtk_container_set_border_width (GTK_CONTAINER (box
), 2);
1119 if (fMode
[fTop
] != kTabMode
&& label
[0] != 0)
1121 GtkWidget
* frame
= addWidget(label
, gtk_event_box_new ());
1122 gtk_container_add (GTK_CONTAINER(frame
), box
);
1123 gtk_widget_show(box
);
1124 pushBox(kBoxMode
, box
);
1128 pushBox(kBoxMode
, addWidget(label
, box
));
1133 struct uiExpanderBox
: public uiItem
1135 GtkExpander
* fButton
;
1136 uiExpanderBox(UI
* ui
, float* zone
, GtkExpander
* b
) : uiItem(ui
, zone
), fButton(b
) {}
1137 static void expanded (GtkWidget
*widget
, gpointer data
)
1139 float v
= gtk_expander_get_expanded (GTK_EXPANDER(widget
));
1145 ((uiItem
*)data
)->modifyZone(v
);
1148 virtual void reflectZone()
1152 gtk_expander_set_expanded(GTK_EXPANDER(fButton
), v
);
1156 void GTKUI::openExpanderBox(const char* label
, float* zone
)
1159 GtkWidget
* box
= gtk_hbox_new (homogene
, 4);
1160 gtk_container_set_border_width (GTK_CONTAINER (box
), 2);
1161 if (fMode
[fTop
] != kTabMode
&& label
[0] != 0)
1163 GtkWidget
* frame
= addWidget(label
, gtk_expander_new (label
));
1164 gtk_container_add (GTK_CONTAINER(frame
), box
);
1165 uiExpanderBox
* c
= new uiExpanderBox(this, zone
, GTK_EXPANDER(frame
));
1166 gtk_signal_connect (GTK_OBJECT (frame
), "activate", GTK_SIGNAL_FUNC (uiExpanderBox::expanded
), (gpointer
)c
);
1167 gtk_widget_show(box
);
1168 pushBox(kBoxMode
, box
);
1172 pushBox(kBoxMode
, addWidget(label
, box
));
1178 GtkWidget
* GTKUI::addWidget(const char* label
, GtkWidget
* w
)
1180 switch (fMode
[fTop
]) {
1181 case kSingleMode
: gtk_container_add (GTK_CONTAINER(fBox
[fTop
]), w
); break;
1182 case kBoxMode
: gtk_box_pack_start (GTK_BOX(fBox
[fTop
]), w
, expand
, fill
, 0); break;
1183 case kTabMode
: gtk_notebook_append_page (GTK_NOTEBOOK(fBox
[fTop
]), w
, gtk_label_new(label
)); break;
1185 gtk_widget_show (w
);
1189 // --------------------------- Press button ---------------------------
1191 struct uiButton
: public uiItem
1195 uiButton (UI
* ui
, float* zone
, GtkButton
* b
) : uiItem(ui
, zone
), fButton(b
) {}
1197 static void pressed( GtkWidget
*widget
, gpointer data
)
1199 uiItem
* c
= (uiItem
*) data
;
1203 static void released( GtkWidget
*widget
, gpointer data
)
1205 uiItem
* c
= (uiItem
*) data
;
1209 virtual void reflectZone()
1213 if (v
> 0.0) gtk_button_pressed(fButton
); else gtk_button_released(fButton
);
1217 void GTKUI::addButton(const char* label
, float* zone
)
1220 GtkWidget
* button
= gtk_button_new_with_label (label
);
1221 addWidget(label
, button
);
1223 uiButton
* c
= new uiButton(this, zone
, GTK_BUTTON(button
));
1225 gtk_signal_connect (GTK_OBJECT (button
), "pressed", GTK_SIGNAL_FUNC (uiButton::pressed
), (gpointer
) c
);
1226 gtk_signal_connect (GTK_OBJECT (button
), "released", GTK_SIGNAL_FUNC (uiButton::released
), (gpointer
) c
);
1228 checkForTooltip(zone
, button
);
1231 // --------------------------- Toggle Buttons ---------------------------
1233 struct uiToggleButton
: public uiItem
1235 GtkToggleButton
* fButton
;
1237 uiToggleButton(UI
* ui
, float* zone
, GtkToggleButton
* b
) : uiItem(ui
, zone
), fButton(b
) {}
1239 static void toggled (GtkWidget
*widget
, gpointer data
)
1241 float v
= (GTK_TOGGLE_BUTTON (widget
)->active
) ? 1.0 : 0.0;
1242 ((uiItem
*)data
)->modifyZone(v
);
1245 virtual void reflectZone()
1249 gtk_toggle_button_set_active(fButton
, v
> 0.0);
1253 void GTKUI::addToggleButton(const char* label
, float* zone
)
1256 GtkWidget
* button
= gtk_toggle_button_new_with_label (label
);
1257 addWidget(label
, button
);
1259 uiToggleButton
* c
= new uiToggleButton(this, zone
, GTK_TOGGLE_BUTTON(button
));
1260 gtk_signal_connect (GTK_OBJECT (button
), "toggled", GTK_SIGNAL_FUNC (uiToggleButton::toggled
), (gpointer
) c
);
1262 checkForTooltip(zone
, button
);
1267 void show_dialog(GtkWidget
*widget
, gpointer data
)
1269 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(widget
)) == TRUE
)
1271 gtk_widget_show(GTK_WIDGET(data
));
1272 gint root_x
, root_y
;
1273 gtk_window_get_position (GTK_WINDOW(data
), &root_x
, &root_y
);
1275 gtk_window_move(GTK_WINDOW(data
), root_x
, root_y
);
1277 else gtk_widget_hide(GTK_WIDGET(data
));
1280 static gboolean
deleteevent( GtkWidget
*widget
, gpointer data
)
1285 void GTKUI::openDialogBox(const char* label
, float* zone
)
1287 // create toplevel window and set properties
1288 GtkWidget
* dialog
= gtk_window_new (GTK_WINDOW_TOPLEVEL
);
1289 gtk_window_set_decorated(GTK_WINDOW(dialog
), TRUE
);
1290 gtk_window_set_deletable(GTK_WINDOW(dialog
), FALSE
);
1291 gtk_window_set_resizable(GTK_WINDOW(dialog
), FALSE
);
1292 gtk_window_set_gravity(GTK_WINDOW(dialog
), GDK_GRAVITY_SOUTH
);
1293 gtk_window_set_transient_for (GTK_WINDOW(dialog
), GTK_WINDOW(fWindow
));
1294 gtk_window_set_position (GTK_WINDOW(dialog
), GTK_WIN_POS_MOUSE
);
1295 gtk_window_set_keep_below (GTK_WINDOW(dialog
), FALSE
);
1296 gtk_window_set_title (GTK_WINDOW (dialog
), label
);
1297 g_signal_connect (G_OBJECT (dialog
), "delete_event", G_CALLBACK (deleteevent
), NULL
);
1298 gtk_window_set_destroy_with_parent(GTK_WINDOW(dialog
), TRUE
);
1300 GtkWidget
* box
= gtk_hbox_new (homogene
, 4);
1303 GtkWidget
* button
= gtk_toggle_button_new ();
1304 gtk_signal_connect (GTK_OBJECT (button
), "toggled", GTK_SIGNAL_FUNC (show_dialog
), (gpointer
) dialog
);
1306 gtk_container_add (GTK_CONTAINER(fBox
[fTop
]), button
);
1307 gtk_container_add (GTK_CONTAINER(dialog
), box
);
1308 gtk_widget_show (button
);
1309 gtk_widget_show(box
);
1310 pushBox(kBoxMode
, box
);
1316 // --------------------------- Check Button ---------------------------
1318 struct uiCheckButton
: public uiItem
1320 GtkToggleButton
* fButton
;
1322 uiCheckButton(UI
* ui
, float* zone
, GtkToggleButton
* b
) : uiItem(ui
, zone
), fButton(b
) {}
1324 static void toggled (GtkWidget
*widget
, gpointer data
)
1326 float v
= (GTK_TOGGLE_BUTTON (widget
)->active
) ? 1.0 : 0.0;
1327 ((uiItem
*)data
)->modifyZone(v
);
1330 virtual void reflectZone()
1334 gtk_toggle_button_set_active(fButton
, v
> 0.0);
1338 void GTKUI::addCheckButton(const char* label
, float* zone
)
1341 GtkWidget
* button
= gtk_check_button_new_with_label (label
);
1342 addWidget(label
, button
);
1344 uiCheckButton
* c
= new uiCheckButton(this, zone
, GTK_TOGGLE_BUTTON(button
));
1345 gtk_signal_connect (GTK_OBJECT (button
), "toggled", GTK_SIGNAL_FUNC(uiCheckButton::toggled
), (gpointer
) c
);
1347 checkForTooltip(zone
, button
);
1351 // --------------------------- Adjustmenty based widgets ---------------------------
1353 struct uiAdjustment
: public uiItem
1355 GtkAdjustment
* fAdj
;
1357 uiAdjustment(UI
* ui
, float* zone
, GtkAdjustment
* adj
) : uiItem(ui
, zone
), fAdj(adj
) {}
1359 static void changed (GtkWidget
*widget
, gpointer data
)
1361 float v
= GTK_ADJUSTMENT (widget
)->value
;
1362 ((uiItem
*)data
)->modifyZone(v
);
1365 virtual void reflectZone()
1369 gtk_adjustment_set_value(fAdj
, v
);
1373 static int precision(double n
)
1375 if (n
< 0.009999) return 3;
1376 else if (n
< 0.099999) return 2;
1377 else if (n
< 0.999999) return 1;
1381 // -------------------------- Vertical Slider -----------------------------------
1383 void GTKUI::addVerticalSlider(const char* label
, float* zone
, float init
, float min
, float max
, float step
)
1386 GtkObject
* adj
= gtk_adjustment_new(init
, min
, max
, step
, 10*step
, 0);
1388 uiAdjustment
* c
= new uiAdjustment(this, zone
, GTK_ADJUSTMENT(adj
));
1390 gtk_signal_connect (GTK_OBJECT (adj
), "value-changed", GTK_SIGNAL_FUNC (uiAdjustment::changed
), (gpointer
) c
);
1392 GtkWidget
* slider
= gtk_vscale_new (GTK_ADJUSTMENT(adj
));
1393 gtk_range_set_inverted (GTK_RANGE(slider
), TRUE
);
1394 gtk_scale_set_digits(GTK_SCALE(slider
), precision(step
));
1395 float size
= 160 * pow(2, fGuiSize
[zone
]);
1396 gtk_widget_set_usize(slider
, -1, size
);
1398 if (label
&& label
[0]!=0) {
1399 openFrameBox(label
);
1400 addWidget(label
, slider
);
1403 addWidget(label
, slider
);
1406 checkForTooltip(zone
, slider
);
1409 // -------------------------- Horizontal Slider -----------------------------------
1411 void GTKUI::addHorizontalSlider(const char* label
, float* zone
, float init
, float min
, float max
, float step
)
1414 GtkObject
* adj
= gtk_adjustment_new(init
, min
, max
, step
, 10*step
, 0);
1416 uiAdjustment
* c
= new uiAdjustment(this, zone
, GTK_ADJUSTMENT(adj
));
1418 gtk_signal_connect (GTK_OBJECT (adj
), "value-changed", GTK_SIGNAL_FUNC (uiAdjustment::changed
), (gpointer
) c
);
1420 GtkWidget
* slider
= gtk_hscale_new (GTK_ADJUSTMENT(adj
));
1421 gtk_scale_set_digits(GTK_SCALE(slider
), precision(step
));
1422 float size
= 160 * pow(2, fGuiSize
[zone
]);
1423 gtk_widget_set_usize(slider
, size
, -1);
1425 if (label
&& label
[0]!=0) {
1426 openFrameBox(label
);
1427 addWidget(label
, slider
);
1430 addWidget(label
, slider
);
1433 checkForTooltip(zone
, slider
);
1437 // ------------------------------ Num Entry -----------------------------------
1439 void GTKUI::addNumEntry(const char* label
, float* zone
, float init
, float min
, float max
, float step
)
1442 GtkObject
* adj
= gtk_adjustment_new(init
, min
, max
, step
, 10*step
, step
);
1444 uiAdjustment
* c
= new uiAdjustment(this, zone
, GTK_ADJUSTMENT(adj
));
1446 gtk_signal_connect (GTK_OBJECT (adj
), "value-changed", GTK_SIGNAL_FUNC (uiAdjustment::changed
), (gpointer
) c
);
1448 GtkWidget
* spinner
= gtk_spin_button_new (GTK_ADJUSTMENT(adj
), 0.005, precision(step
));
1450 //gtk_widget_set_usize(slider, 160, -1);
1451 openFrameBox(label
);
1452 addWidget(label
, spinner
);
1455 checkForTooltip(zone
, spinner
);
1459 // ========================== passive widgets ===============================
1462 // ------------------------------ Progress Bar -----------------------------------
1464 struct uiBargraph
: public uiItem
1466 GtkProgressBar
* fProgressBar
;
1470 uiBargraph(UI
* ui
, float* zone
, GtkProgressBar
* pbar
, float lo
, float hi
)
1471 : uiItem(ui
, zone
), fProgressBar(pbar
), fMin(lo
), fMax(hi
) {}
1473 float scale(float v
) { return (v
-fMin
)/(fMax
-fMin
); }
1475 virtual void reflectZone()
1479 gtk_progress_bar_set_fraction(fProgressBar
, scale(v
));
1485 void GTKUI::addVerticalBargraph(const char* label
, float* zone
, float lo
, float hi
)
1487 GtkWidget
* pb
= gtk_progress_bar_new();
1488 gtk_progress_bar_set_orientation(GTK_PROGRESS_BAR(pb
), GTK_PROGRESS_BOTTOM_TO_TOP
);
1489 gtk_widget_set_size_request(pb
, 8, -1);
1490 new uiBargraph(this, zone
, GTK_PROGRESS_BAR(pb
), lo
, hi
);
1491 openFrameBox(label
);
1492 addWidget(label
, pb
);
1495 checkForTooltip(zone
, pb
);
1499 void GTKUI::addHorizontalBargraph(const char* label
, float* zone
, float lo
, float hi
)
1501 GtkWidget
* pb
= gtk_progress_bar_new();
1502 gtk_progress_bar_set_orientation(GTK_PROGRESS_BAR(pb
), GTK_PROGRESS_LEFT_TO_RIGHT
);
1503 gtk_widget_set_size_request(pb
, -1, 8);
1504 new uiBargraph(this, zone
, GTK_PROGRESS_BAR(pb
), lo
, hi
);
1505 openFrameBox(label
);
1506 addWidget(label
, pb
);
1509 checkForTooltip(zone
, pb
);
1513 // ------------------------------ Num Display -----------------------------------
1515 struct uiNumDisplay
: public uiItem
1520 uiNumDisplay(UI
* ui
, float* zone
, GtkLabel
* label
, int precision
)
1521 : uiItem(ui
, zone
), fLabel(label
), fPrecision(precision
) {}
1523 virtual void reflectZone()
1528 if (fPrecision
<= 0) {
1529 snprintf(s
, 63, "%d", int(v
));
1530 } else if (fPrecision
>3) {
1531 snprintf(s
, 63, "%f", v
);
1533 const char* format
[] = {"%.1f", "%.2f", "%.3f"};
1534 snprintf(s
, 63, format
[fPrecision
-1], v
);
1536 gtk_label_set_text(fLabel
, s
);
1541 void GTKUI::addNumDisplay(const char* label
, float* zone
, int precision
)
1543 GtkWidget
* lw
= gtk_label_new("");
1544 new uiNumDisplay(this, zone
, GTK_LABEL(lw
), precision
);
1545 openFrameBox(label
);
1546 addWidget(label
, lw
);
1549 checkForTooltip(zone
, lw
);
1553 // ------------------------------ Text Display -----------------------------------
1555 struct uiTextDisplay
: public uiItem
1558 const char** fNames
;
1564 uiTextDisplay (UI
* ui
, float* zone
, GtkLabel
* label
, const char* names
[], float lo
, float hi
)
1565 : uiItem(ui
, zone
), fLabel(label
), fNames(names
), fMin(lo
), fMax(hi
)
1568 while (fNames
[fNum
] != 0) fNum
++;
1571 virtual void reflectZone()
1576 int idx
= int(fNum
*(v
-fMin
)/(fMax
-fMin
));
1578 if (idx
< 0) idx
= 0;
1579 else if (idx
>= fNum
) idx
= fNum
-1;
1581 gtk_label_set_text(fLabel
, fNames
[idx
]);
1586 void GTKUI::addTextDisplay(const char* label
, float* zone
, const char* names
[], float lo
, float hi
)
1588 GtkWidget
* lw
= gtk_label_new("");
1589 new uiTextDisplay (this, zone
, GTK_LABEL(lw
), names
, lo
, hi
);
1590 openFrameBox(label
);
1591 addWidget(label
, lw
);
1594 checkForTooltip(zone
, lw
);
1602 gtk_widget_show (fBox
[0]);
1603 gtk_widget_show (fWindow
);
1608 * Update all user items reflecting zone z
1611 static gboolean
callUpdateAllGuis(gpointer
)
1613 UI::updateAllGuis();
1621 gtk_widget_show (fBox
[0]);
1622 gtk_widget_show (fWindow
);
1623 gtk_timeout_add(40, callUpdateAllGuis
, 0);
1631 /******************************************************************************
1632 *******************************************************************************
1636 *******************************************************************************
1637 *******************************************************************************/
1640 //---------------------------------------------------
1641 // tableaux de buffers initialis� par allocChannels
1642 //---------------------------------------------------
1644 float* gInChannel
[256];
1645 float* gOutChannel
[256];
1647 void allocChannels (int size
, int numInChan
, int numOutChan
)
1650 assert (numInChan
< 256);
1651 assert (numOutChan
< 256);
1654 for (int i
= 0; i
< numInChan
; i
++) {
1655 gInChannel
[i
] = (float*) calloc (size
, sizeof(float));
1656 for (int j
= 0; j
< size
; j
++) {
1657 gInChannel
[i
][j
] = 0.0;
1661 for (int i
= 0; i
< numOutChan
; i
++) {
1662 gOutChannel
[i
] = (float*) calloc (size
, sizeof(float));
1663 for (int j
= 0; j
< size
; j
++) {
1664 gOutChannel
[i
][j
] = 0.0;
1671 //----------------------------------------------------------------
1672 // d�inition du processeur de signal
1673 //----------------------------------------------------------------
1682 virtual int getNumInputs() = 0;
1683 virtual int getNumOutputs() = 0;
1684 virtual void buildUserInterface(UI
* interface
) = 0;
1685 virtual void init(int samplingRate
) = 0;
1686 virtual void compute(int len
, float** inputs
, float** outputs
) = 0;
1691 /********************END ARCHITECTURE SECTION (part 1/2)****************/
1693 /**************************BEGIN USER SECTION **************************/
1697 /***************************END USER SECTION ***************************/
1699 /*******************BEGIN ARCHITECTURE SECTION (part 2/2)***************/
1707 /******************************************************************************
1708 *******************************************************************************
1712 *******************************************************************************
1713 *******************************************************************************/
1715 // Scan Command Line Arguments
1717 long lopt (char *argv
[], const char *name
, long def
)
1720 for (i
=0; argv
[i
]; i
++) if (!strcmp(argv
[i
], name
)) return atoi(argv
[i
+1]);
1725 //-------------------------------------------------------------------------
1727 //-------------------------------------------------------------------------
1728 pthread_t guithread
;
1730 void* run_ui(void* ptr
)
1732 UI
* interface
= (UI
*) ptr
;
1738 int main(int argc
, char *argv
[] )
1740 UI
* interface
= new GTKUI(argv
[0], &argc
, &argv
);
1741 // compute rcfilename to (re)store application state
1742 char rcfilename
[256];
1743 char* home
= getenv("HOME");
1744 snprintf(rcfilename
, 255, "%s/.%src", home
, basename(argv
[0]));
1746 AudioInterface
audio (
1747 AudioParam().frequency(lopt(argv
, "--frequency", 44100))
1748 .buffering(lopt(argv
, "--buffer", 128))
1749 //.mode( ((DSP.getNumInputs()>0)?kRead:0) | ((DSP.getNumOutputs()>0)?kWrite:0) )
1754 DSP
.init(audio
.getSamplingFrequency());
1755 DSP
.buildUserInterface(interface
);
1757 interface
->recallState(rcfilename
);
1759 pthread_create(&guithread
, NULL
, run_ui
, interface
);
1761 float* inChannel
[256];
1762 float* outChannel
[256];
1763 int fpb
= audio
.getFramesPerBuffer();
1765 audio
.allocChanGroup(inChannel
, max(audio
.getNumInputs(), DSP
.getNumInputs()), fpb
);
1766 audio
.allocChanGroup(outChannel
, max(audio
.getNumOutputs(), DSP
.getNumOutputs()), fpb
);
1767 setRealtimePriority();
1769 // Sound processing loop
1770 audio
.write(fpb
, outChannel
);
1771 audio
.write(fpb
, outChannel
);
1772 while(!interface
->stopped()) {
1773 if ( !audio
.write(fpb
, outChannel
)) printf("w");
1774 if ( !audio
.read (fpb
, inChannel
)) printf("r");;
1776 DSP
.compute(fpb
, inChannel
, outChannel
);
1781 interface
->saveState(rcfilename
);
1783 #ifdef BENCHMARKMODE
1790 /********************END ARCHITECTURE SECTION (part 2/2)****************/