static char rcsid[] = "$Id: cd.c,v 1.12 2000/11/23 23:45:22 root Exp $";

/*
 * $Log: cd.c,v $
 * Revision 1.12  2000/11/23 23:45:22  root
 * #
 *
 * Revision 1.11  2000/10/07 18:30:05  root
 * #
 *
 * Revision 1.10  2000/10/06 19:52:19  root
 * #
 *
 * Revision 1.9  2000/09/24 01:46:05  root
 * #
 *
 * Revision 1.8  2000/09/24 01:12:42  root
 * #
 *
 * Revision 1.7  2000/02/20 03:03:57  root
 * #
 *
 * Revision 1.6  2000/02/20 03:03:53  root
 * #
 *
 * Revision 1.5  2000/02/20 02:52:13  root
 * #
 *
 * Revision 1.4  2000/02/16 13:53:26  root
 * #
 *
 * Revision 1.3  2000/02/16 13:51:59  root
 * #
 *
 * Revision 1.2  2000/02/16 13:50:11  root
 * *** empty log message ***
 *
 * Revision 1.1  2000/02/14 04:08:33  root
 * #
 *
 * Revision 1.4  1999/10/26 17:46:46  root
 * #
 *
 * Revision 1.3  1999/10/26 17:46:41  root
 * #
 *
 * Revision 1.2  1999/09/21 23:01:38  root
 * #
 *
 * Revision 1.1  1999/09/21 22:56:11  root
 * Initial revision
 *
 */


#include "project.h"

#include <sys/ioctl.h>
#include <linux/types.h>
#include <linux/cdrom.h>

extern void *msglib;
static int cdrom_fd;

int cdunit;

Byte *
hifipkt_ecd_time (Byte * ptr, Byte min, Byte secs)
{
  ptr = hifipkt_ebyte (ptr, min);
  ptr = hifipkt_ebyte (ptr, secs);
  return ptr;
}

Byte *
hifipkt_ecd_address (Byte * ptr, Byte track, Byte index, Byte min, Byte secs)
{
  ptr = hifipkt_ebyte (ptr, track);
  ptr = hifipkt_ebyte (ptr, index);
  return hifipkt_ecd_time (ptr, min, secs);
}



void
cd_cmdst_message (Byte dunit, Word cmd, Byte * data, Word len)
{
  if ((dunit != cdunit) && (dunit != HIFI_UNIT_ALL))
    return;


  switch (cmd)
    {
    case HIFI_CMD_VOL:
      printf ("Volm set to %d %d\n", data[0], data[1]);
      mixer_set_cdvol (data[0], data[1]);
      break;
    case HIFI_CMD_CD_PLAY:
      {
// FIXME: Currently ignore index (probably correct)
        struct cdrom_tocentry te, end;
        struct cdrom_msf msf;
        int i;

        end.cdte_track = CDROM_LEADOUT;
        end.cdte_format = CDROM_MSF;
        te.cdte_track = data[0];
        te.cdte_format = CDROM_MSF;

        if (ioctl (cdrom_fd, CDROMREADTOCENTRY, &te))
          return;
        if (ioctl (cdrom_fd, CDROMREADTOCENTRY, &end))
          return;

        i = te.cdte_addr.msf.second;
        i += data[3];
        if (i > 60)
          {
            te.cdte_addr.msf.minute++;
            i -= 60;
          }
        te.cdte_addr.msf.second = i;

        te.cdte_addr.msf.minute += data[2];

        msf.cdmsf_min0 = te.cdte_addr.msf.minute;
        msf.cdmsf_sec0 = te.cdte_addr.msf.second;
        msf.cdmsf_frame0 = te.cdte_addr.msf.frame;

        msf.cdmsf_min1 = end.cdte_addr.msf.minute;
        msf.cdmsf_sec1 = end.cdte_addr.msf.second;
        msf.cdmsf_frame1 = end.cdte_addr.msf.frame;


        if (ioctl (cdrom_fd, CDROMPLAYMSF, &msf))
          return;

        printf ("play %d %d %d:%02d (%d:%02d.%02d)\n", data[0], data[1],
                data[2], data[3], msf.cdmsf_min0, msf.cdmsf_sec0,
                msf.cdmsf_frame0);
      }
      break;
    case HIFI_CMD_STOP:
      printf ("stop\n");
      ioctl (cdrom_fd, CDROMSTOP, 0);
      break;
    case HIFI_CMD_EJECT:
      printf ("eject\n");
      ioctl (cdrom_fd, CDROMEJECT, 0);
      break;
    }


}


