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