Thursday, December 24, 2009

JAZZ.FM91 iPhone app now available

I'm very happy to announce the latest iPhone app from Stormy Productions has now been approved by Apple, just in time for the holidays.



It is an app for JAZZ.FM91, Canada's premier jazz station. You can download it on iTunes here:

http://itunes.apple.com/us/app/jazz-fm91/id347636689?mt=8

JAZZ.FM91 has been listed as "one of the best radio stations in the world" by BusinessWeek.com and it was my pleasure to be asked to create an iPhone app for their station.

This app supports listening to the live JAZZ.FM91 stream, as well as several "web radio" streams. It also supports listening to the JAZZ.FM91 podcasts within the app and has support for reading the JAZZ.FM91 music news RSS feed, the JAZZ.FM91 blog, and other sections of the JAZZ.FM91 web site.



And yes, this iPhone apps uses Stormy's RadioKit SDK to handle the radio station streaming.

Monday, December 14, 2009

Ten most useful third-party Mac apps (for me)

It seems to be the time of year people come out with top ten lists, so it got me thinking about what third party applications I find get the most use on my Mac. Here they are, in no particular order:

Things from Culture Code
http://culturedcode.com/things/

I had been searching for a decent todo list tracker for a while. I had been tempted by OmniFocus, but given the relatively high price, I was hesitant. Based on a recent positive review of Things in MacWorld combined with the fact that there is an iPhone companion app, I figured I'd give it a try. So far I'm happy with it.


AirFoil from Rogue Amoeba
http://www.rogueamoeba.com/airfoil/mac/

When I first got my Airport Express and used it for wirelessly piping iTunes music to my stereo, I thought to myself, "Wouldn't it be great if I could do this from other applications other than iTunes?" Well, little did I know there was an application that did exactly that! Combined with the free Airfoil Speakers program (which runs on both Mac and Windows machines), this application is well worth the $25. Now, using a couple spare laptops, I have music easily piped into whichever rooms in the house I want.

Billings 3 from Marketcircle
http://www.billingsapp.com/

This simple client project tracker / invoicing application has helped me run my software development business for the past year and a half. It easily tracks multiple projects and produces professional invoices. I'm occasionally tempted to get something a bit more advanced so I can also track business expenses for my tax records, but the simplicity of this application has kept me using it.

AppViz from Ideaswarm
http://www.ideaswarm.com/products/appviz/

This application is a must-have for any iPhone developer who has an iPhone app in the iTunes app store. It makes it very easy to track sales, upgrades, app rankings, and reviews in all the iTunes stores around the world. I use it every day.

Socialite from RealMac Software
http://www.realmacsoftware.com/socialite/

Previously called EventBox (before RealMac Software bought it), I have a love/hate relationship with this application. It's probably the most frequently used third-party application on my Mac. It's a social networking app that lets you track updates on Facebook, Twitter, Flickr, and a host of other sites. It's extremely handy, but the transition during RealMac Software's migration of the application from the previous incarnation as EventBox was not at all smooth. It was so bad I said I'd never by another RealMacSoftware product, and I currently own all the products they've published (LittleSnapper, RapidWeaver, and Socialite). I think it would be more fair to say I'll never buy another 1.0 release of a RealMac Software product.

Adobe Photoshop Elements from Adobe
http://www.adobe.com/products/photoshopelmac/

I could never justify the cost of the full-blown version of Photoshop, but I've been using Photoshop Elements for years and it does pretty much all I need at a fraction of the cost of the full program.

Adobe Lightroom from Adobe
http://www.adobe.com/products/photoshoplightroom/

I like to take photos. Lots of photos. I have over 13,000 of them. How to keep them all organized and do minor editing work with them while easily preserving the original image? I find Adobe Lightroom to be an ideal solution. It's not cheap ($299), but I don't regret buying it and have been using since it was first released a couple years ago. If you consider yourself an amateur or professional photographer, it's worth consideration.

Fetch from Fetch Softworks
http://fetchsoftworks.com/

There are plenty of FTP utilities, and I imagine there might be one better than Fetch, but I seem to use it for sentimental reasons. Many years ago, long before I used a Mac, I worked at a newspaper and was amused by the cute little FTP program that was used in the creative services department on all the Macs there. When you were sending a file, the cursor turned into a pixelated image of a dog running. So, when I eventually started using a Mac myself a few years ago and needed an FTP program, Fetch was the first one that came to mind.

TextMate from MacroMates
http://macromates.com/

If you want a text editor that recognizes just about every file format a programmer might use, and allows plugins to recognize even more, then this is the program for you. I barely use any of its features, but it's handy for the syntax coloring those times I need to do a quick edit of an XML/HTML/perl/php/... file.

ScreenFlow from Telestream
http://www.telestream.net/screen-flow/overview.htm

I don't use this program very often, but I include it in the list because it is extremely useful when I do need it. It is an application for doing video captures of anything running on the Mac desktop. I mainly use it for making demos of iPhone apps running in the simulator, but have used it on occasion for making tutorials on how to do different things in Xcode.

Stormy's RadioKit SDK documentation

I've put together a new PDF documenting all aspects of the RadioKit SDK. It can be found here:

http://stormyprods.com/products/RadioKitDoc.pdf

This document provides a description of all the class methods, properties, and protocols and gives a very basic example of how the class is used.

As mentioned previously, a complete XCode demo project is also available upon request if you'd like a free evaluation of the SDK.

Tuesday, November 24, 2009

Stormy's RadioKit SDK licensing

I am happy to announce there is now a fairly low-cost method available for other developers to license our iPhone radio steaming technology for their own apps. At just $100 per app project, you can include the same radio streaming technology that is powering the Radio Paradise and Tunemark Radio apps (as well as scores of other radio apps).

This RadioKit SDK includes full support for time-shifting a live stream, allowing pause, rewind, and fast forward back to the live stream. It also includes our robust dropped connection handling which can seamlessly restitch together the old buffer with the new stream, which often eliminates any interruption in listening even though the data connection had been completely dropped.

Aren't sure if the SDK is worth $100? You can test it in an XCode demo project with no financial obligations. When installed on a device (iPhone or iPod Touch), the audio streaming portion of the demo will only function for 10 minutes at a time, however you can test the SDK without any time limits using the simulator.

The SDK is licensed on a per-app project basis, meaning you must purchase a license key tied to each unique iPhone app bundle ID. Volume discounts for license keys are available for those who may be interested in using this SDK in a large number of projects.

You can read more about Stormy's RadioKit SDK at http://www.stormyprods.com/products/radiokit.php

Wednesday, November 18, 2009

Browsing photos and videos on your iPhone via your Mac

Since owning an iPhone 3GS, I've accumulated quite a few videos captured using the built-in camera feature. Oddly, Apple doesn't provide a method for viewing these items via iTunes. In order to access them, I'd launch iPhoto, copy out the movies in which I was interested and then drag the items out of iPhoto into my preferred movie management tool.

It was all a bit of a nuisance since I don't like to use iPhoto.

I figured there must be a simple way to get at these photos and videos without having to use iPhoto or some other bulky image management program. Well, it turns out there is. The iPhone follows the normal "Design rule for Camera File system" convention, so any tool that can browse photos or movies on a camera will be able to access these files. No big surprise there. That's what I expected.

But what did come as a surprise to me was with Mac OS 10.6 there is an ImageKit API which makes accessing this data via a custom program incredibly simple. How simple? How about not even having to write any code simple? Using XCode and Interface Builder, you can literally drag and drop an application which will provide a simple browser interface for any attached cameras on your Mac.

Apple details the simple 2 step procedure in their XCode documentation.

If you don't don't feel like building your own XCode project for this feature, the "Image Capture" program supplied with Snow Leopard provides this exact functionality.

Also, I should note, when I say this allows you to browse videos stored on your iPhone, I am referring to videos you have recorded using the built-in camera. It does not allow you to browse videos loaded via iTunes.

Monday, November 16, 2009

Increased caution regarding "undocumented" API calls

It has always been Apple's official policy that you shouldn't use private frameworks or undocumented API calls in iPhone apps. However, in the past, it seemed the policy was only enforced with regard to using private frameworks. Using undocumented APIs in an app would usually go unnoticed, although as a practice they were risky since at any time Apple could change or remove the undocumented API causing your app to break with a newer release of the OS.

Well, based on reports from many developers recently, it seems Apple now has a tool for scanning submitted apps for undocumented API calls and Apple will reject such apps.

So, double-check those compiler warnings in your code. It could be you are using some undocumented API calls and are at risk for having your next app submission rejected. It's easy to accidentally add some undocumented API calls when searching the Internet for a code snippet to address a problem you've been struggling with for days. A quick cut and paste and your problem is solved, and at the time you might overlook the compiler warning that states the object may not respond to the method being passed (a sure sign that you are using an undocumented API).


Note the compiler warning for this undocumented API call above...

Regardless of how useful some of these undocumented API calls might be, and regardless of the fact that Apple may be using them, if you use them in your apps, your app WILL now get rejected during review.

If Apple does in fact have an automated tool which is scanning submitted apps for these violations, it would be extremely helpful if Apple were to integrate this into the iTunesConnect submission process. Why make a developer wait two weeks to find out their app was rejected because of an API violation when it could have been flagged immediately on submission?

Apple already scans the app binary for some simple items such as version number matching the version listed in the app description during the upload process, so it should be possible to add some more scanning features. Even if it were to take a few minutes, getting an automated rejection several minutes after submission would be preferable to waiting 14 days.

Friday, November 6, 2009

Minor ITC update - Thanks Apple!

Nice! Apple has made a minor change to iTunesConnect which will make the review process a little easier to track.

When you submit a new app or a new update, it will now list the app as "Waiting For Review" rather than "In Review".



Then, when the app is actually being reviewed by Apple the status will change to "In Review". And when approved, yes, as expected, it changes to Approved.



But, best of all, these activities are timestamped! Next to the status of the app is a link called "Status History" which when clicked produces something like this:



This last bit will be useful when setting the date of the app so it appears in the proper date range in the store.

It's just a minor change, but it is nice to see Apple is giving more transparency to the review process.

Wednesday, November 4, 2009

Date parsing on the iPhone

I recently ran into an unexpected behavior using the NSDateFormatter on the iPhone. I was using it for converting strings to internal NSDate objects. Basically, I was parsing an XML file and was trying to turn the dates into usable dates in my code.

All the examples I had seen for using the NSDateFormatter to convert a string to a date went something like this:

You define the format string of how the date is expected to be parsed via:

NSDateFormatter *inputFormatter = [[NSDateFormatter alloc] init];
[inputFormatter setDateFormat:@"yyyyMMdd hh:mm:ss a"];
[inputFormatter setPMSymbol:@"pm"];
[inputFormatter setAMSymbol:@"am"];

And then you can parse a date using this formatter like so:

NSDate *formatterDate = [inputFormatter dateFromString:@"19990711 10:30:00 pm"];
NSLog(@"date:%@", formatterDate);

Well, this doesn't work quite as you might expect. I discovered that on some iPhones, the end resulting date had a time of 10:30AM rather than PM!

It turns out the difference in behavior was due to the "locale" settings on different phones. Specifically in this case, if the user had their phone configured (via Settings) to use a 24 hour clock display, then my format string specifying the am/pm designation was being completely ignored! All times I was trying to convert from text strings were always ending up as AM times.

To prevent this, I needed to add one more step to my NSDateFormatter configuration after it was initialized:

[inputFormatter setLocale:[NSLocale systemLocale]];

By setting the locale to systemLocale, this would prevent the NSDateFormatter from using any custom locale changes the iPhone user may have made.

Tuesday, November 3, 2009

Artificial Life 1.5 now available

Apple has just approved the latest update for Artificial Life (v1.5). As mentioned earlier, this now includes support for editing the chromosomes of individual protozoa. Now you can see if you can do better than natural selection in creating a creature that survives a long time.

Saturday, October 31, 2009

More details on AutoScrollLabel usage

Here are some screenshots demonstrating how to integrate the AutoScrollLabel class into an iPhone XCode project using Interface Builder.

1) Add the AutoScrollLabel class files to your project and add an outlet for the scrolling text. Save the files. Otherwise the next steps won't work.



2) Add a UIScrollView to your view using Interface Builder. Then, using the Inspector, change the class type to AutoScrollLabel.



3) Right click on the scrolling label and assign a referencing outlet to be the outlet you added in step 1.



4) Add code to your view controller class to set the text and other properties for the autoScrollLabel.



5) Compile your project and the autoScrollLabel should now be scrolling like a marquee.

And in case that's not clear, here's a (silent) video demonstrating the same thing. (You might want to bump the video to fullscreen so the text is readable.) Enjoy!

AutoScrollLabel Demo from Brian Stormont on Vimeo.

Friday, October 30, 2009

A simple scrolling UILabel for iPhone devs

Here's a simple class which mimics the most common features of a UILabel, yet will act like a horizontally scrolling marquee. It is actually a subclass of UIScrollView, so to use it with Interface Builder, you will need to create a UIScrollView item and then change its class to this class - which I called AutoScrollLabel.

If you don't care about the technical details of how it works and just want to use it, you can download the class files here:

http://stormyprods.com/sampleCode/AutoScrollLabel.zip

To use the class, simply set the text and if the text is wider than the allocated space in the view, it will automatically scroll. Here's a very simple example:


autoScrollLabel.text = @"Hi Mom! How are you? I really ought to write more often.";
autoScrollLabel.textColor = [UIColor yellowColor];


The class also supports the font property, so you can set the font as you normally would for a UILabel.

In addition, there are a few properties related to the scrolling:

scrollDirection: set to AUTO_SCROLL_LEFT (default) or AUTO_SCROLL_RIGHT
scrollSpeed: set to the number of pixels per second (default is 30)
pauseInterval: set to the number of seconds to pause when the end of the text is reached. (default is 0.5)
bufferSpaceBetweenLabels: how much blank space between the end of the text and the beginning of the next instance

It turns out this autoscrolling feature was fairly easy to implement. I'm surprised there isn't already something like this in the SDK. The scrolling is implemented using two UILabels contained in a UIScrollView. Each label contains an identical copy of the text and the labels are resized to be just large enough to hold the text without any truncation.

If the text in the UILabel is wider than the containing UIScrollView, then the two UILabels are laid out side-by-side, and the scroll view is animated to scroll from the beginning of one label to the beginning of the next label. The second label is there just to give the illusion of the text looping forever.

The class registers itself as the delegate for the scrolling animation block, so when the animation block ends, it waits the defined pause time, and then just performs another animated scroll, in which case the scroll view is reset back to the beginning of the first label and the process is repeated.

And that's it! Pretty simple. The animation block feature of a UIView does all the hard work.

