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:
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;
}