/* 
 * Module:	cdctrl.c
 * Purpose:     to control Linux CD-ROMs
 * Author:      Wade Hampton
 *
 * Copyright (C) 1997, 1998, Wade Hampton
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; version 2 dated June, 1991.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 * 
 */

#include <stdio.h> 
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>

#include "config.h"
#include "cdtool.h"
#include "commands.h"
#include "hardware.h"
#include "info.h"
#include "shuffle.h"
#include "util.h"

#define CD_DEVICE "/dev/cdrom"

/* CONSTANTS- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
static char svnid[] = "$Id: cdctrl.c 1533 2005-10-17 19:11:59Z max $";   

/* LOCAL DATA - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
char caLineIn[BUFSIZ];

/* PROTOTYPES - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
void print_userhelp(int iVersion);
void print_help(void);
void print_info(cdtool_t *cdtool, char *pszCmd);
int  cmd_parse (cdtool_t *cdtool, char *pszBuf, int iRead);

/************************************************************************/
/* Procedure:  print_userhelp
 * Purpose:    to print command and user help on commands
 * 
 * Inputs:     none
 * Outputs:    to stdout, to stderr
 * Returns:    none
 * Notes:  
 *   1.
 */
/************************************************************************/
void print_userhelp(int iVersion)
{
    printf ("cdctrl:\nCommand line CDROM control\nOptions:\n");
    printf ("  cdctrl -c device  -- output using CRLF\n");
    printf ("  cdctrl device     -- normal output\n");
    printf ("  cdctrl [-h|-?|-V] -- help/version\n");

    if (iVersion == TRUE) {
	printf ("  Version %s\n", svnid);
	printf ("  Built on %s %s\n", __DATE__, __TIME__);
    } else {
	printf ("Command-line control options are:\n");
	print_help ();
    }
}

/************************************************************************/
/* Procedure:  print_help
 * Purpose:    to print help on commands
 * 
 * Inputs:     none
 * Outputs:    to stdout, to stderr
 * Returns:    none
 * Notes:  
 *   1.
 */
/************************************************************************/
void print_help ()
{
    infomsg("1    play (start play at track 1)");
    infomsg("s    stop");
    infomsg("p    pause");
    infomsg("r    resume");
    infomsg("e    eject");
    infomsg("c    close");
    infomsg("i    info");
    infomsg("d    dir");
    infomsg("l    shuffle (1 track only)");
    infomsg("-    previous track");
    infomsg("+    next track");
    infomsg("N    play track N");
    infomsg("q    quit");
    infomsg("?    help");
    infomsg("info format:  \"CMD cmd-name cd-status track abs-time rel-time\"");
    infomsg("  cmd-name  := {play, stop, ... quit} from above list");
    infomsg("  cd-status := {invalid, play, paused, completed, error, no status}");
    infomsg("  track     := {1..99} CD track");
    infomsg("  abs-time  := HH:MM:SS elapsed since CD start");
    infomsg("  rel-time  := HH:MM:SS elapsed since track start");
    infomsg("Build: %s %s [%s]", __DATE__, __TIME__, svnid);
}

/************************************************************************/
/* Procedure:  print_info
 * Purpose:    to print info on status
 * 
 * Inputs:     command, device of CDROM
 * Outputs:    to stdout, to stderr
 * Returns:    none
 * Notes:  
 *   1.
 */
/************************************************************************/
void print_info(cdtool_t *cdtool, char *pszCmd)
{
    printf ("CMD %s ", pszCmd);
    do_info (cdtool, I_DISP_ALL); 
}

/************************************************************************/
/* Procedure:  cmd_parse
 * Purpose:    to parse user's commands
 * 
 * Inputs:     program name, file description for CDROM, buffer, 
 *             count, device of CDROM
 * Outputs:    to CDROM, to stdout, to stderr
 * Returns:    T/F, T when "done"
 * Notes:  
 *   1.
 */
/************************************************************************/
int cmd_parse (cdtool_t *cdtool, char *pszBuf, int iRead)
{
    int iDone = FALSE;
    int iTrk;
    char *pszCmd;

    pszCmd = "NULL";

    if ((pszBuf[0] >= '0') && (pszBuf[0] <= '9')) {
	iTrk = atoi (pszBuf);
	do_play(cdtool, iTrk, 0);
	pszCmd = "play";
    } else {

	/* handle commands.... */
	switch (pszBuf[0]) {
	    
	case 's':
	    do_stop(cdtool, 99);
	    pszCmd = "stop";
	    break;
	    
	case 'p':
	    do_pause(cdtool);
	    pszCmd = "pause";
	    break;
	  
	case 'r':
	    do_play(cdtool, 0, 0);
	    pszCmd = "resume";
	    break;
	  
	case 'e':
	    do_eject(cdtool);
	    sleep (3);
	    pszCmd = "eject";
	    break;

	case 'c':
	    do_close(cdtool);
	    sleep (3);
	    pszCmd = "close";
	    break;
	  
	case 'i':
        case 0x0d:
        case 0x0a:
	    pszCmd = "info";
	    break;
	    
	case 'd':
	    do_dir (cdtool, P_RAW, 0); 
	    pszCmd = "dir";
	    break;

	case '-':
	    do_skip(cdtool, SKIPBACK, 1);
	    pszCmd = "previous";
	    break;

	case '+':
	    do_skip(cdtool, SKIPFORWARD, 1);
	    pszCmd = "next";
	    break;

	case 'q':
	    iDone = TRUE;
	    pszCmd = "QUIT";
	    break;

	case 'l':
	    do_shuffle (cdtool, 99, 1, 1);
	    pszCmd = "shuffle";
	    break;

	case '?':
	    print_help();
	    pszCmd = "help";
	    break;


	default:
	    errormsg("ERROR invalid command %s", pszBuf);
	    pszCmd = "default";
	    break;
	}
    }

    print_info(cdtool, pszCmd);
    infomsg ("END");
    return (iDone);

}

