diff --git a/frontend/frontend.c b/frontend/frontend.c index 1380f638f5..63dc85c9fc 100644 --- a/frontend/frontend.c +++ b/frontend/frontend.c @@ -93,7 +93,7 @@ static void rarch_get_environment_console(void) #if defined(ANDROID) #define main_entry android_app_entry -#define returntype void* +#define returntype void #define signature() void* data #define returnfunc() exit(0) #define return_negative() return diff --git a/frontend/frontend_android.c b/frontend/frontend_android.c deleted file mode 100644 index b5a69cd8fa..0000000000 --- a/frontend/frontend_android.c +++ /dev/null @@ -1,456 +0,0 @@ -/* RetroArch - A frontend for libretro. - * Copyright (C) 2010-2013 - Hans-Kristian Arntzen - * Copyright (C) 2011-2013 - Daniel De Matteis - * Copyright (C) 2012-2013 - Michael Lelli - * - * RetroArch is free software: you can redistribute it and/or modify it under the terms - * of the GNU General Public License as published by the Free Software Found- - * ation, either version 3 of the License, or (at your option) any later version. - * - * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR - * PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along with RetroArch. - * If not, see . - */ - -#include -#include -#include -#include -#include - -#include "frontend_android.h" -#include "../general.h" -#include "../performance.h" -#include "../driver.h" -#include "menu/rmenu.h" - -#include "../config.def.h" -#include "frontend_context.h" - -frontend_ctx_driver_t *frontend_ctx; - -#if defined(ANDROID) -#define main_entry android_app_entry -#define returntype void* -#define signature() void* data -#define returnfunc() exit(0) -#define return_negative() return -#define return_var(var) return -#define declare_argc() int argc = 0 -#define declare_argv() char *argv[1] -#define args_type() struct android_app* -#define args_initial_ptr() data -#elif defined(IOS) || defined(OSX) || defined(HAVE_BB10) -#define main_entry rarch_main -#define returntype int -#define signature() int argc, char *argv[] -#define returnfunc() return 0 -#define return_negative() return 1 -#define return_var(var) return var -#define declare_argc() -#define declare_argv() -#define args_type() void* -#define args_initial_ptr() NULL -#else -#define main_entry main -#define returntype int -#define signature() int argc, char *argv[] -#define returnfunc() return 0 -#define return_negative() return 1 -#define return_var(var) return var -#define declare_argc() -#define declare_argv() -#define args_type() void* -#define args_initial_ptr() NULL -#endif - -#if defined(HAVE_BB10) || defined(ANDROID) -#define ra_preinited true -#else -#define ra_preinited false -#endif - -#if defined(HAVE_BB10) || defined(RARCH_CONSOLE) -#define attempt_load_game false -#else -#define attempt_load_game true -#endif - -#if defined(RARCH_CONSOLE) || defined(HAVE_BB10) || defined(ANDROID) -#define initial_menu_lifecycle_state (1ULL << MODE_LOAD_GAME) -#else -#define initial_menu_lifecycle_state (1ULL << MODE_GAME) -#endif - -#if !defined(RARCH_CONSOLE) && !defined(HAVE_BB10) && !defined(ANDROID) -#define attempt_load_game_push_history false -#else -#define attempt_load_game_push_history true -#endif - -#ifndef RARCH_CONSOLE -#define rarch_get_environment_console() (void)0 -#endif - -#if defined(RARCH_CONSOLE) || defined(__QNX__) || defined(ANDROID) -#define attempt_load_game_fails (1ULL << MODE_MENU) -#else -#define attempt_load_game_fails (1ULL << MODE_EXIT) -#endif - -static void android_app_entry(void *data) -{ - declare_argc(); - declare_argv(); - args_type() args = (args_type())args_initial_ptr(); - unsigned i; - frontend_ctx = (frontend_ctx_driver_t*)frontend_ctx_init_first(); - - if (frontend_ctx && frontend_ctx->init) - frontend_ctx->init(args); - - if (!ra_preinited) - { - rarch_main_clear_state(); - rarch_init_msg_queue(); - } - - if (frontend_ctx && frontend_ctx->environment_get) - { - frontend_ctx->environment_get(argc, argv, args); - rarch_get_environment_console(); - } - - if (attempt_load_game) - { - int init_ret; - if ((init_ret = rarch_main_init(argc, argv))) return_var(init_ret); - } - -#if defined(HAVE_MENU) || defined(HAVE_BB10) - menu_init(); - - if (frontend_ctx && frontend_ctx->process_args) - frontend_ctx->process_args(argc, argv, args); - - g_extern.lifecycle_mode_state |= initial_menu_lifecycle_state; - - if (attempt_load_game_push_history) - { - // If we started a ROM directly from command line, - // push it to ROM history. - if (!g_extern.libretro_dummy) - menu_rom_history_push_current(); - } - - for (;;) - { - if (g_extern.system.shutdown) - break; - else if (g_extern.lifecycle_mode_state & (1ULL << MODE_LOAD_GAME)) - { - load_menu_game_prepare(); - - // If ROM load fails, we exit RetroArch. On console it might make more sense to go back to menu though ... - if (load_menu_game()) - g_extern.lifecycle_mode_state |= (1ULL << MODE_GAME); - else - { - g_extern.lifecycle_mode_state = attempt_load_game_fails; - - if (g_extern.lifecycle_mode_state & (1ULL << MODE_EXIT)) - { - if (frontend_ctx && frontend_ctx->shutdown) - frontend_ctx->shutdown(true); - - return_negative(); - } - } - - g_extern.lifecycle_mode_state &= ~(1ULL << MODE_LOAD_GAME); - } - else if (g_extern.lifecycle_mode_state & (1ULL << MODE_GAME)) - { - if (driver.video_poke->set_aspect_ratio) - driver.video_poke->set_aspect_ratio(driver.video_data, g_settings.video.aspect_ratio_idx); - - while ((g_extern.is_paused && !g_extern.is_oneshot) ? rarch_main_idle_iterate() : rarch_main_iterate()) - { - if (frontend_ctx && frontend_ctx->process_events) - frontend_ctx->process_events(args); - - if (!(g_extern.lifecycle_mode_state & (1ULL << MODE_GAME))) - break; - } - g_extern.lifecycle_mode_state &= ~(1ULL << MODE_GAME); - } - else if (g_extern.lifecycle_mode_state & (1ULL << MODE_MENU)) - { - g_extern.lifecycle_mode_state |= 1ULL << MODE_MENU_PREINIT; - // Menu should always run with vsync on. - video_set_nonblock_state_func(false); - // Stop all rumbling when entering RGUI. - for (i = 0; i < MAX_PLAYERS; i++) - { - driver_set_rumble_state(i, RETRO_RUMBLE_STRONG, 0); - driver_set_rumble_state(i, RETRO_RUMBLE_WEAK, 0); - } - - // Override keyboard callback to redirect to menu instead. - // We'll use this later for something ... - // FIXME: This should probably be moved to menu_common somehow. - retro_keyboard_event_t key_event = g_extern.system.key_event; - g_extern.system.key_event = menu_key_event; - - if (driver.audio_data) - audio_stop_func(); - - while (!g_extern.system.shutdown && menu_iterate()) - { - if (frontend_ctx && frontend_ctx->process_events) - frontend_ctx->process_events(args); - - if (!(g_extern.lifecycle_mode_state & (1ULL << MODE_MENU))) - break; - } - - driver_set_nonblock_state(driver.nonblock_state); - - if (driver.audio_data && !g_extern.audio_data.mute && !audio_start_func()) - { - RARCH_ERR("Failed to resume audio driver. Will continue without audio.\n"); - g_extern.audio_active = false; - } - - g_extern.lifecycle_mode_state &= ~(1ULL << MODE_MENU); - - // Restore libretro keyboard callback. - g_extern.system.key_event = key_event; - } - else - break; - } - - g_extern.system.shutdown = false; - menu_free(); - - if (g_extern.config_save_on_exit && *g_extern.config_path) - config_save_file(g_extern.config_path); -#else - while ((g_extern.is_paused && !g_extern.is_oneshot) ? rarch_main_idle_iterate() : rarch_main_iterate()); -#endif - - rarch_main_deinit(); - rarch_deinit_msg_queue(); - global_uninit_drivers(); - -#ifdef PERF_TEST - rarch_perf_log(); -#endif - -#if defined(HAVE_LOGGER) && !defined(ANDROID) - logger_shutdown(); -#elif defined(HAVE_FILE_LOGGER) - if (g_extern.log_file) - fclose(g_extern.log_file); - g_extern.log_file = NULL; -#endif - - if (frontend_ctx && frontend_ctx->deinit) - frontend_ctx->deinit(args); - - if (g_extern.lifecycle_mode_state & (1ULL << MODE_EXITSPAWN) && frontend_ctx - && frontend_ctx->exitspawn) - frontend_ctx->exitspawn(); - - rarch_main_clear_state(); - - if (frontend_ctx && frontend_ctx->shutdown) - frontend_ctx->shutdown(false); - - returnfunc(); -} - -static inline void android_app_write_cmd (void *data, int8_t cmd) -{ - struct android_app *android_app = (struct android_app*)data; - if (write(android_app->msgwrite, &cmd, sizeof(cmd)) != sizeof(cmd)) - RARCH_ERR("Failure writing android_app cmd: %s\n", strerror(errno)); -} - -static void android_app_set_input (void *data, AInputQueue* inputQueue) -{ - struct android_app *android_app = (struct android_app*)data; - slock_lock(android_app->mutex); - android_app->pendingInputQueue = inputQueue; - android_app_write_cmd(android_app, APP_CMD_INPUT_CHANGED); - while (android_app->inputQueue != android_app->pendingInputQueue) - scond_wait(android_app->cond, android_app->mutex); - slock_unlock(android_app->mutex); -} - -static void android_app_set_window (void *data, ANativeWindow* window) -{ - struct android_app *android_app = (struct android_app*)data; - slock_lock(android_app->mutex); - if (android_app->pendingWindow != NULL) - android_app_write_cmd(android_app, APP_CMD_TERM_WINDOW); - - android_app->pendingWindow = window; - - if (window != NULL) - android_app_write_cmd(android_app, APP_CMD_INIT_WINDOW); - - while (android_app->window != android_app->pendingWindow) - scond_wait(android_app->cond, android_app->mutex); - - slock_unlock(android_app->mutex); -} - -static void android_app_set_activity_state (void *data, int8_t cmd) -{ - struct android_app *android_app = (struct android_app*)data; - slock_lock(android_app->mutex); - android_app_write_cmd(android_app, cmd); - while (android_app->activityState != cmd && android_app->activityState != APP_CMD_DEAD) - scond_wait(android_app->cond, android_app->mutex); - slock_unlock(android_app->mutex); - - if (android_app->activityState == APP_CMD_DEAD) - RARCH_LOG("RetroArch thread is dead.\n"); -} - -static void onDestroy(ANativeActivity* activity) -{ - RARCH_LOG("Destroy: %p\n", activity); - struct android_app* android_app = (struct android_app*)activity->instance; - - sthread_join(android_app->thread); - RARCH_LOG("Joined with RetroArch thread.\n"); - - close(android_app->msgread); - close(android_app->msgwrite); - scond_free(android_app->cond); - slock_free(android_app->mutex); - free(android_app); -} - -static void onStart(ANativeActivity* activity) -{ - RARCH_LOG("Start: %p\n", activity); - android_app_set_activity_state((struct android_app*)activity->instance, APP_CMD_START); -} - -static void onResume(ANativeActivity* activity) -{ - RARCH_LOG("Resume: %p\n", activity); - android_app_set_activity_state((struct android_app*)activity->instance, APP_CMD_RESUME); -} - -static void onPause(ANativeActivity* activity) -{ - RARCH_LOG("Pause: %p\n", activity); - android_app_set_activity_state((struct android_app*)activity->instance, APP_CMD_PAUSE); -} - -static void onStop(ANativeActivity* activity) -{ - RARCH_LOG("Stop: %p\n", activity); - android_app_set_activity_state((struct android_app*)activity->instance, APP_CMD_STOP); -} - -static void onConfigurationChanged (ANativeActivity *activity) -{ - struct android_app* android_app = (struct android_app*)activity->instance; - RARCH_LOG("ConfigurationChanged: %p\n", activity); - android_app_write_cmd(android_app, APP_CMD_CONFIG_CHANGED); -} - -static void onWindowFocusChanged(ANativeActivity* activity, int focused) -{ - RARCH_LOG("WindowFocusChanged: %p -- %d\n", activity, focused); - android_app_write_cmd((struct android_app*)activity->instance, - focused ? APP_CMD_GAINED_FOCUS : APP_CMD_LOST_FOCUS); -} - -static void onNativeWindowCreated(ANativeActivity* activity, ANativeWindow* window) -{ - RARCH_LOG("NativeWindowCreated: %p -- %p\n", activity, window); - android_app_set_window((struct android_app*)activity->instance, window); -} - -static void onNativeWindowDestroyed(ANativeActivity* activity, ANativeWindow* window) -{ - RARCH_LOG("NativeWindowDestroyed: %p -- %p\n", activity, window); - android_app_set_window((struct android_app*)activity->instance, NULL); -} - -static void onInputQueueCreated(ANativeActivity* activity, AInputQueue* queue) -{ - RARCH_LOG("InputQueueCreated: %p -- %p\n", activity, queue); - android_app_set_input((struct android_app*)activity->instance, queue); -} - -static void onInputQueueDestroyed(ANativeActivity* activity, AInputQueue* queue) -{ - RARCH_LOG("InputQueueDestroyed: %p -- %p\n", activity, queue); - android_app_set_input((struct android_app*)activity->instance, NULL); -} - -// -------------------------------------------------------------------- -// Native activity interaction (called from main thread) -// -------------------------------------------------------------------- - -void ANativeActivity_onCreate(ANativeActivity* activity, - void* savedState, size_t savedStateSize) -{ - (void)savedState; - (void)savedStateSize; - - RARCH_LOG("Creating Native Activity: %p\n", activity); - activity->callbacks->onDestroy = onDestroy; - activity->callbacks->onStart = onStart; - activity->callbacks->onResume = onResume; - activity->callbacks->onSaveInstanceState = NULL; - activity->callbacks->onPause = onPause; - activity->callbacks->onStop = onStop; - activity->callbacks->onConfigurationChanged = onConfigurationChanged; - activity->callbacks->onLowMemory = NULL; - activity->callbacks->onWindowFocusChanged = onWindowFocusChanged; - activity->callbacks->onNativeWindowCreated = onNativeWindowCreated; - activity->callbacks->onNativeWindowDestroyed = onNativeWindowDestroyed; - activity->callbacks->onInputQueueCreated = onInputQueueCreated; - activity->callbacks->onInputQueueDestroyed = onInputQueueDestroyed; - - // these are set only for the native activity, and are reset when it ends - ANativeActivity_setWindowFlags(activity, AWINDOW_FLAG_KEEP_SCREEN_ON | AWINDOW_FLAG_FULLSCREEN, 0); - - struct android_app* android_app = (struct android_app*)malloc(sizeof(struct android_app)); - memset(android_app, 0, sizeof(struct android_app)); - android_app->activity = activity; - - android_app->mutex = slock_new(); - android_app->cond = scond_new(); - - int msgpipe[2]; - if (pipe(msgpipe)) - { - RARCH_ERR("could not create pipe: %s.\n", strerror(errno)); - activity->instance = NULL; - } - android_app->msgread = msgpipe[0]; - android_app->msgwrite = msgpipe[1]; - - android_app->thread = (sthread_t*)sthread_create(android_app_entry, android_app); - - // Wait for thread to start. - slock_lock(android_app->mutex); - while (!android_app->running) - scond_wait(android_app->cond, android_app->mutex); - slock_unlock(android_app->mutex); - - activity->instance = android_app; -} diff --git a/frontend/platform/platform_android.c b/frontend/platform/platform_android.c index c235c3bab5..d6817d4eb9 100644 --- a/frontend/platform/platform_android.c +++ b/frontend/platform/platform_android.c @@ -32,6 +32,188 @@ struct android_app *g_android; //forward decls static void system_deinit(void *data); static void system_shutdown(bool unused); +extern void android_app_entry(void *args); + +static inline void android_app_write_cmd (void *data, int8_t cmd) +{ + struct android_app *android_app = (struct android_app*)data; + if (write(android_app->msgwrite, &cmd, sizeof(cmd)) != sizeof(cmd)) + RARCH_ERR("Failure writing android_app cmd: %s\n", strerror(errno)); +} + +static void android_app_set_input (void *data, AInputQueue* inputQueue) +{ + struct android_app *android_app = (struct android_app*)data; + slock_lock(android_app->mutex); + android_app->pendingInputQueue = inputQueue; + android_app_write_cmd(android_app, APP_CMD_INPUT_CHANGED); + while (android_app->inputQueue != android_app->pendingInputQueue) + scond_wait(android_app->cond, android_app->mutex); + slock_unlock(android_app->mutex); +} + +static void android_app_set_window (void *data, ANativeWindow* window) +{ + struct android_app *android_app = (struct android_app*)data; + slock_lock(android_app->mutex); + if (android_app->pendingWindow != NULL) + android_app_write_cmd(android_app, APP_CMD_TERM_WINDOW); + + android_app->pendingWindow = window; + + if (window != NULL) + android_app_write_cmd(android_app, APP_CMD_INIT_WINDOW); + + while (android_app->window != android_app->pendingWindow) + scond_wait(android_app->cond, android_app->mutex); + + slock_unlock(android_app->mutex); +} + +static void android_app_set_activity_state (void *data, int8_t cmd) +{ + struct android_app *android_app = (struct android_app*)data; + slock_lock(android_app->mutex); + android_app_write_cmd(android_app, cmd); + while (android_app->activityState != cmd && android_app->activityState != APP_CMD_DEAD) + scond_wait(android_app->cond, android_app->mutex); + slock_unlock(android_app->mutex); + + if (android_app->activityState == APP_CMD_DEAD) + RARCH_LOG("RetroArch thread is dead.\n"); +} + +static void onDestroy(ANativeActivity* activity) +{ + RARCH_LOG("Destroy: %p\n", activity); + struct android_app* android_app = (struct android_app*)activity->instance; + + sthread_join(android_app->thread); + RARCH_LOG("Joined with RetroArch thread.\n"); + + close(android_app->msgread); + close(android_app->msgwrite); + scond_free(android_app->cond); + slock_free(android_app->mutex); + free(android_app); +} + +static void onStart(ANativeActivity* activity) +{ + RARCH_LOG("Start: %p\n", activity); + android_app_set_activity_state((struct android_app*)activity->instance, APP_CMD_START); +} + +static void onResume(ANativeActivity* activity) +{ + RARCH_LOG("Resume: %p\n", activity); + android_app_set_activity_state((struct android_app*)activity->instance, APP_CMD_RESUME); +} + +static void onPause(ANativeActivity* activity) +{ + RARCH_LOG("Pause: %p\n", activity); + android_app_set_activity_state((struct android_app*)activity->instance, APP_CMD_PAUSE); +} + +static void onStop(ANativeActivity* activity) +{ + RARCH_LOG("Stop: %p\n", activity); + android_app_set_activity_state((struct android_app*)activity->instance, APP_CMD_STOP); +} + +static void onConfigurationChanged (ANativeActivity *activity) +{ + struct android_app* android_app = (struct android_app*)activity->instance; + RARCH_LOG("ConfigurationChanged: %p\n", activity); + android_app_write_cmd(android_app, APP_CMD_CONFIG_CHANGED); +} + +static void onWindowFocusChanged(ANativeActivity* activity, int focused) +{ + RARCH_LOG("WindowFocusChanged: %p -- %d\n", activity, focused); + android_app_write_cmd((struct android_app*)activity->instance, + focused ? APP_CMD_GAINED_FOCUS : APP_CMD_LOST_FOCUS); +} + +static void onNativeWindowCreated(ANativeActivity* activity, ANativeWindow* window) +{ + RARCH_LOG("NativeWindowCreated: %p -- %p\n", activity, window); + android_app_set_window((struct android_app*)activity->instance, window); +} + +static void onNativeWindowDestroyed(ANativeActivity* activity, ANativeWindow* window) +{ + RARCH_LOG("NativeWindowDestroyed: %p -- %p\n", activity, window); + android_app_set_window((struct android_app*)activity->instance, NULL); +} + +static void onInputQueueCreated(ANativeActivity* activity, AInputQueue* queue) +{ + RARCH_LOG("InputQueueCreated: %p -- %p\n", activity, queue); + android_app_set_input((struct android_app*)activity->instance, queue); +} + +static void onInputQueueDestroyed(ANativeActivity* activity, AInputQueue* queue) +{ + RARCH_LOG("InputQueueDestroyed: %p -- %p\n", activity, queue); + android_app_set_input((struct android_app*)activity->instance, NULL); +} + +// -------------------------------------------------------------------- +// Native activity interaction (called from main thread) +// -------------------------------------------------------------------- + +void ANativeActivity_onCreate(ANativeActivity* activity, + void* savedState, size_t savedStateSize) +{ + (void)savedState; + (void)savedStateSize; + + RARCH_LOG("Creating Native Activity: %p\n", activity); + activity->callbacks->onDestroy = onDestroy; + activity->callbacks->onStart = onStart; + activity->callbacks->onResume = onResume; + activity->callbacks->onSaveInstanceState = NULL; + activity->callbacks->onPause = onPause; + activity->callbacks->onStop = onStop; + activity->callbacks->onConfigurationChanged = onConfigurationChanged; + activity->callbacks->onLowMemory = NULL; + activity->callbacks->onWindowFocusChanged = onWindowFocusChanged; + activity->callbacks->onNativeWindowCreated = onNativeWindowCreated; + activity->callbacks->onNativeWindowDestroyed = onNativeWindowDestroyed; + activity->callbacks->onInputQueueCreated = onInputQueueCreated; + activity->callbacks->onInputQueueDestroyed = onInputQueueDestroyed; + + // these are set only for the native activity, and are reset when it ends + ANativeActivity_setWindowFlags(activity, AWINDOW_FLAG_KEEP_SCREEN_ON | AWINDOW_FLAG_FULLSCREEN, 0); + + struct android_app* android_app = (struct android_app*)malloc(sizeof(struct android_app)); + memset(android_app, 0, sizeof(struct android_app)); + android_app->activity = activity; + + android_app->mutex = slock_new(); + android_app->cond = scond_new(); + + int msgpipe[2]; + if (pipe(msgpipe)) + { + RARCH_ERR("could not create pipe: %s.\n", strerror(errno)); + activity->instance = NULL; + } + android_app->msgread = msgpipe[0]; + android_app->msgwrite = msgpipe[1]; + + android_app->thread = (sthread_t*)sthread_create(android_app_entry, android_app); + + // Wait for thread to start. + slock_lock(android_app->mutex); + while (!android_app->running) + scond_wait(android_app->cond, android_app->mutex); + slock_unlock(android_app->mutex); + + activity->instance = android_app; +} static bool android_run_events (void *data) { diff --git a/griffin/griffin.c b/griffin/griffin.c index 8f0c967b45..09d2606f0c 100644 --- a/griffin/griffin.c +++ b/griffin/griffin.c @@ -477,8 +477,6 @@ MAIN ============================================================ */ #if defined(XENON) #include "../frontend/frontend_xenon.c" -#elif defined(ANDROID) -#include "../frontend/frontend_android.c" #else #include "../frontend/frontend.c" #endif