# libcec: talking to a television over HDMI-CEC from code

> libcec is the C and C++ library behind Pulse-Eight's USB-CEC adapters, and it now ships bindings for .NET, Node.js and Rust that wrap the native library rather than bundling it. The README also keeps two vendor notes that save hours of debugging, a Panasonic operation-mode sequence and a Raspberry Pi hotplug setting.

**Pulse-Eight/libcec** —   USB CEC Adapter communication Library

- Repository: https://github.com/Pulse-Eight/libcec
- Website: https://libcec.pulse-eight.com/
- Stars: 817 · Forks: 309
- Language: C++
- License: NOASSERTION
- Published: 2026-10-20 · Updated: 2026-10-20 · Language: en
- Canonical page: https://hysenlabs.com/projects/pulse-eight-libcec

## A protocol library for the HDMI feature nobody remembers

libcec provides support for Pulse-Eight's USB-CEC adapter and other CEC capable hardware, like the Raspberry Pi. CEC is the HDMI feature that lets one device control another over the same cable, so a program can turn the television on, change the volume, select an input or press play on a remote that belongs to the set-top box.

The reason this needs a library at all is that CEC is a thin protocol on top of a physical bus, and the bus is not something a general purpose machine can talk to without hardware. A USB-CEC adapter is exactly that hardware, and the Raspberry Pi case works because the SoC has the right pins for the CEC line, so the Pi talks to the television directly over HDMI.

The library is written in C and C++ and exposes a native ICECAdapter interface along with a C API, and the C API is what makes the rest of the ecosystem possible, since a stable C entry point can be wrapped from any language without recompiling the binding for each of them.

There is a FAQ page on the library's own site, and the project keeps a ChangeLog, a Jenkinsfile and a Doxyfile in the repository, which are the artefacts of a project that has been built and documented in the open for a long time. The licence metadata records a custom classification, with the details in the LICENSE file. The default branch is master, the last push was on 2026-09-02, and the recent releases are 8.1.5 and 8.1.6 on 2026-08-07 and 8.1.7 on 2026-09-02.

## Five bindings, one native library

The API documentation is published for every binding at one place, and the README is clear that the docs are generated from this source tree rather than written separately, with the generation instructions in the documentation directory.

The C and C++ documentation covers the native ICECAdapter interface and the C API. The .NET documentation covers the managed LibCecSharp binding. The Node.js documentation covers the N-API addon. The Python documentation covers the SWIG cec module, which is the older binding technology, and it still ships. The Rust documentation covers the libcec crate.

Two of those five are worth a note. The Node.js binding is an N-API addon, which is the current way to write a native addon for Node without depending on the Node ABI, so the addon survives a Node upgrade. The Python binding is generated by SWIG, and SWIG is a code generator that emits a wrapper for a C interface, which is why the Python and Rust wrappers can look different in style while presenting the same calls.

The .NET binding has its own history. The .NET client applications, previously part of this repository, have been moved to a separate repository, so this tree is now the native library plus the bindings that wrap it, and the managed client is maintained elsewhere.

## The packages bind the library, they do not carry it

Three bindings are published to their language's registry, from 8.1.6 onwards, and the README is explicit about what that means.

Each binds the native library rather than containing it, so libCEC itself still has to be installed, and the platform sections below explain how. The install commands are:

```bash
dotnet add package LibCecSharp
npm install libcec
cargo add libcec
```

C, C++ and Python come from the platform packages instead: libcec8-dev and python-libcec on Debian and Ubuntu, or the Windows installer.

That is an important difference in kind between the two groups. A NuGet, npm or crates.io package is a thin wrapper, and on a machine where the native library is absent the wrapper compiles and then fails at run time with a missing shared object. A Debian package installs the native code, the development headers and the wrapper together, which is why the C, C++ and Python path is the one a Linux developer is most likely to want.

The rule of thumb is that the registry packages are for the case where you already have libCEC, and the platform packages are the starting point otherwise. The versions also differ, with the platform packages versioned as libcec8-dev for the 8 series.

## Platforms and the hardware that works

The supported platforms have their own documents in the repository: docs/README.linux.md for Linux and BSD, docs/README.osx.md for Apple OS X, and docs/README.windows.md for Microsoft Windows, with a separate docs/README.developers.md for people working on the library itself.

The supported hardware list is longer than the first entry suggests. There is the Pulse-Eight USB-CEC Adapter, the Pulse-Eight Intel NUC CEC Adapter, and the Pulse-Eight CEC Adapter for the Skull Canyon and Hades Canyon NUC systems. Then there is the Raspberry Pi, some Exynos SoCs, the NXP TDA995x, and the Odroid C2 with its Amlogic S905.

Two patterns are worth noticing. The first is that the Raspberry Pi is a special case rather than a generic device, because a Pi has the HDMI CEC line available on its GPIO header, so it can be the CEC endpoint without any USB adapter in between. The second is that the list is mostly older or embedded silicon, Exynos, the TDA995x, the Amlogic S905, and the NUCs, which tells you this library is aimed at set-top boxes, media centres and homebrew devices rather than at desktops. A desktop would use the USB adapter, which is the first item on the list.

