Hack YouTube flash player for Google Drive

This commit is contained in:
calzoneman 2015-09-15 23:32:01 -07:00
parent f1c61bddb2
commit bfe36e8150
4 changed files with 249 additions and 5 deletions

View file

@ -18,6 +18,7 @@ var order = [
'hitbox.coffee', 'hitbox.coffee',
'ustream.coffee', 'ustream.coffee',
'imgur.coffee', 'imgur.coffee',
'gdrive-youtube.coffee',
'update.coffee' 'update.coffee'
]; ];

View file

@ -0,0 +1,102 @@
window.GoogleDriveYouTubePlayer = class GoogleDriveYouTubePlayer extends Player
constructor: (data) ->
if not (this instanceof GoogleDriveYouTubePlayer)
return new GoogleDriveYouTubePlayer(data)
@setMediaProperties(data)
@init(data)
init: (data) ->
embed = $('<embed />').attr(
type: 'application/x-shockwave-flash'
src: "https://www.youtube.com/get_player?docid=#{data.id}&ps=docs\
&partnerid=30&enablejsapi=1&cc_load_policy=1"
flashvars: 'autoplay=1&playerapiid=uniquePlayerId'
wmode: 'opaque'
allowscriptaccess: 'always'
)
removeOld(embed)
window.onYouTubePlayerReady = =>
if PLAYER != this
return
@yt = embed[0]
window.gdriveStateChange = @onStateChange.bind(this)
@yt.addEventListener('onStateChange', 'gdriveStateChange')
@onReady()
load: (data) ->
@setMediaProperties(data)
@init(data)
onReady: ->
@yt.ready = true
@setVolume(VOLUME)
@setQuality(USEROPTS.default_quality)
onStateChange: (ev) ->
if PLAYER != this
return
if (ev == YT.PlayerState.PAUSED and not @paused) or
(ev == YT.PlayerState.PLAYING and @paused)
@paused = (ev == YT.PlayerState.PAUSED)
if CLIENT.leader
sendVideoUpdate()
if ev == YT.PlayerState.ENDED and CLIENT.leader
socket.emit('playNext')
play: ->
@paused = false
if @yt and @yt.ready
@yt.playVideo()
pause: ->
@paused = true
if @yt and @yt.ready
@yt.pauseVideo()
seekTo: (time) ->
if @yt and @yt.ready
@yt.seekTo(time, true)
setVolume: (volume) ->
if @yt and @yt.ready
if volume > 0
# If the player is muted, even if the volume is set,
# the player remains muted
@yt.unMute()
@yt.setVolume(volume * 100)
setQuality: (quality) ->
if not @yt or not @yt.ready
return
ytQuality = switch String(quality)
when '240' then 'small'
when '360' then 'medium'
when '480' then 'large'
when '720' then 'hd720'
when '1080' then 'hd1080'
when 'best' then 'highres'
else 'auto'
if ytQuality != 'auto'
@yt.setPlaybackQuality(ytQuality)
getTime: (cb) ->
if @yt and @yt.ready
cb(@yt.getCurrentTime())
else
cb(0)
getVolume: (cb) ->
if @yt and @yt.ready
if @yt.isMuted()
cb(0)
else
cb(@yt.getVolume() / 100)
else
cb(VOLUME)

View file

@ -2,7 +2,7 @@ TYPE_MAP =
yt: YouTubePlayer yt: YouTubePlayer
vi: VimeoPlayer vi: VimeoPlayer
dm: DailymotionPlayer dm: DailymotionPlayer
gd: VideoJSPlayer gd: GoogleDriveYouTubePlayer
gp: VideoJSPlayer gp: VideoJSPlayer
fi: FilePlayer fi: FilePlayer
jw: FilePlayer jw: FilePlayer
@ -16,7 +16,7 @@ TYPE_MAP =
im: ImgurPlayer im: ImgurPlayer
window.loadMediaPlayer = (data) -> window.loadMediaPlayer = (data) ->
if data.meta.direct if data.meta.direct and data.type != 'gd'
try try
window.PLAYER = new VideoJSPlayer(data) window.PLAYER = new VideoJSPlayer(data)
catch e catch e

View file

@ -1,5 +1,5 @@
(function() { (function() {
var CUSTOM_EMBED_WARNING, CustomEmbedPlayer, DEFAULT_ERROR, DailymotionPlayer, EmbedPlayer, FilePlayer, HITBOX_ERROR, HitboxPlayer, ImgurPlayer, LivestreamPlayer, Player, RTMPPlayer, SoundCloudPlayer, TYPE_MAP, TwitchPlayer, USTREAM_ERROR, UstreamPlayer, VideoJSPlayer, VimeoPlayer, YouTubePlayer, codecToMimeType, genParam, sortSources, var CUSTOM_EMBED_WARNING, CustomEmbedPlayer, DEFAULT_ERROR, DailymotionPlayer, EmbedPlayer, FilePlayer, GoogleDriveYouTubePlayer, HITBOX_ERROR, HitboxPlayer, ImgurPlayer, LivestreamPlayer, Player, RTMPPlayer, SoundCloudPlayer, TYPE_MAP, TwitchPlayer, USTREAM_ERROR, UstreamPlayer, VideoJSPlayer, VimeoPlayer, YouTubePlayer, codecToMimeType, genParam, sortSources,
extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }, extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
hasProp = {}.hasOwnProperty; hasProp = {}.hasOwnProperty;
@ -1099,11 +1099,152 @@
})(EmbedPlayer); })(EmbedPlayer);
window.GoogleDriveYouTubePlayer = GoogleDriveYouTubePlayer = (function(superClass) {
extend(GoogleDriveYouTubePlayer, superClass);
function GoogleDriveYouTubePlayer(data) {
if (!(this instanceof GoogleDriveYouTubePlayer)) {
return new GoogleDriveYouTubePlayer(data);
}
this.setMediaProperties(data);
this.init(data);
}
GoogleDriveYouTubePlayer.prototype.init = function(data) {
var embed;
embed = $('<embed />').attr({
type: 'application/x-shockwave-flash',
src: "https://www.youtube.com/get_player?docid=" + data.id + "&ps=docs&partnerid=30&enablejsapi=1&cc_load_policy=1",
flashvars: 'autoplay=1&playerapiid=uniquePlayerId',
wmode: 'opaque',
allowscriptaccess: 'always'
});
removeOld(embed);
return window.onYouTubePlayerReady = (function(_this) {
return function() {
if (PLAYER !== _this) {
return;
}
_this.yt = embed[0];
window.gdriveStateChange = _this.onStateChange.bind(_this);
_this.yt.addEventListener('onStateChange', 'gdriveStateChange');
return _this.onReady();
};
})(this);
};
GoogleDriveYouTubePlayer.prototype.load = function(data) {
this.setMediaProperties(data);
return this.init(data);
};
GoogleDriveYouTubePlayer.prototype.onReady = function() {
this.yt.ready = true;
this.setVolume(VOLUME);
return this.setQuality(USEROPTS.default_quality);
};
GoogleDriveYouTubePlayer.prototype.onStateChange = function(ev) {
if (PLAYER !== this) {
return;
}
if ((ev === YT.PlayerState.PAUSED && !this.paused) || (ev === YT.PlayerState.PLAYING && this.paused)) {
this.paused = ev === YT.PlayerState.PAUSED;
if (CLIENT.leader) {
sendVideoUpdate();
}
}
if (ev === YT.PlayerState.ENDED && CLIENT.leader) {
return socket.emit('playNext');
}
};
GoogleDriveYouTubePlayer.prototype.play = function() {
this.paused = false;
if (this.yt && this.yt.ready) {
return this.yt.playVideo();
}
};
GoogleDriveYouTubePlayer.prototype.pause = function() {
this.paused = true;
if (this.yt && this.yt.ready) {
return this.yt.pauseVideo();
}
};
GoogleDriveYouTubePlayer.prototype.seekTo = function(time) {
if (this.yt && this.yt.ready) {
return this.yt.seekTo(time, true);
}
};
GoogleDriveYouTubePlayer.prototype.setVolume = function(volume) {
if (this.yt && this.yt.ready) {
if (volume > 0) {
this.yt.unMute();
}
return this.yt.setVolume(volume * 100);
}
};
GoogleDriveYouTubePlayer.prototype.setQuality = function(quality) {
var ytQuality;
if (!this.yt || !this.yt.ready) {
return;
}
ytQuality = (function() {
switch (String(quality)) {
case '240':
return 'small';
case '360':
return 'medium';
case '480':
return 'large';
case '720':
return 'hd720';
case '1080':
return 'hd1080';
case 'best':
return 'highres';
default:
return 'auto';
}
})();
if (ytQuality !== 'auto') {
return this.yt.setPlaybackQuality(ytQuality);
}
};
GoogleDriveYouTubePlayer.prototype.getTime = function(cb) {
if (this.yt && this.yt.ready) {
return cb(this.yt.getCurrentTime());
} else {
return cb(0);
}
};
GoogleDriveYouTubePlayer.prototype.getVolume = function(cb) {
if (this.yt && this.yt.ready) {
if (this.yt.isMuted()) {
return cb(0);
} else {
return cb(this.yt.getVolume() / 100);
}
} else {
return cb(VOLUME);
}
};
return GoogleDriveYouTubePlayer;
})(Player);
TYPE_MAP = { TYPE_MAP = {
yt: YouTubePlayer, yt: YouTubePlayer,
vi: VimeoPlayer, vi: VimeoPlayer,
dm: DailymotionPlayer, dm: DailymotionPlayer,
gd: VideoJSPlayer, gd: GoogleDriveYouTubePlayer,
gp: VideoJSPlayer, gp: VideoJSPlayer,
fi: FilePlayer, fi: FilePlayer,
jw: FilePlayer, jw: FilePlayer,
@ -1119,7 +1260,7 @@
window.loadMediaPlayer = function(data) { window.loadMediaPlayer = function(data) {
var e; var e;
if (data.meta.direct) { if (data.meta.direct && data.type !== 'gd') {
try { try {
return window.PLAYER = new VideoJSPlayer(data); return window.PLAYER = new VideoJSPlayer(data);
} catch (_error) { } catch (_error) {