1 //**************************************************************************
2 //**
3 //**	##   ##    ##    ##   ##   ####     ####   ###     ###
4 //**	##   ##  ##  ##  ##   ##  ##  ##   ##  ##  ####   ####
5 //**	 ## ##  ##    ##  ## ##  ##    ## ##    ## ## ## ## ##
6 //**	 ## ##  ########  ## ##  ##    ## ##    ## ##  ###  ##
7 //**	  ###   ##    ##   ###    ##  ##   ##  ##  ##       ##
8 //**	   #    ##    ##    #      ####     ####   ##       ##
9 //**
10 //**	$Id: snd_sdlmusic.cpp 4137 2010-03-04 22:39:17Z dj_jl $
11 //**
12 //**	Copyright (C) 1999-2006 Jānis Legzdiņš
13 //**
14 //**	This program is free software; you can redistribute it and/or
15 //**  modify it under the terms of the GNU General Public License
16 //**  as published by the Free Software Foundation; either version 2
17 //**  of the License, or (at your option) any later version.
18 //**
19 //**	This program is distributed in the hope that it will be useful,
20 //**  but WITHOUT ANY WARRANTY; without even the implied warranty of
21 //**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22 //**  GNU General Public License for more details.
23 //**
24 //**************************************************************************
25 
26 // HEADER FILES ------------------------------------------------------------
27 
28 #include <SDL.h>
29 #include <SDL_mixer.h>
30 
31 #include "gamedefs.h"
32 #include "snd_local.h"
33 
34 // MACROS ------------------------------------------------------------------
35 
36 // TYPES -------------------------------------------------------------------
37 
38 class VSDLMidiDevice : public VMidiDevice
39 {
40 public:
41 	bool		DidInitMixer;
42 	Mix_Music*	music;
43 
44 	void*		Mus_SndPtr;
45 	bool		MusicPaused;
46 	float		MusVolume;
47 
48 	VSDLMidiDevice();
49 	void Init();
50 	void Shutdown();
51 	void SetVolume(float);
52 	void Tick(float);
53 	void Play(void*, int, const char*, bool);
54 	void Pause();
55 	void Resume();
56 	void Stop();
57 	bool IsPlaying();
58 };
59 
60 // EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
61 
62 // PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
63 
64 // PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
65 
66 // EXTERNAL DATA DECLARATIONS ----------------------------------------------
67 
68 extern bool					sdl_mixer_initialised;
69 
70 // PUBLIC DATA DEFINITIONS -------------------------------------------------
71 
72 IMPLEMENT_MIDI_DEVICE(VSDLMidiDevice, MIDIDRV_Default, "Default",
73 	"SDL midi device", NULL);
74 
75 // PRIVATE DATA DEFINITIONS ------------------------------------------------
76 
77 // CODE --------------------------------------------------------------------
78 
79 //==========================================================================
80 //
81 //	VSDLMidiDevice::VSDLMidiDevice
82 //
83 //==========================================================================
84 
VSDLMidiDevice()85 VSDLMidiDevice::VSDLMidiDevice()
86 : DidInitMixer(false)
87 , music(NULL)
88 , Mus_SndPtr(NULL)
89 , MusicPaused(false)
90 , MusVolume(-1)
91 {
92 }
93 
94 //==========================================================================
95 //
96 //	VSDLMidiDevice::Init
97 //
98 //==========================================================================
99 
Init()100 void VSDLMidiDevice::Init()
101 {
102 	guard(VSDLMidiDevice::Init);
103 	if (!sdl_mixer_initialised)
104 	{
105 		//	Currently I failed to make OpenAL work with SDL music.
106 #if 1
107 		return;
108 #else
109 		if (Mix_OpenAudio(MIX_DEFAULT_FREQUENCY, MIX_DEFAULT_FORMAT,
110 			MIX_DEFAULT_CHANNELS, 4096) < 0)
111 		{
112 			GCon->Logf(NAME_Init, "Failed to intialise SDL mixer");
113 			return;
114 		}
115 		DidInitMixer = true;
116 #endif
117 	}
118 	Initialised = true;
119 	unguard;
120 }
121 
122 //==========================================================================
123 //
124 //	VSDLMidiDevice::Shutdown
125 //
126 //==========================================================================
127 
Shutdown()128 void VSDLMidiDevice::Shutdown()
129 {
130 	guard(VSDLMidiDevice::Shutdown);
131 	if (Initialised)
132 	{
133 		Stop();
134 		if (DidInitMixer)
135 		{
136 			Mix_CloseAudio();
137 		}
138 	}
139 	unguard;
140 }
141 
142 //==========================================================================
143 //
144 //	VSDLMidiDevice::SetVolume
145 //
146 //==========================================================================
147 
SetVolume(float Volume)148 void VSDLMidiDevice::SetVolume(float Volume)
149 {
150 	guard(VSDLMidiDevice::SetVolume);
151 	if (Volume != MusVolume)
152 	{
153 		MusVolume = Volume;
154 		Mix_VolumeMusic(int(MusVolume * 255));
155 	}
156 	unguard;
157 }
158 
159 //==========================================================================
160 //
161 //  VSDLMidiDevice::Tick
162 //
163 //==========================================================================
164 
Tick(float)165 void VSDLMidiDevice::Tick(float)
166 {
167 }
168 
169 //==========================================================================
170 //
171 //	VSDLMidiDevice::Play
172 //
173 //==========================================================================
174 
Play(void * Data,int len,const char * song,bool loop)175 void VSDLMidiDevice::Play(void* Data, int len, const char* song, bool loop)
176 {
177 	guard(VSDLMidiDevice::Play);
178 	Mus_SndPtr = Data;
179 	VStr TmpFileName = fl_savedir.IsNotEmpty() ? fl_savedir + "/vv_temp.mid" :
180 		"vv_temp.mid";
181 	FILE* f = fopen(*TmpFileName, "wb");
182 	if (!f)
183 	{
184 		return;
185 	}
186 	fwrite(Mus_SndPtr, 1, len, f);
187 	fclose(f);
188 
189 	music = Mix_LoadMUS(*TmpFileName);
190 	remove(*TmpFileName);
191 
192 	if (!music)
193 	{
194 		Z_Free(Mus_SndPtr);
195 		Mus_SndPtr = NULL;
196 		return;
197 	}
198 
199 	Mix_FadeInMusic(music, loop, 2000);
200 
201 	if (!MusVolume || MusicPaused)
202 	{
203 		Mix_PauseMusic();
204 	}
205 	CurrSong = VName(song, VName::AddLower8);
206 	CurrLoop = loop;
207 	unguard;
208 }
209 
210 //==========================================================================
211 //
212 //  VSDLMidiDevice::Pause
213 //
214 //==========================================================================
215 
Pause()216 void VSDLMidiDevice::Pause()
217 {
218 	guard(VSDLMidiDevice::Pause);
219 	Mix_PauseMusic();
220 	MusicPaused = true;
221 	unguard;
222 }
223 
224 //==========================================================================
225 //
226 //  VSDLMidiDevice::Resume
227 //
228 //==========================================================================
229 
Resume()230 void VSDLMidiDevice::Resume()
231 {
232 	guard(VSDLMidiDevice::Resume);
233 	if (MusVolume)
234 		Mix_ResumeMusic();
235 	MusicPaused = false;
236 	unguard;
237 }
238 
239 //==========================================================================
240 //
241 //  VSDLMidiDevice::Stop
242 //
243 //==========================================================================
244 
Stop()245 void VSDLMidiDevice::Stop()
246 {
247 	guard(VSDLMidiDevice::Stop);
248 	if (music)
249 	{
250 		Mix_HaltMusic();
251 		Mix_FreeMusic(music);
252 		music = NULL;
253 	}
254 	if (Mus_SndPtr)
255 	{
256 		Z_Free(Mus_SndPtr);
257 		Mus_SndPtr = NULL;
258 	}
259 	CurrSong = NAME_None;
260 	unguard;
261 }
262 
263 //==========================================================================
264 //
265 //  VSDLMidiDevice::IsPlaying
266 //
267 //==========================================================================
268 
IsPlaying()269 bool VSDLMidiDevice::IsPlaying()
270 {
271 	guard(VSDLMidiDevice::IsPlaying);
272 	return !!music;
273 	unguard;
274 }
275