1

I'm creating a system where JavaScript is listening, on a websocket, for a single click or a double click from an IoT button. When the JavaScript receives the single click, it's supposed to start playing the first song in an array of shuffled audio elements. Then, once the first audio element has finished playing, it's supposed to play the next song in the array. This will go on until it is interrupted by a double click, which denotes a pause. When it gets to the end of the final song, it's to reshuffle and start from the beginning. However, I'm having trouble getting the "on end of song" function to work. Right now, it plays the first song and then stops. If I send another single click it just plays the first one from the beginning.

Javascript:

<!DOCTYPE html>
<head>
  <title>Pusher Test</title>
  <script src="https://js.pusher.com/4.1/pusher.min.js"></script>
  <script>
    function shuffle (input) {

           for (var i = input.length-1; i >=0; i--) {

               var randomIndex = Math.floor(Math.random()*(i+1));
               var itemAtIndex = input[randomIndex];

               input[randomIndex] = input[i];
               input[i] = itemAtIndex;
           }
           return input;
       }

    function startShuffle(songs){
      current = 0;
      for (var i = 0; i < songs.length - 1; i++) {
        songs[i].onended = function () {
        songs[i+1].play();
                current = i + 1;
        }
      }
      songs[songs.length - 1].onended = function () {
        songs = shuffle(songs);
        startShuffle(songs);
      }

    }


    Pusher.logToConsole = true;
        var current = 0;
    var songs = [];
    for (i = 0; i <= 100; i++) {
      songs[i] = new Audio('/Users/eliavhamburger/Desktop/Ser Dree/Music/' + i + '.mp3');
    }


       songs = shuffle(songs);
       startShuffle(songs);
    var pusher = new Pusher('APIKeyHidden', {
      cluster: 'us2',
      encrypted: true
    });

    var channel = pusher.subscribe('my-channel');
    channel.bind('my-event', function(data) {
      document.getElementById("demo").innerHTML = JSON.stringify(data);
      if (JSON.stringify(data) == '"SINGLE"') {
          songs[current].play();
      }
      if (JSON.stringify(data) == '"DOUBLE"') {
        songs[current].pause();
      }

    });
  </script>
</head>
<body>
  <h1>Pusher Test</h1>
  <p>
    Try publishing an event to channel <code>my-channel</code>
    with event name <code>my-event</code>.
  </p>
  <p ID="demo"></p>
  <p ID="nums"></p>
</body>
Eliav Hamburger
  • 85
  • 2
  • 12
  • i'd be surprised if that new Audio(...file path) code is working Javascript doesn't get access to the file system. – Shanon Jackson Sep 04 '18 at 04:00
  • It's stored locally in the same folder – Eliav Hamburger Sep 04 '18 at 04:01
  • And you don't have an error logged in your dev-tools console? From here I see at least a *Cannot read property 'play' of undefined* or alike. (tip: when the first *songs* onended will fire, the loop where you defined it would be ended since a long time, and `i` will now be `songs.length - 1`. But then `songs[i+1]` will actually be `songs[songs.length]` which is obviously `undefined`. But there might be some other issues in the whole code that I didn't fully read carefully. – Kaiido Sep 04 '18 at 05:54

1 Answers1

0

Wild guess: onended is not implemented. Try rewriting the startShuffle method by replacing the 2 occurrences of

songs[/* some index */].onended = function () { /* do something */ };

with

songs[/* some index */].addEventListener('ended', function () { /* do something */ });

This seems to be the official way (scroll to the end for an example).

Stock Overflaw
  • 3,203
  • 1
  • 13
  • 14
  • no, no. onended is in the prototype of `HTMLMediaElement`. – Kaiido Sep 04 '18 at 05:48
  • Yes, Firefox's console suggests it when typing, but 1/ the link I gave uses another way and 2/ setting a _property_ to implicitly ask for a _behavior_, it's so MSIE... so, well, I believe this possibility should be explored. – Stock Overflaw Sep 04 '18 at 12:37