zomgistania

Main page | About | Articles | Previous Posts | Archives

Wednesday, September 27, 2006

Widget stuff

Recently I posted how to save data from widgets to a file to the Opera forums... thought maybe I should put a link here too.


There are three new widgets I've been working on: Jack Bauer facts, IRC Listener and Online Player Search.

Jack Bauer facts is pretty basic stuff code-wise... it loads an XML file using XMLHttpRequest, which contains "facts" about Jack Bauer. Then it starts displaying facts about him. It's pretty funny, and I was going to make a Chuck Norris facts widget but someone beat me to it! :]


IRC Listener is a bit more special piece. I might've mentioned it in the posts about Server-Sent Events. I used the Python SSE framework I made to create an SSE backend which sends the client my IRC logs from some channels. The IRC Listener widget uses this backend and lets the user watch the chat in the channels. It also let's the user pick which channel he/she wants to listen to. I won an Opera 9 t-shirt + some swag for this duo.


The third one, Online Player Search, was also a t-shirt competition inspired one. Using the service at gametiger.net, it lets you to search for players in online games. It's pretty neat, say your friend plays a lot of Counter-Strike under name "Pete", you can just type in "Pete", choose "Counter-Strike" and hit search. The widget then displays you a list of all Petes playing CS it found and the server IPs.



I'm also working on a game which uses SSE and JS. I'll leave it in the dust for now as I've had several problems (related to bugs in the browser) so I don't know if I'm going to get it done to even so much that I can mention it here :]

Labels:

Monday, September 25, 2006

Recipe for success: Lack of sleep

I always get my best ideas when I'm tired! Same happened again just an hour or so back...

I thought.. could I make the floppy drive crucnch? Like if it was trying to read a floppy.

This idea sprung from the fun I had had with the beeper program: I ran it on a computer at school and the few guys there thought the computer was gonna blow up and backed away from it... it was a pretty fun sight ;)


So I thought that making the floppy drive crunch would be a nice effect for fooling with people...

Let's see: if I try to read all files from the disk, will that cause a noise even if there's no disk in the drive? Yes!


So let's put that on an endless loop.... *DURRRRRRRRRRRRRRRRRRRRRRRRRR*

Got my floppy noise... but hey, maybe I could make the CD tray open and close? That's simple. Just some mci stuff.


So now I have a crazy beep, a scary floppy drive noise and a cd tray which opens and closes on its own. What more?

How about the harddisk making a noise? Sure, why not...

This one was a bit more complicated as it seemed just getting all files from C wouldn't make a good noise for long so I thought I'd just loop through all drives, all folders and so on again and again, but to do that I needed a list of all hard disks.

After getting the list, making the file looping was simple.


Okay so I had together the ultimate "scare your computer illiterate friend" program... but I wanted to add more!

I know, let's make it so that every window disappears and reappears and that loops again and again! I called this the -madness parameter. It is pretty intense actually.

Madness is so mad, that it's even quite difficult to stop it! Press ctrl-alt-del and go to task manager... no! The task manager starts blinking!.. you gotta be pretty fast to stop the madness ;)

I tried using my old global keyboard hook code to create a stop command for it. The global keyboard hook would read even if the application itself wasn't visible, so it should've done the job... but it appears it didn't work in a console application and I was too lazy to make it a windows forms app. Oh well... :]


To experience the madness or scare your friends, download the exe. Parameters for the exe are -disk, -beep, -cd, -drives, -madness and -all.

-disk makes the floppy crunch, -beep beeps like a crazy, -cd opens and closes the cd tray, -drives crunches the HDD, -madness makes windows flip out and -all does everything EXCEPT -madness.. so to get everything, you need to type funnay.exe -all -madness


NOTE: If -disk breaks your floppy drive or a floppy disk inside the drive, I'm not responsible. I don't know if the drive can take the constant polling for very long periods of time.

Labels:

Saturday, September 23, 2006

Bettering the input boxes

I was playing around with JS again and was looking at my old messagebox code... which I deemed crap.

