DynaBar 2 - More dynamic userbars!

Alrighty, time to release DynaBar 2.

I’ve thrown together a page for it, check it out. Download and a lot more information on features and plugins are available on the new page.

To see what’s new, take a look at the README in the docs/ directory.

Have fun :).

Technorati Tags: ,

Attached Files:

New title image

Indeed. I discovered the only thing I didn’t like about this site’s design was the page header image.

So it’s gone, and a leet one is in it’s place. Yay.

Lots of stuff

Hmmmmm, long time no update. That’s not to say I haven’t been busy recently.

Last month, we released “UnWheel R5“, which seems to have become the (hopefully) final release. I’m pretty happy with it at the moment, all the major bugs are gone, multiplayer is working wonderfully and the online record system is churning records around at a mean rate (and those records still need a monthly rotation system applied, so still some work to be done there). I still haven’t decided if I want to do this all again in Unreal Torunament 2007 or not :).

Elsewhere, I’ve been playing around with DynaBar, and it’s grown a lot. The plugin system has been tweaked to allow better customisation options from the developer side, as well as having options added to improve the user interaction side of things. There are a whole crapload of other options available as well, multiple layers (supporting PNG graphics with alpha transparency), different scanline styles, text prefixes and suffixes, better caching options, etc. In addition, you can choose to have the bakcground be a gradient blending between any two colours, horizontal or vertical, and you can create “groups”, which is a bunch of userbars animated (with fading/blending between bars), and they all remain fully dynamic. Speaking of dynamic, I’ve also added a whole load of plugins, from XFire, to more Last.FM options, to Battlefield 2 and TrackMania, and even RSS headlines and live game server status via Qstat.

I’ve put up a test system here as a sort of sandbox, so feel free to try out all the options and plugins, and if you have any suggestions or ideas for plugins, please let me know. In addition to the designer, there’s a browser available, which lets you easily build the animated groups mentioned above. Also, it all works with Internet Explorer now, which I didn’t bother fixing with the previous version (wasn’t meant to be such a “big” project :)). Source code package will be available as soon as some more testing is done.

In addition, I’ve been re-writing my online Dosage-powered comic viewer - Injector - again, this time it’s going fully “Web 2.0″ (ZOMG!), so everything’s quite nice and quick. This project still needs a bit of work on the administration and installation side of things before it can see a release.

Aside from all that, I’ve also been slowly building a new UnrealZA site, using the Python-powered Django framework. It really is a wonderful thing. Please excuse me for a minute while I run away from a horde of crazy, twisted, Nevow fans (among others). Anyway, I’ll happily recomment Django any day of the week to anyone looking for a Python web framework.

I’ve also decided I don’t like the look of this site anymore, so I guess that’s another thing to go on my to-do list for the near future.

Technorati Tags: , , , , ,

Spam filtering with SpamBayes

Alright, so I’ve been getting more and more spam in recent weeks, and they’ve been getting harder and harder to build basic filter rules for.

My mail works in a pretty round-about way:
I have multiple POP accounts all over the place, which have sort of accumulated over the years. It becomes a bit of a mission to always set up and check all these accounts, so what I have now is a small Python script that connects to each of the servers, grabs the mail, sorts them based on some simple filters (like, containing a [mailinglist] type subject), and places them within a Maildir structure based on that sorting. In addition, it does the same thing for deciding if it should delete a message - extremely basic spam filtering rules can be set up to check out certain headers for possible spam flags, etc.

The downloaded mail is then served via IMAP, using the Dovecot mail server. The great thing about that, is then every time I re-install any of the machines I use for mail access, or install a new one, I instantly have all my neatly sorted folders, all my mail from all my accounts, and only one IMAP account I need to set up.

Anyway, basically, the spam filtering of the above system was rather lame, so I went on the hunt for something a little more useful. Enter SpamBayes - a mail proxy application written in Python.

It’s already “in Debian”, so installing was as fun as always (aptitude install spambayes), after which I only needed to start the service, and then it’s off to a browser to configure it. Actually there wasone step before that - since I’m running this on my server, and SpamBayes is meant for use by a single user on their own PC, it doesn’t allow connections do it’s browser-based configuration from other hosts. Which is a bit of a problem when running a server which I have no interaction with beyond a command shell. Thanks to Lynx I was able to configure it to allow connections from my local network.

For starters, you need to tell it which POP3 servers you want to connect to, and assign local ports to each one, which will be stand-ins for port 110 when connecting to servers. The interface for this is a bit troublesome however, requireing you to enter each server into a single input field, separated by commas. The associated ports for each server are then entered into another input field in the same manner. It took me a while to get both the fields synced due tot he number of servers I intended using.

Next up, I fed it a few emails for training (saved emails out of Thunderbird as EML files, and these can be uploaded to the server for training via the browser interface) both ‘ham’ and spam.

Once it knew the basics, I simply updated the list of servers in my Python script to “localhost”, and whichever port each one was set to. Shortly thereafter, mail started passing through the system. Most of it was identified as “unsure”, as it hadn’t seen enough examples of ham or spam yet. Quite smartly, it keeps a record of each message that’s passed through, and you can easily train ham or spam from these.

Around 50 mails later, it was identifying almost every message perfectly. I’m going to leave it running for a day or two more, training everything that arrives, then I’ll just add a single filter to my mail fetching script, looking at the “X-Spambayes-Classification” header for “spam” (delete), or “ham” take no action.

I’m quite happy with this setup, looks like it’ll work quite well :D.

Technorati Tags: , , , , , ,

PHP5 broke it

Seems just about everything on my server machine has been running perfectly since I upgraded to PHP5, except this site :(.

So for the time being, the attachments plugin is disabled (the cause of the problem), so no downloads are available until I fixxor it.

Edit:
Well, that took all of 5 minutes to fix ;)

PHP Image Browser and Download Stats

Created two very basic scripts this past week:

The first, a basic Image Browser:
Basically, I really hate trying to set up and use normal image publishing/gallery software. Something like Gallery is pretty nice and feature packed, but for putting a photo of your cat online, it’s pretty much a mission, with users, permissions, logins, galleries, categories, grouping, keywords, thumbnail options, etc, etc. I just want to upload a JPEG and say that’s the end of it, but still have ti browsable with some thumbnails that didn’t take me 10 minutes to create in Photoshop.

Anyway, yar. So I made this script. It’s actually a pair of scripts. A basic browser interface that simply goes through a directory, finds all images, links to them, and shows thumbnails of them via the second script - a basic thumbnail generator.

So ‘installation’ is simply dropping this pair of scripts into the directory you want to publish your images from, and it’s done. Any sub-directories will be navigable, so you can use them as ‘categories’ if you’d like. Since the thumbnails are generated on the fly as needed, there’s no database or anything, and adding a new image is as simple as dropping the file into your image directory.

The second script, is a Download Tracker:
Extremely simple again, simply does a count of hits on any file passed to the “file.php” script. The files can be located anywhere on the system (so if you really don’t want people getting at your files without going through the counter, they can be outside of your www published path).

Again, I was going for simplicity here, so there’s no massive upload manager UI, or snazzy hit monitoring UI, or a 5000 table MySQL database. It keeps track of the hits by simply storing them in a regular PHP array, and then serializing this array to a file. Next time the file it requested, the hit log file is loaded, then unserialized into the array, the array is updated and serialized again. :). So you’ll need to make sure the “files.log” file is writable by the web server (or the whole directory the tracker files are in). It also requires PHP5, unless you write replacement functions for file_get_contents() and file_put_contents() on earlier PHP versions.

Link to a file as follows: “http://my_site.za.net/file.php?installer.exe”, or even “http://my_site.za.net/file.php?path/to/document.pdf”

You can then view the hits and things via the “file_stats.php” which outputs a very basic tabular representation of the stats the hit log tracks.

Both of these packages’ code is pretty well documented, so if anything, they may be educational so you can build more exciting versions of these. However, as they are, they serve my needs, but just thought I’d share anyway ;).

Usage instructions are also within the code.

Delphi: Write multi-line text on a TCanvas

I’ve had to do quite a bit of stuff with images in Delphi recently (lots of manual drawing too), and discovered TCanvas’ TextOut method will only draw text onto one line, line breaks and newlines are ignored. Google search results suggested Windows’ DrawText function, however dispite all the formatting and alignment flags it takes, it refused to draw text centred vertically.

Anyway, here’s a small-ish procedure which will take your multi-line text, and draw it centred on the canvas you pass it. You also need to pass the width and height of the canvas you’re drawing to. It assumes the font can everything else has been set by you, prior to calling it. Also, be sure “Graphics” is in your “uses” section.

procedure multilineCanvasText(canvas: TCanvas; text: String; width, height: Integer);
var
  textSize: TSize;
  lines: TStringList;
  i, blockHeight: Integer;
begin
  // lazy man's way of splitting text by line into a list (split by #13#10)
  lines := TStringList.Create;
  lines.Text := text;

  // see how high our block of text is going to be, based on the font the canvas
  // currently has set
  textSize := canvas.TextExtent('LOZL!');
  blockHeight := textSize.cy * lines.Count;
  blockHeight := blockHeight;

  // go through each line and output it
  for i := 0 to lines.Count - 1 do
  begin
    // we need the width of each line, so we can center it on the canvas
    textSize := canvas.TextExtent(lines[i]);
    // render the text
    canvas.TextOut((width div 2) - (textSize.cx div 2),
                   (height div 2) - (blockHeight div 2) + (textSize.cy * i),
                   lines[i]);
  end;
end;

Technorati Tags: , ,

More new toys

Well, only one for now.

Sadly, I no longer need my laptop for work, as I have been provided with a proper desktop machine (this may be a good thing, since I can now boot Debian permanently, as I’ll no longer need to use Delphi on it). Anyway, I kind of liked having my work stuff and private stuff portable with me. So, I got something a little more portable, which I can both work (well, do basic documents, do all my emailing, track to-do’s, contacts, etc), and personal (fill it with random fun stuff) stuff on.

