Comments
Richard Davies wrote: The UK has a good crop of technology pioneers in cloud computing - for example ElasticHosts, FlexiScale, Flexiant, OnApp - and also some strong government initiatives such as G-Cloud. We will have to see whether this kind of technical leadership converts into swift mass-market adoption or not.
Cloud Expo on Google News

SYS-CON.TV
Cloud Expo & Virtualization 2009 East
PLATINUM SPONSORS:
IBM
Smarter Business Solutions Through Dynamic Infrastructure
IBM
Smarter Insights: How the CIO Becomes a Hero Again
Microsoft
Windows Azure
GOLD SPONSORS:
Appsense
Why VDI?
CA
Maximizing the Business Value of Virtualization in Enterprise and Cloud Computing Environments
ExactTarget
Messaging in the Cloud - Email, SMS and Voice
Freedom OSS
Stairway to the Cloud
Sun
Sun's Incubation Platform: Helping Startups Serve the Enterprise
POWER PANELS:
Cloud Computing & Enterprise IT: Cost & Operational Benefits
How and Why is a Flexible IT Infrastructure the Key To the Future?
Click For 2008 West
Event Webcasts
Video
The way your ancestors intended

One of the primary strengths of Macromedia Director is the various media types it can combine in any application. Director can utilize most any standard graphic format, audio format, and almost every popular video technology on the market. If there is not a current media type supported Director can easily extend its feature set with an Xtra, making it infinitely expandable. This allows for amazing flexibility, but all these different formats can create some authoring hassles.

Video formats vary in capabilities, quality, and size. There is no one universal format that seems to outweigh all others for every use. Flash video is wonderful for Web delivery, and for smaller files. If you need a perfect quality video for a kiosk MPEG-2 or MPEG-4 may suit your needs. QuickTime is great for CD delivery, but there is always the hassle of having to install applications on the end user's machines. Each format has its uses but this can create some complexity for developers when trying to author with multiple formats in mind. There is also the inevitable occurrence of a late project video switch that causes some recoding to adapt to a new format. No one wants to be up late the night before a large project is due trying to rebuild everything for the switch, but is there an easier way to handle this?

Well, since we have gone this far, you can probably guess that I am going to say yes, and also explain my approach for handling this type of problem. As with any solution this approach will require some upfront planning, but the benefits can be reaped many times over. You also get the benefit of taking what I have already written and expanding on it, rather than starting completely from scratch. Here is the thought process that I went through to streamline video playback so that I would almost never have to deal with rebuilding the same old video controller again.

My first rule of programming is simply this. "If you have to do it more than once, there is probably an easier way." Any time you write a new script or behavior look for anything that can be reused. If you make a behavior to control a button, write it so that it can be reused for any type of button in the future. The basic concept can apply here as well. When constructing our video controller we need to look at ways to make it as flexible as possible. This means that we don't want to commit some common mistakes like referring to specific sprite numbers, frames, or requiring some exact order for elements to be aligned in the score. The coding should be as flexible as possible so any part of the system can be removed and it can still function.

The next step is to look at the scope of what we are building. We are creating a video controller, but we already know that this will need to support multiple formats. There are three ways we could easily handle this, each with their pros and cons.

1.  Write separate behaviors for each media type.
This can make editing code simple for each type but also creates a lot of unnecessary duplication in the code. If you want to change core functionality then you have to edit each behavior separately. Let's say we decide one day that we want the rewind button to run on mouseUp until we click play instead of while its being held down. If we have six video formats, that's six chunks of code that have to be rewritten. This is not ideal at all.

2.  Write one big behavior.
This is definitely more elegant, as we have one source to work from. In many cases I would recommend this route as it keeps all the necessary code in one place. An early approach to this behavior that I wrote years ago combined the code for the video, buttons, slider, etc., all into one behavior. It's handy to not have to keep up with the separate pieces. But when dealing with so many formats you can quickly end up with long chunks of code in a rat's nest of "if" and "case" statements. It may be nice and compact, but debugging is still a bit harder than it needs to be.

3.  Centralize all common code and split off only the parts that vary.
This approach is what I demonstrate here. The idea is to carefully plan your code so that the core behavior will handle all the general tasks, then you only split up code that is specific to a particular media type. We will accomplish this through the use of "ancestors".

So what is an ancestor? It doesn't mean you have to track your code's genealogy, but the same basic concept applies. Here is a brief example of how an ancestor can be used.

Let's say we have two animals - a cat and a dog. Both are animals, both have legs, but some properties vary. The following is a simple script for the general "animal".


Property pSound, pHasFur

On new me
  PHasFur = 1
  Return me
End

On putSound me
  Put pSound
