Spotify on 0.4.5

I don’t know if this was possible before, but at least now, I cannot control the volume output from the spotify app. Is that something that is supported with go-librespot? Right now I seem to only be able to control the output volume via changing the levels on the amplipi interface. Thanks!

Sorry for that change. We had to remove volume control initially from our spotify go-librespot integration. Initial testing gave bad quality audio when the volume was low. We are looking at different options to support this in the future.

Volume control would be great because… last night I was playing spotify at probably 30% volume on the amplipi, then an announce came on that’s set to 80% volume (which stopped the spotify playback?). I then resumed spotify playback and the volume was back at 80%, which was terribly loud. Grabbed the phone and hit the volume slider out of habit, but that of course had no affect.

I’m trying to keep from needing to go into the amplipi GUI on a regular basis. Previously, I did not have any of the amplipi volume controls exposed in HA, but I might need to add them as a just-in-case. I built out the following with a grid of custom-button cards. It lists out my 6 zones and 4 inputs. But the only volume I had was to mute the whole zone.

Quick change, just added a hold-action to my template card to show more-info of the entity:

1 Like

Wow that’s pretty slick. I haven’t seen a grid like that before. How did you make that?

As for Spotify volume, we have some ideas to test but I don’t want to make an promises yet…

Thanks! I used the custom:button-card (GitHub - custom-cards/button-card: ❇️ Lovelace button-card for home assistant) inside of custom:layout-card (GitHub - thomasloven/lovelace-layout-card: 🔹 Get more control over the placement of lovelace cards.) grid from hacs:

type: custom:layout-card
layout_type: custom:grid-layout
layout:
  grid-template-columns: 55px 55px 55px 55px 55px 55px 55px
  grid-template-rows: auto
  width: 300
  max_cols: 7
cards:
  - type: custom:button-card
    template: amplipi_header
  - type: custom:button-card
    template: amplipi_header
    icon: mdi:pot-steam
  - type: custom:button-card
    template: amplipi_header
    icon: mdi:sofa
  - type: custom:button-card
    template: amplipi_header
    icon: mdi:desk
  - type: custom:button-card
    template: amplipi_header
    icon: mdi:bed
  - type: custom:button-card
    template: amplipi_header
    icon: mdi:toilet
  - type: custom:button-card
    template: amplipi_header
    icon: mdi:stairs
  - type: custom:button-card
    template: amplipi_header
    icon: mdi:speaker-message
  - type: custom:button-card
    entity: media_player.kitchen_speakers
    template: amplipi_card
    variables:
      source: Source 1
  - type: custom:button-card
    template: amplipi_card
    entity: media_player.living_room_speakers
    variables:
      source: Source 1
  - type: custom:button-card
    template: amplipi_card
    entity: media_player.office_speakers
    variables:
      source: Source 1
  - type: custom:button-card
    template: amplipi_card
    entity: media_player.bedroom_speakers
    variables:
      source: Source 1
  - type: custom:button-card
    template: amplipi_card
    entity: media_player.bathroom_speaker
    variables:
      source: Source 1
  - type: custom:button-card
    template: amplipi_card
    entity: media_player.hallway_speakers
    variables:
      source: Source 1
  - type: custom:button-card
    template: amplipi_header
    icon: mdi:spotify
  - type: custom:button-card
    entity: media_player.kitchen_speakers
    template: amplipi_card
    variables:
      source: Source 2
  - type: custom:button-card
    entity: media_player.living_room_speakers
    template: amplipi_card
    variables:
      source: Source 2
  - type: custom:button-card
    entity: media_player.office_speakers
    template: amplipi_card
    variables:
      source: Source 2
  - type: custom:button-card
    entity: media_player.bedroom_speakers
    template: amplipi_card
    variables:
      source: Source 2
  - type: custom:button-card
    entity: media_player.bathroom_speaker
    template: amplipi_card
    variables:
      source: Source 2
  - type: custom:button-card
    entity: media_player.hallway_speakers
    template: amplipi_card
    variables:
      source: Source 2
  - type: custom:button-card
    template: amplipi_header
    icon: mdi:dlna
  - type: custom:button-card
    entity: media_player.kitchen_speakers
    template: amplipi_card
    variables:
      source: Source 3
  - type: custom:button-card
    entity: media_player.living_room_speakers
    template: amplipi_card
    variables:
      source: Source 3
  - type: custom:button-card
    entity: media_player.office_speakers
    template: amplipi_card
    variables:
      source: Source 3
  - type: custom:button-card
    entity: media_player.bedroom_speakers
    template: amplipi_card
    variables:
      source: Source 3
  - type: custom:button-card
    entity: media_player.bathroom_speaker
    template: amplipi_card
    variables:
      source: Source 3
  - type: custom:button-card
    entity: media_player.hallway_speakers
    template: amplipi_card
    variables:
      source: Source 3
  - type: custom:button-card
    template: amplipi_header
    icon: mdi:spotify
  - type: custom:button-card
    entity: media_player.kitchen_speakers
    template: amplipi_card
    variables:
      source: Source 4
  - type: custom:button-card
    entity: media_player.living_room_speakers
    template: amplipi_card
    variables:
      source: Source 4
  - type: custom:button-card
    entity: media_player.office_speakers
    template: amplipi_card
    variables:
      source: Source 4
  - type: custom:button-card
    entity: media_player.bedroom_speakers
    template: amplipi_card
    variables:
      source: Source 4
  - type: custom:button-card
    entity: media_player.bathroom_speaker
    template: amplipi_card
    variables:
      source: Source 4
  - type: custom:button-card
    entity: media_player.hallway_speakers
    template: amplipi_card
    variables:
      source: Source 4
  - type: custom:button-card
    template: amplipi_header
    icon: mdi:volume-off
  - type: custom:button-card
    entity: media_player.kitchen_speakers
    template: amplipi_mute_card
    icon: mdi:volume-off
  - type: custom:button-card
    entity: media_player.living_room_speakers
    template: amplipi_mute_card
    icon: mdi:volume-off
  - type: custom:button-card
    entity: media_player.office_speakers
    template: amplipi_mute_card
    icon: mdi:volume-off
  - type: custom:button-card
    entity: media_player.bedroom_speakers
    template: amplipi_mute_card
    icon: mdi:volume-off
  - type: custom:button-card
    entity: media_player.bathroom_speaker
    template: amplipi_mute_card
    icon: mdi:volume-off
  - type: custom:button-card
    entity: media_player.hallway_speakers
    template: amplipi_mute_card
    icon: mdi:volume-off
