https://bugs.kde.org/show_bug.cgi?id=523726

            Bug ID: 523726
           Summary: inputhandler: CEC volume commands never reach an AV
                    receiver (soundbar), silently sent to the TV instead
    Classification: Plasma
           Product: Plasma Bigscreen
      Version First unspecified
       Reported In:
          Platform: Fedora RPMs
                OS: Linux
            Status: REPORTED
          Severity: normal
          Priority: NOR
         Component: Input Handler
          Assignee: [email protected]
          Reporter: [email protected]
                CC: [email protected]
  Target Milestone: ---

PRE-AMBLE
I investigated this using Claude/AI to help me work out what was going on. I've
tried to check through the technical detail of what is being reported below,
but I don't understand all the source/cec code references fully. 

I asked Claude to check everything it was writing for this bug report against
my actual setup in practice -- so for at least my fairly general case of 'TV
plugged in to a PC via HDMI, with soundbar plugged into HDMI-ARC on the TV",
this report should be true.

DESCRIPTION
[AI written] The CEC audio-system D-Bus methods added in commit bd4b6cd9
("inputhandler: expose CEC audio-system control over D-Bus") do not work on any
setup where audio is handled by an AV receiver / soundbar rather than the TV
itself. Volume commands are silently delivered to the TV and have no effect.

STEPS TO REPRODUCE
1. HDMI chain with a CEC audio system present (here: Samsung soundbar on the
TV's ARC port, logical address 5, physical address 1.0.0.0).
2. Let plasma-bigscreen-inputhandler start normally and open the CEC adapter.
3. Call sendVolumeUp over D-Bus:
`busctl --user call org.kde.plasma.bigscreen.inputhandler /InputHandler
org.kde.plasma.bigscreen.inputhandler sendVolumeUp`

OBSERVED RESULT
Nothing happens. The soundbar volume does not change. The CEC frame emitted is
addressed to the TV, not the audio system:
    << 10:44:41     (from us -> LA 0 = TV, User Control Pressed, Volume Up)

EXPECTED RESULT
he frame should be addressed to the audio system:
    << 15:44:41     (from us -> LA 5 = audio system)

SOFTWARE/OS VERSIONS
OS: Fedora 44
plasma-bigscreen: master (git), tested at 16edd5e3 with a local build
libCEC: 7.1.1
Adapter: Pulse-Eight USB-CEC Adapter v7
Audio system: Samsung soundbar, LA 5, PA 1.0.0.0
KDE Plasma: 6.7.3
KDE Frameworks: 6.28.0
Qt: 6.11.1
Kernel: 7.1.5-201.fc44.x86_64
Graphics platform: Wayland

ADDITIONAL INFORMATION
I requested Claude write up both a "root cause" analysis and suggested fix for
general users (applicable to all systems and not just mine).

I suspect that Claude is putting a little too much weight into the scenario
where an amp goes to sleep while plasma-bigscreen is running, and is later
turned back on by the user -- the fix in this case may be simpler than doing
the 'scan' behavior before every command. You may know a better suggestion.

[AI]: ROOT CAUSE
CECWorker::sendVolumeUp() calls ICECAdapter::VolumeUp(), which reaches
CCECClient::SendVolumeUp() in libCEC:

```
    CCECAudioSystem* audio(m_processor->GetAudioSystem());
    if (!audio || !audio->IsPresent())
    {
      CCECTV* tv(m_processor->GetTV());
      tv->TransmitVolumeUp(primary, bSendRelease);   // silent fallback
      return (uint8_t)CEC_AUDIO_VOLUME_STATUS_UNKNOWN;
    }
    else
      return audio->VolumeUp(primary, bSendRelease);
```

audio->IsPresent() is only true once libCEC has handshaked with logical address
5. CECWorker::initialize() never polls the audio system, and nothing else in
the daemon does either, so IsPresent() is false and every volume
command takes the TV fallback.
Confirmed by reproducing the fault and the fix with cec-client using the same
configuration the daemon uses (recording device, autodetected physical
address):
    no poll first        -> << 10:44:41   (TV)
    after "poll 5"       -> << 15:44:41   (audio system)  <-- works
    after "pow 5"        -> << 15:44:41   (audio system)  <-- works
    after "scan"         -> << 15:44:41   (audio system)  <-- works

A single targeted poll of CECDEVICE_AUDIOSYSTEM is sufficient; a full scan is
not required.

[AI]: SUGGESTED FIX
Poll the audio system before audio operations, e.g. in CECWorker::sendVolumeUp
/ sendVolumeDown / sendMuteToggle:

```
    m_cecAdapter->PollDevice(CECDEVICE_AUDIOSYSTEM);
    return static_cast<int>(m_cecAdapter->VolumeUp(true));
```

This must happen per-command, not once at init. AV receivers commonly power
themselves down after an idle timeout (10-15 minutes on this hardware), after
which the registration goes stale and the fault returns. A poll is a single
ACKed message, so the cost is negligible.

[ My commentary here is that there may be a better way to 'see' with cecAdapter
control that a device has joined, and use it more appropriately than doing the
poll every time. Just an idea. ]

FINAL NOTE ON ERROR FINDING
[AI]: sendVolumeUp returns CEC_AUDIO_VOLUME_STATUS_UNKNOWN (0x7F / 127) in the
failing case. 

My soundbar does not implement Report Audio Status, so 0x7F is also returned on
success. Claude says this is 'very common amongst receivers and soundbars", so
at the start there was no way to distinguish "sent to the audio system" from
"silently sent to the TV". Is there a way your CEC code can return a distinct
error, or in some other way expose whether or not the audio system was
found/resolved?

-- 
You are receiving this mail because:
You are watching all bug changes.

Reply via email to