Permalink
Browse files

Now enforcing the use of query-string style parameters on the <script…

…> node.

Setting the path to dependant files is now done in at the end of the "src"
attribute for the HtmlMedia.js file, query-string style! i.e. HtmlMedia.js?path=someFolder

Also, now there's an event that the developer can hook into in order to
be confident that <audio> and <video> nodes on the page are properly treated
before interacting with them. It's called "onready" and currently you can
define the name of a global function to call in the query-string src:
i.e. HtmlMedia.js?path=folder&onready=myinit
OR include a "onready" attribute on the <script> node. The content of the
attribute needs to be raw JavaScript, not the name of a function.
  • Loading branch information...
1 parent 17667a5 commit 36f5c1b2d76c268efdfb9e2ddb4f04ad7d75c9c2 @TooTallNate committed Apr 9, 2010
Showing with 345 additions and 179 deletions.
  1. +13 −4 HtmlAudio.htc
  2. BIN HtmlAudio.swf
  3. +193 −68 HtmlMedia.js
  4. +7 −0 HtmlVideo.htc
  5. BIN HtmlVideo.swf
  6. +6 −6 src/HTMLAudioElement.hx
  7. +50 −11 src/HTMLVideoElement.hx
  8. +3 −6 tests/canvas.html
  9. +73 −84 tests/tester.html
View
@@ -21,7 +21,8 @@
* THE SOFTWARE.
*/
<PUBLIC:COMPONENT NAME="HTMLAudioElement" LIGHTWEIGHT=true>
-
+ <PUBLIC:ATTACH EVENT="oncontentready" ONEVENT="__initialize()"/>
+
<PUBLIC:PROPERTY NAME="error" GET="errorGet" />
<PUBLIC:PROPERTY NAME="src" GET="srcGet" PUT="srcSet" />
<PUBLIC:PROPERTY NAME="currentSrc" GET="currentSrcGet" />
@@ -124,13 +125,21 @@
function mutedSet(v) {
this.__mutedSet(v);
}
+
+ function __initialize() {
+ if (this.al) {
+ this.al();
+ }
+ }
// Dispatches an HTML5 media event at the element.
function __fireMediaEvent(eventName)
{
- ev = createEventObject();
- this.__extendEvent(ev, arguments);
- events[eventName].fire(ev);
+ if (eventName in events) {
+ ev = createEventObject();
+ this.__extendEvent(ev, arguments);
+ events[eventName].fire(ev);
+ }
}
</SCRIPT>
</PUBLIC:COMPONENT>
View
Binary file not shown.
View

Large diffs are not rendered by default.

