bookmark-audio-fragment/app/audio-player/ contentscript.js
93 lines
2.3 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. // Pressing spacebar triggers play/pause.
  36. if (event.code === 'Space') {
  37. playpause();
  38. event.stopPropagation();
  39. event.preventDefault();
  40. }
  41. }, { capture: true });
  42. // Load the file
  43. await playlist.load([{
  44. src: document.URL,
  45. }]);
  46. function syncFragmentToSelection() {
  47. // Read target fragment from URL
  48. let start, end;
  49. const fragmentIdentifier = window.location.hash;
  50. if (fragmentIdentifier) {
  51. try {
  52. const parsed = parseMediaFragmentIdentifier(fragmentIdentifier);
  53. start = parsed.start;
  54. end = parsed.end;
  55. } catch (err) {}
  56. }
  57. // Emit event to update selection in player
  58. eventEmitter.emit('select', start, end);
  59. }
  60. // Bind window hash change to update player
  61. window.addEventListener('hashchange', async () => {
  62. if(playlist.isPlaying()) {
  63. eventEmitter.emit('stop')
  64. // pause needs a small delay, coz the lib doesn't
  65. // update player view (drawRequest) when isPlaying() = true.
  66. await delay(10);
  67. }
  68. await syncFragmentToSelection();
  69. eventEmitter.emit('play');
  70. });
  71. // Read start & end from window location.
  72. syncFragmentToSelection();
  73. // Start playing. A tiny delay seems needed in Firefox to show the cursor at the right place.
  74. requestAnimationFrame(() => eventEmitter.emit('play'));
  75. return playlist;
  76. }