Unix Technical Forum

Re: [PATCH] cdio's ``cdplay'' gets keyboard control

This is a discussion on Re: [PATCH] cdio's ``cdplay'' gets keyboard control within the mailing.openbsd.tech forums, part of the OpenBSD category; --> On 2007-07-11, Alexey Vatchenko <avv@mail.zp.ua> wrote: > I implemented keyboard control for cdplay command of cdio program. > Implemented ...


Go Back   Unix Technical Forum > Unix Operating Systems > OpenBSD > mailing.openbsd.tech

Register FAQ Members List Calendar Search Today's Posts Mark Forums Read
  #1 (permalink)  
Old 02-18-2008, 09:29 AM
Alexey Vatchenko
 
Posts: n/a
Default Re: [PATCH] cdio's ``cdplay'' gets keyboard control

On 2007-07-11, Alexey Vatchenko <avv@mail.zp.ua> wrote:
> I implemented keyboard control for cdplay command of cdio program.
> Implemented are pause, quit, next trace, rewind, forward.


Second revision of the patch (also attached):
http://www.bsdua.org/patches/cdio-cdplay-ctrl2.html

- man page suggestions by Jason McIntyre.
- forward/rewind time is changed to 10 seconds.

--
Alexey Vatchenko
http://www.bsdua.org
E-mail: avv@mail.zp.ua
JID: alex.vatchenko@gmail.com

Index: cdio.1
================================================== =================
RCS file: /cvs/openbsd/src/usr.bin/cdio/cdio.1,v
retrieving revision 1.44
diff -u -u -r1.44 cdio.1
--- cdio.1 31 May 2007 19:20:08 -0000 1.44
+++ cdio.1 16 Jul 2007 19:12:20 -0000
@@ -29,7 +29,7 @@
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
-.Dd $Mdocdate$
+.Dd $Mdocdate: May 31 2007 $
.Dt CDIO 1
.Os
.Sh NAME
@@ -110,6 +110,22 @@
If range is specified in descending order tracks will be played in descending order.
If the first value in the range is omitted, tracks from first track on disk to the specified one will be played.
If the last value in the range is omitted, tracks from the specified track to the last track on disk will be played.
+.Pp
+.Ic cdplay
+supports keyboard control:
+.Bl -tag -width "[space]XXX" -compact -offset indent
+.It Cm [space]
+Pause.
+.It Cm <
+Rewind 10 seconds.
+.It Cm >
+Forward 10 seconds.
+.It Cm n
+Jump to the next track.
+.It Cm q
+Exit from
+.Ic cdplay .
+.El
.It Ic close
Inject the disc.
.It Ic debug Ar on | off
Index: rip.c
================================================== =================
RCS file: /cvs/openbsd/src/usr.bin/cdio/rip.c,v
retrieving revision 1.5
diff -u -u -r1.5 rip.c
--- rip.c 29 May 2007 21:13:09 -0000 1.5
+++ rip.c 16 Jul 2007 19:12:21 -0000
@@ -35,6 +35,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <termios.h>
#include <unistd.h>

extern int fd;
@@ -91,22 +92,43 @@
u_int32_t end_lba; /* starting address of the next track */
};

-int read_track(int fd, struct track_info *ti);
+struct rip_func {
+ int (*next_track)(struct track_info *);
+ int (*next_sector)(void);
+};

-int rip_next_track(struct track_info *info);
-int play_next_track(struct track_info *info);
+static int read_track(int fd, struct track_info *ti,
+ struct rip_func *func);

-static int rip_tracks_loop(struct track_pair *tp, u_int n_tracks,
- int (*next_track)(struct track_info *));
+#define READTRK_OK 0
+#define READTRK_FAIL 1
+#define READTRK_EXIT 2
+#define READTRK_FORWARD 3
+#define READTRK_REWIND 4
+#define READTRK_NEXT 5
+
+static int rip_next_track(struct track_info *info);
+static int play_next_track(struct track_info *info);
+static int rip_next_sector(void);
+static int play_next_sector(void);

