Touchy - Touch friendly media player card (combination of cards)

Hi. How can i do to make this card fit in a swiper card? because of the multiple button card entity, it will not work.

Thxs

EDIT: Ok, i managed to do it by setting all the button card inside a picture element

How you make this ? Can you config delen whit me ?

Thank you for sharing !
i would like to test but the link for your overlay svg is dead. Can you post a new link please ?
thanks

I updated the link. Btw: I donā€™t get notifications with new responses, only when mentioned directly.

Thanks you very much !

Hey @ASNNetworks
Love you media card.
I have implemented it in Mattiasā€™s homekits beautiful concept but I get errors. Iā€™m thinking itā€™s styling errors?
The music works though and the cover art is shown.

This is the code:

      - type: grid
        title: Media
        view_layout:
          grid-area: media
        columns: 1
        cards:
          - type: custom:swipe-card
            start_card: 1
            parameters:
              roundLengths: true
              effect: coverflow
              speed: 650
              spaceBetween: 20
              threshold: 7
              coverflowEffect:
                rotate: 80
                depth: 300
            cards:

              - type: horizontal-stack
                cards:
                  - type: picture-elements
                    image: 'local/tablet/overlay.svg'
                    style: |
                      ha-card {
                        --ha-card-background: none !important;
                        box-shadow: none !important;
                      }                          
                    elements:
                      - aspect_ratio: 1/1
                        entity: media_player.lesboutin
                        icon: 'mdi:speaker-wireless'
                        label: Living Room Sonos
                        name: Sonos
                        show_icon: false
                        show_label: false
                        show_last_changed: false
                        show_entity_picture: true
                        show_name: false
                        show_state: false
                        tap_action:
                          action: none
                        style:
                          height: 100%
                          width: 100%
                          top: 50%
                          left: 50%
                        state:
                          - styles:
                              entity_picture:
                                - filter: grayscale(100%) blur(4px)
                                - transition: all 0.5s ease
                            value: paused
                        styles:
                          card:
                            - padding: 0px
                            - background-color: var(--card-background-off) #the color when there is no artwork, change or remove to use own color
                          entity_picture:
                            - border-radius: 20px
                            - height: 100%
                            - width: 100%
                            - position: absolute
                            - transition: all 0.5s ease
                        type: 'custom:button-card'
                      - type: 'custom:mod-card'
                        style:
                          '--mini-media-player-icon-color': var(--text-color) #change or remove to use own color
                          '--mini-media-player-base-color': var(--text-color) #change or remove to use own color
                          '--mini-media-player-accent-color': var(--music-accent-color) #change or remove to use own color
                          border-top-left-radius: 0px !important
                          border-top-right-radius: 0px !important   
                          width: 100%
                          transform: 'translate(0%, -100%'
                        card:
                          artwork: none
                          entity: media_player.lesboutin
                          group: false
                          hide:
                            controls: true
                            icon: false
                            name: false
                            power: true
                            runtime: false
                            source: true
                            volume: true
                          hold_action:
                            action: none
                          tap_action:
                            action: none
                          icon: 'mdi:speaker-wireless'
                          info: scroll
                          source: true
                        # change the styling variable below to the color and width of scrolling info you want. Change height or remove line for default.
                          style: |
                            .mmp-player {          
                              background: rgba(0, 0, 0, 0.75) !important;
                              border-top-left-radius: 0px !important;
                              border-top-right-radius: 0px !important;
                              height: 95px;
                            }      
                            .entity__info {
                              max-width: 60% !important;
                            }                           
                          type: 'custom:mini-media-player'
                        #This here below is if you want to have the option to tap_hold anywhere on the card for more-info popup. Remove this part if not needed.
                      - aspect_ratio: 1.2/1
                        entity: media_player.lesboutin
                        icon: 'mdi:speaker-wireless'
                        label: Living Room Sonos
                        name: Sonos
                        show_icon: false
                        show_label: false
                        show_last_changed: false
                        show_entity_picture: false
                        show_name: false
                        show_state: false
                        tap_action:
                          action: none
                        hold_action:
                          action: more-info
                        style:
                          height: 80%
                          width: 100%
                          top: 40%
                          left: 50%
                        styles:
                          card:
                            - filter: opacity(0%)
                        type: 'custom:button-card'
                      - aspect_ratio: 1/1
                        show_name: false
                        show_icon: true
                        icon: 'mdi:skip-next-circle'
                        type: 'custom:button-card'
                        size: 100%
                        entity: media_player.lesboutin
                        style:
                          right: '-5%'
                          top: 50%
                          height: 25%
                          width: 25%
                        state:
                          - styles:
                              icon:
                                - filter: opacity(100%)
                                - transition: all 0.5s ease
                                - color: '#FFFFFF' #color of button while paused
                            value: paused
                        styles:
                          card:
                            - padding: 0px
                            - border-radius: 50%
                          icon:
                            - filter: opacity(30%)
                            - transition: all 0.5s ease
                            - color: var(--music-accent-color) #color of button while playing
                        tap_action:
                          action: call-service
                          service: media_player.media_next_track
                          service_data:
                            entity_id: media_player.lesboutin
                          haptic: medium
                        hold_action:
                          action: none
                      - aspect_ratio: 1/1
                        show_name: false
                        show_icon: true
                        icon: 'mdi:skip-previous-circle'
                        type: 'custom:button-card'
                        size: 100%
                        entity: media_player.lesboutin
                        style:
                          right: 55%
                          top: 50%
                          height: 25%
                          width: 25%
                        state:
                          - styles:
                              icon:
                                - filter: opacity(100%)
                                - transition: all 0.5s ease
                                - color: '#FFFFFF' #color of button while paused
                            value: paused
                        styles:
                          card:
                            - padding: 0px
                            - border-radius: 50%
                          icon:
                            - filter: opacity(30%)
                            - transition: all 0.5s ease
                            - color: var(--music-accent-color) #color of button while playing
                        tap_action:
                          action: call-service
                          service: media_player.media_previous_track
                          service_data:
                            entity_id: media_player.lesboutin
                          haptic: medium
                        hold_action:
                          action: none
                      - aspect_ratio: 1/1
                        show_name: false
                        show_icon: true
                        icon: 'mdi:pause-circle'
                        type: 'custom:button-card'
                        size: 100%
                        entity: media_player.lesboutin
                        style:
                          right: 10%
                          top: 50%
                          height: 40%
                          width: 40%
                        state:
                          - styles:
                              icon:
                                - filter: opacity(100%)
                                - transition: all 0.5s ease
                                - color: '#FFFFFF' #color of button while paused
                            value: paused
                            icon: 'mdi:play-circle'
                        styles:
                          card:
                            - padding: 0px
                            - border-radius: 50%
                          icon:
                            - filter: opacity(30%)
                            - transition: all 0.5s ease
                            - color: var(--music-accent-color) #color of button while playing
                        tap_action:
                          action: call-service
                          service: media_player.media_play_pause
                          service_data:
                            entity_id: media_player.lesboutin
                          haptic: medium
                        hold_action:
                          action: none
                      - aspect_ratio: 1/1
                        show_name: false
                        show_icon: true
                        icon: 'mdi:heart-plus'
                        type: 'custom:button-card'
                        size: 90%
                        style:
                          right: 10%
                          top: 88%
                          height: 5%
                          width: 5%
                        styles:
                          card:
                            - padding: 0px
                            - border-radius: 50%
                          icon:
                            - color: var(--text-color)
                        tap_action:
                          action: call-service
                          service: script.add_to_playlist_sonos
                          haptic: medium
                        hold_action:
                          action: none
                      - aspect_ratio: 1/1
                        show_name: false
                        show_icon: true
                        icon: 'mdi:power-standby'
                        type: 'custom:button-card'
                        size: 90%
                        style:
                          right: 2%
                          top: 88%
                          height: 5%
                          width: 5%
                        styles:
                          card:
                            - padding: 0px
                            - border-radius: 50%
                          icon:
                            - color: var(--text-color)
                        tap_action:
                          action: call-service
                          service: media_player.turn_off
                          service_data:
                            entity_id: media_player.lesboutin
                          haptic: medium
                        hold_action:
                          action: none
                      - aspect_ratio: 1/1
                        show_name: false
                        show_icon: true
                        icon: 'mdi:dots-horizontal-circle'
                        type: 'custom:button-card'
                        size: 90%
                        style:
                          right: 18%
                          top: 88%
                          height: 5%
                          width: 5%
                        styles:
                          card:
                            - padding: 0px
                            - border-radius: 50%
                          icon:
                            - color: var(--text-color)
                        tap_action:
                          action: call-service
                          service: browser_mod.more_info
                          service_data:
                            entity_id: media_player.lesboutin
                            deviceID: this
                          haptic: medium
                        hold_action:
                          action: none

              - type: grid
                columns: 2
                cards:
                  - type: custom:button-card
                    entity: media_player.livingroom_appletv
                    name: Living Room
                    template:
                      - media
                      - icon_apple_tv

                  - type: custom:button-card
                    name: Bedroom
                    entity: media_player.bedroom_appletv
                    template:
                      - media
                      - icon_apple_tv

                  - type: custom:button-card
                    entity: media_player.spotify_cheznath
                    name: Spotify
                    template:
                      - media
                      - icon_spotify

                  - type: custom:button-card
                    entity: media_player.livingroom_sonos
                    name: Sonos
                    template:
                      - media
                      - icon_sonos

