var VIMEO_FLASH = false; function removeOld(replace) { $("#sc_volume").remove(); replace = replace || $("
").addClass("embed-responsive-item"); var old = $("#ytapiplayer"); replace.insertBefore(old); old.remove(); replace.attr("id", "ytapiplayer"); } var YouTubePlayer = function (data) { var self = this; waitUntilDefined(window, "YT", function () { waitUntilDefined(YT, "Player", function () { removeOld(); self.paused = false; self.videoId = data.id; self.videoLength = data.seconds; self.theYouTubeDevsNeedToFixThisShit = false; var wmode = USEROPTS.wmode_transparent ? "transparent" : "opaque"; self.player = new YT.Player("ytapiplayer", { videoId: data.id, playerVars: { autohide: 1, // Autohide controls autoplay: 1, // Autoplay video controls: 1, // Show controls iv_load_policy: 3, // No annotations rel: 0, // No related videos wmode: wmode }, events: { onReady: function () { PLAYER.setVolume(VOLUME); }, onStateChange: function (ev) { /** * Race conditions suck. * Race conditions in other peoples' code that you can't fix * but are forced to work around suck more. */ if (ev.data === YT.PlayerState.PLAYING && self.theYouTubeDevsNeedToFixThisShit) { PLAYER.seek(0.000001); PLAYER.pause(); self.theYouTubeDevsNeedToFixThisShit = false; } if(PLAYER.paused && ev.data != YT.PlayerState.PAUSED || !PLAYER.paused && ev.data == YT.PlayerState.PAUSED) { self.paused = (ev.data == YT.PlayerState.PAUSED); if(CLIENT.leader) sendVideoUpdate(); } else { self.paused = (ev.data == YT.PlayerState.PAUSED); } if(CLIENT.leader && ev.data == YT.PlayerState.ENDED) { socket.emit("playNext"); } } } }); $("#ytapiplayer").css("border", "none"); }); }); self.load = function (data) { if(self.player && self.player.loadVideoById) { self.player.loadVideoById(data.id, data.currentTime); if (USEROPTS.default_quality) { self.player.setPlaybackQuality(USEROPTS.default_quality); // What's that? Another stupid hack for the HTML5 player? self.player.setPlaybackQuality(USEROPTS.default_quality); } self.videoId = data.id; self.videoLength = data.seconds; } }; self.pause = function () { if(self.player && self.player.pauseVideo) self.player.pauseVideo(); }; self.play = function () { if(self.player && self.player.playVideo) self.player.playVideo(); }; self.getTime = function (callback) { if(self.player && self.player.getCurrentTime) callback(self.player.getCurrentTime()); }; self.seek = function (time) { if(self.player && self.player.seekTo) self.player.seekTo(time, true); }; self.getVolume = function (cb) { if (!self.player || !self.player.getVolume || !self.player.isMuted) { return; } // YouTube's API is strange in the sense that getVolume() returns // the regular (unmuted) volume even if it is muted... // YouTube's volume is 0..100, normalize it to 0..1 var vol = self.player.isMuted() ? 0 : (self.player.getVolume() / 100); cb(vol); }; self.setVolume = function (vol) { if (self.player && self.player.setVolume) { if (vol > 0) { self.player.unMute(); } self.player.setVolume(vol * 100); } }; }; var VimeoPlayer = function (data) { var self = this; waitUntilDefined(window, "$f", function () { self.videoId = data.id; self.videoLength = data.seconds; self.init = function () { var iframe = $(""); removeOld(iframe); var prto = location.protocol; iframe.attr("src", prto+"//player.vimeo.com/video/"+self.videoId+"?api=1&player_id=ytapiplayer"); iframe.attr("webkitAllowFullScreen", ""); iframe.attr("mozallowfullscreen", ""); iframe.attr("allowFullScreen", ""); if(USEROPTS.wmode_transparent) iframe.attr("wmode", "transparent"); iframe.css("border", "none"); $f(iframe[0]).addEvent("ready", function () { self.player = $f(iframe[0]); self.player.api("play"); self.player.addEvent("finish", function () { if(CLIENT.leader) { socket.emit("playNext"); } }); self.player.addEvent("pause", function () { self.paused = true; if(CLIENT.leader) sendVideoUpdate(); }); self.player.addEvent("play", function () { self.paused = false; if(CLIENT.leader) sendVideoUpdate(); }); self.setVolume(VOLUME); }.bind(self)); }; self.load = function (data) { self.videoId = data.id; self.videoLength = data.seconds; self.init(); }; self.pause = function () { if(self.player && self.player.api) self.player.api("pause"); }; self.play = function () { if(self.player && self.player.api) self.player.api("play"); }; self.getTime = function (callback) { if(self.player && self.player.api) { // Vimeo api returns time as a string because fuck logic self.player.api("getCurrentTime", function (time) { callback(parseFloat(time)); }); } }; self.seek = function(time) { if(self.player && self.player.api) self.player.api("seekTo", time); }; self.getVolume = function (cb) { if (self.player && self.player.api) { self.player.api("getVolume", cb); } }; self.setVolume = function (vol) { self.player.api("setVolume", vol); }; self.init(); }); }; var VimeoFlashPlayer = function (data) { var self = this; self.videoId = data.id; self.videoLength = data.seconds; self.init = function () { removeOld(); var prto = location.protocol; var url = prto+"//vimeo.com/moogaloop.swf?clip_id="+self.videoId; url += "&" + [ "server=vimeo.com", "api=2", "show_title=0", "show_byline=0", "show_portrait=0", "fullscreen=1", "loop=0" ].join("&"); var flashvars = { api: 2, player_id: "ytapiplayer" }; var params = { allowfullscreen: true, allowScriptAccess: "always", wmode: USEROPTS.wmode_transparent ? "transparent" : undefined }; swfobject.embedSWF(url, "ytapiplayer", VWIDTH, VHEIGHT, "9.0.0", "expressInstall.swf", flashvars, params); self.player = $("#ytapiplayer")[0]; waitUntilDefined(self.player, "api_addEventListener", function () { self.player.api_addEventListener("ready", function () { self.player.api_play(); self.player.api_addEvent("finish", function () { if(CLIENT.leader) socket.emit("playNext"); }); self.player.api_addEvent("pause", function () { PLAYER.paused = true; if(CLIENT.leader) sendVideoUpdate(); }); self.player.api_addEvent("play", function () { PLAYER.paused = false; if(CLIENT.leader) sendVideoUpdate(); }); self.setVolume(VOLUME); }); }); }; self.load = function (data) { self.videoId = data.id; self.videoLength = data.seconds; self.init(); }; self.pause = function () { if(self.player && self.player.api_pause) self.player.api_pause(); }; self.play = function () { if(self.player && self.player.api_play) self.player.api_play(); }; self.getTime = function (callback) { if(self.player && self.player.api_getCurrentTime) { var t = parseFloat(self.player.api_getCurrentTime()); callback(t); } }; self.seek = function (time) { if(self.player.api_seekTo); self.player.api_seekTo(time); }; self.getVolume = function (cb) { if (self.player && self.player.api_getVolume) { cb(self.player.api_getVolume()); } }; self.setVolume = function (vol) { self.player.api_setVolume(vol); }; self.init(); }; var DailymotionPlayer = function (data) { var self = this; waitUntilDefined(window, "DM", function () { removeOld(); self.videoId = data.id; self.videoLength = data.seconds; var q = undefined; if (USEROPTS.default_quality) { /* Map youtube-style quality names to dailymotion values */ q = { small: 240, medium: 380, large: 480, hd720: 720, hd1080: 1080, highres: 1080 }[USEROPTS.default_quality]; } var params = { autoplay: 1, wmode: USEROPTS.wmode_transparent ? "transparent" : "opaque", quality: q, logo: 0 }; self.player = DM.player("ytapiplayer", { video: data.id, width: parseInt(VWIDTH, 10), height: parseInt(VHEIGHT, 10), params: params }); self.player.addEventListener("apiready", function (e) { self.player.addEventListener("ended", function (e) { if(CLIENT.leader) { socket.emit("playNext"); } }); self.player.addEventListener("pause", function (e) { PLAYER.paused = true; if(CLIENT.leader) sendVideoUpdate(); }); self.player.addEventListener("playing", function (e) { PLAYER.paused = false; if(CLIENT.leader) sendVideoUpdate(); if (!self.volumeIsSet) { try { self.setVolume(VOLUME); self.volumeIsSet = true; } catch (err) { } } }); }); }); self.load = function (data) { self.videoId = data.id; self.videoLength = data.seconds; if (self.player && self.player.api) { self.player.api("load", data.id); } }; self.pause = function () { if(self.player && self.player.api) self.player.api("pause"); }; self.play = function () { if(self.player && self.player.api) self.player.api("play"); }; self.getTime = function (callback) { if(self.player) callback(self.player.currentTime); }; self.seek = function (seconds) { if(self.player && self.player.api) self.player.api("seek", seconds); }; self.getVolume = function (cb) { if (self.player) { var volume = self.player.muted ? 0 : self.player.volume; /* * If the volume was changed by the UI slider, it will be in the range * [0, 100], otherwise if it was only set by the API, it will be in [0, 1]. */ if (volume > 1) volume /= 100.0; cb(volume); } }; self.setVolume = function (vol) { if (self.player && self.player.api) { self.player.api("volume", vol); } }; }; var SoundcloudPlayer = function (data) { var self = this; // The getVolume function on their widget throws TypeErrors // Go figure self.soundcloudIsSeriouslyFuckingBroken = VOLUME; self.videoId = data.id; self.videoLength = data.seconds; waitUntilDefined(window, "SC", function () { unfixSoundcloudShit(); var iframe = $(""); removeOld(); iframe.appendTo($("#ytapiplayer")); iframe.attr("id", "scplayer"); iframe.attr("src", "https://w.soundcloud.com/player/?url="+self.videoId); iframe.css("height", "166px"); iframe.css("border", "none"); var volslider = $("").attr("id", "sc_volume") .css("top", "170px") .insertAfter(iframe); volslider.slider({ range: "min", value: VOLUME * 100, stop: function (event, ui) { self.player.setVolume(ui.value / 100); self.soundcloudIsSeriouslyFuckingBroken = ui.value / 100; } }); self.player = SC.Widget("scplayer"); self.player.bind(SC.Widget.Events.READY, function () { self.player.load(self.videoId, { auto_play: true }); self.player.bind(SC.Widget.Events.PAUSE, function () { PLAYER.paused = true; if(CLIENT.leader) sendVideoUpdate(); }); self.player.bind(SC.Widget.Events.FINISH, function () { if(CLIENT.leader) { socket.emit("playNext"); } }); self.player.bind(SC.Widget.Events.PLAY, function () { PLAYER.paused = false; if(CLIENT.leader) sendVideoUpdate(); }); // THAT'S RIGHT, YOU CAN'T SET THE VOLUME BEFORE IT STARTS PLAYING var soundcloudNeedsToFuckingFixTheirPlayer = function () { self.setVolume(VOLUME); self.player.unbind(SC.Widget.Events.PLAY_PROGRESS); }; self.player.bind(SC.Widget.Events.PLAY_PROGRESS, soundcloudNeedsToFuckingFixTheirPlayer); }.bind(self)); }); self.load = function (data) { self.videoId = data.id; self.videoLength = data.seconds; if(self.player && self.player.load) { self.player.load(data.id, { auto_play: true }); var soundcloudNeedsToFuckingFixTheirPlayer = function () { self.setVolume(VOLUME); self.player.unbind(SC.Widget.Events.PLAY_PROGRESS); }; self.player.bind(SC.Widget.Events.PLAY_PROGRESS, soundcloudNeedsToFuckingFixTheirPlayer); } }; self.pause = function () { if(self.player && self.player.pause) self.player.pause(); }; self.play = function () { if(self.player && self.player.play) self.player.play(); }; self.getTime = function (callback) { if(self.player && self.player.getPosition) { self.player.getPosition(function (pos) { callback(pos / 1000); }); } }; self.seek = function (seconds) { if(self.player && self.player.seekTo) self.player.seekTo(seconds * 1000); }; self.getVolume = function (cb) { cb(self.soundcloudIsSeriouslyFuckingBroken); }; self.setVolume = function (vol) { self.player.setVolume(vol); }; }; var LivestreamPlayer = function (data) { removeOld(); var self = this; self.videoId = data.id; self.videoLength = data.seconds; self.init = function () { var flashvars = { channel: self.videoId }; var params = { AllowScriptAccess: "always" }; var prto = location.protocol; swfobject.embedSWF( prto+"//cdn.livestream.com/chromelessPlayer/v20/playerapi.swf", "ytapiplayer", VWIDTH, VHEIGHT, "9.0.0", "expressInstall.swf", flashvars, params ); }; self.load = function(data) { self.videoId = data.id; self.videoLength = data.seconds; self.init(); }; self.pause = function () { }; self.play = function () { }; self.getTime = function () { }; self.seek = function () { }; self.getVolume = function () { }; self.setVolume = function () { }; waitUntilDefined(window, "swfobject", function () { self.init(); }); }; var TwitchTVPlayer = function (data) { removeOld(); var self = this; self.videoId = data.id; self.videoLength = data.seconds; self.init = function () { var url = "https://www-cdn.jtvnw.net/swflibs/TwitchPlayer.swf?channel="+self.videoId; var params = { allowFullScreen: "true", allowScriptAccess: "always", allowNetworking: "all", movie: "https://www-cdn.jtvnw.net/swflibs/TwitchPlayer.swf", id: "live_embed_player_flash", flashvars: "hostname=www.twitch.tv&channel="+self.videoId+"&auto_play=true&start_volume=" + VOLUME }; swfobject.embedSWF(url, "ytapiplayer", VWIDTH, VHEIGHT, "8", null, null, params, {} ); }; self.load = function (data) { self.videoId = data.id; self.videoLength = data.seconds; self.init(); }; self.pause = function () { }; self.play = function () { }; self.getTime = function () { }; self.seek = function () { }; self.getVolume = function () { }; self.setVolume = function () { }; waitUntilDefined(window, "swfobject", function () { self.init(); }); }; function rtmpEventHandler(id, ev, data) { if (ev === "volumechange") { PLAYER.volume = (data.muted ? 0 : data.volume); } } var RTMPPlayer = function (data) { removeOld(); var self =this; self.volume = VOLUME; self.videoId = data.id; self.videoLength = data.seconds; self.init = function () { var prto = location.protocol; var url = prto+"//fpdownload.adobe.com/strobe/FlashMediaPlayback_101.swf"; var src = encodeURIComponent(self.videoId); var params = { allowFullScreen: "true", allowScriptAccess: "always", allowNetworking: "all", wMode: "direct", movie: prto+"//fpdownload.adobe.com/strobe/FlashMediaPlayback_101.swf", flashvars: "src="+src+"&streamType=live&javascriptCallbackFunction=rtmpEventHandler&autoPlay=true&volume=" + VOLUME }; swfobject.embedSWF(url, "ytapiplayer", VWIDTH, VHEIGHT, "8", null, null, params, {} ); }; self.load = function (data) { self.videoId = data.id; self.videoLength = data.seconds; self.init(); }; self.pause = function () { }; self.play = function () { }; self.getTime = function () { }; self.seek = function () { }; self.getVolume = function (cb) { cb(self.volume); }; self.setVolume = function () { }; waitUntilDefined(window, "swfobject", function () { self.init(); }); }; var JWPlayer = function (data) { var self = this; self.videoId = data.id; if (data.url) { self.videoURL = data.url; } else { self.videoURL = data.id; } self.videoLength = data.seconds; self.init = function () { removeOld(); jwplayer("ytapiplayer").setup({ file: self.videoURL, width: "100%", height: "100%", autostart: true, type: data.contentType }); jwplayer().onReady(function() { $("#ytapiplayer").addClass("embed-responsive-item"); if ($("#ytapiplayer")[0].tagName === "OBJECT") { $("#ytapiplayer").parent().css("position", "absolute"); } handleVideoResize(); }); jwplayer().onPlay(function() { /* Somehow JWPlayer manages to have THE SAME PROBLEM AS SOUNDCLOUD. * It seems to be impossible to set the volume before the video has * started playing. How this is so damn difficult to get right I will * never understand. */ self.setVolume(VOLUME); self.paused = false; if(CLIENT.leader) sendVideoUpdate(); }); jwplayer().onPause(function() { self.paused = true; if(CLIENT.leader) sendVideoUpdate(); }); jwplayer().onComplete(function() { socket.emit("playNext"); }); }; self.load = function (data) { self.videoId = data.id; if (data.url) { self.videoURL = data.url; } else { self.videoURL = data.id; } self.videoLength = data.seconds; self.init(); }; self.pause = function () { if(jwplayer) jwplayer().pause(true); }; self.play = function () { if(jwplayer) jwplayer().play(true); }; self.getTime = function (callback) { // Only return time for non-live media if(jwplayer && jwplayer().getDuration() != -1) { callback(jwplayer().getPosition()); } }; self.seek = function (time) { if(jwplayer) jwplayer().seek(time); }; self.getVolume = function (cb) { cb(jwplayer().getVolume() / 100); }; self.setVolume = function (vol) { jwplayer().setVolume(vol * 100); }; waitUntilDefined(window, "jwplayer", function () { self.init(); }); }; var UstreamPlayer = function (data) { var self = this; self.videoId = data.id; self.videoLength = data.seconds; self.init = function () { var iframe = $(""); removeOld(iframe); iframe.attr("width", VWIDTH); iframe.attr("height", VHEIGHT); iframe.attr("src", "//www.ustream.tv/embed/"+self.videoId+"?v=3&wmode=direct"); iframe.attr("frameborder", "0"); iframe.attr("scrolling", "no"); iframe.css("border", "none"); }; self.load = function (data) { self.videoId = data.id; self.videoLength = data.seconds; self.init(); }; self.pause = function () { }; self.play = function () { }; self.getTime = function () { }; self.seek = function () { }; self.getVolume = function () { }; self.setVolume = function () { }; self.init(); }; var ImgurPlayer = function (data) { var self = this; self.init = function () { var iframe = $(""); removeOld(iframe); iframe.attr("width", VWIDTH); iframe.attr("height", VHEIGHT); var prto = location.protocol; iframe.attr("src", prto+"//imgur.com/a/"+self.videoId+"/embed"); iframe.attr("frameborder", "0"); iframe.attr("scrolling", "no"); iframe.css("border", "none"); }; self.load = function (data) { self.videoId = data.id; self.videoLength = data.seconds; self.init(); }; self.pause = function () { }; self.play = function () { }; self.getTime = function () { }; self.seek = function () { }; self.getVolume = function () { }; self.setVolume = function () { }; self.init(); }; var CustomPlayer = function (data) { var self = this; self.videoId = data.id; self.videoLength = data.seconds; self.init = function () { removeOld(); var div = $("#ytapiplayer"); div.attr("id", ""); /* * 2014-12-10 * * If a user is connected via HTTPS and the custom link is * HTTP, then the embed fails due to mixed active content * policy. Display a message indicating this. */ if (location.protocol.match(/^https/) && self.videoId.match(/http:/)) { div.html("You are currently connected via HTTPS but " + "the custom embed link uses non-secure HTTP. " + "Your browser may therefore block it from loading. " + "To fix this, either add the custom embed as a secure " + "URL (https://...) if the source supports it, or " + "visit this page over plain HTTP (your websocket will still " + "use secure HTTPS for communication, just the page " + "will load over plain HTTP)."); // Try to salvage the link self.videoId = self.videoId.replace(/http:/g, "https:"); } div.append(self.videoId); self.player = div.find("iframe"); if(self.player.length === 0) self.player = div.find("object"); if(self.player.length === 0) self.player = div; self.player.attr("id", "ytapiplayer"); self.player.attr("width", VWIDTH); self.player.attr("height", VHEIGHT); }; self.load = function (data) { self.videoId = data.id; self.videoLength = data.seconds; self.init(); }; self.pause = function () { }; self.play = function () { }; self.getTime = function () { }; self.seek = function () { }; self.getVolume = function () { }; self.setVolume = function () { }; self.init(); }; function FilePlayer(data) { var self = this; self.init = function (data) { if (!data.url) { return; } self.videoId = data.id; self.videoURL = data.url; var isAudio = data.meta.codec && data.meta.codec.match(/^mp3$|^vorbis$/); var video; if (isAudio) { video = $(""); } else { video = $("") } video .addClass("embed-responsive-item") .attr("src", self.videoURL) .attr("controls", "controls") .attr("id", "#ytapiplayer") .attr("width", VWIDTH) .attr("height", VHEIGHT) .attr("autoplay", true) .html("Your browser does not support HTML5<video>
tags :(");
video.error(function (err) {
setTimeout(function () {
console.log("