Add auto_play and auto_unmute for consistency.

This commit is contained in:
Dermot Duffy
2022-05-08 08:05:33 -07:00
parent d552cf1a0d
commit f6cdf2f01d
9 changed files with 176 additions and 53 deletions
+23 -10
View File
@@ -1,18 +1,25 @@
import { EmblaCarouselType, EmblaPluginType } from 'embla-carousel';
import { AutoMuteCondition, AutoPauseCondition, FrigateCardMediaPlayer } from '../../types.js';
import {
AutoMuteCondition,
AutoPauseCondition,
AutoPlayCondition,
AutoUnmuteCondition,
FrigateCardMediaPlayer,
} from '../../types.js';
export type AutoMediaPluginOptionsType = {
playerSelector: string;
autoPlayWhenVisible?: boolean;
autoUnmuteWhenVisible?: boolean;
// Note: Neither play nor unmute will activate on selection. The caller is
// expected to call the methods manually when the media is actually loaded
// (not just the slide shown).
autoPlayCondition?: AutoPlayCondition;
autoUnmuteCondition?: AutoUnmuteCondition;
autoPauseCondition?: AutoPauseCondition;
autoMuteCondition?: AutoMuteCondition;
};
export const defaultOptions: Partial<AutoMediaPluginOptionsType> = {
autoPlayWhenVisible: true,
autoUnmuteWhenVisible: true,
};
export const defaultOptions: Partial<AutoMediaPluginOptionsType> = {};
export type AutoMediaPluginType = EmblaPluginType<AutoMediaPluginOptionsType> & {
play: () => void;
@@ -102,10 +109,16 @@ export function AutoMediaPlugin(
muteAll();
}
} else if (document.visibilityState == 'visible') {
if (options.autoPlayWhenVisible) {
if (
options.autoPlayCondition &&
['all', 'visible'].includes(options.autoPlayCondition)
) {
play();
}
if (options.autoUnmuteWhenVisible) {
if (
options.autoUnmuteCondition &&
['all', 'visible'].includes(options.autoUnmuteCondition)
) {
unmute();
}
}
@@ -174,7 +187,7 @@ export function AutoMediaPlugin(
/**
* Mute all slides.
*/
function muteAll(): void {
function muteAll(): void {
for (const slide of slides) {
getPlayer(slide)?.mute();
}
+25 -4
View File
@@ -299,22 +299,42 @@ export class FrigateCardLiveCarousel extends FrigateCardMediaCarousel {
}),
AutoMediaPlugin({
playerSelector: 'frigate-card-live-provider',
autoUnmuteWhenVisible: !!this.liveConfig?.auto_unmute,
...(this.liveConfig?.auto_play && {
autoPlayCondition: this.liveConfig.auto_play,
}),
...(this.liveConfig?.auto_pause && {
autoPauseCondition: this.liveConfig.auto_pause,
}),
...(this.liveConfig?.auto_mute && {
autoMuteCondition: this.liveConfig.auto_mute,
}),
...(this.liveConfig?.auto_unmute && {
autoUnmuteCondition: this.liveConfig.auto_unmute,
}),
}),
];
}
/**
* Unmute the media on the selected slide.
* Play the media on the loaded slide.
*/
protected _autoUnmuteHandler(): void {
if (this.liveConfig?.auto_unmute) {
protected _autoPlayHandler(): void {
if (
this.liveConfig?.auto_play &&
['all', 'selected'].includes(this.liveConfig.auto_play)
) {
super._autoPlayHandler();
}
}
/**
* Unmute the media on the loaded slide.
*/
protected _autoUnmuteHandler(): void {
if (
this.liveConfig?.auto_unmute &&
['all', 'selected'].includes(this.liveConfig.auto_unmute)
) {
super._autoUnmuteHandler();
}
}
@@ -984,6 +1004,7 @@ export class FrigateCardLiveJSMPEG extends LitElement {
// The media carousel may automatically pause when the browser tab is
// inactive, JSMPEG does not need to also do so independently.
pauseWhenHidden: false,
autoplay: false,
protocols: [],
audio: false,
videoBufferSize: 1024 * 1024 * 4,
+20 -7
View File
@@ -206,23 +206,32 @@ export class FrigateCardViewerCarousel extends FrigateCardMediaCarousel {
}
/**
* Play the media on the selected slide.
* Play the media on the loaded slide.
*/
protected _autoPlayHandler(): void {
if (this.viewerConfig?.auto_play) {
protected _autoPlayHandler(): void {
if (
this.viewerConfig?.auto_play &&
['all', 'selected'].includes(this.viewerConfig.auto_play)
) {
super._autoPlayHandler();
}
}
/**
* Unmute the media on the selected slide.
* Unmute the media on the loaded slide.
*/
protected _autoUnmuteHandler(): void {
if (this.viewerConfig?.auto_unmute) {
if (
this.viewerConfig?.auto_unmute &&
['all', 'selected'].includes(this.viewerConfig.auto_unmute)
) {
super._autoUnmuteHandler();
}
}
/**
* Destroy the carousel.
*/
protected _destroyCarousel(): void {
super._destroyCarousel();
@@ -280,14 +289,18 @@ export class FrigateCardViewerCarousel extends FrigateCardMediaCarousel {
}),
AutoMediaPlugin({
playerSelector: 'frigate-card-ha-hls-player',
autoPlayWhenVisible: !!this.viewerConfig?.auto_play,
autoUnmuteWhenVisible: !!this.viewerConfig?.auto_unmute,
...(this.viewerConfig?.auto_play && {
autoPlayCondition: this.viewerConfig.auto_play,
}),
...(this.viewerConfig?.auto_pause && {
autoPauseCondition: this.viewerConfig.auto_pause,
}),
...(this.viewerConfig?.auto_mute && {
autoMuteCondition: this.viewerConfig.auto_mute,
}),
...(this.viewerConfig?.auto_unmute && {
autoUnmuteCondition: this.viewerConfig.auto_unmute,
}),
}),
];
}
+11
View File
@@ -35,6 +35,8 @@ import {
CONF_VIEW_DEFAULT,
CONF_VIEW_TIMEOUT_SECONDS,
CONF_VIEW_UPDATE_ENTITIES,
CONF_LIVE_AUTO_UNMUTE,
CONF_EVENT_VIEWER_AUTO_UNMUTE,
} from './const';
import {
BUTTON_SIZE_MIN,
@@ -592,4 +594,13 @@ const UPGRADES = [
upgrade(CONF_LIVE_LAZY_UNLOAD, (val) =>
typeof val === 'boolean' ? (val ? 'all' : 'never') : undefined,
),
upgrade(CONF_LIVE_AUTO_UNMUTE, (val) =>
typeof val === 'boolean' ? (val ? 'all' : 'never') : undefined,
),
upgrade(CONF_EVENT_VIEWER_AUTO_PLAY, (val) =>
typeof val === 'boolean' ? (val ? 'all' : 'never') : undefined,
),
upgrade(CONF_EVENT_VIEWER_AUTO_UNMUTE, (val) =>
typeof val === 'boolean' ? (val ? 'all' : 'never') : undefined,
),
];
+2 -1
View File
@@ -43,8 +43,8 @@ export const CONF_EVENT_GALLERY_CONTROLS_THUMBNAILS_SIZE =
`${CONF_EVENT_GALLERY}.controls.thumbnails.size` 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_PLAY = `${CONF_EVENT_VIEWER}.auto_play` as const;
export const CONF_EVENT_VIEWER_AUTO_PAUSE = `${CONF_EVENT_VIEWER}.auto_pause` 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_DRAGGABLE = `${CONF_EVENT_VIEWER}.draggable` as const;
@@ -69,6 +69,7 @@ export const CONF_EVENT_VIEWER_CONTROLS_TITLE_DURATION_SECONDS =
`${CONF_EVENT_VIEWER}.controls.title.duration_seconds` as const;
export const CONF_LIVE = 'live' as const;
export const CONF_LIVE_AUTO_PLAY = `${CONF_LIVE}.auto_play` 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;
+33 -11
View File
@@ -54,6 +54,7 @@ import {
CONF_IMAGE_URL,
CONF_LIVE_AUTO_MUTE,
CONF_LIVE_AUTO_PAUSE,
CONF_LIVE_AUTO_PLAY,
CONF_LIVE_AUTO_UNMUTE,
CONF_LIVE_CONTROLS_NEXT_PREVIOUS_SIZE,
CONF_LIVE_CONTROLS_NEXT_PREVIOUS_STYLE,
@@ -353,7 +354,7 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor
{ value: 'auto', label: localize('config.view.dark_modes.auto') },
];
protected _mediaActionConditions: EditorSelectOption[] = [
protected _mediaActionNegativeConditions: EditorSelectOption[] = [
{ value: '', label: '' },
{ value: 'all', label: localize('config.common.media_action_conditions.all') },
{
@@ -364,6 +365,20 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor
{ value: 'never', label: localize('config.common.media_action_conditions.never') },
];
protected _mediaActionPositiveConditions: EditorSelectOption[] = [
{ value: '', label: '' },
{ value: 'all', label: localize('config.common.media_action_conditions.all') },
{
value: 'selected',
label: localize('config.common.media_action_conditions.selected'),
},
{
value: 'visible',
label: localize('config.common.media_action_conditions.visible'),
},
{ value: 'never', label: localize('config.common.media_action_conditions.never') },
];
public setConfig(config: RawFrigateCardConfig): void {
// Note: This does not use Zod to parse the configuration, so it may be
// partially or completely invalid. It's more useful to have a partially
@@ -1006,17 +1021,24 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor
${this._renderSwitch(CONF_LIVE_LAZY_LOAD, defaults.live.lazy_load)}
${this._renderOptionSelector(
CONF_LIVE_LAZY_UNLOAD,
this._mediaActionConditions,
this._mediaActionNegativeConditions,
)}
${this._renderOptionSelector(
CONF_LIVE_AUTO_PLAY,
this._mediaActionPositiveConditions,
)}
${this._renderOptionSelector(
CONF_LIVE_AUTO_PAUSE,
this._mediaActionConditions,
this._mediaActionNegativeConditions,
)}
${this._renderOptionSelector(
CONF_LIVE_AUTO_MUTE,
this._mediaActionConditions,
this._mediaActionNegativeConditions,
)}
${this._renderOptionSelector(
CONF_LIVE_AUTO_UNMUTE,
this._mediaActionPositiveConditions,
)}
${this._renderSwitch(CONF_LIVE_AUTO_UNMUTE, defaults.live.auto_unmute)}
${this._renderOptionSelector(
CONF_LIVE_CONTROLS_NEXT_PREVIOUS_STYLE,
this._liveNextPreviousControlStyles,
@@ -1079,21 +1101,21 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor
${this._renderOptionSetHeader('event_viewer')}
${this._expandedMenus[MENU_OPTIONS] === 'event_viewer'
? html` <div class="values">
${this._renderSwitch(
${this._renderOptionSelector(
CONF_EVENT_VIEWER_AUTO_PLAY,
defaults.event_viewer.auto_play,
this._mediaActionPositiveConditions,
)}
${this._renderOptionSelector(
CONF_EVENT_VIEWER_AUTO_PAUSE,
this._mediaActionConditions,
this._mediaActionNegativeConditions,
)}
${this._renderOptionSelector(
CONF_EVENT_VIEWER_AUTO_MUTE,
this._mediaActionConditions,
this._mediaActionNegativeConditions,
)}
${this._renderSwitch(
${this._renderOptionSelector(
CONF_EVENT_VIEWER_AUTO_UNMUTE,
defaults.event_viewer.auto_unmute,
this._mediaActionPositiveConditions,
)}
${this._renderSwitch(
CONF_EVENT_VIEWER_DRAGGABLE,
+3
View File
@@ -37,7 +37,9 @@
"media_action_conditions": {
"all": "All opportunities",
"unselected": "On unselection",
"selected": "On selection",
"hidden": "On browser/tab hiding",
"visible": "On browser/tab visibility",
"never": "Never"
}
},
@@ -127,6 +129,7 @@
"draggable": "Live cameras view can be dragged/swiped",
"lazy_load": "Live cameras are lazily loaded",
"lazy_unload": "Live cameras are lazily unloaded",
"auto_play": "Automatically play live cameras",
"auto_pause": "Automatically pause live cameras",
"auto_mute": "Automatically mute live cameras",
"auto_unmute": "Automatically unmute live cameras",
+50 -16
View File
@@ -64,10 +64,24 @@ export const FRIGATE_MENU_PRIORITY_MAX = 100;
const LIVE_PROVIDERS = ['auto', 'ha', 'frigate-jsmpeg', 'webrtc-card'] as const;
export type LiveProvider = typeof LIVE_PROVIDERS[number];
const MEDIA_ACTION_CONDITIONS = ['all', 'unselected', 'hidden', 'never'] as const;
export type LazyUnloadCondition = typeof MEDIA_ACTION_CONDITIONS[number];
export type AutoMuteCondition = typeof MEDIA_ACTION_CONDITIONS[number];
export type AutoPauseCondition = typeof MEDIA_ACTION_CONDITIONS[number];
const MEDIA_ACTION_NEGATIVE_CONDITIONS = [
'all',
'unselected',
'hidden',
'never',
] as const;
export type LazyUnloadCondition = typeof MEDIA_ACTION_NEGATIVE_CONDITIONS[number];
export type AutoMuteCondition = typeof MEDIA_ACTION_NEGATIVE_CONDITIONS[number];
export type AutoPauseCondition = typeof MEDIA_ACTION_NEGATIVE_CONDITIONS[number];
const MEDIA_ACTION_POSITIVE_CONDITIONS = [
'all',
'selected',
'visible',
'never',
] as const;
export type AutoUnmuteCondition = typeof MEDIA_ACTION_POSITIVE_CONDITIONS[number];
export type AutoPlayCondition = typeof MEDIA_ACTION_POSITIVE_CONDITIONS[number];
export class FrigateCardError extends Error {}
@@ -562,9 +576,10 @@ export type TitleControlConfig = z.infer<typeof titleControlConfigSchema>;
* Live view configuration section.
*/
const liveConfigDefault = {
auto_pause: 'all' as const,
auto_play: 'all' as const,
auto_pause: 'never' as const,
auto_mute: 'all' as const,
auto_unmute: false,
auto_unmute: 'never' as const,
preload: false,
lazy_load: true,
lazy_unload: 'never' as const,
@@ -669,12 +684,23 @@ const liveOverridableConfigSchema = z
const liveConfigSchema = liveOverridableConfigSchema
.extend({
// Non-overrideable parameters.
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_play: z
.enum(MEDIA_ACTION_POSITIVE_CONDITIONS)
.default(liveConfigDefault.auto_play),
auto_pause: z
.enum(MEDIA_ACTION_NEGATIVE_CONDITIONS)
.default(liveConfigDefault.auto_pause),
auto_mute: z
.enum(MEDIA_ACTION_NEGATIVE_CONDITIONS)
.default(liveConfigDefault.auto_mute),
auto_unmute: z
.enum(MEDIA_ACTION_POSITIVE_CONDITIONS)
.default(liveConfigDefault.auto_unmute),
preload: z.boolean().default(liveConfigDefault.preload),
lazy_load: z.boolean().default(liveConfigDefault.lazy_load),
lazy_unload: z.enum(MEDIA_ACTION_CONDITIONS).default(liveConfigDefault.lazy_unload),
lazy_unload: z
.enum(MEDIA_ACTION_NEGATIVE_CONDITIONS)
.default(liveConfigDefault.lazy_unload),
draggable: z.boolean().default(liveConfigDefault.draggable),
transition_effect: transitionEffectConfigSchema.default(
liveConfigDefault.transition_effect,
@@ -756,10 +782,10 @@ export type MenuConfig = z.infer<typeof menuConfigSchema>;
* Event viewer configuration section (clip, snapshot).
*/
const viewerConfigDefault = {
auto_play: 'all' as const,
auto_pause: 'all' as const,
auto_play: true,
auto_mute: 'all' as const,
auto_unmute: false,
auto_unmute: 'never' as const,
lazy_load: true,
draggable: true,
transition_effect: 'slide' as const,
@@ -794,10 +820,18 @@ export type ViewerNextPreviousControlConfig = z.infer<
const viewerConfigSchema = z
.object({
auto_pause: z.enum(MEDIA_ACTION_CONDITIONS).default(viewerConfigDefault.auto_pause),
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_play: z
.enum(MEDIA_ACTION_POSITIVE_CONDITIONS)
.default(viewerConfigDefault.auto_play),
auto_pause: z
.enum(MEDIA_ACTION_NEGATIVE_CONDITIONS)
.default(viewerConfigDefault.auto_pause),
auto_mute: z
.enum(MEDIA_ACTION_NEGATIVE_CONDITIONS)
.default(viewerConfigDefault.auto_mute),
auto_unmute: z
.enum(MEDIA_ACTION_POSITIVE_CONDITIONS)
.default(viewerConfigDefault.auto_unmute),
lazy_load: z.boolean().default(viewerConfigDefault.lazy_load),
draggable: z.boolean().default(viewerConfigDefault.draggable),
transition_effect: transitionEffectConfigSchema.default(