icculus quake2 doxygen  1.0 dev
cd_win.c
Go to the documentation of this file.
1 /*
2 Copyright (C) 1997-2001 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 "../client/client.h"
25 
26 extern HWND cl_hwnd;
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 byte remap[100];
35 static byte cdrom;
36 static byte playTrack;
37 static byte maxTrack;
38 
42 
45 
46 
47 void CDAudio_Pause(void);
48 
49 static void CDAudio_Eject(void)
50 {
51  DWORD dwReturn;
52 
53  if (dwReturn = mciSendCommand(wDeviceID, MCI_SET, MCI_SET_DOOR_OPEN, (DWORD)NULL))
54  Com_DPrintf("MCI_SET_DOOR_OPEN failed (%i)\n", dwReturn);
55 }
56 
57 
58 static void CDAudio_CloseDoor(void)
59 {
60  DWORD dwReturn;
61 
62  if (dwReturn = mciSendCommand(wDeviceID, MCI_SET, MCI_SET_DOOR_CLOSED, (DWORD)NULL))
63  Com_DPrintf("MCI_SET_DOOR_CLOSED failed (%i)\n", dwReturn);
64 }
65 
66 
67 static int CDAudio_GetAudioDiskInfo(void)
68 {
69  DWORD dwReturn;
70  MCI_STATUS_PARMS mciStatusParms;
71 
72 
73  cdValid = false;
74 
75  mciStatusParms.dwItem = MCI_STATUS_READY;
76  dwReturn = mciSendCommand(wDeviceID, MCI_STATUS, MCI_STATUS_ITEM | MCI_WAIT, (DWORD) (LPVOID) &mciStatusParms);
77  if (dwReturn)
78  {
79  Com_DPrintf("CDAudio: drive ready test - get status failed\n");
80  return -1;
81  }
82  if (!mciStatusParms.dwReturn)
83  {
84  Com_DPrintf("CDAudio: drive not ready\n");
85  return -1;
86  }
87 
88  mciStatusParms.dwItem = MCI_STATUS_NUMBER_OF_TRACKS;
89  dwReturn = mciSendCommand(wDeviceID, MCI_STATUS, MCI_STATUS_ITEM | MCI_WAIT, (DWORD) (LPVOID) &mciStatusParms);
90  if (dwReturn)
91  {
92  Com_DPrintf("CDAudio: get tracks - status failed\n");
93  return -1;
94  }
95  if (mciStatusParms.dwReturn < 1)
96  {
97  Com_DPrintf("CDAudio: no music tracks\n");
98  return -1;
99  }
100 
101  cdValid = true;
102  maxTrack = mciStatusParms.dwReturn;
103 
104  return 0;
105 }
106 
107 void CDAudio_Play2(int track, qboolean looping)
108 {
109  DWORD dwReturn;
110  MCI_PLAY_PARMS mciPlayParms;
111  MCI_STATUS_PARMS mciStatusParms;
112 
113  if (!enabled)
114  return;
115 
116  if (!cdValid)
117  {
119  if (!cdValid)
120  return;
121  }
122 
123  track = remap[track];
124 
125  if (track < 1 || track > maxTrack)
126  {
127  CDAudio_Stop();
128  return;
129  }
130 
131  // don't try to play a non-audio track
132  mciStatusParms.dwItem = MCI_CDA_STATUS_TYPE_TRACK;
133  mciStatusParms.dwTrack = track;
134  dwReturn = mciSendCommand(wDeviceID, MCI_STATUS, MCI_STATUS_ITEM | MCI_TRACK | MCI_WAIT, (DWORD) (LPVOID) &mciStatusParms);
135  if (dwReturn)
136  {
137  Com_DPrintf("MCI_STATUS failed (%i)\n", dwReturn);
138  return;
139  }
140  if (mciStatusParms.dwReturn != MCI_CDA_TRACK_AUDIO)
141  {
142  Com_Printf("CDAudio: track %i is not audio\n", track);
143  return;
144  }
145 
146  // get the length of the track to be played
147  mciStatusParms.dwItem = MCI_STATUS_LENGTH;
148  mciStatusParms.dwTrack = track;
149  dwReturn = mciSendCommand(wDeviceID, MCI_STATUS, MCI_STATUS_ITEM | MCI_TRACK | MCI_WAIT, (DWORD) (LPVOID) &mciStatusParms);
150  if (dwReturn)
151  {
152  Com_DPrintf("MCI_STATUS failed (%i)\n", dwReturn);
153  return;
154  }
155 
156  if (playing)
157  {
158  if (playTrack == track)
159  return;
160  CDAudio_Stop();
161  }
162 
163  mciPlayParms.dwFrom = MCI_MAKE_TMSF(track, 0, 0, 0);
164  mciPlayParms.dwTo = (mciStatusParms.dwReturn << 8) | track;
165  mciPlayParms.dwCallback = (DWORD)cl_hwnd;
166  dwReturn = mciSendCommand(wDeviceID, MCI_PLAY, MCI_NOTIFY | MCI_FROM | MCI_TO, (DWORD)(LPVOID) &mciPlayParms);
167  if (dwReturn)
168  {
169  Com_DPrintf("CDAudio: MCI_PLAY failed (%i)\n", dwReturn);
170  return;
171  }
172 
173  playLooping = looping;
174  playTrack = track;
175  playing = true;
176 
177  if ( Cvar_VariableValue( "cd_nocd" ) )
178  CDAudio_Pause ();
179 }
180 
181 
182 void CDAudio_Play(int track, qboolean looping)
183 {
184  // set a loop counter so that this track will change to the
185  // looptrack later
186  loopcounter = 0;
187  CDAudio_Play2(track, looping);
188 }
189 
191 {
192  int track, i = 0, free_tracks = 0, remap_track;
193  float f;
194  byte* track_bools;;
195  DWORD dwReturn;
196  MCI_PLAY_PARMS mciPlayParms;
197  MCI_STATUS_PARMS mciStatusParms;
198 
199  if (!enabled)
200  return;
201 
202  //create array of available audio tracknumbers
203 
204  track_bools = (byte*)malloc(maxTrack * sizeof(byte));
205 
206  if (track_bools == 0)
207  return;
208 
209  for (; i < maxTrack; i++)
210  {
211  // don't try to play a non-audio track
212  mciStatusParms.dwItem = MCI_CDA_STATUS_TYPE_TRACK;
213  mciStatusParms.dwTrack = remap[i];
214  dwReturn = mciSendCommand(wDeviceID, MCI_STATUS, MCI_STATUS_ITEM | MCI_TRACK | MCI_WAIT, (DWORD) (LPVOID) &mciStatusParms);
215  if (dwReturn)
216  {
217  track_bools[i] = 0;
218  }
219  else
220  track_bools[i] = (mciStatusParms.dwReturn == MCI_CDA_TRACK_AUDIO);
221 
222  free_tracks += track_bools[i];
223  }
224 
225  if (!free_tracks)
226  {
227  Com_DPrintf("CDAudio_RandomPlay: Unable to find and play a random audio track, insert an audio cd please");
228  goto free_end;
229  }
230 
231  //choose random audio track
232  do
233  {
234  do
235  {
236  f = ((float)rand()) / ((float)RAND_MAX + 1.0);
237  track = (int)(maxTrack * f);
238  }
239  while(!track_bools[track]);
240 
241  remap_track = remap[track];
242 
243  // get the length of the track to be played
244  mciStatusParms.dwItem = MCI_STATUS_LENGTH;
245  mciStatusParms.dwTrack = remap_track;
246  dwReturn = mciSendCommand(wDeviceID, MCI_STATUS, MCI_STATUS_ITEM | MCI_TRACK | MCI_WAIT, (DWORD) (LPVOID) &mciStatusParms);
247  if (dwReturn)
248  {
249  Com_DPrintf("MCI_STATUS failed (%i)\n", dwReturn);
250  goto free_end;
251  }
252 
253  if (playing)
254  {
255  if (playTrack == remap_track)
256  {
257  goto free_end;
258  }
259  CDAudio_Stop();
260  }
261 
262  mciPlayParms.dwFrom = MCI_MAKE_TMSF(remap_track, 0, 0, 0);
263  mciPlayParms.dwTo = (mciStatusParms.dwReturn << 8) | remap_track;
264  mciPlayParms.dwCallback = (DWORD)cl_hwnd;
265  dwReturn = mciSendCommand(wDeviceID, MCI_PLAY, MCI_NOTIFY | MCI_FROM | MCI_TO, (DWORD)(LPVOID) &mciPlayParms);
266  if (dwReturn)
267  {
268  track_bools[track] = 0;
269  free_tracks--;
270  }
271  else
272  {
273  playLooping = true;
274  playTrack = remap_track;
275  playing = true;
276  break;
277  }
278  while (free_tracks > 0);
279 
280 free_end:
281  free((void*)track_bools);
282 }
283 
284 void CDAudio_Stop(void)
285 {
286  DWORD dwReturn;
287 
288  if (!enabled)
289  return;
290 
291  if (!playing)
292  return;
293 
294  if (dwReturn = mciSendCommand(wDeviceID, MCI_STOP, 0, (DWORD)NULL))
295  Com_DPrintf("MCI_STOP failed (%i)", dwReturn);
296 
297  wasPlaying = false;
298  playing = false;
299 }
300 
301 
302 void CDAudio_Pause(void)
303 {
304  DWORD dwReturn;
305  MCI_GENERIC_PARMS mciGenericParms;
306 
307  if (!enabled)
308  return;
309 
310  if (!playing)
311  return;
312 
313  mciGenericParms.dwCallback = (DWORD)cl_hwnd;
314  if (dwReturn = mciSendCommand(wDeviceID, MCI_PAUSE, 0, (DWORD)(LPVOID) &mciGenericParms))
315  Com_DPrintf("MCI_PAUSE failed (%i)", dwReturn);
316 
318  playing = false;
319 }
320 
321 
322 void CDAudio_Resume(void)
323 {
324  DWORD dwReturn;
325  MCI_PLAY_PARMS mciPlayParms;
326 
327  if (!enabled)
328  return;
329 
330  if (!cdValid)
331  return;
332 
333  if (!wasPlaying)
334  return;
335 
336  mciPlayParms.dwFrom = MCI_MAKE_TMSF(playTrack, 0, 0, 0);
337  mciPlayParms.dwTo = MCI_MAKE_TMSF(playTrack + 1, 0, 0, 0);
338  mciPlayParms.dwCallback = (DWORD)cl_hwnd;
339  dwReturn = mciSendCommand(wDeviceID, MCI_PLAY, MCI_TO | MCI_NOTIFY, (DWORD)(LPVOID) &mciPlayParms);
340  if (dwReturn)
341  {
342  Com_DPrintf("CDAudio: MCI_PLAY failed (%i)\n", dwReturn);
343  return;
344  }
345  playing = true;
346 }
347 
348 
349 static void CD_f (void)
350 {
351  char *command;
352  int ret;
353  int n;
354 
355  if (Cmd_Argc() < 2)
356  return;
357 
358  command = Cmd_Argv (1);
359 
360  if (Q_strcasecmp(command, "on") == 0)
361  {
362  enabled = true;
363  return;
364  }
365 
366  if (Q_strcasecmp(command, "off") == 0)
367  {
368  if (playing)
369  CDAudio_Stop();
370  enabled = false;
371  return;
372  }
373 
374  if (Q_strcasecmp(command, "reset") == 0)
375  {
376  enabled = true;
377  if (playing)
378  CDAudio_Stop();
379  for (n = 0; n < 100; n++)
380  remap[n] = n;
382  return;
383  }
384 
385  if (Q_strcasecmp(command, "remap") == 0)
386  {
387  ret = Cmd_Argc() - 2;
388  if (ret <= 0)
389  {
390  for (n = 1; n < 100; n++)
391  if (remap[n] != n)
392  Com_Printf(" %u -> %u\n", n, remap[n]);
393  return;
394  }
395  for (n = 1; n <= ret; n++)
396  remap[n] = atoi(Cmd_Argv (n+1));
397  return;
398  }
399 
400  if (Q_strcasecmp(command, "close") == 0)
401  {
403  return;
404  }
405 
406  if (!cdValid)
407  {
409  if (!cdValid)
410  {
411  Com_Printf("No CD in player.\n");
412  return;
413  }
414  }
415 
416  if (Q_strcasecmp(command, "play") == 0)
417  {
418  CDAudio_Play(atoi(Cmd_Argv (2)), false);
419  return;
420  }
421 
422  if (Q_strcasecmp(command, "loop") == 0)
423  {
424  CDAudio_Play(atoi(Cmd_Argv (2)), true);
425  return;
426  }
427 
428  if (Q_strcasecmp(command, "stop") == 0)
429  {
430  CDAudio_Stop();
431  return;
432  }
433 
434  if (Q_strcasecmp(command, "pause") == 0)
435  {
436  CDAudio_Pause();
437  return;
438  }
439 
440  if (Q_strcasecmp(command, "resume") == 0)
441  {
442  CDAudio_Resume();
443  return;
444  }
445 
446  if (Q_strcasecmp(command, "eject") == 0)
447  {
448  if (playing)
449  CDAudio_Stop();
450  CDAudio_Eject();
451  cdValid = false;
452  return;
453  }
454 
455  if (Q_strcasecmp(command, "info") == 0)
456  {
457  Com_Printf("%u tracks\n", maxTrack);
458  if (playing)
459  Com_Printf("Currently %s track %u\n", playLooping ? "looping" : "playing", playTrack);
460  else if (wasPlaying)
461  Com_Printf("Paused %s track %u\n", playLooping ? "looping" : "playing", playTrack);
462  return;
463  }
464 }
465 
466 
467 LONG CDAudio_MessageHandler(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
468 {
469  if (lParam != wDeviceID)
470  return 1;
471 
472  switch (wParam)
473  {
474  case MCI_NOTIFY_SUCCESSFUL:
475  if (playing)
476  {
477  playing = false;
478  if (playLooping)
479  {
480  // if the track has played the given number of times,
481  // go to the ambient track
482  if (++loopcounter >= cd_loopcount->value)
484  else
485  CDAudio_Play2(playTrack, true);
486  }
487  }
488  break;
489 
490  case MCI_NOTIFY_ABORTED:
491  case MCI_NOTIFY_SUPERSEDED:
492  break;
493 
494  case MCI_NOTIFY_FAILURE:
495  Com_DPrintf("MCI_NOTIFY_FAILURE\n");
496  CDAudio_Stop ();
497  cdValid = false;
498  break;
499 
500  default:
501  Com_DPrintf("Unexpected MM_MCINOTIFY type (%i)\n", wParam);
502  return 1;
503  }
504 
505  return 0;
506 }
507 
508 
509 void CDAudio_Update(void)
510 {
511  if ( cd_nocd->value != !enabled )
512  {
513  if ( cd_nocd->value )
514  {
515  CDAudio_Stop();
516  enabled = false;
517  }
518  else
519  {
520  enabled = true;
521  CDAudio_Resume ();
522  }
523  }
524 }
525 
526 
527 int CDAudio_Init(void)
528 {
529  DWORD dwReturn;
530  MCI_OPEN_PARMS mciOpenParms;
531  MCI_SET_PARMS mciSetParms;
532  int n;
533 
534  if (initialized)
535  return;
536 
537  cd_nocd = Cvar_Get ("cd_nocd", "0", CVAR_ARCHIVE );
538  cd_loopcount = Cvar_Get ("cd_loopcount", "4", 0);
539  cd_looptrack = Cvar_Get ("cd_looptrack", "11", 0);
540  if ( cd_nocd->value)
541  return -1;
542 
543  mciOpenParms.lpstrDeviceType = "cdaudio";
544  if (dwReturn = mciSendCommand(0, MCI_OPEN, MCI_OPEN_TYPE | MCI_OPEN_SHAREABLE, (DWORD) (LPVOID) &mciOpenParms))
545  {
546  Com_Printf("CDAudio_Init: MCI_OPEN failed (%i)\n", dwReturn);
547  return -1;
548  }
549  wDeviceID = mciOpenParms.wDeviceID;
550 
551  // Set the time format to track/minute/second/frame (TMSF).
552  mciSetParms.dwTimeFormat = MCI_FORMAT_TMSF;
553  if (dwReturn = mciSendCommand(wDeviceID, MCI_SET, MCI_SET_TIME_FORMAT, (DWORD)(LPVOID) &mciSetParms))
554  {
555  Com_Printf("MCI_SET_TIME_FORMAT failed (%i)\n", dwReturn);
556  mciSendCommand(wDeviceID, MCI_CLOSE, 0, (DWORD)NULL);
557  return -1;
558  }
559 
560  for (n = 0; n < 100; n++)
561  remap[n] = n;
562  initialized = true;
563  enabled = true;
564 
566  {
567 // Com_Printf("CDAudio_Init: No CD in player.\n");
568  cdValid = false;
569  enabled = false;
570  }
571 
572  Cmd_AddCommand ("cd", CD_f);
573 
574  Com_Printf("CD Audio Initialized\n");
575 
576  return 0;
577 }
578 
579 
580 void CDAudio_Shutdown(void)
581 {
582  if (!initialized)
583  return;
584  CDAudio_Stop();
585  if (mciSendCommand(wDeviceID, MCI_CLOSE, MCI_WAIT, (DWORD)NULL))
586  Com_DPrintf("CDAudio_Shutdown: MCI_CLOSE failed\n");
587  initialized = false;
588 }
589 
590 
591 /*
592 ===========
593 CDAudio_Activate
594 
595 Called when the main window gains or loses focus.
596 The window have been destroyed and recreated
597 between a deactivate and an activate.
598 ===========
599 */
600 void CDAudio_Activate (qboolean active)
601 {
602  if (active)
603  CDAudio_Resume ();
604  else
605  CDAudio_Pause ();
606 }
wDeviceID
UINT wDeviceID
Definition: cd_win.c:43
CDAudio_CloseDoor
static void CDAudio_CloseDoor(void)
Definition: cd_win.c:58
CDAudio_Stop
void CDAudio_Stop(void)
int
CONST PIXELFORMATDESCRIPTOR int
Definition: qgl_win.c:35
CDAudio_Eject
static void CDAudio_Eject(void)
Definition: cd_win.c:49
CDAudio_GetAudioDiskInfo
static int CDAudio_GetAudioDiskInfo(void)
Definition: cd_win.c:67
playTrack
static byte playTrack
Definition: cd_win.c:36
qboolean
qboolean
Definition: q_shared.h:56
i
int i
Definition: q_shared.c:305
cd_nocd
cvar_t * cd_nocd
Definition: cd_win.c:39
playLooping
static qboolean playLooping
Definition: cd_win.c:33
cd_loopcount
cvar_t * cd_loopcount
Definition: cd_win.c:40
Cvar_Get
cvar_t * Cvar_Get(char *var_name, char *var_value, int flags)
Definition: cvar.c:127
cvar_s
Definition: q_shared.h:317
CDAudio_Activate
void CDAudio_Activate(qboolean active)
Cmd_Argv
char * Cmd_Argv(int arg)
Definition: cmd.c:517
loopcounter
int loopcounter
Definition: cd_win.c:44
Cmd_Argc
int Cmd_Argc(void)
Definition: cmd.c:507
CDAudio_Play
void CDAudio_Play(int track, qboolean looping)
Definition: cd_win.c:182
cdValid
static qboolean cdValid
Definition: cd_win.c:28
UINT
CONST PIXELFORMATDESCRIPTOR UINT
Definition: qgl_win.c:35
Cmd_AddCommand
void Cmd_AddCommand(char *cmd_name, xcommand_t function)
Definition: cmd.c:691
cdrom
static byte cdrom
Definition: cd_win.c:35
CVAR_ARCHIVE
#define CVAR_ARCHIVE
Definition: q_shared.h:309
cl_hwnd
HWND cl_hwnd
Definition: vid_dll.c:53
cvar_s::value
float value
Definition: q_shared.h:324
NULL
#define NULL
Definition: q_shared.h:60
CDAudio_RandomPlay
void CDAudio_RandomPlay(void)
Definition: cd_win.c:190
maxTrack
static byte maxTrack
Definition: cd_win.c:37
CDAudio_Init
int CDAudio_Init(void)
CDAudio_Pause
void CDAudio_Pause(void)
wasPlaying
static qboolean wasPlaying
Definition: cd_win.c:30
CDAudio_Update
void CDAudio_Update(void)
playing
static qboolean playing
Definition: cd_win.c:29
CDAudio_Play2
void CDAudio_Play2(int track, qboolean looping)
Definition: cd_win.c:107
Com_DPrintf
void Com_DPrintf(char *fmt,...)
Definition: common.c:155
DWORD
DWORD
Definition: qgl_win.c:49
initialized
static qboolean initialized
Definition: cd_win.c:31
Com_Printf
void Com_Printf(char *fmt,...)
Definition: common.c:102
Q_strcasecmp
int Q_strcasecmp(char *s1, char *s2)
Definition: q_shared.c:1229
enabled
static qboolean enabled
Definition: cd_win.c:32
remap
static byte remap[100]
Definition: cd_win.c:34
CDAudio_Shutdown
void CDAudio_Shutdown(void)
cd_looptrack
cvar_t * cd_looptrack
Definition: cd_win.c:41
Cvar_VariableValue
float Cvar_VariableValue(char *var_name)
Definition: cvar.c:63