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