Add play/pause event support.

This commit is contained in:
Dermot Duffy
2021-09-23 23:10:30 -07:00
parent 1ff0cdf621
commit 3d22dcb686
3 changed files with 55 additions and 42 deletions
+16 -33
View File
@@ -106,8 +106,8 @@ export class FrigateCard extends LitElement {
@query('frigate-card-menu') @query('frigate-card-menu')
_menu!: FrigateCardMenu; _menu!: FrigateCardMenu;
// Whether or not there is an active clip being played. // Whether or not media is actively playing (live or clip).
protected _clipPlaying = false; protected _mediaPlaying = false;
// A small cache to avoid needing to create a new list of entities every time // A small cache to avoid needing to create a new list of entities every time
// a hass update arrives. // a hass update arrives.
@@ -253,7 +253,7 @@ export class FrigateCard extends LitElement {
// are browsing the mini-gallery). Do not allow re-rendering from a Home // are browsing the mini-gallery). Do not allow re-rendering from a Home
// Assistant update if there's been recent interaction (e.g. clicks on the // Assistant update if there's been recent interaction (e.g. clicks on the
// card) or if there is a clip active playing. // card) or if there is a clip active playing.
if (this._interactionTimerID || this._clipPlaying) { if (this._interactionTimerID || this._mediaPlaying) {
return false; return false;
} }
return shouldUpdateBasedOnHass(this._hass, oldHass, this._entitiesToMonitor); return shouldUpdateBasedOnHass(this._hass, oldHass, this._entitiesToMonitor);
@@ -294,35 +294,6 @@ export class FrigateCard extends LitElement {
return `${this.config.frigate_url}/events?camera=${this.config.frigate_camera_name}`; return `${this.config.frigate_url}/events?camera=${this.config.frigate_camera_name}`;
} }
public updated(): void {
this.updateComplete.then(() => {
// DOM elements are not always present until after updateComplete promise
// is resolved. Note that children of children (i.e. the underlying video
// element) is not always present even when the promise returns, so
// capture the event at the upper shadow root instead.
const hls_player = this.renderRoot
?.querySelector('ha-card')
?.querySelector('ha-hls-player');
if (hls_player) {
hls_player.shadowRoot?.addEventListener(
'play',
() => {
this._clipPlaying = true;
},
true,
);
hls_player.shadowRoot?.addEventListener(
'pause',
() => {
this._clipPlaying = true;
},
true,
);
}
});
}
// Record interactions with the card. // Record interactions with the card.
protected _interactionHandler(): void { protected _interactionHandler(): void {
if (!this.config.view_timeout) { if (!this.config.view_timeout) {
@@ -363,6 +334,14 @@ export class FrigateCard extends LitElement {
zone: this.config.zone, zone: this.config.zone,
}; };
} }
protected _playHandler(): void {
this._mediaPlaying = true;
}
protected _pauseHandler(): void {
this._mediaPlaying = false;
}
protected _mediaLoadHandler(e: CustomEvent<MediaLoadInfo>): void { protected _mediaLoadHandler(e: CustomEvent<MediaLoadInfo>): void {
const mediaInfo = e.detail; const mediaInfo = e.detail;
@@ -461,7 +440,9 @@ export class FrigateCard extends LitElement {
.autoplayClip=${this.config.autoplay_clip} .autoplayClip=${this.config.autoplay_clip}
@frigate-card:change-view=${this._changeViewHandler} @frigate-card:change-view=${this._changeViewHandler}
@frigate-card:media-load=${this._mediaLoadHandler} @frigate-card:media-load=${this._mediaLoadHandler}
> @frigate-card:pause=${this._pauseHandler}
@frigate-card:play=${this._playHandler}
>
</frigate-card-viewer>` </frigate-card-viewer>`
: ``} : ``}
${this._view.is('live') ${this._view.is('live')
@@ -469,6 +450,8 @@ export class FrigateCard extends LitElement {
.hass=${this._hass} .hass=${this._hass}
.config=${this.config} .config=${this.config}
@frigate-card:media-load=${this._mediaLoadHandler} @frigate-card:media-load=${this._mediaLoadHandler}
@frigate-card:pause=${this._pauseHandler}
@frigate-card:play=${this._playHandler}
> >
</frigate-card-live>` </frigate-card-live>`
: ``} : ``}
+36 -8
View File
@@ -7,7 +7,12 @@ import { signedPathSchema } from '../types';
import type { ExtendedHomeAssistant, FrigateCardConfig } from '../types'; import type { ExtendedHomeAssistant, FrigateCardConfig } from '../types';
import { localize } from '../localize/localize'; import { localize } from '../localize/localize';
import { dispatchMediaLoadEvent, homeAssistantWSRequest } from '../common'; import {
dispatchMediaLoadEvent,
dispatchPauseEvent,
dispatchPlayEvent,
homeAssistantWSRequest,
} from '../common';
import { import {
renderMessage, renderMessage,
renderErrorMessage, renderErrorMessage,
@@ -95,7 +100,6 @@ export class FrigateCardViewerWebRTC extends LitElement {
protected _webRTCElement: HTMLElement | null = null; protected _webRTCElement: HTMLElement | null = null;
protected _createWebRTC(): TemplateResult | void { protected _createWebRTC(): TemplateResult | void {
// eslint-disable-next-line @typescript-eslint/no-explicit-any // eslint-disable-next-line @typescript-eslint/no-explicit-any
const webrtcElement = customElements.get('webrtc-camera') as any; const webrtcElement = customElements.get('webrtc-camera') as any;
if (webrtcElement) { if (webrtcElement) {
@@ -125,11 +129,30 @@ export class FrigateCardViewerWebRTC extends LitElement {
this.updateComplete.then(() => { this.updateComplete.then(() => {
const video = this.renderRoot.querySelector('#video') as HTMLVideoElement; const video = this.renderRoot.querySelector('#video') as HTMLVideoElement;
if (video) { if (video) {
video.onloadedmetadata = () => { const onloadedmetadata = video.onloadedmetadata;
const onplay = video.onplay;
const onpause = video.onpause;
video.onloadedmetadata = (e) => {
if (onloadedmetadata) {
onloadedmetadata.call(video, e);
}
dispatchMediaLoadEvent(this, video); dispatchMediaLoadEvent(this, video);
} };
video.onplay = (e) => {
if (onplay) {
onplay.call(video, e);
}
dispatchPlayEvent(this);
};
video.onpause = (e) => {
if (onpause) {
onpause.call(video, e);
}
dispatchPauseEvent(this);
};
} }
}) });
} }
static get styles(): CSSResultGroup { static get styles(): CSSResultGroup {
@@ -212,11 +235,16 @@ export class FrigateCardViewerJSMPEG extends LitElement {
// amount of time the canvas is empty (and show the spinner // amount of time the canvas is empty (and show the spinner
// instead). // instead).
play: () => { play: () => {
dispatchPlayEvent(this);
resolve(html`${this._jsmpegCanvasElement}`); resolve(html`${this._jsmpegCanvasElement}`);
}, },
pause: () => {
dispatchPauseEvent(this);
},
}, },
}, },
{ protocols: [], {
protocols: [],
videoBufferSize: 1024 * 1024 * 4, videoBufferSize: 1024 * 1024 * 4,
onVideoDecode: () => { onVideoDecode: () => {
// This is the only callback that is called after the dimensions // This is the only callback that is called after the dimensions
@@ -226,8 +254,8 @@ export class FrigateCardViewerJSMPEG extends LitElement {
videoDecoded = true; videoDecoded = true;
dispatchMediaLoadEvent(this, this._jsmpegCanvasElement); dispatchMediaLoadEvent(this, this._jsmpegCanvasElement);
} }
} },
}, },
); );
}); });
} }
+3 -1
View File
@@ -14,7 +14,7 @@ import {
html, html,
} from 'lit'; } from 'lit';
import { customElement } from 'lit/decorators'; import { customElement } from 'lit/decorators';
import { dispatchMediaLoadEvent } from '../common'; import { dispatchMediaLoadEvent, dispatchPauseEvent, dispatchPlayEvent } from '../common';
customElements.whenDefined("ha-hls-player").then(() => { customElements.whenDefined("ha-hls-player").then(() => {
@customElement("frigate-card-ha-hls-player") @customElement("frigate-card-ha-hls-player")
@@ -33,6 +33,8 @@ customElements.whenDefined("ha-hls-player").then(() => {
?controls=${this.controls} ?controls=${this.controls}
@loadedmetadata=${(e) => dispatchMediaLoadEvent(this, e)} @loadedmetadata=${(e) => dispatchMediaLoadEvent(this, e)}
@loadeddata=${this._elementResized} @loadeddata=${this._elementResized}
@pause=${() => dispatchPauseEvent(this)}
@play=${() => dispatchPlayEvent(this)}
></video> ></video>
`; `;
} }