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