modules.c 64.2 KB
Newer Older
Sam Hocevar's avatar
   
Sam Hocevar committed
1
/*****************************************************************************
2
 * modules.c : Builtin and plugin modules management functions
Sam Hocevar's avatar
   
Sam Hocevar committed
3
 *****************************************************************************
zorglub's avatar
zorglub committed
4
 * Copyright (C) 2001-2004 VideoLAN
5
 * $Id$
Sam Hocevar's avatar
   
Sam Hocevar committed
6
 *
7
 * Authors: Sam Hocevar <sam@zoy.org>
Sam Hocevar's avatar
   
Sam Hocevar committed
8
 *          Ethan C. Baldridge <BaldridgeE@cadmus.com>
Sam Hocevar's avatar
   
Sam Hocevar committed
9
 *          Hans-Peter Jansen <hpj@urpla.net>
10
 *          Gildas Bazin <gbazin@videolan.org>
Sam Hocevar's avatar
   
Sam Hocevar committed
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
 *****************************************************************************/

Sam Hocevar's avatar
   
Sam Hocevar committed
27
28
29
30
31
32
/* Some faulty libcs have a broken struct dirent when _FILE_OFFSET_BITS
 * is set to 64. Don't try to be cleverer. */
#ifdef _FILE_OFFSET_BITS
#undef _FILE_OFFSET_BITS
#endif

Sam Hocevar's avatar
   
Sam Hocevar committed
33
34
#include <stdlib.h>                                      /* free(), strtol() */
#include <stdio.h>                                              /* sprintf() */
Sam Hocevar's avatar
   
Sam Hocevar committed
35
#include <string.h>                                              /* strdup() */
Sam Hocevar's avatar
   
Sam Hocevar committed
36

37
#include <vlc/vlc.h>
Laurent Aimar's avatar
Laurent Aimar committed
38
#include <vlc/input.h>
Sam Hocevar's avatar
   
Sam Hocevar committed
39

40
41
#ifdef HAVE_DIRENT_H
#   include <dirent.h>
42
43
#elif defined( UNDER_CE )
#   include <windows.h>                               /* GetFileAttributes() */
44
45
46
47
#else
#   include "../extras/dirent.h"
#endif

48
49
50
51
52
53
#ifdef HAVE_SYS_TYPES_H
#   include <sys/types.h>
#endif
#ifdef HAVE_SYS_STAT_H
#   include <sys/stat.h>
#endif
54
55
56
#ifdef HAVE_UNISTD_H
#   include <unistd.h>
#endif
Sam Hocevar's avatar
   
Sam Hocevar committed
57

zorglub's avatar
zorglub committed
58
#define HAVE_DYNAMIC_PLUGINS
Sam Hocevar's avatar
Sam Hocevar committed
59
60
61
62
63
64
65
66
67
#if defined(HAVE_DL_DYLD)
#   if defined(HAVE_MACH_O_DYLD_H)
#       include <mach-o/dyld.h>
#   endif
#elif defined(HAVE_DL_BEOS)
#   if defined(HAVE_IMAGE_H)
#       include <image.h>
#   endif
#elif defined(HAVE_DL_WINDOWS)
Sam Hocevar's avatar
Sam Hocevar committed
68
#   include <windows.h>
Sam Hocevar's avatar
Sam Hocevar committed
69
70
#elif defined(HAVE_DL_DLOPEN)
#   if defined(HAVE_DLFCN_H) /* Linux, BSD, Hurd */
Sam Hocevar's avatar
Sam Hocevar committed
71
72
#       include <dlfcn.h>
#   endif
Sam Hocevar's avatar
Sam Hocevar committed
73
#   if defined(HAVE_SYS_DL_H)
Sam Hocevar's avatar
Sam Hocevar committed
74
75
#       include <sys/dl.h>
#   endif
Sam Hocevar's avatar
Sam Hocevar committed
76
77
#elif defined(HAVE_DL_SHL_LOAD)
#   if defined(HAVE_DL_H)
Sam Hocevar's avatar
Sam Hocevar committed
78
79
#       include <dl.h>
#   endif
Sam Hocevar's avatar
   
Sam Hocevar committed
80
#else
Sam Hocevar's avatar
   
Sam Hocevar committed
81
#   undef HAVE_DYNAMIC_PLUGINS
Sam Hocevar's avatar
   
Sam Hocevar committed
82
83
#endif

84
#include "vlc_error.h"
Sam Hocevar's avatar
   
Sam Hocevar committed
85

86
#include "vlc_interface.h"
Sam Hocevar's avatar
   
Sam Hocevar committed
87
#include "intf_eject.h"
Sam Hocevar's avatar
   
Sam Hocevar committed
88

89
90
#include "vlc_playlist.h"

91
#include "vlc_video.h"
Sam Hocevar's avatar
   
Sam Hocevar committed
92
#include "video_output.h"
93
#include "vout_synchro.h"
94
#include "vlc_spu.h"
Sam Hocevar's avatar
   
Sam Hocevar committed
95
96

#include "audio_output.h"
97
#include "aout_internal.h"
Sam Hocevar's avatar
   
Sam Hocevar committed
98

99
#include "stream_output.h"
100
#include "osd.h"
sigmunau's avatar
sigmunau committed
101
#include "vlc_httpd.h"
102

gbazin's avatar
   
gbazin committed
103
#include "iso_lang.h"
hartman's avatar
hartman committed
104
#include "charset.h"
gbazin's avatar
   
gbazin committed
105

106
107
#include "vlc_block.h"

108
109
#include "vlc_vlm.h"

Sam Hocevar's avatar
   
Sam Hocevar committed
110
#ifdef HAVE_DYNAMIC_PLUGINS
Sam Hocevar's avatar
   
