Skip to content

Commit

Permalink
All custom changes
Browse files Browse the repository at this point in the history
* Displaying station logo image
* Adding option to display custom sensor text (song author and title)
* Fix (workaround) for long playback start for specific radio stations
* Fix for icons not showing up after HA update to version 2021.11.X
  • Loading branch information
thehijacker committed Nov 9, 2021
1 parent f0b4ccd commit e90402b
Show file tree
Hide file tree
Showing 3 changed files with 151 additions and 33 deletions.
44 changes: 22 additions & 22 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
# Fork details

This is a fork of original project made/edited/updated by [lukx](https://github.com/lukx/home-assistant-jukebox). I added couple of new functions like:

* Displaying station logo image
* Adding option to display custom sensor text (song author and title)
* Fix (workaround) for long playback start for specific radio stations
* Fix for icons not showing up after HA update to version 2021.11.X

# Jukebox Card for Home-Assistant

This is a media player UI for Home-Assistant leveraging the potential of the excellent new
Expand All @@ -10,7 +19,7 @@ You can send different media to different players, which makes it usable for mul
to some *Frozen*, while you're Jazzing in the Kitchen. Volume-Level is handled separately, too.

## Screenshot
![alt text](https://github.com/lukx/home-assistant-jukebox/blob/master/screenshot.png?raw=true "See the jukebox in action")
![alt text](https://github.com/thehijacker/home-assistant-jukebox/blob/master/screenshot.png?raw=true "See the jukebox in action")

## Acknowledgement
Apart from the home-assistant project, I need to say thanks to User [Bob_NL](https://community.home-assistant.io/u/Bob_NL)
Expand All @@ -26,7 +35,7 @@ I recommend using [HACS](https://hacs.xyz/) to install and update this integrati
* In your Home Assistant, open the HACS panel
* Click on "Frontend" to see the list of Frontend (or "Lovelace") integrations
* On the top right of your screen, click on the three dots to see "Custom Repositories"
* in the "Custom Repositories" dialogue, paste `https://github.com/lukx/home-assistant-jukebox.git` in the "custom repository URL" box, and select "Lovelace" as the Category.
* in the "Custom Repositories" dialogue, paste `https://github.com/thehijacker/home-assistant-jukebox.git` in the "custom repository URL" box, and select "Lovelace" as the Category.
* Now, in the Frontend Category, search for "Jukebox" and install this module like you would install any other module.


Expand All @@ -48,18 +57,14 @@ views:
links:
- url: http://streams.greenhost.nl:8080/jazz
name: Concertzender Jazz
logo: https://raw.githubusercontent.com/home-assistant/assets/master/logo/logo-small.png
song: sensor.radio_jazz
- url: http://fs-insidejazz.fast-serv.com:8282/;stream.nsv
name: Inside Jazz
logo: https://raw.githubusercontent.com/home-assistant/assets/master/logo/logo-small.png
song: sensor.radio_inside_jazz
- url: http://stream.srg-ssr.ch/m/rsj/mp3_128
name: Radio Swiss Jazz
- url: http://stream.beachlatinoradio.com:8030/;?d=
name: Beach Latino Radio
- url: http://streams.calmradio.com/api/43/128/stream/;?d=
name: Calm Radio
- url: http://swr-swr1-bw.cast.addradio.de/swr/swr1/bw/mp3/128/stream.mp3
name: SWR 1
- url: http://94.23.252.14:8067/stream
name: Nature Sounds
entities:
- media_player.wuerfel_wohnzimmer
- media_player.wuerfel_kueche
Expand All @@ -75,21 +80,16 @@ Example config (note the differances from the above example):
type: "custom:jukebox-card"
links:
- url: http://streams.greenhost.nl:8080/jazz
name: Concertzender Jazz
name: Concertzender Jazz
logo: https://raw.githubusercontent.com/home-assistant/assets/master/logo/logo-small.png
song: sensor.radio_jazz
- url: http://fs-insidejazz.fast-serv.com:8282/;stream.nsv
name: Inside Jazz
name: Inside Jazz
logo: https://raw.githubusercontent.com/home-assistant/assets/master/logo/logo-small.png
song: sensor.radio_inside_jazz
- url: http://stream.srg-ssr.ch/m/rsj/mp3_128
name: Radio Swiss Jazz
- url: http://stream.beachlatinoradio.com:8030/;?d=
name: Beach Latino Radio
- url: http://streams.calmradio.com/api/43/128/stream/;?d=
name: Calm Radio
- url: http://swr-swr1-bw.cast.addradio.de/swr/swr1/bw/mp3/128/stream.mp3
name: SWR 1
- url: http://94.23.252.14:8067/stream
name: Nature Sounds
name: Radio Swiss Jazz
entities:
- media_player.wuerfel_wohnzimmer
- media_player.wuerfel_kueche
```
140 changes: 129 additions & 11 deletions jukebox-card.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
console.info(`%c HOME-ASSISTANT-JUKEBOX %c v2021_11_09_v1`, 'color: orange; font-weight: bold; background: black', 'color: white; font-weight: bold; background: dimgray');
class JukeboxCard extends HTMLElement {
set hass(hass) {
if (!this.content) {
Expand All @@ -10,6 +11,7 @@ class JukeboxCard extends HTMLElement {

this.content.appendChild(this.buildSpeakerSwitches(hass));
this.content.appendChild(this.buildVolumeSlider());
this.content.appendChild(this.buildSongDisplay());
this.content.appendChild(this.buildStationList());
}

Expand Down Expand Up @@ -49,7 +51,7 @@ class JukeboxCard extends HTMLElement {
stationList.classList.add('station-list');

this.config.links.forEach(linkCfg => {
const stationButton = this.buildStationSwitch(linkCfg.name, linkCfg.url)
const stationButton = this.buildStationSwitch(linkCfg.name, linkCfg.url, linkCfg.logo, linkCfg.song)
this._stationButtons.push(stationButton);
stationList.appendChild(stationButton);
});
Expand All @@ -60,6 +62,13 @@ class JukeboxCard extends HTMLElement {
return stationList;
}

buildSongDisplay() {
this._song = document.createElement('div');
this._song.className = 'song-content';
this._hassObservers.push(this.updateSongState.bind(this));
return this._song;
}

buildVolumeSlider() {
const volumeContainer = document.createElement('div');
volumeContainer.className = 'volume center horizontal layout';
Expand All @@ -68,6 +77,9 @@ class JukeboxCard extends HTMLElement {
muteButton.icon = 'hass:volume-high';
muteButton.isMute = false;
muteButton.addEventListener('click', this.onMuteUnmute.bind(this));
const muteButtonIcon = document.createElement('ha-icon');
muteButtonIcon.icon = 'hass:volume-high';
muteButton.appendChild(muteButtonIcon);

const slider = document.createElement('ha-slider');
slider.min = 0;
Expand All @@ -79,7 +91,17 @@ class JukeboxCard extends HTMLElement {
stopButton.icon = 'hass:stop';
stopButton.setAttribute('disabled', true);
stopButton.addEventListener('click', this.onStop.bind(this));

const stopButtonIcon = document.createElement('ha-icon')
stopButtonIcon.icon = 'hass:stop';
stopButton.appendChild(stopButtonIcon);

const powerButton = document.createElement('ha-icon-button')
powerButton.icon = 'hass:power';
powerButton.setAttribute('disabled', true);
powerButton.addEventListener('click', this.onPower.bind(this));
const powerButtonIcon = document.createElement('ha-icon')
powerButtonIcon.icon = 'hass:power';
powerButton.appendChild(powerButtonIcon);

this._hassObservers.push(hass => {
if (!this._selectedSpeaker || !hass.states[this._selectedSpeaker]) {
Expand All @@ -90,10 +112,14 @@ class JukeboxCard extends HTMLElement {
// no speaker level? then hide mute button and volume
if (!speakerState.hasOwnProperty('volume_level')) {
slider.setAttribute('hidden', true);
stopButton.setAttribute('hidden', true)
stopButton.setAttribute('hidden', true);
powerButton.setAttribute('hidden', true);
this._song.setAttribute('hidden', true);
} else {
slider.removeAttribute('hidden');
stopButton.removeAttribute('hidden')
stopButton.removeAttribute('hidden');
powerButton.removeAttribute('hidden');
this._song.removeAttribute('hidden');
}

if (!speakerState.hasOwnProperty('is_volume_muted')) {
Expand All @@ -104,6 +130,7 @@ class JukeboxCard extends HTMLElement {

if (hass.states[this._selectedSpeaker].state === 'playing') {
stopButton.removeAttribute('disabled');
powerButton.removeAttribute('disabled');
} else {
stopButton.setAttribute('disabled', true);
}
Expand All @@ -124,6 +151,7 @@ class JukeboxCard extends HTMLElement {
volumeContainer.appendChild(muteButton);
volumeContainer.appendChild(slider);
volumeContainer.appendChild(stopButton);
volumeContainer.appendChild(powerButton);
return volumeContainer;
}

Expand All @@ -149,42 +177,117 @@ class JukeboxCard extends HTMLElement {
this.hass.callService('media_player', 'media_stop', {
entity_id: this._selectedSpeaker
});

delete this._songEntity;
this._song.innerHTML = '';
}

onPower(e) {
this.hass.callService('media_player', 'turn_off', {
entity_id: this._selectedSpeaker
});

delete this._songEntity;
this._song.innerHTML = '';
}

updateStationSwitchStates(hass) {
let playingUrl = null;
const selectedSpeaker = this._selectedSpeaker;

if (hass.states[selectedSpeaker] && hass.states[selectedSpeaker].state === 'playing') {
if (hass.states[selectedSpeaker] && hass.states[selectedSpeaker].state === 'playing'){
playingUrl = hass.states[selectedSpeaker].attributes.media_content_id;
}

this._stationButtons.forEach(stationSwitch => {
if (stationSwitch.hasAttribute('raised') && stationSwitch.stationUrl !== playingUrl) {
this._stationButtons.forEach(stationSwitch =>
{
if (stationSwitch.hasAttribute('raised') && stationSwitch.stationUrl !== playingUrl)
{
stationSwitch.removeAttribute('raised');
return;
}
if (!stationSwitch.hasAttribute('raised') && stationSwitch.stationUrl === playingUrl) {
if (!stationSwitch.hasAttribute('raised') && stationSwitch.stationUrl === playingUrl)
{
stationSwitch.setAttribute('raised', true);

// Show song entity state for selected station if available
if (stationSwitch.stationSong)
this._songEntity = stationSwitch.stationSong;
}
})
}

buildStationSwitch(name, url) {
updateSongState(hass)
{
if (this._songEntity)
{
if (this._song.innerHTML != hass.states[this._songEntity].state)
{
this._song.innerHTML = hass.states[this._songEntity].state;
}
} else
{
this._song.innerHTML = '';
}
}

buildStationSwitch(name, url, logo, song) {
const btn = document.createElement('mwc-button');
btn.stationUrl = url;
btn.stationName = name;
btn.stationLogo = logo;
btn.stationSong = song;
btn.className = 'juke-toggle';
btn.innerText = name;
btn.addEventListener('click', this.onStationSelect.bind(this));
return btn;
}

onStationSelect(e) {
onStationSelect(e) {
delete this._songEntity;
this._song.innerHTML = '';

/*
// If there is a song entity, display it, otherwise clear it
if (e.currentTarget.stationSong)
{
this._song.innerHTML = this.hass.states[e.currentTarget.stationSong].state;
this._songEntity = e.currentTarget.stationSong;
} else
{
delete this._songEntity;
this._song.innerHTML = '';
}
*/

this.hass.callService('media_player', 'play_media', {
entity_id: this._selectedSpeaker,
media_content_id: e.currentTarget.stationUrl,
media_content_type: 'audio/mp4'
media_content_type: 'music',
extra: {
metadata: {
stream_type: "LIVE",
metadataType: 3,
title: e.currentTarget.stationName,
artist: "Live Radio",
images: [
{ url: e.currentTarget.stationLogo }
]
}
}
});

// Force play for 10 seconds every half a second
var that = this;
var i = 0;
for (i = 500; i <= 5000; i=i+500)
{
setTimeout(function() {
that.hass.callService('media_player', 'media_play', {
entity_id: that._selectedSpeaker
}); }, i);
}

}

setVolume(value) {
Expand Down Expand Up @@ -228,6 +331,15 @@ class JukeboxCard extends HTMLElement {
}
}

function pauseBrowser(millis)
{
var date = Date.now();
var curDate = null;
do {
curDate = Date.now();
} while (curDate-date < millis);
}

function getStyle() {
const frag = document.createDocumentFragment();

Expand Down Expand Up @@ -269,6 +381,12 @@ function getStyle() {
.volume {
padding: 10px 20px;
}
.song-content {
text-align: center;
color: green;
font-weight: bold;
}
mwc-button.juke-toggle {
--mdc-theme-primary: var(--primary-text-color);
Expand Down
Binary file modified screenshot.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit e90402b

Please sign in to comment.