From c63821f8f61c41f66f790018f795db49778b0c14 Mon Sep 17 00:00:00 2001 From: WofWca Date: Sun, 11 Jun 2023 12:42:52 +0400 Subject: [PATCH] refactor: rearrange getOrCreateMediaElementSourceAndUpdateMap --- .../content/AllMediaElementsController.ts | 4 +- .../ElementPlaybackControllerCloning.ts | 9 +++- .../ElementPlaybackControllerStretching.ts | 10 +++- src/entry-points/content/audioContext.ts | 16 ------ ...tOrCreateMediaElementSourceAndUpdateMap.ts | 50 +++++++++++++++++++ 5 files changed, 68 insertions(+), 21 deletions(-) create mode 100644 src/entry-points/content/getOrCreateMediaElementSourceAndUpdateMap.ts diff --git a/src/entry-points/content/AllMediaElementsController.ts b/src/entry-points/content/AllMediaElementsController.ts index 823377d2..dedae307 100644 --- a/src/entry-points/content/AllMediaElementsController.ts +++ b/src/entry-points/content/AllMediaElementsController.ts @@ -36,7 +36,9 @@ import type { keydownEventToActions } from '@/hotkeys'; import broadcastStatus from './broadcastStatus'; import once from 'lodash/once'; import debounce from 'lodash/debounce'; -import { mediaElementSourcesMap } from '@/entry-points/content/audioContext'; +import { + mediaElementSourcesMap +} from '@/entry-points/content/getOrCreateMediaElementSourceAndUpdateMap'; import { lastPlaybackRateSetByThisExtensionMap, lastDefaultPlaybackRateSetByThisExtensionMap, setPlaybackRateAndRememberIt diff --git a/src/entry-points/content/ElementPlaybackControllerCloning/ElementPlaybackControllerCloning.ts b/src/entry-points/content/ElementPlaybackControllerCloning/ElementPlaybackControllerCloning.ts index 44a7c2fa..52779d2d 100644 --- a/src/entry-points/content/ElementPlaybackControllerCloning/ElementPlaybackControllerCloning.ts +++ b/src/entry-points/content/ElementPlaybackControllerCloning/ElementPlaybackControllerCloning.ts @@ -32,8 +32,10 @@ import VolumeFilterNode from '@/entry-points/content/VolumeFilter/VolumeFilterNo import lookaheadVolumeFilterSmoothing from './lookaheadVolumeFilterSmoothing.json' import { audioContext as commonAudioContext, - getOrCreateMediaElementSourceAndUpdateMap } from '@/entry-points/content/audioContext'; +import { + getOrCreateMediaElementSourceAndUpdateMap +} from '@/entry-points/content/getOrCreateMediaElementSourceAndUpdateMap'; import { setPlaybackRateAndRememberIt, setDefaultPlaybackRateAndRememberIt, @@ -363,7 +365,10 @@ export default class Controller { if (BUILD_DEFINITIONS.BROWSER === 'gecko') { const mozCaptureStreamUsed = !unprefixedCaptureStreamPresent; if (mozCaptureStreamUsed) { - const mediaElementSource = getOrCreateMediaElementSourceAndUpdateMap(element); + const [, mediaElementSource] = getOrCreateMediaElementSourceAndUpdateMap( + element, + () => commonAudioContext + ); mediaElementSource.connect(commonAudioContext.destination); } } diff --git a/src/entry-points/content/ElementPlaybackControllerStretching/ElementPlaybackControllerStretching.ts b/src/entry-points/content/ElementPlaybackControllerStretching/ElementPlaybackControllerStretching.ts index 5f3a4416..e92b634f 100644 --- a/src/entry-points/content/ElementPlaybackControllerStretching/ElementPlaybackControllerStretching.ts +++ b/src/entry-points/content/ElementPlaybackControllerStretching/ElementPlaybackControllerStretching.ts @@ -19,7 +19,10 @@ */ import browser from '@/webextensions-api'; -import { audioContext, getOrCreateMediaElementSourceAndUpdateMap } from '@/entry-points/content/audioContext'; +import { audioContext } from '@/entry-points/content/audioContext'; +import { + getOrCreateMediaElementSourceAndUpdateMap +} from '@/entry-points/content/getOrCreateMediaElementSourceAndUpdateMap'; import { getRealtimeMargin, getOptimalLookaheadDelay, @@ -291,7 +294,10 @@ export default class Controller { }); } - const mediaElementSource = getOrCreateMediaElementSourceAndUpdateMap(element); + const [, mediaElementSource] = getOrCreateMediaElementSourceAndUpdateMap( + element, + () => audioContext + ); let toDestinationChainLastConnectedLink: { connect: (destinationNode: AudioNode) => void } = mediaElementSource; if (this.isStretcherEnabled()) { diff --git a/src/entry-points/content/audioContext.ts b/src/entry-points/content/audioContext.ts index f66193e0..400ed01b 100644 --- a/src/entry-points/content/audioContext.ts +++ b/src/entry-points/content/audioContext.ts @@ -27,19 +27,3 @@ export const audioContext = new AudioContext({ // Would be cool if I was wrong. latencyHint: 'playback', }); - -// Doing it the way it's suggested in https://stackoverflow.com/a/39725071/10406353 -export const mediaElementSourcesMap: WeakMap = new WeakMap(); - -export function getOrCreateMediaElementSourceAndUpdateMap(element: HTMLMediaElement): MediaElementAudioSourceNode { - const srcFromMap = mediaElementSourcesMap.get(element); - let mediaElementSource: MediaElementAudioSourceNode; - if (srcFromMap) { - mediaElementSource = srcFromMap; - mediaElementSource.disconnect(); - } else { - mediaElementSource = audioContext.createMediaElementSource(element); - mediaElementSourcesMap.set(element, mediaElementSource) - } - return mediaElementSource; -} diff --git a/src/entry-points/content/getOrCreateMediaElementSourceAndUpdateMap.ts b/src/entry-points/content/getOrCreateMediaElementSourceAndUpdateMap.ts new file mode 100644 index 00000000..8ca6169b --- /dev/null +++ b/src/entry-points/content/getOrCreateMediaElementSourceAndUpdateMap.ts @@ -0,0 +1,50 @@ +/** + * @license + * Copyright (C) 2020, 2021, 2022, 2023 WofWca + * + * This file is part of Jump Cutter Browser Extension. + * + * Jump Cutter Browser Extension is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Jump Cutter Browser Extension is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with Jump Cutter Browser Extension. If not, see . + */ + +// Doing it the way it's suggested in https://stackoverflow.com/a/39725071/10406353 +export const mediaElementSourcesMap: + WeakMap + = new WeakMap(); + +/** + * @param getDefaultAudioContext must return an AudioContext that is gonna be used when + * `createMediaElementSource` has not been called for the `element` yet. + */ +export function getOrCreateMediaElementSourceAndUpdateMap( + element: HTMLMediaElement, + getDefaultAudioContext: () => AudioContext, +): [AudioContext, MediaElementAudioSourceNode] { + const fromMap = mediaElementSourcesMap.get(element); + // let mediaElementSource: MediaElementAudioSourceNode; + if (fromMap) { + const mediaElementSource = fromMap[1]; + // Act as if it's the first time that `createMediaElementSource` is called for the element + // (i.e. it's not connected to anything, not even `context.destination`). + mediaElementSource.disconnect(); + return fromMap; + } else { + const audioContext = getDefaultAudioContext(); + const mediaElementSource = audioContext.createMediaElementSource(element); + const tuple: [AudioContext, MediaElementAudioSourceNode] + = [audioContext, mediaElementSource]; + mediaElementSourcesMap.set(element, tuple); + return tuple; + } +}