nkeynes@1024 | 1 | /**
|
nkeynes@1024 | 2 | * $Id$
|
nkeynes@1024 | 3 | *
|
nkeynes@1024 | 4 | * Plugin loader code
|
nkeynes@1024 | 5 | *
|
nkeynes@1024 | 6 | * Copyright (c) 2009 Nathan Keynes.
|
nkeynes@1024 | 7 | *
|
nkeynes@1024 | 8 | * This program is free software; you can redistribute it and/or modify
|
nkeynes@1024 | 9 | * it under the terms of the GNU General Public License as published by
|
nkeynes@1024 | 10 | * the Free Software Foundation; either version 2 of the License, or
|
nkeynes@1024 | 11 | * (at your option) any later version.
|
nkeynes@1024 | 12 | *
|
nkeynes@1024 | 13 | * This program is distributed in the hope that it will be useful,
|
nkeynes@1024 | 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
nkeynes@1024 | 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
nkeynes@1024 | 16 | * GNU General Public License for more details.
|
nkeynes@1024 | 17 | */
|
nkeynes@1024 | 18 |
|
nkeynes@1024 | 19 | #include <dirent.h>
|
nkeynes@1024 | 20 | #include <dlfcn.h>
|
nkeynes@1024 | 21 | #include <string.h>
|
nkeynes@1024 | 22 | #include <glib/gmem.h>
|
nkeynes@1024 | 23 | #include <glib/gstrfuncs.h>
|
nkeynes@1024 | 24 | #include "plugin.h"
|
nkeynes@1024 | 25 |
|
nkeynes@1024 | 26 |
|
nkeynes@1024 | 27 | #ifdef APPLE_BUILD
|
nkeynes@1024 | 28 | #define SOEXT ".dylib"
|
nkeynes@1024 | 29 | #else
|
nkeynes@1024 | 30 | #define SOEXT ".so"
|
nkeynes@1024 | 31 | #endif
|
nkeynes@1024 | 32 |
|
nkeynes@1024 | 33 | const char *plugin_type_string[] = { "Undefined", "Audio driver", "Input driver" };
|
nkeynes@1024 | 34 |
|
nkeynes@1024 | 35 | gboolean plugin_load( const gchar *plugin_path )
|
nkeynes@1024 | 36 | {
|
nkeynes@1024 | 37 | void *so = dlopen(plugin_path, RTLD_NOW|RTLD_LOCAL);
|
nkeynes@1024 | 38 | if( so == NULL ) {
|
nkeynes@1024 | 39 | WARN("Failed to load plugin '%s': %s", plugin_path, dlerror());
|
nkeynes@1024 | 40 | return FALSE;
|
nkeynes@1024 | 41 | }
|
nkeynes@1024 | 42 |
|
nkeynes@1024 | 43 | struct plugin_struct *plugin = (struct plugin_struct *)dlsym(so,"lxdream_plugin_entry");
|
nkeynes@1024 | 44 | if( plugin == NULL ) {
|
nkeynes@1024 | 45 | WARN("Failed to load plugin: '%s': Not an lxdream plugin", plugin_path);
|
nkeynes@1024 | 46 | dlclose(so);
|
nkeynes@1024 | 47 | return FALSE;
|
nkeynes@1024 | 48 | }
|
nkeynes@1024 | 49 |
|
nkeynes@1024 | 50 | if( strcmp(lxdream_short_version, plugin->version) != 0 ) {
|
nkeynes@1024 | 51 | WARN("Failed to load plugin: '%s': Incompatible version (%s)", plugin_path, plugin->version);
|
nkeynes@1024 | 52 | dlclose(so);
|
nkeynes@1024 | 53 | return FALSE;
|
nkeynes@1024 | 54 | }
|
nkeynes@1024 | 55 |
|
nkeynes@1024 | 56 | if( plugin->type < PLUGIN_MIN_TYPE || plugin->type > PLUGIN_MAX_TYPE ) {
|
nkeynes@1024 | 57 | WARN("Failed to load plugin: '%s': Unrecognized plugin type (%d)", plugin_path, plugin->type );
|
nkeynes@1024 | 58 | dlclose(so);
|
nkeynes@1024 | 59 | return FALSE;
|
nkeynes@1024 | 60 | }
|
nkeynes@1024 | 61 |
|
nkeynes@1024 | 62 | if( plugin->register_plugin() == FALSE ) {
|
nkeynes@1024 | 63 | WARN("Failed to load plugin: '%s': Initialization failed", plugin_path);
|
nkeynes@1024 | 64 | dlclose(so);
|
nkeynes@1024 | 65 | return FALSE;
|
nkeynes@1024 | 66 | }
|
nkeynes@1024 | 67 | INFO("Loaded %s plugin '%s'", plugin_type_string[plugin->type], plugin->name);
|
nkeynes@1024 | 68 | return TRUE;
|
nkeynes@1024 | 69 | }
|
nkeynes@1024 | 70 |
|
nkeynes@1024 | 71 | /**
|
nkeynes@1024 | 72 | * Scan the plugin dir and load all valid plugins.
|
nkeynes@1024 | 73 | */
|
nkeynes@1024 | 74 | int plugin_init( const gchar *plugin_dir )
|
nkeynes@1024 | 75 | {
|
nkeynes@1024 | 76 | int plugin_count;
|
nkeynes@1024 | 77 | struct dirent *ent;
|
nkeynes@1024 | 78 | DIR *dir = opendir(plugin_dir);
|
nkeynes@1024 | 79 | if( dir == NULL ) {
|
nkeynes@1024 | 80 | WARN( "Unable to open plugin directory '%s'", plugin_dir );
|
nkeynes@1024 | 81 | return 0;
|
nkeynes@1024 | 82 | }
|
nkeynes@1024 | 83 |
|
nkeynes@1024 | 84 | while( (ent = readdir(dir)) != NULL ) {
|
nkeynes@1024 | 85 | const char *ext = strrchr(ent->d_name, '.');
|
nkeynes@1024 | 86 | if( ext != NULL && strcasecmp(SOEXT,ext) == 0 ) {
|
nkeynes@1024 | 87 | char *libname = g_strdup_printf( "%s/%s", plugin_dir,ent->d_name );
|
nkeynes@1024 | 88 | if( plugin_load( libname ) ) {
|
nkeynes@1024 | 89 | plugin_count++;
|
nkeynes@1024 | 90 | }
|
nkeynes@1024 | 91 | g_free(libname);
|
nkeynes@1024 | 92 | }
|
nkeynes@1024 | 93 | }
|
nkeynes@1024 | 94 | return plugin_count;
|
nkeynes@1024 | 95 | }
|