Monthly Archives: September 2012

Comparision of 4 approaches to playing audio in iOS

There are at least four different ways of playing audio in iOS.  Each has their own wrinkles and advantages. In this article I briefly compare and contrast some of the differences between the options.  For the TL;DR version skip to the table at the end which compares the approaches. (actually, to be honest, I’ve had this post in my drafts for a very long time, and just wanted to get it published. The body of the article isn’t as good as the table — skim the article and go to the table :))

  • MPMusicPlayerController(using the iPodMusicPlayer)
  • MPMusicPlayerController(using the applicationMusicPlayer)
  • AVAudioPlayer
  • AVPlayer

 

The MPMusicPlayerController using the iPodMusicPlayer is the highest level player, and matches closely to the iPod.  The actual iPod music player can be accessed and used with the factory method:

+[MPMusicPlayerController iPodMusicPlayer];

The nowPlaying item property will expose the current playing item in the iPod when using the iPodMusicPlayer. Changes to the current item in your application will also update the main iPod music player.

To load your own music player with the same API, use:

+[MPMusicPlayerController applicationMusicPlayer];

In iOS 5.1 and below it is not easily possible to use the AVAudioPlayer to play items from the iTunes library.  While it is possible to retrieve the url for the object, it doesn’t really do what you want. When trying this you will see a somewhat unhelpful error:

Domain = NSOSStatusErrorDomain
Code = -43
Description = Error Domain=NSOSStatusErrorDomain Code=-43 “The operation couldn’t be completed. (OSStatus error -43.)”

The AVPlayer however, allows access to the  iTunes library, playing in the background, custom background behaviour, and playing non-Library audio.

Of the accesible API’s this is the most functionality.  For the hard-core/determined developer, there are lower levels to dig down into, but these 4 options provide a decent set of options to play audio in iOS.  The table below outlines the highlights.

iosMediaPlayer applicationMusicPlayer AVAudioPlayer AVPlayer
play library Y Y N Y
access iPod play location Y N N N
Play in Background Y N ? Y
Custom Background behaviour N N/A ? Y
Play non-Library Audio N N Y Y

Options for getting JRuby 1.6 to use Ruby 1.9 Syntax

In 2012 and beyond you really want to be using Ruby 1.9 syntax (as per the standard ruby implementation KRI). JRuby 1.6 uses Ruby 1.8 syntax by default, but this can be changed to be 1.9. There are a bevy of different ways to do this. I’ll outline these here, and give you my recommendation on what to do.

Command Line parameter

The first way to set the ruby syntax version is to call ruby with a –1.9 parameter thusly:

This I don’t like at all because it doesn’t work with irb, and you have to type different things when using KRI and JRuby.

RUBYOPT Environment variable

A second option is to set the RUBYOPT environment variable to –1.9

This works for irb, but will actually prevent KRI from starting up as KRI doesn’t support the –1.9 parameter (KRI is Ruby 1.9 so the parameter doesn’t make sense).

JRUBY_OPTS Environment variable

Another option is to set the JRUBY_OPTS environment variable.

This works great for JRuby , irb in JRuby, and KRI.

.jrubyrc file

The next useful option is in a user specific .jrubyrc file. This gets called before JRuby starts up. Keep it in ~/.jrubyrc

This works well if you are working in an environment where you will always be running 1.9 compatible code. It’s what I currently do.

rvm

If you are using rvm there are a number of ways to do things.

First you can use a .rvmrc and set the JRUBY_OPTS variable, or a PROJECT_JRUBY_OPTS environment variable.

The second option is to enable rvm jruby hooks.

hooks live in $rvm_path/hooks.

In rvm 1.14.3 there are a series of after_use hooks, including some after_use_jruby hooks. Inspect these to see what they do (after_use runs all the other after_use hooks, and the after_use_jruby scripts will get some JRuby magic happening). You could put one of the earlier options here to help make JRuby work.

Conclusion

In conclusion my recommendations for getting JRuby 1.6 to use Ruby 1.9 syntax are:

  1. use a .jrubyrc file wherever possible
  2. use a .rvmrc for situations where you need different versions of JRuby.

Writing Beautiful RSpec Matchers

thoughtbot have created a really nice set of custom matchers for RSpec.  The Shoulda matchers make writing tests for rails models beautiful and clean.

Shoulda matchers make it possible to write specs of the form:

It’s easy to do this for yourself using the friendly matcher DSL that ships with RSpec. Let’s take a look at how.

In the simplest form, all you need to do is to call the define method, passing a name, and a block which in turn calls out to match. The simple case might be:

We’ve just defined a matcher :be_less_than which allows us to do the following:

If we use the describe auto subject feature of RSpec we can also write:

and

With that example we can see that we are getting close to the shoulda matcher syntax.  There’s still an extra level that helps make the shoulda matchers nice, chaining. Happily this is easy to do as well. The dsl provides a chain method.  The chain methods are called before the match, so you can use the chain calls to collect up additional information to validate.  Using our example above, we might want to add in an :and_greater_than chain.

This now will give us the ability to write:

Unfortunately the default descriptions don’t quite work as nice when there are chains in place. You’ll find that you’ll want to write a description in the matcher definition.

Unfortunately the description doesn’t automatically get used in the error messages when the matcher fails, so you’ll want to specify a failure_message_for_should. Basing it off the description is an ok starting point.

Happily RSpec does the right thing with the should not description, so with the details above the matcher will be good. There might be a case where you want a different failure_message_for_should_not, which can also be specified.

That covers how to write simple reusable RSpec matchers to make your test code look as beautiful as your production code. Go ahead and try it yourself.  I’d love to see comments or questions you might have on this.