Subversion Repositories Kolibri OS

Rev

Rev 8645 | Rev 9213 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
8645 turbocat 1
/*
2
  SDL_mixer:  An audio mixer library based on the SDL library
3
  Copyright (C) 1997-2012 Sam Lantinga 
4
 
5
  This software is provided 'as-is', without any express or implied
6
  warranty.  In no event will the authors be held liable for any damages
7
  arising from the use of this software.
8
 
9
  Permission is granted to anyone to use this software for any purpose,
10
  including commercial applications, and to alter it and redistribute it
11
  freely, subject to the following restrictions:
12
 
13
  1. The origin of this software must not be misrepresented; you must not
14
     claim that you wrote the original software. If you use this software
15
     in a product, an acknowledgment in the product documentation would be
16
     appreciated but is not required.
17
  2. Altered source versions must be plainly marked as such, and must not be
18
     misrepresented as being the original software.
19
  3. This notice may not be removed or altered from any source distribution.
20
*/
21
 
22
/* $Id$ */
23
 
24
#include 
25
#include 
26
#include 
27
#include 
28
#include "SDL_endian.h"
29
#include "SDL_audio.h"
30
#include "SDL_timer.h"
31
 
32
#include "SDL_mixer.h"
33
 
34
#ifdef CMD_MUSIC
35
#include "music_cmd.h"
36
#endif
37
#ifdef WAV_MUSIC
38
#include "wavestream.h"
39
#endif
40
#ifdef MODPLUG_MUSIC
41
#include "music_modplug.h"
42
#endif
43
#ifdef MOD_MUSIC
44
#include "music_mod.h"
45
#endif
46
#ifdef MID_MUSIC
47
#  ifdef USE_TIMIDITY_MIDI
48
#    include "timidity.h"
49
#  endif
50
#  ifdef USE_FLUIDSYNTH_MIDI
51
#    include "fluidsynth.h"
52
#  endif
53
#  ifdef USE_NATIVE_MIDI
54
#    include "native_midi.h"
55
#  endif
56
#endif
57
#ifdef OGG_MUSIC
58
#include "music_ogg.h"
59
#endif
60
#ifdef MP3_MUSIC
61
#include "dynamic_mp3.h"
62
#endif
63
#ifdef MP3_MAD_MUSIC
64
#include "music_mad.h"
65
#endif
66
#ifdef FLAC_MUSIC
67
#include "music_flac.h"
68
#endif
69
 
70
#if defined(MP3_MUSIC) || defined(MP3_MAD_MUSIC)
71
static SDL_AudioSpec used_mixer;
72
#endif
73
 
9097 turbocat 74
#ifdef _KOLIBRI
75
    extern void      uSDL_Delay(unsigned int time);
76
    extern unsigned  uSDL_GetTicks();
77
#else
78
    #define uSDL_Delay SDL_Delay
79
    #define  uSDL_GetTicks SDL_GetTicks
80
#endif
8645 turbocat 81
 
82
int volatile music_active = 1;
83
static int volatile music_stopped = 0;
84
static int music_loops = 0;
85
static char *music_cmd = NULL;
86
static Mix_Music * volatile music_playing = NULL;
87
static int music_volume = MIX_MAX_VOLUME;
88
 
89
struct _Mix_Music {
90
	Mix_MusicType type;
91
	union {
92
#ifdef CMD_MUSIC
93
		MusicCMD *cmd;
94
#endif
95
#ifdef WAV_MUSIC
96
		WAVStream *wave;
97
#endif
98
#ifdef MODPLUG_MUSIC
99
		modplug_data *modplug;
100
#endif
101
#ifdef MOD_MUSIC
102
		struct MODULE *module;
103
#endif
104
#ifdef MID_MUSIC
105
#ifdef USE_TIMIDITY_MIDI
106
		MidiSong *midi;
107
#endif
108
#ifdef USE_FLUIDSYNTH_MIDI
109
		FluidSynthMidiSong *fluidsynthmidi;
110
#endif
111
#ifdef USE_NATIVE_MIDI
112
		NativeMidiSong *nativemidi;
113
#endif
114
#endif
115
#ifdef OGG_MUSIC
116
		OGG_music *ogg;
117
#endif
118
#ifdef MP3_MUSIC
119
		SMPEG *mp3;
120
#endif
121
#ifdef MP3_MAD_MUSIC
122
		mad_data *mp3_mad;
123
#endif
124
#ifdef FLAC_MUSIC
125
		FLAC_music *flac;
126
#endif
127
	} data;
128
	Mix_Fading fading;
129
	int fade_step;
130
	int fade_steps;
131
	int error;
132
};
133
#ifdef MID_MUSIC
134
#ifdef USE_TIMIDITY_MIDI
135
static int timidity_ok;
136
static int samplesize;
137
#endif
138
#ifdef USE_FLUIDSYNTH_MIDI
139
static int fluidsynth_ok;
140
#endif
141
#ifdef USE_NATIVE_MIDI
142
static int native_midi_ok;
143
#endif
144
#endif
145
 
146
/* Used to calculate fading steps */
147
static int ms_per_step;
148
 
149
/* rcg06042009 report available decoders at runtime. */
150
static const char **music_decoders = NULL;
151
static int num_decoders = 0;
152
 
153
/* Semicolon-separated SoundFont paths */
154
#ifdef MID_MUSIC
155
char* soundfont_paths = NULL;
156
#endif
157
 
158
int Mix_GetNumMusicDecoders(void)
159
{
160
	return(num_decoders);
161
}
162
 
163
const char *Mix_GetMusicDecoder(int index)
164
{
165
	if ((index < 0) || (index >= num_decoders)) {
166
		return NULL;
167
	}
168
	return(music_decoders[index]);
169
}
170
 
171
static void add_music_decoder(const char *decoder)
172
{
173
	void *ptr = SDL_realloc(music_decoders, (num_decoders + 1) * sizeof (const char **));
174
	if (ptr == NULL) {
175
		return;  /* oh well, go on without it. */
176
	}
177
	music_decoders = (const char **) ptr;
178
	music_decoders[num_decoders++] = decoder;
179
}
180
 
181
/* Local low-level functions prototypes */
182
static void music_internal_initialize_volume(void);
183
static void music_internal_volume(int volume);
184
static int  music_internal_play(Mix_Music *music, double position);
185
static int  music_internal_position(double position);
186
static int  music_internal_playing();
187
static void music_internal_halt(void);
188
 
189
 
190
/* Support for hooking when the music has finished */
191
static void (*music_finished_hook)(void) = NULL;
192
 
193
void Mix_HookMusicFinished(void (*music_finished)(void))
194
{
195
	SDL_LockAudio();
196
	music_finished_hook = music_finished;
197
	SDL_UnlockAudio();
198
}
199
 
200
 
