cd_win.c (10308B)
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 39 cvar_t *cd_nocd; 40 cvar_t *cd_loopcount; 41 cvar_t *cd_looptrack; 42 43 UINT wDeviceID; 44 int loopcounter; 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 108 109 void CDAudio_Play2(int track, qboolean looping) 110 { 111 DWORD dwReturn; 112 MCI_PLAY_PARMS mciPlayParms; 113 MCI_STATUS_PARMS mciStatusParms; 114 115 if (!enabled) 116 return; 117 118 if (!cdValid) 119 { 120 CDAudio_GetAudioDiskInfo(); 121 if (!cdValid) 122 return; 123 } 124 125 track = remap[track]; 126 127 if (track < 1 || track > maxTrack) 128 { 129 CDAudio_Stop(); 130 return; 131 } 132 133 // don't try to play a non-audio track 134 mciStatusParms.dwItem = MCI_CDA_STATUS_TYPE_TRACK; 135 mciStatusParms.dwTrack = track; 136 dwReturn = mciSendCommand(wDeviceID, MCI_STATUS, MCI_STATUS_ITEM | MCI_TRACK | MCI_WAIT, (DWORD) (LPVOID) &mciStatusParms); 137 if (dwReturn) 138 { 139 Com_DPrintf("MCI_STATUS failed (%i)\n", dwReturn); 140 return; 141 } 142 if (mciStatusParms.dwReturn != MCI_CDA_TRACK_AUDIO) 143 { 144 Com_Printf("CDAudio: track %i is not audio\n", track); 145 return; 146 } 147 148 // get the length of the track to be played 149 mciStatusParms.dwItem = MCI_STATUS_LENGTH; 150 mciStatusParms.dwTrack = track; 151 dwReturn = mciSendCommand(wDeviceID, MCI_STATUS, MCI_STATUS_ITEM | MCI_TRACK | MCI_WAIT, (DWORD) (LPVOID) &mciStatusParms); 152 if (dwReturn) 153 { 154 Com_DPrintf("MCI_STATUS failed (%i)\n", dwReturn); 155 return; 156 } 157 158 if (playing) 159 { 160 if (playTrack == track) 161 return; 162 CDAudio_Stop(); 163 } 164 165 mciPlayParms.dwFrom = MCI_MAKE_TMSF(track, 0, 0, 0); 166 mciPlayParms.dwTo = (mciStatusParms.dwReturn << 8) | track; 167 mciPlayParms.dwCallback = (DWORD)cl_hwnd; 168 dwReturn = mciSendCommand(wDeviceID, MCI_PLAY, MCI_NOTIFY | MCI_FROM | MCI_TO, (DWORD)(LPVOID) &mciPlayParms); 169 if (dwReturn) 170 { 171 Com_DPrintf("CDAudio: MCI_PLAY failed (%i)\n", dwReturn); 172 return; 173 } 174 175 playLooping = looping; 176 playTrack = track; 177 playing = true; 178 179 if ( Cvar_VariableValue( "cd_nocd" ) ) 180 CDAudio_Pause (); 181 } 182 183 184 void CDAudio_Play(int track, qboolean looping) 185 { 186 // set a loop counter so that this track will change to the 187 // looptrack later 188 loopcounter = 0; 189 CDAudio_Play2(track, looping); 190 } 191 192 void CDAudio_Stop(void) 193 { 194 DWORD dwReturn; 195 196 if (!enabled) 197 return; 198 199 if (!playing) 200 return; 201 202 if (dwReturn = mciSendCommand(wDeviceID, MCI_STOP, 0, (DWORD)NULL)) 203 Com_DPrintf("MCI_STOP failed (%i)", dwReturn); 204 205 wasPlaying = false; 206 playing = false; 207 } 208 209 210 void CDAudio_Pause(void) 211 { 212 DWORD dwReturn; 213 MCI_GENERIC_PARMS mciGenericParms; 214 215 if (!enabled) 216 return; 217 218 if (!playing) 219 return; 220 221 mciGenericParms.dwCallback = (DWORD)cl_hwnd; 222 if (dwReturn = mciSendCommand(wDeviceID, MCI_PAUSE, 0, (DWORD)(LPVOID) &mciGenericParms)) 223 Com_DPrintf("MCI_PAUSE failed (%i)", dwReturn); 224 225 wasPlaying = playing; 226 playing = false; 227 } 228 229 230 void CDAudio_Resume(void) 231 { 232 DWORD dwReturn; 233 MCI_PLAY_PARMS mciPlayParms; 234 235 if (!enabled) 236 return; 237 238 if (!cdValid) 239 return; 240 241 if (!wasPlaying) 242 return; 243 244 mciPlayParms.dwFrom = MCI_MAKE_TMSF(playTrack, 0, 0, 0); 245 mciPlayParms.dwTo = MCI_MAKE_TMSF(playTrack + 1, 0, 0, 0); 246 mciPlayParms.dwCallback = (DWORD)cl_hwnd; 247 dwReturn = mciSendCommand(wDeviceID, MCI_PLAY, MCI_TO | MCI_NOTIFY, (DWORD)(LPVOID) &mciPlayParms); 248 if (dwReturn) 249 { 250 Com_DPrintf("CDAudio: MCI_PLAY failed (%i)\n", dwReturn); 251 return; 252 } 253 playing = true; 254 } 255 256 257 static void CD_f (void) 258 { 259 char *command; 260 int ret; 261 int n; 262 263 if (Cmd_Argc() < 2) 264 return; 265 266 command = Cmd_Argv (1); 267 268 if (Q_strcasecmp(command, "on") == 0) 269 { 270 enabled = true; 271 return; 272 } 273 274 if (Q_strcasecmp(command, "off") == 0) 275 { 276 if (playing) 277 CDAudio_Stop(); 278 enabled = false; 279 return; 280 } 281 282 if (Q_strcasecmp(command, "reset") == 0) 283 { 284 enabled = true; 285 if (playing) 286 CDAudio_Stop(); 287 for (n = 0; n < 100; n++) 288 remap[n] = n; 289 CDAudio_GetAudioDiskInfo(); 290 return; 291 } 292 293 if (Q_strcasecmp(command, "remap") == 0) 294 { 295 ret = Cmd_Argc() - 2; 296 if (ret <= 0) 297 { 298 for (n = 1; n < 100; n++) 299 if (remap[n] != n) 300 Com_Printf(" %u -> %u\n", n, remap[n]); 301 return; 302 } 303 for (n = 1; n <= ret; n++) 304 remap[n] = atoi(Cmd_Argv (n+1)); 305 return; 306 } 307 308 if (Q_strcasecmp(command, "close") == 0) 309 { 310 CDAudio_CloseDoor(); 311 return; 312 } 313 314 if (!cdValid) 315 { 316 CDAudio_GetAudioDiskInfo(); 317 if (!cdValid) 318 { 319 Com_Printf("No CD in player.\n"); 320 return; 321 } 322 } 323 324 if (Q_strcasecmp(command, "play") == 0) 325 { 326 CDAudio_Play(atoi(Cmd_Argv (2)), false); 327 return; 328 } 329 330 if (Q_strcasecmp(command, "loop") == 0) 331 { 332 CDAudio_Play(atoi(Cmd_Argv (2)), true); 333 return; 334 } 335 336 if (Q_strcasecmp(command, "stop") == 0) 337 { 338 CDAudio_Stop(); 339 return; 340 } 341 342 if (Q_strcasecmp(command, "pause") == 0) 343 { 344 CDAudio_Pause(); 345 return; 346 } 347 348 if (Q_strcasecmp(command, "resume") == 0) 349 { 350 CDAudio_Resume(); 351 return; 352 } 353 354 if (Q_strcasecmp(command, "eject") == 0) 355 { 356 if (playing) 357 CDAudio_Stop(); 358 CDAudio_Eject(); 359 cdValid = false; 360 return; 361 } 362 363 if (Q_strcasecmp(command, "info") == 0) 364 { 365 Com_Printf("%u tracks\n", maxTrack); 366 if (playing) 367 Com_Printf("Currently %s track %u\n", playLooping ? "looping" : "playing", playTrack); 368 else if (wasPlaying) 369 Com_Printf("Paused %s track %u\n", playLooping ? "looping" : "playing", playTrack); 370 return; 371 } 372 } 373 374 375 LONG CDAudio_MessageHandler(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) 376 { 377 if (lParam != wDeviceID) 378 return 1; 379 380 switch (wParam) 381 { 382 case MCI_NOTIFY_SUCCESSFUL: 383 if (playing) 384 { 385 playing = false; 386 if (playLooping) 387 { 388 // if the track has played the given number of times, 389 // go to the ambient track 390 if (++loopcounter >= cd_loopcount->value) 391 CDAudio_Play2(cd_looptrack->value, true); 392 else 393 CDAudio_Play2(playTrack, true); 394 } 395 } 396 break; 397 398 case MCI_NOTIFY_ABORTED: 399 case MCI_NOTIFY_SUPERSEDED: 400 break; 401 402 case MCI_NOTIFY_FAILURE: 403 Com_DPrintf("MCI_NOTIFY_FAILURE\n"); 404 CDAudio_Stop (); 405 cdValid = false; 406 break; 407 408 default: 409 Com_DPrintf("Unexpected MM_MCINOTIFY type (%i)\n", wParam); 410 return 1; 411 } 412 413 return 0; 414 } 415 416 417 void CDAudio_Update(void) 418 { 419 if ( cd_nocd->value != !enabled ) 420 { 421 if ( cd_nocd->value ) 422 { 423 CDAudio_Stop(); 424 enabled = false; 425 } 426 else 427 { 428 enabled = true; 429 CDAudio_Resume (); 430 } 431 } 432 } 433 434 435 int CDAudio_Init(void) 436 { 437 DWORD dwReturn; 438 MCI_OPEN_PARMS mciOpenParms; 439 MCI_SET_PARMS mciSetParms; 440 int n; 441 442 cd_nocd = Cvar_Get ("cd_nocd", "0", CVAR_ARCHIVE ); 443 cd_loopcount = Cvar_Get ("cd_loopcount", "4", 0); 444 cd_looptrack = Cvar_Get ("cd_looptrack", "11", 0); 445 if ( cd_nocd->value) 446 return -1; 447 448 mciOpenParms.lpstrDeviceType = "cdaudio"; 449 if (dwReturn = mciSendCommand(0, MCI_OPEN, MCI_OPEN_TYPE | MCI_OPEN_SHAREABLE, (DWORD) (LPVOID) &mciOpenParms)) 450 { 451 Com_Printf("CDAudio_Init: MCI_OPEN failed (%i)\n", dwReturn); 452 return -1; 453 } 454 wDeviceID = mciOpenParms.wDeviceID; 455 456 // Set the time format to track/minute/second/frame (TMSF). 457 mciSetParms.dwTimeFormat = MCI_FORMAT_TMSF; 458 if (dwReturn = mciSendCommand(wDeviceID, MCI_SET, MCI_SET_TIME_FORMAT, (DWORD)(LPVOID) &mciSetParms)) 459 { 460 Com_Printf("MCI_SET_TIME_FORMAT failed (%i)\n", dwReturn); 461 mciSendCommand(wDeviceID, MCI_CLOSE, 0, (DWORD)NULL); 462 return -1; 463 } 464 465 for (n = 0; n < 100; n++) 466 remap[n] = n; 467 initialized = true; 468 enabled = true; 469 470 if (CDAudio_GetAudioDiskInfo()) 471 { 472 // Com_Printf("CDAudio_Init: No CD in player.\n"); 473 cdValid = false; 474 enabled = false; 475 } 476 477 Cmd_AddCommand ("cd", CD_f); 478 479 Com_Printf("CD Audio Initialized\n"); 480 481 return 0; 482 } 483 484 485 void CDAudio_Shutdown(void) 486 { 487 if (!initialized) 488 return; 489 CDAudio_Stop(); 490 if (mciSendCommand(wDeviceID, MCI_CLOSE, MCI_WAIT, (DWORD)NULL)) 491 Com_DPrintf("CDAudio_Shutdown: MCI_CLOSE failed\n"); 492 } 493 494 495 /* 496 =========== 497 CDAudio_Activate 498 499 Called when the main window gains or loses focus. 500 The window have been destroyed and recreated 501 between a deactivate and an activate. 502 =========== 503 */ 504 void CDAudio_Activate (qboolean active) 505 { 506 if (active) 507 CDAudio_Resume (); 508 else 509 CDAudio_Pause (); 510 }