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.
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)
The NGPlugin structure¶
The NGPlugin structure is defined in the file 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
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, "https://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
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
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
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 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
nntpgrab_plugin_destroy¶
On program shutdown, this function will be automatically called. Most plugins don't need to add any implementation to this function
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
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 API documentation section
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 API documentation section
API documentation¶
For a list of functions which NNTPGrab plugins can use to communicate with other plugins, see the documentation for nntpgrab_plugin.h
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().
config_changed¶
Something in the configuration has changed
void config_changed (NGPlugin *plugin_data, void *user_data)
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)
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)
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)
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)
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)
collection_added¶
A new collection was added
void collection_added (NGPlugin *plugin_data, const char *collection_name, const char *poster, void *user_data)
collection_removed¶
A collection was removed
void collection_removed (NGPlugin *plugin_data, const char *collection_name, void *user_data)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
plugin_loaded¶
A plugin has been loaded
void plugin_loaded (NGPlugin *plugin_data, const char *plugin_name, ngboolean is_persistent, void *user_data)
plugin_unloaded¶
A plugin has been unloaded
void plugin_unloaded (NGPlugin *plugin_data, const char *plugin_name, void *user_data)
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
Example plugin¶
For a simple example plugin, see the file 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
NNTPGrab

