Update April 7, 2008: I’ve written a new AS3 class named LegacyCaptivateLoader that uses ExternalInterface to bridge the AS3 SWF and the Captivate SWF. Check it out.

I guess I’m late to the party, but I only recently realized that although a Flash Player 9 SWF can load an older Flash Player 6/7/8 SWF, it can’t communicate with it.

(In my defense, since we haven’t really started using ActionScript 3 at work yet, I’ve been a bit slow in switching to AS3. The leap from AS2 to AS3 is pretty daunting, so I’m sure I’m not the only one dragging my feet!)

Turns out the mechanism that processes the ActionScript (the ActionScript Virtual Machine, or “AVM” for short) has been rebuilt. Flash Player now ships with two unique ActionScript processors: AVM1 for legacy ActionScript 1 & 2 SWFs, and AVM2 for ActionScript 3 SWFs. Without getting overly technical, this enables AVM2 (Flash Player 9 SWFs) to be exponentially faster than AVM1 (Flash Player 8 and lower SWFs).

As you can imagine, many Flash developers — like you and me — still need to load old SWFs into a new Flash Player 9 (ActionScript 3) user interface. For instance, many Flash-based e-learning courses load ‘content’ SWFs that were created a couple of years ago with Flash MX (7) or Captivate. No one wants to recreate or republish a few years’ worth of development files.

To accommodate people who still need to use their older SWFs, Adobe configured Flash Player to allow AMV2 SWFs to load the older AVM1 SWFs in a virtual sandbox. But, as I mentioned, there’s a catch: these AVM1 SWFs cannot communicate with the parent AVM2 SWF.

This is a very big problem for many Adobe Captivate users. Adobe didn’t wait for the Captivate development team to convert Captivate to AS3, which means Captivate users are still publishing AS2 SWFs on a daily basis. A large number of Captivate users ‘play’ their Captivate files in custom Flash-based course interfaces. If they want to use a newer AS3 interface to control their Captivate SWFs (play, pause, etc.), they’re out of luck.

I guess you can’t blame Adobe for not updating Captivate’s codebase; Captivate has probably had the same codebase since early versions of RoboDemo, and converting to AS3 would probably require a complete overhaul of the product. No small task.

The Experiment

Anyway, I’ll get to the point: I researched the different methods available for AVM1 to AVM2 communication, and discovered there are a few workarounds that can enable the AS3 SWF to communicate with the AS2 SWF. I spent the entire day whipping up a Captivate-specific proof-of-concept, which can be viewed here.

For this experiment, I used LocalConnection. I’ve also been researching an ExternalInterface method, but the LocalConnection method was much easier to implement and doesn’t require JavaScript.

Because LocalConnection requires the old SWF to have specific LocalConnection code inside it, we can’t use LocalConnection on Captivate SWFs without a little help. I was able to use a proxy SWF to load the Captivate movie.

I’m not ready to explain the code and hand out the source files, but I hope this proof of concept can help others out. The short version is:

  1. A ‘player’ SWF (AS3) loads an AS2-based ‘proxy’ SWF. This proxy SWF is configured with custom LocalConnection settings allowing it to send and receive commands from the AS3 player.
  2. The proxy SWF loads the Captivate SWF. Since the proxy SWF and Captivate SWF are both AS2, they can communicate with each other using the famed ‘Captivate variables’.

Thus the AS3 SWF sends instructions to the proxy SWF, which relays the instructions to the Captivate SWF. Conversely, the Captivate SWF sends data (frame count, current slide, etc.) to the proxy SWF, which then sends the data via LocalConnection to the AS3 SWF.

BTW, using LocalConnection to bridge AVM1 and AVM2 isn’t an original idea… many people have blogged about these concepts over the last year or two, and had some good tips (see my references at the end of this post). There are even a few functional commercial and freeware products out there.

