Intro
The current capabilities of what a plugin can do is very limited. Although there are some useful plugins now (OsdPlugin, RmsPlugin to name a few) it is impossible to write an encryption plugin for Licq. That means all types of encryption must be integrated into the daemon, which is far from optimal. The new API that is described here will allow all forms of plugins to be made, such as a spell checker or encryption plugins. These kinds of plugins will modify outgoing/ingoing events without any user interaction. This kind of system will require a priority based pipeline for the daemon to pass data to the plugins as it goes from receiving input to actually doing the final action. This document will describe the plugin API for General Plugins (GUI, Functionality) and Protocol Plugins. It is very important to note the difference here of these plugins. A protocol plugin is strictly a plugin that will interact with a network based protocol, such as MSN, Yahoo, Oscar.
General Plugin API
Below is a working draft of the new proposed General Plugin (GP) API. At the moment, it is a draft so it is under discussion and will have some changes. This is not a final draft, so don't start making plugins yet!
Plugin Registration
A plugin will do the following when it is loaded:
- Connect events that it expects to callbacks.
- Setup anything it needs in order to be executed (ie create a GUI, open up file I/O, etc)
Registering Callbacks
All plugins will register callbacks with the registerCallback function. It supports non-member functions and class-member functions. Here is some code to register a callback with a normal non-member function the following code will do the necessary work:
Licq::IDaemon *d = Licq::IDaemon::daemon();
d->registerCallback("signal-name", myCallback, nPriority);
For member functions, an instance of the class is necessary and so is the usage of a helper function. Here is an example:
Licq::IDaemon *d = Licq::IDaemon::daemon();
boost::shared_ptr<CClass> callbackInstance(new CClass);
Licq::TCallback callback =
Licq::createMemberCallback(&CClass::myCallback, callbackInstance);
d->registerCallback("signal-name", callback, nPriority);
More details about Licq::IDaemon will be given later...
Receiving Events
Callback functions are used, so to receive events... your callback function gets called. It's that simple! Here is some sample code to match the code from above.
void CClass::handleStatusChange(void *cbData)
{
CStatusChange *p = static_cast<CStatusChange *>(cbData);
// Do stuff with the data
}
Sending Events
Plugins need to interact with protocols by sending events to them. The structure of these events is more defined, but still flexible to new events that protocols implement. Let's take a look at the following code to get a better feel about how this works.
user->sendEvent("send-message", pMsgData);
daemon->pushToProto(pOwner->protocolId(), "change-status", pStatusData);
Hmm, that was simple, wasn't it? The main idea here is that you need 2 things when you send data to a protocol plugin. The first example is for a user event, user->sendEvent calls the function that handle pushing the data to the correct protocol plugin instance. "send-message" is the event we are pushing to the specified protocol and pMsgData is a pointer to the ProtocolEvent structure. In the second example, we are changing our status for the protocol specified by the protocol Id of pOwner. "change-status" is the event and pStatusData contains the specific information about changing our status.
The ProtocolEvent structure provides an abstract way for plugins and protocol plugins to communicate with each other. The daemon will just push the events around to the proper plugins. This way makes the plugins able to support events that the daemon doesn't know anything about.
Modifying GUI
General Plugins should be allowed to modify the user interfaces that other plugins provide. For example:
- Adding menu items to the main menu
- Adding menu items to the user menu
- Specifying an options tab
API Structures
Protocol Plugin API
Plugin Registration
When a plugin is loaded by request from the user, it will have to perform some basic initialization to interact with the daemon. The daemon will create a ProtocolPluginId for the protocol instance that will be used from all plugins to reference this protocol instance.
Receiving Events
The Protocol Plugin API will receive events in the same manner as the General Plugin API. It will create LicqCallbacks? with the daemon. The parameter list will be exactly the same in order to be compatible with both types of plugins.
Sending Events
Protocols need to send signals of events to the protocol list. It will do this by telling the daemon, and then the daemon will pass it on to all appropriate plugins. When there is an event to notify the plugins of, the following function will be used:
boost::shared_ptr<CEventData> pData(new CEventData);
pData->setData("userId", nUserId); // implied setData<int>
pData->setData<EStatus>("newStatus", STATUS_ONLINE);
pData->setData<time_t>("timestamp", time());
daemon->pushToPlugins("user-changed-status", pData);
Additional data can be retrieve from the CLicqUser object, if necessary.
Modifying GUI
Protocol Plugins should be allowed to modify the user interfaces that other plugins provide. For example:
- Adding menu items to the main menu
- Adding a special owner menu item, for each owner.
- Adding menu items to the user menu
- Specifying an options tab
API Structures
GUI Considerations
Both general and protocol plugins need to modify the way Licq is shown to provide the functions they provide. The new version of Licq will be designed to allow the maximum amount of flexibility to the plugins to alter the GUI. Here is a list of plugin ideas and what they will need to modify. Please edit this freely, but when you do so, send an email to Licq-Devel about your changes.
- History Plugin - Provide a fully-featured history browser plugin
- Add a "View history" item to the all users' popup menu.
- For each owner, add a "View history" item to each owner's sub menu (for viewing system messages).
- In all message windows, add a button to view history.
- Add a tab to all users' info window, for displaying the actually history.
- Basic Protocol Plugin - Provide use to a different messaging protocol
- Add an owner sub menu to the main menu for each owner
- Auto-reply Plugin - Reply to messages automatically (i.e. a chatbot)
- Add an auto-reply history menu item to the main menu
- Encryption Plugin - Encrypt messages in a conversation
- Indicate when the conversation is encrypted (how? - a line in the conversation window should notify about it - or can the gui plugin do that by itself?)
- Add an encrypted indicator icon to the contact list window
- Add an encrypted tooltip in the contact list window
- Add an option in the user's menu to set the policy for this user (OTR has 4 states)
- Shake Window Plugin - Move the window to attract attention
- Add an option in the user's menu to enable/disable this per-user
- Shake the conversation window, which requires getting the Window Id
