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

07 Jan 2022
UPDATE: Added fast forward and rewind commands. Holding skip/previous will continiously fast forward/rewind for 15s every 1s holding. Updated the original code.

02 Jan 2022
UPDATE: Revamped V2 card: with more control, all requirements and code :point_right: Touchy - Touch friendly media player card (combination of cards) - #79 by ASNNetworks

OLD INFO, DEPRECATED
UPDATE: use the updated code :point_right: Touchy - Touch friendly media player card (combination of cards) - #11 by ASNNetworks

And DO READ the rest of my explanation below!

:point_down::point_down::point_down:

Hi, this is my first write up so I hope the explanation is not a total mess :nerd_face: I created a little project and got a lot of messages from people to share it. Instead of explaining it one by one, or in the picture-elements thread where it might get burried, I decided to share here.

Summary

This is what it looks like, below you will find the full write up and explanation.
Day theme:
tCbp2xuc2x

Night theme:
NapfdMQRDM

Like many of us I use mini media player card to control my music and other media. I really love that card and the work Kalkih has done. However, I missed some features that fitted my needs more. I fully understand he cannot please everyone ofcourse, so I decided to get creative and figure out how I could use that card and add features.

So I present to you this fully loaded media player card. For now, you will need three cards for it to work: picture-elements (core), RomRider’s button card and Kalkih’s mini media player. I wrapped this inside a conditional card, so it’s hidden when media player it not playing/paused.

Picture-elements
The card is built onto a picture-elements card with a square shaped transparent overlay.svg. Just create that, or download mine here.

Buton card
I used button card for the artwork (because it supports state based stylings) and also for the media control buttons (also because of state based styling).

Mini media player
I still use mini media player for the media info, icon and progress bar. I have hidden everything else.

When I was creating this little project I saw more elements of mini media player I could replace. I tried to fully replace mini media player by using markdown for the media info. This does work and allows an extra level of customization. However, I couldn’t find a way to create a progress bar and playtime, so I decided to keep mini media player and hide other elements. Perhaps someone else has an idea how to create a live progress bar and playtime. Ofcourse I love mini media player, but I try to make a card that is not so dependable on other custom cards (button card being the exeption).

Spotify favorites
The button to add the current playing track to a predefined Spotify playlist works with a script and IFTTT. More info here.

Day and night theme
I created an input_boolean to switch between day and night themes. Added that in my automation that changes my theme, so it all works automatically with just one predefined setup.

Final words
Ofcourse there are a million ways to do things, this is just one way of doing so. A lot of thought and trial/error has gone into this. There are more things I wanted to add, like opening the new media browser as a popup, but that’s not possible yet (not easily at least). I did get that to work by wrapping that inside a webpage card and use that as a popup. It did work on my tablet and desktop, but not inside HA app on iOS.

You can copy/paste this also if not using yaml mode. Just use manual code and remove all the #comments. You can easily change the code to apply different sylings or control different media players. I also created one to control my PS4 and AppleTV by simply changing icons and media_player control service calls.

If you have other ideas to do things easier, use less code or make the media player better in any way: feel free to share! I have no experience with creating custom cards myself, feel free to use this as inspiration! And who knows, maybe mini media player will implement all these features and render this project useless (would not mind that :slight_smile: !)

