Blame
Date:
Thu Mar 3 13:50:12 2022 UTC
Message:
rework how the daemon is automatically spawned The previous way introduce possible races if multiple `amused' instances try to start the daemon. The new approach is heavily lifted from how tmux does it, but with some minor differences. If the initial connect fails we try to grab a lock to safely execute the daemon only one time. In fact we try to connect one more time even when we hold the lock because another instance can grab the lock, start the daemon and release it between the failure of connect and the first flock. It also changes slightly how the program behaves and how the -d option works. Now running `amused' without arguments is a synonym for `amused status' and the -d option only works if no arguments were given and if the daemon wasn't running.
001
2022-02-16
op
/*
002
2022-02-16
op
* Copyright (c) 2022 Omar Polo <op@openbsd.org>
003
2022-02-16
op
*
004
2022-02-16
op
* Permission to use, copy, modify, and distribute this software for any
005
2022-02-16
op
* purpose with or without fee is hereby granted, provided that the above
006
2022-02-16
op
* copyright notice and this permission notice appear in all copies.
007
2022-02-16
op
*
008
2022-02-16
op
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
009
2022-02-16
op
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
010
2022-02-16
op
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
011
2022-02-16
op
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
012
2022-02-16
op
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
013
2022-02-16
op
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
014
2022-02-16
op
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
015
2022-02-16
op
*/
016
2022-02-16
op
017
2022-02-16
op
#include <sys/types.h>
018
2022-02-16
op
#include <sys/queue.h>
019
2022-02-16
op
#include <sys/socket.h>
020
2022-02-24
op
#include <sys/stat.h>
021
2022-02-16
op
#include <sys/uio.h>
022
2022-02-16
op
#include <sys/wait.h>
023
2022-02-16
op
024
2022-02-16
op
#include <event.h>
025
2022-02-16
op
#include <errno.h>
026
2022-02-16
op
#include <fcntl.h>
027
2022-02-16
op
#include <limits.h>
028
2022-02-16
op
#include <sndio.h>
029
2022-02-16
op
#include <signal.h>
030
2022-02-16
op
#include <stdio.h>
031
2022-02-16
op
#include <stdlib.h>
032
2022-02-16
op
#include <stdint.h>
033
2022-02-16
op
#include <string.h>
034
2022-02-16
op
#include <syslog.h>
035
2022-02-16
op
#include <unistd.h>
036
2022-02-16
op
#include <imsg.h>
037
2022-02-16
op
038
2022-02-16
op
#include "amused.h"
039
2022-02-16
op
#include "control.h"
040
2022-02-16
op
#include "log.h"
041
2022-02-16
op
#include "playlist.h"
042
2022-02-16
op
#include "xmalloc.h"
043
2022-02-16
op
044
2022-02-16
op
struct sio_hdl *hdl;
045
2022-02-16
op
char *csock = NULL;
046
2022-02-16
op
int debug;
047
2022-02-16
op
int verbose;
048
2022-02-16
op
struct imsgev *iev_player;
049
2022-02-16
op
050
2022-02-16
op
const char *argv0;
051
2022-02-16
op
pid_t player_pid;
052
2022-02-16
op
struct event ev_sigint;
053
2022-02-16
op
struct event ev_sigterm;
054
2022-02-16
op
055
2022-02-16
op
enum amused_process {
056
2022-02-16
op
PROC_MAIN,
057
2022-02-16
op
PROC_PLAYER,
058
2022-02-16
op
};
059
2022-02-16
op
060
2022-02-16
op
__dead void
061
2022-02-16
op
main_shutdown(void)
062
2022-02-16
op
{
063
2022-02-16
op
pid_t pid;
064
2022-02-16
op
int status;
065
2022-02-16
op
066
2022-02-16
op
/* close pipes. */
067
2022-02-16
op
msgbuf_clear(&iev_player->ibuf.w);
068
2022-02-16
op
close(iev_player->ibuf.fd);
069
2022-02-16
op
free(iev_player);
070
2022-02-16
op
071
2022-02-16
op
log_debug("waiting for children to terminate");
072
2022-02-16
op
do {
073
2022-02-16
op
pid = wait(&status);
074
2022-02-16
op
if (pid == -1) {
075
2022-02-16
op
if (errno != EINTR && errno != ECHILD)
076
2022-02-16
op
fatal("wait");
077
2022-02-16
op
} else if (WIFSIGNALED(status))
078
2022-02-16
op
log_warnx("player terminated; signal %d",
079
2022-02-16
op
WTERMSIG(status));
080
2022-02-16
op
} while (pid != -1 || (pid == -1 && errno == EINTR));
081
2022-02-16
op
082
2022-02-16
op
log_info("terminating");
083
2022-02-16
op
exit(0);
084
2022-02-16
op
}
085
2022-02-16
op
086
2022-02-16
op
static void
087
2022-02-16
op
main_sig_handler(int sig, short event, void *arg)
088
2022-02-16
op
{
089
2022-02-16
op
/*
090
2022-02-16
op
* Normal signal handler rules don't apply because libevent
091
2022-02-16
op
* decouples for us.
092
2022-02-16
op
*/
093
2022-02-16
op
094
2022-02-16
op
switch (sig) {
095
2022-02-16
op
case SIGTERM:
096
2022-02-16
op
case SIGINT:
097
2022-02-16
op
main_shutdown();
098
2022-02-16
op
break;
099
2022-02-16
op
default:
100
2022-02-16
op
fatalx("unexpected signal %d", sig);
101
2022-02-16
op
}
102
2022-02-16
op
}
103
2022-02-16
op
104
2022-02-16
op
static void
105
2022-02-16
op
main_dispatch_player(int sig, short event, void *d)
106
2022-02-16
op
{
107
2022-02-16
op
struct imsgev *iev = d;
108
2022-02-16
op
struct imsgbuf *ibuf = &iev->ibuf;
109
2022-02-16
op
struct imsg imsg;
110
2022-02-16
op
ssize_t n;
111
2022-02-16
op
int shut = 0;
112
2022-02-16
op
113
2022-02-16
op
if (event & EV_READ) {
114
2022-02-16
op
if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN)
115
2022-02-16
op
fatal("imsg_read error");
116
2022-02-16
op
if (n == 0) /* Connection closed */
117
2022-02-16
op
shut = 1;
118
2022-02-16
op
}
119
2022-02-16
op
if (event & EV_WRITE) {
120
2022-02-16
op
if ((n = msgbuf_write(&ibuf->w)) == -1 && errno != EAGAIN)
121
2022-02-16
op
fatal("msgbuf_write");
122
2022-02-16
op
if (n == 0) /* Connection closed */
123
2022-02-16
op
shut = 1;
124
2022-02-16
op
}
125
2022-02-16
op
126
2022-02-16
op
for (;;) {
127
2022-02-16
op
if ((n = imsg_get(ibuf, &imsg)) == -1)
128
2022-02-16
op
fatal("imsg_get");
129
2022-02-16
op
if (n == 0) /* No more messages. */
130
2022-02-16
op
break;
131
2022-02-16
op
132
2022-02-16
op
switch (imsg.hdr.type) {
133
2022-02-16
op
case IMSG_ERR:
134
2022-02-16
op
playlist_dropcurrent();
135
2022-02-22
op
/* fallthrough */
136
2022-02-16
op
case IMSG_EOF:
137
2022-02-22
op
if (repeat_one && current_song != NULL) {
138
2022-02-19
op
if (main_play_song(current_song))
139
2022-02-19
op
break;
140
2022-02-22
op
playlist_dropcurrent();
141
2022-02-22
op
}
142
2022-02-16
op
main_playlist_advance();
143
2022-02-21
op
if (play_state == STATE_PLAYING)
144
2022-02-21
op
control_notify(NULL, IMSG_CTL_NEXT);
145
2022-02-21
op
else
146
2022-02-21
op
control_notify(NULL, IMSG_CTL_STOP);
147
2022-02-16
op
break;
148
2022-02-16
op
default:
149
2022-02-16
op
log_debug("%s: error handling imsg %d", __func__,
150
2022-02-16
op
imsg.hdr.type);
151
2022-02-16
op
break;
152
2022-02-16
op
}
153
2022-02-16
op
imsg_free(&imsg);
154
2022-02-16
op
}
155
2022-02-16
op
156
2022-02-16
op
if (!shut)
157
2022-02-16
op
imsg_event_add(iev);
158
2022-02-16
op
else {
159
2022-02-16
op
/* This pipe is dead. Remove its event handler. */
160
2022-02-16
op
event_del(&iev->ev);
161
2022-02-16
op
event_loopexit(NULL);
162
2022-02-16
op
}
163
2022-02-16
op
}
164
2022-02-16
op
165
2022-02-16
op
static pid_t
166
2022-02-16
op
start_child(enum amused_process proc, int fd)
167
2022-02-16
op
{
168
2022-03-03
op
const char *argv[7];
169
2022-02-16
op
int argc = 0;
170
2022-02-16
op
pid_t pid;
171
2022-02-16
op
172
2022-03-03
op
if (fd == -1 && debug)
173
2022-03-03
op
goto exec;
174
2022-03-03
op
175
2022-02-16
op
switch (pid = fork()) {
176
2022-02-16
op
case -1:
177
2022-02-16
op
fatal("cannot fork");
178
2022-02-16
op
case 0:
179
2022-02-16
op
break;
180
2022-02-16
op
default:
181
2022-02-16
op
close(fd);
182
2022-02-16
op
return pid;
183
2022-02-16
op
}
184
2022-02-16
op
185
2022-02-16
op
if (fd != 3) {
186
2022-02-16
op
if (fd != -1 && dup2(fd, 3) == -1)
187
2022-02-16
op
fatal("cannot setup imsg fd");
188
2022-02-16
op
} else if (fcntl(F_SETFD, 0) == -1)
189
2022-02-16
op
fatal("cannot setup imsg fd");
190
2022-02-16
op
191
2022-03-03
op
exec:
192
2022-02-16
op
argv[argc++] = argv0;
193
2022-02-17
op
194
2022-02-16
op
switch (proc) {
195
2022-02-16
op
case PROC_MAIN:
196
2022-02-17
op
argv[argc++] = "-s";
197
2022-02-17
op
argv[argc++] = csock;
198
2022-03-03
op
argv[argc++] = "-Tm";
199
2022-02-16
op
break;
200
2022-02-16
op
case PROC_PLAYER:
201
2022-02-16
op
argv[argc++] = "-Tp";
202
2022-02-16
op
break;
203
2022-02-16
op
}
204
2022-02-16
op
205
2022-02-16
op
if (debug)
206
2022-02-16
op
argv[argc++] = "-d";
207
2022-02-16
op
if (verbose)
208
2022-02-16
op
argv[argc++] = "-v";
209
2022-02-16
op
argv[argc++] = NULL;
210
2022-02-16
op
211
2022-02-16
op
/* obnoxious casts */
212
2022-02-16
op
execvp(argv0, (char *const *)argv);
213
2022-02-16
op
fatal("execvp %s", argv0);
214
2022-02-16
op
}
215
2022-02-16
op
216
2022-02-16
op
/* daemon main routine */
217
2022-02-16
op
static __dead int
218
2022-02-16
op
amused_main(void)
219
2022-02-16
op
{
220
2022-02-16
op
int pipe_main2player[2];
221
2022-02-16
op
int control_fd;
222
2022-02-16
op
223
2022-02-16
op
log_init(debug, LOG_DAEMON);
224
2022-02-16
op
log_setverbose(verbose);
225
2022-02-16
op
log_procinit("main");
226
2022-02-16
op
227
2022-02-16
op
if (!debug)
228
2022-02-16
op
daemon(1, 0);
229
2022-02-16
op
230
2022-02-16
op
if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK,
231
2022-02-16
op
PF_UNSPEC, pipe_main2player) == -1)
232
2022-02-16
op
fatal("socketpair");
233
2022-02-16
op
234
2022-02-16
op
player_pid = start_child(PROC_PLAYER, pipe_main2player[1]);
235
2022-02-16
op
236
2022-02-16
op
event_init();
237
2022-02-16
op
238
2022-02-16
op
signal_set(&ev_sigint, SIGINT, main_sig_handler, NULL);
239
2022-02-16
op
signal_set(&ev_sigterm, SIGTERM, main_sig_handler, NULL);
240
2022-02-16
op
241
2022-02-16
op
signal_add(&ev_sigint, NULL);
242
2022-02-16
op
signal_add(&ev_sigterm, NULL);
243
2022-02-16
op
244
2022-02-16
op
signal(SIGHUP, SIG_IGN);
245
2022-02-16
op
signal(SIGCHLD, SIG_IGN);
246
2022-02-16
op
signal(SIGPIPE, SIG_IGN);
247
2022-02-16
op
248
2022-02-16
op
iev_player = xmalloc(sizeof(*iev_player));
249
2022-02-16
op
imsg_init(&iev_player->ibuf, pipe_main2player[0]);
250
2022-02-16
op
iev_player->handler = main_dispatch_player;
251
2022-02-16
op
iev_player->events = EV_READ;
252
2022-02-16
op
event_set(&iev_player->ev, iev_player->ibuf.fd, iev_player->events,
253
2022-02-16
op
iev_player->handler, iev_player);
254
2022-02-16
op
event_add(&iev_player->ev, NULL);
255
2022-02-16
op
256
2022-02-16
op
if ((control_fd = control_init(csock)) == -1)
257
2022-02-16
op
fatal("control socket setup failed %s", csock);
258
2022-02-16
op
control_listen(control_fd);
259
2022-02-16
op
260
2022-02-16
op
if (pledge("stdio rpath unix sendfd", NULL) == -1)
261
2022-02-16
op
fatal("pledge");
262
2022-02-16
op
263
2022-02-16
op
log_info("startup");
264
2022-02-16
op
event_dispatch();
265
2022-02-16
op
main_shutdown();
266
2022-02-16
op
}
267
2022-02-16
op
268
2022-02-16
op
int
269
2022-02-16
op
main(int argc, char **argv)
270
2022-02-16
op
{
271
2022-03-03
op
int ch, proc = -1;
272
2022-02-16
op
273
2022-02-16
op
log_init(1, LOG_DAEMON); /* Log to stderr until daemonized */
274
2022-02-16
op
log_setverbose(1);
275
2022-02-16
op
276
2022-02-16
op
argv0 = argv[0];
277
2022-02-16
op
if (argv0 == NULL)
278
2022-02-16
op
argv0 = "amused";
279
2022-02-16
op
280
2022-02-19
op
while ((ch = getopt(argc, argv, "ds:T:v")) != -1) {
281
2022-02-16
op
switch (ch) {
282
2022-02-16
op
case 'd':
283
2022-02-16
op
debug = 1;
284
2022-02-16
op
break;
285
2022-02-16
op
case 's':
286
2022-02-16
op
free(csock);
287
2022-02-16
op
csock = xstrdup(optarg);
288
2022-02-16
op
break;
289
2022-02-16
op
case 'T':
290
2022-02-16
op
switch (*optarg) {
291
2022-03-03
op
case 'm':
292
2022-03-03
op
proc = PROC_MAIN;
293
2022-03-03
op
break;
294
2022-02-16
op
case 'p':
295
2022-02-16
op
proc = PROC_PLAYER;
296
2022-02-16
op
break;
297
2022-02-16
op
default:
298
2022-02-16
op
usage();
299
2022-02-16
op
}
300
2022-02-16
op
break;
301
2022-02-16
op
case 'v':
302
2022-02-16
op
verbose++;
303
2022-02-16
op
break;
304
2022-02-16
op
default:
305
2022-02-16
op
usage();
306
2022-02-16
op
}
307
2022-02-16
op
}
308
2022-02-16
op
argv += optind;
309
2022-02-16
op
argc -= optind;
310
2022-02-16
op
311
2022-03-03
op
if (proc == PROC_MAIN)
312
2022-03-03
op
amused_main();
313
2022-02-16
op
if (proc == PROC_PLAYER)
314
2022-02-16
op
exit(player(debug, verbose));
315
2022-02-16
op
316
2022-02-16
op
if (csock == NULL)
317
2022-02-16
op
xasprintf(&csock, "/tmp/amused-%d", getuid());
318
2022-02-16
op
319
2022-03-03
op
if (argc > 0)
320
2022-03-03
op
debug = 0;
321
2022-03-03
op
322
2022-03-03
op
ctl(argc, argv);
323
2022-02-16
op
}
324
2022-02-16
op
325
2022-02-16
op
void
326
2022-02-16
op
spawn_daemon(void)
327
2022-02-16
op
{
328
2022-02-16
op
start_child(PROC_MAIN, -1);
329
2022-02-16
op
}
330
2022-02-16
op
331
2022-02-16
op
void
332
2022-02-16
op
imsg_event_add(struct imsgev *iev)
333
2022-02-16
op
{
334
2022-02-16
op
iev->events = EV_READ;
335
2022-02-16
op
if (iev->ibuf.w.queued)
336
2022-02-16
op
iev->events |= EV_WRITE;
337
2022-02-16
op
338
2022-02-16
op
event_del(&iev->ev);
339
2022-02-16
op
event_set(&iev->ev, iev->ibuf.fd, iev->events, iev->handler, iev);
340
2022-02-16
op
event_add(&iev->ev, NULL);
341
2022-02-16
op
}
342
2022-02-16
op
343
2022-02-16
op
int
344
2022-02-16
op
imsg_compose_event(struct imsgev *iev, uint16_t type, uint32_t peerid,
345
2022-02-16
op
pid_t pid, int fd, const void *data, uint16_t datalen)
346
2022-02-16
op
{
347
2022-02-16
op
int ret;
348
2022-02-16
op
349
2022-02-16
op
if ((ret = imsg_compose(&iev->ibuf, type, peerid, pid, fd, data,
350
2022-02-16
op
datalen)) != -1)
351
2022-02-16
op
imsg_event_add(iev);
352
2022-02-16
op
353
2022-02-16
op
return ret;
354
2022-02-16
op
}
355
2022-02-16
op
356
2022-02-16
op
int
357
2022-02-16
op
main_send_player(uint16_t type, int fd, const void *data, uint16_t datalen)
358
2022-02-16
op
{
359
2022-02-16
op
return imsg_compose_event(iev_player, type, 0, 0, fd, data, datalen);
360
2022-02-16
op
}
361
2022-02-16
op
362
2022-02-16
op
int
363
2022-02-16
op
main_play_song(const char *song)
364
2022-02-16
op
{
365
2022-02-24
op
struct stat sb;
366
2022-02-16
op
char path[PATH_MAX] = { 0 };
367
2022-02-16
op
int fd;
368
2022-02-16
op
369
2022-02-16
op
strlcpy(path, song, sizeof(path));
370
2022-02-16
op
if ((fd = open(path, O_RDONLY)) == -1) {
371
2022-02-16
op
log_warn("open %s", path);
372
2022-02-24
op
return 0;
373
2022-02-24
op
}
374
2022-02-24
op
375
2022-02-24
op
if (fstat(fd, &sb) == -1) {
376
2022-02-24
op
log_warn("failed to stat %s", path);
377
2022-02-24
op
close(fd);
378
2022-02-16
op
return 0;
379
2022-02-16
op
}
380
2022-02-16
op
381
2022-02-24
op
if (S_ISDIR(sb.st_mode)) {
382
2022-02-24
op
log_info("skipping a directory: %s", path);
383
2022-02-24
op
close(fd);
384
2022-02-24
op
return 0;
385
2022-02-24
op
}
386
2022-02-24
op
387
2022-02-16
op
play_state = STATE_PLAYING;
388
2022-02-16
op
imsg_compose_event(iev_player, IMSG_PLAY, 0, 0, fd,
389
2022-02-16
op
path, sizeof(path));
390
2022-02-16
op
return 1;
391
2022-02-17
op
}
392
2022-02-17
op
393
2022-02-17
op
void
394
2022-02-17
op
main_playlist_jump(struct imsgev *iev, struct imsg *imsg)
395
2022-02-17
op
{
396
2022-02-17
op
size_t datalen;
397
2022-02-17
op
char arg[PATH_MAX];
398
2022-02-17
op
const char *song;
399
2022-02-17
op
400
2022-02-17
op
datalen = IMSG_DATA_SIZE(*imsg);
401
2022-02-17
op
if (datalen != sizeof(arg)) {
402
2022-02-17
op
main_senderr(iev, "wrong size");
403
2022-02-17
op
return;
404
2022-02-17
op
}
405
2022-02-17
op
406
2022-02-17
op
memcpy(arg, imsg->data, sizeof(arg));
407
2022-02-17
op
if (arg[sizeof(arg)-1] != '\0') {
408
2022-02-17
op
main_senderr(iev, "data corrupted");
409
2022-02-17
op
return;
410
2022-02-17
op
}
411
2022-02-17
op
412
2022-02-17
op
song = playlist_jump(arg);
413
2022-02-17
op
if (song == NULL) {
414
2022-02-17
op
main_senderr(iev, "not found");
415
2022-02-17
op
return;
416
2022-02-17
op
}
417
2022-02-17
op
418
2022-02-17
op
main_send_player(IMSG_STOP, -1, NULL, 0);
419
2022-02-17
op
if (!main_play_song(song)) {
420
2022-02-17
op
main_senderr(iev, "can't play");
421
2022-02-17
op
playlist_dropcurrent();
422
2022-02-17
op
main_playlist_advance();
423
2022-02-17
op
return;
424
2022-02-17
op
}
425
2022-02-17
op
426
2022-02-17
op
main_send_status(iev);
427
2022-02-17
op
}
428
2022-02-17
op
429
2022-02-17
op
void
430
2022-02-17
op
main_playlist_resume(void)
431
2022-02-17
op
{
432
2022-02-17
op
const char *song;
433
2022-02-17
op
434
2022-02-19
op
if ((song = current_song) == NULL)
435
2022-02-17
op
song = playlist_advance();
436
2022-02-17
op
437
2022-02-17
op
for (; song != NULL; song = playlist_advance()) {
438
2022-02-17
op
if (main_play_song(song))
439
2022-02-17
op
return;
440
2022-02-17
op
441
2022-02-17
op
playlist_dropcurrent();
442
2022-02-17
op
}
443
2022-02-16
op
}
444
2022-02-16
op
445
2022-02-16
op
void
446
2022-02-16
op
main_playlist_advance(void)
447
2022-02-16
op
{
448
2022-02-16
op
const char *song;
449
2022-02-16
op
450
2022-02-16
op
for (;;) {
451
2022-02-16
op
song = playlist_advance();
452
2022-02-16
op
if (song == NULL)
453
2022-02-16
op
return;
454
2022-02-16
op
455
2022-02-16
op
if (main_play_song(song))
456
2022-02-16
op
break;
457
2022-02-16
op
458
2022-02-16
op
playlist_dropcurrent();
459
2022-02-16
op
}
460
2022-02-16
op
}
461
2022-02-16
op
462
2022-02-16
op
void
463
2022-02-17
op
main_playlist_previous(void)
464
2022-02-17
op
{
465
2022-02-17
op
const char *song;
466
2022-02-17
op
467
2022-02-17
op
for (;;) {
468
2022-02-17
op
song = playlist_previous();
469
2022-02-17
op
if (song == NULL)
470
2022-02-17
op
return;
471
2022-02-17
op
472
2022-02-17
op
if (main_play_song(song))
473
2022-02-17
op
break;
474
2022-02-17
op
475
2022-02-17
op
playlist_dropcurrent();
476
2022-02-17
op
}
477
2022-02-17
op
}
478
2022-02-17
op
479
2022-02-17
op
void
480
2022-02-16
op
main_restart_track(void)
481
2022-02-16
op
{
482
2022-02-16
op
const char *song;
483
2022-02-16
op
484
2022-02-19
op
song = current_song;
485
2022-02-16
op
if (song == NULL)
486
2022-02-16
op
return;
487
2022-02-16
op
488
2022-02-16
op
if (main_play_song(song))
489
2022-02-16
op
return;
490
2022-02-16
op
491
2022-02-16
op
playlist_dropcurrent();
492
2022-02-16
op
main_playlist_advance();
493
2022-02-16
op
}
494
2022-02-16
op
495
2022-02-16
op
void
496
2022-02-17
op
main_senderr(struct imsgev *iev, const char *msg)
497
2022-02-16
op
{
498
2022-02-17
op
imsg_compose_event(iev, IMSG_CTL_ERR, 0, 0, -1,
499
2022-02-17
op
msg, strlen(msg)+1);
500
2022-02-17
op
}
501
2022-02-17
op
502
2022-02-17
op
void
503
2022-02-17
op
main_enqueue(int tx, struct playlist *px, struct imsgev *iev,
504
2022-02-17
op
struct imsg *imsg)
505
2022-02-17
op
{
506
2022-02-16
op
size_t datalen;
507
2022-02-16
op
char path[PATH_MAX] = { 0 };
508
2022-02-16
op
const char *err = NULL;
509
2022-02-16
op
510
2022-02-16
op
datalen = IMSG_DATA_SIZE(*imsg);
511
2022-02-16
op
if (datalen != sizeof(path)) {
512
2022-02-16
op
err = "data size mismatch";
513
2022-02-16
op
goto err;
514
2022-02-16
op
}
515
2022-02-16
op
516
2022-02-16
op
memcpy(path, imsg->data, sizeof(path));
517
2022-02-16
op
if (path[datalen-1] != '\0') {
518
2022-02-16
op
err = "malformed data";
519
2022-02-16
op
goto err;
520
2022-02-16
op
}
521
2022-02-16
op
522
2022-02-18
op
if (tx)
523
2022-02-17
op
playlist_push(px, path);
524
2022-02-17
op
else
525
2022-02-17
op
playlist_enqueue(path);
526
2022-02-16
op
imsg_compose_event(iev, IMSG_CTL_ADD, 0, 0, -1, path, sizeof(path));
527
2022-02-16
op
return;
528
2022-02-16
op
err:
529
2022-03-02
op
main_senderr(iev, err);
530
2022-02-16
op
}
531
2022-02-16
op
532
2022-02-16
op
void
533
2022-02-16
op
main_send_playlist(struct imsgev *iev)
534
2022-02-16
op
{
535
2022-02-17
op
struct player_status s;
536
2022-02-16
op
size_t i;
537
2022-02-16
op
538
2022-02-16
op
for (i = 0; i < playlist.len; ++i) {
539
2022-02-17
op
memset(&s, 0, sizeof(s));
540
2022-02-17
op
strlcpy(s.path, playlist.songs[i], sizeof(s.path));
541
2022-02-17
op
s.status = play_off == i ? STATE_PLAYING : STATE_STOPPED;
542
2022-02-17
op
imsg_compose_event(iev, IMSG_CTL_SHOW, 0, 0, -1, &s,
543
2022-02-17
op
sizeof(s));
544
2022-02-16
op
}
545
2022-02-16
op
546
2022-02-16
op
imsg_compose_event(iev, IMSG_CTL_SHOW, 0, 0, -1, NULL, 0);
547
2022-02-16
op
}
548
2022-02-16
op
549
2022-02-16
op
void
550
2022-02-16
op
main_send_status(struct imsgev *iev)
551
2022-02-16
op
{
552
2022-02-16
op
struct player_status s;
553
2022-02-16
op
554
2022-02-16
op
memset(&s, 0, sizeof(s));
555
2022-02-16
op
556
2022-02-19
op
if (current_song != NULL)
557
2022-02-19
op
strlcpy(s.path, current_song, sizeof(s.path));
558
2022-02-16
op
s.status = play_state;
559
2022-02-19
op
s.rp.repeat_all = repeat_all;
560
2022-02-19
op
s.rp.repeat_one = repeat_one;
561
2022-02-16
op
562
2022-02-16
op
imsg_compose_event(iev, IMSG_CTL_STATUS, 0, 0, -1, &s, sizeof(s));
563
2022-02-16
op
}
Omar Polo