From 23ce1b19abc4b8125ff4bb74cd687b560f444e8a Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Fri, 12 May 2006 09:42:24 +0000 Subject: [PATCH] Added support for dynamically loading SMPEG library --- configure.in | 5 +- dynamic_mp3.c | 180 ++++++++++++++++++++++++++++++++++++++++++++++++++ dynamic_mp3.h | 49 ++++++++++++++ dynamic_ogg.c | 2 + music.c | 61 +++++++++-------- 5 files changed, 269 insertions(+), 28 deletions(-) create mode 100644 dynamic_mp3.c create mode 100644 dynamic_mp3.h diff --git a/configure.in b/configure.in index 70627cdb..017c88dd 100644 --- a/configure.in +++ b/configure.in @@ -265,8 +265,8 @@ if test x$enable_music_mp3 = xyes; then AM_PATH_SMPEG($SMPEG_VERSION, have_smpeg=yes, have_smpeg=no) if test x$have_smpeg = xyes; then AC_ARG_ENABLE([music-mp3-shared], -AC_HELP_STRING([--enable-music-mp3-shared], [dynamically load MP3 support [[default=no]]]), - [], [enable_music_mp3_shared=no]) +AC_HELP_STRING([--enable-music-mp3-shared], [dynamically load MP3 support [[default=yes]]]), + [], [enable_music_mp3_shared=yes]) case "$host" in *-*-darwin*) smpeg_lib='' @@ -282,6 +282,7 @@ AC_HELP_STRING([--enable-music-mp3-shared], [dynamically load MP3 support [[defa done ;; esac + SOURCES="$SOURCES $srcdir/*_mp3.c" EXTRA_CFLAGS="$EXTRA_CFLAGS -DMP3_MUSIC $SMPEG_CFLAGS" if test x$enable_music_mp3_shared = xyes && test x$smpeg_lib != x; then echo "-- dynamic libsmpeg -> $smpeg_lib" diff --git a/dynamic_mp3.c b/dynamic_mp3.c new file mode 100644 index 00000000..2ffcf6c7 --- /dev/null +++ b/dynamic_mp3.c @@ -0,0 +1,180 @@ +/* + SDL_mixer: An audio mixer library based on the SDL library + Copyright (C) 1997-2004 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ + +#ifdef MP3_MUSIC + +#include "SDL_loadso.h" + +#include "dynamic_mp3.h" + +smpeg_loader smpeg = { + 0, NULL +}; + +#ifdef MP3_DYNAMIC +int Mix_InitMP3() +{ + if ( smpeg.loaded == 0 ) { + smpeg.handle = SDL_LoadObject(MP3_DYNAMIC); + if ( smpeg.handle == NULL ) { + return -1; + } + smpeg.SMPEG_actualSpec = + (void (*)( SMPEG *, SDL_AudioSpec * )) + SDL_LoadFunction(smpeg.handle, "SMPEG_actualSpec"); + if ( smpeg.SMPEG_actualSpec == NULL ) { + SDL_UnloadObject(smpeg.handle); + return -1; + } + smpeg.SMPEG_delete = + (void (*)( SMPEG* )) + SDL_LoadFunction(smpeg.handle, "SMPEG_delete"); + if ( smpeg.SMPEG_delete == NULL ) { + SDL_UnloadObject(smpeg.handle); + return -1; + } + smpeg.SMPEG_enableaudio = + (void (*)( SMPEG*, int )) + SDL_LoadFunction(smpeg.handle, "SMPEG_enableaudio"); + if ( smpeg.SMPEG_enableaudio == NULL ) { + SDL_UnloadObject(smpeg.handle); + return -1; + } + smpeg.SMPEG_enablevideo = + (void (*)( SMPEG*, int )) + SDL_LoadFunction(smpeg.handle, "SMPEG_enablevideo"); + if ( smpeg.SMPEG_enablevideo == NULL ) { + SDL_UnloadObject(smpeg.handle); + return -1; + } + smpeg.SMPEG_new = + (SMPEG* (*)(const char *, SMPEG_Info*, int)) + SDL_LoadFunction(smpeg.handle, "SMPEG_new"); + if ( smpeg.SMPEG_new == NULL ) { + SDL_UnloadObject(smpeg.handle); + return -1; + } + smpeg.SMPEG_new_rwops = + (SMPEG* (*)(SDL_RWops *, SMPEG_Info*, int)) + SDL_LoadFunction(smpeg.handle, "SMPEG_new_rwops"); + if ( smpeg.SMPEG_new_rwops == NULL ) { + SDL_UnloadObject(smpeg.handle); + return -1; + } + smpeg.SMPEG_play = + (void (*)( SMPEG* )) + SDL_LoadFunction(smpeg.handle, "SMPEG_play"); + if ( smpeg.SMPEG_play == NULL ) { + SDL_UnloadObject(smpeg.handle); + return -1; + } + smpeg.SMPEG_playAudio = + (int (*)( SMPEG *, Uint8 *, int )) + SDL_LoadFunction(smpeg.handle, "SMPEG_playAudio"); + if ( smpeg.SMPEG_playAudio == NULL ) { + SDL_UnloadObject(smpeg.handle); + return -1; + } + smpeg.SMPEG_rewind = + (void (*)( SMPEG* )) + SDL_LoadFunction(smpeg.handle, "SMPEG_rewind"); + if ( smpeg.SMPEG_rewind == NULL ) { + SDL_UnloadObject(smpeg.handle); + return -1; + } + smpeg.SMPEG_setvolume = + (void (*)( SMPEG*, int )) + SDL_LoadFunction(smpeg.handle, "SMPEG_setvolume"); + if ( smpeg.SMPEG_setvolume == NULL ) { + SDL_UnloadObject(smpeg.handle); + return -1; + } + smpeg.SMPEG_skip = + (void (*)( SMPEG*, float )) + SDL_LoadFunction(smpeg.handle, "SMPEG_skip"); + if ( smpeg.SMPEG_skip == NULL ) { + SDL_UnloadObject(smpeg.handle); + return -1; + } + smpeg.SMPEG_status = + (SMPEGstatus (*)( SMPEG* )) + SDL_LoadFunction(smpeg.handle, "SMPEG_status"); + if ( smpeg.SMPEG_status == NULL ) { + SDL_UnloadObject(smpeg.handle); + return -1; + } + smpeg.SMPEG_stop = + (void (*)( SMPEG* )) + SDL_LoadFunction(smpeg.handle, "SMPEG_stop"); + if ( smpeg.SMPEG_stop == NULL ) { + SDL_UnloadObject(smpeg.handle); + return -1; + } + } + ++smpeg.loaded; + + return 0; +} +void Mix_QuitMP3() +{ + if ( smpeg.loaded == 0 ) { + return; + } + if ( smpeg.loaded == 1 ) { + SDL_UnloadObject(smpeg.handle); + } + --smpeg.loaded; +} +#else +int Mix_InitMP3() +{ + if ( smpeg.loaded == 0 ) { + smpeg.SMPEG_actualSpec = SMPEG_actualSpec; + smpeg.SMPEG_delete = SMPEG_delete; + smpeg.SMPEG_enableaudio = SMPEG_enableaudio; + smpeg.SMPEG_enablevideo = SMPEG_enablevideo; + smpeg.SMPEG_new = SMPEG_new; + smpeg.SMPEG_new_rwops = SMPEG_new_rwops; + smpeg.SMPEG_play = SMPEG_play; + smpeg.SMPEG_playAudio = SMPEG_playAudio; + smpeg.SMPEG_rewind = SMPEG_rewind; + smpeg.SMPEG_setvolume = SMPEG_setvolume; + smpeg.SMPEG_skip = SMPEG_skip; + smpeg.SMPEG_status = SMPEG_status; + smpeg.SMPEG_stop = SMPEG_stop; + } + ++smpeg.loaded; + + return 0; +} +void Mix_QuitMP3() +{ + if ( smpeg.loaded == 0 ) { + return; + } + if ( smpeg.loaded == 1 ) { + } + --smpeg.loaded; +} +#endif /* MP3_DYNAMIC */ + +#endif /* MP3_MUSIC */ diff --git a/dynamic_mp3.h b/dynamic_mp3.h new file mode 100644 index 00000000..de51ff0f --- /dev/null +++ b/dynamic_mp3.h @@ -0,0 +1,49 @@ +/* + SDL_mixer: An audio mixer library based on the SDL library + Copyright (C) 1997-2004 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ + +#ifdef MP3_MUSIC +#include "smpeg.h" + +typedef struct { + int loaded; + void *handle; + void (*SMPEG_actualSpec)( SMPEG *mpeg, SDL_AudioSpec *spec ); + void (*SMPEG_delete)( SMPEG* mpeg ); + void (*SMPEG_enableaudio)( SMPEG* mpeg, int enable ); + void (*SMPEG_enablevideo)( SMPEG* mpeg, int enable ); + SMPEG* (*SMPEG_new)(const char *file, SMPEG_Info* info, int sdl_audio); + SMPEG* (*SMPEG_new_rwops)(SDL_RWops *src, SMPEG_Info* info, int sdl_audio); + void (*SMPEG_play)( SMPEG* mpeg ); + int (*SMPEG_playAudio)( SMPEG *mpeg, Uint8 *stream, int len ); + void (*SMPEG_rewind)( SMPEG* mpeg ); + void (*SMPEG_setvolume)( SMPEG* mpeg, int volume ); + void (*SMPEG_skip)( SMPEG* mpeg, float seconds ); + SMPEGstatus (*SMPEG_status)( SMPEG* mpeg ); + void (*SMPEG_stop)( SMPEG* mpeg ); +} smpeg_loader; + +extern smpeg_loader smpeg; + +extern int Mix_InitMP3(); +extern void Mix_QuitMP3(); + +#endif diff --git a/dynamic_ogg.c b/dynamic_ogg.c index 9adaf56e..ed85d8ba 100644 --- a/dynamic_ogg.c +++ b/dynamic_ogg.c @@ -115,6 +115,8 @@ int Mix_InitOgg() vorbis.ov_time_seek = ov_time_seek; } ++vorbis.loaded; + + return 0; } void Mix_QuitOgg() { diff --git a/music.c b/music.c index d710852f..f1c4ee83 100644 --- a/music.c +++ b/music.c @@ -84,7 +84,7 @@ #include "music_ogg.h" #endif #ifdef MP3_MUSIC -#include "smpeg.h" +#include "dynamic_mp3.h" static SDL_AudioSpec used_mixer; #endif @@ -338,7 +338,7 @@ void music_mixer(void *udata, Uint8 *stream, int len) #endif #ifdef MP3_MUSIC case MUS_MP3: - SMPEG_playAudio(music_playing->data.mp3, stream, len); + smpeg.SMPEG_playAudio(music_playing->data.mp3, stream, len); break; #endif default: @@ -593,14 +593,18 @@ Mix_Music *Mix_LoadMUS(const char *file) (ext && MIX_string_equals(ext, "MP3")) || (ext && MIX_string_equals(ext, "MPEG")) || (magic[0] == 0xFF && (magic[1] & 0xF0) == 0xF0) ) { - SMPEG_Info info; - music->type = MUS_MP3; - music->data.mp3 = SMPEG_new(file, &info, 0); - if ( !info.has_audio ) { - Mix_SetError("MPEG file does not have any audio stream."); - music->error = 1; + if ( Mix_InitMP3() == 0 ) { + SMPEG_Info info; + music->type = MUS_MP3; + music->data.mp3 = smpeg.SMPEG_new(file, &info, 0); + if ( !info.has_audio ) { + Mix_SetError("MPEG file does not have any audio stream."); + music->error = 1; + } else { + smpeg.SMPEG_actualSpec(music->data.mp3, &used_mixer); + } } else { - SMPEG_actualSpec(music->data.mp3, &used_mixer); + music->error = 1; } } else #endif @@ -690,7 +694,8 @@ void Mix_FreeMusic(Mix_Music *music) #endif #ifdef MP3_MUSIC case MUS_MP3: - SMPEG_delete(music->data.mp3); + smpeg.SMPEG_delete(music->data.mp3); + Mix_QuitMP3(); break; #endif default: @@ -777,9 +782,9 @@ static int music_internal_play(Mix_Music *music, double position) #endif #ifdef MP3_MUSIC case MUS_MP3: - SMPEG_enableaudio(music->data.mp3,1); - SMPEG_enablevideo(music->data.mp3,0); - SMPEG_play(music_playing->data.mp3); + smpeg.SMPEG_enableaudio(music->data.mp3,1); + smpeg.SMPEG_enablevideo(music->data.mp3,0); + smpeg.SMPEG_play(music_playing->data.mp3); break; #endif default: @@ -868,10 +873,10 @@ int music_internal_position(double position) #ifdef MP3_MUSIC case MUS_MP3: if ( position > 0.0 ) { - SMPEG_skip(music_playing->data.mp3, (float)position); + smpeg.SMPEG_skip(music_playing->data.mp3, (float)position); } else { - SMPEG_rewind(music_playing->data.mp3); - SMPEG_play(music_playing->data.mp3); + smpeg.SMPEG_rewind(music_playing->data.mp3); + smpeg.SMPEG_play(music_playing->data.mp3); } break; #endif @@ -951,7 +956,7 @@ static void music_internal_volume(int volume) #endif #ifdef MP3_MUSIC case MUS_MP3: - SMPEG_setvolume(music_playing->data.mp3,(int)(((float)volume/(float)MIX_MAX_VOLUME)*100.0)); + smpeg.SMPEG_setvolume(music_playing->data.mp3,(int)(((float)volume/(float)MIX_MAX_VOLUME)*100.0)); break; #endif default: @@ -1019,7 +1024,7 @@ static void music_internal_halt(void) #endif #ifdef MP3_MUSIC case MUS_MP3: - SMPEG_stop(music_playing->data.mp3); + smpeg.SMPEG_stop(music_playing->data.mp3); break; #endif default: @@ -1161,7 +1166,7 @@ static int music_internal_playing() #endif #ifdef MP3_MUSIC case MUS_MP3: - if ( SMPEG_status(music_playing->data.mp3) != SMPEG_PLAYING ) + if ( smpeg.SMPEG_status(music_playing->data.mp3) != SMPEG_PLAYING ) playing = 0; break; #endif @@ -1388,14 +1393,18 @@ Mix_Music *Mix_LoadMUS_RW(SDL_RWops *rw) { #endif #ifdef MP3_MUSIC if ( magic[0] == 0xFF && (magic[1] & 0xF0) == 0xF0 ) { - SMPEG_Info info; - music->type = MUS_MP3; - music->data.mp3 = SMPEG_new_rwops(rw, &info, 0); - if ( !info.has_audio ) { - Mix_SetError("MPEG file does not have any audio stream."); - music->error = 1; + if ( Mix_InitMP3() == 0 ) { + SMPEG_Info info; + music->type = MUS_MP3; + music->data.mp3 = smpeg.SMPEG_new_rwops(rw, &info, 0); + if ( !info.has_audio ) { + Mix_SetError("MPEG file does not have any audio stream."); + music->error = 1; + } else { + smpeg.SMPEG_actualSpec(music->data.mp3, &used_mixer); + } } else { - SMPEG_actualSpec(music->data.mp3, &used_mixer); + music->error = 1; } } else #endif