PluginDevelopersGuide

From AMSN
Jump to: navigation, search

Contents

What Is An aMSN Plugin?

Plugins extend the functionality of aMSN. Some plugins (such as the Nudge plugin) are included with aMSN. Others are avaliable on the plugins page of the aMSN website.

Back to top

What Do I Need To Create A Plugin?

All you need is the latest version of aMSN, and a plain text editor (not a WYSIWYG editor like MSWord or OOWriter, but something like gedit on Linux, Smultron on Mac OS X, and Notepad2 for Windows).

A knowledge of Tcl/Tk would also help!

Back to top

What Is The Directory Structure Of A Plugin?

The most basic plugin requires one xml file called plugininfo.xml, and a Tcl source file. The plugininfo.xml file should be layed out like this:

<?xml version="1.0"?>
<plugin>
  <name>The Plugin's Name</name>
  <author>Your Name</author>
  <description>A short description of your plugin</description>
  <description_fr>A translated description in French (fr).</description_fr>
  <amsn_version>The oldest version of aMSN the plugin will work with.</amsn_version>
  <plugin_version>The plugin's version.</plugin_version>
  <plugin_file>the name of the source file (ie. pluginName.tcl).</plugin_file>
  <plugin_namespace>Your plugin's namespace (only A-Z,a-z,0-9 characters here).</plugin_namespace>
  <init_procedure>The name of your init procedure.</init_procedure>
  <deinit_procedure>The name of your deinit procedure.</deinit_procedure>
</plugin>

Your tcl source file must have the namespace described in the xml file, and the init & deinit procedures must also exist within your plugins namespace or your plugin will not load.

Your Tcl source file should look like this:

namespace eval ::namespace {
  proc init { dir } {
    ::plugins::RegisterPlugin "Plugin Name (As In The XML File)"
    ::plugins::RegisterEvent "Plugin Name (As In The XML File)" postEvent localProcToCall
  }

  proc deinit { } {
    #Clean up?
  }
}

Back to top

How Do Plugins Work?

Plugins rely on events in aMSN called PostEvents. These are called when events happen, such as changing state, or a new message is recieved or another similar event.

List of events

Here is a full list of events (SVN r8478):

FileName or Event Parameters Description
abook.tcl
parse_nick variable login Before a nick is stored into abook.
automsg.tcl
ChangeMyState automessage idx When the user changes his state.
chatwindow.tcl
chatwindow_closed chatid When a window is destroyed.
new_conversation chatid usr_name When a window is created
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.
chatwininput input buttons picture window
chatsendbutton window_name bottomleft
TopUpdate chatid win_name user_list When the top of the window is updated with the user names and states.
gui.tcl
chat_ink_send nick ink chatid win_name Before an ink is sent.
chat_ink_sent nick ink chatid win_name After an ink is sent.
user_joins_chat usr_name chatid win_name When an user joins a chat.
user_leaves_chat usr_name chatid win_name When an user leaves a chat.
chat_msg_send nick msg chatid win_name fontfamily fontstyle fontcolor Before a message is sent.
chat_msg_sent nick msg chatid win_name fontfamily fontstyle fontcolor After a message is sent.
chat_msg_receive user msg chatid fontformat message Before a message is recieved.
chat_msg_received user msg chatid fontformat message After a message is recieved.
mainmenu menu When the main menu is created.
new_conversation chatid usr_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 colorbar 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.
ChangeMyState automessage idx When the user changes his state.
right_menu menu_name user_login
xtra_choosepic_buttons target win
loging.tcl
ft_loged email txt When a filetransfer is logged
msnp2p.tcl
WinkReceived chatid filename When a wink is received.
plugins.tcl
Load name status When a plugin is loaded.
PluginConfigured name When a plugin's configuration is being saved.
protocol.tcl
contactlistLoaded
DataCastPacketReceived chatid typer nick msg id data
PacketReceived chatid typer nick msg
ChangeState user substate When a contact change his/her state.
UserConnect email user_name When a contact get's connected.
OnConnect When a contact get connected.

You subscribe to PostEvents, and when they occur, a specific procedure (which you select) in your plugin will be called. The parameters that occur with a PostEvent are variables which you can read and write to. You can therefore alter the way aMSN functions.

Back to top

How Do I Subscribe to a PostEvent?

This is done during your plugin's init procedure. First you must register your plugin by running this:

::plugins::RegisterPlugin "Plugin Name (As It Appears In The XML File)"

You can then subscribe to a PostEvent by calling this function in your code:

::plugins::RegisterEvent "Plugin Name (As It Appears In The XML File)" postEvent functionToCall

Your functionToCall must have two arguements: event & epvar. For example:

proc functionToCall {event epvar} {
  #Interesting stuff goes here!
  return 1
}

Back to top

How Do I Access/Modify Variables Sent By A Post Event?

The argument "epvar" set by the PostEvent is an array of all the various parameters that are avaliable for the post event. At this point you need to decide if you want a copy of the variable, or if you want to modify the variable (so that aMSN will use your version of the variable instead of it's own).

To Get A Copy Of A Variable

Run this in the function called by the post event:

upvar 2 $epvar args
set localVariableName $args(parameterName)

Any changes you make to localVariableName, will not edit the way aMSN functions.

To Modify A Variable

Run this in the function called by the post event:

upvar 2 parameterName parameterName

You can then refer to the parameterName variable, and any changes you make will be reflected back to the copy that aMSN uses.

Back to top

How Do I Make My Plugin Configurable?

You need to add a list of configurable options for your plugin inside it's namespace. Not inside any of the procs, but just inside the namespace. The options for the type of data you can store are as follows:

DataType Description
str String (Plain text).
pass Same thing as str, but for password.
bool Checkbox (1 or 0, activate or desactivate).
rbt RadioButton (Returns the index number of the selected radio button).
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.

Here's an example of a plugins configlist:

set ::namespace::configlist [list \
  [list str "Label" variableName] \
  [list pass "Label" variableName] \
  [list bool "Label" variableName] \
  [list rbt "Item 1 Label" "Item 2 Label" indexNumberOfCurrentRadioButton] \
  [list ext "Button Text" command] \
  [list label "Label Text"] \
  [list lst "Item 1" "Item 2" selectedItemName] \
]

To set default values for your plugin, then place this in your init proc. If the user changes a value, then the user's choice will override your default values:

array set ::namespace::config {
  variableName {"defaultValue"} 
}

Back to top

How Do I Make My Plugin Translatable?

First create a folder inside your plugin called lang. Then create langfiles within this folder with their calling the files lang followed by their locale name. IE for an English lang file, you would put langen. The structure of a langfile is as such:

item1 Translated text for item 1.
item2 Translated text for item 2.

You must also place these lines in your init proc (which must have $dir as an arguement):

# Load english by default, then load the current locale if it's avaliable.
set langdir [file join $dir "lang"]
load_lang en $langdir
load_lang [::config::getGlobalKey language] $langdir

Back to top

Personal tools