Blob


1 /*
2 * Copyright (c) 2022 Omar Polo <op@openbsd.org>
3 *
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
17 #include "config.h"
19 #include <sys/mman.h>
20 #include <sys/stat.h>
22 #include <limits.h>
23 #include <unistd.h>
25 #include <mpg123.h>
27 #include "amused.h"
28 #include "log.h"
30 static int
31 setup(mpg123_handle *mh)
32 {
33 long rate;
34 int chan, enc;
36 if (mpg123_getformat(mh, &rate, &chan, &enc) != MPG123_OK) {
37 log_warnx("mpg123_getformat failed");
38 return 0;
39 }
41 if (player_setup(mpg123_encsize(enc) * 8, rate, chan) == -1)
42 err(1, "player_setup");
44 return 1;
45 }
47 int
48 play_mp3(int fd, const char **errstr)
49 {
50 static char buf[4096];
51 size_t len;
52 mpg123_handle *mh;
53 int64_t seek = -1;
54 int err, ret = -1;
56 if ((mh = mpg123_new(NULL, NULL)) == NULL)
57 fatal("mpg123_new");
59 if (mpg123_open_fd(mh, fd) != MPG123_OK) {
60 *errstr = "mpg123_open_fd failed";
61 close(fd);
62 return -1;
63 }
65 if (!setup(mh))
66 goto done;
68 player_setduration(mpg123_length(mh));
70 for (;;) {
71 if (seek != -1) {
72 seek = mpg123_seek(mh, seek, SEEK_SET);
73 if (seek < 0) {
74 ret = 0;
75 break;
76 }
77 player_setpos(seek);
78 }
80 err = mpg123_read(mh, buf, sizeof(buf), &len);
81 switch (err) {
82 case MPG123_DONE:
83 ret = 0;
84 goto done;
85 case MPG123_NEW_FORMAT:
86 if (!setup(mh))
87 goto done;
88 break;
89 case MPG123_OK:
90 if (!play(buf, len, &seek)) {
91 ret = 1;
92 goto done;
93 }
94 break;
95 default:
96 log_warnx("error decoding mp3, "
97 "continuing nevertheless");
98 break;
99 }
102 done:
103 mpg123_delete(mh);
104 close(fd);
105 return ret;