Code and explanation in comments below:

  # Picture-elements as base with a transparent overlay.svg to build everything on #
  type: picture-elements
  image: local/mediaplayer/overlay.svg
  style: |
    ha-card {
      --ha-card-background: none !important;
      box-shadow: none !important;
    }                          
  elements:
  
      # Custom button card that shows media player artwork without paddings #
    - aspect_ratio: 1/1
      entity: media_player.multispeakers_cast
      icon: 'mdi:speaker-multiple'
      label: not needed
      name: not needed
      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: '#000000'
        entity_picture:
          - border-radius: 20px
          - height: 100%
          - width: 100%
          - position: absolute
          - transition: all 0.5s ease
      type: 'custom:button-card'   
      
      # Custom card: button card for the background behind the media info, tied it to a input_boolean which is set in my automations to pair night/dark mode themes #
    - type: "custom:button-card"
      entity: input_boolean.mediaplayer_nightmode
      show_icon: false
      show_name: false
      aspect_ratio: 4/1
      state:
        - styles:
            card:
              - background: '#000000'    
              - filter: 'opacity(70%)'
          value: 'on'
      styles:
        card:
          - background: '#FFFFFF'
          - filter: 'opacity(70%)'
      style:
        '--ha-card-border-radius': '0px 0px 20px 20px'
        height: 100%
        width: 100%
        top: 130%
        left: 50%          
      
      # Custom card: mini media player card for media info and progress bar, hidden everything else #
    - artwork: full-cover
      entity: media_player.multispeakers_cast
      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-multiple'
      info: short
      source: true
      style:
        '--ha-card-background': '#000000'
        '--mini-media-player-artwork-opacity': '0'
        '--ha-card-border-radius': '20px'
        '--mini-media-player-overlay-base-color': 'var(--text-color)' # make sure your theme is setup properly, or define this line in theme.yaml alltogether.
        left: 50%
        top: 50%
        height: 100%
        width: 100%      
      type: 'custom:mini-media-player'
      
      # Custom card: button card eant to allow hold_action for more-info on anywhere on the card. Can be deleted if using more-info button #
    - aspect_ratio: 1.2/1
      entity: media_player.multispeakers_cast
      icon: 'mdi:speaker-multiple'
      label: not needed
      name: not needed
      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'
      
      # Custom card: button card to call service media_next_track. Applied state styles based on entity state.
    - aspect_ratio: 1/1
      show_name: false
      show_icon: true
      icon: 'mdi:skip-next-circle'
      type: 'custom:button-card'
      size: 100%
      entity: media_player.multispeakers_cast
      style:
        right: -5%
        top: 50%
        height: 25%
        width: 25%
      state:
        - styles:
            icon:
              - filter: opacity(100%)
              - transition: all 0.5s ease
          value: 'paused'
      styles:
        card:
          - padding: 0px               
          - border-radius: 50%
        icon:
          - filter: opacity(30%)
          - transition: all 0.5s ease
          - color: '#FFFFFF'
      tap_action:
        action: call-service
        service: media_player.media_next_track
        service_data:
          entity_id: media_player.multispeakers_cast
        haptic: medium
      hold_action:
        action: none                  
        
      # Custom card: button card to call service media_previous_track. Applied state styles based on entity state.  
    - aspect_ratio: 1/1
      show_name: false
      show_icon: true
      icon: 'mdi:skip-previous-circle'
      type: 'custom:button-card'
      size: 100%
      entity: media_player.multispeakers_cast
      style:
        right: 55%
        top: 50%
        height: 25%
        width: 25%
      state:
        - styles:
            icon:
              - filter: opacity(100%)
              - transition: all 0.5s ease
          value: 'paused'
      styles:
        card:
          - padding: 0px               
          - border-radius: 50%
        icon:
          - filter: opacity(30%)
          - transition: all 0.5s ease
          - color: '#FFFFFF'
      tap_action:
        action: call-service
        service: media_player.media_previous_track
        service_data:
          entity_id: media_player.multispeakers_cast
        haptic: medium
      hold_action:
        action: none                  
        
      # Custom card: button card to call service media_play_pause. Applied state styles based on entity state.   
    - aspect_ratio: 1/1
      show_name: false
      show_icon: true
      icon: 'mdi:pause-circle'
      type: 'custom:button-card'
      size: 100%
      entity: media_player.multispeakers_cast
      style:
        right: 10%
        top: 50%
        height: 40%
        width: 40%
      state:
        - styles:
            icon:
              - filter: opacity(100%)
              - transition: all 0.5s ease
          value: 'paused'
          icon: 'mdi:play-circle'
      styles:
        card:
          - padding: 0px               
          - border-radius: 50%                
        icon:
          - filter: opacity(30%)   
          - transition: all 0.5s ease
          - color: '#FFFFFF'                    
      tap_action:
        action: call-service
        service: media_player.media_play_pause
        service_data:
          entity_id: media_player.multispeakers_cast
        haptic: medium
      hold_action:
        action: none             
        
      # Custom card: button card to add current track to a predefined Spotify playlist    
    - 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_multispeakers_cast
        haptic: medium
      hold_action:
        action: none          
        
      # Custom card: button card to turn off media player
    - 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.multispeakers_cast
        haptic: medium
      hold_action:
        action: none            
        
      # Custom card: button card to invoke more-info. Written it with browser mod service call, to change easily for popup mod. Can be simplified to tap_action: more info instead.
    - 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.multispeakers_cast
          deviceID: this
        haptic: medium
      hold_action:
        action: none  
