@@ -19,7 +19,12 @@ import { CameraConfig, ImageMode, ImageViewConfig } from '../config/types.js';
|
||||
import defaultImage from '../images/frigate-bird-in-sky.jpg';
|
||||
import { localize } from '../localize/localize.js';
|
||||
import imageStyle from '../scss/image.scss';
|
||||
import { FrigateCardMediaPlayer, MediaLoadedInfo, Message } from '../types.js';
|
||||
import {
|
||||
FrigateCardMediaPlayer,
|
||||
FullscreenElement,
|
||||
MediaLoadedInfo,
|
||||
Message,
|
||||
} from '../types.js';
|
||||
import { contentsChanged } from '../utils/basic.js';
|
||||
import { isHassDifferent } from '../utils/ha/index.js';
|
||||
import {
|
||||
@@ -123,6 +128,10 @@ export class FrigateCardImageBase extends LitElement implements FrigateCardMedia
|
||||
return this._cachedValueController?.value ?? null;
|
||||
}
|
||||
|
||||
public getFullscreenElement(): FullscreenElement | null {
|
||||
return this._refImage.value ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the element should be updated.
|
||||
* @param changedProps The changed properties if any.
|
||||
|
||||
@@ -17,7 +17,7 @@ import { handleZoomSettingsObservedEvent } from '../components-lib/zoom/zoom-vie
|
||||
import { CameraConfig, ImageViewConfig } from '../config/types';
|
||||
import { IMAGE_VIEW_ZOOM_TARGET_SENTINEL } from '../const';
|
||||
import basicBlockStyle from '../scss/basic-block.scss';
|
||||
import { FrigateCardMediaPlayer } from '../types.js';
|
||||
import { FrigateCardMediaPlayer, FullscreenElement } from '../types.js';
|
||||
import { aspectRatioToString } from '../utils/basic';
|
||||
import { updateElementStyleFromMediaLayoutConfig } from '../utils/media-layout.js';
|
||||
import './image-base';
|
||||
@@ -79,6 +79,10 @@ export class FrigateCardImage extends LitElement implements FrigateCardMediaPlay
|
||||
return (await this._refImage.value?.getScreenshotURL()) ?? null;
|
||||
}
|
||||
|
||||
public getFullscreenElement(): FullscreenElement | null {
|
||||
return this._refImage.value?.getFullscreenElement() ?? null;
|
||||
}
|
||||
|
||||
protected willUpdate(changedProps: PropertyValues): void {
|
||||
if (changedProps.has('cameraConfig') || changedProps.has('imageConfig')) {
|
||||
if (
|
||||
|
||||
@@ -24,7 +24,11 @@ import {
|
||||
import { STREAM_TROUBLESHOOTING_URL } from '../../const.js';
|
||||
import { localize } from '../../localize/localize.js';
|
||||
import liveProviderStyle from '../../scss/live-provider.scss';
|
||||
import { ExtendedHomeAssistant, FrigateCardMediaPlayer } from '../../types.js';
|
||||
import {
|
||||
ExtendedHomeAssistant,
|
||||
FrigateCardMediaPlayer,
|
||||
FullscreenElement,
|
||||
} from '../../types.js';
|
||||
import { aspectRatioToString } from '../../utils/basic.js';
|
||||
import { dispatchMediaUnloadedEvent } from '../../utils/media-info.js';
|
||||
import { updateElementStyleFromMediaLayoutConfig } from '../../utils/media-layout.js';
|
||||
@@ -144,6 +148,10 @@ export class FrigateCardLiveProvider
|
||||
return (await this._refProvider.value?.getScreenshotURL()) ?? null;
|
||||
}
|
||||
|
||||
public getFullscreenElement(): FullscreenElement | null {
|
||||
return this._refProvider.value?.getFullscreenElement() ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the fully resolved live provider.
|
||||
* @returns A live provider (that is not 'auto').
|
||||
|
||||
@@ -16,6 +16,7 @@ import liveGo2RTCStyle from '../../../../scss/live-go2rtc.scss';
|
||||
import {
|
||||
ExtendedHomeAssistant,
|
||||
FrigateCardMediaPlayer,
|
||||
FullscreenElement,
|
||||
Message,
|
||||
} from '../../../../types.js';
|
||||
import { convertEndpointAddressToSignedWebsocket } from '../../../../utils/endpoint.js';
|
||||
@@ -102,6 +103,10 @@ export class FrigateCardGo2RTC extends LitElement implements FrigateCardMediaPla
|
||||
return this._player?.video ? screenshotMedia(this._player.video) : null;
|
||||
}
|
||||
|
||||
public getFullscreenElement(): FullscreenElement | null {
|
||||
return this._player?.video ?? null;
|
||||
}
|
||||
|
||||
disconnectedCallback(): void {
|
||||
this._player = undefined;
|
||||
this._message = null;
|
||||
@@ -151,7 +156,7 @@ export class FrigateCardGo2RTC extends LitElement implements FrigateCardMediaPla
|
||||
this._player.microphoneStream = this.microphoneState?.stream ?? null;
|
||||
this._player.src = address;
|
||||
this._player.visibilityCheck = false;
|
||||
this._player.controls = this.controls;
|
||||
this._player.setControls(this.controls);
|
||||
|
||||
if (this.cameraConfig?.go2rtc?.modes && this.cameraConfig.go2rtc.modes.length) {
|
||||
this._player.mode = this.cameraConfig.go2rtc.modes.join(',');
|
||||
@@ -170,7 +175,7 @@ export class FrigateCardGo2RTC extends LitElement implements FrigateCardMediaPla
|
||||
}
|
||||
|
||||
if (changedProps.has('controls') && this._player) {
|
||||
this._player.controls = this.controls;
|
||||
this._player.setControls(this.controls);
|
||||
}
|
||||
|
||||
if (
|
||||
|
||||
+2
-1
@@ -29,8 +29,9 @@ export class VideoRTC extends HTMLElement {
|
||||
onmessage: Record<string, (msg: { type: string; value: string }) => void>;
|
||||
|
||||
// Custom methods/members.
|
||||
controls: boolean;
|
||||
containingPlayer: FrigateCardMediaPlayer | null;
|
||||
microphoneStream: MediaStream | null;
|
||||
reconnect();
|
||||
|
||||
setControls(controls: boolean): void;
|
||||
}
|
||||
|
||||
@@ -168,7 +168,7 @@ export class VideoRTC extends HTMLElement {
|
||||
this.containingPlayer = null;
|
||||
|
||||
/**
|
||||
* Whether to show or hide video controls.
|
||||
* Whether to show or hide video controls for videos created in future.
|
||||
* @type {boolean}}
|
||||
*/
|
||||
this.controls = true;
|
||||
@@ -191,6 +191,15 @@ export class VideoRTC extends HTMLElement {
|
||||
}
|
||||
}
|
||||
|
||||
setControls(controls) {
|
||||
this.controls = controls;
|
||||
|
||||
// If the video already exists the controls won't be changed by default.
|
||||
if (this.video) {
|
||||
setControlsOnVideo(this.video, controls);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set video source (WebSocket URL). Support relative path.
|
||||
* @param {string|URL} value
|
||||
|
||||
@@ -7,7 +7,7 @@ import '../../../patches/ha-camera-stream';
|
||||
import '../../../patches/ha-hls-player.js';
|
||||
import '../../../patches/ha-web-rtc-player.js';
|
||||
import liveHAStyle from '../../../scss/live-ha.scss';
|
||||
import { FrigateCardMediaPlayer } from '../../../types.js';
|
||||
import { FrigateCardMediaPlayer, FullscreenElement } from '../../../types.js';
|
||||
|
||||
@customElement('frigate-card-live-ha')
|
||||
export class FrigateCardLiveHA extends LitElement implements FrigateCardMediaPlayer {
|
||||
@@ -58,6 +58,10 @@ export class FrigateCardLiveHA extends LitElement implements FrigateCardMediaPla
|
||||
return (await this._playerRef.value?.getScreenshotURL()) ?? null;
|
||||
}
|
||||
|
||||
public getFullscreenElement(): FullscreenElement | null {
|
||||
return this._playerRef.value?.getFullscreenElement() ?? null;
|
||||
}
|
||||
|
||||
protected render(): TemplateResult | void {
|
||||
if (!this.hass) {
|
||||
return;
|
||||
|
||||
@@ -4,7 +4,7 @@ import { customElement, property } from 'lit/decorators.js';
|
||||
import { createRef, ref, Ref } from 'lit/directives/ref.js';
|
||||
import { CameraConfig } from '../../../config/types';
|
||||
import basicBlockStyle from '../../../scss/basic-block.scss';
|
||||
import { FrigateCardMediaPlayer } from '../../../types.js';
|
||||
import { FrigateCardMediaPlayer, FullscreenElement } from '../../../types.js';
|
||||
import '../../image-base.js';
|
||||
|
||||
@customElement('frigate-card-live-image')
|
||||
@@ -53,6 +53,10 @@ export class FrigateCardLiveImage extends LitElement implements FrigateCardMedia
|
||||
return (await this._refImage.value?.getScreenshotURL()) ?? null;
|
||||
}
|
||||
|
||||
public getFullscreenElement(): FullscreenElement | null {
|
||||
return this._refImage.value?.getFullscreenElement() ?? null;
|
||||
}
|
||||
|
||||
protected render(): TemplateResult | void {
|
||||
if (!this.hass || !this.cameraConfig) {
|
||||
return;
|
||||
|
||||
@@ -17,6 +17,7 @@ import liveJSMPEGStyle from '../../../scss/live-jsmpeg.scss';
|
||||
import {
|
||||
ExtendedHomeAssistant,
|
||||
FrigateCardMediaPlayer,
|
||||
FullscreenElement,
|
||||
Message,
|
||||
} from '../../../types.js';
|
||||
import { convertEndpointAddressToSignedWebsocket } from '../../../utils/endpoint.js';
|
||||
@@ -101,6 +102,10 @@ export class FrigateCardLiveJSMPEG extends LitElement implements FrigateCardMedi
|
||||
return this._jsmpegCanvasElement?.toDataURL('image/jpeg') ?? null;
|
||||
}
|
||||
|
||||
public getFullscreenElement(): FullscreenElement | null {
|
||||
return this._jsmpegCanvasElement ?? null;
|
||||
}
|
||||
|
||||
protected willUpdate(changedProperties: PropertyValues): void {
|
||||
if (
|
||||
['cameraConfig', 'cameraEndpoints'].some((prop) => changedProperties.has(prop))
|
||||
|
||||
@@ -15,7 +15,12 @@ import { getTechnologyForVideoRTC } from '../../../components-lib/live/utils/get
|
||||
import { CameraConfig, CardWideConfig } from '../../../config/types.js';
|
||||
import { localize } from '../../../localize/localize.js';
|
||||
import liveWebRTCCardStyle from '../../../scss/live-webrtc-card.scss';
|
||||
import { FrigateCardError, FrigateCardMediaPlayer, Message } from '../../../types.js';
|
||||
import {
|
||||
FrigateCardError,
|
||||
FrigateCardMediaPlayer,
|
||||
FullscreenElement,
|
||||
Message,
|
||||
} from '../../../types.js';
|
||||
import { mayHaveAudio } from '../../../utils/audio.js';
|
||||
import {
|
||||
dispatchMediaLoadedEvent,
|
||||
@@ -64,54 +69,58 @@ export class FrigateCardLiveWebRTCCard
|
||||
protected _webrtcTask = new Task(this, this._getWebRTCCardElement, () => [1]);
|
||||
|
||||
public async play(): Promise<void> {
|
||||
return this._getPlayer()?.play();
|
||||
return this._getVideo()?.play();
|
||||
}
|
||||
|
||||
public async pause(): Promise<void> {
|
||||
this._getPlayer()?.pause();
|
||||
this._getVideo()?.pause();
|
||||
}
|
||||
|
||||
public async mute(): Promise<void> {
|
||||
const player = this._getPlayer();
|
||||
const player = this._getVideo();
|
||||
if (player) {
|
||||
player.muted = true;
|
||||
}
|
||||
}
|
||||
|
||||
public async unmute(): Promise<void> {
|
||||
const player = this._getPlayer();
|
||||
const player = this._getVideo();
|
||||
if (player) {
|
||||
player.muted = false;
|
||||
}
|
||||
}
|
||||
|
||||
public isMuted(): boolean {
|
||||
return this._getPlayer()?.muted ?? true;
|
||||
return this._getVideo()?.muted ?? true;
|
||||
}
|
||||
|
||||
public async seek(seconds: number): Promise<void> {
|
||||
const player = this._getPlayer();
|
||||
const player = this._getVideo();
|
||||
if (player) {
|
||||
player.currentTime = seconds;
|
||||
}
|
||||
}
|
||||
|
||||
public async setControls(controls?: boolean): Promise<void> {
|
||||
const player = this._getPlayer();
|
||||
const player = this._getVideo();
|
||||
if (player) {
|
||||
setControlsOnVideo(player, controls ?? this.controls);
|
||||
}
|
||||
}
|
||||
|
||||
public isPaused(): boolean {
|
||||
return this._getPlayer()?.paused ?? true;
|
||||
return this._getVideo()?.paused ?? true;
|
||||
}
|
||||
|
||||
public async getScreenshotURL(): Promise<string | null> {
|
||||
const video = this._getPlayer();
|
||||
const video = this._getVideo();
|
||||
return video ? screenshotMedia(video) : null;
|
||||
}
|
||||
|
||||
public getFullscreenElement(): FullscreenElement | null {
|
||||
return this._getVideo();
|
||||
}
|
||||
|
||||
connectedCallback(): void {
|
||||
super.connectedCallback();
|
||||
|
||||
@@ -141,7 +150,7 @@ export class FrigateCardLiveWebRTCCard
|
||||
* Get the underlying video player.
|
||||
* @returns The player or `null` if not found.
|
||||
*/
|
||||
protected _getPlayer(): HTMLVideoElement | null {
|
||||
protected _getVideo(): HTMLVideoElement | null {
|
||||
return this._getVideoRTC()?.video ?? null;
|
||||
}
|
||||
|
||||
@@ -236,7 +245,7 @@ export class FrigateCardLiveWebRTCCard
|
||||
// media load event.
|
||||
this.updateComplete.then(() => {
|
||||
const videoRTC = this._getVideoRTC();
|
||||
const video = this._getPlayer();
|
||||
const video = this._getVideo();
|
||||
if (video) {
|
||||
setControlsOnVideo(video, this.controls);
|
||||
video.onloadeddata = () => {
|
||||
|
||||
@@ -19,6 +19,7 @@ import viewerProviderStyle from '../../scss/viewer-provider.scss';
|
||||
import {
|
||||
ExtendedHomeAssistant,
|
||||
FrigateCardMediaPlayer,
|
||||
FullscreenElement,
|
||||
ResolvedMedia,
|
||||
} from '../../types.js';
|
||||
import { mayHaveAudio } from '../../utils/audio.js';
|
||||
@@ -169,6 +170,15 @@ export class FrigateCardViewerProvider
|
||||
return null;
|
||||
}
|
||||
|
||||
public getFullscreenElement(): FullscreenElement | null {
|
||||
if (this._refFrigateCardMediaPlayer.value) {
|
||||
return this._refFrigateCardMediaPlayer.value.getFullscreenElement();
|
||||
} else if (this._refVideoProvider.value) {
|
||||
return this._refVideoProvider.value;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
protected async _switchToRelatedClipView(): Promise<void> {
|
||||
const view = this.viewManagerEpoch?.manager.getView();
|
||||
if (
|
||||
|
||||
Reference in New Issue
Block a user