]> icculus.org git repositories - divverent/darkplaces.git/blob - cd_win.c
fix the off-by-one fix (oops)
[divverent/darkplaces.git] / cd_win.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 <windows.h>
24 #include "quakedef.h"
25
26 extern  HWND    mainwindow;
27
28 static qboolean cdValid = false;
29 static qboolean playing = false;
30 static qboolean wasPlaying = false;
31 static qboolean initialized = false;
32 static qboolean enabled = false;
33 static qboolean playLooping = false;
34 static float    cdvolume;
35 static byte     remap[100];
36 static byte             cdrom;
37 static byte             playTrack;
38 static byte             maxTrack;
39
40 UINT    wDeviceID;
41
42
43 static void CDAudio_Eject(void)
44 {
45         DWORD   dwReturn;
46
47     if (dwReturn = mciSendCommand(wDeviceID, MCI_SET, MCI_SET_DOOR_OPEN, (DWORD)NULL))
48                 Con_DPrintf("MCI_SET_DOOR_OPEN failed (%i)\n", dwReturn);
49 }
50
51
52 static void CDAudio_CloseDoor(void)
53 {
54         DWORD   dwReturn;
55
56     if (dwReturn = mciSendCommand(wDeviceID, MCI_SET, MCI_SET_DOOR_CLOSED, (DWORD)NULL))
57                 Con_DPrintf("MCI_SET_DOOR_CLOSED failed (%i)\n", dwReturn);
58 }
59
60
61 static int CDAudio_GetAudioDiskInfo(void)
62 {
63         DWORD                           dwReturn;
64         MCI_STATUS_PARMS        mciStatusParms;
65
66
67         cdValid = false;
68
69         mciStatusParms.dwItem = MCI_STATUS_READY;
70     dwReturn = mciSendCommand(wDeviceID, MCI_STATUS, MCI_STATUS_ITEM | MCI_WAIT, (DWORD) (LPVOID) &mciStatusParms);
71         if (dwReturn)
72         {
73                 Con_DPrintf("CDAudio: drive ready test - get status failed\n");
74                 return -1;
75         }
76         if (!mciStatusParms.dwReturn)
77         {
78                 Con_DPrintf("CDAudio: drive not ready\n");
79                 return -1;
80         }
81
82         mciStatusParms.dwItem = MCI_STATUS_NUMBER_OF_TRACKS;
83     dwReturn = mciSendCommand(wDeviceID, MCI_STATUS, MCI_STATUS_ITEM | MCI_WAIT, (DWORD) (LPVOID) &mciStatusParms);
84         if (dwReturn)
85         {
86                 Con_DPrintf("CDAudio: get tracks - status failed\n");
87                 return -1;
88         }
89         if (mciStatusParms.dwReturn < 1)
90         {
91                 Con_DPrintf("CDAudio: no music tracks\n");
92                 return -1;
93         }
94
95         cdValid = true;
96         maxTrack = mciStatusParms.dwReturn;
97
98         return 0;
99 }
100
101
102 void CDAudio_Play(byte track, qboolean looping)
103 {
104         DWORD                           dwReturn;
105     MCI_PLAY_PARMS              mciPlayParms;
106         MCI_STATUS_PARMS        mciStatusParms;
107
108         if (!enabled)
109                 return;
110         
111         if (!cdValid)
112         {
113                 CDAudio_GetAudioDiskInfo();
114                 if (!cdValid)
115                         return;
116         }
117
118         track = remap[track];
119
120         if (track < 1 || track > maxTrack)
121         {
122                 Con_DPrintf("CDAudio: Bad track number %u.\n", track);
123                 return;
124         }
125
126         // don't try to play a non-audio track
127         mciStatusParms.dwItem = MCI_CDA_STATUS_TYPE_TRACK;
128         mciStatusParms.dwTrack = track;
129     dwReturn = mciSendCommand(wDeviceID, MCI_STATUS, MCI_STATUS_ITEM | MCI_TRACK | MCI_WAIT, (DWORD) (LPVOID) &mciStatusParms);
130         if (dwReturn)
131         {
132                 Con_DPrintf("MCI_STATUS failed (%i)\n", dwReturn);
133                 return;
134         }
135         if (mciStatusParms.dwReturn != MCI_CDA_TRACK_AUDIO)
136         {
137                 Con_Printf("CDAudio: track %i is not audio\n", track);
138                 return;
139         }
140
141         // get the length of the track to be played
142         mciStatusParms.dwItem = MCI_STATUS_LENGTH;
143         mciStatusParms.dwTrack = track;
144     dwReturn = mciSendCommand(wDeviceID, MCI_STATUS, MCI_STATUS_ITEM | MCI_TRACK | MCI_WAIT, (DWORD) (LPVOID) &mciStatusParms);
145         if (dwReturn)
146         {
147                 Con_DPrintf("MCI_STATUS failed (%i)\n", dwReturn);
148                 return;
149         }
150
151         if (playing)
152         {
153                 if (playTrack == track)
154                         return;
155                 CDAudio_Stop();
156         }
157
158     mciPlayParms.dwFrom = MCI_MAKE_TMSF(track, 0, 0, 0);
159         mciPlayParms.dwTo = (mciStatusParms.dwReturn << 8) | track;
160     mciPlayParms.dwCallback = (DWORD)mainwindow;
161     dwReturn = mciSendCommand(wDeviceID, MCI_PLAY, MCI_NOTIFY | MCI_FROM | MCI_TO, (DWORD)(LPVOID) &mciPlayParms);
162         if (dwReturn)
163         {
164                 Con_DPrintf("CDAudio: MCI_PLAY failed (%i)\n", dwReturn);
165                 return;
166         }
167
168         playLooping = looping;
169         playTrack = track;
170         playing = true;
171
172         if (cdvolume == 0.0)
173                 CDAudio_Pause ();
174 }
175
176
177 void CDAudio_Stop(void)
178 {
179         DWORD   dwReturn;
180
181         if (!enabled)
182                 return;
183         
184         if (!playing)
185                 return;
186
187     if (dwReturn = mciSendCommand(wDeviceID, MCI_STOP, 0, (DWORD)NULL))
188                 Con_DPrintf("MCI_STOP failed (%i)", dwReturn);
189
190         wasPlaying = false;
191         playing = false;
192 }
193
194
195 void CDAudio_Pause(void)
196 {
197         DWORD                           dwReturn;
198         MCI_GENERIC_PARMS       mciGenericParms;
199
200         if (!enabled)
201                 return;
202
203         if (!playing)
204                 return;
205
206         mciGenericParms.dwCallback = (DWORD)mainwindow;
207     if (dwReturn = mciSendCommand(wDeviceID, MCI_PAUSE, 0, (DWORD)(LPVOID) &mciGenericParms))
208                 Con_DPrintf("MCI_PAUSE failed (%i)", dwReturn);
209
210         wasPlaying = playing;
211         playing = false;
212 }
213
214
215 void CDAudio_Resume(void)
216 {
217         DWORD                   dwReturn;
218     MCI_PLAY_PARMS      mciPlayParms;
219
220         if (!enabled)
221                 return;
222         
223         if (!cdValid)
224                 return;
225
226         if (!wasPlaying)
227                 return;
228         
229     mciPlayParms.dwFrom = MCI_MAKE_TMSF(playTrack, 0, 0, 0);
230     mciPlayParms.dwTo = MCI_MAKE_TMSF(playTrack + 1, 0, 0, 0);
231     mciPlayParms.dwCallback = (DWORD)mainwindow;
232     dwReturn = mciSendCommand(wDeviceID, MCI_PLAY, MCI_TO | MCI_NOTIFY, (DWORD)(LPVOID) &mciPlayParms);
233         if (dwReturn)
234         {
235                 Con_DPrintf("CDAudio: MCI_PLAY failed (%i)\n", dwReturn);
236                 return;
237         }
238         playing = true;
239 }
240
241
242 static void CD_f (void)
243 {
244         char    *command;
245         int             ret;
246         int             n;
247
248         if (Cmd_Argc() < 2)
249                 return;
250
251         command = Cmd_Argv (1);
252
253         if (Q_strcasecmp(command, "on") == 0)
254         {
255                 enabled = true;
256                 return;
257         }
258
259         if (Q_strcasecmp(command, "off") == 0)
260         {
261                 if (playing)
262                         CDAudio_Stop();
263                 enabled = false;
264                 return;
265         }
266
267         if (Q_strcasecmp(command, "reset") == 0)
268         {
269                 enabled = true;
270                 if (playing)
271                         CDAudio_Stop();
272                 for (n = 0; n < 100; n++)
273                         remap[n] = n;
274                 CDAudio_GetAudioDiskInfo();
275                 return;
276         }
277
278         if (Q_strcasecmp(command, "remap") == 0)
279         {
280                 ret = Cmd_Argc() - 2;
281                 if (ret <= 0)
282                 {
283                         for (n = 1; n < 100; n++)
284                                 if (remap[n] != n)
285                                         Con_Printf("  %u -> %u\n", n, remap[n]);
286                         return;
287                 }
288                 for (n = 1; n <= ret; n++)
289                         remap[n] = atoi(Cmd_Argv (n+1));
290                 return;
291         }
292
293         if (Q_strcasecmp(command, "close") == 0)
294         {
295                 CDAudio_CloseDoor();
296                 return;
297         }
298
299         if (!cdValid)
300         {
301                 CDAudio_GetAudioDiskInfo();
302                 if (!cdValid)
303                 {
304                         Con_Printf("No CD in player.\n");
305                         return;
306                 }
307         }
308
309         if (Q_strcasecmp(command, "play") == 0)
310         {
311                 CDAudio_Play((byte)atoi(Cmd_Argv (2)), false);
312                 return;
313         }
314
315         if (Q_strcasecmp(command, "loop") == 0)
316         {
317                 CDAudio_Play((byte)atoi(Cmd_Argv (2)), true);
318                 return;
319         }
320
321         if (Q_strcasecmp(command, "stop") == 0)
322         {
323                 CDAudio_Stop();
324                 return;
325         }
326
327         if (Q_strcasecmp(command, "pause") == 0)
328         {
329                 CDAudio_Pause();
330                 return;
331         }
332
333         if (Q_strcasecmp(command, "resume") == 0)
334         {
335                 CDAudio_Resume();
336                 return;
337         }
338
339         if (Q_strcasecmp(command, "eject") == 0)
340         {
341                 if (playing)
342                         CDAudio_Stop();
343                 CDAudio_Eject();
344                 cdValid = false;
345                 return;
346         }
347
348         if (Q_strcasecmp(command, "info") == 0)
349         {
350                 Con_Printf("%u tracks\n", maxTrack);
351                 if (playing)
352                         Con_Printf("Currently %s track %u\n", playLooping ? "looping" : "playing", playTrack);
353                 else if (wasPlaying)
354                         Con_Printf("Paused %s track %u\n", playLooping ? "looping" : "playing", playTrack);
355                 Con_Printf("Volume is %f\n", cdvolume);
356                 return;
357         }
358 }
359
360
361 LONG CDAudio_MessageHandler(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
362 {
363         if (lParam != wDeviceID)
364                 return 1;
365
366         switch (wParam)
367         {
368                 case MCI_NOTIFY_SUCCESSFUL:
369                         if (playing)
370                         {
371                                 playing = false;
372                                 if (playLooping)
373                                         CDAudio_Play(playTrack, true);
374                         }
375                         break;
376
377                 case MCI_NOTIFY_ABORTED:
378                 case MCI_NOTIFY_SUPERSEDED:
379                         break;
380
381                 case MCI_NOTIFY_FAILURE:
382                         Con_DPrintf("MCI_NOTIFY_FAILURE\n");
383                         CDAudio_Stop ();
384                         cdValid = false;
385                         break;
386
387                 default:
388                         Con_DPrintf("Unexpected MM_MCINOTIFY type (%i)\n", wParam);
389                         return 1;
390         }
391
392         return 0;
393 }
394
395
396 void CDAudio_Update(void)
397 {
398         if (!enabled)
399                 return;
400
401         if (bgmvolume.value != cdvolume)
402         {
403                 if (cdvolume)
404                 {
405                         Cvar_SetValue ("bgmvolume", 0.0);
406                         cdvolume = bgmvolume.value;
407                         CDAudio_Pause ();
408                 }
409                 else
410                 {
411                         Cvar_SetValue ("bgmvolume", 1.0);
412                         cdvolume = bgmvolume.value;
413                         CDAudio_Resume ();
414                 }
415         }
416 }
417
418
419 int CDAudio_Init(void)
420 {
421         DWORD   dwReturn;
422         MCI_OPEN_PARMS  mciOpenParms;
423     MCI_SET_PARMS       mciSetParms;
424         int                             n;
425
426         if (cls.state == ca_dedicated)
427                 return -1;
428
429         if (COM_CheckParm("-nocdaudio"))
430                 return -1;
431
432         mciOpenParms.lpstrDeviceType = "cdaudio";
433         if (dwReturn = mciSendCommand(0, MCI_OPEN, MCI_OPEN_TYPE | MCI_OPEN_SHAREABLE, (DWORD) (LPVOID) &mciOpenParms))
434         {
435                 Con_Printf("CDAudio_Init: MCI_OPEN failed (%i)\n", dwReturn);
436                 return -1;
437         }
438         wDeviceID = mciOpenParms.wDeviceID;
439
440     // Set the time format to track/minute/second/frame (TMSF).
441     mciSetParms.dwTimeFormat = MCI_FORMAT_TMSF;
442     if (dwReturn = mciSendCommand(wDeviceID, MCI_SET, MCI_SET_TIME_FORMAT, (DWORD)(LPVOID) &mciSetParms))
443     {
444                 Con_Printf("MCI_SET_TIME_FORMAT failed (%i)\n", dwReturn);
445         mciSendCommand(wDeviceID, MCI_CLOSE, 0, (DWORD)NULL);
446                 return -1;
447     }
448
449         for (n = 0; n < 100; n++)
450                 remap[n] = n;
451         initialized = true;
452         enabled = true;
453
454         if (CDAudio_GetAudioDiskInfo())
455         {
456                 Con_Printf("CDAudio_Init: No CD in player.\n");
457                 cdValid = false;
458         }
459
460         Cmd_AddCommand ("cd", CD_f);
461
462         Con_Printf("CD Audio Initialized\n");
463
464         return 0;
465 }
466
467
468 void CDAudio_Shutdown(void)
469 {
470         if (!initialized)
471                 return;
472         CDAudio_Stop();
473         if (mciSendCommand(wDeviceID, MCI_CLOSE, MCI_WAIT, (DWORD)NULL))
474                 Con_DPrintf("CDAudio_Shutdown: MCI_CLOSE failed\n");
475 }