Sam Hocevar committed
111
#   include "modules_plugin.h"
Sam Hocevar's avatar
   
Sam Hocevar committed
112
#endif
gbazin's avatar
   
gbazin committed
113

114
115
116
#if defined( UNDER_CE )
#    include "modules_builtin_evc.h"
#elif defined( _MSC_VER )
gbazin's avatar
   
gbazin committed
117
#    include "modules_builtin_msvc.h"
118
119
#else
#    include "modules_builtin.h"
gbazin's avatar
   
gbazin committed
120
#endif
Laurent Aimar's avatar
   
Laurent Aimar committed
121
#include "network.h"
Sam Hocevar's avatar
   
Sam Hocevar committed
122

123
124
125
126
127
#if defined( WIN32) || defined( UNDER_CE )
    /* Avoid name collisions */
#   define LoadModule(a,b,c) _LoadModule(a,b,c)
#endif

Sam Hocevar's avatar
   
Sam Hocevar committed
128
129
130
/*****************************************************************************
 * Local prototypes
 *****************************************************************************/
Sam Hocevar's avatar
   
Sam Hocevar committed
131
#ifdef HAVE_DYNAMIC_PLUGINS
132
133
134
135
static void AllocateAllPlugins  ( vlc_object_t * );
static void AllocatePluginDir   ( vlc_object_t *, const char *, int );
static int  AllocatePluginFile  ( vlc_object_t *, char *, int64_t, int64_t );
static module_t * AllocatePlugin( vlc_object_t *, char * );
Sam Hocevar's avatar
   
Sam Hocevar committed
136
#endif
137
static int  AllocateBuiltinModule( vlc_object_t *, int ( * ) ( module_t * ) );
Sam Hocevar's avatar
   
Sam Hocevar committed
138
static int  DeleteModule ( module_t * );
Sam Hocevar's avatar
   
Sam Hocevar committed
139
#ifdef HAVE_DYNAMIC_PLUGINS
140
141
142
static void   DupModule        ( module_t * );
static void   UndupModule      ( module_t * );
static int    CallEntry        ( module_t * );
143
static int    LoadModule       ( vlc_object_t *, char *, module_handle_t * );
144
145
static void   CloseModule      ( module_handle_t );
static void * GetSymbol        ( module_handle_t, const char * );
146
static void   CacheLoad        ( vlc_object_t * );
147
static int    CacheLoadConfig  ( module_t *, FILE * );
148
149
150
151
152
static void   CacheSave        ( vlc_object_t * );
static void   CacheSaveConfig  ( module_t *, FILE * );
static void   CacheMerge       ( vlc_object_t *, module_t *, module_t * );
static module_cache_t * CacheFind( vlc_object_t *, char *, int64_t, int64_t );

Sam Hocevar's avatar
Sam Hocevar committed
153
#if defined(HAVE_DL_WINDOWS)
154
155
static char * GetWindowsError  ( void );
#endif
156
#endif
Sam Hocevar's avatar
   
Sam Hocevar committed
157

Sam Hocevar's avatar
   
Sam Hocevar committed
158
159
160
/*****************************************************************************
 * module_InitBank: create the module bank.
 *****************************************************************************
gbazin's avatar
   
gbazin committed
161
162
 * This function creates a module bank structure which will be filled later
 * on with all the modules found.
Sam Hocevar's avatar
   
Sam Hocevar committed
163
 *****************************************************************************/
164
void __module_InitBank( vlc_object_t *p_this )
Sam Hocevar's avatar
   
Sam Hocevar committed
165
{
166
    module_bank_t *p_bank;
167
168
169
170
171
172
173
174
175
176
177
178
179
180
    vlc_value_t  lockval;

    var_Create( p_this->p_libvlc, "libvlc", VLC_VAR_MUTEX );
    var_Get( p_this->p_libvlc, "libvlc", &lockval );
    vlc_mutex_lock( lockval.p_address );
    if( p_this->p_libvlc->p_module_bank )
    {
        p_this->p_libvlc->p_module_bank->i_usage++;
        vlc_mutex_unlock( lockval.p_address );
        var_Destroy( p_this->p_libvlc, "libvlc" );
        return;
    }
    vlc_mutex_unlock( lockval.p_address );
    var_Destroy( p_this->p_libvlc, "libvlc" );
181
182
183

    p_bank = vlc_object_create( p_this, sizeof(module_bank_t) );
    p_bank->psz_object_name = "module bank";
184
    p_bank->i_usage = 1;
185
186
187
188
    p_bank->i_cache = p_bank->i_loaded_cache = 0;
    p_bank->pp_cache = p_bank->pp_loaded_cache = 0;
    p_bank->b_cache = p_bank->b_cache_dirty =
        p_bank->b_cache_delete = VLC_FALSE;
189

Sam Hocevar's avatar
   
Sam Hocevar committed
190
191
192
    /*
     * Store the symbols to be exported
     */
193
#ifdef HAVE_DYNAMIC_PLUGINS
194
    STORE_SYMBOLS( &p_bank->symbols );
195
#endif
Sam Hocevar's avatar
   
Sam Hocevar committed
196

197
    /* Everything worked, attach the object */
198
199
    p_this->p_libvlc->p_module_bank = p_bank;
    vlc_object_attach( p_bank, p_this->p_libvlc );
200

201
202
    module_LoadMain( p_this );

gbazin's avatar
   
gbazin committed
203
204
205
206
    return;
}

/*****************************************************************************
207
 * module_ResetBank: reset the module bank.
gbazin's avatar
   
gbazin committed
208
 *****************************************************************************
209
210
 * This function resets the module bank by unloading all unused plugin
 * modules.
gbazin's avatar
   
gbazin committed
211
 *****************************************************************************/
