Dev:Plugin Developer Guide

Jump to: navigation, search



This tutorial is written for amsn's plugin developers by amsn team. It intends to make people out of amsn team to participate coding plugins and they don't have to know nothing about amsn except the things explained in this guide.

Getting Started

aMSN looks for plugins in a directory called plugins in 3 places. One is AMSN's main directory. Another is the AMSN's configuration directory (~/.amsn/ for Linux). And the last one is user's profile configuration directory. Your plugin should be placed in one of these places in it's own unique directory. We will refer to this 'unique directory' as plugin's dir.

Your plugin must have at least 2 files: an xml file (plugininfo.xml) and your tcl plugin main file.

First of all, we'll take a look at plugininfo.xml (amsnplus example):

 <?xml version="1.0"?>
       <name>aMSN Plus</name>
       <description>aMSN Extension (commands in chat window, coloring nicks...)</description>
       <description_fr>The same description, but in french</description_fr>

Note : the <description_fr> field is only avaible since amsn 0.96, but is compatible with 0.95, but not 0.94 :(. "fr" is the langcode used for the translation. Refer to the Lang_HowTo in order to know what is the code you should use.

It is very easy to understand but be careful with amsn_version. This is the plugin requirement to rule, in this example, with amsn 0.93 or older, plugin won't load so, if you require a post event that was added after 0.94, you have to put 0.95 here.

After this xml file is read, amsn will source the plugin_file and execute the init_procedure in plugin_namespace, so be careful and verify the xml file is well done, otherwise it won't work properly.

Then, we have to take a look at plugin file. Let's see the init proc (amsnplus example):

 proc amsnplusStart { dir } {
               ::plugins::RegisterPlugin "aMSN Plus"
               ::plugins::RegisterEvent "aMSN Plus" chat_msg_send parseCommand

The init proc has one parameter: dir and must be in the plugin namespace.

 ::plugins::RegisterPlugin "aMSN Plus"

This registers the plugin with plugin name. You must register the plugin with its name, equal than you've put in the xml file, otherwise it won't work fine.

 ::plugins::RegisterEvent "aMSN Plus" chat_msg_send parseCommand

RegisterEvent binds a procedure to a event. It takes 3 arguments. First is the name of the plugin where the proc is, then the event (look at the bottom), and finaly the procedure to execute on this event (must be in the plugin namespace). So we just say that when chat_msg_send event occurs, amsn will execute ::amsnplus::parseCommand with the event parameters.

Now the plugin loads and the binding is done but, we have to create the procs to execute when the event occurs. We'll take a look at an example:

 proc parseCommand {event epvar} {   

This proc must have 2 arguments: event (the event that calls this proc) and epvar (the information sent to this proc). Now we have to get the parameters sent by epvar. We have to choose: get a copy or get feedback.

To get a copy

 upvar 2 $epvar args
 set nick $args(nick)  

Note that if you want to get 3 variables from epvar, you only have to do the 1st line one time.

To make feedback

 upvar 2 nick nick  

If you choose to make feedback you should know that if you modify the variable, you'll modify the original one, so be sure that you don't make bugs in amsn.


It is also possible to configure a plugin! You have to add some lines in the init proc:

 array set ::amsnplus::config {
     colour_nicks {0}

This creates the config.

 colour_nicks {0}  

And creates a config parameter so colour_nicks it is configured by default to 0.

But to be configurable, we have to do this:

 set ::amsnplus::configlist [ \
      list [list bool "Colour Nicks?" colour_nicks] \
 list [list bool "Colour Nicks?" colour_nicks]  

Not the tricky part of the whole process. The configlist variable in the amsnplus namespace is a list containing lists. We call those lists in the list config data. These config data lists have 3 items. First is the type of the item, second is the title of the item and 3th is the key in the config array it belongs to. The Plugins System parses this list and creates specific fields for it. The possible items type are:

  • str  : Text label
  • pass  : Same thing than str, but for password
  • bool  : Checkbox (1 or 0, activate or desactivate)
  • rbt : RadioButton
  • ext  : Action button, the 3rd key here is the command we give to the button
  • label : Just a place to write some text to describe all the configuration stuff
  • frame: Frame to put your own custom stuff in, third argument is a proc (with namespace) that takes one argument which will be the path to the window
  • lst  : A listbox of items where one will be selected. 3rd is a list of values and 4th is the name

Now to use the configuration, all you have to do is access the config array in your plugins namespace.


Got problems? Just use AMSN's internat status system. First, put calls to plugins_log procedure. It takes on two required arguments, the plugin name and the message. To see the messages, press Alt+P (or Meta-P on Mac OS X) in AMSN to get the plugins log screen. Also if you want to know what is happening in the internals of aMSN, press Ctrl-S (or Command-S on Mac OS X) and you will the a status screen which is a plugins_log of the core.

Translation Support

If you want translation support, you have to add a folder inside you plugin called lang and put inside the lang files called the same way amsn does (take a look at amsn's lang folder). Then, in the plugin's init proc, you have to add:

 set langdir [file join $dir "lang"]
 set lang [::config::getGlobalKey language]
 load_lang en $langdir
 load_lang $lang $langdir

The first line append /lang to the plugin dir because load_lang will look at plugins' lang folder, not plugins' folder. The second line gets the language that's been using. The third line load the default langen (english) file, that way, if a user use a language that is not inside the lang folder, he will get the english keys instead. And the fourth line calls load_lang to load all the plugin translations. You have to note that if you put a wrong path to the lang files, it won't break anything and you can't replace any amsn translation, it won't be replaced! You should ALWAYS ship the langen file (english lang files) by default for ALL your lang keys. This is the main language files.

Post Events

Here is the list of the Post Events classfied by files (this might change so check it in the files by doing, fo example, in the msn directory : grep PostEvent * ). If you commit something and add a Post Event, please tell to the list or add it in the wiki.

 proc -> parameters -> description


parse_nick -> data -> before a nick is stored into abook.

getDisplayNick -> nick customnick globalnick psm user_login -> called when contact list is drawn.


chatmenu -> window_name menu_name -> when the chat menu is being created

chatwindowbutton -> window_name bottom -> when the buttons in the chat window are being created

new_chatwindow -> win -> when a new chat window is opened.


chat_msg_send -> nick msg chatid win_name fontfamily fontcolor fontstyle -> before a message is sent

chat_msg_sent -> nick msg chatid win_name fontfamily fontcolor fontstyle -> after a message is sent

chat_msg_receive -> user nick msg -> before a message is recieved

chat_msg_received -> user nick msg -> after a message is recieved

main_menu -> menu -> when the main menu is created

new_conversation -> chatid user_name -> when a new conversation begins

WinWrite -> tagname winname msg -> before text is written to the window

WinWritten -> tagname winname msg -> after text is written to the window

OnDisconnect -> email nick -> when you get disconnected

ContactListColourBarDrawn -> text -> Straight after the colour bar is drawn in the contact list

ContactListEmailsDraw -> text msg -> just before the emails line is drawn in the contact list

ContactListEmailsDrawn -> text -> straight after the emails line is drawn in the contact list


Load -> name status -> when a plugin is loaded

Unload -> name status -> when a plugin is going to be unloaded

PluginConfigured -> name -> when a plugin's configuration is being saved


ChangeState -> user substate -> when a contact change his/her state

UserConnect -> user user_name -> when a contact get's connected

OnConnect -> email nick -> when a contact get connected


ChangeMyState -> automessage idx -> when the user changes his/her state


If you want your plugin to be automatically updated, write this into the plugininfo.xml file :

For updating the main file:

 <cvs_version>The CVS version corresponding to the version you want to release</cvs_version>

For updating the language files:

     <langcode>The langcode of the language (ca, fr, en, es, ...)</langcode>
     <version>The CVS version of the language</langcode>

For updating the other files:

     <path>The path of the file</path>
     <version>The CVS version of the file</version>

For instance, with the Nudge plugin:


You can also defined URL (for instance, for external plugins)


The URL can contains variables :

 main : $version
 lang : $version and $langcode
 file : $version and $file (for the path)

Example for growl plugin


See also

Personal tools