aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--build-client.hxml1
-rw-r--r--build-server.hxml2
-rw-r--r--build/server.js4
-rw-r--r--res/client.js217
-rw-r--r--src/client/IPlayer.hx1
-rw-r--r--src/client/Main.hx18
-rw-r--r--src/client/Player.hx21
-rw-r--r--src/client/players/Raw.hx17
-rw-r--r--src/client/players/Youtube.hx145
-rw-r--r--src/server/Main.hx4
10 files changed, 362 insertions, 68 deletions
diff --git a/build-client.hxml b/build-client.hxml
index f4eca40..7c499bf 100644
--- a/build-client.hxml
+++ b/build-client.hxml
@@ -1,3 +1,4 @@
+-lib youtubeIFramePlayer
-cp src
--main client.Main
-D analyzer-optimize
diff --git a/build-server.hxml b/build-server.hxml
index 220be8e..bcf8611 100644
--- a/build-server.hxml
+++ b/build-server.hxml
@@ -1,5 +1,7 @@
-lib hxnodejs
-lib hxnodejs-ws
+# Client libs for completion
+-lib youtubeIFramePlayer
-cp src
--main server.Main
-D analyzer-optimize
diff --git a/build/server.js b/build/server.js
index c90a298..0a90ca2 100644
--- a/build/server.js
+++ b/build/server.js
@@ -867,11 +867,11 @@ server_Main.prototype = {
switch(data.type) {
case "AddVideo":
var item = data.addVideo.item;
+ item.author = client.name;
var local = "" + this.localIp + ":" + this.port;
if(item.url.indexOf(local) != -1) {
item.url = StringTools.replace(item.url,local,"" + this.globalIp + ":" + this.port);
}
- item.author = client.name;
if(Lambda.exists(this.videoList,function(i) {
return i.url == item.url;
})) {
@@ -952,6 +952,7 @@ server_Main.prototype = {
if((client.group & 2) == 0) {
return;
}
+ this.videoTimer.setTime(data.pause.time);
this.videoTimer.pause();
this.broadcast(data);
break;
@@ -962,6 +963,7 @@ server_Main.prototype = {
if((client.group & 2) == 0) {
return;
}
+ this.videoTimer.setTime(data.play.time);
this.videoTimer.play();
this.broadcast(data);
break;
diff --git a/res/client.js b/res/client.js
index 3367bcf..14e7ca4 100644
--- a/res/client.js
+++ b/res/client.js
@@ -779,15 +779,14 @@ client_Main.prototype = {
if(!StringTools.startsWith(url,"http")) {
url = "" + protocol + "//" + url;
}
- var pos = url.lastIndexOf("/") + 1;
- var name = HxOverrides.substr(url,pos,null);
+ var name = HxOverrides.substr(url,url.lastIndexOf("/") + 1,null);
var matchName = new EReg("^(.+)\\.","");
if(matchName.match(name)) {
name = matchName.matched(1);
} else {
name = Lang.get("rawVideo");
}
- this.getRemoteVideoDuration(url,function(duration) {
+ this.player.getRemoteDuration(url,function(duration) {
if(duration == 0) {
var tmp = Lang.get("addVideoError");
_gthis.serverMessage(4,tmp);
@@ -822,31 +821,11 @@ client_Main.prototype = {
}
return StringTools.replace(url,this.globalIp,this.host);
}
- ,getRemoteVideoDuration: function(src,callback) {
- var player = window.document.querySelector("#ytapiplayer");
- var video = window.document.createElement("video");
- video.src = src;
- video.onerror = function(e) {
- if(player.contains(video)) {
- player.removeChild(video);
- }
- callback(0);
- return;
- };
- video.onloadedmetadata = function() {
- if(player.contains(video)) {
- player.removeChild(video);
- }
- callback(video.duration);
- return;
- };
- client_Utils.prepend(player,video);
- }
,onMessage: function(e) {
var data = JSON.parse(e.data);
var t = data.type;
var t1 = t.charAt(0).toLowerCase() + HxOverrides.substr(t,1,null);
- haxe_Log.trace("Event: " + data.type,{ fileName : "src/client/Main.hx", lineNumber : 228, className : "client.Main", methodName : "onMessage", customParams : [data[t1]]});
+ haxe_Log.trace("Event: " + data.type,{ fileName : "src/client/Main.hx", lineNumber : 212, className : "client.Main", methodName : "onMessage", customParams : [data[t1]]});
switch(data.type) {
case "AddVideo":
this.player.addVideoItem(data.addVideo.item,data.addVideo.atEnd);
@@ -1019,9 +998,8 @@ client_Main.prototype = {
}
var smilesWrap = window.document.querySelector("#smileswrap");
smilesWrap.onclick = function(e) {
- var el = e.target;
var form = window.document.querySelector("#chatline");
- form.value += " " + el.title;
+ form.value += " " + e.target.title;
form.focus();
return;
};
@@ -1224,7 +1202,6 @@ client_MobileView.init = function() {
};
};
var client_Player = function(main) {
- this.matchYoutube = new EReg("v=([A-z0-9_-]+)","");
this.skipSetTime = false;
this.isLoaded = false;
this.itemPos = 0;
@@ -1271,21 +1248,18 @@ client_Player.prototype = {
,setPlayer: function(player) {
this.player = player;
}
- ,isYoutube: function(url) {
- if(url.indexOf("youtube.com/") == -1) {
- return false;
- }
- if(url.indexOf("youtu.be/") == -1) {
- return false;
- }
- if(!this.matchYoutube.match(url)) {
- return false;
+ ,getRemoteDuration: function(url,callback) {
+ if(client_players_Youtube.isYoutube(url)) {
+ new client_players_Youtube(this.main,this).getRemoteDuration(url,callback);
+ } else {
+ new client_players_Raw(this.main,this).getRemoteDuration(url,callback);
}
- return true;
}
,setVideo: function(i) {
var item = this.items[i];
- if(!this.isYoutube(item.url)) {
+ if(client_players_Youtube.isYoutube(item.url)) {
+ this.setPlayer(new client_players_Youtube(this.main,this));
+ } else {
this.setPlayer(new client_players_Raw(this.main,this));
}
var childs = this.videoItemsEl.children;
@@ -1577,7 +1551,27 @@ var client_players_Raw = function(main,player) {
};
client_players_Raw.__name__ = true;
client_players_Raw.prototype = {
- loadVideo: function(item) {
+ getRemoteDuration: function(src,callback) {
+ var _gthis = this;
+ var video = window.document.createElement("video");
+ video.src = src;
+ video.onerror = function(e) {
+ if(_gthis.playerEl.contains(video)) {
+ _gthis.playerEl.removeChild(video);
+ }
+ callback(0);
+ return;
+ };
+ video.onloadedmetadata = function() {
+ if(_gthis.playerEl.contains(video)) {
+ _gthis.playerEl.removeChild(video);
+ }
+ callback(video.duration);
+ return;
+ };
+ client_Utils.prepend(this.playerEl,video);
+ }
+ ,loadVideo: function(item) {
var _gthis = this;
this.video = window.document.createElement("video");
this.video.id = "videoplayer";
@@ -1635,6 +1629,133 @@ client_players_Raw.prototype = {
this.video.currentTime = time;
}
};
+var client_players_Youtube = function(main,player) {
+ this.isLoaded = false;
+ this.playerEl = window.document.querySelector("#ytapiplayer");
+ this.main = main;
+ this.player = player;
+};
+client_players_Youtube.__name__ = true;
+client_players_Youtube.isYoutube = function(url) {
+ if(url.indexOf("youtu.be/") != -1) {
+ return client_players_Youtube.matchShort.match(url);
+ }
+ if(url.indexOf("youtube.com/embed/") != -1) {
+ return client_players_Youtube.matchEmbed.match(url);
+ }
+ if(url.indexOf("youtube.com/") == -1) {
+ return false;
+ }
+ return client_players_Youtube.matchId.match(url);
+};
+client_players_Youtube.prototype = {
+ extractVideoId: function(url) {
+ if(url.indexOf("youtu.be/") != -1) {
+ client_players_Youtube.matchShort.match(url);
+ return client_players_Youtube.matchShort.matched(1);
+ }
+ if(url.indexOf("youtube.com/embed/") != -1) {
+ client_players_Youtube.matchEmbed.match(url);
+ return client_players_Youtube.matchEmbed.matched(1);
+ }
+ client_players_Youtube.matchId.match(url);
+ return client_players_Youtube.matchId.matched(1);
+ }
+ ,getRemoteDuration: function(url,callback) {
+ var _gthis = this;
+ if(!js_youtube_Youtube.isLoadedAPI) {
+ js_youtube_Youtube.init(function() {
+ _gthis.getRemoteDuration(url,callback);
+ return;
+ });
+ return;
+ }
+ var video = window.document.createElement("div");
+ video.id = "temp-videoplayer";
+ client_Utils.prepend(this.playerEl,video);
+ this.youtube = new YT.Player(video.id,{ videoId : this.extractVideoId(url), playerVars : { modestbranding : 1, rel : 0, showinfo : 0}, events : { onReady : function(e) {
+ if(_gthis.playerEl.contains(video)) {
+ _gthis.playerEl.removeChild(video);
+ }
+ var tmp = _gthis.youtube.getDuration();
+ callback(tmp);
+ return;
+ }, onError : function(e1) {
+ haxe_Log.trace("Error " + e1.data,{ fileName : "src/client/players/Youtube.hx", lineNumber : 74, className : "client.players.Youtube", methodName : "getRemoteDuration"});
+ if(_gthis.playerEl.contains(video)) {
+ _gthis.playerEl.removeChild(video);
+ }
+ callback(0);
+ return;
+ }}});
+ }
+ ,loadVideo: function(item) {
+ var _gthis = this;
+ if(!js_youtube_Youtube.isLoadedAPI) {
+ js_youtube_Youtube.init(function() {
+ _gthis.loadVideo(item);
+ return;
+ });
+ return;
+ }
+ this.video = window.document.createElement("div");
+ this.video.id = "videoplayer";
+ this.playerEl.appendChild(this.video);
+ this.youtube = new YT.Player(this.video.id,{ videoId : this.extractVideoId(item.url), playerVars : { autoplay : 1, modestbranding : 1, rel : 0, showinfo : 0}, events : { onStateChange : function(e) {
+ switch(e.data) {
+ case -1:
+ _gthis.isLoaded = true;
+ _gthis.player.onCanBePlayed();
+ break;
+ case 0:
+ break;
+ case 1:
+ _gthis.player.onPlay();
+ break;
+ case 2:
+ _gthis.player.onPause();
+ break;
+ case 3:
+ _gthis.player.onSetTime();
+ break;
+ case 5:
+ break;
+ }
+ return;
+ }}});
+ }
+ ,removeVideo: function() {
+ if(this.video == null) {
+ return;
+ }
+ this.playerEl.removeChild(this.video);
+ this.video = null;
+ }
+ ,play: function() {
+ if(!this.isLoaded) {
+ return;
+ }
+ this.youtube.playVideo();
+ }
+ ,pause: function() {
+ if(!this.isLoaded) {
+ return;
+ }
+ this.youtube.pauseVideo();
+ }
+ ,getTime: function() {
+ if(!this.isLoaded) {
+ return 0;
+ }
+ return this.youtube.getCurrentTime();
+ }
+ ,setTime: function(time) {
+ if(!this.isLoaded) {
+ return;
+ }
+ this.youtube.seekTo(time,true);
+ }
+};
var haxe_Log = function() { };
haxe_Log.__name__ = true;
haxe_Log.formatOutput = function(v,infos) {
@@ -2063,6 +2184,20 @@ js_Browser.createXMLHttpRequest = function() {
}
throw new js__$Boot_HaxeError("Unable to create XMLHttpRequest object.");
};
+var js_youtube_Youtube = function() { };
+js_youtube_Youtube.__name__ = true;
+js_youtube_Youtube.init = function(onAPIReady) {
+ var firstElement = window.document.getElementsByTagName("script")[0];
+ var script = window.document.createElement("script");
+ script.src = "https://www.youtube.com/player_api";
+ firstElement.parentNode.insertBefore(script,firstElement);
+ window.onYouTubePlayerAPIReady = function() {
+ js_youtube_Youtube.isLoadedAPI = true;
+ if(onAPIReady != null) {
+ onAPIReady();
+ }
+ };
+};
function $getIterator(o) { if( o instanceof Array ) return HxOverrides.iter(o); else return o.iterator(); }
function $bind(o,m) { if( m == null ) return null; if( m.__id__ == null ) m.__id__ = $global.$haxeUID++; var f; if( o.hx__closures__ == null ) o.hx__closures__ = {}; else f = o.hx__closures__[m.__id__]; if( f == null ) { f = m.bind(o); o.hx__closures__[m.__id__] = f; } return f; }
$global.$haxeUID |= 0;
@@ -2079,5 +2214,9 @@ Lang.langs = new haxe_ds_StringMap();
Lang.lang = HxOverrides.substr(window.navigator.language,0,2).toLowerCase();
client_Buttons.personalHistory = [];
client_Buttons.personalHistoryId = -1;
+client_players_Youtube.matchId = new EReg("v=([A-z0-9_-]+)","");
+client_players_Youtube.matchShort = new EReg("youtu.be/([A-z0-9_-]+)","");
+client_players_Youtube.matchEmbed = new EReg("embed/([A-z0-9_-]+)","");
+js_youtube_Youtube.isLoadedAPI = false;
client_Main.main();
})(typeof window != "undefined" ? window : typeof global != "undefined" ? global : typeof self != "undefined" ? self : this);
diff --git a/src/client/IPlayer.hx b/src/client/IPlayer.hx
index 9f224a8..a20b22b 100644
--- a/src/client/IPlayer.hx
+++ b/src/client/IPlayer.hx
@@ -3,6 +3,7 @@ package client;
import Types.VideoItem;
interface IPlayer {
+ function getRemoteDuration(url:String, callback:(duration:Float)->Void):Void;
function loadVideo(item:VideoItem):Void;
function removeVideo():Void;
function play():Void;
diff --git a/src/client/Main.hx b/src/client/Main.hx
index 1804ca1..d3271e9 100644
--- a/src/client/Main.hx
+++ b/src/client/Main.hx
@@ -161,7 +161,7 @@ class Main {
if (matchName.match(name)) name = matchName.matched(1);
else name = Lang.get("rawVideo");
- getRemoteVideoDuration(url, (duration:Float) -> {
+ player.getRemoteDuration(url, (duration:Float) -> {
if (duration == 0) {
serverMessage(4, Lang.get("addVideoError"));
return;
@@ -205,22 +205,6 @@ class Main {
return url.replace(globalIp, host);
}
- function getRemoteVideoDuration(src:String, callback:(duration:Float)->Void):Void {
- final player:Element = ge("#ytapiplayer");
- final video = document.createVideoElement();
- video.src = src;
- // TODO catch errors on AddVideo and getRemoteVideoDuration
- video.onerror = e -> {
- if (player.contains(video)) player.removeChild(video);
- callback(0);
- }
- video.onloadedmetadata = () -> {
- if (player.contains(video)) player.removeChild(video);
- callback(video.duration);
- }
- Utils.prepend(player, video);
- }
-
function onMessage(e):Void {
final data:WsEvent = Json.parse(e.data);
final t:String = cast data.type;
diff --git a/src/client/Player.hx b/src/client/Player.hx
index 3941bdb..7bd2f4e 100644
--- a/src/client/Player.hx
+++ b/src/client/Player.hx
@@ -4,9 +4,9 @@ import js.html.Element;
import js.Browser.document;
import client.Main.ge;
import client.players.Raw;
+import client.players.Youtube;
import Types.VideoItem;
using StringTools;
-using Lambda;
class Player {
@@ -19,7 +19,6 @@ class Player {
var itemPos = 0;
var isLoaded = false;
var skipSetTime = false;
- final matchYoutube = ~/v=([A-z0-9_-]+)/;
public function new(main:Main):Void {
this.main = main;
@@ -81,17 +80,21 @@ class Player {
this.player = player;
}
- function isYoutube(url:String):Bool {
- if (!url.contains("youtube.com/")) return false;
- if (!url.contains("youtu.be/")) return false;
- if (!matchYoutube.match(url)) return false;
- return true;
+ public function getRemoteDuration(url:String, callback:(duration:Float)->Void):Void {
+ if (Youtube.isYoutube(url)) {
+ new Youtube(main, this).getRemoteDuration(url, callback);
+ } else {
+ new Raw(main, this).getRemoteDuration(url, callback);
+ }
}
public function setVideo(i:Int):Void {
final item = items[i];
- if (isYoutube(item.url)) {} // setPlayer(new Youtube(main, this));
- else setPlayer(new Raw(main, this));
+ if (Youtube.isYoutube(item.url)) {
+ setPlayer(new Youtube(main, this));
+ } else {
+ setPlayer(new Raw(main, this));
+ }
final childs = videoItemsEl.children;
if (childs[itemPos] != null) {
diff --git a/src/client/players/Raw.hx b/src/client/players/Raw.hx
index 41b421c..1e5d245 100644
--- a/src/client/players/Raw.hx
+++ b/src/client/players/Raw.hx
@@ -11,14 +11,29 @@ class Raw implements IPlayer {
final main:Main;
final player:Player;
- var video:VideoElement;
final playerEl:Element = ge("#ytapiplayer");
+ var video:VideoElement;
public function new(main:Main, player:Player) {
this.main = main;
this.player = player;
}
+ public function getRemoteDuration(src:String, callback:(duration:Float)->Void):Void {
+ final video = document.createVideoElement();
+ video.src = src;
+ // TODO catch errors on AddVideo and getRemoteVideoDuration
+ video.onerror = e -> {
+ if (playerEl.contains(video)) playerEl.removeChild(video);
+ callback(0);
+ }
+ video.onloadedmetadata = () -> {
+ if (playerEl.contains(video)) playerEl.removeChild(video);
+ callback(video.duration);
+ }
+ Utils.prepend(playerEl, video);
+ }
+
public function loadVideo(item:VideoItem):Void {
video = document.createVideoElement();
video.id = "videoplayer";
diff --git a/src/client/players/Youtube.hx b/src/client/players/Youtube.hx
new file mode 100644
index 0000000..cba3fc4
--- /dev/null
+++ b/src/client/players/Youtube.hx
@@ -0,0 +1,145 @@
+package client.players;
+
+import js.html.Element;
+import js.Browser.document;
+import client.Main.ge;
+import js.youtube.Youtube as YtInit;
+import js.youtube.YoutubePlayer;
+import Types.VideoItem;
+using StringTools;
+
+class Youtube implements IPlayer {
+
+ static final matchId = ~/v=([A-z0-9_-]+)/;
+ static final matchShort = ~/youtu.be\/([A-z0-9_-]+)/;
+ static final matchEmbed = ~/embed\/([A-z0-9_-]+)/;
+ final main:Main;
+ final player:Player;
+ final playerEl:Element = ge("#ytapiplayer");
+ var video:Element;
+ var youtube:YoutubePlayer;
+ var isLoaded = false;
+
+ public function new(main:Main, player:Player) {
+ this.main = main;
+ this.player = player;
+ }
+
+ public static function isYoutube(url:String):Bool {
+ if (url.contains("youtu.be/")) {
+ return matchShort.match(url);
+ }
+ if (url.contains("youtube.com/embed/")) {
+ return matchEmbed.match(url);
+ }
+ if (!url.contains("youtube.com/")) return false;
+ return matchId.match(url);
+ }
+
+ function extractVideoId(url:String):String {
+ if (url.contains("youtu.be/")) {
+ matchShort.match(url);
+ return matchShort.matched(1);
+ }
+ if (url.contains("youtube.com/embed/")) {
+ matchEmbed.match(url);
+ return matchEmbed.matched(1);
+ }
+ matchId.match(url);
+ return matchId.matched(1);
+ }
+
+ public function getRemoteDuration(url:String, callback:(duration:Float)->Void):Void {
+ if (!YtInit.isLoadedAPI) {
+ YtInit.init(() -> getRemoteDuration(url, callback));
+ return;
+ }
+ final video = document.createDivElement();
+ video.id = "temp-videoplayer";
+ Utils.prepend(playerEl, video);
+ youtube = new YoutubePlayer(video.id, {
+ videoId: extractVideoId(url),
+ playerVars: {
+ modestbranding: 1,
+ rel: 0,
+ showinfo: 0
+ },
+ events: {
+ onReady: e -> {
+ if (playerEl.contains(video)) playerEl.removeChild(video);
+ callback(youtube.getDuration());
+ },
+ onError: e -> {
+ trace('Error ${e.data}');
+ if (playerEl.contains(video)) playerEl.removeChild(video);
+ callback(0);
+ }
+ }
+ });
+ }
+
+ public function loadVideo(item:VideoItem):Void {
+ if (!YtInit.isLoadedAPI) {
+ YtInit.init(() -> loadVideo(item));
+ return;
+ }
+ video = document.createDivElement();
+ video.id = "videoplayer";
+ playerEl.appendChild(video);
+
+ youtube = new YoutubePlayer(video.id, {
+ videoId: extractVideoId(item.url),
+ playerVars: {
+ autoplay: 1,
+ modestbranding: 1,
+ rel: 0,
+ showinfo: 0,
+ },
+ events: {
+ // onReady: e -> player.onCanBePlayed(),
+ onStateChange: e -> {
+ switch (e.data) {
+ case UNSTARTED:
+ isLoaded = true;
+ player.onCanBePlayed();
+ case ENDED:
+ case PLAYING:
+ player.onPlay();
+ case PAUSED:
+ player.onPause();
+ case BUFFERING:
+ player.onSetTime();
+ case CUED:
+ }
+ }
+ }
+ });
+ }
+
+ public function removeVideo():Void {
+ if (video == null) return;
+ playerEl.removeChild(video);
+ video = null;
+ }
+
+ public function play():Void {
+ if (!isLoaded) return;
+ youtube.playVideo();
+ }
+
+ public function pause():Void {
+ if (!isLoaded) return;
+ youtube.pauseVideo();
+ }
+
+ public function getTime():Float {
+ if (!isLoaded) return 0;
+ return youtube.getCurrentTime();
+ }
+
+ public function setTime(time:Float):Void {
+ if (!isLoaded) return;
+ youtube.seekTo((time : Any), true);
+ }
+
+}
diff --git a/src/server/Main.hx b/src/server/Main.hx
index e5b50c8..aaf9277 100644
--- a/src/server/Main.hx
+++ b/src/server/Main.hx
@@ -248,11 +248,11 @@ class Main {
case AddVideo:
final item = data.addVideo.item;
+ item.author = client.name;
final local = '$localIp:$port';
if (item.url.contains(local)) {
item.url = item.url.replace(local, '$globalIp:$port');
}
- item.author = client.name;
if (videoList.exists(i -> i.url == item.url)) {
// TODO send server message
return;
@@ -290,12 +290,14 @@ class Main {
case Pause:
if (videoList.length == 0) return;
if (!client.isLeader) return;
+ videoTimer.setTime(data.pause.time);
videoTimer.pause();
broadcast(data);
case Play:
if (videoList.length == 0) return;
if (!client.isLeader) return;
+ videoTimer.setTime(data.play.time);
videoTimer.play();
broadcast(data);
send patches to the email below
yukais@pinapelz.com
include the subject [PATCH repo_name]
pinapelz.com
homepage