S_LoadSound now automatically tries both with and without sound/ when loading sounds...
[divverent/darkplaces.git] / cd_shared.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20 // Quake is a trademark of Id Software, Inc., (c) 1996 Id Software, Inc. All
21 // rights reserved.
22
23 #include "quakedef.h"
24
25 #define MAXTRACKS       256
26
27 // Prototypes of the system dependent functions
28 extern void CDAudio_SysEject (void);
29 extern void CDAudio_SysCloseDoor (void);
30 extern int CDAudio_SysGetAudioDiskInfo (void);
31 extern float CDAudio_SysGetVolume (void);
32 extern void CDAudio_SysSetVolume (float volume);
33 extern int CDAudio_SysPlay (qbyte track);
34 extern int CDAudio_SysStop (void);
35 extern int CDAudio_SysPause (void);
36 extern int CDAudio_SysResume (void);
37 extern int CDAudio_SysUpdate (void);
38 extern void CDAudio_SysInit (void);
39 extern int CDAudio_SysStartup (void);
40 extern void CDAudio_SysShutdown (void);
41
42 // used by menu to ghost CD audio slider
43 cvar_t  cdaudioinitialized = {CVAR_READONLY,"cdaudioinitialized","0"};
44
45 static qboolean wasPlaying = false;
46 static qboolean initialized = false;
47 static qboolean enabled = false;
48 static float cdvolume;
49 static qbyte remap[MAXTRACKS];
50 static qbyte maxTrack;
51 static int faketrack = -1;
52
53 static float saved_vol = 1.0f;
54
55 // exported variables
56 qboolean cdValid = false;
57 qboolean cdPlaying = false;
58 qboolean cdPlayLooping = false;
59 qbyte cdPlayTrack;
60
61
62 static void CDAudio_Eject (void)
63 {
64         if (!enabled)
65                 return;
66
67         CDAudio_SysEject();
68 }
69
70
71 static void CDAudio_CloseDoor (void)
72 {
73         if (!enabled)
74                 return;
75
76         CDAudio_SysCloseDoor();
77 }
78
79 static int CDAudio_GetAudioDiskInfo (void)
80 {
81         int ret;
82
83         cdValid = false;
84
85         ret = CDAudio_SysGetAudioDiskInfo();
86         if (ret < 1)
87                 return -1;
88
89         cdValid = true;
90         maxTrack = ret;
91
92         return 0;
93 }
94
95
96 void CDAudio_Play (qbyte track, qboolean looping)
97 {
98         sfx_t* sfx;
99
100         if (!enabled)
101                 return;
102
103         track = remap[track];
104         if (track < 1)
105         {
106                 Con_DPrintf("CDAudio: Bad track number %u.\n", track);
107                 return;
108         }
109
110         if (cdPlaying && cdPlayTrack == track)
111                 return;
112         CDAudio_Stop ();
113
114         // Try playing a fake track (sound file) first
115         sfx = S_PrecacheSound (va ("cdtracks/track%02u.wav", track), false, false);
116         // FIXME: perhaps force it to be always %03u (but for compatibility?):
117         if (!sfx)
118                 sfx = S_PrecacheSound (va ("cdtracks/track%03u.wav", track), false, false);
119         if (sfx != NULL)
120         {
121                 faketrack = S_StartSound (-1, 0, sfx, vec3_origin, cdvolume, 0);
122                 if (faketrack != -1)
123                 {
124                         if (looping)
125                                 S_SetChannelFlag (faketrack, CHANNELFLAG_FORCELOOP, true);
126                         S_SetChannelFlag (faketrack, CHANNELFLAG_FULLVOLUME, true);
127                         Con_DPrintf ("Fake CD track %u playing...\n", track);
128                 }
129         }
130
131         // If we can't play a fake CD track, try the real one
132         if (faketrack == -1)
133         {
134                 if (!cdValid)
135                 {
136                         CDAudio_GetAudioDiskInfo();
137                         if (!cdValid)
138                         {
139                                 Con_Print ("No CD in player.\n");
140                                 return;
141                         }
142                 }
143
144                 if (track > maxTrack)
145                 {
146                         Con_Printf("CDAudio: Bad track number %u.\n", track);
147                         return;
148                 }
149
150                 if (CDAudio_SysPlay(track) == -1)
151                         return;
152         }
153
154         cdPlayLooping = looping;
155         cdPlayTrack = track;
156         cdPlaying = true;
157
158         if (cdvolume == 0.0)
159                 CDAudio_Pause ();
160 }
161
162
163 void CDAudio_Stop (void)
164 {
165         if (!enabled || !cdPlaying)
166                 return;
167
168         if (faketrack != -1)
169         {
170                 S_StopChannel (faketrack);
171                 faketrack = -1;
172         }
173         else if (CDAudio_SysStop() == -1)
174                 return;
175
176         wasPlaying = false;
177         cdPlaying = false;
178 }
179
180 void CDAudio_Pause (void)
181 {
182         if (!enabled || !cdPlaying)
183                 return;
184
185         if (faketrack != -1)
186                 S_SetChannelFlag (faketrack, CHANNELFLAG_PAUSED, true);
187         else if (CDAudio_SysPause() == -1)
188                 return;
189
190         wasPlaying = cdPlaying;
191         cdPlaying = false;
192 }
193
194
195 void CDAudio_Resume (void)
196 {
197         if (!enabled || cdPlaying || !wasPlaying)
198                 return;
199
200         if (faketrack != -1)
201                 S_SetChannelFlag (faketrack, CHANNELFLAG_PAUSED, false);
202         else if (CDAudio_SysResume() == -1)
203                 return;
204         cdPlaying = true;
205 }
206
207 static void CD_f (void)
208 {
209         const char *command;
210         int ret;
211         int n;
212
213         if (Cmd_Argc() < 2)
214                 return;
215
216         command = Cmd_Argv (1);
217
218         if (strcasecmp(command, "on") == 0)
219         {
220                 enabled = true;
221                 return;
222         }
223
224         if (strcasecmp(command, "off") == 0)
225         {
226                 if (cdPlaying)
227                         CDAudio_Stop();
228                 enabled = false;
229                 return;
230         }
231
232         if (strcasecmp(command, "reset") == 0)
233         {
234                 enabled = true;
235                 if (cdPlaying)
236                         CDAudio_Stop();
237                 for (n = 0; n < MAXTRACKS; n++)
238                         remap[n] = n;
239                 CDAudio_GetAudioDiskInfo();
240                 return;
241         }
242
243         if (strcasecmp(command, "remap") == 0)
244         {
245                 ret = Cmd_Argc() - 2;
246                 if (ret <= 0)
247                 {
248                         for (n = 1; n < MAXTRACKS; n++)
249                                 if (remap[n] != n)
250                                         Con_Printf("  %u -> %u\n", n, remap[n]);
251                         return;
252                 }
253                 for (n = 1; n <= ret; n++)
254                         remap[n] = atoi(Cmd_Argv (n+1));
255                 return;
256         }
257
258         if (strcasecmp(command, "close") == 0)
259         {
260                 CDAudio_CloseDoor();
261                 return;
262         }
263
264         if (strcasecmp(command, "play") == 0)
265         {
266                 CDAudio_Play((qbyte)atoi(Cmd_Argv (2)), false);
267                 return;
268         }
269
270         if (strcasecmp(command, "loop") == 0)
271         {
272                 CDAudio_Play((qbyte)atoi(Cmd_Argv (2)), true);
273                 return;
274         }
275
276         if (strcasecmp(command, "stop") == 0)
277         {
278                 CDAudio_Stop();
279                 return;
280         }
281
282         if (strcasecmp(command, "pause") == 0)
283         {
284                 CDAudio_Pause();
285                 return;
286         }
287
288         if (strcasecmp(command, "resume") == 0)
289         {
290                 CDAudio_Resume();
291                 return;
292         }
293
294         if (strcasecmp(command, "eject") == 0)
295         {
296                 if (cdPlaying && faketrack == -1)
297                         CDAudio_Stop();
298                 CDAudio_Eject();
299                 cdValid = false;
300                 return;
301         }
302
303         if (strcasecmp(command, "info") == 0)
304         {
305                 CDAudio_GetAudioDiskInfo ();
306                 if (cdValid)
307                         Con_Printf("%u tracks on CD.\n", maxTrack);
308                 else
309                         Con_Print ("No CD in player.\n");
310                 if (cdPlaying)
311                         Con_Printf("Currently %s track %u\n", cdPlayLooping ? "looping" : "playing", cdPlayTrack);
312                 else if (wasPlaying)
313                         Con_Printf("Paused %s track %u\n", cdPlayLooping ? "looping" : "playing", cdPlayTrack);
314                 Con_Printf("Volume is %f\n", cdvolume);
315                 return;
316         }
317 }
318
319 void CDAudio_SetVolume (float newvol)
320 {
321         // If the volume hasn't changed
322         if (newvol == cdvolume)
323                 return;
324
325         // If the CD has been muted
326         if (newvol == 0.0f)
327                 CDAudio_Pause ();
328         else
329         {
330                 // If the CD has been unmuted
331                 if (cdvolume == 0.0f)
332                         CDAudio_Resume ();
333
334                 if (faketrack != -1)
335                         S_SetChannelVolume (faketrack, newvol);
336                 CDAudio_SysSetVolume (newvol);
337         }
338
339         cdvolume = newvol;
340 }
341
342 void CDAudio_Update (void)
343 {
344         if (!enabled)
345                 return;
346
347         CDAudio_SetVolume (bgmvolume.value);
348
349         if (faketrack == -1)
350                 CDAudio_SysUpdate();
351 }
352
353 int CDAudio_Init (void)
354 {
355         int i;
356
357         if (cls.state == ca_dedicated)
358                 return -1;
359
360 // COMMANDLINEOPTION: Sound: -nocdaudio disables CD audio support
361         if (COM_CheckParm("-nocdaudio") || COM_CheckParm("-safe"))
362                 return -1;
363
364         CDAudio_SysInit();
365
366         for (i = 0; i < MAXTRACKS; i++)
367                 remap[i] = i;
368
369         Cvar_RegisterVariable(&cdaudioinitialized);
370         Cvar_SetValueQuick(&cdaudioinitialized, true);
371         enabled = true;
372
373         Cmd_AddCommand("cd", CD_f);
374
375         return 0;
376 }
377
378 int CDAudio_Startup (void)
379 {
380         CDAudio_SysStartup ();
381
382         if (CDAudio_GetAudioDiskInfo())
383         {
384                 Con_DPrint("CDAudio_Init: No CD in player.\n");
385                 cdValid = false;
386         }
387
388         saved_vol = CDAudio_SysGetVolume ();
389         if (saved_vol < 0.0f)
390         {
391                 Con_DPrint ("Can't get initial CD volume\n");
392                 saved_vol = 1.0f;
393         }
394         else
395                 Con_DPrintf ("Initial CD volume: %g\n", saved_vol);
396
397         initialized = true;
398
399         Con_DPrint("CD Audio Initialized\n");
400
401         return 0;
402 }
403
404 void CDAudio_Shutdown (void)
405 {
406         if (!initialized)
407                 return;
408
409         CDAudio_SysSetVolume (saved_vol);
410
411         CDAudio_Stop();
412         CDAudio_SysShutdown();
413         initialized = false;
414 }