|
|
1.1 ! root 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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.