Monday 31 August 2009

Reviewing Videos on Apple TV with Automator

The new Services support in Snow Leopard has got me interested in "really smoothing my Mac workflows", a term used by the demonstrator with the crazy hair at the last Apple keynote.

I take a lot of home movies with a Kodak Zi6; it's a cheap, but cheerful, HD handheld video camera that produces great looking images with not so hot audio.  I want to use my Apple TV to quickly review the home movies I produce on the camera - but that can be awkward.  The Quicktime wrapped files produced aren't quite compatible with Apple TV directly and so I've had to use a manual workflow of opening the files in iMovie, exporting to Apple TV, importing to iTunes and then syncing to finally get them onto the Apple TV.

With Quicktime 10, and the new Services support in Snow Leopard it is now possible to build a simple Automator workflow that allows me to -

  1. Select any number of Zi6 movies in the Finder.

  2. Right click, and select the "Review on Apple TV" service that i've built using Automator and some Applescript.

  3. The service will pick up all the selected files and send them to Quicktime for output in "Apple TV" format.

  4. It then uses some Applescript to import the converted files into iTunes, ready for syncing with my Apple TV.

The workflow is attached to the article for download.  Unzip the file and place it in your ~/Library/Services folder and then you can immediately right click any movie file and select the option to "Review on Apple TV".  It can also be opened in Automator and freely modified.

I still haven't perfected the workflow.  I want to add some metadata (specifically genre = "For Review") to the converted files so that I can quickly find them on the Apple TV.  I also want to trigger a sync on the Apple TV automatically but I can't see how that is possible in Applescript.  For now though, it works pretty well as a simple first start.

Download the Service here

Thursday 27 August 2009

Keynote Remote with Macbook Pro Ad-hoc Network

