/*                           CDROM AUDIO PLAYER
			      By Barry Egerter

			    Written July 18, 1994

			    Using Borland C++ 3.1

	     Code and program: FREEWARE - alter and use at will.


	       Internet Email:      barry.egerter@softnet.com
*/

#include <dos.h>
#include <mem.h>
#include <conio.h>
#include <stdio.h>
#include <stdlib.h>
#include <process.h>
#include <ctype.h>
#include "cdrom.h"
/******************************PLAYER PROGRAM*******************************/

/* VARIABLES GLOBAL TO TEST PROGRAM */
  struct playinfo my_cd;
  struct volumeinfo my_vol;
  unsigned char minutes, seconds, frames;
  short screeny, ctr, done, playing, paused;
  unsigned long disklen, mark[900];
  unsigned char ch, playmode, curupc[7];
  unsigned short curcheck, curmark;
  unsigned long oldstatus = 0;
#define TRUE 1
#define FALSE 0
#define PLAY_DISK 0
#define PLAY_TRACK 1
#define PLAY_SHUFFLE 2

void show_status (void);
void show_mode (void);
void newdisk (void);

void show_status (void)
{
  unsigned char diskid[6];

  cd_status ();
  oldstatus = cdrom_data.status;
  textbackground (BLUE);
  textcolor (WHITE);

  gotoxy (42, 1);
  if (cdrom_data.status & 1)
    cprintf ("Door open  ");
  else cprintf ("Door closed");

  gotoxy (42, 2);
  if (cdrom_data.status & 2)
    cprintf ("Door unlocked");
  else cprintf ("Door locked  ");

  gotoxy (42, 3);
  if (cdrom_data.status & 4)
    cprintf ("Supports raw & cooked reading");
  else cprintf ("Cooked reading only          ");

  gotoxy (42, 4);
  if (cdrom_data.status & 8)
    cprintf ("Writable!");
  else cprintf ("Read Only");

  gotoxy (42, 5);
  if (cdrom_data.status & 16)
    cprintf ("Can play audio/video tracks");
  else cprintf ("Data read only              ");

  gotoxy (42, 6);
  if (cdrom_data.status & 128)
    cprintf ("Supports prefetch requests");
  else cprintf ("No prefetching             ");

  gotoxy (42, 7);
  if (cdrom_data.status & 256)
    cprintf ("Supports audio channel control");
  else cprintf ("No audio channel manipulation ");

  gotoxy (42, 8);
  if (cdrom_data.status & 512)
    cprintf ("Supports Red Book & HSG addressing");
  else cprintf ("Supports HSG addressing mode      ");
}


void show_mode (void)
{
  gotoxy (60, 11);
  if (playmode == 0)
    printf ("Mode: DISC   ");
  else if(playmode == 1)
    printf ("Mode: TRACK  ");
  else printf ("Mode: SHUFFLE");
}


void nodisk (void)
{
  textmode (3);
  textbackground (BLACK);
  clrscr ();
  printf ("Drive Error, no disk found.\n\nProgram halted.\n");
  exit (0);
}


