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