Grant Skinner

The "g" in gskinner. Also the "skinner".

@gskinner

Return of the Blue Lego

As some people have noticed, Apple has eliminated the blue lego icon that indicates a missing plugin on the iPad. I believe that this is a not so subtle way of shifting users from believing that the iPad browser is lacking something, to believing that the site they are viewing is broken.

In response to this, I’ve created the blueLego edition of SWFObject 2.2. It works exactly the same as regular SWFObject, except it will display the blue lego icon, with a link to Adobe’s get Flash Player page on iPhone, iPod, and iPad.

As of April 13, this page correctly displays content explaining to iPad users why Flash is unavailable on their device. This is the same content shown on the iPhone, which is described here. You’re obviously free to modify the iDevice alternate content or the code itself to suit your own needs.

It is released under the MIT license, and you can download it by clicking here. Whether it is useful for production or not, I leave to you. It was created more as a statement than anything.

The blueLego art was created from scratch and I’ve included the source FLA so you can modify it as you like.

It looks like this in use:

You can test it by pointing your iDevice browser to this url:

http://gskinner.com/playpen/bluelego/

Thanks to Rob Hall and others for helping spark the idea.


Edit: Copying my comment from below here, to clarify the purpose of this post:

This post was *not* a Flash pro/con, or Flash vs HTML5 statement.

Apple made a conscious decision to move from fairly and correctly showing users that they were unable to display a certain type of content (whether you like that content / technology or not), to making it look like the site itself is broken. It places the apparent blame not on Adobe or Apple, but on content providers. Regardless of your position on Flash or plugins, this is wrong, and it’s a dirty play by Apple.

This post, and the blueLego SWFObject library were intended as a light way to point out the issue and to help rectify it for site owners by letting them accurately convey why their content does not work on an iPad. It was not intended as some weak form of “revenge” at Apple.

Colorgasm Music Visualizer

While exploring the flash.sampler API this morning, I whipped together a quick demo to test its output when rapidly creating / deleting objects.

The demo turned out kind of cool in it’s own right, so I thought I’d post it. Nothing incredible, but you’ve gotta love what you can accidentally create in a couple hours and 1.8kb in Flash.

Note that I’m too lazy to add a preloader, so nothing will happen until it loads the 5.4MB music file.

One day maybe I’ll play with this some more, tie in proper spectrum analysis, a preloader, etc. *shrug* The Hype framework would probably work great as a starting point for that.

Continue reading →

The flash.sampler.* API and the Sample object

I recently became aware of the flash.sampler.* package, which gives you access to the same profiling data via AS3 that FlashBuilder uses for it’s profiler. It’s a very useful API for performance and memory profiling, offering enhanced introspection tools, more granular timing, method invocation counts, and method invocation sampling. It has been available in the Debug player since player 9.0r115, but I somehow remained aware of it’s existence until a few days ago.

Given that, I thought I’d write up a quick post about the API to help people get started with using it. The API is generally well documented in the Flex 4 language reference, so I’ll just focus on a few key methods and gotchas.

General information
Most of the API exists as methods within the flash.sampler package. Simply import flash.sampler.* (or the individual methods), and call the methods directly. The sampler API is only available in a debug player.

It’s also worth knowing that along with the API, the Flash player allows you to specify your own preload SWF, which will be loaded prior to other content in debug players. You can specify this in the “mm.cfg” file – the details are documented in the Flex API docs for the sampler package. This mechanism is what FlashBuilder uses to funnel sample data to the profiler. This let’s you build your own tool chain that can be invoked on any site. There’s lots of room here for building tools that run in the browser, or that connect to a companion AIR app for inspecting or profiling content.

(as an aside – jpauclair has the best write ups of mm.cfg I’ve seen – definitely worth reading if you’re interested in profiling Flash content)

Introspection
The sampler API includes a few handy introspection methods:

getSize() // returns the size in memory of the specified object in bytes
getMemberNames() // returns an iterator object containing all of the private and public members (properties / methods) on the specified object
isGetterSetter() // checks whether a proper is defined with a getter/setter

Sampling
Sampling allows you to log all of the methods that were invoked over a period of time, and determine the amount of time each method took to execute. Here are the key methods:

startSampling(); // starts collecting sample data
stopSampling(); // ends a sampling session, and clears all sample data
pauseSampling(); // stops collecting sample data, without clearing existing data
getSamples(); // returns an iterator object (see below) containing all of the samples collected since the last clear
getSampleCount(); // returns the number of samples that will be returned by getSamples()
clearSamples(); // clears current samples data - you will generally want to call this after each getSamples() call to remove the samples you have already read.

For the most part this API is pretty straightforward. Where it gets weird is when you look at the object returned by getSamples(). Initially, I simply traced the object, and got an error saying “Property toString not found on (null) and there is no default value”.

This made me think that I was doing something wrong, and that getSamples was returning null. Then I realized that null always traces as “null”. It occurred to me that the error was actually showing that the type of the offending object was outputting null. Running describeType on the object returns its type as “*::*”. Very interesting! Apparently it is using some low-level iterator object that doesn’t even have an AS3 type (I’m trying to get more info on this).

If you ignore the weird return type, and simply iterate the object with a for..each loop (which appears to provide a determinate order for this object type, also interesting), you will get a list of Sample objects, which includes a time stamp in microseconds, and an array of StackFrame objects which contain the function’s full path/name and the SWF line number associated with it.

var o:* = getSamples();
for each (var s:Sample in o) {
trace(s.time,s.stack);
}
clearSamples();

Samples may also be instances of the NewObjectSample or DeleteObjectSample subclasses, which indicate the costs of instantiating or destroying an object respectively. The former has a type property that indicates the created object’s type. The latter has a size property that indicates the object’s size in memory at the time it was deleted. Both have an id property (presently undocumented on NewObjectSample) which lets you pair the create and destroy actions together.

With this information and some analysis, you can track time spent in any method (singularly or as an aggregate) and object creation.

I’ll be playing around with this API more over the next couple of weeks. I will likely talk about it a bit at FitC in Toronto and Flash and the City in NYC. I’m hoping to incorporate some of it’s capabilities into an updated version of PerformanceTest, and might build out some other tools around it. I’ll blog more as I learn more.

Building Framework Independent Code Libraries

I’ve recently encountered a couple of libraries that despite being 99% pure AS3 had minor dependencies on the Flex framework that prevented their use in ActionScript projects or in Flash without modification. This is unfortunate, because it limits the immediate usefulness of the libraries, and fragments the community’s access to them.

Regrettably, this approach is (unintentionally) promoted by Adobe. There is a ton of useful code distributed in the Flex SDK with minor or no dependencies on the framework, and no effort has been made to eliminate those dependencies and distribute / identify those classes for use in non-Flex projects. I’d love to see some kind of identifier / documentation for framework independent code, and have it distributed with Flash as well.

<tangent>Moreso, I’d love to see a core UI framework that is shared between Flash and Flex, and is extended (in the general sense, not necessarily via inheritance) with Flex specific functionality (and the bulk that implies). It’s time for a unified component framework in the Flash platform! But that’s a rant for another post.</tangent>

So, what strategies can you use to create framework independent libraries?

The most obvious approach is to avoid including framework dependencies whenever possible. For instance, use an Array or Vector instead of an ArrayCollection. It’s platform independent, and a lot more efficient. Almost all of the libraries I release use this approach. Of course, this isn’t always possible or desireable, so we need other solutions.

From an architecture standpoint, you can utilize inheritance, interfaces, and composition to append framework specific functionality to your core code.

Inheritance allows you to “branch” your core logic to create framework specific subclasses, including all framework imports. This comes with all the usual caveats of inheritance, including making sure you define methods appropriately to make it easy to override ones that will become framework specific. Generally you will have a functional core class to use in ActionScript projects, a Flex specific subclass, and potentially a Flash specific subclass.

Composition can provide a more flexible approach. You can build your core classes to rely on plugins that encapsulate all framework specific logic, and which define a simple interface. By default these plugins can point to a framework independent implementation (even to the classes that use them). As a simple example, you could have an ITextInputMediator plugin that exposes methods and events for working with text inputs. By default it would point to a TextFieldMediator class, but could also be pointed at a FlashTextInputMediator or FlexTextInputMediator classes.

The act of setting up these plugins could be done manually by the library user, or could use a keystone class. This class would be compiled into a project once, and would import and assign the appropriate plugins and factories when it initializes.

You can also use conditional compilation to toggle imports and logic blocks based on the environment. For the most part, this offers the cleanest approach, but you must ensure to document it clearly, as conditional compilation is not yet widely used or understood in the Flash world.

Locally, you can leverage reflection (ex. getDefinitionByName and the “in” keyword), dynamic access, and events to your benefit. The first two should be used as little as possible, because they come with unwanted side effects like reduced compile time error checking. Because the event model exists at the player level, you can listen to any event from any IEventDispatcher object, without having to reference its type directly. SPL uses this to listen for “valueCommit” events from Flex controls, without having to import the framework – it uses a local constant for the event name instead of importing the Flex event object.

As a last resort, if your library has dependencies on well encapsulated Flex framework classes (ex. utility classes like HashUtil), you could choose to distribute them with your library to make it easier for users to get running. Always test the package in isolation to ensure you have included all of the dependencies (like that pesky Version.as file), and document which classes you included, so people using your library with Flex can optionally delete the copies you included.

Making your libraries more widely usable means they can be used by more people, which is really the point to releasing them. It also helps provide a more consistent code base for all Flash platform developers, regardless of the framework they’re using. If you aren’t going to make your library framework independent, at least consider trying to architect it in such a way that another developer could more easily modify it to work without the dependencies.

Now let’s see what we can do about encouraging Adobe to embrace this idea internally. 🙂

If you have other approaches or ideas on creating platform independent libraries, feel free to share in the comments.

Silverlight, MIX & gskinner.com

As some people have noticed, I will be speaking at Microsoft MIX this year. I’m sure a few people are curious what I’m doing there.

A couple of months ago, gskinner.com was presented with an opportunity to work on a very interesting Silverlight project, with a fairly flexible timeline. I’ve been looking for an excuse to dig deeper into Silverlight for a while so it made a lot of sense. As an extension of that project Microsoft asked me to present a talk at MIX discussing the project. Regrettably, the project start was pushed back due to (not entirely unexpected) bureaucratic delays. As such, the talk will focus on a more general overview of the casual gaming market, and what opportunities exist in it for Silverlight.

That covers why I’m speaking in Vegas, but what about the politics? While I am not so naive to believe that there are no politics involved with asking me to speak (though MS assures me there are not), I am choosing not to be concerned with them. The opportunity that was presented to us was a good one – it’s a fun project, it made business sense, and it provided us with a low stress environment to really learn Silverlight development.

While my primary focus is (and remains) Flash, I am an interactive developer. I would be sorely remiss to ignore other technologies. Not only does knowledge of other technologies potentially open new project opportunities, but it lets me reinvest ideas and mental models from them back into my work with Flash. Working with C# has already sparked some new ideas for me (not to mention a few AS3 feature requests). Knowledge of alternative technologies also lets us suggest the best possible solutions for our customers or talk them out of a bad one.

We have done HTML/AJAX work in the past and continue to do small amounts of iPhone development for these same reasons. As HTML 5 matures, you can bet we will play and work with it to see how it fits (or doesn’t fit) into our offerings.

We are not jumping ship to Silverlight. Microsoft has not “bought” our loyalty, and they have assured me that working with us is more about seeing what we can do with their technology and our experience in interactive than as a political move. You’ll note that at no point do they associate me with Flash (though it is obviously somewhat implicit), and I will be minimizing comparisons between the technologies when I speak.

I’m looking forward to the conference. I’m a little hesitant with regard to my talk, because I don’t feel I’ve played with Silverlight enough to really discuss the details I’d like, but I’m excited to see what Microsoft announces, and to hang out with the community. If you’re going to be in Vegas for the event look me up!

I’m planning to blog a fair amount about my experience with Silverlight on this project, once I feel that I’ve dug deep enough to be fair. I’ll be very blunt and honest in what I find – it’s one of the risks Microsoft is taking in involving me, but also shows a level of confidence with the new version that I haven’t seen in the past.

