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 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18 * 02111-1307, 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 "fluidsynth_priv.h"
40
41
42void fluid_sys_config(void);
43void fluid_log_config(void);
44void fluid_time_config(void);
45
46
47/*
48 * Utility functions
49 */
50char *fluid_strtok (char **str, char *delim);
51
52
53/**
54
55  Additional debugging system, separate from the log system. This
56  allows to print selected debug messages of a specific subsystem.
57
58 */
59
60extern unsigned int fluid_debug_flags;
61
62#if DEBUG
63
64enum fluid_debug_level {
65  FLUID_DBG_DRIVER = 1
66};
67
68int fluid_debug(int level, char * fmt, ...);
69
70#else
71#define fluid_debug
72#endif
73
74
75/** fluid_curtime() returns the current time in milliseconds. This time
76    should only be used in relative time measurements.  */
77
78/** fluid_utime() returns the time in micro seconds. this time should
79    only be used to measure duration (relative times). */
80
81#if defined(WIN32)
82#define fluid_curtime()   GetTickCount()
83
84double fluid_utime(void);
85
86#elif defined(MACOS9)
87#include <OSUtils.h>
88#include <Timer.h>
89
90unsigned int fluid_curtime();
91#define fluid_utime()  0.0
92
93#elif defined(__OS2__)
94#define INCL_DOS
95#include <os2.h>
96
97typedef int socklen_t;
98
99unsigned int fluid_curtime(void);
100double fluid_utime(void);
101
102#elif (defined(__BEOS__) || defined(__HAIKU__))
103
104#include <OS.h>
105unsigned int fluid_curtime(void);
106double fluid_utime(void);
107
108#else
109
110unsigned int fluid_curtime(void);
111double fluid_utime(void);
112
113#endif
114
115
116
117/**
118    Timers
119
120 */
121
122/* if the callback function returns 1 the timer will continue; if it
123   returns 0 it will stop */
124typedef int (*fluid_timer_callback_t)(void* data, unsigned int msec);
125
126typedef struct _fluid_timer_t fluid_timer_t;
127
128fluid_timer_t* new_fluid_timer(int msec, fluid_timer_callback_t callback,
129					    void* data, int new_thread, int auto_destroy);
130
131int delete_fluid_timer(fluid_timer_t* timer);
132int fluid_timer_join(fluid_timer_t* timer);
133int fluid_timer_stop(fluid_timer_t* timer);
134
135/**
136
137    Muteces
138
139*/
140
141#if defined(MACOS9)
142typedef int fluid_mutex_t;
143#define fluid_mutex_init(_m)      { (_m) = 0; }
144#define fluid_mutex_destroy(_m)
145#define fluid_mutex_lock(_m)
146#define fluid_mutex_unlock(_m)
147
148#elif defined(WIN32)
149typedef HANDLE fluid_mutex_t;
150#define fluid_mutex_init(_m)      { (_m) = CreateMutex(NULL, 0, NULL); }
151#define fluid_mutex_destroy(_m)   if (_m) { CloseHandle(_m); }
152#define fluid_mutex_lock(_m)      WaitForSingleObject(_m, INFINITE)
153#define fluid_mutex_unlock(_m)    ReleaseMutex(_m)
154
155#elif defined(__OS2__)
156typedef HMTX fluid_mutex_t;
157#define fluid_mutex_init(_m)      { (_m) = 0; DosCreateMutexSem( NULL, &(_m), 0, FALSE ); }
158#define fluid_mutex_destroy(_m)   if (_m) { DosCloseMutexSem(_m); }
159#define fluid_mutex_lock(_m)      DosRequestMutexSem(_m, -1L)
160#define fluid_mutex_unlock(_m)    DosReleaseMutexSem(_m)
161
162#else
163typedef pthread_mutex_t fluid_mutex_t;
164#define fluid_mutex_init(_m)      pthread_mutex_init(&(_m), NULL)
165#define fluid_mutex_destroy(_m)   pthread_mutex_destroy(&(_m))
166#define fluid_mutex_lock(_m)      pthread_mutex_lock(&(_m))
167#define fluid_mutex_unlock(_m)    pthread_mutex_unlock(&(_m))
168#endif
169
170
171/**
172     Threads
173
174*/
175
176typedef struct _fluid_thread_t fluid_thread_t;
177typedef void (*fluid_thread_func_t)(void* data);
178
179/** When detached, 'join' does not work and the thread destroys itself
180    when finished. */
181fluid_thread_t* new_fluid_thread(fluid_thread_func_t func, void* data, int detach);
182int delete_fluid_thread(fluid_thread_t* thread);
183int fluid_thread_join(fluid_thread_t* thread);
184
185
186/**
187     Sockets
188
189*/
190
191
192/** The function should return 0 if no error occured, non-zero
193    otherwise. If the function return non-zero, the socket will be
194    closed by the server. */
195typedef int (*fluid_server_func_t)(void* data, fluid_socket_t client_socket, char* addr);
196
197
198fluid_server_socket_t* new_fluid_server_socket(int port, fluid_server_func_t func, void* data);
199int delete_fluid_server_socket(fluid_server_socket_t* sock);
200int fluid_server_socket_join(fluid_server_socket_t* sock);
201
202
203/** Create a new client socket. */
204fluid_socket_t new_fluid_client_socket(char* host, int port);
205
206/** Delete the client socket. This function should only be called on
207    sockets create with 'new_fluid_client_socket'. */
208void delete_fluid_client_socket(fluid_socket_t sock);
209
210
211void fluid_socket_close(fluid_socket_t sock);
212fluid_istream_t fluid_socket_get_istream(fluid_socket_t sock);
213fluid_ostream_t fluid_socket_get_ostream(fluid_socket_t sock);
214
215
216
217/**
218
219    Profiling
220 */
221
222
223/**
224    Profile numbers. List all the pieces of code you want to profile
225    here. Be sure to add an entry in the fluid_profile_data table in
226    fluid_sys.c
227*/
228enum {
229  FLUID_PROF_WRITE_S16,
230  FLUID_PROF_ONE_BLOCK,
231  FLUID_PROF_ONE_BLOCK_CLEAR,
232  FLUID_PROF_ONE_BLOCK_VOICE,
233  FLUID_PROF_ONE_BLOCK_VOICES,
234  FLUID_PROF_ONE_BLOCK_REVERB,
235  FLUID_PROF_ONE_BLOCK_CHORUS,
236  FLUID_PROF_VOICE_NOTE,
237  FLUID_PROF_VOICE_RELEASE,
238  FLUID_PROF_LAST
239};
240
241
242#if WITH_PROFILING
243
244void fluid_profiling_print(void);
245
246
247/** Profiling data. Keep track of min/avg/max values to execute a
248    piece of code. */
249typedef struct _fluid_profile_data_t {
250  int num;
251  char* description;
252  double min, max, total;
253  unsigned int count;
254} fluid_profile_data_t;
255
256extern fluid_profile_data_t fluid_profile_data[];
257
258/** Macro to obtain a time refence used for the profiling */
259#define fluid_profile_ref() fluid_utime()
260
261/** Macro to calculate the min/avg/max. Needs a time refence and a
262    profile number. */
263#define fluid_profile(_num,_ref) { \
264  double _now = fluid_utime(); \
265  double _delta = _now - _ref; \
266  fluid_profile_data[_num].min = _delta < fluid_profile_data[_num].min ? _delta : fluid_profile_data[_num].min; \
267  fluid_profile_data[_num].max = _delta > fluid_profile_data[_num].max ? _delta : fluid_profile_data[_num].max; \
268  fluid_profile_data[_num].total += _delta; \
269  fluid_profile_data[_num].count++; \
270  _ref = _now; \
271}
272
273
274#else
275
276/* No profiling */
277#define fluid_profiling_print()
278#define fluid_profile_ref()  0
279#define fluid_profile(_num,_ref)
280
281#endif
282
283
284
285/**
286
287    Memory locking
288
289    Memory locking is used to avoid swapping of the large block of
290    sample data.
291 */
292
293#if defined(HAVE_SYS_MMAN_H) && !defined(__OS2__)
294#define fluid_mlock(_p,_n)      mlock(_p, _n)
295#define fluid_munlock(_p,_n)    munlock(_p,_n)
296#else
297#define fluid_mlock(_p,_n)      0
298#define fluid_munlock(_p,_n)
299#endif
300
301
302/**
303
304    Floating point exceptions
305
306    fluid_check_fpe() checks for "unnormalized numbers" and other
307    exceptions of the floating point processsor.
308*/
309#ifdef FPE_CHECK
310#define fluid_check_fpe(expl) fluid_check_fpe_i386(expl)
311#define fluid_clear_fpe() fluid_clear_fpe_i386()
312#else
313#define fluid_check_fpe(expl)
314#define fluid_clear_fpe()
315#endif
316
317unsigned int fluid_check_fpe_i386(char * explanation_in_case_of_fpe);
318void fluid_clear_fpe_i386(void);
319
320#endif /* _FLUID_SYS_H */
321