Latest Entries »

Fink

First heard “Yesterday Was Hard On All Of Us” on an episode of House. The guy is a genius. Really want to see him live.

Best Man Speech!

At the weekend I, along with my mate Tony had the honour of being Best Men at our friend Trev’s wedding to his wife Hannah. To say it has been stressful is an understatement (we’ve been tearing our hair out while the Groom’s been as calm as anything). The Stag appeared to be a success (it was one of the best weekends of my life, with a great circle of friends). One of the most stressful aspects of being a Best Man (in my case at least) was the speech. It was the part Tony and I were dreading the most, both writing and standing up to perform it. Other than a severe case of nerves (to the point where both of us were shaking throughout performing it), it seemed to be received well, and we even got a few laughs. Here it is in all it’s splendour.

Good afternoon ladies and gentlemen. Before we continue, we would like to point out to those who may be feeling the effects of the alcohol already that you are not seeing double and there are actually two best men standing here. For those of you who don’t know us I’m Tony…and I’m Tom and we are both good friends of Trev’s from senior school.

We’ve both been quite nervous in the lead up to this moment, in fact the last time either of us felt this worried we were travelling in Trev’s car and he started to skip through his collection of Drum & Bass anthems, if you can call them that. The problem was we’d both forgotten our ear plugs and Trev was in the mood to sing. Hopefully we won’t be hearing any of that later, but just in case…

<< PULL EAR PLUGS OUT OF OUR POCKETS >>

We’d like to say a big thank you to everyone that has made it here today; we know a lot of you have travelled a long way to be here, which just goes to show the lengths some people will go to, to get a free meal.

<< STARE AT OUR LOT >>

It’s our duty, on behalf of the bridesmaids Rachel, Emma and Rachel to thank Trevor for his kind words. We have to say they all look wonderful and have done a brilliant job helping Hannah, who looks amazing we’re sure you’ll agree, to get ready for her special day.

It’s always customary to give the Groom a bit of a roasting with an embarrassing story or two, but with Trev it’s near impossible. While on occasion there has been mayhem going on around him, it always seems the embarrassing stories being played out are to be written into someone else’s best man speech. While chaos reigns around him Trev will be in the background somewhere, happily continuing with whatever he is doing, nothing affecting or fazing him at all.

Trev’s more common traits are on the football pitch, where he has a turning circle that rivals a small ocean-liner, and he has the ability to annoy even the calmest of teammates by shooting from wherever he is on the pitch when he receives the ball. On the golf course he’s been known to make up his own rules and use buggies as off-road rally karts, and on the bowling lane he is only there to win, regardless of the opposition, even if he’s there on a first date and trying to impress a young lady. We think Hannah knows what we’re talking about…

<< TURN TO LOOK AT TREV AND HANNAH >>

Three strikes on your first three goes wasn’t it Trev? Was that before or after Hannah threw a ball into the next lane? And they say chivalry’s dead!

We know some things are frowned upon in a best man’s speech, especially the Groom’s lovelife, but such a history with international models was difficult to leave out. Trev’s first love had many attributes; Italian, petite, fine curves as well as rumoured to have been involved with a Formula 1 legend, to name a few. All good memories of Trev’s first car, his little yellow Fiat Seicento, Michael Schumacher sporting edition.

At this stage of the speech it’s usually tradition for the best man, or in this case men, to impart some words of advice to the Groom, but seeing as though he’s the one getting married and we’re both single, that doesn’t seem quite right somehow. But tradition is tradition, so we thought we’d keep it short and to the point…

<< TURN TO TREV AND IN SAY IN UNISON >>

Don’t mess it up!

In a couple of days’ time Trev and Hannah are off on their honeymoon – a road trip down the East Coast of America. When you think about it, a road trip is a pretty apt way to describe a marriage; there’ll be a few near misses, you’ll do some amazing things and see some amazing sights, but most importantly you’re having the time of your life with the one person you couldn’t imagine doing it without. So if we could ask you all to raise your glasses, we’d like to propose a toast, to Trev and Hannah.

Like Eating Glass

Me playing one of my favourite Bloc Party songs, “Like Eating Glass”. It was my first attempt so I hope you can forgive the couple of mistakes in there…I make no apologies for the singing voice, I’m aware it’s not great :)

One to Watch 2012 – Of Monsters and Men

This indie-folk-rock-pop group from Iceland have been making lots of waves on these shores recently. I heard the track “Little Talks” on Dev’s early morning show on BBC Radio 1 a month or two ago and have been in love with them ever since. They’ve been around for a while (“Little Talks” was officially released in August last year, but had been around since at least 2010) but have only gained notoriety more recently. An EP has been released, they’ve already sold out the Electric Ballroom next week and with the album due out on the 27th August the next month or so is going to be a big one for them.

Some Day Soon

After moving to Los Angeles and starting his new life originally as a Screenwriter, Alexi Murdoch became an overnight success with his track “Orange Sky” when it appeared in numerous TV shows and films, including “The OC” and Zach Braff’s “Garden State”, his debut album “Time Without Consequence” was a joy to behold, with the aforementioned “Orange Sky”, “Blue Mind” and “All My Days” being real stand-out tracks for myself. Everything seemed to go quiet for a while (Alexi doesn’t seem to do a lot of self-promotion, and keeps himself to himself), but after a few years the “difficult second” album appeared, and although slightly shorter than his debut, this only concentrated the quality of the record further.

I tried for years to get tickets to see him in my native England, some obstacle always standing in my way. Finally, in November last year, I got to see Alexi play at the Union Chapel in Islington, probably my favourite venue in the whole of London. He was exceptional. He played a lot of experimental stuff, but the stand out track was “Some Day Soon”, taken from the second LP.

I hope it isn’t too long before we hear from Mr Murdoch again, but until that time I’ll have to comfort myself with visiting YouTube once in a while to find little nuggets of gold, like the one below.

Been playing around with this for a while, it’s such a great song, from the long intro (you’ll have to listen to the album version to appreciate it) to the song itself, it never fails to put a smile on my face when I listen to it, and makes me immediately think of a gorgeous summer evening.

Anyway, here’s a quickly-rushed recording of me messing around with the different sections of the song, I’ll attempt it properly soon. Please ignore the singing too, I know I’m pants, I just had the sudden urge to wail along.

Pagination, Pagination, Pagination

For a recent project I’ve been working I needed an easy-to-use Pagination class but after a scour around I couldn’t find anything that would do the job in the way I wanted to (Zend’s came close, as I’ve used it before, but it’s not lightweight enough for this project). I decided to write my own one instead.

The constructor takes a minimum of two arguments – an array of the whole set of data to be paginated, and the page of results to display. Optional arguments that can also be passed include an array of data to be included in the query string for each navigation link (most likely the $_GET predefined variable), the number of results to display per-page and how many links to include in the navigation (this value doesn’t affect the First/Last, Previous/Next navigation links):

This class will most probably not be of use if you are trying to paginate more that 1000 or so rows of data to paginate as doing it this way is bad practice (if pulling the data from a database you should be selecting your subset there, much more efficient).

As ever, let me know your thoughts!

