Sylpheed Plugin Specification
=============================

The following is the architecture of plugin system of Sylpheed.

 +----------+    +----------------------+     +-----------+
 | Sylpheed |----| libsylpheed-plugin-0 |--+--| Plug-in A |
 +----------+    +----------------------+  |  +-----------+
   Sylpheed         Plug-in interface      |   Plug-in DLL
                    library             +--+
        |        +------------+         |  |  +-----------+
        +--------| libsylph-0 |---------+  +--| Plug-in B |
                 +------------+               +-----------+
                 LibSylph mail library

Sylpheed loads the plug-in DLLs installed in the plug-in directory on
startup.

Plug-in can only access the functions of Sylpheed through the APIs provided
with libsylpheed-plugin-0 and libsylph-0 library.

There are two kinds of plug-in API. One is called directly from plug-ins,
another one utilizes the signal mechanism of GObject and calls the callback
functions on specific events.

The plug-in system is implemented in libsylph/sylmain.[ch] and
src/plugin.[ch].


Plug-in API
===========

Functions used by Sylpheed
--------------------------

-------------------------------------------------------------------------
void syl_plugin_signal_connect  (const gchar *name, GCallback callback,
                                 gpointer data);

Connects to signals available with SylPlugin object (obtained inside library).
The specification of callback functions that receive signals is similar to
that of normal GObject.
Refer to the signals list for available signals.
-------------------------------------------------------------------------
void syl_plugin_signal_disconnect(gpointer func, gpointer data);

Disconnects signals connected by syl_plugin_signal_connect().
-------------------------------------------------------------------------
void syl_plugin_signal_emit(const gchar *name, ...);

Emits SylPlugin object signals.
-------------------------------------------------------------------------
gint syl_plugin_init_lib        (void);

Initializes the libsylpheed-plugin-0 library.
-------------------------------------------------------------------------
gint syl_plugin_load            (const gchar *file);

Loads plug-in DLL files into memory.
-------------------------------------------------------------------------
gint syl_plugin_load_all        (const gchar *dir);

Loads plug-in DLL files in the specified directory into memory.
-------------------------------------------------------------------------
void syl_plugin_unload_all      (void);

Unloads all loaded plug-ins.
-------------------------------------------------------------------------
GSList *syl_plugin_get_module_list      (void);

Obtains the list of plug-ins loaded into memory.
It returns the list of pointers to GModule struct.
The list is obtained by the library internally, so it must not be freed.
-------------------------------------------------------------------------
SylPluginInfo *syl_plugin_get_info      (GModule *module);

Obtains plug-in information. The information is returned as SylPluginInfo
struct.
-------------------------------------------------------------------------
gboolean syl_plugin_check_version       (GModule *module);

Compares plug-in interface versions and checks if the plug-in is compatible.
Returns TRUE if the version matches, FALSE otherwise.
-------------------------------------------------------------------------
gint syl_plugin_add_symbol              (const gchar *name, gpointer sym);

Registers symbol name and pointer value related to it to the library.
-------------------------------------------------------------------------
gpointer syl_plugin_lookup_symbol       (const gchar *name);

Searches symbol registered by syl_plugin_add_symbol() and returns its
pointer value.
-------------------------------------------------------------------------


Functions which must be implemented by plug-ins
-----------------------------------------------

-------------------------------------------------------------------------
void plugin_load(void)

Called from Sylpheed on plug-in load.
Do initialization of plug-in etc. here.
-------------------------------------------------------------------------
void plugin_unload(void)

Called from Sylpheed on plug-in unload.
Do finalization of plug-in etc. here.
-------------------------------------------------------------------------
SylPluginInfo *plugin_info(void)

Fuction to return struct which stores plug-in information to Sylpheed.
It normally returns pointer to static struct.
-------------------------------------------------------------------------
gint plugin_interface_version(void)

Function to return plug-in API interface version to Sylpheed.
A plug-in normally returns constant value SYL_PLUGIN_INTERFACE_VERSION.
Sylpheed compares this value with its own value and checks if it is
compatible. Sylpheed's plug-in interface version must be equal to or greater
than the plug-in's plug-in interface verson. If the major versions of the
interface version differ, they are treated as incompatible.

Ex.1: Sylpheed plug-in interface version: 0x0102
      A plug-in plug-in interface version: 0x0100: OK
