Subversion Repositories Kolibri OS

Rev

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