int songs_play_song( int songnum, int repeat ) { songs_init(); if (!Songs_initialized) return 0; switch (GameCfg.MusicType) { case MUSIC_TYPE_BUILTIN: { // EXCEPTION: If SONG_ENDLEVEL is not available, continue playing level song. if (Song_playing >= SONG_FIRST_LEVEL_SONG && songnum == SONG_ENDLEVEL && !PHYSFSX_exists(BIMSongs[songnum].filename, 1)) return Song_playing; Song_playing = -1; #ifdef _WIN32 if (GameArg.SndDisableSdlMixer) { if (digi_win32_play_midi_song( BIMSongs[songnum].filename, repeat )) // NOTE: If SDL_mixer active, this will still be called in mix_play_file in case file is hmp { Song_playing = songnum; } } else #endif #ifdef USE_SDLMIXER { if (mix_play_file(BIMSongs[songnum].filename, repeat, NULL)) { Song_playing = songnum; } } #endif break; } case MUSIC_TYPE_REDBOOK: { int num_tracks = RBAGetNumberOfTracks(); Song_playing = -1; if ((songnum < SONG_ENDGAME) && (songnum + 2 <= num_tracks)) { if (RBAPlayTracks(songnum + 2, songnum + 2, repeat ? redbook_repeat_func : NULL)) { Redbook_playing = songnum + 2; Song_playing = songnum; } } else if ((songnum == SONG_ENDGAME) && (REDBOOK_ENDGAME_TRACK <= num_tracks)) // The endgame track is the last track { if (RBAPlayTracks(REDBOOK_ENDGAME_TRACK, REDBOOK_ENDGAME_TRACK, repeat ? redbook_repeat_func : NULL)) { Redbook_playing = REDBOOK_ENDGAME_TRACK; Song_playing = songnum; } } else if ((songnum > SONG_ENDGAME) && (songnum + 1 <= num_tracks)) { if (RBAPlayTracks(songnum + 1, songnum + 1, repeat ? redbook_repeat_func : NULL)) { Redbook_playing = songnum + 1; Song_playing = songnum; } } break; } #ifdef USE_SDLMIXER case MUSIC_TYPE_CUSTOM: { // EXCEPTION: If SONG_ENDLEVEL is undefined, continue playing level song. if (Song_playing >= SONG_FIRST_LEVEL_SONG && songnum == SONG_ENDLEVEL && !strlen(GameCfg.CMMiscMusic[songnum])) return Song_playing; Song_playing = -1; if (mix_play_file(GameCfg.CMMiscMusic[songnum], repeat, NULL)) Song_playing = songnum; break; } #endif default: 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; }
// play track given by levelnum (depending on the music type and it's playing behaviour) or increment/decrement current track number via offset value int songs_play_level_song( int levelnum, int offset ) { int songnum; Assert( levelnum != 0 ); songs_init(); if (!Songs_initialized) return 0; songnum = (levelnum>0)?(levelnum-1):(-levelnum); switch (GameCfg.MusicType) { case MUSIC_TYPE_BUILTIN: { if (offset) return Song_playing; 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)); #ifdef _WIN32 if (GameArg.SndDisableSdlMixer) { if (digi_win32_play_midi_song( BIMSongs[songnum].filename, 1 )) // NOTE: If SDL_mixer active, this will still be called in mix_play_file in case file is hmp { Song_playing = songnum; } } #ifdef USE_SDLMIXER else #endif #endif #ifdef USE_SDLMIXER { if (mix_play_file(BIMSongs[songnum].filename, 1, NULL)) { Song_playing = songnum; } } #endif } break; } case MUSIC_TYPE_REDBOOK: { int n_tracks = RBAGetNumberOfTracks(); int tracknum; if (!offset) { // we have just been told to play the same as we do already -> ignore if (Song_playing >= SONG_FIRST_LEVEL_SONG && songnum + SONG_FIRST_LEVEL_SONG == Song_playing) return Song_playing; tracknum = REDBOOK_FIRST_LEVEL_TRACK + ((n_tracks<=REDBOOK_FIRST_LEVEL_TRACK) ? 0 : (songnum % (n_tracks-REDBOOK_FIRST_LEVEL_TRACK))); } else { tracknum = Redbook_playing+offset; if (tracknum < REDBOOK_FIRST_LEVEL_TRACK) tracknum = n_tracks - (REDBOOK_FIRST_LEVEL_TRACK - tracknum) + 1; else if (tracknum > n_tracks) tracknum = REDBOOK_FIRST_LEVEL_TRACK + (tracknum - n_tracks) - 1; } 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)) { Song_playing = songnum + SONG_FIRST_LEVEL_SONG; Redbook_playing = tracknum; } } break; } #ifdef USE_SDLMIXER case MUSIC_TYPE_CUSTOM: { if (GameCfg.CMLevelMusicPlayOrder == MUSIC_CM_PLAYORDER_RAND) GameCfg.CMLevelMusicTrack[0] = d_rand() % GameCfg.CMLevelMusicTrack[1]; // simply a random selection - no check if this song has already been played. But that's how I roll! else if (!offset) { if (GameCfg.CMLevelMusicPlayOrder == MUSIC_CM_PLAYORDER_CONT) { static int last_songnum = -1; if (Song_playing >= SONG_FIRST_LEVEL_SONG) return Song_playing; // As soon as we start a new level, go to next track if (last_songnum != -1 && songnum != last_songnum) ((GameCfg.CMLevelMusicTrack[0]+1>=GameCfg.CMLevelMusicTrack[1])?GameCfg.CMLevelMusicTrack[0]=0:GameCfg.CMLevelMusicTrack[0]++); last_songnum = songnum; } else if (GameCfg.CMLevelMusicPlayOrder == MUSIC_CM_PLAYORDER_LEVEL) GameCfg.CMLevelMusicTrack[0] = (songnum % GameCfg.CMLevelMusicTrack[1]); } else { GameCfg.CMLevelMusicTrack[0] += offset; if (GameCfg.CMLevelMusicTrack[0] < 0) GameCfg.CMLevelMusicTrack[0] = GameCfg.CMLevelMusicTrack[1] + GameCfg.CMLevelMusicTrack[0]; if (GameCfg.CMLevelMusicTrack[0] + 1 > GameCfg.CMLevelMusicTrack[1]) GameCfg.CMLevelMusicTrack[0] = GameCfg.CMLevelMusicTrack[0] - GameCfg.CMLevelMusicTrack[1]; } Song_playing = -1; if (jukebox_play()) Song_playing = songnum + SONG_FIRST_LEVEL_SONG; break; } #endif default: 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; }
int mix_play_file(char *filename, int loop, void (*hook_finished_track)()) { SDL_RWops *rw = NULL; PHYSFS_file *filehandle = NULL; char full_path[PATH_MAX]; char *fptr; unsigned int bufsize = 0; mix_free_music(); // stop and free what we're already playing, if anything fptr = strrchr(filename, '.'); if (fptr == NULL) return 0; // It's a .hmp! if (!stricmp(fptr, ".hmp")) { #ifdef _WIN32 // on _WIN32, play natively return digi_win32_play_midi_song( filename, loop ); #else // otherwise convert and load to current_music hmp2mid(filename, ¤t_music_hndlbuf, &bufsize); rw = SDL_RWFromConstMem(current_music_hndlbuf,bufsize*sizeof(char)); current_music = Mix_LoadMUS_RW(rw); #endif } // try loading music via given filename 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) { PHYSFSX_getRealPath(filename, full_path); current_music = Mix_LoadMUS(full_path); if (current_music) filename = full_path; // used later for possible error reporting } // still nothin'? Let's open via PhysFS in case it's located inside an archive if (!current_music) { filehandle = PHYSFS_openRead(filename); if (filehandle != NULL) { unsigned len = (unsigned)(PHYSFSX_UNSAFE_TRUNCATE_TO_32BIT_INT)PHYSFS_fileLength(filehandle); unsigned char *p = (unsigned char *)d_realloc(current_music_hndlbuf, sizeof(char)*len); if (p) { current_music_hndlbuf = p; bufsize = (unsigned int)(PHYSFSX_UNSAFE_TRUNCATE_TO_32BIT_INT)PHYSFS_read(filehandle, current_music_hndlbuf, sizeof(char), len); rw = SDL_RWFromConstMem(current_music_hndlbuf,bufsize*sizeof(char)); current_music = Mix_LoadMUS_RW(rw); } PHYSFS_close(filehandle); } } if (current_music) { Mix_PlayMusic(current_music, (loop ? -1 : 1)); Mix_HookMusicFinished(hook_finished_track ? hook_finished_track : mix_free_music); return 1; } else { con_printf(CON_CRITICAL,"Music %s could not be loaded: %s\n", filename, Mix_GetError()); mix_stop_music(); } return 0; }