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 
37 static const struct {
38  const char * name;
40 
41  union {
42  struct {
44  void (* stop) (PluginHandle * plugin);
45  } m;
46 
47  struct {
48  PluginHandle * (* probe) (void);
49  PluginHandle * (* get_current) (void);
51  } s;
52  } u;
53 } table[PLUGIN_TYPES] = {
54  [PLUGIN_TYPE_TRANSPORT] = {"transport", FALSE, .u.m = {NULL, NULL}},
55  [PLUGIN_TYPE_PLAYLIST] = {"playlist", FALSE, .u.m = {NULL, NULL}},
56  [PLUGIN_TYPE_INPUT] = {"input", FALSE, .u.m = {NULL, NULL}},
58  [PLUGIN_TYPE_OUTPUT] = {"output", TRUE, .u.s = {output_plugin_probe,
60  [PLUGIN_TYPE_VIS] = {"visualization", FALSE, .u.m = {vis_plugin_start, vis_plugin_stop}},
62  [PLUGIN_TYPE_IFACE] = {"interface", TRUE, .u.s = {iface_plugin_probe,
64 
65 static bool_t find_enabled_cb (PluginHandle * p, void * pp)
66 {
67  * (PluginHandle * *) pp = p;
68  return FALSE;
69 }
70 
72 {
73  PluginHandle * p = NULL;
75  return p;
76 }
77 
78 static void start_single (int type)
79 {
80  PluginHandle * p;
81 
82  if ((p = find_enabled (type)) != NULL)
83  {
84  AUDDBG ("Starting selected %s plugin %s.\n", table[type].name,
85  plugin_get_name (p));
86 
87  if (table[type].u.s.set_current (p))
88  return;
89 
90  AUDDBG ("%s failed to start.\n", plugin_get_name (p));
92  }
93 
94  AUDDBG ("Probing for %s plugin.\n", table[type].name);
95 
96  if ((p = table[type].u.s.probe ()) == NULL)
97  {
98  fprintf (stderr, "FATAL: No %s plugin found.\n", table[type].name);
99  exit (EXIT_FAILURE);
100  }
101 
102  AUDDBG ("Starting %s.\n", plugin_get_name (p));
104 
105  if (! table[type].u.s.set_current (p))
106  {
107  fprintf (stderr, "FATAL: %s failed to start.\n", plugin_get_name (p));
109  exit (EXIT_FAILURE);
110  }
111 }
112 
114 {
115  AUDDBG ("Starting %s.\n", plugin_get_name (p));
116 
117  if (! table[GPOINTER_TO_INT (type)].u.m.start (p))
118  {
119  AUDDBG ("%s failed to start; disabling.\n", plugin_get_name (p));
121  }
122 
123  return TRUE;
124 }
125 
126 static void start_plugins (int type)
127 {
128  if (headless && type == PLUGIN_TYPE_IFACE)
129  return;
130 
131  if (table[type].is_single)
132  start_single (type);
133  else
134  {
135  if (table[type].u.m.start)
136  plugin_for_enabled (type, start_multi_cb, GINT_TO_POINTER (type));
137  }
138 }
139 
140 static VFSConstructor * lookup_transport (const char * scheme)
141 {
143  if (! plugin)
144  return NULL;
145 
146  TransportPlugin * tp = plugin_get_header (plugin);
147  return tp ? tp->vtable : NULL;
148 }
149 
150 void start_plugins_one (void)
151 {
154 
155  for (int i = 0; i < PLUGIN_TYPE_GENERAL; i ++)
156  start_plugins (i);
157 }
158 
159 void start_plugins_two (void)
160 {
161  for (int i = PLUGIN_TYPE_GENERAL; i < PLUGIN_TYPES; i ++)
162  start_plugins (i);
163 }
164 
165 static bool_t misc_cleanup_cb (PluginHandle * p, void * unused)
166 {
168  return TRUE;
169 }
170 
171 static bool_t stop_multi_cb (PluginHandle * p, void * type)
172 {
173  AUDDBG ("Shutting down %s.\n", plugin_get_name (p));
174  table[GPOINTER_TO_INT (type)].u.m.stop (p);
175  return TRUE;
176 }
177 
178 static void stop_plugins (int type)
179 {
180  if (headless && type == PLUGIN_TYPE_IFACE)
181  return;
182 
183  plugin_for_enabled (type, misc_cleanup_cb, GINT_TO_POINTER (type));
184 
185  if (table[type].is_single)
186  {
187  AUDDBG ("Shutting down %s.\n", plugin_get_name
188  (table[type].u.s.get_current ()));
189  table[type].u.s.set_current (NULL);
190  }
191  else
192  {
193  if (table[type].u.m.stop)
194  plugin_for_enabled (type, stop_multi_cb, GINT_TO_POINTER (type));
195  }
196 }
197 
198 void stop_plugins_two (void)
199 {
200  for (int i = PLUGIN_TYPES - 1; i >= PLUGIN_TYPE_GENERAL; i --)
201  stop_plugins (i);
202 }
203 
204 void stop_plugins_one (void)
205 {
206  for (int i = PLUGIN_TYPE_GENERAL - 1; i >= 0; i --)
207  stop_plugins (i);
208 
211 }
212 
214 {
215  g_return_val_if_fail (table[type].is_single, NULL);
216  return table[type].u.s.get_current ();
217 }
218 
220 {
221  PluginHandle * old = table[type].u.s.get_current ();
222 
223  plugin_misc_cleanup (old);
224 
225  AUDDBG ("Switching from %s to %s.\n", plugin_get_name (old),
226  plugin_get_name (p));
227  plugin_set_enabled (old, FALSE);
229 
230  if (table[type].u.s.set_current (p))
231  return TRUE;
232 
233  fprintf (stderr, "%s failed to start; falling back to %s.\n",
234  plugin_get_name (p), plugin_get_name (old));
236  plugin_set_enabled (old, TRUE);
237 
238  if (table[type].u.s.set_current (old))
239  return FALSE;
240 
241  fprintf (stderr, "FATAL: %s failed to start.\n", plugin_get_name (old));
242  plugin_set_enabled (old, FALSE);
243  exit (EXIT_FAILURE);
244 }
245 
246 static bool_t enable_multi (int type, PluginHandle * p, bool_t enable)
247 {
248  if (! enable)
250 
251  AUDDBG ("%sabling %s.\n", enable ? "En" : "Dis", plugin_get_name (p));
252  plugin_set_enabled (p, enable);
253 
254  if (enable)
255  {
256  if (table[type].u.m.start && ! table[type].u.m.start (p))
257  {
258  fprintf (stderr, "%s failed to start.\n", plugin_get_name (p));
260  return FALSE;
261  }
262  }
263  else
264  {
265  if (table[type].u.m.stop)
266  table[type].u.m.stop (p);
267  }
268 
269  return TRUE;
270 }
271 
273 {
274  if (! enable == ! plugin_get_enabled (plugin))
275  return TRUE;
276 
277  int type = plugin_get_type (plugin);
278 
279  if (table[type].is_single)
280  {
281  g_return_val_if_fail (enable, FALSE);
282  return enable_single (type, plugin);
283  }
284 
285  return enable_multi (type, plugin, enable);
286 }
287 
288 /* Miscellaneous plugin-related functions ... */
289 
290 PluginHandle * plugin_by_widget (/* GtkWidget * */ void * widget)
291 {
292  PluginHandle * p;
293  if ((p = vis_plugin_by_widget (widget)))
294  return p;
295  if ((p = general_plugin_by_widget (widget)))
296  return p;
297  return NULL;
298 }
299 
300 int plugin_send_message (PluginHandle * plugin, const char * code, const void * data, int size)
301 {
302  if (! plugin_get_enabled (plugin))
303  return ENOSYS;
304 
305  Plugin * header = plugin_get_header (plugin);
306  if (! header || ! PLUGIN_HAS_FUNC (header, take_message))
307  return ENOSYS;
308 
309  return header->take_message (code, data, size);
310 }
311 
313 {
314  g_return_if_fail (plugin_get_enabled (plugin));
315  Plugin * header = plugin_get_header (plugin);
316  g_return_if_fail (header);
317 
318  if (PLUGIN_HAS_FUNC (header, about))
319  header->about ();
320  else if (PLUGIN_HAS_FUNC (header, about_text))
321  plugin_make_about_window (plugin);
322 }
323 
325 {
326  g_return_if_fail (plugin_get_enabled (plugin));
327  Plugin * header = plugin_get_header (plugin);
328  g_return_if_fail (header);
329 
330  if (PLUGIN_HAS_FUNC (header, configure))
331  header->configure ();
332  else if (PLUGIN_HAS_FUNC (header, prefs))
333  plugin_make_config_window (plugin);
334 }