libCEC — .NET API (LibCecSharp)
LibCecSharp (namespace CecSharp) is the managed binding for libCEC: a pure
C# assembly that binds the native library through its C API (P/Invoke over
cecc.h), targeting net8.0. Unlike the old C++/CLI wrappers it runs anywhere
the native library does — Windows, Linux, macOS and Raspberry Pi.
It lets .NET applications control CEC-capable HDMI devices — power a TV on or to standby, become the active source, send remote keys, read device state — and receive bus events. Every binding wraps the same engine, so the concepts match the C/C++ reference, which documents them in the most depth.
Requirements
- A Pulse-Eight USB-CEC adapter (or a supported SoC-native CEC backend).
- The native libCEC library available at runtime (
cec.dllon Windows,libcec.soon Linux,libcec.dylibon macOS). - The .NET 8 runtime (the Windows installer prompts for the .NET 8 Desktop Runtime when the managed component is selected).
Installing
Debian / Ubuntu
sudo apt-get install libcec-dotnet
This installs the LibCecSharp assembly and its NuGet package alongside the
native library.
Windows
The USB-CEC Adapter software installer ships LibCecSharp.dll and the native
cec.dll together (select the managed component). To build both from source, run
python windows\create-installer.py, which drives cmake with
-DENABLE_DOTNET_LIB=1.
Build from source (any platform with the .NET SDK)
The managed binding is a cmake option, off by default:
mkdir build && cd build
cmake .. -DENABLE_DOTNET_LIB=1
make -j4
Add -DENABLE_DOTNET_APPS=1 to also build the Windows-only cec-tray and the
cross-platform CecSharpTester sample. Reference the resulting LibCecSharp.dll
(or its NuGet package) from your project, and make sure the native library is on
the loader path at runtime.
Using the API
Derive from CecCallbackMethods to receive
events, describe yourself in a
LibCECConfiguration, then construct
LibCecSharp and open a connection.
using CecSharp;
// 1. handle events by overriding the callback methods
class CecClient : CecCallbackMethods
{
public override int ReceiveLogMessage(CecLogMessage message)
{
Console.WriteLine($"log: {message.Message}");
return 1;
}
public override int ReceiveKeypress(CecKeypress key)
{
Console.WriteLine($"key: {key.Keycode}");
return 1;
}
}
var client = new CecClient();
// 2. describe this client
var config = new LibCECConfiguration();
config.DeviceName = "CecSharp";
config.DeviceTypes.Types[0] = CecDeviceType.RecordingDevice;
config.ClientVersion = LibCECConfiguration.CurrentVersion;
config.Callbacks = client;
// 3. create the instance and open the first adapter found
using var lib = new LibCecSharp(client, config);
CecAdapter[] adapters = lib.FindAdapters(string.Empty);
if (adapters.Length > 0 && lib.Open(adapters[0].ComPort, 10000))
{
// 4. control the bus
lib.PowerOnDevices(CecLogicalAddress.Tv);
foreach (var address in lib.GetActiveDevices().Addresses)
if (address != CecLogicalAddress.Unknown)
Console.WriteLine(lib.GetDeviceOSDName(address));
// 5. clean up
lib.Close();
}
FindAdapters(string.Empty) enumerates connected adapters;
Open connects to one. The callback methods
are invoked from libCEC's worker thread, so keep them short. Dispose the
LibCecSharp instance (the using above) to close the connection and release
the native resources.
See the CecSharpTester console sample and the cec-tray WinForms app in the
cec-dotnet repository for complete,
runnable programs.
API reference
Browse the full type reference under Api in the navigation, starting with
LibCecSharp.