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 #include <stdio.h>
00027 #include <stdlib.h>
00028 #include <string.h>
00029 #include <syslog.h>
00030
00031 #include <common/xmalloc.h>
00032 #include <common/xmlt.h>
00033 #include <drivers/backend.h>
00034
00035 #include "ltdl.h"
00036 #include "drivers.h"
00037
00038 #ifndef FLCDD_MODULE_PATH_ENV
00039 # define FLCDD_MODULE_PATH_ENV "FLCDD_MODULE_PATH"
00040 #endif
00041
00042 typedef enum { DRIVER = 0, BACKEND = 1 } tag_idx;
00043 typedef enum { NAME = 0 } attr_idx;
00044
00045 static tag_idx tag_array[] = { DRIVER, BACKEND };
00046 static attr_idx attr_array[] = { NAME };
00047
00048 static dict_pair tag_translate[] = {
00049 { "backend", &tag_array[BACKEND] },
00050 { "driver", &tag_array[DRIVER] }
00051 };
00052
00053 static dict_pair attr_translate[] = {
00054 { "name", &attr_array[NAME] }
00055 };
00056
00057 static dictionary tag_dict = { tag_translate, 2 };
00058 static dictionary attr_dict = { attr_translate, 1 };
00059
00060 typedef struct
00061 {
00062 void *drv_handle;
00063 void *backend_handle;
00064 void (*destroy_handle)(void *handle);
00065 const char *(*get_info)(const char *field);
00066 void (*process_canvas)(void *handle, void *canvas);
00067 }
00068 driver_info;
00069
00070
00071 static int
00072 _ltdl_error ()
00073 {
00074 syslog (LOG_ERR, "libtool init failed: %s\n", lt_dlerror ());
00075
00076 return -1;
00077 }
00078
00079 static void *
00080 _module_error ()
00081 {
00082 syslog (LOG_ERR, "loading plug-in failed: %s\n", lt_dlerror ());
00083
00084 return 0;
00085 }
00086
00087 static void *
00088 _create_failed (void *backend)
00089 {
00090 backend_free_handle (backend);
00091 return 0;
00092 }
00093
00094 int
00095 drivers_init ()
00096 {
00097 static int initialized = 0;
00098 const char *path = 0;
00099
00100 if (initialized)
00101 return 0;
00102
00103
00104 lt_dlmalloc = (lt_ptr(*)(size_t)) xmalloc;
00105
00106
00107
00108
00109 if (lt_dlinit () != 0)
00110 return _ltdl_error ();
00111
00112 path = getenv (FLCDD_MODULE_PATH_ENV);
00113 if (path && lt_dlsetsearchpath (path) != 0)
00114 return _ltdl_error ();
00115
00116 lt_dladdsearchdir (MODULE_PATH);
00117 initialized = 1;
00118
00119 return 0;
00120 }
00121
00122 void *
00123 drivers_create_output (xml_node *config)
00124 {
00125 typedef void*(ch_func)(xml_node *);
00126 typedef void(bb_func)(void *, void *);
00127 typedef void(dh_func)(void *);
00128 typedef const char *(gi_func)(const char *);
00129
00130 driver_info *info = xmalloc (sizeof (driver_info));
00131 ch_func* create_handle;
00132 bb_func* bind_backend;
00133
00134 void *backend;
00135 void *driver;
00136 const char *backend_name;
00137 const char *driver_name;
00138 xml_node *found;
00139 lt_dlhandle module;
00140
00141 xmlt_rescan_document (config, &tag_dict, &attr_dict);
00142
00143 found = xmlt_find (config, 0, BACKEND);
00144 if (!found)
00145 return 0;
00146
00147 backend_name = xmlt_get_attrib (found, NAME);
00148 backend = backend_create_handle (found, backend_name);
00149 if (!backend)
00150 return 0;
00151
00152 found = xmlt_find (config, 0, DRIVER);
00153 if (!found)
00154 return _create_failed (backend);
00155
00156 driver_name = xmlt_get_attrib (found, NAME);
00157 if (!driver_name)
00158 return _create_failed (backend);
00159
00160 module = lt_dlopenext (driver_name);
00161 if (!module)
00162 return _module_error ();
00163
00164 create_handle = (ch_func*)lt_dlsym (module, "drv_create_handle");
00165 if (!create_handle)
00166 return _module_error();
00167
00168 bind_backend = (bb_func*)lt_dlsym (module, "drv_bind_backend");
00169 if (!bind_backend)
00170 return _module_error();
00171
00172 driver = create_handle (found);
00173 if (!driver)
00174 return _create_failed (backend);
00175
00176 info->drv_handle = driver;
00177 info->backend_handle = backend;
00178 info->destroy_handle = (dh_func*)lt_dlsym (module, "drv_destroy_handle");
00179 info->get_info = (gi_func*)lt_dlsym (module, "drv_get_info");
00180 info->process_canvas = (bb_func*)lt_dlsym (module, "drv_process_canvas");
00181
00182 bind_backend (driver, backend);
00183
00184 return info;
00185 }
00186
00187 void
00188 drivers_process_canvas (void *info_, cc_canvas *canvas)
00189 {
00190 driver_info *info = info_;
00191
00192 info->process_canvas (info->drv_handle, canvas);
00193 }
00194