Remove events_pending
[gmpc.git] / doc / PluginHowto.txt
blobb694791ff4d29a9923e05c109bcb2ebf3b6c00f5
1 Howto write a plugin for gmpc
2 =============================
3 Qball Cow <Qball@sarine.nl>
4 v0.1, Oct. 2007
6 The best tip I can give you is, look at the existing plugins and at the gmpc source. Internally gmpc uses the plugin structure for almost all parts.
8 Plugin Example
9 --------------
10 Here is a simple example of a useless plugin.
11 This can be used as template.
12 The fields of the gmpcPlugin will be explained in the next chapter.
14 [c,numbered]
15 source~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
16 #include <gmpc/plugin.h>
18 gmpcPlugin plugin;
20 static int plugin_get_enabled(void)
22     /* Getting the enable state from gmpc's config system */
23     return cfg_get_single_value_as_int_with_default(config, plugin.name, "enabled", TRUE);
26 static void plugin_set_enabled(int enabled)
28     /* Storing the enable state in gmpc's config system */
29     cfg_set_single_value_as_int(config, plugin.name, "enabled", enabled);
30     /* Now handle the changes */
33 static void plugin_init(void)
35     /* initialize the plugin here */
37 static void plugin_destroy(void)
39     /* destroy the plugin here */
41 static void plugin_save_myself(void)
43     /* Save any settings */
46 /**
47  * Signals
48  */
49 static void plugin_connection_changed(MpdObj *mi, int connect, void *userdata)
53 static void plugin_status_changed(MpdObj *mi,ChangedStatusType what , void *userdata)
55     if(what&MPD_CST_SONGID)
56     {
57         /* This part of the function is called when mpd changes song */
59     }
62 gmpcPlugin plugin = {
63     /* Required fields */
64     .name                   = "The plugin Name",
65     .version                = {0,15,5},
66     .plugin_type            = GMPC_PLUGIN_NO_GUI,
67     .get_enabled            = plugin_get_enabled,
68     .set_enabled            = plugin_set_enabled,
70     /* Optional fields */
71     .init                   = plugin_init,
72     .destroy                = plugin_destroy,
73     .save_yourself          = plugin_save_myself,
75     /* Extentions 
76      * (These are sub-structures)
77      */
79      /* A structure that provide the functionality off adding a browser to the main interface,
80       * catching keystrokes, add menu options, etc.
81       */
82     .browser                = NULL,
84     /* A structure that exposes 2 functions that are needed to make the plugin function as metadata provider */
85     .metadata               = NULL,
87     /* A structure that allows the plugin to add a panel to the preferences window.*/
88     .pref                   = NULL,
90     /* Signals */
91     .mpd_connection_changed = plugin_connection_changed,
92     .mpd_status_changed     = plugin_status_changed
93 };                                                         
95 int plugin_api_version = PLUGIN_API_VERSION;
96 source~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
100 gmpcPlugin
101 ----------
103 Every plugin must have a (filled in) version of the gmpcPlugin called plugin. This will be what gmpc tries to load.
105 It is prefered to use the "named" filling of the plugin ( .name = <value>,), instead of making a long list of values.
106 2 fields are filled in by gmpc and should be left empty. This is the id field (an number that identifies the plugin) and the path field (is filled in with the path to the executable).
108 Plugin name and version
109 ~~~~~~~~~~~~~~~~~~~~~~~
110 A plugin must have a name and a version to be valid.
111 The version consists of 3 numbers, normally plugin numbers are kept in sync with the gmpc release. 
112 The name will be used to report error about the plugin and in the preferences window.
114 Types of plugins
115 ~~~~~~~~~~~~~~~~~
116 A plugin can have one or several different functions.
117 This is set using the plugin_type field in the gmpcPlugin structure.
118 The following types are available:
120 1. GMPC_PLUGIN_DUMMY:
121    This plugin does not have a particular function, and should not be used.
123 2. GMPC_PLUGIN_PL_BROWSER:
124     This plugin extends the main window with an extra browser.  Therefor the browser field in the gmpcPlugin must be filled in.
125     examples:
126     * Magnatune browser
127     * Server statistics
128     * Wikipedia
129 3. GMPC_PLUGIN_NO_GUI:
130     Extends gmpc withouth adding a gui component to the main interface.
131     examples:
132     * osd
133 4. GMPC_INTERNALL:
134     Should never be used, this is used to mark an internal plugin. 
135 5. GMPC_DEPRECATED:
136     This used to be the id of plugin for the old metadata system.
137 6. GMPC_PLUGIN_META_DATA:
138     This plugin provides gmpc with metadata. the metadata field in gmpcPlugin needs to be filled in.
139     examples:
140     * mdcover
141     * coveramazon
142     * Magnatune browsr.
144 The Magnatune browser, as visible above, is an example of a plugin that implements 2 types. 1 a GMPC_PLUGIN_PL_BROWSER and 2 a GMPC_PLUGIN_META_DATA.
145 In the plugin_type field those can be added bitwise. for example plugin_type = GMPC_PLUGIN PL_BROWSER|GMPC_PLUGIN_META_DATA.
146 Remeber that both the metadata and the browser entry in the gmpcPlugin needs to be filled in.
149 Init/Destroy/Save yourself
150 ~~~~~~~~~~~~~~~~~~~~~~~~~~
151 There are 3 functions used to construct and destroy the plugin.
153 init
154 ^^^^
155 On startup, before gtk enters it mainloop and before the main interface is created. the init() function of the plugin gets called.
156 At this time the config system is working and gtk is initialized. Here plugins can initialize libraries (f.e. libxosd or dbus) that it requires later in the program.
158 Save yourself
159 ^^^^^^^^^^^^^
160 This is called for all plugins, then every plugin is destroyed. 
161 F.e.  a Browser plugin should save the position of browser here (and not in the destroy handler, because other plugins that are destoyed might cause the location to change). 
163 Destroy
164 ^^^^^^^
165 A plugin should destroy itself here.
167 Get/Set Enabled
168 ~~~~~~~~~~~~~~~
169 [NOTE] These functions are needed for the plugin to be loaded.
171 Get Enabled
172 ^^^^^^^^^^^
173 Queries the plugin's enable state.
175 Set Enabled
176 ^^^^^^^^^^^
177 Set the plugin enable state.
178 If the plugin add's gui elements to the interface, it should show/hide them. 
179 For example the stop button plugin removes the button when set_enabled(FALSE) is called.
181 Signals
182 ~~~~~~~
183 Libmpd can give 3 types of signals to the users, 2 of them are forwarded to the plugins.
184 Namely the 'status changed' and the 'connection changed'. 
185 For more information see the libmpd api reference.
187 Status changed
188 ^^^^^^^^^^^^^^
189 A bitmask 'what' is passed, telling  you how mpd changed. See the libmpd documentation for more information.
191 Connection Changed
192 ^^^^^^^^^^^^^^^^^^
193 The function is called when the state of the connection changed. The 'connect' field indicates the new state.
195 Preferences
196 ~~~~~~~~~~~
197 The 'gmpcPlugin' structure can hold a substructure for preferences: 'gmpcPrefPlugin'.
200 source~~~~~~~~~~
201 static GtkWidget *vbox = NULL;
202 static void preferences_panel_construct(GtkWidget *container)
204     GtkWidget *label;
205     vbox = gtk_vbox_new(FALSE, 6);
206     label = gtk_label_new("Testing");
207     gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE,0);
208     /* add it to the right part of the preferences window */
209     /* vbox has a floating ref. on creation, adding it to the 
210      * container will give it a real one
211      */
212     gtk_container_add(GTK_CONTAINER(container), vbox);
214 static void preferences_panel_destroy(GtkWidget *container)
216     /* Removing the vbox from the container will release the ref. the container has on it. 
217      * So the vbox will be free-ed
218      * If you don't want this, you must add your own ref. to the vbox in the construct function
219      */
220     gtk_container(remove(GTK_CONTAINER(container), vbox);
221     vbox = NULL;
223 gmpcPrefPugin pref = {
224     .construct  = preferences_panel_construct,
225     .destroy    = preferences_panel_destroy 
227 source~~~~~~~~~~
229 These functions allow you to embed a 'window' in the preferences window. If the structure isn't available, no entry will be made.
231 construct
232 ~~~~~~~~~
233 Create a widget that contains the panel, add this then to the container using *gtk_container_add*.
235 destroy
236 ~~~~~~~
237 Remove the added panel from the container, using *gtk_container_remove*, and cleanup.
239 Metadata
240 ^^^^^^^^
241 'gmpcMetaDataPlugin'
243 plugin_api_version
244 ------------------
245 Every plugin must have the following define:
247     int plugin_api_version = PLUGIN_API_VERSION;
249 This allows gmpc to check if the plugin is compiled against the same plugin interface as gmpc has.