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)

This commit is contained in:
Chris Taylor 2011-04-18 20:32:36 +08:00
parent a2806837e8
commit cc5a7d1359
8 changed files with 107 additions and 63 deletions

View file

@ -1,5 +1,9 @@
D2X-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, main/titles.c: 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

View file

@ -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();
}

View file

@ -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)))
{

View file

@ -92,12 +92,12 @@ int ReadConfigFile()
memset(GameCfg.CMMiscMusic[SONG_CREDITS],0,PATH_MAX+1);
#if defined(__APPLE__) && defined(__MACH__)
GameCfg.OrigTrackOrder = 1;
snprintf(GameCfg.CMLevelMusicPath, PATH_MAX, "%s/%s", PHYSFS_getUserDir(), "Music/iTunes/iTunes Music/Redbook Soundtrack/Descent II, Macintosh CD-ROM/");
snprintf(GameCfg.CMMiscMusic[SONG_TITLE], PATH_MAX, "%s/%s", PHYSFS_getUserDir(), "Music/iTunes/iTunes Music/Redbook Soundtrack/Descent II, Macintosh CD-ROM/02 Title.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/Redbook Soundtrack/Descent II, Macintosh CD-ROM/03 Crawl.mp3");
snprintf(GameCfg.CMLevelMusicPath, PATH_MAX, "%s", "descent2.m3u");
snprintf(GameCfg.CMMiscMusic[SONG_TITLE], PATH_MAX, "%s%s", PHYSFS_getUserDir(), "Music/iTunes/iTunes Music/Redbook Soundtrack/Descent II, Macintosh CD-ROM/02 Title.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/Redbook Soundtrack/Descent II, Macintosh CD-ROM/03 Crawl.mp3");
#endif
GameCfg.GammaLevel = 0;
memset(GameCfg.LastPlayer,0,CALLSIGN_LEN+1);

View file

@ -1539,6 +1539,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)
@ -1553,6 +1554,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)
{

View file

@ -36,7 +36,7 @@ COPYRIGHT 1993-1999 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;
@ -180,7 +180,7 @@ void songs_uninit()
if (BIMSongs != NULL)
d_free(BIMSongs);
Song_playing = 0;
Song_playing = -1;
Songs_initialized = 0;
}
@ -195,7 +195,7 @@ void songs_stop_all(void)
mix_stop_music();
#endif
Song_playing = 0;
Song_playing = -1;
}
void songs_pause(void)
@ -300,7 +300,7 @@ int songs_play_song( int songnum, int repeat )
{
case MUSIC_TYPE_BUILTIN:
{
Song_playing = 0;
Song_playing = -1;
#ifdef _WIN32
if (GameArg.SndDisableSdlMixer)
{
@ -325,7 +325,7 @@ int songs_play_song( int songnum, int repeat )
{
int num_tracks = RBAGetNumberOfTracks();
//Song_playing = 0; // keep playing current music if chosen song is unavailable (e.g. SONG_ENDLEVEL)
//Song_playing = -1; // keep playing current music if chosen song is unavailable (e.g. SONG_ENDLEVEL)
if ((songnum == SONG_TITLE) && (REDBOOK_TITLE_TRACK <= num_tracks))
{
if (RBAPlayTracks(REDBOOK_TITLE_TRACK, REDBOOK_TITLE_TRACK, repeat ? play_credits_track : NULL))
@ -351,7 +351,7 @@ 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],
// Play the credits track after the title track and loop the credits track if original CD track order was chosen
(songnum == SONG_TITLE && GameCfg.OrigTrackOrder) ? 0 : repeat,
@ -361,10 +361,14 @@ int songs_play_song( int songnum, int repeat )
}
#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;
}
@ -385,7 +389,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)
@ -395,7 +399,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));
@ -443,7 +447,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, n_tracks, redbook_first_song_func))
@ -464,7 +468,7 @@ int songs_play_level_song( int levelnum, int offset )
if (GameCfg.CMLevelMusicPlayOrder == MUSIC_CM_PLAYORDER_CONT)
{
static int last_songnum = -1;
if (Song_playing >= SONG_FIRST_LEVEL_SONG)
return Song_playing;
@ -485,7 +489,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;
@ -493,14 +497,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;

View file

@ -24,7 +24,7 @@ int songs_play_level_song( int levelnum, int offset );
//stop any songs - midi, redbook or jukebox - that are currently playing
void songs_stop_all(void);
// check which song is playing
// check which song is playing, or -1 if not playing anything
int songs_is_playing();
void songs_pause(void);

View file

@ -1250,7 +1250,7 @@ int new_briefing_screen(briefing *br, int first)
br->guy_bitmap_show = 0;
br->prev_ch = -1;
if (!songs_is_playing() && (br->hum_channel == -1))
if ((songs_is_playing() == -1) && (br->hum_channel == -1))
br->hum_channel = digi_start_sound( digi_xlat_sound(SOUND_BRIEFING_HUM), F1_0/2, 0xFFFF/2, 1, -1, -1, -1 );
return 1;