summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorVito Caputo <vcaputo@pengaru.com>2020-07-31 14:22:09 -0700
committerVito Caputo <vcaputo@pengaru.com>2020-07-31 14:26:11 -0700
commite3d7338a979e1c2cba2328df5ac29856f4de1e0e (patch)
tree80a35955f1b79623a7c5ff0ec3cc5a6d00e11d72 /src
parentb4911c2abfa513e91c82a712ef277f7e6209b502 (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.c105
-rw-r--r--src/play.h8
2 files changed, 76 insertions, 37 deletions
diff --git a/src/play.c b/src/play.c
index ca51c2e..fdd1bd8 100644
--- a/src/play.c
+++ b/src/play.c
@@ -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;
diff --git a/src/play.h b/src/play.h
index 0f1d2da..73d3815 100644
--- a/src/play.h
+++ b/src/play.h
@@ -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);
© All Rights Reserved