Beispiel #1
0
static void mp_load_per_file_config(struct MPContext *mpctx)
{
    struct MPOpts *opts = mpctx->opts;
    char *confpath;
    char cfg[512];
    const char *file = mpctx->filename;

    if (snprintf(cfg, sizeof(cfg), "%s.conf", file) >= sizeof(cfg)) {
        MP_WARN(mpctx, "Filename is too long, "
                "can not load file or directory specific config files\n");
        return;
    }

    char *name = mp_basename(cfg);

    if (opts->use_filedir_conf) {
        bstr dir = mp_dirname(cfg);
        char *dircfg = mp_path_join(NULL, dir, bstr0("mpv.conf"));
        try_load_config(mpctx, dircfg, FILE_LOCAL_FLAGS);
        talloc_free(dircfg);

        if (try_load_config(mpctx, cfg, FILE_LOCAL_FLAGS))
            return;
    }

    if ((confpath = mp_find_user_config_file(NULL, mpctx->global, name))) {
        try_load_config(mpctx, confpath, FILE_LOCAL_FLAGS);

        talloc_free(confpath);
    }
}
Beispiel #2
0
bool mp_parse_cfgfiles(struct MPContext *mpctx)
{
    struct MPOpts *opts = mpctx->opts;
    if (!opts->load_config)
        return true;

    m_config_t *conf = mpctx->mconfig;
    void *tmp = talloc_new(NULL);
    bool r = true;
    char *conffile;

    // The #if is a stupid hack to avoid errors if libavfilter is not available.
#if HAVE_VF_LAVFI && HAVE_ENCODING
    conffile = mp_find_config_file(tmp, mpctx->global, "encoding-profiles.conf");
    if (conffile && mp_path_exists(conffile))
        m_config_parse_config_file(mpctx->mconfig, conffile, 0);
#endif

    conffile = mp_find_global_config_file(tmp, mpctx->global, "mpv.conf");
    if (conffile && m_config_parse_config_file(conf, conffile, 0) < 0) {
        r = false;
        goto done;
    }
    mp_mk_config_dir(mpctx->global, NULL);
    if (!(conffile = mp_find_user_config_file(tmp, mpctx->global, "config")))
        MP_ERR(mpctx, "mp_find_user_config_file(\"config\") problem\n");
    else if (m_config_parse_config_file(conf, conffile, 0) < 0) {
        r = false;
        goto done;
    }

done:
    talloc_free(tmp);
    return r;
}
Beispiel #3
0
/* Allocate memory and set function pointers
   af audio filter instance
   returns AF_OK or AF_ERROR
*/
static int af_open( struct af_instance* af )
{
  af->control = control;
  af->uninit  = uninit;
  af->play    = play;
  af->setup   = calloc(1, sizeof(af_export_t));
  if(af->setup == NULL)
    return AF_ERROR;

  ((af_export_t *)af->setup)->filename = mp_find_user_config_file(SHARED_FILE);

  return AF_OK;
}
Beispiel #4
0
static char *mp_get_playback_resume_config_filename(struct MPContext *mpctx,
                                                    const char *fname)
{
    struct MPOpts *opts = mpctx->opts;
    char *res = NULL;
    void *tmp = talloc_new(NULL);
    const char *realpath = fname;
    bstr bfname = bstr0(fname);
    if (!mp_is_url(bfname)) {
        if (opts->ignore_path_in_watch_later_config) {
            realpath = mp_basename(fname);
        } else {
            char *cwd = mp_getcwd(tmp);
            if (!cwd)
                goto exit;
            realpath = mp_path_join(tmp, cwd, fname);
        }
    }
    if (bstr_startswith0(bfname, "dvd://") && opts->dvd_opts && opts->dvd_opts->device)
        realpath = talloc_asprintf(tmp, "%s - %s", realpath, opts->dvd_opts->device);
    if ((bstr_startswith0(bfname, "br://") || bstr_startswith0(bfname, "bd://") ||
         bstr_startswith0(bfname, "bluray://")) && opts->bluray_device)
        realpath = talloc_asprintf(tmp, "%s - %s", realpath, opts->bluray_device);
    uint8_t md5[16];
    av_md5_sum(md5, realpath, strlen(realpath));
    char *conf = talloc_strdup(tmp, "");
    for (int i = 0; i < 16; i++)
        conf = talloc_asprintf_append(conf, "%02X", md5[i]);

    if (!mpctx->cached_watch_later_configdir) {
        char *wl_dir = mpctx->opts->watch_later_directory;
        if (wl_dir && wl_dir[0]) {
            mpctx->cached_watch_later_configdir =
                mp_get_user_path(mpctx, mpctx->global, wl_dir);
        }
    }

    if (!mpctx->cached_watch_later_configdir) {
        mpctx->cached_watch_later_configdir =
            mp_find_user_config_file(mpctx, mpctx->global, MP_WATCH_LATER_CONF);
    }

    if (mpctx->cached_watch_later_configdir)
        res = mp_path_join(NULL, mpctx->cached_watch_later_configdir, conf);

exit:
    talloc_free(tmp);
    return res;
}
Beispiel #5
0
/* Allocate memory and set function pointers
   af audio filter instance
   returns AF_OK or AF_ERROR
*/
static int af_open( struct af_instance* af )
{
  af->control = control;
  af->uninit  = uninit;
  af->filter  = filter;
  af_export_t *priv = af->priv;

  if (!priv->filename || !priv->filename[0])
      priv->filename = mp_find_user_config_file(SHARED_FILE);

  if (!priv->filename || !priv->filename[0])
      return AF_ERROR;

  return AF_OK;
}
Beispiel #6
0
Datei: ass_mp.c Projekt: kax4/mpv
void mp_ass_configure_fonts(ASS_Renderer *priv, struct osd_style_opts *opts)
{
    char *default_font = mp_find_user_config_file("subfont.ttf");
    char *config       = mp_find_config_file("fonts.conf");

    if (!mp_path_exists(default_font)) {
        talloc_free(default_font);
        default_font = NULL;
    }

    ass_set_fonts(priv, default_font, opts->font, 1, config, 1);

    talloc_free(default_font);
    talloc_free(config);
}
Beispiel #7
0
void mp_ass_configure_fonts(ASS_Renderer *priv, struct osd_style_opts *opts,
                            struct mpv_global *global, struct mp_log *log)
{
    void *tmp = talloc_new(NULL);
    char *default_font = mp_find_user_config_file(tmp, global, "subfont.ttf");
    char *config       = mp_find_config_file(tmp, global, "fonts.conf");

