Exddcutil (Exddcutil v0.1.0)

View Source

Elixir wrapper for the ddcutil tool to control monitor settings via DDC/CI.

This library provides a high-level interface to query and modify monitor settings on Linux systems using the DDC/CI protocol through the ddcutil command-line tool.

Prerequisites

  • Linux system with ddcutil installed
  • DDC/CI compatible monitor(s) with DDC/CI enabled in the OSD

Testing Status

This library has been tested with:

  • Dell P2715Q

Other DDC/CI compatible monitors should work, but behavior may vary depending on manufacturer implementation.

Basic Usage

# Detect available displays
{:ok, displays} = Exddcutil.detect()

# Get display capabilities
{:ok, caps} = Exddcutil.capabilities(1)

# Set brightness
:ok = Exddcutil.set_brightness(1, 75)

# Get current brightness
{:ok, %{current: 75, max: 100}} = Exddcutil.get_brightness(1)

Most functions take a display index (1-based) as the first argument, as returned by detect/1.

Summary

Functions

Gets the full capabilities of a display.

Detects all available displays connected to the system.

Gets the current blue gain/drive.

Gets the current brightness setting.

Gets the current color preset/temperature.

Gets the current contrast setting.

Gets the current display mode.

Gets the current green gain/drive.

Gets the current input source.

Lists available input sources with an active flag indicating the current source.

Gets the current red gain/drive.

Gets the current screen orientation.

Reads an arbitrary VCP code.

Lists available input sources from display capabilities.

Sets the blue gain/drive.

Sets the green gain/drive.

Sets the screen orientation. Note: may be read-only on some monitors.

Sets an arbitrary VCP code to a value.

Types

bus_index()

@type bus_index() :: pos_integer()

common_opt()

@type common_opt() :: runner_opt() | target_opt()

display_index()

@type display_index() :: pos_integer()

runner_opt()

@type runner_opt() :: {:runner, module()}

target_opt()

@type target_opt() :: {:display, display_index()} | {:bus, bus_index()}

Functions

capabilities(display_index, opts \\ [])

@spec capabilities(display_index(), [common_opt()]) :: {:ok, map()} | {:error, any()}

Gets the full capabilities of a display.

Returns a map containing model, vendor, serial, and available features with their values.

Examples

iex> Exddcutil.capabilities(1)
{:ok, %{
  model: "DELL P2715Q",
  vendor: "DEL",
  features: %{
    "Brightness" => %{code: 16, values: %{range: {0, 100}}},
    "Input Source" => %{code: 96, values: [%{code: "0x11", name: "HDMI-1"}]}
  },
  input_sources: [%{code: "0x11", name: "HDMI-1"}]
}}

detect(opts \\ [])

@spec detect([runner_opt()]) :: {:ok, list()} | {:error, any()}

Detects all available displays connected to the system.

Returns a list of maps containing display information including index, bus number, model, vendor, and serial number.

Examples

iex> Exddcutil.detect()
{:ok, [
  %{index: 1, bus: 5, model: "DELL P2715Q", vendor: "DEL", serial: "ABC123"}
]}

get_blue(display_index, opts \\ [])

@spec get_blue(display_index(), [common_opt()]) :: {:ok, map()} | {:error, any()}

Gets the current blue gain/drive.

get_brightness(display_index, opts \\ [])

@spec get_brightness(display_index(), [common_opt()]) ::
  {:ok, map()} | {:error, any()}

Gets the current brightness setting.

get_color_preset(display_index, opts \\ [])

@spec get_color_preset(display_index(), [common_opt()]) ::
  {:ok, map()} | {:error, any()}

Gets the current color preset/temperature.

get_contrast(display_index, opts \\ [])

@spec get_contrast(display_index(), [common_opt()]) :: {:ok, map()} | {:error, any()}

Gets the current contrast setting.

get_display_mode(display_index, opts \\ [])

@spec get_display_mode(display_index(), [common_opt()]) ::
  {:ok, map()} | {:error, any()}

Gets the current display mode.

get_green(display_index, opts \\ [])

@spec get_green(display_index(), [common_opt()]) :: {:ok, map()} | {:error, any()}

Gets the current green gain/drive.

get_input_source(display_index, opts \\ [])

@spec get_input_source(display_index(), [common_opt()]) ::
  {:ok, map()} | {:error, any()}

Gets the current input source.

Returns a map with the current source code and label.

Examples

iex> Exddcutil.get_input_source(1)
{:ok, %{code: "0x60", name: "Input Source", current: "0x0f", current_label: "DisplayPort-1"}}

get_input_sources(display_index, opts \\ [])

@spec get_input_sources(display_index(), [common_opt()]) ::
  {:ok, list()} | {:error, any()}

