mirror of
https://github.com/DarkFlippers/unleashed-firmware.git
synced 2026-11-13 10:27:37 +00:00
Follow-up to #1119, fixing the findings from the review of that PR (#1120). Compact's Left and Right did nothing on the bottom half of its left column: the jump to the other column ran past the end of the menu, and an index past the end is dropped. C64 had the same defect at menu sizes where its right column is only partly filled. Both now share one helper that jumps when the other column has anything in it, clamps into it when it is ragged, and stays put when it is empty. The Vertical style restored the canvas orientation before canvas_commit(), and canvas_commit() is what tags the frame for rpc_gui, so screen streaming showed a rotated image labelled horizontal. menu_reset() freed the item icon animations while holding the view model mutex, and each of those blocks on the timer daemon - which is where the menu's own scroll callback waits for that same mutex. Icons are released after the model has let go of them. A style plugin that failed to load was indistinguishable from one that loaded: the PluginManagerError was discarded and the entry point taken unvalidated, so a .fal with a null draw would have been branched to from the GUI thread. The settings picker offered any .fal in the shared loader plugin directory, skipped unreadable ones without a word, and showed "Default" for a style whose file had gone. It now filters on the appid prefix, reports what it skips and says "Missing". Also: Wii underflowed on a single-item menu, items are indexed on position rather than count, desktop settings terminates the strings it loads, and a style navigating outside the menu is logged - that silence is what let the dead keys ship unnoticed. The styles are a port of Momentum Firmware's menu styles, which nothing said; both are GPL-3.0, so this is credit. The plugin ABI that went into the SDK with no documentation now describes its threading, locking and bounds contract, and static_asserts pin the offsets a style reads, since a layout change moves no symbol and the SDK version in a .fal is compared on its major part only. No API change. +148 B .text, +131 B .rodata; -8 B across the style plugins. Not verified on hardware - see the device pass in the PR.
182 lines
5.5 KiB
C
182 lines
5.5 KiB
C
#pragma once
|
|
#include <furi.h>
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
#define RECORD_LOADER "loader"
|
|
#define LOADER_APPLICATIONS_NAME "Apps"
|
|
/**
|
|
* @brief Where menu style plugins live
|
|
*
|
|
* They declare requires=["loader"], and fbt deploys a plugin under each of its parent apps, so
|
|
* this is where they land; putting them anywhere else would mean patching the fbt resource
|
|
* packer. The directory is shared with any other loader plugin, hence the prefix below.
|
|
*/
|
|
#define LOADER_MENU_STYLES_PATH "/ext/apps_data/loader/plugins"
|
|
|
|
/**
|
|
* @brief Filename prefix that marks a menu style, since fbt names a .fal after its appid
|
|
*/
|
|
#define LOADER_MENU_STYLE_PREFIX "menu_style_"
|
|
|
|
typedef struct Loader Loader;
|
|
|
|
typedef enum {
|
|
LoaderStatusOk,
|
|
LoaderStatusErrorAppStarted,
|
|
LoaderStatusErrorUnknownApp,
|
|
LoaderStatusErrorInternal,
|
|
LoaderStatusErrorApiMismatch,
|
|
LoaderStatusErrorApiMismatchExit,
|
|
} LoaderStatus;
|
|
|
|
typedef enum {
|
|
LoaderEventTypeApplicationBeforeLoad,
|
|
LoaderEventTypeApplicationLoadFailed,
|
|
LoaderEventTypeApplicationStopped,
|
|
LoaderEventTypeNoMoreAppsInQueue, //<! The normal `Stopped` event still fires before this one
|
|
} LoaderEventType;
|
|
|
|
typedef struct {
|
|
LoaderEventType type;
|
|
} LoaderEvent;
|
|
|
|
typedef enum {
|
|
LoaderDeferredLaunchFlagNone = 0,
|
|
LoaderDeferredLaunchFlagGui = (1 << 1), //<! Report launch to the user via a dialog
|
|
} LoaderDeferredLaunchFlag;
|
|
|
|
/**
|
|
* @brief Start application
|
|
* @param[in] instance loader instance
|
|
* @param[in] name application name or id
|
|
* @param[in] args application arguments
|
|
* @param[out] error_message detailed error message, can be NULL
|
|
* @return LoaderStatus
|
|
*/
|
|
LoaderStatus
|
|
loader_start(Loader* instance, const char* name, const char* args, FuriString* error_message);
|
|
|
|
/**
|
|
* @brief Start application with GUI error message
|
|
* @param[in] instance loader instance
|
|
* @param[in] name application name or id
|
|
* @param[in] args application arguments
|
|
* @return LoaderStatus
|
|
*/
|
|
LoaderStatus loader_start_with_gui_error(Loader* loader, const char* name, const char* args);
|
|
|
|
/**
|
|
* @brief Start application detached with GUI error message
|
|
* @param[in] instance loader instance
|
|
* @param[in] name application name or id
|
|
* @param[in] args application arguments
|
|
*/
|
|
void loader_start_detached_with_gui_error(Loader* loader, const char* name, const char* args);
|
|
|
|
/**
|
|
* @brief Lock application start
|
|
* @param[in] instance loader instance
|
|
* @return true on success
|
|
*/
|
|
bool loader_lock(Loader* instance);
|
|
|
|
/**
|
|
* @brief Unlock application start
|
|
* @param[in] instance loader instance
|
|
*/
|
|
void loader_unlock(Loader* instance);
|
|
|
|
/**
|
|
* @brief Check if loader is locked
|
|
* @param[in] instance loader instance
|
|
* @return true if locked
|
|
*/
|
|
bool loader_is_locked(Loader* instance);
|
|
|
|
/**
|
|
* @brief Show loader menu
|
|
* @param[in] instance loader instance
|
|
*/
|
|
void loader_show_menu(Loader* instance);
|
|
|
|
/**
|
|
* @brief Set the main menu style
|
|
* @param[in] instance loader instance
|
|
* @param[in] name file name of a menu style plugin inside LOADER_MENU_STYLES_PATH, or NULL or an
|
|
* empty string for the built-in list. Copied; the previously loaded plugin is
|
|
* unloaded once the menu no longer references it.
|
|
*/
|
|
void loader_set_menu_style(Loader* instance, const char* name);
|
|
|
|
/**
|
|
* @brief Get loader pubsub
|
|
* @param[in] instance loader instance
|
|
* @return FuriPubSub*
|
|
*/
|
|
FuriPubSub* loader_get_pubsub(Loader* instance);
|
|
|
|
/**
|
|
* @brief Send a signal to the currently running application
|
|
*
|
|
* @param[in] instance pointer to the loader instance
|
|
* @param[in] signal signal value to be sent
|
|
* @param[inout] arg optional argument (can be of any value, including NULL)
|
|
*
|
|
* @return true if the signal was handled by the application, false otherwise
|
|
*/
|
|
bool loader_signal(Loader* instance, uint32_t signal, void* arg);
|
|
|
|
/**
|
|
* @brief Get the name of the currently running application
|
|
*
|
|
* @param[in] instance pointer to the loader instance
|
|
* @param[inout] name pointer to the string to contain the name (must be allocated)
|
|
* @return true if it was possible to get an application name, false otherwise
|
|
*/
|
|
bool loader_get_application_name(Loader* instance, FuriString* name);
|
|
|
|
/**
|
|
* @brief Get the launch path or name of the currently running application
|
|
*
|
|
* This is the string that was supplied to `loader_start` such that the current
|
|
* app is running now. It might be a name (in the case of internal apps) or a
|
|
* path (in the case of external apps). This value can be used to launch the
|
|
* same app again.
|
|
*
|
|
* @param[in] instance pointer to the loader instance
|
|
* @param[inout] name pointer to the string to contain the path or name
|
|
* (must be allocated)
|
|
* @return true if it was possible to get an application path, false otherwise
|
|
*/
|
|
bool loader_get_application_launch_path(Loader* instance, FuriString* name);
|
|
|
|
/**
|
|
* @brief Enqueues a request to launch an application after the current one
|
|
*
|
|
* @param[in] instance pointer to the loader instance
|
|
* @param[in] name pointer to the name or path of the application, or NULL to
|
|
* cancel a previous request
|
|
* @param[in] args pointer to argument to provide to the next app
|
|
* @param[in] flags additional flags. see enum documentation for more info
|
|
*/
|
|
void loader_enqueue_launch(
|
|
Loader* instance,
|
|
const char* name,
|
|
const char* args,
|
|
LoaderDeferredLaunchFlag flags);
|
|
|
|
/**
|
|
* @brief Removes all requests to launch applications after the current one
|
|
* exits
|
|
*
|
|
* @param[in] instance pointer to the loader instance
|
|
*/
|
|
void loader_clear_launch_queue(Loader* instance);
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|