source: roaraudio/roard/plugins.c @ 5607:9b10a70d82e4

Last change on this file since 5607:9b10a70d82e4 was 5592:da9a9bb6ece0, checked in by phi, 12 years ago

addded --list-plugins

File size: 9.2 KB
RevLine 
[3353]1//plugins.c:
2
3/*
[5381]4 *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2010-2012
[3353]5 *
6 *  This file is part of roard a part of RoarAudio,
7 *  a cross-platform sound system for both, home and professional use.
8 *  See README for details.
9 *
10 *  This file is free software; you can redistribute it and/or modify
11 *  it under the terms of the GNU General Public License version 3
12 *  as published by the Free Software Foundation.
13 *
14 *  RoarAudio is distributed in the hope that it will be useful,
15 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 *  GNU General Public License for more details.
18 *
19 *  You should have received a copy of the GNU General Public License
20 *  along with this software; see the file COPYING.  If not, write to
[3517]21 *  the Free Software Foundation, 51 Franklin Street, Fifth Floor,
22 *  Boston, MA 02110-1301, USA.
[3353]23 *
24 */
25
26#include "roard.h"
27
[3355]28#define MAX_PLUGINS    8
29
[3362]30static struct _roard_plugin {
31 struct roar_dl_lhandle     * lhandle;
32 struct roard_plugins_sched * sched;
[5275]33 int protocols[MAX_PROTOS];
[3362]34} g_plugins[MAX_PLUGINS];
35static struct _roard_plugin * _pp = NULL;
[3355]36
[5567]37static int _plugins_inited = 0;
38
[5576]39static int plugin_callback(enum roar_dl_fnreg_action action, int fn, int subtype, const void * object, size_t objectlen, int version, int options, void * userdata, struct roar_dl_lhandle * lhandle);
40static const struct roar_dl_fnreg _plugin_callbacks = {
41 .fn = -1,
42 .subtype = -1,
43 .version = -1,
44 .callback = plugin_callback,
45 .userdata = NULL
46};
47
[3362]48static struct _roard_plugin * _find_free(void) {
[3355]49 int i;
50
[5592]51 ROAR_DBG("_find_free(void) = ?");
52
[3355]53 for (i = 0; i < MAX_PLUGINS; i++) {
[3362]54  if ( g_plugins[i].lhandle == NULL ) {
55   memset(&(g_plugins[i]), 0, sizeof(struct _roard_plugin));
[5592]56   ROAR_DBG("_find_free(void) = %p // i=%i", &(g_plugins[i]), i);
[3355]57   return &(g_plugins[i]);
[3362]58  }
[3355]59 }
60
[5592]61 ROAR_DBG("_find_free(void) = NULL");
[3355]62 return NULL;
63}
64
[3354]65int plugins_preinit  (void) {
[5592]66 ROAR_DBG("plugins_preinit(void) = ?");
67
[3355]68 memset(g_plugins, 0, sizeof(g_plugins));
69
[5592]70#ifdef DEBUG
71 print_pluginlist(FORMAT_NATIVE);
72#endif
73
74 ROAR_DBG("plugins_preinit(void) = 0");
[3354]75 return 0;
76}
77
[5586]78static inline void plugins_delete(struct _roard_plugin * plugin) {
[5275]79 int i;
80
[5592]81 ROAR_DBG("plugins_delete(plugin=%p) = ?", plugin);
82
[5312]83 if ( plugin->sched != NULL ) {
84  if ( plugin->sched->free != NULL ) {
85   roar_dl_context_restore(plugin->lhandle);
[5275]86   plugin->sched->free();
[5312]87   roar_dl_context_store(plugin->lhandle);
88  }
89 }
[5275]90
[5319]91 roar_dl_appsched_trigger(plugin->lhandle, ROAR_DL_APPSCHED_FREE);
92
[5275]93 for (i = 0; i < MAX_PROTOS; i++) {
94  if ( plugin->protocols[i] != -1 ) {
95   clients_unregister_proto(plugin->protocols[i]);
96  }
97 }
98
99 roar_dl_close(plugin->lhandle);
100 memset(plugin, 0, sizeof(struct _roard_plugin));
101 plugin->lhandle = NULL;
102}
103
[5567]104static int plugins_init_one(struct _roard_plugin * plugin) {
105 if ( plugin == NULL )
106  return -1;
107
[5592]108 ROAR_DBG("plugins_init_one(plugin=%p) = ?", plugin);
109
[5567]110 _pp = plugin;
111 _pp->sched = NULL;
112
113 if ( roar_dl_ra_init(plugin->lhandle, NULL, NULL) == -1 ) {
114  ROAR_WARN("plugins_init(void): Can not RA init lib at %p: %s", plugin->lhandle, roar_error2str(roar_error));
115  plugins_delete(plugin);
116  return -1;
117 }
118
119 if ( plugin->sched != NULL ) {
120  if ( plugin->sched->init != NULL ) {
121   roar_dl_context_restore(plugin->lhandle);
122   plugin->sched->init();
123   roar_dl_context_store(plugin->lhandle);
124  }
125 }
126
127 roar_dl_appsched_trigger(plugin->lhandle, ROAR_DL_APPSCHED_INIT);
128
129 _pp = NULL;
130
131 return 0;
132}
133
[3354]134int plugins_init  (void) {
[5567]135 size_t i;
136
[5592]137 ROAR_DBG("plugins_init(void) = ?");
138
139#ifdef DEBUG
140 print_pluginlist(FORMAT_NATIVE);
141#endif
142
[5567]143 if ( _plugins_inited ) {
[5592]144  ROAR_DBG("plugins_init(void) = -1 // error=BUSY");
[5567]145  roar_err_set(ROAR_ERROR_BUSY);
146  return -1;
147 }
[3355]148
[5582]149 ROAR_DL_RFNREG(ROAR_DL_HANDLE_APPLICATION, _plugin_callbacks);
[5576]150
[3355]151 for (i = 0; i < MAX_PLUGINS; i++) {
[3362]152  if ( g_plugins[i].lhandle != NULL ) {
[5567]153   plugins_init_one(&(g_plugins[i]));
[3355]154  }
155 }
156
[5567]157 _plugins_inited = 1;
158
[5592]159#ifdef DEBUG
160 print_pluginlist(FORMAT_NATIVE);
161#endif
162
163 ROAR_DBG("plugins_init(void) = 0");
[3354]164 return 0;
165}
[3353]166
[3354]167int plugins_free  (void) {
[3355]168 int i;
169
[5592]170 ROAR_DBG("plugins_free(void) = ?");
171
[3355]172 for (i = 0; i < MAX_PLUGINS; i++) {
[3362]173  if ( g_plugins[i].lhandle != NULL ) {
[5275]174   plugins_delete(&(g_plugins[i]));
[3355]175  }
176 }
177
[3357]178 return plugins_preinit();
[3354]179}
180
[3362]181int plugins_update   (void) {
182 int ret = 0;
183 int i;
184
[5312]185 for (i = 0; i < MAX_PLUGINS; i++) {
186  if ( g_plugins[i].lhandle != NULL ) {
187   if ( g_plugins[i].sched != NULL ) {
188    if ( g_plugins[i].sched->update != NULL ) {
189     roar_dl_context_restore(g_plugins[i].lhandle);
[4682]190     if ( g_plugins[i].sched->update() == -1 )
191      ret = -1;
[5312]192     roar_dl_context_store(g_plugins[i].lhandle);
193    }
194   }
[5319]195   if ( roar_dl_appsched_trigger(g_plugins[i].lhandle, ROAR_DL_APPSCHED_UPDATE) == -1 )
196    if ( roar_error != ROAR_ERROR_NOENT )
197     ret = -1;
[5312]198  }
199 }
[3362]200
201 return ret;
202}
203
[5275]204int plugins_load  (const char * filename, const char * args) {
[3362]205 struct _roard_plugin * next = _find_free();
[5275]206 struct roar_dl_librarypara * para;
207 int i;
[3355]208
[5592]209 ROAR_DBG("plugins_load(filename=\"%s\", args=\"%s\") = ?", filename, args);
210
[3355]211 if ( next == NULL )
212  return -1;
213
[5592]214 for (i = 0; i < MAX_PLUGINS; i++)
[5275]215  next->protocols[i] = -1;
216
217 if ( (para = roar_dl_para_new(args, NULL, ROARD_DL_APPNAME, ROARD_DL_ABIVERSION)) == NULL ) {
218  ROAR_WARN("Can not load plugin (allocate para set): %s: %s", filename, roar_error2str(roar_error));
219  return -1;
220 }
221
[5427]222 next->lhandle = roar_dl_open(filename, ROAR_DL_FLAG_PLUGIN, 0 /* we delay this until plugins_init() */, para);
[5275]223 roar_dl_para_unref(para);
224
[3365]225 if ( next->lhandle == NULL ) {
226  ROAR_ERR("plugins_load(filename='%s'): can not load plugin: %s", filename, roar_dl_errstr(NULL));
[3355]227  return -1;
[3365]228 }
[3355]229
[5567]230 if ( _plugins_inited )
231  return plugins_init_one(next);
232
[3355]233 return 0;
[3354]234}
[3353]235
[5592]236void print_pluginlist(enum output_format format) {
237 const struct roar_dl_libraryname * libname;
238 struct _roard_plugin * p;
239 size_t i;
240
241 switch (format) {
242  case FORMAT_NATIVE:
243    printf("  Name\n");
244    printf("   Attributes\n");
245    printf("-----------------------------------------------------\n");
246   break;
247  case FORMAT_WIKI:
248  case FORMAT_CSV:
249  default:
250    roar_err_set(ROAR_ERROR_NOTSUP);
251    return;
252 }
253
254 for (i = 0; i < MAX_PLUGINS; i++) {
255  p = &(g_plugins[i]);
256  if ( p->lhandle == NULL )
257   continue;
258
259  libname = roar_dl_getlibname(p->lhandle);
260  if ( libname == NULL ) {
261  } else {
262   printf("  %s\n", libname->libname);
263   printf("   Flags:       %s\n", p->sched != NULL ? "roardsched" : "");
264   if ( libname->description != NULL )
265    printf("   Description: %s\n", libname->description);
266   if ( libname->contact != NULL )
267    printf("   Contact:     %s\n", libname->contact);
268  }
269 }
270}
271
[3362]272int plugins_reg_sched(struct roard_plugins_sched * sched) {
273 if ( _pp == NULL )
274  return -1;
275
276 _pp->sched = sched;
277
278 return 0;
279}
280
[4680]281int plugins_reg_proto(struct roard_proto         * proto) {
[5275]282 int i;
283
[4680]284 if ( _pp == NULL )
285  return -1;
286
[5275]287 for (i = 0; i < MAX_PROTOS; i++) {
288  if ( _pp->protocols[i] == -1 ) {
289   _pp->protocols[i] = proto->proto;
290   break;
291  }
292 }
293
294 if ( i == MAX_PROTOS ) {
295  roar_err_set(ROAR_ERROR_NOMEM);
296  return -1;
297 }
298
[5312]299 return clients_register_proto(proto, _pp->lhandle);
[4680]300}
301
[5576]302static int plugin_callback(enum roar_dl_fnreg_action action, int fn, int subtype, const void * object, size_t objectlen, int version, int options, void * userdata, struct roar_dl_lhandle * lhandle) {
303
[5586]304 (void)options, (void)userdata;
305
[5576]306 ROAR_DBG("plugin_callback(action=%i, fn=%i, subtype=%i, object=%p, objectlen=%llu, version=%i, options=0x%x, userdata=%p, lhandle=%p) = ?", (int)action, fn, subtype, object, (long long unsigned int)objectlen, version, options, userdata, lhandle);
307
308 switch (fn) {
309  case ROAR_DL_FN_PROTO:
310    if ( subtype != ROAR_DL_PROTO_SUBTYPE ) {
311     ROAR_DBG("plugin_callback(action=%i, fn=%i, subtype=%i, object=%p, objectlen=%llu, version=%i, options=0x%x, userdata=%p, lhandle=%p) = -1 // error=TYPEMM", (int)action, fn, subtype, object, (long long unsigned int)objectlen, version, options, userdata, lhandle);
312
313     roar_err_set(ROAR_ERROR_TYPEMM);
314     return -1;
315    }
316    if ( objectlen != ROAR_DL_PROTO_SIZE ) {
317     ROAR_DBG("plugin_callback(action=%i, fn=%i, subtype=%i, object=%p, objectlen=%llu, version=%i, options=0x%x, userdata=%p, lhandle=%p) = -1 // error=BADLIB", (int)action, fn, subtype, object, (long long unsigned int)objectlen, version, options, userdata, lhandle);
318     roar_err_set(ROAR_ERROR_BADLIB);
319     return -1;
320    }
321    if ( version != ROAR_DL_PROTO_VERSION ) {
322     ROAR_DBG("plugin_callback(action=%i, fn=%i, subtype=%i, object=%p, objectlen=%llu, version=%i, options=0x%x, userdata=%p, lhandle=%p) = -1 // error=BADVERSION", (int)action, fn, subtype, object, (long long unsigned int)objectlen, version, options, userdata, lhandle);
323     roar_err_set(ROAR_ERROR_BADVERSION);
324     return -1;
325    }
326    switch (action) {
327     case ROAR_DL_FNREG:
328       return clients_register_proto_common(object, lhandle);
329      break;
330     case ROAR_DL_FNUNREG:
331       return clients_unregister_proto(((const struct roard_proto *)object)->proto);
332      break;
333    }
334   break;
335 }
336
337 ROAR_DBG("plugin_callback(action=%i, fn=%i, subtype=%i, object=%p, objectlen=%llu, version=%i, options=0x%x, userdata=%p, lhandle=%p) = -1 // error=NOTSUP", (int)action, fn, subtype, object, (long long unsigned int)objectlen, version, options, userdata, lhandle);
338 roar_err_set(ROAR_ERROR_NOTSUP);
339 return -1;
340}
341
[3353]342//ll
Note: See TracBrowser for help on using the repository browser.