Posts Tagged ‘AIR’

Memory usage during file upload in AIR

Saturday, March 29th, 2008

Uploading files in AIR is a little bit problematic these days.

Here is the code:

<?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" showStatusBar="false" 
  initialize="onInitialize(event)">  
 
  <mx:Script>
    <![CDATA[
 
      import com.rwnage.s3.service.S3PostOptions;
      import flash.events.Event;
 
      public function onInitialize(event:Event):void {
        var accessKey:String = "0RXZ3R7Y034PA8VGNWR2";
        var bucketName:String = "rwnage_test";
        var objectName:String = "test_file";
        var contentType:String = "application/octet-stream";
        var secretAccessKey:String = "[PUT YOUR SECRET ACCESS KEY HERE]";      
 
        var postOptions:S3PostOptions = new S3PostOptions(bucketName, objectName, accessKey, 
          { contentType: contentType });
 
        var policy:String = postOptions.getPolicy();
        var signature:String = postOptions.getSignature(secretAccessKey, policy);
 
        html.htmlText = '<html><body> \
          <form name="upload" action="http://' + bucketName + '.s3.amazonaws.com/" method="post" enctype="multipart/form-data"> \
            Key to upload: <input type="input" name="key" value="' + objectName + '" /><br /> \
            Content-Type: <input type="input" name="Content-Type" value="' + contentType + '" /><br /> \
            <input type="hidden" name="AWSAccessKeyId" value="' + accessKey + '" /> \
            <input type="hidden" name="Policy" value="' + policy + '" /> \
            <input type="hidden" name="Signature" value="' + signature + '" /> \
            File: <input type="file" name="file" /> <br /> \
            <!-- The elements after this will be ignored --> \
            <input type="submit" name="submit" value="Upload to Amazon S3" /> \
          </form></body></html>';                                                     
      }
 
    ]]>
  </mx:Script>
 
  <mx:HTML id="html" width="100%" height="100%" paddingLeft="20" paddingTop="20"/>
 
</mx:WindowedApplication>

No I don’t normally use mx:script tags, its a test case.

Eventually it malloc fails and crashes. This issue is Mac only and also occurs during a FileReference (or File) upload.

Socket output progress in AIR

Thursday, January 17th, 2008

Currently when using the flash.net.Socket api, there is no way to
determine that buffered data has been written to the socket. (The flush method is non-blocking and applies only to the actionscript socket buffer).

This is a follow-up to a previous post.

This issue does not arise when using the new File api (and writing to
files), since an event has been included in
flash.filesystem.FileStream: OutputProgressEvent.OUTPUT_PROGRESS

If this (or a similar) event could be added to the Socket api, it
would allow us to:

  • Send large amounts of data on a socket (without causing large memory
    usage as data buffers in memory).
  • Measure the current progress of data being sent on the socket.

We came upon this limitation from using our AS3 http client library, and trying to send large
files as part of a multipart upload. However this issue would arise
when sending any significant amounts of data on a socket. For example, an FTP or bittorrent client would be impossible.

This issue has been discussed in other places, but is probably more
pressing now with the AIR releases.

Update: Vote on this bug (FP-6)

popen’ing

Wednesday, November 7th, 2007

I updated airake to work on windows (thanks Todd). Instead of using system (or %x), I am trying IO.popen:

IO.popen(@cmd) do |f|
  @output = f.read
  @process = Process.waitpid2(f.pid)[1]
end

and in windows you’ll need to cmd.exe /c it:

@cmd = RUBY_PLATFORM =~ /win32/ ? "cmd.exe /c #{cmd}" : cmd

This thread was helpful and I popened a new airake/runner.rb version. The FCSH daemon still doesn’t work in windows yet.

Update: Google Reader AIR app

Wednesday, October 31st, 2007

Download GReader-0_1_2.air

I updated the app to work in Leopard. I have no idea why but using the url, http://www.google.com/reader/view, instead of http://reader.google.com fixed it. I think that might mean there is a redirect issue? I changed the dock icon unread count to just show the number in the top right. Also I added an option to enable the hicksdesign google reader theme. I had to mess with it since apparently AIR webkit doesn’t support the css data uri scheme, which is annoying.

I apply the style through the javascript bridge:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
    [Embed(source="/assets/styles/greader/greader.css", mimeType="application/octet-stream")]
    private var cssClass:Class;

    private var html:HTML;
    ...

    public function applyStyle(e:Event):void {
      var cssByteArray:ByteArrayAsset = ByteArrayAsset(new cssClass());
      var css:String = cssByteArray.readUTFBytes(cssByteArray.length);
      
      var document:JavaScriptObject = html.htmlControl.window.document;
      
      var head:JavaScriptObject = document.getElementsByTagName("head")[0];
      var node:JavaScriptObject = document.createElement("style");
      node.type = "text/css";
      node.appendChild(document.createTextNode(css));
      head.appendChild(node); 
    }