I'm giving a presentation in about a month and I'm planning to use Keynote on my Macbook Pro.  I was hoping to use the iPhone Keynote Remote app, to act as a very modern version of a slide changer (if that's what you call it?).  Keynote Remote expects both the host computer and the iPhone to be on the same network; but there are numerous reports of connection problems between both, not to mention the fact that you don't always have a Wifi network available at presentation venues.

Then, I had the bright idea of using the ability of Mac OS X to create an ad-hoc wireless network by clicking the Airport icon in the menu bar and clicking "Create Network...".  When I tried to connect the iPhone to the new network (Settings/Wifi) it appeared to connect - but the menubar network icon still showed a worse than Edge connection (I get terrible reception here).  Keynote Remote would work for a few slides, but then the connection would drop out - making it useless.

After the usual Googling, I stumbled across this Apple thread which suggested turning Airplane mode on in Settings, and THEN connecting to the ad-hoc network.  For some reason the iPhone now shows a Wifi connection and Keynote Remote seems to be working reliably.  Excellent tip!

Saturday 23 May 2009

Eclipse Working Sets

Eclipse is a fantastic IDE, especially for developing Java code. However, recently I've been getting a little irritated by its speed. This is probably exacerbated by the fact that the code I'm working on has about 20 Eclipse projects in it's source tree and thousands of source files. Eclipse gives the developer plenty of help - it does code completion, resolves dependencies, performs automatic imports and refactors across projects - all of which come at a cost. I'm not sure how much time i've spend waiting for my workspace to build, but it can be 10% of the day at worst! Even navigation through that many files becomes a productivity issue.

Recently i've found what is probably a fairly obvious feature of Eclipse but if you haven’t found yet it the concept of “Working Sets” should be useful.

Working sets are a way of choosing only those projects and files that are relevant for the task in hand. It's an alternative, more focussed way to view source files and resources that the Project Explorer - that can really get out of hand if you are working with more than, say, 10 projects. At the simplest level, working sets allow you to configure multiple profiles of visible projects that you can select from depending on the task you are performing. For example, if you are only working on the Eclipse projects that deal with order management in your system, you can select the “Order Management” working set and it will show only those Eclipse projects in the Project Explorer.

You can also bring working sets much further - you can select individual packages and files to form part of the working set (you can even create a working set of breakpoints), so you can be very specific about what you want to split out and see in context. All-in-all it is a useful way to make your Eclipse environment significantly easier to navigate.

To manage working sets use the dropdown arrow on the Project Explorer.

Click New... to create a new working set and select the type of set you want. The default Java type is usually fine for Java programming.

Select the various resources that should be part of the set, and give it a name. The resources can be anything - files, packages or projects.

Finally, use the dropdown menu on the Project Explorer to change active sets.

See the video tutorials here for a walkthrough

Friday 8 May 2009

New iPhone Apps to be tested on iPhone OS 3 Beta 5

Any new iPhone apps submitted to the App Store for evaluation will from now be tested on iPhone OS 3, beta 5.  Developers need to make sure their apps are well tested on the new beta before submission, otherwise they could fail the process.

Beta 5 of both the iPhone OS and the SDK are available on ADC if you're a registered iPhone developer.


Tuesday 5 May 2009

Squarespace to do iPhone App

I've been looking around on the iTunes Store for an app that does some basics for Squarespace - blog posts, basic comment management, viewing of stats etc. It appears there is an official one on the way. I know that Ego is an excellent app for browsing various site stat services - Feedburner, Google Analytics, Mint, Squarespace and Twitter are supported, but it doesn't do most of the extras a Squarespace specific app will do.

Monday 20 April 2009

iPhone Tweetie Style Navigation Framework

I love the iPhone Twitter client Tweetie - it has a really excellent navigation framework that makes it fast to navigate between multiple Twitter accounts.

I'm developing an iPhone app that logs actions against one or more persons and thought that Tweetie's navigation style would suit. Tweetie uses a navigation controller to handle the hierarchical nature of browsing account/tweets/users but also uses a tab bar to navigate between various views - a user's tweets, their mentions, DMs etc.  Investigating the Apple documentation, having a tab bar controller within a navigation controller is not a supported Apple user interface approach - the iPhone SDK doesn’t support it and trying results in a blank tab bar when you navigate to the view hosting it. I then found this post, with a comment from Tweetie developer himself, @atebits, alluding to the fact that a custom tab view controller solution is required.

The general steps are outlined below and full source code that can be used as a template for your own projects is posted at GitHub. I recommend you download this now for reference while working through this article.

The App Delegate

The App Delegate holds the navigation controller - this controller is at the root of the view tree and contains any other view controller that is pushed onto it. The navigation bar at the top of the screen that handles the navigation back and forth between views is to a large extent, managed automatically by the navigation controller.

As discussed previously, the issue with current versions of the SDK is that a tab bar controller cannot be pushed onto a navigation controller.

Now, have a look at MainWindow.xib in Interface Builder.

Note that the navigation controller has a “root view controller”. This is the controller that handles the first view that is pushed onto the navigation controller. Opening RootViewController.h reveals that the controller is inherited from UITableViewController. It is fairly typical that the navigation controller oversees multiple levels of table views.
@implementation BabyBookAppDelegate
@synthesize window;
@synthesize navigationController;

The Root View Controller

In Tweetie, the root view controller is the list of Twitter accounts. In my sample code, each table cell is driven from a simple array of strings (people’s names) for demonstration purposes.
self.title = @"Accounts";
NSArray *array = [[NSArray alloc] initWithObjects:@"Jack", @"Jill", @"John", nil];
self.accounts = array;
[array release];
When a cell is clicked, the delegate method didSelectRowAtIndexPath is executed. This pushes the custom tab view controller onto the navigation controllers stack. Note, that this is a custom tab view controller, and does not inherit from the typical SDK class UITabViewController. This means that there is some extra work to manually build this view controller, and also the view it owns.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[self.tabViewController setTitle:[accounts objectAtIndex:indexPath.row]];
[self.navigationController pushViewController:self.tabViewController animated:YES];

The UICustomTabViewController

Open TabViewController.xib. Have a look at the structure of the interface. I've manually created a Tab Bar, which in this case contains the two default tab bar items - Favourites and More. These two buttons have associated view controllers that own the view that appears when a button is clicked. The UICustomTabViewController class manages the switching of the views by maintaining (a) an array of the view controllers and (b) a reference to the selected view controller.

The controller also acts as a delegate for the tab bar, so can respond to taps on the tab bar items through the didSelectItem delegate method. Based on the item tapped, a reference to the appropriate view controller (Favourites or More) is pulled from the array of view controllers. The current view is removed from the superview and the view of the selected view controller is then added to the UICustomTabViewController’s view. Really, the view above the tab bar is getting swapped out for a new view, depending on which tab bar item is tapped.
- (void)tabBar:(UITabBar *)tabBar didSelectItem:(UITabBarItem *)item
   if (item == favouritesTabBarItem) {
     UIViewController *fabViewController = [viewControllers objectAtIndex:0];
     [self.selectedViewController.view removeFromSuperview];
     [self.view addSubview:fabViewController.view];
     self.selectedViewController = fabViewController;
   } else if (item == moreTabBarItem) {
     UIViewController *moreViewController = [viewControllers objectAtIndex:1];
     [self.selectedViewController.view removeFromSuperview];
     [self.view addSubview:moreViewController.view];
     self.selectedViewController = moreViewController;

The More Tab

The MoreTabViewController.m class controls another table view and demonstrates that the navigation controller can be used to manage further views in a hierarchy. The delegate method didSelectRowAtIndexPath will retrieve the navigation controller from the application delegate and push the view controller that handles the next view in the navigation hierarchy - MoreOptionViewController.
NavTabAppDelegate *delegate = [[UIApplication sharedApplication] delegate];
[delegate.navigationController pushViewController:moreOptionViewController animated:YES];
[moreOptionViewController.label setText:msg];
Again, the full source for the NavTab project is on GitHub.

Further recommended reading -

Apple View Controller Programming Guide

Thursday 16 April 2009

Wil Shipley's App Hype

I came across this video from the C4 conference of the famous Mac programmer Wil Shipley talking about how to generate hype and buzz for your applications.  He talks alot of sense - in fact most of it seems like common sense - but there are alot of things that most of us probably won't pick up straight off.  If you're a Mac/iPhone programmer you'd do well to take some of this onboard.

I found out about Wil after downloading Delicious Library 2 as part of the Macheist bundle, and then realised he was one of the founders of The Omni Group - check out OmniGraffle if you want to draw fantastic looking diagrams!  Great examples of simple, cool apps.  He is also worth following @wilshipley.


Sunday 12 April 2009

How to rename an Xcode project

I've recently been working on a iPhone framework which performs Tweetie style navigation - basically supporting a tab bar controller within a navigation controller, as this isn't supported natively by the iPhone SDK. I developed the framework in a seperate project and wanted to use this as a base for a new project I've just started working on. It's fairly simple to take a copy of an existing iPhone Xcode project and rename it for a new project - here are the steps I followed -

  1. In Finder, copy the old project directory to a new location and rename the folder to reflect the new project name.

  2. Move the <oldproj>.xcodeproj file in the project directory to <newproj>.xcodeproj.

  3. Open the new xcodeproj file/project in Xcode.

  4. If using version control on the provious project, turn that off - right click the project, Get Info and set the version control drop down value to "None".

  5. Refactor those classes that carry the <oldproj> name e.g. open the application delegate header file <oldproj>AppDelegate.h, right click the class name <oldproj>AppDelegate and then select refactor. Rename to <newprog>AppDelegate, Preview then Apply. Repeat this for any classes that hold the old name.

  6. In Other Sources, pick the <oldproj>_Prefix.pch file and refactor - rename to <newproj>_Prefix.pch.

  7. Select the <oldproj> build target and rename to <newproj>.

  8. Bring up info for the <newproj> target - Select “All Configurations”, “All Settings” and navigate through the build configuration settings changing these references of <oldproj> to <newproj>
    Product Name
    Build and test