Let me know if you have any questions, and I’m happy to answer them in the comments.


UPDATE: I just want to clarify the intent of this post. It’s not intended as a defence of working with Silverlight – I don’t believe one is necessary. I haven’t met with any hostility, but there has been a fair amount of curiousity, so I thought I would provide some information for those that were interested.

ASDocr Update for AIR 2 Beta 2

ASDocr 1.1 is available. This update provides compatibility with AIR 2 beta 2, fixes a bug that prevented multiple exclude-namespaces values from working, fixes a problem with locating the default output directory on OSX, and correctly opens the last used configuration when you restart the application.

ASDocr provides a GUI for working with ASDoc to make generating documentation for AS3 classes easy. For more information on ASDocr, read the original post on it.

To install version 1.1:

1. Uninstall ASDocr version 1.0

2. Upgrade to the AIR 2 beta 2 runtime. It can be found here.

3. Download and install ASDocr 1.1

Known issues:

There is a bug in AIR 2 beta 2 that can cause the Open HTML and Open Output Folder actions to take a long time (~30s) on some Windows XP machines.

Download:

Download for Mac OSX

Download for Windows


UPDATE: The latest version of ASDocr, with support for the AIR 2 Release Candidate can be downloaded here.

Create New Files & Projects In OSX Finder Easily

QuickFiles is a free OSX 10.6 AppleScript service plugin that lets you create new files of any kind in the Finder with a keystroke. Install QuickFiles then place files or folders that you’d like to use as templates into the “QuickFiles Templates” folder. When you run QuickFiles, simply select a template from the list, and it will be copied into your current folder.

QuickFiles also supports multi-select, so you can create two or more files in one operation. Just hold Command or Shift to select multiple templates from the list.

Best of all, everything can be controlled via the keyboard by binding a shortcut to the service (I used Command-Control-N). Hit the keyboard shortcut, type the first letter or two of the template you want, then hit enter to copy it into your current folder. The new file is selected for you, so you can immediately hit Enter to rename it, or Cmd-O to open it for editing.

I originally created QuickFiles because I was jealous of Window’s right-click menu to create new files in Explorer, but I think it’s evolved into something much more powerful and usable.

Here’s a few ways you can use it:

  • create a new blank text document
  • create a new class file, FLA, or xml file from a template file
  • create a copy of a sales letter or contract that you personalize often
  • create a new project folder with all of its sub folders and starting files already in place
  • create an alias to a file or folder that you use regularly
  • copy frequently used code libraries (including package directories) into your project

This version is only compatible with OSX 10.6 Snow Leopard. There is an older version available here, with less features, that supports early versions of OSX.

You can download QuickFiles for OSX 10.6 here. It includes the AppleScript workflow service file, and a ReadMe file that I highly recommend reading for information on installation, use, and setting up a keyboard shortcut (all very simple, not necessarily self-evident if you haven’t installed services before).

I’ve found this plugin very useful for coding, and day to day tasks. Hopefully it’s useful to other people as well.

PerformanceTest v2 Beta: Benchmark AS3 / Graphics

When I built the original PerformanceTest, I hacked it together quickly to meet a specific need I had at the time. As I used it, I found I needed more capability, and I became increasingly frustrated with both the messy code, and the poorly thought out API.

In response to feedback, and my own frustrations, I’ve completely rebuilt PerformanceTest to be more robust, extensible, feature-rich, *and* easier to use.

Core features:

  • Track time, memory usage and retained (unreleased) memory for functions.
  • Test rendering time for any display object.
  • Write simple one line tests, or build formal test suites.
  • Test suites can be built using inheritance or aggregation/composition.
  • Trace simple text results, or access robust XML reports.
  • Save XML and compare results between different versions of your code, or on different Flash players.
  • Easily build logging classes to analyze or visualize results.
  • Run multiple iterations of tests to get min, max, and deviation values.
  • Run tests synchronously, or queue them to run them asynchronously.
  • Listen for events from tests, test suites, and PerformanceTest.
  • Integrates easily with TDD by facilitating the creation of tests for time, memory, and retained memory limits.

Here’s a very simple demo:

Continue reading →