summaryrefslogtreecommitdiff
path: root/src/i_sdlmusic.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/i_sdlmusic.c')
-rw-r--r--src/i_sdlmusic.c317
1 files changed, 317 insertions, 0 deletions
diff --git a/src/i_sdlmusic.c b/src/i_sdlmusic.c
new file mode 100644
index 00000000..d2471578
--- /dev/null
+++ b/src/i_sdlmusic.c
@@ -0,0 +1,317 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// DESCRIPTION:
+// System interface for music.
+//
+//-----------------------------------------------------------------------------
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "SDL.h"
+#include "SDL_mixer.h"
+
+#include "doomdef.h"
+#include "memio.h"
+#include "mus2mid.h"
+
+#include "deh_main.h"
+#include "m_misc.h"
+#include "s_sound.h"
+#include "w_wad.h"
+#include "z_zone.h"
+
+#define MAXMIDLENGTH (96 * 1024)
+
+static boolean music_initialised = false;
+
+// If this is true, this module initialised SDL sound and has the
+// responsibility to shut it down
+
+static boolean sdl_was_initialised = false;
+
+static boolean musicpaused = false;
+static int current_music_volume;
+
+void I_ShutdownMusic(void)
+{
+ if (music_initialised)
+ {
+ Mix_HaltMusic();
+ music_initialised = false;
+
+ if (sdl_was_initialised)
+ {
+ Mix_CloseAudio();
+ SDL_QuitSubSystem(SDL_INIT_AUDIO);
+ sdl_was_initialised = false;
+ }
+ }
+}
+
+static boolean SDLIsInitialised(void)
+{
+ int freq, channels;
+ Uint16 format;
+
+ return Mix_QuerySpec(&freq, &format, &channels) != 0;
+}
+
+void I_InitMusic()
+{
+ // When trying to run with music enabled on OSX, display
+ // a warning message.
+
+#ifdef __MACOSX__
+ printf("\n"
+ " *** WARNING ***\n"
+ " Music playback on OSX may cause crashes and\n"
+ " is disabled by default.\n"
+ "\n");
+#endif
+
+ // If SDL_mixer is not initialised, we have to initialise it
+ // and have the responsibility to shut it down later on.
+
+ if (!SDLIsInitialised())
+ {
+ if (SDL_Init(SDL_INIT_AUDIO) < 0)
+ {
+ fprintf(stderr, "Unable to set up sound.\n");
+ return;
+ }
+
+ if (Mix_OpenAudio(snd_samplerate, AUDIO_S16SYS, 2, 1024) < 0)
+ {
+ fprintf(stderr, "Error initialising SDL_mixer: %s\n", Mix_GetError());
+ SDL_QuitSubSystem(SDL_INIT_AUDIO);
+ return;
+ }
+
+ SDL_PauseAudio(0);
+
+ sdl_was_initialised = true;
+ }
+
+ music_initialised = true;
+}
+
+//
+// SDL_mixer's native MIDI music playing does not pause properly.
+// As a workaround, set the volume to 0 when paused.
+//
+
+static void UpdateMusicVolume(void)
+{
+ int vol;
+
+ if (musicpaused)
+ {
+ vol = 0;
+ }
+ else
+ {
+ vol = (current_music_volume * MIX_MAX_VOLUME) / 127;
+ }
+
+ Mix_VolumeMusic(vol);
+}
+
+// MUSIC API - dummy. Some code from DOS version.
+void I_SetMusicVolume(int volume)
+{
+ // Internal state variable.
+ current_music_volume = volume;
+
+ UpdateMusicVolume();
+}
+
+void I_PlaySong(void *handle, int looping)
+{
+ Mix_Music *music = (Mix_Music *) handle;
+ int loops;
+
+ if (!music_initialised)
+ {
+ return;
+ }
+
+ if (handle == NULL)
+ {
+ return;
+ }
+
+ if (looping)
+ {
+ loops = -1;
+ }
+ else
+ {
+ loops = 1;
+ }
+
+ Mix_PlayMusic(music, loops);
+}
+
+void I_PauseSong (void *handle)
+{
+ if (!music_initialised)
+ {
+ return;
+ }
+
+ musicpaused = true;
+
+ UpdateMusicVolume();
+}
+
+void I_ResumeSong (void *handle)
+{
+ if (!music_initialised)
+ {
+ return;
+ }
+
+ musicpaused = false;
+
+ UpdateMusicVolume();
+}
+
+void I_StopSong(void *handle)
+{
+ if (!music_initialised)
+ {
+ return;
+ }
+
+ Mix_HaltMusic();
+}
+
+void I_UnRegisterSong(void *handle)
+{
+ Mix_Music *music = (Mix_Music *) handle;
+
+ if (!music_initialised)
+ {
+ return;
+ }
+
+ if (handle == NULL)
+ {
+ return;
+ }
+
+ Mix_FreeMusic(music);
+}
+
+// Determine whether memory block is a .mid file
+
+static boolean IsMid(byte *mem, int len)
+{
+ return len > 4 && !memcmp(mem, "MThd", 4);
+}
+
+static boolean ConvertMus(byte *musdata, int len, char *filename)
+{
+ MEMFILE *instream;
+ MEMFILE *outstream;
+ void *outbuf;
+ size_t outbuf_len;
+ int result;
+
+ instream = mem_fopen_read(musdata, len);
+ outstream = mem_fopen_write();
+
+ result = mus2mid(instream, outstream);
+
+ if (result == 0)
+ {
+ mem_get_buf(outstream, &outbuf, &outbuf_len);
+
+ M_WriteFile(filename, outbuf, outbuf_len);
+ }
+
+ mem_fclose(instream);
+ mem_fclose(outstream);
+
+ return result;
+}
+
+void *I_RegisterSong(void *data, int len)
+{
+ char *filename;
+ Mix_Music *music;
+
+ if (!music_initialised)
+ {
+ return NULL;
+ }
+
+ // MUS files begin with "MUS"
+ // Reject anything which doesnt have this signature
+
+ filename = M_TempFile("doom.mid");
+
+ if (IsMid(data, len) && len < MAXMIDLENGTH)
+ {
+ M_WriteFile(filename, data, len);
+ }
+ else
+ {
+ // Assume a MUS file and try to convert
+
+ ConvertMus(data, len, filename);
+ }
+
+ // Load the MIDI
+
+ music = Mix_LoadMUS(filename);
+
+ if (music == NULL)
+ {
+ // Failed to load
+
+ fprintf(stderr, "Error loading midi: %s\n", Mix_GetError());
+ }
+
+ // remove file now
+
+ remove(filename);
+
+ Z_Free(filename);
+
+ return music;
+}
+
+// Is the song playing?
+boolean I_QrySongPlaying(void *handle)
+{
+ if (!music_initialised)
+ {
+ return false;
+ }
+
+ return Mix_PlayingMusic();
+}
+
+
+