Would you be able to help me out, trying to figure things out?

Iā€™m also using this in my config:

media_player:
  - platform: universal
    name: media_player.lesboutin
    children:
      - media_player.bathroom_sonos
      - media_player.livingroom_sonos
      - media_player.onkyo_tx_nr686_f0935c_2
      - media_player.spotify_cheznath

And Iā€™m using your script too. But Iā€™m guessing Iā€™m missing something with iftt.

alias: add_to_playlist_sonos
sequence:
  - service: ifttt.trigger
    data_template:
      event: add_to_playlist
      value1: '{{ states.media_player.lesboutin.attributes.media_title }}'
      value2: '{{ states.media_player.lesboutin.attributes.media_artist }}'
mode: single

Thanks. And I realize itā€™s been a while for you. :joy:
No problem if you canā€™t bother.
Thanks again

EDIT: Yes, I do have card-mod, mini media player and button card. also using your overlay.svg in the correct folder.

Oh, when music is playing it look the same.

How can I not have the code in there? And bringing down the buttons?

@xADDRx
Do you remember what you did to bring those buttons down?

Iā€™m getting placesā€¦ I got the damn overlay to now be seen. Now, what is that css text in the button? How can I take that out?

So Iā€™m guessing this needs to be re written with card_mod 3 changes.
Iā€™ll try and see if I can do that? But I doubt it.

