// returns M_OPT_... error code int m_config_parse_mp_command_line(m_config_t *config, struct playlist *files, struct mpv_global *global, char **argv) { int ret = M_OPT_UNKNOWN; int mode = 0; struct playlist_entry *local_start = NULL; int local_params_count = 0; struct playlist_param *local_params = 0; assert(config != NULL); mode = GLOBAL; struct parse_state p = {config, argv}; while (split_opt(&p)) { if (p.is_opt) { int flags = M_SETOPT_FROM_CMDLINE; if (mode == LOCAL) flags |= M_SETOPT_BACKUP | M_SETOPT_CHECK_ONLY; int r = m_config_set_option_ext(config, p.arg, p.param, flags); if (r == M_OPT_EXIT) { ret = r; goto err_out; } else if (r < 0) { MP_FATAL(config, "Setting command line option '--%.*s=%.*s' failed.\n", BSTR_P(p.arg), BSTR_P(p.param)); goto err_out; } // Handle some special arguments outside option parser. if (!bstrcmp0(p.arg, "{")) { if (mode != GLOBAL) { MP_ERR(config, "'--{' can not be nested.\n"); goto err_out; } mode = LOCAL; assert(!local_start); local_start = files->last; continue; } if (!bstrcmp0(p.arg, "}")) { if (mode != LOCAL) { MP_ERR(config, "Too many closing '--}'.\n"); goto err_out; } if (local_params_count) { // The files added between '{' and '}' are the entries from // the entry _after_ local_start, until the end of the list. // If local_start is NULL, the list was empty on '{', and we // want all files in the list. struct playlist_entry *cur = local_start ? local_start->next : files->first; if (!cur) MP_WARN(config, "Ignored options!\n"); while (cur) { playlist_entry_add_params(cur, local_params, local_params_count); cur = cur->next; } } local_params_count = 0; mode = GLOBAL; m_config_restore_backups(config); local_start = NULL; continue; } if (bstrcmp0(p.arg, "playlist") == 0) { // append the playlist to the local args char *param0 = bstrdup0(NULL, p.param); struct playlist *pl = playlist_parse_file(param0, global); talloc_free(param0); if (!pl) { MP_FATAL(config, "Error reading playlist '%.*s'\n", BSTR_P(p.param)); goto err_out; } playlist_transfer_entries(files, pl); talloc_free(pl); continue; } if (mode == LOCAL) { MP_TARRAY_APPEND(NULL, local_params, local_params_count, (struct playlist_param) {p.arg, p.param}); }
bool m_config_parse_mp_command_line(m_config_t *config, struct playlist *files, int argc, char **argv) { int mode = 0; struct playlist_entry *local_start = NULL; bool shuffle = false; int local_params_count = 0; struct playlist_param *local_params = 0; assert(config != NULL); assert(!config->file_local_mode); config->mode = M_COMMAND_LINE; mode = GLOBAL; #ifdef CONFIG_MACOSX_FINDER if (macosx_finder_args(config, files, argc, argv)) return true; #endif struct parse_state p = {config, argc, argv}; while (split_opt(&p)) { if (p.mp_opt) { int r; if (mode == GLOBAL && !(p.mp_opt->flags & M_OPT_PRE_PARSE)) { r = m_config_set_option(config, p.arg, p.param); } else { r = m_config_check_option(config, p.arg, p.param); } if (r <= M_OPT_EXIT) goto err_out; if (r < 0) { char *msg = m_option_strerror(r); if (!msg) goto print_err; mp_tmsg(MSGT_CFGPARSER, MSGL_FATAL, "Error parsing commandline option %.*s: %s\n", BSTR_P(p.arg), msg); goto err_out; } // Handle some special arguments outside option parser. if (!bstrcmp0(p.arg, "{")) { if (mode != GLOBAL) { mp_msg(MSGT_CFGPARSER, MSGL_ERR, "'--{' can not be nested.\n"); goto err_out; } mode = LOCAL; // Needed for option checking. m_config_enter_file_local(config); assert(!local_start); local_start = files->last; continue; } if (!bstrcmp0(p.arg, "}")) { if (mode != LOCAL) { mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Too many closing '--}'.\n"); goto err_out; } if (local_params_count) { // The files added between '{' and '}' are the entries from // the entry _after_ local_start, until the end of the list. // If local_start is NULL, the list was empty on '{', and we // want all files in the list. struct playlist_entry *cur = local_start ? local_start->next : files->first; if (!cur) mp_msg(MSGT_CFGPARSER, MSGL_WARN, "Ignored options!\n"); while (cur) { playlist_entry_add_params(cur, local_params, local_params_count); cur = cur->next; } } local_params_count = 0; mode = GLOBAL; m_config_leave_file_local(config); local_start = NULL; shuffle = false; continue; } if (bstrcmp0(p.arg, "shuffle") == 0) { shuffle = parse_flag(p.arg, p.param); continue; } if (bstrcmp0(p.arg, "playlist") == 0) { // append the playlist to the local args char *param0 = bstrdup0(NULL, p.param); struct playlist *pl = playlist_parse_file(param0); talloc_free(param0); if (!pl) goto print_err; playlist_transfer_entries(files, pl); talloc_free(pl); continue; } if (mode == LOCAL) { MP_TARRAY_APPEND(NULL, local_params, local_params_count, (struct playlist_param) {p.arg, p.param}); }