diff --git a/player/twitch.coffee b/player/twitch.coffee index 120dcbca..34a7d239 100644 --- a/player/twitch.coffee +++ b/player/twitch.coffee @@ -1,29 +1,91 @@ -window.twitchEventCallback = (events) -> - if not (PLAYER instanceof TwitchPlayer) - return false - - events.forEach((event) -> - if event.event == 'playerInit' - PLAYER.twitch.unmute() - PLAYER.twitch.ready = true - ) - -window.TwitchPlayer = class TwitchPlayer extends EmbedPlayer +window.TwitchPlayer = class TwitchPlayer extends Player constructor: (data) -> if not (this instanceof TwitchPlayer) return new TwitchPlayer(data) - @load(data) + @setMediaProperties(data) + waitUntilDefined(window, 'Twitch', => + waitUntilDefined(Twitch, 'Player', => + @init(data) + ) + ) + + init: (data) -> + removeOld() + options = + channel: data.id + @twitch = new Twitch.Player('ytapiplayer', options) + @twitch.addEventListener(Twitch.Player.READY, => + @setVolume(VOLUME) + @twitch.setQuality(@mapQuality(USEROPTS.default_quality)) + @twitch.addEventListener(Twitch.Player.PLAY, => + if CLIENT.leader + sendVideoUpdate() + ) + @twitch.addEventListener(Twitch.Player.PAUSE, => + if CLIENT.leader + sendVideoUpdate() + ) + @twitch.addEventListener(Twitch.Player.ENDED, => + if CLIENT.leader + socket.emit('playNext') + ) + ) load: (data) -> - data.meta.embed = - src: '//www-cdn.jtvnw.net/swflibs/TwitchPlayer.swf' - tag: 'object' - params: - flashvars: "embed=1&\ - hostname=localhost&\ - channel=#{data.id}& - eventsCallback=twitchEventCallback&\ - auto_play=true&\ - start_volume=#{Math.floor(VOLUME * 100)}" - super(data) + @setMediaProperties(data) + try + @twitch.setChannel(data.id) + catch error + console.error(error) + + pause: -> + try + @twitch.pause() + catch error + console.error(error) + + play: -> + try + @twitch.play() + catch error + console.error(error) + + seekTo: (time) -> + try + @twitch.seek(time) + catch error + console.error(error) + + getTime: (cb) -> + try + cb(@twitch.getVolume()) + catch error + console.error(error) + + setVolume: (volume) -> + try + @twitch.setVolume(volume) + if volume > 0 + @twitch.setMuted(false) + catch error + console.error(error) + + getVolume: (cb) -> + try + if @twitch.isPaused() + cb(0) + else + cb(@twitch.getVolume()) + catch error + console.error(error) + + mapQuality: (quality) -> + switch String(quality) + when '1080' then 'chunked' + when '720' then 'high' + when '480' then 'medium' + when '360' then 'low' + when '240' then 'mobile' + when 'best' then 'chunked' + else '' diff --git a/templates/channel.pug b/templates/channel.pug index c1dd7d2b..e56f5b63 100644 --- a/templates/channel.pug +++ b/templates/channel.pug @@ -250,3 +250,4 @@ html(lang="en") script(defer, src="/js/froogaloop.min.js") script(defer, src="/js/video.js") script(defer, src="/js/videojs-contrib-hls.min.js") + script(defer, src="https://player.twitch.tv/js/embed/v1.js") diff --git a/www/js/player.js b/www/js/player.js index 3089fe24..14c9e4da 100644 --- a/www/js/player.js +++ b/www/js/player.js @@ -963,18 +963,6 @@ })(Player); - window.twitchEventCallback = function(events) { - if (!(PLAYER instanceof TwitchPlayer)) { - return false; - } - return events.forEach(function(event) { - if (event.event === 'playerInit') { - PLAYER.twitch.unmute(); - return PLAYER.twitch.ready = true; - } - }); - }; - window.TwitchPlayer = TwitchPlayer = (function(superClass) { extend(TwitchPlayer, superClass); @@ -982,23 +970,146 @@ if (!(this instanceof TwitchPlayer)) { return new TwitchPlayer(data); } - this.load(data); + this.setMediaProperties(data); + waitUntilDefined(window, 'Twitch', (function(_this) { + return function() { + return waitUntilDefined(Twitch, 'Player', function() { + return _this.init(data); + }); + }; + })(this)); } - TwitchPlayer.prototype.load = function(data) { - data.meta.embed = { - src: '//www-cdn.jtvnw.net/swflibs/TwitchPlayer.swf', - tag: 'object', - params: { - flashvars: "embed=1&hostname=localhost&channel=" + data.id + "& eventsCallback=twitchEventCallback&auto_play=true&start_volume=" + (Math.floor(VOLUME * 100)) - } + TwitchPlayer.prototype.init = function(data) { + var options; + removeOld(); + options = { + channel: data.id }; - return TwitchPlayer.__super__.load.call(this, data); + this.twitch = new Twitch.Player('ytapiplayer', options); + return this.twitch.addEventListener(Twitch.Player.READY, (function(_this) { + return function() { + _this.setVolume(VOLUME); + _this.twitch.setQuality(_this.mapQuality(USEROPTS.default_quality)); + _this.twitch.addEventListener(Twitch.Player.PLAY, function() { + if (CLIENT.leader) { + return sendVideoUpdate(); + } + }); + _this.twitch.addEventListener(Twitch.Player.PAUSE, function() { + if (CLIENT.leader) { + return sendVideoUpdate(); + } + }); + return _this.twitch.addEventListener(Twitch.Player.ENDED, function() { + if (CLIENT.leader) { + return socket.emit('playNext'); + } + }); + }; + })(this)); + }; + + TwitchPlayer.prototype.load = function(data) { + var error, error1; + this.setMediaProperties(data); + try { + return this.twitch.setChannel(data.id); + } catch (error1) { + error = error1; + return console.error(error); + } + }; + + TwitchPlayer.prototype.pause = function() { + var error, error1; + try { + return this.twitch.pause(); + } catch (error1) { + error = error1; + return console.error(error); + } + }; + + TwitchPlayer.prototype.play = function() { + var error, error1; + try { + return this.twitch.play(); + } catch (error1) { + error = error1; + return console.error(error); + } + }; + + TwitchPlayer.prototype.seekTo = function(time) { + var error, error1; + try { + return this.twitch.seek(time); + } catch (error1) { + error = error1; + return console.error(error); + } + }; + + TwitchPlayer.prototype.getTime = function(cb) { + var error, error1; + try { + return cb(this.twitch.getVolume()); + } catch (error1) { + error = error1; + return console.error(error); + } + }; + + TwitchPlayer.prototype.setVolume = function(volume) { + var error, error1; + try { + this.twitch.setVolume(volume); + if (volume > 0) { + return this.twitch.setMuted(false); + } + } catch (error1) { + error = error1; + return console.error(error); + } + }; + + TwitchPlayer.prototype.getVolume = function(cb) { + var error, error1; + try { + if (this.twitch.isPaused()) { + return cb(0); + } else { + return cb(this.twitch.getVolume()); + } + } catch (error1) { + error = error1; + return console.error(error); + } + }; + + TwitchPlayer.prototype.mapQuality = function(quality) { + switch (String(quality)) { + case '1080': + return 'chunked'; + case '720': + return 'high'; + case '480': + return 'medium'; + case '360': + return 'low'; + case '240': + return 'mobile'; + case 'best': + return 'chunked'; + default: + return ''; + } }; return TwitchPlayer; - })(EmbedPlayer); + })(Player); window.LivestreamPlayer = LivestreamPlayer = (function(superClass) { extend(LivestreamPlayer, superClass);