summaryrefslogtreecommitdiffstats
path: root/flow/gsl/gslcommon.h
blob: 6b74c7774e7bf989012580761f8c8d5f8d90638f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
/* GSL - Generic Sound Layer
 * Copyright (C) 2001 Tim Janik
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General
 * Public License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
 * Boston, MA 02111-1307, USA.
 */
#ifndef __GSL_COMMON_H__
#define __GSL_COMMON_H__

#include <gsl/gsldefs.h>

#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */



/* --- global initialization --- */
typedef struct
{
  const char *value_name;
  double      value;
} GslConfigValue;
typedef struct
{
  guint  n_processors;
  /* # values to pad around wave chunk blocks per channel */
  guint  wave_chunk_padding;
  guint  wave_chunk_big_pad;
  /* data (file) cache block size (aligned to power of 2) */
  guint	 dcache_block_size;
  /* amount of bytes to spare for memory cache */
  guint  dcache_cache_memory;
  guint  midi_kammer_note;
  /* kammer frequency, normally 440Hz, historically 435Hz */
  gfloat kammer_freq;
} GslConfig;
typedef struct _GslMutexTable GslMutexTable;
void			gsl_init	(const GslConfigValue	values[],
					 GslMutexTable	       *mtable);
const GslConfig*	gsl_get_config	(void) G_GNUC_CONST;
#define	GSL_CONFIG(value)	((gsl_get_config () [0]) . value)


/* --- memory allocation --- */
#define gsl_new_struct(type, n)		((type*) gsl_alloc_memblock (sizeof (type) * (n)))
#define gsl_new_struct0(type, n)	((type*) gsl_alloc_memblock0 (sizeof (type) * (n)))
#define gsl_delete_struct(type, mem)	gsl_delete_structs (type, 1, (mem))
#ifndef	__GNUC__
#  define gsl_delete_structs(type, n, mem)	(gsl_free_memblock (sizeof (type) * (n), (mem)))
#else					/* provide typesafety if possible */
#  define gsl_delete_structs(type, n, mem)	do { \
  type *__typed_pointer = (mem); \
  gsl_free_memblock (sizeof (type) * (n), __typed_pointer); \
} while(0)
#endif
#define	GSL_ALIGNED_SIZE(size,align)	((align) > 0 ? _GSL_INTERN_ALIGN (((gsize) (size)), ((gsize) (align))) : (gsize) (size))
#define	_GSL_INTERN_ALIGN(s, a)		(((s + (a - 1)) / a) * a)
#define	GSL_STD_ALIGN			(MAX (MAX (sizeof (float), sizeof (int)), sizeof (void*)))


/* --- ring (circular-list) --- */
struct _GslRing
{
  GslRing  *next;
  GslRing  *prev;
  gpointer  data;
};
GslRing*	gsl_ring_prepend	(GslRing	*head,
					 gpointer	 data);
GslRing*	gsl_ring_prepend_uniq	(GslRing	*head,
					 gpointer	 data);
GslRing*	gsl_ring_append		(GslRing	*head,
					 gpointer	 data);
GslRing*	gsl_ring_insert_sorted	(GslRing	*head,
					 gpointer	 data,
					 GCompareFunc	 func);
GslRing*	gsl_ring_remove_node	(GslRing	*head,
					 GslRing	*node);
GslRing*	gsl_ring_remove		(GslRing	*head,
					 gpointer	 data);
guint		gsl_ring_length		(GslRing	*head);
GslRing*	gsl_ring_concat		(GslRing	*head1,
					 GslRing	*head2);
GslRing*	gsl_ring_find		(GslRing	*head,
					 gconstpointer	 data);
GslRing*	gsl_ring_nth		(GslRing	*head,
					 guint           n);
gpointer	gsl_ring_nth_data	(GslRing	*head,
					 guint           n);
gpointer	gsl_ring_pop_head	(GslRing       **head);
gpointer	gsl_ring_pop_tail	(GslRing       **head);
#define		gsl_ring_push_head	gsl_ring_prepend
#define		gsl_ring_push_tail	gsl_ring_append
void		gsl_ring_free		(GslRing	*head);
#define gsl_ring_walk(head,node)	((node) != (head)->prev ? (node)->next : NULL)


/* --- GslMessage and debugging --- */
typedef enum /*< skip >*/
{
  GSL_MSG_NOTIFY	= 1 << 0,
  GSL_MSG_DATA_CACHE	= 1 << 1,
  GSL_MSG_DATA_HANDLE	= 1 << 2,
  GSL_MSG_LOADER	= 1 << 3,
  GSL_MSG_OSC		= 1 << 4,
  GSL_MSG_ENGINE	= 1 << 5,
  GSL_MSG_JOBS		= 1 << 6,
  GSL_MSG_FJOBS		= 1 << 7,
  GSL_MSG_SCHED		= 1 << 8,
  GSL_MSG_MASTER	= 1 << 9,
  GSL_MSG_SLAVE		= 1 << 10
} GslDebugFlags;
extern const GDebugKey *gsl_debug_keys;
extern const guint      gsl_n_debug_keys;
void		gsl_debug		(GslDebugFlags  reporter,
					 const gchar   *section,
					 const gchar   *format,
					 ...)	G_GNUC_PRINTF (3, 4);
