Modo portatil: ejecutar FOSFENO en un portatil Linux

Anade 'bash install.sh --laptop' y el lanzador './fosfeno' para correr FOSFENO en portatiles Debian/Ubuntu/Mint sin Raspberry Pi: puerto 8080, sin arranque automatico ni cambios en el sistema. El servidor admite las variables FOSFENO_PORT y FOSFENO_NO_KIOSK. Nueva documentacion en docs/portatil.md.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
hacklab 2026-05-22 14:39:34 +02:00
parent 30a09fdee6
commit 3c1c631895
7 changed files with 250 additions and 53 deletions

View file

@ -76,6 +76,12 @@ bash install.sh --no-projectm # omite la compilación de projectM
bash install.sh --check # solo comprueba el sistema, no instala nada
```
### En un portátil Linux
FOSFENO también corre en un portátil con Debian, Ubuntu o Mint, sin Raspberry
Pi. Se instala con `bash install.sh --laptop` y se arranca cuando quieras con
`./fosfeno`. Los detalles están en [FOSFENO en un portátil](docs/portatil.md).
Después:
```bash

View file

@ -13,6 +13,7 @@ Motores: projectm (nativo), butterchurn, hydra, shaders (GLSL) y mixer
"""
import json
import os
import shutil
import socket
import subprocess
@ -44,7 +45,10 @@ def load_json(path, default):
CFG = load_json(BASE / "config.json", {})
HOST = CFG.get("server", {}).get("host", "0.0.0.0")
PORT = int(CFG.get("server", {}).get("port", 80))
# El puerto y el modo kiosko se pueden forzar por variable de entorno; asi el
# modo portatil (script 'fosfeno') usa el puerto 8080 sin tocar config.json.
PORT = int(os.environ.get("FOSFENO_PORT") or CFG.get("server", {}).get("port", 80))
NO_KIOSK = bool(os.environ.get("FOSFENO_NO_KIOSK"))
app = Flask(__name__, static_folder=None)
socketio = SocketIO(app, async_mode="threading", cors_allowed_origins="*")
@ -180,7 +184,7 @@ def start_chromium():
notify("error", "No se encontro Chromium. Las visuales web no pueden "
"mostrarse. Ejecuta install.sh para instalarlo.")
return
url = kiosk.get("url", f"http://localhost:{PORT}/stage")
url = f"http://localhost:{PORT}/stage"
procs["chromium"] = subprocess.Popen([
browser,
"--kiosk", f"--app={url}",
@ -442,7 +446,8 @@ def watchdog():
time.sleep(10)
if refresh_network():
broadcast()
if state["engine"] != "projectm" and not is_running(procs["chromium"]):
if not NO_KIOSK and state["engine"] != "projectm" \
and not is_running(procs["chromium"]):
notify("warn", "El navegador de las visuales se cerro. "
"Reabriendolo automaticamente.")
start_chromium()
@ -471,6 +476,8 @@ def main():
check_install()
setup_audio()
refresh_network()
# En modo portatil el script 'fosfeno' abre el navegador; el servidor no.
if not NO_KIOSK:
threading.Timer(3.0, start_chromium).start()
threading.Thread(target=watchdog, daemon=True).start()

View file

@ -4,7 +4,6 @@
"port": 80
},
"kiosk": {
"url": "http://localhost/stage",
"browser": "chromium-browser"
},
"audio": {

View file

@ -16,6 +16,9 @@ para consultarse a saltos después.
Cómo encuentra el usuario el panel de control: el código QR del proyector,
la dirección `fosfeno.local` y qué hacer con el router.
- [FOSFENO en un portátil Linux](portatil.md)
Cómo correr FOSFENO en un portátil Debian, Ubuntu o Mint, sin Raspberry Pi.
- [Uso del panel](uso.md)
Cómo se maneja desde el móvil, qué hace cada motor de visuales y cómo se
configura cada opción.

71
docs/portatil.md Normal file
View file

@ -0,0 +1,71 @@
# FOSFENO en un portátil Linux
FOSFENO nació para una Raspberry Pi, pero está hecho con tecnología web, así
que funciona igual de bien en un portátil con Linux. De hecho un portátil va
más sobrado, ya trae micrófono y cámara, y lo conectas al proyector por HDMI
como cualquier otra cosa.
Este modo está pensado para Debian, Ubuntu o Linux Mint, que son las
distribuciones que usan `apt`.
## Instalar
Una sola vez, desde la carpeta del proyecto:
```
bash install.sh --laptop
```
Hace lo mismo que en la Raspberry (entorno de Python, librerías de visuales,
y projectM si quieres), pero sin las cosas propias de un aparato dedicado: no
toca el arranque del sistema, no cambia el nombre de red y no necesita
permisos especiales de puertos.
## Arrancar
Cuando quieras usarlo, desde la carpeta del proyecto:
```
./fosfeno
```
Eso levanta FOSFENO y abre dos cosas:
- El **panel de control** en tu navegador, en `http://localhost:8080/`.
- Una **ventana con las visuales**, aparte.
Para cerrarlo todo, pulsa `Ctrl+C` en la terminal donde lanzaste `./fosfeno`.
## Llevar las visuales al proyector
La ventana de las visuales es una ventana normal. Conecta el proyector por
HDMI, arrastra esa ventana a la pantalla del proyector y pulsa `F11` para
ponerla a pantalla completa. El panel de control lo manejas desde el portátil,
o desde el móvil si prefieres.
## Micrófono y cámara
El portátil ya trae micrófono y cámara integrados. No hace falta nada por USB,
aunque puedes usarlo si quieres mejor sonido o una webcam mejor.
La primera vez, elige el micrófono en el apartado Audio del panel, y la cámara
en el apartado del Mezclador. Si los conectas con FOSFENO ya abierto, usa el
botón de buscar dispositivos de nuevo.
## Controlarlo desde el móvil
Si quieres manejar el panel desde el móvil mientras el portátil hace de VJ,
conecta el móvil a la misma red WiFi y entra en `http://nombre-del-portatil.local:8080/`.
El nombre del portátil lo ves con el comando `hostname`. La dirección exacta
también aparece en la terminal al arrancar `./fosfeno`.
## En qué se diferencia de la Raspberry
- No arranca solo: lo lanzas tú con `./fosfeno` cuando lo necesitas.
- Usa el puerto 8080 en lugar del 80.
- No cambia el nombre de red del equipo.
- Los botones de reiniciar y apagar del panel no harán nada (es tu portátil,
no un aparato dedicado, así que es lo correcto).
Todo lo demás (los cinco motores, el editor de código, la detección de BPM,
el mezclador) funciona exactamente igual.

77
fosfeno Executable file
View file

@ -0,0 +1,77 @@
#!/usr/bin/env bash
# ===========================================================================
# FOSFENO :: arranque en modo portatil (Linux de escritorio)
#
# Lanza el servidor, abre el panel y las visuales, y lo cierra todo con Ctrl+C.
# Antes hay que instalar una vez con: bash install.sh --laptop
# ===========================================================================
set -u
DIR="$(cd "$(dirname "$0")" && pwd)"
PORT=8080
export FOSFENO_PORT="$PORT"
export FOSFENO_NO_KIOSK=1
if [ ! -x "$DIR/.venv/bin/python3" ]; then
echo "FOSFENO no esta instalado todavia. Ejecuta primero:"
echo " bash install.sh --laptop"
exit 1
fi
SERVER_PID=""
STAGE_PID=""
cleanup() {
echo
echo "Cerrando FOSFENO..."
[ -n "$STAGE_PID" ] && kill "$STAGE_PID" 2>/dev/null
[ -n "$SERVER_PID" ] && kill "$SERVER_PID" 2>/dev/null
exit 0
}
trap cleanup INT TERM
echo "Arrancando FOSFENO..."
"$DIR/.venv/bin/python3" "$DIR/backend/server.py" &
SERVER_PID=$!
# Espera (hasta 20 s) a que el servidor responda
for _ in $(seq 1 40); do
curl -s "http://localhost:$PORT/" >/dev/null 2>&1 && break
sleep 0.5
done
# Abre las visuales en una ventana propia de Chromium. Es una ventana normal:
# arrastrala al proyector y pulsa F11 para ponerla a pantalla completa.
BROWSER="$(command -v chromium-browser || command -v chromium \
|| command -v google-chrome || true)"
if [ -n "$BROWSER" ]; then
"$BROWSER" --app="http://localhost:$PORT/stage" \
--user-data-dir="/tmp/fosfeno-stage" \
--use-fake-ui-for-media-stream \
--autoplay-policy=no-user-gesture-required \
>/dev/null 2>&1 &
STAGE_PID=$!
else
echo "Aviso: no se encontro Chromium. Abre las visuales a mano en:"
echo " http://localhost:$PORT/stage"
fi
# Abre el panel de control en el navegador por defecto
xdg-open "http://localhost:$PORT/" >/dev/null 2>&1 || true
cat <<EOF
FOSFENO en marcha (modo portatil).
Panel de control: http://localhost:$PORT/
Visuales: ventana de Chromium aparte
(arrastrala al proyector y pulsa F11)
Desde el movil, en la misma red WiFi:
http://$(hostname).local:$PORT/
Pulsa Ctrl+C aqui para cerrar FOSFENO.
EOF
wait "$SERVER_PID"
cleanup

View file

@ -2,7 +2,8 @@
# ===========================================================================
# FOSFENO :: instalador para Raspberry Pi OS Bookworm (Raspberry Pi 4 y 5)
#
# Uso: bash install.sh # instala todo (incluido projectM)
# Uso: bash install.sh # Raspberry Pi: instala todo
# bash install.sh --laptop # portatil Linux (Debian/Ubuntu/Mint)
# bash install.sh --no-projectm # omite la compilacion de projectM
# bash install.sh --check # solo comprueba el sistema, no instala
# ===========================================================================
@ -13,10 +14,12 @@ source "$DIR/scripts/lib.sh"
MODE="install"
SKIP_PM="no"
LAPTOP="no"
for arg in "$@"; do
case "$arg" in
--no-projectm) SKIP_PM="yes" ;;
--check) MODE="check" ;;
--laptop) LAPTOP="yes" ;;
*) echo "Opcion desconocida: $arg"; exit 1 ;;
esac
done
@ -34,32 +37,34 @@ printf '%s\n' "===================================================$C_RST"
# ---------------------------------------------------------------------------
# 1. Comprobacion del hardware y del sistema operativo
# ---------------------------------------------------------------------------
log_step "[1/9] Comprobando hardware y sistema operativo"
log_step "[1/9] Comprobando el sistema"
if [ -r /etc/os-release ]; then
. /etc/os-release
log_info "Sistema: ${PRETTY_NAME:-desconocido}"
fi
if [ "$LAPTOP" = "yes" ]; then
log_ok "Modo portatil (Linux de escritorio)"
if ! need_cmd apt-get; then
log_fail "El modo --laptop usa apt (Debian, Ubuntu o Mint)."
log_fail "Tu sistema no tiene apt; este instalador no sirve aqui."
exit 1
fi
else
MODELO="$(pi_model)"
log_info "Modelo detectado: $MODELO"
case "$MODELO" in
*"Raspberry Pi 5"*) log_ok "Raspberry Pi 5 (soportada)" ;;
*"Raspberry Pi 4"*) log_ok "Raspberry Pi 4 (soportada)" ;;
*"Raspberry Pi"*) warn "Raspberry Pi distinta de 4/5: puede funcionar pero sin garantias" ;;
*) warn "No parece una Raspberry Pi: continuando bajo tu responsabilidad" ;;
*) warn "No parece una Raspberry Pi. Si es un portatil, usa: bash install.sh --laptop" ;;
esac
if [ -r /etc/os-release ]; then
. /etc/os-release
log_info "Sistema: ${PRETTY_NAME:-desconocido}"
if [ "${VERSION_CODENAME:-}" = "bookworm" ]; then
log_ok "Raspberry Pi OS Bookworm"
else
if [ "${VERSION_CODENAME:-}" != "bookworm" ]; then
warn "Se recomienda Raspberry Pi OS Bookworm (detectado: ${VERSION_CODENAME:-?})"
fi
fi
ARCH="$(uname -m)"
log_info "Arquitectura: $ARCH"
[ "$ARCH" = "aarch64" ] && log_ok "Sistema de 64 bits" \
|| warn "Se recomienda Raspberry Pi OS de 64 bits para mejor rendimiento"
# ---------------------------------------------------------------------------
# Modo --check: solo verifica lo que ya esta instalado y termina
# ---------------------------------------------------------------------------
@ -222,8 +227,15 @@ log_info "Copia tus clips .mp4 en: $DIR/data/videos/"
# ---------------------------------------------------------------------------
# 8. Arranque automatico y permisos
# ---------------------------------------------------------------------------
log_step "[8/9] Configurando arranque automatico y permisos"
chmod +x "$DIR/scripts/"*.sh "$DIR/install.sh" "$DIR/uninstall.sh"
log_step "[8/9] Arranque automatico y permisos"
chmod +x "$DIR/scripts/"*.sh "$DIR/install.sh" "$DIR/uninstall.sh" 2>/dev/null
[ -f "$DIR/fosfeno" ] && chmod +x "$DIR/fosfeno"
HOSTNAME_WANT="$(hostname)"
if [ "$LAPTOP" = "yes" ]; then
log_info "Modo portatil: sin arranque automatico ni cambios en el sistema."
log_info "FOSFENO se lanza a mano con ./fosfeno cuando quieras usarlo."
else
mkdir -p "$HOME/.config/autostart"
if sed "s#__DIR__#$DIR#g" "$DIR/scripts/fosfeno-autostart.desktop" \
> "$HOME/.config/autostart/fosfeno.desktop"; then
@ -249,17 +261,22 @@ if echo "$USER ALL=(ALL) NOPASSWD: /sbin/reboot, /sbin/poweroff" \
&& sudo chmod 440 /etc/sudoers.d/fosfeno; then
log_ok "Permisos de reinicio/apagado configurados"
fi
fi
# ---------------------------------------------------------------------------
# 9. Permiso para el puerto 80
# 9. Acceso de red
# ---------------------------------------------------------------------------
log_step "[9/9] Permitiendo a Python escuchar en el puerto 80"
log_step "[9/9] Acceso de red"
if [ "$LAPTOP" = "yes" ]; then
log_info "Modo portatil: el panel usara el puerto 8080, no hace falta nada mas."
else
PYBIN="$(readlink -f "$DIR/.venv/bin/python3")"
if sudo setcap 'cap_net_bind_service=+ep' "$PYBIN" 2>/dev/null; then
log_ok "Puerto 80 habilitado"
else
warn "no se pudo habilitar el puerto 80; cambia 'server.port' a 8080 en config.json"
fi
fi
# ---------------------------------------------------------------------------
# Resumen final
@ -271,6 +288,22 @@ else
log_warn "FOSFENO instalado con $FOSFENO_WARNINGS aviso(s) (revisa arriba)."
fi
printf '%s\n' "===================================================$C_RST"
if [ "$LAPTOP" = "yes" ]; then
cat <<EOF
FOSFENO instalado en modo portatil.
Para arrancarlo, desde esta carpeta:
./fosfeno
Se abrira el panel de control en el navegador y una ventana aparte con
las visuales (arrastrala al proyector y pulsa F11 para pantalla completa).
Para cerrarlo todo, pulsa Ctrl+C en la terminal.
Para comprobar el sistema sin reinstalar:
bash install.sh --check
EOF
else
cat <<EOF
Siguientes pasos:
@ -288,3 +321,4 @@ cat <<EOF
Para volver a comprobar el sistema sin reinstalar:
bash install.sh --check
EOF
fi