void mp_parse_cfgfiles(struct MPContext *mpctx) { struct MPOpts *opts = mpctx->opts; if (!opts->load_config) return; mp_mk_config_dir(mpctx->global, ""); m_config_t *conf = mpctx->mconfig; char *section = NULL; bool encoding = opts->encode_opts && opts->encode_opts->file && opts->encode_opts->file[0]; // 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 char *cf = mp_find_config_file(NULL, mpctx->global, "encoding-profiles.conf"); if (cf) m_config_parse_config_file(mpctx->mconfig, cf, SECT_ENCODE, 0); talloc_free(cf); #endif load_all_cfgfiles(mpctx, section, "config"); load_all_cfgfiles(mpctx, section, "mpv.conf"); if (encoding) m_config_set_profile(conf, m_config_add_profile(conf, SECT_ENCODE), 0); }
void mp_write_watch_later_conf(struct MPContext *mpctx) { char *filename = mpctx->filename; char *conffile = NULL; if (!filename) goto exit; struct demuxer *demux = mpctx->demuxer; if (demux && (!demux->seekable || demux->partially_seekable)) { MP_INFO(mpctx, "Not seekable - not saving state.\n"); goto exit; } double pos = get_current_time(mpctx); if (pos == MP_NOPTS_VALUE) goto exit; mp_mk_config_dir(mpctx->global, MP_WATCH_LATER_CONF); conffile = mp_get_playback_resume_config_filename(mpctx->global, filename); if (!conffile) goto exit; MP_INFO(mpctx, "Saving state.\n"); FILE *file = fopen(conffile, "wb"); if (!file) goto exit; if (mpctx->opts->write_filename_in_watch_later_config) { char write_name[1024] = {0}; for (int n = 0; filename[n] && n < sizeof(write_name) - 1; n++) write_name[n] = (unsigned char)filename[n] < 32 ? '_' : filename[n]; fprintf(file, "# %s\n", write_name); } fprintf(file, "start=%f\n", pos); for (int i = 0; backup_properties[i]; i++) { const char *pname = backup_properties[i]; char *val = NULL; int r = mp_property_do(pname, M_PROPERTY_GET_STRING, &val, mpctx); if (r == M_PROPERTY_OK) { if (strncmp(pname, "options/", 8) == 0) pname += 8; // Only store it if it's different from the initial value. char *prev = mpctx->resume_defaults[i]; if (!prev || strcmp(prev, val) != 0) { if (needs_config_quoting(val)) { // e.g. '%6%STRING' fprintf(file, "%s=%%%d%%%s\n", pname, (int)strlen(val), val); } else { fprintf(file, "%s=%s\n", pname, val); } } } talloc_free(val); } fclose(file); exit: talloc_free(conffile); }
void mp_parse_cfgfiles(struct MPContext *mpctx) { struct MPOpts *opts = mpctx->opts; if (!opts->load_config) return; mp_mk_config_dir(mpctx->global, ""); m_config_t *conf = mpctx->mconfig; char *section = NULL; bool encoding = opts->encode_opts && opts->encode_opts->file && opts->encode_opts->file[0]; // 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"; load_all_cfgfiles(mpctx, SECT_ENCODE, "encoding-profiles.conf"); } load_all_cfgfiles(mpctx, section, "mpv.conf|config"); if (encoding) m_config_set_profile(conf, SECT_ENCODE, 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; }
void mp_write_watch_later_conf(struct MPContext *mpctx) { void *tmp = talloc_new(NULL); char *filename = mpctx->filename; if (!filename) goto exit; double pos = get_current_time(mpctx); if (pos == MP_NOPTS_VALUE) goto exit; mp_mk_config_dir(mpctx->global, MP_WATCH_LATER_CONF); char *conffile = mp_get_playback_resume_config_filename(mpctx->global, mpctx->filename); talloc_steal(tmp, conffile); if (!conffile) goto exit; MP_INFO(mpctx, "Saving state.\n"); FILE *file = fopen(conffile, "wb"); if (!file) goto exit; fprintf(file, "start=%f\n", pos); for (int i = 0; backup_properties[i]; i++) { const char *pname = backup_properties[i]; char *val = NULL; int r = mp_property_do(pname, M_PROPERTY_GET_STRING, &val, mpctx); if (r == M_PROPERTY_OK) { if (strncmp(pname, "options/", 8) == 0) pname += 8; // Only store it if it's different from the initial value. char *prev = mpctx->resume_defaults[i]; if (!prev || strcmp(prev, val) != 0) { if (needs_config_quoting(val)) { // e.g. '%6%STRING' fprintf(file, "%s=%%%d%%%s\n", pname, (int)strlen(val), val); } else { fprintf(file, "%s=%s\n", pname, val); } } } talloc_free(val); } fclose(file); exit: talloc_free(tmp); }
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; }
void mp_write_watch_later_conf(struct MPContext *mpctx) { struct playlist_entry *cur = mpctx->playing; char *conffile = NULL; if (!cur) goto exit; struct demuxer *demux = mpctx->demuxer; if (demux && (!demux->seekable || demux->partially_seekable)) { MP_INFO(mpctx, "Not seekable - not saving state.\n"); goto exit; } conffile = mp_get_playback_resume_config_filename(mpctx, cur->filename); if (!conffile) goto exit; mp_mk_config_dir(mpctx->global, mpctx->cached_watch_later_configdir); MP_INFO(mpctx, "Saving state.\n"); FILE *file = fopen(conffile, "wb"); if (!file) goto exit; write_filename(mpctx, file, cur->filename); double pos = get_current_time(mpctx); if (pos != MP_NOPTS_VALUE) fprintf(file, "start=%f\n", pos); for (int i = 0; backup_properties[i]; i++) { const char *pname = backup_properties[i]; char *val = NULL; int r = mp_property_do(pname, M_PROPERTY_GET_STRING, &val, mpctx); if (r == M_PROPERTY_OK) { if (strncmp(pname, "options/", 8) == 0) pname += 8; // Only store it if it's different from the initial value. char *prev = mpctx->resume_defaults[i]; if (!prev || strcmp(prev, val) != 0) { if (needs_config_quoting(val)) { // e.g. '%6%STRING' fprintf(file, "%s=%%%d%%%s\n", pname, (int)strlen(val), val); } else { fprintf(file, "%s=%s\n", pname, val); } } } talloc_free(val); } fclose(file); // This allows us to recursively resume directories etc., whose entries are // expanded the first time it's "played". For example, if "/a/b/c.mkv" is // the current entry, then we want to resume this file if the user does // "mpv /a". This would expand to the directory entries in "/a", and if // "/a/a.mkv" is not the first entry, this would be played. // Here, we write resume entries for "/a" and "/a/b". // (Unfortunately, this will leave stray resume files on resume, because // obviously it resumes only from one of those paths.) for (int n = 0; n < cur->num_redirects; n++) write_redirect(mpctx, cur->redirects[n]); // And at last, for local directories, we write an entry for each path // prefix, so the user can resume from an arbitrary directory. This starts // with the first redirect (all other redirects are further prefixes). if (cur->num_redirects) { char *path = cur->redirects[0]; char tmp[4096]; if (!mp_is_url(bstr0(path)) && strlen(path) < sizeof(tmp)) { snprintf(tmp, sizeof(tmp), "%s", path); for (;;) { bstr dir = mp_dirname(tmp); if (dir.len == strlen(tmp) || !dir.len || bstr_equals0(dir, ".")) break; tmp[dir.len] = '\0'; if (strlen(tmp) >= 2) // keep "/" mp_path_strip_trailing_separator(tmp); write_redirect(mpctx, tmp); } } } exit: talloc_free(conffile); }