mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-12 03:46:34 +00:00
Allow changing volume media player entity (#11781)
Co-authored-by: Zack Barett <zackbarett@hey.com>
This commit is contained in:
parent
f5b5414461
commit
5335772a7a
@ -360,3 +360,17 @@ export const cleanupMediaTitle = (title?: string): string | undefined => {
|
|||||||
const index = title.indexOf("?authSig=");
|
const index = title.indexOf("?authSig=");
|
||||||
return index > 0 ? title.slice(0, index) : title;
|
return index > 0 ? title.slice(0, index) : title;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set volume of a media player entity.
|
||||||
|
* @param hass Home Assistant object
|
||||||
|
* @param entity_id entity ID of media player
|
||||||
|
* @param volume_level number between 0..1
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export const setMediaPlayerVolume = (
|
||||||
|
hass: HomeAssistant,
|
||||||
|
entity_id: string,
|
||||||
|
volume_level: number
|
||||||
|
) =>
|
||||||
|
hass.callService("media_player", "volume_set", { entity_id, volume_level });
|
||||||
|
@ -4,6 +4,7 @@ import {
|
|||||||
MediaPlayerItem,
|
MediaPlayerItem,
|
||||||
SUPPORT_PAUSE,
|
SUPPORT_PAUSE,
|
||||||
SUPPORT_PLAY,
|
SUPPORT_PLAY,
|
||||||
|
SUPPORT_VOLUME_SET,
|
||||||
} from "../../data/media-player";
|
} from "../../data/media-player";
|
||||||
import { ResolvedMediaSource } from "../../data/media_source";
|
import { ResolvedMediaSource } from "../../data/media_source";
|
||||||
import { HomeAssistant } from "../../types";
|
import { HomeAssistant } from "../../types";
|
||||||
@ -20,9 +21,11 @@ export class BrowserMediaPlayer {
|
|||||||
public hass: HomeAssistant,
|
public hass: HomeAssistant,
|
||||||
public item: MediaPlayerItem,
|
public item: MediaPlayerItem,
|
||||||
public resolved: ResolvedMediaSource,
|
public resolved: ResolvedMediaSource,
|
||||||
|
volume: number,
|
||||||
private onChange: () => void
|
private onChange: () => void
|
||||||
) {
|
) {
|
||||||
const player = new Audio(this.resolved.url);
|
const player = new Audio(this.resolved.url);
|
||||||
|
player.volume = volume;
|
||||||
player.addEventListener("play", this._handleChange);
|
player.addEventListener("play", this._handleChange);
|
||||||
player.addEventListener("playing", () => {
|
player.addEventListener("playing", () => {
|
||||||
this.buffering = false;
|
this.buffering = false;
|
||||||
@ -57,6 +60,11 @@ export class BrowserMediaPlayer {
|
|||||||
this.player.play();
|
this.player.play();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public setVolume(volume: number) {
|
||||||
|
this.player.volume = volume;
|
||||||
|
this.onChange();
|
||||||
|
}
|
||||||
|
|
||||||
public remove() {
|
public remove() {
|
||||||
this._removed = true;
|
this._removed = true;
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
@ -89,8 +97,9 @@ export class BrowserMediaPlayer {
|
|||||||
base.attributes = {
|
base.attributes = {
|
||||||
media_title: this.item.title,
|
media_title: this.item.title,
|
||||||
entity_picture: this.item.thumbnail,
|
entity_picture: this.item.thumbnail,
|
||||||
|
volume_level: this.player.volume,
|
||||||
// eslint-disable-next-line no-bitwise
|
// eslint-disable-next-line no-bitwise
|
||||||
supported_features: SUPPORT_PLAY | SUPPORT_PAUSE,
|
supported_features: SUPPORT_PLAY | SUPPORT_PAUSE | SUPPORT_VOLUME_SET,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (this.player.duration) {
|
if (this.player.duration) {
|
||||||
|
@ -9,6 +9,7 @@ import {
|
|||||||
mdiPlay,
|
mdiPlay,
|
||||||
mdiPlayPause,
|
mdiPlayPause,
|
||||||
mdiStop,
|
mdiStop,
|
||||||
|
mdiVolumeHigh,
|
||||||
} from "@mdi/js";
|
} from "@mdi/js";
|
||||||
import {
|
import {
|
||||||
css,
|
css,
|
||||||
@ -40,10 +41,12 @@ import {
|
|||||||
getCurrentProgress,
|
getCurrentProgress,
|
||||||
MediaPlayerEntity,
|
MediaPlayerEntity,
|
||||||
MediaPlayerItem,
|
MediaPlayerItem,
|
||||||
|
setMediaPlayerVolume,
|
||||||
SUPPORT_BROWSE_MEDIA,
|
SUPPORT_BROWSE_MEDIA,
|
||||||
SUPPORT_PAUSE,
|
SUPPORT_PAUSE,
|
||||||
SUPPORT_PLAY,
|
SUPPORT_PLAY,
|
||||||
SUPPORT_STOP,
|
SUPPORT_STOP,
|
||||||
|
SUPPORT_VOLUME_SET,
|
||||||
} from "../../data/media-player";
|
} from "../../data/media-player";
|
||||||
import { ResolvedMediaSource } from "../../data/media_source";
|
import { ResolvedMediaSource } from "../../data/media_source";
|
||||||
import type { HomeAssistant } from "../../types";
|
import type { HomeAssistant } from "../../types";
|
||||||
@ -77,6 +80,8 @@ export class BarMediaPlayer extends LitElement {
|
|||||||
|
|
||||||
private _progressInterval?: number;
|
private _progressInterval?: number;
|
||||||
|
|
||||||
|
private _browserPlayerVolume = 0.8;
|
||||||
|
|
||||||
public connectedCallback(): void {
|
public connectedCallback(): void {
|
||||||
super.connectedCallback();
|
super.connectedCallback();
|
||||||
|
|
||||||
@ -124,6 +129,7 @@ export class BarMediaPlayer extends LitElement {
|
|||||||
this.hass,
|
this.hass,
|
||||||
item,
|
item,
|
||||||
resolved,
|
resolved,
|
||||||
|
this._browserPlayerVolume,
|
||||||
() => this.requestUpdate("_browserPlayer")
|
() => this.requestUpdate("_browserPlayer")
|
||||||
);
|
);
|
||||||
this._newMediaExpected = false;
|
this._newMediaExpected = false;
|
||||||
@ -230,7 +236,7 @@ export class BarMediaPlayer extends LitElement {
|
|||||||
)}
|
)}
|
||||||
.path=${control.icon}
|
.path=${control.icon}
|
||||||
action=${control.action}
|
action=${control.action}
|
||||||
@click=${this._handleClick}
|
@click=${this._handleControlClick}
|
||||||
>
|
>
|
||||||
</ha-icon-button>
|
</ha-icon-button>
|
||||||
`
|
`
|
||||||
@ -257,6 +263,27 @@ export class BarMediaPlayer extends LitElement {
|
|||||||
const isBrowser = this.entityId === BROWSER_PLAYER;
|
const isBrowser = this.entityId === BROWSER_PLAYER;
|
||||||
return html`
|
return html`
|
||||||
<div class="choose-player ${isBrowser ? "browser" : ""}">
|
<div class="choose-player ${isBrowser ? "browser" : ""}">
|
||||||
|
${
|
||||||
|
stateObj && supportsFeature(stateObj, SUPPORT_VOLUME_SET)
|
||||||
|
? html`
|
||||||
|
<ha-button-menu corner="BOTTOM_START">
|
||||||
|
<ha-icon-button
|
||||||
|
slot="trigger"
|
||||||
|
.path=${mdiVolumeHigh}
|
||||||
|
></ha-icon-button>
|
||||||
|
<ha-slider
|
||||||
|
min="0"
|
||||||
|
max="100"
|
||||||
|
step="1"
|
||||||
|
.value=${stateObj.attributes.volume_level! * 100}
|
||||||
|
@change=${this._handleVolumeChange}
|
||||||
|
>
|
||||||
|
</ha-slider>
|
||||||
|
</ha-button-menu>
|
||||||
|
`
|
||||||
|
: ""
|
||||||
|
}
|
||||||
|
|
||||||
<ha-button-menu corner="BOTTOM_START">
|
<ha-button-menu corner="BOTTOM_START">
|
||||||
${
|
${
|
||||||
this.narrow
|
this.narrow
|
||||||
@ -441,7 +468,7 @@ export class BarMediaPlayer extends LitElement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private _handleClick(e: MouseEvent): void {
|
private _handleControlClick(e: MouseEvent): void {
|
||||||
const action = (e.currentTarget! as HTMLElement).getAttribute("action")!;
|
const action = (e.currentTarget! as HTMLElement).getAttribute("action")!;
|
||||||
|
|
||||||
if (!this._browserPlayer) {
|
if (!this._browserPlayer) {
|
||||||
@ -474,6 +501,17 @@ export class BarMediaPlayer extends LitElement {
|
|||||||
fireEvent(this, "player-picked", { entityId });
|
fireEvent(this, "player-picked", { entityId });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async _handleVolumeChange(ev) {
|
||||||
|
ev.stopPropagation();
|
||||||
|
const value = Number(ev.target.value) / 100;
|
||||||
|
if (this._browserPlayer) {
|
||||||
|
this._browserPlayerVolume = value;
|
||||||
|
this._browserPlayer.setVolume(value);
|
||||||
|
} else {
|
||||||
|
await setMediaPlayerVolume(this.hass, this.entityId, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static get styles(): CSSResultGroup {
|
static get styles(): CSSResultGroup {
|
||||||
return css`
|
return css`
|
||||||
:host {
|
:host {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user