Search
lxdream.org :: lxdream/src/plugin.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/plugin.c
changeset 1075:1a21750d300c
prev1071:182cfe43c09e
next1296:30ecee61f811
author nkeynes
date Tue Feb 28 17:27:39 2012 +1000 (12 years ago)
permissions -rw-r--r--
last change Pass the application home dir through to the native code, so we can use it
as the default data directory
view annotate diff log raw
     1 /**
     2  * $Id$
     3  *
     4  * Plugin loader code
     5  *
     6  * Copyright (c) 2009 Nathan Keynes.
     7  *
     8  * This program is free software; you can redistribute it and/or modify
     9  * it under the terms of the GNU General Public License as published by
    10  * the Free Software Foundation; either version 2 of the License, or
    11  * (at your option) any later version.
    12  *
    13  * This program is distributed in the hope that it will be useful,
    14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    16  * GNU General Public License for more details.
    17  */
    19 #include <sys/stat.h>
    20 #include <dirent.h>
    21 #include <dlfcn.h>
    22 #include <string.h>
    23 #include <glib/gmem.h>
    24 #include <glib/gstrfuncs.h>
    25 #include "plugin.h"
    26 #include "lxpaths.h"
    28 #ifdef APPLE_BUILD
    29 #define SOEXT ".dylib"
    30 #else
    31 #define SOEXT ".so"
    32 #endif
    34 /** Dummy plugin used as a plugin directory marker */
    35 #define DUMMY_PLUGIN ("lxdream_dummy" SOEXT) 
    37 const char *plugin_type_string[] = { "undefined", "audio driver", "input driver" };
    39 int main(int argc, char *argv[]);
    40 static const char *exec_path = NULL;
    42 /**
    43  * Return the full path to the main binary
    44  */
    45 static const char *get_exec_path()
    46 {
    47     if( exec_path == NULL ) {
    48         Dl_info dli;
    50         /* Use dladdr for this, since it should be available for any platform
    51          * that we can support plugins on at all.
    52          */
    53         if( dladdr( main, &dli) ) {
    54             gchar *path = g_strdup( dli.dli_fname );
    55             char *i = strrchr( path, '/' );
    56             if( i > path ) {
    57                 *i = '\0';
    58                 exec_path = path;
    59             } else {
    60                 g_free(path);
    61             }
    62         }
    63     }
    64     return exec_path;
    65 }
    67 static gboolean plugin_load( const gchar *plugin_path )
    68 {
    69     void *so = dlopen(plugin_path, RTLD_NOW|RTLD_LOCAL);
    70     if( so == NULL ) {
    71         WARN("Failed to load plugin '%s': %s", plugin_path, dlerror());
    72         return FALSE;
    73     }
    75     struct plugin_struct *plugin = (struct plugin_struct *)dlsym(so,"lxdream_plugin_entry");
    76     if( plugin == NULL ) {
    77         WARN("Failed to load plugin: '%s': Not an lxdream plugin", plugin_path);
    78         dlclose(so);
    79         return FALSE;
    80     }
    82     if( strcmp(lxdream_short_version, plugin->version) != 0 ) {
    83         WARN("Failed to load plugin: '%s': Incompatible version (%s)", plugin_path, plugin->version);
    84         dlclose(so);
    85         return FALSE;
    86     }
    88     if( plugin->type == PLUGIN_NONE ) {
    89         /* 'dummy' plugin - we don't actually want to load it */
    90         dlclose(so);
    91         return FALSE;
    92     }
    94     if( plugin->type < PLUGIN_MIN_TYPE || plugin->type > PLUGIN_MAX_TYPE ) {
    95         WARN("Failed to load plugin: '%s': Unrecognized plugin type (%d)", plugin_path, plugin->type );
    96         dlclose(so);
    97         return FALSE;
    98     }
   100     if( plugin->register_plugin() == FALSE ) {
   101         WARN("Failed to load plugin: '%s': Initialization failed", plugin_path);
   102         dlclose(so);
   103         return FALSE;
   104     }
   105     DEBUG("Loaded %s '%s'", plugin_type_string[plugin->type], plugin->name);
   106     return TRUE;
   107 }
   109 static gboolean has_plugins( const gchar *path )
   110 {
   111     struct stat st;
   113     gchar *dummy_name = g_strdup_printf( "%s/%s", path, DUMMY_PLUGIN );
   114     if( stat( dummy_name, &st ) == 0 ) {
   115         return TRUE;
   116     } else {
   117         return FALSE;
   118     }
   119 }
   121 /**
   122  * Scan the plugin dir and load all valid plugins.
   123  */
   124 static int plugin_load_all( const gchar *plugin_dir )
   125 {
   126     int plugin_count = 0;
   127     struct dirent *ent;
   129     DIR *dir = opendir(plugin_dir);
   130     if( dir == NULL ) {
   131         WARN( "Unable to open plugin directory '%s'", plugin_dir );
   132         return 0;
   133     }
   135     while( (ent = readdir(dir)) != NULL ) {
   136         const char *ext = strrchr(ent->d_name, '.');
   137         if( ext != NULL && strcasecmp(SOEXT,ext) == 0 ) {
   138             char *libname = g_strdup_printf( "%s/%s", plugin_dir,ent->d_name );
   139             if( plugin_load( libname ) ) {
   140                 plugin_count++;
   141             }
   142             g_free(libname);
   143         }
   144     }
   145     return plugin_count;
   146 }
   148 int plugin_init()
   149 {
   150     const char *path = get_exec_path();
   151     if( path == NULL || !has_plugins(path) ) {
   152         path = get_plugin_path();
   153     }
   155     DEBUG( "Plugin directory: %s", path );
   156     return plugin_load_all( path );
   157 }
.