Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nextcloud/apps.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVictor Dubiniuk <victor.dubiniuk@gmail.com>2014-04-24 16:38:24 +0400
committerVictor Dubiniuk <victor.dubiniuk@gmail.com>2014-04-24 16:38:24 +0400
commite31c19a2a9c5c874526dafc7f27686f85e45e833 (patch)
tree124a6ab188b0ad180ee998827099349c1ddb846e /files_videoviewer
parentde807fc1cb669f827435ce152434ddc0e9671635 (diff)
Update mediaelement to 2.4.12. Fix #1766
Diffstat (limited to 'files_videoviewer')
-rw-r--r--files_videoviewer/css/mediaelementplayer.css132
-rw-r--r--files_videoviewer/js/flashmediaelement.swfbin28709 -> 29194 bytes
-rw-r--r--files_videoviewer/js/mediaelement-and-player.js192
-rw-r--r--files_videoviewer/src/flash/FlashMediaElement.as1087
-rw-r--r--files_videoviewer/src/flash/FlashMediaElement.flabin0 -> 26223 bytes
-rw-r--r--files_videoviewer/src/flash/HtmlMediaEvent.as29
-rw-r--r--files_videoviewer/src/flash/htmlelements/AudioElement.as332
-rw-r--r--files_videoviewer/src/flash/htmlelements/IMediaElement.as35
-rw-r--r--files_videoviewer/src/flash/htmlelements/VideoElement.as1
-rw-r--r--files_videoviewer/src/flash/htmlelements/YouTubeElement.as403
-rw-r--r--files_videoviewer/src/silverlight/App.xaml8
-rw-r--r--files_videoviewer/src/silverlight/App.xaml.cs68
-rw-r--r--files_videoviewer/src/silverlight/MainPage.xaml276
-rw-r--r--files_videoviewer/src/silverlight/MainPage.xaml.cs636
-rw-r--r--files_videoviewer/src/silverlight/Properties/AppManifest.xml6
-rw-r--r--files_videoviewer/src/silverlight/Properties/AssemblyInfo.cs35
-rw-r--r--files_videoviewer/src/silverlight/SilverlightMediaElement.csproj112
-rw-r--r--files_videoviewer/src/silverlight/SilverlightMediaElement.csproj.user32
-rw-r--r--files_videoviewer/src/silverlight/SilverlightMediaElement.sln20
19 files changed, 3291 insertions, 113 deletions
diff --git a/files_videoviewer/css/mediaelementplayer.css b/files_videoviewer/css/mediaelementplayer.css
index 0c2ae2cfa..8ee248385 100644
--- a/files_videoviewer/css/mediaelementplayer.css
+++ b/files_videoviewer/css/mediaelementplayer.css
@@ -20,6 +20,11 @@
overflow: hidden;
}
+.mejs-fullscreen {
+ /* set it to not show scroll bars so 100% will work */
+ overflow: hidden !important;
+}
+
.mejs-container-fullscreen {
position: fixed;
left: 0;
@@ -35,12 +40,17 @@
height: 100%;
}
+.mejs-clear {
+ clear: both;
+}
+
/* Start: LAYERS */
.mejs-background {
position: absolute;
top: 0;
left: 0;
}
+
.mejs-mediaelement {
position: absolute;
top: 0;
@@ -48,25 +58,35 @@
width: 100%;
height: 100%;
}
+
.mejs-poster {
position: absolute;
top: 0;
left: 0;
+ background-size: contain ;
+ background-position: 50% 50% ;
+ background-repeat: no-repeat ;
+}
+:root .mejs-poster img {
+ display: none ;
}
+
.mejs-poster img {
border: 0;
padding: 0;
border: 0;
- display: block;
}
+
.mejs-overlay {
position: absolute;
top: 0;
left: 0;
}
+
.mejs-overlay-play {
cursor: pointer;
}
+
.mejs-overlay-button {
position: absolute;
top: 50%;
@@ -76,12 +96,15 @@
margin: -50px 0 0 -50px;
background: url('../img/skin/bigplay.svg') no-repeat;
}
+
.no-svg .mejs-overlay-button {
background-image: url('../img/skin/bigplay.png');
}
+
.mejs-overlay:hover .mejs-overlay-button {
background-position: 0 -100px ;
}
+
.mejs-overlay-loading {
position: absolute;
top: 50%;
@@ -99,11 +122,12 @@
background: -ms-linear-gradient(top, rgba(50,50,50,0.9), rgba(0,0,0,0.9));
background: linear-gradient(rgba(50,50,50,0.9), rgba(0,0,0,0.9));
}
+
.mejs-overlay-loading span {
display: block;
width: 80px;
height: 80px;
- background: transparent url('../img/skin/loading.gif) 50% 50% no-repeat;
+ background: transparent url('../img/skin/loading.gif') 50% 50% no-repeat;
}
/* End: LAYERS */
@@ -111,7 +135,6 @@
/* Start: CONTROL BAR */
.mejs-container .mejs-controls {
position: absolute;
- background: none;
list-style-type: none;
margin: 0;
padding: 0;
@@ -139,7 +162,6 @@
height: 26px;
font-size: 11px;
line-height: 11px;
- background: 0;
font-family: Helvetica, Arial;
border: 0;
}
@@ -165,12 +187,12 @@
/* :focus for accessibility */
.mejs-controls .mejs-button button:focus {
- outline: solid 1px yellow;
+ outline: dotted 1px #999;
}
/* End: CONTROL BAR */
-/* Start: Time (current / duration) */
+/* Start: Time (Current / Duration) */
.mejs-container .mejs-controls .mejs-time {
color: #fff;
display: block;
@@ -179,44 +201,43 @@
padding: 8px 3px 0 3px ;
overflow: hidden;
text-align: center;
- padding: auto 4px;
- box-sizing: content-box;
-moz-box-sizing: content-box;
-webkit-box-sizing: content-box;
+ box-sizing: content-box;
}
+
.mejs-container .mejs-controls .mejs-time span {
- font-size: 11px;
color: #fff;
+ font-size: 11px;
line-height: 12px;
display: block;
float: left;
margin: 1px 2px 0 0;
width: auto;
}
-/* End: Time (current / duration) */
-
+/* End: Time (Current / Duration) */
-/* Start: Play/pause */
+/* Start: Play/Pause/Stop */
.mejs-controls .mejs-play button {
background-position: 0 0;
}
+
.mejs-controls .mejs-pause button {
background-position: 0 -16px;
}
-/* End: Play/pause */
-
-/* Stop */
.mejs-controls .mejs-stop button {
background-position: -112px 0;
}
-/* End: Play/pause */
+/* Start: Play/Pause/Stop */
-/* Start: Progress bar */
+/* Start: Progress Bar */
.mejs-controls div.mejs-time-rail {
+ direction: ltr;
width: 200px;
padding-top: 5px;
}
+
.mejs-controls .mejs-time-rail span {
display: block;
position: absolute;
@@ -227,6 +248,7 @@
border-radius: 2px;
cursor: pointer;
}
+
.mejs-controls .mejs-time-rail .mejs-time-total {
margin: 5px;
background: #333;
@@ -238,6 +260,7 @@
background: -ms-linear-gradient(top, rgba(30,30,30,0.8), rgba(60,60,60,0.8));
background: linear-gradient(rgba(30,30,30,0.8), rgba(60,60,60,0.8));
}
+
.mejs-controls .mejs-time-rail .mejs-time-buffering {
width: 100%;
background-image: -o-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
@@ -274,8 +297,8 @@
background: linear-gradient(rgba(44,124,145,0.8), rgba(78,183,212,0.8));
width: 0;
}
+
.mejs-controls .mejs-time-rail .mejs-time-current {
- width: 0;
background: #fff;
background: rgba(255,255,255,0.8);
background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(rgba(255,255,255,0.9)), to(rgba(200,200,200,0.8)));
@@ -284,6 +307,7 @@
background: -o-linear-gradient(top, rgba(255,255,255,0.9), rgba(200,200,200,0.8));
background: -ms-linear-gradient(top, rgba(255,255,255,0.9), rgba(200,200,200,0.8));
background: linear-gradient(rgba(255,255,255,0.9), rgba(200,200,200,0.8));
+ width: 0;
}
.mejs-controls .mejs-time-rail .mejs-time-handle {
@@ -321,6 +345,7 @@
text-align: center;
left: 0;
}
+
.mejs-controls .mejs-time-rail .mejs-time-float-corner {
position: absolute;
display: block;
@@ -334,7 +359,6 @@
border-radius: 0;
top: 15px;
left: 13px;
-
}
.mejs-long-video .mejs-controls .mejs-time-rail .mejs-time-float {
@@ -349,21 +373,18 @@
left: 18px;
}
-
-
-
-
/*
.mejs-controls .mejs-time-rail:hover .mejs-time-handle {
visibility:visible;
}
*/
-/* End: Progress bar */
+/* End: Progress Bar */
/* Start: Fullscreen */
.mejs-controls .mejs-fullscreen-button button {
background-position: -32px 0;
}
+
.mejs-controls .mejs-unfullscreen button {
background-position: -32px -16px;
}
@@ -401,11 +422,13 @@
position: absolute;
margin: 0;
}
+
.mejs-controls .mejs-volume-button:hover {
-webkit-border-radius: 0 0 4px 4px;
-moz-border-radius: 0 0 4px 4px;
border-radius: 0 0 4px 4px;
}
+
/*
.mejs-controls .mejs-volume-button:hover .mejs-volume-slider {
display: block;
@@ -449,9 +472,7 @@
margin: 0;
}
-
/* horizontal version */
-
.mejs-controls div.mejs-horizontal-volume-slider {
height: 26px;
width: 60px;
@@ -467,11 +488,9 @@
margin: 0;
padding: 0;
font-size: 1px;
-
-webkit-border-radius: 2px;
-moz-border-radius: 2px;
border-radius: 2px;
-
background: #333;
background: rgba(50,50,50,0.8);
background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(rgba(30,30,30,0.8)), to(rgba(60,60,60,0.8)));
@@ -480,7 +499,6 @@
background: -o-linear-gradient(top, rgba(30,30,30,0.8), rgba(60,60,60,0.8));
background: -ms-linear-gradient(top, rgba(30,30,30,0.8), rgba(60,60,60,0.8));
background: linear-gradient(rgba(30,30,30,0.8), rgba(60,60,60,0.8));
-
}
.mejs-controls .mejs-horizontal-volume-slider .mejs-horizontal-volume-current {
@@ -492,11 +510,9 @@
margin: 0;
padding: 0;
font-size: 1px;
-
-webkit-border-radius: 2px;
-moz-border-radius: 2px;
border-radius: 2px;
-
background: #fff;
background: rgba(255,255,255,0.8);
background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(rgba(255,255,255,0.9)), to(rgba(200,200,200,0.8)));
@@ -505,20 +521,15 @@
background: -o-linear-gradient(top, rgba(255,255,255,0.9), rgba(200,200,200,0.8));
background: -ms-linear-gradient(top, rgba(255,255,255,0.9), rgba(200,200,200,0.8));
background: linear-gradient(rgba(255,255,255,0.9), rgba(200,200,200,0.8));
-
}
-
.mejs-controls .mejs-horizontal-volume-slider .mejs-horizontal-volume-handle {
display: none;
}
/* End: Mute/Volume */
-
-
-
-/* Start: TRACK (Captions and Chapters) */
+/* Start: Track (Captions and Chapters) */
.mejs-controls .mejs-captions-button {
position: relative;
}
@@ -542,6 +553,7 @@
-moz-border-radius: 0;
border-radius: 0;
}
+
/*
.mejs-controls .mejs-captions-button:hover .mejs-captions-selector {
visibility: visible;
@@ -555,6 +567,7 @@
list-style-type: none !important;
overflow: hidden;
}
+
.mejs-controls .mejs-captions-button .mejs-captions-selector ul li {
margin: 0 0 6px 0;
padding: 0;
@@ -563,11 +576,13 @@
color: #fff;
overflow: hidden;
}
+
.mejs-controls .mejs-captions-button .mejs-captions-selector ul li input {
clear: both;
float: left;
margin: 3px 3px 0 5px;
}
+
.mejs-controls .mejs-captions-button .mejs-captions-selector ul li label {
width: 100px;
float: left;
@@ -582,7 +597,6 @@
margin: 0 0 5px 0;
}
-
.mejs-chapters {
position: absolute;
top: 0;
@@ -591,6 +605,7 @@
width: 10000px;
z-index: 1;
}
+
.mejs-chapters .mejs-chapter {
position: absolute;
float: left;
@@ -606,6 +621,7 @@
overflow: hidden;
border: 0;
}
+
.mejs-chapters .mejs-chapter .mejs-chapter-block {
font-size: 11px;
color: #fff;
@@ -615,12 +631,12 @@
border-bottom: solid 1px #333;
cursor: pointer;
}
+
.mejs-chapters .mejs-chapter .mejs-chapter-block-last {
border-right: none;
}
.mejs-chapters .mejs-chapter .mejs-chapter-block:hover {
- /*background: #333;*/
background: #666;
background: rgba(102,102,102, 0.7);
background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(rgba(102,102,102,0.7)), to(rgba(50,50,50,0.6)));
@@ -631,6 +647,7 @@
background: linear-gradient(rgba(102,102,102,0.7), rgba(50,50,50,0.6));
filter: progid:DXImageTransform.Microsoft.Gradient(GradientType=0, startColorstr=#666666,endColorstr=#323232);
}
+
.mejs-chapters .mejs-chapter .mejs-chapter-block .ch-title {
font-size: 12px;
font-weight: bold;
@@ -640,6 +657,7 @@
margin: 0 0 3px 0;
line-height: 12px;
}
+
.mejs-chapters .mejs-chapter .mejs-chapter-block .ch-timespan {
font-size: 12px;
line-height: 12px;
@@ -649,21 +667,21 @@
text-overflow: ellipsis;
}
-
.mejs-captions-layer {
position: absolute;
bottom: 0;
left: 0;
text-align:center;
- /*font-weight: bold;*/
line-height: 22px;
font-size: 12px;
color: #fff;
}
+
.mejs-captions-layer a {
color: #fff;
text-decoration: underline;
}
+
.mejs-captions-layer[lang=ar] {
font-size: 20px;
font-weight: normal;
@@ -686,52 +704,50 @@
background: rgba(20, 20, 20, 0.8);
}
-/* End: TRACK (Captions and Chapters) */
-
-
-
-.mejs-clear {
- clear: both;
-}
+/* End: Track (Captions and Chapters) */
-/* Start: ERROR */
+/* Start: Error */
.me-cannotplay {
}
+
.me-cannotplay a {
color: #fff;
font-weight: bold;
}
+
.me-cannotplay span {
padding: 15px;
display: block;
}
-/* End: ERROR */
+/* End: Error */
/* Start: Loop */
.mejs-controls .mejs-loop-off button {
background-position: -64px -16px;
}
+
.mejs-controls .mejs-loop-on button {
background-position: -64px 0;
}
+
/* End: Loop */
/* Start: backlight */
.mejs-controls .mejs-backlight-off button {
background-position: -80px -16px;
}
+
.mejs-controls .mejs-backlight-on button {
background-position: -80px 0;
}
/* End: backlight */
-
-/* Start: picture controls */
+/* Start: Picture Controls */
.mejs-controls .mejs-picturecontrols-button {
background-position: -96px 0;
}
-/* End: picture controls */
+/* End: Picture Controls */
/* context menu */
@@ -765,8 +781,7 @@
color: #fff;
}
-
-/* Start: SourceChooser */
+/* Start: Source Chooser */
.mejs-controls .mejs-sourcechooser-button {
position: relative;
}
@@ -774,6 +789,7 @@
.mejs-controls .mejs-sourcechooser-button button {
background-position: -128px 0;
}
+
.mejs-controls .mejs-sourcechooser-button .mejs-sourcechooser-selector {
visibility: hidden;
position: absolute;
@@ -798,6 +814,7 @@
list-style-type: none !important;
overflow: hidden;
}
+
.mejs-controls .mejs-sourcechooser-button .mejs-sourcechooser-selector ul li {
margin: 0 0 6px 0;
padding: 0;
@@ -806,11 +823,13 @@
color: #fff;
overflow: hidden;
}
+
.mejs-controls .mejs-sourcechooser-button .mejs-sourcechooser-selector ul li input {
clear: both;
float: left;
margin: 3px 3px 0 5px;
}
+
.mejs-controls .mejs-sourcechooser-button .mejs-sourcechooser-selector ul li label {
width: 100px;
float: left;
@@ -819,8 +838,7 @@
font-family: helvetica, arial;
font-size: 10px;
}
-/* End: SourceChooser */
-
+/* End: Source Chooser */
/* Start: Postroll */
.mejs-postroll-layer {
diff --git a/files_videoviewer/js/flashmediaelement.swf b/files_videoviewer/js/flashmediaelement.swf
index 2a5cb8da7..18daaad70 100644
--- a/files_videoviewer/js/flashmediaelement.swf
+++ b/files_videoviewer/js/flashmediaelement.swf
Binary files differ
diff --git a/files_videoviewer/js/mediaelement-and-player.js b/files_videoviewer/js/mediaelement-and-player.js
index 9b0d668da..7b52c33a8 100644
--- a/files_videoviewer/js/mediaelement-and-player.js
+++ b/files_videoviewer/js/mediaelement-and-player.js
@@ -7,7 +7,7 @@
* for browsers that don't understand HTML5 or can't play the provided codec
* Can play MP4 (H.264), Ogg, WebM, FLV, WMV, WMA, ACC, and MP3
*
-* Copyright 2010-2013, John Dyer (http://j.hn)
+* Copyright 2010-2014, John Dyer (http://j.hn)
* License: MIT
*
*/
@@ -15,7 +15,7 @@
var mejs = mejs || {};
// version number
-mejs.version = '2.13.2';
+mejs.version = '2.14.2';
// player number (for missing, same id attr)
@@ -535,7 +535,7 @@ mejs.PluginMediaElement.prototype = {
// HTML5 methods
play: function () {
if (this.pluginApi != null) {
- if (this.pluginType == 'youtube') {
+ if (this.pluginType == 'youtube' || this.pluginType == 'vimeo') {
this.pluginApi.playVideo();
} else {
this.pluginApi.playMedia();
@@ -545,7 +545,7 @@ mejs.PluginMediaElement.prototype = {
},
load: function () {
if (this.pluginApi != null) {
- if (this.pluginType == 'youtube') {
+ if (this.pluginType == 'youtube' || this.pluginType == 'vimeo') {
} else {
this.pluginApi.loadMedia();
}
@@ -555,7 +555,7 @@ mejs.PluginMediaElement.prototype = {
},
pause: function () {
if (this.pluginApi != null) {
- if (this.pluginType == 'youtube') {
+ if (this.pluginType == 'youtube' || this.pluginType == 'vimeo') {
this.pluginApi.pauseVideo();
} else {
this.pluginApi.pauseMedia();
@@ -567,7 +567,7 @@ mejs.PluginMediaElement.prototype = {
},
stop: function () {
if (this.pluginApi != null) {
- if (this.pluginType == 'youtube') {
+ if (this.pluginType == 'youtube' || this.pluginType == 'vimeo') {
this.pluginApi.stopVideo();
} else {
this.pluginApi.stopMedia();
@@ -637,7 +637,7 @@ mejs.PluginMediaElement.prototype = {
},
setCurrentTime: function (time) {
if (this.pluginApi != null) {
- if (this.pluginType == 'youtube') {
+ if (this.pluginType == 'youtube' || this.pluginType == 'vimeo') {
this.pluginApi.seekTo(time);
} else {
this.pluginApi.setCurrentTime(time);
@@ -651,7 +651,7 @@ mejs.PluginMediaElement.prototype = {
setVolume: function (volume) {
if (this.pluginApi != null) {
// same on YouTube and MEjs
- if (this.pluginType == 'youtube') {
+ if (this.pluginType == 'youtube' || this.pluginType == 'vimeo') {
this.pluginApi.setVolume(volume * 100);
} else {
this.pluginApi.setVolume(volume);
@@ -661,7 +661,7 @@ mejs.PluginMediaElement.prototype = {
},
setMuted: function (muted) {
if (this.pluginApi != null) {
- if (this.pluginType == 'youtube') {
+ if (this.pluginType == 'youtube' || this.pluginType == 'vimeo') {
if (muted) {
this.pluginApi.mute();
} else {
@@ -719,7 +719,7 @@ mejs.PluginMediaElement.prototype = {
var callbacks = this.events[eventName];
if (!callbacks) return true;
if (!callback) { this.events[eventName] = []; return true; }
- for (i = 0; i < callbacks.length; i++) {
+ for (var i = 0; i < callbacks.length; i++) {
if (callbacks[i] === callback) {
this.events[eventName].splice(i, 1);
return true;
@@ -1051,7 +1051,9 @@ mejs.HtmlMediaElementShim = {
// normal check
if (htmlMediaElement.canPlayType(mediaFiles[i].type).replace(/no/, '') !== ''
// special case for Mac/Safari 5.0.3 which answers '' to canPlayType('audio/mp3') but 'maybe' to canPlayType('audio/mpeg')
- || htmlMediaElement.canPlayType(mediaFiles[i].type.replace(/mp3/,'mpeg')).replace(/no/, '') !== '') {
+ || htmlMediaElement.canPlayType(mediaFiles[i].type.replace(/mp3/,'mpeg')).replace(/no/, '') !== ''
+ // special case for m4a supported by detecting mp4 support
+ || htmlMediaElement.canPlayType(mediaFiles[i].type.replace(/m4a/,'mp4')).replace(/no/, '') !== '') {
result.method = 'native';
result.url = mediaFiles[i].url;
break;
@@ -1152,6 +1154,7 @@ mejs.HtmlMediaElementShim = {
switch (ext) {
case 'mp4':
case 'm4v':
+ case 'm4a':
return 'mp4';
case 'webm':
case 'webma':
@@ -1217,8 +1220,8 @@ mejs.HtmlMediaElementShim = {
// check for placement inside a <p> tag (sometimes WYSIWYG editors do this)
node = htmlMediaElement.parentNode;
- while (node !== null && node.tagName.toLowerCase() != 'body') {
- if (node.parentNode.tagName.toLowerCase() == 'p') {
+ while (node !== null && node.tagName.toLowerCase() !== 'body' && node.parentNode != null) {
+ if (node.parentNode.tagName.toLowerCase() === 'p') {
node.parentNode.parentNode.insertBefore(node, node.parentNode);
break;
}
@@ -1345,9 +1348,18 @@ mejs.HtmlMediaElementShim = {
case 'youtube':
- var
+ var videoId;
+ // youtu.be url from share button
+ if (playback.url.lastIndexOf("youtu.be") != -1) {
+ videoId = playback.url.substr(playback.url.lastIndexOf('/')+1);
+ if (videoId.indexOf('?') != -1) {
+ videoId = videoId.substr(0, videoId.indexOf('?'));
+ }
+ }
+ else {
videoId = playback.url.substr(playback.url.lastIndexOf('=')+1);
- youtubeSettings = {
+ }
+ youtubeSettings = {
container: container,
containerId: container.id,
pluginMediaElement: pluginMediaElement,
@@ -1367,23 +1379,57 @@ mejs.HtmlMediaElementShim = {
// DEMO Code. Does NOT work.
case 'vimeo':
- //
-
+ var player_id = pluginid + "_player";
pluginMediaElement.vimeoid = playback.url.substr(playback.url.lastIndexOf('/')+1);
- container.innerHTML ='<iframe src="http://player.vimeo.com/video/' + pluginMediaElement.vimeoid + '?portrait=0&byline=0&title=0" width="' + width +'" height="' + height +'" frameborder="0" class="mejs-shim"></iframe>';
-
- /*
- container.innerHTML =
- '<object width="' + width + '" height="' + height + '" class="mejs-shim">' +
- '<param name="allowfullscreen" value="true" />' +
- '<param name="allowscriptaccess" value="always" />' +
- '<param name="flashvars" value="api=1" />' +
- '<param name="movie" value="http://vimeo.com/moogaloop.swf?clip_id=' + pluginMediaElement.vimeoid + '&amp;server=vimeo.com&amp;show_title=0&amp;show_byline=0&amp;show_portrait=0&amp;color=00adef&amp;fullscreen=1&amp;autoplay=0&amp;loop=0" />' +
- '<embed src="//vimeo.com/moogaloop.swf?api=1&amp;clip_id=' + pluginMediaElement.vimeoid + '&amp;server=vimeo.com&amp;show_title=0&amp;show_byline=0&amp;show_portrait=0&amp;color=00adef&amp;fullscreen=1&amp;autoplay=0&amp;loop=0" type="application/x-shockwave-flash" allowfullscreen="true" allowscriptaccess="always" width="' + width + '" height="' + height + '" class="mejs-shim"></embed>' +
- '</object>';
- */
-
+ container.innerHTML ='<iframe src="//player.vimeo.com/video/' + pluginMediaElement.vimeoid + '?api=1&portrait=0&byline=0&title=0&player_id=' + player_id + '" width="' + width +'" height="' + height +'" frameborder="0" class="mejs-shim" id="' + player_id + '"></iframe>';
+ if (typeof($f) == 'function') { // froogaloop available
+ var player = $f(container.childNodes[0]);
+ player.addEvent('ready', function() {
+ player.playVideo = function() {
+ player.api('play');
+ };
+ player.pauseVideo = function() {
+ player.api('pause');
+ };
+ player.seekTo = function(seconds) {
+ player.api('seekTo', seconds);
+ };
+ function createEvent(player, pluginMediaElement, eventName, e) {
+ var obj = {
+ type: eventName,
+ target: pluginMediaElement
+ };
+ if (eventName == 'timeupdate') {
+ pluginMediaElement.currentTime = obj.currentTime = e.seconds;
+ pluginMediaElement.duration = obj.duration = e.duration;
+ }
+ pluginMediaElement.dispatchEvent(obj.type, obj);
+ }
+ player.addEvent('play', function() {
+ createEvent(player, pluginMediaElement, 'play');
+ createEvent(player, pluginMediaElement, 'playing');
+ });
+ player.addEvent('pause', function() {
+ createEvent(player, pluginMediaElement, 'pause');
+ });
+
+ player.addEvent('finish', function() {
+ createEvent(player, pluginMediaElement, 'ended');
+ });
+ player.addEvent('playProgress', function(e) {
+ createEvent(player, pluginMediaElement, 'timeupdate', e);
+ });
+ pluginMediaElement.pluginApi = player;
+
+ // init mejs
+ mejs.MediaPluginBridge.initPlugin(pluginid);
+
+ });
+ }
+ else {
+ console.warn("You need to include froogaloop for vimeo to work");
+ }
break;
}
// hide original element
@@ -1539,7 +1585,7 @@ mejs.YouTubeApi = {
},
length: 1
};
-
+
}
// send event up the chain
@@ -2417,8 +2463,8 @@ if (typeof jQuery != 'undefined') {
} catch (e) {
// TODO: report control error
//throw e;
- //
- //
+
+
}
}
}
@@ -2455,7 +2501,7 @@ if (typeof jQuery != 'undefined') {
// create callback here since it needs access to current
// MediaElement object
- mejs.MediaElementPlayer.prototype.clickToPlayPauseCallback = function() {
+ t.clickToPlayPauseCallback = function() {
//
if (t.options.clickToPlayPause) {
@@ -2656,6 +2702,11 @@ if (typeof jQuery != 'undefined') {
parentWidth = t.container.parent().closest(':visible').width(),
newHeight = t.isVideo || !t.options.autosizeProgress ? parseInt(parentWidth * nativeHeight/nativeWidth, 10) : nativeHeight;
+ // When we use percent, the newHeight can't be calculated so we get the container height
+ if(isNaN(newHeight)) {
+ newHeight = t.container.parent().closest(':visible').height();
+ }
+
if (t.container.parent()[0].tagName.toLowerCase() === 'body') { // && t.container.siblings().count == 0) {
parentWidth = $(window).width();
newHeight = $(window).height();
@@ -2715,7 +2766,14 @@ if (typeof jQuery != 'undefined') {
total = t.controls.find('.mejs-time-total'),
current = t.controls.find('.mejs-time-current'),
loaded = t.controls.find('.mejs-time-loaded'),
- others = rail.siblings();
+ others = rail.siblings(),
+ lastControl = others.last(),
+ lastControlPosition = null;
+
+ // skip calculation if hidden
+ if (!t.container.is(':visible') || !rail.length || !rail.is(':visible')) {
+ return;
+ }
// allow the size to come from custom CSS
@@ -2739,12 +2797,22 @@ if (typeof jQuery != 'undefined') {
// fit the rail into the remaining space
railWidth = t.controls.width() - usedWidth - (rail.outerWidth(true) - rail.width());
}
-
- // outer area
- rail.width(railWidth);
- // dark space
- total.width(railWidth - (total.outerWidth(true) - total.width()));
-
+
+ // resize the rail,
+ // but then check if the last control (say, the fullscreen button) got pushed down
+ // this often happens when zoomed
+ do {
+ // outer area
+ rail.width(railWidth);
+ // dark space
+ total.width(railWidth - (total.outerWidth(true) - total.width()));
+
+ if (lastControl.css('position') != 'absolute') {
+ lastControlPosition = lastControl.position();
+ railWidth--;
+ }
+ } while (lastControlPosition != null && lastControlPosition.top > 0 && railWidth > 0);
+
if (t.setProgressRail)
t.setProgressRail();
if (t.setCurrentRail)
@@ -2823,7 +2891,7 @@ if (typeof jQuery != 'undefined') {
.bind('click touchstart', function() {
if (t.options.clickToPlayPause) {
if (media.paused) {
- t.play();
+ media.play();
}
}
});
@@ -2924,9 +2992,7 @@ if (typeof jQuery != 'undefined') {
// check if someone clicked outside a player region, then kill its focus
t.globalBind('click', function(event) {
- if ($(event.target).closest('.mejs-container').length == 0) {
- player.hasFocus = false;
- }
+ player.hasFocus = $(event.target).closest('.mejs-container').length != 0;
});
},
@@ -3027,7 +3093,9 @@ if (typeof jQuery != 'undefined') {
// Remove the player from the mejs.players object so that pauseOtherPlayers doesn't blow up when trying to pause a non existance flash api.
delete mejs.players[t.id];
- t.container.remove();
+ if (typeof t.container == 'object') {
+ t.container.remove();
+ }
t.globalUnbind();
delete t.node.player;
}
@@ -3210,9 +3278,14 @@ if (typeof jQuery != 'undefined') {
timefloat = controls.find('.mejs-time-float'),
timefloatcurrent = controls.find('.mejs-time-float-current'),
handleMouseMove = function (e) {
- // mouse position relative to the object
- var x = e.pageX,
- offset = total.offset(),
+ // mouse or touch position relative to the object
+ if (e.originalEvent.changedTouches) {
+ var x = e.originalEvent.changedTouches[0].pageX;
+ }else{
+ var x = e.pageX;
+ }
+
+ var offset = total.offset(),
width = total.outerWidth(true),
percentage = 0,
newTime = 0,
@@ -3249,15 +3322,15 @@ if (typeof jQuery != 'undefined') {
// handle clicks
//controls.find('.mejs-time-rail').delegate('span', 'click', handleMouseMove);
total
- .bind('mousedown', function (e) {
- // only handle left clicks
- if (e.which === 1) {
+ .bind('mousedown touchstart', function (e) {
+ // only handle left clicks or touch
+ if (e.which === 1 || e.which === 0) {
mouseIsDown = true;
handleMouseMove(e);
- t.globalBind('mousemove.dur', function(e) {
+ t.globalBind('mousemove.dur touchmove.dur', function(e) {
handleMouseMove(e);
});
- t.globalBind('mouseup.dur', function (e) {
+ t.globalBind('mouseup.dur touchend.dur', function (e) {
mouseIsDown = false;
timefloat.hide();
t.globalUnbind('.dur');
@@ -3454,7 +3527,7 @@ if (typeof jQuery != 'undefined') {
buildvolume: function(player, controls, layers, media) {
// Android and iOS don't support volume controls
- if (mejs.MediaFeatures.hasTouch && this.options.hideVolumeOnTouchDevices)
+ if ((mejs.MediaFeatures.isAndroid || mejs.MediaFeatures.isiOS) && this.options.hideVolumeOnTouchDevices)
return;
var t = this,
@@ -3988,9 +4061,16 @@ if (typeof jQuery != 'undefined') {
setTimeout(function checkFullscreen() {
if (t.isNativeFullScreen) {
+ var zoomMultiplier = window["devicePixelRatio"] || 1;
+ // Use a percent error margin since devicePixelRatio is a float and not exact.
+ var percentErrorMargin = 0.002; // 0.2%
+ var windowWidth = zoomMultiplier * $(window).width();
+ var screenWidth = screen.width;
+ var absDiff = Math.abs(screenWidth - windowWidth);
+ var marginError = screenWidth * percentErrorMargin;
// check if the video is suddenly not really fullscreen
- if ($(window).width() !== screen.width) {
+ if (absDiff > marginError) {
// manually exit
t.exitFullScreen();
} else {
diff --git a/files_videoviewer/src/flash/FlashMediaElement.as b/files_videoviewer/src/flash/FlashMediaElement.as
new file mode 100644
index 000000000..5d11d20b5
--- /dev/null
+++ b/files_videoviewer/src/flash/FlashMediaElement.as
@@ -0,0 +1,1087 @@
+package
+{
+ import flash.display.*;
+ import flash.events.*;
+ import flash.media.*;
+ import flash.net.*;
+ import flash.text.*;
+ import flash.system.*;
+
+ import flash.media.Video;
+ import flash.net.NetConnection;
+ import flash.net.NetStream;
+
+ import flash.geom.ColorTransform;
+
+ import flash.filters.DropShadowFilter;
+ import flash.utils.Timer;
+ import flash.external.ExternalInterface;
+ import flash.geom.Rectangle;
+
+ import htmlelements.IMediaElement;
+ import htmlelements.VideoElement;
+ import htmlelements.AudioElement;
+ import htmlelements.YouTubeElement;
+
+ public class FlashMediaElement extends MovieClip {
+
+ private var _mediaUrl:String;
+ private var _autoplay:Boolean;
+ private var _preload:String;
+ private var _debug:Boolean;
+ private var _isVideo:Boolean;
+ private var _video:DisplayObject;
+ private var _timerRate:Number;
+ private var _stageWidth:Number;
+ private var _stageHeight:Number;
+ private var _enableSmoothing:Boolean;
+ private var _allowedPluginDomain:String;
+ private var _isFullScreen:Boolean = false;
+ private var _startVolume:Number;
+ private var _controlStyle:String;
+ private var _autoHide:Boolean = true;
+ private var _streamer:String = "";
+ private var _enablePseudoStreaming:Boolean;
+ private var _pseudoStreamingStartQueryParam:String;
+
+ // native video size (from meta data)
+ private var _nativeVideoWidth:Number = 0;
+ private var _nativeVideoHeight:Number = 0;
+
+ // visual elements
+ private var _output:TextField;
+ private var _fullscreenButton:SimpleButton;
+
+ // media
+ private var _mediaElement:IMediaElement;
+
+ // connection to fullscreen
+ private var _connection:LocalConnection;
+ private var _connectionName:String;
+
+ //private var fullscreen_btn:SimpleButton;
+
+ // CONTROLS
+ private var _alwaysShowControls:Boolean;
+ private var _controlBar:MovieClip;
+ private var _controlBarBg:MovieClip;
+ private var _scrubBar:MovieClip;
+ private var _scrubTrack:MovieClip;
+ private var _scrubOverlay:MovieClip;
+ private var _scrubLoaded:MovieClip;
+ private var _hoverTime:MovieClip;
+ private var _hoverTimeText:TextField;
+ private var _playButton:SimpleButton;
+ private var _pauseButton:SimpleButton;
+ private var _duration:TextField;
+ private var _currentTime:TextField;
+ private var _fullscreenIcon:SimpleButton;
+ private var _volumeMuted:SimpleButton;
+ private var _volumeUnMuted:SimpleButton;
+ private var _scrubTrackColor:String;
+ private var _scrubBarColor:String;
+ private var _scrubLoadedColor:String;
+
+ // IDLE Timer for mouse for showing/hiding controls
+ private var _inactiveTime:int;
+ private var _timer:Timer;
+ private var _idleTime:int;
+ private var _isMouseActive:Boolean
+ private var _isOverStage:Boolean = false;
+
+ // security checkes
+ private var securityIssue:Boolean = false; // When SWF parameters contain illegal characters
+ private var directAccess:Boolean = false; // When SWF visited directly with no parameters (or when security issue detected)
+
+
+ public function FlashMediaElement() {
+ // check for security issues (borrowed from jPLayer)
+ checkFlashVars(loaderInfo.parameters);
+
+ // allows this player to be called from a different domain than the HTML page hosting the player
+ //Security.allowDomain("*");
+ //Security.allowInsecureDomain('*');
+
+
+ // add debug output
+ _output = new TextField();
+ _output.textColor = 0xeeeeee;
+ _output.width = stage.stageWidth - 100;
+ _output.height = stage.stageHeight;
+ _output.multiline = true;
+ _output.wordWrap = true;
+ _output.border = false;
+ _output.filters = [new DropShadowFilter(1, 0x000000, 45, 1, 2, 2, 1)];
+
+ _output.text = "Initializing...\n";
+ addChild(_output);
+ _output.visible = securityIssue;
+
+ if (securityIssue) {
+ _output.text = "WARNING: Security issue detected. Player stopped.";
+ return;
+ }
+
+ // get parameters
+ // Use only FlashVars, ignore QueryString
+ var params:Object, pos:int, query:Object;
+
+ params = LoaderInfo(this.root.loaderInfo).parameters;
+ pos = root.loaderInfo.url.indexOf('?');
+ if (pos !== -1) {
+ query = parseStr(root.loaderInfo.url.substr(pos + 1));
+
+ for (var key:String in params) {
+ if (query.hasOwnProperty(trim(key))) {
+ delete params[key];
+ }
+ }
+ }
+
+ _mediaUrl = (params['file'] != undefined) ? String(params['file']) : "";
+ _autoplay = (params['autoplay'] != undefined) ? (String(params['autoplay']) == "true") : false;
+ _debug = (params['debug'] != undefined) ? (String(params['debug']) == "true") : false;
+ _isVideo = (params['isvideo'] != undefined) ? ((String(params['isvideo']) == "false") ? false : true ) : true;
+ _timerRate = (params['timerrate'] != undefined) ? (parseInt(params['timerrate'], 10)) : 250;
+ _alwaysShowControls = (params['controls'] != undefined) ? (String(params['controls']) == "true") : false;
+ _enableSmoothing = (params['smoothing'] != undefined) ? (String(params['smoothing']) == "true") : false;
+ _startVolume = (params['startvolume'] != undefined) ? (parseFloat(params['startvolume'])) : 0.8;
+ _preload = (params['preload'] != undefined) ? params['preload'] : "none";
+ _controlStyle = (params['controlstyle'] != undefined) ? (String(params['controlstyle'])) : ""; // blank or "floating"
+ _autoHide = (params['autohide'] != undefined) ? (String(params['autohide']) == "true") : true;
+ _scrubTrackColor = (params['scrubtrackcolor'] != undefined) ? (String(params['scrubtrackcolor'])) : "0x333333";
+ _scrubBarColor = (params['scrubbarcolor'] != undefined) ? (String(params['scrubbarcolor'])) : "0xefefef";
+ _scrubLoadedColor = (params['scrubloadedcolor'] != undefined) ? (String(params['scrubloadedcolor'])) : "0x3CACC8";
+ _enablePseudoStreaming = (params['pseudostreaming'] != undefined) ? (String(params['pseudostreaming']) == "true") : false;
+ _pseudoStreamingStartQueryParam = (params['pseudostreamstart'] != undefined) ? (String(params['pseudostreamstart'])) : "start";
+ _streamer = (params['flashstreamer'] != undefined) ? (String(params['flashstreamer'])) : "";
+
+ // for audio them controls always show them
+
+ if (!_isVideo && _alwaysShowControls) {
+ _autoHide = false;
+ }
+
+ _output.visible = _debug;
+
+ if (isNaN(_timerRate))
+ _timerRate = 250;
+
+ // setup stage and player sizes/scales
+ stage.align = StageAlign.TOP_LEFT;
+ stage.scaleMode = StageScaleMode.NO_SCALE;
+ _stageWidth = stage.stageWidth;
+ _stageHeight = stage.stageHeight;
+
+ //_autoplay = true;
+ //_mediaUrl = "http://mediafiles.dts.edu/chapel/mp4/20100609.mp4";
+ //_alwaysShowControls = true;
+ //_mediaUrl = "../media/Parades-PastLives.mp3";
+ //_mediaUrl = "../media/echo-hereweare.mp4";
+
+ //_mediaUrl = "http://video.ted.com/talks/podcast/AlGore_2006_480.mp4";
+ //_mediaUrl = "rtmp://stream2.france24.yacast.net/france24_live/en/f24_liveen";
+
+ //_mediaUrl = "http://www.youtube.com/watch?feature=player_embedded&v=yyWWXSwtPP0"; // hosea
+ //_mediaUrl = "http://www.youtube.com/watch?feature=player_embedded&v=m5VDDJlsD6I"; // railer with notes
+
+ //_alwaysShowControls = true;
+
+ //_debug=true;
+
+
+
+
+ // position and hide
+ _fullscreenButton = getChildByName("fullscreen_btn") as SimpleButton;
+ _fullscreenButton.visible = _isVideo;
+ _fullscreenButton.alpha = 0;
+ _fullscreenButton.addEventListener(MouseEvent.CLICK, fullscreenClick, false);
+ _fullscreenButton.x = stage.stageWidth - _fullscreenButton.width;
+ _fullscreenButton.y = stage.stageHeight - _fullscreenButton.height;
+
+
+ // create media element
+ if (_isVideo) {
+
+ if (_mediaUrl.indexOf("youtube.com") > -1 || _mediaUrl.indexOf("youtu.be") > -1) {
+
+ //Security.allowDomain("http://www.youtube.com");
+
+ _mediaElement = new YouTubeElement(this, _autoplay, _preload, _timerRate, _startVolume);
+ _video = (_mediaElement as YouTubeElement).player;
+
+ // these are set and then used once the player is loaded
+ (_mediaElement as YouTubeElement).initWidth = _stageWidth;
+ (_mediaElement as YouTubeElement).initHeight = _stageHeight;
+
+ } else {
+
+ _mediaElement = new VideoElement(this, _autoplay, _preload, _timerRate, _startVolume, _streamer);
+ _video = (_mediaElement as VideoElement).video;
+ _video.width = _stageWidth;
+ _video.height = _stageHeight;
+ (_video as Video).smoothing = _enableSmoothing;
+ (_mediaElement as VideoElement).setReference(this);
+ (_mediaElement as VideoElement).setPseudoStreaming(_enablePseudoStreaming);
+ (_mediaElement as VideoElement).setPseudoStreamingStartParam(_pseudoStreamingStartQueryParam);
+ //_video.scaleMode = VideoScaleMode.MAINTAIN_ASPECT_RATIO;
+ addChild(_video);
+ }
+ } else {
+
+ //var player2:AudioDecoder = new com.automatastudios.audio.audiodecoder.AudioDecoder();
+ _mediaElement = new AudioElement(this, _autoplay, _preload, _timerRate, _startVolume);
+ }
+
+
+ // controls!
+ _controlBar = getChildByName("controls_mc") as MovieClip;
+ _controlBarBg = _controlBar.getChildByName("controls_bg_mc") as MovieClip;
+ _scrubTrack = _controlBar.getChildByName("scrubTrack") as MovieClip;
+ _scrubBar = _controlBar.getChildByName("scrubBar") as MovieClip;
+ _scrubOverlay = _controlBar.getChildByName("scrubOverlay") as MovieClip;
+ _scrubLoaded = _controlBar.getChildByName("scrubLoaded") as MovieClip;
+
+ _scrubOverlay.buttonMode = true;
+ _scrubOverlay.useHandCursor = true
+
+ applyColor(_scrubTrack, _scrubTrackColor);
+ applyColor(_scrubBar, _scrubBarColor);
+ applyColor(_scrubLoaded, _scrubLoadedColor);
+
+ _fullscreenIcon = _controlBar.getChildByName("fullscreenIcon") as SimpleButton;
+ _fullscreenIcon.visible = _isVideo;
+
+ // New fullscreenIcon for new fullscreen floating controls
+ //if(_alwaysShowControls && _controlStyle.toUpperCase()=="FLOATING") {
+ _fullscreenIcon.addEventListener(MouseEvent.CLICK, fullScreenIconClick, false);
+ //}
+
+ _volumeMuted = _controlBar.getChildByName("muted_mc") as SimpleButton;
+ _volumeUnMuted = _controlBar.getChildByName("unmuted_mc") as SimpleButton;
+
+ _volumeMuted.addEventListener(MouseEvent.CLICK, toggleVolume, false);
+ _volumeUnMuted.addEventListener(MouseEvent.CLICK, toggleVolume, false);
+
+ _playButton = _controlBar.getChildByName("play_btn") as SimpleButton;
+ _playButton.addEventListener(MouseEvent.CLICK, function(e:MouseEvent) {
+ _mediaElement.play();
+ });
+ _pauseButton = _controlBar.getChildByName("pause_btn") as SimpleButton;
+ _pauseButton.addEventListener(MouseEvent.CLICK, function(e:MouseEvent) {
+ _mediaElement.pause();
+ });
+ _pauseButton.visible = false;
+ _duration = _controlBar.getChildByName("duration_txt") as TextField;
+ _currentTime = _controlBar.getChildByName("currentTime_txt") as TextField;
+ _hoverTime = _controlBar.getChildByName("hoverTime") as MovieClip;
+ _hoverTimeText = _hoverTime.getChildByName("hoverTime_txt") as TextField;
+ _hoverTime.visible=false;
+ _hoverTime.y=(_hoverTime.height/2)+1;
+ _hoverTime.x=0;
+
+
+
+ // Add new timeline scrubber events
+ _scrubOverlay.addEventListener(MouseEvent.MOUSE_MOVE, scrubMove);
+ _scrubOverlay.addEventListener(MouseEvent.CLICK, scrubClick);
+ _scrubOverlay.addEventListener(MouseEvent.MOUSE_OVER, scrubOver);
+ _scrubOverlay.addEventListener(MouseEvent.MOUSE_OUT, scrubOut);
+
+ if (_autoHide) { // && _alwaysShowControls) {
+ // Add mouse activity for show/hide of controls
+ stage.addEventListener(Event.MOUSE_LEAVE, mouseActivityLeave);
+ stage.addEventListener(MouseEvent.MOUSE_MOVE, mouseActivityMove);
+ _inactiveTime = 2500;
+ _timer = new Timer(_inactiveTime)
+ _timer.addEventListener(TimerEvent.TIMER, idleTimer);
+ _timer.start();
+ // set
+ }
+
+ if(_startVolume<=0) {
+ trace("INITIAL VOLUME: "+_startVolume+" MUTED");
+ _volumeMuted.visible=true;
+ _volumeUnMuted.visible=false;
+ } else {
+ trace("INITIAL VOLUME: "+_startVolume+" UNMUTED");
+ _volumeMuted.visible=false;
+ _volumeUnMuted.visible=true;
+ }
+
+ _controlBar.visible = _alwaysShowControls;
+
+ setControlDepth();
+
+ _output.appendText("stage: " + stage.stageWidth + "x" + stage.stageHeight + "\n");
+ _output.appendText("file: " + _mediaUrl + "\n");
+ _output.appendText("autoplay: " + _autoplay.toString() + "\n");
+ _output.appendText("preload: " + _preload.toString() + "\n");
+ _output.appendText("isvideo: " + _isVideo.toString() + "\n");
+ _output.appendText("smoothing: " + _enableSmoothing.toString() + "\n");
+ _output.appendText("timerrate: " + _timerRate.toString() + "\n");
+ _output.appendText("displayState: " +(stage.hasOwnProperty("displayState")).toString() + "\n");
+
+ // attach javascript
+ _output.appendText("ExternalInterface.available: " + ExternalInterface.available.toString() + "\n");
+ _output.appendText("ExternalInterface.objectID: " + ((ExternalInterface.objectID != null)? ExternalInterface.objectID.toString() : "null") + "\n");
+
+ if (_mediaUrl != "") {
+ _mediaElement.setSrc(_mediaUrl);
+ }
+
+ positionControls();
+
+ // Fire this once just to set the width on some dynamically sized scrub bar items;
+ _scrubBar.scaleX=0;
+ _scrubLoaded.scaleX=0;
+
+
+ if (ExternalInterface.available) { // && !_alwaysShowControls
+
+ _output.appendText("Adding callbacks...\n");
+ try {
+ if (ExternalInterface.objectID != null && ExternalInterface.objectID.toString() != "") {
+
+ // add HTML media methods
+ ExternalInterface.addCallback("playMedia", playMedia);
+ ExternalInterface.addCallback("loadMedia", loadMedia);
+ ExternalInterface.addCallback("pauseMedia", pauseMedia);
+ ExternalInterface.addCallback("stopMedia", stopMedia);
+
+ ExternalInterface.addCallback("setSrc", setSrc);
+ ExternalInterface.addCallback("setCurrentTime", setCurrentTime);
+ ExternalInterface.addCallback("setVolume", setVolume);
+ ExternalInterface.addCallback("setMuted", setMuted);
+
+ ExternalInterface.addCallback("setFullscreen", setFullscreen);
+ ExternalInterface.addCallback("setVideoSize", setVideoSize);
+
+ ExternalInterface.addCallback("positionFullscreenButton", positionFullscreenButton);
+ ExternalInterface.addCallback("hideFullscreenButton", hideFullscreenButton);
+
+ // fire init method
+ ExternalInterface.call("mejs.MediaPluginBridge.initPlugin", ExternalInterface.objectID);
+ }
+
+ _output.appendText("Success...\n");
+
+ } catch (error:SecurityError) {
+ _output.appendText("A SecurityError occurred: " + error.message + "\n");
+ } catch (error:Error) {
+ _output.appendText("An Error occurred: " + error.message + "\n");
+ }
+
+ }
+
+ if (_preload != "none") {
+ _mediaElement.load();
+
+ if (_autoplay) {
+ _mediaElement.play();
+ }
+ } else if (_autoplay) {
+ _mediaElement.load();
+ _mediaElement.play();
+ }
+
+ // listen for resize
+ stage.addEventListener(Event.RESIZE, resizeHandler);
+
+ // send click events up to javascript
+ stage.addEventListener(MouseEvent.CLICK, stageClicked);
+
+ // resize
+ stage.addEventListener(FullScreenEvent.FULL_SCREEN, stageFullScreenChanged);
+ }
+
+ public function setControlDepth():void {
+ // put these on top
+ addChild(_output);
+ addChild(_controlBar);
+ addChild(_fullscreenButton);
+
+ }
+
+ // borrowed from jPLayer
+ // https://github.com/happyworm/jPlayer/blob/e8ca190f7f972a6a421cb95f09e138720e40ed6d/actionscript/Jplayer.as#L228
+ private function checkFlashVars(p:Object):void {
+ var i:Number = 0;
+ for (var s:String in p) {
+ if (isIllegalChar(p[s], s === 'file')) {
+ securityIssue = true; // Illegal char found
+ }
+ i++;
+ }
+ if(i === 0 || securityIssue) {
+ directAccess = true;
+ }
+ }
+
+ private static function parseStr (str:String) : Object {
+ var hash:Object = {},
+ arr1:Array, arr2:Array;
+
+ str = unescape(str).replace(/\+/g, " ");
+
+ arr1 = str.split('&');
+ if (!arr1.length) {
+ return {};
+ }
+
+ for (var i:uint = 0, length:uint = arr1.length; i < length; i++) {
+ arr2 = arr1[i].split('=');
+ if (!arr2.length) {
+ continue;
+ }
+ hash[trim(arr2[0])] = trim(arr2[1]);
+ }
+ return hash;
+ }
+
+
+ private static function trim(str:String) : String {
+ if (!str) {
+ return str;
+ }
+
+ return str.toString().replace(/^\s*/, '').replace(/\s*$/, '');
+ }
+
+ private function isIllegalChar(s:String, isUrl:Boolean):Boolean {
+ var illegals:String = "' \" ( ) { } * + \\ < >";
+ if(isUrl) {
+ illegals = "\" { } \\ < >";
+ }
+ if(Boolean(s)) { // Otherwise exception if parameter null.
+ for each (var illegal:String in illegals.split(' ')) {
+ if(s.indexOf(illegal) >= 0) {
+ return true; // Illegal char found
+ }
+ }
+ }
+ return false;
+ }
+
+
+ // START: Controls and events
+ function mouseActivityMove(event:MouseEvent):void {
+
+ // if mouse is in the video area
+ if (_autoHide && (mouseX>=0 && mouseX<=stage.stageWidth) && (mouseY>=0 && mouseY<=stage.stageHeight)) {
+
+ // This could be move to a nice fade at some point...
+ _controlBar.visible = (_alwaysShowControls || _isFullScreen);
+ _isMouseActive = true;
+ _idleTime = 0;
+ _timer.reset();
+ _timer.start()
+ }
+ }
+
+ function mouseActivityLeave(event:Event):void {
+ if (_autoHide) {
+ _isOverStage = false;
+ // This could be move to a nice fade at some point...
+ _controlBar.visible = false;
+ _isMouseActive = false;
+ _idleTime = 0;
+ _timer.reset();
+ _timer.stop();
+ }
+ }
+
+ function idleTimer(event:TimerEvent):void {
+
+ if (_autoHide) {
+ // This could be move to a nice fade at some point...
+ _controlBar.visible = false;
+ _isMouseActive = false;
+ _idleTime += _inactiveTime;
+ _idleTime = 0;
+ _timer.reset();
+ _timer.stop();
+ }
+ }
+
+
+ function scrubMove(event:MouseEvent):void {
+
+ //if (_alwaysShowControls) {
+ if (_hoverTime.visible) {
+ var seekBarPosition:Number = ((event.localX / _scrubTrack.width) *_mediaElement.duration())*_scrubTrack.scaleX;
+ var hoverPos:Number = (seekBarPosition / _mediaElement.duration()) *_scrubTrack.scaleX;
+
+ if (_isFullScreen) {
+ _hoverTime.x=event.target.parent.mouseX;
+ } else {
+ _hoverTime.x=mouseX;
+ }
+ _hoverTime.y = _scrubBar.y - (_hoverTime.height/2);
+ _hoverTimeText.text = secondsToTimeCode(seekBarPosition);
+ }
+ //}
+ //trace(event);
+ }
+
+ function scrubOver(event:MouseEvent):void {
+ _hoverTime.y = _scrubBar.y-(_hoverTime.height/2)+1;
+ _hoverTime.visible = true;
+ trace(event);
+ }
+
+ function scrubOut(event:MouseEvent):void {
+ _hoverTime.y = _scrubBar.y+(_hoverTime.height/2)+1;
+ _hoverTime.visible = false;
+ //_hoverTime.x=0;
+ //trace(event);
+ }
+
+ function scrubClick(event:MouseEvent):void {
+ //trace(event);
+ var seekBarPosition:Number = ((event.localX / _scrubTrack.width) *_mediaElement.duration())*_scrubTrack.scaleX;
+
+ var tmp:Number = (_mediaElement.currentTime()/_mediaElement.duration())*_scrubTrack.width;
+ var canSeekToPosition:Boolean = _scrubLoaded.scaleX > (seekBarPosition / _mediaElement.duration()) *_scrubTrack.scaleX;
+ //var canSeekToPosition:Boolean = true;
+
+ /*
+ amountLoaded = ns.bytesLoaded / ns.bytesTotal;
+ loader.loadbar._width = amountLoaded * 208.9;
+ loader.scrub._x = ns.time / duration * 208.9;
+ */
+
+ trace("seekBarPosition:"+seekBarPosition, "CanSeekToPosition: "+canSeekToPosition);
+
+ if (seekBarPosition>0 && seekBarPosition<_mediaElement.duration() && canSeekToPosition) {
+ _mediaElement.setCurrentTime(seekBarPosition);
+ }
+ }
+
+ function toggleVolume(event:MouseEvent):void {
+ trace(event.currentTarget.name);
+ switch(event.currentTarget.name) {
+ case "muted_mc":
+ setMuted(false);
+ break;
+ case "unmuted_mc":
+ setMuted(true);
+ break;
+ }
+ }
+
+ function toggleVolumeIcons(volume:Number) {
+ if(volume<=0) {
+ _volumeMuted.visible = true;
+ _volumeUnMuted.visible = false;
+ } else {
+ _volumeMuted.visible = false;
+ _volumeUnMuted.visible = true;
+ }
+ }
+
+ public function positionControls(forced:Boolean=false) {
+
+
+ if ( _controlStyle.toUpperCase() == "FLOATING" && _isFullScreen) {
+
+ trace("CONTROLS: floating");
+ _hoverTime.y=(_hoverTime.height/2)+1;
+ _hoverTime.x=0;
+ _controlBarBg.width = 300;
+ _controlBarBg.height = 93;
+ //_controlBarBg.x = (stage.stageWidth/2) - (_controlBarBg.width/2);
+ //_controlBarBg.y = stage.stageHeight - 300;
+
+ _pauseButton.scaleX = _playButton.scaleX=3.5;
+ _pauseButton.scaleY= _playButton.scaleY=3.5;
+ // center the play button and make it big and at the top
+ _pauseButton.x = _playButton.x = (_controlBarBg.width/2)-(_playButton.width/2)+7;
+ _pauseButton.y = _playButton.y = _controlBarBg.height-_playButton.height-(14)
+
+ _controlBar.x = (stage.stageWidth/2) -150;
+ _controlBar.y = stage.stageHeight - _controlBar.height-100;
+
+
+ // reposition the time and duration items
+
+ _duration.x = _controlBarBg.width - _duration.width - 10;
+ _duration.y = _controlBarBg.height - _duration.height -7;
+ //_currentTime.x = _controlBarBg.width - _duration.width - 10 - _currentTime.width - 10;
+ _currentTime.x = 5
+ _currentTime.y= _controlBarBg.height - _currentTime.height-7;
+
+ _fullscreenIcon.x = _controlBarBg.width - _fullscreenIcon.width - 7;
+ _fullscreenIcon.y = 7;
+
+ _volumeMuted.x = _volumeUnMuted.x = 7;
+ _volumeMuted.y = _volumeUnMuted.y = 7;
+
+ _scrubLoaded.x = _scrubBar.x = _scrubOverlay.x = _scrubTrack.x =_currentTime.x+_currentTime.width+7;
+ _scrubLoaded.y = _scrubBar.y = _scrubOverlay.y = _scrubTrack.y=_controlBarBg.height-_scrubTrack.height-10;
+
+ _scrubBar.width = _scrubOverlay.width = _scrubTrack.width = (_duration.x-_duration.width-14);
+
+
+ } else {
+ trace("CONTROLS: normal, original");
+
+ /*
+ // Original style bottom display
+ _hoverTime.y=(_hoverTime.height/2)+1;
+ _hoverTime.x=0;
+ _controlBarBg.width = stage.stageWidth;
+ _controlBar.y = stage.stageHeight - _controlBar.height;
+ _duration.x = stage.stageWidth - _duration.width - 10;
+ //_currentTime.x = stage.stageWidth - _duration.width - 10 - _currentTime.width - 10;
+ _currentTime.x = _playButton.x+_playButton.width;
+ _scrubTrack.width = (_duration.x-_duration.width-10)-_duration.width+10;
+ _scrubOverlay.width = _scrubTrack.width;
+ _scrubBar.width = _scrubTrack.width;
+ */
+
+ // FLOATING MODE BOTTOM DISPLAY - similar to normal
+ trace("THAT WAY!");
+ _hoverTime.y=(_hoverTime.height/2)+1;
+ _hoverTime.x=0;
+ _controlBarBg.width = stage.stageWidth;
+ _controlBarBg.height = 30;
+ _controlBarBg.y=0;
+ _controlBarBg.x=0;
+ // _controlBarBg.x = 0;
+ // _controlBarBg.y = stage.stageHeight - _controlBar.height;
+
+ _pauseButton.scaleX = _playButton.scaleX=1;
+ _pauseButton.scaleY = _playButton.scaleY=1;
+
+ _pauseButton.x = _playButton.x = 7;
+ _pauseButton.y = _playButton.y = _controlBarBg.height-_playButton.height-2;
+
+
+ //_currentTime.x = stage.stageWidth - _duration.width - 10 - _currentTime.width - 10;
+ _currentTime.x = _playButton.x+_playButton.width;
+
+ _fullscreenIcon.x = _controlBarBg.width - _fullscreenIcon.width - 7;
+ _fullscreenIcon.y = 8;
+
+ _volumeMuted.x = _volumeUnMuted.x = (_isVideo ? _fullscreenIcon.x : _controlBarBg.width) - _volumeMuted.width - 10;
+ _volumeMuted.y = _volumeUnMuted.y = 10;
+
+ _duration.x = _volumeMuted.x - _volumeMuted.width - _duration.width + 5;
+ _duration.y = _currentTime.y = _controlBarBg.height - _currentTime.height - 7;
+
+ _scrubLoaded.x = _scrubBar.x = _scrubOverlay.x = _scrubTrack.x = _currentTime.x + _currentTime.width + 10;
+ _scrubLoaded.y = _scrubBar.y = _scrubOverlay.y = _scrubTrack.y = _controlBarBg.height - _scrubTrack.height - 9;
+
+ _scrubBar.width = _scrubOverlay.width = _scrubTrack.width = (_duration.x-_duration.width-10)-_duration.width+5;
+ _controlBar.x = 0;
+ _controlBar.y = stage.stageHeight - _controlBar.height;
+
+ }
+
+ }
+
+ // END: Controls
+
+
+ function stageClicked(e:MouseEvent):void {
+ //_output.appendText("click: " + e.stageX.toString() +","+e.stageY.toString() + "\n");
+ if (e.target == stage) {
+ sendEvent("click", "");
+ }
+ }
+
+ function resizeHandler(e:Event):void {
+ //_video.scaleX = stage.stageWidth / _stageWidth;
+ //_video.scaleY = stage.stageHeight / _stageHeight;
+ //positionControls();
+
+ repositionVideo();
+ }
+
+ // START: Fullscreen
+ function enterFullscreen() {
+
+ _output.appendText("enterFullscreen()\n");
+
+ var screenRectangle:Rectangle = new Rectangle(0, 0, flash.system.Capabilities.screenResolutionX, flash.system.Capabilities.screenResolutionY);
+ stage.fullScreenSourceRect = screenRectangle;
+
+ stage.displayState = StageDisplayState.FULL_SCREEN;
+
+ repositionVideo();
+ positionControls();
+ updateControls(HtmlMediaEvent.FULLSCREENCHANGE);
+
+ _controlBar.visible = true;
+
+ _isFullScreen = true;
+ }
+
+ function exitFullscreen() {
+
+ stage.displayState = StageDisplayState.NORMAL;
+
+
+ _controlBar.visible = false;
+
+ _isFullScreen = false;
+ }
+
+ function setFullscreen(gofullscreen:Boolean) {
+
+ _output.appendText("setFullscreen: " + gofullscreen.toString() + "\n");
+
+ try {
+ //_fullscreenButton.visible = false;
+
+ if (gofullscreen) {
+ enterFullscreen();
+
+ } else {
+ exitFullscreen();
+ }
+
+ } catch (error:Error) {
+
+ // show the button when the security error doesn't let it work
+ //_fullscreenButton.visible = true;
+ _fullscreenButton.alpha = 1;
+
+ _isFullScreen = false;
+
+ _output.appendText("error setting fullscreen: " + error.message.toString() + "\n");
+ }
+ }
+
+ // control bar button/icon
+ function fullScreenIconClick(e:MouseEvent) {
+ try {
+ _controlBar.visible = true;
+ setFullscreen(!_isFullScreen);
+ repositionVideo();
+ } catch (error:Error) {
+ }
+ }
+
+ // special floating fullscreen icon
+ function fullscreenClick(e:MouseEvent) {
+ //_fullscreenButton.visible = false;
+ _fullscreenButton.alpha = 0
+
+ try {
+ _controlBar.visible = true;
+ setFullscreen(true);
+ repositionVideo();
+ positionControls();
+ } catch (error:Error) {
+ }
+ }
+
+
+ function stageFullScreenChanged(e:FullScreenEvent) {
+ _output.appendText("fullscreen event: " + e.fullScreen.toString() + "\n");
+
+ //_fullscreenButton.visible = false;
+ _fullscreenButton.alpha = 0;
+ _isFullScreen = e.fullScreen;
+
+ sendEvent(HtmlMediaEvent.FULLSCREENCHANGE, "isFullScreen:" + e.fullScreen );
+
+ if (!e.fullScreen) {
+ _controlBar.visible = _alwaysShowControls;
+ }
+ }
+ // END: Fullscreen
+
+ // START: external interface
+ function playMedia() {
+ _output.appendText("play\n");
+ _mediaElement.play();
+ }
+
+ function loadMedia() {
+ _output.appendText("load\n");
+ _mediaElement.load();
+ }
+
+ function pauseMedia() {
+ _output.appendText("pause\n");
+ _mediaElement.pause();
+ }
+
+ function setSrc(url:String) {
+ _output.appendText("setSrc: " + url + "\n");
+ _mediaElement.setSrc(url);
+ }
+
+ function stopMedia() {
+ _output.appendText("stop\n");
+ _mediaElement.stop();
+ }
+
+ function setCurrentTime(time:Number) {
+ _output.appendText("seek: " + time.toString() + "\n");
+ _mediaElement.setCurrentTime(time);
+ }
+
+ function setVolume(volume:Number) {
+ _output.appendText("volume: " + volume.toString() + "\n");
+ _mediaElement.setVolume(volume);
+ toggleVolumeIcons(volume);
+ }
+
+ function setMuted(muted:Boolean) {
+ _output.appendText("muted: " + muted.toString() + "\n");
+ _mediaElement.setMuted(muted);
+ toggleVolumeIcons(_mediaElement.getVolume());
+ }
+
+ function setVideoSize(width:Number, height:Number) {
+ _output.appendText("setVideoSize: " + width.toString() + "," + height.toString() + "\n");
+
+ _stageWidth = width;
+ _stageHeight = height;
+
+ if (_video != null) {
+ repositionVideo();
+ positionControls();
+ //_fullscreenButton.x = stage.stageWidth - _fullscreenButton.width - 10;
+ _output.appendText("result: " + _video.width.toString() + "," + _video.height.toString() + "\n");
+ }
+
+
+ }
+
+ function positionFullscreenButton(x:Number, y:Number, visibleAndAbove:Boolean ) {
+
+ _output.appendText("position FS: " + x.toString() + "x" + y.toString() + "\n");
+
+ // bottom corner
+ /*
+ _fullscreenButton.x = stage.stageWidth - _fullscreenButton.width
+ _fullscreenButton.y = stage.stageHeight - _fullscreenButton.height;
+ */
+
+ // position just above
+ if (visibleAndAbove) {
+ _fullscreenButton.x = x+1;
+ _fullscreenButton.y = y - _fullscreenButton.height+1;
+ } else {
+ _fullscreenButton.x = x;
+ _fullscreenButton.y = y;
+ }
+
+ // check for oversizing
+ if ((_fullscreenButton.x + _fullscreenButton.width) > stage.stageWidth)
+ _fullscreenButton.x = stage.stageWidth - _fullscreenButton.width;
+
+ // show it!
+ if (visibleAndAbove) {
+ _fullscreenButton.alpha = 1;
+ }
+ }
+
+ function hideFullscreenButton() {
+
+ //_fullscreenButton.visible = false;
+ _fullscreenButton.alpha = 0;
+ }
+
+ // END: external interface
+
+
+ function repositionVideo():void {
+
+ if (stage.displayState == "fullScreen") {
+ fullscreen = true;
+ } else {
+ fullscreen = false;
+ }
+
+ _output.appendText("positioning video "+stage.displayState+"\n");
+
+ if (_mediaElement is VideoElement) {
+
+ if (isNaN(_nativeVideoWidth) || isNaN(_nativeVideoHeight) || _nativeVideoWidth <= 0 || _nativeVideoHeight <= 0) {
+ _output.appendText("ERR: I dont' have the native dimension\n");
+ return;
+ }
+
+ // calculate ratios
+ var stageRatio, nativeRatio;
+
+ _video.x = 0;
+ _video.y = 0;
+
+ if(fullscreen == true) {
+ stageRatio = flash.system.Capabilities.screenResolutionX/flash.system.Capabilities.screenResolutionY;
+ nativeRatio = _nativeVideoWidth/_nativeVideoHeight;
+
+ // adjust size and position
+ if (nativeRatio > stageRatio) {
+ _mediaElement.setSize(flash.system.Capabilities.screenResolutionX, _nativeVideoHeight * flash.system.Capabilities.screenResolutionX / _nativeVideoWidth);
+ _video.y = flash.system.Capabilities.screenResolutionY/2 - _video.height/2;
+ } else if (stageRatio > nativeRatio) {
+ _mediaElement.setSize(_nativeVideoWidth * flash.system.Capabilities.screenResolutionY / _nativeVideoHeight, flash.system.Capabilities.screenResolutionY);
+ _video.x = flash.system.Capabilities.screenResolutionX/2 - _video.width/2;
+ } else if (stageRatio == nativeRatio) {
+ _mediaElement.setSize(flash.system.Capabilities.screenResolutionX, flash.system.Capabilities.screenResolutionY);
+ }
+
+ } else {
+ stageRatio = _stageWidth/_stageHeight;
+ nativeRatio = _nativeVideoWidth/_nativeVideoHeight;
+
+ // adjust size and position
+ if (nativeRatio > stageRatio) {
+ _mediaElement.setSize(_stageWidth, _nativeVideoHeight * _stageWidth / _nativeVideoWidth);
+ _video.y = _stageHeight/2 - _video.height/2;
+ } else if (stageRatio > nativeRatio) {
+ _mediaElement.setSize( _nativeVideoWidth * _stageHeight / _nativeVideoHeight, _stageHeight);
+ _video.x = _stageWidth/2 - _video.width/2;
+ } else if (stageRatio == nativeRatio) {
+ _mediaElement.setSize(_stageWidth, _stageHeight);
+ }
+
+ }
+
+ } else if (_mediaElement is YouTubeElement) {
+ if(fullscreen == true) {
+ _mediaElement.setSize(flash.system.Capabilities.screenResolutionX, flash.system.Capabilities.screenResolutionY);
+
+ } else {
+ _mediaElement.setSize(_stageWidth, _stageHeight);
+
+ }
+
+ }
+
+ positionControls();
+ }
+
+ // SEND events to JavaScript
+ public function sendEvent(eventName:String, eventValues:String) {
+
+ // special video event
+ if (eventName == HtmlMediaEvent.LOADEDMETADATA && _isVideo) {
+
+ _output.appendText("METADATA RECEIVED: ");
+
+ try {
+ if (_mediaElement is VideoElement) {
+ _nativeVideoWidth = (_mediaElement as VideoElement).videoWidth;
+ _nativeVideoHeight = (_mediaElement as VideoElement).videoHeight;
+ }
+ } catch (e:Error) {
+ _output.appendText(e.toString() + "\n");
+ }
+
+ _output.appendText(_nativeVideoWidth.toString() + "x" + _nativeVideoHeight.toString() + "\n");
+
+
+ if(stage.displayState == "fullScreen" ) {
+ setVideoSize(_nativeVideoWidth, _nativeVideoHeight);
+ }
+ repositionVideo();
+
+ }
+
+ updateControls(eventName);
+
+ //trace((_mediaElement.duration()*1).toString() + " / " + (_mediaElement.currentTime()*1).toString());
+ //trace("CurrentProgress:"+_mediaElement.currentProgress());
+
+ if (ExternalInterface.objectID != null && ExternalInterface.objectID.toString() != "") {
+
+ //_output.appendText("event:" + eventName + " : " + eventValues);
+ //trace("event", eventName, eventValues);
+
+ if (eventValues == null)
+ eventValues == "";
+
+ if (_isVideo) {
+ eventValues += (eventValues != "" ? "," : "") + "isFullScreen:" + _isFullScreen;
+ }
+
+ eventValues = "{" + eventValues + "}";
+
+ /*
+ OLD DIRECT METHOD
+ ExternalInterface.call(
+ "function(id, name) { mejs.MediaPluginBridge.fireEvent(id,name," + eventValues + "); }",
+ ExternalInterface.objectID,
+ eventName);
+ */
+
+ // use set timeout for performance reasons
+ //if (!_alwaysShowControls) {
+ ExternalInterface.call("setTimeout", "mejs.MediaPluginBridge.fireEvent('" + ExternalInterface.objectID + "','" + eventName + "'," + eventValues + ")",0);
+ //}
+ }
+ }
+
+
+ function updateControls(eventName:String):void {
+
+ //trace("updating controls");
+
+ try {
+ // update controls
+ switch (eventName) {
+ case "pause":
+ case "paused":
+ case "ended":
+ _playButton.visible = true;
+ _pauseButton.visible = false;
+ break;
+ case "play":
+ case "playing":
+ _playButton.visible = false;
+ _pauseButton.visible = true;
+ break;
+ }
+
+ if (eventName == HtmlMediaEvent.TIMEUPDATE ||
+ eventName == HtmlMediaEvent.PROGRESS ||
+ eventName == HtmlMediaEvent.FULLSCREENCHANGE) {
+
+ //_duration.text = (_mediaElement.duration()*1).toString();
+ _duration.text = secondsToTimeCode(_mediaElement.duration());
+ //_currentTime.text = (_mediaElement.currentTime()*1).toString();
+ _currentTime.text = secondsToTimeCode(_mediaElement.currentTime());
+
+ var pct:Number = (_mediaElement.currentTime() / _mediaElement.duration()) *_scrubTrack.scaleX;
+
+ _scrubBar.scaleX = pct;
+ _scrubLoaded.scaleX = (_mediaElement.currentProgress()*_scrubTrack.scaleX)/100;
+ }
+ } catch (error:Error) {
+ trace("error: " + error.toString());
+
+ }
+
+ }
+
+ // START: utility
+ function secondsToTimeCode(seconds:Number):String {
+ var timeCode:String = "";
+ seconds = Math.round(seconds);
+ var minutes:Number = Math.floor(seconds / 60);
+ timeCode = (minutes >= 10) ? minutes.toString() : "0" + minutes.toString();
+ seconds = Math.floor(seconds % 60);
+ timeCode += ":" + ((seconds >= 10) ? seconds.toString() : "0" + seconds.toString());
+ return timeCode; //minutes.toString() + ":" + seconds.toString();
+ }
+
+ function applyColor(item:Object, color:String):void {
+
+ var myColor:ColorTransform = item.transform.colorTransform;
+ myColor.color = Number(color);
+ item.transform.colorTransform = myColor;
+ }
+ // END: utility
+
+ }
+} \ No newline at end of file
diff --git a/files_videoviewer/src/flash/FlashMediaElement.fla b/files_videoviewer/src/flash/FlashMediaElement.fla
new file mode 100644
index 000000000..adf6e99fc
--- /dev/null
+++ b/files_videoviewer/src/flash/FlashMediaElement.fla
Binary files differ
diff --git a/files_videoviewer/src/flash/HtmlMediaEvent.as b/files_videoviewer/src/flash/HtmlMediaEvent.as
new file mode 100644
index 000000000..d12c0fedf
--- /dev/null
+++ b/files_videoviewer/src/flash/HtmlMediaEvent.as
@@ -0,0 +1,29 @@
+package {
+
+ public class HtmlMediaEvent {
+
+ public static var LOADED_DATA:String = "loadeddata";
+ public static var PROGRESS:String = "progress";
+ public static var TIMEUPDATE:String = "timeupdate";
+ public static var SEEKED:String = "seeked";
+ public static var PLAY:String = "play";
+ public static var PLAYING:String = "playing";
+ public static var PAUSE:String = "pause";
+ public static var LOADEDMETADATA:String = "loadedmetadata";
+ public static var ENDED:String = "ended";
+ public static var VOLUMECHANGE:String = "volumechange";
+ public static var STOP:String = "stop";
+
+ // new : 2/15/2011
+ public static var LOADSTART:String = "loadstart";
+ public static var CANPLAY:String = "canplay";
+ // new : 3/3/2011
+ public static var LOADEDDATA:String = "loadeddata";
+
+ // new : 4/12/2011
+ public static var SEEKING:String = "seeking";
+
+ // new : 1/2/2012
+ public static var FULLSCREENCHANGE:String = "fullscreenchange";
+ }
+}
diff --git a/files_videoviewer/src/flash/htmlelements/AudioElement.as b/files_videoviewer/src/flash/htmlelements/AudioElement.as
new file mode 100644
index 000000000..750599d4a
--- /dev/null
+++ b/files_videoviewer/src/flash/htmlelements/AudioElement.as
@@ -0,0 +1,332 @@
+
+package htmlelements
+{
+ import flash.events.Event;
+ import flash.events.IOErrorEvent;
+ import flash.events.ProgressEvent;
+ import flash.events.TimerEvent;
+ import flash.media.ID3Info;
+ import flash.media.Sound;
+ import flash.media.SoundChannel;
+ import flash.media.SoundLoaderContext;
+ import flash.media.SoundTransform;
+ import flash.net.URLRequest;
+ import flash.utils.Timer;
+
+
+
+ /**
+ * ...
+ * @author DefaultUser (Tools -> Custom Arguments...)
+ */
+ public class AudioElement implements IMediaElement
+ {
+
+ private var _sound:Sound;
+ private var _soundTransform:SoundTransform;
+ private var _soundChannel:SoundChannel;
+ private var _soundLoaderContext:SoundLoaderContext;
+
+ private var _volume:Number = 1;
+ private var _preMuteVolume:Number = 0;
+ private var _isMuted:Boolean = false;
+ private var _isPaused:Boolean = true;
+ private var _isEnded:Boolean = false;
+ private var _isLoaded:Boolean = false;
+ private var _currentTime:Number = 0;
+ private var _duration:Number = 0;
+ private var _bytesLoaded:Number = 0;
+ private var _bytesTotal:Number = 0;
+ private var _bufferedTime:Number = 0;
+ private var _bufferingChanged:Boolean = false;
+
+ private var _currentUrl:String = "";
+ private var _autoplay:Boolean = true;
+ private var _preload:String = "";
+
+ private var _element:FlashMediaElement;
+ private var _timer:Timer;
+ private var _firedCanPlay:Boolean = false;
+
+ public function setSize(width:Number, height:Number):void {
+ // do nothing!
+ }
+
+ public function duration():Number {
+ return _duration;
+ }
+
+ public function currentTime():Number {
+ return _currentTime;
+ }
+
+ public function currentProgress():Number {
+ return Math.round(_bytesLoaded/_bytesTotal*100);
+ }
+
+ public function AudioElement(element:FlashMediaElement, autoplay:Boolean, preload:String, timerRate:Number, startVolume:Number)
+ {
+ _element = element;
+ _autoplay = autoplay;
+ _volume = startVolume;
+ _preload = preload;
+
+ _timer = new Timer(timerRate);
+ _timer.addEventListener(TimerEvent.TIMER, timerEventHandler);
+
+ _soundTransform = new SoundTransform(_volume);
+ _soundLoaderContext = new SoundLoaderContext();
+ }
+
+ // events
+ function progressHandler(e:ProgressEvent):void {
+
+ _bytesLoaded = e.bytesLoaded;
+ _bytesTotal = e.bytesTotal;
+
+ // this happens too much to send every time
+ //sendEvent(HtmlMediaEvent.PROGRESS);
+
+ // so now we just trigger a flag and send with the timer
+ _bufferingChanged = true;
+ }
+
+ function id3Handler(e:Event):void {
+ sendEvent(HtmlMediaEvent.LOADEDMETADATA);
+
+ try {
+ var id3:ID3Info = _sound.id3;
+ var obj = {
+ type:'id3',
+ album:id3.album,
+ artist:id3.artist,
+ comment:id3.comment,
+ genre:id3.genre,
+ songName:id3.songName,
+ track:id3.track,
+ year:id3.year
+ }
+ } catch (err:Error) {}
+
+
+ }
+
+ function timerEventHandler(e:TimerEvent) {
+ _currentTime = _soundChannel.position/1000;
+
+ // calculate duration
+ var duration = Math.round(_sound.length * _sound.bytesTotal/_sound.bytesLoaded/100) / 10;
+
+ // check to see if the estimated duration changed
+ if (_duration != duration && !isNaN(duration)) {
+
+ _duration = duration;
+ sendEvent(HtmlMediaEvent.LOADEDMETADATA);
+ }
+
+ // check for progress
+ if (_bufferingChanged) {
+
+ sendEvent(HtmlMediaEvent.PROGRESS);
+
+ _bufferingChanged = false;
+ }
+
+ // send timeupdate
+ sendEvent(HtmlMediaEvent.TIMEUPDATE);
+
+ // sometimes the ended event doesn't fire, here's a fake one
+ if (_duration > 0 && _currentTime >= _duration-0.2) {
+ handleEnded();
+ }
+ }
+
+ function soundCompleteHandler(e:Event) {
+ handleEnded();
+ }
+
+ function handleEnded():void {
+ _timer.stop();
+ _currentTime = 0;
+ _isEnded = true;
+
+ sendEvent(HtmlMediaEvent.ENDED);
+ }
+
+ //events
+
+
+ // METHODS
+ public function setSrc(url:String):void {
+ _currentUrl = url;
+ _isLoaded = false;
+ }
+
+
+ public function load():void {
+
+ if (_currentUrl == "")
+ return;
+
+ _sound = new Sound();
+ //sound.addEventListener(IOErrorEvent.IO_ERROR,errorHandler);
+ _sound.addEventListener(ProgressEvent.PROGRESS,progressHandler);
+ _sound.addEventListener(Event.ID3,id3Handler);
+ _sound.load(new URLRequest(_currentUrl));
+ _currentTime = 0;
+
+ sendEvent(HtmlMediaEvent.LOADSTART);
+
+ _isLoaded = true;
+
+ sendEvent(HtmlMediaEvent.LOADEDDATA);
+ sendEvent(HtmlMediaEvent.CANPLAY);
+ _firedCanPlay = true;
+
+ if (_playAfterLoading) {
+ _playAfterLoading = false;
+ play();
+ }
+ }
+
+ private var _playAfterLoading:Boolean= false;
+
+ public function play():void {
+
+ if (!_isLoaded) {
+ _playAfterLoading = true;
+ load();
+ return;
+ }
+
+ _timer.stop();
+
+ _soundChannel = _sound.play(_currentTime*1000, 0, _soundTransform);
+ _soundChannel.removeEventListener(Event.SOUND_COMPLETE, soundCompleteHandler);
+ _soundChannel.addEventListener(Event.SOUND_COMPLETE, soundCompleteHandler);
+
+ _timer.start();
+
+ didStartPlaying();
+ }
+
+ public function pause():void {
+
+ _timer.stop();
+ if (_soundChannel != null) {
+ _currentTime = _soundChannel.position/1000;
+ _soundChannel.stop();
+ }
+
+ _isPaused = true;
+ sendEvent(HtmlMediaEvent.PAUSE);
+ }
+
+
+ public function stop():void {
+ if (_timer != null) {
+ _timer.stop();
+ }
+ if (_soundChannel != null) {
+ _soundChannel.stop();
+ _sound.close();
+ }
+ unload();
+ sendEvent(HtmlMediaEvent.STOP);
+ }
+
+ public function setCurrentTime(pos:Number):void {
+ sendEvent(HtmlMediaEvent.SEEKING);
+ _timer.stop();
+ _currentTime = pos;
+ _soundChannel.stop();
+ _sound.length
+ _soundChannel = _sound.play(_currentTime * 1000, 0, _soundTransform);
+ sendEvent(HtmlMediaEvent.SEEKED);
+
+ _timer.start();
+
+ didStartPlaying();
+ }
+
+ private function didStartPlaying():void {
+ _isPaused = false;
+ sendEvent(HtmlMediaEvent.PLAY);
+ sendEvent(HtmlMediaEvent.PLAYING);
+ if (!_firedCanPlay) {
+ sendEvent(HtmlMediaEvent.LOADEDDATA);
+ sendEvent(HtmlMediaEvent.CANPLAY);
+ _firedCanPlay = true;
+ }
+ }
+
+
+ public function setVolume(volume:Number):void {
+
+ _volume = volume;
+ _soundTransform.volume = volume;
+
+ if (_soundChannel != null) {
+ _soundChannel.soundTransform = _soundTransform;
+ }
+
+ _isMuted = (_volume == 0);
+
+ sendEvent(HtmlMediaEvent.VOLUMECHANGE);
+ }
+
+ public function getVolume():Number {
+ if(_isMuted) {
+ return 0;
+ } else {
+ return _volume;
+ }
+ }
+
+
+ public function setMuted(muted:Boolean):void {
+
+ // ignore if already set
+ if ( (muted && _isMuted) || (!muted && !_isMuted))
+ return;
+
+ if (muted) {
+ _preMuteVolume = _soundTransform.volume;
+ setVolume(0);
+ } else {
+ setVolume(_preMuteVolume);
+ }
+
+ _isMuted = muted;
+ }
+
+ public function unload():void {
+ _sound = null;
+ _isLoaded = false;
+ }
+
+ private function sendEvent(eventName:String) {
+
+ // calculate this to mimic HTML5
+ _bufferedTime = _bytesLoaded / _bytesTotal * _duration;
+
+ // build JSON
+ var values:String = "duration:" + _duration +
+ ",currentTime:" + _currentTime +
+ ",muted:" + _isMuted +
+ ",paused:" + _isPaused +
+ ",ended:" + _isEnded +
+ ",volume:" + _volume +
+ ",src:\"" + _currentUrl + "\"" +
+ ",bytesTotal:" + _bytesTotal +
+ ",bufferedBytes:" + _bytesLoaded +
+ ",bufferedTime:" + _bufferedTime +
+ "";
+
+ _element.sendEvent(eventName, values);
+ }
+
+ }
+
+}
+
diff --git a/files_videoviewer/src/flash/htmlelements/IMediaElement.as b/files_videoviewer/src/flash/htmlelements/IMediaElement.as
new file mode 100644
index 000000000..d62660795
--- /dev/null
+++ b/files_videoviewer/src/flash/htmlelements/IMediaElement.as
@@ -0,0 +1,35 @@
+
+package htmlelements
+{
+
+ public interface IMediaElement {
+
+ function play():void;
+
+ function pause():void;
+
+ function load():void;
+
+ function stop():void;
+
+ function setSrc(url:String):void;
+
+ function setSize(width:Number, height:Number):void;
+
+ function setCurrentTime(pos:Number):void;
+
+ function setVolume(vol:Number):void;
+
+ function getVolume():Number;
+
+ function setMuted(muted:Boolean):void;
+
+ function duration():Number;
+
+ function currentTime():Number;
+
+ function currentProgress():Number;
+
+ }
+
+}
diff --git a/files_videoviewer/src/flash/htmlelements/VideoElement.as b/files_videoviewer/src/flash/htmlelements/VideoElement.as
new file mode 100644
index 000000000..7673c4f6c
--- /dev/null
+++ b/files_videoviewer/src/flash/htmlelements/VideoElement.as
@@ -0,0 +1 @@
+package htmlelements { import flash.display.Sprite; import flash.events.*; import flash.net.NetConnection; import flash.net.NetStream; import flash.media.Video; import flash.media.SoundTransform; import flash.utils.Timer; import FlashMediaElement; import HtmlMediaEvent; public class VideoElement extends Sprite implements IMediaElement { private var _currentUrl:String = ""; private var _autoplay:Boolean = true; private var _preload:String = ""; private var _isPreloading:Boolean = false; private var _connection:NetConnection; private var _stream:NetStream; private var _video:Video; private var _element:FlashMediaElement; private var _soundTransform; private var _oldVolume:Number = 1; // event values private var _duration:Number = 0; private var _framerate:Number; private var _isPaused:Boolean = true; private var _isEnded:Boolean = false; private var _volume:Number = 1; private var _isMuted:Boolean = false; private var _bytesLoaded:Number = 0; private var _bytesTotal:Number = 0; private var _bufferedTime:Number = 0; private var _bufferEmpty:Boolean = false; private var _bufferingChanged:Boolean = false; private var _seekOffset:Number = 0; private var _videoWidth:Number = -1; private var _videoHeight:Number = -1; private var _timer:Timer; private var _isRTMP:Boolean = false; private var _streamer:String = ""; private var _isConnected:Boolean = false; private var _playWhenConnected:Boolean = false; private var _hasStartedPlaying:Boolean = false; private var _parentReference:Object; private var _pseudoStreamingEnabled:Boolean = false; private var _pseudoStreamingStartQueryParam:String = "start"; public function setReference(arg:Object):void { _parentReference = arg; } public function setSize(width:Number, height:Number):void { _video.width = width; _video.height = height; } public function setPseudoStreaming(enablePseudoStreaming:Boolean):void { _pseudoStreamingEnabled = enablePseudoStreaming; } public function setPseudoStreamingStartParam(pseudoStreamingStartQueryParam:String):void { _pseudoStreamingStartQueryParam = pseudoStreamingStartQueryParam; } public function get video():Video { return _video; } public function get videoHeight():Number { return _videoHeight; } public function get videoWidth():Number { return _videoWidth; } public function duration():Number { return _duration; } public function currentProgress():Number { if(_stream != null) { return Math.round(_stream.bytesLoaded/_stream.bytesTotal*100); } else { return 0; } } public function currentTime():Number { var currentTime:Number = 0; if (_stream != null) { currentTime = _stream.time; if (_pseudoStreamingEnabled) { currentTime += _seekOffset; } } return currentTime; } // (1) load() // calls _connection.connect(); // waits for NetConnection.Connect.Success // _stream gets created public function VideoElement(element:FlashMediaElement, autoplay:Boolean, preload:String, timerRate:Number, startVolume:Number, streamer:String) { _element = element; _autoplay = autoplay; _volume = startVolume; _preload = preload; _streamer = streamer; _video = new Video(); addChild(_video); _connection = new NetConnection(); _connection.client = { onBWDone: function():void{} }; _connection.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler); _connection.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler); //_connection.connect(null); _timer = new Timer(timerRate); _timer.addEventListener("timer", timerHandler); } private function timerHandler(e:TimerEvent) { _bytesLoaded = _stream.bytesLoaded; _bytesTotal = _stream.bytesTotal; if (!_isPaused) { sendEvent(HtmlMediaEvent.TIMEUPDATE); } //trace("bytes", _bytesLoaded, _bytesTotal); if (_bytesLoaded < _bytesTotal) sendEvent(HtmlMediaEvent.PROGRESS); } // internal events private function netStatusHandler(event:NetStatusEvent):void { trace("netStatus", event.info.code); switch (event.info.code) { case "NetStream.Buffer.Empty": _bufferEmpty = true; _isEnded ? sendEvent(HtmlMediaEvent.ENDED) : null; break; case "NetStream.Buffer.Full": _bytesLoaded = _stream.bytesLoaded; _bytesTotal = _stream.bytesTotal; _bufferEmpty = false; sendEvent(HtmlMediaEvent.PROGRESS); break; case "NetConnection.Connect.Success": connectStream(); break; case "NetStream.Play.StreamNotFound": trace("Unable to locate video"); break; // STREAM case "NetStream.Play.Start": _isPaused = false; sendEvent(HtmlMediaEvent.LOADEDDATA); sendEvent(HtmlMediaEvent.CANPLAY); if (!_isPreloading) { sendEvent(HtmlMediaEvent.PLAY); sendEvent(HtmlMediaEvent.PLAYING); } _timer.start(); break; case "NetStream.Seek.Notify": sendEvent(HtmlMediaEvent.SEEKED); break; case "NetStream.Pause.Notify": _isPaused = true; sendEvent(HtmlMediaEvent.PAUSE); break; case "NetStream.Play.Stop": _isEnded = true; _isPaused = false; _timer.stop(); _bufferEmpty ? sendEvent(HtmlMediaEvent.ENDED) : null; break; } } private function securityErrorHandler(event:SecurityErrorEvent):void { trace("securityErrorHandler: " + event); } private function asyncErrorHandler(event:AsyncErrorEvent):void { // ignore AsyncErrorEvent events. } private function onMetaDataHandler(info:Object):void { // Only set the duration when we first load the video if (_duration == 0) { _duration = info.duration; } _framerate = info.framerate; _videoWidth = info.width; _videoHeight = info.height; // set size? sendEvent(HtmlMediaEvent.LOADEDMETADATA); if (_isPreloading) { _stream.pause(); _isPaused = true; _isPreloading = false; sendEvent(HtmlMediaEvent.PROGRESS); sendEvent(HtmlMediaEvent.TIMEUPDATE); } } // interface members public function setSrc(url:String):void { if (_isConnected && _stream) { // stop and restart _stream.pause(); } _currentUrl = url; _isRTMP = !!_currentUrl.match(/^rtmp(s|t|e|te)?\:\/\//) || _streamer != ""; _isConnected = false; _hasStartedPlaying = false; } public function load():void { // disconnect existing stream and connection if (_isConnected && _stream) { _stream.pause(); _stream.close(); _connection.close(); } _isConnected = false; _isPreloading = false; _isEnded = false; _bufferEmpty = false; // start new connection if (_isRTMP) { var rtmpInfo:Object = parseRTMP(_currentUrl); if (_streamer != "") { rtmpInfo.server = _streamer; rtmpInfo.stream = _currentUrl; } _connection.connect(rtmpInfo.server); } else { _connection.connect(null); } // in a few moments the "NetConnection.Connect.Success" event will fire // and call createConnection which finishes the "load" sequence sendEvent(HtmlMediaEvent.LOADSTART); } private function connectStream():void { trace("connectStream"); _stream = new NetStream(_connection); // explicitly set the sound since it could have come before the connection was made _soundTransform = new SoundTransform(_volume); _stream.soundTransform = _soundTransform; // set the buffer to ensure nice playback _stream.bufferTime = 1; _stream.bufferTimeMax = 3; _stream.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler); // same event as connection _stream.addEventListener(AsyncErrorEvent.ASYNC_ERROR, asyncErrorHandler); var customClient:Object = new Object(); customClient.onMetaData = onMetaDataHandler; _stream.client = customClient; _video.attachNetStream(_stream); // start downloading without playing )based on preload and play() hasn't been called) // I wish flash had a load() command to make this less awkward if (_preload != "none" && !_playWhenConnected) { _isPaused = true; //stream.bufferTime = 20; _stream.play(getCurrentUrl(0), 0, 0); _stream.pause(); _isPreloading = true; //_stream.pause(); // //sendEvent(HtmlMediaEvent.PAUSE); // have to send this because the "playing" event gets sent via event handlers } _isConnected = true; if (_playWhenConnected && !_hasStartedPlaying) { play(); _playWhenConnected = false; } } public function play():void { if (!_hasStartedPlaying && !_isConnected) { _playWhenConnected = true; load(); return; } if (_hasStartedPlaying) { if (_isPaused) { _stream.resume(); _timer.start(); _isPaused = false; sendEvent(HtmlMediaEvent.PLAY); sendEvent(HtmlMediaEvent.PLAYING); } } else { if (_isRTMP) { var rtmpInfo:Object = parseRTMP(_currentUrl); _stream.play(rtmpInfo.stream); } else { _stream.play(getCurrentUrl(0)); } _timer.start(); _isPaused = false; _hasStartedPlaying = true; // don't toss play/playing events here, because we haven't sent a // canplay / loadeddata event yet. that'll be handled in the net // event listener } } public function pause():void { if (_stream == null) return; _stream.pause(); _isPaused = true; if (_bytesLoaded == _bytesTotal) { _timer.stop(); } _isPaused = true; sendEvent(HtmlMediaEvent.PAUSE); } public function stop():void { if (_stream == null) return; _stream.close(); _isPaused = false; _timer.stop(); sendEvent(HtmlMediaEvent.STOP); } public function setCurrentTime(pos:Number):void { if (_stream == null) { return; } // Calculate the position of the buffered video var bufferPosition:Number = _bytesLoaded / _bytesTotal * _duration; if (_pseudoStreamingEnabled) { sendEvent(HtmlMediaEvent.SEEKING); // Normal seek if it is in buffer and this is the first seek if (pos < bufferPosition && _seekOffset == 0) { _stream.seek(pos); } else { // Uses server-side pseudo-streaming to seek _stream.play(getCurrentUrl(pos)); _seekOffset = pos; } } else { sendEvent(HtmlMediaEvent.SEEKING); _stream.seek(pos); } if (!_isEnded) { sendEvent(HtmlMediaEvent.TIMEUPDATE); } } public function setVolume(volume:Number):void { if (_stream != null) { _soundTransform = new SoundTransform(volume); _stream.soundTransform = _soundTransform; } _volume = volume; _isMuted = (_volume == 0); sendEvent(HtmlMediaEvent.VOLUMECHANGE); } public function getVolume():Number { if(_isMuted) { return 0; } else { return _volume; } } public function setMuted(muted:Boolean):void { if (_isMuted == muted) return; if (muted) { _oldVolume = (_stream == null) ? _oldVolume : _stream.soundTransform.volume; setVolume(0); } else { setVolume(_oldVolume); } _isMuted = muted; } private function sendEvent(eventName:String) { // calculate this to mimic HTML5 _bufferedTime = _bytesLoaded / _bytesTotal * _duration; // build JSON var values:String = "duration:" + _duration + ",framerate:" + _framerate + ",currentTime:" + currentTime() + ",muted:" + _isMuted + ",paused:" + _isPaused + ",ended:" + _isEnded + ",volume:" + _volume + ",src:\"" + _currentUrl + "\"" + ",bytesTotal:" + _bytesTotal + ",bufferedBytes:" + _bytesLoaded + ",bufferedTime:" + _bufferedTime + ",videoWidth:" + _videoWidth + ",videoHeight:" + _videoHeight + ""; _element.sendEvent(eventName, values); } private function parseRTMP(url:String) { var match:Array = url.match(/(.*)\/((flv|mp4|mp3):.*)/); var rtmpInfo:Object = { server: null, stream: null }; if (match) { rtmpInfo.server = match[1]; rtmpInfo.stream = match[2]; } else { rtmpInfo.server = url.replace(/\/[^\/]+$/,"/"); rtmpInfo.stream = url.split("/").pop(); } trace("parseRTMP - server: " + rtmpInfo.server + " stream: " + rtmpInfo.stream); return rtmpInfo; } private function getCurrentUrl(pos:Number):String { var url:String = _currentUrl; if (_pseudoStreamingEnabled) { if (url.indexOf('?') > -1) { url = url + '&' + _pseudoStreamingStartQueryParam + '=' + pos; } else { url = url + '?' + _pseudoStreamingStartQueryParam + '=' + pos; } } return url; } } } \ No newline at end of file
diff --git a/files_videoviewer/src/flash/htmlelements/YouTubeElement.as b/files_videoviewer/src/flash/htmlelements/YouTubeElement.as
new file mode 100644
index 000000000..80986fa62
--- /dev/null
+++ b/files_videoviewer/src/flash/htmlelements/YouTubeElement.as
@@ -0,0 +1,403 @@
+package htmlelements
+{
+ import flash.display.Sprite;
+ import flash.events.*;
+ import flash.net.NetConnection;
+ import flash.net.NetStream;
+ import flash.media.Video;
+ import flash.media.SoundTransform;
+ import flash.utils.Timer;
+ import flash.net.URLLoader;
+ import flash.net.URLRequest;
+ import flash.net.URLVariables;
+ import flash.net.URLRequestMethod;
+ import flash.display.MovieClip;
+ import flash.display.Loader;
+ import flash.display.DisplayObject;
+
+
+
+ import FlashMediaElement;
+ import HtmlMediaEvent;
+
+ public class YouTubeElement extends Sprite implements IMediaElement
+ {
+ private var _currentUrl:String = "";
+ private var _autoplay:Boolean = true;
+ private var _preload:String = "";
+
+ private var _element:FlashMediaElement;
+
+ // event values
+ private var _currentTime:Number = 0;
+ private var _duration:Number = 0;
+ private var _framerate:Number;
+ private var _isPaused:Boolean = true;
+ private var _isEnded:Boolean = false;
+ private var _volume:Number = 1;
+ private var _isMuted:Boolean = false;
+
+ private var _bytesLoaded:Number = 0;
+ private var _bytesTotal:Number = 0;
+ private var _bufferedTime:Number = 0;
+ private var _bufferEmpty:Boolean = false;
+
+ private var _videoWidth:Number = -1;
+ private var _videoHeight:Number = -1;
+
+ private var _timer:Timer;
+
+ // YouTube stuff
+ private var _playerLoader:Loader;
+ private var _player:Object = null;
+ private var _playerIsLoaded:Boolean = false;
+ private var _youTubeId:String = "";
+
+ //http://code.google.com/p/gdata-samples/source/browse/trunk/ytplayer/actionscript3/com/google/youtube/examples/AS3Player.as
+ private static const WIDESCREEN_ASPECT_RATIO:String = "widescreen";
+ private static const QUALITY_TO_PLAYER_WIDTH:Object = {
+ small: 320,
+ medium: 640,
+ large: 854,
+ hd720: 1280
+ };
+ private static const STATE_ENDED:Number = 0;
+ private static const STATE_PLAYING:Number = 1;
+ private static const STATE_PAUSED:Number = 2;
+ private static const STATE_CUED:Number = 5;
+
+
+ public function get player():DisplayObject {
+ return _player;
+ }
+
+ public function setSize(width:Number, height:Number):void {
+ if (_player != null) {
+ _player.setSize(width, height);
+ } else {
+ initHeight = height;
+ initWidth = width;
+ }
+ }
+
+ public function get videoHeight():Number {
+ return _videoHeight;
+ }
+
+ public function get videoWidth():Number {
+ return _videoWidth;
+ }
+
+
+ public function duration():Number {
+ return _duration;
+ }
+
+ public function currentProgress():Number {
+ if(_bytesTotal> 0) {
+ return Math.round(_bytesLoaded/_bytesTotal*100);
+ } else {
+ return 0;
+ }
+ }
+
+ public function currentTime():Number {
+ return _currentTime;
+ }
+
+
+ public var initHeight:Number;
+ public var initWidth:Number;
+
+ // (1) load()
+ // calls _connection.connect();
+ // waits for NetConnection.Connect.Success
+ // _stream gets created
+
+ private var _isChromeless:Boolean = false;
+
+
+ public function YouTubeElement(element:FlashMediaElement, autoplay:Boolean, preload:String, timerRate:Number, startVolume:Number)
+ {
+ _element = element;
+ _autoplay = autoplay;
+ _volume = startVolume;
+ _preload = preload;
+ initHeight = 0;
+ initWidth = 0;
+
+ _playerLoader = new Loader();
+ _playerLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, playerLoaderInitHandler);
+
+ // chromeless
+ if (_isChromeless) {
+ _playerLoader.load(new URLRequest("//www.youtube.com/apiplayer?version=3&controls=1&rel=0&showinfo=0&iv_load_policy=1"));
+ }
+
+
+ _timer = new Timer(timerRate);
+ _timer.addEventListener("timer", timerHandler);
+ _timer.start();
+ }
+
+ private function playerLoaderInitHandler(event:Event):void {
+
+ trace("yt player init");
+
+ _element.addChild(_playerLoader.content);
+ _element.setControlDepth();
+ _playerLoader.content.addEventListener("onReady", onPlayerReady);
+ _playerLoader.content.addEventListener("onError", onPlayerError);
+ _playerLoader.content.addEventListener("onStateChange", onPlayerStateChange);
+ _playerLoader.content.addEventListener("onPlaybackQualityChange", onVideoPlaybackQualityChange);
+ }
+
+ private function onPlayerReady(event:Event):void {
+ _playerIsLoaded = true;
+
+ _player = _playerLoader.content;
+
+ if (initHeight > 0 && initWidth > 0)
+ _player.setSize(initWidth, initHeight);
+
+ if (_youTubeId != "") { // && _isChromeless) {
+ if (_autoplay) {
+ player.loadVideoById(_youTubeId);
+ } else {
+ player.cueVideoById(_youTubeId);
+ }
+ _timer.start();
+ }
+ }
+
+ private function onPlayerError(event:Event):void {
+ // trace("Player error:", Object(event).data);
+ }
+
+ private function onPlayerStateChange(event:Event):void {
+ trace("State is", Object(event).data);
+
+ _duration = _player.getDuration();
+
+ switch (Object(event).data) {
+ case STATE_ENDED:
+ _isEnded = true;
+ _isPaused = false;
+
+ sendEvent(HtmlMediaEvent.ENDED);
+
+ break;
+
+ case STATE_PLAYING:
+ _isEnded = false;
+ _isPaused = false;
+
+ sendEvent(HtmlMediaEvent.PLAY);
+ sendEvent(HtmlMediaEvent.PLAYING);
+ break;
+
+ case STATE_PAUSED:
+ _isEnded = false;
+ _isPaused = true;
+
+ sendEvent(HtmlMediaEvent.PAUSE);
+
+ break;
+
+ case STATE_CUED:
+ sendEvent(HtmlMediaEvent.CANPLAY);
+
+ // resize?
+
+ break;
+ }
+ }
+
+ private function onVideoPlaybackQualityChange(event:Event):void {
+ trace("Current video quality:", Object(event).data);
+ //resizePlayer(Object(event).data);
+ }
+
+ private function timerHandler(e:TimerEvent) {
+
+ if (_playerIsLoaded) {
+ _bytesLoaded = _player.getVideoBytesLoaded();
+ _bytesTotal = _player.getVideoBytesTotal();
+ _currentTime = player.getCurrentTime();
+
+ if (!_isPaused)
+ sendEvent(HtmlMediaEvent.TIMEUPDATE);
+
+ if (_bytesLoaded < _bytesTotal)
+ sendEvent(HtmlMediaEvent.PROGRESS);
+ }
+
+ }
+
+ private function getYouTubeId(url:String):String {
+ // http://www.youtube.com/watch?feature=player_embedded&v=yyWWXSwtPP0
+ // http://www.youtube.com/v/VIDEO_ID?version=3
+ // http://youtu.be/Djd6tPrxc08
+
+ url = unescape(url);
+
+ var youTubeId:String = "";
+
+ if (url.indexOf("?") > 0) {
+ // assuming: http://www.youtube.com/watch?feature=player_embedded&v=yyWWXSwtPP0
+ youTubeId = getYouTubeIdFromParam(url);
+
+ // if it's http://www.youtube.com/v/VIDEO_ID?version=3
+ if (youTubeId == "") {
+ youTubeId = getYouTubeIdFromUrl(url);
+ }
+ } else {
+ youTubeId = getYouTubeIdFromUrl(url);
+ }
+
+ return youTubeId;
+ }
+
+ // http://www.youtube.com/watch?feature=player_embedded&v=yyWWXSwtPP0
+ private function getYouTubeIdFromParam(url:String):String {
+
+
+ var youTubeId:String = "";
+ var parts:Array = url.split('?');
+ var parameters:Array = parts[1].split('&');
+
+ for (var i:Number=0; i<parameters.length; i++) {
+ var paramParts = parameters[i].split('=');
+ if (paramParts[0] == "v") {
+
+ youTubeId = paramParts[1];
+ break;
+ }
+
+ }
+
+
+ return youTubeId;
+ }
+
+
+ // http://www.youtube.com/v/VIDEO_ID?version=3
+ // http://youtu.be/Djd6tPrxc08
+ private function getYouTubeIdFromUrl(url:String):String {
+
+
+ var youTubeId:String = "";
+
+ // remove any querystring elements
+ var parts:Array = url.split('?');
+ url = parts[0];
+
+ youTubeId = url.substring(url.lastIndexOf("/")+1);
+
+ return youTubeId;
+ }
+
+
+ // interface members
+ public function setSrc(url:String):void {
+ trace("yt setSrc()" + url );
+
+ _currentUrl = url;
+
+ _youTubeId = getYouTubeId(url);
+
+ if (!_playerIsLoaded && !_isChromeless) {
+ _playerLoader.load(new URLRequest("//www.youtube.com/v/" + _youTubeId + "?version=3&controls=0&rel=0&showinfo=0&iv_load_policy=1"));
+ }
+ }
+
+
+
+
+ public function load():void {
+ // do nothing
+ trace("yt load()");
+
+ if (_playerIsLoaded) {
+ player.loadVideoById(_youTubeId);
+ _timer.start();
+ } else {
+ /*
+ if (!_isChromless && _youTubeId != "") {
+ _playerLoader.load(new URLRequest("http://www.youtube.com/v/" + _youTubeId + "?version=3&controls=0&rel=0&showinfo=0&iv_load_policy=1"));
+ }
+ */
+ }
+ }
+
+ public function play():void {
+ if (_playerIsLoaded) {
+ _player.playVideo();
+ }
+
+ }
+
+ public function pause():void {
+ if (_playerIsLoaded) {
+ _player.pauseVideo();
+ }
+ }
+
+ public function stop():void {
+ if (_playerIsLoaded) {
+ _player.pauseVideo();
+ }
+ }
+
+ public function setCurrentTime(pos:Number):void {
+ //_player.seekTo(pos, false);
+ _player.seekTo(pos, true); // works in all places now
+ }
+
+ public function setVolume(volume:Number):void {
+ _player.setVolume(volume*100);
+ _volume = volume;
+ }
+
+ public function getVolume():Number {
+ return _player.getVolume()*100;
+ }
+
+ public function setMuted(muted:Boolean):void {
+ if (muted) {
+ _player.mute();
+
+ } else {
+ _player.unMute();
+ }
+ _isMuted = _player.isMuted();
+ sendEvent(HtmlMediaEvent.VOLUMECHANGE);
+ }
+
+
+ private function sendEvent(eventName:String) {
+
+ // calculate this to mimic HTML5
+ _bufferedTime = _bytesLoaded / _bytesTotal * _duration;
+
+ // build JSON
+ var values:String =
+ "duration:" + _duration +
+ ",framerate:" + _framerate +
+ ",currentTime:" + _currentTime +
+ ",muted:" + _isMuted +
+ ",paused:" + _isPaused +
+ ",ended:" + _isEnded +
+ ",volume:" + _volume +
+ ",src:\"" + _currentUrl + "\"" +
+ ",bytesTotal:" + _bytesTotal +
+ ",bufferedBytes:" + _bytesLoaded +
+ ",bufferedTime:" + _bufferedTime +
+ ",videoWidth:" + _videoWidth +
+ ",videoHeight:" + _videoHeight +
+ "";
+
+ _element.sendEvent(eventName, values);
+ }
+ }
+}
diff --git a/files_videoviewer/src/silverlight/App.xaml b/files_videoviewer/src/silverlight/App.xaml
new file mode 100644
index 000000000..47cf6fb13
--- /dev/null
+++ b/files_videoviewer/src/silverlight/App.xaml
@@ -0,0 +1,8 @@
+<Application xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ x:Class="SilverlightMediaElement.App"
+ >
+ <Application.Resources>
+
+ </Application.Resources>
+</Application>
diff --git a/files_videoviewer/src/silverlight/App.xaml.cs b/files_videoviewer/src/silverlight/App.xaml.cs
new file mode 100644
index 000000000..be67bfbf7
--- /dev/null
+++ b/files_videoviewer/src/silverlight/App.xaml.cs
@@ -0,0 +1,68 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Animation;
+using System.Windows.Shapes;
+
+namespace SilverlightMediaElement
+{
+ public partial class App : Application
+ {
+
+ public App()
+ {
+ this.Startup += this.Application_Startup;
+ this.Exit += this.Application_Exit;
+ this.UnhandledException += this.Application_UnhandledException;
+
+ InitializeComponent();
+ }
+
+ private void Application_Startup(object sender, StartupEventArgs e)
+ {
+ this.RootVisual = new MainPage(e.InitParams);
+ }
+
+ private void Application_Exit(object sender, EventArgs e)
+ {
+
+ }
+
+ private void Application_UnhandledException(object sender, ApplicationUnhandledExceptionEventArgs e)
+ {
+ // If the app is running outside of the debugger then report the exception using
+ // the browser's exception mechanism. On IE this will display it a yellow alert
+ // icon in the status bar and Firefox will display a script error.
+ if (!System.Diagnostics.Debugger.IsAttached)
+ {
+
+ // NOTE: This will allow the application to continue running after an exception has been thrown
+ // but not handled.
+ // For production applications this error handling should be replaced with something that will
+ // report the error to the website and stop the application.
+ e.Handled = true;
+ Deployment.Current.Dispatcher.BeginInvoke(delegate { ReportErrorToDOM(e); });
+ }
+ }
+
+ private void ReportErrorToDOM(ApplicationUnhandledExceptionEventArgs e)
+ {
+ try
+ {
+ string errorMsg = e.ExceptionObject.Message + e.ExceptionObject.StackTrace;
+ errorMsg = errorMsg.Replace('"', '\'').Replace("\r\n", @"\n");
+
+ System.Windows.Browser.HtmlPage.Window.Eval("throw new Error(\"Unhandled Error in Silverlight Application " + errorMsg + "\");");
+ }
+ catch (Exception)
+ {
+ }
+ }
+ }
+}
diff --git a/files_videoviewer/src/silverlight/MainPage.xaml b/files_videoviewer/src/silverlight/MainPage.xaml
new file mode 100644
index 000000000..54af028fe
--- /dev/null
+++ b/files_videoviewer/src/silverlight/MainPage.xaml
@@ -0,0 +1,276 @@
+
+<UserControl
+ x:Class="SilverlightMediaElement.MainPage"
+ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+ xmlns:vsm="clr-namespace:System.Windows;assembly=System.Windows"
+ mc:Ignorable="d"
+ Width="640" Height="360">
+ <UserControl.Resources>
+ <Style x:Key="roundThumbStyle" TargetType="Thumb">
+ <Setter Property="Template">
+ <Setter.Value>
+ <ControlTemplate TargetType="Thumb">
+ <Ellipse Stroke="#FFFFFFFF" StrokeThickness="2" Fill="#FF484848"/>
+ </ControlTemplate>
+ </Setter.Value>
+ </Setter>
+ </Style>
+
+ <Style x:Key="SliderStyle" TargetType="Slider">
+ <Setter Property="Template">
+ <Setter.Value>
+ <ControlTemplate TargetType="Slider">
+ <Grid x:Name="Root" Background="Transparent">
+ <Grid.Resources>
+ <ControlTemplate x:Key="RightRepeatButtonTemplate">
+ <Rectangle Height="8" Margin="-5,0,0,0" Grid.Column="0" Grid.ColumnSpan="3"
+ StrokeThickness="0.5" RadiusY="1" RadiusX="1" Fill="#FF484848"/>
+ </ControlTemplate>
+ <ControlTemplate x:Key="LeftRepeatButtonTemplate">
+ <Rectangle Height="8" Margin="0,0,-5,0" Grid.Column="0" Grid.ColumnSpan="3"
+ StrokeThickness="0.5" RadiusY="1" RadiusX="1" Fill="#FFAFAFAF"/>
+ </ControlTemplate>
+ </Grid.Resources>
+ <Grid x:Name="HorizontalTemplate">
+ <Grid.ColumnDefinitions>
+ <ColumnDefinition Width="Auto"/>
+ <ColumnDefinition Width="Auto"/>
+ <ColumnDefinition Width="*"/>
+ </Grid.ColumnDefinitions>
+
+ <RepeatButton x:Name="HorizontalTrackLargeChangeDecreaseRepeatButton" Grid.Column="0"
+ IsTabStop="False" Template="{StaticResource LeftRepeatButtonTemplate}"/>
+ <Rectangle x:Name="LeftTrack" Grid.Row="1" Fill="#00FFFFFF" Cursor="Hand" MouseLeftButtonDown="LeftTrack_MouseLeftButtonDown"/>
+ <Thumb Background="#00FFFFFF" Height="10" x:Name="HorizontalThumb" Width="10"
+ Grid.Column="1" Style="{StaticResource roundThumbStyle}" HorizontalAlignment="Left"
+ DragStarted="HorizontalThumb_DragStarted" DragCompleted="HorizontalThumb_DragCompleted"
+ Canvas.ZIndex="1"/>
+ <RepeatButton x:Name="HorizontalTrackLargeChangeIncreaseRepeatButton" Grid.Column="2"
+ IsTabStop="False" Template="{StaticResource RightRepeatButtonTemplate}"/>
+ <Rectangle x:Name="RightTrack" Grid.Column="2" Grid.Row="1" Fill="#00FFFFFF" Cursor="Hand" MouseLeftButtonDown="LeftTrack_MouseLeftButtonDown"/>
+ </Grid>
+ </Grid>
+ </ControlTemplate>
+ </Setter.Value>
+ </Setter>
+ </Style>
+
+ <ControlTemplate x:Key="PlayButtonTemplate" TargetType="ToggleButton">
+ <Grid x:Name="grid" Background="Transparent">
+ <vsm:VisualStateManager.VisualStateGroups>
+ <vsm:VisualStateGroup x:Name="FocusStates">
+ <vsm:VisualState x:Name="Focused">
+ <Storyboard>
+ </Storyboard>
+ </vsm:VisualState>
+ <vsm:VisualState x:Name="Unfocused">
+ <Storyboard/>
+ </vsm:VisualState>
+ </vsm:VisualStateGroup>
+ <vsm:VisualStateGroup x:Name="CommonStates">
+ <vsm:VisualState x:Name="Normal">
+ <Storyboard/>
+ </vsm:VisualState>
+ <vsm:VisualState x:Name="MouseOver">
+ <Storyboard>
+ </Storyboard>
+ </vsm:VisualState>
+ <vsm:VisualState x:Name="Pressed">
+ <Storyboard/>
+ </vsm:VisualState>
+ </vsm:VisualStateGroup>
+ <vsm:VisualStateGroup x:Name="CheckStates">
+ <vsm:VisualState x:Name="Checked">
+ <Storyboard>
+ <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000"
+ Storyboard.TargetName="playSymbol"
+ Storyboard.TargetProperty="(UIElement.Opacity)">
+ <SplineDoubleKeyFrame KeyTime="00:00:00" Value="0"/>
+ </DoubleAnimationUsingKeyFrames>
+ <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000"
+ Storyboard.TargetName="pauseSymbol"
+ Storyboard.TargetProperty="(UIElement.Opacity)">
+ <SplineDoubleKeyFrame KeyTime="00:00:00" Value="1"/>
+ </DoubleAnimationUsingKeyFrames>
+ </Storyboard>
+ </vsm:VisualState>
+ <vsm:VisualState x:Name="Unchecked">
+ <Storyboard>
+ <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000" Storyboard.TargetName="pauseSymbol" Storyboard.TargetProperty="(UIElement.Opacity)">
+ <SplineDoubleKeyFrame KeyTime="00:00:00" Value="0"/>
+ </DoubleAnimationUsingKeyFrames>
+ </Storyboard>
+ </vsm:VisualState>
+ </vsm:VisualStateGroup>
+ </vsm:VisualStateManager.VisualStateGroups>
+ <Grid Margin="11,3,0,0" HorizontalAlignment="Left" VerticalAlignment="Center"
+ Opacity="1" x:Name="playSymbol" Width="21" Height="22">
+ <Path Width="14" Height="15" Stretch="Fill" Fill="#FF7F7F7F"
+ Data="F1 M 15.1997,22.542L 29.7776,14.89L 15.2707,6.99886L 15.1997,22.542 Z "/>
+ </Grid>
+ <Grid Margin="11,2,0,0" Opacity="0" x:Name="pauseSymbol" Width="31" Height="15">
+ <Rectangle Stretch="Fill" Fill="#FF7F7F7F" HorizontalAlignment="Left"
+ Margin="0,0,0,0" Width="6"/>
+ <Rectangle Stretch="Fill" Fill="#FF7F7F7F" HorizontalAlignment="Stretch"
+ Margin="6,0,13,0" Width="6"/>
+ </Grid>
+ </Grid>
+ </ControlTemplate>
+
+ <ControlTemplate x:Key="MuteButtonTemplate" TargetType="ToggleButton">
+ <Grid Background="Transparent" Cursor="Hand">
+ <vsm:VisualStateManager.VisualStateGroups>
+ <vsm:VisualStateGroup x:Name="FocusStates">
+ <vsm:VisualState x:Name="Focused">
+ <Storyboard>
+ </Storyboard>
+ </vsm:VisualState>
+ <vsm:VisualState x:Name="Unfocused">
+ <Storyboard/>
+ </vsm:VisualState>
+ </vsm:VisualStateGroup>
+ <vsm:VisualStateGroup x:Name="CommonStates">
+ <vsm:VisualState x:Name="Normal">
+ <Storyboard/>
+ </vsm:VisualState>
+ <vsm:VisualState x:Name="MouseOver">
+ <Storyboard>
+ </Storyboard>
+ </vsm:VisualState>
+ <vsm:VisualState x:Name="Pressed">
+ <Storyboard/>
+ </vsm:VisualState>
+ </vsm:VisualStateGroup>
+ <vsm:VisualStateGroup x:Name="CheckStates">
+ <vsm:VisualState x:Name="Checked">
+ <Storyboard>
+ <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000"
+ Storyboard.TargetName="volumeSymbol"
+ Storyboard.TargetProperty="(UIElement.Opacity)">
+ <SplineDoubleKeyFrame KeyTime="00:00:00" Value="0"/>
+ </DoubleAnimationUsingKeyFrames>
+ </Storyboard>
+ </vsm:VisualState>
+ <vsm:VisualState x:Name="Unchecked">
+ <Storyboard>
+ <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000"
+ Storyboard.TargetName="volumeSymbol"
+ Storyboard.TargetProperty="(UIElement.Opacity)">
+ <SplineDoubleKeyFrame KeyTime="00:00:00" Value="1"/>
+ </DoubleAnimationUsingKeyFrames>
+ </Storyboard>
+ </vsm:VisualState>
+ </vsm:VisualStateGroup>
+ </vsm:VisualStateManager.VisualStateGroups>
+ <Grid HorizontalAlignment="Left" VerticalAlignment="Top"
+ Width="17">
+ <Path HorizontalAlignment="Left" Stretch="Fill"
+ Fill="#FF7F7F7F" Data="F1 M 23.1457,26.5056L 23.1457,33.8944L 25.7913,33.8944L 28.8235,37.4722L 30.5346,37.4722L 30.5665,23.0833L 28.8995,23.0833L 25.8679,26.5056L 23.1457,26.5056 Z "
+ Width="7.421" Height="14.389" UseLayoutRounding="False"
+ Margin="0,6.5,0,6.5"/>
+
+ <Grid HorizontalAlignment="Right" Width="7.003" x:Name="volumeSymbol" Margin="0,10">
+ <Path HorizontalAlignment="Right" VerticalAlignment="Stretch"
+ Width="2.398"
+ Data="M0.5,0.5 C0.5,0.5 2.5939558,2.7128265 2.5946648,7.0504856 C2.5953746,11.391507 0.50033337,13.889001 0.50033337,13.889001"
+ Stretch="Fill" Stroke="#FF7F7F7F" Margin="0,0,-0.398,0" UseLayoutRounding="False"/>
+ <Path HorizontalAlignment="Stretch" Margin="2.4,2.384,2.317,1.584" VerticalAlignment="Stretch"
+ Data="M0.5,0.50000006 C0.5,0.50000006 1.4786903,2.1275051 1.4781417,4.9569001 C1.4776551,7.4670725 0.35717732,9.892808 0.35717732,9.892808" Stretch="Fill" Stroke="#FF7F7F7F" UseLayoutRounding="False"/>
+ <Path HorizontalAlignment="Left" Margin="0,4.36,0,3.46" VerticalAlignment="Stretch" Width="1.542"
+ Data="M0.5,0.5 C0.5,0.5 1.0412779,1.4903735 1.042276,3.1459465 C1.0429831,4.3189368 0.66544437,6.0685911 0.66544437,6.0685911" Stretch="Fill" Stroke="#FF7F7F7F" d:LayoutOverrides="Width"/>
+ </Grid>
+ </Grid>
+ </Grid>
+ </ControlTemplate>
+
+ <ControlTemplate x:Key="ButtonTemplate" TargetType="Button">
+ <Grid Background="Transparent">
+ <ContentPresenter Width="Auto"/>
+ </Grid>
+ </ControlTemplate>
+ </UserControl.Resources>
+
+ <Grid x:Name="LayoutRoot" Background="Black" Width="640" Height="360">
+
+ <MediaElement Grid.Row="0" Grid.Column="0" Width="640" Height="360"
+ CacheMode="BitmapCache" AutoPlay="false" Name="media">
+
+ </MediaElement>
+ <Button x:Name="bigPlayButton" Template="{StaticResource ButtonTemplate}"
+ Click="BigPlayButton_Click" Grid.Row="0" Visibility="Collapsed">
+ <Canvas Width="100" Height="100">
+ <Path Width="100" Height="100" Canvas.Left="0" Canvas.Top="0" Stretch="Fill"
+ Fill="#77000000" Data="F1 M 15,0L 85,0C 93.2843,0 100,6.71573 100,15L 100,85C 100,93.2843 93.2843,100 85,100L 15,100C 6.71573,100 0,93.2843 0,85L 0,15C 0,6.71573 6.71573,0 15,0 Z "/>
+ <Path Width="40.8182" Height="47.1328" Canvas.Left="34.6439"
+ Canvas.Top="27.6003" Stretch="Fill" Fill="#FFFFFFFF"
+ Data="F1 M 75.4621,51.1667L 34.6439,27.6003L 34.6439,74.7331L 75.4621,51.1667 Z "/>
+ </Canvas>
+ </Button>
+ <TextBox Margin="25,25,0,0" Name="textBox1" VerticalScrollBarVisibility="Auto" Height="146" VerticalAlignment="Top" HorizontalAlignment="Left" Width="235" />
+ <Button Content="" Height="36" HorizontalAlignment="Right" x:Name="FullscreenButton" VerticalAlignment="Bottom" Width="31" Click="FullscreenButton_Click" Opacity="0" Background="#00000000" Cursor="Hand" />
+
+ <Grid x:Name="transportControls" VerticalAlignment="Bottom" Height="40" Background="#FF000000"
+ Grid.Row="1" >
+ <Grid.ColumnDefinitions>
+ <ColumnDefinition Width="Auto" />
+ <ColumnDefinition Width="*" />
+ <ColumnDefinition Width="0" />
+ <ColumnDefinition Width="Auto" />
+ <ColumnDefinition Width="Auto" MinWidth="10" />
+ <ColumnDefinition Width="Auto" MinWidth="10" />
+ </Grid.ColumnDefinitions>
+
+ <!-- play symbol showing is checked = false, Pause symbol showing is checked = true-->
+ <ToggleButton x:Name="playPauseButton" Template="{StaticResource PlayButtonTemplate}"
+ Click="PlayPauseButton_Click" IsChecked="false" Cursor="Hand"/>
+
+ <Grid x:Name="time" Grid.Column="1" HorizontalAlignment="Stretch" VerticalAlignment="Center">
+ <Grid.ColumnDefinitions>
+ <ColumnDefinition Width="40" />
+ <ColumnDefinition Width="*" />
+ <ColumnDefinition Width="10" />
+ <ColumnDefinition Width="40" />
+ </Grid.ColumnDefinitions>
+
+ <TextBlock x:Name="currentTimeTextBlock" Margin="0,1.5,10,0" Height="12"
+ FontFamily="Verdana" FontSize="10" Text="00:00" TextWrapping="Wrap"
+ Foreground="#FFFFFFFF" FontStyle="Normal" HorizontalAlignment="Right"
+ TextAlignment="Right" Grid.Column="0"/>
+
+ <Slider x:Name="timelineSlider" Margin="0,2,0,-1"
+ Maximum="1" Style="{StaticResource SliderStyle}" Grid.Column="1"
+ ValueChanged="TimelineSlider_ValueChanged"
+ Value="0"/>
+
+ <TextBlock Margin="0,1.5,0,0" Height="12" FontFamily="Verdana" FontSize="10"
+ Text="" TextWrapping="Wrap" Foreground="#FFFFFFFF"
+ FontStyle="Normal" HorizontalAlignment="Center" TextAlignment="Right"
+ Grid.Column="2"/>
+ <TextBlock x:Name="totalTimeTextBlock" Margin="0,1.5,0,0" Height="12"
+ FontFamily="Verdana" FontSize="10" Text="00:00" TextWrapping="Wrap"
+ Foreground="#FFFFFFFF" FontStyle="Normal" HorizontalAlignment="Left"
+ TextAlignment="Right" Grid.Column="3"/>
+ </Grid>
+
+ <ToggleButton IsChecked="false" Grid.Column="3" x:Name="muteButton"
+ Template="{StaticResource MuteButtonTemplate}" Click="MuteButton_Click"
+ VerticalAlignment="Center" Margin="0,0,6,0" Cursor="Hand"/>
+
+ <Slider Grid.Column="4" HorizontalAlignment="Stretch" Margin="3,0,0,0"
+ VerticalAlignment="Center" Maximum="1" x:Name="volumeSlider"
+ Background="#FF777777" Style="{StaticResource SliderStyle}" Width="50"
+ Value="{Binding ElementName=media, Mode=TwoWay, Path=Volume, UpdateSourceTrigger=Default}"/>
+
+ <Button x:Name="fullScreenButton" Grid.Column="5" Margin="8,10,4,10" Click="FullScreenButton_Click"
+ Template="{StaticResource ButtonTemplate}" VerticalAlignment="Center" Cursor="Hand">
+ <Path Height="14.375" HorizontalAlignment="Stretch"
+ VerticalAlignment="Bottom" RenderTransformOrigin="0.212389379739761,0.208695650100708"
+ Data="M10.181361,8.375 L12.844413,11.008244 L14.125,9.7418737 L14.125,14.375 L9.675765,14.374833 L10.906104,13.158273 L8.125,10.408315 L10.181361,8.375 z M3.9666855,8.375 L6,10.431361 L3.3667567,13.094413 L4.6331258,14.375 L0,14.375 L0.00016707927,9.925765 L1.2167276,11.156104 L3.9666855,8.375 z M9.4918737,0 L14.125,0 L14.124833,4.449235 L12.908273,3.2188957 L10.158315,6 L8.125,3.943639 L10.758244,1.2805867 L9.4918737,0 z M0,0 L4.449235,0.00016686507 L3.2188957,1.2167276 L6,3.9666855 L3.943639,6 L1.280587,3.3667567 L0,4.6331258 L0,0 z"
+ Fill="#FF7F7F7F" Stretch="Fill" Stroke="#FF000000" StrokeThickness="0" />
+ </Button>
+ </Grid>
+ </Grid>
+</UserControl> \ No newline at end of file
diff --git a/files_videoviewer/src/silverlight/MainPage.xaml.cs b/files_videoviewer/src/silverlight/MainPage.xaml.cs
new file mode 100644
index 000000000..5f5da703f
--- /dev/null
+++ b/files_videoviewer/src/silverlight/MainPage.xaml.cs
@@ -0,0 +1,636 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Animation;
+using System.Windows.Shapes;
+using System.Windows.Browser;
+using System.Globalization;
+
+
+namespace SilverlightMediaElement
+{
+ [ScriptableType]
+ public partial class MainPage : UserControl
+ {
+ System.Windows.Threading.DispatcherTimer _timer;
+
+ // work arounds for src, load(), play() compatibility
+ bool _isLoading = false;
+ bool _isAttemptingToPlay = false;
+
+ // variables
+ string _mediaUrl;
+ string _preload;
+ string _htmlid;
+ bool _autoplay = false;
+ bool _debug = false;
+ int _width = 0;
+ int _height = 0;
+ int _timerRate = 0;
+ double _bufferedBytes = 0;
+ double _bufferedTime = 0;
+ double _volume = 1;
+ int _videoWidth = 0;
+ int _videoHeight = 0;
+
+ // state
+ bool _isPaused = true;
+ bool _isEnded = false;
+
+ // dummy
+ bool _firedCanPlay = false;
+
+ // mediaElement.Position updates TimelineSlider.Value, and
+ // updating TimelineSlider.Value updates mediaElement.Position,
+ // this variable helps us break the infinite loop
+ private bool duringTickEvent = false;
+
+ private bool playVideoWhenSliderDragIsOver = false;
+
+ public MainPage(IDictionary<string, string> initParams)
+ {
+ InitializeComponent();
+
+ HtmlPage.RegisterScriptableObject("MediaElementJS", this);
+
+
+ // add events
+ media.BufferingProgressChanged += new RoutedEventHandler(media_BufferingProgressChanged);
+ media.DownloadProgressChanged += new RoutedEventHandler(media_DownloadProgressChanged);
+ media.CurrentStateChanged += new RoutedEventHandler(media_CurrentStateChanged);
+ media.MediaEnded += new RoutedEventHandler(media_MediaEnded);
+ media.MediaFailed += new EventHandler<ExceptionRoutedEventArgs>(media_MediaFailed);
+ media.MediaOpened += new RoutedEventHandler(media_MediaOpened);
+ media.MouseLeftButtonDown += new MouseButtonEventHandler(media_MouseLeftButtonDown);
+ CompositionTarget.Rendering += new EventHandler(CompositionTarget_Rendering);
+ transportControls.Visibility = System.Windows.Visibility.Collapsed;
+
+ // get parameters
+ if (initParams.ContainsKey("id"))
+ _htmlid = initParams["id"];
+ if (initParams.ContainsKey("file"))
+ _mediaUrl = initParams["file"];
+ if (initParams.ContainsKey("autoplay") && initParams["autoplay"] == "true")
+ _autoplay = true;
+ if (initParams.ContainsKey("debug") && initParams["debug"] == "true")
+ _debug = true;
+ if (initParams.ContainsKey("preload"))
+ _preload = initParams["preload"].ToLower();
+ else
+ _preload = "";
+
+ if (!(new string[] { "none", "metadata", "auto" }).Contains(_preload)){
+ _preload = "none";
+ }
+
+ if (initParams.ContainsKey("width"))
+ Int32.TryParse(initParams["width"], out _width);
+ if (initParams.ContainsKey("height"))
+ Int32.TryParse(initParams["height"], out _height);
+ if (initParams.ContainsKey("timerate"))
+ Int32.TryParse(initParams["timerrate"], out _timerRate);
+ if (initParams.ContainsKey("startvolume"))
+ Double.TryParse(initParams["startvolume"], out _volume);
+
+ if (_timerRate == 0)
+ _timerRate = 250;
+
+ // timer
+ _timer = new System.Windows.Threading.DispatcherTimer();
+ _timer.Interval = new TimeSpan(0, 0, 0, 0, _timerRate); // 200 Milliseconds
+ _timer.Tick += new EventHandler(timer_Tick);
+ _timer.Stop();
+
+ //_mediaUrl = "http://local.mediaelement.com/media/jsaddington.mp4";
+ //_autoplay = true;
+
+ // set stage and media sizes
+ if (_width > 0)
+ LayoutRoot.Width = media.Width = this.Width = _width;
+ if (_height > 0)
+ LayoutRoot.Height = media.Height = this.Height = _height;
+
+ // debug
+ textBox1.Visibility = (_debug) ? System.Windows.Visibility.Visible : System.Windows.Visibility.Collapsed;
+ textBox1.IsEnabled = false;
+ textBox1.Text = "id: " + _htmlid + "\n" +
+ "file: " + _mediaUrl + "\n";
+
+
+ media.AutoPlay = _autoplay;
+ media.Volume = _volume;
+ if (!String.IsNullOrEmpty(_mediaUrl)) {
+ setSrc(_mediaUrl);
+ if (_autoplay || _preload != "none")
+ loadMedia();
+ }
+
+ media.MouseLeftButtonUp += new MouseButtonEventHandler(media_MouseLeftButtonUp);
+
+ // full screen settings
+ Application.Current.Host.Content.FullScreenChanged += new EventHandler(DisplaySizeInformation);
+ Application.Current.Host.Content.Resized += new EventHandler(DisplaySizeInformation);
+ //FullscreenButton.Visibility = System.Windows.Visibility.Collapsed;
+
+ // send out init call
+ //HtmlPage.Window.Invoke("html5_MediaPluginBridge_initPlugin", new object[] {_htmlid});
+ try
+ {
+ HtmlPage.Window.Eval("mejs.MediaPluginBridge.initPlugin('" + _htmlid + "');");
+ }
+ catch { }
+ }
+
+ void media_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
+ {
+ switch (media.CurrentState)
+ {
+ case MediaElementState.Playing:
+ pauseMedia();
+ break;
+
+ case MediaElementState.Paused:
+ playMedia();
+ break;
+ case MediaElementState.Stopped:
+
+ break;
+ case MediaElementState.Buffering:
+ pauseMedia();
+ break;
+ }
+ }
+
+ void media_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) {
+ SendEvent("click");
+ }
+
+ void media_MediaOpened(object sender, RoutedEventArgs e) {
+
+ _videoWidth = Convert.ToInt32(media.NaturalVideoWidth);
+ _videoHeight = Convert.ToInt32(media.NaturalVideoHeight);
+
+ TimeSpan duration = media.NaturalDuration.TimeSpan;
+ totalTimeTextBlock.Text = TimeSpanToString(duration);
+ UpdateVideoSize();
+
+ playPauseButton.IsChecked = true;
+
+ SendEvent("loadedmetadata");
+ }
+
+ void timer_Tick(object sender, EventArgs e) {
+ SendEvent("timeupdate");
+ }
+
+ void StartTimer() {
+ _timer.Start();
+ }
+
+ void StopTimer() {
+ _timer.Stop();
+ }
+
+ void WriteDebug(string text) {
+ textBox1.Text += text + "\n";
+ }
+
+ void media_MediaFailed(object sender, ExceptionRoutedEventArgs e) {
+ SendEvent(e.ToString());
+ }
+
+ void media_MediaEnded(object sender, RoutedEventArgs e) {
+ _isEnded = true;
+ _isPaused = false;
+ SendEvent("ended");
+ StopTimer();
+ }
+
+ void media_CurrentStateChanged(object sender, RoutedEventArgs e) {
+
+ WriteDebug("state:" + media.CurrentState.ToString());
+
+ switch (media.CurrentState)
+ {
+ case MediaElementState.Opening:
+ SendEvent("loadstart");
+ break;
+ case MediaElementState.Playing:
+ _isEnded = false;
+ _isPaused = false;
+ _isAttemptingToPlay = false;
+ StartTimer();
+
+
+ SendEvent("play");
+ SendEvent("playing");
+ break;
+
+ case MediaElementState.Paused:
+ _isEnded = false;
+ _isPaused = true;
+
+ // special settings to allow play() to work
+ _isLoading = false;
+ WriteDebug("paused event, " + _isAttemptingToPlay);
+ if (_isAttemptingToPlay) {
+ this.playMedia();
+ }
+
+ StopTimer();
+ SendEvent("paused");
+ break;
+ case MediaElementState.Stopped:
+ _isEnded = false;
+ _isPaused = true;
+ StopTimer();
+ SendEvent("paused");
+ break;
+ case MediaElementState.Buffering:
+ SendEvent("progress");
+ break;
+ }
+
+ }
+
+ void media_BufferingProgressChanged(object sender, RoutedEventArgs e) {
+ _bufferedTime = media.DownloadProgress * media.NaturalDuration.TimeSpan.TotalSeconds;
+ _bufferedBytes = media.BufferingProgress;
+
+
+ SendEvent("progress");
+ }
+
+ void media_DownloadProgressChanged(object sender, RoutedEventArgs e) {
+ _bufferedTime = media.DownloadProgress * media.NaturalDuration.TimeSpan.TotalSeconds;
+ _bufferedBytes = media.BufferingProgress;
+
+ if (!_firedCanPlay) {
+ SendEvent("loadeddata");
+ SendEvent("canplay");
+ _firedCanPlay = true;
+ }
+
+ SendEvent("progress");
+ }
+
+
+ void SendEvent(string name) {
+ /*
+ * INVOKE
+ HtmlPage.Window.Invoke("html5_MediaPluginBridge_fireEvent",
+ _htmlid,
+ name,
+ @"'{" +
+ @"""name"": """ + name + @"""" +
+ @", ""currentTime"":" + (media.Position.TotalSeconds).ToString() + @"" +
+ @", ""duration"":" + (media.NaturalDuration.TimeSpan.TotalSeconds).ToString() + @"" +
+ @", ""paused"":" + (_isEnded).ToString().ToLower() + @"" +
+ @", ""muted"":" + (media.IsMuted).ToString().ToLower() + @"" +
+ @", ""ended"":" + (_isPaused).ToString().ToLower() + @"" +
+ @", ""volume"":" + (media.Volume).ToString() + @"" +
+ @", ""bufferedBytes"":" + (_bufferedBytes).ToString() + @"" +
+ @", ""bufferedTime"":" + (_bufferedTime).ToString() + @"" +
+ @"}'");
+ */
+
+ /*
+ * EVAL
+ HtmlPage.Window.Eval("mejs.MediaPluginBridge.fireEvent('" + _htmlid + "','" + name + "'," +
+ @"{" +
+ @"""name"": """ + name + @"""" +
+ @", ""currentTime"":" + (media.Position.TotalSeconds).ToString() + @"" +
+ @", ""duration"":" + (media.NaturalDuration.TimeSpan.TotalSeconds).ToString() + @"" +
+ @", ""paused"":" + (_isEnded).ToString().ToLower() + @"" +
+ @", ""muted"":" + (media.IsMuted).ToString().ToLower() + @"" +
+ @", ""ended"":" + (_isPaused).ToString().ToLower() + @"" +
+ @", ""volume"":" + (media.Volume).ToString() + @"" +
+ @", ""bufferedBytes"":" + (_bufferedBytes).ToString() + @"" +
+ @", ""bufferedTime"":" + (_bufferedTime).ToString() + @"" +
+ @"});");
+ * */
+
+ // setTimeout
+ try {
+ CultureInfo invCulture = CultureInfo.InvariantCulture;
+
+ HtmlPage.Window.Invoke("setTimeout", "mejs.MediaPluginBridge.fireEvent('" + _htmlid + "','" + name + "'," +
+ @"{" +
+ @"""name"": """ + name + @"""" +
+ @", ""currentTime"":" + (media.Position.TotalSeconds).ToString(invCulture) + @"" +
+ @", ""duration"":" + (media.NaturalDuration.TimeSpan.TotalSeconds).ToString(invCulture) + @"" +
+ @", ""paused"":" + (_isPaused).ToString().ToLower() + @"" +
+ @", ""muted"":" + (media.IsMuted).ToString().ToLower() + @"" +
+ @", ""ended"":" + (_isEnded).ToString().ToLower() + @"" +
+ @", ""volume"":" + (media.Volume).ToString(invCulture) + @"" +
+ @", ""bufferedBytes"":" + (_bufferedBytes).ToString(invCulture) + @"" +
+ @", ""bufferedTime"":" + (_bufferedTime).ToString(invCulture) + @"" +
+ @", ""videoWidth"":" + (_videoWidth).ToString() + @"" +
+ @", ""videoHeight"":" + (_videoHeight).ToString() + @"" +
+ @"});", 0);
+ } catch { }
+
+ }
+
+ /* HTML5 wrapper methods */
+ [ScriptableMember]
+ public void playMedia() {
+ WriteDebug("method:play " + media.CurrentState);
+
+ // sometimes people forget to call load() first
+ if (_mediaUrl != "" && media.Source == null) {
+ _isAttemptingToPlay = true;
+ loadMedia();
+ }
+
+ // store and trigger with the state change above
+ if (media.CurrentState == MediaElementState.Closed && _isLoading) {
+ WriteDebug("storing _isAttemptingToPlay ");
+ _isAttemptingToPlay = true;
+ }
+
+ media.Play();
+ _isEnded = false;
+ _isPaused = false;
+
+ playPauseButton.IsChecked = true;
+
+ //StartTimer();
+ }
+
+ [ScriptableMember]
+ public void pauseMedia() {
+ WriteDebug("method:pause " + media.CurrentState);
+
+ _isEnded = false;
+ _isPaused = true;
+
+ media.Pause();
+ StopTimer();
+ playPauseButton.IsChecked = false;
+ }
+
+ [ScriptableMember]
+ public void loadMedia() {
+ _isLoading = true;
+ _firedCanPlay = false;
+
+ WriteDebug("method:load " + media.CurrentState);
+ WriteDebug(" - " + _mediaUrl.ToString());
+
+ media.Source = new Uri(_mediaUrl, UriKind.Absolute);
+ //media.Play();
+ //media.Stop();
+ }
+
+ [ScriptableMember]
+ public void stopMedia() {
+ WriteDebug("method:stop " + media.CurrentState);
+
+ _isEnded = true;
+ _isPaused = false;
+
+ media.Stop();
+ StopTimer();
+ playPauseButton.IsChecked = false;
+ }
+
+ [ScriptableMember]
+ public void setVolume(Double volume) {
+ WriteDebug("method:setvolume: " + volume.ToString());
+
+ media.Volume = volume;
+
+ SendEvent("volumechange");
+ }
+
+ [ScriptableMember]
+ public void setMuted(bool isMuted) {
+ WriteDebug("method:setmuted: " + isMuted.ToString());
+
+ media.IsMuted = isMuted;
+ muteButton.IsChecked = isMuted;
+ SendEvent("volumechange");
+
+ }
+
+ [ScriptableMember]
+ public void setCurrentTime(Double position) {
+ WriteDebug("method:setCurrentTime: " + position.ToString());
+
+ int milliseconds = Convert.ToInt32(position * 1000);
+
+ SendEvent("seeking");
+ media.Position = new TimeSpan(0, 0, 0, 0, milliseconds);
+ SendEvent("seeked");
+ }
+
+ [ScriptableMember]
+ public void setSrc(string url) {
+ _mediaUrl = url;
+ }
+
+ [ScriptableMember]
+ public void setFullscreen(bool goFullscreen) {
+
+ FullscreenButton.Visibility = System.Windows.Visibility.Visible;
+ }
+
+ [ScriptableMember]
+ public void setVideoSize(int width, int height) {
+ this.Width = media.Width = width;
+ this.Height = media.Height = height;
+ }
+
+ [ScriptableMember]
+ public void positionFullscreenButton(int x, int y,bool visibleAndAbove) {
+ if (visibleAndAbove)
+ {
+ //FullscreenButton.Visibility = System.Windows.Visibility.Collapsed;
+ }
+ else
+ {
+ //FullscreenButton.Visibility = System.Windows.Visibility.Visible;
+ }
+ }
+
+ private void FullscreenButton_Click(object sender, RoutedEventArgs e) {
+ Application.Current.Host.Content.IsFullScreen = true;
+ //FullscreenButton.Visibility = System.Windows.Visibility.Collapsed;
+ }
+
+ private void DisplaySizeInformation(Object sender, EventArgs e) {
+ this.Width = LayoutRoot.Width = media.Width = Application.Current.Host.Content.ActualWidth;
+ this.Height = LayoutRoot.Height = media.Height = Application.Current.Host.Content.ActualHeight;
+
+ UpdateVideoSize();
+ }
+
+
+
+
+ #region play button
+
+ private void BigPlayButton_Click(object sender, RoutedEventArgs e)
+ {
+ playPauseButton.IsChecked = true;
+ PlayPauseButton_Click(sender, e);
+ }
+
+ private void PlayPauseButton_Click(object sender, RoutedEventArgs e)
+ {
+ bigPlayButton.Visibility = Visibility.Collapsed;
+
+ // this will be the toggle button state after the click has been processed
+ if (playPauseButton.IsChecked == true)
+ playMedia();
+ else
+ pauseMedia();
+ }
+
+
+
+ #endregion
+
+ #region timelineSlider
+
+ private void Seek(double percentComplete)
+ {
+ if (duringTickEvent)
+ throw new Exception("Can't call Seek() now, you'll get an infinite loop");
+
+ TimeSpan duration = media.NaturalDuration.TimeSpan;
+ int newPosition = (int)(duration.TotalSeconds * percentComplete);
+ media.Position = new TimeSpan(0, 0, newPosition);
+
+ // let the next CompositionTarget.Rendering take care of updating the text blocks
+ }
+
+ private Slider GetSliderParent(object sender)
+ {
+ FrameworkElement element = (FrameworkElement)sender;
+ do
+ {
+ element = (FrameworkElement)VisualTreeHelper.GetParent(element);
+ } while (!(element is Slider));
+ return (Slider)element;
+ }
+
+ private void LeftTrack_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
+ {
+ e.Handled = true;
+ FrameworkElement lefttrack = (sender as FrameworkElement).FindName("LeftTrack") as FrameworkElement;
+ FrameworkElement righttrack = (sender as FrameworkElement).FindName("RightTrack") as FrameworkElement;
+ double position = e.GetPosition(lefttrack).X;
+ double width = righttrack.TransformToVisual(lefttrack).Transform(new Point(righttrack.ActualWidth, righttrack.ActualHeight)).X;
+ double percent = position / width;
+ Slider slider = GetSliderParent(sender);
+ slider.Value = percent;
+ }
+
+ private void HorizontalThumb_DragStarted(object sender, System.Windows.Controls.Primitives.DragStartedEventArgs e)
+ {
+ if (GetSliderParent(sender) != timelineSlider) return;
+
+ bool notPlaying = (media.CurrentState == MediaElementState.Paused
+ || media.CurrentState == MediaElementState.Stopped);
+
+ if (notPlaying)
+ {
+ playVideoWhenSliderDragIsOver = false;
+ }
+ else
+ {
+ playVideoWhenSliderDragIsOver = true;
+ media.Pause();
+ }
+ }
+
+ private void HorizontalThumb_DragCompleted(object sender, System.Windows.Controls.Primitives.DragCompletedEventArgs e)
+ {
+ if (playVideoWhenSliderDragIsOver)
+ media.Play();
+ }
+
+ private void TimelineSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
+ {
+ if (duringTickEvent)
+ return;
+
+ Seek(timelineSlider.Value);
+ }
+
+ #endregion
+
+ #region updating current time
+
+ private void CompositionTarget_Rendering(object sender, EventArgs e)
+ {
+ duringTickEvent = true;
+
+ TimeSpan duration = media.NaturalDuration.TimeSpan;
+ if (duration.TotalSeconds != 0)
+ {
+ double percentComplete = (media.Position.TotalSeconds / duration.TotalSeconds);
+ timelineSlider.Value = percentComplete;
+ string text = TimeSpanToString(media.Position);
+ if (this.currentTimeTextBlock.Text != text)
+ this.currentTimeTextBlock.Text = text;
+ }
+
+ duringTickEvent = false;
+ }
+
+ private static string TimeSpanToString(TimeSpan time)
+ {
+ return string.Format("{0:00}:{1:00}", (time.Hours * 60) + time.Minutes, time.Seconds);
+ }
+ #endregion
+
+ private void MuteButton_Click(object sender, RoutedEventArgs e)
+ {
+ //media.IsMuted = (bool)muteButton.IsChecked;
+ setMuted((bool)muteButton.IsChecked);
+ }
+
+ #region fullscreen mode
+
+ private void FullScreenButton_Click(object sender, RoutedEventArgs e)
+ {
+ var content = Application.Current.Host.Content;
+ content.IsFullScreen = !content.IsFullScreen;
+ }
+
+ private void Content_FullScreenChanged(object sender, EventArgs e)
+ {
+ UpdateVideoSize();
+ }
+
+ private void UpdateVideoSize()
+ {
+ if (App.Current.Host.Content.IsFullScreen)
+ {
+ transportControls.Visibility = System.Windows.Visibility.Visible;
+ // mediaElement takes all available space
+ //VideoRow.Height = new GridLength(1, GridUnitType.Star);
+ //VideoColumn.Width = new GridLength(1, GridUnitType.Star);
+ }
+ else
+ {
+ transportControls.Visibility = System.Windows.Visibility.Collapsed;
+ // mediaElement is only as big as the source video
+ //VideoRow.Height = new GridLength(1, GridUnitType.Auto);
+ //VideoColumn.Width = new GridLength(1, GridUnitType.Auto);
+ }
+ }
+
+ #endregion
+ }
+}
+
diff --git a/files_videoviewer/src/silverlight/Properties/AppManifest.xml b/files_videoviewer/src/silverlight/Properties/AppManifest.xml
new file mode 100644
index 000000000..6712a1178
--- /dev/null
+++ b/files_videoviewer/src/silverlight/Properties/AppManifest.xml
@@ -0,0 +1,6 @@
+<Deployment xmlns="http://schemas.microsoft.com/client/2007/deployment"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+>
+ <Deployment.Parts>
+ </Deployment.Parts>
+</Deployment>
diff --git a/files_videoviewer/src/silverlight/Properties/AssemblyInfo.cs b/files_videoviewer/src/silverlight/Properties/AssemblyInfo.cs
new file mode 100644
index 000000000..8d8bbce31
--- /dev/null
+++ b/files_videoviewer/src/silverlight/Properties/AssemblyInfo.cs
@@ -0,0 +1,35 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("SilverlightMediaElement")]
+[assembly: AssemblyDescription("Silverlight player for http://mediaelementjs.com/")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("John Dyer")]
+[assembly: AssemblyProduct("SilverlightMediaElement")]
+[assembly: AssemblyCopyright("Copyright 2010 John Dyer")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("29fe7094-d10f-4359-8abb-1c76971133a4")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Revision and Build Numbers
+// by using the '*' as shown below:
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/files_videoviewer/src/silverlight/SilverlightMediaElement.csproj b/files_videoviewer/src/silverlight/SilverlightMediaElement.csproj
new file mode 100644
index 000000000..565830460
--- /dev/null
+++ b/files_videoviewer/src/silverlight/SilverlightMediaElement.csproj
@@ -0,0 +1,112 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>8.0.50727</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{CE832DD6-B659-4F3E-B49B-F297E2AC923A}</ProjectGuid>
+ <ProjectTypeGuids>{A1591282-1198-4647-A2B1-27E5FF5F6F3B};{fae04ec0-301f-11d3-bf4b-00c04f79efbc}</ProjectTypeGuids>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>SilverlightMediaElement</RootNamespace>
+ <AssemblyName>SilverlightMediaElement</AssemblyName>
+ <TargetFrameworkIdentifier>Silverlight</TargetFrameworkIdentifier>
+ <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+ <SilverlightVersion>$(TargetFrameworkVersion)</SilverlightVersion>
+ <SilverlightApplication>true</SilverlightApplication>
+ <SupportedCultures>
+ </SupportedCultures>
+ <XapOutputs>true</XapOutputs>
+ <GenerateSilverlightManifest>true</GenerateSilverlightManifest>
+ <XapFilename>silverlightmediaelement.xap</XapFilename>
+ <SilverlightManifestTemplate>Properties\AppManifest.xml</SilverlightManifestTemplate>
+ <SilverlightAppEntry>SilverlightMediaElement.App</SilverlightAppEntry>
+ <TestPageFileName>SilverlightMediaElementTestPage.html</TestPageFileName>
+ <CreateTestPage>true</CreateTestPage>
+ <ValidateXaml>true</ValidateXaml>
+ <EnableOutOfBrowser>false</EnableOutOfBrowser>
+ <OutOfBrowserSettingsFile>Properties\OutOfBrowserSettings.xml</OutOfBrowserSettingsFile>
+ <UsePlatformExtensions>false</UsePlatformExtensions>
+ <ThrowErrorsInValidation>true</ThrowErrorsInValidation>
+ <LinkedServerProject>
+ </LinkedServerProject>
+ <SignManifests>false</SignManifests>
+ <TargetFrameworkProfile />
+ </PropertyGroup>
+ <!-- This property group is only here to support building this project using the
+ MSBuild 3.5 toolset. In order to work correctly with this older toolset, it needs
+ to set the TargetFrameworkVersion to v3.5 -->
+ <PropertyGroup Condition="'$(MSBuildToolsVersion)' == '3.5'">
+ <TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>..\..\build\</OutputPath>
+ <DefineConstants>DEBUG;TRACE;SILVERLIGHT</DefineConstants>
+ <NoStdLib>true</NoStdLib>
+ <NoConfig>true</NoConfig>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>..\..\src\</OutputPath>
+ <DefineConstants>TRACE;SILVERLIGHT</DefineConstants>
+ <NoStdLib>true</NoStdLib>
+ <NoConfig>true</NoConfig>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <DocumentationFile>
+ </DocumentationFile>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="mscorlib" />
+ <Reference Include="System.Windows" />
+ <Reference Include="system" />
+ <Reference Include="System.Core" />
+ <Reference Include="System.Net" />
+ <Reference Include="System.Xml" />
+ <Reference Include="System.Windows.Browser" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="App.xaml.cs">
+ <DependentUpon>App.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="MainPage.xaml.cs">
+ <DependentUpon>MainPage.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ApplicationDefinition Include="App.xaml">
+ <SubType>Designer</SubType>
+ <Generator>MSBuild:Compile</Generator>
+ </ApplicationDefinition>
+ <Page Include="MainPage.xaml">
+ <SubType>Designer</SubType>
+ <Generator>MSBuild:Compile</Generator>
+ </Page>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="Properties\AppManifest.xml" />
+ </ItemGroup>
+ <Import Project="$(MSBuildExtensionsPath32)\Microsoft\Silverlight\$(SilverlightVersion)\Microsoft.Silverlight.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+ <ProjectExtensions>
+ <VisualStudio>
+ <FlavorProperties GUID="{A1591282-1198-4647-A2B1-27E5FF5F6F3B}">
+ <SilverlightProjectProperties />
+ </FlavorProperties>
+ </VisualStudio>
+ </ProjectExtensions>
+</Project> \ No newline at end of file
diff --git a/files_videoviewer/src/silverlight/SilverlightMediaElement.csproj.user b/files_videoviewer/src/silverlight/SilverlightMediaElement.csproj.user
new file mode 100644
index 000000000..2fe79f9ea
--- /dev/null
+++ b/files_videoviewer/src/silverlight/SilverlightMediaElement.csproj.user
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <ProjectView>ShowAllFiles</ProjectView>
+ </PropertyGroup>
+ <ProjectExtensions>
+ <VisualStudio>
+ <FlavorProperties GUID="{A1591282-1198-4647-A2B1-27E5FF5F6F3B}">
+ <SilverlightProjectProperties>
+ <StartPageUrl>
+ </StartPageUrl>
+ <StartAction>DynamicPage</StartAction>
+ <AspNetDebugging>True</AspNetDebugging>
+ <NativeDebugging>False</NativeDebugging>
+ <SQLDebugging>False</SQLDebugging>
+ <ExternalProgram>
+ </ExternalProgram>
+ <StartExternalURL>
+ </StartExternalURL>
+ <StartCmdLineArguments>
+ </StartCmdLineArguments>
+ <StartWorkingDirectory>
+ </StartWorkingDirectory>
+ <ShowWebRefOnDebugPrompt>True</ShowWebRefOnDebugPrompt>
+ <OutOfBrowserProjectToDebug>
+ </OutOfBrowserProjectToDebug>
+ <ShowRiaSvcsOnDebugPrompt>True</ShowRiaSvcsOnDebugPrompt>
+ </SilverlightProjectProperties>
+ </FlavorProperties>
+ </VisualStudio>
+ </ProjectExtensions>
+</Project> \ No newline at end of file
diff --git a/files_videoviewer/src/silverlight/SilverlightMediaElement.sln b/files_videoviewer/src/silverlight/SilverlightMediaElement.sln
new file mode 100644
index 000000000..b3110c843
--- /dev/null
+++ b/files_videoviewer/src/silverlight/SilverlightMediaElement.sln
@@ -0,0 +1,20 @@
+
+Microsoft Visual Studio Solution File, Format Version 11.00
+# Visual Studio 2010
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SilverlightMediaElement", "SilverlightMediaElement.csproj", "{CE832DD6-B659-4F3E-B49B-F297E2AC923A}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {CE832DD6-B659-4F3E-B49B-F297E2AC923A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {CE832DD6-B659-4F3E-B49B-F297E2AC923A}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {CE832DD6-B659-4F3E-B49B-F297E2AC923A}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {CE832DD6-B659-4F3E-B49B-F297E2AC923A}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal