*BSD News Article 40123


Return to BSD News archive

Path: sserve!newshost.anu.edu.au!munnari.oz.au!bruce.cs.monash.edu.au!harbinger.cc.monash.edu.au!msunews!uwm.edu!vixen.cso.uiuc.edu!howland.reston.ans.net!Germany.EU.net!news.dfn.de!zeus.rbi.informatik.uni-frankfurt.de!terra.wiwi.uni-frankfurt.de!news.th-darmstadt.de!zib-berlin.de!math.fu-berlin.de!fub!kwcom1.in-berlin.de!kwcom.in-berlin.de!matthaei
From: matthaei@kwcom.in-berlin.de (Olaf Matthaei)
Newsgroups: comp.os.386bsd.questions
Subject: Re: S: utree and cdplayer
Date: 28 Dec 1994 18:01:22 +0100
Organization: Public access FreeBSD system, 15711 Koenigs Wusterhausen, DE
Lines: 501
Message-ID: <3ds5l2$23v@kwcom.in-berlin.de>
References: <3dkg8l$j6h@kwcom.in-berlin.de>
NNTP-Posting-Host: kwcom.in-berlin.de
X-Newsreader: TIN [version 1.2 PL2]

Olaf Matthaei (matthaei@kwcom.in-berlin.de) wrote:
: Hi !

: Does anyone know, where I can find utree and cdplayer (not xcdplayer)
: packages for FreeBSD 2.0 ?

OK here is the source for the textbased cdplayer:

----------------------------------------------------------
/*
 *	(#)@ cdplayer.c
 *
 *	Stand Alone Non X CD Player module
 *
 *
 */

#include <stdio.h>
#include <sys/file.h>
#include <sys/cdio.h>
#include <sys/ioctl.h>

#define MITSUMI

#ifndef DEVICE
#ifdef MITSUMI
#define DEVICE "/dev/rmcd0a"
#else
#define DEVICE "/dev/rcd0a"
#endif
#endif

#define command(s) strncmp(cmd,s,strlen(s))==0

/* 
 * CD Player Shared Data (define the pointers here...  Use malloc() to
 * create the actual data areas.
 */
#define TOC_ENTRIES	64
static struct cd_toc_entry toc_buffer[TOC_ENTRIES];
static struct cd_sub_channel_info *s;

int cd_fd = -1;
int been_here = 0;
int standalone;


char cmd[132];

int	pause ();
int	resume ();
int	stop ();
int	eject ();
int	setvol (int, int, int, int);
int	read_toc_header ();
int	read_toc_entry (int);
int	play_msf (int, int, int, int, int, int);
int	play_track (int, int, struct ioc_toc_header *);
int	get_vol (int *, int *);
u_char	status ();
int	input ();
void	open_cd ();
void	usage();
void	disp_status(int);
void	disp_subchan();

u_char trk, hrs, min, sec,  frame;
u_char t_trk, t_hrs, t_min, t_sec, t_frame;

int start, end;
char toggle[20];
int debug_flag;
int m1, m2, s1, s2, f1, f2;
int l, r, lo, ro;

