Mercurial > audio-send
comparison Alc/helpers.c @ 0:f9476ff7637e
initial forking of open-al to create multiple listeners
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Tue, 25 Oct 2011 13:02:31 -0700 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:f9476ff7637e |
---|---|
1 /** | |
2 * OpenAL cross platform audio library | |
3 * Copyright (C) 2011 by authors. | |
4 * This library is free software; you can redistribute it and/or | |
5 * modify it under the terms of the GNU Library General Public | |
6 * License as published by the Free Software Foundation; either | |
7 * version 2 of the License, or (at your option) any later version. | |
8 * | |
9 * This library is distributed in the hope that it will be useful, | |
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
12 * Library General Public License for more details. | |
13 * | |
14 * You should have received a copy of the GNU Library General Public | |
15 * License along with this library; if not, write to the | |
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
17 * Boston, MA 02111-1307, USA. | |
18 * Or go to http://www.gnu.org/copyleft/lgpl.html | |
19 */ | |
20 | |
21 #include "config.h" | |
22 | |
23 #include <stdlib.h> | |
24 #ifdef HAVE_DLFCN_H | |
25 #include <dlfcn.h> | |
26 #endif | |
27 | |
28 #if defined(HAVE_GUIDDEF_H) || defined(HAVE_INITGUID_H) | |
29 #define INITGUID | |
30 #include <windows.h> | |
31 #ifdef HAVE_GUIDDEF_H | |
32 #include <guiddef.h> | |
33 #else | |
34 #include <initguid.h> | |
35 #endif | |
36 | |
37 DEFINE_GUID(KSDATAFORMAT_SUBTYPE_PCM, 0x00000001, 0x0000, 0x0010, 0x80,0x00, 0x00,0xaa,0x00,0x38,0x9b,0x71); | |
38 DEFINE_GUID(KSDATAFORMAT_SUBTYPE_IEEE_FLOAT, 0x00000003, 0x0000, 0x0010, 0x80,0x00, 0x00,0xaa,0x00,0x38,0x9b,0x71); | |
39 | |
40 DEFINE_GUID(IID_IDirectSoundNotify, 0xb0210783, 0x89cd, 0x11d0, 0xaf,0x08, 0x00,0xa0,0xc9,0x25,0xcd,0x16); | |
41 | |
42 DEFINE_GUID(CLSID_MMDeviceEnumerator, 0xbcde0395, 0xe52f, 0x467c, 0x8e,0x3d, 0xc4,0x57,0x92,0x91,0x69,0x2e); | |
43 DEFINE_GUID(IID_IMMDeviceEnumerator, 0xa95664d2, 0x9614, 0x4f35, 0xa7,0x46, 0xde,0x8d,0xb6,0x36,0x17,0xe6); | |
44 DEFINE_GUID(IID_IAudioClient, 0x1cb9ad4c, 0xdbfa, 0x4c32, 0xb1,0x78, 0xc2,0xf5,0x68,0xa7,0x03,0xb2); | |
45 DEFINE_GUID(IID_IAudioRenderClient, 0xf294acfc, 0x3146, 0x4483, 0xa7,0xbf, 0xad,0xdc,0xa7,0xc2,0x60,0xe2); | |
46 | |
47 #endif | |
48 | |
49 #include "alMain.h" | |
50 | |
51 #ifdef _WIN32 | |
52 void pthread_once(pthread_once_t *once, void (*callback)(void)) | |
53 { | |
54 LONG ret; | |
55 while((ret=InterlockedExchange(once, 1)) == 1) | |
56 Sleep(0); | |
57 if(ret == 0) | |
58 callback(); | |
59 InterlockedExchange(once, 2); | |
60 } | |
61 | |
62 void *LoadLib(const char *name) | |
63 { return LoadLibraryA(name); } | |
64 void CloseLib(void *handle) | |
65 { FreeLibrary((HANDLE)handle); } | |
66 void *GetSymbol(void *handle, const char *name) | |
67 { | |
68 void *ret; | |
69 | |
70 ret = (void*)GetProcAddress((HANDLE)handle, name); | |
71 if(ret == NULL) | |
72 ERR("Failed to load %s\n", name); | |
73 return ret; | |
74 } | |
75 | |
76 #else | |
77 | |
78 void InitializeCriticalSection(CRITICAL_SECTION *cs) | |
79 { | |
80 pthread_mutexattr_t attrib; | |
81 int ret; | |
82 | |
83 ret = pthread_mutexattr_init(&attrib); | |
84 assert(ret == 0); | |
85 | |
86 ret = pthread_mutexattr_settype(&attrib, PTHREAD_MUTEX_RECURSIVE); | |
87 #ifdef HAVE_PTHREAD_NP_H | |
88 if(ret != 0) | |
89 ret = pthread_mutexattr_setkind_np(&attrib, PTHREAD_MUTEX_RECURSIVE); | |
90 #endif | |
91 assert(ret == 0); | |
92 ret = pthread_mutex_init(cs, &attrib); | |
93 assert(ret == 0); | |
94 | |
95 pthread_mutexattr_destroy(&attrib); | |
96 } | |
97 void DeleteCriticalSection(CRITICAL_SECTION *cs) | |
98 { | |
99 int ret; | |
100 ret = pthread_mutex_destroy(cs); | |
101 assert(ret == 0); | |
102 } | |
103 void EnterCriticalSection(CRITICAL_SECTION *cs) | |
104 { | |
105 int ret; | |
106 ret = pthread_mutex_lock(cs); | |
107 assert(ret == 0); | |
108 } | |
109 void LeaveCriticalSection(CRITICAL_SECTION *cs) | |
110 { | |
111 int ret; | |
112 ret = pthread_mutex_unlock(cs); | |
113 assert(ret == 0); | |
114 } | |
115 | |
116 /* NOTE: This wrapper isn't quite accurate as it returns an ALuint, as opposed | |
117 * to the expected DWORD. Both are defined as unsigned 32-bit types, however. | |
118 * Additionally, Win32 is supposed to measure the time since Windows started, | |
119 * as opposed to the actual time. */ | |
120 ALuint timeGetTime(void) | |
121 { | |
122 #if _POSIX_TIMERS > 0 | |
123 struct timespec ts; | |
124 int ret = -1; | |
125 | |
126 #if defined(_POSIX_MONOTONIC_CLOCK) && (_POSIX_MONOTONIC_CLOCK >= 0) | |
127 #if _POSIX_MONOTONIC_CLOCK == 0 | |
128 static int hasmono = 0; | |
129 if(hasmono > 0 || (hasmono == 0 && | |
130 (hasmono=sysconf(_SC_MONOTONIC_CLOCK)) > 0)) | |
131 #endif | |
132 ret = clock_gettime(CLOCK_MONOTONIC, &ts); | |
133 #endif | |
134 if(ret != 0) | |
135 ret = clock_gettime(CLOCK_REALTIME, &ts); | |
136 assert(ret == 0); | |
137 | |
138 return ts.tv_nsec/1000000 + ts.tv_sec*1000; | |
139 #else | |
140 struct timeval tv; | |
141 int ret; | |
142 | |
143 ret = gettimeofday(&tv, NULL); | |
144 assert(ret == 0); | |
145 | |
146 return tv.tv_usec/1000 + tv.tv_sec*1000; | |
147 #endif | |
148 } | |
149 | |
150 #ifdef HAVE_DLFCN_H | |
151 | |
152 void *LoadLib(const char *name) | |
153 { | |
154 const char *err; | |
155 void *handle; | |
156 | |
157 dlerror(); | |
158 handle = dlopen(name, RTLD_NOW); | |
159 if((err=dlerror()) != NULL) | |
160 handle = NULL; | |
161 return handle; | |
162 } | |
163 void CloseLib(void *handle) | |
164 { dlclose(handle); } | |
165 void *GetSymbol(void *handle, const char *name) | |
166 { | |
167 const char *err; | |
168 void *sym; | |
169 | |
170 dlerror(); | |
171 sym = dlsym(handle, name); | |
172 if((err=dlerror()) != NULL) | |
173 { | |
174 ERR("Failed to load %s: %s\n", name, err); | |
175 sym = NULL; | |
176 } | |
177 return sym; | |
178 } | |
179 | |
180 #endif | |
181 #endif | |
182 | |
183 | |
184 void al_print(const char *fname, unsigned int line, const char *fmt, ...) | |
185 { | |
186 const char *fn; | |
187 char str[256]; | |
188 int i; | |
189 | |
190 fn = strrchr(fname, '/'); | |
191 if(!fn) fn = strrchr(fname, '\\'); | |
192 if(!fn) fn = fname; | |
193 else fn += 1; | |
194 | |
195 i = snprintf(str, sizeof(str), "AL lib: %s:%d: ", fn, line); | |
196 if(i < (int)sizeof(str) && i > 0) | |
197 { | |
198 va_list ap; | |
199 va_start(ap, fmt); | |
200 vsnprintf(str+i, sizeof(str)-i, fmt, ap); | |
201 va_end(ap); | |
202 } | |
203 str[sizeof(str)-1] = 0; | |
204 | |
205 fprintf(LogFile, "%s", str); | |
206 fflush(LogFile); | |
207 } | |
208 | |
209 | |
210 void SetRTPriority(void) | |
211 { | |
212 ALboolean failed; | |
213 | |
214 #ifdef _WIN32 | |
215 if(RTPrioLevel > 0) | |
216 failed = !SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL); | |
217 else | |
218 failed = !SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_NORMAL); | |
219 #elif defined(HAVE_PTHREAD_SETSCHEDPARAM) && !defined(__OpenBSD__) | |
220 struct sched_param param; | |
221 | |
222 if(RTPrioLevel > 0) | |
223 { | |
224 /* Use the minimum real-time priority possible for now (on Linux this | |
225 * should be 1 for SCHED_RR) */ | |
226 param.sched_priority = sched_get_priority_min(SCHED_RR); | |
227 failed = !!pthread_setschedparam(pthread_self(), SCHED_RR, ¶m); | |
228 } | |
229 else | |
230 { | |
231 param.sched_priority = 0; | |
232 failed = !!pthread_setschedparam(pthread_self(), SCHED_OTHER, ¶m); | |
233 } | |
234 #else | |
235 /* Real-time priority not available */ | |
236 failed = (RTPrioLevel>0); | |
237 #endif | |
238 if(failed) | |
239 ERR("Failed to set priority level for thread\n"); | |
240 } | |
241 | |
242 | |
243 void InitUIntMap(UIntMap *map) | |
244 { | |
245 map->array = NULL; | |
246 map->size = 0; | |
247 map->maxsize = 0; | |
248 } | |
249 | |
250 void ResetUIntMap(UIntMap *map) | |
251 { | |
252 free(map->array); | |
253 map->array = NULL; | |
254 map->size = 0; | |
255 map->maxsize = 0; | |
256 } | |
257 | |
258 ALenum InsertUIntMapEntry(UIntMap *map, ALuint key, ALvoid *value) | |
259 { | |
260 ALsizei pos = 0; | |
261 | |
262 if(map->size > 0) | |
263 { | |
264 ALsizei low = 0; | |
265 ALsizei high = map->size - 1; | |
266 while(low < high) | |
267 { | |
268 ALsizei mid = low + (high-low)/2; | |
269 if(map->array[mid].key < key) | |
270 low = mid + 1; | |
271 else | |
272 high = mid; | |
273 } | |
274 if(map->array[low].key < key) | |
275 low++; | |
276 pos = low; | |
277 } | |
278 | |
279 if(pos == map->size || map->array[pos].key != key) | |
280 { | |
281 if(map->size == map->maxsize) | |
282 { | |
283 ALvoid *temp; | |
284 ALsizei newsize; | |
285 | |
286 newsize = (map->maxsize ? (map->maxsize<<1) : 4); | |
287 if(newsize < map->maxsize) | |
288 return AL_OUT_OF_MEMORY; | |
289 | |
290 temp = realloc(map->array, newsize*sizeof(map->array[0])); | |
291 if(!temp) return AL_OUT_OF_MEMORY; | |
292 map->array = temp; | |
293 map->maxsize = newsize; | |
294 } | |
295 | |
296 map->size++; | |
297 if(pos < map->size-1) | |
298 memmove(&map->array[pos+1], &map->array[pos], | |
299 (map->size-1-pos)*sizeof(map->array[0])); | |
300 } | |
301 map->array[pos].key = key; | |
302 map->array[pos].value = value; | |
303 | |
304 return AL_NO_ERROR; | |
305 } | |
306 | |
307 void RemoveUIntMapKey(UIntMap *map, ALuint key) | |
308 { | |
309 if(map->size > 0) | |
310 { | |
311 ALsizei low = 0; | |
312 ALsizei high = map->size - 1; | |
313 while(low < high) | |
314 { | |
315 ALsizei mid = low + (high-low)/2; | |
316 if(map->array[mid].key < key) | |
317 low = mid + 1; | |
318 else | |
319 high = mid; | |
320 } | |
321 if(map->array[low].key == key) | |
322 { | |
323 if(low < map->size-1) | |
324 memmove(&map->array[low], &map->array[low+1], | |
325 (map->size-1-low)*sizeof(map->array[0])); | |
326 map->size--; | |
327 } | |
328 } | |
329 } | |
330 | |
331 ALvoid *LookupUIntMapKey(UIntMap *map, ALuint key) | |
332 { | |
333 if(map->size > 0) | |
334 { | |
335 ALsizei low = 0; | |
336 ALsizei high = map->size - 1; | |
337 while(low < high) | |
338 { | |
339 ALsizei mid = low + (high-low)/2; | |
340 if(map->array[mid].key < key) | |
341 low = mid + 1; | |
342 else | |
343 high = mid; | |
344 } | |
345 if(map->array[low].key == key) | |
346 return map->array[low].value; | |
347 } | |
348 return NULL; | |
349 } |