From 8df07e9530b4281a85105fef75b146c234edbf7f Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Sat, 3 Oct 2009 08:09:27 +0000 Subject: [PATCH] Split the mikmod support out into a separate file for clean coding --- configure.in | 21 ++- music.c | 352 +++++--------------------------------------- music_mod.c | 403 +++++++++++++++++++++++++++++++++++++++++++++++++++ music_mod.h | 72 +++++++++ 4 files changed, 526 insertions(+), 322 deletions(-) create mode 100644 music_mod.c create mode 100644 music_mod.h diff --git a/configure.in b/configure.in index 62568ec0..a8640d32 100644 --- a/configure.in +++ b/configure.in @@ -191,17 +191,26 @@ int main(int argc, char **argv) printf("no\n*** libmikmod is older than %d.%d.%d, not using.\n",maj,min,rev); return 1; } -], EXTRA_CFLAGS="$EXTRA_CFLAGS -DLIBMIKMOD_MUSIC `$LIBMIKMOD_CONFIG --cflags`";EXTRA_LDFLAGS="$EXTRA_LDFLAGS `$LIBMIKMOD_CONFIG --libs`", CFLAGS="$CFLAGS_SAVED";LIBS="$LIBS_SAVED", -[echo $ac_n "cross compiling; assumed OK... $ac_c"]) +], , , [echo $ac_n "cross compiling; assumed OK... $ac_c"]) fi + CFLAGS="$CFLAGS_SAVED" + LIBS="$LIBS_SAVED" fi AC_ARG_ENABLE([music-mod], AC_HELP_STRING([--enable-music-mod], [enable MOD music via mikmod [[default=yes]]]), - [], [enable_music_mod=$no_libmikmod]) -if test x$enable_music_mod = xyes -a x$enable_music_libmikmod = xno; then - EXTRA_CFLAGS="$EXTRA_CFLAGS -DMOD_MUSIC -I\$(srcdir)/mikmod" - SOURCES="$SOURCES $srcdir/mikmod/*.c" + [], [enable_music_mod=yes]) +if test x$enable_music_mod = xyes; then + EXTRA_CFLAGS="$EXTRA_CFLAGS -DMOD_MUSIC" + SOURCES="$SOURCES $srcdir/music_mod.c" + + if test x$enable_music_libmikmod = xyes; then + EXTRA_CFLAGS="$EXTRA_CFLAGS -DLIBMIKMOD_MUSIC `$LIBMIKMOD_CONFIG --cflags`" + EXTRA_LDFLAGS="$EXTRA_LDFLAGS `$LIBMIKMOD_CONFIG --libs`" + else + EXTRA_CFLAGS="$EXTRA_CFLAGS -I\$(srcdir)/mikmod" + SOURCES="$SOURCES $srcdir/mikmod/*.c" + fi fi AC_ARG_ENABLE([music-midi], AC_HELP_STRING([--enable-music-midi], [enable MIDI music via timidity [[default=yes]]]), diff --git a/music.c b/music.c index d7ffaeeb..a785dc5b 100644 --- a/music.c +++ b/music.c @@ -32,14 +32,6 @@ #include "SDL_mixer.h" -#define SDL_SURROUND - -#ifdef SDL_SURROUND -#define MAX_OUTPUT_CHANNELS 6 -#else -#define MAX_OUTPUT_CHANNELS 2 -#endif - /* The music command hack is UNIX specific */ #ifndef unix #undef CMD_MUSIC @@ -51,21 +43,8 @@ #ifdef WAV_MUSIC #include "wavestream.h" #endif -#if defined(MOD_MUSIC) || defined(LIBMIKMOD_MUSIC) -# include "mikmod.h" -# if defined(LIBMIKMOD_VERSION) /* libmikmod 3.1.8 */ -# define UNIMOD MODULE -# define MikMod_Init() MikMod_Init(NULL) -# define MikMod_LoadSong(a,b) Player_Load(a,b,0) -# ifndef LIBMIKMOD_MUSIC -# define MikMod_LoadSongRW(a,b) Player_LoadRW(a,b,0) -# endif -# define MikMod_FreeSong Player_Free - extern int MikMod_errno; -# else /* old MikMod 3.0.3 */ -# define MikMod_strerror(x) _mm_errmsg[x]) -# define MikMod_errno _mm_errno -# endif +#ifdef MOD_MUSIC +#include "music_mod.h" #endif #ifdef MID_MUSIC # ifdef USE_TIMIDITY_MIDI @@ -104,8 +83,6 @@ static int music_loops = 0; static char *music_cmd = NULL; static Mix_Music * volatile music_playing = NULL; static int music_volume = MIX_MAX_VOLUME; -static int music_swap8; -static int music_swap16; struct _Mix_Music { Mix_MusicType type; @@ -116,8 +93,8 @@ struct _Mix_Music { #ifdef WAV_MUSIC WAVStream *wave; #endif -#if defined(MOD_MUSIC) || defined(LIBMIKMOD_MUSIC) - UNIMOD *module; +#ifdef MOD_MUSIC + struct MODULE *module; #endif #ifdef MID_MUSIC #ifdef USE_TIMIDITY_MIDI @@ -155,10 +132,6 @@ static int native_midi_ok; #endif #endif -/* Reference for converting mikmod output to 4/6 channels */ -static int current_output_channels; -static Uint16 current_output_format; - /* Used to calculate fading steps */ static int ms_per_step; @@ -185,7 +158,7 @@ static void add_music_decoder(const char *decoder) if (ptr == NULL) { return; /* oh well, go on without it. */ } - music_decoders = (const char **) ptr; + music_decoders = (const char **) ptr; music_decoders[num_decoders++] = decoder; } @@ -285,80 +258,9 @@ void music_mixer(void *udata, Uint8 *stream, int len) left = WAVStream_PlaySome(stream, len); break; #endif -#if defined(MOD_MUSIC) || defined(LIBMIKMOD_MUSIC) +#ifdef MOD_MUSIC case MUS_MOD: - if (current_output_channels > 2) { - int small_len = 2 * len / current_output_channels; - int i; - Uint8 *src, *dst; - - VC_WriteBytes((SBYTE *)stream, small_len); - /* and extend to len by copying channels */ - src = stream + small_len; - dst = stream + len; - - switch (current_output_format & 0xFF) { - case 8: - for ( i=small_len/2; i; --i ) { - src -= 2; - dst -= current_output_channels; - dst[0] = src[0]; - dst[1] = src[1]; - dst[2] = src[0]; - dst[3] = src[1]; - if (current_output_channels == 6) { - dst[4] = src[0]; - dst[5] = src[1]; - } - } - break; - case 16: - for ( i=small_len/4; i; --i ) { - src -= 4; - dst -= 2 * current_output_channels; - dst[0] = src[0]; - dst[1] = src[1]; - dst[2] = src[2]; - dst[3] = src[3]; - dst[4] = src[0]; - dst[5] = src[1]; - dst[6] = src[2]; - dst[7] = src[3]; - if (current_output_channels == 6) { - dst[8] = src[0]; - dst[9] = src[1]; - dst[10] = src[2]; - dst[11] = src[3]; - } - } - break; - } - - - - } - else 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; - } - } + left = MOD_playAudio(music_playing->data.module, stream, len); break; #endif #ifdef MID_MUSIC @@ -407,12 +309,8 @@ void music_mixer(void *udata, Uint8 *stream, int len) /* Initialize the music players with a certain desired audio format */ int open_music(SDL_AudioSpec *mixer) { - int music_error; -#ifdef LIBMIKMOD_MUSIC - CHAR *list; -#endif + int music_error = 0; - music_error = 0; #ifdef WAV_MUSIC if ( WAVStream_Init(mixer) < 0 ) { ++music_error; @@ -420,76 +318,12 @@ int open_music(SDL_AudioSpec *mixer) add_music_decoder("WAVE"); } #endif -#if defined(MOD_MUSIC) || defined(LIBMIKMOD_MUSIC) - /* Set the MikMod music format */ - music_swap8 = 0; - music_swap16 = 0; - switch (mixer->format) { - - case AUDIO_U8: - case AUDIO_S8: { - if ( mixer->format == AUDIO_S8 ) { - music_swap8 = 1; - } - md_mode = 0; - } - break; - - case AUDIO_S16LSB: - case AUDIO_S16MSB: { - /* See if we need to correct MikMod mixing */ -#if SDL_BYTEORDER == SDL_LIL_ENDIAN - if ( mixer->format == AUDIO_S16MSB ) { -#else - if ( mixer->format == AUDIO_S16LSB ) { -#endif - music_swap16 = 1; - } - md_mode = DMODE_16BITS; - } - break; - - default: { - Mix_SetError("Unknown hardware audio format"); - ++music_error; - } - } - current_output_channels = mixer->channels; - current_output_format = mixer->format; - if ( mixer->channels > 1 ) { - if ( mixer->channels > MAX_OUTPUT_CHANNELS ) { - Mix_SetError("Hardware uses more channels than mixer"); - ++music_error; - } - md_mode |= DMODE_STEREO; - } - md_mixfreq = mixer->freq; - md_device = 0; - md_volume = 96; - md_musicvolume = 128; - md_sndfxvolume = 128; - md_pansep = 128; - md_reverb = 0; - md_mode |= DMODE_HQMIXER|DMODE_SOFT_MUSIC|DMODE_SURROUND; -#ifdef LIBMIKMOD_MUSIC - list = MikMod_InfoDriver(); - if ( list ) - free(list); - else -#endif - MikMod_RegisterDriver(&drv_nos); -#ifdef LIBMIKMOD_MUSIC - list = MikMod_InfoLoader(); - if ( list ) - free(list); - else -#endif - MikMod_RegisterAllLoaders(); - if ( MikMod_Init() ) { - Mix_SetError("%s", MikMod_strerror(MikMod_errno)); +#ifdef MOD_MUSIC + if ( MOD_init(mixer) < 0 ) { ++music_error; + } else { + add_music_decoder("MIKMOD"); } - add_music_decoder("MIKMOD"); #endif #ifdef MID_MUSIC #ifdef USE_TIMIDITY_MIDI @@ -708,23 +542,12 @@ Mix_Music *Mix_LoadMUS(const char *file) } } else #endif -#if defined(MOD_MUSIC) || defined(LIBMIKMOD_MUSIC) +#ifdef MOD_MUSIC if ( 1 ) { music->type = MUS_MOD; - music->data.module = MikMod_LoadSong((char *)file, 64); + music->data.module = MOD_new(file); if ( music->data.module == NULL ) { - Mix_SetError("%s", MikMod_strerror(MikMod_errno)); music->error = 1; - } else { - /* Stop implicit looping, fade out and other flags. */ - music->data.module->extspd = 1; - music->data.module->panflag = 1; - music->data.module->wrap = 0; - music->data.module->loop = 1; -#if 0 /* Don't set fade out by default - unfortunately there's no real way - to query the status of the song or set trigger actions. Hum. */ - music->data.module->fadeout = 1; -#endif } } else #endif @@ -768,9 +591,9 @@ void Mix_FreeMusic(Mix_Music *music) WAVStream_FreeSong(music->data.wave); break; #endif -#if defined(MOD_MUSIC) || defined(LIBMIKMOD_MUSIC) +#ifdef MOD_MUSIC case MUS_MOD: - MikMod_FreeSong(music->data.module); + MOD_delete(music->data.module); break; #endif #ifdef MID_MUSIC @@ -864,9 +687,9 @@ static int music_internal_play(Mix_Music *music, double position) WAVStream_Start(music->data.wave); break; #endif -#if defined(MOD_MUSIC) || defined(LIBMIKMOD_MUSIC) +#ifdef MOD_MUSIC case MUS_MOD: - Player_Start(music->data.module); + MOD_play(music->data.module); /* Player_SetVolume() does nothing before Player_Start() */ music_internal_initialize_volume(); break; @@ -980,9 +803,9 @@ int music_internal_position(double position) int retval = 0; switch (music_playing->type) { -#if defined(MOD_MUSIC) || defined(LIBMIKMOD_MUSIC) +#ifdef MOD_MUSIC case MUS_MOD: - Player_SetPosition((UWORD)position); + MOD_jump_to_time(music_playing->data.module, position); break; #endif #ifdef OGG_MUSIC @@ -1060,9 +883,9 @@ static void music_internal_volume(int volume) WAVStream_SetVolume(volume); break; #endif -#if defined(MOD_MUSIC) || defined(LIBMIKMOD_MUSIC) +#ifdef MOD_MUSIC case MUS_MOD: - Player_SetVolume((SWORD)volume); + MOD_setvolume(music_playing->data.module, volume); break; #endif #ifdef MID_MUSIC @@ -1138,9 +961,9 @@ static void music_internal_halt(void) WAVStream_Stop(); break; #endif -#if defined(MOD_MUSIC) || defined(LIBMIKMOD_MUSIC) +#ifdef MOD_MUSIC case MUS_MOD: - Player_Stop(); + MOD_stop(music_playing->data.module); break; #endif #ifdef MID_MUSIC @@ -1284,9 +1107,9 @@ static int music_internal_playing() } break; #endif -#if defined(MOD_MUSIC) || defined(LIBMIKMOD_MUSIC) +#ifdef MOD_MUSIC case MUS_MOD: - if ( ! Player_Active() ) { + if ( ! MOD_playing(music_playing->data.module) ) { playing = 0; } break; @@ -1371,32 +1194,13 @@ int Mix_SetMusicCMD(const char *command) return(0); } -#ifdef LIBMIKMOD_MUSIC -static int _pl_synchro_value; -void Player_SetSynchroValue(int i) -{ - fprintf(stderr,"SDL_mixer: Player_SetSynchroValue is not supported.\n"); - _pl_synchro_value = i; -} - -int Player_GetSynchroValue(void) -{ - fprintf(stderr,"SDL_mixer: Player_GetSynchroValue is not supported.\n"); - return _pl_synchro_value; -} -#endif - int Mix_SetSynchroValue(int i) { if ( music_playing && ! music_stopped ) { switch (music_playing->type) { -#if defined(MOD_MUSIC) || defined(LIBMIKMOD_MUSIC) +#ifdef MOD_MUSIC case MUS_MOD: - if ( ! Player_Active() ) { - return(-1); - } - Player_SetSynchroValue(i); - return 0; + return MOD_SetSynchroValue(i); break; #endif default: @@ -1412,12 +1216,9 @@ int Mix_GetSynchroValue(void) { if ( music_playing && ! music_stopped ) { switch (music_playing->type) { -#if defined(MOD_MUSIC) || defined(LIBMIKMOD_MUSIC) +#ifdef MOD_MUSIC case MUS_MOD: - if ( ! Player_Active() ) { - return(-1); - } - return Player_GetSynchroValue(); + return MOD_GetSynchroValue(); break; #endif default: @@ -1437,12 +1238,8 @@ void close_music(void) #ifdef CMD_MUSIC Mix_SetMusicCMD(NULL); #endif -#if defined(MOD_MUSIC) || defined(LIBMIKMOD_MUSIC) - MikMod_Exit(); -# ifndef LIBMIKMOD_MUSIC - MikMod_UnregisterAllLoaders(); - MikMod_UnregisterAllDrivers(); -# endif +#ifdef MOD_MUSIC + MOD_exit(); #endif #ifdef MID_MUSIC # ifdef USE_TIMIDITY_MIDI @@ -1456,72 +1253,6 @@ void close_music(void) num_decoders = 0; } -# ifdef LIBMIKMOD_MUSIC -typedef struct -{ - MREADER mr; - int offset; - int eof; - SDL_RWops *rw; -} LMM_MREADER; -BOOL LMM_Seek(struct MREADER *mr,long to,int dir) -{ - int at; - LMM_MREADER* lmmmr=(LMM_MREADER*)mr; - if(dir==SEEK_SET) - to+=lmmmr->offset; - at=SDL_RWseek(lmmmr->rw, to, dir); - return atoffset; -} -long LMM_Tell(struct MREADER *mr) -{ - int at; - LMM_MREADER* lmmmr=(LMM_MREADER*)mr; - at=SDL_RWtell(lmmmr->rw)-lmmmr->offset; - return at; -} -BOOL LMM_Read(struct MREADER *mr,void *buf,size_t sz) -{ - int got; - LMM_MREADER* lmmmr=(LMM_MREADER*)mr; - got=SDL_RWread(lmmmr->rw, buf, sz, 1); - return got; -} -int LMM_Get(struct MREADER *mr) -{ - unsigned char c; - int i=EOF; - LMM_MREADER* lmmmr=(LMM_MREADER*)mr; - if(SDL_RWread(lmmmr->rw,&c,1,1)) - i=c; - return i; -} -BOOL LMM_Eof(struct MREADER *mr) -{ - int offset; - LMM_MREADER* lmmmr=(LMM_MREADER*)mr; - offset=LMM_Tell(mr); - return offset>=lmmmr->eof; -} -MODULE *MikMod_LoadSongRW(SDL_RWops *rw, int maxchan) -{ - LMM_MREADER lmmmr = { - { LMM_Seek, LMM_Tell, LMM_Read, LMM_Get, LMM_Eof }, - 0, - 0, - 0 - }; - MODULE *m; - lmmmr.rw = rw; - lmmmr.offset=SDL_RWtell(rw); - SDL_RWseek(rw,0,SEEK_END); - lmmmr.eof=SDL_RWtell(rw); - SDL_RWseek(rw,lmmmr.offset,SEEK_SET); - m=Player_LoadGeneric((MREADER*)&lmmmr,maxchan,0); - return m; -} -# endif - 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,*/ @@ -1644,23 +1375,12 @@ Mix_Music *Mix_LoadMUS_RW(SDL_RWops *rw) #endif } else #endif -#if defined(MOD_MUSIC) || defined(LIBMIKMOD_MUSIC) +#ifdef MOD_MUSIC if (1) { music->type=MUS_MOD; - music->data.module=MikMod_LoadSongRW(rw,64); - if (music->data.module==NULL) { - Mix_SetError("%s",MikMod_strerror(MikMod_errno)); - music->error=1; - } else { - /* Stop implicit looping, fade out and other flags. */ - music->data.module->extspd = 1; - music->data.module->panflag = 1; - music->data.module->wrap = 0; - music->data.module->loop = 0; -#if 0 /* Don't set fade out by default - unfortunately there's no real way - to query the status of the song or set trigger actions. Hum. */ - music->data.module->fadeout = 1; -#endif + music->data.module = MOD_new_RW(rw); + if ( music->data.module == NULL ) { + music->error = 1; } } else #endif diff --git a/music_mod.c b/music_mod.c new file mode 100644 index 00000000..549ac6ce --- /dev/null +++ b/music_mod.c @@ -0,0 +1,403 @@ +/* + SDL_mixer: An audio mixer library based on the SDL library + Copyright (C) 1997-2009 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 +*/ + +/* $Id: music_mod.c 4211 2008-12-08 00:27:32Z slouken $ */ + +#ifdef MOD_MUSIC + +/* This file supports MOD tracker music streams */ + +#include "SDL_mixer.h" +/*#include "dynamic_mod.h"*/ +#include "music_mod.h" + +#include "mikmod.h" + +#if defined(LIBMIKMOD_VERSION) /* libmikmod 3.1.8 */ +#define UNIMOD MODULE +#define MikMod_Init() MikMod_Init(NULL) +#define MikMod_LoadSong(a,b) Player_Load(a,b,0) +#ifndef LIBMIKMOD_MUSIC +#define MikMod_LoadSongRW(a,b) Player_LoadRW(a,b,0) +#endif +#define MikMod_FreeSong Player_Free + extern int MikMod_errno; +#else /* old MikMod 3.0.3 */ +#define MikMod_strerror(x) _mm_errmsg[x]) +#define MikMod_errno _mm_errno +#endif + +#define SDL_SURROUND +#ifdef SDL_SURROUND +#define MAX_OUTPUT_CHANNELS 6 +#else +#define MAX_OUTPUT_CHANNELS 2 +#endif + +/* Reference for converting mikmod output to 4/6 channels */ +static int current_output_channels; +static Uint16 current_output_format; + +static int music_swap8; +static int music_swap16; + +/* Initialize the Ogg Vorbis player, with the given mixer settings + This function returns 0, or -1 if there was an error. + */ +int MOD_init(SDL_AudioSpec *mixerfmt) +{ +#ifdef LIBMIKMOD_MUSIC + CHAR *list; +#endif + + /* Set the MikMod music format */ + music_swap8 = 0; + music_swap16 = 0; + switch (mixerfmt->format) { + + case AUDIO_U8: + case AUDIO_S8: { + if ( mixerfmt->format == AUDIO_S8 ) { + music_swap8 = 1; + } + md_mode = 0; + } + break; + + case AUDIO_S16LSB: + case AUDIO_S16MSB: { + /* See if we need to correct MikMod mixing */ +#if SDL_BYTEORDER == SDL_LIL_ENDIAN + if ( mixerfmt->format == AUDIO_S16MSB ) { +#else + if ( mixerfmt->format == AUDIO_S16LSB ) { +#endif + music_swap16 = 1; + } + md_mode = DMODE_16BITS; + } + break; + + default: { + Mix_SetError("Unknown hardware audio format"); + return -1; + } + } + current_output_channels = mixerfmt->channels; + current_output_format = mixerfmt->format; + if ( mixerfmt->channels > 1 ) { + if ( mixerfmt->channels > MAX_OUTPUT_CHANNELS ) { + Mix_SetError("Hardware uses more channels than mixerfmt"); + return -1; + } + md_mode |= DMODE_STEREO; + } + md_mixfreq = mixerfmt->freq; + md_device = 0; + md_volume = 96; + md_musicvolume = 128; + md_sndfxvolume = 128; + md_pansep = 128; + md_reverb = 0; + md_mode |= DMODE_HQMIXER|DMODE_SOFT_MUSIC|DMODE_SURROUND; +#ifdef LIBMIKMOD_MUSIC + list = MikMod_InfoDriver(); + if ( list ) + free(list); + else +#endif + MikMod_RegisterDriver(&drv_nos); +#ifdef LIBMIKMOD_MUSIC + list = MikMod_InfoLoader(); + if ( list ) + free(list); + else +#endif + MikMod_RegisterAllLoaders(); + if ( MikMod_Init() ) { + Mix_SetError("%s", MikMod_strerror(MikMod_errno)); + return -1; + } + + return 0; +} + +/* Uninitialize the music players */ +void MOD_exit(void) +{ + MikMod_Exit(); +#ifndef LIBMIKMOD_MUSIC + MikMod_UnregisterAllLoaders(); + MikMod_UnregisterAllDrivers(); +#endif +} + +/* Set the volume for a MOD stream */ +void MOD_setvolume(MODULE *music, int volume) +{ + Player_SetVolume((SWORD)volume); +} + +/* Load a MOD stream from the given file */ +MODULE *MOD_new(const char *file) +{ + SDL_RWops *rw; + + rw = SDL_RWFromFile(file, "rb"); + if ( rw == NULL ) { + /* FIXME: Free rw, need to free on delete */ + SDL_SetError("Couldn't open %s", file); + return NULL; + } + return MOD_new_RW(rw); +} + + +#ifdef LIBMIKMOD_MUSIC +typedef struct +{ + MREADER mr; + int offset; + int eof; + SDL_RWops *rw; +} LMM_MREADER; + +BOOL LMM_Seek(struct MREADER *mr,long to,int dir) +{ + int at; + LMM_MREADER* lmmmr=(LMM_MREADER*)mr; + if(dir==SEEK_SET) + to+=lmmmr->offset; + at=SDL_RWseek(lmmmr->rw, to, dir); + return atoffset; +} +long LMM_Tell(struct MREADER *mr) +{ + int at; + LMM_MREADER* lmmmr=(LMM_MREADER*)mr; + at=SDL_RWtell(lmmmr->rw)-lmmmr->offset; + return at; +} +BOOL LMM_Read(struct MREADER *mr,void *buf,size_t sz) +{ + int got; + LMM_MREADER* lmmmr=(LMM_MREADER*)mr; + got=SDL_RWread(lmmmr->rw, buf, sz, 1); + return got; +} +int LMM_Get(struct MREADER *mr) +{ + unsigned char c; + int i=EOF; + LMM_MREADER* lmmmr=(LMM_MREADER*)mr; + if(SDL_RWread(lmmmr->rw,&c,1,1)) + i=c; + return i; +} +BOOL LMM_Eof(struct MREADER *mr) +{ + int offset; + LMM_MREADER* lmmmr=(LMM_MREADER*)mr; + offset=LMM_Tell(mr); + return offset>=lmmmr->eof; +} +MODULE *MikMod_LoadSongRW(SDL_RWops *rw, int maxchan) +{ + LMM_MREADER lmmmr = { + { LMM_Seek, LMM_Tell, LMM_Read, LMM_Get, LMM_Eof }, + 0, + 0, + 0 + }; + MODULE *m; + lmmmr.rw = rw; + lmmmr.offset=SDL_RWtell(rw); + SDL_RWseek(rw,0,SEEK_END); + lmmmr.eof=SDL_RWtell(rw); + SDL_RWseek(rw,lmmmr.offset,SEEK_SET); + m=Player_LoadGeneric((MREADER*)&lmmmr,maxchan,0); + return m; +} +#endif + +/* Load a MOD stream from an SDL_RWops object */ +MODULE *MOD_new_RW(SDL_RWops *rw) +{ + MODULE *module = MikMod_LoadSongRW(rw,64); + if (!module) { + Mix_SetError("%s", MikMod_strerror(MikMod_errno)); + return NULL; + } + + /* Stop implicit looping, fade out and other flags. */ + module->extspd = 1; + module->panflag = 1; + module->wrap = 0; + module->loop = 0; +#if 0 /* Don't set fade out by default - unfortunately there's no real way +to query the status of the song or set trigger actions. Hum. */ + module->fadeout = 1; +#endif + return module; +} + +/* Start playback of a given MOD stream */ +void MOD_play(MODULE *music) +{ + Player_Start(music); +} + +/* Return non-zero if a stream is currently playing */ +int MOD_playing(MODULE *music) +{ + return Player_Active(); +} + +/* Play some of a stream previously started with MOD_play() */ +int MOD_playAudio(MODULE *music, Uint8 *stream, int len) +{ + if (current_output_channels > 2) { + int small_len = 2 * len / current_output_channels; + int i; + Uint8 *src, *dst; + + VC_WriteBytes((SBYTE *)stream, small_len); + /* and extend to len by copying channels */ + src = stream + small_len; + dst = stream + len; + + switch (current_output_format & 0xFF) { + case 8: + for ( i=small_len/2; i; --i ) { + src -= 2; + dst -= current_output_channels; + dst[0] = src[0]; + dst[1] = src[1]; + dst[2] = src[0]; + dst[3] = src[1]; + if (current_output_channels == 6) { + dst[4] = src[0]; + dst[5] = src[1]; + } + } + break; + case 16: + for ( i=small_len/4; i; --i ) { + src -= 4; + dst -= 2 * current_output_channels; + dst[0] = src[0]; + dst[1] = src[1]; + dst[2] = src[2]; + dst[3] = src[3]; + dst[4] = src[0]; + dst[5] = src[1]; + dst[6] = src[2]; + dst[7] = src[3]; + if (current_output_channels == 6) { + dst[8] = src[0]; + dst[9] = src[1]; + dst[10] = src[2]; + dst[11] = src[3]; + } + } + break; + } + } else { + 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; + } + } + return 0; +} + +/* Stop playback of a stream previously started with MOD_play() */ +void MOD_stop(MODULE *music) +{ + Player_Stop(); +} + +/* Close the given MOD stream */ +void MOD_delete(MODULE *music) +{ + MikMod_FreeSong(music); +} + +/* Jump (seek) to a given position (time is in seconds) */ +void MOD_jump_to_time(MODULE *music, double time) +{ + Player_SetPosition((UWORD)time); +} + +#ifdef LIBMIKMOD_MUSIC +static int _pl_synchro_value; +void Player_SetSynchroValue(int i) +{ + fprintf(stderr,"SDL_mixer: Player_SetSynchroValue is not supported.\n"); + _pl_synchro_value = i; +} + +int Player_GetSynchroValue(void) +{ + fprintf(stderr,"SDL_mixer: Player_GetSynchroValue is not supported.\n"); + return _pl_synchro_value; +} +#endif + +/* Set the MOD synchronization value */ +int MOD_SetSynchroValue(int i) +{ + if ( ! Player_Active() ) { + return(-1); + } + Player_SetSynchroValue(i); + return 0; +} + +/* Get the MOD synchronization value */ +int MOD_GetSynchroValue(void) +{ + if ( ! Player_Active() ) { + return(-1); + } + return Player_GetSynchroValue(); +} + +#endif /* MOD_MUSIC */ diff --git a/music_mod.h b/music_mod.h new file mode 100644 index 00000000..d7c79e01 --- /dev/null +++ b/music_mod.h @@ -0,0 +1,72 @@ +/* + SDL_mixer: An audio mixer library based on the SDL library + Copyright (C) 1997-2009 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 +*/ + +/* $Id: music_mod.h 4211 2008-12-08 00:27:32Z slouken $ */ + +#ifdef MOD_MUSIC + +/* This file supports MOD tracker music streams */ + +struct MODULE; + +/* Initialize the Ogg Vorbis player, with the given mixer settings + This function returns 0, or -1 if there was an error. + */ +extern int MOD_init(SDL_AudioSpec *mixer); + +/* Uninitialize the music players */ +extern void MOD_exit(void); + +/* Set the volume for a MOD stream */ +extern void MOD_setvolume(struct MODULE *music, int volume); + +/* Load a MOD stream from the given file */ +extern struct MODULE *MOD_new(const char *file); + +/* Load a MOD stream from an SDL_RWops object */ +extern struct MODULE *MOD_new_RW(SDL_RWops *rw); + +/* Start playback of a given MOD stream */ +extern void MOD_play(struct MODULE *music); + +/* Return non-zero if a stream is currently playing */ +extern int MOD_playing(struct MODULE *music); + +/* Play some of a stream previously started with MOD_play() */ +extern int MOD_playAudio(struct MODULE *music, Uint8 *stream, int len); + +/* Stop playback of a stream previously started with MOD_play() */ +extern void MOD_stop(struct MODULE *music); + +/* Close the given MOD stream */ +extern void MOD_delete(struct MODULE *music); + +/* Jump (seek) to a given position (time is in seconds) */ +extern void MOD_jump_to_time(struct MODULE *music, double time); + +/* Set the MOD synchronization value */ +extern int MOD_SetSynchroValue(int i); + +/* Get the MOD synchronization value */ +extern int MOD_GetSynchroValue(void); + +#endif /* MOD_MUSIC */