Subject: Re: audio CD players for NetBSD
To: Boudreault Benoit <boudreab@ERE.UMontreal.CA>
From: Scott Reynolds <scottr@edsi.org>
List: port-mac68k
Date: 01/27/1996 11:53:21
On Sat, 27 Jan 1996, Boudreault Benoit wrote:
> i was wondering if there is an audio CD player around that doesnt need Xwindows to run
> if it exists, anyway to point me in the right direction? :)
I've appended a little program I found somewhere -- not quite sure where,
someone might have given it to me :-) -- which works on my Mac + AppleCD
600e. Note: I haven't been particularly trusting of the CDIOC*
ioctl()'s, and I've had disk corruption that I can attribute only to using
the CD-ROM. Your mileage may vary, but if I were you I'd make sure I have
a backup of anything important.
Having said that, I've been using this recently quite a bit (in an
attempt to reproduce the problem) and it's not yet given me a problem
with my -current kernel.
--scott
#!/bin/sh
# This is a shell archive. Save it in a file, remove anything before
# this line, and then unpack it by entering "sh file". Note, it may
# create directories; files and directories will be owned by you and
# have default permissions.
#
# This archive contains:
#
# Makefile
# cdplay.c
#
echo x - Makefile
sed 's/^X//' >Makefile << 'END-of-Makefile'
XPROG= cdplay
X
X.include <bsd.prog.mk>
END-of-Makefile
echo x - cdplay.c
sed 's/^X//' >cdplay.c << 'END-of-cdplay.c'
X#include <stdio.h>
X#include <errno.h>
X#include <sys/file.h>
X#include <sys/cdio.h>
X#include <sys/ioctl.h>
X
X#define DEVICE "/dev/rcd0c"
X
X#define COMMAND(s) strncmp(cmd,s,strlen(s))==0
X
Xstruct cd_toc_entry toc_buffer[100];
X
Xint cd_fd = -1;
Xint standalone;
X
Xchar *cmd;
X
Xint pause (), resume (), stop (), eject (), setvol (int, int),
X read_toc_header (struct ioc_toc_header *), read_toc_entry (int),
X play_msf (int, int, int, int, int, int), play_track (int, int),
X get_vol (int *, int *), status (int *, int *, int *, int *);
Xvoid open_cd ();
Xint input ();
X
Xmain (int argc, char **argv)
X{
X int rc;
X
X standalone = isatty (0);
X while (input ()) {
X rc = 0;
X open_cd ();
X if (COMMAND ("play")) {
X int start, end;
X sscanf (cmd+4, "%d %d", &start, &end);
X rc = play_track (start, end);
X } else if (COMMAND ("help")) {
X printf("play, pause, resume, stop, eject, setvol, getvol, tochdr, msfplay, tocentry, status, quit\n");
X } else if (COMMAND ("pause"))
X rc = pause ();
X else if (COMMAND ("resume"))
X rc = resume ();
X else if (COMMAND ("stop"))
X rc = stop ();
X else if (COMMAND ("eject")) {
X rc = eject ();
X close (cd_fd);
X cd_fd = -1;
X } else if (COMMAND ("setvol")) {
X int l, r;
X sscanf (cmd+6, "%d %d", &l, &r);
X rc = setvol (l, r);
X } else if (COMMAND ("getvol")) {
X int r, l;
X rc = getvol (&l, &r);
X printf ("Volume: left %d, right %d\n", l, r);
X } else if (COMMAND ("tochdr")) {
X struct ioc_toc_header h;
X rc = read_toc_header (&h);
X printf ("%d %d %d\n", h.len, h.starting_track, h.ending_track);
X } else if (COMMAND ("msfplay")) {
X int m1, m2, s1, s2, f1, f2;
X sscanf(cmd+7, "%d%d%d%d%d%d", &m1, &s1, &f1, &m2, &s2, &f2);
X rc = play_msf (m1, s1, f1, m2, s2, f2);
X } else if (COMMAND ("tocentry")) {
X struct ioc_toc_header h;
X int i, n;
X rc = read_toc_header (&h);
X n = h.ending_track - h.starting_track + 1;
X rc = read_toc_entry ((n+2)*sizeof(struct cd_toc_entry));
X toc_buffer[n].track = 255;
X for (i = 0; i <= n; i++)
X#ifdef __NetBSD__
X printf ("Track %d: %d %d %d\n",
X toc_buffer[i].track,
X toc_buffer[i].addr[1],
X toc_buffer[i].addr[2],
X toc_buffer[i].addr[3]);
X#else
X printf ("%d %d %d %d\n",
X toc_buffer[i].track,
X toc_buffer[i].addr.msf.minute,
X toc_buffer[i].addr.msf.second,
X toc_buffer[i].addr.msf.frame);
X#endif
X } else if (COMMAND ("status")) {
X int trk, m, s, f;
X if (cd_fd < 0)
X rc = -1; /* assume ejected */
X else
X rc = status (&trk, &m, &s, &f);
X printf ("%d %02d %d %d %d\n", rc, trk, m, s, f);
X } else if (COMMAND("quit"))
X break;
X fflush (stdout);
X if (rc < 0 && standalone)
X perror("cdplayer");
X }
X exit (0);
X}
Xint
Xplay_track (int start, int end)
X{
X struct ioc_play_track t;
X
X t.start_track = start;
X t.start_index = 1;
X t.end_track = end;
X t.end_index = 1;
X return ioctl (cd_fd, CDIOCPLAYTRACKS, &t);
X}
Xint
Xpause ()
X{
X return ioctl (cd_fd, CDIOCPAUSE);
X}
Xint
Xresume ()
X{
X return (ioctl (cd_fd, CDIOCRESUME));
X}
Xint
Xstop ()
X{
X return ioctl (cd_fd, CDIOCSTOP);
X}
Xint
Xeject ()
X{
X int rc = ioctl (cd_fd, CDIOCALLOW);
X return rc ? rc : ioctl (cd_fd, CDIOCEJECT);
X}
Xint
Xsetvol (int l, int r)
X{
X struct ioc_vol v;
X
X v.vol[0] = l;
X v.vol[1] = r;
X v.vol[2] = 0;
X v.vol[3] = 0;
X return ioctl (cd_fd, CDIOCSETVOL, &v);
X}
Xint
Xgetvol (int *l, int *r)
X{
X struct ioc_vol v;
X if (ioctl (cd_fd, CDIOCGETVOL, &v) < 0)
X return -1;
X *l = v.vol[0];
X *r = v.vol[1];
X return 0;
X}
Xint
Xread_toc_header (struct ioc_toc_header *h)
X{
X return ioctl (cd_fd, CDIOREADTOCHEADER, (char *) h);
X}
Xint
Xread_toc_entry (int len)
X{
X struct ioc_read_toc_entry t;
X
X t.address_format = CD_MSF_FORMAT;
X t.starting_track = 0;
X t.data_len = len;
X t.data = toc_buffer;
X return ioctl (cd_fd, CDIOREADTOCENTRYS, (char *) &t);
X}
Xint
Xplay_msf (int start_m, int start_s, int start_f,
X int end_m, int end_s, int end_f)
X{
X struct ioc_play_msf a;
X
X a.start_m = start_m;
X a.start_s = start_s;
X a.start_f = start_f;
X a.end_m = end_m;
X a.end_s = end_s;
X a.end_f = end_f;
X return ioctl (cd_fd, CDIOCPLAYMSF, (char *) &a);
X}
Xint
Xstatus (int *trk, int *min, int *sec, int *frame)
X{
X struct ioc_read_subchannel s;
X struct cd_sub_channel_info data;
X bzero(&s, sizeof(s));
X s.data = &data;
X s.data_len = sizeof (data);
X s.address_format = CD_MSF_FORMAT;
X s.data_format = CD_CURRENT_POSITION;
X open_cd ();
X if (ioctl (cd_fd, CDIOCREADSUBCHANNEL, (char *) &s) < 0)
X return -1;
X *trk = s.data->what.position.track_number;
X#ifdef __NetBSD__
X *min = s.data->what.position.reladdr[1];
X *sec = s.data->what.position.reladdr[2];
X *frame = s.data->what.position.reladdr[3];
X#else
X *min = s.data->what.position.reladdr.msf.minute;
X *sec = s.data->what.position.reladdr.msf.second;
X *frame = s.data->what.position.reladdr.msf.frame;
X#endif
X return s.data->header.audio_status;
X}
X
Xint
Xinput ()
X{
X int len;
X
X if (standalone)
X fprintf (stderr, "CD>");
X#ifdef __NetBSD__
X cmd = fgetln (stdin, &len);
X#else
X cmd = fgetline (stdin, 0);
X#endif
X return cmd != 0;
X}
Xvoid
Xopen_cd ()
X{
X int trk, m, s, f;
X extern int errno;
X
X if (cd_fd > -1)
X return;
X cd_fd = open (DEVICE, O_RDONLY);
X if (cd_fd < 0) {
X if (errno == ENXIO)
X return; /* open says 'Device not configured if there is no cd in */
X perror("open");
X exit (1);
X }
X if (status (&trk, &m, &s, &f) < 0 ) {
X close (cd_fd);
X cd_fd = -1;
X }
X}
END-of-cdplay.c
exit