From f069c82417d7ceccf206c0725b9c02fc8bd47a9b Mon Sep 17 00:00:00 2001 From: meancoot Date: Sat, 21 Dec 2013 19:42:10 -0500 Subject: [PATCH] (Apple) First pass at removing UI/RetroArch thread split. --- apple/OSX/platform.m | 12 +- apple/OSX/settings.m | 5 - apple/common/RAGameView.m | 184 ++++++++++------------------- apple/common/RetroArch_Apple.h | 3 - apple/common/apple_export.h | 12 +- apple/common/apple_input.c | 25 ++-- apple/common/main.m | 65 ++++------ apple/common/rarch_wrapper.h | 3 +- apple/iOS/menu.m | 2 +- apple/iOS/platform.m | 3 - frontend/frontend_apple.c | 105 ++++++++++++++++ frontend/platform/platform_apple.c | 166 ++++++++------------------ griffin/griffin.c | 2 + 13 files changed, 261 insertions(+), 326 deletions(-) create mode 100644 frontend/frontend_apple.c diff --git a/apple/OSX/platform.m b/apple/OSX/platform.m index 3a3855af9b..06483f1c41 100644 --- a/apple/OSX/platform.m +++ b/apple/OSX/platform.m @@ -13,7 +13,6 @@ * If not, see . */ -#include #include #include @@ -148,7 +147,7 @@ static void* const associated_core_key = (void*)&associated_core_key; apple_display_alert(@"No libretro cores were found.\nSelect \"Go->Cores Directory\" from the menu and place libretro dylib files there.", @"RetroArch"); // Run RGUI if needed - if (!_wantReload || apple_argv) + if (!_wantReload)//TODO || apple_argv) apple_run_core(nil, 0); else [self chooseCore]; @@ -169,7 +168,7 @@ static void* const associated_core_key = (void*)&associated_core_key; _isTerminating = true; if (apple_is_running) - apple_frontend_post_event(apple_event_basic_command, (void*)QUIT); + apple_event_basic_command(QUIT); return apple_is_running ? NSTerminateCancel : NSTerminateNow; } @@ -212,7 +211,6 @@ static void* const associated_core_key = (void*)&associated_core_key; } // This utility function will queue the self.core and self.file instance values for running. -// If the emulator thread is already running it will tell it to quit. - (void)runCore { _wantReload = apple_is_running; @@ -220,7 +218,7 @@ static void* const associated_core_key = (void*)&associated_core_key; if (!apple_is_running) apple_run_core(self.core, [self.file UTF8String]); else - apple_frontend_post_event(apple_event_basic_command, (void*)QUIT); + apple_event_basic_command(QUIT); } - (void)chooseCore @@ -280,7 +278,7 @@ static void* const associated_core_key = (void*)&associated_core_key; - (IBAction)basicEvent:(id)sender { if (apple_is_running) - apple_frontend_post_event(&apple_event_basic_command, (void*)[sender tag]); + apple_event_basic_command([sender tag]); } - (void)alertDidEnd:(NSAlert *)alert returnCode:(NSInteger)returnCode contextInfo:(void *)contextInfo @@ -292,6 +290,7 @@ static void* const associated_core_key = (void*)&associated_core_key; int main(int argc, char *argv[]) { +/* TODO uint32_t current_argc = 0; for (int i = 0; i != argc; i ++) @@ -308,6 +307,7 @@ int main(int argc, char *argv[]) apple_argv[current_argc ++] = argv[i]; } } +*/ return NSApplicationMain(argc, (const char **) argv); } diff --git a/apple/OSX/settings.m b/apple/OSX/settings.m index 59d1df408a..29b46be810 100644 --- a/apple/OSX/settings.m +++ b/apple/OSX/settings.m @@ -135,8 +135,6 @@ static void* const associated_name_tag = (void*)&associated_name_tag; - (void)awakeFromNib { - apple_enter_stasis(); - NSMutableArray* thisGroup = nil; NSMutableArray* thisSubGroup = nil; self.settings = [NSMutableArray array]; @@ -193,9 +191,6 @@ static void* const associated_name_tag = (void*)&associated_name_tag; - (void)windowWillClose:(NSNotification *)notification { setting_data_save_config_path(setting_data_get_list(), [apple_platform.globalConfigFile UTF8String]); - - apple_exit_stasis(true); - [NSApp stopModal]; } diff --git a/apple/common/RAGameView.m b/apple/common/RAGameView.m index 97473c6ff7..fece1fcb07 100644 --- a/apple/common/RAGameView.m +++ b/apple/common/RAGameView.m @@ -267,7 +267,8 @@ didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer { // TODO: Don't post if event queue is full CVPixelBufferRef pixelBuffer = CVPixelBufferRetain(CMSampleBufferGetImageBuffer(sampleBuffer)); - apple_frontend_post_event(event_process_camera_frame, pixelBuffer);} + event_process_camera_frame(pixelBuffer); +} - (void) onCameraInit { @@ -375,46 +376,27 @@ didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer @end static RAScreen* get_chosen_screen() -{ -#ifdef OSX - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; -#else - @autoreleasepool { -#endif - +{ if (g_settings.video.monitor_index >= RAScreen.screens.count) { RARCH_WARN("video_monitor_index is greater than the number of connected monitors; using main screen instead.\n"); -#ifdef OSX - [pool drain]; -#endif return [RAScreen mainScreen]; } NSArray *screens = [RAScreen screens]; - RAScreen *s = (RAScreen*)[screens objectAtIndex:g_settings.video.monitor_index]; -#ifdef OSX - [pool drain]; -#endif - return s; -#ifdef IOS - } -#endif + return (RAScreen*)[screens objectAtIndex:g_settings.video.monitor_index]; } bool apple_gfx_ctx_init(void) { - dispatch_sync(dispatch_get_main_queue(), - ^{ - // Make sure the view was created - [RAGameView get]; - + // Make sure the view was created + [RAGameView get]; + #ifdef IOS // Show pause button for a few seconds, so people know it's there - g_pause_indicator_view.alpha = 1.0f; - [NSObject cancelPreviousPerformRequestsWithTarget:g_instance]; - [g_instance performSelector:@selector(hidePauseButton) withObject:g_instance afterDelay:3.0f]; + g_pause_indicator_view.alpha = 1.0f; + [NSObject cancelPreviousPerformRequestsWithTarget:g_instance]; + [g_instance performSelector:@selector(hidePauseButton) withObject:g_instance afterDelay:3.0f]; #endif - }); g_initialized = true; @@ -427,14 +409,11 @@ void apple_gfx_ctx_destroy(void) [GLContextClass clearCurrentContext]; - dispatch_sync(dispatch_get_main_queue(), - ^{ #ifdef IOS - g_view.context = nil; + g_view.context = nil; #endif - [GLContextClass clearCurrentContext]; - g_context = nil; - }); + [GLContextClass clearCurrentContext]; + g_context = nil; } bool apple_gfx_ctx_bind_api(enum gfx_ctx_api api, unsigned major, unsigned minor) @@ -442,43 +421,35 @@ bool apple_gfx_ctx_bind_api(enum gfx_ctx_api api, unsigned major, unsigned minor if (api != GLAPIType) return false; - [GLContextClass clearCurrentContext]; - dispatch_sync(dispatch_get_main_queue(), - ^{ - [GLContextClass clearCurrentContext]; - #ifdef OSX - [g_context clearDrawable]; - [g_context release], g_context = nil; - [g_format release], g_format = nil; - - NSOpenGLPixelFormatAttribute attributes [] = { - NSOpenGLPFADoubleBuffer, // double buffered - NSOpenGLPFADepthSize, - (NSOpenGLPixelFormatAttribute)16, // 16 bit depth buffer + [g_context clearDrawable]; + [g_context release], g_context = nil; + [g_format release], g_format = nil; + + NSOpenGLPixelFormatAttribute attributes [] = { + NSOpenGLPFADoubleBuffer, // double buffered + NSOpenGLPFADepthSize, + (NSOpenGLPixelFormatAttribute)16, // 16 bit depth buffer #ifdef MAC_OS_X_VERSION_10_7 - (major || minor) ? NSOpenGLPFAOpenGLProfile : 0, - (major << 12) | (minor << 8), + (major || minor) ? NSOpenGLPFAOpenGLProfile : 0, + (major << 12) | (minor << 8), #endif - (NSOpenGLPixelFormatAttribute)nil - }; + (NSOpenGLPixelFormatAttribute)nil + }; - [g_format release]; - [g_context release]; + [g_format release]; + [g_context release]; - g_format = [[NSOpenGLPixelFormat alloc] initWithAttributes:attributes]; - g_context = [[NSOpenGLContext alloc] initWithFormat:g_format shareContext:nil]; - [g_context setView:g_view]; + g_format = [[NSOpenGLPixelFormat alloc] initWithAttributes:attributes]; + g_context = [[NSOpenGLContext alloc] initWithFormat:g_format shareContext:nil]; + [g_context setView:g_view]; #else - g_context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; - g_view.context = g_context; + g_context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; + g_view.context = g_context; #endif - [g_context makeCurrentContext]; - }); - [g_context makeCurrentContext]; return true; } @@ -498,26 +469,23 @@ void apple_gfx_ctx_swap_interval(unsigned interval) bool apple_gfx_ctx_set_video_mode(unsigned width, unsigned height, bool fullscreen) { #ifdef OSX - dispatch_sync(dispatch_get_main_queue(), - ^{ - // TODO: Sceen mode support - - if (fullscreen && !g_has_went_fullscreen) - { - [g_view enterFullScreenMode:get_chosen_screen() withOptions:nil]; - [NSCursor hide]; - } - else if (!fullscreen && g_has_went_fullscreen) - { - [g_view exitFullScreenModeWithOptions:nil]; - [[g_view window] makeFirstResponder:g_view]; - [NSCursor unhide]; - } - - g_has_went_fullscreen = fullscreen; - if (!g_has_went_fullscreen) - [[g_view window] setContentSize:NSMakeSize(width, height)]; - }); + // TODO: Sceen mode support + + if (fullscreen && !g_has_went_fullscreen) + { + [g_view enterFullScreenMode:get_chosen_screen() withOptions:nil]; + [NSCursor hide]; + } + else if (!fullscreen && g_has_went_fullscreen) + { + [g_view exitFullScreenModeWithOptions:nil]; + [[g_view window] makeFirstResponder:g_view]; + [NSCursor unhide]; + } + + g_has_went_fullscreen = fullscreen; + if (!g_has_went_fullscreen) + [[g_view window] setContentSize:NSMakeSize(width, height)]; #endif // TODO: Maybe iOS users should be apple to show/hide the status bar here? @@ -558,12 +526,7 @@ void apple_gfx_ctx_update_window_title(void) #ifdef OSX if (got_text) { - // NOTE: This could go bad if buf is updated again before this completes. - // If it poses a problem it should be changed to dispatch_sync. - dispatch_async(dispatch_get_main_queue(), - ^{ - [[g_view window] setTitle:[NSString stringWithCString:text encoding:NSUTF8StringEncoding]]; - }); + [[g_view window] setTitle:[NSString stringWithCString:text encoding:NSUTF8StringEncoding]]; } #endif if (fps_draw) @@ -579,11 +542,7 @@ void apple_gfx_ctx_swap_buffers() { if (--g_fast_forward_skips < 0) { - dispatch_sync(dispatch_get_main_queue(), - ^{ - [g_view display]; - }); - + [g_view display]; g_fast_forward_skips = g_is_syncing ? 0 : 3; } } @@ -602,10 +561,8 @@ gfx_ctx_proc_t apple_gfx_ctx_get_proc_address(const char *symbol_name) #ifdef IOS void apple_bind_game_view_fbo(void) { - dispatch_sync(dispatch_get_main_queue(), ^{ - if (g_context) - [g_view bindDrawable]; - }); + if (g_context) + [g_view bindDrawable]; } typedef struct ios_camera @@ -700,17 +657,14 @@ static void *apple_location_init() if (!applelocation) return NULL; - dispatch_async(dispatch_get_main_queue(), - ^{ - // Create the location manager if this object does not - // already have one. - if (nil == locationManager) - locationManager = [[CLLocationManager alloc] init]; - - locationManager.delegate = [RAGameView get]; - locationManager.desiredAccuracy = kCLLocationAccuracyBest; - locationManager.distanceFilter = kCLDistanceFilterNone; - }); + // Create the location manager if this object does not + // already have one. + if (nil == locationManager) + locationManager = [[CLLocationManager alloc] init]; + + locationManager.delegate = [RAGameView get]; + locationManager.desiredAccuracy = kCLLocationAccuracyBest; + locationManager.distanceFilter = kCLDistanceFilterNone; return applelocation; } @@ -719,10 +673,7 @@ static void apple_location_set_interval(void *data, unsigned interval_update_ms, { (void)data; - dispatch_async(dispatch_get_main_queue(), - ^{ - locationManager.distanceFilter = interval_distance ? interval_distance : kCLDistanceFilterNone; - }); + locationManager.distanceFilter = interval_distance ? interval_distance : kCLDistanceFilterNone; } static void apple_location_free(void *data) @@ -740,11 +691,7 @@ static bool apple_location_start(void *data) { (void)data; - dispatch_async(dispatch_get_main_queue(), - ^{ - [locationManager startUpdatingLocation]; - }); - + [locationManager startUpdatingLocation]; return true; } @@ -752,10 +699,7 @@ static void apple_location_stop(void *data) { (void)data; - dispatch_async(dispatch_get_main_queue(), - ^{ - [locationManager stopUpdatingLocation]; - }); + [locationManager stopUpdatingLocation]; } static bool apple_location_get_position(void *data, double *lat, double *lon, double *horiz_accuracy, diff --git a/apple/common/RetroArch_Apple.h b/apple/common/RetroArch_Apple.h index 422bab0ebc..ca2612b162 100644 --- a/apple/common/RetroArch_Apple.h +++ b/apple/common/RetroArch_Apple.h @@ -69,9 +69,6 @@ extern NSString *apple_get_core_display_name(NSString *core_id); - (id)initWithSetting:(const rarch_setting_t*)setting; @end -// frontend/platform/platform_apple.c -extern void apple_frontend_post_event(void (*fn)(void*), void* userdata); - // #define BOXSTRING(x) [NSString stringWithUTF8String:x] #define BOXINT(x) [NSNumber numberWithInt:x] diff --git a/apple/common/apple_export.h b/apple/common/apple_export.h index 5e859e3258..e28cb5092d 100644 --- a/apple/common/apple_export.h +++ b/apple/common/apple_export.h @@ -25,16 +25,10 @@ enum basic_event_t { SAVE_STATE = 3, QUIT = 4 }; -extern void apple_event_basic_command(void* userdata); -extern void apple_event_set_state_slot(void* userdata); -extern void apple_event_show_rgui(void* userdata); +extern void apple_event_basic_command(enum basic_event_t action); extern void apple_refresh_config(void); -extern void apple_enter_stasis(void); -extern void apple_exit_stasis(bool reload_config); -extern void objc_clear_config_hack(void); -extern void *rarch_main_spring(void* args); - -extern bool apple_is_running; +extern int apple_rarch_load_content(int argc, char* argv[]); +extern int apple_rarch_iterate_once(); #endif diff --git a/apple/common/apple_input.c b/apple/common/apple_input.c index 6031cd5a4b..9e8eda791b 100644 --- a/apple/common/apple_input.c +++ b/apple/common/apple_input.c @@ -15,7 +15,6 @@ #include -#include #include "input/input_common.h" #include "apple_input.h" @@ -168,22 +167,20 @@ static void *apple_input_init(void) static void apple_input_poll(void *data) { - dispatch_sync(dispatch_get_main_queue(), ^{ - memcpy(&g_polled_input_data, &g_current_input_data, sizeof(apple_input_data_t)); + memcpy(&g_polled_input_data, &g_current_input_data, sizeof(apple_input_data_t)); - for (int i = 0; i != g_polled_input_data.touch_count; i ++) - { - input_translate_coord_viewport(g_polled_input_data.touches[i].screen_x, g_polled_input_data.touches[i].screen_y, - &g_polled_input_data.touches[i].fixed_x, &g_polled_input_data.touches[i].fixed_y, - &g_polled_input_data.touches[i].full_x, &g_polled_input_data.touches[i].full_y); - } + for (int i = 0; i != g_polled_input_data.touch_count; i ++) + { + input_translate_coord_viewport(g_polled_input_data.touches[i].screen_x, g_polled_input_data.touches[i].screen_y, + &g_polled_input_data.touches[i].fixed_x, &g_polled_input_data.touches[i].fixed_y, + &g_polled_input_data.touches[i].full_x, &g_polled_input_data.touches[i].full_y); + } - input_joypad_poll(g_joydriver); - g_polled_input_data.pad_buttons[0] |= apple_input_get_icade_buttons(); + input_joypad_poll(g_joydriver); + g_polled_input_data.pad_buttons[0] |= apple_input_get_icade_buttons(); - g_current_input_data.mouse_delta[0] = 0; - g_current_input_data.mouse_delta[1] = 0; - }); + g_current_input_data.mouse_delta[0] = 0; + g_current_input_data.mouse_delta[1] = 0; } static int16_t apple_input_state(void *data, const struct retro_keybind **binds, unsigned port, unsigned device, unsigned index, unsigned id) diff --git a/apple/common/main.m b/apple/common/main.m index 76891e0f23..783d6cd259 100644 --- a/apple/common/main.m +++ b/apple/common/main.m @@ -14,7 +14,6 @@ * If not, see . */ -#include #include #import "RetroArch_Apple.h" @@ -24,12 +23,9 @@ #include "file.h" -char** apple_argv; - id apple_platform; #pragma mark EMULATION -static pthread_t apple_retro_thread; bool apple_is_running; bool apple_use_tv_mode; NSString* apple_core; @@ -39,68 +35,51 @@ void apple_run_core(NSString* core, const char* file) if (!apple_is_running) { #ifndef OSX - if (core && file) - { - char basedir[256]; - fill_pathname_basedir(basedir, file, sizeof(basedir)); - if (access(basedir, R_OK | W_OK | X_OK)) - apple_display_alert(@"The directory containing the selected file has limited permissions. This may " - "prevent zipped content from loading, and will cause some cores to not function.", 0); - } + char basedir[256]; + fill_pathname_basedir(basedir, file, sizeof(basedir)); + if (file && access(basedir, R_OK | W_OK | X_OK)) + apple_display_alert(@"The directory containing the selected file has limited permissions. This may " + "prevent zipped content from loading, and will cause some cores to not function.", 0); #endif [apple_platform loadingCore:core withFile:file]; -#ifdef OSX - [apple_core release]; -#endif - apple_core = [core copy]; + apple_core = core; apple_is_running = true; static char config_path[PATH_MAX]; static char core_path[PATH_MAX]; static char file_path[PATH_MAX]; - if (!apple_argv) - { - if (apple_core_info_has_custom_config([apple_core UTF8String])) - apple_core_info_get_custom_config([apple_core UTF8String], config_path, sizeof(config_path)); - else - strlcpy(config_path, [apple_platform.globalConfigFile UTF8String], sizeof(config_path)); + if (apple_core_info_has_custom_config(apple_core.UTF8String)) + apple_core_info_get_custom_config(apple_core.UTF8String, config_path, sizeof(config_path)); + else + strlcpy(config_path, apple_platform.globalConfigFile.UTF8String, sizeof(config_path)); - static const char* const argv_game[] = { "retroarch", "-c", config_path, "-L", core_path, file_path, 0 }; - static const char* const argv_menu[] = { "retroarch", "-c", config_path, "--menu", 0 }; + static const char* const argv_game[] = { "retroarch", "-c", config_path, "-L", core_path, file_path, 0 }; + static const char* const argv_menu[] = { "retroarch", "-c", config_path, "--menu", 0 }; - if (file && core) - { - strlcpy(core_path, [apple_core UTF8String], sizeof(core_path)); - strlcpy(file_path, file, sizeof(file_path)); - } - - apple_argv = (char**)((file && core) ? argv_game : argv_menu); - } - - if (pthread_create(&apple_retro_thread, 0, rarch_main_spring, apple_argv)) + if (file && core) { - apple_argv = 0; - - apple_rarch_exited((void*)1); - return; + strlcpy(core_path, apple_core.UTF8String, sizeof(core_path)); + strlcpy(file_path, file, sizeof(file_path)); } - apple_argv = 0; + int argc = (file && core) ? 6 : 4; + char** argv = (char**)((file && core) ? argv_game : argv_menu); - pthread_detach(apple_retro_thread); + if (apple_rarch_load_content(argc, argv)) + apple_rarch_exited(true); } } -void apple_rarch_exited(void* result) +void apple_rarch_exited(bool on_error) { - if (result) + if (on_error) apple_display_alert(@"Failed to load content.", 0); NSString* used_core = apple_core; - apple_core = 0; + apple_core = 0; if (apple_is_running) { diff --git a/apple/common/rarch_wrapper.h b/apple/common/rarch_wrapper.h index 471f56bcf4..78a0d78c57 100644 --- a/apple/common/rarch_wrapper.h +++ b/apple/common/rarch_wrapper.h @@ -19,8 +19,7 @@ #include "gfx/gfx_context.h" -// These functions should only be called as arguments to dispatch_sync -void apple_rarch_exited (void* result); +void apple_rarch_exited (bool on_error); // These functions must only be called in gfx/context/apple_gl_context.c bool apple_gfx_ctx_init(void); diff --git a/apple/iOS/menu.m b/apple/iOS/menu.m index 5300740460..47a25b99b7 100644 --- a/apple/iOS/menu.m +++ b/apple/iOS/menu.m @@ -497,7 +497,7 @@ static void RunActionSheet(const char* title, const struct string_list* items, U - (void)performBasicAction:(enum basic_event_t)action { [[RetroArch_iOS get] showGameView]; - apple_frontend_post_event(apple_event_basic_command, action); + apple_event_basic_command(action); } - (void)chooseCoreWithPath:(NSString*)path diff --git a/apple/iOS/platform.m b/apple/iOS/platform.m index a24fe79be2..f1f27428ff 100644 --- a/apple/iOS/platform.m +++ b/apple/iOS/platform.m @@ -13,7 +13,6 @@ * If not, see . */ -#include #include #import "RetroArch_Apple.h" @@ -232,12 +231,10 @@ static void handle_touch_event(NSArray* touches) - (void)applicationDidBecomeActive:(UIApplication *)application { - apple_exit_stasis(false); } - (void)applicationWillResignActive:(UIApplication *)application { - apple_enter_stasis(); } -(BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation diff --git a/frontend/frontend_apple.c b/frontend/frontend_apple.c new file mode 100644 index 0000000000..f978600078 --- /dev/null +++ b/frontend/frontend_apple.c @@ -0,0 +1,105 @@ +/* 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 "../general.h" +#include "../conf/config_file.h" +#include "../file.h" + +#ifdef HAVE_MENU +#include "../frontend/menu/menu_common.h" +#endif + +static bool menuloop; + +int apple_rarch_iterate_once(void) +{ + if (g_extern.system.shutdown) + { + 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); + + if (g_extern.main_is_init) + rarch_main_deinit(); + + rarch_deinit_msg_queue(); + +#ifdef PERF_TEST + rarch_perf_log(); +#endif + + rarch_main_clear_state(); + return 1; + } + else if (menuloop) + { + if (!menu_iterate()) + { + menuloop = false; + driver_set_nonblock_state(driver.nonblock_state); + + if (driver.audio_data && !audio_start_func()) + { + RARCH_ERR("Failed to resume audio driver. Will continue without audio.\n"); + g_extern.audio_active = false; + } + + g_extern.lifecycle_state &= ~(1ULL << MODE_MENU); + } + } + else if (g_extern.lifecycle_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_state |= (1ULL << MODE_GAME); + else + return 2; + + g_extern.lifecycle_state &= ~(1ULL << MODE_LOAD_GAME); + } + else if (g_extern.lifecycle_state & (1ULL << MODE_GAME)) + { + bool r; + if (g_extern.is_paused && !g_extern.is_oneshot) + r = rarch_main_idle_iterate(); + else + r = rarch_main_iterate(); + if (!r) + g_extern.lifecycle_state &= ~(1ULL << MODE_GAME); + } + else if (g_extern.lifecycle_state & (1ULL << MODE_MENU)) + { + g_extern.lifecycle_state |= 1ULL << MODE_MENU_PREINIT; + // Menu should always run with vsync on. + video_set_nonblock_state_func(false); + + if (driver.audio_data) + audio_stop_func(); + + menuloop = true; + } + else + { + g_extern.system.shutdown = true; + } + + return 0; +} diff --git a/frontend/platform/platform_apple.c b/frontend/platform/platform_apple.c index fafe120f84..079913476f 100644 --- a/frontend/platform/platform_apple.c +++ b/frontend/platform/platform_apple.c @@ -14,8 +14,9 @@ * If not, see . */ -#include -#include +#include + +#include "../menu/menu_common.h" #include "../../apple/common/rarch_wrapper.h" #include "../../apple/common/apple_export.h" #include "../../apple/common/setting_data.h" @@ -27,33 +28,10 @@ #include #include -static pthread_mutex_t apple_event_queue_lock = PTHREAD_MUTEX_INITIALIZER; +static CFRunLoopObserverRef iterate_observer; -static struct +void apple_event_basic_command(enum basic_event_t action) { - void (*function)(void*); - void* userdata; -} apple_event_queue[16]; - -static uint32_t apple_event_queue_size; - -void apple_frontend_post_event(void (*fn)(void*), void* userdata) -{ - pthread_mutex_lock(&apple_event_queue_lock); - - if (apple_event_queue_size < 16) - { - apple_event_queue[apple_event_queue_size].function = fn; - apple_event_queue[apple_event_queue_size].userdata = userdata; - apple_event_queue_size ++; - } - - pthread_mutex_unlock(&apple_event_queue_lock); -} - -void apple_event_basic_command(void* userdata) -{ - int action = (int)userdata; switch (action) { case RESET: @@ -71,110 +49,58 @@ void apple_event_basic_command(void* userdata) } } -void apple_event_set_state_slot(void* userdata) -{ - g_extern.state_slot = (uint32_t)userdata; -} - -void apple_event_show_rgui(void* userdata) -{ - const bool in_menu = g_extern.lifecycle_state & (1 << MODE_MENU); - g_extern.lifecycle_state &= ~(1ULL << (in_menu ? MODE_MENU : MODE_GAME)); - g_extern.lifecycle_state |= (1ULL << (in_menu ? MODE_GAME : MODE_MENU)); -} - -// Little nudge to prevent stale values when reloading the confg file -void objc_clear_config_hack(void) +void apple_refresh_config() { + // Little nudge to prevent stale values when reloading the confg file g_extern.block_config_read = false; memset(g_settings.input.overlay, 0, sizeof(g_settings.input.overlay)); memset(g_settings.video.shader_path, 0, sizeof(g_settings.video.shader_path)); -} -static void event_reload_config(void* userdata) -{ - objc_clear_config_hack(); - - uninit_drivers(); - config_load(); - init_drivers(); -} - -void apple_refresh_config() -{ - if (apple_is_running) - apple_frontend_post_event(&event_reload_config, 0); - else - objc_clear_config_hack(); -} - -pthread_mutex_t stasis_mutex = PTHREAD_MUTEX_INITIALIZER; - -static void event_stasis(void* userdata) -{ - uninit_drivers(); - pthread_mutex_lock(&stasis_mutex); - pthread_mutex_unlock(&stasis_mutex); - init_drivers(); -} - -void apple_enter_stasis() -{ - if (apple_is_running) + if (iterate_observer) { - pthread_mutex_lock(&stasis_mutex); - apple_frontend_post_event(event_stasis, 0); - } -} - -void apple_exit_stasis(bool reload_config) -{ - if (reload_config) - { - objc_clear_config_hack(); + uninit_drivers(); config_load(); + init_drivers(); } - - if (apple_is_running) - pthread_mutex_unlock(&stasis_mutex); } -static int process_events(void *data) +static void do_iteration() { - (void)data; - pthread_mutex_lock(&apple_event_queue_lock); - - for (int i = 0; i < apple_event_queue_size; i ++) - apple_event_queue[i].function(apple_event_queue[i].userdata); - - apple_event_queue_size = 0; - - pthread_mutex_unlock(&apple_event_queue_lock); - return 0; -} - -static void system_shutdown(bool force) -{ - /* force set to true makes it display the 'Failed to load game' message. */ - if (force) - dispatch_async_f(dispatch_get_main_queue(), (void*)1, apple_rarch_exited); - else - dispatch_async_f(dispatch_get_main_queue(), 0, apple_rarch_exited); -} - -void *rarch_main_spring(void* args) -{ - char** argv = args; - - uint32_t argc = 0; - while (argv && argv[argc]) - argc++; - - if (rarch_main(argc, argv)) + if (iterate_observer) { - rarch_main_clear_state(); - dispatch_async_f(dispatch_get_main_queue(), (void*)1, apple_rarch_exited); + if (apple_rarch_iterate_once()) + { + CFRunLoopObserverInvalidate(iterate_observer); + CFRelease(iterate_observer); + iterate_observer = 0; + + apple_rarch_exited(false); + } + else + CFRunLoopWakeUp(CFRunLoopGetMain()); } +} + +int apple_rarch_load_content(int argc, char* argv[]) +{ + if (iterate_observer) + { + RARCH_ERR("apple_rarch_load_content called while content is still running."); + return 1; + } + + rarch_main_clear_state(); + rarch_init_msg_queue(); + + if (rarch_main_init(argc, argv)) + return 1; + + menu_init(); + g_extern.lifecycle_state |= 1ULL << MODE_GAME; + g_extern.lifecycle_state |= 1ULL << MODE_GAME_ONESHOT; + + iterate_observer = CFRunLoopObserverCreate(0, kCFRunLoopBeforeWaiting, true, 0, do_iteration, 0); + CFRunLoopAddObserver(CFRunLoopGetMain(), iterate_observer, kCFRunLoopCommonModes); return 0; } @@ -185,8 +111,8 @@ const frontend_ctx_driver_t frontend_ctx_apple = { NULL, /* deinit */ NULL, /* exitspawn */ NULL, /* process_args */ - process_events, /* process_events */ + NULL, /* process_events */ NULL, /* exec */ - system_shutdown, /* shutdown */ + NULL, /* shutdown */ "apple", }; diff --git a/griffin/griffin.c b/griffin/griffin.c index 8f1be287de..736c13a3bb 100644 --- a/griffin/griffin.c +++ b/griffin/griffin.c @@ -519,6 +519,8 @@ MAIN ============================================================ */ #if defined(XENON) #include "../frontend/frontend_xenon.c" +#elif defined(IOS) || defined(OSX) +#include "../frontend/frontend_apple.c" #else #include "../frontend/frontend.c" #endif