/* * This is an alternate backend for the music system. * It uses SDL_mixer to provide a more reliable playback, * and allow processing of multiple audio formats. * * -- MD2211 (2006-04-24) */ #include #include #include #include #include "args.h" #include "hmp2mid.h" #include "digi_mixer_music.h" #include "cfile.h" #include "u_mem.h" Mix_Music *current_music = NULL; void convert_hmp(char *filename, char *mid_filename) { if (1) //!PHYSFS_exists(mid_filename)) // allow custom MIDI in add-on hogs to be used without caching everything { const char *err; PHYSFS_file *hmp_in; PHYSFS_file *mid_out = PHYSFSX_openWriteBuffered(mid_filename); if (!mid_out) { con_printf(CON_CRITICAL," could not open: %s for writing: %s\n", mid_filename, PHYSFS_getLastError()); return; } con_printf(CON_DEBUG,"convert_hmp: converting %s to %s\n", filename, mid_filename); hmp_in = PHYSFSX_openReadBuffered(filename); if (!hmp_in) { con_printf(CON_CRITICAL," could not open: %s\n", filename); PHYSFS_close(mid_out); return; } err = hmp2mid(hmp_in, mid_out); PHYSFS_close(mid_out); PHYSFS_close(hmp_in); if (err) { con_printf(CON_CRITICAL,"%s\n", err); PHYSFS_delete(mid_filename); return; } } else { con_printf(CON_DEBUG,"convert_hmp: %s already exists\n", mid_filename); } } /* * Plays a music file from an absolute path */ int mix_play_file(char *filename, int loop, void (*hook_finished_track)()) { char tmp_file[PATH_MAX], real_filename[PATH_MAX], real_filename_absolute[PATH_MAX]; char *basedir = "music", *fptr; mix_free_music(); // stop and free what we're already playing, if anything fptr = strrchr(filename, '.'); if (fptr == NULL) return 0; snprintf(tmp_file, sizeof(char)*(strlen(filename)+1), filename); // It's a .hmp. Convert to mid, store ind music/ and pass the new filename. if (!stricmp(fptr, ".hmp")) { strcpy(tmp_file+strlen(tmp_file)-4,".mid"); if (!PHYSFS_isDirectory(basedir)) PHYSFS_mkdir(basedir); snprintf(real_filename, strlen(basedir)+strlen(tmp_file)+6, "%s/%s", basedir, tmp_file); convert_hmp(filename, real_filename); } else { snprintf(real_filename, sizeof(char)*(strlen(filename)+1), filename); } loop = loop ? -1 : 1; // loop means loop infinitely, otherwise play once current_music = Mix_LoadMUS(real_filename); // Could not open the file, yet. Try to get absolute path. if (!current_music) { PHYSFSX_getRealPath(real_filename, real_filename_absolute); current_music = Mix_LoadMUS(real_filename_absolute); } // Still no luck. Maybe the music is stored in an archive. Try that. // NOTE: This method should basically always work - making the above steps unnecessary. But for now it stays the last resort for the sake of memory swallowed by 'buf'. if (!current_music) { SDL_RWops *rw = NULL; PHYSFS_file *filehandle = NULL; char *buf = NULL; int bufsize = 0; filehandle = PHYSFS_openRead(real_filename); if (filehandle != NULL) { buf = realloc(buf, sizeof(char *)*PHYSFS_fileLength(filehandle)); bufsize = PHYSFS_read(filehandle, buf, sizeof(char), PHYSFS_fileLength(filehandle)); rw = SDL_RWFromConstMem(buf,bufsize*sizeof(char)); PHYSFS_close(filehandle); current_music = Mix_LoadMUS_RW(rw); } } if (current_music) { Mix_PlayMusic(current_music, loop); Mix_HookMusicFinished(hook_finished_track ? hook_finished_track : mix_free_music); return 1; } else { con_printf(CON_CRITICAL,"Music %s could not be loaded\n", real_filename_absolute); Mix_HaltMusic(); } return 0; } // What to do when stopping song playback void mix_free_music() { Mix_HaltMusic(); if (current_music) { Mix_FreeMusic(current_music); current_music = NULL; } } void mix_set_music_volume(int vol) { Mix_VolumeMusic(vol); } void mix_stop_music() { Mix_HaltMusic(); } void mix_pause_music() { Mix_PauseMusic(); } void mix_resume_music() { Mix_ResumeMusic(); } void mix_pause_resume_music() { if (Mix_PausedMusic()) Mix_ResumeMusic(); else if (Mix_PlayingMusic()) Mix_PauseMusic(); }