Fix small typo
[gmpc.git] / src / plugin.c
blob5d8f6b4c408f68a10b679edaa70384d548059737
1 #include <string.h>
2 #include <glib.h>
3 #include <gtk/gtk.h>
4 #include <gmodule.h>
5 #include "main.h"
6 #include "metadata.h"
9 gmpcPlugin **plugins = NULL;
10 int num_plugins = 0;
12 gmpcPlugin * plugin_get_from_id(int id)
14 return plugins[plugin_get_pos(id)];
18 int plugin_get_pos(int id)
20 return id&(PLUGIN_ID_MARK-1);
22 static int plugin_validate(gmpcPlugin *plug)
24 int i;
25 if(plug == NULL)
27 debug_printf(DEBUG_ERROR, "plug != NULL failed");
28 return FALSE;
30 if(plug->name == NULL)
32 debug_printf(DEBUG_ERROR, "Plugin has no name.");
33 return FALSE;
35 /* check if plugin with same name is allready loaded */
36 for(i=0;i<num_plugins;i++)
38 if(strcmp(plugins[i]->name, plug->name) == 0)
40 debug_printf(DEBUG_ERROR, "Plugin with same name allready exists.");
41 return FALSE;
44 if(plug->set_enabled == NULL || plug->get_enabled == NULL)
46 debug_printf(DEBUG_ERROR, "%s: set_enabled == NULL || get_enabled == NULL failed",plug->name);
47 return FALSE;
49 if(plug->plugin_type&GMPC_PLUGIN_PL_BROWSER)
51 if(plug->browser == NULL)
53 debug_printf(DEBUG_ERROR, "%s: plugin_type&GMPC_PLUGIN_PL_BROWSER && plugin->browser != NULL Failed",plug->name);
54 return FALSE;
57 if(plug->plugin_type&GMPC_PLUGIN_META_DATA)
59 if(plug->metadata == NULL)
61 debug_printf(DEBUG_ERROR, "%s: plugin_type&GMPC_PLUGIN_META_DATA && plugin->metadata != NULL Failed",plug->name);
62 return FALSE;
64 if(plug->metadata->get_priority == NULL)
66 debug_printf(DEBUG_ERROR, "%s: plugin_type&GMPC_PLUGIN_META_DATA && plugin->metadata->get_priority != NULL Failed",plug->name);
67 return FALSE;
69 if(plug->metadata->get_image == NULL)
71 debug_printf(DEBUG_ERROR, "%s: plugin_type&GMPC_PLUGIN_META_DATA && plugin->metadata->get_image != NULL Failed",plug->name);
72 return FALSE;
75 /* if there is a browser field, check validity */
76 if(plug->browser)
78 if((plug->browser->selected && plug->browser->unselected == NULL) ||(plug->browser->selected == NULL && plug->browser->unselected))
80 debug_printf(DEBUG_ERROR, "%s: If a plugin provides a browser pane, it needs both selected and unselected",plug->name);
81 return FALSE;
84 /* if there is a pref window withouth both construct/destroy, give an error */
85 if(plug->pref)
87 if(!(plug->pref->construct && plug->pref->destroy))
89 debug_printf(DEBUG_ERROR, "%s: If a plugin has a preferences pane, it needs both construct and destroy", plug->name);
93 return TRUE;
96 void plugin_add(gmpcPlugin *plug, int plugin)
98 /* set plugin id */
99 plug->id = num_plugins|((plugin)?PLUGIN_ID_MARK:PLUGIN_ID_INTERNALL);
100 /* put it in the list */
101 num_plugins++;
102 plugins = g_realloc(plugins,(num_plugins+1)*sizeof(gmpcPlugin **));
103 plugins[num_plugins-1] = plug;
104 plugins[num_plugins] = NULL;
106 if(plug->plugin_type&GMPC_PLUGIN_META_DATA)
108 meta_data_add_plugin(plug);
111 static int plugin_load(char *path, const char *file)
113 GModule *handle;
114 int *api_version=0;
115 gmpcPlugin *plug = NULL;
116 gchar *string = NULL;
117 gchar *full_path = NULL;
118 if(path == NULL)
120 return 1;
122 full_path = g_strdup_printf("%s%c%s", path,G_DIR_SEPARATOR, file);
123 debug_printf(DEBUG_INFO, "plugin_load: trying to load plugin %s", full_path);
125 handle = g_module_open(full_path, G_MODULE_BIND_LOCAL);
126 q_free(full_path);
127 if (!handle) {
128 gchar *message = g_strdup_printf("Failed to load plugin:\n%s:%s",file, g_module_error());
129 debug_printf (DEBUG_ERROR, "plugin_load: module failed to load: %s:%s\n", file, g_module_error());
130 show_error_message(message, FALSE);
131 q_free(message);
132 return 1;
134 if(!g_module_symbol(handle, "plugin_api_version", (gpointer)&api_version)){
135 gchar *message = g_strdup_printf("Failed to load plugin:\n%s:%s",file, g_module_error());
136 debug_printf(DEBUG_ERROR, "plugin_load: symbol failed to bind: %s:%s\n",file, g_module_error());
137 show_error_message(message,FALSE);
138 q_free(string);
139 q_free(message);
140 g_module_close(handle);
141 return 1;
143 if(*api_version != PLUGIN_API_VERSION)
145 gchar *message = g_strdup_printf("Plugin '%s' has the wrong api version.\nPlugin api is %i, but we need %i",
146 file, *api_version, PLUGIN_API_VERSION);
147 debug_printf(DEBUG_ERROR, "Plugin '%s' has the wrong api version.\nPlugin api is %i, but we need %i",
148 file, *api_version, PLUGIN_API_VERSION);
149 show_error_message(message,FALSE);
150 q_free(string);
151 q_free(message);
152 g_module_close(handle);
153 return 1;
156 if(!g_module_symbol(handle, "plugin", (gpointer)&plug)){
157 gchar *message = g_strdup_printf("Failed to load plugin:\n%s:%s",file, g_module_error());
158 debug_printf(DEBUG_ERROR, "plugin_load: symbol failed to bind: %s:%s\n",file, g_module_error());
159 show_error_message(message,FALSE);
160 q_free(string);
161 q_free(message);
162 g_module_close(handle);
163 return 1;
165 if(plug == NULL)
167 debug_printf(DEBUG_WARNING, "plugin load: unknown type of plugin.\n");
168 g_module_close(handle);
169 return 1;
171 if(!plugin_validate(plug))
173 debug_printf(DEBUG_ERROR, "Faled to validate plugin: %s\n", file);
174 g_module_close(handle);
175 return 1;
177 /* set path, plugins might want this for images and glade files. */
178 plug->path = g_strdup(path);
179 /* add the plugin to the list */
180 plugin_add(plug,1);
181 return 0;
184 void plugin_load_dir(gchar *path)
186 GDir *dir = g_dir_open(path, 0, NULL);
187 if(dir)
189 const gchar *dirname = NULL;
190 while((dirname = g_dir_read_name(dir)) != NULL)
192 gchar *full_path = g_strdup_printf("%s%c%s",path,G_DIR_SEPARATOR,dirname);
193 /* Make sure only to load plugins */
194 if(g_str_has_suffix(dirname, G_MODULE_SUFFIX))
196 if(plugin_load(path,dirname))
198 debug_printf(DEBUG_ERROR, "Failed to load plugin: %s\n", dirname);
201 else
203 debug_printf(DEBUG_INFO, "File not loaded, wrong extention, should be: '%s'", G_MODULE_SUFFIX);
205 q_free(full_path);
207 g_dir_close(dir);