212
void __module_ResetBank( vlc_object_t *p_this )
gbazin's avatar
   
gbazin committed
213
{
214
215
    msg_Err( p_this, "FIXME: module_ResetBank unimplemented" );
    return;
Sam Hocevar's avatar
   
Sam Hocevar committed
216
217
}

Sam Hocevar's avatar
   
Sam Hocevar committed
218
/*****************************************************************************
Sam Hocevar's avatar
   
Sam Hocevar committed
219
 * module_EndBank: empty the module bank.
Sam Hocevar's avatar
   
Sam Hocevar committed
220
 *****************************************************************************
Sam Hocevar's avatar
   
Sam Hocevar committed
221
 * This function unloads all unused plugin modules and empties the module
Sam Hocevar's avatar
   
Sam Hocevar committed
222
223
 * bank in case of success.
 *****************************************************************************/
224
void __module_EndBank( vlc_object_t *p_this )
Sam Hocevar's avatar
   
Sam Hocevar committed
225
{
Sam Hocevar's avatar
   
Sam Hocevar committed
226
    module_t * p_next;
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
    vlc_value_t  lockval;

    var_Create( p_this->p_libvlc, "libvlc", VLC_VAR_MUTEX );
    var_Get( p_this->p_libvlc, "libvlc", &lockval );
    vlc_mutex_lock( lockval.p_address );
    if( !p_this->p_libvlc->p_module_bank )
    {
        vlc_mutex_unlock( lockval.p_address );
        var_Destroy( p_this->p_libvlc, "libvlc" );
        return;
    }
    if( --p_this->p_libvlc->p_module_bank->i_usage )
    {
        vlc_mutex_unlock( lockval.p_address );
        var_Destroy( p_this->p_libvlc, "libvlc" );
        return;
    }
    vlc_mutex_unlock( lockval.p_address );
    var_Destroy( p_this->p_libvlc, "libvlc" );
Sam Hocevar's avatar
   
Sam Hocevar committed
246

247
248
249
250
#ifdef HAVE_DYNAMIC_PLUGINS
    if( p_this->p_libvlc->p_module_bank->b_cache ) CacheSave( p_this );
#endif

251
    vlc_object_detach( p_this->p_libvlc->p_module_bank );
252

253
    while( p_this->p_libvlc->p_module_bank->i_children )
Sam Hocevar's avatar
   
Sam Hocevar committed
254
    {
255
        p_next = (module_t *)p_this->p_libvlc->p_module_bank->pp_children[0];
256
257

        if( DeleteModule( p_next ) )
Sam Hocevar's avatar
   
Sam Hocevar committed
258
259
        {
            /* Module deletion failed */
260
            msg_Err( p_this, "module \"%s\" can't be removed, trying harder",
261
                     p_next->psz_object_name );
Sam Hocevar's avatar
   
Sam Hocevar committed
262
263

            /* We just free the module by hand. Niahahahahaha. */
264
265
            vlc_object_detach( p_next );
            vlc_object_destroy( p_next );
Sam Hocevar's avatar
   
Sam Hocevar committed
266
267
268
        }
    }

269
    vlc_object_destroy( p_this->p_libvlc->p_module_bank );
Sam Hocevar's avatar
   
Sam Hocevar committed
270
271

    return;
Sam Hocevar's avatar
   
Sam Hocevar committed
272
273
274
}

/*****************************************************************************
275
 * module_LoadMain: load the main program info into the module bank.
Sam Hocevar's avatar
   
Sam Hocevar committed
276
 *****************************************************************************
277
278
279
280
 * This function fills the module bank structure with the main module infos.
 * This is very useful as it will allow us to consider the main program just
 * as another module, and for instance the configuration options of main will
 * be available in the module bank structure just as for every other module.
Sam Hocevar's avatar
   
Sam Hocevar committed
281
 *****************************************************************************/
282
void __module_LoadMain( vlc_object_t *p_this )
Sam Hocevar's avatar
   
Sam Hocevar committed
283
{
284
    AllocateBuiltinModule( p_this, vlc_entry__main );
285
286
287
288
289
290
291
}

/*****************************************************************************
 * module_LoadBuiltins: load all modules which we built with.
 *****************************************************************************
 * This function fills the module bank structure with the builtin modules.
 *****************************************************************************/
292
void __module_LoadBuiltins( vlc_object_t * p_this )
293
294
295
296
297
298
299
300
301
302
{
    msg_Dbg( p_this, "checking builtin modules" );
    ALLOCATE_ALL_BUILTINS();
}

/*****************************************************************************
 * module_LoadPlugins: load all plugin modules we can find.
 *****************************************************************************
 * This function fills the module bank structure with the plugin modules.
 *****************************************************************************/
303
void __module_LoadPlugins( vlc_object_t * p_this )
304
305
306
{
#ifdef HAVE_DYNAMIC_PLUGINS
    msg_Dbg( p_this, "checking plugin modules" );
307
308
309
310
311
312
313

    if( config_GetInt( p_this, "plugins-cache" ) )
        p_this->p_libvlc->p_module_bank->b_cache = VLC_TRUE;

    if( p_this->p_libvlc->p_module_bank->b_cache ||
        p_this->p_libvlc->p_module_bank->b_cache_delete ) CacheLoad( p_this );

314
315
    AllocateAllPlugins( p_this );
#endif
Sam Hocevar's avatar
   
Sam Hocevar committed
316
317
318
}

/*****************************************************************************
319
 * module_Need: return the best module function, given a capability list.
Sam Hocevar's avatar
   
Sam Hocevar committed
320
 *****************************************************************************
321
 * This function returns the module that best fits the asked capabilities.
Sam Hocevar's avatar
   
Sam Hocevar committed
322
 *****************************************************************************/
