Merge branch 'deploy'
2
.rvmrc
|
@ -1 +1 @@
|
||||||
rvm --create 1.9.2@wezm.net
|
rvm use default
|
||||||
|
|
7
Gemfile
|
@ -1,14 +1,13 @@
|
||||||
source :rubygems
|
source :rubygems
|
||||||
|
|
||||||
|
gem 'rake'
|
||||||
gem 'mime-types'
|
gem 'mime-types'
|
||||||
gem 'nanoc'
|
gem 'nanoc'
|
||||||
gem 'bitly'
|
gem 'bitly'
|
||||||
gem 'haml'
|
gem 'haml'
|
||||||
|
gem 'sass'
|
||||||
gem 'rdiscount'
|
gem 'rdiscount'
|
||||||
gem 'rubypants'
|
gem 'rubypants'
|
||||||
gem 'nokogiri'
|
gem 'nokogiri'
|
||||||
gem 'builder'
|
gem 'builder'
|
||||||
gem 'rb-fsevent'
|
gem 'fssm'
|
||||||
gem 'guard'
|
|
||||||
gem 'guard-nanoc'
|
|
||||||
gem 'growl'
|
|
||||||
|
|
85
Gemfile.lock
|
@ -1,51 +1,43 @@
|
||||||
GEM
|
GEM
|
||||||
remote: http://rubygems.org/
|
remote: http://rubygems.org/
|
||||||
specs:
|
specs:
|
||||||
addressable (2.2.2)
|
bitly (0.8.0)
|
||||||
bitly (0.6.1)
|
|
||||||
crack (>= 0.1.4)
|
crack (>= 0.1.4)
|
||||||
httparty (>= 0.5.2)
|
httparty (>= 0.7.6)
|
||||||
oauth2 (>= 0.1.1)
|
oauth2 (>= 0.5.0, < 0.9)
|
||||||
builder (3.0.0)
|
builder (3.1.4)
|
||||||
configuration (1.2.0)
|
colored (1.2)
|
||||||
crack (0.1.8)
|
crack (0.3.1)
|
||||||
cri (1.0.1)
|
cri (2.3.0)
|
||||||
faraday (0.5.4)
|
colored (>= 1.2)
|
||||||
addressable (~> 2.2.2)
|
faraday (0.8.4)
|
||||||
multipart-post (~> 1.1.0)
|
multipart-post (~> 1.1)
|
||||||
rack (< 2, >= 1.1.0)
|
fssm (0.2.9)
|
||||||
growl (1.0.3)
|
haml (3.1.7)
|
||||||
guard (0.3.0)
|
httparty (0.9.0)
|
||||||
open_gem (~> 1.4.2)
|
multi_json (~> 1.0)
|
||||||
thor (~> 0.14.6)
|
multi_xml
|
||||||
guard-nanoc (0.1.0)
|
httpauth (0.2.0)
|
||||||
guard (>= 0.2.1)
|
jwt (0.1.5)
|
||||||
nanoc (>= 3.1.5)
|
multi_json (>= 1.0)
|
||||||
haml (3.0.25)
|
mime-types (1.19)
|
||||||
httparty (0.7.2)
|
multi_json (1.3.6)
|
||||||
crack (= 0.1.8)
|
multi_xml (0.5.1)
|
||||||
launchy (0.3.7)
|
multipart-post (1.1.5)
|
||||||
configuration (>= 0.0.5)
|
nanoc (3.4.3)
|
||||||
rake (>= 0.8.1)
|
cri (~> 2.2)
|
||||||
mime-types (1.16)
|
nokogiri (1.5.5)
|
||||||
multi_json (0.0.5)
|
oauth2 (0.8.0)
|
||||||
multipart-post (1.1.0)
|
faraday (~> 0.8)
|
||||||
nanoc (3.1.6)
|
httpauth (~> 0.1)
|
||||||
nanoc3 (>= 3.1.6)
|
jwt (~> 0.1.4)
|
||||||
nanoc3 (3.1.6)
|
multi_json (~> 1.0)
|
||||||
cri (>= 1.0.0)
|
rack (~> 1.2)
|
||||||
nokogiri (1.4.4)
|
rack (1.4.1)
|
||||||
oauth2 (0.1.1)
|
rake (0.9.2.2)
|
||||||
faraday (~> 0.5.0)
|
rdiscount (1.6.8)
|
||||||
multi_json (~> 0.0.4)
|
|
||||||
open_gem (1.4.2)
|
|
||||||
launchy (~> 0.3.5)
|
|
||||||
rack (1.2.1)
|
|
||||||
rake (0.8.7)
|
|
||||||
rb-fsevent (0.3.9)
|
|
||||||
rdiscount (1.6.5)
|
|
||||||
rubypants (0.2.0)
|
rubypants (0.2.0)
|
||||||
thor (0.14.6)
|
sass (3.2.1)
|
||||||
|
|
||||||
PLATFORMS
|
PLATFORMS
|
||||||
ruby
|
ruby
|
||||||
|
@ -53,13 +45,12 @@ PLATFORMS
|
||||||
DEPENDENCIES
|
DEPENDENCIES
|
||||||
bitly
|
bitly
|
||||||
builder
|
builder
|
||||||
growl
|
fssm
|
||||||
guard
|
|
||||||
guard-nanoc
|
|
||||||
haml
|
haml
|
||||||
mime-types
|
mime-types
|
||||||
nanoc
|
nanoc
|
||||||
nokogiri
|
nokogiri
|
||||||
rb-fsevent
|
rake
|
||||||
rdiscount
|
rdiscount
|
||||||
rubypants
|
rubypants
|
||||||
|
sass
|
||||||
|
|
|
@ -1,6 +0,0 @@
|
||||||
guard 'nanoc' do
|
|
||||||
watch(%r'^config.yaml')
|
|
||||||
watch(%r'^Rules')
|
|
||||||
watch(%r'^layouts\/')
|
|
||||||
watch(%r'^content\/')
|
|
||||||
end
|
|
|
@ -12,10 +12,13 @@ This Site
|
||||||
---------
|
---------
|
||||||
|
|
||||||
This site is written in [Markdown][markdown] and [SASS][sass], generated using
|
This site is written in [Markdown][markdown] and [SASS][sass], generated using
|
||||||
[nanoc][nanoc], enhanced with [jQuery][jquery] and hosted on a <a
|
[nanoc][nanoc], enhanced with [jQuery][jquery] and hosted on VPS running
|
||||||
href="http://manage.crucialp.com/aff.php?aff=261" class="affiliate"
|
[Debian GNU/Linux][debian] and [nginx][nginx]. It makes use of the following
|
||||||
title="Affiliate link">Crucial Paradigm</a> VPS running [Debian
|
resources made available freely by their authors:
|
||||||
GNU/Linux][debian] and [nginx][nginx].
|
|
||||||
|
* [Reset CSS][cssreset] by Eric Meyer
|
||||||
|
* [Mono icons][monoicons] by tutorial9
|
||||||
|
* [Feed icon][feedicon] by FeedIcons.com and the Mozilla Foundation
|
||||||
|
|
||||||
The content is split into two sections:
|
The content is split into two sections:
|
||||||
[Technical](/technical/articles/) and [Personal](/personal/articles/). There is
|
[Technical](/technical/articles/) and [Personal](/personal/articles/). There is
|
||||||
|
@ -48,3 +51,6 @@ photos. My primary camera is a Canon 400D SLR, with the following lenses:
|
||||||
[debian]: http://www.debian.org/
|
[debian]: http://www.debian.org/
|
||||||
[jquery]: http://jquery.com/
|
[jquery]: http://jquery.com/
|
||||||
[sass]: http://sass-lang.com/
|
[sass]: http://sass-lang.com/
|
||||||
|
[cssreset]: http://meyerweb.com/eric/tools/css/reset/
|
||||||
|
[monoicons]: http://www.tutorial9.net/resources/108-mono-icons-huge-set-of-minimal-icons/
|
||||||
|
[feedicon]: http://feedicons.com/
|
||||||
|
|
|
@ -35,6 +35,11 @@ while(x=eval(x));}hiveware_enkoder();
|
||||||
//]]>
|
//]]>
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
App.net
|
||||||
|
-------
|
||||||
|
|
||||||
|
[https://alpha.app.net/wezm](https://alpha.app.net/wezm)
|
||||||
|
|
||||||
Twitter
|
Twitter
|
||||||
-------
|
-------
|
||||||
|
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
Google's web browser, Chrome, has been available as a developer preview for some time now. Recently it shifted to beta status and the polish keeps piling on. There are a lot of nice touches in the browser that have contributed to me switching away from Safari such as multi-purpose address/search bar, tab closing behaviour, performance and a supported extension mechanism. Some of these things were discussed in Rob Friesel Jr.'s <a href="http://blog.founddrama.net/2010/01/a-week-with-chrome/">a Week With Chrome</a> and Basil Safwat's obviously tab focussed, <a href="http://www.theinvisibl.com/news/2009/12/08/a-piece-with-a-lot-of-screenshots-about-the-close-tab-behaviour-in-google-chrome/">A piece with a lot of screenshots about the close tab behaviour in Google Chrome</a>.
|
|
||||||
|
|
||||||
Today, whilst reading http://orderedlist.com/our-writing/resources/html-css/single-line-css/
|
|
|
@ -1,14 +0,0 @@
|
||||||
---
|
|
||||||
slug: google-chrome-for-mac
|
|
||||||
permalink: http://www.wezm.net/?p=298
|
|
||||||
kind: draft
|
|
||||||
is_hidden: true
|
|
||||||
section: personal
|
|
||||||
created_at: 0000-00-00 00:00:00
|
|
||||||
title: Google Chrome for Mac
|
|
||||||
post_id: 298
|
|
||||||
tags: []
|
|
||||||
|
|
||||||
categories:
|
|
||||||
- Miscellaneous
|
|
||||||
status: draft
|
|
|
@ -1,3 +0,0 @@
|
||||||
On the topic of OS's nearing release, Haiku is set for an alpha release in Sep[1]: http://www.osnews.com/story/22001/Haiku_Schedules_First_Alpha_Release_for_September_9
|
|
||||||
|
|
||||||
If you haven't heard of <a href="http://www.haiku-os.org/">Haiku </a>its a rewrite of BeOS from scratch. The aim of the first release is compatibility with the last official release of BeOS: R5. They're a good way down that path. As far as I know many apps that were built for R5 will run on Haiku. I've been following the project for a while now. Back in uni I downloaded an installed BeOS on my PC, this was obviously before the company went out of business/was bought by Palm (I think). The bit that interests me about it is that its GUI out of the box, much like OS X and Windows. Its attributes such as compactness, GUI, open source and POSIX core makes it a great candidate for high level embedded type projects I think. Things like the digital photo frame project I've had in mind for a while. Its one drawback in my mind is that the platform's primary language is C++, which I'm not a huge fan of. However if you're into C++ it might be worth checking out. If I recall correctly large parts of the kernel are written in C++ too.
|
|
|
@ -1,14 +0,0 @@
|
||||||
---
|
|
||||||
slug: haiku
|
|
||||||
permalink: http://www.wezm.net/?p=240
|
|
||||||
kind: draft
|
|
||||||
is_hidden: true
|
|
||||||
section: personal
|
|
||||||
created_at: 0000-00-00 00:00:00
|
|
||||||
title: Haiku
|
|
||||||
post_id: 240
|
|
||||||
tags:
|
|
||||||
- os
|
|
||||||
categories:
|
|
||||||
- Miscellaneous
|
|
||||||
status: draft
|
|
|
@ -1,3 +0,0 @@
|
||||||
Reminders aren't aggressive enough. A single buzz when on silent is not enough and makes them very easy to miss. They should behave like a phone call and persist until acknwledged.
|
|
||||||
|
|
||||||
Lack of camera functionality: no timed photos
|
|
|
@ -1,14 +0,0 @@
|
||||||
---
|
|
||||||
slug: iphone-gripes-reminders
|
|
||||||
permalink: http://www.wezm.net/?p=237
|
|
||||||
kind: draft
|
|
||||||
is_hidden: true
|
|
||||||
section: technical
|
|
||||||
created_at: 2008-07-24 14:11:35
|
|
||||||
title: "iPhone gripes: Reminders"
|
|
||||||
post_id: 237
|
|
||||||
tags: []
|
|
||||||
|
|
||||||
categories:
|
|
||||||
- iPhone
|
|
||||||
status: draft
|
|
|
@ -4,7 +4,7 @@ permalink: http://www.wezm.net/?p=100
|
||||||
kind: draft
|
kind: draft
|
||||||
is_hidden: true
|
is_hidden: true
|
||||||
section: uncategorized
|
section: uncategorized
|
||||||
created_at: 0000-00-00 00:00:00
|
created_at: 2012-01-01 00:00:00
|
||||||
title: Perl Worst Practices
|
title: Perl Worst Practices
|
||||||
post_id: 100
|
post_id: 100
|
||||||
tags: []
|
tags: []
|
||||||
|
|
|
@ -54,13 +54,17 @@ what I'm most interested in.
|
||||||
<figure>
|
<figure>
|
||||||
<a href="/images/2010/09/_IM_9078-9080.jpg" rel="prettyPhoto[weather]"><img src="/images/2010/09/_IM_9078-9080-small.jpg" width="266" height="400" alt="The Finished Installation" /></a>
|
<a href="/images/2010/09/_IM_9078-9080.jpg" rel="prettyPhoto[weather]"><img src="/images/2010/09/_IM_9078-9080-small.jpg" width="266" height="400" alt="The Finished Installation" /></a>
|
||||||
<figcaption>The Finished Installation</figcaption>
|
<figcaption>The Finished Installation</figcaption>
|
||||||
<figure>
|
</figure>
|
||||||
|
|
||||||
To log and upload the weather readings to [http://weather.wezm.net/][weather]
|
To log and upload the weather readings to [http://weather.wezm.net/][weather]
|
||||||
I'm using the [wview][wview] weather station software. wview is running on the
|
I'm using the [wview][wview] weather station software. wview is running on the
|
||||||
Mac mini connected to our TV. The site layout is pretty basic so I hope to come
|
Mac mini connected to our TV. The site layout is pretty basic so I hope to come
|
||||||
up with a cleaner design in the coming weeks.
|
up with a cleaner design in the coming weeks.
|
||||||
|
|
||||||
|
**Update:** I built a custom logging and charting solution. See the post,
|
||||||
|
[Weather Station Software][software].
|
||||||
|
|
||||||
|
[software]: /technical/2010/09/weather-station-software/
|
||||||
[WS2355]: http://www.lacrossetechnology.com.au/shop2/product_info.php?cPath=21&products_id=93
|
[WS2355]: http://www.lacrossetechnology.com.au/shop2/product_info.php?cPath=21&products_id=93
|
||||||
[wview]: http://www.wviewweather.com/
|
[wview]: http://www.wviewweather.com/
|
||||||
[weather]: http://weather.wezm.net/
|
[weather]: http://weather.wezm.net/
|
||||||
|
|
39
content/personal/2012/01/a-photo-a-day-in-2012.html
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
This year I've decided to have a go at publishing a photo every day
|
||||||
|
of the year. I'm not the first to do this, its also known by the name
|
||||||
|
[Project 365][project365]. I'm publishing my photos to the [2012 set on
|
||||||
|
Flickr][set]. The first week whilst I was still on Christmas holidays was
|
||||||
|
pretty easy. Although I am missing a photo for Jan 2 as the photo I took
|
||||||
|
got deleted whilst trying to restore my iPhone that got drowned in a river.
|
||||||
|
Anyway after returning to work its been harder to find things to take
|
||||||
|
pictures of but I haven't missed a day yet.
|
||||||
|
|
||||||
|
[set]: http://www.flickr.com/photos/wezm/sets/72157628659470185/
|
||||||
|
[project365]: http://content.photojojo.com/tutorials/project-365-take-a-photo-a-day/
|
||||||
|
|
||||||
|
Some of my favourites from the first 3 weeks are:
|
||||||
|
|
||||||
|
<figure>
|
||||||
|
<a href="http://www.flickr.com/photos/wezm/6657534021/"><img src="http://farm8.staticflickr.com/7012/6657534021_4f817ed181.jpg" alt="Eastern Spinebill" /></a>
|
||||||
|
<figcaption>Jan 8 — Eastern Spinebill</figcaption>
|
||||||
|
</figure>
|
||||||
|
|
||||||
|
<figure>
|
||||||
|
<a href="http://www.flickr.com/photos/wezm/6689132165/"><img src="http://farm8.staticflickr.com/7165/6689132165_a804d761de.jpg" alt="CityLink" /></a>
|
||||||
|
<figcaption>Jan 13 — CityLink</figcaption>
|
||||||
|
</figure>
|
||||||
|
|
||||||
|
<figure>
|
||||||
|
<a href="http://www.flickr.com/photos/wezm/6697126903/"><img src="http://farm8.staticflickr.com/7022/6697126903_7edb0f16f4.jpg" alt="Sulphur Crested Cockatoo" /></a>
|
||||||
|
<figcaption>Jan 15 — Sulphur Crested Cockatoo</figcaption>
|
||||||
|
</figure>
|
||||||
|
|
||||||
|
<figure>
|
||||||
|
<a href="http://www.flickr.com/photos/wezm/6719362425/"><img src="http://farm8.staticflickr.com/7160/6719362425_4ca8528510.jpg" alt="Belvedere — Intense" /></a>
|
||||||
|
<figcaption>Jan 18 — Belvedere – Intense</figcaption>
|
||||||
|
</figure>
|
||||||
|
|
||||||
|
<figure>
|
||||||
|
<a href="http://www.flickr.com/photos/wezm/6727700109/"><img src="http://farm8.staticflickr.com/7147/6727700109_2b71858bf7.jpg" alt="Macedon Primary School Plantation" /></a>
|
||||||
|
<figcaption>Jan 19 — Macedon Primary School Plantation</figcaption>
|
||||||
|
</figure>
|
||||||
|
|
11
content/personal/2012/01/a-photo-a-day-in-2012.yaml
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
---
|
||||||
|
title: A Photo a Day in 2012
|
||||||
|
extra: In 2012 I'm aiming to take and publish a photo every day.
|
||||||
|
kind: article
|
||||||
|
section: personal
|
||||||
|
created_at: 2012-01-21 17:18:00
|
||||||
|
keywords:
|
||||||
|
- photography
|
||||||
|
- "2012"
|
||||||
|
- project365
|
||||||
|
short_url: http://bit.ly/wKwmtl
|
|
@ -3,21 +3,31 @@ more noteworthy projects are listed below.
|
||||||
|
|
||||||
[github]: http://github.com/wezm
|
[github]: http://github.com/wezm
|
||||||
|
|
||||||
<!--
|
|
||||||
|
|
||||||
Monothumb
|
Monothumb
|
||||||
---------
|
---------
|
||||||
|
|
||||||
`monothumb` is the tool that generates the thumbnails on the [home page](/). It
|
[monothumb] is the tool that generates the thumbnails on the [home page](/). It
|
||||||
retrieves thumbnails of my [recent uploads to Flickr][flickr], converts them to
|
retrieves thumbnails of my [recent uploads to Flickr][flickr], converts them to
|
||||||
greyscale and then generates a single output image with both the colour and
|
greyscale and then generates a single output image with both the colour and
|
||||||
monochrome version of the thumbnail. There are two version of the tool. The
|
monochrome versions of the thumbnail. There are two version of the tool. The
|
||||||
original one, written in Objective-C that uses CoreImage and a second version
|
original one, written in Objective-C that uses CoreImage and a second version
|
||||||
written in Lua. The Lua one is the one currently in use.
|
written in Lua. The Lua one uses my [lua-imlib](#lua-imlib) fork.
|
||||||
|
|
||||||
[flickr]: http://www.flickr.com/photos/wezm/
|
[flickr]: http://www.flickr.com/photos/wezm/
|
||||||
|
[monothumb]: https://github.com/wezm/monothumb
|
||||||
|
|
||||||
-->
|
<a name="lua-imlib"></a>
|
||||||
|
lua-imlib2
|
||||||
|
----------
|
||||||
|
|
||||||
|
[lua-imlib2] is a fork of the published lua-imlib library with additional
|
||||||
|
functionality. This library allows image processing in Lua. Specifically I
|
||||||
|
added:
|
||||||
|
|
||||||
|
* Support for filters
|
||||||
|
* Image blending
|
||||||
|
|
||||||
|
[lua-imlib2]: https://github.com/wezm/lua-imlib2
|
||||||
|
|
||||||
node-genx
|
node-genx
|
||||||
---------
|
---------
|
||||||
|
|
|
@ -282,7 +282,7 @@ a
|
||||||
height: 75px
|
height: 75px
|
||||||
width: 75px
|
width: 75px
|
||||||
border: 1px solid #ccc
|
border: 1px solid #ccc
|
||||||
background: url(/images/photos.jpg) no-repeat 0 -75px
|
background: url(/images/photos.jpg?20120121) no-repeat 0 -75px
|
||||||
|
|
||||||
&:first-child
|
&:first-child
|
||||||
margin-left: 2em
|
margin-left: 2em
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
Here's tip for something I worked out today. WordPress blogs generally have an RSS feed available for the comments on a post. This is handy for when you want to see other comments posted without having to remember to check back. The problem is many <acronym title="WordPress">WP</acronym> themes don't provide a link to the feed. The solution is to add `/feed` to the URL of the post, so for this post the comment feed is at:
|
Here's tip for something I worked out today. WordPress blogs generally have an RSS feed available for the comments on a post. This is handy for when you want to see other comments posted without having to remember to check back. The problem is many <acronym title="WordPress">WP</acronym> themes don't provide a link to the feed. The solution is to add `/feed` to the URL of the post, so for this post the comment feed is at:
|
||||||
<a href="http://www.wezm.net/2008/07/02/comment-feeds-in-wordpress/feed">http://www.wezm.net/2008/07/02/comment-feeds-in-wordpress/feed</a>.
|
|
||||||
|
<u>http://www.wezm.net/2008/07/02/comment-feeds-in-wordpress/feed</u>
|
||||||
|
|
||||||
**Update 25 Mar 2010:** The example given will no longer work because I've moved this site off WordPress.
|
**Update 25 Mar 2010:** The example given will no longer work because I've moved this site off WordPress.
|
|
@ -16,7 +16,7 @@ functions for communicating with a LaCrosse WS-23xx weather station and a set
|
||||||
of tools. wview logged its observations to an SQLite database, which seemed
|
of tools. wview logged its observations to an SQLite database, which seemed
|
||||||
appropriate for this application. There were tools in Open2300 to log current
|
appropriate for this application. There were tools in Open2300 to log current
|
||||||
conditions to MySQL and PostgreSQL databases but not SQLite. So last weekend
|
conditions to MySQL and PostgreSQL databases but not SQLite. So last weekend
|
||||||
I spend some of the afternoon learning enough of the SQLite C API to add
|
I spent some of the afternoon learning enough of the SQLite C API to add
|
||||||
such a tool. The result is in my
|
such a tool. The result is in my
|
||||||
[git mirror of the Open2300 SVN repo][open2300git]. Once the SQLite tool is
|
[git mirror of the Open2300 SVN repo][open2300git]. Once the SQLite tool is
|
||||||
tidied up a bit more I'll submit it upstream.
|
tidied up a bit more I'll submit it upstream.
|
||||||
|
@ -29,9 +29,10 @@ that wview was previously generated. To do this I wrote a small
|
||||||
[Lua tool][weather-tools]
|
[Lua tool][weather-tools]
|
||||||
to query the database and output the results to a [JSON][json] file. The
|
to query the database and output the results to a [JSON][json] file. The
|
||||||
JSON is used on the new [weather page][weather], which is largely populated
|
JSON is used on the new [weather page][weather], which is largely populated
|
||||||
by Javascript and uses the [flot charting library][flot] to graph the
|
by Javascript and uses the [flot][flot] and [dygraphs][dygraphs] libraries
|
||||||
temperature history.
|
visualise the weather data.
|
||||||
|
|
||||||
[json]: http://www.json.org/
|
[json]: http://www.json.org/
|
||||||
[flot]: http://code.google.com/p/flot/
|
[flot]: http://code.google.com/p/flot/
|
||||||
|
[dygraphs]: http://dygraphs.com/
|
||||||
[weather-tools]: http://github.com/wezm/weather-tools
|
[weather-tools]: http://github.com/wezm/weather-tools
|
49
content/technical/2011/08/monochrome-thumbnails.html
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
Ever since this version of my site went live I've been meaning to
|
||||||
|
post about the generation of the monochrome thumbnails on the [front page](/).
|
||||||
|
When I was building the site I wanted to include recent items
|
||||||
|
from my Flickr photostream. However with the predominantly monochrome
|
||||||
|
design I didn't like the look of all the colour they added. So I looked into
|
||||||
|
having monochrome versions of the thumbnails shown.
|
||||||
|
|
||||||
|
The first thing I investigated was Javascript image processing libraries. The
|
||||||
|
only main contender in that space was [Pixastic]. It worked but its cross browser
|
||||||
|
support wasn't great at the time. So I moved on to writing a tool that I
|
||||||
|
could run locally.
|
||||||
|
|
||||||
|
[Pixastic]: http://pixastic.com/
|
||||||
|
|
||||||
|
I decided the tool should generate a single image with
|
||||||
|
both the colour and monochrome versions in it (a technique known as spriting).
|
||||||
|
Using a single image means only one HTTP request instead of forty. Being a
|
||||||
|
programmer with an interest in Cocoa programming I created a small command line
|
||||||
|
tool that used the Flickr API to get the details of the last twenty images in
|
||||||
|
my photostream, fetch them and then use Core Image to convert them to
|
||||||
|
monochrome, add both the colour and monochrome versions to the output image and
|
||||||
|
finally save the result.
|
||||||
|
|
||||||
|
This worked great, however when I stopped hosting my site on my Mac I thought I
|
||||||
|
would need to run the process periodically on my Linux server, which ruled out
|
||||||
|
Core Image. I took this as another opportunity to learn something new and
|
||||||
|
rewrote it in Lua using imlib2 bindings. I had to make some additions to the
|
||||||
|
imlib bindings, which are [published on GitHub][luaimlib].
|
||||||
|
|
||||||
|
[luaimlib]: https://github.com/wezm/lua-imlib2
|
||||||
|
|
||||||
|
I used the Lua version for some time but never bothered to set it up
|
||||||
|
on the server. I wasn't uploading photos all that frequently and it
|
||||||
|
was simple enough to run locally and rsync the result. I've recently
|
||||||
|
switched back to the Mac version as it was simpler to get up and running
|
||||||
|
on my new laptop.
|
||||||
|
|
||||||
|
The [code is on GitHub][code] if anyone wants to do something similar. The
|
||||||
|
Cocoa version is on the master branch, the Lua version is on the
|
||||||
|
[lua branch][lua-branch].
|
||||||
|
|
||||||
|
[code]: https://github.com/wezm/monothumb
|
||||||
|
[lua-branch]: https://github.com/wezm/monothumb/tree/lua
|
||||||
|
|
||||||
|
The current version of the processed thumbnails is shown below.
|
||||||
|
|
||||||
|
<div style="overflow-x: auto; overflow-y: hidden;">
|
||||||
|
<img src="/images/photos.jpg" />
|
||||||
|
</div>
|
13
content/technical/2011/08/monochrome-thumbnails.yaml
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
---
|
||||||
|
title: Monochrome Thumbnails
|
||||||
|
extra: Generating monochrome thumbnails with a color rollover from my Flickr feed
|
||||||
|
kind: article
|
||||||
|
section: technical
|
||||||
|
created_at: 2011-08-27 18:54:00
|
||||||
|
keywords:
|
||||||
|
- image
|
||||||
|
- processing
|
||||||
|
- lua
|
||||||
|
- core
|
||||||
|
- monochrome
|
||||||
|
short_url: http://bit.ly/omIs0U
|
|
@ -0,0 +1,29 @@
|
||||||
|
Xcode has a bad habit of adding trailing whitespace to code, which is a pet
|
||||||
|
peeve of mine. It introduces irrelevant changes into diffs and is particularly
|
||||||
|
glaring when commiting code with [GitX], which highlights it in red. In [TextMate]
|
||||||
|
and now [Vico] I have bound the strip trailing whitespace in current document
|
||||||
|
action to ⌃⌥⌘S (control-option-command-s). This makes it quick and easy.
|
||||||
|
Xcode makes adding these types of actions a bit harder but I came up with a
|
||||||
|
solution that uses the Behaviours functionality in Xcode 4. This is how I did
|
||||||
|
it:
|
||||||
|
|
||||||
|
[GitX]: http://gitx.frim.nl/
|
||||||
|
[Vico]: http://www.vicoapp.com/
|
||||||
|
[TextMate]: http://macromates.com/
|
||||||
|
|
||||||
|
Create a shell script that invokes `sed` on each git tracked file that is
|
||||||
|
modified. Since Xcode doesn't tell the script what the current file was and
|
||||||
|
I didn't want to run sed over every file every time, processing tracked files
|
||||||
|
with modifications was the best solution I could come up with. Note that the
|
||||||
|
script also only prcocesses `.m` and `.h` files. I have my copy of the script
|
||||||
|
in `~/Documents/strip.sh`, be sure to give it the execute permission.
|
||||||
|
|
||||||
|
<script src="https://gist.github.com/1175182.js?file=strip.sh"></script>
|
||||||
|
|
||||||
|
Next you need to add a behaviour to Xcode. Go to the Xcode preferences and
|
||||||
|
click the Behaviours section, then click the + button. Name the behaviour and
|
||||||
|
give it a keyboard shortcut. In the right pane check Run and choose the script
|
||||||
|
you saved above. That's it. Now you can kill off that nasty whitespace with
|
||||||
|
ease.
|
||||||
|
|
||||||
|
<a href="/images/2011/08/xcode-behaviours-preferences.png" rel="prettyPhoto[xcode]"><img src="/images/2011/08/xcode-behaviours-preferences-small.png" width="600" height="423" alt="Xcode 4 Behaviours Preferences" /></a>
|
|
@ -0,0 +1,16 @@
|
||||||
|
---
|
||||||
|
title: Strip Trailing Whitespace in Xcode 4
|
||||||
|
extra: How to create a behaviour in Xcode 4 to strip trailing whitespace from all git tracked files with changes.
|
||||||
|
kind: article
|
||||||
|
section: technical
|
||||||
|
created_at: 2011-08-27 19:36:00
|
||||||
|
keywords:
|
||||||
|
- xcode
|
||||||
|
- strip
|
||||||
|
- trailing
|
||||||
|
- whitespace
|
||||||
|
- text
|
||||||
|
- editing
|
||||||
|
- programming
|
||||||
|
- apple
|
||||||
|
short_url: http://bit.ly/nGeJrK
|
54
content/technical/2011/09/custom-search-engine-safari.html
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
In my ongoing efforts to distance myself from Google I started using
|
||||||
|
[DuckDuckGo][duck] as my default search engine. I tried the DDG Safari
|
||||||
|
extension but didn't really like it, especially
|
||||||
|
since it needed to add an entire new toolbar to the browser. Other
|
||||||
|
suggestions for adding DDG to Safari involved [hacking the binary][hack]
|
||||||
|
or other extensions, which I wasn't interested in.
|
||||||
|
|
||||||
|
[duck]: http://duckduckgo.com/
|
||||||
|
[hack]: http://hints.macworld.com/article.php?story=20030514035516436
|
||||||
|
|
||||||
|
**Update:** There an easier way to achive what I describe below: Just
|
||||||
|
add a hosts file entry for search.yahoo.com that points at DuckDuckGo's
|
||||||
|
IP address and set you search engine to Yahoo! in Safari. [See DuckDuckGo
|
||||||
|
for the full instructions][hosts].
|
||||||
|
|
||||||
|
[hosts]: http://help.duckduckgo.com/customer/portal/articles/255650
|
||||||
|
|
||||||
|
My solution to the problem was to hijack the Bing option in the default
|
||||||
|
search box for use with DDG. **Note:** This solution assumes you will
|
||||||
|
never want to go to the `www.bing.com` domain, not a problem for me. The
|
||||||
|
steps to implement it are:
|
||||||
|
|
||||||
|
Add an entry for `www.bing.com` to `/etc/hosts` that points the domain to
|
||||||
|
your local machine:
|
||||||
|
|
||||||
|
127.0.0.1 www.bing.com
|
||||||
|
|
||||||
|
Next configure an Apache virtual machine to respond to the `www.bing.com`
|
||||||
|
domain and redirect the request to Duck Duck Go (or your search engine
|
||||||
|
of choice). This works because DDG accepts the search query in the same
|
||||||
|
query string parameter, `q`, as Bing and ignores the other Bing related
|
||||||
|
params.
|
||||||
|
|
||||||
|
`/etc/apache2/extra/httpd-vhosts.conf`:
|
||||||
|
|
||||||
|
<VirtualHost *:80>
|
||||||
|
ServerName www.bing.com
|
||||||
|
RewriteEngine On
|
||||||
|
RewriteRule ^/search(.*)$ http://duckduckgo.com/$1 [redirect,last]
|
||||||
|
</VirtualHost>
|
||||||
|
|
||||||
|
For this to work you will need to have "Web Sharing" enabled in the Sharing
|
||||||
|
preferences pane and have the the following line included in
|
||||||
|
`/etc/apache2/httpd.conf`:
|
||||||
|
|
||||||
|
Include /private/etc/apache2/extra/httpd-vhosts.conf
|
||||||
|
|
||||||
|
Restart Apache (`sudo apachectl graceful`) and set your search engine
|
||||||
|
to Bing in Safari. Do a search and you should end up at the DDG
|
||||||
|
results. One of the neat features of DDG is its [!bang syntax][bang],
|
||||||
|
which allows you to search to 100s of sites directly. One of which is
|
||||||
|
`!g` for those times when you need to fall back on Google.
|
||||||
|
|
||||||
|
[bang]: http://duckduckgo.com/bang.html
|
15
content/technical/2011/09/custom-search-engine-safari.yaml
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
---
|
||||||
|
title: Add a Custom Search Engine to Safari
|
||||||
|
extra: How to add a custom search engine to Safari without nasty hacks or input managers.
|
||||||
|
kind: article
|
||||||
|
section: technical
|
||||||
|
created_at: 2011-09-24 15:34:00
|
||||||
|
keywords:
|
||||||
|
- safari
|
||||||
|
- custom
|
||||||
|
- search
|
||||||
|
- engine
|
||||||
|
- duckduckgo
|
||||||
|
- google
|
||||||
|
- apache
|
||||||
|
short_url: http://bit.ly/rj1slK
|
162
content/technical/2011/12/freebsd-zfs-powered-nas.html
Normal file
|
@ -0,0 +1,162 @@
|
||||||
|
## Summary
|
||||||
|
|
||||||
|
Here's the tl;dr version: I sold my Mac Pro to fund building a home
|
||||||
|
NAS. The result is a HP MicroServer with 4Gb RAM and 3 × 2Tb hard
|
||||||
|
drives running FreeBSD from the system drive and a ZFS pool across the
|
||||||
|
three 2Tb drives. Total cost: AU$731.67.
|
||||||
|
|
||||||
|
## Rationale
|
||||||
|
|
||||||
|
Recently the Time Machine drive in my Mac Pro started to randomly
|
||||||
|
disappear and Mac OS X would say that I had removed it improperly,
|
||||||
|
which was not true given it was an internal drive still inside the
|
||||||
|
machine.
|
||||||
|
|
||||||
|
I've seen this behaviour before and in that case it resulted in the drive
|
||||||
|
being replaced due to its inability to complete a short S.M.A.R.T.
|
||||||
|
scan. This drive (also a Samsung) was suffering a similar problem except
|
||||||
|
that initiating the S.M.A.R.T. scan would actually cause it to disappear
|
||||||
|
from the SATA bus. A check on the Samsung site showed that the drive was
|
||||||
|
out of warranty so I was up for a replacement.
|
||||||
|
|
||||||
|
The Mac Pro wasn't getting used for much since I got a i7 powered Mac
|
||||||
|
Book Pro. Its main duties involved storing my iTunes library, Aperture
|
||||||
|
library and running my weather logger. It wasn't exactly a very energy
|
||||||
|
efficient machine to run all the time. It would in fact keep the study
|
||||||
|
warm overnight when the door was closed during winter.
|
||||||
|
|
||||||
|
There was also a problem with replacing the failing drive: I couldn't afford
|
||||||
|
to do so. So I decided to move the weather logging to my [ALIX board][alix]
|
||||||
|
and sell the Mac Pro to fund building a home NAS. I was able to sell the
|
||||||
|
Mac Pro very quickly on eBay for $1500 but gave myself a budget of $1000 for
|
||||||
|
the NAS. I wanted the NAS to have reliable, redundant storage, which for me
|
||||||
|
meant [ZFS]. This implied the new machine would need to run one of [Solaris],
|
||||||
|
[illumos], [FreeBSD], [FreeNAS] or [SmartOS]. The requirement to run one of
|
||||||
|
these OS's ruled out an off the shelf NAS appliance.
|
||||||
|
|
||||||
|
[ZFS]: http://www.opensolaris.org/os/community/zfs/
|
||||||
|
[alix]: /technical/2011/12/openwrt-on-alix/
|
||||||
|
[Solaris]: http://oracle.com/solaris
|
||||||
|
[illumos]: https://www.illumos.org/
|
||||||
|
[FreeBSD]: http://www.FreeBSD.org/
|
||||||
|
[SmartOS]: http://smartos.org/
|
||||||
|
[FreeNAS]: https://www.illumos.org/
|
||||||
|
|
||||||
|
I did a lot of research into different ways to build the machine and
|
||||||
|
tried out all the OS options in virtual machines. I considered using
|
||||||
|
basic PC hardware, MiniITX, HP MicroServer, etc. Each had its own
|
||||||
|
pros and cons. The basic PC approach was possibly the cheapest but it
|
||||||
|
was the largest. MiniITX was more expensive and choice of multi hard
|
||||||
|
drive bay cases were limited. I ended up settling on the [HP Proliant
|
||||||
|
MicroServer][microserver] running FreeBSD.
|
||||||
|
|
||||||
|
[microserver]: http://h10010.www1.hp.com/wwpc/hk/en/sm/WF06b/15351-15351-4237916-4237917-4237917-4248009-5163345.html
|
||||||
|
|
||||||
|
<script type="text/javascript" charset="utf-8">
|
||||||
|
$(function () {
|
||||||
|
var alt = $(document.createElement('img')).attr('src', '/images/2012/01/_MG_0581.jpg');
|
||||||
|
$('#inside-outside-view').toggle(function() {
|
||||||
|
$(this).attr('src', alt.attr('src'))
|
||||||
|
}, function() {
|
||||||
|
$(this).attr('src', '/images/2012/01/_MG_0582.jpg')
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<figure>
|
||||||
|
<img id="inside-outside-view" src="/images/2012/01/_MG_0582.jpg" width="600" height="600" alt="Inside/outside view of HP MicroServer" />
|
||||||
|
<figcaption>The end result. Click/tap to toggle inside view.</figcaption>
|
||||||
|
</figure>
|
||||||
|
|
||||||
|
<figure>
|
||||||
|
<img src="/images/2012/01/_MG_0583.jpg" width="600" height="600" alt="Fron of MicroServer with CD for size comparison" />
|
||||||
|
<figcaption>CD for size comparison.</figcaption>
|
||||||
|
</figure>
|
||||||
|
|
||||||
|
<figure>
|
||||||
|
<img src="/images/2012/01/_MG_0584.jpg" width="600" height="600" alt="Oblique view of HP MicroServer" />
|
||||||
|
<figcaption>Oblique view (excuse the finger prints).</figcaption>
|
||||||
|
</figure>
|
||||||
|
|
||||||
|
|
||||||
|
## The Build
|
||||||
|
|
||||||
|
The MicroServer is a neat little unit. It uses a low power dual core AMD
|
||||||
|
Turion II CPU and comes with 2Gb ECC RAM and a 250Gb HD. I has 4 non-hot
|
||||||
|
swappable hard drive bays all packaged up in a squat little box. I ordered
|
||||||
|
mine with an extra 2Gb or RAM as ZFS likes to have plenty of RAM available
|
||||||
|
to run well.
|
||||||
|
|
||||||
|
During my research hard drive prices sky rocketed due to floods
|
||||||
|
in Thailand, however I was able to get some at pre-flood prices from
|
||||||
|
[ht.com.au][ht]. They have since put the price up ~$40 and placed order
|
||||||
|
limits on them.
|
||||||
|
|
||||||
|
For the drives I chose 2Tb Seagate Barracuda Green's. They feature SATA 3
|
||||||
|
and a 64Mb cache and run at an atypical 5900RPM. These drives seemed to be
|
||||||
|
a good balance across energy efficiency, noise, performance and price.
|
||||||
|
|
||||||
|
[ht]: http://ht.com.au/
|
||||||
|
|
||||||
|
The final parts list ended up being rather diminutive:
|
||||||
|
|
||||||
|
* 1 × [HP MicroServer][microserver] (658553-371) + 2Gb extra RAM $336.82
|
||||||
|
* 3 × [2Tb Seagate Barracuda Green Hard Drives][hard-drives] $394.85
|
||||||
|
|
||||||
|
[hard-drives]: http://www.ht.com.au/cart/1/part/V0531-Seagate-Barracuda-Green-ST2000DL003-hard-drive-2-TB-SATA-600/detail.hts
|
||||||
|
|
||||||
|
The total cost ended up being $731.67, healthily under budget.
|
||||||
|
|
||||||
|
<figure>
|
||||||
|
<img src="/images/2012/01/IMG_0097.jpg" width="600" height="600" alt="Installing RAM into HP MicroServer" />
|
||||||
|
<figcaption>Installing the extra RAM.</figcaption>
|
||||||
|
</figure>
|
||||||
|
|
||||||
|
<figure>
|
||||||
|
<img src="/images/2012/01/IMG_0098.jpg" width="600" height="600" alt="Installing hard drives into HP MicroServer" />
|
||||||
|
<figcaption>Installing the hard drives.</figcaption>
|
||||||
|
</figure>
|
||||||
|
|
||||||
|
## Software
|
||||||
|
|
||||||
|
Installing FreeBSD and setting up the ZFS pool was very
|
||||||
|
straightforward. I'm running the drives in a RAIDZ configuration,
|
||||||
|
giving 3.6Tb of usable storage. I currently have two ZFS file systems
|
||||||
|
on that. One in a normal configuration and the other for photos with
|
||||||
|
`copies=2` set.
|
||||||
|
|
||||||
|
The system all ran well for a few days however on the forth day one of
|
||||||
|
the brand new drives failed and started making a terrible clicking, beeping
|
||||||
|
noise. Fortunately HT replaced it very promptly and the replacement has
|
||||||
|
been running fine since. During the time the failed drive was out for
|
||||||
|
replacement the ZFS pool continued to run fine in its degraded state, with
|
||||||
|
no data loss. Once the new drive was installed it was a simple matter of
|
||||||
|
issuing `zfs replace ada1` and it began the process of resilvering the data
|
||||||
|
onto the new drive and it has been running incident free since.
|
||||||
|
|
||||||
|
$ zpool status
|
||||||
|
pool: storage
|
||||||
|
state: ONLINE
|
||||||
|
scan: resilvered 1.07T in 9h32m with 0 errors on Tue Nov 29 07:13:29 2011
|
||||||
|
config:
|
||||||
|
|
||||||
|
NAME STATE READ WRITE CKSUM
|
||||||
|
storage ONLINE 0 0 0
|
||||||
|
raidz1-0 ONLINE 0 0 0
|
||||||
|
ada1 ONLINE 0 0 0
|
||||||
|
ada2 ONLINE 0 0 0
|
||||||
|
ada3 ONLINE 0 0 0
|
||||||
|
|
||||||
|
errors: No known data errors
|
||||||
|
|
||||||
|
After setting up the OS and file systems the only other thing I
|
||||||
|
needed to so was make the storage available to other machines on the
|
||||||
|
network. Since my house is all Macs I built [netatalk] via the FreeBSD
|
||||||
|
ports collection to make the storage available via <abbr title="Apple
|
||||||
|
Filing Protocol">AFP</abbr>.
|
||||||
|
|
||||||
|
[netatalk]: http://netatalk.sourceforge.net/
|
||||||
|
|
||||||
|
With that done it's the sever shows up in the Finder via Bonjour and
|
||||||
|
copying/accessing data is dead simple.
|
||||||
|
|
14
content/technical/2011/12/freebsd-zfs-powered-nas.yaml
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
---
|
||||||
|
title: Home NAS Powered by FreeBSD and ZFS
|
||||||
|
extra: Building a home NAS with a HP MicroServer running FreeBSD and ZFS.
|
||||||
|
kind: article
|
||||||
|
section: technical
|
||||||
|
created_at: 2012-01-21 17:08:00
|
||||||
|
keywords:
|
||||||
|
- zfs
|
||||||
|
- freebsd
|
||||||
|
- hp
|
||||||
|
- proliant
|
||||||
|
- microserver
|
||||||
|
- nas
|
||||||
|
short_url: http://bit.ly/xz4hnt
|
|
@ -0,0 +1,46 @@
|
||||||
|
When it comes time to present errors or other messages in iOS with
|
||||||
|
[UIAlertView] it is immediately obvious that a more convenient interface
|
||||||
|
would involve the use of blocks. A [search on GitHub][github-search]
|
||||||
|
shows just about every iOS developer has had the same thought and had a crack at it.
|
||||||
|
|
||||||
|
[UIAlertView]: http://developer.apple.com/library/ios/#documentation/uikit/reference/UIAlertView_Class/UIAlertView/UIAlertView.html
|
||||||
|
[github-search]: https://github.com/search?type=Repositories&language=&q=uialertview&repo=&langOverride=&x=14&y=17&start_value=1
|
||||||
|
|
||||||
|
After reviewing the better options (I.e. those that actually had a
|
||||||
|
README with more than a few lines of content) on GitHub it appeared
|
||||||
|
that one of the challenges was how to handle memory. This stems from
|
||||||
|
the wrapper becoming the delegate for the UIAlertView but not having a
|
||||||
|
strong reference from the caller. I saw various solutions to this, most
|
||||||
|
involving adding a extra retain call to keep everything around until the
|
||||||
|
delegate methods were called.
|
||||||
|
|
||||||
|
Since my project is using ARC I looked for a solution that
|
||||||
|
didn't involve marking the wrapper file as non-ARC and
|
||||||
|
invoking `retain`. The solution I came up with was to use
|
||||||
|
[`objc_setAssociatedObject`][set-object]. This Objective-C runtime
|
||||||
|
function allows one object to be associated with another using various
|
||||||
|
memory management strategies. I used this to associate the UIAlertView
|
||||||
|
blocks based wrapper with the UIAlertView.
|
||||||
|
|
||||||
|
[set-object]: http://developer.apple.com/library/ios/#documentation/Cocoa/Conceptual/ObjectiveC/Chapters/ocAssociativeReferences.html
|
||||||
|
|
||||||
|
In the `init` method the wrapper instance is associated with its UIAlertView:
|
||||||
|
|
||||||
|
objc_setAssociatedObject(alertView, _cmd, self, OBJC_ASSOCIATION_RETAIN);
|
||||||
|
|
||||||
|
Note that I'm using the implicit second argument to the method, its
|
||||||
|
selector, `_cmd` as the key for the associated object. This was
|
||||||
|
suggested in a [tweet by Bill Bumgarner][bbum].
|
||||||
|
|
||||||
|
[bbum]: http://twitter.com/bbum/status/3609098005
|
||||||
|
|
||||||
|
Then in `alertView:didDismissWithButtonIndex:`, the association
|
||||||
|
is removed, `dealloc` of the wrapper called as a result and the
|
||||||
|
`UIAlertView` also released.
|
||||||
|
|
||||||
|
SEL key = @selector(initWithTitle:message:);
|
||||||
|
objc_setAssociatedObject(self.alertView, key, nil, OBJC_ASSOCIATION_RETAIN);
|
||||||
|
|
||||||
|
The full [MIT licensed code][gist] is available as a [gist on GitHub][gist].
|
||||||
|
|
||||||
|
[gist]: https://gist.github.com/1392611
|
|
@ -0,0 +1,14 @@
|
||||||
|
---
|
||||||
|
title: Fun With objc_setAssociatedObject and UIAlertView
|
||||||
|
extra: Using objc_setAssociatedObject in a blocks based UIAlertView wrapper.
|
||||||
|
kind: article
|
||||||
|
section: technical
|
||||||
|
created_at: 2011-12-11 17:26:00
|
||||||
|
keywords:
|
||||||
|
- ios
|
||||||
|
- uialertview
|
||||||
|
- blocks
|
||||||
|
- objc_setAssociatedObject
|
||||||
|
- arc
|
||||||
|
- objective-c
|
||||||
|
short_url: http://bit.ly/u9Ys9v
|
|
@ -0,0 +1,61 @@
|
||||||
|
At work we're currently having an iOS app that I'm working on styled
|
||||||
|
by a designer. The second screen we were supplied was a pretty splash
|
||||||
|
screen with a big logo on it. We responded saying that we didn't want
|
||||||
|
to use the launch image like that. Our designer responded saying that
|
||||||
|
was fine but the majority of the clients nowadays require heavy emphases
|
||||||
|
on corporate branding therefore it was a standard practice to cater to
|
||||||
|
those requirements. It's a shame that this is what people are are asking
|
||||||
|
for since its is not the intended use of the launch image.
|
||||||
|
|
||||||
|
Justin Williams recently had the following clear-cut words to say on the
|
||||||
|
topic of splash screens in his [On Magazines and the iPad][carpeaqua]
|
||||||
|
article (emphasis from the article):
|
||||||
|
|
||||||
|
> Remember, kids. The first rule of mobile development is that *no one
|
||||||
|
> gives a fuck about your brand*. A splash screen with a giant logo
|
||||||
|
> is something that makes editors and marketing directors feel good,
|
||||||
|
> but to a user it just feels like a meaningless delay. You know that
|
||||||
|
> feeling of frustration you get each time there’s a 15-second preroll
|
||||||
|
> before a video on the web? That’s what a splash screen with logos and
|
||||||
|
> advertisements is.
|
||||||
|
|
||||||
|
[carpeaqua]: http://carpeaqua.com/2011/12/04/on-magazines-and-the-ipad/
|
||||||
|
|
||||||
|
The Apple [iOS Human Interface Guidelines][MobileHIG] include the
|
||||||
|
following suggestions:
|
||||||
|
|
||||||
|
> Avoid taking space away from the content people care about. For
|
||||||
|
> example, displaying a second, persistent bar at the top of the screen
|
||||||
|
> that does nothing but display branding assets means that there’s less
|
||||||
|
> room for content. Consider other, less intrusive ways to display
|
||||||
|
> pervasive branding, such as subtly customizing the background of a
|
||||||
|
> screen.
|
||||||
|
|
||||||
|
> Display a launch image that closely resembles the first screen of the
|
||||||
|
> application. This practice decreases the perceived launch time of your
|
||||||
|
> application.
|
||||||
|
|
||||||
|
> Avoid displaying an About window or a splash screen. In general, try
|
||||||
|
> to avoid providing any type of startup experience that prevents people
|
||||||
|
> from using your application immediately.
|
||||||
|
|
||||||
|
> Supply a launch image to improve user experience.
|
||||||
|
>
|
||||||
|
> Avoid using your launch image as an opportunity to provide:
|
||||||
|
>
|
||||||
|
> * An "application entry experience," such as a splash screen
|
||||||
|
> * An About window
|
||||||
|
> * Branding elements, unless they are a static part of your
|
||||||
|
> application’s first screen
|
||||||
|
>
|
||||||
|
> Because users are likely to switch among applications frequently, you
|
||||||
|
> should make every effort to cut launch time to a minimum, and you
|
||||||
|
> should design a launch image that downplays the experience rather than
|
||||||
|
> drawing attention to it.
|
||||||
|
|
||||||
|
[MobileHIG]: http://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/MobileHIG/MobileHIG.pdf
|
||||||
|
|
||||||
|
The launch image is designed to make the perceived launch time of you app
|
||||||
|
feel faster by showing something resembling the interface that will be loaded
|
||||||
|
as quickly as possible. Displaying a logo does nothing but draw attention
|
||||||
|
to how quickly your app loads and adds nothing to the user's experience.
|
|
@ -0,0 +1,15 @@
|
||||||
|
---
|
||||||
|
title: The iOS Launch Image is Not a Splash Screen
|
||||||
|
extra: Reasons why the launch image in iOS apps is not intended to be a splash screen with your pretty logo on it.
|
||||||
|
kind: article
|
||||||
|
section: technical
|
||||||
|
created_at: 2011-12-08 07:29:00
|
||||||
|
keywords:
|
||||||
|
- ios
|
||||||
|
- iphone
|
||||||
|
- ipad
|
||||||
|
- splash
|
||||||
|
- screen
|
||||||
|
- launch
|
||||||
|
- image
|
||||||
|
short_url: http://bit.ly/uRHJqI
|
85
content/technical/2011/12/openwrt-on-alix.html
Normal file
|
@ -0,0 +1,85 @@
|
||||||
|
After ongoing issues with maintaining a reliable Internet connection at
|
||||||
|
home I decided to add a router box to the network in charge of assigning
|
||||||
|
IP addresses and sharing our Internet connection with the rest of the
|
||||||
|
network. I wanted something with at least two Ethernet ports so that
|
||||||
|
all Internet traffic would flow through the device and allow bandwidth
|
||||||
|
hogs to be identified at times when the connection appeared flooded.
|
||||||
|
|
||||||
|
After a bunch of research into appropriate hardware and software I
|
||||||
|
decided on a [PC Engines ALIX][alix] single board computer (alix2d13). The
|
||||||
|
ALIX is a small board about the size of a CD case with the following
|
||||||
|
features:
|
||||||
|
|
||||||
|
* 500Mhz AMD Geode (x86 compatible) CPU
|
||||||
|
* 256Mb RAM
|
||||||
|
* 2 × USB ports
|
||||||
|
* 3 × 10/100 Ethernet ports
|
||||||
|
* Mini-PCI socket (for WiFi if desired)
|
||||||
|
* RS-232 serial port
|
||||||
|
* CompactFlash socket
|
||||||
|
|
||||||
|
Along with the board I ordered one of [PC Engines cases][case]
|
||||||
|
(case1s2u) to go with it.
|
||||||
|
|
||||||
|
[alix]: http://www.pcengines.ch/alix2d13.htm
|
||||||
|
[case]: http://www.pcengines.ch/case1d2u.htm
|
||||||
|
|
||||||
|
For the software I settled on [OpenWRT][openwrt]. I chose it for a number of
|
||||||
|
reasons:
|
||||||
|
|
||||||
|
* Good support for ALIX boards.
|
||||||
|
* Designed to run from Flash and read only file systems.
|
||||||
|
* Great binary package manager that allows additional software to be
|
||||||
|
installed.
|
||||||
|
* Lightweight [Lua] based Web UI available ([LuCI][luci]).
|
||||||
|
|
||||||
|
[openwrt]: https://openwrt.org/
|
||||||
|
[luci]: http://luci.subsignal.org/
|
||||||
|
[Lua]: http://www.lua.org/
|
||||||
|
|
||||||
|
After learning to use the excellent OpenWRT build system I was able to
|
||||||
|
build a custom CompactFlash image for the board to run. I also created a
|
||||||
|
package for my [weather logging software][weather-software] so that the
|
||||||
|
ALIX can do all my [weather station][weather] logging.
|
||||||
|
|
||||||
|
[weather]: /personal/2010/09/weather-station/
|
||||||
|
[weather-software]: /technical/2010/09/weather-station-software/
|
||||||
|
|
||||||
|
This setup has been extremely reliable. I've pushed all services on to
|
||||||
|
it that my ADSL modem and AirPort base station used to be responsible
|
||||||
|
for. Including maintaining the PPPoE connection to my ISP. I'd certainly
|
||||||
|
recommend a set up like this to anyone who is looking for a small
|
||||||
|
dedicated home router.
|
||||||
|
|
||||||
|
If you don't like the prospect of building your own custom OS image I'd
|
||||||
|
also highly recommend <tt>[m0n0wall]</tt>, which is a [FreeBSD] derived
|
||||||
|
router system. I ran this on the ALIX initially and it was very easy
|
||||||
|
to get up an running (write image to CF card, boot from card - default
|
||||||
|
settings worked fine but can be changed via a web UI) and very reliable.
|
||||||
|
|
||||||
|
[m0n0wall]: http://m0n0.ch/wall/
|
||||||
|
[FreeBSD]: http://www.freebsd.org/
|
||||||
|
|
||||||
|
<figure>
|
||||||
|
<img src="/images/2012/01/_MG_0562.jpg" width="600" height="258" alt="Front view" />
|
||||||
|
<figcaption>Front with three LEDs. The behaviour of the LEDs can
|
||||||
|
be customised in OpenWRT. I have the left one indication power and
|
||||||
|
the middle one indicating activity on the WAN port. The other one is
|
||||||
|
currently unused.</figcaption>
|
||||||
|
</figure>
|
||||||
|
|
||||||
|
<figure>
|
||||||
|
<img src="/images/2012/01/_MG_0569.jpg" width="600" height="600" alt="Top view with CD for size comparison" />
|
||||||
|
<figcaption>Top of case, showing size in comparison to a CD case.</figcaption>
|
||||||
|
</figure>
|
||||||
|
|
||||||
|
<figure>
|
||||||
|
<img src="/images/2012/01/_MG_0567.jpg" width="600" height="600" alt="alix2d13 board" />
|
||||||
|
<figcaption>The ALIX board itself with the following connected: WAN
|
||||||
|
and LAN Ethernet, 8Gb [MosKeyto USB flash drive][moskeyto],
|
||||||
|
weather station USB cable and 32Mb CF card that the system runs
|
||||||
|
off.</figcaption>
|
||||||
|
</figure>
|
||||||
|
|
||||||
|
[moskeyto]: http://www.lacie.com/au/products/product.htm?id=10425
|
||||||
|
|
16
content/technical/2011/12/openwrt-on-alix.yaml
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
---
|
||||||
|
title: Little Linux Router Box
|
||||||
|
extra: Solving my Internet connection issues with a PC Engines ALIX single board computer and OpenWRT.
|
||||||
|
kind: article
|
||||||
|
section: technical
|
||||||
|
created_at: 2012-01-21 15:33:00
|
||||||
|
keywords:
|
||||||
|
- alix
|
||||||
|
- embedded
|
||||||
|
- linux
|
||||||
|
- openwrt
|
||||||
|
- server
|
||||||
|
- appliance
|
||||||
|
- freebsd
|
||||||
|
- m0n0wall
|
||||||
|
short_url: http://bit.ly/y9ZEKZ
|
|
@ -26,7 +26,7 @@
|
||||||
<div class="rainfall week chart"></div>
|
<div class="rainfall week chart"></div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<small>Forecast icons by <a href="http://lavana.deviantart.com/art/Flat-Weather-Icons-32021664">LavAna</a></small>
|
<small>Forecast icons by <a href="http://lavana.deviantart.com/art/Flat-Weather-Icons-32021664">LavAna</a>. Data from my <a href="/personal/2010/09/weather-station/">weather station</a>.</small>
|
||||||
<script id="current-template" type="text/x-handlebars-template">
|
<script id="current-template" type="text/x-handlebars-template">
|
||||||
<div id="current">
|
<div id="current">
|
||||||
<figure class="forecast">
|
<figure class="forecast">
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<meta name="viewport" content="width=device-width" />
|
<meta name="viewport" content="width=device-width" />
|
||||||
<title><%=h [@item[:title], 'WezM.net'].compact.join(' - ') %></title>
|
<title><%=h [@item[:title], 'WezM.net by Wesley Moore'].compact.join(' - ') %></title>
|
||||||
<% if @item[:extra] %><meta name="description" content="<%=h @item[:extra] %>"><% end %>
|
<% if @item[:extra] %><meta name="description" content="<%=h @item[:extra] %>"><% end %>
|
||||||
<% if @item[:keywords] %><meta name="keywords" content="<%=h @item[:keywords].join(',') %>"><% end %>
|
<% if @item[:keywords] %><meta name="keywords" content="<%=h @item[:keywords].join(',') %>"><% end %>
|
||||||
<!--[if lt IE 9]>
|
<!--[if lt IE 9]>
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
<% post_date = WezM::Helpers.parse_post_date(@item) %>
|
<% post_date = WezM::Helpers.parse_post_date(@item) %>
|
||||||
|
<% short = @item[:short_url] %>
|
||||||
<div class="published">
|
<div class="published">
|
||||||
Published on
|
Published on
|
||||||
<abbr class="calender date" title="<%= post_date.iso8601 %>">
|
<abbr class="calender date" title="<%= post_date.iso8601 %>">
|
||||||
|
@ -11,7 +12,8 @@
|
||||||
<%= yield %>
|
<%= yield %>
|
||||||
<div id="respond">
|
<div id="respond">
|
||||||
<h2>Something to Add?</h2>
|
<h2>Something to Add?</h2>
|
||||||
<p>Contact me by email or Twitter if you have a comment, correction or just want to get in touch.</p>
|
<p>Contact me by email, App.net or Twitter if you have a comment, correction
|
||||||
|
or just want to get in touch.</p>
|
||||||
<ul class="inline">
|
<ul class="inline">
|
||||||
<li>
|
<li>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
|
@ -51,7 +53,9 @@
|
||||||
</script>
|
</script>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<% short = @item[:short_url] %>
|
<a href="https://alpha.app.net/intent/post?text=<%= URI.encode("#{@item[:title]} - #{short} @wezm") %>" target="_blank">Post on App.net</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
<a href="http://twitter.com/home?status=<%= URI.encode("#{@item[:title]} - #{short} @wezm") %>" target="_blank">Tweet</a>
|
<a href="http://twitter.com/home?status=<%= URI.encode("#{@item[:title]} - #{short} @wezm") %>" target="_blank">Tweet</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="short">Short URL: <a href="<%= short %>"><%= short %></a></li>
|
<li class="short">Short URL: <a href="<%= short %>"><%= short %></a></li>
|
||||||
|
|
|
@ -4,7 +4,7 @@ module WezM
|
||||||
module Helpers
|
module Helpers
|
||||||
|
|
||||||
def self.parse_post_date(article)
|
def self.parse_post_date(article)
|
||||||
Time.parse(article[:created_at])
|
article[:created_at]
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
BIN
output/images/2011/08/xcode-behaviours-preferences-small.png
Normal file
After Width: | Height: | Size: 145 KiB |
BIN
output/images/2011/08/xcode-behaviours-preferences.png
Normal file
After Width: | Height: | Size: 177 KiB |
BIN
output/images/2012/01/IMG_0097.jpg
Normal file
After Width: | Height: | Size: 142 KiB |
BIN
output/images/2012/01/IMG_0098.jpg
Normal file
After Width: | Height: | Size: 119 KiB |
BIN
output/images/2012/01/_MG_0562.jpg
Normal file
After Width: | Height: | Size: 34 KiB |
BIN
output/images/2012/01/_MG_0567.jpg
Normal file
After Width: | Height: | Size: 138 KiB |
BIN
output/images/2012/01/_MG_0569.jpg
Normal file
After Width: | Height: | Size: 80 KiB |
BIN
output/images/2012/01/_MG_0581.jpg
Normal file
After Width: | Height: | Size: 96 KiB |
BIN
output/images/2012/01/_MG_0582.jpg
Normal file
After Width: | Height: | Size: 76 KiB |
BIN
output/images/2012/01/_MG_0583.jpg
Normal file
After Width: | Height: | Size: 86 KiB |
BIN
output/images/2012/01/_MG_0584.jpg
Normal file
After Width: | Height: | Size: 65 KiB |
Before Width: | Height: | Size: 122 KiB After Width: | Height: | Size: 131 KiB |
|
@ -8,7 +8,7 @@ jQuery(function () {
|
||||||
var photo = $(obj);
|
var photo = $(obj);
|
||||||
var image = {
|
var image = {
|
||||||
href: photo.attr('url_z'),
|
href: photo.attr('url_z'),
|
||||||
src: '/images/photos.jpg',
|
src: '/images/photos.jpg?20120121',
|
||||||
alt: photo.attr('title')
|
alt: photo.attr('title')
|
||||||
};
|
};
|
||||||
var li = $(image_template(image));
|
var li = $(image_template(image));
|
||||||
|
@ -20,5 +20,5 @@ jQuery(function () {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Populate Flickr
|
// Populate Flickr
|
||||||
jQuery.get("/photos.xml", {}, populate_flickr);
|
jQuery.get("/photos.xml?20111208", {}, populate_flickr);
|
||||||
});
|
});
|
||||||
|
|
|
@ -39,8 +39,9 @@
|
||||||
].join('')
|
].join('')
|
||||||
}
|
}
|
||||||
|
|
||||||
function datetimeString(date) {
|
|
||||||
var months = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'];
|
var months = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'];
|
||||||
|
function datetimeString(date) {
|
||||||
|
if (!date) return '';
|
||||||
return [
|
return [
|
||||||
date.getDate(),
|
date.getDate(),
|
||||||
months[date.getMonth()],
|
months[date.getMonth()],
|
||||||
|
@ -49,6 +50,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
function timeString(date) {
|
function timeString(date) {
|
||||||
|
if (!date) return '';
|
||||||
return [
|
return [
|
||||||
padNumber(date.getHours()),
|
padNumber(date.getHours()),
|
||||||
padNumber(date.getMinutes())
|
padNumber(date.getMinutes())
|
||||||
|
@ -100,8 +102,13 @@
|
||||||
forecast: data.current.forecast
|
forecast: data.current.forecast
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (current.temperature === undefined) {
|
||||||
|
$('.loading').replaceWith($('<p>Unavailable</p>'));
|
||||||
|
}
|
||||||
|
else {
|
||||||
var current_div = currentTemplate(current);
|
var current_div = currentTemplate(current);
|
||||||
$('.loading').replaceWith(current_div)
|
$('.loading').replaceWith(current_div)
|
||||||
|
}
|
||||||
|
|
||||||
// Populate the extremes
|
// Populate the extremes
|
||||||
var extremes = [];
|
var extremes = [];
|
||||||
|
|