Accessing Skype APIs with Ruby

I was fiddling around with the Skype APIs for the past few days and things seem pretty happening in the Skype developer community. The last time I looked at it was a beta of Skype’s very first release and that wasn’t so long ago. It is now at the 3.0 beta release, a release that looks pretty solid to me even though access to the ‘naked’ version of Skype (the Skype engine without actually invoking the Skype client) is still a pipe-dream.

For those who are unaware of a Skype API at all, yes, Skype actually opens up its network and APIs to the public. There is support in for Windows, Linux and Mac (though not in the Windows Mobile, as far as I know). There is also support for Java using Skype4Java and ActiveX using Skype4COM.

I won’t go into the API details but essentially the Skype API allows applications to pass commands to Skype in simple text messages. There are two sets of APIs — the phone API, which is mostly used by device developers (e.g. USB phone manufacturers) and the access API, which is mostly for the desktop developers. I’ll talk more on the access API in this post.

The access API enables external applications to control Skype functions. However before this is allowed, Skype will pop-up the name of the application and asks the user to grant permission to do this. Also, all actions that are done by the external application will be mirrored on the Skype client itself. This can be pretty annoying. The good news is that since Skype 2.6 you can use the ‘silent mode’ to mute this. However you’ll still need to get the user’s permission to execute the application.

There isn’t a Ruby binding of the Skype APIs (at least not that I know of) though you can probably try to go at it through Skype4Java via JRuby.  However there is an alternative if you’re running this on Windows. Ruby provides a very neat and powerful extension (built-in with any Ruby Windows distribution) called Win32OLE that allows a Windows automation client to command or query a Windows automation server. To cut a long story short, you can use Win32OLE to access Skype4COM.

Let me run through quickly how this can be done. Firstly you need to download Skype4COM. This contains a bunch of files, among which the most important is skype4com.dll. You will also use skype4com.chm (the Windows Help API reference file) pretty often. If you intend to run in silent mode, you’ll need to make sure you run at least Skype 2.6 and above. Try Skype 3.0 beta. Just download and install it, you don’t need to do anything else.
Now that you have the files, run this command to register the Skype library:

regsvr32 skype4com.dll

And you’re done. Copy this code somewhere, save it and run it:

# This simple example echos whatever chat message that is sent to you

require 'win32ole'

# create the new Skype automation object
skype = WIN32OLE.new 'Skype4COM.Skype'

# some constants for easy viewing
$RECEIVED= skype.Convert.TextToChatMessageStatus("RECEIVED")
$SAID = skype.Convert.TextToChatMessageType("SAID")

# uncomment the below if you want to run in silent mode. Only works from Skype 2.6 and above
# skype.SilentMode = true

# attach to Skype
skype.attach

# A default handler for any events. You can use this to handle all miscellanous events or if
# you don't have any specific behaviors you want to trigger on
def default_handler(event, *args)
case event
# When someone calls
when "CallStatus"
# do nothing for now

# When any online status changes
when "OnlineStatus"
# do nothing
end

end

# Or you can use a specific method to catch this event
def message_status(msg,status)
# echo whatever is send to you in a chat message
msg.chat.SendMessage msg.body if status == $RECEIVED && msg.Type == $SAID
end

# register to receive events from Skype
event = WIN32OLE_EVENT.new(skype, '_ISkypeEvents')
# on any event at all, go to the default handler
event.on_event {|*args| default_handler(*args)}
# for this specific event
event.on_event("MessageStatus") { | *args| message_status args[0], args[1]}

# loop forever
catch(:done) do
loop do
WIN32OLE_EVENT.message_loop
end
end

This is a simple example, but you can see how powerful it can be. For instance you can grab any chat messages sent to you while you are away and send it to you via SMS. Or turning it on its tail you can set up multiple clients with Skype, and literally send command messages to the various clients to execute. Also, though mashups are more associated with APIs like Google Map or Flickr, you can imagine that Skype is a pretty powerful mashup API as well, mixing it up with the others available out there.

Skype has opened up a Pandora’s box of possibilities with the release of their API. Do check it out.

Thanks

I found this little gem next to the Newton Circus (a traffic roundabout in Singapore, if you’re thinking of the acrobats or horses). Not sure if this is deliberately funny or particularly religious though I suspect the latter. Anyway it brightened up my Sunday morning. Enjoy!

Thanks ...

A primer on the Squeak programming environment

Before we start actually doing anything on Seaside, it’s important to learn a bit on the environment. I’m working on the assumption that, like myself, you know next to nothing about Squeak or Smalltalk. The first thing you need to do is to download the environment from the Squeak website. You should know that Squeak consists of a ‘virtual machine’ that is specific to a platform, and an image (usually .image file). The image file is rather large (usually in tens of MB) but this should not be shocking as it is the complete environment.

Once you have downloaded your VM of choice (from now on, I’ll use Windows since I run Windows most of the time) and an image of choice (I use the one from Seaside), you’re ready to go. Double click on squeak.exe and select your image.

squeak_env.png

Once you get into the environment you’ll see a nice graphical user interface which is quite familiar but yet not familiar. To start an application, you don’t double click but drag and drop it on to the main workspace. There is an application called Workspace, which is ‘console-like’. You can type Smaltalk in it, then right-click and select ‘do it’ to run your script. The shortcut on Windows is use alt-d. For example, to run the the Komanche web server, type ‘WAKom startOn: 8080’, select this line and ‘do it’.

One of the first things you’ll see is the System Browser. You might think it strange but it’s really going to be your main development tool. There are five main panes, 4 of them in the top row and a big one at the bottom row. If you don’t see it, left click once on the desktop (to get the ‘world’ popup menu), select ‘open …’ and then ‘browser’.