For a project that controls a television, the practical consequence is that the hardware choice determines the install path, and the vendor notes below are the ones that come up once the hardware is chosen.

## Two vendor notes that cost hours if you do not read them

The vendor specific notes section is short and both entries are the kind of detail that looks like a firmware bug and is not.

For Panasonic, to enable the media control buttons on the bottom of the remote you may have to change the operation mode. The procedure is: press the bottom Power button, keep it pressed, and press 7 3 Stop. After releasing the Power button, Play, Pause and the rest should work in XBMC.

So the fix is a three key sequence on the television's own remote, and the symptom is a remote whose transport buttons do nothing while everything else does. That is a mode rather than a fault, and the README points out that you may have to change it, so it is a setup step rather than a workaround.

For the Raspberry Pi, if your television cannot detect the Pi's CEC, or if the Pi cannot detect the television, try adding the following line in the boot configuration file and reboot the Pi:

```
hdmi_force_hotplug=1
```

The setting is a hotplug override, and it addresses a specific and common failure: a Pi that is powered on after the television, or a television that does not assert the hotplug line for the Pi's HDMI port. Forcing the assertion makes the two devices find each other.

Both notes are of the same kind, and they are the most useful part of the README for anyone bringing up this hardware for the first time. Neither is a bug in the library, and both are invisible from the code.

## The repository layout, and what each directory implies

The top-level listing shows a project with several toolchains in it, and most directories imply one.

The source is in src/ with the public headers in include/, and the build is CMake, with a CMakeLists.txt at the root and a cmake/ directory for the modules. The Doxyfile is the input to the API documentation that the README says is generated from this tree. There is a debian/ directory, which is the Debian and Ubuntu packaging that produces the libcec8-dev and python-libcec packages the README tells Linux users to install, and a windows/ directory for the Windows build and installer, plus a systemd/ directory for the Linux service units.

The .gitmodules file says the build has submodules, which is typical of a project that vendors a code generator or a piece of the toolchain. There is a licenses/ directory, which is how a project keeps the licence texts of everything it ships, and a support/ directory. The .github/ directory holds the workflows, and the Jenkinsfile is the older continuous integration definition, so both are in use. A CLAUDE.md and an AUTHORS file sit alongside the README and the ChangeLog, and the ChangeLog rather than a generated changelog is a good sign for a project where every release note matters to someone packaging it.

The homepage is libcec.pulse-eight.com, which is also where the FAQ lives, and the API reference is published separately at the project's GitHub Pages site.

## Conclusion

Adopt libcec if you are building software that has to control a television, a soundbar or an amplifier over HDMI-CEC, because it handles the protocol on hardware from a USB adapter to a Raspberry Pi, and the C API underneath is what all the other bindings call. Do not adopt the language packages as self-contained dependencies, because each binding only wraps the native library, so libCEC itself has to be installed as well, and the C, C++ and Python installs come from platform packages rather than from a registry. Before you write code, read the two vendor notes, since a Raspberry Pi that cannot see the television often needs hdmi_force_hotplug=1 in its boot configuration, and a Panasonic remote needs its operation mode changed with the 7 3 sequence.

## FAQ

### What is libcec used for?

It provides support for Pulse-Eight's USB-CEC adapter and other CEC capable hardware such as the Raspberry Pi, so that software can control a television, amplifier or other device over the HDMI-CEC bus. The library is written in C and C++ and exposes a native ICECAdapter interface plus a C API.

### Do the npm, NuGet and crates.io packages include the native library?

No. The README says each binding binds the native library rather than containing it, so libCEC itself still has to be installed. C, C++ and Python come from the platform packages libcec8-dev and python-libcec on Debian and Ubuntu, or from the Windows installer.

### Which language bindings does libcec have?

Five, with published API references for each: C and C++ through the native ICECAdapter interface and the C API, .NET through the managed LibCecSharp binding, Node.js through the N-API addon, Python through the SWIG cec module, and Rust through the libcec crate. The .NET client applications were moved to a separate repository.

### My Raspberry Pi cannot see the television over CEC, what should I try?

The README suggests adding hdmi_force_hotplug=1 to the boot configuration file and rebooting the Pi, which forces the HDMI hotplug assertion so the two devices find each other. There is also a Panasonic note, where the media control buttons on the bottom of the remote need the operation mode changed by pressing the bottom Power button, holding it and pressing 7 3 Stop.

## Sources

- [Issues](https://github.com/Pulse-Eight/libcec/issues)
- [Project website](https://libcec.pulse-eight.com/)
- [Pulse-Eight/libcec on GitHub](https://github.com/Pulse-Eight/libcec)
- [README](https://github.com/Pulse-Eight/libcec/blob/master/README.md)
- [Releases](https://github.com/Pulse-Eight/libcec/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/pulse-eight-libcec
