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