diff options
author | Vito Caputo <vcaputo@pengaru.com> | 2020-07-31 14:22:09 -0700 |
---|---|---|
committer | Vito Caputo <vcaputo@pengaru.com> | 2020-07-31 14:26:11 -0700 |
commit | e3d7338a979e1c2cba2328df5ac29856f4de1e0e (patch) | |
tree | 80a35955f1b79623a7c5ff0ec3cc5a6d00e11d72 /src | |
parent | b4911c2abfa513e91c82a712ef277f7e6209b502 (diff) |
play: add flags to play_startup()
Introduce flags for disabling audio/video/gamecontroller caps
Most of the time, all of these will be desirable for a game. But
sometimes I might use this as a quick bootstrap into SDL land,
especially as I accumulate play_ops_t boilerplate I'd like to
be maximally reusable. The video-only use case is particularly
likely especially for development tools, and I'm likely to have
a corpus of play_ops_t integrations for the myriad GL/vulkan
flavors...
Note the flags are plumbed down to the play_ops_t.init hook so
ops implementations can also be flags-aware.
I didn't try make things like audio samplerate/channels
configurable, as this library is intended to be a vendored .a
anyways there's no hard ABI/API commitments. It can always
grow and evolve when the need arises.
Diffstat (limited to 'src')
-rw-r--r-- | src/play.c | 105 | ||||
-rw-r--r-- | src/play.h | 8 |
2 files changed, 76 insertions, 37 deletions
@@ -34,6 +34,7 @@ typedef struct play_t { Uint32 ticks_paused_at; unsigned ticks_paused:1; unsigned update_needed:1; + unsigned has_audio:1; const play_ops_t **ops; int n_ops; int context; @@ -51,6 +52,9 @@ void play_music_set(play_t *play, unsigned flags, const char *fmt, ...) Mix_Music *new; va_list ap; + assert(play); + assert(play->has_audio); + va_start(ap, fmt); vsnprintf(file, sizeof(file), fmt, ap); va_end(ap); @@ -140,12 +144,18 @@ static void music_finished(void) void play_music_pause(play_t *play) { + assert(play); + assert(play->has_audio); + Mix_PauseMusic(); } void play_music_resume(play_t *play) { + assert(play); + assert(play->has_audio); + Mix_ResumeMusic(); } @@ -268,11 +278,16 @@ void play_quit(play_t *play) /* This initializes a bunch of SDL stuff and calls all the ops.init() hooks * serially, in-order, before returning a handle to it all. + * * Note this doesn't create an SDL window or OpenGL context, as that's all * quite game-specific so it's left for presumably the first init hook. + * + * Flags may be used to disable audio/video/gamepad support, simply use empty flags + * to get all three. */ -play_t * play_startup(int argc, char *argv[], const play_ops_t *ops[]) +play_t * play_startup(int argc, char *argv[], unsigned flags, const play_ops_t *ops[]) { + Uint32 sdl_flags = 0; size_t n_ops; play_t *play; @@ -285,54 +300,74 @@ play_t * play_startup(int argc, char *argv[], const play_ops_t *ops[]) fatal_if(!play, "Unable to allocate play_t"); - fatal_if(SDL_Init(SDL_INIT_VIDEO|SDL_INIT_AUDIO|SDL_INIT_GAMECONTROLLER) != 0, + /* since it's expected that the vast majority of callers will want + * sound+video+gamecontroller this is inverted so those may pass + * empty flags, and instead the exceptions turn off which things + * they don't want. + */ + if (!(flags & PLAY_FLAG_NOAUDIO)) { + sdl_flags |= SDL_INIT_AUDIO; + play->has_audio = 1; + } + + if (!(flags & PLAY_FLAG_NOVIDEO)) + sdl_flags |= SDL_INIT_VIDEO; + + if (!(flags & PLAY_FLAG_NOGAMEPAD)) + sdl_flags |= SDL_INIT_GAMECONTROLLER; + + fatal_if(SDL_Init(sdl_flags) != 0, "Unable to initialize SDL"); fatal_if(atexit(SDL_Quit), "Unable to set exit handler"); - fatal_if(Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, 2, 2048) == -1, - "Unable to open audio"); - - __play_ptr_for_music_fixme = play; - Mix_HookMusicFinished(music_finished); - Mix_AllocateChannels(32); - - /* Just in case the user has dropped a game controller mapping */ - SDL_GameControllerAddMappingsFromFile("gamecontrollerdb.txt"); + if (play->has_audio) { + fatal_if(Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, 2, 2048) == -1, + "Unable to open audio"); - /* I don't want to get too crazy over here with controller handling, just open all - * the attached controllers at startup and get on with it. - */ - for (int i = 0; i < SDL_NumJoysticks(); ++i) { - SDL_GameController *controller; - char guid[64] = {}; - - SDL_JoystickGetGUIDString(SDL_JoystickGetDeviceGUID(i), guid, sizeof(guid)); - - if (!SDL_IsGameController(i)) { - fprintf(stderr, - "Ignoring unrecognized joystick \"%s\",\n" - "add a \"gamecontrollerdb.txt\" to use it.\n", - guid); - continue; - } + __play_ptr_for_music_fixme = play; + Mix_HookMusicFinished(music_finished); + Mix_AllocateChannels(32); + } - controller = SDL_GameControllerOpen(i); - warn_if(!controller, - "Could not open game controller \"%s\": %s", - guid, SDL_GetError()); + if (!(flags & PLAY_FLAG_NOGAMEPAD)) { + /* Just in case the user has dropped a game controller mapping */ + SDL_GameControllerAddMappingsFromFile("gamecontrollerdb.txt"); - /* XXX: For now I'm just opening all of them and losing their handles, - * it seems benign enough, the events will be delivered just the same. - * If the controller handle is needed for things then it gets more tricky.. + /* I don't want to get too crazy over here with controller handling, just open all + * the attached controllers at startup and get on with it. */ + for (int i = 0; i < SDL_NumJoysticks(); ++i) { + SDL_GameController *controller; + char guid[64] = {}; + + SDL_JoystickGetGUIDString(SDL_JoystickGetDeviceGUID(i), guid, sizeof(guid)); + + if (!SDL_IsGameController(i)) { + fprintf(stderr, + "Ignoring unrecognized joystick \"%s\",\n" + "add a \"gamecontrollerdb.txt\" to use it.\n", + guid); + continue; + } + + controller = SDL_GameControllerOpen(i); + warn_if(!controller, + "Could not open game controller \"%s\": %s", + guid, SDL_GetError()); + + /* XXX: For now I'm just opening all of them and losing their handles, + * it seems benign enough, the events will be delivered just the same. + * If the controller handle is needed for things then it gets more tricky.. + */ + } } for (size_t i = 0; i < n_ops; i++) { play->n_ops++; if (ops[i]->init) - play->contexts[i] = ops[i]->init(play, argc, argv); + play->contexts[i] = ops[i]->init(play, argc, argv, flags); } play->ops = ops; @@ -33,6 +33,10 @@ typedef enum play_ticks_t { PLAY_TICKS_CNT } play_ticks_t; +#define PLAY_FLAG_NOAUDIO (1L) +#define PLAY_FLAG_NOVIDEO (1L << 1) +#define PLAY_FLAG_NOGAMEPAD (1L << 2) + #define PLAY_MUSIC_FLAG_LOOP (1L) #define PLAY_MUSIC_FLAG_FADEIN (1L << 1) #define PLAY_MUSIC_FLAG_OPTIONAL (1L << 2) @@ -42,7 +46,7 @@ typedef enum play_ticks_t { typedef struct play_t play_t; typedef struct play_ops_t { - void * (*init)(play_t *play, int argc, char *argv[]); + void * (*init)(play_t *play, int argc, char *argv[], unsigned flags); void (*destroy)(play_t *play, void *context); void (*enter)(play_t *play, void *context); void (*leave)(play_t *play, void *context); @@ -51,7 +55,7 @@ typedef struct play_ops_t { void (*dispatch)(play_t *play, void *context, SDL_Event *event); } play_ops_t; -play_t * play_startup(int argc, char *argv[], const play_ops_t *ops[]); +play_t * play_startup(int argc, char *argv[], unsigned flags, const play_ops_t *ops[]); int play_shutdown(play_t *play); void play_run(play_t *play); |