Subject: bin/13682: cdplay(1) does not support random playing mode.
To: None <gnats-bugs@gnats.netbsd.org>
From: None <svs@ropnet.ru>
List: netbsd-bugs
Date: 08/11/2001 07:43:16
>Number: 13682
>Category: bin
>Synopsis: cdplay(1) does not support random playing mode.
>Confidential: no
>Severity: non-critical
>Priority: medium
>Responsible: bin-bug-people
>State: open
>Class: change-request
>Submitter-Id: net
>Arrival-Date: Sat Aug 11 07:40:00 PDT 2001
>Closed-Date:
>Last-Modified:
>Originator: Sergey Svishchev
>Release: 1.5X
>Organization:
>Environment:
>Description:
cdplay(1) can only play single tracks, track ranges, but not tracks
chosen randomly.
Also, it does not report current index when playing a CD that has them.
>How-To-Repeat:
>Fix:
Index: cdplay.c
===================================================================
RCS file: /cvsroot/basesrc/usr.bin/cdplay/cdplay.c,v
retrieving revision 1.13
diff -u -r1.13 cdplay.c
--- cdplay.c 2001/07/01 05:04:26 1.13
+++ cdplay.c 2001/08/11 14:07:07
@@ -68,6 +68,7 @@
#include <err.h>
#include <errno.h>
#include <histedit.h>
+#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -99,6 +100,7 @@
#define CMD_STATUS 14
#define CMD_NEXT 15
#define CMD_PREV 16
+#define CMD_SHUFFLE 17
#define STATUS_AUDIO 0x1
#define STATUS_MEDIA 0x2
#define STATUS_VOLUME 0x4
@@ -114,17 +116,18 @@
{ CMD_HELP, "?", 1, 0 },
{ CMD_HELP, "help", 1, "" },
{ CMD_INFO, "info", 1, "" },
+{ CMD_NEXT, "next", 1, "" },
{ CMD_PAUSE, "pause", 2, "" },
{ CMD_PLAY, "play", 1, "min1:sec1[.fram1] [min2:sec2[.fram2]]" },
{ CMD_PLAY, "play", 1, "track1[.index1] [track2[.index2]]" },
{ CMD_PLAY, "play", 1, "tr1 m1:s1[.f1] [[tr2] [m2:s2[.f2]]]" },
{ CMD_PLAY, "play", 1, "[#block [len]]" },
{ CMD_PREV, "prev", 2, "" },
-{ CMD_NEXT, "next", 1, "" },
{ CMD_QUIT, "quit", 1, "" },
{ CMD_RESET, "reset", 4, "" },
{ CMD_RESUME, "resume", 1, "" },
{ CMD_SET, "set", 2, "msf | lba" },
+{ CMD_SHUFFLE, "shuffle", 2, "" },
{ CMD_STATUS, "status", 1, "[audio | media | volume]" },
{ CMD_STOP, "stop", 3, "" },
{ CMD_VOLUME, "volume", 1, "<l> <r> | left | right | mute | mono | stereo" },
@@ -136,6 +139,9 @@
const char *cdname;
int fd = -1;
int msf = 1;
+int shuffle = 0;
+int interactive = 1;
+struct itimerval itv_timer;
/* for histedit */
History *hist;
@@ -147,7 +153,7 @@
int play_msf __P((int, int, int, int, int, int));
int play_track __P((int, int, int, int));
int get_vol __P((int *, int *));
-int status __P((int *, int *, int *, int *));
+int status __P((int *, int *, int *, int *, int *));
int opencd __P((void));
int play __P((char *));
int skip __P((int));
@@ -163,6 +169,7 @@
void help __P((void));
void usage __P((void));
char *strstatus __P((int));
+void sig_timer __P((int, int, struct sigcontext *));
int main __P((int, char **));
void
@@ -209,7 +216,8 @@
int cmd, len;
char *line;
const char *elline;
- int scratch;
+ int scratch, rc;
+ struct sigaction sa_timer;
cdname = getenv("MUSIC_CD");
if (!cdname)
@@ -244,8 +252,10 @@
}
opencd();
+ srandom(time(NULL));
if (argc > 0) {
+ interactive = 0;
for (p = buf; argc-- > 0; ++argv) {
len = strlen(*argv);
@@ -273,6 +283,13 @@
el_set(elptr, EL_HIST, history, hist);
el_source(elptr, NULL);
+ sigemptyset(&sa_timer.sa_mask);
+ sa_timer.sa_handler = (void (*)(int)) sig_timer;
+ sa_timer.sa_flags = SA_RESTART;
+ rc = sigaction(SIGALRM, &sa_timer, NULL);
+ if (rc < 0)
+ perror("sigaction");
+
for (;;) {
line = NULL;
do {
@@ -316,11 +333,8 @@
case CMD_CLOSE:
if (fd >= 0) {
ioctl(fd, CDIOCALLOW);
- if ((rc = ioctl(fd, CDIOCCLOSE)) < 0)
- return (rc);
- close(fd);
- fd = -1;
- return (0);
+ ioctl(fd, CDIOCCLOSE);
+ return (-1); /* close(fd) will get called if run() returns -1 */
}
break;
}
@@ -355,6 +369,8 @@
case CMD_EJECT:
ioctl(fd, CDIOCALLOW);
+ if (shuffle)
+ run(CMD_SHUFFLE, NULL);
if ((rc = ioctl(fd, CDIOCEJECT)) < 0)
return (rc);
return (0);
@@ -378,6 +394,25 @@
case CMD_NEXT:
return (skip(1));
+ case CMD_SHUFFLE:
+ if (interactive == 0)
+ return (-1);
+ if (shuffle == 0) {
+ itv_timer.it_interval.tv_sec = itv_timer.it_value.tv_sec = 1;
+ itv_timer.it_interval.tv_usec = itv_timer.it_value.tv_usec = 0;
+ rc = setitimer(ITIMER_REAL, &itv_timer, NULL);
+ if (rc == 0) {
+ shuffle = 1;
+ skip (0);
+ }
+ } else {
+ itv_timer.it_interval.tv_sec = itv_timer.it_value.tv_sec = 0;
+ itv_timer.it_interval.tv_usec = itv_timer.it_value.tv_usec = 0;
+ rc = setitimer(ITIMER_REAL, &itv_timer, NULL);
+ shuffle = 0;
+ }
+ return (0);
+
case CMD_SET:
if (!strcasecmp(arg, "msf"))
msf = 1;
@@ -441,7 +476,7 @@
if (!arg || !*arg) {
/* Play the whole disc */
- return (play_track(h.starting_track, 1, h.ending_track, 1));
+ return (play_track(h.starting_track, 1, h.ending_track, 99));
}
if (strchr(arg, '#')) {
@@ -497,6 +532,11 @@
goto Play_Relative_Addresses;
tr2 = m2 = s2 = f2 = f1 = 0;
+ if (6 == sscanf(arg, "%d %d:%d %d %d:%d", &tr1, &m1, &s1,
+ &tr2, &m2, &s2))
+ goto Play_Relative_Addresses;
+
+ tr2 = m2 = s2 = f2 = f1 = 0;
if (6 == sscanf(arg, "%d %d:%d.%d %d:%d", &tr1, &m1, &s1, &f1,
&m2, &s2))
goto Play_Relative_Addresses;
@@ -688,25 +728,47 @@
return (0);
}
+void
+sig_timer (sig, code, scp)
+ int sig, code;
+ struct sigcontext *scp;
+{
+ sigset_t anymore;
+
+ sigpending(&anymore);
+ if (sigismember(&anymore, SIGALRM))
+ return;
+ setitimer(ITIMER_REAL, &itv_timer, NULL);
+ if (fd != -1)
+ skip (0);
+}
+
int
skip(dir)
int dir;
{
- char str[4];
- int rc, trk, m, s, f;
+ char str[8];
+ int rc, trk, idx, m, s, f;
struct ioc_toc_header h;
if ((rc = ioctl(fd, CDIOREADTOCHEADER, &h)) < 0) {
- printf("ioctl failed\n");
+ perror("skip: ioctl failed");
return (rc);
}
- if ((rc = status(&trk, &m, &s, &f)) < 0) {
+ if ((rc = status(&trk, &idx, &m, &s, &f)) < 0) {
printf("status failed\n");
return (rc);
}
- if (trk+dir > h.ending_track || trk+dir < h.starting_track)
- return (0);
- sprintf(str, "%d", trk+dir);
+ if (shuffle) {
+ if (dir == 0 && (rc == ASTS_PLAYING || rc == ASTS_PAUSED))
+ return 0;
+ dir = h.starting_track + random() % (h.ending_track - h.starting_track + 1);
+ snprintf(str, sizeof(str), "%d %d", dir, dir);
+ } else {
+ if (trk+dir > h.ending_track || trk+dir < h.starting_track)
+ return (0);
+ snprintf(str, sizeof(str), "%d", trk+dir);
+ }
return (play(str));
}
@@ -739,7 +801,7 @@
{
struct cd_sub_channel_info data;
struct ioc_read_subchannel ss;
- int rc, trk, m, s, f;
+ int rc, trk, idx, m, s, f;
struct ioc_vol v;
int what = 0;
char *p;
@@ -764,13 +826,15 @@
if (!what)
what = STATUS_AUDIO | STATUS_MEDIA | STATUS_VOLUME;
if (what & STATUS_AUDIO) {
- rc = status(&trk, &m, &s, &f);
+ rc = status(&trk, &idx, &m, &s, &f);
if (rc >= 0) {
printf("Audio status:\t%s\n", strstatus(rc));
printf("Current track:\t%d\n", trk);
+ printf("Current index:\t%d\n", idx);
printf("Position:\t%d:%02d.%02d\n", m, s, f);
} else
printf("Audio status:\tno info available\n");
+ printf("Shuffle play:\t%s\n", shuffle ? "on":"off");
}
if (what & STATUS_MEDIA) {
bzero(&ss, sizeof(ss));
@@ -920,6 +984,22 @@
}
int
+play_msf(start_m, start_s, start_f, end_m, end_s, end_f)
+ int start_m, start_s, start_f, end_m, end_s, end_f;
+{
+ struct ioc_play_msf a;
+
+ a.start_m = start_m;
+ a.start_s = start_s;
+ a.start_f = start_f;
+ a.end_m = end_m;
+ a.end_s = end_s;
+ a.end_f = end_f;
+
+ return (ioctl(fd, CDIOCPLAYMSF, (char *) &a));
+}
+
+int
setvol(left, right)
int left, right;
{
@@ -947,25 +1027,9 @@
return (ioctl(fd, CDIOREADTOCENTRYS, (char *)&t));
}
-int
-play_msf(start_m, start_s, start_f, end_m, end_s, end_f)
- int start_m, start_s, start_f, end_m, end_s, end_f;
-{
- struct ioc_play_msf a;
-
- a.start_m = start_m;
- a.start_s = start_s;
- a.start_f = start_f;
- a.end_m = end_m;
- a.end_s = end_s;
- a.end_f = end_f;
-
- return (ioctl(fd, CDIOCPLAYMSF, (char *) &a));
-}
-
int
-status(trk, min, sec, frame)
- int *trk, *min, *sec, *frame;
+status(trk, idx, min, sec, frame)
+ int *trk, *idx, *min, *sec, *frame;
{
struct ioc_read_subchannel s;
struct cd_sub_channel_info data;
@@ -981,6 +1045,7 @@
return -1;
*trk = s.data->what.position.track_number;
+ *idx = s.data->what.position.index_number;
if (msf) {
*min = s.data->what.position.reladdr.msf.minute;
*sec = s.data->what.position.reladdr.msf.second;
>Release-Note:
>Audit-Trail:
>Unformatted: