Subversion Repositories Kolibri OS

Rev

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