summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--GNUmakefile36
-rw-r--r--src/sdl.c150
3 files changed, 187 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..6a3417b
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+/out/
diff --git a/GNUmakefile b/GNUmakefile
new file mode 100644
index 0000000..09bd738
--- /dev/null
+++ b/GNUmakefile
@@ -0,0 +1,36 @@
+#!/usr/bin/env -S gmake -f
+
+GLAD ?= glad
+MKDIR ?= mkdir -p
+
+libs ::= SDL2
+cflags ::= -I . -g -Og ${CFLAGS}
+ldflags ::= -Wl,--rpath,'$$ORIGIN' $(addprefix -l,${libs}) ${LDFLAGS}
+
+srcs ::= $(wildcard src/*.c)
+objs ::= $(addprefix out/,$(notdir ${srcs:.c=.o}))
+deps ::= $(addprefix out/,$(notdir ${srcs:.c=.d}))
+
+.PHONY: all run clean
+
+all: out/mu-sdl
+
+run: out/mu-sdl
+ ./$<
+
+clean:
+ ${RM} -r out/
+
+out/:
+ ${MKDIR} $@
+
+out/%.o: src/%.c out/%.d | out/
+ ${CC} -c -o $@ $< ${cflags}
+
+out/%.d: src/%.c | out/
+ ${CC} ${cflags} ${CPPFLAGS} -MM -MG -MF $@ -MT "${@:.d=.o} $@" $<
+
+out/mu-sdl: ${objs} | out/
+ ${CC} -o $@ $^ ${cflags} ${ldflags}
+
+include ${deps}
diff --git a/src/sdl.c b/src/sdl.c
new file mode 100644
index 0000000..0072c87
--- /dev/null
+++ b/src/sdl.c
@@ -0,0 +1,150 @@
+#define SDL_MAIN_HANDLED
+#include <SDL2/SDL.h>
+
+#include <stdbool.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <libopenmpt/libopenmpt.h>
+
+#define eprintf(...) fprintf(stderr, __VA_ARGS__)
+
+static const int WINDOW_WIDTH = 160, WINDOW_HEIGHT = 90;
+
+struct blob {
+ void *data;
+ size_t size;
+};
+
+SDL_Window *window = NULL;
+
+struct blob load_file(char const *const name);
+
+struct userdata {
+ SDL_AudioCallback callback;
+ void *user;
+} userdata = {
+ .callback = NULL,
+ .user = NULL,
+};
+
+void audio_callback(void *userdata_void, unsigned char *stream_void, int const length) {
+ struct userdata *user = userdata_void;
+ float *stream = (float *) stream_void;
+ if (user->callback == NULL) {
+ for (int i = 0; i < length / sizeof (float); i++) {
+ stream[i] = 0.0;
+ }
+ } else {
+ user->callback(user->user, stream_void, length);
+ }
+}
+
+int main(void) {
+ if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO)) {
+ eprintf("failed to init SDL: %s\n");
+ return EXIT_FAILURE;
+ }
+
+ SDL_StopTextInput();
+
+ if ((window = SDL_CreateWindow("mu-sdl", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, WINDOW_WIDTH, WINDOW_HEIGHT, SDL_WINDOW_RESIZABLE)) == NULL) {
+ eprintf("failed to create a window: %s\n");
+ SDL_Quit();
+ return EXIT_FAILURE;
+ }
+
+ SDL_AudioSpec desired = {
+ .freq = 48000,
+ .format = AUDIO_F32SYS,
+ .channels = 2,
+ .samples = 8096,
+ .callback = audio_callback,
+ .userdata = &userdata,
+ };
+ SDL_AudioDeviceID audio = SDL_OpenAudioDevice(NULL, 0, &desired, NULL, 0);
+
+ SDL_PauseAudioDevice(audio, 0);
+ while (true) {
+ SDL_Event evt;
+ while (SDL_PollEvent(&evt)) {
+ switch (evt.type) {
+ case SDL_QUIT:
+ goto done;
+
+ case SDL_KEYDOWN:
+ // ^Q
+ if (evt.key.keysym.sym == SDLK_q && evt.key.keysym.mod & KMOD_CTRL) {
+ goto done;
+ }
+ // ESC
+ if (evt.key.keysym.sym == SDLK_ESCAPE) {
+ goto done;
+ }
+ break;
+
+ case SDL_DROPFILE:
+ puts(evt.drop.file);
+ struct blob file = load_file(evt.drop.file);
+ if (file.data == NULL) {
+ perror(evt.drop.file);
+ SDL_free(evt.drop.file);
+ break;
+ }
+ SDL_free(evt.drop.file);
+ //SDL_LockAudioDevice(audio);
+ //openmpt_module *mod = openmpt_module_create_from_memory2(file.data, file.size, &libopenmpt_example_logfunc, NULL, &libopenmpt_example_errfunc, NULL, &mod_err, &mod_err_str, NULL);
+ //SDL_UnlockAudioDevice(audio);
+ free(file.data);
+ break;
+
+ default:
+ }
+ }
+ }
+ done:
+
+ SDL_DestroyWindow(window);
+
+ SDL_CloseAudioDevice(audio);
+
+ SDL_Quit();
+
+ return EXIT_SUCCESS;
+}
+
+struct blob load_file(char const *const name) {
+ const size_t START_SIZE = 1;
+ FILE *file = fopen(name, "rb");
+ if (file == NULL) {
+ return (struct blob) {.data = NULL};
+ }
+ void *data = malloc(START_SIZE);
+ size_t allocated = START_SIZE;
+ size_t used = 0;
+ while (1) {
+ size_t read = fread(data + used, 1, allocated - used, file);
+ if (read != allocated - used) {
+ used += read;
+ break;
+ }
+ used += read;
+ allocated *= 2;
+ void *const newdata = realloc(data, allocated);
+ if (newdata == NULL) {
+ goto realloc_error;
+ }
+ data = newdata;
+ }
+ void *const newdata = realloc(data, used);
+ if (newdata == NULL) {
+ goto realloc_error;
+ }
+ fclose(file);
+ return (struct blob) {.data = newdata, .size = used};
+
+ realloc_error:
+ free(data);
+ fclose(file);
+ return (struct blob) {.data = NULL};
+}