    if (default_font && !mp_path_exists(default_font))
        default_font = NULL;

    mp_verbose(log, "Setting up fonts...\n");
    ass_set_fonts(priv, default_font, opts->font, 1, config, 1);
    mp_verbose(log, "Done.\n");

    talloc_free(tmp);
}
Beispiel #8
0
bool mp_parse_cfgfiles(struct MPContext *mpctx)
{
    struct MPOpts *opts = mpctx->opts;
    if (!opts->load_config)
        return true;

    m_config_t *conf = mpctx->mconfig;
    void *tmp = talloc_new(NULL);
    bool r = true;
    char *conffile;
    char *section = NULL;
    bool encoding = opts->encode_output.file && *opts->encode_output.file;
    // In encoding mode, we don't want to apply normal config options.
    // So we "divert" normal options into a separate section, and the diverted
    // section is never used - unless maybe it's explicitly referenced from an
    // encoding profile.
    if (encoding)
        section = "playback-default";

    // The #if is a stupid hack to avoid errors if libavfilter is not available.
#if HAVE_LIBAVFILTER && HAVE_ENCODING
    conffile = mp_find_config_file(tmp, mpctx->global, "encoding-profiles.conf");
    if (conffile && mp_path_exists(conffile))
        m_config_parse_config_file(mpctx->mconfig, conffile, SECT_ENCODE, 0);
#endif

    conffile = mp_find_global_config_file(tmp, mpctx->global, "mpv.conf");
    if (conffile && m_config_parse_config_file(conf, conffile, section, 0) < 0) {
        r = false;
        goto done;
    }
    mp_mk_config_dir(mpctx->global, NULL);
    if (!(conffile = mp_find_user_config_file(tmp, mpctx->global, "config")))
        MP_ERR(mpctx, "mp_find_user_config_file(\"config\") problem\n");
    else if (m_config_parse_config_file(conf, conffile, section, 0) < 0) {
        r = false;
        goto done;
    }

    if (encoding)
        m_config_set_profile(conf, m_config_add_profile(conf, SECT_ENCODE), 0);

done:
    talloc_free(tmp);
    return r;
}
Beispiel #9
0
void mp_ass_configure_fonts(ASS_Renderer *priv, struct osd_style_opts *opts)
{
    char *default_font = mp_find_user_config_file("subfont.ttf");
    char *config       = mp_find_config_file("fonts.conf");

    if (default_font && !mp_path_exists(default_font)) {
        talloc_free(default_font);
        default_font = NULL;
    }

    mp_msg(MSGT_ASS, MSGL_V, "[ass] Setting up fonts...\n");
    ass_set_fonts(priv, default_font, opts->font, 1, config, 1);
    mp_msg(MSGT_ASS, MSGL_V, "[ass] Done.\n");

    talloc_free(default_font);
    talloc_free(config);
}
Beispiel #10
0
static char *mp_get_playback_resume_config_filename(struct mpv_global *global,
        const char *fname)
{
    char *res = NULL;
    void *tmp = talloc_new(NULL);
    const char *realpath = fname;
    bstr bfname = bstr0(fname);
    if (!mp_is_url(bfname)) {
        char *cwd = mp_getcwd(tmp);
        if (!cwd)
            goto exit;
        realpath = mp_path_join(tmp, bstr0(cwd), bstr0(fname));
    }
#if HAVE_DVDREAD || HAVE_DVDNAV
    if (bstr_startswith0(bfname, "dvd://"))
        realpath = talloc_asprintf(tmp, "%s - %s", realpath, dvd_device);
#endif
#if HAVE_LIBBLURAY
    if (bstr_startswith0(bfname, "br://") || bstr_startswith0(bfname, "bd://") ||
            bstr_startswith0(bfname, "bluray://"))
        realpath = talloc_asprintf(tmp, "%s - %s", realpath, bluray_device);
#endif
    uint8_t md5[16];
    av_md5_sum(md5, realpath, strlen(realpath));
    char *conf = talloc_strdup(tmp, "");
    for (int i = 0; i < 16; i++)
        conf = talloc_asprintf_append(conf, "%02X", md5[i]);

    conf = talloc_asprintf(tmp, "%s/%s", MP_WATCH_LATER_CONF, conf);

    res = mp_find_user_config_file(NULL, global, conf);

exit:
    talloc_free(tmp);
    return res;
}
Beispiel #11
0
dvb_config_t *dvb_get_config(void)
{
	int i, fd, type, size;
	char filename[30], *conf_file, *name;
	dvb_channels_list *list;
	dvb_card_config_t *cards = NULL, *tmp;
	dvb_config_t *conf = NULL;


	conf = malloc(sizeof(dvb_config_t));
	if(conf == NULL)
		return NULL;

	conf->priv = NULL;
	conf->count = 0;
	conf->cards = NULL;
	for(i=0; i<MAX_CARDS; i++)
	{
		snprintf(filename, sizeof(filename), "/dev/dvb/adapter%d/frontend0", i);
		fd = open(filename, O_RDONLY|O_NONBLOCK);
		if(fd < 0)
		{
			mp_msg(MSGT_DEMUX, MSGL_V, "DVB_CONFIG, can't open device %s, skipping\n", filename);
			continue;
		}

		type = dvb_get_tuner_type(fd);
		close(fd);
		if(type != TUNER_SAT && type != TUNER_TER && type != TUNER_CBL && type != TUNER_ATSC)
		{
			mp_msg(MSGT_DEMUX, MSGL_V, "DVB_CONFIG, can't detect tuner type of card %d, skipping\n", i);
			continue;
		}

        void *talloc_ctx = talloc_new(NULL);
        conf_file = talloc_steal(talloc_ctx,
                mp_find_user_config_file("channels.conf"));
        switch(type) {
            case TUNER_TER:
                conf_file = talloc_steal(talloc_ctx,
                        mp_find_user_config_file("channels.conf.ter"));
                break;
            case TUNER_CBL:
                conf_file = talloc_steal(talloc_ctx,
                        mp_find_user_config_file("channels.conf.cbl"));
                break;
            case TUNER_SAT:
                conf_file = talloc_steal(talloc_ctx,
                        mp_find_user_config_file("channels.conf.sat"));
                break;
            case TUNER_ATSC:
                conf_file = talloc_steal(talloc_ctx,
                        mp_find_user_config_file("channels.conf.atsc"));
                break;
        }

        if(conf_file && (access(conf_file, F_OK | R_OK) != 0)) {
            conf_file = talloc_steal(talloc_ctx,
                    mp_find_user_config_file("channels.conf"));

            if(conf_file && (access(conf_file, F_OK | R_OK) != 0)) {
                conf_file = talloc_steal(talloc_ctx,
                        mp_find_global_config_file("channels.conf"));
            }
        }

        list = dvb_get_channels(conf_file, type);
        talloc_free(talloc_ctx);

		if(list == NULL)
			continue;

		size = sizeof(dvb_card_config_t) * (conf->count + 1);
		tmp = realloc(conf->cards, size);

		if(tmp == NULL)
		{
			fprintf(stderr, "DVB_CONFIG, can't realloc %d bytes, skipping\n", size);
			continue;
		}
		cards = tmp;

		name = malloc(20);
		if(name==NULL)
		{
			fprintf(stderr, "DVB_CONFIG, can't realloc 20 bytes, skipping\n");
			continue;
		}

		conf->cards = cards;
		conf->cards[conf->count].devno = i;
		conf->cards[conf->count].list = list;
		conf->cards[conf->count].type = type;
		snprintf(name, 20, "DVB-%c card n. %d", type==TUNER_TER ? 'T' : (type==TUNER_CBL ? 'C' : 'S'), conf->count+1);
		conf->cards[conf->count].name = name;
		conf->count++;
	}

	if(conf->count == 0)
	{
		free(conf);
		conf = NULL;
	}

	return conf;
}
Beispiel #12
0
static struct bstr strip_ext(struct bstr str)
{
    int dotpos = bstrrchr(str, '.');
    if (dotpos < 0)
        return str;
    return (struct bstr){str.start, dotpos};
}

