Wednesday, August 25, 2010

DisplayObject inheritance in Corona

In Corona SDK, DisplayObjects are actually native C++ objects under the hood. Lua makes it relatively easy to expose native functionality in the Lua language, but then a Lua "userdata" loses the "object-oriented" capabilities of a Lua table.

Corona goes way beyond the simple solution with this problem; a Corona DisplayObject behaves partially as a normal Lua table, giving you the ability to add properties to it. This is a great convenience, but because of the way Lua is implemented, it cannot give you the full ability to "override" methods and properties that Lua can for generic tables.

Here's a more detailed description and example.

Corona Display Objects are actually C++ native objects internally. The way Lua implements binding native pointers is with "userdata", which sets a metatable, used for looking up methods and properties, giving you a very powerful kind of extensibility. However, userdata metatables cannot be replaced by Lua code; this is a measure defined by Lua (see "Programming in Lua" for details).

Normally, native objects bound to Lua in this way do not behave like tables. There are a number of examples in Corona of this. They may have properties and/or methods but are not extensible. The fact that Display Objects behave partly like tables is a convenience feature. The alternative would have been having a DisplayObject field for custom data, allowing you to access your own data associated with a DisplayObject, for example. Raising this functionality directly into the DisplayObject is conceptually simpler (although more work to implement). But the underlying native bridge is constrained by the way Lua implements it, and we view this as a feature, not a bug, since allowing an instance of a native object to selectively override parts of its interface could be profoundly destabilizing and possibly insecure.

Meanwhile, it is possible to "extend" Corona DisplayObjects as tables, by using Lua's built in features. This is not exactly like Lua's normal capabilities, because we can't replace the DisplayObject metatable in this case. However, it is very useful if you want to extend DisplayObjects.

So here's a code example of how to accomplish this. An image is loaded by makeProxy(), but the actual object returned is a table. Any properties/methods not defined by the proxy table are forwarded to the underlying DisplayObject.

The basic method is described in http://www.lua.org/pil/13.4.4.html.

function makeProxy(params)

local t = display.newImage(params.background)

local _t = t

-- create proxy
local t = {}

-- create metatable
local mt = {
__index = function (t,k)
print("*access to element " .. tostring(k))
return _t[k] -- access the original table
end,

__newindex = function (t,k,v)
print("*update of element " .. tostring(k) ..
" to " .. tostring(v))
_t[k] = v -- update original table
end

}

setmetatable(t, mt)

function t.bar()
print("bar on you!")
end

return t
end

aPuppy = makeProxy({background="puppy.jpeg"})

aPuppy.y = 200

function aPuppy:foo()

print("foo on you!")
end

aPuppy:foo()
aPuppy:bar()

Monday, May 10, 2010

Android GUI resources

Here's a great resource for UI design on Android:

Android App Developers GUI Kits, Icons, Fonts and Tools

Tuesday, April 20, 2010

Progress with Android 1.5

Recently in Ansca's Corona Lab we decided to support Android 1.5. As of today, the Corona 2.0 beta supports Android 2.0.1. We have several requests to support earlier versions from our Japan group and several customers. And as you can see from the following data, there's a lot of older phones out there:


(Source: Google)

After experimenting a bit, it looks like porting to Android 1.5 isn't too hard. There are a few missing APIs compared to the newer SDK, but for the most part that's ok. Here's a screenshot of Core Damage running in the Android 1.5 emulator:



Sound is working as well. Internally it looks like there's some missing OpenGL functionality as well, so I'll have to do some exploring to see what that means for the Corona rendering engine. Also, I don't have a device to test it on, although someone in the office has a 1.6 phone. I'm sure we can solve that problem.

Nonetheless, this is an exciting development, as it opens Corona's horizons much wider! We should be able to get this into an upcoming Corona beta update in the next couple weeks.

Friday, April 16, 2010

Objective-C to Lua translator

Supposing, of course, that speculation is correct and iPhone developers will be prohibited from originating their apps using any language other than C, C++, and Objective-C, it's only natural that one should translate those languages to the language of one's choice. I've spent a few hours trying to do just that. Naturally, I used Lua's excellent LPEG library, and googled for bits of Objective-C grammar.

Here's the input to the translator:

// This is a comment
#import "foobar"

int i = 1;

-(void)mySelector:(int)count
{
    int foo = 3;
    int bar;
}

The results of the translation are:

-- This is a comment
 require "foobar"
 local i = 1; function mySelector(count) local foo = 3; local bar; end 