201
/* If music isn't playing, halt it if no looping is required, restart it */
202
/* otherwhise. NOP if the music is playing */
203
static int music_halt_or_loop (void)
204
{
205
	/* Restart music if it has to loop */
206
 
207
	if (!music_internal_playing())
208
	{
209
#ifdef USE_NATIVE_MIDI
210
		/* Native MIDI handles looping internally */
211
		if (music_playing->type == MUS_MID && native_midi_ok) {
212
			music_loops = 0;
213
		}
214
#endif
215
 
216
		/* Restart music if it has to loop at a high level */
217
		if (music_loops)
218
		{
219
			Mix_Fading current_fade;
220
			--music_loops;
221
			current_fade = music_playing->fading;
222
			music_internal_play(music_playing, 0.0);
223
			music_playing->fading = current_fade;
224
		}
225
		else
226
		{
227
			music_internal_halt();
228
			if (music_finished_hook)
229
				music_finished_hook();
230
 
231
			return 0;
232
		}
233
	}
234
 
235
	return 1;
236
}
237
 
238
 
239
 
240
/* Mixing function */
241
void music_mixer(void *udata, Uint8 *stream, int len)
242
{
243
	int left = 0;
244
 
245
	if ( music_playing && music_active ) {
246
		/* Handle fading */
247
		if ( music_playing->fading != MIX_NO_FADING ) {
248
			if ( music_playing->fade_step++ < music_playing->fade_steps ) {
249
				int volume;
250
				int fade_step = music_playing->fade_step;
251
				int fade_steps = music_playing->fade_steps;
252
 
253
				if ( music_playing->fading == MIX_FADING_OUT ) {
254
					volume = (music_volume * (fade_steps-fade_step)) / fade_steps;
255
				} else { /* Fading in */
256
					volume = (music_volume * fade_step) / fade_steps;
257
				}
258
				music_internal_volume(volume);
259
			} else {
260
				if ( music_playing->fading == MIX_FADING_OUT ) {
261
					music_internal_halt();
262
					if ( music_finished_hook ) {
263
						music_finished_hook();
264
					}
265
					return;
266
				}
267
				music_playing->fading = MIX_NO_FADING;
268
			}
269
		}
270
 
271
		music_halt_or_loop();
272
		if (!music_internal_playing())
273
			return;
274
 
275
		switch (music_playing->type) {
276
#ifdef CMD_MUSIC
277
			case MUS_CMD:
278
				/* The playing is done externally */
279
				break;
280
#endif
281
#ifdef WAV_MUSIC
282
			case MUS_WAV:
283
				left = WAVStream_PlaySome(stream, len);
284
				break;
285
#endif
286
#ifdef MODPLUG_MUSIC
287
			case MUS_MODPLUG:
288
				left = modplug_playAudio(music_playing->data.modplug, stream, len);
289
				break;
290
#endif
291
#ifdef MOD_MUSIC
292
			case MUS_MOD:
293
				left = MOD_playAudio(music_playing->data.module, stream, len);
294
				break;
295
#endif
296
#ifdef MID_MUSIC
297
			case MUS_MID:
298
#ifdef USE_NATIVE_MIDI
299
  				if ( native_midi_ok ) {
300
					/* Native midi is handled asynchronously */
301
					goto skip;
302
	  			}
303
#endif
304
#ifdef USE_FLUIDSYNTH_MIDI
305
				if ( fluidsynth_ok ) {
306
					fluidsynth_playsome(music_playing->data.fluidsynthmidi, stream, len);
307
					goto skip;
308
				}
309
#endif
310
#ifdef USE_TIMIDITY_MIDI
311
				if ( timidity_ok ) {
312
					int samples = len / samplesize;
313
  					Timidity_PlaySome(stream, samples);
314
					goto skip;
315
				}
316
#endif
317
				break;
318
#endif
319
#ifdef OGG_MUSIC
320
			case MUS_OGG:
321
 
322
				left = OGG_playAudio(music_playing->data.ogg, stream, len);
323
				break;
324
#endif
325
#ifdef FLAC_MUSIC
326
			case MUS_FLAC:
327
				left = FLAC_playAudio(music_playing->data.flac, stream, len);
328
				break;
329
#endif
330
#ifdef MP3_MUSIC
331
			case MUS_MP3:
332
				left = (len - smpeg.SMPEG_playAudio(music_playing->data.mp3, stream, len));
333
				break;
334
#endif
335
#ifdef MP3_MAD_MUSIC
336
			case MUS_MP3_MAD:
337
				left = mad_getSamples(music_playing->data.mp3_mad, stream, len);
338
				break;
339
#endif
340
			default:
341
				/* Unknown music type?? */
342
				break;
343
		}
344
	}
345
 
346
skip:
347
	/* Handle seamless music looping */
348
	if (left > 0 && left < len) {
349
		music_halt_or_loop();
350
		if (music_internal_playing())
351
			music_mixer(udata, stream+(len-left), left);
352
	}
353
}
354
 
355
/* Initialize the music players with a certain desired audio format */
356
int open_music(SDL_AudioSpec *mixer)
357
{
358
#ifdef WAV_MUSIC
359
	if ( WAVStream_Init(mixer) == 0 ) {
360
		add_music_decoder("WAVE");
361
	}
362
#endif
363
#ifdef MODPLUG_MUSIC
364
	if ( modplug_init(mixer) == 0 ) {
365
		add_music_decoder("MODPLUG");
366
	}
367
#endif
368
#ifdef MOD_MUSIC
369
	if ( MOD_init(mixer) == 0 ) {
370
		add_music_decoder("MIKMOD");
371
	}
372
#endif
373
#ifdef MID_MUSIC
374
#ifdef USE_TIMIDITY_MIDI
375
	samplesize = mixer->size / mixer->samples;
376
	if ( Timidity_Init(mixer->freq, mixer->format,
377
	                    mixer->channels, mixer->samples) == 0 ) {
378
		timidity_ok = 1;
379
		add_music_decoder("TIMIDITY");
380
	} else {
381
		timidity_ok = 0;
382
	}
383
#endif
384
#ifdef USE_FLUIDSYNTH_MIDI
385
	if ( fluidsynth_init(mixer) == 0 ) {
386
		fluidsynth_ok = 1;
387
		add_music_decoder("FLUIDSYNTH");
388
	} else {
389
		fluidsynth_ok = 0;
390
	}
391
#endif
392
#ifdef USE_NATIVE_MIDI
393
#ifdef USE_FLUIDSYNTH_MIDI
394
	native_midi_ok = !fluidsynth_ok;
395
	if ( native_midi_ok )
396
#endif
397
#ifdef USE_TIMIDITY_MIDI
398
		native_midi_ok = !timidity_ok;
399
	if ( !native_midi_ok ) {
400
		native_midi_ok = (getenv("SDL_NATIVE_MUSIC") != NULL);
401
	}
402
	if ( native_midi_ok )
403
#endif
404
		native_midi_ok = native_midi_detect();
405
	if ( native_midi_ok )
406
		add_music_decoder("NATIVEMIDI");
407
#endif
408
#endif
409
#ifdef OGG_MUSIC
410
	if ( OGG_init(mixer) == 0 ) {
411
		add_music_decoder("OGG");
412
	}
413
#endif
414
#ifdef FLAC_MUSIC
415
	if ( FLAC_init(mixer) == 0 ) {
416
		add_music_decoder("FLAC");
417
	}
418
#endif
419
#if defined(MP3_MUSIC) || defined(MP3_MAD_MUSIC)
420
	/* Keep a copy of the mixer */
421
	used_mixer = *mixer;
422
	add_music_decoder("MP3");
423
#endif
424
 
425
	music_playing = NULL;
426
	music_stopped = 0;
427
	Mix_VolumeMusic(SDL_MIX_MAXVOLUME);
428
 
429
	/* Calculate the number of ms for each callback */
430
	ms_per_step = (int) (((float)mixer->samples * 1000.0) / mixer->freq);
431
 
432
	return(0);
433
}
434
 