static struct bstr get_ext(struct bstr s)
{
    int dotpos = bstrrchr(s, '.');
    if (dotpos < 0)
        return (struct bstr){NULL, 0};
    return bstr_splice(s, dotpos + 1, s.len);
}

struct subfn {
    int priority;
    char *fname;
};

static int compare_sub_priority(const void *a, const void *b)
{
    const struct subfn *s1 = a;
    const struct subfn *s2 = b;
    if (s1->priority > s2->priority)
        return -1;
    if (s1->priority < s2->priority)
        return 1;
    return strcoll(s1->fname, s2->fname);
}

static struct bstr guess_lang_from_filename(struct bstr name)
{
    if (name.len < 2)
        return (struct bstr){NULL, 0};

    int n = 0;
    int i = name.len - 1;

    if (name.start[i] == ')' || name.start[i] == ']')
        i--;
    while (i >= 0 && isalpha(name.start[i])) {
        n++;
        if (n > 3)
            return (struct bstr){NULL, 0};
        i--;
    }
    if (n < 2)
        return (struct bstr){NULL, 0};
    return (struct bstr){name.start + i + 1, n};
}

struct sub_list {
    struct subfn subs[MAX_SUBTITLE_FILES];
    void *ctx;
};

/**
 * @brief Append all the subtitles in the given path matching fname
 * @param opts MPlayer options
 * @param slist pointer to the subtitles list tallocated
 * @param nsub pointer to the number of subtitles
 * @param path Look for subtitles in this directory
 * @param fname Subtitle filename (pattern)
 * @param limit_fuzziness Ignore flag when sub_fuziness == 2
 */
