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