コード例 #1
0
ファイル: playlist.c プロジェクト: 0x0all/mpv
void playlist_add_base_path(struct playlist *pl, bstr base_path)
{
    if (base_path.len == 0 || bstrcmp0(base_path, ".") == 0)
        return;
    for (struct playlist_entry *e = pl->first; e; e = e->next) {
        if (!mp_is_url(bstr0(e->filename))) {
            char *new_file = mp_path_join(e, base_path, bstr0(e->filename));
            talloc_free(e->filename);
            e->filename = new_file;
        }
    }
}
コード例 #2
0
ファイル: parser-mpcmd.c プロジェクト: keeperofdakeys/mpv
// Returns 0 if a valid option/file is available, <0 on error, 1 on end of args.
static int split_opt_silent(struct parse_state *p)
{
    assert(!p->error);

    if (p->argc < 1)
        return 1;

    p->is_opt = false;
    p->arg = bstr0(p->argv[0]);
    p->param = bstr0(NULL);

    p->argc--;
    p->argv++;

    if (p->no_more_opts || !bstr_startswith0(p->arg, "-") || p->arg.len == 1)
        return 0;

    if (bstrcmp0(p->arg, "--") == 0) {
        p->no_more_opts = true;
        return split_opt_silent(p);
    }

    p->is_opt = true;

    if (!bstr_eatstart0(&p->arg, "--"))
        bstr_eatstart0(&p->arg, "-");

    bool ambiguous = !bstr_split_tok(p->arg, "=", &p->arg, &p->param);

    int r = m_config_option_requires_param(p->config, p->arg);
    if (r < 0)
        return r;

    if (ambiguous && r > 0) {
        if (p->argc < 1)
            return M_OPT_MISSING_PARAM;
        p->param = bstr0(p->argv[0]);
        p->argc--;
        p->argv++;
    }

    return 0;
}
コード例 #3
0
ファイル: m_config.c プロジェクト: zerix/mpv
static int parse_profile(struct m_config *config, const struct m_option *opt,
                         struct bstr name, struct bstr param, bool set)
{
    if (!bstrcmp0(param, "help")) {
        struct m_profile *p;
        if (!config->profiles) {
            mp_tmsg(MSGT_CFGPARSER, MSGL_INFO,
                    "No profiles have been defined.\n");
            return M_OPT_EXIT - 1;
        }
        mp_tmsg(MSGT_CFGPARSER, MSGL_INFO, "Available profiles:\n");
        for (p = config->profiles; p; p = p->next)
            mp_msg(MSGT_CFGPARSER, MSGL_INFO, "\t%s\t%s\n", p->name,
                   p->desc ? p->desc : "");
        mp_msg(MSGT_CFGPARSER, MSGL_INFO, "\n");
        return M_OPT_EXIT - 1;
    }

    char **list = NULL;
    int r = m_option_type_string_list.parse(opt, name, param, &list);
    if (r < 0)
        return r;
    if (!list || !list[0])
        return M_OPT_INVALID;
    for (int i = 0; list[i]; i++) {
        struct m_profile *p = m_config_get_profile(config, list[i]);
        if (!p) {
            mp_tmsg(MSGT_CFGPARSER, MSGL_WARN, "Unknown profile '%s'.\n",
                    list[i]);
            r = M_OPT_INVALID;
        } else if (set)
            m_config_set_profile(config, p);
    }
    m_option_free(opt, &list);
    return r;
}
コード例 #4
0
ファイル: parse_commandline.c プロジェクト: chyiz/mpv
// 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});
            }
コード例 #5
0
ファイル: parser-mpcmd.c プロジェクト: kax4/mpv
// Returns 0 if a valid option/file is available, <0 on error, 1 on end of args.
static int split_opt_silent(struct parse_state *p)
{
    assert(!p->error);

    if (p->argc < 1)
        return 1;

    p->mp_opt = NULL;
    p->arg = bstr0(p->argv[0]);
    p->param = bstr0(NULL);

    p->argc--;
    p->argv++;

    if (p->no_more_opts || !bstr_startswith0(p->arg, "-") || p->arg.len == 1)
        return 0;

    if (bstrcmp0(p->arg, "--") == 0) {
        p->no_more_opts = true;
        return split_opt_silent(p);
    }

    bool old_syntax = !bstr_startswith0(p->arg, "--");
    if (old_syntax) {
        p->arg = bstr_cut(p->arg, 1);
    } else {
        p->arg = bstr_cut(p->arg, 2);
        int idx = bstrchr(p->arg, '=');
        if (idx > 0) {
            p->param = bstr_cut(p->arg, idx + 1);
            p->arg = bstr_splice(p->arg, 0, idx);
        }
    }

    p->mp_opt = m_config_get_option(p->config, p->arg);
    if (!p->mp_opt) {
        // Automagic "no-" arguments: "--no-bla" turns into "--bla=no".
        if (!bstr_startswith0(p->arg, "no-"))
            return -1;

        struct bstr s = bstr_cut(p->arg, 3);
        p->mp_opt = m_config_get_option(p->config, s);
        if (!p->mp_opt || p->mp_opt->type != &m_option_type_flag)
            return -1;
        // Avoid allowing "--no-no-bla".
        if (bstr_startswith(bstr0(p->mp_opt->name), bstr0("no-")))
            return -1;
        // Flag options never have parameters.
        old_syntax = false;
        if (p->param.len)
            return -2;
        p->arg = s;
        p->param = bstr0("no");
    }

    if (bstr_endswith0(p->arg, "-clr"))
        old_syntax = false;

    if (old_syntax && !(p->mp_opt->type->flags & M_OPT_TYPE_OLD_SYNTAX_NO_PARAM))
    {
        if (p->argc < 1)
            return -3;
        p->param = bstr0(p->argv[0]);
        p->argc--;
        p->argv++;
    }

    return 0;
}
コード例 #6
0
ファイル: parser-mpcmd.c プロジェクト: kax4/mpv
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});
            }