00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
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 "main.h"
00032 #include "output.h"
00033 #include "plugin.h"
00034 #include "plugins.h"
00035 #include "ui_preferences.h"
00036 #include "visualization.h"
00037
00038 static gboolean dummy_plugin_start (PluginHandle * p)
00039 {
00040 return TRUE;
00041 }
00042
00043 static void dummy_plugin_stop (PluginHandle * p)
00044 {
00045 }
00046
00047 static const struct {
00048 const gchar * name;
00049 gboolean is_managed, is_single;
00050
00051 union {
00052 struct {
00053 gboolean (* start) (PluginHandle * plugin);
00054 void (* stop) (PluginHandle * plugin);
00055 } m;
00056
00057 struct {
00058 PluginHandle * (* probe) (void);
00059 PluginHandle * (* get_current) (void);
00060 gboolean (* set_current) (PluginHandle * plugin);
00061 } s;
00062 } u;
00063 } table[PLUGIN_TYPES] = {
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 if (headless && type == PLUGIN_TYPE_IFACE)
00147 return;
00148
00149 if (table[type].is_single)
00150 start_single (type);
00151 else
00152 plugin_for_enabled (type, (PluginForEachFunc) start_multi_cb,
00153 GINT_TO_POINTER (type));
00154 }
00155
00156 static VFSConstructor * lookup_transport (const gchar * scheme)
00157 {
00158 PluginHandle * plugin = transport_plugin_for_scheme (scheme);
00159 if (! plugin)
00160 return NULL;
00161
00162 TransportPlugin * tp = plugin_get_header (plugin);
00163 return tp ? tp->vtable : NULL;
00164 }
00165
00166 void start_plugins_one (void)
00167 {
00168 plugin_system_init ();
00169 vfs_set_lookup_func (lookup_transport);
00170
00171 for (gint i = 0; i < PLUGIN_TYPE_GENERAL; i ++)
00172 start_plugins (i);
00173 }
00174
00175 void start_plugins_two (void)
00176 {
00177 for (gint i = PLUGIN_TYPE_GENERAL; i < PLUGIN_TYPES; i ++)
00178 start_plugins (i);
00179 }
00180
00181 static gboolean stop_multi_cb (PluginHandle * p, void * type)
00182 {
00183 AUDDBG ("Shutting down %s.\n", plugin_get_name (p));
00184 table[GPOINTER_TO_INT (type)].u.m.stop (p);
00185 return TRUE;
00186 }
00187
00188 static void stop_plugins (gint type)
00189 {
00190 if (! table[type].is_managed)
00191 return;
00192 if (headless && type == PLUGIN_TYPE_IFACE)
00193 return;
00194
00195 if (table[type].is_single)
00196 {
00197 AUDDBG ("Shutting down %s.\n", plugin_get_name
00198 (table[type].u.s.get_current ()));
00199 table[type].u.s.set_current (NULL);
00200 }
00201 else
00202 plugin_for_enabled (type, (PluginForEachFunc) stop_multi_cb,
00203 GINT_TO_POINTER (type));
00204 }
00205
00206 void stop_plugins_two (void)
00207 {
00208 for (gint i = PLUGIN_TYPES - 1; i >= PLUGIN_TYPE_GENERAL; i --)
00209 stop_plugins (i);
00210 }
00211
00212 void stop_plugins_one (void)
00213 {
00214 for (gint i = PLUGIN_TYPE_GENERAL - 1; i >= 0; i --)
00215 stop_plugins (i);
00216
00217 vfs_set_lookup_func (NULL);
00218 plugin_system_cleanup ();
00219 }
00220
00221 PluginHandle * plugin_get_current (gint type)
00222 {
00223 g_return_val_if_fail (table[type].is_managed && table[type].is_single, NULL);
00224 return table[type].u.s.get_current ();
00225 }
00226
00227 static gboolean enable_single (gint type, PluginHandle * p)
00228 {
00229 PluginHandle * old = table[type].u.s.get_current ();
00230
00231 AUDDBG ("Switching from %s to %s.\n", plugin_get_name (old),
00232 plugin_get_name (p));
00233 plugin_set_enabled (old, FALSE);
00234 plugin_set_enabled (p, TRUE);
00235
00236 if (table[type].u.s.set_current (p))
00237 return TRUE;
00238
00239 fprintf (stderr, "%s failed to start; falling back to %s.\n",
00240 plugin_get_name (p), plugin_get_name (old));
00241 plugin_set_enabled (p, FALSE);
00242 plugin_set_enabled (old, TRUE);
00243
00244 if (table[type].u.s.set_current (old))
00245 return FALSE;
00246
00247 fprintf (stderr, "FATAL: %s failed to start.\n", plugin_get_name (old));
00248 plugin_set_enabled (old, FALSE);
00249 exit (EXIT_FAILURE);
00250 }
00251
00252 static gboolean enable_multi (gint type, PluginHandle * p, gboolean enable)
00253 {
00254 AUDDBG ("%sabling %s.\n", enable ? "En" : "Dis", plugin_get_name (p));
00255 plugin_set_enabled (p, enable);
00256
00257 if (enable)
00258 {
00259 if (! table[type].u.m.start (p))
00260 {
00261 fprintf (stderr, "%s failed to start.\n", plugin_get_name (p));
00262 plugin_set_enabled (p, FALSE);
00263 return FALSE;
00264 }
00265 }
00266 else
00267 table[type].u.m.stop (p);
00268
00269 return TRUE;
00270 }
00271
00272 gboolean plugin_enable (PluginHandle * plugin, gboolean enable)
00273 {
00274 if (! enable == ! plugin_get_enabled (plugin))
00275 {
00276 AUDDBG ("%s is already %sabled.\n", plugin_get_name (plugin), enable ?
00277 "en" : "dis");
00278 return TRUE;
00279 }
00280
00281 gint type = plugin_get_type (plugin);
00282 g_return_val_if_fail (table[type].is_managed, FALSE);
00283
00284 if (table[type].is_single)
00285 {
00286 g_return_val_if_fail (enable, FALSE);
00287 return enable_single (type, plugin);
00288 }
00289
00290 return enable_multi (type, plugin, enable);
00291 }
00292
00293
00294 PluginHandle * plugin_by_widget ( void * widget)
00295 {
00296 PluginHandle * p;
00297 if ((p = vis_plugin_by_widget (widget)))
00298 return p;
00299 if ((p = general_plugin_by_widget (widget)))
00300 return p;
00301 return NULL;
00302 }