/
music.c
1608 lines (1497 loc) · 34 KB
1
/*
2
SDL_mixer: An audio mixer library based on the SDL library
3
Copyright (C) 1997-2009 Sam Lantinga
4
5
6
7
8
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
9
10
11
12
13
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
Library General Public License for more details.
14
15
16
17
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
19
20
Sam Lantinga
slouken@libsdl.org
21
22
*/
23
/* $Id$ */
24
25
26
#include <stdlib.h>
#include <string.h>
27
#include <ctype.h>
28
#include <assert.h>
29
30
#include "SDL_endian.h"
#include "SDL_audio.h"
31
#include "SDL_timer.h"
32
33
#include "SDL_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 FLAC_MUSIC
#include "music_flac.h"
#endif
70
71
#if defined(MP3_MUSIC) || defined(MP3_MAD_MUSIC)
72
73
74
static SDL_AudioSpec used_mixer;
#endif
76
77
int volatile music_active = 1;
static int volatile music_stopped = 0;
78
79
static int music_loops = 0;
static char *music_cmd = NULL;
80
static Mix_Music * volatile music_playing = NULL;
81
static int music_volume = MIX_MAX_VOLUME;
82
83
struct _Mix_Music {
84
Mix_MusicType type;
85
86
87
88
89
90
91
union {
#ifdef CMD_MUSIC
MusicCMD *cmd;
#endif
#ifdef WAV_MUSIC
WAVStream *wave;
#endif
92
93
94
#ifdef MODPLUG_MUSIC
modplug_data *modplug;
#endif
95
96
#ifdef MOD_MUSIC
struct MODULE *module;
97
98
#endif
#ifdef MID_MUSIC
99
#ifdef USE_TIMIDITY_MIDI
100
MidiSong *midi;
101
#endif
102
103
104
#ifdef USE_FLUIDSYNTH_MIDI
FluidSynthMidiSong *fluidsynthmidi;
#endif
105
106
107
#ifdef USE_NATIVE_MIDI
NativeMidiSong *nativemidi;
#endif
108
#endif
109
110
111
#ifdef OGG_MUSIC
OGG_music *ogg;
#endif
112
113
#ifdef MP3_MUSIC
SMPEG *mp3;
114
115
116
#endif
#ifdef MP3_MAD_MUSIC
mad_data *mp3_mad;
117
118
119
#endif
#ifdef FLAC_MUSIC
FLAC_music *flac;
120
121
#endif
} data;
122
Mix_Fading fading;
123
124
int fade_step;
int fade_steps;
125
126
int error;
};
127
#ifdef MID_MUSIC
128
#ifdef USE_TIMIDITY_MIDI
129
static int timidity_ok;
130
static int samplesize;
131
#endif
132
133
134
#ifdef USE_FLUIDSYNTH_MIDI
static int fluidsynth_ok;
#endif
135
136
137
#ifdef USE_NATIVE_MIDI
static int native_midi_ok;
#endif
138
#endif
139
140
141
142
/* Used to calculate fading steps */
static int ms_per_step;
143
144
145
146
/* rcg06042009 report available decoders at runtime. */
static const char **music_decoders = NULL;
static int num_decoders = 0;
147
148
149
150
151
/* Semicolon-separated SoundFont paths */
#ifdef MID_MUSIC
char* soundfont_paths = NULL;
#endif
152
int Mix_GetNumMusicDecoders(void)
153
154
155
156
157
158
159
160
161
162
163
164
165
166
{
return(num_decoders);
}
const char *Mix_GetMusicDecoder(int index)
{
if ((index < 0) || (index >= num_decoders)) {
return NULL;
}
return(music_decoders[index]);
}
static void add_music_decoder(const char *decoder)
{
167
void *ptr = realloc(music_decoders, (num_decoders + 1) * sizeof (const char **));
168
169
170
if (ptr == NULL) {
return; /* oh well, go on without it. */
}
171
music_decoders = (const char **) ptr;
172
173
174
music_decoders[num_decoders++] = decoder;
}
175
/* Local low-level functions prototypes */
176
static void music_internal_initialize_volume(void);
177
178
179
180
181
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);
182
183
184
185
186
187
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))
{
SDL_LockAudio();
music_finished_hook = music_finished;
SDL_UnlockAudio();
}
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
/* If music isn't playing, halt it if no looping is required, restart it */
/* otherwhise. NOP if the music is playing */
static int music_halt_or_loop (void)
{
/* Restart music if it has to loop */
if (!music_internal_playing())
{
/* Restart music if it has to loop at a high level */
if (music_loops && --music_loops)
{
Mix_Fading 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;
}
225
226
227
/* Mixing function */
void music_mixer(void *udata, Uint8 *stream, int len)
{
228
229
int left = 0;
230
if ( music_playing && music_active ) {
231
/* Handle fading */
232
233
if ( music_playing->fading != MIX_NO_FADING ) {
if ( music_playing->fade_step++ < music_playing->fade_steps ) {
234
int volume;
235
236
int fade_step = music_playing->fade_step;
int fade_steps = music_playing->fade_steps;
237
238
if ( music_playing->fading == MIX_FADING_OUT ) {
239
volume = (music_volume * (fade_steps-fade_step)) / fade_steps;
240
} else { /* Fading in */
241
volume = (music_volume * fade_step) / fade_steps;
242
}
243
music_internal_volume(volume);
244
245
} else {
if ( music_playing->fading == MIX_FADING_OUT ) {
246
247
248
249
music_internal_halt();
if ( music_finished_hook ) {
music_finished_hook();
}
250
return;
251
}
252
music_playing->fading = MIX_NO_FADING;
253
254
}
}
255
256
257
music_halt_or_loop();
if (!music_internal_playing())
258
return;
259
260
261
262
263
264
265
266
267
switch (music_playing->type) {
#ifdef CMD_MUSIC
case MUS_CMD:
/* The playing is done externally */
break;
#endif
#ifdef WAV_MUSIC
case MUS_WAV:
268
left = WAVStream_PlaySome(stream, len);
269
270
break;
#endif
271
272
273
274
275
#ifdef MODPLUG_MUSIC
case MUS_MODPLUG:
left = modplug_playAudio(music_playing->data.modplug, stream, len);
break;
#endif
276
#ifdef MOD_MUSIC
277
case MUS_MOD:
278
left = MOD_playAudio(music_playing->data.module, stream, len);
279
280
281
282
break;
#endif
#ifdef MID_MUSIC
case MUS_MID:
283
284
285
286
287
288
289
#ifdef USE_FLUIDSYNTH_MIDI
if ( fluidsynth_ok ) {
fluidsynth_playsome(music_playing->data.fluidsynthmidi, stream, len);
goto skip;
}
#endif
#ifdef USE_TIMIDITY_MIDI
290
291
292
if ( timidity_ok ) {
int samples = len / samplesize;
Timidity_PlaySome(stream, samples);
293
goto skip;
294
}
295
#endif
296
break;
297
#endif
298
299
#ifdef OGG_MUSIC
case MUS_OGG:
300
301
left = OGG_playAudio(music_playing->data.ogg, stream, len);
302
303
break;
#endif
304
305
#ifdef FLAC_MUSIC
case MUS_FLAC:
306
left = FLAC_playAudio(music_playing->data.flac, stream, len);
307
308
break;
#endif
309
#ifdef MP3_MUSIC
310
case MUS_MP3:
311
left = (len - smpeg.SMPEG_playAudio(music_playing->data.mp3, stream, len));
312
break;
313
314
315
#endif
#ifdef MP3_MAD_MUSIC
case MUS_MP3_MAD:
316
left = mad_getSamples(music_playing->data.mp3_mad, stream, len);
318
319
320
321
322
323
#endif
default:
/* Unknown music type?? */
break;
}
}
324
325
skip:
326
/* Handle seamless music looping */
327
328
329
330
if (left > 0 && left < len) {
music_halt_or_loop();
if (music_internal_playing())
music_mixer(udata, stream+(len-left), left);
331
}
332
333
334
335
336
337
}
/* Initialize the music players with a certain desired audio format */
int open_music(SDL_AudioSpec *mixer)
{
#ifdef WAV_MUSIC
338
if ( WAVStream_Init(mixer) == 0 ) {
339
add_music_decoder("WAVE");
340
341
}
#endif
342
#ifdef MODPLUG_MUSIC
343
if ( modplug_init(mixer) == 0 ) {
344
345
346
add_music_decoder("MODPLUG");
}
#endif
347
#ifdef MOD_MUSIC
348
if ( MOD_init(mixer) == 0 ) {
349
add_music_decoder("MIKMOD");
350
351
352
}
#endif
#ifdef MID_MUSIC
353
#ifdef USE_TIMIDITY_MIDI
354
samplesize = mixer->size / mixer->samples;
355
if ( Timidity_Init(mixer->freq, mixer->format,
356
mixer->channels, mixer->samples) == 0 ) {
357
timidity_ok = 1;
358
add_music_decoder("TIMIDITY");
359
360
361
} else {
timidity_ok = 0;
}
362
#endif
363
364
365
366
367
368
369
370
#ifdef USE_FLUIDSYNTH_MIDI
if ( fluidsynth_init(mixer) == 0 ) {
fluidsynth_ok = 1;
add_music_decoder("FLUIDSYNTH");
} else {
fluidsynth_ok = 0;
}
#endif
371
#ifdef USE_NATIVE_MIDI
372
373
374
375
#ifdef USE_FLUIDSYNTH_MIDI
native_midi_ok = !fluidsynth_ok;
if ( native_midi_ok )
#endif
376
#ifdef USE_TIMIDITY_MIDI
377
native_midi_ok = !timidity_ok;
378
379
380
if ( !native_midi_ok ) {
native_midi_ok = (getenv("SDL_NATIVE_MUSIC") != NULL);
}
381
382
if ( native_midi_ok )
#endif
383
native_midi_ok = native_midi_detect();
384
385
if ( native_midi_ok )
add_music_decoder("NATIVEMIDI");
386
#endif
387
#endif
388
#ifdef OGG_MUSIC
389
if ( OGG_init(mixer) == 0 ) {
390
add_music_decoder("OGG");
391
392
}
#endif
393
#ifdef FLAC_MUSIC
394
if ( FLAC_init(mixer) == 0 ) {
395
add_music_decoder("FLAC");
396
397
}
#endif
398
#if defined(MP3_MUSIC) || defined(MP3_MAD_MUSIC)
399
400
/* Keep a copy of the mixer */
used_mixer = *mixer;
401
add_music_decoder("MP3");
402
#endif
403
404
music_playing = NULL;
405
music_stopped = 0;
406
407
Mix_VolumeMusic(SDL_MIX_MAXVOLUME);
408
/* Calculate the number of ms for each callback */
409
ms_per_step = (int) (((float)mixer->samples * 1000.0) / mixer->freq);
410
411
412
413
return(0);
}
414
415
416
417
418
419
420
421
422
423
424
425
426
/* Portable case-insensitive string compare function */
int MIX_string_equals(const char *str1, const char *str2)
{
while ( *str1 && *str2 ) {
if ( toupper((unsigned char)*str1) !=
toupper((unsigned char)*str2) )
break;
++str1;
++str2;
}
return (!*str1 && !*str2);
}
427
428
429
430
/* Load a music file */
Mix_Music *Mix_LoadMUS(const char *file)
{
FILE *fp;
431
char *ext;
432
Uint8 magic[5], moremagic[9];
433
434
435
436
437
438
439
440
Mix_Music *music;
/* Figure out what kind of file this is */
fp = fopen(file, "rb");
if ( (fp == NULL) || !fread(magic, 4, 1, fp) ) {
if ( fp != NULL ) {
fclose(fp);
}
441
Mix_SetError("Couldn't read from '%s'", file);
442
443
return(NULL);
}
444
445
446
447
if (!fread(moremagic, 8, 1, fp)) {
Mix_SetError("Couldn't read from '%s'", file);
return(NULL);
}
448
magic[4] = '\0';
449
moremagic[8] = '\0';
450
451
fclose(fp);
452
453
454
455
/* Figure out the file extension, so we can determine the type */
ext = strrchr(file, '.');
if ( ext ) ++ext; /* skip the dot in the extension */
456
457
458
/* Allocate memory for the music structure */
music = (Mix_Music *)malloc(sizeof(Mix_Music));
if ( music == NULL ) {
459
Mix_SetError("Out of memory");
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
return(NULL);
}
music->error = 0;
#ifdef CMD_MUSIC
if ( music_cmd ) {
music->type = MUS_CMD;
music->data.cmd = MusicCMD_LoadSong(music_cmd, file);
if ( music->data.cmd == NULL ) {
music->error = 1;
}
} else
#endif
#ifdef WAV_MUSIC
/* WAVE files have the magic four bytes "RIFF"
AIFF files have the magic 12 bytes "FORM" XXXX "AIFF"
*/
477
if ( (ext && MIX_string_equals(ext, "WAV")) ||
478
((strcmp((char *)magic, "RIFF") == 0) && (strcmp((char *)(moremagic+4), "WAVE") == 0)) ||
479
(strcmp((char *)magic, "FORM") == 0) ) {
480
music->type = MUS_WAV;
481
music->data.wave = WAVStream_LoadSong(file, (char *)magic);
482
if ( music->data.wave == NULL ) {
483
Mix_SetError("Unable to load WAV file");
484
485
486
487
488
489
music->error = 1;
}
} else
#endif
#ifdef MID_MUSIC
/* MIDI files have the magic four bytes "MThd" */
490
491
if ( (ext && MIX_string_equals(ext, "MID")) ||
(ext && MIX_string_equals(ext, "MIDI")) ||
492
493
494
strcmp((char *)magic, "MThd") == 0 ||
( strcmp((char *)magic, "RIFF") == 0 &&
strcmp((char *)(moremagic+4), "RMID") == 0 ) ) {
495
music->type = MUS_MID;
496
497
#ifdef USE_NATIVE_MIDI
if ( native_midi_ok ) {
498
music->data.nativemidi = native_midi_loadsong(file);
499
500
501
502
if ( music->data.nativemidi == NULL ) {
Mix_SetError("%s", native_midi_error());
music->error = 1;
}
503
504
505
506
507
508
509
510
511
512
513
goto skip;
}
#endif
#ifdef USE_FLUIDSYNTH_MIDI
if ( fluidsynth_ok ) {
music->data.fluidsynthmidi = fluidsynth_loadsong(file);
if ( music->data.fluidsynthmidi == NULL ) {
music->error = 1;
}
goto skip;
}
514
#endif
515
#ifdef USE_TIMIDITY_MIDI
516
if ( timidity_ok ) {
517
music->data.midi = Timidity_LoadSong(file);
518
if ( music->data.midi == NULL ) {
519
Mix_SetError("%s", Timidity_Error());
520
521
music->error = 1;
}
522
} else {
523
Mix_SetError("%s", Timidity_Error());
524
525
music->error = 1;
}
526
#endif
527
528
} else
#endif
529
530
#ifdef OGG_MUSIC
/* Ogg Vorbis files have the magic four bytes "OggS" */
531
if ( (ext && MIX_string_equals(ext, "OGG")) ||
532
strcmp((char *)magic, "OggS") == 0 ) {
533
534
535
536
537
538
539
music->type = MUS_OGG;
music->data.ogg = OGG_new(file);
if ( music->data.ogg == NULL ) {
music->error = 1;
}
} else
#endif
540
541
542
543
544
545
546
547
548
549
550
#ifdef FLAC_MUSIC
/* FLAC files have the magic four bytes "fLaC" */
if ( (ext && MIX_string_equals(ext, "FLAC")) ||
strcmp((char *)magic, "fLaC") == 0 ) {
music->type = MUS_FLAC;
music->data.flac = FLAC_new(file);
if ( music->data.flac == NULL ) {
music->error = 1;
}
} else
#endif
551
#ifdef MP3_MUSIC
552
if ( (ext && MIX_string_equals(ext, "MPG")) ||
553
(ext && MIX_string_equals(ext, "MP3")) ||
554
(ext && MIX_string_equals(ext, "MPEG")) ||
555
556
(magic[0] == 0xFF && (magic[1] & 0xF0) == 0xF0) ||
(strncmp((char *)magic, "ID3", 3) == 0) ) {
557
if ( Mix_Init(MIX_INIT_MP3) ) {
558
559
560
561
562
563
564
565
566
SMPEG_Info info;
music->type = MUS_MP3;
music->data.mp3 = smpeg.SMPEG_new(file, &info, 0);
if ( !info.has_audio ) {
Mix_SetError("MPEG file does not have any audio stream.");
music->error = 1;
} else {
smpeg.SMPEG_actualSpec(music->data.mp3, &used_mixer);
}
567
} else {
568
music->error = 1;
569
570
571
}
} else
#endif
572
573
574
575
576
#ifdef MP3_MAD_MUSIC
if ( (ext && MIX_string_equals(ext, "MPG")) ||
(ext && MIX_string_equals(ext, "MP3")) ||
(ext && MIX_string_equals(ext, "MPEG")) ||
(ext && MIX_string_equals(ext, "MAD")) ||
577
578
(magic[0] == 0xFF && (magic[1] & 0xF0) == 0xF0) ||
(strncmp((char *)magic, "ID3", 3) == 0) ) {
579
580
581
582
583
584
585
586
music->type = MUS_MP3_MAD;
music->data.mp3_mad = mad_openFile(file, &used_mixer);
if (music->data.mp3_mad == 0) {
Mix_SetError("Could not initialize MPEG stream.");
music->error = 1;
}
} else
#endif
587
588
589
590
591
592
593
594
595
#ifdef MODPLUG_MUSIC
if ( 1 ) {
music->type = MUS_MODPLUG;
music->data.modplug = modplug_new(file);
if ( music->data.modplug == NULL ) {
music->error = 1;
}
} else
#endif
596
#ifdef MOD_MUSIC
597
598
if ( 1 ) {
music->type = MUS_MOD;
599
music->data.module = MOD_new(file);
600
601
602
603
604
605
if ( music->data.module == NULL ) {
music->error = 1;
}
} else
#endif
{
606
Mix_SetError("Unrecognized music format");
607
608
music->error = 1;
}
609
610
skip:
611
612
613
614
615
616
617
618
619
620
621
if ( music->error ) {
free(music);
music = NULL;
}
return(music);
}
/* Free a music chunk previously loaded */
void Mix_FreeMusic(Mix_Music *music)
{
if ( music ) {
622
623
624
625
626
627
628
629
630
631
632
/* Stop the music if it's currently playing */
SDL_LockAudio();
if ( music == music_playing ) {
/* Wait for any fade out to finish */
while ( music->fading == MIX_FADING_OUT ) {
SDL_UnlockAudio();
SDL_Delay(100);
SDL_LockAudio();
}
if ( music == music_playing ) {
music_internal_halt();
633
}
634
}
635
SDL_UnlockAudio();
636
637
638
639
640
641
642
643
644
645
646
switch (music->type) {
#ifdef CMD_MUSIC
case MUS_CMD:
MusicCMD_FreeSong(music->data.cmd);
break;
#endif
#ifdef WAV_MUSIC
case MUS_WAV:
WAVStream_FreeSong(music->data.wave);
break;
#endif
647
648
649
650
651
#ifdef MODPLUG_MUSIC
case MUS_MODPLUG:
modplug_delete(music->data.modplug);
break;
#endif
652
#ifdef MOD_MUSIC
653
case MUS_MOD:
654
MOD_delete(music->data.module);
655
656
657
658
break;
#endif
#ifdef MID_MUSIC
case MUS_MID:
659
660
661
#ifdef USE_NATIVE_MIDI
if ( native_midi_ok ) {
native_midi_freesong(music->data.nativemidi);
662
663
664
665
666
667
668
669
goto skip;
}
#endif
#ifdef USE_FLUIDSYNTH_MIDI
if ( fluidsynth_ok ) {
fluidsynth_freesong(music->data.fluidsynthmidi);
goto skip;
}
670
#endif
671
#ifdef USE_TIMIDITY_MIDI
672
673
if ( timidity_ok ) {
Timidity_FreeSong(music->data.midi);
674
goto skip;
675
}
676
#endif
677
678
break;
#endif
679
680
681
682
683
#ifdef OGG_MUSIC
case MUS_OGG:
OGG_delete(music->data.ogg);
break;
#endif
684
685
686
687
688
#ifdef FLAC_MUSIC
case MUS_FLAC:
FLAC_delete(music->data.flac);
break;
#endif
689
#ifdef MP3_MUSIC
690
case MUS_MP3:
691
smpeg.SMPEG_delete(music->data.mp3);
692
break;
693
694
695
696
697
#endif
#ifdef MP3_MAD_MUSIC
case MUS_MP3_MAD:
mad_closeFile(music->data.mp3_mad);
break;
698
699
700
701
702
#endif
default:
/* Unknown music type?? */
break;
}
703
704
skip:
705
706
707
708
free(music);
}
}
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
/* 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)
{
Mix_MusicType type = MUS_NONE;
if ( music ) {
type = music->type;
} else {
SDL_LockAudio();
if ( music_playing ) {
type = music_playing->type;
}
SDL_UnlockAudio();
}
return(type);
}
728
729
730
/* Play a music chunk. Returns 0, or -1 if there was an error.
*/
static int music_internal_play(Mix_Music *music, double position)
731
{
732
733
734
735
736
737
738
int retval = 0;
/* Note the music we're playing */
if ( music_playing ) {
music_internal_halt();
}
music_playing = music;
739
740
/* Set the initial volume */
741
742
if ( music->type != MUS_MOD ) {
music_internal_initialize_volume();
743
744
745
}
/* Set up for playback */
746
747
switch (music->type) {
#ifdef CMD_MUSIC
748
749
750
case MUS_CMD:
MusicCMD_Start(music->data.cmd);
break;
751
752
#endif
#ifdef WAV_MUSIC
753
754
755
case MUS_WAV:
WAVStream_Start(music->data.wave);
break;
756
#endif
757
758
759
760
761
762
763
#ifdef MODPLUG_MUSIC
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;
#endif
764
#ifdef MOD_MUSIC
765
case MUS_MOD:
766
MOD_play(music->data.module);
767
768
/* Player_SetVolume() does nothing before Player_Start() */
music_internal_initialize_volume();
769
break;
770
771
#endif
#ifdef MID_MUSIC
772
case MUS_MID:
773
#ifdef USE_NATIVE_MIDI
774
775
if ( native_midi_ok ) {
native_midi_start(music->data.nativemidi);
776
777
778
779
780
781
782
783
goto skip;
}
#endif
#ifdef USE_FLUIDSYNTH_MIDI
if (fluidsynth_ok ) {
fluidsynth_start(music->data.fluidsynthmidi);
goto skip;
}
784
#endif
785
#ifdef USE_TIMIDITY_MIDI
786
787
if ( timidity_ok ) {
Timidity_Start(music->data.midi);
788
goto skip;
789
}
790
#endif
791
break;
792
#endif
793
#ifdef OGG_MUSIC
794
795
796
case MUS_OGG:
OGG_play(music->data.ogg);
break;
797
#endif
798
799
800
801
802
#ifdef FLAC_MUSIC
case MUS_FLAC:
FLAC_play(music->data.flac);
break;
#endif
803
#ifdef MP3_MUSIC
804
case MUS_MP3:
805
806
807
smpeg.SMPEG_enableaudio(music->data.mp3,1);
smpeg.SMPEG_enablevideo(music->data.mp3,0);
smpeg.SMPEG_play(music_playing->data.mp3);
808
break;
809
810
811
812
813
#endif
#ifdef MP3_MAD_MUSIC
case MUS_MP3_MAD:
mad_start(music->data.mp3_mad);
break;
814
#endif
815
816
817
818
default:
Mix_SetError("Can't play unknown music type");
retval = -1;
break;
819
}
820
821
skip:
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
/* Set the playback position, note any errors if an offset is used */
if ( retval == 0 ) {
if ( position > 0.0 ) {
if ( music_internal_position(position) < 0 ) {
Mix_SetError("Position not implemented for music type");
retval = -1;
}
} else {
music_internal_position(0.0);
}
}
/* If the setup failed, we're not playing any music anymore */
if ( retval < 0 ) {
music_playing = NULL;
}
return(retval);
}
int Mix_FadeInMusicPos(Mix_Music *music, int loops, int ms, double position)
841
{
842
843
int retval;
844
845
846
847
848
if ( ms_per_step == 0 ) {
SDL_SetError("Audio device hasn't been opened");
return(-1);
}
849
850
/* Don't play null pointers :-) */
if ( music == NULL ) {
851
Mix_SetError("music parameter was NULL");
852
853
return(-1);
}
854
855
856
857
858
859
/* Setup the data */
if ( ms ) {
music->fading = MIX_FADING_IN;
} else {
music->fading = MIX_NO_FADING;
860
}
861
862
music->fade_step = 0;
music->fade_steps = ms/ms_per_step;
863
864
865
866
867
868
869
870
/* Play the puppy */
SDL_LockAudio();
/* If the current music is fading out, wait for the fade to complete */
while ( music_playing && (music_playing->fading == MIX_FADING_OUT) ) {
SDL_UnlockAudio();
SDL_Delay(100);
SDL_LockAudio();
871
}
872
music_active = 1;
873
music_loops = loops;
874
875
876
877
878
879
880
881
882
883
884
885
retval = music_internal_play(music, position);
SDL_UnlockAudio();
return(retval);
}
int Mix_FadeInMusic(Mix_Music *music, int loops, int ms)
{
return Mix_FadeInMusicPos(music, loops, ms, 0.0);
}
int Mix_PlayMusic(Mix_Music *music, int loops)
{
return Mix_FadeInMusicPos(music, loops, 0, 0.0);
886
887
}
888
889
/* Set the playing music position */
int music_internal_position(double position)
890
{
891
892
893
int retval = 0;
switch (music_playing->type) {
894
895
896
897
898
#ifdef MODPLUG_MUSIC
case MUS_MODPLUG:
modplug_jump_to_time(music_playing->data.modplug, position);
break;
#endif
899
#ifdef MOD_MUSIC
900
case MUS_MOD:
901
MOD_jump_to_time(music_playing->data.module, position);
902
break;
903
904
#endif
#ifdef OGG_MUSIC
905
906
907
case MUS_OGG:
OGG_jump_to_time(music_playing->data.ogg, position);
break;
908
#endif
909
910
911
912
913
#ifdef FLAC_MUSIC
case MUS_FLAC:
FLAC_jump_to_time(music_playing->data.flac, position);
break;
#endif
914
#ifdef MP3_MUSIC
915
case MUS_MP3:
916
if ( position > 0.0 ) {
917
smpeg.SMPEG_skip(music_playing->data.mp3, (float)position);
918
} else {
919
920
smpeg.SMPEG_rewind(music_playing->data.mp3);
smpeg.SMPEG_play(music_playing->data.mp3);
921
}
922
break;
923
924
925
926
927
#endif
#ifdef MP3_MAD_MUSIC
case MUS_MP3_MAD:
mad_seek(music_playing->data.mp3_mad, position);
break;
928
929
930
931
932
#endif
default:
/* TODO: Implement this for other music backends */
retval = -1;
break;
933
}
934
return(retval);
935
}
936
int Mix_SetMusicPosition(double position)
937
{
938
939
940
941
942
943
944
int retval;
SDL_LockAudio();
if ( music_playing ) {
retval = music_internal_position(position);
if ( retval < 0 ) {
Mix_SetError("Position not implemented for music type");
945
}
946
947
948
} else {
Mix_SetError("Music isn't playing");
retval = -1;
949
}
950
SDL_UnlockAudio();
951
952
return(retval);
953
954
}
955
956
957
958
959
960
961
962
963
964
/* Set the music's initial volume */
static void music_internal_initialize_volume(void)
{
if ( music_playing->fading == MIX_FADING_IN ) {
music_internal_volume(0);
} else {
music_internal_volume(music_volume);
}
}
965
/* Set the music volume */
966
static void music_internal_volume(int volume)
967
{
968
switch (music_playing->type) {
969
#ifdef CMD_MUSIC
970
971
972
case MUS_CMD:
MusicCMD_SetVolume(volume);
break;
973
974
#endif
#ifdef WAV_MUSIC
975
976
977
case MUS_WAV:
WAVStream_SetVolume(volume);
break;
978
#endif
979
980
981
982
983
#ifdef MODPLUG_MUSIC
case MUS_MODPLUG:
modplug_setvolume(music_playing->data.modplug, volume);
break;
#endif
984
#ifdef MOD_MUSIC
985
case MUS_MOD:
986
MOD_setvolume(music_playing->data.module, volume);
987
break;
988
989
#endif
#ifdef MID_MUSIC
990
case MUS_MID:
991
#ifdef USE_NATIVE_MIDI
992
993
if ( native_midi_ok ) {
native_midi_setvolume(volume);
994
995
996
997
998
999
1000
return;
}
#endif
#ifdef USE_FLUIDSYNTH_MIDI
if ( fluidsynth_ok ) {
fluidsynth_setvolume(music_playing->data.fluidsynthmidi, volume);
return;