]> git.sesse.net Git - vlc/blob - src/libvlc-common.c
D-Bus module now uses new specification
[vlc] / src / libvlc-common.c
1 /*****************************************************************************
2  * libvlc-common.c: libvlc instances creation and deletion, interfaces handling
3  *****************************************************************************
4  * Copyright (C) 1998-2006 the VideoLAN team
5  * $Id$
6  *
7  * Authors: Vincent Seguin <seguin@via.ecp.fr>
8  *          Samuel Hocevar <sam@zoy.org>
9  *          Gildas Bazin <gbazin@videolan.org>
10  *          Derk-Jan Hartman <hartman at videolan dot org>
11  *          RĂ©mi Denis-Courmont <rem # videolan : org>
12  *
13  * This program is free software; you can redistribute it and/or modify
14  * it under the terms of the GNU General Public License as published by
15  * the Free Software Foundation; either version 2 of the License, or
16  * (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software
25  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
26  *****************************************************************************/
27
28 /** \file
29  * This file contains functions to create and destroy libvlc instances
30  */
31
32 /*****************************************************************************
33  * Preamble
34  *****************************************************************************/
35 #include <vlc/vlc.h>
36 #include "control/libvlc_internal.h"
37 #include <vlc_input.h>
38
39 #include "misc/modules.h"
40 #include "misc/configuration.h"
41
42 #include <errno.h>                                                 /* ENOMEM */
43 #include <stdio.h>                                              /* sprintf() */
44 #include <string.h>                                            /* strerror() */
45 #include <stdlib.h>                                                /* free() */
46
47 #ifndef WIN32
48 #   include <netinet/in.h>                            /* BSD: struct in_addr */
49 #endif
50
51 #ifdef HAVE_UNISTD_H
52 #   include <unistd.h>
53 #elif defined( WIN32 ) && !defined( UNDER_CE )
54 #   include <io.h>
55 #endif
56
57 #ifdef WIN32                       /* optind, getopt(), included in unistd.h */
58 #   include "extras/getopt.h"
59 #endif
60
61 #ifdef HAVE_LOCALE_H
62 #   include <locale.h>
63 #endif
64
65 #ifdef HAVE_DBUS_3
66 /* used for one-instance mode */
67 #   include <dbus/dbus.h>
68 #endif
69
70 #ifdef HAVE_HAL
71 #   include <hal/libhal.h>
72 #endif
73
74 #include "vlc_os_specific.h"
75
76 #include <vlc_playlist.h>
77 #include <vlc_interface.h>
78
79 #include <vlc_aout.h>
80 #include "audio_output/aout_internal.h"
81
82 #include <vlc_vout.h>
83
84 #include <vlc_sout.h>
85 #include "stream_output/stream_output.h"
86
87 #include <vlc_charset.h>
88
89 #include "libvlc.h"
90
91 #include "playlist/playlist_internal.h"
92
93 /*****************************************************************************
94  * The evil global variable. We handle it with care, don't worry.
95  *****************************************************************************/
96 static libvlc_global_data_t   libvlc_global;
97 static libvlc_global_data_t * p_libvlc_global;
98 static libvlc_int_t *    p_static_vlc;
99 static volatile unsigned int i_instances = 0;
100
101 /*****************************************************************************
102  * Local prototypes
103  *****************************************************************************/
104 void LocaleInit( vlc_object_t * );
105 void LocaleDeinit( void );
106 static void SetLanguage   ( char const * );
107 static int  GetFilenames  ( libvlc_int_t *, int, char *[] );
108 static void Help          ( libvlc_int_t *, char const *psz_help_name );
109 static void Usage         ( libvlc_int_t *, char const *psz_module_name );
110 static void ListModules   ( libvlc_int_t * );
111 static void Version       ( void );
112
113 #ifdef WIN32
114 static void ShowConsole   ( vlc_bool_t );
115 static void PauseConsole  ( void );
116 #endif
117 static int  ConsoleWidth  ( void );
118
119 static int  VerboseCallback( vlc_object_t *, char const *,
120                              vlc_value_t, vlc_value_t, void * );
121
122 static void InitDeviceValues( libvlc_int_t * );
123
124 /* Refs misc/cpu.c */
125 uint32_t CPUCapabilities( void );
126
127 /*****************************************************************************
128  * vlc_current_object: return the current object.
129  *****************************************************************************
130  * If i_object is non-zero, return the corresponding object. Otherwise,
131  * return the statically allocated p_vlc object.
132  *****************************************************************************/
133 libvlc_int_t * vlc_current_object( int i_object )
134 {
135     if( i_object )
136     {
137          return vlc_object_get( p_libvlc_global, i_object );
138     }
139
140     return p_static_vlc;
141 }
142
143
144 /**
145  * Allocate a libvlc instance, initialize global data if needed
146  * It also initializes the threading system
147  */
148 libvlc_int_t * libvlc_InternalCreate( void )
149 {
150     int i_ret;
151     libvlc_int_t * p_libvlc = NULL;
152     vlc_value_t lockval;
153     char *psz_env;
154
155     /* &libvlc_global never changes,
156      * so we can safely call this multiple times. */
157     p_libvlc_global = &libvlc_global;
158
159     /* vlc_threads_init *must* be the first internal call! No other call is
160      * allowed before the thread system has been initialized. */
161     i_ret = vlc_threads_init( p_libvlc_global );
162     if( i_ret < 0 ) return NULL;
163
164     /* Now that the thread system is initialized, we don't have much, but
165      * at least we have var_Create */
166     var_Create( p_libvlc_global, "libvlc", VLC_VAR_MUTEX );
167     var_Get( p_libvlc_global, "libvlc", &lockval );
168     vlc_mutex_lock( lockval.p_address );
169
170     i_instances++;
171
172     if( !libvlc_global.b_ready )
173     {
174         /* Guess what CPU we have */
175         libvlc_global.i_cpu = CPUCapabilities();
176        /* The module bank will be initialized later */
177         libvlc_global.p_module_bank = NULL;
178
179         libvlc_global.b_ready = VLC_TRUE;
180     }
181     vlc_mutex_unlock( lockval.p_address );
182     var_Destroy( p_libvlc_global, "libvlc" );
183
184     /* Allocate a libvlc instance object */
185     p_libvlc = vlc_object_create( p_libvlc_global, VLC_OBJECT_LIBVLC );
186     if( p_libvlc == NULL ) { i_instances--; return NULL; }
187     p_libvlc->thread_id = 0;
188     p_libvlc->p_playlist = NULL;
189     p_libvlc->psz_object_name = "libvlc";
190
191     /* Initialize message queue */
192     msg_Create( p_libvlc );
193     /* Announce who we are - Do it only for first instance ? */
194     msg_Dbg( p_libvlc, COPYRIGHT_MESSAGE );
195     msg_Dbg( p_libvlc, "libvlc was configured with %s", CONFIGURE_LINE );
196
197     /* Find verbosity from VLC_VERBOSE environment variable */
198     psz_env = getenv( "VLC_VERBOSE" );
199     p_libvlc->i_verbose = psz_env ? atoi( psz_env ) : -1;
200
201 #if defined( HAVE_ISATTY ) && !defined( WIN32 )
202     p_libvlc->b_color = isatty( 2 ); /* 2 is for stderr */
203 #else
204     p_libvlc->b_color = VLC_FALSE;
205 #endif
206
207     /* Initialize mutexes */
208     vlc_mutex_init( p_libvlc, &p_libvlc->config_lock );
209 #ifdef __APPLE__
210     vlc_mutex_init( p_libvlc, &p_libvlc->quicktime_lock );
211     vlc_thread_set_priority( p_libvlc, VLC_THREAD_PRIORITY_LOW );
212 #endif
213     /* Fake attachment */
214     p_libvlc->b_attached = VLC_TRUE;
215     /* Store data for the non-reentrant API */
216     p_static_vlc = p_libvlc;
217
218     return p_libvlc;
219 }
220
221 /*
222  * D-Bus callback needed in libvlc_InternalInit()
223  */
224 #ifdef HAVE_DBUS_3
225 /* Handling of messages received on / object */
226 static DBusHandlerResult handle_root
227     ( DBusConnection *p_conn, DBusMessage *p_from, void *p_data ) 
228 {
229     DBusMessage* p_msg = dbus_message_new_method_return( p_from );
230     if( !p_msg ) return DBUS_HANDLER_RESULT_NEED_MEMORY;
231
232     DBusMessageIter args;
233     dbus_message_iter_init_append( p_msg, &args );
234
235     char *p_root = malloc( strlen( "<node name='/'></node>" ) );
236     if (!p_root ) return DBUS_HANDLER_RESULT_NEED_MEMORY;
237     sprintf( p_root, "<node name='/'></node>" );
238
239     if( !dbus_message_iter_append_basic( &args, DBUS_TYPE_STRING, &p_root ) )
240             return DBUS_HANDLER_RESULT_NEED_MEMORY;
241
242     if( !dbus_connection_send( p_conn, p_msg, NULL ) )
243         return DBUS_HANDLER_RESULT_NEED_MEMORY;
244     dbus_connection_flush( p_conn );
245     dbus_message_unref( p_msg );
246     return DBUS_HANDLER_RESULT_HANDLED;
247 }
248 /* vtable passed to dbus_connection_register_object_path() */
249 static DBusObjectPathVTable vlc_dbus_root_vtable = {
250     NULL, handle_root, NULL, NULL, NULL, NULL
251 };
252
253 #endif
254
255 /**
256  * Initialize a libvlc instance
257  * This function initializes a previously allocated libvlc instance:
258  *  - CPU detection
259  *  - gettext initialization
260  *  - message queue, module bank and playlist initialization
261  *  - configuration and commandline parsing
262  */
263 int libvlc_InternalInit( libvlc_int_t *p_libvlc, int i_argc, char *ppsz_argv[] )
264 {
265     char         p_capabilities[200];
266     char *       p_tmp;
267     char *       psz_modules;
268     char *       psz_parser;
269     char *       psz_control;
270     vlc_bool_t   b_exit = VLC_FALSE;
271     int          i_ret = VLC_EEXIT;
272     module_t    *p_help_module;
273     playlist_t  *p_playlist;
274     vlc_value_t  val;
275 #if defined( ENABLE_NLS ) \
276      && ( defined( HAVE_GETTEXT ) || defined( HAVE_INCLUDED_GETTEXT ) )
277 # if defined (WIN32) || defined (__APPLE__)
278     char *       psz_language;
279 #endif
280 #endif
281
282     /* System specific initialization code */
283     system_Init( p_libvlc, &i_argc, ppsz_argv );
284
285     /* Get the executable name (similar to the basename command) */
286     if( i_argc > 0 )
287     {
288         p_libvlc->psz_object_name = p_tmp = ppsz_argv[ 0 ];
289         while( *p_tmp )
290         {
291             if( *p_tmp == '/' ) p_libvlc->psz_object_name = ++p_tmp;
292             else ++p_tmp;
293         }
294     }
295     else
296     {
297         p_libvlc->psz_object_name = "vlc";
298     }
299
300     /*
301      * Support for gettext
302      */
303     SetLanguage( "" );
304
305     /*
306      * Global iconv, must be done after setlocale()
307      * so that vlc_current_charset() works.
308      */
309     LocaleInit( (vlc_object_t *)p_libvlc );
310
311     /* Translate "C" to the language code: "fr", "en_GB", "nl", "ru"... */
312     msg_Dbg( p_libvlc, "translation test: code is \"%s\"", _("C") );
313
314     /* Initialize the module bank and load the configuration of the
315      * main module. We need to do this at this stage to be able to display
316      * a short help if required by the user. (short help == main module
317      * options) */
318     module_InitBank( p_libvlc );
319
320     /* Hack: insert the help module here */
321     p_help_module = vlc_object_create( p_libvlc, VLC_OBJECT_MODULE );
322     if( p_help_module == NULL )
323     {
324         module_EndBank( p_libvlc );
325         return VLC_EGENERIC;
326     }
327     p_help_module->psz_object_name = "help";
328     p_help_module->psz_longname = N_("Help options");
329     config_Duplicate( p_help_module, libvlc_config, libvlc_config_count );
330     vlc_object_attach( p_help_module, libvlc_global.p_module_bank );
331     /* End hack */
332
333     if( config_LoadCmdLine( p_libvlc, &i_argc, ppsz_argv, VLC_TRUE ) )
334     {
335         vlc_object_detach( p_help_module );
336         config_Free( p_help_module );
337         vlc_object_destroy( p_help_module );
338         module_EndBank( p_libvlc );
339         return VLC_EGENERIC;
340     }
341
342     /* Check for short help option */
343     if( config_GetInt( p_libvlc, "help" ) )
344     {
345         Help( p_libvlc, "help" );
346         b_exit = VLC_TRUE;
347         i_ret = VLC_EEXITSUCCESS;
348     }
349     /* Check for version option */
350     else if( config_GetInt( p_libvlc, "version" ) )
351     {
352         Version();
353         b_exit = VLC_TRUE;
354         i_ret = VLC_EEXITSUCCESS;
355     }
356
357     /* Set the config file stuff */
358     p_libvlc->psz_homedir = config_GetHomeDir();
359     p_libvlc->psz_userdir = config_GetUserDir();
360     if( p_libvlc->psz_userdir == NULL )
361         p_libvlc->psz_userdir = strdup(p_libvlc->psz_homedir);
362     p_libvlc->psz_configfile = config_GetPsz( p_libvlc, "config" );
363     if( p_libvlc->psz_configfile != NULL && p_libvlc->psz_configfile[0] == '~'
364          && p_libvlc->psz_configfile[1] == '/' )
365     {
366         char *psz = malloc( strlen(p_libvlc->psz_userdir)
367                              + strlen(p_libvlc->psz_configfile) );
368         /* This is incomplete : we should also support the ~cmassiot/ syntax. */
369         sprintf( psz, "%s/%s", p_libvlc->psz_userdir,
370                                p_libvlc->psz_configfile + 2 );
371         free( p_libvlc->psz_configfile );
372         p_libvlc->psz_configfile = psz;
373     }
374
375     /* Check for plugins cache options */
376     if( config_GetInt( p_libvlc, "reset-plugins-cache" ) )
377     {
378         libvlc_global.p_module_bank->b_cache_delete = VLC_TRUE;
379     }
380
381     /* Hack: remove the help module here */
382     vlc_object_detach( p_help_module );
383     /* End hack */
384
385     /* Will be re-done properly later on */
386     p_libvlc->i_verbose = config_GetInt( p_libvlc, "verbose" );
387
388     /* Check for daemon mode */
389 #ifndef WIN32
390     if( config_GetInt( p_libvlc, "daemon" ) )
391     {
392 #if HAVE_DAEMON
393         if( daemon( 1, 0) != 0 )
394         {
395             msg_Err( p_libvlc, "Unable to fork vlc to daemon mode" );
396             b_exit = VLC_TRUE;
397         }
398
399         p_libvlc->p_libvlc_global->b_daemon = VLC_TRUE;
400
401         /* lets check if we need to write the pidfile */
402         char * psz_pidfile = config_GetPsz( p_libvlc, "pidfile" );
403
404         if( psz_pidfile != NULL )
405         {
406             FILE *pidfile;
407             pid_t i_pid = getpid ();
408             msg_Dbg( p_libvlc, "PID is %d, writing it to %s",
409                                i_pid, psz_pidfile );
410             pidfile = utf8_fopen( psz_pidfile,"w" );
411             if( pidfile != NULL )
412             {
413                 utf8_fprintf( pidfile, "%d", (int)i_pid );
414                 fclose( pidfile );
415             }
416             else
417             {
418                 msg_Err( p_libvlc, "cannot open pid file for writing: %s (%s)",
419                          psz_pidfile, strerror(errno) );
420             }
421         }
422         free( psz_pidfile );
423
424 #else
425         pid_t i_pid;
426
427         if( ( i_pid = fork() ) < 0 )
428         {
429             msg_Err( p_libvlc, "unable to fork vlc to daemon mode" );
430             b_exit = VLC_TRUE;
431         }
432         else if( i_pid )
433         {
434             /* This is the parent, exit right now */
435             msg_Dbg( p_libvlc, "closing parent process" );
436             b_exit = VLC_TRUE;
437             i_ret = VLC_EEXITSUCCESS;
438         }
439         else
440         {
441             /* We are the child */
442             msg_Dbg( p_libvlc, "daemon spawned" );
443             close( STDIN_FILENO );
444             close( STDOUT_FILENO );
445             close( STDERR_FILENO );
446
447             p_libvlc->p_libvlc_global->b_daemon = VLC_TRUE;
448         }
449 #endif
450     }
451 #endif
452
453     if( b_exit )
454     {
455         config_Free( p_help_module );
456         vlc_object_destroy( p_help_module );
457         module_EndBank( p_libvlc );
458         return i_ret;
459     }
460
461     /* Check for translation config option */
462 #if defined( ENABLE_NLS ) \
463      && ( defined( HAVE_GETTEXT ) || defined( HAVE_INCLUDED_GETTEXT ) )
464 # if defined (WIN32) || defined (__APPLE__)
465     /* This ain't really nice to have to reload the config here but it seems
466      * the only way to do it. */
467     config_LoadConfigFile( p_libvlc, "main" );
468     config_LoadCmdLine( p_libvlc, &i_argc, ppsz_argv, VLC_TRUE );
469
470     /* Check if the user specified a custom language */
471     psz_language = config_GetPsz( p_libvlc, "language" );
472     if( psz_language && *psz_language && strcmp( psz_language, "auto" ) )
473     {
474         vlc_bool_t b_cache_delete = libvlc_global.p_module_bank->b_cache_delete;
475
476         /* Reset the default domain */
477         SetLanguage( psz_language );
478
479         /* Translate "C" to the language code: "fr", "en_GB", "nl", "ru"... */
480         msg_Dbg( p_libvlc, "translation test: code is \"%s\"", _("C") );
481
482         module_EndBank( p_libvlc );
483         module_InitBank( p_libvlc );
484         config_LoadConfigFile( p_libvlc, "main" );
485         config_LoadCmdLine( p_libvlc, &i_argc, ppsz_argv, VLC_TRUE );
486         libvlc_global.p_module_bank->b_cache_delete = b_cache_delete;
487     }
488     if( psz_language ) free( psz_language );
489 # endif
490 #endif
491
492     /*
493      * Load the builtins and plugins into the module_bank.
494      * We have to do it before config_Load*() because this also gets the
495      * list of configuration options exported by each module and loads their
496      * default values.
497      */
498     module_LoadBuiltins( p_libvlc );
499     module_LoadPlugins( p_libvlc );
500     if( p_libvlc->b_die )
501     {
502         b_exit = VLC_TRUE;
503     }
504
505     msg_Dbg( p_libvlc, "module bank initialized, found %i modules",
506                     libvlc_global.p_module_bank->i_children );
507
508     /* Hack: insert the help module here */
509     vlc_object_attach( p_help_module, libvlc_global.p_module_bank );
510     /* End hack */
511
512     /* Check for help on modules */
513     if( (p_tmp = config_GetPsz( p_libvlc, "module" )) )
514     {
515         Help( p_libvlc, p_tmp );
516         free( p_tmp );
517         b_exit = VLC_TRUE;
518         i_ret = VLC_EEXITSUCCESS;
519     }
520     /* Check for long help option */
521     else if( config_GetInt( p_libvlc, "longhelp" ) )
522     {
523         Help( p_libvlc, "longhelp" );
524         b_exit = VLC_TRUE;
525         i_ret = VLC_EEXITSUCCESS;
526     }
527     /* Check for module list option */
528     else if( config_GetInt( p_libvlc, "list" ) )
529     {
530         ListModules( p_libvlc );
531         b_exit = VLC_TRUE;
532         i_ret = VLC_EEXITSUCCESS;
533     }
534
535     /* Check for config file options */
536     if( config_GetInt( p_libvlc, "reset-config" ) )
537     {
538         vlc_object_detach( p_help_module );
539         config_ResetAll( p_libvlc );
540         config_LoadCmdLine( p_libvlc, &i_argc, ppsz_argv, VLC_TRUE );
541         config_SaveConfigFile( p_libvlc, NULL );
542         vlc_object_attach( p_help_module, libvlc_global.p_module_bank );
543     }
544     if( config_GetInt( p_libvlc, "save-config" ) )
545     {
546         vlc_object_detach( p_help_module );
547         config_LoadConfigFile( p_libvlc, NULL );
548         config_LoadCmdLine( p_libvlc, &i_argc, ppsz_argv, VLC_TRUE );
549         config_SaveConfigFile( p_libvlc, NULL );
550         vlc_object_attach( p_help_module, libvlc_global.p_module_bank );
551     }
552
553     /* Hack: remove the help module here */
554     vlc_object_detach( p_help_module );
555     /* End hack */
556
557     if( b_exit )
558     {
559         config_Free( p_help_module );
560         vlc_object_destroy( p_help_module );
561         module_EndBank( p_libvlc );
562         return i_ret;
563     }
564
565     /*
566      * Init device values
567      */
568     InitDeviceValues( p_libvlc );
569
570     /*
571      * Override default configuration with config file settings
572      */
573     config_LoadConfigFile( p_libvlc, NULL );
574
575     /* Hack: insert the help module here */
576     vlc_object_attach( p_help_module, libvlc_global.p_module_bank );
577     /* End hack */
578
579     /*
580      * Override configuration with command line settings
581      */
582     if( config_LoadCmdLine( p_libvlc, &i_argc, ppsz_argv, VLC_FALSE ) )
583     {
584 #ifdef WIN32
585         ShowConsole( VLC_FALSE );
586         /* Pause the console because it's destroyed when we exit */
587         fprintf( stderr, "The command line options couldn't be loaded, check "
588                  "that they are valid.\n" );
589         PauseConsole();
590 #endif
591         vlc_object_detach( p_help_module );
592         config_Free( p_help_module );
593         vlc_object_destroy( p_help_module );
594         module_EndBank( p_libvlc );
595         return VLC_EGENERIC;
596     }
597
598     /* Hack: remove the help module here */
599     vlc_object_detach( p_help_module );
600     config_Free( p_help_module );
601     vlc_object_destroy( p_help_module );
602     /* End hack */
603
604     /*
605      * System specific configuration
606      */
607     system_Configure( p_libvlc, &i_argc, ppsz_argv );
608
609 /* FIXME: could be replaced by using Unix sockets */
610 #ifdef HAVE_DBUS_3
611     /* Initialise D-Bus interface, check for other instances */
612     DBusConnection  *p_conn;
613     DBusError       dbus_error;
614     int             i_dbus_service;
615
616     dbus_threads_init_default();
617     dbus_error_init( &dbus_error );
618
619     /* connect to the session bus */
620     p_conn = dbus_bus_get( DBUS_BUS_SESSION, &dbus_error );
621     if( !p_conn )
622     {
623         msg_Err( p_libvlc, "Failed to connect to the D-Bus session daemon: %s",
624                 dbus_error.message );
625         dbus_error_free( &dbus_error );
626     }
627     else
628     {
629         /* we request the service org.videolan.vlc */
630         i_dbus_service = dbus_bus_request_name( p_conn, "org.videolan.vlc", 0, 
631                 &dbus_error );
632         if( dbus_error_is_set( &dbus_error ) )
633         { 
634             msg_Err( p_libvlc, "Error requesting org.videolan.vlc service: "
635                     "%s\n", dbus_error.message );
636             dbus_error_free( &dbus_error );
637         }
638         else
639         {
640             if( i_dbus_service != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER )
641             { /* the name is already registered by another instance of vlc */
642                 if( config_GetInt( p_libvlc, "one-instance" ) )
643                 {
644                     /* check if a Media Player is available
645                      * if not: D-Bus control is not enabled on the other
646                      * instance and we can't pass MRLs to it */
647                     DBusMessage *p_test_msg, *p_test_reply;
648                     p_test_msg =  dbus_message_new_method_call(
649                             "org.freedesktop.MediaPlayer", "/",
650                             "org.freedesktop.MediaPlayer", "Identity" );
651                     /* block until a reply arrives */
652                     p_test_reply = dbus_connection_send_with_reply_and_block(
653                             p_conn, p_test_msg, -1, &dbus_error );
654                     dbus_message_unref( p_test_msg );
655                     if( p_test_reply == NULL )
656                     {
657                         dbus_error_free( &dbus_error );
658                         msg_Err( p_libvlc, "one instance mode has been "
659                                 "set but D-Bus control interface is not "
660                                 "enabled. Enable it and restart vlc, or "
661                                 "disable one instance mode." );
662                     }
663                     else
664                     {
665                         dbus_message_unref( p_test_reply );
666                         msg_Warn( p_libvlc,
667                                 "Another vlc instance exists: will now exit");
668
669                         int i_input;
670                         DBusMessage* p_dbus_msg;
671                         DBusMessageIter dbus_args;
672                         DBusPendingCall* p_dbus_pending;
673                         dbus_bool_t b_play;
674
675                         for( i_input = optind;i_input < i_argc;i_input++ )
676                         {
677                             msg_Dbg( p_libvlc, "Give %s to other vlc\n",
678                                     ppsz_argv[i_input] );
679
680                             p_dbus_msg = dbus_message_new_method_call(
681                                     "org.freedesktop.MediaPlayer", "/TrackList",
682                                     "org.freedesktop.MediaPlayer", "AddTrack" );
683
684                             if ( NULL == p_dbus_msg )
685                             {
686                                 msg_Err( p_libvlc, "D-Bus problem" );
687                                 system_End( p_libvlc );
688                                 exit( 0 );
689                             }
690
691                             /* append MRLs */
692                             dbus_message_iter_init_append( p_dbus_msg,
693                                     &dbus_args );
694                             if ( !dbus_message_iter_append_basic( &dbus_args, 
695                                         DBUS_TYPE_STRING,
696                                         &ppsz_argv[i_input] ) )
697                             {
698                                 msg_Err( p_libvlc, "Out of memory" );
699                                 dbus_message_unref( p_dbus_msg );
700                                 system_End( p_libvlc );
701                                 exit( 0 );
702                             }
703                             b_play = TRUE;
704                             if( config_GetInt( p_libvlc, "playlist-enqueue" ) )
705                                 b_play = FALSE;
706                             if ( !dbus_message_iter_append_basic( &dbus_args,
707                                         DBUS_TYPE_BOOLEAN, &b_play ) )
708                             {
709                                 msg_Err( p_libvlc, "Out of memory" );
710                                 dbus_message_unref( p_dbus_msg );
711                                 system_End( p_libvlc );
712                                 exit( 0 );
713                             }
714
715                             /* send message and get a handle for a reply */
716                             if ( !dbus_connection_send_with_reply ( p_conn,
717                                         p_dbus_msg, &p_dbus_pending, -1 ) )
718                             {
719                                 msg_Err( p_libvlc, "D-Bus problem" );
720                                 dbus_message_unref( p_dbus_msg );
721                                 system_End( p_libvlc );
722                                 exit( 0 );
723                             }
724
725                             if ( NULL == p_dbus_pending )
726                             {
727                                 msg_Err( p_libvlc, "D-Bus problem" );
728                                 dbus_message_unref( p_dbus_msg );
729                                 system_End( p_libvlc );
730                                 exit( 0 );
731                             }
732                             dbus_connection_flush( p_conn );
733                             dbus_message_unref( p_dbus_msg );
734                             /* block until we receive a reply */
735                             dbus_pending_call_block( p_dbus_pending );
736                             dbus_pending_call_unref( p_dbus_pending );
737                         } /* processes all command line MRLs */
738
739                         /* bye bye */
740                         system_End( p_libvlc );
741                         exit( 0 );
742                     }
743                 } /* we're not in one-instance mode */
744                 else
745                 {
746                     msg_Dbg( p_libvlc, "org.videolan.vlc is already registered "
747                             "on the session bus\n" );
748                 }
749             } /* the named is owned by something else */
750             else
751             {
752                 /* register "/" object */
753                 if( !dbus_connection_register_object_path( p_conn, "/", 
754                         &vlc_dbus_root_vtable, NULL ) )
755                 {
756                     msg_Err( p_libvlc, "Out of memory" );
757                 }
758                 msg_Dbg( p_libvlc, 
759                         "We are the primary owner of org.videolan.vlc on the "
760                         " session bus" );
761             }
762         } /* no error when requesting the name on the bus */
763         /* we unreference the connection when we've finished with it */
764         dbus_connection_unref( p_conn );
765     } /* ( p_conn != NULL ) */
766 #endif
767
768     /*
769      * Message queue options
770      */
771
772     var_Create( p_libvlc, "verbose", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
773     if( config_GetInt( p_libvlc, "quiet" ) )
774     {
775         val.i_int = -1;
776         var_Set( p_libvlc, "verbose", val );
777     }
778     var_AddCallback( p_libvlc, "verbose", VerboseCallback, NULL );
779     var_Change( p_libvlc, "verbose", VLC_VAR_TRIGGER_CALLBACKS, NULL, NULL );
780
781     p_libvlc->b_color = p_libvlc->b_color && config_GetInt( p_libvlc, "color" );
782
783     /*
784      * Output messages that may still be in the queue
785      */
786     msg_Flush( p_libvlc );
787
788     /* p_libvlc initialization. FIXME ? */
789
790     if( !config_GetInt( p_libvlc, "fpu" ) )
791         libvlc_global.i_cpu &= ~CPU_CAPABILITY_FPU;
792
793 #if defined( __i386__ ) || defined( __x86_64__ )
794     if( !config_GetInt( p_libvlc, "mmx" ) )
795         libvlc_global.i_cpu &= ~CPU_CAPABILITY_MMX;
796     if( !config_GetInt( p_libvlc, "3dn" ) )
797         libvlc_global.i_cpu &= ~CPU_CAPABILITY_3DNOW;
798     if( !config_GetInt( p_libvlc, "mmxext" ) )
799         libvlc_global.i_cpu &= ~CPU_CAPABILITY_MMXEXT;
800     if( !config_GetInt( p_libvlc, "sse" ) )
801         libvlc_global.i_cpu &= ~CPU_CAPABILITY_SSE;
802     if( !config_GetInt( p_libvlc, "sse2" ) )
803         libvlc_global.i_cpu &= ~CPU_CAPABILITY_SSE2;
804 #endif
805 #if defined( __powerpc__ ) || defined( __ppc__ ) || defined( __ppc64__ )
806     if( !config_GetInt( p_libvlc, "altivec" ) )
807         libvlc_global.i_cpu &= ~CPU_CAPABILITY_ALTIVEC;
808 #endif
809
810 #define PRINT_CAPABILITY( capability, string )                              \
811     if( libvlc_global.i_cpu & capability )                                         \
812     {                                                                       \
813         strncat( p_capabilities, string " ",                                \
814                  sizeof(p_capabilities) - strlen(p_capabilities) );         \
815         p_capabilities[sizeof(p_capabilities) - 1] = '\0';                  \
816     }
817
818     p_capabilities[0] = '\0';
819     PRINT_CAPABILITY( CPU_CAPABILITY_486, "486" );
820     PRINT_CAPABILITY( CPU_CAPABILITY_586, "586" );
821     PRINT_CAPABILITY( CPU_CAPABILITY_PPRO, "Pentium Pro" );
822     PRINT_CAPABILITY( CPU_CAPABILITY_MMX, "MMX" );
823     PRINT_CAPABILITY( CPU_CAPABILITY_3DNOW, "3DNow!" );
824     PRINT_CAPABILITY( CPU_CAPABILITY_MMXEXT, "MMXEXT" );
825     PRINT_CAPABILITY( CPU_CAPABILITY_SSE, "SSE" );
826     PRINT_CAPABILITY( CPU_CAPABILITY_SSE2, "SSE2" );
827     PRINT_CAPABILITY( CPU_CAPABILITY_ALTIVEC, "AltiVec" );
828     PRINT_CAPABILITY( CPU_CAPABILITY_FPU, "FPU" );
829     msg_Dbg( p_libvlc, "CPU has capabilities %s", p_capabilities );
830
831     /*
832      * Choose the best memcpy module
833      */
834     p_libvlc->p_memcpy_module = module_Need( p_libvlc, "memcpy", "$memcpy", 0 );
835
836     if( p_libvlc->pf_memcpy == NULL )
837     {
838         p_libvlc->pf_memcpy = memcpy;
839     }
840
841     if( p_libvlc->pf_memset == NULL )
842     {
843         p_libvlc->pf_memset = memset;
844     }
845
846     p_libvlc->b_stats = config_GetInt( p_libvlc, "stats" );
847     p_libvlc->i_timers = 0;
848     p_libvlc->pp_timers = NULL;
849     vlc_mutex_init( p_libvlc, &p_libvlc->timer_lock );
850
851     /*
852      * Initialize hotkey handling
853      */
854     var_Create( p_libvlc, "key-pressed", VLC_VAR_INTEGER );
855     p_libvlc->p_hotkeys = malloc( libvlc_hotkeys_size );
856     /* Do a copy (we don't need to modify the strings) */
857     memcpy( p_libvlc->p_hotkeys, libvlc_hotkeys, libvlc_hotkeys_size );
858
859     /* Initialize playlist and get commandline files */
860     playlist_ThreadCreate( p_libvlc );
861     if( !p_libvlc->p_playlist )
862     {
863         msg_Err( p_libvlc, "playlist initialization failed" );
864         if( p_libvlc->p_memcpy_module != NULL )
865         {
866             module_Unneed( p_libvlc, p_libvlc->p_memcpy_module );
867         }
868         module_EndBank( p_libvlc );
869         return VLC_EGENERIC;
870     }
871     p_playlist = p_libvlc->p_playlist;
872
873     psz_modules = config_GetPsz( p_playlist, "services-discovery" );
874     if( psz_modules && *psz_modules )
875     {
876         /* Add service discovery modules */
877         playlist_ServicesDiscoveryAdd( p_playlist, psz_modules );
878     }
879     if( psz_modules ) free( psz_modules );
880
881     /*
882      * Load background interfaces
883      */
884     psz_modules = config_GetPsz( p_libvlc, "extraintf" );
885     psz_control = config_GetPsz( p_libvlc, "control" );
886
887     if( psz_modules && *psz_modules && psz_control && *psz_control )
888     {
889         psz_modules = (char *)realloc( psz_modules, strlen( psz_modules ) +
890                                                     strlen( psz_control ) + 1 );
891         sprintf( psz_modules, "%s:%s", psz_modules, psz_control );
892     }
893     else if( psz_control && *psz_control )
894     {
895         if( psz_modules ) free( psz_modules );
896         psz_modules = strdup( psz_control );
897     }
898
899     psz_parser = psz_modules;
900     while ( psz_parser && *psz_parser )
901     {
902         char *psz_module, *psz_temp;
903         psz_module = psz_parser;
904         psz_parser = strchr( psz_module, ':' );
905         if ( psz_parser )
906         {
907             *psz_parser = '\0';
908             psz_parser++;
909         }
910         psz_temp = (char *)malloc( strlen(psz_module) + sizeof(",none") );
911         if( psz_temp )
912         {
913             sprintf( psz_temp, "%s,none", psz_module );
914             VLC_AddIntf( 0, psz_temp, VLC_FALSE, VLC_FALSE );
915             free( psz_temp );
916         }
917     }
918     if ( psz_modules )
919     {
920         free( psz_modules );
921     }
922
923     /*
924      * Always load the hotkeys interface if it exists
925      */
926     VLC_AddIntf( 0, "hotkeys,none", VLC_FALSE, VLC_FALSE );
927
928     /*
929      * If needed, load the Xscreensaver interface
930      * Currently, only for X
931      */
932 #ifdef HAVE_X11_XLIB_H
933     if( config_GetInt( p_libvlc, "disable-screensaver" ) == 1 )
934     {
935         VLC_AddIntf( 0, "screensaver,none", VLC_FALSE, VLC_FALSE );
936     }
937 #endif
938
939     if( config_GetInt( p_libvlc, "file-logging" ) == 1 )
940     {
941         VLC_AddIntf( 0, "logger,none", VLC_FALSE, VLC_FALSE );
942     }
943 #ifdef HAVE_SYSLOG_H
944     if( config_GetInt( p_libvlc, "syslog" ) == 1 )
945     {
946         const char *psz_logmode = "logmode=syslog";
947         libvlc_InternalAddIntf( 0, "logger,none", VLC_FALSE, VLC_FALSE,
948                                 1, &psz_logmode );
949     }
950 #endif
951
952     if( config_GetInt( p_libvlc, "show-intf" ) == 1 )
953     {
954         VLC_AddIntf( 0, "showintf,none", VLC_FALSE, VLC_FALSE );
955     }
956
957     if( config_GetInt( p_libvlc, "network-synchronisation") == 1 )
958     {
959         VLC_AddIntf( 0, "netsync,none", VLC_FALSE, VLC_FALSE );
960     }
961
962     /*
963      * FIXME: kludge to use a p_libvlc-local variable for the Mozilla plugin
964      */
965     var_Create( p_libvlc, "drawable", VLC_VAR_INTEGER );
966     var_Create( p_libvlc, "drawable-view-top", VLC_VAR_INTEGER );
967     var_Create( p_libvlc, "drawable-view-left", VLC_VAR_INTEGER );
968     var_Create( p_libvlc, "drawable-view-bottom", VLC_VAR_INTEGER );
969     var_Create( p_libvlc, "drawable-view-right", VLC_VAR_INTEGER );
970     var_Create( p_libvlc, "drawable-clip-top", VLC_VAR_INTEGER );
971     var_Create( p_libvlc, "drawable-clip-left", VLC_VAR_INTEGER );
972     var_Create( p_libvlc, "drawable-clip-bottom", VLC_VAR_INTEGER );
973     var_Create( p_libvlc, "drawable-clip-right", VLC_VAR_INTEGER );
974
975     /* Create volume callback system. */
976     var_Create( p_libvlc, "volume-change", VLC_VAR_BOOL );
977
978     /*
979      * Get input filenames given as commandline arguments
980      */
981     GetFilenames( p_libvlc, i_argc, ppsz_argv );
982
983     /*
984      * Get --open argument
985      */
986     var_Create( p_libvlc, "open", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
987     var_Get( p_libvlc, "open", &val );
988     if ( val.psz_string != NULL && *val.psz_string )
989     {
990         VLC_AddTarget( p_libvlc->i_object_id, val.psz_string, NULL, 0,
991                        PLAYLIST_INSERT, 0 );
992     }
993     if ( val.psz_string != NULL ) free( val.psz_string );
994
995     return VLC_SUCCESS;
996 }
997
998 /**
999  * Cleanup a libvlc instance. The instance is not completely deallocated
1000  * \param p_libvlc the instance to clean
1001  */
1002 int libvlc_InternalCleanup( libvlc_int_t *p_libvlc )
1003 {
1004     intf_thread_t      * p_intf;
1005     vout_thread_t      * p_vout;
1006     aout_instance_t    * p_aout;
1007     announce_handler_t * p_announce;
1008
1009     /* Ask the interfaces to stop and destroy them */
1010     msg_Dbg( p_libvlc, "removing all interfaces" );
1011     while( (p_intf = vlc_object_find( p_libvlc, VLC_OBJECT_INTF, FIND_CHILD )) )
1012     {
1013         intf_StopThread( p_intf );
1014         vlc_object_detach( p_intf );
1015         vlc_object_release( p_intf );
1016         intf_Destroy( p_intf );
1017     }
1018
1019     /* Free playlist */
1020     msg_Dbg( p_libvlc, "removing playlist" );
1021     playlist_ThreadDestroy( p_libvlc->p_playlist );
1022
1023     /* Free video outputs */
1024     msg_Dbg( p_libvlc, "removing all video outputs" );
1025     while( (p_vout = vlc_object_find( p_libvlc, VLC_OBJECT_VOUT, FIND_CHILD )) )
1026     {
1027         vlc_object_detach( p_vout );
1028         vlc_object_release( p_vout );
1029         vout_Destroy( p_vout );
1030     }
1031
1032     /* Free audio outputs */
1033     msg_Dbg( p_libvlc, "removing all audio outputs" );
1034     while( (p_aout = vlc_object_find( p_libvlc, VLC_OBJECT_AOUT, FIND_CHILD )) )
1035     {
1036         vlc_object_detach( (vlc_object_t *)p_aout );
1037         vlc_object_release( (vlc_object_t *)p_aout );
1038         aout_Delete( p_aout );
1039     }
1040
1041     stats_TimersDumpAll( p_libvlc );
1042     stats_TimersClean( p_libvlc );
1043
1044     /* Free announce handler(s?) */
1045     while( (p_announce = vlc_object_find( p_libvlc, VLC_OBJECT_ANNOUNCE,
1046                                                  FIND_CHILD ) ) )
1047     {
1048         msg_Dbg( p_libvlc, "removing announce handler" );
1049         vlc_object_detach( p_announce );
1050         vlc_object_release( p_announce );
1051         announce_HandlerDestroy( p_announce );
1052     }
1053     return VLC_SUCCESS;
1054 }
1055
1056 /**
1057  * Destroy everything.
1058  * This function requests the running threads to finish, waits for their
1059  * termination, and destroys their structure.
1060  * It stops the thread systems: no instance can run after this has run
1061  * \param p_libvlc the instance to destroy
1062  * \param b_release whether we should do a release on the instance
1063  */
1064 int libvlc_InternalDestroy( libvlc_int_t *p_libvlc, vlc_bool_t b_release )
1065 {
1066     vlc_value_t lockval;
1067
1068     if( p_libvlc->p_memcpy_module )
1069     {
1070         module_Unneed( p_libvlc, p_libvlc->p_memcpy_module );
1071         p_libvlc->p_memcpy_module = NULL;
1072     }
1073
1074     /* Free module bank. It is refcounted, so we call this each time  */
1075     module_EndBank( p_libvlc );
1076
1077     FREENULL( p_libvlc->psz_homedir );
1078     FREENULL( p_libvlc->psz_userdir );
1079     FREENULL( p_libvlc->psz_configfile );
1080     FREENULL( p_libvlc->p_hotkeys );
1081
1082     var_Create( p_libvlc_global, "libvlc", VLC_VAR_MUTEX );
1083     var_Get( p_libvlc_global, "libvlc", &lockval );
1084     vlc_mutex_lock( lockval.p_address );
1085     i_instances--;
1086
1087     if( i_instances == 0 )
1088     {
1089         /* System specific cleaning code */
1090         system_End( p_libvlc );
1091
1092        /* Destroy global iconv */
1093         LocaleDeinit();
1094     }
1095     vlc_mutex_unlock( lockval.p_address );
1096     var_Destroy( p_libvlc_global, "libvlc" );
1097
1098     msg_Flush( p_libvlc );
1099     msg_Destroy( p_libvlc );
1100
1101     /* Destroy mutexes */
1102     vlc_mutex_destroy( &p_libvlc->config_lock );
1103     vlc_mutex_destroy( &p_libvlc->timer_lock );
1104
1105     if( b_release ) vlc_object_release( p_libvlc );
1106     vlc_object_destroy( p_libvlc );
1107
1108     /* Stop thread system: last one out please shut the door!
1109      * The number of initializations of the thread system is counted, we 
1110      * can call this each time */
1111     vlc_threads_end( p_libvlc_global );
1112
1113     return VLC_SUCCESS;
1114 }
1115
1116 /**
1117  * Add an interface plugin and run it
1118  */
1119 int libvlc_InternalAddIntf( libvlc_int_t *p_libvlc,
1120                             char const *psz_module,
1121                             vlc_bool_t b_block, vlc_bool_t b_play,
1122                             int i_options, const char *const *ppsz_options )
1123 {
1124     int i_err;
1125     intf_thread_t *p_intf;
1126
1127 #ifndef WIN32
1128     if( p_libvlc->p_libvlc_global->b_daemon && b_block && !psz_module )
1129     {
1130         /* Daemon mode hack.
1131          * We prefer the dummy interface if none is specified. */
1132         char *psz_interface = config_GetPsz( p_libvlc, "intf" );
1133         if( !psz_interface || !*psz_interface ) psz_module = "dummy";
1134         if( psz_interface ) free( psz_interface );
1135     }
1136 #endif
1137
1138     /* Try to create the interface */
1139     p_intf = intf_Create( p_libvlc, psz_module ? psz_module : "$intf",
1140                           i_options, ppsz_options );
1141
1142     if( p_intf == NULL )
1143     {
1144         msg_Err( p_libvlc, "interface \"%s\" initialization failed",
1145                  psz_module );
1146         return VLC_EGENERIC;
1147     }
1148
1149     /* Interface doesn't handle play on start so do it ourselves */
1150     if( !p_intf->b_play && b_play )
1151         playlist_Play( p_libvlc->p_playlist );
1152
1153     /* Try to run the interface */
1154     p_intf->b_play = b_play;
1155     p_intf->b_block = b_block;
1156     i_err = intf_RunThread( p_intf );
1157     if( i_err )
1158     {
1159         vlc_object_detach( p_intf );
1160         intf_Destroy( p_intf );
1161         return i_err;
1162     }
1163     return VLC_SUCCESS;
1164 };
1165
1166
1167 /*****************************************************************************
1168  * SetLanguage: set the interface language.
1169  *****************************************************************************
1170  * We set the LC_MESSAGES locale category for interface messages and buttons,
1171  * as well as the LC_CTYPE category for string sorting and possible wide
1172  * character support.
1173  *****************************************************************************/
1174 static void SetLanguage ( char const *psz_lang )
1175 {
1176 #if defined( ENABLE_NLS ) \
1177      && ( defined( HAVE_GETTEXT ) || defined( HAVE_INCLUDED_GETTEXT ) )
1178
1179     const char *          psz_path;
1180 #if defined( __APPLE__ ) || defined ( WIN32 ) || defined( SYS_BEOS )
1181     char            psz_tmp[1024];
1182 #endif
1183
1184     if( psz_lang && !*psz_lang )
1185     {
1186 #   if defined( HAVE_LC_MESSAGES )
1187         setlocale( LC_MESSAGES, psz_lang );
1188 #   endif
1189         setlocale( LC_CTYPE, psz_lang );
1190     }
1191     else if( psz_lang )
1192     {
1193 #ifdef __APPLE__
1194         /* I need that under Darwin, please check it doesn't disturb
1195          * other platforms. --Meuuh */
1196         setenv( "LANG", psz_lang, 1 );
1197
1198 #elif defined( SYS_BEOS ) || defined( WIN32 )
1199         /* We set LC_ALL manually because it is the only way to set
1200          * the language at runtime under eg. Windows. Beware that this
1201          * makes the environment unconsistent when libvlc is unloaded and
1202          * should probably be moved to a safer place like vlc.c. */
1203         static char psz_lcall[20];
1204         snprintf( psz_lcall, 19, "LC_ALL=%s", psz_lang );
1205         psz_lcall[19] = '\0';
1206         putenv( psz_lcall );
1207 #endif
1208
1209         setlocale( LC_ALL, psz_lang );
1210     }
1211
1212     /* Specify where to find the locales for current domain */
1213 #if !defined( __APPLE__ ) && !defined( WIN32 ) && !defined( SYS_BEOS )
1214     psz_path = LOCALEDIR;
1215 #else
1216     snprintf( psz_tmp, sizeof(psz_tmp), "%s/%s", libvlc_global.psz_vlcpath,
1217               "locale" );
1218     psz_path = psz_tmp;
1219 #endif
1220     if( !bindtextdomain( PACKAGE_NAME, psz_path ) )
1221     {
1222         fprintf( stderr, "warning: couldn't bind domain %s in directory %s\n",
1223                  PACKAGE_NAME, psz_path );
1224     }
1225
1226     /* Set the default domain */
1227     bind_textdomain_codeset( PACKAGE_NAME, "UTF-8" );
1228 #endif
1229 }
1230
1231 /*****************************************************************************
1232  * GetFilenames: parse command line options which are not flags
1233  *****************************************************************************
1234  * Parse command line for input files as well as their associated options.
1235  * An option always follows its associated input and begins with a ":".
1236  *****************************************************************************/
1237 static int GetFilenames( libvlc_int_t *p_vlc, int i_argc, char *ppsz_argv[] )
1238 {
1239     int i_opt, i_options;
1240
1241     /* We assume that the remaining parameters are filenames
1242      * and their input options */
1243     for( i_opt = i_argc - 1; i_opt >= optind; i_opt-- )
1244     {
1245         const char *psz_target;
1246         i_options = 0;
1247
1248         /* Count the input options */
1249         while( *ppsz_argv[ i_opt ] == ':' && i_opt > optind )
1250         {
1251             i_options++;
1252             i_opt--;
1253         }
1254
1255         /* TODO: write an internal function of this one, to avoid
1256          *       unnecessary lookups. */
1257         /* FIXME: should we convert options to UTF-8 as well ?? */
1258
1259 #ifdef WIN32
1260         if( GetVersion() < 0x80000000 )
1261         {
1262             VLC_AddTarget( p_vlc->i_object_id, ppsz_argv[i_opt],
1263                        (char const **)( i_options ? &ppsz_argv[i_opt + 1] :
1264                                         NULL ), i_options,
1265                        PLAYLIST_INSERT, 0 );
1266         }
1267         else
1268 #endif
1269         {
1270             psz_target = FromLocale( ppsz_argv[ i_opt ] );
1271             VLC_AddTarget( p_vlc->i_object_id, psz_target,
1272                        (char const **)( i_options ? &ppsz_argv[i_opt + 1] :
1273                                         NULL ), i_options,
1274                        PLAYLIST_INSERT, 0 );
1275             LocaleFree( psz_target );
1276         }
1277     }
1278
1279     return VLC_SUCCESS;
1280 }
1281
1282 /*****************************************************************************
1283  * Help: print program help
1284  *****************************************************************************
1285  * Print a short inline help. Message interface is initialized at this stage.
1286  *****************************************************************************/
1287 static void Help( libvlc_int_t *p_this, char const *psz_help_name )
1288 {
1289 #ifdef WIN32
1290     ShowConsole( VLC_TRUE );
1291 #endif
1292
1293     if( psz_help_name && !strcmp( psz_help_name, "help" ) )
1294     {
1295         utf8_fprintf( stdout, vlc_usage, p_this->psz_object_name );
1296         Usage( p_this, "help" );
1297         Usage( p_this, "main" );
1298     }
1299     else if( psz_help_name && !strcmp( psz_help_name, "longhelp" ) )
1300     {
1301         utf8_fprintf( stdout, vlc_usage, p_this->psz_object_name );
1302         Usage( p_this, NULL );
1303     }
1304     else if( psz_help_name )
1305     {
1306         Usage( p_this, psz_help_name );
1307     }
1308
1309 #ifdef WIN32        /* Pause the console because it's destroyed when we exit */
1310     PauseConsole();
1311 #endif
1312 }
1313
1314 /*****************************************************************************
1315  * Usage: print module usage
1316  *****************************************************************************
1317  * Print a short inline help. Message interface is initialized at this stage.
1318  *****************************************************************************/
1319 static void Usage( libvlc_int_t *p_this, char const *psz_module_name )
1320 {
1321 #define FORMAT_STRING "  %s --%s%s%s%s%s%s%s "
1322     /* short option ------'    | | | | | | |
1323      * option name ------------' | | | | | |
1324      * <bra ---------------------' | | | | |
1325      * option type or "" ----------' | | | |
1326      * ket> -------------------------' | | |
1327      * padding spaces -----------------' | |
1328      * comment --------------------------' |
1329      * comment suffix ---------------------'
1330      *
1331      * The purpose of having bra and ket is that we might i18n them as well.
1332      */
1333 #define LINE_START 8
1334 #define PADDING_SPACES 25
1335 #ifdef WIN32
1336 #   define OPTION_VALUE_SEP "="
1337 #else
1338 #   define OPTION_VALUE_SEP " "
1339 #endif
1340     vlc_list_t *p_list;
1341     char psz_spaces_text[PADDING_SPACES+LINE_START+1];
1342     char psz_spaces_longtext[LINE_START+3];
1343     char psz_format[sizeof(FORMAT_STRING)];
1344     char psz_buffer[10000];
1345     char psz_short[4];
1346     int i_index;
1347     int i_width = ConsoleWidth() - (PADDING_SPACES+LINE_START+1);
1348     vlc_bool_t b_advanced = config_GetInt( p_this, "advanced" );
1349     vlc_bool_t b_description;
1350
1351     memset( psz_spaces_text, ' ', PADDING_SPACES+LINE_START );
1352     psz_spaces_text[PADDING_SPACES+LINE_START] = '\0';
1353     memset( psz_spaces_longtext, ' ', LINE_START+2 );
1354     psz_spaces_longtext[LINE_START+2] = '\0';
1355
1356     strcpy( psz_format, FORMAT_STRING );
1357
1358     /* List all modules */
1359     p_list = vlc_list_find( p_this, VLC_OBJECT_MODULE, FIND_ANYWHERE );
1360
1361     /* Enumerate the config for each module */
1362     for( i_index = 0; i_index < p_list->i_count; i_index++ )
1363     {
1364         vlc_bool_t b_help_module;
1365         module_t *p_parser = (module_t *)p_list->p_values[i_index].p_object;
1366         module_config_t *p_item,
1367                         *p_end = p_parser->p_config + p_parser->confsize;
1368
1369         if( psz_module_name && strcmp( psz_module_name,
1370                                        p_parser->psz_object_name ) )
1371         {
1372             continue;
1373         }
1374
1375         /* Ignore modules without config options */
1376         if( !p_parser->i_config_items )
1377         {
1378             continue;
1379         }
1380
1381         /* Ignore modules with only advanced config options if requested */
1382         if( !b_advanced )
1383         {
1384             for( p_item = p_parser->p_config;
1385                  p_item < p_end;
1386                  p_item++ )
1387             {
1388                 if( (p_item->i_type & CONFIG_ITEM) &&
1389                     !p_item->b_advanced ) break;
1390             }
1391         }
1392
1393         /* Print name of module */
1394         if( strcmp( "main", p_parser->psz_object_name ) )
1395         utf8_fprintf( stdout, "\n %s\n", p_parser->psz_longname );
1396
1397         b_help_module = !strcmp( "help", p_parser->psz_object_name );
1398
1399         /* Print module options */
1400         for( p_item = p_parser->p_config;
1401              p_item < p_end;
1402              p_item++ )
1403         {
1404             char *psz_text, *psz_spaces = psz_spaces_text;
1405             const char *psz_bra = NULL, *psz_type = NULL, *psz_ket = NULL;
1406             const char *psz_suf = "", *psz_prefix = NULL;
1407             signed int i;
1408
1409             /* Skip deprecated options */
1410             if( p_item->psz_current )
1411             {
1412                 continue;
1413             }
1414             /* Skip advanced options if requested */
1415             if( p_item->b_advanced && !b_advanced )
1416             {
1417                 continue;
1418             }
1419
1420             switch( p_item->i_type )
1421             {
1422             case CONFIG_HINT_CATEGORY:
1423             case CONFIG_HINT_USAGE:
1424                 if( !strcmp( "main", p_parser->psz_object_name ) )
1425                 utf8_fprintf( stdout, "\n %s\n", p_item->psz_text );
1426                 break;
1427
1428             case CONFIG_ITEM_STRING:
1429             case CONFIG_ITEM_FILE:
1430             case CONFIG_ITEM_DIRECTORY:
1431             case CONFIG_ITEM_MODULE: /* We could also have "=<" here */
1432             case CONFIG_ITEM_MODULE_CAT:
1433             case CONFIG_ITEM_MODULE_LIST:
1434             case CONFIG_ITEM_MODULE_LIST_CAT:
1435                 psz_bra = OPTION_VALUE_SEP "<";
1436                 psz_type = _("string");
1437                 psz_ket = ">";
1438
1439                 if( p_item->ppsz_list )
1440                 {
1441                     psz_bra = OPTION_VALUE_SEP "{";
1442                     psz_type = psz_buffer;
1443                     psz_buffer[0] = '\0';
1444                     for( i = 0; p_item->ppsz_list[i]; i++ )
1445                     {
1446                         if( i ) strcat( psz_buffer, "," );
1447                         strcat( psz_buffer, p_item->ppsz_list[i] );
1448                     }
1449                     psz_ket = "}";
1450                 }
1451                 break;
1452             case CONFIG_ITEM_INTEGER:
1453             case CONFIG_ITEM_KEY: /* FIXME: do something a bit more clever */
1454                 psz_bra = OPTION_VALUE_SEP "<";
1455                 psz_type = _("integer");
1456                 psz_ket = ">";
1457
1458                 if( p_item->i_list )
1459                 {
1460                     psz_bra = OPTION_VALUE_SEP "{";
1461                     psz_type = psz_buffer;
1462                     psz_buffer[0] = '\0';
1463                     for( i = 0; p_item->ppsz_list_text[i]; i++ )
1464                     {
1465                         if( i ) strcat( psz_buffer, ", " );
1466                         sprintf( psz_buffer + strlen(psz_buffer), "%i (%s)",
1467                                  p_item->pi_list[i],
1468                                  p_item->ppsz_list_text[i] );
1469                     }
1470                     psz_ket = "}";
1471                 }
1472                 break;
1473             case CONFIG_ITEM_FLOAT:
1474                 psz_bra = OPTION_VALUE_SEP "<";
1475                 psz_type = _("float");
1476                 psz_ket = ">";
1477                 break;
1478             case CONFIG_ITEM_BOOL:
1479                 psz_bra = ""; psz_type = ""; psz_ket = "";
1480                 if( !b_help_module )
1481                 {
1482                     psz_suf = p_item->value.i ? _(" (default enabled)") :
1483                                                 _(" (default disabled)");
1484                 }
1485                 break;
1486             }
1487
1488             if( !psz_type )
1489             {
1490                 continue;
1491             }
1492
1493             /* Add short option if any */
1494             if( p_item->i_short )
1495             {
1496                 sprintf( psz_short, "-%c,", p_item->i_short );
1497             }
1498             else
1499             {
1500                 strcpy( psz_short, "   " );
1501             }
1502
1503             i = PADDING_SPACES - strlen( p_item->psz_name )
1504                  - strlen( psz_bra ) - strlen( psz_type )
1505                  - strlen( psz_ket ) - 1;
1506
1507             if( p_item->i_type == CONFIG_ITEM_BOOL && !b_help_module )
1508             {
1509                 psz_prefix =  ", --no-";
1510                 i -= strlen( p_item->psz_name ) + strlen( psz_prefix );
1511             }
1512
1513             if( i < 0 )
1514             {
1515                 psz_spaces[0] = '\n';
1516                 i = 0;
1517             }
1518             else
1519             {
1520                 psz_spaces[i] = '\0';
1521             }
1522
1523             if( p_item->i_type == CONFIG_ITEM_BOOL && !b_help_module )
1524             {
1525                 utf8_fprintf( stdout, psz_format, psz_short, p_item->psz_name,
1526                          psz_prefix, p_item->psz_name, psz_bra, psz_type,
1527                          psz_ket, psz_spaces );
1528             }
1529             else
1530             {
1531                 utf8_fprintf( stdout, psz_format, psz_short, p_item->psz_name,
1532                          "", "", psz_bra, psz_type, psz_ket, psz_spaces );
1533             }
1534
1535             psz_spaces[i] = ' ';
1536
1537             /* We wrap the rest of the output */
1538             sprintf( psz_buffer, "%s%s", p_item->psz_text, psz_suf );
1539             b_description = config_GetInt( p_this, "help-verbose" );
1540
1541  description:
1542             psz_text = psz_buffer;
1543             while( *psz_text )
1544             {
1545                 char *psz_parser, *psz_word;
1546                 size_t i_end = strlen( psz_text );
1547
1548                 /* If the remaining text fits in a line, print it. */
1549                 if( i_end <= (size_t)i_width )
1550                 {
1551                     utf8_fprintf( stdout, "%s\n", psz_text );
1552                     break;
1553                 }
1554
1555                 /* Otherwise, eat as many words as possible */
1556                 psz_parser = psz_text;
1557                 do
1558                 {
1559                     psz_word = psz_parser;
1560                     psz_parser = strchr( psz_word, ' ' );
1561                     /* If no space was found, we reached the end of the text
1562                      * block; otherwise, we skip the space we just found. */
1563                     psz_parser = psz_parser ? psz_parser + 1
1564                                             : psz_text + i_end;
1565
1566                 } while( psz_parser - psz_text <= i_width );
1567
1568                 /* We cut a word in one of these cases:
1569                  *  - it's the only word in the line and it's too long.
1570                  *  - we used less than 80% of the width and the word we are
1571                  *    going to wrap is longer than 40% of the width, and even
1572                  *    if the word would have fit in the next line. */
1573                 if( psz_word == psz_text
1574                      || ( psz_word - psz_text < 80 * i_width / 100
1575                            && psz_parser - psz_word > 40 * i_width / 100 ) )
1576                 {
1577                     char c = psz_text[i_width];
1578                     psz_text[i_width] = '\0';
1579                     utf8_fprintf( stdout, "%s\n%s", psz_text, psz_spaces );
1580                     psz_text += i_width;
1581                     psz_text[0] = c;
1582                 }
1583                 else
1584                 {
1585                     psz_word[-1] = '\0';
1586                     utf8_fprintf( stdout, "%s\n%s", psz_text, psz_spaces );
1587                     psz_text = psz_word;
1588                 }
1589             }
1590
1591             if( b_description && p_item->psz_longtext )
1592             {
1593                 sprintf( psz_buffer, "%s%s", p_item->psz_longtext, psz_suf );
1594                 b_description = VLC_FALSE;
1595                 psz_spaces = psz_spaces_longtext;
1596                 utf8_fprintf( stdout, "%s", psz_spaces );
1597                 goto description;
1598             }
1599         }
1600     }
1601
1602     /* Release the module list */
1603     vlc_list_release( p_list );
1604 }
1605
1606 /*****************************************************************************
1607  * ListModules: list the available modules with their description
1608  *****************************************************************************
1609  * Print a list of all available modules (builtins and plugins) and a short
1610  * description for each one.
1611  *****************************************************************************/
1612 static void ListModules( libvlc_int_t *p_this )
1613 {
1614     vlc_list_t *p_list;
1615     module_t *p_parser;
1616     char psz_spaces[22];
1617     int i_index;
1618
1619     memset( psz_spaces, ' ', 22 );
1620
1621 #ifdef WIN32
1622     ShowConsole( VLC_TRUE );
1623 #endif
1624
1625     /* List all modules */
1626     p_list = vlc_list_find( p_this, VLC_OBJECT_MODULE, FIND_ANYWHERE );
1627
1628     /* Enumerate each module */
1629     for( i_index = 0; i_index < p_list->i_count; i_index++ )
1630     {
1631         int i;
1632
1633         p_parser = (module_t *)p_list->p_values[i_index].p_object ;
1634
1635         /* Nasty hack, but right now I'm too tired to think about a nice
1636          * solution */
1637         i = 22 - strlen( p_parser->psz_object_name ) - 1;
1638         if( i < 0 ) i = 0;
1639         psz_spaces[i] = 0;
1640
1641         utf8_fprintf( stdout, "  %s%s %s\n", p_parser->psz_object_name,
1642                          psz_spaces, p_parser->psz_longname );
1643
1644         psz_spaces[i] = ' ';
1645     }
1646
1647     vlc_list_release( p_list );
1648
1649 #ifdef WIN32        /* Pause the console because it's destroyed when we exit */
1650     PauseConsole();
1651 #endif
1652 }
1653
1654 /*****************************************************************************
1655  * Version: print complete program version
1656  *****************************************************************************
1657  * Print complete program version and build number.
1658  *****************************************************************************/
1659 static void Version( void )
1660 {
1661 #ifdef WIN32
1662     ShowConsole( VLC_TRUE );
1663 #endif
1664
1665     utf8_fprintf( stdout, _("VLC version %s\n"), VLC_Version() );
1666     utf8_fprintf( stdout, _("Compiled by %s@%s.%s\n"),
1667              VLC_CompileBy(), VLC_CompileHost(), VLC_CompileDomain() );
1668     utf8_fprintf( stdout, _("Compiler: %s\n"), VLC_Compiler() );
1669 #ifndef HAVE_SHARED_LIBVLC
1670     if( strcmp( VLC_Changeset(), "exported" ) )
1671         utf8_fprintf( stdout, _("Based upon svn changeset [%s]\n"),
1672                  VLC_Changeset() );
1673 #endif
1674     utf8_fprintf( stdout, LICENSE_MSG );
1675
1676 #ifdef WIN32        /* Pause the console because it's destroyed when we exit */
1677     PauseConsole();
1678 #endif
1679 }
1680
1681 /*****************************************************************************
1682  * ShowConsole: On Win32, create an output console for debug messages
1683  *****************************************************************************
1684  * This function is useful only on Win32.
1685  *****************************************************************************/
1686 #ifdef WIN32 /*  */
1687 static void ShowConsole( vlc_bool_t b_dofile )
1688 {
1689 #   ifndef UNDER_CE
1690     FILE *f_help;
1691
1692     if( getenv( "PWD" ) && getenv( "PS1" ) ) return; /* cygwin shell */
1693
1694     AllocConsole();
1695
1696     freopen( "CONOUT$", "w", stderr );
1697     freopen( "CONIN$", "r", stdin );
1698
1699     if( b_dofile && (f_help = fopen( "vlc-help.txt", "wt" )) )
1700     {
1701         fclose( f_help );
1702         freopen( "vlc-help.txt", "wt", stdout );
1703         utf8_fprintf( stderr, _("\nDumped content to vlc-help.txt file.\n") );
1704     }
1705
1706     else freopen( "CONOUT$", "w", stdout );
1707
1708 #   endif
1709 }
1710 #endif
1711
1712 /*****************************************************************************
1713  * PauseConsole: On Win32, wait for a key press before closing the console
1714  *****************************************************************************
1715  * This function is useful only on Win32.
1716  *****************************************************************************/
1717 #ifdef WIN32 /*  */
1718 static void PauseConsole( void )
1719 {
1720 #   ifndef UNDER_CE
1721
1722     if( getenv( "PWD" ) && getenv( "PS1" ) ) return; /* cygwin shell */
1723
1724     utf8_fprintf( stderr, _("\nPress the RETURN key to continue...\n") );
1725     getchar();
1726     fclose( stdout );
1727
1728 #   endif
1729 }
1730 #endif
1731
1732 /*****************************************************************************
1733  * ConsoleWidth: Return the console width in characters
1734  *****************************************************************************
1735  * We use the stty shell command to get the console width; if this fails or
1736  * if the width is less than 80, we default to 80.
1737  *****************************************************************************/
1738 static int ConsoleWidth( void )
1739 {
1740     int i_width = 80;
1741
1742 #ifndef WIN32
1743     char buf[20], *psz_parser;
1744     FILE *file;
1745     int i_ret;
1746
1747     file = popen( "stty size 2>/dev/null", "r" );
1748     if( file )
1749     {
1750         i_ret = fread( buf, 1, 20, file );
1751         if( i_ret > 0 )
1752         {
1753             buf[19] = '\0';
1754             psz_parser = strchr( buf, ' ' );
1755             if( psz_parser )
1756             {
1757                 i_ret = atoi( psz_parser + 1 );
1758                 if( i_ret >= 80 )
1759                 {
1760                     i_width = i_ret;
1761                 }
1762             }
1763         }
1764
1765         pclose( file );
1766     }
1767 #endif
1768
1769     return i_width;
1770 }
1771
1772 static int VerboseCallback( vlc_object_t *p_this, const char *psz_variable,
1773                      vlc_value_t old_val, vlc_value_t new_val, void *param)
1774 {
1775     libvlc_int_t *p_libvlc = (libvlc_int_t *)p_this;
1776
1777     if( new_val.i_int >= -1 )
1778     {
1779         p_libvlc->i_verbose = __MIN( new_val.i_int, 2 );
1780     }
1781     return VLC_SUCCESS;
1782 }
1783
1784 /*****************************************************************************
1785  * InitDeviceValues: initialize device values
1786  *****************************************************************************
1787  * This function inits the dvd, vcd and cd-audio values
1788  *****************************************************************************/
1789 static void InitDeviceValues( libvlc_int_t *p_vlc )
1790 {
1791 #ifdef HAVE_HAL
1792     LibHalContext * ctx;
1793     int i, i_devices;
1794     char **devices;
1795     char *block_dev;
1796     dbus_bool_t b_dvd;
1797     DBusConnection *p_connection;
1798     DBusError       error;
1799
1800 #ifdef HAVE_HAL_1
1801     ctx =  libhal_ctx_new();
1802     if( !ctx ) return;
1803     dbus_error_init( &error );
1804     p_connection = dbus_bus_get ( DBUS_BUS_SYSTEM, &error );
1805     if( dbus_error_is_set( &error ) )
1806     {
1807         dbus_error_free( &error );
1808         return;
1809     }
1810     libhal_ctx_set_dbus_connection( ctx, p_connection );
1811     if( libhal_ctx_init( ctx, &error ) )
1812 #else
1813     if( ( ctx = hal_initialize( NULL, FALSE ) ) )
1814 #endif
1815     {
1816 #ifdef HAVE_HAL_1
1817         if( ( devices = libhal_get_all_devices( ctx, &i_devices, NULL ) ) )
1818 #else
1819         if( ( devices = hal_get_all_devices( ctx, &i_devices ) ) )
1820 #endif
1821         {
1822             for( i = 0; i < i_devices; i++ )
1823             {
1824 #ifdef HAVE_HAL_1
1825                 if( !libhal_device_property_exists( ctx, devices[i],
1826                                                 "storage.cdrom.dvd", NULL ) )
1827 #else
1828                 if( !hal_device_property_exists( ctx, devices[ i ],
1829                                                 "storage.cdrom.dvd" ) )
1830 #endif
1831                 {
1832                     continue;
1833                 }
1834 #ifdef HAVE_HAL_1
1835                 b_dvd = libhal_device_get_property_bool( ctx, devices[ i ],
1836                                                  "storage.cdrom.dvd", NULL  );
1837                 block_dev = libhal_device_get_property_string( ctx,
1838                                 devices[ i ], "block.device" , NULL );
1839 #else
1840                 b_dvd = hal_device_get_property_bool( ctx, devices[ i ],
1841                                                       "storage.cdrom.dvd" );
1842                 block_dev = hal_device_get_property_string( ctx, devices[ i ],
1843                                                             "block.device" );
1844 #endif
1845                 if( b_dvd )
1846                 {
1847                     config_PutPsz( p_vlc, "dvd", block_dev );
1848                 }
1849
1850                 config_PutPsz( p_vlc, "vcd", block_dev );
1851                 config_PutPsz( p_vlc, "cd-audio", block_dev );
1852 #ifdef HAVE_HAL_1
1853                 libhal_free_string( block_dev );
1854 #else
1855                 hal_free_string( block_dev );
1856 #endif
1857             }
1858 #ifdef HAVE_HAL_1
1859             libhal_free_string_array( devices );
1860 #else
1861             hal_free_string_array( devices );
1862 #endif
1863         }
1864
1865 #ifdef HAVE_HAL_1
1866         libhal_ctx_shutdown( ctx, NULL );
1867         dbus_connection_unref( p_connection );
1868 #else
1869         hal_shutdown( ctx );
1870 #endif
1871     }
1872     else
1873     {
1874         msg_Warn( p_vlc, "Unable to get HAL device properties" );
1875     }
1876 #endif
1877 }