Posts for Saturday, November 14, 2009

Installing Go in Ubuntu Jaunty

Processor: x86
Operating System: Ubuntu Linux 9.04 Jaunty Jackalope

1. CONFIGURE THE ENVIRONMENT
Set the necessary variables in your .bashrc that is if you are using bash. Assuming you have a 386-descendant processor and you want to keep the installation clean in an external disk (/media/disk).

# Google Go Programming Language Settings
export GOROOT=/media/disk/go
export GOARCH=386
export GOOS=linux
export GOBIN=/media/disk/go/bin

2. INSTALL MERCURIAL.
Easy.

$ sudo easy_install mercurial

Install process,

Searching for mercurial
Reading http://pypi.python.org/simple/mercurial/
Reading http://www.selenic.com/mercurial
Best match: mercurial 1.3.1
Downloading http://mercurial.selenic.com/release/mercurial-1.3.1.tar.gz
Processing mercurial-1.3.1.tar.gz
Running mercurial-1.3.1/setup.py -q bdist_egg --dist-dir /tmp/easy_install-a3YaRd/mercurial-1.3.1/egg-dist-tmp-VyNqd2
zip_safe flag not set; analyzing archive contents...
mercurial.lsprof: module references __file__
mercurial.templater: module references __file__
mercurial.extensions: module references __file__
mercurial.i18n: module references __file__
Adding mercurial 1.3.1 to easy-install.pth file
Installing hg script to /usr/local/bin
	
Installed /usr/local/lib/python2.6/dist-packages/mercurial-1.3.1-py2.6-linux-i686.egg
Processing dependencies for mercurial
Finished processing dependencies for mercurial


3. CHECKOUT GO USING MERCURIAL

$ hg clone -r release https://go.googlecode.com/hg/ $GOROOT

Checkout process,

requesting all changes
adding changesets
adding manifests
adding file changes
added 4016 changesets with 16888 changes to 2931 files
updating working directory
1640 files updated, 0 files merged, 0 files removed, 0 files unresolved

4. BUILD GO

$ cd $GOROOT/src
$ ./all.bash

Build process,

--- cd pkg/exp/ogle
rm -rf *.[568vqo] *.a [568vq].out *.cgo[12].go *.cgo[34].c *.so _obj _test _testmain.go ogle
8g -o _go_.8 abort.go arch.go cmd.go event.go frame.go goroutine.go rruntime.go rtype.go rvalue.go process.go vars.go
rm -f _obj/exp/ogle.a
gopack grc _obj/exp/ogle.a _go_.8
8g -I_obj main.go
8l -L_obj -o ogle main.8
	
real	0m2.264s
user	0m1.496s
sys	0m0.136s
	
--- cd ../doc/progs
	
real	0m4.430s
user	0m3.144s
sys	0m0.444s
	
--- cd ../test/bench
fasta
reverse-complement
nbody
binary-tree
binary-tree-freelist
fannkuch
regex-dna
spectral-norm
k-nucleotide
mandelbrot
meteor-contest
pidigits
threadring
chameneosredux

It should end with the following lines,

--- cd ../test
0 known bugs; 0 unexpected bugs

5. ENJOY!

avatar

Aspire One / X.org screen blanking

When using X on my Acer Aspire One (110L) and playing videos with mplayer, X would occasionally blank the screen after a few minutes without any way out but to suspend/resume to get your X back. This didn’t only happen with mplayer, and it didn’t have anything to do with xscreensaver.Anyway, after some digging I found that adding Option "FramebufferCompression" "off"to the Device-section of my xorg.conf resolved the problem.
Another cool thing I found out while going through ssh manpages is that you can silence the motd on login simply by touching ~/.hushlogin.

I'm turning into a Lisp snob

Reddit and StackOverflow and other websites I frequent are filled to the brim with discussion of Google's Go. The code snippet on the front page is:

package main

import "fmt"

func main() {
  fmt.Printf("Hello, 世界\n")
}

First thoughts that ran through my head as I looked over the site:

  • Ugh, look at all that syntax.
  • Nice(r) type system (than C++ and Java). I'll stick with multimethods though.
  • Concurrency semantics, hmmm... Shared mutable memory between threads? I think I'll stick with Clojure for now thanks.
  • Where are the macros?
  • It has anonymous functions and closures and sort-of first-class functions? Good. Welcome to the 1960's.
  • len is a special operator? Sigh. (Programming language quality is usually inversely proportional to the number of special forms.)
  • Cool that they used Japanese in the example though. (That word is sekai, "world", obviously.)

Compared to a Lisp, this language looks indistinguishable to C, Perl, Python, Java etc. It looks like such a small incremental improvement (if it even is an improvement). Yet another imperative, for-loop-wielding, curly-brace-using, pointer-mangling, state-mutating, OOP language.

In fact via Reddit today I read this awesome post to a mailing list which compares Go with ALGOL68, and it gave me a would-you-look-at-that moment. Once you learn a few languages that are significantly different from ALGOL derivatives, all ALGOLish languages start to look eerily similar. Are we really stuck with ALGOL-derived languages being the only viable mainstream languages for all time? How much polish can we possibly apply to the same turd?

Then I realized, I'm turning into a Lisp snob. : ( Learning a Lisp apparently does spoil you for the rest of time. I am without a basis to judge whether this language will be a successful replacement of anything. All I know is I probably won't use it. Honestly I'm much more excited about new things on the horizon in Clojure. And I still have getting better at Haskell on my TODO list.

Posts for Friday, November 13, 2009

avatar

Gentoo Wallpaper

I just found this wallpaper I seem to have made in ‘06 (around August) and posted to the Gentoo Forums. It never went anywhere, but it would be a shame to let it go to waste, so here you go. Don’t ask for any higher resolutions though ;)

Download it in 800×600, 1024×768 or 1280×1024.

Linux audio player comparison (nit-picking)

Given my inability to use Amarok 1.4 and my lack of desire to use Amarok 2.0, I tried loads of music players and for now I've landed on aTunes.

It's not perfect. It's far from perfect. But it's the best of the bunch. These are the features I MUST HAVE for a media player and which aTunes possesses.

  1. Last.fm integration. aTunes has probably the best integration I've seen in a player, without going over-the-top and stuffing a whole web browser into the app.
  2. System tray icon, right-clickable with song controls in the menu.
  3. Commandline interface.
  4. Able to display CJK fonts. In Arch (or in Gentoo using the icedtea6-bin VM) CJK fonts are displayed as empty boxes, but in Gentoo using Sun JVM, it works fine.
  5. Tag editing. aTunes has a pretty nice tag editor for single songs or multiple at once.
  6. Amarok-like tree of albums/artists/genres/whatever I want. I want a single expandable and collapsable tree-list, not 3 panes I have to click between.
  7. Equalizer.
  8. Skins are nice; aTunes has these.
  9. "Collection" support and folder-watching/auto-updating when I dump music into ~/music. aTunes does this very well. Scanned a few thousand files fairly quickly, and does updates very fast.
  10. Amarok-1.4-like spreadsheetish playlist layout.
  11. Lightweight build process. No gstreamer. aTunes provides Mplayer and Xine backends and has few to no other dependencies (besides Java). The Mplayer backend didn't work out very well for me, but Xine works beautifully.

