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 <stdio.h>
24 #include <string.h>
25 #include <time.h>
26 #include <boolean.h>
27 
28 #include "qtypes.h"
29 #include "cdaudio.h"
30 #include "cdaudio_driver.h"
31 #include "cmd.h"
32 #include "common.h"
33 #include "console.h"
34 #include "sound.h"
35 
36 #ifdef NQ_HACK
37 #include "client.h"
38 #endif
39 
40 static byte remap[100];
41 static qboolean enabled = false;
42 static qboolean initialized = false;
43 static qboolean playing = false;
44 static qboolean wasPlaying = false;
45 static qboolean playLooping = false;
46 static qboolean cdValid = false;
47 static byte maxTrack;
48 static byte playTrack;
49 static float cdvolume;
50 
51 static void CDAudio_SetVolume_f(struct cvar_s *var);
52 
53 static void
CDAudio_Eject(void)54 CDAudio_Eject(void)
55 {
56     if (enabled)
57 	CDDrv_Eject();
58 }
59 
60 static void
CDAudio_CloseDoor(void)61 CDAudio_CloseDoor(void)
62 {
63     if (enabled)
64 	CDDrv_CloseDoor();
65 }
66 
67 static int
CDAudio_GetAudioDiskInfo(void)68 CDAudio_GetAudioDiskInfo(void)
69 {
70     int err;
71 
72     cdValid = false;
73     err = CDDrv_GetMaxTrack(&maxTrack);
74     if (!err)
75 	cdValid = true;
76 
77     return err;
78 }
79 
80 static void
CDAudio_SetVolume_f(struct cvar_s * var)81 CDAudio_SetVolume_f(struct cvar_s *var)
82 {
83    qboolean changed = false;
84 
85    /* Clamp the volume 0.0 - 1.0 */
86    if (var->value > 1.0) {
87       var->value = 1.0;
88       changed = true;
89    } else if (var->value < 0.0) {
90       var->value = 0.0;
91       changed = true;
92    }
93 
94    if (cdvolume != var->value)
95    {
96       int ret = CDDrv_SetVolume(var->value * 255.0);
97       if (ret >= 0)
98          cdvolume = (float)ret / 255.0;
99       if (var->value != cdvolume) {
100          var->value = cdvolume;
101          changed = true;
102       }
103    }
104 
105    /*
106     * If the volume we set is not the one originally passed in, we need to set
107     * the cvar again, so the .string member is updated to match
108     */
109    if (changed)
110       Cvar_SetValue("bgmvolume", var->value);
111 }
112 
113 void
CDAudio_Stop(void)114 CDAudio_Stop(void)
115 {
116     if (!enabled)
117 	return;
118     if (!playing)
119 	return;
120 
121     CDDrv_Stop();
122     wasPlaying = false;
123     playing = false;
124 }
125 
126 void
CDAudio_Pause(void)127 CDAudio_Pause(void)
128 {
129     if (!enabled)
130 	return;
131     if (!playing)
132 	return;
133 
134     CDDrv_Pause();
135     wasPlaying = playing;
136     playing = false;
137 }
138 
139 void
CDAudio_Resume(void)140 CDAudio_Resume(void)
141 {
142     if (!enabled)
143 	return;
144     if (!cdValid)
145 	return;
146     if (!wasPlaying)
147 	return;
148 
149     CDDrv_Resume(playTrack);
150     playing = true;
151 }
152 
153 
154 int
CDAudio_Play(byte track,qboolean looping)155 CDAudio_Play(byte track, qboolean looping)
156 {
157     int err;
158 
159     if (!enabled)
160 	return -1;
161 
162     if (!cdValid) {
163 	CDAudio_GetAudioDiskInfo();
164 	if (!cdValid)
165 	    return -1;
166     }
167     track = remap[track];
168     if (track < 1 || track > maxTrack) {
169 	Con_DPrintf("CDAudio: Bad track number %u.\n", track);
170 	return -1;
171     }
172     if (!CDDrv_IsAudioTrack(track)) {
173 	Con_Printf("CDAudio: track %i is not audio\n", track);
174 	return -1;
175     }
176     if (playing) {
177 	if (playTrack == track)
178 	    return -1;
179 	CDAudio_Stop();
180     }
181     err = CDDrv_PlayTrack(track);
182     if (!err) {
183 	playLooping = looping;
184 	playTrack = track;
185 	playing = true;
186     }
187     if (cdvolume == 0.0)
188 	CDAudio_Pause();
189     return 0;
190 }
191 
192 void
CDAudio_InvalidateDisk(void)193 CDAudio_InvalidateDisk(void)
194 {
195     cdValid = false;
196 }
197 
198 void
CDAudio_Update(void)199 CDAudio_Update(void)
200 {
201     static time_t lastchk;
202 
203     if (!enabled)
204 	return;
205 
206     if (playing && lastchk < time(NULL)) {
207 	lastchk = time(NULL) + 2;	//two seconds between chks
208 	if (!CDDrv_IsPlaying(playTrack)) {
209 	    playing = false;
210 	    if (playLooping)
211 		CDAudio_Play(playTrack, true);
212 	}
213     }
214 }
215 
216 static void
CD_f(void)217 CD_f(void)
218 {
219    const char *command;
220    int n;
221 
222    if (Cmd_Argc() < 2)
223       return;
224 
225    command = Cmd_Argv(1);
226 
227    if (strcasecmp(command, "on") == 0) {
228       enabled = true;
229       return;
230    }
231    if (strcasecmp(command, "off") == 0) {
232       if (playing)
233          CDAudio_Stop();
234       enabled = false;
235       return;
236    }
237    if (strcasecmp(command, "reset") == 0) {
238       enabled = true;
239       if (playing)
240          CDAudio_Stop();
241       for (n = 0; n < 100; n++)
242          remap[n] = n;
243       CDAudio_GetAudioDiskInfo();
244       return;
245    }
246    if (strcasecmp(command, "remap") == 0)
247    {
248       int ret = Cmd_Argc() - 2;
249       if (ret <= 0) {
250          for (n = 1; n < 100; n++)
251             if (remap[n] != n)
252                Con_Printf("  %u -> %u\n", n, remap[n]);
253          return;
254       }
255       for (n = 1; n <= ret; n++)
256          remap[n] = Q_atoi(Cmd_Argv(n + 1));
257       return;
258    }
259    if (strcasecmp(command, "close") == 0) {
260       CDAudio_CloseDoor();
261       return;
262    }
263    if (!cdValid) {
264       CDAudio_GetAudioDiskInfo();
265       if (!cdValid) {
266          Con_Printf("No CD in player.\n");
267          return;
268       }
269    }
270    if (strcasecmp(command, "play") == 0) {
271       CDAudio_Play((byte)Q_atoi(Cmd_Argv(2)), false);
272       return;
273    }
274    if (strcasecmp(command, "loop") == 0) {
275       CDAudio_Play((byte)Q_atoi(Cmd_Argv(2)), true);
276       return;
277    }
278    if (strcasecmp(command, "stop") == 0) {
279       CDAudio_Stop();
280       return;
281    }
282    if (strcasecmp(command, "pause") == 0) {
283       CDAudio_Pause();
284       return;
285    }
286    if (strcasecmp(command, "resume") == 0) {
287       CDAudio_Resume();
288       return;
289    }
290    if (strcasecmp(command, "eject") == 0) {
291       if (playing)
292          CDAudio_Stop();
293       CDAudio_Eject();
294       cdValid = false;
295       return;
296    }
297    if (strcasecmp(command, "info") == 0) {
298       Con_Printf("%u tracks\n", maxTrack);
299       if (playing)
300          Con_Printf("Currently %s track %u\n",
301                playLooping ? "looping" : "playing", playTrack);
302       else if (wasPlaying)
303          Con_Printf("Paused %s track %u\n",
304                playLooping ? "looping" : "playing", playTrack);
305       Con_Printf("Volume is %f\n", bgmvolume.value);
306       return;
307    }
308 }
309 
310 int
CDAudio_Init(void)311 CDAudio_Init(void)
312 {
313     int i, err;
314 
315 #ifdef NQ_HACK
316     // FIXME - not a valid client state in QW?
317     if (cls.state == ca_dedicated)
318 	return -1;
319 #endif
320 
321     if (COM_CheckParm("-nocdaudio"))
322 	return -1;
323 
324     Cmd_AddCommand("cd", CD_f);
325     err = CDDrv_InitDevice();
326     if (err)
327 	return err;
328 
329     for (i = 0; i < 100; i++)
330 	remap[i] = i;
331     initialized = true;
332     enabled = true;
333 
334     Con_Printf("CD Audio Initialized\n");
335     if (CDAudio_GetAudioDiskInfo()) {
336 	Con_Printf("CDAudio_Init: No CD in player.\n");
337 	cdValid = false;
338     }
339 
340     return 0;
341 }
342 
343 void
CDAudio_Shutdown(void)344 CDAudio_Shutdown(void)
345 {
346     if (!initialized)
347 	return;
348     CDAudio_Stop();
349     CDDrv_CloseDevice();
350     initialized = false;
351 }
352