Lists available input sources with an active flag indicating the current source.

Combines input_sources/2 and get_input_source/2 to mark which input is currently active.

Examples

iex> Exddcutil.get_input_sources(1)
{:ok, [
  %{code: "0x11", name: "HDMI-1", active: false},
  %{code: "0x0f", name: "DisplayPort-1", active: true}
]}

get_red(display_index, opts \\ [])

@spec get_red(display_index(), [common_opt()]) :: {:ok, map()} | {:error, any()}

Gets the current red gain/drive.

get_screen_orientation(display_index, opts \\ [])

@spec get_screen_orientation(display_index(), [common_opt()]) ::
  {:ok, map()} | {:error, any()}

Gets the current screen orientation.

get_vcp(display_index, code, opts \\ [])

@spec get_vcp(display_index(), non_neg_integer() | String.t(), [common_opt()]) ::
  {:ok, map()} | {:error, any()}

Reads an arbitrary VCP code.

Returns a map with code, name, current value, and optionally max value and current label.

Examples

iex> Exddcutil.get_vcp(1, 0x10)
{:ok, %{code: "0x10", name: "Brightness", current: 75, max: 100}}

input_sources(display_index, opts \\ [])

@spec input_sources(display_index(), [common_opt()]) ::
  {:ok, list()} | {:error, any()}

Lists available input sources from display capabilities.

Returns a list of maps with code and name for each input source.

Examples

iex> Exddcutil.input_sources(1)
{:ok, [
  %{code: "0x11", name: "HDMI-1"},
  %{code: "0x0f", name: "DisplayPort-1"}
]}

run_ddc(args, opts \\ [])

@spec run_ddc([String.t()], [common_opt()]) :: {:ok, String.t()} | {:error, any()}

set_blue(display_index, value, opts \\ [])

@spec set_blue(display_index(), non_neg_integer(), [common_opt()]) ::
  :ok | {:error, any()}

Sets the blue gain/drive.

set_brightness(display_index, value, opts \\ [])

@spec set_brightness(display_index(), non_neg_integer(), [common_opt()]) ::
  :ok | {:error, any()}

Sets the display brightness.

Parameters

  • display_index - Display index (1-based)
  • value - Brightness value (typically 0..100, check capabilities for range)
  • opts - Optional keyword list (runner, bus)

Examples

iex> Exddcutil.set_brightness(1, 75)
:ok

set_color_preset(display_index, value, opts \\ [])

@spec set_color_preset(display_index(), term(), [common_opt()]) ::
  :ok | {:error, any()}

Sets the color preset.

Examples

iex> Exddcutil.set_color_preset(1, 0x05)
:ok

iex> Exddcutil.set_color_preset(1, "0x05")
:ok

set_contrast(display_index, value, opts \\ [])

@spec set_contrast(display_index(), non_neg_integer(), [common_opt()]) ::
  :ok | {:error, any()}

Sets the display contrast.

Examples

iex> Exddcutil.set_contrast(1, 50)
:ok

set_display_mode(display_index, mode, opts \\ [])

@spec set_display_mode(display_index(), term(), [common_opt()]) ::
  :ok | {:error, any()}

Sets the display mode.

set_green(display_index, value, opts \\ [])

@spec set_green(display_index(), non_neg_integer(), [common_opt()]) ::
  :ok | {:error, any()}

Sets the green gain/drive.

set_input_source(display_index, source, opts \\ [])

@spec set_input_source(display_index(), term(), [common_opt()]) ::
  :ok | {:error, any()}

Sets the input source.

Accepts either a source name (e.g., "HDMI-1"), hex code (e.g., "0x11"), or integer code.

Examples

iex> Exddcutil.set_input_source(1, "DisplayPort-1")
:ok

iex> Exddcutil.set_input_source(1, "0x0f")
:ok

set_red(display_index, value, opts \\ [])

@spec set_red(display_index(), non_neg_integer(), [common_opt()]) ::
  :ok | {:error, any()}

Sets the red gain/drive.

set_screen_orientation(display_index, orientation, opts \\ [])

@spec set_screen_orientation(display_index(), term(), [common_opt()]) ::
  :ok | {:error, any()}

Sets the screen orientation. Note: may be read-only on some monitors.

set_vcp(display_index, code, value, opts \\ [])

@spec set_vcp(
  display_index(),
  non_neg_integer() | String.t(),
  non_neg_integer() | String.t(),
  [
    common_opt()
  ]
) :: :ok | {:error, any()}

Sets an arbitrary VCP code to a value.

Examples

iex> Exddcutil.set_vcp(1, 0x14, 6500)  # Color temperature
:ok