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 ...
| |||||||
| Register | FAQ | Members List | Calendar | Search | Today's Posts | Mark Forums Read |
| ||||
| 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); } |