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