Quake-2

Quake 2 GPL Source Release
Log | Files | Refs

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 }