Audacious $Id:Doxyfile42802007-03-2104:39:00Znenolod$
|
00001 /* 00002 * plugin-init.c 00003 * Copyright 2010-2011 John Lindgren 00004 * 00005 * This file is part of Audacious. 00006 * 00007 * Audacious is free software: you can redistribute it and/or modify it under 00008 * the terms of the GNU General Public License as published by the Free Software 00009 * Foundation, version 2 or version 3 of the License. 00010 * 00011 * Audacious is distributed in the hope that it will be useful, but WITHOUT ANY 00012 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 00013 * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 00014 * 00015 * You should have received a copy of the GNU General Public License along with 00016 * Audacious. If not, see <http://www.gnu.org/licenses/>. 00017 * 00018 * The Audacious team does not consider modular code linking to Audacious or 00019 * using our public API to be a derived work. 00020 */ 00021 00022 #include <errno.h> 00023 #include <stdio.h> 00024 #include <stdlib.h> 00025 00026 #include <glib.h> 00027 00028 #include "debug.h" 00029 #include "effect.h" 00030 #include "general.h" 00031 #include "interface.h" 00032 #include "main.h" 00033 #include "output.h" 00034 #include "plugin.h" 00035 #include "plugins.h" 00036 #include "ui_preferences.h" 00037 #include "visualization.h" 00038 00039 static bool_t dummy_plugin_start (PluginHandle * p) 00040 { 00041 return TRUE; 00042 } 00043 00044 static void dummy_plugin_stop (PluginHandle * p) 00045 { 00046 } 00047 00048 static const struct { 00049 const char * name; 00050 bool_t is_managed, is_single; 00051 00052 union { 00053 struct { 00054 bool_t (* start) (PluginHandle * plugin); 00055 void (* stop) (PluginHandle * plugin); 00056 } m; 00057 00058 struct { 00059 PluginHandle * (* probe) (void); 00060 PluginHandle * (* get_current) (void); 00061 bool_t (* set_current) (PluginHandle * plugin); 00062 } s; 00063 } u; 00064 } table[PLUGIN_TYPES] = { 00065 [PLUGIN_TYPE_TRANSPORT] = {"transport", TRUE, FALSE, .u.m = 00066 {dummy_plugin_start, dummy_plugin_stop}}, 00067 [PLUGIN_TYPE_PLAYLIST] = {"playlist", TRUE, FALSE, .u.m = {dummy_plugin_start, 00068 dummy_plugin_stop}}, 00069 [PLUGIN_TYPE_INPUT] = {"input", TRUE, FALSE, .u.m = {dummy_plugin_start, 00070 dummy_plugin_stop}}, 00071 [PLUGIN_TYPE_EFFECT] = {"effect", TRUE, FALSE, .u.m = {effect_plugin_start, 00072 effect_plugin_stop}}, 00073 [PLUGIN_TYPE_OUTPUT] = {"output", TRUE, TRUE, .u.s = {output_plugin_probe, 00074 output_plugin_get_current, output_plugin_set_current}}, 00075 [PLUGIN_TYPE_VIS] = {"visualization", TRUE, FALSE, .u.m = {vis_plugin_start, 00076 vis_plugin_stop}}, 00077 [PLUGIN_TYPE_GENERAL] = {"general", TRUE, FALSE, .u.m = {general_plugin_start, 00078 general_plugin_stop}}, 00079 [PLUGIN_TYPE_IFACE] = {"interface", TRUE, TRUE, .u.s = {iface_plugin_probe, 00080 iface_plugin_get_current, iface_plugin_set_current}}}; 00081 00082 static bool_t find_enabled_cb (PluginHandle * p, PluginHandle * * pp) 00083 { 00084 * pp = p; 00085 return FALSE; 00086 } 00087 00088 static PluginHandle * find_enabled (int type) 00089 { 00090 PluginHandle * p = NULL; 00091 plugin_for_enabled (type, (PluginForEachFunc) find_enabled_cb, & p); 00092 return p; 00093 } 00094 00095 static void start_single (int type) 00096 { 00097 PluginHandle * p; 00098 00099 if ((p = find_enabled (type)) != NULL) 00100 { 00101 AUDDBG ("Starting selected %s plugin %s.\n", table[type].name, 00102 plugin_get_name (p)); 00103 00104 if (table[type].u.s.set_current (p)) 00105 return; 00106 00107 AUDDBG ("%s failed to start.\n", plugin_get_name (p)); 00108 plugin_set_enabled (p, FALSE); 00109 } 00110 00111 AUDDBG ("Probing for %s plugin.\n", table[type].name); 00112 00113 if ((p = table[type].u.s.probe ()) == NULL) 00114 { 00115 fprintf (stderr, "FATAL: No %s plugin found.\n", table[type].name); 00116 exit (EXIT_FAILURE); 00117 } 00118 00119 AUDDBG ("Starting %s.\n", plugin_get_name (p)); 00120 plugin_set_enabled (p, TRUE); 00121 00122 if (! table[type].u.s.set_current (p)) 00123 { 00124 fprintf (stderr, "FATAL: %s failed to start.\n", plugin_get_name (p)); 00125 plugin_set_enabled (p, FALSE); 00126 exit (EXIT_FAILURE); 00127 } 00128 } 00129 00130 static bool_t start_multi_cb (PluginHandle * p, void * type) 00131 { 00132 AUDDBG ("Starting %s.\n", plugin_get_name (p)); 00133 00134 if (! table[GPOINTER_TO_INT (type)].u.m.start (p)) 00135 { 00136 AUDDBG ("%s failed to start; disabling.\n", plugin_get_name (p)); 00137 plugin_set_enabled (p, FALSE); 00138 } 00139 00140 return TRUE; 00141 } 00142 00143 static void start_plugins (int type) 00144 { 00145 if (! table[type].is_managed) 00146 return; 00147 if (headless && type == PLUGIN_TYPE_IFACE) 00148 return; 00149 00150 if (table[type].is_single) 00151 start_single (type); 00152 else 00153 plugin_for_enabled (type, (PluginForEachFunc) start_multi_cb, 00154 GINT_TO_POINTER (type)); 00155 } 00156 00157 static VFSConstructor * lookup_transport (const char * scheme) 00158 { 00159 PluginHandle * plugin = transport_plugin_for_scheme (scheme); 00160 if (! plugin) 00161 return NULL; 00162 00163 TransportPlugin * tp = plugin_get_header (plugin); 00164 return tp ? tp->vtable : NULL; 00165 } 00166 00167 void start_plugins_one (void) 00168 { 00169 plugin_system_init (); 00170 vfs_set_lookup_func (lookup_transport); 00171 00172 for (int i = 0; i < PLUGIN_TYPE_GENERAL; i ++) 00173 start_plugins (i); 00174 } 00175 00176 void start_plugins_two (void) 00177 { 00178 for (int i = PLUGIN_TYPE_GENERAL; i < PLUGIN_TYPES; i ++) 00179 start_plugins (i); 00180 } 00181 00182 static bool_t stop_multi_cb (PluginHandle * p, void * type) 00183 { 00184 AUDDBG ("Shutting down %s.\n", plugin_get_name (p)); 00185 table[GPOINTER_TO_INT (type)].u.m.stop (p); 00186 return TRUE; 00187 } 00188 00189 static void stop_plugins (int type) 00190 { 00191 if (! table[type].is_managed) 00192 return; 00193 if (headless && type == PLUGIN_TYPE_IFACE) 00194 return; 00195 00196 if (table[type].is_single) 00197 { 00198 AUDDBG ("Shutting down %s.\n", plugin_get_name 00199 (table[type].u.s.get_current ())); 00200 table[type].u.s.set_current (NULL); 00201 } 00202 else 00203 plugin_for_enabled (type, (PluginForEachFunc) stop_multi_cb, 00204 GINT_TO_POINTER (type)); 00205 } 00206 00207 void stop_plugins_two (void) 00208 { 00209 for (int i = PLUGIN_TYPES - 1; i >= PLUGIN_TYPE_GENERAL; i --) 00210 stop_plugins (i); 00211 } 00212 00213 void stop_plugins_one (void) 00214 { 00215 for (int i = PLUGIN_TYPE_GENERAL - 1; i >= 0; i --) 00216 stop_plugins (i); 00217 00218 vfs_set_lookup_func (NULL); 00219 plugin_system_cleanup (); 00220 } 00221 00222 PluginHandle * plugin_get_current (int type) 00223 { 00224 g_return_val_if_fail (table[type].is_managed && table[type].is_single, NULL); 00225 return table[type].u.s.get_current (); 00226 } 00227 00228 static bool_t enable_single (int type, PluginHandle * p) 00229 { 00230 PluginHandle * old = table[type].u.s.get_current (); 00231 00232 AUDDBG ("Switching from %s to %s.\n", plugin_get_name (old), 00233 plugin_get_name (p)); 00234 plugin_set_enabled (old, FALSE); 00235 plugin_set_enabled (p, TRUE); 00236 00237 if (table[type].u.s.set_current (p)) 00238 return TRUE; 00239 00240 fprintf (stderr, "%s failed to start; falling back to %s.\n", 00241 plugin_get_name (p), plugin_get_name (old)); 00242 plugin_set_enabled (p, FALSE); 00243 plugin_set_enabled (old, TRUE); 00244 00245 if (table[type].u.s.set_current (old)) 00246 return FALSE; 00247 00248 fprintf (stderr, "FATAL: %s failed to start.\n", plugin_get_name (old)); 00249 plugin_set_enabled (old, FALSE); 00250 exit (EXIT_FAILURE); 00251 } 00252 00253 static bool_t enable_multi (int type, PluginHandle * p, bool_t enable) 00254 { 00255 AUDDBG ("%sabling %s.\n", enable ? "En" : "Dis", plugin_get_name (p)); 00256 plugin_set_enabled (p, enable); 00257 00258 if (enable) 00259 { 00260 if (! table[type].u.m.start (p)) 00261 { 00262 fprintf (stderr, "%s failed to start.\n", plugin_get_name (p)); 00263 plugin_set_enabled (p, FALSE); 00264 return FALSE; 00265 } 00266 } 00267 else 00268 table[type].u.m.stop (p); 00269 00270 return TRUE; 00271 } 00272 00273 bool_t plugin_enable (PluginHandle * plugin, bool_t enable) 00274 { 00275 if (! enable == ! plugin_get_enabled (plugin)) 00276 { 00277 AUDDBG ("%s is already %sabled.\n", plugin_get_name (plugin), enable ? 00278 "en" : "dis"); 00279 return TRUE; 00280 } 00281 00282 int type = plugin_get_type (plugin); 00283 g_return_val_if_fail (table[type].is_managed, FALSE); 00284 00285 if (table[type].is_single) 00286 { 00287 g_return_val_if_fail (enable, FALSE); 00288 return enable_single (type, plugin); 00289 } 00290 00291 return enable_multi (type, plugin, enable); 00292 } 00293 00294 /* Miscellaneous plugin-related functions ... */ 00295 00296 PluginHandle * plugin_by_widget (/* GtkWidget * */ void * widget) 00297 { 00298 PluginHandle * p; 00299 if ((p = vis_plugin_by_widget (widget))) 00300 return p; 00301 if ((p = general_plugin_by_widget (widget))) 00302 return p; 00303 return NULL; 00304 } 00305 00306 int plugin_send_message (PluginHandle * plugin, const char * code, const void * data, int size) 00307 { 00308 if (! plugin_get_enabled (plugin)) 00309 return ENOSYS; 00310 00311 Plugin * header = plugin_get_header (plugin); 00312 if (! header || ! PLUGIN_HAS_FUNC (header, take_message)) 00313 return ENOSYS; 00314 00315 return header->take_message (code, data, size); 00316 }