second part of: change offset arguments to various <T>Buffer::read/merge methods...
[ardour.git] / libs / fluidsynth / src / fluid_sys.h
1 /* FluidSynth - A Software Synthesizer
2  *
3  * Copyright (C) 2003  Peter Hanappe and others.
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public License
7  * as published by the Free Software Foundation; either version 2 of
8  * the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public
16  * License along with this library; if not, write to the Free
17  * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18  * 02110-1301, USA
19  */
20
21
22 /**
23
24    This header contains a bunch of (mostly) system and machine
25    dependent functions:
26
27    - timers
28    - current time in milliseconds and microseconds
29    - debug logging
30    - profiling
31    - memory locking
32    - checking for floating point exceptions
33
34  */
35
36 #ifndef _FLUID_SYS_H
37 #define _FLUID_SYS_H
38
39 #include <glib.h>
40 #include "fluidsynth_priv.h"
41
42
43 /**
44  * Macro used for safely accessing a message from a GError and using a default
45  * message if it is NULL.
46  * @param err Pointer to a GError to access the message field of.
47  * @return Message string
48  */
49 #define fluid_gerror_message(err)  ((err) ? err->message : "No error details")
50
51
52 void fluid_sys_config(void);
53 void fluid_log_config(void);
54 void fluid_time_config(void);
55
56
57 /* Misc */
58
59 #define fluid_return_val_if_fail  g_return_val_if_fail
60 #define fluid_return_if_fail      g_return_if_fail
61 #define FLUID_INLINE              inline
62 #define FLUID_POINTER_TO_UINT     GPOINTER_TO_UINT
63 #define FLUID_UINT_TO_POINTER     GUINT_TO_POINTER
64 #define FLUID_POINTER_TO_INT      GPOINTER_TO_INT
65 #define FLUID_INT_TO_POINTER      GINT_TO_POINTER
66 #define FLUID_N_ELEMENTS(struct)  (sizeof (struct) / sizeof (struct[0]))
67
68 #define FLUID_IS_BIG_ENDIAN       (G_BYTE_ORDER == G_BIG_ENDIAN)
69
70 /*
71  * Utility functions
72  */
73 char *fluid_strtok (char **str, char *delim);
74
75
76 /**
77
78   Additional debugging system, separate from the log system. This
79   allows to print selected debug messages of a specific subsystem.
80  */
81
82 extern unsigned int fluid_debug_flags;
83
84 #if DEBUG
85
86 enum fluid_debug_level {
87   FLUID_DBG_DRIVER = 1
88 };
89
90 int fluid_debug(int level, char * fmt, ...);
91
92 #else
93 #define fluid_debug
94 #endif
95
96
97 #if defined(__OS2__)
98 #define INCL_DOS
99 #include <os2.h>
100
101 typedef int socklen_t;
102 #endif
103
104 unsigned int fluid_curtime(void);
105 double fluid_utime(void);
106
107
108 /**
109     Timers
110
111  */
112
113 /* if the callback function returns 1 the timer will continue; if it
114    returns 0 it will stop */
115 typedef int (*fluid_timer_callback_t)(void* data, unsigned int msec);
116
117 typedef struct _fluid_timer_t fluid_timer_t;
118
119 fluid_timer_t* new_fluid_timer(int msec, fluid_timer_callback_t callback,
120                                void* data, int new_thread, int auto_destroy,
121                                int high_priority);
122
123 int delete_fluid_timer(fluid_timer_t* timer);
124 int fluid_timer_join(fluid_timer_t* timer);
125 int fluid_timer_stop(fluid_timer_t* timer);
126
127 // Macros to use for pre-processor if statements to test which Glib thread API we have (pre or post 2.32)
128 #define NEW_GLIB_THREAD_API  (GLIB_MAJOR_VERSION > 2 || (GLIB_MAJOR_VERSION == 2 && GLIB_MINOR_VERSION >= 32))
129 #define OLD_GLIB_THREAD_API  (GLIB_MAJOR_VERSION < 2 || (GLIB_MAJOR_VERSION == 2 && GLIB_MINOR_VERSION < 32))
130
131 /* Muteces */
132
133 #if NEW_GLIB_THREAD_API
134
135 /* glib 2.32 and newer */
136
137 /* Regular mutex */
138 typedef GMutex fluid_mutex_t;
139 #define FLUID_MUTEX_INIT          { 0 }
140 #define fluid_mutex_init(_m)      g_mutex_init (&(_m))
141 #define fluid_mutex_destroy(_m)   g_mutex_clear (&(_m))
142 #define fluid_mutex_lock(_m)      g_mutex_lock(&(_m))
143 #define fluid_mutex_unlock(_m)    g_mutex_unlock(&(_m))
144
145 /* Recursive lock capable mutex */
146 typedef GRecMutex fluid_rec_mutex_t;
147 #define fluid_rec_mutex_init(_m)      g_rec_mutex_init(&(_m))
148 #define fluid_rec_mutex_destroy(_m)   g_rec_mutex_clear(&(_m))
149 #define fluid_rec_mutex_lock(_m)      g_rec_mutex_lock(&(_m))
150 #define fluid_rec_mutex_unlock(_m)    g_rec_mutex_unlock(&(_m))
151
152 /* Dynamically allocated mutex suitable for fluid_cond_t use */
153 typedef GMutex    fluid_cond_mutex_t;
154 #define fluid_cond_mutex_lock(m)        g_mutex_lock(m)
155 #define fluid_cond_mutex_unlock(m)      g_mutex_unlock(m)
156
157 static FLUID_INLINE fluid_cond_mutex_t *
158 new_fluid_cond_mutex (void)
159 {
160   GMutex *mutex;
161   mutex = g_new (GMutex, 1);
162   g_mutex_init (mutex);
163   return (mutex);
164 }
165
166 static FLUID_INLINE void
167 delete_fluid_cond_mutex (fluid_cond_mutex_t *m)
168 {
169   g_mutex_clear (m);
170   g_free (m);
171 }
172
173 /* Thread condition signaling */
174 typedef GCond fluid_cond_t;
175 #define fluid_cond_signal(cond)         g_cond_signal(cond)
176 #define fluid_cond_broadcast(cond)      g_cond_broadcast(cond)
177 #define fluid_cond_wait(cond, mutex)    g_cond_wait(cond, mutex)
178
179 static FLUID_INLINE fluid_cond_t *
180 new_fluid_cond (void)
181 {
182   GCond *cond;
183   cond = g_new (GCond, 1);
184   g_cond_init (cond);
185   return (cond);
186 }
187
188 static FLUID_INLINE void
189 delete_fluid_cond (fluid_cond_t *cond)
190 {
191   g_cond_clear (cond);
192   g_free (cond);
193 }
194
195 /* Thread private data */
196
197 typedef GPrivate fluid_private_t;
198 #define fluid_private_init(_priv)                  memset (&_priv, 0, sizeof (_priv))
199 #define fluid_private_free(_priv)
200 #define fluid_private_get(_priv)                   g_private_get(&(_priv))
201 #define fluid_private_set(_priv, _data)            g_private_set(&(_priv), _data)
202
203 #else
204
205 /* glib prior to 2.32 */
206
207 /* Regular mutex */
208 typedef GStaticMutex fluid_mutex_t;
209 #define FLUID_MUTEX_INIT          G_STATIC_MUTEX_INIT
210 #define fluid_mutex_destroy(_m)   g_static_mutex_free(&(_m))
211 #define fluid_mutex_lock(_m)      g_static_mutex_lock(&(_m))
212 #define fluid_mutex_unlock(_m)    g_static_mutex_unlock(&(_m))
213
214 #define fluid_mutex_init(_m)      G_STMT_START { \
215   if (!g_thread_supported ()) g_thread_init (NULL); \
216   g_static_mutex_init (&(_m)); \
217 } G_STMT_END;
218
219 /* Recursive lock capable mutex */
220 typedef GStaticRecMutex fluid_rec_mutex_t;
221 #define fluid_rec_mutex_destroy(_m)   g_static_rec_mutex_free(&(_m))
222 #define fluid_rec_mutex_lock(_m)      g_static_rec_mutex_lock(&(_m))
223 #define fluid_rec_mutex_unlock(_m)    g_static_rec_mutex_unlock(&(_m))
224
225 #define fluid_rec_mutex_init(_m)      G_STMT_START { \
226   if (!g_thread_supported ()) g_thread_init (NULL); \
227   g_static_rec_mutex_init (&(_m)); \
228 } G_STMT_END;
229
230 /* Dynamically allocated mutex suitable for fluid_cond_t use */
231 typedef GMutex    fluid_cond_mutex_t;
232 #define delete_fluid_cond_mutex(m)      g_mutex_free(m)
233 #define fluid_cond_mutex_lock(m)        g_mutex_lock(m)
234 #define fluid_cond_mutex_unlock(m)      g_mutex_unlock(m)
235
236 static FLUID_INLINE fluid_cond_mutex_t *
237 new_fluid_cond_mutex (void)
238 {
239   if (!g_thread_supported ()) g_thread_init (NULL);
240   return g_mutex_new ();
241 }
242
243 /* Thread condition signaling */
244 typedef GCond fluid_cond_t;
245 fluid_cond_t *new_fluid_cond (void);
246 #define delete_fluid_cond(cond)         g_cond_free(cond)
247 #define fluid_cond_signal(cond)         g_cond_signal(cond)
248 #define fluid_cond_broadcast(cond)      g_cond_broadcast(cond)
249 #define fluid_cond_wait(cond, mutex)    g_cond_wait(cond, mutex)
250
251 /* Thread private data */
252 typedef GStaticPrivate fluid_private_t;
253 #define fluid_private_get(_priv)                   g_static_private_get(&(_priv))
254 #define fluid_private_set(_priv, _data)            g_static_private_set(&(_priv), _data, NULL)
255 #define fluid_private_free(_priv)                  g_static_private_free(&(_priv))
256
257 #define fluid_private_init(_priv)                  G_STMT_START { \
258   if (!g_thread_supported ()) g_thread_init (NULL); \
259   g_static_private_init (&(_priv)); \
260 } G_STMT_END;
261
262 #endif
263
264
265 /* Atomic operations */
266
267 #define fluid_atomic_int_inc(_pi) g_atomic_int_inc(_pi)
268 #define fluid_atomic_int_add(_pi, _val) g_atomic_int_add(_pi, _val)
269 #define fluid_atomic_int_get(_pi) g_atomic_int_get(_pi)
270 #define fluid_atomic_int_set(_pi, _val) g_atomic_int_set(_pi, _val)
271 #define fluid_atomic_int_dec_and_test(_pi) g_atomic_int_dec_and_test(_pi)
272 #define fluid_atomic_int_compare_and_exchange(_pi, _old, _new) \
273   g_atomic_int_compare_and_exchange(_pi, _old, _new)
274
275 #if GLIB_MAJOR_VERSION > 2 || (GLIB_MAJOR_VERSION == 2 && GLIB_MINOR_VERSION >= 30)
276 #define fluid_atomic_int_exchange_and_add(_pi, _add) \
277   g_atomic_int_add(_pi, _add)
278 #else
279 #define fluid_atomic_int_exchange_and_add(_pi, _add) \
280   g_atomic_int_exchange_and_add(_pi, _add)
281 #endif
282
283 #define fluid_atomic_pointer_get(_pp)           g_atomic_pointer_get(_pp)
284 #define fluid_atomic_pointer_set(_pp, val)      g_atomic_pointer_set(_pp, val)
285 #define fluid_atomic_pointer_compare_and_exchange(_pp, _old, _new) \
286   g_atomic_pointer_compare_and_exchange(_pp, _old, _new)
287
288 static FLUID_INLINE void
289 fluid_atomic_float_set(volatile float *fptr, float val)
290 {
291   sint32 ival;
292   memcpy (&ival, &val, 4);
293   fluid_atomic_int_set ((volatile int *)fptr, ival);
294 }
295
296 static FLUID_INLINE float
297 fluid_atomic_float_get(volatile float *fptr)
298 {
299   sint32 ival;
300   float fval;
301   ival = fluid_atomic_int_get ((volatile int *)fptr);
302   memcpy (&fval, &ival, 4);
303   return fval;
304 }
305
306
307 /* Threads */
308
309 typedef GThread fluid_thread_t;
310 typedef void (*fluid_thread_func_t)(void* data);
311
312 #define FLUID_THREAD_ID_NULL            NULL                    /* A NULL "ID" value */
313 #define fluid_thread_id_t               GThread *               /* Data type for a thread ID */
314 #define fluid_thread_get_id()           g_thread_self()         /* Get unique "ID" for current thread */
315
316 fluid_thread_t* new_fluid_thread(const char *name, fluid_thread_func_t func, void *data,
317                                  int prio_level, int detach);
318 void delete_fluid_thread(fluid_thread_t* thread);
319 void fluid_thread_self_set_prio (int prio_level);
320 int fluid_thread_join(fluid_thread_t* thread);
321
322 /* Sockets and I/O */
323
324 fluid_istream_t fluid_get_stdin (void);
325 fluid_ostream_t fluid_get_stdout (void);
326 int fluid_istream_readline(fluid_istream_t in, fluid_ostream_t out, char* prompt, char* buf, int len);
327 int fluid_ostream_printf (fluid_ostream_t out, char* format, ...);
328
329 /* The function should return 0 if no error occured, non-zero
330    otherwise. If the function return non-zero, the socket will be
331    closed by the server. */
332 typedef int (*fluid_server_func_t)(void* data, fluid_socket_t client_socket, char* addr);
333
334 fluid_server_socket_t* new_fluid_server_socket(int port, fluid_server_func_t func, void* data);
335 int delete_fluid_server_socket(fluid_server_socket_t* sock);
336 int fluid_server_socket_join(fluid_server_socket_t* sock);
337 void fluid_socket_close(fluid_socket_t sock);
338 fluid_istream_t fluid_socket_get_istream(fluid_socket_t sock);
339 fluid_ostream_t fluid_socket_get_ostream(fluid_socket_t sock);
340
341
342
343 /* Profiling */
344
345
346 /**
347  * Profile numbers. List all the pieces of code you want to profile
348  * here. Be sure to add an entry in the fluid_profile_data table in
349  * fluid_sys.c
350  */
351 enum {
352   FLUID_PROF_WRITE,
353   FLUID_PROF_ONE_BLOCK,
354   FLUID_PROF_ONE_BLOCK_CLEAR,
355   FLUID_PROF_ONE_BLOCK_VOICE,
356   FLUID_PROF_ONE_BLOCK_VOICES,
357   FLUID_PROF_ONE_BLOCK_REVERB,
358   FLUID_PROF_ONE_BLOCK_CHORUS,
359   FLUID_PROF_VOICE_NOTE,
360   FLUID_PROF_VOICE_RELEASE,
361   FLUID_PROF_LAST
362 };
363
364
365 #if WITH_PROFILING
366
367 void fluid_profiling_print(void);
368
369
370 /** Profiling data. Keep track of min/avg/max values to execute a
371     piece of code. */
372 typedef struct _fluid_profile_data_t {
373   int num;
374   char* description;
375   double min, max, total;
376   unsigned int count;
377 } fluid_profile_data_t;
378
379 extern fluid_profile_data_t fluid_profile_data[];
380
381 /** Macro to obtain a time refence used for the profiling */
382 #define fluid_profile_ref() fluid_utime()
383
384 /** Macro to create a variable and assign the current reference time for profiling.
385  * So we don't get unused variable warnings when profiling is disabled. */
386 #define fluid_profile_ref_var(name)     double name = fluid_utime()
387
388 /** Macro to calculate the min/avg/max. Needs a time refence and a
389     profile number. */
390 #define fluid_profile(_num,_ref) { \
391   double _now = fluid_utime(); \
392   double _delta = _now - _ref; \
393   fluid_profile_data[_num].min = _delta < fluid_profile_data[_num].min ? _delta : fluid_profile_data[_num].min; \
394   fluid_profile_data[_num].max = _delta > fluid_profile_data[_num].max ? _delta : fluid_profile_data[_num].max; \
395   fluid_profile_data[_num].total += _delta; \
396   fluid_profile_data[_num].count++; \
397   _ref = _now; \
398 }
399
400
401 #else
402
403 /* No profiling */
404 #define fluid_profiling_print()
405 #define fluid_profile_ref()  0
406 #define fluid_profile_ref_var(name)
407 #define fluid_profile(_num,_ref)
408
409 #endif
410
411
412
413 /**
414
415     Memory locking
416
417     Memory locking is used to avoid swapping of the large block of
418     sample data.
419  */
420
421 #if defined(HAVE_SYS_MMAN_H) && !defined(__OS2__)
422 #define fluid_mlock(_p,_n)      mlock(_p, _n)
423 #define fluid_munlock(_p,_n)    munlock(_p,_n)
424 #else
425 #define fluid_mlock(_p,_n)      0
426 #define fluid_munlock(_p,_n)
427 #endif
428
429
430 /**
431
432     Floating point exceptions
433
434     fluid_check_fpe() checks for "unnormalized numbers" and other
435     exceptions of the floating point processsor.
436 */
437 #ifdef FPE_CHECK
438 #define fluid_check_fpe(expl) fluid_check_fpe_i386(expl)
439 #define fluid_clear_fpe() fluid_clear_fpe_i386()
440 #else
441 #define fluid_check_fpe(expl)
442 #define fluid_clear_fpe()
443 #endif
444
445 unsigned int fluid_check_fpe_i386(char * explanation_in_case_of_fpe);
446 void fluid_clear_fpe_i386(void);
447
448 #endif /* _FLUID_SYS_H */