home *** CD-ROM | disk | FTP | other *** search
/ The Datafile PD-CD 3 / PDCD_3.iso / internet / freenet / WrkBone001 / Linux / WBone / WorkBone-0.1 / hardware.c < prev    next >
C/C++ Source or Header  |  1993-12-08  |  16KB  |  745 lines

  1. #define load() /* nothing */
  2.  
  3. /*
  4.  * @(#)hardware.c    1.12    12/17/92
  5.  *
  6.  * Get information about a CD.
  7.  */
  8. #ifdef BOZO 
  9. static char *ident = "@(#)hardware.c    1.12 12/17/92";
  10. #endif
  11.  
  12. void strmcpy (char **t, char *s);
  13.  
  14. #include <errno.h>
  15. #include <stdio.h>
  16. #include <stdlib.h>
  17. #include <unistd.h>
  18. #include <sys/types.h>
  19. #include <sys/ioctl.h>
  20. #include <fcntl.h>
  21. #include <sys/param.h>
  22. #include <sys/stat.h>
  23. #include <sys/time.h>
  24. #    ifdef linux
  25. #     include <linux/cdrom.h>
  26. #    else
  27. #     include <sundev/srreg.h>
  28. #    endif /* linux */
  29. #include "struct.h"
  30.  
  31.  
  32. void *malloc();
  33. char *strchr();
  34.  
  35. extern struct play *playlist;
  36. extern struct cdinfo thiscd, *cd;
  37.  
  38. int    cd_fd = -1;
  39.  
  40. /*
  41.  * The minimum volume setting for the Sun and DEC CD-ROMs is 128 but for other
  42.  * machines this might not be the case.
  43.  */
  44. int    min_volume = 128;
  45. int    max_volume = 255;
  46.  
  47. # ifdef linux
  48. char    *cd_device = "/dev/cdrom\0";
  49. # else
  50. char    *cd_device = "/dev/rsr0\0";
  51. # endif
  52.  
  53. extern int cur_track, cur_index, cur_lasttrack, cur_firsttrack, cur_pos_abs,    
  54.     cur_frame, cur_pos_rel, cur_tracklen, cur_cdlen, cur_ntracks,    
  55.     cur_nsections, cur_cdmode, cur_listno, cur_stopmode, exit_on_eject,
  56.     cur_balance;
  57. extern char *cur_artist, *cur_cdname, *cur_trackname;
  58. extern char    cur_contd, cur_avoid;
  59. /*
  60.  * read_toc()
  61.  *
  62.  * Read the table of contents from the CD.  Return a pointer to a cdinfo
  63.  * struct containing the relevant information (minus artist/cdname/etc.)
  64.  * This is a static struct.  Returns NULL if there was an error.
  65.  *
  66.  * XXX allocates one trackinfo too many.
  67.  */
  68.  
  69. struct cdinfo *
  70. read_toc()
  71. {
  72.     struct playlist        *l;
  73.     struct cdrom_tochdr    hdr;
  74.     struct cdrom_tocentry    entry;
  75.     int            i, pos;
  76.  
  77.     if (cd_fd < 0)
  78.         return(NULL);
  79.  
  80.     if (ioctl(cd_fd, CDROMREADTOCHDR, &hdr))
  81.     {
  82.         perror("readtochdr");
  83.         return (NULL);
  84.     }
  85.  
  86.     thiscd.artist[0] = thiscd.cdname[0] = '\0';
  87.     thiscd.whichdb = thiscd.otherrc = thiscd.otherdb = NULL;
  88.     thiscd.length = 0;
  89.     thiscd.autoplay = thiscd.playmode = thiscd.volume = 0;
  90.     thiscd.ntracks = hdr.cdth_trk1;
  91.  
  92.     if (thiscd.lists != NULL)
  93.     {
  94.         for (l = thiscd.lists; l->name != NULL; l++)
  95.         {
  96.             free(l->name);
  97.             free(l->list);
  98.         }
  99.         free(thiscd.lists);
  100.         thiscd.lists = NULL;
  101.     }
  102.  
  103.     if (thiscd.trk != NULL)
  104.         free(thiscd.trk);
  105.  
  106.     thiscd.trk = malloc((thiscd.ntracks + 1) * sizeof(struct trackinfo));
  107.     if (thiscd.trk == NULL)
  108.     {
  109.         perror("malloc");
  110.         return (NULL);
  111.     }
  112.     for (i = 0; i <= thiscd.ntracks; i++)
  113.     {
  114.         if (i == thiscd.ntracks)
  115.             entry.cdte_track = CDROM_LEADOUT;
  116.         else
  117.             entry.cdte_track = i + 1;
  118.         entry.cdte_format = CDROM_MSF;
  119.         if (ioctl(cd_fd, CDROMREADTOCENTRY, &entry))
  120.         {
  121.             perror("tocentry read");
  122.             return (NULL);
  123.         }
  124.  
  125.         thiscd.trk[i].data =
  126.         thiscd.trk[i].avoid = entry.cdte_ctrl & CDROM_DATA_TRACK ?
  127.             1 : 0;
  128.         thiscd.trk[i].length = entry.cdte_addr.msf.minute * 60 +
  129.                 entry.cdte_addr.msf.second;
  130.         thiscd.trk[i].start = thiscd.trk[i].length * 75 +
  131.                 entry.cdte_addr.msf.frame;
  132.         thiscd.trk[i].songname = thiscd.trk[i].otherrc =
  133.         thiscd.trk[i].otherdb = NULL;
  134.         thiscd.trk[i].contd = 0;
  135.         thiscd.trk[i].volume = 0;
  136.         thiscd.trk[i].track = i + 1;
  137.         thiscd.trk[i].section = 0;
  138.     }
  139.  
  140. /* Now compute actual track lengths. */
  141.     pos = thiscd.trk[0].length;
  142.  
  143.     for (i = 0; i < thiscd.ntracks; i++)
  144.     {
  145.         thiscd.trk[i].length = thiscd.trk[i+1].length - pos;
  146.         pos = thiscd.trk[i+1].length;
  147.         if (thiscd.trk[i].data)
  148.             thiscd.trk[i].length = (thiscd.trk[i + 1].start -
  149.                 thiscd.trk[i].start) * 2;
  150.         if (thiscd.trk[i].avoid)
  151.             strmcpy(&thiscd.trk[i].songname, "DATA TRACK");
  152.     }
  153.  
  154.     thiscd.length = thiscd.trk[thiscd.ntracks].length;
  155.  
  156.     return (&thiscd);
  157. }
  158.  
  159. /*
  160.  * cd_status()
  161.  *
  162.  * Return values:
  163.  *
  164.  *    0    No CD in drive.
  165.  *    1    CD in drive.
  166.  *    2    CD has just been inserted (TOC has been read)
  167.  *    3    CD has just been removed
  168.  *
  169.  * Updates cur_track, cur_pos_rel, cur_pos_abs and other variables.
  170.  */
  171. int
  172. cd_status()
  173. {
  174.     char                realname[MAXPATHLEN];
  175.     static int            warned = 0;
  176.     struct cdrom_subchnl        sc;
  177.  
  178.     int                ret = 1;
  179.  
  180.     if (cd_fd < 0)
  181.     {
  182.  
  183.         if ((cd_fd = open(cd_device, 0)) < 0)
  184.         {
  185.  
  186.             if (errno == EACCES)
  187.             {
  188.                 if (!warned)
  189.                 {
  190.                     strcpy(realname, cd_device);
  191.  
  192.                     fprintf(stderr,
  193.         "As root, please run\n\nchmod 666 %s\n\n%s\n", realname,
  194.         "to give yourself permission to access the CD-ROM device.");
  195.                     warned++;
  196.                 }
  197.             }
  198.             else if (errno != ENXIO)
  199.             {
  200.                 perror(cd_device);
  201.                 if (thiscd.trk != NULL)
  202.                     free(thiscd.trk);
  203.                 exit(1);
  204.             }
  205.             return (0);
  206.         }
  207.         cur_cdmode = 5;
  208.     }
  209.  
  210.     if (warned)
  211.     {
  212.         warned = 0;
  213.         fprintf(stderr, "Thank you.\n");
  214.     }
  215.  
  216.     sc.cdsc_format = CDROM_MSF;
  217.  
  218.     if (ioctl(cd_fd, CDROMSUBCHNL, &sc))
  219.     {
  220.         cur_cdmode = 5;
  221.         cur_track = -1;
  222.         cur_cdlen = cur_tracklen = 1;
  223.         cur_pos_abs = cur_pos_rel = cur_frame = 0;
  224.  
  225.         if (exit_on_eject)
  226.             exit(0);
  227.  
  228.         return (0);
  229.     }
  230.  
  231.     if (cur_cdmode == 5)    /* CD has been ejected */
  232.     {
  233.         cur_pos_rel = cur_pos_abs = cur_frame = 0;
  234.  
  235.         if ((cd = read_toc()) == NULL) 
  236.         {
  237.             close(cd_fd);
  238.             cd_fd = -1;
  239.             if (exit_on_eject)
  240.                 exit(0);
  241.             else
  242.                 return (0);
  243.         }
  244.         cur_nsections = 0;
  245.         cur_ntracks = cd->ntracks;
  246.         cur_cdlen = cd->length;
  247.         load();
  248.         cur_artist = cd->artist;
  249.         cur_cdname = cd->cdname;
  250.         cur_cdmode = 4;
  251.         ret = 2;
  252.     }
  253.  
  254.     switch (sc.cdsc_audiostatus) {
  255.     case CDROM_AUDIO_PLAY:
  256.         cur_cdmode = 1;
  257. dopos:
  258.         cur_pos_abs = sc.cdsc_absaddr.msf.minute * 60 +
  259.             sc.cdsc_absaddr.msf.second;
  260.         cur_frame = cur_pos_abs * 75 + sc.cdsc_absaddr.msf.frame;
  261.  
  262.         /* Only look up the current track number if necessary. */
  263.         if (cur_track < 1 || cur_frame < cd->trk[cur_track-1].start ||
  264.                 cur_frame >= (cur_track >= cur_ntracks ?
  265.                 (cur_cdlen + 1) * 75 :
  266.                 cd->trk[cur_track].start))
  267.         {
  268.             cur_track = 0;
  269.             while (cur_track < cur_ntracks && cur_frame >=
  270.                     cd->trk[cur_track].start)
  271.                 cur_track++;
  272.         }
  273.         if (cur_track >= 1 && sc.cdsc_trk > cd->trk[cur_track-1].track)
  274.             cur_track++;
  275.  
  276.         cur_index = sc.cdsc_ind;
  277. doall:
  278.         if (cur_track >= 1 && cur_track <= cur_ntracks)
  279.         {
  280.             cur_trackname = cd->trk[cur_track-1].songname;
  281.             cur_avoid = cd->trk[cur_track-1].avoid;
  282.             cur_contd = cd->trk[cur_track-1].contd;
  283.             cur_pos_rel = (cur_frame -
  284.                 cd->trk[cur_track-1].start) / 75;
  285.             if (cur_pos_rel < 0)
  286.                 cur_pos_rel = -cur_pos_rel;
  287.         }
  288.  
  289.         /* note: workbone requires playlist == NULL always! */        
  290.         if (playlist != NULL && playlist[0].start)
  291.         {
  292.             cur_pos_abs -= cd->trk[playlist[cur_listno-1].
  293.                 start - 1].start / 75;
  294.             cur_pos_abs += playlist[cur_listno-1].starttime;
  295.         }
  296.         if (cur_pos_abs < 0)
  297.             cur_pos_abs = cur_frame = 0;
  298.  
  299.         if (cur_track < 1)
  300.             cur_tracklen = cd->length;
  301.         else
  302.             cur_tracklen = cd->trk[cur_track-1].length;
  303.         break;
  304.  
  305.     case CDROM_AUDIO_PAUSED:
  306.         if (cur_cdmode == 1 || cur_cdmode == 3)
  307.         {
  308.             cur_cdmode = 3;
  309.             goto dopos;
  310.         }
  311.         else
  312.             cur_cdmode = 4;
  313.         goto doall;
  314.  
  315.     case CDROM_AUDIO_COMPLETED:
  316.         cur_cdmode = 0;        /* waiting for next track. */
  317.         break;
  318.  
  319.     case CDROM_AUDIO_NO_STATUS:
  320.         cur_cdmode = 4;
  321.         cur_lasttrack = cur_firsttrack = -1;
  322.         goto doall;
  323.     }
  324.     return (ret);
  325. }
  326. #ifdef BOZO
  327. /*
  328.  * scale_volume(vol, max)
  329.  *
  330.  * Return a volume value suitable for passing to the CD-ROM drive.  "vol"
  331.  * is a volume slider setting; "max" is the slider's maximum value.
  332.  *
  333.  * On Sun and DEC CD-ROM drives, the amount of sound coming out the jack
  334.  * increases much faster toward the top end of the volume scale than it
  335.  * does at the bottom.  To make up for this, we make the volume scale look
  336.  * sort of logarithmic (actually an upside-down inverse square curve) so
  337.  * that the volume value passed to the drive changes less and less as you
  338.  * approach the maximum slider setting.  The actual formula looks like
  339.  *
  340.  *     (max^2 - (max - vol)^2) * (max_volume - min_volume)
  341.  * v = --------------------------------------------------- + min_volume
  342.  *                           max^2
  343.  *
  344.  * If your system's volume settings aren't broken in this way, something
  345.  * like the following should work:
  346.  *
  347.  *    return ((vol * (max_volume - min_volume)) / max + min_volume);
  348.  */
  349. scale_volume(vol, max)
  350.     int    vol, max;
  351. {
  352.     return ((max * max - (max - vol) * (max - vol)) *
  353.         (max_volume - min_volume) / (max * max) + min_volume);
  354. }
  355.  
  356. /*
  357.  * unscale_volume(cd_vol, max)
  358.  *
  359.  * Given a value between min_volume and max_volume, return the volume slider
  360.  * value needed to achieve that value.
  361.  *
  362.  * Rather