26 Likes

Nice work, really creative usage of resources, looks great!

2 Likes

Coming from you, that means alot :grinning:

1 Like

Thank you @ASNNetworks for sharing your code. This is really cool!

I have some troubles using this. The final result is similar but very rough then yours.
Do you have any suggestion?

Hi! Glad you like it. You probably have border-color in your theme by default. I have that invisible from within theme.yaml

Add this to your theme.yaml to disable all:

border-color: 'rgba(0, 0, 0, 0.00)'

Or add it to each button-card in the code, if you don’t want it across all cards your lovelace theme.

Maybe you need to apply to shadows as well: ha-card-box-shadow: I have them both to that rgba value, which essentially makes it invisible.

Also remove that for mini media player card if you don’t do it by theme, so that looks clean too. When your media has no artwork, it shows a black screen. You can change this to any color though. I used black, so the buttons remain visible regardless of colors/themes.

1 Like

Thank you! I’ll give it a try!

EDIT:

Is this corrected?
2020-10-14_205

@ASNNetworks at the end i decided to modify my Theme.yaml in order to get the result easier.

One more question: I did a new test, copying your whole code and changing only the entity id.
I get the media player on the top instead of the bottom, like yours.

What is wrong with my code?

2020-10-14_209

                  - type: picture-elements
                    image: local/images/overlay.svg
                    style: |
                      ha-card {
                        --ha-card-background: none !important;
                        box-shadow: none !important;
                      }                          
                    elements:
                    
                        # Custom button card that shows media player artwork without paddings #
                      - aspect_ratio: 1/1
                        entity: media_player.appletv_soggiorno
                        icon: 'mdi:speaker-multiple'
                        label: not needed
                        name: not needed
                        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: '#000000'
                          entity_picture:
                            - border-radius: 20px
                            - height: 100%
                            - width: 100%
                            - position: absolute
                            - transition: all 0.5s ease
                        type: 'custom:button-card'   
                        
                        # Custom card: button card for the background behind the media info, tied it to a input_boolean which is set in my automations to pair night/dark mode themes #
                      - type: "custom:button-card"
                        entity: input_boolean.mediaplayer_nightmode
                        show_icon: false
                        show_name: false
                        aspect_ratio: 4/1
                        state:
                          - styles:
                              card:
                                - background: '#000000'    
                                - filter: 'opacity(70%)'
                            value: 'on'
                        styles:
                          card:
                            - background: '#FFFFFF'
                            - filter: 'opacity(70%)'
                        style:
                          '--ha-card-border-radius': '0px 0px 20px 20px'
                          height: 100%
                          width: 100%
                          top: 130%
                          left: 50%          
                        
                        # Custom card: mini media player card for media info and progress bar, hidden everything else #
                      - artwork: full-cover
                        entity: media_player.appletv_soggiorno
                        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-multiple'
                        info: short
                        source: true
                        style:
                          '--ha-card-background': '#000000'
                          '--mini-media-player-artwork-opacity': '0'
                          '--ha-card-border-radius': '20px'
                          '--mini-media-player-overlay-base-color': 'var(--text-color)' # make sure your theme is setup properly, or define this line in theme.yaml alltogether.
                          left: 50%
                          top: 50%
                          height: 100%
                          width: 100%      
                        type: 'custom:mini-media-player'
                        
                        # Custom card: button card eant to allow hold_action for more-info on anywhere on the card. Can be deleted if using more-info button #
                      - aspect_ratio: 1.2/1
                        entity: media_player.appletv_soggiorno
                        icon: 'mdi:speaker-multiple'
                        label: not needed
                        name: not needed
                        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'
                        
                        # Custom card: button card to call service media_next_track. Applied state styles based on entity state.
                      - aspect_ratio: 1/1
                        show_name: false
                        show_icon: true
                        icon: 'mdi:skip-next-circle'
                        type: 'custom:button-card'
                        size: 100%
                        entity: media_player.appletv_soggiorno
                        style:
                          right: -5%
                          top: 50%
                          height: 25%
                          width: 25%
                        state:
                          - styles:
                              icon:
                                - filter: opacity(100%)
                                - transition: all 0.5s ease
                            value: 'paused'
                        styles:
                          card:
                            - padding: 0px               
                            - border-radius: 50%
                          icon:
                            - filter: opacity(30%)
                            - transition: all 0.5s ease
                            - color: '#FFFFFF'
                        tap_action:
                          action: call-service
                          service: media_player.media_next_track
                          service_data:
                            entity_id: media_player.appletv_soggiorno
                          haptic: medium
                        hold_action:
                          action: none                  
                          
                        # Custom card: button card to call service media_previous_track. Applied state styles based on entity state.  
                      - aspect_ratio: 1/1
                        show_name: false
                        show_icon: true
                        icon: 'mdi:skip-previous-circle'
                        type: 'custom:button-card'
                        size: 100%
                        entity: media_player.appletv_soggiorno
                        style:
                          right: 55%
                          top: 50%
                          height: 25%
                          width: 25%
                        state:
                          - styles:
                              icon:
                                - filter: opacity(100%)
                                - transition: all 0.5s ease
                            value: 'paused'
                        styles:
                          card:
                            - padding: 0px               
                            - border-radius: 50%
                          icon:
                            - filter: opacity(30%)
                            - transition: all 0.5s ease
                            - color: '#FFFFFF'
                        tap_action:
                          action: call-service
                          service: media_player.media_previous_track
                          service_data:
                            entity_id: media_player.appletv_soggiorno
                          haptic: medium
                        hold_action:
                          action: none                  
                          
                        # Custom card: button card to call service media_play_pause. Applied state styles based on entity state.   
                      - aspect_ratio: 1/1
                        show_name: false
                        show_icon: true
                        icon: 'mdi:pause-circle'
                        type: 'custom:button-card'
                        size: 100%
                        entity: media_player.appletv_soggiorno
                        style:
                          right: 10%
                          top: 50%
                          height: 40%
                          width: 40%
                        state:
                          - styles:
                              icon:
                                - filter: opacity(100%)
                                - transition: all 0.5s ease
                            value: 'paused'
                            icon: 'mdi:play-circle'
                        styles:
                          card:
                            - padding: 0px               
                            - border-radius: 50%                
                          icon:
                            - filter: opacity(30%)   
                            - transition: all 0.5s ease
                            - color: '#FFFFFF'                    
                        tap_action:
                          action: call-service
                          service: media_player.media_play_pause
                          service_data:
                            entity_id: media_player.appletv_soggiorno
                          haptic: medium
                        hold_action:
                          action: none              
                          
                        # Custom card: button card to turn off media player
                      - 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.appletv_soggiorno
                          haptic: medium
                        hold_action:
                          action: none            
                          
                        # Custom card: button card to invoke more-info. Written it with browser mod service call, to change easily for popup mod. Can be simplified to tap_action: more info instead.
                      - 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.appletv_soggiorno
                            deviceID: this
                          haptic: medium
                        hold_action:
                          action: none

