Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

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