From 6076b7640d2de3f16206b3668296640e107a534e Mon Sep 17 00:00:00 2001 From: Chris Taylor Date: Mon, 18 Apr 2011 20:30:46 +0800 Subject: [PATCH] Fix broken m3u playlist support (in jukebox_play() path resolving); point to default descent.m3u playlist for Mac OS X (will be included in bundle); better error reporting in mix_play_file(); only make relative Jukebox path in the menu absolute after browsing it - relative paths are more flexible; allow select_file_recursive() to figure out PhysicsFS relative paths passed to it; stop the music if Jukebox is chosen and unavailable (used to just keep playing the last song) --- CHANGELOG.txt | 4 ++ arch/sdl/digi_mixer_music.c | 15 +++++- arch/sdl/jukebox.c | 91 +++++++++++++++++++++---------------- main/config.c | 12 ++--- main/menu.c | 8 ++++ main/songs.c | 34 ++++++++------ main/songs.h | 2 +- 7 files changed, 105 insertions(+), 61 deletions(-) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index fbf51caf0..981a63a14 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -1,5 +1,9 @@ D1X-Rebirth Changelog +20110418 +-------- +arch/sdl/digi_mixer_music.c, arch/sdl/jukebox.c, main/config.c, main/menu.c, main/songs.c, main/songs.h: Fix broken m3u playlist support (in jukebox_play() path resolving); point to default descent.m3u playlist for Mac OS X (will be included in bundle); better error reporting in mix_play_file(); only make relative Jukebox path in the menu absolute after browsing it - relative paths are more flexible; allow select_file_recursive() to figure out PhysicsFS relative paths passed to it; stop the music if Jukebox is chosen and unavailable (used to just keep playing the last song) + 20110414 -------- main/kmatrix.c: Fixing km struct being used after it's being freed by closing the window in EVENT_WINDOW_DRAW diff --git a/arch/sdl/digi_mixer_music.c b/arch/sdl/digi_mixer_music.c index 1bd007ef2..84d989b72 100644 --- a/arch/sdl/digi_mixer_music.c +++ b/arch/sdl/digi_mixer_music.c @@ -63,6 +63,19 @@ int mix_play_file(char *filename, int loop, void (*hook_finished_track)()) if (!current_music) current_music = Mix_LoadMUS(filename); + // allow the shell convention tilde character to mean the user's home folder + // chiefly used for default jukebox level song music referenced in 'descent.m3u' for Mac OS X + if (!current_music && *filename == '~') + { + snprintf(full_path, PATH_MAX, "%s%s", PHYSFS_getUserDir(), + &filename[1 + (!strncmp(&filename[1], PHYSFS_getDirSeparator(), strlen(PHYSFS_getDirSeparator())) ? + strlen(PHYSFS_getDirSeparator()) : 0)]); + current_music = Mix_LoadMUS(full_path); + if (current_music) + filename = full_path; // used later for possible error reporting + } + + // no luck. so it might be in Searchpath. So try to build absolute path if (!current_music) { @@ -94,7 +107,7 @@ int mix_play_file(char *filename, int loop, void (*hook_finished_track)()) } else { - con_printf(CON_CRITICAL,"Music %s could not be loaded\n", filename); + con_printf(CON_CRITICAL,"Music %s could not be loaded: %s\n", filename, Mix_GetError()); mix_stop_music(); } diff --git a/arch/sdl/jukebox.c b/arch/sdl/jukebox.c index 32c14abba..84796e0c0 100644 --- a/arch/sdl/jukebox.c +++ b/arch/sdl/jukebox.c @@ -59,15 +59,29 @@ void jukebox_unload() char *jukebox_exts[] = { ".mp3", ".ogg", ".wav", ".aif", ".mid", NULL }; -void read_m3u(void) +int read_m3u(void) { FILE *fp; int length; char *buf; + char *abspath; - fp = fopen(GameCfg.CMLevelMusicPath, "rb"); + MALLOC(abspath, char, PATH_MAX); + if (!abspath) + return 0; + + if (PHYSFS_exists(GameCfg.CMLevelMusicPath)) // it's a child of Sharepath, build full path + PHYSFSX_getRealPath(GameCfg.CMLevelMusicPath, abspath); + else + { + strncpy(abspath, GameCfg.CMLevelMusicPath, PATH_MAX - 1); + abspath[PATH_MAX - 1] = '\0'; + } + + fp = fopen(abspath, "rb"); + d_free(abspath); if (!fp) - return; + return 0; fseek( fp, -1, SEEK_END ); length = ftell(fp) + 1; @@ -75,7 +89,7 @@ void read_m3u(void) if (!JukeboxSongs.list_buf) { fclose(fp); - return; + return 0; } fseek(fp, 0, SEEK_SET); @@ -83,7 +97,7 @@ void read_m3u(void) { d_free(JukeboxSongs.list_buf); fclose(fp); - return; + return 0; } fclose(fp); // Finished with it @@ -93,7 +107,7 @@ void read_m3u(void) if (!JukeboxSongs.list) { d_free(JukeboxSongs.list_buf); - return; + return 0; } JukeboxSongs.max_songs = 1024; @@ -125,15 +139,14 @@ void read_m3u(void) *buf = 0; } + + return 1; } /* Loads music file names from a given directory or M3U playlist */ void jukebox_load() { static int jukebox_init = 1; - int new_path = 0; - char *p; - const char *sep = PHYSFS_getDirSeparator(); // initialize JukeboxSongs structure once per runtime if (jukebox_init) @@ -145,41 +158,36 @@ void jukebox_load() jukebox_unload(); - // build path properly. - if (strlen(GameCfg.CMLevelMusicPath) >= strlen(sep)) - { - char *abspath; - - MALLOC(abspath, char, PATH_MAX); - - p = GameCfg.CMLevelMusicPath + strlen(GameCfg.CMLevelMusicPath) - strlen(sep); - if (strcmp(p, sep) && stricmp(&GameCfg.CMLevelMusicPath[strlen(GameCfg.CMLevelMusicPath) - 4], ".m3u")) - strncat(GameCfg.CMLevelMusicPath, sep, PATH_MAX - 1 - strlen(GameCfg.CMLevelMusicPath)); - - if (PHYSFS_isDirectory(GameCfg.CMLevelMusicPath)) // it's a child of Sharepath, build full path - { - PHYSFSX_getRealPath(GameCfg.CMLevelMusicPath,abspath); - snprintf(GameCfg.CMLevelMusicPath,sizeof(char)*PATH_MAX,"%s",abspath); - } - d_free(abspath); - } - - new_path = PHYSFSX_isNewPath(GameCfg.CMLevelMusicPath); - // Check if it's an M3U file - if (!PHYSFS_addToSearchPath(GameCfg.CMLevelMusicPath, 0)) - { - if (!stricmp(&GameCfg.CMLevelMusicPath[strlen(GameCfg.CMLevelMusicPath) - 4], ".m3u")) - read_m3u(); - } - else + if (!stricmp(&GameCfg.CMLevelMusicPath[strlen(GameCfg.CMLevelMusicPath) - 4], ".m3u")) + read_m3u(); + else // a directory { + int new_path = 0; + char *p; + const char *sep = PHYSFS_getDirSeparator(); int i; - // Read directory using PhysicsFS + // stick a separator on the end if necessary. + if (strlen(GameCfg.CMLevelMusicPath) >= strlen(sep)) + { + p = GameCfg.CMLevelMusicPath + strlen(GameCfg.CMLevelMusicPath) - strlen(sep); + if (strcmp(p, sep)) + strncat(GameCfg.CMLevelMusicPath, sep, PATH_MAX - 1 - strlen(GameCfg.CMLevelMusicPath)); + } + + // Read directory using PhysicsFS + if (PHYSFS_isDirectory(GameCfg.CMLevelMusicPath)) // find files in relative directory + JukeboxSongs.list = PHYSFSX_findFiles(GameCfg.CMLevelMusicPath, jukebox_exts); + else + { + new_path = PHYSFSX_isNewPath(GameCfg.CMLevelMusicPath); + PHYSFS_addToSearchPath(GameCfg.CMLevelMusicPath, 0); + + // as mountpoints are no option (yet), make sure only files originating from GameCfg.CMLevelMusicPath are aded to the list. + JukeboxSongs.list = PHYSFSX_findabsoluteFiles("", GameCfg.CMLevelMusicPath, jukebox_exts); + } - // as mountpoints are no option (yet), make sure only files originating from GameCfg.CMLevelMusicPath are aded to the list. - JukeboxSongs.list = PHYSFSX_findabsoluteFiles("", GameCfg.CMLevelMusicPath, jukebox_exts); if (!JukeboxSongs.list) { if (new_path) @@ -243,7 +251,10 @@ int jukebox_play() MALLOC(full_filename, char, strlen(GameCfg.CMLevelMusicPath)+strlen(music_filename)+1); memset(full_filename, '\0', strlen(GameCfg.CMLevelMusicPath)+strlen(music_filename)+1); - snprintf(full_filename, strlen(GameCfg.CMLevelMusicPath)+strlen(music_filename)+1, "%s%s", GameCfg.CMLevelMusicPath, music_filename); + if (!stricmp(&GameCfg.CMLevelMusicPath[strlen(GameCfg.CMLevelMusicPath) - 4], ".m3u")) // if it's from an M3U playlist + strcpy(full_filename, music_filename); + else // if it's from a specified path + snprintf(full_filename, strlen(GameCfg.CMLevelMusicPath)+strlen(music_filename)+1, "%s%s", GameCfg.CMLevelMusicPath, music_filename); if (!mix_play_file(full_filename, ((GameCfg.CMLevelMusicPlayOrder == MUSIC_CM_PLAYORDER_LEVEL)?1:0), ((GameCfg.CMLevelMusicPlayOrder == MUSIC_CM_PLAYORDER_LEVEL)?NULL:jukebox_hook_next))) { diff --git a/main/config.c b/main/config.c index ed14562af..d9e362262 100644 --- a/main/config.c +++ b/main/config.c @@ -92,12 +92,12 @@ int ReadConfigFile() #if defined(__APPLE__) && defined(__MACH__) GameCfg.OrigTrackOrder = 1; GameCfg.CMLevelMusicPlayOrder = MUSIC_CM_PLAYORDER_LEVEL; - snprintf(GameCfg.CMLevelMusicPath, PATH_MAX, "%s/%s", PHYSFS_getUserDir(), "Music/iTunes/iTunes Music/Insanity/Descent/"); - snprintf(GameCfg.CMMiscMusic[SONG_TITLE], PATH_MAX, "%s/%s", PHYSFS_getUserDir(), "Music/iTunes/iTunes Music/Insanity/Descent/02 Primitive Rage.mp3"); - snprintf(GameCfg.CMMiscMusic[SONG_BRIEFING], PATH_MAX, "%s/%s", PHYSFS_getUserDir(), "Music/iTunes/iTunes Music/Insanity/Descent/03 Outerlimits.mp3"); - snprintf(GameCfg.CMMiscMusic[SONG_ENDLEVEL], PATH_MAX, "%s/%s", PHYSFS_getUserDir(), "Music/iTunes/iTunes Music/Insanity/Descent/04 Close Call.mp3"); - snprintf(GameCfg.CMMiscMusic[SONG_ENDGAME], PATH_MAX, "%s/%s", PHYSFS_getUserDir(), "Music/iTunes/iTunes Music/Insanity/Descent/14 Insanity.mp3"); - snprintf(GameCfg.CMMiscMusic[SONG_CREDITS], PATH_MAX, "%s/%s", PHYSFS_getUserDir(), "Music/iTunes/iTunes Music/Insanity/Descent/05 The Darkness Of Space.mp3"); + snprintf(GameCfg.CMLevelMusicPath, PATH_MAX, "%s", "descent.m3u"); + snprintf(GameCfg.CMMiscMusic[SONG_TITLE], PATH_MAX, "%s%s", PHYSFS_getUserDir(), "Music/iTunes/iTunes Music/Insanity/Descent/02 Primitive Rage.mp3"); + snprintf(GameCfg.CMMiscMusic[SONG_BRIEFING], PATH_MAX, "%s%s", PHYSFS_getUserDir(), "Music/iTunes/iTunes Music/Insanity/Descent/03 Outerlimits.mp3"); + snprintf(GameCfg.CMMiscMusic[SONG_ENDLEVEL], PATH_MAX, "%s%s", PHYSFS_getUserDir(), "Music/iTunes/iTunes Music/Insanity/Descent/04 Close Call.mp3"); + snprintf(GameCfg.CMMiscMusic[SONG_ENDGAME], PATH_MAX, "%s%s", PHYSFS_getUserDir(), "Music/iTunes/iTunes Music/Insanity/Descent/14 Insanity.mp3"); + snprintf(GameCfg.CMMiscMusic[SONG_CREDITS], PATH_MAX, "%s%s", PHYSFS_getUserDir(), "Music/iTunes/iTunes Music/Insanity/Descent/05 The Darkness Of Space.mp3"); #endif GameCfg.GammaLevel = 0; memset(GameCfg.LastPlayer,0,CALLSIGN_LEN+1); diff --git a/main/menu.c b/main/menu.c index ddba7d648..f91f0b487 100644 --- a/main/menu.c +++ b/main/menu.c @@ -1495,6 +1495,7 @@ int select_file_recursive(char *title, const char *orig_path, char **ext_list, i browser *b; const char *sep = PHYSFS_getDirSeparator(); char *p; + char new_path[PATH_MAX]; MALLOC(b, browser, 1); if (!b) @@ -1509,6 +1510,13 @@ int select_file_recursive(char *title, const char *orig_path, char **ext_list, i b->view_path[0] = '\0'; b->new_path = 1; + // Check for a PhysicsFS path first, saves complication! + if (orig_path && strncmp(orig_path, sep, strlen(sep)) && PHYSFS_exists(orig_path)) + { + PHYSFSX_getRealPath(orig_path, new_path); + orig_path = new_path; + } + // Set the viewing directory to orig_path, or some parent of it if (orig_path) { diff --git a/main/songs.c b/main/songs.c index dcc828404..0651e2a57 100644 --- a/main/songs.c +++ b/main/songs.c @@ -36,7 +36,7 @@ COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. #include "timer.h" int Songs_initialized = 0; -static int Song_playing = 0; // 0 if no song playing, else the Descent song number +static int Song_playing = -1; // -1 if no song playing, else the Descent song number static int Redbook_playing = 0; // Redbook track num differs from Song_playing. We need this for Redbook repeat hooks. bim_song_info *BIMSongs = NULL; @@ -188,7 +188,7 @@ void songs_uninit() if (BIMSongs != NULL) d_free(BIMSongs); - Song_playing = 0; + Song_playing = -1; Songs_initialized = 0; } @@ -203,7 +203,7 @@ void songs_stop_all(void) mix_stop_music(); #endif - Song_playing = 0; + Song_playing = -1; } void songs_pause(void) @@ -287,7 +287,7 @@ int songs_play_song( int songnum, int repeat ) { case MUSIC_TYPE_BUILTIN: { - Song_playing = 0; + Song_playing = -1; #ifdef _WIN32 if (GameArg.SndDisableSdlMixer) { @@ -312,7 +312,7 @@ int songs_play_song( int songnum, int repeat ) { int num_tracks = RBAGetNumberOfTracks(); - Song_playing = 0; + Song_playing = -1; if ((songnum < SONG_ENDGAME) && (songnum + 2 <= num_tracks)) { if (RBAPlayTracks(songnum + 2, songnum + 2, repeat ? redbook_repeat_func : NULL)) @@ -346,17 +346,21 @@ int songs_play_song( int songnum, int repeat ) if (Song_playing >= SONG_FIRST_LEVEL_SONG && songnum == SONG_ENDLEVEL && !strlen(GameCfg.CMMiscMusic[songnum])) return Song_playing; - Song_playing = 0; + Song_playing = -1; if (mix_play_file(GameCfg.CMMiscMusic[songnum], repeat, NULL)) Song_playing = songnum; break; } #endif default: - Song_playing = 0; + Song_playing = -1; break; } + // If we couldn't play the song, most likely because it wasn't specified, play no music. + if (Song_playing == -1) + songs_stop_all(); + return Song_playing; } @@ -377,7 +381,7 @@ int songs_play_level_song( int levelnum, int offset ) songs_init(); if (!Songs_initialized) return 0; - + songnum = (levelnum>0)?(levelnum-1):(-levelnum); switch (GameCfg.MusicType) @@ -387,7 +391,7 @@ int songs_play_level_song( int levelnum, int offset ) if (offset) return Song_playing; - Song_playing = 0; + Song_playing = -1; if ((Num_bim_songs - SONG_FIRST_LEVEL_SONG) > 0) { songnum = SONG_FIRST_LEVEL_SONG + (songnum % (Num_bim_songs - SONG_FIRST_LEVEL_SONG)); @@ -435,7 +439,7 @@ int songs_play_level_song( int levelnum, int offset ) tracknum = REDBOOK_FIRST_LEVEL_TRACK + (tracknum - n_tracks) - 1; } - Song_playing = 0; + Song_playing = -1; if (RBAEnabled() && (tracknum <= n_tracks)) { if (RBAPlayTracks(tracknum, !songs_haved1_cd()?n_tracks:tracknum, songs_haved1_cd() ? redbook_repeat_func : redbook_first_song_func)) @@ -477,7 +481,7 @@ int songs_play_level_song( int levelnum, int offset ) GameCfg.CMLevelMusicTrack[0] = GameCfg.CMLevelMusicTrack[0] - GameCfg.CMLevelMusicTrack[1]; } - Song_playing = 0; + Song_playing = -1; if (jukebox_play()) Song_playing = songnum + SONG_FIRST_LEVEL_SONG; @@ -485,14 +489,18 @@ int songs_play_level_song( int levelnum, int offset ) } #endif default: - Song_playing = 0; + Song_playing = -1; break; } + // If we couldn't play the song, most likely because it wasn't specified, play no music. + if (Song_playing == -1) + songs_stop_all(); + return Song_playing; } -// check which song is playing +// check which song is playing, or -1 if not playing anything int songs_is_playing() { return Song_playing; diff --git a/main/songs.h b/main/songs.h index 108397e0a..db2067991 100644 --- a/main/songs.h +++ b/main/songs.h @@ -28,7 +28,7 @@ void songs_pause(void); void songs_resume(void); void songs_pause_resume(void); -// check which song is playing +// check which song is playing, or -1 if not playing anything int songs_is_playing(); // set volume for selected music playback system