Google Reader AIR app

Monday, October 29th, 2007

Download GReader-0_1.air

I was playing around with the actionscript to javascript bridge and built this Google Reader AIR app:

I find the unread count from ‘reading-list-unread-count’:

1
2
3
var html:HTML = ...
var window:JavaScriptObject = html.htmlControl.window;
var unread:String = window.document.getElementById("reading-list-unread-count").innerHTML.toString();

Then I generate a dock icon (ignore all the hard coded pixel math):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
[Embed(source="/assets/app_icons/greader/icon_128.png")]
private var iconClass:Class;

[Embed(source="/assets/fonts/Verdana.ttf", fontName="GReaderDockIconFont", mimeType="application/x-font-truetype")]
private var fontClass:Class;
....

private function draw():void {  
  var icon:BitmapAsset = BitmapAsset(new iconClass()); 
      
  var shape:Shape = new Shape();
  shape.graphics.beginBitmapFill(icon.bitmapData, new Matrix(), true, false);
  shape.graphics.drawRect(0, 0, dimensions, dimensions);
  shape.graphics.endFill();
  
  shape.graphics.beginFill(0xDF0013);
  shape.graphics.drawCircle(32, dimensions - 32, 32);
  shape.graphics.endFill();
  addChild(shape);
  
  if (unreadCount > 0) addChild(buildText());      
}

public function buildText():Bitmap {
  var countText:TextField = new TextField();
  countText.embedFonts = true;

  var format:TextFormat = new TextFormat();
  format.font = new fontClass().fontName;
  format.color = 0xFFFFFF;      
  format.size = 26;
  format.align = TextFormatAlign.CENTER;
  
  countText.defaultTextFormat = format;
  countText.selectable = false;      
  countText.text = unreadCount.toString();
  countText.height = 32;
  countText.width = 54;
  
  var bitmapData:BitmapData = new BitmapData(64, 32, true, 0x00000000);
  bitmapData.draw(countText);      
  var bitmap:Bitmap = new Bitmap(bitmapData);
  bitmap.smoothing = true;
  bitmap.y = 128 - 52;
  bitmap.x = 4;
  return bitmap;
}

Set the dock icon with the generated bitmap data:

1
2
if (Shell.shell.icon is InteractiveIcon) 
  InteractiveIcon(Shell.shell.icon).bitmaps = icons;

For more info on dynamic dock icons, see Generating Dynamic Dock and System Tray Icons in AIR

I think the next step is taking a bunch of greasemonkey js scripts and adding them in. This might be how you would do that:

1
2
3
4
5
6
7
8
var html:HTML = ...
var window:JavaScriptObject = html.htmlControl.window;      
var head:JavaScriptObject = window.document.getElementsByTagName("head")[0];         
var script:JavaScriptObject = window.document.createElement('script');
script.type = 'text/javascript';
//script.src = 'http://lolcats.com/script.js';
script.innerHTML = "alert('HAI.. KTHXBYE');";
head.appendChild(script);

Update: I’ve seen it tack the CPU when interacting in a couple places so I will try to figure out if its AIR webkit being buggy or me. Also will fix the external link lameness at some point.

Update: Oops. Looks like it doesn’t work in Leopard.

browsair – Letting sites live in your dock

Saturday, October 13th, 2007

I wrote an AIR project generator for airake called browsair. It will build you a AIR webkit browser app targeted at a web site, so you can let it live in you dock (or tray whatever), instead of that 4th tab on the 2nd firefox window.

Theoretically someone could make a packaged browser + greasemonkey + stylish AIR app for particular web sites that growl notifies and lives in the dock and be more in your face; but this scaffold right now is pretty basic.

I should also mention there is a website called airifier which does this as well, except I think they give you a packaged app only, without the source.

I also got a bunch of fixes into this version of airake; packaging is fixed, and there is a task for creating certificates, among other things. I just deployed version 0.2.4 to rubyforge so it should be up by the time you read this.

The usage:

browsair GReader http://reader.google.com path/to/rss_icon_128x128.png

Creates an AIR project for a google reader AIR app. In the GReader project, run:

rake air:package CERTIFICATE=path/to/cert.pfx

If you need to generate a certificate:

rake air:certificate CERTIFICATE=../ducktyper.pfx

