1 Commits
Author SHA1 Message Date
bps b932610be7 Survive the headset going to sleep mid-stream
Writing to the dropped connection raised SIGPIPE and killed the app. It is
now ignored, so the session reports the lost connection instead.

Also document that the console's browser window stays in front of Visor after
opening it from the home screen icon until Circle is pressed.
2026-10-11 18:37:18 -03:00
4 changed files with 16 additions and 15 deletions

No files matched your search

+2
View File
@@ -69,6 +69,8 @@ the headset.
- **Quest 2 only for now.** Other headsets have different screens, so the eye
crop would be off. "Both eyes" in the settings works on anything.
- The headset has to be awake (on your head) to stream.
- The home screen icon is a web shortcut, so the console opens its browser
window first and leaves it in front of Visor. Press Circle once to dismiss it.
## How it works
+3
View File
@@ -67,6 +67,9 @@ feito no headset.
- **Só Quest 2 por enquanto.** Outros headsets têm telas diferentes e o recorte
do olho sairia errado. "Os dois" olhos, nos ajustes, funciona em qualquer um.
- O headset precisa estar acordado (na cabeça) para transmitir.
- O ícone da tela inicial é um atalho web, então o console abre a janela do
navegador primeiro e a deixa na frente do Visor. Aperte Círculo uma vez para
dispensá-la.
## Como funciona
+6 -15
View File
@@ -4,8 +4,8 @@
* 3. abre o app quando o atalho e clicado.
*
* O atalho e um "app web": o sistema abre o navegador na deeplinkUri, que
* aponta para o servidor HTTP minimo daqui. Ao receber o pedido, fechamos o
* navegador e lancamos o app com o loader do websrv (third_party/websrv). */
* aponta para o servidor HTTP minimo daqui. Ao receber o pedido, lancamos o
* app com o loader do websrv (third_party/websrv). */
#include <fcntl.h>
#include <signal.h>
@@ -34,9 +34,6 @@ int sceUserServiceInitialize(void*);
int sceAppInstUtilInitialize(void);
int sceAppInstUtilTerminate(void);
int sceAppInstUtilAppInstallAll(void*);
int sceLncUtilGetAppId(const char* title_id);
int sceSystemServiceKillApp(int app_id, int how, int reason, int core_dump);
int sceKernelGetAppState(int app_id, int*, int*);
int sceKernelSendNotificationRequest(int, void*, size_t, int);
/* Os caminhos sao relativos a raiz do repo e a pasta de build (-I no CMake). */
@@ -144,18 +141,12 @@ static void install_tile(void) {
sceAppInstUtilTerminate();
}
/* Fecha o navegador que o atalho abriu; sem isso ele fica na frente do app. */
static void close_browser(void) {
int id = sceLncUtilGetAppId(TILE_ID);
if (id <= 0) return;
printf("[visor] fechando o navegador (app 0x%x): 0x%08x\n", id,
sceSystemServiceKillApp(id, -1, 0, 0));
for (int i = 0; i < 50 && !sceKernelGetAppState(id, 0, 0); i++) usleep(100000);
}
/* ponytail: o navegador que o atalho abre e uma janela da ShellUI e fica por
* cima do app ate o usuario apertar Circulo. Matar o app do atalho,
* sceLncUtilSetAppFocus e sceShellCoreUtilLaunchByUri("psgm:play") nao
* resolveram; o caminho e um atalho que lance o titulo direto, sem navegador. */
static void launch(void) {
char* argv[] = {DIR "/visor-app.elf", 0};
close_browser();
printf("[visor] app iniciado, pid %d\n",
hbldr_launch(DIR, argv[0], STDOUT_FILENO, argv, 0));
}
+5
View File
@@ -1,3 +1,4 @@
#include <csignal>
#include <cstdio>
#include <cstdlib>
#include <filesystem>
@@ -47,6 +48,10 @@ int SDL_main(int argc, char* args[]) {
Rml::Context* ctx;
auto app = std::make_unique<App>();
// Sem isto, escrever no socket depois que o headset dorme mata o processo;
// ignorando, o send falha e a sessao mostra "conexao perdida".
signal(SIGPIPE, SIG_IGN);
if (!Backend::Initialize("Visor", SCREEN_WIDTH, SCREEN_HEIGHT, false)) {
return -1;
}