435
/* Portable case-insensitive string compare function */
436
int MIX_string_equals(const char *str1, const char *str2)
437
{
438
	while ( *str1 && *str2 ) {
439
		if ( toupper((unsigned char)*str1) !=
440
		     toupper((unsigned char)*str2) )
441
			break;
442
		++str1;
443
		++str2;
444
	}
445
	return (!*str1 && !*str2);
446
}
447
 
448
static int detect_mp3(Uint8 *magic)
449
{
450
	if ( strncmp((char *)magic, "ID3", 3) == 0 ) {
451
		return 1;
452
	}
453
 
454
	/* Detection code lifted from SMPEG */
455
	if(((magic[0] & 0xff) != 0xff) || // No sync bits
456
	   ((magic[1] & 0xf0) != 0xf0) || //
457
	   ((magic[2] & 0xf0) == 0x00) || // Bitrate is 0
458
	   ((magic[2] & 0xf0) == 0xf0) || // Bitrate is 15
459
	   ((magic[2] & 0x0c) == 0x0c) || // Frequency is 3
460
	   ((magic[1] & 0x06) == 0x00)) { // Layer is 4
461
		return(0);
462
	}
463
	return 1;
464
}
465
 
466
/* MUS_MOD can't be auto-detected. If no other format was detected, MOD is
467
 * assumed and MUS_MOD will be returned, meaning that the format might not
468
 * actually be MOD-based.
469
 *
470
 * Returns MUS_NONE in case of errors. */
471
static Mix_MusicType detect_music_type(SDL_RWops *rw)
472
{
473
	Uint8 magic[5];
474
	Uint8 moremagic[9];
475
 
476
	int start = SDL_RWtell(rw);
477
	if (SDL_RWread(rw, magic, 1, 4) != 4 || SDL_RWread(rw, moremagic, 1, 8) != 8 ) {
478
		Mix_SetError("Couldn't read from RWops");
479
		return MUS_NONE;
480
	}
481
	SDL_RWseek(rw, start, RW_SEEK_SET);
482
	magic[4]='\0';
483
	moremagic[8] = '\0';
484
 
485
	/* WAVE files have the magic four bytes "RIFF"
486
	   AIFF files have the magic 12 bytes "FORM" XXXX "AIFF" */
487
	if (((strcmp((char *)magic, "RIFF") == 0) && (strcmp((char *)(moremagic+4), "WAVE") == 0)) ||
488
		(strcmp((char *)magic, "FORM") == 0)) {
489
		return MUS_WAV;
490
	}
491
 
492
	/* Ogg Vorbis files have the magic four bytes "OggS" */
493
	if (strcmp((char *)magic, "OggS") == 0) {
494
		return MUS_OGG;
495
	}
496
 
497
	/* FLAC files have the magic four bytes "fLaC" */
498
	if (strcmp((char *)magic, "fLaC") == 0) {
499
		return MUS_FLAC;
500
	}
501
 
502
	/* MIDI files have the magic four bytes "MThd" */
503
	if (strcmp((char *)magic, "MThd") == 0) {
504
		return MUS_MID;
505
	}
506
 
507
	if (detect_mp3(magic)) {
508
		return MUS_MP3;
509
	}
510
 
511
	/* Assume MOD format.
512
	 *
513
	 * Apparently there is no way to check if the file is really a MOD,
514
	 * or there are too many formats supported by MikMod/ModPlug, or
515
	 * MikMod/ModPlug does this check by itself. */
516
	return MUS_MOD;
517
}
518
 
519
/* Load a music file */
520
Mix_Music *Mix_LoadMUS(const char *file)
521
{
522
	SDL_RWops *rw;
523
	Mix_Music *music;
524
	Mix_MusicType type;
525
	char *ext = strrchr(file, '.');
526
 
527
#ifdef CMD_MUSIC
528
	if ( music_cmd ) {
529
		/* Allocate memory for the music structure */
530
		music = (Mix_Music *)SDL_malloc(sizeof(Mix_Music));
531
		if ( music == NULL ) {
532
			Mix_SetError("Out of memory");
533
			return(NULL);
534
		}
535
		music->error = 0;
536
		music->type = MUS_CMD;
537
		music->data.cmd = MusicCMD_LoadSong(music_cmd, file);
538
		if ( music->data.cmd == NULL ) {
539
			SDL_free(music);
540
			music == NULL;
541
		}
542
		return music;
543
	}
544
#endif
545
 
546
	rw = SDL_RWFromFile(file, "rb");
547
	if ( rw == NULL ) {
548
		Mix_SetError("Couldn't open '%s'", file);
549
		return NULL;
550
	}
551
 
552
	/* Use the extension as a first guess on the file type */
553
	type = MUS_NONE;
554
	ext = strrchr(file, '.');
555
	/* No need to guard these with #ifdef *_MUSIC stuff,
556
	 * since we simply call Mix_LoadMUSType_RW() later */
557
	if ( ext ) {
558
		++ext; /* skip the dot in the extension */
559
		if ( MIX_string_equals(ext, "WAV") ) {
560
			type = MUS_WAV;
561
		} else if ( MIX_string_equals(ext, "MID") ||
562
		            MIX_string_equals(ext, "MIDI") ||
563
		            MIX_string_equals(ext, "KAR") ) {
564
			type = MUS_MID;
565
		} else if ( MIX_string_equals(ext, "OGG") ) {
566
			type = MUS_OGG;
567
		} else if ( MIX_string_equals(ext, "FLAC") ) {
568
			type = MUS_FLAC;
569
		} else 	if ( MIX_string_equals(ext, "MPG") ||
570
		             MIX_string_equals(ext, "MPEG") ||
571
		             MIX_string_equals(ext, "MP3") ||
572
		             MIX_string_equals(ext, "MAD") ) {
573
			type = MUS_MP3;
574
		}
575
	}
576
	if ( type == MUS_NONE ) {
577
		type = detect_music_type(rw);
578
	}
579
 
580
	/* We need to know if a specific error occurs; if not, we'll set a
581
	 * generic one, so we clear the current one. */
582
	Mix_SetError("");
583
	music = Mix_LoadMUSType_RW(rw, type, SDL_TRUE);
584
	if ( music == NULL && Mix_GetError()[0] == '\0' ) {
585
		SDL_FreeRW(rw);
586
		Mix_SetError("Couldn't open '%s'", file);
587
	}
588
	return music;
589
}
590
 
