(function() { var CUSTOM_EMBED_WARNING, CustomEmbedPlayer, DEFAULT_ERROR, DailymotionPlayer, EmbedPlayer, FilePlayer, GoogleDrivePlayer, HLSPlayer, ImgurPlayer, LivestreamPlayer, Player, PlayerJSPlayer, RTMPPlayer, SmashcastPlayer, SoundCloudPlayer, StreamablePlayer, TYPE_MAP, TwitchClipPlayer, TwitchPlayer, UstreamPlayer, VideoJSPlayer, VimeoPlayer, YouTubePlayer, codecToMimeType, genParam, getSourceLabel, hasAnyTextTracks, sortSources, extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }, hasProp = {}.hasOwnProperty; window.Player = Player = (function() { function Player(data) { if (!(this instanceof Player)) { return new Player(data); } this.setMediaProperties(data); this.paused = false; } Player.prototype.load = function(data) { return this.setMediaProperties(data); }; Player.prototype.setMediaProperties = function(data) { this.mediaId = data.id; this.mediaType = data.type; return this.mediaLength = data.seconds; }; Player.prototype.play = function() { return this.paused = false; }; Player.prototype.pause = function() { return this.paused = true; }; Player.prototype.seekTo = function(time) {}; Player.prototype.setVolume = function(volume) {}; Player.prototype.getTime = function(cb) { return cb(0); }; Player.prototype.isPaused = function(cb) { return cb(this.paused); }; Player.prototype.getVolume = function(cb) { return cb(VOLUME); }; Player.prototype.destroy = function() {}; return Player; })(); window.VimeoPlayer = VimeoPlayer = (function(superClass) { extend(VimeoPlayer, superClass); function VimeoPlayer(data) { if (!(this instanceof VimeoPlayer)) { return new VimeoPlayer(data); } this.load(data); } VimeoPlayer.prototype.load = function(data) { this.setMediaProperties(data); return waitUntilDefined(window, 'Vimeo', (function(_this) { return function() { var video; video = $(''); removeOld(video); video.attr({ src: "https://player.vimeo.com/video/" + data.id, webkitallowfullscreen: true, mozallowfullscreen: true, allowfullscreen: true }); if (USEROPTS.wmode_transparent) { video.attr('wmode', 'transparent'); } _this.vimeo = new Vimeo.Player(video[0]); _this.vimeo.on('ended', function() { if (CLIENT.leader) { return socket.emit('playNext'); } }); _this.vimeo.on('pause', function() { _this.paused = true; if (CLIENT.leader) { return sendVideoUpdate(); } }); _this.vimeo.on('play', function() { _this.paused = false; if (CLIENT.leader) { return sendVideoUpdate(); } }); _this.play(); return _this.setVolume(VOLUME); }; })(this)); }; VimeoPlayer.prototype.play = function() { this.paused = false; if (this.vimeo) { return this.vimeo.play()["catch"](function(error) { return console.error('vimeo::play():', error); }); } }; VimeoPlayer.prototype.pause = function() { this.paused = true; if (this.vimeo) { return this.vimeo.pause()["catch"](function(error) { return console.error('vimeo::pause():', error); }); } }; VimeoPlayer.prototype.seekTo = function(time) { if (this.vimeo) { return this.vimeo.setCurrentTime(time)["catch"](function(error) { return console.error('vimeo::setCurrentTime():', error); }); } }; VimeoPlayer.prototype.setVolume = function(volume) { if (this.vimeo) { return this.vimeo.setVolume(volume)["catch"](function(error) { return console.error('vimeo::setVolume():', error); }); } }; VimeoPlayer.prototype.getTime = function(cb) { if (this.vimeo) { return this.vimeo.getCurrentTime().then(function(time) { return cb(parseFloat(time)); })["catch"](function(error) { return console.error('vimeo::getCurrentTime():', error); }); } else { return cb(0); } }; VimeoPlayer.prototype.getVolume = function(cb) { if (this.vimeo) { return this.vimeo.getVolume().then(function(volume) { return cb(parseFloat(volume)); })["catch"](function(error) { return console.error('vimeo::getVolume():', error); }); } else { return cb(VOLUME); } }; return VimeoPlayer; })(Player); window.YouTubePlayer = YouTubePlayer = (function(superClass) { extend(YouTubePlayer, superClass); function YouTubePlayer(data) { if (!(this instanceof YouTubePlayer)) { return new YouTubePlayer(data); } this.setMediaProperties(data); this.pauseSeekRaceCondition = false; waitUntilDefined(window, 'YT', (function(_this) { return function() { return waitUntilDefined(YT, 'Player', function() { var wmode; removeOld(); wmode = USEROPTS.wmode_transparent ? 'transparent' : 'opaque'; return _this.yt = new YT.Player('ytapiplayer', { videoId: data.id, playerVars: { autohide: 1, autoplay: 1, controls: 1, iv_load_policy: 3, rel: 0, wmode: wmode }, events: { onReady: _this.onReady.bind(_this), onStateChange: _this.onStateChange.bind(_this) } }); }); }; })(this)); } YouTubePlayer.prototype.load = function(data) { this.setMediaProperties(data); if (this.yt && this.yt.ready) { return this.yt.loadVideoById(data.id, data.currentTime); } else { return console.error('WTF? YouTubePlayer::load() called but yt is not ready'); } }; YouTubePlayer.prototype.onReady = function() { this.yt.ready = true; return this.setVolume(VOLUME); }; YouTubePlayer.prototype.onStateChange = function(ev) { if (ev.data === YT.PlayerState.PLAYING && this.pauseSeekRaceCondition) { this.pause(); this.pauseSeekRaceCondition = false; } if ((ev.data === YT.PlayerState.PAUSED && !this.paused) || (ev.data === YT.PlayerState.PLAYING && this.paused)) { this.paused = ev.data === YT.PlayerState.PAUSED; if (CLIENT.leader) { sendVideoUpdate(); } } if (ev.data === YT.PlayerState.ENDED && CLIENT.leader) { return socket.emit('playNext'); } }; YouTubePlayer.prototype.play = function() { this.paused = false; if (this.yt && this.yt.ready) { return this.yt.playVideo(); } }; YouTubePlayer.prototype.pause = function() { this.paused = true; if (this.yt && this.yt.ready) { return this.yt.pauseVideo(); } }; YouTubePlayer.prototype.seekTo = function(time) { if (this.yt && this.yt.ready) { return this.yt.seekTo(time, true); } }; YouTubePlayer.prototype.setVolume = function(volume) { if (this.yt && this.yt.ready) { if (volume > 0) { this.yt.unMute(); } return this.yt.setVolume(volume * 100); } }; YouTubePlayer.prototype.setQuality = function(quality) {}; YouTubePlayer.prototype.getTime = function(cb) { if (this.yt && this.yt.ready) { return cb(this.yt.getCurrentTime()); } else { return cb(0); } }; YouTubePlayer.prototype.getVolume = function(cb) { if (this.yt && this.yt.ready) { if (this.yt.isMuted()) { return cb(0); } else { return cb(this.yt.getVolume() / 100); } } else { return cb(VOLUME); } }; return YouTubePlayer; })(Player); window.DailymotionPlayer = DailymotionPlayer = (function(superClass) { extend(DailymotionPlayer, superClass); function DailymotionPlayer(data) { if (!(this instanceof DailymotionPlayer)) { return new DailymotionPlayer(data); } this.setMediaProperties(data); this.initialVolumeSet = false; this.playbackReadyCb = null; waitUntilDefined(window, 'DM', (function(_this) { return function() { var params, quality; removeOld(); params = { autoplay: 1, wmode: USEROPTS.wmode_transparent ? 'transparent' : 'opaque', logo: 0 }; quality = _this.mapQuality(USEROPTS.default_quality); if (quality !== 'auto') { params.quality = quality; } _this.dm = DM.player('ytapiplayer', { video: data.id, width: parseInt(VWIDTH, 10), height: parseInt(VHEIGHT, 10), params: params }); return _this.dm.addEventListener('apiready', function() { _this.dmReady = true; _this.dm.addEventListener('ended', function() { if (CLIENT.leader) { return socket.emit('playNext'); } }); _this.dm.addEventListener('pause', function() { _this.paused = true; if (CLIENT.leader) { return sendVideoUpdate(); } }); _this.dm.addEventListener('playing', function() { _this.paused = false; if (CLIENT.leader) { sendVideoUpdate(); } if (!_this.initialVolumeSet) { _this.setVolume(VOLUME); return _this.initialVolumeSet = true; } }); _this.dm.addEventListener('video_end', function() { return _this.dmReady = false; }); return _this.dm.addEventListener('playback_ready', function() { _this.dmReady = true; if (_this.playbackReadyCb) { _this.playbackReadyCb(); return _this.playbackReadyCb = null; } }); }); }; })(this)); } DailymotionPlayer.prototype.load = function(data) { this.setMediaProperties(data); if (this.dm && this.dmReady) { this.dm.load(data.id); return this.dm.seek(data.currentTime); } else if (this.dm) { console.log('Warning: load() called before DM is ready, queueing callback'); return this.playbackReadyCb = (function(_this) { return function() { _this.dm.load(data.id); return _this.dm.seek(data.currentTime); }; })(this); } else { return console.error('WTF? DailymotionPlayer::load() called but @dm is undefined'); } }; DailymotionPlayer.prototype.pause = function() { if (this.dm && this.dmReady) { this.paused = true; return this.dm.pause(); } }; DailymotionPlayer.prototype.play = function() { if (this.dm && this.dmReady) { this.paused = false; return this.dm.play(); } }; DailymotionPlayer.prototype.seekTo = function(time) { if (this.dm && this.dmReady) { return this.dm.seek(time); } }; DailymotionPlayer.prototype.setVolume = function(volume) { if (this.dm && this.dmReady) { return this.dm.setVolume(volume); } }; DailymotionPlayer.prototype.getTime = function(cb) { if (this.dm && this.dmReady) { return cb(this.dm.currentTime); } else { return cb(0); } }; DailymotionPlayer.prototype.getVolume = function(cb) { var volume; if (this.dm && this.dmReady) { if (this.dm.muted) { return cb(0); } else { volume = this.dm.volume; if (volume > 1) { volume /= 100; } return cb(volume); } } else { return cb(VOLUME); } }; DailymotionPlayer.prototype.mapQuality = function(quality) { switch (String(quality)) { case '240': case '480': case '720': case '1080': return String(quality); case '360': return '380'; case 'best': return '1080'; default: return 'auto'; } }; DailymotionPlayer.prototype.destroy = function() { if (this.dm) { return this.dm.destroy('ytapiplayer'); } }; return DailymotionPlayer; })(Player); sortSources = function(sources) { var flv, flvOrder, idx, j, len, nonflv, pref, qualities, quality, qualityOrder, sourceOrder; if (!sources) { console.error('sortSources() called with null source list'); return []; } qualities = ['2160', '1440', '1080', '720', '540', '480', '360', '240']; pref = String(USEROPTS.default_quality); if (USEROPTS.default_quality === 'best') { pref = '2160'; } idx = qualities.indexOf(pref); if (idx < 0) { idx = 5; } qualityOrder = qualities.slice(idx).concat(qualities.slice(0, idx).reverse()); qualityOrder.unshift('auto'); sourceOrder = []; flvOrder = []; for (j = 0, len = qualityOrder.length; j < len; j++) { quality = qualityOrder[j]; if (quality in sources) { flv = []; nonflv = []; sources[quality].forEach(function(source) { source.quality = quality; if (source.contentType === 'video/flv') { return flv.push(source); } else { return nonflv.push(source); } }); sourceOrder = sourceOrder.concat(nonflv); flvOrder = flvOrder.concat(flv); } } return sourceOrder.concat(flvOrder).map(function(source) { return { type: source.contentType, src: source.link, res: source.quality, label: getSourceLabel(source) }; }); }; getSourceLabel = function(source) { if (source.res === 'auto') { return 'auto'; } else { return source.quality + "p " + (source.contentType.split('/')[1]); } }; waitUntilDefined(window, 'videojs', (function(_this) { return function() { return videojs.options.flash.swf = '/video-js.swf'; }; })(this)); hasAnyTextTracks = function(data) { var ntracks, ref, ref1, ref2; ntracks = (ref = data != null ? (ref1 = data.meta) != null ? (ref2 = ref1.textTracks) != null ? ref2.length : void 0 : void 0 : void 0) != null ? ref : 0; return ntracks > 0; }; window.VideoJSPlayer = VideoJSPlayer = (function(superClass) { extend(VideoJSPlayer, superClass); function VideoJSPlayer(data) { if (!(this instanceof VideoJSPlayer)) { return new VideoJSPlayer(data); } this.load(data); } VideoJSPlayer.prototype.loadPlayer = function(data) { return waitUntilDefined(window, 'videojs', (function(_this) { return function() { var attrs, video; attrs = { width: '100%', height: '100%' }; if (_this.mediaType === 'cm' && hasAnyTextTracks(data)) { attrs.crossorigin = 'anonymous'; } video = $('').addClass('video-js vjs-default-skin embed-responsive-item').attr(attrs); removeOld(video); _this.sources = sortSources(data.meta.direct); if (_this.sources.length === 0) { console.error('VideoJSPlayer::constructor(): data.meta.direct has no sources!'); _this.mediaType = null; return; } _this.sourceIdx = 0; if (data.meta.gdrive_subtitles) { data.meta.gdrive_subtitles.available.forEach(function(subt) { var label; label = subt.lang_original; if (subt.name) { label += " (" + subt.name + ")"; } return $('').attr({ src: "/gdvtt/" + data.id + "/" + subt.lang + "/" + subt.name + ".vtt?vid=" + data.meta.gdrive_subtitles.vid, kind: 'subtitles', srclang: subt.lang, label: label }).appendTo(video); }); } if (data.meta.textTracks) { data.meta.textTracks.forEach(function(track) { var label; label = track.name; attrs = { src: track.url, kind: 'subtitles', type: track.type, label: label }; if ((track["default"] != null) && track["default"]) { attrs["default"] = ''; } return $('').attr(attrs).appendTo(video); }); } _this.player = videojs(video[0], { autoplay: _this.sources[0].type !== 'application/dash+xml', controls: true, plugins: { videoJsResolutionSwitcher: { "default": _this.sources[0].res } } }); return _this.player.ready(function() { _this.player.updateSrc(_this.sources); _this.player.on('error', function() { var err; err = _this.player.error(); if (err && err.code === 4) { console.error('Caught error, trying next source'); _this.sourceIdx++; if (_this.sourceIdx < _this.sources.length) { return _this.player.src(_this.sources[_this.sourceIdx]); } else { console.error('Out of sources, video will not play'); if (_this.mediaType === 'gd') { if (!window.hasDriveUserscript) { return window.promptToInstallDriveUserscript(); } else { return window.tellUserNotToContactMeAboutThingsThatAreNotSupported(); } } } } }); _this.setVolume(VOLUME); _this.player.on('ended', function() { if (CLIENT.leader) { return socket.emit('playNext'); } }); _this.player.on('pause', function() { _this.paused = true; if (CLIENT.leader) { return sendVideoUpdate(); } }); _this.player.on('play', function() { _this.paused = false; if (CLIENT.leader) { return sendVideoUpdate(); } }); _this.player.on('seeked', function() { return $('.vjs-waiting').removeClass('vjs-waiting'); }); return setTimeout(function() { return $('#ytapiplayer .vjs-subtitles-button .vjs-menu-item').each(function(i, elem) { var textNode; textNode = elem.childNodes[0]; if (textNode.textContent === localStorage.lastSubtitle) { elem.click(); } return elem.onclick = function() { if (elem.attributes['aria-checked'].value === 'true') { return localStorage.lastSubtitle = textNode.textContent; } }; }); }, 1); }); }; })(this)); }; VideoJSPlayer.prototype.load = function(data) { this.setMediaProperties(data); this.destroy(); return this.loadPlayer(data); }; VideoJSPlayer.prototype.play = function() { this.paused = false; if (this.player && this.player.readyState() > 0) { return this.player.play(); } }; VideoJSPlayer.prototype.pause = function() { this.paused = true; if (this.player && this.player.readyState() > 0) { return this.player.pause(); } }; VideoJSPlayer.prototype.seekTo = function(time) { if (this.player && this.player.readyState() > 0) { return this.player.currentTime(time); } }; VideoJSPlayer.prototype.setVolume = function(volume) { if (this.player) { return this.player.volume(volume); } }; VideoJSPlayer.prototype.getTime = function(cb) { if (this.player && this.player.readyState() > 0) { return cb(this.player.currentTime()); } else { return cb(0); } }; VideoJSPlayer.prototype.getVolume = function(cb) { if (this.player && this.player.readyState() > 0) { if (this.player.muted()) { return cb(0); } else { return cb(this.player.volume()); } } else { return cb(VOLUME); } }; VideoJSPlayer.prototype.destroy = function() { removeOld(); if (this.player) { return this.player.dispose(); } }; return VideoJSPlayer; })(Player); window.PlayerJSPlayer = PlayerJSPlayer = (function(superClass) { extend(PlayerJSPlayer, superClass); function PlayerJSPlayer(data) { if (!(this instanceof PlayerJSPlayer)) { return new PlayerJSPlayer(data); } this.load(data); } PlayerJSPlayer.prototype.load = function(data) { this.setMediaProperties(data); this.ready = false; this.finishing = false; if (!data.meta.playerjs) { throw new Error('Invalid input: missing meta.playerjs'); } return waitUntilDefined(window, 'playerjs', (function(_this) { return function() { var iframe; iframe = $('').attr({ src: data.meta.playerjs.src }); removeOld(iframe); _this.player = new playerjs.Player(iframe[0]); return _this.player.on('ready', function() { _this.player.on('error', function(error) { return console.error('PlayerJS error', error.stack); }); _this.player.on('ended', function() { if (CLIENT.leader) { return socket.emit('playNext'); } }); _this.player.on('timeupdate', function(time) { if (time.duration - time.seconds < 1 && !_this.finishing) { setTimeout(function() { if (CLIENT.leader) { socket.emit('playNext'); } return _this.pause(); }, (time.duration - time.seconds) * 1000); return _this.finishing = true; } }); _this.player.on('play', function() { this.paused = false; if (CLIENT.leader) { return sendVideoUpdate(); } }); _this.player.on('pause', function() { this.paused = true; if (CLIENT.leader) { return sendVideoUpdate(); } }); _this.player.setVolume(VOLUME * 100); if (!_this.paused) { _this.player.play(); } return _this.ready = true; }); }; })(this)); }; PlayerJSPlayer.prototype.play = function() { this.paused = false; if (this.player && this.ready) { return this.player.play(); } }; PlayerJSPlayer.prototype.pause = function() { this.paused = true; if (this.player && this.ready) { return this.player.pause(); } }; PlayerJSPlayer.prototype.seekTo = function(time) { if (this.player && this.ready) { return this.player.setCurrentTime(time); } }; PlayerJSPlayer.prototype.setVolume = function(volume) { if (this.player && this.ready) { return this.player.setVolume(volume * 100); } }; PlayerJSPlayer.prototype.getTime = function(cb) { if (this.player && this.ready) { return this.player.getCurrentTime(cb); } else { return cb(0); } }; PlayerJSPlayer.prototype.getVolume = function(cb) { if (this.player && this.ready) { return this.player.getVolume(function(volume) { return cb(volume / 100); }); } else { return cb(VOLUME); } }; return PlayerJSPlayer; })(Player); window.StreamablePlayer = StreamablePlayer = (function(superClass) { extend(StreamablePlayer, superClass); function StreamablePlayer(data) { if (!(this instanceof StreamablePlayer)) { return new StreamablePlayer(data); } StreamablePlayer.__super__.constructor.call(this, data); } StreamablePlayer.prototype.load = function(data) { data.meta.playerjs = { src: "https://streamable.com/e/" + data.id }; return StreamablePlayer.__super__.load.call(this, data); }; return StreamablePlayer; })(PlayerJSPlayer); window.GoogleDrivePlayer = GoogleDrivePlayer = (function(superClass) { extend(GoogleDrivePlayer, superClass); function GoogleDrivePlayer(data) { if (!(this instanceof GoogleDrivePlayer)) { return new GoogleDrivePlayer(data); } GoogleDrivePlayer.__super__.constructor.call(this, data); } GoogleDrivePlayer.prototype.load = function(data) { if (!window.hasDriveUserscript) { window.promptToInstallDriveUserscript(); } else if (window.hasDriveUserscript) { window.maybePromptToUpgradeUserscript(); } if (typeof window.getGoogleDriveMetadata === 'function') { return setTimeout((function(_this) { return function() { return backoffRetry(function(cb) { return window.getGoogleDriveMetadata(data.id, cb); }, function(error, metadata) { var alertBox; if (error) { console.error(error); alertBox = window.document.createElement('div'); alertBox.className = 'alert alert-danger'; alertBox.textContent = error; return document.getElementById('ytapiplayer').appendChild(alertBox); } else { data.meta.direct = metadata.videoMap; return GoogleDrivePlayer.__super__.load.call(_this, data); } }, { maxTries: 3, delay: 1000, factor: 1.2, jitter: 500 }); }; })(this), Math.random() * 1000); } }; return GoogleDrivePlayer; })(VideoJSPlayer); window.promptToInstallDriveUserscript = function() { var alertBox, closeButton, infoLink; if (document.getElementById('prompt-install-drive-userscript')) { return; } alertBox = document.createElement('div'); alertBox.id = 'prompt-install-drive-userscript'; alertBox.className = 'alert alert-info'; alertBox.innerHTML = "Due to continual breaking changes making it increasingly difficult to\nmaintain Google Drive support, Google Drive now requires installing\na userscript in order to play the video."; alertBox.appendChild(document.createElement('br')); infoLink = document.createElement('a'); infoLink.className = 'btn btn-info'; infoLink.href = '/google_drive_userscript'; infoLink.textContent = 'Click here for details'; infoLink.target = '_blank'; alertBox.appendChild(infoLink); closeButton = document.createElement('button'); closeButton.className = 'close pull-right'; closeButton.innerHTML = '×'; closeButton.onclick = function() { return alertBox.parentNode.removeChild(alertBox); }; alertBox.insertBefore(closeButton, alertBox.firstChild); return removeOld($('
').append(alertBox)); }; window.tellUserNotToContactMeAboutThingsThatAreNotSupported = function() { var alertBox, closeButton, infoLink; if (document.getElementById('prompt-no-gdrive-support')) { return; } alertBox = document.createElement('div'); alertBox.id = 'prompt-no-gdrive-support'; alertBox.className = 'alert alert-danger'; alertBox.innerHTML = "CyTube has detected an error in Google Drive playback. Please note that the\nstaff in CyTube support channels DO NOT PROVIDE SUPPORT FOR GOOGLE DRIVE. It\nis left in the code as-is for existing users, but we will not assist in\ntroubleshooting any errors that occur.