Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.en-US.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@

English (US) release notes, mirroring CHANGELOG.md (Brazilian Portuguese). Before publishing a version, add a `## [VERSION]` section to **both** files: the workflow publishes the section matching the tag from each one and fails if either is missing.

## [Unreleased]
### What's new
- Settings → TV: console mode turns the TV on and switches it to the PC's HDMI input, and can put it in standby on restore. First route: Google TV / Android TV over the network (ADB), nothing to install on the PC. (#93)
- TV control through Home Assistant: runs a script, scene, automation or media_player on start and on restore, with the token stored encrypted. (#95)

## [1.5.0]
### What's new
- Console interface: a full-screen, controller-first home and Settings, driven by the D-pad/stick and A/B with Xbox and PlayStation pads. Automatic mode picks it whenever a controller is connected. (#41, #42, #47)
Expand Down
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@

Notas em português do Brasil; a versão em inglês (Estados Unidos) fica em `CHANGELOG.en-US.md`. Antes de publicar uma versão, adicione uma seção `## [VERSÃO]` com o changelog daquela versão **nos dois arquivos**. O workflow publica as duas seções correspondentes à tag na mesma release e falha se faltar alguma.

## [Unreleased]
### Novidades
- Ajustes → TV: o modo console liga a TV e troca para a entrada HDMI do PC, e pode colocá-la em espera ao restaurar. Primeiro caminho: Google TV / Android TV pela rede (ADB), sem instalar nada no PC. (#93)
- Controle da TV pelo Home Assistant: roda um script, cena, automação ou media_player ao entrar e ao restaurar, com o token guardado criptografado. (#95)

## [1.5.0]
### Novidades
- Interface Console: tela inicial e Ajustes em tela cheia, pensados para o controle (direcional/analógico, A/B) com controles Xbox e PlayStation. O modo Automático escolhe essa interface sempre que há um controle conectado. (#41, #42, #47)
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ Prefer the couch? With the app in the tray, hold the controller's Home button an
- Hide the other screens by **disconnecting** them, **black overlays** or **DDC/CI**
- Per-screen **resolution and refresh rate**, **HDR**, **VRR** and an **FPS limit** (RTSS) while you play
- Audio goes to the TV (or any output) and comes back afterwards
- [Turns the TV on and switches it to the PC's input](docs/GUIDE.md#tv-control) (Google TV / Android TV over the network, or anything Home Assistant controls), and can put it in standby afterwards
- Launches **Steam Big Picture**, **Playnite fullscreen** or **Xbox** mode
- Two interfaces: **Desktop** (mouse) and **Console** (full screen, Xbox and PlayStation pads)
- Automation with `consolemode://start` / `stop` / `menu` links (Stream Deck, scripts) and a [local control API](docs/GUIDE.md#local-control-api)
Expand Down
1 change: 1 addition & 0 deletions README.pt-BR.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ Prefere o sofá? Com o app na bandeja, segure o botão Home do controle e ele co
- Esconde as outras telas **desconectando**, com **cortinas pretas** ou por **DDC/CI**
- **Resolução e Hz** por tela, **HDR**, **VRR** e **limite de FPS** (RTSS) enquanto você joga
- O áudio vai para a TV (ou qualquer saída) e volta depois
- [Liga a TV e troca para a entrada do PC](docs/GUIDE.pt-BR.md#controle-da-tv) (Google TV / Android TV pela rede, ou qualquer TV que o Home Assistant controle), e pode colocá-la em espera no fim
- Abre **Steam Big Picture**, **Playnite em tela cheia** ou o **Modo Xbox**
- Duas interfaces: **Desktop** (mouse) e **Console** (tela cheia, controles Xbox e PlayStation)
- Automação com os links `consolemode://start` / `stop` / `menu` (Stream Deck, scripts) e uma [API de controle local](docs/GUIDE.pt-BR.md#api-de-controle-local)
Expand Down
29 changes: 29 additions & 0 deletions docs/GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,35 @@ You can also restore anytime from the tray (*Restore setup* / *Show window*). Wi

`start`, `stop` and `show` do exactly what the matching `consolemode://` link does, then reply once the app has settled (`ok:false` with an `error` if console mode didn't start or the restore didn't finish). `status` only reads. Only the signed-in user and LocalSystem can connect; nothing is exposed to the network.

## TV control

Settings → **TV** can turn the TV on and switch it to the PC's HDMI input when console mode starts, and optionally put it back in standby after the desk is restored. A TV that doesn't answer never blocks console mode: the app logs it and waits for the game screen as usual.

Most PC graphics cards can't send HDMI-CEC, so the app talks to the TV over the network instead:

### Google TV / Android TV

TCL, Sony, Hisense, Philips and other TVs running Google TV or Android TV, through ADB (the Android debugging protocol). Nothing to install on the PC.

1. On the TV: **Settings → System → About**, press **Android TV OS build** 7 times to unlock Developer options.
2. **Settings → System → Developer options**: turn on **USB debugging** (on some TVs, **Network debugging** / **ADB over network**).
3. In Console Mode, pick *Google TV / Android TV*, enter the TV's IP (Settings → Network on the TV; reserve it in your router) and the HDMI input the PC uses.
4. Press **Test now**. The TV asks "Allow debugging from this computer?": tick **Always allow** and press **Allow**.

Waking uses the Android wake-up key, then the **HDMI 1-4** key. If your TV ignores that key, set **Input command** to any Android shell command that opens the PC's input. If the TV drops off the network in standby, fill in its **MAC address** so the app sends Wake-on-LAN first (the TV's "Wake on network" / "Wake on Wi-Fi" option must be on).

"Wireless debugging" with a pairing code (Android 11+ phones) is a different, TLS-wrapped protocol and isn't supported: use USB / network debugging.

### Home Assistant

If you already run [Home Assistant](https://www.home-assistant.io/), it can reach almost any TV (HDMI-CEC from a Raspberry Pi, LG, Samsung, Sony, Roku, Android TV…). Console Mode just runs an entity there when console mode starts, and another one on restore.

1. In Home Assistant, write a **script** that turns the TV on and selects the PC's input (for example `media_player.turn_on` followed by `media_player.select_source`), and optionally one that turns it off.
2. Create a **long-lived access token**: your profile → **Security** → *Long-lived access tokens*.
3. In Console Mode, pick *Home Assistant* and fill in the address (e.g. `http://homeassistant.local:8123`), the token and the entity to run (e.g. `script.tv_to_pc`). Press **Test now**.

Scripts and scenes are run with `turn_on`, automations with `trigger`, buttons with `press`; other entities (`media_player`, `switch`…) with `turn_on`, and on restore with `turn_off` when no restore entity is set. The token is stored encrypted for your Windows user (DPAPI).

## Optional extras

### HDR
Expand Down
29 changes: 29 additions & 0 deletions docs/GUIDE.pt-BR.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,35 @@ Os links `consolemode://` não dão resposta. Ferramentas que precisam de uma

`start`, `stop` e `show` fazem o mesmo que o link `consolemode://` correspondente e respondem quando o app terminou (`ok:false` com `error` se o modo console não entrou ou a restauração não terminou). `status` só consulta. Só o usuário logado e o LocalSystem conseguem conectar; nada fica exposto na rede.

## Controle da TV

Ajustes → **TV** pode ligar a TV e trocar para a entrada HDMI do PC quando o modo console começa e, se você quiser, colocá-la em espera depois que a mesa volta. Uma TV que não responde nunca trava o modo console: o app registra no log e espera a tela de jogo como sempre.

A maioria das placas de vídeo de PC não envia HDMI-CEC, então o app fala com a TV pela rede:

### Google TV / Android TV

TVs TCL, Sony, Hisense, Philips e outras com Google TV ou Android TV, via ADB (o protocolo de depuração do Android). Nada para instalar no PC.

1. Na TV: **Configurações → Sistema → Sobre**, aperte **Build do Android TV OS** 7 vezes para liberar as Opções do desenvolvedor.
2. **Configurações → Sistema → Opções do desenvolvedor**: ative **Depuração USB** (em algumas TVs, **Depuração pela rede** / **ADB pela rede**).
3. No Console Mode, escolha *Google TV / Android TV*, informe o IP da TV (Configurações → Rede na TV; reserve esse IP no roteador) e a entrada HDMI do PC.
4. Aperte **Testar agora**. A TV pergunta "Permitir depuração deste computador?": marque **Sempre permitir** e aperte **Permitir**.

Para acordar, o app usa a tecla de despertar do Android e depois a tecla **HDMI 1-4**. Se a sua TV ignorar essa tecla, preencha **Comando da entrada** com qualquer comando de shell do Android que abra a entrada do PC. Se a TV sai da rede em espera, informe o **endereço MAC** para o app mandar Wake-on-LAN antes (a opção "Ligar pela rede" / "Wake on Wi-Fi" da TV precisa estar ativa).

A "Depuração sem fio" com código de pareamento (Android 11+ em celulares) é outro protocolo, com TLS, e não é suportada: use a depuração USB / pela rede.

### Home Assistant

Se você já usa o [Home Assistant](https://www.home-assistant.io/), ele alcança quase qualquer TV (HDMI-CEC por um Raspberry Pi, LG, Samsung, Sony, Roku, Android TV…). O Console Mode só executa uma entidade lá quando o modo console começa, e outra ao restaurar.

1. No Home Assistant, crie um **script** que liga a TV e escolhe a entrada do PC (por exemplo `media_player.turn_on` seguido de `media_player.select_source`) e, se quiser, outro que a desliga.
2. Crie um **token de acesso de longa duração**: seu perfil → **Segurança** → *Tokens de acesso de longa duração*.
3. No Console Mode, escolha *Home Assistant* e preencha o endereço (ex.: `http://homeassistant.local:8123`), o token e a entidade a executar (ex.: `script.ligar_tv_pc`). Aperte **Testar agora**.

Scripts e cenas rodam com `turn_on`, automações com `trigger`, botões com `press`; as outras entidades (`media_player`, `switch`…) com `turn_on` e, ao restaurar, com `turn_off` quando não há entidade de restauração. O token fica guardado criptografado para o seu usuário do Windows (DPAPI).

## Extras opcionais

### HDR
Expand Down
25 changes: 25 additions & 0 deletions docs/TESTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,31 @@ Pré-condições: Ajustes → Interface = **Automático** (padrão).
- [ ] "Copiar diagnóstico" cola dispositivos + amostra; o `consolemode.log` tem a linha `Controles: …` de abertura com o DualSense listado. Resultado: ______
- [ ] Desconectar e reconectar durante o teste: a lista atualiza e a leitura continua. Resultado: ______

## 3c. Controle da TV: Google TV / Android TV (issue #75)

Pré-condições: TV Google TV / Android TV na mesma rede do PC, com **Depuração USB** (ou "Depuração pela rede") ativada nas Opções do desenvolvedor; Ajustes → TV → *Google TV / Android TV* com o IP e a entrada HDMI do PC.

- [ ] **Testar agora** na primeira vez: a TV pede "Permitir depuração"; com "Sempre permitir" + "Permitir", a TV acorda e vai para a entrada do PC. O status mostra sucesso. Resultado: ______
- [ ] **Testar agora** de novo: não pede mais permissão; com a TV em espera, ela liga e troca a entrada. Resultado: ______
- [ ] Recusar o pedido na TV (ou esperar 60 s): o status explica que a TV não autorizou este PC. Resultado: ______
- [ ] IP errado / TV fora da rede: o status diz que a TV não respondeu, em poucos segundos. Resultado: ______
- [ ] **Jogar agora** com a TV em espera: ela liga, troca para o PC e o modo console segue normal. O log tem `TV: ligar (androidTv) ok`. Resultado: ______
- [ ] Com a TV desligada da tomada: o modo console não trava; o log tem `TV: ligar ... falhou` e o fluxo segue (a TV não aparece, o app avisa como antes). Resultado: ______
- [ ] TV que some da rede em espera + **MAC** preenchido: o log mostra `enviando Wake-on-LAN` e a TV liga (com "Ligar pela rede" ativo na TV). Resultado: ______
- [ ] **Colocar a TV em espera ao restaurar** ligado: ao sair do Big Picture, a mesa volta e depois a TV entra em espera. Desligado (padrão): a TV continua ligada. Resultado: ______
- [ ] TV que ignora a tecla HDMI: preencher **Comando da entrada** faz a troca funcionar. Resultado: ______
- [ ] Escolher "Não controlar": os campos somem e nada é enviado à TV. Resultado: ______

## 3e. Controle da TV: Home Assistant (issue #75)

Pré-condições: Home Assistant acessível pelo PC; um script que liga a TV e troca a entrada; token de longa duração; Ajustes → TV → *Home Assistant* preenchido.

- [ ] **Testar agora**: o script roda (histórico do Home Assistant) e a TV liga na entrada do PC. Resultado: ______
- [ ] O `config.json` guarda o token começando com `dpapi:` (não em texto puro); reabrir o app mostra o token (mascarado) e o teste continua funcionando. Resultado: ______
- [ ] Token errado: o status diz que o Home Assistant recusou o token. Entidade inexistente: diz que não encontrou a entidade. Endereço errado: diz que não respondeu. Resultado: ______
- [ ] **Jogar agora**: o script roda antes das telas mudarem; o log tem `TV: Home Assistant script.turn_on ... → 200`. Resultado: ______
- [ ] "Colocar a TV em espera ao restaurar" com entidade de restauração: ela roda depois que a mesa volta. Sem entidade de restauração e entidade inicial `media_player`: roda `media_player.turn_off`. Com script como entidade inicial e sem a de restauração: nada acontece (log explica). Resultado: ______

## 4. Regressões

- [ ] Interface Desktop: mapa de telas, `Segmented`, chips, tour de 3 passos e Ajustes continuam como antes. Resultado: ______
Expand Down
1 change: 1 addition & 0 deletions src/ConsoleMode/ConsoleMode.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
<PackageReference Include="H.NotifyIcon.WinUI" Version="2.3.1" />
<PackageReference Include="Microsoft.WindowsAppSDK" Version="1.7.250401001" />
<PackageReference Include="Microsoft.Windows.SDK.BuildTools" Version="10.0.26100.1742" />
<PackageReference Include="System.Security.Cryptography.ProtectedData" Version="8.0.0" />
<Manifest Include="$(ApplicationManifest)" />
</ItemGroup>

Expand Down
45 changes: 45 additions & 0 deletions src/ConsoleMode/Models/Models.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,54 @@ public sealed class AppConfig
/// <summary>A version the user chose to skip; newer ones are still announced.</summary>
public string SkippedUpdateVersion { get; set; } = "";

/// <summary>Turning the TV on / to the PC's input when console mode starts (issue #75).</summary>
public TvControlConfig Tv { get; set; } = new();

[JsonIgnore]
public string SetupKey =>
$"{FocusMonitor}|{(MonitorModes.TryGetValue(FocusMonitor, out var mode) ? mode.Key : "current")}";
}

public sealed class TvControlConfig
{
public const string None = "none";
public const string AndroidTv = "androidTv";
public const string HomeAssistant = "homeAssistant";

/// <summary>"none" | "androidTv" | "homeAssistant".</summary>
public string Provider { get; set; } = None;

/// <summary>The TV's IP address or host name, optionally with ":port".</summary>
public string Host { get; set; } = "";

/// <summary>For Wake-on-LAN when the TV is in deep standby; empty = don't send it.</summary>
public string MacAddress { get; set; } = "";

/// <summary>HDMI input the PC is plugged into (1-4).</summary>
public int HdmiInput { get; set; } = 1;

/// <summary>Android TV: shell command that switches to the PC's input, for TVs that ignore the HDMI key codes.</summary>
public string InputCommand { get; set; } = "";

/// <summary>Home Assistant base URL, e.g. http://homeassistant.local:8123.</summary>
public string HomeAssistantUrl { get; set; } = "";

/// <summary>Long-lived access token, encrypted for this Windows user (DPAPI, "dpapi:" prefix).</summary>
public string HomeAssistantToken { get; set; } = "";

/// <summary>Entity run when console mode starts (script, scene, automation, media_player…).</summary>
public string HomeAssistantOnEntity { get; set; } = "";

/// <summary>Entity run on restore; empty = turn the start entity off, when it can be.</summary>
public string HomeAssistantOffEntity { get; set; } = "";

/// <summary>Put the TV in standby after the desk is restored. Off by default.</summary>
public bool TurnOffOnRestore { get; set; }

[JsonIgnore]
public bool IsEnabled => !string.IsNullOrWhiteSpace(Provider) && Provider != None;
}

public sealed class SavedDisplayMode
{
public int Width { get; set; }
Expand Down Expand Up @@ -231,6 +274,8 @@ public sealed class ScreenRect
public sealed class ConsoleRuntimeState
{
public bool IsActive { get; set; }
/// <summary>TV control used for this session, for the optional standby on restore.</summary>
public TvControlConfig? Tv { get; set; }
public bool ShouldExit { get; set; }
public bool RestoreInProgress { get; set; }
public bool SteamMoved { get; set; }
Expand Down
Loading
Loading