<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss 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/" version="2.0">

<channel>
	<title>Command-Tab</title>
	
	<link>http://www.command-tab.com</link>
	<description>Technology and Mac geekery. One part exuberance, two parts obsession.</description>
	<lastBuildDate>Sat, 07 Jan 2012 18:00:29 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/commandtab" /><feedburner:info xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" uri="commandtab" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item>
		<title>Widerbug No Longer Needed</title>
		<link>http://www.command-tab.com/2012/01/07/widerbug-no-longer-needed/</link>
		<comments>http://www.command-tab.com/2012/01/07/widerbug-no-longer-needed/#comments</comments>
		<pubDate>Sat, 07 Jan 2012 18:00:29 +0000</pubDate>
		<dc:creator>Collin</dc:creator>
				<category><![CDATA[Misc]]></category>

		<guid isPermaLink="false">http://www.command-tab.com/?p=1267</guid>
		<description><![CDATA[Good news Widerbug users! The dedicated Firebug team has just added the widescreen option that Widerbug enables into the core of Firebug 1.9.0, making Widerbug obsolete. You may uninstall Widerbug and go back to using regular Firebug and be able to change the layout using the option seen below. This is welcome news to everyone, [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://static.command-tab.com/2008/widerbug_banner.jpg" alt="Widerbug" /></p>
<p>Good news Widerbug users!</p>
<p>The dedicated Firebug team has just added the widescreen option that Widerbug enables into the core of <a href="http://blog.getfirebug.com/2012/01/06/firebug-1-9-0/">Firebug 1.9.0</a>, making Widerbug obsolete. You may uninstall Widerbug and go back to using regular Firebug and be able to change the layout using the option seen below.</p>
<p><img class="framed" src="http://static.command-tab.com/2011/firebug-widescreen-support.jpg" alt="Firebug widescreen support" /></p>
<p>This is welcome news to everyone, I imagine. It&#8217;s been difficult to keep up with Firefox&#8217;s new fast-track release schedule, as well as continually adapting to the Firebug internal changes.  Now you can enjoy widescreen support, with Firebug in one of several locations, without sacrificing new critical updates and feature improvements.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.command-tab.com/2012/01/07/widerbug-no-longer-needed/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>True PHP Debugging with Nginx and PHP-FPM</title>
		<link>http://www.command-tab.com/2011/06/20/true-php-debugging-with-nginx-and-php-fpm/</link>
		<comments>http://www.command-tab.com/2011/06/20/true-php-debugging-with-nginx-and-php-fpm/#comments</comments>
		<pubDate>Mon, 20 Jun 2011 15:27:42 +0000</pubDate>
		<dc:creator>Collin</dc:creator>
				<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://www.command-tab.com/?p=1165</guid>
		<description><![CDATA[Mac OS X is an increasingly popular platform for web developers, client-side and server-side alike. For doing intensive PHP development on OS X, you can use a full-blown IDE like Zend Studio or PhpStorm, but I like my toolkit to be much more lightweight. I prefer to code in TextMate, execute SQL queries in Querious, [...]]]></description>
			<content:encoded><![CDATA[<p>Mac OS X is an increasingly popular platform for web developers, client-side and server-side alike.  For doing intensive PHP development on OS X, you can use a full-blown IDE like <a href="http://www.zend.com/en/products/studio/">Zend Studio</a> or <a href="http://www.jetbrains.com/phpstorm/">PhpStorm</a>, but I like my toolkit to be much more lightweight.  I prefer to code in <a href="http://macromates.com/">TextMate</a>, execute SQL queries in <a href="http://www.araelium.com/querious/">Querious</a>, run code in Safari, and perform technical tasks in Terminal.  Absent from this agile team, though, is a true PHP debugger, leaving you with only rudimentary calls like <code>printf</code> and <code>var_dump</code> for debugging.  Worse still, you have to change your code just to debug it.  We can do better.</p>
<p>Recently, I discovered an excellent tool that filled the need for a lightweight PHP debugger.  <a href="http://www.bluestatic.org/software/macgdbp/">MacGDBp</a> communicates with PHP using the <a href="http://xdebug.org/">Xdebug</a> PHP extension, and offers variable inspection, stepping controls, breakpoints, and a call stack, all in a native Cocoa app &#8212; no bloated Java IDEs required:</p>
<p><img class="framed" src="http://static.command-tab.com/2011/php-debugging/macgdbp.jpg" alt="MacGDBp debugging a Zend Framework application" /></p>
<h4>What is Nginx?</h4>
<p><a href="http://nginx.org/en/">Nginx</a> is a web server similar to Apache, in that it&#8217;s capable of serving web content over HTTP and HTTPS to visitors.  While Apache is far and away the most common web server &#8212; currently serving up about 64% of all websites on the internet &#8212; it&#8217;s also about a decade older than Nginx.  Being newer, Nginx doesn&#8217;t have all the baggage that Apache has accumulated over that time, and it&#8217;s only gaining in usage, particularly on high-traffic sites.  In addition, Nginx&#8217;s config file format is much saner and less verbose than Apache&#8217;s, simplifying setup.</p>
<p>The only speed bump I&#8217;ve run into with Nginx is a lack of <code>.htaccess</code> support, requiring your URL rewrites to be done in your site&#8217;s configuration file, as opposed to read at runtime. It&#8217;s a different approach, but it helps you centralize your configurations instead of spreading them throughout your project.  This way, environment-related details are kept in the web server environment, and the application code base is all about the application.</p>
<h4>What is PHP-FPM?</h4>
<p><a href="http://php-fpm.org/">PHP-FPM</a> was originally a standalone source code patch that added independent process management to PHP, but is now included as part of the PHP project.  When Apache handles web requests, its PHP module gets loaded even if it&#8217;s not needed, wasting time and memory.  By contrast, under PHP-FPM, processes are launched as demand increases (up to limits we&#8217;ll set), increasing speed and reducing memory usage.</p>
<p>With the setup detailed below, you&#8217;ll be able to run PHP with Nginx and debug server-side code with the simplicity of a Mac application.  A build of MySQL 5.5 is also included, but you could, of course, substitute your preferred database if desired.</p>
<h4>Install Xcode</h4>
<p>Many of the following steps depend on a compiler and other programs that are included with Apple&#8217;s Xcode developer tools.  A version of Xcode is included on your Mac OS X Install DVD, and a more recent version is available on the <a href="http://itunes.apple.com/us/app/xcode/id422352214?mt=12">Mac App Store</a>. Registered Mac and iOS developers can download a copy through the <a href="http://developer.apple.com/">Apple Developer</a> site.  Any version that&#8217;s compatible with your Mac OS X version should suffice.  For this tutorial, I&#8217;m running Mac OS X 10.6.7 and Xcode 4.0.2.  The default install of Xcode should provide everything you need to complete this step.</p>
<h4>Install X11</h4>
<p>Some of the libraries we&#8217;ll use aren&#8217;t part of a default OS X install, but are provided by Apple in their optional X11 distribution.  Insert your Mac OS X Install DVD or USB drive and open the &#8220;Optional Installs&#8221; folder and run the &#8220;Optional Installs.mpkg&#8221; package.  When you get to the customization screen, open the Applications disclosure triangle, and check off X11 before performing the install.</p>
<p><img class="framed" src="http://static.command-tab.com/2011/php-debugging/x11.jpg" /></p>
<h4>Install Homebrew</h4>
<p><a href="http://mxcl.github.com/homebrew/">Homebrew</a> is a package manager for Mac OS X, similar to <code>yum</code> for Linux.  It&#8217;s a faster, lower-overhead alternative to other OS X package managers like MacPorts and Fink.  We&#8217;ll be using it to install a few dependencies.  To get things rolling, open a Terminal window, and run:</p>
<pre class="command">
ruby -e "$(curl -fsSL https://raw.github.com/gist/323731)"</code>
</pre>
<h4>Create a Place to Work</h4>
<p>We&#8217;ll need some easily-accessible place to download source code and build it, so a SourceCache folder in the your Home folder is as good a place as any.</p>
<pre class="command">
mkdir ~/SourceCache
</pre>
<h4>Download and Build Nginx</h4>
<p>Building and installing Nginx is fairly straightforward. We&#8217;ll download the code from the Nginx site, unpack it, install a single dependency using Homebrew, configure, compile, and install:</p>
<pre class="command">
cd ~/SourceCache
curl -O http://nginx.org/download/nginx-1.0.4.tar.gz
tar -xzf nginx-1.0.4.tar.gz
cd nginx-1.0.4
brew install pcre
./configure --prefix=/usr/local/nginx --pid-path=/usr/local/nginx/var/run/nginx.pid --with-http_ssl_module
make
sudo make install
</pre>
<p>Nginx is now installed and ready to run.  With the creation of a small file, you can even set Nginx to run at startup.  Mac OS X uses <a href="http://en.wikipedia.org/wiki/Launchd">launchd</a> to run scripts at the appropriate time, so we&#8217;ll create a simple launchd <a href="http://en.wikipedia.org/wiki/Property_list">plist</a> to start Nginx at boot.</p>
<p>I&#8217;ll be using TextMate&#8217;s built-in <code>mate</code> command to edit files here, but you can use vi, nano, or any other text editor that floats your boat.</p>
<pre class="command">
sudo mate /Library/LaunchDaemons/org.nginx.nginx.plist
</pre>
<p>Then paste in this plist content:</p>
<pre class="code">
&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"&gt;
&lt;plist version="1.0"&gt;
&lt;dict&gt;
    &lt;key&gt;KeepAlive&lt;/key&gt;
    &lt;true/&gt;
    &lt;key&gt;Label&lt;/key&gt;
    &lt;string&gt;org.nginx.nginx&lt;/string&gt;
    &lt;key&gt;LaunchOnlyOnce&lt;/key&gt;
    &lt;true/&gt;
    &lt;key&gt;NetworkState&lt;/key&gt;
    &lt;true/&gt;
    &lt;key&gt;ProgramArguments&lt;/key&gt;
    &lt;array&gt;
        &lt;string&gt;/usr/local/nginx/sbin/nginx&lt;/string&gt;
    &lt;/array&gt;
    &lt;key&gt;RunAtLoad&lt;/key&gt;
    &lt;true/&gt;
    &lt;key&gt;ServiceDescription&lt;/key&gt;
    &lt;string&gt;Nginx web server&lt;/string&gt;
    &lt;key&gt;StandardErrorPath&lt;/key&gt;
    &lt;string&gt;/var/log/system.log&lt;/string&gt;
&lt;/dict&gt;
&lt;/plist&gt;
</pre>
<h4>Edit Nginx Config Files for PHP</h4>
<p>Nginx is now ready to run on its own, but it still needs to be told where to look for your sites on disk, and how to handle <code>.php</code> files once we install PHP.  We can create some config files now so that they work after the PHP install is complete.  This first config file is a basic Nginx config file.  You&#8217;ll want to replace &#8220;collin&#8221; towards the top of the file with your own OS X short username (which you can see by running <code>whoami</code>), so that Nginx runs as your user.  Or, if you prefer, you can add a new user and group dedicated for Nginx.  Since this is just a local development setup and not a production web server, I didn&#8217;t bother going that route.</p>
<pre class="command">
sudo mate /usr/local/nginx/conf/nginx.conf
</pre>
<p>Here is the content for the config file:</p>
<pre class="code">
user collin staff;
worker_processes 2;

events {
    worker_connections 1024;
}

http {
    include mime.types;

    default_type text/plain;
    server_tokens off;

    sendfile on;
    tcp_nopush on;
    keepalive_timeout 10;

    gzip on;
    gzip_comp_level 2;
    gzip_proxied any;
    gzip_types text/plain text/css text/javascript application/json application/x-javascript text/xml application/xml application/xml+rss;

    index index.html index.php;
    include sites-enabled/*.link;
}
</pre>
<p>After we install PHP, Nginx will need to know how to interact with it. Unlike running PHP as an Apache module, PHP-FPM runs its own separate set of processes, and Nginx has no idea they exist unless you tell it about them.  Nginx communicates over the FastCGI protocol, with the master process listening on a local port so it can handle PHP requests from Nginx.</p>
<p>Now we&#8217;ll create an Nginx config file that holds all the details about PHP-FPM.  Note that, at the bottom of this config file, we instruct FastCGI to listen on port 9001 instead of the default port 9000.  This will come into play later when we setup the debugging tools.</p>
<pre class="command">
sudo mate /usr/local/nginx/conf/php.conf
</pre>
<pre class="code">
fastcgi_intercept_errors on;

location ~ \.php$
{
    fastcgi_split_path_info ^(.+\.php)(/.+)$;

    fastcgi_param PATH_INFO         $fastcgi_path_info;
    fastcgi_param PATH_TRANSLATED   $document_root$fastcgi_path_info;
    fastcgi_param QUERY_STRING      $query_string;
    fastcgi_param REQUEST_METHOD    $request_method;
    fastcgi_param CONTENT_TYPE      $content_type;
    fastcgi_param CONTENT_LENGTH    $content_length;
    fastcgi_param SCRIPT_NAME       $fastcgi_script_name;
    fastcgi_param SCRIPT_FILENAME   $document_root$fastcgi_script_name;
    fastcgi_param REQUEST_URI       $request_uri;
    fastcgi_param DOCUMENT_URI      $document_uri;
    fastcgi_param DOCUMENT_ROOT     $document_root;
    fastcgi_param SERVER_PROTOCOL   $server_protocol;
    fastcgi_param GATEWAY_INTERFACE CGI/1.1;
    fastcgi_param SERVER_SOFTWARE   nginx;
    fastcgi_param REMOTE_ADDR       $remote_addr;
    fastcgi_param REMOTE_PORT       $remote_port;
    fastcgi_param SERVER_ADDR       $server_addr;
    fastcgi_param SERVER_PORT       $server_port;
    fastcgi_param SERVER_NAME       $server_name;

    fastcgi_read_timeout 600; # Set fairly high for debugging

    fastcgi_pass  127.0.0.1:9001; # Non-default port
    fastcgi_index index.php;
}
</pre>
<p>Nginx is now configured to talk to PHP, but only when we include this particular config file in a particular site&#8217;s config file.</p>
<h4>Configure Local Sites</h4>
<p>At the bottom of the main Nginx config file, we called <code>include sites-enabled/*.link</code>.  We&#8217;ll now create <code>sites-available</code> and <code>sites-enabled</code> folders to hold config files for each site you develop locally.  <code>sites-available</code> will hold all available site config files, and <code>sites-enabled</code> will contain only symbolic links to the config files of enabled sites, allowing you to turn local sites on and off just by linking or unlinking their config files and restarting Nginx.</p>
<pre class="command">
sudo mkdir /usr/local/nginx/conf/sites-available
sudo mkdir /usr/local/nginx/conf/sites-enabled
</pre>
<p>With those two folders available, we&#8217;ll set up an example site that will make use of the PHP config file above. Again, you&#8217;ll want to replace &#8220;collin&#8221; with your own username so Nginx looks in the correct folder for website content.</p>
<pre class="command">
sudo mate /usr/local/nginx/conf/sites-available/example.conf
</pre>
<pre class="code">
server
{
    listen 80;
    server_name example.local;
    root /Users/collin/Sites/example/public;

    access_log /Users/collin/Sites/example/logs/access_log.txt;
    error_log /Users/collin/Sites/example/logs/error_log.txt;

    location /
    {
        index index.php;
        try_files $uri $uri/ /index.php?q=$uri&$args;
    }

    include php.conf;
}
</pre>
<p>Now we can enable the site by symlinking the config file from the sites-available folder into the sites-enabled folder:</p>
<pre class="command">
sudo ln -s /usr/local/nginx/conf/sites-available/example.conf /usr/local/nginx/conf/sites-enabled/example.link
</pre>
<p>While we&#8217;re configuring this site, we should also create the actual folder structure on disk.  The <code>public</code> folder will be where Nginx considers the web-accessible root to be when visited in a web browser, and <code>logs</code> will be where Nginx (and possibly your web application) puts log files.</p>
<pre class="command">
mkdir -p ~/Sites/example/public
mkdir -p ~/Sites/example/logs
</pre>
<p>Finally, we need to make sure that visiting <code>example.local</code> in a browser actually routes to your computer (if you were to visit it right now, more than likely nothing would happen):</p>
<pre class="command">
sudo mate /etc/hosts
</pre>
<p>Add the following line to the <em>end</em> of the file:</p>
<pre class="code">
127.0.0.1    example.local
</pre>
<p>And with that, we&#8217;ve configured a local website for Nginx.</p>
<h4>Install MySQL</h4>
<p>With Homebrew, installing MySQL is the easiest of all the installs we&#8217;ll perform.  This build of MySQL via Homebrew includes a launchd script, which we&#8217;ll copy into the LaunchDaemons folder just like we did with Nginx.</p>
<pre class="command">
brew install mysql
unset TMPDIR
mysql_install_db --verbose --user=`whoami` --basedir="$(brew --prefix mysql)" --datadir=/usr/local/var/mysql --tmpdir=/tmp
sudo cp /usr/local/Cellar/mysql/5.5.10/com.mysql.mysqld.plist /Library/LaunchDaemons/
</pre>
<h4>Install PHP Dependencies</h4>
<p>Unlike Nginx and MySQL, PHP requires quite a few other software packages depending on how you build it. We&#8217;ll install some common ones before proceeding with with PHP build and install.</p>
<pre class="command">
brew install libjpeg mcrypt
</pre>
<pre class="command">
cd ~/SourceCache
curl -O http://download.icu-project.org/files/icu4c/4.6.1/icu4c-4_6_1-src.tgz
tar -xzf icu4c-4_6_1-src.tgz
cd icu
sh source/configure --prefix=/usr/local
gnumake
sudo make install
</pre>
<pre class="command">
cd /usr/local
curl -O ftp://ftp.cac.washington.edu/mail/imap.tar.Z
tar -xzf imap.tar.Z
cd imap-2007e
make osx
mkdir include
ln -s c-client include
mkdir lib
cd lib
ln -s ../c-client/c-client.a libc-client.a
rm /usr/local/imap.tar.Z
</pre>
<h4>Download and Build PHP with PHP-FPM</h4>
<pre class="command">
cd ~/SourceCache
curl -O http://us2.php.net/distributions/php-5.3.6.tar.gz
tar -xzf php-5.3.6.tar.gz
cd php-5.3.6
</pre>
<p>This next configure line is escaped with backslashes and should be run as one giant, single command:</p>
<pre class="command">
./configure --prefix=/usr/local/php \
--mandir=/usr/share/man \
--infodir=/usr/share/info \
--sysconfdir=/private/etc \
--enable-cli \
--with-config-file-path=/usr/local/php/etc \
--with-libxml-dir=/usr \
--enable-xml \
--with-openssl=/usr \
--with-kerberos=/usr \
--with-zlib=/usr \
--enable-bcmath \
--with-bz2=/usr \
--enable-calendar \
--with-curl=/usr \
--enable-exif \
--enable-ftp \
--with-gd \
--with-jpeg-dir=/usr/local/Cellar/jpeg/8c/lib \
--with-png-dir=/usr/X11 \
--enable-gd-native-ttf \
--with-imap=/usr/local/imap-2007e \
--with-imap-ssl \
--with-ldap=/usr \
--with-ldap-sasl=/usr \
--enable-magic-quotes \
--enable-mbstring \
--enable-mbregex \
--enable-json \
--with-mysql=mysqlnd \
--with-mysqli=mysqlnd \
--with-pdo-mysql=mysqlnd \
--with-mysql-sock=/tmp/mysql.sock \
--with-iodbc=/usr \
--enable-shmop \
--with-snmp=/usr \
--enable-soap \
--enable-sockets \
--with-sqlite \
--enable-sysvmsg \
--enable-sysvsem \
--enable-sysvshm \
--enable-wddx \
--enable-fpm \
--with-mhash \
--with-mcrypt \
--with-xmlrpc \
--enable-xmlwriter \
--enable-xmlreader \
--with-iconv-dir=/usr \
--with-xsl=/usr \
--enable-zend-multibyte \
--enable-zip \
--with-pcre-regex=/usr \
--with-pdo-sqlite \
--enable-pdo \
--with-pdo-mysql \
--enable-dba \
--with-freetype-dir=/usr/X11 \
--enable-dom \
--enable-gd-native-ttf \
--enable-posix \
--enable-fileinfo
</pre>
<p>After PHP is done configuring, it&#8217;s time to build it.  This will take some time, so you might consider going and making a sandwich.</p>
<pre class="command">
make
</pre>
<p>Once compiled, PHP can be installed, and default/example config files can be copied to their actual destinations:</p>
<pre class="command">
sudo make install
sudo cp /private/etc/php-fpm.conf.default /private/etc/php-fpm.conf
sudo mkdir /usr/local/php/etc
sudo cp /private/etc/php.ini.default /usr/local/php/etc/php.ini
</pre>
<p>Like Nginx and MySQL, PHP-FPM won&#8217;t start up on its own, so we&#8217;ll again make use of a launchd plist:</p>
<pre class="command">
sudo mate /Library/LaunchDaemons/net.php.php-fpm.plist
</pre>
<p>Here is the content for the PHP-FPM launchd plist:</p>
<pre class="code">
&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"&gt;
&lt;plist version="1.0"&gt;
&lt;dict&gt;
    &lt;key&gt;KeepAlive&lt;/key&gt;
    &lt;true/&gt;
    &lt;key&gt;Label&lt;/key&gt;
    &lt;string&gt;net.php.php-fpm&lt;/string&gt;
    &lt;key&gt;LaunchOnlyOnce&lt;/key&gt;
    &lt;true/&gt;
    &lt;key&gt;NetworkState&lt;/key&gt;
    &lt;true/&gt;
    &lt;key&gt;ProgramArguments&lt;/key&gt;
    &lt;array&gt;
        &lt;string&gt;/usr/local/php/sbin/php-fpm&lt;/string&gt;
    &lt;/array&gt;
    &lt;key&gt;RunAtLoad&lt;/key&gt;
    &lt;true/&gt;
    &lt;key&gt;ServiceDescription&lt;/key&gt;
    &lt;string&gt;PHP FastCGI Process Manager&lt;/string&gt;
    &lt;key&gt;StandardErrorPath&lt;/key&gt;
    &lt;string&gt;/var/log/system.log&lt;/string&gt;
&lt;/dict&gt;
&lt;/plist&gt;
</pre>
<h4>Edit PHP-FPM Config File</h4>
<p>We&#8217;ve configured Nginx to communicate with PHP on port 9001, so now we need to configure PHP-FPM to listen for Nginx&#8217;s call.  At the same time, there are a few other options that can be configured such as the number of PHP-FPM processes to run simultaneously.</p>
<pre class="command">
sudo mate /private/etc/php-fpm.conf
</pre>
<p>Here is the content for a basic PHP-FPM config file that, among other things, tells PHP-FPM to listen on port 9001. Again, my username is in the config file, so you&#8217;ll want to replace that with your own.</p>
<pre class="code">
[global]
pid = /usr/local/php/var/run/php-fpm.pid
daemonize = yes

[www]
listen = 127.0.0.1:9001
user = collin
group = staff
pm = dynamic
pm.max_children = 10
pm.start_servers = 5
pm.min_spare_servers = 5
pm.max_spare_servers = 10
pm.max_requests = 500
</pre>
<p>With the config file saved, PHP-FPM is ready to run several worker processes at startup.</p>
<h4>Download and Build Xdebug</h4>
<p>The real key to the PHP debugging puzzle is the Xdebug extension, which is delightfully easy to build:</p>
<pre class="command">
cd ~/SourceCache
curl -O http://www.xdebug.org/files/xdebug-2.1.1.tgz
tar -xzf xdebug-2.1.1.tgz
cd xdebug-2.1.1
/usr/local/php/bin/phpize
/usr/local/php/bin/php-config
./configure --enable-xdebug
make
sudo make install
</pre>
<p>After installing Xdebug, we need to inform PHP that the extension is available and set a few basic options.  We can do this by editing the <code>php.ini</code> file we copied earlier, which contains a myriad of settings for PHP&#8217;s operation.</p>
<pre class="command">
sudo mate /usr/local/php/etc/php.ini
</pre>
<p>Add the following to the end of the file:</p>
<pre class="code">
zend_extension=/usr/lib/php/extensions/no-debug-non-zts-20090626/xdebug.so
xdebug.remote_enable=1
xdebug.remote_host=localhost
xdebug.remote_port=9000
xdebug.remote_autostart=1
</pre>
<h4>Start Everything Up</h4>
<p>One by one, start up each of the services we&#8217;ve installed:</p>
<pre class="command">
sudo launchctl load -F /Library/LaunchDaemons/com.mysql.mysqld.plist
sudo launchctl load -F /Library/LaunchDaemons/net.php.php-fpm.plist
sudo launchctl load -F /Library/LaunchDaemons/org.nginx.nginx.plist
</pre>
<h4>Write a PHP Script</h4>
<p>Just to make sure everything works, create a simple PHP script:</p>
<pre class="command">
mate ~/Sites/example/public/index.php
</pre>
<pre class="code">
&lt;?php

$animals = array('dog', 'cat', 'rabbit');
foreach ($animals as $animal)
{
    print "&lt;p&gt;Hello, $animal&lt;/p&gt;";
}
</pre>
<p>Visit <a href="http://example.local">http://example.local</a> in a browser to see the result.  It&#8217;s not Facebook or Twitter yet, but it&#8217;s enough to step into with a debugger.</p>
<h4>Install an Xdebug Browser Extension</h4>
<p>By default, Xdebug does not automatically debug PHP requests.  It needs to be triggered by a GET or POST parameter of <code>XDEBUG_SESSION_START</code>, or a cookie of the same name, but there is an even easier way.  Install an Xdebug extension for <a href="https://github.com/benmatselby/xdebug-toggler">Safari</a>, <a href="https://addons.mozilla.org/en-US/firefox/addon/58688">Firefox</a>, or <a href="https://chrome.google.com/extensions/detail/eadndfjplgieldjbigjakmdgkmoaaaoc">Chrome</a> to automatically set the Xdebug cookie when you need to debug code.</p>
<h4>Launch MacGDBp</h4>
<p>Now that we have all the tools installed, a PHP debug extension ready, and a browser extension to trigger it all, it&#8217;s time to debug that awesome script.</p>
<p>Launch MacGDBp, and note that it has a main debug window, a Breakpoints window, and a variable inspector.  Take a peek at the Preferences for MacGDBp, and you&#8217;ll note that you can choose to break on the first line of PHP (or wait until a breakpoint is hit).  I like to uncheck that checkbox because some applications have a fair bit of setup code that needs to be skipped each time.  You&#8217;ll also find that the default Xdebug port is set to 9000.  Earlier, we configured PHP-FPM to listen on port 9001, and this is why we made that change &#8212; both tools default to running on port 9000.  And just like in Ghostbusters, it&#8217;s best not to cross the streams.  It would be bad.</p>
<p><img src="http://static.command-tab.com/2011/php-debugging/macdbgp-port.jpg" class="framed" /></p>
<p>In MacGDBp&#8217;s Breakpoints window, hit the little &#8220;+&#8221; button in the lower-left to add a new breakpoint, and navigate to the <code>index.php</code> we created above.  Once added, you&#8217;ll see the source code for that script in the upper half of the window.  Click on a line number to add a breakpoint.</p>
<p><img src="http://static.command-tab.com/2011/php-debugging/breakpoint.jpg" class="framed" /></p>
<p>With the breakpoint set, flip back to your browser and toggle Xdebug using the installed extension, and reload the page.  You&#8217;ll see your browser appear to hang while loading, as if the page is taking a while to load.  Under the hood, Xdebug has actually paused PHP&#8217;s script execution and started a debug session, ready for you to see what&#8217;s going on.</p>
<p><img src="http://static.command-tab.com/2011/php-debugging/browser-hang.jpg" class="framed" /></p>
<p>Behind the browser window, MacDBGp should have hit the breakpoint, ready to inspect variables or step through code:</p>
<p><img src="http://static.command-tab.com/2011/php-debugging/stepping.jpg" class="framed" /></p>
<p>This works for everything from the simplest scripts like we did here, up through complex web apps with deep frameworks.  Just set a breakpoint, start the code, and step through to see where the execution deviates from your expectations.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.command-tab.com/2011/06/20/true-php-debugging-with-nginx-and-php-fpm/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Apple ID Email Verification Woes</title>
		<link>http://www.command-tab.com/2011/06/13/apple-id-email-verification-woes/</link>
		<comments>http://www.command-tab.com/2011/06/13/apple-id-email-verification-woes/#comments</comments>
		<pubDate>Tue, 14 Jun 2011 04:43:40 +0000</pubDate>
		<dc:creator>Collin</dc:creator>
				<category><![CDATA[Misc]]></category>

		<guid isPermaLink="false">http://www.command-tab.com/?p=1159</guid>
		<description><![CDATA[As a longtime Mac user, I&#8217;ve had an account on file with Apple dating back to when iTools was available. Only recently has the Apple ID become much more important as a personal identifier. Back then, Apple IDs were mostly a means for me to identify myself to Apple. Now, people find me using my [...]]]></description>
			<content:encoded><![CDATA[<p>As a longtime Mac user, I&#8217;ve had an account on file with Apple dating back to when iTools was available. Only recently has the Apple ID become much more important as a personal identifier. Back then, Apple IDs were mostly a means for me to identify myself to Apple. Now, people find me using my Apple ID for FaceTime, iMessage, Game Center, and more.</p>
<p>Not so long ago, I decided that I wasn&#8217;t happy with this Apple ID and created a new one to do everything with. It was, however, long enough ago that Apple IDs weren&#8217;t yet required to be in the form of an email address. So, this new one was just a new name.</p>
<p>More recently, I decided that I should switch my new Apple ID to be in the form of an email address like they now encourage, and verify the matching email address with it.  Only, the Apple ID management system would not let me do this, reporting that:</p>
<blockquote><p>Email address is already verified for another Apple ID</p></blockquote>
<p>I didn&#8217;t recall verifying this email address with any other Apple ID.  Even using the &#8220;Forgot my Apple ID&#8221; tool, which searches for Apple IDs given an email address, produced no Apple IDs that had a record of that email address.  Even my old Apple ID didn&#8217;t list this email address as one of its verified emails.</p>
<p>As it turns out &#8212; and this is after trying many different things including contacting Apple ID Support &#8212; MobileMe requires a backup email address in the event you forget your MobileMe password.  The email address I wanted to verify with my new Apple ID was set as my MobileMe backup email address for my old Apple ID.  This counts as a verify, even though it&#8217;s not listed as a verified email address on the Apple ID site for my MobileMe account.</p>
<p>Simply setting up a new email account with my provider dedicated to MobileMe &#8212; one I&#8217;ll probably never check unless I need to &#8212; and using <em>that</em> as my MobileMe backup email address freed up the desired email address I wanted to associate with my new Apple ID.</p>
<p>Hopefully this will help someone who may be running into the same issue. Figuring all this out was wildly confusing at times, and even more difficult to explain to Apple ID Support, which is probably why we never got the issue resolved until now!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.command-tab.com/2011/06/13/apple-id-email-verification-woes/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Simulating Slow Internet for iOS Testing</title>
		<link>http://www.command-tab.com/2011/05/11/simulating-slow-internet-for-ios-testing/</link>
		<comments>http://www.command-tab.com/2011/05/11/simulating-slow-internet-for-ios-testing/#comments</comments>
		<pubDate>Thu, 12 May 2011 02:58:35 +0000</pubDate>
		<dc:creator>Collin</dc:creator>
				<category><![CDATA[Misc]]></category>

		<guid isPermaLink="false">http://www.command-tab.com/?p=991</guid>
		<description><![CDATA[Apple&#8217;s iOS Simulator is an acceptable environment for testing development code, but when users purchase your finished app from the App Store, they&#8217;ll be running it on real hardware, particularly on networks that are likely much less reliable than your home or office internet. To ensure your app performs well under real-world conditions, you can [...]]]></description>
			<content:encoded><![CDATA[<p>Apple&#8217;s iOS Simulator is an acceptable environment for testing development code, but when users purchase your finished app from the App Store, they&#8217;ll be running it on real hardware, particularly on networks that are likely much less reliable than your home or office internet.  </p>
<p>To ensure your app performs well under real-world conditions, you can load up the code on a device and go outside, but then you can&#8217;t debug as easily.  And even if you bring your MacBook Air with you, what if your Verizon iPhone is everything you hoped, and it performs admirably on the worst of days?  To get around all of this, you can approximate an unreliable network with <a href="http://mschrag.github.com/">SpeedLimit</a>.  SpeedLimit is a System Preferences pane for intentionally and selectively slowing down specific ports and domains:</p>
<p><a href="http://mschrag.github.com/"><img class="framed" src="http://static.command-tab.com/2011/speedlimit/speedlimit.jpg" alt="SpeedLimit Preference Pane" /></a></p>
<p>Download and install SpeedLimit, add one or more hosts (separated by commas, as seen above), select a target speed, and click Slow Down.  Subsequent network requests matching the criteria you set will be throttled, giving you time to go all out testing your app&#8217;s performance and error handling.  Does it crash when users hit the Back button while a UITableView is loading?  Does it lock the UI while downloading avatars or thumbnails?  SpeedLimit lets you find out, and be confident in your networking code.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.command-tab.com/2011/05/11/simulating-slow-internet-for-ios-testing/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>iOS Icon Template</title>
		<link>http://www.command-tab.com/2011/04/22/ios-icon-template/</link>
		<comments>http://www.command-tab.com/2011/04/22/ios-icon-template/#comments</comments>
		<pubDate>Fri, 22 Apr 2011 15:36:12 +0000</pubDate>
		<dc:creator>Collin</dc:creator>
				<category><![CDATA[Icons]]></category>
		<category><![CDATA[Photoshop]]></category>

		<guid isPermaLink="false">http://www.command-tab.com/?p=973</guid>
		<description><![CDATA[So you want to make pixel-perfect icons for iPhone and iPad, but can&#8217;t get it just right? Here&#8217;s my own personal icon template that makes designing and previewing icons a breeze. Click the preview to download the organized and layered Photoshop file. The template also includes layers for creating iPad document icons. Be sure to [...]]]></description>
			<content:encoded><![CDATA[<p>So you want to make pixel-perfect icons for iPhone and iPad, but can&#8217;t get it <em>just</em> right?  Here&#8217;s my own personal icon template that makes designing and previewing icons a breeze.  Click the preview to download the organized and layered Photoshop file.</p>
<p><a href="http://static.command-tab.com/2011/ios-icon-template/iOS%20Icon%20Template.zip"><img class="framed" src="http://static.command-tab.com/2011/ios-icon-template/preview.jpg" alt="iOS Icon Template Preview" /></a></p>
<p>The template also includes layers for creating iPad document icons.  Be sure to read Apple&#8217;s documentation for a clear explanation of how icons are to be formatted and used in apps: <a href="http://developer.apple.com/library/ios/#documentation/userexperience/conceptual/mobilehig/IconsImages/IconsImages.html">iOS Human Interface Guidelines: Custom Icon and Image Creation Guidelines</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.command-tab.com/2011/04/22/ios-icon-template/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>fmTuner 1.1</title>
		<link>http://www.command-tab.com/2010/02/01/fmtuner-1-1/</link>
		<comments>http://www.command-tab.com/2010/02/01/fmtuner-1-1/#comments</comments>
		<pubDate>Mon, 01 Feb 2010 21:09:51 +0000</pubDate>
		<dc:creator>Collin</dc:creator>
				<category><![CDATA[Misc]]></category>

		<guid isPermaLink="false">http://www.command-tab.com/?p=516</guid>
		<description><![CDATA[My WordPress plugin for displaying Last.fm music, fmTuner, has been updated to 1.1, adding a much-requested album artwork placeholder field, and testing for the latest and greatest version of WordPress. The upgrade will work seamlessly with your current fmTuner design, but if you visit the fmTuner Settings page, you&#8217;ll see that you can now specify [...]]]></description>
			<content:encoded><![CDATA[<p>My WordPress plugin for displaying Last.fm music, <a href="http://wordpress.org/extend/plugins/fmtuner/">fmTuner</a>, has been updated to 1.1, adding a much-requested album artwork placeholder field, and testing for the latest and greatest version of <a href="http://wordpress.org/">WordPress</a>.</p>
<p>The upgrade will work seamlessly with your current fmTuner design, but if you visit the fmTuner Settings page, you&#8217;ll see that you can now specify a link to a placeholder image, which will be used if Last.fm comes up short on album art.  Leaving this field blank (the default) will simply skip tracks without artwork.  If you want to get really fancy, there&#8217;s even a fmTuner tag that will print out the path to your current WordPress theme, if you&#8217;d like different album art placeholders for different themes.</p>
<p><a href="http://wordpress.org/extend/plugins/fmtuner/">Download fmTuner from WordPress.org</a> for the latest version!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.command-tab.com/2010/02/01/fmtuner-1-1/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Widerbug for Firefox 3.6+</title>
		<link>http://www.command-tab.com/2010/01/25/widerbug-for-firefox-3-6/</link>
		<comments>http://www.command-tab.com/2010/01/25/widerbug-for-firefox-3-6/#comments</comments>
		<pubDate>Tue, 26 Jan 2010 02:28:55 +0000</pubDate>
		<dc:creator>Collin</dc:creator>
				<category><![CDATA[Misc]]></category>

		<guid isPermaLink="false">http://www.command-tab.com/?p=515</guid>
		<description><![CDATA[I&#8217;ve just updated Widerbug to 1.5.0, once again up to date with the enhancements from Firebug 1.5.0. If you&#8217;re running Widerbug 1.3.3 or later, you should receive 1.5.0 via an automatic update. Or, head over to the Widerbug download page to install it. I know at some point I should attempt to merge my changes [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://static.command-tab.com/2008/widerbug_banner.jpg" alt="Widerbug" /><br />
I&#8217;ve just updated Widerbug to 1.5.0, once again up to date with the enhancements from Firebug 1.5.0.  If you&#8217;re running Widerbug 1.3.3 or later, you should receive 1.5.0 via an automatic update.  Or, head over to the <a href="/2008/01/19/widerbug-widescreen-firebug/">Widerbug download page</a> to install it.</p>
<p>I know at some point I should attempt to merge my changes into the Firebug codebase and submit a patch (and stop this Firebug cat-and-mouse game), but my XUL knowledge is still fairly limited.  If anyone would like to take on the challenge, though, I imagine your patch would be a welcome addition to Firebug&#8217;s core!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.command-tab.com/2010/01/25/widerbug-for-firefox-3-6/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How to Find the Right Windows Driver</title>
		<link>http://www.command-tab.com/2009/09/13/how-to-find-the-right-windows-driver/</link>
		<comments>http://www.command-tab.com/2009/09/13/how-to-find-the-right-windows-driver/#comments</comments>
		<pubDate>Mon, 14 Sep 2009 02:32:14 +0000</pubDate>
		<dc:creator>Collin</dc:creator>
				<category><![CDATA[Misc]]></category>

		<guid isPermaLink="false">http://www.command-tab.com/?p=499</guid>
		<description><![CDATA[When setting up a new Windows machine, whether it&#8217;s Windows 2000 all the way up through Windows 7, you&#8217;ll occasionally run into an issue where you need drivers for a system or PCI device that you just can&#8217;t seem to find. To make matters worse, you don&#8217;t know which company made the device, so you [...]]]></description>
			<content:encoded><![CDATA[<p>When setting up a new Windows machine, whether it&#8217;s Windows 2000 all the way up through Windows 7, you&#8217;ll occasionally run into an issue where you need drivers for a system or PCI device that you just can&#8217;t seem to find.  To make matters worse, you don&#8217;t know which company made the device, so you don&#8217;t even know where to start looking for drivers.  Should you go to Dell&#8217;s site?  The motherboard manufacturer?  Persistent &#8220;Unknown device&#8221; entries in the Windows Device Manager are a plague upon even the most seasoned techs.  Here&#8217;s a tip to get your driver hunt moving in the right direction.</p>
<h4>Find Out Who Made the Device</h4>
<p>Figuring out which company made the device(s) in question is the first step towards getting it working.  Start by opening the Windows Device Manager.  My preferred quick way of doing this is clicking Start -> Run -> type &#8220;devmgmt.msc&#8221; -> press Enter.  Once there, choose the device in question and right click it, and select Properties.  Select the Details tab to see something like the view below:</p>
<p><img src="http://static.command-tab.com/2009/windows_device_manager.jpg" alt="Windows Device Manager" class="framed"  /></p>
<p>Note the PCI &#8220;VEN&#8221; and &#8220;DEV&#8221; 4-character identifiers.  PCI, USB, and many other system devices have Vendor and Device IDs.  The Vendor ID is specific to the manufacturer, like Broadcom or nVIDIA.  The Device ID is specific to the particular make or model of device you have.  These are expressed in hexadecimal (0 through 9 plus A through F), so don&#8217;t be surprised to see letters there, as well.  Some common Vendor IDs are 8080 and 8086 for Intel, 0A5C for Broadcom, 10DE for nVIDIA, 1002 for ATI, and <a href="http://www.pcidatabase.com/reports.php?type=tab-delimeted">many more</a>.</p>
<h4>Look Up Vendor and Device IDs</h4>
<p>A common way to express both the Vendor and Device IDs in a single string is 1022:2000, Vendor ID first.  Combine your Vendor and Device IDs in this manner, and wrap it with quotes: &#8220;1022:2000&#8243;.  Google that, and you should quickly figure out who made your &#8220;Unknown device&#8221; and what model it is.  With this knowledge, you can either find the appropriate driver on your computer manufacturer&#8217;s website (Dell makes a good note of which manufacturer&#8217;s devices they use for a particular system), or you can visit the device manufacturer&#8217;s website directly.</p>
<p>I hope this information can help those looking to simply get their hardware working under Windows, whether it&#8217;s running on a Mac or PC.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.command-tab.com/2009/09/13/how-to-find-the-right-windows-driver/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Widerbug for Firefox 3.5+</title>
		<link>http://www.command-tab.com/2009/07/17/widerbug-for-firefox-3-5/</link>
		<comments>http://www.command-tab.com/2009/07/17/widerbug-for-firefox-3-5/#comments</comments>
		<pubDate>Sat, 18 Jul 2009 02:23:56 +0000</pubDate>
		<dc:creator>Collin</dc:creator>
				<category><![CDATA[NerdLab]]></category>

		<guid isPermaLink="false">http://www.command-tab.com/?p=497</guid>
		<description><![CDATA[I&#8217;ve just updated Widerbug to 1.4.0, keeping in step with the most recent Firebug update. Most notably, this release is compatible with Firefox 3.5 and newer. Head over to the Widerbug download page to install it. Or, if you already have Widerbug 1.3.3, you should receive it via automatic update.]]></description>
			<content:encoded><![CDATA[<p><img src="http://static.command-tab.com/2008/widerbug_banner.jpg" alt="Widerbug" /><br />
I&#8217;ve just updated Widerbug to 1.4.0, keeping in step with the most recent Firebug update.  Most notably, this release is compatible with Firefox 3.5 and newer.  Head over to the <a href="/2008/01/19/widerbug-widescreen-firebug/">Widerbug download page</a> to install it.  Or, if you already have Widerbug 1.3.3, you should receive it via automatic update.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.command-tab.com/2009/07/17/widerbug-for-firefox-3-5/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>MacAlly IceKey USB 2.0</title>
		<link>http://www.command-tab.com/2009/07/05/macally-icekey-usb-2-0/</link>
		<comments>http://www.command-tab.com/2009/07/05/macally-icekey-usb-2-0/#comments</comments>
		<pubDate>Sun, 05 Jul 2009 17:35:02 +0000</pubDate>
		<dc:creator>Collin</dc:creator>
				<category><![CDATA[Hacks]]></category>

		<guid isPermaLink="false">http://www.command-tab.com/?p=486</guid>
		<description><![CDATA[MacAlly has been producing the same IceKey keyboard since 2003, and while it&#8217;s a solid performer featuring comfortable low profile scissor keys and extra USB ports, it still ships with a maddeningly slow internal USB 1.1 hub. While this early USB specification is plenty fast for a keyboard alone, it throttles back speeds of all [...]]]></description>
			<content:encoded><![CDATA[<p>MacAlly has been producing the same IceKey keyboard since 2003, and while it&#8217;s a solid performer featuring comfortable low profile scissor keys and extra USB ports, it still ships with a maddeningly slow internal USB 1.1 hub.  While this early USB specification is plenty fast for a keyboard alone, it throttles back speeds of all attached devices like flash drives, iPods, and digital cameras.  Copying an music album or two can take several minutes over USB 1.1, whereas today&#8217;s USB 2.0 takes only seconds.  With USB 2.0 as today&#8217;s ubiquitous standard and USB 3.0 just around the corner, it&#8217;s disappointing that MacAlly has yet to update the IceKey to include a faster hub.  Luckily, you can take matters into your own hands.  Here&#8217;s how to install a high speed hub inside the keyboard while maintaining MacAlly&#8217;s elegant factory appearance.</p>
<p><img src="http://static.command-tab.com/2009/macally_icekey_start.jpg" alt="MacAlly IceKey USB 2.0" class="framed" /></p>
<h4>What You&#8217;ll Need</h4>
<ul>
<li>a MacAlly IceKey</li>
<li>a small, narrow USB hub (a cheapo Targus hub worked fine for me)</li>
<li>a screwdriver set</li>
<li>a soldering iron, solder, and spare wire</li>
<li>a pocket knife (I&#8217;m not sure any project I&#8217;ve done <em>didn&#8217;t</em> require this&#8230;)</li>
</ul>
<h4>Open the Hub</h4>
<p>USB hubs generally aren&#8217;t too complicated to open, and this Targus on is no exception.  A single screw on the underside holds together the hub&#8217;s two plastic halves, which snap apart with little effort.  Write a note or take a picture to document the wire colors and order relevant to the orientation of the board inside &#8212; it will come in handy later.</p>
<p><img src="http://static.command-tab.com/2009/macally_usb_hub_board.jpg" alt="USB Hub Board" class="framed" /></p>
<h4>Open the Keyboard</h4>
<p>The MacAlly IceKey is slightly trickier to get apart, but not much.  Remove all the obvious screws on the bottom of the keyboard, including the one under the &#8220;Do Not Remove&#8221;/Quality Control/Warranty sticker.  Then, flip open the pivoting feet to expose two more screws covered by a protective piece of rubber.  The final two screws are under the front rubber feet.</p>
<p>Starting with the keyboard upright and facing you, begin unsnapping the plastic hooks around the perimeter starting at the front middle.  A <a href="/2005/11/17/apples-black-stick/">plastic pry tool</a> might come in handy, but isn&#8217;t required.  Once the top is removed, you can clearly see all the important electronics, including a very common Cypress USB controller chip.</p>
<p><img src="http://static.command-tab.com/2009/macally_keyboard_controller.jpg" alt="MacAlly IceKey USB 1.1 Keyboard Controller" class="framed" /></p>
<p><img src="http://static.command-tab.com/2009/macally_keyboard_leftport.jpg" alt="MacAlly IceKey Left USB 1.1 Port" class="framed" /></p>
<h4>Test Fit Everything</h4>
<p>Just to make sure the rest of this modification is physically possible, fit the USB hub board in the open space at the top of the keyboard and set the keyboard bezel on top.  Luckily, the IceKey has plenty of room to spare.  I was planning to have to remove the USB ports from the hub board to make everything fit, but there was so much extra space that I didn&#8217;t even have to go to that length.</p>
<h4>Unhook the Keyboard</h4>
<p>Carefully pull the keyboard ribbon cables straight away from their matching plugs on the controller board.  Gently flip the keyboard pad over, and unscrew the two short ground wires to completely free the keyboard keys from the plastic housing.  Set it aside for later; it does not need to be modified &#8212; all the action happens on the two remaining circuit boards.  Unscrew both boards to get at the backs of each.</p>
<p><img src="http://static.command-tab.com/2009/macally_keyboard_ribbon_cables.jpg" alt="MacAlly IceKey Keyboard Ribbon Cables" class="framed" /></p>
<h4>Cut Wires</h4>
<p>Cut the gray ribbon that leads from the controller board to the left port.  Since that wire only provides USB 1.1 speed, we won&#8217;t be using it.  You&#8217;ll note that it has two extra wires that run to an unpopulated LED on the left board, so we can skip those when doing the re-wiring.  (I wonder what MacAlly had in store for that, or if this keyboard is a &#8220;port&#8221; from another language or something?)</p>
<p>Unplug the USB cord from the controller board and cut off the connector.  This cord needs to run to the input on the new USB hub, and not to the input on the keyboard controller board where it currently connects.</p>
<h4>Cut Traces</h4>
<p>Since the right port also needs USB 2.0 speeds, it too will need to be disconnected from its USB 1.1 source.  However, it is soldered directly onto the controller board and is effectively hard-wired into the slowness.  This is perhaps the trickiest part of the whole project: desolder the USB connector and use a knife to scrape away the traces that run to the port.  Some are on top of the board, and some are on the bottom.  (You might be able to get away with cutting the traces without removing the port, as a little bit of the traces are exposed on the top before routing into electronic components, but you&#8217;ll want to test with a multimeter and make sure you&#8217;ve done this successfully.)  Once all four traces to the port are cut, re-solder the USB port in place (if you removed it).</p>
<p><img src="http://static.command-tab.com/2009/macally_usb_traces_cut.jpg" alt="MacAlly IceKey USB Traces Cut" class="framed" /></p>
<h4>Re-wire the Keyboard Controller and Ports</h4>
<p>Here&#8217;s a simple before and after block diagram to help your wiring layout:</p>
<p><img src="http://static.command-tab.com/2009/macally_icekey2_diagram.gif" alt="MacAlly IceKey USB 2.0 Diagram" class="framed" /></p>
<h4>Solder Keyboard Cord to Hub Input</h4>
<p>Strip about an inch of plastic from the cut end of the keyboard cord to expose its individual wires, and strip just a millimeter or two from each of those.  Using your note from earlier, solder the keyboard wires to the matching USB hub input connections.  On this Targus hub, the wires were in the same order as the standard <a href="http://images.google.com/images?q=USB%20pinout">USB pinout</a>.</p>
<h4>Solder Keyboard Controller to a Hub Port</h4>
<p>Solder four wires from the keyboard input port (where the cord originally connected to) to one of the USB hub ports, effectively making the keyboard controller into one of four devices on the hub.  Previously, the keyboard supplied its own hub, but we&#8217;re bypassing it altogether.  Luckily, most everything is either color coded or silkscreen labeled on the circuit boards (<code>V/5V</code> is red, <code>D-</code> is green, <code>D+</code> is white, and <code>G/GND</code> is black).</p>
<h4>Solder Keyboard USB Ports to Hub Ports</h4>
<p>Solder wire from the left USB port board to another free USB hub port, making sure to get the order correct.  With the traces cut on the right port, run wire from the connections under the board to yet another free hub port.  You should end up with a hub layout like this:</p>
<p><img src="http://static.command-tab.com/2009/macally_keyboard_hub_wires.jpg" alt="MacAlly IceKey USB 2.0 Hub Wires" class="framed" /></p>
<h4>Test and Close It Up</h4>
<p>With each new component wired up, double-check your connections and plug it in.  Initially, my first test failed and Windows complained about a malfunctioning USB device (I tested it on an old PC, just in case I shorted out the computer&#8217;s USB controller.  I&#8217;d rather fry an old computer than my new iMac!)  The key to making everything work properly was to reconnect those two shared ground wires from early on &#8212; the keyboard must have a common ground with the controller and hub!</p>
<p><img src="http://static.command-tab.com/2009/macally_keyboard_test.jpg" alt="MacAlly IceKey USB 2.0 Keyboard Test" class="framed" /></p>
<p>Once it works, secure all the wires and boards.  I used a few short pieces of electrical tape to stop everything from bouncing around, too.  Snap the plastic top back on, replace all the screws, and enjoy your USB 2.0 MacAlly IceKey!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.command-tab.com/2009/07/05/macally-icekey-usb-2-0/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