static void append_dir_subtitles(struct MPOpts *opts,
                                 struct subfn **slist, int *nsub,
                                 struct bstr path, const char *fname,
                                 int limit_fuzziness)
{
    char *sub_exts[] = {"utf", "utf8", "utf-8", "idx", "sub", "srt", "smi", "rt", "txt", "ssa", "aqt", "jss", "js", "ass", NULL};
    void *tmpmem = talloc_new(NULL);
    FILE *f;
    assert(strlen(fname) < 1e6);

    struct bstr f_fname = bstr0(mp_basename(fname));
    struct bstr f_fname_noext = bstrdup(tmpmem, strip_ext(f_fname));
    bstr_lower(f_fname_noext);
    struct bstr f_fname_trim = bstr_strip(f_fname_noext);

    // 0 = nothing
    // 1 = any subtitle file
    // 2 = any sub file containing movie name
    // 3 = sub file containing movie name and the lang extension
    char *path0 = bstrdup0(tmpmem, path);
    DIR *d = opendir(path0);
    if (!d)
        goto out;
    mp_msg(MSGT_SUBREADER, MSGL_V, "Load subtitles in %.*s\n", BSTR_P(path));
    struct dirent *de;
    while ((de = readdir(d))) {
        struct bstr dename = bstr0(de->d_name);
        void *tmpmem2 = talloc_new(tmpmem);

        // retrieve various parts of the filename
        struct bstr tmp_fname_noext = bstrdup(tmpmem2, strip_ext(dename));
        bstr_lower(tmp_fname_noext);
        struct bstr tmp_fname_ext = get_ext(dename);
        struct bstr tmp_fname_trim = bstr_strip(tmp_fname_noext);

        // does it end with a subtitle extension?
#ifdef CONFIG_ICONV
#ifdef CONFIG_ENCA
        int i = (opts->sub_cp && strncasecmp(opts->sub_cp, "enca", 4) != 0) ? 3 : 0;
#else
        int i = opts->sub_cp ? 3 : 0;
#endif
#else
        int i = 0;
#endif
        while (1) {
            if (!sub_exts[i])
                goto next_sub;
            if (bstrcasecmp(bstr0(sub_exts[i]), tmp_fname_ext) == 0)
                break;
            i++;
        }

        // we have a (likely) subtitle file
        int prio = 0;
        if (opts->sub_lang) {
            if (bstr_startswith(tmp_fname_trim, f_fname_trim)) {
                struct bstr lang = guess_lang_from_filename(tmp_fname_trim);
                if (lang.len) {
                    for (int n = 0; opts->sub_lang[n]; n++) {
                        if (bstr_startswith(lang,
                                            bstr0(opts->sub_lang[n]))) {
                            prio = 4; // matches the movie name + lang extension
                            break;
                        }
                    }
                }
            }
        }
        if (!prio && bstrcmp(tmp_fname_trim, f_fname_trim) == 0)
            prio = 3; // matches the movie name
        if (!prio && bstr_find(tmp_fname_trim, f_fname_trim) >= 0
            && opts->sub_match_fuzziness >= 1)
            prio = 2; // contains the movie name
        if (!prio) {
            // doesn't contain the movie name
            // don't try in the mplayer subtitle directory
            if (!limit_fuzziness && opts->sub_match_fuzziness >= 2) {
                prio = 1;
            }
        }

        mp_msg(MSGT_SUBREADER, MSGL_DBG2, "Potential sub file: "
               "\"%s\"  Priority: %d\n", de->d_name, prio);
        if (prio) {
            prio += prio;
#ifdef CONFIG_ICONV
            if (i < 4) // prefer UTF-8 coded, or idx over sub (vobsubs)
                prio++;
#endif
            char *subpath = mp_path_join(*slist, path, dename);
            if ((f = fopen(subpath, "rt"))) {
                MP_GROW_ARRAY(*slist, *nsub);
                struct subfn *sub = *slist + (*nsub)++;

                fclose(f);
                sub->priority = prio;
                sub->fname    = subpath;
            } else
                talloc_free(subpath);
        }

    next_sub:
        talloc_free(tmpmem2);
    }
    closedir(d);

 out:
    talloc_free(tmpmem);
}

