Implement auto_mute .
This commit is contained in:
@@ -1,11 +1,12 @@
|
|||||||
import { EmblaCarouselType, EmblaPluginType } from 'embla-carousel';
|
import { EmblaCarouselType, EmblaPluginType } from 'embla-carousel';
|
||||||
import { AutoPauseCondition, FrigateCardMediaPlayer } from '../../types.js';
|
import { AutoMuteCondition, AutoPauseCondition, FrigateCardMediaPlayer } from '../../types.js';
|
||||||
|
|
||||||
export type AutoMediaPluginOptionsType = {
|
export type AutoMediaPluginOptionsType = {
|
||||||
playerSelector: string;
|
playerSelector: string;
|
||||||
autoPlayWhenVisible?: boolean;
|
autoPlayWhenVisible?: boolean;
|
||||||
autoUnmuteWhenVisible?: boolean;
|
autoUnmuteWhenVisible?: boolean;
|
||||||
autoPauseCondition?: AutoPauseCondition;
|
autoPauseCondition?: AutoPauseCondition;
|
||||||
|
autoMuteCondition?: AutoMuteCondition;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const defaultOptions: Partial<AutoMediaPluginOptionsType> = {
|
export const defaultOptions: Partial<AutoMediaPluginOptionsType> = {
|
||||||
@@ -51,7 +52,12 @@ export function AutoMediaPlugin(
|
|||||||
carousel.on('select', pausePrevious);
|
carousel.on('select', pausePrevious);
|
||||||
}
|
}
|
||||||
carousel.on('destroy', mute);
|
carousel.on('destroy', mute);
|
||||||
carousel.on('select', mutePrevious);
|
if (
|
||||||
|
options.autoMuteCondition &&
|
||||||
|
['all', 'unselected'].includes(options.autoMuteCondition)
|
||||||
|
) {
|
||||||
|
carousel.on('select', mutePrevious);
|
||||||
|
}
|
||||||
|
|
||||||
document.addEventListener('visibilitychange', visibilityHandler);
|
document.addEventListener('visibilitychange', visibilityHandler);
|
||||||
}
|
}
|
||||||
@@ -68,7 +74,12 @@ export function AutoMediaPlugin(
|
|||||||
carousel.off('select', pausePrevious);
|
carousel.off('select', pausePrevious);
|
||||||
}
|
}
|
||||||
carousel.off('destroy', mute);
|
carousel.off('destroy', mute);
|
||||||
carousel.off('select', mutePrevious);
|
if (
|
||||||
|
options.autoMuteCondition &&
|
||||||
|
['all', 'unselected'].includes(options.autoMuteCondition)
|
||||||
|
) {
|
||||||
|
carousel.off('select', mutePrevious);
|
||||||
|
}
|
||||||
|
|
||||||
document.removeEventListener('visibilitychange', visibilityHandler);
|
document.removeEventListener('visibilitychange', visibilityHandler);
|
||||||
}
|
}
|
||||||
@@ -84,7 +95,12 @@ export function AutoMediaPlugin(
|
|||||||
) {
|
) {
|
||||||
pauseAll();
|
pauseAll();
|
||||||
}
|
}
|
||||||
mute();
|
if (
|
||||||
|
options.autoMuteCondition &&
|
||||||
|
['all', 'hidden'].includes(options.autoMuteCondition)
|
||||||
|
) {
|
||||||
|
muteAll();
|
||||||
|
}
|
||||||
} else if (document.visibilityState == 'visible') {
|
} else if (document.visibilityState == 'visible') {
|
||||||
if (options.autoPlayWhenVisible) {
|
if (options.autoPlayWhenVisible) {
|
||||||
play();
|
play();
|
||||||
@@ -126,7 +142,7 @@ export function AutoMediaPlugin(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pause the previous slide.
|
* Pause all slides.
|
||||||
*/
|
*/
|
||||||
function pauseAll(): void {
|
function pauseAll(): void {
|
||||||
for (const slide of slides) {
|
for (const slide of slides) {
|
||||||
@@ -155,6 +171,15 @@ export function AutoMediaPlugin(
|
|||||||
getPlayer(slides[carousel.previousScrollSnap()])?.mute();
|
getPlayer(slides[carousel.previousScrollSnap()])?.mute();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mute all slides.
|
||||||
|
*/
|
||||||
|
function muteAll(): void {
|
||||||
|
for (const slide of slides) {
|
||||||
|
getPlayer(slide)?.mute();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const self: AutoMediaPluginType = {
|
const self: AutoMediaPluginType = {
|
||||||
name: 'AutoMediaPlugin',
|
name: 'AutoMediaPlugin',
|
||||||
options,
|
options,
|
||||||
|
|||||||
@@ -303,6 +303,9 @@ export class FrigateCardLiveCarousel extends FrigateCardMediaCarousel {
|
|||||||
...(this.liveConfig?.auto_pause && {
|
...(this.liveConfig?.auto_pause && {
|
||||||
autoPauseCondition: this.liveConfig.auto_pause,
|
autoPauseCondition: this.liveConfig.auto_pause,
|
||||||
}),
|
}),
|
||||||
|
...(this.liveConfig?.auto_mute && {
|
||||||
|
autoMuteCondition: this.liveConfig.auto_mute,
|
||||||
|
}),
|
||||||
}),
|
}),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -285,6 +285,9 @@ export class FrigateCardViewerCarousel extends FrigateCardMediaCarousel {
|
|||||||
...(this.viewerConfig?.auto_pause && {
|
...(this.viewerConfig?.auto_pause && {
|
||||||
autoPauseCondition: this.viewerConfig.auto_pause,
|
autoPauseCondition: this.viewerConfig.auto_pause,
|
||||||
}),
|
}),
|
||||||
|
...(this.viewerConfig?.auto_mute && {
|
||||||
|
autoMuteCondition: this.viewerConfig.auto_mute,
|
||||||
|
}),
|
||||||
}),
|
}),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ export const CONF_EVENT_GALLERY_CONTROLS_THUMBNAILS_SIZE =
|
|||||||
export const CONF_EVENT_VIEWER = 'event_viewer' as const;
|
export const CONF_EVENT_VIEWER = 'event_viewer' as const;
|
||||||
export const CONF_EVENT_VIEWER_AUTO_PAUSE = `${CONF_EVENT_VIEWER}.auto_pause` as const;
|
export const CONF_EVENT_VIEWER_AUTO_PAUSE = `${CONF_EVENT_VIEWER}.auto_pause` as const;
|
||||||
export const CONF_EVENT_VIEWER_AUTO_PLAY = `${CONF_EVENT_VIEWER}.auto_play` as const;
|
export const CONF_EVENT_VIEWER_AUTO_PLAY = `${CONF_EVENT_VIEWER}.auto_play` as const;
|
||||||
|
export const CONF_EVENT_VIEWER_AUTO_MUTE = `${CONF_EVENT_VIEWER}.auto_mute` as const;
|
||||||
export const CONF_EVENT_VIEWER_AUTO_UNMUTE = `${CONF_EVENT_VIEWER}.auto_unmute` as const;
|
export const CONF_EVENT_VIEWER_AUTO_UNMUTE = `${CONF_EVENT_VIEWER}.auto_unmute` as const;
|
||||||
export const CONF_EVENT_VIEWER_DRAGGABLE = `${CONF_EVENT_VIEWER}.draggable` as const;
|
export const CONF_EVENT_VIEWER_DRAGGABLE = `${CONF_EVENT_VIEWER}.draggable` as const;
|
||||||
export const CONF_EVENT_VIEWER_LAZY_LOAD = `${CONF_EVENT_VIEWER}.lazy_load` as const;
|
export const CONF_EVENT_VIEWER_LAZY_LOAD = `${CONF_EVENT_VIEWER}.lazy_load` as const;
|
||||||
@@ -69,6 +70,7 @@ export const CONF_EVENT_VIEWER_CONTROLS_TITLE_DURATION_SECONDS =
|
|||||||
|
|
||||||
export const CONF_LIVE = 'live' as const;
|
export const CONF_LIVE = 'live' as const;
|
||||||
export const CONF_LIVE_AUTO_PAUSE = `${CONF_LIVE}.auto_pause` as const;
|
export const CONF_LIVE_AUTO_PAUSE = `${CONF_LIVE}.auto_pause` as const;
|
||||||
|
export const CONF_LIVE_AUTO_MUTE = `${CONF_LIVE}.auto_mute` as const;
|
||||||
export const CONF_LIVE_AUTO_UNMUTE = `${CONF_LIVE}.auto_unmute` as const;
|
export const CONF_LIVE_AUTO_UNMUTE = `${CONF_LIVE}.auto_unmute` as const;
|
||||||
export const CONF_LIVE_CONTROLS_NEXT_PREVIOUS_STYLE =
|
export const CONF_LIVE_CONTROLS_NEXT_PREVIOUS_STYLE =
|
||||||
`${CONF_LIVE}.controls.next_previous.style` as const;
|
`${CONF_LIVE}.controls.next_previous.style` as const;
|
||||||
|
|||||||
+14
-4
@@ -34,6 +34,7 @@ import {
|
|||||||
CONF_EVENT_GALLERY_CONTROLS_THUMBNAILS_SHOW_CONTROLS,
|
CONF_EVENT_GALLERY_CONTROLS_THUMBNAILS_SHOW_CONTROLS,
|
||||||
CONF_EVENT_GALLERY_CONTROLS_THUMBNAILS_SHOW_DETAILS,
|
CONF_EVENT_GALLERY_CONTROLS_THUMBNAILS_SHOW_DETAILS,
|
||||||
CONF_EVENT_GALLERY_CONTROLS_THUMBNAILS_SIZE,
|
CONF_EVENT_GALLERY_CONTROLS_THUMBNAILS_SIZE,
|
||||||
|
CONF_EVENT_VIEWER_AUTO_MUTE,
|
||||||
CONF_EVENT_VIEWER_AUTO_PAUSE,
|
CONF_EVENT_VIEWER_AUTO_PAUSE,
|
||||||
CONF_EVENT_VIEWER_AUTO_PLAY,
|
CONF_EVENT_VIEWER_AUTO_PLAY,
|
||||||
CONF_EVENT_VIEWER_AUTO_UNMUTE,
|
CONF_EVENT_VIEWER_AUTO_UNMUTE,
|
||||||
@@ -51,6 +52,7 @@ import {
|
|||||||
CONF_IMAGE_MODE,
|
CONF_IMAGE_MODE,
|
||||||
CONF_IMAGE_REFRESH_SECONDS,
|
CONF_IMAGE_REFRESH_SECONDS,
|
||||||
CONF_IMAGE_URL,
|
CONF_IMAGE_URL,
|
||||||
|
CONF_LIVE_AUTO_MUTE,
|
||||||
CONF_LIVE_AUTO_PAUSE,
|
CONF_LIVE_AUTO_PAUSE,
|
||||||
CONF_LIVE_AUTO_UNMUTE,
|
CONF_LIVE_AUTO_UNMUTE,
|
||||||
CONF_LIVE_CONTROLS_NEXT_PREVIOUS_SIZE,
|
CONF_LIVE_CONTROLS_NEXT_PREVIOUS_SIZE,
|
||||||
@@ -1010,6 +1012,10 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor
|
|||||||
CONF_LIVE_AUTO_PAUSE,
|
CONF_LIVE_AUTO_PAUSE,
|
||||||
this._mediaActionConditions,
|
this._mediaActionConditions,
|
||||||
)}
|
)}
|
||||||
|
${this._renderOptionSelector(
|
||||||
|
CONF_LIVE_AUTO_MUTE,
|
||||||
|
this._mediaActionConditions,
|
||||||
|
)}
|
||||||
${this._renderSwitch(CONF_LIVE_AUTO_UNMUTE, defaults.live.auto_unmute)}
|
${this._renderSwitch(CONF_LIVE_AUTO_UNMUTE, defaults.live.auto_unmute)}
|
||||||
${this._renderOptionSelector(
|
${this._renderOptionSelector(
|
||||||
CONF_LIVE_CONTROLS_NEXT_PREVIOUS_STYLE,
|
CONF_LIVE_CONTROLS_NEXT_PREVIOUS_STYLE,
|
||||||
@@ -1077,14 +1083,18 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor
|
|||||||
CONF_EVENT_VIEWER_AUTO_PLAY,
|
CONF_EVENT_VIEWER_AUTO_PLAY,
|
||||||
defaults.event_viewer.auto_play,
|
defaults.event_viewer.auto_play,
|
||||||
)}
|
)}
|
||||||
${this._renderSwitch(
|
|
||||||
CONF_EVENT_VIEWER_AUTO_UNMUTE,
|
|
||||||
defaults.event_viewer.auto_unmute,
|
|
||||||
)}
|
|
||||||
${this._renderOptionSelector(
|
${this._renderOptionSelector(
|
||||||
CONF_EVENT_VIEWER_AUTO_PAUSE,
|
CONF_EVENT_VIEWER_AUTO_PAUSE,
|
||||||
this._mediaActionConditions,
|
this._mediaActionConditions,
|
||||||
)}
|
)}
|
||||||
|
${this._renderOptionSelector(
|
||||||
|
CONF_EVENT_VIEWER_AUTO_MUTE,
|
||||||
|
this._mediaActionConditions,
|
||||||
|
)}
|
||||||
|
${this._renderSwitch(
|
||||||
|
CONF_EVENT_VIEWER_AUTO_UNMUTE,
|
||||||
|
defaults.event_viewer.auto_unmute,
|
||||||
|
)}
|
||||||
${this._renderSwitch(
|
${this._renderSwitch(
|
||||||
CONF_EVENT_VIEWER_DRAGGABLE,
|
CONF_EVENT_VIEWER_DRAGGABLE,
|
||||||
defaults.event_viewer.draggable,
|
defaults.event_viewer.draggable,
|
||||||
|
|||||||
@@ -77,6 +77,7 @@
|
|||||||
"event_viewer": {
|
"event_viewer": {
|
||||||
"auto_play": "Automatically play media",
|
"auto_play": "Automatically play media",
|
||||||
"auto_pause": "Automatically pause media",
|
"auto_pause": "Automatically pause media",
|
||||||
|
"auto_mute": "Automatically mute media",
|
||||||
"auto_unmute": "Automatically unmute media",
|
"auto_unmute": "Automatically unmute media",
|
||||||
"draggable": "Event Viewer can be dragged/swiped",
|
"draggable": "Event Viewer can be dragged/swiped",
|
||||||
"lazy_load": "Event Viewer media is lazily loaded in carousel",
|
"lazy_load": "Event Viewer media is lazily loaded in carousel",
|
||||||
@@ -127,6 +128,7 @@
|
|||||||
"lazy_load": "Live cameras are lazily loaded",
|
"lazy_load": "Live cameras are lazily loaded",
|
||||||
"lazy_unload": "Live cameras are lazily unloaded",
|
"lazy_unload": "Live cameras are lazily unloaded",
|
||||||
"auto_pause": "Automatically pause live cameras",
|
"auto_pause": "Automatically pause live cameras",
|
||||||
|
"auto_mute": "Automatically mute live cameras",
|
||||||
"auto_unmute": "Automatically unmute live cameras",
|
"auto_unmute": "Automatically unmute live cameras",
|
||||||
"transition_effect": "Live camera transition effect",
|
"transition_effect": "Live camera transition effect",
|
||||||
"controls": {
|
"controls": {
|
||||||
|
|||||||
@@ -63,14 +63,14 @@ customElements.whenDefined('ha-camera-stream').then(() => {
|
|||||||
* Mute the video.
|
* Mute the video.
|
||||||
*/
|
*/
|
||||||
public mute(): void {
|
public mute(): void {
|
||||||
this.muted = true;
|
this._playerRef.value?.mute();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unmute the video.
|
* Unmute the video.
|
||||||
*/
|
*/
|
||||||
public unmute(): void {
|
public unmute(): void {
|
||||||
this.muted = false;
|
this._playerRef.value?.unmute();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -38,14 +38,21 @@ customElements.whenDefined('ha-hls-player').then(() => {
|
|||||||
* Mute the video.
|
* Mute the video.
|
||||||
*/
|
*/
|
||||||
public mute(): void {
|
public mute(): void {
|
||||||
this.muted = true;
|
// The muted property is only for the initial muted state. Must explicitly
|
||||||
|
// set the muted on the video player to make the change dynamic.
|
||||||
|
if (this._videoRef.value) {
|
||||||
|
this._videoRef.value.muted = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unmute the video.
|
* Unmute the video.
|
||||||
*/
|
*/
|
||||||
public unmute(): void {
|
public unmute(): void {
|
||||||
this.muted = false;
|
// See note in mute().
|
||||||
|
if (this._videoRef.value) {
|
||||||
|
this._videoRef.value.muted = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// =====================================================================================
|
// =====================================================================================
|
||||||
@@ -54,8 +61,7 @@ customElements.whenDefined('ha-hls-player').then(() => {
|
|||||||
// =====================================================================================
|
// =====================================================================================
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult {
|
||||||
if (this._error) {
|
if (this._error) {
|
||||||
// Use native Frigate card error handling, and attach the entityid to
|
// Use native Frigate card error handling.
|
||||||
// clarify which camera the error refers to.
|
|
||||||
return dispatchErrorMessageEvent(this, this._error);
|
return dispatchErrorMessageEvent(this, this._error);
|
||||||
}
|
}
|
||||||
return html`
|
return html`
|
||||||
|
|||||||
@@ -66,6 +66,7 @@ export type LiveProvider = typeof LIVE_PROVIDERS[number];
|
|||||||
|
|
||||||
const MEDIA_ACTION_CONDITIONS = ['all', 'unselected', 'hidden', 'never'] as const;
|
const MEDIA_ACTION_CONDITIONS = ['all', 'unselected', 'hidden', 'never'] as const;
|
||||||
export type LazyUnloadCondition = typeof MEDIA_ACTION_CONDITIONS[number];
|
export type LazyUnloadCondition = typeof MEDIA_ACTION_CONDITIONS[number];
|
||||||
|
export type AutoMuteCondition = typeof MEDIA_ACTION_CONDITIONS[number];
|
||||||
export type AutoPauseCondition = typeof MEDIA_ACTION_CONDITIONS[number];
|
export type AutoPauseCondition = typeof MEDIA_ACTION_CONDITIONS[number];
|
||||||
|
|
||||||
export class FrigateCardError extends Error {}
|
export class FrigateCardError extends Error {}
|
||||||
@@ -562,6 +563,7 @@ export type TitleControlConfig = z.infer<typeof titleControlConfigSchema>;
|
|||||||
*/
|
*/
|
||||||
const liveConfigDefault = {
|
const liveConfigDefault = {
|
||||||
auto_pause: 'all' as const,
|
auto_pause: 'all' as const,
|
||||||
|
auto_mute: 'all' as const,
|
||||||
auto_unmute: false,
|
auto_unmute: false,
|
||||||
preload: false,
|
preload: false,
|
||||||
lazy_load: true,
|
lazy_load: true,
|
||||||
@@ -668,6 +670,7 @@ const liveConfigSchema = liveOverridableConfigSchema
|
|||||||
.extend({
|
.extend({
|
||||||
// Non-overrideable parameters.
|
// Non-overrideable parameters.
|
||||||
auto_pause: z.enum(MEDIA_ACTION_CONDITIONS).default(liveConfigDefault.auto_pause),
|
auto_pause: z.enum(MEDIA_ACTION_CONDITIONS).default(liveConfigDefault.auto_pause),
|
||||||
|
auto_mute: z.enum(MEDIA_ACTION_CONDITIONS).default(liveConfigDefault.auto_mute),
|
||||||
auto_unmute: z.boolean().default(liveConfigDefault.auto_unmute),
|
auto_unmute: z.boolean().default(liveConfigDefault.auto_unmute),
|
||||||
preload: z.boolean().default(liveConfigDefault.preload),
|
preload: z.boolean().default(liveConfigDefault.preload),
|
||||||
lazy_load: z.boolean().default(liveConfigDefault.lazy_load),
|
lazy_load: z.boolean().default(liveConfigDefault.lazy_load),
|
||||||
@@ -755,6 +758,7 @@ export type MenuConfig = z.infer<typeof menuConfigSchema>;
|
|||||||
const viewerConfigDefault = {
|
const viewerConfigDefault = {
|
||||||
auto_pause: 'all' as const,
|
auto_pause: 'all' as const,
|
||||||
auto_play: true,
|
auto_play: true,
|
||||||
|
auto_mute: 'all' as const,
|
||||||
auto_unmute: false,
|
auto_unmute: false,
|
||||||
lazy_load: true,
|
lazy_load: true,
|
||||||
draggable: true,
|
draggable: true,
|
||||||
@@ -792,6 +796,7 @@ const viewerConfigSchema = z
|
|||||||
.object({
|
.object({
|
||||||
auto_pause: z.enum(MEDIA_ACTION_CONDITIONS).default(viewerConfigDefault.auto_pause),
|
auto_pause: z.enum(MEDIA_ACTION_CONDITIONS).default(viewerConfigDefault.auto_pause),
|
||||||
auto_play: z.boolean().default(viewerConfigDefault.auto_play),
|
auto_play: z.boolean().default(viewerConfigDefault.auto_play),
|
||||||
|
auto_mute: z.enum(MEDIA_ACTION_CONDITIONS).default(viewerConfigDefault.auto_mute),
|
||||||
auto_unmute: z.boolean().default(viewerConfigDefault.auto_unmute),
|
auto_unmute: z.boolean().default(viewerConfigDefault.auto_unmute),
|
||||||
lazy_load: z.boolean().default(viewerConfigDefault.lazy_load),
|
lazy_load: z.boolean().default(viewerConfigDefault.lazy_load),
|
||||||
draggable: z.boolean().default(viewerConfigDefault.draggable),
|
draggable: z.boolean().default(viewerConfigDefault.draggable),
|
||||||
|
|||||||
Reference in New Issue
Block a user