squeak_sys_browser.png

Starting from the left, the first pane is the class category pane. Class categories are convenient placeholders for classes, a means of organizing your classes. To add a new class category, right click once and select ‘add item…’. Fill up the input box when it pops up and you have a new class category.

The second pane is the class pane. This pane shows a list of classes for the class category you select. To add a new class, if you expect to right-click the class pane and select ‘add class’ you’ll be dead wrong. I was stumped for a few days on this. Notice if you create a class category ‘Saush’ on the first pane and select it, you will see something like this at the bottom pane:

Object subclass: #NameOfSubclass
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'Saush'

This is the class template. Change #NameOfSubclass to something else e.g. #MyFirstClass (remember to keep the hash), then right click and select ‘accept’ or alt-s to save. You will see a new class appearing at the second pane called ‘MyFirstClass’. At the bottom of the second pane are two buttons, labeled ‘instance’ and ‘class’ respectively. If you click on the instance button you’ll show the instance method categories and methods to the third and fourth panes. If you click on the class button, you’ll show the class method categories and class methods on those panes.

The third pane is the method category pane. Method categories are just means of classifing methods and have no other meaning than that. How do you add a new method category? If you guessed right clicking on the pane and selecting ‘new category’, then you’re absolutely correct! There is a method category called ‘all’ that you can click and display all methods on the right-most pane.

The fourth and last pane to the right is the method pane. If you have followed the above carefully you might have guessed that to create a method belonging to a method category you’ll select the method category, then fill up the template displayed at the bottom pane and save it. The template looks something like this:

message selector and argument names
"comment stating purpose of message"

| temporary variable names |
statements

‘Message’ here means the class method (Smalltalk calls all methods “messages”). Comments are delimited by the ” (whereas most languages use ” for string definition. Whatever you define between the vertical bars ‘|’ are variables you will use in the method. Note that if you create a method when selecting the ‘all’ method category you’ll get a ‘as yet unclassified’ category and your new method will belong to it. To change the classification of the method just drag and drop it to the correct method category.

One of the menu items when you select from any of the panes is ‘FileOut’. If you select this you will create a file out of the item you selected. You can take the file, modify it and do a FileIn from the File List application. Just go to the ‘World’ popup menu, click on ‘open’ and then ‘file list’. Select the file you have just modified, click on the ‘file in’ button at the top of the application.

If you look carefully at the file that you generated from FileOut you’ll see the method categories are bounded with ‘!’. You need method categories. If you create a method without a method category you can’t do a FileIn anymore.

Play around a bit more with the System Browser until you’re comfortable. You’ll be using it a lot in my next post on creating a Seaside application.

Seaside, Squeak and Smalltalk

I had an interesting chat with Nick last week and he mentioned the concept of continuations to me. One thing led to another and soon I was mucking around with an web application framework called Seaside. Seaside is quite a different type of web application framework from what I’m used to (J2EE-types, Struts, Webwork or even Ruby on Rails). For one it’s a continuations-based web application framework. Also, it’s a web application framework built with Smalltalk. Yes, Smalltalk.

That’s a language I’ve not heard for a long time. I remembered learning about Smalltalk last during my university days and not much about it since. Smalltalk, for those uninitiated, is the granddaddy of all object-oriented languages, first introduced about 35 years ago in 1971 but really made it as a programming language as Smalltalk-80 (in 1980 of course). It’s the first language that has the ‘everything is an object’ paradigm. Seaside runs on a couple of variants of Smalltalk but the one that I used is Squeak. Squeak, derived from Smalltalk-80 is an open source Smalltalk variant developed originally by Apple programmers in 1996 and currently has an active development community.

But what’s so special about Seaside besides being a web application framework done in a niche programming language? Without going into the details (that’ll take a lot of writing), Seaside provides some interesting features that I’ve not seen in any other web application framework I know. For example, Seaside encourages developers to create web applications with a macro view of the application flow instead of individual page flows. Web applications are made from highly re-usable components (really Smalltalk objects) which are not tied to the flow of the application, can have its own control flow, its own state and contain can other components. Seaside allows developers to model application flows in a single piece of code compared to modelling it in disparate HTTP request handlers (think servlets in J2EE or action classes in Struts or controller methods in Rails). Frameworks like Struts or Webwork tries to model this kind of flow in static XML configuration files, which is at best, a hack. Rails tries to do this in its own code by convention, which is a good attempt but the way Seaside does it is the best I’ve seen so far.

Seaside is full of interesting bits and pieces done by various members of the Seaside community, which I’m just barely touching the tip of the iceberg. Ajax is supported through the inclusion of Scriptaculous, the incredibly useful library by Thomas Fuchs. Connectivity to relational databases like MySQL and PosgresSQL is available, though connecting to object-oriented databases like GOODS is more natural. There are also OR mapping libraries, and all the normal stuff you’ll expect from a web application framework.

However Seaside is not all a bed of roses. Firstly if you’re like me, coming from a mainly C++ and Java background, you’ll find Smalltalk a challenge to even read (though you can try ‘I Can Read C++ and Java But I Can’t Read Smalltalk‘). The Squeak environment is Windowed and GUI, which is familiar but not so familiar. The environment is based on the concept of ‘images’ that are snapshots of the entire environment. Development is through a built-in Systems Browser and incredibly also at the web browser (I kid you not) which fascinated and freaked me out a bit initially. But like most new tools, once you get used to it, it becomes more natural and comfortable.

I’ll be doing more write-ups on Squeak and Seaside in the next few blog entries. Stay posted!

Some good links to learn about Seaside besides the official web site.