SproutCore and Cappucino on Windows

January 28th, 2011

I’ve been wanting to play with a web framework for building a desktop application. Heard good things about SproutCore so I set out to install it, but ran into a number of roadblocks that made it difficult to do on Windows. 

The one that made me give up was trying to install the Ruby sproutcore gem.  Installing this requires eventmachine, which includes native code.  I installed the Ruby DevKit which includes GCC for building the native code, but it produces an error compiling parts of eventmachine. 

Most of the cool new web development these days is done on the Mac.  With good reason, of course, but I happen to be sitting in front of the computer I use for gaming.  It has a nice monitor (whereas my laptop has the laptop monitor), but it runs Windows.  This stuff is theoretically all portable so getting it to work should be possible, but I guess that so few people do it that the installers and documentation tend to lapse.

So on to Cappucino

SproutCore has a build step which requires Ruby, but Cappucino claims that you can just unzip it and invoke index.html and you’re good.  But Chrome won’t have that; it doesn’t allow requests to other domains from pages loaded from file:// URLs.

To fix this, you’ll need to serve the files through a web server, like IIS.  To install IIS on Windows 7:

  1. Open the Control Panel
  2. Select Programs
  3. Select Turn Windows Features On and Off
  4. Select Internet Information Services, hit OK

This will install a basic IIS.  The default website is in c:\inetpub\wwwroot so grab the Cappucino Starter application and drop it in that folder.  (You’ll probably need to enter some administrator credentials along the way).

So now your Cappucino site is accessible at http://localhost/Starter/index.html but it still won’t work, because IIS won’t serve files whose MIME type it doesn’t recognize.  So head for the IIS control panel:

  1. Open the Control Panel
  2. Select System and Security
  3. Select Administrative Tools
  4. Select Internet Information Services (IIS) Manager.
  5. Select MIME Types.

To add a new MIME type, click the “Add” link at the right.  Add 3 new MIME types:  .j, .sj, and .plist.

Now you should be able to load your Cappucino app!

TV Research

January 24th, 2011

I’ve been shopping for a TV.  If you’re not shopping for a TV, you may want to skip this post.

For a lot of people this means walking into a store, looking at a few TV’s, picking one, and being done with it.  But not me. 

I enjoy digging into the technology behind the sets, analyzing the different feature sets and trying to figure out which one I think I’d like the most.  It’d an odd process, because here’s how it usually goes:

I spend hours online comparing options and picking something that looks good.  I find a store in the area that has one in stock (thanks to Future Shop and Best Buy having their inventory available online, mostly). I drive over and have a look.  I find something about the set that I don’t like, feed that back into the process and iterate.

I’m about 4 iterations in so far.

I figured I’d share what I’m learning here so I can perhaps help anyone else who’s looking for the same sort of thing I am.

What am I Looking For?

In a nutshell, a great looking TV that’s sharper and bigger than the one I have.  That shouldn’t be hard – right now I’m using an rear-projection Toshiba 57HX84.  There’s some argument to be made for the purity of a CRT set – no LCD screendoor effect, much less messing with the picture done by various processing engines – but it’s just not that sharp.  And the black levels suck.

It seems like there are a lot of options when you’re buying TVs but some of that is artificial.  For one thing, there are a small number of companies that make LCD panels, and even those fancy new “LED TVs” are just LCD TVs with a different kind of light.

My current TV is 57” and I’m looking for something bigger.  Unfortunately, 55” is really the sweet spot right now in terms of price.  There’s a significant price premium for those extra 5 inches.

And at 55” there are simply way more options.

I’m going to talk mostly about options at Best Buy in Canada, because they have the best selection of the online retailers I’ve been looking at.  Go to http://www.bestbuy.ca, click on Televisions in the menu.  The sidebar shows 31 TVs in the 50 to 59 inch range, and 9 in the 60+ range.

