Skip to content

fix(playback): fix built-in speaker detection and bypass capabilities…#540

Open
mattsigal wants to merge 1 commit into
Moonfin-Client:mainfrom
mattsigal:bugfix/audio-routing-avr-override
Open

fix(playback): fix built-in speaker detection and bypass capabilities…#540
mattsigal wants to merge 1 commit into
Moonfin-Client:mainfrom
mattsigal:bugfix/audio-routing-avr-override

Conversation

@mattsigal

@mattsigal mattsigal commented Jun 15, 2026

Copy link
Copy Markdown
Contributor

Pull Request

Summary

This PR fixes the issue where built-in TV speakers are misdetected as HDMI receivers (ROUTE_HDMI), and when the user manually overrides "Audio Output" to "AV receiver (Atmos / DTS:X)", the app still downmixes to stereo. It updates the native audio routing logic to correctly detect TV speakers and shifts the capability-gating logic to the Dart side so that manual preference overrides can bypass route restrictions.

On a Smart TV panel (e.g., Sony Bravia, TCL, Hisense running Android TV) using its built-in speakers the Android OS reports both AudioDeviceInfo.TYPE_BUILTIN_SPEAKER and AudioDeviceInfo.TYPE_HDMI (the HDMI inputs on the back of the TV panel). Before this PR, because TYPE_HDMI was checked first in resolveRouteType, the TV resolved to ROUTE_HDMI (thinking an external AVR was connected). As a result, the TV speakers were incorrectly treated as a surround receiver, and the app attempted to bitstream lossless formats like TrueHD and DTS-HD. Because TV speakers cannot decode or handle lossless passthrough, the user got complete silence or playback hangs.

With this PR, isExternalBox returns false on a TV panel, causing it to correctly fall back to ROUTE_SPEAKER (TV Speakers), restricting the output to stereo PCM and forcing the server to transcode TrueHD/DTS-HD.

Related Issues

  • TV built-in speakers detected as ROUTE_HDMI instead of ROUTE_SPEAKER (limiting channels to 2 and disabling TrueHD/DTS-HD).
  • Manual override to "AV receiver (Atmos / DTS:X)" still downmixing to stereo or failing to pass through HD audio.
  • Discord user issue using TV speakesr
  • Closes #
  • Fixes #
  • Related to #

Type of Change

  • Bug fix
  • New feature
  • Refactor
  • Performance improvement
  • UI/UX update
  • Documentation update
  • Build/CI change
  • Other (describe):

Changes Made

Android Native (android/app) AudioCapabilities.kt :

  • Removed native route-based capability clearing block (TrueHD/DTS-HD/Atmos).
  • Added isExternalBox() check using Build.BRAND, Build.MANUFACTURER, and Build.MODEL to skip identifying dummy speakers on external TV boxes (Shield, Chromecast, Fire TV, Mi Box, Onn).
  • Updated resolveRouteType to prioritize bluetooth, wired/USB headsets, ARC/eARC, built-in speakers (on non-external panels), HDMI/LINE_DIGITAL, and then built-in speakers as a fallback.

Flutter/Dart Client (lib) audio_capability_profile.dart:

  • Shifted ARC/speaker capability gating logic from native code to Dart side in AudioCapabilityProfile.fromMap.
  • Accept AudioOutputMode in fromMap. If AudioOutputMode.avrPassthrough is active, override the route type to AudioRouteType.hdmi (if not already earc), and force maxPcmChannels to at least 8, bypassing speaker route restrictions and preserving detected receiver pass-through capabilities.

user_preferences.dart:

  • Updated detectedAudioCapabilities to resolve and pass the current AudioOutputMode to AudioCapabilityProfile.fromMap.

settings_side_panel.dart:

  • Updated settings screen's _audioCapabilityProfile helper to pass the resolved AudioOutputMode.

Player Backends & Playback Module:
Refactored media3_player_backend.dart, media_kit_player_backend.dart, appletv_mpv_backend.dart, html_video_backend_profile.dart, and playback_module.dart to query the consolidated detectedAudioCapabilities from preferences, removing redundant snapshot parses and unused imports.

Platform

  • Android
  • iOS
  • macOS
  • Windows
  • Linux
  • All / Shared code

Testing

Describe how this change was tested.

  • Tested on emulator / simulator
  • Tested on physical device
  • Manual testing completed
  • Not tested (explain why):

Test Steps

  1. Deploy to Shield TV. On "Auto", verify routing resolves to ROUTE_HDMI (showing "HDMI • 8ch PCM" or passthrough formats).
  2. Deploy to a TV with built-in speakers. On "Auto", verify routing resolves to ROUTE_SPEAKER (limiting PCM channels to 2 and hiding TrueHD/DTS-HD options).
  3. Toggle "Audio Output" to "AV receiver (Atmos / DTS:X)" on the TV. Verify capabilities override to HDMI / 8 PCM channels and expose passthrough capabilities.

Screenshots (if applicable)

AVR ON:
Shield_Screenshot_2026-06-14_22-33-50

AVR OFF:
Shield_Screenshot_2026-06-14_22-35-36

Checklist

  • Code builds successfully
  • Code follows project style and conventions
  • No unnecessary commented-out code
  • No new warnings introduced

… gating on manual AVR override

- Update native route type resolution to identify built-in speakers for Smart TV panels and fall back to HDMI only on external streaming boxes.
- Relocate audio capabilities routing/gating checks from native code to Dart side in `AudioCapabilityProfile.fromMap`.
- Ensure manual AVR override (AV receiver preset) bypasses capability gating, setting the route type to HDMI and unlocking up to 8 PCM channels and HD audio pass-throughs (TrueHD, DTS-HD, etc.).
- Refactor player backends and playback module to read consolidated audio capabilities from user preferences.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant