Compare commits

..

No commits in common. "13cfb9ff1422b2c054591418ce645c56ab872e50" and "2337f7a3ba908b7922c19d3dcffb61cdcfeddcf2" have entirely different histories.

21 changed files with 259 additions and 1126 deletions

View File

@ -52,8 +52,6 @@ export type SettingsReloadComponent = 'PlayerData' | 'VideoData';
export type SettingsReloadFlags = true | SettingsReloadComponent; export type SettingsReloadFlags = true | SettingsReloadComponent;
export interface AardSettings { export interface AardSettings {
aardType: 'webgl' | 'legacy' | 'auto';
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.
// Any more and we don't adjust ar. // Any more and we don't adjust ar.

View File

@ -2,11 +2,12 @@
<div <div
class="context-spawn uw-ui-trigger" class="context-spawn uw-ui-trigger"
style="z-index: 1000" style="z-index: 1000"
@mouseenter="(ev) => setTriggerZoneActive(true, ev)"
@mouseleave="(ev) => setTriggerZoneActive(false, ev)"
> >
<div <div
class="spawn-container uw-trigger" class="spawn-container uw-trigger"
:style="triggerZoneStyles" :style="triggerZoneStyles"
@mouseenter="(ev) => setTriggerZoneActive(true, ev)"
> >
&nbsp; &nbsp;
</div> </div>
@ -29,14 +30,16 @@
</div> </div>
</template> </template>
<slot> <slot>
<div class="menu-width">
<GhettoContextMenuItem :disableHover="true" :css="{'ard-blocked': true}">
<div v-if="statusFlags.hasDrm || true" class="smallcaps text-center">
<b>NOTE:</b><br/>
<b>Autodetection<br/>blocked by website</b>
</div>
<div>
<!-- </div>
Didn't manage to ensure that extension status pops up above other menu items in less than 3 minutes with z-index, </GhettoContextMenuItem>
so wrapping 'status' and 'real menu items' in two different divs, ordering them in the opposite way, and then
ensuring correct ordering with flex-direction: column-reverse ended up being easier and faster.
-->
<div class="menu-width flex-reverse-order">
<div style="z-index: 1000">
<GhettoContextMenu alignment="right"> <GhettoContextMenu alignment="right">
<template v-slot:activator> <template v-slot:activator>
Crop Crop
@ -86,12 +89,12 @@
<!-- shortcut for configuring UI --> <!-- shortcut for configuring UI -->
<GhettoContextMenuOption <GhettoContextMenuOption
v-if="settings.active.newFeatureTracker?.['uw6.ui-popup']?.show > 0" v-if="settings.active.newFeatureTracker?.['uw6.ui-popup']?.show > 0"
@click="showUwWindow('playerUiSettings')" @click="showUwWindow('ui-config')"
> >
<span style="color: #fa6;">I hate this popup<br/></span> <span style="color: #fa6;">I hate this popup<br/></span>
<span style="font-size: 0.8em"> <span style="font-size: 0.8em">
<span style="text-transform: uppercase; font-size: 0.8em"> <span style="text-transform: uppercase; font-size: 0.8em">
<a @click="showUwWindow('playerUiSettings')"> <a @click="showUwWindow('ui-config')">
Do something about it Do something about it
</a> × <a @click="acknowledgeNewFeature('uw6.ui-popup')">keep the popup</a> </a> × <a @click="acknowledgeNewFeature('uw6.ui-popup')">keep the popup</a>
</span> </span>
@ -103,52 +106,23 @@
</GhettoContextMenuOption> </GhettoContextMenuOption>
<!-- --> <!-- -->
<GhettoContextMenuOption <GhettoContextMenuOption
@click="showUwWindow()" @click="showUwWindow()"
label="Extension settings" label="Extension settings"
> >
</GhettoContextMenuOption> </GhettoContextMenuOption>
<GhettoContextMenuOption
@click="showUwWindow('playerDetection')"
label="Incorrect cropping?"
>
</GhettoContextMenuOption>
<GhettoContextMenuOption <GhettoContextMenuOption
@click="showUwWindow('about')" @click="showUwWindow('about')"
label="Not working?" label="Not working?"
> >
</GhettoContextMenuOption> </GhettoContextMenuOption>
</div> </div>
<div style="z-index: 10000">
<GhettoContextMenuItem
class="extension-status-messages"
:disableHover="true"
>
Site compatibility:
<SupportLevelIndicator
:siteSupportLevel="siteSupportLevel"
>
</SupportLevelIndicator>
<div v-if="statusFlags.hasDrm" class="aard-blocked">
Autodetection potentially<br/>
unavailable due to <a href="https://en.wikipedia.org/wiki/Digital_rights_management">DRM</a>.
</div>
<div v-else-if="statusFlags.aardErrors?.cors" class="aard-blocked">
Autodetection blocked<br/>
by site/browser (CORS).
</div>
<div v-else-if="statusFlags.aardErrors?.webglError" class="aard-blocked">
Autodetection unavailable<br/>
due to webgl error.
</div>
</GhettoContextMenuItem>
</div>
</div>
</slot> </slot>
</GhettoContextMenu> </GhettoContextMenu>
</div> </div>
<div <div
v-if="settingsInitialized && uwWindowVisible" v-if="settingsInitialized && uwWindowVisible"
class="uw-window flex flex-col uw-clickable" class="uw-window flex flex-col uw-clickable"
@ -165,19 +139,6 @@
@preventClose="(event) => uwWindowFadeOutDisabled = event" @preventClose="(event) => uwWindowFadeOutDisabled = event"
></PlayerUIWindow> ></PlayerUIWindow>
</div> </div>
<div
class="context-spawn uw-ui-trigger"
style="z-index: 1000;"
>
<TriggerZoneEditor
class="uw-clickable"
:settings="settings"
:playerDimensions="playerDimensions"
>
</TriggerZoneEditor>
</div>
</template> </template>
<script> <script>
@ -193,8 +154,6 @@ import EventBus from '../ext/lib/EventBus';
import UIProbeMixin from './src/utils/UIProbeMixin'; import UIProbeMixin from './src/utils/UIProbeMixin';
import KeyboardShortcutParserMixin from './src/utils/KeyboardShortcutParserMixin'; import KeyboardShortcutParserMixin from './src/utils/KeyboardShortcutParserMixin';
import CommsMixin from './src/utils/CommsMixin'; import CommsMixin from './src/utils/CommsMixin';
import SupportLevelIndicator from './src/components/SupportLevelIndicator.vue';
import TriggerZoneEditor from './src/components/TriggerZoneEditor.vue';
export default { export default {
components: { components: {
@ -203,8 +162,6 @@ export default {
GhettoContextMenuItem, GhettoContextMenuItem,
GhettoContextMenuOption, GhettoContextMenuOption,
AlignmentOptionsControlComponent, AlignmentOptionsControlComponent,
SupportLevelIndicator,
TriggerZoneEditor,
}, },
mixins: [ mixins: [
UIProbeMixin, UIProbeMixin,
@ -263,13 +220,10 @@ export default {
statusFlags: { statusFlags: {
hasDrm: undefined, hasDrm: undefined,
aardErrors: undefined,
}, },
defaultWindowTab: 'videoSettings', defaultWindowTab: 'videoSettings',
saveState: {}, saveState: {},
siteSettings: undefined,
previewZoneVisible: false,
}; };
}, },
computed: { computed: {
@ -282,12 +236,6 @@ export default {
windowHeight() { windowHeight() {
return window.innerHeight; return window.innerHeight;
}, },
// LPT: NO ARROW FUNCTIONS IN COMPUTED,
// IS SUPER HARAM
// THINGS WILL NOT WORK IF YOU USE ARROWS
siteSupportLevel() {
return (this.site && this.siteSettings) ? this.siteSettings.data.type || 'no-support' : 'waiting';
}
}, },
watch: { watch: {
showUi(visible) { showUi(visible) {
@ -314,8 +262,6 @@ export default {
}); });
this.settings = new Settings({afterSettingsSaved: this.updateConfig, logger: this.logger}); this.settings = new Settings({afterSettingsSaved: this.updateConfig, logger: this.logger});
this.settings.listenAfterChange(() => this.updateTriggerZones());
await this.settings.init(); await this.settings.init();
this.settingsInitialized = true; this.settingsInitialized = true;
@ -326,20 +272,12 @@ export default {
}); });
this.eventBus.subscribe('uw-config-broadcast', {function: (data) => { this.eventBus.subscribe('uw-config-broadcast', {function: (data) => {
switch (data.type) { if (data.type === 'drm-status') {
case 'drm-status':
this.statusFlags.hasDrm = data.hasDrm; this.statusFlags.hasDrm = data.hasDrm;
break;
case 'aard-error':
this.statusFlags.aardErrors = data.aardErrors;
break;
case 'player-dimensions':
console.log('player dimensions response received.', data);
this.playerDimensionsUpdate(data.data);
break;
} }
}}); }});
this.eventBus.subscribe('uw-set-ui-state', { function: (data) => { this.eventBus.subscribe('uw-set-ui-state', { function: (data) => {
if (data.globalUiVisible !== undefined) { if (data.globalUiVisible !== undefined) {
if (this.isGlobal) { if (this.isGlobal) {
@ -380,19 +318,11 @@ export default {
} }
); );
this.eventBus.subscribe('ui-trigger-zone-update', {
function: (data) => {
this.showTriggerZonePreview = data.previewZoneVisible;
// this.;
}
});
this.sendToParentLowLevel('uwui-get-role', null); this.sendToParentLowLevel('uwui-get-role', null);
this.sendToParentLowLevel('uwui-get-theme', null); this.sendToParentLowLevel('uwui-get-theme', null);
this.sendToParentLowLevel('uw-bus-tunnel', { //
action: 'get-player-dimensions'
});
}, },
methods: { methods: {
@ -414,7 +344,6 @@ 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(this.site);
} }
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':
@ -623,34 +552,4 @@ export default {
// } // }
} }
.extension-status-messages {
z-index: 1000;
text-transform: uppercase;
display: flex;
flex-direction: column;
text-align: center;
width: 112.25%;
transform: translate(-12.5%, 12.5%) scale(0.75);
> * {
margin-top: 0.5rem;
margin-bottom: 0.5rem;
}
}
.flex-reverse-order {
display: flex;
flex-direction: column-reverse;
}
.aard-blocked {
color: #fa6;
}
.trigger-zone-preview {
border: 4px solid #fa4;
}
</style> </style>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 273 KiB

View File

@ -5,16 +5,52 @@
<div class="popup-window-header"> <div class="popup-window-header">
<div class="header-title"> <div class="header-title">
<div class="popup-title">Ultrawidify <small>{{settings?.active?.version}} - {{BrowserDetect.processEnvChannel}}</small></div> <div class="popup-title">Ultrawidify <small>{{settings?.active?.version}} - {{BrowserDetect.processEnvChannel}}</small></div>
<div class="site-support-info flex flex-row"> <div class="site-support-info">
<div class="site-support-site">{{site}}</div> <div class="site-support-site">{{site}}</div>
<SupportLevelIndicator <template v-if="inPlayer">
v-if="inPlayer" <div v-if="siteSupportLevel === 'official'" class="site-support official">
:siteSupportLevel="siteSupportLevel" <mdicon name="check-decagram" />
> <div>Verified</div>
</SupportLevelIndicator> <div class="tooltip">The extension is being tested and should work on this site.</div>
</div>
<div v-if="siteSupportLevel === 'community'" class="site-support community">
<mdicon name="handshake" />
<div>Community</div>
<div class="tooltip">
People say extension works on this site (or have provided help getting the extension to work if it didn't).<br/><br/>
Tamius (the dev) does not test the extension on this site, probably because it requires a subscription or
is geoblocked.
</div>
</div>
<div v-if="siteSupportLevel === 'no-support'" class="site-support no-support">
<mdicon name="help-circle-outline" />
<div>Unknown</div>
<div class="tooltip">
Not officially supported. Extension will try to fix things, but no promises.<br/><br/>
Tamius (the dev) does not test the extension on this site for various reasons
(unaware, not using the site, language barrier, geoblocking, paid services Tam doesn't use).
</div>
</div>
<div v-if="siteSupportLevel === 'user-added'" class="site-support user-added">
<mdicon name="account" />
<div>Custom</div>
<div class="tooltip">
You have manually changed settings for this site. The extension is doing what you told it to do.
</div>
</div>
<mdicon v-if="siteSupportLevel === 'community'" class="site-support supported" name="checkbox-marked-circle" />
</template>
</div> </div>
</div> </div>
<div class="header-buttons"> <div class="header-buttons">
<div
class="header-button"
:class="{'button-active': preventClose}"
@click="setPreventClose(!preventClose)"
>
<mdicon v-if="!preventClose" name="pin-outline" :size="32" />
<mdicon v-else name="pin" :size="32" />
</div>
<div <div
class="header-button close-button" class="header-button close-button"
@click="$emit('close')" @click="$emit('close')"
@ -83,12 +119,6 @@
:site="site" :site="site"
> >
</PlayerDetectionPanel> </PlayerDetectionPanel>
<PlayerUiSettings
v-if="selectedTab === 'playerUiSettings'"
:settings="settings"
:eventBus="eventBus"
>
</PlayerUiSettings>
<BaseExtensionSettings <BaseExtensionSettings
v-if="selectedTab === 'extensionSettings'" v-if="selectedTab === 'extensionSettings'"
:settings="settings" :settings="settings"
@ -117,11 +147,6 @@
v-if="selectedTab === 'about'" v-if="selectedTab === 'about'"
> >
</AboutPanel> </AboutPanel>
<ResetBackupPanel
v-if="selectedTab === 'resetBackup'"
:settings="settings"
>
</ResetBackupPanel>
</div> </div>
</div> </div>
</div> </div>
@ -136,10 +161,6 @@ import VideoSettings from './PlayerUiPanels/VideoSettings.vue'
import BrowserDetect from '../../ext/conf/BrowserDetect' import BrowserDetect from '../../ext/conf/BrowserDetect'
import ChangelogPanel from './PlayerUiPanels/ChangelogPanel.vue' import ChangelogPanel from './PlayerUiPanels/ChangelogPanel.vue'
import AboutPanel from './PlayerUiPanels/AboutPanel.vue' import AboutPanel from './PlayerUiPanels/AboutPanel.vue'
import PlayerUiSettings from './PlayerUiPanels/PlayerUiSettings.vue'
import ResetBackupPanel from './PlayerUiPanels/ResetBackupPanel.vue'
import SupportLevelIndicator from './components/SupportLevelIndicator.vue'
export default { export default {
components: { components: {
@ -148,11 +169,8 @@ export default {
BaseExtensionSettings, BaseExtensionSettings,
AutodetectionSettingsPanel, AutodetectionSettingsPanel,
DebugPanel, DebugPanel,
PlayerUiSettings,
ChangelogPanel, ChangelogPanel,
AboutPanel, AboutPanel
SupportLevelIndicator,
ResetBackupPanel,
}, },
mixins: [], mixins: [],
data() { data() {
@ -164,14 +182,12 @@ export default {
tabs: [ tabs: [
// {id: 'videoSettings', label: 'Video settings', icon: 'crop'}, // {id: 'videoSettings', label: 'Video settings', icon: 'crop'},
{id: 'extensionSettings', label: 'Site and Extension options', icon: 'cogs' }, {id: 'extensionSettings', label: 'Site and Extension options', icon: 'cogs' },
{id: 'playerUiSettings', label: 'In-player interface', icon: 'movie-cog-outline' },
{id: 'playerDetection', label: 'Player detection', icon: 'television-play'}, {id: 'playerDetection', label: 'Player detection', icon: 'television-play'},
{id: 'autodetectionSettings', label: 'Autodetection options', icon: 'auto-fix'}, {id: 'autodetectionSettings', label: 'Autodetection options', icon: ''},
// {id: 'advancedOptions', label: 'Advanced options', icon: 'cogs' }, // {id: 'advancedOptions', label: 'Advanced options', icon: 'cogs' },
// {id: 'debugging', label: 'Debugging', icon: 'bug-outline' } // {id: 'debugging', label: 'Debugging', icon: 'bug-outline' }
{id: 'changelog', label: 'What\'s new', icon: 'alert-decagram' }, {id: 'changelog', label: 'What\'s new', icon: 'information-box-outline' },
{id: 'about', label: 'About', icon: 'information-outline'}, {id: 'about', label: 'About', icon: 'star-four-points-circle'}
{id: 'resetBackup', label: 'Reset and backup', icon: 'file-restore-outline'},
], ],
selectedTab: 'extensionSettings', selectedTab: 'extensionSettings',
BrowserDetect: BrowserDetect, BrowserDetect: BrowserDetect,
@ -254,6 +270,86 @@ export default {
overflow: hidden; overflow: hidden;
} }
.site-support-info {
display: flex;
flex-direction: row;
align-items: center;
.site-support-site {
font-size: 1.5em;
}
.site-support {
display: inline-flex;
flex-direction: row;
align-items: center;
margin-left: 1rem;
border-radius: 8px;
padding: 0rem 1.5rem 0rem 1rem;
position: relative;
.tooltip {
padding: 1rem;
display: none;
position: absolute;
bottom: 0;
transform: translateY(110%);
width: 42em;
background-color: rgba(0,0,0,0.90);
color: #ccc;
}
&:hover {
.tooltip {
display: block;
}
}
.mdi {
margin-right: 1rem;
}
&.official {
background-color: #fa6;
color: #000;
.mdi {
fill: #000 !important;
}
}
&.community {
background-color: rgb(85, 85, 179);
color: #fff;
.mdi {
fill: #fff !important;
}
}
&.no-support {
background-color: rgb(138, 65, 126);
color: #eee;
.mdi {
fill: #eee !important;
}
}
&.user-added {
border: 1px solid #ff0;
color: #ff0;
.mdi {
fill: #ff0 !important;
}
}
}
}
.content { .content {
flex-grow: 1; flex-grow: 1;
@ -294,16 +390,6 @@ export default {
} }
.site-support-info {
display: flex;
flex-direction: row;
align-items: bottom;
.site-support-site {
font-size: 1.5em;
}
}
.popup-panel { .popup-panel {
background-color: rgba(0,0,0,0.50); background-color: rgba(0,0,0,0.50);
color: #fff; color: #fff;

View File

@ -5,19 +5,6 @@
<h1>What's new</h1> <h1>What's new</h1>
<p>Full changelog for older versions <a href="https://github.com/tamius-han/ultrawidify/blob/master/CHANGELOG.md" target="_blank">is available here</a>.</p> <p>Full changelog for older versions <a href="https://github.com/tamius-han/ultrawidify/blob/master/CHANGELOG.md" target="_blank">is available here</a>.</p>
<h2>6.2.0</h2>
<p>
There's been another major change that skips a version.
</p>
<ul>
<li>Parts of automatic aspect ratio detection use WebGL now. This should result in improved performance. Slightly underwhelming blog post about this issue can be found <a href="https://stuff.tamius.net/sacred-texts/2024/10/02/hot-dang-i-shouldnt-have-given-on-webgl/" target="_blank">here</a>.</li>
<li>In-player UI now indicates whether a site is having a problem with automatic aspect ratio detection.</li>
<li>UI improvements</li>
</ul>
<p>
Since automatic aspect ratio detection had to be rewritten completely and since the new version needs to be out 5 days ago, there are some regressions in the automatic aspect ratio detection.
</p>
<h2>6.0.1</h2> <h2>6.0.1</h2>
<p>Fixed external links.</p> <p>Fixed external links.</p>
@ -55,6 +42,17 @@
Panning option that's a bit more intuitive. Panning option that's a bit more intuitive.
</li> --> </li> -->
</ul> </ul>
<h3>Unbaked features</h3>
<ul>
<li>
<b>Player UI settings</b>. Ultrawidify doesn't always correctly identify which area the video should fill, especially when not in full screen mode.
Version 6.0.0 was intended to come with UI that makes it easier for you to "help" ultrawidify by identifying the correct player element. Alas, I was
busier than expected and manifest v3 deadline came faster than expected.
</li>
<li>
<b>Disabling Ultrawidify UI trigger zone, or otherwise changing target area size and position, is not possible</b>.
</li>
</ul>
<h3>Regressions</h3> <h3>Regressions</h3>
<ul> <ul>
<li> <li>
@ -92,7 +90,7 @@ export default({
], ],
mounted() { mounted() {
this.settings.active.whatsNewChecked = true; this.settings.active.whatsNewChecked = true;
this.settings.saveWithoutReload(); this.settings.save();
} }
}); });
</script> </script>

View File

@ -1,254 +0,0 @@
<template>
<div class="flex flex-col" style="position: relative; width: 100%;">
<!-- The rest of the tab is under 'edit ratios and shortcuts' row -->
<div class="flex flex-col" style="width: 100%">
<h2>Player UI options</h2>
<div class="field">
<div class="label">Enable in-player UI</div>
<input type="checkbox" v-model="settings.active.ui.inPlayer.enabled" />
</div>
<div
class="flex flex-col"
:class="{disabled: settings.active.ui.inPlayer.enabled}"
>
<div class="field">
<div class="label">Enable only in full screen</div>
<input type="checkbox" v-model="settings.active.ui.inPlayer.enabledFullscreenOnly" />
</div>
<div class="field">
<div class="label">
Popup activator position:
</div>
<div class="select">
<select
v-model="settings.active.ui.inPlayer.alignment"
@click="setUiOption('alignment', $event)"
>
<option value="left">Left</option>
<option value="right">Right</option>
</select>
</div>
</div>
<div class="field">
<div class="label">
Activate in-player UI:
</div>
<div class="select">
<select
v-model="settings.active.ui.inPlayer.activation"
@click="setUiOption('', $event)"
>
<option value="player">
When mouse hovers over player
</option>
<option value="trigger-zone">
When mouse hovers over trigger zone
</option>
</select>
</div>
</div>
<div class="field">
<div class="label">Edit trigger zone:</div>
<button>Edit</button>
</div>
<div v-if="settings.active.ui.inPlayer.activation === 'trigger-zone'">
<div class="trigger-zone-editor">
<div class="heading">
<h3>Trigger zone editor</h3>
</div>
<div class="field">
<div class="label">Trigger zone width:</div>
<div class="input range-input">
<input
v-model="settings.active.ui.inPlayer.triggerZoneDimensions.width"
class="slider"
type="range"
min="0.1"
max="1"
step="0.01"
>
<input
:value="(settings.active.ui.inPlayer.triggerZoneDimensions.width * 100).toFixed(2)"
@input="(event) => setTriggerZoneSize('width', event.target.value)"
>
</div>
<div class="hint">
Width of the trigger zone (% of player area).
</div>
</div>
<div class="field">
<div class="label">Trigger zone height:</div>
<div class="input range-input">
<input
v-model="settings.active.ui.inPlayer.triggerZoneDimensions.height"
type="range"
min="0.1"
max="1"
step="0.01"
>
<input
:value="(settings.active.ui.inPlayer.triggerZoneDimensions.height * 100).toFixed(2)"
@input="(event) => setTriggerZoneSize('width', event.target.value)"
>
</div>
<div class="hint">
Height of the trigger zone (% of player area).
</div>
</div>
<div class="field">
<div class="label">Trigger zone horizontal offset:</div>
<div class="input range-input">
<input
v-model="settings.active.ui.inPlayer.triggerZoneDimensions.offsetX"
type="range"
min="-100"
max="100"
>
<input
v-model="settings.active.ui.inPlayer.triggerZoneDimensions.offsetX"
>
</div>
<div class="hint">
By default, trigger zone is centered around the button. This option moves trigger zone left and right.
</div>
</div>
<div class="field">
<div class="label">Trigger zone vertical offset:</div>
<div class="input range-input">
<input
v-model="settings.active.ui.inPlayer.triggerZoneDimensions.offsetY"
type="range"
min="-100"
max="100"
>
<input
v-model="settings.active.ui.inPlayer.triggerZoneDimensions.offsetY"
>
</div>
<div class="hint">
By default, trigger zone is centered around the button. This option moves trigger zone up and down.
</div>
</div>
</div>
</div>
<div class="field">
<div class="label">
Do not show in-player UI when video player is narrower than (% of screen width)
</div>
<div>TODO: slider</div>
</div>
</div>
</div>
</div>
</template>
<script>
import Button from '../components/Button.vue'
import BrowserDetect from '../../../ext/conf/BrowserDetect';
export default {
data() {
return {
}
},
mixins: [
],
props: [
'settings', // required for buttons and actions, which are global
'eventBus',
],
created() {
},
mounted() {
},
components: {
Button,
},
methods: {
setUiPage(key, event) {
},
forceNumber(value) {
// Change EU format to US if needed
// | remove everything after second period if necessary
// | | | remove non-numeric characters
// | | | |
return value.replaceAll(',', '.').split('.', 2).join('.').replace(/[^0-9.]/g, '');
},
setTriggerZoneSize(key, value) {
let size = (+this.forceNumber(value) / 100);
if (isNaN(+size)) {
size = 0.5;
}
this.settings.active.ui.inPlayer.triggerZoneDimensions[key] = size;
this.settings.saveWithoutReload();
},
async openOptionsPage() {
BrowserDetect.runtime.openOptionsPage();
},
}
}
</script>
<style lang="scss" src="../../res/css/flex.scss" scoped module></style>
<style lang="scss" src="../res-common/panels.scss" scoped module></style>
<style lang="scss" src="../res-common/common.scss" scoped module></style>
<style lang="scss" scoped>
.justify-center {
justify-content: center;
}
.items-center {
align-items: center;
}
.mt-4{
margin-top: 1rem;
}
.input {
max-width: 24rem;
}
.range-input {
display: flex;
flex-direction: row;
* {
margin-left: 0.5rem;
margin-right: 0.5rem;
}
input {
max-width: 5rem;
}
input[type=range] {
max-width: none;
}
}
.trigger-zone-editor {
background-color: rgba(0,0,0,0.25);
padding-bottom: 2rem;
.field {
margin-bottom: -1em;
}
}
</style>

View File

@ -1,30 +0,0 @@
<template>
<div class="flex flex-col">
<h1>Reset and backup</h1>
<p>
Pressing the button will reset settings to default without asking.
</p>
<button
class="danger"
@click="resetSettings"
>
Reset settings
</button>
</div>
</template>
<script>
export default {
props: {
settings: Object
},
methods: {
resetSettings() {
this.settings.active = JSON.parse(JSON.stringify(this.settings.default));
this.settings.saveWithoutReload();
}
}
}
</script>
<style lang="scss" src="../../res/css/flex.scss" scoped module></style>
<style lang="scss" src="../res-common/panels.scss" scoped module></style>
<style lang="scss" src="../res-common/common.scss" scoped module></style>

View File

@ -1,17 +0,0 @@
<template>
<div>
</div>
</template>
<script>
export default {
props: {
siteSettings: Object,
hasDrm: Boolean,
problems: Object,
}
}
</script>
<style lang="scss">
</style>

View File

@ -1,137 +0,0 @@
<template>
<div v-if="siteSupportLevel === 'official'" class="site-support official">
<mdicon name="check-decagram" />
<div v-if="!small">Verified</div>
<div class="tooltip">
<template v-if="small">Verified&nbsp;&nbsp;</template>
The extension is being tested and should work on this site.
</div>
</div>
<div v-if="siteSupportLevel === 'community'" class="site-support community">
<mdicon name="handshake" />
<div v-if="!small">Community</div>
<div class="tooltip">
<template v-if="small">Community&nbsp;&nbsp;</template>
People say extension works on this site (or have provided help getting the extension to work if it didn't).<br/><br/>
Tamius (the dev) does not test the extension on this site, probably because it requires a subscription or
is geoblocked.
</div>
</div>
<div v-if="siteSupportLevel === 'no-support'" class="site-support no-support">
<mdicon name="help-circle-outline" />
<div v-if="!small">Unknown</div>
<div class="tooltip">
<template v-if="small">Unknown&nbsp;&nbsp;</template>
Not officially supported. Extension will try to fix things, but no promises.<br/><br/>
Tamius (the dev) does not test the extension on this site for various reasons
(unaware, not using the site, language barrier, geoblocking, paid services Tam doesn't use).
</div>
</div>
<div v-if="siteSupportLevel === 'user-added'" class="site-support user-added">
<mdicon name="account" />
<div v-if="!small">Custom</div>
<div class="tooltip">
<template v-if="small">Custom&nbsp;&nbsp;</template>
You have manually changed settings for this site. The extension is doing what you told it to do.
</div>
</div>
<div v-if="siteSupportLevel === 'community'">
<mdicon class="site-support no-support" name="checkbox-marked-circle" />
<div v-if="!small">Not supported</div>
<div class="tooltip">
<template v-if="small">Not supported&nbsp;&nbsp;</template>
Extension is known to not work with this site.
</div>
</div>
</template>
<script>
export default {
props: {
siteSupportLevel: String,
small: Boolean,
}
}
</script>
<style lang="scss" scoped>
.site-support {
display: inline-flex;
flex-direction: row;
align-items: center;
margin-left: 1rem;
border-radius: 8px;
padding: 0rem 1.5rem 0rem 1rem;
position: relative;
.tooltip {
padding: 1rem;
display: none;
position: absolute;
bottom: 0;
transform: translateY(110%);
width: 42em;
background-color: rgba(0,0,0,0.90);
color: #ccc;
z-index: 99999 !important;
white-space: normal;
overflow-wrap: break-word;
word-wrap: break-word;
word-break: break-word;
}
&:hover {
.tooltip {
display: block;
}
}
.mdi {
margin-right: 1rem;
}
&.official {
background-color: #fa6;
color: #000;
.mdi {
fill: #000 !important;
}
}
&.community {
background-color: rgb(85, 85, 179);
color: #fff;
.mdi {
fill: #fff !important;
}
}
&.no-support {
background-color: rgb(132, 24, 40);
color: #eee;
.mdi {
fill: #eee !important;
}
}
&.user-added {
border: 1px solid #ff0;
color: #ff0;
.mdi {
fill: #ff0 !important;
}
}
}
</style>

View File

@ -1,196 +0,0 @@
<template>
<div
v-if="settings?.active?.ui"
class="active-trigger-area uw-clickable"
:style="triggerZoneStyles"
>
<div class="trigger-zone-editor"
@mousedown="(event) => handleMouseDown('offset', event)"
>
<div
class="uw-clickable tl"
@mousedown.stop="(event) => handleMouseDown('tl', event)"
>
XX
</div>
<div
class="uw-clickable tr"
@mousedown.stop="(event) => handleMouseDown('tr', event)"
>
XX
</div>
<div
class="uw-clickable bl"
@mousedown.stop="(event) => handleMouseDown('bl', event)"
>
XX
</div>
<div
class="uw-clickable br"
@mousedown.stop="(event) => handleMouseDown('br', event)"
>
XX
</div>
</div>
</div>
</template>
<script>
export default {
props: [
'settings',
'playerDimensions',
],
watch: {
playerDimensions(newVal, oldVal) {
console.log('triggerzone -- dimensions changed!', this.playerDimensions, newVal, oldVal);
this.updateTriggerZones();
}
},
data() {
return {
triggerZoneStyles: {},
activeCornerDrag: undefined,
dragStartPosition: undefined,
dragStartConfiguration: undefined,
}
},
created() {
document.addEventListener("mouseup", this.handleMouseUp);
document.addEventListener("mousemove", this.handleMouseMove);
},
methods: {
updateTriggerZones() {
if (this.playerDimensions && this.settings?.active?.ui?.inPlayer?.triggerZoneDimensions) {
this.triggerZoneStyles = {
width: `${Math.round(this.playerDimensions.width * this.settings.active.ui.inPlayer.triggerZoneDimensions.width)}px`,
height: `${Math.round(this.playerDimensions.height * this.settings.active.ui.inPlayer.triggerZoneDimensions.height)}px`,
transform: `translate(${(this.settings.active.ui.inPlayer.triggerZoneDimensions.offsetX)}%, ${this.settings.active.ui.inPlayer.triggerZoneDimensions.offsetY}%)`,
};
}
},
handleMouseDown(corner, event) {
this.activeCornerDrag = corner;
// we need to save this because we don't know the location of the player element,
// just its dimensions ... that means we need to
this.dragStartPosition = {
x: event.clientX,
y: event.clientY
};
this.dragStartConfiguration = JSON.parse(JSON.stringify(this.settings.active.ui.inPlayer.triggerZoneDimensions));
console.log(`Mousedown on ${corner}`);
},
handleMouseUp(event) {
if (!this.activeCornerDrag) {
return;
}
this.activeCornerDrag = undefined;
this.settings.saveWithoutReload();
},
handleMouseMove(event) {
if (!this.activeCornerDrag) {
return;
}
if (this.activeCornerDrag === 'offset') {
this.handleMove(event);
} else {
this.handleResize(event);
}
this.updateTriggerZones();
},
handleResize(event) {
// drag distance in px
const dx = event.clientX - this.dragStartPosition.x;
const dy = event.clientY - this.dragStartPosition.y;
// convert drag distance to % of current width:
const dxr = dx / this.playerDimensions.width * 2;
const dyr = dy / this.playerDimensions.height * 2;
// // update settings:
let nw, nh;
switch (this.activeCornerDrag) {
case 'tl':
nw = this.dragStartConfiguration.width - dxr;
nh = this.dragStartConfiguration.height - dyr;
break;
case 'tr':
nw = this.dragStartConfiguration.width + dxr;
nh = this.dragStartConfiguration.height - dyr;
break;
case 'bl':
nw = this.dragStartConfiguration.width - dxr;
nh = this.dragStartConfiguration.height + dyr;
break;
case 'br':
nw = this.dragStartConfiguration.width + dxr;
nh = this.dragStartConfiguration.height + dyr;
break;
}
// ensure everything is properly limited
const cw = Math.min(0.95, Math.max(0.125, nw));
const ch = Math.min(0.95, Math.max(0.125, nh));
// // update properties
this.settings.active.ui.inPlayer.triggerZoneDimensions.width = cw;
this.settings.active.ui.inPlayer.triggerZoneDimensions.height = ch;
},
handleMove(event) {
const dx = event.clientX - this.dragStartPosition.x;
const dy = event.clientY - this.dragStartPosition.y;
// convert drag distance to % of current width:
const dxr = dx / this.playerDimensions.width;
const dyr = dy / this.playerDimensions.height;
// const [min, max] = this.settings.active.ui.inPlayer.popupAlignment === 'right' ? [5, 90] : [-90, -5];
// const [minCrossAxis, maxCrossAxis] = [-90, 90];
const min = -90;
const max = -5;
const minCrossAxis = -90;
const maxCrossAxis = 90;
const cx = Math.min(max, Math.max(min, this.settings.active.ui.inPlayer.triggerZoneDimensions.offsetX + dxr));
const cy = Math.min(maxCrossAxis, Math.max(minCrossAxis, this.settings.active.ui.inPlayer.triggerZoneDimensions.offsetY + dyr));
this.settings.active.ui.inPlayer.triggerZoneDimensions.offsetX = cx;
this.settings.active.ui.inPlayer.triggerZoneDimensions.offsetY = cy;
}
}
}
</script>
<style lang="scss" scoped>
.active-trigger-area {
background-image: url('/res/img/grid_512.webp');
}
.trigger-zone-editor {
width: 100%;
height: 100%;
position: relative;
> * {
position: absolute;
}
.tr, .tl {
top: 0;
}
.br, .bl {
bottom: 0;
}
.tl, .bl {
left: 0;
}
.tr, .br {
right: 0;
}
}
</style>

View File

@ -30,7 +30,7 @@ h1, h2, h3 {
padding: 0; padding: 0;
} }
button, .button { .button {
background-color: rgba($blackBg, $normalTransparentOpacity); background-color: rgba($blackBg, $normalTransparentOpacity);
padding: 0.5rem 2rem; padding: 0.5rem 2rem;
@ -51,11 +51,6 @@ button, .button {
background-color: $primaryBg; background-color: $primaryBg;
border-color: rgba($primary, .5); border-color: rgba($primary, .5);
} }
&.danger {
background-color: #ff2211 !important;
color:#000;
}
} }
.b3 { .b3 {
margin: 0.25rem; margin: 0.25rem;

View File

@ -26,28 +26,14 @@ export default {
}, },
methods: { methods: {
playerDimensionsUpdate(dimensions) { playerDimensionsUpdate(dimensions) {
if (!dimensions.width || !dimensions.height) {
this.playerDimensions = undefined;
}
console.log('player dimensions update received:', dimensions);
if (dimensions?.width !== this.playerDimensions?.width || dimensions?.height !== this.playerDimensions?.height) { if (dimensions?.width !== this.playerDimensions?.width || dimensions?.height !== this.playerDimensions?.height) {
console.log('Player dimensions changed!', dimensions);
this.playerDimensions = dimensions; this.playerDimensions = dimensions;
this.updateTriggerZones();
}
},
updateTriggerZones() {
console.log('triggered zone style recheck. player dims:', this.playerDimensions, 'in player settings:', this.settings.active.ui);
if (this.playerDimensions && this.settings) {
this.triggerZoneStyles = { this.triggerZoneStyles = {
width: `${Math.round(this.playerDimensions.width * this.settings.active.ui.inPlayer.triggerZoneDimensions.width)}px`, height: `${this.playerDimensions.height * 0.5}px`,
height: `${Math.round(this.playerDimensions.height * this.settings.active.ui.inPlayer.triggerZoneDimensions.height)}px`, width: `${this.playerDimensions.width * 0.5}px`,
transform: `translate(${(this.settings.active.ui.inPlayer.triggerZoneDimensions.offsetX)}%, ${this.settings.active.ui.inPlayer.triggerZoneDimensions.offsetY}%)`, transform: `translate(${(this.settings.active.ui.inPlayer.triggerZoneDimensions.offsetX)}%, ${this.settings.active.ui.inPlayer.triggerZoneDimensions.offsetY}%)`,
}; };
console.log(
'player trigger zone css:', this.triggerZoneStyles
);
} }
}, },

View File

@ -166,7 +166,6 @@ const ExtensionConfPatch = [
for (const domOption in userOptions.sites[site].DOMConfig) for (const domOption in userOptions.sites[site].DOMConfig)
userOptions.sites[site].DOMConfig[domOption].customCss; userOptions.sites[site].DOMConfig[domOption].customCss;
} }
userOptions.arDetect.aardType = 'auto';
userOptions.ui = { userOptions.ui = {
inPlayer: { inPlayer: {
enabled: true, // enable by default on new installs enabled: true, // enable by default on new installs

View File

@ -15,7 +15,6 @@ if(Debug.debug)
const ExtensionConf: SettingsInterface = { const ExtensionConf: SettingsInterface = {
arDetect: { arDetect: {
aardType: 'auto',
disabledReason: "", // if automatic aspect ratio has been disabled, show reason disabledReason: "", // if automatic aspect ratio has been disabled, show reason
allowedMisaligned: 0.05, // top and bottom letterbox thickness can differ by this much. allowedMisaligned: 0.05, // top and bottom letterbox thickness can differ by this much.
// Any more and we don't adjust ar. // Any more and we don't adjust ar.

View File

@ -36,9 +36,6 @@ class Settings {
//#region callbacks //#region callbacks
onSettingsChanged: any; onSettingsChanged: any;
afterSettingsSaved: any; afterSettingsSaved: any;
onChangedCallbacks: any[] = [];
afterSettingsChangedCallbacks: any[] = [];
//#endregion //#endregion
constructor(options) { constructor(options) {
@ -66,31 +63,15 @@ class Settings {
this.logger?.log('info', 'debug', 'Does parsedSettings.preventReload exist?', parsedSettings.preventReload, "Does callback exist?", !!this.onSettingsChanged); this.logger?.log('info', 'debug', 'Does parsedSettings.preventReload exist?', parsedSettings.preventReload, "Does callback exist?", !!this.onSettingsChanged);
if (!parsedSettings.preventReload) { if (!parsedSettings.preventReload && this.onSettingsChanged) {
try { try {
for (const fn of this.onChangedCallbacks) {
try {
fn();
} catch (e) {
this.logger?.log('warn', 'settings', "[Settings] afterSettingsChanged fallback failed. It's possible that a vue component got destroyed, and this function is nothing more than vestigal remains. It would be nice if we implemented something that allows us to remove callback functions from array, and remove vue callbacks from the callback array when their respective UI component gets destroyed. Or this could be an error with the function itself. IDK, here's the error.", e)
}
}
if (this.onSettingsChanged) {
this.onSettingsChanged(); this.onSettingsChanged();
}
this.logger?.log('info', 'settings', '[Settings] Update callback finished.') this.logger?.log('info', 'settings', '[Settings] Update callback finished.')
} catch (e) { } catch (e) {
this.logger?.log('error', 'settings', "[Settings] CALLING UPDATE CALLBACK FAILED. Reason:", e) this.logger?.log('error', 'settings', "[Settings] CALLING UPDATE CALLBACK FAILED. Reason:", e)
} }
} }
for (const fn of this.afterSettingsChangedCallbacks) {
try {
fn();
} catch (e) {
this.logger?.log('warn', 'settings', "[Settings] afterSettingsChanged fallback failed. It's possible that a vue component got destroyed, and this function is nothing more than vestigal remains. It would be nice if we implemented something that allows us to remove callback functions from array, and remove vue callbacks from the callback array when their respective UI component gets destroyed. Or this could be an error with the function itself. IDK, here's the error.", e)
}
}
if (this.afterSettingsSaved) { if (this.afterSettingsSaved) {
this.afterSettingsSaved(); this.afterSettingsSaved();
} }
@ -198,7 +179,6 @@ class Settings {
updateFn(this.active, this.getDefaultSettings()); updateFn(this.active, this.getDefaultSettings());
} catch (e) { } catch (e) {
this.logger?.log('error', 'settings', '[Settings::applySettingsPatches] Failed to execute update function. Keeping settings object as-is. Error:', e); this.logger?.log('error', 'settings', '[Settings::applySettingsPatches] Failed to execute update function. Keeping settings object as-is. Error:', e);
} }
} }
@ -378,13 +358,6 @@ class Settings {
getSiteSettings(site: string = window.location.hostname): SiteSettings { getSiteSettings(site: string = window.location.hostname): SiteSettings {
return new SiteSettings(this, site); return new SiteSettings(this, site);
} }
listenOnChange(fn: () => void): void {
this.onChangedCallbacks.push(fn);
}
listenAfterChange(fn: () => void): void {
this.afterSettingsChangedCallbacks.push(fn);
}
} }
export default Settings; export default Settings;

View File

@ -5,7 +5,6 @@ import Settings from '../Settings';
import VideoData from '../video-data/VideoData'; import VideoData from '../video-data/VideoData';
import { Corner } from './enums/corner.enum'; import { Corner } from './enums/corner.enum';
import { VideoPlaybackState } from './enums/video-playback-state.enum'; import { VideoPlaybackState } from './enums/video-playback-state.enum';
import { FallbackCanvas } from './gl/FallbackCanvas';
import { GlCanvas } from './gl/GlCanvas'; import { GlCanvas } from './gl/GlCanvas';
import { AardCanvasStore } from './interfaces/aard-canvas-store.interface'; import { AardCanvasStore } from './interfaces/aard-canvas-store.interface';
import { AardDetectionSample, generateSampleArray, resetSamples } from './interfaces/aard-detection-sample.interface'; import { AardDetectionSample, generateSampleArray, resetSamples } from './interfaces/aard-detection-sample.interface';
@ -235,8 +234,6 @@ export class Aard {
//#region internal state //#region internal state
public status: AardStatus = initAardStatus(); public status: AardStatus = initAardStatus();
private timers: AardTimers = initAardTimers(); private timers: AardTimers = initAardTimers();
private inFallback: boolean = false;
private fallbackReason: any;
private canvasStore: AardCanvasStore; private canvasStore: AardCanvasStore;
private testResults: AardTestResults; private testResults: AardTestResults;
private canvasSamples: AardDetectionSample; private canvasSamples: AardDetectionSample;
@ -248,8 +245,6 @@ export class Aard {
return undefined; return undefined;
} }
this.video.setAttribute('crossOrigin', 'anonymous');
const ratio = this.video.videoWidth / this.video.videoHeight; const ratio = this.video.videoWidth / this.video.videoHeight;
if (isNaN(ratio)) { if (isNaN(ratio)) {
return undefined; return undefined;
@ -289,10 +284,8 @@ export class Aard {
* This method should only ever be called from constructor. * This method should only ever be called from constructor.
*/ */
private init() { private init() {
this.canvasStore = { this.canvasStore = {
main: this.createCanvas('main-gl') main: new GlCanvas(new GlCanvas({...this.settings.active.arDetect.canvasDimensions.sampleCanvas, id: 'main-gl'})),
}; };
@ -309,42 +302,6 @@ export class Aard {
this.start(); this.start();
} }
private createCanvas(canvasId: string, canvasType?: 'webgl' | 'fallback') {
if (canvasType) {
if (canvasType === this.settings.active.arDetect.aardType || this.settings.active.arDetect.aardType === 'auto') {
if (canvasType === 'webgl') {
return new GlCanvas({...this.settings.active.arDetect.canvasDimensions.sampleCanvas, id: 'main-gl'});
} else if (canvasType === 'fallback') {
return new FallbackCanvas({...this.settings.active.arDetect.canvasDimensions.sampleCanvas, id: 'main-fallback'});
} else {
// TODO: throw error
}
} else {
// TODO: throw error
}
}
if (['auto', 'webgl'].includes(this.settings.active.arDetect.aardType)) {
try {
return new GlCanvas({...this.settings.active.arDetect.canvasDimensions.sampleCanvas, id: 'main-gl'});
} catch (e) {
if (this.settings.active.arDetect.aardType !== 'webgl') {
return new FallbackCanvas({...this.settings.active.arDetect.canvasDimensions.sampleCanvas, id: 'main-fallback'});
}
console.error('[ultrawidify|Aard::createCanvas] could not create webgl canvas:', e);
this.eventBus.send('uw-config-broadcast', {type: 'aard-error', aardErrors: {webglError: true}});
throw e;
}
} else if (this.settings.active.arDetect.aardType === 'legacy') {
return new FallbackCanvas({...this.settings.active.arDetect.canvasDimensions.sampleCanvas, id: 'main-fallback'});
} else {
console.error('[ultrawidify|Aard::createCanvas] invalid value in settings.arDetect.aardType:', this.settings.active.arDetect.aardType);
this.eventBus.send('uw-config-broadcast', {type: 'aard-error', aardErrors: {invalidSettings: true}});
throw 'AARD_INVALID_SETTINGS';
}
}
//#endregion //#endregion
/** /**
@ -436,35 +393,8 @@ export class Aard {
do { do {
const imageData = await new Promise<Uint8Array>( const imageData = await new Promise<Uint8Array>(
resolve => { resolve => {
try {
this.canvasStore.main.drawVideoFrame(this.video); this.canvasStore.main.drawVideoFrame(this.video);
resolve(this.canvasStore.main.getImageData()); resolve(this.canvasStore.main.getImageData());
} catch (e) {
if (e.name === 'SecurityError') {
this.eventBus.send('uw-config-broadcast', {type: 'aard-error', aardErrors: {cors: true}});
this.stop();
}
if (this.canvasStore.main instanceof FallbackCanvas) {
if (this.inFallback) {
this.eventBus.send('uw-config-broadcast', {type: 'aard-error', aardErrors: this.fallbackReason});
this.stop();
} else {
this.eventBus.send('uw-config-broadcast', {type: 'aard-error', aardErrors: {fallbackCanvasError: true}});
this.stop();
}
} else {
if (this.settings.active.arDetect.aardType === 'auto') {
this.canvasStore.main.destroy();
this.canvasStore.main = this.createCanvas('main-gl', 'fallback');
}
this.inFallback = true;
this.fallbackReason = {cors: true};
if (this.settings.active.arDetect.aardType !== 'auto') {
this.stop();
}
}
}
} }
); );
@ -477,7 +407,6 @@ export class Aard {
); );
if (this.testResults.notLetterbox) { if (this.testResults.notLetterbox) {
// TODO: reset aspect ratio to "AR not applied" // TODO: reset aspect ratio to "AR not applied"
console.log('NOT LETTERBOX!');
this.testResults.lastStage = 1; this.testResults.lastStage = 1;
break; break;
} }
@ -491,7 +420,6 @@ export class Aard {
this.settings.active.arDetect.canvasDimensions.sampleCanvas.width, this.settings.active.arDetect.canvasDimensions.sampleCanvas.width,
this.settings.active.arDetect.canvasDimensions.sampleCanvas.height this.settings.active.arDetect.canvasDimensions.sampleCanvas.height
); );
console.log('LETTERBOX SHRINK CHECK RESULT — IS GUARDLINE INVALIDATED?', this.testResults.guardLine.invalidated)
if (! this.testResults.guardLine.invalidated) { if (! this.testResults.guardLine.invalidated) {
this.checkLetterboxGrow( this.checkLetterboxGrow(
imageData, imageData,
@ -524,17 +452,12 @@ export class Aard {
// if detection is uncertain, we don't do anything at all // if detection is uncertain, we don't do anything at all
if (this.testResults.aspectRatioUncertain) { if (this.testResults.aspectRatioUncertain) {
console.info('aspect ratio not cettain.');
console.warn('check finished:', JSON.parse(JSON.stringify(this.testResults)), JSON.parse(JSON.stringify(this.canvasSamples)), '\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n');
return; return;
} }
// TODO: emit debug values if debugging is enabled // TODO: emit debug values if debugging is enabled
this.testResults.isFinished = true; this.testResults.isFinished = true;
console.warn('check finished:', JSON.parse(JSON.stringify(this.testResults)), JSON.parse(JSON.stringify(this.canvasSamples)), '\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n');
// if edge width changed, emit update event. // if edge width changed, emit update event.
if (this.testResults.aspectRatioUpdated) { if (this.testResults.aspectRatioUpdated) {
this.videoData.resizer.updateAr({ this.videoData.resizer.updateAr({
@ -1085,12 +1008,7 @@ export class Aard {
// fact that it makes the 'if' statement governing gradient detection // fact that it makes the 'if' statement governing gradient detection
// bit more nicely visible (instead of hidden among spagheti) // bit more nicely visible (instead of hidden among spagheti)
this.edgeScan(imageData, width, height); this.edgeScan(imageData, width, height);
console.log('edge scan:', JSON.parse(JSON.stringify(this.canvasSamples)));
this.validateEdgeScan(imageData, width, height); this.validateEdgeScan(imageData, width, height);
console.log('edge scan post valid:', JSON.parse(JSON.stringify(this.canvasSamples)));
// TODO: _if gradient detection is enabled, then: // TODO: _if gradient detection is enabled, then:
this.sampleForGradient(imageData, width, height); this.sampleForGradient(imageData, width, height);
@ -1143,7 +1061,6 @@ export class Aard {
x = 0; x = 0;
isImage = false; isImage = false;
finishedRows = 0; finishedRows = 0;
while (row < topEnd) { while (row < topEnd) {
i = 0; i = 0;
rowOffset = row * 4 * width; rowOffset = row * 4 * width;
@ -1209,7 +1126,6 @@ export class Aard {
|| imageData[rowOffset + x + 2] > this.testResults.blackLevel; || imageData[rowOffset + x + 2] > this.testResults.blackLevel;
if (!isImage) { if (!isImage) {
// console.log('(row:', row, ')', 'val:', imageData[rowOffset + x], 'col', x >> 2, x, 'pxoffset:', rowOffset + x, 'len:', imageData.length)
// TODO: maybe some day mark this pixel as checked by writing to alpha channel // TODO: maybe some day mark this pixel as checked by writing to alpha channel
i++; i++;
continue; continue;
@ -1356,7 +1272,6 @@ export class Aard {
// didn't change meaningfully from the first, in which chance we aren't. If the brightness increased // didn't change meaningfully from the first, in which chance we aren't. If the brightness increased
// anywhere between 'not enough' and 'too much', we mark the measurement as invalid. // anywhere between 'not enough' and 'too much', we mark the measurement as invalid.
if (lastSubpixel - firstSubpixel > this.settings.active.arDetect.edgeDetection.gradientTestMinDelta) { if (lastSubpixel - firstSubpixel > this.settings.active.arDetect.edgeDetection.gradientTestMinDelta) {
console.log('sample invalidated cus gradient:');
this.canvasSamples.top[i] = -1; this.canvasSamples.top[i] = -1;
} }
} }
@ -1730,26 +1645,6 @@ export class Aard {
const compensatedWidth = fileAr === canvasAr ? this.canvasStore.main.width : this.canvasStore.main.width * fileAr; const compensatedWidth = fileAr === canvasAr ? this.canvasStore.main.width : this.canvasStore.main.width * fileAr;
console.log(`
ASPECT RATIO CALCULATION:
canvas size: ${this.canvasStore.main.width} x ${this.canvasStore.main.height} (1:${this.canvasStore.main.width / this.canvasStore.main.height})
file size: ${this.video.videoWidth} x ${this.video.videoHeight} (1:${this.video.videoWidth / this.video.videoHeight})
compensated size: ${compensatedWidth} x ${this.canvasStore.main.height} (1:${compensatedWidth / this.canvasStore.main.height})
letterbox height: ${this.testResults.letterboxWidth}
net video height: ${this.canvasStore.main.height - (this.testResults.letterboxWidth * 2)}
calculated aspect ratio -----
${compensatedWidth} ${compensatedWidth} ${compensatedWidth}
= = = ${compensatedWidth / (this.canvasStore.main.height - (this.testResults.letterboxWidth * 2))}
${this.canvasStore.main.height} - 2 x ${this.testResults.letterboxWidth} ${this.canvasStore.main.height} - ${2 * this.testResults.letterboxWidth} ${this.canvasStore.main.height - (this.testResults.letterboxWidth * 2)}
`);
return compensatedWidth / (this.canvasStore.main.height - (this.testResults.letterboxWidth * 2)); return compensatedWidth / (this.canvasStore.main.height - (this.testResults.letterboxWidth * 2));
} }

View File

@ -1,36 +0,0 @@
import { GlCanvas, GlCanvasOptions } from './GlCanvas';
export class FallbackCanvas extends GlCanvas {
context: CanvasRenderingContext2D;
constructor(options: GlCanvasOptions) {
super(options);
}
/**
* We need to override the following methods in order to avoid default behaviour,
* since these methods in GlCanvas touch some webGL properties that we cannot really
* touch in this class.
*/
destroy() { }
protected initContext() {
this.context = this.canvas.getContext('2d', {desynchronized: true});
}
protected initWebgl() { }
drawVideoFrame(video: HTMLVideoElement) {
console.log('context:', this.context, 'canvas:', this.canvas );
this.context.drawImage(video, this.context.canvas.width, this.context.canvas.height);
}
getImageData() {
this.frameBuffer = this.context.getImageData(0,0,this.context.canvas.width,this.context.canvas.height).data as any as Uint8Array;
return this.frameBuffer;
}
}

View File

@ -71,7 +71,7 @@ export class GlCanvas {
private frameBufferSize: number; private frameBufferSize: number;
private _frameBuffer: Uint8Array; private _frameBuffer: Uint8Array;
protected set frameBuffer(x: Uint8Array) { private set frameBuffer(x: Uint8Array) {
this._frameBuffer = x; this._frameBuffer = x;
} }
public get frameBuffer(): Uint8Array { public get frameBuffer(): Uint8Array {
@ -95,7 +95,16 @@ export class GlCanvas {
this.canvas.setAttribute('width', `${options.width}`); this.canvas.setAttribute('width', `${options.width}`);
this.canvas.setAttribute('height', `${options.height}`); this.canvas.setAttribute('height', `${options.height}`);
this.initContext(options); this.gl = this.canvas.getContext('webgl');
if (!this.gl) {
throw new Error('WebGL not supported');
}
if(options.id) {
this.canvas.setAttribute('id', options.id);
}
this.frameBufferSize = options.width * options.height * 4;
this.initWebgl(); this.initWebgl();
} }
@ -109,7 +118,7 @@ export class GlCanvas {
} }
/** /**
* Reads pixels from the canvas into framebuffer, and returns pointer to the framebuffer * Reads pixels from the canvas
* @returns * @returns
*/ */
getImageData(): Uint8Array { getImageData(): Uint8Array {
@ -147,25 +156,7 @@ export class GlCanvas {
this.gl.deleteTexture(this.texture); this.gl.deleteTexture(this.texture);
} }
protected initContext(options: GlCanvasOptions) { private initWebgl() {
this.gl = this.canvas.getContext(
'webgl2',
{
preserveDrawingBuffer: true
}
);
if (!this.gl) {
throw new Error('WebGL not supported');
}
if(options.id) {
this.canvas.setAttribute('id', options.id);
}
this.frameBufferSize = options.width * options.height * 4;
}
protected initWebgl() {
// Initialize the GL context // Initialize the GL context
this.gl.clearColor(0.0, 0.0, 0.0, 1.0); this.gl.clearColor(0.0, 0.0, 0.0, 1.0);
this.gl.clear(this.gl.COLOR_BUFFER_BIT); this.gl.clear(this.gl.COLOR_BUFFER_BIT);

View File

@ -97,16 +97,6 @@ class PlayerData {
'get-player-tree': [{ 'get-player-tree': [{
function: () => this.handlePlayerTreeRequest() function: () => this.handlePlayerTreeRequest()
}], }],
'get-player-dimensions': [{
function: () => {
console.log('received get player dimensions! -- returning:', this.dimensions)
this.eventBus.send('uw-config-broadcast', {
type: 'player-dimensions',
data: this.dimensions
});
}
}],
'set-mark-element': [{ // NOTE: is this still used? 'set-mark-element': [{ // NOTE: is this still used?
function: (data) => this.markElement(data) function: (data) => this.markElement(data)
}], }],
@ -381,10 +371,6 @@ class PlayerData {
this.eventBus.send('restore-ar', null); this.eventBus.send('restore-ar', null);
this.eventBus.send('delayed-restore-ar', {delay: 500}); this.eventBus.send('delayed-restore-ar', {delay: 500});
// this.videoData.resizer?.restore(); // this.videoData.resizer?.restore();
this.eventBus.send('uw-config-broadcast', {
type: 'player-dimensions',
data: newDimensions
});
} }
} }
@ -392,7 +378,6 @@ class PlayerData {
this.trackDimensionChanges(); this.trackDimensionChanges();
} }
//#region player element change detection //#region player element change detection
/** /**
* Starts change detection. * Starts change detection.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 273 KiB

View File

@ -203,8 +203,7 @@ const config = {
'process.env.CHANNEL': JSON.stringify(process.env.CHANNEL), 'process.env.CHANNEL': JSON.stringify(process.env.CHANNEL),
'__VUE_OPTIONS_API__': true, '__VUE_OPTIONS_API__': true,
'__VUE_PROD_DEVTOOLS__': false, '__VUE_PROD_DEVTOOLS__': false
'__VUE_PROD_HYDRATION_MISMATCH_DETAILS__': true
}) })
], ],
optimization: { optimization: {