I hope others find this useful. If you notice any problems in the code, please let me know.

Monday, October 26, 2009

Time Bomb v2.0 - Now Available on iTunes


A new update for Time Bomb is now available for download on iTunes. This update adds support for OpenFeint. You can now compare your fastest times to players around the world, send challenges and counter-challenges to friends, and unlock dozens of achievements.

You can read the full details about the game at TimeBombGame.com.

Friday, October 23, 2009

DevDiary: Artificial Life 1.5 progress

I'm making decent progress with the updates for the newest update of my Artificial Life iPhone app. I've completed the chromosome rule editing, so it will now be possible to edit a protozoa and give it whatever behavior you want!

Here are some screenshots of the new rule editing:





The rules can be dragged to be reordered as well.

I have a few more minor changes to make, and then hopefully will be submitting this update to Apple today. There are a lot more new features I plan on adding in future updates, but this update has been delayed so long I figure it is best to make it available now. I only have a small amount of time to work on this project during the downtime between other clients' projects.

Here's a short video demonstrating the rule editing:

Wednesday, October 21, 2009

Supporting AAC+ via the iPhone SDK

I've been asked a few times about how I've managed to support AAC+ v1 (also known as HE AAC v1) using the iPhone SDK. Even though AAC+ has been supported since iPhone OS 2.2, the process is not currently documented well at all in Apple's iPhone documentation. About 6 months ago, when I had a project requiring AAC+ support, I ended up using one of my iPhone Developer tech support credits to get an answer from Apple. Even then, the answer provided by Apple was fairly vague and it took a few more hours of tinkering for me to get things working.

Since it's apparently still not a well documented procedure, I figured I should share this information. I may be shooting myself in the foot competitively - AAC+ isn't something every radio app currently supports - but I do try to share with the developer community. AAC+ support isn't meant to be some secret feature usable only by some developers - it's officially supported by the SDK. It's just that the documentation is lacking.

This is not meant to be a full tutorial of using the iPhone SDK audio streams and queues. I am assuming you can already play standard audio streams in your app.

When you receive the audiostreamproperty notification for an AAC+ stream, initially the stream property will be AAC. You'll then need enumerate the kAudioFileStreamProperty_FormatList for that property. Retrieve the format list via a call to AudioFileStreamGetProperty(). Loop through the format list and if the stream is in AAC+ format one of the format IDs will be kAudioFormatMPEG4AAC_HE. This is the descriptor you'll need to use for AAC+ support when you call AudioQueueNewOutput().

This last point is key! You must use this new descriptor pulled out of the format list to create your audio queue. If you use the original descriptor, you will only be creating an AAC audio queue rather than an AAC+ one.

Oh, and don't expect this to work on the simulator. For some reason HE AAC is only supported on the real iPhone hardware - the simulator will never return a result of HE AAC - at least it didn't under 2.2.1. I haven't re-tested with any of the 3.x sims.

Also note that the SDK currently only supports AAC+ v1 with SBR (Spectral Band Replication). The PS (parametric stereo) feature of AAC+ v2 does not work and results in a mono audio playback. Also, the AAC+ support only works on OS 2.2 and higher.

Here's an example of how I detect the HE AAC descriptor in an audiostreamproperty notification handler . It's just a snippet of code taken out of context, but hopefully gives you an idea of how it is done:

AudioStreamBasicDescription asbd;
UInt32 asbdSize = sizeof(asbd);
UInt32 formatListSize;
Boolean writable;

err =
AudioFileStreamGetProperty(inAudioFileStream, kAudioFileStreamProperty_DataFormat, &asbdSize, &asbd);
if (err) { /* do something for an error */ }