591
Mix_Music *Mix_LoadMUS_RW(SDL_RWops *rw)
592
{
593
	return Mix_LoadMUSType_RW(rw, MUS_NONE, SDL_FALSE);
594
}
595
 
596
Mix_Music *Mix_LoadMUSType_RW(SDL_RWops *rw, Mix_MusicType type, int freesrc)
597
{
598
	Mix_Music *music;
599
 
600
	if (!rw) {
601
		Mix_SetError("RWops pointer is NULL");
602
		return NULL;
603
	}
604
 
605
	/* If the caller wants auto-detection, figure out what kind of file
606
	 * this is. */
607
	if (type == MUS_NONE) {
608
		if ((type = detect_music_type(rw)) == MUS_NONE) {
609
			/* Don't call Mix_SetError() here since detect_music_type()
610
			 * does that. */
611
			return NULL;
612
		}
613
	}
614
 
615
	/* Allocate memory for the music structure */
616
	music = (Mix_Music *)SDL_malloc(sizeof(Mix_Music));
617
	if (music == NULL ) {
618
		Mix_SetError("Out of memory");
619
		return NULL;
620
	}
621
	music->error = 0;
622
 
623
	switch (type) {
624
#ifdef WAV_MUSIC
625
	case MUS_WAV:
626
		/* The WAVE loader needs the first 4 bytes of the header */
627
		{
628
			Uint8 magic[5];
629
			int start = SDL_RWtell(rw);
630
			if (SDL_RWread(rw, magic, 1, 4) != 4) {
631
				Mix_SetError("Couldn't read from RWops");
632
				return MUS_NONE;
633
			}
634
			SDL_RWseek(rw, start, RW_SEEK_SET);
635
			magic[4] = '\0';
636
			music->type = MUS_WAV;
637
			music->data.wave = WAVStream_LoadSong_RW(rw, (char *)magic, freesrc);
638
		}
639
		if (music->data.wave == NULL) {
640
			music->error = 1;
641
		}
642
		break;
643
#endif
644
#ifdef OGG_MUSIC
645
	case MUS_OGG:
646
		music->type = MUS_OGG;
647
		music->data.ogg = OGG_new_RW(rw, freesrc);
648
		if ( music->data.ogg == NULL ) {
649
			music->error = 1;
650
		}
651
		break;
652
#endif
653
#ifdef FLAC_MUSIC
654
	case MUS_FLAC:
655
		music->type = MUS_FLAC;
656
		music->data.flac = FLAC_new_RW(rw, freesrc);
657
		if ( music->data.flac == NULL ) {
658
			music->error = 1;
659
		}
660
		break;
661
#endif
662
#ifdef MP3_MUSIC
663
	case MUS_MP3:
664
		if ( Mix_Init(MIX_INIT_MP3) ) {
665
			SMPEG_Info info;
666
			music->type = MUS_MP3;
667
			music->data.mp3 = smpeg.SMPEG_new_rwops(rw, &info, 0);
668
			if ( !info.has_audio ) {
669
				Mix_SetError("MPEG file does not have any audio stream.");
670
				music->error = 1;
671
			} else {
672
				smpeg.SMPEG_actualSpec(music->data.mp3, &used_mixer);
673
			}
674
		} else {
675
			music->error = 1;
676
		}
677
		break;
678
#elif defined(MP3_MAD_MUSIC)
679
	case MUS_MP3:
680
		music->type = MUS_MP3_MAD;
681
		music->data.mp3_mad = mad_openFileRW(rw, &used_mixer, freesrc);
682
		if (music->data.mp3_mad == 0) {
683
			Mix_SetError("Could not initialize MPEG stream.");
684
			music->error = 1;
685
		}
686
		break;
687
#endif
688
#ifdef MID_MUSIC
689
	case MUS_MID:
690
		music->type = MUS_MID;
691
#ifdef USE_NATIVE_MIDI
692
		if ( native_midi_ok ) {
693
			music->data.nativemidi = native_midi_loadsong_RW(rw, freesrc);
694
	  		if ( music->data.nativemidi == NULL ) {
695
		  		Mix_SetError("%s", native_midi_error());
696
			  	music->error = 1;
697
			}
698
			break;
699
		}
700
#endif
701
#ifdef USE_FLUIDSYNTH_MIDI
702
		if ( fluidsynth_ok ) {
703
			music->data.fluidsynthmidi = fluidsynth_loadsong_RW(rw, freesrc);
704
			if ( music->data.fluidsynthmidi == NULL ) {
705
				music->error = 1;
706
			}
707
			break;
708
		}
709
#endif
710
#ifdef USE_TIMIDITY_MIDI
711
		if ( timidity_ok ) {
712
			music->data.midi = Timidity_LoadSong_RW(rw, freesrc);
713
			if ( music->data.midi == NULL ) {
714
				Mix_SetError("%s", Timidity_Error());
715
				music->error = 1;
716
			}
717
		} else {
718
			Mix_SetError("%s", Timidity_Error());
719
			music->error = 1;
720
		}
721
#endif
722
		break;
723
#endif
724
#if defined(MODPLUG_MUSIC) || defined(MOD_MUSIC)
725
	case MUS_MOD:
726
		music->error = 1;
727
#ifdef MODPLUG_MUSIC
728
		if ( music->error ) {
729
			music->type = MUS_MODPLUG;
730
			music->data.modplug = modplug_new_RW(rw, freesrc);
731
			if ( music->data.modplug ) {
732
				music->error = 0;
733
			}
734
		}
735
#endif
736
#ifdef MOD_MUSIC
737
		if ( music->error ) {
738
			music->type = MUS_MOD;
739
			music->data.module = MOD_new_RW(rw, freesrc);
740
			if ( music->data.module ) {
741
				music->error = 0;
742
			}
743
		}
744
#endif
745
		break;
746
#endif
747
 
748
	default:
749
		Mix_SetError("Unrecognized music format");
750
		music->error=1;
751
	} /* switch (want) */
752
 
753
 
754
	if (music->error) {
755
		SDL_free(music);
756
		music=NULL;
757
	}
758
	return(music);
759
}
760
 
761
/* Free a music chunk previously loaded */
762
void Mix_FreeMusic(Mix_Music *music)
763
{
764
	if ( music ) {
765
		/* Stop the music if it's currently playing */
766
		SDL_LockAudio();
767
		if ( music == music_playing ) {
768
			/* Wait for any fade out to finish */
769
			while ( music->fading == MIX_FADING_OUT ) {
770
				SDL_UnlockAudio();
9097 turbocat 771
				uSDL_Delay(100);
8645 turbocat 772
				SDL_LockAudio();
773
			}
774
			if ( music == music_playing ) {
775
				music_internal_halt();
776
			}
777
		}
778
		SDL_UnlockAudio();
779
		switch (music->type) {
780
#ifdef CMD_MUSIC
781
			case MUS_CMD:
782
				MusicCMD_FreeSong(music->data.cmd);
783
				break;
784
#endif
785
#ifdef WAV_MUSIC
786
			case MUS_WAV:
787
				WAVStream_FreeSong(music->data.wave);
788
				break;
789
#endif
790
#ifdef MODPLUG_MUSIC
791
			case MUS_MODPLUG:
792
				modplug_delete(music->data.modplug);
793
				break;
794
#endif
795
#ifdef MOD_MUSIC
796
			case MUS_MOD:
797
				MOD_delete(music->data.module);
798
				break;
799
#endif
800
#ifdef MID_MUSIC
801
			case MUS_MID:
802
#ifdef USE_NATIVE_MIDI
803
  				if ( native_midi_ok ) {
804
					native_midi_freesong(music->data.nativemidi);
805
					goto skip;
806
				}
807
#endif
808
#ifdef USE_FLUIDSYNTH_MIDI
809
				if ( fluidsynth_ok ) {
810
					fluidsynth_freesong(music->data.fluidsynthmidi);
811
					goto skip;
812
				}
813
#endif
814
#ifdef USE_TIMIDITY_MIDI
815
				if ( timidity_ok ) {
816
					Timidity_FreeSong(music->data.midi);
817
					goto skip;
818
				}
819
#endif
820
				break;
821
#endif
822
#ifdef OGG_MUSIC
823
			case MUS_OGG:
824
				OGG_delete(music->data.ogg);
825
				break;
826
#endif
827
#ifdef FLAC_MUSIC
828
			case MUS_FLAC:
829
				FLAC_delete(music->data.flac);
830
				break;
831
#endif
832
#ifdef MP3_MUSIC
833
			case MUS_MP3:
834
				smpeg.SMPEG_delete(music->data.mp3);
835
				break;
836
#endif
837
#ifdef MP3_MAD_MUSIC
838
			case MUS_MP3_MAD:
839
				mad_closeFile(music->data.mp3_mad);
840
				break;
841
#endif
842
			default:
843
				/* Unknown music type?? */
844
				break;
845
		}
846
 
847
    skip:
848
		SDL_free(music);
849
	}
850
}
851
 
852
/* Find out the music format of a mixer music, or the currently playing
853
   music, if 'music' is NULL.
854
*/
855
Mix_MusicType Mix_GetMusicType(const Mix_Music *music)
856
{
857
	Mix_MusicType type = MUS_NONE;
858
 
859
	if ( music ) {
860
		type = music->type;
861
	} else {
862
		SDL_LockAudio();
863
		if ( music_playing ) {
864
			type = music_playing->type;
865
		}
866
		SDL_UnlockAudio();
867
	}
868
	return(type);
869
}
870
 
871
/* Play a music chunk.  Returns 0, or -1 if there was an error.
872
 */
873
static int music_internal_play(Mix_Music *music, double position)
874
{
875
	int retval = 0;
876
 
877
#if defined(__MACOSX__) && defined(USE_NATIVE_MIDI)
878
	/* This fixes a bug with native MIDI on Mac OS X, where you
879
	   can't really stop and restart MIDI from the audio callback.
880
	*/
881
	if ( music == music_playing && music->type == MUS_MID && native_midi_ok ) {
882
		/* Just a seek suffices to restart playing */
883
		music_internal_position(position);
884
		return 0;
885
	}
886
#endif
887
 
888
	/* Note the music we're playing */
889
	if ( music_playing ) {
890
		music_internal_halt();
891
	}
892
	music_playing = music;
893
 
894
	/* Set the initial volume */
895
	if ( music->type != MUS_MOD ) {
896
		music_internal_initialize_volume();
897
	}
898
 
899
	/* Set up for playback */
900
	switch (music->type) {
901
#ifdef CMD_MUSIC
902
	    case MUS_CMD:
903
		MusicCMD_Start(music->data.cmd);
904
		break;
905
#endif
906
#ifdef WAV_MUSIC
907
	    case MUS_WAV:
908
		WAVStream_Start(music->data.wave);
909
		break;
910
#endif
911
#ifdef MODPLUG_MUSIC
912
	    case MUS_MODPLUG:
913
		/* can't set volume until file is loaded, so finally set it now */
914
		music_internal_initialize_volume();
915
		modplug_play(music->data.modplug);
916
		break;
917
#endif
918
#ifdef MOD_MUSIC
919
	    case MUS_MOD:
920
		MOD_play(music->data.module);
921
		/* Player_SetVolume() does nothing before Player_Start() */
922
		music_internal_initialize_volume();
923
		break;
924
#endif
925
#ifdef MID_MUSIC
926
	    case MUS_MID:
927
#ifdef USE_NATIVE_MIDI
928
		if ( native_midi_ok ) {
929
			native_midi_start(music->data.nativemidi, music_loops);
930
			goto skip;
931
		}
932
#endif
933
#ifdef USE_FLUIDSYNTH_MIDI
934
		if (fluidsynth_ok ) {
935
			fluidsynth_start(music->data.fluidsynthmidi);
936
			goto skip;
937
		}
938
#endif
939
#ifdef USE_TIMIDITY_MIDI
940
		if ( timidity_ok ) {
941
			Timidity_Start(music->data.midi);
942
			goto skip;
943
		}
944
#endif
945
		break;
946
#endif
947
#ifdef OGG_MUSIC
948
	    case MUS_OGG:
949
		OGG_play(music->data.ogg);
950
		break;
951
#endif
952
#ifdef FLAC_MUSIC
953
	    case MUS_FLAC:
954
		FLAC_play(music->data.flac);
955
		break;
956
#endif
957
#ifdef MP3_MUSIC
958
	    case MUS_MP3:
959
		smpeg.SMPEG_enableaudio(music->data.mp3,1);
960
		smpeg.SMPEG_enablevideo(music->data.mp3,0);
961
		smpeg.SMPEG_play(music_playing->data.mp3);
962
		break;
963
#endif
964
#ifdef MP3_MAD_MUSIC
965
	    case MUS_MP3_MAD:
966
		mad_start(music->data.mp3_mad);
967
		break;
968
#endif
969
	    default:
970
		Mix_SetError("Can't play unknown music type");
971
		retval = -1;
972
		break;
973
	}
974
 
975
skip:
976
	/* Set the playback position, note any errors if an offset is used */
977
	if ( retval == 0 ) {
978
		if ( position > 0.0 ) {
979
			if ( music_internal_position(position) < 0 ) {
980
				Mix_SetError("Position not implemented for music type");
981
				retval = -1;
982
			}
983
		} else {
984
			music_internal_position(0.0);
985
		}
986
	}
987
 
988
	/* If the setup failed, we're not playing any music anymore */
989
	if ( retval < 0 ) {
990
		music_playing = NULL;
991
	}
992
	return(retval);
993
}
994
int Mix_FadeInMusicPos(Mix_Music *music, int loops, int ms, double position)
995
{
996
	int retval;
997
 
998
	if ( ms_per_step == 0 ) {
999
		SDL_SetError("Audio device hasn't been opened");
1000
		return(-1);
1001
	}
1002
 
1003
	/* Don't play null pointers :-) */
1004
	if ( music == NULL ) {
1005
		Mix_SetError("music parameter was NULL");
1006
		return(-1);
1007
	}
1008
 
1009
	/* Setup the data */
1010
	if ( ms ) {
1011
		music->fading = MIX_FADING_IN;
1012
	} else {
1013
		music->fading = MIX_NO_FADING;
1014
	}
1015
	music->fade_step = 0;
1016
	music->fade_steps = ms/ms_per_step;
1017
 
1018
	/* Play the puppy */
1019
	SDL_LockAudio();
1020
	/* If the current music is fading out, wait for the fade to complete */
1021
	while ( music_playing && (music_playing->fading == MIX_FADING_OUT) ) {
1022
		SDL_UnlockAudio();
9097 turbocat 1023
		uSDL_Delay(100);
8645 turbocat 1024
		SDL_LockAudio();
1025
	}
1026
	music_active = 1;
1027
	if (loops == 1) {
1028
		/* Loop is the number of times to play the audio */
1029
		loops = 0;
1030
	}
1031
	music_loops = loops;
1032
	retval = music_internal_play(music, position);
1033
	SDL_UnlockAudio();
1034
 
1035
	return(retval);
1036
}
1037
int Mix_FadeInMusic(Mix_Music *music, int loops, int ms)
1038
{
1039
	return Mix_FadeInMusicPos(music, loops, ms, 0.0);
1040
}
1041
int Mix_PlayMusic(Mix_Music *music, int loops)
1042
{
1043
	return Mix_FadeInMusicPos(music, loops, 0, 0.0);
1044
}
1045
 
