cd_linux.c 7.1 KB

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