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