diff options
Diffstat (limited to 'www/static/js/player.js')
| -rwxr-xr-x | www/static/js/player.js | 546 |
1 files changed, 546 insertions, 0 deletions
diff --git a/www/static/js/player.js b/www/static/js/player.js new file mode 100755 index 0000000..87973a4 --- /dev/null +++ b/www/static/js/player.js @@ -0,0 +1,546 @@ +var VIMEOregexp = /^(\bhttps?:\/\/)(www.)?vimeo.com\/([0-9]+).*$/i +var PLAY_BUTTONS = + { + prev: "<div class='arrow-prev'></div> <div class='arrow-prev'></div>", + next: "<div class='arrow-next'></div> <div class='arrow-next'></div>", + pause: "<div class='arrow-pause'></div> <div class='arrow-pause'></div>", + play: "<div class='arrow-play'></div>", + } +var Player = + { + videos: {}, + queue: [], + projectors: {}, + projector: null, + newVideos: false, + currentIdx: 0, + video: false, + errors: 0, + width: '100%', + height: '100%', + playlistOffset: 30, + queueOffset: 60, + paused: false, + muted: false, + enqueue: function (video) + { + if (! (video.type in Player.projectors)) + return d.error("unknown video type "+video.type) + var key = video.type+"_"+video.name + if (key in Player.videos) + { + Player.videos[key].idx = Player.queue.length + Player.videos[key].seen = false + if (video.offset) + Player.videos[key].offset = video.offset + d.warn("bumped "+key) + } + else + { + video.key = key + video.idx = Player.queue.length + Player.videos[key] = video + Player.newVideos = true + d.warn("enqueued "+key) + } + $("#"+video.key).html(video.title) + Player.queue.push(key) + return true + }, + clearQueue: function () + { + Player.queue = [] + Player.currentIdx = 0 + Playlist.count = 0 + }, + register: function (projector) + { + d.warn("registered "+projector.type) + Player.projectors[projector.type] = projector + }, + unregister: function (projectortype) + { + d.warn("unregistered "+projectortype) + delete Player.projectors[projectortype] + }, + start: function () + { + d.warn("PLAYER START") + Player.currentIdx = Player.queue.length - 1 + if (! Player.queue.length) + return d.error("empty queue") + Player.playLatest() + }, + finish: function () + { + d.warn("PLAYER FINISH") + d.warn("____________") + Player.playLatest() + }, + error: function (s) + { + if (s) + d.error(Player.errors+" "+s) + else + d.error("PLAYER ERROR "+Player.errors) + $("li#queue_"+Player.video.idx+" span.title").html("<i>This video cannot be embedded</i>") + Player.video.error = true + }, + playLatest: function () + { + d.warn("PLAY LATEST") + var idx = Player.currentIdx + var len = Player.queue.length + if (Player.newVideos) + { + for (i = idx; i < len; i++) + { + var video = Player.videos[Player.queue[i]] + d.warn("check "+Player.queue[i]) + if (video.seen) + continue + Player.currentIdx = i + d.joy("new video! "+video.key+" at "+i) + Player.queueJumpToCurrentVideo(Player.currentIdx) + Player.playVideo(video) + return + } + for (i = idx - 1; i >= 0; i--) + { + var video = Player.videos[Player.queue[i]] + d.warn("check "+Player.queue[i]) + if (video.seen) + continue + Player.currentIdx = i + d.joy("new video! "+video.key+" at "+i) + Player.queueJumpToCurrentVideo(Player.currentIdx) + Player.playVideo(video) + return + } + Player.newVideos = false + d.warn("no new videos") + } + Player.playNext() + }, + playNext: function () + { + d.warn("____________") + d.warn("PLAY NEXT") + var idx = Player.currentIdx + do + { + idx -= 1 + if (Player.queue[idx] === Player.video.key) + idx -= 1 + if (idx < 0) + idx = Player.queue.length - 1 + } + while (Player.videos[ Player.queue[idx] ].error === true) + Player.queueJumpToCurrentVideo(idx) + Player.playIdx(idx) + }, + playPrev: function () + { + d.warn("____________") + d.warn("PLAY PREV") + var idx = Player.currentIdx + do + { + idx = (idx + 1) % Player.queue.length + if (Player.queue[idx] === Player.video.key) + continue + } + while (Player.videos[ Player.queue[idx] ].error === true) + Player.queueJumpToCurrentVideo(idx) + Player.playIdx(idx) + }, + playKey: function (key) + { + Player.playVideo( Player.videos[key] ) + }, + playIdx: function (idx) + { + d.warn("play idx: "+idx) + Player.currentIdx = idx + Player.playVideo( Player.videos[Player.queue[idx]] ) + }, + throttle: function () + { + d.error("THROTTLED") + Player.stop() + Player.errors = 0 + }, + stop: function () + { + Player.projector.stop() + }, + playVideo: function (video) + { + if (! video) + { + d.error("GOT EMPTY VIDEO") + d.warn(Player.currentIdx) + d.warn(Player.queue[ Player.currentIdx ]) + d.warn(Player.videos[ Player.queue[ Player.currentIdx ] ]) + return + } + if (video.error === true) + { + Player.errors += 1 + d.error(video.key) + if (Player.errors > Player.queue.length) + return Player.throttle() + return Player.finish() + } + d.warn("PLAY VIDEO: "+video.key) + if (video.type !== Player.projector.type) + { + d.warn("SWITCHING PROJECTORS") + d.warn([Player.projector.type, video.type].join(" → ")) + Player.projector.unload() + Player.projector = Player.projectors[video.type] + Player.projector.load() + if (Player.muted) + Player.projector.setVolume(0) + } + video.seen = true + if (! Player.fullscreenMode) + { + $("#video-title").hide().html(video.title).fadeIn(100, function () { + setTimeout("$('#video-title').fadeOut(2000)", 4000) + }) + } + + Player.errors = 0 + Player.video = video + Player.projector.play(video) + Player.linkUpdate(video) + Player.currentIdx = video.idx + $("#queue li.playing").removeClass("playing") + $("#chat a.ytlink.playing").removeClass("playing") + $("#queue li").removeClass("playing") + $("li#queue_"+video.idx).addClass("playing") + $("#"+video.key).addClass("playing") + $("#"+video.key).html(video.title) + $("#like").removeClass("liked").html("LIKE") + $("#pause").html(PLAY_BUTTONS.pause) + if (Local.isLiked(video.id)) + { + $("#like").addClass("liked").html("LIKED") + } + }, + queueJumpToCurrentVideo: function (idx) + { + $("#playlist").scrollTop( $("li#queue_"+idx)[0].offsetTop - Player.playlistOffset ) + $("#queue").scrollTop( $("li#queue_"+idx)[0].offsetTop - Player.queueOffset ) + }, + toggle: function () + { + Player.projector.toggle() + }, + pause: function () + { + Player.projector.pause() + $("#pause").html(PLAY_BUTTONS.play) + }, + mute: function () + { + if (Player.projector) + { + if (Player.muted) + Player.projector.setVolume(100) + else + Player.projector.setVolume(0) + } + Player.muted = ! Player.muted + }, + muteClick: function () + { + if (Player.muted) + $("#mute").removeClass("muted") + else + $("#mute").addClass("muted") + Player.mute() + }, + prevClick: function () + { + d.act("+ clicked prev") + Player.playPrev() + }, + pauseClick: function () + { + d.act("+ clicked pause") + Player.errors = 0 + if (Player.projector.toggle()) + { + $("#pause").html(PLAY_BUTTONS.play) + d.warn("set to play") + } + else + { + $("#pause").html(PLAY_BUTTONS.pause) + d.warn("set to pause") + } + }, + nextClick: function () + { + d.act("+ clicked next") + Player.playNext() + }, + scanClick: function () + { + d.act("+ clicked scan") + Scanner.scan() + }, + likeClick: function () + { + d.act("+ clicked player like") + Like.likeVideo(Player.video) + }, + linkClick: function () + { + d.act("+ clicked permalink") + Player.pause() + }, + linkUpdate: function (video) + { + d.warn("UPDATING LINK") + $("#video-link").attr("href", video.src) + var vidurl = "http://scannerjammer.com/" + if (Room.name !== "main") + vidurl += Room.name+"/" + vidurl += "#v="+video.id + $("#sharebutton").attr("st_url", vidurl).attr("st_title", video.title) +/* + stWidget.addEntry({ + service: "sharethis", + element: document.getElementById("sharebutton"), + url: vidurl, + title: video.title, + summary: "ScannerJammer: Youtube video chat", + }) +*/ + }, + + fullscreenClick: function () + { + d.act("+ clicked fullscreen") + }, + setVolume: function (vol) + { + if (Player.projector && Player.projector.type !== 'null') + { + // alert(Player.projector.type) + Player.projector.setVolume(vol) + } + }, + init: function () + { + d.warn("PLAYER INIT") + $("#prev").html(PLAY_BUTTONS.prev) + $("#pause").html(PLAY_BUTTONS.play) + $("#next").html(PLAY_BUTTONS.next) + $("#prev").bind("click", Player.prevClick) + $("#pause").bind("click", Player.pauseClick) + $("#next").bind("click", Player.nextClick) + $("#scan").bind("click", Player.scanClick) + $("#like").bind("click", Player.likeClick) + $("#video-link").bind("click", Player.linkClick) + $("#fullscreen").bind("click", Viewport.fullscreenOn) + Player.projector = {type:"null",load:d.noop,unload:Youtube.unload,} + for (i in Player.projectors) + Player.projectors[i].init() + if (Player.queue.length > 0) + Player.currentIdx = Player.queue.length + Playlist.init() + } + } + +var Playlist = + { + count: 0, + showScores: false, + enqueue: function (videos) + { + if (! (videos instanceof Array)) + videos = [videos] + // d.warn("PLAYLIST ENQUEUE "+videos.length) + var rows = [] + var clickables = [] + for (i in videos) + { + var video = videos[i] + $("#"+video.key).html(video.title) + if (Player.enqueue(video)) + { + rows.push(Playlist.display(video)) + Playlist.count += 1 + } + } + $("#queue").prepend(rows.reverse().join("")) + }, + enqueueOldVideoFormat: function (videos) + { + // d.warn("ENQUEUING "+videos.length+" OLD FORMAT") + for (i in videos) + { + // 0 id 1 date 2 userid 3 user 4 url 5 title + var row = videos[i] + var video = + { + id: row[0], + date: row[1], + userid: row[2], + username: row[3], + src: row[4], + title: row[5] || '___', + seen: false, + error: false, + } + if (row.length > 6) + { + video.score = parseInt(row[6]) || 0 + // block video if it's a duplicate + } + var url = row[4] + if (url.indexOf("youtube.com") !== -1) + { + var ytid = Youtube.getYtid(url) + video.type = "youtube" + video.name = ytid + } + else if (url.indexOf("vimeo.com") !== -1) + { + var vimeoid = url.replace(VIMEOregexp, "$3") + video.type = "vimeo" + video.name = vimeoid + } + else if (url.indexOf("soundcloud.com") !== -1) + { + video.type = "soundcloud" + video.name = $.md5(video.src) + } + else if (url.indexOf("mp3") !== -1) + { + video.type = "audio" + video.name = $.md5(video.src) + } + else + { + d.error("bad video id in "+url) + continue + } + video.key = video.type + "_" + video.name + Playlist.enqueue(video) + // d.joy("GOT VIDEO: "+key) + } + }, + clickTitle: function (e) + { + var id = $(this).parent().attr("id") + var idx = id.substr(id.indexOf("_")+1) + d.act("+ clicked playlist "+idx) + Player.playIdx(parseInt(idx)) + }, + clickLike: function (e) + { + var id = $(this).parent().attr("id") + var idx = id.substr(id.indexOf("_")+1) + var videokey = Player.queue[idx] + var video = Player.videos[videokey] + d.act("+ clicked playlist like "+video.key) + Like.likeVideo(video) + }, + clickChatlink: function (e) + { + e.preventDefault() + var key = $(this).attr("id") + var video = Player.videos[key] + d.act("+ clicked link "+video.key) + Player.playVideo(video) + }, + display: function (video) + { + var likeClass = '' + var likeWord = " like" + if (video.username === Auth.username) + { + likeClass = "you" + } + else if (Local.isLiked(video.id)) + { + likeClass = 'liked' + likeWord = 'liked' + } + var s = "<li id='queue_"+Playlist.count+"'>" + if (Playlist.showScores) + { + score = video.score + if (score < 1) + score = ' ' + s += "<span class='score' id='score_"+video.id+"'>"+score+"</span>" + } + s += "<span id='like_"+video.id+"' class='like "+likeClass+"'>"+likeWord+"</span>" + s += "<a class='user' href='/profile/"+video.username+"'>"+video.username+"</a>" + s += "<span class='title'>"+video.title+"</span>" + s += "</li>" + return s + }, + init: function () + { + d.warn("PLAYLIST INIT") + $("#queue li span.title").live("click", Playlist.clickTitle) + $("#queue li span.like").live("click", Playlist.clickLike) + $("#chat a.ytlink").live("click", Playlist.clickChatlink) + } + } + +var Scanner = + { + scanMode: false, + scanTimeout: false, + scanBlinkTimeout: false, + scanBlinkState: false, + scanBlinkRate: 200, + scanRate: 9000, + scanBlink: function () + { + if (Scanner.scanBlinkState) + { + $("#scan").addClass("blinkOff") + $("#scan").removeClass("blinkOn") + Scanner.scanBlinkState = false + } + else + { + $("#scan").addClass("blinkOn") + $("#scan").removeClass("blinkOff") + Scanner.scanBlinkState = true + } + Scanner.scanBlinkTimeout = setTimeout(Scanner.scanBlink, Scanner.scanBlinkRate) + }, + scanGo: function () + { + Player.playNext() + Scanner.scanTimeout = setTimeout(Scanner.scanGo, Scanner.scanRate) + }, + scan: function () + { + if (Scanner.scanMode) + { + d.warn("SCANNER ON") + Scanner.scanMode = false + clearTimeout(Scanner.scanTimeout) + clearTimeout(Scanner.scanBlinkTimeout) + $("#scan").removeClass("blinkOn") + $("#scan").removeClass("blinkOff") + } + else + { + d.warn("SCANNER OFF") + Scanner.scanMode = true + Scanner.scanBlink() + Scanner.scanGo() + } + } + } |
