mirror of
https://github.com/mauiaaron/apple2.git
synced 2024-12-26 15:29:19 +00:00
Allow CLI dynamic choice of A/V backends
This commit is contained in:
parent
2517b45720
commit
8e6701bcbb
@ -539,6 +539,10 @@ static long openal_systemShutdown(INOUT AudioContext_s **audio_context) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char *openal_systemName(void) {
|
||||
return "OpenAL";
|
||||
}
|
||||
|
||||
static long openal_systemSetup(INOUT AudioContext_s **audio_context) {
|
||||
assert(*audio_context == NULL);
|
||||
assert(voices == NULL);
|
||||
@ -625,6 +629,7 @@ static long openal_systemResume(AudioContext_s *audio_context) {
|
||||
|
||||
static void _init_openal(void) {
|
||||
LOG("Initializing OpenAL sound system");
|
||||
openal_audio_backend.name = &openal_systemName;
|
||||
openal_audio_backend.setup = &openal_systemSetup;
|
||||
openal_audio_backend.shutdown = &openal_systemShutdown;
|
||||
openal_audio_backend.pause = &openal_systemPause;
|
||||
|
@ -526,6 +526,10 @@ static long opensles_systemShutdown(AudioContext_s **audio_context) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char *opensles_systemName(void) {
|
||||
return "OpenSLES";
|
||||
}
|
||||
|
||||
static long opensles_systemSetup(INOUT AudioContext_s **audio_context) {
|
||||
assert(*audio_context == NULL);
|
||||
|
||||
@ -760,6 +764,7 @@ static long opensles_systemResume(AudioContext_s *audio_context) {
|
||||
|
||||
static void _init_opensl(void) {
|
||||
LOG("Initializing OpenSLES sound system");
|
||||
opensles_audio_backend.name = &opensles_systemName;
|
||||
opensles_audio_backend.setup = &opensles_systemSetup;
|
||||
opensles_audio_backend.shutdown = &opensles_systemShutdown;
|
||||
opensles_audio_backend.pause = &opensles_systemPause;
|
||||
|
@ -34,6 +34,8 @@ typedef struct backend_node_s {
|
||||
|
||||
static backend_node_s *head = NULL;
|
||||
|
||||
static AudioBackend_s *currentBackend = NULL;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
long audio_createSoundBuffer(INOUT AudioBuffer_s **audioBuffer) {
|
||||
@ -82,10 +84,10 @@ bool audio_init(void) {
|
||||
|
||||
do {
|
||||
if (audioContext) {
|
||||
audio_getCurrentBackend()->shutdown(&audioContext);
|
||||
currentBackend->shutdown(&audioContext);
|
||||
}
|
||||
|
||||
long err = audio_getCurrentBackend()->setup((AudioContext_s**)&audioContext);
|
||||
long err = currentBackend->setup((AudioContext_s**)&audioContext);
|
||||
if (err) {
|
||||
LOG("Failed to create an audio context!");
|
||||
break;
|
||||
@ -103,7 +105,7 @@ void audio_shutdown(void) {
|
||||
if (!audio_isAvailable) {
|
||||
return;
|
||||
}
|
||||
audio_getCurrentBackend()->shutdown(&audioContext);
|
||||
currentBackend->shutdown(&audioContext);
|
||||
audio_isAvailable = false;
|
||||
}
|
||||
|
||||
@ -118,7 +120,7 @@ void audio_pause(void) {
|
||||
if (!audio_isAvailable) {
|
||||
return;
|
||||
}
|
||||
audio_getCurrentBackend()->pause(audioContext);
|
||||
currentBackend->pause(audioContext);
|
||||
}
|
||||
|
||||
void audio_resume(void) {
|
||||
@ -127,7 +129,7 @@ void audio_resume(void) {
|
||||
if (!audio_isAvailable) {
|
||||
return;
|
||||
}
|
||||
audio_getCurrentBackend()->resume(audioContext);
|
||||
currentBackend->resume(audioContext);
|
||||
}
|
||||
|
||||
void audio_setLatency(float latencySecs) {
|
||||
@ -141,9 +143,6 @@ float audio_getLatency(void) {
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void audio_registerBackend(AudioBackend_s *backend, long order) {
|
||||
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
pthread_mutex_lock(&mutex);
|
||||
|
||||
backend_node_s *node = MALLOC(sizeof(backend_node_s));
|
||||
assert(node);
|
||||
node->next = NULL;
|
||||
@ -163,11 +162,46 @@ void audio_registerBackend(AudioBackend_s *backend, long order) {
|
||||
}
|
||||
node->next = p;
|
||||
|
||||
pthread_mutex_unlock(&mutex);
|
||||
currentBackend = head->backend;
|
||||
}
|
||||
|
||||
void audio_printBackends(FILE *out) {
|
||||
backend_node_s *p = head;
|
||||
int count = 0;
|
||||
while (p) {
|
||||
const char *name = p->backend->name();
|
||||
if (count++) {
|
||||
fprintf(out, "|");
|
||||
}
|
||||
fprintf(out, "%s", name);
|
||||
p = p->next;
|
||||
}
|
||||
}
|
||||
|
||||
static const char *_null_backend_name(void);
|
||||
void audio_chooseBackend(const char *name) {
|
||||
if (!name) {
|
||||
name = _null_backend_name();
|
||||
}
|
||||
|
||||
backend_node_s *p = head;
|
||||
while (p) {
|
||||
const char *bname = p->backend->name();
|
||||
if (strcasecmp(name, bname) == 0) {
|
||||
currentBackend = p->backend;
|
||||
LOG("Setting current audio backend to %s", name);
|
||||
break;
|
||||
}
|
||||
p = p->next;
|
||||
}
|
||||
}
|
||||
|
||||
AudioBackend_s *audio_getCurrentBackend(void) {
|
||||
return head->backend;
|
||||
return currentBackend;
|
||||
}
|
||||
|
||||
static const char *_null_backend_name(void) {
|
||||
return "none";
|
||||
}
|
||||
|
||||
static long _null_backend_setup(INOUT AudioContext_s **audio_context) {
|
||||
@ -191,6 +225,7 @@ static long _null_backend_resume(AudioContext_s *audio_context) {
|
||||
static void _init_soundcore(void) {
|
||||
LOG("Initializing audio subsystem");
|
||||
static AudioBackend_s null_backend = { { 0 } };
|
||||
null_backend.name = &_null_backend_name;
|
||||
null_backend.setup = &_null_backend_setup;
|
||||
null_backend.shutdown = &_null_backend_shutdown;
|
||||
null_backend.pause = &_null_backend_pause;
|
||||
|
@ -137,6 +137,8 @@ typedef struct AudioBackend_s {
|
||||
|
||||
AudioSettings_s systemSettings;
|
||||
|
||||
const char *(*name)(void);
|
||||
|
||||
// basic backend functionality controlled by soundcore
|
||||
PRIVATE long (*setup)(INOUT AudioContext_s **audio_context);
|
||||
PRIVATE long (*shutdown)(INOUT AudioContext_s **audio_context);
|
||||
@ -155,6 +157,10 @@ enum {
|
||||
|
||||
void audio_registerBackend(AudioBackend_s *backend, long prio);
|
||||
|
||||
void audio_printBackends(FILE *out);
|
||||
|
||||
void audio_chooseBackend(const char *name);
|
||||
|
||||
AudioBackend_s *audio_getCurrentBackend(void);
|
||||
|
||||
#endif /* whole file */
|
||||
|
43
src/misc.c
43
src/misc.c
@ -44,6 +44,43 @@ static void _init_common(void) {
|
||||
static __attribute__((constructor)) void __init_common(void) {
|
||||
emulator_registerStartupCallback(CTOR_PRIORITY_FIRST, &_init_common);
|
||||
}
|
||||
|
||||
static void _cli_help(void) {
|
||||
fprintf(stderr, "\n");
|
||||
fprintf(stderr, "Usage: %s [-A <audio>] [-V <video>]\n", argv[0]);
|
||||
|
||||
const char *aname = audio_getCurrentBackend()->name();
|
||||
fprintf(stderr, "\t-A <");
|
||||
audio_printBackends(stderr);
|
||||
fprintf(stderr, "> -- choose audio renderer (default: %s)\n", aname);
|
||||
|
||||
const char *vname = video_getCurrentBackend()->name();
|
||||
fprintf(stderr, "\t-V <");
|
||||
video_printBackends(stderr);
|
||||
fprintf(stderr, "> -- choose video renderer (default: %s)\n", vname);
|
||||
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
|
||||
static void _cli_argsToPrefs(void) {
|
||||
int opt = -1;
|
||||
while ((opt = getopt(argc, argv, "?hA:V:")) != -1) {
|
||||
switch (opt) {
|
||||
case 'A':
|
||||
audio_chooseBackend(optarg);
|
||||
break;
|
||||
case 'V':
|
||||
video_chooseBackend(optarg);
|
||||
break;
|
||||
case '?':
|
||||
case 'h':
|
||||
default:
|
||||
_cli_help();
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined(ANDROID) || (TARGET_OS_MAC || TARGET_OS_PHONE)
|
||||
// data_dir is set up elsewhere
|
||||
#else
|
||||
@ -371,6 +408,10 @@ void emulator_start(void) {
|
||||
prefs_load(); // user prefs
|
||||
prefs_sync(NULL);
|
||||
|
||||
#if defined(CONFIG_DATADIR)
|
||||
_cli_argsToPrefs();
|
||||
#endif
|
||||
|
||||
#if defined(INTERFACE_CLASSIC) && !TESTING
|
||||
c_keys_set_key(kF8); // show credits before emulation start
|
||||
#endif
|
||||
@ -439,7 +480,7 @@ int main(int _argc, char **_argv) {
|
||||
|
||||
LOG("Emulator exit ...");
|
||||
|
||||
return 0;
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -138,10 +138,17 @@ static void _glnode_initGLUTPost(void) {
|
||||
}
|
||||
#endif
|
||||
|
||||
static const char *glnode_name(void) {
|
||||
return "OpenGL";
|
||||
}
|
||||
|
||||
static void glnode_setupNodes(void *ctx) {
|
||||
LOG("BEGIN glnode_setupNodes ...");
|
||||
|
||||
#if USE_GLUT
|
||||
# if !TEST_CPU
|
||||
joydriver_resetJoystick = &_glutJoystickReset;
|
||||
# endif
|
||||
_glnode_initGLUTPre();
|
||||
#endif
|
||||
|
||||
@ -238,6 +245,7 @@ static void glnode_mainLoop(void) {
|
||||
static void _init_glnode_manager(void) {
|
||||
LOG("Initializing GLNode manager subsystem");
|
||||
|
||||
glnode_backend.name = &glnode_name;
|
||||
glnode_backend.init = &glnode_setupNodes;
|
||||
glnode_backend.main_loop = &glnode_mainLoop;
|
||||
glnode_backend.render = &glnode_renderNodes;
|
||||
@ -248,10 +256,6 @@ static void _init_glnode_manager(void) {
|
||||
interface_onTouchEvent = &glnode_onTouchEvent;
|
||||
#endif
|
||||
|
||||
#if USE_GLUT && !TEST_CPU
|
||||
joydriver_resetJoystick = &_glutJoystickReset;
|
||||
#endif
|
||||
|
||||
video_registerBackend(&glnode_backend, VID_PRIO_GRAPHICS_GL);
|
||||
}
|
||||
|
||||
|
@ -111,9 +111,6 @@ bool video_loadState(StateHelper_s *helper) {
|
||||
void video_registerBackend(video_backend_s *backend, long order) {
|
||||
assert(!video_initialized); // backends cannot be registered after we've picked one to use
|
||||
|
||||
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
pthread_mutex_lock(&mutex);
|
||||
|
||||
backend_node_s *node = MALLOC(sizeof(backend_node_s));
|
||||
assert(node);
|
||||
node->next = NULL;
|
||||
@ -134,17 +131,54 @@ void video_registerBackend(video_backend_s *backend, long order) {
|
||||
node->next = p;
|
||||
|
||||
currentBackend = head->backend;
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&mutex);
|
||||
void video_printBackends(FILE *out) {
|
||||
backend_node_s *p = head;
|
||||
int count = 0;
|
||||
while (p) {
|
||||
const char *name = p->backend->name();
|
||||
if (count++) {
|
||||
fprintf(out, "|");
|
||||
}
|
||||
fprintf(out, "%s", name);
|
||||
p = p->next;
|
||||
}
|
||||
}
|
||||
|
||||
static const char *_null_backend_name(void);
|
||||
void video_chooseBackend(const char *name) {
|
||||
if (!name) {
|
||||
name = _null_backend_name();
|
||||
}
|
||||
|
||||
backend_node_s *p = head;
|
||||
while (p) {
|
||||
const char *bname = p->backend->name();
|
||||
if (strcasecmp(name, bname) == 0) {
|
||||
currentBackend = p->backend;
|
||||
LOG("Setting current video backend to %s", name);
|
||||
break;
|
||||
}
|
||||
p = p->next;
|
||||
}
|
||||
}
|
||||
|
||||
video_animation_s *video_getAnimationDriver(void) {
|
||||
return currentBackend->anim;
|
||||
}
|
||||
|
||||
video_backend_s *video_getCurrentBackend(void) {
|
||||
return currentBackend;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// NULL video backend ...
|
||||
|
||||
static const char *_null_backend_name(void) {
|
||||
return "none";
|
||||
}
|
||||
|
||||
static void _null_backend_init(void *context) {
|
||||
}
|
||||
|
||||
@ -163,6 +197,7 @@ static void _null_backend_shutdown(void) {
|
||||
|
||||
static __attribute__((constructor)) void _init_video(void) {
|
||||
static video_backend_s null_backend = { 0 };
|
||||
null_backend.name = &_null_backend_name;
|
||||
null_backend.init = &_null_backend_init;
|
||||
null_backend.main_loop = &_null_backend_main_loop;
|
||||
null_backend.render = &_null_backend_render;
|
||||
|
@ -115,6 +115,7 @@ video_animation_s *video_getAnimationDriver(void);
|
||||
// Video Backend API
|
||||
|
||||
typedef struct video_backend_s {
|
||||
const char *(*name)(void);
|
||||
void (*init)(void *context);
|
||||
void (*main_loop)(void);
|
||||
void (*render)(void);
|
||||
@ -142,9 +143,15 @@ enum {
|
||||
};
|
||||
|
||||
/*
|
||||
* Register a video backend at the specific prioritization, regardless of user choice.
|
||||
* Register a video backend at the specific prioritization
|
||||
*/
|
||||
void video_registerBackend(video_backend_s *backend, long prio);
|
||||
|
||||
void video_printBackends(FILE *out);
|
||||
|
||||
void video_chooseBackend(const char *name);
|
||||
|
||||
video_backend_s *video_getCurrentBackend(void);
|
||||
|
||||
#endif /* !A2_VIDEO_H */
|
||||
|
||||
|
@ -639,6 +639,10 @@ static void _redo_image(void) {
|
||||
_size_hints_set_fixed();
|
||||
}
|
||||
|
||||
static const char *xdriver_name(void) {
|
||||
return "X11";
|
||||
}
|
||||
|
||||
static void xdriver_init(void *context) {
|
||||
XSetWindowAttributes attribs;
|
||||
unsigned long attribmask;
|
||||
@ -888,6 +892,7 @@ static void _init_xvideo(void) {
|
||||
|
||||
static video_backend_s xvideo_backend = { 0 };
|
||||
static video_animation_s xdriver_animations = { 0 };
|
||||
xvideo_backend.name = &xdriver_name;
|
||||
xvideo_backend.init = &xdriver_init;
|
||||
xvideo_backend.main_loop = &xdriver_main_loop;
|
||||
xvideo_backend.render = &xdriver_render;
|
||||
|
Loading…
Reference in New Issue
Block a user