323
module_t * __module_Need( vlc_object_t *p_this, const char *psz_capability,
gbazin's avatar
   
gbazin committed
324
                          const char *psz_name, vlc_bool_t b_strict )
Sam Hocevar's avatar
   
Sam Hocevar committed
325
{
326
    typedef struct module_list_t module_list_t;
327

328
    struct module_list_t
Sam Hocevar's avatar
   
Sam Hocevar committed
329
    {
330
        module_t *p_module;
331
        int i_score;
332
        vlc_bool_t b_force;
333
334
335
336
        module_list_t *p_next;
    };

    module_list_t *p_list, *p_first, *p_tmp;
337
    vlc_list_t *p_all;
Sam Hocevar's avatar
   
Sam Hocevar committed
338

gbazin's avatar
   
gbazin committed
339
    int i_which_module, i_index = 0;
340
    vlc_bool_t b_intf = VLC_FALSE;
Sam Hocevar's avatar
   
Sam Hocevar committed
341
342

    module_t *p_module;
343

344
    int   i_shortcuts = 0;
345
    char *psz_shortcuts = NULL, *psz_var = NULL;
Sam Hocevar's avatar
   
Sam Hocevar committed
346

347
    msg_Dbg( p_this, "looking for %s module", psz_capability );
348

349
350
351
    /* Deal with variables */
    if( psz_name && psz_name[0] == '$' )
    {
gbazin's avatar
   
gbazin committed
352
353
354
355
        vlc_value_t val;
        var_Create( p_this, psz_name + 1, VLC_VAR_MODULE | VLC_VAR_DOINHERIT );
        var_Get( p_this, psz_name + 1, &val );
        psz_var = val.psz_string;
356
        psz_name = psz_var;
357
358
    }

359
    /* Count how many different shortcuts were asked for */
360
    if( psz_name && *psz_name )
Sam Hocevar's avatar
   
Sam Hocevar committed
361
    {
gbazin's avatar
   
gbazin committed
362
        char *psz_parser, *psz_last_shortcut;
363

364
365
366
        /* If the user wants none, give him none. */
        if( !strcmp( psz_name, "none" ) )
        {
367
            if( psz_var ) free( psz_var );
368
369
370
            return NULL;
        }

371
        i_shortcuts++;
gbazin's avatar
   
gbazin committed
372
        psz_shortcuts = psz_last_shortcut = strdup( psz_name );
373
374

        for( psz_parser = psz_shortcuts; *psz_parser; psz_parser++ )
Sam Hocevar's avatar
   
Sam Hocevar committed
375
        {
376
            if( *psz_parser == ',' )
Sam Hocevar's avatar
   
Sam Hocevar committed
377
            {
378
379
                 *psz_parser = '\0';
                 i_shortcuts++;
gbazin's avatar
   
gbazin committed
380
                 psz_last_shortcut = psz_parser + 1;
Sam Hocevar's avatar
   
Sam Hocevar committed
381
            }
Sam Hocevar's avatar
   
Sam Hocevar committed
382
        }
gbazin's avatar
   
gbazin committed
383
384
385
386

        /* Check if the user wants to override the "strict" mode */
        if( psz_last_shortcut )
        {
387
388
389
390
391
392
393
394
395
396
            if( !strcmp(psz_last_shortcut, "none") )
            {
                b_strict = VLC_TRUE;
                i_shortcuts--;
            }
            else if( !strcmp(psz_last_shortcut, "any") )
            {
                b_strict = VLC_FALSE;
                i_shortcuts--;
            }
gbazin's avatar
   
gbazin committed
397
        }
Sam Hocevar's avatar
   
Sam Hocevar committed
398
    }
Sam Hocevar's avatar
   
Sam Hocevar committed
399

Sam Hocevar's avatar
   
Sam Hocevar committed
400
    /* Sort the modules and test them */
401
402
    p_all = vlc_list_find( p_this, VLC_OBJECT_MODULE, FIND_ANYWHERE );
    p_list = malloc( p_all->i_count * sizeof( module_list_t ) );
Sam Hocevar's avatar
   
Sam Hocevar committed
403
    p_first = NULL;
Sam Hocevar's avatar
   
Sam Hocevar committed
404

Sam Hocevar's avatar
   
Sam Hocevar committed
405
    /* Parse the module list for capabilities and probe each of them */
406
    for( i_which_module = 0; i_which_module < p_all->i_count; i_which_module++ )
Sam Hocevar's avatar
   
Sam Hocevar committed
407
    {
408
        int i_shortcut_bonus = 0;
409

410
        p_module = (module_t *)p_all->p_values[i_which_module].p_object;
411

412
413
        /* Test that this module can do what we need */
        if( strcmp( p_module->psz_capability, psz_capability ) )
Sam Hocevar's avatar
   
Sam Hocevar committed
414
        {
415
416
417
            /* Don't recurse through the sub-modules because vlc_list_find()
             * will list them anyway. */
            continue;
Sam Hocevar's avatar
   
Sam Hocevar committed
418
419
        }

Sam Hocevar's avatar
   
Sam Hocevar committed
420
        /* Test if we have the required CPU */
421
        if( (p_module->i_cpu & p_this->p_libvlc->i_cpu) != p_module->i_cpu )
Sam Hocevar's avatar
   
Sam Hocevar committed
422
        {
Sam Hocevar's avatar
   
Sam Hocevar committed
423
            continue;
Sam Hocevar's avatar
   
Sam Hocevar committed
424
        }
Sam Hocevar's avatar
   
Sam Hocevar committed
425

426
        /* If we required a shortcut, check this plugin provides it. */
427
        if( i_shortcuts > 0 )
Sam Hocevar's avatar
   
Sam Hocevar committed
428
        {
gbazin's avatar
   
gbazin committed
429
            vlc_bool_t b_trash;
430
431
            int i_dummy, i_short = i_shortcuts;
            char *psz_name = psz_shortcuts;
Sam Hocevar's avatar
   
Sam Hocevar committed
432

433
            /* Let's drop modules with a <= 0 score (unless they are
gbazin's avatar
   
gbazin committed
434
             * explicitly requested) */
435
            b_trash = p_module->i_score <= 0;
gbazin's avatar
   
gbazin committed
436

437
            while( i_short > 0 )
Sam Hocevar's avatar
   
Sam Hocevar committed
438
            {
gbazin's avatar
   
gbazin committed
439
                for( i_dummy = 0; p_module->pp_shortcuts[i_dummy]; i_dummy++ )
440
                {
441
442
                    if( !strcasecmp( psz_name,
                                     p_module->pp_shortcuts[i_dummy] ) )
gbazin's avatar
   
gbazin committed
443
444
445
446
447
448
                    {
                        /* Found it */
                        b_trash = VLC_FALSE;
                        i_shortcut_bonus = i_short * 10000;
                        break;
                    }
449
450
                }

gbazin's avatar
   
gbazin committed
451
                if( i_shortcut_bonus )
452
                {
gbazin's avatar
   
gbazin committed
453
                    /* We found it... remember ? */
454
455
456
                    break;
                }

457
                /* Go to the next shortcut... This is so lame! */
458
459
460
461
462
463
                while( *psz_name )
                {
                    psz_name++;
                }
                psz_name++;
                i_short--;
Sam Hocevar's avatar
   
Sam Hocevar committed
464
            }
Sam Hocevar's avatar
   
Sam Hocevar committed
465

466
467
468
469
470
471
472
473
            /* If we are in "strict" mode and we couldn't
             * find the module in the list of provided shortcuts,
             * then kick the bastard out of here!!! */
            if( i_short == 0 && b_strict )
            {
                b_trash = VLC_TRUE;
            }

474
            if( b_trash )
475
            {
Sam Hocevar's avatar
   
Sam Hocevar committed
476
477
                continue;
            }
Sam Hocevar's avatar
   
Sam Hocevar committed
478
        }
479
480
        /* If we didn't require a shortcut, trash <= 0 scored plugins */
        else if( p_module->i_score <= 0 )
481
482
483
        {
            continue;
        }
484

Sam Hocevar's avatar
   
Sam Hocevar committed
485
        /* Special case: test if we requested a particular intf plugin */
gbazin's avatar
   
gbazin committed
486
        if( !i_shortcuts && p_module->psz_program
487
488
             && !strcmp( p_module->psz_program,
                         p_this->p_vlc->psz_object_name ) )
Sam Hocevar's avatar
   
Sam Hocevar committed
489
        {
490
            if( !b_intf )
Sam Hocevar's avatar
   
Sam Hocevar committed
491
            {
492
493
494
                /* Remove previous non-matching plugins */
                i_index = 0;
                b_intf = VLC_TRUE;
Sam Hocevar's avatar
   
Sam Hocevar committed
495
            }
Sam Hocevar's avatar
   
Sam Hocevar committed
496
        }
497
498
499
500
501
        else if( b_intf )
        {
            /* This one doesn't match */
            continue;
        }
502

Sam Hocevar's avatar
   
Sam Hocevar committed
503
504
        /* Store this new module */
        p_list[ i_index ].p_module = p_module;
505
        p_list[ i_index ].i_score = p_module->i_score + i_shortcut_bonus;
506
        p_list[ i_index ].b_force = !!i_shortcut_bonus;
Sam Hocevar's avatar
   
Sam Hocevar committed
507

Sam Hocevar's avatar
   
Sam Hocevar committed
508
        /* Add it to the modules-to-probe list */
Sam Hocevar's avatar
   
Sam Hocevar committed
509
510
        if( i_index == 0 )
        {
Sam Hocevar's avatar
   
Sam Hocevar committed
511
            p_list[ 0 ].p_next = NULL;
Sam Hocevar's avatar
   
Sam Hocevar committed
512
513
514
515
516
517
518
            p_first = p_list;
        }
        else
        {
            /* Ok, so at school you learned that quicksort is quick, and
             * bubble sort sucks raw eggs. But that's when dealing with
             * thousands of items. Here we have barely 50. */
519
            module_list_t *p_newlist = p_first;
Sam Hocevar's avatar
   
Sam Hocevar committed
520

521
            if( p_first->i_score < p_list[ i_index ].i_score )
Sam Hocevar's avatar
   
Sam Hocevar committed
522
            {
Sam Hocevar's avatar
   
Sam Hocevar committed
523
524
                p_list[ i_index ].p_next = p_first;
                p_first = &p_list[ i_index ];
Sam Hocevar's avatar
   
Sam Hocevar committed
525
526
            }
            else
527
            {
528
529
                while( p_newlist->p_next != NULL &&
                    p_newlist->p_next->i_score >= p_list[ i_index ].i_score )
Sam Hocevar's avatar
   
Sam Hocevar committed
530
                {
Sam Hocevar's avatar
   
Sam Hocevar committed
531
                    p_newlist = p_newlist->p_next;
Sam Hocevar's avatar
   
Sam Hocevar committed
532
533
                }

Sam Hocevar's avatar
   
Sam Hocevar committed
534
535
536
                p_list[ i_index ].p_next = p_newlist->p_next;
                p_newlist->p_next = &p_list[ i_index ];
            }
Sam Hocevar's avatar
   
Sam Hocevar committed
537
538
        }

Sam Hocevar's avatar
   
Sam Hocevar committed
539
540
        i_index++;
    }
Sam Hocevar's avatar
   
Sam Hocevar committed
541

542
543
544
    msg_Dbg( p_this, "probing %i candidate%s",
                     i_index, i_index == 1 ? "" : "s" );

545
    /* Lock all candidate modules */
546
547
    p_tmp = p_first;
    while( p_tmp != NULL )
Sam Hocevar's avatar
   
Sam Hocevar committed
548
    {
549
        vlc_object_yield( p_tmp->p_module );
550
        p_tmp = p_tmp->p_next;
Sam Hocevar's avatar
   
Sam Hocevar committed
551
552
    }

553
    /* We can release the list, interesting modules were yielded */
554
    vlc_list_release( p_all );
Sam Hocevar's avatar
   
Sam Hocevar committed
555

Sam Hocevar's avatar
   
Sam Hocevar committed
556
    /* Parse the linked list and use the first successful module */
557
558
    p_tmp = p_first;
    while( p_tmp != NULL )
Sam Hocevar's avatar
   
Sam Hocevar committed
559
    {
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
#ifdef HAVE_DYNAMIC_PLUGINS
        /* Make sure the module is loaded in mem */
        module_t *p_module = p_tmp->p_module->b_submodule ?
            (module_t *)p_tmp->p_module->p_parent : p_tmp->p_module;
        if( !p_module->b_builtin && !p_module->b_loaded )
        {
            module_t *p_new_module =
                AllocatePlugin( p_this, p_module->psz_filename );
            if( p_new_module )
            {
                CacheMerge( p_this, p_module, p_new_module );
                vlc_object_attach( p_new_module, p_module );
                DeleteModule( p_new_module );
            }
        }
#endif

577
        p_this->b_force = p_tmp->b_force;
578
579
        if( p_tmp->p_module->pf_activate
             && p_tmp->p_module->pf_activate( p_this ) == VLC_SUCCESS )
Sam Hocevar's avatar
   
Sam Hocevar committed
580
581
        {
            break;
582
        }
Sam Hocevar's avatar
   
Sam Hocevar committed
583

584
        vlc_object_release( p_tmp->p_module );
585
        p_tmp = p_tmp->p_next;
Sam Hocevar's avatar
   
Sam Hocevar committed
586
    }
Sam Hocevar's avatar
   
Sam Hocevar committed
587

Sam Hocevar's avatar
   
Sam Hocevar committed
588
    /* Store the locked module value */
589
    if( p_tmp != NULL )
Sam Hocevar's avatar
   
Sam Hocevar committed
590
    {
591
592
        p_module = p_tmp->p_module;
        p_tmp = p_tmp->p_next;
Sam Hocevar's avatar
   
Sam Hocevar committed
593
    }
Sam Hocevar's avatar
   
Sam Hocevar committed
594
595
596
597
    else
    {
        p_module = NULL;
    }
Sam Hocevar's avatar
   
Sam Hocevar committed
598

Sam Hocevar's avatar
   
Sam Hocevar committed
599
    /* Unlock the remaining modules */
600
    while( p_tmp != NULL )
Sam Hocevar's avatar
   
Sam Hocevar committed
601
    {
602
        vlc_object_release( p_tmp->p_module );
603
        p_tmp = p_tmp->p_next;
Sam Hocevar's avatar
   
Sam Hocevar committed
604
    }
Sam Hocevar's avatar
   
Sam Hocevar committed
605

Sam Hocevar's avatar
   
Sam Hocevar committed
606
    free( p_list );
607
    p_this->b_force = VLC_FALSE;
Sam Hocevar's avatar
   
Sam Hocevar committed
608

Sam Hocevar's avatar
   
Sam Hocevar committed
609
    if( p_module != NULL )
Sam Hocevar's avatar
   
Sam Hocevar committed
610
    {
611
612
        msg_Dbg( p_module, "using %s module \"%s\"",
                 psz_capability, p_module->psz_object_name );
613
614
615
    }
    else if( p_first == NULL )
    {
616
617
618
        if( !strcmp( psz_capability, "access_demux" ) )
        {
            msg_Warn( p_this, "no %s module matched \"%s\"",
619
                 psz_capability, (psz_name && *psz_name) ? psz_name : "any" );
620
621
622
623
624
625
        }
        else
        {  
            msg_Err( p_this, "no %s module matched \"%s\"",
                 psz_capability, (psz_name && *psz_name) ? psz_name : "any" );
        }
Sam Hocevar's avatar
   
Sam Hocevar committed
626
    }
Sam Hocevar's avatar
   
Sam Hocevar committed
627
628
    else if( psz_name != NULL && *psz_name )
    {
Christophe Massiot's avatar
Christophe Massiot committed
629
630
        msg_Warn( p_this, "no %s module matching \"%s\" could be loaded",
                  psz_capability, (psz_name && *psz_name) ? psz_name : "any" );
Sam Hocevar's avatar
   
Sam Hocevar committed
631
632
    }

633
    if( psz_shortcuts )
Sam Hocevar's avatar
   
Sam Hocevar committed
634
    {
635
        free( psz_shortcuts );
Sam Hocevar's avatar
   
Sam Hocevar committed
636
    }
Sam Hocevar's avatar
   
Sam Hocevar committed
637

638
    if( psz_var )
639
    {
640
        free( psz_var );
641
642
    }

Sam Hocevar's avatar
   
Sam Hocevar committed
643
    /* Don't forget that the module is still locked */
644
    return p_module;
Sam Hocevar's avatar
   
Sam Hocevar committed
645
646
647
648
649
}

