summaryrefslogtreecommitdiff
path: root/docs/reference/totem-plugins.xml
blob: 4d839c3b65fd88fd81414b0493cb5cb999565a3e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
<refentry id="totem-plugins">
	<refmeta>
		<refentrytitle role="top_of_page" id="totem-plugins.top_of_page">Writing Totem Plugins</refentrytitle>
		<manvolnum>3</manvolnum>
		<refmiscinfo>Totem</refmiscinfo>
	</refmeta>
	<refnamediv>
		<refname>Writing Totem Plugins</refname>
		<refpurpose>brief tutorial on writing Totem plugins</refpurpose>
	</refnamediv>

	<refsect1>
		<title>Introduction</title>
		<para>Totem is extensible by means of small, dynamically-loadable plugins, which add functionality wanted by some but not others.</para>

		<refsect2>
			<title>Locations</title>
			<para>Totem plugins can either be installed in the system path
				(e.g. <filename class="directory">/usr/lib/totem/plugins/</filename>), or in a user's home directory
				(e.g. <filename class="directory">~/.local/share/totem/plugins/</filename>). In either case, each plugin resides in a
				subdirectory named after the plugin itself.</para>
			<para>In addition, each plugin needs a <filename class="extension">.plugin</filename> index file, residing inside the plugin
				directory. This gives the code name of the plugin, as well as some metadata about the plugin such as its human-readable
				name, description and author.</para>
			<example>
				<title>Example Plugin Directory</title>
				<para>A system-installed plugin called <literal>subtitle-downloader</literal> would reside in
					<filename class="directory">/usr/lib/totem/plugins/subtitle-downloader</filename>, and would (at a
					minimum) have the following files:
					<itemizedlist>
						<listitem><filename>subtitle-downloader.plugin</filename></listitem>
						<listitem><filename>libsubtitle-downloader.so</filename></listitem>
					</itemizedlist>
				</para>
				<para>If installed in a user's home directory, it would reside in
					<filename class="extension">~/.local/share/totem/plugins/subtitle-downloader</filename> and have the same
					files.</para>
			</example>
		</refsect2>

		<refsect2>
			<title>The <filename class="extension">.plugin</filename> File</title>
			<para>The file should use the following template:
				<programlisting>[Plugin]
	Module=<replaceable>plugin-name</replaceable>
	IAge=<replaceable>plugin interface age (starting at 1)</replaceable>
	Builtin=<replaceable><literal>true</literal> or <literal>false</literal></replaceable>
	Name=<replaceable>Human-Readable Plugin Name</replaceable>
	Description=<replaceable>Simple sentence describing the plugin's functionality.</replaceable>
	Authors=<replaceable>Plugin Author Name</replaceable>
	Copyright=Copyright © <replaceable>year</replaceable> <replaceable>Copyright Holder</replaceable>
	Website=<replaceable>http://plugin/website/</replaceable></programlisting>
				Most of the values in the template are fairly self-explanatory. One thing to note is that the plugin name should be
				in lowercase, and contain no spaces. The plugin interface age should start at <literal>1</literal>, and only be
				incremented when the binary interface of the plugin (as used by Totem) changes. If the plugin does not have its own
				website, Totem's website (<literal>https://wiki.gnome.org/Apps/Videos</literal>) can be used.</para>
			<para>The library file containing the plugin's code should be named
				<filename>lib<replaceable>plugin-name</replaceable>.so</filename> (for C, or other compiled language, plugins) or
				<filename><replaceable>pluginname</replaceable>.py</filename> (for Python plugins).</para>
		</refsect2>

		<refsect2>
			<title>Writing a Plugin</title>
			<para>Writing a plugin in C is a matter of creating a new <type><link linkend="GObject">GObject</link></type> which inherits
				from <type><link linkend="PeasExtensionBase">PeasExtensionBase</link></type> and which implements
				<type><link linkend="PeasActivatable">PeasActivatable</link></type>. The following code will create a simple plugin
				called <literal>foobar</literal>:
				<example>
					<title>Example Plugin Code</title>
					<programlisting>
#define TOTEM_TYPE_FOOBAR_PLUGIN		(totem_foobar_plugin_get_type ())
#define TOTEM_FOOBAR_PLUGIN(o)			(G_TYPE_CHECK_INSTANCE_CAST ((o), TOTEM_TYPE_FOOBAR_PLUGIN, TotemFoobarPlugin))
#define TOTEM_FOOBAR_PLUGIN_CLASS(k)		(G_TYPE_CHECK_CLASS_CAST((k), TOTEM_TYPE_FOOBAR_PLUGIN, TotemFoobarPluginClass))
#define TOTEM_IS_FOOBAR_PLUGIN(o)		(G_TYPE_CHECK_INSTANCE_TYPE ((o), TOTEM_TYPE_FOOBAR_PLUGIN))
#define TOTEM_IS_FOOBAR_PLUGIN_CLASS(k)		(G_TYPE_CHECK_CLASS_TYPE ((k), TOTEM_TYPE_FOOBAR_PLUGIN))
#define TOTEM_FOOBAR_PLUGIN_GET_CLASS(o)	(G_TYPE_INSTANCE_GET_CLASS ((o), TOTEM_TYPE_FOOBAR_PLUGIN, TotemFoobarPluginClass))

typedef struct {
	/* Plugin private member variables */
} TotemFoobarPluginPrivate;

TOTEM_PLUGIN_REGISTER (TOTEM_TYPE_FOOBAR_PLUGIN, TotemFoobarPlugin, totem_foobar_plugin);

static void
impl_activate (PeasActivatable *plugin)
{
	TotemFoobarPlugin *self = TOTEM_FOOBAR_PLUGIN (plugin);
	TotemFoobarPluginPrivate *priv = self->priv;
	TotemObject *totem = g_object_get_data (G_OBJECT (plugin), "object");

	/* Initialise resources, connect to events, create menu items and UI, etc., here.
	 * Note that impl_activate() and impl_deactivate() can be called multiple times in one
	 * Totem instance, though impl_activate() will always be followed by impl_deactivate() before
	 * it is called again. Similarly, impl_deactivate() cannot be called twice in succession. */
}

static void
impl_deactivate (PeasActivatable *plugin)
{
	TotemFoobarPlugin *self = TOTEM_FOOBAR_PLUGIN (plugin);

	/* Destroy resources created in impl_activate() here. e.g. Disconnect from signals
	 * and remove menu entries and UI. */
}</programlisting>
				</example></para>
			<para>Once resources have been created, and the plugin has been connected to Totem's UI in the <function>impl_activate</function>
				function, the plugin is free to go about its tasks as appropriate. If the user deactivates the plugin, or Totem decides
				to deactivate it, the <function>impl_deactivate</function> will be called. The plugin should free any resources
				grabbed or allocated in the <function>impl_activate</function> function, and remove itself from the Totem
				interface.</para>
			<para>Note that plugins can be activated and deactivated (e.g. from Totem's plugin manager) many times during one Totem session,
				so the <function>impl_activate</function> and <function>impl_deactivate</function> functions must be able to cope with
				this.</para>
			<para>Any of the API documented in the rest of the Totem API reference can be used by plugins. Python plugins are written in
				the same way as C plugins, and are similarly implemented as classes derived from
				<type><link linkend="PeasExtensionBase">PeasExtensionBase</link></type> and implementing
				<type><link linkend="PeasActivatable">PeasActivatable</link></type>.</para>
		</refsect2>
	</refsect1>
</refentry>