Let’s look at those 60+ sets.  They currently range for $1499 to $2799.  Let’s look at the $1499 sets and start ruling them out.

One of my criteria is that I want an LED set.  Why LED?  They’re low power, they don’t dim over time, and some sets will dim them when the overall picture quality darkens, to enable more detail in scenes with low light.  LED sets also tend to be thinner, especially edge-lit sets where the lights are around the outside of the frame instead of behind the picture.

Higher end TVs divide the screen into zones, and can dim just some of the LEDs, although to me this seems like a bit of a gimmick.  I want the set to be able to have white pixels next to black pixels anywhere, not just when the white and black are in different zones.

The Sharp $1499 TV thus loses out on a few counts:  It’s thick (12.7cm), power hungry (390 watts), and CCFL backlit.  It loses out on the panel as well, but I’ll get to that.

There’s an LG Plasma on sale for $1499.  What about that?

Plasmas are a whole different beast than LED TVs.  Used to be, plasma had some serious drawbacks.  Much higher power consumption, heat generation, picture burn-in.  They also tend to buzz a little.  I had pretty much written off plasma, until I went in to a local store that had a great display of Panasonic plasma sets. 

The high-end Panasonic Viera sets are jaw-dropping. 

The store (FM Audio Video in Brantford) has a wall of TVs all hooked up to the same HDMI source, and can run various tests through them.  They can also dim the lights on the whole wall so you can compare the sets in reasonable room lighting, not just store lighting.  One of the test is basically just some light objects moving around on a dark background.  And for this test, the Panasonic plasma was hands down the best set – it was obvious.

The salesperson ran down the list of plasma advantages – faster refresh rate, deeper colours, deeper blacks, they draw less power than they used to (and it’s true – one I looked at was 250 watts), they don’t burn in permanently (although temporary burn-in still happens).  But this comes at a price – around $3400 for a 58” (which doesn’t really qualify as bigger than my existing set) and $4400 for a 65”.  That’s way more than I want to spend.  And you need to buy top of the line plasma to get the picture quality advantages that the Panasonic Viera sets show.  Also, I just have more faith in the long term survivability of an LED-backlit set than a plasma set.

Back to the TVs at Best Buy.  There’s a Samsung LN60C630 for $1999, but it’s CCFL backlit, 10.9cm thick, and not getting great ratings.

Next up is the Sony KDL-60EX700.  On paper this set looks perfect.  It’s $1999, 60 inches, edge-lit LED, draws 117 watts of power and 6.6cm thick.

But when I saw this on the floor at Future Shop, there was something a bit surprising in the display.  Text in the menus had this odd sawtooth quality on the edges, and it didn’t quite look as “sharp” as some of the other sets I’d looked at.  I dug into this a bit and discovered the LCD panel in the 60” Sony sets in 2010 is manufactured by Sharp, and is a UV2A panel.  Sharp’s UV2A technology has gotten a lot of accolades for delivering high quality fast motion and good black levels, but part of the way this panel works is that if you have a scene that’s 50% bright, rather than dimming all the pixels evenly, it will basically dim half of them.  I started a thread on this at AVSForum and some other folks came up with pictures of what this means for the quality of a PC image displayed on this TV.  From 10’ away you might not be able to see the dithering in the grey menu image, but it still bugs me.  I want a panel that’s going to display the image it’s sent, pixel for pixel. 

So that ruled out this set, but it also ruled out all the other Sony 60” sets for 2010, since they all use the same panel.

At this point I’m starting to consider 55”.  I was at a Best Buy yesterday and saw the Sony 55NX810.  I gotta say, the monolithic design and glass panel really does give it some awesome contrast, and the high-def sports they had playing on it looked very good.

It’s possible that 60” is the point where high def stops looking razor sharp (from close up) because the pixels just get too big – like how a 24” PC monitor at 1920x1080 doesn’t look as sharp as a 20” at the same resolution.