char **find_text_subtitles(struct MPOpts *opts, const char *fname)
{
    char **subnames = NULL;
    struct subfn *slist = talloc_array_ptrtype(NULL, slist, 1);
    int n = 0;

    // Load subtitles from current media directory
    append_dir_subtitles(opts, &slist, &n, mp_dirname(fname), fname, 0);

    // Load subtitles in dirs specified by sub-paths option
    if (opts->sub_paths) {
        for (int i = 0; opts->sub_paths[i]; i++) {
            char *path = mp_path_join(slist, mp_dirname(fname),
                                      bstr0(opts->sub_paths[i]));
            append_dir_subtitles(opts, &slist, &n, bstr0(path), fname, 0);
        }
    }

    // Load subtitles in ~/.mplayer/sub limiting sub fuzziness
    char *mp_subdir = mp_find_user_config_file("sub/");
    if (mp_subdir)
        append_dir_subtitles(opts, &slist, &n, bstr0(mp_subdir), fname, 1);
    talloc_free(mp_subdir);

    // Sort subs by priority and append them
    qsort(slist, n, sizeof(*slist), compare_sub_priority);

    subnames = talloc_array_ptrtype(NULL, subnames, n);
    for (int i = 0; i < n; i++)
        subnames[i] = talloc_strdup(subnames, slist[i].fname);

    talloc_free(slist);
    return subnames;
}
Beispiel #13
0
int cddb_resolve(const char *dev, char **xmcd_file)
{
    char cddb_cache_dir[] = DEFAULT_CACHE_DIR;
    char *home_dir = NULL;
    cddb_data_t cddb_data;
    void *talloc_ctx = talloc_new(NULL);

    if (cdtoc_last_track <= 0) {
        cdtoc_last_track = read_toc(dev);
        if (cdtoc_last_track < 0) {
            mp_tmsg(MSGT_OPEN, MSGL_ERR, "Failed to open %s device.\n", dev);
            return -1;
        }
    }
    cddb_data.tracks    = cdtoc_last_track;
    cddb_data.disc_id   = cddb_discid(cddb_data.tracks);
    cddb_data.anonymous = 1;    // Don't send user info by default

    mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_CDDB_DISCID=%08lx\n",
           cddb_data.disc_id);

    // Check if there is a CD in the drive
    // FIXME: That's not really a good way to check
    if (cddb_data.disc_id == 0) {
        mp_tmsg(MSGT_DEMUX, MSGL_ERR, "No CD in the drive.\n");
        return -1;
    }

    home_dir = getenv("HOME");
