cd_win.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511
  1. /*
  2. Copyright (C) 1997-2001 Id Software, Inc.
  3. This program is free software; you can redistribute it and/or
  4. modify it under the terms of the GNU General Public License
  5. as published by the Free Software Foundation; either version 2
  6. of the License, or (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. See the GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program; if not, write to the Free Software
  13. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  14. */
  15. // Quake is a trademark of Id Software, Inc., (c) 1996 Id Software, Inc. All
  16. // rights reserved.
  17. #include <windows.h>
  18. #include "../client/client.h"
  19. extern HWND cl_hwnd;
  20. static qboolean cdValid = false;
  21. static qboolean playing = false;
  22. static qboolean wasPlaying = false;
  23. static qboolean initialized = false;
  24. static qboolean enabled = false;
  25. static qboolean playLooping = false;
  26. static byte remap[100];
  27. static byte cdrom;
  28. static byte playTrack;
  29. static byte maxTrack;
  30. cvar_t *cd_nocd;
  31. cvar_t *cd_loopcount;
  32. cvar_t *cd_looptrack;
  33. UINT wDeviceID;
  34. int loopcounter;
  35. void CDAudio_Pause(void);
  36. static void CDAudio_Eject(void)
  37. {
  38. DWORD dwReturn;
  39. if (dwReturn = mciSendCommand(wDeviceID, MCI_SET, MCI_SET_DOOR_OPEN, (DWORD)NULL))
  40. Com_DPrintf("MCI_SET_DOOR_OPEN failed (%i)\n", dwReturn);
  41. }
  42. static void CDAudio_CloseDoor(void)
  43. {
  44. DWORD dwReturn;
  45. if (dwReturn = mciSendCommand(wDeviceID, MCI_SET, MCI_SET_DOOR_CLOSED, (DWORD)NULL))
  46. Com_DPrintf("MCI_SET_DOOR_CLOSED failed (%i)\n", dwReturn);
  47. }
  48. static int CDAudio_GetAudioDiskInfo(void)
  49. {
  50. DWORD dwReturn;
  51. MCI_STATUS_PARMS mciStatusParms;
  52. cdValid = false;
  53. mciStatusParms.dwItem = MCI_STATUS_READY;
  54. dwReturn = mciSendCommand(wDeviceID, MCI_STATUS, MCI_STATUS_ITEM | MCI_WAIT, (DWORD) (LPVOID) &mciStatusParms);
  55. if (dwReturn)
  56. {
  57. Com_DPrintf("CDAudio: drive ready test - get status failed\n");
  58. return -1;
  59. }
  60. if (!mciStatusParms.dwReturn)
  61. {
  62. Com_DPrintf("CDAudio: drive not ready\n");
  63. return -1;
  64. }
  65. mciStatusParms.dwItem = MCI_STATUS_NUMBER_OF_TRACKS;
  66. dwReturn = mciSendCommand(wDeviceID, MCI_STATUS, MCI_STATUS_ITEM | MCI_WAIT, (DWORD) (LPVOID) &mciStatusParms);
  67. if (dwReturn)
  68. {
  69. Com_DPrintf("CDAudio: get tracks - status failed\n");
  70. return -1;
  71. }
  72. if (mciStatusParms.dwReturn < 1)
  73. {
  74. Com_DPrintf("CDAudio: no music tracks\n");
  75. return -1;
  76. }
  77. cdValid = true;
  78. maxTrack = mciStatusParms.dwReturn;
  79. return 0;
  80. }
  81. void CDAudio_Play2(int track, qboolean looping)
  82. {
  83. DWORD dwReturn;
  84. MCI_PLAY_PARMS mciPlayParms;
  85. MCI_STATUS_PARMS mciStatusParms;
  86. if (!enabled)
  87. return;
  88. if (!cdValid)
  89. {
  90. CDAudio_GetAudioDiskInfo();
  91. if (!cdValid)
  92. return;
  93. }
  94. track = remap[track];
  95. if (track < 1 || track > maxTrack)
  96. {
  97. CDAudio_Stop();
  98. return;
  99. }
  100. // don't try to play a non-audio track
  101. mciStatusParms.dwItem = MCI_CDA_STATUS_TYPE_TRACK;
  102. mciStatusParms.dwTrack = track;
  103. dwReturn = mciSendCommand(wDeviceID, MCI_STATUS, MCI_STATUS_ITEM | MCI_TRACK | MCI_WAIT, (DWORD) (LPVOID) &mciStatusParms);
  104. if (dwReturn)
  105. {
  106. Com_DPrintf("MCI_STATUS failed (%i)\n", dwReturn);
  107. return;
  108. }
  109. if (mciStatusParms.dwReturn != MCI_CDA_TRACK_AUDIO)
  110. {
  111. Com_Printf("CDAudio: track %i is not audio\n", track);
  112. return;
  113. }
  114. // get the length of the track to be played
  115. mciStatusParms.dwItem = MCI_STATUS_LENGTH;
  116. mciStatusParms.dwTrack = track;
  117. dwReturn = mciSendCommand(wDeviceID, MCI_STATUS, MCI_STATUS_ITEM | MCI_TRACK | MCI_WAIT, (DWORD) (LPVOID) &mciStatusParms);
  118. if (dwReturn)
  119. {
  120. Com_DPrintf("MCI_STATUS failed (%i)\n", dwReturn);
  121. return;
  122. }
  123. if (playing)
  124. {
  125. if (playTrack == track)
  126. return;
  127. CDAudio_Stop();
  128. }
  129. mciPlayParms.dwFrom = MCI_MAKE_TMSF(track, 0, 0, 0);
  130. mciPlayParms.dwTo = (mciStatusParms.dwReturn << 8) | track;
  131. mciPlayParms.dwCallback = (DWORD)cl_hwnd;
  132. dwReturn = mciSendCommand(wDeviceID, MCI_PLAY, MCI_NOTIFY | MCI_FROM | MCI_TO, (DWORD)(LPVOID) &mciPlayParms);
  133. if (dwReturn)
  134. {
  135. Com_DPrintf("CDAudio: MCI_PLAY failed (%i)\n", dwReturn);
  136. return;
  137. }
  138. playLooping = looping;
  139. playTrack = track;
  140. playing = true;
  141. if ( Cvar_VariableValue( "cd_nocd" ) )
  142. CDAudio_Pause ();
  143. }
  144. void CDAudio_Play(int track, qboolean looping)
  145. {
  146. // set a loop counter so that this track will change to the
  147. // looptrack later
  148. loopcounter = 0;
  149. CDAudio_Play2(track, looping);
  150. }
  151. void CDAudio_Stop(void)
  152. {
  153. DWORD dwReturn;
  154. if (!enabled)
  155. return;
  156. if (!playing)
  157. return;
  158. if (dwReturn = mciSendCommand(wDeviceID, MCI_STOP, 0, (DWORD)NULL))
  159. Com_DPrintf("MCI_STOP failed (%i)", dwReturn);
  160. wasPlaying = false;
  161. playing = false;
  162. }
  163. void CDAudio_Pause(void)
  164. {
  165. DWORD dwReturn;
  166. MCI_GENERIC_PARMS mciGenericParms;
  167. if (!enabled)
  168. return;
  169. if (!playing)
  170. return;
  171. mciGenericParms.dwCallback = (DWORD)cl_hwnd;
  172. if (dwReturn = mciSendCommand(wDeviceID, MCI_PAUSE, 0, (DWORD)(LPVOID) &mciGenericParms))
  173. Com_DPrintf("MCI_PAUSE failed (%i)", dwReturn);
  174. wasPlaying = playing;
  175. playing = false;
  176. }
  177. void CDAudio_Resume(void)
  178. {
  179. DWORD dwReturn;
  180. MCI_PLAY_PARMS mciPlayParms;
  181. if (!enabled)
  182. return;
  183. if (!cdValid)
  184. return;
  185. if (!wasPlaying)
  186. return;
  187. mciPlayParms.dwFrom = MCI_MAKE_TMSF(playTrack, 0, 0, 0);
  188. mciPlayParms.dwTo = MCI_MAKE_TMSF(playTrack + 1, 0, 0, 0);
  189. mciPlayParms.dwCallback = (DWORD)cl_hwnd;
  190. dwReturn = mciSendCommand(wDeviceID, MCI_PLAY, MCI_TO | MCI_NOTIFY, (DWORD)(LPVOID) &mciPlayParms);
  191. if (dwReturn)
  192. {
  193. Com_DPrintf("CDAudio: MCI_PLAY failed (%i)\n", dwReturn);
  194. return;
  195. }
  196. playing = true;
  197. }
  198. static void CD_f (void)
  199. {
  200. char *command;
  201. int ret;
  202. int n;
  203. if (Cmd_Argc() < 2)
  204. return;
  205. command = Cmd_Argv (1);
  206. if (Q_strcasecmp(command, "on") == 0)
  207. {
  208. enabled = true;
  209. return;
  210. }
  211. if (Q_strcasecmp(command, "off") == 0)
  212. {
  213. if (playing)
  214. CDAudio_Stop();
  215. enabled = false;
  216. return;
  217. }
  218. if (Q_strcasecmp(command, "reset") == 0)
  219. {
  220. enabled = true;
  221. if (playing)
  222. CDAudio_Stop();
  223. for (n = 0; n < 100; n++)
  224. remap[n] = n;
  225. CDAudio_GetAudioDiskInfo();
  226. return;
  227. }
  228. if (Q_strcasecmp(command, "remap") == 0)
  229. {
  230. ret = Cmd_Argc() - 2;
  231. if (ret <= 0)
  232. {
  233. for (n = 1; n < 100; n++)
  234. if (remap[n] != n)
  235. Com_Printf(" %u -> %u\n", n, remap[n]);
  236. return;
  237. }
  238. for (n = 1; n <= ret; n++)
  239. remap[n] = atoi(Cmd_Argv (n+1));
  240. return;
  241. }
  242. if (Q_strcasecmp(command, "close") == 0)
  243. {
  244. CDAudio_CloseDoor();
  245. return;
  246. }
  247. if (!cdValid)
  248. {
  249. CDAudio_GetAudioDiskInfo();
  250. if (!cdValid)
  251. {
  252. Com_Printf("No CD in player.\n");
  253. return;
  254. }
  255. }
  256. if (Q_strcasecmp(command, "play") == 0)
  257. {
  258. CDAudio_Play(atoi(Cmd_Argv (2)), false);
  259. return;
  260. }
  261. if (Q_strcasecmp(command, "loop") == 0)
  262. {
  263. CDAudio_Play(atoi(Cmd_Argv (2)), true);
  264. return;
  265. }
  266. if (Q_strcasecmp(command, "stop") == 0)
  267. {
  268. CDAudio_Stop();
  269. return;
  270. }
  271. if (Q_strcasecmp(command, "pause") == 0)
  272. {
  273. CDAudio_Pause();
  274. return;
  275. }
  276. if (Q_strcasecmp(command, "resume") == 0)
  277. {
  278. CDAudio_Resume();
  279. return;
  280. }
  281. if (Q_strcasecmp(command, "eject") == 0)
  282. {
  283. if (playing)
  284. CDAudio_Stop();
  285. CDAudio_Eject();
  286. cdValid = false;
  287. return;
  288. }
  289. if (Q_strcasecmp(command, "info") == 0)
  290. {
  291. Com_Printf("%u tracks\n", maxTrack);
  292. if (playing)
  293. Com_Printf("Currently %s track %u\n", playLooping ? "looping" : "playing", playTrack);
  294. else if (wasPlaying)
  295. Com_Printf("Paused %s track %u\n", playLooping ? "looping" : "playing", playTrack);
  296. return;
  297. }
  298. }
  299. LONG CDAudio_MessageHandler(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  300. {
  301. if (lParam != wDeviceID)
  302. return 1;
  303. switch (wParam)
  304. {
  305. case MCI_NOTIFY_SUCCESSFUL:
  306. if (playing)
  307. {
  308. playing = false;
  309. if (playLooping)
  310. {
  311. // if the track has played the given number of times,
  312. // go to the ambient track
  313. if (++loopcounter >= cd_loopcount->value)
  314. CDAudio_Play2(cd_looptrack->value, true);
  315. else
  316. CDAudio_Play2(playTrack, true);
  317. }
  318. }
  319. break;
  320. case MCI_NOTIFY_ABORTED:
  321. case MCI_NOTIFY_SUPERSEDED:
  322. break;
  323. case MCI_NOTIFY_FAILURE:
  324. Com_DPrintf("MCI_NOTIFY_FAILURE\n");
  325. CDAudio_Stop ();
  326. cdValid = false;
  327. break;
  328. default:
  329. Com_DPrintf("Unexpected MM_MCINOTIFY type (%i)\n", wParam);
  330. return 1;
  331. }
  332. return 0;
  333. }
  334. void CDAudio_Update(void)
  335. {
  336. if ( cd_nocd->value != !enabled )
  337. {
  338. if ( cd_nocd->value )
  339. {
  340. CDAudio_Stop();
  341. enabled = false;
  342. }
  343. else
  344. {
  345. enabled = true;
  346. CDAudio_Resume ();
  347. }
  348. }
  349. }
  350. int CDAudio_Init(void)
  351. {
  352. DWORD dwReturn;
  353. MCI_OPEN_PARMS mciOpenParms;
  354. MCI_SET_PARMS mciSetParms;
  355. int n;
  356. cd_nocd = Cvar_Get ("cd_nocd", "0", CVAR_ARCHIVE );
  357. cd_loopcount = Cvar_Get ("cd_loopcount", "4", 0);
  358. cd_looptrack = Cvar_Get ("cd_looptrack", "11", 0);
  359. if ( cd_nocd->value)
  360. return -1;
  361. mciOpenParms.lpstrDeviceType = "cdaudio";
  362. if (dwReturn = mciSendCommand(0, MCI_OPEN, MCI_OPEN_TYPE | MCI_OPEN_SHAREABLE, (DWORD) (LPVOID) &mciOpenParms))
  363. {
  364. Com_Printf("CDAudio_Init: MCI_OPEN failed (%i)\n", dwReturn);
  365. return -1;
  366. }
  367. wDeviceID = mciOpenParms.wDeviceID;
  368. // Set the time format to track/minute/second/frame (TMSF).
  369. mciSetParms.dwTimeFormat = MCI_FORMAT_TMSF;
  370. if (dwReturn = mciSendCommand(wDeviceID, MCI_SET, MCI_SET_TIME_FORMAT, (DWORD)(LPVOID) &mciSetParms))
  371. {
  372. Com_Printf("MCI_SET_TIME_FORMAT failed (%i)\n", dwReturn);
  373. mciSendCommand(wDeviceID, MCI_CLOSE, 0, (DWORD)NULL);
  374. return -1;
  375. }
  376. for (n = 0; n < 100; n++)
  377. remap[n] = n;
  378. initialized = true;
  379. enabled = true;
  380. if (CDAudio_GetAudioDiskInfo())
  381. {
  382. // Com_Printf("CDAudio_Init: No CD in player.\n");
  383. cdValid = false;
  384. enabled = false;
  385. }
  386. Cmd_AddCommand ("cd", CD_f);
  387. Com_Printf("CD Audio Initialized\n");
  388. return 0;
  389. }
  390. void CDAudio_Shutdown(void)
  391. {
  392. if (!initialized)
  393. return;
  394. CDAudio_Stop();
  395. if (mciSendCommand(wDeviceID, MCI_CLOSE, MCI_WAIT, (DWORD)NULL))
  396. Com_DPrintf("CDAudio_Shutdown: MCI_CLOSE failed\n");
  397. }
  398. /*
  399. ===========
  400. CDAudio_Activate
  401. Called when the main window gains or loses focus.
  402. The window have been destroyed and recreated
  403. between a deactivate and an activate.
  404. ===========
  405. */
  406. void CDAudio_Activate (qboolean active)
  407. {
  408. if (active)
  409. CDAudio_Resume ();
  410. else
  411. CDAudio_Pause ();
  412. }