Blame
Date:
Fri Jun 10 07:57:19 2022 UTC
Message:
don't sio_start if we're not stopped
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/uio.h>
020
2022-02-16
op
021
2022-02-16
op
#include <limits.h>
022
2022-02-16
op
023
2022-02-16
op
#include <assert.h>
024
2022-02-16
op
#include <errno.h>
025
2022-02-16
op
#include <event.h>
026
2022-02-16
op
#include <poll.h>
027
2022-02-16
op
#include <signal.h>
028
2022-02-16
op
#include <sndio.h>
029
2022-02-17
op
#include <stdio.h>
030
2022-02-16
op
#include <stdlib.h>
031
2022-02-16
op
#include <stdint.h>
032
2022-02-16
op
#include <imsg.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
037
2022-02-16
op
#include "amused.h"
038
2022-02-16
op
#include "log.h"
039
2022-02-16
op
#include "xmalloc.h"
040
2022-02-16
op
041
2022-03-09
op
struct sio_hdl *hdl;
042
2022-06-10
op
struct pollfd *player_pfds;
043
2022-03-09
op
static struct imsgbuf *ibuf;
044
2022-02-16
op
045
2022-06-10
op
static int stopped = 1;
046
2022-02-16
op
static int nextfd = -1;
047
2022-02-16
op
048
2022-02-16
op
volatile sig_atomic_t halted;
049
2022-02-16
op
050
2022-06-09
op
void
051
2022-02-16
op
player_signal_handler(int signo)
052
2022-02-16
op
{
053
2022-02-16
op
halted = 1;
054
2022-02-16
op
}
055
2022-02-16
op
056
2022-02-16
op
int
057
2022-02-21
op
player_setup(int bits, int rate, int channels)
058
2022-02-16
op
{
059
2022-06-10
op
static struct sio_par par;
060
2022-06-10
op
int nfds, fpct;
061
2022-02-16
op
062
2022-02-23
op
log_debug("%s: bits=%d, rate=%d, channels=%d", __func__,
063
2022-02-23
op
bits, rate, channels);
064
2022-06-10
op
065
2022-06-10
op
fpct = (rate*5)/100;
066
2022-06-10
op
067
2022-06-10
op
/* don't stop if the parameters are the same */
068
2022-06-10
op
if (bits == par.bits && channels == par.pchan &&
069
2022-06-10
op
par.rate - fpct <= rate && rate <= par.rate + fpct) {
070
2022-06-10
op
if (stopped)
071
2022-06-10
op
goto start;
072
2022-06-10
op
return 0;
073
2022-06-10
op
}
074
2022-02-16
op
075
2022-06-10
op
again:
076
2022-06-10
op
if (!stopped) {
077
2022-06-10
op
sio_stop(hdl);
078
2022-06-10
op
stopped = 1;
079
2022-06-10
op
}
080
2022-02-16
op
081
2022-02-16
op
sio_initpar(&par);
082
2022-02-21
op
par.bits = bits;
083
2022-02-16
op
par.rate = rate;
084
2022-02-18
op
par.pchan = channels;
085
2022-06-10
op
if (!sio_setpar(hdl, &par)) {
086
2022-06-10
op
if (errno == EAGAIN) {
087
2022-06-10
op
nfds = sio_pollfd(hdl, player_pfds + 1, POLLOUT);
088
2022-06-10
op
if (poll(player_pfds + 1, nfds, INFTIM) == -1)
089
2022-06-10
op
fatal("poll");
090
2022-06-10
op
goto again;
091
2022-06-10
op
}
092
2022-05-09
op
log_warnx("invalid params (bits=%d, rate=%d, channels=%d",
093
2022-05-09
op
bits, rate, channels);
094
2022-02-18
op
return -1;
095
2022-02-18
op
}
096
2022-06-10
op
if (!sio_getpar(hdl, &par)) {
097
2022-06-10
op
log_warnx("can't get params");
098
2022-06-10
op
return -1;
099
2022-06-10
op
}
100
2022-02-18
op
101
2022-02-21
op
if (par.bits != bits || par.pchan != channels) {
102
2022-02-18
op
log_warnx("failed to set params");
103
2022-02-16
op
return -1;
104
2022-02-16
op
}
105
2022-02-16
op
106
2022-02-16
op
/* TODO: check the sample rate? */
107
2022-02-16
op
108
2022-06-10
op
start:
109
2022-02-16
op
if (!sio_start(hdl)) {
110
2022-02-16
op
log_warn("sio_start");
111
2022-02-16
op
return -1;
112
2022-02-16
op
}
113
2022-06-10
op
stopped = 0;
114
2022-02-16
op
return 0;
115
2022-02-16
op
}
116
2022-02-16
op
117
2022-02-16
op
/* process only one message */
118
2022-02-16
op
int
119
2022-02-16
op
player_dispatch(void)
120
2022-02-16
op
{
121
2022-05-19
op
struct pollfd pfd;
122
2022-02-16
op
struct imsg imsg;
123
2022-02-16
op
ssize_t n;
124
2022-02-16
op
int ret;
125
2022-02-16
op
126
2022-02-16
op
if (halted != 0)
127
2022-02-16
op
return IMSG_STOP;
128
2022-05-19
op
129
2022-05-19
op
again:
130
2022-02-16
op
if ((n = imsg_get(ibuf, &imsg)) == -1)
131
2022-02-16
op
fatal("imsg_get");
132
2022-05-19
op
if (n == 0) {
133
2022-05-19
op
pfd.fd = ibuf->fd;
134
2022-05-19
op
pfd.events = POLLIN;
135
2022-05-19
op
if (poll(&pfd, 1, INFTIM) == -1)
136
2022-05-19
op
fatal("poll");
137
2022-05-19
op
if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN)
138
2022-05-19
op
fatal("imsg_read");
139
2022-05-19
op
if (n == 0)
140
2022-05-19
op
fatalx("pipe closed");
141
2022-05-19
op
goto again;
142
2022-05-19
op
}
143
2022-02-16
op
144
2022-02-16
op
ret = imsg.hdr.type;
145
2022-02-16
op
switch (imsg.hdr.type) {
146
2022-02-16
op
case IMSG_PLAY:
147
2022-06-09
op
if (nextfd != -1)
148
2022-06-09
op
fatalx("track already enqueued");
149
2022-06-09
op
if ((nextfd = imsg.fd) == -1)
150
2022-06-09
op
fatalx("%s: got invalid file descriptor", __func__);
151
2022-06-09
op
log_debug("song enqueued");
152
2022-02-16
op
ret = IMSG_STOP;
153
2022-02-16
op
break;
154
2022-02-16
op
case IMSG_RESUME:
155
2022-02-16
op
case IMSG_PAUSE:
156
2022-02-16
op
case IMSG_STOP:
157
2022-02-16
op
break;
158
2022-02-16
op
default:
159
2022-02-16
op
fatalx("unknown imsg %d", imsg.hdr.type);
160
2022-02-16
op
}
161
2022-02-16
op
162
2022-06-09
op
imsg_free(&imsg);
163
2022-02-16
op
return ret;
164
2022-02-16
op
}
165
2022-02-16
op
166
2022-02-16
op
void
167
2022-02-16
op
player_senderr(void)
168
2022-02-16
op
{
169
2022-02-16
op
imsg_compose(ibuf, IMSG_ERR, 0, 0, -1, NULL, 0);
170
2022-02-16
op
imsg_flush(ibuf);
171
2022-02-16
op
}
172
2022-02-16
op
173
2022-02-16
op
void
174
2022-02-16
op
player_sendeof(void)
175
2022-02-16
op
{
176
2022-02-16
op
imsg_compose(ibuf, IMSG_EOF, 0, 0, -1, NULL, 0);
177
2022-02-16
op
imsg_flush(ibuf);
178
2022-02-16
op
}
179
2022-02-16
op
180
2022-05-09
op
int
181
2022-02-16
op
player_playnext(void)
182
2022-02-16
op
{
183
2022-05-09
op
static char buf[512];
184
2022-05-09
op
ssize_t r;
185
2022-02-16
op
int fd = nextfd;
186
2022-02-16
op
187
2022-02-16
op
assert(nextfd != -1);
188
2022-02-16
op
nextfd = -1;
189
2022-02-16
op
190
2022-05-09
op
r = read(fd, buf, sizeof(buf));
191
2022-05-09
op
192
2022-05-09
op
/* 8 byte is the larger magic number */
193
2022-05-09
op
if (r < 8) {
194
2022-05-10
op
log_warn("read failed");
195
2022-05-09
op
goto err;
196
2022-05-09
op
}
197
2022-05-09
op
198
2022-05-09
op
if (lseek(fd, 0, SEEK_SET) == -1) {
199
2022-05-09
op
log_warn("lseek failed");
200
2022-05-09
op
goto err;
201
2022-05-09
op
}
202
2022-05-09
op
203
2022-05-09
op
if (memcmp(buf, "fLaC", 4) == 0)
204
2022-05-09
op
return play_flac(fd);
205
2022-05-09
op
if (memcmp(buf, "ID3", 3) == 0 ||
206
2022-05-09
op
memcmp(buf, "\xFF\xFB", 2) == 0)
207
2022-05-09
op
return play_mp3(fd);
208
2022-05-09
op
if (memmem(buf, r, "OpusHead", 8) != NULL)
209
2022-05-09
op
return play_opus(fd);
210
2022-05-09
op
if (memmem(buf, r, "OggS", 4) != NULL)
211
2022-05-09
op
return play_oggvorbis(fd);
212
2022-02-22
op
213
2022-05-10
op
log_warnx("unknown file type");
214
2022-05-09
op
err:
215
2022-05-09
op
close(fd);
216
2022-05-09
op
return -1;
217
2022-02-16
op
}
218
2022-02-16
op
219
2022-02-16
op
int
220
2022-02-16
op
player_pause(void)
221
2022-02-16
op
{
222
2022-02-16
op
int r;
223
2022-02-16
op
224
2022-02-16
op
r = player_dispatch();
225
2022-02-16
op
return r == IMSG_RESUME;
226
2022-02-16
op
}
227
2022-02-16
op
228
2022-02-16
op
int
229
2022-02-16
op
player_shouldstop(void)
230
2022-02-16
op
{
231
2022-02-16
op
switch (player_dispatch()) {
232
2022-02-16
op
case IMSG_PAUSE:
233
2022-02-16
op
if (player_pause())
234
2022-02-16
op
break;
235
2022-02-16
op
/* fallthrough */
236
2022-02-16
op
case IMSG_STOP:
237
2022-02-16
op
return 1;
238
2022-02-16
op
}
239
2022-02-16
op
240
2022-02-16
op
return 0;
241
2022-02-16
op
}
242
2022-02-16
op
243
2022-02-16
op
int
244
2022-03-09
op
play(const void *buf, size_t len)
245
2022-03-09
op
{
246
2022-06-10
op
size_t w;
247
2022-06-10
op
int nfds, revents, r;
248
2022-06-10
op
249
2022-06-10
op
while (len != 0) {
250
2022-06-10
op
nfds = sio_pollfd(hdl, player_pfds + 1, POLLOUT);
251
2022-06-10
op
r = poll(player_pfds, nfds + 1, INFTIM);
252
2022-06-10
op
if (r == -1)
253
2022-06-10
op
fatal("poll");
254
2022-06-10
op
255
2022-06-10
op
if (player_pfds[0].revents & (POLLHUP|POLLIN)) {
256
2022-06-10
op
if (player_shouldstop()) {
257
2022-06-10
op
sio_flush(hdl);
258
2022-06-10
op
stopped = 1;
259
2022-06-10
op
return 0;
260
2022-06-10
op
}
261
2022-06-10
op
}
262
2022-06-10
op
263
2022-06-10
op
revents = sio_revents(hdl, player_pfds + 1);
264
2022-06-10
op
if (revents & POLLHUP)
265
2022-06-10
op
fatalx("sndio hang-up");
266
2022-06-10
op
if (revents & POLLOUT) {
267
2022-06-10
op
w = sio_write(hdl, buf, len);
268
2022-06-10
op
len -= w;
269
2022-06-10
op
buf += w;
270
2022-06-10
op
}
271
2022-06-10
op
}
272
2022-06-10
op
273
2022-03-09
op
return 1;
274
2022-03-09
op
}
275
2022-03-09
op
276
2022-03-09
op
int
277
2022-02-16
op
player(int debug, int verbose)
278
2022-02-16
op
{
279
2022-05-19
op
int r;
280
2022-05-19
op
281
2022-02-16
op
log_init(debug, LOG_DAEMON);
282
2022-02-16
op
log_setverbose(verbose);
283
2022-02-16
op
284
2022-02-16
op
setproctitle("player");
285
2022-02-16
op
log_procinit("player");
286
2022-02-16
op
287
2022-02-16
op
#if 0
288
2022-02-16
op
{
289
2022-02-16
op
static int attached;
290
2022-02-16
op
291
2022-02-16
op
while (!attached)
292
2022-02-16
op
sleep(1);
293
2022-02-16
op
}
294
2022-02-16
op
#endif
295
2022-02-16
op
296
2022-06-10
op
if ((hdl = sio_open(SIO_DEVANY, SIO_PLAY, 1)) == NULL)
297
2022-06-10
op
fatal("sio_open");
298
2022-02-16
op
299
2022-06-10
op
/* allocate one extra for imsg */
300
2022-06-10
op
player_pfds = calloc(sio_nfds(hdl) + 1, sizeof(*player_pfds));
301
2022-06-10
op
if (player_pfds == NULL)
302
2022-06-10
op
fatal("calloc");
303
2022-06-10
op
304
2022-06-10
op
player_pfds[0].events = POLLIN;
305
2022-06-10
op
player_pfds[0].fd = 3;
306
2022-06-10
op
307
2022-02-16
op
ibuf = xmalloc(sizeof(*ibuf));
308
2022-02-16
op
imsg_init(ibuf, 3);
309
2022-02-16
op
310
2022-02-16
op
signal(SIGINT, player_signal_handler);
311
2022-02-16
op
signal(SIGTERM, player_signal_handler);
312
2022-02-16
op
313
2022-02-16
op
signal(SIGHUP, SIG_IGN);
314
2022-02-16
op
signal(SIGPIPE, SIG_IGN);
315
2022-02-16
op
316
2022-03-10
op
if (pledge("stdio recvfd audio", NULL) == -1)
317
2022-02-16
op
fatal("pledge");
318
2022-02-16
op
319
2022-02-16
op
while (!halted) {
320
2022-02-16
op
while (nextfd == -1)
321
2022-02-16
op
player_dispatch();
322
2022-05-09
op
323
2022-05-09
op
r = player_playnext();
324
2022-05-09
op
if (r == -1)
325
2022-05-09
op
player_senderr();
326
2022-05-09
op
if (r == 0)
327
2022-05-09
op
player_sendeof();
328
2022-02-16
op
}
329
2022-02-16
op
330
2022-02-16
op
return 0;
331
2022-02-16
op
}
Omar Polo