]> git.sesse.net Git - vlc/blob - src/libvlc.c
7ca55b75273798e05de71a0da4990115bd3b7f2b
[vlc] / src / libvlc.c
1 /*****************************************************************************
2  * libvlc.c: main libvlc source
3  *****************************************************************************
4  * Copyright (C) 1998-2002 VideoLAN
5  * $Id: libvlc.c,v 1.33 2002/09/29 18:19:53 sam 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 <errno.h>                                                 /* ENOMEM */
37 #include <stdio.h>                                              /* sprintf() */
38 #include <string.h>                                            /* strerror() */
39 #include <stdlib.h>                                                /* free() */
40
41 #include <vlc/vlc.h>
42
43 #ifndef WIN32
44 #   include <netinet/in.h>                            /* BSD: struct in_addr */
45 #endif
46
47 #ifdef HAVE_UNISTD_H
48 #   include <unistd.h>
49 #elif defined( _MSC_VER ) && defined( _WIN32 )
50 #   include <io.h>
51 #endif
52
53 #ifdef WIN32                       /* optind, getopt(), included in unistd.h */
54 #   include "extras/GNUgetopt/getopt.h"
55 #endif
56
57 #ifdef HAVE_LOCALE_H
58 #   include <locale.h>
59 #endif
60
61 #include "vlc_cpu.h"                                        /* CPU detection */
62 #include "os_specific.h"
63
64 #include "netutils.h"                                 /* network_ChannelJoin */
65
66 #include "stream_control.h"
67 #include "input_ext-intf.h"
68
69 #include "vlc_playlist.h"
70 #include "interface.h"
71
72 #include "audio_output.h"
73
74 #include "video.h"
75 #include "video_output.h"
76
77 #include "libvlc.h"
78
79 /*****************************************************************************
80  * The evil global variables. We handle them with care, don't worry.
81  *****************************************************************************/
82
83 /* This global lock is used for critical sections - don't abuse it! */
84 static vlc_mutex_t global_lock;
85 void *             p_global_data;
86
87 /* A list of all the currently allocated vlc objects */
88 static int      volatile i_vlc = 0;
89 static vlc_t ** volatile pp_vlc = NULL;
90
91 /*****************************************************************************
92  * Local prototypes
93  *****************************************************************************/
94 static int  GetFilenames  ( vlc_t *, int, char *[] );
95 static void Usage         ( vlc_t *, const char *psz_module_name );
96 static void ListModules   ( vlc_t * );
97 static void Version       ( void );
98
99 #ifdef WIN32
100 static void ShowConsole   ( void );
101 #endif
102
103 /*****************************************************************************
104  * vlc_create: allocate a vlc_t structure, and initialize libvlc if needed.
105  *****************************************************************************
106  * This function allocates a vlc_t structure and returns NULL in case of
107  * failure. Also, the thread system is initialized.
108  *****************************************************************************/
109 vlc_error_t vlc_create( void )
110 {
111     vlc_t * p_vlc;
112     vlc_bool_t b_failed = VLC_FALSE;
113
114     /* This gives us a rather good protection against concurrent calls, but
115      * an additional check will be necessary for complete thread safety. */
116     if( i_vlc )
117     {
118         return VLC_EGENERIC;
119     }
120
121     p_vlc = vlc_create_r();
122
123     if( p_vlc == NULL )
124     {
125         return VLC_EGENERIC;
126     }
127
128     /* We have created an object, which ensures us that p_global_lock has
129      * been properly initialized. We can now atomically check that we are
130      * the only p_vlc object. */
131     vlc_mutex_lock( p_vlc->p_global_lock );
132     if( i_vlc != 1 )
133     {
134         b_failed = VLC_TRUE;
135     }
136     vlc_mutex_unlock( p_vlc->p_global_lock );
137
138     /* There can be only one */
139     if( b_failed )
140     {
141         vlc_destroy_r( p_vlc );
142         return VLC_EGENERIC;
143     }
144
145     return VLC_SUCCESS;
146 }
147
148 vlc_t * vlc_create_r( void )
149 {
150     static int i_instance = 0;
151     vlc_t * p_vlc = NULL;
152
153     /* Allocate the main structure */
154     p_vlc = vlc_object_create( p_vlc, VLC_OBJECT_ROOT );
155     if( p_vlc == NULL )
156     {
157         return NULL;
158     }
159
160     p_vlc->psz_object_name = "root";
161
162     p_vlc->p_global_lock = &global_lock;
163     p_vlc->pp_global_data = &p_global_data;
164
165     p_vlc->b_verbose = VLC_FALSE;
166     p_vlc->b_quiet = VLC_FALSE; /* FIXME: delay message queue output! */
167
168     /* Initialize the threads system */
169     vlc_threads_init( p_vlc );
170
171     /* Initialize mutexes */
172     vlc_mutex_init( p_vlc, &p_vlc->config_lock );
173     vlc_mutex_init( p_vlc, &p_vlc->structure_lock );
174
175     /* Store our newly allocated structure in the global list */
176     vlc_mutex_lock( p_vlc->p_global_lock );
177     pp_vlc = realloc( pp_vlc, (i_vlc+1) * sizeof( vlc_t * ) );
178     pp_vlc[ i_vlc ] = p_vlc;
179     i_vlc++;
180     p_vlc->i_instance = i_instance;
181     i_instance++;
182     vlc_mutex_unlock( p_vlc->p_global_lock );
183
184     /* Update the handle status */
185     p_vlc->i_status = VLC_STATUS_CREATED;
186
187     return p_vlc;
188 }
189
190 /*****************************************************************************
191  * vlc_init: initialize a vlc_t structure.
192  *****************************************************************************
193  * This function initializes a previously allocated vlc_t structure:
194  *  - CPU detection
195  *  - gettext initialization
196  *  - message queue, module bank and playlist initialization
197  *  - configuration and commandline parsing
198  *****************************************************************************/
199 vlc_error_t vlc_init( int i_argc, char *ppsz_argv[] )
200 {
201     return vlc_init_r( ( i_vlc == 1 ) ? pp_vlc[0] : NULL, i_argc, ppsz_argv );
202 }
203
204 vlc_error_t vlc_init_r( vlc_t *p_vlc, int i_argc, char *ppsz_argv[] )
205 {
206     char         p_capabilities[200];
207     char *       p_tmp;
208     vlc_bool_t   b_exit;
209     module_t    *p_help_module;
210     playlist_t  *p_playlist;
211
212     /* Check that the handle is valid */
213     if( !p_vlc || p_vlc->i_status != VLC_STATUS_CREATED )
214     {
215         fprintf( stderr, "error: invalid status (!CREATED)\n" );
216         return VLC_ESTATUS;
217     }
218
219     /* Guess what CPU we have */
220     p_vlc->i_cpu = CPUCapabilities( p_vlc );
221
222     /*
223      * Support for gettext
224      */
225 #if defined( ENABLE_NLS ) && defined ( HAVE_GETTEXT )
226 #   if defined( HAVE_LOCALE_H ) && defined( HAVE_LC_MESSAGES )
227     if( !setlocale( LC_MESSAGES, "" ) )
228     {
229         fprintf( stderr, "warning: unsupported locale settings\n" );
230     }
231
232     setlocale( LC_CTYPE, "" );
233 #   endif
234
235     if( !bindtextdomain( PACKAGE, LOCALEDIR ) )
236     {
237         fprintf( stderr, "warning: no domain %s in directory %s\n",
238                  PACKAGE, LOCALEDIR );
239     }
240
241     textdomain( PACKAGE );
242 #endif
243
244     /*
245      * Initialize message queue
246      */
247     msg_Create( p_vlc );
248
249     /*
250      * System specific initialization code
251      */
252     system_Init( p_vlc, &i_argc, ppsz_argv );
253
254     /* Get the executable name (similar to the basename command) */
255     if( i_argc > 0 )
256     {
257         p_vlc->psz_object_name = p_tmp = ppsz_argv[ 0 ];
258         while( *p_tmp )
259         {
260             if( *p_tmp == '/' ) p_vlc->psz_object_name = ++p_tmp;
261             else ++p_tmp;
262         }
263     }
264     else
265     {
266         p_vlc->psz_object_name = "vlc";
267     }
268
269     /* Announce who we are */
270     msg_Dbg( p_vlc, COPYRIGHT_MESSAGE );
271     msg_Dbg( p_vlc, "libvlc was configured with %s", CONFIGURE_LINE );
272
273     /*
274      * Initialize the module bank and and load the configuration of the main
275      * module. We need to do this at this stage to be able to display a short
276      * help if required by the user. (short help == main module options)
277      */
278     module_InitBank( p_vlc );
279     module_LoadMain( p_vlc );
280
281     /* Hack: insert the help module here */
282     p_help_module = vlc_object_create( p_vlc, VLC_OBJECT_MODULE );
283     if( p_help_module == NULL )
284     {
285         module_EndBank( p_vlc );
286         msg_Destroy( p_vlc );
287         return VLC_EGENERIC;
288     }
289     p_help_module->psz_object_name = "help";
290     config_Duplicate( p_help_module, p_help_config );
291     vlc_object_attach( p_help_module, p_vlc->p_module_bank );
292     /* End hack */
293
294     if( config_LoadCmdLine( p_vlc, &i_argc, ppsz_argv, VLC_TRUE ) )
295     {
296         vlc_object_detach( p_help_module );
297         config_Free( p_help_module );
298         vlc_object_destroy( p_help_module );
299         module_EndBank( p_vlc );
300         msg_Destroy( p_vlc );
301         return VLC_EGENERIC;
302     }
303
304     b_exit = VLC_FALSE;
305
306     /* Check for short help option */
307     if( config_GetInt( p_vlc, "help" ) )
308     {
309         fprintf( stderr, _("Usage: %s [options] [items]...\n\n"),
310                          p_vlc->psz_object_name );
311         Usage( p_vlc, "main" );
312         Usage( p_vlc, "help" );
313         b_exit = VLC_TRUE;
314     }
315     /* Check for version option */
316     else if( config_GetInt( p_vlc, "version" ) )
317     {
318         Version();
319         b_exit = VLC_TRUE;
320     }
321
322     /* Hack: remove the help module here */
323     vlc_object_detach( p_help_module );
324     /* End hack */
325
326     if( b_exit )
327     {
328         config_Free( p_help_module );
329         vlc_object_destroy( p_help_module );
330         module_EndBank( p_vlc );
331         msg_Destroy( p_vlc );
332         return VLC_EEXIT;
333     }
334
335     /*
336      * Load the builtins and plugins into the module_bank.
337      * We have to do it before config_Load*() because this also gets the
338      * list of configuration options exported by each module and loads their
339      * default values.
340      */
341     module_LoadBuiltins( p_vlc );
342     module_LoadPlugins( p_vlc );
343     msg_Dbg( p_vlc, "module bank initialized, found %i modules",
344                     p_vlc->p_module_bank->i_children );
345
346     /* Hack: insert the help module here */
347     vlc_object_attach( p_help_module, p_vlc->p_module_bank );
348     /* End hack */
349
350     /* Check for help on modules */
351     if( (p_tmp = config_GetPsz( p_vlc, "module" )) )
352     {
353         Usage( p_vlc, p_tmp );
354         free( p_tmp );
355         b_exit = VLC_TRUE;
356     }
357     /* Check for long help option */
358     else if( config_GetInt( p_vlc, "longhelp" ) )
359     {
360         Usage( p_vlc, NULL );
361         b_exit = VLC_TRUE;
362     }
363     /* Check for module list option */
364     else if( config_GetInt( p_vlc, "list" ) )
365     {
366         ListModules( p_vlc );
367         b_exit = VLC_TRUE;
368     }
369
370     /* Hack: remove the help module here */
371     vlc_object_detach( p_help_module );
372     config_Free( p_help_module );
373     vlc_object_destroy( p_help_module );
374     /* End hack */
375
376     if( b_exit )
377     {
378         module_EndBank( p_vlc );
379         msg_Destroy( p_vlc );
380         return VLC_EEXIT;
381     }
382
383     /*
384      * Override default configuration with config file settings
385      */
386     p_vlc->psz_homedir = config_GetHomeDir();
387     config_LoadConfigFile( p_vlc, NULL );
388
389     /*
390      * Override configuration with command line settings
391      */
392     if( config_LoadCmdLine( p_vlc, &i_argc, ppsz_argv, VLC_FALSE ) )
393     {
394 #ifdef WIN32
395         ShowConsole();
396         /* Pause the console because it's destroyed when we exit */
397         fprintf( stderr, "The command line options couldn't be loaded, check "
398                  "that they are valid.\nPress the RETURN key to continue..." );
399         getchar();
400 #endif
401         module_EndBank( p_vlc );
402         msg_Destroy( p_vlc );
403         return VLC_EGENERIC;
404     }
405
406     /*
407      * System specific configuration
408      */
409     system_Configure( p_vlc );
410
411     /*
412      * Output messages that may still be in the queue
413      */
414     p_vlc->b_verbose = config_GetInt( p_vlc, "verbose" );
415     p_vlc->b_quiet = config_GetInt( p_vlc, "quiet" );
416     p_vlc->b_color = config_GetInt( p_vlc, "color" );
417     msg_Flush( p_vlc );
418
419     /* p_vlc inititalization. FIXME ? */
420     p_vlc->i_desync = config_GetInt( p_vlc, "desync" ) * (mtime_t)1000;
421 #if defined( __i386__ )
422     if( !config_GetInt( p_vlc, "mmx" ) )
423         p_vlc->i_cpu &= ~CPU_CAPABILITY_MMX;
424     if( !config_GetInt( p_vlc, "3dn" ) )
425         p_vlc->i_cpu &= ~CPU_CAPABILITY_3DNOW;
426     if( !config_GetInt( p_vlc, "mmxext" ) )
427         p_vlc->i_cpu &= ~CPU_CAPABILITY_MMXEXT;
428     if( !config_GetInt( p_vlc, "sse" ) )
429         p_vlc->i_cpu &= ~CPU_CAPABILITY_SSE;
430 #endif
431 #if defined( __powerpc__ ) || defined( SYS_DARWIN )
432     if( !config_GetInt( p_vlc, "altivec" ) )
433         p_vlc->i_cpu &= ~CPU_CAPABILITY_ALTIVEC;
434 #endif
435
436 #define PRINT_CAPABILITY( capability, string )                              \
437     if( p_vlc->i_cpu & capability )                                         \
438     {                                                                       \
439         strncat( p_capabilities, string " ",                                \
440                  sizeof(p_capabilities) - strlen(p_capabilities) );         \
441         p_capabilities[sizeof(p_capabilities) - 1] = '\0';                  \
442     }
443
444     p_capabilities[0] = '\0';
445     PRINT_CAPABILITY( CPU_CAPABILITY_486, "486" );
446     PRINT_CAPABILITY( CPU_CAPABILITY_586, "586" );
447     PRINT_CAPABILITY( CPU_CAPABILITY_PPRO, "Pentium Pro" );
448     PRINT_CAPABILITY( CPU_CAPABILITY_MMX, "MMX" );
449     PRINT_CAPABILITY( CPU_CAPABILITY_3DNOW, "3DNow!" );
450     PRINT_CAPABILITY( CPU_CAPABILITY_MMXEXT, "MMXEXT" );
451     PRINT_CAPABILITY( CPU_CAPABILITY_SSE, "SSE" );
452     PRINT_CAPABILITY( CPU_CAPABILITY_ALTIVEC, "AltiVec" );
453     PRINT_CAPABILITY( CPU_CAPABILITY_FPU, "FPU" );
454     msg_Dbg( p_vlc, "CPU has capabilities %s", p_capabilities );
455
456     /*
457      * Choose the best memcpy module
458      */
459     p_vlc->p_memcpy_module = module_Need( p_vlc, "memcpy", "$memcpy" );
460
461     if( p_vlc->pf_memcpy == NULL )
462     {
463         p_vlc->pf_memcpy = memcpy;
464     }
465
466     if( p_vlc->pf_memset == NULL )
467     {
468         p_vlc->pf_memset = memset;
469     }
470
471     /*
472      * Initialize shared resources and libraries
473      */
474     if( config_GetInt( p_vlc, "network-channel" )
475          && network_ChannelCreate( p_vlc ) )
476     {
477         /* On error during Channels initialization, switch off channels */
478         msg_Warn( p_vlc,
479                   "channels initialization failed, deactivating channels" );
480         config_PutInt( p_vlc, "network-channel", VLC_FALSE );
481     }
482
483     /*
484      * Initialize playlist and get commandline files
485      */
486     p_playlist = playlist_Create( p_vlc );
487     if( !p_playlist )
488     {
489         msg_Err( p_vlc, "playlist initialization failed" );
490         if( p_vlc->p_memcpy_module != NULL )
491         {
492             module_Unneed( p_vlc, p_vlc->p_memcpy_module );
493         }
494         module_EndBank( p_vlc );
495         msg_Destroy( p_vlc );
496         return VLC_EGENERIC;
497     }
498
499     /* Update the handle status */
500     p_vlc->i_status = VLC_STATUS_STOPPED;
501
502     /*
503      * Get input filenames given as commandline arguments
504      */
505     GetFilenames( p_vlc, i_argc, ppsz_argv );
506
507     return VLC_SUCCESS;
508 }
509
510 /*****************************************************************************
511  * vlc_add_intf: add an interface
512  *****************************************************************************
513  * This function opens an interface plugin and runs it. If b_block is set
514  * to 0, vlc_add_intf will return immediately and let the interface run in a
515  * separate thread. If b_block is set to 1, vlc_add_intf will continue until
516  * user requests to quit.
517  *****************************************************************************/
518 vlc_error_t vlc_add_intf( const char *psz_module, vlc_bool_t b_block )
519 {
520     return vlc_add_intf_r( ( i_vlc == 1 ) ? pp_vlc[0] : NULL,
521                            psz_module, b_block );
522 }
523
524 vlc_error_t vlc_add_intf_r( vlc_t *p_vlc, const char *psz_module,
525                                           vlc_bool_t b_block )
526 {
527     vlc_error_t err;
528     intf_thread_t *p_intf;
529     char *psz_oldmodule = NULL;
530
531     /* Check that the handle is valid */
532     if( !p_vlc || p_vlc->i_status != VLC_STATUS_RUNNING )
533     {
534         fprintf( stderr, "error: invalid status (!RUNNING)\n" );
535         return VLC_ESTATUS;
536     }
537
538     if( psz_module )
539     {
540         psz_oldmodule = config_GetPsz( p_vlc, "intf" );
541         config_PutPsz( p_vlc, "intf", psz_module );
542     }
543
544     /* Try to create the interface */
545     p_intf = intf_Create( p_vlc );
546
547     if( psz_module )
548     {
549         config_PutPsz( p_vlc, "intf", psz_oldmodule );
550         if( psz_oldmodule )
551         {
552             free( psz_oldmodule );
553         }
554     }
555
556     if( p_intf == NULL )
557     {
558         msg_Err( p_vlc, "interface initialization failed" );
559         return VLC_EGENERIC;
560     }
561
562     /* Try to run the interface */
563     p_intf->b_block = b_block;
564     err = intf_RunThread( p_intf );
565     if( err )
566     {
567         vlc_object_detach( p_intf );
568         intf_Destroy( p_intf );
569         return err;
570     }
571
572     return VLC_SUCCESS;
573 }
574
575 /*****************************************************************************
576  * vlc_destroy: stop playing and destroy everything.
577  *****************************************************************************
578  * This function requests the running threads to finish, waits for their
579  * termination, and destroys their structure.
580  *****************************************************************************/
581 vlc_error_t vlc_destroy( void )
582 {
583     return vlc_destroy_r( ( i_vlc == 1 ) ? pp_vlc[0] : NULL );
584 }
585
586 vlc_error_t vlc_destroy_r( vlc_t *p_vlc )
587 {
588     int               i_index;
589
590     /* Check that the handle is valid */
591     if( !p_vlc || (p_vlc->i_status != VLC_STATUS_STOPPED
592                     && p_vlc->i_status != VLC_STATUS_CREATED) )
593     {
594         fprintf( stderr, "error: invalid status "
595                          "(!STOPPED&&!CREATED)\n" );
596         return VLC_ESTATUS;
597     }
598
599     if( p_vlc->i_status == VLC_STATUS_STOPPED )
600     {
601         /*
602          * Go back into channel 0 which is the network
603          */
604         if( config_GetInt( p_vlc, "network-channel" ) && p_vlc->p_channel )
605         {
606             network_ChannelJoin( p_vlc, COMMON_CHANNEL );
607         }
608     
609         /*
610          * Free allocated memory
611          */
612         if( p_vlc->p_memcpy_module != NULL )
613         {
614             module_Unneed( p_vlc, p_vlc->p_memcpy_module );
615         }
616     
617         free( p_vlc->psz_homedir );
618     
619         /*
620          * Free module bank
621          */
622         module_EndBank( p_vlc );
623     
624         /*
625          * System specific cleaning code
626          */
627         system_End( p_vlc );
628     
629         /*
630          * Terminate messages interface and program
631          */
632         msg_Destroy( p_vlc );
633
634         /* Update the handle status */
635         p_vlc->i_status = VLC_STATUS_CREATED;
636     }
637
638     /* Update the handle status, just in case */
639     p_vlc->i_status = VLC_STATUS_NONE;
640
641     /* Remove our structure from the global list */
642     vlc_mutex_lock( p_vlc->p_global_lock );
643     for( i_index = 0 ; i_index < i_vlc ; i_index++ )
644     {
645         if( pp_vlc[ i_index ] == p_vlc )
646         {
647             break;
648         }
649     }
650
651     if( i_index == i_vlc )
652     {
653         fprintf( stderr, "error: trying to unregister %p which is not in "
654                          "the list\n", (void *)p_vlc );
655         vlc_mutex_unlock( p_vlc->p_global_lock );
656         vlc_object_destroy( p_vlc );
657         return VLC_EGENERIC;
658     }
659
660     for( i_index++ ; i_index < i_vlc ; i_index++ )
661     {
662         pp_vlc[ i_index - 1 ] = pp_vlc[ i_index ];
663     }
664
665     i_vlc--;
666     if( i_vlc )
667     {
668         pp_vlc = realloc( pp_vlc, i_vlc * sizeof( vlc_t * ) );
669     }
670     else
671     {
672         free( pp_vlc );
673         pp_vlc = NULL;
674     }
675     vlc_mutex_unlock( p_vlc->p_global_lock );
676
677     /* Stop thread system: last one out please shut the door! */
678     vlc_threads_end( p_vlc );
679
680     /* Destroy mutexes */
681     vlc_mutex_destroy( &p_vlc->structure_lock );
682     vlc_mutex_destroy( &p_vlc->config_lock );
683
684     vlc_object_destroy( p_vlc );
685
686     return VLC_SUCCESS;
687 }
688
689 /*****************************************************************************
690  * vlc_die: ask vlc to die.
691  *****************************************************************************
692  * This function sets p_vlc->b_die to VLC_TRUE, but does not do any other
693  * task. It is your duty to call vlc_end and vlc_destroy afterwards.
694  *****************************************************************************/
695 vlc_error_t vlc_die( void )
696 {
697     return vlc_die_r( ( i_vlc == 1 ) ? pp_vlc[0] : NULL );
698 }
699
700 vlc_error_t vlc_die_r( vlc_t *p_vlc )
701 {
702     if( !p_vlc )
703     {
704         fprintf( stderr, "error: invalid status (!EXIST)\n" );
705         return VLC_ESTATUS;
706     }
707
708     p_vlc->b_die = VLC_TRUE;
709
710     return VLC_SUCCESS;
711 }
712
713 /*****************************************************************************
714  * vlc_status: return the current vlc status.
715  *****************************************************************************
716  * This function returns the current value of p_vlc->i_status.
717  *****************************************************************************/
718 vlc_status_t vlc_status( void )
719 {
720     return vlc_status_r( ( i_vlc == 1 ) ? pp_vlc[0] : NULL );
721 }
722
723 vlc_status_t vlc_status_r( vlc_t *p_vlc )
724 {
725     if( !p_vlc )
726     {
727         return VLC_STATUS_NONE;
728     }
729
730     return p_vlc->i_status;
731 }
732
733 /*****************************************************************************
734  * vlc_add_target: adds a target for playing.
735  *****************************************************************************
736  * This function adds psz_target to the current playlist. If a playlist does
737  * not exist, it will create one.
738  *****************************************************************************/
739 vlc_error_t vlc_add_target( const char *psz_target, int i_mode, int i_pos )
740 {
741     return vlc_add_target_r( ( i_vlc == 1 ) ? pp_vlc[0] : NULL,
742                              psz_target, i_mode, i_pos );
743 }
744
745 vlc_error_t vlc_add_target_r( vlc_t *p_vlc, const char *psz_target,
746                                             int i_mode, int i_pos )
747 {
748     vlc_error_t err;
749     playlist_t *p_playlist;
750
751     if( !p_vlc || ( p_vlc->i_status != VLC_STATUS_STOPPED
752                      && p_vlc->i_status != VLC_STATUS_RUNNING ) )
753     {
754         fprintf( stderr, "error: invalid status (!STOPPED&&!RUNNING)\n" );
755         return VLC_ESTATUS;
756     }
757
758     p_playlist = vlc_object_find( p_vlc, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
759
760     if( p_playlist == NULL )
761     {
762         msg_Dbg( p_vlc, "no playlist present, creating one" );
763         p_playlist = playlist_Create( p_vlc );
764
765         if( p_playlist == NULL )
766         {
767             return VLC_EGENERIC;
768         }
769
770         vlc_object_yield( p_playlist );
771     }
772
773     err = playlist_Add( p_playlist, psz_target, i_mode, i_pos );
774
775     vlc_object_release( p_playlist );
776
777     return err;
778 }
779
780 /*****************************************************************************
781  * vlc_set: set a vlc variable
782  *****************************************************************************
783  *
784  *****************************************************************************/
785 vlc_error_t vlc_set( const char *psz_var, const char *psz_val )
786 {
787     return vlc_set_r( ( i_vlc == 1 ) ? pp_vlc[0] : NULL, psz_var, psz_val );
788 }
789
790 vlc_error_t vlc_set_r( vlc_t *p_vlc, const char *psz_var, const char *psz_val )
791 {
792     module_config_t *p_config;
793
794     if( !p_vlc )
795     {
796         fprintf( stderr, "error: invalid status\n" );
797         return VLC_ESTATUS;
798     }
799
800     p_config = config_FindConfig( VLC_OBJECT(p_vlc), psz_var );
801
802     if( !p_config )
803     {
804         msg_Err( p_vlc, "option %s does not exist", psz_var );
805         return VLC_EGENERIC;
806     }
807
808     vlc_mutex_lock( p_config->p_lock );
809
810     switch( p_config->i_type )
811     {
812     case CONFIG_ITEM_BOOL:
813         if( psz_val && *psz_val )
814         {
815             if( !strcmp( psz_val, "off" ) || !strcmp( psz_val, "no" ) )
816             {
817                 p_config->i_value = VLC_FALSE;
818             }
819             else
820             {
821                 p_config->i_value = atoi( psz_val );
822             }
823         }
824         else
825         {
826             p_config->i_value = VLC_TRUE;
827         }
828         break;
829     case CONFIG_ITEM_INTEGER:
830         if( psz_val && *psz_val )
831         {
832             p_config->i_value = atoi( psz_val );
833         }
834         else
835         {
836             p_config->i_value = 0;
837         }
838         break;
839     case CONFIG_ITEM_FLOAT:
840         if( psz_val && *psz_val )
841         {
842             p_config->f_value = (float)atof( psz_val );
843         }
844         else
845         {
846             p_config->f_value = 0.0;
847         }
848         break;
849     case CONFIG_ITEM_STRING:
850     case CONFIG_ITEM_FILE:
851     case CONFIG_ITEM_MODULE:
852     default:
853         if( p_config->psz_value )
854         {
855             free( p_config->psz_value );
856         }
857
858         if( psz_val )
859         {
860             p_config->psz_value = strdup( psz_val );
861         }
862         else
863         {
864             p_config->psz_value = NULL;
865         }
866         break;
867     }
868
869     if( p_config->pf_callback )
870     {
871         vlc_mutex_unlock( p_config->p_lock );
872         p_config->pf_callback( VLC_OBJECT(p_vlc) );
873     }
874     else
875     {
876         vlc_mutex_unlock( p_config->p_lock );
877     }
878
879     return VLC_SUCCESS;
880 }
881
882 /* XXX: temporary hacks */
883
884 /*****************************************************************************
885  * vlc_play: play
886  *****************************************************************************/
887 vlc_error_t vlc_play( )
888 {
889     return vlc_play_r( ( i_vlc == 1 ) ? pp_vlc[0] : NULL );
890 }
891
892 vlc_error_t vlc_play_r( vlc_t *p_vlc )
893 {
894     playlist_t * p_playlist;
895
896     /* Check that the handle is valid */
897     if( !p_vlc || p_vlc->i_status != VLC_STATUS_STOPPED )
898     {
899         fprintf( stderr, "error: invalid status (!STOPPED)\n" );
900         return VLC_ESTATUS;
901     }
902
903     /* Update the handle status */
904     p_vlc->i_status = VLC_STATUS_RUNNING;
905
906     p_playlist = vlc_object_find( p_vlc, VLC_OBJECT_PLAYLIST, FIND_CHILD );
907
908     if( !p_playlist )
909     {
910         return VLC_EOBJECT;
911     }
912
913     vlc_mutex_lock( &p_playlist->object_lock );
914     if( p_playlist->i_size )
915     {
916         vlc_mutex_unlock( &p_playlist->object_lock );
917         playlist_Play( p_playlist );
918     }
919     else
920     {
921         vlc_mutex_unlock( &p_playlist->object_lock );
922     }
923
924     vlc_object_release( p_playlist );
925
926     return VLC_SUCCESS;
927 }
928
929 /*****************************************************************************
930  * vlc_stop: stop
931  *****************************************************************************/
932 vlc_error_t vlc_stop( )
933 {
934     return vlc_stop_r( ( i_vlc == 1 ) ? pp_vlc[0] : NULL );
935 }
936
937 vlc_error_t vlc_stop_r( vlc_t *p_vlc )
938 {
939     intf_thread_t *   p_intf;
940     playlist_t    *   p_playlist;
941     vout_thread_t *   p_vout;
942     aout_instance_t * p_aout;
943
944     /* Check that the handle is valid */
945     if( !p_vlc || ( p_vlc->i_status != VLC_STATUS_STOPPED
946                      && p_vlc->i_status != VLC_STATUS_RUNNING ) )
947     {
948         fprintf( stderr, "error: invalid status (!STOPPED&&!RUNNING)\n" );
949         return VLC_ESTATUS;
950     }
951
952     /*
953      * Ask the interfaces to stop and destroy them
954      */
955     msg_Dbg( p_vlc, "removing all interfaces" );
956     while( (p_intf = vlc_object_find( p_vlc, VLC_OBJECT_INTF, FIND_CHILD )) )
957     {
958         intf_StopThread( p_intf );
959         vlc_object_detach( p_intf );
960         vlc_object_release( p_intf );
961         intf_Destroy( p_intf );
962     }
963
964     /*
965      * Free playlists
966      */
967     msg_Dbg( p_vlc, "removing all playlists" );
968     while( (p_playlist = vlc_object_find( p_vlc, VLC_OBJECT_PLAYLIST,
969                                           FIND_CHILD )) )
970     {
971         vlc_object_detach( p_playlist );
972         vlc_object_release( p_playlist );
973         playlist_Destroy( p_playlist );
974     }
975
976     /*
977      * Free video outputs
978      */
979     msg_Dbg( p_vlc, "removing all video outputs" );
980     while( (p_vout = vlc_object_find( p_vlc, VLC_OBJECT_VOUT, FIND_CHILD )) )
981     {
982         vlc_object_detach( p_vout );
983         vlc_object_release( p_vout );
984         vout_DestroyThread( p_vout );
985     }
986
987     /*
988      * Free audio outputs
989      */
990     msg_Dbg( p_vlc, "removing all audio outputs" );
991     while( (p_aout = vlc_object_find( p_vlc, VLC_OBJECT_AOUT, FIND_CHILD )) )
992     {
993         vlc_object_detach( (vlc_object_t *)p_aout );
994         vlc_object_release( (vlc_object_t *)p_aout );
995         aout_Delete( p_aout );
996     }
997
998     /* Update the handle status */
999     p_vlc->i_status = VLC_STATUS_STOPPED;
1000
1001     return VLC_SUCCESS;
1002 }
1003
1004 /*****************************************************************************
1005  * vlc_pause: toggle pause
1006  *****************************************************************************/
1007 vlc_error_t vlc_pause( )
1008 {
1009     return vlc_pause_r( ( i_vlc == 1 ) ? pp_vlc[0] : NULL );
1010 }
1011
1012 vlc_error_t vlc_pause_r( vlc_t *p_vlc )
1013 {
1014     input_thread_t *p_input;
1015
1016     p_input = vlc_object_find( p_vlc, VLC_OBJECT_INPUT, FIND_CHILD );
1017
1018     if( !p_input )
1019     {
1020         return VLC_EOBJECT;
1021     }
1022
1023     input_SetStatus( p_input, INPUT_STATUS_PAUSE );
1024     vlc_object_release( p_input );
1025
1026     return VLC_SUCCESS;
1027 }
1028
1029 /*****************************************************************************
1030  * vlc_fullscreen: toggle fullscreen mode
1031  *****************************************************************************/
1032 vlc_error_t vlc_fullscreen( )
1033 {
1034     return vlc_fullscreen_r( ( i_vlc == 1 ) ? pp_vlc[0] : NULL );
1035 }
1036
1037 vlc_error_t vlc_fullscreen_r( vlc_t *p_vlc )
1038 {
1039     vout_thread_t *p_vout;
1040
1041     p_vout = vlc_object_find( p_vlc, VLC_OBJECT_VOUT, FIND_CHILD );
1042
1043     if( !p_vout )
1044     {
1045         return VLC_EOBJECT;
1046     }
1047
1048     p_vout->i_changes |= VOUT_FULLSCREEN_CHANGE;
1049     vlc_object_release( p_vout );
1050
1051     return VLC_SUCCESS;
1052 }
1053
1054 /* following functions are local */
1055
1056 /*****************************************************************************
1057  * GetFilenames: parse command line options which are not flags
1058  *****************************************************************************
1059  * Parse command line for input files.
1060  *****************************************************************************/
1061 static int GetFilenames( vlc_t *p_vlc, int i_argc, char *ppsz_argv[] )
1062 {
1063     int i_opt;
1064
1065     /* We assume that the remaining parameters are filenames */
1066     for( i_opt = optind; i_opt < i_argc; i_opt++ )
1067     {
1068         vlc_add_target_r( p_vlc, ppsz_argv[ i_opt ],
1069                           PLAYLIST_APPEND | PLAYLIST_GO, PLAYLIST_END );
1070     }
1071
1072     return VLC_SUCCESS;
1073 }
1074
1075 /*****************************************************************************
1076  * Usage: print program usage
1077  *****************************************************************************
1078  * Print a short inline help. Message interface is initialized at this stage.
1079  *****************************************************************************/
1080 static void Usage( vlc_t *p_this, const char *psz_module_name )
1081 {
1082 #define FORMAT_STRING "      --%s%s%s%s%s%s%s %s%s\n"
1083     /* option name -------------'     | | | |  | |
1084      * <bra --------------------------' | | |  | |
1085      * option type or "" ---------------' | |  | |
1086      * ket> ------------------------------' |  | |
1087      * padding spaces ----------------------'  | |
1088      * comment --------------------------------' |
1089      * comment suffix ---------------------------'
1090      *
1091      * The purpose of having bra and ket is that we might i18n them as well.
1092      */
1093 #define LINE_START 8
1094 #define PADDING_SPACES 25
1095     vlc_list_t *p_list;
1096     module_t **pp_parser;
1097     module_config_t *p_item;
1098     char psz_spaces[PADDING_SPACES+LINE_START+1];
1099     char psz_format[sizeof(FORMAT_STRING)];
1100
1101     memset( psz_spaces, ' ', PADDING_SPACES+LINE_START );
1102     psz_spaces[PADDING_SPACES+LINE_START] = '\0';
1103
1104     strcpy( psz_format, FORMAT_STRING );
1105
1106 #ifdef WIN32
1107     ShowConsole();
1108 #endif
1109
1110     /* List all modules */
1111     p_list = vlc_list_find( p_this, VLC_OBJECT_MODULE, FIND_ANYWHERE );
1112
1113     /* Enumerate the config for each module */
1114     for( pp_parser = (module_t **)p_list->pp_objects ;
1115          *pp_parser ;
1116          pp_parser++ )
1117     {
1118         vlc_bool_t b_help_module;
1119
1120         if( psz_module_name && strcmp( psz_module_name,
1121                                        (*pp_parser)->psz_object_name ) )
1122         {
1123             continue;
1124         }
1125
1126         /* Ignore modules without config options */
1127         if( !(*pp_parser)->i_config_items )
1128         {
1129             continue;
1130         }
1131
1132         b_help_module = !strcmp( "help", (*pp_parser)->psz_object_name );
1133
1134         /* Print module options */
1135         for( p_item = (*pp_parser)->p_config;
1136              p_item->i_type != CONFIG_HINT_END;
1137              p_item++ )
1138         {
1139             char *psz_bra = NULL, *psz_type = NULL, *psz_ket = NULL;
1140             char *psz_suf = "", *psz_prefix = NULL;
1141             int i;
1142
1143             switch( p_item->i_type )
1144             {
1145             case CONFIG_HINT_CATEGORY:
1146             case CONFIG_HINT_USAGE:
1147                 fprintf( stderr, " %s\n", p_item->psz_text );
1148                 break;
1149
1150             case CONFIG_ITEM_STRING:
1151             case CONFIG_ITEM_FILE:
1152             case CONFIG_ITEM_MODULE: /* We could also have "=<" here */
1153                 if( !p_item->ppsz_list )
1154                 {
1155                     psz_bra = " <"; psz_type = _("string"); psz_ket = ">";
1156                     break;
1157                 }
1158                 else
1159                 {
1160                     psz_bra = " [";
1161                     psz_type = malloc( 1000 );
1162                     memset( psz_type, 0, 1000 );
1163                     for( i=0; p_item->ppsz_list[i]; i++ )
1164                     {
1165                         strcat( psz_type, p_item->ppsz_list[i] );
1166                         strcat( psz_type, "|" );
1167                     }
1168                     psz_type[ strlen( psz_type ) - 1 ] = '\0';
1169                     psz_ket = "]";
1170                     break;
1171                 }
1172             case CONFIG_ITEM_INTEGER:
1173                 psz_bra = " <"; psz_type = _("integer"); psz_ket = ">";
1174                 break;
1175             case CONFIG_ITEM_FLOAT:
1176                 psz_bra = " <"; psz_type = _("float"); psz_ket = ">";
1177                 break;
1178             case CONFIG_ITEM_BOOL:
1179                 psz_bra = ""; psz_type = ""; psz_ket = "";
1180                 if( !b_help_module )
1181                 {
1182                     psz_suf = p_item->i_value ? _(" (default enabled)") :
1183                                                 _(" (default disabled)");
1184                 }
1185                 break;
1186             }
1187
1188             /* Add short option if any */
1189             if( p_item->i_short )
1190             {
1191                 psz_format[2] = '-';
1192                 psz_format[3] = p_item->i_short;
1193                 psz_format[4] = ',';
1194             }
1195             else
1196             {
1197                 psz_format[2] = ' ';
1198                 psz_format[3] = ' ';
1199                 psz_format[4] = ' ';
1200             }
1201
1202             if( psz_type )
1203             {
1204                 i = PADDING_SPACES - strlen( p_item->psz_name )
1205                      - strlen( psz_bra ) - strlen( psz_type )
1206                      - strlen( psz_ket ) - 1;
1207                 if( p_item->i_type == CONFIG_ITEM_BOOL
1208                      && !b_help_module )
1209                 {
1210                     /* If option is of type --foo-bar, we print its counterpart
1211                      * as --no-foo-bar, but if it is of type --foobar (without
1212                      * dashes in the name) we print it as --nofoobar. Both
1213                      * values are of course valid, only the display changes. */
1214                     vlc_bool_t b_dash = VLC_FALSE;
1215                     psz_prefix = p_item->psz_name;
1216                     while( *psz_prefix )
1217                     {
1218                         if( *psz_prefix++ == '-' )
1219                         {
1220                             b_dash = VLC_TRUE;
1221                             break;
1222                         }
1223                     }
1224
1225                     if( b_dash )
1226                     {
1227                         psz_prefix = ", --no-";
1228                         i -= strlen( p_item->psz_name ) + strlen( ", --no-" );
1229                     }
1230                     else
1231                     {
1232                         psz_prefix = ", --no";
1233                         i -= strlen( p_item->psz_name ) + strlen( ", --no" );
1234                     }
1235                 }
1236
1237                 if( i < 0 )
1238                 {
1239                     i = 0;
1240                     psz_spaces[i] = '\n';
1241                 }
1242                 else
1243                 {
1244                     psz_spaces[i] = '\0';
1245                 }
1246
1247                 if( p_item->i_type == CONFIG_ITEM_BOOL &&
1248                     !b_help_module )
1249                 {
1250                     fprintf( stderr, psz_format, p_item->psz_name, psz_prefix,
1251                              p_item->psz_name, psz_bra, psz_type, psz_ket,
1252                              psz_spaces, p_item->psz_text, psz_suf );
1253                 }
1254                 else
1255                 {
1256                     fprintf( stderr, psz_format, p_item->psz_name, "", "",
1257                              psz_bra, psz_type, psz_ket, psz_spaces,
1258                              p_item->psz_text, psz_suf );
1259                 }
1260                 psz_spaces[i] = ' ';
1261                 if ( p_item->ppsz_list )
1262                 {
1263                     free( psz_type );
1264                 }
1265             }
1266         }
1267     }
1268
1269     /* Release the module list */
1270     vlc_list_release( p_list );
1271
1272 #ifdef WIN32        /* Pause the console because it's destroyed when we exit */
1273         fprintf( stderr, _("\nPress the RETURN key to continue...\n") );
1274         getchar();
1275 #endif
1276 }
1277
1278 /*****************************************************************************
1279  * ListModules: list the available modules with their description
1280  *****************************************************************************
1281  * Print a list of all available modules (builtins and plugins) and a short
1282  * description for each one.
1283  *****************************************************************************/
1284 static void ListModules( vlc_t *p_this )
1285 {
1286     vlc_list_t *p_list;
1287     module_t **pp_parser;
1288     char psz_spaces[22];
1289
1290     memset( psz_spaces, ' ', 22 );
1291
1292 #ifdef WIN32
1293     ShowConsole();
1294 #endif
1295
1296     /* Usage */
1297     fprintf( stderr, _("Usage: %s [options] [items]...\n\n"),
1298                      p_this->p_vlc->psz_object_name );
1299
1300     fprintf( stderr, _("[module]              [description]\n") );
1301
1302     /* List all modules */
1303     p_list = vlc_list_find( p_this, VLC_OBJECT_MODULE, FIND_ANYWHERE );
1304
1305     /* Enumerate each module */
1306     for( pp_parser = (module_t **)p_list->pp_objects ;
1307          *pp_parser ;
1308          pp_parser++ )
1309     {
1310         int i;
1311
1312         /* Nasty hack, but right now I'm too tired to think about a nice
1313          * solution */
1314         i = 22 - strlen( (*pp_parser)->psz_object_name ) - 1;
1315         if( i < 0 ) i = 0;
1316         psz_spaces[i] = 0;
1317
1318         fprintf( stderr, "  %s%s %s\n", (*pp_parser)->psz_object_name,
1319                          psz_spaces, (*pp_parser)->psz_longname );
1320
1321         psz_spaces[i] = ' ';
1322     }
1323
1324     vlc_list_release( p_list );
1325
1326 #ifdef WIN32        /* Pause the console because it's destroyed when we exit */
1327         fprintf( stderr, _("\nPress the RETURN key to continue...\n") );
1328         getchar();
1329 #endif
1330 }
1331
1332 /*****************************************************************************
1333  * Version: print complete program version
1334  *****************************************************************************
1335  * Print complete program version and build number.
1336  *****************************************************************************/
1337 static void Version( void )
1338 {
1339 #ifdef WIN32
1340     ShowConsole();
1341 #endif
1342
1343     fprintf( stderr, VERSION_MESSAGE "\n" );
1344     fprintf( stderr,
1345       _("This program comes with NO WARRANTY, to the extent permitted by "
1346         "law.\nYou may redistribute it under the terms of the GNU General "
1347         "Public License;\nsee the file named COPYING for details.\n"
1348         "Written by the VideoLAN team at Ecole Centrale, Paris.\n") );
1349
1350 #ifdef WIN32        /* Pause the console because it's destroyed when we exit */
1351     fprintf( stderr, _("\nPress the RETURN key to continue...\n") );
1352     getchar();
1353 #endif
1354 }
1355
1356 /*****************************************************************************
1357  * ShowConsole: On Win32, create an output console for debug messages
1358  *****************************************************************************
1359  * This function is useful only on Win32.
1360  *****************************************************************************/
1361 #ifdef WIN32 /*  */
1362 static void ShowConsole( void )
1363 {
1364     AllocConsole();
1365     freopen( "CONOUT$", "w", stdout );
1366     freopen( "CONOUT$", "w", stderr );
1367     freopen( "CONIN$", "r", stdin );
1368     return;
1369 }
1370 #endif
1371