Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions src/data/media-player.ts
Original file line number Diff line number Diff line change
Expand Up @@ -360,3 +360,17 @@ export const cleanupMediaTitle = (title?: string): string | undefined => {
const index = title.indexOf("?authSig=");
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 });
11 changes: 10 additions & 1 deletion src/panels/media-browser/browser-media-player.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
MediaPlayerItem,
SUPPORT_PAUSE,
SUPPORT_PLAY,
SUPPORT_VOLUME_SET,
} from "../../data/media-player";
import { ResolvedMediaSource } from "../../data/media_source";
import { HomeAssistant } from "../../types";
Expand All @@ -20,9 +21,11 @@ export class BrowserMediaPlayer {
public hass: HomeAssistant,
public item: MediaPlayerItem,
public resolved: ResolvedMediaSource,
volume: number,
private onChange: () => void
) {
const player = new Audio(this.resolved.url);
player.volume = volume;
player.addEventListener("play", this._handleChange);
player.addEventListener("playing", () => {
this.buffering = false;
Expand Down Expand Up @@ -57,6 +60,11 @@ export class BrowserMediaPlayer {
this.player.play();
}

public setVolume(volume: number) {
this.player.volume = volume;
this.onChange();
}

public remove() {
this._removed = true;
// @ts-ignore
Expand Down Expand Up @@ -89,8 +97,9 @@ export class BrowserMediaPlayer {
base.attributes = {
media_title: this.item.title,
entity_picture: this.item.thumbnail,
volume_level: this.player.volume,
// 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) {
Expand Down
42 changes: 40 additions & 2 deletions src/panels/media-browser/ha-bar-media-player.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
mdiPlay,
mdiPlayPause,
mdiStop,
mdiVolumeHigh,
} from "@mdi/js";
import {
css,
Expand Down Expand Up @@ -40,10 +41,12 @@ import {
getCurrentProgress,
MediaPlayerEntity,
MediaPlayerItem,
setMediaPlayerVolume,
SUPPORT_BROWSE_MEDIA,
SUPPORT_PAUSE,
SUPPORT_PLAY,
SUPPORT_STOP,
SUPPORT_VOLUME_SET,
} from "../../data/media-player";
import { ResolvedMediaSource } from "../../data/media_source";
import type { HomeAssistant } from "../../types";
Expand Down Expand Up @@ -77,6 +80,8 @@ export class BarMediaPlayer extends LitElement {

private _progressInterval?: number;

private _browserPlayerVolume = 0.8;

public connectedCallback(): void {
super.connectedCallback();

Expand Down Expand Up @@ -124,6 +129,7 @@ export class BarMediaPlayer extends LitElement {
this.hass,
item,
resolved,
this._browserPlayerVolume,
() => this.requestUpdate("_browserPlayer")
);
this._newMediaExpected = false;
Expand Down Expand Up @@ -230,7 +236,7 @@ export class BarMediaPlayer extends LitElement {
)}
.path=${control.icon}
action=${control.action}
@click=${this._handleClick}
@click=${this._handleControlClick}
>
</ha-icon-button>
`
Expand All @@ -257,6 +263,27 @@ export class BarMediaPlayer extends LitElement {
const isBrowser = this.entityId === BROWSER_PLAYER;
return html`
<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">
${
this.narrow
Expand Down Expand Up @@ -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")!;

if (!this._browserPlayer) {
Expand Down Expand Up @@ -474,6 +501,17 @@ export class BarMediaPlayer extends LitElement {
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 {
return css`
:host {
Expand Down