/*****************************************************************************
 * module_Unneed: decrease the usage count of a module.
 *****************************************************************************
650
651
 * This function must be called by the thread that called module_Need, to
 * decrease the reference count and allow for hiding of modules.
Sam Hocevar's avatar
   
Sam Hocevar committed
652
 *****************************************************************************/
653
void __module_Unneed( vlc_object_t * p_this, module_t * p_module )
Sam Hocevar's avatar
   
Sam Hocevar committed
654
{
655
656
657
658
659
660
    /* Use the close method */
    if( p_module->pf_deactivate )
    {
        p_module->pf_deactivate( p_this );
    }

661
    msg_Dbg( p_module, "unlocking module \"%s\"", p_module->psz_object_name );
Sam Hocevar's avatar
   
Sam Hocevar committed
662

663
    vlc_object_release( p_module );
664
665

    return;
Sam Hocevar's avatar
   
Sam Hocevar committed
666
667
668
669
670
671
}

/*****************************************************************************
 * Following functions are local.
 *****************************************************************************/

Sam Hocevar's avatar
   
Sam Hocevar committed
672
673
674
/*****************************************************************************
 * AllocateAllPlugins: load all plugin modules we can find.
 *****************************************************************************/
Sam Hocevar's avatar
   
Sam Hocevar committed
675
#ifdef HAVE_DYNAMIC_PLUGINS
676
static void AllocateAllPlugins( vlc_object_t *p_this )
Sam Hocevar's avatar
   