#ifdef __MINGW32__
    if (home_dir == NULL)
        home_dir = getenv("USERPROFILE");
    if (home_dir == NULL)
        home_dir = getenv("HOMEPATH");
    // Last resort, store the cddb cache in the mplayer directory
    if (home_dir == NULL)
        home_dir = (char *)talloc_steal(talloc_ctx,
                                        mp_find_user_config_file(""));
#endif
    if (home_dir == NULL) {
        cddb_data.cache_dir = NULL;
    } else {
        unsigned len = strlen(home_dir) + strlen(cddb_cache_dir) + 1;
        cddb_data.cache_dir = malloc(len);
        if (cddb_data.cache_dir == NULL) {
            mp_tmsg(MSGT_DEMUX, MSGL_ERR, "Memory allocation failed.\n");
            talloc_free(talloc_ctx);
            return -1;
        }
        snprintf(cddb_data.cache_dir, len, "%s%s", home_dir, cddb_cache_dir);
    }
    talloc_free(talloc_ctx);

    // Check for a cached file
    if (cddb_read_cache(&cddb_data) < 0) {
        // No Cache found
        if (cddb_retrieve(&cddb_data) < 0) {
            return -1;
        }
    }

    if (cddb_data.xmcd_file != NULL) {
//        printf("%s\n", cddb_data.xmcd_file);
        *xmcd_file = cddb_data.xmcd_file;
        return 0;
    }

    return -1;
}
Beispiel #14
0
/* Initialization and runtime control
   af audio filter instance
   cmd control command
   arg argument
*/
static int control(struct af_instance* af, int cmd, void* arg)
{
  af_export_t* s = af->setup;
  switch (cmd){
  case AF_CONTROL_REINIT:{
    int i=0;
    int mapsize;

    // Free previous buffers
    if (s->buf)
      free(s->buf[0]);

    // unmap previous area
    if(s->mmap_area)
      munmap(s->mmap_area, SIZE_HEADER + (af->data->bps*s->sz*af->data->nch));
    // close previous file descriptor
    if(s->fd)
      close(s->fd);

    // Accept only int16_t as input format (which sucks)
    mp_audio_copy_config(af->data, (struct mp_audio*)arg);
    mp_audio_set_format(af->data, AF_FORMAT_S16);

    // If buffer length isn't set, set it to the default value
    if(s->sz == 0)
      s->sz = DEF_SZ;

    // Allocate new buffers (as one continuous block)
    s->buf[0] = calloc(s->sz*af->data->nch, af->data->bps);
    if(NULL == s->buf[0])
      mp_msg(MSGT_AFILTER, MSGL_FATAL, "[export] Out of memory\n");
    for(i = 1; i < af->data->nch; i++)
      s->buf[i] = (uint8_t *)s->buf[0] + i*s->sz*af->data->bps;

    if (!s->filename) {
        mp_msg(MSGT_AFILTER, MSGL_FATAL, "[export] No filename set.\n");
        return AF_ERROR;
    }

    // Init memory mapping
    s->fd = open(s->filename, O_RDWR | O_CREAT | O_TRUNC, 0640);
    mp_msg(MSGT_AFILTER, MSGL_INFO, "[export] Exporting to file: %s\n", s->filename);
    if(s->fd < 0) {
      mp_msg(MSGT_AFILTER, MSGL_FATAL, "[export] Could not open/create file: %s\n",
	     s->filename);
      return AF_ERROR;
    }

    // header + buffer
    mapsize = (SIZE_HEADER + (af->data->bps * s->sz * af->data->nch));

    // grow file to needed size
    for(i = 0; i < mapsize; i++){
      char null = 0;
      write(s->fd, (void*) &null, 1);
    }

    // mmap size
    s->mmap_area = mmap(0, mapsize, PROT_READ|PROT_WRITE,MAP_SHARED, s->fd, 0);
    if(s->mmap_area == NULL)
      mp_msg(MSGT_AFILTER, MSGL_FATAL, "[export] Could not mmap file %s\n", s->filename);
    mp_msg(MSGT_AFILTER, MSGL_INFO, "[export] Memory mapped to file: %s (%p)\n",
	   s->filename, s->mmap_area);

    // Initialize header
    *((int*)s->mmap_area) = af->data->nch;
    *((int*)s->mmap_area + 1) = s->sz * af->data->bps * af->data->nch;
    msync(s->mmap_area, mapsize, MS_ASYNC);

    // Use test_output to return FALSE if necessary
    return af_test_output(af, (struct mp_audio*)arg);
  }
  case AF_CONTROL_COMMAND_LINE:{
    int i=0;
    char *str = arg;

    if (!str){
      talloc_free(s->filename);

      s->filename = mp_find_user_config_file(SHARED_FILE);
      return AF_OK;
    }

    while((str[i]) && (str[i] != ':'))
      i++;

    talloc_free(s->filename);

    s->filename = talloc_array_size(NULL, 1, i + 1);
    memcpy(s->filename, str, i);
    s->filename[i] = 0;

    sscanf(str + i + 1, "%d", &(s->sz));

    if((s->sz <= 0) || (s->sz > 2048))
      mp_msg(MSGT_AFILTER, MSGL_ERR, "[export] Buffer size must be between"
	      " 1 and 2048\n" );

    return AF_OK;

  }
  }
  return AF_UNKNOWN;
}
Beispiel #15
0
static struct bstr strip_ext(struct bstr str)
{
    int dotpos = bstrrchr(str, '.');
    if (dotpos < 0)
        return str;
    return (struct bstr){str.start, dotpos};
}

