From 48a2a131632049d3275634f126986d138fc4fc5a Mon Sep 17 00:00:00 2001 From: Araxeus <78568641+Araxeus@users.noreply.github.com> Date: Sat, 30 Oct 2021 12:00:29 +0300 Subject: [PATCH 1/8] fix playback speed plugin --- plugins/playback-speed/front.js | 104 +++++++++---------- plugins/playback-speed/templates/slider.html | 1 + providers/dom-elements.js | 21 +--- 3 files changed, 51 insertions(+), 75 deletions(-) diff --git a/plugins/playback-speed/front.js b/plugins/playback-speed/front.js index fff07fee..7d970e22 100644 --- a/plugins/playback-speed/front.js +++ b/plugins/playback-speed/front.js @@ -1,83 +1,77 @@ -const { - getSongMenu, - watchDOMElement, -} = require("../../providers/dom-elements"); +const { getSongMenu } = require("../../providers/dom-elements"); const { ElementFromFile, templatePath } = require("../utils"); +function $(selector) { return document.querySelector(selector); } + const slider = ElementFromFile(templatePath(__dirname, "slider.html")); const MIN_PLAYBACK_SPEED = 0.25; const MAX_PLAYBACK_SPEED = 2; -let videoElement; -let playbackSpeedPercentage = 50; // = Playback speed of 1 +let playbackSpeed = 1; -const computePlayBackSpeed = () => { - if (playbackSpeedPercentage <= 50) { +const computePlayBackSpeed = (playbackSpeedPercentage) => { + if (playbackSpeedPercentage <= 50) { // = Playback speed <= 1 // Slow down video by setting a playback speed between MIN_PLAYBACK_SPEED and 1 return ( MIN_PLAYBACK_SPEED + ((1 - MIN_PLAYBACK_SPEED) / 50) * playbackSpeedPercentage - ); + ).toFixed(2); } // Accelerate video by setting a playback speed between 1 and MAX_PLAYBACK_SPEED - return 1 + ((MAX_PLAYBACK_SPEED - 1) / 50) * (playbackSpeedPercentage - 50); + return (1 + ((MAX_PLAYBACK_SPEED - 1) / 50) * (playbackSpeedPercentage - 50)).toFixed(2); }; const updatePlayBackSpeed = () => { - const playbackSpeed = Math.round(computePlayBackSpeed() * 100) / 100; + $('video').playbackRate = playbackSpeed; - if (!videoElement || videoElement.playbackRate === playbackSpeed) { - return; - } - - videoElement.playbackRate = playbackSpeed; - - const playbackSpeedElement = document.querySelector("#playback-speed-value"); + const playbackSpeedElement = $("#playback-speed-value"); if (playbackSpeedElement) { playbackSpeedElement.innerHTML = playbackSpeed; } }; -module.exports = () => { - watchDOMElement( - "video", - (document) => document.querySelector("video"), - (element) => { - videoElement = element; - updatePlayBackSpeed(); +let menu; + +const observePopupContainer = () => { + const observer = new MutationObserver(() => { + if (!menu) { + menu = getSongMenu(); } - ); - watchDOMElement( - "menu", - (document) => getSongMenu(document), - (menuElement) => { - if (!menuElement.contains(slider)) { - menuElement.prepend(slider); - } - - const playbackSpeedElement = document.querySelector( - "#playback-speed-slider #sliderKnob .slider-knob-inner" - ); - - const playbackSpeedObserver = new MutationObserver((mutations) => { - mutations.forEach(function (mutation) { - if (mutation.type == "attributes") { - const value = playbackSpeedElement.getAttribute("value"); - playbackSpeedPercentage = parseInt(value, 10); - if (isNaN(playbackSpeedPercentage)) { - playbackSpeedPercentage = 50; - } - updatePlayBackSpeed(); - return; - } - }); - }); - playbackSpeedObserver.observe(playbackSpeedElement, { - attributes: true, - }); + if (menu && !menu.contains(slider)) { + menu.prepend(slider); + $('#playback-speed-slider').addEventListener("immediate-value-change", () => { + playbackSpeed = computePlayBackSpeed($('#playback-speed-slider #sliderBar').value); + if (isNaN(playbackSpeed)) { + playbackSpeed = 1; + } + updatePlayBackSpeed(); + }) } - ); + }); + + observer.observe($('ytmusic-popup-container'), { + childList: true, + subtree: true, + }); +}; + +const observeVideo = () => { + $('video').addEventListener('ratechange', forcePlaybackRate) + $('video').addEventListener('loadeddata', forcePlaybackRate) +} + +function forcePlaybackRate (e) { + if (e.target.playbackRate !== playbackSpeed) { + e.target.playbackRate = playbackSpeed + } +} + +module.exports = () => { + document.addEventListener('apiLoaded', e => { + observePopupContainer(); + observeVideo(); + }) }; diff --git a/plugins/playback-speed/templates/slider.html b/plugins/playback-speed/templates/slider.html index 85865af0..d12e00e9 100644 --- a/plugins/playback-speed/templates/slider.html +++ b/plugins/playback-speed/templates/slider.html @@ -13,6 +13,7 @@ { - const observer = new MutationObserver((mutations, observer) => { - if (!domElements[name]) { - domElements[name] = selectorFn(document); - } - - if (domElements[name]) { - cb(domElements[name]); - } - }); - - observer.observe(document, { - childList: true, - subtree: true, - }); -}; - const getSongMenu = () => document.querySelector("ytmusic-menu-popup-renderer tp-yt-paper-listbox"); -module.exports = { getSongMenu, watchDOMElement }; +module.exports = { getSongMenu }; From 754eac6ee074ab56f8221020c28abb4ea246df9f Mon Sep 17 00:00:00 2001 From: Araxeus <78568641+Araxeus@users.noreply.github.com> Date: Sat, 30 Oct 2021 12:14:04 +0300 Subject: [PATCH 2/8] use apiLoaded 'once' lint --- plugins/playback-speed/front.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/playback-speed/front.js b/plugins/playback-speed/front.js index 7d970e22..54cac30c 100644 --- a/plugins/playback-speed/front.js +++ b/plugins/playback-speed/front.js @@ -73,5 +73,5 @@ module.exports = () => { document.addEventListener('apiLoaded', e => { observePopupContainer(); observeVideo(); - }) + }, { once: true, passive: true }) }; From 6c1a4c0ac24dcbee02d2d613a3c1631518d4a0f8 Mon Sep 17 00:00:00 2001 From: Araxeus <78568641+Araxeus@users.noreply.github.com> Date: Sat, 30 Oct 2021 14:49:03 +0300 Subject: [PATCH 3/8] playbackSpeed wheel listener --- plugins/playback-speed/front.js | 32 ++++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/plugins/playback-speed/front.js b/plugins/playback-speed/front.js index 54cac30c..4d67cee4 100644 --- a/plugins/playback-speed/front.js +++ b/plugins/playback-speed/front.js @@ -5,6 +5,8 @@ function $(selector) { return document.querySelector(selector); } const slider = ElementFromFile(templatePath(__dirname, "slider.html")); +const roundToTwo = (n) => Math.round( n * 1e2 ) / 1e2; + const MIN_PLAYBACK_SPEED = 0.25; const MAX_PLAYBACK_SPEED = 2; @@ -20,7 +22,7 @@ const computePlayBackSpeed = (playbackSpeedPercentage) => { } // Accelerate video by setting a playback speed between 1 and MAX_PLAYBACK_SPEED - return (1 + ((MAX_PLAYBACK_SPEED - 1) / 50) * (playbackSpeedPercentage - 50)).toFixed(2); + return roundToTwo(1 + ((MAX_PLAYBACK_SPEED - 1) / 50) * (playbackSpeedPercentage - 50)); }; const updatePlayBackSpeed = () => { @@ -42,13 +44,6 @@ const observePopupContainer = () => { if (menu && !menu.contains(slider)) { menu.prepend(slider); - $('#playback-speed-slider').addEventListener("immediate-value-change", () => { - playbackSpeed = computePlayBackSpeed($('#playback-speed-slider #sliderBar').value); - if (isNaN(playbackSpeed)) { - playbackSpeed = 1; - } - updatePlayBackSpeed(); - }) } }); @@ -63,6 +58,26 @@ const observeVideo = () => { $('video').addEventListener('loadeddata', forcePlaybackRate) } +const setupSliderListeners = () => { + slider.addEventListener('immediate-value-change', () => { + playbackSpeed = computePlayBackSpeed($('#playback-speed-slider #sliderBar').value); + if (isNaN(playbackSpeed)) { + playbackSpeed = 1; + } + updatePlayBackSpeed(); + }) + slider.addEventListener('wheel', e => { + e.preventDefault(); + if (isNaN(playbackSpeed)) { + playbackSpeed = 1; + } + // e.deltaY < 0 means wheel-up 0.01 + playbackSpeed = roundToTwo(e.deltaY < 0 ? playbackSpeed + 0.01 : playbackSpeed - 0.01); + updatePlayBackSpeed(); + $('#playback-speed-slider').value = playbackSpeed * 50; + }) +} + function forcePlaybackRate (e) { if (e.target.playbackRate !== playbackSpeed) { e.target.playbackRate = playbackSpeed @@ -73,5 +88,6 @@ module.exports = () => { document.addEventListener('apiLoaded', e => { observePopupContainer(); observeVideo(); + setupSliderListeners(); }, { once: true, passive: true }) }; From 9bd089adb0c1cf7270bcef02589b315006753ead Mon Sep 17 00:00:00 2001 From: Araxeus <78568641+Araxeus@users.noreply.github.com> Date: Sat, 30 Oct 2021 14:54:00 +0300 Subject: [PATCH 4/8] add check for lowest playback speed (0.07) --- plugins/playback-speed/front.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plugins/playback-speed/front.js b/plugins/playback-speed/front.js index 4d67cee4..f88cd7d6 100644 --- a/plugins/playback-speed/front.js +++ b/plugins/playback-speed/front.js @@ -67,11 +67,12 @@ const setupSliderListeners = () => { updatePlayBackSpeed(); }) slider.addEventListener('wheel', e => { + if (playbackSpeed <= 0.07) return; // lowest possible speed e.preventDefault(); if (isNaN(playbackSpeed)) { playbackSpeed = 1; } - // e.deltaY < 0 means wheel-up 0.01 + // e.deltaY < 0 means wheel-up playbackSpeed = roundToTwo(e.deltaY < 0 ? playbackSpeed + 0.01 : playbackSpeed - 0.01); updatePlayBackSpeed(); $('#playback-speed-slider').value = playbackSpeed * 50; From 1434849142bb3834f47d83c5e8c79cacfc764743 Mon Sep 17 00:00:00 2001 From: Araxeus <78568641+Araxeus@users.noreply.github.com> Date: Sat, 30 Oct 2021 15:38:40 +0300 Subject: [PATCH 5/8] simplify playback rate steps --- plugins/playback-speed/front.js | 25 +++++++------------- plugins/playback-speed/templates/slider.html | 18 +++++++------- 2 files changed, 17 insertions(+), 26 deletions(-) diff --git a/plugins/playback-speed/front.js b/plugins/playback-speed/front.js index f88cd7d6..d56c31df 100644 --- a/plugins/playback-speed/front.js +++ b/plugins/playback-speed/front.js @@ -7,23 +7,11 @@ const slider = ElementFromFile(templatePath(__dirname, "slider.html")); const roundToTwo = (n) => Math.round( n * 1e2 ) / 1e2; -const MIN_PLAYBACK_SPEED = 0.25; -const MAX_PLAYBACK_SPEED = 2; +const MIN_PLAYBACK_SPEED = 0.07; let playbackSpeed = 1; -const computePlayBackSpeed = (playbackSpeedPercentage) => { - if (playbackSpeedPercentage <= 50) { // = Playback speed <= 1 - // Slow down video by setting a playback speed between MIN_PLAYBACK_SPEED and 1 - return ( - MIN_PLAYBACK_SPEED + - ((1 - MIN_PLAYBACK_SPEED) / 50) * playbackSpeedPercentage - ).toFixed(2); - } - - // Accelerate video by setting a playback speed between 1 and MAX_PLAYBACK_SPEED - return roundToTwo(1 + ((MAX_PLAYBACK_SPEED - 1) / 50) * (playbackSpeedPercentage - 50)); -}; +const computePlayBackSpeed = (playbackSpeedPercentage) => playbackSpeedPercentage || MIN_PLAYBACK_SPEED; const updatePlayBackSpeed = () => { $('video').playbackRate = playbackSpeed; @@ -67,15 +55,18 @@ const setupSliderListeners = () => { updatePlayBackSpeed(); }) slider.addEventListener('wheel', e => { - if (playbackSpeed <= 0.07) return; // lowest possible speed e.preventDefault(); if (isNaN(playbackSpeed)) { playbackSpeed = 1; } // e.deltaY < 0 means wheel-up - playbackSpeed = roundToTwo(e.deltaY < 0 ? playbackSpeed + 0.01 : playbackSpeed - 0.01); + playbackSpeed = roundToTwo(e.deltaY < 0 ? + playbackSpeed + 0.01 : + Math.max(playbackSpeed - 0.01, MIN_PLAYBACK_SPEED)); + updatePlayBackSpeed(); - $('#playback-speed-slider').value = playbackSpeed * 50; + // update slider position + $('#playback-speed-slider').value = playbackSpeed; }) } diff --git a/plugins/playback-speed/templates/slider.html b/plugins/playback-speed/templates/slider.html index d12e00e9..ebd98537 100644 --- a/plugins/playback-speed/templates/slider.html +++ b/plugins/playback-speed/templates/slider.html @@ -14,19 +14,19 @@ id="playback-speed-slider" class="volume-slider style-scope ytmusic-player-bar on-hover" style="display: inherit !important" - max="100" + max="2" min="0" - step="5" + step="0.125" dir="ltr" title="Playback speed" aria-label="Playback speed" role="slider" tabindex="0" aria-valuemin="0" - aria-valuemax="100" - aria-valuenow="50" + aria-valuemax="2" + aria-valuenow="1" aria-disabled="false" - value="50" + value="1" >
@@ -35,10 +35,10 @@ aria-hidden="true" class="style-scope tp-yt-paper-slider" role="progressbar" - value="50" - aria-valuenow="50" + value="1" + aria-valuenow="1" aria-valuemin="0" - aria-valuemax="100" + aria-valuemax="2" aria-disabled="false" style="touch-action: none" > @@ -71,7 +71,7 @@ >
From 6243e6fd489249474db06715cac69f8646f802ce Mon Sep 17 00:00:00 2001 From: Araxeus <78568641+Araxeus@users.noreply.github.com> Date: Sat, 30 Oct 2021 15:56:12 +0300 Subject: [PATCH 6/8] set max playback speed to 16 ;) --- plugins/playback-speed/front.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/plugins/playback-speed/front.js b/plugins/playback-speed/front.js index d56c31df..091c48c9 100644 --- a/plugins/playback-speed/front.js +++ b/plugins/playback-speed/front.js @@ -8,6 +8,7 @@ const slider = ElementFromFile(templatePath(__dirname, "slider.html")); const roundToTwo = (n) => Math.round( n * 1e2 ) / 1e2; const MIN_PLAYBACK_SPEED = 0.07; +const MAX_PLAYBACK_SPEED = 16; let playbackSpeed = 1; @@ -61,8 +62,9 @@ const setupSliderListeners = () => { } // e.deltaY < 0 means wheel-up playbackSpeed = roundToTwo(e.deltaY < 0 ? - playbackSpeed + 0.01 : - Math.max(playbackSpeed - 0.01, MIN_PLAYBACK_SPEED)); + math.min(playbackSpeed + 0.01, MAX_PLAYBACK_SPEED) : + Math.max(playbackSpeed - 0.01, MIN_PLAYBACK_SPEED) + ); updatePlayBackSpeed(); // update slider position From 29d5b3c7dbff9add1a983e2bd9f5a48459ba189f Mon Sep 17 00:00:00 2001 From: Araxeus <78568641+Araxeus@users.noreply.github.com> Date: Mon, 1 Nov 2021 16:02:27 +0200 Subject: [PATCH 7/8] lint --- plugins/playback-speed/front.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/plugins/playback-speed/front.js b/plugins/playback-speed/front.js index 091c48c9..ab2a975c 100644 --- a/plugins/playback-speed/front.js +++ b/plugins/playback-speed/front.js @@ -1,11 +1,11 @@ -const { getSongMenu } = require("../../providers/dom-elements"); +const { getSongMenu } = require("../../providers/dom-elements"); const { ElementFromFile, templatePath } = require("../utils"); function $(selector) { return document.querySelector(selector); } const slider = ElementFromFile(templatePath(__dirname, "slider.html")); -const roundToTwo = (n) => Math.round( n * 1e2 ) / 1e2; +const roundToTwo = (n) => Math.round(n * 1e2) / 1e2; const MIN_PLAYBACK_SPEED = 0.07; const MAX_PLAYBACK_SPEED = 16; @@ -61,8 +61,8 @@ const setupSliderListeners = () => { playbackSpeed = 1; } // e.deltaY < 0 means wheel-up - playbackSpeed = roundToTwo(e.deltaY < 0 ? - math.min(playbackSpeed + 0.01, MAX_PLAYBACK_SPEED) : + playbackSpeed = roundToTwo(e.deltaY < 0 ? + Math.min(playbackSpeed + 0.01, MAX_PLAYBACK_SPEED) : Math.max(playbackSpeed - 0.01, MIN_PLAYBACK_SPEED) ); @@ -72,7 +72,7 @@ const setupSliderListeners = () => { }) } -function forcePlaybackRate (e) { +function forcePlaybackRate(e) { if (e.target.playbackRate !== playbackSpeed) { e.target.playbackRate = playbackSpeed } From 41285ac9fc6d0e0f6b8b8ef130917c19d13bc09e Mon Sep 17 00:00:00 2001 From: Araxeus <78568641+Araxeus@users.noreply.github.com> Date: Mon, 1 Nov 2021 22:23:26 +0200 Subject: [PATCH 8/8] fix slider not working on tap --- plugins/playback-speed/front.js | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/plugins/playback-speed/front.js b/plugins/playback-speed/front.js index ab2a975c..f1ea78e8 100644 --- a/plugins/playback-speed/front.js +++ b/plugins/playback-speed/front.js @@ -24,6 +24,7 @@ const updatePlayBackSpeed = () => { }; let menu; +let observingSlider = false; const observePopupContainer = () => { const observer = new MutationObserver(() => { @@ -33,6 +34,10 @@ const observePopupContainer = () => { if (menu && !menu.contains(slider)) { menu.prepend(slider); + if (!observingSlider) { + setupSliderListener(); + observingSlider = true; + } } }); @@ -47,14 +52,7 @@ const observeVideo = () => { $('video').addEventListener('loadeddata', forcePlaybackRate) } -const setupSliderListeners = () => { - slider.addEventListener('immediate-value-change', () => { - playbackSpeed = computePlayBackSpeed($('#playback-speed-slider #sliderBar').value); - if (isNaN(playbackSpeed)) { - playbackSpeed = 1; - } - updatePlayBackSpeed(); - }) +const setupWheelListener = () => { slider.addEventListener('wheel', e => { e.preventDefault(); if (isNaN(playbackSpeed)) { @@ -72,6 +70,16 @@ const setupSliderListeners = () => { }) } +function setupSliderListener() { + $('#playback-speed-slider').addEventListener('immediate-value-changed', () => { + playbackSpeed = computePlayBackSpeed($('#playback-speed-slider #sliderBar').value); + if (isNaN(playbackSpeed)) { + playbackSpeed = 1; + } + updatePlayBackSpeed(); + }) +} + function forcePlaybackRate(e) { if (e.target.playbackRate !== playbackSpeed) { e.target.playbackRate = playbackSpeed @@ -82,6 +90,6 @@ module.exports = () => { document.addEventListener('apiLoaded', e => { observePopupContainer(); observeVideo(); - setupSliderListeners(); + setupWheelListener(); }, { once: true, passive: true }) };