Ex.2: Sylpheed plug-in interface version: 0x0102
      A plug-in plug-in interface version: 0x0103: NG
-------------------------------------------------------------------------


Functions used by plug-ins
--------------------------

Refer to the header file plugin.h for the functions list.


Signals list
------------

* libsylpheed-plugin-0

Call syl_plugin_signal_connect() to use the following signals.

Example:
  syl_plugin_signal_connect("plugin-load", G_CALLBACK(plugin_load_cb), data);

-------------------------------------------------------------------------
void (* plugin_load)    (GObject *obj, GModule *module);

Emitted on plug-in loading by syl_plugin_load().
-------------------------------------------------------------------------
void (* plugin_unload)  (GObject *obj, GModule *module);

Emitted on plug-in unloading by syl_plugin_unload_all().
-------------------------------------------------------------------------
void (* folderview_menu_popup)  (GObject *obj, gpointer ifactory);

Emitted on popup of the context menu of FolderView.
-------------------------------------------------------------------------
void (* compose_created)        (GObject *obj, gpointer compose);

Emitted on creating 'Compose' message composition window.
-------------------------------------------------------------------------
void (* compose_destroy)        (GObject *obj, gpointer compose);

Emitted just before 'Compose' message composition window is destroyed.
-------------------------------------------------------------------------

* libsylph-0

The following signals can be used by passing GObject obtained by
syl_app_get() to the first argument of g_signal_connect().

Example:

void init_done_cb(GObject *obj, gpointer data)
{
    ...
}

    g_signal_connect(syl_app_get(), "init-done", G_CALLBACK(init_done_cb),
                     data);

-------------------------------------------------------------------------
void (* init_done) (GObject *obj)

Emitted when the initialization of application completes.
-------------------------------------------------------------------------
void (* app_exit) (GObject *obj)

Emitted when application exits.
-------------------------------------------------------------------------
void (* add_msg) (GObject *obj, FolderItem *item, const gchar *file, guint num)

Emitted when a message (number num) is added into folder item.
-------------------------------------------------------------------------
void (* remove_msg) (GObject *obj, FolderItem *item, const gchar *file,
                     guint num)

Emitted when a message (number num) is removed from folder item.
-------------------------------------------------------------------------
void (* remove_all_msg) (GObject *obj, FolderItem *item)

Emitted when all messages are removed from folder item.
-------------------------------------------------------------------------
void (* remove_folder) (GObject *obj, FolderItem *item)

Emitted when folder item is removed.
-------------------------------------------------------------------------
void (* move_folder) (GObject *obj, FolderItem *item, const gchar *old_id,
                      const gchar *new_id)

Emitted when folder item is moved (renamed) from old_id to new_id.
old_id and new_id are folder identifier strings.
-------------------------------------------------------------------------
void (* folderlist_updated) (GObject *obj)

Emitted when folder information is modified and folderlist.xml, which
contains folder list, is updated.
-------------------------------------------------------------------------
void (* account_updated) (GObject *obj)

Emitted on the update of account information.
It will not be emitted if it is locked by account_update_lock(), though.
-------------------------------------------------------------------------


Sample plug-in
==============

There is a sample plug-in at plugin/test. This plug-in will not be installed
with 'make install'. It is required to enter the directory plugin/test and
run 'make install-plugin'.

The 'test' plug-in has the basic structure of Sylpheed plug-in and the
following process:

- Output string "test plug-in loaded!" to stdout on load
- Get folder list and output to stdout
- Get Sylpheed version string and output to stdout
- Get the main window and put it in front
- Add sub widget under the folder view
- Add 'Plugin test' menu item on the 'Tools' menu
- When 'Plugin test' menu is selected, a window with a button named
  'Click this button' is displayed. When it is clicked, a message is displayed
- Capture the following events and show messages: application initialization
  and exiting, folder view context menu popup, creating and destroying compose
  window


About license
=============

It is required that a plug-in DLL dynamically loaded by Sylpheed is GPL or
GPL-compatible license (ex. modified BSD license) based on the GPL clause
because the license of Sylpheed itself is GPL.

If you want to apply non-GPL license like proprietary license to your plug-in,
you must make the module an independent executable file, and make it work with
inter-process communication with a DLL.
