Copy link to clipboard
Copied
I recently switched from a FLVPlayer to a plain flash.media.Video object to play rtsp VOD streams. But to get the 'play.complete' event to work I had to jump through hoops for days. This code finally works, but I still have questions.
Problem 1. to get the stream to throw 'complete' you must make a CustomClient class that defines onPlayStatus
// video1 is on the stage already
// from main timeline
stream = new NetStream(connection);
stream.client = new CustomClient();
video1.attachNetStream(stream);
stream.play("mp4:myVideo.mp4");
//then in the CustomClient.as class define
public function onPlayStatus(info:Object):void {
trace("onPlayStatus: code: "+info.code); // output NetStream.Play.Complete
}
Question: Who is actually calling the onPlayStatus method and passing info:Object? Is it the NetStream? If stream already knows the name of my method why isn't it defined in the NetStream class to begin with? I dont understand the purpose of assigning stream.client
Problem 2. The CustomClient class does not have access to the maintimeline.
On the maintimeline I define a variable and a function to handle a playlist
// main timeline
var nowPlaying:Number = 0;
function change_video (playListNum:Number) {
// play another video fron the playListArray
}
But whe the CustomClient class calls the complete method the maintimeline elements are not available
// from CustomClient class
public function onPlayStatus(info:Object):void {
change_video(nowPlaying++);
}
1120: Access of undefined property nowPlaying
1180: Call to a possibly undefined method change_video
I tried using stage, but stage is also undefined in the class
trace (stage.nowPlaying);
1119: Access of a possibly undefined property nowPlaying through a reference with static type flash.display:Stage
I finally passed a reference of stage from the maintimeline to the CustomClient class
// from main time line
stream.client = new CustomClient(this.stage);
// class constructor
private var _main;
public function CustomClient (_stage){
_main= _stage.getChildAt(0); // first child of stage is mainTimeline
trace("_main: "+_main); // returns '_main: [object MainTimeline]'
}
public function onPlayStatus(info:Object):void {
_main.change_video(_main.nowPlaying);
} // This works!
Notice that _stage by itself is useless. It does not contain your stuff. _stage.firstChild is the maintimeline
Questions: Why aren't variables and functions available to the class below them? (I am new to OOP)
Why is the stage not accessible inside a class
Why are things not available on the stage? You need to use stage.firstChild to get to the timeline. I have never seen this mentioned in any of the AS3 documentation.
Thanks for your answers
Ted
You may have overcomplicated things for yourself. With AS2, the stream's client was implied to be 'this', and so things like onMetaData events, and others, could be trapped by functions that are right there next to your other routines. If your AS3 video creation lines are in the maintimeline, you could say:
stream.client = this;
and then the functions could be on the maintimeline too, where they would have access to everything you mentioned.
For the general problem of a class knowing about the main
...Copy link to clipboard
Copied
You may have overcomplicated things for yourself. With AS2, the stream's client was implied to be 'this', and so things like onMetaData events, and others, could be trapped by functions that are right there next to your other routines. If your AS3 video creation lines are in the maintimeline, you could say:
stream.client = this;
and then the functions could be on the maintimeline too, where they would have access to everything you mentioned.
For the general problem of a class knowing about the maintimeline, you can either pass in a reference when you create the class, for example, if you did do a custom client class to handle your maintimeline stream, you could say:
stream.client = new CustomClient(this);
and in the CustomClient class you would store the reference passed in. Or you can most times get away with looking at root. Like this (inside the class):
var maintimeline:MovieClip = MovieClip(root);
maintimeline.DoSomeMaintimelineFunction();
Copy link to clipboard
Copied
Wow, thanks Colin. "this" is a wonderful solution. It solves the whole onComplete-in-a-class problem in one word.
It also provides a perfect reference to pass to classes as well as movieclips components buttons, etc
I still wonder why 'video' is like an AS2 object and doesn't incorporate a normal AS3 onComplete or onPlayStatus event listner
thanks again
Ted
Copy link to clipboard
Copied
Because we say
import flash.net.NetStream;
does this mean it is an AS2 package??
is that the difference between
import fl.*
and
import flash.*
Copy link to clipboard
Copied
No, sometimes you're import fl things, and other times you're importing flash things. It doesn't mean it's AS2.
As for the event functions, those get called when they happen. I suspect that doing the more usual addEventListener approach doesn't work out, you can't attach a listener to a netstream, and so instead you tell the netstream where the functions are (using the client property) that it will need to call.
Copy link to clipboard
Copied
Well netstream seems to be a mutant hybrid because you can add event listeners like these
stream.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler);
stream.addEventListener(AsyncErrorEvent.ASYNC_ERROR, asyncErrorHandler);
but for onMetaData, onCuePoint and onPlayStatus you must pass the client reference.
A bit confusing.
Copy link to clipboard
Copied
"mutant hybrid"... no wonder I get on well with AS3.
Copy link to clipboard
Copied
Perhaps that was a bit harsh, but it does seem to have each foot in a different language. Thanks for helping me figure it all out.