static struct bstr get_ext(struct bstr s)
{
    int dotpos = bstrrchr(s, '.');
    if (dotpos < 0)
        return (struct bstr){NULL, 0};
    return bstr_splice(s, dotpos + 1, s.len);
}

bool mp_might_be_subtitle_file(const char *filename)
{
    return is_sub_ext(get_ext(bstr0(filename)));
}

static int compare_sub_filename(const void *a, const void *b)
{
    const struct subfn *s1 = a;
    const struct subfn *s2 = b;
    return strcoll(s1->fname, s2->fname);
}

static int compare_sub_priority(const void *a, const void *b)
{
    const struct subfn *s1 = a;
    const struct subfn *s2 = b;
    if (s1->priority > s2->priority)
        return -1;
    if (s1->priority < s2->priority)
        return 1;
    return strcoll(s1->fname, s2->fname);
}

static struct bstr guess_lang_from_filename(struct bstr name)
{
    if (name.len < 2)
        return (struct bstr){NULL, 0};

    int n = 0;
    int i = name.len - 1;

    if (name.start[i] == ')' || name.start[i] == ']')
        i--;
    while (i >= 0 && isalpha(name.start[i])) {
        n++;
        if (n > 3)
            return (struct bstr){NULL, 0};
        i--;
    }
    if (n < 2)
        return (struct bstr){NULL, 0};
    return (struct bstr){name.start + i + 1, n};
}

/**
 * @brief Append all the subtitles in the given path matching fname
 * @param opts MPlayer options
 * @param slist pointer to the subtitles list tallocated
 * @param nsub pointer to the number of subtitles
 * @param path Look for subtitles in this directory
 * @param fname Subtitle filename (pattern)
 * @param limit_fuzziness Ignore flag when sub_fuziness == 2
 */
