Realtime MP3 Decoding in Actionscript 3

So did you ever try to play Shoutcast streams in Flash? Did you run into memory leaks? Did the playback sound pitched or otherwise screwed? Fear no more. Let me introduce you to as3icy.

as3icy is a drop-in replacement for the Flash Player’s Sound object that can reliably play Shoutcast, Icecast and Limewire MP3 streams. And it extracts metadata info from the stream in real time. It also reliably plays VBR MP3.

Continue reading

Posted in AS3

SWFtrospection

Open Flash CS4, create new AS3 FLA, add as3swf.swc and paste this on frame 1:

import com.codeazur.as3swf.SWF;
var swf:SWF = new SWF(root.loaderInfo.bytes);
trace(swf);

Trace output:

[SWF]
  Header:
    Version: 10
    FileLength: 149405
    FileLengthCompressed: 149405
    FrameSize: (550,400)
    FrameRate: 24
    FrameCount: 1
  Tags:
    [69:FileAttributes] AS3: true, HasMetadata: false, 
      UseDirectBlit: false, UseGPU: false, UseNetwork: false
    [09:SetBackgroundColor] Color: #FFFFFF
    [86:DefineSceneAndFrameLabelData] 
      Scenes:
        [0] Frame: 0, Name: Scene 1
    [82:DoABC] Lazy: true, Length: 149219
    [76:SymbolClass] 
      Symbols:
        [0] TagID: 0, Name: Untitled_fla.MainTimeline
    [01:ShowFrame] 
    [00:End]

Excercise: Draw something on stage, and run the code again.

Want more? Drop by my session Hacking SWF at FITC Amsterdam (Feb 22th, 16:00).

[Edit] Jim Cheng deserves credits. He was the one who whispered “root.loaderInfo.bytes” into my virtual ear on IM.

Back when Twitter was called FlashCoders

Back when Twitter was called FlashCoders, there was a ragtag bunch of rebels who refused to bow to the Empire.

The Rebel Alliance had mastered the ancient art of wielding the __proto__, an elegant weapon for a more civilized age. Its sharp underscores could slice through any object. So cleanly, in fact, that members could be attached to new objects and stay alive.

The Empire loved to twist the Prototype in unnatural ways. But the Alliance refused to turn to the Dark Side.

“A Jedi’s strength flows from the Prototype,” said Obiyang. He was the wise mentor of the Alliance, preserving the Old Ways in his quantum archives. Obiyang was the first to achieve MovieClip fusion by plunging his __proto__ deep into the Prototype.

Count Moockoo was a double agent. He maintained a cozy relationship with the Empire whilst feeding information to the Rebels.

Skypenner developed an unhealthy obsession with parenting issues. He challenged Jabba Grossman to a duel in the Beta quadrant, brandishing an ECMA-262 spec-tronator. But Grossman laughed at Skypenner and returned to eating frogs.

(by Robert Penner on the Grumpy Old Flashers mailinglist)

Hacking SWF – Everything You Never Wanted To Know About Shapes In Flash

I have been inbetween projects the last weeks and thought i could do something productive while i’m idle, so i created as3swf, a low level Actionscript 3 library to parse, create, modify and publish SWF files.

At the same time i experimented with iPhone development, as we at côdeazur have some commercial iPhone work lined up. Part of those experiments involved Core Graphics/Quartz programming, and the old grumpy Flash developer in me immediately thought it would be cool if i could reuse Flash vector art in my iPhone applications. More details on that here: Shape Export to Objective-C.

With as3swf (which parses SWF shapes down to the bone) i already had a powerful weapon in my hands. I’d “just” had to extend it to generate Objective-C source code from a SWF shape. SWF shape records translate almost directly to AS3 drawing API calls (so i thought), and thus also to the similar Quartz Core Graphics API calls. I couldn’t have been more wrong.

Continue reading

Undocumented SWF Tags written by MXMLC

While testing my AS3 SWF library as3swf yesterday, i found that MXMLC (the compiler that comes with the Flex SDKs)  writes undocumented SWF tags to the SWFs it produces.

I was able to identify two so far:

ProductInfo (Tag ID 41)

The ProductInfo tag contains infos about the tool used to generate the SWF, as well as the date and time the SWF was compiled. It also contains info about the “Edition” of the software used (see below), and although this seems to be always set to “None” in Flex Builder 3 and Flash Builder 4, it potentially could become a privacy issue, especially being an undocumented feature (you better know about this tag just in case you accidentally publish commercial work with your non commercial Flash Builder license).

  • ProductID (UI32)
    0: Unknown
    1: Macromedia Flex for J2EE
    2: Macromedia Flex for .NET
    3: Adobe Flex
  • Edition (UI32)
    0: Developer Edition
    1: Full Commercial Edition
    2: Non Commercial Edition
    3: Educational Edition
    4: Not For Resale (NFR) Edition
    5: Trial Edition
    6: None
  • MajorVersion (UI8)
  • MinorVersion (UI8)
  • BuildLow (UI32)
  • BuildHigh (UI32)
  • CompilationDate (UI64)
    Milliseconds since 1.1.1970

