source: roaraudio/roard/plugins.c @ 5576:a98545bcc3f1

Last change on this file since 5576:a98545bcc3f1 was 5576:a98545bcc3f1, checked in by phi, 12 years ago

Support a common protocol interface (Closes: #257)

File size: 7.7 KB
Line 
1//plugins.c:
2
3/*
4 *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2010-2012
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
21 *  the Free Software Foundation, 51 Franklin Street, Fifth Floor,
22 *  Boston, MA 02110-1301, USA.
23 *
24 */
25
26#include "roard.h"
27
28#define MAX_PLUGINS    8
29
30static struct _roard_plugin {
31 struct roar_dl_lhandle     * lhandle;
32 struct roard_plugins_sched * sched;
33 int protocols[MAX_PROTOS];
34} g_plugins[MAX_PLUGINS];
35static struct _roard_plugin * _pp = NULL;
36
37static int _plugins_inited = 0;
38
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
48static struct _roard_plugin * _find_free(void) {
49 int i;
50
51 for (i = 0; i < MAX_PLUGINS; i++) {
52  if ( g_plugins[i].lhandle == NULL ) {
53   memset(&(g_plugins[i]), 0, sizeof(struct _roard_plugin));
54   return &(g_plugins[i]);
55  }
56 }
57
58 return NULL;
59}
60
61int plugins_preinit  (void) {
62 memset(g_plugins, 0, sizeof(g_plugins));
63
64 return 0;
65}
66
67static void inline plugins_delete(struct _roard_plugin * plugin) {
68 int i;
69
70 if ( plugin->sched != NULL ) {
71  if ( plugin->sched->free != NULL ) {
72   roar_dl_context_restore(plugin->lhandle);
73   plugin->sched->free();
74   roar_dl_context_store(plugin->lhandle);
75  }
76 }
77
78 roar_dl_appsched_trigger(plugin->lhandle, ROAR_DL_APPSCHED_FREE);
79
80 for (i = 0; i < MAX_PROTOS; i++) {
81  if ( plugin->protocols[i] != -1 ) {
82   clients_unregister_proto(plugin->protocols[i]);
83  }
84 }
85
86 roar_dl_close(plugin->lhandle);
87 memset(plugin, 0, sizeof(struct _roard_plugin));
88 plugin->lhandle = NULL;
89}
90
91static int plugins_init_one(struct _roard_plugin * plugin) {
92 if ( plugin == NULL )
93  return -1;
94
95 _pp = plugin;
96 _pp->sched = NULL;
97
98 if ( roar_dl_ra_init(plugin->lhandle, NULL, NULL) == -1 ) {
99  ROAR_WARN("plugins_init(void): Can not RA init lib at %p: %s", plugin->lhandle, roar_error2str(roar_error));
100  plugins_delete(plugin);
101  return -1;
102 }
103
104 if ( plugin->sched != NULL ) {
105  if ( plugin->sched->init != NULL ) {
106   roar_dl_context_restore(plugin->lhandle);
107   plugin->sched->init();
108   roar_dl_context_store(plugin->lhandle);
109  }
110 }
111
112 roar_dl_appsched_trigger(plugin->lhandle, ROAR_DL_APPSCHED_INIT);
113
114 _pp = NULL;
115
116 return 0;
117}
118
119int plugins_init  (void) {
120 size_t i;
121
122 if ( _plugins_inited ) {
123  roar_err_set(ROAR_ERROR_BUSY);
124  return -1;
125 }
126
127 roar_dl_register_fn(ROAR_DL_HANDLE_APPLICATION, ROAR_DL_FN_REGFN, ROAR_DL_FNREG_SUBTYPE, &_plugin_callbacks, ROAR_DL_FNREG_SIZE, ROAR_DL_FNREG_VERSION, ROAR_DL_FNREG_OPT_NONE);
128
129 for (i = 0; i < MAX_PLUGINS; i++) {
130  if ( g_plugins[i].lhandle != NULL ) {
131   plugins_init_one(&(g_plugins[i]));
132  }
133 }
134
135 _plugins_inited = 1;
136
137 return 0;
138}
139
140int plugins_free  (void) {
141 int i;
142
143 for (i = 0; i < MAX_PLUGINS; i++) {
144  if ( g_plugins[i].lhandle != NULL ) {
145   plugins_delete(&(g_plugins[i]));
146  }
147 }
148
149 return plugins_preinit();
150}
151
152int plugins_update   (void) {
153 int ret = 0;
154 int i;
155
156 for (i = 0; i < MAX_PLUGINS; i++) {
157  if ( g_plugins[i].lhandle != NULL ) {
158   if ( g_plugins[i].sched != NULL ) {
159    if ( g_plugins[i].sched->update != NULL ) {
160     roar_dl_context_restore(g_plugins[i].lhandle);
161     if ( g_plugins[i].sched->update() == -1 )
162      ret = -1;
163     roar_dl_context_store(g_plugins[i].lhandle);
164    }
165   }
166   if ( roar_dl_appsched_trigger(g_plugins[i].lhandle, ROAR_DL_APPSCHED_UPDATE) == -1 )
167    if ( roar_error != ROAR_ERROR_NOENT )
168     ret = -1;
169  }
170 }
171
172 return ret;
173}
174
175int plugins_load  (const char * filename, const char * args) {
176 struct _roard_plugin * next = _find_free();
177 struct roar_dl_librarypara * para;
178 int i;
179
180 if ( next == NULL )
181  return -1;
182
183 for (i = 0; i < MAX_PROTOS; i++)
184  next->protocols[i] = -1;
185
186 if ( (para = roar_dl_para_new(args, NULL, ROARD_DL_APPNAME, ROARD_DL_ABIVERSION)) == NULL ) {
187  ROAR_WARN("Can not load plugin (allocate para set): %s: %s", filename, roar_error2str(roar_error));
188  return -1;
189 }
190
191 next->lhandle = roar_dl_open(filename, ROAR_DL_FLAG_PLUGIN, 0 /* we delay this until plugins_init() */, para);
192 roar_dl_para_unref(para);
193
194 if ( next->lhandle == NULL ) {
195  ROAR_ERR("plugins_load(filename='%s'): can not load plugin: %s", filename, roar_dl_errstr(NULL));
196  return -1;
197 }
198
199 if ( _plugins_inited )
200  return plugins_init_one(next);
201
202 return 0;
203}
204
205int plugins_reg_sched(struct roard_plugins_sched * sched) {
206 if ( _pp == NULL )
207  return -1;
208
209 _pp->sched = sched;
210
211 return 0;
212}
213
214int plugins_reg_proto(struct roard_proto         * proto) {
215 int i;
216
217 if ( _pp == NULL )
218  return -1;
219
220 for (i = 0; i < MAX_PROTOS; i++) {
221  if ( _pp->protocols[i] == -1 ) {
222   _pp->protocols[i] = proto->proto;
223   break;
224  }
225 }
226
227 if ( i == MAX_PROTOS ) {
228  roar_err_set(ROAR_ERROR_NOMEM);
229  return -1;
230 }
231
232 return clients_register_proto(proto, _pp->lhandle);
233}
234
235static 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) {
236
237 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);
238
239 switch (fn) {
240  case ROAR_DL_FN_PROTO:
241    if ( subtype != ROAR_DL_PROTO_SUBTYPE ) {
242     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);
243
244     roar_err_set(ROAR_ERROR_TYPEMM);
245     return -1;
246    }
247    if ( objectlen != ROAR_DL_PROTO_SIZE ) {
248     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);
249     roar_err_set(ROAR_ERROR_BADLIB);
250     return -1;
251    }
252    if ( version != ROAR_DL_PROTO_VERSION ) {
253     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);
254     roar_err_set(ROAR_ERROR_BADVERSION);
255     return -1;
256    }
257    switch (action) {
258     case ROAR_DL_FNREG:
259       return clients_register_proto_common(object, lhandle);
260      break;
261     case ROAR_DL_FNUNREG:
262       return clients_unregister_proto(((const struct roard_proto *)object)->proto);
263      break;
264    }
265   break;
266 }
267
268 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);
269 roar_err_set(ROAR_ERROR_NOTSUP);
270 return -1;
271}
272
273//ll
Note: See TracBrowser for help on using the repository browser.