So I just took it from the start and made a completely new class for showing boxes which can be used for asking for user input or just displaying info like alert() and such.


function GenericBox(cssclass, titletxt, messagetxt, showInput, showButton, validatorFunc)
{
//this function is called when the user presses the OK button
var validator = validatorFunc;

//Save a reference to this object for later
var self = this;

//create the div for the messagebox
//the box is just defined in CSS and the CSS class it uses
//is defined in the parameter cssclass
var element = document.createElement('div');
element.className = cssclass;


//create the title
var title = document.createElement('h1');
title.innerHTML = titletxt;
element.appendChild(title);

//create the message
var message = document.createElement('p');
message.innerHTML = messagetxt;
element.appendChild(message);

//create the input box
var input = document.createElement('input');
input.type = 'text';
input.onkeydown = function()
{
if(!e) var e = window.event;

//if the user presses enter when in the input,
//call the validator function with a reference to
//this object and the value of the input field
if(e.keyCode == 13)
validator(self,this.value);
}

//hide input if user doesn't want to show it
if(!showInput)
input.style.display = 'none';

element.appendChild(input);

element.appendChild(document.createElement('br'));

//Create the OK button
var button = document.createElement('input');
button.type = 'button';
button.value = 'OK';
button.onclick = function()
{
//when the user clicks this we send the data to the func
validator(self,this.previousSibling.previousSibling.value);
}

//again, hide if not wanted
if(!showButton)
button.style.display = 'none';

element.appendChild(button);

var visible = false;

//used for showing the box
this.Show = function()
{
if(!visible)
{
document.appendChild(element);
visible = true;
}
}

//used for hiding the box
this.Hide = function()
{
if(visible)
{
document.removeChild(element)
visible = false;
}
}

//use this to change the message
this.SetText = function(newtext)
{
message.innerHTML = newtext;
}

//this can hide the inputs in the box
this.HideInputs = function()
{
input.style.display = 'none';
button.style.display = 'none';
}
}


The basic use is pretty simple again...

function ShowBox()
{
var box = new GenericBox('genericbox','Example','This is an example box',false,true,HideMe);
box.Show();
}

function HideMe(obj,input)
{
obj.Hide();
}


When calling ShowBox, the user would get a box with title "Example" and text "This is an example box" which has a button OK. When the OK button is pressed, HideMe function gets called. The HideMe function just uses the reference to the object and hides it with the Hide() function.

Pretty simple huh?

the CSS class for the box should at least contain the details on the box like position: absolute and it's left and top position and width and height and such.


If the above code would've set the showInput to true, the input parameter in the HideMe function would contain the data in the input field.


The SetText and HideInputs functions are there so you can re-use the box a bit... say, you're sending the data from the input box to a web page so you could do something like first use HideInputs to hide the inputs and then SetText and change the message to something like "Working..." so the user knows you're processing the data.

Labels: ,

Thursday, September 14, 2006

Beep beep.

Being somewhat bored and such again, I figured out a way to use the PC Speaker to play sounds with C#. It's actually pretty simple, just use the winapi Beep() function.

Of course that's not all! I made a small class which can be used to play songs (or annoying beeps) with the PC speaker and a console app which uses it.

The notation is simple enough: ,

Labels: , ,

Sunday, September 10, 2006

Gravity and collisions

I was kind of bored yesterday, so I made this with JavaScript.

Doesn't require much code to get a realistic-ish looking bouncing done.
It has a few flaws though... the ball goes like one of those superballs when it goes up or down which isn't necessarily a bad thing but for anything else than a superball simulation...

Labels: ,

Saturday, September 09, 2006

Writing SSE backends with Python

And here we go again with the snake...

As I mentioned in the last post, I wrote this server script for SSE in Python.

Well, I thought it would be more worthwhile to turn it into a framework kind of thing, on which you can easily build your SSE backends.


Warning: the code and stuff are in Python and I'm not going to go into details about the language here. I'll just describe the functions and classes in the framework.


The basic implementation is built on the Twisted networking framework for Python. If you want to know more about Twisted, you can find their docs from their page.