It also has some other nice bonuses, like the elegant way it uses the Album Artist tag for albums with multiple artists, the interesting statistics and bar graphs it can produce from your song listening history, playlist tabs, and so on.

Things I dislike about aTunes... well it's a Java app, so it takes a decade to start up. It also has horrid fonts and the widgets are clunky. But it's responsive once it's running, and I don't care how it looks as much as how sane the layout is. Searching is also clunky. But these aren't show-stoppers.

Here's a list of other players I tried, and why I didn't use them.

Amarok 1.4

  • I'd use this if I could. :( It compiles and runs on my Gentoo box but too much stuff is broken due to bit-rot.

Amarok 2

Banshee

  • It wanted to pull in about a billion and a half Gnome dependencies. This is not fun for a KDE user.

Songbird

So close. This is probably second place behind aTunes. It has a great plugin system, it's skinnable, the layout is extremely functional and compact and easy to use and customizable. But...

  • No system tray icon in Linux! This is a show-stopper. There's alltray but it doesn't let me right-click and have song controls.
  • It has a clumsy commandline interface which makes setting global KDE keyboard shortcuts annoying.
  • Bloat. Do you really need a full-fledged web browser in your media player?
  • XUL, ew.

gmusicbrowser

This is very customizable (almost absurdly so) and looks promising. However...

  • Still a bit beta-quality.
  • Crashed on me a couple times in the short time I used it.
  • Interface has a kitchen-sink feel to it. Too many tabs and widgets all over the place. I couldn't find a layout I liked.
  • Looks pretty good, but no real compelling reason to use this.
  • Written in Perl?

amaroq

  • Alpha-quality PyQt4 clone of Amarok 1.4. Looks promising. I will keep an eye on this.

MPD

Last time I tried MPD was years ago. If aTunes doesn't work out, I'll try this next. But aTunes has kept me going for a week now, and I have very few complaints.

If they do a complete rewrite for aTunes 2.0 and destroy the interface, I'll jump off a bridge.

Clojure: redirecting output to a file

In a scripting language, you often run scripts from a command line and print things to STDOUT. For long output you can redirect it to a file via shell-redirection ($ foo.rb > foo.txt).

But if you're using Clojure for ad-hoc scripting, you're probably sitting in a REPL, not running from a command line. REPLs generally don't have shell-redirection. Printed output just gets dumped into your REPL. This can be annoying. (After a good 10,000 lines of output into a REPL buffer, Emacs starts to lag.)

But you can write a macro to handle this easily enough.

(use 'clojure.contrib.duck-streams)
(defmacro redir [filename & body]
  `(spit ~filename (with-out-str ~@body)))

Then:

user> (redir "foo.txt" (foo) (bar) (baz))

Now whatever (foo) and friends would've printed to STDOUT will instead go to foo.txt. I've found this somewhat useful at work lately.

Edit: better version via Graham Fawcett:

(defmacro redir [filename & body]
  `(binding [*out* (writer ~filename)] ~@body))

Sleep Button in KDE 4 Workaround


If you noticed that pushing the sleep button does nothing in KDE 4 (as of this writing <=4.3.3), this is because of a bug in KDEs’ power management tool Powerdevil. It appears that in most cases Powerdevil does not recognize the Xorg servers’ XF86Sleep key. To fix this, you may be able to rebind the sleep key in the KDE control panel.

Add a New Input Action

Open System Settings then Input Actions. Then add a new Global Shortcut:

Name it ‘Sleep’ or whatever you like. Add a Comment if you wish and in the Trigger tab select your hotkey. Try setting the sleep key first. For me, setting the hotkey to the sleep key didn’t work because I believe that Powerdevil already has it bound. There have been others though that look to have sucessfully done so.

Note: If someone knows of a way to decouple the Powerdevil sleep key please let me know.

I bound mine to Scroll Lock (hope I don’t need it anytime soon) then in the Action tab entere the dbus command to suspend to ram:

qdbus org.kde.kded /modules/powerdevil suspend 2

If this doesn’t work, try ’suspend 1′. If you would like to suspend to disk:

qdbus org.kde.kded /modules/powerdevil suspend 4

Posts for Thursday, November 12, 2009

Loggerhead Init Script for Gentoo

I just set up a Bazaar repository server at work. Gentoo has no official ebuild for Loggerhead, so I installed it from Mark Lee's Bazaar overlay. Unfortunately, this does not ship with an init script for serve-branches, so I wrote one.

The script is /etc/init.d/loggerhead (mode 755):

#!/sbin/runscript
# Copyright 1999-2009 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Header: $

PIDFILE=/var/run/loggerhead.pid
LOGDIR=/var/log/loggerhead

depend() {
    need net
}

start() {
    ebegin "Starting loggerhead"
        start-stop-daemon --start --quiet --background \
        --make-pidfile --pidfile ${PIDFILE} \
        --exec /usr/bin/serve-branches -- --log-folder=${LOGDIR} \
        ${LOGGERHEAD_OPTS}
    eend $?
}                               
                                
stop() {                        
    ebegin "Stopping loggerhead"
        start-stop-daemon --stop --quiet \
        --pidfile ${PIDFILE}
    eend $?                 
}

This uses a single entry from /etc/conf.d/loggerhead:

LOGGERHEAD_OPTS="/var/bzr"

It seems to work. When I get the chance I may patch the ebuild to include it and suggest it to the maintainer.

How Round Is Your Circle?


As everyone knows, a point is that which has no part, a line is a breadthless length, and it is possible to cut a sphere up into a finite number of pieces, move them around and put them back together again to get two spheres identical in every way to the original sphere.

Unfortunately, in reality, points have a size, lines have a width, spheres aren’t spheres and they can’t be cut up into infinitely complicated pieces. How Round Is Your Circle, Where Engineering and Mathematics Meet by John Bryant and Chris Sangwin is an attempt by engineers to convince mathematicians that caring about real world issues can be interesting.

The book covers various practical issues, such as:

  • How to draw a straight line, and how to make a ruler
  • How to test how circular a circle is
  • How to measure area

In the process, it discusses all kinds of cunning gadgetry used in the olden days before digital computers and mass production, from steam engine linkages and pistons to slide rules and draughting devices. It also covers various physical demonstrations of geometric problems, and illustrates what happens when physical inaccuracies are ignored:

64 = 65

It’s certainly an interesting read, although I would have preferred more emphasis on the tools and gadgets used than on demonstrations of things they can be used to make. The maths isn’t particularly heavy, and shouldn’t put too many people off. Similarly, there’s nothing on the engineering side that would be inaccessible to anyone with no engineering background.

Posted in hardware Tagged: books
avatar

stackoverflow response that I absolutely loved


I absolutely love this quote:

“Any fool can write code that a computer can understand. Good programmers write code that humans can understand” (Martin Fowler, “Refactoring: Improving the Design of Existing Code”)

Check out this question/answer on stackoverflow.com.

Is Google evil?

Google has become quite ubiquitous in our modern world. Starting out as a pure search engine, the company added Email and online office applications as well as a maps and route planning software and many many more. Whenever Google sees a need for more or better software they seem to jump in trying to fix it.

Google is really into personalization: They offer to store your search history in order to improve future searches for example. Their contacts application transcends application borders to make finding your contacts simple (as long as everybody has a Google account).

On the other hand Google is being severely criticized for their monopoly on information: If Google drops your page from their index it's basically dead because people will not find it (given Google's marketshare). Google's company motto is "Don't be evil" but how serious can we take that statement? Are we too focussed on that one service to rule them all?

