/*++

File: cdlib.c

    Read the AsimCDFS CDDA library.

--*/


#include <stdio.h>


typedef int BOOL;
#define FALSE   0
#define TRUE    1

char *pcIdxF = "AsimCDFS_Buffer:CD_Library.index";
char *pcDatF = "AsimCDFS_Buffer:CD_Library.data";
FILE *fIdx, *fDat;



/*++

Function: Help()

    Print command line usage.

--*/

void Help()
    {
    fprintf( stderr, "CdLib: list the AsimCDFS audio disc library\n" );
    fprintf( stderr, "Usage:\n  CdLib [options] >listfile\n" );
    fprintf( stderr, "where options are\n" );
    fprintf( stderr, "  -d    list discs\n" );
    fprintf( stderr, "  -t    list tracks\n" );
    fprintf( stderr, "  -v/-V verbose track listing\n" );
    fprintf( stderr, "  -u    show user settings\n" );
    }



/*++

Function: DiscInfo()

    Print information about one CD in the database.

Arguments:

    nRecord - record number, zero-based

    nFlags - option bitmap: 1=discs, 2=tracks, 4=user settings

    nLevel - level of track listing verbosity: 1=add artist, 2=add album

Return Value:

    FALSE, if no such record exists.

--*/

BOOL DiscInfo( long lRecord, int nFlags, int nLevel )
    {
    long lOffset;
    int i;
    char caName[ 50 ], caTitle[ 50 ], caTrack[ 50 ];
    unsigned char cMode, cTrks, cMin, cSec, cFlags, cPos;

    if( fseek( fIdx, 4 * lRecord, SEEK_SET ) != 0 )
        return FALSE;
    if( fread( &lOffset, sizeof( long ), 1, fIdx ) < 1 )
        return FALSE;
    fseek( fDat, lOffset, SEEK_SET );
    fread( caName, sizeof( char ), 41, fDat );
    fread( caTitle, sizeof( char ), 34, fDat );
    cFlags = fgetc( fDat );
    cTrks = fgetc( fDat );
    cMin  = fgetc( fDat );
    cSec  = fgetc( fDat );
    fseek( fDat, 10, SEEK_CUR );
    cMode = fgetc( fDat );
    if( nFlags & 1 )
        {
        if( nFlags & 4 )
            {
            if( cFlags & 1 )
                printf( "A%c/%c%c ", " PRO"[ cMode ],
                        (cFlags & 2) ? 'S':'s', (cFlags & 4) ? 'R':'r' );
            else
                printf( "      " );
            }
        printf( "%2d:%02d ", cMin, cSec );
        printf( "%-30s %-30s ", caTitle, caName );
        printf( "%2d", cTrks );
        putchar( '\n' );
        }
    if( nFlags & 2 )
        {
        fseek( fDat, 34, SEEK_CUR );
        for( i = 0; i < cTrks; i++ )
            {
            fread( caTrack, sizeof( char ), 30, fDat );
            cMin  = fgetc( fDat );
            cSec  = fgetc( fDat );
            fseek( fDat, 5, SEEK_CUR );
            cPos   = fgetc( fDat );
            cFlags = fgetc( fDat );
            fseek( fDat, 15, SEEK_CUR );
            if( nFlags & 4 )
                {
                printf( ( cPos <= cTrks ) ? "%3d" : "   ", cPos );
                printf( " %c ", (cFlags & 1) ? 'x':' ' );
                }
            printf( "%2d:%02d ", cMin, cSec );
            printf( "%-30s ", caTrack );
            if( nLevel > 0 )
                printf( "%-30s %s", caName, (nLevel > 1) ? caTitle : "" );
            putchar( '\n' );
            }
        }

    return TRUE;
    }



/*++

Function: main()

    Uses unix style command line parsing, see Help() for explanation
    of the expected parameters.

--*/

int main( int argc, char *argv[] )
    {
    long lDiscs, lIdx;
    int nFlags = 0, nLevel = 0;

    while( --argc )
        {
        argv++;
        if( *argv[ 0 ] == '-' )
            switch( argv[ 0 ][ 1 ] )
                {
                case 'd':
                    nFlags |= 1;
                    break;
                case 't':
                    nFlags |= 2;
                    break;
                case 'u':
                    nFlags |= 4;
                    break;
                case 'v':
                    nLevel = 1;
                    break;
                case 'V':
                    nLevel = 2;
                    break;
                default:
                    Help();
                    return 5;
                }
        else
            {
            Help();
            return 5;
            }
        }

    fIdx = fopen( pcIdxF, "rb" );
    if( fIdx == NULL )
        {
        fprintf( stderr, "file not found: \"%s\"\n", pcIdxF );
        return 10;
        }
    fDat = fopen( pcDatF, "rb" );
    if( fDat == NULL )
        {
        fprintf( stderr, "file not found: \"%s\"\n", pcDatF );
        return 10;
        }
    fseek( fIdx, 0, SEEK_END );
    lDiscs = ftell( fIdx ) / 4;
    printf( "%ld audio CDs listed\n", lDiscs );
    if( nFlags > 0 )
        for( lIdx = 0; lIdx < lDiscs; lIdx++ )
            DiscInfo( lIdx, nFlags, nLevel );

    fclose( fIdx );
    fclose( fDat );

    return 0;
    }
