Press n or j to go to the next uncovered block, b, p or k for the previous block.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 | 1x 11x 11x 11x 11x 1x 1x | import { computed } from '@ember/object'; import Sound from './sound'; import { createTimeObject } from 'ember-audio/utils'; /** * A class that represents a "track" of music, similar in concept to a track on * a CD or an MP3 player. Provides methods for tracking the play position of the * underlying {{#crossLink "AudioBuffer"}}{{/crossLink}}, and pausing/resuming. * * @public * @class Track * @extends Sound * @todo move play override to _play so that all super.play methods work */ const Track = Sound.extend({ /** * Computed property. Value is an object containing the current play position * of the audioBuffer in three formats. The three * formats are `raw`, `string`, and `pojo`. * * Play position of 6 minutes would be output as: * * { * raw: 360, // seconds * string: '06:00', * pojo: { * minutes: 6, * seconds: 0 * } * } * * @public * @property position * @type {object} */ position: computed('startOffset', function () { const offset = this.startOffset; const min = Math.floor(offset / 60); const sec = offset - min * 60; return createTimeObject(offset, min, sec); }), /** * Computed property. Value is the current play position of the * audioBuffer, formatted as a percentage. * * @public * @property percentPlayed * @type {number} */ percentPlayed: computed('duration.raw', 'startOffset', function () { const ratio = this.startOffset / this.get('duration.raw'); return ratio * 100; }), /** * Plays the audio source immediately. * * @public * @method play */ play() { this._super(); this.getNodeFrom('audioSource').onended = () => this.stop(); this._trackPlayPosition(); }, /** * Pauses the audio source by stopping without * setting startOffset back to 0. * * @public * @method pause */ pause() { if (this.isPlaying) { const node = this.getNodeFrom('audioSource'); node.onended = function () {}; node.stop(); this.set('isPlaying', false); } }, /** * Stops the audio source and sets * startOffset to 0. * * @public * @method stop */ stop() { this.set('startOffset', 0); if (this.isPlaying) { this.getNodeFrom('audioSource').onended = function () {}; this._super(); } }, /** * Sets up a `requestAnimationFrame` based loop that updates the * startOffset as `audioContext.currentTime` grows. * Loop ends when `isPlaying` is false. * * @method _trackPlayPosition * @private */ _trackPlayPosition() { const ctx = this.audioContext; const startOffset = this.startOffset; const startedPlayingAt = this._startedPlayingAt; const animate = () => { if (this.isPlaying) { this.set( 'startOffset', startOffset + ctx.currentTime - startedPlayingAt ); requestAnimationFrame(animate); } }; requestAnimationFrame(animate); }, }); export default Track; |