47

AudioPlaylist

An instance of AudioPlaylist manages a list of audio tracks which are played by an instance of AudioPlayer.

Objective
  • Responder
    • View
      • AudioPlaylist
00:00:00

Click on the name of a track in the list to load it in the player.

Press the play button to start playing the audio. Press the pause button to pause it. Move the slider or click in the progression bar to jump forward or backward in the audio. Turn on or off playing the audio in a loop. NOTE: The player moves automatically to the next track if playing in a loop is turned off.

In the console of the browser, load a track in the player:

audioplaylist.currentTrack=4

Add a time in milliseconds to wait between tracks:

audioplaylist.gap=2000

Turn off playing in a loop:

audioplayer.loop=false

Start the player:

audioplayer.play()
  1. function AudioPlaylist(player, tracks) {
  2.     View.call(this);
  3.  
  4.     player.addListener(this);
  5.  
  6.     this._player = player;
  7.  
  8.     this._tracks = tracks;
  9.  
  10.     this._currentTrack = 1;
  11.  
  12.     this._gap = 0;
  13.  
  14.     this._timer = null;
  15. }
  16.  
  17. AudioPlaylist.prototype = Object.create(View.prototype);
  18.  
  19. Object.defineProperty(AudioPlaylist.prototype, 'constructor', { value: AudioPlaylist, enumerable: false, writable: true });

The AudioPlaylist class inherits from the View class. player is an instance of AudioPlayer. tracks is an array which lists the audio tracks managed by the instance. Each track in the list is an object with a field title, a character string, the title of the track, and a field url, a character string, a URL which points to the audio file.

  1. Object.defineProperty(AudioPlaylist.prototype, 'currentTrack', {
  2.     get:    function() {
  3.         return this._currentTrack;
  4.     },
  5.     set:    function(n) {
  6.         if (!Number.isInteger(n))
  7.             throw new TypeError();
  8.  
  9.         if (n < 1 || n > this._tracks.length)
  10.             n = this._tracks.length;
  11.  
  12.         if (this._tracks[this._currentTrack-1].widget)
  13.             this._tracks[this._currentTrack-1].widget.classList.remove('selected');
  14.  
  15.         this._currentTrack = n;
  16.  
  17.         if (this._tracks[this._currentTrack-1].widget)
  18.             this._tracks[this._currentTrack-1].widget.classList.add('selected');
  19.  
  20.         this._player.src = this._tracks[n-1].url;
  21.     }
  22. });

currentTrack is an accessor which returns or changes the track loaded in the audio player managed by this. currentTrack returns or accepts in argument a track number. A track number starts at 1. If the track number in argument is smaller than 1 or larger than the number of tracks managed by this, currentTrack loads the last track.

  1. Object.defineProperty(AudioPlaylist.prototype, 'gap', {
  2.     get:    function() {
  3.         return this._gap;
  4.     },
  5.     set:    function(ms) {
  6.         if (!Number.isInteger(ms))
  7.             throw new TypeError();
  8.  
  9.         if (ms < 0)
  10.             throw new RangeError();
  11.  
  12.         this._gap = ms;
  13.     }
  14. });
  1. AudioPlaylist.prototype.audioEnded = function(sender) {
  2.     if (this._currentTrack == this._tracks.length)
  3.         this.currentTrack = 1;
  4.     else {
  5.         this.nextTrack();
  6.  
  7.         if (this._gap > 0)
  8.             this._timer = setTimeout(() => { this._timer = null; this._player.play(); }, this._gap);
  9.         else
  10.             this._player.play();
  11.     }
  12. };
  1. AudioPlaylist.prototype.audioPlayed = function(sender) {
  2.     if (this._timer) {
  3.         clearTimeout(this._timer);
  4.         this._timer = null;
  5.     }
  6. };
  1. AudioPlaylist.prototype.nextTrack = function() {
  2.     return this.currentTrack = this._currentTrack == this._tracks.length ? 1 : this._currentTrack + 1;
  3. };
  1. AudioPlaylist.prototype.previousTrack = function() {
  2.     return this.currentTrack = this._currentTrack == 1 ? this._tracks.length : this._currentTrack - 1;
  3. };
  1. AudioPlaylist.prototype.setWidget = function(w) {
  2.     if (! (w.tagName == 'OL' || w.tagName == 'UL'))
  3.         throw new TypeError();
  4.  
  5.     w.querySelectorAll('li > span').forEach((e, i) => {
  6.         this._tracks[i].widget = e;
  7.         e.onclick = () => this.currentTrack = i + 1;
  8.     });
  9.  
  10.     View.prototype.setWidget.call(this, w);
  11.  
  12.     return this;
  13. };
  1. AudioPlaylist.prototype.createWidget = function() {
  2.     const playlist = [];
  3.  
  4.     for (let trackdata of this._tracks)
  5.         playlist.push(`<li><span>${trackdata.title}</span></li>`);
  6.  
  7.     const html = '<ol class="ojs_playlist">' + '\n' + playlist.join('\n') + '\n' + '</ol>';
  8.  
  9.     let template = document.createElement('template');
  10.  
  11.     template.innerHTML = html;
  12.  
  13.     let widget = template.content.children[0];
  14.  
  15.     this.setWidget(widget);
  16.  
  17.     return this;
  18. };
  1. AudioPlaylist.prototype.destroyWidget = function() {
  2.     View.prototype.destroyWidget.call(this);
  3.  
  4.     for (let trackdata of this._tracks)
  5.         delete trackdata.widget;
  6.  
  7.     return this;
  8. };
