ap

An audio player suited to my tastes
Log | Files | Refs | README | LICENSE

commit ad78c8e8c299f71aacb4d4e9d8cbf2b49c1276fe
parent 64e616f54d5ad9edb6881154318856fd0e784330
Author: Jacob R. Edwards <jacobouno@protonmail.com>
Date:   Fri, 16 Jul 2021 00:45:25 -0700

Improve player management

Add a completed state which tells if the player exited successfully
and interrupt poll when the player state updates due to SIGCHLD.

Diffstat:
Maps/command.c | 3+++
Maps/main.c | 20++++++++++++++++----
Maps/player.c | 15++++++---------
Maps/player.h | 3++-
Maps/queue.c | 4++--
5 files changed, 29 insertions(+), 16 deletions(-)

diff --git a/aps/command.c b/aps/command.c @@ -229,6 +229,9 @@ aps_status(struct aps *aps, int s, int argc, char **argv) case FAILURE: status = "failure"; break; + case COMPLETE: + status = "complete"; + break; default: BUG("impossible player state"); } diff --git a/aps/main.c b/aps/main.c @@ -57,17 +57,28 @@ sigchld(int sig) while ((pid = waitpid(-1, &status, WCONTINUED | WNOHANG | WUNTRACED)) > 0) { - if (pid == aps->player->pid) + if (pid == aps->player->pid) { pupdate(aps->player, status); + kill(getpid(), SIGINT); + } } } +void +sigint(int sig) +{ +} + int run(struct aps *aps) { while (!aps->close) { - if (!aps->player->state && aps->queue) - aps_next(aps, -1, 0, NULL); + if (aps->queue) { + if (aps->player->state == COMPLETE) + aps_next(aps, -1, 0, NULL); + if (aps->player->state == OFF) + pplay(aps->player, aps->queue->path); + } if ((aps_accept(aps) || aps_update(aps)) && errno != EINTR) return 1; } @@ -96,7 +107,8 @@ main(int argc, char *argv[]) aps->logmask = INFO | WARN | ERROR | FATAL; signal(SIGCHLD, sigchld); - signal(SIGINT, sigclose); + signal(SIGINT, sigint); + signal(SIGQUIT, sigclose); signal(SIGTERM, sigclose); error = run(aps); diff --git a/aps/player.c b/aps/player.c @@ -61,8 +61,8 @@ pstop(struct player *p) errno = EALREADY; return 1; } - if (p->state & (RUNNING | SUSPENDED) && kill(p->pid, SIGTERM) == -1) - return 1; + if (p->state & (RUNNING | SUSPENDED)) + kill(p->pid, SIGTERM); /* errors unconsequential */ p->state = STOPPED; return 0; } @@ -132,13 +132,10 @@ ptoggle(struct player *p) void pupdate(struct player *p, int status) { - if (WIFEXITED(status) || WIFSIGNALED(status)) { - if (p->state != STOPPED) { - if (WIFEXITED(status) && WEXITSTATUS(status)) - p->state = FAILURE; - else - p->state = 0; - } + if (WIFEXITED(status)) { + p->state = (WEXITSTATUS(status) ? FAILURE : COMPLETE); + } else if (WIFSIGNALED(status)) { + p->state = STOPPED; } else if (WIFCONTINUED(status)) { p->state = RUNNING; } else if (WIFSTOPPED(status)) { diff --git a/aps/player.h b/aps/player.h @@ -3,7 +3,8 @@ enum pstate { RUNNING = 1, STOPPED = 2, SUSPENDED = 4, - FAILURE = 8 + FAILURE = 8, + COMPLETE = 16 }; struct player { diff --git a/aps/queue.c b/aps/queue.c @@ -28,10 +28,10 @@ int queue_set(struct aps *aps, struct item *item) { aps->queue = item; - if (aps->player->state && aps->player->state != STOPPED) { + if (aps->player->state != OFF && aps->player->state != STOPPED) { if (pstop(aps->player)) return 1; - aps->player->state = 0; + aps->player->state = OFF; } return 0; }