Examples:

Flex 4.0 – [41:ProductInfo] ProductID: 3, Edition: 6, Version: 4.0.0.7791, CompileDate: Fri Aug 21 05:18:21 GMT-0300 2009

Flex 3.2 – [41:ProductInfo] ProductID: 3, Edition: 6, Version: 3.2.0.3958, CompileDate: Fri Aug 21 05:23:22 GMT-0300 2009

DebugID (Tag ID 63)

This tag is written to SWFs that are enabled for debugging. It contains a 16 byte UUID.

  • UUID (UI8[16])

Example:

[63:DebugID] UUID: b8f36d6a-c735-a340-daa7-44730af92505

Reference

Flex SDK:

Community:

AUPEO!

In case you were wondering what i have been working on in the last few months (and what will keep me busy in the coming months).. AUPEO! is a brand new platform that combines music and community – online, offline, on the road, on the web, on your desktop, on your devices.

I can’t tell too much just yet but i think it’s safe to say that it’s going to seriously rock the tardis. It will feature an open REST API for your integration pleasures, it will come with a super sweet AIR application that i am sure you will love (not only because it will be 100% open sourced), and the site (handcrafted in Rails and designed by one of the coolest design houses in the universe) is definately going to please your eyes and ears.

Be one of the first to play with it, sign up for the closed beta today!

AUPEO!

Custom Installer For Adobe AIR Applications

I need a custom installer for an AIR application i’m currently developing. That’s because my AIR app needs additional functionality that the AIR runtime doesn’t provide (specifically: detecting USB storage devices, act as a TCP socket server, talk to Last.fm scrobbler plugins). For that purpose i wrote a local RPC socket server gateway in C (one for Mac OS X and one for Windows) which always runs once the user logs in to her OS. The AIR application can then call methods on that local gateway, or receive events.

The problem is that the user needs to install the RPC server before she installs the actual AIR application. The install process should be seamless (one installer installs RPC server, AIR runtime if needed, and the application itself in one go) and the installer should be as small as possible. Currently there is no info available from Adobe on how to write custom installers that automatically download/install the AIR runtime if needed (is there?).

Artemis is another project aiming at extending AIR using a local socket server, but it seems that the project has been shut down because of the reasons stated above.

So i have been pulling out my hair lately on how to solve that problem.

I think i found a feasible solution. I am not sure because i haven’t tested all this, but i wanted to throw it online for discussion. The drawback is that the user needs to install your application with a OS native custom installer.

First you write standard installers for both Mac OS X and Windows, that install the local socket server either as a service/daemon or as an agent so that the server always starts at system launch or user login. Nothing special here yet.

The trick would be to write a simple SWHX application that basically implements the code included with the AIR Installer badge. That helper application can then be included with the installer, which executes it after the local socket server has been installed.

As i said i haven’t tested this yet (will do soonish), but this should work, no?

The question remains why i don’t just use SWHX for the main app and screw AIR alltogether.

FZip Alpha Release: Create And Modify ZIP Archives

FZip has been around for some time now, and people seem to like it. However one feature has been asked for repeatedly: In addition to reading ZIP archive, people want to be able to create new (and modify existing) archives.

So i finally sat down this weekend and added that.

The code is not tested very well (it works for me but may not work for you) and has no ASDocs yet, so i release it as an alpha version, with the hope of massive bug feedback.. :)

Download: fzip_1_0_52_alpha.zip fzip.zip

New methods in class FZip:

  • addFile(name:String, date:Date, content:ByteArray)
  • addFileAt(index:uint, name:String, date:Date, content:ByteArray)
  • removeFileAt(index:uint)
  • serialize(stream:IDataOutput)

Sample code:

// Create file contents
var ba:ByteArray = new ByteArray();
ba.writeUTFBytes("Hello World!");
// Create ZIP archive and add file
var zip:FZip = new FZip();
zip.addFile("hello.txt", null, ba);
// Serialize ZIP into a new file
// (we use the Adobe AIR specific class FileStream here,
// but you can as well use ByteArray or anything that
// implements IDataOutput)
var file:File = File.applicationStorageDirectory;
file = file.resolvePath("hello.zip");
var stream:FileStream = new FileStream();
stream.open(file, FileMode.WRITE);
zip.serialize(stream);
stream.close();

FZip, AIRRemoteUpdater Upgraded for AIR Beta 2

Just a quick FYI: FZip and AIRRemoteUpdater upgrades for AIR Beta 2 are now available for download.

FZip now uses ByteArray.uncompress(CompressionAlgorithm.DEFLATE) instead of the now deprecated ByteArray.inflate(). I also tweaked FZip to throw an exception when a parsing error occurs and no event listener is registered for FZipErrorEvent.PARSE_ERROR events.

AIRRemoteUpdater now gets the local descriptor XML via Shell.shell.applicationDescriptor which was added in AIR Beta 2, and uses the upgraded FZip sources.

Enjoy, and please let me know if you run into any problems with this new release.