playem.js
function createEventHandlers (playemFunctions) {
      var eventHandlers = {
        onApiReady: function (player) {
          // console.log(player.label + " api ready");
          if (whenReady && player == whenReady.player) { whenReady.fct() }
          if (--playersToLoad == 0) { that.emit('onReady') }
        },
        onEmbedReady: function (player) {
          // console.log("embed ready");
          setVolume(volume)
        },
        onBuffering: function (player) {
          setTimeout(function () {
            setPlayTimeout()
            that.emit('onBuffering')
          })
        },
        onPlaying: function (player) {
          // console.log(player.label + ".onPlaying");
          // setPlayTimeout(); // removed because soundcloud sends a "onPlaying" event, even for not authorized tracks
          setVolume(volume)
          setTimeout(function () {
            that.emit('onPlay')
          }, 1)
          if (player.trackInfo && player.trackInfo.duration) {
            eventHandlers.onTrackInfo({
              position: player.trackInfo.position || 0,
              duration: player.trackInfo.duration
            })
          }

          if (progress) { clearInterval(progress) }

          if (player.getTrackPosition) {
            // var that = eventHandlers; //this;
            progress = setInterval(function () {
              player.getTrackPosition(function (trackPos) {
                eventHandlers.onTrackInfo({
                  position: trackPos,
                  duration: player.trackInfo.duration || currentTrack.trackDuration
                })
              })
            }, 1000)
          }
        },
        onTrackInfo: function (trackInfo) {
          // console.log("ontrackinfo", trackInfo, currentTrack);
          if (currentTrack && trackInfo) {
            if (trackInfo.duration) {
              currentTrack.trackDuration = trackInfo.duration
              setPlayTimeout()
            }
            if (trackInfo.position) { currentTrack.trackPosition = trackInfo.position }
          }
          that.emit('onTrackInfo', currentTrack)
        },
        onPaused: function (player) {
          // console.log(player.label + ".onPaused");
          setPlayTimeout()
          if (progress) { clearInterval(progress) }
          progress = null
          // if (!avoidPauseEventPropagation)
          //  that.emit("onPause");
          // avoidPauseEventPropagation = false;
        },
        onEnded: function (player) {
          // console.log(player.label + ".onEnded");
          stopTrack()
          that.emit('onEnd')
          playemFunctions.next()
        },
        onError: function (player, error) {
          console.error(player.label + ' error:', ((error || {}).exception || error || {}).stack || error)
          setPlayTimeout()
          that.emit('onError', error)
        }
      };
      // handlers will only be triggered is their associated player is currently active
      ['onEmbedReady', 'onBuffering', 'onPlaying', 'onPaused', 'onEnded', 'onError'].map(function (evt) {
        var fct = eventHandlers[evt]
        eventHandlers[evt] = function (player, x) {
          if (currentTrack && player == currentTrack.player) { return fct(player, x) }
          /*
          else if (evt != "onEmbedReady")
            console.warn("ignore event:", evt, "from", player, "instead of:", currentTrack.player);
          */
        }
      })
      return eventHandlers
    }
function createEventHandlers (playemFunctions) {
      var eventHandlers = {
        onApiReady: function (player) {
          // console.log(player.label + " api ready");
          if (whenReady && player == whenReady.player) { whenReady.fct() }
          if (--playersToLoad == 0) { that.emit('onReady') }
        },
        onEmbedReady: function (player) {
          // console.log("embed ready");
          setVolume(volume)
        },
        onBuffering: function (player) {
          setTimeout(function () {
            setPlayTimeout()
            that.emit('onBuffering')
          })
        },
        onPlaying: function (player) {
          // console.log(player.label + ".onPlaying");
          // setPlayTimeout(); // removed because soundcloud sends a "onPlaying" event, even for not authorized tracks
          setVolume(volume)
          setTimeout(function () {
            that.emit('onPlay')
          }, 1)
          if (player.trackInfo && player.trackInfo.duration) {
            eventHandlers.onTrackInfo({
              position: player.trackInfo.position || 0,
              duration: player.trackInfo.duration
            })
          }

          if (progress) { clearInterval(progress) }

          if (player.getTrackPosition) {
            // var that = eventHandlers; //this;
            progress = setInterval(function () {
              player.getTrackPosition(function (trackPos) {
                eventHandlers.onTrackInfo({
                  position: trackPos,
                  duration: player.trackInfo.duration || currentTrack.trackDuration
                })
              })
            }, 1000)
          }
        },
        onTrackInfo: function (trackInfo) {
          // console.log("ontrackinfo", trackInfo, currentTrack);
          if (currentTrack && trackInfo) {
            if (trackInfo.duration) {
              currentTrack.trackDuration = trackInfo.duration
              setPlayTimeout()
            }
            if (trackInfo.position) { currentTrack.trackPosition = trackInfo.position }
          }
          that.emit('onTrackInfo', currentTrack)
        },
        onPaused: function (player) {
          // console.log(player.label + ".onPaused");
          setPlayTimeout()
          if (progress) { clearInterval(progress) }
          progress = null
          // if (!avoidPauseEventPropagation)
          //  that.emit("onPause");
          // avoidPauseEventPropagation = false;
        },
        onEnded: function (player) {
          // console.log(player.label + ".onEnded");
          stopTrack()
          that.emit('onEnd')
          playemFunctions.next()
        },
        onError: function (player, error) {
          console.error(player.label + ' error:', ((error || {}).exception || error || {}).stack || error)
          setPlayTimeout()
          that.emit('onError', error)
        }
      };
      // handlers will only be triggered is their associated player is currently active
      ['onEmbedReady', 'onBuffering', 'onPlaying', 'onPaused', 'onEnded', 'onError'].map(function (evt) {
        var fct = eventHandlers[evt]
        eventHandlers[evt] = function (player, x) {
          if (currentTrack && player == currentTrack.player) { return fct(player, x) }
          /*
          else if (evt != "onEmbedReady")
            console.warn("ignore event:", evt, "from", player, "instead of:", currentTrack.player);
          */
        }
      })
      return eventHandlers
    }
function createEventHandlers ( playemFunctions ) { var eventHandlers = { onApiReady : function ( player ) { // console.log(player.label + " api ready"); if ( whenReady && player == whenReady . player ) { whenReady . fct ( ) } if ( -- playersToLoad == 0 ) { that . emit ( 'onReady' ) } } , onEmbedReady : function ( player ) { // console.log("embed ready"); setVolume ( volume ) } , onBuffering : function ( player ) { setTimeout ( function ( ) { setPlayTimeout ( ) that . emit ( 'onBuffering' ) } ) } , onPlaying : function ( player ) { // console.log(player.label + ".onPlaying"); // setPlayTimeout(); // removed because soundcloud sends a "onPlaying" event, even for not authorized tracks setVolume ( volume ) setTimeout ( function ( ) { that . emit ( 'onPlay' ) } , 1 ) if ( player . trackInfo && player . trackInfo . duration ) { eventHandlers . onTrackInfo ( { position : player . trackInfo . position || 0 , duration : player . trackInfo . duration } ) } if ( progress ) { clearInterval ( progress ) } if ( player . getTrackPosition ) { // var that = eventHandlers; //this; progress = setInterval ( function ( ) { player . getTrackPosition ( function ( trackPos ) { eventHandlers . onTrackInfo ( { position : trackPos , duration : player . trackInfo . duration || currentTrack . trackDuration } ) } ) } , 1000 ) } } , onTrackInfo : function ( trackInfo ) { // console.log("ontrackinfo", trackInfo, currentTrack); if ( currentTrack && trackInfo ) { if ( trackInfo . duration ) { currentTrack . trackDuration = trackInfo . duration setPlayTimeout ( ) } if ( trackInfo . position ) { currentTrack . trackPosition = trackInfo . position } } that . emit ( 'onTrackInfo' , currentTrack ) } , onPaused : function ( player ) { // console.log(player.label + ".onPaused"); setPlayTimeout ( ) if ( progress ) { clearInterval ( progress ) } progress = null // if (!avoidPauseEventPropagation) //  that.emit("onPause"); // avoidPauseEventPropagation = false; } , onEnded : function ( player ) { // console.log(player.label + ".onEnded"); stopTrack ( ) that . emit ( 'onEnd' ) playemFunctions . next ( ) } , onError : function ( player , error ) { console . error ( player . label + ' error:' , ( ( error || { } ) . exception || error || { } ) . stack || error ) setPlayTimeout ( ) that . emit ( 'onError' , error ) } } ; // handlers will only be triggered is their associated player is currently active [ 'onEmbedReady' , 'onBuffering' , 'onPlaying' , 'onPaused' , 'onEnded' , 'onError' ] . map ( function ( evt ) { var fct = eventHandlers [ evt ] eventHandlers [ evt ] = function ( player , x ) { if ( currentTrack && player == currentTrack . player ) { return fct ( player , x ) } /*
          else if (evt != "onEmbedReady")
            console.warn("ignore event:", evt, "from", player, "instead of:", currentTrack.player);
          */ } } ) return eventHandlers }
functions that are called by players => to propagate to client
functions that are called by players = > to propagate to client