Audacious  $Id:Doxyfile42802007-03-2104:39:00Znenolod$
plugin-init.c
Go to the documentation of this file.
1 /*
2  * plugin-init.c
3  * Copyright 2010-2011 John Lindgren
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice,
9  * this list of conditions, and the following disclaimer.
10  *
11  * 2. Redistributions in binary form must reproduce the above copyright notice,
12  * this list of conditions, and the following disclaimer in the documentation
13  * provided with the distribution.
14  *
15  * This software is provided "as is" and without any warranty, express or
16  * implied. In no event shall the authors be liable for any damages arising from
17  * the use of this software.
18  */
19 
20 #include <errno.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 
24 #include <glib.h>
25 
26 #include "debug.h"
27 #include "effect.h"
28 #include "general.h"
29 #include "interface.h"
30 #include "main.h"
31 #include "output.h"
32 #include "plugin.h"
33 #include "plugins.h"
34 #include "ui_preferences.h"
35 #include "visualization.h"
36 
38 {
39  return TRUE;
40 }
41 
43 {
44 }
45 
46 static const struct {
47  const char * name;
49 
50  union {
51  struct {
53  void (* stop) (PluginHandle * plugin);
54  } m;
55 
56  struct {
57  PluginHandle * (* probe) (void);
58  PluginHandle * (* get_current) (void);
60  } s;
61  } u;
62 } table[PLUGIN_TYPES] = {
67  [PLUGIN_TYPE_OUTPUT] = {"output", TRUE, .u.s = {output_plugin_probe,
69  [PLUGIN_TYPE_VIS] = {"visualization", FALSE, .u.m = {vis_plugin_start, vis_plugin_stop}},
71  [PLUGIN_TYPE_IFACE] = {"interface", TRUE, .u.s = {iface_plugin_probe,
73 
74 static bool_t find_enabled_cb (PluginHandle * p, void * pp)
75 {
76  * (PluginHandle * *) pp = p;
77  return FALSE;
78 }
79 
81 {
82  PluginHandle * p = NULL;
84  return p;
85 }
86 
87 static void start_single (int type)
88 {
89  PluginHandle * p;
90 
91  if ((p = find_enabled (type)) != NULL)
92  {
93  AUDDBG ("Starting selected %s plugin %s.\n", table[type].name,
94  plugin_get_name (p));
95 
96  if (table[type].u.s.set_current (p))
97  return;
98 
99  AUDDBG ("%s failed to start.\n", plugin_get_name (p));
101  }
102 
103  AUDDBG ("Probing for %s plugin.\n", table[type].name);
104 
105  if ((p = table[type].u.s.probe ()) == NULL)
106  {
107  fprintf (stderr, "FATAL: No %s plugin found.\n", table[type].name);
108  exit (EXIT_FAILURE);
109  }
110 
111  AUDDBG ("Starting %s.\n", plugin_get_name (p));
113 
114  if (! table[type].u.s.set_current (p))
115  {
116  fprintf (stderr, "FATAL: %s failed to start.\n", plugin_get_name (p));
118  exit (EXIT_FAILURE);
119  }
120 }
121 
123 {
124  AUDDBG ("Starting %s.\n", plugin_get_name (p));
125 
126  if (! table[GPOINTER_TO_INT (type)].u.m.start (p))
127  {
128  AUDDBG ("%s failed to start; disabling.\n", plugin_get_name (p));
130  }
131 
132  return TRUE;
133 }
134 
135 static void start_plugins (int type)
136 {
137  if (headless && type == PLUGIN_TYPE_IFACE)
138  return;
139 
140  if (table[type].is_single)
141  start_single (type);
142  else
143  plugin_for_enabled (type, start_multi_cb, GINT_TO_POINTER (type));
144 }
145 
146 static VFSConstructor * lookup_transport (const char * scheme)
147 {
149  if (! plugin)
150  return NULL;
151 
152  TransportPlugin * tp = plugin_get_header (plugin);
153  return tp ? tp->vtable : NULL;
154 }
155 
156 void start_plugins_one (void)
157 {
160 
161  for (int i = 0; i < PLUGIN_TYPE_GENERAL; i ++)
162  start_plugins (i);
163 }
164 
165 void start_plugins_two (void)
166 {
167  for (int i = PLUGIN_TYPE_GENERAL; i < PLUGIN_TYPES; i ++)
168  start_plugins (i);
169 }
170 
171 static bool_t misc_cleanup_cb (PluginHandle * p, void * unused)
172 {
174  return TRUE;
175 }
176 
177 static bool_t stop_multi_cb (PluginHandle * p, void * type)
178 {
179  AUDDBG ("Shutting down %s.\n", plugin_get_name (p));
180  table[GPOINTER_TO_INT (type)].u.m.stop (p);
181  return TRUE;
182 }
183 
184 static void stop_plugins (int type)
185 {
186  if (headless && type == PLUGIN_TYPE_IFACE)
187  return;
188 
189  plugin_for_enabled (type, misc_cleanup_cb, GINT_TO_POINTER (type));
190 
191  if (table[type].is_single)
192  {
193  AUDDBG ("Shutting down %s.\n", plugin_get_name
194  (table[type].u.s.get_current ()));
195  table[type].u.s.set_current (NULL);
196  }
197  else
198  plugin_for_enabled (type, stop_multi_cb, GINT_TO_POINTER (type));
199 }
200 
201 void stop_plugins_two (void)
202 {
203  for (int i = PLUGIN_TYPES - 1; i >= PLUGIN_TYPE_GENERAL; i --)
204  stop_plugins (i);
205 }
206 
207 void stop_plugins_one (void)
208 {
209  for (int i = PLUGIN_TYPE_GENERAL - 1; i >= 0; i --)
210  stop_plugins (i);
211 
214 }
215 
217 {
218  g_return_val_if_fail (table[type].is_single, NULL);
219  return table[type].u.s.get_current ();
220 }
221 
223 {
224  PluginHandle * old = table[type].u.s.get_current ();
225 
226  AUDDBG ("Switching from %s to %s.\n", plugin_get_name (old),
227  plugin_get_name (p));
228  plugin_set_enabled (old, FALSE);
230 
231  if (table[type].u.s.set_current (p))
232  return TRUE;
233 
234  fprintf (stderr, "%s failed to start; falling back to %s.\n",
235  plugin_get_name (p), plugin_get_name (old));
237  plugin_set_enabled (old, TRUE);
238 
239  if (table[type].u.s.set_current (old))
240  return FALSE;
241 
242  fprintf (stderr, "FATAL: %s failed to start.\n", plugin_get_name (old));
243  plugin_set_enabled (old, FALSE);
244  exit (EXIT_FAILURE);
245 }
246 
247 static bool_t enable_multi (int type, PluginHandle * p, bool_t enable)
248 {
249  AUDDBG ("%sabling %s.\n", enable ? "En" : "Dis", plugin_get_name (p));
250  plugin_set_enabled (p, enable);
251 
252  if (enable)
253  {
254  if (! table[type].u.m.start (p))
255  {
256  fprintf (stderr, "%s failed to start.\n", plugin_get_name (p));
258  return FALSE;
259  }
260  }
261  else
262  table[type].u.m.stop (p);
263 
264  return TRUE;
265 }
266 
268 {
269  if (! enable == ! plugin_get_enabled (plugin))
270  return TRUE;
271 
272  if (! enable)
273  plugin_misc_cleanup (plugin);
274 
275  int type = plugin_get_type (plugin);
276 
277  if (table[type].is_single)
278  {
279  g_return_val_if_fail (enable, FALSE);
280  return enable_single (type, plugin);
281  }
282 
283  return enable_multi (type, plugin, enable);
284 }
285 
286 /* Miscellaneous plugin-related functions ... */
287 
288 PluginHandle * plugin_by_widget (/* GtkWidget * */ void * widget)
289 {
290  PluginHandle * p;
291  if ((p = vis_plugin_by_widget (widget)))
292  return p;
293  if ((p = general_plugin_by_widget (widget)))
294  return p;
295  return NULL;
296 }
297 
298 int plugin_send_message (PluginHandle * plugin, const char * code, const void * data, int size)
299 {
300  if (! plugin_get_enabled (plugin))
301  return ENOSYS;
302 
303  Plugin * header = plugin_get_header (plugin);
304  if (! header || ! PLUGIN_HAS_FUNC (header, take_message))
305  return ENOSYS;
306 
307  return header->take_message (code, data, size);
308 }
309 
311 {
312  g_return_if_fail (plugin_get_enabled (plugin));
313  Plugin * header = plugin_get_header (plugin);
314  g_return_if_fail (header);
315 
316  if (PLUGIN_HAS_FUNC (header, about))
317  header->about ();
318  else if (PLUGIN_HAS_FUNC (header, about_text))
319  plugin_make_about_window (plugin);
320 }
321 
323 {
324  g_return_if_fail (plugin_get_enabled (plugin));
325  Plugin * header = plugin_get_header (plugin);
326  g_return_if_fail (header);
327 
328  if (PLUGIN_HAS_FUNC (header, configure))
329  header->configure ();
330  else if (PLUGIN_HAS_FUNC (header, prefs))
331  plugin_make_config_window (plugin);
332 }