title: Control
columns: 7

And in the lovelace configuration, you can add templates to use over and over (which a grid like this basically is):

button_card_templates:
  amplipi_header:
    name: '[[[ return variables.var_name ]]]'
    show_label: false
    styles:
      card:
        - width: 50px
        - height: 50px
  amplipi_mute_card:
    name: '[[[ return variables.var_name ]]]'
    entity: '[[[ return entity.entity_id ]]]'
    show_label: false
    styles:
      card:
        - width: 50px
        - height: 50px
    state:
      - operator: template
        value: |
          [[[ 
            var muted = entity.attributes.is_volume_muted;
            if (muted == null)
              muted = new Boolean(true);
            if (muted)
              return true;
            else
              return false;
          ]]]
        color: grey
        icon: mdi:volume-off
      - operator: template
        value: |
          [[[ 
            var muted = entity.attributes.is_volume_muted;
            if (muted == null)
              muted = new Boolean(true);
            if (muted)
              return false;
            else
              return true;
          ]]]
        color: grey
        icon: mdi:volume-medium
    tap_action:
      action: call-service
      service: script.mute_toggle
      data:
        media_player: '[[[ return entity.entity_id ]]]'
    hold_action:
      action: more-info
  amplipi_card:
    variables:
      on_color: '#276e1d'
      off_color: '#030303'
      red_color: '#8f2d28'
    name: '[[[ return variables.var_name ]]]'
    color: grey
    state:
      - operator: template
        value: '[[[ return (entity.state == "playing"); ]]]'
        color: '#21618C'
      - operator: template
        value: '[[[ return (entity.state != "playing"); ]]]'
        color: grey
    label: '[[[ return variables.source.substr(5,5); ]]]'
    show_label: false
    icon: |
      [[[ 
        var source = entity.attributes.source;
        if (source == null)
          source = '';
        if (source.substr(0,(variables.source).length).toUpperCase() == (variables.source).toUpperCase())
          return 'mdi:radiobox-marked';
        else
          return 'mdi:radiobox-blank';
      ]]]
    tap_action:
      action: call-service
      service: media_player.select_source
      data:
        source: '[[[ return variables.source ]]]'
      target:
        entity_id: '[[[ return entity.entity_id ]]]'
    styles:
      card:
        - width: 50px
        - height: 50px
  amplipi_source:
    variables:
      source_name: media_player.amplipi_source_1
      zone_name: media_player.amplipi_kitchen
      source_id: 0
      zone_id: 0
    name: |
      [[[
        return states[variables.source_name].attributes.source
      ]]]
    entity: |
      [[[
        return variables.zone_name
      ]]]
    entity_picture: |
      [[[
        return states[variables.source_name].attributes.entity_picture
      ]]]
    show_entity_picture: true
    aspect_ratio: 1/1
    triggers_update: all
    tap_action:
      action: call-service
      service: rest_command.amplipi_set_zone
      service_data:
        zone_id: |
          [[[
            return variables.zone_id 
          ]]]
        source_id: |
          [[[
            return variables.source_id 
          ]]]
    state:
      - operator: template
        value: |
          [[[ 
            return states[variables.zone_name].attributes.source == states[variables.source_name].attributes.source
          ]]]
        styles:
          card:
            - background-color: rgb(255, 193, 7)
1 Like

HOLD UP DUDE - this is a very slick way to think about it-- I’m assuming the top are zones and the down is the source? Way to go on this…I need to figure out how to do this too. What’s with the different colors? I’ve got 13 or so zones so this would really help me out on the configuring fast haha

Correct. The “columns” are my zones (Kitchen, Living Room, Office, Bedroom, Bathroom and Stairs). The colors trigger off of the state of the media_player, which is a bit of an odd concept, but the blue means the Kitchen and Living Room are set to playing in HA, even though they are muted. On the Amplipi GUI, it looks like this (Upstairs = Kitchen and Living Room):

And the HA entity:

vs the Office, which is not attached to an input:

It’s not perfect, and I’m sure someone can come up with a better way, but I like how I can easily see a grid of inputs and outputs.