EDIT: I got tit working.
I just switched - type: 'custom:mod-card' to

card_mod:

Hi, Iā€™ve been busy on holidays. Have you gotten everything working now? Yes, I changed the codes when card_mod was updated. I donā€™t visit this thread much, so havenā€™t updated the code on here.

@ASNNetworks Yes, itā€™s all working great.
I had one though. When nothing is playing, itā€™s blank right? Do you have any else going on while itā€™s blank? I mean, did you update it to show something else or you just see it blank?

Glad you got it working. I just updated the code in my post. Btw regarding the favorite/heart button: I used that prior when I used Spotcast and created a script using IFTTT. I switched all my audio to Logitech Media Server for a while now and ditched IFTTT. Currently itā€™s a non-functional button in my own setup.

When nothing is playing the card is blank, since there is no artwork. In my case all my media players are hidden. All my speakers have their own media card, which are all inside their own conditional card. So when a speaker is off, the specific media card is hidden. I also wrapped them all inside one swiper card, so I can easily swipe between media cards/speakers.

See in action: Imgur: The magic of the Internet

Oh wow, thatā€™s cool. Something new I have to do nowā€¦ arghā€¦ haha. It just never ends it seems.
You wouldnā€™t happen to have your code on a github. :wink:
I know Mattias also did something like this, with conditions. I didnā€™t dwell into conditions yet.
On your code, the only thing that doesnā€™t work are the actions. For some reason, the three dot actions and the main whole button press action donā€™t work at all.

