/
music.c
1668 lines (1544 loc) · 40.9 KB
1
/*
2
SDL_mixer: An audio mixer library based on the SDL library
3
Copyright (C) 1997-2017 Sam Lantinga <slouken@libsdl.org>
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
20
21
*/
22
/* $Id$ */
23
24
25
#include <stdlib.h>
#include <string.h>
26
#include <ctype.h>
27
#include <assert.h>
28
29
#include "SDL_endian.h"
#include "SDL_audio.h"
30
#include "SDL_timer.h"
31
32
#include "SDL_mixer.h"
33
#include "mixer.h"
34
35
36
37
38
39
40
#ifdef CMD_MUSIC
#include "music_cmd.h"
#endif
#ifdef WAV_MUSIC
#include "wavestream.h"
#endif
41
42
43
#ifdef MODPLUG_MUSIC
#include "music_modplug.h"
#endif
44
45
#ifdef MOD_MUSIC
#include "music_mod.h"
46
47
#endif
#ifdef MID_MUSIC
48
49
50
# ifdef USE_TIMIDITY_MIDI
# include "timidity.h"
# endif
51
52
53
# ifdef USE_FLUIDSYNTH_MIDI
# include "fluidsynth.h"
# endif
54
55
56
# ifdef USE_NATIVE_MIDI
# include "native_midi.h"
# endif
57
#endif
58
59
60
#ifdef OGG_MUSIC
#include "music_ogg.h"
#endif
61
#ifdef MP3_MUSIC
62
#include "dynamic_mp3.h"
63
64
65
66
#endif
#ifdef MP3_MAD_MUSIC
#include "music_mad.h"
#endif
67
68
69
#ifdef MP3_MPG_MUSIC
#include "music_mpg.h"
#endif
70
71
72
#ifdef FLAC_MUSIC
#include "music_flac.h"
#endif
73
74
#if defined(MP3_MUSIC) || defined(MP3_MAD_MUSIC) || defined(MP3_MPG_MUSIC)
75
76
77
static SDL_AudioSpec used_mixer;
#endif
79
80
int volatile music_active = 1;
static int volatile music_stopped = 0;
81
82
static int music_loops = 0;
static char *music_cmd = NULL;
83
static Mix_Music * volatile music_playing = NULL;
84
static int music_volume = MIX_MAX_VOLUME;
85
86
struct _Mix_Music {
87
88
Mix_MusicType type;
union {
89
#ifdef CMD_MUSIC
90
MusicCMD *cmd;
91
92
#endif
#ifdef WAV_MUSIC
93
WAVStream *wave;
94
#endif
95
#ifdef MODPLUG_MUSIC
96
modplug_data *modplug;
97
#endif
98
#ifdef MOD_MUSIC
99
struct MODULE *module;
100
101
#endif
#ifdef MID_MUSIC
102
#ifdef USE_TIMIDITY_MIDI
103
MidiSong *midi;
104
#endif
105
#ifdef USE_FLUIDSYNTH_MIDI
106
FluidSynthMidiSong *fluidsynthmidi;
107
#endif
108
#ifdef USE_NATIVE_MIDI
109
NativeMidiSong *nativemidi;
110
#endif
111
#endif
112
#ifdef OGG_MUSIC
113
OGG_music *ogg;
114
#endif
115
#ifdef MP3_MUSIC
116
SMPEG *mp3;
117
118
#endif
#ifdef MP3_MAD_MUSIC
119
mad_data *mp3_mad;
120
#endif
121
122
123
#ifdef MP3_MPG_MUSIC
mpg_data *mp3_mpg;
#endif
124
#ifdef FLAC_MUSIC
125
FLAC_music *flac;
126
#endif
127
128
129
130
131
} data;
Mix_Fading fading;
int fade_step;
int fade_steps;
int error;
132
};
133
#ifdef MID_MUSIC
134
#ifdef USE_TIMIDITY_MIDI
135
static int timidity_ok;
136
static int samplesize;
137
#endif
138
139
140
#ifdef USE_FLUIDSYNTH_MIDI
static int fluidsynth_ok;
#endif
141
142
143
#ifdef USE_NATIVE_MIDI
static int native_midi_ok;
#endif
144
#endif
145
146
147
148
/* Used to calculate fading steps */
static int ms_per_step;
149
150
151
152
/* rcg06042009 report available decoders at runtime. */
static const char **music_decoders = NULL;
static int num_decoders = 0;
153
154
155
156
157
/* Semicolon-separated SoundFont paths */
#ifdef MID_MUSIC
char* soundfont_paths = NULL;
#endif
158
int Mix_GetNumMusicDecoders(void)
159
{
160
return(num_decoders);
161
162
163
164
}
const char *Mix_GetMusicDecoder(int index)
{
165
166
167
168
if ((index < 0) || (index >= num_decoders)) {
return NULL;
}
return(music_decoders[index]);
169
170
171
172
}
static void add_music_decoder(const char *decoder)
{
173
void *ptr = SDL_realloc((void *)music_decoders, (num_decoders + 1) * sizeof (const char *));
174
175
176
177
178
if (ptr == NULL) {
return; /* oh well, go on without it. */
}
music_decoders = (const char **) ptr;
music_decoders[num_decoders++] = decoder;
179
180
}
181
/* Local low-level functions prototypes */
182
static void music_internal_initialize_volume(void);
183
184
185
186
187
static void music_internal_volume(int volume);
static int music_internal_play(Mix_Music *music, double position);
static int music_internal_position(double position);
static int music_internal_playing();
static void music_internal_halt(void);
188
189
190
191
192
193
194
/* Support for hooking when the music has finished */
static void (*music_finished_hook)(void) = NULL;
void Mix_HookMusicFinished(void (*music_finished)(void))
{
195
Mix_LockAudio();
196
music_finished_hook = music_finished;
197
Mix_UnlockAudio();
198
199
200
}
201
/* If music isn't playing, halt it if no looping is required, restart it */
202
/* othesrchise. NOP if the music is playing */
203
204
static int music_halt_or_loop (void)
{
205
206
207
208
/* Restart music if it has to loop */
if (!music_internal_playing())
{
209
#ifdef USE_NATIVE_MIDI
210
211
212
213
214
215
216
217
218
219
/* Native MIDI handles looping internally */
if (music_playing->type == MUS_MID && native_midi_ok) {
music_loops = 0;
}
#endif
/* Restart music if it has to loop at a high level */
if (music_loops)
{
Mix_Fading current_fade;
220
221
222
if (music_loops > 0) {
--music_loops;
}
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
current_fade = music_playing->fading;
music_internal_play(music_playing, 0.0);
music_playing->fading = current_fade;
}
else
{
music_internal_halt();
if (music_finished_hook)
music_finished_hook();
return 0;
}
}
return 1;
238
239
240
241
}
242
243
244
/* Mixing function */
void music_mixer(void *udata, Uint8 *stream, int len)
{
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
int left = 0;
if ( music_playing && music_active ) {
/* Handle fading */
if ( music_playing->fading != MIX_NO_FADING ) {
if ( music_playing->fade_step++ < music_playing->fade_steps ) {
int volume;
int fade_step = music_playing->fade_step;
int fade_steps = music_playing->fade_steps;
if ( music_playing->fading == MIX_FADING_OUT ) {
volume = (music_volume * (fade_steps-fade_step)) / fade_steps;
} else { /* Fading in */
volume = (music_volume * fade_step) / fade_steps;
}
music_internal_volume(volume);
} else {
if ( music_playing->fading == MIX_FADING_OUT ) {
music_internal_halt();
if ( music_finished_hook ) {
music_finished_hook();
}
return;
}
music_playing->fading = MIX_NO_FADING;
}
}
music_halt_or_loop();
if (!music_internal_playing())
return;
switch (music_playing->type) {
278
#ifdef CMD_MUSIC
279
280
281
case MUS_CMD:
/* The playing is done externally */
break;
282
283
#endif
#ifdef WAV_MUSIC
284
285
286
case MUS_WAV:
left = WAVStream_PlaySome(stream, len);
break;
287
#endif
288
#ifdef MODPLUG_MUSIC
289
290
291
case MUS_MODPLUG:
left = modplug_playAudio(music_playing->data.modplug, stream, len);
break;
292
#endif
293
#ifdef MOD_MUSIC
294
295
296
case MUS_MOD:
left = MOD_playAudio(music_playing->data.module, stream, len);
break;
297
298
#endif
#ifdef MID_MUSIC
299
case MUS_MID:
300
#ifdef USE_NATIVE_MIDI
301
302
303
304
if ( native_midi_ok ) {
/* Native midi is handled asynchronously */
goto skip;
}
305
#endif
306
#ifdef USE_FLUIDSYNTH_MIDI
307
308
309
310
if ( fluidsynth_ok ) {
fluidsynth_playsome(music_playing->data.fluidsynthmidi, stream, len);
goto skip;
}
311
312
#endif
#ifdef USE_TIMIDITY_MIDI
313
314
315
316
317
if ( timidity_ok ) {
int samples = len / samplesize;
Timidity_PlaySome(stream, samples);
goto skip;
}
318
#endif
319
break;
320
#endif
321
#ifdef OGG_MUSIC
322
323
324
325
case MUS_OGG:
left = OGG_playAudio(music_playing->data.ogg, stream, len);
break;
326
#endif
327
#ifdef FLAC_MUSIC
328
329
330
case MUS_FLAC:
left = FLAC_playAudio(music_playing->data.flac, stream, len);
break;
331
#endif
332
#ifdef MP3_MUSIC
333
334
335
case MUS_MP3:
left = (len - smpeg.SMPEG_playAudio(music_playing->data.mp3, stream, len));
break;
336
337
#endif
#ifdef MP3_MAD_MUSIC
338
339
340
case MUS_MP3_MAD:
left = mad_getSamples(music_playing->data.mp3_mad, stream, len);
break;
341
342
343
344
345
#endif
#ifdef MP3_MPG_MUSIC
case MUS_MP3_MPG:
left = mpg_get_samples(music_playing->data.mp3_mpg, stream, len);
break;
346
#endif
347
348
349
350
351
default:
/* Unknown music type?? */
break;
}
}
352
353
skip:
354
355
356
357
358
359
/* Handle seamless music looping */
if (left > 0 && left < len) {
music_halt_or_loop();
if (music_internal_playing())
music_mixer(udata, stream+(len-left), left);
}
360
361
362
363
364
365
}
/* Initialize the music players with a certain desired audio format */
int open_music(SDL_AudioSpec *mixer)
{
#ifdef WAV_MUSIC
366
367
368
if ( WAVStream_Init(mixer) == 0 ) {
add_music_decoder("WAVE");
}
369
#endif
370
#ifdef MODPLUG_MUSIC
371
372
373
if ( modplug_init(mixer) == 0 ) {
add_music_decoder("MODPLUG");
}
374
#endif
375
#ifdef MOD_MUSIC
376
377
378
if ( MOD_init(mixer) == 0 ) {
add_music_decoder("MIKMOD");
}
379
380
#endif
#ifdef MID_MUSIC
381
#ifdef USE_TIMIDITY_MIDI
382
383
384
385
386
387
388
389
samplesize = mixer->size / mixer->samples;
if ( Timidity_Init(mixer->freq, mixer->format,
mixer->channels, mixer->samples) == 0 ) {
timidity_ok = 1;
add_music_decoder("TIMIDITY");
} else {
timidity_ok = 0;
}
390
#endif
391
#ifdef USE_FLUIDSYNTH_MIDI
392
393
394
395
396
397
if ( fluidsynth_init(mixer) == 0 ) {
fluidsynth_ok = 1;
add_music_decoder("FLUIDSYNTH");
} else {
fluidsynth_ok = 0;
}
398
#endif
399
#ifdef USE_NATIVE_MIDI
400
#ifdef USE_FLUIDSYNTH_MIDI
401
402
native_midi_ok = !fluidsynth_ok;
if ( native_midi_ok )
403
#endif
404
#ifdef USE_TIMIDITY_MIDI
405
406
407
408
409
native_midi_ok = !timidity_ok;
if ( !native_midi_ok ) {
native_midi_ok = (getenv("SDL_NATIVE_MUSIC") != NULL);
}
if ( native_midi_ok )
410
#endif
411
412
413
native_midi_ok = native_midi_detect();
if ( native_midi_ok )
add_music_decoder("NATIVEMIDI");
414
#endif
415
#endif
416
#ifdef OGG_MUSIC
417
418
419
if ( OGG_init(mixer) == 0 ) {
add_music_decoder("OGG");
}
420
#endif
421
#ifdef FLAC_MUSIC
422
423
424
if ( FLAC_init(mixer) == 0 ) {
add_music_decoder("FLAC");
}
425
#endif
426
#if defined(MP3_MUSIC) || defined(MP3_MAD_MUSIC) || defined(MP3_MPG_MUSIC)
427
428
429
/* Keep a copy of the mixer */
used_mixer = *mixer;
add_music_decoder("MP3");
430
#endif
431
432
433
434
music_playing = NULL;
music_stopped = 0;
Mix_VolumeMusic(SDL_MIX_MAXVOLUME);
435
436
437
/* Calculate the number of ms for each callback */
ms_per_step = (int) (((float)mixer->samples * 1000.0) / mixer->freq);
438
439
return(0);
440
441
}
442
443
444
/* Portable case-insensitive string compare function */
int MIX_string_equals(const char *str1, const char *str2)
{
445
446
447
448
449
450
451
452
while ( *str1 && *str2 ) {
if ( toupper((unsigned char)*str1) !=
toupper((unsigned char)*str2) )
break;
++str1;
++str2;
}
return (!*str1 && !*str2);
453
454
}
455
456
static int detect_mp3(Uint8 *magic)
{
457
458
459
460
461
462
463
464
465
466
467
468
469
470
if ( strncmp((char *)magic, "ID3", 3) == 0 ) {
return 1;
}
/* Detection code lifted from SMPEG */
if(((magic[0] & 0xff) != 0xff) || // No sync bits
((magic[1] & 0xf0) != 0xf0) || //
((magic[2] & 0xf0) == 0x00) || // Bitrate is 0
((magic[2] & 0xf0) == 0xf0) || // Bitrate is 15
((magic[2] & 0x0c) == 0x0c) || // Frequency is 3
((magic[1] & 0x06) == 0x00)) { // Layer is 4
return(0);
}
return 1;
471
472
473
474
475
476
477
}
/* MUS_MOD can't be auto-detected. If no other format was detected, MOD is
* assumed and MUS_MOD will be returned, meaning that the format might not
* actually be MOD-based.
*
* Returns MUS_NONE in case of errors. */
478
static Mix_MusicType detect_music_type(SDL_RWops *src)
479
{
480
481
482
Uint8 magic[5];
Uint8 moremagic[9];
483
484
Sint64 start = SDL_RWtell(src);
if (SDL_RWread(src, magic, 1, 4) != 4 || SDL_RWread(src, moremagic, 1, 8) != 8 ) {
485
486
487
Mix_SetError("Couldn't read from RWops");
return MUS_NONE;
}
488
SDL_RWseek(src, start, RW_SEEK_SET);
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
magic[4]='\0';
moremagic[8] = '\0';
/* WAVE files have the magic four bytes "RIFF"
AIFF files have the magic 12 bytes "FORM" XXXX "AIFF" */
if (((strcmp((char *)magic, "RIFF") == 0) && (strcmp((char *)(moremagic+4), "WAVE") == 0)) ||
(strcmp((char *)magic, "FORM") == 0)) {
return MUS_WAV;
}
/* Ogg Vorbis files have the magic four bytes "OggS" */
if (strcmp((char *)magic, "OggS") == 0) {
return MUS_OGG;
}
/* FLAC files have the magic four bytes "fLaC" */
if (strcmp((char *)magic, "fLaC") == 0) {
return MUS_FLAC;
}
/* MIDI files have the magic four bytes "MThd" */
if (strcmp((char *)magic, "MThd") == 0) {
return MUS_MID;
}
if (detect_mp3(magic)) {
return MUS_MP3;
}
/* Assume MOD format.
*
* Apparently there is no way to check if the file is really a MOD,
* or there are too many formats supported by MikMod/ModPlug, or
* MikMod/ModPlug does this check by itself. */
return MUS_MOD;
524
525
}
526
527
528
/* Load a music file */
Mix_Music *Mix_LoadMUS(const char *file)
{
529
SDL_RWops *src;
530
531
532
Mix_Music *music;
Mix_MusicType type;
char *ext = strrchr(file, '.');
533
534
#ifdef CMD_MUSIC
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
if ( music_cmd ) {
/* Allocate memory for the music structure */
music = (Mix_Music *)SDL_malloc(sizeof(Mix_Music));
if ( music == NULL ) {
Mix_SetError("Out of memory");
return(NULL);
}
music->error = 0;
music->type = MUS_CMD;
music->data.cmd = MusicCMD_LoadSong(music_cmd, file);
if ( music->data.cmd == NULL ) {
SDL_free(music);
music = NULL;
}
return music;
}
#endif
553
554
src = SDL_RWFromFile(file, "rb");
if ( src == NULL ) {
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
Mix_SetError("Couldn't open '%s'", file);
return NULL;
}
/* Use the extension as a first guess on the file type */
type = MUS_NONE;
ext = strrchr(file, '.');
/* No need to guard these with #ifdef *_MUSIC stuff,
* since we simply call Mix_LoadMUSType_RW() later */
if ( ext ) {
++ext; /* skip the dot in the extension */
if ( MIX_string_equals(ext, "WAV") ) {
type = MUS_WAV;
} else if ( MIX_string_equals(ext, "MID") ||
MIX_string_equals(ext, "MIDI") ||
MIX_string_equals(ext, "KAR") ) {
type = MUS_MID;
} else if ( MIX_string_equals(ext, "OGG") ) {
type = MUS_OGG;
} else if ( MIX_string_equals(ext, "FLAC") ) {
type = MUS_FLAC;
} else if ( MIX_string_equals(ext, "MPG") ||
MIX_string_equals(ext, "MPEG") ||
MIX_string_equals(ext, "MP3") ||
MIX_string_equals(ext, "MAD") ) {
type = MUS_MP3;
}
}
if ( type == MUS_NONE ) {
584
type = detect_music_type(src);
585
586
587
588
}
/* We need to know if a specific error occurs; if not, we'll set a
* generic one, so we clear the current one. */
589
SDL_ClearError();
590
music = Mix_LoadMUSType_RW(src, type, SDL_TRUE);
591
if ( music == NULL && Mix_GetError()[0] == '\0' ) {
592
Mix_SetError("Unrecognized music format");
593
594
}
return music;
595
596
}
597
Mix_Music *Mix_LoadMUS_RW(SDL_RWops *src, int freesrc)
598
{
599
return Mix_LoadMUSType_RW(src, MUS_NONE, freesrc);
600
601
}
602
Mix_Music *Mix_LoadMUSType_RW(SDL_RWops *src, Mix_MusicType type, int freesrc)
603
{
604
Mix_Music *music;
605
Sint64 start;
606
607
if (!src) {
608
609
610
Mix_SetError("RWops pointer is NULL");
return NULL;
}
611
start = SDL_RWtell(src);
612
613
614
615
/* If the caller wants auto-detection, figure out what kind of file
* this is. */
if (type == MUS_NONE) {
616
if ((type = detect_music_type(src)) == MUS_NONE) {
617
618
/* Don't call Mix_SetError() here since detect_music_type()
* does that. */
619
620
621
if (freesrc) {
SDL_RWclose(src);
}
622
623
624
625
626
627
628
629
return NULL;
}
}
/* Allocate memory for the music structure */
music = (Mix_Music *)SDL_malloc(sizeof(Mix_Music));
if (music == NULL ) {
Mix_SetError("Out of memory");
630
631
632
if (freesrc) {
SDL_RWclose(src);
}
633
634
return NULL;
}
635
music->error = 1;
636
637
switch (type) {
638
#ifdef WAV_MUSIC
639
case MUS_WAV:
640
641
642
643
music->type = MUS_WAV;
music->data.wave = WAVStream_LoadSong_RW(src, freesrc);
if (music->data.wave) {
music->error = 0;
644
645
}
break;
646
#endif
647
#ifdef OGG_MUSIC
648
649
case MUS_OGG:
music->type = MUS_OGG;
650
651
652
music->data.ogg = OGG_new_RW(src, freesrc);
if (music->data.ogg) {
music->error = 0;
653
654
}
break;
655
#endif
656
#ifdef FLAC_MUSIC
657
658
case MUS_FLAC:
music->type = MUS_FLAC;
659
660
661
music->data.flac = FLAC_new_RW(src, freesrc);
if (music->data.flac) {
music->error = 0;
662
663
}
break;
664
#endif
665
#ifdef MP3_MUSIC
666
case MUS_MP3:
667
if (Mix_Init(MIX_INIT_MP3)) {
668
669
SMPEG_Info info;
music->type = MUS_MP3;
670
671
music->data.mp3 = smpeg.SMPEG_new_rwops(src, &info, freesrc, 0);
if (!info.has_audio) {
672
Mix_SetError("MPEG file does not have any audio stream.");
673
674
675
smpeg.SMPEG_delete(music->data.mp3);
/* Deleting the MP3 closed the source if desired */
freesrc = SDL_FALSE;
676
677
} else {
smpeg.SMPEG_actualSpec(music->data.mp3, &used_mixer);
678
music->error = 0;
679
680
681
}
}
break;
682
#elif defined(MP3_MAD_MUSIC)
683
684
case MUS_MP3:
music->type = MUS_MP3_MAD;
685
686
687
688
music->data.mp3_mad = mad_openFileRW(src, &used_mixer, freesrc);
if (music->data.mp3_mad) {
music->error = 0;
} else {
689
690
691
Mix_SetError("Could not initialize MPEG stream.");
}
break;
692
693
694
695
696
697
698
699
700
701
#elif defined(MP3_MPG_MUSIC)
case MUS_MP3:
music->type = MUS_MP3_MPG;
music->data.mp3_mpg = mpg_new_rw(src, &used_mixer, freesrc);
if (music->data.mp3_mpg) {
music->error = 0;
} else {
Mix_SetError("Could not initialize MPEG stream.");
}
break;
703
#ifdef MID_MUSIC
704
705
case MUS_MID:
music->type = MUS_MID;
706
#ifdef USE_NATIVE_MIDI
707
708
709
710
711
712
if (native_midi_ok) {
SDL_RWseek(src, start, RW_SEEK_SET);
music->data.nativemidi = native_midi_loadsong_RW(src, freesrc);
if (music->data.nativemidi) {
music->error = 0;
} else {
713
714
715
716
Mix_SetError("%s", native_midi_error());
}
break;
}
717
718
#endif
#ifdef USE_FLUIDSYNTH_MIDI
719
720
721
722
723
if (fluidsynth_ok) {
SDL_RWseek(src, start, RW_SEEK_SET);
music->data.fluidsynthmidi = fluidsynth_loadsong_RW(src, freesrc);
if (music->data.fluidsynthmidi) {
music->error = 0;
724
725
726
}
break;
}
727
728
#endif
#ifdef USE_TIMIDITY_MIDI
729
730
731
732
733
734
if (timidity_ok) {
SDL_RWseek(src, start, RW_SEEK_SET);
music->data.midi = Timidity_LoadSong_RW(src, freesrc);
if (music->data.midi) {
music->error = 0;
} else {
735
736
737
738
739
740
741
Mix_SetError("%s", Timidity_Error());
}
} else {
Mix_SetError("%s", Timidity_Error());
}
#endif
break;
742
743
#endif
#if defined(MODPLUG_MUSIC) || defined(MOD_MUSIC)
744
case MUS_MOD:
745
#ifdef MODPLUG_MUSIC
746
747
if (music->error) {
SDL_RWseek(src, start, RW_SEEK_SET);
748
music->type = MUS_MODPLUG;
749
750
music->data.modplug = modplug_new_RW(src, freesrc);
if (music->data.modplug) {
751
752
753
music->error = 0;
}
}
754
#endif
755
#ifdef MOD_MUSIC
756
757
if (music->error) {
SDL_RWseek(src, start, RW_SEEK_SET);
758
music->type = MUS_MOD;
759
760
music->data.module = MOD_new_RW(src, freesrc);
if (music->data.module) {
761
762
763
music->error = 0;
}
}
764
#endif
765
break;
766
767
#endif
768
769
default:
Mix_SetError("Unrecognized music format");
770
break;
771
} /* switch (want) */
772
773
774
if (music->error) {
SDL_free(music);
775
776
777
778
779
780
if (freesrc) {
SDL_RWclose(src);
} else {
SDL_RWseek(src, start, RW_SEEK_SET);
}
music = NULL;
781
}
782
return music;
783
784
785
786
787
}
/* Free a music chunk previously loaded */
void Mix_FreeMusic(Mix_Music *music)
{
788
789
if ( music ) {
/* Stop the music if it's currently playing */
790
Mix_LockAudio();
791
792
793
if ( music == music_playing ) {
/* Wait for any fade out to finish */
while ( music->fading == MIX_FADING_OUT ) {
794
Mix_UnlockAudio();
795
SDL_Delay(100);
796
Mix_LockAudio();
797
798
799
800
801
}
if ( music == music_playing ) {
music_internal_halt();
}
}
802
Mix_UnlockAudio();
803
switch (music->type) {
804
#ifdef CMD_MUSIC
805
806
807
case MUS_CMD:
MusicCMD_FreeSong(music->data.cmd);
break;
808
809
#endif
#ifdef WAV_MUSIC
810
811
812
case MUS_WAV:
WAVStream_FreeSong(music->data.wave);
break;
813
#endif
814
#ifdef MODPLUG_MUSIC
815
816
817
case MUS_MODPLUG:
modplug_delete(music->data.modplug);
break;
818
#endif
819
#ifdef MOD_MUSIC
820
821
822
case MUS_MOD:
MOD_delete(music->data.module);
break;
823
824
#endif
#ifdef MID_MUSIC
825
case MUS_MID:
826
#ifdef USE_NATIVE_MIDI
827
828
829
830
if ( native_midi_ok ) {
native_midi_freesong(music->data.nativemidi);
goto skip;
}
831
832
#endif
#ifdef USE_FLUIDSYNTH_MIDI
833
834
835
836
if ( fluidsynth_ok ) {
fluidsynth_freesong(music->data.fluidsynthmidi);
goto skip;
}
837
#endif
838
#ifdef USE_TIMIDITY_MIDI
839
840
841
842
if ( timidity_ok ) {
Timidity_FreeSong(music->data.midi);
goto skip;
}
843
#endif
844
break;
845
#endif
846
#ifdef OGG_MUSIC
847
848
849
case MUS_OGG:
OGG_delete(music->data.ogg);
break;
850
#endif
851
#ifdef FLAC_MUSIC
852
853
854
case MUS_FLAC:
FLAC_delete(music->data.flac);
break;
855
#endif
856
#ifdef MP3_MUSIC
857
858
859
case MUS_MP3:
smpeg.SMPEG_delete(music->data.mp3);
break;
860
861
#endif
#ifdef MP3_MAD_MUSIC
862
863
864
case MUS_MP3_MAD:
mad_closeFile(music->data.mp3_mad);
break;
865
866
867
868
869
#endif
#ifdef MP3_MPG_MUSIC
case MUS_MP3_MPG:
mpg_delete(music->data.mp3_mpg);
break;
870
#endif
871
872
873
874
default:
/* Unknown music type?? */
break;
}
875
876
skip:
877
878
SDL_free(music);
}
879
880
}
881
882
883
884
885
/* Find out the music format of a mixer music, or the currently playing
music, if 'music' is NULL.
*/
Mix_MusicType Mix_GetMusicType(const Mix_Music *music)
{
886
887
888
889
890
Mix_MusicType type = MUS_NONE;
if ( music ) {
type = music->type;
} else {
891
Mix_LockAudio();
892
893
894
if ( music_playing ) {
type = music_playing->type;
}
895
Mix_UnlockAudio();
896
897
}
return(type);
898
899
}
900
901
902
/* Play a music chunk. Returns 0, or -1 if there was an error.
*/
static int music_internal_play(Mix_Music *music, double position)
903
{
904
int retval = 0;
905
906
#if defined(__MACOSX__) && defined(USE_NATIVE_MIDI)
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
/* This fixes a bug with native MIDI on Mac OS X, where you
can't really stop and restart MIDI from the audio callback.
*/
if ( music == music_playing && music->type == MUS_MID && native_midi_ok ) {
/* Just a seek suffices to restart playing */
music_internal_position(position);
return 0;
}
#endif
/* Note the music we're playing */
if ( music_playing ) {
music_internal_halt();
}
music_playing = music;
/* Set the initial volume */
if ( music->type != MUS_MOD ) {
music_internal_initialize_volume();
}
/* Set up for playback */
switch (music->type) {
930
#ifdef CMD_MUSIC
931
932
933
case MUS_CMD:
MusicCMD_Start(music->data.cmd);
break;
934
935
#endif
#ifdef WAV_MUSIC
936
937
938
case MUS_WAV:
WAVStream_Start(music->data.wave);
break;
939
#endif
940
#ifdef MODPLUG_MUSIC
941
942
943
944
945
case MUS_MODPLUG:
/* can't set volume until file is loaded, so finally set it now */
music_internal_initialize_volume();
modplug_play(music->data.modplug);
break;
946
#endif
947
#ifdef MOD_MUSIC
948
949
950
951
952
case MUS_MOD:
MOD_play(music->data.module);
/* Player_SetVolume() does nothing before Player_Start() */
music_internal_initialize_volume();
break;
953
954
#endif
#ifdef MID_MUSIC
955
case MUS_MID:
956
#ifdef USE_NATIVE_MIDI
957
958
959
960
if ( native_midi_ok ) {
native_midi_start(music->data.nativemidi, music_loops);
goto skip;
}
961
962
#endif
#ifdef USE_FLUIDSYNTH_MIDI
963
964
965
966
if (fluidsynth_ok ) {
fluidsynth_start(music->data.fluidsynthmidi);
goto skip;
}
967
#endif
968
#ifdef USE_TIMIDITY_MIDI
969
970
971
972
if ( timidity_ok ) {
Timidity_Start(music->data.midi);
goto skip;
}
973
#endif
974
break;
975
#endif
976
#ifdef OGG_MUSIC
977
978
979
case MUS_OGG:
OGG_play(music->data.ogg);
break;
980
#endif
981
#ifdef FLAC_MUSIC
982
983
984
case MUS_FLAC:
FLAC_play(music->data.flac);
break;
985
#endif
986
#ifdef MP3_MUSIC
987
988
989
990
991
case MUS_MP3:
smpeg.SMPEG_enableaudio(music->data.mp3,1);
smpeg.SMPEG_enablevideo(music->data.mp3,0);
smpeg.SMPEG_play(music_playing->data.mp3);
break;
992
993
#endif
#ifdef MP3_MAD_MUSIC
994
995
996
case MUS_MP3_MAD:
mad_start(music->data.mp3_mad);
break;
997
998
999
1000
#endif
#ifdef MP3_MPG_MUSIC
case MUS_MP3_MPG:
mpg_start(music->data.mp3_mpg);