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