diff --git a/channel.js b/channel.js index 375610b4..e504d907 100644 --- a/channel.js +++ b/channel.js @@ -142,7 +142,7 @@ Channel.prototype.loadDump = function() { fs.readFile("chandump/" + this.name, function(err, data) { if(err) { if(err.code == "ENOENT") { - Logger.errlog.log("WARN: missing dump for " + this.name); + Logger.errlog.log("WARN: missing dump for.Media " + this.name); this.initialized = true; this.saveDump(); } @@ -155,7 +155,6 @@ Channel.prototype.loadDump = function() { try { this.logger.log("*** Loading channel dump from disk"); data = JSON.parse(data); - // TODO fix loading if(data.queue) { for(var i = 0; i < data.queue.length; i++) { var e = data.queue[i]; @@ -166,24 +165,22 @@ Channel.prototype.loadDump = function() { if(e.temp !== undefined) { p.temp = e.temp; } - //this.playlist.append(p); + this.playlist.append(p); } + this.sendAll("playlist", this.playlist.toArray()); + if(this.playlist.current) + this.sendAll("setCurrent", this.playlist.current.uid); + this.broadcastPlaylistMeta(); } else if(data.playlist) { - //TODO fix - this.playlist.current = this.playlist.find(data.currentUID) || null; + var chan = this; + this.playlist.load(data.playlist, function() { + chan.sendAll("playlist", chan.playlist.toArray()); + if(chan.playlist.current) + chan.sendAll("setCurrent", chan.playlist.current.uid); + chan.broadcastPlaylistMeta(); + }); } - this.sendAll("playlist", this.playlist.toArray()); - this.broadcastPlaylistMeta(); - // Backwards compatibility - if(data.currentPosition != undefined) { - this.position = data.currentPosition - 1; - } - else { - this.position = data.position - 1; - } - if(this.position < -1) - this.position = -1; for(var key in data.opts) { // Gotta love backwards compatibility if(key == "customcss" || key == "customjs") { @@ -234,7 +231,7 @@ Channel.prototype.loadDump = function() { } catch(e) { Logger.errlog.log("Channel dump load failed: "); - Logger.errlog.log(e); + Logger.errlog.log(e.stack); } }.bind(this)); } @@ -249,7 +246,7 @@ Channel.prototype.saveDump = function() { var dump = { position: this.position, currentTime: this.media ? this.media.currentTime : 0, - playlist: this.playlist.toArray(), + playlist: this.playlist.dump(), opts: this.opts, permissions: this.permissions, filters: filts, @@ -731,6 +728,8 @@ Channel.prototype.sendChannelRanks = function(user) { Channel.prototype.sendPlaylist = function(user) { user.socket.emit("playlist", this.playlist.toArray()); + if(this.playlist.current) + user.socket.emit("setCurrent", this.playlist.current.uid); user.socket.emit("setPlaylistMeta", this.plmeta); } @@ -1007,21 +1006,20 @@ function isLive(type) { } Channel.prototype.queueAdd = function(item, after) { + var chan = this; + function afterAdd() { + chan.sendAll("queue", { + item: item.pack(), + after: after + }); + chan.broadcastPlaylistMeta(); + } if(after === "prepend") - this.playlist.prepend(item); + this.playlist.prepend(item, afterAdd); else if(after === "append") - this.playlist.append(item); + this.playlist.append(item, afterAdd); else - this.playlist.insertAfter(item, after); - - this.sendAll("queue", { - item: item.pack(), - after: after - }); - - this.broadcastPlaylistMeta(); - if(this.playlist.length == 1) - this.sendAll("changeMedia", this.playlist.current.media.fullupdate()); + this.playlist.insertAfter(item, after, afterAdd); } Channel.prototype.autoTemp = function(item, user) { @@ -1075,7 +1073,7 @@ Channel.prototype.enqueue = function(data, user, callback) { user.socket.emit("queueFail", err); return; } - var item = this.playlist.makeItem(item); + var item = this.playlist.makeItem(media); item.queueby = user ? user.name : ""; this.autoTemp(item, user); this.queueAdd(item, after); @@ -1245,7 +1243,7 @@ Channel.prototype.setTemp = function(uid, temp) { }); if(!temp) { - this.cacheMedia(m); + this.cacheMedia(item.media); } } @@ -1261,10 +1259,13 @@ Channel.prototype.trySetTemp = function(user, data) { } -Channel.prototype.dequeue = function(uid, removeonly) { - if(!this.playlist.remove(uid, true)) +Channel.prototype.dequeue = function(uid) { + var chan = this; + function afterDelete() { + chan.broadcastPlaylistMeta(); + } + if(!this.playlist.remove(uid, true, afterDelete)) return; - this.broadcastPlaylistMeta(); } Channel.prototype.tryDequeue = function(user, data) { @@ -1290,47 +1291,20 @@ Channel.prototype.tryUncache = function(user, data) { } } -Channel.prototype.resetVideoMeta = function() { - this.voteskip = false; - this.broadcastVoteskipUpdate(); - this.drinks = 0; - this.broadcastDrinks(); - if(this.playlist.current) { - this.playlist.current.media["currentTime"]; - this.playlist.current.media["paused"]; - } -} - Channel.prototype.playNext = function() { - this.resetVideoMeta(); this.playlist.next(); - if(this.playlist.current) - this.sendAll("changeMedia", this.playlist.current.media.fullupdate()); } Channel.prototype.tryPlayNext = function(user) { if(!this.hasPermission(user, "playlistjump")) { return; - } + } - this.playNext(); + this.playNext(); } Channel.prototype.jumpTo = function(uid) { - this.resetVideoMeta(); - var oid = this.playlist.current ? this.playlist.current.uid : -1; - if(!this.playlist.jump(uid)) - return; - - this.sendAll("changeMedia", this.playlist.current.media.fullupdate()); - - // If it's not a livestream, enable autolead - if(this.leader == null && !isLive(this.playlist.current.media.type)) { - this.time = new Date().getTime(); - if(this.playlist.current.media.uid != oid) { - //mediaUpdate(this, this.playlist.current.media); - } - } + return this.playlist.jump(uid); } Channel.prototype.tryJumpTo = function(user, data) { @@ -1408,35 +1382,20 @@ Channel.prototype.tryUpdate = function(user, data) { } Channel.prototype.move = function(data, user) { - var item = this.playlist.find(data.from); - if(!this.playlist.remove(data.from)) { - console.log("remove failed"); - return; + var chan = this; + function afterMove() { + var moveby = user && user.name ? user.name : null; + if(typeof data.moveby !== "undefined") + moveby = data.moveby; + + chan.sendAll("moveVideo", { + from: data.from, + after: data.after, + moveby: moveby + }); } - if(data.after === "prepend") { - if(!this.playlist.prepend(item)) { - return; - } - } - else if(data.after === "append") { - if(!this.playlist.append(item)) { - return; - } - } - else if(!this.playlist.insertAfter(item, data.after)) { - return; - } - - var moveby = user && user.name ? user.name : null; - if(typeof data.moveby !== "undefined") - moveby = data.moveby; - - this.sendAll("moveVideo", { - from: data.from, - after: data.after, - moveby: moveby - }); + this.playlist.move(data.from, data.after, afterMove); } Channel.prototype.tryMove = function(user, data) { diff --git a/database.js b/database.js index 30a42530..108ff8ae 100644 --- a/database.js +++ b/database.js @@ -867,10 +867,10 @@ function saveUserPlaylist(pl, user, name) { var time = 0; for(var i = 0; i < pl.length; i++) { var e = { - id: pl[i].id, - type: pl[i].type + id: pl[i].media.id, + type: pl[i].media.type }; - time += pl[i].seconds; + time += pl[i].media.seconds; pl2.push(e); } var count = pl2.length; diff --git a/get-info.js b/get-info.js index 9afb5b74..bdbdb908 100644 --- a/get-info.js +++ b/get-info.js @@ -254,7 +254,7 @@ exports.getMedia = function(id, type, callback) { } catch(e) { Logger.errlog.log("getMedia failed: "); - Logger.errlog.log(e); + Logger.errlog.log(e.stack); callback(true, null); } }); diff --git a/playlist.js b/playlist.js index 301e2d5b..64aad4dd 100644 --- a/playlist.js +++ b/playlist.js @@ -1,3 +1,5 @@ +var Media = require("./media").Media; + function PlaylistItem(media, uid) { this.media = media; this.uid = uid; @@ -9,7 +11,7 @@ function PlaylistItem(media, uid) { PlaylistItem.prototype.pack = function() { return { - media: this.media, + media: this.media.pack(), uid: this.uid, temp: this.temp, queueby: this.queueby @@ -49,6 +51,49 @@ function Playlist(chan) { } } +Playlist.prototype.dump = function() { + var arr = []; + var item = this.first; + var i = 0; + var pos = 0; + while(item != null) { + arr.push(item.pack()); + if(item == this.current) + pos = i; + i++; + item = item.next; + } + + var time = 0; + if(this.current) + time = this.current.media.currentTime; + + return { + pl: arr, + pos: pos, + time: time + }; +} + +Playlist.prototype.load = function(data, callback) { + this.clear(); + for(var i in data.pl) { + var e = data.pl[i].media; + var m = new Media(e.id, e.title, e.seconds, e.type); + var it = this.makeItem(m); + it.temp = data.pl[i].temp; + it.queueby = data.pl[i].queueby; + this._append(it); + if(i == parseInt(data.pos)) { + this.current = it; + this.startPlayback(data.time); + } + } + + if(callback) + callback(); +} + Playlist.prototype.on = function(ev, fn) { if(typeof fn === "undefined") { var pl = this; @@ -83,7 +128,13 @@ Playlist.prototype.find = function(uid) { return false; } -Playlist.prototype.prepend = function(plitem) { +Playlist.prototype.prepend = function(plitem, callback) { + this._prepend(plitem, callback); + if(this.length == 1) + this.startPlayback(); +} + +Playlist.prototype._prepend = function(plitem, callback) { if(this.first !== null) { plitem.next = this.first; this.first.prev = plitem; @@ -92,15 +143,22 @@ Playlist.prototype.prepend = function(plitem) { else { this.current = plitem; this.last = plitem; - this.startPlayback(); } this.first = plitem; this.first.prev = null; this.length++; + if(callback) + callback(); return true; } -Playlist.prototype.append = function(plitem) { +Playlist.prototype.append = function(plitem, callback) { + this._append(plitem, callback); + if(this.length == 1) + this.startPlayback(); +} + +Playlist.prototype._append = function(plitem, callback) { if(this.last != null) { plitem.prev = this.last; this.last.next = plitem; @@ -109,15 +167,20 @@ Playlist.prototype.append = function(plitem) { else { this.first = plitem; this.current = plitem; - this.startPlayback(); } this.last = plitem; this.last.next = null; this.length++; + if(callback) + callback(); return true; } -Playlist.prototype.insertAfter = function(plitem, uid) { +Playlist.prototype.insertAfter = function(plitem, uid, callback) { + this._insertAfter(plitem, uid, callback); +} + +Playlist.prototype._insertAfter = function(plitem, uid, callback) { var item = this.find(uid); if(item) { @@ -128,6 +191,8 @@ Playlist.prototype.insertAfter = function(plitem, uid) { this.last = plitem; } this.length++; + if(callback) + callback(); return true; } @@ -135,6 +200,11 @@ Playlist.prototype.insertAfter = function(plitem, uid) { } Playlist.prototype.remove = function(uid, next) { + this._remove(uid, next); + this.on("remove")(item); +} + +Playlist.prototype._remove = function(uid, next) { var item = this.find(uid); if(!item) return false; @@ -149,8 +219,6 @@ Playlist.prototype.remove = function(uid, next) { if(item.next) item.next.prev = item.prev; - this.on("remove")(item); - if(this.current == item && next) this._next(); @@ -158,6 +226,27 @@ Playlist.prototype.remove = function(uid, next) { return true; } +Playlist.prototype.move = function(from, after, callback) { + var it = this.find(from); + if(!this._remove(from)) + return; + + if(after === "prepend") { + if(!this._prepend(it)) + return; + } + + else if(after === "append") { + if(!this._append(it)) + return; + } + + else if(!this._insertAfter(it, after)) + return; + + callback(); +} + Playlist.prototype.next = function() { if(!this.current) return; @@ -240,9 +329,9 @@ Playlist.prototype.lead = function(lead) { } } -Playlist.prototype.startPlayback = function() { +Playlist.prototype.startPlayback = function(time) { this.current.media.paused = true; - this.current.media.currentTime = -2; + this.current.media.currentTime = time || -2; var pl = this; setTimeout(function() { if(!pl.current) @@ -251,6 +340,7 @@ Playlist.prototype.startPlayback = function() { pl.on("mediaUpdate")(pl.current.media); }, 2000); if(this.leading && !this._leadInterval && !isLive(this.current.media.type)) { + this._lastUpdate = Date.now(); this._leadInterval = setInterval(function() { pl._leadLoop(); }, 1000); @@ -281,7 +371,6 @@ Playlist.prototype._leadLoop = function() { this.current.media.currentTime += (Date.now() - this._lastUpdate) / 1000.0; this._lastUpdate = Date.now(); this._counter++; - console.log("lead", this._counter); if(this.current.media.currentTime >= this.current.media.seconds + 2) { this.next(); diff --git a/user.js b/user.js index 26a74ae1..4653e110 100644 --- a/user.js +++ b/user.js @@ -484,7 +484,7 @@ User.prototype.initCallbacks = function() { return; } - var pl = this.channel.queue; + var pl = this.channel.playlist.toArray(); var result = Database.saveUserPlaylist(pl, this.name, data.name); this.socket.emit("savePlaylist", { success: result,