Handle already exited ogg123(1) gracefully
[oggquiz.git] / player.c
blobe83663abcf969057b6efa6b459e355a9f0bcc6ae
1 /*-
2 * "THE BEER-WARE LICENSE" (Revision 42):
3 * <tobias.rehbein@web.de> wrote this file. As long as you retain this notice
4 * you can do whatever you want with this stuff. If we meet some day, and you
5 * think this stuff is worth it, you can buy me a beer in return.
6 * Tobias Rehbein
7 */
9 #include <assert.h>
10 #include <err.h>
11 #include <errno.h>
12 #include <signal.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <sysexits.h>
16 #include <unistd.h>
17 #include <sys/types.h>
19 #include "player.h"
21 struct plr_context {
22 char *ogg123;
23 char *ogg123_options;
24 pid_t pid;
27 struct plr_context *
28 plr_context_open(char const *ogg123, char const *ogg123_options)
30 struct plr_context *ctx;
31 size_t len;
33 assert(ogg123 != NULL);
35 if ((ctx = malloc(sizeof(*ctx))) == NULL)
36 err(EX_SOFTWARE, "could not malloc plr_ctx");
38 len = strlen(ogg123);
39 if ((ctx->ogg123 = malloc(len + 1)) == NULL)
40 err(EX_SOFTWARE, "could not malloc plr_ctx->ogg123");
41 strncpy(ctx->ogg123, ogg123, len);
42 ctx->ogg123[len] = '\0';
44 len = strlen(ogg123_options);
45 if (len > 0) {
46 if ((ctx->ogg123_options = malloc(len + 1)) == NULL)
47 err(EX_SOFTWARE, "could not malloc plr_ctx->ogg123_options");
48 strncpy(ctx->ogg123_options, ogg123_options, len);
49 ctx->ogg123_options[len] = '\0';
50 } else
51 ctx->ogg123_options = NULL;
53 ctx->pid = (pid_t) - 1;
55 return (ctx);
58 void
59 plr_context_close(struct plr_context *ctx)
61 assert(ctx != NULL);
63 plr_stop(ctx);
64 free(ctx->ogg123);
65 free(ctx);
68 void
69 plr_play(struct plr_context *ctx, char *ogg)
71 pid_t lpid;
73 assert(ctx != NULL);
74 assert(ogg != NULL);
76 plr_stop(ctx);
78 switch (lpid = fork()) {
79 case (0):
80 execl(ctx->ogg123, ctx->ogg123, "-q", ogg, ctx->ogg123_options, NULL);
81 err(EX_OSERR, "could not exec %s", ctx->ogg123);
82 case (-1):
83 err(EX_OSERR, "could not fork player");
84 default:
85 ctx->pid = lpid;
89 void
90 plr_stop(struct plr_context *ctx)
92 if (ctx->pid != (pid_t) (-1)) {
93 if ((kill(ctx->pid, SIGHUP) == -1) && (errno != ESRCH))
94 err(EX_OSERR, "could not kill running player: %d", ctx->pid);
95 ctx->pid = -1;