Test

The audio tracks by djduppy are available on Freesound.

  1. <?php $debug=true; ?>

Setting $debug to true gives access in the console of the navigator to the variables audioplayer, the instance of the AudioPlayer, and audioplaylist, the instance of the AudioPlaylist. If $debug is false, all the code in JavaScript is protected by a closure function.

  1. <?php $ojs_audiolistdir='/files/sounds/djduppy'; ?>
  2. <?php $ojs_audiolist=array('bigbeat', 'electro', 'garage', 'hardtrance', 'hipfunk', 'ragga'); ?>

Defines the list of audio tracks read by the player, i. e. their file names and the folder on the server which contains them. Depending on the type of audio file the browser can read, the code adds the extension .ogg or .mp3 to the name of a track.

  1. <?php $id=uniqid('id'); ?>

Defines the identifier of the <div> which surrounds the HTML of the audio player.

  1. .ojs_playlist {
  2.     columns: 2;
  3. }
  4. .ojs_playlist li span:hover, .ojs_playlist li span.selected {
  5.     color: #3bc;

Displays the list of audio tracks in 2 columns. Changes the color of the selected title.

  1. <div id="<?php echo $id; ?>" class="noprint">
  2. <div class="ojs_audio">
  3. <span class="audiocontrols">
  4. <span class="audioplay"><i class="fas fa-3x fa-play-circle"></i></span>
  5. <span class="audiopause"><i class="fas fa-3x fa-pause-circle"></i></span>
  6. <input class="audiobar" type="range" min="0" max="100" step="1" value="0"/>
  7. <span class="audiotime">00:00:00</span>
  8. <span class="audioloop"><i class="fas fa-sm fa-sync-alt"></i></span>
  9. </span>
  10. </div>
  11. </div>

Creates the widgets of the interface.

  1. <?php head('javascript', '/objectivejs/Objective.js'); ?>
  2. <?php head('javascript', '/objectivejs/Responder.js'); ?>
  3. <?php head('javascript', '/objectivejs/View.js'); ?>
  4. <?php head('javascript', '/objectivejs/AudioPlayer.js'); ?>
  5. <?php head('javascript', '/objectivejs/AudioPlaylist.js'); ?>

Includes the code of all the necessary classes. REMINDER: The function head of the iZend library adds a tag such as <script src="/objectivejs/Objective.js"></script> to the <head> section of the document in HTML. Adapt the code to your development environment.

  1. <?php if (!$debug): ?>
  2. (function() {
  3. <?php endif; ?>

Isolates all the code in JavaScript in a closure function if $debug is false.

  1.     const audioplayer = new AudioPlayer();
  2.  
  3.     const container = document.querySelector('#<?php echo $id; ?>');
  4.  
  5.     audioplayer.setManagedWidget(container.querySelector('.ojs_audio'));
  6.  
  7.     audioplayer.loop = true;
  8.  
  9.     const dirname = '<?php echo $ojs_audiolistdir; ?>';
  10.  
  11.     const filelist = [<?php echo implode(',', array_map(function($s) { return "'$s'"; }, $ojs_audiolist)); ?>];
  12.  
  13.     const filetype = audioplayer.canPlayType('audio/ogg') ? '.ogg' : '.mp3';
  14.  
  15.     const audiotracks = [];
  16.  
  17.     for (let filename of filelist)
  18.         audiotracks.push({title: filename, url: `${dirname}/${filename}${filetype}`});
  19.  
  20.     const audioplaylist = new AudioPlaylist(audioplayer, audiotracks);
  21.  
  22.     audioplaylist.createManagedWidget(container);
  23.  
  24.     audioplaylist.currentTrack = 1;
  1. <?php if (!$debug): ?>
  2. })();
  3. <?php endif; ?>

Closes the function which isolates the code in JavaScript if $debug is false.

SEE ALSO

View, AudioPlayer, Write data on a server

Comments

Your comment:
[p] [b] [i] [u] [s] [quote] [pre] [br] [code] [url] [email] strip help 2000

Enter a maximum of 2000 characters.
Improve the presentation of your text with the following formatting tags:
[p]paragraph[/p], [b]bold[/b], [i]italics[/i], [u]underline[/u], [s]strike[/s], [quote]citation[/quote], [pre]as is[/pre], [br]line break,
[url]http://www.izend.org[/url], [url=http://www.izend.org]site[/url], [email]izend@izend.org[/email], [email=izend@izend.org]izend[/email],
[code]command[/code], [code=language]source code in c, java, php, html, javascript, xml, css, sql, bash, dos, make, etc.[/code].