From 07a2880dc8afbdbd4235f1fd7ef4df687d8f113a Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Sun, 22 Aug 2004 07:55:14 +0000 Subject: [PATCH] Martin_Storsj? - Sun, 22 Aug 2004 02:21:14 +0300 (EEST) * Added SDL_RWops support for reading Ogg Vorbis files --- CHANGES | 2 ++ music.c | 26 +++++++++++++++++++------- music_ogg.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++ music_ogg.h | 3 +++ 4 files changed, 76 insertions(+), 7 deletions(-) diff --git a/CHANGES b/CHANGES index b348c05c..d13ed9d3 100644 --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,6 @@ 1.2.6: +Martin_Storsjö - Sun, 22 Aug 2004 02:21:14 +0300 (EEST) + * Added SDL_RWops support for reading Ogg Vorbis files Greg Lee - Wed, 14 Jul 2004 05:13:14 -1000 * Added 4 and 6 channel surround sound output support * Added support for RMID format MIDI files diff --git a/music.c b/music.c index fa7f0bb8..dccff920 100644 --- a/music.c +++ b/music.c @@ -1203,19 +1203,21 @@ void close_music(void) #ifdef USE_RWOPS Mix_Music *Mix_LoadMUS_RW(SDL_RWops *rw) { - /*Uint8 magic[5]; Apparently there is no way to check if the file is really a MOD,*/ - /* or there are too many formats supported by MikMod or MikMod does */ - /* this check by itself. If someone implements other formats (e.g. MP3) */ - /* the check can be uncommented */ + Uint8 magic[5]; /*Apparently there is no way to check if the file is really a MOD,*/ + /* or there are too many formats supported by MikMod or MikMod does */ + /* this check by itself. If someone implements other formats (e.g. MP3) */ + /* the check can be uncommented */ Mix_Music *music; + int start; - /* Just skip the check */ /* Figure out what kind of file this is */ - /*if (SDL_RWread(rw,magic,1,4)!=4) { + start = SDL_RWtell(rw); + if (SDL_RWread(rw,magic,1,4)!=4) { Mix_SetError("Couldn't read from RWops"); return NULL; } - magic[4]='\0';*/ + SDL_RWseek(rw, start, SEEK_SET); + magic[4]='\0'; /* Allocate memory for the music structure */ music=(Mix_Music *)malloc(sizeof(Mix_Music)); @@ -1225,6 +1227,16 @@ Mix_Music *Mix_LoadMUS_RW(SDL_RWops *rw) { } music->error = 0; +#ifdef OGG_MUSIC + /* Ogg Vorbis files have the magic four bytes "OggS" */ + if ( strcmp((char *)magic, "OggS") == 0 ) { + music->type = MUS_OGG; + music->data.ogg = OGG_new_RW(rw); + if ( music->data.ogg == NULL ) { + music->error = 1; + } + } else +#endif #ifdef MOD_MUSIC if (1) { music->type=MUS_MOD; diff --git a/music_ogg.c b/music_ogg.c index 7d61e745..40610733 100644 --- a/music_ogg.c +++ b/music_ogg.c @@ -83,6 +83,58 @@ OGG_music *OGG_new(const char *file) return(music); } + +static size_t sdl_read_func(void *ptr, size_t size, size_t nmemb, void *datasource) +{ + return SDL_RWread((SDL_RWops*)datasource, ptr, size, nmemb); +} + +static int sdl_seek_func(void *datasource, ogg_int64_t offset, int whence) +{ + return SDL_RWseek((SDL_RWops*)datasource, (int)offset, whence); +} + +static int sdl_close_func(void *datasource) +{ + return SDL_RWclose((SDL_RWops*)datasource); +} + +static long sdl_tell_func(void *datasource) +{ + return SDL_RWtell((SDL_RWops*)datasource); +} + +/* Load an OGG stream from an SDL_RWops object */ +OGG_music *OGG_new_RW(SDL_RWops *rw) +{ + OGG_music *music; + ov_callbacks callbacks; + + callbacks.read_func = sdl_read_func; + callbacks.seek_func = sdl_seek_func; + callbacks.close_func = sdl_close_func; + callbacks.tell_func = sdl_tell_func; + + music = (OGG_music *)malloc(sizeof *music); + if ( music ) { + /* Initialize the music structure */ + memset(music, 0, (sizeof *music)); + OGG_stop(music); + OGG_setvolume(music, MIX_MAX_VOLUME); + music->section = -1; + + if ( ov_open_callbacks(rw, &music->vf, NULL, 0, callbacks) < 0 ) { + SDL_SetError("Not an Ogg Vorbis audio stream"); + free(music); + SDL_RWclose(rw); + return(NULL); + } + } else { + SDL_SetError("Out of memory"); + } + return(music); +} + /* Start playback of a given OGG stream */ void OGG_play(OGG_music *music) { diff --git a/music_ogg.h b/music_ogg.h index 69fa819f..988bb08f 100644 --- a/music_ogg.h +++ b/music_ogg.h @@ -49,6 +49,9 @@ extern void OGG_setvolume(OGG_music *music, int volume); /* Load an OGG stream from the given file */ extern OGG_music *OGG_new(const char *file); +/* Load an OGG stream from an SDL_RWops object */ +extern OGG_music *OGG_new_RW(SDL_RWops *rw); + /* Start playback of a given OGG stream */ extern void OGG_play(OGG_music *music);