main (int argc, char **argv)
{
    int rc, i;
    int	min, sec;
    char volc[12];
    struct ioc_toc_header h;

    s =(struct cd_sub_channel_info *)malloc(sizeof(struct cd_sub_channel_info));
    standalone = isatty(0);
    while (been_here == 0 && input (argc, argv)) {
        open_cd ();
	for (i=0; i < strlen(cmd); cmd[i]=tolower(cmd[i]),i++); 
	if (command ("play")) {
	    sscanf (cmd+4, "%d %d", &start, &end);
	    read_toc_header (&h);
	    play_track (start, end, &h);
	} else if (command ("msfplay")) {
	    sscanf(cmd+7, "%d %d %d %d %d %d", &m1, &s1, &f1, &m2, &s2, &f2);
	    play_msf (m1, s1, f1, m2, s2, f2);
	} else if (command ("status")) {
	    disp_status(argc);
	} else if (command ("debug")) {
	    sscanf (cmd+5, "%3s", &toggle);
	    if (strcmp("on",toggle) == 0) {
		debug_flag = 1;
		(void)ioctl(cd_fd,CDIOCSETDEBUG);
	    }
	    if (strcmp("off",toggle) == 0) {
		debug_flag = 0;
		(void)ioctl(cd_fd,CDIOCCLRDEBUG);
	    }
	}
	else if (command ("pause"))
	    pause ();
	else if (command ("resume"))
	    resume ();
	else if (command ("stop")) {
	    stop ();
	} else if (command ("eject")) {
	    eject ();
	} else if (command ("vol")) {
	    sscanf (cmd+3, "%s", volc);
	    if (strcmp("mono",volc) == 0) {
		(void)ioctl(cd_fd,CDIOCSETMONO);
	    } else if (strcmp("stereo",volc) == 0) {
		(void)ioctl(cd_fd,CDIOCSETSTERIO);
	    } else if (strcmp("mute",volc) == 0) {
		(void)ioctl(cd_fd,CDIOCSETMUTE);
	    } else if (strcmp("left",volc) == 0) {
		(void)ioctl(cd_fd,CDIOCSETLEFT);
	    } else if (strcmp("right",volc) == 0) {
		(void)ioctl(cd_fd,CDIOCSETRIGHT);
	    } else {
		(void)ioctl(cd_fd,CDIOCSETSTERIO);
	    }
	} else if (command ("setvol")) {
	    sscanf (cmd+6, "%d %d %d %d", &l, &r, &lo, &ro);
	    setvol (l, r, lo, ro);
	} else if (command ("getvol")) {
	    struct ioc_vol volume;

	    for (i = 0; i < 4; i++) 
		volume.vol[i] = 0;
	    getvol(&volume);
	    printf ("%d %d %d %d\n", 
		volume.vol[0], volume.vol[2], 
		volume.vol[1], volume.vol[3]);
	} else if (command ("subchan")) {
	    disp_subchan();
	} else if (command ("status")) {
	    disp_status(argc);
	} else if (command ("tochdr")) {
	    read_toc_header (&h);
	    printf ("%d %d %d\n", h.len, h.starting_track, h.ending_track);
	} else if (command ("tocentry")) {
	    int i,n;
	    read_toc_header (&h);
	    n =  h.ending_track - h.starting_track + 1;
	    read_toc_entry(n);
	    printf("Track\tStart Time\tDuration\n");
	    for (i = 0; toc_buffer[i].track < 110 && i < h.ending_track; i++) {
		/*printf ("%3d\t%5d:%02d", toc_buffer[i].track, 
			toc_buffer[i].addr[1],
			toc_buffer[i].addr[2]);
		min = toc_buffer[i+1].addr[1] - toc_buffer[i].addr[1];
		sec = toc_buffer[i+1].addr[2] - toc_buffer[i].addr[2];
		if (sec < 0)*/ {
		    sec += 60;
		    min --;
		}
		if (min < 0) {
		    sec = 0; 
		    min = 0;
		}
		printf ("\t%5d:%02d",min,sec);
		if (debug_flag)
		    printf ("\t%d %d",toc_buffer[i].control, 
					toc_buffer[i].addr_type);
		putchar('\n');
		status();
	    }
	} else if (command("reset")) {
	    do_reset();
	} else if (command("help")) {
	    usage();
	} else if (command("quit")) {
	    break;
	} else if (command("exit"))
	    break;
	fflush (stdout);
	close (cd_fd);
	cd_fd = -1;
    }
    exit (0);
}

/* Display a help message */

void usage()
{
    printf("Text based CD Player\n");
    printf("    play b e : Play a CD.\n");
    printf("               where b is the starting track \n");
    printf("                 and e is the ending track.\n");
    printf("    msfplay bm bs bf em es ef \n");
    printf("             : Play a CD.\n");
    printf("    debug [on|off]\n");
    printf("             : Turn kernel debug output on or off.\n");
    printf("    pause    : Pause the current playing CD.\n");
    printf("    resume   : Resume playing a CD.\n");
    printf("    stop     : Stop the current CD.\n");
    printf("    tochdr   : Get CD Time and track numbers.\n");
    printf("    tocentry : Get Table of Contents for CD.\n");
    printf("    getvol   : Get the Volume Information.\n");
    printf("    setvol   : Set the Volume Information.\n");
    printf("    vol {mono, stereo, mute, left, right}\n");
    printf("             : Set Volume Control Functions.\n");
    printf("    eject    : Eject the current CD (if supported).\n");
    printf("    status   : Display the current CD status.\n");
    printf("    quit     : Get out of here (does not stop CD).\n");
}

