Chrome’s Flash Player Trickiness

August 2nd, 2010

If you’re like me and do debug testing of your Flash and Flex apps in Google Chrome, you may have already run into this, or you may soon if you update Chrome or have to reinstall it. I was upgrading my machine to Windows 7 and reinstalling everything, including Google Chrome and the Flash 10.1 debug player. However, when I tried to debug my projects in Flash Builder, I could not get it to connect to the debugger. I even tried reinstalling the debug player. However, when I went to a site that would tell whether or not you had the debug player, it said I didn’t. What the heck?

I found the answer here:
http://www.timo-ernst.net/2010/04/chrome-flash-debugger-not-connecting-to-flexflash-builder/comment-page-1/#comment-11203. The gist of it is that Google Chrome, trying to be helpful, already has a version of Flash Player installed. It is not a debug version. Unfortunately, it trumps any version you try to install, so you have to go in and manually disable the Chrome Flash Player so that it will use your debug version. Not cool.

LiveStreamCast 1.0

February 2nd, 2010

If you want an easy Edge-Origin video streaming application for Flash Media Server, you may be in luck. Adobe is now making available the LiveStreamCast application on its FMS Software Tools page. LiveStreamCast handles all the server-side logic necessary for both 2-tier (Edge-Origin) and 3-tier (Edge-Intermediate-Origin) deployments. This means that you can spread your licensed number of connections, as well as bandwidth usage, between several different Flash Media Servers.

I downloaded the app and took it for a spin. It is easy enough to deploy in its unmodified form for an Edge-Origin deployment. I got that working both locally on my machine and between my locahost and my office’s FMS. After playing with it for a while, I was not able to get it working in an Edge-Intermediate-Origin deployment. I’m not entirely sure of the benefit of that deployment anyway, unless you have a tremendous number of users.

Here’s the pros and cons that I see:

Pros:

  • Ready-made, easy-to-deploy FMS application for complex Edge-Origin deployments
  • Handles multiple Origins for a single stream, including both backup servers and multiple server groups of primary and backup servers
  • Handles failover by maintaining a table of servers, managing reconnects after idle timeouts, and putting failed servers at the bottom of the connection table
  • Possibly usable for 3-tier deployments
  • Does work with FMLE.
  • Does logging.