/************************************************************************/
/* Procedure:  main
 * Purpose:    cdctrl's main 
 * 
 * Inputs:     command line args
 * Outputs:    to CDROM, to stdout, to stderr
 * Returns:    T/F, T when "done"
 * Notes:  
 *   1.
 */
/************************************************************************/
int main (int argc, char *argv[])
{
    cdtool_t cdtool;
    extern int optind, getopt();
    extern char *optarg;
    char *device = NULL;
    int opt=1;

    int iRead;
    int iDone = FALSE;

    setprogname("cdctrl");
    cdtool.device = NULL;
    cdtool_show_crlf = DOLF;
    cdtool_show_debug = FALSE;
    cdtool_show_verbose = FALSE;
    
    /* parse environment and command line args */
    while (argv[opt] != NULL && argv[opt][0] == '-') {
      switch (argv[opt][1]) {    
        case '0':
        case '1':
        case '2':
        case '3':
        case '4':
        case '5':
        case '6':
        case '7':
        case '8':
        case '9':
  	  device = strdup(CD_DEVICE "?");
  	  *(device + sizeof(CD_DEVICE)-1) = argv[opt][1] - '0';
          argv++; argc--;
  	  break;
  
        case 'd':
          if (argv[opt+1] == NULL) {
              errormsg("%P: -d needs an argument");
              exit(1);
          }
  	  device = argv[opt+1];
          argv += 2; argc -= 2;
  	  break;
        
        case 'D':
  	  cdtool_show_debug = TRUE;
          argv++; argc--;
          break;
	
        case 'v':
  	  cdtool_show_verbose = TRUE;
          argv++; argc--;
          break;

        case 'c':
          cdtool_show_crlf = DOCRLF;
          argv++; argc--;
          break;
	  
        case 'h':
        case 'V':
        case '?':
          print_userhelp(FALSE);
          exit(0);
        
        default:
          errormsg("%P: unknown option: %s", argv[opt]);
          exit(1);
      }
    }

    if (argc > 1)
        device = argv[opt];
    
    /* close stderr and redirect to stdout */
    close(2);
    dup2(1, 2);
    
    /* try to open the CD device(s) */
    if (cdtool_open(&cdtool, device) < 0)
	exit(1);
    
    infomsg("Opened %s as device %d", cdtool.device, cdtool.fd);

    /* process commands */
    while (iDone == FALSE) {
        if (update_hw(cdtool.hw, cdtool.fd) < 0) {
            errormsg("Error reading from hardware\n");
            break;
        }
        
        if (fgets(caLineIn, sizeof(caLineIn)-1, stdin) != NULL) {
            iRead = strlen(caLineIn);
            if (iRead > 0) {
                iDone = cmd_parse(&cdtool, caLineIn, iRead);
            }
        }
        fflush (stdout);
    }
    
    /* cleanup */
    close (cdtool.fd);
    infomsg("EXITING");
    return (TRUE);
}

/*
 * Revision History: (no longer updated)
 * 
 * Language/Compiler/O/S:   GCC 2.7.2, Linux 2.0.X
 * Date:        12/22/97
 *
 * [from RCS]
 *
 * $Log: cdctrl.c,v $
 * Revision 1.6  1998/07/15 13:49:58  wadeh
 * prior to Lin's changes
 *
 * Revision 1.5  1998/01/06 21:00:33  wadeh
 * Added DoCr, changes to fix cdeject crash.
 *
 * Revision 1.4  1997/12/30 22:59:31  wadeh
 * Added fflush to properly work with pipes...
 *
 * Revision 1.3  1997/12/24 15:39:10  wadeh
 * Minor bug fixes:
 * 1) Fixed cdctrl eject command causing a signal 11.
 * 2) Fixed Makefile debug option to not strip symbols, can now debug.
 * 3) Added command.h and more prototypes, more documentation.
 * 4) Fixed read_hw to always return buffer, even on error.
 * ,
 *
 * Revision 1.2  1997/12/23 22:52:51  wadeh
 * 2.1 beta 1 release
 *
 * Revision 1.1  1997/12/23 21:38:52  wadeh
 * Initial revision
 *
 *
 * Notes:
 * 1) 
 */
