Browse Source

Move current code into app/audio-player

tags/v0.1.0
Gerben 4 years ago
parent
commit
ad6bf930c9
4 changed files with 142 additions and 140 deletions
  1. +52
    -0
      app/audio-player/background.js
  2. +88
    -0
      app/audio-player/contentscript.js
  3. +1
    -52
      app/scripts/background.js
  4. +1
    -88
      app/scripts/contentscript.js

+ 52
- 0
app/audio-player/background.js View File

@@ -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'],
);

+ 88
- 0
app/audio-player/contentscript.js View File

@@ -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
app/scripts/background.js View File

@@ -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
app/scripts/contentscript.js View File

@@ -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'

Loading…
Cancel
Save