00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include <cerrno>
00029
00030 #include <cstdio>
00031 #include <cstring>
00032 #include <cstdlib>
00033
00034
00035 #include <dirent.h>
00036
00037 #include <gmodule.h>
00038
00039 #include "plugin_ctrl.h"
00040
00041
00042
00043
00044
00045 #define GXSM_PI_VOID_PREFIX "_Z"
00046 #define GXSM_PI_VOID_SUFFIX "v"
00047 #define GXSM_PI_VOIDP_SUFFIX "Pv"
00048
00049
00050
00051
00052
00053
00054
00055 gint pi_total = 0;
00056 gint pi_num = 0;
00057
00068 plugin_ctrl::plugin_ctrl(GList *pi_dirlist, gint (*check) (const gchar *)){
00069 GList *node = pi_dirlist;
00070 plugins = NULL;
00071 Check = check;
00072
00073 pi_num=0;
00074 pi_total=1;
00075
00076
00077 gapp->GxsmSplash (-0.1, "...", "Scanning for GXSM Plugins");
00078 XSM_DEBUG (DBG_L3, "Scanning for Plugins");
00079 while(node){
00080 gapp->GxsmSplash (100./(gdouble)pi_total, (gchar *)node->data);
00081 scan_for_pi((gchar *) node->data);
00082 node = node->next;
00083 ++pi_total;
00084 }
00085
00086 gapp->GxsmSplash (0.0, "---", "Initializing GXSM Plugins");
00087 XSM_DEBUG (DBG_L3, "Configuring Plugins");
00088 node = plugins;
00089 while(node){
00090 init_pi((void *) node->data);
00091 node = node->next;
00092 ++pi_num;
00093 }
00094 gapp->GxsmSplash (1.0, "100%", "GXSM Plugins loaded.");
00095 }
00096
00103 plugin_ctrl::~plugin_ctrl(){
00104 GList *node = plugins;
00105 XSM_DEBUG (DBG_L3, "Cleaning up Plugins");
00106 while(node){
00107 cleanup_pi((void *) node->data);
00108 node = node->next;
00109 }
00110 g_list_free(plugins);
00111 XSM_DEBUG (DBG_L3, "Cleaning up Plugins done");
00112 }
00113
00114 void plugin_ctrl::scan_for_pi(gchar *dirname){
00115 gchar *filename, *ext;
00116 DIR *dir;
00117 struct dirent *ent;
00118 struct stat statbuf;
00119
00120 XSM_DEBUG (DBG_L3, "Scanning for GXSM plugins in " << dirname);
00121 dir = opendir(dirname);
00122 if (!dir)
00123 return;
00124
00125 while ((ent = readdir(dir)) != NULL)
00126 {
00127 filename = g_strdup_printf("%s/%s", dirname, ent->d_name);
00128 if (!stat(filename, &statbuf) && S_ISREG(statbuf.st_mode) &&
00129 (ext = strrchr(ent->d_name, '.')) != NULL)
00130 if (!strcmp(ext, SHARED_LIB_EXT_LINUX))
00131 add_pi(filename);
00132 else
00133 if (!strcmp(ext, SHARED_LIB_EXT_DARWIN))
00134 add_pi(filename);
00135 g_free(filename);
00136 }
00137 closedir(dir);
00138 }
00139
00140 void plugin_ctrl::add_pi(gchar *filename){
00141 gint ok;
00142 GModule *gxsm_module;
00143 GxsmPlugin *(*gpi) (void);
00144
00145 XSM_DEBUG (DBG_L3, "Checking Plugin: " << filename );
00146
00147 if ((gxsm_module = g_module_open (filename, G_MODULE_BIND_LAZY)) != NULL)
00148 {
00149 XSM_DEBUG (DBG_L3, " g_module_open OK... checking symbol 'get_gxsm_plugin_info'");
00150
00151
00152 if (g_module_symbol (gxsm_module, "_Z20""get_gxsm_plugin_info"GXSM_PI_VOID_SUFFIX, (gpointer*)&gpi))
00153 {
00154 GxsmPlugin *p = gpi();
00155 ok = TRUE;
00156 if(Check && p -> category)
00157 ok = Check( p -> category );
00158 if(ok){
00159 p->module = gxsm_module;
00160 p->filename = g_strdup(filename);
00161 plugins = g_list_prepend(plugins, p);
00162 XSM_DEBUG (DBG_L3, " ==> " << filename << " added." );
00163 }else{
00164 XSM_DEBUG (DBG_L3, " ==> " << filename << " is OK,\n but not loaded: Category does not match." );
00165 g_module_close(gxsm_module);
00166 }
00167 }
00168 else{
00169 XSM_DEBUG (DBG_L3, "--> symbol not found, no/bad GXSM plugin? :" << g_module_error() );
00170 XSM_DEBUG_ERROR (DBG_L1, " Error: " << g_module_error() );
00171 XSM_DEBUG_ERROR (DBG_L1, " closing module." );
00172 g_module_close(gxsm_module);
00173 }
00174 }
00175 else{
00176 XSM_DEBUG (DBG_L3, "--> module >" << filename << "< not found: " << g_module_error());
00177 XSM_DEBUG_ERROR (DBG_L1, " Error:" << g_module_error() );
00178 g_print ("Error loading PlugIn %s: %s", filename, g_module_error());
00179 }
00180
00181 }
00182
00183
00184
00185 void plugin_ctrl::init_pi(void *pi){
00186 GxsmPlugin *p;
00187
00188 p = (GxsmPlugin *) pi;
00189 if (p) {
00190
00191 gapp->GxsmSplash ((gdouble)pi_num/(gdouble)pi_total, p->filename);
00192 gapp->SetStatus (p->filename);
00193 gdk_flush ();
00194 }
00195 if (p && p->init)
00196 {
00197 p->init();
00198 }
00199 }
00200
00201 void plugin_ctrl::cleanup_pi(void *pi){
00202 GxsmPlugin *p;
00203
00204 p = (GxsmPlugin *) pi;
00205 if (p) {
00206
00207 gapp->SetStatus (p->filename);
00208 gdk_flush ();
00209 }
00210 if (p && p->cleanup)
00211 {
00212 XSM_DEBUG (DBG_L3, "Cleanup: " << p->name);
00213 p->cleanup ();
00214 XSM_DEBUG (DBG_L3, "Cleanup OK, closing module: " << p->filename);
00215 }
00216 if (p){
00217 g_free (p->filename);
00218 g_module_close (p->module);
00219 }
00220 XSM_DEBUG (DBG_L3, "Closed.");
00221 }
00222
00223
00224 void plugin_ctrl::view_pi_info(){
00225 GList *node = plugins;
00226 time_t t;
00227 time (&t);
00228 gchar *pi_status_file = gapp->file_dialog("HTML PlugIn status file to save", ".",
00229 "*.html", "/tmp/gxsm_plugins.html",
00230 "pi_status_save");
00231 if (!pi_status_file) return;
00232 std::ofstream html_file;
00233 html_file.open (pi_status_file);
00234 html_file << "<H2>GXSM - List of Plug-Ins</H2>" << std::endl
00235 << "Dump of all GXSM Plug-In Information Structure Data, "
00236 << "generated by \"GXSM->Tools->Plugin Info\"." << std::endl
00237 << "See also the GXSM manual for a complete PlugIn documentation." << std::endl
00238 << "<p>Table of all GXSM Plug-Ins:" << std::endl
00239 << "<p>" << std::endl;
00240
00241 html_file << "<table cellspacing=\"1\" cellpadding=\"5\" width=\"100%\" border=\"0\" bgcolor=\"#FAFCFF\">" << std::endl;
00242 #define PLUGIN_NAME_TR_TAG_HTML "<tr valign=top BGCOLOR=\"#CACCCF\">"
00243 #define PLUGIN_INFO_TR_TAG_HTML "<tr valign=top BGCOLOR=\"#EAECEF\">"
00244 int count=0;
00245 while (node){
00246 GxsmPlugin *p;
00247 html_file << PLUGIN_NAME_TR_TAG_HTML << std::endl;
00248 p = (GxsmPlugin *) node->data;
00249 if (p){
00250 html_file << "<td>" << ++count << "</td><td> Plugin \"" << p->name << "\"</td>" << std::endl;
00251 } else {
00252 html_file << "<td>Error:</td><td> no PlugIn info data available for"
00253 << p->filename << "</td>" << std::endl;
00254 }
00255 html_file << "</tr>" << std::endl;
00256 if (p && p->description && p->menupath)
00257 {
00258 html_file << PLUGIN_INFO_TR_TAG_HTML << std::endl
00259 << "<td>Pluginpath</td><td>" << p->filename << "</td></tr>" << std::endl
00260 << PLUGIN_INFO_TR_TAG_HTML << std::endl
00261 << "<td>Name</td><td>" << p->name << "</td></tr>" << std::endl
00262 << PLUGIN_INFO_TR_TAG_HTML << std::endl
00263 << "<td>Description</td><td>" << p->description << "</td></tr>" << std::endl
00264 << PLUGIN_INFO_TR_TAG_HTML << std::endl
00265 << "<td>Categorie</td><td>" << (p->category ? p->category:N_("(NULL): All")) << "</td></tr>" << std::endl
00266 << PLUGIN_INFO_TR_TAG_HTML << std::endl
00267 << "<td>Author</td><td>" << p->authors << "</td></tr>" << std::endl
00268 << PLUGIN_INFO_TR_TAG_HTML << std::endl
00269 << "<td>Menupath</td><td>" << p->menupath << p->menuentry << "</td></tr>" << std::endl
00270 << PLUGIN_INFO_TR_TAG_HTML << std::endl
00271 << "<td>Help </td><td>" << (p->help ? p->help:"--") << "</td></tr>" << std::endl
00272 << PLUGIN_INFO_TR_TAG_HTML << std::endl
00273 << "<td>Info </td><td>" << (p->info ? p->info:"--") << "</td></tr>" << std::endl
00274 << PLUGIN_INFO_TR_TAG_HTML << std::endl
00275 << "<td>Error </td><td>" << (p->errormsg ? p->errormsg:N_("--")) << "</td></tr>" << std::endl
00276 << PLUGIN_INFO_TR_TAG_HTML << std::endl
00277 << "<td>Status</td><td>" << (p->status ? p->status:N_("--")) << "</td></tr>" << std::endl
00278 << PLUGIN_INFO_TR_TAG_HTML << std::endl
00279 << "<td>Init-F </td><td>" << (p->init? N_("Yes"):N_("No")) << "</td></tr>" << std::endl
00280 << PLUGIN_INFO_TR_TAG_HTML << std::endl
00281 << "<td>Query-F </td><td>" << (p->query? N_("Yes"):N_("No")) << "</td></tr>" << std::endl
00282 << PLUGIN_INFO_TR_TAG_HTML << std::endl
00283 << "<td>About-F </td><td>" << (p->about? N_("Yes"):N_("No")) << "</td></tr>" << std::endl
00284 << PLUGIN_INFO_TR_TAG_HTML << std::endl
00285 << "<td>Configure-F</td><td>" << (p->configure?N_("Yes"):N_("No")) << "</td></tr>" << std::endl
00286 << PLUGIN_INFO_TR_TAG_HTML << std::endl
00287 << "<td>Run-F </td><td>" << (p->run? N_("Yes"):N_("No")) << "</td></tr>" << std::endl
00288 << PLUGIN_INFO_TR_TAG_HTML << std::endl
00289 << "<td>Cleanup-F </td><td>" << (p->cleanup? N_("Yes"):N_("No")) << "</td></tr>" << std::endl
00290 ;
00291 }
00292 else
00293 html_file << PLUGIN_INFO_TR_TAG_HTML << std::endl
00294 << "<td>Sorry</td><td>Plugin has no description/menupath!</td></tr>" << std::endl;
00295
00296 node = node->next;
00297 }
00298
00299 html_file << "</table>" << std::endl
00300 << "<p>" << std::endl
00301 << "Last Updated: " << ctime(&t) << "<p>" << std::endl;
00302 html_file.close ();
00303 }
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316 #define GXSM_PI_MATH_TYPE_MANGLE_NAME(NN,symbol) GXSM_PI_VOID_PREFIX""NN"get_gxsm_math_"symbol"_plugin_info"GXSM_PI_VOID_SUFFIX
00317
00318
00319 gxsm_plugins::gxsm_plugins(App *app, GList *pi_dirlist, gint (*check)(const gchar *))
00320 : plugin_ctrl(pi_dirlist, check){
00321 GList *node;
00322 GxsmPlugin *p;
00323 void *(*gpi) (void);
00324 static GnomeUIInfo menuinfo[] = {
00325 { GNOME_APP_UI_ITEM, NULL, NULL, NULL, NULL,
00326 NULL, GNOME_APP_PIXMAP_STOCK, GNOME_STOCK_MENU_BLANK,
00327 0, GDK_CONTROL_MASK, NULL },
00328 GNOMEUIINFO_END
00329 };
00330
00331
00332 XSM_DEBUG (DBG_L3, "Configuring GXSM Plugins");
00333 node = plugins;
00334
00335 while(node) {
00336 p = (GxsmPlugin *) node->data;
00337
00338 p->app = app;
00339 XSM_DEBUG (DBG_L3, "Setting up menus, ...: " << p->name);
00340
00341
00342
00343 if( p->query ){
00344 p->query ();
00345 }
00346
00347 if( !p->query || p->status){
00348 if (p->status)
00349 XSM_DEBUG (DBG_L3, "Special Plugin Query instruction: " << p->status);
00350
00351 if( p && p->menupath && p->menuentry ){
00352 menuinfo[0].label = p -> menuentry;
00353 menuinfo[0].hint = p -> help;
00354
00355 if(p->run){
00356 menuinfo[0].moreinfo = (gpointer) p -> run;
00357 menuinfo[0].user_data = p -> name;
00358 } else {
00359
00360 if (g_module_symbol (p->module, GXSM_PI_MATH_TYPE_MANGLE_NAME("33","one_src"), (gpointer*)&gpi)){
00361 menuinfo[0].moreinfo = (gpointer) App::math_onearg_callback;
00362 menuinfo[0].user_data = (gpointer) ((GxsmMathOneSrcPlugin *) gpi()) -> run;
00363 } else
00364 if (g_module_symbol (p->module, GXSM_PI_MATH_TYPE_MANGLE_NAME("33","two_src"), (gpointer*)&gpi)){
00365 menuinfo[0].moreinfo = (gpointer) App::math_twoarg_callback;
00366 menuinfo[0].user_data = (gpointer) ((GxsmMathTwoSrcPlugin *) gpi()) -> run;
00367 } else
00368 if (g_module_symbol (p->module, GXSM_PI_MATH_TYPE_MANGLE_NAME("52","two_src_no_same_size_check"), (gpointer*)&gpi)){
00369 menuinfo[0].moreinfo = (gpointer) App::math_twoarg_no_same_size_check_callback;
00370 menuinfo[0].user_data = (gpointer) ((GxsmMathTwoSrcPlugin *) gpi()) -> run;
00371 } else
00372 if (g_module_symbol (p->module, GXSM_PI_MATH_TYPE_MANGLE_NAME("41","one_src_no_dest"), (gpointer*)&gpi)){
00373 menuinfo[0].moreinfo = (gpointer) App::math_onearg_nodest_callback;
00374 menuinfo[0].user_data = (gpointer) ((GxsmMathOneSrcNoDestPlugin *) gpi()) -> run;
00375 } else {
00376 XSM_DEBUG (DBG_L3, "Bad Plugin Descriptor found/type unknown: " << p->name);
00377 menuinfo[0].moreinfo = NULL;
00378 menuinfo[0].user_data = NULL;
00379 if(p->status) g_free(p->status);
00380 p->status = g_strconcat(N_("Type of Plugin with "),
00381 p->name,
00382 N_(" is not recognized, it's not attached and not usable yet."),
00383 NULL);
00384 }
00385 }
00386
00387 if( menuinfo[0].moreinfo ){
00388 gnome_app_insert_menus(GNOME_APP(app->getApp()), p->menupath, menuinfo);
00389 if(p->status) g_free(p->status);
00390 p->status = g_strconcat(N_("Plugin "),
00391 p->name,
00392 N_(" is attached and ready to use"),
00393 NULL);
00394 }
00395 }
00396 }
00397 node = node->next;
00398 }
00399 }
00400
00401 gxsm_plugins::~gxsm_plugins(){
00402 GList *node;
00403 GxsmPlugin *p;
00404
00405
00406 XSM_DEBUG (DBG_L3, "Removing GXSM Plugins");
00407
00408 for(node = plugins; node; node = node->next){
00409 if( !( p = (GxsmPlugin *) node->data ))
00410 continue;
00411 XSM_DEBUG (DBG_L3, "Removing: " << p->name);
00412
00413 if( p->status ){
00414 g_free( p->status );
00415 p->status = NULL;
00416 }
00417 if( p->description ){
00418 g_free( p->description );
00419 p->description = NULL;
00420 }
00421 if( p->menupath && p->menuentry ){
00422 gchar *mp = g_strconcat(p->menupath, p->menuentry, NULL);
00423 gpointer dummy;
00424
00425 if ( p->run ||
00426 g_module_symbol (p->module, GXSM_PI_MATH_TYPE_MANGLE_NAME("41","one_src_no_dest"), &dummy) ||
00427 g_module_symbol (p->module, GXSM_PI_MATH_TYPE_MANGLE_NAME("33","one_src"), &dummy) ||
00428 g_module_symbol (p->module, GXSM_PI_MATH_TYPE_MANGLE_NAME("52","two_src_no_same_size_check"), &dummy) ||
00429 g_module_symbol (p->module, GXSM_PI_MATH_TYPE_MANGLE_NAME("33","two_src"), &dummy) )
00430 gnome_app_remove_menus (GNOME_APP( p->app->getApp() ),
00431 (const gchar*) mp, 1);
00432 if(mp) g_free(mp);
00433 }
00434 }
00435 }
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446 #define MSG_OUT std::cerr
00447 #define XSM_HWI_DEBUG(L, DBGTXT) do { if(debug_level > L) MSG_OUT << "** (" << __FILE__ << ": " << __FUNCTION__ << ") Gxsm-DEBUG-MESSAGE **: " << NEWLINE << " - " << DBGTXT << NEWLINE; } while(0)
00448
00449 #define GXSM_HWI_TYPE_MANGLE_NAME GXSM_PI_VOID_PREFIX"27""get_gxsm_hwi_hardware_class"GXSM_PI_VOIDP_SUFFIX
00450
00451 gxsm_hwi_plugins::gxsm_hwi_plugins (GList *pi_dirlist, gint (*check)(const gchar *), gchar *fulltype, App* app)
00452 : plugin_ctrl(pi_dirlist, check){
00453 GList *node;
00454 GxsmPlugin *p;
00455 void *(*gpi) (void *);
00456
00457 xsm_hwi_class = NULL;
00458
00459
00460 XSM_HWI_DEBUG (DBG_L3, "Setting up GXSM HwI Plugin(s)");
00461 node = plugins;
00462 if (!node){
00463 XSM_HWI_DEBUG (DBG_L3, "No GXSM HwI Plugin(s) found!!");
00464 }
00465 while(node){
00466 p = (GxsmPlugin *) node->data;
00467 p->app = app;
00468 XSM_HWI_DEBUG (DBG_L3, "Asking HwI-PI for XSM_Hardware class reference :: " << p->name);
00469
00470
00471
00472 if (g_module_symbol (p->module, GXSM_HWI_TYPE_MANGLE_NAME, (gpointer*)&gpi)){
00473 if (p->status) g_free(p->status);
00474 if ((xsm_hwi_class = (XSM_Hardware*) gpi ((void*) fulltype)))
00475 p->status = g_strconcat ("HwI <", fulltype ? fulltype:"NULL", "> is selected.", NULL);
00476 else
00477 p->status = g_strconcat ("HwI class request error: <", fulltype ? fulltype:"NULL", "> not available.", NULL);
00478 XSM_HWI_DEBUG (DBG_L3, "Status: '" << p->status << "' :: " << p->name);
00479 }
00480
00481
00482 XSM_HWI_DEBUG (DBG_L3, "Looking for Query/Selfinstall of HwI PI :: " << p->name);
00483 if( p->query ){
00484 p->query();
00485 }
00486 else{
00487 XSM_HWI_DEBUG (DBG_L3, "No Query/Selfinstall func. of HwI PI :: " << p->name);
00488 }
00489
00490 node = node->next;
00491 }
00492 }
00493
00494
00495 gxsm_hwi_plugins::~gxsm_hwi_plugins(){
00496 GList *node;
00497 GxsmPlugin *p;
00498
00499
00500 XSM_HWI_DEBUG (DBG_L3, "Removing GXSM HwI Plugins");
00501
00502 xsm_hwi_class = NULL;
00503
00504 if (!plugins) return;
00505
00506 for(node = plugins; node; node = node->next){
00507 if( !( p = (GxsmPlugin *) node->data ))
00508 continue;
00509 XSM_HWI_DEBUG (DBG_L3, "Removing HwI PI: " << p->name);
00510
00511 if( p->status ){
00512 g_free( p->status );
00513 p->status = NULL;
00514 }
00515 if( p->description ){
00516 g_free( p->description );
00517 p->description = NULL;
00518 }
00519 }
00520 }
00521
00522 XSM_Hardware* gxsm_hwi_plugins::get_xsm_hwi_class (gchar *hwi_sub_type)
00523 {
00524 return xsm_hwi_class;
00525 }