diff --git a/skeleton/SYSTEM/desktop/bin/run_hooks.sh b/skeleton/SYSTEM/desktop/bin/run_hooks.sh new file mode 100755 index 000000000..30b86ca60 --- /dev/null +++ b/skeleton/SYSTEM/desktop/bin/run_hooks.sh @@ -0,0 +1,36 @@ +#!/bin/sh +# run_hooks.sh - shared hook runner for NextUI +# Usage: run_hooks.sh [--sync-only] +# +# dir-name: directory name under $USERDATA_PATH/.hooks/ (e.g. pre-launch.d, boot.d) +# --sync-only: force all scripts to run synchronously +# +# By default, scripts run in the background. Scripts ending in .sync.sh +# always run synchronously. All background scripts are waited on before exit. + +DIR_NAME="$1" +SYNC_ONLY="${2:-}" + +: "${SDCARD_PATH:=/var/tmp/nextui/sdcard}" +: "${PLATFORM:=desktop}" +: "${USERDATA_PATH:=$SDCARD_PATH/.userdata/$PLATFORM}" + +HOOK_DIR="$USERDATA_PATH/.hooks/$DIR_NAME" +[ -d "$HOOK_DIR" ] || exit 0 + +case "$DIR_NAME" in + pre-*) export HOOK_PHASE="pre" ;; + post-*) export HOOK_PHASE="post" ;; + boot*) export HOOK_PHASE="boot" ;; +esac +export HOOK_CATEGORY="$DIR_NAME" + +for script in "$HOOK_DIR"/*.sh; do + [ -f "$script" ] || continue + if [ "$SYNC_ONLY" = "--sync-only" ] || echo "$script" | grep -q '\.sync\.sh$'; then + ( "$script" ) > /dev/null 2>&1 || true + else + ( "$script" ) > /dev/null 2>&1 & + fi +done +wait diff --git a/skeleton/SYSTEM/desktop/paks/MinUI.pak/launch.sh b/skeleton/SYSTEM/desktop/paks/MinUI.pak/launch.sh index 5c1f99ae0..5b6922bcc 100755 --- a/skeleton/SYSTEM/desktop/paks/MinUI.pak/launch.sh +++ b/skeleton/SYSTEM/desktop/paks/MinUI.pak/launch.sh @@ -45,8 +45,29 @@ if [ -f "$AUTO_PATH" ]; then "$AUTO_PATH" fi +# Composable boot hooks (run after auto.sh for backward compatibility) +"$SYSTEM_PATH/bin/run_hooks.sh" boot.d + cd $(dirname "$0") +####################################### +# Hook system + +parse_hook_cmd() { + HOOK_CMD="$1" + HOOK_EMU_PATH=$(echo "$HOOK_CMD" | sed "s/^'\\([^']*\\)'.*/\\1/") + _remainder=$(echo "$HOOK_CMD" | sed "s/^'[^']*'//") + if echo "$_remainder" | grep -q "'"; then + HOOK_TYPE="rom" + HOOK_ROM_PATH=$(echo "$_remainder" | sed "s/.*'\\([^']*\\)'.*/\\1/") + else + HOOK_TYPE="pak" + HOOK_ROM_PATH="" + fi + [ -f /tmp/last.txt ] && HOOK_LAST=$(cat /tmp/last.txt) || HOOK_LAST="" + export HOOK_CMD HOOK_EMU_PATH HOOK_TYPE HOOK_ROM_PATH HOOK_LAST +} + ####################################### EXEC_PATH="/tmp/nextui_exec" @@ -57,7 +78,10 @@ touch "$EXEC_PATH" && sync if [ -f $NEXT_PATH ]; then CMD=`cat $NEXT_PATH` + parse_hook_cmd "$CMD" + "$SYSTEM_PATH/bin/run_hooks.sh" pre-launch.d eval $CMD + "$SYSTEM_PATH/bin/run_hooks.sh" post-launch.d rm -f $NEXT_PATH fi #done diff --git a/skeleton/SYSTEM/tg5040/bin/run_hooks.sh b/skeleton/SYSTEM/tg5040/bin/run_hooks.sh new file mode 100755 index 000000000..96fbe4833 --- /dev/null +++ b/skeleton/SYSTEM/tg5040/bin/run_hooks.sh @@ -0,0 +1,36 @@ +#!/bin/sh +# run_hooks.sh - shared hook runner for NextUI +# Usage: run_hooks.sh [--sync-only] +# +# dir-name: directory name under $USERDATA_PATH/.hooks/ (e.g. pre-launch.d, boot.d) +# --sync-only: force all scripts to run synchronously +# +# By default, scripts run in the background. Scripts ending in .sync.sh +# always run synchronously. All background scripts are waited on before exit. + +DIR_NAME="$1" +SYNC_ONLY="${2:-}" + +: "${SDCARD_PATH:=/mnt/SDCARD}" +: "${PLATFORM:=tg5040}" +: "${USERDATA_PATH:=$SDCARD_PATH/.userdata/$PLATFORM}" + +HOOK_DIR="$USERDATA_PATH/.hooks/$DIR_NAME" +[ -d "$HOOK_DIR" ] || exit 0 + +case "$DIR_NAME" in + pre-*) export HOOK_PHASE="pre" ;; + post-*) export HOOK_PHASE="post" ;; + boot*) export HOOK_PHASE="boot" ;; +esac +export HOOK_CATEGORY="$DIR_NAME" + +for script in "$HOOK_DIR"/*.sh; do + [ -f "$script" ] || continue + if [ "$SYNC_ONLY" = "--sync-only" ] || echo "$script" | grep -q '\.sync\.sh$'; then + ( "$script" ) > /dev/null 2>&1 || true + else + ( "$script" ) > /dev/null 2>&1 & + fi +done +wait diff --git a/skeleton/SYSTEM/tg5040/bin/suspend b/skeleton/SYSTEM/tg5040/bin/suspend index 4a384d4c7..593159423 100644 --- a/skeleton/SYSTEM/tg5040/bin/suspend +++ b/skeleton/SYSTEM/tg5040/bin/suspend @@ -16,6 +16,10 @@ asound_state_dir=/tmp/asound-suspend before() { >&2 echo "Preparing for suspend..." + # Run pre-sleep hooks synchronously before services are stopped. + # Subshell ensures a crashing hook cannot block suspend. + ( "$SYSTEM_PATH/bin/run_hooks.sh" pre-sleep.d --sync-only ) >/dev/null 2>&1 || true + >&2 echo "Saving mixer state..." mkdir -p "$asound_state_dir" alsactl --file "$asound_state_dir/asound.state.pre" store || true @@ -36,6 +40,9 @@ before() { after() { >&2 echo "Resumed from suspend." + # Run post-resume hooks in background immediately after wake. + ( "$SYSTEM_PATH/bin/run_hooks.sh" post-resume.d ) >/dev/null 2>&1 & + if [ -n "$wifid_running" ]; then >&2 echo "Starting wpa_supplicant..." /etc/wifi/wifi_init.sh start || true diff --git a/skeleton/SYSTEM/tg5040/paks/MinUI.pak/launch.sh b/skeleton/SYSTEM/tg5040/paks/MinUI.pak/launch.sh index 09528cf3a..a3e141076 100755 --- a/skeleton/SYSTEM/tg5040/paks/MinUI.pak/launch.sh +++ b/skeleton/SYSTEM/tg5040/paks/MinUI.pak/launch.sh @@ -151,8 +151,29 @@ if [ -f "$AUTO_PATH" ]; then "$AUTO_PATH" fi +# Composable boot hooks (run after auto.sh for backward compatibility) +"$SYSTEM_PATH/bin/run_hooks.sh" boot.d + cd $(dirname "$0") +####################################### +# Hook system + +parse_hook_cmd() { + HOOK_CMD="$1" + HOOK_EMU_PATH=$(echo "$HOOK_CMD" | sed "s/^'\\([^']*\\)'.*/\\1/") + _remainder=$(echo "$HOOK_CMD" | sed "s/^'[^']*'//") + if echo "$_remainder" | grep -q "'"; then + HOOK_TYPE="rom" + HOOK_ROM_PATH=$(echo "$_remainder" | sed "s/.*'\\([^']*\\)'.*/\\1/") + else + HOOK_TYPE="pak" + HOOK_ROM_PATH="" + fi + [ -f /tmp/last.txt ] && HOOK_LAST=$(cat /tmp/last.txt) || HOOK_LAST="" + export HOOK_CMD HOOK_EMU_PATH HOOK_TYPE HOOK_ROM_PATH HOOK_LAST +} + ####################################### # kill show2.elf if running @@ -167,7 +188,10 @@ while [ -f $EXEC_PATH ]; do if [ -f $NEXT_PATH ]; then CMD=`cat $NEXT_PATH` + parse_hook_cmd "$CMD" + "$SYSTEM_PATH/bin/run_hooks.sh" pre-launch.d eval $CMD + "$SYSTEM_PATH/bin/run_hooks.sh" post-launch.d rm -f $NEXT_PATH echo $CPU_SPEED_PERF > $CPU_PATH fi diff --git a/skeleton/SYSTEM/tg5050/bin/run_hooks.sh b/skeleton/SYSTEM/tg5050/bin/run_hooks.sh new file mode 100755 index 000000000..7e6886546 --- /dev/null +++ b/skeleton/SYSTEM/tg5050/bin/run_hooks.sh @@ -0,0 +1,36 @@ +#!/bin/sh +# run_hooks.sh - shared hook runner for NextUI +# Usage: run_hooks.sh [--sync-only] +# +# dir-name: directory name under $USERDATA_PATH/.hooks/ (e.g. pre-launch.d, boot.d) +# --sync-only: force all scripts to run synchronously +# +# By default, scripts run in the background. Scripts ending in .sync.sh +# always run synchronously. All background scripts are waited on before exit. + +DIR_NAME="$1" +SYNC_ONLY="${2:-}" + +: "${SDCARD_PATH:=/mnt/SDCARD}" +: "${PLATFORM:=tg5050}" +: "${USERDATA_PATH:=$SDCARD_PATH/.userdata/$PLATFORM}" + +HOOK_DIR="$USERDATA_PATH/.hooks/$DIR_NAME" +[ -d "$HOOK_DIR" ] || exit 0 + +case "$DIR_NAME" in + pre-*) export HOOK_PHASE="pre" ;; + post-*) export HOOK_PHASE="post" ;; + boot*) export HOOK_PHASE="boot" ;; +esac +export HOOK_CATEGORY="$DIR_NAME" + +for script in "$HOOK_DIR"/*.sh; do + [ -f "$script" ] || continue + if [ "$SYNC_ONLY" = "--sync-only" ] || echo "$script" | grep -q '\.sync\.sh$'; then + ( "$script" ) > /dev/null 2>&1 || true + else + ( "$script" ) > /dev/null 2>&1 & + fi +done +wait diff --git a/skeleton/SYSTEM/tg5050/bin/suspend b/skeleton/SYSTEM/tg5050/bin/suspend index 9062b84ef..090cfbad5 100644 --- a/skeleton/SYSTEM/tg5050/bin/suspend +++ b/skeleton/SYSTEM/tg5050/bin/suspend @@ -16,6 +16,10 @@ asound_state_dir=/tmp/asound-suspend before() { >&2 echo "Preparing for suspend..." + # Run pre-sleep hooks synchronously before services are stopped. + # Subshell ensures a crashing hook cannot block suspend. + ( "$SYSTEM_PATH/bin/run_hooks.sh" pre-sleep.d --sync-only ) >/dev/null 2>&1 || true + >&2 echo "Saving mixer state..." mkdir -p "$asound_state_dir" alsactl --file "$asound_state_dir/asound.state.pre" store || true @@ -36,6 +40,9 @@ before() { after() { >&2 echo "Resumed from suspend." + # Run post-resume hooks in background immediately after wake. + ( "$SYSTEM_PATH/bin/run_hooks.sh" post-resume.d ) >/dev/null 2>&1 & + if [ -n "$wifid_running" ]; then >&2 echo "Starting wpa_supplicant..." $SYSTEM_PATH/etc/wifi/wifi_init.sh start || true diff --git a/skeleton/SYSTEM/tg5050/paks/MinUI.pak/launch.sh b/skeleton/SYSTEM/tg5050/paks/MinUI.pak/launch.sh index d73b92a2a..db8fb90ab 100755 --- a/skeleton/SYSTEM/tg5050/paks/MinUI.pak/launch.sh +++ b/skeleton/SYSTEM/tg5050/paks/MinUI.pak/launch.sh @@ -164,8 +164,29 @@ if [ -f "$AUTO_PATH" ]; then echo after auto.sh `cat /proc/uptime` >> /tmp/nextui_boottime fi +# Composable boot hooks (run after auto.sh for backward compatibility) +"$SYSTEM_PATH/bin/run_hooks.sh" boot.d + cd $(dirname "$0") +####################################### +# Hook system + +parse_hook_cmd() { + HOOK_CMD="$1" + HOOK_EMU_PATH=$(echo "$HOOK_CMD" | sed "s/^'\\([^']*\\)'.*/\\1/") + _remainder=$(echo "$HOOK_CMD" | sed "s/^'[^']*'//") + if echo "$_remainder" | grep -q "'"; then + HOOK_TYPE="rom" + HOOK_ROM_PATH=$(echo "$_remainder" | sed "s/.*'\\([^']*\\)'.*/\\1/") + else + HOOK_TYPE="pak" + HOOK_ROM_PATH="" + fi + [ -f /tmp/last.txt ] && HOOK_LAST=$(cat /tmp/last.txt) || HOOK_LAST="" + export HOOK_CMD HOOK_EMU_PATH HOOK_TYPE HOOK_ROM_PATH HOOK_LAST +} + ####################################### # kill show2.elf if running @@ -180,7 +201,10 @@ while [ -f $EXEC_PATH ]; do if [ -f $NEXT_PATH ]; then CMD=`cat $NEXT_PATH` + parse_hook_cmd "$CMD" + "$SYSTEM_PATH/bin/run_hooks.sh" pre-launch.d eval $CMD + "$SYSTEM_PATH/bin/run_hooks.sh" post-launch.d rm -f $NEXT_PATH echo $CPU_SPEED_PERF > $BIG_PATH fi