Let's look at how Google got where it is today. Back in the day there were many competing search engines (and meta search engines) but at some point everybody started using Google because it was the best product, it provided the best (most relevant) results, it was not as cluttered as the other offerings, it was simple to use but powerful.

From their very strong position in search they branched out: When GMail came out, most other services didn't offer as much storage and Gmail's interface is still one of the best (if not the best) webmail interfaces out there (and it supports real tagging).

Instead of relying on slow Java Applets, Google Maps ran quick in every browser. It had not just abstract maps but also the overlayed satellite photo view which looks really cool.

Looking back Google got into the position they are in by competing and winning. I'm not one of those "the market will fix everything, yay" kind of people, but if you think that markets are such a good thing, Google did play your game.

Well let's get back to the topic at hand, are they "evil"?

Looking at how Google seems to work and what kinds of software they release they are not evil they're just radical pragmatists, or even simpler: Engineers. The engineer sees a problem and seeks a technical solution to it. But many of the problems that technology creates (for example privacy issues) are not technological problems themselves and therefore cannot be solved by technology.

I've heard people joking about Germans based on the existence of the word "Technikfolgenabschätzung". That a word like that could just come from Germans cause they take everything to seriously. But technology assessment, as it's called in English, is often what Google lacks. Google's not evil, they just seem to look at the world through a purely technological filter and (please engineers, don't cry) most problems are not technical.

I do absolutely agree with people that advise others to reflect their media and service usage, to think about whether putting all their data into one company's hands is such a smart idea, to see whether other services might serve them better, but I also believe in using the best tool for the job.

It's kinda funny how people complain about Google building a monopoly when they run Microsoft's Windows on all their machines. Monopolies slap you in the face all over the place.

And Microsoft isn't "evil" either, they just produce an operating system that is not good enough for me to use. "Evil" and "good" are words that fit into fairy tales and religious texts but they usually do not apply to what people in the real world do because they are not absolute.

We all know the "evil genius" character from movies, but does that happen in the real world? Do people use an evil laughter and plan nasty things? No.

Everybody acts on what they know and think is right. Their assumptions on what is right, their priorities might be different than yours, but nobody acts "evil". If you look at other people's actions you might consider them to be evil, but that's because you compare them to your own set of rules and priorities. We as a society have agreed on a certain canon of things generally to be considered "good" but probably everybody could name a few circumstances where those rules don't apply: Many people would agree to killing a mass murderer "for the greater good" for example even though killing people is generally considered to be "bad".

Google isn't evil and I love many of their services but I'm always careful when it comes to giving others full access to my data (which is why I host my own mail server for example). The monopoly Google built is based on merit. You are concerned about that? Fix it, build something better.

My boss recently said that maybe the government should provide a search engine (obviously an uncensored one) and actually I think that is a great idea: Let's take all that EU money they burn in worthless projects every year and hire a bunch of smart people to run a not-for-profit search engine. Don't outsource it to companies that just try to milk the project but really set up your own group doing it. If your service is as good as (or even better than) Google's, the monopoly will be broken. But just telling people to use services that work worse for them won't help and isn't the right way.

Clients are annoying, but life goes on

It's only Wednesday, and it feels like tomorrow should be Friday or Saturday. It's been a long week at work, dealing with some annoyances from clients. One in particular is rushing us along with any real understanding of the underlying process and order that tasks need to be completed in. I'm sorry, but we can't take your site live until your previous host releases your domain name to us. Maybe you should call them.

Another client is just being stubborn when we're working as fast as we can to get his site up. If we ask you to test-drive the site, don't tell us that you'll test drive it after we do. If you work at the same pace we do, we'll hammer out more bugs in a shorter period of time.

We're going to be re-working our terms with the latter of those two clients after this project is completed. We have so many pressing projects right now that every spare moment is precious. When we're ready for you to test the site, you will test the site.

Outside of work, I've enjoyed the last few nights. Sunday night, a few friends and I saw The Reverend Peyton's Big Damn Band at Pittsburgh's Hard Rock Cafe. Tuesday, I helped my friend Nick set up his new blog that I'm hosting. He'll be focusing on a lot of computer security matters, so it should be a good read.

Which brings me to today — Wednesday — where I received a phone call around 3:30PM asking me to come in and help cook for burger night at my Moose Lodge. I worked burger night from when I was fired from Buffalo Wild Wings up to when I landed the job at Savvior. I stopped only because burger night starts at 5:00PM, the same time I leave work. Somehow, I managed to make it from the Northside to Greensburg in just under an hour. We had an easy night.

I have so many projects I want to pursue right now that it's ridiculous. There are so many time constraints between work and friends, that it seems impossible to even maintain one of these projects. And I only continue to add more projects to that list! And now I'm back to the spot where I'm considering taking an officer position at my Moose Lodge. Maybe if I take the time one day and finally hook up the lodge's DSL and put in a wireless router I can work on my projects from there. We'll have to see.

Are you treating your computer better than yourself?

Yes, I am guilty. Most of us are not aware that we are treating our computers better than ourselves. We often juggle tasks like a computer processor. It has been proven by experts recently that multitasking drops IQ. The Dumb Little Man has some cool tips for us.

Read the article, Are You Treating Your Computer Better Than You Treat Yourself?

Posts for Wednesday, November 11, 2009

Doukutsu (aka Cave Story) with an Xbox Controller


What do you know, Doukutsu (aka Cave Story) can be played with a Gamepad! For a Xbox controller this is how I set the controls:

SVG

And how to configure it:

Works great. I love this game. If you don’t want to install Wine (the configuration tool requires Wine) you can download this config file and place it as ‘~/.doukutsu/Config.dat.

tar -xvf doukutsu-config.tar.gz -C ~/

It’s an executable file (probably because the Wine app edited it), haven’t bothered changing it :).

The Go Programming Language

Good day! Try out [The Go Programming Language].

As quoted from its home page,

Go is …

… simple

package main
	
import "fmt"
	
func main() {
  fmt.Printf("Hello, 世界\n")
}

… fast
Go compilers produce fast code fast. Typical builds take a fraction of a second yet the resulting programs run nearly as quickly as comparable C or C++ code.

… safe
Go is type safe and memory safe. Go has pointers but no pointer arithmetic. For random access, use slices, which know their limits.

… concurrent
Go promotes writing systems and servers as sets of lightweight communicating processes, called goroutines, with strong support from the language. Run thousands of goroutines if you want—and say good-bye to stack overflows.

… fun
Go has fast builds, clean syntax, garbage collection, methods for any type, and run-time reflection. It feels like a dynamic language but has the speed and safety of a static language. It’s a joy to use.

… open source

Install Go! Click [here].

Posts for Tuesday, November 10, 2009

avatar

finally attempting to use stackoverflow


For a while now, I’ve seen stackoverflow in my google searches, but whenever I went there, I never felt like I wanted to participate.  But after watching this google tech talk about stackoverflow, it kind of inspired me to start using it.

Upon navigating to stackoverflow.com, I also stumbled upon sister sites of stackoverflow and promptly signed up with them too.  But one in particular caught my eye, careers.stackoverflow.com.  It is basically a supped up resume platform.  It looks pretty awesome and I’ve signed up for that also.  Just need to get working on filling it out.  I’ll probably do that tonight and post it on here when I’m done with it.

Pretty cool none-the-less.

To Parted Magic with <3


I’ve never gotten into a good grove when it comes maintenance of a hard drive. Usually this process involves me loading a LiveCD like Ubuntu, downloading the tools I needed (Gparted, shredder, Partiso…) and going through the slow proccess from there. On occasion when I have to do this process over I have to download all the tools again and it’s just not that much fun to try to remember where the package manager is and what the package names are. This is probably one of those cases where everyone has heard about it but me, but I just discovered Parted Magic and I’m… in… love.