The Lua code is:

require 're'

parser = re.compile[[
 S <- <externaldeclaration>*
 WS <- [ %nl\t]+
 NWS <- [ %nl\t]*
 IDENTIFIER <- ([%a$_] [%a$_%d]*)
 LINECOMMENT <- '//' {[^%nl]* %nl} -> '--%1'
 COMMENT <- '/*' <CLOSECOMMENT> -> '--'
 COMMENTMIDDLE <- {.} <CLOSECOMMENT> -> '%1'
 CLOSECOMMENT <- '*/' / <COMMENTMIDDLE>
 IMPORT <- ('#import' <WS> <filespecification>) / ('#include' <WS> <filespecification>)
 filespecification <- (["<] {[%a%d%s/_]+} [">]{%nl}) -> 'require "%1"%2'
 preprocessordeclaration <- <IMPORT> 
 identifier <- <IDENTIFIER>
 DECIMALLITERAL <- {%d+} <IntegerTypeSuffix>? -> '%1'
 IntegerTypeSuffix <- [uUlL]
 STRINGLITERAL <- { ('"' ( <EscapeSequence> / [^\"] )* '%') } -> '%1'
 EscapeSequence <- '\' [btnfr"'\] / <OctalEscape>
 OctalEscape <- ('\' [0-3] [0-7] [0-7]) / ('\' [0-7] [0-7]) / ('%' [0-7])
 constant <- <DECIMALLITERAL>

 externaldeclaration <-
  <WS>
  / <COMMENT> 
  / <LINECOMMENT> 
  / <preprocessordeclaration>
  / <declaration>
  / <instancemethoddefinition>

 typespecifier <- 
  ('void' / 'char' / 'short' / 'int' / 'long' / 'float' / 'double' / 'signed' / 'unsigned' 
  / <identifier>)

 declaration <- ( <declarationspecifiers> <NWS> <initdeclaratorlist>? <NWS> ';' <NWS> )
 declarationspecifiers <- <typespecifier>

 initdeclaratorlist <- <declarator>

 declarator <- <directdeclarator>

 directdeclarator <- {<identifier> <NWS> ( '=' <NWS> <primaryexpression> )? <NWS> } -> "local %1;"

 expression <- (<assignmentexpression> <NWS> (',' <NWS> <assignmentexpression> <NWS> )* )

 assignmentexpression <- <conditionalexpression> ( <NWS> <assignmentoperator> <NWS>  <assignmentexpression>)?

 assignmentoperator <- ('=' / '*=' / '/=' / '%=' / '+=' / '-=' / '<<=' / '>>=' / '&=' / '^=' / '|=') <NWS>

 conditionalexpression <- <logicalorexpression> <NWS> ('?' <NWS> <logicalorexpression> <NWS> ':' <NWS> <logicalorexpression> <NWS>)?

 constantexpression <- <conditionalexpression>

 logicalorexpression <- <logicalandexpression> <NWS> 
   ('||' <NWS> <logicalandexpression> <NWS>)*

 logicalandexpression <- <inclusiveorexpression> <NWS> 
   ('&&' <NWS>  <inclusiveorexpression> <NWS>)*

 inclusiveorexpression <- <exclusiveorexpression> <NWS> 
   ('|' <NWS> <exclusiveorexpression> <NWS>)*

 exclusiveorexpression <- <andexpression> <NWS>  ('^' <NWS>  <andexpression> <NWS>)*

 andexpression <- <equalityexpression> <NWS> ('&' <NWS> <equalityexpression> <NWS>)*

 equalityexpression <- <relationalexpression> <NWS>
   (('!=' / '==') <NWS> <relationalexpression> <NWS>)*

 relationalexpression <- <shiftexpression> <NWS>
  (('<' / '>' / '<=' / '>=') <NWS> <shiftexpression> <NWS>)*

 shiftexpression <- <additiveexpression> <NWS> (('<<' / '>>') <NWS> <additiveexpression> <NWS>)*

 additiveexpression <- <multiplicativeexpression> <NWS> 
   (('+' / '-') <NWS> <multiplicativeexpression> <NWS>)*

 multiplicativeexpression <- <castexpression> <NWS> 
   (('*' / '/' / '%') <NWS> <castexpression> <NWS>)*

 castexpression <- ('(' <NWS> <typename> <NWS> ')' <NWS> <castexpression>) / (<unaryexpression> <NWS>)

 unaryexpression <- <postfixexpression>
   / ('++' <NWS> <unaryexpression> <NWS> )
   / ('--' <NWS> <unaryexpression> <NWS> )
   / (<unaryoperator> <NWS> <castexpression> <NWS> )
   / ('sizeof' <NWS> ( ('(' <NWS> <typename> <NWS> ')') / (<unaryexpression> <NWS>) ) )

 unaryoperator <- ( ( '&' / '*' / '-' / '~' / '!' ) <NWS>)

 postfixexpression <- <primaryexpression>
   ( ('[' <NWS> <expression> <NWS> ']' <NWS>)
   / ('.' <NWS> <identifier> <NWS>)
   / ('->' <NWS> <identifier> <NWS>)
   / ('++' <NWS>)
   / ('--' <NWS>)
   )*

 primaryexpression <-
  ( <IDENTIFIER> <NWS> )
  / ( <constant> <NWS> )
  / ( <STRINGLITERAL> <NWS> )

 instancemethoddefinition <- ('-' <NWS> <methoddefinition> <NWS>)
   
 methoddefinition <- (<methodtype>)? <methodselector> <compoundstatement>
 
 methodselector <- (<keyworddeclarator>+ / <plainselector>)
 plainselector <- {<selector>} <NWS> -> 'function %1()'

 selector <- <IDENTIFIER>

 methodtype <- '(' <NWS> <typename> <NWS> ')' <NWS>

 typename <- (<typespecifier>)
 keyworddeclarator <- ( { <selector> } <NWS> ':' <NWS> <parameter> <NWS> ) -> 'function %1(%2)'

 parameter <- <methodtype> {<IDENTIFIER>}
 
 compoundstatement <- '{' <NWS> (<declaration>)* <NWS> <statementlist>? <NWS> '}' <NWS> -> 'end'

 statementlist <- (<statement>)+ 

 statement <- <WS>
  / ';'
  / (<expression> <NWS> ';')
  / <compoundstatement>
  / <selectionstatement>

 selectionstatement
  <- ('if' <NWS> '(' <NWS> <expression> <NWS> ')' <statement> <NWS> ('else' <NWS> <statement>)? <NWS> )
]]

print(parser:match[[
// This is a comment
#import "foobar"

int i = 1;

-(void)mySelector:(int)count
{
    int foo = 3;
    int bar;
}
]]
)



Saturday, April 10, 2010

The quiet in the middle of a raging category 5 hurricane

It's been a couple of days since the Apple dropped a nuclear bomb into the iPhone developer community . The initial shock has faded, but many questions remain. What will Apple actually do? Will they actively enforce their new restrictions? Will they respond to the serious concerns of the broad development community and modify the language? Or will they simply leave it as a strong No Trespassing warning, with a loaded shotgun on the porch ready to use whenever they wake up from their nap?

Meanwhile, various 3rd party developers critique the policy.

Adobe CTO Kevin Lynch concentrates attention on the CS5 launch, downplays the importance of the Flash packager for iPhone, and looks beyond. Is that capitulation, or merely putting all of the fuss into (much needed) perspective?

Behind the scenes at Adobe, a personal blog by Lee Brimelow underscores the emotional impact of the issue.

3rd party developer Appcelerator's CEO Jeff Haynie waits anxiously for Apple to clarify its position. I don't anticipate Apple doing any such thing anytime soon. They have all the cards, and they've never been one to worry too much about pissing off developers -- remember Hypercard? Cyberdog? Metrowerks? The list goes on and on.

Ansca CTO Walter Luh confidently discusses their position.

CEO Robert Virkus of Enough Software blogs about the clause, arguing that developers should band together to discuss their options, including legal ones if necessary. They don't use the word monopoly, but this is clearly implied: "this lock in effect of clause 3.3.1 is not fair because Apple uses its dominant position in the mobile application space to force developers to develop directly for its platform."

MonoTouch's official statement is here and affirms support for Apple's SDK 4.0, stating "If Apple's motives are technical, or are intended to ensure the use of the Apple toolchain, MonoTouch should have little difficulty staying compliant with the terms of the SDK."

Unity CEO David Helgason weighs in with their position here, noting "the new ToS are difficult to parse with certainty and open to broad interpretation"

Luckily we now have some humorous takes on the situation... Music may now only be produced with GarageBand, and Apple's developer license prohibits apps written by the left hand.

Meanwhile, a few iPhone developers are hanging up their hats. Dan Grigsby at Mobile Orchard is stopping publication and abandoning iPhone development. This is an admirable and principled stance, although I wouldn't expect many iPhone developers to follow suit.

On the iTunes store, Muchosmedia's application Just Letters says "it is probably that [the Just Letters app] will soon be banished from the walled garden of Eden. How tragic." Humorously the app price has now been raised to $199.99. Good luck with that.

The real winner in all of this has to be Android, and by extension, Google. As the mobile OS popularity rivals and potentially exceeds that of the mighty iPhone, if 3rd party developers are locked (or frightened) out of the iPhone world, there is exactly one place they can go, and that is Android. All of that talent and innovation, all of the rapid development frameworks, and all of the non-Objective-C developers out there (and there are a LOT) will look to the increasingly attractive alternative. Any plans that were formerly iPhone-first, port-to-Android-etc-second, suddenly change to Android-ASAP (with a possibility of Palm, Blackberry, etc support later).

Update: Ars Technica weighs in with this review. In it, they state "this move hurts Android. In fact, I think the harm done to Android could end up being even more substantial than the harm to Adobe. Although I would say that the biggest virtues of these banned tools are faster, easier development, the fact is that they also often encourage cross-platform development". I took the opposite position. Yes, it's true that from the vantage point of an iPhone developer, if I have an Objective-C app, I will have a higher hill to climb for Android (than if I could use a porting tool). That is true today. But the 3rd party tools, driven to Android, will in fact make it easier to develop any app for Android. Worst case, you may have to rewrite from scratch for Android, but you won't have to pay nearly the same price as you did for Objective-C. And in fact, many prospective app developers who wouldn't have been able to use Objective-C in the first place, will have no place to go but Android.

Friday, April 9, 2010

Into the firestorm

Yesterday was the day that you didn't want to have anytime soon, if you were in the alternative iPhone app development world.

Apple announced some drastic changes to its SDK, quietly, by publishing a new license on the same day that iPhone OS 4.0 was announced. The twitterverse went bananas after Daring Fireball noticed the change in text.

There are subtle phrases in there that would require a team of lawyers to untangle. What do "originally written", "compile" and "link" mean?

Suppose I write a specification for an app that reads like this:
  • Display background image
  • Display score at bottom left of screen
  • Randomly place 10 bombs on screen
  • When user touches a bomb, remove it and increase score by 10
  • Set 30 second timer. When timer elapses, game is over
I just "wrote" an app in a language called "English". Am I therefore prohibited from making an iPhone version of the game?

What does "compile" mean? Ok, so directly using an interpreter is probably not ok. What if you use a compiler to an intermediate format? For example, let's say you compile C# to C (which then compiles in XCode to ARM). Is that ok because it doesn't directly "compile" against the APIs?

What if the app is written in Objective-C, which is then translated to C#, compiles to Perl, which then is compiled into Lua, which then is cross-compiled into Pascal, which then is compiled to Java bytecode, which is then compiled into C?

How about "link"? Does that mean any language "instruction" that invokes an iPhone API "links" to it? Take the following pseudo-XML:

<circle r=25 x=100 y=50/>

This XML simply tells another piece of code to use native APIs to draw a circle. Does it "link" against the native API? If so, any app that loads XML data could be considered in violation. XML is a "language", and it's not C, Objective-C, or C++. And an XML parser sure looks like an intermediary compatibility layer.

To reiterate, what if I compile most of the app in C first, and the app internally runs a state machine that can do different things based on input? For example, touching the screen paints a circle. Ok, now let's supposed the input isn't from my finger, but is from an XML file that originally was generated by a PHP script on a server?

(Yeah, I know that many XML apps should really be web apps, in general, but XML is commonly used as a format for data exchange on the net, such as retrieving a list of customers from a remote database.)

At what point does a language of any kind become the Application? Is it a 50% binary size kind of thing? What if I have a small piece of code that mostly loads very large images?

What about applications that use SQL? It is a language. Strangely enough, Apple ships sqllite in the iPhone SDK. Does that mean we can't use it?

This is pretty ridiculous. Standard Computer Science says merely that CPUs execute instructions. Those instructions read and modify data. How the instructions are generated, and where the data comes from, are abstract concepts. Apple wants all of the instructions to stay in the Apple box, and they want the data to come from the Apple data pipe as well. That's not good for anyone but Apple.

Developers are like cats. Apple is trying to herd cats here, but has only succeeded in freaking them out.

Interestingly, Windows Phone 7 created the exact same kind of platform lock-in by neglecting to ship a native development kit. That means you can only create apps for that platform in Microsoft's tools. It's a similar situation because things you could do in WinMo 6.5 and before just can't be done in WinPho 7. Unfortunately for MS, they are the also-ran in the smartphone space at this point, so fewer people care. Nonetheless, they managed to royally piss off a lot of developers who have made a large investment in native code on their platforms. Apple's doing the same thing, but in a slightly different direction. MS is saying you can't port to their platform. Apple is saying you can't port away from their platform (at least, not the Objective-C part).

Similarly, Palm originally didn't allow native applications, but more recently shipped a native development kit (which they call a PDK). Maybe Microsoft will relent at some point. They said at one point that they are working with Adobe to port Flash to their browser, so clearly under the hood there's an NDK, just not public yet. Maybe.

By the way, Daring Fireball follows up on the issue makes the strange assertion that "Cross-platform software toolkits have never — ever — produced top-notch native apps for Apple platforms". That is just flat out not true. First of all, most of the entire Adobe Creative Suite is built on cross platform toolkits. Ok, let's stretch reality and say that even though they are popular, they aren't top-notch. There is a laundry list of top iPhone and Mac apps and games that are built with cross-platform tools from Unity.

Saturday, February 13, 2010

How not to create a website

I'm doing research on parental controls filtering on routers. Ok, there's a blog on Yahoo that lists a few -- oops, it's woefully out of date, but it appears the major brands have some solution or other. The Netgear seems ok, I don't want the software solution, I don't like D-link. I have used LinkSys products in the past and they've been pretty good. So let's see if they have a reasonable solution for me. So I go to the LinkSys site (linksys is now owned by Cisco, ok) and type in "parental controls" into their "Help me find" box. The first three results are in spanish. Not helpful. Ok, the fourth is "Configuring Safe Web Surfing and Parental Controls through HND in Network Magic 5.5" which seems promising. This leads to a page that says "Safe Web Surfing is a services [sic] where allow customer to block dangerous and malicious websites (fraud, phishing scams, viruses) for all devices connected in your Network Magic." Oops on the spelling. What's a Network Magic? What's an HND? Let's find out a bit more. Oh, I guess HND is Home Network Defender. I also guess they like acronyms: "To access HND in NM, click here."

Ok, well what routers support these acronyms? I go back to the home page and search for "Network Magic". The first hit is "Cisco Network Magic Pro 5.5 - CNMPRO" which apparently is a product. Great. Click on that. The page says "Parental Monitoring gives parents the ability to monitor their kids' online activity providing peace of mind and a safer online experience. Restrict Internet access plus take remote desktop screenshots to see real-time what they are doing from your own computer." Great. I want to know more, like in detail what it does.

Not much on this page. On the right there's a More Information which downloads a PDF which is basically a glossy brochure with a few more details about what it can do. "Cisco Network Magic offers controls that allow you to manage when and where your networked computers access the Internet. You can restrict Internet access to certain times of the day, making sure your kids are doing their homework and not surfing the web or chatting with." But nothing like the level of detail I want. How do you configure it?

There's also a More button which... brings you to the updates and drivers page. Fail.

Oh, but there's still HND to look at. Ok, back to search for that. Snarkily, I type in HND and am rewarded with the cryptic "Linksys by Cisco - LELA 3.1 (HND) Support". More acronyms. And I don't want support. Then the next 3 hits are in italian! I love italian! Unfortunately I don't read it. The 11th hit is "Configuring Safe Web Surfing and Parental Controls through HND in Network Magic 5.5". That sounds good. Nope, I've already seen that page and it has very basic information.

Fine, I type in "Home network defender". The first hit is "Linksys by Cisco Network Defender". Awesome. Let's look at it. Gotta skip past the "what about the children?" videos. At the bottom there's a data sheet, great. Nope! It's a one page summary. Lame.

Let's try the FAQ. For the first time, there's a bit of pricing information -- but it's incomplete. At the bottom there's "For more information, visit the EasyLink Advisor FAQs". What's EasyLink Advisor? Oh, it's actually Linksys EasyLink Advisor -- LELA! Then there's lots of Q&A which still doesn't tell me what the product does.

This is marketing gone terribly, terribly wrong, and website execution total fail. After about ten searches and lots of link clicks, I still don't have my questions answered about whether their products have the features I want.