-int rip_tracks(char *arg, int (*next_track)(struct track_info *),
- int issorted);
+static int rip_tracks_loop(struct track_pair *tp, u_int n_tracks,
+ struct rip_func *func);
+static int rip_tracks(char *arg, struct rip_func *func, int issorted);

/* Next-Track function exit codes */
#define NXTRACK_OK 0
#define NXTRACK_FAIL 1
#define NXTRACK_SKIP 2

+/*
+ * CDplay Control
+ */
+static int ttyfd;
+static void enable_playctrl(void);
+
+#define SKIP_SEC_NUM 750 /* 10 seconds */
+
static int
_parse_val(char *start, char *nxt, int *val)
{
@@ -353,8 +375,15 @@
return (0);
}

+/*
+ * RETURN VALUES
+ * The function can return
+ * [READTRK_OK] Play next track
+ * [READTRK_FAIL] Error
+ * [READTRK_EXIT] Exit from CDplay
+ */
int
-read_track(int fd, struct track_info *ti)
+read_track(int fd, struct track_info *ti, struct rip_func *func)
{
u_int32_t i, blksize, n_sec;
u_char *sec;
@@ -364,36 +393,56 @@
blksize = (ti->isaudio) ? 2352 : 2048;
sec = (u_char *)malloc(blksize);
if (sec == NULL)
- return (-1);
+ return (READTRK_FAIL);

for (i = 0; i < n_sec; ) {
fprintf(stderr, "track %u '%c' %08u/%08u %3u%%\r", ti->track,
(ti->isaudio) ? 'a' : 'd', i, n_sec, 100 * i / n_sec);

+ error = func->next_sector();
+ switch (error) {
+ case READTRK_NEXT:
+ error = READTRK_OK;
+ /* FALLTHOUGH */
+ case READTRK_FAIL:
+ case READTRK_EXIT:
+ free(sec);
+ fprintf(stderr, "\n");
+ return (error);
+
+ case READTRK_FORWARD:
+ i = (i > n_sec) ? n_sec - 1 : i + SKIP_SEC_NUM;
+ break;
+
+ case READTRK_REWIND:
+ i = (i < SKIP_SEC_NUM) ? 0 : i - SKIP_SEC_NUM;
+ break;
+ }
+
error = read_data_sector(i + ti->start_lba, sec, blksize);
if (error == 0) {
if (write_sector(ti->fd, sec, blksize) != 0) {
free(sec);
warnx("\nerror while writing to the %s file",
ti->name);
- return (-1);
+ return (READTRK_FAIL);
}

i++;
} else if (error != EAGAIN) {
free(sec);
warnx("\nerror while reading from device");
- return (-1);
+ return (READTRK_FAIL);
}
}

free(sec);
fprintf(stderr, "track %u '%c' %08u/%08u 100%%\n", ti->track,
(ti->isaudio) ? 'a' : 'd', i, n_sec);
- return (0);
+ return (READTRK_OK);
}

-int
+static int
rip_next_track(struct track_info *info)
{
int error;
@@ -424,7 +473,7 @@
return (NXTRACK_OK);
}

-int
+static int
play_next_track(struct track_info *info)
{
int fd, error;
@@ -437,7 +486,7 @@
S_IRUSR | S_IWUSR);
if (info->fd == -1) {
warnx("can't open /dev/audio");
- return (NXTRACK_SKIP); /* just skip this track */
+ return (NXTRACK_FAIL);
}

fd = open("/dev/audioctl", O_RDWR);
@@ -463,8 +512,51 @@
}