My framework consists of three classes: the SSEClient, SSEServer and Service classes.

The SSEServer class is the "main" processor. It handles reading the console for input, pinging users and sending requests to the correct Services.


The Service class is what the programmer will be mainly using.


The SSEClient is used as the client for the services. It contains the SSE request and methods to write data to the stream and such.


You can download the framework from here.

An example Service made with the framework can be downloaded from here.

The example service can be run with Python with python sseexample.py. It starts the server in port 3080.


Descriptions of the classes

SSEServer:

example = SSEServer(services,True,True)

the SSEServer takes three parameters:
a dict of the services
True/False if you want it to ping users automatically
True/False if you want it to read console input

the format for the service dict:
{'/service/path': ServiceClass(), '/second/service': SecondClass()}

For example, if you set the path to '/', the service is accessible with http://yourserver:port/ and if you set it to '/example', it's accessible with http://yourserver:port/example.




Service:

example = Service('Service name')

Service takes one parameter: the name of the service. The service itself does nothing, so you will have to make your own class which inherits from it.

Service functions:

parse(request) - this is called when a client wants to access the service. Override in your own class

findClient(request) - can be used to see if the user has already opened an SSE session. Returns the SSEClient if found, otherwise None.

startSession(client) - used to start a new SSE session. Pass an SSEClient as the parameter. After the session is created, it sends the clients session-id. Format:
Event: session-id
data:

broadcast(type,message) - sends a message to all clients. type is the event type and message is the data for the event

ping() - sends a ping to every user who hasn't received a message in the last 60 seconds. Used automatically by the SSEServer pinger.

drop(client) - removes a client from the list. Parameter is an SSEClient


SSEClient

example = SSEClient(service,request)

Parameters for the SSEClient are the "owner" service and the client's request.

You can override the SSEClient so you can add more variables to it, like the users name in a chat or something like that.

functions:

stop(reason) - automatically called when the users connection is closed. Calls the parent services drop method.

sendMsg(type,data) - send a message to the client. type is the event type and data the event data. The data can also be a list and it will be handled properly.




There we go. Feel free to ask if you have anything on your mind.

Labels: , ,

Wednesday, September 06, 2006

Server Sent Events: The new chapter in AJAX

Opera 9 features some of the Server-Sent Events features from WHATWG Web Applications 1.0 spec.

But what on earth is that? Well, basically it means that your web page listens to messages from the server! You don't need to do XmlHttpRequests to the server to ask for more data, the server just sends the data to you instead.


A good example of this technology is the Opera Web Chat. Note that it only works in Opera at the moment, as no other browser yet supports SSE.


I created a IRC log forwarder server using Python and Twisted. I first tried using PHP, but I found that it was much easier to have a dedicated server application running and serving clients than trying to keep track of them with PHP, which also seemed to have trouble keeping track of whether the user was disconnected from the page or not. Could've been a problem in my PHP configuration as well, but so what if I can do it easily with Python.


If you are using Opera, you can find the log forwarder from http://iikeli.ath.cx:3080/

to choose a channel use the channel get parameter, ie.
http://iikeli.ath.cx:3080/?channel=lounge for #lounge and
http://iikeli.ath.cx:3080/?channel=opera for #opera

If no channel is selected, it defaults to #opera.

At the moment there are only #opera and #lounge from irc.opera.com available, but I might add more if someone asks me to.

Example HTML page which uses this can be found at http://iikeli.ath.cx:3000/projects/sse/irclog.php
The channel get parameter works with that as well.


I will post the source code for the server script later so hopefully others can learn from it.


For more details on the implementation of SSE in Opera and sample code, visit the Opera Web Applications blog

Labels: , ,

Monday, September 04, 2006

Taskbar Arranger

Here's something I made recently... a taskbar arranger tool.

It's pretty useful if you have lots of programs running, as you can sort the taskbar in such order that the important programs are leftmost or such.

You can download the .exe from here


I've also uploaded the source-code for the app, which is downloadable from here.

Written in C# as usual and it uses some Windows API functions which aren't available in native C# with P/Invoke.

Labels: ,