Oops, something went wrong.
View
@@ -21,6 +21,7 @@
* THE SOFTWARE.
*/
<PUBLIC:COMPONENT NAME="HTMLVideoElement" LIGHTWEIGHT=true>
+ <PUBLIC:ATTACH EVENT="oncontentready" ONEVENT="__initialize()"/>
<PUBLIC:PROPERTY NAME="width" GET="widthGet" PUT="widthSet" />
<PUBLIC:PROPERTY NAME="height" GET="heightGet" PUT="heightSet" />
@@ -44,6 +45,12 @@
function posterSet(v) {
this.__posterSet(v);
}
+
+ function __initialize() {
+ if (this.vl) {
+ this.vl();
+ }
+ }
</SCRIPT>
</PUBLIC:COMPONENT>
View
Binary file not shown.
View
@@ -59,9 +59,10 @@ class HTMLAudioElement extends HTMLMediaElement {
}
public function play() {
+ if (this.lastPosition == this.sound.length) this.lastPosition = 0;
this.channel = this.sound.play(this.lastPosition, 0, this.transform);
this.channel.addEventListener("soundComplete", this.channelComplete);
- this.playTimer = new Timer(250);
+ this.playTimer = new Timer(200);
this.playTimer.run = this.sendTimeUpdate;
}
@@ -102,10 +103,12 @@ class HTMLAudioElement extends HTMLMediaElement {
// Called when the sound finishes playing to the end (by SoundChannel's 'soundComplete' event)
private function channelComplete(e) {
+ //ExternalInterface.call("console.log", "channelComplete");
this.playTimer.stop();
this.channel.removeEventListener("soundComplete", this.channelComplete);
this.channel.stop();
- this.lastPosition = this.channel.position;
+ this.channel = null;
+ this.lastPosition = this.sound.length;
ExternalInterface.call("HTMLAudioElement.__swfSounds["+this.fallbackId+"].__endedCallback");
}
@@ -122,9 +125,6 @@ class HTMLAudioElement extends HTMLMediaElement {
private function soundId3(e) {
//ExternalInterface.call("console.log", e);
- //if (this.sound.id3["TLEN"]) {
- //var length : Float = Std.parseFloat(this.sound.id3.TLEN);
- //}
}
private function soundIoError(e) {
@@ -225,6 +225,6 @@ class HTMLAudioElement extends HTMLMediaElement {
"};",
"HTMLAudioElement.__swf = f('embed') || f('object');",
"})" ].join('') );
- ExternalInterface.call("HTMLAudioElement.__swfLoaded");
+ ExternalInterface.call("HTMLAudioElement.__swfLoaded");
}
}
View
@@ -28,11 +28,13 @@ import flash.external.ExternalInterface;
import flash.net.NetStream;
import flash.net.NetConnection;
import flash.media.Video;
+import flash.ui.ContextMenu;
+import flash.ui.ContextMenuItem;
class HTMLVideoElement extends HTMLMediaElement {
private var stream : NetStream;
private var connection : NetConnection;
- private var video: Video;
+ public var video: Video;
public function new(fallbackId:Int, src:String, volume:Float, muted:Bool) {
super(fallbackId, src, volume, muted);
@@ -52,10 +54,6 @@ class HTMLVideoElement extends HTMLMediaElement {
this.stream.soundTransform = this.transform;
}
- public function getVid() {
- return this.video;
- }
-
public function getCurrentImageData() {
try {
//var t1 : Float = Date.now().getTime();
@@ -87,50 +85,91 @@ class HTMLVideoElement extends HTMLMediaElement {
}
public function load(src:String) {
+ this.metadataSent = false;
this.stream.close();
this.stream.play(src);
+ this.stream.pause();
}
public function play() {
this.stream.resume();
+ this.playTimer = new Timer(200);
+ this.playTimer.run = this.sendTimeUpdate;
+ }
+
+ private function sendTimeUpdate() {
+ ExternalInterface.call("HTMLVideoElement.__vids["+this.fallbackId+"].__fireMediaEvent", "timeupdate");
}
public function pause() {
+ this.playTimer.stop();
this.stream.pause();
}
// Event Listeners
public function onMetaData(metadata) {
- ExternalInterface.call("HTMLVideoElement.__vids["+this.fallbackId+"].__metadataCallback", metadata.duration, this.video.videoWidth, this.video.videoHeight);
+ if (!this.metadataSent) {
+ ExternalInterface.call("HTMLVideoElement.__vids["+this.fallbackId+"].__metadataCallback", metadata.duration, this.video.videoWidth, this.video.videoHeight);
+ this.metadataSent = true;
+ }
}
public function onPlayStatus(playStatus) {
ExternalInterface.call("console.log", "playStatus");
}
// Static Stuff
+ /**
+ * The single HTMLVideoElement that this SWF displays.
+ */
public static var videoElement : HTMLVideoElement;
+ /**
+ * Instantiate a custom ContextMenu and set it to the
+ * current Stage. Should contain Play/Pause, Mute/Unmute,
+ * and a Full-Screen button.
+ */
+ public static function initContextMenu() {
+ var contextMenu : ContextMenu = new ContextMenu();
+ contextMenu.hideBuiltInItems();
+ var label : ContextMenuItem = new ContextMenuItem("HtmlMedia <video> Player");
+ contextMenu.customItems.push(label);
+ flash.Lib.current.contextMenu = contextMenu;
+ }
+
+ /**
+ * Every time the SWF is resized on the page (through CSS, etc.),
+ * we need to resize the video to maximize the stage, while still
+ * constraining porportions.
+ */
public static function onResize(e:Event) {
- ExternalInterface.call("console.log", "Stage resized: " + flash.Lib.current.stage.stageWidth + " x " + flash.Lib.current.stage.stageHeight);
+ var s:Float = Math.min(flash.Lib.current.stage.stageWidth / videoElement.video.videoWidth, flash.Lib.current.stage.stageHeight / videoElement.video.videoHeight);
+ videoElement.video.width = s*videoElement.video.videoWidth;
+ videoElement.video.height = s*videoElement.video.videoHeight;
+ videoElement.video.x = (flash.Lib.current.stage.stageWidth / 2) - (videoElement.video.width / 2);
+ videoElement.video.y = (flash.Lib.current.stage.stageHeight / 2) - (videoElement.video.height / 2);
}
public static function main() {
var flashvars : Dynamic<String> = flash.Lib.current.loaderInfo.parameters;
videoElement = new HTMLVideoElement(Std.parseInt(flashvars.id), flashvars.src, Std.parseFloat(flashvars.volume), flashvars.muted.toLowerCase() == "true");
- flash.Lib.current.addChild(videoElement.getVid());
+ flash.Lib.current.addChild(videoElement.video);
+ initContextMenu();
flash.Lib.current.stage.scaleMode = StageScaleMode.NO_SCALE;
flash.Lib.current.stage.addEventListener(Event.RESIZE, onResize);
ExternalInterface.addCallback("__load", videoElement.load);
- ExternalInterface.addCallback("__getCurrentTime", videoElement.getCurrentTime);
- ExternalInterface.addCallback("__setCurrentTime", videoElement.setCurrentTime);
- ExternalInterface.addCallback("__getImageData", videoElement.getCurrentImageData);
ExternalInterface.addCallback("__play", videoElement.play);
ExternalInterface.addCallback("__pause", videoElement.pause);
+ ExternalInterface.addCallback("__setMuted", videoElement.setMuted);
ExternalInterface.addCallback("__setVolume", videoElement.setVolume);
+ ExternalInterface.addCallback("__getCurrentTime", videoElement.getCurrentTime);
+ ExternalInterface.addCallback("__setCurrentTime", videoElement.setCurrentTime);
+ ExternalInterface.addCallback("__getImageData", videoElement.getCurrentImageData);
+
+ // Everything on the Flash side in initialized, notifiy the page:
ExternalInterface.call("HTMLVideoElement.__vids["+flashvars.id+"].__swfInit");
}
}
View
@@ -18,10 +18,8 @@
</style>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/prototype/1.6.1.0/prototype.js"></script>
<script type="text/javascript" src="../swfobject.js"></script>
- <script type="text/javascript" src="../HtmlMedia.js"></script>
+ <script type="text/javascript" src="../HtmlMedia.js?path=.." onready="init();"></script>
<script type="text/javascript">
- // Set the path for `HtmlMedia` dependant files
- HTMLMediaElement.setPath("..");
function timerCallback() {
if (video.paused || video.ended) {
@@ -48,7 +46,7 @@
ctx2.putImageData(frame, 0, 0);
}
- document.observe("dom:loaded", function() {
+ function init() {
video = $("video");
c1 = $("c1");
ctx1 = c1.getContext("2d");
@@ -57,8 +55,7 @@
video.observe("play", function() {
timerCallback();
});
- });
-
+ }
</script>
</head>
<body>
Oops, something went wrong.

0 comments on commit 36f5c1b

Please sign in to comment.