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 }