Category: Flash

  • Flash on an iPhone in Quicktime?

    Posted this over at the Flashlite group on Google Groups. Re-posting here.

    Good news and bad news.

    The good news is, Gary Rosenzweig at Developer Dispatch ported some of his Flash 5 games to work in Quicktime. Quicktime, the player, actually has a series of tracks or “layers” that can be baked into a .mov file. So, he apparently got a bunch of these to successfully work in Quicktime embedded in Safari, the web browser that the iPhone will use.

    The Bad news is, I remember JD reporting that Apple turned this off last September. While he says it’s Flash 3, Gary’s saying it’s Flash 5. Either way, if you’ve ever seen how complicated it is to futz with Quicktime settings, then you know there is no way in heck a consumer is going to turn this on, especially on an iPhone.

    Straight ghetto, but Flash 5 is better than no Flash. Furthermore, you can depend on Quicktime actually being there on the iPhone… I think. Anyway, nothing official yet.

  • No One Likes Our Flash Video Codecs

    No Flash on iPhone

    For the record, “reports coming out” is not a valid citation.

    h.264? Give me a break. Hey, look ma, that’s On2… DROPPING THE F’ING BALL! Or maybe Adobe? Who’s accountable? Who cares? I do!!!!11

    I wish we could get a solid response instead of all of these uncited rumors. Regardless, I can no longer take the suspense, and am going to put a bullet in my head. The good news is, I do a decent Peter Petrelli impression, and I’ve briefly been around Claire (stole the ho’s glowsticks at a club). So, when someone gets an iPhone with Flash running on it, take the bullet out of my head and I’ll wise fum ma gwave to code another day!

  • Flex Controlling Flash

    Preface

    This article focuses on controlling applications written Flash Player 8 and below that are loaded into Flex at runtime. If you want to read up on the various ways of doing this, I’ve written in the past how to control Flash Player 8SWF’s in Flash Player 9’s new AVM. This article specifically will talk about using Flash Player 8 content in a Flex 2 environment.

    Before you read further, I strongly suggest you beg those in charge to allow you to re-write the AS2 content in AS3 (Flex 2 or Flash CS3). If that fails, keep reading.

    Use Cases

    Here are some common use cases where one would want to load Flash content into Flex content:

    1. You have some existing Flash content that was previously written for a Flash Player before 9 (8, 7, or 6). This content could be a fully functioning application that has already proven itself by working successfully for awhile. Therefore, you’d like load it in atruntime and let it do it’s thing. There is no time, budget, and/or resources to re-write the content in AS3. An example would be a video player written for Flash Player 8/7/6 customers (those who don’t have 9).

    2. You have some content that was created by another company or 3rd party tool that you want to integrate and possibly control. This could be SWF’s generated by Captivate, Connect, Swish, or perhaps even older versions of Flash. There technically are no “source files” so you couldn’t necessarily re-write the content, or said content just couldn’t be created in Flex in the first place.

    3. You’re a Flex Developer and have no intentions of learning Flash. You’ve been ordered to load SWF’s that are not AS3 and control them.

    4. Like #3, except you can’t find any Flash Developer contractors that are available. Imagine that.

    For the record, all 3 are valiant efforts fraught with peril. Knowing this, you can re-attempt my advice to plead with management to abandon the course in folly, or grit yer teeth and git-r-done. I won’t re-iterate the problems here, you can read that in the above link. I will, however, give a quick refresher on what you can and can’t do.

    First, none of the above scenarios allow embedding. If you do not have the source FLA created in Flash, with a valid copy of the Flash authoring tool (MX, MX 2004, 8, or CS3), you have no choice but to load this stuff at runtime. If you DID have a copy, you could embed it. Embedding AS2 SWF’s, however, removes all of your code. Thus, embedding AS2 applications won’t work. You don’t have these problems with AS3.

    Second, loading AS2 / AS1 content at runtime creates a separate, special security sandbox for the SWF that’s being loaded. The DisplayObject is called AVM1Movie, and he’s an iron-clad, impenetrable black box. There is physically no way to breech it via ActionScript 3 to talk to it. You can, however, useliasons over / under the wall via ExternalInterface or LocalConnection. ExternalInterface sucks because it uses JavaScript. Every project I’ve ever done that incorporated JavaScript as a necessity added 1 more level of complexity, extended the debugging time in the project, and overall made it more challenging to make progress. Thus, while theAVM’s may be different versions, at least we’re coding in a semblance of the same language and runtime… well, more than JavaScript anyway. AS1 and he may be similar , but at least AS1 works the same in all browsers. You already have enough challenging things to worry about now that you are down this dangerous path; you don’t need another headache.

    Third, your AS3 content cannot immediately “get rid of” AS2 / AS1 content in this AVM1Movie thing. Garbage Collection will get it when it feels like it. In the AS2 / AS1 AVM, removeMovieClip for the win! It works immediately, and while the actual RAM of the used variables may not go away, all media stops (sounds, video, animation) as opposed to AS3 where you have to be explicit to do so, not just remove it from theDisplayList.

    Solution: A proxy SWF, aka proxy.swf, aka, a Flex liaison to AVM1 content.

    Why a Proxy SWF

    Since Flex 2 content (Flash Player 9, AS3 AVM+ SWF’s) cannot tell AVM1 SWF’s what to do, they use a guy on the inside, a proxy.swf, to act as agents for them in that world. The proxy.swf executes the orders that Flex issues, and these orders are communicated via LocalConnection.

    That downside is, you still need to code this proxy.swf in AS2 or AS1 and compile it for at least the Flash Player 8 or below. You don’t necessarily need Flash to do this. You could use MTASC, PHP’s Ming, or JGenerator (I think what Lazslo uses?). I haven’t gotten this to work myself, but you could also possibly use the Flex 2 SDK’s mxmlc with the “as3” compiler option set to false, and the “es” option set to true. This should generate a Flash Player 9 SWF that uses the old AVM (so… technically AS2 like code that’s compiled to AS1 bytecode using a Flash Player 9 compiler).

    …or, you could use my generic compiled example, and hope for the best.

    If you want to do it right (keeping in mind “right” here means not-so-right since we shouldn’t be using older SWF content anyway), you typically tailor a proxy.swf for the particular content you are loading. For example, if you are loading Captivate SWF’s, you build a proxy SWF that can:

    1. load in Captivate content
    2. control Captivate content by their *hidden API
    3. unload Captivate content

    * For more info on hidden API, go here, scroll to the bottom and download the big ole PDF, search for “rdinfoFrameCount” which should take you to the “Controlling Adobe Captivate projects with variables” section.

    This, as opposed to just my generic proxy that just accepts methods as strings and runs them much like JavaScript’s eval. That way, you can expose a loose API. You can’t share AS3 and AS2 interfaces, but we’re already past the point of IDE help here, so you’re really doing faith based coding at this point. Anyone whose ever used a dynamic language (as opposed to strict typing) shouldn’t have a problem with this. If you don’t code the proxySWF specifically for the content you are loading, it’s harder to debug, and basically really hard to identify which remote method invocations are failing.

    I’ve provided 2 examples at the bottom of this article. One is my generic “I’ll run what you send me” one and the other is one built specifically to control the Flash 8 Video Player. While the generic can be something you can build upon to support your content, I highly recommend you follow how the video player one is built and build the proxy.swf specifically control a specific SWF.

    How It Works

    They both work the same way.

    1. Flex SWFLoader loads an AVM1 proxy.swf
    2. proxy.swf loads the content it’s supposed to use via loadMovie / MovieClipLoader
    3. once the proxy.swf has loaded it’s content, it let’s Flex know
    4. at this point, Flex can now tell the proxy.swf to do things with the content it’s loaded

    These can sometimes breakdown. LocalConnections are by their very nature asynchronous. While you can create an instance immediately, that doesn’t mean it’s immediately available for use. For example, the AVM1 version of LocalConnection gives you a Boolean so you know if the send actually worked. If you get a true, it doesn’t mean it actually sent, just that the send operation itself “worked”. Amazingly f’ing useless. Send again? Hell… WHY NOT!?!

    The AS3 version is different. You can get a few different types of exceptions from sending messages, such as ArgumentErrors and AsyncErrors. While the docs claim that your syntax can be correct, and it could be your request is just bigger than 40k, this is a crock. Even simple strings can just fail, and then magically work later. In short, LocalConnection is flaky; you’re code should compensate. If you need ensured communication, use ExternalInterface. That, however, has it’s own can of worms.

    You do not have to use a SWFLoader. You could just a Loader, but since Flex is UIComponent based, SWFLoader is UIComponent based, so there you go.

    The proxy examples I have both use MovieClipLoader. While you could simply use loadMovie, MovieClipLoader gives you more events to understand what’s happening with your loaded content. You don’t have to write polling code yourself; instead, you have dependable events that fire. The only one you really care about is onLoadInit. When that fires, whatever SWF you are loading can now be accessed by code in an ensured fashion. This is why you wait for that to fire as opposed to onLoadComplete.

    LocalConnections

    All of this communication between Flash & Flex is done via 4 LocalConnections; 2 in Flex, 2 in Flash. LocalConnections are only 1 way. Meaning, you can only send messages or receive messages; not both. I typically use the “in_lc” and “out_lc” naming convention; feel free to make up your own. The Flex out_lc talks to the Flash in_lc. Vice versa, the Flash out_lc talks the Flex in_lc. The only thing uber confusing is that in Flex, the names are reversed. Since LocalConnections connect on a “connection name”, these 2 names need to be the same in Flash & Flex. So, in Flash I have:

    LC_IN_NAME = “_JXLFlashProxy_IN”;
    LC_OUT_NAME = “_JXLFlashProxy_OUT”;

    And in Flex, I’ll have the same thing for values, but different things for the names; just to help easy the insanity.

    public static const FLASH_LC_IN_NAME:String = “_JXLFlashProxy_IN”;
    public static const FLASH_LC_OUT_NAME:String = “_JXLFlashProxy_OUT”;

    The only difference is in Flex, you use the OUT name for your Flex “in” connection. Since Flash is sending messages out on the OUT connection, Flex needs its IN connection listening to the “Flash OUT” connection name. The reverse holds true for Flex sending messages. He’ll send them on Flash’s IN connection name.

    To reiterate, these messages are asynchronous. They don’t arrive immediately, and you cannot return values. You can treat it like events, where the LocalConnection in Flash can send a message back to Flex with data, but unlike events, you can’t depend on this; some messages just don’t make it.

    Dynamic Flash

    If you are not familiar with Flash, you’ll notice that both AVM1 examples just dig right into the SWF they are loading. This is because there is no runtime strong-typing in pre-Flash Player 9. For example, if you look at the video_player2.fla, you’ll notice some methods on the main timeline. Flex asks the proxy.swf to call those methods since he can’t. Like a kingpin asking a thug to get his hands dirty. I can access those methods as if they were public class methods… even dynamically by concatenating strings together in Flash Player 8 and below. This is where a proxy.swf shines in that since it’s made in dynamic Flash land, it can play by dynamic Flash rules. This is important because sometimes you’ll be loading SWF’s that you don’t have code control over, and need to jury rig them to do things they weren’t originally intended to do.

    Keep in mind a proxy.swf can do more than just dynamically call methods and set properties on a load SWF application. It can also affect the nature of that application. Since you are still in a prototype based language, an object’s prototype property is writable. Thus, even if you don’t have the source, and don’t feel like using aSWF decompiler to get some form of source, you can overwrite prototype objects that you introspect to force the SWF to do things you need.

    …you know, in writing all of that, I’d much rather use a proxy.swf with ExternalInterface. As much as I hate JavaScript, it was pretty easy to break LocalConnection. Maybe next weekend…

    Source Code

    Video Player Flex Example – Example | View Source | ZIP

    Generic Flex Example – Example | View Source | ZIP

  • Controlling Flash Player 8 SWFs in Flash Player 9 SWFs

    One of the things I’ve been promoting the last year is encouraging people not to mess with loading legacy Flash Player 8 content into Flash Player 9, usually with regards to Flex 2 content loading Flash 8 content.

    ExternalInterface gives you less browser support, the calls are blocking which locks up your visual display depending on speed, and causes security debugging challenges if you don’t know exactly what you are doing. The last is the kicker because you DON’T have to know, you just know it works, and you move on. When under a deadline crunch with a boss yelling at you, it’s really frustrating to not know why a SWF is yelling about security rules. You don’t need another headache. LocalConnection is asynchronous, and has little strong-typing, and has a limit on the size of messages you can send. Furthermore, you have no guarantee every call you make will… make it. There have been abstraction attempts which really end up with about the same amount of code had you not abstracted it.

    Bottom line, it’s a major headache, painful to debug, and gets really funky when you start loading multiple pre-Flash Player 9 SWF’s into the same app. My guess is, it shares the same security & application domain sandbox which you’re code is not allowed access to. Therefore, any static variables I’m guessing are stuck there too (aka, classes on _global). Never really figured out the exact reason, but it’s just blatantly crazy how bad things are and just flat out don’t work as you’d expect.

    …but there is something far worse, and foreboding. Flash Player 9’s DisplayList + Garbage Collection. In Flash 8 and below, we’re pretty spoiled. We do a my_mc.removeMovieClip(), and poof, everything is gone. All sounds stop, everything stops showing, and most RAM goes with it, immediately. Not in Flash Player 9. Since you don’t have access to this AVM1Movie “sandbox”, whatever the heck it is, you can’t stop the stuff either. Case in point, load in a SWF with a video player, and then unload the SWFLoader. You’ll still hear the video, and it’ll STILL be using resources… that is, until Garbage Collection decides to nail it, if ever. In effect, Flex speaks Espanol, and Flash speaks English. You need a translator.

    In the past I’d do what I’ve been doing the last 2 years; reverently exclaim you need to go to management and explain the benefits of AS3, and just rewrite your legacy content. Since I wasn’t the one who had to deal with the ramifications & implementations of those decisions, it was pretty easy for me to do so upon a high horse.

    …then I started working for an Internet TV company. Thousands upon thousands of customers using Flash Player 8. Existing customers, entrenched, with working software. Boat loads of existing Flash Player 8, 7, and 6 content that works for a variety of existing customers and clients. In effect, Flash Player 8 content AND development isn’t going away for at least another year. Bugger…

    I tried eating my own dog food, but you can’t just immediately demand thousands of people upgrade their rigs without incurring significant costs and losses doing so. Then I tried my best to sequester myself away from said Flash Player 8 content. No dice. The amount, and thoroughness of some of the implementations was too great for me to just re-write in AS3. I can only code so fast.

    So, in the end, I’ve settled on a 3 tier setup. A Flex component that uses a SWFLoader via composition with 2 LocalConnections; 1 for talking to the SWF, and for the SWF to talk to it. A Flash Player 8, AS2 SWF that has 2 LocalConnections, 1 for talking to Flex, and another for Flex talking to it. This Flash SWF manages all content it loads, usually written for a specific piece of content. If you have control of the servers you are loading from, you can either have yourMovieClipLoader check the policy file, and boom, you’ve got no problem with loaded Flash content talking to Flash content. Even if it’s not yours, it’s very easy to dig around in someone else’s classes and “make stuff work” since everything is public in Flash Player 8 and below bytecode.

    The important job of the proxy.swf is clean up the mess when you unload stuff. In the case of a Video Player, you have to stop the video, stop all sounds, and unload the player. It’s ok if the Flex component holding the proxy.swf doesn’t die immediately; the proxy.swf has basically done his job well: stopped all multimedia, and lessened the RAM & CPU damage. An ancillary benefit is you can issue commands through this proxy.swf to control your content. I just send string messages in this case and the proxy.swf knows what to do with them.

    If you find yourself in this situation, don’t go down the ExternalInterface route; it’s too painful. Don’t load it using a simple Flex SWFLoader either since you’ll have no control over the content. Yes, it sucks you have to build a seperate SWF as a Mediator Pattern implementation, but if you don’t, you won’t have any control over the SWF you’re loading in. Remeber, test and get it working in Flash first before you start involving Flex in the mix.