static int
-rip_tracks_loop(struct track_pair *tp, u_int n_tracks,
- int (*next_track)(struct track_info *))
+rip_next_sector(void)
+{
+ return (READTRK_OK);
+}
+
+static int
+play_next_sector(void)
+{
+ struct timespec ts;
+ ssize_t sz;
+ char ch;
+ int forever;
+
+ ts.tv_sec = 0;
+ ts.tv_nsec = 10; /* release CPU for 10 nanosec */
+ forever = 0;
+ do {
+ sz = read(ttyfd, &ch, sizeof(ch));
+ if (sz > 0) {
+ if (ch == ' ')
+ forever = !forever;
+ else if (ch == '>')
+ return (READTRK_FORWARD);
+ else if (ch == '<')
+ return (READTRK_REWIND);
+ else if (ch == 'n')
+ return (READTRK_NEXT);
+ else if (ch == 'q')
+ return (READTRK_EXIT);
+ }
+
+ if (forever) {
+ /*
+ * Without sleep process consumes too much CPU time
+ * when paused.
+ */
+ nanosleep(&ts, NULL);
+ }
+ } while (forever);
+
+ return (READTRK_OK);
+}
+
+static int
+rip_tracks_loop(struct track_pair *tp, u_int n_tracks, struct rip_func *func)
{
struct track_info info;
u_char trk;
@@ -503,21 +595,20 @@
info.end_lba = toc_buffer[i + 1].addr.lba;
}

- error = next_track(&info);
- if (error == NXTRACK_SKIP)
- continue;
- else if (error == NXTRACK_FAIL) {
+ error = func->next_track(&info);
+ if (error == NXTRACK_FAIL) {
error = -1;
break;
- }
-
- error = read_track(fd, &info);
- close(info.fd);
-
- if (error != 0) {
- warnx("can't rip %u track",
- toc_buffer[i].track);
- break;
+ } else if (error != NXTRACK_SKIP) {
+ error = read_track(fd, &info, func);
+ close(info.fd);
+
+ if (error == READTRK_FAIL) {
+ warnx("can't rip %u track",
+ toc_buffer[i].track);
+ break;
+ } else if (error == READTRK_EXIT)
+ break;
}
}

@@ -529,8 +620,33 @@
return (error);
}

-int
-rip_tracks(char *arg, int (*next_track)(struct track_info *), int issorted)
+static void
+enable_playctrl(void)
+{
+ struct termios tp;
+
+ ttyfd = open("/dev/tty", O_RDONLY);
+ if (ttyfd == -1) {
+ warnx("can't open /dev/tty. Play control is disabled.");
+ return;
+ }
+
+ if (fcntl(ttyfd, F_SETFL, O_NONBLOCK) != -1) {
+ if (tcgetattr(ttyfd, &tp) != -1) {
+ tp.c_lflag &= ~(ICANON | ECHO);
+ tp.c_lflag |= ISIG;
+ if (tcsetattr(ttyfd, TCSANOW, &tp) != -1)
+ return;
+ }
+ }
+
+ close(ttyfd);
+ ttyfd = -1;
+ warnx("can't configure tty. Play control is disabled.");
+}
+
+static int
+rip_tracks(char *arg, struct rip_func *func, int issorted)
{
struct track_pair_head list;
struct track_pair *tp;
@@ -568,7 +684,7 @@
}

TAILQ_FOREACH(tp, &list, list) {
- rc = rip_tracks_loop(tp, n, next_track);
+ rc = rip_tracks_loop(tp, n, func);
if (rc < 0)
break;
}
@@ -580,11 +696,27 @@
int
cdrip(char *arg)
{
- return rip_tracks(arg, rip_next_track, 1);
+ struct rip_func func;
+
+ func.next_track = rip_next_track;
+ func.next_sector = rip_next_sector;
+ return rip_tracks(arg, &func, 1);
}

int
cdplay(char *arg)
{
- return rip_tracks(arg, play_next_track, 0);
+ struct rip_func func;
+ int rv;
+
+ func.next_track = play_next_track;
+ func.next_sector = play_next_sector;
+
+ enable_playctrl();
+ if (ttyfd == -1)
+ func.next_sector = rip_next_sector; /* it does nothing */
+ rv = rip_tracks(arg, &func, 0);
+ if (ttyfd != -1)
+ close(ttyfd);
+ return (rv);
}

Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
Reply


Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On
Forum Jump


All times are GMT. The time now is 05:05 AM.


Powered by vBulletin® Version 3.6.5
Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.
SEO by vBSEO 3.2.0
www.UnixAdminTalk.com