<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>TouchCentric &#187; iPhone Development</title>
	<atom:link href="http://www.touchcentric.com/blog/archives/category/iphone-development/feed" rel="self" type="application/rss+xml" />
	<link>http://www.touchcentric.com/blog</link>
	<description>iPhone-centric stuff we're thinking about</description>
	<lastBuildDate>Wed, 25 Aug 2010 17:09:15 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>Video Mirroring for iOS 4 Apps</title>
		<link>http://www.touchcentric.com/blog/archives/123</link>
		<comments>http://www.touchcentric.com/blog/archives/123#comments</comments>
		<pubDate>Tue, 24 Aug 2010 15:34:53 +0000</pubDate>
		<dc:creator>Rob Terrell</dc:creator>
				<category><![CDATA[iPhone Development]]></category>
		<category><![CDATA[component]]></category>
		<category><![CDATA[composite]]></category>
		<category><![CDATA[ios 4]]></category>
		<category><![CDATA[mirrored video]]></category>
		<category><![CDATA[vga]]></category>
		<category><![CDATA[video out]]></category>

		<guid isPermaLink="false">http://www.touchcentric.com/blog/?p=123</guid>
		<description><![CDATA[Project the video of your iPhone app to thousands of adoring fans! This is an iOS 4.0 rewrite of the TVOut code described here: http://www.touchcentric.com/blog/archives/3. I wrote the original code so members of our local iPhone Developer’s Meetup could show our apps to each other. Since then it’s been used by hundreds of developers. It’s proven invaluable for group demos, trade shows, client meetings, investor pitches, and so on. Sadly, iOS 4.0 completely broke the old code, so a rewrite was necessary. Happily iOS 4 makes previously difficult things fairly easy. A bonus: this code is now entirely safe for the App Store.]]></description>
			<content:encoded><![CDATA[<h2 id="be_like_steve_">Be Like Steve!</h2>
<p>Project the video of your iPhone app to thousands of adoring fans! This is an iOS 4.0 rewrite of the &#8220;iPhone App Video Mirroring&#8221; code described here: <a href="http://www.touchcentric.com/blog/archives/3">http://www.touchcentric.com/blog/archives/3</a>. As I said last time, &#8220;Why can’t we be like Steve, using our apps on our phone, with the display projected for all to see?&#8221; Now you can.</p>
<p>I wrote the original code so members of our local <a href="http://www.meetup.com/iPhone-Developers/">iPhone Developer’s Meetup</a> could show our apps to each other. Since then it’s been used by hundreds of developers. It’s proven invaluable for group demos, trade shows, client meetings, investor pitches, and so on. Sadly, iOS 4.0 completely broke the old code, so a rewrite was necessary. Happily, iOS 4 makes previously difficult things fairly easy.</p>
<div class="wp-caption alignright" style="width: 310px"><img class=" " title="TVOutManager running on an iPad" src="http://touchcentric.com/img/ZZ20A6535A.jpg" alt="TVOutManager running on an iPad" width="300" height="223" /><p class="wp-caption-text">TVOutManager running on an iPad</p></div>
<p>A bonus: this code is now entirely safe for the App Store. Zero private APIs are used. (You do have the option to use one, as you’ll see below, but it’s turned off by default.)</p>
<p>This code has been tested on iOS 4.0.1 on an iPad and an iPhone 4. If you find problems with other devices, please let me know in the comments.</p>
<h3 id="what8217s_new">What’s New</h3>
<p>Like before, this is a fire-and-forget solution to mirroring the display of your iOS device (iPhone, iPod Touch, iPad) on an external display. The new version uses public APIs, so it can be used in apps published on the App Store. It supports detecting cabling (plugging and unplugging the display), orientation changes, and even offers a “tv safe mode” for displaying your app on an older analog video device. (You probably don’t even know what that is, because you’re a young whippersnapper who grew up with LCD flatscreen TVs, whereas I am testing this code on my old beloved Apple ][+ color display, and thus find the TV safe mode handy.)</p>
<p>Under the hood, new in this release is the TVOutManager singleton class. In the previous release, I’d made the TVOut manager code as a category on UIApplication, thinking that would make it easier to use and simpler to understand. Based on the emails I got, I think it was definitely simple to use, although not really simpler to understand.</p>
<p>So now TVOutManager is its own class. It’s a singleton, so you simply invoke commands on the shared instance. For example, here’s how you start showing video:</p>
<pre><code>[[TVOutManager sharedInstance] startTVOut];
</code></pre>
<p>Stopping is just as easy:</p>
<pre><code>[[TVOutManager sharedInstance] stopTVOut];
</code></pre>
<p>While the cable is connected, changes to the device orientation are tracked and the mirrored output is rotated (with a little animation effect).</p>
<h3 id="get_the_code">How To Use It</h3>
<p>It's crazy easy. Just three steps:</p>
<ol>
<li>Get the files TVOutManager.m and TVOutManager.h from github and add them to your project.</li>
<li>In your app controller, add this to the other imports near the top:  <code>#import "TVOutManager.h" </code></li>
<li>In your application's -applicationDidFinishLaunching: method, add this line: <code>[[TVOutManager sharedInstance] startTVOut];</code></li>
</ol>
<h3 id="get_the_code">Get the Code!</h3>
<p>A sample project that includes the TVOutManager singleton can be downloaded from github:</p>
<p><a href="http://github.com/robterrell/TVOutManager">http://github.com/robterrell/TVOutManager</a></p>
<h3 id="connections_and_re_connections">Connections and re-connections</h3>
<p>Last year our cable options were limited to composite and component cables used for playing videos on a TV. Since the launch of the iPad, Apple also offers a VGA connector cable, ostensibly iPad-only but which is what I used with an iPhone 4 while developing this code. I also tested with the composite out cable. Both cable seem to work fine. I’m not sure about iPhone 3GS and older devices, though — those devices may not support the VGA cable, although they certainly do support the composite and component cables.</p>
<p>While the TV output is running, if the video output cable is disconnected, the class will catch a notification, and stop sending video to the external window. Likewise, if a video output cable is connected, the class will catch that notification, and automatically start showing the video.</p>
<p>You don't even need to call -startTVOut -- just initialize the singleton sharedInstance, and the class will watch for cable connection notifications.</p>
<h2 id="app_store_safe">App-Store Safe!</h2>
<p>Unlike the previous version, this class uses app-store safe methods. You can ship apps that use this code. We are using an Apple-approvied safe-and-friendly method of collecting bitmaps of all visible windows, and then drawing that bitmap on the external screen, which is also displayed using Apple-approved non-private APIs.</p>
<p>The previous version used the MPTVOutWindow class, which seems have to disappeared from iOS 4.0, and UIGetScreenImage() to copy the image of the screen. MPTVOutWindow has always been forbidden, but for a brief time, Apple allowed apps using UIGetScreenImage() onto the store (from December of 2009 until July 2010). However, with the release of iOS 4.0, Apple stuck the “private” designation on it again, and apps are once again being rejected for it. (Apple’s terrible communciation with developers generally means that developers learn this by submitting an app and getting rejected.)</p>
<p>So, here I’ve made use of UIGetScreenImage() an option. Why would you ever use it? For one thing, in my testing it’s quicker than the non-private methods. It also captures the entire screen display, including the status bar, which is handy for our particular use. UIGetScreenImage() also captures the output of EAGLViews, which the Apple-approved method does not (although Apple does have yet another method for getting that).</p>
<h3 id="opengl_support">OpenGL Support</h3>
<p>There was widespread belief that the pervious version wouldn’t work with OpenGL. That mistaken belief came from me — I didn’t realize that UIGetScreenImage() would capture the contents of an OpenGL view. In fact, it does, and it works great.</p>
<p><img class="alignright" title="Simple test of TV out in Unity" src="http://touchcentric.com/img//ZZ2C2E88B9.jpg" alt="Simple test of TV out in Unity" width="288" height="192" />I dropped this new TVOutManager version into a simple test project made with the Unity 3 beta (http://unity3d.com), added one line to the AppController.mm file to call -startTVOut, and changed the USE_UIGETSCREENIMAGE constant to YES. The Unity game played on the TV screen. The framerate dropped from 30 fps to about 26 fps. Definitely watchable and playable. (I’ve gotten into a bad habit of playtesting Unity games on a big screen TV.)</p>
<p>Using UIGetScreenImage means you can’t ship this code; it’s just for demos. If you need to ship TV out code, you’ll have to change the class to follow Apple’s example of converting an EAGLView to a UIImage at http://developer.apple.com/iphone/library/qa/qa2010/qa1704.html. If there’s demand, I can add this to the TVOutManager in a future release.</p>
<h3 id="debugging_with_the_video_out_cable_attached">Debugging with the Video Out Cable Attached</h3>
<p>Obviously you can’t debug an app in Xcode without having the device connected via USB. Likewise, you can’t view the video output without having the VGA cable attached. So debugging was basically impossible.</p>
<p>Thankfully the latest Simulator includes an option to show an external display, but the simulator can’t start and stop this external display while the app is running, so it can’t be used to debug notifications like UIScreenDidConnectNotification.</p>
<p>To work around the problem, I figured I’d have to buy or make a Y-adapter cable: strip down the VGA cable to see what pins it used, and either wire in a USB connector, or make a full Y adapter that merged the pins required for both cable. Intensive Googling led to parts I could <a href="http://www.sparkfun.com/commerce/product&lt;em&gt;info.php?products_id=8035">buy from Sparkfun</a>. Reality set in (these days I don’t have much free time for tinkering and soldering) and I started to look for something a bit more prefab.</p>
<p><img class="alignright" src="http://images.acco.com/KENSINGTON/K33368/K33368-15105.jpg" alt="" width="200" height="200" /></p>
<p>Reading some ancient forum posts about iPod dock issues, I found a reference to the Kensington K33368 “4-in-1 Car Charger,” which is a USB cable that includes a full pass-through dock connector, intended for an FM tuner. I guessed that they’d have wired all of the pins, and it would allow me to plug a second dock cable into the first. These are no longer manufactured, but a few online stores still had stock. I ended up buying one from a seller on eBay. It turned out to work perfectly. I plugged the Kensington cable into my Mac, and the RCA video out or VGA cable into the Kensington cable, and was able to debug away. I highly recommend this setup if you need to debug while watching the display on the big screen.</p>
<h3 id="improvements_needed">Improvements Needed</h3>
<p>Currently, device rotation is correctly tracked for the Portrait and Landscape Left initial starting positions. You can turn the device 90 degrees to the left or right and the view on the external monitor will rotate to match. (There’s even a nice animated rotation of the screen contents on the external video window.) However, portraitUpsideDown is not handled.</p>
<p>It’s possible to confuse it with other starting orientations. This would be easily fixable if we knew what the previous orientation was, but since the UIDeviceOrientationDidChangeNotification doesn’t pass in the previous orientation (or even the new orientation — you have to get it from UIDevice) the code is essentially making a guess about how it should turn the mirrored view. This guess happens to work fine for all starting positions and turns I usually care about (i.e. portrait and landscape left, and 90° turns from these).</p>
<p>If you need to fix this, one possible solution is to track the device orientation at -init and across the lifetime of the object, and figure out the proper rotation of the view at each device orientation change notification. It seemed like a big hassle and I didn’t need it so I didn’t do it, but if someone can contribute it, that would be great.</p>
<h3 id="mirror_other_apps">Mirroring Other Apps</h3>
<p>Adam Curry asked via email if it would be possible to run this in the background (in iOS 4.0) and magically mirror any app running on the device. I tried it, but it didn’t work. Seems like the external monitor support switches to whatever app is in the foreground. This is consistent with other apps that play video (i.e. the iPod app, StreamToMe, etc.) so I’m guessing this is just not possible without digging deeper into private APIs.</p>
<h3 id="compatibility_note">Compatibility Note</h3>
<p>This class relies on certain APIs (i.e. [UIScreen screens]) that only exist in iOS SDK 3.2 and above. If you need to support older devices, you’ll have to use the <a href="http://www.touchcentric.com/blog/archives/3">older version</a>.</p>
<p>The older version uses a class called MPTVOutWindow, which is either missing or renamed in iOS 4.0. This is what causes the older version to crash. The new version walks through the [UIScreen screens] array to find an external screen, and creates a window on that screen (using the UIWindow screen property). Being documented and all, this method appears to be fully future-proof.</p>
<h3 id="tvoutmanager_class_reference">TVOutManager Class Reference</h3>
<p>-sharedInstance<br />
Creates a singleton instance (if it doesn’t already exist) and returns it. Starts listening to cable connection/disconnection and device orientation notifications.</p>
<p>-startTVOut<br />
Creates a window on the second screen at the highest resolution it supports, and starts a timer (at the frames per second rate defined in the class file) to copy the screen contents to the window. If no screen is attached, -startTVOut will simply report a failure to the console.</p>
<p>-stopTVOut<br />
Stops the periodic video-mirror timer (or thread) and releases the offscreen window.</p>
<p>tvSafeMode<br />
When tvSafeMode is YES, the class will scale down the output size by 20%, so that the entire picture can fit within the visible scan area of an analog TV. If you don’t know what an analog TV is, don’t worry, you’ll probably never see one.</p>
<p>kUseBackgroundThread<br />
By default, the class will use an NSTimer to periodically copy the screen display. If you’re doing something that blocks the runloop, a background thread may work better for you. Simply change the define to YES and the class will spawn a thread to periodically copy the screen.</p>
<p>define USE_UIGETSCREENIMAGE</p>
<p>Set to NO to use the App-Store- and Simulator-safe method of capturing the screen. Set to YES to get the highest framerate and capture the status bar, OpenGL views and UIKit transitions.</p>
<p></p>
]]></content:encoded>
			<wfw:commentRss>http://www.touchcentric.com/blog/archives/123/feed</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>WUNC App is in the App Store!</title>
		<link>http://www.touchcentric.com/blog/archives/101</link>
		<comments>http://www.touchcentric.com/blog/archives/101#comments</comments>
		<pubDate>Mon, 07 Dec 2009 02:27:01 +0000</pubDate>
		<dc:creator>Rob Terrell</dc:creator>
				<category><![CDATA[iPhone Development]]></category>

		<guid isPermaLink="false">http://www.touchcentric.com/blog/?p=101</guid>
		<description><![CDATA[The app we built for our local public radio station WUNC has finally emerged from the review process and is available, for free, from the App Store. The app plays the station&#8217;s live audio stream. You can pause the stream, too, and the app will buffer the stream playback, so you can pick up where [...]]]></description>
			<content:encoded><![CDATA[<p>The app we built for our local public radio station WUNC has finally emerged from the review process and is available, for free, from the App Store. The app plays the station&#8217;s live audio stream. You can pause the stream, too, and the app will buffer the stream playback, so you can pick up where you paused it. Here&#8217;s a peek:</p>
<p><img src="http://touchcentric.com/img/wunc_screenshot_1.jpg" alt="The WUNC app" /></p>
<p>If you listen to WUNC at all, you&#8217;ll be hearing about this on-air once or twice, I bet.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.touchcentric.com/blog/archives/101/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>iPhone App Video Mirroring in Three Easy Steps</title>
		<link>http://www.touchcentric.com/blog/archives/91</link>
		<comments>http://www.touchcentric.com/blog/archives/91#comments</comments>
		<pubDate>Wed, 04 Nov 2009 14:29:44 +0000</pubDate>
		<dc:creator>Rob Terrell</dc:creator>
				<category><![CDATA[Cocoa Touch]]></category>
		<category><![CDATA[iPhone Development]]></category>

		<guid isPermaLink="false">http://www.touchcentric.com/blog/?p=91</guid>
		<description><![CDATA[I got an email that said: Hi I am a complete newbie to Xcode and programing in Cocoa and I was wondering if I cout get some help or a brief tutorial on implementing the UIApplication+TVOut.m in a small project and I am trying to build please any and all help would greatly be appreciated [...]]]></description>
			<content:encoded><![CDATA[<p>I got an email that said:</p>
<blockquote><p>Hi I am a complete newbie to Xcode and programing in Cocoa and I was wondering if I cout get some help or a brief tutorial on implementing the <a href="http://www.touchcentric.com/blog/archives/3">UIApplication+TVOut.m</a> in a small project and I am trying to build please any and all help would greatly be appreciated</p></blockquote>
<p>Sure, it&#8217;s pretty simple:</p>
<ol>
<li>Add the file &#8220;UIApplication+TVOut.m&#8221; (<a href="http://groups.google.com/group/iphone-developers-nc/web/UIApplication_TVOut.m">download link</a>) to your XCode project. (i.e. Drag the file from the desktop into the project window&#8217;s list of files; check the &#8220;copy files&#8221; option if you want.)</li>
<li>In your project&#8217;s file list, right click on the &#8220;Frameworks&#8221; group item, and pick &#8220;Add existing framework&#8221;. Pick the &#8220;MediaPlayer.framework&#8221; framework.
</li>
<li>In your project&#8217;s file list, there should be an app delegate file. It&#8217;ll be named whatever you called the project, i.e. &#8220;MyTestProjectAppDelegate.m&#8221;. In that file, find the method called &#8220;applicationDidFinishLaunching:&#8221; and add &#8220;[application startTVOut];&#8221; to it, like this:
</li>
</ol>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1">- (void)applicationDidFinishLaunching:(UIApplication *)application {
</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;[application startTVOut];
</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li2">
<div class="de2">}</div>
</li>
</ol>
</div>
<p>That&#8217;s all there is to it.</p>
<p>That will generate a warning upon build, since we didn&#8217;t define &#8220;startTVOut&#8221; in a header anywhere, but it&#8217;s safe to ignore it. (If you&#8217;re the kind of person who always turns on &#8220;treat warnings as errors,&#8221; then there&#8217;s one more step &#8212; also add (and #import) the header file, UIApplication+TVOut.h.)</p>
]]></content:encoded>
			<wfw:commentRss>http://www.touchcentric.com/blog/archives/91/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>App Store Rank for Many Apps</title>
		<link>http://www.touchcentric.com/blog/archives/42</link>
		<comments>http://www.touchcentric.com/blog/archives/42#comments</comments>
		<pubDate>Tue, 26 May 2009 17:57:01 +0000</pubDate>
		<dc:creator>Rob Terrell</dc:creator>
				<category><![CDATA[Cocoa Touch]]></category>
		<category><![CDATA[iPhone Development]]></category>
		<category><![CDATA[app store]]></category>
		<category><![CDATA[iphone]]></category>
		<category><![CDATA[iphonedev]]></category>
		<category><![CDATA[rank]]></category>

		<guid isPermaLink="false">http://www.touchcentric.com/blog/?p=42</guid>
		<description><![CDATA[If you have more than a few apps in the App Store, keeping track of the rank of your apps can become a chore. Currently there are 21 apps in the store that I've developed, and for marketing (and, sure, ego) reasons I'd like to know how they are doing. But not at the expense of a lot of time.

The goal here was to have a single, flexible script to handle all of the possible app ranking cases. And specifically, I wanted a script I could call from AppleScript, which would place the results into a spreadsheet, without lots of text parsing in AppleScript (because text parsing is tedious in AppleScript, although to be fair, everything is tedious in AppleScript.)]]></description>
			<content:encoded><![CDATA[<p>If you have more than a few apps in the App Store, keeping track of the rank of your apps can become a chore. There&#8217;s over a dozen apps in the store that I&#8217;ve developed, and for marketing (and, sure, ego) reasons I&#8217;d like to know how they are doing. But I&#8217;m busy. And laaazy. I wanted a script to do it for me.</p>
<p>The goal was to have a single, flexible script. And specifically, I wanted something I could call from an AppleScript, which would place the results into a spreadsheet without lots of text parsing in AppleScript (because text parsing is tedious in AppleScript, although to be fair, everything is tedious in AppleScript.)</p>
<p>The script I came up with is mostly <a href="http://benchatelain.com/2009/03/05/scraping-app-store-rankings-around-the-world/">Ben Chatelain&#8217;s excellent perl script</a> (again based on the work of Erica Sadun). To better fit my workflow, I modified Ben&#8217;s script in the following ways:</p>
<ul>
<li>Accepts the app ID, category, &#8220;free&#8221; or &#8220;paid&#8221;, and country name as arguments the command line.</li>
<li>Returns just a number (the app&#8217;s rank in the given category), or &#8220;n/a&#8221; if it&#8217;s not ranked in the top 100 for that category/country combination.</li>
<li>Arguments (except app ID) are optional &#8212; the script will assume &#8220;Top Overall&#8221;, &#8220;United States&#8221;, and &#8220;free&#8221;.)</li>
<li>The script will cache the most recent data (and curl is invoked with -z). This way, if you call the script a dozen times in a row, it only pulls the page once, and the rest of the invocations use the cached data (stored in /tmp).</li>
<li>To check the &#8220;Top Apps&#8221; overall rankings, pass in &#8220;Top Overall&#8221; for the category name.</li>
<li>Likewise, to see the ranking for every country in the world, pass in &#8220;world&#8221; for country. The script will check the top apps for every country. In this case, the returned results are a string of &#8220;countryName: rank\n&#8221;, one per country.</li>
</ul>
<p>You call it from the command line like this:</p>
<pre>app_rank.pl appID categoryName free|paid countryName</pre>
<pre>rob$ app_rank.pl 300872165 News free
37</pre>
<p>Or to see the results for the whole world (results edited for blog brevity):</p>
<pre>rob$ app_rank.pl 300872165 News free world
Lebanon: 47
Saudi Arabia: 73
Pakistan: 74
Mexico: 71
Colombia: 61
Hungary: 89
Croatia: 19
...et cetera...</pre>
<p>(How is my english-language not-localized North-Carolina-specific app #19 in Croatia?!?)</p>
<p>Here&#8217;s the AppleScript I use to populate a spreadsheet:</p>
<div id="attachment_43" class="wp-caption alignnone" style="width: 494px"><img class="size-full wp-image-43" title="AppleScript for App Rank" src="http://www.touchcentric.com/blog/wp-content/uploads/2009/05/apprankingscript.jpg" alt="AppleScript to get the app rank and put it into Numbers" width="484" height="457" /><p class="wp-caption-text">AppleScript to get the app rank and put it into Numbers</p></div>
<p>Here&#8217;s the spreadsheet it fills out. The AppleScript pulls the appID to look up from the first cell in each column, and then adds the timestamp and the app&#8217;s rank, so I can add new app IDs as I get them.</p>
<div id="attachment_44" class="wp-caption alignnone" style="width: 587px"><img class="size-full wp-image-44" title="App rank data in Numbers" src="http://www.touchcentric.com/blog/wp-content/uploads/2009/05/apprankingnumbers.jpg" alt="App rank data in Numbers" width="577" height="209" /><p class="wp-caption-text">App rank data in Numbers</p></div>
<p>I scheduled the script to run every few hours (using Ligon) and so I&#8217;m slowly accumulating data. Of course, I can never sleep my laptop or I&#8217;ll miss some data. This concept would probably be best realized as something that runs on a server via cron. Since it&#8217;s a perl script that uses curl instead of some CPAN package it&#8217;s probably easily portable to just about anywhere. It would be simple to move this script to a server and collect the data in some other fashion.</p>
<p>Note that you can also use this same technique to track your app&#8217;s success against competing apps.</p>
<p>The <a onclick="javascript: pageTracker._trackPageview('http://touchcentric.com/clients/app_rank.zip'); " href="http://touchcentric.com/clients/app_rank.zip">script is here</a> (3k zipped perl script).</p>
]]></content:encoded>
			<wfw:commentRss>http://www.touchcentric.com/blog/archives/42/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>iPhone App Video Mirroring</title>
		<link>http://www.touchcentric.com/blog/archives/3</link>
		<comments>http://www.touchcentric.com/blog/archives/3#comments</comments>
		<pubDate>Fri, 15 May 2009 20:51:08 +0000</pubDate>
		<dc:creator>Rob Terrell</dc:creator>
				<category><![CDATA[Cocoa Touch]]></category>
		<category><![CDATA[iPhone Development]]></category>
		<category><![CDATA[cocoa]]></category>
		<category><![CDATA[iphone]]></category>
		<category><![CDATA[iphonesdk]]></category>
		<category><![CDATA[mptvoutwindow]]></category>

		<guid isPermaLink="false">http://www.touchcentric.com/blog/?p=3</guid>
		<description><![CDATA[<p>How can you show your app to a large group? What if you want to show an app to a client, an investor, or at a trade show? Extensive Googling reveals lots of people asking the question, but no good answer. </p>
<p>I'm the organizer of the <a href="http://www.meetup.com/iPhone-Developers/">Raleigh iPhone Developer's Meetup</a> and it's basically impossible for our group's members to demo their apps. The "crowd people around a phone" method breaks at around four people. And our last meetup had 20 people!</p>
<p>Why can't we be like Steve, using our apps on our phone, with the display projected for all to see?</p>
<img class="size-full wp-image-28" title="iPhone App Video Output" src="http://www.touchcentric.com/blog/wp-content/uploads/2009/05/tvout1.jpg" alt="iPhone app displaying its output on a TV" width="500" />
<p>I have a solution, if you're willing to make a special build of your app that's not meant for the app store. No jailbreaking required! Although a willingness to use private methods is.</p>]]></description>
			<content:encoded><![CDATA[<p>How can you show your app to a large group? What if you want to show an app to a client, an investor, or at a trade show? Extensive Googling reveals lots of people asking the question, but no good answer.</p>
<p>I&#8217;m the organizer of the <a href="http://www.meetup.com/iPhone-Developers/">Raleigh iPhone Developer&#8217;s Meetup</a> and it&#8217;s basically impossible for our group&#8217;s members to demo their apps. The &#8220;crowd people around a phone&#8221; method breaks at around four people. And our last meetup had 20 people!</p>
<p>Why can&#8217;t we be like Steve, using our apps on our phone, with the display projected for all to see?</p>
<p>I have a solution, if you&#8217;re willing to make a special build of your app that&#8217;s not meant for the app store. No jailbreaking required! Although a willingness to use private methods is.</p>
<p><b>Update:</b> There&#8217;s a new version for iOS 4.0 here: <a href="http://www.touchcentric.com/blog/archives/123">http://www.touchcentric.com/blog/archives/123</a></p>
<p><strong>How It Works</strong></p>
<p>Inside the iPhone SDK exists a private API for video output. A class called MPTVOutWindow will display whatever it contains via the video output dock connector. (Thanks to Erica Sadun who discovered this class and figured out how to use it!)</p>
<p>I created a UIApplication category (that is to say, an extension to the existing UIApplication class) that uses MPTVOutWindow to mirror the device display onto the TV display. The goal was to make it seamless &#8212; drop the file into a project, recompile, and go. And it&#8217;s really just that easy, with a couple of caveats.</p>
<p>Caveat #1: apps that use this won&#8217;t be allowed into the App Store. That&#8217;s because it uses a couple of private APIs (the MPTVOutWindow class and UIGetScreenImage()). But since you&#8217;re already an iPhone application developer, creating a private build for your own use is normal.</p>
<p><span style="text-decoration: line-through;">Caveat #2: it doesn&#8217;t copy parts of the screen that belong to OpenGL. The class could be extended to do that, if you needed to.</span></p>
<p>Update: actually, it works fine with OpenGL. I demoed an OpenGL game using this at about 20 fps.</p>
<p><strong>Getting Started</strong></p>
<p>First, get a video out cable. It&#8217;s the same cable you&#8217;d use to watch videos from your iPhone on a TV using the dock connector (note: headphone-jack video cables from older iPods do not work). Apple&#8217;s official cable, <a href="http://store.apple.com/us/product/MB128LL/B?fnode=MTY1NDAzOQ&amp;mco=MjE1NTI2OA">Apple Component AV Cable</a>, is $50 for composite video. A similar cable is only $14.18 at <a href="http://www.monoprice.com/products/product.asp?c_id=108&amp;cp_id=10831&amp;cs_id=1083105&amp;p_id=4825&amp;seq=1&amp;format=2">MonoPrice.com</a>. Component cables are also available.<span style="white-space: pre;"> </span>`</p>
<p><strong>How To Use</strong></p>
<p>Add the file UIApplication+TVOut.m to your project. Also, you&#8217;ll need the &#8220;MediaPlayer.framework&#8221; framework, which contains references to the private API we&#8217;re using.</p>
<p>Somewhere in your code you need to call start. Anytime <strong>after </strong>your app&#8217;s primary window has been created, call startTVOut:</p>
<div>
<pre><code>     [[UIApplication] sharedApplication] startTVOut];
</code></pre>
</div>
<p>That&#8217;s about all you need to do. The application category handles everything necessary to mirror the device&#8217;s display. The startTVOut method creates the MPTVoutWindow, adds the necessary subviews, rotates them to match your app&#8217;s orientation, and centers them to appear properly on the TV. A background thread copies the bits from your main display into a view in the MPTVOutWindow. (You can configure the frames per second in the #define at the top of the file. 12 fps works well for me.)</p>
<div id="attachment_28" class="wp-caption alignnone" style="width: 624px"><img class="size-full wp-image-28 " title="iPhone App Video Output" src="http://www.touchcentric.com/blog/wp-content/uploads/2009/05/tvout1.jpg" alt="iPhone app displaying its output on a TV" width="614" height="461" /><p class="wp-caption-text">iPhone app displaying its output on a TV</p></div>
<p>In my test app, I call it from applicationDidFinishLaunching:. One thing to remember about applicationDidFinishLaunching: is that it gets called before the runloop starts, so your primary window isn&#8217;t on screen yet. I call it with a brief delay to give the runloop a chance to get going.</p>
<pre><code>- (void)applicationDidFinishLaunching:(UIApplication*)application {<span>	</span>
// give the runloop a chance to start
    [[UIApplication sharedApplication] performSelector: @selector(startTVOut)
    withObject: nil afterDelay: .1];
}</code></pre>
<p>And actually, you don&#8217;t even need to call startTVOut. The category can start itself. The code includes an override for a private method called reportAppLaunchFinished:. This undocumented method seems to get called after the app has finished loading. (Being undocumented, I&#8217;m not really sure what it does, or what the negative consequences of overriding it has. As far as I can tell, it&#8217;s only used to clean up the Default.png display.) I&#8217;ve commented out that method, since it&#8217;s a bit mysterious. But if you uncomment the method, it will automatically start the TV out display for you. No changes to your code needed!</p>
<p><strong>Mirroring Other Apps?</strong></p>
<p>Since this code runs as part of your app, it stops running when your app stops running. So it&#8217;s not a general purpose full-time video mirroring solution.</p>
<p>However, using other private methods, it&#8217;s possible to launch other apps while your app remains running, thus mirroring whatever app is in front. I&#8217;ve managed to mirror Safari (launched using the private openURL:asPanel: method). I&#8217;m sure you can figure ways to mirror other apps using some of the private app launching methods.</p>
<p><strong>Not for Public Consumption!</strong></p>
<p>Since this uses private methods, it would almost certainly not survive Apple&#8217;s app review process. To avoid getting your app rejected, you should remove this code from your release builds. This is pretty easy &#8212; set the current target to Release and uncheck the checkbox next to the file&#8217;s name. Also, if you call startTVOut manually, you&#8217;ll need to put some #ifdefs around that call, so it won&#8217;t get compiled into release builds.</p>
<p><strong>Great, Where&#8217;s the Code?</strong></p>
<p>Grab the latest code from here:</p>
<p><a onclick="javascript: pageTracker._trackPageview('http://groups.google.com/group/iphone-developers-nc/web/UIApplication_TVOut.m');" href="http://groups.google.com/group/iphone-developers-nc/web/UIApplication_TVOut.m">http://groups.google.com/group/iphone-developers-nc/web/UIApplication_TVOut.m</a></p>
<p>If you have any comments or questions, feel free to email me.</p>
<p>&#8211; Rob</p>
]]></content:encoded>
			<wfw:commentRss>http://www.touchcentric.com/blog/archives/3/feed</wfw:commentRss>
		<slash:comments>21</slash:comments>
		</item>
	</channel>
</rss>