End

	Now let's create one of each...

Cat = script("cat").new()
Cat.putSound()
--"meow"

	and a dog...

Dog = script("dog").new()
Dog.putSound()
--"arf"

Neither cat nor dog have a property named "pSound" built in and neither have a function called putSound, but both are able to use these as they have defined the "animal" script as their ancestor. Ancestors are similar to parent classes or prototypes. They simply allow one set of code to inherit all the properties, methods, and functions of another.

With this in mind, there are two ways we can approach our new controller.

  1. Create one ancestor for each new controller type.
  2. Create one script that dynamically selects an ancestor.
Either way is perfectly fine, but for my uses I think the second option will be better. With this approach the ancestor is chosen based on the type of media it finds. Because the core behavior is the same, we can swap media on a sprite over and over again without ever having to change the behavior attached to it. This allows us to focus more on the project at hand, and worry less about what type of media we just placed on screen.

The first part of the code we need is the video controller. This will be placed on the video sprite and handles all the interaction. The behavior has a few key tasks.

  1. Determine what type of media we are using
  2. Attach the appropriate ancestor
  3. Handle all video events from buttons (play, pause, seek)
  4. Track base properties of the video
Listing 1 is the beginSprite handler.

The first thing we do is to establish the type of media we are going to utilize. Using that we can check to see if we have an available script for that type and attach it. As long as we name the future scripts in the same manner we can continue to add new media types without ever touching the base code again. This becomes infinitely scalable with no hassles for existing media types.

We then grab the Director movie's tempo (it is used by some media types to calculate rewind and FF intervals) and run a prepVideo() handler. This is the first example of a handler that does not reside anywhere in the base script. PrepVideo becomes a handler we place in any new media type script to initialize and setup calls for that video. For QuickTime it might be for turning on Direct-to-Stage. For Flash we may want to calculate its playback speed/rate. We look for any common places that we may need to interact with the media and create these universal calls to adapt to each new type.

The last item we run is the doVideo() command. This is our base script handler to interpret events from buttons. We run this with the #play property to trigger the video to start up immediately.

Let's take a quick look at the doVideo() handler to see how we handle each event; then we will look at how two specific media types vary.


on doVideo me, vItem, vParam
  if not pActive then exit
  case vItem of
    #play :
      --slow director
      me.slowDirector()
      --play it
      me.playVideo()

If you look at the beginSprite handler you will see that we disable the script if a valid ancestor is not found. This prevents errors on unrecognized types. We check this at the start of the doVideo command and exit if we are not active. Next we look at what command was sent. In this case we focus on the play command. The slowDirector call is an option I have written into my code to allow Director to slow its frame rate and allow the video to claim more of the CPU if necessary. Next we call the playVideo() call to the ancestor to let it start the video. Let's look at the Flash and QuickTime versions of the ancestor scripts to see how they vary for this command.

Flash:


