<?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>Say Goodnight</title>
	<atom:link href="http://www.saygoodnight.com/?feed=rss2" rel="self" type="application/rss+xml" />
	<link>http://www.saygoodnight.com</link>
	<description>A Blog About Coding And Debugging...</description>
	<lastBuildDate>Tue, 20 Apr 2010 18:54:43 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.5</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Inside Out WinDbg Extensions</title>
		<link>http://www.saygoodnight.com/?p=163</link>
		<comments>http://www.saygoodnight.com/?p=163#comments</comments>
		<pubDate>Tue, 20 Apr 2010 18:50:12 +0000</pubDate>
		<dc:creator>pj4533</dc:creator>
				<category><![CDATA[Techniques]]></category>
		<category><![CDATA[debugging]]></category>
		<category><![CDATA[dmpfiles]]></category>
		<category><![CDATA[extension]]></category>
		<category><![CDATA[windbg]]></category>

		<guid isPermaLink="false">http://www.saygoodnight.com/?p=163</guid>
		<description><![CDATA[
This idea started with a question I posted to StackOverflow.com a few weeks ago.
Basically, I have been writing WinDbg extensions the &#8216;normal&#8217; way for a while.  I found them extremely useful for parsing data from large DMP files.  Specifically, I work on a large application, and being able to pull information from data [...]]]></description>
			<content:encoded><![CDATA[<p><img class="alignnone size-medium wp-image-164" title="inside-out-bear" src="http://www.saygoodnight.com/wp-content/uploads/2010/04/inside-out-bear-288x300.png" alt="inside-out-bear" width="288" height="300" /></p>
<p>This idea started with a <a href="http://stackoverflow.com/questions/2573242/how-can-i-create-objects-based-on-dump-file-memory-in-a-windbg-extension">question</a> I posted to StackOverflow.com a few weeks ago.</p>
<p>Basically, I have been writing WinDbg extensions the &#8216;normal&#8217; way for a while.  I found them extremely useful for parsing data from large DMP files.  Specifically, I work on a large application, and being able to pull information from data structures in the minidump (with full memory) is awesome.  I would write code like this:</p>
<p><span id="more-163"></span></p>
<pre class="brush: cpp;">
Address = GetExpression(&quot;somemodule!somesymbol&quot;);
ReadMemory(Address, &amp;addressOfPtr, sizeof(addressOfPtr), &amp;cb);

// get the actual address
ReadMemory(addressOfObj, &amp;addressOfObj, sizeof(addressOfObj), &amp;cb);

ULONG offset;
ULONG addressOfField;

GetFieldOffset(&quot;somemodule!somesymbolclass&quot;, &quot;somefield&quot;, &amp;offset);
ReadMemory(addressOfObj+offset, &amp;addressOfField, sizeof(addressOfField), &amp;cb);
</pre>
<p>That works well, but it becomes very tedious to keep referencing individual fields.  Further, if you want to do anything beyond the most basic of referencing data, it become a very involved process.  I have access to the source code of the program that my DMP files come from, of course.  So it seems like there should be a way to pull out actual objects from the DMP and be able to use them in utility functions of my large applications code base.   An &#8216;inside out&#8217; debugger extension!</p>
<p>It&#8217;s easy to pull the object out of the DMP file with some code like this:</p>
<pre class="brush: cpp;">SomeClass* thisClass = SomeClass::New();
ReadMemory(addressOfObj, &amp;(*thisClass), sizeof(*thisClass), &amp;cb);
</pre>
<p>However, because this is directly from a DMP file, none of the pointers point to anything in my extension!  This includes the virtual function tables.  So, anytime you try to call a function on the &#8216;thisClass&#8217;, it fails with an invalid pointer.  I figured out that I could get around this issue, by skipping the virtual function tables when I read from the dump file, and leaving the vtables in my new object intact.  That way they point to actual addresses, and there is no problem calling functions.   Basically, something like this:</p>
<pre class="brush: cpp;">SomeClass* thisClass = SomeClass::New();
ReadMemory(inRemoteAddress + 0x4, (PVOID) ((ULONG)&amp;(*this) +0x4), sizeof(SomeClass) - 4, &amp;cb)</pre>
<p>Now, we have a &#8216;SomeClass&#8217; object, with valid vtables, and all the data from the dump file!  Unfortunately, any pointers in the class have to be copied in by hand as well, but that is left as an excersize to the reader. <img src='http://www.saygoodnight.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>As I worked with this new idea, I came up with a structure of templates that mimicked the class hierarchy in my application.  Essentially, each real class had a &#8216;remote&#8217; template class that knows about how to pull information from the dump file for that class.  Each template remote class derives from its corresponding remote base class until it gets to ARemote<T> which derives from the formal parameter itself.   For example:</p>
<pre class="brush: cpp;">template &lt;class T&gt;
class ASomeClassRemote : public ARemote&lt;T&gt;
{
protected:
	ASomeClassRemote (ULONG inRemoteAddress)
	: ARemote&lt;T&gt;(inRemoteAddress)
	{
	}

public:
	static	ASomeClassRemote &lt;T&gt;* New(ULONG inRemoteAddress)
	{
		ASomeClassRemote &lt;T&gt;* x = new ASomeClassRemote &lt;T&gt;(inRemoteAddress);

		return (x);
	}

	void SetupObject()
	{
                // call base class setup
		ARemote&lt;T&gt;::SetupObject();

		// read from dump file the stuff that SomeClass knows about
	}
};
</pre>
<p>And the corresponding ARemote<T> would look like this:</p>
<pre class="brush: cpp;">template &lt;class T&gt;
class ARemote : public T
{
protected:
	ARemote(ULONG inRemoteAddress)
	{
		m_Address = inRemoteAddress;
	}

public:
	static	ARemote&lt;T&gt;* New(ULONG inRemoteAddress)
	{
		ARemote&lt;T&gt;* x = new ARemote&lt;T&gt;(inRemoteAddress);

		return (x);
	}

	void SetupObject()
	{
		ULONG cb;

		ULONG sizeOfObject = sizeof(T);

		// check if +0x40 is another vtable pointer, that is the same as offset 0
		ULONG addressOfVTable;
		char bufferVtableOffset0[4096];
		char bufferVtableOffset0x40[4096];
		ULONG64 displacement;
		ReadMemory(m_Address, &amp;addressOfVTable, sizeof(addressOfVTable), &amp;cb);
		GetSymbol(addressOfVTable, bufferVtableOffset0, &amp;displacement);
		ReadMemory(m_Address + 64, &amp;addressOfVTable, sizeof(addressOfVTable), &amp;cb);
		GetSymbol(addressOfVTable, bufferVtableOffset0x40, &amp;displacement);
		if (!strcmp(bufferVtableOffset0, bufferVtableOffset0x40) &amp;&amp; (sizeOfObject &gt; 68) )
		{
			// if so, skip that too
			ReadMemory(m_Address + 4, (PVOID) ((ULONG)&amp;(*this) + 4), 60, &amp;cb);
			ReadMemory(m_Address + 68, (PVOID) ((ULONG)&amp;(*this) + 68), sizeOfObject-68, &amp;cb);
		}
		else
		{
			// if not, read all at once.
			ReadMemory(m_Address + 0x4, (PVOID) ((ULONG)&amp;(*this) +0x4), sizeOfObject-4, &amp;cb);
		}
	}

protected:

	ULONG					m_Address;
};</pre>
<p>Then you would use the templates like this:</p>
<pre class="brush: cpp;">SomeClassRemote&lt;SomeOtherClass&gt;* obj = SomeClassRemote&lt;SomeOtherClass&gt;::New(inRemoteAddress);
obj-&gt;SetupObject();
</pre>
<p>In this case, &#8216;SomeOtherClass&#8217; would be a class that had derived from &#8216;SomeClass&#8217;, and you wanted to make sure that you pulled &#8216;SomeClass&#8217;s stuff out of the dump file.  Maybe you don&#8217;t care about resolving any of the pointers in &#8216;SomeOtherClass&#8217; just yet.  If you did, you could make a new template called &#8216;SomeOtherClass&#8217; that pulled what you needed from the dump file, and it would look like this:</p>
<pre class="brush: cpp;">SomeOtherClassRemote&lt;SomeOtherClass&gt;* obj = SomeOtherClassRemote&lt;SomeOtherClass&gt;::New(inRemoteAddress);
obj-&gt;SetupObject();
</pre>
<p>The great thing about this method is that the resulting objects are actually types that exist in your original codebase, just with the extra &#8216;remote&#8217; stuff added on.  So if you have debugging utility functions that take objects, or perhaps your objects themselves have &#8216;print&#8217; functions, no new code is necessary to print them out!  It becomes a game of making sure the new &#8216;remote&#8217; objects have everything you need in the right place!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.saygoodnight.com/?feed=rss2&amp;p=163</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Win at the Web</title>
		<link>http://www.saygoodnight.com/?p=151</link>
		<comments>http://www.saygoodnight.com/?p=151#comments</comments>
		<pubDate>Mon, 30 Nov 2009 03:55:31 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Applications]]></category>
		<category><![CDATA[News]]></category>

		<guid isPermaLink="false">http://www.saygoodnight.com/?p=151</guid>
		<description><![CDATA[Just went to alpha test on my web based social networking game Win at the Web!
What is WIN AT THE WEB? It is a web game in which points are gained or lost based on the users activity at various social networking sites, such as Twitter and Facebook. Similar to the various social networking ranking [...]]]></description>
			<content:encoded><![CDATA[<p>Just went to alpha test on my web based social networking game <a href="http://www.winattheweb.com/" target="_blank">Win at the Web</a>!</p>
<p>What is WIN AT THE WEB? It is a web game in which points are gained or lost based on the users activity at various social networking sites, such as Twitter and Facebook. Similar to the <a href="http://tweetlevel.edelman.com/">various</a> <a href="http://twitter.grader.com/">social</a> <a href="http://facebook.grader.com/">networking</a> <a href="http://twinfluence.com/">ranking</a> <a href="http://klout.com/">sites</a>, except more competitive, fun and hilarious.  Oh, and with custom badges, achievements and levels.</p>
<p>If you are interested, you can follow along by reading the <a href="http://www.winattheweb.com/blog" target="_blank">development blog</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.saygoodnight.com/?feed=rss2&amp;p=151</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Help define features for ceeFrenzy v2.0!</title>
		<link>http://www.saygoodnight.com/?p=148</link>
		<comments>http://www.saygoodnight.com/?p=148#comments</comments>
		<pubDate>Tue, 03 Nov 2009 19:20:42 +0000</pubDate>
		<dc:creator>pj4533</dc:creator>
				<category><![CDATA[News]]></category>
		<category><![CDATA[iphone]]></category>

		<guid isPermaLink="false">http://www.saygoodnight.com/?p=148</guid>
		<description><![CDATA[
I created a new forum for suggestions on what to implement in v2.0 of ceeFrenzy, the iPhone application for record collectors.
Access the forum here:  Click Here
]]></description>
			<content:encoded><![CDATA[<p><img alt="" src="http://www.saygoodnight.com/uploaded_images/ceeFrenzy_1-727360.jpg" title="ceeFrenzy1" class="alignnone" width="223" height="320" /><img alt="" src="http://www.saygoodnight.com/uploaded_images/ceeFrenzy_2-758993.jpg" title="ceefrenzy2" class="alignnone" width="223" height="320" /></p>
<p>I created a new <a href="http://saygoodnight.uservoice.com/pages/32835-ceefrenzy-v2-0">forum</a> for suggestions on what to implement in v2.0 of <a href="http://www.saygoodnight.com/?page_id=43">ceeFrenzy</a>, the iPhone application for record collectors.</p>
<p>Access the forum here:  <a href="http://saygoodnight.uservoice.com/pages/32835-ceefrenzy-v2-0">Click Here</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.saygoodnight.com/?feed=rss2&amp;p=148</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Wave Robots Part 2 &#8211; Anybody want a peanut?</title>
		<link>http://www.saygoodnight.com/?p=141</link>
		<comments>http://www.saygoodnight.com/?p=141#comments</comments>
		<pubDate>Tue, 13 Oct 2009 16:04:47 +0000</pubDate>
		<dc:creator>pj4533</dc:creator>
				<category><![CDATA[Applications]]></category>
		<category><![CDATA[fezzik]]></category>
		<category><![CDATA[google wave]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[JSON]]></category>
		<category><![CDATA[peanut]]></category>
		<category><![CDATA[princess bride]]></category>
		<category><![CDATA[REST]]></category>

		<guid isPermaLink="false">http://www.saygoodnight.com/?p=141</guid>
		<description><![CDATA[
Wrote another wave robot, this are strangely addicting to write.    Its weird because at this level Wave is really just a glorified IRC chatroom.  They have been doing bots in rooms for decades.   But I don&#8217;t know, something is really cool about going back to the purity of that [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.saygoodnight.com/wp-content/uploads/2009/10/Fezzik.JPG" alt="Fezzik" title="Fezzik" width="250" height="188" class="alignnone size-full wp-image-142" /></p>
<p>Wrote another wave robot, this are strangely addicting to write.    Its weird because at this level Wave is really just a glorified IRC chatroom.  They have been doing bots in rooms for decades.   But I don&#8217;t know, something is really cool about going back to the purity of that model, while using future-looking technology like Wave.   I am on board 100%.</p>
<p>Anyway,  FEZZIKYBOT!     </p>
<p><span id="more-141"></span></p>
<p><img src="http://www.saygoodnight.com/wp-content/uploads/2009/10/fezziky.png" alt="fezziky" title="fezziky" width="538" height="451" class="alignnone size-full wp-image-143" /></p>
<p>I did a search and found <a href="http://www.azarask.in/blog/post/restful-rhyme-dictionary-web-service/">this cool service</a> that <a href="http://www.azarask.in/blog/">Aza Raskin</a> made.   It is a simple RESTful service (he even included JSONP!) that takes a term and returns JSON output of words that it rhymes with!   Super simple!   So I hooked into that service from my Fezzikybot.   The bot will attempt to rhyme the last word of the previous sentences blip.   It chooses a random rhyme, ignores punctutation, and then puts it in a randomly chosen canned response.  </p>
<p>Silly.  Simple.  Dumb.   INCREDIBLY entertaining.   </p>
<p>If you wanna play with Fezziky, just add him to your wave:</p>
<p>fezzikybot@appspot.com</p>
]]></content:encoded>
			<wfw:commentRss>http://www.saygoodnight.com/?feed=rss2&amp;p=141</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Google Wave Robots &#8211; Dude Approved.</title>
		<link>http://www.saygoodnight.com/?p=135</link>
		<comments>http://www.saygoodnight.com/?p=135#comments</comments>
		<pubDate>Tue, 13 Oct 2009 02:15:25 +0000</pubDate>
		<dc:creator>pj4533</dc:creator>
				<category><![CDATA[Applications]]></category>
		<category><![CDATA[big lebowski]]></category>
		<category><![CDATA[google wave]]></category>
		<category><![CDATA[robots]]></category>
		<category><![CDATA[the dude]]></category>

		<guid isPermaLink="false">http://www.saygoodnight.com/?p=135</guid>
		<description><![CDATA[
Thaaaats right dude, google wave is here.  I got my invite last week, and tonight was the first night I really got to play with it so I decided to write a little wave robot.  I had no idea how easy/difficult it would be so I made something simple.    
Enter [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.saygoodnight.com/wp-content/uploads/2009/10/lebowskiman.jpg" alt="lebowskiman" title="lebowskiman" width="595" height="325" class="alignnone size-full wp-image-136" /></p>
<p>Thaaaats right dude, google wave is here.  I got my invite last week, and tonight was the first night I really got to play with it so I decided to write a little wave robot.  I had no idea how easy/difficult it would be so I made something simple.    </p>
<p>Enter THE DUDE-Y!</p>
<p><span id="more-135"></span><br />
Google Wave Robots have so far started a naming convention that includes a cutesy name ending in a -y.   Spelly.   Trippy.   Tweety.   So I felt it was only natural that I create The Dude-y.   The Dude-y simply notices keywords and responds to them with some canned responses.   Which, btw, are all Big Lebowski quotes, which of course makes those boring waves much more freaking hilarious.    I am sure Wave will be the life changing experience that we all hope it will be, when people are on it, but for now&#8230;..frankly its kinda boring.</p>
<p><img src="http://www.saygoodnight.com/wp-content/uploads/2009/10/waveshot.jpg" alt="waveshot" title="waveshot" width="483" height="385" class="alignnone size-full wp-image-139" /></p>
<p>As for the technical stuff, writing a wave robot is pretty simple.   I have been hacking on GWT programs for a while now, and writing a robot nearly identical.  In fact, for someone already using the Google App Engine for their GWT apps, writing a robot is dead easy. </p>
<p>I followed <a href="http://code.google.com/apis/wave/extensions/robots/java-tutorial.html">this tutorial</a>, which basically says blahblahblah, extend AbstractRobotServlet, blahblahblah, listen to processEvents blahblahblah.  The only part I found even slightly difficult was figuring out how to get an icon for my robot.   Using the java client library, you have to make another servlet extended from ProfileServlet which responds to getRobotAvatarUrl, and returns the url of your icon (100&#215;100 png) file.   Then just put that file inside your war and deploy it.   OF COURSE, don&#8217;t forget to add the new servlet to your web.xml!    Just check out any of the examples in the <a href="http://wave-samples-gallery.appspot.com/">wave robot example gallery</a> for how to do this. </p>
<p>The last thing to be aware of is versioning.  As I responded to the BLIP_SUBMITTED message apparently it had my old version of the robot cached in wave.   So I needed to increment the version number in the capabilities.xml file.   In fact, I think it even didn&#8217;t work the first time I incremented it, but after playing with it a bit, it eventually was updated.  Not sure if there is an issue there, or if it was my own dam fault.</p>
<p>Anyway, you can play with THE DUDE-Y by adding his email to your wave:  </p>
<p>thedude-y@appspot.com</p>
<p>Btw, nice marmot.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.saygoodnight.com/?feed=rss2&amp;p=135</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Gears and War</title>
		<link>http://www.saygoodnight.com/?p=104</link>
		<comments>http://www.saygoodnight.com/?p=104#comments</comments>
		<pubDate>Sat, 03 Oct 2009 21:40:59 +0000</pubDate>
		<dc:creator>pj4533</dc:creator>
				<category><![CDATA[Techniques]]></category>
		<category><![CDATA[Google Gears]]></category>
		<category><![CDATA[GWT]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[JSON]]></category>

		<guid isPermaLink="false">http://www.saygoodnight.com/?p=104</guid>
		<description><![CDATA[
I have been doing quite a bit of Google Web Toolkit programming lately.  I thought I would start sharing a few of the troubles and fixes along the way.   Most recently I have been attempting to get Google Gears working for offline access with my GWT 1.7 web application.
On the surface, this isn&#8217;t too difficult.   [...]]]></description>
			<content:encoded><![CDATA[<p><img class="alignnone size-full wp-image-105" title="gearsofwar" src="http://www.saygoodnight.com/wp-content/uploads/2009/10/gearsofwar.jpg" alt="gearsofwar" width="320" height="320" /></p>
<p>I have been doing quite a bit of Google Web Toolkit programming lately.  I thought I would start sharing a few of the troubles and fixes along the way.   Most recently I have been attempting to get Google Gears working for offline access with my GWT 1.7 web application.</p>
<p><span id="more-104"></span>On the surface, this isn&#8217;t too difficult.   The Gears API for GWT includes a handy Offline package for automatically generate the necessary JSON manifest file to make the LocalServer happy.   There are plenty examples of how to do that on the Gears website but, just in case its something like this:</p>
<pre class="brush: java;">
	private void createManagedResourceStore() {
		try {
			final ManagedResourceStore managedResourceStore = Offline.getManagedResourceStore();

			new Timer() {
				String transferringData = &amp;amp;quot;Transferring data&amp;amp;quot;;

				@Override
				public void run() {
					switch (managedResourceStore.getUpdateStatus()) {
					case ManagedResourceStore.UPDATE_OK:
						display.getOnlineStatusLabel().setText(&amp;amp;quot;Status: Offline&amp;amp;quot;);
						break;
					case ManagedResourceStore.UPDATE_CHECKING:
					case ManagedResourceStore.UPDATE_DOWNLOADING:
						transferringData += &amp;amp;quot;.&amp;amp;quot;;
						display.getOnlineStatusLabel().setText(transferringData);
						schedule(500);
						break;
					case ManagedResourceStore.UPDATE_FAILED:
						display.getOnlineStatusLabel().setText(&amp;amp;quot;Status: FAILED&amp;amp;quot;);
						break;
					}
				}
			}.schedule(500);

		} catch (GearsException e) {
			display.getOnlineStatusLabel().setText(&amp;amp;quot;&amp;amp;quot;);
			Window.alert(e.getMessage());
		}
	}
</pre>
<p>That works great for everything inside your module.  However, as of GWT 1.6 projects are by default using a War directory structure.   This puts your default app .html/.css files (at least) one directory level higher than the module itself.  Further, normally you would add any other resources to that directory as well (such as image directories and whatnot).  All of those files are not gathered by the Offline automatic manifest generation.   And as such, will not be caught by the Gears plugin.   Further, since that html file serves your whole page&#8230;.it kinda keeps your whole app from working offline.  Slightly important that they be caught, in other words.</p>
<p>This was discussed on the google group for the Gears API, and I assume they are working on a fix.  But I am by nature impatient and want it to work noooooooooow.   </p>
<p>The easiest way I found was to let the Offline module create your manifest file, then go in and add the extra files to it that you know will need to be cached.   Its a manual step, but at least it gets it working.  The manifest is located in your module directory (with the other compiled output), in a file called:   modulename.nocache.manifest</p>
<p>I just brought that sucker up in vi and added a few files to the end like so (this is only the end of the file obviously):</p>
<p><code>{ "url" : "gwt/standard/standard_rtl.css" },<br />
{ "url" : "hosted.html" },<br />
{ "url" : "mymodule.nocache.js" },<br />
{ "url" : "mymodule.nocache.js?compiled" },<br />
{ "url" : "../Mymodule.css" },<br />
{ "url" : "../Mymodule.html" },<br />
{ "url" : "../images/someimage.jpg" },<br />
{ "url" : "../" }<br />
]<br />
}<br />
</code>  </p>
<p>So as you can see I just reference back one directory to pick up the other files the Offline package missed.   Note I also included the base directory.  This was important because I was using the greeting-file mechanism in my web.xml to by default tell the server to give me the Mymodule.html file.   So you need to be sure to cache that if you want your users to be able to go to that directory without specifying the actual html file itself.   Thats it!  Just save that file, and clear your cache.   Then when you call the above function it should correctly cache the files you added.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.saygoodnight.com/?feed=rss2&amp;p=104</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Pulling metadata out of enhanced podcasts (.m4a) and into XML</title>
		<link>http://www.saygoodnight.com/?p=100</link>
		<comments>http://www.saygoodnight.com/?p=100#comments</comments>
		<pubDate>Thu, 13 Aug 2009 21:26:55 +0000</pubDate>
		<dc:creator>pj4533</dc:creator>
				<category><![CDATA[Techniques]]></category>
		<category><![CDATA[apple]]></category>
		<category><![CDATA[audio]]></category>
		<category><![CDATA[cocoa]]></category>
		<category><![CDATA[mac]]></category>
		<category><![CDATA[opensource]]></category>
		<category><![CDATA[osx]]></category>
		<category><![CDATA[projects]]></category>
		<category><![CDATA[quicktime]]></category>
		<category><![CDATA[utility]]></category>

		<guid isPermaLink="false">http://www.saygoodnight.com/?p=100</guid>
		<description><![CDATA[
For my radio show iPhone application project, I wanted to use the metadata contained in my enhanced podcast files.  Including:

chapter information (artist/song)
chapter start time
chapter image

Once I had this information I wanted to store it in XML on my server so I could access it whenever I wanted (from the iPhone application).

I accomplished this by [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://174.143.169.246/wp-content/uploads/2009/08/puzzle_pieces300x199.jpg"><img class="alignnone size-full wp-image-99" title="puzzle_pieces300x199" src="http://174.143.169.246/wp-content/uploads/2009/08/puzzle_pieces300x199.jpg" alt="puzzle_pieces300x199" width="300" height="199" /></a></p>
<p>For my radio show iPhone application project, I wanted to use the metadata contained in my enhanced podcast files.  Including:</p>
<ul>
<li>chapter information (artist/song)</li>
<li>chapter start time</li>
<li>chapter image</li>
</ul>
<p>Once I had this information I wanted to store it in XML on my server so I could access it whenever I wanted (from the iPhone application).</p>
<p><span id="more-100"></span><br />
I accomplished this by writing a simple little command line utility that parses an enhanced podcast .m4a file with QTKit and pulls out the metadata, and adds it to an XML file.   Once you track down all the details, it is fairly simple, but I figured maybe it would help people to see all the information in one place.    Obviously my code is tailored for my radio show example, but I think it is fairly clear how to translate it for other uses.</p>
<p>Here is the most interesting function of my project:</p>
<pre class="brush: cpp;">
void addFileToTree( NSXMLElement* inRoot, NSString* inFileName )
{
	QTMovie* movie = [QTMovie movieWithFile:inFileName error:nil];

	NSInteger numChapters = [movie chapterCount];
	NSLog(@&amp;amp;quot;Number of Chapters: %d&amp;amp;quot;, numChapters);

	NSXMLElement *showNode = [NSXMLNode elementWithName:@&amp;amp;quot;Show&amp;amp;quot;];
	[inRoot addChild:showNode];

	NSString* baseShowName = [inFileName stringByReplacingOccurrencesOfString:@&amp;amp;quot;.m4a&amp;amp;quot; withString:@&amp;amp;quot;&amp;amp;quot;];

	NSString* mp3Filename = [inFileName stringByReplacingOccurrencesOfString:@&amp;amp;quot;.m4a&amp;amp;quot; withString:@&amp;amp;quot;.mp3&amp;amp;quot;];
	[showNode addChild:[NSXMLNode elementWithName:@&amp;amp;quot;Filename&amp;amp;quot; stringValue:mp3Filename  ] ];

	NSDictionary* movieAttrs = [movie movieAttributes];
	NSString* movieDisplayName = [movieAttrs objectForKey:@&amp;amp;quot;QTMovieDisplayNameAttribute&amp;amp;quot;];
	[showNode addChild:[NSXMLNode elementWithName:@&amp;amp;quot;EpisodeName&amp;amp;quot; stringValue:movieDisplayName  ] ];

	NSDate* movieCreationDate = [movieAttrs objectForKey:@&amp;amp;quot;QTMovieCreationTimeAttribute&amp;amp;quot;];
	[showNode addChild:[NSXMLNode elementWithName:@&amp;amp;quot;Date&amp;amp;quot; stringValue:[movieCreationDate description]  ] ];

	NSArray* chapterArray = [movie chapters];
	NSInteger curChap = 0;
	for ( NSDictionary* chapDict in chapterArray )
	{
		curChap++;

		NSXMLElement *songNode = [NSXMLNode elementWithName:@&amp;amp;quot;Song&amp;amp;quot;];
		[showNode addChild:songNode];

		NSValue* startTimeValue = [chapDict objectForKey:@&amp;amp;quot;QTMovieChapterStartTime&amp;amp;quot;];

		QTTime startTime;
		[startTimeValue getValue:&amp;amp;amp;startTime];

		NSInteger offsetInSeconds = startTime.timeValue / startTime.timeScale;

		/////////////////////
		NSArray* trackArray = [movie tracksOfMediaType:QTMediaTypeText];

		for (int i=0; i &amp;amp;lt; [trackArray count]; i++)
		{
			QTTrack* thisTrack = [trackArray objectAtIndex:i];
			[thisTrack setEnabled:NO];
		}

		NSDictionary *imageAttrs = [NSDictionary dictionaryWithObjectsAndKeys:
									QTMovieFrameImageTypeNSImage, QTMovieFrameImageType,
									[NSNumber numberWithBool:YES], QTMovieFrameImageHighQuality,
									[NSValue valueWithSize:NSMakeSize(320, 320)], QTMovieFrameImageSize, nil];

		NSImage* chapImage = [movie frameImageAtTime:startTime withAttributes:imageAttrs error:nil];

 		// write image to disk
		NSString* filenameString = [NSString stringWithFormat:@&amp;amp;quot;%@_%d.jpg&amp;amp;quot;, baseShowName, curChap];

		NSArray *representations;
		NSData *bitmapData;

		representations = [chapImage representations];

		// Specify that we want to save the file as a JPG
		bitmapData = [NSBitmapImageRep representationOfImageRepsInArray:representations
															  usingType:NSJPEGFileType
															 properties:[NSDictionary dictionaryWithObject:[NSDecimalNumber numberWithFloat:0.6]
																									forKey:NSImageCompressionFactor]];

		[bitmapData writeToFile:filenameString  atomically:YES];

		/////////////////////

		[songNode addChild:[NSXMLNode elementWithName:@&amp;amp;quot;Chapter&amp;amp;quot; stringValue:[NSString stringWithFormat:@&amp;amp;quot;%d&amp;amp;quot;, curChap] ] ];

		NSString* chapterName = [chapDict objectForKey:@&amp;amp;quot;QTMovieChapterName&amp;amp;quot;];
		NSArray *songArray = [chapterName componentsSeparatedByString:@&amp;amp;quot; - &amp;amp;quot;];

		if ( [songArray count] == 1 )
		{
			[songNode addChild:[NSXMLNode elementWithName:@&amp;amp;quot;Artist&amp;amp;quot; stringValue:@&amp;amp;quot;PJ Gray&amp;amp;quot;  ] ];
			[songNode addChild:[NSXMLNode elementWithName:@&amp;amp;quot;Title&amp;amp;quot; stringValue:[songArray objectAtIndex:0]  ] ];
		}
		else
		{
			[songNode addChild:[NSXMLNode elementWithName:@&amp;amp;quot;Artist&amp;amp;quot; stringValue:[songArray objectAtIndex:0]  ] ];
			[songNode addChild:[NSXMLNode elementWithName:@&amp;amp;quot;Title&amp;amp;quot; stringValue: [songArray objectAtIndex:1] ] ];
		}
		[songNode addChild:[NSXMLNode elementWithName:@&amp;amp;quot;StartOffset&amp;amp;quot; stringValue: [NSString stringWithFormat:@&amp;amp;quot;%d&amp;amp;quot;, offsetInSeconds] ] ];

		NSValue* endTimeValue;
		if ( curChap &amp;amp;lt;= [chapterArray count]-1 )
		{
			NSDictionary* nextChap = [chapterArray objectAtIndex:curChap];
			endTimeValue = [nextChap objectForKey:@&amp;amp;quot;QTMovieChapterStartTime&amp;amp;quot;];
		}
		else
			endTimeValue = [movieAttrs objectForKey:@&amp;amp;quot;QTMovieDurationAttribute&amp;amp;quot;];

		QTTime endTime;
		[endTimeValue getValue:&amp;amp;amp;endTime];
		NSInteger endtimeInSeconds = endTime.timeValue / endTime.timeScale;
		[songNode addChild:[NSXMLNode elementWithName:@&amp;amp;quot;EndOffset&amp;amp;quot; stringValue:[NSString stringWithFormat:@&amp;amp;quot;%d&amp;amp;quot;, endtimeInSeconds] ] ];

		[songNode addChild:[NSXMLNode elementWithName:@&amp;amp;quot;Image&amp;amp;quot; stringValue:filenameString ] ];

		NSLog(@&amp;amp;quot;%@&amp;amp;quot;,  [chapDict objectForKey:@&amp;amp;quot;QTMovieChapterName&amp;amp;quot;]);
	}

}
</pre>
<p>That is a huge function, I know.  However, it really does simple tasks.  It is using QTKit to take the metadata out of the m4a file, including both offset times, and image information.  The most interesting bit is probably the exact code to write the image information out as a jpg, as that take a bit more than what the docs describe.   If you have any questions or comments, please let me know!</p>
<p>Download source: <a href='http://174.143.169.246/wp-content/uploads/2009/08/m4a2xml.zip'>m4a2xml</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.saygoodnight.com/?feed=rss2&amp;p=100</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Prebuffering iPhone Audio Streams For Gapless Playback</title>
		<link>http://www.saygoodnight.com/?p=77</link>
		<comments>http://www.saygoodnight.com/?p=77#comments</comments>
		<pubDate>Mon, 10 Aug 2009 21:10:27 +0000</pubDate>
		<dc:creator>pj4533</dc:creator>
				<category><![CDATA[Techniques]]></category>
		<category><![CDATA[apple]]></category>
		<category><![CDATA[audio]]></category>
		<category><![CDATA[iphone]]></category>
		<category><![CDATA[ipod touch]]></category>
		<category><![CDATA[mac]]></category>
		<category><![CDATA[opensource]]></category>
		<category><![CDATA[osx]]></category>
		<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://www.saygoodnight.com/?p=77</guid>
		<description><![CDATA[
I have been working on a project that requires me to stream audio from a webserver to the iPhone, starting at an offset in an mp3 file.   I showed how to modify Matt Gallagers awesome AudioStreamer code in a previous post.  What I find myself doing quite a bit is stopping play [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://174.143.169.246/wp-content/uploads/2009/08/prebuff.jpg"><img class="alignnone size-full wp-image-83" title="prebuff" src="http://174.143.169.246/wp-content/uploads/2009/08/prebuff.jpg" alt="prebuff" width="497" height="321" /></a></p>
<p>I have been working on a project that requires me to stream audio from a webserver to the iPhone, starting at an offset in an mp3 file.   I showed how to modify Matt Gallagers awesome AudioStreamer code in a previous post.  What I find myself doing quite a bit is stopping play on one file and starting play on another.   Obviously you want the gap between tracks to be as minimal as possible.</p>
<p>The easy way to do this would be just to keep track of duration in a &#8217;switcher&#8217; object, <span id="more-77"></span> when the progress of the &#8216;A&#8217; streamer reaches the duration, start playing the &#8216;B&#8217; streamer.   This can be managed in the switcher object.   However, it isn&#8217;t quite optimal because the cost of starting play on a new streamer is paid after the first streamer has finished.   What would be best is if you could get the &#8216;B&#8217; streamer all ready to play, so as soon the &#8216;A&#8217; streamer finished you could seamlessly start hearing the audio from the &#8216;B&#8217; streamer.</p>
<p>Unfortunately, the iPhone hardware as it exists today only allows for one mp3 audio queue to be played or &#8216;primed&#8217; at a time.   The priming of the audio queue is what is desired here, as it will decompress the buffers getting them set to be output.   (Apparently there are CPU concerns when it comes to decompression)</p>
<blockquote><p>How do I play multiple sounds simultaneously?</p>
<p>Use the interfaces in Audio Queue Services (AudioToolbox/AudioQueue.h). Create one audio queue object for each sound that you want to play. Then specify simultaneous start times for the first audio buffer in each audio queue, using the AudioQueueEnqueueBufferWithParameters function.</p>
<p>The following limitations pertain for simultaneous sounds in iPhone OS, depending on the audio data format:</p>
<p>AAC, MP3, and ALAC (Apple Lossless) audio: no simultaneous playback; one sound at a time.</p>
<p>Linear PCM and IMA/ADPCM (IMA4 audio): You can play multiple linear PCM or IMA4 format sounds simultaneously without CPU resource concerns.</p></blockquote>
<p>However, this is not all that happens in the AudioStreamer object.  We also have to read the bytes from the network and get them in our array, ready to be processed by the audio queue.   This work can be done while the other streamer is finishing, so that while playback won&#8217;t be immediate when switching streamers, it will be minimized.</p>
<p>So I will make a class called AudioStreamSwitcher that will wrap 2 AudioStreamers:</p>
<pre class="brush: cpp;">
#import &amp;amp;lt;Foundation/Foundation.h&amp;amp;gt;

#import &amp;amp;quot;AudioStreamer.h&amp;amp;quot;

@interface AudioStreamSwitcher : NSObject
{
	AudioStreamer* streamerA;
	AudioStreamer* streamerB;
	AudioStreamer* currentStreamer;

	BOOL streamerAIsCurrent;

	UInt32 currentDuration;

	NSTimer *checkForEndTimer;

	BOOL sentCueNotification;

}

@property (readonly) double progress;
@property (readonly) UInt32 bitRate;

- (void) startForDurationInSecs:(UInt32) inDurationSecs;
- (void) startWithOffsetInSecs:(UInt32)offsetInSecs forDurationInSecs:(UInt32) inDurationSecs;
- (void) startPlayingURLWhenFinished:(NSURL*)inURL withOffsetInSecs:(UInt32) offsetInSecs forDurationInSecs:(UInt32) inDurationSecs;
- (void) stop;

- (void)checkForEnd:(NSTimer *)aNotification;

- (BOOL)isPlaying;
- (BOOL)isPaused;
- (BOOL)isWaiting;
- (BOOL)isIdle;

@end
</pre>
<p>Normal usage will be:<br />
- start playing<br />
- right before finish, send notification we are about to finish<br />
- observer responds by calling startPlayingURLWhenFinished<br />
- we get the opposite streamer ready to go as much as possible<br />
- at finish switch and start playing the opposite streamer</p>
<p>Also in the code are some fixes for problems with my earlier post.   I put in a workaround for calculating the byte offset based on an offset in seconds.  You need the bitrate from the file, so rather than blocking on waiting for the bitrate to get set, I have the AudioStreamer tear down the ReadStream object once it has the bitrate based on reading the first packet from the file.  Then it does the calculation to get the correct byte offset, and reopens the ReadStream at the right place.  This is all done with one AudioFileStream.</p>
<p>Further, if any errors occur when attempting to create the AudioQueue, it is likely due to the offset putting us in a weird place in the file.  I have found the best (and easiest) remedy is to just back up and try again.   Rather than blocking on waiting to start play, I send a notification that an error occured, and the AudioStreamer is the only observer, and it knows to back up 1000 bytes and try again.</p>
<p>While this method is good&#8230;(fantastic on the simulator), it is only soso on the iPhone hardware.  We always get the delay of waiting for starting of the second queue&#8230;unless we could feed one queue with 2 different files! Since we control the files, there is no reason to have a 1 to 1 relationship between files and queues.  I started implementing this method, and I have no doubt it will work.   However, you can&#8217;t change the format of an AudioQueue, so unless your files are all the same format it won&#8217;t work.  My files might be different, so I gave up on this method.</p>
<p>Anyway, hope this discussion &#038; code is helpful for some people.  I definitely learned alot while hacking away at this code.   I am sure I&#8217;ll make more changes as I go&#8230; thats the fun part!</p>
<p>Here is the code for the <a href='http://174.143.169.246/wp-content/uploads/2009/08/AudioStreamer_prebufferExample.zip'>AudioStreamSwitcher example</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.saygoodnight.com/?feed=rss2&amp;p=77</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>ceeFrenzy: APPROVED!</title>
		<link>http://www.saygoodnight.com/?p=71</link>
		<comments>http://www.saygoodnight.com/?p=71#comments</comments>
		<pubDate>Fri, 07 Aug 2009 15:21:50 +0000</pubDate>
		<dc:creator>pj4533</dc:creator>
				<category><![CDATA[Applications]]></category>
		<category><![CDATA[cocoa]]></category>
		<category><![CDATA[iphone]]></category>
		<category><![CDATA[ipod touch]]></category>
		<category><![CDATA[mac]]></category>
		<category><![CDATA[say goodnight software]]></category>

		<guid isPermaLink="false">http://www.saygoodnight.com/?p=71</guid>
		<description><![CDATA[
My first iPhone application got approved!    Details are on the Say Goodnight Software page.

Now on to my FREE Galactic Fractures Streaming Radio application!
]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.saygoodnight.com/uploaded_images/ceeFrenzy_1-727360.jpg" border="0" alt="icon" /><img src="http://www.saygoodnight.com/uploaded_images/ceeFrenzy_2-758993.jpg" border="0" alt="icon" /></p>
<p>My first iPhone application got approved!    Details are on the <a href="http://www.saygoodnight.com/?page_id=43">Say Goodnight Software</a> page.<br />
<span id="more-71"></span><br />
Now on to my FREE <a href="http://www.galacticfractures.com/">Galactic Fractures</a> Streaming Radio application!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.saygoodnight.com/?feed=rss2&amp;p=71</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>A Simple Quick Reusable XML Parser For The iPhone</title>
		<link>http://www.saygoodnight.com/?p=50</link>
		<comments>http://www.saygoodnight.com/?p=50#comments</comments>
		<pubDate>Wed, 05 Aug 2009 14:14:09 +0000</pubDate>
		<dc:creator>pj4533</dc:creator>
				<category><![CDATA[Techniques]]></category>
		<category><![CDATA[apple]]></category>
		<category><![CDATA[iphone]]></category>
		<category><![CDATA[ipod touch]]></category>
		<category><![CDATA[mac]]></category>
		<category><![CDATA[opensource]]></category>
		<category><![CDATA[osx]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[xml]]></category>

		<guid isPermaLink="false">http://www.saygoodnight.com/?p=50</guid>
		<description><![CDATA[
I found that I was needing an XML parser for nearly every iPhone application I was writing. Once you figure out the streaming nature of NSXMLParser, it really isn&#8217;t very difficult to use. However, since I was always having the didStartElement/foundCharacters/didEndElement functions in each application, I really wanted to break them out into a reusable [...]]]></description>
			<content:encoded><![CDATA[<p style="clear: both"><a href="http://www.xml.org/"><img class="alignnone size-full wp-image-59" title="logo" src="http://www.saygoodnight.com/blog/wp-content/logo.jpg" alt="logo" /></a></p>
<p style="clear: both">I found that I was needing an XML parser for nearly every iPhone application I was writing. Once you figure out the streaming nature of NSXMLParser, it really isn&#8217;t very difficult to use. However, since I was always having the didStartElement/foundCharacters/didEndElement functions in each application, I really wanted to break them out into a reusable class.</p>
<p style="clear: both">I found that most my XML implementations were VERY simple, as I was just using it for data storage and transfer. However, of course, each XML is different so my class has to handle that properly.</p>
<p style="clear: both">After making several iterations, I settled on using an NSArray for the root of the XML file. Each node is a NSDictionary with three object/key pairs:</p>
<p style="clear: both">
<p><span id="more-50"></span></p>
<ul style="clear: both">
<li>element &#8211; This is the element name</li>
<li>data &#8211; This is the string data in the element</li>
<li>children &#8211; This is an NSArray of the children</li>
</ul>
<p>So a basic usage would be to let it parse your XML, then walk thru the array you get back filling up your internal data structures with the information you need. You can dump the XML to the debug console with simple code like this:</p>
<p style="clear: both">
<pre class="brush: cpp;">
NSURL *URL=[[NSURL alloc] initWithString:@&amp;quot;http://www.w3schools.com/XML/cd_catalog.xml&amp;quot;];
SimpleXMLParser* thisParser = [[SimpleXMLParser alloc] initWithURL:URL];
[URL release];
[thisParser parse];
[thisParser dumpRoot];
</pre>
</pre>
<p>The dumpRoot function is implemented as two functions as so:</p>
<pre class="brush: cpp;">

- (void) dumpArrayRecursive: (NSArray*) inArray parentElement:(NSString*)inParent
{
 for (int i=0;i&amp;lt;[inArray count];i++)
 {
 NSDictionary* thisDict = [inArray objectAtIndex:i];
 NSLog(@&amp;quot;Element: %@    Data:  %@    Parent:  %@&amp;quot;, [thisDict objectForKey:@&amp;quot;element&amp;quot;], [thisDict objectForKey:@&amp;quot;data&amp;quot;], inParent);
 [self dumpArrayRecursive:[thisDict objectForKey:@&amp;quot;children&amp;quot;] parentElement:[thisDict objectForKey:@&amp;quot;element&amp;quot;] ];
 }
}

- (void) dumpRoot
{
 [self dumpArrayRecursive:theMainStack parentElement:@&amp;quot;Root&amp;quot;];
}
</pre>
<p style="clear: both">I am sure many improvements could be made, so feel free to be vocal in the comments section. I am fairly new to Objective-C and don't feel I have a real grasp of memory management. I am SURE I am leaking quite a bit. I figure I should be walking through the root array recursively releasing each dictionary, and each array on each dictionary. But I havn't implemented that yet...so... beware of that. Or maybe I could use some internal garbage collection to do it for me? I don't know really...any suggestions would be fantastic.</p>
<p style="clear: both">At any rate, this is a good example of a simple XML parser. No it isn't going to work in all cases, but it is reusable, so it beats re-implementing the streaming parser each time!</p>
<p style="clear: both">Here is the code:   <a href="http://www.saygoodnight.com/SimpleXMLTest.zip">SimpleXMLTest.zip</a></p>
<p style="clear: both">
<p><br class="final-break" style="clear: both" /></p>
]]></content:encoded>
			<wfw:commentRss>http://www.saygoodnight.com/?feed=rss2&amp;p=50</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>
