/* otherwhise. NOP if the music is playing */ static int music_halt_or_loop (void) { /* Restart music if it has to loop */ if (!music_internal_playing()) { /* Restart music if it has to loop at a high level */ if (music_loops && --music_loops) { Mix_Fading current_fade = music_playing->fading; music_internal_play(music_playing, 0.0); music_playing->fading = current_fade; } else { music_internal_halt(); if (music_finished_hook) music_finished_hook(); return 0; } } return 1; }
/* otherwhise. NOP if the music is playing */ static int music_halt_or_loop (void) { /* Restart music if it has to loop */ if (!music_internal_playing()) { #ifdef USE_NATIVE_MIDI /* Native MIDI handles looping internally */ if (music_playing->type == MUS_MID && native_midi_ok) { music_loops = 0; } #endif /* Restart music if it has to loop at a high level */ if (music_loops) { Mix_Fading current_fade; --music_loops; current_fade = music_playing->fading; music_internal_play(music_playing, 0.0); music_playing->fading = current_fade; } else { music_internal_halt(); if (music_finished_hook) music_finished_hook(); return 0; } } return 1; }
int Mix_HaltMusic(void) { SDL_LockAudio(); if ( music_playing ) { music_internal_halt(); } SDL_UnlockAudio(); return(0); }
/* Mixing function */ void music_mixer(void *udata, Uint8 *stream, int len) { int left = 0; if ( music_playing && music_active ) { /* Handle fading */ if ( music_playing->fading != MIX_NO_FADING ) { if ( music_playing->fade_step++ < music_playing->fade_steps ) { int volume; int fade_step = music_playing->fade_step; int fade_steps = music_playing->fade_steps; if ( music_playing->fading == MIX_FADING_OUT ) { volume = (music_volume * (fade_steps-fade_step)) / fade_steps; } else { /* Fading in */ volume = (music_volume * fade_step) / fade_steps; } music_internal_volume(volume); } else { if ( music_playing->fading == MIX_FADING_OUT ) { music_internal_halt(); if ( music_finished_hook ) { music_finished_hook(); } return; } music_playing->fading = MIX_NO_FADING; } } if (music_halt_or_loop() == 0) return; switch (music_playing->type) { #ifdef CMD_MUSIC case MUS_CMD: /* The playing is done externally */ break; #endif #ifdef WAV_MUSIC case MUS_WAV: left = WAVStream_PlaySome(stream, len); break; #endif #ifdef MOD_MUSIC case MUS_MOD: left = MOD_playAudio(music_playing->data.module, stream, len); break; #endif #ifdef MID_MUSIC #ifdef USE_TIMIDITY_MIDI case MUS_MID: if ( timidity_ok ) { int samples = len / samplesize; Timidity_PlaySome(stream, samples); } break; #endif #endif #ifdef OGG_MUSIC case MUS_OGG: left = OGG_playAudio(music_playing->data.ogg, stream, len); break; #endif #ifdef FLAC_MUSIC case MUS_FLAC: left = FLAC_playAudio(music_playing->data.flac, stream, len); break; #endif #ifdef MP3_MUSIC case MUS_MP3: left = (len - smpeg.SMPEG_playAudio(music_playing->data.mp3, stream, len)); break; #endif #ifdef MP3_MAD_MUSIC case MUS_MP3_MAD: left = mad_getSamples(music_playing->data.mp3_mad, stream, len); break; #endif default: /* Unknown music type?? */ break; } } /* Handle seamless music looping */ if (left > 0 && left < len && music_halt_or_loop()) { music_mixer(udata, stream+(len-left), left); } }
/* Mixing function */ void music_mixer(void *udata, Uint8 *stream, int len) { Mix_Music *music_playing_aux = music_playing;//maks if ( music_playing_aux && music_active ) { /* Handle fading */ if ( music_playing_aux->fading != MIX_NO_FADING ) { if ( music_playing_aux->fade_step++ < music_playing_aux->fade_steps ) { int volume; int fade_step = music_playing_aux->fade_step; int fade_steps = music_playing_aux->fade_steps; if ( music_playing_aux->fading == MIX_FADING_OUT ) { volume = (music_volume * (fade_steps-fade_step)) / fade_steps; } else { /* Fading in */ volume = (music_volume * fade_step) / fade_steps; } music_internal_volume(volume); } else { if ( music_playing_aux->fading == MIX_FADING_OUT ) { music_internal_halt(); if ( music_finished_hook ) { music_finished_hook(); } return; } music_playing_aux->fading = MIX_NO_FADING; } } /* Restart music if it has to loop */ if ( !music_internal_playing() ) { /* Restart music if it has to loop at a high level */ if ( music_loops && --music_loops ) { Mix_Fading current_fade = music_playing_aux->fading; music_internal_play(music_playing_aux, 0.0); music_playing_aux->fading = current_fade; } else { music_internal_halt(); if ( music_finished_hook ) { music_finished_hook(); } return; } } switch (music_playing_aux->type) { #ifdef CMD_MUSIC case MUS_CMD: /* The playing is done externally */ break; #endif #ifdef WAV_MUSIC case MUS_WAV: WAVStream_PlaySome(stream, len); break; #endif #ifdef MOD_MUSIC case MUS_MOD: VC_WriteBytes((SBYTE *)stream, len); if ( music_swap8 ) { Uint8 *dst; int i; dst = stream; for ( i=len; i; --i ) { *dst++ ^= 0x80; } } else if ( music_swap16 ) { Uint8 *dst, tmp; int i; dst = stream; for ( i=(len/2); i; --i ) { tmp = dst[0]; dst[0] = dst[1]; dst[1] = tmp; dst += 2; } } break; #endif #ifdef MID_MUSIC #ifdef USE_TIMIDITY_MIDI case MUS_MID: if ( timidity_ok ) { int samples = len / samplesize; Timidity_PlaySome(stream, samples); } break; #endif #endif #ifdef OGG_MUSIC case MUS_OGG: OGG_playAudio(music_playing_aux->data.ogg, stream, len); break; #endif #ifdef MP3_MUSIC case MUS_MP3: //maks //SMPEG_playAudio(music_playing_aux->data.mp3, stream, len); { static Uint8 *mp3Buf = NULL; static int lenBuf = 0; int decoded; if(!mp3Buf || len > lenBuf) mp3Buf = realloc(mp3Buf, len); lenBuf = len; decoded = MAD_Decode(music_playing_aux->data.mp3, mp3Buf, len, used_mixer.channels); if(decoded > 0) { SDL_MixAudio(stream, mp3Buf, decoded, music_playing_aux->data.mp3->volume); } else { music_playing_aux->data.mp3->playing = 0; } } break; #endif default: /* Unknown music type?? */ break; } } }
/* Play a music chunk. Returns 0, or -1 if there was an error. */ static int music_internal_play(Mix_Music *music, double position) { int retval = 0; #if defined(__MACOSX__) && defined(USE_NATIVE_MIDI) /* This fixes a bug with native MIDI on Mac OS X, where you can't really stop and restart MIDI from the audio callback. */ if ( music == music_playing && music->type == MUS_MID && native_midi_ok ) { /* Just a seek suffices to restart playing */ music_internal_position(position); return 0; } #endif /* Note the music we're playing */ if ( music_playing ) { music_internal_halt(); } music_playing = music; /* Set the initial volume */ if ( music->type != MUS_MOD ) { music_internal_initialize_volume(); } /* Set up for playback */ switch (music->type) { #ifdef CMD_MUSIC case MUS_CMD: MusicCMD_Start(music->data.cmd); break; #endif #ifdef WAV_MUSIC case MUS_WAV: WAVStream_Start(music->data.wave); break; #endif #ifdef MODPLUG_MUSIC case MUS_MODPLUG: /* can't set volume until file is loaded, so finally set it now */ music_internal_initialize_volume(); modplug_play(music->data.modplug); break; #endif #ifdef MOD_MUSIC case MUS_MOD: MOD_play(music->data.module); /* Player_SetVolume() does nothing before Player_Start() */ music_internal_initialize_volume(); break; #endif #ifdef MID_MUSIC case MUS_MID: #ifdef USE_NATIVE_MIDI if ( native_midi_ok ) { native_midi_start(music->data.nativemidi, music_loops); goto skip; } #endif #ifdef USE_FLUIDSYNTH_MIDI if (fluidsynth_ok ) { fluidsynth_start(music->data.fluidsynthmidi); goto skip; } #endif #ifdef USE_TIMIDITY_MIDI if ( timidity_ok ) { Timidity_Start(music->data.midi); goto skip; } #endif break; #endif #ifdef OGG_MUSIC case MUS_OGG: OGG_play(music->data.ogg); break; #endif #ifdef FLAC_MUSIC case MUS_FLAC: FLAC_play(music->data.flac); break; #endif #ifdef MP3_MUSIC case MUS_MP3: smpeg.SMPEG_enableaudio(music->data.mp3,1); smpeg.SMPEG_enablevideo(music->data.mp3,0); smpeg.SMPEG_play(music_playing->data.mp3); break; #endif #ifdef MP3_MAD_MUSIC case MUS_MP3_MAD: mad_start(music->data.mp3_mad); break; #endif default: Mix_SetError("Can't play unknown music type"); retval = -1; break; } skip: /* Set the playback position, note any errors if an offset is used */ if ( retval == 0 ) { if ( position > 0.0 ) { if ( music_internal_position(position) < 0 ) { Mix_SetError("Position not implemented for music type"); retval = -1; } } else { music_internal_position(0.0); } } /* If the setup failed, we're not playing any music anymore */ if ( retval < 0 ) { music_playing = NULL; } return(retval); }
/* Free a music chunk previously loaded */ void Mix_FreeMusic(Mix_Music *music) { if ( music ) { /* Stop the music if it's currently playing */ SDL_LockAudio(); if ( music == music_playing ) { /* Wait for any fade out to finish */ while ( music->fading == MIX_FADING_OUT ) { SDL_UnlockAudio(); SDL_Delay(100); SDL_LockAudio(); } if ( music == music_playing ) { music_internal_halt(); } } SDL_UnlockAudio(); switch (music->type) { #ifdef CMD_MUSIC case MUS_CMD: MusicCMD_FreeSong(music->data.cmd); break; #endif #ifdef WAV_MUSIC case MUS_WAV: WAVStream_FreeSong(music->data.wave); break; #endif #ifdef MODPLUG_MUSIC case MUS_MODPLUG: modplug_delete(music->data.modplug); break; #endif #ifdef MOD_MUSIC case MUS_MOD: MOD_delete(music->data.module); break; #endif #ifdef MID_MUSIC case MUS_MID: #ifdef USE_NATIVE_MIDI if ( native_midi_ok ) { native_midi_freesong(music->data.nativemidi); goto skip; } #endif #ifdef USE_FLUIDSYNTH_MIDI if ( fluidsynth_ok ) { fluidsynth_freesong(music->data.fluidsynthmidi); goto skip; } #endif #ifdef USE_TIMIDITY_MIDI if ( timidity_ok ) { Timidity_FreeSong(music->data.midi); goto skip; } #endif break; #endif #ifdef OGG_MUSIC case MUS_OGG: OGG_delete(music->data.ogg); break; #endif #ifdef FLAC_MUSIC case MUS_FLAC: FLAC_delete(music->data.flac); break; #endif #ifdef MP3_MUSIC case MUS_MP3: smpeg.SMPEG_delete(music->data.mp3); break; #endif #ifdef MP3_MAD_MUSIC case MUS_MP3_MAD: mad_closeFile(music->data.mp3_mad); break; #endif default: /* Unknown music type?? */ break; } skip: SDL_free(music); } }