I figured this out and it would have been much faster except that my Denon AVR kept gaslighting me. Denon, you make a fine AVR, but seriously – be far more deterministic when returning the current ‘source’! It’s not useful when it keeps changing!
Okay, first off, a custom “Template” will apparently not work since there is no Media Player Template type (other than an unsupported HACS example).
What works is the “Universal Media Player”. I’ll give two examples and discuss their pros and cons.
First “con” is for the Universal Media Player itself – there is no way to configure it via the UI. And unfortunately, sometimes just reloading the YAML doesn’t reload the player and thus requires rebooting HA itself. No idea why.
Simple Example
- media_player:
- platform: universal
name: Merged Media Players
children:
- media_player.kodi
- media_player.roku
device_class: tv
unique_id: merged_media_players
This is super simple and gets me 90% of the way. Ostensibly, this will automatically switch to whatever media player is currently active and not only have the current state, but also a set of controls and attributes that are specific to the currently active player. Very slick!
Alas, Roku mucks up the waters a bit since it arbitrarily changes its state based on a timeout, not on what you do. For example, if you are watching something on the Roku, then the universal player will be all focused on it. You stop watching something and the Roku moves to the “On” state. You then switch to Kodi, which is in “Idle” state until you actively start playing something. That means that the above universal player will still be focused on Roku while you are trying to browse Kodi. It won’t switch to Kodi until you either start actively playing or Roku times out and it switches to “Idle”.
Honestly, this simple case would likely be fine if my streaming player was anything but a Roku, but since it is a Roku, I needed something a bit more direct.
Guaranteed Example
- media_player:
- platform: universal
name: Theater Media Players
children:
- media_player.kodi
- media_player.roku
device_class: tv
unique_id: theater_media_players
active_child_template: >
{% if is_state_attr('media_player.harmony', 'source', 'Watch Roku') %}
media_player.roku
{% elif is_state_attr('media_player.harmony', 'source', 'Watch Kodi') %}
media_player.kodi
{% else %}
media_player.denon_avr_x6200w
{% endif %}
This one works for me 100% of the time since it forces the actually active media player to the forefront based on which player currently has control of the screen. I could even have a Roku actively playing a video while switching to Kodi and this will (properly) start serving up the Kodi state and controls.
This does require having a central control of what is playing. I originally wanted this control to be my Denon AVR, but it’s ‘source’ attribute was never the same each time I tried so sometimes it would work and sometimes it would just be “unknown”. The Harmony source is at least consistent every time.
Why I’m Doing This
For anybody making it this far… I never said why I wanted the merged or active state. It’s for an automation where I turn on my theater lights to 10% when the current video is paused. Just using the state change as a trigger wasn’t enough, since the Roku would change state a few minutes later and trigger the light to go on. Thus, I needed to check the current state as a condition and not turn on the light if anything is currently playing. The above “Guaranteed Example” does exactly what I need.