err =
AudioFileStreamGetPropertyInfo(inAudioFileStream, kAudioFileStreamProperty_FormatList, &formatListSize, &writable);
if (!err) {

        
// get the FormatList data
        void* formatListData = calloc(1, formatListSize);
        err =
AudioFileStreamGetProperty(inAudioFileStream, kAudioFileStreamProperty_FormatList, &formatListSize, formatListData);
        
if (err) { PRINTERROR("get kAudioFilePropertyFormatList"); free(formatListData); ; }
        
        
// Scan through all the supported formats and look for HE AAC
        for (int x = 0; x < formatListSize; x += sizeof(AudioFormatListItem)){
                
AudioStreamBasicDescription *pasbd = formatListData + x;
        
                
if (pasbd->mFormatID == kAudioFormatMPEG4AAC_HE){
                        
NSLog(@“Found HE AAC!");
                        
// HE AAC isn't supported on the simulator for some reason
                        if (!TARGET_IPHONE_SIMULATOR){
                                
memcpy(&asbd, pasbd, sizeof(asbd));
                        }
                        
break;
                }                                
        }
        
free(formatListData);
}

Wednesday, October 14, 2009

Tunemark Radio 1.0.3 has been released!

The latest update for the FREE Tunemark Radio app is now available on iTunes. This update includes some improvements to the clock-radio feature.

I've added a "sleep" timer so you can have the app automatically stop playing music after a preset amount of time.

The alarm now has a failsafe mechanism to play a built in audio tone if the radio station you selected for wake-up is not accessible due to network problems. Also, the alarm has a "Snooze" button so you can choose to go back to sleep for another 10 minutes.

And lastly, the alarm no longer requires the device to plugged into a charger in order for it to work.

As always, this app will remain FREE with no banner ads. If you have additional suggestions for improvements, please let me know.

You can read more about the app here: http://stormyprods.com/products/tunemark_radio.php

Wednesday, October 7, 2009

Balancing views of making money in the App Store

I find these two articles interesting reading. One is a very positive uplifting article regarding the opportunities writing iPhone apps (written by someone who has had a #1 ranked game and is obviously making decent money) and the second is by Newsweek, putting a more somber tone on the idea of trying to make money in the Apple App Store.

http://criticalthoughtgames.com/node/109

http://www.newsweek.com/id/216788/output/print

My personal opinion? Both articles make valid points. I'm not expecting to become a millionaire via the iPhone. I originally quit my job over a year ago to pursue a more challenging career and try to make it on my own doing freelance development. The iPhone is just one platform I was going to use. As it turned out, iPhone development turned out to be very interesting and enjoyable platform to use (even with all the frustrations the come with having to deal with Apple's review process) and I've been able to stay afloat financially concentrating solely on it for the past year. But, when I say stay afloat - I mean just that. I'm making about 1/4 of the salary I was making as a senior software engineer at a corporation. My revenue now is pretty much equal to my expenses - my bank account is about the same as it was when I first quit my job a year ago.

Looking out a little more long term, I don't think I'll continue to focus primarily on the iPhone. The income I am getting is just barely meeting expenses and it doesn't make financial sense to continue the sole iPhone focus indefinitely. At some point I will start working on other platforms to see if something else is a bit more financially viable. I'm not looking to get rich, but it would be best to do more than break even on the expenses.

I definitely have no regrets about quitting my job, though. The change in lifestyle gained from being my own boss and running my own business is well worth the loss in income. It's hard to put a price on freedom - and I suppose I should be grateful for the iPhone, since it has given me my start with this freedom.

Tuesday, October 6, 2009

Dev Diary: preventing iPhone sleep

I've recently added a "clock radio" alarm feature to some of my iPhone radio apps. As part of this process, I had to figure out a reasonable work-around for Apple's restriction of not allowing 3rd party apps to run in the background.

Unfortunately, the best that can be done for an app that wants to behave as an alarm clock is to require the user of the app to not exit the app. While this seems fairly straightforward, it does introduce another problem. When on battery power, most users will not want the screen of the iPhone to be on while they are using the alarm feature, so normal behavior would be for a user to set the alarm and then "lock" the iPhone screen. And there's the problem - the iPhone OS has a feature where if it is running on battery power, it will suspend any running app if the iPhone screen is locked, except under one condition. If the app is playing audio with the audio session property of kAudioSessionCategory_MediaPlayback, the app will be allowed to continue to run indefinitely while the iPhone screen is locked.

So, if you have an alarm clock feature in an app, this would seem to imply that you must keep the iPhone plugged into a charger, otherwise the app will be suspended a few minutes after you lock the screen and the alarm timer will never get triggered. Fortunately there is another way around this problem and it only uses a minor amount of battery power. If you have your app continuously play a silent audio file while the screen is locked, then this will prevent the OS from suspending the app.

Here's a rough example of how you can implement this using a few lines of code and the AVAudioPlayer class.


AVAudioPlayer *silentPlayer;
NSString *soundFile =[NSString stringWithFormat:@"%@/%@", [[NSBundle mainBundle] resourcePath], SILENT_SOUND_FILE];
NSData *data = [NSData dataWithContentsOfFile:soundFile];

if (data){
NSError *outError;
silentPlayer = [[AVAudioPlayer alloc] initWithData:data error:&outError];
}else{
// trigger some error
}

silentPlayer.delegate = self;
silentPlayer.volume = 0.0;
[silentPlayer play];


Then, since I am specifying the class using this silentPlayer is its delegate, I also implement the following method to be notified when the silent file has finished playing. In this case, I want the silent file to loop, so I simply restart it.


- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag
{
// When the sound stops, wait 1 second and play it again - forever!
[NSThread sleepForTimeInterval:1.0f];
[player play];
}


Obviously, this isn't a complete implementation, but should give you the basics to get started with preventing the iPhone from sleeping. In my particular case, when I want the silent file to stop playing, I simply remove the delegate for the silentPlayer and then tell it to stop:

silentPlayer.delegate = nil;
[silentPlayer stop];

This way, when the silentPlayer stops playing, the audioPlayerDidFinishPlaying method will not be called again, so the silent file will no longer be looping.

Radio Paradise iPhone app v2.0 coming soon!

I've submitted the latest version of the Radio Paradise iPhone app to Apple for approval. This newest version will be 2.0. Based on Apple's current review times, hopefully it will be available mid-October.

I've changed the user interface a bit - hopefully most people will think it is an improvement. Here's a screenshot:



As is true with earlier versions, the app includes displaying the album artwork for the current song playing, along with support for viewing more song info (listener comments, ratings, etc.) via tapping the artwork. Tapping on the musical note brings up a "tunemark" feature for saving the song details to a list, emailing the info, or searching on iTunes for the track.

Also noticeable in this screenshot is a new feature - or at least the button for the new feature. I've added an alarm clock and sleep timer feature. This will allow you to use the app as a clock radio - waking up to Radio Paradise as well as a sleep timer to have the app automatically stop after a set amount of time. In the above example screenshot, the sleep timer is currently active and is counting down from 29 minutes.

The following screenshot shows the clock radio configuration screen:



Again, I'm not an artist or a skilled graphic designer, so the screen is pretty plain, but functional. You can have both the alarm clock and sleep timer active at the same time. In the above screenshot, the alarm is currently on and is set for 7am.

Unfortunately, Apple does not allow 3rd party apps to run in the background, so in order for the alarm clock to work, the app must continue to be running. The screen can be turned off to save battery power, but the app still must be running.

Since the radio playing depends on the Internet, the alarm clock feature includes a failsafe. If the Radio Paradise stream is down, or the wireless network is down, the alarm will detect this problem and will still play an audible sound - a simple "dinging".

Thursday, September 17, 2009

App review process is getting better!

Wow! I must say, after all my whining about Apple's iPhone app review process, I was pleasantly surprised today. I submitted an app update for Tunemark Radio after discovering a crash bug that could occur under poor network conditions. I had read in developer forums that it was possible to email Apple when you had a critical update and there was a chance for getting the update reviewed a bit quicker.

Well, I submitted a crash fix update on Tuesday night and emailed Apple informing them of the update on Wednesday morning. This evening (one day later!) I received notification that my update has been approved. Total time in the queue was less than 2 days. Thank you Apple!

It seems this review process is improving.

Thursday, September 10, 2009

Stormy's Tunemark Radio is now available

Stormy's Tunemark Radio is now available as a free download on iTunes.

This was originally mentioned in earlier blog entries as "Stormy's Radio Thing", however a friend made the suggestion I rename the app "Tunemark Radio" based on the feature it has of allowing tunemarking (i.e. bookmarking or tagging) tune names for later reference or lookup on iTunes, emailing to friends, etc.

This is designed as a FREE multipurpose radio tuner app and will always be free of banner ads.

Features include:

  • Support for mp3, AAC, AAC+ v1

  • Add custom URLs - pls, m3u, and direct link

  • Browse the complete free SHOUTcast™ directory

  • Search SHOUTcast™ via keywords

  • Tunemark songs - search on iTunes, email song info, or save to a list for later reference

  • SHOUTcast™ stations can be 'favorited' for faster reference

  • Alarm clock - wake up to your favorite station

  • Multiple skins - choose from 4 different backgrounds



If you have any suggestions for future features, please let me know.

You can download the app on iTunes today here.

Monday, August 3, 2009

Apple's Absurdity

Ok, I seriously think Apple must be trying their hardest to annoy developers. Tonight I received the following email:

Dear Brian,

We noticed that your application, Radio Paradise, which is live on the App Store is not appropriately rated. In order to change the rating of your application, you will need to resubmit a new binary to iTunes Connect. Please reply to this email once this has been completed, and we will expedite your review.

Regards,

iPhone Developer Program


Ok, now, let me be clear on one point. The app rating is not something that is negotiable with Apple. If you submit an app with what they feel is an incorrect rating, Apple will reject it.

So, do you notice anything missing from this email? Apparently, Apple prefers to play a guessing game. I get to try to guess what app rating they want, and each time I guess wrong, they'll get to say "Bzzt! Wrong!" and reject the app.

What the heck Apple? Why not just tell me the freaking rating you want?!?!?! It's not like I have any choice in the matter. Even simpler, why not just change the rating to the one you want. The rating you want is the only real option I have.

Apple is acting like some twisted insecure friend who wants to put you through some stupid head-game tests just to make you demonstrate how much you really do love them. And you know something Apple? The love is wearing thin.

To be clear, I don't have a problem re-rating the app. I'll put whatever rating Apple wants. I honestly don't have a choice in the matter anyhow. But making me guess at what rating they want - that's just absurd. Obviously they have a rating in mind. Why not just tell me what it should be?

UPDATE: I sent a couple email messages to Apple asking for clarification on what rating they'd like me to assign to the app. As of 8/31, Apple never replied. I finally just resubmitted the app with the rating I felt was appropriate (12+) and sent another email to Apple letting them know (as they requested) that I resubmitted the app. Oddly, even though Apple never even acknowledged my previous two emails asking what rating they'd like, Apple did immediately reply thanking me for resubmitting the app. Sheesh. Apple is definitely playing the twisted insecure friend role well. Reminds me of an old girlfriend...

Sunday, August 2, 2009

Important iTunesConnect changes

In case you haven't read, Apple has made two significant changes to the app store over the past few days.

1) App Title: Once entered, you can no longer change the title of an app. It can only be changed again if you resubmit a new app for review, or your app is in the "rejected" state. This applies to all current apps. All existing apps are locked with their current titles.

