Introduction
After hearing of all the great new enhancements made to Flash Player 8 during Macromedia MAX this year, I was inspired to take one of the new features that caught my eye for a test drive. The feature I am speaking of is the External API.
The External API allows an ActionScript developer to easily interact with the container program that is hosting Flash Player 8 and vice versa. The majority of the time, this will most likely be a Web browser, but this does not always have to be the case.
As many C# developers know, it is easy to house an ActiveX control (the IE version of Flash Player 8) in a .NET Windows application. This means we can now load an SWF in our Windows application and easily send data back and forth. Keep in mind that the keyword in this statement is "easily;" although possible before, it was not nearly as simple as the External API makes it now!
For my test application, I decided to begin porting over the FLVPlayer I built earlier this year using Flash Player 7, to Flash Player 8. This is just a simple program that allows double click playback of FLV encoded video.
C# -> ActionScript Communication
As I said before, communication between Flash Player 8 and its container has been made extremely easy. The new class that makes this process so easy is the ExternalInterface
. We will begin in the ActionScript. First, we need to import this new class so we can use it:
import flash.external.ExternalInterface;
Next, we have to register any function we want to make available externally:
ExternalInterface.addCallback("loadAndPlayVideo", null, loadAndPlayVideo);
Basically, the code above will allow us to call the loadAndPlayVideo
function (which I will show in a minute) from the C# application. The second argument is null
because the loadAndPlayVideo
function is declared on the _root
of the timeline.
The loadAndPlayVideo
function is as below. Basically, it takes a file path and sets it as the content path in an instance of the FLVPlayback
component named videoPlayer
.
function loadAndPlayVideo(uri:String):Void
{
videoPlayer.contentPath = uri;
}
That's it from the ActionScript side. Now all we need to do is call the function from C#. First, I add an instance of the Flash Player 8 ActiveX control to my form and load the SWF we created in the form's constructor:
private AxShockwaveFlash flashPlayer;
public FLVPlayer ()
{
flashPlayer.LoadMovie(0, Application.StartupPath + "\\player.swf");
.
.
.
}
Next, all we have to do is call the externalized method when desired. In my case, it is in response to the user selecting a file from a standard OpenFileDialog
:
fileDialog = new OpenFileDialog();
fileDialog.Filter = "*.flv|*.flv";
fileDialog.Title = "Select a Flash Video file...";
fileDialog.Multiselect = false;
fileDialog.RestoreDirectory = true;
if(fileDialog.ShowDialog() == DialogResult.OK)
{
flashPlayer.CallFunction("<invoke" +
" name=\"loadAndPlayVideo\" returntype=\"xml\">
<arguments><string>" + fileDialog.FileName +
"</string></arguments></invoke>");
}
That's it! As you can see, we call loadAndPlayVideo
by sending in a specially formatted XML string containing the name of the method to invoke and the list of function parameters.
ActionScript -> C# Communication
Again, you will need to include the ExternalInterface
in the ActionScript:
import flash.external.ExternalInterface;
Then to make the call from ActionScript we use a static method on the ExternalInterface
class:
ExternalInterface.call("ResizePlayer",
videoPlayer.metadata.width, videoPlayer.metadata.height);
As you can see, I am calling a method called ResizePlayer
and passing the width and height of the video currently loaded as parameters. Now to receive the message in C#, we first have to subscribe to the FlashCall
event. To do this, I added the following line to the form's constructor:
flashPlayer.FlashCall +=
new _IShockwaveFlashEvents_FlashCallEventHandler(flashPlayer_FlashCall);
Now the call made in ActionScript will be received in the request
property of the event argument. For my particular call, the XML will look like this:
<invoke name="ResizePlayer" returntype="xml">
<arguments>
<number>320</number>
<number>240</number>
</arguments>
</invoke>
So now all we have to do is parse the XML in the event handler and invoke the C# function locally:
XmlDocument document = new XmlDocument();
document.LoadXml(e.request);
XmlNodeList list = document.GetElementsByTagName("arguments");
ResizePlayer(Convert.ToInt32(list[0].FirstChild.InnerText),
Convert.ToInt32(list[0].ChildNodes[1].InnerText));
Viola! It is now that easy to pass data back and forth between ActionScript and C#.
What's Next?
As I am sure many of you are thinking, writing and parsing of the XML being sent back and forth can be completely plucked out and wrapped up into utility classes for easy re-use.
As time permits, I will continue to work on porting FLVPlayer into the Flash Player 8 era and will work on building the utility classes necessary. Look for another article with details, when completed…
Example Code
I have made the simple example discussed available. Keep in mind this is only meant to demonstrate the External API and is not the final version of the FLVPlayer. In fact, if you try to load a video larger then 320x240, you will see that the resize functionality is not complete.