Saturday, June 21, 2008

Facebook Chat

This started as a long post, but as i am learning actions speak louder than words

Monday, May 19, 2008

Backrow, Thats a big ass framework

Some months a ago i spoke about front row. First, the plan was to reverse engineering it, then it was building a plugin for it. Well, it hasn't exactly had my complete attention, however it did drift back into my mind today.

The main sticking point for me has been the lack of documenation, however this should be expected considering that we're talking about a unsupported framework, from one of the most secretive corporate entities in existance.

So in my quest to write for leopard front row, i decided that a nice class diagram would come in handy, easy right...

Well this is what it looks like, after exploring appoximately 30-40% of the 500+ classes!

However i've learnt alot about naming conventions and framework layout. The most striking thing is the level of depth. For example there are classes for everything under the sun, like the Entry of IPv6 addresses. Stuff i personally would have overlooked. I guess thats why i get the semi-big bucks.

Needless to say the folks at apple know how to design a framework, and have done a great job in the absence of namespaces, to provide rigid catagorization of classes.

Class names are nice and logical, for example any class ending with 'layer', is most likely a subclass of BRRenderLayer, eg. BRListLayer or BRTextMenuLayer.

The experience has also made me feel like i've been using the framework, rather than an outsider, looking in. So hopefully in the coming days i can actually leverage this thing to do something other than allow me navigate tv series from the comfort of my bed.

Quote of the Day
"It's a pitty they made so much fuss about gay cowboys, it's actually a decent film"

I happen to think brokeback mountain is a half decent flick

Sunday, May 18, 2008

Snake in the torrents ...

I decided to branch out last week and use python seriously for the first time.

Turns out it is as good as all the praise it gets. This conversion was round about the same time i switched to Transmission for my torrenting needs as the jre + azuerus don't do my memory usage any real favours. The main thing that i love about azuerus was the fact that i could have it subscribe to a rss feed and download "linux iso's" automatically. Coupled with the fact that everyones favourite release group, EZTV provides there releases in the RSS form, it was perfect. However the plugin stopped working correctly about a month ago and i've been forced to actually operate my torrent client, gasp!

Anyways, while having a shower (Yes, i come up with concepts in the shower), i thought maybe i can replicate that functionality using python! Transmission has a feature that makes it scan a folder for torrents, so in theory i would simply need to do the following ...
  • Read a list of files/shows
  • extract the respective links from a rss/xml feed
  • calculate which ones are the most recent
  • download the torrent files
Below is the entire script. It stores all torrent information in sqlite database, meaning that you can extend anyway you want. The script is released under GPL 2.0. I haven't done any real testing, but it works fine with the following conditions
  • Python 2.5.1
  • OS X 10.5
  • Atom RSS source feed (Mininova)
My plan to schedule it as a cron job and sit back and watch.

Python



#Channel 0.1
# Jonathan Dalrymple
# May 17th, 2008

from xml.etree import ElementTree as ET
import os
import shutil
import sqlite3
import urllib

currentDirectory = os.path.dirname( os.path.abspath( __file__ ))

#Create SQL
dbConn = sqlite3.connect( os.path.join( currentDirectory,"torrentsDB") )

#Create the new table
sql = "DROP TABLE IF EXISTS torrents"

dbConn.execute( sql )

sql = """
CREATE TABLE IF NOT EXISTS torrents (
id INTEGER PRIMARY KEY AUTOINCREMENT,
title TEXT,
date TEXT,
url TEXT
)
"""

dbConn.execute( sql )
dbConn.commit()

#Get XML file
response = urllib.urlretrieve( "http://www.mininova.org/rss.xml?user=eztv" )

shutil.copyfile(response[0], os.path.join( currentDirectory,"rssSource.xml") )

xmlFile = os.path.join( currentDirectory, "rssSource.xml" )

try:

tree = ET.parse( xmlFile )

selection = tree.getiterator('item')

i = 0
#For each item tag
for element in selection:
#Get the request elements from the selection

title = element.findtext('title')
date = element.findtext('pubDate')
enclosure = element.find('enclosure').attrib['url']

sql = "INSERT INTO torrents (title, date, url ) VALUES ( '%s','%s','%s')" % (title, date, enclosure)

dbConn.execute( sql )

i += 1

#Commit records
dbConn.commit()

