1 /*
2 * Allegro audio codec table.
3 */
4
5 #include "allegro5/allegro.h"
6 #include "allegro5/allegro_audio.h"
7 #include "allegro5/internal/aintern.h"
8 #include "allegro5/internal/aintern_audio.h"
9 #include "allegro5/internal/aintern_exitfunc.h"
10 #include "allegro5/internal/aintern_vector.h"
11
12 ALLEGRO_DEBUG_CHANNEL("audio")
13
14
15 #define MAX_EXTENSION_LENGTH (32)
16
17 typedef struct ACODEC_TABLE ACODEC_TABLE;
18 struct ACODEC_TABLE
19 {
20 char ext[MAX_EXTENSION_LENGTH];
21 ALLEGRO_SAMPLE * (*loader)(const char *filename);
22 bool (*saver)(const char *filename, ALLEGRO_SAMPLE *spl);
23 ALLEGRO_AUDIO_STREAM *(*stream_loader)(const char *filename,
24 size_t buffer_count, unsigned int samples);
25
26 ALLEGRO_SAMPLE * (*fs_loader)(ALLEGRO_FILE *fp);
27 bool (*fs_saver)(ALLEGRO_FILE *fp, ALLEGRO_SAMPLE *spl);
28 ALLEGRO_AUDIO_STREAM *(*fs_stream_loader)(ALLEGRO_FILE *fp,
29 size_t buffer_count, unsigned int samples);
30 };
31
32
33 /* globals */
34 static bool acodec_inited = false;
35 static _AL_VECTOR acodec_table = _AL_VECTOR_INITIALIZER(ACODEC_TABLE);
36
37
acodec_shutdown(void)38 static void acodec_shutdown(void)
39 {
40 if (acodec_inited) {
41 _al_vector_free(&acodec_table);
42 acodec_inited = false;
43 }
44 }
45
46
find_acodec_table_entry(const char * ext)47 static ACODEC_TABLE *find_acodec_table_entry(const char *ext)
48 {
49 ACODEC_TABLE *ent;
50 unsigned i;
51
52 if (!acodec_inited) {
53 acodec_inited = true;
54 _al_add_exit_func(acodec_shutdown, "acodec_shutdown");
55 }
56
57 for (i = 0; i < _al_vector_size(&acodec_table); i++) {
58 ent = _al_vector_ref(&acodec_table, i);
59 if (0 == _al_stricmp(ent->ext, ext)) {
60 return ent;
61 }
62 }
63
64 return NULL;
65 }
66
67
add_acodec_table_entry(const char * ext)68 static ACODEC_TABLE *add_acodec_table_entry(const char *ext)
69 {
70 ACODEC_TABLE *ent;
71
72 ent = _al_vector_alloc_back(&acodec_table);
73 strcpy(ent->ext, ext);
74 ent->loader = NULL;
75 ent->saver = NULL;
76 ent->stream_loader = NULL;
77
78 ent->fs_loader = NULL;
79 ent->fs_saver = NULL;
80 ent->fs_stream_loader = NULL;
81
82 return ent;
83 }
84
85
86 /* Function: al_register_sample_loader
87 */
al_register_sample_loader(const char * ext,ALLEGRO_SAMPLE * (* loader)(const char * filename))88 bool al_register_sample_loader(const char *ext,
89 ALLEGRO_SAMPLE *(*loader)(const char *filename))
90 {
91 ACODEC_TABLE *ent;
92
93 if (strlen(ext) + 1 >= MAX_EXTENSION_LENGTH) {
94 return false;
95 }
96
97 ent = find_acodec_table_entry(ext);
98 if (!loader) {
99 if (!ent || !ent->loader) {
100 return false; /* Nothing to remove. */
101 }
102 }
103 else if (!ent) {
104 ent = add_acodec_table_entry(ext);
105 }
106
107 ent->loader = loader;
108
109 return true;
110 }
111
112
113 /* Function: al_register_sample_loader_f
114 */
al_register_sample_loader_f(const char * ext,ALLEGRO_SAMPLE * (* loader)(ALLEGRO_FILE * fp))115 bool al_register_sample_loader_f(const char *ext,
116 ALLEGRO_SAMPLE *(*loader)(ALLEGRO_FILE* fp))
117 {
118 ACODEC_TABLE *ent;
119
120 if (strlen(ext) + 1 >= MAX_EXTENSION_LENGTH) {
121 return false;
122 }
123
124 ent = find_acodec_table_entry(ext);
125 if (!loader) {
126 if (!ent || !ent->fs_loader) {
127 return false; /* Nothing to remove. */
128 }
129 }
130 else if (!ent) {
131 ent = add_acodec_table_entry(ext);
132 }
133
134 ent->fs_loader = loader;
135
136 return true;
137 }
138
139
140 /* Function: al_register_sample_saver
141 */
al_register_sample_saver(const char * ext,bool (* saver)(const char * filename,ALLEGRO_SAMPLE * spl))142 bool al_register_sample_saver(const char *ext,
143 bool (*saver)(const char *filename, ALLEGRO_SAMPLE *spl))
144 {
145 ACODEC_TABLE *ent;
146
147 if (strlen(ext) + 1 >= MAX_EXTENSION_LENGTH) {
148 return false;
149 }
150
151 ent = find_acodec_table_entry(ext);
152 if (!saver) {
153 if (!ent || !ent->saver) {
154 return false; /* Nothing to remove. */
155 }
156 }
157 else if (!ent) {
158 ent = add_acodec_table_entry(ext);
159 }
160
161 ent->saver = saver;
162
163 return true;
164 }
165
166
167 /* Function: al_register_sample_saver_f
168 */
al_register_sample_saver_f(const char * ext,bool (* saver)(ALLEGRO_FILE * fp,ALLEGRO_SAMPLE * spl))169 bool al_register_sample_saver_f(const char *ext,
170 bool (*saver)(ALLEGRO_FILE* fp, ALLEGRO_SAMPLE *spl))
171 {
172 ACODEC_TABLE *ent;
173
174 if (strlen(ext) + 1 >= MAX_EXTENSION_LENGTH) {
175 return false;
176 }
177
178 ent = find_acodec_table_entry(ext);
179 if (!saver) {
180 if (!ent || !ent->fs_saver) {
181 return false; /* Nothing to remove. */
182 }
183 }
184 else if (!ent) {
185 ent = add_acodec_table_entry(ext);
186 }
187
188 ent->fs_saver = saver;
189
190 return true;
191 }
192
193
194 /* Function: al_register_audio_stream_loader
195 */
al_register_audio_stream_loader(const char * ext,ALLEGRO_AUDIO_STREAM * (* stream_loader)(const char * filename,size_t buffer_count,unsigned int samples))196 bool al_register_audio_stream_loader(const char *ext,
197 ALLEGRO_AUDIO_STREAM *(*stream_loader)(const char *filename,
198 size_t buffer_count, unsigned int samples))
199 {
200 ACODEC_TABLE *ent;
201
202 if (strlen(ext) + 1 >= MAX_EXTENSION_LENGTH) {
203 return false;
204 }
205
206 ent = find_acodec_table_entry(ext);
207 if (!stream_loader) {
208 if (!ent || !ent->stream_loader) {
209 return false; /* Nothing to remove. */
210 }
211 }
212 else if (!ent) {
213 ent = add_acodec_table_entry(ext);
214 }
215
216 ent->stream_loader = stream_loader;
217
218 return true;
219 }
220
221
222 /* Function: al_register_audio_stream_loader_f
223 */
al_register_audio_stream_loader_f(const char * ext,ALLEGRO_AUDIO_STREAM * (* stream_loader)(ALLEGRO_FILE * fp,size_t buffer_count,unsigned int samples))224 bool al_register_audio_stream_loader_f(const char *ext,
225 ALLEGRO_AUDIO_STREAM *(*stream_loader)(ALLEGRO_FILE* fp,
226 size_t buffer_count, unsigned int samples))
227 {
228 ACODEC_TABLE *ent;
229
230 if (strlen(ext) + 1 >= MAX_EXTENSION_LENGTH) {
231 return false;
232 }
233
234 ent = find_acodec_table_entry(ext);
235 if (!stream_loader) {
236 if (!ent || !ent->fs_stream_loader) {
237 return false; /* Nothing to remove. */
238 }
239 }
240 else if (!ent) {
241 ent = add_acodec_table_entry(ext);
242 }
243
244 ent->fs_stream_loader = stream_loader;
245
246 return true;
247 }
248
249
250 /* Function: al_load_sample
251 */
al_load_sample(const char * filename)252 ALLEGRO_SAMPLE *al_load_sample(const char *filename)
253 {
254 const char *ext;
255 ACODEC_TABLE *ent;
256
257 ASSERT(filename);
258 ext = strrchr(filename, '.');
259 if (ext == NULL) {
260 ALLEGRO_ERROR("Unable to determine extension for %s.\n", filename);
261 return NULL;
262 }
263
264 ent = find_acodec_table_entry(ext);
265 if (ent && ent->loader) {
266 return (ent->loader)(filename);
267 }
268 else {
269 ALLEGRO_ERROR("No handler for audio file extension %s - "
270 "therefore not trying to load %s.\n", ext, filename);
271 }
272
273 return NULL;
274 }
275
276
277 /* Function: al_load_sample_f
278 */
al_load_sample_f(ALLEGRO_FILE * fp,const char * ident)279 ALLEGRO_SAMPLE *al_load_sample_f(ALLEGRO_FILE* fp, const char *ident)
280 {
281 ACODEC_TABLE *ent;
282
283 ASSERT(fp);
284 ASSERT(ident);
285
286 ent = find_acodec_table_entry(ident);
287 if (ent && ent->fs_loader) {
288 return (ent->fs_loader)(fp);
289 }
290 else {
291 ALLEGRO_ERROR("No handler for audio file extension %s.\n", ident);
292 }
293
294 return NULL;
295 }
296
297
298 /* Function: al_load_audio_stream
299 */
al_load_audio_stream(const char * filename,size_t buffer_count,unsigned int samples)300 ALLEGRO_AUDIO_STREAM *al_load_audio_stream(const char *filename,
301 size_t buffer_count, unsigned int samples)
302 {
303 const char *ext;
304 ACODEC_TABLE *ent;
305
306 ASSERT(filename);
307 ext = strrchr(filename, '.');
308 if (ext == NULL) {
309 ALLEGRO_ERROR("Unable to determine extension for %s.\n", filename);
310 return NULL;
311 }
312
313 ent = find_acodec_table_entry(ext);
314 if (ent && ent->stream_loader) {
315 return (ent->stream_loader)(filename, buffer_count, samples);
316 }
317 else {
318 ALLEGRO_ERROR("No handler for audio file extension %s - "
319 "therefore not trying to load %s.\n", ext, filename);
320 }
321
322 return NULL;
323 }
324
325
326 /* Function: al_load_audio_stream_f
327 */
al_load_audio_stream_f(ALLEGRO_FILE * fp,const char * ident,size_t buffer_count,unsigned int samples)328 ALLEGRO_AUDIO_STREAM *al_load_audio_stream_f(ALLEGRO_FILE* fp, const char *ident,
329 size_t buffer_count, unsigned int samples)
330 {
331 ACODEC_TABLE *ent;
332
333 ASSERT(fp);
334 ASSERT(ident);
335
336 ent = find_acodec_table_entry(ident);
337 if (ent && ent->fs_stream_loader) {
338 return (ent->fs_stream_loader)(fp, buffer_count, samples);
339 }
340 else {
341 ALLEGRO_ERROR("No handler for audio file extension %s.\n", ident);
342 }
343
344 return NULL;
345 }
346
347
348 /* Function: al_save_sample
349 */
al_save_sample(const char * filename,ALLEGRO_SAMPLE * spl)350 bool al_save_sample(const char *filename, ALLEGRO_SAMPLE *spl)
351 {
352 const char *ext;
353 ACODEC_TABLE *ent;
354
355 ASSERT(filename);
356 ext = strrchr(filename, '.');
357 if (ext == NULL) {
358 ALLEGRO_ERROR("Unable to determine extension for %s.\n", filename);
359 return false;
360 }
361
362 ent = find_acodec_table_entry(ext);
363 if (ent && ent->saver) {
364 return (ent->saver)(filename, spl);
365 }
366 else {
367 ALLEGRO_ERROR("No handler for audio file extension %s - "
368 "therefore not trying to load %s.\n", ext, filename);
369 }
370
371 return false;
372 }
373
374
375 /* Function: al_save_sample_f
376 */
al_save_sample_f(ALLEGRO_FILE * fp,const char * ident,ALLEGRO_SAMPLE * spl)377 bool al_save_sample_f(ALLEGRO_FILE *fp, const char *ident, ALLEGRO_SAMPLE *spl)
378 {
379 ACODEC_TABLE *ent;
380
381 ASSERT(fp);
382 ASSERT(ident);
383
384 ent = find_acodec_table_entry(ident);
385 if (ent && ent->fs_saver) {
386 return (ent->fs_saver)(fp, spl);
387 }
388 else {
389 ALLEGRO_ERROR("No handler for audio file extension %s.\n", ident);
390 }
391
392 return false;
393 }
394
395
396 /* vim: set sts=3 sw=3 et: */
397