h1. Plugin development As of NNTPGrab 0.6.0 the program is fully plugin based. This makes it very easy to add new functionality to the program. New functionality can be added in the form of seperate plugins. This documentation describes the steps needed to create a plugin suitable for NNTPGrab. h1. Lifecycle of a plugin All plugins need to implement a number of functions. These functions need to be exported before the plugin can be loaded from the NNTPGrab Core:

void nntpgrab_plugin_initialize(NGPlugin *plugin_data)
ngboolean nntpgrab_plugin_load(NGPlugin *plugin_data, char **errmsg)
ngboolean nntpgrab_plugin_can_unload(NGPlugin *plugin_data, char **reason)
void nntpgrab_plugin_unload(NGPlugin *plugin_data)
void nntpgrab_plugin_destroy(NGPlugin *plugin_data)
int nntpgrab_plugin_get_version(void)
h2. The NGPlugin structure The NGPlugin structure is defined in the file "nntpgrab_core/nntpgrab_plugin.h":http://www.nntpgrab.nl/projects/nntpgrab/repository/entry/trunk/nntpgrab_core/nntpgrab_plugin.h. Plugins must include this file. The NGPlugin structure looks like this:

typedef struct _ng_plugin {
    GObject parent;

    NGPluginCoreData *core_data;
    NGPluginCoreFuncs core_funcs; 
    gpointer priv;
} NGPlugin;
This structure contains 4 fields. The first field is _GObject parent_. This is used internally by GLib/GObject and must not be touched by plugins The second field is _NGPluginCoreData *core_data_. This is a pointer to a structure containing internal plugin information which is maintained by the NNTPGrab Core. This structure also must not be touched by plugins The third field is _NGPluginCoreFuncs core_funcs_. This structure contains pointers to various functions in the NNTPGrab Core. Plugins can call these functions to change the behaviour of the program The fourth field is _gpointer priv_. Plugins can put any kind of data in this field h2. nntpgrab_plugin_initialize On startup of NNTPGrab, the program searches in the plugin folder for all the available plugins. This is done by searching files which implement all the functions which were listed above. To retrieve information about the plugin, this function is called automatically. Must of the time, this function is implemented like this:

void
nntpgrab_plugin_initialize(NGPlugin *plugin_data)
{
    ng_plugin_set_name(plugin_data, "Example");
    ng_plugin_set_version(plugin_data, "1.0");
    ng_plugin_set_author(plugin_data, "Erik van Pienbroek");
    ng_plugin_set_url(plugin_data, "http://www.nntpgrab.nl");
    ng_plugin_set_description(plugin_data, "Example plugin which prints a message in the console every time a file is added");
}
If the plugin want to offer new functionality (functions) to the NNTPGrab Core or other plugins then the function ng_plugin_register_function() can be used here If the plugin wants to use functionality (functions) from other plugins, then this can be indicated by using the function ng_plugin_set_required_function() This is also the only place where the functions ng_plugin_register_function() and ng_plugin_set_required_function() can be used h2. nntpgrab_plugin_load This function will be called by the NNTPGrab Core when the plugin needs to be loaded and get ready to used. The function ng_plugin_connect_event() can be used here to connect to events. If wanted, the plugin_data->priv field can be initialized here to something useful h2. nntpgrab_plugin_can_unload NNTPGrab frontends can call this function to find out whether the plugin is performing a task at the moment. If this is the case, the parameter char **reason can be set to a small comment about the active task and the value _FALSE_ can be returned. If the plugin isn't doing anything at the moment, the value _TRUE_ can be returned h2. nntpgrab_plugin_unload Whenever a plugin needs to be unloaded (because of program shutdown or on the user's request) this function will be called. It's basically the reverse of the [[Plugin_development#nntpgrab_plugin_load|nntpgrab_plugin_load]] function. If the plugin_data->priv field was set, then it can be cleared here It isn't necessary to unregister any event connections (done by ng_plugin_connect_event()) as that'll be automatically done by the NNTPGrab Core h2. nntpgrab_plugin_destroy On program shutdown, this function will be automatically called. Most plugins don't need to add any implementation to this function h2. nntpgrab_plugin_get_version The implementation of this function must be the same across all plugins. All that needs to happen is a _return NNTPGRAB_PLUGIN_API_VERSION;_. With this information, the NNTPGrab Core can find out if the plugin is using the same API version of the NNTPGrab Core is expecting. When an API mismatch is detected, the plugin will be ignored h1. Executing functions of other plugins Whenever a plugin want to use functionality from another plugin, a special function has to be used: ng_plugin_call() This function expects a variable number of arguments. The first parameters (which are always required) are a pointer to an instance of the NGPlugin structure (which is used across all plugin functions) and a function name. Depending on the function which needs to be executed, zero or more additional arguments are needed. If the function which needs to be executed has a return value, then it needs to be added as the last parameter to the ng_plugin_call() call. To help the NNTPGrab Core in dependency resolving, any external function which will be used by the plugin needs to be registered with the ng_plugin_set_required_function() function in the [Plugin_development#nntpgrab_plugin_initialize|nntpgrab_plugin_initialize()]] function Every function expects a different set of parameters. To find out what the right expected parameters are see the [[Plugin development#API-documentation|API documentation]] section h1. Connecting to events of other plugins Plugins can emit events whenever something has occured. Other plugins can connect to these event by using the ng_plugin_connect_event() function This function expects a pointer to an instance of the NGPlugin structure (which is used across all plugin functions), an event name and the name of the function which needs to be invoked whenever the event occurs. Every event has a different set of arguments. To find out what the right expected parameters are see the [[Plugin development#API-documentation|API documentation]] section h1. API documentation For a list of functions which NNTPGrab plugins can use to communicate with other plugins, see the "documentation for nntpgrab_plugin.h":http://nntpgrab.nl/embedded/nntpgrab/docs/NNTPGrab-NNTPGrab-Plugin-API.html This is a list of events which are exported by the NNTPGrab Core and other plugins. Plugins can connect to these events with the function ng_plugin_connect_event(). h2. config_changed Something in the configuration has changed
void config_changed (NGPlugin *plugin_data, void *user_data)
h2. part_download_start The download of a part has just started
void part_download_start (NGPlugin *plugin_data, const char *servername, int conn_id, const char *collection_name, const char *subject, int part_num, void *user_data)
h2. part_done The download of a part has completed successfully
void part_done (NGPlugin *plugin_data, const char *servername, int conn_id, const char *collection_name, const char *subject, int part_num, int size, void *user_data)
h2. part_failed The download of a part has failed (probably because the part isn't available on the server)
void part_failed (NGPlugin *plugin_data, const char *servername, int conn_id, const char *collection_name, const char *subject, int part_num, int size, ngboolean all_servers_tried, void *user_data)
h2. traffic_monitor_update Every second, traffic statistics about the last 10 seconds are given
void traffic_monitor_update (NGPlugin *plugin_data, int bytes_received1, int bytes_received2, int bytes_received3, int bytes_received4, int bytes_received5, int bytes_received6, int bytes_received7, int bytes_received8, int bytes_received9, int bytes_received10, guint64 stamp, double average, void *user_data)
h2. part_progress_update Every 1/10th second of a part download, this message will be sent
void part_progress_update (NGPlugin *plugin_data, const char *servername, int conn_id, const char *subject, int part_num, int bytes_downloaded, int bytes_total, void *user_data)
h2. collection_added A new collection was added
void collection_added (NGPlugin *plugin_data, const char *collection_name, const char *poster, void *user_data)
h2. collection_removed A collection was removed
void collection_removed (NGPlugin *plugin_data, const char *collection_name, void *user_data)
h2. collection_modified The poster of a collection was modified
void collection_modified (NGPlugin *plugin_data, const char *collection_name, const char *poster, void *user_data)
h2. file_added A file was added to a already existing collection
void file_added (NGPlugin *plugin_data, const char *collection_name, const char *subject, const char *poster, nguint64 stamp, nguint64 file_size, nguint64 total_size, nguint64 total_size_remaining, NGTaskState status, int num_parts, NGList *groups, void *user_data)
The _groups_ argument is a list of newsgroups (const char*'s) h2. file_removed A file was removed from the download queue
void file_removed (NGPlugin *plugin_data, const char *collection_name, const char *subject, nguint64 total_size, nguint64 total_size_remaining, void *user_data)
h2. file_download_state_update The state of a file in the download queue has changed
void file_download_state_update (NGPlugin *plugin_data, const char *collection_name, const char *subject, int num_parts_total, int num_parts_done, int num_parts_failed, nguint64 file_size, nguint64 file_size_remaining, nguint64 total_size, nguint64 total_size_remaining, void *user_data)
h2. file_state_changed A file in the download queue was restarted
void file_state_changed (NGPlugin *plugin_data, const char *collection_name, const char *subject, const char *real_filename, NGTaskState old_state, NGTaskState new_state, void *user_data)
h2. connection_connecting A new connection is being made to a usenet server
void connection_connecting (NGPlugin *plugin_data, const char *servername, int conn_id, void *user_data)
h2. connection_connected A connection attempt has succeeded
void connection_connected (NGPlugin *plugin_data, const char *servername, int conn_id, const char *welcome_msg, void *user_data)
h2. connection_disconnect A connection to a usenet server was disconnected
void connection_disconnect (NGPlugin *plugin_data, const char *servername, int conn_id, NNTPDisconnectType disconnect_type, const char *msg, void *user_data)
h2. schedular_state_changed The state of the schedular has changed
void schedular_state_changed (NGPlugin *plugin_data, NGSchedularState new_state, const char *reason, void *user_data)
h2. log_message A log message has been emitted
void log_message (NGPlugin *plugin_data, const char *component, NGLogLevel log_level, const char *msg, void *user_data)
h2. task_moved The position of a task in the download queue has changed
void task_moved (NGPlugin *plugin_data, const char *orig_collection_name, const char *subject, const char *new_collection_name, int old_position, int new_position, void *user_data)
h2. collection_moved The position of a collection in the download queue has changed
void collection_moved (NGPlugin *plugin_data, const char *collection_name, int old_position, int new_position, void *user_data)
h2. all_downloads_completed This message is emit when all the items in the download queue are completed
void all_downloads_completed (NGPlugin *plugin_data, void *user_data)
h2. plugin_loaded A plugin has been loaded
void plugin_loaded (NGPlugin *plugin_data, const char *plugin_name, ngboolean is_persistent, void *user_data)
h2. plugin_unloaded A plugin has been unloaded
void plugin_unloaded (NGPlugin *plugin_data, const char *plugin_name, void *user_data)
h2. plugin_event A plugin has emit an event
void plugin_event (NGPlugin *plugin_data, const char *plugin_name, const char *event_name, const char **values)
The _values_ parameter is a NULL-terminated array containing const char*'s h1. Example plugin For a simple example plugin, see the file "plugins/example/example.c":http://www.nntpgrab.nl/projects/nntpgrab/repository/entry/trunk/plugins/example/example.c. This is a very basic plugin which waits for the event _file_added_ to occur. Whenever the event occurs, some parameters belonging to that specific event are printed in the console