Fixes; start refactoring clientside

This commit is contained in:
calzoneman 2013-04-03 15:18:35 -05:00
parent 42a76c4632
commit 5880be6f68
6 changed files with 273 additions and 239 deletions

View File

@ -276,7 +276,6 @@ Channel.prototype.userJoin = function(user) {
// Set the new guy up
this.sendPlaylist(user);
if(user.playerReady)
this.sendMediaUpdate(user);
user.socket.emit("queueLock", {locked: this.qlocked});
this.sendUserlist(user);
@ -473,26 +472,26 @@ Channel.prototype.broadcastMotd = function() {
// The server autolead function
function mediaUpdate(chan, id) {
// Bail cases - video changed, someone's leader, no video playing
if(chan.currentMedia == null ||
id != chan.currentMedia.id ||
if(chan.media == null ||
id != chan.media.id ||
chan.leader != null) {
return;
}
chan.currentMedia.currentTime += (new Date().getTime() - chan.time) / 1000.0;
chan.media.currentTime += (new Date().getTime() - chan.time) / 1000.0;
chan.time = new Date().getTime();
// Show's over, move on to the next thing
if(chan.currentMedia.currentTime > chan.currentMedia.seconds) {
if(chan.media.currentTime > chan.media.seconds) {
chan.playNext();
}
// Send updates about every 5 seconds
else if(chan.i % 5 == 0) {
chan.sendAll("mediaUpdate", chan.currentMedia.packupdate());
chan.sendAll("mediaUpdate", chan.media.packupdate());
}
chan.i++;
setTimeout(function() { channelVideoUpdate(chan, id); }, 1000);
setTimeout(function() { mediaUpdate(chan, id); }, 1000);
}
Channel.prototype.enqueue = function(data) {
@ -534,7 +533,7 @@ Channel.prototype.enqueue = function(data) {
});
break;
case "tw":
var media = new Media(data.id, "Twitch ~ " + data.id, "--:--", "li");
var media = new Media(data.id, "Twitch ~ " + data.id, "--:--", "tw");
this.queue.splice(idx, 0, media);
this.sendAll("queue", {
media: media.pack(),
@ -730,10 +729,10 @@ Channel.prototype.move = function(data) {
});
// Account for moving things around the active video
if(data.src < this.position && data.dest >= this.currentPosition) {
if(data.src < this.position && data.dest >= this.position) {
this.position--;
}
else if(data.src > this.position && data.dest < this.currentPosition) {
else if(data.src > this.position && data.dest < this.position) {
this.position++
}
else if(data.src == this.position) {

View File

@ -208,18 +208,13 @@ function initCallbacks() {
$("#currenttitle").text("Currently Playing: " + data.title);
if(data.type != "sc" && MEDIATYPE == "sc")
fixSoundcloudShit();
if(data.type == "yt")
updateYT(data);
else if(data.type == "tw")
loadTwitch(data.id);
else if(data.type == "li")
loadLivestream(data.id);
else if(data.type == "sc")
updateSC(data);
else if(data.type == "vi")
updateVI(data);
else if(data.type == "dm")
updateDM(data);
if(data.type != MEDIATYPE) {
MEDIATYPE = data.type;
PLAYER = new Media(data);
}
else {
PLAYER.update(data);
}
});
socket.on("userlist", function(data) {
@ -239,6 +234,16 @@ function initCallbacks() {
if(LEADER) {
// I'm a leader! Set up sync function
sendVideoUpdate = function() {
PLAYER.getTime(function(seconds) {
socket.emit("mediaUpdate", {
id: PLAYER.id,
seconds: seconds,
paused: false,
type: PLAYER.type
});
});
/*
if(MEDIATYPE == "yt") {
socket.emit("mediaUpdate", {
id: parseYTURL(PLAYER.getVideoUrl()),
@ -275,6 +280,7 @@ function initCallbacks() {
type: "dm"
});
}
*/
};
}
// I'm not a leader. Don"t send syncs to the server

View File

@ -102,17 +102,6 @@ tag.src = "http://www.youtube.com/iframe_api";
var firstScriptTag = document.getElementsByTagName("script")[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
// Load the Dailymotion iframe API
/*
var tag = document.createElement("script");
tag.src = "http://api.dmcdn.net/all.js";
var firstScriptTag = document.getElementsByTagName("script")[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
*/
if(uname != null && pw != null && pw != "false") {
socket.emit("login", {
name: uname,
@ -391,45 +380,7 @@ function synchtubeLayout() {
}
function onYouTubeIframeAPIReady() {
PLAYER = new YT.Player("ytapiplayer", {
height: VHEIGHT,
width: VWIDTH,
videoId: "",
playerVars: {
"autoplay": 0,
"controls": 1,
},
events: {
"onReady": onPlayerReady,
"onStateChange": onPlayerStateChange
}
});
}
function onPlayerReady() {
socket.emit("playerReady");
}
function onPlayerStateChange(state) {
if(LEADER && state.data == YT.PlayerState.ENDED) {
socket.emit("playNext");
}
else if(LEADER && state.data == YT.PlayerState.PAUSED) {
socket.emit("mediaUpdate", {
id: parseYTURL(PLAYER.getVideoUrl()),
seconds: PLAYER.getCurrentTime(),
type: "yt",
paused: true
});
}
if(LEADER && state.data == YT.PlayerState.PLAYING) {
socket.emit("mediaUpdate", {
id: parseYTURL(PLAYER.getVideoUrl()),
seconds: PLAYER.getCurrentTime(),
type: "yt",
paused: false
});
}
PLAYER = new Media({id: "", type: "yt"});
}
function createCookie(name,value,days) {

View File

@ -317,172 +317,6 @@ function moveVideo(src, dest, noanim) {
POSITION++;
}
// YouTube Synchronization
function updateYT(data) {
if(MEDIATYPE != "yt") {
removeCurrentPlayer();
MEDIATYPE = "yt";
// Note to Soundcloud/Vimeo API designers:
// YouTube"s API is actually nice to use
PLAYER = new YT.Player("ytapiplayer", {
height: VHEIGHT,
width: VWIDTH,
videoId: "",
playerVars: {
"autoplay": 0,
"controls": 1,
},
events: {
"onReady": onPlayerReady,
"onStateChange": onPlayerStateChange
}
});
}
// Load new video
if(PLAYER.getVideoUrl && data.id != parseYTURL(PLAYER.getVideoUrl())) {
PLAYER.loadVideoById(data.id, data.currentTime, $("#quality").val());
if(data.paused)
PLAYER.pauseVideo();
}
// Sync playback time
else if(PLAYER.seekTo) {
if(Math.abs(PLAYER.getCurrentTime() - data.currentTime) > SYNC_THRESHOLD)
PLAYER.seekTo(data.currentTime, true);
if(!data.paused)
PLAYER.playVideo();
}
}
// Soundcloud synchronization
function updateSC(data) {
if(MEDIATYPE != "sc") {
unfixSoundcloudShit();
var currentEmbed = $("#ytapiplayer");
var iframe = $("<iframe/>").insertBefore(currentEmbed);
currentEmbed.remove();
iframe.attr("id","ytapiplayer");
iframe.attr("src", "https://w.soundcloud.com/player/?url=");
iframe.css("width", "100%").attr("height", "166")
.attr("frameborder", "no");
PLAYER = SC.Widget("ytapiplayer");
MEDIATYPE = "sc";
}
// Server is on a different soundcloud track than client
if(PLAYER.mediaId != data.id) {
PLAYER.load(data.id, {
auto_play: true
});
// Keep track of current ID
PLAYER.mediaId = data.id;
}
// Soundcloud"s API is async
// Query the playback position and compare that with the sync packet
PLAYER.getPosition(function(pos) {
if(Math.abs(pos / 1000 - data.currentTime) > SYNC_THRESHOLD) {
PLAYER.seekTo(data.currentTime * 1000);
}
});
}
// Dailymotion synchronization
function updateDM(data) {
if(MEDIATYPE != "dm") {
removeCurrentPlayer();
PLAYER = DM.player("ytapiplayer", {
video: data.id,
width: parseInt(VWIDTH),
height: parseInt(VHEIGHT),
params: {autoplay: 1}
});
PLAYER.mediaId = data.id;
MEDIATYPE = "dm";
}
else if(PLAYER.mediaId != data.id) {
PLAYER.api("load", data.id);
PLAYER.mediaId = data.id;
}
else {
if(Math.abs(data.currentTime - PLAYER.currentTime) > SYNC_THRESHOLD) {
PLAYER.api("seek", data.currentTime);
}
else if(PLAYER.currentTime > data.seconds || PLAYER.currentTime+"" == "NaN") {
PLAYER.api("load", data.id);
}
}
}
// Vimeo synchronization
// URGH building a synchronizing tool is so frustrating when
// these APIs are designed to be async
function updateVI(data) {
if(MEDIATYPE != "vi") {
initVI(data);
}
// Either vimeo"s API doesn"t support loading a new video
// or their terrible documentation doesn"t document it
else if(data.id != PLAYER.videoid) {
initVI(data);
}
PLAYER.api("getCurrentTime", function(time) {
if(Math.abs(time - data.currentTime) > SYNC_THRESHOLD) {
PLAYER.api("seekTo", data.currentTime);
}
});
}
// Loads up a Vimeo player
function initVI(data) {
var currentEmbed = $("#ytapiplayer");
var div = currentEmbed.parent();
currentEmbed.remove();
// Ugly but it"s the only way I managed to get the API calls to work
div[0].innerHTML += "<iframe id=\"ytapiplayer\" src=\"http://player.vimeo.com/video/" + data.id + "?api=1&player_id=ytapiplayer\" width=\"" + VWIDTH + "\" height=\"" + VHEIGHT + "\" frameborder=\"0\" webkitAllowFullScreen mozallowfullscreen allowFullScreen></iframe>";
// $f() is defined by froogaloop, Vimeo"s API wrapper
PLAYER = $f($("iframe")[0]);
// So we can retrieve the ID synchronously instead of waiting for
// getVideoId with a callback
PLAYER.videoid = data.id;
PLAYER.addEvent("ready", function() {
// Autoplay
PLAYER.api("play");
});
MEDIATYPE = "vi";
}
function loadTwitch(channel) {
MEDIATYPE = "tw";
removeCurrentPlayer();
var url = "http://www.twitch.tv/widgets/live_embed_player.swf?channel="+channel;
var params = {
allowFullScreen:"true",
allowScriptAccess:"always",
allowNetworking:"all",
movie:"http://www.twitch.tv/widgets/live_embed_player.swf",
id: "live_embed_player_flash",
flashvars:"hostname=www.twitch.tv&channel="+channel+"&auto_play=true&start_volume=100"
};
swfobject.embedSWF( url, "ytapiplayer", VWIDTH, VHEIGHT, "8", null, null, params, {} );
}
function loadLivestream(channel) {
MEDIATYPE = "li";
removeCurrentPlayer();
flashvars = { channel: channel };
params = { AllowScriptAccess: "always" };
swfobject.embedSWF("http://cdn.livestream.com/chromelessPlayer/v20/playerapi.swf", "ytapiplayer", VWIDTH, VHEIGHT, "9.0.0", "expressInstall.swf", flashvars, params);
}
function removeCurrentPlayer(){
var currentEmbed = $("#ytapiplayer");
var placeholder = $("<div/>").insertBefore(currentEmbed);
currentEmbed.remove();
placeholder.attr("id","ytapiplayer");
}
function parseVideoURL(url){
url = url.trim()
if(typeof(url) != "string")

243
www/assets/js/media.js Normal file
View File

@ -0,0 +1,243 @@
var Media = function(data) {
this.id = data.id;
this.type = data.type;
switch(this.type) {
case "yt":
this.initYouTube();
break;
case "vi":
this.initVimeo();
break;
case "dm":
this.initDailymotion();
break;
case "sc":
this.initSoundcloud();
break;
case "li":
this.initLivestream();
break;
case "tw":
this.initTwitch();
break;
default:
break;
}
}
Media.prototype.initYouTube = function() {
this.removeOld();
this.player = new YT.Player("ytapiplayer", {
height: VHEIGHT,
width: VWIDTH,
videoId: this.id,
playerVars: {
"autoplay": 1,
"controls": 1,
},
events: {
onPlayerReady: function() {
socket.emit("playerReady");
}
}
});
this.load = function(data) {
this.player.loadVideoById(data.id, data.currentTime);
this.id = data.id;
}
this.pause = function() {
this.player.pauseVideo();
}
this.play = function() {
this.player.playVideo();
}
this.getTime = function(callback) {
callback(this.player.getCurrentTime());
}
this.seek = function(time) {
this.player.seekTo(time, true);
}
}
Media.prototype.initVimeo = function() {
var iframe = $("<iframe/>").insertBefore($("#ytapiplayer"));
$("#ytapiplayer").remove();
iframe.attr("id", "ytapiplayer");
iframe.attr("width", VWIDTH);
iframe.attr("height", VHEIGHT);
iframe.attr("src", "http://player.vimeo.com/video/"+this.id+"?api=1&player_id=ytapiplayer");
iframe.attr("webkitAllowFullScreen", "");
iframe.attr("mozallowfullscreen", "");
iframe.attr("allowFullScreen", "");
iframe.css("border", "none");
this.player = $f(iframe[0]);
$f(iframe[0]).addEvent("ready", function() {
this.player = $f(iframe[0]);
this.play();
}.bind(this));
this.load = function(data) {
this.id = data.id;
this.initVimeo();
}
this.pause = function() {
this.player.api("pause");
}
this.play = function() {
this.player.api("play");
}
this.getTime = function(callback) {
this.player.api("getCurrentTime", callback);
}
this.seek = function(time) {
this.player.api("seekTo", time);
}
}
Media.prototype.initDailymotion = function() {
this.removeOld();
this.player = DM.player("ytapiplayer", {
video: this.id,
width: parseInt(VWIDTH),
height: parseInt(VHEIGHT),
params: {autoplay: 1}
});
this.load = function(data) {
this.id = data.id;
this.player.api("load", data.id);
}
this.pause = function() {
this.player.api("pause");
}
this.play = function() {
this.player.api("play");
}
this.getTime = function(callback) {
callback(this.player.currentTime);
}
this.seek = function(seconds) {
this.player.api("seek", seconds);
}
}
Media.prototype.initSoundcloud = function() {
unfixSoundcloudShit();
var iframe = $("<iframe/>").insertBefore($("#ytapiplayer"));
$("#ytapiplayer").remove();
iframe.attr("id", "ytapiplayer");
iframe.attr("src", "https://w.soundcloud.com/player/?url=" + this.id);
iframe.css("width", "100%").attr("height", "166");
iframe.css("border", "none");
this.player = SC.Widget("ytapiplayer");
setTimeout(function() { this.play(); }.bind(this), 1000);
this.load = function(data) {
this.id = data.id;
this.player.load(data.id, {auto_play: true});
}
this.pause = function() {
this.player.pause();
}
this.play = function() {
this.player.play();
}
this.getTime = function(callback) {
this.player.getPosition(function(pos) {
callback(pos / 1000);
});
}
this.seek = function(seconds) {
this.player.seekTo(seconds * 1000);
}
}
Media.prototype.initLivestream = function() {
this.removeOld();
var flashvars = {channel: this.id};
var params = {AllowScriptAccess: "always"};
swfobject.embedSWF("http://cdn.livestream.com/chromelessPlayer/v20/playerapi.swf", "ytapiplayer", VWIDTH, VHEIGHT, "9.0.0", "expressInstall.swf", flashvars, params);
this.load = function(data) {
this.id = data.id;
this.initLivestream();
}
this.pause = function() { }
this.play = function() { }
this.getTime = function() { }
this.seek = function() { }
}
Media.prototype.initTwitch = function() {
this.removeOld();
var url = "http://www.twitch.tv/widgets/live_embed_player.swf?channel="+this.id;
var params = {
allowFullScreen:"true",
allowScriptAccess:"always",
allowNetworking:"all",
movie:"http://www.twitch.tv/widgets/live_embed_player.swf",
id: "live_embed_player_flash",
flashvars:"hostname=www.twitch.tv&channel="+this.id+"&auto_play=true&start_volume=100"
};
swfobject.embedSWF( url, "ytapiplayer", VWIDTH, VHEIGHT, "8", null, null, params, {} );
this.load = function(data) {
this.id = data.id;
this.initTwitch();
}
this.pause = function() { }
this.play = function() { }
this.getTime = function() { }
this.seek = function() { }
}
Media.prototype.update = function(data) {
if(data.id != this.id) {
this.load(data);
}
if(data.paused) {
this.pause();
}
this.getTime(function(seconds) {
if(Math.abs(data.currentTime - seconds) > SYNC_THRESHOLD) {
this.seek(data.currentTime);
}
}.bind(this));
}
Media.prototype.removeOld = function() {
var old = $("#ytapiplayer");
var placeholder = $("<div/>").insertBefore(old);
old.remove();
placeholder.attr("id", "ytapiplayer");
}

View File

@ -208,6 +208,7 @@
<script src="./assets/js/functions.js"></script>
<script src="./assets/js/callbacks.js"></script>
<script src="./assets/js/iourl.js"></script>
<script src="./assets/js/media.js"></script>
<script src="./assets/js/client.js"></script>
<script src="./assets/js/swf.js"></script>