Click here to Skip to main content
15,897,273 members
Articles / Programming Languages / C#
Article

Fun with C# and the Flash Player 8 External API

Rate me:
Please Sign up or sign in to vote.
4.72/5 (31 votes)
19 Oct 20054 min read 543.7K   13.8K   172   92
Demonstrates how to communicate between Flash Player 8 and C# using the new External API

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:

flash
import flash.external.ExternalInterface;

Next, we have to register any function we want to make available externally:

flash
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.

flash
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:

C#
private AxShockwaveFlash flashPlayer;

public FLVPlayer ()
{
     // Error handling removed for the sake of condensing the code
     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:

C#
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:

flash
import flash.external.ExternalInterface;

Then to make the call from ActionScript we use a static method on the ExternalInterface class:

flash
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:

C#
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:

XML
<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:

C#
XmlDocument document = new XmlDocument();
document.LoadXml(e.request);

// Get all the arguments
XmlNodeList list = document.GetElementsByTagName("arguments");

// Since in this case I only have one call from ActionScript to C# I
// know I need to invoke the ResizePlayer function
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

Sample Image - flashexternalapi.jpg

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.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
United States United States
.NET Software Developer

Education
- Working towards M.S. Computer Science
- B.S. Computer Science
- B.S. Computer Information Systems
- Minor Mathematics

Professional
- Microsoft Certified Application Developer
- Microsoft Certified Professional
- C# ASP.NET Developer (4 years)

Other Interests
- Flash Remoting
- Video Encoding (Windows Media and Flash Video)
- Microsoft Content Management Server

More Programming Thoughts and Tips
- http://gabewishnie.blogspot.com

Comments and Discussions

 
AnswerRe: Password Protected .swf Pin
Gabe Wishnie9-Dec-05 16:29
Gabe Wishnie9-Dec-05 16:29 
QuestionHow to invoke a button control using Action script Pin
jaans27-Nov-05 20:10
jaans27-Nov-05 20:10 
AnswerRe: How to invoke a button control using Action script Pin
Gabe Wishnie28-Nov-05 16:24
Gabe Wishnie28-Nov-05 16:24 
GeneralRe: How to invoke a button control using Action script Pin
jaans28-Nov-05 17:23
jaans28-Nov-05 17:23 
GeneralRe: How to invoke a button control using Action script Pin
Gabe Wishnie28-Nov-05 17:38
Gabe Wishnie28-Nov-05 17:38 
GeneralRe: How to invoke a button control using Action script Pin
jaans28-Nov-05 17:58
jaans28-Nov-05 17:58 
GeneralA few questions... Pin
theidealist2-Nov-05 16:05
theidealist2-Nov-05 16:05 
AnswerRe: A few questions... Pin
Gabe Wishnie2-Nov-05 17:44
Gabe Wishnie2-Nov-05 17:44 
Glad you liked the articles and hope I am able to help w/ some of the questions...

1. Personally I have used it twice so far in a single movie and have had no problem. From the documentation I have read, there is no limitation as to the number of external functions that can be exposed. However, time will tell on this one I am sure.

2. I actually was asked this very question on the introductory article on my blog (http://gabewishnie.blogspot.com). The Flash movie will resize to the dimensions of the control it is being loaded into as it does in a browser. If you are only loading a single movie you can just size the control appropriately and it should load at the correct size. However, if you are loading many movies of different dimensions it gets a little trickier. After looking into it there seem to be two ways I can think of how this can be handled. One requires that you are able to enforce a piece of content in the Flash movie and the other will not. However, the latter will be a lot more difficult.

Method 1 (the simple method): You put two methods in the movie and make them externally available. The first one returns the Stage.height and the second the Stage.width. These two properties will pull the dimensions of the actual movie from the header of the SWF file. Once you have these values in the Form you can resize the control and form if necessary so the movie is not scaled.

Method 2 (the complex but flexible method): The SWF format is a documented format. Every SWF file contains a header at the top of the file that provides basic meta data about the movie itself. In this header there are the actual dimensions of the movie. Here is the catch... Starting at Flash 6 (if I remember correctly), Macromedia added the ability to compress the movie while compiling (using the ZLIB standard).

When you start looking at the SWF header you will see that an uncompressed movie has the character 'F' for the first byte of the header while a compressed has a 'C'. This is where the first hurdle comes in, if the header contains a 'C' everything after the File Length field is compressed, so it will first have to be uncompressed.

The second hurdle is the Rectangle data structure the dimensions are stored in. This type is a variable bit type and the data is not necessarily aligned on an 8-byte boundary, so it gets tricky parsing this correctly.

I am slowly trying to get this method working, but it might be a while until I get to play with it some more. However, I do have a simple example of the first method that I can send if requested. If interested you can learn more about the 7 format here - so far the 8 format has been the same from what I can tell, you can use WinHex to open a SWF and get a good idea of what it looks like - http://download.macromedia.com/pub/flash/flash_file_format_specification.pdf

3. As far as DLL's you would have to distribute the 2 DLL's that allow your C# managed code to interop with the COM Flash player component.
- Interop.ShockwaveFlashObjects.dll
- AxInterop.ShockwaveFlashObjects.dll

These should both be automatically created when you add the Shockwave Player to your toolbox in VS.NET and place it on your Form.

The user's computer will only require Flash 8 Player (the IE ActiveX version).

4. Try adding the Shockwave Player COM component to the VS.NET toolbox. This will cause VS.NET to automatically run the command line utility that comes w/ the Framework that will generate the RCW DLL. Also, you will probably want to make sure both the references are set to copy locally once the component has been added to the Form.

Let me know if you have any more questions. I have been working on the XML parsing as discussed and will be posting as soon as I complete, hopefully within the next few weeks.

Thanks,
Gabe
QuestionRe: A few questions... Pin
theidealist7-Nov-05 16:09
theidealist7-Nov-05 16:09 
AnswerRe: A few questions... Pin
Gabe Wishnie7-Nov-05 16:53
Gabe Wishnie7-Nov-05 16:53 
GeneralRe: A few questions... Pin
theidealist7-Nov-05 18:10
theidealist7-Nov-05 18:10 
AnswerRe: A few questions... Pin
Gabe Wishnie8-Nov-05 3:22
Gabe Wishnie8-Nov-05 3:22 
GeneralRe: A few questions... Pin
theidealist8-Nov-05 3:39
theidealist8-Nov-05 3:39 
AnswerRe: A few questions... Pin
Gabe Wishnie7-Nov-05 17:36
Gabe Wishnie7-Nov-05 17:36 
GeneralRe: A few questions... Pin
theidealist7-Nov-05 17:59
theidealist7-Nov-05 17:59 
GeneralRe: A few questions... Pin
Gabe Wishnie8-Nov-05 2:49
Gabe Wishnie8-Nov-05 2:49 
GeneralRe: A few questions... Pin
theidealist8-Nov-05 3:28
theidealist8-Nov-05 3:28 
GeneralRe: A few questions... Pin
Gabe Wishnie8-Nov-05 15:07
Gabe Wishnie8-Nov-05 15:07 
GeneralDownload Pin
Mark Focas19-Oct-05 22:03
Mark Focas19-Oct-05 22:03 
AnswerRe: Download Pin
Gabe Wishnie20-Oct-05 5:37
Gabe Wishnie20-Oct-05 5:37 
AnswerRe: Download Pin
Gabe Wishnie20-Oct-05 6:23
Gabe Wishnie20-Oct-05 6:23 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.