/* Display the Volume Information */

void
disp_subchan()
{
    struct ioc_read_subchannel subchan;
    struct cd_sub_channel_info subdata;
    int i;

    subchan.data_format = CD_MEDIA_CATALOG;
    subchan.address_format = CD_MSF_FORMAT;
    subchan.data_len = sizeof(struct cd_sub_channel_info);
    subchan.data = &subdata;
    ioctl (cd_fd, CDIOCREADSUBCHANNEL, &subchan);
    printf("Valid Catalog: %s\n", (subdata.what.media_catalog.mc_valid) ? "Yes" : "No");
    printf("Data Format:   %d\n", subdata.what.media_catalog.data_format);
    printf("Track Numbers: %d\n", bcd2bin(subdata.what.media_catalog.mc_number[0]));
    for (i = 1; i < 15; i++)
        printf("               %d\n", bcd2bin(subdata.what.media_catalog.mc_number[i]));
    printf("Audio Status:  %d\n", subdata.header.audio_status);
}

/* Display a reasonable status output */

void
disp_status(argc)
{
    u_char rc;
    char stat_str[40];
     
	if (cd_fd <= 0) 
	    rc = -1;
	else
	    rc = status ();
	switch (rc) {
	case CD_AS_AUDIO_INVALID :
		strcpy(stat_str,"Audio invalid");
		break;
	case CD_AS_PLAY_IN_PROGRESS :
		strcpy(stat_str,"Playing.");
		break;
	case CD_AS_PLAY_PAUSED :
		strcpy(stat_str,"Paused.");
		break;
	case CD_AS_PLAY_COMPLETED :
		strcpy(stat_str,"Play complete.");
		break;
	case CD_AS_PLAY_ERROR :
		strcpy(stat_str,"Play error.");
		break;
	case CD_AS_NO_STATUS :
		strcpy(stat_str,"No status available.");
		break;
 	default :
		printf("rc = %d\n",rc);
		strcpy(stat_str,"rc error.");
		break;
	}

	printf ("%-40s\n", stat_str);
    	printf ("Track: %02d%50s\n", trk," ");
    	printf ("Current Time: %02d:%02d%40s\n",  min, sec, " ");
	/* This hack is because the 'total time' is the time at the
	   point of the CD we are at, including the dead time at the
	   beginning.  This is usually off by about 2 seconds, so we
	   will just assume that this is true until I change it later.
	 */
	if (t_sec < 2) {
	    t_sec += 58;
	    t_min--;
	} else {
	    t_sec -= 2;
    	}
	printf ("Total   Time: %02d:%02d%40s\n", t_min, t_sec, " ");
}

/*
 * play CD tracks <start> through <end>
 */
int
play_track (int start, int end, struct ioc_toc_header *h)
{

    struct ioc_play_track t;

    if (start < 1) {
	t.start_track = h->starting_track;
    } else {
	t.start_track = (u_char)start;
    }
    if (end < t.start_track) {
	t.end_track = h->ending_track;
    } else {
	t.end_track = (u_char)end;
    }
    t.start_index = (u_char)1;
    t.end_index  = (u_char)1;

    return ioctl (cd_fd, CDIOCPLAYTRACKS, &t);
}

int
pause ()
{
    return ioctl (cd_fd, CDIOCPAUSE);
}

int
resume ()
{
    return ioctl (cd_fd, CDIOCRESUME);
}

int
stop ()
{
    return ioctl (cd_fd, CDIOCSTOP);
}

int
eject ()
{
    return ioctl (cd_fd, CDIOCEJECT);
}

int
do_reset ()
{
    return ioctl (cd_fd, CDIOCRESET);
}

int
setvol (int l, int r, int lo, int ro)
{
    struct ioc_vol v;

    v.vol[0] = l;
    v.vol[1] = r;
    v.vol[2] = lo;
    v.vol[3] = ro;
    return ioctl (cd_fd, CDIOCSETVOL, &v);
}

int
getvol (struct ioc_vol *v) 
{
    return ioctl (cd_fd, CDIOCGETVOL, v);
}

