Sunday 31 October 2010

Post To Tumblr Version 0.4



Today is a small update day it seems.

I have updated my Post To Tumblr extension again. I was getting a couple of requests for the ability to add a 'caption' to a post before the image is uploaded so I cranked out this little feature. You can enable it in the options.

Once enabled rather than immediately posting the image it will popup a new tab allowing you to add a caption or whatever to your post:



Its not perfect, I would have preferred the pre formatting window to open in a div popup on the current page instead of a whole new tab, but for now this solution is simple and it works.

I must admit I borrowed the idea from another Tumblr posting extension called "Share on Tumblr". The code is ultra simple:

[codesyntax lang="html4strict"]
<html>
<head>
<script>

// Thanks to share on tumblr extension for this
chrome.tabs.getSelected(null, function(tab)
{
var url = getParam(tab.url,"u")
//var url = encodeURIComponent(getParam(tab.url,"u"));
var finalurl="http://www.tumblr.com/share?v=3&u="+url+"&s=";
document.getElementById("container").src=finalurl;
});

// Thanks http://www.netlobo.com/url_query_string_javascript.html
function getParam( url, name )
{
name = name.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]");
var regexS = "[\\?&]"+name+"=([^&#]*)";
var regex = new RegExp( regexS );
var results = regex.exec( url );
if( results == null )
return "";
else
return results[1];
}

</script>
<link rel="stylesheet" href="main.css" type="text/css"/>
</head>
<body>
<div id="header">
<h1>Post To Tumblr</h1>
</div>
<div class="section-header first"><em>Format your post below</em></div>
<br >
<iframe id="container" style="width:500px;height:430px;border:0px" src=""></iframe></body>
</html>

[/codesyntax]

It just opens an iframe with the Tumblr Share page. Simples!

Post To Tumblr Version 0.3



Just made a quick little update to my chrome extension "Post To Tumblr".

In this update I finally worked out how to catch bad username or password returns from the Tumbr API. Basically it just involved me using the ajax rather than the post jQuery function and using "async:false" like so:

[codesyntax lang="javascript"]
$.ajax({
url: 'http://www.tumblr.com/api/write',
type: 'POST',
data:o,
async: false,
complete: function(transport)
{
if(transport.status == 200 || transport.status == 201)
{
postingNote.cancel();
var postedNote = webkitNotifications.createNotification('images/icon48.png', "Image Posted!", info.srcUrl);
setTimeout(function() { postedNote.cancel(); }, 5000);
postedNote.show();
}
else if(transport.status == 403)
{
postingNote.cancel();
var errorNote = webkitNotifications.createNotification('images/icon48.png', "Posting Error!", "Bad email or password");
setTimeout(function() { errorNote.cancel(); }, 5000);
errorNote.show();
}

}
});

[/codesyntax]

In addition I have added some notifications to indicate when the extension is doing something.

I have made a little demo video below to show this off:



Chrome should auto update for you. If you dont have the extension yet head over to the extension gallery to grab it now!

Monday 25 October 2010

Inputtie - Version 0.1.6

Made a few small stability changes with Inputtie tonight, thought I would share.

Release notes are as follows:

Inputtie Version 0.1.6 (25/10/10)

+ Inputtie now checks for updates every 12 hours
+ Mouse can now correctly reach all the way to the edge of the screen
+ Mouse now remains in the last position it was before the connection closes

Saturday 23 October 2010

Inputtie Development History - Networking

This is part two in my series of posts on the development history of Inputtie.

In this post I talk about the challenge of device discovery and networking in the Inputtie app.

Zero Configure Networking

I knew I wanted Inputtie to be as simple to get running as simply starting it up. For this to happen Inputtie would need to discover all other devices on the network also running Inputtie. So how to do this?



Well, as it happened I had been reading at the time about Apple's Bonjour which was designed to do just what I needed. It is a combination of a multi-cast and DNS lookup service that allows it to detect other Bonjour capable devices on the network. Sounds perfect.

So I got to work on implementing their Java API. After many trials and tribulations I eventually had it working.. kinda. It was detecting other devices sure, but every now and then it would sporadically disconnect from the network. I couldn't for the life of me work out why. I posted on forums and even tried to read the reams of source to see what was going on but alas to no avail.

After much deliberation I decided to look for another solution to the problem of Zero Conf. networking. Next up were a whole host of other attempts. I tried JmDNS which is was supposedly very similar to Bonjour. I also experimented with JGroups. I had limited success with all of them and in the end only really succeeded in wasting several months worth of development time.

The Solution

In the end the solution (and the one currently employed in Inputtie) was the simplest. After months of messing around with these libraries I had learnt quite abit about how they performed their magic. At the heart of it they either used multi-cast or broadcasting to announce a device on a network. Broadcasting can be thought of as a sort of sonar pulse. The broadcasting computer sends a message on a specific IP address then another device listens for the message and proceeds to open a Socket for a more private form of communication. From Wikipedia:
A broadcast address is a logical address at which all devices connected to a multiple-access communications network are enabled to receive datagrams. A message sent to a broadcast address is typically received by all network-attached hosts, rather than by a specific host.

I decided that if these libraries could use broadcasting for discovery then so could I and if I wrote it myself I could keep it simple. So I set to work coding an example in Java. In no time at all I had it running and surprisingly it worked! Sure it wasnt as robust as the established libraries, it didn't handle devices disconnecting from the network, different network subnets or IPv6 but it was simple and at least it worked!

Broadcasting in Adobe AIR

As I mentioned in a previous post Inputtie went through many re-writes during development from its original form in Java through C++, C Sharp and finally Adobe AIR. With the latest (it was still in beta when I started development) version of Adobe AIR 2.0 several new APIs were made available for use, one of them being new classes designed specifically for peer to peer (P2P) networking. With these new APIs I believed I should be able to implement network broadcasting much in the same was I was doing in Java. Unfortunately however it seemed that Adobe was restricting the use of broadcast to their new P2P service Cirrus.

There was however another crucial API released with AIR 2.0; the NativeProcess API. With this a developer is able to easily execute and communicate with a program written in another language. What this meant for Inputtie was that I could write the user interface in AIR and then use NativeProcess to call Java code that would perform actions not available in AIR, such as Broadcasting. (incidentally it also is a great way to do multi-threading in Air ;))

So the current solution in Inputtie is to use NativeProcess from AIR to communicate with a small headless (no user-interface) Java process that does the broadcasting and listening for broadcasts. Once the Java process detects an incoming broadcast it passes the information back to AIR.

EDIT: If anyone is interested in seeing the source to my previous (failed) attempt just drop me a comment or an email and I would be happy to share.

Sunday 17 October 2010

Inputtie - Version 0.1.5



Just a few small changes in this update:

From the release notes:

Inputtie Version 0.1.5 (17/10/10)

+ Middle mouse input is now caught and transferred between devices
+ More errors are caught in the client
+ Keys are now depressed when a connection is cut, no more lingering Shift, yey!

The new version should automatically download, but if you don't yet have it go grab it on the download page -> http://www.inputtie.com/download/

Post To Tumblr - v0.2



Just a quick update to my first chrome extension.

Following a request someone left in the comments I have now added an option to set how the post should be published. So now you can choose whether you want your cat with a lime on its head to be posted to your drafts or your queue or simply to your default wall.

You can grab the new version in the usual place on the Chrome Extensions Gallery -> https://chrome.google.com/extensions/detail/dbpicbbcpanckagpdjflgojlknomoiah?hl=en

I think it updates by its itself, but I cant be sure!

Enjoy!

Thursday 14 October 2010

My First Chrome Extension - "Post To Tumblr"



Mummy wow! Im a big boy now! I have just published my first Chrome extension.

It was really annoying me that when I found a funny cat or some other silly image I would have to go through a whole ball-ache process to get that image on my Tumblr account.

What I really wanted was some right-click-post action going on and wondered why no one had one it yet. So with an hour or so to spare I whipped this extension up really quick.

It uses the Chrome 6 Context Menu API so you obviously need to have Chrome 6 to be able to use it.

Currently it only posts images as that's all I needed for now but if enough people want more then ill whip out the other data types.

The source couldn't be any simpler really, infact this is it here:

[codesyntax lang="javascript" lines="normal" blockstate="expanded"]
chrome.contextMenus.create({"title": "Post Image To Tumblr", "contexts":["image"], "onclick": postImage});

function postImage(info, tab)
{
var email = localStorage["tumblr_email"];
var password = localStorage["tumblr_pass"];

if(!email || email=="" || !password || password=="")
{
alert("Need to set your Tumblr username and password in the options before posting!");
}
else
{
var o =
{
"email":email,
"password":password,
"type":"photo",
"source":info.srcUrl
};

var success = function(data,textStatus,request)
{
if(textStatus=="success"){ alert("Image posted to Tumblr. Image -> "+info.srcUrl); }
else { alert("Bad email or password"); }
}

$.post("http://www.tumblr.com/api/write",o, success);
}
}

[/codesyntax]

Simples!

Theres even an option page where you put in your Tumblr details:



Oh, there is one issue.

No matter what I tried I couldn't manage to get the Tumblr API to return an error. So if you enter your username or password incorrectly it still reports success, not entirely sure why, if someone knows I would love to hear why!

Interested? You can go grab it over on the chrome extensions gallery page -> HERE

Saturday 9 October 2010

Inputtie History - The Beginning

I promised in a previous post to post to talk about the Inputtie development process a little, the various challenges encountered and how I attempted to solve them.

In this post im going to talk about the very beginning of the project and what I knew I wanted to have in the final version. Subsequent posts will elaborate on the various technical hurdles and my attempts to solve them.

The Problem


[caption id="attachment_1372" align="alignright" width="229" caption="Various Inputtie Attempts"]Various Inputtie Attempts[/caption]

I have already talked about the problem in my previous post but ill recap.

About a year ago I was doing a lot of work at home that involved working both on my desktop PC and my MacbookPro. Often I would find myself using my mouse and keyboard on my PC then having to lean accross to use the trackpad and keyboard on my MBP. Now, I hate trackpads so what I started doing was unplugging my keyboard and mouse from my desktop then plugging back into my MBP when I wanted to use it.

This situation was obviously less than ideal, so I started looking around for other solutions. I had heard of hardware you can buy that involves flipping a switch when you want to change which device you want your input to go to. I considered this but thought there must be a more elegant software solution. I had an idea in my head where I wanted you to simply move my mouse pointer off my desktop monitor and it would then magically appear on the laptop screen.

It was at this point I found out about Synergy. I took a good look at it but for the life of me could not get it to work no matter how hard I tried. It also involved lots of fiddley messing around with IP addresses / hostnames and command line parameters (it has improved in a year, but more on that later). So I thought to myself surely there is a better way of doing this, surely its not a tough technical problem to solve!?

Technical Hurdles


So starting back in October 2009 I decided to undertake the problem, it shouldn't take more than a few evenings to put something together surely?

First I tried to identify the core features I knew I wanted the tool to have:

  1. Work on the three major operating systems, Windows, OSX, Linux.

  2. Be appealing and simple to use without any fiddly configuration file editing.

  3. Without any effort on the part of the user detect other available devices on the network.

  4. Capture low-level input, mouse & keyboard.

  5. Transfer the input to the other device and have it applied.


With the core features roughly sketched out I could now start thinking about the various technologies I would need to implement them.

My initial thoughts were that Java should be the ideal language to do this in. I could capture the input from one device (somehow) then I could send it to another device and use the Robot class in Java to simulate the input. Because its Java it will work across all operating systems seamlessly so people using it on windows / mac / linux would all get exactly the same experience and I wouldn't have to lift an extra coding finger as Java would take care of all the nasties for me.

It also helped that I was very familiar with Java having worked on severl personal and professional projects in the language. From my Chain Reaction project I knew it was possible to create relatively nice user interfaces probably it would take some work to make them look as good as I wanted but surely it wouldn't be too hard.

So with some confidence I decided to get cracking on development.

Edit: I am breaking this up into several posts as this was getting to be rather large and difficult to read ;) So check out the posts in the coming weeks for more.