1046
/* Set the playing music position */
1047
int music_internal_position(double position)
1048
{
1049
	int retval = 0;
1050
 
1051
	switch (music_playing->type) {
1052
#ifdef MODPLUG_MUSIC
1053
	    case MUS_MODPLUG:
1054
		modplug_jump_to_time(music_playing->data.modplug, position);
1055
		break;
1056
#endif
1057
#ifdef MOD_MUSIC
1058
	    case MUS_MOD:
1059
		MOD_jump_to_time(music_playing->data.module, position);
1060
		break;
1061
#endif
1062
#ifdef OGG_MUSIC
1063
	    case MUS_OGG:
1064
		OGG_jump_to_time(music_playing->data.ogg, position);
1065
		break;
1066
#endif
1067
#ifdef FLAC_MUSIC
1068
	    case MUS_FLAC:
1069
		FLAC_jump_to_time(music_playing->data.flac, position);
1070
		break;
1071
#endif
1072
#ifdef MP3_MUSIC
1073
	    case MUS_MP3:
1074
		smpeg.SMPEG_rewind(music_playing->data.mp3);
1075
		smpeg.SMPEG_play(music_playing->data.mp3);
1076
		if ( position > 0.0 ) {
1077
			smpeg.SMPEG_skip(music_playing->data.mp3, (float)position);
1078
		}
1079
		break;
1080
#endif
1081
#ifdef MP3_MAD_MUSIC
1082
	    case MUS_MP3_MAD:
1083
		mad_seek(music_playing->data.mp3_mad, position);
1084
		break;
1085
#endif
1086
	    default:
1087
		/* TODO: Implement this for other music backends */
1088
		retval = -1;
1089
		break;
1090
	}
1091
	return(retval);
1092
}
1093
int Mix_SetMusicPosition(double position)
1094
{
1095
	int retval;
1096
 
1097
	SDL_LockAudio();
1098
	if ( music_playing ) {
1099
		retval = music_internal_position(position);
1100
		if ( retval < 0 ) {
1101
			Mix_SetError("Position not implemented for music type");
1102
		}
1103
	} else {
1104
		Mix_SetError("Music isn't playing");
1105
		retval = -1;
1106
	}
1107
	SDL_UnlockAudio();
1108
 
1109
	return(retval);
1110
}
1111
 
1112
/* Set the music's initial volume */
1113
static void music_internal_initialize_volume(void)
1114
{
1115
	if ( music_playing->fading == MIX_FADING_IN ) {
1116
		music_internal_volume(0);
1117
	} else {
1118
		music_internal_volume(music_volume);
1119
	}
1120
}
1121
 
1122
/* Set the music volume */
1123
static void music_internal_volume(int volume)
1124
{
1125
	switch (music_playing->type) {
1126
#ifdef CMD_MUSIC
1127
	    case MUS_CMD:
1128
		MusicCMD_SetVolume(volume);
1129
		break;
1130
#endif
1131
#ifdef WAV_MUSIC
1132
	    case MUS_WAV:
1133
		WAVStream_SetVolume(volume);
1134
		break;
1135
#endif
1136
#ifdef MODPLUG_MUSIC
1137
	    case MUS_MODPLUG:
1138
		modplug_setvolume(music_playing->data.modplug, volume);
1139
		break;
1140
#endif
1141
#ifdef MOD_MUSIC
1142
	    case MUS_MOD:
1143
		MOD_setvolume(music_playing->data.module, volume);
1144
		break;
1145
#endif
1146
#ifdef MID_MUSIC
1147
	    case MUS_MID:
1148
#ifdef USE_NATIVE_MIDI
1149
		if ( native_midi_ok ) {
1150
			native_midi_setvolume(volume);
1151
			return;
1152
		}
1153
#endif
1154
#ifdef USE_FLUIDSYNTH_MIDI
1155
		if ( fluidsynth_ok ) {
1156
			fluidsynth_setvolume(music_playing->data.fluidsynthmidi, volume);
1157
			return;
1158
		}
1159
#endif
1160
#ifdef USE_TIMIDITY_MIDI
1161
		if ( timidity_ok ) {
1162
			Timidity_SetVolume(volume);
1163
			return;
1164
		}
1165
#endif
1166
		break;
1167
#endif
1168
#ifdef OGG_MUSIC
1169
	    case MUS_OGG:
1170
		OGG_setvolume(music_playing->data.ogg, volume);
1171
		break;
1172
#endif
1173
#ifdef FLAC_MUSIC
1174
	    case MUS_FLAC:
1175
		FLAC_setvolume(music_playing->data.flac, volume);
1176
		break;
1177
#endif
1178
#ifdef MP3_MUSIC
1179
	    case MUS_MP3:
1180
		smpeg.SMPEG_setvolume(music_playing->data.mp3,(int)(((float)volume/(float)MIX_MAX_VOLUME)*100.0));
1181
		break;
1182
#endif
1183
#ifdef MP3_MAD_MUSIC
1184
	    case MUS_MP3_MAD:
1185
		mad_setVolume(music_playing->data.mp3_mad, volume);
1186
		break;
1187
#endif
1188
	    default:
1189
		/* Unknown music type?? */
1190
		break;
1191
	}
1192
}
1193
int Mix_VolumeMusic(int volume)
1194
{
1195
	int prev_volume;
1196
 
1197
	prev_volume = music_volume;
1198
	if ( volume < 0 ) {
1199
		return prev_volume;
1200
	}
1201
	if ( volume > SDL_MIX_MAXVOLUME ) {
1202
		volume = SDL_MIX_MAXVOLUME;
1203
	}
1204
	music_volume = volume;
1205
	SDL_LockAudio();
1206
	if ( music_playing ) {
1207
		music_internal_volume(music_volume);
1208
	}
1209
	SDL_UnlockAudio();
1210
	return(prev_volume);
1211
}
1212
 
