Add options for controlling how aard runs in small players and background tabs + allow auto-disabling aard after first detection

This commit is contained in:
Tamius Han 2025-10-08 19:35:12 +02:00
parent 4276a9f03a
commit accc320971
12 changed files with 239 additions and 268 deletions

View File

@ -1,4 +1,5 @@
import { Action } from '../../../node_modules/vuex/types/index' import { Action } from '../../../node_modules/vuex/types/index'
import { AardPollingOptions } from '../../ext/lib/aard/enums/aard-polling-options.enum'
import AntiGradientMode from '../enums/AntiGradientMode.enum' import AntiGradientMode from '../enums/AntiGradientMode.enum'
import AspectRatioType from '../enums/AspectRatioType.enum' import AspectRatioType from '../enums/AspectRatioType.enum'
import CropModePersistence from '../enums/CropModePersistence.enum' import CropModePersistence from '../enums/CropModePersistence.enum'
@ -74,6 +75,10 @@ export interface AardSettings {
stopTimeout: number; stopTimeout: number;
}, },
polling: {
runInBackgroundTabs: AardPollingOptions;
runOnSmallVideos: AardPollingOptions;
}
disabledReason: string, // if automatic aspect ratio has been disabled, show reason disabledReason: string, // if automatic aspect ratio has been disabled, show reason
allowedMisaligned: number, // top and bottom letterbox thickness can differ by this much. allowedMisaligned: number, // top and bottom letterbox thickness can differ by this much.
@ -87,13 +92,17 @@ export interface AardSettings {
minimumTimeout: number, minimumTimeout: number,
tickrate: number, // 1 tick every this many milliseconds tickrate: number, // 1 tick every this many milliseconds
}, },
autoDisable: { // settings for automatically disabling the extension
maxExecutionTime: number, // if execution time of main autodetect loop exceeds this many milliseconds,
// we disable it.
consecutiveTimeoutCount: number, // we only do it if it happens this many consecutive times
// FOR FUTURE USE subtitles: {
consecutiveArResets: number // if aspect ratio reverts immediately after AR change is applied, we disable everything resetIfDetected?: boolean, // reset if subtitles are detected
resumeAfter?: number, // resume after X ms of no subtitles
},
autoDisable: { // settings for automatically disabling the extension
onFirstChange: boolean,
ifNotChanged: boolean,
ifNotChangedTimeout: number,
ifSubtitles: boolean;
}, },
canvasDimensions: { canvasDimensions: {
blackframeCanvas: { // smaller than sample canvas, blackframe canvas is used to recon for black frames blackframeCanvas: { // smaller than sample canvas, blackframe canvas is used to recon for black frames

View File

@ -463,7 +463,7 @@ export default {
if (!this.site) { if (!this.site) {
this.origin = event.origin; this.origin = event.origin;
this.site = event.origin.split('//')[1]; this.site = event.origin.split('//')[1];
this.siteSettings = this.settings.getSiteSettings({site: this.site}); this.siteSettings = this.settings.getSiteSettings({site: this.site, isIframe: event.data.isIframe});
} }
return this.handleProbe(event.data, event.origin); // handleProbe is defined in UIProbeMixin return this.handleProbe(event.data, event.origin); // handleProbe is defined in UIProbeMixin
case 'uw-bus-tunnel': case 'uw-bus-tunnel':

View File

@ -9,217 +9,7 @@
</div> </div>
<div class="aard-settings-group"> <div class="aard-settings-group">
<!-- the last time i tried to comment out this block, it didn't work properly v-if="false" it is -->
<div v-if="false">
<p>
<b>Autodetection performance</b>
</p>
<p>
Automatic aspect ratio detection is a resource-hungry feature.
This page allows you to trade autodetection accuracy and/or frequency for
better performance.
</p>
<p>
Note that some browsers <a href="https://developer.mozilla.org/en-US/docs/Web/API/Performance/now" target="_blank">limit the accuracy of time measurements</a>, though once the bars go past the blue line those limitations are largely inconsequential.
</p>
<div class="performance-graph-container">
<div class="performance-graph">
<div class="time-budget hz144"></div>
<div class="time-budget hz120"></div>
<div class="time-budget hz60"></div>
<div class="time-budget hz30"></div>
<div class="time-budget hz24"></div>
<div class="time-budget rest"></div>
<div class="bar-container">
<div class="average-case">
<div class="stats">
<b>Average: </b>
<span class="draw">draw (main) {{(performanceData?.imageDraw?.averageTime ?? 0).toFixed(1)}} ms</span> |
<span class="draw-blackframe">blackframe {{(performanceData?.blackFrame?.averageTime ?? 0).toFixed(1)}} ms</span> |
<span class="processing">
processing {{
Math.max(
(performanceData?.total?.averageTime ?? 0)
- (performanceData?.imageDraw?.averageTime ?? 0)
- (performanceData?.blackFrame?.averageTime ?? 0),
0
).toFixed(1)
}} ms
</span>
</div>
<div class="bar">
<div
class="draw"
:style="{'width': (performanceData?.imageDraw?.averageTime ?? 0) + '%'}"
>
</div>
<div
class="draw-blackframe"
:style="{'width': (performanceData?.blackFrame?.averageTime ?? 0) + '%'}"
>
</div>
<div
class="processing"
:style="{
'width': Math.max(
(performanceData?.total?.averageTime ?? 0)
- (performanceData?.imageDraw?.averageTime ?? 0)
- (performanceData?.blackFrame?.averageTime ?? 0),
0
) + '%'
}"
>
</div>
</div>
</div>
<div class="worst-case">
<div class="stats">
<b>Worst: </b>
<span class="draw">draw (main) {{(performanceData?.imageDraw?.worstTime ?? 0).toFixed(1)}} ms</span> |
<span class="draw-blackframe">blackframe {{(performanceData?.blackFrame?.worstTime ?? 0).toFixed(1)}} ms</span> |
<span class="processing">
processing {{
Math.max(
(performanceData?.total?.worstTime ?? 0)
- (performanceData?.imageDraw?.worstTime ?? 0)
- (performanceData?.blackFrame?.worstTime ?? 0),
0
).toFixed(1)
}} ms
</span>
</div>
<div class="bar">
<div
class="draw"
:style="{'width': (performanceData?.imageDraw?.worstTime ?? 0) + '%'}"
>
</div>
<div
class="draw-blackframe"
:style="{'width': (performanceData?.blackFrame?.worstTime ?? 0) + '%'}"
>
</div>
<div
class="processing"
:style="{
'width': Math.max(
(performanceData?.total?.worstTime ?? 0)
- (performanceData?.imageDraw?.worstTime ?? 0)
- (performanceData?.blackFrame?.worstTime ?? 0),
0
) + '%'
}"
>
</div>
</div>
</div>
<div class="average-case">
<div class="stats">
<b>AR change (average): </b>
<span class="draw">draw (main) {{(performanceData?.imageDraw?.averageTime ?? 0).toFixed(1)}} ms</span> |
<span class="draw-blackframe">blackframe {{(performanceData?.blackFrame?.averageTime ?? 0).toFixed(1)}} ms</span> |
<span class="processing">processing {{
(
(performanceData?.fastLetterbox?.averageTime ?? 0)
+ (performanceData?.edgeDetect?.averageTime ?? 0)
).toFixed(1)
}} ms</span>
</div>
<div class="bar">
<div
class="draw"
:style="{'width': (performanceData?.imageDraw?.averageTime ?? 0) + '%'}"
>
</div>
<div
class="draw-blackframe"
:style="{'width': (performanceData?.blackFrame?.averageTime ?? 0) + '%'}"
>
</div>
<div
class="processing"
:style="{
'width': (
(performanceData?.fastLetterbox?.averageTime ?? 0)
+ (performanceData?.edgeDetect?.averageTime ?? 0)
) + '%'
}"
>
</div>
</div>
</div>
<div class="worst-case">
<div class="stats">
<b>AR change (worst): </b>
<span class="draw">draw (main) {{(performanceData?.imageDraw?.worstTime ?? 0).toFixed(1)}} ms</span> |
<span class="draw-blackframe">blackframe {{(performanceData?.blackFrame?.worstTime ?? 0).toFixed(1)}} ms</span> |
<span class="processing">processing {{
(
(performanceData?.fastLetterbox?.worstTime ?? 0)
+ (performanceData?.edgeDetect?.worstTime ?? 0)
).toFixed(1)
}} ms</span>
</div>
<div class="bar">
<div
class="draw"
:style="{'width': (performanceData?.imageDraw?.worstTime ?? 0) + '%'}"
>
</div>
<div
class="draw-blackframe"
:style="{'width': (performanceData?.blackFrame?.worstTime ?? 0) + '%'}"
>
</div>
<div
class="processing"
:style="{
'width': (
(performanceData?.fastLetterbox?.worstTime ?? 0)
+ (performanceData?.edgeDetect?.worstTime ?? 0)
) + '%'
}"
>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="settings-segment"> <div class="settings-segment">
<!-- <h2>Basic settings</h2> -->
<!-- <div class="field">
<div class="label">
Stop autodetection after first detection:
</div>
<div class="">
<input type="checkbox" v-model="settings.active.arDetect.earlyStopOptions.stopAfterFirstDetection" />
</div>
</div>
<div class="field">
<div class="label">
Stop detection after a period of time:
</div>
<div class="">
<input type="checkbox" v-model="settings.active.arDetect.earlyStopOptions.stopAfterTimeout" />
</div>
</div>
<div class="field">
<div class="label">
Stop detection after:
</div>
<div class="input">
<input type="input" v-model="settings.active.arDetect.earlyStopOptions.stopTimeout" />
<div class="unit">seconds</div>
</div>
</div> -->
<div class="field"> <div class="field">
<div class="label">Autodetection frequency (time between samples)</div> <div class="label">Autodetection frequency (time between samples)</div>
@ -243,7 +33,97 @@
</div> </div>
<div class="field"> <div class="field">
<div class="label">Frame extraction canvas type:</div> <div class="label">Reduced autodetection frequency</div>
<div class="range-input">
<input
type="range"
:value="Math.log(settings.active.arDetect.timers.playingReduced)"
@change="setArCheckFrequency($event.target.value, 'playingReduced')"
min="2.3"
max="9.3"
step="0.01"
/>
<input
v-model="settings.active.arDetect.timers.playingReduced"
@change="setArCheckFrequency($event.target.value, 'playingReduced')"
class="input"
type="text"
>
<div class="unit">ms</div>
</div>
</div>
<div class="field">
<div class="label">Poll for aspect ratio changes in background tabs:</div>
<div class="select">
<select v-model="settings.active.arDetect.polling.runInBackgroundTabs" @change="settings.saveWithoutReload">
<option :value="AardPollingOptions.No">Never</option>
<option :value="AardPollingOptions.Reduced">Use reduced polling rate</option>
<option :value="AardPollingOptions.Full">Use normal polling rate</option>
</select>
</div>
</div>
<div v-if="settings.active.arDetect.polling.runInBackgroundTabs === AardPollingOptions.Full" class="hint warn">
Using normal polling rate in background tabs is NOT recommended.
</div>
<div class="field">
<div class="label">Poll for aspect ratio changes in small players:</div>
<div class="select">
<select v-model="settings.active.arDetect.polling.runOnSmallVideos" @change="settings.saveWithoutReload">
<option :value="AardPollingOptions.No">Never</option>
<option :value="AardPollingOptions.Reduced">Use reduced polling rate</option>
<option :value="AardPollingOptions.Full">Use normal polling rate</option>
</select>
</div>
</div>
<div v-if="settings.active.arDetect.polling.runOnSmallVideos === AardPollingOptions.Full" class="hint warn">
Using normal polling rate on small videos is NOT recommended.
</div>
<div class="field">
<div class="label">Stop autodetection after first detection:</div>
<div class="select">
<select v-model="settings.active.arDetect.autoDisable.onFirstChange" @change="settings.saveWithoutReload">
<option :value="true">Yes</option>
<option :value="false">No</option>
</select>
</div>
</div>
<div class="field" :class="{disabled: settings.active.arDetect.autoDisable.onFirstChange}">
<div class="label">Stop autodetection if aspect ratio doesn't change for some time:</div>
<div class="select">
<select v-model="settings.active.arDetect.autoDisable.ifNotChanged" @change="settings.saveWithoutReload">
<option :value="true">Yes</option>
<option :value="false">No</option>
</select>
</div>
</div>
<div v-if="settings.active.arDetect.autoDisable.ifNotChanged" class="field">
<div class="label">Stop autodetection if aspect ratio doesn't change for:</div>
<div class="range-input">
<input
type="range"
:value="Math.log(settings.active.arDetect.autoDisable.ifNotChangedTimeout / 10)"
@change="setAutoDisableTimeout($event.target.value, 10)"
min="2.3"
max="9.3"
step="0.01"
/>
<input
:value="settings.active.arDetect.autoDisable.ifNotChangedTimeout / 1000"
@change="setAutoDisableTimeout($event.target.value, 1000)"
class="input"
type="text"
>
<div class="unit">s</div>
</div>
</div>
<div class="field">
<div class="label">Autodetection canvas type:</div>
<div class="select"> <div class="select">
<select v-model="settings.active.arDetect.aardType" @change="settings.saveWithoutReload"> <select v-model="settings.active.arDetect.aardType" @change="settings.saveWithoutReload">
<option value="auto">Automatic</option> <option value="auto">Automatic</option>
@ -258,13 +138,13 @@
<div class="input"> <div class="input">
<input v-model="settings.active.arDetect.allowedMisaligned" /> <input v-model="settings.active.arDetect.allowedMisaligned" />
</div> </div>
</div>
<div class="hint"> <div class="hint">
Ultrawidify detects letterbox only if video is vertically centered. Some people are bad at vertically Ultrawidify detects letterbox only if video is vertically centered. Some people are bad at vertically
centering the content, though. This is how off-center the video can be before autodetection will centering the content, though. This is how off-center the video can be before autodetection will
refuse to crop it (% of total height). refuse to crop it (% of total height).
</div> </div>
</div> </div>
</div>
<div v-if="settings.active.ui.devMode" class="settings-segment"> <div v-if="settings.active.ui.devMode" class="settings-segment">
<p> <p>
@ -310,6 +190,7 @@ import StretchType from '../../../common/enums/StretchType.enum';
import CropModePersistence from '../../../common/enums/CropModePersistence.enum'; import CropModePersistence from '../../../common/enums/CropModePersistence.enum';
import AlignmentOptionsControlComponent from './AlignmentOptionsControlComponent.vue'; import AlignmentOptionsControlComponent from './AlignmentOptionsControlComponent.vue';
import JsonEditor from '@csui/src/components/JsonEditor'; import JsonEditor from '@csui/src/components/JsonEditor';
import {AardPollingOptions} from '@src/ext/lib/aard/enums/aard-polling-options.enum';
export default { export default {
components: { components: {
@ -333,6 +214,9 @@ export default {
performanceData: {}, performanceData: {},
graphRefreshInterval: undefined, graphRefreshInterval: undefined,
settingsJson: {}, settingsJson: {},
// enums n stuff
AardPollingOptions,
} }
}, },
computed: { computed: {
@ -348,7 +232,7 @@ export default {
}, },
mounted() { mounted() {
this.eventBus.sendToTunnel('get-aard-timing'); this.eventBus.sendToTunnel('get-aard-timing');
this.graphRefreshInterval = setInterval(() => this.eventBus.sendToTunnel('get-aard-timing'), 500); // this.graphRefreshInterval = setInterval(() => this.eventBus.sendToTunnel('get-aard-timing'), 500);
this.resetSettingsEditor(); this.resetSettingsEditor();
}, },
destroyed() { destroyed() {
@ -359,8 +243,13 @@ export default {
async openOptionsPage() { async openOptionsPage() {
BrowserDetect.runtime.openOptionsPage(); BrowserDetect.runtime.openOptionsPage();
}, },
setArCheckFrequency(event) { setArCheckFrequency(event, timer) {
this.settings.active.arDetect.timers.playing = Math.floor(Math.pow(Math.E, event)); this.settings.active.arDetect.timers[timer ?? 'playing'] = Math.floor(Math.pow(Math.E, event));
this.settings.saveWithoutReload();
},
setAutoDisableTimeout(event, multiplier) {
this.settings.active.arDetect.autoDisable.ifNotChangedTimeout = Math.floor(Math.pow(Math.E, event)) * multiplier;
this.settings.saveWithoutReload();
}, },
refreshGraph() { refreshGraph() {
this.eventBus.sendToTunnel('get-aard-timing'); this.eventBus.sendToTunnel('get-aard-timing');

View File

@ -425,7 +425,6 @@ export default {
break; break;
} }
// console.log('getting data from:', settingsData);
try { try {
if ( if (
@ -594,8 +593,6 @@ export default {
setExtensionMode(component, event) { setExtensionMode(component, event) {
const option = event.target.value; const option = event.target.value;
console.log('SET EXTENSION MODE — OPTIONS:', option);
if (option === 'complex') { if (option === 'complex') {
return; return;
} }

View File

@ -9,18 +9,21 @@
<div class="info"> <div class="info">
Extension is not enabled for this site. Extension is not enabled for this site.
</div> </div>
<div> <div class="text-center">
Please enable extension for this site. <p>Please enable extension for this site.</p>
</div> </div>
<div> <div>
<button <button
class="flex flex-row items-center" class="flex flex-row items-center"
style="background-color: transparent; padding: 0.25rem 0.5rem; margin-top: 1rem;" style="background-color: transparent; padding: 0.5rem 1rem; margin-top: 1rem; border: 1px solid #fa68;"
@click="openSettings()" @click="openSettings()"
> >
Open settings <mdicon style="margin-left: 0.5rem;" name="open-in-new" size="16"></mdicon> Open settings <mdicon style="margin-left: 0.5rem;" name="open-in-new" size="16"></mdicon>
</button> </button>
</div> </div>
<div class="text-center">
<p><small>Extension may work on content embedded from other sites.</small></p>
</div>
</div> </div>
</template> </template>

View File

@ -251,7 +251,16 @@ const ExtensionConfPatch = Object.freeze([
} }
} }
} }
},
{
forVersion: '6.3.93',
updateFn: (userOptions: SettingsInterface, defaultOptions: SettingsInterface) => {
userOptions.arDetect.polling = defaultOptions.arDetect.polling;
userOptions.arDetect.subtitles = defaultOptions.arDetect.subtitles;
userOptions.arDetect.autoDisable = defaultOptions.arDetect.autoDisable;
} }
}
]); ]);

View File

@ -10,6 +10,7 @@ import SettingsInterface from '../../common/interfaces/SettingsInterface';
import BrowserDetect from './BrowserDetect'; import BrowserDetect from './BrowserDetect';
import { Extension } from 'typescript'; import { Extension } from 'typescript';
import EmbeddedContentSettingsOverridePolicy from '../../common/enums/EmbeddedContentSettingsOverridePolicy.enum'; import EmbeddedContentSettingsOverridePolicy from '../../common/enums/EmbeddedContentSettingsOverridePolicy.enum';
import { AardPollingOptions } from '../lib/aard/enums/aard-polling-options.enum';
if(Debug.debug) if(Debug.debug)
console.log("Loading: ExtensionConf.js"); console.log("Loading: ExtensionConf.js");
@ -22,6 +23,16 @@ const ExtensionConf: SettingsInterface = {
arDetect: { arDetect: {
aardType: 'auto', aardType: 'auto',
polling: {
runInBackgroundTabs: AardPollingOptions.Reduced,
runOnSmallVideos: AardPollingOptions.Reduced
},
subtitles: {
resetIfDetected: true,
resumeAfter: 5000,
},
earlyStopOptions: { earlyStopOptions: {
stopAfterFirstDetection: false, stopAfterFirstDetection: false,
stopAfterTimeout: false, stopAfterTimeout: false,
@ -41,12 +52,10 @@ const ExtensionConf: SettingsInterface = {
tickrate: 10, // 1 tick every this many milliseconds tickrate: 10, // 1 tick every this many milliseconds
}, },
autoDisable: { // settings for automatically disabling the extension autoDisable: { // settings for automatically disabling the extension
maxExecutionTime: 6000, // if execution time of main autodetect loop exceeds this many milliseconds, onFirstChange: false, // disable once we have a stable aspect ratio
// we disable it. ifNotChanged: false, // disable if Ar hasn't changed for this long
consecutiveTimeoutCount: 5, // we only do it if it happens this many consecutive times ifNotChangedTimeout: 20000, // if user enables ifNotChangedTimeout, we default to 20s
ifSubtitles: false, // disable if subtitles are detected
// FOR FUTURE USE
consecutiveArResets: 5 // if aspect ratio reverts immediately after AR change is applied, we disable everything
}, },
canvasDimensions: { canvasDimensions: {
blackframeCanvas: { // smaller than sample canvas, blackframe canvas is used to recon for black frames blackframeCanvas: { // smaller than sample canvas, blackframe canvas is used to recon for black frames

View File

@ -19,6 +19,7 @@ import { AardStatus, initAardStatus } from './interfaces/aard-status.interface';
import { AardTestResults, initAardTestResults, resetAardTestResults, resetGuardLine } from './interfaces/aard-test-results.interface'; import { AardTestResults, initAardTestResults, resetAardTestResults, resetGuardLine } from './interfaces/aard-test-results.interface';
import { AardTimers, initAardTimers } from './interfaces/aard-timers.interface'; import { AardTimers, initAardTimers } from './interfaces/aard-timers.interface';
import { ComponentLogger } from '../logging/ComponentLogger'; import { ComponentLogger } from '../logging/ComponentLogger';
import { AardPollingOptions } from './enums/aard-polling-options.enum';
/** /**
@ -232,7 +233,7 @@ export class Aard {
private eventBusCommands = { private eventBusCommands = {
'uw-environment-change': { 'uw-environment-change': {
function: (newEnvironment: ExtensionEnvironment) => { function: (newEnvironment: ExtensionEnvironment) => {
console.log('received extension environment:', newEnvironment, 'player env:', this.videoData?.player?.environment); // console.log('received extension environment:', newEnvironment, 'player env:', this.videoData?.player?.environment);
this.startCheck(); this.startCheck();
} }
}, },
@ -244,6 +245,11 @@ export class Aard {
this.hideDebugCanvas(); this.hideDebugCanvas();
} }
} }
},
'url-changed': {
function: () => {
this.clearAutoDisabled();
}
} }
// 'get-aard-timing': { // 'get-aard-timing': {
// function: () => this.handlePerformanceDataRequest() // function: () => this.handlePerformanceDataRequest()
@ -430,10 +436,19 @@ export class Aard {
} }
} }
/**
* Clears autoDisable flag
*/
clearAutoDisabled() {
this.status.autoDisabled = false;
this.timers.autoDisableAt = undefined;
}
/** /**
* Starts autodetection loop. * Starts autodetection loop.
*/ */
start() { start() {
this.clearAutoDisabled();
this.forceFullRecheck = true; this.forceFullRecheck = true;
if (this.videoData.resizer.lastAr.type === AspectRatioType.AutomaticUpdate) { if (this.videoData.resizer.lastAr.type === AspectRatioType.AutomaticUpdate) {
// ensure first autodetection will run in any case // ensure first autodetection will run in any case
@ -450,6 +465,11 @@ export class Aard {
this.status.aardActive = true; this.status.aardActive = true;
this.animationFrame = window.requestAnimationFrame( (ts: DOMHighResTimeStamp) => this.onAnimationFrame(ts)); this.animationFrame = window.requestAnimationFrame( (ts: DOMHighResTimeStamp) => this.onAnimationFrame(ts));
// set auto-disable timer if detection timeout is set
if (this.settings.active.arDetect.autoDisable.ifNotChanged) {
this.timers.autoDisableAt = Date.now() + this.settings.active.arDetect.autoDisable.ifNotChangedTimeout;
}
} }
/** /**
@ -482,24 +502,42 @@ export class Aard {
* @returns * @returns
*/ */
private canTriggerFrameCheck() { private canTriggerFrameCheck() {
// if (this._paused || this._halted || this._exited) {
// return false; // console.log('ard check status:', this.status);
// }
// if video was paused & we know that we already checked that frame, // if video was paused & we know that we already checked that frame,
// we will not check it again. // we will not check it again.
const videoState = this.getVideoPlaybackState(); const videoState = this.getVideoPlaybackState();
const polling = this.settings.active.arDetect.polling;
const now = Date.now();
if (videoState !== VideoPlaybackState.Playing) { if (videoState !== VideoPlaybackState.Playing) {
if (this.status.lastVideoStatus === videoState) { if (this.status.lastVideoStatus === videoState) {
return false; return false;
} }
} }
if (this.status.autoDisabled) {
return false;
}
if (this.timers.autoDisableAt < now) {
this.status.autoDisabled = true;
return false;
}
this.status.lastVideoStatus = videoState; this.status.lastVideoStatus = videoState;
const now = Date.now(); const tabVisible = document.visibilityState === 'visible';
if (!tabVisible && polling.runInBackgroundTabs === AardPollingOptions.No) {
return false;
}
if (this.videoData.player.isTooSmall && polling.runOnSmallVideos === AardPollingOptions.No) {
return false;
}
if (now < (this.videoData.player.isTooSmall ? this.timers.reducedPollingNextCheckTime : this.timers.nextFrameCheckTime)) { const isActive = (tabVisible || polling.runInBackgroundTabs !== AardPollingOptions.Reduced)
&& (!this.videoData.player.isTooSmall || polling.runOnSmallVideos !== AardPollingOptions.Reduced);
const nextCheck = isActive ? this.timers.nextFrameCheckTime : this.timers.reducedPollingNextCheckTime;
if (now < nextCheck) {
return false; return false;
} }
@ -508,6 +546,12 @@ export class Aard {
return true; return true;
} }
/**
* Bootstraps the main loop.
*
* Honestly this doesn't need description, but I want to put some green
* between two adjacent functions.
*/
private onAnimationFrame(ts: DOMHighResTimeStamp) { private onAnimationFrame(ts: DOMHighResTimeStamp) {
if (this.canTriggerFrameCheck()) { if (this.canTriggerFrameCheck()) {
resetAardTestResults(this.testResults); resetAardTestResults(this.testResults);
@ -671,7 +715,7 @@ export class Aard {
// console.warn('ASPECT RATIO UNCERTAIN, GUARD LINE INVALIDATED (resetting)') // console.warn('ASPECT RATIO UNCERTAIN, GUARD LINE INVALIDATED (resetting)')
this.timer.arChanged(); this.timer.arChanged();
this.updateAspectRatio(this.defaultAr); this.updateAspectRatio(this.defaultAr, {uncertainDetection: true});
break; break;
} }
@ -2027,14 +2071,12 @@ export class Aard {
/** /**
* Updates aspect ratio if new aspect ratio is different enough from the old one * Updates aspect ratio if new aspect ratio is different enough from the old one
*/ */
private updateAspectRatio(overrideAr?: number) { private updateAspectRatio(ar: number, options?: {uncertainDetection?: boolean}) {
const ar = overrideAr ?? this.getAr();
// Calculate difference between two ratios // Calculate difference between two ratios
const maxRatio = Math.max(ar, this.testResults.activeAspectRatio); const maxRatio = Math.max(ar, this.testResults.activeAspectRatio);
const diff = Math.abs(ar - this.testResults.activeAspectRatio); const diff = Math.abs(ar - this.testResults.activeAspectRatio);
if (overrideAr || (diff / maxRatio) > this.settings.active.arDetect.allowedArVariance) { if ((diff / maxRatio) > this.settings.active.arDetect.allowedArVariance) {
this.videoData.resizer.updateAr({ this.videoData.resizer.updateAr({
type: AspectRatioType.AutomaticUpdate, type: AspectRatioType.AutomaticUpdate,
ratio: this.getAr(), ratio: this.getAr(),
@ -2042,6 +2084,16 @@ export class Aard {
variant: this.arVariant variant: this.arVariant
}); });
this.testResults.activeAspectRatio = ar; this.testResults.activeAspectRatio = ar;
if (!options?.uncertainDetection) {
if (this.settings.active.arDetect.autoDisable.onFirstChange) {
this.status.autoDisabled = true;
}
if (this.settings.active.arDetect.autoDisable.ifNotChanged) {
this.timers.autoDisableAt = Date.now() + this.settings.active.arDetect.autoDisable.ifNotChangedTimeout;
}
}
} }
} }

View File

@ -0,0 +1,5 @@
export enum AardPollingOptions {
No = 0,
Reduced = 1,
Full = 2
}

View File

@ -5,7 +5,7 @@ export interface AardStatus {
aardReducedPolling: boolean, aardReducedPolling: boolean,
checkInProgress: boolean, checkInProgress: boolean,
lastVideoStatus: VideoPlaybackState, lastVideoStatus: VideoPlaybackState,
autoDisabled: boolean,
} }
export function initAardStatus(): AardStatus { export function initAardStatus(): AardStatus {
@ -14,5 +14,6 @@ export function initAardStatus(): AardStatus {
aardReducedPolling: true, aardReducedPolling: true,
checkInProgress: false, checkInProgress: false,
lastVideoStatus: VideoPlaybackState.NotInitialized, lastVideoStatus: VideoPlaybackState.NotInitialized,
autoDisabled: false,
} }
} }

View File

@ -1,4 +1,5 @@
export interface AardTimers { export interface AardTimers {
autoDisableAt: number | undefined;
nextFrameCheckTime: number; nextFrameCheckTime: number;
reducedPollingNextCheckTime: number; reducedPollingNextCheckTime: number;
} }
@ -7,5 +8,6 @@ export function initAardTimers(): AardTimers {
return { return {
nextFrameCheckTime: 0, nextFrameCheckTime: 0,
reducedPollingNextCheckTime: 0, reducedPollingNextCheckTime: 0,
autoDisableAt: undefined,
}; };
} }

View File

@ -111,15 +111,6 @@ class PageInfo {
this.scheduleUrlCheck(); this.scheduleUrlCheck();
document.addEventListener('fullscreenchange', this.fsEventListener); document.addEventListener('fullscreenchange', this.fsEventListener);
this.eventBus.subscribeMulti({
'probe-video': {
function: () => {
console.log(`[${window.location}] probe-video received.`)
this.rescan();
}
}
});
} }
destroy() { destroy() {
@ -413,11 +404,14 @@ class PageInfo {
let ths = this; let ths = this;
this.urlCheckTimer = setTimeout(function(){ this.urlCheckTimer = setTimeout(
function(){
ths.urlCheckTimer = null; ths.urlCheckTimer = null;
ths.ghettoUrlCheck(); ths.ghettoUrlCheck();
ths = null; ths = null;
}, this.settings.active.pageInfo.timeouts.urlCheck) },
this.settings.active.pageInfo.timeouts.urlCheck
);
} catch(e){ } catch(e){
this.logger.log('scheduleUrlCheck', "scheduling URL check failed. Here's why:",e) this.logger.log('scheduleUrlCheck', "scheduling URL check failed. Here's why:",e)
} }
@ -428,6 +422,7 @@ class PageInfo {
this.logger.warn('ghettoUrlCheck', "URL has changed. Triggering a rescan!"); this.logger.warn('ghettoUrlCheck', "URL has changed. Triggering a rescan!");
this.rescan(RescanReason.URL_CHANGE); this.rescan(RescanReason.URL_CHANGE);
this.eventBus.send("url-changed", {newUrl: window.location.href});
this.lastUrl = window.location.href; this.lastUrl = window.location.href;
} }