print '%d Torrents have been processed and added to the database' % (i)

except Exception, inst:
print 'Parse Error: %s' % (inst)

#Read the config file for the shows
configFile = file("shows.txt")
shows = configFile.readlines()

#Get the url for the show
print "The following torrents where found ..."

for show in shows:

dataSet = dbConn.cursor()

dataSet.execute( "SELECT title, url FROM torrents WHERE title LIKE '%" + show.rstrip() +"%' ORDER BY id DESC LIMIT 1" )

row = dataSet.fetchone()

#Test to ensure that a record exists
if type(row) == type(tuple()):
try:
print row[0]

#download the torrent file
response = urllib.urlretrieve( row[1] )

newFilename = os.path.join (currentDirectory, show + ".torrent")
#Move from the temp folder
shutil.copyfile( response[0], newFilename )

except Exception, inst:
print 'Download Error: %s' % (inst)

print 'Complete'


Lastly to create the config file, just open your favourite text editor and list your tv shows, delimited using return, mine looks like this

Lost
Battlestar Galactica
House
Cops
American Dad

It's not case sensitive, so don't panic.

Tuesday, April 08, 2008

touch base

I've been reading Microsoft's Code Complete in recent weeks. I highly recommend it for those of you, who like myself are mostly self taught. Yes we may be trying to b rockstar programmers but, we can't plan or organize a project to save our lives.

With that being said i've got a couple of old projects and a few new ones in the pipeline. As usual most are open source. As the term winds down and the amount of time i have to spend grows larger i hope to release a few.

Also as usual for the summer, i'm looking for work for the summer so if you run a start up and your looking for a half decent programmer in and around greater london and the south west, drop me a line.

Thursday, February 21, 2008

Coming to Alderaan



My favourite Youtube video of the year, enjoy

Introducing JGrid 0.01: Simple inline Table Editing

Introducing Jgrid.

Basically i got fed up of the sheer amount of configuring that was required by most inline data grid editing systems. And because programmers are lazy, and big headed, i wrote my own.

Currently it's very rough around the edges, and i would imagine it's got a few bugs. Not to mention all the console/debuging code still in place. But i am releasing more for feedback purposes.

I'm always looking to improve my development practices, so please tell me what you think.

Jgrid was built on top of jquery, and is a jquery plugin. I've built it using jquery 1.2.3, which is included in the release package below. A Documentation document (PDF/ODF) is also included as well as a basic html page, which draws data from a database, [HINT: it will break when you run it on your machine!], i plan to update in version 0.02 when i have more than a single callback.

Enjoy.



Download

Wednesday, January 30, 2008

Memories ... of Lego Aircraft Carriers

Over at Gizmondo, they are showing some of the best lego sets in history.

I'm quite proud to say, that they in fact have two of my favorites.




I spent may a good day, in PJ's playing with them in my grandma spare room in jamaica. She had a kingsize bed, which i used as underground airport, and the wardrobe that was the super secret submarine base. Not to mention the drawers with where the hills surrounding the valley, which had my custom built lego aircraft carrier, which could store a helicopter, a VSTOL aircraft, and a hovercraft, all technic size i might add! It also had two escape canoes, as well as an armory, and control tower, SAM launcher and ....

Ok, i remember it a little too vividly considering it's been 6 years since i last saw it, and a few more since i last really played with it. But it was a lot of fun, and my favorite toy of my childhood. Oh, and to add it could also carry my weight on the carriers deck, thanks to a well placed supporting beam that ran across the ship and tied the hull walls together! It was 2 feet long, and foot wide, and half a foot high.

Enough carrier talk for one night don't you think!

Quote of the Day
"I Guess to you Starbucks is like Dr. Phil"

Some people seek solace at Starbucks

Sunday, January 27, 2008

The gift that just keeps on giving

After my 14 hour stint yesterday, i'm back on the trail.

Today i've cooked up a Javascript shopping cart. In true fashion it's all OO, and shiny. However very unlike me, it's JS library agnostic! Yes, thats right, i wrote by very own 'getElementById' staements!. I've only provided methods for adding, removing, and getting the price of all the objects. There is also a method for updating a ordered or unordered list, with the items stored in the object.

Javascript (No Library required!)

//Basket Object
//Library agnostic
var BasketObj = function(){
this.items = new Array();
this.bindToElementId = null

//Add an object to the basket
this.addItem = function( pObj ){
retVal = false;
if( pObj.name.length > 1 ){
this.items.push( pObj );
console.log('Object added to basket');
retVal = true;
}
else{
console.log('Not a valid object');
}

return retVal;
}
//Remove the first matching item from the basket and return it
this.removeItem = function( pItemName ){
var retVal = null;

for(i=0; i < this.items.length; i++){

if( this.items[i].name == pItemName ){

console.log('Object removed from basket')
// reference the obj
retVal = this.items[i];
//dereference it
this.items[i] = null;
//exit the loop
break;
}

}

return retVal;
}

//Calculate the total basket value
this.total = function(){
var retVal = 0.00;

for(i=0; i < this.items.length; i++){
retVal += this.items[i].price;
}

return retVal;
}

//Updates the gui display of the object
this.updateDisplay = function(){
if( this.bindToElementId != null ){
//Empty the element first
document.getElementById( this.bindToElementId ).innerHTML = '';

//Sort the array before we print
//this.items.sort();

//Now proceed to fill it
for(i=0; i < this.items.length; i++){
document.getElementById( this.bindToElementId ).innerHTML += '<li>' + this.items[i].name + '</li>';
}
}
}
}


To use it, you must first create the object,


x = new BasketObj();


Once thats done you can set it up, the only thing that you really need to set, is the id name of the object you wish to have the results shown in. This is store in a variable called bindToElementId.

x.bindToElementId = 'basketList';


Now you can add your objects to it. Your objects can be as complex as you want, however they must have the following properties,
name: This is the display name for the object, and the name that will be used for internal lookups
price: This is the value that will be added to create your total,

You use the addItem() to add items to the object, and the removeItem( nameOfObject ) to remove items.

To update your list with the current objects you call updateDisplay. And to get the total value of all the objects you can call total().

One other thing to mention, is that i use console.log statements, so be aware of those, and also i check for the name attribute before adding objects to the internal array, so don't try and add them, and prototype the method to your object later on.

Anyways, this object features in my DFTI coursework, which i've been streaming though over this past weekend, i've now implemented the Drag and drop shopping and it looks a little something like this...



I still have to do the admin page, and stock control logic, however imagine this could be done in a day or so.

When it rains it php's

Ever wanted to convert a camel case string into something more user friendly?

Introducing the super dupa know it all function, should be good for PHP 4+

PHP

/*
Make a camel case string user friendly ^_^
*/
function implodeCamelCase( $pStr, $delimiter = ' '){

$strArr = str_split($pStr);
$retArr = array();

foreach( $strArr as $val ){

if( ord($val) <= 90 ){
array_push($retArr, ' ');
}

//add to return array
array_push($retArr, $val);
}

//explictly destroy array
$strArr = null;

return mb_convert_case(implode('',$retArr),MB_CASE_TITLE);
}


It's a bit rough around the edges, anything thats not a lower case character or anything else with a decimal ascii number over 90, will have a space inserted before it, of course thats easy enough to tweak.

Saturday, January 26, 2008

Json Encoding

For a enterprising young developer like myself, i don't take advantage of json enough. So since i'm in the mix at the moment, with my DFTI course work, i thought now would be a good time.

Unfortunately the json_encode() function that i had seen in the PHP documentation, is only in the CVS distributions at the moment (v 5.1.2), so i came up with the below.

PHP

/*
This function converts an array to a Json string.
*/
function jsonEncode( $pArr ){
$arr = Array('{');

foreach( $pArr as $val ){

if( is_numeric( $val) ){
array_push($arr, $val );
}else{
array_push($arr, '"');
array_push($arr, $val);
array_push($arr, '"');
}
array_push($arr,',');
}
//Remove trailing comma
array_pop($arr);

return implode('',$arr);
}

/*
This function converts an associative array to a Json string.
*/
function jsonEncodeAssoc( $pArr ){
$arr = Array('{');

foreach( $pArr as $key => $val){
array_push($arr, '"');
array_push($arr, $key);
array_push($arr, '"');
array_push($arr, ':');

if( is_numeric( $val ) ){
array_push($arr, $val);
}
else{
array_push($arr, '"');
array_push($arr, $val);
array_push($arr, '"');
}

array_push($arr, ',');
}

//Remove trailing comma
array_pop($arr);

array_push($arr,'}');

return implode('',$arr);
}


Both functions take either a regular array, or a Associative and converts it to a json string, which looks like ...


{"id":1,"name":"Ham And Pineapple","description":"<p>Fusce magna sem, gravida in, feugiat ac, molestie eget, wisi.</p>","categoryId":1,"hasNuts":0,"vegetarians":0,"imagePath":"ham-and-pineapple.gif","price":4.95}



The above is just some data from my database. It's a pizza ordering system. I plan to go all ajaxan with a Drag and drop shopping cart, as well as some other shiny stuff.

I haven't a clue what i'm going to do concerning javascript, i'm looking at mootools, mochikit, and of course jquery and maybe even yahoo ui. Might be a last minute thing.

Sunday, January 13, 2008

My Broadband got upgraded!

Or at least so it would appear

Happy posting :), and don't write anything too stupid!

I don't know about you, but this is the fastest torrent speed i've witnessed, ever. Speedtest.net put the connection speed at 6mb!

Wednesday, January 09, 2008

Happy New year, have a server for 08

Happy 2008.

I'm in the middle of finishing up my Object Orientated Application Assignment, and i ran across this piece of code in my repository.


import java.io.*;
import java.net.*;

public class ServerInstance {

private Socket Connection;
private BufferedOutputStream Outbound;
private InputStream Inbound;
private HTTPData RawHttpData;

private int listeningPort;

//ClassFlags
private boolean connectionEstablished = false;
private boolean instanceComplete = false;

public ServerInstance(){
//This one Sets all variables to defaults
listeningPort = Preferences.DEFAULTPORT;
}

/*public ServerInstance(Preferences){

}*/

public boolean run(){
ServerSocket ListenSocket;

boolean retBool = false;
boolean endLoop = false;
int readValue = -1024; // Set to extreme value to show that it is default;
int i = 0;

/*
* How the Server Will work
*
* 1. Get the Data from the browser / Read the Stream
* 2. Send Data off to extract the headers
* 3. While Data is being Processed Send data back to the client
* 4. Flag that server action is complete, and shutdown and clean up
*
*/
try{
ListeningSocket = new ServerSocket( listeningPort );

Connection = ListeningSocket.accept();

connectionEstablished = true;

//1. Get Data from Browser
Inbound = Connection.getInputStream();

Outbound = new BufferedOutputStream ( Connection.getOutputStream() ); //Place output in a Buffered Stream

//Write to both Objects simultainously
while( !endLoop ){
readValue = Inbound.read();

if(readValue != -1){
Outbound.write( readValue ); //Send data to the client
RawHttpData.write( readValue ); //Write data to a HTTPData Object
}
else{
endLoop = true;
}
i++;
}

Outbound.flush(); //Make sure all the data has been sent back to the browser
//Just while we code
System.out.println("Server: has RX/TX " + i + " Bytes of data");

//4. Clean up
Inbound.close();
Outbound.close();
Connection.close();

instanceComplete = true;
}
catch(IOException e){
System.out.println("<-- Server Error -->");
System.err.print( e );
}
catch(IllegalBlockingModeException e){
//I doubt this will come up, but refer to java documentation on serversocket.accept() in the event it does
System.out.println("<-- Server says no! -->");
System.err.print( e );
}
finally{
return retBool;
}
}

public boolean isConnected(){
return connectionEstablished;
}

public boolean isComplete(){
return instanceComplete;
}
}


Code is released under the GPL 2.0 License, go forth and improve (and credit).


This is a working server implementation in java, a relic from my isolation project,( Isolation was meant to act as a personal proxy, similar to how google gears works, however their wouldn't need to modification to the web app, as isolation was meant to pre-fetch the data, based on monitor the users actions/http requests.).

Anyway as you can imagine this was a big project, coupled with my second major data disaster, it didn't really ever see the light of day.

Couple of things to mention, the Preferences class was a data structure to store, ... well user preferences, and the class was meant to implement the runnable interface, so that you could operate multiple server instances.

I learnt a lot researching for it, and thanks to it i have a very good idea of how the HTTP protocol works, however i think it was a little too complex for someone at my current level, i should really stick to trying to reverse engineer front row, and learning lisp.

On the note of the reversing of front row, a plugin called sapphire was released last year. From what i can determine they have worked out how to beat apples protection scheme governing the loading of foreign NSbundles (Yeah, i know about them!). So when i finally get around to it, i'll (try to) reverse it as well.

Quote of the Day
"Rave for business"

I love Capitalism, don't you

Saturday, December 29, 2007

rounded corners anyone?

You may notice my new rounded corners.

Well in true fashion, they're CSS corners.

Instead of loading up one of the many css corner library, i decided to take the opportunity to write my own. The other plus is that as this is a blogger account, i have no real file storage, so linking against the jquery lib makes way more sense.


//Corner rounding function
roundCorners = function( pElement, pSize, pForeground, pBackground ){
//Logging
/*
console.log( 'Corner size ' + pSize);
console.log( 'Fore color ' + pForeground );
console.log( 'Back color ' + pBackground );
*/
if( pBackground.match('none') != null ){
pBackground = 'transparent';
//console.log('transparent background');
}

//constants
containerStr = '<div class="cornerContainer" style="margin:0px 0px;height:auto;background:'+ pBackground +'"></div>';
cornerAttributesStr = 'border:none;overflow:hidden;height:1px;background-color:'+ pForeground +';';


//Reset the parent element
$( pElement).parent().css('padding','none');

//Insert container Div and set background color
$(pElement).prepend( containerStr );
$(pElement).append( containerStr );

for(i=1;i < pSize; i++){
$('div.cornerContainer').eq(0).append('<div style="' + cornerAttributesStr + 'margin: 0 '+ Math.round(pSize/i) +'pt"></div>');
//console.log('Insert element ' + pSize/i);
}

for(i=pSize; i > 1; i--){
$('div.cornerContainer').eq(1).append('<div style="' + cornerAttributesStr + 'margin: 0 '+ Math.round(pSize/i) +'pt"></div>');
}

}


Currently it doesn't support chaining, however according to my understanding, you just have to encapsulated within a jquery.extend, and change the passed object references call and your good to go.

Tuesday, December 25, 2007

New Design

Just a quick note to say here is the new design. Nice and light weight, no shiny stuff (yet). I'll add in some javascript nuts and bolts later, but now i have to set the table for christmas dinner. Btw, this took me like 3 hours, not too bad considering i have to cut and paste into the online editor.

Merry Christmas

Saturday, December 22, 2007

And to think people think i waste my time

I've been hitting the Dev Trail pretty hard over the last week or so. My fringe Cocoa/Objective-C skills are getting better each day. To give you an idea of what my Programming space looks like here's a screenshot.
The Work zone
To summerize, i'm in the middle of linking the mysql-cocoa framework into my project. Now i have hit a slight snag on that front. The snag being that it looks like i can't sell the app.

Why? Because the use of the GPL'd open source framework means that i have to release the source code. Now for a long time, i have considered releasing an application that one has to pay for, but is also open source. However with this kinda of app, my target market, most likely already has xcode installed, and would find it trivial to download the source and hit 'build'.

I'm gonna email the FSF, and find out what they have to say. But i think i might try and release this as an open source application. I love open source as much as the next guy, so maybe this is the way it should go down.

In other news i've finally popped for a Western digital 250GB notebook hard drive. After some stupidity (and a trip to Eastleigh) on my part it's churning away inside my Macbook. The old drive is now a Time machine Drive, speaking of time machine ...

Interface design at it's wildest

It's a nutty excuse for an interface, but it really is fantastic. Pre-Time Machine, i used a backup script i 'wrote' in automator, however it wasn't as flash as this. However it did zip my documents folder from almost 2GB to 700MB which always impressed me, or at least one side of me.

Well it's almost the end of another year and this blog has seen quite a few annual transitions now, 4 to be correct. In keeping with RSS tradition i'll have the usual wrap up posts, plus a 4/5 redesign. Hopefully this time done properly with more ajax than you can shake a stick at, and a cleaner ui, after all i'm a professional now ........



Quote of the Day

Caption

Sunday, December 16, 2007

One byte

Not sure what all the moaning was about, but i must say i like the look of the new iplayer from the bbc. It's not a big slab of flash. Nice ajax like effects. Works in safari. A nice job i would say overall.

I doubt it works for those outside these fair shores, but if it does work i would recommend.

Btw this is post 255, hence the title.

Merry Christmas

Wednesday, December 12, 2007

Reg Exp

In case you ever need them, here are a couple of regular expressions for dealing with dates.

For dates like this: December 19, 2008

[A-z]{3,8}.[0-9]{1,2}.{1,2}[0-9]{4}


For dates like this: 05/03/87

[0-9]{1,2}/[0-9]{1,2}/[0-9]{1,2}


They form part of my fantastic plan to .... write loads of regular expressions ^_^

Tuesday, November 13, 2007

Google's Android: My two cents

I love it. At least from a developers point of view. Now the real question is, can they get the devices with the right form factors to really complete with the big boys, MS, Symbian, and now Apple.

With HTC behind them, there is no reason why they can't. So why does a tech skeptic like me like this FOB (Fresh off the boat) platform so much. Well here's why

  • SDK for OS X, Linux & Windows (Take note Apple!)
  • It uses Java as the language of choice.
  • Each app runs in VM, they borrowed an idea from palm os(kinda)
  • They provided a C Api
  • XML GUI layouts, nice and open
  • The Platform is wide open
If you wanna look at this from a web 2.0 mashup point of view, its like the following

Microsoft's level developer support + Googles Open-ness + Apples inovation

Alternatively Lets compare it to it's rivals

Symbian - 'Modern' widely supported Language (Java vs C++).
Microsoft - It doesn't look like it was retrofitted to be used in a phone
Palm - Multiple device makers, means better form factors + it's a brand new os
Apple - It's not a Objective-C only world, and locked down like a [insert word of choice]
Others - It's got traction, and the developer community behind it, we all love google.

I'm getting to work on developing some apps for this platform. As i said it's got my support, it's solid under the hood, and i look forward to queuing for my first device. 

BTW i hate the iphone if anyone is wondering.


Quote of the Day
Red Light District

Some are more hungry than others...

Tuesday, November 06, 2007

Quick and Dirty Leopard Dock Image replacement script

This one is for all the dock hackers out there. I'm gonna try and roll this into a application during my lectures today ^_^

Cut and paste the script into a text editor of your choice, and save it as "dockSwitcher.sh"

To use this save your new dock images on the desktop and then run the script. Beware i haven't tested as i A. Use the non-glass dock, and B. didn't have time. So use with caution.


#!/bin/bash
## Quick and dirty Dock Image Replacement script
## Jonathan Dalrymple
## November 6, 2007

##Root Checking
## Thanks to
## http://blog.mecworks.com/articles/2006/02/23/bash-scripting-tip-running-a-script-as-root/
CMDLN_ARGS="$@" # Command line arguments for this script
export CMDLN_ARGS

# Run this script as root if not already.
chk_root () {

if [ ! $( id -u ) -eq 0 ]; then
echo "Please enter root's password."
exec su -c "${0} ${CMDLN_ARGS}" # Call this prog as root
exit ${?} # sice we're 'execing' above, we wont reach this exit
# unless something goes wrong.
fi

}

# Check if user is root
chk_root

##Back up dock
cp /System/Library/CoreServices/Dock.app ~/Dock.backup.app

##Remove the old files
rm /System/Library/CoreServices/Dock.app/Contents/Resources/scurve-l.png

rm /System/Library/CoreServices/Dock.app/Contents/Resources/scurve-m.png

rm /System/Library/CoreServices/Dock.app/Contents/Resources/scurve-sm.png

rm /System/Library/CoreServices/Dock.app/Contents/Resources/scurve-xl.png

##Put in the new files
mv ~/Desktop/scurve-l.png /System/Library/CoreServices/Dock.app/Contents/Resources/

mv ~/Desktop/scurve-m.png /System/Library/CoreServices/Dock.app/Contents/Resources/

mv ~/Desktop/scurve-sm.png /System/Library/CoreServices/Dock.app/Contents/Resources/

mv ~/Desktop/scurve-xl.png /System/Library/CoreServices/Dock.app/Contents/Resources/

##Remove dock images from desktop
rm ~/Desktop/scurve-l.png

rm ~/Desktop/scurve-m.png

rm ~/Desktop/scurve-sm.png

rm ~/Desktop/scurve-xl.png

##
killall Dock