views:

69

answers:

4

Hi everyone, once again I'm getting plagued by the dreaded Flash error: Cannot access a property or method.

I'm building a new video player and I need to send the total width of my progress bar(created in PlayerControls.as) to my VideoPlayer.as class. As well as control the width of the progress bar from an update function inside my VideoPlayer.as class.

I'm not able to get these values in my VideoPlayer class, I'm wondering if it has anything to do with the order of which I call these classes in my Document class:

Document Class

package {
// IMPORTS

public class TEN extends Global {

    //private consts
    //private vars

    public function TEN():void {
        if (stage) {
            init();
        } else {
            addEventListener(Event.ADDED_TO_STAGE,init);
        }
    }

    private function init(e:Event=null):void {
        removeEventListener(Event.ADDED_TO_STAGE,init);
        // Using the BulkLoader class to phrase XML
    }

    private function onBulkLoadComplete(e:Event):void {
        trace("[BulkLoader] COMPLETE"+"\r");

        Global.xml=loader.getXML("xmldata");
        // I get XML values
        // XML info goes into ARRAYS here

        drawBackground();
        drawVideo();
        drawControls();
    }
    // Background.as
    private function drawBackground():void {
        trace("\r"+"          drawBackground();");
        trace("------------------------------");
        bg=new Background  ;
        bg.drawBackground(globalWidth,globalHeight,firstTitle);
        stage.addChild(bg);
    }
    // VideoDisplay.as
    private function drawVideo():void {
        trace("\r"+"          drawVideo();");
        trace("------------------------------");
        vd=new VideoDisplay  ;
        vd.drawVideo(globalWidth,globalHeight,videoName,videoHDiff,limeLight);
        vd.x=videoX;
        vd.y=videoY;
        stage.addChild(vd);
    }
    // PlayerControls.as
    private function drawControls():void {
        trace("\r"+"          drawControls();");
        trace("------------------------------");
        pc=new PlayerControls  ;
        pc.drawControls(globalWidth,globalHeight,HEX,specialCheck,specialText,specialUrl);
        pc.x=videoX;
        pc.y=controlsY;
        pc.addEventListener("onPlay",vd.playVideo);
        pc.addEventListener("onPause",vd.pauseVideo);
        stage.addChild(pc);
    }

    private function onBulkLoadProgress(e:BulkProgressEvent):void {

        //trace(e.weightPercent);
    }
}

}

PlayerControls.as

package src.ui
{
// IMPORTS

public class PlayerControls extends MovieClip
{
    // private consts
    // private vars

    public var progressBar:MovieClip;
    public var progressTotalW;

    public function PlayerControls():void
    {
        if (stage) init();
        else addEventListener(Event.ADDED_TO_STAGE, init);
    }

    private function init(e:Event = null):void {            
        removeEventListener(Event.ADDED_TO_STAGE, init);
    }

    public function drawControls(w, h, color, specialCheck, extraTxt, extraLink):void
    {           
        // SET VALUES w,h,color, etc...

        vd = new VideoDisplay(); // <-- VideoDisplay Class

        // I create graphics

        // I add graphics


        createSpecialBtn(); // Create special button
    }

    // Create Special Button ·······································
    public function createSpecialBtn():void
    {
        // other code
        fullscreenCreate(btn_SpecialW); // Create FullScreen Button
    }

    // Create Fullscreen Button ·····································
    public function fullscreenCreate(extraW):void
    {
        // other code
        createSoundBtn(btn_Fullx); // Create Sound Button
    }

    // Create Sound Button ·····································
    public function createSoundBtn(xSpacer):void
    {
        // other code           
        createTimeCounter(timeCountX); // Create Time Clock
    }

    // Create Time Count ·····································
    public function createTimeCounter(spaceX):void
    {           
        // other code           
        createGroove(); // Create progress bar background
    }

    // Create Groove Bar ············································
    public function createGroove():void
    {
        // Here we go!
        groove       = new Groove();
        groove.width = grooveW;
        groove.x     = grooveX;
        groove.y     = grooveY;


        progressTotalW = grooveW;
        //trace("grooveW = "+grooveW);
        //trace("progressTotalW = "+progressTotalW);

        vd.setProgressW(progressTotalW);

        createProgress();
    }

    // Create Progress Bar ··········································
    public function createProgress():void
    {
        progressBar       = new ProgBar;
        TweenLite.to(progressBar, .1, {tint:xmlColor});
        progressBar.x     = grooveX;
        progressBar.y     = grooveY;
        progressBar.width = 1;

        //trace("progressBar.x = "+progressBar.x);
        //trace("progressBar.y = "+progressBar.y);

        controls.addChild(groove);
        controls.addChild(progressBar);
    }

    // BUTTON EVENTS here

}

}

