diff --git a/build.sh b/build.sh index 11f51d1..38b9e83 100755 --- a/build.sh +++ b/build.sh @@ -1,5 +1,11 @@ #!/bin/sh pushd build -gcc -o sdlamp2 -Wall -O0 -ggdb3 ../src/sdlamp2.c `sdl2-config --cflags --libs` + +gcc -Wall -O0 -ggdb3 \ + -o sdlamp2 \ + `sdl2-config --cflags --libs` \ + -lSDL2_image \ + ../src/sdlamp2.c + popd diff --git a/build/controls.png b/build/controls.png new file mode 100644 index 0000000..744affb Binary files /dev/null and b/build/controls.png differ diff --git a/src/sdlamp2.c b/src/sdlamp2.c index c52bdd8..1827d0d 100644 --- a/src/sdlamp2.c +++ b/src/sdlamp2.c @@ -1,9 +1,17 @@ #include "SDL.h" +#include "SDL_image.h" -static SDL_AudioDeviceID audio_device = 0; static SDL_Window *window = NULL; static SDL_Renderer *renderer = NULL; +static SDL_AudioDeviceID audio_device = 0; +static Uint8 *wavbuf = NULL; +static Uint32 wavlen = 0; +static SDL_AudioSpec wavspec; +static SDL_AudioStream *stream = NULL; +// static SDL_bool paused = SDL_TRUE; +static SDL_bool paused = SDL_FALSE; + static void panic_and_abort(const char *title, const char *text) { fprintf(stderr, "PANIC: %s ... %s\n", title, text); SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, title, text, window); @@ -11,10 +19,53 @@ static void panic_and_abort(const char *title, const char *text) { exit(1); } +static SDL_bool load_audio_file(const char *fname) { + SDL_FreeAudioStream(stream); + stream = NULL; + SDL_FreeWAV(wavbuf); + wavbuf = NULL; + wavlen = 0; + + if (SDL_LoadWAV(fname, &wavspec, &wavbuf, &wavlen) == NULL) { + SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Couldn't load wav file!", + SDL_GetError(), window); + return SDL_FALSE; + } + + stream = SDL_NewAudioStream(wavspec.format, wavspec.channels, wavspec.freq, + AUDIO_F32, 2, 48000); + if (!stream) { + SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, + "Couldn't create audio stream!", SDL_GetError(), + window); + SDL_FreeWAV(wavbuf); + wavbuf = NULL; + wavlen = 0; + } + + if (SDL_AudioStreamPut(stream, wavbuf, wavlen) == + -1) { // FIXME(m): graceful handling. + panic_and_abort("Audio stream put failed!", SDL_GetError()); + } + SDL_AudioStreamFlush(stream); // FIXME(m): error handling. + SDL_PauseAudioDevice(audio_device, paused); + + return SDL_TRUE; +} + int main(int argc, char **argv) { - Uint8 *wavbuf = NULL; - Uint32 wavlen = 0; - SDL_AudioSpec wavspec; + SDL_AudioSpec desired; + SDL_bool running = SDL_TRUE; + const SDL_Rect rewind_rect = {10, 10, 100, 100}; + const SDL_Rect stop_rect = {120, 10, 100, 100}; + const SDL_Rect play_pause_rect = {230, 10, 100, 100}; + const SDL_Rect fast_forward_rect = {340, 10, 100, 100}; + + const SDL_Rect rewind_symbol_rect = {0, 0, 200, 200}; + const SDL_Rect play_symbol_rect = {220, 0, 200, 200}; + const SDL_Rect fast_forward_symbol_rect = {440, 0, 200, 200}; + const SDL_Rect stop_symbol_rect = {0, 220, 200, 200}; + const SDL_Rect pause_symbol_rect = {220, 220, 200, 200}; if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) != 0) { panic_and_abort("SDL_Init failed!", SDL_GetError()); @@ -31,23 +82,35 @@ int main(int argc, char **argv) { panic_and_abort("SDL_CreateRenderer failed!", SDL_GetError()); } - if (SDL_LoadWAV("music.wav", &wavspec, &wavbuf, &wavlen) == NULL) { - panic_and_abort("Couldn't load wav file!", SDL_GetError()); - } - audio_device = SDL_OpenAudioDevice(NULL, 0, &wavspec, NULL, 0); + SDL_zero(desired); + desired.freq = 48000; + desired.format = AUDIO_F32; + desired.channels = 2; + desired.samples = 4096; + desired.callback = NULL; + + audio_device = SDL_OpenAudioDevice(NULL, 0, &desired, NULL, 0); if (audio_device == 0) { panic_and_abort("Could not open audio device!", SDL_GetError()); } - SDL_QueueAudio(audio_device, wavbuf, wavlen); - SDL_bool paused = SDL_TRUE; - const SDL_Rect rewind_rect = {100, 100, 100, 100}; - const SDL_Rect pause_rect = {400, 100, 100, 100}; + load_audio_file("music.wav"); + + SDL_Surface *controls_surface = IMG_Load("controls.png"); + if (controls_surface == NULL) { + panic_and_abort("Could not load controls asset!", SDL_GetError()); + } + + SDL_Texture *controls_texture = + SDL_CreateTextureFromSurface(renderer, controls_surface); + SDL_FreeSurface(controls_surface); + if (controls_texture == NULL) { + panic_and_abort("Could not load controls asset!", SDL_GetError()); + } - SDL_bool running = SDL_TRUE; SDL_Event e; - while (running) { + // Event loop while (SDL_PollEvent(&e)) { switch (e.type) { case SDL_QUIT: @@ -56,10 +119,17 @@ int main(int argc, char **argv) { case SDL_MOUSEBUTTONDOWN: { const SDL_Point pt = {e.button.x, e.button.y}; - if (SDL_PointInRect(&pt, &rewind_rect)) { + if (SDL_PointInRect(&pt, &rewind_rect)) { // Pressed the "rewind" button SDL_ClearQueuedAudio(audio_device); - SDL_QueueAudio(audio_device, wavbuf, wavlen); - } else if (SDL_PointInRect(&pt, &pause_rect)) { + SDL_AudioStreamClear(stream); + if (SDL_AudioStreamPut(stream, wavbuf, wavlen) == + -1) { // FIXME(m): graceful handling. + panic_and_abort("Audio stream put failed!", SDL_GetError()); + } + SDL_AudioStreamFlush(stream); // FIXME(m): error handling. + } else if (SDL_PointInRect( + &pt, + &play_pause_rect)) { // Pressed the "pause" button paused = paused ? SDL_FALSE : SDL_TRUE; SDL_PauseAudioDevice(audio_device, paused); } @@ -68,16 +138,45 @@ int main(int argc, char **argv) { } } - SDL_SetRenderDrawColor(renderer, 0, 0xFF, 0, 0xFF); + // Deal with audio + if (SDL_GetQueuedAudioSize(audio_device) < 8192) { + const int bytes_remaining = SDL_AudioStreamAvailable(stream); + if (bytes_remaining > 0) { + const int new_bytes = SDL_min(bytes_remaining, 32 * 1024); + static Uint8 converted_buffer[32 * 1024]; + SDL_AudioStreamGet(stream, converted_buffer, + new_bytes); // FIXME(m): error handling. + SDL_QueueAudio(audio_device, converted_buffer, new_bytes); + } + } + + // Deal with drawing to screen + SDL_SetRenderDrawColor(renderer, 0xFF, 0xFF, 0xFF, 0xFF); SDL_RenderClear(renderer); SDL_SetRenderDrawColor(renderer, 0xFF, 0xFF, 0xFF, 0xFF); SDL_RenderFillRect(renderer, &rewind_rect); - SDL_RenderFillRect(renderer, &pause_rect); + SDL_RenderFillRect(renderer, &stop_rect); + SDL_RenderFillRect(renderer, &play_pause_rect); + SDL_RenderFillRect(renderer, &fast_forward_rect); + + SDL_RenderCopy(renderer, controls_texture, &rewind_symbol_rect, + &rewind_rect); + SDL_RenderCopy(renderer, controls_texture, &stop_symbol_rect, &stop_rect); + if (paused) { + SDL_RenderCopy(renderer, controls_texture, &play_symbol_rect, + &play_pause_rect); + } else { + SDL_RenderCopy(renderer, controls_texture, &pause_symbol_rect, + &play_pause_rect); + } + SDL_RenderCopy(renderer, controls_texture, &fast_forward_symbol_rect, + &fast_forward_rect); SDL_RenderPresent(renderer); } + // Clean up SDL_FreeWAV(wavbuf); SDL_CloseAudioDevice(audio_device); SDL_DestroyRenderer(renderer);