source: roaraudio/roard/plugins.c @ 5575:5293c26f7113

Last change on this file since 5575:5293c26f7113 was 5567:6ecf012d7063, checked in by phi, 12 years ago

roard now tries to auto load missing protocols as plugins (Closes: #275)

File size: 5.0 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
[3362]39static struct _roard_plugin * _find_free(void) {
[3355]40 int i;
41
42 for (i = 0; i < MAX_PLUGINS; i++) {
[3362]43  if ( g_plugins[i].lhandle == NULL ) {
44   memset(&(g_plugins[i]), 0, sizeof(struct _roard_plugin));
[3355]45   return &(g_plugins[i]);
[3362]46  }
[3355]47 }
48
49 return NULL;
50}
51
[3354]52int plugins_preinit  (void) {
[3355]53 memset(g_plugins, 0, sizeof(g_plugins));
54
[3354]55 return 0;
56}
57
[5275]58static void inline plugins_delete(struct _roard_plugin * plugin) {
59 int i;
60
[5312]61 if ( plugin->sched != NULL ) {
62  if ( plugin->sched->free != NULL ) {
63   roar_dl_context_restore(plugin->lhandle);
[5275]64   plugin->sched->free();
[5312]65   roar_dl_context_store(plugin->lhandle);
66  }
67 }
[5275]68
[5319]69 roar_dl_appsched_trigger(plugin->lhandle, ROAR_DL_APPSCHED_FREE);
70
[5275]71 for (i = 0; i < MAX_PROTOS; i++) {
72  if ( plugin->protocols[i] != -1 ) {
73   clients_unregister_proto(plugin->protocols[i]);
74  }
75 }
76
77 roar_dl_close(plugin->lhandle);
78 memset(plugin, 0, sizeof(struct _roard_plugin));
79 plugin->lhandle = NULL;
80}
81
[5567]82static int plugins_init_one(struct _roard_plugin * plugin) {
83 if ( plugin == NULL )
84  return -1;
85
86 _pp = plugin;
87 _pp->sched = NULL;
88
89 if ( roar_dl_ra_init(plugin->lhandle, NULL, NULL) == -1 ) {
90  ROAR_WARN("plugins_init(void): Can not RA init lib at %p: %s", plugin->lhandle, roar_error2str(roar_error));
91  plugins_delete(plugin);
92  return -1;
93 }
94
95 if ( plugin->sched != NULL ) {
96  if ( plugin->sched->init != NULL ) {
97   roar_dl_context_restore(plugin->lhandle);
98   plugin->sched->init();
99   roar_dl_context_store(plugin->lhandle);
100  }
101 }
102
103 roar_dl_appsched_trigger(plugin->lhandle, ROAR_DL_APPSCHED_INIT);
104
105 _pp = NULL;
106
107 return 0;
108}
109
[3354]110int plugins_init  (void) {
[5567]111 size_t i;
112
113 if ( _plugins_inited ) {
114  roar_err_set(ROAR_ERROR_BUSY);
115  return -1;
116 }
[3355]117
118 for (i = 0; i < MAX_PLUGINS; i++) {
[3362]119  if ( g_plugins[i].lhandle != NULL ) {
[5567]120   plugins_init_one(&(g_plugins[i]));
[3355]121  }
122 }
123
[5567]124 _plugins_inited = 1;
125
[3354]126 return 0;
127}
[3353]128
[3354]129int plugins_free  (void) {
[3355]130 int i;
131
132 for (i = 0; i < MAX_PLUGINS; i++) {
[3362]133  if ( g_plugins[i].lhandle != NULL ) {
[5275]134   plugins_delete(&(g_plugins[i]));
[3355]135  }
136 }
137
[3357]138 return plugins_preinit();
[3354]139}
140
[3362]141int plugins_update   (void) {
142 int ret = 0;
143 int i;
144
[5312]145 for (i = 0; i < MAX_PLUGINS; i++) {
146  if ( g_plugins[i].lhandle != NULL ) {
147   if ( g_plugins[i].sched != NULL ) {
148    if ( g_plugins[i].sched->update != NULL ) {
149     roar_dl_context_restore(g_plugins[i].lhandle);
[4682]150     if ( g_plugins[i].sched->update() == -1 )
151      ret = -1;
[5312]152     roar_dl_context_store(g_plugins[i].lhandle);
153    }
154   }
[5319]155   if ( roar_dl_appsched_trigger(g_plugins[i].lhandle, ROAR_DL_APPSCHED_UPDATE) == -1 )
156    if ( roar_error != ROAR_ERROR_NOENT )
157     ret = -1;
[5312]158  }
159 }
[3362]160
161 return ret;
162}
163
[5275]164int plugins_load  (const char * filename, const char * args) {
[3362]165 struct _roard_plugin * next = _find_free();
[5275]166 struct roar_dl_librarypara * para;
167 int i;
[3355]168
169 if ( next == NULL )
170  return -1;
171
[5275]172 for (i = 0; i < MAX_PROTOS; i++)
173  next->protocols[i] = -1;
174
175 if ( (para = roar_dl_para_new(args, NULL, ROARD_DL_APPNAME, ROARD_DL_ABIVERSION)) == NULL ) {
176  ROAR_WARN("Can not load plugin (allocate para set): %s: %s", filename, roar_error2str(roar_error));
177  return -1;
178 }
179
[5427]180 next->lhandle = roar_dl_open(filename, ROAR_DL_FLAG_PLUGIN, 0 /* we delay this until plugins_init() */, para);
[5275]181 roar_dl_para_unref(para);
182
[3365]183 if ( next->lhandle == NULL ) {
184  ROAR_ERR("plugins_load(filename='%s'): can not load plugin: %s", filename, roar_dl_errstr(NULL));
[3355]185  return -1;
[3365]186 }
[3355]187
[5567]188 if ( _plugins_inited )
189  return plugins_init_one(next);
190
[3355]191 return 0;
[3354]192}
[3353]193
[3362]194int plugins_reg_sched(struct roard_plugins_sched * sched) {
195 if ( _pp == NULL )
196  return -1;
197
198 _pp->sched = sched;
199
200 return 0;
201}
202
[4680]203int plugins_reg_proto(struct roard_proto         * proto) {
[5275]204 int i;
205
[4680]206 if ( _pp == NULL )
207  return -1;
208
[5275]209 for (i = 0; i < MAX_PROTOS; i++) {
210  if ( _pp->protocols[i] == -1 ) {
211   _pp->protocols[i] = proto->proto;
212   break;
213  }
214 }
215
216 if ( i == MAX_PROTOS ) {
217  roar_err_set(ROAR_ERROR_NOMEM);
218  return -1;
219 }
220
[5312]221 return clients_register_proto(proto, _pp->lhandle);
[4680]222}
223
[3353]224//ll
Note: See TracBrowser for help on using the repository browser.