Friday, August 24, 2007

Flex RemoteObject concurrency

We have just started using amfphp for our Flex projects. For a long time we held off because the PHP remoting options seemed a bit immature. Then we were in the middle of a large project and it wasn't a good time to make the change. During that time we were requesting PHP generated XML using HTTPService. Anyway here we are using amfphp (I plan to write a longer post about that soon). But as part of the change we've also been trialing ServiceCapture (also looked at Charles which is also looked very good). ServiceCapture is a web debugging proxy and it allows you to see all transactions between your machine and the web. It's particularly good for remoting as it shows exactly what the remote gateway is returning to your application.

One thing we noticed was that many of our remoting calls were happening twice. This seemed a bit odd . Turns out RemoteObject has a very useful property called concurrency. For example setting concurrency to 'single' means that only one RemoteObject call is made at a time. Exactly what we needed.

I eventually realised the reason the RemoteObject was getting called twice was that I had a group of RadioButtons with a change event. Selecting one RadioButton changes both buttons in the group and consequently triggers two RemoteObject calls. I changed my change events to click events and the problem was doubly solved.

This small problem highlighted for me how important tools like ServiceCapture and Charles are for Flex work.

Wednesday, August 22, 2007

Flash Player Moviestar

This is already all over the Flash blogs (though it's been a bit slow to make it to the mainstream technologies columns considering the scale of it's implications) but I wanted to summarise the news for my own reference. Tinic Uro's blog is the place to go for the real detail. But the guts of it is that a beta of the Flash Player was released last night. This beta player, code named MovieStar adds support for popular media codecs; H264 and AAC. Meaning that in the future we will no longer be limited to using Flash video (.flv) files in our applications.

Our department has for many years used Quicktime as our standard for video production. There were many good reasons for this; the main one being quality and availability. But in the last 18 months the success of YouTube and Google video has made Flash video an almost standard for online delivery. Consequently we've been considering our options for moving towards Flash for future video development. But one of the sticking points has always been quality. The ability to play alternative video formats in Flash changes everything. There are still a few questions to answer before making any changes and we'll need to leave time for a non-beta release to trickle out to our audience. But this will definitely determine our future direction.

Saturday, August 18, 2007

Bridge : Managing Favorites

If you are like me then you like to get rid of extraneous clutter in the applications you use. Therefore one of the first things I did after installing CS3 was to have a close look at what was available within each application and decide what wasn't needed and if it was possible to get rid of the things I wouldn't need.

Bridge opens with a long list of Favourites. Some of these feel more like marketing (i.e Start Meeting) than an actual feature. They are easy to get rid of you just right click and select "Remove From Favorites". One of the first things to go was Bridge Home. But today Alan Mussellman has a post "Bridge Home and Fireworks CS3" that got me to thinking I may have been a bit hasty in my decision to remove Bridge Home. But how do you get a banished favorite back. In the end it took me a while to work this out. I looked in all the menus and sub-menus, searched the help all with no luck. Finally I decided to look in preferences (win :Edit > Preferences; Mac : Bridge > Preferences). Under General preferences at the bottom of the page you'll find a list of the available top level favorites. Just tick the checkbox for the items you want to see.

If you want to add a folder to your favorites you can drag and drop it from the content pane to the favorites panel. This is useful for quickly accessing current project files.

Some of the default favorites are Flash pages (i.e. Bridge Home). So I guess there must be some way to add our own favorites pages using Flash/Flex. Now that could be really useful. I can think of a lot of conent I wouldn't mind accessing in Bridge. But a few quick tests show web pages being opened by the default browser and swf files getting opened by Flash (even after adding them to Favorites). Think I'll need to add this to my Research list.

Additional (19th August, 2007):

It seems there is some information around relating to extending Bridge CS3. You can find a few examples at the Adobe - Bridge Exchange.

Wednesday, August 15, 2007

Flex Frameworks : Getting Started with Cairngorm

We've being looking for an appropriate Flex framework to use over the last few months. Adopting a framework has been on my mind since I started using Flex. But initially learning Flex offered a big enough learning curve and being the only Flex developer in the office made it less of an imperative. But earlier this year we appointed a new web developer and part of his job description was to become a Flex developer. He has just completed his first Flex project and we are about to start on a larger collaborative project. Consequently adopting a suitable framework became a higher priority.