I have somewhat changed the code throughout time because I started using decluttering-card. But the three dots should open more-info. So make sure that service call is still correct. Same applies to the main play/pause button.

I believe browser_mod has been changed a few times as well, which changes the more_info command. I donā€™t use it as a more-info anymore myself. I think you can just set it as:

                    tap_action:
                      action: more-info

And get rid of browser_mod command there.

Regarding conditions: itā€™s very simple, the HA documentations explain the usage of that card very well: Conditional Card - Home Assistant

Example in your case:

type: conditional
conditions:
  - entity: media_player.media_player.lesboutin
    state_not: 'off'
  - entity: media_player.media_player.lesboutin
    state_not: unavailable
card:
  type: picture-elements
  image: 'local/tablet/overlay.svg'
  REST OF THE CODE OF THIS MEDIA CARD

This will hide the card if itā€™s either off or unavailable for some reason (like disconnected). When itā€™s playing, idle, paused etc it will show. You can change the conditions to what you see fit yourself.

UPDATED CARD V2: new fresh look with more control

Warning, since itā€™s inside a picture-element some features do not work properly, like changing sources or shortcut buttons because they expand the card, which is why I disabled those by default.

I updated my cardā€™s look and feel along with some more control buttons. I wanted to share the code with whoever is interested :slight_smile: I have switched over to decluttering-card a while back, so this is easier for others to copy as well.

Make sure you have button-card and decluttering-card installed and templates for both declared in the root of your lovelace yaml! All the control buttons are button-cards with actions. So you can change the icons and actions! Bonus: the volume up and down support hold action to keep increasing/decreasing volume! I want to also add hold_action to the skip/previous button so it will seek forward/backwards +10 seconds. But I still need to investigate to see what klind of template I can use.

Requirements

