9ed877f967a56a7c381711e79336bea508a43e9a
[vlc.git] / src / libvlc.c
1 /*****************************************************************************
2  * libvlc.c: main libvlc source
3  *****************************************************************************
4  * Copyright (C) 1998-2002 VideoLAN
5  * $Id: libvlc.c,v 1.84 2003/05/08 15:58:44 gbazin Exp $
6  *
7  * Authors: Vincent Seguin <seguin@via.ecp.fr>
8  *          Samuel Hocevar <sam@zoy.org>
9  *          Gildas Bazin <gbazin@netcourrier.com>
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or
14  * (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
24  *****************************************************************************/
25
26 /*****************************************************************************
27  * Pretend we are a builtin module
28  *****************************************************************************/
29 #define MODULE_NAME main
30 #define MODULE_PATH main
31 #define __BUILTIN__
32
33 /*****************************************************************************
34  * Preamble
35  *****************************************************************************/
36 #include <vlc/vlc.h>
37
38 #ifdef HAVE_ERRNO_H
39 #   include <errno.h>                                              /* ENOMEM */
40 #endif
41 #include <stdio.h>                                              /* sprintf() */
42 #include <string.h>                                            /* strerror() */
43 #include <stdlib.h>                                                /* free() */
44
45 #ifndef WIN32
46 #   include <netinet/in.h>                            /* BSD: struct in_addr */
47 #endif
48
49 #ifdef HAVE_UNISTD_H
50 #   include <unistd.h>
51 #elif defined( WIN32 ) && !defined( UNDER_CE )
52 #   include <io.h>
53 #endif
54
55 #ifdef WIN32                       /* optind, getopt(), included in unistd.h */
56 #   include "extras/getopt.h"
57 #endif
58
59 #ifdef HAVE_LOCALE_H
60 #   include <locale.h>
61 #endif
62
63 #include "vlc_cpu.h"                                        /* CPU detection */
64 #include "os_specific.h"
65
66 #include "error.h"
67
68 #include "stream_control.h"
69 #include "input_ext-intf.h"
70
71 #include "vlc_playlist.h"
72 #include "interface.h"
73
74 #include "audio_output.h"
75
76 #include "video.h"
77 #include "video_output.h"
78
79 #include "libvlc.h"
80
81 /*****************************************************************************
82  * The evil global variable. We handle it with care, don't worry.
83  *****************************************************************************/
84 static libvlc_t libvlc;
85 static vlc_t *  p_static_vlc;
86
87 /*****************************************************************************
88  * Local prototypes
89  *****************************************************************************/
90 static void SetLanguage   ( char const * );
91 static int  GetFilenames  ( vlc_t *, int, char *[] );
92 static void Usage         ( vlc_t *, char const *psz_module_name );
93 static void ListModules   ( vlc_t * );
94 static void Version       ( void );
95
96 #ifdef WIN32
97 static void ShowConsole   ( void );
98 #endif
99 static int  ConsoleWidth  ( void );
100
101 /*****************************************************************************
102  * VLC_Version: return the libvlc version.
103  *****************************************************************************
104  * This function returns full version string (numeric version and codename).
105  *****************************************************************************/
106 char const * VLC_Version( void )
107 {
108     return VERSION_MESSAGE;
109 }
110
111 /*****************************************************************************
112  * VLC_Error: strerror() equivalent
113  *****************************************************************************
114  * This function returns full version string (numeric version and codename).
115  *****************************************************************************/
116 char const * VLC_Error( int i_err )
117 {
118     return vlc_error( i_err );
119 }
120
121 /*****************************************************************************
122  * VLC_Create: allocate a vlc_t structure, and initialize libvlc if needed.
123  *****************************************************************************
124  * This function allocates a vlc_t structure and returns a negative value
125  * in case of failure. Also, the thread system is initialized.
126  *****************************************************************************/
127 int VLC_Create( void )
128 {
129     int i_ret;
130     vlc_t * p_vlc = NULL;
131     vlc_value_t lockval;
132
133     /* vlc_threads_init *must* be the first internal call! No other call is
134      * allowed before the thread system has been initialized. */
135     i_ret = vlc_threads_init( &libvlc );
136     if( i_ret < 0 )
137     {
138         return i_ret;
139     }
140
141     /* Now that the thread system is initialized, we don't have much, but
142      * at least we have var_Create */
143     var_Create( &libvlc, "libvlc", VLC_VAR_MUTEX );
144     var_Get( &libvlc, "libvlc", &lockval );
145     vlc_mutex_lock( lockval.p_address );
146     if( !libvlc.b_ready )
147     {
148         char *psz_env;
149
150         /* Guess what CPU we have */
151         libvlc.i_cpu = CPUCapabilities();
152
153         /* Find verbosity from VLC_VERBOSE environment variable */
154         psz_env = getenv( "VLC_VERBOSE" );
155         libvlc.i_verbose = psz_env ? atoi( psz_env ) : -1;
156
157 #if defined( HAVE_ISATTY ) && !defined( WIN32 )
158         libvlc.b_color = isatty( 2 ); /* 2 is for stderr */
159 #else
160         libvlc.b_color = VLC_FALSE;
161 #endif
162
163         /* Initialize message queue */
164         msg_Create( &libvlc );
165
166         /* Announce who we are */
167         msg_Dbg( &libvlc, COPYRIGHT_MESSAGE );
168         msg_Dbg( &libvlc, "libvlc was configured with %s", CONFIGURE_LINE );
169
170         /* The module bank will be initialized later */
171         libvlc.p_module_bank = NULL;
172
173         libvlc.b_ready = VLC_TRUE;
174     }
175     vlc_mutex_unlock( lockval.p_address );
176     var_Destroy( &libvlc, "libvlc" );
177
178     /* Allocate a vlc object */
179     p_vlc = vlc_object_create( &libvlc, VLC_OBJECT_VLC );
180     if( p_vlc == NULL )
181     {
182         return VLC_EGENERIC;
183     }
184     vlc_thread_set_priority( p_vlc, VLC_THREAD_PRIORITY_LOW );
185
186     p_vlc->psz_object_name = "root";
187
188     /* Initialize mutexes */
189     vlc_mutex_init( p_vlc, &p_vlc->config_lock );
190
191     /* Store our newly allocated structure in the global list */
192     vlc_object_attach( p_vlc, &libvlc );
193
194     /* Store data for the non-reentrant API */
195     p_static_vlc = p_vlc;
196
197     return p_vlc->i_object_id;
198 }
199
200 /*****************************************************************************
201  * VLC_Init: initialize a vlc_t structure.
202  *****************************************************************************
203  * This function initializes a previously allocated vlc_t structure:
204  *  - CPU detection
205  *  - gettext initialization
206  *  - message queue, module bank and playlist initialization
207  *  - configuration and commandline parsing
208  *****************************************************************************/
209 int VLC_Init( int i_object, int i_argc, char *ppsz_argv[] )
210 {
211     char         p_capabilities[200];
212     char *       p_tmp;
213     char *       psz_modules;
214     char *       psz_parser;
215     char *       psz_translation;
216     vlc_bool_t   b_exit = VLC_FALSE;
217     vlc_t *      p_vlc;
218     module_t    *p_help_module;
219     playlist_t  *p_playlist;
220     vlc_value_t  lockval;
221
222     p_vlc = i_object ? vlc_object_get( &libvlc, i_object ) : p_static_vlc;
223
224     if( !p_vlc )
225     {
226         return VLC_ENOOBJ;
227     }
228
229     /*
230      * System specific initialization code
231      */
232     system_Init( p_vlc, &i_argc, ppsz_argv );
233
234     /* Get the executable name (similar to the basename command) */
235     if( i_argc > 0 )
236     {
237         p_vlc->psz_object_name = p_tmp = ppsz_argv[ 0 ];
238         while( *p_tmp )
239         {
240             if( *p_tmp == '/' ) p_vlc->psz_object_name = ++p_tmp;
241             else ++p_tmp;
242         }
243     }
244     else
245     {
246         p_vlc->psz_object_name = "vlc";
247     }
248
249     /*
250      * Support for gettext
251      */
252     SetLanguage( "" );
253
254     /* Translate "C" to the language code: "fr", "en_GB", "nl", "ru"... */
255     msg_Dbg( p_vlc, "translation test: code is \"%s\"", _("C") );
256
257     /* Initialize the module bank and load the configuration of the
258      * main module. We need to do this at this stage to be able to display
259      * a short help if required by the user. (short help == main module
260      * options) */
261     var_Create( &libvlc, "libvlc", VLC_VAR_MUTEX );
262     var_Get( &libvlc, "libvlc", &lockval );
263     vlc_mutex_lock( lockval.p_address );
264     if( libvlc.p_module_bank == NULL )
265     {
266         module_InitBank( &libvlc );
267         module_LoadMain( &libvlc );
268     }
269     vlc_mutex_unlock( lockval.p_address );
270     var_Destroy( &libvlc, "libvlc" );
271
272     /* Hack: insert the help module here */
273     p_help_module = vlc_object_create( p_vlc, VLC_OBJECT_MODULE );
274     if( p_help_module == NULL )
275     {
276         //module_EndBank( p_vlc );
277         if( i_object ) vlc_object_release( p_vlc );
278         return VLC_EGENERIC;
279     }
280     p_help_module->psz_object_name = "help";
281     config_Duplicate( p_help_module, p_help_config );
282     vlc_object_attach( p_help_module, libvlc.p_module_bank );
283     /* End hack */
284
285     if( config_LoadCmdLine( p_vlc, &i_argc, ppsz_argv, VLC_TRUE ) )
286     {
287         vlc_object_detach( p_help_module );
288         config_Free( p_help_module );
289         vlc_object_destroy( p_help_module );
290         //module_EndBank( p_vlc );
291         if( i_object ) vlc_object_release( p_vlc );
292         return VLC_EGENERIC;
293     }
294
295     /* Check for short help option */
296     if( config_GetInt( p_vlc, "help" ) )
297     {
298         fprintf( stdout, _("Usage: %s [options] [items]...\n\n"),
299                          p_vlc->psz_object_name );
300         Usage( p_vlc, "main" );
301         Usage( p_vlc, "help" );
302         b_exit = VLC_TRUE;
303     }
304     /* Check for version option */
305     else if( config_GetInt( p_vlc, "version" ) )
306     {
307         Version();
308         b_exit = VLC_TRUE;
309     }
310
311     /* Hack: remove the help module here */
312     vlc_object_detach( p_help_module );
313     /* End hack */
314
315     if( b_exit )
316     {
317         config_Free( p_help_module );
318         vlc_object_destroy( p_help_module );
319         //module_EndBank( p_vlc );
320         if( i_object ) vlc_object_release( p_vlc );
321         return VLC_EEXIT;
322     }
323
324     /* Check for translation config option */
325 #if defined( ENABLE_NLS ) \
326      && ( defined( HAVE_GETTEXT ) || defined( HAVE_INCLUDED_GETTEXT ) )
327
328     /* This ain't really nice to have to reload the config here but it seems
329      * the only way to do it. */
330     p_vlc->psz_homedir = config_GetHomeDir();
331     config_LoadConfigFile( p_vlc, "main" );
332     config_LoadCmdLine( p_vlc, &i_argc, ppsz_argv, VLC_TRUE );
333
334     psz_translation = config_GetPsz( p_vlc, "translation" );
335     if( psz_translation && *psz_translation )
336     {
337         /* Reset the default domain */
338         SetLanguage( psz_translation );
339
340         /* Translate "C" to the language code: "fr", "en_GB", "nl", "ru"... */
341         msg_Dbg( p_vlc, "translation test: code is \"%s\"", _("C") );
342
343         textdomain( PACKAGE );
344
345         module_EndBank( p_vlc );
346         module_InitBank( &libvlc );
347         module_LoadMain( &libvlc );
348         config_LoadCmdLine( p_vlc, &i_argc, ppsz_argv, VLC_TRUE );
349     }
350 #endif
351
352     /*
353      * Load the builtins and plugins into the module_bank.
354      * We have to do it before config_Load*() because this also gets the
355      * list of configuration options exported by each module and loads their
356      * default values.
357      */
358     module_LoadBuiltins( &libvlc );
359     module_LoadPlugins( &libvlc );
360     msg_Dbg( p_vlc, "module bank initialized, found %i modules",
361                     libvlc.p_module_bank->i_children );
362
363     /* Hack: insert the help module here */
364     vlc_object_attach( p_help_module, libvlc.p_module_bank );
365     /* End hack */
366
367     /* Check for help on modules */
368     if( (p_tmp = config_GetPsz( p_vlc, "module" )) )
369     {
370         Usage( p_vlc, p_tmp );
371         free( p_tmp );
372         b_exit = VLC_TRUE;
373     }
374     /* Check for long help option */
375     else if( config_GetInt( p_vlc, "longhelp" ) )
376     {
377         Usage( p_vlc, NULL );
378         b_exit = VLC_TRUE;
379     }
380     /* Check for module list option */
381     else if( config_GetInt( p_vlc, "list" ) )
382     {
383         ListModules( p_vlc );
384         b_exit = VLC_TRUE;
385     }
386
387     /* Hack: remove the help module here */
388     vlc_object_detach( p_help_module );
389     config_Free( p_help_module );
390     vlc_object_destroy( p_help_module );
391     /* End hack */
392
393     if( b_exit )
394     {
395         //module_EndBank( p_vlc );
396         if( i_object ) vlc_object_release( p_vlc );
397         return VLC_EEXIT;
398     }
399
400     /*
401      * Override default configuration with config file settings
402      */
403     p_vlc->psz_homedir = config_GetHomeDir();
404     config_LoadConfigFile( p_vlc, NULL );
405
406     /*
407      * Override configuration with command line settings
408      */
409     if( config_LoadCmdLine( p_vlc, &i_argc, ppsz_argv, VLC_FALSE ) )
410     {
411 #ifdef WIN32
412         ShowConsole();
413         /* Pause the console because it's destroyed when we exit */
414         fprintf( stderr, "The command line options couldn't be loaded, check "
415                  "that they are valid.\nPress the RETURN key to continue..." );
416         getchar();
417 #endif
418         //module_EndBank( p_vlc );
419         if( i_object ) vlc_object_release( p_vlc );
420         return VLC_EGENERIC;
421     }
422
423     /*
424      * System specific configuration
425      */
426     system_Configure( p_vlc );
427
428     /*
429      * Message queue options
430      */
431     if( config_GetInt( p_vlc, "quiet" ) )
432     {
433         libvlc.i_verbose = -1;
434     }
435     else
436     {
437         int i_tmp = config_GetInt( p_vlc, "verbose" );
438         if( i_tmp >= 0 )
439         {
440             libvlc.i_verbose = __MIN( i_tmp, 2 );
441         }
442     }
443     libvlc.b_color = libvlc.b_color && config_GetInt( p_vlc, "color" );
444
445     /*
446      * Output messages that may still be in the queue
447      */
448     msg_Flush( p_vlc );
449
450     /* p_vlc initialization. FIXME ? */
451     p_vlc->i_desync = config_GetInt( p_vlc, "desync" ) * (mtime_t)1000;
452
453 #if defined( __i386__ )
454     if( !config_GetInt( p_vlc, "mmx" ) )
455         libvlc.i_cpu &= ~CPU_CAPABILITY_MMX;
456     if( !config_GetInt( p_vlc, "3dn" ) )
457         libvlc.i_cpu &= ~CPU_CAPABILITY_3DNOW;
458     if( !config_GetInt( p_vlc, "mmxext" ) )
459         libvlc.i_cpu &= ~CPU_CAPABILITY_MMXEXT;
460     if( !config_GetInt( p_vlc, "sse" ) )
461         libvlc.i_cpu &= ~CPU_CAPABILITY_SSE;
462 #endif
463 #if defined( __powerpc__ ) || defined( SYS_DARWIN )
464     if( !config_GetInt( p_vlc, "altivec" ) )
465         libvlc.i_cpu &= ~CPU_CAPABILITY_ALTIVEC;
466 #endif
467
468 #define PRINT_CAPABILITY( capability, string )                              \
469     if( libvlc.i_cpu & capability )                                         \
470     {                                                                       \
471         strncat( p_capabilities, string " ",                                \
472                  sizeof(p_capabilities) - strlen(p_capabilities) );         \
473         p_capabilities[sizeof(p_capabilities) - 1] = '\0';                  \
474     }
475
476     p_capabilities[0] = '\0';
477     PRINT_CAPABILITY( CPU_CAPABILITY_486, "486" );
478     PRINT_CAPABILITY( CPU_CAPABILITY_586, "586" );
479     PRINT_CAPABILITY( CPU_CAPABILITY_PPRO, "Pentium Pro" );
480     PRINT_CAPABILITY( CPU_CAPABILITY_MMX, "MMX" );
481     PRINT_CAPABILITY( CPU_CAPABILITY_3DNOW, "3DNow!" );
482     PRINT_CAPABILITY( CPU_CAPABILITY_MMXEXT, "MMXEXT" );
483     PRINT_CAPABILITY( CPU_CAPABILITY_SSE, "SSE" );
484     PRINT_CAPABILITY( CPU_CAPABILITY_ALTIVEC, "AltiVec" );
485     PRINT_CAPABILITY( CPU_CAPABILITY_FPU, "FPU" );
486     msg_Dbg( p_vlc, "CPU has capabilities %s", p_capabilities );
487
488     /*
489      * Choose the best memcpy module
490      */
491     p_vlc->p_memcpy_module = module_Need( p_vlc, "memcpy", "$memcpy" );
492
493     if( p_vlc->pf_memcpy == NULL )
494     {
495         p_vlc->pf_memcpy = memcpy;
496     }
497
498     if( p_vlc->pf_memset == NULL )
499     {
500         p_vlc->pf_memset = memset;
501     }
502
503     /*
504      * Initialize playlist and get commandline files
505      */
506     p_playlist = playlist_Create( p_vlc );
507     if( !p_playlist )
508     {
509         msg_Err( p_vlc, "playlist initialization failed" );
510         if( p_vlc->p_memcpy_module != NULL )
511         {
512             module_Unneed( p_vlc, p_vlc->p_memcpy_module );
513         }
514         //module_EndBank( p_vlc );
515         if( i_object ) vlc_object_release( p_vlc );
516         return VLC_EGENERIC;
517     }
518
519     /*
520      * Load background interfaces
521      */
522     psz_modules = config_GetPsz( p_vlc, "extraintf" );
523     psz_parser = psz_modules;
524     while ( psz_parser && *psz_parser )
525     {
526         char *psz_module, *psz_temp;
527         psz_module = psz_parser;
528         psz_parser = strchr( psz_module, ',' );
529         if ( psz_parser )
530         {
531             *psz_parser = '\0';
532             psz_parser++;
533         }
534         psz_temp = (char *)malloc( strlen(psz_module) + sizeof(",none") );
535         if( psz_temp )
536         {
537             sprintf( psz_temp, "%s,none", psz_module );
538             VLC_AddIntf( 0, psz_temp, VLC_FALSE );
539             free( psz_temp );
540         }
541     }
542     if ( psz_modules )
543     {
544         free( psz_modules );
545     }
546
547     /*
548      * FIXME: kludge to use a p_vlc-local variable for the Mozilla plugin
549      */
550     var_Create( p_vlc, "drawable", VLC_VAR_INTEGER );
551
552     /*
553      * Get input filenames given as commandline arguments
554      */
555     GetFilenames( p_vlc, i_argc, ppsz_argv );
556
557     if( i_object ) vlc_object_release( p_vlc );
558     return VLC_SUCCESS;
559 }
560
561 /*****************************************************************************
562  * VLC_AddIntf: add an interface
563  *****************************************************************************
564  * This function opens an interface plugin and runs it. If b_block is set
565  * to 0, VLC_AddIntf will return immediately and let the interface run in a
566  * separate thread. If b_block is set to 1, VLC_AddIntf will continue until
567  * user requests to quit.
568  *****************************************************************************/
569 int VLC_AddIntf( int i_object, char const *psz_module, vlc_bool_t b_block )
570 {
571     int i_err;
572     intf_thread_t *p_intf;
573     vlc_t *p_vlc;
574
575     p_vlc = i_object ? vlc_object_get( &libvlc, i_object ) : p_static_vlc;
576
577     if( !p_vlc )
578     {
579         return VLC_ENOOBJ;
580     }
581
582     /* Try to create the interface */
583     p_intf = intf_Create( p_vlc, psz_module ? psz_module : "$intf" );
584
585     if( p_intf == NULL )
586     {
587         msg_Err( p_vlc, "interface \"%s\" initialization failed", psz_module );
588         if( i_object ) vlc_object_release( p_vlc );
589         return VLC_EGENERIC;
590     }
591
592     /* Try to run the interface */
593     p_intf->b_block = b_block;
594     i_err = intf_RunThread( p_intf );
595     if( i_err )
596     {
597         vlc_object_detach( p_intf );
598         intf_Destroy( p_intf );
599         if( i_object ) vlc_object_release( p_vlc );
600         return i_err;
601     }
602
603     if( i_object ) vlc_object_release( p_vlc );
604     return VLC_SUCCESS;
605 }
606
607 /*****************************************************************************
608  * VLC_Destroy: stop playing and destroy everything.
609  *****************************************************************************
610  * This function requests the running threads to finish, waits for their
611  * termination, and destroys their structure.
612  *****************************************************************************/
613 int VLC_Destroy( int i_object )
614 {
615     vlc_t *p_vlc;
616
617     p_vlc = i_object ? vlc_object_get( &libvlc, i_object ) : p_static_vlc;
618
619     if( !p_vlc )
620     {
621         return VLC_ENOOBJ;
622     }
623
624     /*
625      * Free allocated memory
626      */
627     if( p_vlc->p_memcpy_module )
628     {
629         module_Unneed( p_vlc, p_vlc->p_memcpy_module );
630         p_vlc->p_memcpy_module = NULL;
631     }
632
633     if( p_vlc->psz_homedir )
634     {
635         free( p_vlc->psz_homedir );
636         p_vlc->psz_homedir = NULL;
637     }
638
639     /*
640      * XXX: Free module bank !
641      */
642     //module_EndBank( p_vlc );
643
644     /*
645      * System specific cleaning code
646      */
647     system_End( p_vlc );
648
649     /* Destroy mutexes */
650     vlc_mutex_destroy( &p_vlc->config_lock );
651
652     vlc_object_detach( p_vlc );
653
654     /* Release object before destroying it */
655     if( i_object ) vlc_object_release( p_vlc );
656
657     vlc_object_destroy( p_vlc );
658
659     /* Stop thread system: last one out please shut the door! */
660     vlc_threads_end( &libvlc );
661
662     return VLC_SUCCESS;
663 }
664
665 /*****************************************************************************
666  * VLC_Die: ask vlc to die.
667  *****************************************************************************
668  * This function sets p_vlc->b_die to VLC_TRUE, but does not do any other
669  * task. It is your duty to call vlc_end and VLC_Destroy afterwards.
670  *****************************************************************************/
671 int VLC_Die( int i_object )
672 {
673     vlc_t *p_vlc;
674
675     p_vlc = i_object ? vlc_object_get( &libvlc, i_object ) : p_static_vlc;
676
677     if( !p_vlc )
678     {
679         return VLC_ENOOBJ;
680     }
681
682     p_vlc->b_die = VLC_TRUE;
683
684     if( i_object ) vlc_object_release( p_vlc );
685     return VLC_SUCCESS;
686 }
687
688 /*****************************************************************************
689  * VLC_AddTarget: adds a target for playing.
690  *****************************************************************************
691  * This function adds psz_target to the current playlist. If a playlist does
692  * not exist, it will create one.
693  *****************************************************************************/
694 int VLC_AddTarget( int i_object, char const *psz_target, int i_mode, int i_pos )
695 {
696     int i_err;
697     playlist_t *p_playlist;
698     vlc_t *p_vlc;
699
700     p_vlc = i_object ? vlc_object_get( &libvlc, i_object ) : p_static_vlc;
701
702     if( !p_vlc )
703     {
704         return VLC_ENOOBJ;
705     }
706
707     p_playlist = vlc_object_find( p_vlc, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
708
709     if( p_playlist == NULL )
710     {
711         msg_Dbg( p_vlc, "no playlist present, creating one" );
712         p_playlist = playlist_Create( p_vlc );
713
714         if( p_playlist == NULL )
715         {
716             if( i_object ) vlc_object_release( p_vlc );
717             return VLC_EGENERIC;
718         }
719
720         vlc_object_yield( p_playlist );
721     }
722
723     i_err = playlist_Add( p_playlist, psz_target, i_mode, i_pos );
724
725     vlc_object_release( p_playlist );
726
727     if( i_object ) vlc_object_release( p_vlc );
728     return i_err;
729 }
730
731 /*****************************************************************************
732  * VLC_Set: set a vlc variable
733  *****************************************************************************
734  *
735  *****************************************************************************/
736 int VLC_Set( int i_object, char const *psz_var, vlc_value_t value )
737 {
738     vlc_t *p_vlc;
739     int i_ret;
740
741     p_vlc = i_object ? vlc_object_get( &libvlc, i_object ) : p_static_vlc;
742
743     if( !p_vlc )
744     {
745         return VLC_ENOOBJ;
746     }
747
748     /* FIXME: Temporary hack for Mozilla, if variable starts with conf:: then
749      * we handle it as a configuration variable. Don't tell Gildas :) -- sam */
750     if( !strncmp( psz_var, "conf::", 6 ) )
751     {
752         module_config_t *p_item;
753         char const *psz_newvar = psz_var + 6;
754
755         p_item = config_FindConfig( VLC_OBJECT(p_vlc), psz_newvar );
756
757         if( p_item )
758         {
759             switch( p_item->i_type )
760             {
761                 case CONFIG_ITEM_BOOL:
762                     config_PutInt( p_vlc, psz_newvar, value.b_bool );
763                     break;
764                 case CONFIG_ITEM_INTEGER:
765                     config_PutInt( p_vlc, psz_newvar, value.i_int );
766                     break;
767                 case CONFIG_ITEM_FLOAT:
768                     config_PutFloat( p_vlc, psz_newvar, value.f_float );
769                     break;
770                 default:
771                     config_PutPsz( p_vlc, psz_newvar, value.psz_string );
772                     break;
773             }
774             if( i_object ) vlc_object_release( p_vlc );
775             return VLC_SUCCESS;
776         }
777     }
778
779     i_ret = var_Set( p_vlc, psz_var, value );
780
781     if( i_object ) vlc_object_release( p_vlc );
782     return i_ret;
783 }
784
785 /*****************************************************************************
786  * VLC_Get: get a vlc variable
787  *****************************************************************************
788  *
789  *****************************************************************************/
790 int VLC_Get( int i_object, char const *psz_var, vlc_value_t *p_value )
791 {
792     vlc_t *p_vlc;
793     int i_ret;
794
795     p_vlc = i_object ? vlc_object_get( &libvlc, i_object ) : p_static_vlc;
796
797     if( !p_vlc )
798     {
799         return VLC_ENOOBJ;
800     }
801
802     i_ret = var_Get( p_vlc, psz_var, p_value );
803
804     if( i_object ) vlc_object_release( p_vlc );
805     return i_ret;
806 }
807
808 /* FIXME: temporary hacks */
809
810 /*****************************************************************************
811  * VLC_Play: play
812  *****************************************************************************/
813 int VLC_Play( int i_object )
814 {
815     playlist_t * p_playlist;
816     vlc_t *p_vlc;
817
818     p_vlc = i_object ? vlc_object_get( &libvlc, i_object ) : p_static_vlc;
819
820     /* Check that the handle is valid */
821     if( !p_vlc )
822     {
823         return VLC_ENOOBJ;
824     }
825
826     p_playlist = vlc_object_find( p_vlc, VLC_OBJECT_PLAYLIST, FIND_CHILD );
827
828     if( !p_playlist )
829     {
830         if( i_object ) vlc_object_release( p_vlc );
831         return VLC_ENOOBJ;
832     }
833
834     vlc_mutex_lock( &p_playlist->object_lock );
835     if( p_playlist->i_size )
836     {
837         vlc_mutex_unlock( &p_playlist->object_lock );
838         playlist_Play( p_playlist );
839     }
840     else
841     {
842         vlc_mutex_unlock( &p_playlist->object_lock );
843     }
844
845     vlc_object_release( p_playlist );
846
847     if( i_object ) vlc_object_release( p_vlc );
848     return VLC_SUCCESS;
849 }
850
851 /*****************************************************************************
852  * VLC_Stop: stop
853  *****************************************************************************/
854 int VLC_Stop( int i_object )
855 {
856     intf_thread_t *   p_intf;
857     playlist_t    *   p_playlist;
858     vout_thread_t *   p_vout;
859     aout_instance_t * p_aout;
860     vlc_t *p_vlc;
861
862     p_vlc = i_object ? vlc_object_get( &libvlc, i_object ) : p_static_vlc;
863
864     /* Check that the handle is valid */
865     if( !p_vlc )
866     {
867         return VLC_ENOOBJ;
868     }
869
870     /*
871      * Ask the interfaces to stop and destroy them
872      */
873     msg_Dbg( p_vlc, "removing all interfaces" );
874     while( (p_intf = vlc_object_find( p_vlc, VLC_OBJECT_INTF, FIND_CHILD )) )
875     {
876         intf_StopThread( p_intf );
877         vlc_object_detach( p_intf );
878         vlc_object_release( p_intf );
879         intf_Destroy( p_intf );
880     }
881
882     /*
883      * Free playlists
884      */
885     msg_Dbg( p_vlc, "removing all playlists" );
886     while( (p_playlist = vlc_object_find( p_vlc, VLC_OBJECT_PLAYLIST,
887                                           FIND_CHILD )) )
888     {
889         vlc_object_detach( p_playlist );
890         vlc_object_release( p_playlist );
891         playlist_Destroy( p_playlist );
892     }
893
894     /*
895      * Free video outputs
896      */
897     msg_Dbg( p_vlc, "removing all video outputs" );
898     while( (p_vout = vlc_object_find( p_vlc, VLC_OBJECT_VOUT, FIND_CHILD )) )
899     {
900         vlc_object_detach( p_vout );
901         vlc_object_release( p_vout );
902         vout_Destroy( p_vout );
903     }
904
905     /*
906      * Free audio outputs
907      */
908     msg_Dbg( p_vlc, "removing all audio outputs" );
909     while( (p_aout = vlc_object_find( p_vlc, VLC_OBJECT_AOUT, FIND_CHILD )) )
910     {
911         vlc_object_detach( (vlc_object_t *)p_aout );
912         vlc_object_release( (vlc_object_t *)p_aout );
913         aout_Delete( p_aout );
914     }
915
916     if( i_object ) vlc_object_release( p_vlc );
917     return VLC_SUCCESS;
918 }
919
920 /*****************************************************************************
921  * VLC_Pause: toggle pause
922  *****************************************************************************/
923 int VLC_Pause( int i_object )
924 {
925     input_thread_t *p_input;
926     vlc_t *p_vlc;
927
928     p_vlc = i_object ? vlc_object_get( &libvlc, i_object ) : p_static_vlc;
929
930     if( !p_vlc )
931     {
932         return VLC_ENOOBJ;
933     }
934
935     p_input = vlc_object_find( p_vlc, VLC_OBJECT_INPUT, FIND_CHILD );
936
937     if( !p_input )
938     {
939         if( i_object ) vlc_object_release( p_vlc );
940         return VLC_ENOOBJ;
941     }
942
943     input_SetStatus( p_input, INPUT_STATUS_PAUSE );
944     vlc_object_release( p_input );
945
946     if( i_object ) vlc_object_release( p_vlc );
947     return VLC_SUCCESS;
948 }
949
950 /*****************************************************************************
951  * VLC_FullScreen: toggle fullscreen mode
952  *****************************************************************************/
953 int VLC_FullScreen( int i_object )
954 {
955     vout_thread_t *p_vout;
956     vlc_t *p_vlc;
957
958     p_vlc = i_object ? vlc_object_get( &libvlc, i_object ) : p_static_vlc;
959
960     if( !p_vlc )
961     {
962         return VLC_ENOOBJ;
963     }
964
965     p_vout = vlc_object_find( p_vlc, VLC_OBJECT_VOUT, FIND_CHILD );
966
967     if( !p_vout )
968     {
969         if( i_object ) vlc_object_release( p_vlc );
970         return VLC_ENOOBJ;
971     }
972
973     p_vout->i_changes |= VOUT_FULLSCREEN_CHANGE;
974     vlc_object_release( p_vout );
975
976     if( i_object ) vlc_object_release( p_vlc );
977     return VLC_SUCCESS;
978 }
979
980 /* following functions are local */
981
982 /*****************************************************************************
983  * SetLanguage: set the interface language.
984  *****************************************************************************
985  * We set the LC_MESSAGES locale category for interface messages and buttons,
986  * as well as the LC_CTYPE category for string sorting and possible wide
987  * character support.
988  *****************************************************************************/
989 static void SetLanguage ( char const *psz_lang )
990 {
991 #if defined( ENABLE_NLS ) \
992      && ( defined( HAVE_GETTEXT ) || defined( HAVE_INCLUDED_GETTEXT ) )
993
994     char *          psz_path;
995 #if defined( SYS_DARWIN ) || defined ( WIN32 ) || defined( SYS_BEOS )
996     char            psz_tmp[1024];
997 #endif
998
999 #   if defined( HAVE_INCLUDED_GETTEXT ) && !defined( HAVE_LC_MESSAGES )
1000     if( *psz_lang )
1001     {
1002         /* We set LC_ALL manually because it is the only way to set
1003          * the language at runtime under eg. Windows. Beware that this
1004          * makes the environment unconsistent when libvlc is unloaded and
1005          * should probably be moved to a safer place like vlc.c. */
1006         static char psz_lcall[20];
1007         snprintf( psz_lcall, 19, "LC_ALL=%s", psz_lang );
1008         psz_lcall[19] = '\0';
1009         putenv( psz_lcall );
1010     }
1011 #   endif
1012
1013     if( psz_lang && !*psz_lang )
1014     {
1015 #   if defined( HAVE_LC_MESSAGES )
1016         setlocale( LC_MESSAGES, psz_lang );
1017 #   endif
1018         setlocale( LC_CTYPE, psz_lang );
1019     }
1020     else
1021     {
1022 #ifdef SYS_BEOS 
1023         static char psz_lcall[20];
1024 #endif
1025         setlocale( LC_ALL, psz_lang );
1026 #ifdef SYS_DARWIN
1027         /* I need that under Darwin, please check it doesn't disturb
1028          * other platforms. --Meuuh */
1029         setenv( "LANG", psz_lang, 1 );
1030 #endif
1031 #ifdef SYS_BEOS
1032         /* I need this under BeOS... */
1033         snprintf( psz_lcall, 19, "LC_ALL=%s", psz_lang );
1034         psz_lcall[19] = '\0';
1035         putenv( psz_lcall );
1036 #endif
1037     }
1038
1039     /* Specify where to find the locales for current domain */
1040 #if !defined( SYS_DARWIN ) && !defined( WIN32 ) && !defined( SYS_BEOS )
1041     psz_path = LOCALEDIR;
1042 #else
1043     snprintf( psz_tmp, sizeof(psz_tmp), "%s/%s", libvlc.psz_vlcpath,
1044               "locale" );
1045     psz_path = psz_tmp;
1046 #endif
1047     if( !bindtextdomain( PACKAGE, psz_path ) )
1048     {
1049         fprintf( stderr, "warning: no domain %s in directory %s\n",
1050                  PACKAGE, psz_path );
1051     }
1052
1053     /* Set the default domain */
1054     textdomain( PACKAGE );
1055
1056 #ifdef SYS_BEOS
1057     /* BeOS only support UTF8 strings */
1058     bind_textdomain_codeset( PACKAGE, "UTF-8" );
1059 #endif
1060
1061 #endif
1062 }
1063
1064 /*****************************************************************************
1065  * GetFilenames: parse command line options which are not flags
1066  *****************************************************************************
1067  * Parse command line for input files.
1068  *****************************************************************************/
1069 static int GetFilenames( vlc_t *p_vlc, int i_argc, char *ppsz_argv[] )
1070 {
1071     int i_opt;
1072
1073     /* We assume that the remaining parameters are filenames */
1074     for( i_opt = i_argc - 1; i_opt > optind; i_opt-- )
1075     {
1076         /* TODO: write an internal function of this one, to avoid
1077          *       unnecessary lookups. */
1078         VLC_AddTarget( p_vlc->i_object_id, ppsz_argv[ i_opt ],
1079                        PLAYLIST_INSERT, 0 );
1080     }
1081
1082     /* If there is at least one target, play it */
1083     if( i_argc > optind )
1084     {
1085         VLC_AddTarget( p_vlc->i_object_id, ppsz_argv[ optind ],
1086                        PLAYLIST_INSERT | PLAYLIST_GO, 0 );
1087     }
1088
1089     return VLC_SUCCESS;
1090 }
1091
1092 /*****************************************************************************
1093  * Usage: print program usage
1094  *****************************************************************************
1095  * Print a short inline help. Message interface is initialized at this stage.
1096  *****************************************************************************/
1097 static void Usage( vlc_t *p_this, char const *psz_module_name )
1098 {
1099 #define FORMAT_STRING "  %s --%s%s%s%s%s%s%s "
1100     /* short option ------'    |     | | | |  | |
1101      * option name ------------'     | | | |  | |
1102      * <bra -------------------------' | | |  | |
1103      * option type or "" --------------' | |  | |
1104      * ket> -----------------------------' |  | |
1105      * padding spaces ---------------------'  | |
1106      * comment -------------------------------' |
1107      * comment suffix --------------------------'
1108      *
1109      * The purpose of having bra and ket is that we might i18n them as well.
1110      */
1111 #define LINE_START 8
1112 #define PADDING_SPACES 25
1113     vlc_list_t *p_list;
1114     module_t *p_parser;
1115     module_config_t *p_item;
1116     char psz_spaces[PADDING_SPACES+LINE_START+1];
1117     char psz_format[sizeof(FORMAT_STRING)];
1118     char psz_buffer[1000];
1119     char psz_short[4];
1120     int i_index;
1121     int i_width = ConsoleWidth() - (PADDING_SPACES+LINE_START+1);
1122
1123     memset( psz_spaces, ' ', PADDING_SPACES+LINE_START );
1124     psz_spaces[PADDING_SPACES+LINE_START] = '\0';
1125
1126     strcpy( psz_format, FORMAT_STRING );
1127
1128 #ifdef WIN32
1129     ShowConsole();
1130 #endif
1131
1132     /* List all modules */
1133     p_list = vlc_list_find( p_this, VLC_OBJECT_MODULE, FIND_ANYWHERE );
1134
1135     /* Enumerate the config for each module */
1136     for( i_index = 0; i_index < p_list->i_count; i_index++ )
1137     {
1138         vlc_bool_t b_help_module;
1139
1140         p_parser = (module_t *)p_list->p_values[i_index].p_object ;
1141
1142         if( psz_module_name && strcmp( psz_module_name,
1143                                        p_parser->psz_object_name ) )
1144         {
1145             continue;
1146         }
1147
1148         /* Ignore modules without config options */
1149         if( !p_parser->i_config_items )
1150         {
1151             continue;
1152         }
1153
1154         b_help_module = !strcmp( "help", p_parser->psz_object_name );
1155
1156         /* Print module options */
1157         for( p_item = p_parser->p_config;
1158              p_item->i_type != CONFIG_HINT_END;
1159              p_item++ )
1160         {
1161             char *psz_text;
1162             char *psz_bra = NULL, *psz_type = NULL, *psz_ket = NULL;
1163             char *psz_suf = "", *psz_prefix = NULL;
1164             int i;
1165             if ( p_item->b_advanced && !config_GetInt( p_this, "advanced" ))
1166             {
1167                 continue;
1168             }
1169             switch( p_item->i_type )
1170             {
1171             case CONFIG_HINT_CATEGORY:
1172             case CONFIG_HINT_USAGE:
1173                 fprintf( stdout, " %s\n", p_item->psz_text );
1174                 break;
1175
1176             case CONFIG_ITEM_STRING:
1177             case CONFIG_ITEM_FILE:
1178             case CONFIG_ITEM_MODULE: /* We could also have "=<" here */
1179                 if( !p_item->ppsz_list )
1180                 {
1181                     psz_bra = " <"; psz_type = _("string"); psz_ket = ">";
1182                     break;
1183                 }
1184                 else
1185                 {
1186                     psz_bra = " {";
1187                     psz_type = psz_buffer;
1188                     psz_type[0] = '\0';
1189                     for( i = 0; p_item->ppsz_list[i]; i++ )
1190                     {
1191                         if( i ) strcat( psz_type, "," );
1192                         strcat( psz_type, p_item->ppsz_list[i] );
1193                     }
1194                     psz_ket = "}";
1195                     break;
1196                 }
1197             case CONFIG_ITEM_INTEGER:
1198                 psz_bra = " <"; psz_type = _("integer"); psz_ket = ">";
1199                 break;
1200             case CONFIG_ITEM_FLOAT:
1201                 psz_bra = " <"; psz_type = _("float"); psz_ket = ">";
1202                 break;
1203             case CONFIG_ITEM_BOOL:
1204                 psz_bra = ""; psz_type = ""; psz_ket = "";
1205                 if( !b_help_module )
1206                 {
1207                     psz_suf = p_item->i_value ? _(" (default enabled)") :
1208                                                 _(" (default disabled)");
1209                 }
1210                 break;
1211             }
1212
1213             if( !psz_type )
1214             {
1215                 continue;
1216             }
1217
1218             /* Add short option if any */
1219             if( p_item->i_short )
1220             {
1221                 sprintf( psz_short, "-%c,", p_item->i_short );
1222             }
1223             else
1224             {
1225                 strcpy( psz_short, "   " );
1226             }
1227
1228             i = PADDING_SPACES - strlen( p_item->psz_name )
1229                  - strlen( psz_bra ) - strlen( psz_type )
1230                  - strlen( psz_ket ) - 1;
1231
1232             if( p_item->i_type == CONFIG_ITEM_BOOL && !b_help_module )
1233             {
1234                 /* If option is of type --foo-bar, we print its counterpart
1235                  * as --no-foo-bar, but if it is of type --foobar (without
1236                  * dashes in the name) we print it as --nofoobar. Both
1237                  * values are of course valid, only the display changes. */
1238                 psz_prefix = strchr( p_item->psz_name, '-' ) ? ", --no-"
1239                                                              : ", --no";
1240                 i -= strlen( p_item->psz_name ) + strlen( psz_prefix );
1241             }
1242
1243             if( i < 0 )
1244             {
1245                 psz_spaces[0] = '\n';
1246                 i = 0;
1247             }
1248             else
1249             {
1250                 psz_spaces[i] = '\0';
1251             }
1252
1253             if( p_item->i_type == CONFIG_ITEM_BOOL && !b_help_module )
1254             {
1255                 fprintf( stdout, psz_format, psz_short, p_item->psz_name,
1256                          psz_prefix, p_item->psz_name, psz_bra, psz_type,
1257                          psz_ket, psz_spaces );
1258             }
1259             else
1260             {
1261                 fprintf( stdout, psz_format, psz_short, p_item->psz_name,
1262                          "", "", psz_bra, psz_type, psz_ket, psz_spaces );
1263             }
1264
1265             psz_spaces[i] = ' ';
1266
1267             /* We wrap the rest of the output */
1268             sprintf( psz_buffer, "%s%s", p_item->psz_text, psz_suf );
1269             psz_text = psz_buffer;
1270             while( *psz_text )
1271             {
1272                 char *psz_parser, *psz_word;
1273                 int i_end = strlen( psz_text );
1274
1275                 /* If the remaining text fits in a line, print it. */
1276                 if( i_end <= i_width )
1277                 {
1278                     fprintf( stdout, "%s\n", psz_text );
1279                     break;
1280                 }
1281
1282                 /* Otherwise, eat as many words as possible */
1283                 psz_parser = psz_text;
1284                 do
1285                 {
1286                     psz_word = psz_parser;
1287                     psz_parser = strchr( psz_word, ' ' );
1288                     /* If no space was found, we reached the end of the text
1289                      * block; otherwise, we skip the space we just found. */
1290                     psz_parser = psz_parser ? psz_parser + 1
1291                                             : psz_text + i_end;
1292
1293                 } while( psz_parser - psz_text <= i_width );
1294
1295                 /* We cut a word in one of these cases:
1296                  *  - it's the only word in the line and it's too long.
1297                  *  - we used less than 80% of the width and the word we are
1298                  *    going to wrap is longer than 40% of the width, and even
1299                  *    if the word would have fit in the next line. */
1300                 if( psz_word == psz_text
1301                      || ( psz_word - psz_text < 80 * i_width / 100
1302                            && psz_parser - psz_word > 40 * i_width / 100 ) )
1303                 {
1304                     char c = psz_text[i_width];
1305                     psz_text[i_width] = '\0';
1306                     fprintf( stdout, "%s\n%s", psz_text, psz_spaces );
1307                     psz_text += i_width;
1308                     psz_text[0] = c;
1309                 }
1310                 else
1311                 {
1312                     psz_word[-1] = '\0';
1313                     fprintf( stdout, "%s\n%s", psz_text, psz_spaces );
1314                     psz_text = psz_word;
1315                 }
1316             }
1317         }
1318     }
1319
1320     /* Release the module list */
1321     vlc_list_release( p_list );
1322
1323 #ifdef WIN32        /* Pause the console because it's destroyed when we exit */
1324     fprintf( stdout, _("\nPress the RETURN key to continue...\n") );
1325     getchar();
1326 #endif
1327 }
1328
1329 /*****************************************************************************
1330  * ListModules: list the available modules with their description
1331  *****************************************************************************
1332  * Print a list of all available modules (builtins and plugins) and a short
1333  * description for each one.
1334  *****************************************************************************/
1335 static void ListModules( vlc_t *p_this )
1336 {
1337     vlc_list_t *p_list;
1338     module_t *p_parser;
1339     char psz_spaces[22];
1340     int i_index;
1341
1342     memset( psz_spaces, ' ', 22 );
1343
1344 #ifdef WIN32
1345     ShowConsole();
1346 #endif
1347
1348     /* Usage */
1349     fprintf( stdout, _("Usage: %s [options] [items]...\n\n"),
1350                      p_this->p_vlc->psz_object_name );
1351
1352     fprintf( stdout, _("[module]              [description]\n") );
1353
1354     /* List all modules */
1355     p_list = vlc_list_find( p_this, VLC_OBJECT_MODULE, FIND_ANYWHERE );
1356
1357     /* Enumerate each module */
1358     for( i_index = 0; i_index < p_list->i_count; i_index++ )
1359     {
1360         int i;
1361
1362         p_parser = (module_t *)p_list->p_values[i_index].p_object ;
1363
1364         /* Nasty hack, but right now I'm too tired to think about a nice
1365          * solution */
1366         i = 22 - strlen( p_parser->psz_object_name ) - 1;
1367         if( i < 0 ) i = 0;
1368         psz_spaces[i] = 0;
1369
1370         fprintf( stdout, "  %s%s %s\n", p_parser->psz_object_name,
1371                          psz_spaces, p_parser->psz_longname );
1372
1373         psz_spaces[i] = ' ';
1374     }
1375
1376     vlc_list_release( p_list );
1377
1378 #ifdef WIN32        /* Pause the console because it's destroyed when we exit */
1379     fprintf( stdout, _("\nPress the RETURN key to continue...\n") );
1380     getchar();
1381 #endif
1382 }
1383
1384 /*****************************************************************************
1385  * Version: print complete program version
1386  *****************************************************************************
1387  * Print complete program version and build number.
1388  *****************************************************************************/
1389 static void Version( void )
1390 {
1391 #ifdef WIN32
1392     ShowConsole();
1393 #endif
1394
1395     fprintf( stdout, VERSION_MESSAGE "\n" );
1396     fprintf( stdout,
1397       _("This program comes with NO WARRANTY, to the extent permitted by "
1398         "law.\nYou may redistribute it under the terms of the GNU General "
1399         "Public License;\nsee the file named COPYING for details.\n"
1400         "Written by the VideoLAN team at Ecole Centrale, Paris.\n") );
1401
1402 #ifdef WIN32        /* Pause the console because it's destroyed when we exit */
1403     fprintf( stdout, _("\nPress the RETURN key to continue...\n") );
1404     getchar();
1405 #endif
1406 }
1407
1408 /*****************************************************************************
1409  * ShowConsole: On Win32, create an output console for debug messages
1410  *****************************************************************************
1411  * This function is useful only on Win32.
1412  *****************************************************************************/
1413 #ifdef WIN32 /*  */
1414 static void ShowConsole( void )
1415 {
1416 #   ifndef UNDER_CE
1417     AllocConsole();
1418     freopen( "CONOUT$", "w", stdout );
1419     freopen( "CONOUT$", "w", stderr );
1420     freopen( "CONIN$", "r", stdin );
1421 #   endif
1422     return;
1423 }
1424 #endif
1425
1426 /*****************************************************************************
1427  * ConsoleWidth: Return the console width in characters
1428  *****************************************************************************
1429  * We use the stty shell command to get the console width; if this fails or
1430  * if the width is less than 80, we default to 80.
1431  *****************************************************************************/
1432 static int ConsoleWidth( void )
1433 {
1434     int i_width = 80;
1435
1436 #ifndef WIN32
1437     char buf[20], *psz_parser;
1438     FILE *file;
1439     int i_ret;
1440
1441     file = popen( "stty size 2>/dev/null", "r" );
1442     if( file )
1443     {
1444         i_ret = fread( buf, 1, 20, file );
1445         if( i_ret > 0 )
1446         {
1447             buf[19] = '\0';
1448             psz_parser = strchr( buf, ' ' );
1449             if( psz_parser )
1450             {
1451                 i_ret = atoi( psz_parser + 1 );
1452                 if( i_ret >= 80 )
1453                 {
1454                     i_width = i_ret;
1455                 }
1456             }
1457         }
1458
1459         pclose( file );
1460     }
1461 #endif
1462
1463     return i_width;
1464 }