void newdisk (void)
{
  short error_ctr;

  textcolor (LIGHTGRAY);
  textbackground (BLACK);
  clrscr ();
  mark[0] = 0;
  curmark = 1;
  playmode = PLAY_DISK;
  textcolor (WHITE);
  for (ctr = 1; ctr < 10; ctr++)
  {
    gotoxy (1, ctr);
    textbackground (RED);
    cprintf ("%39c", 32);
    gotoxy (40, ctr);
    textbackground (BLUE);
    cprintf ("%40c", 32);
  }
  error_ctr = 0;
  gotoxy (54, 9);
  textcolor (WHITE + BLINK);
  cprintf ("WORKING.....");
  do {
    cd_get_audio_info ();
    error_ctr++;
  } while ((cdrom_data.error == 0x8102) && (error_ctr < 500));
  textcolor (LIGHTGRAY);
  gotoxy (54, 9);
  cprintf ("            ");
  if (error_ctr == 500)
    nodisk ();
  if (cdrom_data.high_audio > 30)
    cdrom_data.high_audio = 35;
  for (ctr = cdrom_data.low_audio; ctr <= cdrom_data.high_audio; ctr++)
  {
    gotoxy (1, ctr+9);
    textbackground (MAGENTA);
    textcolor (YELLOW);
    cprintf ("%39c", 32);
  }
  gotoxy (1,1);
  textcolor (WHITE);
  textbackground (RED);
  cprintf ("Barry's CD AUDIO player");
  printf ("\n");
  cprintf ("Copyright 1994");
  printf ("\n\n");
  cprintf ("Number of drives: %i", cdrom_data.drives);
  printf ("\n");
  cprintf ("First drive     : %c", cdrom_data.first_drive+65);
  printf ("\n\n");

//  if (playing == FALSE)
//  {
//    cd_getupc ();
//    cprintf ("Disk UPC Code   : Loaded");
//  }
  printf ("\n\n");
  cprintf ("TRACK    LENGTH    TYPE");

  textbackground (MAGENTA);
  textcolor (YELLOW);
  for (ctr = cdrom_data.low_audio; ctr <= cdrom_data.high_audio; ctr++)
  {
    gotoxy (1, ctr+9);
    cd_track_length (ctr, &minutes, &seconds, &frames);
    cprintf ("%2d.      %02i:%02i", ctr, minutes, seconds);
    cd_set_track (ctr);
    if (cdrom_data.track_type == DATA_TRACK)
      cprintf ("     Data");
    else cprintf ("     Audio");
  }
  printf ("\nDisk length:   %02d:%02d\n\n", cdrom_data.disk_length_min, cdrom_data.disk_length_sec);
  screeny = wherey ();

  if (playing == TRUE)
  {
    gotoxy (1, screeny);
    printf ("Disk play time :");
  }
  cd_get_volume (&my_vol);
  gotoxy (45, 11);
  printf ("Volume: %3i", my_vol.volume0);
  show_mode ();
  show_status ();
  gotoxy (45, 13);
  printf ("Q         Quit");
  gotoxy (45, 15);
  printf ("P         Play");
  gotoxy (45, 16);
  printf ("P         Pause/Resume");
  gotoxy (45, 17);
  printf ("SPACE     Stop Song");
  gotoxy (45, 18);
  printf ("K         Karaoke Mark");
  gotoxy (45, 20);
  printf ("V         Full Volume");
  gotoxy (45, 21);
  printf ("M         Mute");
  gotoxy (45, 22);
  printf ("+         Increase Volume");
  gotoxy (45, 23);
  printf ("-         Decrease Volume");
  gotoxy (45, 25);
  printf ("E         Eject Tray");
  gotoxy (45, 26);
  printf ("C         Close Tray");
  gotoxy (45, 27);
  printf ("L         Lock Door");
  gotoxy (45, 28);
  printf ("U         Unlock Door");
  gotoxy (45, 30);
  printf ("D         Disk mode");
}


short play_song (void)
{
  short temp;
  unsigned long startpos, endpos;

  curcheck = 1;
  if (playmode != PLAY_SHUFFLE)
  {
    gotoxy (1, 49);
    printf ("Enter track to play: ");
    scanf ("%i", &ctr);
    gotoxy (1, 49);
    printf ("                                            ");
    if ((ctr < cdrom_data.low_audio) || (ctr > cdrom_data.high_audio))
      return 0;
    cd_set_track (ctr);
  }
  else cd_set_track ((rand () % cdrom_data.high_audio) + 1);

  if (cdrom_data.track_type == DATA_TRACK)
    return 0;
  startpos = cdrom_data.track_position;
  if (playmode == PLAY_DISK)
    endpos = cdrom_data.endofdisk;
  else {
    temp = cdrom_data.current_track;
    if ((temp+1) > cdrom_data.high_audio)
      endpos = cdrom_data.endofdisk;
    else {
      cd_set_track (temp+1);
      endpos = cdrom_data.track_position;
      cd_set_track (temp);
    }
  }

  cd_lock (LOCK);
  cd_seek (cdrom_data.track_position);
  delay (400);
  cd_play_audio (startpos, endpos);
  gotoxy (26, 9+cdrom_data.current_track);
  textbackground (MAGENTA);
  textcolor (YELLOW + BLINK);
  cprintf ("PLAYING");
  gotoxy (1, screeny);
  printf ("Disk play time :");
  screeny = wherey ();
  while (cd_done_play ());
  playing = TRUE;
  return 1;
}