VideoDisplay.as

package src.display
{
// IMPORTS

public class VideoDisplay extends PlayerControls
{
    // Variables...
    private var pc:PlayerControls;

    public function VideoDisplay():void
    {
        this.addEventListener(Event.ADDED_TO_STAGE, stageListens);
    }

    //¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ NetStream Check
    private function netStatusHandler(event:NetStatusEvent):void {

        switch (event.info.code) {
            //case "NetConnection.Connect.Success": ... etc
        }
    }

    //¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ Error Handling
    private function asyncErrorHandler(event:AsyncErrorEvent):void {trace(event.text);}
    private function onBWDone(...args):void {}
    private function onXMPData(infoObject:Object):void {}

    //¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ Declare MetaData     
    function getMetaData(client_ns) {
        // Meta data
    }

    // ☼ --------------------------------------------------------------------------------- Connect to Stream
    public function connectStream():void 
    {   
        // NetStream code
    }

    public function drawVideo(w, h, flvUrl, minusHeight, LL):void
    {
        sizeW     = w;
        sizeH     = h;
        flvSource = flvUrl;
        appName   = LL;

        pc        = new PlayerControls();  // <- PlayerControls.as

        // RTMP - ns - nc CODE

        // draw graphics

        // Timer
        tmrDisplay = new Timer(DISPLAY_DELAY);
        tmrDisplay.addEventListener(TimerEvent.TIMER, updateDisplay); // <--

        // addChilds
    }

    public function playVideo(e:CustomEvent = null):void
    {
        // play function
    }

    public function pauseVideo(e:CustomEvent = null):void
    {
        // pause function
    }

    // Getter & Setter
    public function setProgressW(setMe):void
    {
        progressTotalW = setMe;
        ajoyTest = setMe;
        trace("Getter & Setter - progressTotalW = "+progressTotalW);

        /*tmrDisplay = new Timer(DISPLAY_DELAY);
        tmrDisplay.addEventListener(TimerEvent.TIMER, updateDisplay);*/
    }

    private function updateDisplay(e:TimerEvent):void
    {
        //trace("ns.time * 287 / videoDuration = "+(ns.time * 287 / videoDuration));
        //pc.progressBar.width = ns.time * pc.progressTotalW / videoDuration;
        //trace("ns.time = "+ns.time);
        //trace("videoDuration = "+videoDuration);
        trace("ajoyTest = "+ajoyTest);
        trace("progressTotalW = "+progressTotalW);
    }

    // Other functions

}

}

^ for some reason I can't target the progressBar.width inside of PlayerControls.as

Any help or tips on this would be appreciated! UPDATE: Thanks for the insightful comments and answers everyone! Understanding how to properly instance a Class to be used by multiple Classes has just opened up my AS3 flexibility that much more :)

+1  A: 

Try changing the order in which you call addChild and progressBar.width. Also make sure that PlayerControls are added to the stage when createProgress is called.

UPDATE

Sorry I misunderstood the problem. So it's this line that's causing the grief

pc.progressBar.width = ns.time * pc.progressTotalW / videoDuration;

The order in which you have the functions listed is not relevant but the order in which you call them. I think the problem is in your Timer. I don't see the code that executes it but I would guess that the first event dispatch from Timer to VideoDisplay comes before the PlayerControls are created, or before the progressBar inside PlayerControls is created.

