<?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>Jesper Särnesjö</title>
	<atom:link href="http://jesper.sarnesjo.org/blog/feed/" rel="self" type="application/rss+xml" />
	<link>http://jesper.sarnesjo.org/blog</link>
	<description>Just another WordPress weblog</description>
	<lastBuildDate>Tue, 05 May 2009 10:58:34 +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>pbcopy and pbpaste</title>
		<link>http://jesper.sarnesjo.org/blog/pbcopy-and-pbpaste/</link>
		<comments>http://jesper.sarnesjo.org/blog/pbcopy-and-pbpaste/#comments</comments>
		<pubDate>Tue, 05 May 2009 09:31:44 +0000</pubDate>
		<dc:creator>Jesper Särnesjö</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[macosx]]></category>
		<category><![CDATA[pbcopy]]></category>
		<category><![CDATA[pbpaste]]></category>

		<guid isPermaLink="false">http://jesper.sarnesjo.org/blog/?p=22</guid>
		<description><![CDATA[Here&#8217;s a quick tip about two handy command line utilities for Mac OS X: pbcopy
and pbpaste.

pbcopy is used to capture output from any command line program and place it into
the pasteboard. An example:

$ cat hello.txt 
hello world!
$ cat hello.txt &#124; pbcopy 


We can now paste the output from cat in the regular cmd-v fashion mostly
anywhere.

pbpaste, [...]]]></description>
			<content:encoded><![CDATA[<p>Here&#8217;s a quick tip about two handy command line utilities for Mac OS X: <code>pbcopy</code>
and <code>pbpaste</code>.</p>

<p><code>pbcopy</code> is used to capture output from any command line program and place it into
the pasteboard. An example:</p>

<pre><code>$ cat hello.txt 
hello world!
$ cat hello.txt | pbcopy 
</code></pre>

<p>We can now paste the output from <code>cat</code> in the regular cmd-v fashion mostly
anywhere.</p>

<p><code>pbpaste</code>, on the other hand, outputs the contents of the pasteboard. An example:</p>

<pre><code>$ pbpaste 
hello world!
</code></pre>

<p>In this way, <code>pbcopy</code> and <code>pbpaste</code> can be used to move data between command line
programs and GUI applications.</p>

<p><code>pbcopy</code> and <code>pbpaste</code> have a few tricks up their proverbial sleeves. You can read
all about them in their man page, which is available <a href="http://developer.apple.com/documentation/Darwin/Reference/ManPages/man1/pbcopy.1.html">online</a>, or simply by
entering <code>man pbcopy</code> on the command line.</p>

<p><strong>Update:</strong> Boy genius <a href="http://arrelid.com/">Mattias Arrelid</a> pointed out that to get <code>pbcopy</code> and <code>pbpaste</code> to play nicely with UTF-8, you need to set <code>__CF_USER_TEXT_ENCODING</code> correctly. Read the full scoop over at <a href="http://www.macosxhints.com/article.php?story=20081231012753422">Mac OS X Hints</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://jesper.sarnesjo.org/blog/pbcopy-and-pbpaste/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>GreenStripes: Ruby bindings for libspotify</title>
		<link>http://jesper.sarnesjo.org/blog/greenstripes-ruby-bindings-for-libspotify/</link>
		<comments>http://jesper.sarnesjo.org/blog/greenstripes-ruby-bindings-for-libspotify/#comments</comments>
		<pubDate>Wed, 15 Apr 2009 17:45:17 +0000</pubDate>
		<dc:creator>Jesper Särnesjö</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[c]]></category>
		<category><![CDATA[github]]></category>
		<category><![CDATA[greenstripes]]></category>
		<category><![CDATA[libspotify]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[rubygems]]></category>
		<category><![CDATA[spotify]]></category>

		<guid isPermaLink="false">http://jesper.sarnesjo.org/blog/?p=17</guid>
		<description><![CDATA[About a week ago, Spotify released libspotify, a C API for
writing applications that utilize their service.

Now, while I&#8217;m certainly not averse to C, I think that a more human-friendly
language is a better fit for many tasks. So I whipped up a set of Ruby bindings
that lets you write programs like this one:

session = GreenStripes::Session.new(APPLICATION_KEY, 'GreenStripes', [...]]]></description>
			<content:encoded><![CDATA[<p>About a week ago, <a href="http://www.spotify.com/blog/archives/2009/04/07/spotify-opens-its-doors-to-developers/">Spotify</a> <a href="http://developer.spotify.com/blog/archives/2009/04/07/launching-libspotify-and-developers-website/">released</a> <a href="http://developer.spotify.com/libspotify/">libspotify</a>, a C API for
writing applications that utilize their service.</p>

<p>Now, while I&#8217;m certainly not averse to C, I think that a more human-friendly
language is a better fit for many tasks. So I whipped up a set of Ruby bindings
that lets you write programs like this one:</p>

<pre><code>session = GreenStripes::Session.new(APPLICATION_KEY, 'GreenStripes', 'tmp', 'tmp')
session.login(USERNAME, PASSWORD)
session.process_events until session.connection_state == GreenStripes::ConnectionState::LOGGED_IN

search = GreenStripes::Search.new(session, 'yakety sax', 0, 100)
session.process_events until search.loaded?
puts "found #{search.num_tracks} tracks"
if search.num_tracks &gt; 0
  track = search.track(0)
  session.process_events until track.loaded? and track.artist(0).loaded?
  puts "the first one is #{track.name} by #{track.artist(0).name}"
end

session.logout
session.process_events until session.connection_state == GreenStripes::ConnectionState::LOGGED_OUT
</code></pre>

<p>GreenStripes is very much in a beta stage, lacks features and
has bugs, but it&#8217;s gotten to a point where you can actually play around
with it and build stuff.</p>

<p>Interested? GreenStripes is available in source or gem form from GitHub, where
you can also read installation instructions and sign up to be notified of
updates: </p>

<ul>
<li><a href="http://github.com/sarnesjo/greenstripes/">GreenStripes on GitHub</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://jesper.sarnesjo.org/blog/greenstripes-ruby-bindings-for-libspotify/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Cocoa sans Xcode and Interface Builder</title>
		<link>http://jesper.sarnesjo.org/blog/cocoa-sans-xcode-and-interface-builder/</link>
		<comments>http://jesper.sarnesjo.org/blog/cocoa-sans-xcode-and-interface-builder/#comments</comments>
		<pubDate>Tue, 03 Mar 2009 03:20:10 +0000</pubDate>
		<dc:creator>Jesper Särnesjö</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[c]]></category>
		<category><![CDATA[cocoa]]></category>
		<category><![CDATA[cocoaheads]]></category>
		<category><![CDATA[gcc]]></category>
		<category><![CDATA[interfacebuilder]]></category>
		<category><![CDATA[macosx]]></category>
		<category><![CDATA[objectivec]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[xcode]]></category>

		<guid isPermaLink="false">http://jesper.sarnesjo.org/blog/?p=7</guid>
		<description><![CDATA[Something that has always bugged me about Cocoa development is that
it&#8217;s so tightly coupled with Xcode and Interface Builder. Virtually every single
guide on the topic will use those two apps, and if you dare ask how one would go
about without them, the answer will almost certainly be an exasperated &#8220;why
would anyone want to do that?!&#8221;

And [...]]]></description>
			<content:encoded><![CDATA[<p>Something that has always bugged me about <a href="http://developer.apple.com/cocoa/">Cocoa</a> development is that
it&#8217;s so tightly coupled with Xcode and Interface Builder. Virtually every single
guide on the topic will use those two apps, and if you dare ask how one would go
about without them, the answer will almost certainly be an exasperated <em>&#8220;why
would anyone want to do that?!&#8221;</em></p>

<p>And that&#8217;s something that bugs me even more. Good programmers love taking things
apart to figure out what makes them tick, and I strive to be one. It&#8217;s not that
I hate Xcode and Interface Builder, but rather that I like to understand what&#8217;s
going on.</p>

<p>Turns out it&#8217;s not tricky at all.</p>

<p>Before we get started, let&#8217;s define what developing a Cocoa app without Xcode or
Interface Builder actually means. No Xcode means we can use any editor and any
build system we want. No Interface Builder means that we&#8217;ll be creating our
views programmatically.  Of course, these are three completely separate topics,
and it&#8217;s quite possible to do just one or two of them. But let&#8217;s go the whole
hog.</p>

<p>Objective-C, being a strict superset of C, has to obey every rule that C obeys.
Hence, a truly minimal Objective-C program would be something along the lines
of:</p>

<pre><code>int main(int argc, char *argv[])
{
  return 0;
}
</code></pre>

<p>Of course, this doesn&#8217;t do anything interesting, and crucially, it&#8217;s not a
Cocoa app.</p>

<p>Now, what makes a Cocoa app? Well, if you create an empty Cocoa app project in
Xcode, <code>main</code> will contain a call to <code>NSApplicationMain</code> and nothing else. So, I
suppose we could just stick that in our <code>main</code>, call it done and go out to
lunch. But that would be cheating. Besides, what does <code>NSApplicationMain</code> do
anyway?</p>

<p>It actually has an <a href="http://developer.apple.com/documentation/Cocoa/Reference/ApplicationKit/Miscellaneous/AppKit_Functions/Reference/reference.html#//apple_ref/c/func/NSApplicationMain">entry</a> in the API reference, but that
will not tell you much about what it does. That information is tucked away, for
some reason, in the docs for the <a href="http://developer.apple.com/documentation/Cocoa/Reference/ApplicationKit/Classes/NSApplication_Class/index.html"><code>NSApplication</code></a> class.</p>

<p>With this knowledge, and considering we&#8217;re not going to load any nibs, we can
change the code for our minimal Cocoa app into something like this:</p>

<pre><code>#import &lt;Cocoa/Cocoa.h&gt;

int main(int argc, char *argv[])
{
  [NSApplication sharedApplication];
  [NSApp run];
  return 0;
}
</code></pre>

<p>Save the above in a file called <code>kakao.m</code> and compile it with <code>gcc</code> like so:</p>

<pre><code>$ gcc -framework Cocoa -o Kakao kakao.m
</code></pre>

<p>You can even run the app if you feel like it:</p>

<pre><code>$ ./Kakao
</code></pre>

<p>Although, as you might have noticed, that won&#8217;t do much except hang until you
kill it. So let&#8217;s add something more interesting, like a window.</p>

<p>After a quick look in the docs for the <a href="http://developer.apple.com/documentation/Cocoa/Reference/ApplicationKit/Classes/NSWindow_Class/index.html"><code>NSWindow</code></a> class, we change
the code for our app into this:</p>

<pre><code>#import &lt;Cocoa/Cocoa.h&gt;

int main(int argc, char *argv[])
{
  [NSApplication sharedApplication];
  NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
  NSUInteger style = NSTitledWindowMask
                   | NSClosableWindowMask
                   | NSMiniaturizableWindowMask
                   | NSResizableWindowMask;
  NSWindow *window = [[NSWindow alloc] initWithContentRect:NSMakeRect(0,0,400,400)
                                                 styleMask:style
                                                   backing:NSBackingStoreBuffered
                                                     defer:NO];
  [window makeKeyAndOrderFront:nil];
  [pool drain];
  [NSApp run];
  return 0;
}
</code></pre>

<p>Note that we create an <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSAutoreleasePool_Class/index.html"><code>NSAutoreleasePool</code></a> before we create
the window, and drain it afterwards. This is something Cocoa will usually take
care of, but since we are not yet in an event loop, we have to do it manually.</p>

<p>Compile and run the program like before, and lo, a window appears!</p>

<p>However, this is clearly not a <em>trüe</em> Cocoa app yet. It doesn&#8217;t get its own
icon in the dock or in the cmd-tab view, and if you try launching it from the
Finder, things just get plain silly.</p>

<p>Of course, this is something we can fix. Applications, as well as many other
kinds of bundles, are nothing but directories with special names in Mac OS X.</p>

<p>If you&#8217;ve ever peeked inside a .app bundle (right-click, Show Package
Contents), you know it contains a directory called <code>Contents</code>, which contains
among other things a directory called <code>MacOS</code>, which contains the actual
executable for the app.</p>

<p>So, without further ado:</p>

<pre><code>$ mkdir -p Kakao.app/Contents/MacOS
$ mv Kakao Kakao.app/Contents/MacOS/
</code></pre>

<p>And presto! You have a bonafide Cocoa app, complete with icon and menu bar
(which is empty, but still) that can be launched from the Finder.</p>

<p>Now, if you <em>have</em> been digging around .app bundles before, you know that there
are two more files that should go in there: <a href="http://developer.apple.com/DOCUMENTATION/MacOSX/Conceptual/BPRuntimeConfig/Articles/ConfigFiles.html"><code>Info.plist</code></a> and
<a href="http://developer.apple.com/DOCUMENTATION/MacOSX/Conceptual/BPRuntimeConfig/Articles/ConfigApplications.html#//apple_ref/doc/uid/20002094-98415"><code>PkgInfo</code></a>. And yes, if you&#8217;re developing an actual app you plan on
having actual users for, you should create those files as well. But for our
purposes, we&#8217;ll do fine without them as long as the executable has the same name
as the bundle, minus the &#8220;.app&#8221; suffix.</p>

<p>Oh, and in case you&#8217;re wondering, &#8220;kakao&#8221; is Swedish for &#8220;cocoa&#8221;.</p>

<h3>Recommended reading</h3>

<ul>
<li><a href="http://developer.apple.com/documentation/Cocoa/Reference/ApplicationKit/Classes/NSApplication_Class/index.html">NSApplication Class Reference</a></li>
<li><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSAutoreleasePool_Class/index.html">NSAutoreleasePool Class Reference</a></li>
<li><a href="http://developer.apple.com/DOCUMENTATION/MacOSX/Conceptual/BPRuntimeConfig/index.html">Runtime Configuration Guidelines</a></li>
<li><a href="http://hackety.org/2008/06/25/callingCocoaCommandline.html">Calling Cocoa Commandline</a>
by why the lucky stiff, from which I borrowed heavily.</li>
</ul>

<p><em>This is based on a presentation I gave at <a href="http://cocoaheads.org/se/Stockholm/index.html">CocoaHeads Stockholm</a>.
If you&#8217;re into Cocoa, and live in or near Stockholm, you should drop by and say
hi.</em></p>
]]></content:encoded>
			<wfw:commentRss>http://jesper.sarnesjo.org/blog/cocoa-sans-xcode-and-interface-builder/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Getting started with Spotify</title>
		<link>http://jesper.sarnesjo.org/blog/getting-started-with-spotify/</link>
		<comments>http://jesper.sarnesjo.org/blog/getting-started-with-spotify/#comments</comments>
		<pubDate>Tue, 03 Mar 2009 03:16:37 +0000</pubDate>
		<dc:creator>Jesper Särnesjö</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[lastfm]]></category>
		<category><![CDATA[spotify]]></category>

		<guid isPermaLink="false">http://jesper.sarnesjo.org/blog/?p=3</guid>
		<description><![CDATA[I&#8217;ve introduced a lot of people to Spotify lately, and I tend to say
pretty much the same things every time. So, in the interest of having something
you can point a web browser at, I decided to sum it up in a blog post.

I&#8217;m not going to go over the basics, because I think the Spotify [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve introduced a lot of people to <a href="http://www.spotify.com/">Spotify</a> lately, and I tend to say
pretty much the same things every time. So, in the interest of having something
you can point a web browser at, I decided to sum it up in a blog post.</p>

<p>I&#8217;m not going to go over the basics, because I think the Spotify application
does a pretty good job at explaining itself. If you&#8217;re new to Spotify, just play
with it for an hour or two, and you should get the hang of it.</p>

<p>Done? Great!</p>

<h3>Sharing playlists</h3>

<p>Like most other things in Spotify, playlists have <a href="http://en.wikipedia.org/wiki/Uniform_Resource_Identifier">URIs</a>. What this means,
is that you can right-click on any of your playlists and select &#8220;Copy HTTP Link&#8221;
or &#8220;Copy Spotify URI&#8221;, and you&#8217;ll get something you can paste on your blog, in
an e-mail or chat message, or pretty much anywhere else. It works just like a
link to a website, except it points to a playlist in Spotify.</p>

<p>Anyone who comes across one of these URIs can either click on it, or paste it
into the search box in the Spotify application. Now, they too will be able to
listen to your playlist, but they won&#8217;t be able to make any changes to it.</p>

<p>If you want that to happen, right-click on the playlist and select
&#8220;Collaborative Playlist&#8221;. This is great for making playlists with your friends!
Just remember that anyone who knows the URI of your playlist will be able to add
or remove tracks to it now.</p>

<h3>The Inbox</h3>

<p>There is a special kind of collaborative playlist, which as far as I know was
first seen <a href="http://aehn.jaiku.com/presence/24924358">here</a>, and that is The Inbox.</p>

<p>From a technical point of view, there is nothing special about The Inbox. It&#8217;s
simply a playlist which is called &#8220;Inbox&#8221; and marked as collaborative.</p>

<p>The idea behind it, however, is that you give the URI for it to all your
friends (and, if you&#8217;re adventurous, complete strangers), and ask them to put
music they think you might like in it. Sure, you might get the occasional
<a href="http://www.spotify.com/blog/archives/2008/03/05/spam-in-spotify/">spam track</a>, but usually it works great. You should make one for yourself!</p>

<p><a href="spotify:user:sarnesjo:playlist:3nCwOiwDiZtv9xsuEIFw4q">Here is my Spotify Inbox!</a></p>

<h3>Last.fm</h3>

<p><a href="http://www.last.fm/">Last.fm</a> is not directly related to Spotify, and is quite a bit older,
but is awesome nonetheless.</p>

<p>Basically, it&#8217;s a website that keeps track of all the music you listen to, and
creates a profile for you based on that. And this is where the magic starts. Not
only can you get nice charts of your listening statistics, but also
recommendations for music you might like and reminders for concerts and so much
more. It can be a little iffy at first, but once you&#8217;ve scrobbled enough
tracks, it really gets spot on.</p>

<p>And you can make it be the chocolate to Spotify&#8217;s peanut butter.</p>

<p>First off, you need to sign up for a Last.fm account. Once you&#8217;ve done that, go
to the Preferences view in the Spotify application, and look for the Last.fm
section. Here, make sure &#8220;Enable scrobbling to Last.fm&#8221; is checked, and put your
Last.fm username and password in their respective fields.</p>

<p>And then just listen to music.</p>

<p><a href="http://www.last.fm/user/sarnesjo">Here is my Last.fm Profile!</a></p>
]]></content:encoded>
			<wfw:commentRss>http://jesper.sarnesjo.org/blog/getting-started-with-spotify/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
