<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">

  <title><![CDATA[Tales From An Unchecked Mind]]></title>
  <link href="http://ikennd.ac//atom.xml" rel="self"/>
  <link href="http://ikennd.ac//"/>
  <updated>2013-05-03T16:59:32+02:00</updated>
  <id>http://ikennd.ac//</id>
  <author>
    <name><![CDATA[Daniel Kennett]]></name>
    
  </author>
  <generator uri="http://octopress.org/">Octopress</generator>

  
  <entry>
    <title type="html"><![CDATA[Canon EOS 6D "Review"]]></title>
    <link href="http://ikennd.ac//blog/2013/03/canon-eos-6d-review/"/>
    <updated>2013-03-23T16:42:00+01:00</updated>
    <id>http://ikennd.ac//blog/2013/03/canon-eos-6d-review</id>
    <content type="html"><![CDATA[<p>I&#8217;ve been in to photography since my Dad (who was a journalist) gave me his <a href="http://en.wikipedia.org/wiki/Olympus_OM-1">Olympus OM-1</a> SLR when I was a kid, which was released in 1972 and was <em>entirely</em> manual — the battery was optional and only powered the light meter.</p>

<p><a href="http://500px.com/photo/29004385"><img class="center" src="http://pcdn.500px.net/29004385/987e01fa1789575b4bf8a0f0b5aa9695907bd6b7/4.jpg"></a></p>

<p style="text-align:center;"> <em>Alas, my childhood OM-1 has seen better days.</em></p>

<p>When I hit 19 or so, I got a part-time job at the now-defunct <a href="http://en.wikipedia.org/wiki/Jessops">Jessops</a> camera store, and enjoyed my first income stream and a staff discount, which accelerated my photography interest quite a bit. My next camera was the EOS 3000N, a more modern film SLR. After that, I went digital with the EOS 300D, then an original 5D, then a 7D and after a brief stint with a 60D, I&#8217;ve landed with the wonderful EOS 6D.</p>

<p>Now, I&#8217;m not actually going to review the camera per se — there are lots of photography review websites <em>far</em> more qualified to do that than me. However, I do absolutely adore this thing — its image quality is superb and it&#8217;s beautifully light and easy to carry around. The incredible silent drive mode combined with the amazingly tiny <a href="http://www.usa.canon.com/cusa/consumer/products/cameras/ef_lens_lineup/ef_40mm_f_2_8_stm">40mm f/2.8 STM</a> pancake lens allows me to wander around the city and take photos without a bunch of people staring at me — I feel <em>discreet</em> with this setup, which is something I haven&#8217;t felt in years.</p>

<p><a href="http://500px.com/photo/29004361"><img class="center" src="http://pcdn.500px.net/29004361/69075366b5eef1f7b997cb9097cc6e77ebfdbcc0/4.jpg"></a></p>

<p style="text-align:center;"> <em>&#8220;I&#8217;m not fat, I&#8217;m just full-frame!&#8221;</em></p>

<p>However, this camera is the first SLR I&#8217;ve purchased that has a built-in shelf life on some of its features, which makes me slightly uncomfortable.</p>

<h3>The March of Technology</h3>

<p>I have a sort of love-hate relationship with technology, specifically computing technology. I&#8217;m a programmer, so obviously computing technology and I are intertwined, but I&#8217;m a firm believer that if the user is conscious that their machine has computers in it, the designers failed unless the product is specifically advertised as <em>THIS IS A COMPUTER</em>.</p>

<p>Let me give you an example. I&#8217;ve been fortunate enough to own several different cars so far in my life, and by far my favourite is the Mazda RX-8. The RX-8 is designed to be a mechanically brilliant car, and excels in this area — you can hurl it around the track like a madman and it&#8217;ll just lap it up and egg you on. When you&#8217;re driving, it&#8217;s all mechanical — a stubby gearstick sticks up directly from the gearbox, the steering has a very direct connection to the road, and on the dashboard you have a thing that tells you how fast the engine is going, another thing that tells you how fast the <em>car</em> is going, and not much else.</p>

<p><a href="http://500px.com/photo/29004717"><img class="center" src="http://pcdn.500px.net/29004717/787cb97d99ce89fb9156617b25ded6e32193b256/4.jpg"></a></p>

<p style="text-align:center;"> <em>The RX-8&#8217;s dashboard.</em></p>

<p>Underneath this is an incredible amount of computing power trying to make sure I don&#8217;t slam face-first into the nearest wall — computers making sure the engine is mixing fuel correctly, computers to make sure the car goes in the direction I tell it to, and so on. However, back in the cockpit all you&#8217;re doing is giggling wildly as this glorious heap of metal seems to defy the laws of physics as it propels you around the twisty piece of Tarmac that is whatever racetrack you&#8217;re on, and there&#8217;s absolutely no indication in the car that there&#8217;s all this computing going on behind the scenes unless something goes wrong.</p>

<p>And that&#8217;s the way it should be.</p>

<h3>Isn&#8217;t this supposed to be about a camera?</h3>

<p>So, how is this relevant to the EOS 6D? Well, to me, cameras are like cars (and washing machines, toasters, fridges, etc) — they&#8217;re appliances designed to do a certain job. Your relationship with them is physical, and all of the control is done through the manipulation of buttons, switches and levers, not touch-screens or keyboards and mice. Sure, they&#8217;re computers on the inside, but if I&#8217;m conscious of that then something has gone wrong somewhere.</p>

<p><img class="center" src="http://ikennd.ac//pictures/6dchassis.jpg"></p>

<p style="text-align:center;"> <em>The 6D&#8217;s chassis (photo credit: <a href="http://cpn.canon-europe.com/content/education/technical/inside_the_canon_eos_6d.do">Canon</a>).</em></p>

<p>This is a <em>physical</em> device which I use to make photographs. Sure, it has a computer inside it, but that&#8217;s a detail you don&#8217;t care about — the specifications talk about the image quality and how well the camera stands up to rain, not gigahertz and RAM. In ten years, I should still be able to use it to take pictures and as long as I can get them out of the camera and into my computer, I&#8217;m set. The computing technology in this thing has one job — to help the user create the best photos they can.</p>

<p>It makes me slightly uncomfortable to switch on my camera to see this:</p>

<p><a href="http://500px.com/photo/29004401"><img class="center" src="http://pcdn.500px.net/29004401/165f1a53ea2f8bb59877c6fe31390c1fd6467a24/4.jpg"></a></p>

<p>I&#8217;m not actually 100% sure why this feature irks me so much. The WiFi feature of the camera is incredibly useful — I can connect it to my computer or phone and shoot and preview shots wirelessly. However, seeing Facebook and Twitter icons on this thing crosses the line from an appliance to a computer. Before, my camera longevity concerns were all physical — how long will the shutter last? What happens if I get it wet? What if I drop it?</p>

<p>Now, I get to think about stuff <em>other</em> than my camera when thinking about my camera. Twitter are notorious about being strict with their API — what if it changes or goes away? What if Facebook goes the way of every other social network before it? That&#8217;s fine on a &#8220;big&#8221; computer — I&#8217;m already conditioned to have to update and change the software set on it, but my camera? It&#8217;s a metal box with buttons and switches on it, and I shouldn&#8217;t have to deal with &#8220;computer crap&#8221; like this.</p>

<h3>Conclusion</h3>

<p>Well, the EOS 6D is a great camera and you should all go buy one. However, seeing features like Facebook and Twitter integration in it make me worry about a future filled with appliances whose feature sets have shelf lives. It&#8217;s not just this camera, though — the whole industry is going this way, even cars. The Tesla Model S has Google Maps built right into the dashboard, for example.</p>

<p>My Olympus OM-1 is still exactly as functional as it was when it came out forty years ago. Will I be able to say that about my 6D forty years from now? How about if I bought a Model S? It seems that as technology advances, previously immutable appliances like cameras and cars are getting caught in the net of rapidly obsoleting technology.</p>

<p>Then again, maybe I&#8217;m just getting old. My first camera didn&#8217;t even require a battery, so obviously my idea of what a camera <em>should be</em> is biased towards a mechanical interface, and memories of mechanical cameras are going the way those of the floppy disk are.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[It's Alive, But Still Very Stupid]]></title>
    <link href="http://ikennd.ac//blog/2013/02/its-alive/"/>
    <updated>2013-02-10T16:30:00+01:00</updated>
    <id>http://ikennd.ac//blog/2013/02/its-alive</id>
    <content type="html"><![CDATA[<p>Well over a year ago, I blogged about <a href="http://ikennd.ac/blog/2011/10/where-the-hell-is-my-self-driving-car/">starting a project</a> in which I replace a radio-controlled car&#8217;s guts with an Arduino and have it be able to navigate to a given GPS location.</p>

<p>Well, that project is <em>finally</em> underway.</p>

<h2>Hardware</h2>

<p>It very quickly became apparent that an Arduino wouldn&#8217;t cut it for the kind of computational work I want to do, mainly because of the tiny amount of RAM it has. I ended up with a pairing of a Raspberry Pi and an Arduino Uno. The Arduino&#8217;s job is to interface with the various sensors on the car and pass that information back to the Pi, which has a lot more resources for doing computation.</p>

<p><strong>Note:</strong> This chapter is a fairly quick overview of how the car is put together. You can find a shopping list with exact components at the end of this post.</p>

<h3>Arduino</h3>

<p>The Arduino has a prototype board attached to it, which on the underside has two three-pin connectors for connecting the car&#8217;s servos (one for speed, one for steering). The car&#8217;s speed controller is connected to the battery and provides the Arduino with power.</p>

<p><a href="http://500px.com/photo/25510001"><img class="center" src="http://pcdn.500px.net/25510001/63b40e55ecd4707d5b9c930c8f8faeeff7e00bf4/4.jpg"></a></p>

<p>The top of the board (which is <em>very</em> messy — I intend to build a much neater one) hosts an accelerometer as well as a few cables for powering the Raspberry Pi, powering the Ultrasonic Sensors and reading data from the Ultrasonic sensors.</p>

<p><a href="http://500px.com/photo/25510047"><img class="center" src="http://pcdn.500px.net/25510047/fd79b683c20b46149bdf162e2b13d9494154679c/4.jpg"></a></p>

<p style="text-align:center;"> <em>Black: Raspberry Pi power, Yellow and white: Ultrasonic sensor power, White four-lane: Ultrasonic sensor data, Raised red board: Accelerometer.</em></p>

<p>There are four Ultrasonic sensors mounted on the car&#8217;s body — three at the front and one at the rear. All the cabling for these sensors end up at a pair of connectors on the inside of the roof, which allows the body to easily be separated from the chassis when needed.</p>

<p><a href="http://500px.com/photo/25510039"><img class="center" src="http://pcdn.500px.net/25510039/44a9598ca829a61df70750112c099f9c9c696d28/4.jpg"></a></p>

<p><a href="http://500px.com/photo/25510019"><img class="center" src="http://pcdn.500px.net/25510019/f8b5f3870096b1ff19b45805d364ba123104c31e/4.jpg"></a></p>

<p style="text-align:center;"> <em>Leaving the body clear so you could see the electronics seemed like a good idea at the time, but instead it all looks messy and is really hard to photograph. Lesson learned!</em></p>

<p>The Arduino and prototype board are mounted inside an Arduino case that&#8217;s attached to the car&#8217;s chassis with zip ties. The case has a lid, but I&#8217;ve left it out of the photos to illustrate what goes there.</p>

<p><a href="http://500px.com/photo/25510083"><img class="center" src="http://pcdn.500px.net/25510083/04f9446eb980749018827de6e2979272d4c2fe6a/4.jpg"></a></p>

<p><a href="http://500px.com/photo/25510095"><img class="center" src="http://pcdn.500px.net/25510095/a6ebbfcd1d3c9f56a0e47b3bcbc7196868f18c9e/4.jpg"></a></p>

<p style="text-align:center;"> <em>The vertical posts support the body, which rests on the clips. They can be raised to give more room.</em></p>

<h3>Raspberry Pi</h3>

<p>The Raspberry Pi is mated with a UI module from BitWizard, which hosts a 2x16 character LCD display, six buttons and a few breakout connectors for various serial busses.</p>

<p><a href="http://500px.com/photo/25510075"><img class="center" src="http://pcdn.500px.net/25510075/bb48c9a5f34e0773f2eb47a1e9b06cd1e7da9169/4.jpg"></a></p>

<p style="text-align:center;"> <em>Raspberry Pi with attached UI module. The garbled character to the right of the up arrow should be a down arrow, but there seems to be a bug in my custom character code!</em></p>

<p>The Raspberry Pi connects to the Arduino twice — once for power from the Arduino and once via USB to communicate with it. When it&#8217;s all assembled, it gets rather messy!</p>

<p><a href="http://500px.com/photo/25510103"><img class="center" src="http://pcdn.500px.net/25510103/af092a6fb6a8dc2fb9520eb9afe1965e9441234a/4.jpg"></a></p>

<p>Thankfully, with the body on, it&#8217;s a lot cleaner. The final part is to find a housing for the Raspberry Pi and a place to mount it on the car itself.</p>

<p><a href="http://500px.com/photo/25510065"><img class="center" src="http://pcdn.500px.net/25510065/91490a3a3b98b7eaa26efca8fa2f4c63ce9e3648/4.jpg"></a></p>

<p>Here&#8217;s a diagram of how everything fits together. Clear as mud!</p>

<p><img class="center" src="http://ikennd.ac//pictures/rc/component_diagram.png"></p>

<h2>Software</h2>

<h3>Arduino</h3>

<p>The Arduino is running a very simple loop that polls the attached sensors and writes their values out to the serial port. <code>ACCEL:</code> lines are accelerometer readings in G, and <code>DISTANCE:</code> lines are ultrasonic sensor readings in cm.</p>

<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>ACCEL: 0.06,0.05,0.89
</span><span class='line'>ACCEL: 0.07,0.05,0.90
</span><span class='line'>ACCEL: 0.07,0.05,0.90
</span><span class='line'>ACCEL: 0.06,0.05,0.90
</span><span class='line'>ACCEL: 0.06,0.05,0.88
</span><span class='line'>DISTANCE: 89,111,32,15
</span><span class='line'>ACCEL: 0.07,0.05,0.89
</span><span class='line'>ACCEL: 0.07,0.05,0.90
</span><span class='line'>ACCEL: 0.07,0.04,0.90
</span><span class='line'>ACCEL: 0.07,0.05,0.90
</span><span class='line'>ACCEL: 0.07,0.06,0.90
</span><span class='line'>DISTANCE: 89,111,32,15</span></code></pre></td></tr></table></div></figure>


<p style="text-align:center;"> <em>Sample Arduino output.</em></p>

<p>In addition, the Arduino listens for input on the serial port for setting speed and steering values for the servos. This is not unlike the protocol used in my <a href="http://ikennd.ac/blog/2011/09/arduino-dioder-part-one/">Arduino LED project</a>, with two header bytes, a byte for the steering angle (0 - 180), a byte for the throttle angle (0 - 180) and a checksum byte.</p>

<h3>Main Software Stack - Raspberry Pi</h3>

<p>Everything so far is just enabling the main software stack of the car to observe and interact with the hardware in the car.</p>

<p>The main software stack is written in C# against the Mono Framework. I chose this setup because it&#8217;s pretty much the only nice Object-Oriented language available with a fully featured runtime available on multiple platforms (of course, there&#8217;s also Python and Java, but I prefer C# over those two). This setup allows me to write and debug the code on Mac OS X, then copy it over the the Raspberry Pi running Debian Linux for real-life use.</p>

<p>At the moment, the software stack is at the point where it&#8217;s a fully functional object model wrapping all of the implementation details of the car:</p>

<ul>
<li><p>The <code>Sensor</code> class tree provides objects representing the various sensors on the car, providing events for when their readouts change.</p></li>
<li><p>The <code>Servo</code> class provides getters and setters for adjusting the servos on the car.</p></li>
<li><p>The <code>SerialCarHardwareInterface</code> class implements the <code>ICarHardwareInterface</code>, which defines various methods for getting the sensors and servos on the car. This is split out into an interface for when I need to implement a mock car for testing AI routines without risking damage to my car or other property (it goes quite fast!).</p></li>
<li><p>The <code>CarHTTPServer</code> class provides a simple REST API over HTTP to allow other computers on the network to observe the car&#8217;s sensors. This is great for writing tools to visualise the car&#8217;s status graphically.</p></li>
</ul>


<p><img class="center" src="http://ikennd.ac//pictures/rc/visualizer.png"></p>

<p style="text-align:center;"> <em>RCSensorVisualizer showing the car&#8217;s accelerometer (top) and distance (bottom) sensor readouts graphically.</em></p>

<ul>
<li><p>The <code>CarEventLoop</code> class runs a dual loop for running AI code. The first loop is a low-latency loop that monitors the car&#8217;s sensors, which can have interrupt handlers attached to it — simple classes that decide if execution should be halted, for example if the car turns upside-down. The second loop runs on a different thread and is where the main AI processes will take place. This dual setup allows the car to detect if it&#8217;s upside-down and halt operation even an AI process is taking a long time.</p></li>
<li><p>The <code>I2CUIDevice</code> class provides an interface to the screen mounted to the Raspberry Pi, allowing text to be written to the screen and firing events when buttons are pushed.</p></li>
<li><p>The <code>MenuController</code> class as friends provide logic for presenting a menu system on the display, allowing menu item selection and navigation, as well as &#8220;screens&#8221; for presenting information or prompting the user to confirm a chosen action.</p></li>
</ul>


<h2>Bringing It All Together</h2>

<p>Below is a video showing the whole lot working together. I scroll through the menus on the Raspberry Pi and observe sensor readouts as well as adjusting the steering and throttle.</p>

<iframe width="853" height="480" src="http://www.youtube.com/embed/Xi2m6Cru-ok?rel=0" frameborder="0" allowfullscreen></iframe>


<p>The project is now ready for its next steps, which will be writing AI code to have the car navigate its surroundings. It doesn&#8217;t have GPS at the moment so it&#8217;ll be limited to &#8220;drive forwards and don&#8217;t crash into stuff&#8221; for now, but it&#8217;s a start!</p>

<p>You can find the code for this project over on <a href="https://github.com/iKenndac/RCCarControl">my GitHub</a>. It includes the Arduino Sketch, the C# software stack for the Raspberry Pi and and Objective-C Mac application for observing the sensors.</p>

<h2>Shopping List</h2>

<p>The project at the moment uses the following hardware:</p>

<ul>
<li>1x Dual Hunter Monster Truck (<a href="http://www.tamiya.com/english/products/58396dualhunter/index.htm">Tamiya.com</a>).</li>
<li>1x Raspberry Pi (<a href="http://raspberrypi.org/">RaspberryPi.org</a>).</li>
<li>1x Raspberry Pi UI Module with 16x2 LCD (<a href="http://www.bitwizard.nl/catalog/product_info.php?products_id=115">BitWizard.nl</a>).</li>
<li>1x Arduino Uno (<a href="http://arduino.cc/en/Main/ArduinoBoardUno">Arduino.cc</a>).</li>
<li>1x Arduino Proto-shield (<a href="http://arduino.cc/en/Main/ArduinoProtoShield">Arduino.cc</a>).</li>
<li>1x ADXL345 Accelerometer (<a href="https://www.sparkfun.com/products/9836">SparkFun.com</a>).</li>
<li>4x SRF05 Ultrasonic Sensor (<a href="http://www.robot-electronics.co.uk/htm/srf05tech.htm">Robot-Electronics.co.uk</a>).</li>
<li>A ton of wires and stuff to link them all together.</li>
</ul>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Your Runtime And You]]></title>
    <link href="http://ikennd.ac//blog/2013/02/your-runtime-and-you/"/>
    <updated>2013-02-04T18:15:00+01:00</updated>
    <id>http://ikennd.ac//blog/2013/02/your-runtime-and-you</id>
    <content type="html"><![CDATA[<p>There&#8217;ve been a <a href="http://ashfurrow.com/blog/the-necessity-of-c-in-objective-c">few</a> <a href="http://ashfurrow.com/blog/seven-deadly-sins-of-modern-objective-c">posts</a>* <a href="http://ashfurrow.com/blog/objcmsgsend-is-not-your-bottleneck">floating</a> <a href="http://xinsight.ca/blog/saving-objc-method-calls/">around</a> the internets recently discussing some rules about when to use Objective-C or not, mainly focusing on performance but touching on code readability and maintainability too. These posts are all written by intelligent people who make reasonable arguments, I get a rather uneasy feeling reading them.</p>

<p>For a little while I couldn&#8217;t place it, but today it came to me — these posts, to me at least, seem to be looking at the problem (or lack thereof) too closely, citing small code snippets and &#8220;rules&#8221; on how to fix them with the correct choice of language.</p>

<p>* Specifically, point 6 of that post.</p>

<h2>Clarifying the Problem</h2>

<p>Now, the discussion has become slightly muddled between two issues - one is that Objective-C&#8217;s runtime is slower than some other runtimes (like, say, C), and the other is of code efficiency. Since a method call has more overhead in Objective-C,  inefficient code is affected more than that same code in C, so people jump to the conclusion that Objective-C is slow and the followup fix is to move to C.</p>

<p>Inefficient code will always be slow. However, since a method invocation has more overhead in Objective-C than C, C++ or most other static runtimes, people who&#8217;ve just learned about the Objective-C runtime will often blame the runtime and switch to C.</p>

<p>Unfortunately, I need to be blunt here: If you think your code is slow because Objective-C is slow, you&#8217;re wrong. Your code is slow because you wrote slow code.</p>

<h2>The Bigger Picture</h2>

<p>In day-to-day programming, you may end up in a situation in which you&#8217;re looking at <code>objc_msgSend</code> and thinking that Objective-C is too slow. If this is the case, there are only two outcomes.</p>

<ol>
<li><p>You wrote inefficient code and need to go fix it. It sucks, but this will be 99.9% of cases.</p></li>
<li><p>You screwed up big-style and Objective-C genuinely isn&#8217;t the correct tool for the job at hand. This sucks even more, because you misunderstood your problem and now have to scrap all of the Objective-C code you wrote and write it again in something else. This will be <em>very</em> rare.</p></li>
</ol>


<p>Thinking about one implementation detail in your runtime (and with Objective-C, that invariably becomes <code>objc_msgSend</code>) is <em>not</em> thinking about the bigger picture and you&#8217;ll go down a horrible road of writing little sections of code in C, copying data back and forth between the two runtimes and creating a big horrible mess. You&#8217;ll start thinking things like <em>&#8220;Accessing this instance variable directly is way faster than using Objective-C properties. This&#8217;ll make my app fast!&#8221;</em>, and will fall down that horrible trap of pre-optimising stuff that doesn&#8217;t actually make a difference.</p>

<p>Instead, you need to be thinking about the <em>behaviour</em> of your runtime and how it affects your problem. Ideally, you should do this <em>before</em> starting to implement your solution to that problem.</p>

<h3>Problem 1: I looked at Instruments and objc_msgSend is 10% of my application&#8217;s usage!</h3>

<p>Is your application actually slow? If not, who cares? If you&#8217;re making a lot of method calls, this is to be expected.</p>

<p>This problem has nothing to do with the Objective-C runtime.</p>

<h3>Problem 2: I profiled my application when it&#8217;s acting slow, and it&#8217;s some Objective-C code slowing it down!</h3>

<p>Make your code more efficient. Depending on the nature of the problem, one or more of these might help:</p>

<ul>
<li><p>Stop doing obviously silly things. Loading huge images lazily on the main thread, for instance.</p></li>
<li><p>Learn about <a href="http://en.wikipedia.org/wiki/Computational_complexity_theory">complexity</a> and how to write more efficient code.</p></li>
<li><p>Learn about perceptive performance. For example, if you do your work on a background thread and keep your UI fluid in the meantime, your application won&#8217;t feel slow. It&#8217;s better that your application remains fluid and takes ten seconds to do its work than it locking up for five seconds. Five seconds is indeed faster, but it <em>feels</em> a lot slower when an application&#8217;s UI is blocked.</p></li>
</ul>


<p>This problem also has nothing to do with the Objective-C runtime.</p>

<h3>Problem 3: I&#8217;ll be working in a realtime thread and I&#8217;m worried about the fact that Objective-C is a dynamic runtime!</h3>

<p>Aha! Now we&#8217;re getting somewhere.</p>

<p>Objective-C isn&#8217;t slow. It simply isn&#8217;t. However, one thing that it <em>is</em> is dynamic. Objective-C&#8217;s dynamic runtime gives it all the wonderful features we adore, but it isn&#8217;t appropriate for some uses.</p>

<p>Real-time threads <em>can be</em> one of those uses.</p>

<p>But not because Objective-C is slow.</p>

<p>Because it&#8217;s <em>dynamic</em>.</p>

<p>A good example of a realtime thread is a Core Audio render thread. When I get that callback from Core Audio asking me for more audio data to play, I have <em>x</em> milliseconds to return that data before the audio pipelines run out of buffer and an under-run occurs, causing playback stuttering.</p>

<p>Because that number is measured in milliseconds rather than nanoseconds, Objective-C would be perfectly fast enough to perform it. In fact, if I wrote my audio code in Objective-C it&#8217;d likely work just fine. However, because I&#8217;m under contract to return data in a certain time, I can&#8217;t safely use a dynamic runtime like Objective-C to implement it.</p>

<p>C, for instance, has a static runtime and a fixed overhead for method calls. Copy some stuff to the stack, jump to the function&#8217;s memory offset, and away you go.</p>

<p>Objective-C, though, is dynamic and you can&#8217;t guarantee a thing. Anyone can load a class into the runtime that overrides <code>-methodSignatureForSelector:</code> and redirects your method calls elsewhere, or can use something like <code>method_exchangeImplementations()</code> to swap out method implementations entirely. This means that at runtime, you can&#8217;t count on anything being what you thought it was.</p>

<p>So, because I&#8217;m under contract to return within a certain time and I personally believe it&#8217;s bad form to use a dynamic runtime in such a situation, I choose to implement that problem entirely in C.</p>

<h2>Conclusion</h2>

<p>The decision to use the C language for problem 3 was entirely a high-level decision based on the behaviour of the Objective-C runtime compared with the problem at hand.</p>

<p>This is really how you should be thinking about your runtime. If you get to the point where you&#8217;ve got some slow code and are noticing an implementation detail of the runtime pop up, you need to go back and code better. If you&#8217;ve coded the best you possibly can, you need to learn to code better. If you&#8217;ve learned to code better and the runtime is still getting in the way, you chose the wrong runtime for the entire problem.</p>

<p>Notice that this entire post is devoid of <em>any</em> code samples. This is intentional — the point of this post is that you choose your language and runtime <em>first</em> based on your problem, not <em>second</em> because of a problem in your code. If you&#8217;re switching languages and runtimes halfway through a problem, the issue is your approach to solving the problem, not the language or runtime you&#8217;re using to solve it.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[My Life In Pictures]]></title>
    <link href="http://ikennd.ac//blog/2013/02/my-life-in-pictures/"/>
    <updated>2013-02-02T21:45:00+01:00</updated>
    <id>http://ikennd.ac//blog/2013/02/my-life-in-pictures</id>
    <content type="html"><![CDATA[<p><a href="http://500px.com/photo/24869407"><img class="center" src="http://pcdn.500px.net/24869407/e466265324b08167c6eb5394eff0e268db3fd778/4.jpg"></a></p>

<p>In 2005, two things happened: I bought a kickass car, and <a href="http://www.apple.com/aperture/">Aperture 1.0</a> was released at the rather eye-watering price of £349. At the end of the year, I was playing with Aperture&#8217;s photo book tool by putting some pictures of my car in a book and inadvertently started a tradition I simultaneously despise and adore: My Life In Pictures.</p>

<p>Every year, I make a photo book of the interesting stuff that year brought — an interesting outcome is that a book&#8217;s thickness is a great way to see how interesting a year was for me. 2009 is an embarrassing 35 pages, whereas 2008 and 2006 are both pushing 100.</p>

<p>I despise them during the construction phase because they take an <em>age</em> to make — over a week of evenings for a long one. By the end I&#8217;m so sick and tired of looking at those damn photos I hesitate to buy the book I put together. Thankfully I&#8217;ve learned to push through that feeling and order, because every single time a book arrives I adore the result and happily add it to the slowly expanding collection.</p>

<p><a href="http://500px.com/photo/24869423"><img class="center" src="http://pcdn.500px.net/24869423/a614512861b0b0cad5e128281fe20d4f87b1e82b/4.jpg"></a></p>

<p style="text-align:center;"> <em>Inside 2012 In Pictures.</em></p>

<p>These things are expensive — 2012 In Pictures is 63 pages and ordered through <a href="http://blurb.com/">Blurb</a>, which came to around €55 plus tax and shipping. However, they&#8217;re well worth it and I&#8217;m already enjoying going back a few years ago and flicking through what I did in the past. They also make great gifts for family members who are into that sort of thing.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Making Future-You Happy: Figuring Out How To Organise and Tag Your Photo Library]]></title>
    <link href="http://ikennd.ac//blog/2013/01/making-future-you-happy/"/>
    <updated>2013-01-20T21:14:00+01:00</updated>
    <id>http://ikennd.ac//blog/2013/01/making-future-you-happy</id>
    <content type="html"><![CDATA[<p>My Aperture library is over 15,000 photos strong, which isn&#8217;t <em>huge</em>, but it&#8217;s enough photos to make proper storage and tagging important.</p>

<p>My Aperture library is organised by Category, then by year (maybe), then by &#8220;event&#8221;. For example&#8230;</p>

<ul>
<li>Events

<ul>
<li>2010</li>
<li>2011</li>
<li>2012</li>
</ul>
</li>
<li>Holidays and Trips

<ul>
<li>2012

<ul>
<li>WWDC 2012</li>
</ul>
</li>
</ul>
</li>
<li>People and Things

<ul>
<li>House</li>
</ul>
</li>
</ul>


<p>This seemed like a good idea to start with, but it&#8217;s actually fairly terrible. For example, I want a photo from WWDC 2012. Is that in <em>Events</em> or <em>Holidays and Trips</em>? I mean, it&#8217;s a &#8220;trip&#8221; for me, but WWDC is actually an event! This wishy-washy organisation isn&#8217;t so helpful when you&#8217;re trying to find photos from years ago. This, coupled with a complete lack of manual tagging, is a pain to work with.</p>

<h2>A Fresh Start</h2>

<p>After my previous <a href="http://ikennd.ac/blog/2012/12/the-educated-fanboy-aperture-vs-lightroom/">post</a> discussing Adobe Lightroom, not <em>three weeks ago</em>, basically concluded that I prefer Aperture, well, I&#8217;ve decided to slug it out a bit longer with Lightroom and do a long-term test.</p>

<p>On January 1st 2013, after waking up in the afternoon and noting that 2013 was in no was different to 2012, I launched Lightroom and pressed the &#8220;New Catalog&#8221; button. Starting then, I&#8217;d be using Lightroom for all of my photography work instead of Aperture, something I wasn&#8217;t sure would be a smart idea considering I didn&#8217;t actually like the program all that much. (I&#8217;ve since come to like Lightroom much more, but that&#8217;s for another post).</p>

<p><a href="http://500px.com/photo/22000369"><img class="center" src="http://pcdn.500px.net/22000369/e080bb38658c1ffecac817d15c3d50014b36d1a0/4.jpg"></a></p>

<p style="text-align:center;"> <em>New year, New photo library!</em></p>

<p>With this fresh new start, I&#8217;m determined to start and keep up with a photo library that allows me to find my photos reasonably quickly and with as little frustration as possible. My library should meet the following criteria:</p>

<ol>
<li><p>I shouldn&#8217;t be spending more than a few seconds per photo on import to get the metadata to a state of meeting the rest of these criteria.</p></li>
<li><p>A good portion of it should be automatable, if possible.</p></li>
<li><p>The metadata should allow me to, in the future, filter down my library to a reasonable number of candidates for the photo I&#8217;m actually looking for.</p></li>
<li><p>The data input for each photo must conform to a defined schema to keep metadata consistent.</p></li>
</ol>


<p>My rationale behind the first entry is that if metadata input takes too long, I won&#8217;t bother doing it. The second entry helps the first become more of a reality. The third is a realisation of the first two — if my metadata entry isn&#8217;t taking very long, it won&#8217;t be <em>that</em> comprehensive, but if I can filter my 15,000 photos down to 150 candidates I&#8217;ll be able to find the photo I&#8217;m looking for manually in not too much time.</p>

<p>The last entry is to try and combat &#8220;tag creep&#8221;. I&#8217;ve seen this a lot, especially on blogs, where people just type in tags as they pop into their head. For example, in the photo above, well, it&#8217;s <strong>night</strong>. And there are <strong>fireworks</strong>. Oh, and <strong>trees</strong>. And <strong>clouds</strong>! <strong>night, fireworks, trees, clouds</strong> actually seems like a reasonable set of tags. However, my next fireworks shot is on the next night and there&#8217;s only one <strong>firework</strong> and it&#8217;s a <strong>starry</strong> night. <strong>night, firework, trees, starry</strong>. The only two tags those photos have in common are <strong>night</strong> and <strong>trees</strong>, neither of which are material to the photos! Clearly, we need a well-defined way of tagging photos.</p>

<h2>It&#8217;s all about the questions!</h2>

<p>Earlier this evening, I <a href="http://twitter.com/iKenndac/status/293052592366419968">tweeted</a> asking others how they organised their libraries, and quickly learned that everyone is different, and nobody seems to have a catch-all solution.</p>

<p>So, I started thinking about what I should tag my photos with and didn&#8217;t get far. <em>Then</em>, I started thinking about how I try to find photos once they&#8217;re in the library. That&#8217;s when I started getting somewhere — and I started listing all the questions I ask myself (and my photo library software) when trying to find my photos. Then I remembered that damnit, if I&#8217;m putting this effort into cataloging my library, the computer should be asking <em>me</em> the questions!</p>

<p>This brainwave has completely flipped how I think about metadata — <strong>it isn&#8217;t for finding the photo you want, but for dismissing the photos you don&#8217;t want</strong>.</p>

<p>The list below isn&#8217;t the questions I ask my computer to find photos — it&#8217;s the questions I want the computer to be able to ask <em>me</em> to get rid of the photos I&#8217;m not interested in:</p>

<h3>Where did you put the photo on disk?</h3>

<p>I&#8217;ll get this out of the way quickly — when trying to find photos, I <em>never</em> think about my computer or any detail of it. Therefore, I don&#8217;t care where my photos are on my computer. I let Aperture/Lightroom deal with them as they&#8217;d like to, and make sure I have backups. Hard drives, folders and filesystems are things for computers to deal with, not me. Therefore, I don&#8217;t use custom folder names or anything crazy like that.</p>

<h3>What did you name the photo&#8217;s file?</h3>

<p>Similar to my previous point, filenames have no hope of being helpful and I never think about them. There&#8217;s no way they can contain enough information to be useful, and one day you&#8217;ll encounter a USB stick formatted as FAT16 and you won&#8217;t be able to put your crazily-named files on it. I&#8217;ll let my computer deal with that and not care myself.</p>

<h3>When did you take the photo?</h3>

<p>Thankfully, assuming you have your camera&#8217;s clock set correctly, this is a non-issue. Time and date metadata is already present in my photos. Hooray!</p>

<h3>Where did you take the photo?</h3>

<p>Location, in my opinion, is one of the most important pieces of metadata a photo can have, even if it&#8217;s not that accurate. Hell, <em>especially</em> if it&#8217;s not that accurate! For example, I remember seeing an awesome car when I was a kid somewhere in France. That&#8217;s enough information (<strong>France</strong>, <strong>1985 - 1995</strong>, <strong>Car</strong>) to filter out 99% of my library!</p>

<p>I already geolocate my photos in two ways — if I was out and about snapping away I&#8217;ll manually geolocate as best as I can when I return. Even if I find a year-old picture on some motorway in Germany, I&#8217;ll geolocate it to <strong>Germany</strong> and be done with it.</p>

<p>If I&#8217;m going on a photo walk — that is, a walk or similar with an express intent to take photos along the way - I&#8217;ll bring my <a href="http://ikennd.ac/blog/2012/04/high-tech-meets-low-tech-gps/">bike&#8217;s GPS</a> with me. It&#8217;s a Garmin Montana, and I specifically chose that rather expensive model because the battery lasts up to 16 hours. I can switch it on, throw it in my backpack and when I get home I have a trace of where I&#8217;ve been all day. Both Aperture and Lightroom contain tools to link this trace to your photos, automatically and accurately geotagging the day&#8217;s photos in an instant.</p>

<h3>What is in the photo?</h3>

<p>This one is a bit more difficult. Photos always contain <em>lots</em> of things. The photo above contains fireworks, the sky, clouds, trees, people, street lamps, buildings, snow, gravel, probably a mouse hibernating under a bush somewhere (Note: mice probably don&#8217;t hibernate in bushes), a bench, etc etc etc.</p>

<p><em>However</em>, I never care what&#8217;s in the photo when looking for it. I care what the photo is <em>of</em>, and that photo is of fireworks. However, as discussed above, telling the computer what the photo is <em>of</em> can quickly get messy.</p>

<p>Instead, I&#8217;ve decided to distill this question down further, to a simple yes/no question:</p>

<p><strong>Is the photo of a ______ ?</strong></p>

<p>This way, tags can always be singular. Is the photo of a <strong>firework</strong>? Is it of a <strong>tree</strong>?</p>

<h3>What environment was the photo taken in?</h3>

<p>Sometimes, I want to find some pictures I know were taken at night, or in the snow, or both. Adding a tag for this would be useful!</p>

<h2>Browsing</h2>

<p>Sometimes, rather than searching for specific photos, I want to browse through all of the photos I took at, for example, WWDC 2012. In addition, I often keep a photo reference of progress on various projects such as my <a href="http://ikennd.ac/blog/2012/10/winter-project-model-railway/">railway</a> or <a href="http://ikennd.ac/blog/2011/10/where-the-hell-is-my-self-driving-car/">robotic monster truck</a>.</p>

<p>To allow this, I&#8217;ll continue to organise my photos by year, but rather than vague top-level folders I&#8217;ll stick with three: <strong>Projects</strong>, <strong>Events &amp; Trips</strong> and <strong>Photography</strong>, the latter reserved for photos where the sole point of taking the photo was to make a beautiful photo.</p>

<p>Additionally, sometimes I want to browse (or share) my favourite photos, either because they&#8217;re photos I&#8217;m proud of technically or they just remind me of something amazing. For this, I&#8217;ll use the star rating system — typically photos in my library are ★★★★★ or nothing.</p>

<p><a href="http://500px.com/photo/8718249"><img class="center" src="http://pcdn.500px.net/8718249/e9601f6b6f087f6783ebef4d0ba7a9361cfdadb4/4.jpg"></a></p>

<p style="text-align:center;"> <em>&#8220;Port of San Francisco&#8221;, a photo I consider ★★★★★.</em></p>

<h2>The Metadata Schema</h2>

<p>Based on these questions and the above criteria, I&#8217;ve settled on the following metadata schema on top of the metadata already added to the photo by the camera:</p>

<ul>
<li>Location, as accurately as possible.</li>
<li><strong>One</strong> tag for the environment (examples: <strong>Indoors</strong>, <strong>Snow</strong>, <strong>Rain</strong>).</li>
<li><strong>One</strong> tag for the subject matter unless it&#8217;s a photo of people, which must be singular (examples: <strong>Plane</strong>, <strong>Car</strong>, <strong>Landscape</strong>).</li>
<li><strong>One</strong> tag <strong>per primary person</strong> in the shot (examples: <strong>Tim</strong>, <strong>Chester</strong>, <strong>Me</strong>).</li>
<li>If the photo was taken at night, the tag <strong>Night</strong>.</li>
</ul>


<p>This metadata schema is quick to enter and will allow me to filter down my library fairly accurately based on the questions I typically ask when searching for photos. It&#8217;s also intentionally very restrictive to avoid tag creep — I don&#8217;t want to be entering twenty tags per photo in a year&#8217;s time as I slowly start adding more things in.</p>

<p>As for whether this will work, well, only time will tell. It can&#8217;t be worse than it was before, right?</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Your Drives WILL Fail, All At Once: Backing Up For The Apocalypse]]></title>
    <link href="http://ikennd.ac//blog/2013/01/your-drives-will-fail/"/>
    <updated>2013-01-02T19:44:00+01:00</updated>
    <id>http://ikennd.ac//blog/2013/01/your-drives-will-fail</id>
    <content type="html"><![CDATA[<p>So, you&#8217;ve decided that it&#8217;s time to do proper backups!</p>

<p>If you <em>haven&#8217;t</em> decided it&#8217;s time to do proper backups, you&#8217;re <s>an idiot</s> wrong. All drives, spinning, SSD or otherwise, have a spec called <em>Mean Time Between Failures</em> or MTBF. This is the average time a drive can be expected to work before it fails. Like brake discs on a car, they&#8217;re expected to wear out over time. Not <em>fast</em>, but they&#8217;re certainly expected to stop working.</p>

<p>Fortunately for you, my dear readers, I have the experience to help! Quoth my friend Tim:</p>

<blockquote><p>You have, by far, the highest drive failure rate of <em>anyone</em> I know, and I work in a data centre with 1000s of them.</p></blockquote>

<p>He&#8217;s quite right — over the past couple of years I&#8217;ve had two spinning disks and one SSD completely die on me. The spinning disks were in an always-on Mac mini and I finally cottoned-on to the fact that laptop drives aren&#8217;t designed for continuous running and the head generated therein, and the SSD succumbed to the dreaded <a href="http://www.techspot.com/news/44694-intel-confirms-8mb-bug-in-320-series-ssds-fix-available.html">8MB bug</a> that affects cheaper Intel SSDs, which isn&#8217;t as &#8220;fixed&#8221; as they claim.</p>

<p>Still, as a result I&#8217;ve gotten my backup regime to the point where the worst part of a drive failure is the effort of buying and replacing the broken drive, and the boredom of watching the progress bar slowly inch forwards as the restoration is done.</p>

<p>If my apartment building catches fire and <em>all</em> of my drives are lost, then the restoration process isn&#8217;t so smooth and I don&#8217;t have 100% data coverage, but I&#8217;ve got the important stuff covered.</p>

<p>I&#8217;ve also found a few tricks to ease the pain of restoring, which can be found below. A backup is <em>useless</em> unless it restores properly!</p>

<h2>Local Backup</h2>

<p>My local backup uses Time Machine to a <a href="http://www.drobo.com/">Drobo</a> connected to a Mac mini that&#8217;s at the other end of my apartment. The Drobo can survive a drive failure without breaking a sweat, and there&#8217;s a couple of fire walls between the two machines, so if a small fire breaks out with luck one of them will survive.</p>

<p>The Time Machine backup isn&#8217;t bootable, so if you&#8217;re in a situation where you&#8217;d need to carry on using your computer in as little time as possible, consider something like <a href="http://www.shirt-pocket.com/SuperDuper/SuperDuperDescription.html">SuperDuper!</a> or <a href="http://www.bombich.com/">Carbon Copy Cloner</a> to keep a live, bootable backup.</p>

<h2>Offsite Backup: Online</h2>

<p>For offsite backup, I backup my most important stuff (my Documents and Photos folders) online, which totals around 230Gb at the moment. Backing up <em>everything</em> isn&#8217;t very economical since it&#8217;d take too long, and I could live without most of my other stuff anyway, or get it from somewhere else.</p>

<p>My online backup uses <a href="http://www.haystacksoftware.com/arq/">Arq</a> to backup to <a href="http://aws.amazon.com/glacier/">Amazon Glacier</a>, which I just moved to using instead of <a href="http://aws.amazon.com/s3/">Amazon S3</a>. Amazon Glacier is cheaper than S3, but doesn&#8217;t have instant access to your data — you may have to wait a few hours between requesting your data and being able to download it. My logic is that if I&#8217;m in a situation where I need to recover using my online backup, having to wait a bit will be the least of my worries. Arq supports both S3 and Glacier just fine, so you can use whichever service you prefer.</p>

<p>There are also services that provide online backup solutions, such as CrashPlan, Mozy and many more. However, you have to <em>trust</em> them not to screw up (and going by a friend&#8217;s <a href="https://twitter.com/asmitter/status/279321565567520768">recent</a> <a href="https://twitter.com/asmitter/status/279321712728879104">experiences</a>, that&#8217;s not something you should do lightly). If they go out of business, bye-bye data. However, I trust Amazon not to go out of business any time soon, and Arq backs up using a <a href="http://www.haystacksoftware.com/arq/s3_data_format.txt">documented format</a> and there&#8217;s even an open-source command-line restoration tool <a href="http://sreitshamer.github.com/arq_restore/">on GitHub</a>, so even if Arq stops being made, I can still get at my data.</p>

<p><em>Then again</em>, these services do offer some great features such as mailing you a restoration DVD or hard drive if you have a slow internet connection — it&#8217;s up to you to weigh up the pros and cons of each method.</p>

<h2>Offsite Backup: Offline</h2>

<p>If you want <em>everything</em> safely offsite, or online backup isn&#8217;t feasible due to a slow internet connection (or both), you&#8217;ll want to start physically moving disks around. I don&#8217;t do this, but a good solution would be to have two separate backup disks and rotate them. For example:</p>

<ul>
<li>Have Time Machine (or whatever) backup to disk 1. Put disk 2 offsite somewhere, like in a locker at work.</li>
<li>One week later, take disk 1 to work and bring disk 2 home with you.</li>
<li>Have Time Machine backup to disk 2.</li>
<li>One week later, take disk 2 to work and bring disk 1 home with you.</li>
<li>Repeat forever!</li>
</ul>


<p>As of Mountain Lion, Time Machine supports backing up to multiple disks properly, so swapping them out once a week will be seamless. With this setup, if your house catches fire and you lose everything, the worst case scenario is that your backup is a week behind.</p>

<h2>Easing Restoration</h2>

<p>For local restoration, there&#8217;s a few things you can do to make the restoration process a bit easier:</p>

<h3>Getting the Operating System Running</h3>

<p>If you have a modern Mac, it has a feature called <a href="http://support.apple.com/kb/HT4718">Internet Recovery</a> that allows the machine to download and install Mac OS X onto a completely blank drive.</p>

<p>However, if you don&#8217;t have a fast internet connection or if your Mac doesn&#8217;t have Internet Recovery (like my iMac), you can do what I did — I set up my Mac mini running Mac OS X Server (which is now a cheap add-on to Mac OS X from the App Store) to act as a NetInstall agent. It&#8217;s a really simple process — an assistant will ask you for a Mac OS X installer either from the App Store or an install DVD and convert it to a NetInstall image.</p>

<p><img class="center" src="http://ikennd.ac//pictures/NetInstall.png"></p>

<p style="text-align:center;"> <em>NetInstall images appear as any other startup disk would.</em></p>

<p>Once this is done, any Mac capable of running the Mac OS X version you&#8217;ve made an image of can boot up and install Mac OS X without having to hunt around for installation media. Simply connect your Mac to the same network as the server and hold <strong>Command+N</strong> as you switch it on.</p>

<p><strong>Note:</strong> When installing over NetInstall, <em>don&#8217;t</em> be tempted to do it over WiFi. It&#8217;ll be slow and painful!</p>

<p><strong>Double Note:</strong> NetInstall isn&#8217;t the same as Net<em>Boot</em>. NetBoot allows you to boot up a computer normally over the network, which isn&#8217;t the same.</p>

<h3>Getting Yourself Up And Running</h3>

<p>If you&#8217;re happy to leave your computer churning away for hours while your backup is being restored, simply have it restore &#8220;normally&#8221; through Time Machine or your backup software of choice. Your computer will be out of action for the duration of the restore, but it&#8217;s simple and your computer will be just like it was before this whole mess started.</p>

<p>However, if you&#8217;re like <em>me</em>, you&#8217;ll be impatient and will want to start doing stuff with your computer as soon as possible. Please note that this is a very advanced technique, and I&#8217;ve purposefully left the instructions vague to dissuade people from doing it. If you don&#8217;t know how to do any of the steps I detailed, you should just let your Mac restore fully through your backup software.</p>

<ul>
<li>Using your backup solution, restore as little as possible to get a functioning computer that <strong>includes your user account</strong> but not the contents of your Documents, Photos, etc folders.</li>
<li>Log into your empty user.</li>
<li>Start manually copying things from your backup into your home folder.</li>
</ul>


<p>Using this technique, you can get up and running really quickly while your massive photo library restores in the background. However, it&#8217;s <em>critically</em> important that you restore your user from backup, as both the UID and UUID of the user on your computer <em>must</em> match the one in the backup otherwise you&#8217;ll get permissions problems.</p>

<p>The last thing to do is to copy the Library folder. This is invisible by default, and replacing your Library folder of the current user is a bad idea. Therefore, you need to:</p>

<ul>
<li>Copy the backed-up Library into your home folder with a new name, like &#8220;Library-New&#8221;.</li>
<li>Reboot your Mac into Recovery Mode by holding <em>Command+R</em> as you reboot.</li>
<li>In the Terminal in Recovery Mode, delete your user&#8217;s Library folder and move the &#8220;Library-New&#8221; into its place.</li>
</ul>


<p>When you reboot normally, your user will be a mirror of what it was in the backup.</p>

<h2>Last Words</h2>

<p>The problem with backup is that it&#8217;s boring and a pain in the ass. What makes it worse is that computers are very good at hiding the fact that drives are, basically, starting to fail the day you buy them — they&#8217;re black boxes of electronics that people assume will keep working.</p>

<p>I&#8217;ve gone through enough drive failures to feel incredibly uneasy if my important data is in less than three places — my computer, my local backup and my online backup. Unfortunately, I only got this way by suffering data loss when a drive failed years ago and I had no backup.</p>

<p>If you&#8217;re reading this and haven&#8217;t already started backing up, I&#8217;m sure this advice and all other advice about backups will fall on deaf ears. However, once you <em>do</em> suffer data loss, I hope you come back to this article and that it&#8217;s useful for next time.</p>

<p>I&#8217;ll leave you with this final thought:</p>

<p>Close your eyes and imagine what you&#8217;d do if you went to switch on your computer and you found that it&#8217;s drives were completely blank. All of those thousands of hours poured into documents, all those photos of your friends and family, all gone. Forever.</p>

<p>If your answer is anything but &#8220;I&#8217;d buy a new drive and restore from my backup&#8221;, you&#8217;d better read this post again while buying external hard drives on Amazon.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[The Educated Fanboy: Aperture vs. Lightroom]]></title>
    <link href="http://ikennd.ac//blog/2012/12/the-educated-fanboy-aperture-vs-lightroom/"/>
    <updated>2012-12-27T18:17:00+01:00</updated>
    <id>http://ikennd.ac//blog/2012/12/the-educated-fanboy-aperture-vs-lightroom</id>
    <content type="html"><![CDATA[<p>As I&#8217;ve grown older (and I&#8217;m aware that, at 27, I&#8217;m not actually allowed to claim that I&#8217;m &#8220;old&#8221; yet), I seem to have settled into a middle ground between the random person on the street that doesn&#8217;t know what a <a href="http://www.youtube.com/watch?v=o4MwTvtyrUQ">browser is</a> <em>(YouTube Link)</em> and full-out fanboy — something I like to call the <em>educated fanboy</em>.</p>

<p>The Educated Fanboy is someone who, like a normal fanboy, is completely fanatical about the things they choose to use. They research their product(s) to an insane degree, and end up knowing more than is useful (or even healthy) about the companies and products involved. However, unlike a normal fanboy, an educated fanboy is able to answer the question &#8220;So, why don&#8217;t you use <em>competitor X</em> instead?&#8221;</p>

<p>Fanboy answer: <em>BECAUSE MACS ARE SHIT.</em></p>

<p>Educated Fanboy answer: <em>I like iOS, but the UI is starting to stagnate a little so I thought I&#8217;d hop over and try Android. It&#8217;s more interesting, but I miss the seamless integration that iCloud gives you.</em></p>

<p>Being an Educated Fanboy is why I&#8217;m currently using an Android phone after using an iPhone for years, is why I nearly replaced my Canon SLR with a Nikon one despite having a rather large pile of Canon lenses, and is why I have both an iMac and a Windows PC sitting at my desk.</p>

<h2>To The Point, Already!</h2>

<p>Right! So, I&#8217;ve been using Apple&#8217;s <a href="http://www.apple.com/aperture/">Aperture</a> as my photography tool since it was at version 1.0 and cost £300. Many years later, I&#8217;ve finally decided to sit down and give Adobe&#8217;s Lightroom (or, more accurately, Adobe® Photoshop® Lightroom® 4) a go.</p>

<p>Like most fanboy things — <em>Canon</em> vs. <em>Nikon</em>, <em>Xbox</em> vs. <em>Playstation</em>, <em>Corvette</em> vs. <em>Viper</em>, <em>Chrome</em> vs. <em>Safari</em>, <em>Aperture</em> vs. <em>Lightroom</em>, etc — the thing that&#8217;ll swing it one way or another for a particular person will be fairly small in the grand scheme of the overall product. All of them are fine products, and nobody can intelligently claim someone is wrong for going one way or the other.</p>

<p>In the Lightroom vs. Aperture fight for my own personal use, the fight came down to three things:</p>

<ul>
<li>Lightroom&#8217;s Noise Reduction is absolutely amazing.</li>
<li>Aperture&#8217;s book templates are <em>way</em> better than Lightroom&#8217;s.</li>
<li>Lightroom&#8217;s workflow MAKES ME WANT TO PUNCH THINGS.</li>
</ul>


<p>And the workflow is what makes Lightroom fall over for me. When making a book, every time I wanted to make an adjustment to an image I had to hop over to the Develop module, completely removing my book workspace from the screen and breaking my flow. For a while, I just started playing with the Noise Reduction slider to make myself happy again, but considering that I&#8217;ve never wanted to de-noise a photo before and that I make books relatively often, there&#8217;s no way me and Lightroom can be happy together.</p>

<p>But man, that Noise Reduction…</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[1,000 km]]></title>
    <link href="http://ikennd.ac//blog/2012/11/1000km/"/>
    <updated>2012-11-21T21:45:00+01:00</updated>
    <id>http://ikennd.ac//blog/2012/11/1000km</id>
    <content type="html"><![CDATA[<p>Today, after a slightly extended trip home from work, I hit 1,000km ridden on my bike since March 25th this year, which is enough to ride from South London to Monaco in a straight line! In those eight months, I have…</p>

<ul>
<li>Spent 71 hours on my bikes.</li>
<li>Gone on 81 separate rides, which averages 2.5 per week.</li>
<li>My <a href="http://app.strava.com/rides/13036767">longest ride</a> was just over 30km.</li>
</ul>


<p>You can see my full cycling stats on my <a href="http://app.strava.com/athletes/401933">Strava profile</a>.</p>

<iframe height='405' width='590' frameborder='0' allowtransparency='true' scrolling='no' src='http://app.strava.com/runs/28819085/embed/307db656b437d928402cdb56b9ef8ebea07fb06b' style="display:block; margin: auto;"></iframe>


<p style="text-align:center;"> <em>The ride home from work that tipped me over 1,000km.</em></p>

<p>My <a href="http://ikennd.ac/blog/2012/07/mountain-bikes-plus-mountains-equals-awesome/">new bike</a> has been put through a wide range of terrain, from the dry, sandy mountains of <a href="http://ikennd.ac/blog/2012/07/mountain-bikes-plus-mountains-equals-awesome/">the Alps</a> to wet but smooth rides into work to the muddy, dirty, leafy forests in there area around my home.</p>

<p>One of the reasons I replaced my bike this year was that my old bike had suffered from neglect. A few years ago I rode it a lot in wet, gravelly conditions and fine pieces of gravel got everywhere. I didn&#8217;t get my bike serviced (or service it myself), and the gravel wore away at irreparable parts of the frame. It wasn&#8217;t gone by any means, but as the bike started needing serious money spending to replace work parts, I didn&#8217;t want to spend that money on a failing frame.</p>

<p><img class="center" src="http://ikennd.ac/pictures/cycling/muddy.jpg"></p>

<p style="text-align:center;"> <em>Cycling in wet, muddy conditions takes its toll on me, too!</em></p>

<p>So, I&#8217;m preparing to give my bike a thorough service now I&#8217;ll be winding the riding down as it gets snowy. Armed with the knowledge I&#8217;ve gained over the years and <a href="http://www.amazon.com/Park-Tool-BBB-2-Bicycle-Repair/dp/B001B6NAW2/ref=sr_1_1?s=books&amp;ie=UTF8&amp;qid=1353531679&amp;sr=1-1&amp;keywords=Big+Blue+Book+of+Bicycle+Repair">The Big Blue Book of Bicycle Repair</a>, I&#8217;ll be spending a weekend taking my bike apart and thoroughly cleaning and re-lubricating the sensitive parts. Since I&#8217;ll have it apart <em>anyway</em>, I&#8217;ve decided to do a couple of upgrades to the brake system (new hoses) and the tyres (converting to tubeless). It&#8217;ll be as good as new!</p>

<p>Here&#8217;s my list of tasks. It&#8217;ll be a busy weekend!</p>

<p><strong>Brakes</strong></p>

<ul>
<li>Bleed brake lines (if needed)</li>
<li>Adjust lever travel and reach</li>
</ul>


<p><strong>Rear Gears</strong></p>

<ul>
<li>Remove cassette and clean</li>
<li>Clean and re-lubricate derailleur</li>
<li>Check gear cables for smoothness/fraying, re-lubricate or replace if needed</li>
<li>Check and adjust gear shifting</li>
</ul>


<p><strong>Rest of Drivechain</strong></p>

<ul>
<li>Check chain for stretch, replace if needed</li>
<li>Remove crank and bottom bracket, clean, lubricate and reassemble</li>
<li>Check wheels and axles for lubrication, correct tightness</li>
</ul>


<p><strong>Suspension</strong></p>

<ul>
<li>Check seals and pressures</li>
<li>Re-adjust if needed</li>
</ul>


<p><strong>Frame</strong></p>

<ul>
<li>Check frame for cracks etc</li>
<li>Clean frame, sticker/paint over damage, observe friction points</li>
</ul>


<p><strong>Miscellaneous</strong></p>

<ul>
<li>Check saddle height and position</li>
<li>Remove dropper post, clean and re-lubricate if needed</li>
</ul>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Winter Project: Model Railway]]></title>
    <link href="http://ikennd.ac//blog/2012/10/winter-project-model-railway/"/>
    <updated>2012-10-10T21:36:00+02:00</updated>
    <id>http://ikennd.ac//blog/2012/10/winter-project-model-railway</id>
    <content type="html"><![CDATA[<p>It&#8217;s October, and winter is in the air! In Sweden, that means you hunker down and prepare from the oncoming arctic darkness. Since Swedish infrastructure survives this just fine and food isn&#8217;t a problem, that means it&#8217;s time to build toys, er&#8230; models!</p>

<p>I&#8217;ve written about models railways on and off on this blog for a few years. However, last year we moved into an apartment large enough for me to dedicate a room to a railway. No more cramped lofts!</p>

<p>Over the next few months, I&#8217;m planning to slowly build up a scenic model railway layout complete with towns, forests, lakes and so on. Turns out this quite a huge undertaking, and I&#8217;ve already spent a month planning and starting the build. Here we go!</p>

<p><a href="http://500px.com/photo/15633855"><img class="center" src="http://pcdn.500px.net/15633855/4726f281aa37041e84259c69ed472d2b616bc8df/4.jpg"></a></p>

<p style="text-align:center;"> <em>InterCity 125 and Mallard.</em></p>

<h2>Planning</h2>

<p>The track, once properly laid, will be pretty much permanent - surrounded by scenery, attached to point motors and have its power lines soldered in. Because of this, make sure you take your sweet time settling on the layout!</p>

<p>I used an app called <a href="http://www.railmodeller.com">RailModeller</a> to try various layouts on the computer. Once I&#8217;d settled on a rough design, I bought the track plus extras (RailModeller will give you a list of exactly what track you need to create the layout you&#8217;ve made) and plonked it down on the board. Inevitably, you&#8217;ll tweak the layout once you see it in real life - make sure you keep your changes in sync with RailModeller so you have an accurate inventory of track, and so you can try virtual changes at any time.</p>

<p>Once you have trains running around track set loosely on the table, start asking some questions:</p>

<ul>
<li>Is the track too dense? You need space for scenery.</li>
<li>Is the track too sparse? After all, it is a model railway?</li>
<li>What&#8217;ll go in that gap? How about over there?</li>
<li>How about more interesting features like tunnels and bridges?</li>
<li>Is there a station?</li>
<li>Is there enough storage space to park trains when not in use?</li>
<li>Is there at least one complete loop so you can set a train running on its own?</li>
</ul>


<p>Once you&#8217;re settled on a layout that&#8217;ll make a good model, it&#8217;s time to make the track more permanent so you can build it!</p>

<p><img class="center" src="http://ikennd.ac/pictures/railway/RailModeller.png"></p>

<p style="text-align:center;"> <em>My final layout in RailModeller. Real life is a little more flexible than RealModeller, so it&#8217;s ok if things don&#8217;t exactly line up.</em></p>

<h2>Assembling</h2>

<p><a href="http://500px.com/photo/15633889"><img class="center" src="http://pcdn.500px.net/15633889/d46df6b85d06c738aab3121326bb32c878c24c4a/4.jpg"></a></p>

<p style="text-align:center;"> <em>Things will get messy when you start assembing the layout!</em></p>

<h3>Electrical</h3>

<p>My layout is digital, powered by a system called DCC. DCC is a standard that uses AC current to power the trains and connected accessories. Each train/accessory has a unique address, and commands to them are encoded by varying the frequency of the AC current. This makes the electrical component of the layout slightly more fragile than a traditional DC system, so the layout is wired with a &#8220;master&#8221; wire running underneath the board, connecting to the track every few metres by smaller wires soldered to the track and passing through holes in the board.</p>

<p>The motors connected to the points are connected to the master wire directly rather than to the track, again through holes in the board.</p>

<h3>Ramps</h3>

<p>The ramps are made from 9mm plywood, strengthened by thicker timber underneath where appropriate. The drop from the point the 9mm plywood hits the board to the board itself is done using a polystyrene gradient from <a href="http://woodlandscenics.woodlandscenics.com/show/Item/ST1411/page/1">Woodland Scenics</a>.</p>

<p>When designing and building ramps, it&#8217;s important not to make them too steep - about 4% is the steepest you can realistically get away with!</p>

<h3>Track Bed</h3>

<p>To keep the trains running smoothly and quietly, it&#8217;s important to have the track running on a foam or cork bed. I used track bedding once again from <a href="http://woodlandscenics.woodlandscenics.com/show/category/HOScaleTrackBedSystem">Woodland Scenics</a>.</p>

<p>This will likely be the most tedious part of the initial build of the layout - it took me a few days to put the bedding on mine. The bedding needs to be cut and curved correctly then glued onto the track. Points are even harder!</p>

<p><a href="http://500px.com/photo/15633875"><img class="center" src="http://pcdn.500px.net/15633875/6254e4bd4d988c7bd6368d191f2d8fde1617869e/4.jpg"></a></p>

<p style="text-align:center;"> <em>&#8230;however, once it&#8217;s done it&#8217;ll be clean, tidy and smooth running.</em></p>

<h2>Controlling</h2>

<p>As mentioned earlier, my layout runs using a digital system called DCC. My controller is fairly normal looking, with a little UI to choose which train or accessory you&#8217;d like to control. While controlling trains like this is a lot of fun, controlling accessories is less so. There are thirteen sets of points on my layout, and unlike trains, they can&#8217;t be named. When I need to switch a point to drive a train into a siding, it&#8217;s often difficult to remember if that point is number 8 or 9.</p>

<p>This is where a piece of software called RailMaster comes in. Plug in the controller via USB and you can use it to build a rough version of your layout, telling it which points are where. Once you&#8217;re done, you can click the points on the map of your layout to switch them.</p>

<p><img class="center" src="http://ikennd.ac/pictures/railway/Railmaster.png"></p>

<p style="text-align:center;"> <em>My layout in RailMaster.</em></p>

<p>The software can also control the trains and runs alongside the controller, allowing you to switch between the software and the controller as you wish.</p>

<h2>Next Steps</h2>

<p>And with that, my track is completely assembled, ready for the arid wooden plains to be converted into lush forests and busy towns.</p>

<p>And obviously, I didn&#8217;t attach my GoPro to a train and make any stupid&#8230; oh, who am I kidding?</p>

<p><a href="http://500px.com/photo/15633851"><img class="center" src="http://pcdn.500px.net/15633851/b9aa1f8044e8877d09a9db2bbed71167e68f9883/4.jpg"></a></p>

<iframe width="770" height="433" src="http://www.youtube.com/embed/lg5ckQUe3Os" frameborder="0" allowfullscreen></iframe>


<p>Time to start stocking up on fake trees!</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Mountain Bikes + Mountains = Awesome]]></title>
    <link href="http://ikennd.ac//blog/2012/07/mountain-bikes-plus-mountains-equals-awesome/"/>
    <updated>2012-07-29T13:33:00+02:00</updated>
    <id>http://ikennd.ac//blog/2012/07/mountain-bikes-plus-mountains-equals-awesome</id>
    <content type="html"><![CDATA[<p><a href="http://ikennd.ac/blog/2012/03/public-shaming-the-only-way/">In March</a>, I publicly announced I wanted to get fit enough to go snowboarding and have fun. <a href="http://ikennd.ac/blog/2012/05/how-to-win-at-cycling-for-fun/">In May</a>, I talked about how I&#8217;d rekindled a love of mountain biking that I had before I moved to Sweden.</p>

<p>Soon after that, my fiancée and I decided to take our mountain bikes on a planned summer trip to the French Alps. I&#8217;d been saving for a new bike for a couple of months, and ended up going into crunch mode to try and get it before we left. I was successful, and a couple of weeks ago we set off to France with my shiny new yellow bike strapped to the back!</p>

<p><a href="http://500px.com/photo/9046240"><img class="center" src="http://pcdn.500px.net/9046240/265406eebf171bc3fc0a4c4a916ada314c40e499/4.jpg"></a></p>

<p style="text-align:center;"> <em>It didn&#8217;t stay this shiny for long!</em></p>

<p><a href="http://500px.com/photo/10664333"><img class="center" src="http://pcdn.500px.net/10664333/bb3af8f7057667899b7d241ecc6304e2ca5c0a10/4.jpg"></a></p>

<p style="text-align:center;"> <em>2,400km each way. Totally worth it!</em></p>

<p>What greeted us after over 24 hours of driving over two days was, well, stunning.</p>

<p><a href="http://500px.com/photo/10662733"><img class="center" src="http://pcdn.500px.net/10662733/16af9fe2d4c9bed23dfb20784565235517298c30/4.jpg"></a></p>

<p style="text-align:center;"> <em>Beats flat old Sweden any day.</em></p>

<h2>Les 2 Alpes</h2>

<p>Some of the ski resorts turn into mountain biking parks during the summer, and we were lucky enough to have one within a couple of hours of where we were staying. The general idea is that you rock up to the resort, pay for a lift pass and you get to fly down the fun descents while having lifts escort you and your bike bike up to the top again.</p>

<p>We ended up spending two days at Les 2 Alpes, which gave some of the most awesome bike riding I&#8217;ve experienced. It was a <em>lot</em> more technical than I was expecting, and on one of the routes were were thinking &#8220;This is a <em>green</em> run?!&#8221; a lot of the time.</p>

<p><a href="http://500px.com/photo/10662747"><img class="center" src="http://pcdn.500px.net/10662747/e54d7f19a106e03d6497d33d494098cbc46af15e/4.jpg"></a></p>

<p style="text-align:center;"> <em>As I&#8217;m helpfully pointing out, you can see some of the lower courses carving their way down the opposite mountain.</em></p>

<p><a href="http://500px.com/photo/10662759"><img class="center" src="http://pcdn.500px.net/10662759/666f45b692b39fe1d583c1ba77f2cb472cc6b1cb/4.jpg"></a></p>

<p style="text-align:center;"> <em>A rest stop halfway down one of the more difficult &#8220;green&#8221; runs.</em></p>

<p><a href="http://500px.com/photo/10662777"><img class="center" src="http://pcdn.500px.net/10662777/769b83e12e696c1c2ad4c5875dd66f11498330f7/4.jpg"></a></p>

<p style="text-align:center;"> <em>It sucks to have to stop to adjust stuff, but at least there&#8217;s a nice view while you do it!</em></p>

<p>I also took my new GoPro camera with me, and we had fun attaching the camera to various bits of our bikes and ourselves. I&#8217;m really pleased with the result!</p>

<iframe width="853" height="480" src="http://www.youtube.com/embed/EAUM051wu3Y?rel=0" frameborder="0" allowfullscreen></iframe>


<p>If you&#8217;re interested in a less editied version, here&#8217;s a complete run down the shorter green route at Les 2 Alpes, <em>Vallée Blanche</em>. Warning: There&#8217;s some horrible noise from my brakes in this video, which is discussed below!</p>

<iframe width="853" height="480" src="http://www.youtube.com/embed/dxMuzM2qnIk?rel=0" frameborder="0" allowfullscreen></iframe>


<h2>Casualties</h2>

<p>Unfortunately, everything has a weakest link. Much like a lower-end MacBook Pro might be held back by a crappy graphics card, my bike&#8217;s weakest stock component is widely known to be its brakes. Keeping a larger-framed gentleman such as myself in check down mountainsides generates a <em>lot</em> of heat, and two days worth of downhill work caused my brakes to start shrieking in pain, vibrating at the exact frequency to send a horrible resonance through my whole bike.</p>

<p><a href="http://500px.com/photo/10662767"><img class="center" src="http://pcdn.500px.net/10662767/ea81d96aa0a115e9d52d6a9c8fc74128909e8d9f/4.jpg"></a></p>

<p style="text-align:center;"> <em>A day&#8217;s work of braking causes heat discolouration on my bike&#8217;s brake discs.</em></p>

<p>This is a well-known problem with the brakes (Avid Elixir 7) my bike was kitted out with from the factory, and while there are elaborate ways people have found to fix (or at least mitigate) it, I decided that I&#8217;d rather replace them entirely than have a set of brakes that I&#8217;d never be 100% confident in.</p>

<p>Thankfully, <em>un</em>like a MacBook Pro, upgrading components on a bike is fairly simple, and I fitted some beefy Shimano XT brakes to mine when I got back to Sweden. These bad boys are well known to be tough, and even have heatsinks on the brake pads to help dissipate heat better.</p>

<h2>Wait, there was an original goal?</h2>

<p>Right! Snowboarding. The original plan was to get fit enough for snowboarding. I&#8217;ve already cycled over 550km this year and I&#8217;m aiming to hit 1,000km before the Swedish winter makes cycling too cold and/or dangerous to do. I genuinely feel a lot fitter already and think I&#8217;ll be physically fine when I hit the slopes without wheels.</p>

<p>As always, you can follow my efforts <a href="http://app.strava.com/athletes/401933">on Strava</a> as I slowly make my way towards my goal.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Making your Unit Tests AWESOME]]></title>
    <link href="http://ikennd.ac//blog/2012/05/making-your-unit-tests-awesome/"/>
    <updated>2012-05-22T18:15:00+02:00</updated>
    <id>http://ikennd.ac//blog/2012/05/making-your-unit-tests-awesome</id>
    <content type="html"><![CDATA[<p>This blog has had far too much content about cycling and getting fit and other boring stuff like that. It&#8217;s time to return the blog to it&#8217;s roots — doing dumb stuff with computers!</p>

<p>I recently added some unit tests to <a href="https://github.com/spotify/cocoalibspotify">CocoaLibSpotify</a>, the Objective-C Spotify framework I&#8217;m responsible for. I&#8217;m new to using tests, and the benefits have been great — I&#8217;m somewhat a convert to test-driven development now. However, this post isn&#8217;t yet another essay on TDD — it&#8217;s about how to make your testing AWESOME.</p>

<p>On a recent hackday, I took the Mac mini that builds CocoaLibSpotify and runs the unit tests and gave it a slightly more… visual indicator on the test results.</p>

<p><a href="http://500px.com/photo/7840881"><img class="center" src="http://pcdn.500px.net/7840881/202d5d2e2e3a53050e0c977b1abbc9dfae181793/4.jpg"></a></p>

<p style="text-align:center;"> <em>Yellow = running tests, green = all passed, red = one more more failed.</em></p>

<p>To accomplish this, I made a simpler version of my <a href="http://ikennd.ac/blog/2011/10/arduino-dioder-part-three/">previous project</a> to control four individual RGB LED strips. The simplified unit uses an Arduino Uno instead of a Mega2560, and only has two channels instead of four (only one of which is used in this project).</p>

<p><a href="http://500px.com/photo/7840903"><img class="center" src="http://pcdn.500px.net/7840903/7b0e4b152b896ade6775bded0935b7568c04b1e5/4.jpg"></a></p>

<p style="text-align:center;"> <em>The completed hardware - running wires underneath the board makes it much neater!</em></p>

<p>Once the hardware was up-and-running, I made a <a href="https://github.com/iKenndac/Arduino-Dioder-Playground/commit/ad1f02da6f13099718d813353887acec3132618e">slightly modified</a> version of the control software to go on the Arduino (since the Uno has different PWM pins to the Mega2560) and was ready to go! At this point, the unit is compatible with all of the <a href="https://github.com/iKenndac/Arduino-Dioder-Playground">previous code</a> I&#8217;ve written for sending colours, except only channels 1 and 2 do anything.</p>

<p>Next, we get a strip of thin plastic and make a loop roughly the size of the Mac mini&#8217;s base, stick a <a href="http://www.ikea.com/se/sv/catalog/products/00191735/">flexible LED strip</a> to it and voilà! One glowing Mac mini!</p>

<p><a href="http://500px.com/photo/7840897"><img class="center" src="http://pcdn.500px.net/7840897/77b4e1cccea73713ed5ab6e3a6db0d6e09905a41/4.jpg"></a></p>

<p><a href="http://500px.com/photo/7840885"><img class="center" src="http://pcdn.500px.net/7840885/94dbe9e3ea37c71222017dab775e6a14199f4415/4.jpg"></a></p>

<p><a href="http://500px.com/photo/7840892"><img class="center" src="http://pcdn.500px.net/7840892/131b5d03bccf210273523585e2a5fcbe679cad3c/4.jpg"></a></p>

<h2>Linking to Unit Tests</h2>

<p>Since this was a hackday, the rest of the project is slightly… slap-dash.</p>

<p>First, I wrote a stupid simple Ruby/Sinatra application that provides a REST API over HTTP, allowing you to push colours with a standard HTTP GET request:</p>

<p><code>http://localhost:4567/push-color?red=0&amp;green=255&amp;blue=0</code></p>

<p>The entirety of the code is below in its horrible, hardcoded, fragile glory. It&#8217;s worth noting that the Uno uses exactly the same protocol as the Mega, so it still needs to be given four colours even though it only supports two.</p>

<figure class='code'><figcaption><span>ArduioderHTTP.rb  </span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
<span class='line-number'>34</span>
<span class='line-number'>35</span>
<span class='line-number'>36</span>
<span class='line-number'>37</span>
<span class='line-number'>38</span>
<span class='line-number'>39</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="nb">require</span> <span class="s1">&#39;sinatra&#39;</span>
</span><span class='line'><span class="nb">require</span> <span class="s1">&#39;serialport&#39;</span>
</span><span class='line'><span class="nb">require</span> <span class="s1">&#39;json&#39;</span>
</span><span class='line'>
</span><span class='line'><span class="n">port</span> <span class="o">=</span> <span class="no">SerialPort</span><span class="o">.</span><span class="n">new</span><span class="p">(</span><span class="s2">&quot;/dev/tty.usbmodemfa131&quot;</span><span class="p">,</span> <span class="mi">57600</span><span class="p">)</span>
</span><span class='line'>
</span><span class='line'><span class="n">get</span> <span class="s1">&#39;/push-color&#39;</span> <span class="k">do</span>
</span><span class='line'>
</span><span class='line'>  <span class="c1"># Push one colour to each channel</span>
</span><span class='line'>  <span class="n">red</span> <span class="o">=</span> <span class="n">params</span><span class="o">[</span><span class="ss">:red</span><span class="o">].</span><span class="n">to_i</span>
</span><span class='line'>  <span class="n">green</span> <span class="o">=</span> <span class="n">params</span><span class="o">[</span><span class="ss">:green</span><span class="o">].</span><span class="n">to_i</span>
</span><span class='line'>  <span class="n">blue</span> <span class="o">=</span> <span class="n">params</span><span class="o">[</span><span class="ss">:blue</span><span class="o">].</span><span class="n">to_i</span>
</span><span class='line'>
</span><span class='line'>  <span class="n">message</span> <span class="o">=</span> <span class="nb">Array</span><span class="o">.</span><span class="n">new</span><span class="p">(</span><span class="mi">15</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span>
</span><span class='line'>  <span class="n">message</span><span class="o">[</span><span class="mi">0</span><span class="o">]</span> <span class="o">=</span> <span class="mh">0xBA</span>
</span><span class='line'>  <span class="n">message</span><span class="o">[</span><span class="mi">1</span><span class="o">]</span> <span class="o">=</span> <span class="mh">0xBE</span>
</span><span class='line'>  <span class="n">message</span><span class="o">[</span><span class="mi">2</span><span class="o">]</span> <span class="o">=</span> <span class="n">green</span>
</span><span class='line'>  <span class="n">message</span><span class="o">[</span><span class="mi">3</span><span class="o">]</span> <span class="o">=</span> <span class="n">blue</span>
</span><span class='line'>  <span class="n">message</span><span class="o">[</span><span class="mi">4</span><span class="o">]</span> <span class="o">=</span> <span class="n">red</span>
</span><span class='line'>  <span class="n">message</span><span class="o">[</span><span class="mi">5</span><span class="o">]</span> <span class="o">=</span> <span class="n">green</span>
</span><span class='line'>  <span class="n">message</span><span class="o">[</span><span class="mi">6</span><span class="o">]</span> <span class="o">=</span> <span class="n">blue</span>
</span><span class='line'>  <span class="n">message</span><span class="o">[</span><span class="mi">7</span><span class="o">]</span> <span class="o">=</span> <span class="n">red</span>
</span><span class='line'>  <span class="n">message</span><span class="o">[</span><span class="mi">8</span><span class="o">]</span> <span class="o">=</span> <span class="n">green</span>
</span><span class='line'>  <span class="n">message</span><span class="o">[</span><span class="mi">9</span><span class="o">]</span> <span class="o">=</span> <span class="n">blue</span>
</span><span class='line'>  <span class="n">message</span><span class="o">[</span><span class="mi">10</span><span class="o">]</span> <span class="o">=</span> <span class="n">red</span>
</span><span class='line'>  <span class="n">message</span><span class="o">[</span><span class="mi">11</span><span class="o">]</span> <span class="o">=</span> <span class="n">green</span>
</span><span class='line'>  <span class="n">message</span><span class="o">[</span><span class="mi">12</span><span class="o">]</span> <span class="o">=</span> <span class="n">blue</span>
</span><span class='line'>  <span class="n">message</span><span class="o">[</span><span class="mi">13</span><span class="o">]</span> <span class="o">=</span> <span class="n">red</span>
</span><span class='line'>  <span class="n">message</span><span class="o">[</span><span class="mi">14</span><span class="o">]</span> <span class="o">=</span> <span class="mi">0</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">for</span> <span class="n">currentIndex</span> <span class="k">in</span> <span class="mi">2</span><span class="o">.</span><span class="n">.</span><span class="mi">13</span>
</span><span class='line'>      <span class="n">message</span><span class="o">[</span><span class="mi">14</span><span class="o">]</span> <span class="o">=</span> <span class="n">message</span><span class="o">[</span><span class="mi">14</span><span class="o">]</span> <span class="o">^</span> <span class="n">message</span><span class="o">[</span><span class="n">currentIndex</span><span class="o">]</span>
</span><span class='line'>  <span class="k">end</span>
</span><span class='line'>
</span><span class='line'>  <span class="n">port</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">message</span><span class="o">.</span><span class="n">pack</span><span class="p">(</span><span class="s1">&#39;c*&#39;</span><span class="p">))</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">return</span> <span class="s2">&quot;&lt;body style=</span><span class="se">\&quot;</span><span class="s2">background-color:rgb(</span><span class="si">#{</span><span class="n">red</span><span class="si">}</span><span class="s2">, </span><span class="si">#{</span><span class="n">green</span><span class="si">}</span><span class="s2">, </span><span class="si">#{</span><span class="n">blue</span><span class="si">}</span><span class="s2">)</span><span class="se">\&quot;</span><span class="s2">&gt;</span><span class="si">#{</span><span class="n">message</span><span class="o">.</span><span class="n">to_s</span><span class="si">}</span><span class="s2">&lt;/body&gt;&quot;</span>
</span><span class='line'>
</span><span class='line'><span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>


<p>Next, continuing the trend of implementing this in the worst way possible, I added HTTP requests directly into the unit test code in CocoaLibSpotify. If you start the tests with the command-line parameter <code>-StatusColorServer localhost:4567</code> it&#8217;ll make HTTP requests to the given server:</p>

<figure class='code'> <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
</pre></td><td class='code'><pre><code class='objc'><span class='line'><span class="o">-</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span><span class="nl">pushColorToStatusServer:</span><span class="p">(</span><span class="n">UIColor</span> <span class="o">*</span><span class="p">)</span><span class="n">color</span> <span class="p">{</span>
</span><span class='line'>  
</span><span class='line'>  <span class="n">NSString</span> <span class="o">*</span><span class="n">statusServerAddress</span> <span class="o">=</span> <span class="p">[[</span><span class="n">NSUserDefaults</span> <span class="n">standardUserDefaults</span><span class="p">]</span> <span class="nl">stringForKey:</span><span class="n">kTestStatusServerUserDefaultsKey</span><span class="p">];</span>
</span><span class='line'>  <span class="k">if</span> <span class="p">(</span><span class="n">statusServerAddress</span><span class="p">.</span><span class="n">length</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="k">return</span><span class="p">;</span>
</span><span class='line'>  
</span><span class='line'>  <span class="n">CGFloat</span> <span class="n">red</span> <span class="o">=</span> <span class="mf">0.0</span><span class="p">;</span>
</span><span class='line'>  <span class="n">CGFloat</span> <span class="n">green</span> <span class="o">=</span> <span class="mf">0.0</span><span class="p">;</span>
</span><span class='line'>  <span class="n">CGFloat</span> <span class="n">blue</span> <span class="o">=</span> <span class="mf">0.0</span><span class="p">;</span>
</span><span class='line'>  
</span><span class='line'>  <span class="p">[</span><span class="n">color</span> <span class="nl">getRed:</span><span class="o">&amp;</span><span class="n">red</span> <span class="nl">green:</span><span class="o">&amp;</span><span class="n">green</span> <span class="nl">blue:</span><span class="o">&amp;</span><span class="n">blue</span> <span class="nl">alpha:</span><span class="nb">NULL</span><span class="p">];</span>
</span><span class='line'>  
</span><span class='line'>  <span class="n">NSString</span> <span class="o">*</span><span class="n">requestUrlString</span> <span class="o">=</span> <span class="p">[</span><span class="n">NSString</span> <span class="nl">stringWithFormat:</span><span class="s">@&quot;http://%@/push-color?red=%lu&amp;green=%lu&amp;blue=%lu&quot;</span><span class="p">,</span>
</span><span class='line'>                                <span class="n">statusServerAddress</span><span class="p">,</span>
</span><span class='line'>                                <span class="p">(</span><span class="n">NSUInteger</span><span class="p">)</span><span class="n">red</span> <span class="o">*</span> <span class="mi">255</span><span class="p">,</span>
</span><span class='line'>                                <span class="p">(</span><span class="n">NSUInteger</span><span class="p">)</span><span class="n">green</span> <span class="o">*</span> <span class="mi">255</span><span class="p">,</span>
</span><span class='line'>                                <span class="p">(</span><span class="n">NSUInteger</span><span class="p">)</span><span class="n">blue</span> <span class="o">*</span> <span class="mi">255</span><span class="p">];</span>
</span><span class='line'>  
</span><span class='line'>  <span class="n">NSURL</span> <span class="o">*</span><span class="n">requestUrl</span> <span class="o">=</span> <span class="p">[</span><span class="n">NSURL</span> <span class="nl">URLWithString:</span><span class="n">requestUrlString</span><span class="p">];</span>                         
</span><span class='line'>  <span class="n">NSURLRequest</span> <span class="o">*</span><span class="n">request</span> <span class="o">=</span> <span class="p">[</span><span class="n">NSURLRequest</span> <span class="nl">requestWithURL:</span><span class="n">requestUrl</span>
</span><span class='line'>                                           <span class="nl">cachePolicy:</span><span class="n">NSURLRequestReloadIgnoringLocalAndRemoteCacheData</span>
</span><span class='line'>                                       <span class="nl">timeoutInterval:</span><span class="mf">1.0</span><span class="p">];</span>
</span><span class='line'>  
</span><span class='line'>  <span class="p">[</span><span class="n">NSURLConnection</span> <span class="nl">sendSynchronousRequest:</span><span class="n">request</span>
</span><span class='line'>                        <span class="nl">returningResponse:</span><span class="nb">nil</span>
</span><span class='line'>                                    <span class="nl">error:</span><span class="nb">nil</span><span class="p">];</span>
</span><span class='line'>  
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>And that, my friends, is it! The unit tests set the colour to yellow when it starts the tests, then red or green depending on the outcome. Don&#8217;t forget to put your IP address on the company IRC so your colleagues can blink the lights all day long!</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[How to Win at Cycling For Fun]]></title>
    <link href="http://ikennd.ac//blog/2012/05/how-to-win-at-cycling-for-fun/"/>
    <updated>2012-05-19T18:00:00+02:00</updated>
    <id>http://ikennd.ac//blog/2012/05/how-to-win-at-cycling-for-fun</id>
    <content type="html"><![CDATA[<p>A while ago, I <a href="http://ikennd.ac/blog/2012/03/public-shaming-the-only-way/">publicly announced</a> that I was going to get my ass into gear and get fit enough to go snowboarding next winter. I&#8217;m happy to say that after ten weeks (<em>ish</em>), I&#8217;m now stronger, fitter, much better at recovering after tough hill climbs on my bike and… exactly that same weight as before. Perhaps celebrating a bike ride with a steak each time isn&#8217;t the right approach.</p>

<p>This wasn&#8217;t the original plan — I was going to get a FitBit and use the Personal Trainer feature to slowly build up the amount of walking and exercise I do to improve fitness. I did get a FitBit and while I really enjoy having it, my use for it now is simply to motivate me to walk where before I might take the lift or an escalator.</p>

<p>What&#8217;s happened is that a side-note in my original blog post (&#8221;<em>…as well as trying my hardest to cycle more.</em>&#8221;) has become a rekindled love of mine — I&#8217;m cycling multiple times a week and am having a ton of fun doing it, almost to the point where I forgot about the original plan to go snowboarding!</p>

<h2>Tips: Cycling For Fun</h2>

<p><a href="http://500px.com/photo/7714503"><img class="center" src="http://ikennd.ac/pictures/cycling/cycling-wide.jpg"></a></p>

<h3>Bike</h3>

<p>Try to match your bike to your terrain as much as you can. Or, rather — match where you ride to the bike you have. Mountain bikes do have more versatility in that you can ride one on the road much better than you can ride a road bike on forest trails, though. A few tips if you&#8217;re looking to buy a bike:</p>

<ul>
<li><p>Spend as much money as you can.</p></li>
<li><p>Don&#8217;t get a full-suspension bike that costs less than £1,000/$1,500. There&#8217;s no hard-and-fast rule, but every full-suspension bike I&#8217;ve seen for less than £1,000 has suffered for simply not having the budget available for decent components (the rear shock absorber on my bike retails for about £300 and is considered &#8220;middle of the range&#8221;). The result is &#8220;pedal bob&#8221; — a lot the work you put into pedalling ends up bouncing you up and down on the suspension instead of propelling you forwards.</p></li>
<li><p>Often, top-end components in one category are better than bottom-end components in the next category up. Cable disc brakes vs. hydraulic disc brakes, mechanically sprung forks vs. air sprung forks, etc.</p></li>
<li><p>Make sure your bike is properly set up for your size and weight, including tyre pressures, suspension setup, etc.</p></li>
<li><p>Find a <em>good</em> local bike shop to help you, and you&#8217;ll be rewarded in spades. See my <a href="http://ikennd.ac/blog/2012/05/the-bike-shop-the-birthday-and-the-averted-disaster/">recent story</a> about my fiancée&#8217;s birthday for a good example.</p></li>
<li><p>Most importantly: <strong>DO NOT BABY YOUR BIKE</strong>. Good bikes are <em>rewarding</em> when they take a pounding, get stupidly muddy and wet, etc. Plus, &#8220;So, I made it all the way to the bottom of the trail only to have my brakes not work right away because they were so covered in mud — I was squeezing so hard on the brakes that when the pads cleaned the discs they locked and I went right over the handlebars!&#8221; is a <em>much</em> more awesome story than &#8220;I went slowly, but at least my bike was clean!&#8221;</p></li>
</ul>


<p><a href="http://500px.com/photo/5883478"><img class="center" src="http://pcdn.500px.net/5883478/f67942a5693951e4ad65e504002d7fc0e8955e01/4.jpg"></a></p>

<p style="text-align:center;"> <em>My friend Tim on a cycling trip to Germany. No pictures of me here since I had the camera, unfortunately.</em></p>

<h3>Clothing</h3>

<p>Cycling can be a literal pain in the ass — I wear a pair of padded lycra cycling shorts every single time I go out on my bike, and a skintight base layer on top to control heat and sweat. Since I&#8217;m well aware nobody wants to see a guy of my figure in stuff like that, I wear a pair of baggy shorts and a t-shirt over the top.</p>

<p>In addition, make sure you have a decent pair of gloves and a comfy helmet.</p>

<h3>Equipment</h3>

<p>I cycle with a decent backpack that has an &#8220;air circulating&#8221; back — there&#8217;s a plastic board in the pack that keeps it away from your back, resulting in a much less sweaty time. Inside that backpack I have:</p>

<ul>
<li>A CamelBak holding 1.5-2 litres of water for continual refreshment.</li>
<li>A bike multi-tool.</li>
<li>A spare inner tube.</li>
<li>A puncture repair kit.</li>
<li>A bike lock.</li>
<li>A pump.</li>
</ul>


<p>On longer journeys, or trips away from home, I also add:</p>

<ul>
<li>A spare chain.</li>
<li>More inner tubes.</li>
</ul>


<p>Also, my bike has a decent light (Light &amp; Motion Seca 700) and a water bottle permanently attached, as well as my GPS, bell, etc.</p>

<h3>Base Route</h3>

<p>I have a 10km loop that I can do without feeling too tired. Over the past few weeks I&#8217;ve gotten faster and less tired around it, and it&#8217;s great to see my gradual improvement over time.</p>

<p align="center"><iframe height='405' width='590' frameborder='0' allowtransparency='true' scrolling='no' src='http://app.strava.com/runs/8677366/embed/332d9638814a1a82d97639cf6f692de7b464b8db'></iframe></p>


<h3>Data</h3>

<p>These posts are going in a category called &#8220;A Nerd Outdoors&#8221; for a reason! I now have a <a href="http://www.garmin.com/montana">Garmin Montana</a> strapped to my bike&#8217;s handlebars, which is linked to a cadence sensor for keeping track of how fast I&#8217;m pedalling.</p>

<p><a href="http://500px.com/photo/7738070"><img class="center" src="http://pcdn.500px.net/7738070/9825b53711f1b925af9f0a20f1fd835c1962002c/4.jpg" title="My Bike's &#34;Dashboard&#34;" alt="My Bike's &#34;Dashboard&#34;"></a></p>

<p style="text-align:center;"> <em>My bike&#8217;s &#8220;dashboard&#8221;</em></p>

<p>The Montana is perhaps overkill for this use, and you can get cheaper devices — even ones specifically designed for bike use — if you&#8217;re not interested in all of the features the Montana has.</p>

<p>Once I have this data, I upload it to <a href="http://wwww.strava.com/">Strava</a>, an <em>excellent</em> online service for keeping track of cycling which lets me compare how I&#8217;m doing with my friends and see my progress and statistics. For example, since April I:</p>

<ul>
<li>Have cycled 202km.</li>
<li>Am averaging 37km/week.</li>
<li>Am averaging 2 hours, 30 minutes on the bike a week.</li>
</ul>


<p>This is an example or a recent ride of mine:</p>

<p align="center"><iframe height='405' width='590' frameborder='0' allowtransparency='true' scrolling='no' src='http://app.strava.com/runs/8794036/embed/5a222d1d71e1017733388a37bb774f97de29e973'></iframe></p>


<p>I&#8217;m <a href="http://www.strava.com/athletes/ikenndac/">iKenndac</a> on Strava if you sign up!</p>

<h3>Maps</h3>

<p>I&#8217;ve already written <a href="http://ikennd.ac/blog/2012/04/high-tech-meets-low-tech-gps/">at length</a> about the advantages of having decent maps for hiking/cycling, but one more use has cropped up: Quite often I&#8217;ll be cycling along and see a path disappearing off into a forest and I&#8217;ll think &#8220;That looks fun, I wonder where that goes?&#8221;. Now I make a mental note of where it starts, and once I get home I can look on the map and see if I can fit it into my next ride.</p>

<p>This has already come up trumps — one of my favourite sections of trail in the area was found with this method. The entrance to it is a tiny, root-covered path with a &#8220;No horses&#8221; sign on it, but it opens out to a fantastically fun, fast, and sweeping section of trail that you can see me on a bit further up the page.</p>

<h3>Move To Sweden</h3>

<p>Well, this last one might be a bit far-fetched, but <em>man</em> is it awesome for cycling here. I live 13km from the centre of the capital city, and I have a nature reserve full of lakes and awesome cycling trails right on my doorstep. A typical rest stop looks like this:</p>

<p><a href="http://500px.com/photo/7740079"><img class="center" src="http://pcdn.500px.net/7740079/4292d49e61123fd6c8ce51f4a0e14bc57e06cb9e/4.jpg"></a></p>

<p>I guess I should get back out there!</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[The Bike Shop, the Birthday and the Averted Disaster]]></title>
    <link href="http://ikennd.ac//blog/2012/05/the-bike-shop-the-birthday-and-the-averted-disaster/"/>
    <updated>2012-05-06T23:30:00+02:00</updated>
    <id>http://ikennd.ac//blog/2012/05/the-bike-shop-the-birthday-and-the-averted-disaster</id>
    <content type="html"><![CDATA[<p>I&#8217;m a country boy by heart — I grew up in a hamlet in Derbyshire with only 13 houses in it, then moved Down South to Hertfordshire and after a couple of moves, ended up in a small village in Bedfordshire that was surrounded by fields and trees.</p>

<p>Moving this close to a city — not to mention one in a foreign country — has taken some getting used to. Thankfully Stockholm is very small as cities go, and it&#8217;s a beautiful city at that. I&#8217;ve grown to love it here, and am finally starting to figure out that although Stockholm is small, it <em>is</em> the capital city of Sweden, so it&#8217;s <em>very</em> likely that if I want something I can find it nearby. However, most of the stores I&#8217;ve found are big-city style fancy shops — everything is expansive and the staff don&#8217;t know squat.</p>

<p><em>Finally</em> I found a place that&#8217;s different, and just in time!</p>

<h3>The Bike Shop</h3>

<p>It&#8217;s a rainy March afternoon and I&#8217;m scuttling through Södermalm (a district of Stockholm), cursing myself for not bringing a coat to work. I&#8217;d just received some new parts for my bike from a <a href="http://www.chainreactioncycles.com">big box retailer</a> and realised that I needed a specific tool fit them. I found a close-ish bike shop that looked halfway decent, and headed out in hope they&#8217;d even heard of a HollowTech II BB Tool, let alone have it in stock.</p>

<p>I opened the door to the small looking-shop and stood there in shock. And wet. But mostly in shock — this place was <em>nirvana</em>. To the right, the walls were jam-packed full of bike parts and accessories literally up to the ceiling. To the left are <em>hundreds</em> of bikes of all kinds — from the road bikes that most bike shops I&#8217;ve tried specialise in to the mountain bikes I love and crave parts and expertise in.</p>

<p>&#8220;<em>Do you have a HollowTech II BB tool in stock?</em>&#8221; I ask, with not much hope.</p>

<p>&#8220;<em>Well, be don&#8217;t have the Park one in, but we do have this other one that&#8217;s just as good,</em>&#8221; the guy behind the counter says while rummaging through shelves before producing the tool I need.</p>

<p>Well, this is unexpected. In a distant, grey corner of Södermalm I&#8217;ve stumbled on what appears to be the perfect bike shop — packed to bursting with parts and tools for <em>my</em> bike, not those damn hipster things, at a reasonable price and, most importantly, with staff who seem to be knowledgable at the task at hand. I&#8217;m in love!</p>

<h3>The Birthday</h3>

<p>&#8220;<em>Is there anything else I can help you with?</em>&#8221;</p>

<p>I pause for a moment to think. I <em>had</em> considered ordering this from a big retailer in the UK, but for stuff this big I <em>really</em> prefer getting it from a local place, but had come up fruitless so far.</p>

<p>&#8220;<em>How much would a <a href="http://www.specialized.com/gb/gb/bc/SBCProduct.jsp?spid=62136&amp;scid=1100&amp;scname=Mountain">Specialized Myka FSR Comp</a> in &#8216;Small&#8217; be? I&#8217;m buying one for my fiancé for her 25th birthday.</em>&#8221;</p>

<p>&#8220;<em>We don&#8217;t have it in stock here, but we could have one in a week or so,</em>&#8221; he said, before telling me the price. It&#8217;s a buttload of money, but actually worked out cheaper than any UK prices I&#8217;d found so far.</p>

<p>&#8220;<em>Great!</em>&#8221; I say. &#8221;<em>I&#8217;ll have one of those, too.</em>&#8221;</p>

<p>He looked slightly surprised at selling a bike so easily, and started taking my details.</p>

<p style="text-align:center;"> <em>~ One week later ~</em></p>

<p>After getting lost twice and likely scaring my friend Rick half to death — I&#8217;m so worried Alana will see through my weak excuse for going into Stockholm without her, my driving is less than ideal — we arrive back at Södermalm to pick up the bike.</p>

<p>To my surprise, the same guy is there again.</p>

<p>&#8220;<em>I didn&#8217;t know how heavy your fiancé is, so I set up the suspension for the average sort of weight of someone that high. Once she gets the bike, you can come back and we&#8217;ll set it up properly for her, if you like.</em>&#8221; At this point I&#8217;m gazing over the wall of parts again, fairly sure I&#8217;ll never need any other bike shop ever again, but assure him I already have the tools to set the suspension up myself and thank him for putting the bike together so quickly (it&#8217;d only arrived the day before, but he was sympathetic to my cause) and was on my way.</p>

<p><img class="center" src="http://pcdn.500px.net/7347795/0cdb26eeb070aef9325ccb716395e0e797c30a4b/4.jpg"></p>

<p style="text-align:center;"> <em>Hey look, a bike! And Rick&#8217;s arm.</em></p>

<p style="text-align:center;"> <em>~ Two weeks later ~</em></p>

<p>&#8220;<em>Surprise!</em>&#8221;</p>

<h3>The Averted Disaster</h3>

<p>My fiancé loves her bike. It&#8217;s been living in my friend&#8217;s apartment since I picked it up, and as I look it over properly for the first time, my heart begins to sink. The rebound on the rear shock absorber is so slow it&#8217;s like it has no pressure in it — when you push the bike down onto its suspension, it takes a good thirty seconds to come up again. I check the pressure — it&#8217;s fine. However, the rebound adjuster seems to be stuck and I don&#8217;t know enough about how shock absorbers to fix it.</p>

<p>Me and my fiancé are driving back to Södermalm to be at the shop for opening time. We walk in to find the same guy yet again.</p>

<p>&#8220;<em>Hi, I picked this bike up a couple of weeks ago,</em>&#8221; I say, &#8221;<em>and I think there&#8217;s something wrong with it — look.</em>&#8221; I push the suspension down and show him the problem.</p>

<p>&#8220;<em>Oh, that&#8217;s not right!</em>&#8221; he says. &#8221;<em>Unfortunately if the shock is broken there&#8217;s nothing I can do until Monday — the supplier is closed at weekends.</em>&#8221;</p>

<p>My heart sinks. I&#8217;d spent so much time organising not just getting the bike in secret, but organising a bunch of her friends to contribute towards it and to take photos saying &#8216;Happy Birthday!&#8217; for a photo book to accompany it. I go pretty much silent, as is often the case when I get upset. All this effort for a broken gift!</p>

<p>&#8220;<em>Oh, it&#8217;s your birthday, right?</em>&#8221; he says, turning to my fiancé. &#8221;<em>I&#8217;m so sorry I ruined the surprise!</em>&#8221;</p>

<p>Cheered up slightly by the fact that he remembered my plan, I ask &#8221;<em>Is there any chance you could take it apart today to see if it&#8217;s just stuck or something?</em>&#8221; It&#8217;s a long shot, but I <em>really</em> want my fiancé to have a working bike on her birthday.</p>

<p>&#8220;<em>Of course!</em>&#8221; he says.</p>

<p>The drive back home is <em>silent</em>. I&#8217;m back to being grumpy about the whole thing, and my fiancé&#8217;s attempts at cheering me up aren&#8217;t really doing much. After a horrible fifteen minutes, we&#8217;re 200 metres from home and her phone rings. They&#8217;d fixed it! We turned around and drove back to the shop.</p>

<p style="text-align:center;"> <em>~Fifteen minutes later~</em></p>

<p>Back at the shop, it&#8217;s <em>packed</em>. There&#8217;s a queue out the door to be served by one of the two people working there, and when it&#8217;s our turn, the same guy I&#8217;d worked with this whole time (I really should learn his name!) explained that the rear shock had simply got stuck in the lowest position and when he&#8217;d taken it out of the bike&#8217;s frame and re-pressurised it, it&#8217;d popped right back into position and was working fine.</p>

<p>I turn slightly red, realising that that might&#8217;ve been my fault — I&#8217;d sat on the bike after picking it up, which was the equivalent of trying to support a tank with car suspension. Genuinely happy again, I thanked him for fixing the bike so quickly — especially when it was this busy — and started to leave.</p>

<p>&#8220;<em>Okay, let&#8217;s get this bike properly set up for you,</em>&#8221; he says to my fiancé and motions us to follow him as he carries the bike down a tiny staircase to the basement, which turns out to be a workshop at least as large as the shop upstairs! In the next twenty minutes he proceeds to set up the bike exactly for my fiancé, from the pressures in the suspension to the rebound rate and even cutting the seat post down a bit (she&#8217;s slightly… <em>vertically challenged</em>). We end up leaving the shop with a perfectly tuned bike and a free water bottle for our trouble.</p>

<p>This bike shop is the kind of local business I will <em>gladly</em> pay the slight price increase over big-box online retailers to. To recap:</p>

<ul>
<li><p>I dealt with the same person every time, who was technically knowledgable and remembered me and my plan over the month it all took place in.</p></li>
<li><p>When something went wrong, not only did he bend over backwards to help us out in what I imagine is the busiest time of the week for the store, he took the time to make sure the bike was perfectly set up in every way once the problem was fixed.</p></li>
</ul>


<p>I can&#8217;t remember the last time I&#8217;ve experienced customer service this good — they managed to turn having my fiancé&#8217;s gift broken on her birthday into two incredibly happy people. That place has me as a customer for life! Everyone should go to <a href="http://www.cykelspecialisten.com">Cykelspecialisten</a> on Långholmsgatan, Södermalm RIGHT NOW and buy LOTS OF BIKES.</p>

<p>I&#8217;ll have a Specialized StumpJumper FSR Comp EVO, please!</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Core Audio: AUGraph Basics in CocoaLibSpotify]]></title>
    <link href="http://ikennd.ac//blog/2012/04/augraph-basics-in-cocoalibspotify/"/>
    <updated>2012-04-24T13:31:00+02:00</updated>
    <id>http://ikennd.ac//blog/2012/04/augraph-basics-in-cocoalibspotify</id>
    <content type="html"><![CDATA[<p>Core Audio is one of the trickier frameworks in the Mac and iOS arsenal, but is incredibly powerful once you manage to tame it. I&#8217;ve been spending some time at Spotify getting to grips with it, and have released some Core Audio code as part of the open-source <a href="https://github.com/spotify/cocoalibspotify">CocoaLibSpotify</a> library.</p>

<p>CocoaLibSpotify is an Objective-C wrapper around the libSpotify library, which is a C API providing access to Spotify&#8217;s service for music streaming, playlists, etc etc. A more advanced example of what you can do with (Cocoa)LibSpotify is my open-source <a href="https://github.com/iKenndac/Viva">Viva</a> Spotify client.</p>

<p>CocoaLibSpotify contains a class called <code>SPCoreAudioController</code> that deals with getting audio data from libSpotify, through a Core Audio <code>AUGraph</code> and to the system audio output. The class also provides an easy way of customising the graph, and this post discusses the basics of Core Audio, <code>AUGraph</code>, and customising <code>SPCoreAudioController</code> with a 10-band graphic equalizier.</p>

<p><strong>Note:</strong> While this post discusses Spotify technologies, I wrote this because I enjoy the topic at hand and thought it&#8217;d be nice to share. The opinions expressed here may not represent those of Spotify, etc etc.</p>

<h3>Push vs. Pull</h3>

<p>Core Audio and libSpotify have two opposing methods of dealing with audio data.</p>

<ul>
<li><p>libSpotify uses the &#8220;push&#8221; method, which basically means it says &#8220;Here is some audio data, you should play it!&#8221;</p></li>
<li><p>Core Audio uses the opposite &#8220;pull&#8221; method, which means it asks &#8220;I need to play some audio, can I have some?&#8221;</p></li>
</ul>


<p>This means that, unfortunately, we can&#8217;t simply hook libSpotify up to Core Audio and get playback happening. Instead, we need to store the audio provided by libSpotify into a buffer which we&#8217;ll then read from when Core Audio requests some audio data.</p>

<p>To solve this in an elegant manner, CocoaLibSpotify includes a <a href="http://en.wikipedia.org/wiki/Circular_buffer">ring buffer</a>, which is a special kind of buffer that allows data to be read and written to is without reallocating memory, which can be expensive.</p>

<h3>Audio Units and AUGraph</h3>

<p>Core Audio uses a concept of &#8220;units&#8221; when working with audio. Each unit carries out a single task, such as applying an effect or actually playing the audio. <code>AUGraph</code> then provides a way to chain Audio Units together, much like how an amplifier stack works in the physical world.</p>

<p>To simplify this for most use cases, CocoaLibSpotify includes a class called <code>SPCoreAudioController</code>, which implements an <code>AUGraph</code> with three nodes:</p>

<ul>
<li><p><strong>Converter</strong> Node: Takes audio as delivered from libSpotify from the ring buffer and converts it into the canonical format used by Core Audio.</p></li>
<li><p><strong>Mixer</strong> Node: Mixers are normally used to mix audio from multiple sources, but here it&#8217;s used simply to provide the ability to control volume separately from the system volume, since the audio output unit on iOS doesn&#8217;t provide volume control.</p></li>
<li><p><strong>Output</strong> Node: This node takes the completed audio and delivers it to the system&#8217;s default audio output.</p></li>
</ul>


<p>Once this is up-and-running, <code>SPCoreAudioController</code> is managing an audio chain that looks like this:</p>

<p><img class="center" src="http://ikennd.ac/pictures/augraph/SPCoreAudioControllerBasicGraph.png"></p>

<h3>Customising SPCoreAudioController</h3>

<p>If you want to customise audio playback, <code>SPCoreAudioController</code> includes a handy pair of methods that allow you to insert any <code>AUNode</code> you like into the <code>AUGraph</code> without having to manage the whole graph, making the chain look like this:</p>

<p><img class="center" src="http://ikennd.ac/pictures/augraph/SPCoreAudioControllerCustomGraph.png"></p>

<p>So, let&#8217;s provide an example that inserts a 10-band graphic EQ into the graph:</p>

<p><img class="center" src="http://ikennd.ac/pictures/augraph/SPCoreAudioControllerEQGraph.png"></p>

<p><strong>Note:</strong> The completed sample project can be found on GitHub <a href="https://github.com/iKenndac/SimplePlayer-with-EQ">here</a>.</p>

<p>First, create a new class subclassing <code>SPCoreAudioController</code> - the sample project calls it <code>EQCoreAudioController</code> - then override <code>-connectOutputBus:ofNode:toInputBus:ofNode:inGraph:error:</code>.</p>

<p>In this first example, set up a description of the EQ Audio Unit then have the graph add a node matching that description before getting a reference to the Audio Unit itself so we can set properties on it. Then, it initializes the Audio Unit and sets it to a 10-band EQ.</p>

<figure class='code'> <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
<span class='line-number'>34</span>
</pre></td><td class='code'><pre><code class='objc'><span class='line'><span class="k">@implementation</span> <span class="nc">EQCoreAudioController</span> <span class="p">{</span>
</span><span class='line'>    <span class="c1">// Keep the node and unit around so we can reference them anytime.</span>
</span><span class='line'>    <span class="n">AUNode</span> <span class="n">eqNode</span><span class="p">;</span>
</span><span class='line'>    <span class="n">AudioUnit</span> <span class="n">eqUnit</span><span class="p">;</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="o">-</span><span class="p">(</span><span class="kt">BOOL</span><span class="p">)</span><span class="nl">connectOutputBus:</span><span class="p">(</span><span class="n">UInt32</span><span class="p">)</span><span class="n">sourceOutputBusNumber</span>
</span><span class='line'>                 <span class="nl">ofNode:</span><span class="p">(</span><span class="n">AUNode</span><span class="p">)</span><span class="n">sourceNode</span>
</span><span class='line'>             <span class="nl">toInputBus:</span><span class="p">(</span><span class="n">UInt32</span><span class="p">)</span><span class="n">destinationInputBusNumber</span>
</span><span class='line'>                 <span class="nl">ofNode:</span><span class="p">(</span><span class="n">AUNode</span><span class="p">)</span><span class="n">destinationNode</span>
</span><span class='line'>                <span class="nl">inGraph:</span><span class="p">(</span><span class="n">AUGraph</span><span class="p">)</span><span class="n">graph</span>
</span><span class='line'>                  <span class="nl">error:</span><span class="p">(</span><span class="n">NSError</span> <span class="o">**</span><span class="p">)</span><span class="n">error</span> <span class="p">{</span>
</span><span class='line'>
</span><span class='line'>    <span class="c1">// A description for the EQ Device</span>
</span><span class='line'>    <span class="n">AudioComponentDescription</span> <span class="n">eqDescription</span><span class="p">;</span>
</span><span class='line'>    <span class="n">eqDescription</span><span class="p">.</span><span class="n">componentType</span> <span class="o">=</span> <span class="n">kAudioUnitType_Effect</span><span class="p">;</span>
</span><span class='line'>    <span class="n">eqDescription</span><span class="p">.</span><span class="n">componentSubType</span> <span class="o">=</span> <span class="n">kAudioUnitSubType_GraphicEQ</span><span class="p">;</span>
</span><span class='line'>    <span class="n">eqDescription</span><span class="p">.</span><span class="n">componentManufacturer</span> <span class="o">=</span> <span class="n">kAudioUnitManufacturer_Apple</span><span class="p">;</span>
</span><span class='line'>    <span class="n">eqDescription</span><span class="p">.</span><span class="n">componentFlags</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span><span class='line'>    <span class="n">eqDescription</span><span class="p">.</span><span class="n">componentFlagsMask</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'>    <span class="c1">// Add the EQ node to the AUGraph</span>
</span><span class='line'>    <span class="n">AUGraphAddNode</span><span class="p">(</span><span class="n">graph</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">eqDescription</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">eqNode</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'>    <span class="c1">// Get the Audio Unit from the node so we can set properties on it</span>
</span><span class='line'>    <span class="n">AUGraphNodeInfo</span><span class="p">(</span><span class="n">graph</span><span class="p">,</span> <span class="n">eqNode</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">eqUnit</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'>    <span class="c1">// Initialize the audio unit</span>
</span><span class='line'>    <span class="n">AudioUnitInitialize</span><span class="p">(</span><span class="n">eqUnit</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'>    <span class="c1">// Set EQ to 10-band</span>
</span><span class='line'>    <span class="n">AudioUnitSetParameter</span><span class="p">(</span><span class="n">eqUnit</span><span class="p">,</span> <span class="mi">10000</span><span class="p">,</span> <span class="n">kAudioUnitScope_Global</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mf">0.0</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'>    <span class="c1">//... continued in next code snippet.</span>
</span></code></pre></td></tr></table></div></figure>


<p>At this point, our EQ is set up and inserted into the audio controller&#8217;s graph. All that&#8217;s left to do now is hook it up to the provided source and destination nodes so audio gets piped through it:</p>

<figure class='code'> <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
</pre></td><td class='code'><pre><code class='objc'><span class='line'>    <span class="c1">// ... continued from previous code snippet.</span>
</span><span class='line'>
</span><span class='line'>    <span class="c1">// Connect the output of the provided audio source node to the input of our EQ.</span>
</span><span class='line'>    <span class="n">AUGraphConnectNodeInput</span><span class="p">(</span><span class="n">graph</span><span class="p">,</span> <span class="n">sourceNode</span><span class="p">,</span> <span class="n">sourceOutputBusNumber</span><span class="p">,</span> <span class="n">eqNode</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'>    <span class="c1">// Connect the output of our EQ to the input of the provided audio destination node.</span>
</span><span class='line'>    <span class="n">AUGraphConnectNodeInput</span><span class="p">(</span><span class="n">graph</span><span class="p">,</span> <span class="n">eqNode</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="n">destinationNode</span><span class="p">,</span> <span class="n">destinationInputBusNumber</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'>    <span class="k">return</span> <span class="n">YES</span><span class="p">;</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="k">@end</span>
</span></code></pre></td></tr></table></div></figure>


<p>That&#8217;s it! The EQ node is now inserted into the <code>AUGraph</code> managed by <code>SPCoreAudioController</code>, which now looks like this:</p>

<p><img class="center" src="http://ikennd.ac/pictures/augraph/SPCoreAudioControllerEQGraph.png"></p>

<p>It&#8217;s important to do cleanup as well so we don&#8217;t leak memory and cause problems. <code>SPCoreAudioController</code> provides <code>-disposeOfCustomNodesInGraph:</code> to be overridden for just this purpose:</p>

<figure class='code'> <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
</pre></td><td class='code'><pre><code class='objc'><span class='line'><span class="o">-</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span><span class="nl">disposeOfCustomNodesInGraph:</span><span class="p">(</span><span class="n">AUGraph</span><span class="p">)</span><span class="n">graph</span> <span class="p">{</span>
</span><span class='line'>
</span><span class='line'>    <span class="c1">// Shut down our unit.</span>
</span><span class='line'>    <span class="n">AudioUnitUninitialize</span><span class="p">(</span><span class="n">eqUnit</span><span class="p">);</span>
</span><span class='line'>    <span class="n">eqUnit</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'>    <span class="c1">// Remove the unit&#39;s node from the graph.</span>
</span><span class='line'>    <span class="n">AUGraphRemoveNode</span><span class="p">(</span><span class="n">graph</span><span class="p">,</span> <span class="n">eqNode</span><span class="p">);</span>
</span><span class='line'>    <span class="n">eqNode</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<h3>Finishing Up &amp; Adding UI</h3>

<p>Now we have an EQ inserted into our Core Audio graph, we need to control the levels! To do this, the sample project implements the following method in <code>EQCoreAudioController</code>, which applies up to ten band values.</p>

<figure class='code'> <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
</pre></td><td class='code'><pre><code class='objc'><span class='line'><span class="o">-</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span><span class="nl">applyBandsToEQ:</span><span class="p">(</span><span class="n">NSArray</span> <span class="o">*</span><span class="p">)</span><span class="n">tenBands</span> <span class="p">{</span>
</span><span class='line'>
</span><span class='line'>    <span class="k">if</span> <span class="p">(</span><span class="n">eqUnit</span> <span class="o">==</span> <span class="nb">NULL</span><span class="p">)</span> <span class="k">return</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'>    <span class="c1">// Loop through our bands and update them.</span>
</span><span class='line'>    <span class="k">for</span> <span class="p">(</span><span class="n">NSUInteger</span> <span class="n">bandIndex</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">bandIndex</span> <span class="o">&lt;</span> <span class="n">MIN</span><span class="p">(</span><span class="mi">10</span><span class="p">,</span> <span class="n">tenBands</span><span class="p">.</span><span class="n">count</span><span class="p">);</span> <span class="n">bandIndex</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>
</span><span class='line'>        <span class="n">Float32</span> <span class="n">bandValue</span> <span class="o">=</span> <span class="p">[[</span><span class="n">tenBands</span> <span class="nl">objectAtIndex:</span><span class="n">bandIndex</span><span class="p">]</span> <span class="n">floatValue</span><span class="p">];</span>
</span><span class='line'>        <span class="n">AudioUnitSetParameter</span><span class="p">(</span><span class="n">eqUnit</span><span class="p">,</span> <span class="n">bandIndex</span><span class="p">,</span> <span class="n">kAudioUnitScope_Global</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="n">bandValue</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>The sample project then has ten continuous vertical sliders all hooked up to different <code>IBOutlet</code>s but calling the same <code>IBAction</code>. It&#8217;s best to set your sliders to range between <code>-12.0</code> and <code>+12.0</code> (this is the range iTunes uses in its EQ) otherwise the distortion gets a bit unbearable!</p>

<figure class='code'> <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
</pre></td><td class='code'><pre><code class='objc'><span class='line'><span class="o">-</span><span class="p">(</span><span class="kt">IBAction</span><span class="p">)</span><span class="nl">eqSliderDidChange:</span><span class="p">(</span><span class="kt">id</span><span class="p">)</span><span class="n">sender</span> <span class="p">{</span>
</span><span class='line'>
</span><span class='line'>    <span class="n">NSMutableArray</span> <span class="o">*</span><span class="n">bands</span> <span class="o">=</span> <span class="p">[</span><span class="n">NSMutableArray</span> <span class="nl">arrayWithCapacity:</span><span class="mi">10</span><span class="p">];</span>
</span><span class='line'>
</span><span class='line'>    <span class="p">[</span><span class="n">bands</span> <span class="nl">addObject:</span><span class="p">[</span><span class="n">NSNumber</span> <span class="nl">numberWithFloat:</span><span class="n">self</span><span class="p">.</span><span class="n">eqSlider1</span><span class="p">.</span><span class="n">floatValue</span><span class="p">]];</span>
</span><span class='line'>    <span class="p">[</span><span class="n">bands</span> <span class="nl">addObject:</span><span class="p">[</span><span class="n">NSNumber</span> <span class="nl">numberWithFloat:</span><span class="n">self</span><span class="p">.</span><span class="n">eqSlider2</span><span class="p">.</span><span class="n">floatValue</span><span class="p">]];</span>
</span><span class='line'>    <span class="p">[</span><span class="n">bands</span> <span class="nl">addObject:</span><span class="p">[</span><span class="n">NSNumber</span> <span class="nl">numberWithFloat:</span><span class="n">self</span><span class="p">.</span><span class="n">eqSlider3</span><span class="p">.</span><span class="n">floatValue</span><span class="p">]];</span>
</span><span class='line'>    <span class="p">[</span><span class="n">bands</span> <span class="nl">addObject:</span><span class="p">[</span><span class="n">NSNumber</span> <span class="nl">numberWithFloat:</span><span class="n">self</span><span class="p">.</span><span class="n">eqSlider4</span><span class="p">.</span><span class="n">floatValue</span><span class="p">]];</span>
</span><span class='line'>    <span class="p">[</span><span class="n">bands</span> <span class="nl">addObject:</span><span class="p">[</span><span class="n">NSNumber</span> <span class="nl">numberWithFloat:</span><span class="n">self</span><span class="p">.</span><span class="n">eqSlider5</span><span class="p">.</span><span class="n">floatValue</span><span class="p">]];</span>
</span><span class='line'>    <span class="p">[</span><span class="n">bands</span> <span class="nl">addObject:</span><span class="p">[</span><span class="n">NSNumber</span> <span class="nl">numberWithFloat:</span><span class="n">self</span><span class="p">.</span><span class="n">eqSlider6</span><span class="p">.</span><span class="n">floatValue</span><span class="p">]];</span>
</span><span class='line'>    <span class="p">[</span><span class="n">bands</span> <span class="nl">addObject:</span><span class="p">[</span><span class="n">NSNumber</span> <span class="nl">numberWithFloat:</span><span class="n">self</span><span class="p">.</span><span class="n">eqSlider7</span><span class="p">.</span><span class="n">floatValue</span><span class="p">]];</span>
</span><span class='line'>    <span class="p">[</span><span class="n">bands</span> <span class="nl">addObject:</span><span class="p">[</span><span class="n">NSNumber</span> <span class="nl">numberWithFloat:</span><span class="n">self</span><span class="p">.</span><span class="n">eqSlider8</span><span class="p">.</span><span class="n">floatValue</span><span class="p">]];</span>
</span><span class='line'>    <span class="p">[</span><span class="n">bands</span> <span class="nl">addObject:</span><span class="p">[</span><span class="n">NSNumber</span> <span class="nl">numberWithFloat:</span><span class="n">self</span><span class="p">.</span><span class="n">eqSlider9</span><span class="p">.</span><span class="n">floatValue</span><span class="p">]];</span>
</span><span class='line'>    <span class="p">[</span><span class="n">bands</span> <span class="nl">addObject:</span><span class="p">[</span><span class="n">NSNumber</span> <span class="nl">numberWithFloat:</span><span class="n">self</span><span class="p">.</span><span class="n">eqSlider10</span><span class="p">.</span><span class="n">floatValue</span><span class="p">]];</span>
</span><span class='line'>
</span><span class='line'>    <span class="p">[</span><span class="n">self</span><span class="p">.</span><span class="n">audioController</span> <span class="nl">applyBandsToEQ:</span><span class="n">bands</span><span class="p">];</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p><img class="center" src="http://ikennd.ac/pictures/augraph/SimplePlayerWithEQ.png"></p>

<h3>Further Reading</h3>

<p><a href="http://my.safaribooksonline.com/book/audio/9780321636973">Learning Core Audio: A Hands-On Guide to Audio Programming for Mac and iOS</a> by Chris Adamson and Kevin Avila.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[High-Tech Meets Low-Tech: GPS, Topographic Mapping and the Great Outdoors]]></title>
    <link href="http://ikennd.ac//blog/2012/04/high-tech-meets-low-tech-gps/"/>
    <updated>2012-04-08T13:39:00+02:00</updated>
    <id>http://ikennd.ac//blog/2012/04/high-tech-meets-low-tech-gps</id>
    <content type="html"><![CDATA[<p>Software that comes with devices, 90% of the time, isn&#8217;t even worth installing. iTunes is almost universally hated. TomTom HOME is awful. <em>Anything</em> written by Sony makes me want to throw my computer out the window.</p>

<p><img class="center" src="http://ikennd.ac/pictures/vita/YES.png" title="Yes!" ></p>

<p style="text-align:center;"> <em>Yes! Sony&#8217;s PS Vita software seeing double and not communicating it very well.</em></p>

<p><a href="http://500px.com/photo/6401871/"><img class="left" src="http://pcdn.500px.net/6401871/f70b5bb699ca7bfe9f4317a2107a72ea5b015cd6/4.jpg" width="300" height="450" title="Garmin Colorado 300" ></a></p>

<p>This is why I&#8217;ve had this expensive GPS unit — a Garmin Colorado — strapped to my bike for nearly four years and I&#8217;ve barely even looked at the software. In 2008, Garmin&#8217;s software was largely Windows-only and while the mapping application (MapSource) was certainly powerful, its UI was very late-90s Windows and incredibly unintuitive to use.</p>

<p>I ended up with a set of incredibly detailed topographic maps on a device with a 3&#8221; display and nowhere else. I certainly got use out of them, but mainly on the trail with my bike or out hiking, using them to decide which direction to turn when I came to a junction.</p>

<p>A few weeks ago, while researching Gamin&#8217;s latest outdoor GPS unit, the Garmin Montana, I discovered they&#8217;d released a Mac version of their newer mapping application, <a href="http://www.garmin.com/us/products/onthetrail/BaseCamp">BaseCamp</a>. I decided to give it a try and it <em>instantly</em> increased the value of topographic maps ten-fold, and has completely transformed cycling and hiking for the better.</p>

<h3>You PAY for maps?! But Google Maps is free!</h3>

<p>As I was tweeting about this as I was researching it, someone derisively pointed out that &#8220;There&#8217;s an app for that!&#8221;, likely free. And sure, topographic maps are expensive — the maps on my device that cover the section of Sweden I&#8217;m in (roughly 1/4 of the country) cost $199. However, Google Maps doesn&#8217;t even come <em>close</em> to offering the level of detail these maps do, and while OpenStreetMap is better in my area they still don&#8217;t match the quality and level-of-detail of these proper maps. Oh, and there&#8217;s no way in hell I&#8217;m strapping an iPhone to my bike&#8217;s handlebars!</p>

<p><img class="center" src="http://ikennd.ac/pictures/mapping/GoogleVsTopo.png" title="Google vs. Topo" ></p>

<p style="text-align:center;"> <em>Google Maps on the left, 1:50,000 Topographic map on the right.</em></p>

<p><a href="http://500px.com/photo/6402371/"><img class="center" src="http://pcdn.500px.net/6402371/a886f9278fdadab7b243dc3096e89f09554ad080/4.jpg" title="This path is on the topographic maps." ></a></p>

<p style="text-align:center;"> <em>This path is on the topographic maps!</em></p>

<h3>Using Garmin BaseCamp and Good Maps for Fun and Adventure</h3>

<p>So, why is this so awesome? Well, BaseCamp has a superb map display, allowing you to virtually explore the paths and trails with ease and import logs of recent hikes and bikerides to be shown on the map.</p>

<p><img class="center" src="http://ikennd.ac/pictures/mapping/BasecampBikeride.png" title="BaseCamp Map Display" ></p>

<p style="text-align:center;"> <em>BaseCamp&#8217;s Map Display, overlaid with a track of a recent bikeride (magenta).</em></p>

<p>The software comes into its own when planning where to go, though. You can draw out potential routes on the maps and you&#8217;ll be given standard stuff like distance, but also a height map of the route. This is invaluable for planning outdoor treks — the route shown above was great fun because as the height map below shows, it&#8217;s paced nicely with each steep uphill part followed with a rest, and running it in reverse on the way home has a nice long downhill section to finish on.</p>

<p><img class="center" src="http://ikennd.ac/pictures/mapping/BasecampHeightProfile.png" title="BaseCamp Map Display" ></p>

<p style="text-align:center;"> <em>BaseCamp&#8217;s Height Map</em></p>

<p>As the <a href="http://ikennd.ac/blog/2012/03/public-shaming-the-only-way/">quest to go snowboarding</a> continues, this workflow is really helping me explore the countryside on my bike and have a lot of fun doing it. We&#8217;re going to the French Alps in the summer, and I&#8217;m really looking forward to getting maps of the area and going on some epic bikerides!</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Public Shaming: The Only Way]]></title>
    <link href="http://ikennd.ac//blog/2012/03/public-shaming-the-only-way/"/>
    <updated>2012-03-06T23:35:00+01:00</updated>
    <id>http://ikennd.ac//blog/2012/03/public-shaming-the-only-way</id>
    <content type="html"><![CDATA[<p>Let&#8217;s be honest from the outset — I&#8217;m a big fat guy. During my third year at University (which was actually a placement year) I got an office job and piled on the weight stupidly fast. At one point I was so worried about it that I went to the doctor to get advice on how to best get healthy again. He did a couple of tests and said that I was fine, and that if I <em>really</em> wanted to lose weight, I should do it slowly rather than crash dieting.</p>

<p>Of course, I stopped worrying and &#8220;slowly&#8221; became &#8220;nothing&#8221;, and I&#8217;ve been more or less a constant weight ever since. In fact, according to the Wii Fit, I&#8217;ve lost 6lbs in the past 617 days.</p>

<p>The problem is, I <em>really</em> enjoy the outdoors. I love hiking, cycling and more recently snowboarding, and being a big fat guy kinda gets in the way of that. Like many people, every year or so I vow that I&#8217;ll cycle and walk more, reduce my cake intake and generally get fitter. And, like most of those people, I fail pretty hard at changing my bad habits.</p>

<p><a href="http://www.flickr.com/photos/ikenndac/6960110725/"><img class="center" src="http://farm8.staticflickr.com/7177/6960110725_d333c4a7cd_z.jpg"></a></p>

<p style="text-align:center;"> <em>Me, right, cycling at the Nürburgring with friends</em></p>

<h3>This Time, I Mean It — But Not Like Those Other Times I Said &#8220;This Time, I Mean It&#8221;</h3>

<p>The problem is setting goals. I hate the gym and don&#8217;t care about my weight in that I have no interest in getting to some arbitrary number. I can already walk and cycle to some degree, so goals like &#8220;I should be able to cycle <em>x</em> kilometres&#8221; ends up being another arbitrary goal I don&#8217;t have much interest in.</p>

<p>However, I&#8217;ve found a new activity I <em>really</em> care about, and that I currently can&#8217;t do very well — sliding down the side of a mountain on a plank of wood! A year or so before we moved to Sweden, my fiancé and I took some skiing and snowboarding lessons and got proficient enough to tackle a mountain. As luck would have it, my mother lives literally twenty minutes drives from Risoul, a ski resort in the French Alps, so off we went for some mountainside action!</p>

<p>I absolutely adore snowboarding — I could&#8217;ve stayed there all week. Except that&#8217;s the problem — I don&#8217;t have the stamina to keep my ample frame upright on a snowboard for more than a day, and after that I started to get exhausted very fast, causing me to fall over more, causing me to get exhausted even faster.</p>

<p><a href="http://www.flickr.com/photos/ikenndac/6813984322/"><img class="center" src="http://farm8.staticflickr.com/7187/6813984322_a14b35417e_z.jpg"></a></p>

<p style="text-align:center;"> <em>I fell over a LOT.</em></p>

<h3>There&#8217;s Nothing Like Public Shaming To Spur Motivation</h3>

<p>I&#8217;m writing about this plan here simply so it&#8217;s out in the public domain — if I fail, my friends and internet strangers have full permission to mock me mercilessly.</p>

<p><strong>The Goal:</strong> To be fit enough to go snowboarding in winter 2012/13 and have a <em>damn good time</em>.</p>

<p><strong>The Plan:</strong> I&#8217;ve bought a <a href="http://www.fitbit.com/">FitBit</a> to allow me to keep track of my daily activity. The software has a &#8220;Trainer&#8221; that slowly ramps up your activity targets over time, allowing me to increase my daily exercise levels in a way that doesn&#8217;t impact my daily routine. In addition, I&#8217;ll have a few of my friends set targets to meet that the software might not think of, as well as trying my hardest to cycle more.</p>

<p>And damnit, I&#8217;ll cut down on Coke/Pepsi/etc once and for all — which will be the hardest thing to do since there&#8217;s a fridge full of the damn stuff at work — for FREE!</p>

<p>So, friends and internet strangers — if I fail again, at least I&#8217;ll be doing it publicly so you can all yell at me for being a lazy bum.</p>

<p>Feel free to shout motivation and/or helpful goals to aim for - I&#8217;m <a href="http://twitter.com/iKenndac">@iKenndac</a> on Twitter. A nice one a friend of mine suggested today was, given <em>x</em> as the number of weeks since you started, do <em>2x</em> pushups each morning. In the first week it&#8217;s just two, which is nothing — but after a few months it really starts to add up!</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[PS Vita Mini-Review and UI Discussion]]></title>
    <link href="http://ikennd.ac//blog/2012/02/ps-vita-review/"/>
    <updated>2012-02-24T13:25:00+01:00</updated>
    <id>http://ikennd.ac//blog/2012/02/ps-vita-review</id>
    <content type="html"><![CDATA[<p><a href="http://www.flickr.com/photos/ikenndac/6925488589/"><img class="center" src="http://farm8.staticflickr.com/7061/6925488589_47166469fc_z.jpg" title="Dragons LOVE Rayman" ></a></p>

<p style="text-align:center;"> <em>Dragons LOVE Rayman!</em></p>

<p>Thursday morning. It&#8217;s cold and wet, and me and three friends are trudging round Stockholm to pick up the PS Vita consoles they wanted. &#8220;I&#8217;m not going to get one!&#8221; I proudly proclaim, &#8220;I have a PSP and never play on it, and Sony have <em>never</em> made good software. Ever!&#8221;</p>

<p>&#8220;True!&#8221; they agreed, &#8220;But the launch lineup looks really good! And look how <em>shiny</em> it is!&#8221; I couldn&#8217;t disagree — it <em>is</em> shiny.</p>

<p>We get back to the office and Rick boots his Vita. &#8220;Would you like to use your PSN account?&#8221; it asked. Of course! He put in his details. Confirms that yes, he&#8217;d like to use his account. &#8220;Please wait…&#8221;.</p>

<p>&#8220;You need to update your Vita to the latest software version to sign into PSN.&#8221; A single button — <em>OK</em>. At this point, the Vita is back one step, at &#8220;Are you sure?&#8221;. We&#8217;re now stuck in the first-boot tutorial with no way forward. After a couple of minutes, we figure out that you need to go back two steps, answer <em>No</em> to &#8220;Would you like to use your PSN account?&#8221; then tell it your date of birth and country to get out of the tutorial and update the software.</p>

<p>I sit, piling a McDonald&#8217;s Big Mac into my face, happy about my decision to not buy one. Sony&#8217;s software is as bad as ever! However, as Rick starts navigating around the device, it doesn&#8217;t look that bad.</p>

<p><img class="center" src="http://ikennd.ac/pictures/vita/pleasewait.jpg" title="Please Wait" ></p>

<p style="text-align:center;"> <em>You&#8217;ll see this a LOT.</em></p>

<h3>The Downfall</h3>

<p>I start to feel a bit woozy. Thinking that perhaps inhaling a Big Mac in less than a minute wasn&#8217;t such a smart idea, I head back to my desk to carry on work. After ten minutes, staying upright in my chair is becoming a challenge and I remember that the hole where I had a tooth removed the week previous felt a bit… funny. I head home, go to the dentist to get told that my mouth is infected &#8220;a bit&#8221;, that I&#8217;ll need to double the use of the antibacterial mouthwash stuff I got last week, and that I&#8217;ll just have to put up with being dizzy for a while.</p>

<p>I return home, feeling rather sorry for myself. Confirm with my team lead that it&#8217;s OK to work from home for the rest of the week since while falling over a lot is hilarious to begin with, its gets old fast. Work for a little while. Porting Objective-C code to C++ starts draining my soul. Now I&#8217;m even more sad.</p>

<p>Hey, look! The Vita is only 1990kr at Elgiganten! That&#8217;s cheaper than Amazon UK!</p>

<h3>FINALLY The Review!</h3>

<p>I&#8217;m not going to do a full review here. You can find a hundred of them online, so I&#8217;ll just sum up my opinions:</p>

<ul>
<li>The screen is <em>beautiful</em>.</li>
<li>Proprietary memory cards and connectors are the spawn of Satan himself.</li>
<li>Rayman Origins and Wipeout 2048 are the most beautiful mobile games I&#8217;ve ever seen.</li>
</ul>


<p><img class="center" src="http://ikennd.ac/pictures/vita/rayman.jpg" title="Rayman Origins" ></p>

<p style="text-align:center;"> <em>Rayman Origins.</em></p>

<p>Oh, and the Mac software for connecting to the device is as awful as you might expect. It took 1.5Gb of RAM on my machine, then popped up this when I connected my Vita:</p>

<p><img class="center" src="http://ikennd.ac/pictures/vita/YES.png" title="Yes!" ></p>

<p>…so that got deleted pretty much right away.</p>

<p>What intrigues me most, though, about the Vita is the &#8220;home screen&#8221; menu system and multi-tasking UI, and the way it deals with the fact that only one &#8220;real&#8221; process can be active at a time. I really quite like the concepts they&#8217;ve employed, and this discussion will be looking past the stupid stuff Sony likes to do (like three separate &#8220;Please Wait…&#8221; dialogs when you sign into PSN) in favour of the overall flow of things.</p>

<p>A basic overview of the UI:</p>

<ul>
<li><p>The Vita displays applications as pebbles on a vertically scrolling grid. Each &#8220;screen&#8221; can hold ten pebbles, which can be moved around freely.</p></li>
<li><p>When you tap an application&#8217;s pebble, its card is loaded and added to the stack, which scrolls horizonally. The main button on this card will launch or resume the application, so getting from the home screen to your application is at least two taps.</p></li>
<li><p>An application&#8217;s card is customisable - each card has a button to launch or resume the application, as well as a optionally other buttons to launch to specific parts of the application, read the manual, visit related websites, and so on.</p></li>
<li><p>Only one major application can be active at a time. If you press the PS button in an application you&#8217;ll be sent back to the home screen and can browse the web, do social stuff and so on. If you try to launch another major application, the Vita will warn you that the other one will be closed.</p></li>
<li><p>Up to six cards can remain in the stack. If you want to remove a card from the stack, grab the top right-hand corner of it and rip it off the screen - this will remove the card and completely quit the application if it&#8217;s still running.</p></li>
</ul>


<p><img class="center" src="http://ikennd.ac/pictures/vita/pebbles.jpg" title="Pebbles" ></p>

<p style="text-align:center;"> <em>Application pebbles.</em></p>

<p><img class="center" src="http://ikennd.ac/pictures/vita/storecard.jpg" title="Please Wait" ></p>

<p style="text-align:center;"> <em>The PSN Store&#8217;s card, featuring buttons for categories and current &#8220;trending&#8221; games.</em></p>

<h3>In Action</h3>

<p>While that sounds like a complicated UI, it actually works really well in real-world use and I&#8217;m very fond of it. The cards allow applications to show useful information without actually launching the app, and tearing a card out of the stack has a wonderful feel. Navigating around the system to find what you need is slick and fast.</p>

<p>Below is a video of the stacks UI, which shows the first-world problem shiny, glossy devices bring - very visible dust!</p>

<p style="text-align: center;"><iframe width="640" height="360" src="http://www.youtube.com/embed/QDCms-8eS8c?rel=0" frameborder="0" allowfullscreen></iframe></p>


<p>Only time will tell, but I&#8217;m really enjoying the experience with the Vita - the games are fun to play and absolutely gorgeous, and the hardware is beautiful. Hopefully it&#8217;ll stand the test of time better than the PSP.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Weekend Project: Aperture Export Plugin for 500px.com]]></title>
    <link href="http://ikennd.ac//blog/2012/02/weekend-project-aperture-export-plugin-for-500px-dot-com/"/>
    <updated>2012-02-19T00:35:00+01:00</updated>
    <id>http://ikennd.ac//blog/2012/02/weekend-project-aperture-export-plugin-for-500px-dot-com</id>
    <content type="html"><![CDATA[<p><a href="http://500px.com/">500px.com</a> is a pretty awesome new(ish) photo site. I really prefer its layout and display of photos over Flickr, in part because it simply displays the photos <em>bigger</em>, and the photos are the most important thing!</p>

<p>They&#8217;ve been saying for a while now that an official Aperture Export plugin is coming, and there seems to be a <a href="http://support.500px.com/customer/portal/questions/182491-5-px-upload-plugin-for-apple-aperture">lot</a> of <a href="http://support.500px.com/customer/portal/questions/153420-aperture-plugin-">demand</a>. Well, I got bored of them taking their sweet-ass time and threw together my own.</p>

<p>It requires Mac OS X 10.7 (Lion) and Aperture 3.x, and do bear in mind that I made this in less than 48 hours, so it may be buggy and it&#8217;s certainly light on features. But, it gets my photos directly from Aperture into 500px, so I&#8217;m happy!</p>

<p><img class="center" src="http://ikennd.ac/pictures/500pxAperturePlugin.png"></p>

<p>You can find out more and download the plugin from <a href="https://github.com/iKenndac/500px-Aperture-Uploader">GitHub</a>. Enjoy!</p>

<p>Oh, and if anyone loves this plugin so much that they want to get me a gift, well, <a href="https://500px.com/gift">gifting me</a> a year&#8217;s worth of awesome would certainly be appreciated!</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Keeping My Feet On The Ground]]></title>
    <link href="http://ikennd.ac//blog/2012/02/keeping-my-feet-on-the-ground/"/>
    <updated>2012-02-08T22:30:00+01:00</updated>
    <id>http://ikennd.ac//blog/2012/02/keeping-my-feet-on-the-ground</id>
    <content type="html"><![CDATA[<p>A few weeks ago, my friend came to visit me from the UK. He&#8217;s quite the photography enthusiast, and while he was here he fell in love with my <a href="http://www.the-digital-picture.com/Reviews/Canon-EF-24-105mm-f-4-L-IS-USM-Lens-Review.aspx">Canon EF 24-105mm f/4 L</a> lens. By the time we left for our road trip to the UK, he&#8217;d already ordered a similar lens and very kindly <em>gave</em> his Canon EF-S 17-85mm lens to my fiancé since his new one would be replacing it.</p>

<p>Two days after we arrive in the UK, the lens my friend gave us stuck at 17mm and wouldn&#8217;t budge. I felt super-bad about this, even though it turned out it was a <a href="http://thydzik.com/canon-efs-17-85mm-is-stucklocked-zoom-repairdisassembly/">common problem</a> with this lens.</p>

<p>Still feeling bad about breaking my friend&#8217;s lens, I dived right into the tutorial and tried to fix it! Lenses are incredibly intricate, and my first attempt wasn&#8217;t so successful - I&#8217;d fixed the zoom sticking, but now the focus didn&#8217;t work!</p>

<p><a href="http://www.flickr.com/photos/ikenndac/6842988461/"><img class="center" src="http://farm8.staticflickr.com/7007/6842988461_411242e2c0_z.jpg"></a></p>

<h3>Take Two</h3>

<p>Tonight, I tried to fix it again, and was successful! The lens&#8217; zoom is a smooth as ever and the focus works too. I was ecstatic, and I looked down to see my dog staring at me with glee, raising his paw as if to say &#8220;HIGH FIVE bro, you tha man!&#8221;</p>

<p>A couple of seconds later I realised he was <em>actually</em> trying to say &#8220;Damnit I&#8217;m hungry - give me food!&#8221; Still pleased with my dexterity and skill, I went to the kitchen to distribute food for him and ended up with, well, a less than optimal result.</p>

<p><a href="http://www.flickr.com/photos/ikenndac/6843149991/"><img class="center" src="http://farm8.staticflickr.com/7008/6843149991_8a4b1dc61a_z.jpg"></a></p>

<p>I guess there&#8217;s no brain surgery in my future after all.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Me Time]]></title>
    <link href="http://ikennd.ac//blog/2012/02/me-time/"/>
    <updated>2012-02-01T19:52:00+01:00</updated>
    <id>http://ikennd.ac//blog/2012/02/me-time</id>
    <content type="html"><![CDATA[<p>Recently I&#8217;ve fallen into a common routine - I&#8217;ll arrive home from work between six and seven in the evening, slump down on the sofa for a rest, eat dinner, then faff around on the computer for a bit. Next thing I know, it&#8217;s 11pm and bed time.</p>

<p>This routine is lovely and lazy, but isn&#8217;t really helping me get stuff done - I have a ton of side projects, I want to play my guitar, I want to occasionally spend time listening to music as a primary activity (rather than in the background while I&#8217;m doing something else), etc etc.</p>

<p>It&#8217;s also been very easy to fall into the trap of thinking I simply don&#8217;t have time to do all these things - I mean, I get home, eat dinner, spend a small amount of time on the computer and now it&#8217;s bed time!</p>

<h2>Be Selfish!</h2>

<p>Recently, I&#8217;ve been trialling having an enforced &#8220;me time&#8221; - one hour per weekday, in the evening, where I&#8217;ll stop what I&#8217;m doing (within reason!) and go and do one of the above things.</p>

<p><img class="center" src="http://ikennd.ac/pictures/metime.png"></p>

<p>So far, it&#8217;s working out really well. I&#8217;m fortunate to live in an apartment large enough to have a room available for filling with the kind of toys required for this - so far it&#8217;s decked out with a model railway, a fairly decent audio system and a small guitar rack with an amp. Best of all, it&#8217;s right at the opposite end of the apartment to the living room and above the entrance hall to the building, meaning I can make a racket without bothering my fiancé or anyone else.</p>

<p><a href="http://www.flickr.com/photos/ikenndac/6802318621/"><img class="center" src="http://farm8.staticflickr.com/7010/6802318621_628d4f59e3_z.jpg" title="View Toy Room on Flickr.com" ></a></p>

<p>Now I&#8217;ve settled into the routine - I&#8217;ve been doing this for a couple of weeks now - I&#8217;m actually finding that I&#8217;m enjoying my evenings way more and I still have plenty of time to do the things I&#8217;d normally do anyway - I can eat dinner, faff around on the computer a bit, play World of Warcraft with my fiancé and still have an hour for Me Time. My fiancé heartily approves because it means she can watch her crappy girl TV without me complaining about it.</p>

<p>So, if you&#8217;re finding you don&#8217;t have time to do the things you&#8217;d like to do in your spare time - I&#8217;d thoroughly recommend giving an hour of forced &#8220;me time&#8221; a try - it doesn&#8217;t even have to be every day!</p>
]]></content>
  </entry>
  
</feed>