Sam Hocevar committed
677
{
678
    /* Yes, there are two NULLs because we replace one with "plugin-path". */
679
680
    char *          path[] = { "modules", PLUGIN_PATH, "plugins", NULL,
                               NULL };
Sam Hocevar's avatar
   
Sam Hocevar committed
681
682
683
684

    char **         ppsz_path = path;
    char *          psz_fullpath;

685
    /* If the user provided a plugin path, we add it to the list */
686
687
    path[ sizeof(path)/sizeof(char*) - 2 ] =
        config_GetPsz( p_this, "plugin-path" );
688

Sam Hocevar's avatar
   
Sam Hocevar committed
689
690
    for( ; *ppsz_path != NULL ; ppsz_path++ )
    {
691
692
#if defined( SYS_BEOS ) || defined( SYS_DARWIN ) \
     || ( defined( WIN32 ) && !defined( UNDER_CE ) )
Sam Hocevar's avatar
   
Sam Hocevar committed
693

694
        /* Handle relative as well as absolute paths */
695
#ifdef WIN32
696
        if( !(*ppsz_path)[0] || (*ppsz_path)[1] != ':' )
697
#else
698
        if( (*ppsz_path)[0] != '/' )
699
#endif
Sam Hocevar's avatar
   
Sam Hocevar committed
700
        {
701
702
            int i_dirlen = strlen( *ppsz_path );
            i_dirlen += strlen( p_this->p_libvlc->psz_vlcpath ) + 2;
Sam Hocevar's avatar
   
Sam Hocevar committed
703
704
705
706
707
708

            psz_fullpath = malloc( i_dirlen );
            if( psz_fullpath == NULL )
            {
                continue;
            }
709
710
711
712
#ifdef WIN32
            sprintf( psz_fullpath, "%s\\%s",
                     p_this->p_libvlc->psz_vlcpath, *ppsz_path );
#else
713
714
            sprintf( psz_fullpath, "%s/%s",
                     p_this->p_libvlc->psz_vlcpath, *ppsz_path );
715
#endif
Sam Hocevar's avatar
   
Sam Hocevar committed
716
717
718
719
        }
        else
#endif
        {
720
            psz_fullpath = strdup( *ppsz_path );
Sam Hocevar's avatar
   
Sam Hocevar committed
721
722
        }

723
        msg_Dbg( p_this, "recursively browsing `%s'", psz_fullpath );
Sam Hocevar's avatar
   
Sam Hocevar committed
724

725
726
        /* Don't go deeper than 5 subdirectories */
        AllocatePluginDir( p_this, psz_fullpath, 5 );
Sam Hocevar's avatar
   
Sam Hocevar committed
727

728
        free( psz_fullpath );
Sam Hocevar's avatar
   
Sam Hocevar committed
729
    }
gbazin's avatar
   
gbazin committed
730
731

    /* Free plugin-path */
732
733
    if( path[ sizeof(path)/sizeof(char*) - 2 ] )
        free( path[ sizeof(path)/sizeof(char*) - 2 ] );
gbazin's avatar
   
gbazin committed
734
    path[ sizeof(path)/sizeof(char*) - 2 ] = NULL;
Sam Hocevar's avatar
   
Sam Hocevar committed
735
736
}

