I put my Steam Machine to sleep. The TV goes black. Three seconds later it's back, glowing, with Samsung's "check device power, turn on the device" screen, and the bastard stays there until I get up and find the remote.
It's annoying AF, especially that I paid a fortune for this supposedly top tier fucking Samsung TV (designed for gaming).
The TV doesn't have internet access, because I only use it for gaming, and the TV manufacturers' anti-consumer, privacy violating crusade does not bolster my confidence in them. In other words: fuck 'em.
So the only thing left that can talk to it is the HDMI cable, which means HDMI-CEC, whose only job is to turn on and off the TV. When it feels like it - at best. It's infuriating, because when I plop down on the couch to do some quality time gaming, finding the remote in my office chaos is the last thing I want to do.
My Steam Controller turns the Steam Machine on and CEC turn-on DOES work.
BUT when I put the Machine into Sleep, the TV turns off for a split second then comes back on. And what do I do? Do unpaid bug hunting for billion dollar companies to do their fucking job for free if I want to enjoy their product to their full extent. Brilliant.
(If your problem is the Steam Machine waking itself back up after the TV goes off, that's a different bug, and this thread is where it lives.)
The Setting That Was Off
In Settings > Power > HDMI CEC there's an option for turning the TV off when the Steam Machine sleeps. On mine it was off. Turning the TV on at wake was on, which is why half of it worked.
Switched it on. Put it to sleep. TV came back AGAIN.
Of course it did.
A Tenth of a Second
So I went through the logs, and the Steam Machine DOES try. It writes "Putting TV in standby", and a tenth of a second later the whole system freezes to go to sleep, before the message has left the box. The TV never hears "go to sleep". It just loses its picture, and Samsung's answer to losing its picture is the nag screen.
A tenth of a second.
sigh Am I going to get up and find the remote every night over a tenth of a second? Absolutely not.
The Fix
A tiny background service that does what SteamOS should: before every sleep it tells the system "hold on", sends the TV to sleep itself, waits until the message is actually out, then lets go. Controller, Steam menu, whatever, the TV goes off now and stays off.
Code's below, but first, the only question that matters:
Does Your TV Even Listen?
On the Steam Machine in Desktop Mode, open Konsole, and send the TV to sleep by hand:
cec-ctl -d /dev/cec0 --to 0 --standby
Mine (Samsung QN90) switched off on the spot. If yours does too, your TV is fine, the problem is on the SteamOS side, and the fix below should work whatever brand you've got. If it ignores you, stop here, this probably won't help.
The Code
The script, saved as ~/.local/bin/tv-standby-on-sleep.py:
#!/usr/bin/python3
# Puts the TV in CEC standby before the Steam Machine sleeps.
import os, subprocess
import dbus
from dbus.mainloop.glib import DBusGMainLoop
from gi.repository import GLib
DBusGMainLoop(set_as_default=True)
bus = dbus.SystemBus()
logind = dbus.Interface(bus.get_object("org.freedesktop.login1", "/org/freedesktop/login1"),"org.freedesktop.login1.Manager")
lock = None
def take_lock():
global lock
if lock is None:
lock = logind.Inhibit("sleep", "tv-standby", "Put TV in standby", "delay").take()
def on_prepare(going_to_sleep):
global lock
if going_to_sleep:
subprocess.run(["cec-ctl", "-d", "/dev/cec0", "--to", "0", "--standby"],
stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, timeout=4)
if lock is not None:
os.close(lock)
lock = None
else:
take_lock()
bus.add_signal_receiver(on_prepare, "PrepareForSleep", "org.freedesktop.login1.Manager")
take_lock()
GLib.MainLoop().run()
The service that runs it, saved as ~/.config/systemd/user/tv-standby.service:
[Unit]
Description=Put TV in CEC standby before sleep
[Service]
ExecStart=%h/.local/bin/tv-standby-on-sleep.py
Restart=on-failure
[Install]
WantedBy=default.target
Switch it on:
chmod +x ~/.local/bin/tv-standby-on-sleep.py
systemctl --user daemon-reload
systemctl --user enable --now tv-standby.service
Everything it needs is already on SteamOS, so no sudo, nothing outside your home folder, so an update shouldn't wipe it.
If you changed your mind (why would you?):
systemctl --user disable --now tv-standby.service
rm ~/.local/bin/tv-standby-on-sleep.py ~/.config/systemd/user/tv-standby.service
So
The TV stays off the internet, turns on when I pick up the controller, and turns off when I put it down. Which is what it should have done from day one. You're welcome, Valve and Samsung.
Tested on SteamOS 3.8.28 and a Samsung QN90.