home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Datafile PD-CD 3
/
PDCD_3.iso
/
internet
/
freenet
/
WrkBone001
/
Linux
/
WBone
/
WorkBone-0.1
/
hardware.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-12-08
|
16KB
|
745 lines
#define load() /* nothing */
/*
* @(#)hardware.c 1.12 12/17/92
*
* Get information about a CD.
*/
#ifdef BOZO
static char *ident = "@(#)hardware.c 1.12 12/17/92";
#endif
void strmcpy (char **t, char *s);
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <sys/time.h>
# ifdef linux
# include <linux/cdrom.h>
# else
# include <sundev/srreg.h>
# endif /* linux */
#include "struct.h"
void *malloc();
char *strchr();
extern struct play *playlist;
extern struct cdinfo thiscd, *cd;
int cd_fd = -1;
/*
* The minimum volume setting for the Sun and DEC CD-ROMs is 128 but for other
* machines this might not be the case.
*/
int min_volume = 128;
int max_volume = 255;
# ifdef linux
char *cd_device = "/dev/cdrom\0";
# else
char *cd_device = "/dev/rsr0\0";
# endif
extern int cur_track, cur_index, cur_lasttrack, cur_firsttrack, cur_pos_abs,
cur_frame, cur_pos_rel, cur_tracklen, cur_cdlen, cur_ntracks,
cur_nsections, cur_cdmode, cur_listno, cur_stopmode, exit_on_eject,
cur_balance;
extern char *cur_artist, *cur_cdname, *cur_trackname;
extern char cur_contd, cur_avoid;
/*
* read_toc()
*
* Read the table of contents from the CD. Return a pointer to a cdinfo
* struct containing the relevant information (minus artist/cdname/etc.)
* This is a static struct. Returns NULL if there was an error.
*
* XXX allocates one trackinfo too many.
*/
struct cdinfo *
read_toc()
{
struct playlist *l;
struct cdrom_tochdr hdr;
struct cdrom_tocentry entry;
int i, pos;
if (cd_fd < 0)
return(NULL);
if (ioctl(cd_fd, CDROMREADTOCHDR, &hdr))
{
perror("readtochdr");
return (NULL);
}
thiscd.artist[0] = thiscd.cdname[0] = '\0';
thiscd.whichdb = thiscd.otherrc = thiscd.otherdb = NULL;
thiscd.length = 0;
thiscd.autoplay = thiscd.playmode = thiscd.volume = 0;
thiscd.ntracks = hdr.cdth_trk1;
if (thiscd.lists != NULL)
{
for (l = thiscd.lists; l->name != NULL; l++)
{
free(l->name);
free(l->list);
}
free(thiscd.lists);
thiscd.lists = NULL;
}
if (thiscd.trk != NULL)
free(thiscd.trk);
thiscd.trk = malloc((thiscd.ntracks + 1) * sizeof(struct trackinfo));
if (thiscd.trk == NULL)
{
perror("malloc");
return (NULL);
}
for (i = 0; i <= thiscd.ntracks; i++)
{
if (i == thiscd.ntracks)
entry.cdte_track = CDROM_LEADOUT;
else
entry.cdte_track = i + 1;
entry.cdte_format = CDROM_MSF;
if (ioctl(cd_fd, CDROMREADTOCENTRY, &entry))
{
perror("tocentry read");
return (NULL);
}
thiscd.trk[i].data =
thiscd.trk[i].avoid = entry.cdte_ctrl & CDROM_DATA_TRACK ?
1 : 0;
thiscd.trk[i].length = entry.cdte_addr.msf.minute * 60 +
entry.cdte_addr.msf.second;
thiscd.trk[i].start = thiscd.trk[i].length * 75 +
entry.cdte_addr.msf.frame;
thiscd.trk[i].songname = thiscd.trk[i].otherrc =
thiscd.trk[i].otherdb = NULL;
thiscd.trk[i].contd = 0;
thiscd.trk[i].volume = 0;
thiscd.trk[i].track = i + 1;
thiscd.trk[i].section = 0;
}
/* Now compute actual track lengths. */
pos = thiscd.trk[0].length;
for (i = 0; i < thiscd.ntracks; i++)
{
thiscd.trk[i].length = thiscd.trk[i+1].length - pos;
pos = thiscd.trk[i+1].length;
if (thiscd.trk[i].data)
thiscd.trk[i].length = (thiscd.trk[i + 1].start -
thiscd.trk[i].start) * 2;
if (thiscd.trk[i].avoid)
strmcpy(&thiscd.trk[i].songname, "DATA TRACK");
}
thiscd.length = thiscd.trk[thiscd.ntracks].length;
return (&thiscd);
}
/*
* cd_status()
*
* Return values:
*
* 0 No CD in drive.
* 1 CD in drive.
* 2 CD has just been inserted (TOC has been read)
* 3 CD has just been removed
*
* Updates cur_track, cur_pos_rel, cur_pos_abs and other variables.
*/
int
cd_status()
{
char realname[MAXPATHLEN];
static int warned = 0;
struct cdrom_subchnl sc;
int ret = 1;
if (cd_fd < 0)
{
if ((cd_fd = open(cd_device, 0)) < 0)
{
if (errno == EACCES)
{
if (!warned)
{
strcpy(realname, cd_device);
fprintf(stderr,
"As root, please run\n\nchmod 666 %s\n\n%s\n", realname,
"to give yourself permission to access the CD-ROM device.");
warned++;
}
}
else if (errno != ENXIO)
{
perror(cd_device);
if (thiscd.trk != NULL)
free(thiscd.trk);
exit(1);
}
return (0);
}
cur_cdmode = 5;
}
if (warned)
{
warned = 0;
fprintf(stderr, "Thank you.\n");
}
sc.cdsc_format = CDROM_MSF;
if (ioctl(cd_fd, CDROMSUBCHNL, &sc))
{
cur_cdmode = 5;
cur_track = -1;
cur_cdlen = cur_tracklen = 1;
cur_pos_abs = cur_pos_rel = cur_frame = 0;
if (exit_on_eject)
exit(0);
return (0);
}
if (cur_cdmode == 5) /* CD has been ejected */
{
cur_pos_rel = cur_pos_abs = cur_frame = 0;
if ((cd = read_toc()) == NULL)
{
close(cd_fd);
cd_fd = -1;
if (exit_on_eject)
exit(0);
else
return (0);
}
cur_nsections = 0;
cur_ntracks = cd->ntracks;
cur_cdlen = cd->length;
load();
cur_artist = cd->artist;
cur_cdname = cd->cdname;
cur_cdmode = 4;
ret = 2;
}
switch (sc.cdsc_audiostatus) {
case CDROM_AUDIO_PLAY:
cur_cdmode = 1;
dopos:
cur_pos_abs = sc.cdsc_absaddr.msf.minute * 60 +
sc.cdsc_absaddr.msf.second;
cur_frame = cur_pos_abs * 75 + sc.cdsc_absaddr.msf.frame;
/* Only look up the current track number if necessary. */
if (cur_track < 1 || cur_frame < cd->trk[cur_track-1].start ||
cur_frame >= (cur_track >= cur_ntracks ?
(cur_cdlen + 1) * 75 :
cd->trk[cur_track].start))
{
cur_track = 0;
while (cur_track < cur_ntracks && cur_frame >=
cd->trk[cur_track].start)
cur_track++;
}
if (cur_track >= 1 && sc.cdsc_trk > cd->trk[cur_track-1].track)
cur_track++;
cur_index = sc.cdsc_ind;
doall:
if (cur_track >= 1 && cur_track <= cur_ntracks)
{
cur_trackname = cd->trk[cur_track-1].songname;
cur_avoid = cd->trk[cur_track-1].avoid;
cur_contd = cd->trk[cur_track-1].contd;
cur_pos_rel = (cur_frame -
cd->trk[cur_track-1].start) / 75;
if (cur_pos_rel < 0)
cur_pos_rel = -cur_pos_rel;
}
/* note: workbone requires playlist == NULL always! */
if (playlist != NULL && playlist[0].start)
{
cur_pos_abs -= cd->trk[playlist[cur_listno-1].
start - 1].start / 75;
cur_pos_abs += playlist[cur_listno-1].starttime;
}
if (cur_pos_abs < 0)
cur_pos_abs = cur_frame = 0;
if (cur_track < 1)
cur_tracklen = cd->length;
else
cur_tracklen = cd->trk[cur_track-1].length;
break;
case CDROM_AUDIO_PAUSED:
if (cur_cdmode == 1 || cur_cdmode == 3)
{
cur_cdmode = 3;
goto dopos;
}
else
cur_cdmode = 4;
goto doall;
case CDROM_AUDIO_COMPLETED:
cur_cdmode = 0; /* waiting for next track. */
break;
case CDROM_AUDIO_NO_STATUS:
cur_cdmode = 4;
cur_lasttrack = cur_firsttrack = -1;
goto doall;
}
return (ret);
}
#ifdef BOZO
/*
* scale_volume(vol, max)
*
* Return a volume value suitable for passing to the CD-ROM drive. "vol"
* is a volume slider setting; "max" is the slider's maximum value.
*
* On Sun and DEC CD-ROM drives, the amount of sound coming out the jack
* increases much faster toward the top end of the volume scale than it
* does at the bottom. To make up for this, we make the volume scale look
* sort of logarithmic (actually an upside-down inverse square curve) so
* that the volume value passed to the drive changes less and less as you
* approach the maximum slider setting. The actual formula looks like
*
* (max^2 - (max - vol)^2) * (max_volume - min_volume)
* v = --------------------------------------------------- + min_volume
* max^2
*
* If your system's volume settings aren't broken in this way, something
* like the following should work:
*
* return ((vol * (max_volume - min_volume)) / max + min_volume);
*/
scale_volume(vol, max)
int vol, max;
{
return ((max * max - (max - vol) * (max - vol)) *
(max_volume - min_volume) / (max * max) + min_volume);
}
/*
* unscale_volume(cd_vol, max)
*
* Given a value between min_volume and max_volume, return the volume slider
* value needed to achieve that value.
*
* Rather