Sam Hocevar's avatar
   
Sam Hocevar committed
737
/*****************************************************************************
738
739
 * AllocatePluginDir: recursively parse a directory to look for plugins
 *****************************************************************************/
740
static void AllocatePluginDir( vlc_object_t *p_this, const char *psz_dir,
741
                               int i_maxdepth )
742
{
gbazin's avatar
   
gbazin committed
743
#if defined( UNDER_CE ) || defined( _MSC_VER )
744
#ifdef UNDER_CE
745
    wchar_t psz_path[MAX_PATH + 256];
746
    wchar_t psz_wdir[MAX_PATH];
gbazin's avatar
   
gbazin committed
747
748
749
#else
    char psz_path[MAX_PATH + 256];
#endif
750
751
752
753
    WIN32_FIND_DATA finddata;
    HANDLE handle;
    unsigned int rc;
#else
754
755
    int    i_dirlen;
    DIR *  dir;
756
    struct dirent * file;
757
#endif
758
    char * psz_file;
759

760
    if( p_this->p_vlc->b_die || i_maxdepth < 0 )
761
762
763
764
    {
        return;
    }

gbazin's avatar
   
gbazin committed
765
#if defined( UNDER_CE ) || defined( _MSC_VER )
766
767
768
    MultiByteToWideChar( CP_ACP, 0, psz_dir, -1, psz_wdir, MAX_PATH );

    rc = GetFileAttributes( psz_wdir );
769
770
771
772
773
774
775
    if( !(rc & FILE_ATTRIBUTE_DIRECTORY) )
    {
        /* Not a directory */
        return;
    }

    /* Parse all files in the directory */
gbazin's avatar
   
gbazin committed
776
#ifdef UNDER_CE
777
    swprintf( psz_path, L"%s\\*.*", psz_dir );
gbazin's avatar
   
gbazin committed
778
779
780
#else
    sprintf( psz_path, "%s\\*.*", psz_dir );
#endif
781
782
783
784
785
786
787
788
789
790
    handle = FindFirstFile( psz_path, &finddata );
    if( handle == INVALID_HANDLE_VALUE )
    {
        /* Empty directory */
        return;
    }

    /* Parse the directory and try to load all files it contains. */
    do
    {
gbazin's avatar
   
gbazin committed
791
#ifdef UNDER_CE
792
793
        unsigned int i_len = wcslen( finddata.cFileName );
        swprintf( psz_path, L"%s\\%s", psz_dir, finddata.cFileName );
gbazin's avatar
   
gbazin committed
794
795
796
797
798
799
800
801
802
803
#else
        unsigned int i_len = strlen( finddata.cFileName );
        /* Skip ".", ".." and anything starting with "." */
        if( !*finddata.cFileName || *finddata.cFileName == '.' )
        {
            if( !FindNextFile( handle, &finddata ) ) break;
            continue;
        }
        sprintf( psz_path, "%s\\%s", psz_dir, finddata.cFileName );
#endif
804
805
806
807
808

        if( GetFileAttributes( psz_path ) & FILE_ATTRIBUTE_DIRECTORY )
        {
            AllocatePluginDir( p_this, psz_path, i_maxdepth - 1 );
        }
gbazin's avatar
   
gbazin committed
809
810
811
812
813
814
815
816
817
        else if( i_len > strlen( LIBEXT )
#ifdef UNDER_CE
                )
#else
                  /* We only load files ending with LIBEXT */
                  && !strncasecmp( psz_path + strlen( psz_path)
                                   - strlen( LIBEXT ),
                                   LIBEXT, strlen( LIBEXT ) ) )
#endif
818
        {
819
820
821
822
823
824
825
826
827
828
#ifdef UNDER_CE
            char psz_filename[MAX_PATH];
            WideCharToMultiByte( CP_ACP, WC_DEFAULTCHAR, psz_path, -1,
                                 psz_filename, MAX_PATH, NULL, NULL );
            psz_file = psz_filename;
#else
            psz_file = psz_path;
#endif

            AllocatePluginFile( p_this, psz_file, 0, 0 );
829
830
        }
    }
