From 1c1eaf20d16ad6d8694cb2a7a9bfee2fc7519909 Mon Sep 17 00:00:00 2001 From: Alan Jeffrey Date: Thu, 4 Apr 2019 17:09:34 -0500 Subject: [PATCH] Get the magicleap immersive demo to respond to new file name arguments --- demo/magicleap/manifest.xml | 4 +- demo/magicleap/src/lib.rs | 60 ++++++++++----- demo/magicleap/src/main.cpp | 144 +++++++++++++++++++----------------- 3 files changed, 120 insertions(+), 88 deletions(-) diff --git a/demo/magicleap/manifest.xml b/demo/magicleap/manifest.xml index 9ed77b74..a0c9d703 100644 --- a/demo/magicleap/manifest.xml +++ b/demo/magicleap/manifest.xml @@ -12,7 +12,7 @@ diff --git a/demo/magicleap/src/lib.rs b/demo/magicleap/src/lib.rs index 546ed394..6715ff02 100644 --- a/demo/magicleap/src/lib.rs +++ b/demo/magicleap/src/lib.rs @@ -45,6 +45,7 @@ use std::ffi::CStr; use std::ffi::CString; use std::os::raw::c_char; use std::os::raw::c_void; +use std::sync::mpsc; use usvg::Options as UsvgOptions; use usvg::Tree; @@ -55,8 +56,14 @@ mod magicleap; #[cfg(feature = "mocked")] mod mocked_c_api; +struct ImmersiveApp { + sender: mpsc::Sender, + receiver: mpsc::Receiver, + demo: DemoApp, +} + #[no_mangle] -pub unsafe extern "C" fn magicleap_pathfinder_demo(egl_display: EGLDisplay, egl_context: EGLContext, file_name: *const c_char) { +pub unsafe extern "C" fn magicleap_pathfinder_demo_init(egl_display: EGLDisplay, egl_context: EGLContext) -> *mut c_void { unsafe { c_api::MLLoggingLog(c_api::MLLogLevel::Info, &b"Pathfinder Demo\0"[0], &b"Initializing\0"[0]) }; let tag = CString::new("Pathfinder Demo").unwrap(); @@ -64,7 +71,7 @@ pub unsafe extern "C" fn magicleap_pathfinder_demo(egl_display: EGLDisplay, egl_ let logger = MagicLeapLogger::new(tag, level); log::set_boxed_logger(Box::new(logger)).unwrap(); log::set_max_level(level); - debug!("Initialized logging"); + info!("Initialized logging"); let window = MagicLeapWindow::new(egl_display, egl_context); let window_size = window.size(); @@ -75,25 +82,42 @@ pub unsafe extern "C" fn magicleap_pathfinder_demo(egl_display: EGLDisplay, egl_ options.mode = Mode::VR; options.jobs = Some(3); options.pipeline = 0; - if let Some(file_name) = file_name.as_ref() { - let file_name = CStr::from_ptr(file_name).to_string_lossy().into_owned(); - options.input_path = SVGPath::Resource(file_name); - } - let mut app = DemoApp::new(window, window_size, options); - debug!("Initialized app"); + let demo = DemoApp::new(window, window_size, options); + info!("Initialized app"); - while app.window.running() { - let mut events = Vec::new(); - while let Some(event) = app.window.try_get_event() { - events.push(event); - } + let (sender, receiver) = mpsc::channel(); + Box::into_raw(Box::new(ImmersiveApp { sender, receiver, demo })) as *mut c_void +} - let scene_count = app.prepare_frame(events); - for scene_index in 0..scene_count { - app.draw_scene(scene_index); - } - app.finish_drawing_frame(); +#[no_mangle] +pub unsafe extern "C" fn magicleap_pathfinder_demo_run(app: *mut c_void) { + let app = app as *mut ImmersiveApp; + if let Some(app) = app.as_mut() { + while app.demo.window.running() { + let mut events = Vec::new(); + while let Some(event) = app.demo.window.try_get_event() { + events.push(event); + } + while let Ok(event) = app.receiver.try_recv() { + events.push(event); + } + let scene_count = app.demo.prepare_frame(events); + for scene_index in 0..scene_count { + app.demo.draw_scene(scene_index); + } + app.demo.finish_drawing_frame(); + } + } +} + +#[no_mangle] +pub unsafe extern "C" fn magicleap_pathfinder_demo_load(app: *mut c_void, svg_filename: *const c_char) { + let app = app as *mut ImmersiveApp; + if let Some(app) = app.as_mut() { + let svg_filename = CStr::from_ptr(svg_filename).to_string_lossy().into_owned(); + info!("Loading {}.", svg_filename); + let _ = app.sender.send(Event::OpenSVG(SVGPath::Resource(svg_filename))); } } diff --git a/demo/magicleap/src/main.cpp b/demo/magicleap/src/main.cpp index d526e414..2f547a9f 100644 --- a/demo/magicleap/src/main.cpp +++ b/demo/magicleap/src/main.cpp @@ -29,8 +29,10 @@ #include #include -// Entry point to the Rust code -extern "C" MLResult magicleap_pathfinder_demo(EGLDisplay egl_display, EGLContext egl_context, const char* file_name); +// Entry points to the Rust code +extern "C" void* magicleap_pathfinder_demo_init(EGLDisplay egl_display, EGLContext egl_context); +extern "C" void magicleap_pathfinder_demo_load(void* app, const char* file_name); +extern "C" void magicleap_pathfinder_demo_run(void* app); // Initialization of the scene thread extern "C" void init_scene_thread(uint64_t id) { @@ -47,10 +49,6 @@ extern "C" void init_scene_thread(uint64_t id) { const char application_name[] = "com.mozilla.pathfinder.demo"; // Structures -struct application_context_t { - int dummy_value; -}; - struct graphics_context_t { EGLDisplay egl_display; @@ -116,24 +114,72 @@ graphics_context_t::~graphics_context_t() { } // Callbacks -static void onStop(void* application_context) +static void onStop(void* app) { - ((struct application_context_t*)application_context)->dummy_value = 0; ML_LOG(Info, "%s: On stop called.", application_name); } -static void onPause(void* application_context) +static void onPause(void* app) { - ((struct application_context_t*)application_context)->dummy_value = 1; ML_LOG(Info, "%s: On pause called.", application_name); } -static void onResume(void* application_context) +static void onResume(void* app) { - ((struct application_context_t*)application_context)->dummy_value = 2; ML_LOG(Info, "%s: On resume called.", application_name); } +static void onNewInitArg(void* app) +{ + ML_LOG(Info, "%s: On new init arg called.", application_name); + + // Get the file argument if there is one + MLLifecycleInitArgList* arg_list = nullptr; + const MLLifecycleInitArg* arg = nullptr; + const MLFileInfo* file_info = nullptr; + const char* file_name = nullptr; + int64_t arg_list_len = 0; + int64_t file_list_len = 0; + + if (MLResult_Ok != MLLifecycleGetInitArgList(&arg_list)) { + ML_LOG(Error, "%s: Failed to get init args.", application_name); + return; + } + + if (MLResult_Ok != MLLifecycleGetInitArgListLength(arg_list, &arg_list_len)) { + ML_LOG(Error, "%s: Failed to get init arg length.", application_name); + return; + } + + if (arg_list_len) { + if (MLResult_Ok != MLLifecycleGetInitArgByIndex(arg_list, 0, &arg)) { + ML_LOG(Error, "%s: Failed to get init arg.", application_name); + return; + } + + if (MLResult_Ok != MLLifecycleGetFileInfoListLength(arg, &file_list_len)) { + ML_LOG(Error, "%s: Failed to get file list length.", application_name); + return; + } + } + + if (file_list_len) { + if (MLResult_Ok != MLLifecycleGetFileInfoByIndex(arg, 0, &file_info)) { + ML_LOG(Error, "%s: Failed to get file info.", application_name); + return; + } + + if (MLResult_Ok != MLFileInfoGetFileName(file_info, &file_name)) { + ML_LOG(Error, "%s: Failed to get file name.", application_name); + return; + } + } + + // Tell pathfinder to load the file + magicleap_pathfinder_demo_load(app, file_name); + MLLifecycleFreeInitArgList(&arg_list); +} + extern "C" void logMessage(MLLogLevel lvl, char* msg) { if (MLLoggingLogLevelIsEnabled(lvl)) { MLLoggingLog(lvl, ML_DEFAULT_LOG_TAG, msg); @@ -144,20 +190,7 @@ int main() { // set up host-specific graphics surface graphics_context_t graphics_context; - // let system know our app has started - MLLifecycleCallbacks lifecycle_callbacks = {}; - lifecycle_callbacks.on_stop = onStop; - lifecycle_callbacks.on_pause = onPause; - lifecycle_callbacks.on_resume = onResume; - - struct application_context_t application_context; - application_context.dummy_value = 2; - - if (MLResult_Ok != MLLifecycleInit(&lifecycle_callbacks, (void*)&application_context)) { - ML_LOG(Error, "%s: Failed to initialize lifecycle.", application_name); - return -1; - } - + // Check privileges if (MLResult_Ok != MLPrivilegesStartup()) { ML_LOG(Error, "%s: Failed to initialize privileges.", application_name); return -1; @@ -182,56 +215,31 @@ int main() { return -1; } - // Get the file argument if there is one - MLLifecycleInitArgList* arg_list = nullptr; - const MLLifecycleInitArg* arg = nullptr; - const MLFileInfo* file_info = nullptr; - const char* file_name = nullptr; - int64_t arg_list_len = 0; - int64_t file_list_len = 0; - - if (MLResult_Ok != MLLifecycleGetInitArgList(&arg_list)) { - ML_LOG(Error, "%s: Failed to get init args.", application_name); + // Initialize pathfinder + void* app = magicleap_pathfinder_demo_init(graphics_context.egl_display, graphics_context.egl_context); + + // let system know our app has started + MLLifecycleCallbacks lifecycle_callbacks = {}; + lifecycle_callbacks.on_stop = onStop; + lifecycle_callbacks.on_pause = onPause; + lifecycle_callbacks.on_resume = onResume; + lifecycle_callbacks.on_new_initarg = onNewInitArg; + + if (MLResult_Ok != MLLifecycleInit(&lifecycle_callbacks, app)) { + ML_LOG(Error, "%s: Failed to initialize lifecycle.", application_name); return -1; } - if (MLResult_Ok != MLLifecycleGetInitArgListLength(arg_list, &arg_list_len)) { - ML_LOG(Error, "%s: Failed to get init arg length.", application_name); - return -1; - } - - if (arg_list_len) { - if (MLResult_Ok != MLLifecycleGetInitArgByIndex(arg_list, 0, &arg)) { - ML_LOG(Error, "%s: Failed to get init arg.", application_name); - return -1; - } - - if (MLResult_Ok != MLLifecycleGetFileInfoListLength(arg, &file_list_len)) { - ML_LOG(Error, "%s: Failed to get file list length.", application_name); - return -1; - } - } - - if (file_list_len) { - if (MLResult_Ok != MLLifecycleGetFileInfoByIndex(arg, 0, &file_info)) { - ML_LOG(Error, "%s: Failed to get file info.", application_name); - return -1; - } - - if (MLResult_Ok != MLFileInfoGetFileName(file_info, &file_name)) { - ML_LOG(Error, "%s: Failed to get file name.", application_name); - return -1; - } - } + // Get the initial argument if there is one. + onNewInitArg(app); // Run the demo! - ML_LOG(Info, "%s: Begin demo (%s).", application_name, file_name); - MLResult status = magicleap_pathfinder_demo(graphics_context.egl_display, graphics_context.egl_context, file_name); - ML_LOG(Info, "%s: End demo (%d).", application_name, status); + ML_LOG(Info, "%s: Begin demo.", application_name); + magicleap_pathfinder_demo_run(app); + ML_LOG(Info, "%s: End demo.", application_name); // Shut down MLPerceptionShutdown(); - MLLifecycleFreeInitArgList(&arg_list); return 0; }