1 //----------------------------------------------------------------------------
2 //  EDGE Music handling Code
3 //----------------------------------------------------------------------------
4 //
5 //  Copyright (c) 1999-2009  The EDGE Team.
6 //
7 //  This program is free software; you can redistribute it and/or
8 //  modify it under the terms of the GNU General Public License
9 //  as published by the Free Software Foundation; either version 2
10 //  of the License, or (at your option) any later version.
11 //
12 //  This program is distributed in the hope that it will be useful,
13 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
14 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 //  GNU General Public License for more details.
16 //
17 //----------------------------------------------------------------------------
18 //
19 // -ACB- 1999/11/13 Written
20 //
21 
22 #include "i_defs.h"
23 
24 #include <stdlib.h>
25 
26 #include "epi/file.h"
27 #include "epi/filesystem.h"
28 
29 #include "ddf/main.h"
30 
31 #include "dm_state.h"
32 #include "s_sound.h"
33 #include "s_music.h"
34 #include "s_ogg.h"
35 #include "s_timid.h"
36 #include "m_misc.h"
37 #include "w_wad.h"
38 
39 // music slider value
40 int mus_volume;
41 
42 int var_music_dev;
43 
44 bool nomusic = false;
45 bool nocdmusic = false;
46 
47 
48 // Current music handle
49 static abstract_music_c *music_player;
50 
51 static int  entry_playing = -1;
52 static bool entry_looped;
53 
54 
S_ChangeMusic(int entrynum,bool loop)55 void S_ChangeMusic(int entrynum, bool loop)
56 {
57 	if (nomusic)
58 		return;
59 
60 	// -AJA- playlist number 0 reserved to mean "no music"
61 	if (entrynum <= 0)
62 	{
63 		S_StopMusic();
64 		return;
65 	}
66 
67 	// -AJA- don't restart the current song (DOOM compatibility)
68 	if (entrynum == entry_playing && entry_looped)
69 		return;
70 
71 	S_StopMusic();
72 
73 	entry_playing = entrynum;
74 	entry_looped  = loop;
75 
76 	// when we cannot find the music entry, no music will play
77 	const pl_entry_c *play = playlist.Find(entrynum);
78 	if (!play)
79 	{
80 		I_Warning("Could not find music entry [%d]\n", entrynum);
81 		return;
82 	}
83 
84 	float volume = slider_to_gain[mus_volume];
85 
86 	if (play->type == MUS_MP3)
87 	{
88 		I_Warning("S_ChangeMusic: MP3 music no longer supported.\n");
89 		return;
90 	}
91 
92 ///	if (play->type == MUS_CD)
93 ///	{
94 ///		int track = atoi(play->info);
95 ///		music_player = I_PlayCDMusic(track, volume, loop);
96 ///		return;
97 ///	}
98 
99 	if (play->type == MUS_OGG)
100 	{
101 		music_player = S_PlayOGGMusic(play, volume, loop);
102 		return;
103 	}
104 
105 	// open the file or lump, and read it into memory
106 	epi::file_c *F;
107 
108 	switch (play->infotype)
109 	{
110 		case MUSINF_FILE:
111 		{
112 			std::string fn = M_ComposeFileName(game_dir.c_str(), play->info.c_str());
113 
114 			F = epi::FS_Open(fn.c_str(), epi::file_c::ACCESS_READ | epi::file_c::ACCESS_BINARY);
115 
116 			if (! F)
117 			{
118 				I_Warning("S_ChangeMusic: Can't Find File '%s'\n", fn.c_str());
119 				return;
120 			}
121 
122 			break;
123 		}
124 
125 		case MUSINF_LUMP:
126 		{
127 			int lump = W_CheckNumForName(play->info);
128 			if (lump < 0)
129 			{
130 				I_Warning("S_ChangeMusic: LUMP '%s' not found.\n", play->info.c_str());
131 				return;
132 			}
133 
134 			F = W_OpenLump(lump);
135 			break;
136 		}
137 
138 		default:
139 			I_Printf("S_ChangeMusic: invalid method %d for MUS/MIDI\n", play->infotype);
140 			return;
141 	}
142 
143 	int length = F->GetLength();
144 
145 	byte *data = F->LoadIntoMemory();
146 
147 	if (! data)
148 	{
149 		delete F;
150 
151 		I_Warning("S_ChangeMusic: Error loading data.\n");
152 		return;
153 	}
154 	if (length < 4)
155 	{
156 		delete F;
157 		delete data;
158 
159 		I_Printf("S_ChangeMusic: ignored short data (%d bytes)\n", length);
160 		return;
161 	}
162 
163 	if (memcmp(data, "Ogg", 3) == 0)
164 	{
165 		delete F;
166 		delete data;
167 
168 		music_player = S_PlayOGGMusic(play, volume, loop);
169 		return;
170 	}
171 
172 	bool is_mus = (data[0] == 'M' && data[1] == 'U' && data[2] == 'S');
173 
174 	if (var_music_dev == 0 && is_mus)
175 		music_player = I_PlayNativeMusic(data, length, volume, loop);
176 	else
177 		music_player = S_PlayTimidity(data, length, is_mus, volume, loop);
178 
179 #if 0
180 	byte *data;
181 	int datlength;
182 	int datnum;
183 	i_music_info_t musdat;
184 
185 	// -ACB- 2000/06/06 This is not system specific
186 	if (play->infotype == MUSINF_FILE)
187 	{
188 		data = NULL;
189 
190 		// -AJA- 2005/01/15: filenames in DDF relative to GAMEDIR
191 
192 		//
193 		// -ACB- 2004/08/18 Something of a hack until we revamp this to be
194 		//                  a little less platform dependent and a little
195 		//                  more object orientated
196 		//
197 		if (play->type != MUS_OGG)
198 		{
199 			data = M_GetFileData(fn.c_str(), &datlength);
200 
201 			if (!data)
202 			{
203 				I_Warning("S_ChangeMusic: Can't Load File '%s'\n", fn.c_str());
204 				return;
205 			}
206 
207 			musdat.format = IMUSSF_DATA;
208 			musdat.info.data.ptr = data;
209 			musdat.info.data.size = datlength;
210 		}
211 		else  /* OGG Vorbis */
212 		{
213 			if (! epi::FS_Access(fn.c_str(), epi::file_c::ACCESS_READ))
214 			{
215 				I_Warning("S_ChangeMusic: Can't Load OGG '%s'\n", fn.c_str());
216 				return;
217 			}
218 
219 			musdat.format = IMUSSF_FILE;
220 			musdat.info.file.name = fn.c_str();
221 		}
222 
223 		musichandle = I_MusicPlayback(&musdat, play->type, looping, volume);
224 
225 		if (data)
226 			delete [] data;
227 	}
228 
229 	if (play->infotype == MUSINF_LUMP)
230 	{
231 		datnum = W_CheckNumForName(play->info);
232 		if (datnum != -1)
233 		{
234 			datlength = W_LumpLength(datnum);
235 			data = (byte*)W_CacheLumpNum(datnum);
236 
237 			musdat.format = IMUSSF_DATA;
238 			musdat.info.data.ptr = data;
239 			musdat.info.data.size = datlength;
240 
241 			musichandle = I_MusicPlayback(&musdat, play->type, looping, volume);
242 			W_DoneWithLump(data);
243 		}
244 		else
245 		{
246 		}
247 	}
248 
249 	if (play->infotype == MUSINF_TRACK)
250 	{
251 		musdat.format = IMUSSF_CD;
252 		musdat.info.cd.track = atoi(play->info);
253 
254 		musichandle = I_MusicPlayback(&musdat, play->type, looping, volume);
255 	}
256 
257 	if (musichandle == -1)
258 		I_Printf("%s\n", I_MusicReturnError());
259 
260 #endif
261 }
262 
263 
S_ResumeMusic(void)264 void S_ResumeMusic(void)
265 {
266 	if (music_player)
267 		music_player->Resume();
268 }
269 
270 
S_PauseMusic(void)271 void S_PauseMusic(void)
272 {
273 	if (music_player)
274 		music_player->Pause();
275 }
276 
277 
S_StopMusic(void)278 void S_StopMusic(void)
279 {
280 	// You can't stop the rock!! This does...
281 
282 	if (music_player)
283 	{
284 		music_player->Stop();
285 
286 		delete music_player;
287 		music_player = NULL;
288 	}
289 
290 	entry_playing = -1;
291 	entry_looped  = false;
292 }
293 
294 
S_MusicTicker(void)295 void S_MusicTicker(void)
296 {
297 	if (music_player)
298 		music_player->Ticker();
299 }
300 
301 
S_ChangeMusicVolume(void)302 void S_ChangeMusicVolume(void)
303 {
304 	if (music_player)
305 		music_player->Volume(slider_to_gain[mus_volume]);
306 }
307 
308 
309 //--- editor settings ---
310 // vi:ts=4:sw=4:noexpandtab
311