Button-card
Decluttering-card
Card-mod
Mini media player card
Overlay.svg (put this in your local folder (www/)

Also make sure you have these variables in your theme.yaml (you can ofcourse change them to whatever you want). If you use night and day themes, you can have auto-switching themes like my screenshots.

mini-media-player-mmp: rgba(255, 255, 255, 0.6)  #or for night rgba(0, 0, 0, 0.6)
text-color: '#404040'
accent-color: '#9FD848' 
Button-card template (you can change icon colors/shadow etc)
music_card_speaker_button:        
  aspect_ratio: 1/1
  show_name: false
  show_icon: true
  size: 100%
  entity: '[[entity]]'
  styles:
    card:
      - background: none
      - padding: 0px
      - border-radius: 50%
      - box-shadow: none
      - -webkit-box-shadow: none          
      - border-style: none    
    icon:
      - color: rgba(255, 255, 255, 1)
      - filter: drop-shadow(2px 4px 4px rgba(0,0,0,0.7)) 
Decluttering template (you can always change icons/actions):
media_card_speaker:
  card:
    type: picture-elements
    image: local/overlay.svg
    card_mod:
      style: |
        ha-card {
          --ha-card-background: none !important;
          # box-shadow: none !important;
        }                          
    elements:
      - aspect_ratio: 1/1
        entity: '[[entity]]'
        show_icon: false
        show_label: false
        show_last_changed: false
        show_entity_picture: true
        show_name: false
        show_state: false
        tap_action:
          action: none
        style:
          height: 100%
          width: 100%
          top: 50%
          left: 50%
        state:
          - styles:
              entity_picture:
                - filter: grayscale(100%) blur(17px)
                - transition: all 0.5s ease
            value: paused
          - styles:
              entity_picture:
                - filter: grayscale(100%) blur(17px)
                - transition: all 0.5s ease
            value: idle        
        styles:
          card:
            - padding: 0px
            - background-color: var(--card-background-off) #the color when there is no artwork, change or remove to use own color
            - box-shadow: none
            - -webkit-box-shadow: none      
            - border-style: none
          entity_picture:
            - height: 110%
            - width: 110%
            - position: absolute
            - transition: all 0.5s ease
            - filter: blur(17px)
        type: 'custom:button-card'
      - type: 'custom:mod-card'
        style:
          '--mini-media-player-icon-color': var(--text-color) #change or remove to use own color
          '--mini-media-player-base-color': var(--text-color) #change or remove to use own color
          '--mini-media-player-accent-color': var(--accent-color) #change or remove to use own color
          border-top-left-radius: 0px !important
          border-top-right-radius: 0px !important      
          width: 100%
          transform: 'translate(0%, -100%)'
          border-style: none 
          border-color: rgba(0,0,0,0.0)
        card:
          artwork: none
          entity: '[[entity]]'
          group: false
          icon: 'mdi:speaker'
          hide:
            controls: true
            icon: false
            name: false
            power: true
            runtime: false
            source: true
            volume: true
          hold_action:
            action: none
          tap_action:
            action: none
          info: scroll
          source: true
          card_mod:
            style: |
              .mmp-player {
                 background: var(--mini-media-player-mmp) !important;
                 border-top-left-radius: 0px !important;
                 border-top-right-radius: 0px !important;
                 border-style: none !important;
                 border-color: rgba(0,0,0,0.0) !important;
              }      
              .entity__info {
                max-width: 95% !important; #change this if you want the scrolling info to be wider/smaller
              }                           
          type: 'custom:mini-media-player'
      - icon: 'mdi:chevron-right'
        template: music_card_speaker_button
        entity: '[[entity]]'
        style:
          right: '-7.5%'
          top: 50%
          height: 25%
          width: 25%
        tap_action:
          action: call-service
          service: media_player.media_next_track
          service_data:
            entity_id: '[[entity]]'
          haptic: medium
        hold_action:
          action: call-service
          service: media_player.media_seek
          service_data:
            seek_position: "[[[ return entity.attributes.media_position + 15 ]]]"
            entity_id: '[[entity]]'
          haptic: heavy          
          repeat: 1000
        type: 'custom:button-card'            
      - icon: 'mdi:chevron-left'
        template: music_card_speaker_button
        entity: '[[entity]]'
        style:
          right: 57.5%
          top: 50%
          height: 25%
          width: 25%
        tap_action:
          action: call-service
          service: media_player.media_previous_track
          service_data:
            entity_id: '[[entity]]'
          haptic: medium
        hold_action:
          action: call-service
          service: media_player.media_seek
          service_data:
            seek_position: "[[[ return entity.attributes.media_position - 15 ]]]"
            entity_id: '[[entity]]'
          haptic: heavy          
          repeat: 1000
        type: 'custom:button-card'            
      - icon: 'mdi:pause-circle'
        aspect_ratio: 1/1
        show_name: false
        show_icon: false
        show_entity_picture: true
        size: 100%
        entity: '[[entity]]'
        style:
          right: 10%
          top: 50%
          height: 40%
          width: 40%
        styles:
          card:
            - background: none
            - padding: 0
            - border-radius: 50%
            - border: 2px solid rgba(255,255,255,0.8)
            - box-shadow: 2px 4px 4px rgba(0,0,0,0.7)
          img_cell:
            - border-radius: 50%
            - place-self: center 
        tap_action:
          action: call-service
          service: media_player.media_play_pause
          service_data:
            entity_id: '[[entity]]'
          haptic: medium
        hold_action:
          action: none
        type: 'custom:button-card'
      - icon: 'mdi:close-circle'
        template: music_card_speaker_button
        entity: '[[entity]]'
        style:
          right: 35%
          top: 15%
          height: 15%
          width: 15%
        tap_action:
          action: call-service
          service: media_player.volume_mute
          service_data:
            is_volume_muted: >
              [[[ if (entity.attributes.is_volume_muted == false) return 'true'; return
              'false' ]]]
            entity_id: '[[entity]]'
          haptic: medium          
        hold_action:
          action: none     
        type: 'custom:button-card'            
      - icon: 'mdi:minus-circle'
        template: music_card_speaker_button
        entity: '[[entity]]'
        style:
          right: 60%
          top: 25%
          height: 15%
          width: 15%
        tap_action:
          action: call-service
          service: media_player.volume_set
          service_data:
            volume_level: "[[[ return entity.attributes.volume_level - 0.020 ]]]"
            entity_id: '[[entity]]'
          haptic: medium       
        hold_action:
          action: call-service
          service: media_player.volume_set
          service_data:
            volume_level: "[[[ return entity.attributes.volume_level - 0.020 ]]]"
            entity_id: '[[entity]]'
          haptic: medium       
          repeat: 300
        type: 'custom:button-card'            
      - icon: 'mdi:plus-circle'
        template: music_card_speaker_button
        entity: '[[entity]]'
        style:
          left: 75%
          top: 25%
          height: 15%
          width: 15%
        tap_action:
          action: call-service
          service: media_player.volume_set
          service_data:
            volume_level: "[[[ return entity.attributes.volume_level + 0.020 ]]]"
            entity_id: '[[entity]]'
          haptic: medium          
        hold_action:
          action: call-service
          service: media_player.volume_set
          service_data:
            volume_level: "[[[ return entity.attributes.volume_level + 0.020 ]]]"
            entity_id: '[[entity]]'
          haptic: medium          
          repeat: 300
        type: 'custom:button-card'            
      - icon: 'mdi:power-standby'
        template: music_card_speaker_button
        entity: '[[entity]]'
        style:
          right: 80%
          top: 10%
          height: 10%
          width: 10%
        tap_action:
          action: call-service
          service: media_player.toggle
          service_data:
            entity_id: '[[entity]]'
          haptic: medium
        hold_action:
          action: none
        type: 'custom:button-card'                
      - icon: 'mdi:dots-vertical'
        entity: '[[entity]]'
        template: music_card_speaker_button
        style:
          left: 90%
          top: 10%
          height: 10%
          width: 10%
        tap_action:
          haptic: medium
          action: more-info   
        hold_action:
          action: none
        type: 'custom:button-card'      
Then in your lovelace.yaml just use this code

Make sure you change it to your media_player entity. Of course you can insert these in other cards, like grid, vertical-stack, horizontal-stack, swipe-card etc.

type: 'custom:decluttering-card'
template: media_card_speaker
variables:
  - entity: media_player.kantoor_lms

Protip: if you want the card to be hidden when off and only show when playing/paused/idle, use it with conditional card, like this:

card: 
  type: 'custom:decluttering-card'
  template: media_card_speaker
  variables:
    - entity: media_player.kantoor_lms                      
conditions:
  - entity: media_player.kantoor_lms
    state_not: 'off'
  - entity: media_player.kantoor_lms
    state_not: unavailable
type: conditional
14 Likes

Great work this Iā€™m going to try it on my tablet of thatā€™s ok.
Although my wife only ever loads the same radio station on my devices all the time :laughing:

1 Like

Feel free to use at how you like. You can also change stuff like icons, colors and actions easily by changing the decluttering en button templates.

Thanks Iā€™ve only just started using decluttering and button templates this week for something else can I use your code in the same Yaml file underneath what I already have it should I put them in a separate Yaml file.

Yes, for example:

If this is your button-card templates yaml file:

  steveukbuttontemplate:
    card:
      TEMPLATE

  music_card_speaker_button:
    card:
      TEMPLATE

Same applies to decluttering-card template yaml:

  steveukdeclutteringtemplate:
    card:
      TEMPLATE

  music_card_speaker:
    card:
      TEMPLATE

Thanks thought it was like that.
Iā€™m trying to copy and paste it over using my phone before I get home from workā€¦ Not the easiest of tasks on a mobile :laughing:

@ASNNetworks
Thanks added nicely to a dashboard iā€™m in the middle of setting up.
I have my theme set to add a thin black border around my cards which as you can see is making your card look odd ha haā€¦
Iā€™m just debating wether to remove the border from the theme or just search through your code to remove all the borders :thinking: