Index: branches/MwEmbedStandAlone/tests/media/sequence_transition_smil.xml |
— | — | @@ -1,65 +0,0 @@ |
2 | | -<?xml version="1.0" encoding="UTF-8"?> |
3 | | -<smil baseProfile="Language" version="3.0" xmlns="http://www.w3.org/ns/SMIL"> |
4 | | - <head> |
5 | | - <meta name="title" content="Simple Crossfading Example"/> |
6 | | - |
7 | | - <transition id="fromGreen" |
8 | | - type="fade" |
9 | | - subtype="fadeFromColor" |
10 | | - fadeColor="#87CF87" |
11 | | - dur="4s"/> |
12 | | - |
13 | | - <transition id="toGreen" |
14 | | - type="fade" |
15 | | - subtype="fadeToColor" |
16 | | - fadeColor="#87CF87" |
17 | | - dur="4s"/> |
18 | | - |
19 | | - <transition id="xFade" |
20 | | - type="fade" |
21 | | - subtype="crossfade" |
22 | | - dur="4s"/> |
23 | | - |
24 | | - </head> |
25 | | - <body> |
26 | | - <seq> |
27 | | - <ref type="text/html" dur="8" uri="Template:My_Video_Intro_Text"><![CDATA[ |
28 | | -<h3> <span class="mw-headline" id="cat">cat</span></h3> |
29 | | -<div class="thumb tright"><div class="thumbinner" style="width:102px;"><img src="http://upload.wikimedia.org/wikipedia/commons/thumb/d/dc/Nos_kota.jpg/120px-Nos_kota.jpg"></div></div> |
30 | | -<div style="color:gray"> MY Date: 21 January, 2010 00:45</div> |
31 | | - |
32 | | -]]><param name="videoTitle">cat</param><param name="MyDate">{{CURRENTDAY}} {{CURRENTMONTHNAME}}, {{CURRENTYEAR}} {{CURRENTTIME}}</param></ref> |
33 | | - |
34 | | - |
35 | | - <video src="http://upload.wikimedia.org/wikipedia/commons/d/d3/Okapia_johnstoni5.ogg" |
36 | | - region="video_region" |
37 | | - transIn="fromGreen" |
38 | | - transOut="xFade" |
39 | | - type="video/ogg" |
40 | | - fill="transition" |
41 | | - durationHint="15" |
42 | | - dur="9s" |
43 | | - poster="http://upload.wikimedia.org/wikipedia/commons/thumb/d/d3/Okapia_johnstoni5.ogg/mid-Okapia_johnstoni5.ogg.jpg" |
44 | | - /> |
45 | | - |
46 | | - <video src="http://upload.wikimedia.org/wikipedia/commons/0/0d/B-36_bomber.ogg" |
47 | | - region="video_region" |
48 | | - fill="transition" |
49 | | - dur="10s" |
50 | | - durationHint="70" |
51 | | - type="video/ogg" |
52 | | - poster="http://upload.wikimedia.org/wikipedia/commons/thumb/0/0d/B-36_bomber.ogg/mid-B-36_bomber.ogg.jpg" |
53 | | - /> |
54 | | - |
55 | | - <img src="http://upload.wikimedia.org/wikipedia/commons/thumb/b/b6/USS_Bunker_Hill_hit_by_two_Kamikazes.jpg/400px-USS_Bunker_Hill_hit_by_two_Kamikazes.jpg" |
56 | | - region="video_region" |
57 | | - dur="5s" |
58 | | - type="image/jpeg" |
59 | | - /> |
60 | | - |
61 | | - </seq> |
62 | | - |
63 | | - </body> |
64 | | -</smil> |
65 | | - |
66 | | - |
Index: branches/MwEmbedStandAlone/modules/SmilPlayer/mw.SmilBody.js |
— | — | @@ -35,7 +35,7 @@ |
36 | 36 | _this.getNodeSmilType( $node ) == 'ref' |
37 | 37 | || _this.getNodeSmilType( $node ) == 'smilText' |
38 | 38 | ) |
39 | | - ){ |
| 39 | + ){ |
40 | 40 | $node.attr('id', _this.smil.embedPlayer.id + '_ref_' + _this.idIndex ); |
41 | 41 | mw.log('SmilBody:: gave: ' + $node.get(0).nodeName + ' id: ' + $node.attr('id') ); |
42 | 42 | _this.idIndex++; |
— | — | @@ -52,23 +52,23 @@ |
53 | 53 | /** |
54 | 54 | * Render the body elements for a given time, use layout engine to draw elements |
55 | 55 | */ |
56 | | - renderTime: function( time ){ |
| 56 | + renderTime: function( time, deltaTime ){ |
57 | 57 | var _this = this; |
58 | 58 | // Get all the draw elements from the body this time: |
59 | 59 | var elementList = this.getElementsForTime( time ); |
60 | | - mw.log("SmilBody::renderTime: draw " + elementList.length + " elementList" ); |
| 60 | + //mw.log("SmilBody::renderTime: draw " + elementList.length + " elementList" ); |
61 | 61 | |
62 | 62 | $j.each( elementList , function( inx, smilElement ) { |
63 | 63 | // xxx need to |
64 | 64 | // var relativeTime = time - smilElement.parentTimeOffset; |
65 | | - var relativeTime = time - $j( smilElement ) .data ( 'parentStartOffset' ); |
| 65 | + var relativeTime = time - $j( smilElement ).data ( 'parentStartOffset' ); |
66 | 66 | |
67 | 67 | // Render the active elements using the layout engine |
68 | 68 | _this.smil.getLayout().drawElement( smilElement, relativeTime ); |
69 | 69 | |
70 | | - // Transform the elements per animate engine |
71 | | - _this.smil.getAnimate().transformElement( smilElement, relativeTime ); |
72 | | - } ) |
| 70 | + // Transform the elements per animate engine |
| 71 | + _this.smil.getAnimate().animateTransform( smilElement, relativeTime, deltaTime ); |
| 72 | + } ); |
73 | 73 | }, |
74 | 74 | |
75 | 75 | /** |
— | — | @@ -139,7 +139,7 @@ |
140 | 140 | // If the nodeType is "ref" add to this.elementsInRange array |
141 | 141 | if( nodeType == 'ref' || nodeType == 'smilText' ) { |
142 | 142 | // Add the parent startOffset |
143 | | - $node.data('parentStartOffset', startOffset ); |
| 143 | + $node.data( 'parentStartOffset', startOffset ); |
144 | 144 | // Ref type get the |
145 | 145 | this.elementsInRange.push( $node ); |
146 | 146 | //mw.log("Add ref to elementsInRange:: " + nodeType + " length:" + this.elementsInRange.length); |
Index: branches/MwEmbedStandAlone/modules/SmilPlayer/mw.SmilLayout.js |
— | — | @@ -71,7 +71,7 @@ |
72 | 72 | var regionId = $j( smilElement ).attr( 'region'); |
73 | 73 | var nodeName = $j( smilElement ).get(0).nodeName ; |
74 | 74 | |
75 | | - mw.log( "SmilLayout::drawElement: " + nodeName + '.' + $j( smilElement ).attr('id' ) + ' into ' + regionId ); |
| 75 | + //mw.log( "SmilLayout::drawElement: " + nodeName + '.' + $j( smilElement ).attr('id' ) + ' into ' + regionId ); |
76 | 76 | var $regionTarget = this.$rootLayout.find( '#' + regionId ); |
77 | 77 | |
78 | 78 | // Check for region target in $rootLayout |
Index: branches/MwEmbedStandAlone/modules/SmilPlayer/mw.SmilAnimate.js |
— | — | @@ -10,17 +10,115 @@ |
11 | 11 | // Constructor: |
12 | 12 | init: function( smilObject ){ |
13 | 13 | this.smil = smilObject; |
| 14 | + |
| 15 | + // xxx possible option? |
| 16 | + this.framerate = mw.getConfig( 'SmilPlayer.framerate' ); |
| 17 | + |
| 18 | + this.callbackRate = 1000 / this.framerate; |
| 19 | + this.animateInterval = []; |
14 | 20 | }, |
15 | 21 | |
| 22 | + /** |
| 23 | + * Animate a smil transform per supplied time. |
| 24 | + */ |
| 25 | + animateTransform: function( smilElement, animateTime, deltaTime ){ |
| 26 | + var _this = this; |
| 27 | + |
| 28 | + // If deltaTime is zero, then we should just transformElement directly: |
| 29 | + if( !deltaTime || deltaTime === 0 ){ |
| 30 | + _this.transformElement( smilElement, animateTime ); |
| 31 | + return ; |
| 32 | + } |
| 33 | + |
| 34 | + // Check if the current smilElement has any transforms to be done |
| 35 | + if( ! this.checkForTransformUpdate( smilElement, animateTime, deltaTime ) ){ |
| 36 | + // xxx no animate loop needed for element: smilElement |
| 37 | + return ; |
| 38 | + } |
| 39 | + |
| 40 | + // We have a delta spawn an short animateInterval |
| 41 | + |
| 42 | + // Clear any old animation loop ( can be caused by overlapping play requests or slow animation ) |
| 43 | + clearInterval( this.animateInterval[ this.smil.getAssetId( smilElement ) ] ); |
| 44 | + |
| 45 | + // Start a new animation interval |
| 46 | + var animationStartTime = new Date().getTime(); |
| 47 | + var animateTimeDelta = 0; |
| 48 | + |
| 49 | + this.animateInterval[ this.smil.getAssetId( smilElement ) ] = |
| 50 | + setInterval( |
| 51 | + function(){ |
| 52 | + var timeElapsed = new Date().getTime() - animationStartTime; |
| 53 | + // Set the animate Time delta |
| 54 | + animateTimeDelta += _this.callbackRate; |
| 55 | + |
| 56 | + if( animateTimeDelta > deltaTime || timeElapsed > deltaTime ){ |
| 57 | + // Stop animating: |
| 58 | + clearInterval( _this.animateInterval[ _this.smil.getAssetId( smilElement ) ] ); |
| 59 | + return ; |
| 60 | + } |
| 61 | + |
| 62 | + if( Math.abs( timeElapsed - animateTimeDelta ) > 100 ){ |
| 63 | + mw.log( "Error more than 100ms lag within animateTransform loop: te:" + timeElapsed + |
| 64 | + ' td:' + animateTimeDelta + ' diff: ' + Math.abs( timeElapsed - animateTimeDelta ) ); |
| 65 | + } |
| 66 | + |
| 67 | + // Do the transform request: |
| 68 | + _this.transformElement( smilElement, animateTime + ( animateTimeDelta/1000 ) ); |
| 69 | + }, |
| 70 | + this.callbackRate |
| 71 | + ); |
| 72 | + }, |
| 73 | + |
| 74 | + /** |
| 75 | + * Quickly check if a given smil element needs to be updated for a given time delta |
| 76 | + */ |
| 77 | + checkForTransformUpdate: function( smilElement, animateTime, deltaTime ){ |
| 78 | + // Get the node type: |
| 79 | + var nodeName = $j( smilElement ).get(0).nodeName; |
| 80 | + |
| 81 | + // NOTE: our img node check sort of avoids deltaTime check but its assumed to not matter much |
| 82 | + // since any our supported keyframe granularity will be equal to deltaTime ie 1/4 a second. |
| 83 | + if( nodeName.toLowerCase() == 'img' ){ |
| 84 | + // Confirm a child animate is in-range |
| 85 | + if( $j( smilElement ).find( 'animate' ).length ) { |
| 86 | + // Check if there are animate elements in range: |
| 87 | + if( this.getSmilAnimateInRange( smilElement, animateTime) ){ |
| 88 | + return true; |
| 89 | + } |
| 90 | + } |
| 91 | + } |
| 92 | + |
| 93 | + // Check if we need to do a smilText clear: |
| 94 | + if( nodeName.toLowerCase() == 'smiltext' ){ |
| 95 | + var el = $j( smilElement ).get(0); |
| 96 | + for ( var i=0; i < el.childNodes.length; i++ ) { |
| 97 | + var node = el.childNodes[i]; |
| 98 | + // Check for text Node type: |
| 99 | + if( node.nodeName == 'clear' ) { |
| 100 | + var clearTime = this.smil.parseTime( $j( node ).attr( 'begin') ); |
| 101 | + //mw.log( ' ct: ' + clearTime + ' >= ' + animateTime + ' , ' + deltaTime ); |
| 102 | + if( clearTime >= animateTime && clearTime <= ( animateTime + deltaTime ) ) { |
| 103 | + return true; |
| 104 | + } |
| 105 | + } |
| 106 | + } |
| 107 | + } |
| 108 | + //mw.log( 'checkForTransformUpdate::' + nodeName +' ' + animateTime ); |
| 109 | + |
| 110 | + return false; |
| 111 | + }, |
| 112 | + |
| 113 | + |
16 | 114 | /** |
17 | 115 | * Transform a smil element for a requested time. |
18 | 116 | * |
19 | 117 | * @param {Element} smilElement Element to be transformed |
20 | | - * @param {float} animateTime The relative time to be transfored. |
| 118 | + * @param {float} animateTime The relative time to be transformed. |
21 | 119 | */ |
22 | 120 | transformElement: function( smilElement, animateTime ) { |
23 | 121 | var nodeName = $j( smilElement ).get(0).nodeName ; |
24 | | - mw.log("transformForTime: " + nodeName ); |
| 122 | + //mw.log("transformForTime: " + nodeName + ' t:' + animateTime ); |
25 | 123 | switch( nodeName.toLowerCase() ){ |
26 | 124 | case 'smiltext': |
27 | 125 | return this.transformTextForTime( smilElement, animateTime); |
— | — | @@ -32,92 +130,113 @@ |
33 | 131 | }, |
34 | 132 | |
35 | 133 | transformTextForTime: function( textElement, animateTime ) { |
| 134 | + //mw.log("transformTextForTime:: " + animateTime ); |
| 135 | + |
36 | 136 | if( $j( textElement ).children().length == 0 ){ |
37 | 137 | // no text transform children |
38 | 138 | return ; |
39 | | - } |
40 | | - |
| 139 | + } |
41 | 140 | // xxx Note: we could have text transforms in the future: |
42 | 141 | var textCss = this.smil.getLayout().transformSmilCss( textElement ); |
| 142 | + |
| 143 | + // Set initial textValue: |
| 144 | + var textValue =''; |
43 | 145 | |
44 | | - var bucketText = ''; |
45 | | - var textBuckets = []; |
46 | | - var clearInx = 0; |
47 | | - var el = $j( textElement ).get(0); |
| 146 | + var el = $j( textElement ).get(0); |
48 | 147 | for ( var i=0; i < el.childNodes.length; i++ ) { |
49 | 148 | var node = el.childNodes[i]; |
50 | 149 | // Check for text Node type: |
51 | 150 | if( node.nodeType == 3 ) { |
52 | | - bucketText += node.nodeValue; |
53 | | - } else if( node.nodeName == 'clear'){ |
54 | | - var clearTime = this.smil.parseTime( $j( node ).attr( 'begin') ); |
55 | | - // append bucket |
56 | | - textBuckets.push( { |
57 | | - 'text' : bucketText, |
58 | | - 'clearTime' : clearTime |
59 | | - } ); |
| 151 | + textValue += node.nodeValue; |
| 152 | + } else if( node.nodeName == 'clear' ){ |
| 153 | + var clearTime = this.smil.parseTime( $j( node ).attr( 'begin') ); |
| 154 | + if( clearTime > animateTime ){ |
| 155 | + break; |
| 156 | + } |
60 | 157 | // Clear the bucket text collection |
61 | | - bucketText =''; |
| 158 | + textValue = ''; |
62 | 159 | } |
63 | | - } |
64 | | - |
65 | | - var textValue =''; |
66 | | - // Get the text node in range given time: |
67 | | - for( var i =0; i < textBuckets.length ; i++){ |
68 | | - var bucket = textBuckets[i]; |
69 | | - if( animateTime < bucket.clearTime ){ |
70 | | - textValue = bucket.text; |
71 | | - break; |
72 | | - } |
73 | | - } |
| 160 | + } |
| 161 | + |
74 | 162 | // Update the text value target |
75 | 163 | // xxx need to profile update vs check value |
76 | 164 | $j( '#' + this.smil.getAssetId( textElement ) ) |
77 | | - .html( |
78 | | - $j('<span />') |
79 | | - // Add the text value |
80 | | - .text( textValue ) |
81 | | - .css( textCss ) |
82 | | - ) |
| 165 | + .html( |
| 166 | + $j('<span />') |
| 167 | + // Add the text value |
| 168 | + .text( textValue ) |
| 169 | + .css( textCss ) |
| 170 | + ) |
83 | 171 | }, |
84 | 172 | |
85 | 173 | transformImageForTime: function( smilImgElement, animateTime ) { |
86 | 174 | var _this = this; |
| 175 | + //mw.log( "transformImageForTime:: animateTime:" + animateTime ); |
| 176 | + |
87 | 177 | if( $j( smilImgElement ).children().length == 0 ){ |
88 | | - // no image transform children |
| 178 | + // No image transform children |
89 | 179 | return ; |
90 | 180 | } |
| 181 | + |
| 182 | + var animateInRange = _this.getSmilAnimateInRange( smilImgElement, animateTime, function( animateElement ){ |
| 183 | + //mw.log('animateInRange callback::' + $j( animateElement ).attr( 'attributeName' ) ); |
| 184 | + switch( $j( animateElement ).attr( 'attributeName' ) ) { |
| 185 | + case 'panZoom': |
| 186 | + // Get the pan zoom css for "this" time |
| 187 | + _this.transformPanZoom ( smilImgElement, animateElement, animateTime ); |
| 188 | + break; |
| 189 | + default: |
| 190 | + mw.log("Error unrecognized Animation attributName: " + |
| 191 | + $j( animateElement ).attr( 'attributeName' ) ); |
| 192 | + } |
| 193 | + }); |
| 194 | + // No animate elements in range, make sure we transform to previus or to initial state if time is zero |
| 195 | + if( !animateInRange ) { |
| 196 | + if( animateTime == 0 ) { |
| 197 | + // just a hack for now ( should read from previus animation or from source attribute |
| 198 | + //this.updateElementLayout( smilImgElement, { 'top':1,'left':1,'width':1, 'height':1 } ); |
| 199 | + var $target = $j( '#' + this.smil.getAssetId( smilImgElement )); |
| 200 | + $target.css({ 'top':'0px','left':'0px','width':'100%', 'height':'100%' } ); |
| 201 | + } |
| 202 | + // xxx should check for transform to previus |
| 203 | + } |
| 204 | + }, |
| 205 | + |
| 206 | + /** |
| 207 | + * Calls a callback with Smil Animate In Range for a requested time |
| 208 | + * |
| 209 | + * @param {Element} smilImgElement The smil element to search for child animate |
| 210 | + * @param {float} animateTime The target animation time |
| 211 | + * @param {function=} callback Optional function to call with elements in range. |
| 212 | + * return @bollean true if animate elements are in range false if none found |
| 213 | + */ |
| 214 | + getSmilAnimateInRange: function( smilImgElement, animateTime, callback ){ |
| 215 | + var _this = this; |
| 216 | + var animateInRange = false; |
91 | 217 | // Get transform elements in range |
92 | 218 | $j( smilImgElement ).find( 'animate' ).each( function( inx, animateElement ){ |
93 | 219 | var begin = _this.smil.parseTime( $j( animateElement ).attr( 'begin') ); |
94 | 220 | var duration = _this.smil.parseTime( $j( animateElement ).attr( 'dur') ); |
95 | | - //mw.log( "b:" + begin +" < " + animateTime + " && b+d: " + ( begin + duration ) + " > " + animateTime ); |
| 221 | + //mw.log( "getSmilAnimateInRange:: b:" + begin +" < " + animateTime + " && b+d: " + ( begin + duration ) + " > " + animateTime ); |
96 | 222 | |
97 | 223 | // Check if the animate element is in range |
98 | 224 | var cssTransform = {}; |
99 | 225 | if( begin <= animateTime && ( begin + duration ) >= animateTime ) { |
100 | | - // Get the transform type: |
101 | | - switch( $j( animateElement ).attr('attributeName') ){ |
102 | | - case 'panZoom': |
103 | | - // Get the pan zoom css for "this" time |
104 | | - _this.transformPanZoom ( smilImgElement, animateElement, animateTime ); |
105 | | - break; |
106 | | - default: |
107 | | - mw.log("Error unrecognized Annimation attributName: " + |
108 | | - $j( animateElement ).attr('attributeName') ); |
109 | | - |
110 | | - } |
111 | | - //mw.log("b:transformImageForTime: " + $j( animateElement ).attr( 'values' ) ); |
112 | | - //$j( smilImgElement ).css( cssTransform ); |
113 | | - } |
114 | | - |
| 226 | + animateInRange = true; |
| 227 | + if( callback ) { |
| 228 | + callback( animateElement ); |
| 229 | + } |
| 230 | + } |
115 | 231 | }); |
| 232 | + return animateInRange; |
116 | 233 | }, |
| 234 | + |
117 | 235 | /** |
118 | | - * get the css layout transforms for a panzoom transform type |
| 236 | + * Get the css layout transforms for a panzoom transform type |
119 | 237 | * |
120 | 238 | * http://www.w3.org/TR/SMIL/smil-extended-media-object.html#q32 |
121 | | - * |
| 239 | + * |
| 240 | + * |
122 | 241 | */ |
123 | 242 | transformPanZoom: function( smilImgElement, animateElement, animateTime ){ |
124 | 243 | var begin = this.smil.parseTime( $j( animateElement ).attr( 'begin') ); |
— | — | @@ -131,6 +250,8 @@ |
132 | 251 | |
133 | 252 | // Get the target interpreted value |
134 | 253 | var targetValue = this.getInterpolatePointsValue( animatePoints, relativeAnimationTime, duration ); |
| 254 | + |
| 255 | + //mw.log( "SmilAnimate::transformPanZoom: source points: " + $j( animateElement ).attr('values') + " target:" + targetValue.join(',') ); |
135 | 256 | |
136 | 257 | // Let Top Width Height |
137 | 258 | // translate values into % values |
— | — | @@ -164,7 +285,8 @@ |
165 | 286 | // xxx need to refactor move to "smilLayout" |
166 | 287 | updateElementLayout: function( smilElement, percentValues ){ |
167 | 288 | |
168 | | - mw.log("updateElementLayout::" + percentValues.top + ' ' + percentValues.left + ' ' + percentValues.width + ' ' + percentValues.height ); |
| 289 | + //mw.log("updateElementLayout::" + percentValues.top + ' ' + percentValues.left + ' ' + percentValues.width + ' ' + percentValues.height ); |
| 290 | + |
169 | 291 | // get a pointer to the html target: |
170 | 292 | var $target = $j( '#' + this.smil.getAssetId( smilElement )); |
171 | 293 | |
— | — | @@ -209,7 +331,6 @@ |
210 | 332 | 'top' : (-1 * percentValues['top'])*100 + '%', |
211 | 333 | 'left' : (-1 * percentValues['left'])*100 + '%', |
212 | 334 | } ); |
213 | | - |
214 | 335 | }, |
215 | 336 | |
216 | 337 | /** |
Index: branches/MwEmbedStandAlone/modules/SmilPlayer/loader.js |
— | — | @@ -4,6 +4,12 @@ |
5 | 5 | // Wrap in mw to not pollute global namespace |
6 | 6 | ( function( mw ) { |
7 | 7 | |
| 8 | + mw.setDefaultConfig( { |
| 9 | + // The framerate for the smil player |
| 10 | + 'SmilPlayer.framerate': 30 |
| 11 | + } ); |
| 12 | + |
| 13 | + |
8 | 14 | mw.addResourcePaths( { |
9 | 15 | "mw.SmilHooks" : "mw.SmilHooks.js", |
10 | 16 | |
Index: branches/MwEmbedStandAlone/modules/SmilPlayer/mw.Smil.js |
— | — | @@ -119,6 +119,17 @@ |
120 | 120 | }, |
121 | 121 | |
122 | 122 | /** |
| 123 | + * We use animateTime instead of a tight framerate loop |
| 124 | + * so that we can optimize with css transformations |
| 125 | + * |
| 126 | + * ( Very similar to renderTime but no callback and we pass a timeDelta |
| 127 | + */ |
| 128 | + animateTime: function( time, timeDelta ){ |
| 129 | + //mw.log("Smil::animateTime: " + time + ' delta: ' + timeDelta ); |
| 130 | + this.getBody().renderTime( time, timeDelta ); |
| 131 | + }, |
| 132 | + |
| 133 | + /** |
123 | 134 | * Get the smil buffer object |
124 | 135 | */ |
125 | 136 | getBuffer: function(){ |
Index: branches/MwEmbedStandAlone/modules/SmilPlayer/tests/panzoom/Fruits-4s.smil.xml |
— | — | @@ -23,11 +23,14 @@ |
24 | 24 | panZoom="0,0,100%,100%" region="image_region" src="fruitStand.jpg">
|
25 | 25 |
|
26 | 26 | <animate attributeName="panZoom" begin="2.0"
|
27 | | - dur="1.5s" fill="freeze" values="-1,4,99%,99%;511,509,47%,14%"/>
|
| 27 | + dur="1.5s" fill="freeze" values="-1,4,99%,99%;511,509,47%,14%"/> |
| 28 | +
|
28 | 29 | <animate attributeName="panZoom" begin="5.0"
|
29 | 30 | dur="1.5s" fill="freeze" values="511,509,47%,14%;418,-3,34%,13%"/>
|
| 31 | + |
30 | 32 | <animate attributeName="panZoom" begin="9.0"
|
31 | | - dur="1.5s" fill="freeze" values="418,-3,34%,13%;9,1115,41%,20%"/>
|
| 33 | + dur="1.5s" fill="freeze" values="418,-3,34%,13%;9,1115,41%,20%"/> |
| 34 | +
|
32 | 35 | <animate attributeName="panZoom" begin="13.0"
|
33 | 36 | dur="1.5s" fill="freeze" values="9,1115,41%,20%;573,2073,64%,17%"/>
|
34 | 37 | <animate attributeName="panZoom" begin="16.0"
|
Index: branches/MwEmbedStandAlone/modules/SmilPlayer/tests/VideoTransition.html |
— | — | @@ -0,0 +1,44 @@ |
| 2 | +<!doctype html> |
| 3 | +<html> |
| 4 | +<head> |
| 5 | + <title>Pan Zoom Example</title> |
| 6 | + <script type="text/javascript" src="../../../mwEmbed.js?debug=true"></script> |
| 7 | + <!-- <script type="text/javascript" src="../../ResourceLoader.php?class=window.jQuery,mwEmbed&debug=true"></script> --> |
| 8 | + <script type="text/javascript"> |
| 9 | + mw.setConfig( 'EmbedPlayer.OverlayControls', false ); |
| 10 | + mw.ready(function(){ |
| 11 | + $j( "#seekInputTime" ).blur( function(){ |
| 12 | + var smilVid = $j('#panzoom').get(0); |
| 13 | + $j('#seekInProgress').show(); |
| 14 | + smilVid.setCurrentTime( parseFloat( $j(this).val() ), function(){ |
| 15 | + $j('#seekInProgress').hide(); |
| 16 | + }); |
| 17 | + }); |
| 18 | + }); |
| 19 | + </script> |
| 20 | +</head> |
| 21 | +<body> |
| 22 | +<h3>Sample playlist pan-zoom animation</h3> |
| 23 | +<table> |
| 24 | +<tr> |
| 25 | +<td> |
| 26 | + |
| 27 | +<video id="panzoom" type="application/smil" src="panzoom/Fruits-4s.smil.xml" width="400" height="400"></video> |
| 28 | +<p></p>seek to <input id="seekInputTime" size="4" value = "10"></input><span id="seekInProgress" style="display: none"> Seeking<blink>...</blink></span> |
| 29 | +</td> |
| 30 | +<td valign="top"> |
| 31 | +Sample playlist code: |
| 32 | +<div style="clear:both"></div> |
| 33 | +<textarea style="width:500px;"> |
| 34 | +<video id="panzoom" type="application/smil" src="panzoom/Fruits-4s.smil.xml" width="400" height="300"></video> |
| 35 | +</textarea> |
| 36 | +<div style="clear:both"></div> |
| 37 | + |
| 38 | +SMIL Source: |
| 39 | +<div style="clear:both"></div> |
| 40 | +<iframe style="width:500px;height:300px" src="panzoom/Fruits-4s.smil.xml"></iframe> |
| 41 | +</td> |
| 42 | +</tr> |
| 43 | +</table> |
| 44 | +</body> |
| 45 | +</html> |
Index: branches/MwEmbedStandAlone/modules/SmilPlayer/tests/VideoTransitionSmil.xml |
— | — | @@ -0,0 +1,65 @@ |
| 2 | +<?xml version="1.0" encoding="UTF-8"?> |
| 3 | +<smil baseProfile="Language" version="3.0" xmlns="http://www.w3.org/ns/SMIL"> |
| 4 | + <head> |
| 5 | + <meta name="title" content="Simple Crossfading Example"/> |
| 6 | + |
| 7 | + <transition id="fromGreen" |
| 8 | + type="fade" |
| 9 | + subtype="fadeFromColor" |
| 10 | + fadeColor="#87CF87" |
| 11 | + dur="4s"/> |
| 12 | + |
| 13 | + <transition id="toGreen" |
| 14 | + type="fade" |
| 15 | + subtype="fadeToColor" |
| 16 | + fadeColor="#87CF87" |
| 17 | + dur="4s"/> |
| 18 | + |
| 19 | + <transition id="xFade" |
| 20 | + type="fade" |
| 21 | + subtype="crossfade" |
| 22 | + dur="4s"/> |
| 23 | + |
| 24 | + </head> |
| 25 | + <body> |
| 26 | + <seq> |
| 27 | + <ref type="text/html" dur="8" uri="Template:My_Video_Intro_Text"><![CDATA[ |
| 28 | +<h3> <span class="mw-headline" id="cat">cat</span></h3> |
| 29 | +<div class="thumb tright"><div class="thumbinner" style="width:102px;"><img src="http://upload.wikimedia.org/wikipedia/commons/thumb/d/dc/Nos_kota.jpg/120px-Nos_kota.jpg"></div></div> |
| 30 | +<div style="color:gray"> MY Date: 21 January, 2010 00:45</div> |
| 31 | + |
| 32 | +]]><param name="videoTitle">cat</param><param name="MyDate">{{CURRENTDAY}} {{CURRENTMONTHNAME}}, {{CURRENTYEAR}} {{CURRENTTIME}}</param></ref> |
| 33 | + |
| 34 | + |
| 35 | + <video src="http://upload.wikimedia.org/wikipedia/commons/d/d3/Okapia_johnstoni5.ogg" |
| 36 | + region="video_region" |
| 37 | + transIn="fromGreen" |
| 38 | + transOut="xFade" |
| 39 | + type="video/ogg" |
| 40 | + fill="transition" |
| 41 | + durationHint="15" |
| 42 | + dur="9s" |
| 43 | + poster="http://upload.wikimedia.org/wikipedia/commons/thumb/d/d3/Okapia_johnstoni5.ogg/mid-Okapia_johnstoni5.ogg.jpg" |
| 44 | + /> |
| 45 | + |
| 46 | + <video src="http://upload.wikimedia.org/wikipedia/commons/0/0d/B-36_bomber.ogg" |
| 47 | + region="video_region" |
| 48 | + fill="transition" |
| 49 | + dur="10s" |
| 50 | + durationHint="70" |
| 51 | + type="video/ogg" |
| 52 | + poster="http://upload.wikimedia.org/wikipedia/commons/thumb/0/0d/B-36_bomber.ogg/mid-B-36_bomber.ogg.jpg" |
| 53 | + /> |
| 54 | + |
| 55 | + <img src="http://upload.wikimedia.org/wikipedia/commons/thumb/b/b6/USS_Bunker_Hill_hit_by_two_Kamikazes.jpg/400px-USS_Bunker_Hill_hit_by_two_Kamikazes.jpg" |
| 56 | + region="video_region" |
| 57 | + dur="5s" |
| 58 | + type="image/jpeg" |
| 59 | + /> |
| 60 | + |
| 61 | + </seq> |
| 62 | + |
| 63 | + </body> |
| 64 | +</smil> |
| 65 | + |
| 66 | + |
Property changes on: branches/MwEmbedStandAlone/modules/SmilPlayer/tests/VideoTransitionSmil.xml |
___________________________________________________________________ |
Name: svn:mergeinfo |
1 | 67 | + /branches/REL1_15/phase3/js2/mwEmbed/example_usage/media/sample_smil.xml:51646 |
/branches/sqlite/js2/mwEmbed/example_usage/media/sample_smil.xml:58211-58321 |
Name: svn:eol-style |
2 | 68 | + native |
Index: branches/MwEmbedStandAlone/modules/SmilPlayer/mw.EmbedPlayerSmil.js |
— | — | @@ -48,19 +48,26 @@ |
49 | 49 | * @param {function} callback Function to be called once currentTime is loaded and displayed |
50 | 50 | */ |
51 | 51 | setCurrentTime: function( time, callback ) { |
52 | | - mw.log('EmbedPlayerSmil::setCurrentTime: ' + time ); |
| 52 | + mw.log('EmbedPlayerSmil::setCurrentTime: ' + time ); |
53 | 53 | // Set "loading" spinner here) |
54 | 54 | $j( this ).append( |
55 | 55 | $j( '<div />') |
56 | 56 | .attr('id', 'loadingSpinner_' + this.id ) |
57 | 57 | .loadingSpinner() |
58 | 58 | ); |
| 59 | + // Start seek |
| 60 | + this.controlBuilder.onSeek(); |
| 61 | + this.smilPlayTime = time; |
59 | 62 | var _this = this; |
60 | 63 | this.getSmil( function( smil ){ |
61 | 64 | smil.renderTime( time, function(){ |
62 | | - mw.log("renderTime callback"); |
| 65 | + mw.log( "setCurrentTime:: renderTime callback" ); |
63 | 66 | $j('#loadingSpinner_' + _this.id ).remove(); |
64 | | - callback(); |
| 67 | + |
| 68 | + _this.monitor(); |
| 69 | + if( callback ){ |
| 70 | + callback(); |
| 71 | + } |
65 | 72 | } ); |
66 | 73 | }); |
67 | 74 | }, |
— | — | @@ -71,7 +78,7 @@ |
72 | 79 | getRenderTarget: function(){ |
73 | 80 | if( !this.$renderTarget ){ |
74 | 81 | if( $j('#smilCanvas_' + this.id ).length === 0 ) { |
75 | | - // if no render target exist create one: |
| 82 | + // If no render target exist create one: |
76 | 83 | $j( this ).html( |
77 | 84 | $j( '<div />') |
78 | 85 | .attr('id', 'smilCanvas_' + this.id ) |
— | — | @@ -93,9 +100,8 @@ |
94 | 101 | this.parent_play(); |
95 | 102 | |
96 | 103 | // Set start clock time: |
97 | | - this.clockStartTime = new Date().getTime(); |
| 104 | + this.clockStartTime = new Date().getTime(); |
98 | 105 | |
99 | | - |
100 | 106 | this.getSmil( function( smil ){ |
101 | 107 | this.smil = smil; |
102 | 108 | }) |
— | — | @@ -106,6 +112,7 @@ |
107 | 113 | stop: function(){ |
108 | 114 | this.smilPlayTime = 0; |
109 | 115 | this.smilPauseTime = 0; |
| 116 | + this.setCurrentTime( 0 ); |
110 | 117 | this.parent_stop(); |
111 | 118 | }, |
112 | 119 | |
— | — | @@ -125,6 +132,7 @@ |
126 | 133 | getPlayerElementTime: function() { |
127 | 134 | return this.smilPlayTime; |
128 | 135 | }, |
| 136 | + |
129 | 137 | |
130 | 138 | /** |
131 | 139 | * Monitor function render a given time |
— | — | @@ -133,14 +141,13 @@ |
134 | 142 | // Update the smilPlayTime |
135 | 143 | if( !this.isPaused() ){ |
136 | 144 | this.smilPlayTime = this.smilPauseTime + ( ( new Date().getTime() - this.clockStartTime ) / 1000 ); |
| 145 | + |
| 146 | + // xxx check buffer to see if we need to pause playback |
| 147 | + |
| 148 | + // Issue an animate time request with monitorDelta |
| 149 | + this.smil.animateTime( this.smilPlayTime, this.monitorRate ); |
137 | 150 | } |
138 | | - |
139 | | - // Animate to time |
140 | | - smil.renderTime( this.smilPlayTime, function(){ |
141 | | - // callback for render |
142 | | - |
143 | | - // xxx if too much time has gone by potentaill flag |
144 | | - }); |
| 151 | + |
145 | 152 | this.parent_monitor(); |
146 | 153 | }, |
147 | 154 | |
Index: branches/MwEmbedStandAlone/modules/EmbedPlayer/loader.js |
— | — | @@ -64,7 +64,10 @@ |
65 | 65 | "EmbedPlayer.ShareEmbedMode" : 'object', |
66 | 66 | |
67 | 67 | // Default player skin name |
68 | | - "EmbedPlayer.SkinName" : "mvpcf" |
| 68 | + "EmbedPlayer.SkinName" : "mvpcf", |
| 69 | + |
| 70 | + // Number of milliseconds between interface updates |
| 71 | + 'EmbedPlayer.MonitorRate' : 250 |
69 | 72 | } ); |
70 | 73 | |
71 | 74 | // Add class file paths |
Index: branches/MwEmbedStandAlone/modules/EmbedPlayer/mw.EmbedPlayer.js |
— | — | @@ -1370,8 +1370,11 @@ |
1371 | 1371 | if ( !this.skinName ) { |
1372 | 1372 | this.skinName = mw.getConfig( 'EmbedPlayer.SkinName' ); |
1373 | 1373 | } |
1374 | | - |
1375 | 1374 | |
| 1375 | + if( !this.monitorRate ){ |
| 1376 | + this.monitorRate = mw.getConfig( 'EmbedPlayer.MonitorRate' ); |
| 1377 | + } |
| 1378 | + |
1376 | 1379 | // Make sure startOffset is cast as an float: |
1377 | 1380 | if ( this.startOffset && this.startOffset.split( ':' ).length >= 2 ) { |
1378 | 1381 | this.startOffset = parseFloat( mw.npt2seconds( this.startOffset ) ); |
— | — | @@ -2895,7 +2898,7 @@ |
2896 | 2899 | } |
2897 | 2900 | |
2898 | 2901 | //mw.log( 'Monitor:: ' + this.currentTime + ' duration: ' + ( parseInt( this.getDuration() ) + 1 ) + ' is seek: ' + this.seeking ); |
2899 | | - if ( this.currentTime && this.currentTime > 0 && this.duration ) { |
| 2902 | + if ( this.currentTime >= 0 && this.duration ) { |
2900 | 2903 | if ( !this.userSlide && !this.seeking ) { |
2901 | 2904 | if ( parseInt( this.startOffset ) != 0 ) { |
2902 | 2905 | // If start offset include that calculation |
— | — | @@ -2945,7 +2948,7 @@ |
2946 | 2949 | if( !this.monitorInterval ){ |
2947 | 2950 | this.monitorInterval = setInterval( function(){ |
2948 | 2951 | _this.monitor(); |
2949 | | - }, 250 ) |
| 2952 | + }, this.monitorRate ) |
2950 | 2953 | } |
2951 | 2954 | } else { |
2952 | 2955 | // If stoped "stop" monitor: |
Index: branches/MwEmbedStandAlone/modules/EmbedPlayer/skins/mw.PlayerControlBuilder.js |
— | — | @@ -635,7 +635,7 @@ |
636 | 636 | return false; |
637 | 637 | } |
638 | 638 | // If the config is false |
639 | | - if( mw.getConfig( 'EmbedPlayer.OverlayControls' ) === false){ |
| 639 | + if( mw.getConfig( 'EmbedPlayer.OverlayControls' ) == false){ |
640 | 640 | return false; |
641 | 641 | } |
642 | 642 | |