It’s because of this. Mini media player originally shows artwork, which I have made transparent, allowing it to be aquare shaped/fullscreen. However, if there is no artwork, mini mediaplayer collapses. Since its position is fixed inside the picture-element, the location changes when the size of the mini media player changes as well. Resulting in it to go to the top.

Initially I tried to disable the artwork altogether from mini media player, so it’s just the collapsed version and set that at the bottom. But it gave mixed results on different devices. On desktop it was working fine, but iOS app had a small offset. So this is why I used this workaround for now. The downside is that the bar goes to the top when there is no artwork.

Try playing something on Netflix or use the card on a mediaplayer like Spotify of Chromecast. It should show artwork then and the menu will be places correctly.

I am still thinking of other solutions to solve this, but ideally I want new way to show the progress bar and running time. Because then mini media player card will not be needed anymore. Giving lighter code and no weird placings.

Btw: protip, you can replace the next/previous service calls with appletv remote service calls for left and right. Then you can also rewind/fastforward :slight_smile:

1 Like

Thank you very much for your explanation. I will think about it too and let you know if I have some idea.

Thank you also for the Apple TV remote tip!

So I went through the code of mini media player and I think I know what causes this. Inside the mini media player card, there is usage of position: relative and absolute. When changing everything to absolute, all element stay at the same location. But the mini media player breaks (all elements are out of place). It probably is fixable, but it won’t be worth the time. Also, having to change it each time mini media player card get’s an update is tedious.

I think I will look into a way to create an own progress slider and timestamp. That way I can be completely independent with this media player setup. If you have any ideas how to recreate those 2 elements, let me know :wink: !

@NdR

So, I have figured it out and updated my code! I managed to get the positioning right on all screen sizes. I don’t know if you still use my card, but I figured I’d share this.

The new and improved code uses better/less code and alters mini media player directly. You DON’T need the input_boolean anymore for the media bar on the bottom. I have also changed the size of the scrolling info to not go behind the side buttons.Also added some lines so the play/pause buttons have a different color when playing vs paused (for better readbility with white backgrounds. You can change this yourself to whatever you like. Basically change all the color codes to whatever you want or use your theme veriables.

msedge_w89gF8sgkL msedge_mjO3JEwOit

And most importantly: if there is no artwork, the media info will still remain at the bottom :smiley:!

msedge_43LrkDt4hC

Let me know if you have other questions. If you no longer use this card, that’s fine too!

Updated code

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.multispeakers_cast
    icon: 'mdi:speaker-multiple'
    label: Google Cast
    name: Badkamer
    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.multispeakers_cast
      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-multiple'
      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.
      card_mod:
        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.multispeakers_cast
    icon: 'mdi:speaker-multiple'
    label: Google Cast
    name: Badkamer
    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.multispeakers_cast
    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.multispeakers_cast
      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.multispeakers_cast
    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.multispeakers_cast
      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.multispeakers_cast
    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.multispeakers_cast
      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_multispeakers_cast
      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.multispeakers_cast
      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.multispeakers_cast
        deviceID: this
      haptic: medium
    hold_action:
      action: none
4 Likes

This is really cool mate!
Thanks again for sharing your work, rly appreciated.

I’ll give it a try tomorrow!

1 Like

Nice job! I wanted to do a pop-ip with your project, but, because I use instead of icons entity pictures, it doesn`t show the artwork.
I tried to modify to show entity_picture_local, but with no chance!

What doesn’t work exactly? Do you mean you want to open a popup with one of the buttons inside the card, or do you want this whole card as a popup?

I have them both working. I also have this card as a popup and one of the buttons opens a more-info popup.

Can you paste your code, then I understand what you’re trying to create with this.

@ASSNetworks, my problem was that I use button card for a google mini and I dont use icon: , I use entity_picture. When I open a pop-up with your card, instead of the artcover it shows my customised entity_picture.
I attach a screenshot to see exactly.
But I for the media players I will not use anymore entity_picture.

Can you please show your pop-up for ispiration, maybe with the code also? Please :relaxed:

I have posted my popup here a while ago: Chromecast Radio with station and player selection
image

Though that one is with my older media card version (it’s updated now with the card you see in this thread).

I used Bob_NL’s code as inspiration for the music selector and script, but applied it to Spotify. In that thread you will find a guide of Bob_NL and others you can use to create that. My popup is basically that + my media player card inside a vertical-stack.

Currently I cannot post my exact code, because I have split it up in different .yaml files and decluttering variables. This will cost a lot of time for me to put them together. But the code is essentially the same as what I linked + my media card inside a vertical-stack. If you’re stuck you can poste your code and I’ll try my best to help you :slight_smile:

1 Like

Hi
Great job Indeed !
But i tried your code (updated)and got an error at gui stage
Cut / paste after using my entity player, removed comments
" config.style.forEach is not a fonction "
Any Idea ?

Can you post your entire code inside a code format?

Hère is the code

type: picture-elements
image: local/tablet/overlay.svg
style: |
  ha-card {
    --ha-card-background: none
    box-shadow: none
  }                          
elements:
  - aspect_ratio: 1/1
    entity: media_player.x96mini
    icon: 'mdi:speaker-multiple'
    label: Google Cast
    name: salon
    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) 
      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) 
      '--mini-media-player-base-color': var(--text-color) 
      '--mini-media-player-accent-color': var(--music-accent-color) 
      border-top-left-radius: 0px
      border-top-right-radius: 0px
      width: 100%
      transform: 'translate(0%, -100%'
    card:
      artwork: none
      entity: media_player.x96mini
      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-multiple'
      info: scroll
      source: true
      style: |
        .mmp-player {          
           background: rgba(0, 0, 0, 0.75)
           border-top-left-radius: 0px
           border-top-right-radius: 0px
           height: 95px;
        }      
        .entity__info {
          max-width: 60% !important;
        }                           
      type: 'custom:mini-media-player'
  - aspect_ratio: 1.2/1
    entity: media_player.x96mini
    icon: 'mdi:speaker-multiple'
    label: Google Cast
    name: Badkamer
    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.x96mini
    style:
      right: '-5%'
      top: 50%
      height: 25%
      width: 25%
    state:
      - styles:
          icon:
            - filter: opacity(100%)
            - transition: all 0.5s ease
            - color: '#FFFFFF' 
        value: paused
    styles:
      card:
        - padding: 0px
        - border-radius: 50%
      icon:
        - filter: opacity(30%)
        - transition: all 0.5s ease
        - color: var(--music-accent-color)
    tap_action:
      action: call-service
      service: media_player.media_next_track
      service_data:
        entity_id: media_player.x96mini
      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.x96mini
    style:
      right: 55%
      top: 50%
      height: 25%
      width: 25%
    state:
      - styles:
          icon:
            - filter: opacity(100%)
            - transition: all 0.5s ease
            - color: '#FFFFFF'
        value: paused
    styles:
      card:
        - padding: 0px
        - border-radius: 50%
      icon:
        - filter: opacity(30%)
        - transition: all 0.5s ease
        - color: var(--music-accent-color) 
    tap_action:
      action: call-service
      service: media_player.media_previous_track
      service_data:
        entity_id: media_player.x96mini
      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.x96mini
    style:
      right: 10%
      top: 50%
      height: 40%
      width: 40%
    state:
      - styles:
          icon:
            - filter: opacity(100%)
            - transition: all 0.5s ease
            - color: '#FFFFFF' 
        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) 
    tap_action:
      action: call-service
      service: media_player.media_play_pause
      service_data:
        entity_id: media_player.x96mini
      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_x96mini
      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.x96mini
      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.x96mini
        deviceID: this
      haptic: medium
    hold_action:
      action: none

The code itself is fine, I copy/pasted your code in my test view in GUI and have no errors. Make sure you have everything setup before you try this code. This isn’t something you can just copy and paste and expect it to work. You need the custom cards that are used installed as well.

I see you use the exact same code for the image (with even the same location as me). Do you have the overlay.svg in that same folder? Do you have card-mod and mini-media-player card installed? Also the ‘add_to_playlist’ function is a script as you can see in the code. Do you have that script yourself? That script is inspired by this post: Save currently-playing song to Spotify playlist

Make sure you have everything setup properly before trying this card.