2) Keywords: There's a new keywords field for every app. These keywords, along with the app title will be used for searches in iTunes. Once entered, keywords can not be changed until you resubmit a new app for review (or the app is in the "rejected" state), so make sure you choose your initial keywords wisely! Keywords are also limited to 100 characters (including the comma separators).

I'm a bit surprised about the app title being locked without any prior warning. It seemed to be a pretty common occurrence for developers to append an "On Sale" or "50% off" as part of the app description when they were having a temporary price reduction and now this will be locked as their app title until they submit a new app.

Sunday, July 26, 2009

DevDiary: Stormy's Radio Thing screenshots

I'm almost finished with Stormy's Radio Thing. Just have some tweaks of the user interface and then it should be ready for submission. Hopefully I'll have some free time to finish it this week. Since it's a free app, I'm working on it with any spare time I might have between my paying iPhone jobs.

This will be a free radio app which allows playing any custom stream URL and also supports browsing and searching the complete Shoutcast directory of thousands and thousands of stations. And, again, I should stress, it will be completely free of banner ads.

Here are some screenshots of how the app is progressing:

Friday, July 17, 2009

Upcoming new iPhone app - Stormy's Radio Thing

I have a new FREE iPhone radio app in the works, called Stormy's Radio Thing. I might change the name - it is kind of (intentionally) goofy.

It is a general-purpose radio player - allowing playing of custom stream URLs as well as have complete access to the Shoutcast directory.

Here are the features it currently has:

* MP3, AAC, and HE AAC v1 support
* Custom URL support for adding streams
* Support for m3u, and pls files
* Access to Shoutcast directory, browse genres and direct search
* Support for marking stations as favorites to add to a list of easily accessible "presets"
* Support for pause, rewind, fast-forward timeshifting of the audio
* iTunes tagging
* Alarm clock - wake up with the music from your favorite online radio station
* NO banner ads - ever. This is a FREE app and will always be free of ads.

Are there any other features you might like to see in a general purpose radio tuner app? If you have any feature suggestions, feel free to leave a comment.

There are some things that will not be doable, such as support for HE AAC v2. It requires patent licensing fees, which is not feasible for a free app. If Apple at some point adds support for HE AAC v2 to the iPhone SDK, then I can piggy-back on that, but otherwise it's not going to be possible.

Thursday, July 16, 2009

Apple's iPhone app approval process needs improvement

It's been said by many developers before, but I'll add my voice to the gripes. Apple's iPhone app approval process needs some serious fixing.

Like any process, it's great when it works, and many developers are fortunate enough to never have to see the ugly side of it. If your app is approved in a timely manner, what's to complain about? But a true representation of a company's customer service comes into focus when there is a problem. And that's where Apple fails miserably.

First of all, there is absolutely no transparency or communication. And when I say communication, I am referring to a dialog. Boiler plate text saying your app "is requiring unexpected additional time for review" is not communication, especially when further queries weeks later to Apple get another boiler plate reply that says the oh so very helpful, "there is no additional information to share at this time".

Why can't Apple simply state the reason for the delay up front? In all the times I've had an app in this state of "requiring unexpected additional time for review" (4 so far out of dozens approved), I've eventually (many days later) received a phone call from someone at Apple who tells me Apple is taking issue with a specific aspect of my app and they want me to change it. It's almost as if they don't want to put it in writing because it's a grey area case. It's never been something that was part of Apple's official written policy.

And even in this case of speaking with someone on the phone, it's not a dialog. It's basically a command - change this. Asking for an explanation of "why" hits a wall. For example, if I ask why my app can't do this when X number of other apps already approved can, it is politely declined to be answered. The best I can get for response is "I can't comment on that," and this is when I'm actually speaking to someone on the phone. Email is worse - it is simply ignored.

Now in my case, I'm producing apps for a third party - mainly radio stations. This lack of information from Apple adds further complications and potential bad press for Apple. All I can tell my client is their app is in "Apple limbo" and that Apple refuses to provide any additional information. When they ask when it might be approved, the only concrete quote I have from Apple to relay to my client is "there is no additional information to share at this time". What kind of good business practice is that?? What other business can get away with treating their customers like that? I certainly won't treat my clients that way. Because of the unpredictability of Apple's approval process, I specifically do not ask for final payment for my development work until the app is approved by Apple. So, these delays from Apple with no explanation are directly affecting my income.

The second problem is the inconsistency of the review process. One app gets approved with feature set X and another with identical features gets rejected. For example, I submitted two apps on the same day. Both were radio apps for different radio stations and contained identical features. One app was approved after a week while the second app received the dreaded this app is "taking unexpected additional time for review" email. It's been over a month now and this second app still hasn't been approved. I even got the eventual call from Apple telling me I need to change a phrase in the app description and was also told once I did this the app would be all set. The other app that was approved contained this exact same phrase. In fact, both these apps were updates and have had the same descriptions since they were approved by Apple last Fall! So, I immediately changed the text Apple found offensive, and now several weeks have gone by and no word on the app being approved. All Apple is willing to say is "there is no additional information to share at this time".

Now, I realize it is Apple's store and they can do whatever they want. They reserve the right to refuse an app for any arbitrary reason - it's in the contract. But treating developers like crap whenever that is a problem is not the best way to do business. When there is a problem, that's when a developer needs help or guidance from Apple the most. Instead, we get a firm "Screw you! It's our store and we can do as we like. Don't bother asking us for help."

At some point, if something better comes along I'll say enough is enough and will spend my time developing software for a different platform. According to the latest stats, I'm only one developer out of 100,000 registered for the iPhone. I'm sure Apple won't even notice I'm gone. But if Apple continues to annoy enough developers and enough developers voice their complaints, maybe Apple will make some much needed changes to their business process.

[EDIT: For a much better written complaint about the approval process, I suggest this article: http://tech.yahoo.com/news/infoworld/20090720/tc_infoworld/83773_1 by Peter Wayner. He covers things in much greater detail and hits every point that has been bothering me - even ones I hadn't mentioned.

And for a very accurate summary of how a phone call "conversation" goes with Apple, read this blog post. I can confirm from personal experience that it is no exaggeration.]

Sunday, July 5, 2009

Radio Paradise app 1.6 - finally approved!

For some unknown reason it took a lot longer than usual (3 weeks!), but Apple finally approved my latest update for Radio Paradise. Version 1.6 is now available as a free download on iTunes.

The big difference in this update is support for buffering about 10 minutes of previously played audio. So, you can now both rewind and pause the live stream, and then fast forward back to the "live" part of the stream.

You can read more about the app here.

.

Monday, June 29, 2009

DevDiary: The tech behind Piggy



