]> git.sesse.net Git - vlc/blob - src/misc/plugins.c
. now we only try to open plugins which are existing files
[vlc] / src / misc / plugins.c
1 /*****************************************************************************
2  * plugins.c : Dynamic plugin management functions
3  *****************************************************************************
4  * Copyright (C) 1999, 2000 VideoLAN
5  *
6  * Authors:
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  * 
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
21  *****************************************************************************/
22 #include "defs.h"
23
24 #include "config.h"
25
26 #include <stdlib.h>                                      /* free(), strtol() */
27 #include <stdio.h>                                              /* sprintf() */
28 #include <string.h>                                            /* strerror() */
29 #include <errno.h>                                                 /* ENOMEM */
30 #include <sys/types.h>                                               /* open */
31 #include <sys/stat.h>
32 #include <fcntl.h>
33 #include <unistd.h>                                                 /* close */
34
35 #if defined(HAVE_DLFCN_H)                                /* Linux, BSD, Hurd */
36 #include <dlfcn.h>                           /* dlopen(), dlsym(), dlclose() */
37
38 #elif defined(HAVE_IMAGE_H)                                          /* BeOS */
39 #include <image.h>
40
41 #else
42 #error no dynamic plugins available on your system !
43 #endif
44
45 #ifdef SYS_BEOS
46 #include "beos_specific.h"
47 #endif
48
49 #include "common.h"
50
51 #include "intf_msg.h"
52 #include "plugins.h"
53
54 /* Local prototypes */
55 char * TestPlugin     ( plugin_id_t *p_plugin_id, char * psz_name );
56 int    AllocatePlugin ( plugin_id_t plugin_id, plugin_bank_t * p_bank,
57                         char * psz_filename );
58
59 plugin_bank_t * bank_Create( void )
60 {
61     plugin_bank_t *p_bank;
62     int i;
63
64     /* Allocate structure */
65     p_bank = malloc( sizeof( plugin_bank_t ) );
66     if( !p_bank )
67     {
68         intf_ErrMsg("plugin bank error: %s\n", strerror( ENOMEM ) );
69         return( NULL );
70     }
71
72     /* Initialize structure */
73     for( i = 0 ; i < MAX_PLUGIN_COUNT ; i++ )
74     {
75         p_bank->p_info[ i ] = NULL;
76     }
77     p_bank->i_plugin_count = MAX_PLUGIN_COUNT;
78
79     intf_Msg("Plugin bank initialized\n");
80     return( p_bank );
81 }
82
83 void bank_Init( plugin_bank_t * p_bank )
84 {
85     plugin_id_t tmp;
86     char * psz_filename;
87
88     /* FIXME: we should browse all directories to get plugins */
89 #define SEEK_PLUGIN( name ) \
90     psz_filename = TestPlugin( &tmp, name ); \
91     if( psz_filename ) AllocatePlugin( tmp, p_bank, psz_filename );
92
93     /* Arch plugins */
94     SEEK_PLUGIN( "beos" );
95
96     /* Low level Video */
97     SEEK_PLUGIN( "x11" );
98     SEEK_PLUGIN( "fb" );
99     SEEK_PLUGIN( "glide" );
100     SEEK_PLUGIN( "mga" );
101      
102     /* High level Video */
103     SEEK_PLUGIN( "gnome" );
104     SEEK_PLUGIN( "ggi" );
105     SEEK_PLUGIN( "sdl" );
106    
107     /* Video calculus */
108     SEEK_PLUGIN( "yuvmmx" );
109     SEEK_PLUGIN( "yuv" );
110
111     /* Audio pluins */
112     SEEK_PLUGIN( "dsp" );
113     SEEK_PLUGIN( "esd" );
114     SEEK_PLUGIN( "alsa" );
115     
116     /* Dummy plugin */
117     SEEK_PLUGIN( "dummy" );
118
119 #undef SEEK_PLUGIN
120 }
121
122 void bank_Destroy( plugin_bank_t * p_bank )
123 {
124     int i;
125     for( i = 0 ; i < p_bank->i_plugin_count ; i++ )
126     {
127         if( p_bank->p_info[ i ] != NULL )
128         {
129             free( p_bank->p_info[ i ]-> psz_filename );
130         }
131     }
132
133     free( p_bank );
134 }
135
136 /*
137  * Following functions are local
138  */
139
140 char * TestPlugin ( plugin_id_t *p_plugin_id, char * psz_name )
141 {
142     int i_count, i_length, i_fd;
143     char * psz_plugin;
144     char * psz_plugin_path[ ] =
145     {
146         ".",
147         "lib", /* this one should disappear */
148         PLUGIN_PATH,
149         NULL
150     };
151
152     i_length = strlen( psz_name );
153
154     for ( i_count = 0 ; psz_plugin_path[ i_count ] ; i_count++ )
155     {
156 #ifdef SYS_BEOS
157         char * psz_program_path;
158         
159         psz_program_path = beos_GetProgramPath();
160         psz_plugin = malloc( strlen(psz_plugin_path[i_count]) +
161                              strlen(psz_program_path) + i_length + 6 );
162         sprintf( psz_plugin, "%s/%s/%s.so", psz_program_path,
163                  psz_plugin_path[i_count], psz_name );        
164
165         *p_plugin_id = load_add_on( psz_plugin );
166 #else
167         psz_plugin = malloc( strlen(psz_plugin_path[i_count]) + i_length + 5 );
168         sprintf( psz_plugin, "%s/%s.so", psz_plugin_path[i_count], psz_name );
169
170         /* Try to open the plugin before dlopen()ing it. */
171         i_fd = open( psz_plugin, O_RDONLY );
172         if( i_fd == -1 )
173         {
174             free( psz_plugin );
175             continue;
176         }
177         close( i_fd );
178         
179         *p_plugin_id = dlopen( psz_plugin, RTLD_NOW | RTLD_GLOBAL );
180 #endif
181
182 #ifdef SYS_BEOS
183         if( *p_plugin_id >= 0 )
184 #else
185         if( *p_plugin_id != NULL )
186 #endif
187         {
188             /* plugin successfuly dlopened */
189             return( psz_plugin );
190         }
191
192 #ifndef SYS_BEOS
193         intf_WarnMsg( 1, "Plugin %s failed: %s\n", psz_plugin, dlerror() );
194 #endif
195
196         free( psz_plugin );
197     }
198
199     return( NULL );
200 }
201
202
203 int AllocatePlugin( plugin_id_t plugin_id, plugin_bank_t * p_bank,
204                     char * psz_filename )
205 {
206     typedef plugin_info_t * ( get_config_t ) ( void );
207     get_config_t * p_func;   
208     int i;
209
210     for( i = 0 ; i < p_bank->i_plugin_count ; i++ )
211     {
212         if( p_bank->p_info[ i ] == NULL )
213         {
214             break;
215         }
216     }
217
218     /* no room to store that plugin, quit */
219     if( i == p_bank->i_plugin_count )
220     {
221         intf_ErrMsg( "plugin bank error: reached max plugin count (%i), "
222                      "increase MAX_PLUGIN_COUNT\n", p_bank->i_plugin_count );
223         return( -1 );
224     }
225
226     /* system-specific dynamic symbol loading */
227     GET_PLUGIN( p_func, plugin_id, "GetConfig" );
228
229     /* if it failed, just quit */
230     if( !p_func )
231     {
232         return( -1 );
233     }
234
235     /* run the plugin function to initialize the structure */
236     p_bank->p_info[ i ]            = p_func( );
237     p_bank->p_info[ i ]->plugin_id = plugin_id;
238     p_bank->p_info[ i ]->psz_filename = strdup( psz_filename );
239
240
241     /* Tell the world we found it */
242     intf_Msg( "Plugin %i: %s %s [0x%x]\n", i,
243               p_bank->p_info[ i ]->psz_name,
244               p_bank->p_info[ i ]->psz_version,
245               p_bank->p_info[ i ]->i_score );
246
247     /* return nicely */
248     return( 0 );
249 }
250
251 #if 0
252 void TrashPlugin ( plugin_id_t plugin_id )
253 {
254 #ifdef SYS_BEOS
255     unload_add_on( plugin_id );
256 #else
257     dlclose( plugin_id );
258 #endif
259 }
260 #endif
261