void		gsl_debug_enable	(GslDebugFlags	dbg_flags);
void		gsl_debug_disable	(GslDebugFlags	dbg_flags);
gboolean	gsl_debug_check		(GslDebugFlags	dbg_flags);
void		gsl_message_send	(GslDebugFlags  reporter,
					 const gchar   *section,  /* maybe NULL */
					 GslErrorType	error,	  /* maybe 0 */
					 const gchar   *messagef,
					 ...)	G_GNUC_PRINTF (4, 5);
const gchar*	gsl_strerror		(GslErrorType	error);

/* provide message/debugging macro templates, so custom messages
 * are done as:
 * #define FOO_DEBUG	GSL_DEBUG_FUNCTION (GSL_MSG_LOADER, "FOO")
 * FOO_DEBUG ("some debug message and number: %d", 5);
 */
#define GSL_DEBUG_FUNCTION(reporter, section)	_GSL_DEBUG_MACRO_IMPL((reporter), (section))
#define GSL_MESSAGE_FUNCTION(reporter, section)	_GSL_MESSAGE_MACRO_IMPL((reporter), (section))


/* --- GslThread --- */
typedef void (*GslThreadFunc)		(gpointer	user_data);
GslThread*	gsl_thread_new		(GslThreadFunc	func,
					 gpointer	user_data);
guint		gsl_threads_get_count	(void);
GslThread*	gsl_thread_self		(void);
GslThread*	gsl_thread_main		(void);


/* --- tick stamps --- */
typedef struct {
  guint64 tick_stamp;
  guint64 system_time;
} GslTickStampUpdate;
guint64		   gsl_tick_stamp	(void);
guint64		   gsl_time_system	(void);
GslTickStampUpdate gsl_tick_stamp_last	(void);
#define		   GSL_TICK_STAMP	(_GSL_TICK_STAMP_VAL ())
#define		   GSL_MAX_TICK_STAMP	(G_MAXUINT64)


/* --- thread syncronization --- */
gboolean	gsl_thread_sleep	(glong		 max_msec);
gboolean	gsl_thread_aborted	(void);
void		gsl_thread_queue_abort	(GslThread	*thread);
void		gsl_thread_abort	(GslThread	*thread);
void		gsl_thread_wakeup	(GslThread	*thread);
void		gsl_thread_awake_after	(guint64	 tick_stamp);
void		gsl_thread_awake_before	(guint64	 tick_stamp);
void		gsl_thread_get_pollfd	(GPollFD	*pfd);


/* --- GslMutex --- */
#define	gsl_mutex_init(mutex)		(gsl_mutex_table.mutex_init (mutex))
#define GSL_SPIN_LOCK(mutex)		(gsl_mutex_table.mutex_lock (mutex))
#define GSL_SPIN_UNLOCK(mutex)		(gsl_mutex_table.mutex_unlock (mutex))
#define GSL_SYNC_LOCK(mutex)		(gsl_mutex_table.mutex_lock (mutex))
#define GSL_SYNC_UNLOCK(mutex)		(gsl_mutex_table.mutex_unlock (mutex))
#define	gsl_mutex_trylock(mutex)	(!gsl_mutex_table.mutex_trylock (mutex))
#define	gsl_mutex_destroy(mutex)	(gsl_mutex_table.mutex_destroy (mutex))
#define	gsl_rec_mutex_init(rmutex)	(gsl_mutex_table.rec_mutex_init (rmutex))
#define	gsl_rec_mutex_lock(rmutex)	(gsl_mutex_table.rec_mutex_lock (rmutex))
#define	gsl_rec_mutex_unlock(rmutex)	(gsl_mutex_table.rec_mutex_unlock (rmutex))
#define	gsl_rec_mutex_trylock(rmutex)	(!gsl_mutex_table.rec_mutex_trylock (rmutex))
#define	gsl_rec_mutex_destroy(rmutex)	(gsl_mutex_table.rec_mutex_destroy (rmutex))
#define	gsl_cond_init(cond)		(gsl_mutex_table.cond_init (cond))
#define	gsl_cond_signal(cond)		(gsl_mutex_table.cond_signal (cond))
#define	gsl_cond_broadcast(cond)	(gsl_mutex_table.cond_broadcast (cond))
#define	gsl_cond_wait(cond, mutex)	(gsl_mutex_table.cond_wait ((cond), (mutex)))
#define	gsl_cond_destroy(cond)		(gsl_mutex_table.cond_destroy (cond))
void	gsl_cond_wait_timed		(GslCond  *cond,
					 GslMutex *mutex,
					 glong     max_useconds);
