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