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

<channel>
	<title>A Tasty Pixel » Blog &#187; Mac</title>
	<atom:link href="http://atastypixel.com/blog/tag/mac/feed/" rel="self" type="application/rss+xml" />
	<link>http://atastypixel.com/blog</link>
	<description></description>
	<lastBuildDate>Tue, 24 Jan 2012 10:40:46 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	
		<item>
		<title>Using a VirtualBox VM to operate a network device for your Mac</title>
		<link>http://atastypixel.com/blog/using-a-virtualbox-vm-to-operate-a-network-device-for-your-mac/</link>
		<comments>http://atastypixel.com/blog/using-a-virtualbox-vm-to-operate-a-network-device-for-your-mac/#comments</comments>
		<pubDate>Sat, 24 Sep 2011 13:54:15 +0000</pubDate>
		<dc:creator>Michael Tyson</dc:creator>
				<category><![CDATA[Geekspeak]]></category>
		<category><![CDATA[Drivers]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[Networking]]></category>
		<category><![CDATA[Virtualization]]></category>

		<guid isPermaLink="false">http://atastypixel.com/blog/?p=2292</guid>
		<description><![CDATA[I recently wrote about our long-range USB WiFi antenna over on Technomadics, which is the nifty little device that we use to connect to the Internet while we&#8217;re travelling. It&#8217;s great, but &#8212; and it&#8217;s a kinda large but &#8212; the OS X driver (it&#8217;s an RTL8187) is just mind-blowingly appalling. It crashes very frequently, [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://atastypixel.com/blog/wp-content/uploads/2011/09/Screen-Shot-2011-09-24-at-14.37.11.png" alt="VirtualBox running TinyCoreLinux, operating the RTL8187 wifi adapter" title="Screen Shot 2011-09-24 at 14.37.11.png" border="0" width="350" height="215" style="border: 1px solid black; float:right;" class="alignright" />I recently wrote about our long-range USB WiFi antenna over on <a href="http://technomadics.net/2011/07/31/equipment-how-were-staying-connected-to-the-internet-in-europe/">Technomadics</a>, which is the nifty little device that we use to connect to the Internet while we&#8217;re travelling.  It&#8217;s great, but &#8212; and it&#8217;s a kinda large but &#8212; the OS X driver (it&#8217;s an RTL8187) is just mind-blowingly appalling.  It crashes very frequently, I can&#8217;t sleep my Mac at night without unplugging the device, and when I plug the device back in in the morning, nine times out of ten I need to reboot. Plus, I have to run the whole system in 32-bit mode because the driver is ancient.  Realtek refuse to assist, so that&#8217;s that.</p>

<p>Three thousand reboots later, I decided enough was enough, and set about seeing if I could run a virtual machine with a small Linux installation which operated the card on behalf of my Mac, and shared the resulting Internet connection.  It was a long learning curve, but I managed to get it all working quite satisfactorily, along with an Internet Sharing setup on my mac to share the connection onwards to other machines on the local network.</p>

<p>What&#8217;s more, the drivers I&#8217;m using under Linux &#8212; actually, they&#8217;re Windows XP drivers, running under the fantastic <em>ndiswrapper</em> utility &#8212; are brilliant, and I get much better signal strength, stability and throughput, to my great surprise.</p>

<p>If you&#8217;re in a similar situation, and either have a crappy driver to contend with, or no driver at all, or even just want a more solid firewall between you and the dangerous open WiFi world, here&#8217;re some instructions on how to get it set up, along with a virtual appliance I put together to make it all happen.</p>

<p>A warning in advance: This is Linux, so it aint for the faint of heart. If you&#8217;re not familiar with Linux, by all means give it a go, but be forewarned that if everything doesn&#8217;t work for you out-of-the-box, it is a steep learning curve.<span id="more-2292"></span></p>

<p>The virtual appliance is set up by default to run the RTL8187 device using ndiswrapper, but the standard wireless drivers package is installed, and should automatically work with another adapter. If not, let me know and I might be able to assist.</p>

<h3>Step 1: Download</h3>

<p>First, download and install <a href="http://www.virtualbox.org/">VirtualBox</a>, the fantastic and totally free VM software.  You&#8217;ll also want to grab the &#8220;VirtualBox 4.1.2 Oracle VM VirtualBox Extension Pack&#8221;, which brings USB 2.0 support.</p>

<p>Next, download the <a href="http://atastypixel.com/blog/wp-content/uploads/2011/09/Microcore-Router.ova">Microcore Router virtual appliance</a> that I put together (it&#8217;s 45Mb).  This is set up for use with <a href="http://www.tinycorelinux.net/">Microcore Linux</a>, and contains:</p>

<ul>
<li>Wireless device drivers</li>
<li>Ndiswrapper</li>
<li>The Windows XP version of the RTL8187 device driver</li>
<li>iptables, with a script to set up IP masquerading</li>
<li>dnsmasq, set up to provide a DHCP address to your Mac host</li>
<li>Wireless-tools (iwconfig, etc), and WICD</li>
</ul>

<p>Finally, <a href="http://distro.ibiblio.org/tinycorelinux/3.x/archive/3.8.4/distribution_files/microcore_3.8.4.iso">download the Microcore live CD image</a> (the virtual appliance was set up with Microcore 3.8.4 &#8211; if you wish to use newer versions, you&#8217;ll also need to update the extensions, but you&#8217;re on your own there.).</p>

<h3>Step 2: Installation and Setup</h3>

<p>Install VirtualBox, then double-click on the extension pack to install that.  Then, double-click on the <em>Microcore-Router.ova</em> virtual appliance to import it.</p>

<p><img style="display:block; margin-left:auto; margin-right:auto;" class="aligncenter" src="http://atastypixel.com/blog/wp-content/uploads/2011/09/Screen-Shot-2011-09-24-at-14.31.45.png" alt="Importing the virtual appliance" title="Screen Shot 2011-09-24 at 14.31.45.png" border="0" width="580" height="478" /></p>

<p>Next, we need to create a virtual network interface to link the guest virtual machine, and your Mac.  Open VirtualBox preferences, and click the &#8220;Network&#8221; tab.  Click the &#8220;+&#8221; button to create a new host-only network, and enter the settings below (192.168.22.2, netmask 255.255.255.0).  Click the &#8220;DHCP Server&#8221; tab and make sure it&#8217;s disabled, then click OK.  This virtual interface is already selected for use within the VM&#8217;s settings.</p>

<p><img style="display:block; margin-left:auto; margin-right:auto;" class="aligncenter" src="http://atastypixel.com/blog/wp-content/uploads/2011/09/Screen-Shot-2011-09-24-at-14.36.03.png" alt="Setting up the host only network interface" title="Screen Shot 2011-09-24 at 14.36.03.png" border="0" width="540" height="371" /></p>

<p>Now attach the Microcore ISO to the virtual appliance by clicking the &#8220;Storage&#8221; section of the VirtualBox VM settings, then selecting the CD item underneath &#8220;IDE Controller&#8221;, selecting &#8220;Choose a virtual CD/DVD disk file…&#8221;, and choosing the Microcore ISO.  This lets us boot the VM into Microcore.</p>

<p><img style="display:block; margin-left:auto; margin-right:auto;" class="aligncenter" src="http://atastypixel.com/blog/wp-content/uploads/2011/09/Screen-Shot-2011-09-24-at-14.34.30.png" alt="Attaching the Microcore iso to the virtual appliance" title="Screen Shot 2011-09-24 at 14.34.30.png" border="0" width="540" height="356" /></p>

<p><img style="display:block; margin-left:auto; margin-right:auto;" class="aligncenter" src="http://atastypixel.com/blog/wp-content/uploads/2011/09/Screen-Shot-2011-09-24-at-14.34.51.png" alt="Microcore ISO attached to VM" title="Screen Shot 2011-09-24 at 14.34.51.png" border="0" width="336" height="246" /></p>

<p>Finally, if you&#8217;re using a USB network device, plug it in now.  Attach the network device to the VM by opening the &#8220;Ports&#8221; (or &#8220;USB&#8221;) settings, then clicking the USB &#8220;+&#8221; symbol and selecting the device.</p>

<p>Note: I&#8217;ve already added the RTL8187 device to the VM setup, so if you&#8217;ve got one too, you shouldn&#8217;t have to do anything here.</p>

<p><img style="display:block; margin-left:auto; margin-right:auto;" class="aligncenter" src="http://atastypixel.com/blog/wp-content/uploads/2011/09/Screen-Shot-2011-09-29-at-11.02.16.png" alt="USB Ports screen" title="Screen Shot 2011-09-29 at 11.02.16.png" border="0" width="540" height="426" /></p>

<h3>Step 3: Boot VM</h3>

<p>Now, you&#8217;re ready to boot.  Close the settings window and hit &#8220;Start&#8221;.  You should see the Microcore boot screen appear, with a prompt for boot options.</p>

<p><img style="display:block; margin-left:auto; margin-right:auto;" class="aligncenter" src="http://atastypixel.com/blog/wp-content/uploads/2011/09/Screen-Shot-2011-09-24-at-14.35.35.png" alt="Microcore boot screen" title="Screen Shot 2011-09-24 at 14.35.35.png" border="0" width="548" height="353" /></p>

<p>Type the following in, to make Microcore boot with the setup contained within the virtual appliance:</p>

<p><code>mc opt=sda1 restore=sda1</code></p>

<p>If you&#8217;re using an RTL8187 too, then you&#8217;ll want to blacklist the buggy Linux device driver here, so that ndiswrapper can run the device with the improved Windows drivers:</p>

<p><code>mc opt=sda1 restore=sda1 blacklist=rtl8187</code></p>

<p>Hit enter to start booting, and within a few seconds you should be faced with an empty screen and a prompt.</p>

<p>With a bit of luck, your network device has been detected and started up; type <code>wicd-curses</code> and hit enter to launch the WiFi control panel.</p>

<p><img style="display:block; margin-left:auto; margin-right:auto;" class="aligncenter" src="http://atastypixel.com/blog/wp-content/uploads/2011/09/Screen-Shot-2011-09-24-at-14.37.111.png" alt="wicd-curses WiFi control panel" title="Screen Shot 2011-09-24 at 14.37.11.png" border="0" width="540" height="332" /></p>

<p>If you don&#8217;t see any networks here, and you expect to, then it could be that your network device hasn&#8217;t been picked up.  Otherwise, breathe a sigh of relief and press on.</p>

<h3>Step 4: Configure the Mac</h3>

<p>Now that we&#8217;re booted and running the VM, we need to set up your Mac to access the internet via the VM&#8217;s connection.</p>

<p>Minimise the VM window &#8212; we&#8217;re done for now &#8212; and open up a Terminal window on your Mac.  Ping 192.168.22.1, which is the VM&#8217;s configured address.  Do you see ping replies?  Then you&#8217;re almost there.</p>

<p>The final step is to make your Mac use the guest&#8217;s DHCP server, to obtain the correct settings. Type the following in Terminal to make it happen:</p>

<p><code>sudo ipconfig set vboxnet0 DHCP</code></p>

<p>To make sure it&#8217;s done the right thing, type <code>ifconfig vboxnet0</code>. You should see something like:</p>

<p><pre>
vboxnet0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> mtu 1500
    ether 0a:00:27:00:00:00 
    inet 192.168.22.2 netmask 0xffffff00 broadcast 192.168.22.255
    inet 192.168.22.72 netmask 0xffffff00 broadcast 192.168.22.255
</pre></p>

<p>That is, the default address we specified when setting up the VirtualBox host adapter, and a new alias that has an address assigned by the DHCP server running within the VM.  If you see this, then you should be good to go: Try opening up a web browser or pinging google.com.</p>

<p>If it&#8217;s working, then congratulations!  Mission accomplished.</p>

<h3>Optional Step 5: Internet Sharing</h3>

<p>For bonus points, you can set up your Mac so that other computers on your network can share the connection.  It&#8217;s not as simple as just starting up Internet Sharing from System Preferences, however, because System Preferences doesn&#8217;t know about the virtual network device we&#8217;re using.</p>

<p>Instead, we have to do it the old-fashioned manual way: Set up IP forwarding, NAT, and set up a DHCP server.  I&#8217;ve created a service (loosely based upon Schley Stauffer Andrew Kutz&#8217;s <a href="http://akutz.wordpress.com/2009/08/20/building-a-better-os-x-firewall-or-how-i-solved-the-nat-problem-for-virtualbox/">akin service</a>) that monitors the VM&#8217;s network state, and automatically does all this, sharing the VM&#8217;s connection via Ethernet and Wi-Fi.</p>

<p>Download the service resources here:</p>

<p><a href="http://atastypixel.com/blog/wp-content/uploads/2012/01/vmboxnat.zip" title="vmboxnat.zip" alt="Vmboxnat">vmboxnat.zip</a></p>

<p>Extract, then go to the folder in Terminal and type:</p>

<p><code>sudo ./install</code></p>

<p>This will install to <code>/usr/local/vmboxnat</code>, and register the service with launchctl.  This is a script which runs in the background and starts up internet sharing when the VM is detected, then stops it when the VM goes away.</p>

<p>If you open up Console now, you should see something like:</p>

<p><pre>
…au.id.tyson.michael.vmboxnat[13099]: Starting vmboxnat
…au.id.tyson.michael.vmboxnat[13099]: assigned DHCP address
…au.id.tyson.michael.vmboxnat[13099]: created alias interfaces
…au.id.tyson.michael.vmboxnat[13099]: enabled ip forwarding
…au.id.tyson.michael.vmboxnat[13099]: enabled natd
…au.id.tyson.michael.vmboxnat[13099]: established ipfw rules
…au.id.tyson.michael.vmboxnat[13099]: enabled bootpd
</pre></p>

<p>That means you&#8217;re all set.</p>

<p>Note that you&#8217;ll need to manually create an ad-hoc WiFi network, as we can&#8217;t automatically create a network the way the official Internet Sharing system does.  Once you&#8217;ve created it, though, other hosts accessing that network should automatically receive an address via DHCP, and be good to go.</p>
 <img src="http://atastypixel.com/blog/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=2292" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://atastypixel.com/blog/using-a-virtualbox-vm-to-operate-a-network-device-for-your-mac/feed/</wfw:commentRss>
		<slash:comments>43</slash:comments>
		</item>
		<item>
		<title>Sparrow users beware: Bug sends prior draft instead of latest email version</title>
		<link>http://atastypixel.com/blog/sparrow-users-beware-bug-sends-prior-draft-instead-of-latest-email-version/</link>
		<comments>http://atastypixel.com/blog/sparrow-users-beware-bug-sends-prior-draft-instead-of-latest-email-version/#comments</comments>
		<pubDate>Thu, 18 Aug 2011 19:41:50 +0000</pubDate>
		<dc:creator>Michael Tyson</dc:creator>
				<category><![CDATA[Geekspeak]]></category>
		<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[Email]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[Sparrow]]></category>

		<guid isPermaLink="false">http://atastypixel.com/blog/?p=2243</guid>
		<description><![CDATA[Update: The Sparrow guys tell me they&#8217;ve found and nailed the bug, and will release the fix in 1.4 in late September. I&#8217;ve just discovered a critical issue with Sparrow that I thought others should be warned of. It just bit me, big-time, when in the middle of an important negotiation with a third party, [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Update</strong>: <em>The Sparrow guys tell me they&#8217;ve found and nailed the bug, and will release the fix in 1.4 in late September.</em></p>

<p>I&#8217;ve just discovered a critical issue with Sparrow that I thought others should be warned of.  It just bit me, big-time, when in the middle of an important negotiation with a third party, an earlier unpolished draft was sent out instead of the final email, when I experienced a momentary Internet connection dropout.</p>

<p>Sparrow has an issue where hitting &#8220;Send&#8221;, in unreliable network conditions, on a draft message that has been modified, results in a prior copy of the message being sent, rather than the latest version.</p>

<p>To replicate this issue reliably:</p>

<ol>
<li>Create a new message (Cmd-N)</li>
<li>Specify a recipient (oneself), subject, and some body content (say, the letter &#8220;A&#8221;)</li>
<li>Hit &#8220;Save&#8221;, to save the draft</li>
<li>Change &#8220;A&#8221; to &#8220;B&#8221;, then disconnect the network connection (in my case, turning off the radio on my external WiFi adapter), then hit &#8220;Send&#8221;.  Sparrow will report a failed connection, and will keep the outgoing message with state &#8220;Pending&#8221;</li>
<li>Restore network connection.  Upon detecting the restored connection, Sparrow will proceed to send the message</li>
<li>Check email. Received test email will have &#8220;A&#8221; in the email body.</li>
</ol>

<p>Scary stuff.  I hope they&#8217;ll fix this soon, but it&#8217;s going to make the app difficult to trust in future!</p>

<p><strong>Update</strong>: I should mention, a probable workaround for this is to never, ever hit &#8220;Send&#8221; until you&#8217;ve saved the draft, and verified that the save operation has completed (perhaps even restart the app first).</p>
 <img src="http://atastypixel.com/blog/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=2243" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://atastypixel.com/blog/sparrow-users-beware-bug-sends-prior-draft-instead-of-latest-email-version/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Quick tip: Manipulating the OS X clipboard</title>
		<link>http://atastypixel.com/blog/quick-tip-manipulating-the-os-x-clipboard/</link>
		<comments>http://atastypixel.com/blog/quick-tip-manipulating-the-os-x-clipboard/#comments</comments>
		<pubDate>Sun, 08 May 2011 13:36:27 +0000</pubDate>
		<dc:creator>Michael Tyson</dc:creator>
				<category><![CDATA[Geekspeak]]></category>
		<category><![CDATA[Mac]]></category>

		<guid isPermaLink="false">http://atastypixel.com/blog/quick-tip-manipulating-the-os-x-clipboard/</guid>
		<description><![CDATA[Here&#8217;s a shortcut that comes in handy sometimes. There are two command-line utilities, pbcopy and pbpaste that provide direct access to the OS X clipboard. They&#8217;re quite useful for doing various quick things with clipboard contents, like, say, writing it to a file: pbpaste &#62; Desktop/output.txt Or altering them: pbpaste &#124; sed s/bacon/bea-con/g &#124; pbcopy [...]]]></description>
			<content:encoded><![CDATA[<p>Here&#8217;s a shortcut that comes in handy sometimes.  There are two command-line utilities, <code>pbcopy</code> and <code>pbpaste</code> that provide direct access to the OS X clipboard.</p>

<p>They&#8217;re quite useful for doing various quick things with clipboard contents, like, say, writing it to a file:</p>

<p><code>pbpaste &gt; Desktop/output.txt</code></p>

<p>Or altering them:</p>

<p><code>pbpaste | sed s/bacon/bea-con/g | pbcopy</code></p>

<p>Fun!</p>
 <img src="http://atastypixel.com/blog/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=2193" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://atastypixel.com/blog/quick-tip-manipulating-the-os-x-clipboard/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Post Grabber sniffs out POST data, generates curl scripts</title>
		<link>http://atastypixel.com/blog/post-grabber-sniffs-out-post-data-generates-curl-scripts/</link>
		<comments>http://atastypixel.com/blog/post-grabber-sniffs-out-post-data-generates-curl-scripts/#comments</comments>
		<pubDate>Thu, 21 Apr 2011 08:59:04 +0000</pubDate>
		<dc:creator>Michael Tyson</dc:creator>
				<category><![CDATA[Geekspeak]]></category>
		<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[Utility]]></category>
		<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://atastypixel.com/blog/post-grabber-sniffs-out-post-data-generates-curl-scripts/</guid>
		<description><![CDATA[Every now and then I find myself needing to automate some web requests, either to download using something a little more robust than a web browser, scrape some web content, or to maintain a session. That automation can be a bit of a pain if there&#8217;s a form submission involved, because it means opening up [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://atastypixel.com/blog/wp-content/uploads/2011/04/michaeltyson_PostGrabber_raw_master_screenshot.png" width="300" height="294" alt="Post Grabber screenshot" class="alignright" />Every now and then I find myself needing to automate some web requests, either to download using something a little more robust than a web browser, scrape some web content, or to maintain a session.  That automation can be a bit of a pain if there&#8217;s a form submission involved, because it means opening up the page source, finding the form and any connected javascript code, and figuring out what fields are submitted.</p>

<p>A little utility I just put together does that for you: <a href="https://github.com/michaeltyson/PostGrabber">Post Grabber</a> detects POST data and generates an equivalent &#8220;curl&#8221; command that can be used in shell or Automator scripts.</p>

<p>Post Grabber works with its own internal browser, so it can intercept POST submissions directly. That means it works with HTTPS, unlike the traditional web sniffer approach.</p>

<p><a href="https://github.com/downloads/michaeltyson/PostGrabber/Post%20Grabber%201.2.zip">Download the app</a>, or see the <a href="https://github.com/michaeltyson/PostGrabber">source on GitHub</a>.</p>
 <img src="http://atastypixel.com/blog/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=2189" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://atastypixel.com/blog/post-grabber-sniffs-out-post-data-generates-curl-scripts/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Internet Timer keeps track of your timed Internet usage</title>
		<link>http://atastypixel.com/blog/internet-timer-keeps-track-of-your-timed-internet-usage/</link>
		<comments>http://atastypixel.com/blog/internet-timer-keeps-track-of-your-timed-internet-usage/#comments</comments>
		<pubDate>Sun, 13 Mar 2011 17:40:02 +0000</pubDate>
		<dc:creator>Michael Tyson</dc:creator>
				<category><![CDATA[Geekspeak]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[Software]]></category>

		<guid isPermaLink="false">http://atastypixel.com/blog/internet-timer-keeps-track-of-your-timed-internet-usage/</guid>
		<description><![CDATA[I threw this utility app together last year, in order to keep track of our Internet usage on a time-limited account. This is a piece of software that lives quietly in your menubar, until an Internet connection is detected. Then, it will count how long you&#8217;ve been online, showing a timer in the menubar. Features: [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://atastypixel.com/blog/wp-content/uploads/2011/03/internet-timer-icon.png" width="200" height="200" alt="Internet Timer icon" class="alignright" />I threw this utility app together last year, in order to keep track of our Internet usage on a time-limited account.  This is a piece of software that lives quietly in your menubar, until an Internet connection is detected.  Then, it will count how long you&#8217;ve been online, showing a timer in the menubar.</p>

<p>Features:</p>

<ul>
<li>Detects your Internet connection automatically, or you can start and stop the timer manually.</li>
<li>Keep a log of your usage, including weekly, monthly, and all-time totals, and daily average, with the ability to reset these.</li>
<li>Time in configurable blocks of time, if your carrier charges in blocks (e.g., 15 minutes)<span id="more-2161"></span><img src="http://atastypixel.com/blog/wp-content/uploads/2011/03/internet-timer-screenshot.png" width="254" height="168" alt="Internet timer screenshot: Menubar" class="aligncenter" style="margin-top: 30px;" /></li>
</ul>

<p><img src="http://atastypixel.com/blog/wp-content/uploads/2011/03/internet-timer-screenshot-2.png" width="400" height="374" alt="Internet Timer screenshot: Statistics viewer" class="aligncenter" /></p>

<p>Grab it here:</p>

<p><center><a href="http://atastypixel.com/blog/wp-content/uploads/2011/03/Internet-Timer.zip" title="Internet Timer.zip" style="text-decoration: none; font-size: 2.0em; color: black;"><img src="http://atastypixel.com/blog/wp-content/uploads/2011/03/internet-timer-icon-small.png" width="48" height="48" alt="internet-timer-icon-small.png" style="vertical-align: middle;" /> Internet Timer</a></center></p>
 <img src="http://atastypixel.com/blog/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=2161" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://atastypixel.com/blog/internet-timer-keeps-track-of-your-timed-internet-usage/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Easy Delayed Messaging using NSProxy and NSInvocation</title>
		<link>http://atastypixel.com/blog/easy-delayed-messaging-using-nsproxy-and-nsinvocation/</link>
		<comments>http://atastypixel.com/blog/easy-delayed-messaging-using-nsproxy-and-nsinvocation/#comments</comments>
		<pubDate>Wed, 01 Sep 2010 22:10:04 +0000</pubDate>
		<dc:creator>Michael Tyson</dc:creator>
				<category><![CDATA[Geekspeak]]></category>
		<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[Code]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[Mac]]></category>

		<guid isPermaLink="false">http://atastypixel.com/blog/easy-delayed-messaging-using-nsproxy-and-nsinvocation/</guid>
		<description><![CDATA[Sometimes it&#8217;s necessary to perform an action some time in the future, whether it&#8217;s disabling a button for a certain time interval after it&#8217;s pressed, performing an animation after a short wait, or triggering a reload of some data. NSTimer is great for that purpose, as well as repeatedly performing actions, but it&#8217;s most convenient [...]]]></description>
			<content:encoded><![CDATA[<p>Sometimes it&#8217;s necessary to perform an action some time in the future, whether it&#8217;s disabling a button for a certain time interval after it&#8217;s pressed, performing an animation after a short wait, or triggering a reload of some data.</p>

<p>NSTimer is great for that purpose, as well as repeatedly performing actions, but it&#8217;s most convenient utility method, <code>scheduledTimerWithTimeInterval:target:selector:userInfo:repeats:</code> only takes one &#8216;<code>id</code>&#8216; argument.  Using the NSInvocation equivalent, <code>scheduledTimerWithTimeInterval:invocation:repeats:</code> requires creating and setting up the NSInvocation itself, which is always verbose and a pain.</p>

<p>NSProxy is a wonderful little construct that lets us interact with it like we were talking to the original object.  I first learned how it works from a <a href="http://lists.apple.com/archives/cocoa-dev/2006/Jun/msg01783.html">post by Shaun Wexler</a> which shows an easier way to send a message on the main thread, by using the NSInvocation given via the NSProxy&#8217;s <code>forwardInvocation:</code> method.  The same technique can be used to easily create a configured NSTimer.</p>

<p>So, instead of some awful thing like this:</p>


<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #400080;">NSInvocation</span> <span style="color: #002200;">*</span>i <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSInvocation</span> invocationWithMethodSignature<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span>mapView methodSignatureForSelector<span style="color: #002200;">:</span><span style="color: #a61390;">@selector</span><span style="color: #002200;">&#40;</span>selectAnnotation<span style="color: #002200;">:</span>animated<span style="color: #002200;">:</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#91;</span>i setTarget<span style="color: #002200;">:</span>mapView<span style="color: #002200;">&#93;</span>;
MKAnnotation <span style="color: #002200;">*</span>annotation <span style="color: #002200;">=</span> view.annotation;
<span style="color: #002200;">&#91;</span>i setArgument<span style="color: #002200;">:&amp;</span>annotation atIndex<span style="color: #002200;">:</span><span style="color: #2400d9;">3</span><span style="color: #002200;">&#93;</span>;
<span style="color: #a61390;">BOOL</span> flag<span style="color: #002200;">=</span><span style="color: #a61390;">YES</span>;
<span style="color: #002200;">&#91;</span>i setArgument<span style="color: #002200;">:&amp;</span>flag atIndex<span style="color: #002200;">:</span><span style="color: #2400d9;">4</span><span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#91;</span><span style="color: #400080;">NSTimer</span> scheduledTimerWithTimeInterval<span style="color: #002200;">:</span><span style="color: #2400d9;">0.5</span> invocation<span style="color: #002200;">:</span>i repeats<span style="color: #002200;">:</span><span style="color: #a61390;">NO</span><span style="color: #002200;">&#93;</span>;</pre></div></div>


<p>We can do this:</p>


<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">&#91;</span><span style="color: #002200;">&#40;</span>MKMapView<span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&#91;</span>TPTimerProxy scheduledTimerProxyWithTarget<span style="color: #002200;">:</span>mapView timeInterval<span style="color: #002200;">:</span><span style="color: #2400d9;">0.5</span> repeats<span style="color: #002200;">:</span><span style="color: #a61390;">NO</span><span style="color: #002200;">&#93;</span> selectAnnotation<span style="color: #002200;">:</span>view.annotation animated<span style="color: #002200;">:</span><span style="color: #a61390;">YES</span><span style="color: #002200;">&#93;</span>;</pre></div></div>


<p>Here&#8217;s the juice:<span id="more-1996"></span></p>


<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #a61390;">@interface</span> TPTimerProxy <span style="color: #002200;">:</span> <span style="color: #400080;">NSProxy</span> <span style="color: #002200;">&#123;</span>
    <span style="color: #a61390;">id</span> target;
    NSTimeInterval timeInterval;
    <span style="color: #a61390;">BOOL</span> repeats;
&nbsp;
    <span style="color: #400080;">NSTimer</span> <span style="color: #002200;">*</span>timer;
<span style="color: #002200;">&#125;</span>
<span style="color: #002200;">+</span> <span style="color: #002200;">&#40;</span>TPTimerProxy<span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>scheduledTimerProxyWithTarget<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span>target timeInterval<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>NSTimeInterval<span style="color: #002200;">&#41;</span>timeInterval repeats<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">BOOL</span><span style="color: #002200;">&#41;</span>repeats;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>invalidate;
<span style="color: #a61390;">@end</span>
&nbsp;
&nbsp;
<span style="color: #a61390;">@implementation</span> TPTimerProxy
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span>initWithTarget<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span>aTarget timeInterval<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>NSTimeInterval<span style="color: #002200;">&#41;</span>aTimeInterval repeats<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">BOOL</span><span style="color: #002200;">&#41;</span>repeatFlag <span style="color: #002200;">&#123;</span>
    target <span style="color: #002200;">=</span> aTarget;
    timeInterval <span style="color: #002200;">=</span> aTimeInterval;
    repeats <span style="color: #002200;">=</span> repeatFlag;
    <span style="color: #a61390;">return</span> self;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">+</span> <span style="color: #002200;">&#40;</span>TPTimerProxy<span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>scheduledTimerProxyWithTarget<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span>target timeInterval<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>NSTimeInterval<span style="color: #002200;">&#41;</span>timeInterval repeats<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">BOOL</span><span style="color: #002200;">&#41;</span>repeats <span style="color: #002200;">&#123;</span>
    <span style="color: #a61390;">return</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>TPTimerProxy alloc<span style="color: #002200;">&#93;</span> initWithTarget<span style="color: #002200;">:</span>target timeInterval<span style="color: #002200;">:</span>timeInterval repeats<span style="color: #002200;">:</span>repeats<span style="color: #002200;">&#93;</span> autorelease<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>invalidate <span style="color: #002200;">&#123;</span>
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span> timer <span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
        <span style="color: #002200;">&#91;</span>timer invalidate<span style="color: #002200;">&#93;</span>;
        timer <span style="color: #002200;">=</span> <span style="color: #a61390;">nil</span>;
    <span style="color: #002200;">&#125;</span>
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #400080;">NSMethodSignature</span> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>methodSignatureForSelector<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">SEL</span><span style="color: #002200;">&#41;</span>selector <span style="color: #002200;">&#123;</span>
    <span style="color: #a61390;">return</span> <span style="color: #002200;">&#91;</span>target methodSignatureForSelector<span style="color: #002200;">:</span>selector<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>forwardInvocation<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #400080;">NSInvocation</span> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>invocation <span style="color: #002200;">&#123;</span>
    <span style="color: #002200;">&#91;</span>invocation setTarget<span style="color: #002200;">:</span>target<span style="color: #002200;">&#93;</span>;
    timer <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSTimer</span> scheduledTimerWithTimeInterval<span style="color: #002200;">:</span>timeInterval invocation<span style="color: #002200;">:</span>invocation repeats<span style="color: #002200;">:</span>repeats<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #a61390;">@end</span></pre></div></div>

 <img src="http://atastypixel.com/blog/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=1996" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://atastypixel.com/blog/easy-delayed-messaging-using-nsproxy-and-nsinvocation/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>iPhone debugging tip: Breaking on exceptions and reading their content</title>
		<link>http://atastypixel.com/blog/iphone-debugging-tip-breaking-on-exceptions-and-reading-their-content/</link>
		<comments>http://atastypixel.com/blog/iphone-debugging-tip-breaking-on-exceptions-and-reading-their-content/#comments</comments>
		<pubDate>Tue, 17 Aug 2010 21:23:12 +0000</pubDate>
		<dc:creator>Michael Tyson</dc:creator>
				<category><![CDATA[Geekspeak]]></category>
		<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[Debugging]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[Mac]]></category>

		<guid isPermaLink="false">http://atastypixel.com/blog/iphone-debugging-tip-breaking-on-exceptions-and-reading-their-content/</guid>
		<description><![CDATA[Just a quick one: This may be obvious to many devs, but it&#8217;s worth noting. One common and useful debugging technique is breaking on exceptions, so that you can see exactly where in your app&#8217;s flow a breakpoint occurs. This can be done by adding -[NSException raise] and objc_exception_throw to your breakpoints list. Once an [...]]]></description>
			<content:encoded><![CDATA[<p>Just a quick one: This may be obvious to many devs, but it&#8217;s worth noting.  One common and useful <a href="http://www.cocoadev.com/index.pl?DebuggingTechniques">debugging technique</a> is breaking on exceptions, so that you can see exactly where in your app&#8217;s flow a breakpoint occurs.</p>

<p>This can be done by adding <code>-[NSException raise]</code> and <code>objc_exception_throw</code> to your breakpoints list.</p>

<p>Once an exception happens, you can then check out the exception itself to see what went wrong.  The approach varies between platforms. If you&#8217;re in the simulator (or any Mac OS X app running on Intel), the exception will be stored in the <code>$eax</code> register.  Take a look by typing:</p>

<p><code>po $eax</code></p>

<p>If you&#8217;re on the iPhone, it&#8217;ll be <code>$r0</code>, so:</p>

<p><code>po $r0</code></p>
 <img src="http://atastypixel.com/blog/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=1991" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://atastypixel.com/blog/iphone-debugging-tip-breaking-on-exceptions-and-reading-their-content/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>iPhone/Mac animation for custom classes: Property animation for more than just CALayer</title>
		<link>http://atastypixel.com/blog/key-path-based-property-animation/</link>
		<comments>http://atastypixel.com/blog/key-path-based-property-animation/#comments</comments>
		<pubDate>Fri, 13 Aug 2010 20:38:18 +0000</pubDate>
		<dc:creator>Michael Tyson</dc:creator>
				<category><![CDATA[Geekspeak]]></category>
		<category><![CDATA[Animation]]></category>
		<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[Code]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Graphics]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[Mac]]></category>

		<guid isPermaLink="false">http://atastypixel.com/blog/key-path-based-property-animation/</guid>
		<description><![CDATA[An Objective-C class that provides similar functionality to CABasicAnimation, but works on any object.]]></description>
			<content:encoded><![CDATA[<p>I recently wrote a custom view &#8212; a 3D vintage-looking pull lever &#8212; that provided a continuous property to control the state.  I wanted to animated this smoothly, a-la CABasicAnimation, but couldn&#8217;t find a built-in way to do so.</p>

<p>So, I wrote a class that provides similar functionality to CABasicAnimation, but works on any object.  I thought I&#8217;d share it.</p>

<p>Features:</p>

<ul>
<li>From/to value settings (currently only supports <code>NSNumber</code> and scalar numeric types, but easily extendable)</li>
<li>Duration, delay settings</li>
<li>Timing functions: Linear, ease out, ease in, and ease in/ease out</li>
<li>Animation chaining (specify another configured animation for <code>chainedAnimation</code>, and it&#8217;ll be fired once the first animation completes)</li>
<li>Delegate notification of animation completion</li>
<li>Uses a single timer for smooth lock-step animation</li>
<li>Uses <code>CADisplayLink</code> if available, to update in sync with screen updates</li>
</ul>

<p>Use it like this:</p>


<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>startMyAnimation <span style="color: #002200;">&#123;</span>
  TPPropertyAnimation <span style="color: #002200;">*</span>animation <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>TPPropertyAnimation propertyAnimationWithKeyPath<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;state&quot;</span><span style="color: #002200;">&#93;</span>;
  animation.toValue <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSNumber</span> numberWithFloat<span style="color: #002200;">:</span><span style="color: #2400d9;">1.0</span><span style="color: #002200;">&#93;</span>; <span style="color: #11740a; font-style: italic;">// fromValue is taken from current value if not specified</span>
  animation.duration <span style="color: #002200;">=</span> <span style="color: #2400d9;">1.0</span>;
  animation.timing <span style="color: #002200;">=</span> TPPropertyAnimationTimingEaseIn;
  <span style="color: #002200;">&#91;</span>animation beginWithTarget<span style="color: #002200;">:</span>self<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span></pre></div></div>


<p>Make sure you also include the QuartzCore framework, used to access <code>CADisplayLink</code>, if it&#8217;s available.</p>

<p>It&#8217;s BSD-licensed.</p>

<p>Grab it here: 
<a href="http://atastypixel.com/blog/wp-content/uploads/2010/08/TPPropertyAnimation.zip" title="TPPropertyAnimation.zip">TPPropertyAnimation.zip</a></p>
 <img src="http://atastypixel.com/blog/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=1973" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://atastypixel.com/blog/key-path-based-property-animation/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Reginald RegEx explorer</title>
		<link>http://atastypixel.com/blog/reginald-regex-explorer/</link>
		<comments>http://atastypixel.com/blog/reginald-regex-explorer/#comments</comments>
		<pubDate>Sat, 31 Jul 2010 22:28:27 +0000</pubDate>
		<dc:creator>Michael Tyson</dc:creator>
				<category><![CDATA[Geekspeak]]></category>
		<category><![CDATA[Debugging]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[Regex]]></category>
		<category><![CDATA[Software]]></category>

		<guid isPermaLink="false">http://atastypixel.com/blog/reginald-regex-explorer/</guid>
		<description><![CDATA[With a desperate need to debug a lengthy regular expression destined for use with the excellent RegexKitLite library, I have quickly put together a Mac OS X application. Reginald is a kindly old gentleman devoted to assisting you with those tricky regular expressions. Provide some sample input, and your regular expression, and Reginald will provide [...]]]></description>
			<content:encoded><![CDATA[<p>With a desperate need to debug a lengthy regular expression destined for use with the excellent <a href="http://regexkit.sourceforge.net/RegexKitLite/">RegexKitLite</a> library, I have quickly put together a Mac OS X application.</p>

<p><img src="http://atastypixel.com/blog/wp-content/uploads/2010/07/reg.png" width="64" height="69" alt="Reginald icon" style="float:right;" />
Reginald is a kindly old gentleman devoted to assisting you with those tricky regular expressions.</p>

<p>Provide some sample input, and your regular expression, and Reginald will provide you with colour-coded output and a list of all your matches and the corresponding capture groups for your exploration.  Select a match or capture group in the list to the right, and the corresponding text will be selected in the panel to the left.</p>

<p>Reginald is built on <a href="http://regexkit.sourceforge.net/RegexKitLite/">RegexKitLite</a>, and so uses the <a href="http://regexkit.sourceforge.net/RegexKitLite/index.html#ICUSyntax">ICU syntax</a>.</p>

<p>It will run on Mac OS X 10.6 and above.</p>

<p><a href="http://github.com/michaeltyson/Reginald/downloads">Download Reginald here</a>, or <a href="http://github.com/michaeltyson/Reginald">access the source on GitHub</a>.</p>

<p><a href="http://atastypixel.com/blog/wp-content/uploads/2010/07/201007312318.jpg" rel="lightbox[1966]"><img src="http://atastypixel.com/blog/wp-content/uploads/2010/07/201007312318-tm.jpg" width="450" height="342" alt="Reginald screenshot" class="aligncenter" /></a></p>
 <img src="http://atastypixel.com/blog/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=1966" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://atastypixel.com/blog/reginald-regex-explorer/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>OS X service to filter selected text through a shell command</title>
		<link>http://atastypixel.com/blog/os-x-service-to-filter-selected-text-through-a-shell-command/</link>
		<comments>http://atastypixel.com/blog/os-x-service-to-filter-selected-text-through-a-shell-command/#comments</comments>
		<pubDate>Sun, 23 May 2010 13:50:07 +0000</pubDate>
		<dc:creator>Michael Tyson</dc:creator>
				<category><![CDATA[Geekspeak]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[Scripts]]></category>
		<category><![CDATA[Shell]]></category>
		<category><![CDATA[Workflow]]></category>

		<guid isPermaLink="false">http://atastypixel.com/blog/os-x-service-to-filter-selected-text-through-a-shell-command/</guid>
		<description><![CDATA[The UNIX shell provides a host of extremely useful utilities for modifying text. This Automator service makes all of them available for filtering text in all OS X applications.]]></description>
			<content:encoded><![CDATA[<p>The UNIX shell provides a host of extremely useful utilities for modifying text. This OS X Automator service makes all of them available for filtering text in all OS X applications.</p>

<p>This can be handy for performing quick operations, like replacing text with regular expressions, sorting lists or swapping fields around.</p>

<p>When triggered, the service requests a command to use for filtering, then runs the command and replaces the selected text with the result.</p>

<p>Some sample operations:</p>

<ul>
<li>Sort lines alphabetically/numerically: <tt>sort</tt> or <tt>sort -n</tt></li>
<li>Change to lowercase: <tt>tr "[:upper:]" "[:lower:]"</tt></li>
<li>Replace a spelling mistake, taking care of case: <tt>sed -E 's/([tT])eh/\1he/g'</tt></li>
<li>Re-order elements in a tab- or comma-separated list: <tt>awk '{print $2 $1}'</tt> or <tt>awk -F, '{print $2 "," $1}'</tt>
</ul>

<p><img src="http://atastypixel.com/blog/wp-content/uploads/2010/05/filter-service.jpg" width="400" height="397" alt="Filter through Shell Command service" class="aligncenter" /></p>

<p>Put it in <code>Library/Services</code>, and it should appear in the &#8216;Services&#8217; menu.</p>

<p><a href="http://atastypixel.com/blog/wp-content/uploads/2010/05/Filter-through-Shell-Command.zip" title="Filter through Shell Command.zip">Filter through Shell Command.zip</a></p>
 <img src="http://atastypixel.com/blog/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=1913" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://atastypixel.com/blog/os-x-service-to-filter-selected-text-through-a-shell-command/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>The Making of Talkie: Multi-interface broadcasting and multicast</title>
		<link>http://atastypixel.com/blog/the-making-of-talkie-multi-interface-broadcasting-and-multicast/</link>
		<comments>http://atastypixel.com/blog/the-making-of-talkie-multi-interface-broadcasting-and-multicast/#comments</comments>
		<pubDate>Sun, 02 May 2010 12:52:38 +0000</pubDate>
		<dc:creator>Michael Tyson</dc:creator>
				<category><![CDATA[Geekspeak]]></category>
		<category><![CDATA[Broadcast]]></category>
		<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[Multicast]]></category>
		<category><![CDATA[Networking]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[Talkie]]></category>
		<category><![CDATA[Talkie-for-Mac]]></category>
		<category><![CDATA[Tutorial]]></category>

		<guid isPermaLink="false">http://atastypixel.com/blog/?p=1901</guid>
		<description><![CDATA[Part 2 Talkie is my newest product, a Walkie Talkie for iPhone and Mac. In Part 1 of this series, I wrote about basic broadcasting. This works fine with one network device, but it&#8217;s worth discussing how to send through all devices, so you can communicate with others connected via, say, Ethernet and WiFi simultaneously. [...]]]></description>
			<content:encoded><![CDATA[<h2>Part 2</h2>

<p><img src="http://atastypixel.com/media/images/products/talkie/icon-medium.jpg" width="183" height="148" alt="Talkie" style="float:right;" /><a href="http://atastypixel.com/products/talkie">Talkie</a> is my newest product, a Walkie Talkie for iPhone and Mac.</p>

<p>In <a href="http://atastypixel.com/blog/2010/03/11/the-making-of-talkie-broadcasting/">Part 1</a> of this series, I wrote about basic broadcasting.  This works fine with one network device, but it&#8217;s worth discussing how to send through all devices, so you can communicate with others connected via, say, Ethernet and WiFi simultaneously.</p>

<p>So, in Part 2 I&#8217;ll write about the approach I took in Talkie for broadcasting from all network devices (a.k.a. network interfaces), so that one can communicate with others connected via WiFi, Ethernet (on a Mac), and any other network devices simultaneously.</p>

<p><span id="more-1901"></span></p>

<h2>Bind them</h2>

<p>From Part 1, we have a <a href="http://atastypixel.com/blog/2010/03/11/the-making-of-talkie-broadcasting/">working broadcast mechanism</a>, but it will only send through the default interface &#8212; whatever you&#8217;re connected to the network via.  This is often sufficient, but if you have more than one device that you communicate through, like Ethernet and WiFi, then you will find that it only works with one.</p>

<p>In order to send through <em>all</em> your connected network interfaces, we need to create one socket for each interface, and <em>bind</em> the socket to its corresponding interface.</p>

<p>Here&#8217;s how:</p>

<p>First, we need to obtain a list of all network interfaces with <code>getifaddrs</code>.</p>


<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #6e371a;">#include &lt;ifaddrs.h&gt;</span>
...
<span style="color: #a61390;">struct</span> ifaddrs <span style="color: #002200;">*</span>addrs;
<span style="color: #a61390;">int</span> result <span style="color: #002200;">=</span> getifaddrs<span style="color: #002200;">&#40;</span><span style="color: #002200;">&amp;</span>addrs<span style="color: #002200;">&#41;</span>;
<span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span> result &lt; <span style="color: #2400d9;">0</span> <span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
  <span style="color: #11740a; font-style: italic;">// Error occurred</span>
  <span style="color: #a61390;">return</span> <span style="color: #2400d9;">0</span>;
<span style="color: #002200;">&#125;</span></pre></div></div>


<p>Now, <code>addrs</code> is a list of interfaces that we can iterate over.  We now do so, picking out those devices that support broadcasting, and that aren&#8217;t loopback or point-to-point devices &#8212; loopback is an internal interface that is provided for your computer&#8217;s inner dialogue, and point-to-point (ppp) devices include dialup interfaces, 3G modems and the like.  We can exclude those guys.</p>


<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #a61390;">const</span> <span style="color: #a61390;">struct</span> ifaddrs <span style="color: #002200;">*</span>cursor <span style="color: #002200;">=</span> addrs;
<span style="color: #a61390;">while</span> <span style="color: #002200;">&#40;</span> cursor <span style="color: #002200;">!=</span> <span style="color: #a61390;">NULL</span> <span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
  <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span> cursor<span style="color: #002200;">-</span>&gt;ifa_addr<span style="color: #002200;">-</span>&gt;sa_family <span style="color: #002200;">==</span> AF_INET 
          <span style="color: #002200;">&amp;&amp;</span> <span style="color: #002200;">!</span><span style="color: #002200;">&#40;</span>cursor<span style="color: #002200;">-</span>&gt;ifa_flags <span style="color: #002200;">&amp;</span> IFF_LOOPBACK<span style="color: #002200;">&#41;</span> 
          <span style="color: #002200;">&amp;&amp;</span> <span style="color: #002200;">!</span><span style="color: #002200;">&#40;</span>cursor<span style="color: #002200;">-</span>&gt;ifa_flags <span style="color: #002200;">&amp;</span> IFF_POINTOPOINT<span style="color: #002200;">&#41;</span> 
          <span style="color: #002200;">&amp;&amp;</span>  <span style="color: #002200;">&#40;</span>cursor<span style="color: #002200;">-</span>&gt;ifa_flags <span style="color: #002200;">&amp;</span> IFF_BROADCAST<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
&nbsp;
    <span style="color: #11740a; font-style: italic;">// We will do some stuff in here</span>
&nbsp;
  <span style="color: #002200;">&#125;</span>
  cursor <span style="color: #002200;">=</span> cursor<span style="color: #002200;">-</span>&gt;ifa_next;
<span style="color: #002200;">&#125;</span></pre></div></div>


<p>Now, for each interface that meets our criteria, we create a socket (which we covered in <a href="http://atastypixel.com/blog/2010/03/11/the-making-of-talkie-broadcasting/">Part 1</a>), then <code>bind</code> the socket to the network interface, to force transmission from that particular device.  Finally, as we did in Part 1, we enable broadcasting using <code>setsockopt</code> with <code>SO_BROADCAST</code>.</p>

<p>We want to store the sockets we create in an array, so we can access them later.  If we assume a maximum number of interfaces we will support (lets call it <code>kMaxSockets</code>), we can just use an array of that length.  So, putting it together:</p>


<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #6e371a;">#define kMaxSockets 16</span>
...
<span style="color: #a61390;">int</span> sock_fds<span style="color: #002200;">&#91;</span>kMaxSockets<span style="color: #002200;">&#93;</span>;
<span style="color: #a61390;">int</span> number_sockets <span style="color: #002200;">=</span> <span style="color: #2400d9;">0</span>;
&nbsp;
<span style="color: #a61390;">while</span> <span style="color: #002200;">&#40;</span> cursor <span style="color: #002200;">!=</span> <span style="color: #a61390;">NULL</span> <span style="color: #002200;">&amp;&amp;</span> number_sockets &lt; kMaxSockets <span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
  <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span> cursor<span style="color: #002200;">-</span>&gt;ifa_addr<span style="color: #002200;">-</span>&gt;sa_family <span style="color: #002200;">==</span> AF_INET 
          <span style="color: #002200;">&amp;&amp;</span> <span style="color: #002200;">!</span><span style="color: #002200;">&#40;</span>cursor<span style="color: #002200;">-</span>&gt;ifa_flags <span style="color: #002200;">&amp;</span> IFF_LOOPBACK<span style="color: #002200;">&#41;</span> 
          <span style="color: #002200;">&amp;&amp;</span> <span style="color: #002200;">!</span><span style="color: #002200;">&#40;</span>cursor<span style="color: #002200;">-</span>&gt;ifa_flags <span style="color: #002200;">&amp;</span> IFF_POINTOPOINT<span style="color: #002200;">&#41;</span> 
          <span style="color: #002200;">&amp;&amp;</span>  <span style="color: #002200;">&#40;</span>cursor<span style="color: #002200;">-</span>&gt;ifa_flags <span style="color: #002200;">&amp;</span> IFF_BROADCAST<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
&nbsp;
    <span style="color: #11740a; font-style: italic;">// Create socket</span>
    sock_fds<span style="color: #002200;">&#91;</span>number_sockets<span style="color: #002200;">&#93;</span> <span style="color: #002200;">=</span> socket<span style="color: #002200;">&#40;</span>AF_INET, SOCK_DGRAM, <span style="color: #2400d9;">0</span><span style="color: #002200;">&#41;</span>;
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span> sock_fds<span style="color: #002200;">&#91;</span>number_sockets<span style="color: #002200;">&#93;</span> <span style="color: #002200;">==</span> <span style="color: #002200;">-</span><span style="color: #2400d9;">1</span> <span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
      <span style="color: #11740a; font-style: italic;">// Error occurred</span>
      <span style="color: #a61390;">return</span> <span style="color: #2400d9;">0</span>;
    <span style="color: #002200;">&#125;</span>
&nbsp;
    <span style="color: #11740a; font-style: italic;">// Create address from which we want to send, and bind it</span>
    <span style="color: #a61390;">struct</span> sockaddr_in addr;
    <span style="color: #a61390;">memset</span><span style="color: #002200;">&#40;</span><span style="color: #002200;">&amp;</span>addr, <span style="color: #2400d9;">0</span>, <span style="color: #a61390;">sizeof</span><span style="color: #002200;">&#40;</span>addr<span style="color: #002200;">&#41;</span><span style="color: #002200;">&#41;</span>;
    addr.sin_family <span style="color: #002200;">=</span> AF_INET;
    addr.sin_addr <span style="color: #002200;">=</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">struct</span> sockaddr_in <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>cursor<span style="color: #002200;">-</span>&gt;ifa_addr<span style="color: #002200;">&#41;</span><span style="color: #002200;">-</span>&gt;sin_addr;
    addr.sin_port <span style="color: #002200;">=</span> htons<span style="color: #002200;">&#40;</span><span style="color: #2400d9;">0</span><span style="color: #002200;">&#41;</span>;
&nbsp;
    <span style="color: #a61390;">int</span> result <span style="color: #002200;">=</span> bind<span style="color: #002200;">&#40;</span>sock_fds<span style="color: #002200;">&#91;</span>number_sockets<span style="color: #002200;">&#93;</span>, <span style="color: #002200;">&#40;</span><span style="color: #a61390;">struct</span> sockaddr<span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&amp;</span>addr, <span style="color: #a61390;">sizeof</span><span style="color: #002200;">&#40;</span>addr<span style="color: #002200;">&#41;</span><span style="color: #002200;">&#41;</span>;
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span> result &lt; <span style="color: #2400d9;">0</span> <span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
      <span style="color: #11740a; font-style: italic;">// Error occurred</span>
      <span style="color: #a61390;">return</span> <span style="color: #2400d9;">0</span>;
    <span style="color: #002200;">&#125;</span>
&nbsp;
    <span style="color: #11740a; font-style: italic;">// Enable broadcast</span>
    <span style="color: #a61390;">int</span> flag <span style="color: #002200;">=</span> <span style="color: #2400d9;">1</span>;
    result <span style="color: #002200;">=</span> setsockopt<span style="color: #002200;">&#40;</span>sock_fds<span style="color: #002200;">&#91;</span>number_sockets<span style="color: #002200;">&#93;</span>, SOL_SOCKET, SO_BROADCAST, <span style="color: #002200;">&amp;</span>flag, <span style="color: #a61390;">sizeof</span><span style="color: #002200;">&#40;</span>flag<span style="color: #002200;">&#41;</span><span style="color: #002200;">&#41;</span>;
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span> result <span style="color: #002200;">!=</span> <span style="color: #2400d9;">0</span> <span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
      <span style="color: #11740a; font-style: italic;">// Error occurred</span>
      <span style="color: #a61390;">return</span> <span style="color: #2400d9;">0</span>;
    <span style="color: #002200;">&#125;</span>
&nbsp;
    number_sockets<span style="color: #002200;">++</span>;
  <span style="color: #002200;">&#125;</span>
  cursor <span style="color: #002200;">=</span> cursor<span style="color: #002200;">-</span>&gt;ifa_next;
<span style="color: #002200;">&#125;</span></pre></div></div>


<p>Finally, as before, we can setup a broadcast address to send to, and use <code>sendto</code> to broadcast, this time for each socket we created:</p>


<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #11740a; font-style: italic;">// Initialise broadcast address</span>
<span style="color: #a61390;">struct</span> sockaddr_in addr;
<span style="color: #a61390;">memset</span><span style="color: #002200;">&#40;</span><span style="color: #002200;">&amp;</span>addr, <span style="color: #2400d9;">0</span>, <span style="color: #a61390;">sizeof</span><span style="color: #002200;">&#40;</span>addr<span style="color: #002200;">&#41;</span><span style="color: #002200;">&#41;</span>;
addr.sin_family <span style="color: #002200;">=</span> AF_INET;
addr.sin_addr.s_addr <span style="color: #002200;">=</span> INADDR_BROADCAST;
addr.sin_port <span style="color: #002200;">=</span> htons<span style="color: #002200;">&#40;</span>kPortNumber<span style="color: #002200;">&#41;</span>;
&nbsp;
<span style="color: #11740a; font-style: italic;">// Send through each interface</span>
<span style="color: #a61390;">int</span> i;
<span style="color: #a61390;">for</span> <span style="color: #002200;">&#40;</span> i<span style="color: #002200;">=</span><span style="color: #2400d9;">0</span>; i&lt;number_sockets; i<span style="color: #002200;">++</span> <span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
  <span style="color: #a61390;">int</span> result <span style="color: #002200;">=</span> sendto<span style="color: #002200;">&#40;</span>sock_fds<span style="color: #002200;">&#91;</span>i<span style="color: #002200;">&#93;</span>, data, length, <span style="color: #2400d9;">0</span>, <span style="color: #002200;">&#40;</span><span style="color: #a61390;">struct</span> sockaddr<span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&amp;</span>addr, <span style="color: #a61390;">sizeof</span><span style="color: #002200;">&#40;</span>addr<span style="color: #002200;">&#41;</span><span style="color: #002200;">&#41;</span>;
  <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span> result &lt; <span style="color: #2400d9;">0</span> <span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
    <span style="color: #11740a; font-style: italic;">// Error occurred</span>
    <span style="color: #a61390;">return</span> <span style="color: #2400d9;">0</span>;
  <span style="color: #002200;">&#125;</span>
<span style="color: #002200;">&#125;</span></pre></div></div>


<p>Note that the receive routine only needs a single socket, as we can receive on any interface when we use <code>INADDR_ANY</code>.  So, the receive routine needs no changes from the single-interface version we saw in Part 1.</p>

<p>Here&#8217;s the test app with the above modification: <a href="http://atastypixel.com/blog/wp-content/uploads/2010/05/broadcast_sample_all_interfaces.c" title="broadcast_sample_all_interfaces.c">broadcast_sample_all_interfaces.c</a></p>

<p>Again, compile by opening Terminal, and typing <code>make broadcast_sample_all_interfaces</code> or <code>cc -o broadcast_sample_all_interfaces broadcast_sample_all_interfaces.c</code>, then run it with <code>./broadcast_sample_all_interfaces "Message to send"</code> to send, or just <code>./broadcast_sample_all_interfaces</code> with no arguments to listen.</p>

<p>You may notice that multiple messages may be received: These have probably arrived via multiple network interfaces, virtual or otherwise.  It&#8217;s usually a good idea to check for duplicate messages, if this is an issue for program operation, by including a sequence number into the message &#8212; this will be discussed in Part 3.</p>

<p>It also may be a good idea to ignore your own messages, which may find their way back to you.  One way to accomplish this is to examine the source address (<code>addr</code> in the example above) and compare it with your local interface addresses (stored in <code>addrs</code>, above).  If you get a match, the message came from you, and you can drop it.</p>

<h2>Multicast</h2>

<p>Broadcast is fine when everyone on the local network is interested in what you have to say.  If this isn&#8217;t the case, though (lets face it, those Chuck Norris jokes aren&#8217;t for everyone), effort is wasted delivering to those who aren&#8217;t particularly interested.</p>

<p>Multicast works by using a specific address that one &#8216;subscribes&#8217; to in order to receive messages sent to that address.  So, it&#8217;s opt-in, allowing for better efficiency and one day, Internet-wide support for &#8216;to-many&#8217; communications.</p>

<p>Well, in theory.  Actually, multicast is still quite new, and for the most part &#8212; from what I understand &#8212; it behaves pretty much like broadcast on a local area network.  However, support can only increase, and given that many services already use it &#8212; Multicast DNS (mDNS), also known as Bonjour, being one of the most well-known examples &#8212; it seems a good idea to follow their lead.  Note also that IPv6, the successor to IP as we know it, and our saviour-to-be from our little Internet overpopulation problem (among other things), doesn&#8217;t even have broadcast provisions &#8212; the future is all multicast.</p>

<p>So, for these reasons, Talkie speaks multicast, instead of plain ol&#8217; broadcast.</p>

<p>Making use of multicast is relatively straightforward: To receive, you join a multicast group using <code>setsockopt</code> with <code>IP_ADD_MEMBERSHIP</code>, and the address of the multicast group, which is in the range 224.0.0.0-239.255.255.255 (for IPv4, of course).  To send, you just use <code>sendto</code> to transmit data to a multicast group address.</p>

<p>Using multicast on all network interfaces is just a little more complicated.  Here&#8217;s how it&#8217;s done with Talkie:</p>

<h3>Sending</h3>

<p>The send routine is very similar to the one above, using broadcast.  However, instead of using <code>bind</code> to specify the outgoing network interface and enabling broadcast, we assign a multicast interface using <code>setsockopt</code> with <code>IP_MULTICAST_IF</code>.  And, instead of transmitting to the broadcast address, we transmit to the multicast group address.</p>

<p>Again, we loop through all network interfaces.  This time, we pick out those that support multicast (<code>ifa_flags &amp; IFF_MULTICAST</code>):</p>


<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #a61390;">const</span> <span style="color: #a61390;">struct</span> ifaddrs <span style="color: #002200;">*</span>cursor <span style="color: #002200;">=</span> addrs;
<span style="color: #a61390;">while</span> <span style="color: #002200;">&#40;</span> cursor <span style="color: #002200;">!=</span> <span style="color: #a61390;">NULL</span> <span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
  <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span> cursor<span style="color: #002200;">-</span>&gt;ifa_addr<span style="color: #002200;">-</span>&gt;sa_family <span style="color: #002200;">==</span> AF_INET 
          <span style="color: #002200;">&amp;&amp;</span> <span style="color: #002200;">!</span><span style="color: #002200;">&#40;</span>cursor<span style="color: #002200;">-</span>&gt;ifa_flags <span style="color: #002200;">&amp;</span> IFF_LOOPBACK<span style="color: #002200;">&#41;</span> 
          <span style="color: #002200;">&amp;&amp;</span> <span style="color: #002200;">!</span><span style="color: #002200;">&#40;</span>cursor<span style="color: #002200;">-</span>&gt;ifa_flags <span style="color: #002200;">&amp;</span> IFF_POINTOPOINT<span style="color: #002200;">&#41;</span> 
          <span style="color: #002200;">&amp;&amp;</span>  <span style="color: #002200;">&#40;</span>cursor<span style="color: #002200;">-</span>&gt;ifa_flags <span style="color: #002200;">&amp;</span> IFF_MULTICAST<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
&nbsp;
    <span style="color: #11740a; font-style: italic;">// We will do some stuff in here</span>
&nbsp;
  <span style="color: #002200;">&#125;</span>
  cursor <span style="color: #002200;">=</span> cursor<span style="color: #002200;">-</span>&gt;ifa_next;
<span style="color: #002200;">&#125;</span></pre></div></div>


<p>And, after creating the socket, we assign the interface:</p>


<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span> setsockopt<span style="color: #002200;">&#40;</span>sock_fds<span style="color: #002200;">&#91;</span>number_sockets<span style="color: #002200;">&#93;</span>, IPPROTO_IP, IP_MULTICAST_IF, <span style="color: #002200;">&amp;</span><span style="color: #002200;">&#40;</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">struct</span> sockaddr_in <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>cursor<span style="color: #002200;">-</span>&gt;ifa_addr<span style="color: #002200;">&#41;</span><span style="color: #002200;">-</span>&gt;sin_addr, <span style="color: #a61390;">sizeof</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">struct</span> in_addr<span style="color: #002200;">&#41;</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">!=</span> <span style="color: #2400d9;">0</span>  <span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
  <span style="color: #11740a; font-style: italic;">// Error occurred</span>
  <span style="color: #a61390;">return</span> <span style="color: #2400d9;">0</span>;
<span style="color: #002200;">&#125;</span></pre></div></div>


<p>Finally, as a nicety, we can disable loopback so that we don&#8217;t receive our own messages.  This isn&#8217;t 100% reliable, as certain network conditions can result in the local machine still receiving its outgoing messages, but it can improve efficiency:</p>


<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;">u_char loop <span style="color: #002200;">=</span> <span style="color: #2400d9;">0</span>;
<span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span> setsockopt<span style="color: #002200;">&#40;</span>sock_fds<span style="color: #002200;">&#91;</span>number_sockets<span style="color: #002200;">&#93;</span>, IPPROTO_IP, IP_MULTICAST_LOOP, <span style="color: #002200;">&amp;</span>loop, <span style="color: #a61390;">sizeof</span><span style="color: #002200;">&#40;</span>loop<span style="color: #002200;">&#41;</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">!=</span> <span style="color: #2400d9;">0</span> <span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
  <span style="color: #11740a; font-style: italic;">// Error occurred</span>
  <span style="color: #a61390;">return</span> <span style="color: #2400d9;">0</span>;
<span style="color: #002200;">&#125;</span></pre></div></div>


<p>Now that our sockets are set up, we can prepare to send to the multicast address:</p>


<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #6e371a;">#define kMulticastAddress &quot;224.0.0.123&quot;</span>
...
<span style="color: #a61390;">memset</span><span style="color: #002200;">&#40;</span><span style="color: #002200;">&amp;</span>addr, <span style="color: #2400d9;">0</span>, <span style="color: #a61390;">sizeof</span><span style="color: #002200;">&#40;</span>addr<span style="color: #002200;">&#41;</span><span style="color: #002200;">&#41;</span>;
addr.sin_family <span style="color: #002200;">=</span> AF_INET;
addr.sin_addr.s_addr <span style="color: #002200;">=</span> inet_addr<span style="color: #002200;">&#40;</span>kMulticastAddress<span style="color: #002200;">&#41;</span>;
addr.sin_port <span style="color: #002200;">=</span> htons<span style="color: #002200;">&#40;</span>kPortNumber<span style="color: #002200;">&#41;</span>;</pre></div></div>


<p>And, as before, we send through each of the sockets we created:</p>


<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #a61390;">int</span> i;
<span style="color: #a61390;">for</span> <span style="color: #002200;">&#40;</span> i<span style="color: #002200;">=</span><span style="color: #2400d9;">0</span>; i&lt;number_sockets; i<span style="color: #002200;">++</span> <span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
  <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span> sendto<span style="color: #002200;">&#40;</span>sock_fds<span style="color: #002200;">&#91;</span>i<span style="color: #002200;">&#93;</span>, data, length, <span style="color: #2400d9;">0</span>, <span style="color: #002200;">&#40;</span><span style="color: #a61390;">struct</span> sockaddr<span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&amp;</span>addr, <span style="color: #a61390;">sizeof</span><span style="color: #002200;">&#40;</span>addr<span style="color: #002200;">&#41;</span><span style="color: #002200;">&#41;</span> &lt; <span style="color: #2400d9;">0</span> <span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
    <span style="color: #11740a; font-style: italic;">// Error occurred</span>
    <span style="color: #a61390;">return</span> <span style="color: #2400d9;">0</span>;
  <span style="color: #002200;">&#125;</span>
<span style="color: #002200;">&#125;</span></pre></div></div>


<h3>Receiving</h3>

<p>Receiving messages from a multicast group on several network interfaces is a little more involved than doing so with broadcast: We need to subscribe to the multicast group from each network interface, explicitly.  If we were to just specify no device in particular, the system would choose a single interface for us, neglecting the others.</p>

<p>Joining the multicast group for each interface takes place in a now-familiar loop:</p>


<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #a61390;">const</span> <span style="color: #a61390;">struct</span> ifaddrs <span style="color: #002200;">*</span>cursor <span style="color: #002200;">=</span> addrs;
<span style="color: #a61390;">while</span> <span style="color: #002200;">&#40;</span> cursor <span style="color: #002200;">!=</span> <span style="color: #a61390;">NULL</span> <span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
  <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span> cursor<span style="color: #002200;">-</span>&gt;ifa_addr<span style="color: #002200;">-</span>&gt;sa_family <span style="color: #002200;">==</span> AF_INET 
          <span style="color: #002200;">&amp;&amp;</span> <span style="color: #002200;">!</span><span style="color: #002200;">&#40;</span>cursor<span style="color: #002200;">-</span>&gt;ifa_flags <span style="color: #002200;">&amp;</span> IFF_LOOPBACK<span style="color: #002200;">&#41;</span> 
          <span style="color: #002200;">&amp;&amp;</span> <span style="color: #002200;">!</span><span style="color: #002200;">&#40;</span>cursor<span style="color: #002200;">-</span>&gt;ifa_flags <span style="color: #002200;">&amp;</span> IFF_POINTOPOINT<span style="color: #002200;">&#41;</span> 
          <span style="color: #002200;">&amp;&amp;</span>  <span style="color: #002200;">&#40;</span>cursor<span style="color: #002200;">-</span>&gt;ifa_flags <span style="color: #002200;">&amp;</span> IFF_MULTICAST<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
&nbsp;
    <span style="color: #11740a; font-style: italic;">// We will do some stuff in here</span>
&nbsp;
  <span style="color: #002200;">&#125;</span>
  cursor <span style="color: #002200;">=</span> cursor<span style="color: #002200;">-</span>&gt;ifa_next;
<span style="color: #002200;">&#125;</span></pre></div></div>


<p>For each network device, we use the <code>IP_ADD_MEMBERSHIP</code> property with <code>setsockopt</code> to join &#8212; thereby subscribing to any messages sent to the multicast group address that reach that network interface.</p>

<p>First, we prepare the join request structure.  This provides the multicast group address, and the network interface:</p>


<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #a61390;">struct</span> ip_mreq multicast_req;
<span style="color: #a61390;">memset</span><span style="color: #002200;">&#40;</span><span style="color: #002200;">&amp;</span>multicast_req, <span style="color: #2400d9;">0</span>, <span style="color: #a61390;">sizeof</span><span style="color: #002200;">&#40;</span>multicast_req<span style="color: #002200;">&#41;</span><span style="color: #002200;">&#41;</span>;
multicast_req.imr_multiaddr.s_addr <span style="color: #002200;">=</span> inet_addr<span style="color: #002200;">&#40;</span>kMulticastAddress<span style="color: #002200;">&#41;</span>;
multicast_req.imr_interface <span style="color: #002200;">=</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">struct</span> sockaddr_in <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>cursor<span style="color: #002200;">-</span>&gt;ifa_addr<span style="color: #002200;">&#41;</span><span style="color: #002200;">-</span>&gt;sin_addr;</pre></div></div>


<p>Now we use this structure to join the group:</p>


<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span> setsockopt<span style="color: #002200;">&#40;</span>sock_fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, <span style="color: #002200;">&amp;</span>multicast_req, <span style="color: #a61390;">sizeof</span><span style="color: #002200;">&#40;</span>multicast_req<span style="color: #002200;">&#41;</span><span style="color: #002200;">&#41;</span> &lt; <span style="color: #2400d9;">0</span> <span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
  <span style="color: #11740a; font-style: italic;">// Error occurred</span>
  <span style="color: #a61390;">return</span> <span style="color: #2400d9;">0</span>;
<span style="color: #002200;">&#125;</span></pre></div></div>


<p>Now, a caveat: While it&#8217;s perfectly legal to join the same multicast group on more than one network interface, and up to 20 memberships may be added to the same socket (see <a href="http://developer.apple.com/mac/library/documentation/Darwin/Reference/ManPages/man4/ip.4.html">ip(4)</a>), for some reason, OS X spews &#8216;Address already in use&#8217; errors when we actually attempt it.</p>

<p>As a workaround, we can &#8216;drop&#8217; the membership first, which would normally have no effect, as we have not yet joined on this interface.  However, it enables us to perform the subsequent join, without dropping prior memberships.</p>

<p>So, before we perform the above <code>IP_ADD_MEMBERSHIP</code>, we do a <code>IP_DROP_MEMBERSHIP</code> first:</p>


<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;">setsockopt<span style="color: #002200;">&#40;</span>sock_fd, IPPROTO_IP, IP_DROP_MEMBERSHIP, <span style="color: #002200;">&amp;</span>multicast_req, <span style="color: #a61390;">sizeof</span><span style="color: #002200;">&#40;</span>multicast_req<span style="color: #002200;">&#41;</span><span style="color: #002200;">&#41;</span>;</pre></div></div>


<p>This sets up our socket to receive messages sent to the multicast group that are received via any interface.</p>

<p>Here it is all put together: <a href="http://atastypixel.com/blog/wp-content/uploads/2010/05/multicast_sample.c" title="multicast_sample.c">multicast_sample.c</a></p>

<p>Compile by opening Terminal, and typing <code>make multicast_sample</code> or <code>cc -o multicast_sample multicast_sample .c</code>, then run it with <code>./multicast_sample "Message to send"</code> to send, or just <code>./multicast_sample</code> with no arguments to listen.</p>

<h2>Still to come</h2>

<p>So, now we mostly have networking covered.  There&#8217;s one obvious omission, though, for an iPhone app: Bluetooth.  In Part 3, I&#8217;ll discuss how to perform communications over Bluetooth on the iPhone, in a way that&#8217;s compatible with the above generic network communications.  I&#8217;ll also talk about how to connect to other devices automatically, without user intervention &#8212; This is one particularly popular feature of Talkie that allows it to behave more like a real walkie-talkie.</p>

<p>I promised in Part 1 that I&#8217;d talk about packet formats.   We&#8217;ve covered a lot of ground in Part 2, however, so it shall be postponed to Part 3 &#8212; I&#8217;ll discuss how to ensure you get messages in the correct order by using sequence numbers, as well as providing for versioning and a few other bits and pieces.</p>
 <img src="http://atastypixel.com/blog/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=1901" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://atastypixel.com/blog/the-making-of-talkie-multi-interface-broadcasting-and-multicast/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>The Making of Talkie: Broadcasting</title>
		<link>http://atastypixel.com/blog/the-making-of-talkie-broadcasting/</link>
		<comments>http://atastypixel.com/blog/the-making-of-talkie-broadcasting/#comments</comments>
		<pubDate>Thu, 11 Mar 2010 00:31:59 +0000</pubDate>
		<dc:creator>Michael Tyson</dc:creator>
				<category><![CDATA[Geekspeak]]></category>
		<category><![CDATA[Broadcast]]></category>
		<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[Networking]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[Talkie]]></category>
		<category><![CDATA[Talkie-for-Mac]]></category>
		<category><![CDATA[Tutorial]]></category>

		<guid isPermaLink="false">http://atastypixel.com/blog/?p=1854</guid>
		<description><![CDATA[Part 1 Talkie is my newest product, the result of a collaboration with a good designer friend, Tim Churchward, who did the user interface. Talkie is a little different from many of the other walkie talkie applications on the App Store (aside from the fact that much of it was written by me from our [...]]]></description>
			<content:encoded><![CDATA[<h2>Part 1</h2>

<p><img src="http://atastypixel.com/media/images/products/talkie/icon-medium.jpg" width="183" height="148" alt="Talkie" style="float:right;" /><a href="http://atastypixel.com/products/talkie">Talkie</a> is my newest product, the result of a collaboration with a good designer friend, Tim Churchward, who did the user interface.</p>

<p>Talkie is a little different from many of the other walkie talkie applications on the App Store (aside from the fact that much of it was written by me from our motorhome in <a href="http://michael.tyson.id.au/2010/01/26/down-time-in-hammamet/">Tunisia</a>!), and I thought I&#8217;d write a little about some of the tech underpinning the app, and some of the choices we made.   Along the way it may get a little tutorial-esque.</p>

<ul>
<li>This first part will introduce our initial motivations, and will talk about basic broadcast communications &#8212; the broadcast communications part may be very familiar to some, in which case it may be worth skipping to the next instalment.</li>
<li>In the <a href="http://atastypixel.com/blog/the-making-of-talkie-broadcasting/">second part</a>, I&#8217;ll continue the theme of networking, and will talk about what I ended up with for Talkie&#8217;s network code after addressing a couple of things, including switching to multicast.  </li>
<li>Finally, I&#8217;ll talk audio, dual platform development, and anything else I think of along the way (Actually, I&#8217;m aching to talk about one particular upcoming feature that had me jumping up and down when I first thought of it, but for now, mum&#8217;s the word on that one.)<span id="more-1854"></span>## Inspiration</li>
</ul>

<p><img src="http://atastypixel.com/media/images/products/talkie/screen-iphone.jpg" width="187" height="400" alt="Talkie screenshot" style="float:right;" />Right from the start, we wanted a product that brought back the fun walkie talkie experience we remember from our childhoods.  I&#8217;m talking colourful plastic, whip antennas and hiding in tree-houses.   This was mostly Tim&#8217;s domain, so I shall leave it to him to discuss how he found that in the user interface.</p>

<p>It also meant stepping back from traditional voice chat, with manual call initialisation and termination and simple one-to-one calls.  We wanted to mimic a radio, so that meant broadcasting as soon as you hit &#8220;Talk&#8221; &#8212; whereupon anyone in the neighbourhood would hear you.</p>

<p>Basically, we wanted to get as close to the real thing as was practical.  This included the addition of a prominent &#8216;morse code&#8217; button, of course, as well as a &#8216;squelch&#8217; control for &#8216;fine tuning&#8217;, which simulated the static of bad reception.</p>

<h2>Going dual-platform</h2>

<p><img src="http://atastypixel.com/media/images/products/talkie-for-mac/screenshot.jpg" width="232" height="190" alt="Talkie for Mac" style="float:left;" />Soon after I started developing Talkie, I realised I wanted a version for the Mac too.</p>

<p>Having Talkie both on the iPhone and on the Mac made sense, as we envisioned that a fairly common usage pattern would involve communication between a desktop and a handheld &#8212; say, someone wandering a campus with the iPhone in their pocket, staying in touch with friends at their desks.</p>

<p>We wanted to offer good value with Talkie, which is why we made Talkie for Mac available for free, when it&#8217;s used with Talkie for iPhone.</p>

<p>One of the very convenient things about developing for both iPhone and Mac is that the platforms are so similar, porting code is usually effortless.  So, going dual-platform was an easy decision.</p>

<h2>Finding common ground</h2>

<p>The result of all of this was the need to develop or find a communication protocol and codec that would work across the iPhone and the Mac, over both Bluetooth for iPhone-iPhone communication, and Wifi, for communication between iPhones and iPhones, and iPhones and Macs.</p>

<p>Version 3.0 of the iPhone SDK introduced the GameKit framework and as part of it, <code>GKVoiceChatService</code>, which provides two person voice chat straight out of the box.  Immediately it was clear that it wouldn&#8217;t serve our purposes &#8212; two person is not broadcast.  I was also keen to provide a Mac version of Talkie, and given that GameKit is iPhone-only, it was time to go off the beaten track.</p>

<p>There are a variety of voice communication protocols out there, with varying licences and varying complexity and feature sets.  I could&#8217;ve spent a week or two researching the options and evaluating them against our need for broadcast functionality, figuring out compilation and linking on the iPhone, resolving any compatibility or performance issues that arose, etc.</p>

<p>Or, I could spend a day putting together a few big building blocks provided by Apple (and the underlying Unix system) and have an easily tweakable working solution that precisely meets our needs and provides for future features.</p>

<p>It may not have been the most scientific approach, but the core of Talkie&#8217;s functionality was up and running on our home wi-fi network within about four hours, and it was working well.</p>

<h2>Getting from a to b (and c, d, e, and f)</h2>

<p>For those unfamiliar with the ins and outs of TCP/IP (the most common communication protocol &#8212; or rather, set of protocols &#8212; between computers, and the fundamental building block of the Internet), communication between computers can be connection-oriented, or connectionless.</p>

<p>Connection-oriented (a.k.a. &#8216;reliable&#8217;) communications are most common: They&#8217;re used when you open up a website, connect to iChat, or check your email.  This is the TCP part of TCP/IP, and includes niceties like built-in guaranteed delivery via retransmission (providing your cat hasn&#8217;t eaten your network cable, of course) and packet ordering so you receive the messages in the right order.  This only works between two computers, though &#8211; you and the server.</p>

<p>Connectionless (or &#8216;unreliable&#8217;) communications are much more open &#8212; it&#8217;s basically just a spray of messages: The data isn&#8217;t carefully ushered along, it&#8217;s just spat out and left to fend for itself.  This is UDP, and is commonly used for time-sensitive applications like audio communication, network gaming, etc., where once a packet arrives late, it&#8217;s useless: No point mucking about re-sending lost data that&#8217;s going to be past its use-by date by the time it arrives.  The other thing about UDP is that, because there&#8217;s no co-operation required from the destination (to acknowledge receipt, etc.), it lends itself to one-to-many communications &#8212; broadcast.</p>

<p>Just what we&#8217;re after.</p>

<p>So, we use connectionless communications (UDP) to send messages containing the audio, and anyone who receives them unpackages and plays the audio within.</p>

<p>The basic mechanics of this are fairly simple, once you get past the arguably cryptic C syntax.</p>

<p>Here&#8217;s how it works.</p>

<h3>Sending</h3>

<p>On the transmission end, on startup, you create a socket using the <code>socket</code> call:</p>


<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #6e371a;">#include &lt;sys/socket.h&gt;</span>
<span style="color: #6e371a;">#include &lt;netinet/in.h&gt;</span>
<span style="color: #6e371a;">#include &lt;arpa/inet.h&gt;</span>
...
<span style="color: #a61390;">int</span> sock_fd <span style="color: #002200;">=</span> socket<span style="color: #002200;">&#40;</span>AF_INET, SOCK_DGRAM, <span style="color: #2400d9;">0</span><span style="color: #002200;">&#41;</span>;
<span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span> sock_fd &lt; <span style="color: #2400d9;">0</span> <span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
   <span style="color: #11740a; font-style: italic;">// Error occurred</span>
<span style="color: #002200;">&#125;</span></pre></div></div>


<p>The socket, identified by <code>sock_fd</code>, will be created using the IPv4 domain (<code>AF_INET</code>), a &#8216;datagram&#8217; type (<code>SOCK_DFRAM</code>: that&#8217;s connectionless communication &#8212; if we wanted connection-oriented, we could put in <code>SOCK_STREAM</code> here instead), using protocol 0, which is IP.</p>

<p>Then, we enable broadcasting:</p>


<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #a61390;">int</span> flag <span style="color: #002200;">=</span> <span style="color: #2400d9;">1</span>;
<span style="color: #a61390;">int</span> result <span style="color: #002200;">=</span> setsockopt<span style="color: #002200;">&#40;</span>sock_fd, SOL_SOCKET, SO_BROADCAST, <span style="color: #002200;">&amp;</span>flag, <span style="color: #a61390;">sizeof</span><span style="color: #002200;">&#40;</span>flag<span style="color: #002200;">&#41;</span><span style="color: #002200;">&#41;</span>;
<span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span> result &lt; <span style="color: #2400d9;">0</span> <span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
   <span style="color: #11740a; font-style: italic;">// Error occurred</span>
<span style="color: #002200;">&#125;</span></pre></div></div>


<p>That is, we set the <code>SO_BROADCAST</code> option at the <code>SOL_SOCKET</code> level to 1 (via the <code>flag</code> variable, which we pass in as a pointer), thereby requesting permission from the operating system kernel to broadcast.</p>

<p>Now we have the carrier pigeon coop at our disposal, we can start dispatching pigeons.  First, we fill out the address:</p>


<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #6e371a;">#define kPortNumber 1234</span>
...
<span style="color: #a61390;">struct</span> sockaddr_in addr;
<span style="color: #a61390;">memset</span><span style="color: #002200;">&#40;</span><span style="color: #002200;">&amp;</span>addr, <span style="color: #2400d9;">0</span>, <span style="color: #a61390;">sizeof</span><span style="color: #002200;">&#40;</span>addr<span style="color: #002200;">&#41;</span><span style="color: #002200;">&#41;</span>;
addr.sin_family <span style="color: #002200;">=</span> AF_INET;
addr.sin_addr.s_addr <span style="color: #002200;">=</span> INADDR_BROADCAST;
addr.sin_port <span style="color: #002200;">=</span> htons<span style="color: #002200;">&#40;</span>kPortNumber<span style="color: #002200;">&#41;</span>;</pre></div></div>


<p>(Note, <code>htons</code> converts <code>kPortNumber</code> into a format that can be understood by any computer, regardless of the way it represents numbers internally.)</p>

<p>Now, send:</p>


<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #400080;">NSData</span> <span style="color: #002200;">*</span>dataToSend;
result <span style="color: #002200;">=</span> sendto<span style="color: #002200;">&#40;</span>sock_fd, <span style="color: #002200;">&#91;</span>data bytes<span style="color: #002200;">&#93;</span>, <span style="color: #002200;">&#91;</span>data length<span style="color: #002200;">&#93;</span>, <span style="color: #2400d9;">0</span>, <span style="color: #002200;">&#40;</span><span style="color: #a61390;">struct</span> sockaddr<span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&amp;</span>addr, <span style="color: #a61390;">sizeof</span><span style="color: #002200;">&#40;</span>addr<span style="color: #002200;">&#41;</span><span style="color: #002200;">&#41;</span>;
<span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span> result &lt; <span style="color: #2400d9;">0</span> <span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
   <span style="color: #11740a; font-style: italic;">// Error occurred</span>
<span style="color: #002200;">&#125;</span></pre></div></div>


<h3>Receiving</h3>

<p>That takes care of outgoing messages.  To receive them, we want another socket:</p>


<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #a61390;">int</span> sock_fd <span style="color: #002200;">=</span> socket<span style="color: #002200;">&#40;</span>AF_INET, SOCK_DGRAM, <span style="color: #2400d9;">0</span><span style="color: #002200;">&#41;</span>;
<span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span> sock_fd &lt; <span style="color: #2400d9;">0</span> <span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
   <span style="color: #11740a; font-style: italic;">// Error occurred</span>
<span style="color: #002200;">&#125;</span></pre></div></div>


<p>Now we specify where we want to receive messages from, by &#8216;binding&#8217; the socket:</p>


<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #a61390;">struct</span> sockaddr_in addr;
<span style="color: #a61390;">memset</span><span style="color: #002200;">&#40;</span><span style="color: #002200;">&amp;</span>addr, <span style="color: #2400d9;">0</span>, <span style="color: #a61390;">sizeof</span><span style="color: #002200;">&#40;</span>addr<span style="color: #002200;">&#41;</span><span style="color: #002200;">&#41;</span>;
addr.sin_family <span style="color: #002200;">=</span> AF_INET;
addr.sin_addr.s_addr <span style="color: #002200;">=</span> INADDR_ANY;
addr.sin_port <span style="color: #002200;">=</span> htons<span style="color: #002200;">&#40;</span>kPortNumber<span style="color: #002200;">&#41;</span>;
result <span style="color: #002200;">=</span> bind<span style="color: #002200;">&#40;</span>sock_fd, <span style="color: #002200;">&#40;</span><span style="color: #a61390;">struct</span> sockaddr<span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&amp;</span>addr, <span style="color: #a61390;">sizeof</span><span style="color: #002200;">&#40;</span>addr<span style="color: #002200;">&#41;</span><span style="color: #002200;">&#41;</span>;
<span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span> result &lt; <span style="color: #2400d9;">0</span> <span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
  <span style="color: #11740a; font-style: italic;">// Error occurred</span>
<span style="color: #002200;">&#125;</span></pre></div></div>


<p>And we pass a buffer to <code>recvfrom</code> to fill up with tasty morsels of data:</p>


<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #6e371a;">#define kBufferSize 1024</span>
...
<span style="color: #a61390;">char</span> buffer<span style="color: #002200;">&#91;</span>kBufferSize<span style="color: #002200;">&#93;</span>;
<span style="color: #a61390;">int</span> addr_len <span style="color: #002200;">=</span> <span style="color: #a61390;">sizeof</span><span style="color: #002200;">&#40;</span>addr<span style="color: #002200;">&#41;</span>;
<span style="color: #a61390;">int</span> bytes_received <span style="color: #002200;">=</span> recvfrom<span style="color: #002200;">&#40;</span>sock_fd, buffer, kBufferSize, <span style="color: #2400d9;">0</span>, <span style="color: #002200;">&#40;</span>struck sockaddr<span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&amp;</span>addr, <span style="color: #002200;">&amp;</span>addr_len<span style="color: #002200;">&#41;</span>;
<span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span> bytes_received &lt; <span style="color: #2400d9;">0</span> <span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
   <span style="color: #11740a; font-style: italic;">// Error occurred</span>
<span style="color: #002200;">&#125;</span></pre></div></div>


<p>Voila, we have <code>bytes_received</code> bytes sitting in <code>buffer</code> for us to do something with.  Note also that <code>addr</code> now also contains the address of the sender.  Now we can loop and continue to receive data as it comes in, passing the data off to some other part of the application to deal with.</p>

<p>We can put it all together into a simple test app: <a href="http://atastypixel.com/blog/wp-content/uploads/2010/03/broadcast_sample.c" title="broadcast_sample.c">broadcast_sample.c</a></p>

<p>Compile it by opening up Terminal, and typing <code>make broadcast_sample</code> (or <code>cc -o broadcast_sample broadcast_sample.c</code>, if you like), then run it with <code>./broadcast_sample "Message to send"</code>, or just <code>./broadcast_sample</code> to listen.</p>

<p><pre>
$ ./broadcast_sample 
Listening...
Hello world!
</pre></p>

<p><pre>
$ ./broadcast_sample 'Hello world!'
"Hello world!" transmitted.
</pre></p>

<h2>Coming next</h2>

<p>This will work happily between computers with just one network interface. But, if you have more than one (say, wireless, and an Ethernet connection too), you&#8217;ll notice that it will only communicate through one of the interfaces.  That&#8217;s because just the default interface is used.  You have to explicitly attend to each interface, to broadcast out of each one, and listen on each one.</p>

<p>In the <a href="http://atastypixel.com/blog/the-making-of-talkie-broadcasting/">next part of this series</a>, I&#8217;ll write about how I addressed that, and about multicast, which is used in things like Bonjour (MDNS).  I&#8217;ll also write about designing packet formats.</p>

<p>Thanks for reading!</p>
 <img src="http://atastypixel.com/blog/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=1854" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://atastypixel.com/blog/the-making-of-talkie-broadcasting/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>DIY Twitter image hosting</title>
		<link>http://atastypixel.com/blog/diy-twitter-image-hosting/</link>
		<comments>http://atastypixel.com/blog/diy-twitter-image-hosting/#comments</comments>
		<pubDate>Thu, 07 Jan 2010 14:16:07 +0000</pubDate>
		<dc:creator>Michael Tyson</dc:creator>
				<category><![CDATA[Geekspeak]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[Twitter]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[Workflow]]></category>

		<guid isPermaLink="false">http://atastypixel.com/blog/?p=1757</guid>
		<description><![CDATA[Twitter doesn&#8217;t yet come with its own inline image support, so we tend to be limited to using image hosting services, and linking to them with short URLs. So, services like Tweetpic host the image, and we direct traffic to them in return. Thinking it&#8217;s better to keep things in the family, and take better [...]]]></description>
			<content:encoded><![CDATA[<p>Twitter doesn&#8217;t yet come with its own inline image support, so we tend to be limited to using image hosting services, and linking to them with short URLs.  So, services like Tweetpic host the image, and we direct traffic to them in return.</p>

<p>Thinking it&#8217;s better to keep things in the family, and take better advantage of that traffic, I put together an image hosting setup of my own.  Now viewers come to my own site, instead of someone else&#8217;s!</p>

<p>It looks like <a href="http://twitter.com/ATastyPixel/status/7478572775">this</a></p>

<p>The setup consists of an Automator service, and some PHP smarts on the site.</p>

<p><img src="http://atastypixel.com/blog/wp-content/uploads/2010/01/201001071440.jpg" width="200" height="70" alt="Send Image to Image Hosting" class="alignright polaroid rotation" />Under Snow Leopard, I can right-click on an image in Finder, click &#8216;Send Image to Image Hosting&#8217;, type in a title,  then paste the URL that&#8217;s automatically been put onto my clipboard into a tweet.</p>

<p>Here&#8217;s how it works &#8211; this assumes a moderate level of understanding of PHP and assorted web administration.<span id="more-1757"></span>
<em>Update</em>: I couldn&#8217;t help myself; I made a <a href="http://atastypixel.com/blog/wordpress/plugins/twitter-image-host">WordPress plugin</a> for this, with some extra nice features.</p>

<h2>Presentation</h2>

<p>First, we need to put together a script that will display the image.  What&#8217;s more, it would be nice to give the image a title, and link it back to the Twitter account.</p>

<p>So, we&#8217;ll want a place to put images, and a way to store the corresponding title and account name.</p>

<p>I opted to store the latter in a file alongside the image called <code>(imagename).meta</code>.  I store the title, then a newline, then the Twitter account name.</p>

<p>Lets create <code>image.php</code> &#8212; it should take an <code>image name</code> parameter, excluding the file extension, and display the corresponding image, with any corresponding meta data.</p>

<p>Here&#8217;s a sample:</p>


<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #000088;">$MEDIA_DIR</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;twitter-images&quot;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// Get the image name, but avoid any path shenanigans by just grabbing the 'basename' of the file</span>
<span style="color: #000088;">$image</span> <span style="color: #339933;">=</span> <span style="color: #990000;">basename</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$_REQUEST</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'name'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// Make sure it exists, or report a 404 error</span>
<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span> <span style="color: #339933;">!</span><span style="color: #000088;">$image</span> <span style="color: #339933;">||</span> <span style="color: #339933;">!</span><span style="color: #990000;">is_file</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;<span style="color: #006699; font-weight: bold;">$MEDIA_DIR</span>/<span style="color: #006699; font-weight: bold;">$image</span>.jpg&quot;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #b1b100;">include</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;404.php&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">return</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// Grab the meta data</span>
<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span> <span style="color: #990000;">file_exists</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;<span style="color: #006699; font-weight: bold;">$MEDIA_DIR</span>/<span style="color: #006699; font-weight: bold;">$image</span>.meta&quot;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #990000;">list</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$title</span><span style="color: #339933;">,</span> <span style="color: #000088;">$source</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">=</span> <span style="color: #990000;">file</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;<span style="color: #006699; font-weight: bold;">$MEDIA_DIR</span>/<span style="color: #006699; font-weight: bold;">$image</span>.meta&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// Set a default title if we don't have any meta data</span>
<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span> <span style="color: #339933;">!</span><span style="color: #000088;">$title</span> <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$title</span> <span style="color: #339933;">=</span> <span style="color: #990000;">ucwords</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">strtolower</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$image</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// Include the page header, if you like</span>
<span style="color: #b1b100;">include</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;header.inc.php&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">?&gt;</span>
&nbsp;
&lt;div class=&quot;content&quot;&gt;
&nbsp;
    &lt;img src=&quot;/<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> MEDIA_DIR <span style="color: #000000; font-weight: bold;">?&gt;</span>/<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> <span style="color: #000088;">$image</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>.jpg&quot; alt=&quot;<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> <span style="color: #990000;">htmlspecialchars</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$title</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>&quot; class=&quot;image&quot; /&gt;
&nbsp;
    &lt;h1&gt;<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> <span style="color: #000088;">$title</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>&lt;/h1&gt;
&nbsp;
    <span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span> <span style="color: #000088;">$source</span> <span style="color: #009900;">&#41;</span> <span style="color: #339933;">:</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
        &lt;p&gt;
            From &lt;a href=&quot;http://twitter.com/<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> <span style="color: #000088;">$source</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>&quot;&gt;
                &lt;img src=&quot;/media/images/twitter.png&quot; width=&quot;14&quot; height=&quot;14&quot; alt=&quot;Follow us on Twitter!&quot;&gt;
                <span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> <span style="color: #000088;">$source</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
            &lt;/a&gt;
        &lt;/p&gt;
    <span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">endif</span><span style="color: #339933;">;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
&nbsp;
&lt;/div&gt;
&nbsp;
<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">include</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;footer.inc.php&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span></pre></div></div>


<p>Make sure it works by making a sample image called, say, <code>IMG.jpg</code>, and an accompanying metadata file, called <code>IMG.meta</code> with a title on the first line and a twitter account name on the second, and opening up <code>http://yoursite.com/image.php?name=IMG</code></p>

<p>Now, we want to keep URLs short, so they don&#8217;t take up too much valuable space in a tweet, so we need to use some tricks here.</p>

<p>We&#8217;ll set up a <code>.htaccess</code> file that uses <code>mod_rewrite</code> to keep the URL short.</p>

<p>Something like this should do the trick:</p>

<blockquote>
<pre>
&lt;IfModule mod_rewrite.c&gt;
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_URI} ^/([^/]+)$
RewriteCond %{DOCUMENT_ROOT}/twitter-images/%1.jpg -f
RewriteRule (.*) /image.php?name=$1 [L]
&lt;/IfModule&gt;
</pre>
</blockquote>

<p>Note on the fifth line we are checking inside our Twitter images folder &#8212; make sure that matches your storage path.</p>

<p>This will take any requests that:</p>

<ul>
<li>Are located in the web-root (<em>start with a slash, followed by anything but a slash until the end</em>)</li>
<li>Have a corresponding file within the directory we&#8217;ll store images in</li>
</ul>

<p>Then, it&#8217;ll rewrite the request silently to use <code>image.php</code>.</p>

<p>Save the <code>.htaccess</code> file, and open <code>http://yoursite.com/IMG</code>.  It should bring up the image, just as before.</p>

<p>Set up some CSS to make it look good, and you&#8217;re set.  Here&#8217;s mine:</p>


<div class="wp_syntax"><div class="code"><pre class="css" style="font-family:monospace;">&nbsp;
<span style="color: #808080; font-style: italic;">/* @group Twitter images */</span>
&nbsp;
<span style="color: #6666ff;">.twitter-image</span> .<span style="color: #000000; font-weight: bold;">content</span> <span style="color: #00AA00;">&#123;</span>
	<span style="color: #000000; font-weight: bold;">margin-top</span><span style="color: #00AA00;">:</span> <span style="color: #933;">50px</span><span style="color: #00AA00;">;</span>
	<span style="color: #000000; font-weight: bold;">margin-bottom</span><span style="color: #00AA00;">:</span> <span style="color: #933;">50px</span><span style="color: #00AA00;">;</span>
<span style="color: #00AA00;">&#125;</span>
&nbsp;
<span style="color: #6666ff;">.twitter-image</span> .<span style="color: #000000; font-weight: bold;">content</span> img<span style="color: #6666ff;">.image</span> <span style="color: #00AA00;">&#123;</span>
	-moz-border-radius<span style="color: #00AA00;">:</span> <span style="color: #933;">20px</span><span style="color: #00AA00;">;</span>
	-webkit-border-radius<span style="color: #00AA00;">:</span> <span style="color: #933;">20px</span><span style="color: #00AA00;">;</span>
	<span style="color: #000000; font-weight: bold;">background</span><span style="color: #00AA00;">:</span> <span style="color: #cc00cc;">#f1f1f1</span><span style="color: #00AA00;">;</span>
	<span style="color: #000000; font-weight: bold;">border</span><span style="color: #00AA00;">:</span> <span style="color: #933;">1px</span> <span style="color: #993333;">solid</span> <span style="color: #cc00cc;">#aaa</span><span style="color: #00AA00;">;</span>
	<span style="color: #000000; font-weight: bold;">padding</span><span style="color: #00AA00;">:</span>  <span style="color: #933;">40px</span><span style="color: #00AA00;">;</span>
	<span style="color: #000000; font-weight: bold;">margin-right</span><span style="color: #00AA00;">:</span> <span style="color: #933;">60px</span><span style="color: #00AA00;">;</span>
	<span style="color: #000000; font-weight: bold;">display</span><span style="color: #00AA00;">:</span> <span style="color: #993333;">block</span><span style="color: #00AA00;">;</span>
	<span style="color: #000000; font-weight: bold;">margin</span><span style="color: #00AA00;">:</span> <span style="color: #cc66cc;">0</span> <span style="color: #993333;">auto</span><span style="color: #00AA00;">;</span>
<span style="color: #00AA00;">&#125;</span>
&nbsp;
<span style="color: #6666ff;">.twitter-image</span> .<span style="color: #000000; font-weight: bold;">content</span> h1 <span style="color: #00AA00;">&#123;</span>
	<span style="color: #000000; font-weight: bold;">padding-top</span><span style="color: #00AA00;">:</span> <span style="color: #933;">60px</span><span style="color: #00AA00;">;</span>
	<span style="color: #000000; font-weight: bold;">text-align</span><span style="color: #00AA00;">:</span> <span style="color: #993333;">center</span><span style="color: #00AA00;">;</span>
<span style="color: #00AA00;">&#125;</span>
&nbsp;
<span style="color: #6666ff;">.twitter-image</span> .<span style="color: #000000; font-weight: bold;">content</span> p <span style="color: #00AA00;">&#123;</span>
	<span style="color: #000000; font-weight: bold;">text-align</span><span style="color: #00AA00;">:</span> <span style="color: #993333;">center</span><span style="color: #00AA00;">;</span>
<span style="color: #00AA00;">&#125;</span>
&nbsp;
<span style="color: #6666ff;">.twitter-image</span> .<span style="color: #000000; font-weight: bold;">content</span> a <span style="color: #00AA00;">&#123;</span>
	<span style="color: #000000; font-weight: bold;">text-decoration</span><span style="color: #00AA00;">:</span> <span style="color: #993333;">none</span><span style="color: #00AA00;">;</span>
<span style="color: #00AA00;">&#125;</span>
&nbsp;
<span style="color: #6666ff;">.twitter-image</span> .<span style="color: #000000; font-weight: bold;">content</span> a img <span style="color: #00AA00;">&#123;</span>
	<span style="color: #000000; font-weight: bold;">vertical-align</span><span style="color: #00AA00;">:</span>text-<span style="color: #000000; font-weight: bold;">bottom</span><span style="color: #00AA00;">;</span>
<span style="color: #00AA00;">&#125;</span>
&nbsp;
<span style="color: #808080; font-style: italic;">/* @end */</span></pre></div></div>


<h2>Automator</h2>

<p>Now, with the web side set up, we need to set up an easy way to send content there.</p>

<p>I opted for an Automator service, which uses <code>scp</code> to upload the content.  If your web host doesn&#8217;t provide for <code>scp</code>, you may want to use something else like <a href="http://www.ncftp.com/download/">ncftpput</a>, or even an Applescript-able application.  You&#8217;ll need to modify the Automator action&#8217;s shell script accordingly.</p>

<p>Here&#8217;s the Automator service I set up: <a href="http://atastypixel.com/blog/wp-content/uploads/2010/01/Send-Image-to-Image-Hosting.zip" title="Send Image to Image Hosting.zip">Send Image to Image Hosting.zip</a>.</p>

<p>For those interested, it contains the following shell script:</p>


<div class="wp_syntax"><div class="code"><pre class="shell" style="font-family:monospace;">APPSUPPORT=~/&quot;Library/Application Support/Image Hosting&quot;
TMPDIR='/tmp/image-hosting.tmp'
DEST='me@mywebsite.com:www/mywebsite/twitter-images/'
URLPREFIX='http://mywebsite.com/'
UPLOADRETRIES=3
# GROWL=&quot;/usr/local/bin/growlnotify&quot; # Uncomment this if you have Growl and growlnotify
&nbsp;
[ ! -e &quot;$APPSUPPORT&quot; ] &amp;&amp; mkdir &quot;$APPSUPPORT&quot;
&nbsp;
for f in &quot;$@&quot;
do
  if [ ! -e &quot;$f&quot; ]; then
    osascript -e 'tell application &quot;Finder&quot;' -e 'activate' -e 'display dialog &quot;Input file '&quot;$f&quot;' does not exist&quot; with title &quot;Image Hosting&quot; buttons {&quot;OK&quot;} with icon Stop' -e 'end tell'
    exit
  fi
&nbsp;
  # Generate random name
  while true; do
      name=`perl -e 'use MIME::Base64; $s=encode_base64(rand()); $s =~ s/=|\n//g; $s = substr($s, -5); print $s'`
      if ! grep &quot;$name&quot; &quot;$APPSUPPORT/Taken Names&quot; &amp;&gt;/dev/null; then break; fi;
  done;
&nbsp;
  # Gather info
  default=`php -r '$s = basename(&quot;'&quot;$f&quot;'&quot;); echo ucwords(strtolower(substr($s, 0, strpos($s, &quot;.&quot;))));'`
  title=`osascript -e 'tell application &quot;Finder&quot;' -e 'activate' -e 'text returned of (display dialog &quot;Enter image title&quot; with title &quot;Image Hosting&quot; default answer &quot;'&quot;$default&quot;'&quot; buttons {&quot;Cancel&quot;, &quot;Continue&quot;} default button 2)' -e 'end tell'`
  [ ! &quot;$title&quot; ] &amp;&amp; exit
  defaulttwitter=`cat &quot;$APPSUPPORT/Default Twitter Account&quot; 2&gt;/dev/null`
  twitter=`osascript -e 'tell application &quot;Finder&quot;' -e 'activate' -e 'text returned of (display dialog &quot;Enter Twitter account&quot; with title &quot;Image Hosting&quot; default answer &quot;'&quot;$defaulttwitter&quot;'&quot; buttons {&quot;Cancel&quot;, &quot;Continue&quot;} default button 2)' -e 'end tell'`
  [ ! &quot;$twitter&quot; ] &amp;&amp; exit
  echo $twitter &gt; &quot;$APPSUPPORT/Default Twitter Account&quot;
&nbsp;
  # Create temp files
  [ -e &quot;$TMPDIR&quot; ] &amp;&amp; rm -rf &quot;$TMPDIR&quot;
  mkdir &quot;$TMPDIR&quot;
  cp &quot;$f&quot; &quot;$TMPDIR/$name.jpg&quot;
  echo &quot;$title
$twitter&quot; &gt; &quot;$TMPDIR/$name.meta&quot;
&nbsp;
  [ -f &quot;$GROWL&quot; ] &amp;&amp; $GROWL -n 'Image Hosting' &quot;Image Hosting: `basename &quot;$f&quot;`&quot; -m &quot;Image Hosting is uploading '$name'&quot;
&nbsp;
  # Upload
  retries=0
  while [ $retries -lt $UPLOADRETRIES ]; do
    result=`scp &quot;$TMPDIR&quot;/* &quot;$DEST&quot; 2&gt;&amp;1` &amp;&amp; break;
    [ -f &quot;$GROWL&quot; ] &amp;&amp; $GROWL -n &quot;Image Hosting: `basename &quot;$f&quot;`&quot; 'Image Hosting' -m 'Upload failed: Retrying'
    retries=$((retries+1))
  done
&nbsp;
  if [ $retries -ge $UPLOADRETRIES ]; then
    osascript -e 'tell application &quot;Finder&quot;' -e 'activate' -e 'display dialog &quot;Could not upload image.  Scp said: '&quot;$result&quot;'&quot; with title &quot;Image Hosting&quot; with icon Stop' -e 'end tell'
    exit
  fi
&nbsp;
  echo $name &gt;&gt; &quot;$APPSUPPORT/Taken Names&quot;
&nbsp;
  osascript -e 'tell application &quot;Finder&quot; to set the clipboard to &quot;'&quot;$URLPREFIX$name&quot;'&quot;'
&nbsp;
  [ -f &quot;$GROWL&quot; ] &amp;&amp; $GROWL -n 'Image Hosting' &quot;Image Hosting: `basename &quot;$f&quot;`&quot; -m &quot;Upload complete.  Available at $URLPREFIX/$name (copied to clipboard)&quot;
done</pre></div></div>


<p>To use it:</p>

<ol>
<li>Unzip it, </li>
<li>Put it into <code>Library/Services</code>, </li>
<li>Double-click on it to open it in Automator,</li>
<li>Change the settings at the top of the &#8216;Shell Script&#8217; segment &#8212; 

<ul>
<li>Set <code>DEST</code> to the <code>scp</code> destination</li>
<li>Set up <a href="http://www.google.com/search?q=ssh%20authorized_keys">key-based SSH authentication</a>, so you don&#8217;t have to enter the password to upload, or, if you&#8217;d prefer to use something other than <code>scp</code> to upload the file, you can change the upload command further down in the script, underneath the &#8216;Upload&#8217; comment (look for <code>scp</code>)</li>
<li>Set <code>URLPREFIX</code> to <code>http://yoursite.com</code></li>
<li>If you have Growl and <code>growlnotify</code> installed, then set <code>GROWL</code> to the location of <code>growlnotify</code> (highly recommended)</li>
</ul></li>
<li>Save</li>
</ol>

<h2>Usage</h2>

<p>If you&#8217;re using Leopard, you may need to log out, then log back in to see the service &#8212; I&#8217;m not entirely certain.  If you&#8217;re on Snow Leopard, you should hopefully be set.  Right-click on an image file in Finder, and click &#8216;<em>Send Image to Image Hosting</em>&#8216;.</p>

<p>You should be asked for a title, then asked for a Twitter account name (this will be remembered for next time), then the upload will happen, and when it completes, the URL to the uploaded image will be put onto the clipboard so you can paste straight into Twitter.</p>

<p>Voila.</p>
 <img src="http://atastypixel.com/blog/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=1757" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://atastypixel.com/blog/diy-twitter-image-hosting/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Flash video cache on OS X</title>
		<link>http://atastypixel.com/blog/flash-video-cache-on-os-x/</link>
		<comments>http://atastypixel.com/blog/flash-video-cache-on-os-x/#comments</comments>
		<pubDate>Mon, 01 Jun 2009 08:52:31 +0000</pubDate>
		<dc:creator>Michael Tyson</dc:creator>
				<category><![CDATA[Geekspeak]]></category>
		<category><![CDATA[Mac]]></category>

		<guid isPermaLink="false">http://atastypixel.com/blog/2009/06/01/flash-video-cache-on-os-x/</guid>
		<description><![CDATA[I just make a happy discovery: Flash stores videos it&#8217;s currently playing (eg. from YouTube, Megavideo, etc) within the /private/var/folders/.../ area. Access it by hitting Cmd-Shift-G in Finder, typing in /private/var/folders and hitting enter, then navigate around until you see something like a TemporaryItems folder &#8211; within will be a file called something like FlashTmp0, [...]]]></description>
			<content:encoded><![CDATA[<p>I just make a happy discovery: Flash stores videos it&#8217;s currently playing (eg. from YouTube, Megavideo, etc) within the <code>/private/var/folders/.../</code> area.</p>

<p>Access it by hitting <em>Cmd-Shift-G</em> in Finder, typing in <code>/private/var/folders</code> and hitting enter, then navigate around until you see something like a <code>TemporaryItems</code> folder &#8211; within will be a file called something like <code>FlashTmp0</code>, which is the <code>.flv</code> file.</p>

<p>Copy it somewhere and rename it, and it&#8217;ll play in VLC or any other player that supports the format (like Quicktime etc with <a href="http://perian.org">Perian</a> installed).</p>
 <img src="http://atastypixel.com/blog/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=1626" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://atastypixel.com/blog/flash-video-cache-on-os-x/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Keeping Flickr away from iPhoto</title>
		<link>http://atastypixel.com/blog/keeping-flickr-away-from-iphoto/</link>
		<comments>http://atastypixel.com/blog/keeping-flickr-away-from-iphoto/#comments</comments>
		<pubDate>Thu, 28 May 2009 01:23:51 +0000</pubDate>
		<dc:creator>Michael Tyson</dc:creator>
				<category><![CDATA[Geekspeak]]></category>
		<category><![CDATA[Mac]]></category>

		<guid isPermaLink="false">http://atastypixel.com/blog/2009/05/28/keeping-flickr-away-from-iphoto/</guid>
		<description><![CDATA[How to edit iPhoto's back-end files to forcibly remove Flickr albums from iPhoto, without the corresponding photosets being deleted on Flickr.]]></description>
			<content:encoded><![CDATA[<p><img src="http://atastypixel.com/blog/wp-content/uploads/2009/05/iphoto.png" width="100" height="100" alt="iphoto.png" title="iphoto.png" class="alignright noframe" />
<em>Update: Andrew made a better suggestion in the comments below that I hadn&#8217;t thought of: De-authorise iPhoto from your Flickr account, then just delete the Flickr albums in iPhoto.  Thanks, Andrew!</em></p>

<p>iPhoto &#8217;09 introduced Flickr support, so that you can post photos and albums to your Flickr account.  Unfortunately for some, it has some issues: A tendency to perform mass-deletions on uploaded photosets after the initial upload.  For example, for me, having uploaded several hundred images, iPhoto has deleted almost all of them on two separate occasions, requiring the photosets to be constructed from scratch.</p>

<p>For those who were considering using Flickr from iPhoto, don&#8217;t, and save yourself the hassle (use <a href="http://connectedflow.com/flickrexport/">FlickrExport</a> instead).  For those who have and are seeking a remedy to keep iPhoto away from Flickr, read on.</p>

<p>I encountered the uncomfortable scenario where iPhoto had forgotten about three quarters of the images in the uploaded photosets, and upon launch, looked like it was going to delete the remainder from my Flickr account.  Rather than let this happen, I force quit iPhoto, and performed the following steps to force iPhoto to forget about my Flickr account.  This is a very complicated process, not for the faint of heart, but it was necessary for me to save my Flickr account:</p>

<ol>
<li>Right-click on the &#8216;iPhoto Library&#8217; package, probably in the &#8216;Pictures&#8217; folder</li>
<li>For the files <code>AlbumData.xml</code> and <code>AlbumData2.xml</code>:

<ol>
<li>Backup the files somewhere</li>
<li>Open the file in a text editor</li>
<li>Search for the term &#8216;http://www.flickr.com&#8217;</li>
<li>Wherever this is found, delete the surrounding text between <code>&lt;dict&gt;</code> and <code>&lt;/dict&gt;</code>.  There will be one of these <code>dict</code> structures for every photoset</li>
<li>Save the file</li>
</ol></li>
<li>Now the tricky part: Find an SQLite editor (I used <a href="http://www.versiontracker.com/dyn/moreinfo/macosx/34013">Froq</a>) and open up <code>iPhotoMain.db</code> within the &#8216;iPhoto Library&#8217; package.  To access the file, I had to copy it to my Desktop first, then open it there (back it up first).

<ol>
<li>Click on the <code>SqPublishedAlbum</code> table to see the contents.  This lists all of the published albums, including Flickr, Facebook, etc.  Find the entries with a <code>publishedURL</code> at flickr.com, and delete them.  In Froq, I had to take note of their primary key values, and manually execute an SQL query (<code>DELETE FROM SqPublishedAlbum WHERE primaryKey = 12345</code>). Remember those primary key values, because you&#8217;ll need them.</li>
<li>Click on the <code>SqAlbum</code> table, and delete the albums with the same primary key values &#8211; if you used an SQL query as above, you can just re-use the same query but change the table name to <code>SqAlbum</code>.</li>
<li>Repeat the same process for the <code>AlbumsPhotosJoin</code> table &#8211; in this case, you&#8217;ll need to delete entries with the <code>sqAlbum</code> field values matching the prior <code>primarykey</code> values.  Something like <code>DELETE FROM AlbumsPhotosJoin WHERE sqAlbum = 12345</code> will do it.</li>
<li>Done with this database &#8211; commit and close, but remember the primary key values for the Flickr albums.</li>
</ol></li>
<li>Next, open up the other SQLite database, <code>iPhotoAux.db</code>, after backing it up

<ol>
<li>Delete the Flickr album records from the <code>SqAlbumSubclasses</code> table. Something like: <code>DELETE FROM SqAlbumSubclasses WHERE primaryKey = 12345</code>.</li>
<li>Commit and close</li>
</ol></li>
<li>Send a bug report to Apple</li>
</ol>

<p>That&#8217;s it! Now, after starting iPhoto, the Flickr albums should be gone, safe at last.  <a href="http://connectedflow.com/flickrexport/">FlickrExport</a> is a £12 plugin that provides better, more reliable functionality than iPhoto &#8217;09.</p>
 <img src="http://atastypixel.com/blog/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=1618" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://atastypixel.com/blog/keeping-flickr-away-from-iphoto/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
	</channel>
</rss>

