Spending my days programming virtual worlds for The Electric Sheep Company. Spending nights and weekends on BlitzPick for Super + Fun. I also enjoy quilting, reading, and singing in the shower.

UStream Cube: An experiment with UStream video in native Flash 3D

I’m working on the Electric Sheep Company’s StreamJam application, a flash-based virtual world that plays streaming video for live events. The StreamJam environments are currently using Papervision3D, which does not yet take advantage of the new 3D features in Flash 10. Papervision materials require access to BitmapData.draw in order to render a texture in 3D. For live or on demand video, that means the flash media server must allow video sample access.

We decided to start off StreamJam using UStream’s video service since it has a flash library for client integration, an easy interface for broadcasting, and built-in metrics. UStream’s media server allows video sample access by default. However, their ad networks usually do not. Thus, when an ad appears on a UStream video playing on a Papervision3D plane, the video blacks out for the duration of the ad, though the audio continues to play. UStream’s paid white label service, Watershed, doesn’t have ads and works just fine.

Of course, we’d like to allow users to stream their own events for free in future. Happily, the native Flash 10 3D features don’t have the same security issues for live streams. To test out UStream in native Flash, I made a silly little app that renders UStream channels on the sides of a cube.

You can rotate the cube by clicking and dragging or right-click the cube and choose a channel. You can also double click on a side to have it straighten out and face forward.

Only the top-most layer plays video at any time. As the cube rotates, it automatically pauses the videos on the other planes and plays the top video.

The video cube isn’t exactly an awesome interface, but it demonstrates the advantage of using native Flash 10. The video is rendered smoothly on each side and the ads are interactive.

Acknowledgments

The ArcBall interface and SimpleZSorter for the cube are from Ralph Hauwert’s blog.

Source

Monday, November 16th, 2009

Facebook Authentication with the ActionScript API

I created a little demo app to help me understand Facebook authentication from flash.

Goals

  1. Use only javascript and actionscript, no php or other Facebook client libraries
  2. The secret key is not hardcoded
  3. The same codebase can be deployed on non-Facebook site or in on Facebook app canvas
  4. The app can be used by both authenticated and unauthenticated users
  5. Users can authenticate with Facebook after loading app without reloading the app

The App

If you are logged into facebook and have authorized the app, the demo pulls in your profile picture and user name and displays them in a panel. If you are not logged into facebook or have not yet authorized the app, it shows a login button which will show a popup (from a connect site) or redirect to the login page.

Facebook Connect site embedded as an iframe:

The same app is available as a Facebook iframe canvas page here.

Goal 1: Use only javascript and actionscript, no php or other server-side facebook client libraries

I wanted to use as few languages as possible and maximize what is done from flash. It worked well as described below.

Goal 2: Secret key is not hardcoded

From what I can tell, there’s no way to start a web session solely from the actionscript api (at least not without hardcoding the secret key, which we want to avoid). Instead, the session information can be passed to the swf. In the demo, the actionscript session is created as:

protected function connect(parameters:Object) : void {
    if (parameters.fb_sig_api_key && parameters.fb_sig_ss 
        && parameters.fb_sig_session_key) {
        session = new WebSession(parameters.fb_sig_api_key,
                     parameters.fb_sig_ss, parameters.fb_sig_session_key);
        session.facebook_internal::_uid = parameters.fb_sig_user;
            
        //Create our facebook instance
        facebook = new Facebook();
        session.addEventListener(FacebookEvent.CONNECT, onSessionConnect);
        facebook.startSession(session);
        session.verifySession();
    }
    ...
}

Details on acquiring the session variables are covered under the next goal.

Goal 3: The same codebase can be deployed on a non-Facebook site or on a Facebook app canvas