Enter, the iPAQ hx2750 :D. Complete with wireless LAN, so I can connect to networks at home, work, and the occasional Mug and Bean, Bluetooth for sending files between the handheld and laptop, and sending photos to to from the phone (I can even dial contacts on the iPAQ via bluetooth on the phone :P, and of course use it as a dial-up modem when a network is not available), SD slot for extra storage, and another way to transfer files between laptop and handheld, and a bunch of other leet stuff it can do.

I’ve also got PocketPuTTY up and running, so when I feel the urge I can pop onto whatever boxen I need, Python CE has already been helpful, as it enabled me to write a small .tar file extraction script for some other files I wanted. Even though I’m still first and foremost an Unreal fanboy, I couldn’t resist installing Pocket Quake. Pocket RAR and Adobe Reader have also come in rather handy.

Pocket Word is quite reasonable, and maintains document’s original formatting quite nicely. Pocket Outlook works very well for receiving, reading, and sending emails, and if ever offered the option of Outlook or Pocket Outlook, I’d have to choose the pocket version :P. It handels POP and IMAP mail eaqually well, and even does IMAPS without complication.

All-in-all, I’m rather impressed, and I find myself using it rather regularly throughout the day, especially for keeping track of projects and things at work, which was partly the main idea anyway.

PyODE physics in PyOgre example

Guess it shouldn’t have taken so long for me to get around to doing this, but at least it’s done now.

Attached to this post you’ll find a zip file, containing a small example application which allows you to spawn PyODE physics-enabled cubes with the middle mouse button into a PyOgre world. You can then bounce and roll the cubes around by holding the left or right mouse buttons.

The code is fairly straight-forward, and I’ve included quite a number of comments. Should be easy enough to follow what’s going on if you’ve been through the PyOgre tutorials.

A note of performance and stability - you can safely spawn loads of cubes as long as there are not too many collisions going on at once (after around 50 cubes, things start to get really sluggish if there are too many inter-cube collisions going on). In practice though, I doubt you’d need that many collisions happening at any one time. Also, If you make a large pile of cubes, lift them all up, and let them fall down together, it seems to bomb out as there are too many collisions happening when they all land on top of eachother at once. I haven’t debugged this very much, so I’m not sure yet if it’s a ODE limitation, or something bad I’m doing in the code. If anyone works it out, I’d be interested to know.

Please don’t ask for advice on stuff like per-polygon collisions, terrain collision and the like, I have not really messed with this beyond the state of this example. Once you get the basics going after checking out the example, I’m sure a few questions shot off at the PyOgre Forums would turn up more useful results than asking me :).

Have fun ;).

Technorati Tags: , , , , ,

Attached Files:

Heavy Delphi cracksmoking

As we all know, PNG images are so much cooler than BMP images. Especially with alpha channels.

A while ago, I found this rather spiffy PNG library for Delphi, which allows you to load PNG files into a TPicture or similar, complete with alpha channels. Generally, it works simplest with TImage, however being a TGraphic subclass, you can do all sorts of drawing and everything else on it.

ANYWAY, I wanted to be able to use these things on buttons (standard TSpeedButton and TBitBtn), however their Glyph property is a TBitmap, preventing us from doing a simple Button.Glyph.LoadFromfile and loaging a PNG file. The other option is to load up the PNG on it’s own with a TPNGObject, and assign it to the glyph property, however the alpha gets buggered.

So I came up with a crackful work-around (as I’m finding 90% of all Delphi coding is):

procedure pngGlyph(Btn: TControl; Img: String);
var
	PNG: TPNGObject;
	BMP: TBitmap;
begin
	PNG := TPNGObject.Create;
	BMP := TBitmap.Create;

	try
		PNG.LoadFromFile('path\to\glyphs\'+Img+'.PNG');   // Update the path to your .png files, or update this to get them somewhere else.

		BMP.Width := PNG.Width;
		BMP.Height := PNG.Height;
		BMP.Canvas.Brush.Style := bsSolid;
		BMP.Canvas.Brush.Color := clBtnFace;
		BMP.Canvas.FillRect(Rect(0, 0, PNG.Width, PNG.Height));
		BMP.Canvas.Draw(0, 0, PNG);
		BMP.Canvas.Pixels[0, BMP.Height-1] := clBtnFace;

		if (Btn is TSpeedButton) then
			(Btn as TSpeedButton).Glyph.Assign(BMP);
		if (Btn is TBitBtn) then
			(Btn as TBitBtn).Glyph.Assign(BMP);
	finally
		PNG.Free;
		BMP.Free;
	end;
end;

To use it, you call it like “pngGlyph(SpeedOrBitButton, ‘glyphname’);”, and the procedure will hack your button’s glyph into something that looks nice. You can use fully alpha-enabled PNG files, and they should look right.

Of corse it would be better to create a new button type with this procedure inside that, so you don’t have to call this for every button you want to add a PNG to, but I don’t really feel like re-adding a million buttons, it’s quicker for me to do a million procedure calls :).

« Previous PageNext Page »