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_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
00289 PluginHandle * plugin_by_widget ( 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 }