gui: macos: use float for rate
[vlc.git] / src / config / help.c
blob160c434a36f531b63a8904ef6e07f035bf7876ae
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 *****************************************************************************/
21 #ifdef HAVE_CONFIG_H
22 # include "config.h"
23 #endif
25 #include <stdio.h>
26 #include <string.h>
27 #include <stdlib.h>
28 #include <wchar.h>
29 #include <wctype.h>
30 #include <limits.h>
31 #include <float.h>
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"
39 #include "libvlc.h"
41 #if defined( _WIN32 )
42 # include <vlc_charset.h>
43 # define wcwidth(cp) (cp, 1) /* LOL */
44 #else
45 # include <unistd.h>
46 # include <termios.h>
47 # include <sys/ioctl.h>
48 #endif
50 #if defined( _WIN32 ) && !VLC_WINSTORE_APP
51 static void ShowConsole (void);
52 static void PauseConsole (void);
53 #else
54 # define ShowConsole() (void)0
55 # define PauseConsole() (void)0
56 #endif
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);
63 /**
64 * Returns the console width or a best guess.
66 static unsigned ConsoleWidth(void)
68 #ifdef TIOCGWINSZ
69 struct winsize ws;
71 if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) == 0)
72 return ws.ws_col;
73 #endif
74 #ifdef WIOCGETD
75 struct uwdata uw;
77 if (ioctl(STDOUT_FILENO, WIOCGETD, &uw) == 0)
78 return uw.uw_height / uw.uw_vs;
79 #endif
80 #if defined (_WIN32) && !VLC_WINSTORE_APP
81 CONSOLE_SCREEN_BUFFER_INFO buf;
83 if (GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &buf))
84 return buf.dwSize.X;
85 #endif
86 return 80;
89 /**
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)
97 char *str;
99 /* Check for short help option */
100 if (var_InheritBool (obj, "help"))
102 Help (obj, "help");
103 return true;
106 /* Check for version option */
107 if (var_InheritBool (obj, "version"))
109 Version();
110 return true;
113 /* Check for help on modules */
114 str = var_InheritString (obj, "module");
115 if (str != NULL)
117 Help (obj, str);
118 free (str);
119 return true;
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");
128 return true;
131 /* Check for long help option */
132 if (var_InheritBool (obj, "longhelp"))
134 Help (obj, "longhelp");
135 return true;
138 /* Check for module list option */
139 if (var_InheritBool (obj, "list"))
141 ListModules (obj, false );
142 return true;
145 if (var_InheritBool (obj, "list-verbose"))
147 ListModules (obj, true);
148 return true;
151 return false;
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 )
161 putchar('\n');
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"
170 "\n"
171 "Options-styles:\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"
176 "\n"
177 "Stream MRL syntax:\n"
178 " [[access][/demux]://]URL[#[title][:chapter][-[title][:chapter]]]\n"
179 " [:option=value ...]\n"
180 "\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"
183 "\n"
184 "URL syntax:\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"
197 "\n");
199 static void Help (vlc_object_t *p_this, char const *psz_help_name)
201 ShowConsole();
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 );
225 PauseConsole();
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"
234 # define RED COL(31)
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;
250 if (item == NULL)
251 return;
252 *sect = NULL;
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;
265 if (color)
266 fputs(BLUE, stdout);
268 const char *word = str;
269 int wordlen = 0, wordwidth = 0;
270 unsigned offset = 0;
271 bool newline = true;
273 while (str[0])
275 uint32_t cp;
276 size_t charlen = vlc_towc(str, &cp);
277 if (unlikely(charlen == (size_t)-1))
278 break;
280 int charwidth = wcwidth(cp);
281 if (charwidth < 0)
282 charwidth = 0;
284 str += charlen;
286 if (iswspace(cp))
288 if (!newline)
290 putchar(' '); /* insert space */
291 charwidth = 1;
293 fwrite(word, 1, wordlen, stdout); /* write complete word */
294 word = str;
295 wordlen = 0;
296 wordwidth = 0;
297 newline = false;
299 else
301 wordlen += charlen;
302 wordwidth += charwidth;
305 offset += charwidth;
306 if (offset >= width)
308 if (newline)
309 { /* overflow (word wider than line) */
310 fwrite(word, 1, wordlen - charlen, stdout);
311 word = str - charlen;
312 wordlen = charlen;
313 wordwidth = charwidth;
315 printf("\n%*s", margin, ""); /* new line */
316 offset = wordwidth;
317 newline = true;
321 if (!newline)
322 putchar(' ');
323 printf(color ? "%s\n"GRAY : "%s\n", word);
326 static int vlc_swidth(const char *str)
328 for (int total = 0;;)
330 uint32_t cp;
331 size_t charlen = vlc_towc(str, &cp);
333 if (charlen == 0)
334 return total;
335 if (charlen == (size_t)-1)
336 return -1;
337 str += charlen;
339 int w = wcwidth(cp);
340 if (w == -1)
341 return -1;
342 total += w;
346 static void print_item(const module_t *m, const module_config_t *item,
347 const module_config_t **section, bool color, bool desc)
349 #ifndef _WIN32
350 # define OPTION_VALUE_SEP " "
351 #else
352 # define OPTION_VALUE_SEP "="
353 #endif
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));
371 break;
373 case CONFIG_SECTION:
374 *section = item;
375 break;
377 return;
379 case CONFIG_ITEM_STRING:
381 type = _("string");
383 char **ppsz_values, **ppsz_texts;
385 ssize_t i_count = config_GetPszChoices(item->psz_name, &ppsz_values, &ppsz_texts);
387 if (i_count > 0)
389 size_t len = 0;
391 for (size_t i = 0; i < (size_t)i_count; i++)
392 len += strlen(ppsz_values[i]) + 1;
394 typebuf = malloc(len);
395 if (typebuf == NULL)
396 goto end_string;
398 bra = OPTION_VALUE_SEP "{";
399 type = typebuf;
400 ket = "}";
402 *typebuf = 0;
403 for (size_t i = 0; i < (size_t)i_count; i++)
405 if (i > 0)
406 strcat(typebuf, ",");
407 strcat(typebuf, ppsz_values[i]);
410 end_string:
411 for (size_t i = 0; i < (size_t)i_count; i++)
413 free(ppsz_values[i]);
414 free(ppsz_texts[i]);
416 free(ppsz_values);
417 free(ppsz_texts);
420 break;
422 case CONFIG_ITEM_INTEGER:
424 type = _("integer");
426 int64_t *pi_values;
427 char **ppsz_texts;
429 ssize_t i_count = config_GetIntChoices(item->psz_name, &pi_values, &ppsz_texts);
431 if (i_count > 0)
433 size_t len = 0;
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);
440 if (typebuf == NULL)
441 goto end_integer;
443 bra = OPTION_VALUE_SEP "{";
444 type = typebuf;
445 ket = "}";
447 *typebuf = 0;
448 for (size_t i = 0; i < (size_t)i_count; i++)
450 if (i != 0)
451 strcat(typebuf, ", ");
452 sprintf(typebuf + strlen(typebuf), "%"PRIi64" (%s)",
453 pi_values[i],
454 ppsz_texts[i]);
457 end_integer:
458 for (size_t i = 0; i < (size_t)i_count; i++)
459 free(ppsz_texts[i]);
460 free(pi_values);
461 free(ppsz_texts);
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)
467 type = typebuf;
468 else
469 typebuf = NULL;
471 break;
473 case CONFIG_ITEM_FLOAT:
474 type = _("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)
479 type = typebuf;
480 else
481 typebuf = NULL;
483 break;
485 case CONFIG_ITEM_BOOL:
486 bra = type = ket = "";
487 prefix = ", --no-";
488 suffix = item->value.i ? _("(default enabled)")
489 : _("(default disabled)");
490 break;
491 default:
492 return;
495 print_section(m, section, color, desc);
497 /* Add short option if any */
498 char shortopt[4];
499 if (item->i_short != '\0')
500 sprintf(shortopt, "-%c,", item->i_short);
501 else
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);
508 else
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);
518 if (offset < 0)
520 putchar('\n');
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);
528 if (suffix != NULL)
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);
541 free(typebuf);
544 static bool module_match(const module_t *m, const char *pattern, bool strict)
546 if (pattern == NULL)
547 return true;
549 const char *objname = module_get_object(m);
551 if (strict ? (strcmp(objname, pattern) == 0)
552 : (strstr(objname, pattern) != NULL))
553 return true;
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))
561 return true;
563 return false;
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))
573 continue;
574 if (item->b_removed)
575 continue;
576 return true;
578 return false;
581 static void Usage (vlc_object_t *p_this, char const *psz_search)
583 bool found = false;
584 bool strict = false;
585 if (psz_search != NULL && psz_search[0] == '=')
587 strict = true;
588 psz_search++;
591 bool color = false;
592 #ifndef _WIN32
593 if (isatty(STDOUT_FILENO))
594 color = var_InheritBool(p_this, "color");
595 #endif
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))
609 continue;
610 found = true;
612 if (!plugin_show(p))
613 continue;
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;
627 if (item->b_removed)
628 continue; /* Skip removed options */
630 print_item(m, item, &section, color, desc);
634 if (!found)
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)
648 bool color = false;
650 ShowConsole();
651 #ifndef _WIN32
652 if (isatty(STDOUT_FILENO))
653 color = var_InheritBool(p_this, "color");
654 #else
655 (void) p_this;
656 #endif
658 /* List all modules */
659 size_t count;
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));
670 if( b_verbose )
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",
676 pp_shortcuts[i]);
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);
683 PauseConsole();
686 /*****************************************************************************
687 * Version: print complete program version
688 *****************************************************************************
689 * Print complete program version and build number.
690 *****************************************************************************/
691 static void Version( void )
693 ShowConsole();
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);
699 PauseConsole();
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") );
728 else
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") );
742 getchar();
743 fclose( stdout );
745 #endif