static void append_dir_subtitles(struct mpv_global *global,
                                 struct subfn **slist, int *nsub,
                                 struct bstr path, const char *fname,
                                 int limit_fuzziness)
{
    void *tmpmem = talloc_new(NULL);
    struct MPOpts *opts = global->opts;
    struct mp_log *log = mp_log_new(tmpmem, global->log, "find_subfiles");

    if (mp_is_url(bstr0(fname)))
        goto out;

    struct bstr f_fname = bstr0(mp_basename(fname));
    struct bstr f_fname_noext = bstrdup(tmpmem, strip_ext(f_fname));
    bstr_lower(f_fname_noext);
    struct bstr f_fname_trim = bstr_strip(f_fname_noext);

    // 0 = nothing
    // 1 = any subtitle file
    // 2 = any sub file containing movie name
    // 3 = sub file containing movie name and the lang extension
    char *path0 = bstrdup0(tmpmem, path);
    DIR *d = opendir(path0);
    if (!d)
        goto out;
    mp_verbose(log, "Load subtitles in %.*s\n", BSTR_P(path));
    struct dirent *de;
    while ((de = readdir(d))) {
        struct bstr dename = bstr0(de->d_name);
        void *tmpmem2 = talloc_new(tmpmem);

        // retrieve various parts of the filename
        struct bstr tmp_fname_noext = bstrdup(tmpmem2, strip_ext(dename));
        bstr_lower(tmp_fname_noext);
        struct bstr tmp_fname_ext = get_ext(dename);
        struct bstr tmp_fname_trim = bstr_strip(tmp_fname_noext);

        // does it end with a subtitle extension?
        if (!is_sub_ext(tmp_fname_ext))
            goto next_sub;

        // we have a (likely) subtitle file
        int prio = 0;
        char *found_lang = NULL;
        if (opts->sub_lang) {
            if (bstr_startswith(tmp_fname_trim, f_fname_trim)) {
                struct bstr lang = guess_lang_from_filename(tmp_fname_trim);
                if (lang.len) {
                    for (int n = 0; opts->sub_lang[n]; n++) {
                        if (bstr_startswith0(lang, opts->sub_lang[n])) {
                            prio = 4; // matches the movie name + lang extension
                            found_lang = opts->sub_lang[n];
                            break;
                        }
                    }
                }
            }
        }
        if (!prio && bstrcmp(tmp_fname_trim, f_fname_trim) == 0)
            prio = 3; // matches the movie name
        if (!prio && bstr_find(tmp_fname_trim, f_fname_trim) >= 0
            && opts->sub_match_fuzziness >= 1)
            prio = 2; // contains the movie name
        if (!prio) {
            // doesn't contain the movie name
            // don't try in the mplayer subtitle directory
            if (!limit_fuzziness && opts->sub_match_fuzziness >= 2) {
                prio = 1;
            }
        }

        mp_dbg(log, "Potential sub file: \"%s\"  Priority: %d\n", de->d_name, prio);
        if (prio) {
            prio += prio;
            char *subpath = mp_path_join(*slist, path, dename);
            if (mp_path_exists(subpath)) {
                MP_GROW_ARRAY(*slist, *nsub);
                struct subfn *sub = *slist + (*nsub)++;

                // annoying and redundant
                if (strncmp(subpath, "./", 2) == 0)
                    subpath += 2;

                sub->priority = prio;
                sub->fname    = subpath;
                sub->lang     = found_lang;
            } else
                talloc_free(subpath);
        }

    next_sub:
        talloc_free(tmpmem2);
    }
    closedir(d);

 out:
    talloc_free(tmpmem);
}

static bool case_endswith(const char *s, const char *end)
{
    size_t len = strlen(s);
    size_t elen = strlen(end);
    return len >= elen && strcasecmp(s + len - elen, end) == 0;
}

// Drop .sub file if .idx file exists.
// Assumes slist is sorted by compare_sub_filename.
static void filter_subidx(struct subfn **slist, int *nsub)
{
    const char *prev = NULL;
    for (int n = 0; n < *nsub; n++) {
        const char *fname = (*slist)[n].fname;
        if (case_endswith(fname, ".idx")) {
            prev = fname;
        } else if (case_endswith(fname, ".sub")) {
            if (prev && strncmp(prev, fname, strlen(fname) - 4) == 0)
                (*slist)[n].priority = -1;
        }
    }
    for (int n = *nsub - 1; n >= 0; n--) {
        if ((*slist)[n].priority < 0)
            MP_TARRAY_REMOVE_AT(*slist, *nsub, n);
    }
}

// Return a list of subtitles found, sorted by priority.
// Last element is terminated with a fname==NULL entry.
struct subfn *find_text_subtitles(struct mpv_global *global, const char *fname)
{
    struct MPOpts *opts = global->opts;
    struct subfn *slist = talloc_array_ptrtype(NULL, slist, 1);
    int n = 0;

    // Load subtitles from current media directory
    append_dir_subtitles(global, &slist, &n, mp_dirname(fname), fname, 0);

    // Load subtitles in dirs specified by sub-paths option
    if (opts->sub_paths) {
        for (int i = 0; opts->sub_paths[i]; i++) {
            char *path = mp_path_join(slist, mp_dirname(fname),
                                      bstr0(opts->sub_paths[i]));
            append_dir_subtitles(global, &slist, &n, bstr0(path), fname, 0);
        }
    }

    // Load subtitles in ~/.mpv/sub limiting sub fuzziness
    char *mp_subdir = mp_find_user_config_file(NULL, global, "sub/");
    if (mp_subdir)
        append_dir_subtitles(global, &slist, &n, bstr0(mp_subdir), fname, 1);
    talloc_free(mp_subdir);

    // Sort by name for filter_subidx()
    qsort(slist, n, sizeof(*slist), compare_sub_filename);

    filter_subidx(&slist, &n);

    // Sort subs by priority and append them
    qsort(slist, n, sizeof(*slist), compare_sub_priority);

    struct subfn z = {0};
    MP_TARRAY_APPEND(NULL, slist, n, z);

    return slist;
}