void
cd_open (void)
{
  cdrom_fd = open ("/dev/cdrom", O_NDELAY | O_RDONLY);
  if (cdrom_fd < 0)
    {
      perror ("open");
      exit (1);
    }
  if (ioctl (cdrom_fd, CDROM_LOCKDOOR, 0))
    {
      perror ("unlockdoor");
    }
  if (ioctl (cdrom_fd, CDROM_SELECT_SPEED, 1))
    {
      perror ("speed");
    }


}


void
cd_status (void)
{
  struct cdrom_subchnl sc;
  struct cdrom_tochdr th;
  struct cdrom_tocentry te, ten;

  Byte *buf = hifi_getbuf ();
  Byte *ptr = buf, *cptr;


  ptr = hifipkt_new_brd (ptr, HIFI_CLASS_CD, cdunit);

  sc.cdsc_format = CDROM_MSF;
  sc.cdsc_trk = HIFI_CD_DUDTRACK;
  if (!ioctl (cdrom_fd, CDROMSUBCHNL, &sc))
    {

      ptr = hifipkt_est (cptr = ptr, HIFI_ST_CD_STATE);

      ptr =
        hifipkt_ecd_address (ptr, sc.cdsc_trk, sc.cdsc_ind,
                             sc.cdsc_reladdr.msf.minute,
                             sc.cdsc_reladdr.msf.second);


      switch (sc.cdsc_audiostatus)
        {
        case CDROM_AUDIO_PLAY:
          ptr = hifipkt_ebyte (ptr, HIFI_CD_State_Playing);
          break;
        case CDROM_AUDIO_PAUSED:
          ptr = hifipkt_ebyte (ptr, HIFI_CD_State_Paused);
          break;
        case CDROM_AUDIO_NO_STATUS:
          ptr = hifipkt_ebyte (ptr, HIFI_CD_State_Stopped);
          break;
        default:
          ptr = hifipkt_ebyte (ptr, HIFI_CD_State_Unknown);
        }

      hifipkt_elen (cptr, HIFI_PTR_DIFF (ptr, cptr));

    }
  else
    {
      ptr = hifipkt_est (cptr = ptr, HIFI_ST_CD_STATE);
      ptr = hifipkt_ecd_address (ptr, 0, 0, 0, 0);
      ptr = hifipkt_ebyte (ptr, HIFI_CD_State_NoDisc);
      hifipkt_elen (cptr, HIFI_PTR_DIFF (ptr, cptr));

    }

  if (!ioctl (cdrom_fd, CDROMREADTOCHDR, &th))
    {

// printf("%d %d \n",sc.cdsc_trk,th.cdth_trk1);

      ptr = hifipkt_est (cptr = ptr, HIFI_ST_CD_TKSTATE);
      ptr = hifipkt_ebyte (ptr, sc.cdsc_trk);
      ptr = hifipkt_ebyte (ptr, th.cdth_trk1); //FIXME: trk0

      te.cdte_track = sc.cdsc_trk;
      te.cdte_format = CDROM_MSF;
      ten.cdte_format = CDROM_MSF;
      ten.cdte_track =
        (sc.cdsc_trk == th.cdth_trk1) ? CDROM_LEADOUT : (sc.cdsc_trk + 1);
      if ((!ioctl (cdrom_fd, CDROMREADTOCENTRY, &te))
          && (!ioctl (cdrom_fd, CDROMREADTOCENTRY, &ten)))
        {
          long int frames;
          frames = ten.cdte_addr.msf.minute - te.cdte_addr.msf.minute;
          frames *= 60;
          frames += ten.cdte_addr.msf.second - te.cdte_addr.msf.second;
          frames *= 75;
          frames += ten.cdte_addr.msf.frame - te.cdte_addr.msf.frame;

          frames = frames / 75;

          ptr = hifipkt_eword (ptr, (Word) frames);

        }
      else
        {
          ptr = hifipkt_eword (ptr, 0);
        }

      hifipkt_elen (cptr, HIFI_PTR_DIFF (ptr, cptr));

    }
  else
    {
      ptr = hifipkt_est (cptr = ptr, HIFI_ST_CD_TKSTATE);
      ptr = hifipkt_ebyte (ptr, sc.cdsc_trk);
      ptr = hifipkt_ebyte (ptr, 0);
      ptr = hifipkt_ecd_time (ptr, 0, 0);
      hifipkt_elen (cptr, HIFI_PTR_DIFF (ptr, cptr));
    }

  {
    int l, r;

    mixer_get_cdvol (&l, &r);



    ptr = hifipkt_est (cptr = ptr, HIFI_ST_VOL);
    ptr = hifipkt_ebyte (ptr, l);
    ptr = hifipkt_ebyte (ptr, r);
    hifipkt_elen (cptr, HIFI_PTR_DIFF (ptr, cptr));

  }
  ptr = hifipkt_eeof (ptr);

  hifi_send (msglib, buf, HIFI_PTR_DIFF (ptr, buf));
  hifi_freebuf (buf);
}