There is a 60” version of the NX810 but it uses the Sharp panel I don’t like.  Sony has announced their 2011 models, which include a 60NX820, but they’ve also added the glass panel (now using the same Gorilla Glass that the iPhone uses) to the 60EX720.  But that won’t be available until April.

So I’m weighing my options:  Go with the 55NX810 which I know looked great, or wait for the 2011 models and see if they’ve switched panels and if they have a 60 inch screen in my budget.  Hmm.

Here’s a rundown of my considerations:

Edge Lit LED – Fine with me.  Cheap sets have clouding or flashlighting effects where you can see where the light is being shone during dark scenes; better sets don’t.

3D – Not really interested.  But as it turns out, it’s hard to buy a high-end set that doesn’t have it.

Apps – Like 3D, it’s hard to find a high-end set that doesn’t have network connectivity and apps, like it or not. 

Thin – Where I plan to put it, you’ll see the wall it’s on from the side.  I would prefer one of the newer razor thin designs (although 3cm is a heck of a razor).

Power Consumption – I realize that the actual cost of running the TV isn’t that high, but it’s still important to me that the set is power efficient.  And less power consumption means less heat generated which probably increases the life of the set.

Sharp – I’ll be reading text on the screen fairly often.  Browsing the Apple TV, menus, searching for movies, that sort of thing.  I want text to be crisp.

Oh yeah, and it’d be nice if it had a good picture, too.  Smile

Disclaimer:  This is all just my thoughts .. people with different priorities would reach different conclusions.

How to Split Scanned Photos in iPhoto

December 18th, 2010

I have a number of photos in my iPhoto library that came from a scanner, and when I scanned them, I had multiple photos on the flatbed. So I had a photo like this in my photo library:

201012180808

While there are tools that will automatically find the embedded photos and separate them, there's an easy way to do this right in iPhoto.

Here's how:

  • Duplicate the image, once per embedded photo. This will create a number of virtual copies of the image. Press Cmd-D to generate a duplicate, as many times as you need.
  • For each duplicate, crop one of the original images using the Crop tool.

That's it. Seems simple enough, but it's not an obvious way to do it.

Note that when you duplicate, iPhoto doesn't actually generate a new copy of the original image, so you're not wasting space for all the duplicates. It will generate a new modified JPG for each of the cropped images, and that's what you'd expect, but they're still linked back to the original so if you want to go and re-crop them later, you can still do it.

Hybrid Native/Browser-Based Windows Mobile App

November 12th, 2010

So you're a Windows Mobile 6 developer working on a C++ application, and you're using the WebBrowser control (which, I guess, is an instance of Pocket IE, the mobile version of Internet Explorer circa IE 6). Your application is hosting a web page, and on that page you want to have a button, and when that button is clicked, you want to run some native code, and then give the result back to the page so that JavaScript can act on it.

Okay, so I'm not sure that this particular "you" exists.  But that was me, recently, and I spent a lot of time researching how to do this.  The answer isn't straightforward because Pocket IE isn't the same as Desktop IE and the documentation is hard to find.

On the desktop the answer is fairly straightforward:  You can use IHTMLDocumentEvents to add an onclick handler and after processing the click, use IHTMLDocument::Script to get the script engine and ask it to run a JavaScript function.

