Sink
A Sink is one playback endpoint as a Kubernetes resource: an
analog jack, an HDMI or DisplayPort output, the playback side of a
USB card, or a Bluetooth speaker. The operator creates one for every
endpoint it publishes, cluster-scoped like a Node, named by the
same device name the ResourceSlice carries. You never create or
delete one. The operator writes status: where the endpoint is, the
controls the card declares, and the values it last read. The media
operator writes status.session, the volume asks of a remote’s keys.
You write spec, which states the settings you want for the endpoint.
apiVersion: audio.liken.sh/v1alpha1
kind: Sink
metadata:
name: node-1-usb-0573-1573-a34004801402-usb-audio
spec:
volume:
level: 80
max: 100
step: 5
controls:
PCM Playback Volume: "120"
status:
node: node-1
location: "1-6"
connectionType: usb
card:
number: 1
id: HID
driver: USB-Audio
name: USB Audio and HID
pcm:
device: 0
id: USB Audio
nodeName: liken.audio.card1-pcm0
layoutSource: ChannelMap
capabilities:
PCM Playback Volume:
type: integer
min: 0
max: 127
minDecibels: "-63.50"
maxDecibels: "0.00"
channels: 2
PCM Playback Switch:
type: boolean
channels: 1
observed:
volume: 80
mute: false
controls:
PCM Playback Volume: "120"
PCM Playback Switch: "on"
conditions:
- type: Connected
status: "True"
- type: Ready
status: "True"
- type: LayoutApplied
status: "True"
The claim and the Sink answer two different needs. A pod that
plays sound still holds the output through a claim, as the
claim guide
shows, and it still has its own
stream volume. The Sink is for everything about the output that
is not the sound itself: its default level, its mute, and the
card’s own controls. Because it is an ordinary Kubernetes resource,
anything with the right RBAC can change it. A pod that only wants
to mute the kitchen needs no claim, and a rule that lowers every
speaker at night is one patch per Sink.
Set endpoint volume and controls
walks through
it.
One playback endpoint: an analog jack, an HDMI or DisplayPort output, a USB card’s playback side, or a Bluetooth speaker. Its status reports hardware facts and the values the operator last read. Its spec declares desired endpoint settings. The name is the machine’s name and the card’s identity, as the Sink reference gives them. When a USB card’s name would pass 63 characters, it holds the first eight hex digits of the SHA-256 of the serial in place of the serial.
spec
The desired settings for the endpoint. Every field is optional. The operator writes volume.level and mute when they change and when the endpoint appears, such as a speaker that reconnects or a node that PipeWire builds again, and otherwise reports the level the endpoint holds. It writes a declared control or codec back when the endpoint diverges from it. It never writes a field that the spec leaves out.
| Field | Type | Required | Description |
|---|---|---|---|
volume |
object | no | The endpoint’s volume, in percent of unity. level is the default level that the operator applies. max and step bound the volume asks the media operator writes into status.session, and the operator does not read them. |
mute |
boolean | no | Whether the endpoint is silent. The operator applies this setting at the same layer as volume.level, and on the same terms. |
controls |
map[string]string | no | The card’s own controls, keyed by the kernel’s control name as status.capabilities lists them, such as Master Playback Volume. An integer control takes a number within its range. A boolean control takes on or off. An enumerated control takes one of its values. The operator writes a control only when spec states it. When two endpoints share one control, the last write wins because the hardware has one register. |
layout |
[]string | no | The channel positions of an ALSA sink, in PCM slot order, in PipeWire’s channel names, such as FL, FR, FC, LFE, RL, RR, SL, SR, RLC, RRC, TFL, TFR, NA for a slot that plays nothing, and AUX0 to AUX63. A 7.1 receiver on HDMI takes [FL, FR, RL, RR, FC, LFE, SL, SR], and a 5.1 one takes [FL, FR, RL, RR, FC, LFE]. When this field is absent, the operator selects the layout from the monitor’s ELD on HDMI and DisplayPort, from the device’s own channel map on USB, and declares no positions on the analog jack, whose streams then play in stereo. The operator declares the layout to PipeWire, and a change restarts PipeWire inside its container once no stream plays on the machine. The number of positions must be a channel count the device accepts, or PipeWire ignores the layout. The operator does not write the kernel’s channel map, so on HDMI each slot reaches the speaker the kernel’s standard allocation gives it, and a height position names a slot that the kernel routes elsewhere. A Bluetooth speaker ignores this field. |
codec |
string | no | The A2DP codec to apply when no claim allocates the Bluetooth speaker. The value must be one of status.bluetooth.codecs. A claim’s codec parameter takes precedence while the claim allocates the speaker. A change here waits until the claim ends because switching codecs replaces the speaker’s node and interrupts playback. The operator ignores this field on an ALSA endpoint. |
spec.volume
The endpoint’s volume, in percent of unity. level is the default level that the operator applies. max and step bound the volume asks the media operator writes into status.session, and the operator does not read them.
| Field | Type | Required | Description |
|---|---|---|---|
level |
integer | no | The endpoint’s default level, as a percent of unity, applied to every channel alike. On an ALSA endpoint it is the gain PipeWire applies in software. On a Bluetooth speaker it is the speaker’s own volume, sent over AVRCP when the speaker supports absolute volume, and a software gain when it does not. The operator applies it when it changes and when the endpoint appears, under a claim or not, and a claim holder’s own stream fader is a separate level above it. A level that changes after that, at the device or by a volume ask, stays, and status.observed.volume reports it. When it is absent, a node that PipeWire builds while the operator runs starts at unity. |
max |
integer | no | The highest level a volume ask can set. The media operator holds its asks at or below it. A person at the device can still set a higher level. Default: 100. |
step |
integer | no | How far one press of a remote’s volume key moves the level the media operator asks for. Default: 5. |
status
What the hardware declares and what the operator last read. The operator owns every field here apart from session, which the media operator owns.
| Field | Type | Required | Description |
|---|---|---|---|
session |
object | no | The unit that uses the Sink, and the last volume ask a press made. The media operator writes this block by server-side apply under its own field manager. The operator writes its own status fields as a merge patch that never names this block, so its writes leave the block in place. It is status and not spec because no person declares it, and a status write changes no metadata.generation. |
node |
string | no | The machine that holds the endpoint now. For a Bluetooth speaker, the value changes when the speaker moves. The name of every other Sink starts with this machine’s name, so a card that moves to another machine gets a new Sink. The operator on each machine lists and watches the Sinks by this field. |
location |
string | no | Where the card is on the machine, in the kernel’s spelling: a PCI address such as 0000:00:1f.3, or a USB port path such as 1-6. Absent on a Bluetooth speaker. |
connectionType |
string | no | How sound leaves the machine. One of: analog, hdmi, displayport, usb, bluetooth. |
card |
object | no | The ALSA card the endpoint is on. The number and the id are this boot’s, and a second card can change both, so nothing durable is keyed to them. |
pcm |
object | no | The PCM device the endpoint plays through. |
monitor |
object | no | The monitor an HDMI or DisplayPort slot feeds, from the ELD the graphics driver wrote into the card. Absent while no monitor answers, and absent on every other connection type. An Intel HDMI codec binds a pin to the first free slot when a monitor appears, so a card with two monitors can swap which slot feeds which between plug events, and this object is where that shows. |
bluetooth |
object | no | The speaker behind a Bluetooth endpoint. Absent on every other connection type. |
nodeName |
string | no | The PipeWire node a consumer’s streams target, the same value a prepared claim delivers as PIPEWIRE_NODE. Absent while PipeWire holds no node for the endpoint. |
format |
object | no | The format the node runs at, from PipeWire’s own Format parameter. Absent while the node is not running. |
capabilities |
map[string]object | no | The card’s own controls for this endpoint, keyed by the kernel’s control name. A Playback control applies to the card’s analog and USB sinks. A control with no direction, such as Auto-Mute Mode, also applies to those sinks. An IEC958 Playback Switch applies to the HDMI slot with the same ordinal. It is the only control an HDMI slot lists because an HDMI PCM has no volume element. The operator omits read-only jack controls because they feed the Connected condition. A Bluetooth speaker lists no card controls. |
layout |
[]string | no | The channel positions the operator declares the sink’s node with, in PCM slot order. Absent when layoutSource is ChannelMap, because PipeWire reads the positions from the device, and absent when it is None. While LayoutApplied is False with the reason Restarting, this is the layout PipeWire loads when its container starts again. |
layoutSource |
string | no | Where the layout came from. Spec is spec.layout. ELD is the monitor’s speaker allocation, capped by the largest LPCM channel count it accepts. ChannelMap is the channel map a USB device describes. None is no positions, and a multichannel stream then plays in stereo. An HDMI sink keeps a layout from the ELD while its monitor is off. Absent on a Bluetooth speaker. One of: Spec, ELD, ChannelMap, None. |
observed |
object | no | The last value the operator read for each setting. The operator reads the card’s control device for every event it receives. It reads PipeWire’s graph for every change PipeWire reports. A change from a physical knob or a client therefore appears here without polling. |
claim |
object | no | The claim that currently allocates the endpoint. This field is absent when no claim allocates it. It identifies the workload that has the speakers. |
conditions |
[]object | no | Connected reports whether the endpoint can play now. It is true for a monitor on an HDMI slot, a plug in an analog jack, a connected speaker, and every USB endpoint. Ready reports whether PipeWire has a node for the endpoint. These two conditions expose the same facts as the device’s no-monitor and no-sink taints, in a form a person can read. LayoutApplied, on a sink of a sound card, reports whether PipeWire runs the sink with the layout the operator selected. It is False with the reason AwaitingIdle while a new layout waits for every stream on the machine to end, and with the reason Restarting while PipeWire restarts in its container to load it. |
status.session
The unit that uses the Sink, and the last volume ask a press made. The media operator writes this block by server-side apply under its own field manager. The operator writes its own status fields as a merge patch that never names this block, so its writes leave the block in place. It is status and not spec because no person declares it, and a status write changes no metadata.generation.
| Field | Type | Required | Description |
|---|---|---|---|
player |
string | no | The Player whose unit uses the Sink, as namespace/name. |
volumeAsk |
object | no | The last level a press asked for. The operator applies each new ask once, to the node or to a Bluetooth speaker’s Route, the same write that spec.volume.level takes, without waiting for the settle window that gathers hardware events into one ResourceSlice write. When several asks arrive before the operator applies one, it applies only the newest. It applies no ask that it finds the first time it reads the Sink, as in its first pass after a start, and no ask for an endpoint that has no node. It never writes an ask’s level again, so a later press of a speaker’s own button stays, and status.observed reports the level the endpoint holds. |
status.session.volumeAsk
The last level a press asked for. The operator applies each new ask once, to the node or to a Bluetooth speaker’s Route, the same write that spec.volume.level takes, without waiting for the settle window that gathers hardware events into one ResourceSlice write. When several asks arrive before the operator applies one, it applies only the newest. It applies no ask that it finds the first time it reads the Sink, as in its first pass after a start, and no ask for an endpoint that has no node. It never writes an ask’s level again, so a later press of a speaker’s own button stays, and status.observed reports the level the endpoint holds.
| Field | Type | Required | Description |
|---|---|---|---|
level |
integer | yes | The level, as a percent of unity. |
mute |
boolean | no | Whether the endpoint is silent. Absent means not muted. |
at |
string | yes | When the press made the ask, with milliseconds. Each new time is one ask. |
status.card
The ALSA card the endpoint is on. The number and the id are this boot’s, and a second card can change both, so nothing durable is keyed to them.
| Field | Type | Required | Description |
|---|---|---|---|
number |
integer | no | The card number the kernel assigned this boot. |
id |
string | no | The card’s short id, such as PCH, with the suffix the kernel appends on a clash, such as PCH_1. |
driver |
string | no | The kernel driver that binds the card, such as HDA-Intel. |
name |
string | no | The card’s name, as the driver states it, such as HDA Intel PCH. |
status.pcm
The PCM device the endpoint plays through.
| Field | Type | Required | Description |
|---|---|---|---|
device |
integer | no | The PCM device number on the card, this boot. |
id |
string | no | The driver’s name for the PCM, such as HDMI 0 or USB Audio. It is the part of the endpoint’s name that outlives the number. |
status.monitor
The monitor an HDMI or DisplayPort slot feeds, from the ELD the graphics driver wrote into the card. Absent while no monitor answers, and absent on every other connection type. An Intel HDMI codec binds a pin to the first free slot when a monitor appears, so a card with two monitors can swap which slot feeds which between plug events, and this object is where that shows.
| Field | Type | Required | Description |
|---|---|---|---|
display |
string | no | The name of the Display the display operator publishes for the same monitor, which is the pairing identity monitor.liken.sh/id. |
manufacturer |
string | no | The monitor’s three-letter PNP id, such as GSM. |
product |
string | no | The monitor’s product code, four lowercase hexadecimal digits. |
name |
string | no | The monitor’s name, from the same EDID descriptor the Display reports as model. |
status.bluetooth
The speaker behind a Bluetooth endpoint. Absent on every other connection type.
| Field | Type | Required | Description |
|---|---|---|---|
address |
string | no | The speaker’s address, uppercase with colons. |
name |
string | no | The name the speaker reports for itself. |
peripheral |
string | no | The name of the Peripheral the bluetooth operator publishes for this speaker, which is the address in lowercase with dashes. |
codec |
string | no | The A2DP codec the transport negotiated, present while the speaker is connected. |
codecs |
[]string | no | Every codec the speaker and this image both support, the one playing first. |
status.format
The format the node runs at, from PipeWire’s own Format parameter. Absent while the node is not running.
| Field | Type | Required | Description |
|---|---|---|---|
rate |
integer | no | The sample rate in hertz. |
channels |
integer | no | The channel count. |
positions |
[]string | no | The channel positions in order, in PipeWire’s names: FL, FR, FC, LFE, RL, RR. |
status.capabilities.*
The card’s own controls for this endpoint, keyed by the kernel’s control name. A Playback control applies to the card’s analog and USB sinks. A control with no direction, such as Auto-Mute Mode, also applies to those sinks. An IEC958 Playback Switch applies to the HDMI slot with the same ordinal. It is the only control an HDMI slot lists because an HDMI PCM has no volume element. The operator omits read-only jack controls because they feed the Connected condition. A Bluetooth speaker lists no card controls.
| Field | Type | Required | Description |
|---|---|---|---|
type |
string | no | What the control takes. One of: integer, boolean, enumerated. |
min |
integer | no | The smallest number an integer control accepts. |
max |
integer | no | The largest number an integer control accepts. |
step |
integer | no | The step between numbers an integer control accepts, absent when every number in the range is accepted. |
minDecibels |
string | no | The level at min, in decibels, when the control declares one, as a decimal string such as -65.25. The string form keeps the value exact where a float would not. |
maxDecibels |
string | no | The level at max, in decibels, when the control declares one. |
values |
[]string | no | Every value an enumerated control accepts. |
channels |
integer | no | How many channels the control carries. A write from spec sets every channel to the same value. |
status.observed
The last value the operator read for each setting. The operator reads the card’s control device for every event it receives. It reads PipeWire’s graph for every change PipeWire reports. A change from a physical knob or a client therefore appears here without polling.
| Field | Type | Required | Description |
|---|---|---|---|
volume |
integer | no | The level the endpoint plays at, as a percent of unity, from the node’s gain or the Bluetooth device’s own volume. A suspended node reports no current level of its own: PipeWire applies a write to it without announcing it, and the node prints no level or the level it last ran at. So a suspended endpoint reports the level the operator last wrote to it, from the spec or a volume ask, which is the level it will run at. With no such write since the node last ran, it reports what the node prints. |
mute |
boolean | no | Whether the endpoint is silent, on the same terms as volume. |
codec |
string | no | The codec a Bluetooth speaker plays with now. |
controls |
map[string]string | no | The value of every control in capabilities, in the same spelling spec.controls takes. A control with several channels reports the first channel’s value. |
status.claim
The claim that currently allocates the endpoint. This field is absent when no claim allocates it. It identifies the workload that has the speakers.
| Field | Type | Required | Description |
|---|---|---|---|
namespace |
string | no | |
name |
string | no |
status.conditions[]
Connected reports whether the endpoint can play now. It is true for a monitor on an HDMI slot, a plug in an analog jack, a connected speaker, and every USB endpoint. Ready reports whether PipeWire has a node for the endpoint. These two conditions expose the same facts as the device’s no-monitor and no-sink taints, in a form a person can read. LayoutApplied, on a sink of a sound card, reports whether PipeWire runs the sink with the layout the operator selected. It is False with the reason AwaitingIdle while a new layout waits for every stream on the machine to end, and with the reason Restarting while PipeWire restarts in its container to load it.
| Field | Type | Required | Description |
|---|---|---|---|
type |
string | yes | |
status |
string | yes | One of: True, False, Unknown. |
reason |
string | yes | |
message |
string | no | |
lastTransitionTime |
string | yes |
The name
The name is built from the hardware’s own identity, so it survives a reboot and a second card:
| Endpoint | Form | Example |
|---|---|---|
| onboard PCI card | node, PCI address, PCM id | node-1-pci-0000-00-1f-3-hdmi-0 |
| USB card with a serial | node, vendor, product, serial, PCM id | node-1-usb-0573-1573-a34004801402-usb-audio |
| USB card with a serial, past 63 characters | node, vendor, product, serial hash, PCM id | studio-screen-12-usb-046d-0a44-5fe3de05-usb-audio |
| USB card with no serial | node, USB port path, PCM id | node-1-usb-1-6-usb-audio |
| Bluetooth speaker | address | 7c-66-ef-01-23-45 |
The PCM id is the driver’s name for the endpoint, HDMI 0 or
USB Audio, lowercased with dashes. Every ALSA form starts with the
node, because a USB serial is not unique across machines: dongles of
one model can all report the same serial. The serial tells apart two
identical dongles on one machine. A card that moves to another
machine becomes a new Sink, and so does a card with no serial that
moves to another port. The old Sink stays, with its spec, and
the operator on the old machine sets its Connected condition to
False. Delete it when you no longer need its declaration. A card that plays and records through one PCM
gives its Source the same name with -capture on the end.
A name is a DNS label, so it holds at most 63 characters. A USB
serial is often 20 characters or more, so on a machine with a longer
name the serial form can pass that. Then the name holds the first
eight hex digits of the serial’s SHA-256 in place of the serial, and
keeps the rest. The hash is stable and differs for each serial, so
two identical dongles on one machine still get two names. The
operator tests each name alone, and -capture adds eight
characters. So a dongle whose Sink name is 56 to 63 characters
keeps the serial in the Sink name and holds the hash in the
Source name. To compute the hash by hand:
printf %s ABCDEF0123456789ABCDEF0 | sha256sum | cut -c1-8
The operator refuses any other name that passes 63 characters, and its log names the endpoint and the length.
On an Intel HDMI codec, hdmi-0 names the card’s first HDMI slot
and not a physical port. A pin binds to the first free slot when a
monitor appears, so on a card with two monitors the slot each one
lands in can change between plug events. status.monitor reports
which monitor the slot feeds now, and a machine with one HDMI
monitor never sees the difference.
How the operator applies the spec
The operator writes a declared volume.level and mute when the
declaration changes and when the endpoint appears: a speaker that
reconnects, or a node that PipeWire builds again. At every other
time it follows the device. A press of a speaker’s own button, a
client that changes the graph, and a volume ask move the level, and
the operator reports the new level in status.observed and does not
write the declaration back. A declared control and a declared codec
are standing instructions: the operator compares each one with the
value it last read, and writes the hardware only where the two
diverge. A declared control is
validated against status.capabilities: a name the card does not
declare, or a value out of its range, fails the pass with the reason
in the operator’s log and is never written. An empty spec writes
nothing at all. The operator invents no value: an endpoint with no
declarations keeps whatever the hardware holds, except that every
sink starts at unity gain so that no hidden multiplier costs
resolution before the codec runs. The unity write goes only to a
node PipeWire builds while the operator runs. After a restart, the
operator writes nothing to a sink that was there before it started,
and the sink keeps the level it holds.
A restart writes no declared level either. The level an endpoint holds when the operator starts can be a volume ask or a press of the speaker’s button that the declaration does not know, and an idle node reports no level, so the operator cannot read whether it already holds the declaration. The first pass treats the declaration as the level each endpoint holds, and a later change of the declaration is written at once.
volume.max and volume.step bound the volume asks below, and the
operator writes neither to the hardware. Each one has a default, 100
and 5 percent, which the API server fills in when spec.volume is
present.
volume.level, mute, and controls apply at once, whether a claim
holds the endpoint or not. codec waits for the claim to end,
because a codec switch replaces the speaker’s node and interrupts
playback, and a claim’s own codec parameter wins while it holds
the speaker.
The volume asks
A remote’s volume key reaches a Sink through the media operator.
It turns each press into an absolute level, at most volume.max,
and writes it into status.session.volumeAsk with the time of the
press. It writes that block by server-side apply under its own field
manager, and this operator writes the rest of status as a merge
patch that never names it, so neither writer removes the other’s
fields.
status:
session:
player: media/den
volumeAsk:
level: 45
mute: false
at: "2026-10-04T12:15:25.164Z"
Each new at is one ask, and the operator applies it once, with the
same write that volume.level takes: the node’s gain, or a
Bluetooth speaker’s own volume over AVRCP. The ask does not wait for
the 1.5 second settle window that gathers a burst of hardware events
into one ResourceSlice write, because a level write changes no
ResourceSlice. When several asks arrive before the operator applies
one, it applies only the newest. When the write lands, the operator
writes the asked level and mute into status.observed at once, and
the next pass replaces them with what PipeWire reports. It applies no ask that it finds the
first time it reads the Sink, as in its first pass after a start,
because the last operator applied that ask, or the device’s level is
newer than it. An ask for an endpoint with no node is dropped, and
the endpoint takes volume.level when it appears.
Observation
status.observed follows two event sources and no timer. The
card’s control device reports every control write from any process,
every jack change, every monitor change, and a knob turned on a USB
DAC. PipeWire’s graph reports every node and device change. So a
change a person made with a knob, a remote, or a speaker’s own
buttons shows in observed within about a second. A declared
control or codec is written back on the same event, and a declared
level is not.
The channel layout
The operator declares every sink of a sound card to PipeWire with a
channel layout: the position of each PCM slot, in PipeWire’s channel
names. WirePlumber links each channel of a stream to the sink’s
channel of the same name. It links every stream to a sink with no
positions as two channels, FL and FR, so a 5.1 or 7.1 stream is
mixed down into them.
The operator takes the layout from the first source that gives one,
and status.layoutSource names it:
| Source | Where the positions come from |
|---|---|
Spec |
spec.layout |
ELD |
the HDMI or DisplayPort monitor’s speaker allocation, capped by the largest LPCM channel count it accepts |
ChannelMap |
the channel map a USB device describes in its descriptors. PipeWire reads it when it opens the device, so status.layout is absent |
None |
nothing. The analog jack reports no speakers, and neither does an HDMI output whose monitor was off when the pod started |
From the ELD, the operator selects one of the HDMI layouts that PipeWire’s own card profiles use:
| The monitor advertises | status.layout |
|---|---|
8-channel LPCM and FL/FR, LFE, FC, RL/RR, RLC/RRC |
FL, FR, RL, RR, FC, LFE, SL, SR |
6-channel LPCM and FL/FR, LFE, FC, RL/RR |
FL, FR, RL, RR, FC, LFE |
| anything else | FL, FR |
Most televisions accept 8-channel LPCM and have two speakers. Such a
set gets FL, FR, so PipeWire mixes the center channel, which
carries the dialog, into the front pair. An HDMI sink keeps its
layout from the ELD while its monitor is off, so a receiver that
turns off and on again changes nothing.
PipeWire reads the layout once, when it starts. When a sink’s layout
changes, because spec.layout changed or a monitor with another
layout answers, the operator writes the new declaration, and the
PipeWire container’s first process restarts PipeWire in place, so the
restart never waits in the kubelet’s crash backoff. The restart ends every
stream on the machine, so the operator waits until no stream plays.
LayoutApplied is False with the reason AwaitingIdle while it
waits, and with the reason Restarting until the new PipeWire
starts. Each change posts one LayoutChanged Event on the Sink,
which names the old layout, the new one, and the source.
Two things the operator does not do:
- It does not write the kernel’s channel map. On HDMI the kernel
routes each slot by its standard allocation for the channel count,
so a height position such as
TFLinspec.layoutnames a slot that the kernel sends to another speaker. The kernel can route front heights (CEA allocation 0x2f), but only when a program writes the PCM’s channel map while the device is open and stopped. - It does not pass a bitstream through. A receiver that plays height speakers from Dolby Atmos or DTS:X needs the compressed stream, and the operator sends PCM. Passthrough is a separate design.
Events
The operator posts a Kubernetes Event on a Sink for each change
of a condition and for each action it takes. A Sink is
cluster-scoped, so its Events are in the default namespace.
kubectl describe sink shows them. kubectl events --for shows them
only with -n default or -A:
kubectl events -n default --for sink/<name>
The API server deletes an Event one hour after its last write, so
the conditions and the operator’s log hold the facts for longer. The
operator patches the count of an Event that repeats within 10
minutes, in place of a new Event.
Each condition change posts one Event with the condition’s own
reason and message, such as NoMonitor, JackEmpty, or
AwaitingIdle. The first status write posts one for each condition.
A change of Ready to False is a Warning while Connected is
True, because sound can leave the endpoint and PipeWire holds no
node to send it through. Every other condition change is Normal: a
television that turns off and a plug pulled from a jack are things a
person does.
The operator posts these reasons for the actions and faults that change no condition:
| Reason | Type | When |
|---|---|---|
LayoutChanged |
Normal |
The operator wrote a new channel layout, and PipeWire restarts in its container to apply it. |
LayoutWriteFailed |
Warning |
The operator could not write the declaration that holds a new layout. The sink keeps its layout, and each pass tries the write again. |
SpecRefused |
Warning |
The spec states a value the endpoint does not take, such as a codec the speaker does not offer. The message names each refused value. |
PipeWireLost |
Warning |
A read of PipeWire’s graph failed. After 3 failed reads in a row, the operator taints every output and restarts. |
PipeWireRecovered |
Normal |
PipeWire answers a graph read again, after one or more that failed. |
BluetoothUnavailable |
Warning |
On a speaker’s Sink: bluetoothd did not answer a read of the paired speakers. The speaker publishes with a taint until it answers. |
BluetoothAvailable |
Normal |
On a speaker’s Sink: bluetoothd answers again. |
Captured |
Normal |
The capture API returned the audio of the Sink to a caller. The message names the caller and the format. |
A fault posts once when the operator first meets it, not once for each pass that meets it again.