Correct behavior for leader/unleader; compensate for Soundcloud being inconsiderate

This commit is contained in:
calzoneman 2013-03-25 13:54:18 -05:00
parent 5bed38d0ec
commit e70002ae4f
5 changed files with 391 additions and 33 deletions

View File

@ -796,6 +796,9 @@ Channel.prototype.broadcastNewUser = function(user) {
// Someone"s rank changed, or their leadership status changed
Channel.prototype.broadcastRankUpdate = function(user) {
user.socket.emit("rank", {
rank: user.rank
});
this.sendAll("updateUser", {
name: user.name,
rank: user.rank,

View File

@ -36,29 +36,8 @@ function initCallbacks() {
});
socket.on("rank", function(data) {
if(data.rank >= Rank.Moderator) {
$("#playlist_controls").css("display", "block");
$("#playlist_controls button").each(function() {
$(this).attr("disabled", false);
});
$("#qlockbtn").css("display", "block");
var poll = $("#pollcontainer .active");
if(poll.length > 0) {
$("<button/>").addClass("btn btn-danger pull-right").text("Close Poll")
.insertAfter(poll.find(".close"))
.click(function() {
socket.emit("closePoll")
});
}
var users = $("#userlist").children();
for(var i = 0; i < users.length; i++) {
addUserDropdown(users[i], users[i].children[1].innerHTML);
}
$("#modnav").show();
$("#chancontrols").show();
}
RANK = data.rank;
handleRankChange();
});
socket.on("login", function(data) {
@ -132,7 +111,7 @@ function initCallbacks() {
}
for(var i = 0; i < data.pl.length; i++) {
var li = makeQueueEntry(data.pl[i]);
if(RANK >= Rank.Moderator || OPENQUEUE)
if(RANK >= Rank.Moderator || OPENQUEUE || LEADER)
addQueueButtons(li);
$(li).appendTo(ul);
}
@ -140,7 +119,7 @@ function initCallbacks() {
socket.on("queue", function(data) {
var li = makeQueueEntry(data.media);
if(RANK >= Rank.Moderator || OPENQUEUE)
if(RANK >= Rank.Moderator || OPENQUEUE || LEADER)
addQueueButtons(li);
$(li).css("display", "none");
var idx = data.pos;
@ -203,6 +182,8 @@ function initCallbacks() {
socket.on("mediaUpdate", function(data) {
$("#currenttitle").text("Currently Playing: " + data.title);
if(data.type != "sc" && MEDIATYPE == "sc")
fixSoundcloudShit();
if(data.type == "yt")
updateYT(data);
else if(data.type == "tw")
@ -230,8 +211,9 @@ function initCallbacks() {
socket.on("updateUser", function(data) {
if(data.name == uname) {
LEADER = data.leader;
handleRankChange();
if(LEADER) {
// I"m a leader! Set up sync function
// I'm a leader! Set up sync function
sendVideoUpdate = function() {
if(MEDIATYPE == "yt") {
socket.emit("mediaUpdate", {
@ -271,14 +253,11 @@ function initCallbacks() {
}
};
}
// I"m not a leader. Don"t send syncs to the server
// I'm not a leader. Don"t send syncs to the server
else {
sendVideoUpdate = function() { }
}
RANK = data.rank;
if(data.rank >= Rank.Moderator)
$("#playlist_controls").css("display", "block");
}
var users = $("#userlist").children();
for(var i = 0; i < users.length; i++) {
@ -308,7 +287,7 @@ function initCallbacks() {
var ul = $("#library")[0];
for(var i = 0; i < data.results.length; i++) {
var li = makeQueueEntry(data.results[i]);
if(RANK >= Rank.Moderator || OPENQUEUE)
if(RANK >= Rank.Moderator || OPENQUEUE || LEADER)
addLibraryButtons(li, data.results[i].id);
$(li).appendTo(ul);
}

View File

@ -319,6 +319,7 @@ function updateYT(data) {
// Soundcloud synchronization
function updateSC(data) {
if(MEDIATYPE != "sc") {
unfixSoundcloudShit();
var currentEmbed = $("#ytapiplayer");
var iframe = $("<iframe/>").insertBefore(currentEmbed);
currentEmbed.remove();
@ -350,7 +351,6 @@ function updateSC(data) {
// Dailymotion synchronization
function updateDM(data) {
if(MEDIATYPE != "dm") {
console.log("updateDM: MEDIATYPE=", MEDIATYPE);
removeCurrentPlayer();
PLAYER = DM.player("ytapiplayer", {
video: data.id,
@ -370,6 +370,9 @@ function updateDM(data) {
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);
}
}
}
@ -582,7 +585,7 @@ function showChannelRegistration() {
$("<button/>").addClass("close pull-right").text("×")
.appendTo(div)
.click(function() { div.remove(); });
$("<h3/>").text("This channel isn"t registered").appendTo(div);
$("<h3/>").text("This channel isn't registered").appendTo(div);
$("<button/>").addClass("btn btn-primary").text("Register it")
.appendTo(div)
.click(function() {
@ -622,3 +625,46 @@ function updateBanlist(entries) {
remove.click(callback);
}
}
function handleRankChange() {
rebuildPlaylist();
if(RANK >= Rank.Moderator || LEADER) {
$("#playlist_controls").css("display", "block");
$("#playlist_controls button").each(function() {
$(this).attr("disabled", false);
});
}
if(RANK >= Rank.Moderator) {
$("#qlockbtn").css("display", "block");
var poll = $("#pollcontainer .active");
if(poll.length > 0) {
$("<button/>").addClass("btn btn-danger pull-right").text("Close Poll")
.insertAfter(poll.find(".close"))
.click(function() {
socket.emit("closePoll")
});
}
var users = $("#userlist").children();
for(var i = 0; i < users.length; i++) {
addUserDropdown(users[i], users[i].children[1].innerHTML);
}
$("#modnav").show();
$("#chancontrols").show();
}
else {
if(OPENQUEUE) {
if(CHANNELOPTS.qopen_allow_qnext || LEADER)
$("#queue_next").attr("disabled", false);
else
$("#queue_next").attr("disabled", true);
if(CHANNELOPTS.qopen_allow_playnext || LEADER)
$("#play_next").attr("disabled", false);
else
$("#play_next").attr("disabled", true);
}
else {
$("#playlist_controls").css("display", "none");
}
}
}

330
www/assets/js/sc.js Normal file
View File

@ -0,0 +1,330 @@
(function () {
var requirejs, require, define, __inflate;
(function (e) {
function a(e, t) {
var n = t && t.split("/"),
i = r.map,
s = i && i["*"] || {}, o, u, a, f, l, c, h;
if (e && e.charAt(0) === "." && t) {
n = n.slice(0, n.length - 1), e = n.concat(e.split("/"));
for (l = 0; h = e[l]; l++) if (h === ".") e.splice(l, 1), l -= 1;
else if (h === "..") {
if (l === 1 && (e[2] === ".." || e[0] === "..")) return !0;
l > 0 && (e.splice(l - 1, 2), l -= 2)
}
e = e.join("/")
}
if ((n || s) && i) {
o = e.split("/");
for (l = o.length; l > 0; l -= 1) {
u = o.slice(0, l).join("/");
if (n) for (c = n.length; c > 0; c -= 1) {
a = i[n.slice(0, c).join("/")];
if (a) {
a = a[u];
if (a) {
f = a;
break
}
}
}
f = f || s[u];
if (f) {
o.splice(0, l, f), e = o.join("/");
break
}
}
}
return e
}
function f(t, n) {
return function () {
return u.apply(e, s.call(arguments, 0).concat([t, n]))
}
}
function l(e) {
return function (t) {
return a(t, e)
}
}
function c(e) {
return function (n) {
t[e] = n
}
}
function h(r) {
if (n.hasOwnProperty(r)) {
var s = n[r];
delete n[r], i[r] = !0, o.apply(e, s)
}
if (!t.hasOwnProperty(r)) throw new Error("No " + r);
return t[r]
}
function p(e, t) {
var n, r, i = e.indexOf("!");
return i !== -1 ? (n = a(e.slice(0, i), t), e = e.slice(i + 1), r = h(n), r && r.normalize ? e = r.normalize(e, l(t)) : e = a(e, t)) : e = a(e, t), {
f: n ? n + "!" + e : e,
n: e,
p: r
}
}
function d(e) {
return function () {
return r && r.config && r.config[e] || {}
}
}
var t = {}, n = {}, r = {}, i = {}, s = [].slice,
o, u;
o = function (r, s, o, u) {
var a = [],
l, v, m, g, y, b;
u = u || r, typeof o == "string" && (o = __inflate(r, o));
if (typeof o == "function") {
s = !s.length && o.length ? ["require", "exports", "module"] : s;
for (b = 0; b < s.length; b++) {
y = p(s[b], u), m = y.f;
if (m === "require") a[b] = f(r);
else if (m === "exports") a[b] = t[r] = {}, l = !0;
else if (m === "module") v = a[b] = {
id: r,
uri: "",
exports: t[r],
config: d(r)
};
else if (t.hasOwnProperty(m) || n.hasOwnProperty(m)) a[b] = h(m);
else if (y.p) y.p.load(y.n, f(u, !0), c(m), {}), a[b] = t[m];
else if (!i[m]) throw new Error(r + " missing " + m)
}
g = o.apply(t[r], a);
if (r) if (v && v.exports !== e && v.exports !== t[r]) t[r] = v.exports;
else if (g !== e || !l) t[r] = g
} else r && (t[r] = o)
}, requirejs = require = u = function (t, n, i, s) {
return typeof t == "string" ? h(p(t, n).f) : (t.splice || (r = t, n.splice ? (t = n, n = i, i = null) : t = e), n = n || function () {}, s ? o(e, t, n, i) : setTimeout(function () {
o(e, t, n, i)
}, 15), u)
}, u.config = function (e) {
return r = e, u
}, define = function (e, t, r) {
t.splice || (r = t, t = []), n[e] = [e, t, r]
}, define.amd = {
jQuery: !0
}
})(), __inflate = function (name, src) {
var r;
return eval(["r = function(a,b,c){", "\n};\n//@ sourceURL=" + name + "\n"].join(src)), r
}, define("lib/api/events", ["require", "exports", "module"], function (e, t, n) {
t.api = {
LOAD_PROGRESS: "loadProgres",
PLAY_PROGRESS: "playProgress",
PLAY: "play",
PAUSE: "pause",
FINISH: "finish",
SEEK: "seek",
READY: "ready",
OPEN_SHARE_PANEL: "sharePanelOpened",
SHARE: "share",
CLICK_DOWNLOAD: "downloadClicked",
CLICK_BUY: "buyClicked"
}, t.bridge = {
REMOVE_LISTENER: "removeEventListener",
ADD_LISTENER: "addEventListener"
}
}), define("lib/api/getters", ["require", "exports", "module"], function (e, t, n) {
n.exports = {
GET_VOLUME: "getVolume",
GET_DURATION: "getDuration",
GET_POSITION: "getPosition",
GET_SOUNDS: "getSounds",
GET_CURRENT_SOUND: "getCurrentSound",
GET_CURRENT_SOUND_INDEX: "getCurrentSoundIndex",
IS_PAUSED: "isPaused"
}
}), define("lib/api/setters", ["require", "exports", "module"], function (e, t, n) {
n.exports = {
PLAY: "play",
PAUSE: "pause",
TOGGLE: "toggle",
SEEK_TO: "seekTo",
SET_VOLUME: "setVolume",
NEXT: "next",
PREV: "prev",
SKIP: "skip"
}
}), define("lib/api/api", ["require", "exports", "module", "lib/api/events", "lib/api/getters", "lib/api/setters"], function (e, t, n) {
function m(e) {
return !!(e === "" || e && e.charCodeAt && e.substr)
}
function g(e) {
return !!(e && e.constructor && e.call && e.apply)
}
function y(e) {
return !!e && e.nodeType === 1 && e.nodeName.toUpperCase() === "IFRAME"
}
function b(e) {
var t = !1,
n;
for (n in i) if (i.hasOwnProperty(n) && i[n] === e) {
t = !0;
break
}
return t
}
function w(e) {
var t, n, r;
for (t = 0, n = f.length; t < n; t++) {
r = e(f[t]);
if (r === !1) break
}
}
function E(e) {
var t = "",
n, r, i;
e.substr(0, 2) === "//" && (e = window.location.protocol + e), i = e.split("/");
for (n = 0, r = i.length; n < r; n++) {
if (!(n < 3)) break;
t += i[n], n < 2 && (t += "/")
}
return t
}
function S(e) {
return e.contentWindow ? e.contentWindow : e.contentDocument && "parentWindow" in e.contentDocument ? e.contentDocument.parentWindow : null
}
function x(e) {
var t = [],
n;
for (n in e) e.hasOwnProperty(n) && t.push(e[n]);
return t
}
function T(e, t, n) {
n.callbacks[e] = n.callbacks[e] || [], n.callbacks[e].push(t)
}
function N(e, t) {
var n = !0,
r;
return t.callbacks[e] = [], w(function (t) {
r = t.callbacks[e] || [];
if (r.length) return n = !1, !1
}), n
}
function C(e, t, n) {
var r = S(n),
i, s;
if (!r.postMessage) return !1;
i = n.getAttribute("src").split("?")[0], s = JSON.stringify({
method: e,
value: t
}), i.substr(0, 2) === "//" && (i = window.location.protocol + i), i = i.replace(/http:\/\/(w|wt).soundcloud.com/, "https://$1.soundcloud.com"), r.postMessage(s, i)
}
function k(e) {
var t;
return w(function (n) {
if (n.instance === e) return t = n, !1
}), t
}
function L(e) {
var t;
return w(function (n) {
if (S(n.element) === e) return t = n, !1
}), t
}
function A(e, t) {
return function (n) {
var r = g(n),
i = k(this),
s = !r && t ? n : null,
o = r && !t ? n : null;
return o && T(e, o, i), C(e, s, i.element), this
}
}
function O(e, t, n) {
var r, i, s;
for (r = 0, i = t.length; r < i; r++) s = t[r], e[s] = A(s, n)
}
function M(e, t, n) {
return e + "?url=" + t + "&" + _(n)
}
function _(e) {
var t, n, r = [];
for (t in e) e.hasOwnProperty(t) && (n = e[t], r.push(t + "=" + (t === "start_track" ? parseInt(n, 10) : n ? "true" : "false")));
return r.join("&")
}
function D(e, t, n) {
var r = e.callbacks[t] || [],
i, s;
for (i = 0, s = r.length; i < s; i++) r[i].apply(e.instance, n);
if (b(t) || t === o.READY) e.callbacks[t] = []
}
function P(e) {
var t, n, r, i, s;
try {
n = JSON.parse(e.data)
} catch (u) {}
t = L(e.source), r = n.method, i = n.value, r === o.READY && (t ? (t.isReady = !0, D(t, l), N(l, t)) : a.push(e.source)), r === o.PLAY && !t.playEventFired && (t.playEventFired = !0), r === o.PLAY_PROGRESS && !t.playEventFired && (t.playEventFired = !0, D(t, o.PLAY, [i]));
if (!t || H(e.origin) !== H(t.domain)) return !1;
s = [], i !== undefined && s.push(i), D(t, r, s)
}
// Hack
function H(e) {
return e.replace(h, "")
}
var r = e("lib/api/events"),
i = e("lib/api/getters"),
s = e("lib/api/setters"),
o = r.api,
u = r.bridge,
a = [],
f = [],
l = "__LATE_BINDING__",
c = "http://wt.soundcloud.dev:9200/",
h = /^http(?:s?)/,
p, d, v;
window.scwtf = P;
window.fixSoundcloudShit = function() {
window.removeEventListener ? window.removeEventListener("message", window.scwtf, !1) : window.detachEvent("onmessage", window.scwtf);
}
window.unfixSoundcloudShit = function() {
window.addEventListener ? window.addEventListener("message", scwtf, !1) : window.attachEvent("onmessage", scwtf);
}
n.exports = v = function (e, t, n) {
m(e) && (e = document.getElementById(e));
if (!y(e)) throw new Error("SC.Widget function should be given either iframe element or a string specifying id attribute of iframe element.");
t && (n = n || {}, e.src = M(c, t, n));
var r = L(S(e)),
i, s;
return r && r.instance ? r.instance : (i = a.indexOf(S(e)) > -1, s = new p(e), f.push(new d(s, e, i)), s)
}, v.Events = o, window.SC = window.SC || {}, window.SC.Widget = v, d = function (e, t, n) {
this.instance = e, this.element = t, this.domain = E(t.getAttribute("src")), this.isReady = !! n, this.callbacks = {}
}, p = function () {}, p.prototype = {
constructor: p,
load: function (e, t) {
if (!e) return;
t = t || {};
var n = this,
r = k(this),
i = r.element,
s = i.src,
a = s.substr(0, s.indexOf("?"));
r.isReady = !1, r.playEventFired = !1, i.onload = function () {
n.bind(o.READY, function () {
var e, n = r.callbacks;
for (e in n) n.hasOwnProperty(e) && e !== o.READY && C(u.ADD_LISTENER, e, r.element);
t.callback && t.callback()
})
}, i.src = M(a, e, t)
},
bind: function (e, t) {
var n = this,
r = k(this);
return r && r.element && (e === o.READY && r.isReady ? setTimeout(t, 1) : r.isReady ? (T(e, t, r), C(u.ADD_LISTENER, e, r.element)) : T(l, function () {
n.bind(e, t)
}, r)), this
},
unbind: function (e) {
var t = k(this),
n;
t && t.element && (n = N(e, t), e !== o.READY && n && C(u.REMOVE_LISTENER, e, t.element))
}
}, O(p.prototype, x(i)), O(p.prototype, x(s), !0)
}), window.SC = window.SC || {}, window.SC.Widget = require("lib/api/api")
})()

View File

@ -160,8 +160,8 @@
</div>
</div> <!-- /container -->
<script src="https://w.soundcloud.com/player/api.js"></script>
<script src="http://api.dmcdn.net/all.js"></script>
<script src="./assets/js/sc.js"></script>
<script src="./assets/js/froogaloop.min.js"></script>
<script src="./assets/js/jquery.js"></script>
<script src="./assets/js/webtoolkit.sha256.js" type="text/javascript"></script>