// ==UserScript==
// @name VLC Station
// @namespace VLCStation
// @description Makes play buttons in Video Station generate VLC playlists rather than playing videos in the browser.
// @include /^https?://[^/]*/.*[?&]launchApp=SYNO.SDS.VideoStation.AppInstance(?=[&#]|$).*$/
// @version 7
// @grant GM_registerMenuCommand
// ==/UserScript==
(function()
{
'use strict';
var DSRequest;
var FileServer;
var Playlist;
var Problem;
var Thumbnail;
var VLCStation;
var Platform;
Platform =
{
LINUX: navigator.platform.startsWith("Linux ")
};
Problem =
{
MESSAGE__HEADING: "VLC Station Error",
MESSAGE_INVALID_REQUEST: "An invalid request was made.",
MESSAGE_NO_CONTACT: "Unable to contact the DiskStation.",
MESSAGE_UNEXPECTED_RESPONSE_FORMAT: "Unexpected response structure.",
MESSAGE_UNKNOWN_THUMBNAIL_TYPE: "Unknown thumbnail type.",
MESSAGE_UNKNOWN_ITEM_FORMAT: "Unknown item format.",
EXTRA_STATUS_CODE: "Status code",
EXTRA_ERROR_CODE: "Error code",
EXTRA_FIELD: "Field",
EXTRA_PATH_ELEMENT: "Path element",
EXTRA_INDEX: "Index",
EXTRA_TYPE: "Type",
PREFIX_EXTRA_SYNOLOGY: "Synology ",
SEPARATOR_EXTRA: "\n",
SEPARATOR_EXTRA_ITEM: ": ",
SEPARATOR_SECTION: "\n\n",
report: function(message, extra)
{
var index;
var buffer;
buffer = [];
if(extra)
for(index in extra)
buffer.push(index + Problem.SEPARATOR_EXTRA_ITEM + extra[index]);
alert([Problem.MESSAGE__HEADING, message, buffer.join(Problem.SEPARATOR_EXTRA)].join(Problem.SEPARATOR_SECTION) + Problem.SEPARATOR_SECTION);
return;
}
};
(Thumbnail = function(element)
{
this._element = element;
return;
}).prototype =
{
_element: null,
_thread: null,
onload: null,
id: null,
token: null,
type: null,
_getImageURL: function()
{
return(this._element.style.backgroundImage || this._element.getAttribute(Thumbnail.ATTRIBUTE_URL));
},
_poll: function()
{
var url;
url = this._getImageURL();
if(!this._element.classList.contains(Thumbnail.CLASS_LOADING) && url)
{
clearInterval(this._thread);
this._parse(url);
}
return;
},
_parse: function(url)
{
var index;
var item;
if(url.endsWith(Thumbnail.SUFFIX_CSS))
url = url.substr(0, url.length - Thumbnail.SUFFIX_CSS.length);
if(url.indexOf(Thumbnail.SEPARATOR_PARAMETER_LIST) !== -1)
{
url = url.substr(url.indexOf(Thumbnail.SEPARATOR_PARAMETER_LIST) + Thumbnail.SEPARATOR_PARAMETER_LIST.length).split(Thumbnail.SEPARATOR_PARAMETER);
index = url.length;
while(index--)
{
item = url[index].split(Thumbnail.SEPARATOR_VALUE);
this[Thumbnail.PARAMETER[item[0]] || Thumbnail.PARAMETER_DEFAULT] = item[1];
}
}
else
Problem.report(Problem.MESSAGE_UNKNOWN_ITEM_FORMAT);
if(this.onload)
this.onload(this);
return;
},
load: function()
{
var url;
url = this._getImageURL();
if(!url)
this._thread = setInterval(this._poll.bind(this), Thumbnail.RATE_POLL);
else
this._parse(url);
return;
}
};
Thumbnail.PARAMETER =
{
id: "id",
SynoToken: "token",
type: "type"
};
Thumbnail.TYPE =
{
tvshow_episode:
{
api: "SYNO.VideoStation2.TVShowEpisode",
infoContainer: "episode",
preferredTitle: "tagline",
episodic: true
},
movie:
{
api: "SYNO.VideoStation2.Movie",
infoContainer: "movie"
},
home_video:
{
api: "SYNO.VideoStation2.HomeVideo",
infoContainer: "video"
}
};
Thumbnail.SEPARATOR_PARAMETER_LIST = "?";
Thumbnail.SEPARATOR_PARAMETER = "&";
Thumbnail.SEPARATOR_VALUE = "=";
Thumbnail.SUFFIX_CSS = "\")";
Thumbnail.PARAMETER_DEFAULT = "last";
Thumbnail.ATTRIBUTE_URL = "url";
Thumbnail.CLASS_LOADING = "loading";
Thumbnail.RATE_POLL = 50;
(DSRequest = function(token)
{
this._request = new XMLHttpRequest();
this._request.onreadystatechange = this._handleStateChange.bind(this);
this._request.open(DSRequest.TYPE_POST, location.origin + DSRequest.URL_ENTRY_POINT);
this._request.setRequestHeader(DSRequest.HEADER_TOKEN, token);
this._parameter = {};
return;
}).prototype =
{
_request: null,
_parameter: null,
onsuccess: null,
response: null,
_handleStateChange: function()
{
var extra;
var index;
if(this._request.readyState === XMLHttpRequest.DONE)
{
if(this._request.status === DSRequest.STATUS_OK)
{
this.response = JSON.parse(this._request.responseText);
if(this.response.success)
{
if(this.onsuccess)
this.onsuccess(this);
}
else
{
extra = this.response.error.errors;
for(index in extra)
{
extra[Problem.PREFIX_EXTRA_SYNOLOGY + index] = extra[index];
delete extra[index];
}
extra[Problem.EXTRA_ERROR_CODE] = this.response.error.code;
Problem.report(Problem.MESSAGE_INVALID_REQUEST, extra);
}
}
else
{
extra = {};
extra[Problem.EXTRA_STATUS_CODE] = this._request.status;
Problem.report(Problem.MESSAGE_NO_CONTACT, extra);
}
}
return;
},
setParameter: function(name, value)
{
this._parameter[name] = value;
return;
},
send: function()
{
var index;
var buffer;
buffer = [];
for(index in this._parameter)
buffer.push(encodeURIComponent(index) + DSRequest.SEPARATOR_VALUE + encodeURIComponent(this._parameter[index]));
this._request.send(buffer.join(DSRequest.SEPARATOR_PARAMETER));
return;
}
};
DSRequest.HEADER_TOKEN = "X-SYNO-TOKEN";
DSRequest.URL_ENTRY_POINT = "/webapi/entry.cgi";
DSRequest.TYPE_POST = "POST";
DSRequest.SEPARATOR_VALUE = "=";
DSRequest.SEPARATOR_PARAMETER = "&";
DSRequest.PARAMETER_ID = "id";
DSRequest.PARAMETER_ADDITIONAL = "additional";
DSRequest.PARAMETER_API = "api";
DSRequest.PARAMETER_METHOD = "method";
DSRequest.PARAMETER_VERSION = "version";
DSRequest.METHOD_GET_INFO = "getinfo";
DSRequest.ADDITION_FILE = "file";
DSRequest.STATUS_OK = 200;
DSRequest.VERSION_API = "1";
(Playlist = function()
{
this.list = [];
return;
}).prototype =
{
list: null,
add: function(filename, title)
{
this.list.push({filename: filename, title: title});
return;
},
addVideoEntry: function(entry, type)
{
var index;
var list;
var listLength;
list = entry.additional.file.concat();
list.sort(Playlist._compareSharepath);
listLength = list.length;
if(listLength > 1)
for(index = 0; index < listLength; index++)
this.add(Playlist._getVideoEntryFilename(list[index]), Playlist._getVideoEntryTitle(entry, type) + Playlist.PREFIX_TITLE_PART + (index + 1) + Playlist.SEPARATOR_TITLE_PART + listLength + Playlist.SUFFIX_TITLE_PART);
else
this.add(Playlist._getVideoEntryFilename(list[0]), Playlist._getVideoEntryTitle(entry, type));
return;
},
addVideoEntryList: function(list, type)
{
var index;
var listLength;
listLength = list.length;
for(index = 0; index < listLength; index++)
this.addVideoEntry(list[index], type);
return;
},
getPLSText: function()
{
var result;
var listLength;
var index;
listLength = this.list.length;
result = [Playlist.HEADER_PLS, Playlist._getPLSRecord(Playlist.FIELD_PLS_ENTRY_COUNT, listLength)];
for(index = 0; index < listLength; index++)
{
result.push(Playlist._getPLSRecord(Playlist.PREIFX_PLS_FIELD_TITLE + (index + 1), this.list[index].title));
result.push(Playlist._getPLSRecord(Playlist.PREIFX_PLS_FIELD_FILE + (index + 1), this.list[index].filename));
}
return(result.join(Playlist.SEPARATOR_PLS_RECORD) + Playlist.SEPARATOR_PLS_RECORD);
}
};
Playlist._compareSharepath = function(alpha, beta)
{
alpha = alpha.sharepath.toUpperCase();
beta = beta.sharepath.toUpperCase();
return(alpha < beta ? -1 : (alpha > beta ? 1 : 0));
};
Playlist._getPLSRecord = function(name, value)
{
return(name + Playlist.SEPARATOR_PLS_VALUE + value);
};
Playlist._getVideoEntryTitle = function(entry, type)
{
var title;
if(type.preferredTitle && entry[type.preferredTitle])
title = entry[type.preferredTitle];
else
if(type.episodic)
title = Playlist.PREFIX_TITLE_EPISODE + entry.episode;
else
title = entry.title;
return(title);
};
Playlist._getVideoEntryFilename = Platform.LINUX
?
function(file)
{
return(Playlist.PREFIX_PATH_LINUX + location.hostname + file.sharepath);
}
:
function(file)
{
return(Playlist.PREFIX_PATH_WINDOWS + (location.hostname + file.sharepath).replace(Playlist.PATTERN_PATH_SEPARATOR, Playlist.SEPARATOR_PATH));
};
Playlist.HEADER_PLS = "[playlist]";
Playlist.FIELD_PLS_ENTRY_COUNT = "NumberOfEntries";
Playlist.PREFIX_TITLE_PART = " (";
Playlist.PREFIX_TITLE_EPISODE = "Episode ";
Playlist.PREFIX_PATH_WINDOWS = "\\\\";
Playlist.PREFIX_PATH_LINUX = "smb://";
Playlist.PREIFX_PLS_FIELD_TITLE = "Title";
Playlist.PREIFX_PLS_FIELD_FILE = "File";
Playlist.SEPARATOR_TITLE_PART = " of ";
Playlist.SEPARATOR_PATH = "\\";
Playlist.SEPARATOR_PLS_RECORD = "\n";
Playlist.SEPARATOR_PLS_VALUE = "=";
Playlist.SUFFIX_TITLE_PART = ")";
Playlist.PATTERN_PATH_SEPARATOR = new RegExp("/", "g");
FileServer =
{
FILENAME_DEFAULT: {},
ELEMENT_ANCHOR: "a",
ELEMENT_IFRAME: "iframe",
ATTRIBUTE_DOWNLOAD: "download",
ATTRIBUTE_HREF: "href",
ATTRIBUTE_SRC: "src",
STYLE_VALUE_NONE: "none",
DELAY_SAFE_REMOVAL: 1000,
PROTOCOL_DATA: "data:",
SEPARATOR_MIME: ";",
SEPARATOR_PRAGMA: ",",
PRAGMA_UTF8: "charset=utf-8",
PRAGMA_BASE64: "base64",
CONTENT_COMPANION: "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",
MIME_PLAYLIST: "application/videolan",
MIME_EXECUTABLE: "application/octet-stream",
FILENAME_COMPANION: "vlc-full.exe",
serve: function(filename, content, pragma, mime)
{
var element;
var url;
if(window.chrome || filename)
{
element = document.createElement(FileServer.ELEMENT_ANCHOR);
element.style.display = FileServer.STYLE_VALUE_NONE;
element.setAttribute(FileServer.ATTRIBUTE_HREF, FileServer._getDataURL(content, pragma, mime));
element.setAttribute(FileServer.ATTRIBUTE_DOWNLOAD, filename || FileServer.FILENAME_DEFAULT[mime]);
document.body.appendChild(element);
element.click();
document.body.removeChild(element);
}
else
{
filename = FileServer.FILENAME_DEFAULT[mime];
element = document.createElement(FileServer.ELEMENT_IFRAME);
element.style.display = FileServer.STYLE_VALUE_NONE;
document.body.appendChild(element);
if(filename && window.File && window.URL)
{
url = URL.createObjectURL(new File([content], filename, {type: mime}));
element.setAttribute(FileServer.ATTRIBUTE_SRC, url);
}
else
element.setAttribute(FileServer.ATTRIBUTE_SRC, FileServer._getDataURL(content, pragma, mime));
setTimeout(this._cleanUpDownload.bind(this, element, url), FileServer.DELAY_SAFE_REMOVAL);
}
return;
},
serveText: function(filename, text, mime)
{
this.serve(filename, text, FileServer.PRAGMA_UTF8, mime);
return;
},
serveCompanion: function()
{
this.serve(FileServer.FILENAME_COMPANION, FileServer.CONTENT_COMPANION, FileServer.PRAGMA_BASE64, FileServer.MIME_EXECUTABLE);
return;
}
};
FileServer._cleanUpDownload = function(element, url)
{
document.body.removeChild(element);
if(url)
URL.revokeObjectURL(url);
return;
};
FileServer._getDataURL = function(content, pragma, mime)
{
return(FileServer.PROTOCOL_DATA + mime + FileServer.SEPARATOR_MIME + pragma + FileServer.SEPARATOR_PRAGMA + (pragma === FileServer.PRAGMA_BASE64 ? content : encodeURIComponent(content)));
};
FileServer.FILENAME_DEFAULT[FileServer.MIME_PLAYLIST] = "playlist.vlc";
VLCStation =
{
start: function()
{
document.body.addEventListener(VLCStation.EVENT_CLICK, this, true);
if(typeof(GM_registerMenuCommand) !== VLCStation.TYPE_UNDEFINED)
GM_registerMenuCommand(VLCStation.MENU_ITEM_DOWNLOAD_COMPANION, FileServer.serveCompanion.bind(FileServer), VLCStation.MENU_ACCESS_DOWNLOAD_COMPANION);
return;
},
handleEvent: function(event)
{
var button;
switch(event.type)
{
case VLCStation.EVENT_CLICK:
button = event.target;
if(!this.play(event, button))
{
button = button.parentNode;
if(button)
{
button = button.parentNode;
if(button)
this.play(event, button);
}
}
break;
}
return;
},
play: function(event, button)
{
var source;
var valid;
valid = button.classList.contains(VLCStation.CLASS_PLAY_BUTTON);
if(valid)
{
source = new Thumbnail(button.parentNode);
source.onload = this.requestPlaylist.bind(this);
source.load();
event.stopPropagation();
}
return(valid);
},
requestPlaylist: function(thumbnail)
{
var playlist;
var request;
var type;
type = Thumbnail.TYPE[thumbnail.type];
if(type)
{
request = new DSRequest(thumbnail.token);
request.onsuccess = function(request)
{
var element;
var extra;
var field;
var index;
var pathLength;
var response;
var test;
response = request.response;
field = type.infoContainer;
test = response;
pathLength = VLCStation.PATH_TEST_PLAYLIST.length;
for(index = 0; index < pathLength; index++)
{
element = VLCStation.PATH_TEST_PLAYLIST[index];
if(element === null)
element = field;
test = test[element];
if(!test)
{
extra = {};
extra[Problem.EXTRA_FIELD] = field;
extra[Problem.EXTRA_PATH_ELEMENT] = VLCStation.PATH_TEST_PLAYLIST[index];
extra[Problem.EXTRA_INDEX] = index;
Problem.report(Problem.MESSAGE_UNEXPECTED_RESPONSE_FORMAT, extra);
break;
}
}
if(index === pathLength)
{
playlist = new Playlist();
playlist.addVideoEntryList(response.data[field], type);
FileServer.serveText(null, playlist.getPLSText(), FileServer.MIME_PLAYLIST);
}
return;
};
request.setParameter(DSRequest.PARAMETER_ID, JSON.stringify([+thumbnail.id]));
request.setParameter(DSRequest.PARAMETER_ADDITIONAL, JSON.stringify([DSRequest.ADDITION_FILE]));
request.setParameter(DSRequest.PARAMETER_API, type.api);
request.setParameter(DSRequest.PARAMETER_METHOD, DSRequest.METHOD_GET_INFO);
request.setParameter(DSRequest.PARAMETER_VERSION, DSRequest.VERSION_API);
request.send();
}
else
{
extra = {};
extra[Problem.EXTRA_TYPE] = thumbnail.type;
Problem.report(Problem.MESSAGE_UNKNOWN_THUMBNAIL_TYPE, extra);
}
return;
}
};
VLCStation.PATH_TEST_PLAYLIST = ["data", null, 0, "additional", "file", 0];
VLCStation.MENU_ACCESS_DOWNLOAD_COMPANION = "D";
VLCStation.MENU_ITEM_DOWNLOAD_COMPANION = "Download VLC Full Screen Launcher (Windows)";
VLCStation.CLASS_PLAY_BUTTON = "play";
VLCStation.EVENT_CLICK = "click";
VLCStation.TYPE_UNDEFINED = "undefined";
VLCStation.start();
return;
})();