bookmark-audio-fragment/app/audio-player/ contentscript.js
91 lines
2.2 KiB

  1. import * as WaveformPlaylist from 'waveform-playlist';
  2. import delay from 'delay';
  3. import html from 'nanohtml'
  4. import { parseMediaFragmentIdentifier } from '../util/media-fragment-identifier.js';
  5. export default async function init() {
  6. document.body.innerHTML = '';
  7. const mainEl = html`
  8. <main>
  9. <div id="controls">
  10. <button id="playpause" onclick=${playpause}>⏯</button>
  11. <div>
  12. <label for="volume" id="volume-label">🔊</label>
  13. <input type="range" min="0" max="100" value="100" id="volume" oninput=${updateVolume}/>
  14. </div>
  15. </div>
  16. <div id="container">
  17. </div>
  18. </main>
  19. `;
  20. document.body.appendChild(mainEl);
  21. const playlist = WaveformPlaylist.init({
  22. container: document.getElementById('container'),
  23. timescale: true,
  24. waveHeight: 100,
  25. state: 'select',
  26. });
  27. const eventEmitter = playlist.getEventEmitter();
  28. function playpause() {
  29. eventEmitter.emit(playlist.isPlaying() ? 'pause' : 'play');
  30. }
  31. function updateVolume(event) {
  32. eventEmitter.emit('mastervolumechange', event.target.value);
  33. }
  34. document.body.addEventListener('keydown', event => {
  35. if (event.target !== document.body) return;
  36. if (event.code === 'Space') {
  37. playpause();
  38. }
  39. });
  40. // Load the file
  41. await playlist.load([{
  42. src: document.URL,
  43. }]);
  44. function syncFragmentToSelection() {
  45. // Read target fragment from URL
  46. let start, end;
  47. const fragmentIdentifier = window.location.hash;
  48. if (fragmentIdentifier) {
  49. try {
  50. const parsed = parseMediaFragmentIdentifier(fragmentIdentifier);
  51. start = parsed.start;
  52. end = parsed.end;
  53. } catch (err) {}
  54. }
  55. // Emit event to update selection in player
  56. eventEmitter.emit('select', start, end);
  57. }
  58. // Bind window hash change to update player
  59. window.addEventListener('hashchange', async () => {
  60. if(playlist.isPlaying()) {
  61. eventEmitter.emit('stop')
  62. // pause needs a small delay, coz the lib doesn't
  63. // update player view (drawRequest) when isPlaying() = true.
  64. await delay(10);
  65. }
  66. await syncFragmentToSelection();
  67. eventEmitter.emit('play');
  68. });
  69. // Read start & end from window location.
  70. syncFragmentToSelection();
  71. // Start playing. A tiny delay seems needed in Firefox to show the cursor at the right place.
  72. requestAnimationFrame(() => eventEmitter.emit('play'));
  73. return playlist;
  74. }