version 1.23, 2002/03/22 03:43:37 |
version 1.24, 2002/04/18 20:18:31 |
|
|
#include <sys/file.h> |
#include <sys/file.h> |
#include <sys/cdio.h> |
#include <sys/cdio.h> |
#include <sys/ioctl.h> |
#include <sys/ioctl.h> |
|
#include "extern.h" |
|
|
#define VERSION "2.0" |
|
|
|
#define ASTS_INVALID 0x00 /* Audio status byte not valid */ |
#define ASTS_INVALID 0x00 /* Audio status byte not valid */ |
#define ASTS_PLAYING 0x11 /* Audio play operation in progress */ |
#define ASTS_PLAYING 0x11 /* Audio play operation in progress */ |
|
|
#define CMD_NEXT 16 |
#define CMD_NEXT 16 |
#define CMD_PREV 17 |
#define CMD_PREV 17 |
#define CMD_REPLAY 18 |
#define CMD_REPLAY 18 |
|
#define CMD_CDDB 19 |
|
|
struct cmdtab { |
struct cmdtab { |
int command; |
int command; |
char *name; |
char *name; |
unsigned min; |
unsigned int min; |
char *args; |
char *args; |
} cmdtab[] = { |
} cmdtab[] = { |
{ CMD_CLOSE, "close", 1, "" }, |
{ CMD_CLOSE, "close", 1, "" }, |
|
|
{ CMD_STATUS, "status", 1, "" }, |
{ CMD_STATUS, "status", 1, "" }, |
{ CMD_STOP, "stop", 3, "" }, |
{ CMD_STOP, "stop", 3, "" }, |
{ CMD_VOLUME, "volume", 1, "<l> <r> | left | right | mute | mono | stereo" }, |
{ CMD_VOLUME, "volume", 1, "<l> <r> | left | right | mute | mono | stereo" }, |
{ 0, } |
{ CMD_CDDB, "cddbinfo", 2, "[n]" }, |
|
{ 0, 0, 0, 0} |
}; |
}; |
|
|
struct cd_toc_entry *toc_buffer; |
struct cd_toc_entry *toc_buffer; |
|
|
int fd = -1; |
int fd = -1; |
int verbose = 1; |
int verbose = 1; |
int msf = 1; |
int msf = 1; |
|
const char *cddb_host; |
|
char **track_names; |
|
|
extern char *__progname; |
extern char *__progname; |
|
|
|
|
int open_cd(char *); |
int open_cd(char *); |
int play(char *arg); |
int play(char *arg); |
int info(char *arg); |
int info(char *arg); |
|
int cddbinfo(char *arg); |
int pstatus(char *arg); |
int pstatus(char *arg); |
int play_next(char *arg); |
int play_next(char *arg); |
int play_prev(char *arg); |
int play_prev(char *arg); |
int play_same(char *arg); |
int play_same(char *arg); |
char *input(int *); |
char *input(int *); |
void prtrack(struct cd_toc_entry *e, int lastflag); |
void prtrack(struct cd_toc_entry *e, int lastflag, char *name); |
void lba2msf(unsigned long lba, u_char *m, u_char *s, u_char *f); |
void lba2msf(unsigned long lba, u_char *m, u_char *s, u_char *f); |
unsigned int msf2lba(u_char m, u_char s, u_char f); |
unsigned int msf2lba(u_char m, u_char s, u_char f); |
int play_blocks(int blk, int len); |
int play_blocks(int blk, int len); |
|
|
} |
} |
|
|
int |
int |
main(argc, argv) |
main(int argc, char **argv) |
int argc; |
|
char **argv; |
|
{ |
{ |
int cmd; |
int cmd; |
char *arg; |
char *arg; |
|
|
if (! cdname) |
if (! cdname) |
cdname = getenv("CDROM"); |
cdname = getenv("CDROM"); |
|
|
|
cddb_host = getenv("CDDB"); |
|
if (!cddb_host) |
|
cddb_host = "freedb.freedb.org"; |
|
|
for (;;) { |
for (;;) { |
switch (getopt(argc, argv, "svf:")) { |
switch (getopt(argc, argv, "svd:f:")) { |
case -1: |
case -1: |
break; |
break; |
case 's': |
case 's': |
|
|
case 'f': |
case 'f': |
cdname = optarg; |
cdname = optarg; |
continue; |
continue; |
|
case 'd': |
|
cddb_host = optarg; |
|
continue; |
default: |
default: |
usage(); |
usage(); |
} |
} |
|
|
} |
} |
|
|
int |
int |
run(cmd, arg) |
run(int cmd, char *arg) |
int cmd; |
|
char *arg; |
|
{ |
{ |
int l, r, rc; |
int l, r, rc; |
static char newcdname[MAXPATHLEN]; |
static char newcdname[MAXPATHLEN]; |
|
|
|
|
return info(arg); |
return info(arg); |
|
|
|
case CMD_CDDB: |
|
if (fd < 0 && ! open_cd(cdname)) |
|
return (0); |
|
|
|
return cddbinfo(arg); |
|
|
case CMD_STATUS: |
case CMD_STATUS: |
if (fd < 0 && ! open_cd(cdname)) |
if (fd < 0 && ! open_cd(cdname)) |
return (0); |
return (0); |
|
|
close(fd); |
close(fd); |
fd = -1; |
fd = -1; |
#endif |
#endif |
|
if (track_names) |
|
free_names(track_names); |
|
track_names = NULL; |
return (0); |
return (0); |
|
|
case CMD_CLOSE: |
case CMD_CLOSE: |
|
|
} |
} |
|
|
int |
int |
play(arg) |
play(char *arg) |
char *arg; |
|
{ |
{ |
struct ioc_toc_header h; |
struct ioc_toc_header h; |
int rc, n, start, end = 0, istart = 1, iend = 1; |
int rc, n, start, end = 0, istart = 1, iend = 1; |
|
|
* |
* |
* tr1 m1:s1[.f1] [[tr2] [m2:s2[.f2]]] |
* tr1 m1:s1[.f1] [[tr2] [m2:s2[.f2]]] |
*/ |
*/ |
unsigned tr1, tr2; |
int tr1, tr2; |
unsigned m1, m2, s1, s2, f1, f2; |
unsigned int m1, m2, s1, s2, f1, f2; |
unsigned char tm, ts, tf; |
unsigned char tm, ts, tf; |
|
|
tr2 = m2 = s2 = f2 = f1 = 0; |
tr2 = m2 = s2 = f2 = f1 = 0; |
|
|
goto Try_Absolute_Timed_Addresses; |
goto Try_Absolute_Timed_Addresses; |
|
|
Play_Relative_Addresses: |
Play_Relative_Addresses: |
if (! tr1) |
if (tr1 <= 0) |
tr1 = 1; |
tr1 = 1; |
else if (tr1 > n) |
else if (tr1 > n) |
tr1 = n; |
tr1 = n; |
|
|
|
|
m1 += tm; |
m1 += tm; |
|
|
if (! tr2) { |
if (tr2 <= 0) { |
if (m2 || s2 || f2) { |
if (m2 || s2 || f2) { |
tr2 = tr1; |
tr2 = tr1; |
f2 += f1; |
f2 += f1; |
|
|
} |
} |
|
|
int |
int |
play_prev(arg) |
play_prev(char *arg) |
char *arg; |
|
{ |
{ |
int trk, min, sec, frm, rc; |
int trk, min, sec, frm, rc; |
struct ioc_toc_header h; |
struct ioc_toc_header h; |
|
|
} |
} |
|
|
int |
int |
play_same(arg) |
play_same(char *arg) |
char *arg; |
|
{ |
{ |
int trk, min, sec, frm, rc; |
int trk, min, sec, frm, rc; |
struct ioc_toc_header h; |
struct ioc_toc_header h; |
|
|
} |
} |
|
|
int |
int |
play_next(arg) |
play_next(char *arg) |
char *arg; |
|
{ |
{ |
int trk, min, sec, frm, rc; |
int trk, min, sec, frm, rc; |
struct ioc_toc_header h; |
struct ioc_toc_header h; |
|
|
} |
} |
|
|
char * |
char * |
strstatus(sts) |
strstatus(int sts) |
int sts; |
|
{ |
{ |
switch (sts) { |
switch (sts) { |
case ASTS_INVALID: |
case ASTS_INVALID: |
|
|
} |
} |
|
|
int |
int |
pstatus(arg) |
pstatus(char *arg) |
char *arg; |
|
{ |
{ |
struct ioc_vol v; |
struct ioc_vol v; |
struct ioc_read_subchannel ss; |
struct ioc_read_subchannel ss; |
|
|
|
|
rc = status(&trk, &m, &s, &f); |
rc = status(&trk, &m, &s, &f); |
if (rc >= 0) { |
if (rc >= 0) { |
if (verbose) |
if (verbose) { |
printf("Audio status = %d<%s>, current track = %d, current position = %d:%02d.%02d\n", |
if (track_names) |
rc, strstatus(rc), trk, m, s, f); |
printf("Audio status = %d<%s>, " |
else |
"current track = %d (%s)\n" |
|
"\tcurrent position = %d:%02d.%02d\n", |
|
rc, strstatus(rc), trk, |
|
trk ? track_names[trk-1] : "", m, s, f); |
|
else |
|
printf("Audio status = %d<%s>, " |
|
"current track = %d, " |
|
"current position = %d:%02d.%02d\n", |
|
rc, strstatus(rc), trk, m, s, f); |
|
} else |
printf("%d %d %d:%02d.%02d\n", rc, trk, m, s, f); |
printf("%d %d %d:%02d.%02d\n", rc, trk, m, s, f); |
} else |
} else |
printf("No current status info available\n"); |
printf("No current status info available\n"); |
|
|
} |
} |
|
|
int |
int |
info(arg) |
info(char *arg) |
char *arg; |
|
{ |
{ |
struct ioc_toc_header h; |
struct ioc_toc_header h; |
int rc, i, n; |
int rc, i, n; |
|
|
|
|
for (i = 0; i < n; i++) { |
for (i = 0; i < n; i++) { |
printf("%5d ", toc_buffer[i].track); |
printf("%5d ", toc_buffer[i].track); |
prtrack(toc_buffer + i, 0); |
prtrack(toc_buffer + i, 0, NULL); |
} |
} |
printf("%5d ", toc_buffer[n].track); |
printf("%5d ", toc_buffer[n].track); |
prtrack(toc_buffer + n, 1); |
prtrack(toc_buffer + n, 1, NULL); |
return (0); |
return (0); |
} |
} |
|
|
|
int |
|
cddbinfo(char *arg) |
|
{ |
|
struct ioc_toc_header h; |
|
int rc, i, n; |
|
|
|
rc = ioctl(fd, CDIOREADTOCHEADER, &h); |
|
if (rc == -1) { |
|
warn("getting toc header"); |
|
return (rc); |
|
} |
|
|
|
n = h.ending_track - h.starting_track + 1; |
|
rc = read_toc_entrys((n + 1) * sizeof (struct cd_toc_entry)); |
|
if (rc < 0) |
|
return (rc); |
|
|
|
if (track_names) |
|
free_names(track_names); |
|
track_names = NULL; |
|
|
|
track_names = cddb(cddb_host, n, toc_buffer, arg); |
|
if (!track_names) |
|
return(0); |
|
|
|
printf("-------------------------------------------------\n"); |
|
|
|
for (i = 0; i < n; i++) { |
|
printf("%5d ", toc_buffer[i].track); |
|
prtrack(toc_buffer + i, 0, track_names[i]); |
|
} |
|
printf("%5d ", toc_buffer[n].track); |
|
prtrack(toc_buffer + n, 1, ""); |
|
return (0); |
|
} |
|
|
void |
void |
lba2msf(lba, m, s, f) |
lba2msf(unsigned long lba, u_char *m, u_char *s, u_char *f) |
unsigned long lba; |
|
u_char *m; |
|
u_char *s; |
|
u_char *f; |
|
{ |
{ |
lba += 150; /* block start offset */ |
lba += 150; /* block start offset */ |
lba &= 0xffffff; /* negative lbas use only 24 bits */ |
lba &= 0xffffff; /* negative lbas use only 24 bits */ |
|
|
return (((m * 60) + s) * 75 + f) - 150; |
return (((m * 60) + s) * 75 + f) - 150; |
} |
} |
|
|
|
unsigned long |
|
entry2time(struct cd_toc_entry *e) |
|
{ |
|
int block; |
|
u_char m, s, f; |
|
|
|
if (msf) { |
|
return (e->addr.msf.minute * 60 + e->addr.msf.second); |
|
} else { |
|
block = ntohl(e->addr.lba); |
|
lba2msf(block, &m, &s, &f); |
|
return (m*60+s); |
|
} |
|
} |
|
|
|
unsigned long |
|
entry2frames(struct cd_toc_entry *e) |
|
{ |
|
int block; |
|
unsigned char m, s, f; |
|
|
|
if (msf) { |
|
return e->addr.msf.frame + e->addr.msf.second * 75 + |
|
e->addr.msf.minute * 60 * 75; |
|
} else { |
|
block = ntohl(e->addr.lba); |
|
lba2msf(block, &m, &s, &f); |
|
return f + s * 75 + m * 60 * 75; |
|
} |
|
} |
|
|
void |
void |
prtrack(e, lastflag) |
prtrack(struct cd_toc_entry *e, int lastflag, char *name) |
struct cd_toc_entry *e; |
|
int lastflag; |
|
{ |
{ |
int block, next, len; |
int block, next, len; |
u_char m, s, f; |
u_char m, s, f; |
|
|
if (msf) { |
if (msf) { |
/* Print track start */ |
if (!name || lastflag) |
printf("%2d:%02d.%02d ", e->addr.msf.minute, |
/* Print track start */ |
e->addr.msf.second, e->addr.msf.frame); |
printf("%2d:%02d.%02d ", e->addr.msf.minute, |
|
e->addr.msf.second, e->addr.msf.frame); |
|
|
block = msf2lba(e->addr.msf.minute, e->addr.msf.second, |
block = msf2lba(e->addr.msf.minute, e->addr.msf.second, |
e->addr.msf.frame); |
e->addr.msf.frame); |
} else { |
} else { |
block = ntohl(e->addr.lba); |
block = ntohl(e->addr.lba); |
lba2msf(block, &m, &s, &f); |
if (!name || lastflag) { |
/* Print track start */ |
lba2msf(block, &m, &s, &f); |
printf("%2d:%02d.%02d ", m, s, f); |
/* Print track start */ |
|
printf("%2d:%02d.%02d ", m, s, f); |
|
} |
} |
} |
if (lastflag) { |
if (lastflag) { |
/* Last track -- print block */ |
if (!name) |
printf(" - %6d - -\n", block); |
/* Last track -- print block */ |
|
printf(" - %6d - -\n", block); |
|
else |
|
printf("\n"); |
return; |
return; |
} |
} |
|
|
|
|
len = next - block; |
len = next - block; |
lba2msf(len, &m, &s, &f); |
lba2msf(len, &m, &s, &f); |
|
|
|
if (name) |
|
printf("%2d:%02d.%02d %s\n", m, s, f, name); |
/* Print duration, block, length, type */ |
/* Print duration, block, length, type */ |
printf("%2d:%02d.%02d %6d %6d %5s\n", m, s, f, block, len, |
else |
(e->control & 4) ? "data" : "audio"); |
printf("%2d:%02d.%02d %6d %6d %5s\n", m, s, f, block, len, |
|
(e->control & 4) ? "data" : "audio"); |
} |
} |
|
|
int |
int |
play_track(tstart, istart, tend, iend) |
play_track(int tstart, int istart, int tend, int iend) |
int tstart; |
|
int istart; |
|
int tend; |
|
int iend; |
|
{ |
{ |
struct ioc_play_track t; |
struct ioc_play_track t; |
|
|
|
|
} |
} |
|
|
int |
int |
play_blocks(blk, len) |
play_blocks(int blk, int len) |
int blk; |
|
int len; |
|
{ |
{ |
struct ioc_play_blocks t; |
struct ioc_play_blocks t; |
|
|
|
|
} |
} |
|
|
int |
int |
setvol(left, right) |
setvol(int left, int right) |
int left; |
|
int right; |
|
{ |
{ |
struct ioc_vol v; |
struct ioc_vol v; |
|
|
|
|
} |
} |
|
|
int |
int |
read_toc_entrys(len) |
read_toc_entrys(int len) |
int len; |
|
{ |
{ |
struct ioc_read_toc_entry t; |
struct ioc_read_toc_entry t; |
|
|
|
|
} |
} |
|
|
int |
int |
play_msf(start_m, start_s, start_f, end_m, end_s, end_f) |
play_msf(int start_m, int start_s, int start_f, int end_m, int end_s, int end_f) |
int start_m; |
|
int start_s; |
|
int start_f; |
|
int end_m; |
|
int end_s; |
|
int end_f; |
|
{ |
{ |
struct ioc_play_msf a; |
struct ioc_play_msf a; |
|
|
|
|
} |
} |
|
|
int |
int |
status(trk, min, sec, frame) |
status(int *trk, int *min, int *sec, int *frame) |
int *trk; |
|
int *min; |
|
int *sec; |
|
int *frame; |
|
{ |
{ |
struct ioc_read_subchannel s; |
struct ioc_read_subchannel s; |
struct cd_sub_channel_info data; |
struct cd_sub_channel_info data; |
|
|
} |
} |
|
|
char * |
char * |
input(cmd) |
input(int *cmd) |
int *cmd; |
|
{ |
{ |
static char buf[80]; |
static char buf[80]; |
char *p; |
char *p; |
|
|
} |
} |
|
|
char * |
char * |
parse(buf, cmd) |
parse(char *buf, int *cmd) |
char *buf; |
|
int *cmd; |
|
{ |
{ |
struct cmdtab *c; |
struct cmdtab *c; |
char *p; |
char *p; |
|
|
} |
} |
|
|
int |
int |
open_cd(dev) |
open_cd(char *dev) |
char *dev; |
|
{ |
{ |
char *realdev; |
char *realdev; |
int tries; |
int tries; |