While the recently released Piggy app might not seem like the most technically advance iPhone app ever produced (and it's not), there was an interesting tech problem to be solved.

The animation used in Piggy is pre-rendered 3D animation. Normally, when playing a pre-rendered movie, you might just use Apple's internal movie player and be done. However, with this piggy app, there are about a dozen different animation sequences and they can be triggered in any order. There's no way to pre-cache all the movies - a bunch of 320x480 movies animated at 30 frames per second would just take up way too much memory. And loading the movies on demand using the SDK's supplied movie player wouldn't be ideal. It wouldn't be a very interactive pig if after tapping on a trigger point you had to wait a few seconds before the animation would occur.

So, as I described a few weeks ago, I converted each frame of animation into a PVRTC texture image. This image format is used natively by the iPhone graphics chip, so if I use them as OpenGL textures, then I can load any frame of animation from storage on the fly and get a nice 30 frames per second.

Piggy - the iPhone app


In the pursuit of mindless silliness on the iPhone, Stormy Productions presents Piggy, a new iPhone app.
You can buy it on iTunes here for $0.99.

And what is Piggy? It's an interactive pig alarm. Isn't that a helpful description? No? Well, let me be a bit clearer. It's a 3D cell-shaded pig that displays a range of animations and produces a series of pig-like sounds on command. Poke the pig in different spots to produce the desired effect.

And, if that weren't enough (you mean you want more than an interactive pig noise maker app?) you can also use the pig as a timer or alarm. Choose the sound effect you'd like, set the timer, and... wait. You can watch the digits count down from the time of your choosing. Have trouble with numbers? You can learn how to count backwards by watching this app! While that's not the most useful or creative way to use the Piggy timer, how you choose to use it is totally up to you.

Saturday, June 20, 2009

Image Picker Sample

The UIImagePickerController provided by Apple is pretty weird. If all you want to do is grab an image, its usage is very straightforward. But, if you want to first allow the user to zoom and crop the photo, the way the controller works is very unintuitive.

Back in February I struggled with trying to use a UIImagePickerController to allow a user to make such cropping adjustments before having the image returned. Fortunately, I found a good starting point with a post on Apple's iPhone developer forum (read it here). Using that sample code and a lot of tinkering with many sample images, I came up with a method that seems to handle the zooming and cropping of arbitrary images.

Someone else was recently writing about how this process is a real pain in the neck, so I figured it might be helpful to others if I posted some sample code.

So, here's a link to a sample XCode project which implements a subclass of UIImagePickerController. The code isn't pretty - I wrote it in a hurry several months ago, it did what I needed at the time, and I don't want to revisit it now. Feel free to do whatever you'd like with it.

My key to understanding the whole image picker crop/zoom process and the cropping info returned is summarized by these comments in my code

"The crop rectangle returned has been scaled relative to the image being 480×640 regardless of the real image dimensions. And, to make matters worse, it’s a virtual 320×320 square centered on the screen rather than being the whole screen. So, we need to rescale the crop rectangle so it matches the original image resolution and so it’s the full screen."

Perhaps this will be useful or helpful to someone else.

The code works with both 2.x and 3.0 of iPhone OS, although the sample project file I include was made specifically for 3.0.

Cheers.

Wednesday, June 17, 2009

My 0.5 seconds of fame

A friend of mine sent me a tip today that I was mentioned in some article at Macnewsworld.com . Here's the link:

http://www.macnewsworld.com/story/67330.html

It's an article about a local company here in Rhode Island (GLAD WORKS) that is seeing an ever increasing part of its business related to iPhone development.

.

Monday, June 15, 2009

Radio Paradise app 1.6 - hopefully next week

I'm just finishing up some enhancements to the free Radio Paradise app - this'll bring it to version 1.6. It's now pending review with Apple.

The most noticeable change will be with the user interface, as can be seen in this screenshot:



The app will now buffer approximately 10 minutes of audio and allows rewind and fast forward within this buffer while still buffering the live stream.

It'll also support true "pause" (again, up to about 10 minutes), so if you accidentally pull out your headphones, or need to stop the music for a few minutes, you can then resume right where you left off!

In the above picture the gray bar above the rewind/stop/fast forward buttons represents the audio currently buffered. The red line represents what portion of the buffer to which you are currently listening. In this example, the buffer is about 1/4 full and we are listening to the "live" part of the stream.

I'm still not crazy about my "tunemarking" buttons. The + one will allow you to tag a song, buy it up on iTunes, email the track info, etc, and the other button will let you manage your list of previously marked songs. I'm admittedly a poor graphic designer (programming is my skill set), so this is the best I've come up with so far for representing the tunemarking concept.

You can read more about the current version of the app here.

Sunday, June 7, 2009

Fast, high quality, small memory footprint. Pick two.

I've finally found a solution to my page-flipping animation problem. The short answer: PVRTC texture maps. PVRTC texture maps are extremely efficient. I've found I can load a 512x512 PVRTC texture directly from the iPhone filesystem for each unique frame of full screen animation and still main 60 frames per second. I repeat - 60 frames per second of fullscreen 320x480 page flipping animation with no a single image being pre-loaded or cached. I was very surprised at the speed difference.

That's the short answer. The long answer is this efficiency doesn't come without some tradeoffs. All the time I was trying to find a good solution to the full screen page-flipping animation problem, I would find things that worked, but the tradeoffs were usually unacceptable. For instance, I could get 30 FPS animation if I load all my frames of animation into ram first and just use drawRect. Given I had over 1300 frame of animation, this was not acceptable - the RAM requirements would be crazy!

My frames of animation are cell-shaded pictures and as jpg images, they only take about 30K each. However, when converted to a PVRTC, the size of each image is about 120K using the standard PVRTC compression and is 64K if I use the most aggressive compression. So, the tradeoff now is the app download size. Instead of being about 35 meg, it's now going to be about 80 meg. But, this is the most reasonable tradeoff of the bunch. I couldn't have my app use more RAM, and I didn't want to drop the frame rate even lower than 10 FPS, so opting for more filesystem space used with the benefit of 60 FPS seems like a decent trade off.

Now I just have to go through the process of converting all the images. Unfortunately, Apple's texturetool program is dog slow! It is taking over 4 seconds per 512x512 on my MacBook Pro. Fortunately I have batched the process using a perl script so I can just let it run overnight.

Saturday, June 6, 2009

DevDiary: Problems with DrawRect:

I've been working on a "hobby" app project off and on for the past few weeks. It involves performing full-screen page-flipping animation. Unfortunately, I keep running into system bottlenecks issues.

I know there must be a good solution, but so far I haven't found it.

Here's the problem. I have about 35 meg worth of cell-style animation, and each image is 320x480 (i.e. it takes up the full iPhone screen). There's about 1300 frame in total. There's no realistic way I can cache all these images in RAM on the iPhone. Since the animation is dynamic, I can't even cache what will be animated next as it is determined by user interaction.

What I am currently doing is loading each frame of animation on demand. This is much slower than caching the images in RAM first (I can only get about 10 FPS rather than the 30 if I were able to cache the images). But this isn't the problem. I'm ok with the lower frame rate.

The problem is I can't seem to find a good method for having low level access to the image buffer of the current view while still maintaing decent responsiveness for touch events.

I'm currently overriding the drawRect method of the UIView (I call [image drawAtPoint:(CGPointMake(0.0, 0.0))]; to render my image) and then for my animation routine, I just repeatedly call [view setNeedsDisplay]. This almost works. There are no memory issues at all since the view is just getting bitmap data written to it rather than a handle to an image. The problem is the rendering takes up so much bandwidth that the app no longer responds to touch events when running under iPhone OS 2.x. Oddly, running under 3.0 the app performs fine with touch events. But, I'd like to release the app for 2.x, so this approach won't work.

I also tried using the CALayer of a view and setting its content to my current image (via layer.content = myImage), but that causes severe memory problems with the iPhone OS. Touch events now work, but memory problems occur. Even though I'm releasing each image after the layer uses it, the memory still hangs around and eventually the iPhone OS kicks my app for being a bad citizen.

So, I'm now trying to figure out another approach. I'm wondering if using OpenGL ES would work. I've used it in another app for doing animation, but have no experience with trying to render large full screen bitmaps. Ideally, what I'd like is to just get raw access to the OpenGL framebuffer, dump my bitmap image there and then display the framebuffer. I'm hoping I don't have to treat my animation frames as textures. That seems like it would add even more overhead and slow down the frmae rate even more.

Anyone have any tips on what might be a good solution?

Friday, June 5, 2009

Adjusting the iPhone master volume programmatically

Looking for a way to adjust the master volume control on the iPhone via a function call? It's been said it can't be done without using the private Celestial framework, but that's not true!

If you are using an MPVolumeView to provide a slider interface for adjusting the iPhone system volume, you can adjust the value of this slider and in turn adjust the master volume on the iPhone.

Here's how I figured it out.

Assuming you already have an instance of the MPVolumeView class, you need to search its subviews to find the MPVolumeSlider view:


UISlider *volumeViewSlider;

// Find the MPVolumeSlider
for (UIView *view in [volumeView subviews]){
if ([[[view class] description] isEqualToString:@"MPVolumeSlider"]) {
volumeViewSlider = view;
}
}


So, what is an MPVolumeSlider and what can you do with it? Well, here's where Erica Sadun's documentation on the iPhone SDK classes comes in handy. Specifically the page which documents the MPVolumeSlider.

If you take a look at that documentation, you can see an MPVolumeSlider is a subclass of the UISlider. This means you can do all the UISlider type stuff to it, such as change the look, color, etc. I've already documented taking advantage of that in a sample XCode project in a previous blog post.

So, if it's a UISlider, what happens if we try to adjust its slider value via this call?


[volumeViewSlider setValue: 1.0f animated:YES];


Well, the slider does change to the maximum value, but the system volume remains the same. If we then just tap on the thumb control for the slider, the volume then immediately jumps to the new volume level, but we are looking for a solution that requires no user interaction. We are getting close, but not quite a complete answer.

Since the volume does change when the slider is tapped, I then tried looking at the targets that might have registered with the UIControl methods of the slider:


NSSet *mySet = [volumeViewSlider allTargets];
NSLog(@"%@", mySet);


No such luck. The targets was null. So, how is the system volume getting changed when someone drags the slider? Something has to be monitoring the slider, right?

Well, I tried to see if any targets were registered as being notified by any UIControl event:

NSArray *actions = [volumeViewSlider actionsForTarget:nil forControlEvent:UIControlEventAllEvents];
NSLog(@"Actions:%@", actions);

But, again the results were nil.

So, not having any luck there, I took another look at the documentation on Erica's site. I noticed a class method for the MPVolumeSlider class called _commitVolumeChange. Hmmm.... could this be useful? Indeed, it is!

A simple two function call as follows does the trick!

[volumeViewSlider setValue: 1.0f animated:YES];
[volumeViewSlider _commitVolumeChange];


So, this turns out to be a very easy way to adjust the master volume of the iPhone. You should be aware the _commitVolumeChange method is NOT documented, which means Apple could change it at any time. It currently works for all versions of the iPhone OS, but that doesn't mean it won't change in the future.

Tuesday, June 2, 2009

DevDiary: Time-shifting live radio streaming

Ah, the joys of refactoring code. I took a couple days to rewrite portions of the audio streaming code used in my radio apps to add some more enhancements. In addition to making the code much more modular to allow it to be easily dropped into new projects with no external dependencies, I made a significant improvement.

The code will now allow the live stream to be buffered for up to 10 minutes! This means if you are listening to a radio program and get distracted and miss a bit of what was just played, you can simply rewind the program. Then, if you choose, you can continue to listen to the program slightly time-shifted, or, just fast-forward back to the live portion of the stream.

Or, if you need to take short break from listening, but don't want to miss anything, you can pause the program for up to 10 minutes and all the new content will be buffered.

The only limit imposed right now is the buffer is designed to hold 10 total minutes worth of audio and this includes both pausing and rewinding. You can't both pause the program for 10 minutes AND have the ability to rewind 10 minutes into the past. If you pause the program for 5 minutes, you'll only have 5 minutes of the program buffered in the past.

Hopefully my clients will find this new feature useful.

Time Bomb v1.4 now available!

The newest update to the Time Bomb app (version 1.4) is now available on iTunes. This is primarily a bug-fix release, however one minor change was made to the graphics. Per popular request (and possibly against my better judgement), I removed the game title text from the game-play screen.



So, the bomb screen now it looks a bit more like a real time bomb, except for the big oval tool selector on the lower left. Yes, I could make that slide out of view after you select a tool to give an even more realistic time bomb look, but intentionally did not do that.

You can read more about the game at TimeBombGame.com.

Sunday, May 31, 2009

Workaround for UIPicker / UIDatePicker landscape bug

There's an odd bug with the UIPicker and UIDatePicker classes on the iPhone when used in a landscape orientation. Rather than rendering as would be expected, the UIDatePicker is shifted to the right by about 50 pixels and the height is wrong. Even worse, if you decide to change the date format to be a count down timer (myPicker.datePickerMode = UIDatePickerModeCountDownTimer), you get a not so nice view like this:



After searching a bit on the various iPhone developer forums, I noticed different people mention that the problem only occurs if your view is already in landscape mode. If the view is first in portrait and you rotate the view to landscape, then the picker is rendered properly during the auto-rotation. This bit of information led me to a simple workaround for getting a properly rendered picker in landscape without having to have the user see a portrait version of the view first.

All you have to do is fake some part of the underlying UI into thinking you are in portrait mode even though your aren't. I have no idea why this works, but it does. I've already wasted too many hours on this annoying bug, so I settled on this hack. (I'm very surprised Apple still has this obvious bug in the SDK when we are coming up on a 3.0 release, but it's there. And yes, people have logged bug reports about it. Ok, enough of my side rant.)

So, how do you do this bit of trickery? Assuming your main app is already in landscape mode, you can do the following in the view controller for the view containing the picker view:


-(void)viewWillAppear: (BOOL)animated {

// Fake the UI rendering to think we are in portrait orientation
[[UIApplication sharedApplication] setStatusBarOrientation: UIInterfaceOrientationPortrait animated: YES];

}


For some reason, this causes the picker view to render properly even though the view really does remain in landscape mode. My countdown timer picker now looks good and proper:



That's it. Just one line of code and the landscape rendering of a picker is fixed. Again, I have no idea why. Perhaps someone more in touch with the inner workings of Cocoa will point out the reason why this hack works.

As a somewhat humorous aside, while searching (in vain) for a solution to this problem on various iPhone SDK forums, I did run into an odd feature of the official Apple developer forums (currently in beta). I typed in a search for "uipickerview uiinterfaceorientationlandscaperight" and the search came back with no matching results, but Apple was kinda enough to offer this helpful suggestion: "Did you mean: cupcake itinerancies?"

Saturday, May 30, 2009

Robotics and Artificial Life

Today I received an email from someone who enjoys my Artificial Life iPhone app. He included a link to an interesting article about an evolutionary robotics experiment in Switzerland that is somewhat similar in concept to what I am trying to do with my app - start with random behaviors and see what useful behavior evolves over time.

Here's a link to the article: http://www.dailygalaxy.com/my_weblog/2009/05/a-robot-hitler.html

If you like artificial life and AI systems, it's an interesting read.

Friday, May 29, 2009

SoundEngine 2.0.3 update

I've uploaded a newer version of the SoundEngine code - version 2.0.3. This provides a few memory leak fixes courtesy of an email I received from HeeHun Kang.

You can read more about the free library code here. The main point of it is to provide a fairly simple method for playing multiple sound effects and background music in an iPhone app using OpenAL. You are welcome to use this code for free however you'd like.

I'm now using this code in a few apps of mine, so I plan on maintaining it for the foreseeable future. I'll post updates and improvements as I make them.

At some point, if I have the spare cycles, I'd like to rewrite the whole library. Right now, as I've mentioned in the past, it's based on the SoundEngine 1.7 code from Apple and it isn't the best example of coding out there. But, I needed something on short notice so modifying it was my best option at the time.

One tip: you need to have the sound effects in the proper format in order to be usable with this code. The following command will convert an audio CAF file to the necessary format:

afconvert -f caff -d LEI16@44100 originalfile.caf convertedfile.caf

The above assumes you have initialized the sound engine to use 44.1Mhz. If you are using a different frequency, adjust the command accordingly.

Tuesday, May 26, 2009

Artificial Life tip

This question has come up several times regarding the recent updates to the Artificial Life app.

Why do I no longer see population explosions like I did with earlier versions of the app?

The reproduction rate of the protozoa is tied directly to their "desire" meter. Two protozoa are only allowed to mate if their desire is 50% or higher. The default timer controlling the protozoa's life meters was adjusted to allow an individual protozoa's life span to be somewhat longer. As a result, the desire meter now increases at a slower rate.

If you would prefer to have the earlier behavior of fairly rapid population explosions, you can achieve this by adjusting the protozoa's "Max Energy" setting. Choosing a value of 100, rather than the default 200 will achieve the desired effect. Protozoa will be able to reproduce at twice the normal rate, although any one protozoa will have half the normal life span if it does not eat anything and will get hungry at twice the default rate.

In a future update I will add a slider so you can choose the desire level at which a protozoa will be able to reproduce. This way you will have a finer level of control over what is occurring without having to also adjust the life-span of a creature.

Friday, May 22, 2009

Replacing the QuickTime logo with a custom image

IMPORTANT NOTE: As of iPhone OS 3.1, this technique no longer works. As I mentioned in the original post, this technique depended on the internal structure of the QuickTime player view hierarchy and could stop working at any time. And, so it has. I leave this post for historical purposes, but it is no longer accurate or valid. Except maybe as a warning to not depend on the internal structure of Apple's classes.

On an iPhone developer forum, someone recently asked whether it is possible to replace the QuickTime 'QT' logo that appears with the iPhone movie player when playing an audio file or stream in an iPhone app. Several people responded saying it is not possible, even though the YouTube app does it. I respectfully disagree. Presented below is a very simple technique which currently will in fact work, and is a technique I am using in an app already available on iTunes.

If you are curious what the end result looks like, take a look at the Hi Tony app on iTunes (link opens iTunes). It's a free download. [ EDIT: the technique I was originally using only works with 2.x of the iPhone OS. A new update to the Hi Tony! app which will work with 3.0 is pending with Apple.]

If you just want to see the code, it is provided below. It assumes a certain view name ("MPVideoBackgroundView") will exist in the movie player class. There's no guarantee Apple won't change this in the future. Use at your own risk.

I should point out that no hidden APIs or function calls are being used, so in theory Apple should not reject your app if you use this technique. Again, however, use at your own risk. As I've mentioned before Apple's review process can be arbitrary and subjective. Just because my app was approved using this technique does not mean yours will.

But, in the interest of "sharing the knowledge", I figured I should make this technique available to any developer that might want to try it themselves. The function for recursively searching an object for its underlying views was based on a simple example from Erica Sadun. As for finding the magical view name of "MPVideoBackgroundView", this just involved a lot of trial and error on my part examining all the subviews of the movie player.

Please note: This is just a rough example to demonstrate the principle. The code as shown below does not clean up after itself memory-wise.

[EDIT: The following code is a lot different than my original post. It has been rewritten to work with iPhone OS 2.x and 3.0]



- (bool) findVideoBackgroundView: (id) aView level: (int) level
{
NSString *name = [[aView class] description];

if ([name isEqualToString:@"MPVideoBackgroundView"]){
CGRect viewRect = CGRectMake(0, 0, 480, 320);
UIView *temp_view = [[UIImageView alloc] initWithFrame:viewRect];
[temp_view setAlpha:1.0];
[temp_view setBackgroundColor:[UIColor blackColor]];

UIImage *img = [UIImage imageNamed:@"Picture 9.png"];

int x_offset = (480 - img.size.width)/2;
int y_offset = (320 - img.size.height)/2;
CGRect titleRect = CGRectMake(x_offset, y_offset, img.size.width, img.size.height);
UIImageView *myImage = [[UIImageView alloc] initWithFrame:titleRect];
[myImage setImage:img];
[temp_view addSubview:myImage];
[aView insertSubview:temp_view atIndex:0];

return true;
}

for (UIView *subview in [aView subviews]){
if ([self findVideoBackgroundView:subview level:(level + 1)]){
return TRUE;
}
}
return FALSE;
}


- (void) monitorMovieWindow
{
// With iPhone OS 3.0, the movie view does not appear immmediately after calling play.
// It could take several seconds before the view appears.
// As a result, we run this thread in the background to look for when the movie player appears.

// There's probably a better way to do this.

NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

bool movieViewNotFound = TRUE;
int maxRetry = 40; // try waiting for the movie view to appear for 4 seconds

while(movieViewNotFound && maxRetry > 0){

// According to Apple's MoviePlayer sample code, the movie player should be the second view in the window stack
NSArray *windows = [[UIApplication sharedApplication] windows];
// Locate the movie player window
UIWindow *moviePlayerWindow = [windows objectAtIndex:1];

if ([self findVideoBackgroundView: moviePlayerWindow level:0]){
movieViewNotFound = FALSE;
}else{
[NSThread sleepForTimeInterval:0.1];
-- maxRetry;
}
}
[pool release];
}


...

// Here's how you would make use of the above methods

// create a new player and initialize it with the movie URL path
MPMoviePlayerController* theMovie=[[MPMoviePlayerController alloc] initWithContentURL:[NSURL URLWithString:@"http://blahblah-insert your URL here"]];
[theMovie play];
// Call the method to overlay the QTlogo view with a custom image
[self performSelectorInBackground:@selector(monitorMovieWindow) withObject:nil];


Thursday, May 21, 2009

Artificial Life 1.4 now available

As the subject line reads, Artificial Life 1.4 is now available in the iTunes store! This update is mainly "cosmetic" - no significant changes were made to the behavior of the life forms. However, the app grew in size by about 16 meg! I've added sound effects and 16 minutes of ambient music. Sound effects and music can be toggled on of off per user preference, so if you prefer silent protozoa, that's your choice.

Special thanks to R. Scott Lachance for granting me a license to use his ambient down tempo jazz tracks in the app! The app only includes excerpts of his music that best fit within the context of the app - full length individual tracks from his CD are not present. Check out his music on iTunes if you like what you hear in the the app. It's listed under the artist name DigiTube.

The next update (1.5) is currently under development and will include some other feature suggestions I've received as feedback. Thanks for sending in your ideas!

All content copyright © 2009  Brian Stormont, unless otherwise noted.   All rights reserved.