I was aware of Cairngorm long before I did any Flex work. But everything I've read says it's not worth the effort for smaller projects and I guess I consider our projects quite small. But when I started looking around the alternative frameworks they either seemed a bit immature or nearly as complex as Cairngorm (but without a strong support community). Consequently we've decided to bite the bullet and use this smaller project as a good place to start learning Cairngorm. To test the idea I built a really small module based project using Cairngorm. The first day was like pulling teeth, but each day after that it became easier and easier. I think the hardest thing about getting started with Cairngorm is there is no obvious starting point. There is an excellent series of six articles written long ago that provide a great insight into the thinking behind Cairngorm and some examples of how things are done. But it doesn't really explain all the elements and how they relate to each other. There are also a number of example applications over at Cairngormdocs that I highly recommend. But looking through these examples involved a lot of opening files and trying to make sense of how the different bits relate to each other. In the end it seemed there were quite a few balls to juggle and so I put together a small document defining our project structure with some notes on how the bits relate. Below are some outtakes from that document that might help fellow Cairngorm newbies. Now keep in mind I'm still a newbie myself so I'm probably off on a few points (I'd appreciate anyone who knows better correcting my mistakes so I'm not spreading mis-information). Each point looks at a typical folder you'll need for a Cairngorm project and their purpose :

  • business : The business folder contains Services.mxml which defines all web service definitions (ie. HTTPService, remoteObject etc). Also add Delegate files here. Delgates initiate the service calls and listen and respond to results/faults.
  • command : Create a Command for each action. Commands are called from the Views in response to user interaction. They could update the model directly or use a Delegate to make a service request.
  • control : The Controller connects events to commands so that when the view dispatches an event through the CairngormEventDispatcher the relevant command is called. These connections are made using addCommand().
  • event : define the custom events (that the control connects to a command) that will be called by the view to trigger commands.
  • model : The Model stores all required state data. Bind views to the model properties so they reflect changes to the model. Update the model through commands or in response to Delegate results.
  • view : The basis for all views in our project will be modules and hence in same folder as the main application file. But it still makes sense to encapsulate many view functions within their own components. These should be stored here.
  • vo : Value Objects (vo's) represent more complex elements of the model. Store value object definitions here.

Monday, August 13, 2007

Victorian Adobe User Group : August Meeting

The August meeting of the Victorian Adobe User Group will be taking place this coming Thursday (16th August, 2007) starting at 6 PM. This month Chris Burgess will be taking a look at web security in relation to Web 2.0, AJAX, RIA development. I doubt we can ever spend enough time learning more about web security. So I'm very much looking forward to Chris's talk.

We'll also be taking a look at the second part of the Actionscript 3 video tutorial from Cartoon Smart.

If you're in the state, available and interested it will be great to see you there. The venue has a limited window of easy access so make sure you check out the access details (note : site still branded as MUV) before coming.

Thursday, August 09, 2007

Flash Quicktime Controller : Quicktime API

In the last two posts I've been looking at communication between Flex and Javascript using ExternalInterface. With the final goal being to create a Flex controller for a Quicktime movie (why?). In this post we'll take a look at the Quicktime API and some examples of how we would use it to communicate with Flex.

The Quicktime API is broken down into 4 sections :
  • Movie Commands
  • Quicktime Properties
  • Movie Properties
  • Track Properties
We'll be working with the first three of these sections. As mentioned in the last post we get Flex to call a javascript function to load the Quicktime movie once the Flex application has finished loading. I'm adding the Quicktime to the page using AC_Quicktime.js (instructions and code). This script has a function named QT_GenerateOBJECTText_XHTML that returns the required string for the embed which I add using innerHTML:
function qt_add(src)
{
var str = QT_GenerateOBJECTText_XHTML(src,'320','240',
'',
'autoplay','true',
'name','qt_mov',
'id','qt_mov',
'controller','false',
'emb#bgcolor','black',
'align','middle');

var o = document.getElementById('qt');
o.innerHTML = str;

interval_ID = window.setInterval("qt_Status()",100);
}

The Quicktime movie needs to load completely before we can inform Flex of the movies duration and current position. To do this we need to use GetPluginStatus(). This function returns a string with one of five possible values (Waiting, Loading, Playing, Complete, Error). By using javascripts setInterval method we can regularly poll the Quicktime movie to check it's status. Once it's status changes to "Complete" we can end the polling and inform Flex that the Quicktime movie is ready. The code to check the load status looks like this (assuming a Quicktime movie with an ID of "qt_mov"):
var s = document.qt_mov.GetPluginStatus();

if(s == "Complete")
{
window.clearInterval(interval_ID);
//tell Flex app movies length
get_qt_duration();
}
I'm going to tell Flex that the movie has loaded by sending it the movies duration (in milliseconds) using the GetDuration method. Within Flex this value is used to set the HSliders maximum value :
 function get_qt_duration()
{
var d = document.qt_mov.GetDuration();

var o = document.getElementById('QT_SWF');
o.set_qt_duration(d);
}
You'll also notice in the status script that we setup another setInterval to regularly check the position of the movies playhead. We can get the time elapsed using GetTime. Within Flex we use this to set the HSliders value.
 function set_qt_time()
{
var d = document.qt_mov.GetTime();

var o = document.getElementById('QT_SWF');
o.set_qt_time(d);
}
Thats really all the information I need to send from the Quicktime movie to Flex. There is of course a few things I'd like to be able to do from Flex. Lets start with the basics ; I want a button to Play/Pause the movie. I don't want to go into the mechanics of the Flex side as I'm assuming that this is a common enough process. But in javascript I decided to go with a function to start and a function to stop the Quicktime movie:
 function qt_play()
{
document.qt_mov.Play();
play_state = true;
}

function qt_stop()
{
document.qt_mov.Stop();
play_state = false;
}
It really doesn't get any simpler than methods called Play and Stop. The next thing we want to be able to do is drag the slider in Flex and then update the Quicktime movies position. We can do this using the setTime method. But there is a small problem. Setting the movies position stops the movie. So you need to follow setTime with a Play() command. But in our example we won't want it to play if the movie is paused. Hence the play_state variable in the last two functions. Now we only restart the movie if the play_state is true :
function update_qt_time(t)
{
document.qt_mov.SetTime(t);

if(play_state)
{
document.qt_mov.Play();
}
}

In Flex we are listening to the sliders thumbPress and thumbRelease events. I respond to the thumbPress by setting a variable called slider_drag_state to true. This is because I don't want the slider to update while I'm dragging it. On thumbRelease we call the javascript function update_qt_time with the new slider value and the Quicktime movies position is updated.

There is a lot more we could do with our Quicktime controller. But this is just a very basic proof of concept to check what is and isn't possible before moving onto the real application later in the year.

Wednesday, August 08, 2007

Flash Quicktime Controller : Javascript To Flex

In my last post we started looking at creating a Flex controller for a Quicktime movie. Specifically we looked at calling javascript functions from Flex using ExternalInterface. This time we'll talk about calling Flex functions from javascript.

As you may remember we called a javascript function after the Flex creationComplete event is fired so the Quicktime movie doesn't load until after the Flex application. Next we'd like to tell the Flex controller that the Quicktime movie is loaded. I'm not going to talk about the Quicktime API in this post so lets assume that there is a mechanism for testing the load state of the Quicktime movie. We have a javascript funtion qt_status which is listening for the Quicktime movie to finish loading. When the load is complete we want it to call a Flex function. For this to work we need to register this event within Flex before it's needed by the javascript function. Once again we'll use the creationComplete event (i.e before we load the Quicktime movie) to register the available functions.
ExternalInterface.addCallback("qt_complete", qt_complete);
As you can see we use ExternalInterface addCallback and send it a string representing the function name to call from javascript (can be different from the actual function name) and the actual Flex function name this refers to. As discussed in the previous post you need to check for the availability of ExternalInterface before adding this callback. Once created you can call this function using javascript, adding parameters if required , like this :
var myFlexApp = document.getElementById('QT_SWF');
myFlexApp.qt_complete(myParam);
For this to work the Flex applications ID needs to be set to 'QT_SWF'. With this done it's really simple to get javascript to communicate with your Flex application. In the next post we'll look at the Quicktime API and using it to interact with our controller.

Tuesday, August 07, 2007

Flash Quicktime Controller : Flex To Javascript

For the last few days I've been prototyping a Flex controller for use with Quicktime movies. The prototype is for an upcoming project that needs to interact with videos from a number of systems. At least one of those systems doesn't publish to Flash.

I'm going to talk about this over a few posts. In this first post we'll look at calling javascript functions from Flex.

In the end I used a HSlider component to create the scrubber and then added a Button to play/pause the movie. The interaction was handled by ExternalInterface on the Flex side and within the page javascript was used to communicate with the Quicktime plugin using it's API.

ExternalInterface is extremely easy to use. You simply need to pass the javascript functions name to the call method:

ExternalInterface.call("functionName");

You can also add parameters (required by the js function) after the function name. ExternalInterface isn't available in all browsers so you should wrap this call in a conditional to check if ExternalInterface is available :

if (ExternalInterface.available)
{
ExternalInterface.call("functionName");
}

Now all you need is a javascript function in your page to respond to this call. In my prototype
I don't want Quicktime to load until after the Flex app has loaded. So I created a js function called swf_init that is called after Flex's creationComplete event. This function adds the Quicktime movie to the page. In the next post I'll talk about creating callbacks with ExternalInterface so javascript functions can talk to our Flex app.

Friday, August 03, 2007

Flickr v YouTube : Crisis Response

Just reading a post from the Flickr blog about photos people have been posting about the Minneapolis bridge collapse. Once again I was fascinated by the perspective on news events that we get from the Flickr community. The world news services invariable present a very narrow and predictable window onto events. But Flickr allows a wide range of individuals to share these moments from their perspective.

One question that came to mind as I browsed the Flickr images relates to how video sharing services respond to these events. To test this I used the same search terms on YouTube as had been used in Flickr. The contrast was amazing. There were no personal videos of the event on YouTube (except for headshot of some guy talking about how he heard about it). Every video was taken from the news. Why is this? Does it tell us something about the communities that use Flickr compared to YouTube? Does it tell us something about the quite different relationship with have to photographs as compared to video? Is it really just a reflection on the availablity of still cameras compared to video cameras. My guess is that it's a combination of all of these (and no doubt a few I haven't considered). What are your thoughts?

