@@ -0,0 +1,52 @@ | |||||
import delay from 'delay'; | |||||
async function tryUntilItWorks(func, delayBetweenTries = 1, maxTries = 10) { | |||||
for (let i = 0; i < maxTries; i++) { | |||||
try { | |||||
await func(); | |||||
return; | |||||
} catch (err) { | |||||
await delay(delayBetweenTries); | |||||
continue; | |||||
} | |||||
} | |||||
} | |||||
async function onHeadersReceived({ responseHeaders, url, tabId }) { | |||||
const isAudio = responseHeaders.some(header => | |||||
header.name === 'Content-Type' && header.value.startsWith('audio/') | |||||
); | |||||
if (isAudio) { | |||||
// Avoid any short glitch of sound (observed in Firefox) before our injected script executes. | |||||
await browser.tabs.update(tabId, { muted: true }); | |||||
// Too quickly executing the script may fail (bug in Firefox), so we retry if necessary. | |||||
await tryUntilItWorks(() => browser.tabs.executeScript(tabId, { | |||||
runAt: 'document_end', | |||||
file: '/scripts/contentscript.js', | |||||
})); | |||||
// Unmute again. | |||||
await browser.tabs.update(tabId, { muted: false }); | |||||
await tryUntilItWorks(() => browser.tabs.insertCSS(tabId, { | |||||
runAt: 'document_end', | |||||
file: '/assets/main.css', | |||||
})); | |||||
await tryUntilItWorks(() => browser.tabs.insertCSS(tabId, { | |||||
runAt: 'document_end', | |||||
file: '/assets/waveform-playlist.css', | |||||
})); | |||||
} | |||||
} | |||||
browser.webRequest.onHeadersReceived.addListener( | |||||
onHeadersReceived, | |||||
{ | |||||
urls: ['<all_urls>'], | |||||
types: ['main_frame'], | |||||
}, | |||||
['responseHeaders'], | |||||
); |
@@ -0,0 +1,88 @@ | |||||
import * as WaveformPlaylist from 'waveform-playlist'; | |||||
import delay from 'delay'; | |||||
async function init() { | |||||
document.body.innerHTML = ` | |||||
<main> | |||||
<div id="controls"> | |||||
<button id="playpause">⏯</button> | |||||
<div> | |||||
<label for="volume" id="volume-label">🔊</label> | |||||
<input type="range" min="0" max="100" value="100" id="volume" /> | |||||
</div> | |||||
</div> | |||||
<div id="container"> | |||||
</div> | |||||
</main> | |||||
`; | |||||
const playlist = WaveformPlaylist.init({ | |||||
container: document.getElementById('container'), | |||||
timescale: true, | |||||
waveHeight: 100, | |||||
state: 'select', | |||||
}); | |||||
const eventEmitter = playlist.getEventEmitter(); | |||||
// Hook up play/pause and volume inputs | |||||
const playpauseEl = document.getElementById('playpause'); | |||||
const volumeEl = document.getElementById('volume'); | |||||
playpauseEl.addEventListener('click', | |||||
e => eventEmitter.emit(playlist.isPlaying() ? 'pause' : 'play') | |||||
); | |||||
volumeEl.addEventListener('input', | |||||
e => eventEmitter.emit("mastervolumechange", e.target.value) | |||||
); | |||||
// Read target fragment from URL | |||||
let start, end; | |||||
async function setFragmentToSelection() { | |||||
const fragmentIdentifier = window.location.hash; | |||||
if (fragmentIdentifier) { | |||||
const match = fragmentIdentifier.match(/#t=(\d+(?:\.\d+)?)?(?:,(\d+(?:\.\d+)?))?/); | |||||
if (match) { | |||||
if (match[1] !== undefined) { | |||||
start = Number.parseFloat(match[1]); | |||||
} | |||||
if (match[2] !== undefined) { | |||||
end = Number.parseFloat(match[2]); | |||||
} | |||||
} | |||||
} | |||||
// Emit event to update selection in player | |||||
eventEmitter.emit('select', start, end); | |||||
} | |||||
// Bind window hash change to update player | |||||
window.addEventListener('hashchange', async function() { | |||||
if(playlist.isPlaying()) { | |||||
eventEmitter.emit('stop') | |||||
// pause needs a small delay, coz the lib doesn't | |||||
// update player view (drawRequest) when isPlaying() = true. | |||||
await delay(10); | |||||
} | |||||
await setFragmentToSelection(); | |||||
eventEmitter.emit('play'); | |||||
}); | |||||
// Load Playlist | |||||
await playlist.load([{ | |||||
src: document.URL | |||||
}]); | |||||
// update start & end for initial load | |||||
setFragmentToSelection(); | |||||
// Start playing. A tiny delay seems needed in Firefox to show the cursor at the right place. | |||||
requestAnimationFrame(() => eventEmitter.emit('play')); | |||||
} | |||||
init(); |
@@ -1,52 +1 @@ | |||||
import delay from 'delay'; | |||||
async function tryUntilItWorks(func, delayBetweenTries = 1, maxTries = 10) { | |||||
for (let i = 0; i < maxTries; i++) { | |||||
try { | |||||
await func(); | |||||
return; | |||||
} catch (err) { | |||||
await delay(delayBetweenTries); | |||||
continue; | |||||
} | |||||
} | |||||
} | |||||
async function onHeadersReceived({ responseHeaders, url, tabId }) { | |||||
const isAudio = responseHeaders.some(header => | |||||
header.name === 'Content-Type' && header.value.startsWith('audio/') | |||||
); | |||||
if (isAudio) { | |||||
// Avoid any short glitch of sound (observed in Firefox) before our injected script executes. | |||||
await browser.tabs.update(tabId, { muted: true }); | |||||
// Too quickly executing the script may fail (bug in Firefox), so we retry if necessary. | |||||
await tryUntilItWorks(() => browser.tabs.executeScript(tabId, { | |||||
runAt: 'document_end', | |||||
file: '/scripts/contentscript.js', | |||||
})); | |||||
// Unmute again. | |||||
await browser.tabs.update(tabId, { muted: false }); | |||||
await tryUntilItWorks(() => browser.tabs.insertCSS(tabId, { | |||||
runAt: 'document_end', | |||||
file: '/assets/main.css', | |||||
})); | |||||
await tryUntilItWorks(() => browser.tabs.insertCSS(tabId, { | |||||
runAt: 'document_end', | |||||
file: '/assets/waveform-playlist.css', | |||||
})); | |||||
} | |||||
} | |||||
browser.webRequest.onHeadersReceived.addListener( | |||||
onHeadersReceived, | |||||
{ | |||||
urls: ['<all_urls>'], | |||||
types: ['main_frame'], | |||||
}, | |||||
['responseHeaders'], | |||||
); | |||||
import '../audio-player/background.js' |
@@ -1,88 +1 @@ | |||||
import * as WaveformPlaylist from 'waveform-playlist'; | |||||
import delay from 'delay'; | |||||
async function init() { | |||||
document.body.innerHTML = ` | |||||
<main> | |||||
<div id="controls"> | |||||
<button id="playpause">⏯</button> | |||||
<div> | |||||
<label for="volume" id="volume-label">🔊</label> | |||||
<input type="range" min="0" max="100" value="100" id="volume" /> | |||||
</div> | |||||
</div> | |||||
<div id="container"> | |||||
</div> | |||||
</main> | |||||
`; | |||||
const playlist = WaveformPlaylist.init({ | |||||
container: document.getElementById('container'), | |||||
timescale: true, | |||||
waveHeight: 100, | |||||
state: 'select', | |||||
}); | |||||
const eventEmitter = playlist.getEventEmitter(); | |||||
// Hook up play/pause and volume inputs | |||||
const playpauseEl = document.getElementById('playpause'); | |||||
const volumeEl = document.getElementById('volume'); | |||||
playpauseEl.addEventListener('click', | |||||
e => eventEmitter.emit(playlist.isPlaying() ? 'pause' : 'play') | |||||
); | |||||
volumeEl.addEventListener('input', | |||||
e => eventEmitter.emit("mastervolumechange", e.target.value) | |||||
); | |||||
// Read target fragment from URL | |||||
let start, end; | |||||
async function setFragmentToSelection() { | |||||
const fragmentIdentifier = window.location.hash; | |||||
if (fragmentIdentifier) { | |||||
const match = fragmentIdentifier.match(/#t=(\d+(?:\.\d+)?)?(?:,(\d+(?:\.\d+)?))?/); | |||||
if (match) { | |||||
if (match[1] !== undefined) { | |||||
start = Number.parseFloat(match[1]); | |||||
} | |||||
if (match[2] !== undefined) { | |||||
end = Number.parseFloat(match[2]); | |||||
} | |||||
} | |||||
} | |||||
// Emit event to update selection in player | |||||
eventEmitter.emit('select', start, end); | |||||
} | |||||
// Bind window hash change to update player | |||||
window.addEventListener('hashchange', async function() { | |||||
if(playlist.isPlaying()) { | |||||
eventEmitter.emit('stop') | |||||
// pause needs a small delay, coz the lib doesn't | |||||
// update player view (drawRequest) when isPlaying() = true. | |||||
await delay(10); | |||||
} | |||||
await setFragmentToSelection(); | |||||
eventEmitter.emit('play'); | |||||
}); | |||||
// Load Playlist | |||||
await playlist.load([{ | |||||
src: document.URL | |||||
}]); | |||||
// update start & end for initial load | |||||
setFragmentToSelection(); | |||||
// Start playing. A tiny delay seems needed in Firefox to show the cursor at the right place. | |||||
requestAnimationFrame(() => eventEmitter.emit('play')); | |||||
} | |||||
init(); | |||||
import '../audio-player/contentscript.js' |