MediaPreferences

A MediaPreferences holds the cluster’s defaults: the preferred audio and subtitle languages, the time zone its displays show, and when an idle display fades and goes dark. It is the lowest of the three tiers a Play resolves: the Play’s own spec first, then the Player ’s, then this default.

There is exactly one, and its name is default. The CRD pins the name with a CEL rule, so a MediaPreferences under any other name is rejected at apply, and the mistake shows at once instead of adding a silent second object. A cluster without one is fine: a missing default is not an error, and resolution skips the tier.

apiVersion: media.liken.sh/v1alpha1
kind: MediaPreferences
metadata:
  name: default
spec:
  audioLanguages: [ja, en]
  subtitleLanguages: [en]
  subtitles: auto
  timeZone: America/New_York
  idle:
    fadeAfterSeconds: 600
    offAfterSeconds: 1200
    offMode: backlight

The cluster’s defaults: the preferred audio and subtitle languages, the time zone its displays show, and what an idle display does. A Player or a Play overrides the language fields field by field; the time zone has no override.

spec

The default language and subtitle fields. The operator uses each one only when the Player and the Play leave it unset.

Field Type Required Description
audioLanguages []string no Ordered audio language codes, most wanted first; mpv takes the first audio track that matches. Codes are IETF language tags, and mpv treats the ISO 639-1 form en and the ISO 639-2 form eng as the same language.
subtitleLanguages []string no Ordered subtitle language codes, separate from the audio list, so one viewer takes foreign audio with native subtitles.
subtitles string no When subtitles show; on always, off never, auto only when the audio that played is not the first choice. One of: on, off, auto.
timeZone string no The time zone, as an IANA name like America/New_York. The player pod reads it as TZ, so the display clock shows local time instead of UTC. One per cluster: no Play or Player overrides it.
idle object no The cluster’s default for what a display does while nothing plays, read for each field a Player’s own block leaves unset.

spec.idle

The cluster’s default for what a display does while nothing plays, read for each field a Player’s own block leaves unset.

Field Type Required Description
controller string no The operator that draws every idle screen whose Player does not name its own, as a domain-qualified name. Two names belong to the media operator: media.liken.sh/idle-screen, the default, which draws the idle screen this operator ships, and media.liken.sh/none, under which nothing draws an idle screen and no claim exists. Any other name hands each screen to the operator that handles it, which reads a Player’s status.idle for the claim to reference, the requests it carries, the two windows, and the bus it joins. Pattern: ^[a-z0-9.-]+/[a-z0-9-]+$.
image string no The container image that draws every idle screen. The image starts with its own entrypoint and reads each unit’s state from the bus. It implements the fade and off windows, the focus gate, the shade, the volume indicator, and the panel desire in its own process. Unset, every screen whose Player names no image runs the idle client that the media operator ships.
fadeAfterSeconds integer no Seconds with no activity before an idle screen fades to black. Zero disables the automatic fade; unset, every screen fades after 600.
offAfterSeconds integer no Seconds with no activity before an idle panel goes dark, at least fadeAfterSeconds. Zero or unset means panels never go dark on their own. A panel goes dark only where the cluster runs a display-operator that publishes a Display for the screen.
offMode string no Which override the off window applies to the screen’s Display. The default, backlight, holds the panel at brightness zero, which still answers DDC. Power off stops some panels from answering DDC at all; use it only for a panel that you have seen wake from it. One of: backlight, power.

How a Play resolves it

Each field settles on its own, Play then Player then the default. The first tier that states a field wins it, and a field no tier states resolves to nothing. For the two lists, omitting the field means the tier states nothing, and an empty list is a statement: a Play with audioLanguages: [] states no preference and overrides the tiers below it.

The operator resolves the tiers when it creates a Play’s pod, and the resolved languages become mpv’s --alang and --slang arguments. It also reports the resolved values on every Play’s status, so kubectl get play shows what the three tiers settled on. The operator watches MediaPreferences, so an edit refreshes that resolved record on a running Play’s status within one pass; the running player keeps the arguments it started with, and the edit reaches the next Play’s pod.

No status

A MediaPreferences is a table a person writes and nothing reports on, so there is no status subresource, and kubectl get mediapreferences shows the subtitle mode and the age.

Not on the bus

MediaPreferences is the one resource of this operator with no topics on the bus . Nothing at run time subscribes to a preference: the operator resolves the three tiers when it builds a pod, and the settled values travel into the pod as arguments and environment, and onto the Play’s status as the record of what resolved.