aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--build/server.js33
-rw-r--r--res/client.js68
-rw-r--r--src/Types.hx30
-rw-r--r--src/VideoList.hx4
-rw-r--r--src/client/JsApi.hx4
-rw-r--r--src/client/Player.hx37
-rw-r--r--src/client/players/Youtube.hx5
-rw-r--r--src/server/Main.hx10
8 files changed, 128 insertions, 63 deletions
diff --git a/build/server.js b/build/server.js
index 301f7d7..c29204f 100644
--- a/build/server.js
+++ b/build/server.js
@@ -456,6 +456,22 @@ json2object_reader_BaseParser.prototype = {
}
return defaultValue;
}
+ ,loadObjectFieldReflect: function(loadJsonFn,field,name,assigned,pos) {
+ try {
+ this.value[name] = loadJsonFn(field.value,field.name);
+ this.mapSet(assigned,name,true);
+ } catch( _g ) {
+ var _g1 = haxe_Exception.caught(_g).unwrap();
+ if(js_Boot.__instanceof(_g1,json2object_InternalError)) {
+ var e = _g1;
+ if(e != json2object_InternalError.ParsingThrow) {
+ throw haxe_Exception.thrown(e);
+ }
+ } else {
+ this.errors.push(json2object_Error.CustomFunctionException(_g1,pos));
+ }
+ }
+ }
,objectSetupAssign: function(assigned,keys,values) {
var _g = 0;
var _g1 = keys.length;
@@ -1332,7 +1348,7 @@ JsonParser_$43.prototype = $extend(json2object_reader_BaseParser.prototype,{
this.value.title = this.loadObjectField(($_=new JsonParser_$44(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"title",assigned,this.value.title,pos);
break;
case "url":
- this.value.url = this.loadObjectField(($_=new JsonParser_$44(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"url",assigned,this.value.url,pos);
+ this.loadObjectFieldReflect(($_=new JsonParser_$44(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"url",assigned,pos);
break;
default:
this.errors.push(json2object_Error.UnknownVariable(field.name,this.putils.convertPosition(field.namePos)));
@@ -2768,6 +2784,11 @@ StringTools.hex = function(n,digits) {
}
return s;
};
+var _$Types_VideoItemTools = function() { };
+_$Types_VideoItemTools.__name__ = true;
+_$Types_VideoItemTools.withUrl = function(item,url) {
+ return { url : url, title : item.title, author : item.author, duration : item.duration, subs : item.subs, isTemp : item.isTemp, isIframe : item.isIframe};
+};
var VideoList = function() {
this.items = [];
this.isOpen = true;
@@ -4913,9 +4934,10 @@ server_Main.prototype = {
}
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);
+ var localIpPort = "" + this.localIp + ":" + this.port;
+ if(item.url.indexOf(localIpPort) != -1) {
+ var newUrl = StringTools.replace(item.url,localIpPort,"" + this.globalIp + ":" + this.port);
+ item = _$Types_VideoItemTools.withUrl(item,newUrl);
}
if(this.videoList.exists(function(i) {
return i.url == item.url;
@@ -4923,6 +4945,7 @@ server_Main.prototype = {
this.serverMessage(client,"videoAlreadyExistsError");
return;
}
+ data.addVideo.item = item;
this.videoList.addItem(item,data.addVideo.atEnd);
this.broadcast(data);
if(this.videoList.items.length == 1) {
@@ -5461,7 +5484,7 @@ server_Main.prototype = {
client.setGroupFlag(ClientGroup.Banned,!isOutdated);
if(isOutdated) {
HxOverrides.remove(this.userList.bans,ban);
- haxe_Log.trace("" + client.name + " ban removed",{ fileName : "src/server/Main.hx", lineNumber : 971, className : "server.Main", methodName : "checkBan"});
+ haxe_Log.trace("" + client.name + " ban removed",{ fileName : "src/server/Main.hx", lineNumber : 973, className : "server.Main", methodName : "checkBan"});
this.sendClientList();
}
break;
diff --git a/res/client.js b/res/client.js
index 48bf37c..35ed305 100644
--- a/res/client.js
+++ b/res/client.js
@@ -481,6 +481,11 @@ StringTools.hex = function(n,digits) {
}
return s;
};
+var _$Types_VideoItemTools = function() { };
+_$Types_VideoItemTools.__name__ = true;
+_$Types_VideoItemTools.withUrl = function(item,url) {
+ return { url : url, title : item.title, author : item.author, duration : item.duration, subs : item.subs, isTemp : item.isTemp, isIframe : item.isIframe};
+};
var VideoList = function() {
this.items = [];
this.pos = 0;
@@ -1186,8 +1191,8 @@ client_JsApi.isLeader = $hx_exports["client"]["JsApi"]["isLeader"] = function()
client_JsApi.forceSyncNextTick = $hx_exports["client"]["JsApi"]["forceSyncNextTick"] = function(flag) {
client_JsApi.main.forceSyncNextTick = flag;
};
-client_JsApi.setVideoSrc = $hx_exports["client"]["JsApi"]["setVideoSrc"] = function(src) {
- client_JsApi.player.changeVideoSrc(src);
+client_JsApi.setVideoSrc = $hx_exports["client"]["JsApi"]["setVideoSrc"] = function(url) {
+ client_JsApi.player.changeVideoSrc(url);
};
client_JsApi.getLocalIp = $hx_exports["client"]["JsApi"]["getLocalIp"] = function() {
return client_JsApi.main.host;
@@ -2412,16 +2417,7 @@ client_Player.prototype = {
return;
}
var item = this.videoList.items[i];
- var currentPlayer = Lambda.find(this.players,function(p) {
- return p.isSupportedLink(item.url);
- });
- if(currentPlayer != null) {
- this.setPlayer(currentPlayer);
- } else if(item.isIframe) {
- this.setPlayer(this.iframePlayer);
- } else {
- this.setPlayer(this.rawPlayer);
- }
+ this.setSupportedPlayer(item.url,item.isIframe);
this.removeActiveLabel(this.videoList.pos);
this.videoList.setPos(i);
this.addActiveLabel(this.videoList.pos);
@@ -2434,11 +2430,20 @@ client_Player.prototype = {
client_JsApi.fireVideoChangeEvents(item);
window.document.querySelector("#currenttitle").textContent = item.title;
}
- ,changeVideoSrc: function(src) {
- if(!this.main.isVideoEnabled) {
- return;
+ ,setSupportedPlayer: function(url,isIframe) {
+ var currentPlayer = Lambda.find(this.players,function(p) {
+ return p.isSupportedLink(url);
+ });
+ if(currentPlayer != null) {
+ this.setPlayer(currentPlayer);
+ } else if(isIframe) {
+ this.setPlayer(this.iframePlayer);
+ } else {
+ this.setPlayer(this.rawPlayer);
}
- if(this.player == null) {
+ }
+ ,changeVideoSrc: function(url) {
+ if(!this.main.isVideoEnabled) {
return;
}
var _this = this.videoList;
@@ -2446,7 +2451,8 @@ client_Player.prototype = {
if(tmp == null) {
return;
}
- this.player.loadVideo({ url : src, title : tmp.title, author : tmp.author, duration : tmp.duration, subs : tmp.subs, isTemp : tmp.isTemp, isIframe : tmp.isIframe});
+ this.setSupportedPlayer(url,tmp.isIframe);
+ this.player.loadVideo(_$Types_VideoItemTools.withUrl(tmp,url));
}
,removeVideo: function() {
var _this = this.videoList;
@@ -2485,6 +2491,19 @@ client_Player.prototype = {
}
,onPause: function() {
var _gthis = this;
+ var _this = this.videoList;
+ var tmp = _this.items[_this.pos];
+ if(tmp == null) {
+ return;
+ }
+ if(this.getTime() >= tmp.duration - 0.01) {
+ return;
+ }
+ if(this.player == this.rawPlayer && this.youtube.isSupportedLink(tmp.url)) {
+ if(this.getTime() >= tmp.duration - 1) {
+ return;
+ }
+ }
if(this.main.hasLeaderOnPauseRequest() && this.videoList.items.length > 0 && this.getTime() > 1 && !this.main.hasLeader()) {
client_JsApi.once("SetLeader",function(event) {
if(event.setLeader.clientName != _gthis.main.personal.name) {
@@ -2810,7 +2829,7 @@ client_Player.prototype = {
}
};
http.onError = function(msg) {
- haxe_Log.trace(msg,{ fileName : "src/client/Player.hx", lineNumber : 482, className : "client.Player", methodName : "skipAd"});
+ haxe_Log.trace(msg,{ fileName : "src/client/Player.hx", lineNumber : 485, className : "client.Player", methodName : "skipAd"});
};
http.request();
}
@@ -3693,7 +3712,11 @@ client_players_Youtube.prototype = {
_gthis.player.onRateChange();
}, onError : function(e) {
haxe_Log.trace("Error " + e.data,{ fileName : "src/client/players/Youtube.hx", lineNumber : 245, className : "client.players.Youtube", methodName : "loadVideo"});
- _gthis.rawSourceFallback(item.url);
+ var tmp = _gthis.player.getCurrentItem();
+ if(tmp == null) {
+ return;
+ }
+ _gthis.rawSourceFallback(tmp.url);
}}});
}
,rawSourceFallback: function(url) {
@@ -3702,12 +3725,11 @@ client_players_Youtube.prototype = {
var info = event.getYoutubeVideoInfo.response;
var tmp = _gthis.getBestStreamFormat(info);
if(tmp == null) {
- haxe_Log.trace("format not found in response info:",{ fileName : "src/client/players/Youtube.hx", lineNumber : 257, className : "client.players.Youtube", methodName : "rawSourceFallback"});
- haxe_Log.trace(info,{ fileName : "src/client/players/Youtube.hx", lineNumber : 258, className : "client.players.Youtube", methodName : "rawSourceFallback"});
+ haxe_Log.trace("format not found in response info:",{ fileName : "src/client/players/Youtube.hx", lineNumber : 258, className : "client.players.Youtube", methodName : "rawSourceFallback"});
+ haxe_Log.trace(info,{ fileName : "src/client/players/Youtube.hx", lineNumber : 259, className : "client.players.Youtube", methodName : "rawSourceFallback"});
return;
}
- _gthis.player.getCurrentItem().url = tmp.url;
- _gthis.player.refresh();
+ _gthis.player.changeVideoSrc(tmp.url);
});
this.main.send({ type : "GetYoutubeVideoInfo", getYoutubeVideoInfo : { url : url}});
}
diff --git a/src/Types.hx b/src/Types.hx
index eeae641..27b2cce 100644
--- a/src/Types.hx
+++ b/src/Types.hx
@@ -98,14 +98,30 @@ typedef Message = {
time:String
}
+@:using(Types.VideoItemTools)
typedef VideoItem = {
- url:String,
- title:String,
- author:String,
- duration:Float,
- ?subs:String,
- isTemp:Bool,
- isIframe:Bool
+ /** Immutable, used as identifier for skipping / removing items **/
+ final url:String;
+ var title:String;
+ var author:String;
+ var duration:Float;
+ var ?subs:String;
+ var isTemp:Bool;
+ var isIframe:Bool;
+}
+
+private class VideoItemTools {
+ public static function withUrl(item:VideoItem, url:String):VideoItem {
+ return {
+ url: url,
+ title: item.title,
+ author: item.author,
+ duration: item.duration,
+ subs: item.subs,
+ isTemp: item.isTemp,
+ isIframe: item.isIframe
+ };
+ }
}
typedef FlashbackItem = {
diff --git a/src/VideoList.hx b/src/VideoList.hx
index 094d2ab..b677060 100644
--- a/src/VideoList.hx
+++ b/src/VideoList.hx
@@ -17,13 +17,13 @@ class VideoList {
return items.length;
}
- public var currentItem(get, never):VideoItem;
+ public var currentItem(get, never):Null<VideoItem>;
inline function get_currentItem():Null<VideoItem> {
return items[pos];
}
- public inline function getItem(i:Int):VideoItem {
+ public inline function getItem(i:Int):Null<VideoItem> {
return items[i];
}
diff --git a/src/client/JsApi.hx b/src/client/JsApi.hx
index 637878d..09e6edb 100644
--- a/src/client/JsApi.hx
+++ b/src/client/JsApi.hx
@@ -104,8 +104,8 @@ class JsApi {
}
@:expose
- public static function setVideoSrc(src:String):Void {
- player.changeVideoSrc(src);
+ public static function setVideoSrc(url:String):Void {
+ player.changeVideoSrc(url);
}
/** Returns current page hostname (domain without protocol) **/
diff --git a/src/client/Player.hx b/src/client/Player.hx
index 06a8f3e..c250a34 100644
--- a/src/client/Player.hx
+++ b/src/client/Player.hx
@@ -89,7 +89,7 @@ class Player {
setItemElementType(el, videoList.getItem(pos).isTemp);
}
- public function getCurrentItem():VideoItem {
+ public function getCurrentItem():Null<VideoItem> {
return videoList.currentItem;
}
@@ -121,10 +121,7 @@ class Player {
public function setVideo(i:Int):Void {
if (!main.isSyncActive) return;
final item = videoList.getItem(i);
- var currentPlayer = players.find(p -> p.isSupportedLink(item.url));
- if (currentPlayer != null) setPlayer(currentPlayer);
- else if (item.isIframe) setPlayer(iframePlayer);
- else setPlayer(rawPlayer);
+ setSupportedPlayer(item.url, item.isIframe);
removeActiveLabel(videoList.pos);
videoList.setPos(i);
@@ -140,19 +137,18 @@ class Player {
ge("#currenttitle").textContent = item.title;
}
- public function changeVideoSrc(src:String):Void {
+ function setSupportedPlayer(url:String, isIframe:Bool):Void {
+ final currentPlayer = players.find(p -> p.isSupportedLink(url));
+ if (currentPlayer != null) setPlayer(currentPlayer);
+ else if (isIframe) setPlayer(iframePlayer);
+ else setPlayer(rawPlayer);
+ }
+
+ public function changeVideoSrc(url:String):Void {
if (!main.isVideoEnabled) return;
- if (player == null) return;
- final item = videoList.currentItem ?? return;
- player.loadVideo({
- url: src,
- title: item.title,
- author: item.author,
- duration: item.duration,
- subs: item.subs,
- isTemp: item.isTemp,
- isIframe: item.isIframe
- });
+ final item:VideoItem = videoList.currentItem ?? return;
+ setSupportedPlayer(url, item.isIframe);
+ player.loadVideo(item.withUrl(url));
}
public function removeVideo():Void {
@@ -191,6 +187,13 @@ class Player {
}
public function onPause():Void {
+ final item = videoList.currentItem ?? return;
+ // do not send pause if video is ended
+ if (getTime() >= item.duration - 0.01) return;
+ // youtube raw fallback has around one second difference from rounded youtube duration
+ if (player == rawPlayer && youtube.isSupportedLink(item.url)) {
+ if (getTime() >= item.duration - 1) return;
+ }
final hasAutoPause = main.hasLeaderOnPauseRequest() && videoList.length > 0
&& getTime() > 1;
if (hasAutoPause && !main.hasLeader()) {
diff --git a/src/client/players/Youtube.hx b/src/client/players/Youtube.hx
index 5308b63..7c98b3f 100644
--- a/src/client/players/Youtube.hx
+++ b/src/client/players/Youtube.hx
@@ -243,6 +243,7 @@ class Youtube implements IPlayer {
onError: e -> {
// TODO message error codes
trace('Error ${e.data}');
+ final item = player.getCurrentItem() ?? return;
rawSourceFallback(item.url);
}
}
@@ -258,9 +259,7 @@ class Youtube implements IPlayer {
trace(info);
return;
};
- final item = player.getCurrentItem();
- item.url = format.url;
- player.refresh();
+ player.changeVideoSrc(format.url);
});
main.send({
type: GetYoutubeVideoInfo,
diff --git a/src/server/Main.hx b/src/server/Main.hx
index e7c38a6..4f09108 100644
--- a/src/server/Main.hx
+++ b/src/server/Main.hx
@@ -612,16 +612,18 @@ class Main {
if (!data.addVideo.atEnd && !checkPermission(client, ChangeOrderPerm)) {
data.addVideo.atEnd = true;
}
- final item = data.addVideo.item;
+ var 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');
+ final localIpPort = '$localIp:$port';
+ if (item.url.contains(localIpPort)) {
+ final newUrl = item.url.replace(localIpPort, '$globalIp:$port');
+ item = item.withUrl(newUrl);
}
if (videoList.exists(i -> i.url == item.url)) {
serverMessage(client, "videoAlreadyExistsError");
return;
}
+ data.addVideo.item = item;
videoList.addItem(item, data.addVideo.atEnd);
broadcast(data);
// Initial timer start if VideoLoaded is not happen
send patches to the email below
yukais@pinapelz.com
include the subject [PATCH repo_name]
pinapelz.com
homepage