chiark / gitweb /
libtests: Include the Unicode test files directly.
[disorder] / server / plugin.c
CommitLineData
460b9539 1/*
2 * This file is part of DisOrder.
8a886602 3 * Copyright (C) 2004-2009, 2011 Richard Kettlewell
460b9539 4 *
e7eb3a27 5 * This program is free software: you can redistribute it and/or modify
460b9539 6 * it under the terms of the GNU General Public License as published by
e7eb3a27 7 * the Free Software Foundation, either version 3 of the License, or
460b9539 8 * (at your option) any later version.
9 *
e7eb3a27
RK
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
460b9539 15 * You should have received a copy of the GNU General Public License
e7eb3a27 16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
460b9539 17 */
132a5a4a
RK
18/** @file server/plugin.c
19 * @brief Server plugin interface
20 */
05b75f8d 21#include "disorder-server.h"
460b9539 22
23#include <dlfcn.h>
460b9539 24
25/* generic plugin support *****************************************************/
26
27#ifndef SOSUFFIX
28# define SOSUFFIX ".so"
29#endif
30
2c6ee627 31/** @brief A loaded plugin */
460b9539 32struct plugin {
2c6ee627 33 /** @brief Next plugin */
460b9539 34 struct plugin *next;
2c6ee627
RK
35
36 /** @brief Handle returned from dlopen() */
460b9539 37 void *dlhandle;
2c6ee627
RK
38
39 /** @brief Plugin name */
460b9539 40 const char *name;
41};
42
43static struct plugin *plugins;
44
45const struct plugin *open_plugin(const char *name,
46 unsigned flags) {
47 void *h = 0;
48 char *p;
49 int n;
50 struct plugin *pl;
51
52 for(pl = plugins; pl && strcmp(pl->name, name); pl = pl->next)
53 ;
54 if(pl) return pl;
62dc3748 55 /* Search the plugin path */
460b9539 56 for(n = 0; n <= config->plugins.n; ++n) {
57 byte_xasprintf(&p, "%s/%s" SOSUFFIX,
58 n == config->plugins.n ? pkglibdir : config->plugins.s[n],
59 name);
60 if(access(p, R_OK) == 0) {
61 h = dlopen(p, RTLD_NOW);
62 if(!h) {
2e9ba080 63 disorder_error(0, "error opening %s: %s", p, dlerror());
460b9539 64 continue;
65 }
66 pl = xmalloc(sizeof *pl);
67 pl->dlhandle = h;
68 pl->name = xstrdup(name);
69 pl->next = plugins;
70 plugins = pl;
71 return pl;
72 }
73 }
2e9ba080
RK
74 (flags & PLUGIN_FATAL ? disorder_fatal : disorder_error)
75 (0, "cannot find plugin '%s'", name);
460b9539 76 return 0;
77}
78
79function_t *get_plugin_function(const struct plugin *pl,
80 const char *symbol) {
81 function_t *f;
460b9539 82
3bd1c92f 83 f = (function_t *)dlfunc(pl->dlhandle, symbol);
f47f3637 84 if(!f)
2e9ba080
RK
85 disorder_fatal(0, "error looking up function '%s' in '%s': %s",
86 symbol, pl->name, dlerror());
460b9539 87 return f;
88}
89
90const void *get_plugin_object(const struct plugin *pl,
91 const char *symbol) {
92 void *o;
460b9539 93
94 o = dlsym(pl->dlhandle, symbol);
f47f3637 95 if(!o)
2e9ba080
RK
96 disorder_fatal(0, "error looking up object '%s' in '%s': %s",
97 symbol, pl->name, dlerror());
460b9539 98 return o;
99}
100
101/* specific plugin interfaces *************************************************/
102
103typedef long tracklength_fn(const char *track, const char *path);
104
62dc3748
RK
105/** Compute the length of a track
106 * @param plugin plugin to use, as configured
107 * @param track UTF-8 name of track
108 * @param path file system path or 0
109 * @return length of track in seconds, 0 for unknown, -1 for error
110 */
111long tracklength(const char *plugin, const char *track, const char *path) {
112 tracklength_fn *f = 0;
460b9539 113
62dc3748
RK
114 f = (tracklength_fn *)get_plugin_function(open_plugin(plugin,
115 PLUGIN_FATAL),
116 "disorder_tracklength");
460b9539 117 return (*f)(track, path);
118}
119
120typedef void scan_fn(const char *root);
121
122void scan(const char *module, const char *root) {
123 ((scan_fn *)get_plugin_function(open_plugin(module, PLUGIN_FATAL),
124 "disorder_scan"))(root);
125}
126
127typedef int check_fn(const char *root, const char *path);
128
129
130int check(const char *module, const char *root, const char *path) {
131 return ((check_fn *)get_plugin_function(open_plugin(module, PLUGIN_FATAL),
132 "disorder_check"))(root, path);
133}
134
135typedef void notify_play_fn(const char *track, const char *submitter);
136
137void notify_play(const char *track,
138 const char *submitter) {
139 static notify_play_fn *f;
140
141 if(!f)
142 f = (notify_play_fn *)get_plugin_function(open_plugin("notify",
143 PLUGIN_FATAL),
144 "disorder_notify_play");
145 (*f)(track, submitter);
146}
147
148typedef void notify_scratch_fn(const char *track,
149 const char *submitter,
150 const char *scratcher,
151 int seconds);
152
153void notify_scratch(const char *track,
154 const char *submitter,
155 const char *scratcher,
156 int seconds) {
157 static notify_scratch_fn *f;
158
159 if(!f)
160 f = (notify_scratch_fn *)get_plugin_function(open_plugin("notify",
161 PLUGIN_FATAL),
162 "disorder_notify_scratch");
163 (*f)(track, submitter, scratcher, seconds);
164}
165
166typedef void notify_not_scratched_fn(const char *track,
167 const char *submitter);
168
169void notify_not_scratched(const char *track,
170 const char *submitter) {
171 static notify_not_scratched_fn *f;
172
173 if(!f)
174 f = (notify_not_scratched_fn *)get_plugin_function
175 (open_plugin("notify",
176 PLUGIN_FATAL),
177 "disorder_notify_not_scratched");
178 (*f)(track, submitter);
179}
180
181typedef void notify_queue_fn(const char *track,
182 const char *submitter);
183
184void notify_queue(const char *track,
185 const char *submitter) {
186 static notify_queue_fn *f;
187
188 if(!f)
189 f = (notify_queue_fn *)get_plugin_function(open_plugin("notify",
190 PLUGIN_FATAL),
191 "disorder_notify_queue");
192 (*f)(track, submitter);
193}
194
195void notify_queue_remove(const char *track,
196 const char *remover) {
197 static notify_queue_fn *f;
198
199 if(!f)
200 f = (notify_queue_fn *)get_plugin_function(open_plugin("notify",
201 PLUGIN_FATAL),
202 "disorder_notify_queue_remove");
203 (*f)(track, remover);
204}
205
206void notify_queue_move(const char *track,
207 const char *mover) {
208 static notify_queue_fn *f;
209
210 if(!f)
211 f = (notify_queue_fn *)get_plugin_function(open_plugin("notify",
212 PLUGIN_FATAL),
213 "disorder_notify_queue_move");
214 (*f)(track, mover);
215}
216
217void notify_pause(const char *track, const char *who) {
218 static notify_queue_fn *f;
219
220 if(!f)
221 f = (notify_queue_fn *)get_plugin_function(open_plugin("notify",
222 PLUGIN_FATAL),
223 "disorder_notify_pause");
224 (*f)(track, who);
225}
226
227void notify_resume(const char *track, const char *who) {
228 static notify_queue_fn *f;
229
230 if(!f)
231 f = (notify_queue_fn *)get_plugin_function(open_plugin("notify",
232 PLUGIN_FATAL),
233 "disorder_notify_resume");
234 (*f)(track, who);
235}
236
237/* player plugin interfaces ***************************************************/
238
239/* get type */
240
241unsigned long play_get_type(const struct plugin *pl) {
242 return *(const unsigned long *)get_plugin_object(pl, "disorder_player_type");
243}
244
245/* prefork */
246
247typedef void *prefork_fn(const char *track);
248
249void *play_prefork(const struct plugin *pl,
250 const char *track) {
251 return ((prefork_fn *)get_plugin_function(pl,
252 "disorder_play_prefork"))(track);
253}
254
255/* play */
256
257typedef void play_track_fn(const char *const *parameters,
258 int nparameters,
259 const char *path,
260 const char *track);
261
262void play_track(const struct plugin *pl,
263 const char *const *parameters,
264 int nparameters,
265 const char *path,
266 const char *track) {
267 ((play_track_fn *)get_plugin_function(pl,
268 "disorder_play_track"))(parameters,
269 nparameters,
270 path,
271 track);
272}
273
274/* cleanup */
275
276typedef void cleanup_fn(void *data);
277
278void play_cleanup(const struct plugin *pl, void *data) {
279 ((cleanup_fn *)get_plugin_function(pl, "disorder_play_cleanup"))(data);
280}
281
282/* pause */
283
284typedef int pause_fn(long *playedp, void *data);
285
286int play_pause(const struct plugin *pl, long *playedp, void *data) {
287 return (((pause_fn *)get_plugin_function(pl, "disorder_pause_track"))
288 (playedp, data));
289}
290
291/* resume */
292
293typedef void resume_fn(void *data);
294
295void play_resume(const struct plugin *pl, void *data) {
296 (((resume_fn *)get_plugin_function(pl, "disorder_resume_track"))
297 (data));
298}
299
300/*
301Local Variables:
302c-basic-offset:2
303comment-column:40
304End:
305*/