version 1.8, 2008/06/30 23:35:39 |
version 1.9, 2008/11/29 08:57:10 |
|
|
#include <sys/signal.h> |
#include <sys/signal.h> |
#include <sys/device.h> |
#include <sys/device.h> |
|
|
#include <sys/audioio.h> |
|
#include <sys/cdio.h> |
#include <sys/cdio.h> |
#include <sys/ioctl.h> |
#include <sys/ioctl.h> |
#include <sys/scsiio.h> |
#include <sys/scsiio.h> |
|
|
#include <err.h> |
#include <err.h> |
#include <errno.h> |
#include <errno.h> |
#include <fcntl.h> |
#include <fcntl.h> |
|
#include <sndio.h> |
#include <stdio.h> |
#include <stdio.h> |
#include <stdlib.h> |
#include <stdlib.h> |
#include <string.h> |
#include <string.h> |
|
|
|
|
struct track_info { |
struct track_info { |
int fd; /* descriptor of output file */ |
int fd; /* descriptor of output file */ |
|
struct sio_hdl *hdl; /* sndio handle */ |
|
struct sio_par par; /* sndio parameters */ |
u_int track; /* track number */ |
u_int track; /* track number */ |
char name[12]; /* output file name, i.e. trackXX.wav/trackXX.dat */ |
char name[12]; /* output file name, i.e. trackXX.wav/trackXX.dat */ |
u_char isaudio; /* true if audio track, otherwise it's data track */ |
u_char isaudio; /* true if audio track, otherwise it's data track */ |
|
|
u_int32_t end_lba; /* starting address of the next track */ |
u_int32_t end_lba; /* starting address of the next track */ |
}; |
}; |
|
|
int read_track(int, struct track_info *); |
int read_track(struct track_info *); |
|
|
int rip_next_track(struct track_info *); |
int rip_next_track(struct track_info *); |
int play_next_track(struct track_info *); |
int play_next_track(struct track_info *); |
|
|
} |
} |
|
|
int |
int |
read_track(int fd, struct track_info *ti) |
read_track(struct track_info *ti) |
{ |
{ |
struct timeval tv, otv, atv; |
struct timeval tv, otv, atv; |
u_int32_t i, blksize, n_sec; |
u_int32_t i, blksize, n_sec; |
|
|
|
|
error = read_data_sector(i + ti->start_lba, sec, blksize); |
error = read_data_sector(i + ti->start_lba, sec, blksize); |
if (error == 0) { |
if (error == 0) { |
if (write_sector(ti->fd, sec, blksize) != 0) { |
if (ti->fd >= 0 && |
|
(write_sector(ti->fd, sec, blksize) != 0)) { |
free(sec); |
free(sec); |
warnx("\nerror while writing to the %s file", |
warnx("\nerror while writing to the %s file", |
ti->name); |
ti->name); |
return (-1); |
return (-1); |
} |
} |
|
if (ti->hdl != NULL && |
|
(sio_write(ti->hdl, sec, blksize) == 0)) { |
|
sio_close(ti->hdl); |
|
ti->hdl = NULL; |
|
warnx("\nerror while writing to audio output"); |
|
return (-1); |
|
} |
|
|
i++; |
i++; |
} else if (error != EAGAIN) { |
} else if (error != EAGAIN) { |
|
|
int |
int |
play_next_track(struct track_info *info) |
play_next_track(struct track_info *info) |
{ |
{ |
int fd, error; |
char *dev; |
audio_info_t ai; |
|
|
|
if (!info->isaudio) |
if (!info->isaudio) |
return (NXTRACK_SKIP); |
return (NXTRACK_SKIP); |
|
|
info->fd = open("/dev/audio", O_CREAT | O_TRUNC | O_RDWR, |
if (info->hdl != NULL) |
S_IRUSR | S_IWUSR); |
return (NXTRACK_OK); |
if (info->fd == -1) { |
|
warnx("can't open /dev/audio"); |
dev = getenv("AUDIODEVICE"); |
return (NXTRACK_FAIL); |
|
|
info->hdl = sio_open(dev, SIO_PLAY, 0); |
|
if (info->hdl == NULL) { |
|
warnx("could not open audio backend"); |
|
goto bad; |
} |
} |
|
|
fd = open("/dev/audioctl", O_RDWR); |
sio_initpar(&info->par); |
if (fd != -1) { |
|
AUDIO_INITINFO(&ai); |
|
ai.play.sample_rate = 44100; |
|
ai.play.channels = 2; |
|
ai.play.precision = 16; |
|
ai.play.encoding = AUDIO_ENCODING_SLINEAR_LE; |
|
error = ioctl(fd, AUDIO_SETINFO, &ai); |
|
close(fd); |
|
} else |
|
error = -1; |
|
|
|
if (error == -1) { |
info->par.rate = 44100; |
warnx("can't configure audio device"); |
info->par.pchan = 2; |
close(info->fd); |
info->par.bits = 16; |
info->fd = -1; |
info->par.sig = 1; |
return (NXTRACK_FAIL); |
info->par.le = 1; |
|
info->par.bufsz = info->par.rate * 3 / 4; |
|
|
|
if (sio_setpar(info->hdl, &info->par) == 0) { |
|
warnx("could not set audio parameters"); |
|
goto bad; |
} |
} |
|
|
|
if (sio_getpar(info->hdl, &info->par) == 0) { |
|
warnx("could not get audio parameters"); |
|
goto bad; |
|
} |
|
|
|
if (info->par.le != 1 || |
|
info->par.sig != 1 || |
|
info->par.bits != 16 || |
|
info->par.pchan != 2 || |
|
(info->par.rate > 44100 * 1.05 || info->par.rate < 44100 * 0.95)) { |
|
warnx("could not configure audio parameters as desired"); |
|
goto bad; |
|
} |
|
|
|
if (sio_start(info->hdl) == 0) { |
|
warnx("could not start audio output"); |
|
goto bad; |
|
} |
|
|
return (NXTRACK_OK); |
return (NXTRACK_OK); |
|
|
|
bad: |
|
sio_close(info->hdl); |
|
info->hdl = NULL; |
|
return (NXTRACK_FAIL); |
} |
} |
|
|
static int |
static int |
|
|
char order; |
char order; |
int error; |
int error; |
|
|
|
info.fd = -1; |
|
info.hdl = NULL; |
|
|
order = (tp->start > tp->end) ? -1 : 1; |
order = (tp->start > tp->end) ? -1 : 1; |
trk = tp->start; |
trk = tp->start; |
for (;;) { |
for (;;) { |
|
|
error = -1; |
error = -1; |
break; |
break; |
} else if (error != NXTRACK_SKIP) { |
} else if (error != NXTRACK_SKIP) { |
error = read_track(fd, &info); |
error = read_track(&info); |
close(info.fd); |
if (info.fd >= 0) { |
|
close(info.fd); |
|
info.fd = -1; |
|
} |
if (error != 0) { |
if (error != 0) { |
warnx("can't rip %u track", |
warnx("can't rip %u track", |
toc_buffer[i].track); |
toc_buffer[i].track); |
|
|
if (trk == tp->end) |
if (trk == tp->end) |
break; |
break; |
trk += order; |
trk += order; |
|
} |
|
|
|
if (info.hdl != NULL) { |
|
sio_close(info.hdl); |
|
info.hdl = NULL; |
} |
} |
|
|
return (error); |
return (error); |