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