Header Image - charles newman's blog

Category Archives

4 Articles

Location of OSMFCCDecoder

I didn’t see any helpful information on this when I did a search so I’m posting this in case it helps anyone looking for the OSMFCCDecoder class mentioned on this page. We’ve had a few customers ask us where this class is after reading that article.

You can find it in the Adobe Media Server installation in this location (on Windows):

C:\Program Files\Adobe\Adobe Media Server 5\samples\osmfcc\OSMFCCLib

So search for Adobe Media Server and install the trial, then look in that folder for the readme.txt file that shows you how to use the code in the OSMFCCLib.swc file you’ll find in that folder.

OSMF – Loading plug-ins locally with the file:/// protocol

Some of you may already know you can load an OSMF plug-in locally using the file protocol like this:

For Mac:

file:///Users/me/Documents/dev/projects/myproject/plugins/SomeOSMFPlugin.swf

For Win:

file:///C:/dev/projects/myproject/plugins/SomeOSMFPlugin.swf

This is very handy when developing a player because you don’t need to copy your player to localhost or a Web server to run and test.

However, I just discovered this oddity:
The plug-in will fail to load if the plug-in is a release build and the player is a debug build.

The failure happens down in the OSMF 1.5 core class DynamicPluginLoader in the onSWFLoaderStateChange method on this line:

var pluginInfo:PluginInfo = root[PLUGININFO_PROPERTY_NAME] as PluginInfo;

Flash Builder clearly shows the pluginInfo property on the root variable but the pluginInfo local variable is null after the above line executes.

This is not an OSMF bug, just something that you need to be aware of. I wasted about 30 minutes on this.

Dynamically loading a SWF and instantiating a Class in that SWF

There are a few blog posts out there on how to do this, but most of them involve a solution that requires a dummy reference in your Application code to the class you wish to instantiate, which forces the compiler to pull in the class, and therefore, allows getDefinition() to work.  But that solution defeats the whole purpose of loading a SWF dynamically.

If you want to load a SWF remotely, and then instantiate a class within that SWF at run-time, you are in the right place.

In the example below, the “application” is Foo and the class we’ll instantiate will be called Bar.  Let’s look at the SWF containing Bar first. Our goal, is to load the SWF that contains Bar and instantiate Bar in our application.

Dynamic.swf

Below is the root level class of the SWF we’ll dynamically load, let’s say it’s called Dynamic.swf. Notice the private var of type Bar. This is necessary to get the compiler to pull the Bar class into our Dynamic.swf. The idea here, is we’ll build Dynamic.swf and put it up on a server somewhere, or localhost so we can test this.

package
{
	import com.charlespatricknewman.sample.Bar;

	import flash.display.Sprite;

	public class Dynamic extends Sprite
	{
		// Need a dummy reference
		private var bar:Bar;

		public function Dynamic()
		{

		}
	}
}

And here is the Bar class we want to instantiate in our Application at run-time:

package com.charlespatricknewman.sample
{
	public class Bar
	{
		public function Bar()
		{
			trace(">>> Bar() constructor!");
		}

		public function doSomething():void
		{
			trace(">>> Bar.doSomething() called!");
		}
	}
}

All this class does is trace out some text, but this is sufficient to prove this is working.

The Application

Next is Foo, the application that will load the SWF and instantiate Bar.  Note this project has no reference or dummy variables of type Bar.

Here is the root level class:

package
{
import com.charlespatricknewman.sample.DynamicClassLoader;

import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;

public class Foo extends Sprite
{
	public function Foo()
	{
		this.addEventListener(Event.ADDED_TO_STAGE,
					onAddedToStage);
	}

	private function onAddedToStage(event:Event):void
	{
		go();
	}

	private function go():void
	{
		var loader:DynamicClassLoader = new DynamicClassLoader();
		setupListeners();
		loader.loadSWF("http://localhost/test/Dynamic.swf",
				"com.charlespatricknewman.sample.Bar");

		function setupListeners(add:Boolean=true):void
		{
			if (add)
			{
				loader.addEventListener(Event.COMPLETE,
					onClassLoaded);
			}
			else
			{
				loader.removeEventListener(Event.COMPLETE,
					onClassLoaded);
			}
		}

		function onClassLoaded(event:Event):void
		{
			setupListeners(false);
			var Bar:Class = loader.instantiateClass(
				"com.charlespatricknewman.sample.Bar");
			var bar:Object = new Bar();
			bar.doSomething();
		}
	}
}
}

And here is the DynamicClassLoader class you see referenced above. This class could reside in the Application SWF or a library (SWC) the application uses at compile time. It’s job is to load the SWF and allow the Application to instantiate a class in the loaded SWF.

package com.charlespatricknewman.sample
{
 import flash.display.Loader;
 import flash.errors.IllegalOperationError;
 import flash.events.Event;
 import flash.net.URLRequest;
 import flash.system.ApplicationDomain;
 import flash.system.LoaderContext;

 public class DynamicClassLoader extends Loader
 {
	public function DynamicClassLoader()
	{
		super();
		contentLoaderInfo.addEventListener(Event.COMPLETE,
						onComplete);
	}

	public function loadSWF(swfPath:String, classPath:String):void
	{
		if (ApplicationDomain.currentDomain.hasDefinition(classPath))
		{
			throw new IllegalOperationError("Class is already loaded!");
		}

		var request:URLRequest = new URLRequest(swfPath);
		var context:LoaderContext = new LoaderContext();

		context.applicationDomain = ApplicationDomain.currentDomain;

		load(request, context);
	}

	public function instantiateClass(classPath:String):Class
	{
		return ApplicationDomain.currentDomain.getDefinition(classPath)
				as Class;
	}

	private function onComplete(event:Event):void
	{
		dispatchEvent(new Event(Event.COMPLETE));
	}
}
}

Due to the security restrictions in the Flash Player, both Dynamic.swf and the Application SWF need to be loaded from either localhost or a web server. You might also need a crossdomain.xml file on the web server, but it’s best to try this from localhost first so you can see it working.

This might be a good solution if you have a SWF or a SWC that contains a large amount of code that is rarely used. Adding that code to your SWF or SWC might cause an unnecessarily large SWF. But loading that bloated Class only when you need it, will provide a much faster initial download and startup for your end users.