PlotKit and Flash Media Interactive Server?

Many of my Adobe AIR demonstrations show the concept of “script briding” between JavaScript and Flash libraries (i.e. SWC files). Using this feature, JavaScript developers can leverage existing work done by Flash developers in areas that were previously not feasible in the browser. It’s important to recognize however, that the Flash Player itself ships with extensive built in functionality that may be useful as well. I wanted to explore this concept a little further, so I put together a little example that leverages PlotKit and Flash Media Server.

The application is actually pretty straightforward. I wanted to be able to leverage Flash Media Server to stream not video, but data to an Adobe AIR client built in JavaScript. When we demonstrate this feature in Flash, it generally takes the form of Flex charts showing make-believe stock data being pushed to the client. Since Adobe AIR includes WebKit, and since WebKit includes support for canvas, I thought PlotKit would serve this project perfectly.

I think it is important to note that for security reasons, not all JavaScript libraries work in AIR right out of the box. It just so happens that in this case, PlotKit is built on MochiKit, and MochiKit is indeed supported in the default AIR application sandbox. This meant I had only to tie the two worlds together.

The first step is to write the logic that goes on the Flash Media Server (FMS) to create the data and randomly push it out to the listening clients. Business logic on FMS is written using ActionScript 2. ActionScript 2 is the step that Flash took between ECMA-262 Ed 3 (i.e. JavaScript) and what we now call ActionScript 3 (i.e. JavaScript 2).

// Start a general data feed when the application starts
application.onAppStart = function()
{
    // Send new values to the clients
    setInterval( updatePrice, 500 );
}

// Handle new client connections
// Generally just accept the connection
application.onConnect = function( client )
{
    this.acceptConnection( client );
}

When the application starts, an event is triggered. That event sets up a timer (setTimeout) that incrementally kicks out a random number. I chose an increment of every 500 milliseconds which seemed to be a decent refresh rate for the charts. When a new client connects, we also need to accept that client. Most of the work is done by the method that the timer calls when it is triggered.

// Handles generating and sending new pricing values
// Values are random and do not reflect real data
function updatePrice()
{
    // Generate a new price value
    var value = Math.round( Math.random() * 100 );

    // Iterate through the clients to push new data
    for( var c = 0; c < application.clients.length; c++ )
    {
        application.clients[c].call( "pricing", null, value );
    }

    // Alternatively:
    // application.broadcastMsg( "pricing", value );

    // Alternatively manage unique clients
    // Send only pertinent data to specific clients
    // Or send all data to all clients, and let them figure it out
    // Or create independent instances for each client
    // A lot of possibilities...
}

Inside the timer function, the first step is to create a random number that we can push out to all the connected clients. The list of clients is stored as an Array as a property on the Application object. Using the call() method, we can tell the clients to invoke a specific function on their side, and pass it some value. This iteration is good if you want to control what clients get what information from the server. If you don’t care about what client get the data, you can alternatively call the broadcastMessage() method.

I’ve chosen to keep the client side code in this case pretty limited - just the chart that shows the current price (random number) and the number itself.

I wanted the chart to appear as though it was scrolling from right to left as new data was made available. The trick to getting this effect (both with Flex and PlotKit) is to pre-populate the data set that is going to be graphed, and then pop the new value into the data set, while you simultaneously remove the oldest value. You also need to tell the chart what it’s minimum and maximum value will be so it doesn’t flicker too much when the data arrive.

// Fill with zeroed out data
// Helps with animation effect
data = new Array();

for( var d = 0; d < 50; d++ )
{
	data.push( [d + 1, 0] );
}

// Setup PlotKit
layout = new PlotKit.Layout( CHART_TYPE, {
	yAxis: [0,100],
	yTickPrecision: 0,
} );
layout.addDataset( "feed", data );
layout.evaluate();			

// Render chart
canvas = MochiKit.DOM.getElement( 'crtPricing' );
renderer = new PlotKit.SweetCanvasRenderer( canvas, layout, {} );
renderer.render();		

The last step is to connect to the Flash Media Server. This is done by using a class that is built into the Flash Player call NetConnection. You’ll notice that it is not included in the AIR aliases file by default, which means you have to use the “window.runtime” property to get at these classes. There’s a lot of other classes like that too that are in the Flash Player, so you may want to check out the documentation and look around.

// Connect to Flash Media Server
conn = new window.runtime.flash.net.NetConnection();
conn.client = this;
conn.connect( FMS_ENDPOINT );	

You can set the document object itself as the client property for the NetConnection class. This lets the incoming requests from the server get channeled to the right object on the client. You can also make some other object and give the client property that reference. The NetConnection.connect() method does exactly what it sounds like by connecting to FMS via RTMP. RTMP is a highly efficient socket connection that makes highly responsive data push a possibility.

function pricing( e )
{
	// Show the actual numeric value
	document.getElementById( 'txtPricing' ).value = e;

	// Splice off first, push on last
	// Gives effect of dataset animating
	data.splice( 0, 1 );
	data.push( [50, e] );

	// Reset index values (y-axis)
	for( var d = 0; d < 50; d++ )
	{
		data[d][0] = d + 1;
	}

	// Clean up and redraw
	layout.evaluate();
	renderer.clear();
	renderer.render();
}

The pricing function is called by the server through the call() method. This is where incoming messages and data arrive. In this case, it is simply a random number. I put this in a text input so you can see the value, and then perform the splice/push technique I mentioned earlier. PlotKit requires an identifier value, so I then iterate through the data points (50 of them), and reset those values. Last but not least is to simply tell PlotKit to render the chart with the new data. This happens so fast that the chart seems to slide across the screen (download project).

plotkit-fms1.jpg

Given that over 80% of online video today is content served up into the Flash Player, and that many companies use Flash Media Server for delivery of that content, I think it is important not to lose sight of existing investments. You may have a Flash Media Server already in house that can effectively be used to push data to clients, even if you’re using JavaScript, thanks to Adobe AIR. This gives you a very efficient, highly scalable means of providing real-time data in your applications.

Leave a Reply

You must be logged in to post a comment.


order cialis in canada clomid without prescription lasix for sale synthroid prescription discount cialis overnight delivery buy generic propecia order no rx viagra buy viagra low price buy viagra online viagra sale cheapest viagra buy cialis from india buy cheap acomplia online buy clomid cheap purchase clomid order discount viagra online where to buy viagra price of lasix price of propecia soma without prescription purchase clomid online find viagra no prescription required buy generic zithromax synthroid online stores price of synthroid purchase lasix cialis approved cheapest generic viagra online find viagra cialis pharmacy online best price viagra buy cheapest cialis on line cheapest viagra price buying cialis lasix generic order cheap cialis find viagra online buy cialis lowest price best price for viagra purchase zithromax lowest price soma cheapest generic cialis order cialis online cialis free delivery lowest price viagra purchase viagra no rx order cheap cialis online viagra australia discount clomid cheap synthroid tablets cheap cialis pharmacy online zithromax online synthroid buy viagra on internet levitra prescription viagra tablets sale cialis cialis price buy cheap clomid online cheap viagra in canada buy clomid online buy generic viagra cheap viagra from canada cialis in bangkok discount viagra online cialis australia acomplia for sale buy cialis no rx buy levitra without prescription viagra online stores buy cheap viagra online viagra cheapest price viagra rx