commit 8bd14d100c8d07485d13211e89984e43183b874c
parent 88245add6512f3b9a56d1da40a7dcba2fcd97fed
Author: Louis Burda <quent.burda@gmail.com>
Date: Sun, 11 Dec 2022 21:59:48 +0100
Pulseaudio simple API version
Diffstat:
M | .gitignore | | | 3 | ++- |
M | Makefile | | | 21 | ++++++++++----------- |
M | compile_commands.json | | | 36 | ++++++++++++++++++------------------ |
D | src/main.c | | | 88 | ------------------------------------------------------------------------------- |
A | src/mplay.c | | | 102 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
5 files changed, 132 insertions(+), 118 deletions(-)
diff --git a/.gitignore b/.gitignore
@@ -1,2 +1,3 @@
.cache
-build/mplay
+mplay
+compile_commands.json
diff --git a/Makefile b/Makefile
@@ -1,19 +1,18 @@
CFLAGS = -g -I src -I lib/minimp3/
-LDLIBS =
+LDLIBS = -lpulse -lpulse-simple
-.PHONY: all clean
-
-all: build/mplay
+all: mplay
clean:
- rm -rf build
+ rm -f mplay
-build:
- mkdir build
+mplay: src/mplay.c
+ $(CC) -o $@ $^ $(CFLAGS) $(LDLIBS)
-build/%.o: src/%.c src/%.h | build
- $(CC) -o $@ -c $< $(CFLAGS) $(LDLIBS)
+install:
+ install -m755 -t mplay "$(DESTDIR)$(PREFIX)$(BINDIR)"
-build/mplay: src/main.c | build
- $(CC) -o $@ $^ $(CFLAGS) $(LDLIBS)
+uninstall:
+ rm -f "$(DESTDIR)$(PREFIX)$(BINDIR)/mplay"
+.PHONY: all clean install uninstall
diff --git a/compile_commands.json b/compile_commands.json
@@ -1,18 +1,19 @@
[
- {
- "arguments": [
- "cc",
- "-c",
- "-g",
- "-I",
- "src",
- "-I",
- "lib/minimp3/",
- "-o",
- "build/mplay",
- "src/main.c"
- ],
- "directory": "/snxdata/lib/dev/mplay",
- "file": "src/main.c"
- }
-]
-\ No newline at end of file
+ {
+ "arguments": [
+ "/usr/bin/cc",
+ "-c",
+ "-g",
+ "-I",
+ "src",
+ "-I",
+ "lib/minimp3/",
+ "-o",
+ "build/mplay",
+ "src/mplay.c"
+ ],
+ "directory": "/snx/dev/mplay",
+ "file": "/snx/dev/mplay/src/mplay.c",
+ "output": "/snx/dev/mplay/build/mplay"
+ }
+]
diff --git a/src/main.c b/src/main.c
@@ -1,88 +0,0 @@
-#define MINIMP3_IMPLEMENTATION
-#include "minimp3.h"
-#include "pulse/error.h"
-#include "pulse/simple.h"
-
-#include <stdint.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-static uint8_t *read_file(const char *filename, size_t *len);
-static void play_file(const char *filename);
-static void daemon(void);
-
-uint8_t *
-read_file(const char *filename, size_t *len)
-{
- FILE *f;
- uint8_t *buf;
- size_t start;
-
- f = fopen(filename, "r");
- if (f == NULL)
- ERROR("Failed to open file\n");
-
- fseek(f, 0, SEEK_END);
- *len = ftell(f) - start;
-
- buf = malloc(*len);
- OOM_CHECK(buf);
-
- fseek(f, 0, SEEK_SET);
- if (fread(buf, 1, *len, f) != len)
- ERROR("Failed to read file contents\n");
-
- fclose(f);
-
- return buf;
-}
-
-void
-play_file(const char *filename)
-{
- static const pa_sample_spec spec = {
- .format = PA_SAMPLE_S16LE,
- .rate = 44100,
- .channels = 2
- };
- mp3dec_frame_info_t info;
- mp3d_sample_t sample;
- mp3dec_t dec;
- pa_simple *stream;
- uint8_t *data;
- size_t len;
- int status, ret;
-
- data = read_file(filename, &len);
-
- mp3dec_init(&dec);
-
- stream = pa_simple_new(NULL, "MPLAY", PA_STREAM_PLAYBACK, NULL,
- "playback", &spec, NULL, NULL, &status);
- // check status
-
- while (mp3dec_decode_frame(&dec, data, len, &sample, &info)) {
- pa_simple_write();
- }
-
- ret = pa_simple_drain(stream, &status);
- if (!ret) ERROR("Failed to drain rest of audio\n");
-
- pa_simple_free(stream);
-}
-
-void
-daemon(void)
-{
-
-}
-
-int
-main(int argc, const char **argv)
-{
- if (argc != 2)
- ERROR("USAGE: mplay FILE\n");
-
- play_file(argv[1]);
-}
diff --git a/src/mplay.c b/src/mplay.c
@@ -0,0 +1,102 @@
+#include "pulse/simple.h"
+#include "pulse/volume.h"
+#include "pulse/error.h"
+
+#define MINIMP3_IMPLEMENTATION
+#include "minimp3.h"
+
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <err.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+static uint8_t *map_file(const char *path, size_t *len);
+static void play_file(const char *path);
+
+static const pa_sample_spec pa_spec = {
+ .format = PA_SAMPLE_S16LE,
+ .rate = 44100,
+ .channels = 2
+};
+
+uint8_t *
+map_file(const char *path, size_t *len)
+{
+ struct stat attr;
+ uint8_t *buf;
+ int fd;
+
+ fd = open(path, O_RDONLY);
+ if (fd < 0) err(1, "open %s", path);
+
+ if (fstat(fd, &attr))
+ err(1, "fstat %s", path);
+
+ buf = mmap(NULL, attr.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
+ if (!buf) err(1, "mmap %s", path);
+
+ *len = attr.st_size;
+
+ close(fd);
+
+ return buf;
+}
+
+void
+play_file(const char *filename)
+{
+ mp3dec_frame_info_t info;
+ mp3d_sample_t samples[MINIMP3_MAX_SAMPLES_PER_FRAME];
+ mp3dec_t mp3d;
+ pa_simple *pa;
+ uint8_t *data, *pos;
+ size_t len;
+ int pa_err;
+ int ret;
+ int cnt;
+
+ data = map_file(filename, &len);
+
+ mp3dec_init(&mp3d);
+
+ pa = pa_simple_new(NULL, "mplay", PA_STREAM_PLAYBACK, NULL,
+ "playback", &pa_spec, NULL, NULL, &pa_err);
+ if (!pa) errx(1, "pa_simple_new: %s", pa_strerror(pa_err));
+
+ pos = data;
+ while (pos < data + len) {
+ cnt = mp3dec_decode_frame(&mp3d, pos, len, samples, &info);
+ if (!cnt && !info.frame_bytes) break;
+
+ pos += info.frame_bytes;
+ if (!cnt) continue;
+
+ ret = pa_simple_write(pa, samples,
+ cnt * info.channels * sizeof(mp3d_sample_t), &pa_err);
+ if (ret) errx(1, "pa_simple_write: %s", pa_strerror(pa_err));
+ }
+
+ ret = pa_simple_drain(pa, &pa_err);
+ if (ret) errx(1, "pa_simple_drain: %s", pa_strerror(pa_err));
+
+ pa_simple_free(pa);
+
+ munmap(data, len);
+}
+
+int
+main(int argc, const char **argv)
+{
+ if (argc != 2) {
+ printf("USAGE: mplay FILE\n");
+ exit(1);
+ }
+
+ play_file(argv[1]);
+}
+