Skip to content

Instantly share code, notes, and snippets.

@jazzyisj
Last active March 31, 2025 17:38
Show Gist options
  • Save jazzyisj/c53c92779785bb5d9952adf3a3a28107 to your computer and use it in GitHub Desktop.
Save jazzyisj/c53c92779785bb5d9952adf3a3a28107 to your computer and use it in GitHub Desktop.
Music Assistant Play Media Package
##################################################################################################################
# Music Assistant Play Media Package - Launch Music Assistant Library Media from HASS dashboard & automations
# Use with Play Music Assistant Media lovelace card - https://gist.github.com/jazzyisj/f90bf1c1c3205d5d2d791f196fc144b1
# Download this package file to your packages folder or add yaml to your configuration.yaml file.
# Change to one of your Music Assistant media player entity_id's where indicated with #TODO tag.
##################################################################################################################
input_boolean:
mass_shuffle:
name: "Shuffle"
icon: mdi:shuffle
mass_radio:
name: "Radio Mode"
icon: mdi:radio
input_select:
mass_enqueue_mode:
name: "Enqueue Mode"
options:
- play
- replace
- next
- replace_next
- add
mass_media_type:
name: "Media Type"
options:
- Artist
- Album
- Track
- Playlist
- Radio
mass_repeat_mode:
name: &repeat_name "Repeat Mode"
icon: &repeat_icon mdi:repeat
options:
- "Off"
- All
- One
input_text:
mass_media_player:
mass_artist:
mass_album:
mass_track:
mass_playlist:
mass_radio:
mass_artist_filter:
mass_album_filter:
input_number:
mass_volume:
name: "Volume"
icon: mdi:volume-high
unit_of_measurement: "%"
mode: slider
min: 0
max: 100
step: 5
template:
###############################################################################
## Update Media Button - used to force update of media select templates
###############################################################################
- button:
- name: "MASS Update Media"
unique_id: mass_udpate_media
icon: mdi:multimedia
press: []
###############################################################################
## Play Media Button - used to start media play with selected options
###############################################################################
- button:
- name: "MASS Play Media"
unique_id: mass_play_media
icon: mdi:play-box
press:
# get the entity id for the selected media player
- variables:
media_player: >
{{ expand('group.mass_players')
| selectattr('name', 'eq', states('select.mass_media_player'))
| map(attribute='entity_id') | join }}
# shuffle / repeat / enqueue not available in radio mode so don't set them
- if: "{{ is_state('input_boolean.mass_radio','off') }}"
then:
# set shuffle parameter using boolean value
- action: media_player.shuffle_set
target:
entity_id: "{{ media_player }}"
data:
shuffle: "{{ is_state('input_boolean.mass_shuffle', 'on') }}"
continue_on_error: true
# set repeat parameter using boolean value
- action: media_player.repeat_set
target:
entity_id: "{{ media_player }}"
data:
repeat: "{{ states('input_select.mass_repeat_mode') | lower }}"
continue_on_error: true
# set media player volume to zero to try and avoid google power on bloop
# you can delete this service call if you are not using Google Cast media players
- action: media_player.volume_set
target:
entity_id: "{{ media_player }}"
data:
volume_level: 0
continue_on_error: true
# play selected media type and set enqueue mode
- action: music_assistant.play_media
target:
entity_id: "{{ media_player }}"
data:
media_id: "{{ states('select.mass_' ~ states('input_select.mass_media_type') | lower) }}"
media_type: "{{ states('input_select.mass_media_type') | lower }}"
enqueue: "{{ states('input_select.mass_enqueue_mode') | lower }}"
artist: "{{ states('select.mass_artist_filter') }}"
album: "{{ states('select.mass_album_filter') }}"
radio_mode: "{{ is_state('input_boolean.mass_radio', 'on') }}"
continue_on_error: true
# wait for media player to start playing
- wait_template: "{{ is_state(media_player, 'playing') }}"
timeout: 60
# set media player to selected volume, done after mass.play_media
# to avoid google bloops when media players turn on
- action: media_player.volume_set
target:
entity_id: "{{ media_player }}"
data:
volume_level: "{{ states('input_number.mass_volume') | float(-1) / 100 }}"
continue_on_error: true
###############################################################################
## Player
###############################################################################
- trigger:
- trigger: homeassistant
event: start
- trigger: event
event_type: event_template_reloaded
- trigger: state
entity_id: group.mass_players
attribute: entity_id
to:
- trigger: state
entity_id: input_text.mass_media_player
to:
select:
- name: "MASS Media Player"
unique_id: mass_media_player
state: "{{ states('input_text.mass_media_player') }}"
select_option:
- condition: template
value_template: "{{ option not in ['', none] }}"
- action: input_text.set_value
target:
entity_id: input_text.mass_media_player
data:
value: "{{ option }}"
options: >
{{ expand('group.mass_players')
| map(attribute='name') | list | sort }}
##################################################################################################################
## Artist
##################################################################################################################
- trigger:
- trigger: homeassistant
event: start
- trigger: event
event_type: event_template_reloaded
- trigger: state
entity_id:
- input_text.mass_artist
- button.mass_update_media
to:
- trigger: time_pattern
minutes: 30 # sync with library every hour at 30 min after
action:
- action: music_assistant.get_library
data:
#TODO change to any one of your music assistant media player entities
config_entry_id: &mass_id "{{ config_entry_id('media_player.bathroom_speaker_mass') }}"
media_type: artist
favorite: true
limit: 50
offset: 0
order_by: sort_name
album_artists_only: true
response_variable: mass_artists
- variables:
artists: >
{% set artist_list = namespace(names=[]) %}
{% for artist in mass_artists['items'] %}
{% set artist_list.names = artist_list.names + [artist.name] %}
{% endfor %}
{{ artist_list.names | unique | list }}
select:
- name: "MASS Artist"
unique_id: mass_artist
state: "{{ states('input_text.mass_artist') }}"
select_option:
- condition: template
value_template: "{{ option not in ['', none] }}"
- action: input_text.set_value
target:
entity_id: input_text.mass_artist
data:
value: "{{ option }}"
options: "{{ artists }}"
##################################################################################################################
## Album
##################################################################################################################
- trigger:
- trigger: homeassistant
event: start
- trigger: event
event_type: event_template_reloaded
- trigger: state
entity_id:
- input_text.mass_album
- button.mass_update_media
to:
- trigger: time_pattern
minutes: 30 # sync with library every hour at 30 min after
action:
- action: music_assistant.get_library
data:
config_entry_id: *mass_id
media_type: album
favorite: true
limit: 50
offset: 0
order_by: sort_name
album_type:
- single
- album
- compilation
- ep
- unknown
response_variable: mass_albums
- variables:
albums: >
{% set album_list = namespace(names=[]) %}
{% for album in mass_albums['items'] %}
{% set album_list.names = album_list.names + [album.name] %}
{% endfor %}
{{ album_list.names | unique | list }}
select:
- name: "MASS Album"
unique_id: mass_album
state: "{{ states('input_text.mass_album') }}"
select_option:
- condition: template
value_template: "{{ option not in ['', none] }}"
- action: input_text.set_value
target:
entity_id: input_text.mass_album
data:
value: "{{ option }}"
options: "{{ albums }}"
##################################################################################################################
## Track
##################################################################################################################
- trigger:
- trigger: homeassistant
event: start
- trigger: event
event_type: event_template_reloaded
- trigger: state
entity_id:
- input_text.mass_track
- button.mass_update_media
to:
- trigger: time_pattern
minutes: 30 # sync with library every hour at 30 min after
action:
- action: music_assistant.get_library
data:
config_entry_id: *mass_id
media_type: track
favorite: true
limit: 100
response_variable: mass_tracks
- variables:
tracks: >
{% set track_list = namespace(names=[]) %}
{% for track in mass_tracks['items'] %}
{% set track_list.names = track_list.names + [track.name] %}
{% endfor %}
{{ track_list.names | unique | list }}
select:
- name: "MASS Track"
unique_id: mass_track
state: "{{ states('input_text.mass_track') }}"
select_option:
- condition: template
value_template: "{{ option not in ['', none] }}"
- action: input_text.set_value
target:
entity_id: input_text.mass_track
data:
value: "{{ option }}"
options: "{{ tracks }}"
##################################################################################################################
## Playlist
##################################################################################################################
- trigger:
- trigger: homeassistant
event: start
- trigger: event
event_type: event_template_reloaded
- trigger: state
entity_id:
- input_text.mass_playlist
- button.mass_update_media
to:
- trigger: time_pattern
minutes: 30 # sync with library every hour at 30 min after
action:
- action: music_assistant.get_library
data:
config_entry_id: *mass_id
media_type: playlist
favorite: true
limit: 50
offset: 0
order_by: sort_name
response_variable: mass_playlists
- variables:
playlists: >
{% set playlist_list = namespace(names=[]) %}
{% for playlist in mass_playlists['items'] %}
{% set playlist_list.names = playlist_list.names + [playlist.name] %}
{% endfor %}
{{ playlist_list.names | unique | list }}
select:
- name: "MASS Playlist"
unique_id: mass_playlist
state: "{{ states('input_text.mass_playlist') }}"
select_option:
- condition: template
value_template: "{{ option not in ['', none] }}"
- action: input_text.set_value
target:
entity_id: input_text.mass_playlist
data:
value: "{{ option }}"
options: "{{ playlists }}"
##################################################################################################################
## Radio Station
##################################################################################################################
- trigger:
- trigger: homeassistant
event: start
- trigger: event
event_type: event_template_reloaded
- trigger: state
entity_id:
- input_text.mass_radio
- button.mass_update_media
to:
- trigger: time_pattern
minutes: 30 # sync with library every hour at 30 min after
action:
- action: music_assistant.get_library
data:
config_entry_id: *mass_id
media_type: radio
favorite: true
limit: 50
offset: 0
order_by: sort_name
response_variable: mass_radios
- variables:
radios: >
{% set radio_list = namespace(names=[]) %}
{% for radio in mass_radios['items'] %}
{% set radio_list.names = radio_list.names + [radio.name] %}
{% endfor %}
{{ radio_list.names | unique | list }}
select:
- name: "MASS Radio"
unique_id: mass_radio
state: "{{ states('input_text.mass_radio') }}"
select_option:
- condition: template
value_template: "{{ option not in ['', none] }}"
- action: input_text.set_value
target:
entity_id: input_text.mass_radio
data:
value: "{{ option }}"
options: "{{ radios }}"
##################################################################################################################
## Artist Filter
##################################################################################################################
- trigger:
- trigger: homeassistant
event: start
- trigger: event
event_type: event_template_reloaded
- trigger: state
entity_id:
- input_select.mass_media_type
- input_text.mass_artist_filter
- select.mass_track
- select.mass_album
- select.mass_album_filter
- button.mass_update_media
to:
not_from:
- unknown
- unavailable
action:
- action: music_assistant.get_library
data:
config_entry_id: *mass_id
media_type: track
favorite: true
limit: 100
response_variable: mass_tracks
- action: music_assistant.get_library
data:
config_entry_id: *mass_id
media_type: album
favorite: true
limit: 100
response_variable: mass_albums
- variables:
artists: >
{% set artist_list = namespace(names=['']) %}
{% if states('input_select.media_type_play') == 'Track' %}
{% for track in mass_tracks['items'] %}
{% if track.name == states('select.media_track_play')
and states('select.media_album_filter_play')
in ['', 'unknown', track.album.name] %}
{% set artist_list.names = artist_list.names + [track.artists[0].name] %}
{% endif %}
{% endfor %}
{% elif states('input_select.media_type_play') == 'Album' %}
{% for album in mass_albums['items'] %}
{% if album.name == states('select.media_album_play') %}
{% set artist_list.names = artist_list.names + [album.artists[0].name] %}
{% endif %}
{% endfor %}
{% endif %}
{{ artist_list.names | unique | list }}
select:
- name: "MASS Artist Filter"
unique_id: mass_artist_filter
state: "{{ states('input_text.mass_artist_filter') }}"
select_option:
- condition: template
value_template: "{{ option not in ['', none] }}"
- action: input_text.set_value
target:
entity_id: input_text.mass_artist_filter
data:
value: "{{ option }}"
options: "{{ artists }}"
##################################################################################################################
## Album Filter
##################################################################################################################
- trigger:
- trigger: homeassistant
event: start
- trigger: event
event_type: event_template_reloaded
- trigger: state
entity_id:
- input_select.mass_media_type
- input_text.mass_album_filter
- select.mass_track
- select.mass_artist_filter
- button.mass_update_media
to:
not_from:
- unknown
- unavailable
action:
- action: music_assistant.get_library
data:
config_entry_id: *mass_id
media_type: track
favorite: true
limit: 100
response_variable: mass_tracks
- variables:
albums: >
{% set album_list = namespace(names=['']) %}
{% if states('input_select.media_type_play') == 'Track' %}
{% for track in mass_tracks['items'] %}
{% if track.name == states('select.media_track_play')
and states('select.media_artist_filter_play')
in ['', 'unknown', track.artists[0].name] %}
{% set album_list.names = album_list.names + [track.album.name] %}
{% endif %}
{% endfor %}
{% endif %}
{{ album_list.names | unique | list }}
select:
- name: "MASS Album Filter"
unique_id: mass_album_filter
state: "{{ states('input_text.mass_album_filter') }}"
select_option:
- condition: template
value_template: "{{ option not in ['', none] }}"
- action: input_text.set_value
target:
entity_id: input_text.mass_album_filter
data:
value: "{{ option }}"
options: "{{ albums }}"
automation:
##################################################################################################################
## Update Mass Media Player Group
##
## This automation automatically creates a group of all your Music Assistant media players.
## Media players are automatically added and removed from the group if come online or they become unavailable
## and are automatically re-added to the group when them become available again.
##################################################################################################################
- id: update_mass_media_players
alias: "Update Mass Media Players"
description: "Update mass media player group."
mode: single
max_exceeded: silent
triggers:
- trigger: homeassistant
id: start
event: start
- trigger: event
id: group
event_type: call_service
event_data:
domain: group
service: reload
- trigger: state
entity_id: button.mass_update_media
to:
- trigger: template
id: offline
value_template: >
# update player list if a media player becomes unavailable
- trigger: template
id: offline
value_template: >
{{ states.media_player
| selectattr('attributes.mass_player_type', 'defined')
| selectattr('state', 'in', ['unknown', 'unavailable'])
| list | count > 0 }}
for: 15 # ignore temporary state changes, allow all player states to update
# update player list if a media player becomes available
- trigger: template
id: online
value_template: >
{{ states.media_player
| selectattr('attributes.mass_player_type', 'defined')
| selectattr('state', 'in', ['unknown', 'unavailable'])
| list | count == 0 }}
for: 15 # ignore temporary state changes, allow all player states to update
actions:
- if: "{{ trigger.id == 'start' }}"
then: # wait for music assistant to load
- wait_template: >
{{ states.media_player
| selectattr('attributes.mass_player_type', 'defined')
| map(attribute='entity_id') | list
| select('has_value') | list | count > 0 }}
timeout: 300
continue_on_timeout: false
- action: group.set
data:
object_id: mass_players
entities: >
{{ states.media_player
| selectattr('attributes.mass_player_type', 'defined')
| map(attribute='entity_id') | list
| select('has_value') | sort }}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment