1
0
Fork
You've already forked cec-controller
0
Use libcec and dbus to start and stop your TV and simulate keyboard presses from your TV Remote
  • Go 98.5%
  • Shell 1.5%
2026年06月21日 13:25:44 +02:00
.github/workflows ci: install libcec runtime in release job for man page generation 2026年03月30日 00:39:29 +02:00
scripts ci: use custom gobinary script for goreleaser prebuilt binaries 2026年03月29日 22:18:00 +02:00
.gitignore ci: use goreleaser builder:prebuilt for multi-arch packaging 2026年03月29日 22:13:48 +02:00
.goreleaser.yml feat: active source switching, logind inhibitor, man pages, example sync 2026年03月30日 00:25:28 +02:00
cec-controller.service fix service 2025年10月12日 14:04:35 +02:00
cec-controller.yaml.example feat: active source switching, logind inhibitor, man pages, example sync 2026年03月30日 00:25:28 +02:00
cec.go feat: active source switching, logind inhibitor, man pages, example sync 2026年03月30日 00:25:28 +02:00
cec_test.go style: fix gofmt alignment in cec_test.go 2026年03月30日 00:31:30 +02:00
config.go feat: active source switching, logind inhibitor, man pages, example sync 2026年03月30日 00:25:28 +02:00
config_test.go feat: active source switching, logind inhibitor, man pages, example sync 2026年03月30日 00:25:28 +02:00
go.mod feat: active source switching, logind inhibitor, man pages, example sync 2026年03月30日 00:25:28 +02:00
go.sum feat: active source switching, logind inhibitor, man pages, example sync 2026年03月30日 00:25:28 +02:00
inhibitor.go feat: active source switching, logind inhibitor, man pages, example sync 2026年03月30日 00:25:28 +02:00
interfaces.go feat: active source switching, logind inhibitor, man pages, example sync 2026年03月30日 00:25:28 +02:00
keymap.go More Logging 2026年06月21日 13:25:44 +02:00
keymap_test.go Fix tests 2026年06月21日 12:36:15 +02:00
LICENSE finish main work 2025年10月09日 19:53:01 +02:00
main.go feat: active source switching, logind inhibitor, man pages, example sync 2026年03月30日 00:25:28 +02:00
power_events.go refactor: fix concurrency bugs, invert CEC semantics, improve queue design 2026年03月29日 21:42:59 +02:00
power_events_test.go Address PR feedback: unexport newCECWithOpener, use struct embedding, remove dummy test 2025年10月12日 12:31:50 +00:00
queue.go refactor: fix concurrency bugs, invert CEC semantics, improve queue design 2026年03月29日 21:42:59 +02:00
queue_test.go refactor: fix concurrency bugs, invert CEC semantics, improve queue design 2026年03月29日 21:42:59 +02:00
README.md Remove default keymapping 2026年06月21日 12:02:16 +02:00

cec-controller

CEC Controller is a Linux CLI application that listens for HDMI-CEC key events and translates them to Linux virtual keyboard actions. It also reacts to system power events (startup, shutdown, sleep, resume) and can be configured for custom key mappings.

Warning

This project requires libcec-compatible hardware. You need a physical HDMI-CEC adapter recognised by libcec — the most common option is the Pulse-Eight USB–CEC Adapter. Some Raspberry Pi models expose a built-in CEC interface (/dev/ttyAMA0). Without compatible hardware the daemon will fail to open the adapter and exit immediately.

Features

  • HDMI-CEC key listening: Uses libcec via Go bindings to receive remote key presses from connected HDMI devices.
  • Virtual keyboard emulation: Maps CEC keys to Linux key codes and triggers key events using micmonay/keybd_event.
  • Customizable key mapping: Define the CEC→Linux key map via CLI flags.
  • Power event hooks: Responds to system startup, shutdown, sleep, and resume of the host machine and transmits corresponding CEC commands (e.g. "Power On", "Standby") to connected devices.
  • Active source switching: Optionally claims the active HDMI source on startup so the TV switches input to this device automatically.
  • Shutdown protection: Holds a systemd-logind delay inhibitor lock while sending CEC standby commands, ensuring the system waits for CEC to complete before sleeping or shutting down.
  • Systemd-ready: Includes a sample systemd service file for robust startup and integration.
  • Man pages: Installs a man page (man cec-controller) when installed via .deb or .rpm package.

Installation

Important

Make sure to have no other services running libcec or any kind of cec-client because only one process can lock the CEC serial.

Download pre-built binaries and packages from the Releases page:

Ubuntu/Debian (amd64):

wget https://github.com/eliottness/cec-controller/releases/latest/download/cec-controller_<version>_ubuntu_amd64.deb
sudo apt install ./cec-controller_<version>_ubuntu_amd64.deb

Ubuntu/Debian (arm64):