on playVideo me
  sprite(me.spriteNum).fixedRate = me.pInfo[#playRate]
  sprite(me.spriteNum).play()
end

QuickTime:
on playVideo me
  sprite(me.spriteNum).movieRate = 1
end

Both trigger the video to start, but each has a different approach. We now have the ability to play back two media types from the same behavior, and can keep adding more. Let's add another popular type - MPEG. MPEG Advance Xtra is a very popular solution for this, so here is its variant of this handler.


on playVideo me
  sprite(me.spriteNum).rate = 1
  sprite(me.spriteNum).play()
end

If we tried to create one large behavior for this we would have a mass of "if" and "case" statements for every command. This can make debugging difficult and gets more complex as we start finding larger and larger variations in how some media types handle different functions. Here is an example comparing QuickTime and Flash for rewinding.

QuickTime allows rewinding by simply setting the movieRate of the sprite to -2. Flash does not allow reverse playback so we instead have to fake it by calculating the time elapsed each frame and reversing the video by 2 times that amount. Here are the two scripts...

QuickTime:


on rewindVideo me
  sprite(me.spriteNum).movieRate = -2
end

Flash:


on rewindVideo me
  sprite(me.spriteNum).pause()
  --grab the time to fake the rewind
  me.pInfo[#lastTime] = the milliseconds
end

on rewindStepVideo me
  --Fake Rewind since MPEG Advance does not support it
  t = the milliseconds -  me.pInfo[#lastTime]
  --backup 2X this ammount
 sprite(me.spriteNum).seek(sprite(me.spriteNum).currentTIme - (2 * t))
  me.pInfo[#lastTime] = the milliseconds
end

Flash needs to check this every frame, while QT simply runs until we change the rate back. These differences would make a single script very unmanageable, while splitting the pieces into separate ancestors make this a very simple and elegant process.

After we code for play, pause, rewind, seek, etc., we need to make one more behavior for all the buttons. Since these buttons all address our core behavior they do not need any changes for each media type either. You can either communicate with scripts directly, use a sendSprite, or a sendAllSprites call. Here is a short overview of the differences.

  1. object.function(): This approach calls a function on a specific object, or sprite. This can be handy as it runs fast, but if there is any problem it will throw an error and stop your program.
  2. sendSprite: This is a step up from calling the object directly. It sends a message to a specific sprite, but if the handler is not on that sprite it's simply ignored. The down side is you have to know where everything is. There are many ways to handle this up front, but I find for systems where speed is not an issue, there is another approach...
  3. SendAllSprites: This command broadcasts a message out to all sprites. If the sprite has the handler it runs it, otherwise it's ignored. This can be a little slower (a very few milliseconds at most) but for a flexible system like this I find it to be very handy. You can establish buttons that span multiple frames and move media to different channels without the worry of any piece losing sight of the rest of the system.
Here is an example of a portion of the button handler that sends out the play command...


on mouseUp me
  case pWhatItem of
    #play, #pause, #stop :
      --play, pause or stop was clicked
      sendAllSprites(#doVideo, pWhatItem)

When we click the button it simply tells the sprite(s) with a doVideo command to run the specified command. This makes it very fast and easy to deploy solutions that will not break by moving frames or changing sprite orders.

You can download the example movie that demonstrates how to use this approach for QuickTime, Flash, and MPEG Advance. I have also utilized this in various portions for Real Media, Windows Media, LDMs (Linked Director Movies), Audio, or other video Xtras. Creating a new media type is as simple as copying another ancestor and adjusting the few lines of code that handle the video playback. The rest is already done for you and never has to be rewritten again.

Summary
Ancestors are a powerful way to reuse and simplify complex systems in lingo. Give them a try and you will see why it's great to be kind to your ancestors.

About Chuck Neal
Chuck Neal is CEO of MediaMacros, Inc. and owner and operator of www.mediamacros.com, a free Web resources for Macromedia Director developers. He has been involved in multimedia for over 8 years in both traditional multimedia as well as 3D animation and video. Over the years Chuck has worked on projects for a number of major clients, including Coca-Cola, United Parcel Service, and Ford Motor Company. Through MediaMacros, he strives to push the envelope of multimedia taking on full projects as well as offering advanced coding services to over 40 multimedia firms in over a dozen countries around the globe.

In order to post a comment you need to be registered and logged in.

Register | Sign-in

Reader Feedback: Page 1 of 1

Latest Cloud Developer Stories
Can you bring services from the cloud to your customers faster and have them adopt it with ease of use or bring the power of bundled services to the fingertips of your clients without creating new rigid ‘apps stove pipes'? Do you want to prevent your business running away to publ...
OCZ Technology Group, a provider of high-performance solid-state drives (SSDs) for computing devices and systems, on Tuesday announced the Z-Drive R4 CloudServ PCI Express (PCIe) flash storage solution, designed to accelerate cloud computing applications and reduce operating expe...
Many organizations have embraced, or are considering, the benefits of cloud computing – speed, flexibility, increased expertise, shared workload, reduced costs, etc. The benefits are many – but so are the risks. What are the threats to cloud security? Which parties assume respons...
In August 2011, SHI Enterprise Solutions (ESS) division launched the SHI Cloud, offering reliable and cost-effective industrial-grade cloud computing platforms. That same division achieved an 82 percent increase in revenue over 2010.
SoftLayer Technologies on Tuesday announced the immediate worldwide availability of SoftLayer Object Storage, a redundant and highly scalable cloud storage service that allows users to easily store, search and retrieve data across the Internet, with optional CDN connectivity, or ...
Subscribe to the World's Most Powerful Newsletters
Subscribe to Our Rss Feeds & Get Your SYS-CON News Live!
Click to Add our RSS Feeds to the Service of Your Choice:
Google Reader or Homepage Add to My Yahoo! Subscribe with Bloglines Subscribe in NewsGator Online
myFeedster Add to My AOL Subscribe in Rojo Add 'Hugg' to Newsburst from CNET News.com Kinja Digest View Additional SYS-CON Feeds
Publish Your Article! Please send it to editorial(at)sys-con.com!

Advertise on this site! Contact advertising(at)sys-con.com! 201 802-3021

SYS-CON Featured Whitepapers
ADS BY GOOGLE

Breaking Cloud Computing News
IceWEB, Inc.™ (OTCBB: IWEB), www.IceWEB.com, a leading provider of Unified Data Storage appliances f...