1 /* ncmpc (Ncurses MPD Client)
2 * (c) 2004-2010 The Music Player Daemon Project
3 * Project homepage: http://musicpd.org
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
33 #define ERROR_UNKNOWN_OPTION 0x01
34 #define ERROR_BAD_ARGUMENT 0x02
35 #define ERROR_GOT_ARGUMENT 0x03
36 #define ERROR_MISSING_ARGUMENT 0x04
42 const char *descrition
;
46 typedef void (*option_callback_fn_t
)(int c
, const char *arg
);
50 .crossfade_time
= DEFAULT_CROSSFADE_TIME
,
52 #ifdef ENABLE_LYRICS_SCREEN
53 .lyrics_timeout
= DEFAULT_LYRICS_TIMEOUT
,
54 .lyrics_autosave
= false,
55 .lyrics_show_plugin
= false,
62 .status_message_time
= 3,
64 .scroll
= DEFAULT_SCROLL
,
65 .welcome_screen_list
= true,
66 .jump_prefix_only
= true,
67 .second_column
= true,
71 static const arg_opt_t option_table
[] = {
72 { '?', "help", NULL
, "Show this help message" },
73 { 'V', "version", NULL
, "Display version information" },
74 { 'c', "colors", NULL
, "Enable colors" },
75 { 'C', "no-colors", NULL
, "Disable colors" },
77 { 'm', "mouse", NULL
, "Enable mouse" },
78 { 'M', "no-mouse", NULL
, "Disable mouse" },
80 { 'e', "exit", NULL
, "Exit on connection errors" },
81 { 'p', "port", "PORT", "Connect to server on port" },
82 { 'h', "host", "HOST", "Connect to server on host" },
83 { 'P', "password","PASSWORD", "Connect with password" },
84 { 'f', "config", "FILE", "Read configuration from file" },
85 { 'k', "key-file","FILE", "Read key bindings from file" },
87 { 'K', "dump-keys", NULL
, "Dump key bindings to stdout" },
91 static const unsigned option_table_size
= sizeof(option_table
) / sizeof(option_table
[0]);
93 static const arg_opt_t
*
94 lookup_option(int s
, char *l
)
98 for (i
= 0; i
< option_table_size
; ++i
) {
99 if (l
&& strcmp(l
, option_table
[i
].longopt
) == 0)
100 return &option_table
[i
];;
101 if (s
&& s
== option_table
[i
].shortopt
)
102 return &option_table
[i
];;
109 option_error(int error
, const char *option
, const char *arg
)
112 case ERROR_UNKNOWN_OPTION
:
113 fprintf(stderr
, PACKAGE
": invalid option %s\n", option
);
115 case ERROR_BAD_ARGUMENT
:
116 fprintf(stderr
, PACKAGE
": bad argument: %s\n", option
);
118 case ERROR_GOT_ARGUMENT
:
119 fprintf(stderr
, PACKAGE
": invalid option %s=%s\n", option
, arg
);
121 case ERROR_MISSING_ARGUMENT
:
122 fprintf(stderr
, PACKAGE
": missing value for %s option\n", option
);
125 fprintf(stderr
, PACKAGE
": internal error %d\n", error
);
137 printf("Usage: %s [OPTION]...\n", PACKAGE
);
139 for (i
= 0; i
< option_table_size
; ++i
) {
142 if (option_table
[i
].argument
)
143 g_snprintf(tmp
, sizeof(tmp
), "%s=%s",
144 option_table
[i
].longopt
,
145 option_table
[i
].argument
);
147 g_strlcpy(tmp
, option_table
[i
].longopt
, 64);
149 printf(" -%c, --%-20s %s\n",
150 option_table
[i
].shortopt
,
152 option_table
[i
].descrition
);
157 handle_option(int c
, const char *arg
)
160 case '?': /* --help */
163 case 'V': /* --version */
164 puts(PACKAGE
" version: " VERSION
"\n"
172 #ifdef ENABLE_MULTIBYTE
195 #ifdef ENABLE_ARTIST_SCREEN
198 #ifdef ENABLE_HELP_SCREEN
201 #ifdef ENABLE_SEARCH_SCREEN
204 #ifdef ENABLE_SONG_SCREEN
207 #ifdef ENABLE_KEYDEF_SCREEN
210 #ifdef ENABLE_LYRICS_SCREEN
213 #ifdef ENABLE_OUTPUTS_SCREEN
219 if (strcmp("translator-credits", _("translator-credits")) != 0)
220 /* To translators: these credits are shown
221 when ncmpc is started with "--version" */
222 printf("\n%s\n", _("translator-credits"));
225 case 'c': /* --colors */
227 options
.enable_colors
= true;
230 case 'C': /* --no-colors */
232 options
.enable_colors
= false;
235 case 'm': /* --mouse */
237 options
.enable_mouse
= true;
240 case 'M': /* --no-mouse */
242 options
.enable_mouse
= false;
245 case 'e': /* --exit */
248 case 'p': /* --port */
249 options
.port
= atoi(arg
);
251 case 'h': /* --host */
252 g_free(options
.host
);
253 options
.host
= g_strdup(arg
);
255 case 'P': /* --password */
256 g_free(options
.password
);
257 options
.password
= locale_to_utf8(arg
);
259 case 'f': /* --config */
260 g_free(options
.config_file
);
261 options
.config_file
= g_strdup(arg
);
263 case 'k': /* --key-file */
264 g_free(options
.key_file
);
265 options
.key_file
= g_strdup(arg
);
269 case 'K': /* --dump-keys */
270 read_configuration();
271 write_key_bindings(stdout
, KEYDEF_WRITE_ALL
| KEYDEF_COMMENT_ALL
);
277 fprintf(stderr
,"Unknown Option %c = %s\n", c
, arg
);
283 options_parse(int argc
, const char *argv
[])
286 const arg_opt_t
*opt
= NULL
;
287 option_callback_fn_t option_cb
= handle_option
;
289 for (i
= 1; i
< argc
; i
++) {
290 const char *arg
= argv
[i
];
291 size_t len
= strlen(arg
);
293 /* check for a long option */
294 if (g_str_has_prefix(arg
, "--")) {
297 /* make sure we got an argument for the previous option */
298 if( opt
&& opt
->argument
)
299 option_error(ERROR_MISSING_ARGUMENT
, opt
->longopt
, opt
->argument
);
301 /* retrieve a option argument */
302 if ((value
=g_strrstr(arg
+2, "="))) {
304 name
= g_strdup(arg
);
308 name
= g_strdup(arg
);
310 /* check if the option exists */
311 if( (opt
=lookup_option(0, name
+2)) == NULL
)
312 option_error(ERROR_UNKNOWN_OPTION
, name
, NULL
);
315 /* abort if we got an argument to the option and don't want one */
316 if( value
&& opt
->argument
==NULL
)
317 option_error(ERROR_GOT_ARGUMENT
, arg
, value
);
319 /* execute option callback */
320 if (value
|| opt
->argument
==NULL
) {
321 option_cb (opt
->shortopt
, value
);
325 /* check for short options */
326 else if (len
>=2 && g_str_has_prefix(arg
, "-")) {
329 for(j
=1; j
<len
; j
++) {
330 /* make sure we got an argument for the previous option */
331 if (opt
&& opt
->argument
)
332 option_error(ERROR_MISSING_ARGUMENT
,
333 opt
->longopt
, opt
->argument
);
335 /* check if the option exists */
336 if ((opt
=lookup_option(arg
[j
], NULL
)) == NULL
)
337 option_error(ERROR_UNKNOWN_OPTION
, arg
, NULL
);
339 /* if no option argument is needed execute callback */
340 if (opt
->argument
== NULL
) {
341 option_cb (opt
->shortopt
, NULL
);
346 /* is this a option argument? */
347 if (opt
&& opt
->argument
) {
348 option_cb (opt
->shortopt
, arg
);
351 option_error(ERROR_BAD_ARGUMENT
, arg
, NULL
);
355 if (opt
&& opt
->argument
== NULL
)
356 option_cb (opt
->shortopt
, NULL
);
357 else if (opt
&& opt
->argument
)
358 option_error(ERROR_MISSING_ARGUMENT
, opt
->longopt
, opt
->argument
);
360 if (!options
.host
&& getenv("MPD_HOST")) {
361 g_free(options
.host
);
362 options
.host
= g_strdup(getenv("MPD_HOST"));
369 /* default option values */
370 options
.list_format
= g_strdup(DEFAULT_LIST_FORMAT
);
371 options
.status_format
= g_strdup(DEFAULT_STATUS_FORMAT
);
372 options
.screen_list
= g_strsplit_set(DEFAULT_SCREEN_LIST
, " ", 0);
374 options
.scroll_sep
= g_strdup(DEFAULT_SCROLL_SEP
);
381 g_free(options
.host
);
382 g_free(options
.username
);
383 g_free(options
.password
);
384 g_free(options
.config_file
);
385 g_free(options
.key_file
);
386 g_free(options
.list_format
);
387 g_free(options
.status_format
);
388 g_strfreev(options
.screen_list
);
390 g_free(options
.xterm_title_format
);
391 g_free(options
.scroll_sep
);