Audacious
$Id:Doxyfile42802007-03-2104:39:00Znenolod$
|
00001 /* 00002 * plugin-init.c 00003 * Copyright 2010 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 <stdio.h> 00023 #include <stdlib.h> 00024 00025 #include <glib.h> 00026 00027 #include "debug.h" 00028 #include "effect.h" 00029 #include "general.h" 00030 #include "interface.h" 00031 #include "output.h" 00032 #include "plugin.h" 00033 #include "plugins.h" 00034 #include "ui_preferences.h" 00035 #include "visualization.h" 00036 00037 static gboolean dummy_plugin_start (PluginHandle * p) 00038 { 00039 return TRUE; 00040 } 00041 00042 static void dummy_plugin_stop (PluginHandle * p) 00043 { 00044 } 00045 00046 static const struct { 00047 const gchar * name; 00048 gboolean is_managed, is_single; 00049 00050 union { 00051 struct { 00052 gboolean (* start) (PluginHandle * plugin); 00053 void (* stop) (PluginHandle * plugin); 00054 } m; 00055 00056 struct { 00057 PluginHandle * (* probe) (void); 00058 PluginHandle * (* get_current) (void); 00059 gboolean (* set_current) (PluginHandle * plugin); 00060 } s; 00061 } u; 00062 } table[PLUGIN_TYPES] = { 00063 [PLUGIN_TYPE_TRANSPORT] = {"transport", TRUE, FALSE, .u.m = 00064 {dummy_plugin_start, dummy_plugin_stop}}, 00065 [PLUGIN_TYPE_PLAYLIST] = {"playlist", TRUE, FALSE, .u.m = {dummy_plugin_start, 00066 dummy_plugin_stop}}, 00067 [PLUGIN_TYPE_INPUT] = {"input", TRUE, FALSE, .u.m = {dummy_plugin_start, 00068 dummy_plugin_stop}}, 00069 [PLUGIN_TYPE_EFFECT] = {"effect", TRUE, FALSE, .u.m = {effect_plugin_start, 00070 effect_plugin_stop}}, 00071 [PLUGIN_TYPE_OUTPUT] = {"output", TRUE, TRUE, .u.s = {output_plugin_probe, 00072 output_plugin_get_current, output_plugin_set_current}}, 00073 [PLUGIN_TYPE_VIS] = {"visualization", TRUE, FALSE, .u.m = {vis_plugin_start, 00074 vis_plugin_stop}}, 00075 [PLUGIN_TYPE_GENERAL] = {"general", TRUE, FALSE, .u.m = {general_plugin_start, 00076 general_plugin_stop}}, 00077 [PLUGIN_TYPE_IFACE] = {"interface", TRUE, TRUE, .u.s = {iface_plugin_probe, 00078 iface_plugin_get_current, iface_plugin_set_current}}}; 00079 00080 static gboolean find_enabled_cb (PluginHandle * p, PluginHandle * * pp) 00081 { 00082 * pp = p; 00083 return FALSE; 00084 } 00085 00086 static PluginHandle * find_enabled (gint type) 00087 { 00088 PluginHandle * p = NULL; 00089 plugin_for_enabled (type, (PluginForEachFunc) find_enabled_cb, & p); 00090 return p; 00091 } 00092 00093 static void start_single (gint type) 00094 { 00095 PluginHandle * p; 00096 00097 if ((p = find_enabled (type)) != NULL) 00098 { 00099 AUDDBG ("Starting selected %s plugin %s.\n", table[type].name, 00100 plugin_get_name (p)); 00101 00102 if (table[type].u.s.set_current (p)) 00103 return; 00104 00105 AUDDBG ("%s failed to start.\n", plugin_get_name (p)); 00106 plugin_set_enabled (p, FALSE); 00107 } 00108 00109 AUDDBG ("Probing for %s plugin.\n", table[type].name); 00110 00111 if ((p = table[type].u.s.probe ()) == NULL) 00112 { 00113 fprintf (stderr, "FATAL: No %s plugin found.\n", table[type].name); 00114 exit (EXIT_FAILURE); 00115 } 00116 00117 AUDDBG ("Starting %s.\n", plugin_get_name (p)); 00118 plugin_set_enabled (p, TRUE); 00119 00120 if (! table[type].u.s.set_current (p)) 00121 { 00122 fprintf (stderr, "FATAL: %s failed to start.\n", plugin_get_name (p)); 00123 plugin_set_enabled (p, FALSE); 00124 exit (EXIT_FAILURE); 00125 } 00126 } 00127 00128 static gboolean start_multi_cb (PluginHandle * p, void * type) 00129 { 00130 AUDDBG ("Starting %s.\n", plugin_get_name (p)); 00131 00132 if (! table[GPOINTER_TO_INT (type)].u.m.start (p)) 00133 { 00134 AUDDBG ("%s failed to start; disabling.\n", plugin_get_name (p)); 00135 plugin_set_enabled (p, FALSE); 00136 } 00137 00138 return TRUE; 00139 } 00140 00141 static void start_plugins (gint type) 00142 { 00143 if (! table[type].is_managed) 00144 return; 00145 00146 if (table[type].is_single) 00147 start_single (type); 00148 else 00149 plugin_for_enabled (type, (PluginForEachFunc) start_multi_cb, 00150 GINT_TO_POINTER (type)); 00151 } 00152 00153 static VFSConstructor * lookup_transport (const gchar * scheme) 00154 { 00155 PluginHandle * plugin = transport_plugin_for_scheme (scheme); 00156 if (! plugin) 00157 return NULL; 00158 00159 TransportPlugin * tp = plugin_get_header (plugin); 00160 return tp->vtable; 00161 } 00162 00163 void start_plugins_one (void) 00164 { 00165 plugin_system_init (); 00166 vfs_set_lookup_func (lookup_transport); 00167 00168 for (gint i = 0; i < PLUGIN_TYPE_GENERAL; i ++) 00169 start_plugins (i); 00170 } 00171 00172 void start_plugins_two (void) 00173 { 00174 for (gint i = PLUGIN_TYPE_GENERAL; i < PLUGIN_TYPES; i ++) 00175 start_plugins (i); 00176 } 00177 00178 static gboolean stop_multi_cb (PluginHandle * p, void * type) 00179 { 00180 AUDDBG ("Shutting down %s.\n", plugin_get_name (p)); 00181 table[GPOINTER_TO_INT (type)].u.m.stop (p); 00182 return TRUE; 00183 } 00184 00185 static void stop_plugins (gint type) 00186 { 00187 if (! table[type].is_managed) 00188 return; 00189 00190 if (table[type].is_single) 00191 { 00192 AUDDBG ("Shutting down %s.\n", plugin_get_name 00193 (table[type].u.s.get_current ())); 00194 table[type].u.s.set_current (NULL); 00195 } 00196 else 00197 plugin_for_enabled (type, (PluginForEachFunc) stop_multi_cb, 00198 GINT_TO_POINTER (type)); 00199 } 00200 00201 void stop_plugins_two (void) 00202 { 00203 for (gint i = PLUGIN_TYPES - 1; i >= PLUGIN_TYPE_GENERAL; i --) 00204 stop_plugins (i); 00205 } 00206 00207 void stop_plugins_one (void) 00208 { 00209 for (gint i = PLUGIN_TYPE_GENERAL - 1; i >= 0; i --) 00210 stop_plugins (i); 00211 00212 vfs_set_lookup_func (NULL); 00213 plugin_system_cleanup (); 00214 } 00215 00216 PluginHandle * plugin_get_current (gint type) 00217 { 00218 g_return_val_if_fail (table[type].is_managed && table[type].is_single, NULL); 00219 return table[type].u.s.get_current (); 00220 } 00221 00222 static gboolean enable_single (gint type, PluginHandle * p) 00223 { 00224 PluginHandle * old = table[type].u.s.get_current (); 00225 00226 AUDDBG ("Switching from %s to %s.\n", plugin_get_name (old), 00227 plugin_get_name (p)); 00228 plugin_set_enabled (old, FALSE); 00229 plugin_set_enabled (p, TRUE); 00230 00231 if (table[type].u.s.set_current (p)) 00232 return TRUE; 00233 00234 fprintf (stderr, "%s failed to start; falling back to %s.\n", 00235 plugin_get_name (p), plugin_get_name (old)); 00236 plugin_set_enabled (p, FALSE); 00237 plugin_set_enabled (old, TRUE); 00238 00239 if (table[type].u.s.set_current (old)) 00240 return FALSE; 00241 00242 fprintf (stderr, "FATAL: %s failed to start.\n", plugin_get_name (old)); 00243 plugin_set_enabled (old, FALSE); 00244 exit (EXIT_FAILURE); 00245 } 00246 00247 static gboolean enable_multi (gint type, PluginHandle * p, gboolean enable) 00248 { 00249 AUDDBG ("%sabling %s.\n", enable ? "En" : "Dis", plugin_get_name (p)); 00250 plugin_set_enabled (p, enable); 00251 00252 if (enable) 00253 { 00254 if (! table[type].u.m.start (p)) 00255 { 00256 fprintf (stderr, "%s failed to start.\n", plugin_get_name (p)); 00257 plugin_set_enabled (p, FALSE); 00258 return FALSE; 00259 } 00260 } 00261 else 00262 table[type].u.m.stop (p); 00263 00264 return TRUE; 00265 } 00266 00267 gboolean plugin_enable (PluginHandle * plugin, gboolean enable) 00268 { 00269 if (! enable == ! plugin_get_enabled (plugin)) 00270 { 00271 AUDDBG ("%s is already %sabled.\n", plugin_get_name (plugin), enable ? 00272 "en" : "dis"); 00273 return TRUE; 00274 } 00275 00276 gint type = plugin_get_type (plugin); 00277 g_return_val_if_fail (table[type].is_managed, FALSE); 00278 00279 if (table[type].is_single) 00280 { 00281 g_return_val_if_fail (enable, FALSE); 00282 return enable_single (type, plugin); 00283 } 00284 00285 return enable_multi (type, plugin, enable); 00286 } 00287 00288 /* This doesn't really belong here, but it's a bit of an oddball. */ 00289 PluginHandle * plugin_by_widget (/* GtkWidget * */ void * widget) 00290 { 00291 PluginHandle * p; 00292 if ((p = vis_plugin_by_widget (widget))) 00293 return p; 00294 if ((p = general_plugin_by_widget (widget))) 00295 return p; 00296 return NULL; 00297 }