<?php
/**
 * Pagination Class
 *
 * Class that will take an array of data and split it into the subsection to be returned, based on the values passed
 */
 class Pagination {
	public $data; // Original Data
	public $query_data; // Data on current query string

	public $page; // Current page of results to display
	public $pages; // Pages to include, dependant upon $page_range value
	public $page_count; // Total Number of Pages
	public $row_count; // Number of rows passed to class in Constructor

	public $first_page; // Show first page link
	public $last_page; // Show last page link
	public $previous_page; // Show previous page link
	public $next_page; // Show next page link

	public $range_start; // The page number to start the range link at
	public $page_range; // Show number of page links to show
	public $query_string; // Query string to use for the links

	public $subsection_of_data;

	/**
	 * Contructor
	 * @param array An array of data to be paginated
	 * @param int Page of data to return as subsection
	 * @param array An array of key/value-paired data for the query string for the Pagination navigation
	 * @param int The number of results to show on one page
	 * @param int Number of pages to display in the Pagination Navigation (Excluding First/Last, Previous/Next links)
	 * @return boolean
	 */
	public function __construct($data, $page, $query_data = array(), $per_page = 25, $page_range = 5)
	{
		$this->data = $data;
		$this->query_data = $query_data;

		$this->subsection_of_data = array();

		$this->pages = array();
		$this->page = $page;
		$this->per_page = $per_page;
		$this->page_range = $page_range;

		$this->process_query_string();
		$this->process_number_of_rows();
		$this->process_page_count();

		$this->process_first_page();
		$this->process_last_page();
		$this->process_previous_page();
		$this->process_next_page();
		$this->process_page_range();

		$this->process_subsection_of_data();
	}

	/**
	 * Count total number of items
	 * @return void
	 */
	public function process_number_of_rows()
	{
		$this->row_count = count($this->data);
	}

	/**
	 * Count total number of pages on data based on $per_page variable
	 * @return void
	 */
	public function process_page_count()
	{
		$this->page_count = floor($this->row_count / $this->per_page) + ($this->row_count % $this->per_page > 0 ? 1 : 0); // Number of Pages in Total
	}

	/**
	 * Determining whether to include "First Page" link in navigation
	 * @return void
	 */
	public function process_first_page()
	{
		$this->first_page = false;

		if ($this->page > 1) :
			$this->first_page = 1;
		endif;
	}

	/**
	 * Determining whether to include "Last Page" link in navigation
	 * @return void
	 */
	public function process_last_page()
	{
		$this->last_page = false;

		if ($this->page < $this->page_count) :
			$this->last_page = $this->page_count;
		endif;
	}

	/**
	 * Determining whether to include "Previous Page" link in navigation
	 * @return void
	 */
	public function process_previous_page()
	{
		$this->previous_page = false;

		if ($this->page > 1) :
			$this->previous_page = $this->page - 1;
		endif;
	}

	/**
	 * Determining whether to include "Next Page" link in navigation
	 * @return void
	 */
	public function process_next_page()
	{
		$this->next_page = false;

		if ($this->page < $this->page_count) :
			$this->next_page = $this->page + 1;
		endif;
	}

	/**
	 * Determining what page links to include in "Page Range" navigation
	 * @return void
	 */
	public function process_page_range()
	{
		$this->range_split = floor(($this->page_range - 1) / 2);

		$this->range_start = $this->page - $this->range_split;

		if ($this->range_start < 1) :
			$this->range_start = 1;
		endif;

		$i = $this->range_start;

		while ($i < ($this->range_start + $this->page_range)) :
			if ($i > 0 && $i <= $this->page_count) :
				$this->pages[] = $i;
			endif;
			$i++;
		endwhile;
	}

	/**
	 * Process query string to use on navigation links (removing the currently selected page, if set)
	 * @return void
	 */
	public function process_query_string()
	{
		$query_data = $this->query_data;

		if (isset($query_data['page'])) {
			unset($query_data['page']);
		}

		$this->query_string = http_build_query($query_data);
	}

	/**
	 * Return set of data to display, based on Page Number and Per Page variable
	 * @return void
	 */
	public function process_subsection_of_data()
	{
		$this->subsection_of_data = $this->data;

		$offset = $this->per_page * ($this->page - 1);
		$limit = $this->per_page;

		$this->subsection_of_data = array_slice($this->data, $offset, $limit);
	}

	/**
	 * Render standard navigation (echoes immediately)
	 * @return void
	 */
	public function render()
	{
		if ($this->page_count > 0): ?>
        	<div class="pagination">
            <?php
			if ($this->page_count > 1): ?>
                <div class="navigation">
				<?php
                if ($this->first_page) : ?>
                    <span class="item"><a href="?<?php echo $this->query_string; ?>&page=<?php echo $this->first_page; ?>">First</a></span>
                <?php
                endif;

                if ($this->previous_page) : ?>
                    <span class="item"><a href="?<?php echo $this->query_string; ?>&page=<?php echo $this->previous_page; ?>">Previous</a></span>
                <?php
                endif; 

                foreach ($this->pages as $page_number) :
                    if ($page_number == $this->page) : ?>
                        <span class="item range current"><?php echo $page_number; ?></span>
                <?php
                    else : ?>
                        <span class="item range"><a href="?<?php echo $this->query_string; ?>&page=<?php echo $page_number; ?>"><?php echo $page_number; ?></a></span>
                <?php
                    endif;
                endforeach; 

                if ($this->next_page) : ?>
                    <span class="item"><a href="?<?php echo $this->query_string; ?>&page=<?php echo $this->next_page; ?>">Next</a></span>
                <?php
                endif;

                if ($this->last_page) : ?>
                    <span class="item"><a href="?<?php echo $this->query_string; ?>&page=<?php echo $this->last_page; ?>">Last</a></span>
                <?php
                endif; ?>
            	</div>
               	<?php
			endif; ?>
            	<span class="summary">Page <?php echo $this->page; ?> of <?php echo $this->page_count; ?></span>
            	<div class="clear"></div>
            </div>
        <?php
		endif;
	}

	/**
	 * Render naviation based on the specified template
	 * @return void
	 */
	public function render_by_template($path)
	{
		if (file_exists($path)) {
			include($path);
		} else {
			echo 'Error: Pagination template cannot be found';
		}
	}
}

Example of use:

<?php
$data = array('Apple', 'Banana', 'Blackberry', 'Blackcurrant', 'Cherry', 'Clementine', 'Elderberry', 'Fig', 'Grape', 'Gooseberry', 'Juniper', 'Kiwi');
$get_data = $_GET;
$page = (int) $get_data['page'];

$pagination = new Pagination($data, $page, $get_data, 5, 5);

$pagination->render(); ?>

<table><?php
foreach ($pagination->subsection_of_data as $row) { ?>
	<tr>
		<td><?php echo $row; ?></td>
	</tr>
} ?>
</table><?php
$pagination->render(); ?>

At my current company we needed a way to track links to downloads or external sites, so they would be logged in Google Analytics. I came up with this piece of code that will allow us to do so, the only prerequisite being at jQuery exists and is used on a particular website.

Here is the code:

<script type="text/javascript">
if (typeof(jQuery) != 'undefined') {
    jQuery(document).ready(function() {
        jQuery(".googleTrack").click(function() {
            var link_href = jQuery(this).attr("href");
            trackGoogleClick(link_href.substr(7));
			return true;
        });
    });
}

function trackGoogleClick(link_href)
{
    if(typeof(window.pageTracker) !== 'undefined') {
        pageTracker._trackPageview('tracked/-/' + link_href);
    } else if (typeof(window._gaq) !== 'undefined') {
		_gaq.push(['_trackPageview', link_href]);
    }
}
</script>

To track a link (or any element for that matter) this method just give the anchor a class or “googleTrack”, and that’s it, it will be tracked.

iTunes Library Parsing Class in PHP

Due to a recent project I’ve been working on I needed to be able to populate a song/artist database with a couple of thousand records for dummy/test data. I thought the best thing to do was to just import my iTunes library however after a quick scan around the net it became apparent that there was nothing around that could easily parse the contents on an exported iTunes XML playlist/library. I put together a rudimentary version for what I needed, but then thought it may be useful for others too, so spent a little longer building a more comprehensive version, which can be seen below:

<?php
/**
 * Itunes_Library - Class the allows user to parse an exported iTunes XML Playlist/Library
 * and convert it into an object
 *
 * @class Itunes_Playlist
 * @author Thomas McGregor <leegleeders@yahoo.co.uk>
 * @link http://thomasmcgregor.co.uk/blog
 * @copyright Copyright (c) 2012, Thomas McGregor
 * @version 0.9.0
 */

class Itunes_Library {
	/**
	 * string	Path to the XML file
     * @static
	 */
	public static $file_path;
	/**
	 * SimpleXML Object   The Parse XML as a SimpleXML object
     * @static
	 */
	public static $xml;

	/**
	 * Import Songs from XML iTunes export
	 * @param string
	 * @param int
	 * @param int|false
	 * @return mixed
	 */
    public static function import_library_xml($file_path, $offset = 0, $limit = false)
	{
		try {
			// Check file exists
			if (file_exists($file_path)) {
				self::$file_path = $file_path;
				// Check SimpleXML is installed
				if (function_exists('simplexml_load_file')) {
					// Instantiate new playlist object
					$playlist = new stdClass();

					// Load XML from file
					self::$xml = simplexml_load_file(self::$file_path);

					// Parse Application Info
					$playlist->info = self::parse_export_info();

					// Parse Track Info
					$playlist->tracks = self::parse_tracks($offset, $limit);

					// Parse Playlist Info
					$playlist->playlists = self::parse_playlists();

					return $playlist;
				} else {
					// SimpleXML not installed
					throw new Exception('SimpleXML does not appear to be installed on this server');
				}
			} else {
				// XML File does not exist
				throw new Exception("File does not exist");
			}
		} catch (Exception $e) {
			echo 'Caught exception: ',  $e->getMessage(), "\n";
			return false;
		}
	}

	/**
	 * Parse Playlist Info from xml, return object
	 * @return object
	 */
    public static function parse_export_info()
	{
		$info = (object) array('major_version' => (int) self::$xml->dict->integer[0],
			'minor_version' => (int) self::$xml->dict->integer[1],
			'date' => (string) self::$xml->dict->date,
			'application_version' => (string) self::$xml->dict->string[0],
			'features' => (int) self::$xml->dict->integer[2],
			'music_folder' => (string) self::$xml->dict->string[1],
			'library_persistent_id' => (string) self::$xml->dict->string[2]);

		return $info;
	}

	/**
	 * Parse Track Info from xml, return array
	 * @param int
	 * @param int|false
	 * @return array
	 */
    public static function parse_tracks($offset, $limit)
	{
		$tracks = array();

		// Initalise Track Counter
		$i = 0;

		// If Offset is not an integer
		if (!is_int($offset)) {
			$offset = $i;
		}

		// If limit is an integer
		if (is_int($limit)) {
			$limit = $offset + $limit;
		}

		// Loop through track nodes
		foreach(self::$xml->dict->dict->dict as $song) {
			if ($i >= $offset && ($limit === false || $i < $limit)) {
				// List properties related to track
				$keys = array();
				foreach($song->key as $key) {
					$keys[] = (string) $key;
				}

				$track = new stdClass();

				$string_index = 0;
				$integer_index = 0;
				$date_index = 0;

				$track->track_id = in_array("Track ID", $keys) ? (int) $song->integer[$integer_index++] : NULL;
				$track->name = in_array("Name", $keys) ? (string) $song->string[$string_index++] : NULL;
				$track->artist = in_array("Artist", $keys) ? (string) $song->string[$string_index++] : NULL;
				$track->album_artist = in_array("Album Artist", $keys) ? (string) $song->string[$string_index++] : NULL;
				$track->composer = in_array("Composer", $keys) ? (string) $song->string[$string_index++] : NULL;
				$track->album = in_array("Album", $keys) ? (string) $song->string[$string_index++] : NULL;
				$track->genre = in_array("Genre", $keys) ? (string) $song->string[$string_index++] : NULL;
				$track->kind = in_array("Kind", $keys) ? (string) $song->string[$string_index++] : NULL;
				$track->size = in_array("Size", $keys) ? (int) $song->integer[$integer_index++] : NULL;
				$track->total_time = in_array("Total Time", $keys) ? (int) $song->integer[$integer_index++] : NULL;
				$track->disc_number = in_array("Disc Number", $keys) ? (int) $song->integer[$integer_index++] : NULL;
				$track->disc_count = in_array("Disc Count", $keys) ? (int) $song->integer[$integer_index++] : NULL;
				$track->track_number = in_array("Track Number", $keys) ? (int) $song->integer[$integer_index++] : NULL;
				$track->track_count = in_array("Track Count", $keys) ? (int) $song->integer[$integer_index++] : NULL;
				$track->year = in_array("Year", $keys) ? (int) $song->integer[$integer_index++] : NULL;
				$track->date_modified = in_array("Date Modified", $keys) ? (string) $song->date[$date_index++] : NULL;
				$track->date_added = in_array("Date Added", $keys) ? (string) $song->date[$date_index++] : NULL;
				$track->bit_rate = in_array("Bit Rate", $keys) ? (int) $song->integer[$integer_index++] : NULL;
				$track->sample_rate = in_array("Sample Rate", $keys) ? (int) $song->integer[$integer_index++] : NULL;
				$track->comments = in_array("Comments", $keys) ? (string) $song->string[$string_index++] : NULL;
				$track->play_count = in_array("Play Count", $keys) ? (int) $song->integer[$integer_index++] : NULL;
				$track->play_date = in_array("Play Date", $keys) ? (int) $song->integer[$integer_index++] : NULL;
				$track->play_date_utc = in_array("Play Date UTC", $keys) ? (string) $song->date[$date_index++] : NULL;
				$track->rating = in_array("Rating", $keys) ? (int) $song->integer[$integer_index++] : NULL;
				$track->album_rating = in_array("Album Rating", $keys) ? (int) $song->integer[$integer_index++] : NULL;
				$track->release_date = in_array("Release Date", $keys) ? (string) $song->date[$date_index++] : NULL;
				$track->normalization = in_array("Normalization", $keys) ? (int) $song->integer[$integer_index++] : NULL;
				$track->artwork_count = in_array("Artwork Count", $keys) ? (int) $song->integer[$integer_index++] : NULL;
				$track->series = in_array("Series", $keys) ? (string) $song->string[$string_index++] : NULL;
				$track->season = in_array("Season", $keys) ? (int) $song->integer[$integer_index++] : NULL;
				$track->episode = in_array("Episode", $keys) ? (string) $song->string[$string_index++] : NULL;
				$track->episode_order = in_array("Episode Order", $keys) ? (int) $song->integer[$integer_index++] : NULL;
				$track->sort_album = in_array("Persisent ID", $keys) ? (string) $song->string[$string_index++] : NULL;
				$track->persistent_id = in_array("Persisent ID", $keys) ? (string) $song->string[$string_index++] : NULL;
				$track->content_rating = in_array("Content Rating", $keys) ? (string) $song->string[$string_index++] : NULL;
				$track->track_type = in_array("Track Type", $keys) ? (string) $song->string[$string_index++] : NULL;
				$track->protected = in_array("Protected", $keys) ? true : false;
				$track->purchased = in_array("Purchased", $keys) ? true : false;
				$track->podcast = in_array("Podcast", $keys) ? true : false;
				$track->unplayed = in_array("Unplayed", $keys) ? true : false;
				$track->has_video = in_array("Has Video", $keys) ? true : false;
				/*HD - No easy way to identify if HD flag is true or false*/
				$track->video_width = in_array("Video Width", $keys) ? (int) $song->integer[$integer_index++] : NULL;
				$track->video_height = in_array("Video Height", $keys) ? (int) $song->integer[$integer_index++] : NULL;
				$track->movie = in_array("Movie", $keys) ? true : false;
				$track->tv_show = in_array("TV Show", $keys) ? true : false;
				$track->music_video = in_array("Music Video", $keys) ? true : false;
				$track->location = in_array("Location", $keys) ? (string) $song->string[$string_index++] : NULL;
				$track->file_folder_count = in_array("File Folder Count", $keys) ? (int) $song->integer[$integer_index++] : NULL;
				$track->library_folder_count = in_array("Library Folder Count", $keys) ? (int) $song->integer[$integer_index++] : NULL;

				$tracks[] = $track;

			}
			$i++;
		}

		return $tracks;
	}