Wednesday, August 01, 2007

FFC : Button - Limitations

After making good progress developing my own LinkButton Fireworks Flex Component (FFC) I was keen to take this a bit further by extending one of the existing FFC's. The natural progression from the LinkButton was to take a look at the Button component. If you installed the Flex Style Explorer you can quickly have a play with the available style options for the Button. There are a number of styles that the LinkButton and Button share. But you'll quickly notice one big difference. The Button has a background (all states) with a gradient and you can change the gradients colors and alpha. The fill colors are controlled using the fillColors array. It looks something like this:

fillColors: ['#FFFFFF','#CCCCCC','#FFFFFF','#EEEEEE'];

The first two values represent the colors for the up states top and bottom colors respectively. The second two values represent the colors for the over states top and bottom colors respectively. The down state is controlled by the themeColor. It turns out to be pretty easy to display changes to the fillColors values by setting the fills gradient.nodes color. The nodes is an array with the Button background having two nodes. You would set the color of one node like this :

var vals   = Widget.elem.customData["currentValues"];
bg_obj = Widget.GetObjectByName("up_fill");
bg_obj.pathAttributes.fill.gradient.nodes[0].color = vals[8].value;

Setting the fillAlphas is a similar process except that you use the gradient.opacityNodes color. There is one crucial difference and that is the addition of an alpha component to the color value. For example, '#FFFFFFFF' is a white opacityNode set to 1.0 (no transperancy); '#FFFFFF00' is a white opacityNode set to 0.0 (full transperancy). The tricky bit here is working out the hex values for the alpha component. Perhaps there is a neat line of javascript that someone could suggest to sort this out. But in the end I wrote a function with a series of conditionals to set values at 0.05 increments. A bit awkward but effective enough for my needs.

This was all good. But as I was working through these issues I finally came to an impasse. As you can see the fillColors property is an array. That's alright we can have an array. But to my knowledge we can't have an array with a color picker for each index. That means hand typing the colors and I was really aiming for better. The other option is to use four values and to combine them for MXML output. This may be an option and I'll probably explore this option. But this got me thinking. What would be great is if you could develop a Flash panel for individual components that shows inside the Symbol Properties and allows you to set properties using a GUI (ie. like the Flex Style Explorer). Ideally this swf just needs to exist alongside the graphic and jsf files for it to be used. So if Button.swf existed in your custom component folder it would become the components editor.