Embed rework
103
CMakeLists.txt
|
@ -370,22 +370,19 @@ add_executable(MistOutHTTP
|
|||
src/output/output_http.cpp
|
||||
src/output/output_http_internal.cpp
|
||||
src/io.cpp
|
||||
generated/silverlight.js.h
|
||||
generated/embed.js.h
|
||||
generated/player.js.h
|
||||
generated/html5.js.h
|
||||
generated/flash_strobe.js.h
|
||||
generated/theoplayer.js.h
|
||||
generated/jwplayer.js.h
|
||||
generated/polytrope.js.h
|
||||
generated/dashjs.js.h
|
||||
generated/videojs.js.h
|
||||
generated/img.js.h
|
||||
generated/playerdash.js.h
|
||||
generated/playerdashlic.js.h
|
||||
generated/playervideo.js.h
|
||||
generated/playerhlsvideo.js.h
|
||||
generated/core.js.h
|
||||
generated/mist.css.h
|
||||
generated/webrtc.js.h
|
||||
generated/player_dash.js.h
|
||||
generated/player_dash_lic.js.h
|
||||
generated/player_video.js.h
|
||||
generated/player_webrtc.js.h
|
||||
generated/skin_default.css.h
|
||||
generated/skin_dev.css.h
|
||||
generated/skin_videojs.css.h
|
||||
)
|
||||
set_target_properties(MistOutHTTP
|
||||
PROPERTIES COMPILE_DEFINITIONS "OUTPUTTYPE=\"output_http_internal.h\""
|
||||
|
@ -445,69 +442,61 @@ endif()
|
|||
########################################
|
||||
# Embed Code #
|
||||
########################################
|
||||
add_custom_command(OUTPUT generated/silverlight.js.h
|
||||
COMMAND ./sourcery ${SOURCE_DIR}/embed/wrappers/silverlight.js silverlight_js generated/silverlight.js.h
|
||||
DEPENDS sourcery ${SOURCE_DIR}/embed/wrappers/silverlight.js
|
||||
)
|
||||
add_custom_command(OUTPUT generated/embed.js.h
|
||||
COMMAND ./sourcery ${SOURCE_DIR}/src/embed.js embed_js generated/embed.js.h
|
||||
DEPENDS sourcery ${SOURCE_DIR}/src/embed.js
|
||||
# main
|
||||
add_custom_command(OUTPUT generated/player.js.h
|
||||
COMMAND ./sourcery ${SOURCE_DIR}/embed/min/player.js player_js generated/player.js.h
|
||||
DEPENDS sourcery ${SOURCE_DIR}/embed/min/player.js
|
||||
)
|
||||
# wrappers
|
||||
add_custom_command(OUTPUT generated/html5.js.h
|
||||
COMMAND ./sourcery ${SOURCE_DIR}/embed/wrappers/html5.js html5_js generated/html5.js.h
|
||||
DEPENDS sourcery ${SOURCE_DIR}/embed/wrappers/html5.js
|
||||
COMMAND ./sourcery ${SOURCE_DIR}/embed/min/wrappers/html5.js html5_js generated/html5.js.h
|
||||
DEPENDS sourcery ${SOURCE_DIR}/embed/min/wrappers/html5.js
|
||||
)
|
||||
add_custom_command(OUTPUT generated/flash_strobe.js.h
|
||||
COMMAND ./sourcery ${SOURCE_DIR}/embed/wrappers/flash_strobe.js flash_strobe_js generated/flash_strobe.js.h
|
||||
DEPENDS sourcery ${SOURCE_DIR}/embed/wrappers/flash_strobe.js
|
||||
)
|
||||
add_custom_command(OUTPUT generated/theoplayer.js.h
|
||||
COMMAND ./sourcery ${SOURCE_DIR}/embed/wrappers/theoplayer.js theoplayer_js generated/theoplayer.js.h
|
||||
DEPENDS sourcery ${SOURCE_DIR}/embed/wrappers/theoplayer.js
|
||||
)
|
||||
add_custom_command(OUTPUT generated/jwplayer.js.h
|
||||
COMMAND ./sourcery ${SOURCE_DIR}/embed/wrappers/jwplayer.js jwplayer_js generated/jwplayer.js.h
|
||||
DEPENDS sourcery ${SOURCE_DIR}/embed/wrappers/jwplayer.js
|
||||
)
|
||||
add_custom_command(OUTPUT generated/polytrope.js.h
|
||||
COMMAND ./sourcery ${SOURCE_DIR}/embed/wrappers/polytrope.js polytrope_js generated/polytrope.js.h
|
||||
DEPENDS sourcery ${SOURCE_DIR}/embed/wrappers/polytrope.js
|
||||
COMMAND ./sourcery ${SOURCE_DIR}/embed/min/wrappers/flash_strobe.js flash_strobe_js generated/flash_strobe.js.h
|
||||
DEPENDS sourcery ${SOURCE_DIR}/embed/min/wrappers/flash_strobe.js
|
||||
)
|
||||
add_custom_command(OUTPUT generated/dashjs.js.h
|
||||
COMMAND ./sourcery ${SOURCE_DIR}/embed/wrappers/dashjs.js dash_js generated/dashjs.js.h
|
||||
DEPENDS sourcery ${SOURCE_DIR}/embed/wrappers/dashjs.js
|
||||
COMMAND ./sourcery ${SOURCE_DIR}/embed/min/wrappers/dashjs.js dash_js generated/dashjs.js.h
|
||||
DEPENDS sourcery ${SOURCE_DIR}/embed/min/wrappers/dashjs.js
|
||||
)
|
||||
add_custom_command(OUTPUT generated/videojs.js.h
|
||||
COMMAND ./sourcery ${SOURCE_DIR}/embed/wrappers/videojs.js video_js generated/videojs.js.h
|
||||
DEPENDS sourcery ${SOURCE_DIR}/embed/wrappers/videojs.js
|
||||
COMMAND ./sourcery ${SOURCE_DIR}/embed/min/wrappers/videojs.js video_js generated/videojs.js.h
|
||||
DEPENDS sourcery ${SOURCE_DIR}/embed/min/wrappers/videojs.js
|
||||
)
|
||||
add_custom_command(OUTPUT generated/img.js.h
|
||||
COMMAND ./sourcery ${SOURCE_DIR}/embed/wrappers/img.js img_js generated/img.js.h
|
||||
DEPENDS sourcery ${SOURCE_DIR}/embed/wrappers/img.js
|
||||
add_custom_command(OUTPUT generated/webrtc.js.h
|
||||
COMMAND ./sourcery ${SOURCE_DIR}/embed/min/wrappers/webrtc.js webrtc_js generated/webrtc.js.h
|
||||
DEPENDS sourcery ${SOURCE_DIR}/embed/min/wrappers/webrtc.js
|
||||
)
|
||||
add_custom_command(OUTPUT generated/playerdashlic.js.h
|
||||
COMMAND ./sourcery ${SOURCE_DIR}/embed/players/dash.js.license.js playerdashlic_js generated/playerdashlic.js.h
|
||||
# players
|
||||
add_custom_command(OUTPUT generated/player_dash_lic.js.h
|
||||
COMMAND ./sourcery ${SOURCE_DIR}/embed/players/dash.js.license.js player_dash_lic_js generated/player_dash_lic.js.h
|
||||
DEPENDS sourcery ${SOURCE_DIR}/embed/players/dash.js.license.js
|
||||
)
|
||||
add_custom_command(OUTPUT generated/playerdash.js.h
|
||||
COMMAND ./sourcery ${SOURCE_DIR}/embed/players/dash.all.min.js playerdash_js generated/playerdash.js.h
|
||||
add_custom_command(OUTPUT generated/player_dash.js.h
|
||||
COMMAND ./sourcery ${SOURCE_DIR}/embed/players/dash.all.min.js player_dash_js generated/player_dash.js.h
|
||||
DEPENDS sourcery ${SOURCE_DIR}/embed/players/dash.all.min.js
|
||||
)
|
||||
add_custom_command(OUTPUT generated/playervideo.js.h
|
||||
COMMAND ./sourcery ${SOURCE_DIR}/embed/players/video.min.js playervideo_js generated/playervideo.js.h
|
||||
add_custom_command(OUTPUT generated/player_video.js.h
|
||||
COMMAND ./sourcery ${SOURCE_DIR}/embed/players/video.min.js player_video_js generated/player_video.js.h
|
||||
DEPENDS sourcery ${SOURCE_DIR}/embed/players/video.min.js
|
||||
)
|
||||
add_custom_command(OUTPUT generated/playerhlsvideo.js.h
|
||||
COMMAND ./sourcery ${SOURCE_DIR}/embed/players/videojs-contrib-hls.min.js playerhlsvideo_js generated/playerhlsvideo.js.h
|
||||
DEPENDS sourcery ${SOURCE_DIR}/embed/players/videojs-contrib-hls.min.js
|
||||
add_custom_command(OUTPUT generated/player_webrtc.js.h
|
||||
COMMAND ./sourcery ${SOURCE_DIR}/embed/players/webrtc.js player_webrtc_js generated/player_webrtc.js.h
|
||||
DEPENDS sourcery ${SOURCE_DIR}/embed/players/webrtc.js
|
||||
)
|
||||
add_custom_command(OUTPUT generated/core.js.h
|
||||
COMMAND ./sourcery ${SOURCE_DIR}/embed/core.js core_js generated/core.js.h
|
||||
DEPENDS sourcery ${SOURCE_DIR}/embed/core.js
|
||||
# css
|
||||
add_custom_command(OUTPUT generated/skin_default.css.h
|
||||
COMMAND ./sourcery ${SOURCE_DIR}/embed/min/skins/default.css skin_default_css generated/skin_default.css.h
|
||||
DEPENDS sourcery ${SOURCE_DIR}/embed/min/skins/default.css
|
||||
)
|
||||
add_custom_command(OUTPUT generated/mist.css.h
|
||||
COMMAND ./sourcery ${SOURCE_DIR}/embed/mist.css mist_css generated/mist.css.h
|
||||
DEPENDS sourcery ${SOURCE_DIR}/embed/mist.css
|
||||
add_custom_command(OUTPUT generated/skin_dev.css.h
|
||||
COMMAND ./sourcery ${SOURCE_DIR}/embed/min/skins/dev.css skin_dev_css generated/skin_dev.css.h
|
||||
DEPENDS sourcery ${SOURCE_DIR}/embed/min/skins/dev.css
|
||||
)
|
||||
add_custom_command(OUTPUT generated/skin_videojs.css.h
|
||||
COMMAND ./sourcery ${SOURCE_DIR}/embed/skins/video-js.css skin_videojs_css generated/skin_videojs.css.h
|
||||
DEPENDS sourcery ${SOURCE_DIR}/embed/skins/video-js.css
|
||||
)
|
||||
|
||||
########################################
|
||||
|
|
122
embed/controls.js
vendored
Normal file
|
@ -0,0 +1,122 @@
|
|||
function MistUI(MistVideo,structure) {
|
||||
MistVideo.UI = this;
|
||||
this.elements = [];
|
||||
|
||||
this.buildStructure = function(structure){
|
||||
if (typeof structure == "function") { structure = structure.call(MistVideo); }
|
||||
|
||||
if ("if" in structure) {
|
||||
var result = false;
|
||||
if (structure.if.call(MistVideo,structure)) {
|
||||
result = structure.then;
|
||||
}
|
||||
else if ("else" in structure) {
|
||||
result = structure.else;
|
||||
}
|
||||
|
||||
if (!result) { return; }
|
||||
|
||||
//append the result with structure options
|
||||
for (var i in structure) {
|
||||
if (["if","then","else"].indexOf(i) < 0) {
|
||||
if (i in result) {
|
||||
if (!(result[i] instanceof Array)) {
|
||||
result[i] = [result[i]];
|
||||
}
|
||||
result[i] = result[i].concat(structure[i]);
|
||||
}
|
||||
else {
|
||||
result[i] = structure[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
return this.buildStructure(result);
|
||||
}
|
||||
|
||||
if ("type" in structure) {
|
||||
if (structure.type in MistVideo.skin.blueprints) {
|
||||
|
||||
//create the element; making sure to pass "this" to blueprint function
|
||||
var container = MistVideo.skin.blueprints[structure.type].call(MistVideo,structure);
|
||||
if (!container) { return; }
|
||||
MistUtil.class.add(container,"mistvideo-"+structure.type);
|
||||
|
||||
if ("css" in structure) {
|
||||
var uid = MistUtil.createUnique();
|
||||
structure.css = [].concat(structure.css); //convert to array; should be in string format with colors already applied
|
||||
|
||||
for (var i in structure.css) {
|
||||
var style = MistUtil.css.createStyle(structure.css[i],uid);
|
||||
container.appendChild(style);
|
||||
}
|
||||
MistUtil.class.add(container,uid);
|
||||
container.uid = uid;
|
||||
}
|
||||
|
||||
if ("classes" in structure) {
|
||||
for (var i in structure.classes) {
|
||||
MistUtil.class.add(container,structure.classes[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if ("title" in structure) {
|
||||
container.title = structure.title;
|
||||
}
|
||||
|
||||
if ("style" in structure) {
|
||||
for (var i in structure.style) {
|
||||
container.style[i] = structure.style[i];
|
||||
}
|
||||
}
|
||||
|
||||
if ("children" in structure) {
|
||||
for (var i in structure.children) {
|
||||
var child = this.buildStructure(structure.children[i]);
|
||||
if (child) {
|
||||
container.appendChild(child);
|
||||
}
|
||||
}
|
||||
}
|
||||
//save the returned element so they can be killed on unload
|
||||
MistVideo.UI.elements.push(container);
|
||||
return container;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
this.build = function(){
|
||||
return this.buildStructure(structure ? structure : MistVideo.skin.structure.main);
|
||||
};
|
||||
|
||||
var container = this.build();
|
||||
|
||||
//apply skin CSS
|
||||
var uid = MistUtil.createUnique();
|
||||
var toload = MistVideo.skin.css.length;
|
||||
if (toload) { container.style.opacity = "0"; }
|
||||
for (var i in MistVideo.skin.css) {
|
||||
var style = MistVideo.skin.css[i];
|
||||
style.callback = function(css) {
|
||||
this.textContent = MistUtil.css.prependClass(css,uid,true);
|
||||
toload--;
|
||||
if (toload <= 0) {
|
||||
container.style.opacity = "";
|
||||
}
|
||||
};
|
||||
if (style.textContent != "") {
|
||||
//it has already loaded
|
||||
style.callback(style.textContent);
|
||||
}
|
||||
container.appendChild(style);
|
||||
}
|
||||
MistUtil.class.add(container,uid);
|
||||
|
||||
//add browser class
|
||||
var browser = MistUtil.getBrowser();
|
||||
if (browser) {
|
||||
MistUtil.class.add(container,"browser-"+browser);
|
||||
}
|
||||
|
||||
return container;
|
||||
}
|
1501
embed/core.js
|
@ -1 +1,13 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?><svg xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" version="1.1" id="svg3937" height="45" width="45"><defs id="defs3939" /><metadata id="metadata3942"><rdf:RDF><cc:Work rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><g transform="translate(0,-1007.3622)" id="layer1"><g transform="translate(0,-1.109375)" id="g4563"><g id="g4558"><path id="rect3945" transform="translate(0,1007.3622)" d="M 5.15625,10 C 3.6913461,10 2.5,11.191346 2.5,12.65625 l 0,19.6875 C 2.5,33.808654 3.6913461,35 5.15625,35 l 34.6875,0 C 41.308654,35 42.5,33.808654 42.5,32.34375 l 0,-19.6875 C 42.5,11.191346 41.308654,10 39.84375,10 L 5.15625,10 z M 5,12.53125 l 35,0 0,20 -35,0 0,-20 z" style="fill:#fff;fill-opacity:1;stroke:none" /><rect ry="0" y="1019.8622" x="5" height="20" width="35" id="rect3947" style="fill:#fff;fill-opacity:0.39215686;stroke:none" /><path id="path3949" transform="translate(0,1007.3622)" d="m 18.78125,35.40625 c -1.53661,0.379809 -2.971465,0.991557 -4.28125,1.8125 l 15.65625,0 c -1.313005,-0.822961 -2.762825,-1.432953 -4.3125,-1.8125 l -7.0625,0 z" style="fill:#fff;fill-opacity:1;stroke:none" /></g><g id="g4007" transform="matrix(2.0353985,0,0,1.1630828,-99.321734,-141.54581)" style="fill:#000"><path id="rect3958" d="m 65.533646,1001.4758 -2.032932,0 0.662913,0.6629 -2.253903,2.2539 0.707107,0.7071 2.253903,-2.2539 0.662912,0.6629 0,-2.0329 z" style="fill:#fff;fill-opacity:1;stroke:none" /><path id="rect3958-5" d="m 65.533646,1012.84 0,-2.033 -0.662836,0.6629 -2.253901,-2.2539 -0.707104,0.7071 2.253902,2.2539 -0.662906,0.6629 2.032845,1e-4 z" style="fill:#fff;fill-opacity:1;stroke:none" /><path id="rect3958-51" d="m 54.16943,1001.4758 2.032932,0 -0.662913,0.6629 2.253903,2.2539 -0.707107,0.7071 -2.253903,-2.2539 -0.662912,0.6629 0,-2.0329 z" style="fill:#fff;fill-opacity:1;stroke:none" /><path id="rect3958-5-7" d="m 54.16943,1012.84 0,-2.033 0.662836,0.6629 2.253901,-2.2539 0.707104,0.7071 -2.253902,2.2539 0.662906,0.6629 -2.032845,1e-4 z" style="fill:#fff;fill-opacity:1;stroke:none" /></g></g></g></svg>
|
||||
<svg width="45" height="45" version="1.1" xmlns="http://www.w3.org/2000/svg">
|
||||
<g fill="#fff">
|
||||
<path d="m5.1562 8.8906c-1.4649 0-2.6562 1.1913-2.6562 2.6562v19.688c0 1.4649 1.1913 2.6562 2.6562 2.6562h34.688c1.4649 0 2.6562-1.1913 2.6562-2.6562v-19.688c0-1.4649-1.1913-2.6562-2.6562-2.6562h-34.688m-0.15625 2.5312h35v20h-35v-20"/>
|
||||
<rect transform="translate(0 -1008.5)" x="5" y="1019.9" width="35" height="20" ry="0" fill-opacity=".39216"/>
|
||||
<path d="m18.781 34.297c-1.5366 0.37981-2.9715 0.99156-4.2812 1.8125h15.656c-1.313-0.82296-2.7628-1.433-4.3125-1.8125h-7.0625"/>
|
||||
<g>
|
||||
<path d="m34.065 14.782h-4.1378l1.3493 0.77101-4.5876 2.6215 1.4392 0.82242 4.5876-2.6215s1.3493 0.77101 1.3493 0.77101v-2.3644"/>
|
||||
<path d="m34.065 27.999v-2.3645s-1.3491 0.77101-1.3491 0.77101l-4.5876-2.6215-1.4392 0.82242 4.5876 2.6215-1.3493 0.77101 4.1376 1.1631e-4"/>
|
||||
<path d="m10.935 14.782h4.1378l-1.3493 0.77101 4.5876 2.6215-1.4392 0.82242-4.5876-2.6215s-1.3493 0.77101-1.3493 0.77101v-2.3644"/>
|
||||
<path d="m10.935 27.999v-2.3645s1.3491 0.77101 1.3491 0.77101l4.5876-2.6215s1.4392 0.82242 1.4392 0.82242l-4.5876 2.6215 1.3493 0.77101-4.1376 1.1631e-4"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
|
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 1.2 KiB |
3
embed/imgs/fullscreen_plain_.svg
Normal file
|
@ -0,0 +1,3 @@
|
|||
<svg width="45" height="45" version="1.1" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="m2.5 10.928v8.5898l4.9023-2.8008 9.6172 5.7832-9.6172 5.7832-4.9023-2.8008v8.5898h15.031l-4.9004-2.8008 9.8691-5.6387 9.8691 5.6387-4.9004 2.8008h15.031v-8.5898l-4.9023 2.8008-9.6172-5.7832 9.6172-5.7832 4.9023 2.8008v-8.5898h-15.033l4.9023 2.8008-9.8691 5.6387-9.8691-5.6387 4.9023-2.8008z" fill="#fff"/>
|
||||
</svg>
|
After Width: | Height: | Size: 402 B |
61
embed/imgs/gear.svg
Normal file
|
@ -0,0 +1,61 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
version="1.1"
|
||||
id="svg4659"
|
||||
height="45"
|
||||
width="45"
|
||||
sodipodi:docname="gear.svg"
|
||||
inkscape:version="0.92.2 5c3e80d, 2017-08-06">
|
||||
<sodipodi:namedview
|
||||
pagecolor="#4cc5a0"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1868"
|
||||
inkscape:window-height="1049"
|
||||
id="namedview8"
|
||||
showgrid="false"
|
||||
fit-margin-top="0"
|
||||
fit-margin-left="0"
|
||||
fit-margin-right="0"
|
||||
fit-margin-bottom="0"
|
||||
inkscape:zoom="6.675088"
|
||||
inkscape:cx="62.439695"
|
||||
inkscape:cy="43.399157"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="0"
|
||||
inkscape:current-layer="svg4659"
|
||||
inkscape:snap-page="true" />
|
||||
<defs
|
||||
id="defs4661" />
|
||||
<metadata
|
||||
id="metadata4664">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<path
|
||||
style="opacity:1;vector-effect:none;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:2.50001693;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||
d="m 24.139007,3.834512 -1.477875,4.3213185 c -1.101822,0.0088 -2.274313,0.1330197 -3.204775,0.3369163 L 17.128868,4.5441522 C 15.631516,4.9971895 14.196746,5.635837 12.858006,6.4452068 l 1.34441,4.3668912 c -0.878085,0.62225 -1.683392,1.341293 -2.400733,2.14357 L 7.6056909,11.132739 c -0.9476032,1.24558 -1.7355288,2.604902 -2.3453935,4.046251 l 3.6523686,2.739277 c -0.3489484,1.021477 -0.5815406,2.079062 -0.6933641,3.15269 L 3.7661466,22.05892 c -0.00716,0.146959 -0.012582,0.293997 -0.016276,0.441084 0.00628,1.417863 0.173364,2.830439 0.4980503,4.21064 l 4.5703436,0.06998 c 0.3217092,1.027112 0.7579402,2.014774 1.3004645,2.944356 l -3.0387575,3.435896 c 0.8950189,1.282782 1.947035,2.448529 3.1315315,3.470075 l 3.735377,-2.628599 c 0.86307,0.64582 1.796153,1.192348 2.781594,1.629243 l -0.436201,4.539419 c 1.475447,0.52082 3.010282,0.854908 4.568716,0.994474 l 1.477875,-4.321319 c 0.05369,0.003 0.107408,0.0057 0.161134,0.0082 1.023951,-0.0061 2.044309,-0.121786 3.043641,-0.345054 l 2.327489,3.948594 c 1.497352,-0.453037 2.932122,-1.091685 4.270862,-1.901055 l -1.34441,-4.366891 c 0.878085,-0.622249 1.683392,-1.341292 2.400733,-2.14357 l 4.195992,1.82293 c 0.947603,-1.245581 1.735529,-2.604903 2.345394,-4.046252 l -3.652368,-2.739276 c 0.348948,-1.021478 0.58154,-2.079063 0.693363,-3.152691 l 4.453156,-0.987963 c 0.0072,-0.146984 0.01258,-0.294022 0.01628,-0.441108 -0.0062,-1.417863 -0.173364,-2.83044 -0.49805,-4.210641 l -4.570344,-0.06998 c -0.321709,-1.027116 -0.75794,-2.014777 -1.300465,-2.94436 l 3.038754,-3.435928 C 37.025006,10.556342 35.97299,9.3905941 34.788493,8.3690481 L 31.053116,10.997647 C 30.190046,10.351826 29.256963,9.8052988 28.271521,9.3684038 L 28.707723,4.8289849 C 27.232276,4.308166 25.697441,3.9740781 24.139007,3.834512 Z"
|
||||
id="path4541"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cccccccccccccccccccccccccccccccccccccccccccc" />
|
||||
</svg>
|
After Width: | Height: | Size: 3.7 KiB |
3
embed/imgs/gear_plain.svg
Normal file
|
@ -0,0 +1,3 @@
|
|||
<svg width="45" height="45" version="1.1" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="m24.139 3.834-1.4785 4.3223c-1.1018 0.0088-2.2727 0.13204-3.2031 0.33594l-2.3281-3.9473c-1.4974 0.45304-2.9327 1.091-4.2715 1.9004l1.3457 4.3672c-0.87808 0.62225-1.685 1.3403-2.4023 2.1426l-4.1953-1.8223c-0.9476 1.2456-1.7358 2.6055-2.3457 4.0469l3.6523 2.7383c-0.34895 1.0215-0.58154 2.0787-0.69336 3.1523l-4.4531 0.98828c-0.00716 0.14696-0.011931 0.29432-0.015625 0.44141 0.00628 1.4179 0.17336 2.8307 0.49805 4.2109l4.5703 0.070312c0.32171 1.0271 0.75826 2.0138 1.3008 2.9434l-3.0391 3.4355c0.89502 1.2828 1.9464 2.4492 3.1309 3.4707l3.7363-2.6289c0.86307 0.64582 1.7958 1.192 2.7812 1.6289l-0.43555 4.541c1.4754 0.52082 3.0099 0.85458 4.5684 0.99414l1.4766-4.3223c0.05369 3e-3 0.10838 0.005313 0.16211 0.007812 1.024-0.0061 2.0436-0.12048 3.043-0.34375l2.3281 3.9473c1.4974-0.45304 2.9327-1.091 4.2715-1.9004l-1.3457-4.3672c0.87808-0.62225 1.685-1.3403 2.4023-2.1426l4.1953 1.8223c0.9476-1.2456 1.7358-2.6055 2.3457-4.0469l-3.6523-2.7383c0.34895-1.0215 0.58154-2.0787 0.69336-3.1523l4.4531-0.98828c0.0072-0.14698 0.011925-0.29432 0.015625-0.44141-0.0062-1.4179-0.17336-2.8307-0.49805-4.2109l-4.5703-0.070312c-0.32171-1.0271-0.75826-2.0138-1.3008-2.9434l3.0391-3.4355c-0.89502-1.2828-1.9464-2.4492-3.1309-3.4707l-3.7363 2.6289c-0.86307-0.64582-1.7958-1.192-2.7812-1.6289l0.43555-4.541c-1.4754-0.52082-3.0099-0.85457-4.5684-0.99414zm-1.6387 7.8789a10.786 10.786 0 0 1 10.787 10.787 10.786 10.786 0 0 1-10.787 10.787 10.786 10.786 0 0 1-10.787-10.787 10.786 10.786 0 0 1 10.787-10.787z" fill="#fff"/>
|
||||
</svg>
|
After Width: | Height: | Size: 1.6 KiB |
1
embed/imgs/loading.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="100%" width="100%"><path d="m49.998 8.7797e-4c-0.060547 0.0018431-0.12109 0.0037961-0.18164 0.0058593-0.1251 0.0015881-0.25012 0.0061465-0.375 0.013672h-0.001954c-27.388 0.30599-49.432 22.59-49.439 49.98 0.020074 2.6488 0.25061 5.292 0.68945 7.904 3.8792-24.231 24.77-42.065 49.311-42.096v-0.0058582h0.001954c4.3638 3.0803e-4 7.9013-3.5366 7.9021-7.9002 1.474e-4 -2.0958-0.83235-4.106-2.3144-5.5879-1.482-1.482-3.492-2.3145-5.5879-2.3144-6.5007e-4 -7.9369e-8 -0.0013001-7.9369e-8 -0.001954 0" class="semiFill"/></svg>
|
After Width: | Height: | Size: 580 B |
|
@ -11,8 +11,9 @@
|
|||
id="svg3937"
|
||||
height="45"
|
||||
width="45"
|
||||
inkscape:version="0.91 r13725"
|
||||
sodipodi:docname="loop.svg">
|
||||
inkscape:version="0.92.2 5c3e80d, 2017-08-06"
|
||||
sodipodi:docname="loop.svg"
|
||||
viewBox="0 0 45 45">
|
||||
<sodipodi:namedview
|
||||
pagecolor="#8bff39"
|
||||
bordercolor="#666666"
|
||||
|
@ -22,8 +23,8 @@
|
|||
guidetolerance="10"
|
||||
inkscape:pageopacity="1"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1055"
|
||||
inkscape:window-width="1868"
|
||||
inkscape:window-height="1049"
|
||||
id="namedview3591"
|
||||
showgrid="false"
|
||||
showguides="true"
|
||||
|
@ -40,37 +41,17 @@
|
|||
inkscape:snap-smooth-nodes="true"
|
||||
inkscape:snap-midpoints="true"
|
||||
inkscape:zoom="14.833529"
|
||||
inkscape:cx="30.216329"
|
||||
inkscape:cy="21.135445"
|
||||
inkscape:cx="21.722684"
|
||||
inkscape:cy="25.7616"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg3937">
|
||||
<sodipodi:guide
|
||||
position="0,0"
|
||||
orientation="0,45"
|
||||
id="guide3615" />
|
||||
<sodipodi:guide
|
||||
position="45,0"
|
||||
orientation="-45,0"
|
||||
id="guide3617" />
|
||||
<sodipodi:guide
|
||||
position="45,45"
|
||||
orientation="0,-45"
|
||||
id="guide3619" />
|
||||
<sodipodi:guide
|
||||
position="0,45"
|
||||
orientation="45,0"
|
||||
id="guide3621" />
|
||||
<sodipodi:guide
|
||||
position="0,0"
|
||||
orientation="-0.70710678,0.70710678"
|
||||
id="guide3624" />
|
||||
<sodipodi:guide
|
||||
position="0,45"
|
||||
orientation="0.70710678,0.70710678"
|
||||
id="guide4491" />
|
||||
</sodipodi:namedview>
|
||||
inkscape:current-layer="svg3937"
|
||||
fit-margin-top="0"
|
||||
fit-margin-left="0"
|
||||
fit-margin-right="0"
|
||||
fit-margin-bottom="0"
|
||||
scale-x="1" />
|
||||
<defs
|
||||
id="defs3939" />
|
||||
<metadata
|
||||
|
@ -86,11 +67,8 @@
|
|||
</rdf:RDF>
|
||||
</metadata>
|
||||
<path
|
||||
style="opacity:1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.5;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||
d="M 0 0 L 0 45 L 45 45 L 45 0 L 0 0 z M 22.5 11.25 A 11.25 11.25 0 0 1 33.75 22.5 A 11.25 11.25 0 0 1 22.5 33.75 A 11.25 11.25 0 0 1 14.550781 30.449219 L 12.714844 32.285156 L 12.714844 25.785156 L 19.214844 25.785156 L 17.376953 27.623047 A 7.25 7.25 0 0 0 22.5 29.75 A 7.25 7.25 0 0 0 29.75 22.5 A 7.25 7.25 0 0 0 22.5 15.25 A 7.25 7.25 0 0 0 17.376953 17.376953 L 14.550781 14.550781 A 11.25 11.25 0 0 1 22.5 11.25 z "
|
||||
id="rect4511" />
|
||||
<path
|
||||
style="opacity:1;fill:none;fill-opacity:0.8584475;fill-rule:evenodd;stroke:#ffffff;stroke-width:1.5;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||
d="M 22.5 11.25 A 11.25 11.25 0 0 0 14.550781 14.550781 L 17.376953 17.376953 A 7.25 7.25 0 0 1 22.5 15.25 A 7.25 7.25 0 0 1 29.75 22.5 A 7.25 7.25 0 0 1 22.5 29.75 A 7.25 7.25 0 0 1 17.376953 27.623047 L 19.214844 25.785156 L 12.714844 25.785156 L 12.714844 32.285156 L 14.550781 30.449219 A 11.25 11.25 0 0 0 22.5 33.75 A 11.25 11.25 0 0 0 33.75 22.5 A 11.25 11.25 0 0 0 22.5 11.25 z "
|
||||
id="path4495" />
|
||||
style="opacity:1;fill:none;fill-opacity:0.8584475;fill-rule:evenodd;stroke:#ffffff;stroke-width:2.50002718;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||
d="M 21.279283,3.749797 A 18.750203,18.750203 0 0 0 8.0304417,9.2511582 L 12.740779,13.961496 A 12.083464,12.083464 0 0 1 21.279283,10.416536 12.083464,12.083464 0 0 1 33.362748,22.5 12.083464,12.083464 0 0 1 21.279283,34.583464 12.083464,12.083464 0 0 1 12.740779,31.038504 l 3.063185,-3.063185 H 4.9705135 V 38.80877 L 8.0304417,35.748842 A 18.750203,18.750203 0 0 0 21.279283,41.250203 18.750203,18.750203 0 0 0 40.029486,22.5 18.750203,18.750203 0 0 0 21.279283,3.749797 Z"
|
||||
id="path4495"
|
||||
inkscape:connector-curvature="0" />
|
||||
</svg>
|
||||
|
|
Before Width: | Height: | Size: 3.7 KiB After Width: | Height: | Size: 2.8 KiB |
7
embed/imgs/muted_plain.svg
Normal file
|
@ -0,0 +1,7 @@
|
|||
<svg width="45" height="45" version="1.1" xmlns="http://www.w3.org/2000/svg">
|
||||
<path class="stroke semiFill toggle" d="m25.587 5.2036c-1.8324-1.1012-4.2007-0.8622-5.7719 0.77112 0 0-7.7388 8.0444-7.7388 8.0444h-3.418c-1.9537 0-3.547 1.6562-3.547 3.6869v9.5864c0 2.0309 1.5933 3.6871 3.547 3.6871h3.418s7.7388 8.0447 7.7388 8.0447c1.5721 1.634 3.9389 1.8747 5.7719 0.77076v-34.591" fill="none" stroke="#000"/>
|
||||
<g fill="none" stroke="#000" stroke-linecap="round" stroke-width="1.4142">
|
||||
<path d="m30.032 27.86 9.8517-9.8517"/>
|
||||
<path d="m30.032 18.008 9.8517 9.8517"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 590 B |
|
@ -1 +1 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?><svg xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" version="1.1" id="svg2" height="45" width="45"><defs id="defs4" /><metadata id="metadata7"><rdf:RDF><cc:Work rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><g transform="translate(0,-1007.3622)" id="layer1"><g style="fill:#fff" transform="translate(3.0304575,47.729705)" id="g3779"><path id="path3823-7" d="m 4.4695429,998.16377 a 4.0011916,4.0011916 0 0 0 3.749999,3.96873 l 2.2812501,0 a 4.0011916,4.0011916 0 0 0 3.96875,-3.75003 l 0,-32.28123 a 4.0011916,4.0011916 0 0 0 -3.75,-3.96875 l -2.2812501,0 a 4.0011916,4.0011916 0 0 0 -3.968749,3.75 l 0,32.28128 z" style="fill:#fff;fill-opacity:1;stroke:none" /><path id="path3823-7-4" d="m 24.469542,998.1638 a 4.0011916,4.0011916 0 0 0 3.75,3.9687 l 2.28125,0 a 4.0011916,4.0011916 0 0 0 3.96875,-3.75 l 0,-32.28126 a 4.0011916,4.0011916 0 0 0 -3.75,-3.96875 l -2.28125,0 a 4.0011916,4.0011916 0 0 0 -3.96875,3.75 l 0,32.28131 z" style="fill:#fff;fill-opacity:1;stroke:none" /></g></g></svg>
|
||||
<svg width="25" height="25" version="1.1" viewBox="0 0 25 25" xmlns="http://www.w3.org/2000/svg"><g transform="matrix(.55556 0 0 .55556 0 -559.65)"><g transform="translate(3.0305 47.73)" fill="#fff"><path d="m4.4695 998.16a4.0012 4.0012 0 0 0 3.75 3.9687h2.2813a4.0012 4.0012 0 0 0 3.9688-3.75v-32.281a4.0012 4.0012 0 0 0-3.75-3.9688h-2.2813a4.0012 4.0012 0 0 0-3.9687 3.75z"/><path d="m24.47 998.16a4.0012 4.0012 0 0 0 3.75 3.9687h2.2812a4.0012 4.0012 0 0 0 3.9688-3.75v-32.281a4.0012 4.0012 0 0 0-3.75-3.9688h-2.2812a4.0012 4.0012 0 0 0-3.9688 3.75z"/></g></g></svg>
|
||||
|
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 569 B |
|
@ -13,10 +13,8 @@
|
|||
height="45"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
inkscape:version="0.48.4 r9939"
|
||||
sodipodi:docname="New document 1">
|
||||
<defs
|
||||
id="defs4" />
|
||||
inkscape:version="0.92.2 5c3e80d, 2017-08-06"
|
||||
sodipodi:docname="play.svg">
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#000000"
|
||||
|
@ -39,28 +37,34 @@
|
|||
inkscape:snap-page="true"
|
||||
inkscape:object-nodes="true"
|
||||
inkscape:snap-nodes="false"
|
||||
inkscape:window-width="981"
|
||||
inkscape:window-height="709"
|
||||
inkscape:window-x="856"
|
||||
inkscape:window-y="240"
|
||||
inkscape:window-width="1868"
|
||||
inkscape:window-height="1049"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="0">
|
||||
<sodipodi:guide
|
||||
position="0,0"
|
||||
inkscape:locked="false"
|
||||
id="guide3785"
|
||||
orientation="0,45"
|
||||
id="guide3785" />
|
||||
position="0,0" />
|
||||
<sodipodi:guide
|
||||
position="45,0"
|
||||
inkscape:locked="false"
|
||||
id="guide3787"
|
||||
orientation="-45,0"
|
||||
id="guide3787" />
|
||||
position="45,0" />
|
||||
<sodipodi:guide
|
||||
position="45,45"
|
||||
inkscape:locked="false"
|
||||
id="guide3789"
|
||||
orientation="0,-45"
|
||||
id="guide3789" />
|
||||
position="45,45" />
|
||||
<sodipodi:guide
|
||||
position="0,45"
|
||||
inkscape:locked="false"
|
||||
id="guide3791"
|
||||
orientation="45,0"
|
||||
id="guide3791" />
|
||||
position="0,45" />
|
||||
</sodipodi:namedview>
|
||||
<defs
|
||||
id="defs4" />
|
||||
<metadata
|
||||
id="metadata7">
|
||||
<rdf:RDF>
|
||||
|
@ -69,22 +73,17 @@
|
|||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
<dc:title />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(0,-1007.3622)">
|
||||
inkscape:groupmode="layer"
|
||||
inkscape:label="Layer 1">
|
||||
<path
|
||||
sodipodi:type="inkscape:offset"
|
||||
inkscape:radius="0"
|
||||
inkscape:original="M 10.3125 -6.34375 A 2.9416186 2.9416186 0 0 0 7.90625 -4.875 L -6.21875 19.625 A 2.9416186 2.9416186 0 0 0 -3.65625 24.03125 L 24.625 24.03125 A 2.9416186 2.9416186 0 0 0 27.15625 19.625 L 13 -4.875 A 2.9416186 2.9416186 0 0 0 10.3125 -6.34375 z "
|
||||
style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none"
|
||||
d="M6.26004984594 3.0550109625C5.27445051914 3.68940862462 4.67905105702 4.78142391497 4.67968264562 5.95354422781C4.67968264562 5.95354422781 4.70004942312 39.0717540916 4.70004942312 39.0717540916C4.70302341604 40.3033886636 5.36331656075 41.439734231 6.43188211452 42.0521884912C7.50044766829 42.6646427515 8.81469531629 42.6600161659 9.87892235656 42.0400537716C9.87892235656 42.0400537716 38.5612768409 25.4802882606 38.5612768409 25.4802882606C39.6181165777 24.8606067582 40.2663250096 23.7262617523 40.2636734301 22.5011460995C40.2610218505 21.2760304467 39.6079092743 20.1445019555 38.5483970356 19.5294009803C38.5483970356 19.5294009803 9.84567577375 2.9709566275 9.84567577375 2.9709566275C8.72898008118 2.32550764609 7.34527425735 2.35794451351 6.26004984594 3.0550109625C6.26004984594 3.0550109625 6.26004984594 3.0550109625 6.26004984594 3.0550109625"
|
||||
id="path3809"
|
||||
d="M 10.3125,-6.34375 A 2.9416186,2.9416186 0 0 0 7.90625,-4.875 l -14.125,24.5 a 2.9416186,2.9416186 0 0 0 2.5625,4.40625 l 28.28125,0 A 2.9416186,2.9416186 0 0 0 27.15625,19.625 L 13,-4.875 a 2.9416186,2.9416186 0 0 0 -2.6875,-1.46875 z"
|
||||
transform="matrix(1.0141827,-0.58553867,0.58553867,1.0141827,-0.48419831,1022.8893)" />
|
||||
style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none" />
|
||||
</g>
|
||||
</svg>
|
||||
|
|
Before Width: | Height: | Size: 3 KiB After Width: | Height: | Size: 3.3 KiB |
3
embed/imgs/popout.svg
Normal file
|
@ -0,0 +1,3 @@
|
|||
<svg width="45" height="45" version="1.1" viewBox="0 0 45 45" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="m24.721 11.075c-12.96 0.049575-32.113 15.432-10.336 28.834-7.6763-7.9825-2.4795-21.824 10.336-22.19v5.5368l15.276-8.862-15.276-8.86v5.5419" fill="none" stroke="#000" stroke-width="1.4142"/>
|
||||
</svg>
|
After Width: | Height: | Size: 306 B |
|
@ -1,6 +1,4 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
|
@ -9,49 +7,38 @@
|
|||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="25"
|
||||
height="25"
|
||||
id="svg4659"
|
||||
version="1.1"
|
||||
inkscape:version="0.91 r13725"
|
||||
sodipodi:docname="speaker.svg">
|
||||
<defs
|
||||
id="defs4661" />
|
||||
id="svg4659"
|
||||
height="45"
|
||||
width="45"
|
||||
sodipodi:docname="speaker.svg"
|
||||
inkscape:version="0.92.2 5c3e80d, 2017-08-06">
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#de43da"
|
||||
pagecolor="#4cc5a0"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="19.289873"
|
||||
inkscape:cx="-2.0603844"
|
||||
inkscape:cy="14.079113"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
inkscape:window-width="1868"
|
||||
inkscape:window-height="1049"
|
||||
id="namedview8"
|
||||
showgrid="false"
|
||||
inkscape:window-width="1918"
|
||||
inkscape:window-height="1040"
|
||||
fit-margin-top="0"
|
||||
fit-margin-left="0"
|
||||
fit-margin-right="0"
|
||||
fit-margin-bottom="0"
|
||||
inkscape:zoom="13.350176"
|
||||
inkscape:cx="0.054475841"
|
||||
inkscape:cy="20.133193"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="19"
|
||||
inkscape:window-maximized="0">
|
||||
<sodipodi:guide
|
||||
position="0,0"
|
||||
orientation="0,25"
|
||||
id="guide4151" />
|
||||
<sodipodi:guide
|
||||
position="25,0"
|
||||
orientation="-25,0"
|
||||
id="guide4153" />
|
||||
<sodipodi:guide
|
||||
position="25,25"
|
||||
orientation="0,-25"
|
||||
id="guide4155" />
|
||||
<sodipodi:guide
|
||||
position="0,25"
|
||||
orientation="25,0"
|
||||
id="guide4157" />
|
||||
</sodipodi:namedview>
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="0"
|
||||
inkscape:current-layer="svg4659" />
|
||||
<defs
|
||||
id="defs4661" />
|
||||
<metadata
|
||||
id="metadata4664">
|
||||
<rdf:RDF>
|
||||
|
@ -65,19 +52,18 @@
|
|||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(0,-1027.3622)">
|
||||
transform="matrix(1.8,0,0,1.8,0,-1849.252)"
|
||||
id="layer1">
|
||||
<path
|
||||
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||
d="M 0 0 L 0 25 L 25 25 L 25 0 L 0 0 z M 16.955078 2.5175781 C 17.381507 2.5360023 17.80574 2.6612 18.1875 2.890625 L 18.1875 22.109375 C 17.169206 22.722675 15.85386 22.587487 14.980469 21.679688 L 10.681641 17.210938 L 8.7832031 17.210938 C 7.6978331 17.210938 6.8125 16.290409 6.8125 15.162109 L 6.8125 9.8359375 C 6.8125 8.7077375 7.6978331 7.7890625 8.7832031 7.7890625 L 10.681641 7.7890625 L 14.980469 3.3183594 C 15.526019 2.7512344 16.244363 2.4868711 16.955078 2.5175781 z "
|
||||
id="rect4139"
|
||||
transform="translate(0,1027.3622)"
|
||||
id="rect4139" />
|
||||
d="M 0,0 V 25 H 25 V 0 Z M 16.955078,2.5175781 C 17.381507,2.5360023 17.80574,2.6612 18.1875,2.890625 v 19.21875 c -1.018294,0.6133 -2.33364,0.478112 -3.207031,-0.429687 l -4.298828,-4.46875 H 8.7832031 c -1.08537,0 -1.9707031,-0.920529 -1.9707031,-2.048829 V 9.8359375 c 0,-1.1282 0.8853331,-2.046875 1.9707031,-2.046875 h 1.8984379 l 4.298828,-4.4707031 c 0.54555,-0.567125 1.263894,-0.8314883 1.974609,-0.8007813 z"
|
||||
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:1.5;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 18.187674,1030.2531 c -1.018026,-0.6118 -2.333715,-0.479 -3.206595,0.4284 l -4.299344,4.4691 -1.8988757,0 c -1.0853708,0 -1.9705331,0.9201 -1.9705331,2.0483 l 0,5.3258 c 0,1.1283 0.8851623,2.0484 1.9705331,2.0484 l 1.8988757,0 4.299344,4.4693 c 0.873391,0.9078 2.188301,1.0415 3.206595,0.4282 l 0,-19.2175 z"
|
||||
id="rect4574"
|
||||
d="m 18.187674,1030.2531 c -1.018026,-0.6118 -2.333715,-0.479 -3.206595,0.4284 l -4.299344,4.4691 H 8.7828593 c -1.0853708,0 -1.9705331,0.9201 -1.9705331,2.0483 v 5.3258 c 0,1.1283 0.8851623,2.0484 1.9705331,2.0484 h 1.8988757 l 4.299344,4.4693 c 0.873391,0.9078 2.188301,1.0415 3.206595,0.4282 z"
|
||||
style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:1.5;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
</svg>
|
||||
|
|
Before Width: | Height: | Size: 3.6 KiB After Width: | Height: | Size: 3.2 KiB |
59
embed/imgs/speaker_.svg
Normal file
|
@ -0,0 +1,59 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
version="1.1"
|
||||
id="svg4659"
|
||||
height="45"
|
||||
width="45"
|
||||
sodipodi:docname="speaker_.svg"
|
||||
inkscape:version="0.92.2 5c3e80d, 2017-08-06">
|
||||
<sodipodi:namedview
|
||||
pagecolor="#4cc5a0"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1868"
|
||||
inkscape:window-height="1049"
|
||||
id="namedview8"
|
||||
showgrid="false"
|
||||
fit-margin-top="0"
|
||||
fit-margin-left="0"
|
||||
fit-margin-right="0"
|
||||
fit-margin-bottom="0"
|
||||
inkscape:zoom="6.675088"
|
||||
inkscape:cx="-34.245466"
|
||||
inkscape:cy="20.740429"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="0"
|
||||
inkscape:current-layer="svg4659" />
|
||||
<defs
|
||||
id="defs4661" />
|
||||
<metadata
|
||||
id="metadata4664">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:3.81837654;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 32.737813,5.2037363 c -1.832447,-1.10124 -4.200687,-0.8622 -5.771871,0.77112 0,0 -7.738819,8.0443797 -7.738819,8.0443797 0,0 -3.417976,0 -3.417976,0 -1.953668,0 -3.54696,1.65618 -3.54696,3.68694 0,0 0,9.58644 0,9.58644 0,2.03094 1.593292,3.68712 3.54696,3.68712 0,0 3.417976,0 3.417976,0 0,0 7.738819,8.04474 7.738819,8.04474 1.572104,1.63404 3.938942,1.8747 5.771871,0.77076 0,0 0,-34.5914997 0,-34.5914997 z"
|
||||
id="rect4574-3" />
|
||||
</svg>
|
After Width: | Height: | Size: 2.1 KiB |
|
@ -1 +1 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?><svg xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" version="1.1" id="svg4659" height="25" width="25"> <defs id="defs4661" /> <metadata id="metadata4664"> <rdf:RDF> <cc:Work rdf:about=""> <dc:format>image/svg+xml</dc:format> <dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> <dc:title></dc:title> </cc:Work> </rdf:RDF> </metadata> <g transform="translate(0,-1027.3622)" id="layer1"> <path id="rect4139" transform="translate(0,1027.3622)" d="M 0 0 L 0 25 L 25 25 L 25 0 L 0 0 z M 16.955078 2.5175781 C 17.381507 2.5360023 17.80574 2.6612 18.1875 2.890625 L 18.1875 22.109375 C 17.169206 22.722675 15.85386 22.587487 14.980469 21.679688 L 10.681641 17.210938 L 8.7832031 17.210938 C 7.6978331 17.210938 6.8125 16.290409 6.8125 15.162109 L 6.8125 9.8359375 C 6.8125 8.7077375 7.6978331 7.7890625 8.7832031 7.7890625 L 10.681641 7.7890625 L 14.980469 3.3183594 C 15.526019 2.7512344 16.244363 2.4868711 16.955078 2.5175781 z " style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" /> <path id="rect4574" d="m 18.187674,1030.2531 c -1.018026,-0.6118 -2.333715,-0.479 -3.206595,0.4284 l -4.299344,4.4691 -1.8988757,0 c -1.0853708,0 -1.9705331,0.9201 -1.9705331,2.0483 l 0,5.3258 c 0,1.1283 0.8851623,2.0484 1.9705331,2.0484 l 1.8988757,0 4.299344,4.4693 c 0.873391,0.9078 2.188301,1.0415 3.206595,0.4282 l 0,-19.2175 z" style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:1.5;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> </g></svg>
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?><svg xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" version="1.1" id="svg4659" height="25" width="25"> <defs id="defs4661" /> <metadata id="metadata4664"> <rdf:RDF> <cc:Work rdf:about=""> <dc:format>image/svg+xml</dc:format> <dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> <dc:title></dc:title> </cc:Work> </rdf:RDF> </metadata> <path d="m 32.737813,5.2037363 c -1.832447,-1.10124 -4.200687,-0.8622 -5.771871,0.77112 0,0 -7.738819,8.0443797 -7.738819,8.0443797 0,0 -3.417976,0 -3.417976,0 -1.953668,0 -3.54696,1.65618 -3.54696,3.68694 0,0 0,9.58644 0,9.58644 0,2.03094 1.593292,3.68712 3.54696,3.68712 0,0 3.417976,0 3.417976,0 0,0 7.738819,8.04474 7.738819,8.04474 1.572104,1.63404 3.938942,1.8747 5.771871,0.77076 0,0 0,-34.5914997 0,-34.5914997 z" class="stroke semiFill toggle"></path></svg>
|
||||
|
|
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 1 KiB |
4
embed/imgs/switchvideo.svg
Normal file
|
@ -0,0 +1,4 @@
|
|||
<svg width="45" height="45" version="1.1" viewBox="0 0 45 45" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="m8.4925 18.786c-3.9578 1.504-6.4432 3.632-6.4434 5.9982 2.183e-4 4.1354 7.5562 7.5509 17.399 8.1467v4.7777l10.718-6.2573-10.718-6.2529v4.5717c-6.9764-0.4712-12.229-2.5226-12.227-4.9859 6.693e-4 -0.72127 0.45868-1.4051 1.2714-2.0267zm28.015 0v3.9715c0.81164 0.62126 1.2685 1.3059 1.2692 2.0267-0.0014 1.4217-1.791 2.75-4.8021 3.6968-2.0515 0.82484-0.93693 3.7696 1.2249 2.9659 5.3088-1.8593 8.7426-3.8616 8.7514-6.6627-1.26e-4 -2.3662-2.4856-4.4942-6.4434-5.9982z"/>
|
||||
<rect x="10.166" y="7.7911" width="24.668" height="15.432" fill="none" stroke="#000" stroke-linecap="round"/>
|
||||
</svg>
|
After Width: | Height: | Size: 694 B |
19
embed/imgs/timeout.svg
Normal file
|
@ -0,0 +1,19 @@
|
|||
<svg width="25" height="25" version="1.1" viewBox="0 0 25 25" xmlns="http://www.w3.org/2000/svg">
|
||||
<defs>
|
||||
<mask id="a">
|
||||
<rect x="0" y="0" width="25" height="25" fill="#fff"/>
|
||||
<rect x="-5" y="-5" width="17.5" height="35" fill="#000" transform="rotate(180,12.5,12.5)">
|
||||
<animateTransform attributeName="transform" type="rotate" from="0,12.5,12.5" to="180,12.5,12.5" dur="5" repeatCount="1"/>
|
||||
</rect>
|
||||
<rect x="0" y="0" width="12.5" height="25" fill="#fff"/>
|
||||
<rect x="-5" y="-5" width="17.5" height="35" fill="#000" transform="rotate(360,12.5,12.5)">
|
||||
<animate attributeType="CSS" attributeName="opacity" from="0" to="1" dur="10" calcMode="discrete" repeatCount="1" />
|
||||
<animateTransform attributeName="transform" type="rotate" from="180,12.5,12.5" to="360,12.5,12.5" begin="5" dur="5" repeatCount="1"/>
|
||||
</rect>
|
||||
<circle cx="12.5" cy="12.5" r="8" fill="#000"/>
|
||||
</mask>
|
||||
</defs>
|
||||
<g mask="url(#a)">
|
||||
<circle cx="12.5" cy="12.5" r="12.5" class="fill"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1 KiB |
|
@ -9,14 +9,25 @@
|
|||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="30"
|
||||
height="65"
|
||||
width="65.000015"
|
||||
height="30"
|
||||
id="svg3937"
|
||||
version="1.1"
|
||||
inkscape:version="0.91 r13725"
|
||||
inkscape:version="0.92.2 5c3e80d, 2017-08-06"
|
||||
sodipodi:docname="volume.svg">
|
||||
<defs
|
||||
id="defs3939" />
|
||||
id="defs3939">
|
||||
<mask
|
||||
maskUnits="userSpaceOnUse"
|
||||
id="mask4516">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4518"
|
||||
d="m -14.830002,1027.1553 58.614316,-18.8626 c 1.795162,-0.5777 3.231854,0.5139 3.231854,2.1982 v 19.0111 c 0,1.3165 -1.098401,2.3764 -2.462782,2.3764 h -59.106775 c -2.946621,0 -3.449835,-3.6727 -0.276613,-4.7231 z"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.96767992;stroke-opacity:1"
|
||||
sodipodi:nodetypes="cccsscc" />
|
||||
</mask>
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#dc39f7"
|
||||
|
@ -24,16 +35,16 @@
|
|||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="4"
|
||||
inkscape:cx="-36.653402"
|
||||
inkscape:cy="38.029112"
|
||||
inkscape:zoom="14.580651"
|
||||
inkscape:cx="30.208524"
|
||||
inkscape:cy="17.533448"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
inkscape:snap-bbox="true"
|
||||
inkscape:bbox-paths="false"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1055"
|
||||
inkscape:window-width="1868"
|
||||
inkscape:window-height="1049"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
|
@ -41,7 +52,13 @@
|
|||
inkscape:object-paths="true"
|
||||
inkscape:snap-page="true"
|
||||
inkscape:snap-global="true"
|
||||
borderlayer="true" />
|
||||
borderlayer="true"
|
||||
fit-margin-top="0"
|
||||
fit-margin-left="0"
|
||||
fit-margin-right="0"
|
||||
fit-margin-bottom="0"
|
||||
showguides="true"
|
||||
inkscape:guide-bbox="true" />
|
||||
<metadata
|
||||
id="metadata3942">
|
||||
<rdf:RDF>
|
||||
|
@ -50,7 +67,7 @@
|
|||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
|
@ -58,16 +75,20 @@
|
|||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(0,-987.3622)">
|
||||
transform="translate(17.50001,-1004.8622)">
|
||||
<path
|
||||
style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;marker:none;enable-background:accumulate"
|
||||
d="m 0,1052.3622 0,-65 5,0 c -0.172588,0 -0.337256,0.0295 -0.5,0.0625 -0.489111,0.1 -0.942345,0.31725 -1.28125,0.65625 -0.226206,0.2262 -0.404743,0.5135 -0.53125,0.8125 -0.126507,0.2991 -0.1875,0.62365 -0.1875,0.96875 0,0 0.075978,0.44705 0.1875,0.78125 l 19.84375,59.49995 c 0.142777,1.2451 1.185414,2.2188 2.46875,2.2188 l -25,0 z m 25,0 c 0.877549,0 1.647663,-0.441 2.09375,-1.125 0.06381,-0.098 0.1062,-0.2046 0.15625,-0.3125 0.02962,-0.062 0.06926,-0.1225 0.09375,-0.1875 0.04501,-0.1212 0.06741,-0.2459 0.09375,-0.375 0.009,-0.044 0.02457,-0.08 0.03125,-0.125 0.01878,-0.1235 0.03125,-0.2462 0.03125,-0.375 l 0,-60 c 0,-1.385 -1.114999,-2.5 -2.5,-2.5 l 5,0 0,65 -5,0 z"
|
||||
id="rect4674"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:none"
|
||||
d="m 25,1052.3617 c -1.283336,0 -2.325973,-0.9737 -2.46875,-2.2187 L 2.6875,990.6429 C 2.575978,990.3087 2.5,989.8617 2.5,989.8617 c 0,-0.3451 0.060993,-0.6697 0.1875,-0.9688 0.126507,-0.299 0.305044,-0.5863 0.53125,-0.8125 0.338905,-0.339 0.792139,-0.5562 1.28125,-0.6562 0.162744,-0.033 0.327412,-0.062 0.5,-0.062 l 20,0 c 1.385001,0 2.5,1.115 2.5,2.5 l 0,60 c 0,0.1288 -0.01247,0.2515 -0.03125,0.375 -0.0067,0.045 -0.02225,0.081 -0.03125,0.125 -0.02634,0.1292 -0.04874,0.2538 -0.09375,0.375 -0.02449,0.065 -0.06413,0.1252 -0.09375,0.1875 -0.05005,0.1079 -0.09244,0.2145 -0.15625,0.3125 -0.446087,0.684 -1.216201,1.125 -2.09375,1.125 z m 0,-1.2187 c 0.474106,0 0.864734,-0.2114 1.09375,-0.5625 -0.02112,0.032 -0.0059,-0.01 0.0625,-0.1563 a 1.204452,1.204452 0 0 1 0,-0.031 c 0.0235,-0.049 0.05198,-0.052 0.0625,-0.062 0.0055,-0.016 0.0094,-0.035 0,-0.031 0.0017,-0.01 0.0055,-0.061 0.03125,-0.1875 0.008,-0.039 0.02555,-0.039 0.03125,-0.062 0.0098,-0.066 0.0055,-0.1027 0,-0.094 -0.0016,-0.03 0,-0.068 0,-0.094 l 0,-60 c 0,-0.7386 -0.542617,-1.2813 -1.28125,-1.2813 l -20,0 c -0.035353,0 -0.105322,0 -0.25,0.031 -0.296863,0.061 -0.546343,0.1713 -0.6875,0.3125 -0.089394,0.089 -0.205263,0.258 -0.28125,0.4375 -0.055315,0.1308 -0.058661,0.2832 -0.0625,0.4687 -2.52e-4,0.012 0,0.019 0,0.031 0.027982,0.1353 0.082499,0.2789 0.125,0.4062 l 19.84375,59.5005 a 1.204452,1.204452 0 0 1 0.03125,0.25 c 0.07527,0.6564 0.607054,1.125 1.28125,1.125 z"
|
||||
id="path4697-6"
|
||||
inkscape:connector-curvature="0" />
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4505"
|
||||
d="m -14.830002,1027.1553 58.614316,-18.8626 c 1.795162,-0.5777 3.231854,0.5139 3.231854,2.1982 v 19.0111 c 0,1.3165 -1.098401,2.3764 -2.462782,2.3764 h -59.106775 c -2.946621,0 -3.449835,-3.6727 -0.276613,-4.7231 z"
|
||||
style="fill:none;fill-opacity:1;stroke:#fdfdfd;stroke-width:0.96767992;stroke-opacity:1"
|
||||
sodipodi:nodetypes="cccsscc" />
|
||||
<rect
|
||||
style="opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:0.60986549;stroke:none;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||
id="rect4507"
|
||||
width="33.400429"
|
||||
height="30"
|
||||
x="-17.50001"
|
||||
y="1004.8622"
|
||||
mask="url(#mask4516)" />
|
||||
</g>
|
||||
</svg>
|
||||
|
|
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 3.3 KiB |
|
@ -1,38 +1,11 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
version="1.1"
|
||||
id="svg3937"
|
||||
height="65"
|
||||
width="30">
|
||||
<defs
|
||||
id="defs3939" />
|
||||
<metadata
|
||||
id="metadata3942">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
transform="translate(0,-987.3622)"
|
||||
id="layer1">
|
||||
<path
|
||||
id="rect4674"
|
||||
d="m 0,1052.3622 0,-65 5,0 c -0.172588,0 -0.337256,0.0295 -0.5,0.0625 -0.489111,0.1 -0.942345,0.31725 -1.28125,0.65625 -0.226206,0.2262 -0.404743,0.5135 -0.53125,0.8125 -0.126507,0.2991 -0.1875,0.62365 -0.1875,0.96875 0,0 0.075978,0.44705 0.1875,0.78125 l 19.84375,59.49995 c 0.142777,1.2451 1.185414,2.2188 2.46875,2.2188 l -25,0 z m 25,0 c 0.877549,0 1.647663,-0.441 2.09375,-1.125 0.06381,-0.098 0.1062,-0.2046 0.15625,-0.3125 0.02962,-0.062 0.06926,-0.1225 0.09375,-0.1875 0.04501,-0.1212 0.06741,-0.2459 0.09375,-0.375 0.009,-0.044 0.02457,-0.08 0.03125,-0.125 0.01878,-0.1235 0.03125,-0.2462 0.03125,-0.375 l 0,-60 c 0,-1.385 -1.114999,-2.5 -2.5,-2.5 l 5,0 0,65 -5,0 z"
|
||||
style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;marker:none;enable-background:accumulate" />
|
||||
<path
|
||||
id="path4697-6"
|
||||
d="m 25,1052.3617 c -1.283336,0 -2.325973,-0.9737 -2.46875,-2.2187 L 2.6875,990.6429 C 2.575978,990.3087 2.5,989.8617 2.5,989.8617 c 0,-0.3451 0.060993,-0.6697 0.1875,-0.9688 0.126507,-0.299 0.305044,-0.5863 0.53125,-0.8125 0.338905,-0.339 0.792139,-0.5562 1.28125,-0.6562 0.162744,-0.033 0.327412,-0.062 0.5,-0.062 l 20,0 c 1.385001,0 2.5,1.115 2.5,2.5 l 0,60 c 0,0.1288 -0.01247,0.2515 -0.03125,0.375 -0.0067,0.045 -0.02225,0.081 -0.03125,0.125 -0.02634,0.1292 -0.04874,0.2538 -0.09375,0.375 -0.02449,0.065 -0.06413,0.1252 -0.09375,0.1875 -0.05005,0.1079 -0.09244,0.2145 -0.15625,0.3125 -0.446087,0.684 -1.216201,1.125 -2.09375,1.125 z m 0,-1.2187 c 0.474106,0 0.864734,-0.2114 1.09375,-0.5625 -0.02112,0.032 -0.0059,-0.01 0.0625,-0.1563 a 1.204452,1.204452 0 0 1 0,-0.031 c 0.0235,-0.049 0.05198,-0.052 0.0625,-0.062 0.0055,-0.016 0.0094,-0.035 0,-0.031 0.0017,-0.01 0.0055,-0.061 0.03125,-0.1875 0.008,-0.039 0.02555,-0.039 0.03125,-0.062 0.0098,-0.066 0.0055,-0.1027 0,-0.094 -0.0016,-0.03 0,-0.068 0,-0.094 l 0,-60 c 0,-0.7386 -0.542617,-1.2813 -1.28125,-1.2813 l -20,0 c -0.035353,0 -0.105322,0 -0.25,0.031 -0.296863,0.061 -0.546343,0.1713 -0.6875,0.3125 -0.089394,0.089 -0.205263,0.258 -0.28125,0.4375 -0.055315,0.1308 -0.058661,0.2832 -0.0625,0.4687 -2.52e-4,0.012 0,0.019 0,0.031 0.027982,0.1353 0.082499,0.2789 0.125,0.4062 l 19.84375,59.5005 a 1.204452,1.204452 0 0 1 0.03125,0.25 c 0.07527,0.6564 0.607054,1.125 1.28125,1.125 z"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:none" />
|
||||
<svg width="100" height="45" version="1.1" xmlns="http://www.w3.org/2000/svg">
|
||||
<defs>
|
||||
<mask id="a" maskUnits="userSpaceOnUse">
|
||||
<rect width="57.288" height="30" fill="#fff" fill-opacity=".74439"/>
|
||||
</mask>
|
||||
</defs>
|
||||
<path d="m6.202 33.254 86.029-28.394c2.6348-0.86966 4.7433 0.77359 4.7433 3.3092v28.617c0 1.9819-1.6122 3.5773-3.6147 3.5773h-86.75c-4.3249 0-5.0634-5.5287-0.40598-7.1098" fill="none" stroke="#fdfdfd" stroke-width="6.0417"/>
|
||||
<g transform="translate(16.609 9.9991)" fill="#fff" mask="url(#a)">
|
||||
<path d="m4.2605 21.935 55.47-18.308c1.6989-0.56074 3.0584 0.4988 3.0584 2.1337v18.452c0 1.2779-1.0395 2.3066-2.3307 2.3066h-55.935c-2.7886 0-3.2648-3.5648-0.26177-4.5843" fill="#fff"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
|
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 731 B |
6
embed/imgs/volume_rect_dot_plain.svg
Normal file
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="100" height="50" version="1.1" viewBox="0 0 100 50" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect y="21" width="100" height="8" fill="#fff"/>
|
||||
<ellipse cx="50" cy="25" rx="10" ry="10" fill="#008000"/>
|
||||
<rect y="21" width="50" height="8" fill="#008000"/>
|
||||
</svg>
|
After Width: | Height: | Size: 312 B |
1
embed/min/player.js
Normal file
92
embed/min/skins/default.css
Normal file
|
@ -0,0 +1,92 @@
|
|||
.mistvideo{display:inline-block;position:relative;color:$stroke;font-family:sans-serif;background-color:#000;justify-content:center;align-items:center}
|
||||
.mistvideo-controls{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}
|
||||
.mistvideo.novideo{overflow:visible}
|
||||
.mistvideo-video{overflow:hidden}
|
||||
svg.icon.loading{z-index:-1;position:absolute;top:0;left:0;right:0;bottom:0;margin:auto;opacity:0}
|
||||
[data-loading]{position:relative}
|
||||
[data-loading=stalled] svg.icon.loading{transition:opacity 0s 3s}
|
||||
[data-loading] svg.icon.loading{z-index:2;opacity:1}
|
||||
[data-loading-css] .mistvideo-controls{display:none}
|
||||
[data-hidecursor],[data-hidecursor] *,[data-hidecursor] .mistvideo-pointer{cursor:none}
|
||||
.mistvideo-error{display:none;position:absolute;top:0;left:0;right:0;bottom:0;background-color:$background;align-items:center;justify-content:center;text-align:center;z-index:2;cursor:default;min-height:fit-content;min-width:fit-content}
|
||||
.mistvideo-error.show{display:flex}
|
||||
.mistvideo-error .message{max-width:80%}
|
||||
.mistvideo-error .message .details table{text-align:left}
|
||||
.mistvideo-controls button,.mistvideo-error button,.mistvideo-video:not(.video-js) button{color:$stroke;border:1px solid $semiFill;background-color:$background;margin:.25em;padding:.5em 1em;opacity:.5;cursor:pointer}
|
||||
button:hover{opacity:1}
|
||||
select{background-color:transparent;color:$stroke;border:none;margin:0 .5em;font-size:inherit;cursor:pointer;-ms-background-color:red}
|
||||
select>option{background-color:$background}
|
||||
.browser-edge select,.browser-safari select{border:1px solid $semiFill;border-top:none;border-left:none;margin-top:2px}
|
||||
@keyframes spin{
|
||||
0%{transform:rotate(0)}
|
||||
100%{transform:rotate(360deg)}
|
||||
}
|
||||
[data-fullscreen]{position:fixed;top:0;left:0;right:0;bottom:0;width:100%!important;height:100%!important}
|
||||
video{display:block;flex-shrink:0}
|
||||
table{color:inherit;font-size:inherit;font-style:inherit}
|
||||
audio:not([controls]){display:block!important}
|
||||
.mistvideo-padding{padding:5px 10px}
|
||||
.mistvideo-pointer{cursor:pointer}
|
||||
.description{color:$semiFill;font-size:.9em}
|
||||
.mistvideo-container{display:flex;flex-wrap:nowrap}
|
||||
.mistvideo-container.mistvideo{display:inline-flex;max-width:100%}
|
||||
.mistvideo-container.mistvideo-row{flex-direction:row}
|
||||
.mistvideo-container.mistvideo-column{flex-direction:column}
|
||||
.mistvideo-container.mistvideo-center{justify-content:center}
|
||||
.mistvideo-align-right{margin-left:auto;margin-right:0}
|
||||
.hover_window_container.pos>.outer_window{position:absolute;pointer-events:none;overflow:hidden}
|
||||
.hover_window_container.pos>.outer_window>.inner_window{position:absolute;pointer-events:all}
|
||||
.hover_window_container:not(:hover)>.outer_window>.inner_window,.hover_window_container>.outer_window[data-hidecursor]>.inner_window{transition:all .5s ease-in .5s}
|
||||
.outer_window>.inner_window{flex-grow:1}
|
||||
.hover_window_container>.outer_window>.inner_window>*{flex-shrink:0}
|
||||
.mistvideo-draggable{overflow:hidden}
|
||||
.mistvideo-tooltip{position:absolute;background-color:$background;padding:.5em 1em;z-index:2}
|
||||
:not(:hover)>.mistvideo-tooltip{transition:opacity .25s ease-in}
|
||||
.mistvideo-tooltip .triangle{border:10px solid $background;position:absolute}
|
||||
.mistvideo-tracks label{display:block}
|
||||
.mistvideo-tracks label>span{margin-right:1em}
|
||||
a{color:$accent}
|
||||
.mistvideo-log .logs{-webkit-user-select:text;-moz-user-select:text;-ms-user-select:text;user-select:text}
|
||||
.mistvideo-placeholder{max-width:100%;max-height:100%}
|
||||
.mistvideo-topright{position:absolute;top:0;right:0}
|
||||
.mistvideo-topleft{position:absolute;top:0;left:0}
|
||||
.mistvideo-delay-display{animation:appear 1s;animation-iteration-count:1;animation-timing-function:steps(1,end)}
|
||||
@keyframes appear{
|
||||
from{opacity:0}
|
||||
to{opacity:1}
|
||||
}
|
||||
svg.icon{display:block;stroke-width:$strokeWidth;fill:none;stroke:none}
|
||||
svg.icon .fill,svg.icon.fill{fill:$fill}
|
||||
svg.icon .semiFill,svg.icon.semiFill{fill:$semiFill}
|
||||
svg.icon .stroke,svg.icon.stroke{stroke:$stroke;vector-effect:non-scaling-stroke}
|
||||
svg.icon.off .toggle .fill,svg.icon.off .toggle .semiFill,svg.icon.off .toggle.fill,svg.icon.off .toggle.semiFill{fill:none}
|
||||
svg.icon .spin,svg.icon.spin{animation:spin 1.5s infinite linear;transform-origin:50% 50%}
|
||||
.mistvideo{line-height:1.2;font-size:14.5px}
|
||||
.mistvideo svg{margin:2.5px}
|
||||
.mistvideo-background{background-color:$background}
|
||||
.mistvideo-totalTime:before{content:'/';margin:.2em}
|
||||
.mistvideo-progress{padding:10px 0;margin:-10px 0;z-index:2}
|
||||
.mistvideo-progress>*{height:2px;background-color:$progressBackground;opacity:.95;position:relative}
|
||||
.mistvideo-novideo .mistvideo-progress>*,.mistvideo-progress:hover>*{height:10px}
|
||||
.mistvideo-progress:not(:hover)>*{transition:height .25s ease-in .5s}
|
||||
.mistvideo-progress .bar{height:inherit;width:0;position:absolute;border-right:inherit;background-color:$accent;z-index:2}
|
||||
.mistvideo-progress .buffer{height:inherit;width:0;position:absolute;background-color:$semiFill}
|
||||
.mistvideo-progress .bar:after{content:'';border:5px solid $accent;border-radius:5px;position:absolute;right:-5px;top:50%;transform:translateY(-50%)}
|
||||
.mistvideo-play[data-state=playing] svg.play{display:none}
|
||||
.mistvideo-play[data-state=paused] svg.pause{display:none}
|
||||
.mistvideo-main{align-items:center}
|
||||
svg.icon.timeout{display:inline-block;height:1em;width:1em;margin:0;margin-right:.25em;vertical-align:top}
|
||||
.mist.largeplay,.mist.muted{position:absolute;opacity:.5}
|
||||
.mist.largeplay{top:50%;left:0;right:0;margin:auto;transform:translateY(-50%)}
|
||||
.mist.muted{top:0;right:0;margin:1em}
|
||||
.mistvideo-secondaryVideo{z-index:1;width:50%;height:50%}
|
||||
.mistvideo-polling{display:inline-block;position:relative;width:25px;height:25px}
|
||||
.mistvideo-polling svg.icon.loading{z-index:0;opacity:1}
|
||||
.mistvideo[data-show-submenu] .mistvideo-submenu{right:5px}
|
||||
.mistvideo[data-show-submenu] .mistvideo-controls{bottom:0}
|
||||
.mistvideo-error[data-passive]{bottom:auto;left:auto;margin:.5em;padding:.5em}
|
||||
.mistvideo-error[data-passive] .message{max-width:none}
|
||||
.mistvideo-error .mistvideo-buttoncontainer{display:flex;flex-flow:row nowrap;justify-content:center}
|
||||
.mistvideo-error .mistvideo-buttoncontainer .mistvideo-button{white-space:nowrap}
|
||||
.browser-ie .mist.icon.loading{animation:spin 1.5s infinite linear;transform-origin:50% 50%}
|
||||
.browser-ie .mist.icon.loading .spin{animation:none}
|
116
embed/min/skins/dev.css
Normal file
|
@ -0,0 +1,116 @@
|
|||
.mistvideo{display:inline-block;position:relative;color:$stroke;font-family:sans-serif;background-color:#000;justify-content:center;align-items:center}
|
||||
.mistvideo-controls{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}
|
||||
.mistvideo.novideo{overflow:visible}
|
||||
.mistvideo-video{overflow:hidden}
|
||||
svg.icon.loading{z-index:-1;position:absolute;top:0;left:0;right:0;bottom:0;margin:auto;opacity:0}
|
||||
[data-loading]{position:relative}
|
||||
[data-loading=stalled] svg.icon.loading{transition:opacity 0s 3s}
|
||||
[data-loading] svg.icon.loading{z-index:2;opacity:1}
|
||||
[data-loading-css] .mistvideo-controls{display:none}
|
||||
[data-hidecursor],[data-hidecursor] *,[data-hidecursor] .mistvideo-pointer{cursor:none}
|
||||
.mistvideo-error{display:none;position:absolute;top:0;left:0;right:0;bottom:0;background-color:$background;align-items:center;justify-content:center;text-align:center;z-index:2;cursor:default;min-height:fit-content;min-width:fit-content}
|
||||
.mistvideo-error.show{display:flex}
|
||||
.mistvideo-error .message{max-width:80%}
|
||||
.mistvideo-error .message .details table{text-align:left}
|
||||
.mistvideo-controls button,.mistvideo-error button,.mistvideo-video:not(.video-js) button{color:$stroke;border:1px solid $semiFill;background-color:$background;margin:.25em;padding:.5em 1em;opacity:.5;cursor:pointer}
|
||||
button:hover{opacity:1}
|
||||
select{background-color:transparent;color:$stroke;border:none;margin:0 .5em;font-size:inherit;cursor:pointer;-ms-background-color:red}
|
||||
select>option{background-color:$background}
|
||||
.browser-edge select,.browser-safari select{border:1px solid $semiFill;border-top:none;border-left:none;margin-top:2px}
|
||||
@keyframes spin{
|
||||
0%{transform:rotate(0)}
|
||||
100%{transform:rotate(360deg)}
|
||||
}
|
||||
[data-fullscreen]{position:fixed;top:0;left:0;right:0;bottom:0;width:100%!important;height:100%!important}
|
||||
video{display:block;flex-shrink:0}
|
||||
table{color:inherit;font-size:inherit;font-style:inherit}
|
||||
audio:not([controls]){display:block!important}
|
||||
.mistvideo-padding{padding:5px 10px}
|
||||
.mistvideo-pointer{cursor:pointer}
|
||||
.description{color:$semiFill;font-size:.9em}
|
||||
.mistvideo-container{display:flex;flex-wrap:nowrap}
|
||||
.mistvideo-container.mistvideo{display:inline-flex;max-width:100%}
|
||||
.mistvideo-container.mistvideo-row{flex-direction:row}
|
||||
.mistvideo-container.mistvideo-column{flex-direction:column}
|
||||
.mistvideo-container.mistvideo-center{justify-content:center}
|
||||
.mistvideo-align-right{margin-left:auto;margin-right:0}
|
||||
.hover_window_container.pos>.outer_window{position:absolute;pointer-events:none;overflow:hidden}
|
||||
.hover_window_container.pos>.outer_window>.inner_window{position:absolute;pointer-events:all}
|
||||
.hover_window_container:not(:hover)>.outer_window>.inner_window,.hover_window_container>.outer_window[data-hidecursor]>.inner_window{transition:all .5s ease-in .5s}
|
||||
.outer_window>.inner_window{flex-grow:1}
|
||||
.hover_window_container>.outer_window>.inner_window>*{flex-shrink:0}
|
||||
.mistvideo-draggable{overflow:hidden}
|
||||
.mistvideo-tooltip{position:absolute;background-color:$background;padding:.5em 1em;z-index:2}
|
||||
:not(:hover)>.mistvideo-tooltip{transition:opacity .25s ease-in}
|
||||
.mistvideo-tooltip .triangle{border:10px solid $background;position:absolute}
|
||||
.mistvideo-tracks label{display:block}
|
||||
.mistvideo-tracks label>span{margin-right:1em}
|
||||
a{color:$accent}
|
||||
.mistvideo-log .logs{-webkit-user-select:text;-moz-user-select:text;-ms-user-select:text;user-select:text}
|
||||
.mistvideo-placeholder{max-width:100%;max-height:100%}
|
||||
.mistvideo-topright{position:absolute;top:0;right:0}
|
||||
.mistvideo-topleft{position:absolute;top:0;left:0}
|
||||
.mistvideo-delay-display{animation:appear 1s;animation-iteration-count:1;animation-timing-function:steps(1,end)}
|
||||
@keyframes appear{
|
||||
from{opacity:0}
|
||||
to{opacity:1}
|
||||
}
|
||||
svg.icon{display:block;stroke-width:$strokeWidth;fill:none;stroke:none}
|
||||
svg.icon .fill,svg.icon.fill{fill:$fill}
|
||||
svg.icon .semiFill,svg.icon.semiFill{fill:$semiFill}
|
||||
svg.icon .stroke,svg.icon.stroke{stroke:$stroke;vector-effect:non-scaling-stroke}
|
||||
svg.icon.off .toggle .fill,svg.icon.off .toggle .semiFill,svg.icon.off .toggle.fill,svg.icon.off .toggle.semiFill{fill:none}
|
||||
svg.icon .spin,svg.icon.spin{animation:spin 1.5s infinite linear;transform-origin:50% 50%}
|
||||
.mistvideo{line-height:1.2;font-size:14.5px}
|
||||
.mistvideo svg{margin:2.5px}
|
||||
.mistvideo-background{background-color:$background}
|
||||
.mistvideo-totalTime:before{content:'/';margin:.2em}
|
||||
.mistvideo-progress{padding:10px 0;margin:-10px 0;z-index:2}
|
||||
.mistvideo-progress>*{height:2px;background-color:$progressBackground;opacity:.95;position:relative}
|
||||
.mistvideo-novideo .mistvideo-progress>*,.mistvideo-progress:hover>*{height:10px}
|
||||
.mistvideo-progress:not(:hover)>*{transition:height .25s ease-in .5s}
|
||||
.mistvideo-progress .bar{height:inherit;width:0;position:absolute;border-right:inherit;background-color:$accent;z-index:2}
|
||||
.mistvideo-progress .buffer{height:inherit;width:0;position:absolute;background-color:$semiFill}
|
||||
.mistvideo-progress .bar:after{content:'';border:5px solid $accent;border-radius:5px;position:absolute;right:-5px;top:50%;transform:translateY(-50%)}
|
||||
.mistvideo-play[data-state=playing] svg.play{display:none}
|
||||
.mistvideo-play[data-state=paused] svg.pause{display:none}
|
||||
.mistvideo-main{align-items:center}
|
||||
svg.icon.timeout{display:inline-block;height:1em;width:1em;margin:0;margin-right:.25em;vertical-align:top}
|
||||
.mist.largeplay,.mist.muted{position:absolute;opacity:.5}
|
||||
.mist.largeplay{top:50%;left:0;right:0;margin:auto;transform:translateY(-50%)}
|
||||
.mist.muted{top:0;right:0;margin:1em}
|
||||
.mistvideo-secondaryVideo{z-index:1;width:50%;height:50%}
|
||||
.mistvideo-polling{display:inline-block;position:relative;width:25px;height:25px}
|
||||
.mistvideo-polling svg.icon.loading{z-index:0;opacity:1}
|
||||
.mistvideo[data-show-submenu] .mistvideo-submenu{right:5px}
|
||||
.mistvideo[data-show-submenu] .mistvideo-controls{bottom:0}
|
||||
.mistvideo-error[data-passive]{bottom:auto;left:auto;margin:.5em;padding:.5em}
|
||||
.mistvideo-error[data-passive] .message{max-width:none}
|
||||
.mistvideo-error .mistvideo-buttoncontainer{display:flex;flex-flow:row nowrap;justify-content:center}
|
||||
.mistvideo-error .mistvideo-buttoncontainer .mistvideo-button{white-space:nowrap}
|
||||
.browser-ie .mist.icon.loading{animation:spin 1.5s infinite linear;transform-origin:50% 50%}
|
||||
.browser-ie .mist.icon.loading .spin{animation:none}
|
||||
.mistvideo-log{margin:.5em 0}
|
||||
.mistvideo-log .logs{max-height:10em;min-height:5em;width:100%;padding:.2em 0;padding-right:1em;overflow-y:auto;overflow-x:hidden;font-size:.9em}
|
||||
.mistvideo-log .logs table td{vertical-align:top;padding:0}
|
||||
.mistvideo-log .logs .entry .message{margin:0 .2em}
|
||||
.mistvideo-log .logs .entry.type-error{color:$accent}
|
||||
.mistvideo-log .logs .counter,.mistvideo-log .logs .timestamp{color:$semiFill}
|
||||
.mistvideo-log .logs .timestamp:before{content:'['}
|
||||
.mistvideo-log .logs .timestamp:after{content:']'}
|
||||
.mistvideo-log .logs .counter:before{content:'('}
|
||||
.mistvideo-log .logs .counter:after{content:'\00d7)'}
|
||||
.mistvideo-devbuttons{font-size:.9em}
|
||||
.mistvideo-devbuttons button{font-size:.8em;margin:.1em;padding:.2em .4em}
|
||||
.mistvideo-forcePlayer>span,.mistvideo-forceSource>span,.mistvideo-forceType>span{display:inline-block;width:7em}
|
||||
.mistvideo-forcePlayer>select,.mistvideo-forceSource>select,.mistvideo-forceType>select{width:15em;min-width:auto}
|
||||
.mistvideo-devcontrols{margin:.5em 0}
|
||||
.mistvideo-decodingIssues>*{display:flex;width:50%;max-width:20em;flex-flow:row nowrap;align-items:flex-end;justify-content:space-between}
|
||||
.mistvideo-decodingIssues>*>:last-child{margin-right:.5em}
|
||||
.mistvideo-decodingIssues{display:flex;flex-flow:row wrap;justify-content:space-between}
|
||||
.mistvideo-decodingIssues label{position:relative}
|
||||
.mistvideo-decodingIssues label .value{font-size:.8em}
|
||||
svg.icon.graph{position:absolute;right:0;top:0;bottom:0;width:6em}
|
||||
select{border-radius:0}
|
||||
input[type=checkbox]{margin:0;margin-right:.2em;border:1px solid $semiFill;border-radius:0;-webkit-appearance:none;-moz-appearance:none;-ms-appearance:none;appearance:none;width:.8em;height:.8em;color:inherit;position:relative;cursor:pointer}
|
||||
input[type=checkbox]:checked:after{content:"\2713";position:absolute;bottom:-.2em;left:0;font-size:1.2em}
|
1
embed/min/wrappers/dashjs.js
Normal file
|
@ -0,0 +1 @@
|
|||
mistplayers.dashjs={name:"Dash.js player",mimes:["dash/video/mp4"],priority:MistUtil.object.keys(mistplayers).length+1,isMimeSupported:function(t){return MistUtil.array.indexOf(this.mimes,t)==-1?false:true},isBrowserSupported:function(t,e,i){if(location.protocol!=MistUtil.http.url.split(e.url).protocol){i.log("HTTP/HTTPS mismatch for this source");return false}if(location.protocol=="file:"){i.log("This source ("+t+") won't load if the page is run via file://");return false}return"MediaSource"in window},player:function(){this.onreadylist=[]},scriptsrc:function(t){return t+"/dashjs.js"}};var p=mistplayers.dashjs.player;p.prototype=new MistPlayer;p.prototype.build=function(t,e){var i=this;this.onDashLoad=function(){if(t.destroyed){return}t.log("Building DashJS player..");var r=document.createElement("video");if("Proxy"in window){var a={get:{},set:{}};t.player.api=new Proxy(r,{get:function(t,e,i){if(e in a.get){return a.get[e].apply(t,arguments)}var r=t[e];if(typeof r==="function"){return function(){return r.apply(t,arguments)}}return r},set:function(t,e,i){if(e in a.set){return a.set[e].call(t,i)}return t[e]=i}});if(t.info.type=="live"){a.get.duration=function(){var e=0;if(this.buffered.length){e=this.buffered.end(this.buffered.length-1)}var i=((new Date).getTime()-t.player.api.lastProgress.getTime())*.001;return e+i+-1*t.player.api.liveOffset+45};a.set.currentTime=function(e){var i=e-t.player.api.duration;t.log("Seeking to "+MistUtil.format.time(e)+" ("+Math.round(i*-10)/10+"s from live)");t.video.currentTime=e};MistUtil.event.addListener(r,"progress",function(){t.player.api.lastProgress=new Date});t.player.api.lastProgress=new Date;t.player.api.liveOffset=0}}else{i.api=r}if(t.options.autoplay){r.setAttribute("autoplay","")}if(t.options.loop&&t.info.type!="live"){r.setAttribute("loop","")}if(t.options.poster){r.setAttribute("poster",t.options.poster)}if(t.options.controls=="stock"){r.setAttribute("controls","")}var s=dashjs.MediaPlayer().create();s.initialize(r,t.source.url,t.options.autoplay);i.dash=s;var o=["METRIC_ADDED","METRIC_CHANGED","METRICS_CHANGED","FRAGMENT_LOADING_STARTED","FRAGMENT_LOADING_COMPLETED","LOG","PLAYBACK_TIME_UPDATED","PLAYBACK_PROGRESS"];for(var n in dashjs.MediaPlayer.events){if(o.indexOf(n)<0){i.dash.on(dashjs.MediaPlayer.events[n],function(e){t.log("Player event fired: "+e.type)})}}t.player.setSize=function(t){this.api.style.width=t.width+"px";this.api.style.height=t.height+"px"};t.player.api.setSource=function(e){t.player.dash.attachSource(e)};t.player.api.setTrack=function(e,r){var a=MistUtil.tracks.parse(t.info.meta.tracks);if(!(e in a)||!(r in a[e])&&r!=0){t.log("Skipping trackselection of "+e+" track "+r+" because it does not exist");return}var s=i.dash.getBitrateInfoListFor("video").length-1;for(var o in t.info.meta.tracks){var n=t.info.meta.tracks[o];if(n.type==e){if(n.trackid==r){break}s--}}i.dash.setAutoSwitchQualityFor(e,false);i.dash.setFastSwitchEnabled(true);i.dash.setQualityFor(e,s)};i.dash.on("qualityChangeRendered",function(e){var r=i.dash.getBitrateInfoListFor("video").length-1;var a;for(var s in t.info.meta.tracks){var o=t.info.meta.tracks[s];if(o.type==e.mediaType){if(e.newQuality==r){a=o.trackid;break}r--}}MistUtil.event.send("playerUpdate_trackChanged",{type:e.mediaType,trackid:a},t.video)});MistUtil.event.addListener(r,"progress",function(e){if(t.container.getAttribute("data-loading")=="stalled"){t.container.removeAttribute("data-loading")}});i.api.unload=function(){i.dash.reset()};t.log("Built html");e(r)};if("dashjs"in window){this.onDashLoad()}else{var r=MistUtil.scripts.insert(t.urlappend(mistplayers.dashjs.scriptsrc(t.options.host)),{onerror:function(e){var i="Failed to load dashjs.js";if(e.message){i+=": "+e.message}t.showError(i)},onload:i.onDashLoad},t)}};
|
1
embed/min/wrappers/flash_strobe.js
Normal file
|
@ -0,0 +1 @@
|
|||
mistplayers.flash_strobe={name:"Strobe Flash media playback",mimes:["flash/10","flash/11","flash/7"],priority:MistUtil.object.keys(mistplayers).length+1,isMimeSupported:function(t){return this.mimes.indexOf(t)==-1?false:true},isBrowserSupported:function(t,e,i){if(MistUtil.http.url.split(e.url).protocol.slice(0,4)=="http"&&location.protocol!=MistUtil.http.url.split(e.url).protocol){i.log("HTTP/HTTPS mismatch for this source");return false}var r=0;try{var a=navigator.mimeTypes["application/x-shockwave-flash"].enabledPlugin;if(a.version){r=a.version.split(".")[0]}else{r=a.description.replace(/([^0-9\.])/g,"").split(".")[0]}}catch(t){}try{r=new ActiveXObject("ShockwaveFlash.ShockwaveFlash").GetVariable("$version").replace(/([^0-9\,])/g,"").split(",")[0]}catch(t){}if(!r){return false}var l=t.split("/");return Number(r)>=Number(l[l.length-1])},player:function(){this.onreadylist=[]}};var p=mistplayers.flash_strobe.player;p.prototype=new MistPlayer;p.prototype.build=function(t,e){var i=document.createElement("object");var r=document.createElement("embed");i.appendChild(r);function a(e){var a=t.options;function l(t,e){var i=document.createElement("param");i.setAttribute("name",t);i.setAttribute("value",e);return i}MistUtil.empty(i);i.appendChild(l("movie",t.urlappend(a.host+t.source.player_url)));var s="src="+encodeURIComponent(e)+"&controlBarMode="+(a.controls?"floating":"none")+"&initialBufferTime=0.5&expandedBufferTime=5&minContinuousPlaybackTime=3"+(a.live?"&streamType=live":"")+(a.autoplay?"&autoPlay=true":"");i.appendChild(l("flashvars",s));i.appendChild(l("allowFullScreen","true"));i.appendChild(l("wmode","direct"));if(a.autoplay){i.appendChild(l("autoPlay","true"))}r.setAttribute("src",t.urlappend(t.source.player_url));r.setAttribute("type","application/x-shockwave-flash");r.setAttribute("allowfullscreen","true");r.setAttribute("flashvars",s)}a(t.source.url);this.api={};this.setSize=function(t){i.setAttribute("width",t.width);i.setAttribute("height",t.height);r.setAttribute("width",t.width);r.setAttribute("height",t.height)};this.setSize(t.calcSize());this.onready(function(){if(t.container){t.container.removeAttribute("data-loading")}});this.api.setSource=function(t){a(t)};t.log("Built html");e(i)};
|
1
embed/min/wrappers/html5.js
Normal file
|
@ -0,0 +1 @@
|
|||
mistplayers.html5={name:"HTML5 video player",mimes:["html5/application/vnd.apple.mpegurl","html5/video/mp4","html5/video/ogg","html5/video/webm","html5/audio/mp3","html5/audio/webm","html5/audio/ogg","html5/audio/wav"],priority:MistUtil.object.keys(mistplayers).length+1,isMimeSupported:function(e){return MistUtil.array.indexOf(this.mimes,e)==-1?false:true},isBrowserSupported:function(e,t,i){if(location.protocol!=MistUtil.http.url.split(t.url).protocol){if(location.protocol=="file:"&&MistUtil.http.url.split(t.url).protocol=="http:"){i.log("This page was loaded over file://, the player might not behave as intended.")}else{i.log("HTTP/HTTPS mismatch for this source");return false}}var r=false;var a=e.split("/");a.shift();try{a=a.join("/");function n(e){var t=document.createElement("video");if(t&&t.canPlayType(e)!=""){r=t.canPlayType(e)}return r}if(a=="video/mp4"){function o(e){function t(t){return("0"+e.init.charCodeAt(t).toString(16)).slice(-2)}switch(e.codec){case"AAC":return"mp4a.40.2";case"MP3":return"mp3";case"AC3":return"ec-3";case"H264":return"avc1."+t(1)+t(2)+t(3);case"HEVC":return"hev1."+t(1)+t(6)+t(7)+t(8)+t(9)+t(10)+t(11)+t(12);default:return e.codec.toLowerCase()}}var s={};for(var l in i.info.meta.tracks){if(i.info.meta.tracks[l].type!="meta"){s[o(i.info.meta.tracks[l])]=1}}s=MistUtil.object.keys(s);if(s.length){if(s.length>t.simul_tracks){var p=0;for(var l in s){var u=n(a+';codecs="'+s[l]+'"');if(u){p++}}return p>=t.simul_tracks}a+=';codecs="'+s.join(",")+'"'}}r=n(a)}catch(e){}return r},player:function(){this.onreadylist=[]},mistControls:true};var p=mistplayers.html5.player;p.prototype=new MistPlayer;p.prototype.build=function(e,t){var i=e.source.type.split("/");i.shift();var r=document.createElement("video");r.setAttribute("crossorigin","anonymous");var a=document.createElement("source");a.setAttribute("src",e.source.url);r.source=a;r.appendChild(a);a.type=i.join("/");var n=["autoplay","loop","poster"];for(var o in n){var s=n[o];if(e.options[s]){r.setAttribute(s,e.options[s]===true?"":e.options[s])}}if(e.options.controls=="stock"){r.setAttribute("controls","")}if(e.info.type=="live"){r.loop=false}if("Proxy"in window&&"Reflect"in window){var l={get:{},set:{}};e.player.api=new Proxy(r,{get:function(e,t,i){if(t in l.get){return l.get[t].apply(e,arguments)}var r=e[t];if(typeof r==="function"){return function(){return r.apply(e,arguments)}}return r},set:function(e,t,i){if(t in l.set){return l.set[t].call(e,i)}return e[t]=i}});if(e.source.type=="html5/audio/mp3"){l.set.currentTime=function(){e.log("Seek attempted, but MistServer does not currently support seeking in MP3.");return false}}if(e.info.type=="live"){l.get.duration=function(){var t=0;if(this.buffered.length){t=this.buffered.end(this.buffered.length-1)}var i=((new Date).getTime()-e.player.api.lastProgress.getTime())*.001;return t+i-e.player.api.liveOffset};l.set.currentTime=function(t){var i=t-e.player.api.duration;e.player.api.liveOffset=i;e.log("Seeking to "+MistUtil.format.time(t)+" ("+Math.round(i*-10)/10+"s from live)");e.player.api.setSource(MistUtil.http.url.addParam(e.source.url,{startunix:i}))};MistUtil.event.addListener(r,"progress",function(){e.player.api.lastProgress=new Date});e.player.api.lastProgress=new Date;e.player.api.liveOffset=0;MistUtil.event.addListener(r,"pause",function(){e.player.api.pausedAt=new Date});l.get.play=function(){return function(){if(e.player.api.paused&&e.player.api.pausedAt&&new Date-e.player.api.pausedAt>5e3){r.load();e.log("Reloading source..")}return r.play.apply(r,arguments)}};if(e.source.type=="html5/video/mp4"){l.get.currentTime=function(){return this.currentTime-e.player.api.liveOffset+e.info.lastms*.001}}}else{if(!isFinite(r.duration)){var p=0;for(var o in e.info.meta.tracks){p=Math.max(p,e.info.meta.tracks[o].lastms)}l.get.duration=function(){if(isFinite(this.duration)){return this.duration}return p*.001}}}}else{e.player.api=r}e.player.api.setSource=function(e){if(e!=this.source.src){this.source.src=e;this.load()}};e.player.api.setSubtitle=function(e){var t=r.getElementsByTagName("track");for(var i=t.length-1;i>=0;i--){r.removeChild(t[i])}if(e){var a=document.createElement("track");r.appendChild(a);a.kind="subtitles";a.label=e.label;a.srclang=e.lang;a.src=e.src;a.setAttribute("default","")}};e.player.setSize=function(e){this.api.style.width=e.width+"px";this.api.style.height=e.height+"px"};t(r)};
|
1
embed/min/wrappers/videojs.js
Normal file
|
@ -0,0 +1 @@
|
|||
mistplayers.videojs={name:"VideoJS player",mimes:["html5/application/vnd.apple.mpegurl"],priority:MistUtil.object.keys(mistplayers).length+1,isMimeSupported:function(e){return this.mimes.indexOf(e)==-1?false:true},isBrowserSupported:function(e,t,i){if(location.protocol!=MistUtil.http.url.split(t.url).protocol){i.log("HTTP/HTTPS mismatch for this source");return false}if(location.protocol=="file:"&&e=="html5/application/vnd.apple"){i.log("This source ("+e+") won't load if the page is run via file://");return false}return"MediaSource"in window},player:function(){},scriptsrc:function(e){return e+"/videojs.js"}};var p=mistplayers.videojs.player;p.prototype=new MistPlayer;p.prototype.build=function(e,t){var i=this;function r(){if(e.destroyed){return}e.log("Building VideoJS player..");var r=document.createElement("video");if(e.source.type!="html5/video/ogg"){r.crossOrigin="anonymous"}var o=e.source.type.split("/");o.shift();var n=document.createElement("source");n.setAttribute("src",e.source.url);i.source=n;r.appendChild(n);n.type=o.join("/");e.log("Adding "+n.type+" source @ "+e.source.url);if(n.type=="application/vnd.apple.mpegurl"){n.type="application/x-mpegURL"}MistUtil.class.add(r,"video-js");var s={};if(e.options.autoplay){s.autoplay=true}if(e.options.loop&&e.info.type!="live"){s.loop=true;r.loop=true}if(e.options.poster){s.poster=e.options.poster}if(e.options.controls=="stock"){r.setAttribute("controls","");if(!document.getElementById("videojs-css")){var l=document.createElement("link");l.rel="stylesheet";l.href=e.options.host+"/skins/videojs.css";l.id="videojs-css";document.head.appendChild(l)}}i.onready(function(){i.videojs=videojs(r,s,function(){e.log("Videojs initialized")});i.api.unload=function(){videojs(r).dispose()}});e.log("Built html");if("Proxy"in window&&"Reflect"in window){var a={get:{},set:{}};e.player.api=new Proxy(r,{get:function(e,t,i){if(t in a.get){return a.get[t].apply(e,arguments)}var r=e[t];if(typeof r==="function"){return function(){return r.apply(e,arguments)}}return r},set:function(e,t,i){if(t in a.set){return a.set[t].call(e,i)}return e[t]=i}});if(e.info.type=="live"){function p(e){var t=0;if(e.buffered.length){t=e.buffered.end(e.buffered.length-1)}return t}var u=90;a.get.duration=function(){return(e.info.lastms+(new Date).getTime()-e.info.updated.getTime())*.001};e.player.api.lastProgress=new Date;e.player.api.liveOffset=0;MistUtil.event.addListener(r,"progress",function(){e.player.api.lastProgress=new Date});a.set.currentTime=function(t){var i=e.player.api.currentTime-t;var r=t-e.player.api.duration;e.log("Seeking to "+MistUtil.format.time(t)+" ("+Math.round(r*-10)/10+"s from live)");e.video.currentTime-=i};a.get.currentTime=function(){return this.currentTime+e.info.lastms*.001-e.player.api.liveOffset-u}}}else{i.api=r}e.player.setSize=function(t){if("videojs"in e.player){e.player.videojs.dimensions(t.width,t.height);r.parentNode.style.width=t.width+"px";r.parentNode.style.height=t.height+"px"}this.api.style.width=t.width+"px";this.api.style.height=t.height+"px"};e.player.api.setSource=function(t){if(!e.player.videojs){return}if(e.player.videojs.src()!=t){e.player.videojs.src({type:e.player.videojs.currentSource().type,src:t})}};e.player.api.setSubtitle=function(e){var t=r.getElementsByTagName("track");for(var i=t.length-1;i>=0;i--){r.removeChild(t[i])}if(e){var o=document.createElement("track");r.appendChild(o);o.kind="subtitles";o.label=e.label;o.srclang=e.lang;o.src=e.src;o.setAttribute("default","")}};t(r)}if("videojs"in window){r()}else{var o=MistUtil.scripts.insert(e.urlappend(mistplayers.videojs.scriptsrc(e.options.host)),{onerror:function(t){var i="Failed to load videojs.js";if(t.message){i+=": "+t.message}e.showError(i)},onload:r},e)}};
|
1
embed/min/wrappers/webrtc.js
Normal file
48
embed/minimize.sh
Executable file
|
@ -0,0 +1,48 @@
|
|||
#!/bin/bash
|
||||
|
||||
echo "Minimizing player code..";
|
||||
|
||||
echo " Minimizing JS..";
|
||||
|
||||
if [ "min/player.js" -ot "util.js" ] || [ "min/player.js" -ot "skins.js" ] || [ "min/player.js" -ot "controls.js" ] || [ "min/player.js" -ot "player.js" ]; then
|
||||
echo " Minimizing 'util.js skins.js controls.js player.js' into 'min/player.js'..";
|
||||
terser -mc -o min/player.js -- util.js skins.js controls.js player.js
|
||||
fi
|
||||
echo " Done.";
|
||||
|
||||
echo " Minimizing wrappers.."
|
||||
|
||||
if [ "min/wrappers/dashjs.js" -ot "wrappers/dashjs.js" ]; then
|
||||
echo " Minimizing dashjs";
|
||||
terser -mn -o min/wrappers/dashjs.js -- wrappers/dashjs.js
|
||||
fi
|
||||
if [ "min/wrappers/flash_strobe.js" -ot "wrappers/flash_strobe.js" ]; then
|
||||
echo " Minimizing flash_strobe";
|
||||
terser -mn -o min/wrappers/flash_strobe.js -- wrappers/flash_strobe.js
|
||||
fi
|
||||
if [ "min/wrappers/html5.js" -ot "wrappers/html5.js" ]; then
|
||||
echo " Minimizing html5";
|
||||
terser -mn -o min/wrappers/html5.js -- wrappers/html5.js
|
||||
fi
|
||||
if [ "min/wrappers/videojs.js" -ot "wrappers/videojs.js" ]; then
|
||||
echo " Minimizing videojs";
|
||||
terser -mn -o min/wrappers/videojs.js -- wrappers/videojs.js
|
||||
fi
|
||||
if [ "min/wrappers/webrtc.js" -ot "wrappers/webrtc.js" ]; then
|
||||
echo " Minimizing webrtc";
|
||||
terser -mn -o min/wrappers/webrtc.js -- wrappers/webrtc.js
|
||||
fi
|
||||
echo " Done.";
|
||||
|
||||
echo " Minimizing CSS..";
|
||||
|
||||
if [ "min/skins/default.css" -ot "skins/default.css" ] || [ "min/skins/default.css" -ot "skins/general.css" ]; then
|
||||
echo " Minimizing default";
|
||||
cleancss --format keep-breaks -o min/skins/default.css skins/general.css skins/default.css
|
||||
fi
|
||||
if [ "min/skins/dev.css" -ot "skins/default.css" ] || [ "min/skins/dev.css" -ot "skins/general.css" ] || [ "min/skins/dev.css" -ot "skins/dev.css" ]; then
|
||||
echo " Minimizing dev";
|
||||
cleancss --format keep-breaks -o min/skins/dev.css skins/general.css skins/default.css skins/dev.css
|
||||
fi
|
||||
echo " Done.";
|
||||
echo "Done.";
|
1633
embed/mist.css
1127
embed/player.js
Normal file
46
embed/players/dash.all.min.js
vendored
8
embed/players/update.sh
Executable file
|
@ -0,0 +1,8 @@
|
|||
#!/bin/bash
|
||||
|
||||
echo "Dashjs"
|
||||
wget https://cdn.dashjs.org/latest/dash.all.min.js -O dash.all.min.js
|
||||
|
||||
echo "Videojs"
|
||||
echo "You'll want to check for the latest version at https://videojs.com/getting-started/#download-cdn"
|
||||
wget https://vjs.zencdn.net/7.3.0/video.min.js -O video.min.js
|
24722
embed/players/video.js
13
embed/players/video.min.js
vendored
7
embed/players/videojs-contrib-hls.min.js
vendored
1
embed/players/webrtc.js
Normal file
2559
embed/skins.js
Normal file
131
embed/skins/default.css
Normal file
|
@ -0,0 +1,131 @@
|
|||
.mistvideo {
|
||||
line-height: 1.2;
|
||||
font-size: 14.5px;
|
||||
}
|
||||
.mistvideo svg {
|
||||
margin: 2.5px;
|
||||
}
|
||||
.mistvideo-background { background-color: $background; }
|
||||
.mistvideo-totalTime:before {
|
||||
content: '/';
|
||||
margin: 0.2em;
|
||||
}
|
||||
.mistvideo-progress {
|
||||
padding: 10px 0;
|
||||
margin: -10px 0;
|
||||
z-index: 2; /*keep above control bar*/
|
||||
}
|
||||
.mistvideo-progress > * {
|
||||
height: 2px;
|
||||
background-color: $progressBackground;
|
||||
opacity: 0.95;
|
||||
position: relative;
|
||||
}
|
||||
.mistvideo-novideo .mistvideo-progress > *,
|
||||
.mistvideo-progress:hover > * {
|
||||
height: 10px;
|
||||
}
|
||||
|
||||
.mistvideo-progress:not(:hover) > * {
|
||||
transition: height 0.25s ease-in 0.5s;
|
||||
}
|
||||
.mistvideo-progress .bar {
|
||||
height: inherit;
|
||||
width: 0;
|
||||
position: absolute;
|
||||
border-right: inherit;
|
||||
background-color: $accent;
|
||||
z-index: 2; /*keep above buffer bar(s)*/
|
||||
}
|
||||
.mistvideo-progress .buffer {
|
||||
height: inherit;
|
||||
width: 0;
|
||||
position: absolute;
|
||||
background-color: $semiFill;
|
||||
}
|
||||
.mistvideo-progress .bar:after {
|
||||
content: '';
|
||||
border: 5px solid $accent;
|
||||
border-radius: 5px;
|
||||
position: absolute;
|
||||
right: -5px;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
|
||||
.mistvideo-play[data-state="playing"] svg.play {
|
||||
display: none;
|
||||
}
|
||||
.mistvideo-play[data-state="paused"] svg.pause {
|
||||
display: none;
|
||||
}
|
||||
.mistvideo-main { align-items: center; }
|
||||
|
||||
svg.icon.timeout {
|
||||
display: inline-block;
|
||||
height: 1em;
|
||||
width: 1em;
|
||||
margin: 0;
|
||||
margin-right: 0.25em;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.mist.largeplay, .mist.muted {
|
||||
position: absolute;
|
||||
opacity: 0.5;
|
||||
}
|
||||
.mist.largeplay {
|
||||
top: 50%;
|
||||
left: 0;
|
||||
right: 0;
|
||||
margin: auto;
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
.mist.muted {
|
||||
top: 0;
|
||||
right: 0;
|
||||
margin: 1em;
|
||||
}
|
||||
.mistvideo-secondaryVideo {
|
||||
z-index: 1;
|
||||
width: 50%;
|
||||
height: 50%;
|
||||
}
|
||||
.mistvideo-polling {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
width: 25px;
|
||||
height: 25px;
|
||||
}
|
||||
.mistvideo-polling svg.icon.loading {
|
||||
z-index: 0;
|
||||
opacity: 1;
|
||||
}
|
||||
.mistvideo[data-show-submenu] .mistvideo-submenu {
|
||||
right: 5px;
|
||||
}
|
||||
.mistvideo[data-show-submenu] .mistvideo-controls {
|
||||
bottom: 0;
|
||||
}
|
||||
.mistvideo-error[data-passive] {
|
||||
bottom: auto;
|
||||
left: auto;
|
||||
margin: 0.5em;
|
||||
padding: 0.5em;
|
||||
}
|
||||
.mistvideo-error[data-passive] .message {
|
||||
max-width: none;
|
||||
}
|
||||
.mistvideo-error .mistvideo-buttoncontainer {
|
||||
display: flex;
|
||||
flex-flow: row nowrap;
|
||||
justify-content: center;
|
||||
}
|
||||
.mistvideo-error .mistvideo-buttoncontainer .mistvideo-button {
|
||||
white-space: nowrap;
|
||||
}
|
||||
.browser-ie .mist.icon.loading {
|
||||
animation: spin 1.5s infinite linear;
|
||||
transform-origin: 50% 50%;
|
||||
}
|
||||
.browser-ie .mist.icon.loading .spin { animation: none; }
|
105
embed/skins/dev.css
Normal file
|
@ -0,0 +1,105 @@
|
|||
.mistvideo-log {
|
||||
margin: 0.5em 0;
|
||||
}
|
||||
.mistvideo-log .logs {
|
||||
max-height: 10em;
|
||||
min-height: 5em;
|
||||
width: 100%;
|
||||
padding: 0.2em 0;
|
||||
padding-right: 1em; /*for scrollbar*/
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
.mistvideo-log .logs table td {
|
||||
vertical-align: top;
|
||||
padding: 0;
|
||||
}
|
||||
.mistvideo-log .logs .entry .message {
|
||||
margin: 0 0.2em;
|
||||
}
|
||||
.mistvideo-log .logs .entry.type-error {
|
||||
color: $accent;
|
||||
}
|
||||
.mistvideo-log .logs .timestamp,
|
||||
.mistvideo-log .logs .counter {
|
||||
color: $semiFill;
|
||||
}
|
||||
.mistvideo-log .logs .timestamp:before { content: '['; }
|
||||
.mistvideo-log .logs .timestamp:after { content: ']'; }
|
||||
.mistvideo-log .logs .counter:before { content: '('; }
|
||||
.mistvideo-log .logs .counter:after { content: '\00d7)'; }
|
||||
|
||||
.mistvideo-devbuttons { font-size: 0.9em; }
|
||||
.mistvideo-devbuttons button {
|
||||
font-size: 0.8em;
|
||||
margin: 0.1em;
|
||||
padding: 0.2em 0.4em;
|
||||
}
|
||||
.mistvideo-forceSource > span,
|
||||
.mistvideo-forceType > span,
|
||||
.mistvideo-forcePlayer > span { display: inline-block; width: 7em; }
|
||||
.mistvideo-forceSource > select,
|
||||
.mistvideo-forceType > select,
|
||||
.mistvideo-forcePlayer > select {
|
||||
width: 15em;
|
||||
min-width: auto;
|
||||
}
|
||||
.mistvideo-devcontrols {
|
||||
margin: 0.5em 0;
|
||||
}
|
||||
|
||||
.mistvideo-decodingIssues > * {
|
||||
display: flex;
|
||||
width: 50%;
|
||||
max-width: 20em;
|
||||
flex-flow: row nowrap;
|
||||
align-items: flex-end;
|
||||
justify-content: space-between;
|
||||
}
|
||||
.mistvideo-decodingIssues > * > :last-child {
|
||||
margin-right: 0.5em;
|
||||
}
|
||||
.mistvideo-decodingIssues {
|
||||
display: flex;
|
||||
flex-flow: row wrap;
|
||||
justify-content: space-between;
|
||||
}
|
||||
.mistvideo-decodingIssues label {
|
||||
position: relative;
|
||||
}
|
||||
.mistvideo-decodingIssues label .value {
|
||||
font-size: 0.8em;
|
||||
}
|
||||
svg.icon.graph {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
width: 6em;
|
||||
}
|
||||
select {
|
||||
border-radius: 0;
|
||||
}
|
||||
input[type="checkbox"] {
|
||||
margin: 0;
|
||||
margin-right: 0.2em;
|
||||
border: 1px solid $semiFill;
|
||||
border-radius: 0;
|
||||
-webkit-appearance: none;
|
||||
-moz-appearance: none;
|
||||
-ms-appearance: none;
|
||||
appearance: none;
|
||||
width: 0.8em;
|
||||
height: 0.8em;
|
||||
color: inherit;
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
}
|
||||
input[type="checkbox"]:checked:after {
|
||||
content: "\2713";
|
||||
position: absolute;
|
||||
bottom: -0.2em;
|
||||
left: 0;
|
||||
font-size: 1.2em;
|
||||
}
|
224
embed/skins/general.css
Normal file
|
@ -0,0 +1,224 @@
|
|||
.mistvideo {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
color: $stroke;
|
||||
font-family: sans-serif;
|
||||
background-color: #000;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
.mistvideo-controls {
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
.mistvideo.novideo {
|
||||
overflow: visible;
|
||||
}
|
||||
.mistvideo-video {
|
||||
overflow: hidden;
|
||||
}
|
||||
svg.icon.loading {
|
||||
z-index: -1; /* don't use display: none because of transition for [data-loading=stalled] */
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
margin: auto;
|
||||
opacity: 0;
|
||||
}
|
||||
[data-loading] {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/*wait before showing icon when stalled*/
|
||||
[data-loading="stalled"] svg.icon.loading {
|
||||
transition: opacity 0s 3s;
|
||||
}
|
||||
[data-loading] svg.icon.loading {
|
||||
z-index: 2;
|
||||
opacity: 1;
|
||||
}
|
||||
[data-loading-css] .mistvideo-controls {
|
||||
display: none;
|
||||
}
|
||||
[data-hidecursor],
|
||||
[data-hidecursor] .mistvideo-pointer,
|
||||
[data-hidecursor] *
|
||||
{ cursor: none }
|
||||
.mistvideo-error {
|
||||
display: none;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background-color: $background;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
text-align: center;
|
||||
z-index: 2; /*above progress bar*/
|
||||
cursor: default; /*cursor won't show up if it was hidden because the mousemove event can no longer reach the video element*/
|
||||
min-height: fit-content; /*overflow if needed*/
|
||||
min-width: fit-content;
|
||||
}
|
||||
.mistvideo-error.show { display: flex; }
|
||||
.mistvideo-error .message { max-width: 80%; }
|
||||
.mistvideo-error .message .details table { text-align: left; }
|
||||
.mistvideo-video:not(.video-js) button,
|
||||
.mistvideo-error button,
|
||||
.mistvideo-controls button
|
||||
{
|
||||
color: $stroke;
|
||||
border: 1px solid $semiFill;
|
||||
background-color: $background;
|
||||
margin: 0.25em;
|
||||
padding: 0.5em 1em;
|
||||
opacity: 0.5;
|
||||
cursor: pointer;
|
||||
}
|
||||
button:hover { opacity: 1; }
|
||||
select {
|
||||
background-color: transparent;
|
||||
color: $stroke;
|
||||
border: none;
|
||||
margin: 0 0.5em;
|
||||
font-size: inherit;
|
||||
cursor: pointer;
|
||||
-ms-background-color: red;
|
||||
}
|
||||
select > option {
|
||||
background-color: $background;
|
||||
}
|
||||
|
||||
.browser-edge select, .browser-safari select {
|
||||
/*These browsers don't show an arrow for select boxes, causing them to be invisible when a border is not applied */
|
||||
border: 1px solid $semiFill;
|
||||
border-top: none;
|
||||
border-left: none;
|
||||
margin-top: 2px;
|
||||
}
|
||||
|
||||
@keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } }
|
||||
[data-fullscreen] {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
width: 100% !important;
|
||||
height: 100% !important;
|
||||
}
|
||||
video {
|
||||
display: block;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
table { color: inherit; font-size: inherit; font-style: inherit; }
|
||||
audio:not([controls]) { display: block !important; }
|
||||
.mistvideo-padding { padding: 5px 10px; }
|
||||
.mistvideo-pointer { cursor: pointer; }
|
||||
.description {
|
||||
color: $semiFill;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
.mistvideo-container {
|
||||
display: flex;
|
||||
flex-wrap: nowrap;
|
||||
}
|
||||
.mistvideo-container.mistvideo { display: inline-flex; max-width: 100%; }
|
||||
.mistvideo-container.mistvideo-row { flex-direction: row; }
|
||||
.mistvideo-container.mistvideo-column { flex-direction: column; }
|
||||
.mistvideo-container.mistvideo-center { justify-content: center; }
|
||||
|
||||
.mistvideo-align-right {
|
||||
margin-left: auto;
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
.hover_window_container.pos > .outer_window {
|
||||
position: absolute;
|
||||
pointer-events: none;
|
||||
overflow: hidden;
|
||||
}
|
||||
.hover_window_container.pos > .outer_window > .inner_window {
|
||||
position: absolute;
|
||||
pointer-events: all;
|
||||
}
|
||||
.hover_window_container:not(:hover) > .outer_window > .inner_window,
|
||||
.hover_window_container > .outer_window[data-hidecursor] > .inner_window
|
||||
{ transition: all 0.5s ease-in 0.5s; }
|
||||
.outer_window > .inner_window { flex-grow: 1; }
|
||||
.hover_window_container > .outer_window > .inner_window > * { flex-shrink: 0; }
|
||||
|
||||
.mistvideo-draggable {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.mistvideo-tooltip {
|
||||
position: absolute;
|
||||
background-color: $background;
|
||||
padding: 0.5em 1em;
|
||||
z-index: 2;
|
||||
}
|
||||
*:not(:hover) > .mistvideo-tooltip { transition: opacity 0.25s ease-in; }
|
||||
.mistvideo-tooltip .triangle {
|
||||
border: 10px solid $background;
|
||||
position: absolute;
|
||||
}
|
||||
.mistvideo-tracks label {
|
||||
display: block;
|
||||
}
|
||||
.mistvideo-tracks label > span {
|
||||
margin-right: 1em;
|
||||
}
|
||||
|
||||
a {
|
||||
color: $accent;
|
||||
}
|
||||
.mistvideo-log .logs {
|
||||
-webkit-user-select: text;
|
||||
-moz-user-select: text;
|
||||
-ms-user-select: text;
|
||||
user-select: text;
|
||||
}
|
||||
.mistvideo-placeholder {
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
}
|
||||
|
||||
.mistvideo-topright {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
}
|
||||
.mistvideo-topleft {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
.mistvideo-delay-display {
|
||||
animation: appear 1s;
|
||||
animation-iteration-count: 1;
|
||||
animation-timing-function: steps(1,end);
|
||||
}
|
||||
@keyframes appear { from { opacity: 0; } to { opacity: 1; } }
|
||||
|
||||
svg.icon {
|
||||
display: block;
|
||||
stroke-width: $strokeWidth;
|
||||
fill: none;
|
||||
stroke: none;
|
||||
}
|
||||
svg.icon.fill, svg.icon .fill { fill: $fill; }
|
||||
svg.icon.semiFill, svg.icon .semiFill { fill: $semiFill; }
|
||||
svg.icon.stroke, svg.icon .stroke { stroke: $stroke; vector-effect: non-scaling-stroke; }
|
||||
svg.icon.off .toggle.fill,
|
||||
svg.icon.off .toggle.semiFill,
|
||||
svg.icon.off .toggle .fill,
|
||||
svg.icon.off .toggle .semiFill { fill: none; }
|
||||
svg.icon.spin, svg.icon .spin {
|
||||
animation: spin 1.5s infinite linear;
|
||||
transform-origin: 50% 50%;
|
||||
}
|
1279
embed/skins/video-js.css
Normal file
954
embed/util.js
Normal file
|
@ -0,0 +1,954 @@
|
|||
var MistUtil = {
|
||||
format: {
|
||||
time: function(secs,options){
|
||||
if (isNaN(secs) || !isFinite(secs)) { return secs; }
|
||||
if (!options) { options = {}; }
|
||||
|
||||
var ago = (secs < 0 ? " ago" : "");
|
||||
secs = Math.abs(secs);
|
||||
|
||||
var days = Math.floor(secs / 86400)
|
||||
secs = secs - days * 86400;
|
||||
var hours = Math.floor(secs / 3600);
|
||||
secs = secs - hours * 3600;
|
||||
var mins = Math.floor(secs / 60);
|
||||
var ms = Math.round((secs % 1)*1e3);
|
||||
secs = Math.floor(secs - mins * 60);
|
||||
var str = [];
|
||||
if (days) {
|
||||
days = days+" day"+(days > 1 ? "s" : "")+", ";
|
||||
}
|
||||
if ((hours) || (days)) {
|
||||
str.push(hours);
|
||||
str.push(("0"+mins).slice(-2));
|
||||
}
|
||||
else {
|
||||
str.push(mins); //don't use 0 padding if there are no hours in front
|
||||
}
|
||||
str.push(("0"+Math.floor(secs)).slice(-2));
|
||||
|
||||
if (options.ms) {
|
||||
str[str.length-1] += "."+("000"+ms).slice(-3);
|
||||
}
|
||||
|
||||
return (days ? days : "")+str.join(":")+ago;
|
||||
},
|
||||
ucFirst: function(string){
|
||||
return string.charAt(0).toUpperCase()+string.slice(1);
|
||||
},
|
||||
number: function(num) {
|
||||
if ((isNaN(Number(num))) || (num == 0)) { return num; }
|
||||
|
||||
//rounding
|
||||
//use a significance of three, but don't round "visible" digits
|
||||
var sig = Math.max(3,Math.ceil(Math.log(num)/Math.LN10));
|
||||
var mult = Math.pow(10,sig - Math.floor(Math.log(num)/Math.LN10) - 1);
|
||||
num = Math.round(num * mult) / mult;
|
||||
|
||||
//thousand seperation
|
||||
if (num >= 1e4) {
|
||||
var seperator = " ";
|
||||
number = num.toString().split(".");
|
||||
var regex = /(\d+)(\d{3})/;
|
||||
while (regex.test(number[0])) {
|
||||
number[0] = number[0].replace(regex,"$1"+seperator+"$2");
|
||||
}
|
||||
num = number.join(".");
|
||||
}
|
||||
|
||||
return num;
|
||||
},
|
||||
bytes: function(val){
|
||||
if (isNaN(Number(val))) { return val; }
|
||||
|
||||
var suffix = ["bytes","KB","MB","GB","TB","PB"];
|
||||
if (val == 0) {
|
||||
unit = suffix[0];
|
||||
}
|
||||
else {
|
||||
var exponent = Math.floor(Math.log(Math.abs(val)) / Math.log(1024));
|
||||
if (exponent < 0) {
|
||||
unit = suffix[0];
|
||||
}
|
||||
else {
|
||||
val = val / Math.pow(1024,exponent);
|
||||
unit = suffix[exponent];
|
||||
}
|
||||
}
|
||||
return this.number(val)+unit;
|
||||
},
|
||||
mime2human: function(mime){
|
||||
switch (mime) {
|
||||
case "html5/video/webm": {
|
||||
return "WebM";
|
||||
break;
|
||||
}
|
||||
case "html5/application/vnd.apple.mpegurl": {
|
||||
return "HLS";
|
||||
break;
|
||||
}
|
||||
case "flash/10": {
|
||||
return "Flash (RTMP)";
|
||||
break;
|
||||
}
|
||||
case "flash/11": {
|
||||
return "Flash (HDS)";
|
||||
break;
|
||||
}
|
||||
case "flash/7": {
|
||||
return "Flash (Progressive)";
|
||||
break;
|
||||
}
|
||||
case "html5/video/mpeg": {
|
||||
return "TS";
|
||||
break;
|
||||
}
|
||||
case "html5/application/vnd.ms-ss": {
|
||||
return "Smooth streaming";
|
||||
break;
|
||||
}
|
||||
case "dash/video/mp4": {
|
||||
return "DASH";
|
||||
break;
|
||||
}
|
||||
case "webrtc": {
|
||||
return "WebRTC";
|
||||
break;
|
||||
}
|
||||
case "silverlight": {
|
||||
return "Smooth streaming (Silverlight)";
|
||||
break;
|
||||
}
|
||||
case "html5/text/vtt": {
|
||||
return "VTT subtitles";
|
||||
break;
|
||||
}
|
||||
case "html5/text/plain": {
|
||||
return "SRT subtitles";
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
return mime.replace("html5/","").replace("video/","").replace("audio/","").toLocaleUpperCase();
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
class: {
|
||||
//reroute classList functionalities if not supported; also avoid indexOf
|
||||
add: function(DOMelement,item){
|
||||
if ("classList" in DOMelement) {
|
||||
DOMelement.classList.add(item);
|
||||
}
|
||||
else {
|
||||
var classes = this.get(DOMelement);
|
||||
|
||||
classes.push(item);
|
||||
this.set(DOMelement,classes);
|
||||
}
|
||||
},
|
||||
remove: function(DOMelement,item){
|
||||
if ("classList" in DOMelement) {
|
||||
DOMelement.classList.remove(item);
|
||||
}
|
||||
else {
|
||||
var classes = this.get(DOMelement);
|
||||
|
||||
for (var i = classes.length-1; i >= 0; i--) {
|
||||
if (classes[i] == item) {
|
||||
classes.splice(i);
|
||||
}
|
||||
}
|
||||
this.set(DOMelement,classes);
|
||||
}
|
||||
},
|
||||
get: function(DOMelement) {
|
||||
var classes;
|
||||
var className = DOMelement.getAttribute("class"); //DOMelement.className does not work on svg elements
|
||||
|
||||
if ((!className) || (className == "")) { classes = []; }
|
||||
else { classes = className.split(" "); }
|
||||
|
||||
return classes;
|
||||
},
|
||||
set: function(DOMelement,classes) {
|
||||
DOMelement.setAttribute("class",classes.join(" "));
|
||||
},
|
||||
has: function(DOMelement,hasClass){
|
||||
return (DOMelement.className.split(" ").indexOf(hasClass) >= 0)
|
||||
}
|
||||
},
|
||||
|
||||
object: {
|
||||
//extend object1 with object2
|
||||
extend: function(object1,object2,deep) {
|
||||
for (var i in object2) {
|
||||
if (deep && (typeof object2[i] == "object") && (!("nodeType" in object2[i]))) {
|
||||
if (!(i in object1)) {
|
||||
if (MistUtil.array.is(object2[i])) {
|
||||
object1[i] = [];
|
||||
}
|
||||
else {
|
||||
object1[i] = {};
|
||||
}
|
||||
}
|
||||
this.extend(object1[i],object2[i],true);
|
||||
}
|
||||
else {
|
||||
object1[i] = object2[i];
|
||||
}
|
||||
}
|
||||
|
||||
return object1;
|
||||
},
|
||||
//replace Object.keys
|
||||
//if sorting: sort the keys alphabetically or use passed sorting function
|
||||
//sorting gets these arguments: keya,keyb,valuea,valueb
|
||||
keys: function(obj,sorting){
|
||||
|
||||
var keys = [];
|
||||
for (var i in obj) {
|
||||
keys.push(i);
|
||||
}
|
||||
|
||||
if (sorting) {
|
||||
if (typeof sorting != "function") {
|
||||
sorting = function(keya,keyb){
|
||||
if (keya > keyb) { return 1; }
|
||||
if (keya < keyb) { return -1; }
|
||||
return 0;
|
||||
};
|
||||
}
|
||||
|
||||
keys.sort(function(keya,keyb){
|
||||
return sorting(keya,keyb,obj[keya],obj[keyb]);
|
||||
});
|
||||
}
|
||||
|
||||
return keys;
|
||||
},
|
||||
//replace Object.values
|
||||
//if sorting: sort the keys alphabetically or use passed sorting function
|
||||
//sorting gets these arguments: keya,keyb,valuea,valueb
|
||||
values: function(obj,sorting){
|
||||
|
||||
var keys = this.keys(obj,sorting);
|
||||
|
||||
values = [];
|
||||
for (var i in keys) {
|
||||
values.push(obj[keys[i]]);
|
||||
}
|
||||
|
||||
return values;
|
||||
}
|
||||
},
|
||||
array: {
|
||||
//replace [].indexOf
|
||||
indexOf: function(array,entry) {
|
||||
if (!(array instanceof Array)) { throw "Tried to use indexOf on something that is not an array"; }
|
||||
if ("indexOf" in array) { return array.indexOf(entry); }
|
||||
|
||||
for (var i; i < array.length; i++) {
|
||||
if (array[i] == entry) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
},
|
||||
//replace isArray
|
||||
is: function(array) {
|
||||
if ("isArray" in Array) {
|
||||
return Array.isArray(array);
|
||||
}
|
||||
return Object.prototype.toString.call(array) === '[object Array]';
|
||||
},
|
||||
multiSort: function (array,sortby) {
|
||||
/*
|
||||
MistUtil.array.multiSort([].concat(video.info.source),[
|
||||
{type: ["html5/video/webm","silverlight"]} or ["type",["html5/video/webm","silverlight"]]
|
||||
,{simul_tracks:-1} or ["simul_tracks",-1]
|
||||
,function(a){ return a.priority * -1; }
|
||||
,"url"
|
||||
]);
|
||||
*/
|
||||
|
||||
var sortfunc = function(a,b){
|
||||
if (isNaN(a) || isNaN(b)) {
|
||||
return a.localeCompare(b);
|
||||
}
|
||||
return Math.sign(a-b);
|
||||
};
|
||||
|
||||
if (!sortby.length) { return array.sort(sortfunc); }
|
||||
|
||||
function getValue(key,a) {
|
||||
|
||||
function parseIt(item,key,sortvalue){
|
||||
if (!(key in item)) {
|
||||
throw "Invalid sorting rule: "+JSON.stringify([key,sortvalue])+". \""+key+"\" is not a key of "+JSON.stringify(item);
|
||||
}
|
||||
|
||||
if (typeof sortvalue == "number") {
|
||||
//deals with something like {priority: -1}
|
||||
if (key in item) {
|
||||
return item[key] * sortvalue;
|
||||
}
|
||||
}
|
||||
|
||||
//deals with something like {type:["webrtc"]}
|
||||
var i = sortvalue.indexOf(item[key])
|
||||
return (i >= 0 ? i : sortvalue.length);
|
||||
}
|
||||
|
||||
//deals with something like function(a){ return a.foo + a.bar; }
|
||||
if (typeof key == "function") { return key(a); }
|
||||
|
||||
if (typeof key == "object") {
|
||||
if (key instanceof Array) {
|
||||
//it's an array
|
||||
return parseIt(a,key[0],key[1]);
|
||||
}
|
||||
//it's an object
|
||||
for (var j in key) { //only listen to a single key
|
||||
return parseIt(a,j,key[j]);
|
||||
}
|
||||
}
|
||||
|
||||
if (key in a) {
|
||||
return a[key];
|
||||
}
|
||||
|
||||
throw "Invalid sorting rule: "+key+". This should be a function, object or key of "+JSON.stringify(a)+".";
|
||||
}
|
||||
|
||||
array.sort(function(a,b){
|
||||
var output = 0;
|
||||
for (var i in sortby) {
|
||||
var key = sortby[i];
|
||||
output = sortfunc(getValue(key,a),getValue(key,b));
|
||||
if (output != 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return output;
|
||||
});
|
||||
|
||||
return array;
|
||||
}
|
||||
},
|
||||
|
||||
createUnique: function() {
|
||||
var i = "uid"+Math.random().toString().replace("0.","");
|
||||
if (document.querySelector("."+i)) {
|
||||
//if this is already used, try again
|
||||
return createUnique();
|
||||
}
|
||||
return i;
|
||||
},
|
||||
|
||||
http: {
|
||||
getpost: function(type,url,data,callback,errorCallback) {
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open(type, url, true);
|
||||
if (type == "POST") { xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); }
|
||||
|
||||
if (errorCallback) { xhr.timeout = 8e3; } //go to timeout function after 8 seconds
|
||||
|
||||
xhr.onload = function() {
|
||||
var status = xhr.status;
|
||||
if ((status >= 200) && (status < 300)) {
|
||||
callback(xhr.response);
|
||||
}
|
||||
else if (errorCallback) {
|
||||
xhr.onerror = function() {
|
||||
errorCallback(xhr);
|
||||
}
|
||||
}
|
||||
};
|
||||
if (errorCallback) {
|
||||
xhr.onerror = function() {
|
||||
errorCallback(xhr);
|
||||
}
|
||||
xhr.ontimeout = xhr.onerror;
|
||||
}
|
||||
if (type == "POST") {
|
||||
var poststr;
|
||||
var post = [];
|
||||
for (var i in data) {
|
||||
post.push(i+"="+encodeURIComponent(data[i]));
|
||||
}
|
||||
if (post.length) { poststr = post.join("&"); }
|
||||
xhr.send(poststr);
|
||||
}
|
||||
else {
|
||||
xhr.send();
|
||||
}
|
||||
},
|
||||
get: function(url,callback,errorCallback){
|
||||
this.getpost("GET",url,null,callback,errorCallback);
|
||||
},
|
||||
post: function(url,data,callback,errorCallback){
|
||||
this.getpost("POST",url,data,callback,errorCallback);
|
||||
},
|
||||
url: {
|
||||
addParam: function(url,params){
|
||||
var spliturl = url.split("?");
|
||||
var ret = [spliturl.shift()];
|
||||
var splitparams = [];
|
||||
if (spliturl.length) {
|
||||
splitparams = spliturl[0].split("&");
|
||||
}
|
||||
for (var i in params) {
|
||||
splitparams.push(i+"="+params[i]);
|
||||
}
|
||||
if (splitparams.length) { ret.push(splitparams.join("&")); }
|
||||
return ret.join("?");
|
||||
},
|
||||
split: function(url){
|
||||
var a = document.createElement("a");
|
||||
a.href = url;
|
||||
return {
|
||||
protocol: a.protocol,
|
||||
host: a.hostname,
|
||||
hash: a.hash,
|
||||
port: a.port,
|
||||
path: a.pathname.replace(/\/*$/,"")
|
||||
};
|
||||
},
|
||||
sanitizeHost: function(host){
|
||||
var split = MistUtil.http.url.split(host);
|
||||
return split.protocol + "//" + split.host + (split.port && (split.port != "") ? ":"+split.port : "") + (split.hash && (split.hash != "") ? "#"+split.hash : "") + (split.path ? split.path : "");
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
css: {
|
||||
cache: {},
|
||||
load: function(url,colors,callback){
|
||||
var style = document.createElement("style");
|
||||
style.type = "text/css";
|
||||
style.setAttribute("data-source",url);
|
||||
if (callback) { style.callback = callback; }
|
||||
var cache = this.cache;
|
||||
|
||||
function onCSSLoad(d) {
|
||||
//parse rules and replace variables; expected syntax $abc[.abc]
|
||||
var css = MistUtil.css.applyColors(d,colors);
|
||||
|
||||
if ("callback" in style) { style.callback(css); }
|
||||
else { style.textContent = css; }
|
||||
}
|
||||
|
||||
if (url in cache) {
|
||||
if (cache[url] instanceof Array) {
|
||||
cache[url].push(onCSSLoad);
|
||||
}
|
||||
else {
|
||||
onCSSLoad(cache[url]);
|
||||
}
|
||||
}
|
||||
else {
|
||||
//retrieve file contents
|
||||
cache[url] = [onCSSLoad];
|
||||
MistUtil.http.get(url,function(d){
|
||||
for (var i in cache[url]) {
|
||||
cache[url][i](d);
|
||||
}
|
||||
cache[url] = d;
|
||||
},function(){
|
||||
throw "Failed to load CSS from "+url;
|
||||
});
|
||||
}
|
||||
|
||||
return style; //its empty now, but will be filled on load
|
||||
},
|
||||
applyColors: function(css,colors) {
|
||||
return css.replace(/\$([^\s^;^}]*)/g,function(str,variable){
|
||||
var index = variable.split(".");
|
||||
var val = colors;
|
||||
for (var j in index) {
|
||||
val = val[index[j]];
|
||||
}
|
||||
return val;
|
||||
});
|
||||
},
|
||||
createStyle: function(css,prepend,applyToChildren){
|
||||
var style = document.createElement("style");
|
||||
style.type = "text/css";
|
||||
|
||||
if (css) {
|
||||
if (prepend) {
|
||||
css = this.prependClass(css,prepend,applyToChildren);
|
||||
}
|
||||
style.textContent = css;
|
||||
}
|
||||
|
||||
return style;
|
||||
},
|
||||
prependClass: function (css,prepend,applyToChildren) {
|
||||
var style = false;
|
||||
if (typeof css != "string") {
|
||||
style = css;
|
||||
if (!("unprepended" in style)) {
|
||||
style.unprepended = style.textContent;
|
||||
}
|
||||
css = style.unprepended;
|
||||
}
|
||||
//remove all block comments
|
||||
css = css.replace(/\/\*.*?\*\//g,"");
|
||||
|
||||
//save all @{} blocks
|
||||
var save = css.match(/@.*?{.*}/g);
|
||||
for (var i in save) {
|
||||
css = css.replace(save[i],"@@@@");
|
||||
}
|
||||
|
||||
//find and replace selectors
|
||||
css = css.replace(/[^@]*?{[^]*?}/g,function(match){
|
||||
var split = match.split("{")
|
||||
var selectors = split[0].split(",");
|
||||
var properties = "{"+split.slice(1).join("}");
|
||||
|
||||
for (var i in selectors) {
|
||||
selectors[i] = selectors[i].trim();
|
||||
var str = "."+prepend+selectors[i];
|
||||
if (applyToChildren) {
|
||||
str += ",\n."+prepend+" "+selectors[i];
|
||||
}
|
||||
selectors[i] = str;
|
||||
}
|
||||
|
||||
|
||||
return "\n"+selectors+" "+properties;
|
||||
});
|
||||
|
||||
//reinsert saved blocks
|
||||
for (var i in save) {
|
||||
css = css.replace(/@@@@/,save[i]);
|
||||
}
|
||||
|
||||
if (style) {
|
||||
style.textContent = css;
|
||||
return;
|
||||
}
|
||||
|
||||
return css;
|
||||
}
|
||||
},
|
||||
|
||||
empty: function(DOMelement) {
|
||||
while (DOMelement.lastChild){
|
||||
if (DOMelement.lastChild.lastChild) {
|
||||
//also empty this child
|
||||
this.empty(DOMelement.lastChild);
|
||||
}
|
||||
if ("attachedListeners" in DOMelement.lastChild) {
|
||||
//remove attached event listeners
|
||||
for (var i in DOMelement.lastChild.attachedListeners) {
|
||||
MistUtil.event.removeListener(DOMelement.lastChild.attachedListeners[i]);
|
||||
}
|
||||
}
|
||||
DOMelement.removeChild(DOMelement.lastChild);
|
||||
}
|
||||
},
|
||||
|
||||
event: {
|
||||
send: function(type,message,target){
|
||||
try {
|
||||
var event = new Event(type,{
|
||||
bubbles: true,
|
||||
cancelable: true
|
||||
});
|
||||
event.message = message;
|
||||
target.dispatchEvent(event);
|
||||
}
|
||||
catch (e) {
|
||||
try {
|
||||
var event = document.createEvent('Event');
|
||||
event.initEvent(type,true,true);
|
||||
event.message = message;
|
||||
target.dispatchEvent(event);
|
||||
}
|
||||
catch (e) { return false; }
|
||||
}
|
||||
return true;
|
||||
},
|
||||
addListener: function(DOMelement,type,callback,storeOnElement) {
|
||||
//add an event listener and store the handles, so they can be cleared
|
||||
|
||||
DOMelement.addEventListener(type,callback);
|
||||
|
||||
if (!storeOnElement) { storeOnElement = DOMelement; }
|
||||
if (!("attachedListeners" in storeOnElement)) {
|
||||
storeOnElement.attachedListeners = [];
|
||||
}
|
||||
var output = {
|
||||
element: DOMelement,
|
||||
type: type,
|
||||
callback: callback
|
||||
};
|
||||
|
||||
storeOnElement.attachedListeners.push(output);
|
||||
return output;
|
||||
},
|
||||
removeListener: function(data) {
|
||||
data.element.removeEventListener(data.type, data.callback);
|
||||
}
|
||||
},
|
||||
|
||||
scripts: {
|
||||
list: {},
|
||||
insert: function(src,onevent,MistVideo){
|
||||
var scripts = this;
|
||||
|
||||
if (MistVideo) {
|
||||
//register so we can remove it on unload
|
||||
MistVideo.errorListeners.push({
|
||||
src: src,
|
||||
onevent: onevent
|
||||
});
|
||||
}
|
||||
if (src in this.list) {
|
||||
//already present
|
||||
//register to error listening
|
||||
this.list[src].subscribers.push(onevent.onerror);
|
||||
//execute onload
|
||||
if ("onload" in onevent) {
|
||||
if (this.hasLoaded) {
|
||||
onevent.onload();
|
||||
}
|
||||
else {
|
||||
MistUtil.event.addListener(this.list[src].tag,"load",onevent.onload);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
var scripttag = document.createElement("script");
|
||||
scripttag.hasLoaded = false;
|
||||
scripttag.setAttribute("src",src);
|
||||
scripttag.setAttribute("crossorigin","anonymous"); //must be set to get info about errors thrown
|
||||
document.head.appendChild(scripttag);
|
||||
scripttag.onerror = function(e){
|
||||
onevent.onerror(e);
|
||||
}
|
||||
scripttag.onload = function(e){
|
||||
this.hasLoaded = true;
|
||||
if (!MistVideo.destroyed) { onevent.onload(e); }
|
||||
}
|
||||
scripttag.addEventListener("error",function(e){
|
||||
onevent.onerror(e);
|
||||
});
|
||||
|
||||
|
||||
//error catching
|
||||
var oldonerror = false;
|
||||
if (window.onerror) {
|
||||
oldonerror = window.onerror;
|
||||
}
|
||||
window.onerror = function(message,source,line,column,error){
|
||||
if (oldonerror) {
|
||||
oldonerror.apply(this,arguments);
|
||||
}
|
||||
if (source == src) {
|
||||
onevent.onerror(error);
|
||||
for (var i in scripts.list[src].subscribers) {
|
||||
scripts.list[src].subscribers[i](error);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this.list[src] = {
|
||||
subscribers: [onevent.onerror],
|
||||
tag: scripttag
|
||||
};
|
||||
|
||||
return scripttag;
|
||||
}
|
||||
},
|
||||
|
||||
tracks: {
|
||||
parse: function(metaTracks){
|
||||
var output = {};
|
||||
for (var i in metaTracks) {
|
||||
var track = MistUtil.object.extend({},metaTracks[i]);
|
||||
if (track.type == "meta") {
|
||||
track.type = track.codec;
|
||||
track.codec = "meta";
|
||||
}
|
||||
|
||||
if (!(track.type in output)) { output[track.type] = {}; }
|
||||
output[track.type][track.trackid] = track;
|
||||
|
||||
//make up something logical for the track displayname
|
||||
var name = {};
|
||||
|
||||
for (var j in track) {
|
||||
switch (j) {
|
||||
case "width":
|
||||
name[j] = track.width+"×"+track.height;
|
||||
break;
|
||||
case "bps":
|
||||
if (track.codec == "meta") { continue; }
|
||||
if (track.bps > 0) {
|
||||
var val;
|
||||
if (track.bps > 1024*1024/8) {
|
||||
val = Math.round(track.bps/1024/1024*8)+"mbps";
|
||||
}
|
||||
else {
|
||||
val = Math.round(track.bps/1024*8)+"kbps";
|
||||
}
|
||||
name[j] = val;
|
||||
}
|
||||
break;
|
||||
case "fpks":
|
||||
if (track.fpks > 0) {
|
||||
name[j] = track.fpks/1e3+"fps";
|
||||
}
|
||||
break;
|
||||
case "channels":
|
||||
if (track.channels > 0) {
|
||||
name[j] = (track.channels == 1 ? "Mono" : (track.channels == 2 ? "Stereo" : "Surround ("+track.channels+"ch)"));
|
||||
}
|
||||
break;
|
||||
case "rate":
|
||||
name[j] = Math.round(track.rate)+"Khz";
|
||||
break;
|
||||
case "language":
|
||||
if (track[j] != "Undetermined") { name[j] = track[j]; }
|
||||
break;
|
||||
case "codec":
|
||||
if (track.codec == "meta") { continue; }
|
||||
name[j] = track[j];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
track.describe = name;
|
||||
|
||||
}
|
||||
|
||||
//filter what to display based on what is different
|
||||
for (var type in output) {
|
||||
var equal = false;
|
||||
for (var i in output[type]) {
|
||||
if (!equal) {
|
||||
//fill equal with all the keys and values of the first track of this type
|
||||
equal = MistUtil.object.extend({},output[type][i].describe);
|
||||
continue;
|
||||
}
|
||||
if (MistUtil.object.keys(output[type]).length > 1) {
|
||||
//if there is more than one track of this type
|
||||
for (var j in output[type][i].describe) {
|
||||
if (equal[j] != output[type][i].describe[j]) {
|
||||
//remove key from equal if not equal
|
||||
delete equal[j];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//apply
|
||||
for (var i in output[type]) {
|
||||
var different = {};
|
||||
var same = {};
|
||||
for (var j in output[type][i].describe) {
|
||||
if (!(j in equal)){
|
||||
different[j] = output[type][i].describe[j];
|
||||
}
|
||||
else {
|
||||
same[j] = output[type][i].describe[j];
|
||||
}
|
||||
}
|
||||
output[type][i].different = different;
|
||||
output[type][i].same = same;
|
||||
var d = MistUtil.object.values(different);
|
||||
output[type][i].displayName = (d.length ? d.join(", ") : MistUtil.object.values(output[type][i].describe).join(" "));
|
||||
}
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
},
|
||||
isTouchDevice: function(){
|
||||
return (('ontouchstart' in window) || (navigator.msMaxTouchPoints > 0));
|
||||
//return true;
|
||||
},
|
||||
getPos: function(element,cursorLocation){
|
||||
var style = element.currentStyle || window.getComputedStyle(element, null);
|
||||
|
||||
var zoom = 1;
|
||||
var node = element;
|
||||
while (node) {
|
||||
if ((node.style.zoom) && (node.style.zoom != "")) {
|
||||
zoom *= parseFloat(node.style.zoom,10);
|
||||
}
|
||||
node = node.parentElement;
|
||||
}
|
||||
|
||||
var pos0 = element.getBoundingClientRect().left - (parseInt(element.borderLeftWidth,10) || 0);
|
||||
|
||||
var width = element.getBoundingClientRect().width;;
|
||||
var perc = Math.max(0,((cursorLocation.clientX/zoom) - pos0) / width);
|
||||
perc = Math.min(perc,1);
|
||||
|
||||
return perc;
|
||||
},
|
||||
|
||||
createGraph: function(data,options){
|
||||
var ns = "http://www.w3.org/2000/svg";
|
||||
|
||||
var svg = document.createElementNS(ns,"svg");
|
||||
svg.setAttributeNS(null,"height","100%");
|
||||
svg.setAttributeNS(null,"width","100%");
|
||||
svg.setAttributeNS(null,"class","mist icon graph");
|
||||
svg.setAttributeNS(null,"preserveAspectRatio","none");
|
||||
|
||||
var x_correction = data.x[0];
|
||||
var lasty = data.y[0];
|
||||
if (options.differentiate) {
|
||||
for (var i = 1; i < data.y.length; i++) {
|
||||
var diff = data.y[i] - lasty;
|
||||
lasty = data.y[i];
|
||||
data.y[i] = diff;
|
||||
}
|
||||
}
|
||||
|
||||
var path = [];
|
||||
var area = {
|
||||
x: {
|
||||
min: data.x[0] - x_correction,
|
||||
max: data.x[0] - x_correction
|
||||
},
|
||||
y: {
|
||||
min: data.y[0]*-1,
|
||||
max: data.y[0]*-1
|
||||
}
|
||||
};
|
||||
|
||||
function updateMinMax(x,y) {
|
||||
if (arguments.length) {
|
||||
area.x.min = Math.min(area.x.min,x);
|
||||
area.x.max = Math.max(area.x.max,x);
|
||||
area.y.min = Math.min(area.y.min,y*-1);
|
||||
area.y.max = Math.max(area.y.max,y*-1);
|
||||
}
|
||||
else {
|
||||
//reprocess the entire path
|
||||
var d = path[0].split(",");
|
||||
area = {
|
||||
x: {
|
||||
min: d[0],
|
||||
max: d[0]
|
||||
},
|
||||
y: {
|
||||
min: d[1],
|
||||
max: d[1]
|
||||
}
|
||||
};
|
||||
for (var i = 1; i < path.length; i++) {
|
||||
var d = path[i].split(",");
|
||||
updateMinMax(d[0],d[1]*-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
path.push([data.x[0] - x_correction,data.y[0]*-1].join(","));
|
||||
for (var i = 1; i < data.y.length; i++) {
|
||||
updateMinMax(data.x[i] - x_correction,data.y[i]*-1);
|
||||
path.push("L "+[data.x[i] - x_correction,data.y[i]*-1].join(","));
|
||||
}
|
||||
|
||||
//define gradient
|
||||
var defs = document.createElementNS(ns,"defs");
|
||||
svg.appendChild(defs);
|
||||
var gradient = document.createElementNS(ns,"linearGradient");
|
||||
defs.appendChild(gradient);
|
||||
gradient.setAttributeNS(null,"id",MistUtil.createUnique());
|
||||
gradient.setAttributeNS(null,"gradientUnits","userSpaceOnUse");
|
||||
gradient.innerHTML += '<stop offset="0" stop-color="green"/>';
|
||||
gradient.innerHTML += '<stop offset="0.33" stop-color="yellow"/>';
|
||||
gradient.innerHTML += '<stop offset="0.66" stop-color="orange"/>';
|
||||
gradient.innerHTML += '<stop offset="1" stop-color="red"/>';
|
||||
|
||||
function updateViewBox() {
|
||||
if ("x" in options) {
|
||||
if ("min" in options.x) { area.x.min = options.x.min; }
|
||||
if ("max" in options.x) { area.x.max = options.x.max; }
|
||||
if ("count" in options.x) { area.x.min = area.x.max - options.x.count; }
|
||||
}
|
||||
if ("y" in options) {
|
||||
if ("min" in options.y) { area.y.min = options.y.max*-1; }
|
||||
if ("max" in options.y) { area.y.max = options.y.min*-1; }
|
||||
}
|
||||
svg.setAttributeNS(null,"viewBox",[area.x.min,area.y.min,area.x.max - area.x.min,area.y.max - area.y.min].join(" "));
|
||||
|
||||
gradient.setAttributeNS(null,"x1",0);
|
||||
gradient.setAttributeNS(null,"x2",0);
|
||||
if (options.reverseGradient) {
|
||||
gradient.setAttributeNS(null,"y1",area.y.max);
|
||||
gradient.setAttributeNS(null,"y2",area.y.min);
|
||||
}
|
||||
else {
|
||||
gradient.setAttributeNS(null,"y1",area.y.min);
|
||||
gradient.setAttributeNS(null,"y2",area.y.max);
|
||||
}
|
||||
}
|
||||
updateViewBox();
|
||||
|
||||
var line = document.createElementNS(ns,"path");
|
||||
svg.appendChild(line);
|
||||
//line.setAttributeNS(null,"vector-effect","non-scaling-stroke");
|
||||
line.setAttributeNS(null,"stroke-width","0.1");
|
||||
line.setAttributeNS(null,"fill","none");
|
||||
line.setAttributeNS(null,"stroke","url(#"+gradient.getAttribute("id")+")");
|
||||
line.setAttributeNS(null,"d","M"+path.join(" L"));
|
||||
|
||||
line.addData = function(newData) {
|
||||
|
||||
if (options.differentiate) {
|
||||
var diff = newData.y - lasty;
|
||||
lasty = newData.y;
|
||||
newData.y = diff;
|
||||
}
|
||||
|
||||
path.push([newData.x - x_correction,newData.y*-1].join(","));
|
||||
if (options.x && options.x.count) {
|
||||
if (path.length > options.x.count) {
|
||||
path.shift();
|
||||
updateMinMax();
|
||||
}
|
||||
}
|
||||
updateMinMax(newData.x - x_correction,newData.y*-1);
|
||||
this.setAttributeNS(null,"d","M"+path.join(" L"));
|
||||
updateViewBox();
|
||||
};
|
||||
svg.addData = function(newData){
|
||||
line.addData(newData);
|
||||
};
|
||||
|
||||
return svg;
|
||||
},
|
||||
getBrowser: function(){
|
||||
var ua = window.navigator.userAgent;
|
||||
|
||||
if ((ua.indexOf("MSIE ") >= 0) || (ua.indexOf("Trident/") >= 0)) {
|
||||
return "ie";
|
||||
}
|
||||
if (ua.indexOf("Edge/") >= 0) {
|
||||
return "edge";
|
||||
}
|
||||
if ((ua.indexOf("Opera") >= 0) || (ua.indexOf('OPR') >= 0)) {
|
||||
return "opera";
|
||||
}
|
||||
if (ua.indexOf("Chrome") >= 0) {
|
||||
return "chrome";
|
||||
}
|
||||
if (ua.indexOf("Safari") >= 0) {
|
||||
return "safari";
|
||||
}
|
||||
if (ua.indexOf("Firefox") >= 0) {
|
||||
return "firefox";
|
||||
}
|
||||
return false; //unknown
|
||||
}
|
||||
};
|
|
@ -1,162 +1,216 @@
|
|||
mistplayers.dashjs = {
|
||||
name: 'Dash.js Player',
|
||||
version: '1.2',
|
||||
mimes: ['dash/video/mp4'],
|
||||
priority: Object.keys(mistplayers).length + 1,
|
||||
name: "Dash.js player",
|
||||
mimes: ["dash/video/mp4"/*,"html5/application/vnd.ms-ss"*/],
|
||||
priority: MistUtil.object.keys(mistplayers).length + 1,
|
||||
isMimeSupported: function (mimetype) {
|
||||
return (this.mimes.indexOf(mimetype) == -1 ? false : true);
|
||||
return (MistUtil.array.indexOf(this.mimes,mimetype) == -1 ? false : true);
|
||||
},
|
||||
isBrowserSupported: function (mimetype,source,options) {
|
||||
if ((options.host.substr(0,7) == 'http://') && (source.url.substr(0,8) == 'https://')) { return false; }
|
||||
return (('MediaSource' in window) && (location.protocol != 'file:'));
|
||||
isBrowserSupported: function (mimetype,source,MistVideo) {
|
||||
|
||||
//check for http/https mismatch
|
||||
if (location.protocol != MistUtil.http.url.split(source.url).protocol) {
|
||||
MistVideo.log("HTTP/HTTPS mismatch for this source");
|
||||
return false;
|
||||
}
|
||||
|
||||
//don't use dashjs if this location is loaded over file://
|
||||
if (location.protocol == "file:") {
|
||||
MistVideo.log("This source ("+mimetype+") won't load if the page is run via file://");
|
||||
return false;
|
||||
}
|
||||
|
||||
return ("MediaSource" in window);
|
||||
},
|
||||
player: function(){this.onreadylist = [];}
|
||||
player: function(){this.onreadylist = [];},
|
||||
scriptsrc: function(host) { return host+"/dashjs.js"; }
|
||||
};
|
||||
var p = mistplayers.dashjs.player;
|
||||
p.prototype = new MistPlayer();
|
||||
p.prototype.build = function (options,callback) {
|
||||
var cont = document.createElement('div');
|
||||
cont.className = 'mistplayer';
|
||||
p.prototype.build = function (MistVideo,callback) {
|
||||
var me = this;
|
||||
|
||||
function onplayerload () {
|
||||
var ele = me.getElement('video');
|
||||
ele.className = '';
|
||||
cont.appendChild(ele);
|
||||
ele.width = options.width;
|
||||
ele.height = options.height;
|
||||
this.onDashLoad = function() {
|
||||
if (MistVideo.destroyed) { return; }
|
||||
|
||||
if (options.autoplay) {
|
||||
ele.setAttribute('autoplay','');
|
||||
}
|
||||
if (options.loop) {
|
||||
ele.setAttribute('loop','');
|
||||
}
|
||||
if (options.poster) {
|
||||
ele.setAttribute('poster',options.poster);
|
||||
}
|
||||
if (options.controls) {
|
||||
if (options.controls == 'stock') {
|
||||
ele.setAttribute('controls','');
|
||||
}
|
||||
else {
|
||||
me.buildMistControls();
|
||||
}
|
||||
}
|
||||
MistVideo.log("Building DashJS player..");
|
||||
|
||||
ele.addEventListener('error',function(e){
|
||||
var msg;
|
||||
if ('message' in e) {
|
||||
msg = e.message;
|
||||
var ele = document.createElement("video");
|
||||
|
||||
if ("Proxy" in window) {
|
||||
var overrides = {
|
||||
get: {},
|
||||
set: {}
|
||||
};
|
||||
|
||||
MistVideo.player.api = new Proxy(ele,{
|
||||
get: function(target, key, receiver){
|
||||
if (key in overrides.get) {
|
||||
return overrides.get[key].apply(target, arguments);
|
||||
}
|
||||
else {
|
||||
msg = 'readyState: ';
|
||||
switch (me.element.readyState) {
|
||||
case 0:
|
||||
msg += 'HAVE_NOTHING';
|
||||
break;
|
||||
case 1:
|
||||
msg += 'HAVE_METADATA';
|
||||
break;
|
||||
case 2:
|
||||
msg += 'HAVE_CURRENT_DATA';
|
||||
break;
|
||||
case 3:
|
||||
msg += 'HAVE_FUTURE_DATA';
|
||||
break;
|
||||
case 4:
|
||||
msg += 'HAVE_ENOUGH_DATA';
|
||||
break;
|
||||
}
|
||||
msg += ' networkState: ';
|
||||
switch (me.element.networkState) {
|
||||
case 0:
|
||||
msg += 'NETWORK_EMPTY';
|
||||
break;
|
||||
case 1:
|
||||
msg += 'NETWORK_IDLE';
|
||||
break;
|
||||
case 2:
|
||||
msg += 'NETWORK_LOADING';
|
||||
break;
|
||||
case 3:
|
||||
msg += 'NETWORK_NO_SOURCE';
|
||||
break;
|
||||
var method = target[key];
|
||||
if (typeof method === "function"){
|
||||
return function () {
|
||||
return method.apply(target, arguments);
|
||||
}
|
||||
}
|
||||
//prevent onerror loops
|
||||
if (e.target == me.element) {
|
||||
e.message = msg;
|
||||
return method;
|
||||
},
|
||||
set: function(target, key, value) {
|
||||
if (key in overrides.set) {
|
||||
return overrides.set[key].call(target,value);
|
||||
}
|
||||
else {
|
||||
me.adderror(msg);
|
||||
return target[key] = value;
|
||||
}
|
||||
});
|
||||
var events = ['abort','canplay','canplaythrough','durationchange','emptied','ended','interruptbegin','interruptend','loadeddata','loadedmetadata','loadstart','pause','play','playing','ratechange','seeked','seeking','stalled','volumechange','waiting'];
|
||||
for (var i in events) {
|
||||
ele.addEventListener(events[i],function(e){
|
||||
me.addlog('Player event fired: '+e.type);
|
||||
|
||||
if (MistVideo.info.type == "live") {
|
||||
overrides.get.duration = function(){
|
||||
//this should indicate the end of Mist's buffer
|
||||
var buffer_end = 0;
|
||||
if (this.buffered.length) {
|
||||
buffer_end = this.buffered.end(this.buffered.length-1)
|
||||
}
|
||||
var time_since_buffer = (new Date().getTime() - MistVideo.player.api.lastProgress.getTime())*1e-3;
|
||||
return buffer_end + time_since_buffer + -1*MistVideo.player.api.liveOffset + 45;
|
||||
};
|
||||
overrides.set.currentTime = function(value){
|
||||
var offset = value - MistVideo.player.api.duration;
|
||||
//MistVideo.player.api.liveOffset = offset;
|
||||
|
||||
MistVideo.log("Seeking to "+MistUtil.format.time(value)+" ("+Math.round(offset*-10)/10+"s from live)");
|
||||
|
||||
MistVideo.video.currentTime = value;
|
||||
//.player.api.setSource(MistUtil.http.url.addParam(MistVideo.source.url,{startunix:offset}));
|
||||
}
|
||||
MistUtil.event.addListener(ele,"progress",function(){
|
||||
MistVideo.player.api.lastProgress = new Date();
|
||||
});
|
||||
MistVideo.player.api.lastProgress = new Date();
|
||||
MistVideo.player.api.liveOffset = 0;
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
me.api = ele;
|
||||
}
|
||||
|
||||
if (MistVideo.options.autoplay) {
|
||||
ele.setAttribute("autoplay","");
|
||||
}
|
||||
if ((MistVideo.options.loop) && (MistVideo.info.type != "live")) {
|
||||
ele.setAttribute("loop","");
|
||||
}
|
||||
if (MistVideo.options.poster) {
|
||||
ele.setAttribute("poster",MistVideo.options.poster);
|
||||
}
|
||||
if (MistVideo.options.controls == "stock") {
|
||||
ele.setAttribute("controls","");
|
||||
}
|
||||
|
||||
var player = dashjs.MediaPlayer().create();
|
||||
player.getDebug().setLogToBrowserConsole(false);
|
||||
player.initialize(ele,options.src,true);
|
||||
//player.getDebug().setLogToBrowserConsole(false);
|
||||
player.initialize(ele,MistVideo.source.url,MistVideo.options.autoplay);
|
||||
|
||||
|
||||
me.dash = player;
|
||||
me.src = options.src;
|
||||
|
||||
|
||||
me.addlog('Built html');
|
||||
callback(cont);
|
||||
//add listeners for events that we can log
|
||||
var skipEvents = ["METRIC_ADDED","METRIC_CHANGED","METRICS_CHANGED","FRAGMENT_LOADING_STARTED","FRAGMENT_LOADING_COMPLETED","LOG","PLAYBACK_TIME_UPDATED","PLAYBACK_PROGRESS"];
|
||||
for (var i in dashjs.MediaPlayer.events) {
|
||||
if (skipEvents.indexOf(i) < 0) {
|
||||
me.dash.on(dashjs.MediaPlayer.events[i],function(e){
|
||||
MistVideo.log("Player event fired: "+e.type);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if ('dash' in window) {
|
||||
onplayerload();
|
||||
}
|
||||
else {
|
||||
//load the dashjs player
|
||||
var scripttag = document.createElement('script');
|
||||
scripttag.src = options.host+'/dashjs.js';
|
||||
me.addlog('Retrieving dashjs player code from '+scripttag.src);
|
||||
document.head.appendChild(scripttag);
|
||||
scripttag.onerror = function(){
|
||||
me.askNextCombo('Failed to load dashjs.js');
|
||||
}
|
||||
scripttag.onload = function(){
|
||||
onplayerload();
|
||||
}
|
||||
}
|
||||
}
|
||||
p.prototype.play = function(){ return this.element.play(); };
|
||||
p.prototype.pause = function(){ return this.element.pause(); };
|
||||
p.prototype.volume = function(level){
|
||||
if (typeof level == 'undefined' ) { return this.element.volume; }
|
||||
return this.element.volume = level;
|
||||
MistVideo.player.setSize = function(size){
|
||||
this.api.style.width = size.width+"px";
|
||||
this.api.style.height = size.height+"px";
|
||||
};
|
||||
p.prototype.play = function(){ return this.element.play(); };
|
||||
p.prototype.load = function(){ return this.element.load(); };
|
||||
if (document.fullscreenEnabled || document.webkitFullscreenEnabled || document.mozFullScreenEnabled || document.msFullscreenEnabled) {
|
||||
p.prototype.fullscreen = function(){
|
||||
if(this.element.requestFullscreen) {
|
||||
return this.element.requestFullscreen();
|
||||
} else if(this.element.mozRequestFullScreen) {
|
||||
return this.element.mozRequestFullScreen();
|
||||
} else if(this.element.webkitRequestFullscreen) {
|
||||
return this.element.webkitRequestFullscreen();
|
||||
} else if(this.element.msRequestFullscreen) {
|
||||
return this.element.msRequestFullscreen();
|
||||
}
|
||||
MistVideo.player.api.setSource = function(url) {
|
||||
MistVideo.player.dash.attachSource(url);
|
||||
};
|
||||
}
|
||||
p.prototype.resize = function(size){
|
||||
this.element.width = size.width;
|
||||
this.element.height = size.height;
|
||||
};
|
||||
p.prototype.updateSrc = function(src){
|
||||
if (src == '') {
|
||||
this.dash.reset();
|
||||
|
||||
//trackswitching
|
||||
MistVideo.player.api.setTrack = function(type,id){
|
||||
var meta = MistUtil.tracks.parse(MistVideo.info.meta.tracks);
|
||||
if ((!(type in meta)) || ((!(id in meta[type]) && (id != 0)))) {
|
||||
MistVideo.log("Skipping trackselection of "+type+" track "+id+" because it does not exist");
|
||||
return;
|
||||
}
|
||||
this.dash.attachSource(src);
|
||||
return true;
|
||||
|
||||
//figure out what the track number is
|
||||
//whyyyy did it have to be reverse order
|
||||
var n = me.dash.getBitrateInfoListFor("video").length - 1;
|
||||
for (var i in MistVideo.info.meta.tracks) {
|
||||
var t = MistVideo.info.meta.tracks[i];
|
||||
if (t.type == type) {
|
||||
if (t.trackid == id) { break; }
|
||||
n--;
|
||||
}
|
||||
}
|
||||
|
||||
me.dash.setAutoSwitchQualityFor(type,false); //turn off ABR rules //TODO do we want this by default?
|
||||
me.dash.setFastSwitchEnabled(true); //show the new track asap
|
||||
me.dash.setQualityFor(type,n);
|
||||
//dash does change the track, but is appended to the buffer, so it seems to take a while..
|
||||
}
|
||||
|
||||
//react to automatic trackswitching
|
||||
me.dash.on("qualityChangeRendered",function(e){
|
||||
//the newQuality-th track of type mediaType is being selected
|
||||
|
||||
//figure out the track id
|
||||
//whyyyy did it have to be reverse order
|
||||
var n = me.dash.getBitrateInfoListFor("video").length - 1;
|
||||
var id;
|
||||
for (var i in MistVideo.info.meta.tracks) {
|
||||
var t = MistVideo.info.meta.tracks[i];
|
||||
if (t.type == e.mediaType) {
|
||||
if (e.newQuality == n) {
|
||||
id = t.trackid;
|
||||
break;
|
||||
}
|
||||
n--;
|
||||
}
|
||||
}
|
||||
|
||||
//create an event to pass this to the skin
|
||||
MistUtil.event.send("playerUpdate_trackChanged",{
|
||||
type: e.mediaType,
|
||||
trackid: id
|
||||
},MistVideo.video);
|
||||
|
||||
});
|
||||
|
||||
//dashjs keeps on spamming the stalled icon >_>
|
||||
MistUtil.event.addListener(ele,"progress",function(e){
|
||||
if (MistVideo.container.getAttribute("data-loading") == "stalled") {
|
||||
MistVideo.container.removeAttribute("data-loading");
|
||||
}
|
||||
});
|
||||
|
||||
me.api.unload = function(){
|
||||
me.dash.reset();
|
||||
};
|
||||
|
||||
MistVideo.log("Built html");
|
||||
callback(ele);
|
||||
}
|
||||
|
||||
if ("dashjs" in window) {
|
||||
this.onDashLoad();
|
||||
}
|
||||
else {
|
||||
|
||||
var scripttag = MistUtil.scripts.insert(MistVideo.urlappend(mistplayers.dashjs.scriptsrc(MistVideo.options.host)),{
|
||||
onerror: function(e){
|
||||
var msg = "Failed to load dashjs.js";
|
||||
if (e.message) { msg += ": "+e.message; }
|
||||
MistVideo.showError(msg);
|
||||
},
|
||||
onload: me.onDashLoad
|
||||
},MistVideo);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,26 +1,37 @@
|
|||
mistplayers.flash_strobe = {
|
||||
name: 'Strobe Flash Media Playback',
|
||||
version: '1.1',
|
||||
mimes: ['flash/10','flash/11','flash/7'],
|
||||
priority: Object.keys(mistplayers).length + 1,
|
||||
name: "Strobe Flash media playback",
|
||||
mimes: ["flash/10","flash/11","flash/7"],
|
||||
priority: MistUtil.object.keys(mistplayers).length + 1,
|
||||
isMimeSupported: function (mimetype) {
|
||||
return (this.mimes.indexOf(mimetype) == -1 ? false : true);
|
||||
},
|
||||
isBrowserSupported: function (mimetype,source,options) {
|
||||
//check for http / https crossovers
|
||||
if ((options.host.substr(0,7) == 'http://') && (source.url.substr(0,8) == 'https://')) { return false; }
|
||||
isBrowserSupported: function (mimetype,source,MistVideo) {
|
||||
|
||||
//check for http/https mismatch
|
||||
if ((MistUtil.http.url.split(source.url).protocol.slice(0,4) == "http") && (location.protocol != MistUtil.http.url.split(source.url).protocol)) {
|
||||
MistVideo.log("HTTP/HTTPS mismatch for this source");
|
||||
return false;
|
||||
}
|
||||
|
||||
var version = 0;
|
||||
try {
|
||||
// check in the mimeTypes
|
||||
version = navigator.mimeTypes['application/x-shockwave-flash'].enabledPlugin.description.replace(/([^0-9\.])/g, '').split('.')[0];
|
||||
var plugin = navigator.mimeTypes["application/x-shockwave-flash"].enabledPlugin;
|
||||
if (plugin.version) { version = plugin.version.split(".")[0]; }
|
||||
else { version = plugin.description.replace(/([^0-9\.])/g, "").split(".")[0]; }
|
||||
} catch(e){}
|
||||
try {
|
||||
// for our special friend IE
|
||||
version = new ActiveXObject('ShockwaveFlash.ShockwaveFlash').GetVariable("$version").replace(/([^0-9\,])/g, '').split(',')[0];
|
||||
version = new ActiveXObject("ShockwaveFlash.ShockwaveFlash").GetVariable("$version").replace(/([^0-9\,])/g, "").split(",")[0];
|
||||
} catch(e){}
|
||||
|
||||
var mimesplit = mimetype.split('/');
|
||||
if (!version) {
|
||||
//flash is not enabled? Might need to ask permission first.
|
||||
//TODO how? just let it build?
|
||||
return false;
|
||||
}
|
||||
|
||||
var mimesplit = mimetype.split("/");
|
||||
|
||||
return Number(version) >= Number(mimesplit[mimesplit.length-1]);
|
||||
},
|
||||
|
@ -28,39 +39,53 @@ mistplayers.flash_strobe = {
|
|||
};
|
||||
var p = mistplayers.flash_strobe.player;
|
||||
p.prototype = new MistPlayer();
|
||||
p.prototype.build = function (options,callback) {
|
||||
p.prototype.build = function (MistVideo,callback) {
|
||||
|
||||
var ele = document.createElement("object");
|
||||
var e = document.createElement("embed");
|
||||
ele.appendChild(e);
|
||||
|
||||
function build(source) {
|
||||
var options = MistVideo.options;
|
||||
function createParam(name,value) {
|
||||
var p = document.createElement('param');
|
||||
p.setAttribute('name',name);
|
||||
p.setAttribute('value',value);
|
||||
var p = document.createElement("param");
|
||||
p.setAttribute("name",name);
|
||||
p.setAttribute("value",value);
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
var ele = this.getElement('object');
|
||||
|
||||
ele.setAttribute('width',options.width);
|
||||
ele.setAttribute('height',options.height);
|
||||
|
||||
ele.appendChild(createParam('movie',options.host+options.source.player_url));
|
||||
var flashvars = 'src='+encodeURIComponent(options.src)+'&controlBarMode='+(options.controls ? 'floating' : 'none')+'&initialBufferTime=0.5&expandedBufferTime=5&minContinuousPlaybackTime=3'+(options.live ? '&streamType=live' : '')+(options.autoplay ? '&autoPlay=true' : '' );
|
||||
ele.appendChild(createParam('flashvars',flashvars));
|
||||
ele.appendChild(createParam('allowFullScreen','true'));
|
||||
ele.appendChild(createParam('wmode','direct'));
|
||||
MistUtil.empty(ele);
|
||||
ele.appendChild(createParam("movie",MistVideo.urlappend(options.host+MistVideo.source.player_url)));
|
||||
var flashvars = "src="+encodeURIComponent(source)+"&controlBarMode="+(options.controls ? "floating" : "none")+"&initialBufferTime=0.5&expandedBufferTime=5&minContinuousPlaybackTime=3"+(options.live ? "&streamType=live" : "")+(options.autoplay ? "&autoPlay=true" : "" );
|
||||
ele.appendChild(createParam("flashvars",flashvars));
|
||||
ele.appendChild(createParam("allowFullScreen","true"));
|
||||
ele.appendChild(createParam("wmode","direct"));
|
||||
if (options.autoplay) {
|
||||
ele.appendChild(createParam('autoPlay','true'));
|
||||
ele.appendChild(createParam("autoPlay","true"));
|
||||
}
|
||||
|
||||
var e = document.createElement('embed');
|
||||
ele.appendChild(e);
|
||||
e.setAttribute('src',options.source.player_url);
|
||||
e.setAttribute('type','application/x-shockwave-flash');
|
||||
e.setAttribute('allowfullscreen','true');
|
||||
e.setAttribute('width',options.width);
|
||||
e.setAttribute('height',options.height);
|
||||
e.setAttribute('flashvars',flashvars);
|
||||
e.setAttribute("src",MistVideo.urlappend(MistVideo.source.player_url));
|
||||
e.setAttribute("type","application/x-shockwave-flash");
|
||||
e.setAttribute("allowfullscreen","true");
|
||||
e.setAttribute("flashvars",flashvars);
|
||||
}
|
||||
build(MistVideo.source.url);
|
||||
|
||||
this.api = {};
|
||||
this.setSize = function(size){
|
||||
ele.setAttribute("width",size.width);
|
||||
ele.setAttribute("height",size.height);
|
||||
e.setAttribute("width",size.width);
|
||||
e.setAttribute("height",size.height);
|
||||
};
|
||||
this.setSize(MistVideo.calcSize());
|
||||
this.onready(function(){
|
||||
if (MistVideo.container) { MistVideo.container.removeAttribute("data-loading"); }
|
||||
});
|
||||
this.api.setSource = function(url){
|
||||
build(url);
|
||||
}
|
||||
|
||||
this.addlog('Built html');
|
||||
MistVideo.log("Built html");
|
||||
callback(ele);
|
||||
}
|
||||
|
|
|
@ -1,29 +1,87 @@
|
|||
mistplayers.html5 = {
|
||||
name: 'HTML5 video player',
|
||||
version: '1.1',
|
||||
mimes: ['html5/application/vnd.apple.mpegurl','html5/video/mp4','html5/video/ogg','html5/video/webm','html5/audio/mp3','html5/audio/webm','html5/audio/ogg','html5/audio/wav'],
|
||||
priority: Object.keys(mistplayers).length + 1,
|
||||
name: "HTML5 video player",
|
||||
mimes: ["html5/application/vnd.apple.mpegurl","html5/video/mp4","html5/video/ogg","html5/video/webm","html5/audio/mp3","html5/audio/webm","html5/audio/ogg","html5/audio/wav"],
|
||||
priority: MistUtil.object.keys(mistplayers).length + 1,
|
||||
isMimeSupported: function (mimetype) {
|
||||
return (this.mimes.indexOf(mimetype) == -1 ? false : true);
|
||||
return (MistUtil.array.indexOf(this.mimes,mimetype) == -1 ? false : true);
|
||||
},
|
||||
isBrowserSupported: function (mimetype,source,options,streaminfo) {
|
||||
if ((['iPad','iPhone','iPod','MacIntel'].indexOf(navigator.platform) != -1) && (mimetype == 'html5/video/mp4')) { return false; }
|
||||
isBrowserSupported: function (mimetype,source,MistVideo) {
|
||||
|
||||
var support = false;
|
||||
var shortmime = mimetype.split('/');
|
||||
shortmime.shift();
|
||||
|
||||
if ((shortmime[0] == 'audio') && (streaminfo.height) && (!options.forceType) && (!options.forceSource)) {
|
||||
//claim you don't support audio-only playback if there is video data, unless this mime is being forced
|
||||
//check for http/https mismatch
|
||||
if (location.protocol != MistUtil.http.url.split(source.url).protocol) {
|
||||
if ((location.protocol == "file:") && (MistUtil.http.url.split(source.url).protocol == "http:")) {
|
||||
MistVideo.log("This page was loaded over file://, the player might not behave as intended.");
|
||||
}
|
||||
else {
|
||||
MistVideo.log("HTTP/HTTPS mismatch for this source");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var support = false;
|
||||
var shortmime = mimetype.split("/");
|
||||
shortmime.shift();
|
||||
|
||||
try {
|
||||
var v = document.createElement((shortmime[0] == 'audio' ? 'audio' : 'video'));
|
||||
shortmime = shortmime.join('/')
|
||||
if ((v) && (v.canPlayType(shortmime) != "")) {
|
||||
support = v.canPlayType(shortmime);
|
||||
shortmime = shortmime.join("/");
|
||||
|
||||
function test(mime) {
|
||||
var v = document.createElement("video");
|
||||
if ((v) && (v.canPlayType(mime) != "")) {
|
||||
support = v.canPlayType(mime);
|
||||
}
|
||||
return support;
|
||||
}
|
||||
|
||||
if (shortmime == "video/mp4") {
|
||||
function translateCodec(track) {
|
||||
|
||||
function bin2hex(index) {
|
||||
return ("0"+track.init.charCodeAt(index).toString(16)).slice(-2);
|
||||
}
|
||||
|
||||
switch (track.codec) {
|
||||
case "AAC":
|
||||
return "mp4a.40.2";
|
||||
case "MP3":
|
||||
return "mp3";
|
||||
//return "mp4a.40.34";
|
||||
case "AC3":
|
||||
return "ec-3";
|
||||
case "H264":
|
||||
return "avc1."+bin2hex(1)+bin2hex(2)+bin2hex(3);
|
||||
case "HEVC":
|
||||
return "hev1."+bin2hex(1)+bin2hex(6)+bin2hex(7)+bin2hex(8)+bin2hex(9)+bin2hex(10)+bin2hex(11)+bin2hex(12);
|
||||
default:
|
||||
return track.codec.toLowerCase();
|
||||
}
|
||||
|
||||
}
|
||||
var codecs = {};
|
||||
for (var i in MistVideo.info.meta.tracks) {
|
||||
if (MistVideo.info.meta.tracks[i].type != "meta") {
|
||||
codecs[translateCodec(MistVideo.info.meta.tracks[i])] = 1;
|
||||
}
|
||||
}
|
||||
codecs = MistUtil.object.keys(codecs);
|
||||
if (codecs.length) {
|
||||
if (codecs.length > source.simul_tracks) {
|
||||
//not all of the tracks have to work
|
||||
var working = 0;
|
||||
for (var i in codecs) {
|
||||
var s = test(shortmime+";codecs=\""+codecs[i]+"\"");
|
||||
if (s) {
|
||||
working++;
|
||||
}
|
||||
}
|
||||
return (working >= source.simul_tracks);
|
||||
}
|
||||
shortmime += ";codecs=\""+codecs.join(",")+"\"";
|
||||
}
|
||||
}
|
||||
|
||||
support = test(shortmime);
|
||||
} catch(e){}
|
||||
return support;
|
||||
},
|
||||
|
@ -34,206 +92,159 @@ mistplayers.html5 = {
|
|||
};
|
||||
var p = mistplayers.html5.player;
|
||||
p.prototype = new MistPlayer();
|
||||
p.prototype.build = function (options,callback) {
|
||||
var cont = document.createElement('div');
|
||||
cont.className = 'mistplayer';
|
||||
var me = this; //to allow nested functions to access the player class itself
|
||||
|
||||
var shortmime = options.source.type.split('/');
|
||||
p.prototype.build = function (MistVideo,callback) {
|
||||
var shortmime = MistVideo.source.type.split("/");
|
||||
shortmime.shift();
|
||||
var video = document.createElement("video");
|
||||
|
||||
var ele = this.getElement((shortmime[0] == 'audio' ? 'audio' : 'video'));
|
||||
ele.className = '';
|
||||
cont.appendChild(ele);
|
||||
//TODO verify: not required if player is loaded from same domain as it should always be when not in dev mode?
|
||||
video.setAttribute("crossorigin","anonymous");//required for subs, breaks ogg?
|
||||
|
||||
if (options.source.type != "html5/video/ogg") {
|
||||
ele.crossOrigin = 'anonymous'; //required for subtitles, but if ogg, the video won't load
|
||||
}
|
||||
var source = document.createElement("source");
|
||||
source.setAttribute("src",MistVideo.source.url);
|
||||
video.source = source;
|
||||
video.appendChild(source);
|
||||
source.type = shortmime.join("/");
|
||||
|
||||
if (shortmime[0] == 'audio') {
|
||||
this.setTracks = function() { return false; }
|
||||
this.fullscreen = false;
|
||||
cont.className += ' audio';
|
||||
}
|
||||
|
||||
this.addlog('Building HTML5 player..');
|
||||
|
||||
var source = document.createElement('source');
|
||||
source.setAttribute('src',options.src);
|
||||
this.source = source;
|
||||
ele.appendChild(source);
|
||||
source.type = shortmime.join('/');
|
||||
this.addlog('Adding '+source.type+' source @ '+options.src);
|
||||
|
||||
if ((this.tracks.subtitle.length) && (this.subtitle)) {
|
||||
for (var i in this.tracks.subtitle) {
|
||||
var t = document.createElement('track');
|
||||
ele.appendChild(t);
|
||||
t.kind = 'subtitles';
|
||||
t.label = this.tracks.subtitle[i].desc;
|
||||
t.srclang = this.tracks.subtitle[i].lang;
|
||||
t.src = this.subtitle+'?track='+this.tracks.subtitle[i].trackid;
|
||||
//apply options
|
||||
var attrs = ["autoplay","loop","poster"];
|
||||
for (var i in attrs) {
|
||||
var attr = attrs[i];
|
||||
if (MistVideo.options[attr]) {
|
||||
video.setAttribute(attr,(MistVideo.options[attr] === true ? "" : MistVideo.options[attr]));
|
||||
}
|
||||
}
|
||||
|
||||
ele.width = options.width;
|
||||
ele.height = options.height;
|
||||
ele.style.width = options.width+'px';
|
||||
ele.style.height = options.height+'px';
|
||||
|
||||
if (options.autoplay) {
|
||||
ele.setAttribute('autoplay','');
|
||||
}
|
||||
if (options.loop) {
|
||||
ele.setAttribute('loop','');
|
||||
}
|
||||
if (options.poster) {
|
||||
ele.setAttribute('poster',options.poster);
|
||||
}
|
||||
if (options.controls) {
|
||||
if ((options.controls == 'stock') || (!this.buildMistControls())) {
|
||||
//MistControls have failed to build in the if condition
|
||||
ele.setAttribute('controls','');
|
||||
if (MistVideo.options.controls == "stock") {
|
||||
video.setAttribute("controls","");
|
||||
}
|
||||
if (MistVideo.info.type == "live") {
|
||||
video.loop = false;
|
||||
}
|
||||
|
||||
cont.onclick = function(){
|
||||
if (ele.paused) { ele.play(); }
|
||||
else { ele.pause(); }
|
||||
if (("Proxy" in window) && ("Reflect" in window)) {
|
||||
var overrides = {
|
||||
get: {},
|
||||
set: {}
|
||||
};
|
||||
|
||||
this.addlog('Built html');
|
||||
|
||||
//forward events
|
||||
ele.addEventListener('error',function(e){
|
||||
if (!e.isTrusted) { return; } //don't trigger on errors we have thrown ourselves
|
||||
|
||||
if (options.live) {
|
||||
if ((ele.error) && (ele.error.code == 3)) {
|
||||
e.stopPropagation(); //dont let this error continue to prevent the core from trying to handle the error
|
||||
me.load();
|
||||
me.cancelAskNextCombo();
|
||||
e.message = 'Handled decoding error';
|
||||
me.addlog('Decoding error: reloading..');
|
||||
me.report({
|
||||
type: 'playback',
|
||||
warn: 'A decoding error was encountered, but handled'
|
||||
MistVideo.player.api = new Proxy(video,{
|
||||
get: function(target, key, receiver){
|
||||
if (key in overrides.get) {
|
||||
return overrides.get[key].apply(target, arguments);
|
||||
}
|
||||
var method = target[key];
|
||||
if (typeof method === "function"){
|
||||
return function () {
|
||||
return method.apply(target, arguments);
|
||||
}
|
||||
}
|
||||
return method;
|
||||
},
|
||||
set: function(target, key, value) {
|
||||
if (key in overrides.set) {
|
||||
return overrides.set[key].call(target,value);
|
||||
}
|
||||
return target[key] = value;
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (MistVideo.source.type == "html5/audio/mp3") {
|
||||
overrides.set.currentTime = function(){
|
||||
MistVideo.log("Seek attempted, but MistServer does not currently support seeking in MP3.");
|
||||
return false;
|
||||
}
|
||||
|
||||
var msg;
|
||||
if ('message' in e) {
|
||||
msg = e.message;
|
||||
}
|
||||
else if ((e.target.tagName == 'SOURCE') && (e.target.getAttribute('src') == '')) {
|
||||
e.stopPropagation();
|
||||
//this error is triggered because the unload function was fired
|
||||
return;
|
||||
if (MistVideo.info.type == "live") {
|
||||
|
||||
overrides.get.duration = function(){
|
||||
//this should indicate the end of Mist's buffer
|
||||
var buffer_end = 0;
|
||||
if (this.buffered.length) {
|
||||
buffer_end = this.buffered.end(this.buffered.length-1)
|
||||
}
|
||||
var time_since_buffer = (new Date().getTime() - MistVideo.player.api.lastProgress.getTime())*1e-3;
|
||||
return buffer_end + time_since_buffer - MistVideo.player.api.liveOffset;
|
||||
};
|
||||
overrides.set.currentTime = function(value){
|
||||
var offset = value - MistVideo.player.api.duration;
|
||||
MistVideo.player.api.liveOffset = offset;
|
||||
|
||||
MistVideo.log("Seeking to "+MistUtil.format.time(value)+" ("+Math.round(offset*-10)/10+"s from live)");
|
||||
|
||||
MistVideo.player.api.setSource(MistUtil.http.url.addParam(MistVideo.source.url,{startunix:offset}));
|
||||
}
|
||||
MistUtil.event.addListener(video,"progress",function(){
|
||||
MistVideo.player.api.lastProgress = new Date();
|
||||
});
|
||||
MistVideo.player.api.lastProgress = new Date();
|
||||
MistVideo.player.api.liveOffset = 0;
|
||||
|
||||
|
||||
MistUtil.event.addListener(video,"pause",function(){
|
||||
MistVideo.player.api.pausedAt = new Date();
|
||||
});
|
||||
overrides.get.play = function(){
|
||||
return function(){
|
||||
if ((MistVideo.player.api.paused) && (MistVideo.player.api.pausedAt) && ((new Date()) - MistVideo.player.api.pausedAt > 5e3)) {
|
||||
video.load();
|
||||
MistVideo.log("Reloading source..");
|
||||
}
|
||||
|
||||
return video.play.apply(video, arguments);
|
||||
}
|
||||
};
|
||||
|
||||
if (MistVideo.source.type == "html5/video/mp4") {
|
||||
overrides.get.currentTime = function(){
|
||||
return this.currentTime - MistVideo.player.api.liveOffset + MistVideo.info.lastms * 1e-3;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
msg = 'readyState: ';
|
||||
switch (me.element.readyState) {
|
||||
case 0:
|
||||
msg += 'HAVE_NOTHING';
|
||||
break;
|
||||
case 1:
|
||||
msg += 'HAVE_METADATA';
|
||||
break;
|
||||
case 2:
|
||||
msg += 'HAVE_CURRENT_DATA';
|
||||
break;
|
||||
case 3:
|
||||
msg += 'HAVE_FUTURE_DATA';
|
||||
break;
|
||||
case 4:
|
||||
msg += 'HAVE_ENOUGH_DATA';
|
||||
break;
|
||||
if (!isFinite(video.duration)) {
|
||||
var duration = 0;
|
||||
for (var i in MistVideo.info.meta.tracks) {
|
||||
duration = Math.max(duration,MistVideo.info.meta.tracks[i].lastms);
|
||||
}
|
||||
overrides.get.duration = function(){
|
||||
if (isFinite(this.duration)) { return this.duration; }
|
||||
return duration * 1e-3;
|
||||
}
|
||||
msg += ' networkState: ';
|
||||
switch (me.element.networkState) {
|
||||
case 0:
|
||||
msg += 'NETWORK_EMPTY';
|
||||
break;
|
||||
case 1:
|
||||
msg += 'NETWORK_IDLE';
|
||||
break;
|
||||
case 2:
|
||||
msg += 'NETWORK_LOADING';
|
||||
break;
|
||||
case 3:
|
||||
msg += 'NETWORK_NO_SOURCE';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
me.adderror(msg);
|
||||
});
|
||||
var events = ['abort','canplay','canplaythrough','durationchange','emptied','ended','interruptbegin','interruptend','loadeddata','loadedmetadata','loadstart','pause','play','playing','ratechange','seeked','seeking','stalled','volumechange','waiting','progress'];
|
||||
for (var i in events) {
|
||||
ele.addEventListener(events[i],function(e){
|
||||
me.addlog('Player event fired: '+e.type);
|
||||
});
|
||||
}
|
||||
callback(cont);
|
||||
}
|
||||
p.prototype.play = function(){ return this.element.play(); };
|
||||
p.prototype.pause = function(){ return this.element.pause(); };
|
||||
p.prototype.volume = function(level){
|
||||
if (typeof level == 'undefined' ) { return this.element.volume; }
|
||||
return this.element.volume = level;
|
||||
};
|
||||
p.prototype.loop = function(bool){
|
||||
if (typeof bool == 'undefined') {
|
||||
return this.element.loop;
|
||||
}
|
||||
return this.element.loop = bool;
|
||||
};
|
||||
p.prototype.load = function(){
|
||||
var load;
|
||||
if (this.element.paused) {
|
||||
load = this.element.load();
|
||||
}
|
||||
else {
|
||||
//sometimes there is a play / pause interrupt: try again
|
||||
//TODO figure out if this happens on paused or on playing
|
||||
MistVideo.player.api = video;
|
||||
}
|
||||
MistVideo.player.api.setSource = function(url) {
|
||||
if (url != this.source.src) {
|
||||
this.source.src = url;
|
||||
this.load();
|
||||
return;
|
||||
}
|
||||
};
|
||||
MistVideo.player.api.setSubtitle = function(trackmeta) {
|
||||
//remove previous subtitles
|
||||
var tracks = video.getElementsByTagName("track");
|
||||
for (var i = tracks.length - 1; i >= 0; i--) {
|
||||
video.removeChild(tracks[i]);
|
||||
}
|
||||
if (trackmeta) { //if the chosen track exists
|
||||
//add the new one
|
||||
var track = document.createElement("track");
|
||||
video.appendChild(track);
|
||||
track.kind = "subtitles";
|
||||
track.label = trackmeta.label;
|
||||
track.srclang = trackmeta.lang;
|
||||
track.src = trackmeta.src;
|
||||
track.setAttribute("default","");
|
||||
}
|
||||
};
|
||||
MistVideo.player.setSize = function(size){
|
||||
this.api.style.width = size.width+"px";
|
||||
this.api.style.height = size.height+"px";
|
||||
};
|
||||
|
||||
//this helps to prevent the player from just showing a black screen after a reload
|
||||
if (this.element.paused) {
|
||||
var me = this;
|
||||
var unpause = function(){
|
||||
if (me.element.paused) {
|
||||
me.element.play();
|
||||
callback(video);
|
||||
}
|
||||
me.element.removeEventListener('progress',unpause);
|
||||
}
|
||||
this.element.addEventListener('progress',unpause);
|
||||
}
|
||||
|
||||
return load;
|
||||
};
|
||||
if (document.fullscreenEnabled || document.webkitFullscreenEnabled || document.mozFullScreenEnabled || document.msFullscreenEnabled) {
|
||||
p.prototype.fullscreen = function(){
|
||||
if(this.element.requestFullscreen) {
|
||||
return this.element.requestFullscreen();
|
||||
} else if(this.element.mozRequestFullScreen) {
|
||||
return this.element.mozRequestFullScreen();
|
||||
} else if(this.element.webkitRequestFullscreen) {
|
||||
return this.element.webkitRequestFullscreen();
|
||||
} else if(this.element.msRequestFullscreen) {
|
||||
return this.element.msRequestFullscreen();
|
||||
}
|
||||
};
|
||||
}
|
||||
p.prototype.updateSrc = function(src){
|
||||
this.source.setAttribute('src',src);
|
||||
return true;
|
||||
};
|
||||
p.prototype.resize = function(size){
|
||||
this.element.width = size.width;
|
||||
this.element.height = size.height;
|
||||
};
|
||||
|
|
|
@ -1,23 +0,0 @@
|
|||
mistplayers.img = {
|
||||
name: 'HTML img tag',
|
||||
version: '1.1',
|
||||
mimes: ['html5/image/jpeg'],
|
||||
priority: Object.keys(mistplayers).length + 1,
|
||||
isMimeSupported: function (mimetype) {
|
||||
return (this.mimes.indexOf(mimetype) == -1 ? false : true);
|
||||
},
|
||||
isBrowserSupported: function (mimetype,source,options,streaminfo) {
|
||||
//only use this if we are sure we just want an image
|
||||
if ((options.forceType) || (options.forceSource) || (options.forcePlayer)) { return true; }
|
||||
return false;
|
||||
},
|
||||
player: function(){this.onreadylist = [];}
|
||||
};
|
||||
var p = mistplayers.img.player;
|
||||
p.prototype = new MistPlayer();
|
||||
p.prototype.build = function (options,callback) {
|
||||
var ele = this.getElement('img');
|
||||
ele.src = options.src;
|
||||
ele.style.display = 'block';
|
||||
callback(ele);
|
||||
}
|
|
@ -1,40 +0,0 @@
|
|||
mistplayers.jwplayer = {
|
||||
name: 'JWPlayer',
|
||||
version: '0.2',
|
||||
mimes: ['html5/video/mp4','html5/video/webm','dash/video/mp4','flash/10','flash/7','html5/application/vnd.apple.mpegurl','html5/audio/mp3','html5/audio/aac'],
|
||||
priority: Object.keys(mistplayers).length + 1,
|
||||
isMimeSupported: function (mimetype) {
|
||||
return (this.mimes.indexOf(mimetype) == -1 ? false : true);
|
||||
},
|
||||
isBrowserSupported: function (mimetype) {
|
||||
//TODO like, actually check the browser or something?
|
||||
if (typeof jwplayer == 'function') {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
player: function(){}
|
||||
};
|
||||
var p = mistplayers.jwplayer.player;
|
||||
p.prototype = new MistPlayer();
|
||||
p.prototype.build = function (options,callback) {
|
||||
var ele = this.getElement('div');
|
||||
|
||||
this.jw = jwplayer(ele).setup({
|
||||
file: options.src,
|
||||
width: options.width,
|
||||
height: options.height,
|
||||
autostart: options.autoplay,
|
||||
image: options.poster,
|
||||
controls: options.controls
|
||||
});
|
||||
|
||||
this.addlog('Built html');
|
||||
callback(ele);
|
||||
}
|
||||
p.prototype.play = function(){ return this.jw.play(); };
|
||||
p.prototype.pause = function(){ return this.jw.pause(); };
|
||||
p.prototype.volume = function(level){
|
||||
if (typeof level == 'undefined' ) { return this.jw.getVolume/100; }
|
||||
return this.jw.setVolume(level*100);
|
||||
};
|
|
@ -1,101 +0,0 @@
|
|||
mistplayers.polytrope = {
|
||||
name: 'Polytrope Flash Player',
|
||||
version: '0.2',
|
||||
mimes: ['flash/11','flash/10','flash/7'],
|
||||
priority: Object.keys(mistplayers).length + 1,
|
||||
isMimeSupported: function (mimetype) {
|
||||
return (this.mimes.indexOf(mimetype) == -1 ? false : true);
|
||||
},
|
||||
isBrowserSupported: function (mimetype) {
|
||||
return false;
|
||||
|
||||
var version = 0;
|
||||
try {
|
||||
// check in the mimeTypes
|
||||
version = navigator.mimeTypes['application/x-shockwave-flash'].enabledPlugin.description.replace(/([^0-9\.])/g, '').split('.')[0];
|
||||
} catch(e){}
|
||||
try {
|
||||
// for our special friend IE
|
||||
version = new ActiveXObject('ShockwaveFlash.ShockwaveFlash').GetVariable("$version").replace(/([^0-9\,])/g, '').split(',')[0];
|
||||
} catch(e){}
|
||||
|
||||
var mimesplit = mimetype.split('/');
|
||||
|
||||
return Number(version) >= Number(mimesplit[mimesplit.length-1]);
|
||||
},
|
||||
player: function(){}
|
||||
};
|
||||
var p = mistplayers.polytrope.player;
|
||||
p.prototype = new MistPlayer();
|
||||
p.prototype.build = function (options,callback) {
|
||||
function createParam(name,value) {
|
||||
var p = document.createElement('param');
|
||||
p.setAttribute('name',name);
|
||||
p.setAttribute('value',value);
|
||||
return p;
|
||||
}
|
||||
|
||||
//TODO its not working.
|
||||
|
||||
/*
|
||||
this.swf = this.video_instance_el.flash({
|
||||
swf: "/shared/swf/videoplayer.swf?" + (new Date).getTime(),
|
||||
width: "100%",
|
||||
height: parseInt(this.options.element.height()),
|
||||
wmode: "opaque",
|
||||
menu: "false",
|
||||
allowFullScreen: "true",
|
||||
allowFullScreenInteractive: "true",
|
||||
allowScriptAccess: "always",
|
||||
id: "cucumbertv-swf-" + this.guid,
|
||||
expressInstall: "/shared/swf/expressInstall.swf",
|
||||
flashvars: {
|
||||
rtmp_url: "rtmp://" + this.options.stream_host + "/play/",
|
||||
stream_name: this.options.stream_name,
|
||||
poster: this.options.poster,
|
||||
autoplay: this.options.autoplay,
|
||||
color_1: "0x1d1d1d",
|
||||
color_2: "0xffffff",
|
||||
buffer_time: .1,
|
||||
is_streaming_url: "/api/user/is_streaming",
|
||||
username: this.options.username,
|
||||
mode: "v" == this.options.type ? "archive" : "live",
|
||||
guid: this.guid
|
||||
}
|
||||
})
|
||||
|
||||
<div>
|
||||
<object data="/shared/swf/videoplayer.swf?1468312898591" type="application/x-shockwave-flash" id="cucumbertv-swf-4dc64c18-59af-91a2-d0c5-ab8df4f45c65" width="100%" height="660">
|
||||
<param name="wmode" value="opaque">
|
||||
<param name="menu" value="false">
|
||||
<param name="allowFullScreen" value="true">
|
||||
<param name="allowFullScreenInteractive" value="true">
|
||||
<param name="allowScriptAccess" value="always">
|
||||
<param name="expressInstall" value="/shared/swf/expressInstall.swf">
|
||||
<param name="flashvars" value="rtmp_url=rtmp://www.stickystage.com/play/&stream_name=stickystage_archive+SrA-2016.07.08.23.54.08&poster=/stickystage/users/SrA/archive/SrA-2016.07.08.23.54.08.jpg&autoplay=true&color_1=0x1d1d1d&color_2=0xffffff&buffer_time=0.1&is_streaming_url=/api/user/is_streaming&username=SrA&mode=archive&guid=4dc64c18-59af-91a2-d0c5-ab8df4f45c65">
|
||||
<param name="movie" value="/shared/swf/videoplayer.swf?1468312898591">
|
||||
</object>
|
||||
</div>
|
||||
*/
|
||||
|
||||
|
||||
|
||||
var ele = this.element('object');
|
||||
ele.data = 'players/polytrope.swf';
|
||||
ele.type = 'application/x-shockwave-flash';
|
||||
ele.width = options.width;
|
||||
ele.height = options.height;
|
||||
|
||||
/*
|
||||
ele.appendChild(createParam('allowFullScreen','true'));
|
||||
ele.appendChild(createParam('allowScriptAccess','always'));
|
||||
var flashvars = 'rtmp_url=rtmp://www.stickystage.com/play/&stream_name=stickystage_archive+SrA-2016.07.08.23.54.08&poster=/stickystage/users/SrA/archive/SrA-2016.07.08.23.54.08.jpg&autoplay=true&color_1=0x1d1d1d&color_2=0xffffff&buffer_time=0.1&is_streaming_url=/api/user/is_streaming&username=SrA&mode=archive&guid=4dc64c18-59af-91a2-d0c5-ab8df4f45c65';
|
||||
ele.appendChild(createParam('flashvars',flashvars));
|
||||
ele.appendChild(createParam('movie','players/polytrope.swf'));
|
||||
*/
|
||||
|
||||
ele.innerHTML = '<param name="wmode" value="opaque"> <param name="menu" value="false"> <param name="allowFullScreen" value="true"> <param name="allowFullScreenInteractive" value="true"> <param name="allowScriptAccess" value="always"> <param name="expressInstall" value="/shared/swf/expressInstall.swf"> <param name="flashvars" value="rtmp_url=rtmp://www.stickystage.com/play/&stream_name=stickystage_archive+SrA-2016.07.08.23.54.08&poster=http://stickystage.com/stickystage/users/SrA/archive/SrA-2016.07.08.23.54.08.jpg&autoplay=true&color_1=0x1d1d1d&color_2=0xffffff&buffer_time=0.1&is_streaming_url=/api/user/is_streaming&username=SrA&mode=archive&guid=4dc64c18-59af-91a2-d0c5-ab8df4f45c65"> <param name="movie" value="players/polytrope.swf">';
|
||||
|
||||
this.addlog('Built html');
|
||||
callback(ele);
|
||||
}
|
|
@ -1,56 +0,0 @@
|
|||
mistplayers.silverlight = {
|
||||
name: 'Silverlight',
|
||||
version: '1.1',
|
||||
mimes: ['silverlight'],
|
||||
priority: Object.keys(mistplayers).length + 1,
|
||||
isMimeSupported: function (mimetype) {
|
||||
return (this.mimes.indexOf(mimetype) == -1 ? false : true);
|
||||
},
|
||||
isBrowserSupported: function (mimetype) {
|
||||
var plugin;
|
||||
try {
|
||||
// check in the mimeTypes
|
||||
plugin = navigator.plugins["Silverlight Plug-In"];
|
||||
return !!plugin;
|
||||
} catch(e){}
|
||||
try {
|
||||
// for our special friend IE
|
||||
plugin = new ActiveXObject('AgControl.AgControl');
|
||||
return true;
|
||||
} catch(e){}
|
||||
|
||||
return false;
|
||||
},
|
||||
player: function(){this.onreadylist = [];}
|
||||
};
|
||||
var p = mistplayers.silverlight.player;
|
||||
p.prototype = new MistPlayer();
|
||||
p.prototype.build = function (options,callback) {
|
||||
function createParam(name,value) {
|
||||
var p = document.createElement('param');
|
||||
p.setAttribute('name',name);
|
||||
p.setAttribute('value',value);
|
||||
return p;
|
||||
}
|
||||
|
||||
var ele = this.getElement('object');
|
||||
ele.setAttribute('data','data:application/x-silverlight,');
|
||||
ele.setAttribute('type','application/x-silverlight');
|
||||
ele.setAttribute('width',options.width);
|
||||
ele.setAttribute('height',options.height);
|
||||
ele.appendChild(createParam('source',encodeURI(options.src)+'/player.xap'));
|
||||
ele.appendChild(createParam('initparams','autoload=false,'+(options.autoplay ? 'autoplay=true' : 'autoplay=false')+',displaytimecode=false,enablecaptions=true,joinLive=true,muted=false'));
|
||||
|
||||
var a = document.createElement('a');
|
||||
ele.appendChild(a);
|
||||
a.setAttribute('href','http://go.microsoft.com/fwlink/?LinkID=124807');
|
||||
a.setAttribute('style','text-decoration: none;');
|
||||
var img = document.createElement('img');
|
||||
a.appendChild(img);
|
||||
img.setAttribute('src','http://go.microsoft.com/fwlink/?LinkId=108181');
|
||||
img.setAttribute('alt','Get Microsoft Silverlight');
|
||||
img.setAttribute('style','border-style: none;')
|
||||
|
||||
this.addlog('Built html');
|
||||
callback(ele);
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
mistplayers.myplayer = {
|
||||
name: 'My video player',
|
||||
version: '0.1',
|
||||
mimes: ['my/mime/types'],
|
||||
priority: Object.keys(mistplayers).length + 1,
|
||||
isMimeSupported: function (mimetype) {
|
||||
return (this.mimes.indexOf(mimetype) == -1 ? false : true);
|
||||
},
|
||||
isBrowserSupported: function (mimetype) {
|
||||
//TODO your code here
|
||||
return false;
|
||||
},
|
||||
player: function(){}
|
||||
};
|
||||
var p = mistplayers.myplayer.player;
|
||||
p.prototype = new MistPlayer();
|
||||
p.prototype.build = function (options,callback) {
|
||||
var ele = this.element('object');
|
||||
|
||||
//TODO your code here
|
||||
|
||||
this.addlog('Built html');
|
||||
callback(ele);
|
||||
}
|
|
@ -1,53 +0,0 @@
|
|||
mistplayers.theoplayer = {
|
||||
name: 'TheoPlayer',
|
||||
version: '0.2',
|
||||
mimes: ['html5/application/vnd.apple.mpegurl','dash/video/mp4'],
|
||||
priority: Object.keys(mistplayers).length + 1,
|
||||
isMimeSupported: function (mimetype) {
|
||||
return (this.mimes.indexOf(mimetype) == -1 ? false : true);
|
||||
},
|
||||
isBrowserSupported: function (mimetype) {
|
||||
//TODO like, actually check the browser or something?
|
||||
if (typeof theoplayer == 'function') {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
player: function(){}
|
||||
};
|
||||
var p = mistplayers.theoplayer.player;
|
||||
p.prototype = new MistPlayer();
|
||||
p.prototype.build = function (options,callback) {
|
||||
var ele = this.getElement('video');
|
||||
|
||||
ele.src = options.src;
|
||||
ele.width = options.width;
|
||||
ele.height = options.height;
|
||||
|
||||
if (options.controls) {
|
||||
ele.setAttribute('controls','');
|
||||
}
|
||||
if (options.autoplay) {
|
||||
ele.setAttribute('autoplay','');
|
||||
}
|
||||
if (options.loop) {
|
||||
ele.setAttribute('loop','');
|
||||
}
|
||||
if (options.poster) {
|
||||
ele.setAttribute('poster',options.poster);
|
||||
}
|
||||
|
||||
this.theoplayer = theoplayer(ele);
|
||||
|
||||
this.addlog('Built html');
|
||||
callback(ele);
|
||||
}
|
||||
p.prototype.play = function(){ return this.theoplayer.play(); };
|
||||
p.prototype.pause = function(){ return this.theoplayer.pause(); };
|
||||
p.prototype.volume = function(level){
|
||||
if (typeof level == 'undefined' ) { return this.theoplayer.volume; }
|
||||
return this.theoplayer.volume = level;
|
||||
};
|
||||
p.prototype.fullscreen = function(){
|
||||
return this.theoplayer.requestFullscreen();
|
||||
};
|
|
@ -1,221 +1,208 @@
|
|||
mistplayers.videojs = {
|
||||
name: 'VideoJS player',
|
||||
version: '1.1',
|
||||
mimes: ['html5/video/mp4','html5/application/vnd.apple.mpegurl','html5/video/ogg','html5/video/webm'],
|
||||
priority: Object.keys(mistplayers).length + 1,
|
||||
name: "VideoJS player",
|
||||
mimes: ["html5/application/vnd.apple.mpegurl"],
|
||||
priority: MistUtil.object.keys(mistplayers).length + 1,
|
||||
isMimeSupported: function (mimetype) {
|
||||
return (this.mimes.indexOf(mimetype) == -1 ? false : true);
|
||||
},
|
||||
isBrowserSupported: function (mimetype,source,options,streaminfo,logfunc) {
|
||||
isBrowserSupported: function (mimetype,source,MistVideo) {
|
||||
|
||||
//dont use https if the player is loaded over http
|
||||
if ((options.host.substr(0,7) == 'http://') && (source.url.substr(0,8) == 'https://')) {
|
||||
if (logfunc) { logfunc('HTTP/HTTPS mismatch for this source'); }
|
||||
//check for http/https mismatch
|
||||
if (location.protocol != MistUtil.http.url.split(source.url).protocol) {
|
||||
MistVideo.log("HTTP/HTTPS mismatch for this source");
|
||||
return false;
|
||||
}
|
||||
|
||||
//dont use videojs if this location is loaded over file://
|
||||
if ((location.protocol == 'file:') && (mimetype == 'html5/application/vnd.apple.mpegurl')) {
|
||||
if (logfunc) { logfunc('This source ('+mimetype+') won\'t work if the page is run via file://'); }
|
||||
//don't use videojs if this location is loaded over file://
|
||||
if ((location.protocol == "file:") && (mimetype == "html5/application/vnd.apple")) {
|
||||
MistVideo.log("This source ("+mimetype+") won't load if the page is run via file://");
|
||||
return false;
|
||||
}
|
||||
|
||||
//dont use HLS if there is an MP3 audio track, unless we're on apple or edge
|
||||
if ((mimetype == 'html5/application/vnd.apple.mpegurl') && (['iPad','iPhone','iPod','MacIntel'].indexOf(navigator.platform) == -1) && (navigator.userAgent.indexOf('Edge') == -1)) {
|
||||
var audio = false;
|
||||
var nonmp3 = false;
|
||||
for (var i in streaminfo.meta.tracks) {
|
||||
var t = streaminfo.meta.tracks[i];
|
||||
if (t.type == 'audio') {
|
||||
audio = true;
|
||||
if (t.codec != 'MP3') {
|
||||
nonmp3 = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((audio) && (!nonmp3)) {
|
||||
if (logfunc) { logfunc('This source has audio, but only MP3, and this browser can\'t play MP3 via HLS'); }
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return ('MediaSource' in window);
|
||||
return ("MediaSource" in window);
|
||||
},
|
||||
player: function(){this.onreadylist = [];}
|
||||
player: function(){},
|
||||
scriptsrc: function(host) { return host+"/videojs.js"; }
|
||||
};
|
||||
var p = mistplayers.videojs.player;
|
||||
p.prototype = new MistPlayer();
|
||||
p.prototype.build = function (options,callback) {
|
||||
p.prototype.build = function (MistVideo,callback) {
|
||||
var me = this; //to allow nested functions to access the player class itself
|
||||
|
||||
function onplayerload () {
|
||||
me.addlog('Building VideoJS player..');
|
||||
function onVideoJSLoad () {
|
||||
if (MistVideo.destroyed) { return;}
|
||||
|
||||
var cont = document.createElement('div');
|
||||
cont.className = 'mistplayer';
|
||||
MistVideo.log("Building VideoJS player..");
|
||||
|
||||
var ele = me.getElement('video');
|
||||
cont.appendChild(ele);
|
||||
ele.className = '';
|
||||
if (options.source.type != "html5/video/ogg") {
|
||||
ele.crossOrigin = 'anonymous'; //required for subtitles, but if ogg, the video won't load
|
||||
var ele = document.createElement("video");
|
||||
if (MistVideo.source.type != "html5/video/ogg") {
|
||||
ele.crossOrigin = "anonymous"; //required for subtitles, but if ogg, the video won"t load
|
||||
}
|
||||
|
||||
var shortmime = options.source.type.split('/');
|
||||
var shortmime = MistVideo.source.type.split("/");
|
||||
shortmime.shift();
|
||||
|
||||
var source = document.createElement('source');
|
||||
source.setAttribute('src',options.src);
|
||||
var source = document.createElement("source");
|
||||
source.setAttribute("src",MistVideo.source.url);
|
||||
me.source = source;
|
||||
ele.appendChild(source);
|
||||
source.type = shortmime.join('/');
|
||||
me.addlog('Adding '+source.type+' source @ '+options.src);
|
||||
if (source.type == 'application/vnd.apple.mpegurl') { source.type = 'application/x-mpegURL'; }
|
||||
source.type = shortmime.join("/");
|
||||
MistVideo.log("Adding "+source.type+" source @ "+MistVideo.source.url);
|
||||
if (source.type == "application/vnd.apple.mpegurl") { source.type = "application/x-mpegURL"; }
|
||||
|
||||
ele.className += ' video-js';
|
||||
ele.width = options.width;
|
||||
ele.height = options.height;
|
||||
ele.style.width = options.width+'px';
|
||||
ele.style.height = options.height+'px';
|
||||
MistUtil.class.add(ele,"video-js");
|
||||
|
||||
var vjsopts = {
|
||||
preload: 'auto'
|
||||
};
|
||||
var vjsopts = {};
|
||||
|
||||
if (options.autoplay) { vjsopts.autoplay = true; }
|
||||
if (options.loop) {
|
||||
if (MistVideo.options.autoplay) { vjsopts.autoplay = true; }
|
||||
if ((MistVideo.options.loop) && (MistVideo.info.type != "live")) {
|
||||
vjsopts.loop = true;
|
||||
ele.loop = true;
|
||||
}
|
||||
if (options.poster) { vjsopts.poster = options.poster; }
|
||||
if (options.controls) {
|
||||
if ((options.controls == 'stock') || (!me.buildMistControls())) {
|
||||
//MistControls have failed to build in the if condition
|
||||
ele.setAttribute('controls',true);
|
||||
if (MistVideo.options.poster) { vjsopts.poster = MistVideo.options.poster; }
|
||||
if (MistVideo.options.controls == "stock") {
|
||||
ele.setAttribute("controls","");
|
||||
if (!document.getElementById("videojs-css")) {
|
||||
var style = document.createElement("link");
|
||||
style.rel = "stylesheet";
|
||||
style.href = MistVideo.options.host+"/skins/videojs.css";
|
||||
style.id = "videojs-css";
|
||||
document.head.appendChild(style);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
me.onready(function(){
|
||||
me.videojs = videojs(ele,vjsopts,function(){
|
||||
me.addlog('Videojs initialized');
|
||||
});
|
||||
MistVideo.log("Videojs initialized");
|
||||
});
|
||||
|
||||
me.addlog('Built html');
|
||||
me.api.unload = function(){
|
||||
videojs(ele).dispose();
|
||||
};
|
||||
});
|
||||
|
||||
//forward events
|
||||
ele.addEventListener('error',function(e){
|
||||
if (!e.isTrusted) { return; } //don't trigger on errors we have thrown ourselves
|
||||
MistVideo.log("Built html");
|
||||
|
||||
var msg;
|
||||
if ('message' in e) {
|
||||
msg = e.message;
|
||||
if (("Proxy" in window) && ("Reflect" in window)) {
|
||||
var overrides = {
|
||||
get: {},
|
||||
set: {}
|
||||
};
|
||||
|
||||
MistVideo.player.api = new Proxy(ele,{
|
||||
get: function(target, key, receiver){
|
||||
if (key in overrides.get) {
|
||||
return overrides.get[key].apply(target, arguments);
|
||||
}
|
||||
var method = target[key];
|
||||
if (typeof method === "function"){
|
||||
return function () {
|
||||
return method.apply(target, arguments);
|
||||
}
|
||||
}
|
||||
return method;
|
||||
},
|
||||
set: function(target, key, value) {
|
||||
if (key in overrides.set) {
|
||||
return overrides.set[key].call(target,value);
|
||||
}
|
||||
return target[key] = value;
|
||||
}
|
||||
});
|
||||
|
||||
if (MistVideo.info.type == "live") {
|
||||
function getLastBuffer(video) {
|
||||
var buffer_end = 0;
|
||||
if (video.buffered.length) {
|
||||
buffer_end = video.buffered.end(video.buffered.length-1)
|
||||
}
|
||||
return buffer_end;
|
||||
}
|
||||
var HLSlatency = 90; //best guess..
|
||||
|
||||
overrides.get.duration = function(){
|
||||
return (MistVideo.info.lastms + (new Date()).getTime() - MistVideo.info.updated.getTime())*1e-3;
|
||||
};
|
||||
MistVideo.player.api.lastProgress = new Date();
|
||||
MistVideo.player.api.liveOffset = 0;
|
||||
|
||||
MistUtil.event.addListener(ele,"progress",function(){
|
||||
MistVideo.player.api.lastProgress = new Date();
|
||||
});
|
||||
overrides.set.currentTime = function(value){
|
||||
var diff = MistVideo.player.api.currentTime - value;
|
||||
var offset = value - MistVideo.player.api.duration;
|
||||
//MistVideo.player.api.liveOffset = offset;
|
||||
|
||||
MistVideo.log("Seeking to "+MistUtil.format.time(value)+" ("+Math.round(offset*-10)/10+"s from live)");
|
||||
MistVideo.video.currentTime -= diff;
|
||||
}
|
||||
overrides.get.currentTime = function(){
|
||||
return this.currentTime + MistVideo.info.lastms*1e-3 - MistVideo.player.api.liveOffset - HLSlatency;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
msg = 'readyState: ';
|
||||
switch (me.element.readyState) {
|
||||
case 0:
|
||||
msg += 'HAVE_NOTHING';
|
||||
break;
|
||||
case 1:
|
||||
msg += 'HAVE_METADATA';
|
||||
break;
|
||||
case 2:
|
||||
msg += 'HAVE_CURRENT_DATA';
|
||||
break;
|
||||
case 3:
|
||||
msg += 'HAVE_FUTURE_DATA';
|
||||
break;
|
||||
case 4:
|
||||
msg += 'HAVE_ENOUGH_DATA';
|
||||
break;
|
||||
}
|
||||
msg += ' networkState: ';
|
||||
switch (me.element.networkState) {
|
||||
case 0:
|
||||
msg += 'NETWORK_EMPTY';
|
||||
break;
|
||||
case 1:
|
||||
msg += 'NETWORK_IDLE';
|
||||
break;
|
||||
case 2:
|
||||
msg += 'NETWORK_LOADING';
|
||||
break;
|
||||
case 3:
|
||||
msg += 'NETWORK_NO_SOURCE';
|
||||
break;
|
||||
}
|
||||
me.api = ele;
|
||||
}
|
||||
|
||||
me.adderror(msg);
|
||||
MistVideo.player.setSize = function(size){
|
||||
if ("videojs" in MistVideo.player) {
|
||||
MistVideo.player.videojs.dimensions(size.width,size.height);
|
||||
|
||||
});
|
||||
var events = ['abort','canplay','canplaythrough','durationchange','emptied','ended','interruptbegin','interruptend','loadeddata','loadedmetadata','loadstart','pause','play','playing','ratechange','seeked','seeking','stalled','volumechange','waiting','progress'];
|
||||
for (var i in events) {
|
||||
ele.addEventListener(events[i],function(e){
|
||||
me.addlog('Player event fired: '+e.type);
|
||||
//for some reason, the videojs' container won't be resized with the method above.
|
||||
//so let's cheat and do it ourselves
|
||||
ele.parentNode.style.width = size.width+"px";
|
||||
ele.parentNode.style.height = size.height+"px";
|
||||
}
|
||||
this.api.style.width = size.width+"px";
|
||||
this.api.style.height = size.height+"px";
|
||||
};
|
||||
MistVideo.player.api.setSource = function(url) {
|
||||
if (!MistVideo.player.videojs) { return; }
|
||||
if (MistVideo.player.videojs.src() != url) {
|
||||
MistVideo.player.videojs.src({
|
||||
type: MistVideo.player.videojs.currentSource().type,
|
||||
src: url
|
||||
});
|
||||
}
|
||||
};
|
||||
MistVideo.player.api.setSubtitle = function(trackmeta) {
|
||||
//remove previous subtitles
|
||||
var tracks = ele.getElementsByTagName("track");
|
||||
for (var i = tracks.length - 1; i >= 0; i--) {
|
||||
ele.removeChild(tracks[i]);
|
||||
}
|
||||
if (trackmeta) { //if the chosen track exists
|
||||
//add the new one
|
||||
var track = document.createElement("track");
|
||||
ele.appendChild(track);
|
||||
track.kind = "subtitles";
|
||||
track.label = trackmeta.label;
|
||||
track.srclang = trackmeta.lang;
|
||||
track.src = trackmeta.src;
|
||||
track.setAttribute("default","");
|
||||
}
|
||||
};
|
||||
|
||||
callback(cont);
|
||||
callback(ele);
|
||||
}
|
||||
|
||||
if ('videojs' in window) {
|
||||
onplayerload();
|
||||
if ("videojs" in window) {
|
||||
onVideoJSLoad();
|
||||
}
|
||||
else {
|
||||
//load the videojs player
|
||||
var scripttag = document.createElement('script');
|
||||
scripttag.src = options.host+'/videojs.js';
|
||||
me.addlog('Retrieving videojs player code from '+scripttag.src);
|
||||
document.head.appendChild(scripttag);
|
||||
scripttag.onerror = function(){
|
||||
me.askNextCombo('Failed to load videojs.js');
|
||||
}
|
||||
scripttag.onload = function(){
|
||||
onplayerload();
|
||||
|
||||
var scripttag = MistUtil.scripts.insert(MistVideo.urlappend(mistplayers.videojs.scriptsrc(MistVideo.options.host)),{
|
||||
onerror: function(e){
|
||||
var msg = "Failed to load videojs.js";
|
||||
if (e.message) { msg += ": "+e.message; }
|
||||
MistVideo.showError(msg);
|
||||
},
|
||||
onload: onVideoJSLoad
|
||||
},MistVideo);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
p.prototype.play = function(){ return this.element.play(); };
|
||||
p.prototype.pause = function(){ return this.element.pause(); };
|
||||
p.prototype.volume = function(level){
|
||||
if (typeof level == 'undefined' ) { return this.element.volume; }
|
||||
return this.element.volume = level;
|
||||
};
|
||||
p.prototype.loop = function(bool){
|
||||
if (typeof bool == 'undefined') {
|
||||
return this.element.loop;
|
||||
}
|
||||
return this.element.loop = bool;
|
||||
};
|
||||
p.prototype.load = function(){ return this.element.load(); };
|
||||
if (document.fullscreenEnabled || document.webkitFullscreenEnabled || document.mozFullScreenEnabled || document.msFullscreenEnabled) {
|
||||
p.prototype.fullscreen = function(){
|
||||
if(this.element.requestFullscreen) {
|
||||
return this.element.requestFullscreen();
|
||||
} else if(this.element.mozRequestFullScreen) {
|
||||
return this.element.mozRequestFullScreen();
|
||||
} else if(this.element.webkitRequestFullscreen) {
|
||||
return this.element.webkitRequestFullscreen();
|
||||
} else if(this.element.msRequestFullscreen) {
|
||||
return this.element.msRequestFullscreen();
|
||||
}
|
||||
};
|
||||
}
|
||||
p.prototype.updateSrc = function(src){
|
||||
if ("videojs" in this) {
|
||||
if (src == '') {
|
||||
this.videojs.dispose();
|
||||
return;
|
||||
}
|
||||
this.videojs.src({
|
||||
src: src,
|
||||
type: this.source.type
|
||||
});
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
|
429
embed/wrappers/webrtc.js
Normal file
|
@ -0,0 +1,429 @@
|
|||
mistplayers.webrtc = {
|
||||
name: "WebRTC player",
|
||||
mimes: ["webrtc"],
|
||||
priority: MistUtil.object.keys(mistplayers).length + 1,
|
||||
isMimeSupported: function (mimetype) {
|
||||
return (this.mimes.indexOf(mimetype) == -1 ? false : true);
|
||||
},
|
||||
isBrowserSupported: function (mimetype,source,MistVideo) {
|
||||
|
||||
if ((!("WebSocket" in window)) || (!("RTCPeerConnection" in window))) { return false; }
|
||||
|
||||
//check for http/https mismatch
|
||||
if (location.protocol.replace(/^http/,"ws") != MistUtil.http.url.split(source.url.replace(/^http/,"ws")).protocol) {
|
||||
MistVideo.log("HTTP/HTTPS mismatch for this source");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
},
|
||||
player: function(){}
|
||||
};
|
||||
var p = mistplayers.webrtc.player;
|
||||
p.prototype = new MistPlayer();
|
||||
p.prototype.build = function (MistVideo,callback) {
|
||||
var me = this;
|
||||
|
||||
if ((typeof WebRTCBrowserEqualizerLoaded == "undefined") || (!WebRTCBrowserEqualizerLoaded)) {
|
||||
//load it
|
||||
var scripttag = document.createElement("script");
|
||||
scripttag.src = MistVideo.urlappend(MistVideo.options.host+"/webrtc.js");
|
||||
MistVideo.log("Retrieving webRTC browser equalizer code from "+scripttag.src);
|
||||
document.head.appendChild(scripttag);
|
||||
scripttag.onerror = function(){
|
||||
MistVideo.showError("Failed to load webrtc browser equalizer",{nextCombo:5});
|
||||
}
|
||||
scripttag.onload = function(){
|
||||
me.build(MistVideo,callback);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
var video = document.createElement("video");
|
||||
|
||||
//apply options
|
||||
var attrs = ["autoplay","loop","poster"];
|
||||
for (var i in attrs) {
|
||||
var attr = attrs[i];
|
||||
if (MistVideo.options[attr]) {
|
||||
video.setAttribute(attr,(MistVideo.options[attr] === true ? "" : MistVideo.options[attr]));
|
||||
}
|
||||
}
|
||||
if (MistVideo.info.type == "live") {
|
||||
video.loop = false;
|
||||
}
|
||||
if (MistVideo.options.controls == "stock") {
|
||||
video.setAttribute("controls","");
|
||||
}
|
||||
video.setAttribute("crossorigin","anonymous");
|
||||
this.setSize = function(size){
|
||||
video.style.width = size.width+"px";
|
||||
video.style.height = size.height+"px";
|
||||
};
|
||||
MistUtil.event.addListener(video,"loadeddata",correctSubtitleSync);
|
||||
MistUtil.event.addListener(video,"seeked",correctSubtitleSync);
|
||||
|
||||
var seekoffset = 0;
|
||||
var hasended = false;
|
||||
this.listeners = {
|
||||
on_connected: function() {
|
||||
seekoffset = 0;
|
||||
hasended = false;
|
||||
this.webrtc.play();
|
||||
},
|
||||
on_disconnected: function() {
|
||||
MistVideo.log("Websocket sent on_disconnect");
|
||||
/*
|
||||
If a VoD file ends, we receive an on_stop, but no on_disconnect
|
||||
If a live stream ends, we receive an on_disconnect, but no on_stop
|
||||
If MistOutWebRTC crashes, we receive an on_stop and then an on_disconnect
|
||||
*/
|
||||
if (hasended) {
|
||||
MistVideo.showError("Connection to media server ended unexpectedly.");
|
||||
}
|
||||
video.pause();
|
||||
},
|
||||
on_answer_sdp: function (ev) {
|
||||
if (!ev.result) {
|
||||
MistVideo.showError("Failed to open stream.");
|
||||
this.on_disconnected();
|
||||
return;
|
||||
}
|
||||
MistVideo.log("SDP answer received");
|
||||
},
|
||||
on_time: function(ev) {
|
||||
//timeupdate
|
||||
var oldoffset = seekoffset;
|
||||
seekoffset = ev.current*1e-3 - video.currentTime;
|
||||
if (Math.abs(oldoffset - seekoffset) > 1) { correctSubtitleSync(); }
|
||||
|
||||
var d = (ev.end == 0 ? Infinity : ev.end*1e-3);
|
||||
if (d != duration) {
|
||||
duration = d;
|
||||
MistUtil.event.send("durationchange",d,video);
|
||||
}
|
||||
},
|
||||
on_seek: function(){
|
||||
MistUtil.event.send("seeked",seekoffset,video);
|
||||
video.play();
|
||||
},
|
||||
on_stop: function(){
|
||||
MistVideo.log("Websocket sent on_stop");
|
||||
MistUtil.event.send("ended",null,video);
|
||||
hasended = true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
function WebRTCPlayer(){
|
||||
this.peerConn = null;
|
||||
this.localOffer = null;
|
||||
this.isConnected = false;
|
||||
var thisWebRTCPlayer = this;
|
||||
|
||||
this.on_event = function(ev) {
|
||||
//if (ev.type != "on_time") { console.log(ev); }
|
||||
switch (ev.type) {
|
||||
case "on_connected": {
|
||||
thisWebRTCPlayer.isConnected = true;
|
||||
break;
|
||||
}
|
||||
case "on_answer_sdp": {
|
||||
thisWebRTCPlayer.peerConn
|
||||
.setRemoteDescription({ type: "answer", sdp: ev.answer_sdp })
|
||||
.then(function(){}, function(err) {
|
||||
console.error(err);
|
||||
});
|
||||
break;
|
||||
}
|
||||
case "on_disconnected": {
|
||||
thisWebRTCPlayer.isConnected = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ev.type in me.listeners) {
|
||||
return me.listeners[ev.type].call(me,ev);
|
||||
}
|
||||
MistVideo.log("Unhandled WebRTC event "+ev.type+": "+JSON.stringify(ev));
|
||||
return false;
|
||||
};
|
||||
|
||||
this.connect = function(callback){
|
||||
thisWebRTCPlayer.signaling = new WebRTCSignaling(thisWebRTCPlayer.on_event);
|
||||
thisWebRTCPlayer.peerConn = new RTCPeerConnection();
|
||||
thisWebRTCPlayer.peerConn.ontrack = function(ev) {
|
||||
video.srcObject = ev.streams[0];
|
||||
if (callback) { callback(); }
|
||||
};
|
||||
};
|
||||
|
||||
this.play = function(){
|
||||
if (!this.isConnected) {
|
||||
throw "Not connected, cannot play";
|
||||
}
|
||||
|
||||
this.peerConn
|
||||
.createOffer({
|
||||
offerToReceiveAudio: true,
|
||||
offerToReceiveVideo: true,
|
||||
})
|
||||
.then(function(offer){
|
||||
thisWebRTCPlayer.localOffer = offer;
|
||||
thisWebRTCPlayer.peerConn
|
||||
.setLocalDescription(offer)
|
||||
.then(function(){
|
||||
thisWebRTCPlayer.signaling.sendOfferSDP(thisWebRTCPlayer.localOffer.sdp);
|
||||
}, function(err){console.error(err)});
|
||||
}, function(err){ throw err; });
|
||||
};
|
||||
|
||||
this.stop = function(){
|
||||
if (!this.isConnected) { throw "Not connected, cannot stop." }
|
||||
this.signaling.send({type: "stop"});
|
||||
};
|
||||
this.seek = function(seekTime){
|
||||
if (!this.isConnected) { return; }
|
||||
this.signaling.send({type: "seek", "seek_time": seekTime*1e3});
|
||||
};
|
||||
this.pause = function(){
|
||||
if (!this.isConnected) { throw "Not connected, cannot pause." }
|
||||
this.signaling.send({type: "pause"});
|
||||
};
|
||||
this.setTrack = function(obj){
|
||||
if (!this.isConnected) { throw "Not connected, cannot set track." }
|
||||
obj.type = "tracks";
|
||||
this.signaling.send(obj);
|
||||
};
|
||||
this.getStats = function(callback){
|
||||
this.peerConn.getStats().then(function(d){
|
||||
var output = {};
|
||||
var entries = Array.from(d.entries());
|
||||
for (var i in entries) {
|
||||
var value = entries[i];
|
||||
if (value[1].type == "inbound-rtp") {
|
||||
output[value[0]] = value[1];
|
||||
}
|
||||
}
|
||||
callback(output);
|
||||
});
|
||||
};
|
||||
//input only
|
||||
/*
|
||||
this.sendVideoBitrate = function(bitrate) {
|
||||
this.send({type: "video_bitrate", video_bitrate: bitrate});
|
||||
};
|
||||
*/
|
||||
|
||||
this.connect();
|
||||
}
|
||||
function WebRTCSignaling(onEvent){
|
||||
this.ws = null;
|
||||
|
||||
this.ws = new WebSocket(MistVideo.source.url.replace(/^http/,"ws"));
|
||||
|
||||
this.ws.onopen = function() {
|
||||
onEvent({type: "on_connected"});
|
||||
};
|
||||
|
||||
this.ws.onmessage = function(e) {
|
||||
try {
|
||||
var cmd = JSON.parse(e.data);
|
||||
onEvent(cmd);
|
||||
}
|
||||
catch (err) {
|
||||
console.error("Failed to parse a response from MistServer",err,e.data);
|
||||
}
|
||||
};
|
||||
|
||||
/* See http://tools.ietf.org/html/rfc6455#section-7.4.1 */
|
||||
this.ws.onclose = function(ev) {
|
||||
switch (ev.code) {
|
||||
default: {
|
||||
onEvent({type: "on_disconnected"});
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.sendOfferSDP = function(sdp) {
|
||||
this.send({type: "offer_sdp", offer_sdp: sdp});
|
||||
};
|
||||
this.send = function(cmd) {
|
||||
if (!this.ws) {
|
||||
throw "Not initialized, cannot send "+JSON.stringify(cmd);
|
||||
}
|
||||
this.ws.send(JSON.stringify(cmd));
|
||||
}
|
||||
};
|
||||
|
||||
this.webrtc = new WebRTCPlayer();
|
||||
|
||||
this.api = {};
|
||||
|
||||
//override video duration
|
||||
var duration;
|
||||
Object.defineProperty(this.api,"duration",{
|
||||
get: function(){ return duration; }
|
||||
});
|
||||
|
||||
//override seeking
|
||||
Object.defineProperty(this.api,"currentTime",{
|
||||
get: function(){
|
||||
return seekoffset + video.currentTime;
|
||||
},
|
||||
set: function(value){
|
||||
seekoffset = value - video.currentTime;
|
||||
video.pause();
|
||||
me.webrtc.seek(value);
|
||||
MistUtil.event.send("seeking",value,video);
|
||||
}
|
||||
});
|
||||
|
||||
//redirect properties
|
||||
//using a function to make sure the "item" is in the correct scope
|
||||
function reroute(item) {
|
||||
Object.defineProperty(me.api,item,{
|
||||
get: function(){ return video[item]; },
|
||||
set: function(value){
|
||||
return video[item] = value;
|
||||
}
|
||||
});
|
||||
}
|
||||
var list = [
|
||||
"volume"
|
||||
,"muted"
|
||||
,"loop"
|
||||
,"paused",
|
||||
,"error"
|
||||
,"textTracks"
|
||||
,"webkitDroppedFrameCount"
|
||||
,"webkitDecodedFrameCount"
|
||||
];
|
||||
for (var i in list) {
|
||||
reroute(list[i]);
|
||||
}
|
||||
|
||||
//redirect methods
|
||||
function redirect(item) {
|
||||
if (item in video) {
|
||||
me.api[item] = function(){
|
||||
return video[item].call(video,arguments);
|
||||
};
|
||||
}
|
||||
}
|
||||
var list = ["load","getVideoPlaybackQuality"];
|
||||
for (var i in list) {
|
||||
redirect(list[i]);
|
||||
}
|
||||
|
||||
//redirect play
|
||||
me.api.play = function(){
|
||||
if (me.api.currentTime) {
|
||||
if ((!me.webrtc.isConnected) || (me.webrtc.peerConn.iceConnectionState != "completed")) {
|
||||
me.webrtc.connect(function(){
|
||||
me.webrtc.seek(me.api.currentTime);
|
||||
});
|
||||
}
|
||||
else {
|
||||
me.webrtc.seek(me.api.currentTime);
|
||||
}
|
||||
}
|
||||
else {
|
||||
video.play();
|
||||
}
|
||||
};
|
||||
|
||||
//redirect pause
|
||||
me.api.pause = function(){
|
||||
video.pause();
|
||||
try {
|
||||
me.webrtc.pause();
|
||||
}
|
||||
catch (e) {}
|
||||
MistUtil.event.send("paused",null,video);
|
||||
};
|
||||
|
||||
me.api.setTracks = function(obj){
|
||||
me.webrtc.setTrack(obj);
|
||||
};
|
||||
function correctSubtitleSync() {
|
||||
if (!me.api.textTracks[0]) { return; }
|
||||
var currentoffset = me.api.textTracks[0].currentOffset || 0;
|
||||
if (Math.abs(seekoffset - currentoffset) < 1) { return; } //don't bother if the change is small
|
||||
var newCues = [];
|
||||
for (var i = me.api.textTracks[0].cues.length-1; i >= 0; i--) {
|
||||
var cue = me.api.textTracks[0].cues[i];
|
||||
me.api.textTracks[0].removeCue(cue);
|
||||
if (!("orig" in cue)) {
|
||||
cue.orig = {start:cue.startTime,end:cue.endTime};
|
||||
}
|
||||
cue.startTime = cue.orig.start - seekoffset;
|
||||
cue.endTime = cue.orig.end - seekoffset;
|
||||
newCues.push(cue);
|
||||
}
|
||||
for (var i in newCues) {
|
||||
me.api.textTracks[0].addCue(newCues[i]);
|
||||
}
|
||||
me.api.textTracks[0].currentOffset = seekoffset;
|
||||
}
|
||||
me.api.setSubtitle = function(trackmeta) {
|
||||
//remove previous subtitles
|
||||
var tracks = video.getElementsByTagName("track");
|
||||
for (var i = tracks.length - 1; i >= 0; i--) {
|
||||
video.removeChild(tracks[i]);
|
||||
}
|
||||
if (trackmeta) { //if the chosen track exists
|
||||
//add the new one
|
||||
var track = document.createElement("track");
|
||||
video.appendChild(track);
|
||||
track.kind = "subtitles";
|
||||
track.label = trackmeta.label;
|
||||
track.srclang = trackmeta.lang;
|
||||
track.src = trackmeta.src;
|
||||
track.setAttribute("default","");
|
||||
|
||||
//correct timesync
|
||||
track.onload = correctSubtitleSync;
|
||||
}
|
||||
};
|
||||
|
||||
//loop
|
||||
MistUtil.event.addListener(video,"ended",function(){
|
||||
if (me.api.loop) {
|
||||
me.webrtc.connect();
|
||||
}
|
||||
});
|
||||
|
||||
if ("decodingIssues" in MistVideo.skin.blueprints) {
|
||||
//get additional dev stats
|
||||
var vars = ["nackCount","pliCount","packetsLost","packetsReceived","bytesReceived"];
|
||||
for (var j in vars) {
|
||||
me.api[vars[j]] = 0;
|
||||
}
|
||||
var f = function() {
|
||||
MistVideo.timers.start(function(){
|
||||
me.webrtc.getStats(function(d){
|
||||
for (var i in d) {
|
||||
for (var j in vars) {
|
||||
if (vars[j] in d[i]) {
|
||||
me.api[vars[j]] = d[i][vars[j]];
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
});
|
||||
f();
|
||||
},1e3);
|
||||
};
|
||||
f();
|
||||
}
|
||||
|
||||
me.api.unload = function(){
|
||||
try {
|
||||
me.webrtc.stop();
|
||||
} catch (e) {}
|
||||
};
|
||||
|
||||
callback(video);
|
||||
|
||||
};
|
327
src/embed.js
|
@ -1,327 +0,0 @@
|
|||
function mistembed(streamname) {
|
||||
|
||||
//find the current script
|
||||
var me;
|
||||
if (('currentScript' in document) && (document.currentScript)) {
|
||||
me = document.currentScript;
|
||||
//not supported in old browsers :(
|
||||
}
|
||||
else {
|
||||
var scripts = document.getElementsByTagName('script');
|
||||
me = scripts[scripts.length - 1];
|
||||
//not correct if the script is inserted dynamically, but this is how it used to be
|
||||
}
|
||||
|
||||
|
||||
// return the current flash version
|
||||
function flash_version() {
|
||||
var version = 0;
|
||||
|
||||
try {
|
||||
// check in the mimeTypes
|
||||
version = navigator.mimeTypes['application/x-shockwave-flash'].enabledPlugin.description.replace(/([^0-9\.])/g, '').split('.')[0];
|
||||
} catch(e){}
|
||||
try {
|
||||
// for our special friend IE
|
||||
version = new ActiveXObject('ShockwaveFlash.ShockwaveFlash').GetVariable("$version").replace(/([^0-9\,])/g, '').split(',')[0];
|
||||
} catch(e){}
|
||||
|
||||
return parseInt(version, 10);
|
||||
};
|
||||
|
||||
// return true if silverlight is installed
|
||||
function silverlight_installed() {
|
||||
var plugin;
|
||||
|
||||
try {
|
||||
// check in the mimeTypes
|
||||
plugin = navigator.plugins["Silverlight Plug-In"];
|
||||
return !!plugin;
|
||||
} catch(e){}
|
||||
try {
|
||||
// for our special friend IE
|
||||
plugin = new ActiveXObject('AgControl.AgControl');
|
||||
return true;
|
||||
} catch(e){}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
// return true if the browser thinks it can play the mimetype
|
||||
function html5_video_type(type) {
|
||||
var support = false;
|
||||
|
||||
|
||||
if (type == 'video/mp4') {
|
||||
if ((navigator.userAgent.indexOf('MSIE') > -1) && (parseInt(navigator.userAgent.split('MSIE')[1]) <= 9)) {
|
||||
//IE <= 9 doesn't support MP4, Firefox seems to correctly see it now.
|
||||
return false;
|
||||
}
|
||||
if (navigator.userAgent.indexOf('Firefox') > -1) {
|
||||
//firefox claims to support MP4 but doesn't when:
|
||||
// - under win xp
|
||||
// - the stream is live
|
||||
|
||||
if (video.type == 'live') {
|
||||
return false;
|
||||
}
|
||||
//find "Windows NT X;" in user userAgent
|
||||
//sorry, I don't like regexes.. I avoid them when I can :$
|
||||
var s = navigator.userAgent.split('Windows NT ');
|
||||
if (s.length > 1) {
|
||||
s = s[1].split(';');
|
||||
s = s[0];
|
||||
if (Number(s) <= 5.1) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
var v = document.createElement('video');
|
||||
|
||||
if( v && v.canPlayType(type) != "" )
|
||||
{
|
||||
support = true; // true-ish, anyway
|
||||
}
|
||||
} catch(e){}
|
||||
|
||||
return support;
|
||||
}
|
||||
|
||||
//return true if rtsp is supported
|
||||
function rtsp_support() {
|
||||
var plugin;
|
||||
|
||||
try {
|
||||
// check in the mimeTypes
|
||||
plugin = navigator.mimeTypes["application/x-google-vlc-plugin"];
|
||||
return !!plugin;
|
||||
} catch(e){}
|
||||
try {
|
||||
// for our special friend IE
|
||||
plugin = new ActiveXObject('VideoLAN.Vlcplugin.1');
|
||||
return true;
|
||||
} catch(e){}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// parse a "type" string from the controller. Format:
|
||||
// xxx/# (e.g. flash/3) or xxx/xxx/xxx (e.g. html5/application/ogg)
|
||||
function parseType(type) {
|
||||
var split = type.split('/');
|
||||
|
||||
if( split.length > 2 ) {
|
||||
split[1] += '/' + split[2];
|
||||
}
|
||||
|
||||
return split;
|
||||
}
|
||||
|
||||
// return true if a type is supported
|
||||
function hasSupport(type) {
|
||||
var typemime = parseType(type);
|
||||
|
||||
switch(typemime[0]) {
|
||||
case 'flash': return flash_version() >= parseInt(typemime[1], 10); break;
|
||||
case 'html5': return html5_video_type(typemime[1]); break;
|
||||
case 'rtsp': return rtsp_support(); break;
|
||||
case 'silverlight': return silverlight_installed(); break;
|
||||
default: return false; break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// build HTML for certain kinds of types
|
||||
function buildPlayer(src, container, videowidth, videoheight, vtype) {
|
||||
// used to recalculate the width/height
|
||||
var ratio;
|
||||
|
||||
// get the container's width/height
|
||||
var containerwidth = parseInt(container.clientWidth, 10);
|
||||
var containerheight = parseInt(container.clientHeight, 10);
|
||||
|
||||
if(videowidth > containerwidth && containerwidth > 0) {
|
||||
ratio = videowidth / containerwidth;
|
||||
|
||||
videowidth /= ratio;
|
||||
videoheight /= ratio;
|
||||
}
|
||||
|
||||
if(videoheight > containerheight && containerheight > 0) {
|
||||
ratio = videoheight / containerheight;
|
||||
|
||||
videowidth /= ratio;
|
||||
videoheight /= ratio;
|
||||
}
|
||||
|
||||
var maintype = parseType(src.type);
|
||||
mistvideo[streamname].embedded = src;
|
||||
|
||||
switch(maintype[0]) {
|
||||
case 'flash':
|
||||
// maintype[1] is already checked (i.e. user has version > maintype[1])
|
||||
var flashplayer,
|
||||
url = encodeURIComponent(src.url) + '&controlBarMode=floating&initialBufferTime=0.5&expandedBufferTime=5&minContinuousPlaybackTime=3' + (vtype == 'live' ? "&streamType=live" : "") + (autoplay ? '&autoPlay=true' : '');
|
||||
|
||||
/*
|
||||
if( parseInt(maintype[1], 10) >= 10 ) {
|
||||
flashplayer = 'http://fpdownload.adobe.com/strobe/FlashMediaPlayback_101.swf';
|
||||
}
|
||||
else {
|
||||
flashplayer = 'http://fpdownload.adobe.com/strobe/FlashMediaPlayback.swf';
|
||||
}
|
||||
*/
|
||||
flashplayer = src.player_url;
|
||||
|
||||
container.innerHTML += '<object width="' + videowidth + '" height="' + videoheight + '">' +
|
||||
'<param name="movie" value="' + flashplayer + '"></param>' +
|
||||
'<param name="flashvars" value="src=' + url + '"></param>' +
|
||||
'<param name="allowFullScreen" value="true"></param>' +
|
||||
'<param name="allowscriptaccess" value="always"></param>' +
|
||||
'<param name="wmode" value="direct"></param>' +
|
||||
(autoplay ? '<param name="autoPlay" value="true">' : '') +
|
||||
'<embed src="' + flashplayer + '" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="' + videowidth + '" height="' + videoheight + '" flashvars="src=' + url + '"></embed>' +
|
||||
'</object>';
|
||||
break;
|
||||
|
||||
case 'html5':
|
||||
container.innerHTML += '<video width="' + videowidth + '" height="' + videoheight + '" src="' + src.url + '" controls="controls" '+(autoplay ? 'autoplay="autoplay"' : '')+'><strong>No HTML5 video support</strong></video>';
|
||||
break;
|
||||
|
||||
case 'rtsp':
|
||||
/*container.innerHTML += '<object classid="clsid:CFCDAA03-8BE4-11cf-B84B-0020AFBBCCFA" width="'+videowidth+'" height="'+videoheight+'">'+
|
||||
'<param name="src" value="'+encodeURI(src.url)+'">'+
|
||||
'<param name="console" value="video1">'+
|
||||
'<param name="controls" value="All">'+
|
||||
'<param name="autostart" value="false">'+
|
||||
'<param name="loop" value="false">'+
|
||||
'<embed name="myMovie" src="'+encodeURI(src.url)+'" width="'+videowidth+'" height="'+videoheight+'" autostart="false" loop="false" nojava="true" console="video1" controls="All"></embed>'+
|
||||
'<noembed>Something went wrong.</noembed>'+
|
||||
'</object>'; //realplayer, doesnt work */
|
||||
container.innerHTML += '<embed type="application/x-google-vlc-plugin"'+
|
||||
'pluginspage="http://www.videolan.org"'+
|
||||
'width="'+videowidth+'"'+
|
||||
'height="'+videoheight+'"'+
|
||||
'target="'+encodeURI(src.url)+'"'+
|
||||
'autoplay="'+(autoplay ? 'yes' : 'no')+'"'+
|
||||
'>'+
|
||||
'</embed>'+
|
||||
'<object classid="clsid:9BE31822-FDAD-461B-AD51-BE1D1C159921" codebase="http://downloads.videolan.org/pub/videolan/vlc/latest/win32/axvlc.cab">'+
|
||||
'</object>'; //vlc, seems to work, sort of. it's trying anyway
|
||||
break;
|
||||
|
||||
case 'silverlight':
|
||||
container.innerHTML += '<object data="data:application/x-silverlight," type="application/x-silverlight" width="' + videowidth + '" height="' + videoheight + '">'+
|
||||
'<param name="source" value="' + encodeURI(src.url) + '/player.xap"/>'+
|
||||
'<param name="onerror" value="onSilverlightError" />'+
|
||||
'<param name="autoUpgrade" value="true" />'+
|
||||
'<param name="background" value="white" />'+
|
||||
'<param name="enableHtmlAccess" value="true" />'+
|
||||
'<param name="minRuntimeVersion" value="3.0.40624.0" />'+
|
||||
'<param name="initparams" value =\'autoload=false,'+(autoplay ? 'autoplay=true' : 'autoplay=false')+',displaytimecode=false,enablecaptions=true,joinLive=true,muted=false,playlist=<playList><playListItems><playListItem title="Test" description="testing" mediaSource="' + encodeURI(src.url) + '" adaptiveStreaming="true" thumbSource="" frameRate="25.0" width="" height=""></playListItem></playListItems></playList>\' />'+
|
||||
'<a href="http://go.microsoft.com/fwlink/?LinkID=124807" style="text-decoration: none;"> <img src="http://go.microsoft.com/fwlink/?LinkId=108181" alt="Get Microsoft Silverlight" style="border-style: none" /></a>'+
|
||||
'</object>';
|
||||
break;
|
||||
default:
|
||||
container.innerHTML += '<strong>Missing embed code for output type "'+src.type+'"</strong>';
|
||||
video.error = 'Missing embed code for output type "'+src.type;
|
||||
}
|
||||
}
|
||||
|
||||
var video = mistvideo[streamname],
|
||||
container = document.createElement('div'),
|
||||
forceType = false,
|
||||
forceSupportCheck = false,
|
||||
autoplay = true,
|
||||
urlappend = false;
|
||||
|
||||
if (me.parentNode.hasAttribute('data-forcetype')) {
|
||||
forceType = me.parentNode.getAttribute('data-forcetype');
|
||||
}
|
||||
if (me.parentNode.hasAttribute('data-forcesupportcheck')) {
|
||||
forceSupportCheck = true;
|
||||
}
|
||||
if (me.parentNode.hasAttribute('data-noautoplay')) {
|
||||
autoplay = false;
|
||||
}
|
||||
if (me.parentNode.hasAttribute('data-urlappend')) {
|
||||
urlappend = me.parentNode.getAttribute('data-urlappend');
|
||||
}
|
||||
|
||||
if (video.width == 0) { video.width = 250; }
|
||||
if (video.height == 0) { video.height = 250; }
|
||||
|
||||
// create the container
|
||||
me.parentNode.insertBefore(container, me);
|
||||
// set the class to 'mistvideo'
|
||||
container.setAttribute('class', 'mistvideo');
|
||||
// remove script tag
|
||||
me.parentNode.removeChild(me);
|
||||
|
||||
if(video.error) {
|
||||
// there was an error; display it
|
||||
if (video.on_error){
|
||||
container.innerHTML = video.on_error;
|
||||
}else{
|
||||
container.innerHTML = ['<strong>Error: ', video.error, '</strong>'].join('');
|
||||
}
|
||||
}
|
||||
else if ((typeof video.source == 'undefined') || (video.source.length < 1)) {
|
||||
// no stream sources
|
||||
if (video.on_error){
|
||||
container.innerHTML = video.on_error;
|
||||
}else{
|
||||
container.innerHTML = '<strong>Error: no active source or compatible protocols for this stream</strong>';
|
||||
}
|
||||
}
|
||||
else {
|
||||
// no error, and sources found. Check the video types and output the best
|
||||
// available video player.
|
||||
var i,
|
||||
vtype = (video.type ? video.type : 'unknown'),
|
||||
foundPlayer = false,
|
||||
len = video.source.length;
|
||||
|
||||
for (var i in video.source) {
|
||||
var support = hasSupport(video.source[i].type);
|
||||
video.source[i].browser_support = support;
|
||||
if ((support) || (forceType)) {
|
||||
if ((!forceType) || ((forceType) && (video.source[i].type.indexOf(forceType) >= 0))) {
|
||||
if (foundPlayer === false) {
|
||||
foundPlayer = i;
|
||||
if (!forceSupportCheck) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (foundPlayer === false) {
|
||||
// of all the streams given, none was supported (eg. no flash and HTML5 video). Display error
|
||||
container.innerHTML = '<strong>No support for any player found</strong>';
|
||||
}
|
||||
else {
|
||||
// we support this kind of video, so build it.
|
||||
var source = video.source[foundPlayer];
|
||||
if (urlappend) {
|
||||
source.url += urlappend;
|
||||
source.relurl += urlappend;
|
||||
}
|
||||
else if (me.src.indexOf('?') != -1) {
|
||||
var params = me.src.split('?');
|
||||
params.shift();
|
||||
params.join('?');
|
||||
source.url += '?'+params;
|
||||
source.relurl += '?'+params;
|
||||
}
|
||||
buildPlayer(source, container, video.width, video.height, vtype);
|
||||
}
|
||||
}
|
||||
|
||||
return (mistvideo[streamname].embedded ? mistvideo[streamname].embedded.type : false);
|
||||
//keep empty line at end of file
|
||||
}
|
|
@ -114,9 +114,12 @@ namespace Mist {
|
|||
capa["url_match"].append("/info_$.js");
|
||||
capa["url_match"].append("/json_$.js");
|
||||
capa["url_match"].append("/player.js");
|
||||
capa["url_match"].append("/player.css");
|
||||
capa["url_match"].append("/videojs.js");
|
||||
capa["url_match"].append("/dashjs.js");
|
||||
capa["url_match"].append("/webrtc.js");
|
||||
capa["url_match"].append("/skins/default.css");
|
||||
capa["url_match"].append("/skins/dev.css");
|
||||
capa["url_match"].append("/skins/videojs.css");
|
||||
capa["url_match"].append("/embed_$.js");
|
||||
capa["url_match"].append("/flashplayer.swf");
|
||||
capa["url_match"].append("/oldflashplayer.swf");
|
||||
|
@ -124,15 +127,11 @@ namespace Mist {
|
|||
capa["optional"]["wrappers"]["help"] = "Which players are attempted and in what order.";
|
||||
capa["optional"]["wrappers"]["default"] = "";
|
||||
capa["optional"]["wrappers"]["type"] = "ord_multi_sel";
|
||||
/*capa["optional"]["wrappers"]["allowed"].append("theoplayer");
|
||||
capa["optional"]["wrappers"]["allowed"].append("jwplayer");*/
|
||||
capa["optional"]["wrappers"]["allowed"].append("html5");
|
||||
capa["optional"]["wrappers"]["allowed"].append("videojs");
|
||||
capa["optional"]["wrappers"]["allowed"].append("dashjs");
|
||||
//capa["optional"]["wrappers"]["allowed"].append("polytrope"); //currently borked
|
||||
capa["optional"]["wrappers"]["allowed"].append("webrtc");
|
||||
capa["optional"]["wrappers"]["allowed"].append("flash_strobe");
|
||||
capa["optional"]["wrappers"]["allowed"].append("silverlight");
|
||||
capa["optional"]["wrappers"]["allowed"].append("img");
|
||||
capa["optional"]["wrappers"]["option"] = "--wrappers";
|
||||
capa["optional"]["wrappers"]["short"] = "w";
|
||||
cfg->addConnectorOptions(8080, capa);
|
||||
|
@ -294,6 +293,10 @@ namespace Mist {
|
|||
fullURL.protocol = getProtocolForPort(fullURL.getPort());
|
||||
}
|
||||
std::string uAgent = H.GetHeader("User-Agent");
|
||||
|
||||
std::string devSkin = "";
|
||||
if (H.GetVar("dev").size()) { devSkin = ",skin:\"dev\""; }
|
||||
|
||||
H.Clean();
|
||||
H.SetHeader("Content-Type", "text/html");
|
||||
H.SetHeader("Server", "MistServer/" PACKAGE_VERSION);
|
||||
|
@ -307,7 +310,7 @@ namespace Mist {
|
|||
std::string hlsUrl = "/hls/"+streamName+"/index.m3u8";
|
||||
std::string mp4Url = "/"+streamName+".mp4";
|
||||
|
||||
H.SetBody("<!DOCTYPE html><html><head><title>"+streamName+"</title><style>body{color:white;background:black;}</style></head><body><div class=mistvideo id=\""+streamName+"\"><noscript><video controls autoplay><source src=\""+hlsUrl+"\" type=\"application/vnd.apple.mpegurl\"><source src=\""+mp4Url+"\" type=\"video/mp4\"><a href=\""+hlsUrl+"\">Click here to play the video [Apple]</a><br><a href=\""+mp4Url+"\">Click here to play the video [MP4]</a></video></noscript><script src=\"player.js\"></script><script>mistPlay('"+streamName+"',{host:'"+fullURL.getUrl()+"',target:document.getElementById('"+streamName+"')})</script></div></body></html>");
|
||||
H.SetBody("<!DOCTYPE html><html><head><title>"+streamName+"</title><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"><style>html{margin:0;padding:0;display:table;width:100%;height:100%;}body{color:white;background:#0f0f0f;margin:0;padding:0;display:table-cell;vertical-align:middle;text-align:center}body>div>div{text-align:left;}</style></head><body><div class=mistvideo id=\""+streamName+"\"><noscript><video controls autoplay><source src=\""+hlsUrl+"\" type=\"application/vnd.apple.mpegurl\"><source src=\""+mp4Url+"\" type=\"video/mp4\"><a href=\""+hlsUrl+"\">Click here to play the video [Apple]</a><br><a href=\""+mp4Url+"\">Click here to play the video [MP4]</a></video></noscript><script src=\"player.js\"></script><script>mistPlay('"+streamName+"',{host:'"+fullURL.getUrl()+"',target:document.getElementById('"+streamName+"')"+devSkin+"})</script></div></body></html>");
|
||||
if ((uAgent.find("iPad") != std::string::npos) || (uAgent.find("iPod") != std::string::npos) || (uAgent.find("iPhone") != std::string::npos)) {
|
||||
H.SetHeader("Location",hlsUrl);
|
||||
H.SendResponse("307", "HLS redirect", myConn);
|
||||
|
@ -568,7 +571,7 @@ namespace Mist {
|
|||
return;
|
||||
}
|
||||
|
||||
if ((H.url.length() > 9 && H.url.substr(0, 6) == "/info_" && H.url.substr(H.url.length() - 3, 3) == ".js") || (H.url.length() > 10 && H.url.substr(0, 7) == "/embed_" && H.url.substr(H.url.length() - 3, 3) == ".js") || (H.url.length() > 9 && H.url.substr(0, 6) == "/json_" && H.url.substr(H.url.length() - 3, 3) == ".js")){
|
||||
if ((H.url.length() > 9 && H.url.substr(0, 6) == "/info_" && H.url.substr(H.url.length() - 3, 3) == ".js") || (H.url.length() > 9 && H.url.substr(0, 6) == "/json_" && H.url.substr(H.url.length() - 3, 3) == ".js")){
|
||||
if (websocketHandler()){return;}
|
||||
std::string reqHost = HTTP::URL(H.GetHeader("Host")).host;
|
||||
std::string useragent = H.GetVar("ua");
|
||||
|
@ -600,24 +603,13 @@ namespace Mist {
|
|||
}else{
|
||||
response = json_resp.toString();
|
||||
}
|
||||
if (rURL.substr(0, 7) == "/embed_" && !json_resp.isMember("error")){
|
||||
#include "embed.js.h"
|
||||
response.append("\n(");
|
||||
if (embed_js[embed_js_len - 2] == ';'){//check if we have a trailing ;\n or just \n
|
||||
response.append((char*)embed_js, (size_t)embed_js_len - 2); //remove trailing ";\n" from xxd conversion
|
||||
}else{
|
||||
response.append((char*)embed_js, (size_t)embed_js_len - 1); //remove trailing "\n" from xxd conversion
|
||||
}
|
||||
response.append("(\"" + streamName + "\"));\n");
|
||||
}
|
||||
H.SetBody(response);
|
||||
H.SendResponse("200", "OK", myConn);
|
||||
H.Clean();
|
||||
return;
|
||||
} //embed code generator
|
||||
|
||||
|
||||
if (H.url == "/player.js"){
|
||||
if ((H.url == "/player.js") || ((H.url.substr(0, 7) == "/embed_") && (H.url.length() > 10) && (H.url.substr(H.url.length() - 3, 3) == ".js"))){
|
||||
HTTP::URL fullURL(H.GetHeader("Host"));
|
||||
if (!fullURL.protocol.size()){
|
||||
fullURL.protocol = getProtocolForPort(fullURL.getPort());
|
||||
|
@ -627,7 +619,7 @@ namespace Mist {
|
|||
H.Clean();
|
||||
H.SetHeader("Server", "MistServer/" PACKAGE_VERSION);
|
||||
H.setCORSHeaders();
|
||||
H.SetHeader("Content-Type", "application/javascript");
|
||||
H.SetHeader("Content-Type", "application/javascript; charset=utf-8");
|
||||
if(method == "OPTIONS" || method == "HEAD"){
|
||||
H.SendResponse("200", "OK", myConn);
|
||||
H.Clean();
|
||||
|
@ -635,8 +627,10 @@ namespace Mist {
|
|||
}
|
||||
|
||||
response.append("if (typeof mistoptions == 'undefined') { mistoptions = {}; }\nif (!('host' in mistoptions)) { mistoptions.host = '"+fullURL.getUrl()+"'; }\n");
|
||||
#include "core.js.h"
|
||||
response.append((char*)core_js, (size_t)core_js_len);
|
||||
|
||||
#include "player.js.h"
|
||||
response.append((char*)player_js, (size_t)player_js_len);
|
||||
|
||||
jsonForEach(config->getOption("wrappers",true),it){
|
||||
bool used = false;
|
||||
if (it->asStringRef() == "html5"){
|
||||
|
@ -649,26 +643,6 @@ namespace Mist {
|
|||
response.append((char*)flash_strobe_js, (size_t)flash_strobe_js_len);
|
||||
used = true;
|
||||
}
|
||||
if (it->asStringRef() == "silverlight"){
|
||||
#include "silverlight.js.h"
|
||||
response.append((char*)silverlight_js, (size_t)silverlight_js_len);
|
||||
used = true;
|
||||
}
|
||||
if (it->asStringRef() == "theoplayer"){
|
||||
#include "theoplayer.js.h"
|
||||
response.append((char*)theoplayer_js, (size_t)theoplayer_js_len);
|
||||
used = true;
|
||||
}
|
||||
if (it->asStringRef() == "jwplayer"){
|
||||
#include "jwplayer.js.h"
|
||||
response.append((char*)jwplayer_js, (size_t)jwplayer_js_len);
|
||||
used = true;
|
||||
}
|
||||
if (it->asStringRef() == "polytrope"){
|
||||
#include "polytrope.js.h"
|
||||
response.append((char*)polytrope_js, (size_t)polytrope_js_len);
|
||||
used = true;
|
||||
}
|
||||
if (it->asStringRef() == "dashjs"){
|
||||
#include "dashjs.js.h"
|
||||
response.append((char*)dash_js, (size_t)dash_js_len);
|
||||
|
@ -679,9 +653,9 @@ namespace Mist {
|
|||
response.append((char*)video_js, (size_t)video_js_len);
|
||||
used = true;
|
||||
}
|
||||
if (it->asStringRef() == "img"){
|
||||
#include "img.js.h"
|
||||
response.append((char*)img_js, (size_t)img_js_len);
|
||||
if (it->asStringRef() == "webrtc"){
|
||||
#include "webrtc.js.h"
|
||||
response.append((char*)webrtc_js, (size_t)webrtc_js_len);
|
||||
used = true;
|
||||
}
|
||||
if (!used) {
|
||||
|
@ -689,6 +663,10 @@ namespace Mist {
|
|||
}
|
||||
}
|
||||
|
||||
if ((rURL.substr(0, 7) == "/embed_") && (rURL.length() > 10) && (rURL.substr(rURL.length() - 3, 3) == ".js")){
|
||||
response.append("var container = document.createElement(\"div\");\ncontainer.id = \""+streamName+"\";\ndocument.write(container.outerHTML);\nmistPlay(\""+streamName+"\",{target:document.getElementById(\""+streamName+"\")});");
|
||||
}
|
||||
|
||||
H.SetBody(response);
|
||||
H.SendResponse("200", "OK", myConn);
|
||||
H.Clean();
|
||||
|
@ -696,8 +674,9 @@ namespace Mist {
|
|||
|
||||
}
|
||||
|
||||
if (H.url == "/player.css"){
|
||||
if (H.url.substr(0, 7) == "/skins/"){
|
||||
std::string response;
|
||||
std::string url = H.url;
|
||||
H.Clean();
|
||||
H.SetHeader("Server", "MistServer/" PACKAGE_VERSION);
|
||||
H.setCORSHeaders();
|
||||
|
@ -708,8 +687,24 @@ namespace Mist {
|
|||
return;
|
||||
}
|
||||
|
||||
#include "mist.css.h"
|
||||
response.append((char*)mist_css, (size_t)mist_css_len);
|
||||
if (url == "/skins/default.css") {
|
||||
#include "skin_default.css.h"
|
||||
response.append((char*)skin_default_css, (size_t)skin_default_css_len);
|
||||
}
|
||||
else if (url == "/skins/dev.css") {
|
||||
#include "skin_dev.css.h"
|
||||
response.append((char*)skin_dev_css, (size_t)skin_dev_css_len);
|
||||
}
|
||||
else if (url == "/skins/videojs.css") {
|
||||
#include "skin_videojs.css.h"
|
||||
response.append((char*)skin_videojs_css, (size_t)skin_videojs_css_len);
|
||||
}
|
||||
else {
|
||||
H.SetBody("Unknown stylesheet: "+url);
|
||||
H.SendResponse("404", "Unknown stylesheet", myConn);
|
||||
H.Clean();
|
||||
return;
|
||||
}
|
||||
|
||||
H.SetBody(response);
|
||||
H.SendResponse("200", "OK", myConn);
|
||||
|
@ -728,10 +723,8 @@ namespace Mist {
|
|||
return;
|
||||
}
|
||||
|
||||
#include "playervideo.js.h"
|
||||
response.append((char*)playervideo_js, (size_t)playervideo_js_len);
|
||||
#include "playerhlsvideo.js.h"
|
||||
response.append((char*)playerhlsvideo_js, (size_t)playerhlsvideo_js_len);
|
||||
#include "player_video.js.h"
|
||||
response.append((char*)player_video_js, (size_t)player_video_js_len);
|
||||
|
||||
H.SetBody(response);
|
||||
H.SendResponse("200", "OK", myConn);
|
||||
|
@ -750,10 +743,30 @@ namespace Mist {
|
|||
return;
|
||||
}
|
||||
|
||||
#include "playerdashlic.js.h"
|
||||
response.append((char*)playerdashlic_js, (size_t)playerdashlic_js_len);
|
||||
#include "playerdash.js.h"
|
||||
response.append((char*)playerdash_js, (size_t)playerdash_js_len);
|
||||
#include "player_dash_lic.js.h"
|
||||
response.append((char*)player_dash_lic_js, (size_t)player_dash_lic_js_len);
|
||||
#include "player_dash.js.h"
|
||||
response.append((char*)player_dash_js, (size_t)player_dash_js_len);
|
||||
|
||||
H.SetBody(response);
|
||||
H.SendResponse("200", "OK", myConn);
|
||||
H.Clean();
|
||||
return;
|
||||
}
|
||||
if (H.url == "/webrtc.js"){
|
||||
std::string response;
|
||||
H.Clean();
|
||||
H.SetHeader("Server", "MistServer/" PACKAGE_VERSION);
|
||||
H.setCORSHeaders();
|
||||
H.SetHeader("Content-Type", "application/javascript");
|
||||
if (method == "OPTIONS" || method == "HEAD"){
|
||||
H.SendResponse("200", "OK", myConn);
|
||||
H.Clean();
|
||||
return;
|
||||
}
|
||||
|
||||
#include "player_webrtc.js.h"
|
||||
response.append((char*)player_webrtc_js, (size_t)player_webrtc_js_len);
|
||||
|
||||
H.SetBody(response);
|
||||
H.SendResponse("200", "OK", myConn);
|
||||
|
|