Parted Magic is just a really well put together tool. It boots with a number of options in Grub (a nice feature [and the default] is that Parted Magic will load into RAM). The Grub menu also features SuperGrub which I’ve never tried before but am glad it’s there in case anything goes wrong. This is the first CD that I’ve booted to RAM (expect the Gentoo minimum install CD [which doesn't really count]) and the ability to take off the sludge of constantly churning, throughput-hogging CD drive is nice. Programs start in a snap and I feel that in my time I’m actually doing something instead of pretending I want another sip of coffee.

Parted Magic keeps it lightweight and uses the LXDE Desktop. I have never tried the LX Desktop Environment before but it is very responsive – something you can kinda forget about with modern desktops. Beside being fast, for the basic tasks I really didn’t find anything on LXDE I could not do on my KDE desktop. Thankfully too, Parted Magic keeps it lightweight by only including the needed programs so you won’t find yourself digging to find a program. Since I like to keep to the basics on my desktop (and trust me on KDE that isn’t an easy thing to do), I really appreciated this.

Parted Magic had all the tools I needed to be able to install a new hard drive. Since I wanted my old system on the new drive, I used Gparted to format it, then Clonezilla (yes, it’s included) to image it over. Afterwords, I resized the partitions with Gparted, then shredded the old drive with the Erase Disk utility. Other handy tools are also included like a mounting tool that makes mounting/unmounting quick and easy, TestDisk for possible repair of a damaged partition table, Photorec to recover Photos on a damaged drive, other cloning tools and believe it or not Firefox (which I think is a good idea in case you ever get in trouble). If you install on a USB stick you also have the ability to save the settings so they will be remembered on the next boot. This is really nice feature but must still be new as I found it would only work part of the time when the USB stick is loading.

Overall Parted Magic is a nice tool that I deperately needed. Thanks to Patrick who developed this tool and making my life in Linux alot more pleasant.

Wonders from a KDE fan and developer about some KDE design choices

Technologies going forward..

Twenty years ago, I was reading some books about Unix at the local library. By the time, it was really difficult for me to see, touch, or test an actual unix system and reading books was the closest I could get.

I remember that among the numerous very good ideas ™ in this system, one totally buzzed me : processes and memory protection. A piece of software was protected from other pieces. If one crahes, the other ones could still keep on doing their stuff. Amazing feature, isn’t it ??

Years later, and until very recently, I could proudly say to my friends: “I use linux, I don’t have such problems that you have in Windows and MacOS”. Well, of course, now at least MacOS is based on a serious kernel and the Windows kernel is far better in this regard. But still, unix has had it for very long, and among them, my favourite Unix : Linux.

… forward …

And then, people started to talk about plasma. It is cool, it is great, it is beautiful. One of the reasons I like KDE so much, is that I am very happy with the technology choices made by the project over the time (do you remember the drop of CORBA ?). I’m not into buzz and fancy desktop, so I did not pay much attention to plasma at the beginning. Later on,  I started to try KDE trunk again. For months, it was about: compile, start, wait few seconds, plasma crashed, and the whole desktop/X session restarted.

Then, it got better : plasma crashing would not make the whole session crash, and plasma would handle its own crashes gracefully by restarting. Trust me, I really like KDE, but I could NOT resist to think “Hey, they now handle crashes as well as MS Word do!, great job!”. Well, of course, It was still pre-alpha times, you are not supposed to expect more at this time.

.. and backward

Still some months pass by, and came the beta time. I could finally get into KDE and plasma would not crash on startup. So I tried this new plasmoid thinguy. I added few plasmoids, played with them, even configured some. I tried to add a new one… and WLANG, suddently the whole thing crashed.

Do you see my point ? One of the plasmoids made the whole plasma thing crash. We are back 30 years ahead in time. End of process separation and memory protection. Back to the “don’t try to touch anything, it WORKS, don’t disturb it” and “I do not dare trying this new cool stuff because it could crash it all”.

Design

This sounded weird. Really, really weird. I wondered, and learned that indeed plasma was only one process. It seemed to me like a very bad design choice, but I do not know much about all of this, so I just kept my faith in KDE and did not worry too much. I don’t know anything about internals. I talked to a few people, on IRC, in real life… but nobody seems concerned. Nothing about that on the FAQ, not even on the (short) architecture documentation.

As time goes by, people put almost anything into plasma. I mean it : anything. Developers and users for once seem to agree, and everybody is happy. I still do not really understand the need to put a browser in a plasmoid, but if people enjoy that, I don’t have a problem with this. Free software is all about fun, isn’t it ?

After I updated to KDE 4.2.1, I’ve spent one hour to fix it, finally removing the plasma configuration files to get a usable system. I did not look further, but I guess I could have removed only one part of one file, or maybe even just remove a faulty plasmoid.

I don’t mind the hour I’ve spent… but I worry about the design of plasma. I do not dare asking plasma people, as it seems so.. deeply obvious. They MUST have thought about it, mustn’t they ?

A trend in KDE ?

Today I had to kill one of my konsole because one of the software I’m working on was eating all the memory. I used the great CTRL-ALT-ESCAPE kill feature and that saved my computer. Once recovered, I was really surprised to see that all my konsoles were dead. “ps” could confirm this. I usually have 4 or 5 konsoles with 5 or 6 tabs each. Lot of opened vi inside and so on. A doubt came to me and i started several new konsole, and then issued a “ps aux | grep konsole”. You’ve guessed it, only one was present. I rushed on konsole source code and konsole/src/main.cpp confirmed my fears : konsole uses only one process on purpose, through the use of KUniqueApplication.

I don’t understand and I’m sad about this.

Conclusion

Don’t get me wrong , I still think that a lot of things are still done right in plasma (and KDE in general): separation between data and views (nothing new, but still a great thing to do), packaging (though it’s not done yet, I like the ideas). And it looks darn good, that’s right, too.

I just feel very uncomfortable with this. This is the first time ever in more than 10 years  that I am not happy with a KDE design choice, and a blog post looked like a great way to release this embarassment. As usual I’m afraid that people will read this post lightly, will feel insulted, and will answer with even more insults.

Posts for Monday, November 9, 2009

avatar

Failing disks suddenly very small?!?

I recently had a disk start spewing media errors all over my kernel logs, as they occaisionally tend to do. I unmounted it and then started some basic investigation to see how bad the problem was. The first thing I checked was whether the partition table was still in tact, which oddly it appeared not to be. The disk was reporting it was a fraction of its previous total size, even in the BIOS.

I did some further investigation and this was when I discovered the “Host Protected Area” (HPA) feature had been activated. At a guess, either the kernel or the disk itself activated this feature to prevent further damage to the troubled areas, but if you don’t know about it and don’t do deep enough research to find out about it, it could be easy to assume that the data is unrecoverable.

As the wikipedia article linked above mentions, a bit of hdparm magic (in my case thanks to sysrescuecd) and your entire disk will be visible again, leaving you free to attempt some data recovery (I used ddrescue and the errsize was only a few hundred K – haven’t found which files yet, so it’s likely data I don’t care about or never use!)

avatar

Logwatch with Metalog

Just a heads up to say that I’ve finally discovered why logwatch doesn’t work with metalog-1 any more – some bright spark changed the default log format. On the up side, it’s configurable, so the configuration to change it back has been added to the guide I wrote on Gentoo Wiki

POSIX cksum algorithm in Java

Most Unix programs rely on cksum for checking duplicate files. If you happen to migrate programs doing that, you need to make sure that you’ll be using the same algorithm for the same functionality of course.

Here is the [cksum algorithm] and here is the [cksum man] page.

The class below is implementing the java.util.zip.Checksum interface for extensibility.

/**
 * Compute the checksum of a data stream using the
 * POSIX cksum algorithm.
 */
public class Cksum implements Checksum {
	
    /**
     * The checksum value.
     */
    private int value;
	
    /**
     * The length of the stream.
     */
    private int length;
	
    /**
     * The cksum payload.
     */
    private final int[] payload = {
        0x00000000,
        0x04C11DB7, 0x09823B6E, 0x0D4326D9, 0x130476DC, 0x17C56B6B,
        0x1A864DB2, 0x1E475005, 0x2608EDB8, 0x22C9F00F, 0x2F8AD6D6,
        0x2B4BCB61, 0x350C9B64, 0x31CD86D3, 0x3C8EA00A, 0x384FBDBD,
        0x4C11DB70, 0x48D0C6C7, 0x4593E01E, 0x4152FDA9, 0x5F15ADAC,
        0x5BD4B01B, 0x569796C2, 0x52568B75, 0x6A1936C8, 0x6ED82B7F,
        0x639B0DA6, 0x675A1011, 0x791D4014, 0x7DDC5DA3, 0x709F7B7A,
        0x745E66CD, 0x9823B6E0, 0x9CE2AB57, 0x91A18D8E, 0x95609039,
        0x8B27C03C, 0x8FE6DD8B, 0x82A5FB52, 0x8664E6E5, 0xBE2B5B58,
        0xBAEA46EF, 0xB7A96036, 0xB3687D81, 0xAD2F2D84, 0xA9EE3033,
        0xA4AD16EA, 0xA06C0B5D, 0xD4326D90, 0xD0F37027, 0xDDB056FE,
        0xD9714B49, 0xC7361B4C, 0xC3F706FB, 0xCEB42022, 0xCA753D95,
        0xF23A8028, 0xF6FB9D9F, 0xFBB8BB46, 0xFF79A6F1, 0xE13EF6F4,
        0xE5FFEB43, 0xE8BCCD9A, 0xEC7DD02D, 0x34867077, 0x30476DC0,
        0x3D044B19, 0x39C556AE, 0x278206AB, 0x23431B1C, 0x2E003DC5,
        0x2AC12072, 0x128E9DCF, 0x164F8078, 0x1B0CA6A1, 0x1FCDBB16,
        0x018AEB13, 0x054BF6A4, 0x0808D07D, 0x0CC9CDCA, 0x7897AB07,
        0x7C56B6B0, 0x71159069, 0x75D48DDE, 0x6B93DDDB, 0x6F52C06C,
        0x6211E6B5, 0x66D0FB02, 0x5E9F46BF, 0x5A5E5B08, 0x571D7DD1,
        0x53DC6066, 0x4D9B3063, 0x495A2DD4, 0x44190B0D, 0x40D816BA,
        0xACA5C697, 0xA864DB20, 0xA527FDF9, 0xA1E6E04E, 0xBFA1B04B,
        0xBB60ADFC, 0xB6238B25, 0xB2E29692, 0x8AAD2B2F, 0x8E6C3698,
        0x832F1041, 0x87EE0DF6, 0x99A95DF3, 0x9D684044, 0x902B669D,
        0x94EA7B2A, 0xE0B41DE7, 0xE4750050, 0xE9362689, 0xEDF73B3E,
        0xF3B06B3B, 0xF771768C, 0xFA325055, 0xFEF34DE2, 0xC6BCF05F,
        0xC27DEDE8, 0xCF3ECB31, 0xCBFFD686, 0xD5B88683, 0xD1799B34,
        0xDC3ABDED, 0xD8FBA05A, 0x690CE0EE, 0x6DCDFD59, 0x608EDB80,
        0x644FC637, 0x7A089632, 0x7EC98B85, 0x738AAD5C, 0x774BB0EB,
        0x4F040D56, 0x4BC510E1, 0x46863638, 0x42472B8F, 0x5C007B8A,
        0x58C1663D, 0x558240E4, 0x51435D53, 0x251D3B9E, 0x21DC2629,
        0x2C9F00F0, 0x285E1D47, 0x36194D42, 0x32D850F5, 0x3F9B762C,
        0x3B5A6B9B, 0x0315D626, 0x07D4CB91, 0x0A97ED48, 0x0E56F0FF,
        0x1011A0FA, 0x14D0BD4D, 0x19939B94, 0x1D528623, 0xF12F560E,
        0xF5EE4BB9, 0xF8AD6D60, 0xFC6C70D7, 0xE22B20D2, 0xE6EA3D65,
        0xEBA91BBC, 0xEF68060B, 0xD727BBB6, 0xD3E6A601, 0xDEA580D8,
        0xDA649D6F, 0xC423CD6A, 0xC0E2D0DD, 0xCDA1F604, 0xC960EBB3,
        0xBD3E8D7E, 0xB9FF90C9, 0xB4BCB610, 0xB07DABA7, 0xAE3AFBA2,
        0xAAFBE615, 0xA7B8C0CC, 0xA379DD7B, 0x9B3660C6, 0x9FF77D71,
        0x92B45BA8, 0x9675461F, 0x8832161A, 0x8CF30BAD, 0x81B02D74,
        0x857130C3, 0x5D8A9099, 0x594B8D2E, 0x5408ABF7, 0x50C9B640,
        0x4E8EE645, 0x4A4FFBF2, 0x470CDD2B, 0x43CDC09C, 0x7B827D21,
        0x7F436096, 0x7200464F, 0x76C15BF8, 0x68860BFD, 0x6C47164A,
        0x61043093, 0x65C52D24, 0x119B4BE9, 0x155A565E, 0x18197087,
        0x1CD86D30, 0x029F3D35, 0x065E2082, 0x0B1D065B, 0x0FDC1BEC,
        0x3793A651, 0x3352BBE6, 0x3E119D3F, 0x3AD08088, 0x2497D08D,
        0x2056CD3A, 0x2D15EBE3, 0x29D4F654, 0xC5A92679, 0xC1683BCE,
        0xCC2B1D17, 0xC8EA00A0, 0xD6AD50A5, 0xD26C4D12, 0xDF2F6BCB,
        0xDBEE767C, 0xE3A1CBC1, 0xE760D676, 0xEA23F0AF, 0xEEE2ED18,
        0xF0A5BD1D, 0xF464A0AA, 0xF9278673, 0xFDE69BC4, 0x89B8FD09,
        0x8D79E0BE, 0x803AC667, 0x84FBDBD0, 0x9ABC8BD5, 0x9E7D9662,
        0x933EB0BB, 0x97FFAD0C, 0xAFB010B1, 0xAB710D06, 0xA6322BDF,
        0xA2F33668, 0xBCB4666D, 0xB8757BDA, 0xB5365D03, 0xB1F740B4
    };
	
    /**
     * Checksum constructor, reset checksum.
     */
    public Cksum() {
        super();
        reset();
    }
	
    /**
     * Reset the checksum.
     */
    public final void reset() {
        value = 0;
        length = 0;
    }
	
    /**
     * Update checksum value using a byte.
     *
     * @param byteRead is the byte read to include in the computation.
     */
    public void update(final byte byteRead) {
        value = (value << 8 ) ^ payload[ ((value >> 24) ^ byteRead)   & 0xFF];
        length++;
    }
	
    /**
     * Update checksum value using an int.
     *
     * @param byteRead is the byte read in int form to include in the computation.
     */
    public void update(final int byteRead) {
        update((byte)(byteRead & 0xFF));
    }
	
    /**
     * Get the cksum checksum value.
     * a 2.5 GB file (length=2684354560), filled with random
     * bytes (Java seed=0), returns a cksum value of 128656372
     *
     * @return the cksum value.
     */
    public final long getValue() {
	
        // store both length and value to temps,
        // so we can launch getValue() multiple times
        long tmpLength = length;
        int tmpValue = value;
	
        // include the length of the file to the checksum value
        for (; tmpLength != 0; tmpLength >> = 8 ) {
            tmpValue = (tmpValue << 8 ) ^ payload[((tmpValue >> 24) ^ (int)(tmpLength & 0xFF)) & 0xFF];
        }
	
        return (~tmpValue & 0xFFFFFFFFL);
    }
	
    /**
     * Get the size of the stream.
     *
     * @return the size of the stream in bytes.
     */
    public final long getLength() {
        return length;
    }
	
    /**
     * Get the value in byte array form.
     *
     * @return the checksum value in byte array form.
     */
    public final byte[] getByteArray() {
        final long localValue = getValue();
        return new byte[]
        {(byte)((localValue >> 24)&0xff),
         (byte)((localValue >> 16)&0xff),
         (byte)((localValue >> 8 )&0xff),
         (byte)(localValue&0xff)};
    }
	
    /**
     * Method to work with java.util.zip.Checksum calls.
     */
    @Override
    public void update(final byte[] b, final int off, final int len) {
        for (int i = off; i < len + off; i++) {
            update(b[i]);
        }
    }
}

TGJE no. 10 — On music players

Having listened to quite a few tracks of music (free and otherwise) and tested quite a few of music playing applications, I decided to comment on those that I used the most.

This being said, what I look in a music player is organising music, scrobbling (i.e. sending track info) to Last.FM, integration with remote resources as much as possible (e.g. Jamendo, Magnatune et al.) and obvously playing music ;)

Herrie — a minimalistic CLI media player with a simple ncurses interface and is able to scrobble. So far this is my favourite CLI player and quickly took over mp3blaster's role. No integration with any netlabels though.

SongBird — I used it via PortableApps when I was forced to use Windows XP on a borrowed laptop and frankly, I don't like it much. The interface is borrowed from iTunes and just doesn't work for me (or big collections in general!). On several occasions I had minute-long lags during playback and even crashes! It does have a Jamendo plugin though, but I find its behaviour odd — it opens up Jamendo's website within the player and then only plays the tracks within its own player instead of the Flash player. The huge downside is that you can only have one album in the playlist; on the other hand it does enable you to rate and comment the album directly on the website. It does sport many plugins because of XUL though and scrobbling works as well.

Rhythmbox — although the interface is very much not to my liking, I was happy to switch to it from SongBird when I got myself an Ubuntu LiveCD (yes, I'm still laptopless! XD). Scrobbling works. Jamendo and Magnatune plugins are included (by default?) and work. There are two problems that I have with its Jamendo plugin though. Firstly, the plugn is handled as separate collection and you cannot mix online tracks with those on your local collection. And secondly, it loads the whole Jamendo music repository into the playlist and then you can only filter through it using the iTunes-esque system.

Amarok 1.x — Scrobbling works. Interface is OK and is very power when it comes to organising (especially huge) collections. Jamendo support is missing, but Magnatune is there. Plugins to add other remote resources also exist.Mixing the remote tracks with local ones was possible.

Amarok 2.x — I absolutely adore this player! The interface is amazing with tons of extra information at hand. In the latest release both the interface and the playlist info can be pimped out to the maximum. Scrobbling, of course works. What I particularly love about it, is that it doesn't differentiate a remote from a local collection — meaning that I can simply combine tracks from my HDD with those on Ampache, Jamendo, Magnatune, Free Music Charts, Last.FM recomendations and even streams and "podcasts" in the same playlist. The Jamendo plugin is not the best yet though — it could use some spit and polish to come at least on par with the Last.FM plugin.

In my time I've used other players as well (Juk, XMMP and its clones, etc.), but that has been so long ago that I won't bother spilling pixels over them...

hook out >> @faculty & birthdaying some more ..."die mauer muß weg!" ...oops, have to run I'll miss the lectures otherwise!

P.S. This is the last TGJE post that will be promoted to the front page. TGJE will continue in my blog section.
<!--break-->

Control LCD Text Over Web Interface (Arduino)

Here is my second project on the Arduino.

I had the idea to expand the LCD project that I previously posted here to add a little bit of customization.

What I did was set it up so that I could type in text on a web page (remotely) and have it show up on the Arduino.

I set up a small PHP script that will allow you to enter text, which is then saved to a text file. I run a Python script that checks that file for changes every ten seconds. If it detects changes, it will write VIA serial to the Arduino and give it the text to send.

Below is a video demonstration. See it on YouTube here.

<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0" height="344" width="425"><param name="allowFullScreen" value="true"><param name="allowscriptaccess" value="always"><param name="src" value="http://www.youtube.com/v/n-PQBjVSod8&amp;hl=en&amp;fs=1&amp;rel=0"><param name="allowfullscreen" value="true"><embed allowfullscreen="true" allowscriptaccess="always" height="344" src="http://www.youtube.com/v/n-PQBjVSod8&amp;hl=en&amp;fs=1&amp;rel=0" type="application/x-shockwave-flash" width="425"></embed></object>

Here is the code:

index.php:

<?php

$filename = “lcd.txt”;

?>

Insert text to show on the arduino LCD:

<form method=”GET”>
<input type=”text” name=”textToShow” />
<input type=”submit” value=”Submit” />
</form>

<?php

if(isset($_GET['textToShow'])){

?>

<br /><br />
The following text should be displayed on the LCD:

<?php

echo $_GET['textToShow'];

$file = fopen($filename, “w”);
fwrite($file, $_GET['textToShow']);
fclose($file);

}

?>

<br /><br />
To see the contents of <?=$filename;?>, click <a href=”<?=$filename;?>”>here</a>.

serialChecker.py:


import serial
import time
import urllib

# Create serial connection to arduino
ser = serial.Serial(’COM4′, 9600, timeout=0)
url = ‘link-to-lcd.txt (can be remote)’
previousMessage = ”;

while(True):
message = urllib.urlopen(url).read()
if(previousMessage != message):
ser.write(message)
previousMessage = message
print message
time.sleep(10)

Arduino Code:

#include <LiquidCrystal.h>

// LiquidCrystal display with:
// RS, EN, D4, D5, D6, D7
// or: RS, R/W, EN, D4, D5, D6, D7
// or: RS, EN, D0, D1, D2, D3, D4, D5, D6, D7
// or: RS, R/W, EN, D0, D1, D2, D3, D4, D5, D6, D7

// In this case, the minimum: RS, EN, D4, D5, D6, D7
LiquidCrystal lcd(7, 8, 9, 10, 11, 12);

void setup()
{
Serial.begin(9600);

lcd.begin(2,16);
}

void loop()
{
if(Serial.available() > 0){
lcd.clear();
lcd.setCursor(0,0);

for(int i = 0; Serial.available() > 0; i++){
if(i == 16){
lcd.setCursor(0,1);
}
lcd.print(Serial.read(), BYTE);
}
}
delay(1000);
}

Posts for Sunday, November 8, 2009

TGJE no. 9 — Joy of discovery

Lately I've been thinkin of what's keeping me hooked to free music — and I found the answer: the joy of discovery!

What I mean by that is probably best explained by examples.

In the MTV era that we (still) reside in, "discovering" an artist means pretty much being the first bloke or lass in your class who saw the video on the music channel. Then you can brag: "Aye, I've been a fan of Bloc Party even before they were hip — I saw the video to Banquet just when it came out on MTV" ...yeah, I've been like that as well ..and, yeah, it's not really thrilling.

Now let's see how I find new free artists nowadays by looking at two examples that lead me to discover uncharted seas of music.

First, a (for me) very typical "Jamendo" scenario:

  1. I was browsing along the Jamendo website when I saw an interesting cover randomly appear in the player applet.
  2. I clicked "play", I liked the song and clicked on the album's link, which lead me to Team9's profile page.
  3. Listening to the rest of the album I fell in love with it and wanted to learn more about it and see if there's more! Sure enough there was a link to the band's/artist's website.
  4. On the website I found a huge amount of awesome mashups, which of course they couldn't publish on Jamendo. I listened to them and downloaded some ...but more importantly for this example, I looked at their links to affiliates and artists they (actually Team9 is just one guy) like(s).
  5. A name cought my eye, I followed the link and landed on the website of World Famous Audio Hacker.
  6. There I saw even more mashups (including the famous 8 Minutes of Madness) and a link to a brand new project/album — Tron 1.5. Seeing the movie as a kid, it brought up nostalgia and I checked it out
  7. Needless to say, I checked out the (surrealistic prank) album and amongst the artists listed and linked I saw Solcofn, Tiger Mendoza and Lilith the Kitten, all of whom I liked a lot on Tron 1.5.
  8. More link-clicking and more great music revealed — Lilith the Kitten has some mean remix of Prodigy's Invaders Must Die and some very nice tracks completely of her own as well (I adore Jewelbox); Tiger Mendoza also has some nice tracks on his self-titled EP on BandCamp; while apart from his music Solcofn has lead me to discover a new netlabelCorpid, which I'm still dicovering.

The next example goes around BlocSonic — another netlabel I frequent:

  1. While checking out the (then) newest release of NetBlocBlocSonic's regular compilations of music from other free netlabels — I heard an enchaning pop song called Animals.
  2. BlocSonic offers direct links to both the artists' and their netlabels' (if they have one) websites, but at that time I just wanted to see if Entertainment for the Braindead (that was her name) has any other songs available and if they're equally as good.
  3. Sure enough on her website there was a videospot and a short discography — it turned out that she hand-crafts every single CD's art, making it unique and doesn't want in return anything more then enough money to cover the material costs of the CD and the cover. Wow!
  4. Browsing around on her website I found a link to her netlabel (because I didn't bother to click on it on BlocSonic) — Aaahh Records. Surprisingly it's a netlabel that specialises on acoustic pop/rock, which is not easy to come by nowadays.
  5. On Aaahh Records I also found The Wind Whistles — not my favourite, but very good acoustic pop/rock all the same.

And least, but not least, how I discovered one of my favourite artists in the worldJimmy the Hideous Penguin:

  1. I was bored and, being a Linux geek, searched for "penguin" in Amarok (it uses Jamendo API) and Jimmy popped up. Imagine the chances! I laugh a little inside by only thinking about it :]

Yes, it takes some more work (although less time) then sitting hours on the couch gawking at MTV and being fed the latest ads and fads. But, boy, was it worth it! Not only is there (again) the thrill and joy of discovering completely new artists and new music, but you have more control, make your own choices, find out what you like and what not. And, yes, being able to talk with the artist instead of only about his/her music, is a lot more fun!

Bottom line: finding free music is a lot more thrilling and gives a lot more joy of discovery! Not because of the (lack of) price, but because of the artists' freedom of speech, the listeners' freedom of choice and the freedom of both to communicate.

hook out >> happy birthdaying and going to bed

P.S. I've decided to slowly stop promoting TGJE blog entries to the front page and keep them in the personal blog area only. Both to keep the front page cleaner and to keep TGJE more personal by being less tied to (self-imposed) rules by which I try o keep the front page more serious.
<!--break-->

HTTP reader in Java

While there are numerous ways of accessing web services, here is a primitive way of doing it. This is a simple class for reading HTTP responses. You can take advantage of this, classic examples are,

1. Reading twitter feeds for executing commands in a target machine
2. Getting the latest articles in a particular website
3. Translating through Google Translate
4. Arithmetic operations through Google
5. Currency conversion through Google

and more!

Here is the class.

/**
 * Hyper-Text Transfer Protocol Reader.
 *
 * @author joset
 */
public final class HttpReader {
	
    private Map<String, List<String>> responseHeader;
    private URL responseUrl;
    private String mimeType;
    private String charset;
    private Object content;
    private int responseCode = -1;
	
    /**
     * Constructor requiring the URL string.
     */
    public HttpReader(final String urlString)
            throws MalformedURLException, IOException {
        // open a connection.
        final URL url = new URL(urlString);
        final URLConnection urlConnection = url.openConnection();
        if (!(urlConnection instanceof HttpURLConnection)) {
            throw new IllegalArgumentException(
                    "URL protocol must be HTTP.");
        }
        final HttpURLConnection connection =
                (HttpURLConnection) urlConnection;
	
        // set up a request.
        connection.setConnectTimeout(10000);    // 10 sec
        connection.setReadTimeout(10000);       // 10 sec
        connection.setInstanceFollowRedirects(true);
        connection.setRequestProperty("user-agent", "spider");
	
        // send the request.
        connection.connect();
	
        // get the response.
        responseHeader = connection.getHeaderFields();
        responseCode = connection.getResponseCode();
        responseUrl = connection.getURL();
        final int length = connection.getContentLength();
        final String type = connection.getContentType();
        if (type != null) {
            final String[] parts = type.split(";");
            mimeType = parts[0].trim();
            for (int i = 1; i < parts.length && charset == null; i++) {
                final String t = parts[i].trim();
                final int index = t.toLowerCase().indexOf("charset=");
                if (index != -1) {
                    charset = t.substring(index + 8 );
                }
            }
        }
	
        // get the content.
        final InputStream stream = connection.getErrorStream();
        if (stream != null) {
            content = readStream(length, stream);
        } else if ((content = connection.getContent()) != null &&
                content instanceof InputStream) {
            content = readStream(length, (InputStream) content);
        }
	
        // close connection.
        connection.disconnect();
    }
	
    /**
     * Read stream bytes and transcode.
     */
    private Object readStream(final int length, final InputStream stream)
            throws IOException {
        final int buflen = Math.max(1024, Math.max(length, stream.available()));
        byte[] buf = new byte[buflen];
        byte[] bytes = null;
	
        for (int nRead = stream.read(buf); nRead != -1; nRead = stream.read(buf)) {
            if (bytes == null) {
                bytes = buf;
                buf = new byte[buflen];
                continue;
            }
            final byte[] newBytes = new byte[bytes.length + nRead];
            System.arraycopy(bytes, 0, newBytes, 0, bytes.length);
            System.arraycopy(buf, 0, newBytes, bytes.length, nRead);
            bytes = newBytes;
        }
	
        if (charset == null) {
            return bytes;
        }
        try {
            return new String(bytes, charset);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return bytes;
    }
	
    /**
     * Get the content.
     */
    public Object getContent() {
        return content;
    }
	
    /**
     * Get the response code.
     */
    public int getResponseCode() {
        return responseCode;
    }
	
    /**
     * Get the response header.
     */
    public Map<String, List<String>> getHeaderFields() {
        return responseHeader;
    }
	
    /**
     * Get the URL of the received page.
     */
    public URL getUrl() {
        return responseUrl;
    }
	
    /**
     * Get the MIME type.
     */
    public String getMimeType() {
        return mimeType;
    }
}

Enjoy!

The young do not know enough to be prudent, and therefore they attempt the impossible — and achieve it, generation after generation. - Pearl S. Buck

Planet Larry is not officially affiliated with Gentoo Linux. Original artwork and logos copyright Gentoo Foundation. Yadda, yadda, yadda.