I decided to develop my own method out of curiosity, and because most of the existing products are overly complicated, designed to handle way more than my dinky little Captivate files. Plus I wanted to create a system that would have the ‘Captivate variables’ built-in, so it will be plug-and-play with any Flash-based Captivate loader.

Caveats

There are some very big caveats when using LocalConnection to bridge AVM1 and AVM2 SWFs; these caveats are big enough to make me question just how far I want to go with this project.

Caveat #1: LocalConnection is asynchronous. This means it can’t return values, and it may not kick in as soon as you’d hoped. I learned firsthand that LocalConnection worked much faster in my local environment than it did after I uploaded it to the server.

Caveat #2: LocalConnection works independent of the browser, and can only have ONE active connection per unique LocalConnection session. For instance, if I create a course that uses a LocalConnection named “FlashToCaptivate_LC”, I can only have one instance of that course running on my computer. If I open a second instance of the course, regardless of which browser it’s in, or whether or not the course is local or online, the second course will return a LocalConnection error because the connection named “FlashToCaptivate_LC” is already in use. Think of it as a phone number without call waiting. If someone is on the phone and you try calling, all you’ll get is a busy signal. That’s LocalConnection.

What do you think?

I’d love to hear any feedback you might have about this topic, including whether or not any of you have tried LocalConnection yourselves.

Resources

Here are some good resources/discussions about the topic if you’d like to learn more (no particular order):

Similar Posts

6 Comments

  1. yeah, since migrating our coursebuilding framework to as3 i’ve been doing a bit of, “if (event.target.content is AVM1Movie” to avoid getting errors when loading and trying to communicate with older swfs.

    it’s not such a big deal, really. it just means that most of the cool new functionality will only be available in newly developed courses.

    best, ian

  2. I am working on a project that is not focused on the problem you are working on, however, due to some similarities in nature I thought I would ask if you can help. I am building a custom Flash player of swf and Captivate swf files. The player pre-loads a series of swf files, and begins to play the first one when loaded. The first time the player loads the files (when the browser cache is empty of these files), the Captivate-generated swf files sometimes do not start, or indeed start, but without being visible. Sometimes a custom scrubber works to get them to show, other times, going to the next slide and coming back is the only thing that reveals them.

    My preloader calls rdcmndRewindAndStop after loading a swf – without this line, they would start playing.

    Once cached, all swf files run fine.

    Do you have any idea what might be causing this to happen? Alternatively, if you would like to share any good resources related to complex scripting of captivate swf files, I would appreciate it very much. Thanks.

  3. Are you talking about Captivate 3?
    It seems to have a publish to flash player 9 option?

  4. @ged
    Publishing to Flash Player 9 doesn’t equate to publishing to AS3. Captivate 3’s “Flash Player 9” output uses AS2.

    @elearningdeveloper
    Not sure what’s causing your problem… I’d head over to the Adobe Captivate user forum and post your problem there. Also, I know IE7 is notorious for strange caching behavior… maybe you can check into that angle.

  5. I’m wrestling with this issue and happened upon your article (big surprised, I’ve happened upon your blog many times as a resource)…

    Anyway, I wrote some AS2 Flash activities that loaded into Captivate 3 projects, with some calls going from the Flash swf to the Cap swf. Now I upgraded to Cap 5 and all the communication between the Flash swfs in AS2 and Cap 5 swfs in AS3 are broken.

    I’m hitting a wall where, I can use LocalConnection to essentially put an AS3 wrapper around my AS2 swfs to make the functions up to the Cap swf work. However, that works the first time you’re on the slide, but if you navigate back to that same slide, it doesn’t work. I’m wondering if you need to dump or clear the LocalConnection object each time the user leaves the slide, but can’t figure out how…

    Did you run across this?

  6. @danny localconnection only allows a single connection (using a unique ID), so if your file is trying to create new connection using the same ID, it could fail.

    i’ve found localconnection to be somewhat unpredictable because of this restriction, which is why i designed LegacyCaptivateLoader to use ExternalInterface instead.

Comments are closed.