diff options
Diffstat (limited to 'libs/fluidsynth/src/fluid_sys.h')
-rw-r--r-- | libs/fluidsynth/src/fluid_sys.h | 448 |
1 files changed, 448 insertions, 0 deletions
diff --git a/libs/fluidsynth/src/fluid_sys.h b/libs/fluidsynth/src/fluid_sys.h new file mode 100644 index 0000000000..4953515692 --- /dev/null +++ b/libs/fluidsynth/src/fluid_sys.h @@ -0,0 +1,448 @@ +/* FluidSynth - A Software Synthesizer + * + * Copyright (C) 2003 Peter Hanappe and others. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public License + * as published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA + */ + + +/** + + This header contains a bunch of (mostly) system and machine + dependent functions: + + - timers + - current time in milliseconds and microseconds + - debug logging + - profiling + - memory locking + - checking for floating point exceptions + + */ + +#ifndef _FLUID_SYS_H +#define _FLUID_SYS_H + +#include <glib.h> +#include "fluidsynth_priv.h" + + +/** + * Macro used for safely accessing a message from a GError and using a default + * message if it is NULL. + * @param err Pointer to a GError to access the message field of. + * @return Message string + */ +#define fluid_gerror_message(err) ((err) ? err->message : "No error details") + + +void fluid_sys_config(void); +void fluid_log_config(void); +void fluid_time_config(void); + + +/* Misc */ + +#define fluid_return_val_if_fail g_return_val_if_fail +#define fluid_return_if_fail g_return_if_fail +#define FLUID_INLINE inline +#define FLUID_POINTER_TO_UINT GPOINTER_TO_UINT +#define FLUID_UINT_TO_POINTER GUINT_TO_POINTER +#define FLUID_POINTER_TO_INT GPOINTER_TO_INT +#define FLUID_INT_TO_POINTER GINT_TO_POINTER +#define FLUID_N_ELEMENTS(struct) (sizeof (struct) / sizeof (struct[0])) + +#define FLUID_IS_BIG_ENDIAN (G_BYTE_ORDER == G_BIG_ENDIAN) + +/* + * Utility functions + */ +char *fluid_strtok (char **str, char *delim); + + +/** + + Additional debugging system, separate from the log system. This + allows to print selected debug messages of a specific subsystem. + */ + +extern unsigned int fluid_debug_flags; + +#if DEBUG + +enum fluid_debug_level { + FLUID_DBG_DRIVER = 1 +}; + +int fluid_debug(int level, char * fmt, ...); + +#else +#define fluid_debug +#endif + + +#if defined(__OS2__) +#define INCL_DOS +#include <os2.h> + +typedef int socklen_t; +#endif + +unsigned int fluid_curtime(void); +double fluid_utime(void); + + +/** + Timers + + */ + +/* if the callback function returns 1 the timer will continue; if it + returns 0 it will stop */ +typedef int (*fluid_timer_callback_t)(void* data, unsigned int msec); + +typedef struct _fluid_timer_t fluid_timer_t; + +fluid_timer_t* new_fluid_timer(int msec, fluid_timer_callback_t callback, + void* data, int new_thread, int auto_destroy, + int high_priority); + +int delete_fluid_timer(fluid_timer_t* timer); +int fluid_timer_join(fluid_timer_t* timer); +int fluid_timer_stop(fluid_timer_t* timer); + +// Macros to use for pre-processor if statements to test which Glib thread API we have (pre or post 2.32) +#define NEW_GLIB_THREAD_API (GLIB_MAJOR_VERSION > 2 || (GLIB_MAJOR_VERSION == 2 && GLIB_MINOR_VERSION >= 32)) +#define OLD_GLIB_THREAD_API (GLIB_MAJOR_VERSION < 2 || (GLIB_MAJOR_VERSION == 2 && GLIB_MINOR_VERSION < 32)) + +/* Muteces */ + +#if NEW_GLIB_THREAD_API + +/* glib 2.32 and newer */ + +/* Regular mutex */ +typedef GMutex fluid_mutex_t; +#define FLUID_MUTEX_INIT { 0 } +#define fluid_mutex_init(_m) g_mutex_init (&(_m)) +#define fluid_mutex_destroy(_m) g_mutex_clear (&(_m)) +#define fluid_mutex_lock(_m) g_mutex_lock(&(_m)) +#define fluid_mutex_unlock(_m) g_mutex_unlock(&(_m)) + +/* Recursive lock capable mutex */ +typedef GRecMutex fluid_rec_mutex_t; +#define fluid_rec_mutex_init(_m) g_rec_mutex_init(&(_m)) +#define fluid_rec_mutex_destroy(_m) g_rec_mutex_clear(&(_m)) +#define fluid_rec_mutex_lock(_m) g_rec_mutex_lock(&(_m)) +#define fluid_rec_mutex_unlock(_m) g_rec_mutex_unlock(&(_m)) + +/* Dynamically allocated mutex suitable for fluid_cond_t use */ +typedef GMutex fluid_cond_mutex_t; +#define fluid_cond_mutex_lock(m) g_mutex_lock(m) +#define fluid_cond_mutex_unlock(m) g_mutex_unlock(m) + +static FLUID_INLINE fluid_cond_mutex_t * +new_fluid_cond_mutex (void) +{ + GMutex *mutex; + mutex = g_new (GMutex, 1); + g_mutex_init (mutex); + return (mutex); +} + +static FLUID_INLINE void +delete_fluid_cond_mutex (fluid_cond_mutex_t *m) +{ + g_mutex_clear (m); + g_free (m); +} + +/* Thread condition signaling */ +typedef GCond fluid_cond_t; +#define fluid_cond_signal(cond) g_cond_signal(cond) +#define fluid_cond_broadcast(cond) g_cond_broadcast(cond) +#define fluid_cond_wait(cond, mutex) g_cond_wait(cond, mutex) + +static FLUID_INLINE fluid_cond_t * +new_fluid_cond (void) +{ + GCond *cond; + cond = g_new (GCond, 1); + g_cond_init (cond); + return (cond); +} + +static FLUID_INLINE void +delete_fluid_cond (fluid_cond_t *cond) +{ + g_cond_clear (cond); + g_free (cond); +} + +/* Thread private data */ + +typedef GPrivate fluid_private_t; +#define fluid_private_init(_priv) memset (&_priv, 0, sizeof (_priv)) +#define fluid_private_free(_priv) +#define fluid_private_get(_priv) g_private_get(&(_priv)) +#define fluid_private_set(_priv, _data) g_private_set(&(_priv), _data) + +#else + +/* glib prior to 2.32 */ + +/* Regular mutex */ +typedef GStaticMutex fluid_mutex_t; +#define FLUID_MUTEX_INIT G_STATIC_MUTEX_INIT +#define fluid_mutex_destroy(_m) g_static_mutex_free(&(_m)) +#define fluid_mutex_lock(_m) g_static_mutex_lock(&(_m)) +#define fluid_mutex_unlock(_m) g_static_mutex_unlock(&(_m)) + +#define fluid_mutex_init(_m) G_STMT_START { \ + if (!g_thread_supported ()) g_thread_init (NULL); \ + g_static_mutex_init (&(_m)); \ +} G_STMT_END; + +/* Recursive lock capable mutex */ +typedef GStaticRecMutex fluid_rec_mutex_t; +#define fluid_rec_mutex_destroy(_m) g_static_rec_mutex_free(&(_m)) +#define fluid_rec_mutex_lock(_m) g_static_rec_mutex_lock(&(_m)) +#define fluid_rec_mutex_unlock(_m) g_static_rec_mutex_unlock(&(_m)) + +#define fluid_rec_mutex_init(_m) G_STMT_START { \ + if (!g_thread_supported ()) g_thread_init (NULL); \ + g_static_rec_mutex_init (&(_m)); \ +} G_STMT_END; + +/* Dynamically allocated mutex suitable for fluid_cond_t use */ +typedef GMutex fluid_cond_mutex_t; +#define delete_fluid_cond_mutex(m) g_mutex_free(m) +#define fluid_cond_mutex_lock(m) g_mutex_lock(m) +#define fluid_cond_mutex_unlock(m) g_mutex_unlock(m) + +static FLUID_INLINE fluid_cond_mutex_t * +new_fluid_cond_mutex (void) +{ + if (!g_thread_supported ()) g_thread_init (NULL); + return g_mutex_new (); +} + +/* Thread condition signaling */ +typedef GCond fluid_cond_t; +fluid_cond_t *new_fluid_cond (void); +#define delete_fluid_cond(cond) g_cond_free(cond) +#define fluid_cond_signal(cond) g_cond_signal(cond) +#define fluid_cond_broadcast(cond) g_cond_broadcast(cond) +#define fluid_cond_wait(cond, mutex) g_cond_wait(cond, mutex) + +/* Thread private data */ +typedef GStaticPrivate fluid_private_t; +#define fluid_private_get(_priv) g_static_private_get(&(_priv)) +#define fluid_private_set(_priv, _data) g_static_private_set(&(_priv), _data, NULL) +#define fluid_private_free(_priv) g_static_private_free(&(_priv)) + +#define fluid_private_init(_priv) G_STMT_START { \ + if (!g_thread_supported ()) g_thread_init (NULL); \ + g_static_private_init (&(_priv)); \ +} G_STMT_END; + +#endif + + +/* Atomic operations */ + +#define fluid_atomic_int_inc(_pi) g_atomic_int_inc(_pi) +#define fluid_atomic_int_add(_pi, _val) g_atomic_int_add(_pi, _val) +#define fluid_atomic_int_get(_pi) g_atomic_int_get(_pi) +#define fluid_atomic_int_set(_pi, _val) g_atomic_int_set(_pi, _val) +#define fluid_atomic_int_dec_and_test(_pi) g_atomic_int_dec_and_test(_pi) +#define fluid_atomic_int_compare_and_exchange(_pi, _old, _new) \ + g_atomic_int_compare_and_exchange(_pi, _old, _new) + +#if GLIB_MAJOR_VERSION > 2 || (GLIB_MAJOR_VERSION == 2 && GLIB_MINOR_VERSION >= 30) +#define fluid_atomic_int_exchange_and_add(_pi, _add) \ + g_atomic_int_add(_pi, _add) +#else +#define fluid_atomic_int_exchange_and_add(_pi, _add) \ + g_atomic_int_exchange_and_add(_pi, _add) +#endif + +#define fluid_atomic_pointer_get(_pp) g_atomic_pointer_get(_pp) +#define fluid_atomic_pointer_set(_pp, val) g_atomic_pointer_set(_pp, val) +#define fluid_atomic_pointer_compare_and_exchange(_pp, _old, _new) \ + g_atomic_pointer_compare_and_exchange(_pp, _old, _new) + +static FLUID_INLINE void +fluid_atomic_float_set(volatile float *fptr, float val) +{ + sint32 ival; + memcpy (&ival, &val, 4); + fluid_atomic_int_set ((volatile int *)fptr, ival); +} + +static FLUID_INLINE float +fluid_atomic_float_get(volatile float *fptr) +{ + sint32 ival; + float fval; + ival = fluid_atomic_int_get ((volatile int *)fptr); + memcpy (&fval, &ival, 4); + return fval; +} + + +/* Threads */ + +typedef GThread fluid_thread_t; +typedef void (*fluid_thread_func_t)(void* data); + +#define FLUID_THREAD_ID_NULL NULL /* A NULL "ID" value */ +#define fluid_thread_id_t GThread * /* Data type for a thread ID */ +#define fluid_thread_get_id() g_thread_self() /* Get unique "ID" for current thread */ + +fluid_thread_t* new_fluid_thread(const char *name, fluid_thread_func_t func, void *data, + int prio_level, int detach); +void delete_fluid_thread(fluid_thread_t* thread); +void fluid_thread_self_set_prio (int prio_level); +int fluid_thread_join(fluid_thread_t* thread); + +/* Sockets and I/O */ + +fluid_istream_t fluid_get_stdin (void); +fluid_ostream_t fluid_get_stdout (void); +int fluid_istream_readline(fluid_istream_t in, fluid_ostream_t out, char* prompt, char* buf, int len); +int fluid_ostream_printf (fluid_ostream_t out, char* format, ...); + +/* The function should return 0 if no error occured, non-zero + otherwise. If the function return non-zero, the socket will be + closed by the server. */ +typedef int (*fluid_server_func_t)(void* data, fluid_socket_t client_socket, char* addr); + +fluid_server_socket_t* new_fluid_server_socket(int port, fluid_server_func_t func, void* data); +int delete_fluid_server_socket(fluid_server_socket_t* sock); +int fluid_server_socket_join(fluid_server_socket_t* sock); +void fluid_socket_close(fluid_socket_t sock); +fluid_istream_t fluid_socket_get_istream(fluid_socket_t sock); +fluid_ostream_t fluid_socket_get_ostream(fluid_socket_t sock); + + + +/* Profiling */ + + +/** + * Profile numbers. List all the pieces of code you want to profile + * here. Be sure to add an entry in the fluid_profile_data table in + * fluid_sys.c + */ +enum { + FLUID_PROF_WRITE, + FLUID_PROF_ONE_BLOCK, + FLUID_PROF_ONE_BLOCK_CLEAR, + FLUID_PROF_ONE_BLOCK_VOICE, + FLUID_PROF_ONE_BLOCK_VOICES, + FLUID_PROF_ONE_BLOCK_REVERB, + FLUID_PROF_ONE_BLOCK_CHORUS, + FLUID_PROF_VOICE_NOTE, + FLUID_PROF_VOICE_RELEASE, + FLUID_PROF_LAST +}; + + +#if WITH_PROFILING + +void fluid_profiling_print(void); + + +/** Profiling data. Keep track of min/avg/max values to execute a + piece of code. */ +typedef struct _fluid_profile_data_t { + int num; + char* description; + double min, max, total; + unsigned int count; +} fluid_profile_data_t; + +extern fluid_profile_data_t fluid_profile_data[]; + +/** Macro to obtain a time refence used for the profiling */ +#define fluid_profile_ref() fluid_utime() + +/** Macro to create a variable and assign the current reference time for profiling. + * So we don't get unused variable warnings when profiling is disabled. */ +#define fluid_profile_ref_var(name) double name = fluid_utime() + +/** Macro to calculate the min/avg/max. Needs a time refence and a + profile number. */ +#define fluid_profile(_num,_ref) { \ + double _now = fluid_utime(); \ + double _delta = _now - _ref; \ + fluid_profile_data[_num].min = _delta < fluid_profile_data[_num].min ? _delta : fluid_profile_data[_num].min; \ + fluid_profile_data[_num].max = _delta > fluid_profile_data[_num].max ? _delta : fluid_profile_data[_num].max; \ + fluid_profile_data[_num].total += _delta; \ + fluid_profile_data[_num].count++; \ + _ref = _now; \ +} + + +#else + +/* No profiling */ +#define fluid_profiling_print() +#define fluid_profile_ref() 0 +#define fluid_profile_ref_var(name) +#define fluid_profile(_num,_ref) + +#endif + + + +/** + + Memory locking + + Memory locking is used to avoid swapping of the large block of + sample data. + */ + +#if defined(HAVE_SYS_MMAN_H) && !defined(__OS2__) +#define fluid_mlock(_p,_n) mlock(_p, _n) +#define fluid_munlock(_p,_n) munlock(_p,_n) +#else +#define fluid_mlock(_p,_n) 0 +#define fluid_munlock(_p,_n) +#endif + + +/** + + Floating point exceptions + + fluid_check_fpe() checks for "unnormalized numbers" and other + exceptions of the floating point processsor. +*/ +#ifdef FPE_CHECK +#define fluid_check_fpe(expl) fluid_check_fpe_i386(expl) +#define fluid_clear_fpe() fluid_clear_fpe_i386() +#else +#define fluid_check_fpe(expl) +#define fluid_clear_fpe() +#endif + +unsigned int fluid_check_fpe_i386(char * explanation_in_case_of_fpe); +void fluid_clear_fpe_i386(void); + +#endif /* _FLUID_SYS_H */ |