/* info.c 
 *
 * Copyright 1994 thomas insel 
 * Copyright 1995 sven oliver moll
 *
 * 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 <sys/types.h>
#include <errno.h>
#include <string.h>

#include "config.h"
#include "cdtool.h"
#include "database.h"
#include "hardware.h"
#include "info.h"
#include "util.h"

char caBuff[(BUFSIZ > (20 + 8*100)) ? BUFSIZ : (20 + 8*100)];


/************************************************************************/
/* Procedure:  tracks_line
 * Purpose:    to display a line of info on a CD-ROM track
 * 
 * Inputs:     hardware info
 * Outputs:    to temp string
 * Returns:    pointer to temp string
 * Notes:  
 *   1.
 */
/************************************************************************/
char *
tracks_line(cdhw_t *hw) 
{
    int i;
    char *tempstr;
    size_t len;
    
    len = 20 + 8 * (hw->tochdr.cdth_trk1 - hw->tochdr.cdth_trk0);
    if ((tempstr = malloc(len)) == NULL)
        return NULL;
  
    sprintf(tempstr, "tracks %u ", hw->tochdr.cdth_trk1);
    for (i=hw->tochdr.cdth_trk0; i<=hw->tochdr.cdth_trk1; i++)
	sprintf(tempstr + strlen(tempstr), "%u ",
		hw->tocentries[i-1].cdte_addr.msf.minute*4500 +
		hw->tocentries[i-1].cdte_addr.msf.second*75 +
		hw->tocentries[i-1].cdte_addr.msf.frame );
    sprintf(tempstr + strlen(tempstr), "%u", 
	    hw->tocentries[hw->tochdr.cdth_trk1].cdte_addr.msf.minute*60 +
	    hw->tocentries[hw->tochdr.cdth_trk1].cdte_addr.msf.second);
    
    return tempstr;
}

/************************************************************************/
/* Procedure:  do_info
 * Purpose:    to print info on a CD-ROM
 * 
 * Inputs:     name of program, cd file descriptior, info level, CR flag,
 *             device of CDROM
 * Outputs:    to stdout/stderr
 * Returns:    n/a
 * Notes:  
 *   1.
 */
/************************************************************************/
void do_info(cdtool_t *cdtool, int info)
{
    cdhw_t *hw = cdtool->hw;

    debugmsg("do_info:  called, info=%d, hw=%lx", info, (long)hw);
	
    if (!check_disc (hw)) {
        infomsg("%s", cd_status_text(hw->iStatus));
        return;
     }
                
    /* audio status */
    if ((info == I_AUDIOSTATUS) || (info == I_DISP_ALL)) {
        switch (hw->subchnl.cdsc_audiostatus) {
            case CDROM_AUDIO_INVALID:
                printf("invalid ");
                break;
            case CDROM_AUDIO_PLAY:
                printf("play ");
                break;
            case CDROM_AUDIO_PAUSED:
                printf("paused ");
                break;
            case CDROM_AUDIO_COMPLETED:
                printf("completed ");
                break;
            case CDROM_AUDIO_ERROR:
                printf("error ");
                break;
            case CDROM_AUDIO_NO_STATUS:
                printf("no-status ");
                break;
            default:
                printf("unknown%d ", hw->subchnl.cdsc_audiostatus);
                break;
        }
    } 

    /* track info */
    if ((info == I_TRACK) || (info == I_DISP_ALL)) {
        printf("%u ",((hw->subchnl.cdsc_audiostatus == CDROM_AUDIO_PLAY) ||
                    (hw->subchnl.cdsc_audiostatus == CDROM_AUDIO_PAUSED))
                ? hw->subchnl.cdsc_trk : 0);
    }
    /* absolute time, i.e., since CD start */
    if ((info == I_DISP_ABS) || (info == I_DISP_ALL)) {
        printf("%2u:%02u.%02u ",
                hw->subchnl.cdsc_absaddr.msf.minute,
                hw->subchnl.cdsc_absaddr.msf.second,
                hw->subchnl.cdsc_absaddr.msf.frame);
    }

    /* relative time, i.e., since track start */
    if ((info == I_DISP_REL) || (info == I_DISP_ALL)) {
        printf("%2u:%02u.%02u ",
                hw->subchnl.cdsc_reladdr.msf.minute,
                hw->subchnl.cdsc_reladdr.msf.second,
                hw->subchnl.cdsc_reladdr.msf.frame);
    }

    debugmsg("do_info:  finished");
}

/************************************************************************/
/* Procedure:  do_dir
 * Purpose:    to print the directory of a CD-ROM
 * 
 * Inputs:     prog name, format info, database, CR flag,
 *             device of CDROm
 * Outputs:    to stdout/stderr
 * Returns:    n/a
 * Notes:  
 *   1.
 */
