Audacious  $Id:Doxyfile42802007-03-2104:39:00Znenolod$
pluginenum.c
Go to the documentation of this file.
1 /*
2  * pluginenum.c
3  * Copyright 2007-2011 William Pitcock and 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 <assert.h>
21 #include <errno.h>
22 #include <glib.h>
23 #include <gmodule.h>
24 #include <pthread.h>
25 #include <string.h>
26 #include <sys/stat.h>
27 
28 #include <libaudcore/audstrings.h>
29 #include <libaudgui/init.h>
30 
31 #include "debug.h"
32 #include "plugin.h"
33 #include "util.h"
34 
35 #define AUD_API_DECLARE
36 #include "drct.h"
37 #include "misc.h"
38 #include "playlist.h"
39 #include "plugins.h"
40 #undef AUD_API_DECLARE
41 
42 static const char * plugin_dir_list[] = {PLUGINSUBS, NULL};
43 
44 char verbose = 0;
45 
47  .drct_api = & drct_api,
48  .misc_api = & misc_api,
49  .playlist_api = & playlist_api,
50  .plugins_api = & plugins_api,
51  .verbose = & verbose};
52 
53 typedef struct {
54  Plugin * header;
55  GModule * module;
56 } LoadedModule;
57 
58 static GList * loaded_modules = NULL;
59 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
60 
61 Plugin * plugin_load (const char * filename)
62 {
63  AUDDBG ("Loading plugin: %s.\n", filename);
64 
65  GModule * module = g_module_open (filename, G_MODULE_BIND_LAZY | G_MODULE_BIND_LOCAL);
66  if (! module)
67  {
68  fprintf (stderr, " *** ERROR: %s could not be loaded: %s\n", filename,
69  g_module_error ());
70  return NULL;
71  }
72 
73  void * ptr;
74  if (! g_module_symbol (module, "get_plugin_info", & ptr))
75  ptr = NULL;
76 
77  Plugin * (* func) (AudAPITable * table) = ptr;
78  Plugin * header;
79 
80  if (! func || ! (header = func (& api_table)) || header->magic != _AUD_PLUGIN_MAGIC)
81  {
82  fprintf (stderr, " *** ERROR: %s is not a valid Audacious plugin.\n", filename);
83  g_module_close (module);
84  return NULL;
85  }
86 
87  if (header->version < _AUD_PLUGIN_VERSION_MIN ||
88  header->version > _AUD_PLUGIN_VERSION)
89  {
90  fprintf (stderr, " *** ERROR: %s is not compatible with this version "
91  "of Audacious.\n", filename);
92  g_module_close (module);
93  return NULL;
94  }
95 
96  if (header->type == PLUGIN_TYPE_TRANSPORT ||
97  header->type == PLUGIN_TYPE_PLAYLIST ||
98  header->type == PLUGIN_TYPE_INPUT ||
99  header->type == PLUGIN_TYPE_EFFECT)
100  {
101  if (PLUGIN_HAS_FUNC (header, init) && ! header->init ())
102  {
103  fprintf (stderr, " *** ERROR: %s failed to initialize.\n", filename);
104  g_module_close (module);
105  return NULL;
106  }
107  }
108 
109  pthread_mutex_lock (& mutex);
110  LoadedModule * loaded = g_slice_new (LoadedModule);
111  loaded->header = header;
112  loaded->module = module;
113  loaded_modules = g_list_prepend (loaded_modules, loaded);
114  pthread_mutex_unlock (& mutex);
115 
116  return header;
117 }
118 
120 {
121  Plugin * header = loaded->header;
122 
123  switch (header->type)
124  {
127  case PLUGIN_TYPE_INPUT:
128  case PLUGIN_TYPE_EFFECT:
129  if (PLUGIN_HAS_FUNC (header, cleanup))
130  header->cleanup ();
131  break;
132  }
133 
134  pthread_mutex_lock (& mutex);
135  g_module_close (loaded->module);
136  g_slice_free (LoadedModule, loaded);
137  pthread_mutex_unlock (& mutex);
138 }
139 
140 /******************************************************************/
141 
142 static bool_t scan_plugin_func(const char * path, const char * basename, void * data)
143 {
144  if (!str_has_suffix_nocase(basename, PLUGIN_SUFFIX))
145  return FALSE;
146 
147  struct stat st;
148  if (stat (path, & st))
149  {
150  fprintf (stderr, "Unable to stat %s: %s\n", path, strerror (errno));
151  return FALSE;
152  }
153 
154  if (S_ISREG (st.st_mode))
155  plugin_register (path, st.st_mtime);
156 
157  return FALSE;
158 }
159 
160 static void scan_plugins(const char * path)
161 {
163 }
164 
166 {
167  assert (g_module_supported ());
168 
169  char *dir;
170  int dirsel = 0;
171 
172  audgui_init (& api_table);
173 
175 
176 #ifndef DISABLE_USER_PLUGIN_DIR
178  /*
179  * This is in a separate loop so if the user puts them in the
180  * wrong dir we'll still get them in the right order (home dir
181  * first) - Zinx
182  */
183  while (plugin_dir_list[dirsel])
184  {
185  dir = g_build_filename (get_path (AUD_PATH_USER_PLUGIN_DIR),
186  plugin_dir_list[dirsel ++], NULL);
187  scan_plugins(dir);
188  g_free(dir);
189  }
190  dirsel = 0;
191 #endif
192 
193  while (plugin_dir_list[dirsel])
194  {
195  dir = g_build_filename (get_path (AUD_PATH_PLUGIN_DIR),
196  plugin_dir_list[dirsel ++], NULL);
197  scan_plugins(dir);
198  g_free(dir);
199  }
200 
202 }
203 
205 {
207 
208  for (GList * node = loaded_modules; node != NULL; node = node->next)
209  plugin2_unload (node->data);
210 
211  g_list_free (loaded_modules);
213 
214  audgui_cleanup ();
215 }
static void plugin2_unload(LoadedModule *loaded)
Definition: pluginenum.c:119
Plugin * header
Definition: pluginenum.c:54
AudAPITable api_table
Definition: pluginenum.c:46
const char filename
Definition: misc-api.h:85
void plugin_register(const char *path, int timestamp)
void plugin_registry_prune(void)
#define _AUD_PLUGIN_VERSION_MIN
Definition: plugin.h:47
Plugin * plugin_load(const char *filename)
Definition: pluginenum.c:61
bool_t dir_foreach(const char *path, DirForeachFunc func, void *user)
Definition: util.c:46
void plugin_system_cleanup(void)
Definition: pluginenum.c:204
#define PLUGIN_HAS_FUNC(p, func)
Definition: plugin.h:515
EXPORT bool_t str_has_suffix_nocase(const char *str, const char *suffix)
Definition: audstrings.c:44
static GHashTable * table
Definition: strpool.c:34
#define FALSE
Definition: core.h:37
Index Index bool_t
Definition: playlist-api.h:122
#define AUDDBG(...)
Definition: debug.h:30
void plugin_registry_load(void)
void plugin_registry_save(void)
#define NULL
Definition: core.h:29
static bool_t verbose
Definition: vfs.c:59
static GList * loaded_modules
Definition: pluginenum.c:58
func
Definition: plugins-api.h:41
struct DRCTAPI * drct_api
Definition: api.h:25
static bool_t loaded
Definition: history.c:32
void plugin_system_init(void)
Definition: pluginenum.c:165
const char * get_path(int id)
Definition: main.c:225
GModule * module
Definition: pluginenum.c:55
static pthread_mutex_t mutex
Definition: pluginenum.c:59
static bool_t scan_plugin_func(const char *path, const char *basename, void *data)
Definition: pluginenum.c:142
static void scan_plugins(const char *path)
Definition: pluginenum.c:160
static const char * plugin_dir_list[]
Definition: pluginenum.c:42
#define _AUD_PLUGIN_MAGIC
Definition: plugin.h:32
#define _AUD_PLUGIN_VERSION
Definition: plugin.h:48