struct _GslMutexTable
{
  void	(*mutex_init)		(GslMutex	*mutex);
  void	(*mutex_lock)		(GslMutex	*mutex);
  int	(*mutex_trylock)	(GslMutex	*mutex); /* 0==has_lock */
  void	(*mutex_unlock)		(GslMutex	*mutex);
  void	(*mutex_destroy)	(GslMutex	*mutex);
  void	(*rec_mutex_init)	(GslRecMutex	*mutex);
  void	(*rec_mutex_lock)	(GslRecMutex	*mutex);
  int	(*rec_mutex_trylock)	(GslRecMutex	*mutex); /* 0==has_lock */
  void	(*rec_mutex_unlock)	(GslRecMutex	*mutex);
  void	(*rec_mutex_destroy)	(GslRecMutex	*mutex);
  void	(*cond_init)		(GslCond	*cond);
  void	(*cond_signal)		(GslCond	*cond);
  void	(*cond_broadcast)	(GslCond	*cond);
  void	(*cond_wait)		(GslCond	*cond,
				 GslMutex	*mutex);
  void	(*cond_wait_timed)	(GslCond	*cond,
				 GslMutex	*mutex,
				 gulong		 abs_secs,
				 gulong		 abs_usecs);
  void	(*cond_destroy)		(GslCond	*cond);
};


/* --- misc --- */
const gchar* gsl_byte_order_to_string   (guint           byte_order);
guint        gsl_byte_order_from_string (const gchar    *string);
GslErrorType gsl_error_from_errno	(gint		 sys_errno,
					 GslErrorType	 fallback);
GslErrorType gsl_check_file		(const gchar	*file_name,
					 const gchar	*mode);


/* --- implementation details --- */
gpointer	gsl_alloc_memblock	(gsize		 size);
gpointer	gsl_alloc_memblock0	(gsize		 size);
void		gsl_free_memblock	(gsize		 size,
					 gpointer	 memblock);
void		gsl_alloc_report	(void);
const guint	gsl_alloc_upper_power2	(const gulong	 number);
void	       _gsl_tick_stamp_inc	(void);
void	       _gsl_tick_stamp_set_leap (guint		 ticks);
void	_gsl_init_signal		(void);
void	_gsl_init_fd_pool		(void);
void	_gsl_init_data_caches		(void);
void	_gsl_init_engine_utils		(void);
void	_gsl_init_loader_gslwave	(void);
void	_gsl_init_loader_wav		(void);
void	_gsl_init_loader_oggvorbis	(void);
void	_gsl_init_loader_mad		(void);
#define		GSL_N_IO_RETRIES	(5)
#define		_GSL_TICK_STAMP_VAL()	(gsl_externvar_tick_stamp + 0)
extern volatile guint64	gsl_externvar_tick_stamp;
extern GslMutexTable gsl_mutex_table;

/* we need to provide a REPORTER and SECTION string for the debugging
 * and message generation functions. for GCC, we also want to make use
 * of printf style format checking with G_GNUC_PRINTF(). for the non GCC
 * case, we push REPORTER and SECTION as thread specific data before
 * invoking the debugging/message generation function. for the GCC case
 * we use GNUC varargs. (using ISO varargs wouldn't provide any benefit,
 * for one, ISO vararg support is broken with gcc-2.95 and ansi/c++, and
 * we only need the macro magic for GCC in the first place to make use
 * of G_GNUC_PRINTF()).
 */
#if     __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ > 4)
#define _GSL_DEBUG_MACRO_IMPL(reporter, section)	gsl_debug ((reporter), (section), _GSL_DEBUG_GCCTAIL
#define _GSL_DEBUG_GCCTAIL(GCCARGS...)			GCCARGS )
#define _GSL_MESSAGE_MACRO_IMPL(reporter, section)	gsl_message_send ((reporter), (section), _GSL_MESSGAE_GCCTAIL
#define _GSL_MESSGAE_GCCTAIL(GCCARGS...)		GCCARGS )
#else   /* non GCC, push data and invoke function */
#define _GSL_DEBUG_MACRO_IMPL(reporter, section)	(gsl_auxlog_push ((reporter), (section)), gsl_auxlog_debug)
#define _GSL_MESSAGE_MACRO_IMPL(reporter, section)	(gsl_auxlog_push ((reporter), (section)), gsl_auxlog_message)
#endif
/* non-GCC message helpers */
void		gsl_auxlog_push		(GslDebugFlags   reporter,
					 const gchar	*section);
void		gsl_auxlog_debug	(const gchar	*format,
					 ...);
void		gsl_auxlog_message	(GslErrorType	 error,
					 const gchar	*format,
					 ...);


#ifdef __cplusplus
}
#endif /* __cplusplus */

#endif /* __GSL_COMMON_H__ */