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 *****************************************************************************/
33 #include <vlc_common.h>
34 #include <vlc_modules.h>
35 #include <vlc_plugin.h>
36 #include <vlc_charset.h>
37 #include "modules/modules.h"
38 #include "config/configuration.h"
42 # include <vlc_charset.h>
43 # define wcwidth(cp) (cp, 1) /* LOL */
47 # include <sys/ioctl.h>
50 #if defined( _WIN32 ) && !VLC_WINSTORE_APP
51 static void ShowConsole (void);
52 static void PauseConsole (void);
54 # define ShowConsole() (void)0
55 # define PauseConsole() (void)0
58 static void Help (vlc_object_t
*, const char *);
59 static void Usage (vlc_object_t
*, const char *);
60 static void Version (void);
61 static void ListModules (vlc_object_t
*, bool);
64 * Returns the console width or a best guess.
66 static unsigned ConsoleWidth(void)
71 if (ioctl(STDOUT_FILENO
, TIOCGWINSZ
, &ws
) == 0)
77 if (ioctl(STDOUT_FILENO
, WIOCGETD
, &uw
) == 0)
78 return uw
.uw_height
/ uw
.uw_vs
;
80 #if defined (_WIN32) && !VLC_WINSTORE_APP
81 CONSOLE_SCREEN_BUFFER_INFO buf
;
83 if (GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE
), &buf
))
90 * Checks for help command line options such as --help or --version.
91 * If one is found, print the corresponding text.
92 * \return true if a command line options caused some help message to be
93 * printed, false otherwise.
95 bool config_PrintHelp (vlc_object_t
*obj
)
99 /* Check for short help option */
100 if (var_InheritBool (obj
, "help"))
106 /* Check for version option */
107 if (var_InheritBool (obj
, "version"))
113 /* Check for help on modules */
114 str
= var_InheritString (obj
, "module");
122 /* Check for full help option */
123 if (var_InheritBool (obj
, "full-help"))
125 var_Create (obj
, "help-verbose", VLC_VAR_BOOL
);
126 var_SetBool (obj
, "help-verbose", true);
127 Help (obj
, "full-help");
131 /* Check for long help option */
132 if (var_InheritBool (obj
, "longhelp"))
134 Help (obj
, "longhelp");
138 /* Check for module list option */
139 if (var_InheritBool (obj
, "list"))
141 ListModules (obj
, false );
145 if (var_InheritBool (obj
, "list-verbose"))
147 ListModules (obj
, true);
154 /*****************************************************************************
155 * Help: print program help
156 *****************************************************************************
157 * Print a short inline help. Message interface is initialized at this stage.
158 *****************************************************************************/
159 static inline void print_help_on_full_help( void )
162 puts(_("To get exhaustive help, use '-H'."));
165 static const char vlc_usage
[] = N_(
166 "Usage: %s [options] [stream] ...\n"
167 "You can specify multiple streams on the commandline.\n"
168 "They will be enqueued in the playlist.\n"
169 "The first item specified will be played first.\n"
172 " --option A global option that is set for the duration of the program.\n"
173 " -option A single letter version of a global --option.\n"
174 " :option An option that only applies to the stream directly before it\n"
175 " and that overrides previous settings.\n"
177 "Stream MRL syntax:\n"
178 " [[access][/demux]://]URL[#[title][:chapter][-[title][:chapter]]]\n"
179 " [:option=value ...]\n"
181 " Many of the global --options can also be used as MRL specific :options.\n"
182 " Multiple :option=value pairs can be specified.\n"
185 " file:///path/file Plain media file\n"
186 " http://host[:port]/file HTTP URL\n"
187 " ftp://host[:port]/file FTP URL\n"
188 " mms://host[:port]/file MMS URL\n"
189 " screen:// Screen capture\n"
190 " dvd://[device] DVD device\n"
191 " vcd://[device] VCD device\n"
192 " cdda://[device] Audio CD device\n"
193 " udp://[[<source address>]@[<bind address>][:<bind port>]]\n"
194 " UDP stream sent by a streaming server\n"
195 " vlc://pause:<seconds> Pause the playlist for a certain time\n"
196 " vlc://quit Special item to quit VLC\n"
199 static void Help (vlc_object_t
*p_this
, char const *psz_help_name
)
203 if( psz_help_name
&& !strcmp( psz_help_name
, "help" ) )
205 printf(_(vlc_usage
), "vlc");
206 Usage( p_this
, "=core" );
207 print_help_on_full_help();
209 else if( psz_help_name
&& !strcmp( psz_help_name
, "longhelp" ) )
211 printf(_(vlc_usage
), "vlc");
212 Usage( p_this
, NULL
);
213 print_help_on_full_help();
215 else if( psz_help_name
&& !strcmp( psz_help_name
, "full-help" ) )
217 printf(_(vlc_usage
), "vlc");
218 Usage( p_this
, NULL
);
220 else if( psz_help_name
)
222 Usage( p_this
, psz_help_name
);
228 /*****************************************************************************
229 * Usage: print module usage
230 *****************************************************************************
231 * Print a short inline help. Message interface is initialized at this stage.
232 *****************************************************************************/
233 # define COL(x) "\033[" #x ";1m"
235 # define GREEN COL(32)
236 # define YELLOW COL(33)
237 # define BLUE COL(34)
238 # define MAGENTA COL(35)
239 # define CYAN COL(36)
240 # define WHITE COL(0)
241 # define GRAY "\033[0m"
242 # define LINE_START 8
243 # define PADDING_SPACES 25
245 static void print_section(const module_t
*m
, const module_config_t
**sect
,
246 bool color
, bool desc
)
248 const module_config_t
*item
= *sect
;
254 printf(color
? RED
" %s:\n"GRAY
: " %s:\n",
255 module_gettext(m
, item
->psz_text
));
256 if (desc
&& item
->psz_longtext
!= NULL
)
257 printf(color
? MAGENTA
" %s\n"GRAY
: " %s\n",
258 module_gettext(m
, item
->psz_longtext
));
261 static void print_desc(const char *str
, unsigned margin
, bool color
)
263 unsigned width
= ConsoleWidth() - margin
;
268 const char *word
= str
;
269 int wordlen
= 0, wordwidth
= 0;
276 size_t charlen
= vlc_towc(str
, &cp
);
277 if (unlikely(charlen
== (size_t)-1))
280 int charwidth
= wcwidth(cp
);
290 putchar(' '); /* insert space */
293 fwrite(word
, 1, wordlen
, stdout
); /* write complete word */
302 wordwidth
+= charwidth
;
309 { /* overflow (word wider than line) */
310 fwrite(word
, 1, wordlen
- charlen
, stdout
);
311 word
= str
- charlen
;
313 wordwidth
= charwidth
;
315 printf("\n%*s", margin
, ""); /* new line */
323 printf(color
? "%s\n"GRAY
: "%s\n", word
);
326 static int vlc_swidth(const char *str
)
328 for (int total
= 0;;)
331 size_t charlen
= vlc_towc(str
, &cp
);
335 if (charlen
== (size_t)-1)
346 static void print_item(const module_t
*m
, const module_config_t
*item
,
347 const module_config_t
**section
, bool color
, bool desc
)
350 # define OPTION_VALUE_SEP " "
352 # define OPTION_VALUE_SEP "="
354 const char *bra
= OPTION_VALUE_SEP
"<", *type
, *ket
= ">";
355 const char *prefix
= NULL
, *suffix
= NULL
;
356 char *typebuf
= NULL
;
358 switch (CONFIG_CLASS(item
->i_type
))
360 case 0: // hint class
361 switch (item
->i_type
)
363 case CONFIG_HINT_CATEGORY
:
364 case CONFIG_HINT_USAGE
:
365 printf(color
? GREEN
"\n %s\n" GRAY
: "\n %s\n",
366 module_gettext(m
, item
->psz_text
));
368 if (desc
&& item
->psz_longtext
!= NULL
)
369 printf(color
? CYAN
" %s\n" GRAY
: " %s\n",
370 module_gettext(m
, item
->psz_longtext
));
379 case CONFIG_ITEM_STRING
:
383 char **ppsz_values
, **ppsz_texts
;
385 ssize_t i_count
= config_GetPszChoices(item
->psz_name
, &ppsz_values
, &ppsz_texts
);
391 for (size_t i
= 0; i
< (size_t)i_count
; i
++)
392 len
+= strlen(ppsz_values
[i
]) + 1;
394 typebuf
= malloc(len
);
398 bra
= OPTION_VALUE_SEP
"{";
403 for (size_t i
= 0; i
< (size_t)i_count
; i
++)
406 strcat(typebuf
, ",");
407 strcat(typebuf
, ppsz_values
[i
]);
411 for (size_t i
= 0; i
< (size_t)i_count
; i
++)
413 free(ppsz_values
[i
]);
422 case CONFIG_ITEM_INTEGER
:
429 ssize_t i_count
= config_GetIntChoices(item
->psz_name
, &pi_values
, &ppsz_texts
);
435 for (size_t i
= 0; i
< (size_t)i_count
; i
++)
436 len
+= strlen(ppsz_texts
[i
])
437 + 4 * sizeof (int64_t) + 5;
439 typebuf
= malloc(len
);
443 bra
= OPTION_VALUE_SEP
"{";
448 for (size_t i
= 0; i
< (size_t)i_count
; i
++)
451 strcat(typebuf
, ", ");
452 sprintf(typebuf
+ strlen(typebuf
), "%"PRIi64
" (%s)",
458 for (size_t i
= 0; i
< (size_t)i_count
; i
++)
463 else if (item
->min
.i
!= INT64_MIN
|| item
->max
.i
!= INT64_MAX
)
465 if (asprintf(&typebuf
, "%s [%"PRId64
" .. %"PRId64
"]",
466 type
, item
->min
.i
, item
->max
.i
) >= 0)
473 case CONFIG_ITEM_FLOAT
:
475 if (item
->min
.f
!= FLT_MIN
|| item
->max
.f
!= FLT_MAX
)
477 if (asprintf(&typebuf
, "%s [%f .. %f]", type
,
478 item
->min
.f
, item
->max
.f
) >= 0)
485 case CONFIG_ITEM_BOOL
:
486 bra
= type
= ket
= "";
488 suffix
= item
->value
.i
? _("(default enabled)")
489 : _("(default disabled)");
495 print_section(m
, section
, color
, desc
);
497 /* Add short option if any */
499 if (item
->i_short
!= '\0')
500 sprintf(shortopt
, "-%c,", item
->i_short
);
502 strcpy(shortopt
, " ");
504 if (CONFIG_CLASS(item
->i_type
) == CONFIG_ITEM_BOOL
)
505 printf(color
? WHITE
" %s --%s" "%s%s%s%s%s "GRAY
506 : " %s --%s%s%s%s%s%s ", shortopt
, item
->psz_name
,
507 prefix
, item
->psz_name
, bra
, type
, ket
);
509 printf(color
? WHITE
" %s --%s"YELLOW
"%s%s%s%s%s "GRAY
510 : " %s --%s%s%s%s%s%s ", shortopt
, item
->psz_name
,
511 "", "", /* XXX */ bra
, type
, ket
);
513 /* Wrap description */
514 int offset
= PADDING_SPACES
- strlen(item
->psz_name
)
515 - strlen(bra
) - vlc_swidth(type
) - strlen(ket
) - 1;
516 if (CONFIG_CLASS(item
->i_type
) == CONFIG_ITEM_BOOL
)
517 offset
-= strlen(item
->psz_name
) + vlc_swidth(prefix
);
521 offset
= PADDING_SPACES
+ LINE_START
;
524 printf("%*s", offset
, "");
525 print_desc(module_gettext(m
, item
->psz_text
),
526 PADDING_SPACES
+ LINE_START
, color
);
530 printf("%*s", PADDING_SPACES
+ LINE_START
, "");
531 print_desc(suffix
, PADDING_SPACES
+ LINE_START
, color
);
534 if (desc
&& (item
->psz_longtext
!= NULL
&& item
->psz_longtext
[0]))
535 { /* Wrap long description */
536 printf("%*s", LINE_START
+ 2, "");
537 print_desc(module_gettext(m
, item
->psz_longtext
),
538 LINE_START
+ 2, false);
544 static bool module_match(const module_t
*m
, const char *pattern
, bool strict
)
549 const char *objname
= module_get_object(m
);
551 if (strict
? (strcmp(objname
, pattern
) == 0)
552 : (strstr(objname
, pattern
) != NULL
))
555 for (unsigned i
= 0; i
< m
->i_shortcuts
; i
++)
557 const char *shortcut
= m
->pp_shortcuts
[i
];
559 if (strict
? (strcmp(shortcut
, pattern
) == 0)
560 : (strstr(shortcut
, pattern
) != NULL
))
566 static bool plugin_show(const vlc_plugin_t
*plugin
)
568 for (size_t i
= 0; i
< plugin
->conf
.size
; i
++)
570 const module_config_t
*item
= plugin
->conf
.items
+ i
;
572 if (!CONFIG_ITEM(item
->i_type
))
581 static void Usage (vlc_object_t
*p_this
, char const *psz_search
)
585 if (psz_search
!= NULL
&& psz_search
[0] == '=')
593 if (isatty(STDOUT_FILENO
))
594 color
= var_InheritBool(p_this
, "color");
597 const bool desc
= var_InheritBool(p_this
, "help-verbose");
599 /* Enumerate the config for each module */
600 for (const vlc_plugin_t
*p
= vlc_plugins
; p
!= NULL
; p
= p
->next
)
602 const module_t
*m
= p
->module
;
603 const module_config_t
*section
= NULL
;
604 const char *objname
= module_get_object(m
);
606 if (p
->conf
.count
== 0)
607 continue; /* Ignore modules without config options */
608 if (!module_match(m
, psz_search
, strict
))
615 /* Print name of module */
616 printf(color
? "\n " GREEN
"%s" GRAY
" (%s)\n" : "\n %s (%s)\n",
617 module_gettext(m
, m
->psz_longname
), objname
);
618 if (m
->psz_help
!= NULL
)
619 printf(color
? CYAN
" %s\n"GRAY
: " %s\n",
620 module_gettext(m
, m
->psz_help
));
622 /* Print module options */
623 for (size_t j
= 0; j
< p
->conf
.size
; j
++)
625 const module_config_t
*item
= p
->conf
.items
+ j
;
628 continue; /* Skip removed options */
630 print_item(m
, item
, §ion
, color
, desc
);
635 printf(color
? "\n" WHITE
"%s" GRAY
"\n" : "\n%s\n",
636 _("No matching module found. Use --list or "
637 "--list-verbose to list available modules."));
640 /*****************************************************************************
641 * ListModules: list the available modules with their description
642 *****************************************************************************
643 * Print a list of all available modules (builtins and plugins) and a short
644 * description for each one.
645 *****************************************************************************/
646 static void ListModules (vlc_object_t
*p_this
, bool b_verbose
)
652 if (isatty(STDOUT_FILENO
))
653 color
= var_InheritBool(p_this
, "color");
658 /* List all modules */
660 module_t
**list
= module_list_get (&count
);
662 /* Enumerate each module */
663 for (size_t j
= 0; j
< count
; j
++)
665 module_t
*p_parser
= list
[j
];
666 const char *objname
= module_get_object (p_parser
);
667 printf(color
? GREEN
" %-22s "WHITE
"%s\n"GRAY
: " %-22s %s\n",
668 objname
, module_gettext(p_parser
, p_parser
->psz_longname
));
672 const char *const *pp_shortcuts
= p_parser
->pp_shortcuts
;
673 for( unsigned i
= 0; i
< p_parser
->i_shortcuts
; i
++ )
674 if( strcmp( pp_shortcuts
[i
], objname
) )
675 printf(color
? CYAN
" s %s\n"GRAY
: " s %s\n",
677 if (p_parser
->psz_capability
!= NULL
)
678 printf(color
? MAGENTA
" c %s (%d)\n"GRAY
: " c %s (%d)\n",
679 p_parser
->psz_capability
, p_parser
->i_score
);
682 module_list_free (list
);
686 /*****************************************************************************
687 * Version: print complete program version
688 *****************************************************************************
689 * Print complete program version and build number.
690 *****************************************************************************/
691 static void Version( void )
694 printf(_("VLC version %s (%s)\n"), VERSION_MESSAGE
, psz_vlc_changeset
);
695 printf(_("Compiled by %s on %s (%s)\n"), VLC_CompileBy(),
696 VLC_CompileHost(), __DATE__
" "__TIME__
);
697 printf(_("Compiler: %s\n"), VLC_Compiler());
698 fputs(LICENSE_MSG
, stdout
);
702 #if defined( _WIN32 ) && !VLC_WINSTORE_APP
703 /*****************************************************************************
704 * ShowConsole: On Win32, create an output console for debug messages
705 *****************************************************************************
706 * This function is useful only on Win32.
707 *****************************************************************************/
708 static void ShowConsole( void )
710 if( getenv( "PWD" ) ) return; /* Cygwin shell or Wine */
712 if( !AllocConsole() ) return;
714 /* Use the ANSI code page (e.g. Windows-1252) as expected by the LibVLC
715 * Unicode/locale subsystem. By default, we have the obsolecent OEM code
716 * page (e.g. CP437 or CP850). */
717 SetConsoleOutputCP (GetACP ());
718 SetConsoleTitle (TEXT("VLC media player version ") TEXT(PACKAGE_VERSION
));
720 freopen( "CONOUT$", "w", stderr
);
721 freopen( "CONIN$", "r", stdin
);
723 if( freopen( "vlc-help.txt", "wt", stdout
) != NULL
)
725 fputs( "\xEF\xBB\xBF", stdout
);
726 fprintf( stderr
, _("\nDumped content to vlc-help.txt file.\n") );
729 freopen( "CONOUT$", "w", stdout
);
732 /*****************************************************************************
733 * PauseConsole: On Win32, wait for a key press before closing the console
734 *****************************************************************************
735 * This function is useful only on Win32.
736 *****************************************************************************/
737 static void PauseConsole( void )
739 if( getenv( "PWD" ) ) return; /* Cygwin shell or Wine */
741 utf8_fprintf( stderr
, _("\nPress the RETURN key to continue...\n") );