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')
_menu!: FrigateCardMenu;
// Whether or not there is an active clip being played.
protected _clipPlaying = false;
// Whether or not media is actively playing (live or clip).
protected _mediaPlaying = false;
// A small cache to avoid needing to create a new list of entities every time
// 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
// Assistant update if there's been recent interaction (e.g. clicks on the
// card) or if there is a clip active playing.
if (this._interactionTimerID || this._clipPlaying) {
if (this._interactionTimerID || this._mediaPlaying) {
return false;
}
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}`;
}
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.
protected _interactionHandler(): void {
if (!this.config.view_timeout) {
@@ -364,6 +335,14 @@ export class FrigateCard extends LitElement {
};
}
protected _playHandler(): void {
this._mediaPlaying = true;
}
protected _pauseHandler(): void {
this._mediaPlaying = false;
}
protected _mediaLoadHandler(e: CustomEvent<MediaLoadInfo>): void {
const mediaInfo = e.detail;
@@ -461,7 +440,9 @@ export class FrigateCard extends LitElement {
.autoplayClip=${this.config.autoplay_clip}
@frigate-card:change-view=${this._changeViewHandler}
@frigate-card:media-load=${this._mediaLoadHandler}
>
@frigate-card:pause=${this._pauseHandler}
@frigate-card:play=${this._playHandler}
>
</frigate-card-viewer>`
: ``}
${this._view.is('live')
@@ -469,6 +450,8 @@ export class FrigateCard extends LitElement {
.hass=${this._hass}
.config=${this.config}
@frigate-card:media-load=${this._mediaLoadHandler}
@frigate-card:pause=${this._pauseHandler}
@frigate-card:play=${this._playHandler}
>
</frigate-card-live>`
: ``}
+36 -8
View File
@@ -7,7 +7,12 @@ import { signedPathSchema } from '../types';
import type { ExtendedHomeAssistant, FrigateCardConfig } from '../types';
import { localize } from '../localize/localize';
import { dispatchMediaLoadEvent, homeAssistantWSRequest } from '../common';
import {
dispatchMediaLoadEvent,
dispatchPauseEvent,
dispatchPlayEvent,
homeAssistantWSRequest,
} from '../common';
import {
renderMessage,
renderErrorMessage,
@@ -95,7 +100,6 @@ export class FrigateCardViewerWebRTC extends LitElement {
protected _webRTCElement: HTMLElement | null = null;
protected _createWebRTC(): TemplateResult | void {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const webrtcElement = customElements.get('webrtc-camera') as any;
if (webrtcElement) {
@@ -125,11 +129,30 @@ export class FrigateCardViewerWebRTC extends LitElement {
this.updateComplete.then(() => {
const video = this.renderRoot.querySelector('#video') as HTMLVideoElement;
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);
}
};
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 {
@@ -212,11 +235,16 @@ export class FrigateCardViewerJSMPEG extends LitElement {
// amount of time the canvas is empty (and show the spinner
// instead).
play: () => {
dispatchPlayEvent(this);
resolve(html`${this._jsmpegCanvasElement}`);
},
pause: () => {
dispatchPauseEvent(this);
},
},
},
{ protocols: [],
{
protocols: [],
videoBufferSize: 1024 * 1024 * 4,
onVideoDecode: () => {
// This is the only callback that is called after the dimensions
@@ -226,8 +254,8 @@ export class FrigateCardViewerJSMPEG extends LitElement {
videoDecoded = true;
dispatchMediaLoadEvent(this, this._jsmpegCanvasElement);
}
}
},
},
},
);
});
}
+3 -1
View File
@@ -14,7 +14,7 @@ import {
html,
} from 'lit';
import { customElement } from 'lit/decorators';
import { dispatchMediaLoadEvent } from '../common';
import { dispatchMediaLoadEvent, dispatchPauseEvent, dispatchPlayEvent } from '../common';
customElements.whenDefined("ha-hls-player").then(() => {
@customElement("frigate-card-ha-hls-player")
@@ -33,6 +33,8 @@ customElements.whenDefined("ha-hls-player").then(() => {
?controls=${this.controls}
@loadedmetadata=${(e) => dispatchMediaLoadEvent(this, e)}
@loadeddata=${this._elementResized}
@pause=${() => dispatchPauseEvent(this)}
@play=${() => dispatchPlayEvent(this)}
></video>
`;
}