void pause_song (void)
{
  if (paused == FALSE)
  {
    cd_stop_audio ();
    paused = TRUE;
    gotoxy (26, 9+cdrom_data.current_track);
    textcolor (YELLOW + BLINK);
    printf ("PAUSED ");
  }
  else {
    cd_resume_audio ();
    paused = FALSE;
    gotoxy (26, 9+cdrom_data.current_track);
    textcolor (YELLOW + BLINK);
    printf ("PLAYING");
  }
}


void main (void)
{
  short error_ctr;
  char tempstr[8];

  if (!cdrom_installed ())
  {
    printf ("No CD-ROM drive found.\n");
    exit (0);
  }

  if (cd_done_play ())
    playing = FALSE;
  else playing = TRUE;
  paused = FALSE;
  done = FALSE;
  my_vol.input0 = 0;
  my_vol.input1 = 1;
  my_vol.input2 = 2;
  my_vol.input3 = 3;

  textmode (C4350);
  newdisk ();
  while (done == FALSE)
  {
    cd_status ();
    if (oldstatus != cdrom_data.status)
    {
      show_status ();
      if ((cdrom_data.status & 1) == 0)
      {
	/* Preserve previous DISK ID */
	disklen = cdrom_data.endofdisk;
	/* Get the new one */
	error_ctr = 0;
	gotoxy (54, 9);
	textcolor (WHITE + BLINK);
	cprintf ("WORKING.....");
	do {
	  cd_get_audio_info ();
	  error_ctr++;
	} while ((cdrom_data.error == 0x8102) && (error_ctr < 2500));
	textcolor (LIGHTGRAY);
	gotoxy (54, 9);
	cprintf ("            ");
	if (error_ctr == 2500)
	  nodisk ();
	/* See if disk was changed */
	if (disklen != cdrom_data.endofdisk)
	  newdisk ();
      }
    }
    if (kbhit ())
    {
    ch = toupper (getch ());
    switch (ch) {
      case 'Q' : done = TRUE;
		 break;
      case 'P' : if (playing == TRUE)
		   pause_song ();
		 else play_song ();
		 break;
      case ' ' : cd_stop_audio ();
		 cd_lock (UNLOCK);
		 playing = FALSE;
		 gotoxy (26, 9+cdrom_data.current_track);
		 textbackground (MAGENTA);
		 textcolor (YELLOW);
		 cprintf ("              ");
		 gotoxy (1, screeny);
		 printf ("                              ");
		 gotoxy (1, screeny+1);
		 printf ("                                 ");
		 break;
      case 'E' : if (playing == FALSE)
		   cd_cmd (EJECT_TRAY);
		 break;
      case 'C' : if (playing == FALSE)
		 {
		   gotoxy (54, 9);
		   textcolor (WHITE + BLINK);
		   cprintf ("WORKING.....");
		   cd_cmd (CLOSE_TRAY);
		   /* Preserve previous DISK ID */
		   disklen = cdrom_data.endofdisk;
		   /* Get the new one */
		   error_ctr = 0;
		   do {
		     cd_get_audio_info ();
		     error_ctr++;
		   } while ((cdrom_data.error == 0x8102) && (error_ctr < 1000));
		   if (error_ctr == 1000)
		     nodisk ();
		   textcolor (LIGHTGRAY);
		   gotoxy (54, 9);
		   cprintf ("            ");
		   /* See if disk was changed */
		   if (cdrom_data.endofdisk != disklen)
		     newdisk ();
		 }
		 break;
      case 'K' : mark[curmark++] = cd_head_position ();
		 mark[0] = cdrom_data.current_track;
		 break;
      case 'V' : my_vol.volume0 = 255;
		 my_vol.volume1 = 255;
		 my_vol.volume2 = 255;
		 my_vol.volume3 = 255;
		 cd_set_volume (&my_vol);
		 gotoxy (45, 11);
		 printf ("Volume: %3i", my_vol.volume0);
		 break;
      case 'M' : my_vol.volume0 = 90;
		 my_vol.volume1 = 90;
		 my_vol.volume2 = 90;
		 my_vol.volume3 = 90;
		 cd_set_volume (&my_vol);
		 gotoxy (45, 11);
		 printf ("Volume: %3i", my_vol.volume0);
		 break;
      case '+' : cd_get_volume (&my_vol);
		 if (my_vol.volume0 < 255)
		   my_vol.volume0++;
		 if (my_vol.volume1 < 255)
		   my_vol.volume1++;
		 if (my_vol.volume2 < 255)
		   my_vol.volume2++;
		 if (my_vol.volume3 < 255)
		   my_vol.volume3++;
		 cd_set_volume (&my_vol);
		 gotoxy (45, 11);
		 printf ("Volume: %3i", my_vol.volume0);
		 break;
      case '-' : cd_get_volume (&my_vol);
		 if (my_vol.volume0 > 0)
		   my_vol.volume0--;
		 if (my_vol.volume1 > 0)
		   my_vol.volume1--;
		 if (my_vol.volume2 > 0)
		   my_vol.volume2--;
		 if (my_vol.volume3 > 0)
		   my_vol.volume3--;
		 cd_set_volume (&my_vol);
		 gotoxy (45, 11);
		 printf ("Volume: %3i", my_vol.volume0);
		 break;
      case 'D' : if (playing == FALSE)
		 {
		   playmode++;
		   if (playmode > PLAY_SHUFFLE)
		     playmode = PLAY_DISK;
		   show_mode ();
		 }
		 break;
      case 'L' : cd_lock (LOCK);
		 break;
      case 'U' : if (playing == FALSE)
		   cd_lock (UNLOCK);
		 break;
    }
    }
    if (playing == TRUE)
    {
      if ((paused == FALSE) && (cd_done_play ()))
      {
	playing = FALSE;
	cd_stop_audio ();
	cd_lock (UNLOCK);
	gotoxy (26, 9+cdrom_data.current_track);
	textbackground (MAGENTA);
	textcolor (YELLOW);
	cprintf ("              ");
	gotoxy (1, screeny);
	printf ("                                 ");
	gotoxy (1, screeny+1);
	printf ("                                 ");
	if (playmode == PLAY_SHUFFLE)
	  play_song ();
      }
      else {
	cd_getpos (&my_cd);
	sprintf ((char *)&tempstr, "%x", my_cd.track);
	my_cd.track = (unsigned char) atol ((char *)&tempstr);
	if ((my_cd.track != cdrom_data.current_track) &&
	    (my_cd.track <= cdrom_data.high_audio) &&
	    (my_cd.track >= cdrom_data.low_audio))
	{
	  textbackground (MAGENTA);
	  textcolor (YELLOW);
	  gotoxy (26, 9+cdrom_data.current_track);
	  cprintf ("              ");
	  textcolor (YELLOW + BLINK);
	  cdrom_data.current_track = my_cd.track;
	  gotoxy (26, 9+cdrom_data.current_track);
	  cprintf ("PLAYING");
	}
	textbackground (MAGENTA);
	textcolor (YELLOW);
	gotoxy (35, 9+cdrom_data.current_track);
	cprintf ("%02i:%02i", my_cd.min, my_cd.sec);
	gotoxy (19, screeny);
	printf ("%02i:%02i", my_cd.amin, my_cd.asec);
	if (mark[0] == cdrom_data.current_track)
	{
	  while ((mark[curcheck] <= cd_head_position ()) && (curcheck < curmark))
	  {
	    gotoxy (1, screeny+1);
	    printf ("Passed mark #%i", curcheck);
	    curcheck++;
	  }
	}
      }
    }
  }
  textmode (C80);
  clrscr ();
  if (playing == TRUE)
  {
    printf ("Stop audio (Y/N) ?   ");
    do {
      ch = toupper (getch ());
    } while ((ch != 'Y') && (ch != 'N'));
    if (ch == 'Y')
    {
      cd_stop_audio ();
      cd_lock (UNLOCK);
    }
  }
}