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