Cons:

  • Can’t use the standard publish() and play() methods. You have to use call() to utilize the server-side API for these tasks.
  • Client has to implement responder methods for calls made by the server (onFCPublish
  • Seems a bit temperamental. I had to restart my server several times when using their testing app until I got the settings just right. The app would start rejecting connections if I did things in the wrong order.  This was fixed by skipping the intermediate deployment, so that app may be the culprit (or just wrong settings I fed in).
  • Dynamic streaming is unsupported. L
  • Application doesn’t work with servers that are configured otherwise to be Edge/Origin servers. I dunno what that other means is.
  • Each non-Origin server in the setup requires an empty application folder called monitor, which is messy, but otherwise harmless. It can be renamed with changes to the ASC files.

One other note I’d put out there is that you cannot use FMLE and the test application included with the server application. Both apps automatically grab your camera, and if one grabs for it while the other is using it, the second app crashes. If the test app is second, it crashes Flash very well.

I’ve not put it through its paces, but it seems like if you’re comfortable putting in the effort to customize your player to accommodate the different server connection API, LiveStreamCast could make your life easier. And if it is between having to rework a NetConnection setup and having to write a complex app in server-side ActionScript, I’ll take the former easily.

Frame Scripts Ignored When Exported to Flash Builder

February 1st, 2010

I wonder if anyone can explain what’s going on here. I’m running into an issue where frame scripts for clips created in the Flash IDE are getting ignored when the clip is brought into Flash Builder. This wasn’t happening with all the components in the skin file, only one particular one. It looked like it was being created the same. The properties were set up the same as other symbols. The component had a defining class that was in the library of the Flash Builder project.  There were no warnings or compiler errors. The problem was, when I’d test the component in the Flash IDE, it would work just fine. When I’d load it into an app made in Flash Builder, it would ignore the stop(); frame script and cruise on through the animation.

I tried a lot of things, which I’ll spare you the details of. I tried stuff with loader context and application domain and more. What ended up working was to set the base class for the component to the class in the application source, rather than having it as the primary class for the component. I then set the class for the component to be an auto-generated class. That did the trick and included the frame scripts. I don’t fully understand why this works, but it must be something about the auto-generated class bringing in the frame scripts, and the custom class ignoring them. All I know is I’m glad to not have to do some kludge with enter frame events.

Microsoft Surprise

January 18th, 2010

Sometimes, Microsoft can surprise you by doing something really cool. I’ve been taking notes in Microsoft’s OneNote. I’m documenting a process with screenshots and text, pasting the screenshots right into the body of the document. I wanted to find something in my text notes, so I did a search in the document. It found matches in the screenshots!!! And it highlighted them too! That, my friends, is pretty darn slick. Probably other folks know about this, but I thought I had to mention it.

Timeline Instances and ActionScript 3

November 17th, 2009

I’ve been doing a little bit of work that requires the mixing of the timeline and ActionScript 3. I quickly ran into a problem where when I would tell my movie clip to gotoAndStop at a particular frame, I couldn’t then access the instance I had put on the stage in that frame. It would come back null. After some digging, I ran across people talking about how that even though you have called gotoAndStop, the actual frame hasn’t changed yet. So I then put a listener for the ENTER_FRAME event, and tried to access the instance on the stage then. That still didn’t work. It makes sense. The ENTER_FRAME event is fired when you enter the frame (durrr), so the assets on the stage haven’t rendered yet.

Unfortunately, there is no exit frame or frame complete event that I saw in the API. So the first solution I came up with to solve this problem, was simply to listen on ENTER_FRAME until the instance I had put on the stage wasn’t null. Then I would remove the listener and get my reference to the instance so I could act on it. It looks something like this:

public function set dir( value:String ):void
{
_dir = value;
if ( _dir )
{
gotoAndStop( _dir );

addEventListener( Event.ENTER_FRAME, _onEnterFrame );
}
}

private function _onEnterFrame( event:Event ):void
{
if ( characterClip )
{
removeEventListener( Event.ENTER_FRAME, _onEnterFrame );
if ( _walking )
{
characterClip.gotoAndPlay( WALK );
}
else
{
characterClip.gotoAndStop( REST );
}
}
}

public function get characterClip():MovieClip
{
return getChildAt( 0 ) as MovieClip;
}

However, that just felt a bit inelegant. I don’t like listening on ENTER_FRAME, as it has the potential to fire forever. Unfortunately, the doLater method is only in Flex. So, I tried out a different solution. I made the instances on the timeline be instances of a TimelineClip class. This class adds on the functionality of dispatching an event when they are instantiated. This way I know they are available. I made the event the class dispatched bubble, so the containing clip knows that its internal clips are ready without having to put a listener on them. The TimelineClip class looks like this:

package com.turbidwater.worldExplorer.view.sprites
{
import flash.display.MovieClip;
import flash.events.Event;

public class TimelineClip extends MovieClip
{
static public const INSTANTIATED:String = 'instantiated';

public function TimelineClip()
{
super();

dispatchEvent( new Event( INSTANTIATED, true ) );
}
}
}

And on the class that contains the timeline, I put this:
public function Character()
{
addEventListener( TimelineClip.INSTANTIATED, _onTimelineClipAvailable );
}

private function _onTimelineClipAvailable( event:Event ):void
{
if ( _walking )
{
characterClip.gotoAndPlay( WALK );
}
else
{
characterClip.gotoAndStop( REST );
}
}

There are two things I don’t like about this. One is that each of my timeline instances have to use this as their base class, which means there are more classes, including those default classes Flash makes for library symbols. The other is that when the animated state I’m going to is the same as the one I am on, the TimelineClip doesn’t fire the INSTANTIATED event. So I have to put in two places the code for what I want done when the clip is available. Is that worse than listening for ENTER_FRAME? I dunno. If there is a better way to do it, I’d be interested to know.

Can’t Hit a Moving Target

November 7th, 2009

I was helping a buddy debug a problem with a game he is making in ActionScript 3 and Flash when we came upon a puzzling problem. He had some balloons that were rising that popped when you clicked on them. However, the problem was that when you clicked on them, sometimes the click event would fire and sometimes it wouldn’t. I thought that maybe something could be getting in the way and blocking the click events, but when I put a listener on the document class listening for click events in the capture phase, it still wouldn’t fire. Since that should trap every mouse click in the application, that meant, for some reason, click events weren’t getting broadcast sometimes.

I added in listeners for other mouse events. MouseEvent.MOUSE_DOWN was the only mouse event firing. What the heck? I tried looking at the Flash assets to see if anything hinky could be going on there with the insides of the balloon MovieClip. Nothing. But I was on the right track. Finally, I turned mouseChildren to false on the balloon and everything worked as expected. The mouseChildren property determines whether or not the assets inside a movie clip can receive mouse interactions.

Now, I still don’t know why this was intermittently causing the click event to not fire. It’s not that we were listening on the wrong target. The click event was never getting fired at all, or else the document class would have heard it in the capture phase. It must have something to do with the objects moving and how a click is differentiated from other mouse interactions. But now I know that when you have an asset that has child sprites or movie clips that don’t require interaction, mouseChildren needs to be turned off. NO MICE FOR YOU KIDS!!!!

The Trouble With Whitespace: “XML or text declaration not at start of entity”

October 28th, 2009

I was switching some XML services from one ColdFusion server to another, which was ColdFusion 9. For some reason, the services wouldn’t provide valid XML. In Firefox I was receiving an error telling me “XML or text declaration not at start of entity.” (Chrome gave me “XML declaration allowed only at the start of the document”.) I could look at the source and see that Firefox was telling me the truth. In front of the XML document header, there were a couple lines and a few tabs. But where the heck was that extra space coming from? The context of the problem told me it had to be some server setting. But what was it? I tried some Googling, but came up with nothing about ColdFusion server settings. I looked through the server settings for something like serving up the wrong kind of MIME type, or the prepending of some weird header. Nothing. Finally, after asking someone for help, I thought to just look at Server Settings > Settings. There was the Enable Whitespace Management option. It was unchecked. I checked that and submitted the new settings and everything was right as rain.

I’m still not sure where the extra spaces were coming from. I was taking a native CF object and converting it to XML. There shouldn’t have been any extras inserted. Bleh. I would think this option would be on by default. Go figure.

Strict Policies

October 5th, 2009

A brutal Friday night spent troubleshooting policy files for a client has left me rather peeved and ticked off. First off, if you haven’t done a cross-domain policy file in a while, you’ll need to take a look at this article about the policy file changes in Flash Player 9 & 10. It is not the easiest read, and currently lacks a sample policy file. So let me post one here, which I ended up making from one I found on FlashKit:

<?xml version="1.0"?>
<!DOCTYPE cross-domain-policy SYSTEM "http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd">
<cross-domain-policy>
<site-control permitted-cross-domain-policies="master-only" />
<allow-access-from domain="*" to-ports="80,3000" />
<allow-http-request-headers-from domain="*" headers="*"/>
</cross-domain-policy>

For me, the thing I was missing was the DTD. The thing that kills me is that the LiveDocs on the subject are out-of-date and wrong. Also, I couldn’t get the policy file debugging to work on my computer, making it hard to use any of the helpful aids in the Adobe article. So watch out! Cross-domain policy files are incredibly stricter in Flash Player 9 & 10 than they have been before.

Loading Modules: When a Class Doesn’t Equal Itself

July 29th, 2009

In working on a project that involves a whole lot of Flex modules, I was running into a weird RTE where Flex was telling me that it could not convert a class to the same type of class:
Type Coercion failed: cannot convert my.package.MyClass@32a73ae1 to my.package.MyClass
Well, that’s annoying. It’s the same class! How can you not convert a class to its own type? I tracked down a solution for using the Loader class, but it used the LoaderContext class, which the ModuleLoader class lacks. It does have an applicationDomain property, but after some initial efforts, I couldn’t get that to work. I found that there is a quick and dirty solution where you can just import the class into the parent application and all is well … until you try to load the modules into a parent app that doesn’t have the same code base and lacks those classes.

I ran into that problem and returned to trying to figure out the applicationDomain deal. Very fortunately for me, I found an incredibly helpful post from Richard Lord that details the problems with setting the applicationDomain on a ModuleLoader, as well as a couple solutions. The solution that worked for me was setting the applicationDomain property of the ModuleLoader in the preinitialize event handler to ApplicationDomain.currentDomain. Thanks Richard!

The Hidden Properties: Constructor and Prototype

June 16th, 2009

So, I had a situation where I was receiving an object of an unknown class type and I needed to make a copy of it. Because it had read-only properties that were set through the constructor, I couldn’t just create my copy through ObjectUtils. I had seen many times in the Live Docs a listing for a public property called constructor. It’s public and originates on Object, so everything should have it. Looking at the documentation, it looked like I could use it to instantiate another instance of the same class as the mystery class type.

In this instance, I had was dealing with classes that extended Event. In the documentation, constructor is listed as a public property that is inherited from Object. The prototype property is the same way. However, whenever I tried to access the constructor property on my extended class, the Flex compiler would pitch a fit. It certainly wasn’t coming up in the code hinting. Hmm. So I tried to access it on an instance of a straight up Event. It didn’t come up in the code hinting, but it did compile. Hmm again.

With some prompting from John, I tried accessing it on my extended classes using square bracket notation: myEvent['constructor']. That worked. It is a mystery to me why I can access it through square bracket notation, but it won’t come up in code hinting or compile, but it can compile for Event. Anyway, here’s what I did to make a new instance of an existing class instance:

var constructorMethod:Object = mysteryEvent[ 'constructor' ];
var newEvent:MyEvent = new constructorMethod( type );
for( var i:String in mysteryEvent)
{
newEvent[ i ] = mysteryEvent[ i ];
}