Fix SIM2 PIN verification and replace Plymouth boot splash with rotating Bananarchy logo
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 40 KiB |
|
After Width: | Height: | Size: 38 KiB |
|
After Width: | Height: | Size: 1.2 KiB |
@@ -0,0 +1,15 @@
|
|||||||
|
#!/sbin/openrc-run
|
||||||
|
|
||||||
|
name="Exit plymouthd"
|
||||||
|
description="Stop plymouthd before running the graphical UI"
|
||||||
|
|
||||||
|
depend() {
|
||||||
|
before display-manager
|
||||||
|
before tinydm
|
||||||
|
}
|
||||||
|
|
||||||
|
start() {
|
||||||
|
ebegin "Stopping boot splash"
|
||||||
|
/usr/bin/plymouth quit 2>/dev/null || true
|
||||||
|
eend 0
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
#!/sbin/openrc-run
|
||||||
|
|
||||||
|
supervisor=supervise-daemon
|
||||||
|
command=/usr/sbin/ModemManager
|
||||||
|
command_args="${modemmanager_opts}"
|
||||||
|
|
||||||
|
description="ModemManager Daemon"
|
||||||
|
|
||||||
|
depend() {
|
||||||
|
need dbus
|
||||||
|
use polkit
|
||||||
|
after msm8909-modem-wwan-port
|
||||||
|
after msm-modem-uim-selection
|
||||||
|
}
|
||||||
|
|
||||||
|
start_pre() {
|
||||||
|
killall -q ModemManager 2>/dev/null || true
|
||||||
|
}
|
||||||
|
|
||||||
|
stop_post() {
|
||||||
|
killall -q ModemManager 2>/dev/null || true
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
#!/sbin/openrc-run
|
||||||
|
supervisor=supervise-daemon
|
||||||
|
|
||||||
|
name="Polkit System Daemon"
|
||||||
|
description="Provide System authentication via PolicyKit1 D-Bus service"
|
||||||
|
|
||||||
|
command=/usr/lib/polkit-1/polkitd
|
||||||
|
command_args="${POLKIT_OPTS:---no-debug --replace}"
|
||||||
|
|
||||||
|
depend() {
|
||||||
|
need dbus
|
||||||
|
}
|
||||||
@@ -109,6 +109,8 @@ parse_uim_card_status() {
|
|||||||
BEGIN {
|
BEGIN {
|
||||||
prim_slot = 0
|
prim_slot = 0
|
||||||
prim_app = 0
|
prim_app = 0
|
||||||
|
sec_slot = 0
|
||||||
|
sec_app = 0
|
||||||
cur_slot = 0
|
cur_slot = 0
|
||||||
in_app = 0
|
in_app = 0
|
||||||
for (s = 1; s <= 2; s++) {
|
for (s = 1; s <= 2; s++) {
|
||||||
@@ -141,6 +143,20 @@ parse_uim_card_status() {
|
|||||||
prim_app = line + 0
|
prim_app = line + 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/Secondary GW:/ {
|
||||||
|
if ($0 ~ /slot \x27[0-9]+\x27/) {
|
||||||
|
line = $0
|
||||||
|
sub(/.*slot \x27/, "", line)
|
||||||
|
sub(/\x27.*/, "", line)
|
||||||
|
sec_slot = line + 0
|
||||||
|
}
|
||||||
|
if ($0 ~ /application \x27[0-9]+\x27/) {
|
||||||
|
line = $0
|
||||||
|
sub(/.*application \x27/, "", line)
|
||||||
|
sub(/\x27.*/, "", line)
|
||||||
|
sec_app = line + 0
|
||||||
|
}
|
||||||
|
}
|
||||||
/^[[:space:]]*Slot \[[0-9]+\]:/ {
|
/^[[:space:]]*Slot \[[0-9]+\]:/ {
|
||||||
line = $0
|
line = $0
|
||||||
sub(/.*Slot \[/, "", line)
|
sub(/.*Slot \[/, "", line)
|
||||||
@@ -239,7 +255,16 @@ parse_uim_card_status() {
|
|||||||
printf "PREFERRED_SLOT=%d\n", (pref == 2 ? 2 : 1)
|
printf "PREFERRED_SLOT=%d\n", (pref == 2 ? 2 : 1)
|
||||||
printf "PRIMARY_GW_SLOT=%d\n", prim_slot
|
printf "PRIMARY_GW_SLOT=%d\n", prim_slot
|
||||||
printf "PRIMARY_GW_APP=%d\n", prim_app
|
printf "PRIMARY_GW_APP=%d\n", prim_app
|
||||||
|
printf "SECONDARY_GW_SLOT=%d\n", sec_slot
|
||||||
|
printf "SECONDARY_GW_APP=%d\n", sec_app
|
||||||
for (s = 1; s <= 2; s++) {
|
for (s = 1; s <= 2; s++) {
|
||||||
|
gsub(/[^A-Za-z0-9_.:-]/, "_", cstate[s])
|
||||||
|
gsub(/[^A-Za-z0-9_.:-]/, "_", rawstate[s])
|
||||||
|
gsub(/[^A-Za-z0-9_.:-]/, "_", app_type[s])
|
||||||
|
gsub(/[^A-Za-z0-9_.:-]/, "_", app_state[s])
|
||||||
|
gsub(/[^A-Za-z0-9_.:-]/, "", aid[s])
|
||||||
|
gsub(/[^A-Za-z0-9_.:-]/, "_", pin1_state[s])
|
||||||
|
gsub(/[^A-Za-z0-9_.:-]/, "_", upin_state[s])
|
||||||
printf "SLOT%d_STATE=%s\n", s, cstate[s]
|
printf "SLOT%d_STATE=%s\n", s, cstate[s]
|
||||||
printf "SLOT%d_RAW_STATE=%s\n", s, rawstate[s]
|
printf "SLOT%d_RAW_STATE=%s\n", s, rawstate[s]
|
||||||
printf "SLOT%d_APP_TYPE=%s\n", s, app_type[s]
|
printf "SLOT%d_APP_TYPE=%s\n", s, app_type[s]
|
||||||
@@ -355,6 +380,7 @@ parse_nas_serving_system() {
|
|||||||
printf "NAS_CS_STATE=%s\n", cs_state
|
printf "NAS_CS_STATE=%s\n", cs_state
|
||||||
printf "NAS_PS_STATE=%s\n", ps_state
|
printf "NAS_PS_STATE=%s\n", ps_state
|
||||||
printf "NAS_RAT=%s\n", rat
|
printf "NAS_RAT=%s\n", rat
|
||||||
|
printf "NAS_RADIO=%s\n", rat
|
||||||
printf "NAS_MCC=%s\n", mcc
|
printf "NAS_MCC=%s\n", mcc
|
||||||
printf "NAS_MNC=%s\n", mnc
|
printf "NAS_MNC=%s\n", mnc
|
||||||
printf "NAS_OPERATOR=%s\n", op_desc
|
printf "NAS_OPERATOR=%s\n", op_desc
|
||||||
@@ -450,6 +476,10 @@ provision_slot() {
|
|||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [ "${SECONDARY_GW_SLOT:-0}" = "$chosen_slot" ]; then
|
||||||
|
$QMICLI_MODEM --uim-change-provisioning-session='activate=no,session-type=secondary-gw-provisioning' >/dev/null 2>&1 || true
|
||||||
|
fi
|
||||||
|
|
||||||
if [ "$PRIMARY_GW_SLOT" != "0" ]; then
|
if [ "$PRIMARY_GW_SLOT" != "0" ]; then
|
||||||
$QMICLI_MODEM --uim-change-provisioning-session='activate=no,session-type=primary-gw-provisioning' >/dev/null 2>&1 || true
|
$QMICLI_MODEM --uim-change-provisioning-session='activate=no,session-type=primary-gw-provisioning' >/dev/null 2>&1 || true
|
||||||
fi
|
fi
|
||||||
@@ -481,6 +511,9 @@ prepare_slot_for_pin_op() {
|
|||||||
fi
|
fi
|
||||||
eval "target_aid=\$SLOT${slot}_AID"
|
eval "target_aid=\$SLOT${slot}_AID"
|
||||||
if [ "$PRIMARY_GW_SLOT" != "$slot" ]; then
|
if [ "$PRIMARY_GW_SLOT" != "$slot" ]; then
|
||||||
|
if [ "${SECONDARY_GW_SLOT:-0}" = "$slot" ]; then
|
||||||
|
$QMICLI_MODEM --uim-change-provisioning-session='activate=no,session-type=secondary-gw-provisioning' >/dev/null 2>&1 || true
|
||||||
|
fi
|
||||||
if [ "$PRIMARY_GW_SLOT" != "0" ]; then
|
if [ "$PRIMARY_GW_SLOT" != "0" ]; then
|
||||||
$QMICLI_MODEM --uim-change-provisioning-session='activate=no,session-type=primary-gw-provisioning' >/dev/null 2>&1 || true
|
$QMICLI_MODEM --uim-change-provisioning-session='activate=no,session-type=primary-gw-provisioning' >/dev/null 2>&1 || true
|
||||||
fi
|
fi
|
||||||
@@ -490,12 +523,26 @@ prepare_slot_for_pin_op() {
|
|||||||
else
|
else
|
||||||
$QMICLI_MODEM --uim-change-provisioning-session="slot=$slot,activate=yes,session-type=primary-gw-provisioning" >/dev/null 2>&1 || true
|
$QMICLI_MODEM --uim-change-provisioning-session="slot=$slot,activate=yes,session-type=primary-gw-provisioning" >/dev/null 2>&1 || true
|
||||||
fi
|
fi
|
||||||
sleep 0.6
|
sleep 0.5
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
restart_modemmanager_clean() {
|
||||||
|
if command -v rc-service >/dev/null 2>&1; then
|
||||||
|
timeout 4 rc-service polkit start >/dev/null 2>&1 || true
|
||||||
|
timeout 6 rc-service modemmanager restart >/dev/null 2>&1 || {
|
||||||
|
killall -q ModemManager 2>/dev/null || true
|
||||||
|
sleep 0.3
|
||||||
|
timeout 6 rc-service modemmanager zap >/dev/null 2>&1 || true
|
||||||
|
timeout 6 rc-service modemmanager start >/dev/null 2>&1 || true
|
||||||
|
}
|
||||||
|
elif command -v systemctl >/dev/null 2>&1; then
|
||||||
|
timeout 6 systemctl restart ModemManager >/dev/null 2>&1 || true
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
enable_and_register_modem() {
|
enable_and_register_modem() {
|
||||||
target_slot="${1:-$PREFERRED_SIM_SLOT}"
|
target_slot="${1:-$PREFERRED_SIM_SLOT}"
|
||||||
force_unlock="${2:-0}"
|
force_unlock="${2:-0}"
|
||||||
@@ -506,7 +553,7 @@ enable_and_register_modem() {
|
|||||||
|
|
||||||
i=0
|
i=0
|
||||||
mm_state=""
|
mm_state=""
|
||||||
while [ "$i" -lt 10 ]; do
|
while [ "$i" -lt 8 ]; do
|
||||||
mm_state="$(timeout 3 mmcli -m any -K 2>/dev/null | awk -F': ' '/^modem\.generic\.state / {print $2; exit}' || true)"
|
mm_state="$(timeout 3 mmcli -m any -K 2>/dev/null | awk -F': ' '/^modem\.generic\.state / {print $2; exit}' || true)"
|
||||||
if [ -n "$mm_state" ]; then
|
if [ -n "$mm_state" ]; then
|
||||||
break
|
break
|
||||||
@@ -515,12 +562,8 @@ enable_and_register_modem() {
|
|||||||
i=$((i + 1))
|
i=$((i + 1))
|
||||||
done
|
done
|
||||||
|
|
||||||
if [ "$mm_state" = "failed" ] || { [ "$force_unlock" = "1" ] && [ "$mm_state" = "locked" ]; }; then
|
if [ -z "$mm_state" ] || [ "$mm_state" = "failed" ] || { [ "$force_unlock" = "1" ] && [ "$mm_state" = "locked" ]; }; then
|
||||||
if command -v rc-service >/dev/null 2>&1; then
|
restart_modemmanager_clean
|
||||||
timeout 6 rc-service modemmanager restart >/dev/null 2>&1 || true
|
|
||||||
elif command -v systemctl >/dev/null 2>&1; then
|
|
||||||
timeout 6 systemctl restart ModemManager >/dev/null 2>&1 || true
|
|
||||||
fi
|
|
||||||
i=0
|
i=0
|
||||||
mm_state=""
|
mm_state=""
|
||||||
while [ "$i" -lt 10 ]; do
|
while [ "$i" -lt 10 ]; do
|
||||||
@@ -604,6 +647,15 @@ case "$cmd" in
|
|||||||
echo "PREFERRED_SLOT=$PREFERRED_SIM_SLOT"
|
echo "PREFERRED_SLOT=$PREFERRED_SIM_SLOT"
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
eval "$(parse_uim_card_status "$QMI_CARDS" "$PREFERRED_SIM_SLOT")"
|
||||||
|
if [ "$PRIMARY_GW_SLOT" = "0" ] && { [ "$SLOT1_STATE" = "present" ] || [ "$SLOT2_STATE" = "present" ]; }; then
|
||||||
|
SIM_WAIT_TIME=1
|
||||||
|
provision_slot "$PREFERRED_SIM_SLOT" 2 >/dev/null 2>&1 || true
|
||||||
|
QMI_CARDS_NEW="$($QMICLI_MODEM --uim-get-card-status 2>/dev/null || true)"
|
||||||
|
if [ -n "$QMI_CARDS_NEW" ]; then
|
||||||
|
QMI_CARDS="$QMI_CARDS_NEW"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
echo "MODEM_AVAILABLE=1"
|
echo "MODEM_AVAILABLE=1"
|
||||||
parse_uim_card_status "$QMI_CARDS" "$PREFERRED_SIM_SLOT"
|
parse_uim_card_status "$QMI_CARDS" "$PREFERRED_SIM_SLOT"
|
||||||
QMI_NAS="$($QMICLI_MODEM --nas-get-serving-system 2>/dev/null || true)"
|
QMI_NAS="$($QMICLI_MODEM --nas-get-serving-system 2>/dev/null || true)"
|
||||||
@@ -622,11 +674,7 @@ case "$cmd" in
|
|||||||
save_preferred_slot "$target"
|
save_preferred_slot "$target"
|
||||||
SIM_WAIT_TIME=3
|
SIM_WAIT_TIME=3
|
||||||
provision_slot "$target" 5
|
provision_slot "$target" 5
|
||||||
if command -v rc-service >/dev/null 2>&1; then
|
restart_modemmanager_clean
|
||||||
timeout 6 rc-service modemmanager restart >/dev/null 2>&1 || true
|
|
||||||
elif command -v systemctl >/dev/null 2>&1; then
|
|
||||||
timeout 6 systemctl restart ModemManager >/dev/null 2>&1 || true
|
|
||||||
fi
|
|
||||||
spawn_enable_and_register "$target" 0
|
spawn_enable_and_register "$target" 0
|
||||||
exit 0
|
exit 0
|
||||||
;;
|
;;
|
||||||
@@ -639,30 +687,29 @@ case "$cmd" in
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
prepare_slot_for_pin_op "$slot"
|
prepare_slot_for_pin_op "$slot"
|
||||||
|
eval "before_ret=\${SLOT${slot}_PIN1_RETRIES:-3}"
|
||||||
verified=0
|
verified=0
|
||||||
|
wrong_pin=0
|
||||||
sim_id="$(timeout 3 mmcli -m any 2>/dev/null | grep -oE 'SIM/[0-9]+' | head -n1 | cut -d'/' -f2 || true)"
|
sim_id="$(timeout 3 mmcli -m any 2>/dev/null | grep -oE 'SIM/[0-9]+' | head -n1 | cut -d'/' -f2 || true)"
|
||||||
if [ -n "$sim_id" ] && timeout 4 mmcli -i "$sim_id" --pin="$pin" >/dev/null 2>&1; then
|
if [ -n "$sim_id" ]; then
|
||||||
verified=1
|
mm_pin_out="$(timeout 5 mmcli -i "$sim_id" --pin="$pin" 2>&1)" && verified=1 || {
|
||||||
|
if printf "%s\n" "$mm_pin_out" | grep -qiE "IncorrectPin|SimPin|SimPuk|PinBlocked|incorrect"; then
|
||||||
|
wrong_pin=1
|
||||||
|
fi
|
||||||
|
}
|
||||||
fi
|
fi
|
||||||
if [ "$verified" = "0" ] && [ -n "$QMICLI_MODEM" ]; then
|
if [ "$verified" = "0" ] && [ "$wrong_pin" = "0" ] && [ -n "$QMICLI_MODEM" ]; then
|
||||||
if $QMICLI_MODEM --uim-verify-pin="PIN1,$pin,session-type=primary-gw-provisioning" >/dev/null 2>&1; then
|
qmi_pin_out="$($QMICLI_MODEM --uim-verify-pin="PIN1,$pin,session-type=primary-gw-provisioning" 2>&1)" && verified=1 || {
|
||||||
verified=1
|
if printf "%s\n" "$qmi_pin_out" | grep -qiE "IncorrectPin|PinBlocked|Blocked"; then
|
||||||
elif $QMICLI_MODEM --uim-verify-pin="PIN1,$pin,session-type=card-slot-$slot" >/dev/null 2>&1; then
|
wrong_pin=1
|
||||||
verified=1
|
fi
|
||||||
elif $QMICLI_MODEM --uim-verify-pin="PIN1,$pin" >/dev/null 2>&1; then
|
}
|
||||||
verified=1
|
if [ "$verified" = "0" ] && [ "$wrong_pin" = "0" ]; then
|
||||||
elif $QMICLI_MODEM --uim-verify-pin="UPIN,$pin,session-type=primary-gw-provisioning" >/dev/null 2>&1; then
|
qmi_pin_out="$($QMICLI_MODEM --uim-verify-pin="PIN1,$pin,session-type=card-slot-$slot" 2>&1)" && verified=1 || {
|
||||||
verified=1
|
if printf "%s\n" "$qmi_pin_out" | grep -qiE "IncorrectPin|PinBlocked|Blocked"; then
|
||||||
elif $QMICLI_MODEM --uim-verify-pin="UPIN,$pin,session-type=card-slot-$slot" >/dev/null 2>&1; then
|
wrong_pin=1
|
||||||
verified=1
|
fi
|
||||||
elif $QMICLI_MODEM --dms-uim-verify-pin="PIN,$pin" >/dev/null 2>&1; then
|
}
|
||||||
verified=1
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
if [ "$verified" = "0" ]; then
|
|
||||||
at_cpin="$("$0" at auto "AT+CPIN=\"$pin\"" 2>/dev/null || true)"
|
|
||||||
if printf "%s\n" "$at_cpin" | grep -qE "(^|[[:space:]])OK([[:space:]]|$)"; then
|
|
||||||
verified=1
|
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
if [ "$verified" = "0" ] && [ -n "$QMICLI_MODEM" ]; then
|
if [ "$verified" = "0" ] && [ -n "$QMICLI_MODEM" ]; then
|
||||||
@@ -671,18 +718,24 @@ case "$cmd" in
|
|||||||
eval "$(parse_uim_card_status "$QMI_CARDS_AFTER" "$slot")"
|
eval "$(parse_uim_card_status "$QMI_CARDS_AFTER" "$slot")"
|
||||||
eval "after_pin1=\$SLOT${slot}_PIN1_STATE"
|
eval "after_pin1=\$SLOT${slot}_PIN1_STATE"
|
||||||
eval "after_app=\$SLOT${slot}_APP_STATE"
|
eval "after_app=\$SLOT${slot}_APP_STATE"
|
||||||
|
eval "after_ret=\$SLOT${slot}_PIN1_RETRIES"
|
||||||
if [ "$after_pin1" = "enabled-verified" ] || [ "$after_pin1" = "disabled" ] || [ "$after_app" = "ready" ]; then
|
if [ "$after_pin1" = "enabled-verified" ] || [ "$after_pin1" = "disabled" ] || [ "$after_app" = "ready" ]; then
|
||||||
verified=1
|
verified=1
|
||||||
|
elif [ "$after_ret" -lt "$before_ret" ] 2>/dev/null; then
|
||||||
|
wrong_pin=1
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
if [ "$verified" = "0" ] && [ "$wrong_pin" = "0" ]; then
|
||||||
|
at_cpin="$("$0" at auto "AT+CPIN=\"$pin\"" 2>/dev/null || true)"
|
||||||
|
if printf "%s\n" "$at_cpin" | grep -qE "(^|[[:space:]])OK([[:space:]]|$)"; then
|
||||||
|
verified=1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
if [ "$verified" = "1" ]; then
|
if [ "$verified" = "1" ]; then
|
||||||
save_preferred_slot "$slot"
|
save_preferred_slot "$slot"
|
||||||
SIM_WAIT_TIME=2
|
SIM_WAIT_TIME=2
|
||||||
provision_slot "$slot" 3 >/dev/null 2>&1 || true
|
provision_slot "$slot" 3 >/dev/null 2>&1 || true
|
||||||
if [ -n "$sim_id" ]; then
|
|
||||||
timeout 4 mmcli -i "$sim_id" --pin="$pin" >/dev/null 2>&1 || true
|
|
||||||
fi
|
|
||||||
timeout 4 mmcli -m any -e >/dev/null 2>&1 || true
|
timeout 4 mmcli -m any -e >/dev/null 2>&1 || true
|
||||||
spawn_enable_and_register "$slot" 1
|
spawn_enable_and_register "$slot" 1
|
||||||
exit 0
|
exit 0
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
[D-BUS Service]
|
[D-BUS Service]
|
||||||
Name=org.freedesktop.ModemManager1
|
Name=org.freedesktop.ModemManager1
|
||||||
Exec=/usr/sbin/ModemManager --debug
|
Exec=/bin/false
|
||||||
User=root
|
User=root
|
||||||
SystemdService=dbus-org.freedesktop.ModemManager1.service
|
SystemdService=dbus-org.freedesktop.ModemManager1.service
|
||||||
|
|||||||
|
After Width: | Height: | Size: 33 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 40 KiB |
@@ -0,0 +1,8 @@
|
|||||||
|
[Plymouth Theme]
|
||||||
|
Name=Bananarchy Spin
|
||||||
|
Description=Bananarchy Linux boot splash with rotating banana circle
|
||||||
|
ModuleName=script
|
||||||
|
|
||||||
|
[script]
|
||||||
|
ImageDir=/usr/share/plymouth/themes/pmos-spin
|
||||||
|
ScriptFile=/usr/share/plymouth/themes/pmos-spin/pmos-spin.script
|
||||||
@@ -0,0 +1,137 @@
|
|||||||
|
# Bananarchy Linux Plymouth Theme Script
|
||||||
|
# Central crossed bananas ("A") remain stationary while the outer banana circle rotates.
|
||||||
|
|
||||||
|
Window.SetBackgroundTopColor(0, 0, 0);
|
||||||
|
Window.SetBackgroundBottomColor(0, 0, 0);
|
||||||
|
|
||||||
|
center_image = Image("center.png");
|
||||||
|
ring_image = Image("ring.png");
|
||||||
|
error_image = Image("error.png");
|
||||||
|
title_image = Image("title.png");
|
||||||
|
|
||||||
|
win_w = Window.GetWidth();
|
||||||
|
win_h = Window.GetHeight();
|
||||||
|
|
||||||
|
target_size = Math.Min(win_w * 0.72, win_h * 0.56);
|
||||||
|
if (target_size > 164 && target_size < 176)
|
||||||
|
{
|
||||||
|
scale_ratio = 1.0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
scale_ratio = target_size / center_image.GetWidth();
|
||||||
|
center_image = center_image.Scale(
|
||||||
|
center_image.GetWidth() * scale_ratio,
|
||||||
|
center_image.GetHeight() * scale_ratio
|
||||||
|
);
|
||||||
|
ring_image = ring_image.Scale(
|
||||||
|
ring_image.GetWidth() * scale_ratio,
|
||||||
|
ring_image.GetHeight() * scale_ratio
|
||||||
|
);
|
||||||
|
error_image = error_image.Scale(
|
||||||
|
error_image.GetWidth() * scale_ratio,
|
||||||
|
error_image.GetHeight() * scale_ratio
|
||||||
|
);
|
||||||
|
title_image = title_image.Scale(
|
||||||
|
title_image.GetWidth() * scale_ratio,
|
||||||
|
title_image.GetHeight() * scale_ratio
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
global.message_font = "Sans 10";
|
||||||
|
|
||||||
|
logo_x = Window.GetX() + win_w / 2 - center_image.GetWidth() / 2;
|
||||||
|
logo_y = Window.GetY() + win_h / 2 - center_image.GetHeight() / 2 - 16;
|
||||||
|
|
||||||
|
title_x = Window.GetX() + win_w / 2 - title_image.GetWidth() / 2;
|
||||||
|
title_y = logo_y + center_image.GetHeight() + 12;
|
||||||
|
|
||||||
|
ring_sprite = Sprite(ring_image);
|
||||||
|
ring_sprite.SetPosition(logo_x, logo_y, 10);
|
||||||
|
ring_sprite.SetOpacity(1);
|
||||||
|
|
||||||
|
center_sprite = Sprite(center_image);
|
||||||
|
center_sprite.SetPosition(logo_x, logo_y, 20);
|
||||||
|
center_sprite.SetOpacity(1);
|
||||||
|
|
||||||
|
title_sprite = Sprite(title_image);
|
||||||
|
title_sprite.SetPosition(title_x, title_y, 20);
|
||||||
|
title_sprite.SetOpacity(1);
|
||||||
|
|
||||||
|
error_sprite = Sprite(error_image);
|
||||||
|
error_sprite.SetPosition(logo_x, logo_y, 30);
|
||||||
|
error_sprite.SetOpacity(0);
|
||||||
|
|
||||||
|
global.angle = 0.0;
|
||||||
|
global.two_pi = 6.283185307;
|
||||||
|
global.status = "normal";
|
||||||
|
|
||||||
|
fun refresh_callback()
|
||||||
|
{
|
||||||
|
if (status == "error")
|
||||||
|
{
|
||||||
|
ring_sprite.SetOpacity(0);
|
||||||
|
center_sprite.SetOpacity(0);
|
||||||
|
error_sprite.SetOpacity(1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
error_sprite.SetOpacity(0);
|
||||||
|
ring_sprite.SetOpacity(1);
|
||||||
|
center_sprite.SetOpacity(1);
|
||||||
|
|
||||||
|
angle = angle + 0.055;
|
||||||
|
if (angle >= two_pi)
|
||||||
|
{
|
||||||
|
angle = angle - two_pi;
|
||||||
|
}
|
||||||
|
ring_sprite.SetImage(ring_image.Rotate(angle));
|
||||||
|
}
|
||||||
|
|
||||||
|
Plymouth.SetRefreshFunction(refresh_callback);
|
||||||
|
|
||||||
|
message_sprite = Sprite();
|
||||||
|
message_sprite.SetPosition(10, 10, 10000);
|
||||||
|
|
||||||
|
fun display_message_callback(text)
|
||||||
|
{
|
||||||
|
if (status == "error")
|
||||||
|
text_image = Image.Text(text, 1, 0.3, 0.2, 1, message_font, "center");
|
||||||
|
else if (status == "warning")
|
||||||
|
text_image = Image.Text(text, 1, 0.84, 0.04, 1, message_font, "center");
|
||||||
|
else
|
||||||
|
text_image = Image.Text(text, 0.8, 0.8, 0.8, 0.9, message_font, "center");
|
||||||
|
|
||||||
|
message_sprite.SetImage(text_image);
|
||||||
|
message_x = Window.GetX() + win_w / 2 - text_image.GetWidth() / 2;
|
||||||
|
message_y = Window.GetY() + win_h - text_image.GetHeight() - 12;
|
||||||
|
message_sprite.SetPosition(message_x, message_y, 10000);
|
||||||
|
}
|
||||||
|
|
||||||
|
fun hide_message_callback(text)
|
||||||
|
{
|
||||||
|
message_sprite = Sprite();
|
||||||
|
message_sprite.SetPosition(10, 10, 10000);
|
||||||
|
status = "normal";
|
||||||
|
}
|
||||||
|
|
||||||
|
Plymouth.SetDisplayMessageFunction(display_message_callback);
|
||||||
|
Plymouth.SetHideMessageFunction(hide_message_callback);
|
||||||
|
|
||||||
|
fun update_status_callback(new_status)
|
||||||
|
{
|
||||||
|
if (new_status == "warning" || new_status == "error")
|
||||||
|
global.status = new_status;
|
||||||
|
else
|
||||||
|
global.status = "normal";
|
||||||
|
}
|
||||||
|
|
||||||
|
Plymouth.SetUpdateStatusFunction(update_status_callback);
|
||||||
|
|
||||||
|
fun quit_callback()
|
||||||
|
{
|
||||||
|
ring_sprite.SetOpacity(1);
|
||||||
|
center_sprite.SetOpacity(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
Plymouth.SetQuitFunction(quit_callback);
|
||||||
|
After Width: | Height: | Size: 38 KiB |
|
After Width: | Height: | Size: 1.2 KiB |
@@ -140,7 +140,101 @@ def main():
|
|||||||
splash.save(os.path.join(ARTWORK_DIR, "splash-240x320.png"), "PNG", optimize=True)
|
splash.save(os.path.join(ARTWORK_DIR, "splash-240x320.png"), "PNG", optimize=True)
|
||||||
splash.save(os.path.join(ARTWORK_DIR, "splash-240x320.ppm"), "PPM")
|
splash.save(os.path.join(ARTWORK_DIR, "splash-240x320.ppm"), "PPM")
|
||||||
|
|
||||||
# 9. Project documentation banner (800x240)
|
# 9. Plymouth rotating boot splash layers (stationary central A + rotating outer ring)
|
||||||
|
import numpy as np
|
||||||
|
from scipy import ndimage
|
||||||
|
src_rgba = src.convert("RGBA")
|
||||||
|
arr = np.array(src_rgba)
|
||||||
|
rgb = arr[:, :, :3].astype(np.float32)
|
||||||
|
r_ch, g_ch, b_ch = rgb[:, :, 0], rgb[:, :, 1], rgb[:, :, 2]
|
||||||
|
lum = rgb.max(axis=2)
|
||||||
|
|
||||||
|
# Separate central A bananas from outer banana circle via distance transform
|
||||||
|
is_yellow = (r_ch > 140) & (g_ch > 90) & (b_ch < 90)
|
||||||
|
labeled, num = ndimage.label(is_yellow)
|
||||||
|
center_yellow = np.zeros_like(is_yellow)
|
||||||
|
outer_yellow = np.zeros_like(is_yellow)
|
||||||
|
for i in range(1, num + 1):
|
||||||
|
pts = np.argwhere(labeled == i)
|
||||||
|
if len(pts) < 50:
|
||||||
|
continue
|
||||||
|
ymin, xmin = pts.min(axis=0)
|
||||||
|
ymax, xmax = pts.max(axis=0)
|
||||||
|
yc, xc = pts.mean(axis=0)
|
||||||
|
rc = np.hypot(xc - 512.0, yc - 512.0)
|
||||||
|
if (xmax - xmin) > 700 or rc > 280.0:
|
||||||
|
outer_yellow |= (labeled == i)
|
||||||
|
else:
|
||||||
|
center_yellow |= (labeled == i)
|
||||||
|
|
||||||
|
dist_center = ndimage.distance_transform_edt(~center_yellow)
|
||||||
|
dist_outer = ndimage.distance_transform_edt(~outer_yellow)
|
||||||
|
y_grid, x_grid = np.ogrid[:1024, :1024]
|
||||||
|
rad = np.hypot(x_grid - 512.0, y_grid - 512.0)
|
||||||
|
fg_alpha = np.clip((lum - 10.0) / 28.0, 0.0, 1.0)
|
||||||
|
|
||||||
|
in_inner_core = np.clip((290.0 - rad) / 4.0, 0.0, 1.0) * np.clip((718.0 - y_grid) / 4.0, 0.0, 1.0)
|
||||||
|
near_center_tip = (
|
||||||
|
np.clip((dist_outer - dist_center + 4.0) / 4.0, 0.0, 1.0)
|
||||||
|
* np.clip((27.0 - dist_center) / 3.0, 0.0, 1.0)
|
||||||
|
* np.clip((y_grid - 91.0) / 2.5, 0.0, 1.0)
|
||||||
|
* np.clip((722.0 - y_grid) / 3.0, 0.0, 1.0)
|
||||||
|
)
|
||||||
|
center_weight = np.maximum(in_inner_core, near_center_tip)
|
||||||
|
ring_weight = 1.0 - center_weight
|
||||||
|
|
||||||
|
center_rgba = arr.copy()
|
||||||
|
center_rgba[:, :, 3] = (fg_alpha * center_weight * 255.0).astype(np.uint8)
|
||||||
|
ring_rgba = arr.copy()
|
||||||
|
ring_rgba[:, :, 3] = (fg_alpha * ring_weight * 255.0).astype(np.uint8)
|
||||||
|
|
||||||
|
err_rgba = arr.copy()
|
||||||
|
err_rgba[:, :, 0] = np.clip(rgb[:, :, 0] * 1.1, 0, 255).astype(np.uint8)
|
||||||
|
err_rgba[:, :, 1] = (rgb[:, :, 1] * 0.22).astype(np.uint8)
|
||||||
|
err_rgba[:, :, 2] = (rgb[:, :, 2] * 0.18).astype(np.uint8)
|
||||||
|
err_rgba[:, :, 3] = (fg_alpha * 255.0).astype(np.uint8)
|
||||||
|
|
||||||
|
ply_size = 168
|
||||||
|
ply_center_img = Image.fromarray(center_rgba).resize((ply_size, ply_size), Image.Resampling.LANCZOS)
|
||||||
|
ply_ring_img = Image.fromarray(ring_rgba).resize((ply_size, ply_size), Image.Resampling.LANCZOS)
|
||||||
|
ply_error_img = Image.fromarray(err_rgba).resize((ply_size, ply_size), Image.Resampling.LANCZOS)
|
||||||
|
|
||||||
|
# Title image for Plymouth splash ("BANANARCHY")
|
||||||
|
ply_title_img = Image.new("RGBA", (180, 28), (0, 0, 0, 0))
|
||||||
|
ptdraw = ImageDraw.Draw(ply_title_img)
|
||||||
|
ptb = ptdraw.textbbox((0, 0), title_text, font=font_title)
|
||||||
|
ptw = ptb[2] - ptb[0]
|
||||||
|
ptdraw.text(((180 - ptw) // 2, 2), title_text, fill=(255, 214, 10, 255), font=font_title)
|
||||||
|
|
||||||
|
ply_center_img.save(os.path.join(ARTWORK_DIR, "plymouth-center.png"), "PNG", optimize=True)
|
||||||
|
ply_ring_img.save(os.path.join(ARTWORK_DIR, "plymouth-ring.png"), "PNG", optimize=True)
|
||||||
|
ply_error_img.save(os.path.join(ARTWORK_DIR, "plymouth-error.png"), "PNG", optimize=True)
|
||||||
|
ply_title_img.save(os.path.join(ARTWORK_DIR, "plymouth-title.png"), "PNG", optimize=True)
|
||||||
|
|
||||||
|
for root_base in (
|
||||||
|
os.path.join(BASE_DIR, "overlay", "rootfs"),
|
||||||
|
os.path.join(BASE_DIR, "rootfs"),
|
||||||
|
):
|
||||||
|
if not os.path.isdir(root_base):
|
||||||
|
continue
|
||||||
|
ply_dir = os.path.join(root_base, "usr", "share", "plymouth")
|
||||||
|
theme_dir = os.path.join(ply_dir, "themes", "pmos-spin")
|
||||||
|
os.makedirs(theme_dir, exist_ok=True)
|
||||||
|
ply_center_img.save(os.path.join(theme_dir, "center.png"), "PNG", optimize=True)
|
||||||
|
ply_ring_img.save(os.path.join(theme_dir, "ring.png"), "PNG", optimize=True)
|
||||||
|
ply_error_img.save(os.path.join(theme_dir, "error.png"), "PNG", optimize=True)
|
||||||
|
ply_title_img.save(os.path.join(theme_dir, "title.png"), "PNG", optimize=True)
|
||||||
|
for stale in ("right.png", "top.png", "left.png"):
|
||||||
|
stale_path = os.path.join(theme_dir, stale)
|
||||||
|
if os.path.exists(stale_path):
|
||||||
|
os.remove(stale_path)
|
||||||
|
icon_rgba = Image.fromarray(arr.copy())
|
||||||
|
icon_rgba.putalpha(Image.fromarray((fg_alpha * 255.0).astype(np.uint8)))
|
||||||
|
icon_rgba.resize((128, 128), Image.Resampling.LANCZOS).save(
|
||||||
|
os.path.join(ply_dir, "bizcom.png"), "PNG", optimize=True
|
||||||
|
)
|
||||||
|
|
||||||
|
# 10. Project documentation banner (800x240)
|
||||||
banner = make_canvas(800, 240, (1, 1, 1))
|
banner = make_canvas(800, 240, (1, 1, 1))
|
||||||
paste_centered(banner, src, 204, 118, 120)
|
paste_centered(banner, src, 204, 118, 120)
|
||||||
bdraw = ImageDraw.Draw(banner)
|
bdraw = ImageDraw.Draw(banner)
|
||||||
|
|||||||