2006-10-17 20:52:09 +00:00
|
|
|
/*
|
|
|
|
* 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 <SDL/SDL.h>
|
|
|
|
#include <SDL/SDL_mixer.h>
|
|
|
|
#include <string.h>
|
2008-01-23 17:25:09 +00:00
|
|
|
#include <stdlib.h>
|
|
|
|
|
2006-10-17 20:52:09 +00:00
|
|
|
#include "args.h"
|
|
|
|
#include "hmp2mid.h"
|
2007-09-18 13:37:39 +00:00
|
|
|
#include "digi_mixer_music.h"
|
2006-10-17 20:52:09 +00:00
|
|
|
#include "cfile.h"
|
2008-01-23 17:25:09 +00:00
|
|
|
#include "u_mem.h"
|
2006-10-17 20:52:09 +00:00
|
|
|
|
2007-02-14 21:02:46 +00:00
|
|
|
#define MIX_MUSIC_DEBUG 0
|
2006-10-17 20:52:09 +00:00
|
|
|
#define MUSIC_FADE_TIME 500 //milliseconds
|
|
|
|
|
|
|
|
Mix_Music *current_music = NULL;
|
|
|
|
|
2006-10-18 17:08:59 +00:00
|
|
|
void convert_hmp(char *filename, char *mid_filename) {
|
|
|
|
|
2008-01-26 01:16:31 +00:00
|
|
|
if (1) //!PHYSFS_exists(mid_filename)) // allow custom MIDI in add-on hogs to be used without caching everything
|
2008-01-23 17:25:09 +00:00
|
|
|
{
|
2006-10-17 20:52:09 +00:00
|
|
|
const char *err;
|
2008-01-23 17:25:09 +00:00
|
|
|
PHYSFS_file *hmp_in;
|
|
|
|
PHYSFS_file *mid_out = PHYSFSX_openWriteBuffered(mid_filename);
|
2006-10-17 20:52:09 +00:00
|
|
|
|
|
|
|
if (!mid_out) {
|
2008-04-06 20:23:28 +00:00
|
|
|
con_printf(CON_CRITICAL," could not open: %s for writing: %s\n", mid_filename, PHYSFS_getLastError());
|
2006-10-17 20:52:09 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2008-04-06 20:23:28 +00:00
|
|
|
con_printf(CON_DEBUG,"convert_hmp: converting %s to %s\n", filename, mid_filename);
|
2008-01-23 17:25:09 +00:00
|
|
|
|
|
|
|
hmp_in = PHYSFSX_openReadBuffered(filename);
|
2006-10-17 20:52:09 +00:00
|
|
|
|
|
|
|
if (!hmp_in) {
|
2008-04-06 20:23:28 +00:00
|
|
|
con_printf(CON_CRITICAL," could not open: %s\n", filename);
|
2008-01-23 17:25:09 +00:00
|
|
|
PHYSFS_close(mid_out);
|
2006-10-17 20:52:09 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2008-01-23 17:25:09 +00:00
|
|
|
err = hmp2mid(hmp_in, mid_out);
|
2006-10-17 20:52:09 +00:00
|
|
|
|
2008-01-23 17:25:09 +00:00
|
|
|
PHYSFS_close(mid_out);
|
|
|
|
PHYSFS_close(hmp_in);
|
2006-10-17 20:52:09 +00:00
|
|
|
|
|
|
|
if (err) {
|
2008-04-06 20:23:28 +00:00
|
|
|
con_printf(CON_CRITICAL,"%s\n", err);
|
2008-01-23 17:25:09 +00:00
|
|
|
PHYSFS_delete(mid_filename);
|
2006-10-17 20:52:09 +00:00
|
|
|
return;
|
|
|
|
}
|
2008-01-23 17:25:09 +00:00
|
|
|
}
|
|
|
|
else {
|
2008-04-06 20:23:28 +00:00
|
|
|
con_printf(CON_DEBUG,"convert_hmp: %s already exists\n", mid_filename);
|
2008-01-23 17:25:09 +00:00
|
|
|
}
|
2006-10-17 20:52:09 +00:00
|
|
|
}
|
|
|
|
|
2008-01-23 17:25:09 +00:00
|
|
|
/*
|
|
|
|
* Plays a music given its name (regular game songs)
|
|
|
|
*/
|
2006-10-17 20:52:09 +00:00
|
|
|
|
2008-01-23 17:25:09 +00:00
|
|
|
void mix_play_music(char *filename, int loop) {
|
2007-10-13 23:49:07 +00:00
|
|
|
int i, got_end=0;
|
2008-01-23 17:25:09 +00:00
|
|
|
char rel_filename[32]; // just the filename of the actual music file used
|
2006-10-18 17:08:59 +00:00
|
|
|
char music_title[16];
|
2008-01-23 17:25:09 +00:00
|
|
|
char *basedir = "Music";
|
|
|
|
|
2006-10-18 17:08:59 +00:00
|
|
|
// Quick hack to filter out the .hmp extension
|
2006-10-17 20:52:09 +00:00
|
|
|
for (i=0; !got_end; i++) {
|
|
|
|
switch (filename[i]) {
|
|
|
|
case '.':
|
|
|
|
case '\0':
|
2006-10-18 17:08:59 +00:00
|
|
|
music_title[i] = '\0';
|
2006-10-17 20:52:09 +00:00
|
|
|
got_end = 1;
|
2006-10-18 17:08:59 +00:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
music_title[i] = filename[i];
|
2006-10-17 20:52:09 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-01-23 17:25:09 +00:00
|
|
|
if (!PHYSFS_isDirectory(basedir))
|
|
|
|
PHYSFS_mkdir(basedir); // tidy up those files
|
2007-10-13 23:49:07 +00:00
|
|
|
|
2006-10-17 20:52:09 +00:00
|
|
|
// What is the extension of external files? If none, default to internal MIDI
|
2007-10-13 23:49:07 +00:00
|
|
|
if (GameArg.SndExternalMusic) {
|
2009-01-14 19:54:45 +00:00
|
|
|
#ifdef _MSC_VER
|
|
|
|
#define snprintf _snprintf
|
|
|
|
#endif
|
2008-06-01 12:53:03 +00:00
|
|
|
snprintf(rel_filename, strlen(basedir)+strlen(music_title)+6, "%s/%s.%s", basedir, music_title, GameArg.SndExternalMusic); // add extension
|
2006-10-17 20:52:09 +00:00
|
|
|
}
|
|
|
|
else {
|
2008-06-01 12:53:03 +00:00
|
|
|
snprintf(rel_filename, strlen(basedir)+strlen(music_title)+6, "%s/%s.mid", basedir, music_title);
|
2007-10-13 23:49:07 +00:00
|
|
|
convert_hmp(filename, rel_filename);
|
2006-10-17 20:52:09 +00:00
|
|
|
}
|
|
|
|
|
2009-03-03 12:55:27 +00:00
|
|
|
mix_play_file(rel_filename, loop, NULL);
|
2007-03-12 21:56:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-01-23 17:25:09 +00:00
|
|
|
/*
|
|
|
|
* Plays a music file from an absolute path (used by jukebox)
|
|
|
|
*/
|
|
|
|
|
2009-03-03 12:55:27 +00:00
|
|
|
void mix_play_file(char *filename, int loop, void (*hook_finished_track)()) {
|
2008-01-23 17:25:09 +00:00
|
|
|
char real_filename[PATH_MAX];
|
|
|
|
|
2009-03-03 12:55:27 +00:00
|
|
|
mix_free_music(); // stop and free what we're already playing, if anything
|
|
|
|
|
2008-01-23 17:25:09 +00:00
|
|
|
PHYSFSX_getRealPath(filename, real_filename); // build absolute path
|
2007-03-12 21:56:41 +00:00
|
|
|
|
2009-03-03 12:55:27 +00:00
|
|
|
loop = loop ? -1 : 1; // loop means loop infinitely, otherwise play once
|
2008-05-01 21:40:34 +00:00
|
|
|
|
2008-06-04 19:30:43 +00:00
|
|
|
current_music = Mix_LoadMUS(real_filename);
|
|
|
|
|
|
|
|
if (current_music) {
|
2006-10-17 20:52:09 +00:00
|
|
|
if (Mix_PlayingMusic()) {
|
|
|
|
// Fade-in effect sounds cleaner if we're already playing something
|
|
|
|
Mix_FadeInMusic(current_music, loop, MUSIC_FADE_TIME);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
Mix_PlayMusic(current_music, loop);
|
|
|
|
}
|
2008-05-01 21:40:34 +00:00
|
|
|
|
2009-03-03 12:55:27 +00:00
|
|
|
Mix_HookMusicFinished(hook_finished_track ? hook_finished_track : mix_free_music);
|
2006-10-17 20:52:09 +00:00
|
|
|
}
|
|
|
|
else {
|
2008-04-06 20:23:28 +00:00
|
|
|
con_printf(CON_CRITICAL,"Music %s could not be loaded\n", real_filename);
|
2006-10-17 20:52:09 +00:00
|
|
|
Mix_HaltMusic();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-03-23 08:42:24 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* See if a music file exists, taking into account possible -music_ext option
|
|
|
|
*/
|
|
|
|
|
|
|
|
int mix_music_exists(const char *filename)
|
|
|
|
{
|
|
|
|
char rel_filename[32]; // just the filename of the actual music file used
|
|
|
|
char music_file[16];
|
|
|
|
char *basedir = "Music";
|
|
|
|
|
|
|
|
if (GameArg.SndExternalMusic)
|
|
|
|
{
|
|
|
|
change_filename_extension(music_file, filename, GameArg.SndExternalMusic);
|
|
|
|
sprintf(rel_filename, "%s/%s", basedir, music_file);
|
|
|
|
return PHYSFS_exists(rel_filename);
|
|
|
|
}
|
|
|
|
|
|
|
|
return PHYSFS_exists(filename);
|
|
|
|
}
|
|
|
|
|
2008-01-10 20:35:59 +00:00
|
|
|
// What to do when stopping song playback
|
2009-03-03 12:55:27 +00:00
|
|
|
void mix_free_music() {
|
2008-01-10 20:35:59 +00:00
|
|
|
Mix_HaltMusic();
|
2008-06-04 19:30:43 +00:00
|
|
|
if (current_music)
|
|
|
|
{
|
|
|
|
Mix_FreeMusic(current_music);
|
|
|
|
current_music = NULL;
|
|
|
|
}
|
2008-01-10 20:35:59 +00:00
|
|
|
}
|
|
|
|
|
2006-10-17 20:52:09 +00:00
|
|
|
void mix_set_music_volume(int vol) {
|
|
|
|
Mix_VolumeMusic(vol);
|
|
|
|
}
|
|
|
|
|
|
|
|
void mix_stop_music() {
|
|
|
|
Mix_HaltMusic();
|
|
|
|
}
|