	/**
	 * Parse Playlist Info from xml, return array
	 * @return array
	 */
    public static function parse_playlists()
	{
		$playlists = array();

		// Loop through playlist nodes
		foreach(self::$xml->dict->array->dict as $playlist) {
			// List properties related to playlist
			$keys = array();
			foreach($playlist->key as $key) {
				$keys[] = (string) $key;
			}

			$object = new stdClass();

			$string_index = 0;
			$integer_index = 0;

			$object->name = in_array("Name", $keys) ? (string) $playlist->string[$string_index++] : NULL;
			$object->playlist_id = in_array("Playlist ID", $keys) ? (int) $playlist->integer[$integer_index++] : NULL;
			$object->playlist_persistent_id = in_array("Playlist Persistent ID", $keys) ? (string) $playlist->string[$string_index++] : NULL;

			$object->tracks = array();

			// If playlist has at least one track in it
			if (count($playlist->array->dict) > 0) {
				// Loop through track ids
				foreach ($playlist->array->dict as $track_id) {
					$object->tracks[] = (int) $track_id->integer;
				}
			}

			$playlists[] = $object;
		}

		return $playlists;
	}
}

The class parses the specified XML file, returning an object with the following properties:

“info” – An object containing info about the version of iTunes used to export the library/playlist, among other things
“track” – An array of objects containing every track listed in the exported library/playlist, along with all supplied data about each one
“playlists” – An array of containing all playlists (and data) listed in the exported library/playlist, along with a list of Track IDs of the tracks included in the playlist.

Many thanks to Steve Springett and his article on parsing iTunes Library XML, which was a great help, even if several of the tags in the XSL are in the wrong order.

Let me know what you think, you’re more than welcome to use it but please credit me in some way if you do. You can copy the code from above or download it from the link below.

Download Parse iTunes Library PHP Class

Whitney Houston – R.I.P.

Woke up to hear the news that Whitney Houston has died at the age of 48 – it’s no age to go. The media will no doubt focus on the troubles that have dogged her in her late life, other’s will define her as a role model. To me she was just an exceptional talent who did some great things, but also made some bad choices in life. It doesn’t make her a bad person. A lot of people look down on addiction but to me it’s a form of mental illness and should be respected as such.

R.I.P. Whitney

httpv://www.youtube.com/watch?v=yDhxKVuVYaY

[Edit] Just seen a link to this on Twitter too – Whitney’s isolated vocals on “How Will I Know”, a perfect demonstration of her talents.

[Edit again] Here is an article that sums up the public in general around events such as this. Couldn’t agree with it more if I tried.