But in Pocket IE, there is no IHTMLDocumentEvents, and no access to the script engine (at least, not that I've found).  In fact, the whole process is different.  Hence this page.

The general strategy I used is:

  • In the HTML, add a button that the user is going to click to call your native function and an input field to receive the result.  (The input field can be invisible).
  • In the dialog’s DocumentComplete (your notification from the browser control that it’s done loading the document):
    • Find buttons on the page (by looking for PIEHTMLInputButtonElement objects) and add click listeners.
    • Also find the input field that will be receiving the result.
  • Pass the result back to the JavaScript by calling put_value on the result field.

I'm going to assume you've already got a dialog that's hosting the browser control and you have an IPIEHTMLDocument2.  If not, you need to get it from the DocumentComplete event.

The includes for the symbols you'll need are:

[cc lang="C++"]
#include
#include
[/cc]

Here's the class I'm using as the listener.  This class implements, through IDispEventSimpleImpl, the dispatch map for the IPIEHTMLInputButtonElementEvents interface.

[cc lang="c++"]
class ButtonEventListener :
      public CObject,
      public IDispEventSimpleImpl
{
      DECLARE_DYNAMIC(ButtonEventListener)
 
      BEGIN_SINK_MAP(ButtonEventListener)
            SINK_ENTRY_EX(ID_BUTTON,
                                DIID_PIEHTMLInputButtonElementEvents,
                                DISPID_HTMLINPUTELEMENTEVENTS_ONCLICK,
                                &ButtonEventListener::OnInputButtonClick)
      END_SINK_MAP()
 
protected:
      HRESULT GetFuncInfoFromId(const IID& iid, DISPID dispidMember,
            LCID lcid, _ATL_FUNC_INFO& info);
 
      CMyBrowserDlg *m_pOwner;
 
      CComPtr m_spButton;
 
public:
      ButtonEventListener(CLCBrowserDlg *pOwner);
      virtual ~ButtonEventListener() {};
 
      void ListenTo(IPIEHTMLInputButtonElement *pButton);
       void __stdcall OnInputButtonClick(IDispatch *pDisp, VARIANT_BOOL *Cancel);
};
[/cc]

A few comments on this class:

  • GetFuncInfoFromId is called because we’re using IDispEventSimpleImpl which doesn’t require a type library.  GetFuncInfoFromId eturns the information that would normally come from the type library.
  • You can embed this class in your dialog class (for example), and pass its constructor the dialog.  This is how I pass the click message from the event sink class back to the dialog.  There are lots of ways to do this; pick one you like.
  • ID_BUTTON is just an arbitrary number (I used ‘1’).

The implementation:

[cc lang="c++]
IMPLEMENT_DYNAMIC(ButtonEventListener, CCmdTarget)

// Constructor: Just store the owner dialog so we can call it later
ButtonEventListener::ButtonEventListener(CMyBrowserDlg *pOwner)
      : m_pOwner(pOwner)
{
}

// Called by the dialog to start listening on a particular button
void ButtonEventListener::ListenTo(IPIEHTMLInputButtonElement *pButton)
{
      m_spButton.Attach(pButton);
      HRESULT hr = IDispEventSimpleImpl::DispEventAdvise(pButton, &DIID_PIEHTMLInputButtonElementEvents);
}

// Called by IE when the button is clicked.
void __stdcall ButtonEventListener::OnInputButtonClick(IDispatch *pDisp, VARIANT_BOOL *Cancel)
{
      m_pOwner->OnButtonClick(m_spButton);
      return;
}

// Required to tell the caller about the function's calling convention (__stdcall)
HRESULT ButtonEventListener::GetFuncInfoFromId(const IID& iid, DISPID dispidMember,
        LCID lcid, _ATL_FUNC_INFO& info)
{
      if (InlineIsEqualGUID(iid, DIID_PIEHTMLInputButtonElementEvents))
      {
            info.cc = CC_STDCALL;
            switch(dispidMember)
            {
                  case DISPID_HTMLINPUTELEMENTEVENTS_ONCLICK:
                        info.vtReturn = VT_I4;
                        info.nParams = 0;
                 return S_OK;
 
                  default:
                 return E_FAIL;
            }
      }

       return E_FAIL;
}
[/cc]

The next step is finding the buttons you want to handle and the control where you’re going to write the result.  What I did for this is I called a function in my DocumentComplete handler which walks the list of all the elements on the page looking for buttons to handle and the input field to use for the response text. 

[cc lang="c++"]
// Set up for native handling of button clicks.
void CLCBrowserDlg::RegisterButtonListener()
{
      // Find the IPIEHTMLDocument2
      CComPtr pDoc2;
      HRESULT hr = E_FAIL;
      CComPtr spDisp;
      if (FAILED(m_spIWebBrowser2->get_Document(&spDisp)))
            return;
 
      pDoc2 = spDisp;
 
      // Get all the elements on the page
      CComPtr spAllElements;
      if (SUCCEEDED(pDoc2->get_all(&spAllElements)))
      {
            LONG lLen = 0;
            if (SUCCEEDED(spAllElements->get_length(&lLen)))
            {
                  // For each item on the page..
                  for (LONG i = 0; i spDispItem;
                        _variant_t index = i;
                        if (SUCCEEDED(spAllElements->item(index, index, &spDispItem)))
                        {
                              // Is it a button?
                              CComPtr spButton;
                              if (SUCCEEDED(spDispItem->QueryInterface(IID_IPIEHTMLInputButtonElement, (void **)&spButton)))
                              {
                                    // Yes .. attach the listener
                                    m_ButtonListener.ListenTo(spButton);
                              }
 
                              // Is it a text field with the specific id we're looking for?
                              CComPtr spTextInput;
                              if (SUCCEEDED(spDispItem->QueryInterface(IID_IPIEHTMLInputTextElement, (void **)&spTextInput)))
                              {
                                    CComBSTR id;
                                    spTextInput->get_id(&id);
                                    if (CString(L"__ipc_result__").Compare(id) == 0)
                                    {
                                          // It is; save it for later
                                          m_spRPC = spTextInput;
                                    }
                              }
                        }
                  }
            }
      }
}
[/cc]

Call RegisterButtonListener from DocumentComplete and you should be getting clicks from the browser hitting breakpoints in your native code.  Getting a result back to the HTML is simple, assuming it's a string:

[cc lang="C++"]
void CMyBrowserDlg::OnButtonClick(IPIEHTMLInputButtonElement *pButton)
{
m_spRPC->put_value(L"Some Value from Native Code");
}
[/cc]

If you need to pass something complex there’s always XML. 

With this snippet of HTML:

[cc lang="html"]



[/cc]

Assuming you’ve got everything set up correctly, a click on the “Click Me” button will cause the alert to show up (‘yo yo’), followed by the native code running and the result field’s value changing to the value we wrote to it from the C++ code. 

It'd be nice if the onclick handler ran after the C++ code instead of before, but you could use this behaviour to set a timer to run after the click to read the result.

The code above has not been extensively tested.  It worked when I tried it, but it’s not perfect. Use at at your own risk.  One missing piece is unsubscribing from the events when you no longer need to listen for them.

But hopefully someone will find this useful.  Let me know if you do.

Twitter Weekly Updates for 2010-11-07

November 7th, 2010

Twitter Weekly Updates for 2010-10-24

October 24th, 2010
  • Best thing about the Mac app store is it gives a real financial incentive to make a Mac app that follows the rules. #
  • Jobs dissing 7" tablets doesn't make sense. He says 7" makes things too small to tap, but you can make UI elements any size you want. #
  • Windows already has an App Store. It's called Steam. #

Brantford Mayoral Election 2010

October 24th, 2010

While I tell everyone I live in Brantford, technically I don't. I live just outside the city, in Brant County, so I don't get to vote for a mayor in Brantford. But one comment by one particular candidate caught my attention recently.

It was Mark Littell, and the comment was this one:

Calling on city hall to be more "open and transparent," Friel suggested reinventing the economy of Brantford from its old failed platform as a "metal bashing town" into higher–tech industry. Specifically, he mentioned videogame design as a possibility.

Game design these days isn't a high tech profession so much as it is a creative one. Look at the credits for some big recent games and you'll see very few developers, but potentially hundreds of people working as artists and actors and in various creative roles.

Years ago Brantford was a real manufacturing center, but so much of that has closed down now that the younger generation just isn't going in that direction. And judging from Brantford's reputation as crime and teen pregnancy capitals, they aren't going anywhere good. Meanwhile, the game business is primarily staffed by younger folks. Mohawk College in Brantford has graphic design courses and I know a number of people with creative skills but nowhere to work. I think this could be a good fit for Brantford.

Now, game design isn't a glamorous industry, as ea_spouse made clear some years ago. But I think that's the exception and not the rule. And it's a better industry than no industry.

Looking at Littell's website, he's promoting bring GO Transit to Brantford which I think would be awesome (that's the rail transit system that connects cities from Hamilton to Toronto), and was a driving force behind the South Colborne plan (which involved taking down some buildings which, while historic, nobody wanted, and were just falling down.

So if I was in Brantford, that's who I'd vote for. Meanwhile in Brant County where I live, in my ward, there are 2 counsellors running for 2 seats, so not much choice there, and so far none of the mayoral candidates jumps out at me. Need to do some more reading there.

Twitter Weekly Updates for 2010-10-17

October 17th, 2010
  • Google still has the ability to surprise me even given my high expectations of them. http://techcrunch.com/2010/10/09/google-automated-cars/ #
  • Hot water heater died today. Called for service and it was fixed in 2 hours (on a holiday weekend). Good service, Reliance Home Comfort. #
  • I'm on a horse. Cow. http://www.youtube.com/watch?v=zkd5dJIVjgM #
  • When I get a new follower the instant I tweet, so far it's always been spam. #
  • RT @ID_AA_Carmack: It is not that uncommon for the cost of an abstraction to outweigh the benefit it delivers. Kill one today! #
  • Maybe it'll feel different on an actual device, but the videos and photos I've seen of the WP7 Metro UI look a bit ugly. #

Getters and Setters

October 8th, 2010

"Best practices" always tell us to use getters and setters instead of exposing properties directly on a class. This is true for just about every language where it makes sense, but I want to look at two particular cases, Java and ActionScript.

How often have you seen classes that do this?

[cc]
class Employee
{
private String firstName;
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getFirstName() {
return firstName;
}
}
[/cc]

Most of the time, this is unnecessary. It's 6 extra lines of code for every property cluttering up the source files for little benefit. The typical reasoning for why you need getters and setters is that it gives you the opportunity to go back later and add additional functionality, like say dispatching an event when a property is changed. In certain circumstances this makes sense.But most of the time, the cost, in terms of the loss of clarity and the additional lines of code to maintain, outweighs the benefit.

If you used a public member instead of accessors and later did want to change your mind, what's the impact? When you make the change, your compiler or IDE will tell you all the references that you need to fix. It might even offer to do it for you.

In ActionScript, there is even less need to write getters and setters for properties, because you can go back and change your mind later. In ActionScript, the Employee class might look like this:

[cc]
class Employee
{
private var _firstName:String;
public function get firstName():String
{
return _firstName;
}

public function set firstName(value:String):void
{
_firstName = value;
}
}
[/cc]

But if you used the simple version:

[cc]
class Employee
{
public var firstName:String;
}
[/cc]

And you later needed to override what happens when you set or get firstName, you can change the property to private and add getters and setters without having to update the clients.

Twitter Weekly Updates for 2010-10-03

October 3rd, 2010
  • Killer #adobemax session: accessing data services from HTML5 / JavaScript, native Android, iOS, Java and .NET http://tinyurl.com/36fbffx #
  • #netflixca might not have the movie you are looking for but they will have movies you want to watch. #
  • @travelmop I'm really liking my cloud-based battery charger. I don't have any batteries here, but wherever they are, they're at 100%. in reply to travelmop #
  • Blackberry's PlayBook looks great! http://press.rim.com/release.jsp?id=4577 #
  • It's so hard, when an installer tells you to close your browser, to remember to keep it closed for the duration of the install. #