From 3f959087af9d3f28397b3ebec0d0cbcb96fa1560 Mon Sep 17 00:00:00 2001 From: Calvin Montgomery Date: Wed, 9 Jul 2014 21:20:14 -0700 Subject: [PATCH] Initial improvements to playback system --- lib/channel/channel.js | 1 + lib/channel/mediarefresher.js | 93 +++++++++++++++++++++++++++++++++++ lib/channel/playlist.js | 90 ++++++++++----------------------- www/js/player.js | 8 +++ 4 files changed, 128 insertions(+), 64 deletions(-) create mode 100644 lib/channel/mediarefresher.js diff --git a/lib/channel/channel.js b/lib/channel/channel.js index 0f573185..6636ae84 100644 --- a/lib/channel/channel.js +++ b/lib/channel/channel.js @@ -114,6 +114,7 @@ Channel.prototype.initModules = function () { "./opts" : "options", "./library" : "library", "./playlist" : "playlist", + "./mediarefresher": "mediarefresher", "./voteskip" : "voteskip", "./poll" : "poll", "./kickban" : "kickban", diff --git a/lib/channel/mediarefresher.js b/lib/channel/mediarefresher.js new file mode 100644 index 00000000..ec758c7a --- /dev/null +++ b/lib/channel/mediarefresher.js @@ -0,0 +1,93 @@ +var ChannelModule = require("./module"); +var Config = require("../config"); +var InfoGetter = require("../get-info"); + +function MediaRefresherModule(channel) { + ChannelModule.apply(this, arguments); + this._interval = false; + this._media = null; +} + +MediaRefresherModule.prototype = Object.create(ChannelModule.prototype); + +MediaRefresherModule.prototype.onMediaChange = function (data) { + if (this._interval) clearInterval(this._interval); + + this._media = data; + + switch (data.type) { + case "gd": + return this.initGoogleDocs(data); + case "vi": + return this.initVimeo(data); + } +}; + +MediaRefresherModule.prototype.initGoogleDocs = function (data) { + var self = this; + self.refreshGoogleDocs(data, true); + + /* + * Refresh every 55 minutes. + * The expiration is 1 hour, but refresh 5 minutes early to be safe + */ + self._interval = setInterval(function () { + self.refreshGoogleDocs(data, false); + }, 55 * 60 * 1000); +}; + +MediaRefresherModule.prototype.initVimeo = function (data) { + if (!Config.get("vimeo-workaround")) { + return; + } + + var self = this; + self.channel.activeLock.lock(); + InfoGetter.vimeoWorkaround(data.id, function (hack) { + if (self._media === data) { + self.channel.logger.log("[mediarefresher] Refreshed vimeo video with ID " + + data.id); + data.meta.direct = hack; + self.channel.broadcastAll("changeMedia", data.getFullUpdate()); + } + self.channel.activeLock.release(); + }); +}; + +MediaRefresherModule.prototype.refreshGoogleDocs = function (media, update) { + var self = this; + + if (self.dead || self.channel.dead) { + return; + } + + self.channel.activeLock.lock(); + InfoGetter.getMedia(media.id, "gd", function (err, data) { + switch (err) { + case "HTTP 302": + case "Video not found": + case "Private video": + return; + default: + if (err) { + Logger.errlog.log("Google Docs refresh failed for ID " + media.id + + ": " + err); + return self.channel.activeLock.release(); + } + } + + if (media !== self._media) { + return self.channel.activeLock.release(); + } + + self.channel.logger.log("[mediarefresher] Refreshed Google Docs video with ID " + + media.id); + media.meta = data.meta; + if (update) { + self.channel.broadcastAll("changeMedia", data.getFullUpdate()); + } + self.channel.activeLock.release(); + }); +}; + +module.exports = MediaRefresherModule; diff --git a/lib/channel/playlist.js b/lib/channel/playlist.js index bf4a17d7..24b22431 100644 --- a/lib/channel/playlist.js +++ b/lib/channel/playlist.js @@ -977,72 +977,34 @@ PlaylistModule.prototype.startPlayback = function (time) { var media = self.current.media; media.reset(); - var continuePlayback = function () { - if (self.leader != null) { - media.paused = false; - media.currentTime = time || 0; - self.sendChangeMedia(self.channel.users); - self.channel.notifyModules("onMediaChange", self.current.media); - return; - } - - /* Lead-in time of 3 seconds to allow clients to buffer */ - time = time || -3; - media.paused = time < 0; - media.currentTime = time; - - /* Module was already leading, stop the previous timer */ - if (self._leadInterval) { - clearInterval(self._leadInterval); - self._leadInterval = false; - } - + if (self.leader != null) { + media.paused = false; + media.currentTime = time || 0; self.sendChangeMedia(self.channel.users); - self.channel.notifyModules("onMediaChange", self.current.media); - - /* Only start the timer if the media item is not live, i.e. has a duration */ - if (media.seconds > 0) { - self._lastUpdate = Date.now(); - self._leadInterval = setInterval(function() { - self._leadLoop(); - }, 1000); - } - - /* Google Docs autorefresh */ - if (self._gdRefreshTimer) { - clearInterval(self._gdRefreshTimer); - self._gdRefreshTimer = false; - } - - if (media.type === "gd") { - self._gdRefreshTimer = setInterval(self.refreshGoogleDocs.bind(self), 3600000); - if (media.meta.expiration && media.meta.expiration < Date.now() + 3600000) { - setTimeout(self.refreshGoogleDocs.bind(self), media.meta.expiration - Date.now()); - } - } - }; - - if (media.type === "vi" && !media.meta.direct && Config.get("vimeo-workaround")) { - self.channel.activeLock.lock(); - vimeoWorkaround(media.id, function (direct) { - self.channel.activeLock.release(); - if (self.current && self.current.media === media) { - self.current.media.meta.direct = direct; - continuePlayback(); - } - }); + self.channel.notifyModules("onMediaChange", [self.current.media]); return; - } else if (media.type === "gd" && isExpired(media) && !media.meta.failed) { - self.channel.activeLock.lock(); - self.refreshGoogleDocs(function () { - self.channel.activeLock.release(); - if (self.current && self.current.media === media) { - continuePlayback(); - } - }); - return; - } else { - continuePlayback(); + } + + /* Lead-in time of 3 seconds to allow clients to buffer */ + time = time || -3; + media.paused = time < 0; + media.currentTime = time; + + /* Module was already leading, stop the previous timer */ + if (self._leadInterval) { + clearInterval(self._leadInterval); + self._leadInterval = false; + } + + self.sendChangeMedia(self.channel.users); + self.channel.notifyModules("onMediaChange", [self.current.media]); + + /* Only start the timer if the media item is not live, i.e. has a duration */ + if (media.seconds > 0) { + self._lastUpdate = Date.now(); + self._leadInterval = setInterval(function() { + self._leadLoop(); + }, 1000); } } diff --git a/www/js/player.js b/www/js/player.js index 58ee605c..b40d28dc 100644 --- a/www/js/player.js +++ b/www/js/player.js @@ -1002,7 +1002,15 @@ var GoogleDocsPlayer = function (data) { self.videoLength = data.seconds; self.paused = false; var wmode = USEROPTS.wmode_transparent ? "transparent" : "opaque"; + var meta = data.meta; + if (!meta || !meta.object || !meta.params) { + // Reset videoId so that a changeMedia with the appropriate data + // will properly reset the player + self.videoId = ""; + return; + } + self.player = $("", meta.object)[0]; $(self.player).attr("data", meta.object.data); $(self.player).attr("width", VWIDTH)