1213
/* Halt playing of music */
1214
static void music_internal_halt(void)
1215
{
1216
	switch (music_playing->type) {
1217
#ifdef CMD_MUSIC
1218
	    case MUS_CMD:
1219
		MusicCMD_Stop(music_playing->data.cmd);
1220
		break;
1221
#endif
1222
#ifdef WAV_MUSIC
1223
	    case MUS_WAV:
1224
		WAVStream_Stop();
1225
		break;
1226
#endif
1227
#ifdef MODPLUG_MUSIC
1228
	    case MUS_MODPLUG:
1229
		modplug_stop(music_playing->data.modplug);
1230
		break;
1231
#endif
1232
#ifdef MOD_MUSIC
1233
	    case MUS_MOD:
1234
		MOD_stop(music_playing->data.module);
1235
		break;
1236
#endif
1237
#ifdef MID_MUSIC
1238
	    case MUS_MID:
1239
#ifdef USE_NATIVE_MIDI
1240
		if ( native_midi_ok ) {
1241
			native_midi_stop();
1242
			goto skip;
1243
		}
1244
#endif
1245
#ifdef USE_FLUIDSYNTH_MIDI
1246
		if ( fluidsynth_ok ) {
1247
			fluidsynth_stop(music_playing->data.fluidsynthmidi);
1248
			goto skip;
1249
		}
1250
#endif
1251
#ifdef USE_TIMIDITY_MIDI
1252
		if ( timidity_ok ) {
1253
			Timidity_Stop();
1254
			goto skip;
1255
		}
1256
#endif
1257
		break;
1258
#endif
1259
#ifdef OGG_MUSIC
1260
	    case MUS_OGG:
1261
		OGG_stop(music_playing->data.ogg);
1262
		break;
1263
#endif
1264
#ifdef FLAC_MUSIC
1265
	    case MUS_FLAC:
1266
		FLAC_stop(music_playing->data.flac);
1267
		break;
1268
#endif
1269
#ifdef MP3_MUSIC
1270
	    case MUS_MP3:
1271
		smpeg.SMPEG_stop(music_playing->data.mp3);
1272
		break;
1273
#endif
1274
#ifdef MP3_MAD_MUSIC
1275
	    case MUS_MP3_MAD:
1276
		mad_stop(music_playing->data.mp3_mad);
1277
		break;
1278
#endif
1279
	    default:
1280
		/* Unknown music type?? */
1281
		return;
1282
	}
1283
 
1284
skip:
1285
	music_playing->fading = MIX_NO_FADING;
1286
	music_playing = NULL;
1287
}
1288
int Mix_HaltMusic(void)
1289
{
1290
	SDL_LockAudio();
1291
	if ( music_playing ) {
1292
		music_internal_halt();
1293
	}
1294
	SDL_UnlockAudio();
1295
 
1296
	return(0);
1297
}
1298
 
1299
/* Progressively stop the music */
1300
int Mix_FadeOutMusic(int ms)
1301
{
1302
	int retval = 0;
1303
 
1304
	if ( ms_per_step == 0 ) {
1305
		SDL_SetError("Audio device hasn't been opened");
1306
		return 0;
1307
	}
1308
 
1309
	if (ms <= 0) {  /* just halt immediately. */
1310
		Mix_HaltMusic();
1311
		return 1;
1312
	}
1313
 
1314
	SDL_LockAudio();
1315
	if ( music_playing) {
1316
                int fade_steps = (ms + ms_per_step - 1)/ms_per_step;
1317
                if ( music_playing->fading == MIX_NO_FADING ) {
1318
	        	music_playing->fade_step = 0;
1319
                } else {
1320
                        int step;
1321
                        int old_fade_steps = music_playing->fade_steps;
1322
                        if ( music_playing->fading == MIX_FADING_OUT ) {
1323
                                step = music_playing->fade_step;
1324
                        } else {
1325
                                step = old_fade_steps
1326
                                        - music_playing->fade_step + 1;
1327
                        }
1328
                        music_playing->fade_step = (step * fade_steps)
1329
                                / old_fade_steps;
1330
                }
1331
		music_playing->fading = MIX_FADING_OUT;
1332
		music_playing->fade_steps = fade_steps;
1333
		retval = 1;
1334
	}
1335
	SDL_UnlockAudio();
1336
 
1337
	return(retval);
1338
}
1339
 
1340
Mix_Fading Mix_FadingMusic(void)
1341
{
1342
	Mix_Fading fading = MIX_NO_FADING;
1343
 
1344
	SDL_LockAudio();
1345
	if ( music_playing ) {
1346
		fading = music_playing->fading;
1347
	}
1348
	SDL_UnlockAudio();
1349
 
1350
	return(fading);
1351
}
1352
 
1353
/* Pause/Resume the music stream */
1354
void Mix_PauseMusic(void)
1355
{
1356
	music_active = 0;
1357
}
1358
 
1359
void Mix_ResumeMusic(void)
1360
{
1361
	music_active = 1;
1362
}
1363
 
1364
void Mix_RewindMusic(void)
1365
{
1366
	Mix_SetMusicPosition(0.0);
1367
}
1368
 
1369
int Mix_PausedMusic(void)
1370
{
1371
	return (music_active == 0);
1372
}
1373
 