I built a couple already if you want to bypass all that compiling:

(If you don’t have the AIR runtime installed, get it here)

Updated airake to support AIR/Flex Beta 2

Friday, October 5th, 2007

I updated airake to support new AIR/Flex beta 2 build.

sudo gem update airake

I changed the fcsh tasks to:

rake fcsh:start
rake fcsh:stop
rake fcsh:restart

airake – Rake tasks and generators for adobe AIR apps

Tuesday, September 11th, 2007

airake gives you tasks for compiling, debugging, testing and packaging Adobe AIR applications. It also has a basic project generator/scaffold. All this was made possible because of the prolific newgem and rubigen gems.

To get started, checkout airake.rubyforge.org

The tasks and project might be a little Flex specific (cause of the particular project we are working on), so feel free to poke around or contribute back. Also I only tested it on MacOSX.

Some of the FCSH (flex compiler shell) daemon and wrappers are from the Sprout project, so be sure to check them out.

Open sourced (Flickr OpenGL C# Library)

Tuesday, March 20th, 2007

Crossposted from cellardoorsw.com:

I GPL licensed all the source to Slickr (that I wrote), and released it into the wild. You can view the trac page, or go straight to the source. Its all C# and OpenGL goodness with some gnarly calls to some windows api’s (for extra’s nothing critical). There are a couple NAnt build scripts for when I was trying to get it working under linux, but you’ll want Visual Studio (2003) to get started quick (and look at the README).
Who knew it would be such a pain to draw text and did I really need to query the monitor power state?

I’ll try to write an overall design doc soon, but until then start at any of the Entrypoint’s. And in the end all that is really going on is this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
private void DrawGLTexture(SlickrImage image)
{
  PointFloat p = image.GetMovement(window.Width, window.Height, true);
  float scale = image.GetScale(window.Width, window.Height);
  float fade = image.GetPercentageFade();
  int texWidth = image.TextureWidth;
  int texHeight = image.TextureHeight;

  Gl.glMatrixMode(Gl.GL_PROJECTION);                                  // Select The Projection Matrix
  Gl.glLoadIdentity();                                                // Reset The Projection Matrix
  float r = (window.Width/scale);
  float b = (window.Height/scale);

  Gl.glOrtho(0, r, b, 0, -1.0f, 1.0f);
  Gl.glMatrixMode(Gl.GL_MODELVIEW);                                   // Select The Modelview Matrix
  Gl.glLoadIdentity();

  Gl.glEnable (Gl.GL_BLEND); // for text fading
  Gl.glBlendFunc (Gl.GL_ONE, Gl.GL_ONE_MINUS_SRC_ALPHA);
  Gl.glColor4f (fade, fade, fade, fade);

  float posX = p.x; //stepX +
  float posY = p.y; //stepY +

  image.DrawAtPoint(posX, posY);

  Gl.glDisable(Gl.GL_BLEND);
}

If you are interesting in working on bug fixes, enhacements, or whatever give me a shout.

Javascript IE PNG fix

Monday, February 26th, 2007

I adapted the pngfix.js to be rails friendly. Not that I should be using image tags anyway.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
var arVersion = navigator.appVersion.split("MSIE");
var version = parseFloat(arVersion[1]);

if ((version >= 5.5) && (document.body.filters)) {        
  var i;
  var length = document.images.length;
    for(i = 0; i < length; i++) {
      var img = document.images[i];
      var re = /\w+\.[Pp][Nn][Gg]\w*/;
      if (img && re.exec(img.src)) {
        var imgTitle = img.title ? "title='" + img.title + "' " : "title='" + img.alt + "' ";
        imgStyle = img.parentElement.href ? "cursor:pointer;" : "";
        imgStyle += "width:" + img.width + "px; height:" + img.height + "px;";
        imgStyle += "filter:progid:DXImageTransform.Microsoft.AlphaImageLoader (src=\'" + img.src + "\', sizingMethod='scale');";
                
        var strNewHTML = "&lt;span " + imgTitle + " style=\"display:inline-block; " + imgStyle + " \"></span>";

        img.outerHTML = strNewHTML;
        i = i - 1;
    }
  }
}

download

Then add this somewhere in your <head>

1
2
3
<!--[if lt IE 7]>
<script defer type="text/javascript" src="/javascripts/pngfix.js"></script>
<![endif]-->

The only other requirement is you specify a width and height on your image_tags


<%= image_tag("fam/date.png", :alt => "ical", :width => "16px", :height => "16px") %>

Though you should use CSS for most images, this is a fast way to make your png’s work in IE6.