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 "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
00290 PluginHandle * plugin_by_widget ( 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 }