If this doesn't solve the issue can you please post the code for both the call order of the init functions (drawVideo,drawControls), the constructors for both those classes and the Timer init code. From what you have up there I can't say more because I can't work out the control flow.

Matti
Tried that, updated code also I have a listener for the Stage, no luck however :/ still getting errors when the VideoDisplay.as updateDisplay function runs...
Leon
Can you post the progress bar class as well.
Matti
There is no progressBar class, pc is the PlayerControls class and progressBar is the movieClip created inside it
Leon
Hey yeah I think that is the issue, I will try re-ordering when I call the functions, updated the code above to show more btw! :)
Leon
+1  A: 

Where are you actually passing a reference to PlayerControls to VideoDisplay? As far as I can tell from your code, your not. You need to set that before you try to access it.

so something like:

myVideoDisplay.pc = myPlayerControls

perhaps I'm just missing something though...

Tyler Egeto
I have that at the the drawVideo function pc = new PlayerControls();
Leon
But that's in a different class. You can't access the pc in DocumentClass from VideoPlayer. You have to pass the pc object reference to VideoPlayer before you access it.
Matti
progressTotalW I set to 0 in PlayerControls, then when I trace it in VideoDisplay it's always 0 and not 287 which it turns into later in PlayerControls
Leon
Are you positive you are sharing the reference with the other Classes? A class is liked a "closed box" it has no idea what is going on outside of itself, you need to share the reference to PlayerControls with it by passing it in.
Tyler Egeto
+1  A: 

You are creating instances of VideoDisplay and PlayerControls in the DocuementClass. That is fine. But unless you are passing a reference of the PlayerControls object "pc" to the VideoControls class, there is no way that the ViedoControls class can know what to do with pc. You need to post more of your code to show the order in which the drawVideo and drawControls methods are being fired.

You probably need to something like in your document class:

drawVideo();
drawControls();
vd.playerControls = pc;
pc.videoDisaply = vd;

Then change the

private var pc:PlayerControls;
to
public var playerControls:PlayerConrols;

And of course change

pc.progressBar.width = ns.time * pc.progressTotalW / videoDuration;
to
playerControls.progressBar.width = ns.time * playerControls.progressTotalW / videoDuration;

Same changes for VideoDisplay as well. Change to public var, change name, and change references with the vd name. The reason I suggest changing the names of the variables inside the VideoDisplay and PlayerControls classes is because this looks ugly to me:

vd.pc = pc
pc.vd = vd

Yeah, that it your problem. When you have

pc=new PlayerControls;

in your DocumentClass, you are creating a new instance of PlayerControls and storing it as pc in the DocuemntClass. So, if you ask the DocumentClass what pc is, it will say: "it is an instance of PlayerControls I hae stored".

Then, in VideoDisplay you do the same thing

 pc        = new PlayerControls();  // <- PlayerControls.as

This does NOT reference the same PlayerControls DocumentClass has. You are saying, create a new instance of PlayerControls and save it in VideoDisplay. Now they are two different instances. The solution I wrote above should work for you.

sberry2A
@Leon. You should not use variable names that are the same as your class names. So, don't do `vd.PlayerControls`, do `vd.playerControls`. Also make sure playerControls and videoDisplay are public variables.
sberry2A
Ok. Change `public var vd:VideoDisplay;` in the PlayerControls class to `public var videoDisplay:VideoDisplay;` then anywhere inside PlayerControls where you are referencing vd, change it to videoDisplay.
sberry2A
Leon
+1  A: 

Try changing these two lines and see if that gets you further.

pc.addEventListener("onPlay",vd.playVideo);
pc.addEventListener("onPause",vd.pauseVideo);

to

pc.addEventListener("onPlay",function(e) { vd.playVideo() });
pc.addEventListener("onPause",function(e) { vd.pauseVideo() });
Preston
Hey that code works also in place of the original, is there better performance with the function(e) added?
Leon