#define SDL_MAIN_HANDLED #include #include #include #include #include "include.h" #include "common/common.h" #define eprintf(...) fprintf(stderr, __VA_ARGS__) static const int WINDOW_WIDTH = 160, WINDOW_HEIGHT = 90; SDL_Window *window = NULL; int paused = 0; struct blob load_file(char const *const name); struct userdata 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 (*file_ext(char *file))(struct blob *, struct userdata *); int main(int argc, char **argv) { 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 | SDL_WINDOW_HIDDEN)) == NULL) { eprintf("failed to create a window: %s\n"); SDL_Quit(); return EXIT_FAILURE; } SDL_Renderer *renderer; if ((renderer = SDL_CreateRenderer(window, -1, 0)) == NULL) { eprintf("failed to create a renderer: %s\n"); SDL_DestroyWindow(window); SDL_Quit(); return EXIT_FAILURE; } SDL_ShowWindow(window); SDL_SetRenderDrawColor(renderer, 0, 0, 0, SDL_ALPHA_OPAQUE); SDL_RenderClear(renderer); SDL_RenderPresent(renderer); SDL_AudioSpec desired = { .freq = SAMPLE_RATE, .format = AUDIO_F32SYS, .channels = OUT_CHANNELS, .samples = 8096, .callback = audio_callback, .userdata = &userdata, }; SDL_AudioDeviceID audio = SDL_OpenAudioDevice(NULL, 0, &desired, NULL, 0); if (argc == 2) { int (*module_func)(struct blob *, struct userdata *) = file_ext(argv[1]); if (module_func == NULL) { eprintf("%s: unrecognized file extension\n", argv[1]); goto arg_load_done; } struct blob file = load_file(argv[1]); if (file.data == NULL) { perror(argv[1]); goto arg_load_done; } module_func(&file, &userdata); } arg_load_done: SDL_PauseAudioDevice(audio, 0); while (true) { SDL_Event evt; while (SDL_PollEvent(&evt)) { switch (evt.type) { case SDL_QUIT: goto done; case SDL_WINDOWEVENT: SDL_RenderClear(renderer); SDL_RenderPresent(renderer); break; 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; } if (evt.key.keysym.sym == SDLK_SPACE) { paused = !paused; SDL_PauseAudioDevice(audio, paused); } 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; } struct userdata newuser = {.callback = NULL, .freefunc = NULL}; int (*module_func)(struct blob *, struct userdata *) = file_ext(evt.drop.file); if (module_func == NULL) { eprintf("%s: unrecognized file extension\n", evt.drop.file); free(file.data); break; } SDL_free(evt.drop.file); if (module_func(&file, &newuser)) { // error } else { SDL_LockAudioDevice(audio); if (userdata.freefunc != NULL) { userdata.freefunc(userdata.user); } userdata = newuser; SDL_UnlockAudioDevice(audio); } free(file.data); break; default: } } } done: if (userdata.freefunc != NULL) { SDL_LockAudioDevice(audio); userdata.freefunc(userdata.user); SDL_PauseAudioDevice(audio, 1); SDL_UnlockAudioDevice(audio); } SDL_DestroyRenderer(renderer); SDL_DestroyWindow(window); SDL_CloseAudioDevice(audio); SDL_Quit(); return EXIT_SUCCESS; }