When loading an app via a Facebook iframe canvas, a number of parameters are appended to the iframe url’s query string, listed here. (The fb_sig_ parameters can also be included using fb:swf on an fbml canvas). In this app, I’ve used javascript to parse the query string into an object and pass to the swf as flashvars on load if the fb_sig_in_iframe=1 parameter is available. The same could be accomplished with a server-side language like php, but I wanted to keep the mix of languages to a minimum.

When loading the app from a Facebook Connect site, the session information is acquired through the javascript Facebook client first, then passed to the swf which sets up its session in the same way as above. In this case, the javascript translates the session variables to the same names used in the iframe query string.

var sessionData = FB.Facebook.apiClient.get_session();
var fbdata = {};
if (sessionData) {
    fbdata.fb_sig_session_key = sessionData.session_key;
    fbdata.fb_sig_ss = sessionData.secret;
    fbdata.fb_sig_user = sessionData.uid;
    fbdata.fb_sig = sessionData.sig;
    fbdata.fb_sig_api_key = api_key;
} 

Goal 4: The app can be used by both authenticated and unauthenticated users

This one is pretty easy: simply do not require a session. Your app will have limited data available, but users who haven’t authorized the app or who don’t have Facebook accounts can still use it if you accommodate them.

Goal 5: Users can authenticate with Facebook after loading app without reloading the app

I had mixed results here. I was unable to get this to work in a canvas page since calls to window.open and FB.Connect.requireSession are ignored in the iframe canvas. Instead, I redirect to facebook.com/login.php if the user needs to log in or authorize the app and then they are returned to the canvas page. This makes some sense since the whole Facebook page needs to refresh if you are logging in.

Logging in from a facebook iframe canvas page:
self.parent.location =  'http://www.facebook.com/login.php?api_key=' + api_key
                         + '&extern=1&fbconnect=1&v=1.0'
                         + '&next=' + escape(CANVAS_PAGE_URL)
                         + '&cancel_url=' + escape(CANVAS_PAGE_URL); 

You can log in without a page refresh in a Facebook Connect site. When the user clicks the “Connect with Facebook” button in the swf, it makes an external interface call to a javascript function. When not in an iframe canvas page, the javascript calls FB.Connect.requireSession. By passing true for the isUserActionHint parameter, the function opens a popup window where the user can login or authorize the app and then closes itself when done.

Logging in via Facebook Connect
FB.ensureInit(function() {
    FB.Connect.requireSession(null, true);  
});

The app page is notified of the status change through the cross domain receiver channel. I initialized the javascript client with a callback for when the user’s logged in status changes. In the callback, the updated session parameters are passed to the swf through another external inteface call.

Initializing the javascript Facebook client:
FB_RequireFeatures(["Api", "Connect"], function() {
    FB.Facebook.init(api_key, 'xd_receiver.html', 
            {   "ifUserConnected": onConnectStatus, 
               "ifUserNotConnected": onConnectStatus
            });   
    });

The Facebook actionscript api docs for the WebSession class recommend using FacebookSessionUtil for managing sessions instead of using WebSession directly. However, FacebookSessionUtil looks for some values only in loaderInfo, which isn’t compatible for updating the session info after the app loads. The demo does use a WebSession instead of FacebookSessionUtil, but it still gets all the necessary information passed in via javascript and doesn’t have hardcoded api or secret keys. The demo doesn’t look for a stored session in a shared object, but it could be added to mimic FacebookSessionUtil closely that way.

Links

View demo using Facebook Connect.

View demo in a Facebook iframe canvas

View and download the source

Reference

Monday, October 26th, 2009

Using System.totalMemory to analyze flash memory usage

When looking for memory leaks on an application that loads many bitmaps, Internet Explorer showed much lower memory usage from System.totalMemory than FireFox.  The difference is because

not everything allocated in the player is allocated by the internal allocator, nor reported through totalMemory…namely anything allocated by OS system calls, memory associated with platform bitmap data, and the JIT buffer associated with the Actionscript VM.”

http://www.justsuppose.com/some-systemgc-and-systemtotalmemory-tips/

Thursday, October 22nd, 2009