chiark / gitweb /
Add missing notification when scratch queued, lost a couple of commits back
[disorder] / server / plugin.c
CommitLineData
460b9539 1/*
2 * This file is part of DisOrder.
5aff007d 3 * Copyright (C) 2004-2008 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
31struct plugin {
32 struct plugin *next;
33 void *dlhandle;
34 const char *name;
35};
36
37static struct plugin *plugins;
38
39const struct plugin *open_plugin(const char *name,
40 unsigned flags) {
41 void *h = 0;
42 char *p;
43 int n;
44 struct plugin *pl;
45
46 for(pl = plugins; pl && strcmp(pl->name, name); pl = pl->next)
47 ;
48 if(pl) return pl;
62dc3748 49 /* Search the plugin path */
460b9539 50 for(n = 0; n <= config->plugins.n; ++n) {
51 byte_xasprintf(&p, "%s/%s" SOSUFFIX,
52 n == config->plugins.n ? pkglibdir : config->plugins.s[n],
53 name);
54 if(access(p, R_OK) == 0) {
55 h = dlopen(p, RTLD_NOW);
56 if(!h) {
2e9ba080 57 disorder_error(0, "error opening %s: %s", p, dlerror());
460b9539 58 continue;
59 }
60 pl = xmalloc(sizeof *pl);
61 pl->dlhandle = h;
62 pl->name = xstrdup(name);
63 pl->next = plugins;
64 plugins = pl;
65 return pl;
66 }
67 }
2e9ba080
RK
68 (flags & PLUGIN_FATAL ? disorder_fatal : disorder_error)
69 (0, "cannot find plugin '%s'", name);
460b9539 70 return 0;
71}
72
73function_t *get_plugin_function(const struct plugin *pl,
74 const char *symbol) {
75 function_t *f;
460b9539 76
77 f = (function_t *)dlsym(pl->dlhandle, symbol);
f47f3637 78 if(!f)
2e9ba080
RK
79 disorder_fatal(0, "error looking up function '%s' in '%s': %s",
80 symbol, pl->name, dlerror());
460b9539 81 return f;
82}
83
84const void *get_plugin_object(const struct plugin *pl,
85 const char *symbol) {
86 void *o;
460b9539 87
88 o = dlsym(pl->dlhandle, symbol);
f47f3637 89 if(!o)
2e9ba080
RK
90 disorder_fatal(0, "error looking up object '%s' in '%s': %s",
91 symbol, pl->name, dlerror());
460b9539 92 return o;
93}
94
95/* specific plugin interfaces *************************************************/
96
97typedef long tracklength_fn(const char *track, const char *path);
98
62dc3748
RK
99/** Compute the length of a track
100 * @param plugin plugin to use, as configured
101 * @param track UTF-8 name of track
102 * @param path file system path or 0
103 * @return length of track in seconds, 0 for unknown, -1 for error
104 */
105long tracklength(const char *plugin, const char *track, const char *path) {
106 tracklength_fn *f = 0;
460b9539 107
62dc3748
RK
108 f = (tracklength_fn *)get_plugin_function(open_plugin(plugin,
109 PLUGIN_FATAL),
110 "disorder_tracklength");
460b9539 111 return (*f)(track, path);
112}
113
114typedef void scan_fn(const char *root);
115
116void scan(const char *module, const char *root) {
117 ((scan_fn *)get_plugin_function(open_plugin(module, PLUGIN_FATAL),
118 "disorder_scan"))(root);
119}
120
121typedef int check_fn(const char *root, const char *path);
122
123
124int check(const char *module, const char *root, const char *path) {
125 return ((check_fn *)get_plugin_function(open_plugin(module, PLUGIN_FATAL),
126 "disorder_check"))(root, path);
127}
128
129typedef void notify_play_fn(const char *track, const char *submitter);
130
131void notify_play(const char *track,
132 const char *submitter) {
133 static notify_play_fn *f;
134
135 if(!f)
136 f = (notify_play_fn *)get_plugin_function(open_plugin("notify",
137 PLUGIN_FATAL),
138 "disorder_notify_play");
139 (*f)(track, submitter);
140}
141
142typedef void notify_scratch_fn(const char *track,
143 const char *submitter,
144 const char *scratcher,
145 int seconds);
146
147void notify_scratch(const char *track,
148 const char *submitter,
149 const char *scratcher,
150 int seconds) {
151 static notify_scratch_fn *f;
152
153 if(!f)
154 f = (notify_scratch_fn *)get_plugin_function(open_plugin("notify",
155 PLUGIN_FATAL),
156 "disorder_notify_scratch");
157 (*f)(track, submitter, scratcher, seconds);
158}
159
160typedef void notify_not_scratched_fn(const char *track,
161 const char *submitter);
162
163void notify_not_scratched(const char *track,
164 const char *submitter) {
165 static notify_not_scratched_fn *f;
166
167 if(!f)
168 f = (notify_not_scratched_fn *)get_plugin_function
169 (open_plugin("notify",
170 PLUGIN_FATAL),
171 "disorder_notify_not_scratched");
172 (*f)(track, submitter);
173}
174
175typedef void notify_queue_fn(const char *track,
176 const char *submitter);
177
178void notify_queue(const char *track,
179 const char *submitter) {
180 static notify_queue_fn *f;
181
182 if(!f)
183 f = (notify_queue_fn *)get_plugin_function(open_plugin("notify",
184 PLUGIN_FATAL),
185 "disorder_notify_queue");
186 (*f)(track, submitter);
187}
188
189void notify_queue_remove(const char *track,
190 const char *remover) {
191 static notify_queue_fn *f;
192
193 if(!f)
194 f = (notify_queue_fn *)get_plugin_function(open_plugin("notify",
195 PLUGIN_FATAL),
196 "disorder_notify_queue_remove");
197 (*f)(track, remover);
198}
199
200void notify_queue_move(const char *track,
201 const char *mover) {
202 static notify_queue_fn *f;
203
204 if(!f)
205 f = (notify_queue_fn *)get_plugin_function(open_plugin("notify",
206 PLUGIN_FATAL),
207 "disorder_notify_queue_move");
208 (*f)(track, mover);
209}
210
211void notify_pause(const char *track, const char *who) {
212 static notify_queue_fn *f;
213
214 if(!f)
215 f = (notify_queue_fn *)get_plugin_function(open_plugin("notify",
216 PLUGIN_FATAL),
217 "disorder_notify_pause");
218 (*f)(track, who);
219}
220
221void notify_resume(const char *track, const char *who) {
222 static notify_queue_fn *f;
223
224 if(!f)
225 f = (notify_queue_fn *)get_plugin_function(open_plugin("notify",
226 PLUGIN_FATAL),
227 "disorder_notify_resume");
228 (*f)(track, who);
229}
230
231/* player plugin interfaces ***************************************************/
232
233/* get type */
234
235unsigned long play_get_type(const struct plugin *pl) {
236 return *(const unsigned long *)get_plugin_object(pl, "disorder_player_type");
237}
238
239/* prefork */
240
241typedef void *prefork_fn(const char *track);
242
243void *play_prefork(const struct plugin *pl,
244 const char *track) {
245 return ((prefork_fn *)get_plugin_function(pl,
246 "disorder_play_prefork"))(track);
247}
248
249/* play */
250
251typedef void play_track_fn(const char *const *parameters,
252 int nparameters,
253 const char *path,
254 const char *track);
255
256void play_track(const struct plugin *pl,
257 const char *const *parameters,
258 int nparameters,
259 const char *path,
260 const char *track) {
261 ((play_track_fn *)get_plugin_function(pl,
262 "disorder_play_track"))(parameters,
263 nparameters,
264 path,
265 track);
266}
267
268/* cleanup */
269
270typedef void cleanup_fn(void *data);
271
272void play_cleanup(const struct plugin *pl, void *data) {
273 ((cleanup_fn *)get_plugin_function(pl, "disorder_play_cleanup"))(data);
274}
275
276/* pause */
277
278typedef int pause_fn(long *playedp, void *data);
279
280int play_pause(const struct plugin *pl, long *playedp, void *data) {
281 return (((pause_fn *)get_plugin_function(pl, "disorder_pause_track"))
282 (playedp, data));
283}
284
285/* resume */
286
287typedef void resume_fn(void *data);
288
289void play_resume(const struct plugin *pl, void *data) {
290 (((resume_fn *)get_plugin_function(pl, "disorder_resume_track"))
291 (data));
292}
293
294/*
295Local Variables:
296c-basic-offset:2
297comment-column:40
298End:
299*/