Here are some more technical details covering AllPlay vs AirVideoEnabler, and future AirVideoEnabler developments for those who are interested...
I've now downloaded AllPlay and had a look at it, to see how its approach varies from mine. Just in case you're interested in some technical details, AllPlay hooks the following:
- [UIMoviePlayerController setAllowsWirelessPlayback:]
- [UIMoviePlayerController initWithPlayerSize:]
- [MPMoviePlayerControllerNew allowsWirelessPlayback]
- [MPMoviePlayerControllerNew setAllowsWirelessPlayback]
- [MPMoviePlayerControllerNew init]
- [MPMoviePlayerController allowsWirelessPlayback]
- [MPMoviePlayerController setAllowsWirelessPlayback:]
- [MPMoviePlayerController initWithContentURL:]
- [MPMoviePlayerController init]
This is actually very similar to my original approach. However, after a little reverse engineering I realised that the above classes (UIMoviePlayerController , MPMoviePlayerController, MPMoviePlayerControllerNew) all form part of a class cluster alongside a few others AllPlay missed (MPPortraitVideoViewController, MPVideoOverlay, MPWildcatFullScreenVideoOverlay, MPTransportControls, and MPVideoViewController).
After a little digging, I realised that the core functionality is implemented in the class "MPVideoViewController", and all the classes mentioned above simply invoke this functionality. Therefore I narrowed down the function that needs to be hooked to exactly *one*
- [MPVideoViewController allowsWirelessPlayback]
While I understand that at first glance, the AirPlay implementation may see more thorough, it is in general far more elegant to implement a hook at the core point where it matters, rather than trying to find and hook every airplay-related hook in the class cluster. More hooks aren't a good thing, and each hook increases the risk of stability problems as things change. For example, AllPlay currently causes all third-party apps linked against earlier frameworks to crash as soon as they try and play some video. Here's what happens when I try and fire up Crash Kart with AllPlay installed:
The class cluster internally instantiates a MPMoviePlayerControllerOld object instead of MPMoviePlayerController, which lacks the setAllowsWirelessPlayback method, and the whole app crashes. This affects a lot of applications, and the average user may not realise why many of their apps are suddenly crashing.
One of the issues I've noticed with AirPlay is that it will send the media URL to the Apple TV, and not the stream itsself. This is a sensible implementation as it removes the need for the iOS to be powered on and reliably networked during playback of videos on the TV, however it introduces problems for some online services like BBC iPlayer as these generate a URL containing a one-time token - so the stream stops working when switching between the iPhone and the Apple TV as the URL is only valid once. In a future AirVideoEnabler update, I plan to add detection of this scenario, and proxying of the video stream via the device.