1374
/* Check the status of the music */
1375
static int music_internal_playing()
1376
{
1377
	int playing = 1;
1378
 
1379
	if (music_playing == NULL) {
1380
		return 0;
1381
	}
1382
 
1383
	switch (music_playing->type) {
1384
#ifdef CMD_MUSIC
1385
	    case MUS_CMD:
1386
		if (!MusicCMD_Active(music_playing->data.cmd)) {
1387
			playing = 0;
1388
		}
1389
		break;
1390
#endif
1391
#ifdef WAV_MUSIC
1392
	    case MUS_WAV:
1393
		if ( ! WAVStream_Active() ) {
1394
			playing = 0;
1395
		}
1396
		break;
1397
#endif
1398
#ifdef MODPLUG_MUSIC
1399
	    case MUS_MODPLUG:
1400
		if ( ! modplug_playing(music_playing->data.modplug) ) {
1401
			playing = 0;
1402
		}
1403
		break;
1404
#endif
1405
#ifdef MOD_MUSIC
1406
	    case MUS_MOD:
1407
		if ( ! MOD_playing(music_playing->data.module) ) {
1408
			playing = 0;
1409
		}
1410
		break;
1411
#endif
1412
#ifdef MID_MUSIC
1413
	    case MUS_MID:
1414
#ifdef USE_NATIVE_MIDI
1415
		if ( native_midi_ok ) {
1416
			if ( ! native_midi_active() )
1417
				playing = 0;
1418
			goto skip;
1419
		}
1420
#endif
1421
#ifdef USE_FLUIDSYNTH_MIDI
1422
		if ( fluidsynth_ok ) {
1423
			if ( ! fluidsynth_active(music_playing->data.fluidsynthmidi) )
1424
				playing = 0;
1425
			goto skip;
1426
		}
1427
#endif
1428
#ifdef USE_TIMIDITY_MIDI
1429
		if ( timidity_ok ) {
1430
			if ( ! Timidity_Active() )
1431
				playing = 0;
1432
			goto skip;
1433
		}
1434
#endif
1435
		break;
1436
#endif
1437
#ifdef OGG_MUSIC
1438
	    case MUS_OGG:
1439
		if ( ! OGG_playing(music_playing->data.ogg) ) {
1440
			playing = 0;
1441
		}
1442
		break;
1443
#endif
1444
#ifdef FLAC_MUSIC
1445
	    case MUS_FLAC:
1446
		if ( ! FLAC_playing(music_playing->data.flac) ) {
1447
			playing = 0;
1448
		}
1449
		break;
1450
#endif
1451
#ifdef MP3_MUSIC
1452
	    case MUS_MP3:
1453
		if ( smpeg.SMPEG_status(music_playing->data.mp3) != SMPEG_PLAYING )
1454
			playing = 0;
1455
		break;
1456
#endif
1457
#ifdef MP3_MAD_MUSIC
1458
	    case MUS_MP3_MAD:
1459
		if (!mad_isPlaying(music_playing->data.mp3_mad)) {
1460
			playing = 0;
1461
		}
1462
		break;
1463
#endif
1464
	    default:
1465
		playing = 0;
1466
		break;
1467
	}
1468
 
1469
skip:
1470
	return(playing);
1471
}
1472
int Mix_PlayingMusic(void)
1473
{
1474
	int playing = 0;
1475
 
1476
	SDL_LockAudio();
1477
	if ( music_playing ) {
1478
		playing = music_loops || music_internal_playing();
1479
	}
1480
	SDL_UnlockAudio();
1481
 
1482
	return(playing);
1483
}
1484
 
1485
/* Set the external music playback command */
1486
int Mix_SetMusicCMD(const char *command)
1487
{
1488
	Mix_HaltMusic();
1489
	if ( music_cmd ) {
1490
		SDL_free(music_cmd);
1491
		music_cmd = NULL;
1492
	}
1493
	if ( command ) {
1494
		music_cmd = (char *)SDL_malloc(strlen(command)+1);
1495
		if ( music_cmd == NULL ) {
1496
			return(-1);
1497
		}
1498
		strcpy(music_cmd, command);
1499
	}
1500
	return(0);
1501
}
1502
 
1503
int Mix_SetSynchroValue(int i)
1504
{
1505
	/* Not supported by any players at this time */
1506
	return(-1);
1507
}
1508
 
1509
int Mix_GetSynchroValue(void)
1510
{
1511
	/* Not supported by any players at this time */
1512
	return(-1);
1513
}
1514
 
1515
 
1516
/* Uninitialize the music players */
1517
void close_music(void)
1518
{
1519
	Mix_HaltMusic();
1520
#ifdef CMD_MUSIC
1521
	Mix_SetMusicCMD(NULL);
1522
#endif
1523
#ifdef MODPLUG_MUSIC
1524
	modplug_exit();
1525
#endif
1526
#ifdef MOD_MUSIC
1527
	MOD_exit();
1528
#endif
1529
#ifdef MID_MUSIC
1530
# ifdef USE_TIMIDITY_MIDI
1531
	Timidity_Close();
1532
# endif
1533
#endif
1534
 
1535
	/* rcg06042009 report available decoders at runtime. */
1536
	SDL_free(music_decoders);
1537
	music_decoders = NULL;
1538
	num_decoders = 0;
1539
 
1540
	ms_per_step = 0;
1541
}
1542
 
1543
int Mix_SetSoundFonts(const char *paths)
1544
{
1545
#ifdef MID_MUSIC
1546
	if (soundfont_paths) {
1547
		SDL_free(soundfont_paths);
1548
		soundfont_paths = NULL;
1549
	}
1550
 
1551
	if (paths) {
1552
		if (!(soundfont_paths = SDL_strdup(paths))) {
1553
			Mix_SetError("Insufficient memory to set SoundFonts");
1554
			return 0;
1555
		}
1556
	}
1557
#endif
1558
	return 1;
1559
}
1560
 
1561
#ifdef MID_MUSIC
1562
const char* Mix_GetSoundFonts(void)
1563
{
1564
	const char* force = getenv("SDL_FORCE_SOUNDFONTS");
1565
 
1566
	if (!soundfont_paths || (force && force[0] == '1')) {
1567
		return getenv("SDL_SOUNDFONTS");
1568
	} else {
1569
		return soundfont_paths;
1570
	}
1571
}
1572
 
1573
int Mix_EachSoundFont(int (*function)(const char*, void*), void *data)
1574
{
1575
	char *context, *path, *paths;
1576
	const char* cpaths = Mix_GetSoundFonts();
1577
 
1578
	if (!cpaths) {
1579
		Mix_SetError("No SoundFonts have been requested");
1580
		return 0;
1581
	}
1582
 
1583
	if (!(paths = SDL_strdup(cpaths))) {
1584
		Mix_SetError("Insufficient memory to iterate over SoundFonts");
1585
		return 0;
1586
	}
1587
 
1588
#if defined(__MINGW32__) || defined(__MINGW64__)
1589
	for (path = strtok(paths, ";"); path; path = strtok(NULL, ";")) {
1590
#elif defined(_WIN32)
1591
	for (path = strtok_s(paths, ";", &context); path; path = strtok_s(NULL, ";", &context)) {
1592
#else
1593
	for (path = strtok_r(paths, ":;", &context); path; path = strtok_r(NULL, ":;", &context)) {
1594
#endif
1595
		if (!function(path, data)) {
1596
			SDL_free(paths);
1597
			return 0;
1598
		}
1599
	}
1600
 
1601
	SDL_free(paths);
1602
	return 1;
1603
}
1604
#endif