/************************************************************************/
void do_dir(cdtool_t *cdtool, int p_format, int usedb) 
{
    cdhw_t *hw;
    char *tracks_buffer;
    cd_t *cd;
    int  i;  /* generic index variable */
    struct cdrom_msf *curmsf;
    struct cdrom_msf *prevmsf;
    struct cdrom_tocentry *tocentry;
    int delfrms; 

    hw = cdtool->hw;
    debugmsg("do_dir:  called, pfmt=%d, usedb=%d", p_format, usedb);

    if (!check_disc (hw)) {
        if (hw->iStatus != CD_STATUS_DATA_DISC) {
            errormsg("%P: %s", cd_status_text(hw->iStatus));
            return;
        }
    }

    tracks_buffer = tracks_line(hw);
    cd = read_db(tracks_buffer, usedb);

    /* print name & artist info */
    if (p_format == P_TEMPL) {
        infomsg("%s", tracks_buffer);
        infomsg("cdname %s", cd->cdname);
        infomsg("artist %s", cd->artist);
    }
        
    if (p_format == P_LONG || p_format == P_QUICK) {
        printf("%s", cd->artist);
        if (cd->cdname[0] && cd->artist[0])
            printf(" - ");
        printf("%s", cd->cdname);
        if (!cd->artist[0] && !cd->cdname[0])
            printf("unknown cd");
        if (p_format == P_LONG) {
            tocentry = &hw->tocentries[hw->tochdr.cdth_trk1];
            printf(" - %2u:%02u in %u tracks",
                    tocentry->cdte_addr.msf.minute,
                    tocentry->cdte_addr.msf.second,
                    hw->tochdr.cdth_trk1);
        }
        do_crlf(stdout);
    }

    /* print tracks */
    switch (p_format) {
        case P_RAW:
            printf("%2u-%2u",hw->tochdr.cdth_trk0, hw->tochdr.cdth_trk1);
            do_crlf(stdout);
            for (i = hw->tochdr.cdth_trk0; i <= hw->tochdr.cdth_trk1+1; i++) {
                tocentry = &hw->tocentries[i-1];
                printf("%2X %02u:%02u.%02u %c",
                    (i < hw->tochdr.cdth_trk1+1) ? ((i/10)*16+i%10) : 0xaa,
                    tocentry->cdte_addr.msf.minute,
                    tocentry->cdte_addr.msf.second,
                    tocentry->cdte_addr.msf.frame,
                   (tocentry->cdte_ctrl == CDROM_DATA_TRACK) ? 'D' : 'A');
                do_crlf(stdout);
            }
            break;

        case P_LONG:
            for (i = hw->tochdr.cdth_trk0; i <= hw->tochdr.cdth_trk1; i++) {
                prevmsf = (struct cdrom_msf *) 
                    &hw->tocentries[i-1].cdte_addr.msf;
                curmsf = (struct cdrom_msf *) 
                    &hw->tocentries[i].cdte_addr.msf;

                delfrms = (curmsf->cdmsf_min0 - prevmsf->cdmsf_min0) * 4500;
                delfrms += (curmsf->cdmsf_sec0 - prevmsf->cdmsf_sec0) * 75;
                delfrms += (curmsf->cdmsf_frame0 - prevmsf->cdmsf_frame0);

                printf(" %2u:%02u.%02u %2u ", delfrms / 4500,
                        (delfrms % 4500) / 75, delfrms % 75, i);

                if (hw->tocentries[i-1].cdte_ctrl == CDROM_DATA_TRACK)
                    printf("[DATA] ");

                if (i == hw->subchnl.cdsc_trk) {
                    if (hw->subchnl.cdsc_audiostatus == CDROM_AUDIO_PLAY)
                        printf("[PLAYING] ");
                    else if (hw->subchnl.cdsc_audiostatus == CDROM_AUDIO_PAUSED)
                        printf("[PAUSED] ");
                }

                if (usedb)
                    printf("%s",cd->track_names[i-1]);
                do_crlf(stdout);
            }
            break; /* P_LONG */

        case P_QUICK:
            switch (hw->subchnl.cdsc_audiostatus) {
                case CDROM_AUDIO_PLAY: 
                    printf(" - ");
                    if (cd->track_names[hw->subchnl.cdsc_trk-1][0])
                        printf("%s ", cd->track_names[hw->subchnl.cdsc_trk-1]);
                    printf("[%u]", hw->subchnl.cdsc_trk);
                    do_crlf(stdout);
                    break;
                case CDROM_AUDIO_PAUSED:
                    printf(" - paused on ");
                    if (cd->track_names[hw->subchnl.cdsc_trk-1][0])
                        printf("%s ", cd->track_names[hw->subchnl.cdsc_trk-1]);
                    printf("[%u]", hw->subchnl.cdsc_trk);
                    do_crlf(stdout);
                    break;
            }
            break; /* P_QUICK */

        case P_TEMPL:
            for (i = hw->tochdr.cdth_trk0; i<=hw->tochdr.cdth_trk1; i++) 
                infomsg("track %s", cd->track_names[i-1]);
            break;
    }

    free(tracks_buffer);
}