wget https://github.com/eliottness/cec-controller/releases/latest/download/cec-controller_<version>_ubuntu_arm64.deb
sudo apt install ./cec-controller_<version>_ubuntu_arm64.deb

Fedora/RHEL (amd64):

wget https://github.com/eliottness/cec-controller/releases/latest/download/cec-controller_<version>_fedora_amd64.rpm
sudo dnf install cec-controller_<version>_fedora_amd64.rpm

Fedora/RHEL (arm64):

wget https://github.com/eliottness/cec-controller/releases/latest/download/cec-controller_<version>_fedora_arm64.rpm
sudo dnf install cec-controller_<version>_fedora_arm64.rpm

From Source

Prerequisites

  • Go 1.24+
  • libcec (sudo apt install libcec-dev)
  • Linux with uinput support (for virtual keyboard)

Build

Requires libcec-dev and libp8-platform-dev on debian-based systems or just libcec-devel on fedora-based systems:

go build -o cec-controller .

Usage

./cec-controller [flags]

Configuration

cec-controller can be configured via command-line flags or a YAML configuration file. Command-line flags take precedence over the configuration file.

Configuration File

Create a configuration file at /etc/cec-controller.yaml. See cec-controller.yaml.example for a complete example.

# Example configurationcec-adapter:"/dev/ttyACM0"device-name:"My PC"debug:falseretries:5keymap:"1": "29+2"# CEC key 1 -> Ctrl+1"2": "29+3"# CEC key 2 -> Ctrl+2devices:- "0"- "1"

Common Flags

  • --cec-adapter=<path>
    Path to HDMI-CEC adapter e.g. /dev/ttyACM0. Leave blank for auto-detect.

  • --debug
    Enable debug logging.

  • --keymap <cec>:<linux>
    Add CEC to Linux key mappings (repeat as needed). Example: --keymap 1:105 maps CEC key 1 to Linux key code 105 (KEY_KP1). You can also specify modifier keys using +, e.g. --keymap 1:29+105 maps CEC key 1 to Ctrl+KP1.

  • --no-power-events
    Disable handling of system power events.

  • --devices Power event device logical addresses (e.g. --devices 0,1). Defaults to 0.

  • --retries Number of times to retry opening the CEC adapter on failure. Default is 5. Each attempt may take up to 10 seconds.

  • --restart-retries Maximum number of process restarts when the CEC library gets stuck. Default is 3. Set to 0 to disable restarts.

  • --device-name Device name to report to the CEC network. Default is the hostname.

  • --set-active-source Claim the active HDMI source on startup, causing the TV to switch its input to this device.

  • --active-source-type CEC device type to report when claiming active source. Default is 4 (Playback Device, suitable for PCs). Accepted values: 0=TV, 1=Recording, 3=Tuner, 4=Playback, 5=AudioSystem.

Example using custom key mappings

Key mapping data for CEC can be found here

Linux key codes can be found here

Here for example, CEC buttons "1" and "2" are mapped to Ctrl+1 and Ctrl+2 to use Steam Big Picture overlays from my TV remote:

./cec-controller --keymap 1:29+2 --keymap 2:29+3

Systemd Integration

See cec-controller.service:

[Unit]
Description=CEC Controller CLI Service
After=local-fs.target
[Service]
Type=simple
ExecStart=/usr/local/bin/cec-controller
Restart=on-failure
[Install]
WantedBy=multi-user.target

Power Event Handling

This app detects and reacts to:

  • Startup: Powers on connected devices when the service starts alongside systemd
  • Shutdown: Puts connected devices to standby on system shutdown/reboot
  • Sleep/Resume: Puts devices to standby on suspend, powers them on again on resume

Before putting devices to standby, cec-controller acquires a systemd-logind delay inhibitor lock for sleep and shutdown. This guarantees the CEC standby command completes before the system proceeds, preventing TVs and receivers from being left powered on after the host sleeps.

Contributing

PRs and issues are welcome!

Running tests locally

# Install build dependencies (Ubuntu/Debian)
sudo apt-get install -y libcec-dev libp8-platform-dev
CGO_ENABLED=1 go test ./...

Before submitting a PR

# Formatting (CI enforces this)
gofmt -l . # should print nothing
gofmt -w . # fix in place
# Vet
CGO_ENABLED=1 go vet ./...

CI will run gofmt, go vet, and go test automatically on every PR, then build binaries for amd64 and arm64.

Releases

Releases are automated via GitHub Actions. Push a semver tag to trigger a build:

git tag v1.2.3
git push origin v1.2.3

The pipeline builds native binaries on ubuntu-latest (amd64) and ubuntu-24.04-arm (arm64), then packages them with goreleaser into .tar.gz, .deb, and .rpm artifacts published to the Releases page.

License

GNU General Public License v3.0 or later. See LICENSE for details.