1 /*****************************************************************************
2 * help.c: command line help
3 *****************************************************************************
4 * Copyright (C) 1998-2011 VLC authors and VideoLAN
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU Lesser General Public License as published by
8 * the Free Software Foundation; either version 2.1 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
19 *****************************************************************************/
29 #include <vlc_common.h>
30 #include <vlc_charset.h>
31 #include <vlc_modules.h>
32 #include <vlc_plugin.h>
33 #include "modules/modules.h"
34 #include "config/configuration.h"
37 #if defined( _WIN32 ) && !VLC_WINSTORE_APP
38 static void ShowConsole (void);
39 static void PauseConsole (void);
41 # define ShowConsole() (void)0
42 # define PauseConsole() (void)0
46 static void Help (vlc_object_t *, const char *);
47 static void Usage (vlc_object_t *, const char *);
48 static void Version (void);
49 static void ListModules (vlc_object_t *, bool);
50 static int ConsoleWidth (void);
53 * Checks for help command line options such as --help or --version.
54 * If one is found, print the corresponding text.
55 * \return true if a command line options caused some help message to be
56 * printed, false otherwise.
58 bool config_PrintHelp (vlc_object_t *obj)
62 /* Check for short help option */
63 if (var_InheritBool (obj, "help"))
69 /* Check for version option */
70 if (var_InheritBool (obj, "version"))
76 /* Check for help on modules */
77 str = var_InheritString (obj, "module");
85 /* Check for full help option */
86 if (var_InheritBool (obj, "full-help"))
88 var_Create (obj, "advanced", VLC_VAR_BOOL);
89 var_SetBool (obj, "advanced", true);
90 var_Create (obj, "help-verbose", VLC_VAR_BOOL);
91 var_SetBool (obj, "help-verbose", true);
92 Help (obj, "full-help");
96 /* Check for long help option */
97 if (var_InheritBool (obj, "longhelp"))
99 Help (obj, "longhelp");
103 /* Check for module list option */
104 if (var_InheritBool (obj, "list"))
106 ListModules (obj, false );
110 if (var_InheritBool (obj, "list-verbose"))
112 ListModules (obj, true);
119 /*****************************************************************************
120 * Help: print program help
121 *****************************************************************************
122 * Print a short inline help. Message interface is initialized at this stage.
123 *****************************************************************************/
124 static inline void print_help_on_full_help( void )
126 utf8_fprintf( stdout, "\n" );
127 utf8_fprintf( stdout, "%s\n", _("To get exhaustive help, use '-H'.") );
130 static const char vlc_usage[] = N_(
131 "Usage: %s [options] [stream] ...\n"
132 "You can specify multiple streams on the commandline.\n"
133 "They will be enqueued in the playlist.\n"
134 "The first item specified will be played first.\n"
137 " --option A global option that is set for the duration of the program.\n"
138 " -option A single letter version of a global --option.\n"
139 " :option An option that only applies to the stream directly before it\n"
140 " and that overrides previous settings.\n"
142 "Stream MRL syntax:\n"
143 " [[access][/demux]://]URL[#[title][:chapter][-[title][:chapter]]]\n"
144 " [:option=value ...]\n"
146 " Many of the global --options can also be used as MRL specific :options.\n"
147 " Multiple :option=value pairs can be specified.\n"
150 " file:///path/file Plain media file\n"
151 " http://host[:port]/file HTTP URL\n"
152 " ftp://host[:port]/file FTP URL\n"
153 " mms://host[:port]/file MMS URL\n"
154 " screen:// Screen capture\n"
155 " dvd://[device] DVD device\n"
156 " vcd://[device] VCD device\n"
157 " cdda://[device] Audio CD device\n"
158 " udp://[[<source address>]@[<bind address>][:<bind port>]]\n"
159 " UDP stream sent by a streaming server\n"
160 " vlc://pause:<seconds> Pause the playlist for a certain time\n"
161 " vlc://quit Special item to quit VLC\n"
164 static void Help (vlc_object_t *p_this, char const *psz_help_name)
168 if( psz_help_name && !strcmp( psz_help_name, "help" ) )
170 utf8_fprintf( stdout, _(vlc_usage), "vlc" );
171 Usage( p_this, "=main" );
172 print_help_on_full_help();
174 else if( psz_help_name && !strcmp( psz_help_name, "longhelp" ) )
176 utf8_fprintf( stdout, _(vlc_usage), "vlc" );
177 Usage( p_this, NULL );
178 print_help_on_full_help();
180 else if( psz_help_name && !strcmp( psz_help_name, "full-help" ) )
182 utf8_fprintf( stdout, _(vlc_usage), "vlc" );
183 Usage( p_this, NULL );
185 else if( psz_help_name )
187 Usage( p_this, psz_help_name );
193 /*****************************************************************************
194 * Usage: print module usage
195 *****************************************************************************
196 * Print a short inline help. Message interface is initialized at this stage.
197 *****************************************************************************/
198 # define COL(x) "\033[" #x ";1m"
200 # define GREEN COL(32)
201 # define YELLOW COL(33)
202 # define BLUE COL(34)
203 # define MAGENTA COL(35)
204 # define CYAN COL(36)
205 # define WHITE COL(0)
206 # define GRAY "\033[0m"
208 print_help_section( const module_t *m, const module_config_t *p_item,
209 bool b_color, bool b_description )
211 if( !p_item ) return;
214 utf8_fprintf( stdout, RED" %s:\n"GRAY,
215 module_gettext( m, p_item->psz_text ) );
216 if( b_description && p_item->psz_longtext )
217 utf8_fprintf( stdout, MAGENTA" %s\n"GRAY,
218 module_gettext( m, p_item->psz_longtext ) );
222 utf8_fprintf( stdout, " %s:\n",
223 module_gettext( m, p_item->psz_text ) );
224 if( b_description && p_item->psz_longtext )
225 utf8_fprintf( stdout, " %s\n",
226 module_gettext(m, p_item->psz_longtext ) );
230 static void Usage (vlc_object_t *p_this, char const *psz_search)
232 #define FORMAT_STRING " %s --%s%s%s%s%s%s%s "
233 /* short option ------' | | | | | | |
234 * option name ------------' | | | | | |
235 * <bra ---------------------' | | | | |
236 * option type or "" ----------' | | | |
237 * ket> -------------------------' | | |
238 * padding spaces -----------------' | |
239 * comment --------------------------' |
240 * comment suffix ---------------------'
242 * The purpose of having bra and ket is that we might i18n them as well.
245 #define COLOR_FORMAT_STRING (WHITE" %s --%s"YELLOW"%s%s%s%s%s%s "GRAY)
246 #define COLOR_FORMAT_STRING_BOOL (WHITE" %s --%s%s%s%s%s%s%s "GRAY)
249 #define PADDING_SPACES 25
251 # define OPTION_VALUE_SEP "="
253 # define OPTION_VALUE_SEP " "
255 char psz_spaces_text[PADDING_SPACES+LINE_START+1];
256 char psz_spaces_longtext[LINE_START+3];
257 char psz_format[sizeof(COLOR_FORMAT_STRING)];
258 char psz_format_bool[sizeof(COLOR_FORMAT_STRING_BOOL)];
259 char psz_buffer[10000];
261 int i_width = ConsoleWidth() - (PADDING_SPACES+LINE_START+1);
262 int i_width_description = i_width + PADDING_SPACES - 1;
263 bool b_advanced = var_InheritBool( p_this, "advanced" );
264 bool b_description = var_InheritBool( p_this, "help-verbose" );
265 bool b_description_hack;
266 bool b_color = var_InheritBool( p_this, "color" );
267 bool b_has_advanced = false;
268 bool b_found = false;
269 unsigned i_only_advanced = 0; /* Number of modules ignored because they
270 * only have advanced options */
271 bool b_strict = psz_search && *psz_search == '=';
272 if( b_strict ) psz_search++;
274 memset( psz_spaces_text, ' ', PADDING_SPACES+LINE_START );
275 psz_spaces_text[PADDING_SPACES+LINE_START] = '\0';
276 memset( psz_spaces_longtext, ' ', LINE_START+2 );
277 psz_spaces_longtext[LINE_START+2] = '\0';
281 b_color = false; // don't put color control codes in a .txt file
285 strcpy( psz_format, COLOR_FORMAT_STRING );
286 strcpy( psz_format_bool, COLOR_FORMAT_STRING_BOOL );
290 strcpy( psz_format, FORMAT_STRING );
291 strcpy( psz_format_bool, FORMAT_STRING );
294 /* List all modules */
296 module_t **list = module_list_get (&count);
298 /* Enumerate the config for each module */
299 for (size_t i = 0; i < count; i++)
301 module_t *p_parser = list[i];
302 module_config_t *p_item = NULL;
303 module_config_t *p_section = NULL;
304 module_config_t *p_end = p_parser->p_config + p_parser->confsize;
305 const char *objname = module_get_object (p_parser);
308 ( b_strict ? strcmp( objname, psz_search )
309 : !strstr( objname, psz_search ) ) )
311 char *const *pp_shortcuts = p_parser->pp_shortcuts;
313 for( i = 0; i < p_parser->i_shortcuts; i++ )
315 if( b_strict ? !strcmp( psz_search, pp_shortcuts[i] )
316 : !!strstr( pp_shortcuts[i], psz_search ) )
319 if( i == p_parser->i_shortcuts )
323 /* Ignore modules without config options */
324 if( !p_parser->i_config_items )
329 /* Ignore modules with only advanced config options if requested */
332 for( p_item = p_parser->p_config;
336 if( CONFIG_ITEM(p_item->i_type) &&
337 !p_item->b_advanced && !p_item->b_removed ) break;
340 if( p_item == p_end )
349 /* Print name of module */
350 if( strcmp( "main", objname ) )
353 utf8_fprintf( stdout, "\n " GREEN "%s" GRAY " (%s)\n",
354 module_gettext( p_parser, p_parser->psz_longname ),
357 utf8_fprintf( stdout, "\n %s\n",
358 module_gettext(p_parser, p_parser->psz_longname ) );
360 if( p_parser->psz_help )
363 utf8_fprintf( stdout, CYAN" %s\n"GRAY,
364 module_gettext( p_parser, p_parser->psz_help ) );
366 utf8_fprintf( stdout, " %s\n",
367 module_gettext( p_parser, p_parser->psz_help ) );
370 /* Print module options */
371 for( p_item = p_parser->p_config;
375 char *psz_text, *psz_spaces = psz_spaces_text;
376 const char *psz_bra = NULL, *psz_type = NULL, *psz_ket = NULL;
377 const char *psz_suf = "", *psz_prefix = NULL;
381 /* Skip removed options */
382 if( p_item->b_removed )
386 /* Skip advanced options if requested */
387 if( p_item->b_advanced && !b_advanced )
389 b_has_advanced = true;
393 switch( CONFIG_CLASS(p_item->i_type) )
395 case 0: // hint class
396 switch( p_item->i_type )
398 case CONFIG_HINT_CATEGORY:
399 case CONFIG_HINT_USAGE:
400 if( !strcmp( "main", objname ) )
403 utf8_fprintf( stdout, GREEN "\n %s\n" GRAY,
404 module_gettext( p_parser, p_item->psz_text ) );
406 utf8_fprintf( stdout, "\n %s\n",
407 module_gettext( p_parser, p_item->psz_text ) );
409 if( b_description && p_item->psz_longtext )
412 utf8_fprintf( stdout, CYAN " %s\n" GRAY,
413 module_gettext( p_parser, p_item->psz_longtext ) );
415 utf8_fprintf( stdout, " %s\n",
416 module_gettext( p_parser, p_item->psz_longtext ) );
420 case CONFIG_HINT_SUBCATEGORY:
421 if( strcmp( "main", objname ) )
429 case CONFIG_ITEM_STRING:
430 print_help_section( p_parser, p_section, b_color,
433 psz_bra = OPTION_VALUE_SEP "<";
434 psz_type = _("string");
437 if( p_item->list_count )
439 psz_bra = OPTION_VALUE_SEP "{";
440 psz_type = psz_buffer;
441 psz_buffer[0] = '\0';
442 for( i = 0; i < p_item->list_count; i++ )
444 if( i ) strcat( psz_buffer, "," );
445 strcat( psz_buffer, p_item->list.psz[i] );
450 case CONFIG_ITEM_INTEGER:
451 print_help_section( p_parser, p_section, b_color,
454 psz_bra = OPTION_VALUE_SEP "<";
455 psz_type = _("integer");
458 if( p_item->min.i || p_item->max.i )
460 sprintf( psz_buffer, "%s [%"PRId64" .. %"PRId64"]",
461 psz_type, p_item->min.i, p_item->max.i );
462 psz_type = psz_buffer;
465 if( p_item->list_count )
467 psz_bra = OPTION_VALUE_SEP "{";
468 psz_type = psz_buffer;
469 psz_buffer[0] = '\0';
470 for( i = 0; i < p_item->list_count; i++ )
472 if( i ) strcat( psz_buffer, ", " );
473 sprintf( psz_buffer + strlen(psz_buffer), "%i (%s)",
475 module_gettext( p_parser, p_item->list_text[i] ) );
480 case CONFIG_ITEM_FLOAT:
481 print_help_section( p_parser, p_section, b_color,
484 psz_bra = OPTION_VALUE_SEP "<";
485 psz_type = _("float");
487 if( p_item->min.f || p_item->max.f )
489 sprintf( psz_buffer, "%s [%f .. %f]", psz_type,
490 p_item->min.f, p_item->max.f );
491 psz_type = psz_buffer;
494 case CONFIG_ITEM_BOOL:
495 print_help_section( p_parser, p_section, b_color,
498 psz_bra = ""; psz_type = ""; psz_ket = "";
499 psz_suf = p_item->value.i ? _(" (default enabled)") :
500 _(" (default disabled)");
509 /* Add short option if any */
510 if( p_item->i_short )
512 sprintf( psz_short, "-%c,", p_item->i_short );
516 strcpy( psz_short, " " );
519 i = PADDING_SPACES - strlen( p_item->psz_name )
520 - strlen( psz_bra ) - strlen( psz_type )
521 - strlen( psz_ket ) - 1;
523 if( CONFIG_CLASS(p_item->i_type) == CONFIG_ITEM_BOOL )
525 psz_prefix = ", --no-";
526 i -= strlen( p_item->psz_name ) + strlen( psz_prefix );
531 psz_spaces[0] = '\n';
536 psz_spaces[i] = '\0';
539 if( CONFIG_CLASS(p_item->i_type) == CONFIG_ITEM_BOOL )
541 utf8_fprintf( stdout, psz_format_bool, psz_short,
542 p_item->psz_name, psz_prefix, p_item->psz_name,
543 psz_bra, psz_type, psz_ket, psz_spaces );
547 utf8_fprintf( stdout, psz_format, psz_short, p_item->psz_name,
548 "", "", psz_bra, psz_type, psz_ket, psz_spaces );
553 /* We wrap the rest of the output */
554 sprintf( psz_buffer, "%s%s", module_gettext( p_parser, p_item->psz_text ),
556 b_description_hack = b_description;
559 psz_text = psz_buffer;
560 i_cur_width = b_description && !b_description_hack
561 ? i_width_description
563 if( !*psz_text ) strcpy(psz_text, " ");
566 char *psz_parser, *psz_word;
567 size_t i_end = strlen( psz_text );
569 /* If the remaining text fits in a line, print it. */
570 if( i_end <= i_cur_width )
574 if( !b_description || b_description_hack )
575 utf8_fprintf( stdout, BLUE"%s\n"GRAY, psz_text );
577 utf8_fprintf( stdout, "%s\n", psz_text );
581 utf8_fprintf( stdout, "%s\n", psz_text );
586 /* Otherwise, eat as many words as possible */
587 psz_parser = psz_text;
590 psz_word = psz_parser;
591 psz_parser = strchr( psz_word, ' ' );
592 /* If no space was found, we reached the end of the text
593 * block; otherwise, we skip the space we just found. */
594 psz_parser = psz_parser ? psz_parser + 1
597 } while( (size_t)(psz_parser - psz_text) <= i_cur_width );
599 /* We cut a word in one of these cases:
600 * - it's the only word in the line and it's too long.
601 * - we used less than 80% of the width and the word we are
602 * going to wrap is longer than 40% of the width, and even
603 * if the word would have fit in the next line. */
604 if( psz_word == psz_text
605 || ( (size_t)(psz_word - psz_text) < 80 * i_cur_width / 100
606 && (size_t)(psz_parser - psz_word) > 40 * i_cur_width / 100 ) )
608 char c = psz_text[i_cur_width];
609 psz_text[i_cur_width] = '\0';
612 if( !b_description || b_description_hack )
613 utf8_fprintf( stdout, BLUE"%s\n%s"GRAY,
614 psz_text, psz_spaces );
616 utf8_fprintf( stdout, "%s\n%s",
617 psz_text, psz_spaces );
621 utf8_fprintf( stdout, "%s\n%s", psz_text, psz_spaces );
623 psz_text += i_cur_width;
631 if( !b_description || b_description_hack )
632 utf8_fprintf( stdout, BLUE"%s\n%s"GRAY,
633 psz_text, psz_spaces );
635 utf8_fprintf( stdout, "%s\n%s",
636 psz_text, psz_spaces );
640 utf8_fprintf( stdout, "%s\n%s", psz_text, psz_spaces );
646 if( b_description_hack && p_item->psz_longtext )
648 sprintf( psz_buffer, "%s%s",
649 module_gettext( p_parser, p_item->psz_longtext ),
651 b_description_hack = false;
652 psz_spaces = psz_spaces_longtext;
653 utf8_fprintf( stdout, "%s", psz_spaces );
662 utf8_fprintf( stdout, "\n" WHITE "%s" GRAY " %s\n", _( "Note:" ),
663 _( "add --advanced to your command line to see advanced options."));
665 utf8_fprintf( stdout, "\n%s %s\n", _( "Note:" ),
666 _( "add --advanced to your command line to see advanced options."));
669 if( i_only_advanced > 0 )
672 utf8_fprintf( stdout, "\n" WHITE "%s" GRAY " ", _( "Note:" ) );
674 utf8_fprintf( stdout, "\n%s ", _( "Note:" ) );
676 utf8_fprintf( stdout, vlc_ngettext("%u module was not displayed "
677 "because it only has advanced options.\n",
678 "%u modules were not displayed "
679 "because they only have advanced options.\n",
680 i_only_advanced ), i_only_advanced );
685 utf8_fprintf( stdout, "\n" WHITE "%s" GRAY "\n",
686 _( "No matching module found. Use --list or " \
687 "--list-verbose to list available modules." ) );
689 utf8_fprintf( stdout, "\n%s\n",
690 _( "No matching module found. Use --list or " \
691 "--list-verbose to list available modules." ) );
694 /* Release the module list */
695 module_list_free (list);
698 /*****************************************************************************
699 * ListModules: list the available modules with their description
700 *****************************************************************************
701 * Print a list of all available modules (builtins and plugins) and a short
702 * description for each one.
703 *****************************************************************************/
704 static void ListModules (vlc_object_t *p_this, bool b_verbose)
706 bool b_color = var_InheritBool( p_this, "color" );
710 b_color = false; // don't put color control codes in a .txt file
716 /* List all modules */
718 module_t **list = module_list_get (&count);
720 /* Enumerate each module */
721 for (size_t j = 0; j < count; j++)
723 module_t *p_parser = list[j];
724 const char *objname = module_get_object (p_parser);
726 utf8_fprintf( stdout, GREEN" %-22s "WHITE"%s\n"GRAY, objname,
727 module_gettext( p_parser, p_parser->psz_longname ) );
729 utf8_fprintf( stdout, " %-22s %s\n", objname,
730 module_gettext( p_parser, p_parser->psz_longname ) );
734 char *const *pp_shortcuts = p_parser->pp_shortcuts;
735 for( unsigned i = 0; i < p_parser->i_shortcuts; i++ )
737 if( strcmp( pp_shortcuts[i], objname ) )
740 utf8_fprintf( stdout, CYAN" s %s\n"GRAY,
743 utf8_fprintf( stdout, " s %s\n",
747 if( p_parser->psz_capability )
750 utf8_fprintf( stdout, MAGENTA" c %s (%d)\n"GRAY,
751 p_parser->psz_capability,
754 utf8_fprintf( stdout, " c %s (%d)\n",
755 p_parser->psz_capability,
760 module_list_free (list);
764 /*****************************************************************************
765 * Version: print complete program version
766 *****************************************************************************
767 * Print complete program version and build number.
768 *****************************************************************************/
769 static void Version( void )
772 utf8_fprintf( stdout, _("VLC version %s (%s)\n"), VERSION_MESSAGE,
774 utf8_fprintf( stdout, _("Compiled by %s on %s (%s)\n"),
775 VLC_CompileBy(), VLC_CompileHost(), __DATE__" "__TIME__ );
776 utf8_fprintf( stdout, _("Compiler: %s\n"), VLC_Compiler() );
777 utf8_fprintf( stdout, "%s", LICENSE_MSG );
781 #if defined( _WIN32 ) && !VLC_WINSTORE_APP
782 /*****************************************************************************
783 * ShowConsole: On Win32, create an output console for debug messages
784 *****************************************************************************
785 * This function is useful only on Win32.
786 *****************************************************************************/
787 static void ShowConsole( void )
791 if( getenv( "PWD" ) ) return; /* Cygwin shell or Wine */
793 if( !AllocConsole() ) return;
795 /* Use the ANSI code page (e.g. Windows-1252) as expected by the LibVLC
796 * Unicode/locale subsystem. By default, we have the obsolecent OEM code
797 * page (e.g. CP437 or CP850). */
798 SetConsoleOutputCP (GetACP ());
799 SetConsoleTitle (TEXT("VLC media player version "PACKAGE_VERSION));
801 freopen( "CONOUT$", "w", stderr );
802 freopen( "CONIN$", "r", stdin );
804 f_help = fopen( "vlc-help.txt", "wt" );
808 freopen( "vlc-help.txt", "wt", stdout );
809 utf8_fprintf( stderr, _("\nDumped content to vlc-help.txt file.\n") );
811 else freopen( "CONOUT$", "w", stdout );
814 /*****************************************************************************
815 * PauseConsole: On Win32, wait for a key press before closing the console
816 *****************************************************************************
817 * This function is useful only on Win32.
818 *****************************************************************************/
819 static void PauseConsole( void )
821 if( getenv( "PWD" ) ) return; /* Cygwin shell or Wine */
823 utf8_fprintf( stderr, _("\nPress the RETURN key to continue...\n") );
829 /*****************************************************************************
830 * ConsoleWidth: Return the console width in characters
831 *****************************************************************************
832 * We use the stty shell command to get the console width; if this fails or
833 * if the width is less than 80, we default to 80.
834 *****************************************************************************/
835 static int ConsoleWidth( void )
837 unsigned i_width = 80;
840 FILE *file = popen( "stty size 2>/dev/null", "r" );
843 if (fscanf (file, "%*u %u", &i_width) <= 0)
847 #elif !VLC_WINSTORE_APP
848 CONSOLE_SCREEN_BUFFER_INFO buf;
850 if (GetConsoleScreenBufferInfo (GetStdHandle (STD_OUTPUT_HANDLE), &buf))
851 i_width = buf.dwSize.X;