Subject: Re: is CDIOCPLAYTRACKS broken?
To: None <graphix@iastate.edu>
From: Michael Graff <explorer@flame.org>
List: current-users
Date: 12/01/1995 22:29:41
> The subject says it all. I can not seem to get CDIOCPLAYTRACKS to
>actually start playing an audio cd. CDIOCPLAYBLOCKS works fine though
>I have yet to find a way to determine the number of tracks on the disk.
Here's what I wrote some time ago:
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/cdio.h>
struct ioc_play_track ipt;
struct ioc_toc_header toc_header;
struct ioc_read_toc_entry toc_entry;
struct cd_toc_entry toc[130]; /* more than enough room I hope! */
typedef struct disk_info {
char *name;
u_int id;
u_char tracks;
} DiskInfo;
typedef struct msf {
u_char minute;
u_char second;
u_char frame;
} MSF;
int PlayTracks(int, int, int);
int GetPositionInfo(int, int *, MSF *, MSF *);
int GetMediaCatalog(int);
int SetVolume(int, float, float, float, float);
int OpenDevice(void);
int ReadTrackInfo(int, DiskInfo *);
int
main(int argc, char **argv)
{
int cd;
int i;
int lastsec;
MSF rel, abs;
int arg;
int track;
int last;
cd = OpenDevice();
ReadTrackInfo(cd, NULL);
GetMediaCatalog(cd);
SetVolume(cd, 0.80, 0.80, 0.0, 0.0);
arg = 0;
track = 0;
for (;;) {
if (argc == 1)
track++;
else {
if (++arg == argc)
exit(1);
track = atoi(argv[arg]);
}
if ((track < toc_header.starting_track)
|| (track > toc_header.ending_track))
fprintf(stderr, "\n\nInvalid track %d requested\n\n", track);
else
PlayTracks(cd, track, track);
for (;;) {
register int status;
int trk;
status = GetPositionInfo(cd, &trk, &rel, &abs);
if (status < 0)
exit(1);
if ((status == CD_AS_PLAY_COMPLETED) || (status == CD_AS_NO_STATUS)) {
printf("\nPlay completed.\n");
break;
}
if (last != (rel.minute * 60 + rel.second)) {
printf("\rTrack %02d Time %02d:%02d [%02d:%02d]",
trk, rel.minute, rel.second, abs.minute, abs.second);
fflush(stdout);
last = rel.minute * 60 + rel.second;
}
usleep(250000);
}
}
}
int
PlayTracks(int cd, int start, int end)
{
struct ioc_play_blocks ipb;
ipb.blk = (toc[start - 1].addr[0] << 24 | toc[start - 1].addr[1] << 16
| toc[start - 1].addr[2] << 8 | toc[start - 1].addr[3]);
ipb.len = (toc[end].addr[0] << 24 | toc[end].addr[1] << 16
| toc[end].addr[2] << 8 | toc[end].addr[3]) - ipb.blk;
if (ioctl(cd, CDIOCPLAYBLOCKS, &ipb) < 0) {
perror("ioctl CDIOCPLAYBLOCKS");
return errno;
}
return 0;
}
int
GetPositionInfo(int cd, int *track, MSF *rel, MSF *abs)
{
struct ioc_read_subchannel req;
struct cd_sub_channel_info sub_channel_info;
req.address_format = CD_MSF_FORMAT;
req.data_format = CD_CURRENT_POSITION;
req.track = 0;
req.data_len = sizeof(sub_channel_info);
req.data = &sub_channel_info;
if (ioctl(cd, CDIOCREADSUBCHANNEL, &req) < 0) {
perror("iocdl CDIOCREADSUBCHANNEL");
return errno;
}
if (track)
*track = sub_channel_info.what.position.track_number;
if (rel) {
rel->minute = sub_channel_info.what.position.reladdr[1];
rel->second = sub_channel_info.what.position.reladdr[2];
rel->frame = sub_channel_info.what.position.reladdr[3];
}
if (abs) {
abs->minute = sub_channel_info.what.position.absaddr[1];
abs->second = sub_channel_info.what.position.absaddr[2];
abs->frame = sub_channel_info.what.position.absaddr[3];
}
return(sub_channel_info.header.audio_status);
}
int
GetMediaCatalog(int cd)
{
int i;
struct ioc_read_subchannel req;
struct cd_sub_channel_info sub_channel_info;
req.address_format = CD_MSF_FORMAT;
req.data_format = CD_MEDIA_CATALOG;
req.track = 0;
req.data_len = sizeof(sub_channel_info);
req.data = &sub_channel_info;
if (ioctl(cd, CDIOCREADSUBCHANNEL, &req) < 0) {
perror("iocdl CDIOCREADSUBCHANNEL");
return errno;
}
for (i = 0 ; i < 15 ; i++)
fprintf(stderr, "%02x ", sub_channel_info.what.media_catalog.mc_number[i]);
fprintf(stderr, "\n");
return 0;
}
int
SetVolume(int cd, /* fd for cd device */
float right, /* right channel volume (percentage of full) */
float left, /* left channel volume */
float other1, /* those other channels */
float other2)
{
struct ioc_vol vol;
vol.vol[0] = 255 * right;
vol.vol[1] = 255 * left;
vol.vol[2] = 255 * other1;
vol.vol[3] = 255 * other2;
if (ioctl(cd, CDIOCSETVOL, &vol) < 0) {
perror("ioctl CDIOCSETVOL");
return errno;
}
return 0;
}
int
OpenDevice(void)
{
int cd;
cd = open("/dev/cd0a", O_RDONLY|O_NONBLOCK, 0x0600);
if (cd < 0) {
perror("open");
exit(1);
}
return (cd);
}
int
ReadTrackInfo(int cd, DiskInfo *di)
{
int i;
if (ioctl(cd, CDIOREADTOCHEADER, &toc_header) < 0) {
perror("ioctl CDIOREADTOCHEADER");
return errno;
}
fprintf(stderr, "Length: %d, start track: %d, ending track: %d\n",
toc_header.len, toc_header.starting_track, toc_header.ending_track);
for (i = 1 ; i <= toc_header.ending_track ; i += 30) {
toc_entry.data = &toc[i-1];
toc_entry.data_len = sizeof(toc[0]) * 30;
toc_entry.starting_track = i;
toc_entry.address_format = CD_LBA_FORMAT;
if (ioctl(cd, CDIOREADTOCENTRYS, &toc_entry) < 0) {
perror("ioctl CDIOREADTOCENTRYS");
return errno;
}
}
for (i = 0 ; i < toc_header.ending_track + 1 ; i++)
fprintf(stderr, "control %d, type %d, track %d, lba %d\n",
toc[i].control, toc[i].addr_type, toc[i].track,
toc[i].addr[0] << 24 | toc[i].addr[1] << 16
| toc[i].addr[2] << 8 | toc[i].addr[3]);
return 0;
}
--Michael
--
Michael Graff <explorer@flame.org> NetBSD is the way to go!
PGP key on a key-server near you! Rayshade the world!