831
    while( !p_this->p_vlc->b_die && FindNextFile( handle, &finddata ) );
832

833
834
835
836
837
    /* Close the directory */
    FindClose( handle );

#else
    dir = opendir( psz_dir );
838
    if( !dir )
839
    {
840
841
842
843
844
845
        return;
    }

    i_dirlen = strlen( psz_dir );

    /* Parse the directory and try to load all files it contains. */
846
    while( !p_this->p_vlc->b_die && (file = readdir( dir )) )
847
848
    {
        struct stat statbuf;
849
        unsigned int i_len;
850
        int i_stat;
851
852
853

        /* Skip ".", ".." and anything starting with "." */
        if( !*file->d_name || *file->d_name == '.' )
854
        {
855
856
            continue;
        }
857

858
        i_len = strlen( file->d_name );
859
        psz_file = malloc( i_dirlen + 1 + i_len + 1 );
860
861
862
#ifdef WIN32
        sprintf( psz_file, "%s\\%s", psz_dir, file->d_name );
#else
863
        sprintf( psz_file, "%s/%s", psz_dir, file->d_name );
864
#endif
865

866
867
        i_stat = stat( psz_file, &statbuf );
        if( !i_stat && statbuf.st_mode & S_IFDIR )
868
        {
869
            AllocatePluginDir( p_this, psz_file, i_maxdepth - 1 );
870
        }
871
872
        else if( i_len > strlen( LIBEXT )
                  /* We only load files ending with LIBEXT */
873
874
                  && !strncasecmp( file->d_name + i_len - strlen( LIBEXT ),
                                   LIBEXT, strlen( LIBEXT ) ) )
875
        {
876
877
878
879
880
881
882
883
884
            int64_t i_time = 0, i_size = 0;

            if( !i_stat )
            {
                i_time = statbuf.st_mtime;
                i_size = statbuf.st_size;
            }

            AllocatePluginFile( p_this, psz_file, i_time, i_size );
885
886
        }

887
        free( psz_file );
888
    }
889
890
891

    /* Close the directory */
    closedir( dir );
892
893

#endif
894
895
896
897
}

/*****************************************************************************
 * AllocatePluginFile: load a module into memory and initialize it.
Sam Hocevar's avatar
   
Sam Hocevar committed
898
899
 *****************************************************************************
 * This function loads a dynamically loadable module and allocates a structure
900
901
 * for its information data. The module can then be handled by module_Need
 * and module_Unneed. It can be removed by DeleteModule.
Sam Hocevar's avatar
   
Sam Hocevar committed
902
 *****************************************************************************/
903
904
static int AllocatePluginFile( vlc_object_t * p_this, char * psz_file,
                               int64_t i_file_time, int64_t i_file_size )
Sam Hocevar's avatar
   
Sam Hocevar committed
905
{