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
|
#ifndef _PLUGIN_H_
#define _PLUGIN_H_
#include <dlfcn.h>
#include <pthread.h>
#include <stdint.h>
/*
* Marker macro to define what functions should be exported. This generates the
* interface which the plugin needs to implement.
*/
#define EXPORT(a) a
typedef void *dlhandle_t;
/* Opaque state for a plugin. Not to be touched by the harness (not that it
* really can be.) */
typedef void *opqst_t;
/*
* Structure for the plugin.
*/
typedef struct PLUGIN {
/* Opaque state of this plugin. The state is usually some kind of pointer to
* the plugin state, but all the harness knows is the opaque state is a
* pointer-sized piece of data.
*
* This opaque state is used in a linear pattern where the handlers take the
* opaque state, maybe operate on it, and return a new opaque state, which is
* then passed to the next handler, etc. It is on the plugin to properly
* manager the memory for this state and to destroy it upon teardown.
*
* It's guaranteed that this state is used linearly, meaning the harness gives
* up all ownership to it once passed into a handler. */
opqst_t state;
/* This plugin's lock. This avoids potential issues with multiple threads
* trying to change the opaque state at once which can lead to undesireable
* outcomes. */
pthread_mutex_t lock;
/* The handle to the shared library. */
dlhandle_t library_handle;
/* Pointer to the plugin name. This is in the shared library and a
* null-terminated string. If the library does not have a plugin name, this
* will be NULL. */
const char *plugin_name;
/** Intializes the plugin with the given argc/argv. This is the first thing
* called on the plugin and is called immediately after the library is loaded.
*/
EXPORT(void (*plugin_load)(int argc, char **argv));
/* Start the plugin with the marshalled state from the previous plugin.
*
* This should return the opaque state from the mashalled_state.
*
* This function should not fail if the state cannot be demarshalled, rather a
* default state should be returned. This is because changing the plugin and
* hot-reloading can produce incompatibilities between the old state and the
* new state, and this should not cause a failure.
*/
EXPORT(opqst_t (*plugin_hot_start)(uint8_t *mashalled_state, uint32_t n));
/*
* Starts the plugin without a marshalled state. Happens during the first boot
* when there is not state.
*/
EXPORT(opqst_t (*plugin_cold_start)());
/*
* Marshals the state to a bytestring. The returned pointer should be malloc'd
* on the heap. The harness takes ownership of the malloc'd pointer.
*
* This is usually called in preparation for a teardown followed by a
* hot-start.
*/
EXPORT(uint8_t *(*plugin_marshal_state)(opqst_t st, uint32_t *szout));
/*
* Teardown the plugin in preperation for the library's imminent unloading.
*/
EXPORT(void (*plugin_teardown)(opqst_t));
/*
* Handles a keybinding.
*/
EXPORT(opqst_t (*plugin_handle_keybinding)(uint32_t keysym, opqst_t state));
/*
* Handles a surface being mapped, unmapped or destroyed.
*/
EXPORT(opqst_t (*plugin_handle_surface_map)(void *surface, opqst_t));
EXPORT(opqst_t (*plugin_handle_surface_unmap)(void *surface, opqst_t));
EXPORT(opqst_t (*plugin_handle_surface_destroy)(void *surface, opqst_t));
} plugin_t;
/** Loads a plugin from the dynamic library handle. Returns a non-zero error
* code on error. */
int load_plugin_from_dl(dlhandle_t library, plugin_t *out);
/* Reloads the plugin. This tears down the existing plugin, marshals the state
* for it and reloads it.
*
* This function will call dlclose on the plugin's library handle if it is not
* the same as 'library'.
*/
int plugin_hot_reload(int argc, char **argv, const char *filepath,
plugin_t *plugin);
/* Reads a plugin from a filename. */
int load_plugin_from_file(const char *filename, plugin_t *plugin);
#endif /* _PLUGIN_H_ */
|