10/11/2011

jPlayer Android Bug

If your using jPlayer and your doing something like this:

        ($jplayer
            .jPlayer('clearMedia')
            .jPlayer('setMedia', {
                mp3: '/some.mp3'
            })
            .jPlayer('play')
        );

... and maybe you've looked at the android logs and seen "Attempt to call getDuration without a valid mediaplayer". The problem is the 'play' command. You should move the play command to an event.

27/10/2011

Super efficient HTML pages/apps for mobile and desktop

I've been toying with this idea and I can't say I've seen it before... it goes a little something like this:

Take this blog ( I didn't write the software obviously but thats beside the point ), there is the page chrome ( the stuff around the edges ) and the content. The content consists of a bunch of ( uninteresting ) blog posts.

The page chrome isnt overly interesting... its exactly the same for every page you view - and its sent every time you view any page. Sounds bad to me! Plus for mobile users we probably dont even need half the chrome. We might want a little header or someting but not all the sidebars and whatever. Now you could say "media queries!" but that doesnt stop useless HTML being sent to the browser.

The blog posts themselves can obviously cached as well. Once we've seen them (or at least the browser has) we really don't need to fetch them again unless they updated for some reason.

( If I'd thought this through a bit better I would of used a different example now... ) If this was some sort of web app we'd also have a bunch of JS that would be loaded... but we don't... but imagine we do.

So I see a lot of waste here to show a page of this blog. I dont need the chrome, its probably not changed. I dont need the (imaginary) JS code, its probably not changed. I dont need the posts we've already seen - they probably haven't changed... Urrrm... we probably do want to see if there any new posts! So you can see there is quite a lot of waste going on here.

The classic method of optimising your HTML page is to heavily cache CSS ( oh i forget CSS! ), JS and images. The best way to do this in my opinion is use some sort of revisioned URL's. For example /img/r12345/foo.png. You can grab the revision from your repo in your build scripts or just use a hash or whatever and shove it in the url in your HTML/CSS/JS so that links reference a specific version of the file. That file will have headers to never ever ever expire. When you update your HTML/CSS/JS with a new URL the browser will refetch the resource. Its absolutly the best because the browser will never attempt to refetch a resource. What if we could take this idea a little further...

I'm a massive fan of what I call JS templates - essentialy any form of client side templates. These are great. They mean you send a load of JSON to the browser and it can render HTML client side ( because we all know heavy DOM manipulation to create/update/delete DOM elements is a sin right? ). And plus im always polling or doing websockets or something to pull in new data and then I need the templates client side anyway. So what if we use client side templates to render the page chrome...? "What? Why?" your saying I would think. Well one reason is because in the client you can check the environment your running in a whole lot better than guessing by looking at the UA on the server.

I'm going to stop talking now and show some code:

index.html:

<html><head>
<meta name="viewport" content="width=device-width" />
<script src="/js/r12345/main.js"></script>
<body></body></html>

main.js:

var handheld = window.matchMedia('only screen and (max-device-width: 480px)').matches;

if( handheld ) {
  some_module_loader.require([...JS/templates/CSS required for mobiles ...]);
} else {
  some_module_loader.require([...JS/templates/CSS required for desktops ...]);
}

So we've sent the browser a single index file. It just loads a single versioned JS script which in turn loads a bunch more versioned URLs that are specific to the device its running on. We can now perfectly tailor the experience to the device. Also new versions of files will only be downloaded when they change.

The downside is, if you were visiting this blog, we'd request once our tiny HTML file and then you'd need one more request to check there were no new blog posts. This may or may not be a problem depending on what your doing. It would be kind of bad for a blog but for an email app it wouldnt be too bad. ( I'm currently having wild ideas about cookies sending the last blog post they saw in the initial request which would then mean you could send in the HTML file a list of new blog posts too... not quite thought that through... ). The upside to this techique is of course incredibly small requests. I have absolutely no profiling data to show for this idea - but it does sound pretty good!

So has anyone done this? Is it stupid? Tell me!

25/08/2011

What I've been up to and a follow up to "XUL Challenge"

Blimey.. over a yea since the last post! Definatly time for a new one... Well what have I been doing in all this time? Mostly getting excited about Javascript! I'm now addicted to NodeJS and generally only want to write things in javascript. My day job is still 50% python ( tho it gets lower with each passing hour ) and I still like python as a language, but Javascript is where my interests are at.

I find the Browser world incredibly exciting these days, it moves so fast and I dont like getting bored! The new stuff coming out of Mozilla is fantastic. With fantastic browsers we need fantastic servers and NodeJS fills that hole perfectly. Gone are the days when I could write a Pylons/WSGI app off the top of my head, now I fire up npm, install express and away I go.

But what have I actually been doing with any of it? Well I blogged (all that time ago) about the "XUL Challenge" - could I convert entirely to using the browser for all my apps. In retrospect I meant "browser" not really XUL... In closing I wrote "I would find it most amusing to run firefox in my .xinit and have no window manager... we shall see." Well we have seen, Mozilla saw too, now they are making B2G (Boot 2 Gecko). Sounds perfect to me!

I did for a while play around with the idea of trying to make a window manager again. I was thinking you could redirect windows to offscreen bitmaps, send those to a browser somehow and draw them in canvas elements, scripting the whole lot with javascript. You'd have easy scripting via javascript and themeing via css. While I still like the idea the concept of a window manager doest really seem as usefull to me anymore. Everything is just tabs these days. I have firefox on one desktop with a bunch of app tabs, irssi with a bunch of windows (that look pretty much like tabs), more terminals for projects - all tabbed... I dont need to be managing windows! Everything runs full screen with a row of tabs at the top. Heck - the window manager I use at the moment (awesome) even has what could be called tabs at the top of the screen for switching desktops and apps. Anyway... the window manager ideas are basically out.

My next stream of ideas was for shells, something like bash, that ran in a browser and talked to my local computer somehow ( its all well and good "running in the cloud but first we need to walk on the ground where all our stuff still is! ). I played around with this for a while but didnt really get going until I saw termkit. The philosophy was exactly what I was thinking. This resulted in kuya-shell2. I got it mostly working and was pleased with the result but something wasnt quite right...

The realisation came that I didnt really want to be launching all those linux commands inside my own shell. I didnt want to be writing something that could run cp/mv/df/du/vim/grep/etc, I wanted the shell to implement those itself. I didnt need a way to launch processes, all I needed was a way to manipulate files and directories by talking to a server and I could implement all those things myself. This meant I could change my complicated server that could handle piping command input/output to other commands and doing all sorts of other things to a very simple server CRUD server that listed directories and served files. Yay - KISS for me

So now Im working on, the imaginativly named, kuya-fileserve ( yet to be put on github ). A simple server and browser front end for managing files via the browser. Its ultra clean and slick and packed with HTML5 goodness. The nice part is that the front end can easily be split out to a more generic file browsing app that could be connected to anything you can think of - managing the files on my computer is the priority at the moment but only because all my files are on my computer.

That does still leave me with the problem of seeing a file in a window and not being able to do much with it apart from copying it around or .. urm.. deleting it. As I was pondering the problem I discovered Web Activites / Web Intents. Joy! The perfect fit! If I intend to edit a file, I just tell my browser so and it can offer me a selection of apps to do so! The puzzle is complete. ( In fact the file browsing part could actually become an activity: "I intend to browse this servers files" - server here could mean localhost ).

So thats where I am now, trying to get to grasps with thes activities/intents and browsing files. Its still a fairly new topic but I'm happiest firmly pressed against the bleeding edge!

Thats all for today - hopefully it wont be so long before the next post but I always say that. Iv actually quite enjoyed writing this one and looking back on the last year. I cant really believe all the things Iv learnt this year and whats changed in the world.

See you soon.

04/04/2010

Pure sillyness

Lets run JSGI apps in WSGI! code

Pure sillyness...

22/02/2010

The XUL challenge

What if I could throw away all ( I say all but really I use a terminal and firefox and thats about it... ) the apps I use and find alternatives that work with XUL ( with or without firefox I dont really mind ). Im already running my email, calendar, rss reader and music from firefox tabs... The trouble is in my terminal ill run vim, irssi and do whatever file managing I need to do in there too.

One solution might be to write a curses lib ontop of canvas then run a shell as usual... Iv already written a term in python so this cant be much harder! Trouble here is that there is no way to run a process and read/write to its stdin/out in firefox/XUL apps. If I could get pyxpcom to work it would be easy...

The other, possibly better solution, is to start using something like bespin ( which unfortunatly is in the middle of a rewrite and not useable yet ). I wouldnt mind using that if I could make it very vim like. I could probably use it to do some simple file management too. That would just leave irssi... chatzilla? "meh"

I would find it most amusing to run firefox in my .xinit and have no window manager... we shall see.

09/11/2009

A step... urr.. backwards?

I talked before about my thought process and the start of my browser. I did some more on the browser but it all got a bit annoying and not exciting enough to keep my attention.

Well since then Iv used selenium a lot at work which includes a firefox extension that provides an IDE. Iv hacked a little on it and looked around trying to work out how to do various things and generally understood a bit more about firefox extensions. Enough indeed to get me looking more and more at firefox extensions and finally I understand enough to write my own.

So... now Iv written the plugin that started me writing my own browser. Dont really need that browser anymore... it was interesting and I may still go back to it yet - but for the moment Im now happy with firefox again. I say happy, I mean mostly satisfied!

Firefox code is quite fun - if you like javascript - which I do have a sick fascination with. Im not sure the XUL/firefox docs are that great but then browsing source always keeps me more interested than reading straight forward docs anyway. Chromebug (firebug for XUL) works quite well - tho Iv had to revert to writing my own debug log functions which is annoying. Im too used to firebug and using its console.

I probably should of mentioned what my extension did by now - it keeps activity information associated with each tab ( Im calling activity any clicking/scrolling/key pressing ). It then provides a menu item to show a dialog with a list of all your tabs sorted by activity. You can select many items at once and close them. This means I can quickly close all the tabs I havent touched in X amount of hours.

Iv also added to the plugin a way to quickly assign a shortcut key to a tab so I can skip around. Kind of like temporary bookmarks.

What Id really like is to drop tabs altogether and go for something a bit more interesting to choose what Im looking at... also Im thinking I should start using bookmarks in some clever way... but this is for another day.

Extension is here http://github.com/dunkfordyce/dunks_gubbins/tree/master/tooomanytabs/

13/10/2009

Word cloud algorithm

This is how Iv been doing my word clouds for anyone to copy/learn/improve. Iv had this working in python/cairo, JS/HTML and JS/SVG and its fast enough to work in all.

First the input - we have words/phrases and a weight. Something like this in python:

[
  ('dunk', 100),
  ('python', 50),
  ('rules', 20),
]

You can make up that list however you want. The important thing is we have a word and an importance.

Standard word clouds use font size to display importance. So from these numbers we need to calculate a font size for each word/importance. You could just use the importance as a font size or you could specify a max/min font size and use the importance to work out a new size. How ever you do it we now have a similar list as the input but we can replace importance with font size.

[
  ('dunk', 20),
  ('python', 10),
  ('rules', 8),
]

Normally you will sort the words by font-size/importance in descending order. If you dont it wont matter but you might get some strange results.

Before we place words we need to be able to be able to calculate a bounding box for each word. This is actually rather important. If your doing this in HTML then you can add a new div element with the right font-size and inner text and then use JS to find the pixel size of the div ( the same technique works for SVG too). If your using cairo then you can simply request the extents of a string without having to actually draw anything.

Placing the first word is simple: just choose somewhere and place the word there. Easiest is probably just choosing the centre of your page but there is nothing stopping you using the corner of your output document or anywhere else. Once you've chosen a place we can remove this item from our input list and add it to a "placed" list.

Now for the best bit: we know that next time we add a word we want to add it close to the last... or - easier: we want to place the next word on one of the edges. All we need is a list of edges that we can try and place our word on.

So after placing the first word, we take the bounding box and turn that into a list of edges. Keep the list of edges in order - either clockwise or anticlockwise. For each edge calculate a normal ( this is why you need to maintain order ). All the normals should point away from the centre of the bounding box. These edges should be added to a "free edges" list.

Now for the next word: first calculate the bounding box for the word. Now for each edge in the free edges list place the word on that edge. You'll need to use the edge normal to correct place the word. We know have the new word neatly aligned with the first. For the second word we have no trouble with collisions as nothing can possibly collide - but for all the other words we have we need to make sure that the new word doesnt collide with any others. For this we can do a simple rect/rect collision test with every word in the placed words list. If we detect a collision simple try the next edge in the free edges list. The successful edge should now be removed from the free edges list and new edges from the new word should be added. The edge on the new word that aligns with the chosen edge can also be removed.

Now just keep repeating until either you cant place any more words or dont have any words left to replace. Keep looping through edges, testing for collisions, adding new edges...

Thats it.

There are a load of ways to make this nicer. First, sorting the free edges list by some criteria makes for nicer clouds. Sorting by distance to the centre makes for a nice looking cloud. You can also consider better ways for adding/removing edges: here I have said simply remove the used edge, but if you think about it adding a new word could possibly create new edges where words dont align perfectly.

Other things to think about are word rotation, which is reasonably simple, you just need to decide when to rotate a word. Also you can make things much more complicated by calculating a bounding box for each character in a word instead of for the whole word. This will let words be placed inside other words. It does of course greatly increase the complexity (and therefore runtime).

05/10/2009

The thought process of a kuya

  • I open too many tabs and I can never be bothered to close them
  • Maybe there is a firefox plugin that can look at the last time a tab was scrolled/clicked/something so I can have something pop up and show me the most un-used windows and let me close them all at once.
  • /me looks for firefox plugins
  • /me cant find anything that looks right
  • Should I learn how to write firefox plugins...?
  • I wish I could do it in python...
  • /me remembers python-webkit and pymozgtk
  • All I really want (in a browser) is tabs and something to remember my history...
  • It couldnt be too hard to write my own browser...
  • /me starts writing his own browser

Now the observant will realise Iv gone from one problem, quite simple and not important, to a completely different problem thats much bigger and much more complicated.

This seems to be the pattern I follow! Im not entirely sure if its a good thing or not. It results in large projects - that I probably wont ever finish. On the other hand I get to try out some really cool things ( which is surely all I care about ).

Well anyway I have a basic tabbed browser using python-webkit. Lets see what becomes of it...

22/09/2009

word cloud visualisation

Been trying this out for spike, written in python of course ;) Does something similar to wordle.net, though I have no idea how their alogorithm works!

Algorithm uses edges and collision detection to work quite fast ( that cloud generated in 0.03s ) - should be fast enough for a little animation :)

update...

Added a bunch of options and actually the ability to render text now. You'll never guess the input to this but I quite like the output :)

31/07/2009

Cave Story

Nothing relatated to python today - http://jayisgames.com/archives/2005/08/cave_story.php is really good! It works in wine too with no messing around.