Quake-2

Quake 2 GPL Source Release
Log | Files | Refs

cd_linux.c (7284B)


      1 // Quake is a trademark of Id Software, Inc., (c) 1996 Id Software, Inc. All
      2 // rights reserved.
      3 
      4 #include <stdio.h>
      5 #include <unistd.h>
      6 #include <stdlib.h>
      7 #include <sys/ioctl.h>
      8 #include <sys/file.h>
      9 #include <sys/types.h>
     10 #include <fcntl.h>
     11 #include <string.h>
     12 #include <time.h>
     13 #include <errno.h>
     14 
     15 #include <linux/cdrom.h>
     16 
     17 #include "../client/client.h"
     18 
     19 static qboolean cdValid = false;
     20 static qboolean	playing = false;
     21 static qboolean	wasPlaying = false;
     22 static qboolean	initialized = false;
     23 static qboolean	enabled = true;
     24 static qboolean playLooping = false;
     25 static float	cdvolume;
     26 static byte 	remap[100];
     27 static byte		playTrack;
     28 static byte		maxTrack;
     29 
     30 static int cdfile = -1;
     31 
     32 //static char cd_dev[64] = "/dev/cdrom";
     33 
     34 cvar_t	*cd_volume;
     35 cvar_t *cd_nocd;
     36 cvar_t *cd_dev;
     37 
     38 void CDAudio_Pause(void);
     39 
     40 static void CDAudio_Eject(void)
     41 {
     42 	if (cdfile == -1 || !enabled)
     43 		return; // no cd init'd
     44 
     45 	if ( ioctl(cdfile, CDROMEJECT) == -1 ) 
     46 		Com_DPrintf("ioctl cdromeject failed\n");
     47 }
     48 
     49 
     50 static void CDAudio_CloseDoor(void)
     51 {
     52 	if (cdfile == -1 || !enabled)
     53 		return; // no cd init'd
     54 
     55 	if ( ioctl(cdfile, CDROMCLOSETRAY) == -1 ) 
     56 		Com_DPrintf("ioctl cdromclosetray failed\n");
     57 }
     58 
     59 static int CDAudio_GetAudioDiskInfo(void)
     60 {
     61 	struct cdrom_tochdr tochdr;
     62 
     63 	cdValid = false;
     64 
     65 	if ( ioctl(cdfile, CDROMREADTOCHDR, &tochdr) == -1 ) 
     66     {
     67       Com_DPrintf("ioctl cdromreadtochdr failed\n");
     68 	  return -1;
     69     }
     70 
     71 	if (tochdr.cdth_trk0 < 1)
     72 	{
     73 		Com_DPrintf("CDAudio: no music tracks\n");
     74 		return -1;
     75 	}
     76 
     77 	cdValid = true;
     78 	maxTrack = tochdr.cdth_trk1;
     79 
     80 	return 0;
     81 }
     82 
     83 
     84 void CDAudio_Play(int track, qboolean looping)
     85 {
     86 	struct cdrom_tocentry entry;
     87 	struct cdrom_ti ti;
     88 
     89 	if (cdfile == -1 || !enabled)
     90 		return;
     91 	
     92 	if (!cdValid)
     93 	{
     94 		CDAudio_GetAudioDiskInfo();
     95 		if (!cdValid)
     96 			return;
     97 	}
     98 
     99 	track = remap[track];
    100 
    101 	if (track < 1 || track > maxTrack)
    102 	{
    103 		Com_DPrintf("CDAudio: Bad track number %u.\n", track);
    104 		return;
    105 	}
    106 
    107 	// don't try to play a non-audio track
    108 	entry.cdte_track = track;
    109 	entry.cdte_format = CDROM_MSF;
    110     if ( ioctl(cdfile, CDROMREADTOCENTRY, &entry) == -1 )
    111 	{
    112 		Com_DPrintf("ioctl cdromreadtocentry failed\n");
    113 		return;
    114 	}
    115 	if (entry.cdte_ctrl == CDROM_DATA_TRACK)
    116 	{
    117 		Com_Printf("CDAudio: track %i is not audio\n", track);
    118 		return;
    119 	}
    120 
    121 	if (playing)
    122 	{
    123 		if (playTrack == track)
    124 			return;
    125 		CDAudio_Stop();
    126 	}
    127 
    128 	ti.cdti_trk0 = track;
    129 	ti.cdti_trk1 = track;
    130 	ti.cdti_ind0 = 1;
    131 	ti.cdti_ind1 = 99;
    132 
    133 	if ( ioctl(cdfile, CDROMPLAYTRKIND, &ti) == -1 ) 
    134     {
    135 		Com_DPrintf("ioctl cdromplaytrkind failed\n");
    136 		return;
    137     }
    138 
    139 	if ( ioctl(cdfile, CDROMRESUME) == -1 ) 
    140 		Com_DPrintf("ioctl cdromresume failed\n");
    141 
    142 	playLooping = looping;
    143 	playTrack = track;
    144 	playing = true;
    145 
    146 	if (cd_volume->value == 0.0)
    147 		CDAudio_Pause ();
    148 }
    149 
    150 
    151 void CDAudio_Stop(void)
    152 {
    153 	if (cdfile == -1 || !enabled)
    154 		return;
    155 	
    156 	if (!playing)
    157 		return;
    158 
    159 	if ( ioctl(cdfile, CDROMSTOP) == -1 )
    160 		Com_DPrintf("ioctl cdromstop failed (%d)\n", errno);
    161 
    162 	wasPlaying = false;
    163 	playing = false;
    164 }
    165 
    166 void CDAudio_Pause(void)
    167 {
    168 	if (cdfile == -1 || !enabled)
    169 		return;
    170 
    171 	if (!playing)
    172 		return;
    173 
    174 	if ( ioctl(cdfile, CDROMPAUSE) == -1 ) 
    175 		Com_DPrintf("ioctl cdrompause failed\n");
    176 
    177 	wasPlaying = playing;
    178 	playing = false;
    179 }
    180 
    181 
    182 void CDAudio_Resume(void)
    183 {
    184 	if (cdfile == -1 || !enabled)
    185 		return;
    186 	
    187 	if (!cdValid)
    188 		return;
    189 
    190 	if (!wasPlaying)
    191 		return;
    192 	
    193 	if ( ioctl(cdfile, CDROMRESUME) == -1 ) 
    194 		Com_DPrintf("ioctl cdromresume failed\n");
    195 	playing = true;
    196 }
    197 
    198 static void CD_f (void)
    199 {
    200 	char	*command;
    201 	int		ret;
    202 	int		n;
    203 
    204 	if (Cmd_Argc() < 2)
    205 		return;
    206 
    207 	command = Cmd_Argv (1);
    208 
    209 	if (Q_strcasecmp(command, "on") == 0)
    210 	{
    211 		enabled = true;
    212 		return;
    213 	}
    214 
    215 	if (Q_strcasecmp(command, "off") == 0)
    216 	{
    217 		if (playing)
    218 			CDAudio_Stop();
    219 		enabled = false;
    220 		return;
    221 	}
    222 
    223 	if (Q_strcasecmp(command, "reset") == 0)
    224 	{
    225 		enabled = true;
    226 		if (playing)
    227 			CDAudio_Stop();
    228 		for (n = 0; n < 100; n++)
    229 			remap[n] = n;
    230 		CDAudio_GetAudioDiskInfo();
    231 		return;
    232 	}
    233 
    234 	if (Q_strcasecmp(command, "remap") == 0)
    235 	{
    236 		ret = Cmd_Argc() - 2;
    237 		if (ret <= 0)
    238 		{
    239 			for (n = 1; n < 100; n++)
    240 				if (remap[n] != n)
    241 					Com_Printf("  %u -> %u\n", n, remap[n]);
    242 			return;
    243 		}
    244 		for (n = 1; n <= ret; n++)
    245 			remap[n] = atoi(Cmd_Argv (n+1));
    246 		return;
    247 	}
    248 
    249 	if (Q_strcasecmp(command, "close") == 0)
    250 	{
    251 		CDAudio_CloseDoor();
    252 		return;
    253 	}
    254 
    255 	if (!cdValid)
    256 	{
    257 		CDAudio_GetAudioDiskInfo();
    258 		if (!cdValid)
    259 		{
    260 			Com_Printf("No CD in player.\n");
    261 			return;
    262 		}
    263 	}
    264 
    265 	if (Q_strcasecmp(command, "play") == 0)
    266 	{
    267 		CDAudio_Play((byte)atoi(Cmd_Argv (2)), false);
    268 		return;
    269 	}
    270 
    271 	if (Q_strcasecmp(command, "loop") == 0)
    272 	{
    273 		CDAudio_Play((byte)atoi(Cmd_Argv (2)), true);
    274 		return;
    275 	}
    276 
    277 	if (Q_strcasecmp(command, "stop") == 0)
    278 	{
    279 		CDAudio_Stop();
    280 		return;
    281 	}
    282 
    283 	if (Q_strcasecmp(command, "pause") == 0)
    284 	{
    285 		CDAudio_Pause();
    286 		return;
    287 	}
    288 
    289 	if (Q_strcasecmp(command, "resume") == 0)
    290 	{
    291 		CDAudio_Resume();
    292 		return;
    293 	}
    294 
    295 	if (Q_strcasecmp(command, "eject") == 0)
    296 	{
    297 		if (playing)
    298 			CDAudio_Stop();
    299 		CDAudio_Eject();
    300 		cdValid = false;
    301 		return;
    302 	}
    303 
    304 	if (Q_strcasecmp(command, "info") == 0)
    305 	{
    306 		Com_Printf("%u tracks\n", maxTrack);
    307 		if (playing)
    308 			Com_Printf("Currently %s track %u\n", playLooping ? "looping" : "playing", playTrack);
    309 		else if (wasPlaying)
    310 			Com_Printf("Paused %s track %u\n", playLooping ? "looping" : "playing", playTrack);
    311 		Com_Printf("Volume is %f\n", cdvolume);
    312 		return;
    313 	}
    314 }
    315 
    316 void CDAudio_Update(void)
    317 {
    318 	struct cdrom_subchnl subchnl;
    319 	static time_t lastchk;
    320 
    321 	if (cdfile == -1 || !enabled)
    322 		return;
    323 
    324 	if (cd_volume && cd_volume->value != cdvolume)
    325 	{
    326 		if (cdvolume)
    327 		{
    328 			Cvar_SetValue ("cd_volume", 0.0);
    329 			cdvolume = cd_volume->value;
    330 			CDAudio_Pause ();
    331 		}
    332 		else
    333 		{
    334 			Cvar_SetValue ("cd_volume", 1.0);
    335 			cdvolume = cd_volume->value;
    336 			CDAudio_Resume ();
    337 		}
    338 	}
    339 
    340 	if (playing && lastchk < time(NULL)) {
    341 		lastchk = time(NULL) + 2; //two seconds between chks
    342 		subchnl.cdsc_format = CDROM_MSF;
    343 		if (ioctl(cdfile, CDROMSUBCHNL, &subchnl) == -1 ) {
    344 			Com_DPrintf("ioctl cdromsubchnl failed\n");
    345 			playing = false;
    346 			return;
    347 		}
    348 		if (subchnl.cdsc_audiostatus != CDROM_AUDIO_PLAY &&
    349 			subchnl.cdsc_audiostatus != CDROM_AUDIO_PAUSED) {
    350 			playing = false;
    351 			if (playLooping)
    352 				CDAudio_Play(playTrack, true);
    353 		}
    354 	}
    355 }
    356 
    357 int CDAudio_Init(void)
    358 {
    359 	int i;
    360 	cvar_t			*cv;
    361 	extern uid_t saved_euid;
    362 
    363 	cv = Cvar_Get ("nocdaudio", "0", CVAR_NOSET);
    364 	if (cv->value)
    365 		return -1;
    366 
    367 	cd_nocd = Cvar_Get ("cd_nocd", "0", CVAR_ARCHIVE );
    368 	if ( cd_nocd->value)
    369 		return -1;
    370 
    371 	cd_volume = Cvar_Get ("cd_volume", "1", CVAR_ARCHIVE);
    372 
    373 	cd_dev = Cvar_Get("cd_dev", "/dev/cdrom", CVAR_ARCHIVE);
    374 
    375 	seteuid(saved_euid);
    376 
    377 	cdfile = open(cd_dev->string, O_RDONLY);
    378 
    379 	seteuid(getuid());
    380 
    381 	if (cdfile == -1) {
    382 		Com_Printf("CDAudio_Init: open of \"%s\" failed (%i)\n", cd_dev->string, errno);
    383 		cdfile = -1;
    384 		return -1;
    385 	}
    386 
    387 	for (i = 0; i < 100; i++)
    388 		remap[i] = i;
    389 	initialized = true;
    390 	enabled = true;
    391 
    392 	if (CDAudio_GetAudioDiskInfo())
    393 	{
    394 		Com_Printf("CDAudio_Init: No CD in player.\n");
    395 		cdValid = false;
    396 	}
    397 
    398 	Cmd_AddCommand ("cd", CD_f);
    399 
    400 	Com_Printf("CD Audio Initialized\n");
    401 
    402 	return 0;
    403 }
    404 
    405 void CDAudio_Activate (qboolean active)
    406 {
    407 	if (active)
    408 		CDAudio_Resume ();
    409 	else
    410 		CDAudio_Pause ();
    411 }
    412 
    413 void CDAudio_Shutdown(void)
    414 {
    415 	if (!initialized)
    416 		return;
    417 	CDAudio_Stop();
    418 	close(cdfile);
    419 	cdfile = -1;
    420 }