int
read_toc_header (struct ioc_toc_header *h)
{
    struct ioc_toc_header toc_head;
    int	ioctl_ret;

    ioctl_ret = ioctl (cd_fd, CDIOREADTOCHEADER, &toc_head);
    h->len = toc_head.len;
    h->starting_track = toc_head.starting_track;
    h->ending_track = toc_head.ending_track;
    return ioctl_ret;
}

int
read_toc_entry (int n)
{
    struct ioc_read_toc_entry toc;

    if (n > TOC_ENTRIES) 
	n = TOC_ENTRIES;
    toc.address_format = CD_MSF_FORMAT;
    toc.starting_track = 1;
    toc.data_len = sizeof(struct cd_toc_entry)*n;
    toc.data = toc_buffer;
    return ioctl (cd_fd, CDIOREADTOCENTRYS, &toc);

}

int
play_msf (int start_m, int start_s, int start_f, 
	  int end_m, int end_s, int end_f)
{

    struct ioc_play_msf a;

    a.start_m = start_m;
    a.start_s = start_s;
    a.start_f = start_f;
    a.end_m = end_m;
    a.end_s = end_s;
    a.end_f = end_f;
    return ioctl (cd_fd, CDIOCPLAYMSF, &a);
}

u_char
status ()
{
/* Set up ioc_read_subchannel structure */
    struct ioc_read_subchannel pos;
    struct cd_sub_channel_info subchan;

    pos.address_format = CD_MSF_FORMAT;
    pos.data_format = CD_CURRENT_POSITION;
    pos.track = 0;
    pos.data_len = sizeof(struct cd_sub_channel_info);
    pos.data = &subchan;

    if (ioctl (cd_fd, CDIOCREADSUBCHANNEL, &pos) < 0) 
	    return -1;
    *s = subchan;
    trk = pos.data->what.position.track_number;
    /*hrs = pos.data->what.position.reladdr[0];
    min = pos.data->what.position.reladdr[1];
    sec = pos.data->what.position.reladdr[2];
    t_hrs = pos.data->what.position.absaddr[0];
    t_min = pos.data->what.position.absaddr[1];
    t_sec = pos.data->what.position.absaddr[2];
    t_frame = pos.data->what.position.absaddr[3];
   */ return pos.data->header.audio_status;
}
    
int
input (int argc, char **argv)
{
    size_t len;
    int i;

    cmd[0] = '\0';
    if (argc > 1 && been_here == 0) {
	for (i = 1; i < argc; i++) {
	    strcat(cmd, argv[i]);
	    strcat(cmd," ");
	}
	been_here = -1;
    } else {
        if (standalone) {
	    fprintf(stderr, "CD>");
        }
        strncpy(cmd,fgetln(stdin, &len),131); 
    }
    return cmd[0] != '\0';
}

void
open_cd ()
{
    if (cd_fd > -1)
	return;
    cd_fd = open (DEVICE, O_RDONLY);
    if (cd_fd < 0) {
	perror("open");
	exit (1);
    }
}

int
bcd2bin(u_char x)
{
    return ((x & 0xf0 >> 4) * 10 + ( x & 0x0f));
}
------------------------------------------------------------

: --
: Mfg

: +----------------------------+-------------------------+--------------------+
: |      Olaf Matthaei         | root@kwcom.in-berlin.de |    FreeBSD 2.0     |
: |   Luckenwalderstrasse 38   +-------------------------+--------------------+
: | 15711 KOENIGSWUSTERHAUSEN  | Line 1: +49 3375 291894 ELSA 28800  V.34     |
: | KW-COMMUNICATION, Germany  | Line 2: +49 3375 292702 YORIKO 28.8 V.FC     |
: +----------------------------+----------------------------------------------+



--
Mfg

+----------------------------+-------------------------+--------------------+
|      Olaf Matthaei         | root@kwcom.in-berlin.de |    FreeBSD 2.0     |
|   Luckenwalderstrasse 38   +-------------------------+--------------------+
| 15711 KOENIGSWUSTERHAUSEN  | Line 1: +49 3375 291894 ELSA 28800  V.34     |
| KW-COMMUNICATION, Germany  | Line 2: +49 3375 292702 YORIKO 28.8 V.FC     |
+----------------------------+----------------------------------------------+