diff options
Diffstat (limited to 'mpvcore')
-rw-r--r-- | mpvcore/av_log.c | 41 | ||||
-rw-r--r-- | mpvcore/av_log.h | 2 | ||||
-rw-r--r-- | mpvcore/command.c | 31 | ||||
-rw-r--r-- | mpvcore/lua/osc.lua | 110 | ||||
-rw-r--r-- | mpvcore/m_config.c | 7 | ||||
-rw-r--r-- | mpvcore/m_config.h | 2 | ||||
-rw-r--r-- | mpvcore/mp_ring.c | 12 | ||||
-rw-r--r-- | mpvcore/mplayer.c | 41 | ||||
-rw-r--r-- | mpvcore/options.c | 5 | ||||
-rw-r--r-- | mpvcore/parser-cfg.c | 50 | ||||
-rw-r--r-- | mpvcore/playlist_parser.c | 3 | ||||
-rw-r--r-- | mpvcore/resolve_quvi9.c | 7 |
12 files changed, 215 insertions, 96 deletions
diff --git a/mpvcore/av_log.c b/mpvcore/av_log.c index c233984be9..9fa6fc93ae 100644 --- a/mpvcore/av_log.c +++ b/mpvcore/av_log.c @@ -41,6 +41,13 @@ #include <libavfilter/avfilter.h> #endif +#ifdef CONFIG_LIBAVRESAMPLE +#include <libavresample/avresample.h> +#endif +#ifdef CONFIG_LIBSWRESAMPLE +#include <libswresample/swresample.h> +#endif + static int av_log_level_to_mp_level(int av_level) { if (av_level > AV_LOG_VERBOSE) @@ -140,22 +147,30 @@ void init_libav(void) } #define V(x) (x)>>16, (x)>>8 & 255, (x) & 255 -static void print_version(char *name, unsigned buildv, unsigned runv) +static void print_version(int v, char *name, unsigned buildv, unsigned runv) { - - if (buildv == runv) - mp_msg(MSGT_CPLAYER, MSGL_V, "Compiled against %s version %d.%d.%d\n", - name, V(buildv)); - else - mp_msg(MSGT_CPLAYER, MSGL_V, "Compiled against %s version %d.%d.%d " - "(runtime %d.%d.%d)\n", name, V(buildv), V(runv)); + mp_msg(MSGT_CPLAYER, v, " %-15s %d.%d.%d", name, V(buildv)); + if (buildv != runv) + mp_msg(MSGT_CPLAYER, v, " (runtime %d.%d.%d)", V(runv)); + mp_msg(MSGT_CPLAYER, v, "\n"); } #undef V -void print_libav_versions(void) +void print_libav_versions(int v) { - print_version("libavutil", LIBAVUTIL_VERSION_INT, avutil_version()); - print_version("libavcodec", LIBAVCODEC_VERSION_INT, avcodec_version()); - print_version("libavformat", LIBAVFORMAT_VERSION_INT, avformat_version()); - print_version("libswscale", LIBSWSCALE_VERSION_INT, swscale_version()); + mp_msg(MSGT_CPLAYER, v, "%s library versions:\n", LIB_PREFIX); + + print_version(v, "libavutil", LIBAVUTIL_VERSION_INT, avutil_version()); + print_version(v, "libavcodec", LIBAVCODEC_VERSION_INT, avcodec_version()); + print_version(v, "libavformat", LIBAVFORMAT_VERSION_INT, avformat_version()); + print_version(v, "libswscale", LIBSWSCALE_VERSION_INT, swscale_version()); +#ifdef CONFIG_LIBAVFILTER + print_version(v, "libavfilter", LIBAVFILTER_VERSION_INT, avfilter_version()); +#endif +#ifdef CONFIG_LIBAVRESAMPLE + print_version(v, "libavresample", LIBAVRESAMPLE_VERSION_INT, avresample_version()); +#endif +#ifdef CONFIG_LIBSWRESAMPLE + print_version(v, "libswresample", LIBSWRESAMPLE_VERSION_INT, swresample_version()); +#endif } diff --git a/mpvcore/av_log.h b/mpvcore/av_log.h index 833a7af03b..d5c57b0aeb 100644 --- a/mpvcore/av_log.h +++ b/mpvcore/av_log.h @@ -1,2 +1,2 @@ void init_libav(void); -void print_libav_versions(void); +void print_libav_versions(int v); diff --git a/mpvcore/command.c b/mpvcore/command.c index 038e58bc8d..fdb507962f 100644 --- a/mpvcore/command.c +++ b/mpvcore/command.c @@ -768,9 +768,13 @@ static int mp_property_volume(m_option_t *prop, int action, void *arg, mixer_getbothvolume(mpctx->mixer, arg); return M_PROPERTY_OK; case M_PROPERTY_SET: + if (!mixer_audio_initialized(mpctx->mixer)) + return M_PROPERTY_ERROR; mixer_setvolume(mpctx->mixer, *(float *) arg, *(float *) arg); return M_PROPERTY_OK; case M_PROPERTY_SWITCH: { + if (!mixer_audio_initialized(mpctx->mixer)) + return M_PROPERTY_ERROR; struct m_property_switch_arg *sarg = arg; if (sarg->inc <= 0) mixer_decvolume(mpctx->mixer); @@ -788,6 +792,8 @@ static int mp_property_mute(m_option_t *prop, int action, void *arg, { switch (action) { case M_PROPERTY_SET: + if (!mixer_audio_initialized(mpctx->mixer)) + return M_PROPERTY_ERROR; mixer_setmute(mpctx->mixer, *(int *) arg); return M_PROPERTY_OK; case M_PROPERTY_GET: @@ -2395,12 +2401,12 @@ void run_command(MPContext *mpctx, mp_cmd_t *cmd) if (r == M_PROPERTY_OK || r == M_PROPERTY_UNAVAILABLE) { show_property_osd(mpctx, cmd->args[0].v.s, cmd->on_osd); } else if (r == M_PROPERTY_UNKNOWN) { - mp_msg(MSGT_CPLAYER, MSGL_WARN, - "Unknown property: '%s'\n", cmd->args[0].v.s); + set_osd_msg(mpctx, OSD_MSG_TEXT, osdl, osd_duration, + "Unknown property: '%s'", cmd->args[0].v.s); } else if (r <= 0) { - mp_msg(MSGT_CPLAYER, MSGL_WARN, - "Failed to set property '%s' to '%s'.\n", - cmd->args[0].v.s, cmd->args[1].v.s); + set_osd_msg(mpctx, OSD_MSG_TEXT, osdl, osd_duration, + "Failed to set property '%s' to '%s'", + cmd->args[0].v.s, cmd->args[1].v.s); } break; } @@ -2418,12 +2424,12 @@ void run_command(MPContext *mpctx, mp_cmd_t *cmd) if (r == M_PROPERTY_OK || r == M_PROPERTY_UNAVAILABLE) { show_property_osd(mpctx, cmd->args[0].v.s, cmd->on_osd); } else if (r == M_PROPERTY_UNKNOWN) { - mp_msg(MSGT_CPLAYER, MSGL_WARN, - "Unknown property: '%s'\n", cmd->args[0].v.s); + set_osd_msg(mpctx, OSD_MSG_TEXT, osdl, osd_duration, + "Unknown property: '%s'", cmd->args[0].v.s); } else if (r <= 0) { - mp_msg(MSGT_CPLAYER, MSGL_WARN, - "Failed to increment property '%s' by %g.\n", - cmd->args[0].v.s, s.inc); + set_osd_msg(mpctx, OSD_MSG_TEXT, osdl, osd_duration, + "Failed to increment property '%s' by %g", + cmd->args[0].v.s, s.inc); } break; } @@ -2502,6 +2508,11 @@ void run_command(MPContext *mpctx, mp_cmd_t *cmd) set_osd_tmsg(mpctx, OSD_MSG_SUB_DELAY, osdl, osd_duration, "Sub delay: %d ms", ROUND(opts->sub_delay * 1000)); } else { + // We can easily get stuck by failing to seek to the video + // frame which actually shows the sub first (because video + // frame PTS and sub PTS rarely match exactly). Add some + // rounding for the mess of it. + a[0] += 0.01 * (a[1] > 0 ? 1 : -1); queue_seek(mpctx, MPSEEK_RELATIVE, a[0], 1); set_osd_function(mpctx, (a[0] > 0) ? OSD_FFW : OSD_REW); if (bar_osd) diff --git a/mpvcore/lua/osc.lua b/mpvcore/lua/osc.lua index 4b7c21abad..c724c7737c 100644 --- a/mpvcore/lua/osc.lua +++ b/mpvcore/lua/osc.lua @@ -10,17 +10,19 @@ local msg = require 'mp.msg' -- default user option values -- do not touch, change them in plugin_osc.conf local user_opts = { - showWindowed = true, -- show OSC when windowed? - showFullscreen = true, -- show OSC when fullscreen? - scaleWindowed = 1, -- scaling of the controller when windowed - scaleFullscreen = 1, -- scaling of the controller when fullscreen - scaleForcedWindow = 2, -- scaling of the controller when rendered on a forced (dummy) window + showwindowed = true, -- show OSC when windowed? + showfullscreen = true, -- show OSC when fullscreen? + scalewindowed = 1, -- scaling of the controller when windowed + scalefullscreen = 1, -- scaling of the controller when fullscreen + scaleforcedwindow = 2, -- scaling of the controller when rendered on a forced (dummy) window vidscale = true, -- scale the controller with the video? valign = 0.8, -- vertical alignment, -1 (top) to 1 (bottom) halign = 0, -- horizontal alignment, -1 (left) to 1 (right) + hidetimeout = 500, -- duration in ms until the OSC hides if no mouse movement, negative value disables autohide fadeduration = 200, -- duration of fade out in ms, 0 = no fade - deadzonedist = 0.15, -- distance between OSC and deadzone - iAmAProgrammer = false, -- use native mpv values and disable OSC internal playlist management (and some functions that depend on it) + deadzonesize = 0, -- size of deadzone + minmousemove = 3, -- minimum amount of pixels the mouse has to move between ticks to make the OSC show up + iamaprogrammer = false, -- use native mpv values and disable OSC internal playlist management (and some functions that depend on it) } local osc_param = { @@ -50,6 +52,7 @@ local osc_styles = { -- internal states, do not touch local state = { + showtime, -- time of last invocation (last mouse move) osc_visible = false, anistart, -- time when the animation started anitype, -- current type of animation @@ -62,6 +65,7 @@ local state = { mp_screen_sizeX, mp_screen_sizeY, -- last screen-resolution, to detect resolution changes to issue reINITs initREQ = false, -- is a re-init request pending? last_seek, -- last seek position, to avoid deadlocks by repeatedly seeking to the same position + last_mouseX, last_mouseY, -- last mouse position, to detect siginificant mouse movement message_text, message_timeout, } @@ -117,16 +121,7 @@ function read_config(options, identifier) local conffile = mp.find_config_file(conffilename) local f = io.open(conffile,"r") if f == nil then - msg.warn(conffile.." does not exist, creating it ...") - -- so create it, write default options - local f = io.open(conffile,"w+") - f:write("# Config file for "..identifier.."\n# <-- works only at beginning of line.\n# Do not have any spare spaces flying around.\n\n") - -- iterate over the options table - for key, value in pairs(options) do - f:write("#" .. key .. "=" .. val2str(value) .. "\n") - end - io.close(f) - + -- config not found else -- config exists, read values local linecounter = 1 @@ -227,7 +222,7 @@ function get_slider_value(element) end function countone(val) - if not (user_opts.iAmAProgrammer) then + if not (user_opts.iamaprogrammer) then val = val + 1 end return val @@ -641,17 +636,17 @@ function osc_init() -- kill old Elements elements = {} - -- set canvas resolution acording to display aspect and scaling setting + -- set canvas resolution according to display aspect and scaling setting local baseResY = 720 local display_w, display_h, display_aspect = mp.get_screen_size() local scale = 1 if (mp.property_get("video") == "no") then -- dummy/forced window - scale = user_opts.scaleForcedWindow + scale = user_opts.scaleforcedwindow elseif (mp.property_get("fullscreen") == "yes") then - scale = user_opts.scaleFullscreen + scale = user_opts.scalefullscreen else - scale = user_opts.scaleWindowed + scale = user_opts.scalewindowed end @@ -796,7 +791,7 @@ function osc_init() -- Smaller buttons -- - if not (user_opts.iAmAProgrammer) then + if not (user_opts.iamaprogrammer) then update_tracklist() end @@ -806,7 +801,7 @@ function osc_init() local eventresponder = {} local contentF - if not (user_opts.iAmAProgrammer) then + if not (user_opts.iamaprogrammer) then metainfo.enabled = (#tracks_osc.audio > 0) contentF = function (ass) @@ -843,7 +838,7 @@ function osc_init() local eventresponder = {} local contentF - if not (user_opts.iAmAProgrammer) then + if not (user_opts.iamaprogrammer) then metainfo.enabled = (#tracks_osc.sub > 0) contentF = function (ass) @@ -1004,6 +999,9 @@ end function show_osc() + --remember last time of invocation (mouse move) + state.showtime = mp.get_timer() + state.osc_visible = true if (user_opts.fadeduration > 0) then @@ -1024,36 +1022,51 @@ end function mouse_leave() hide_osc() + -- reset mouse position + state.last_mouseX, state.last_mouseY = nil, nil end function request_init() state.initREQ = true end --- called by mpv on every frame function render() local current_screen_sizeX, current_screen_sizeY = mp.get_screen_size() + local mouseX, mouseY = mp.get_mouse_pos() + local now = mp.get_timer() + -- check if display changed, if so request reinit if not (state.mp_screen_sizeX == current_screen_sizeX and state.mp_screen_sizeY == current_screen_sizeY) then - -- display changed, reinit everything request_init() state.mp_screen_sizeX, state.mp_screen_sizeY = current_screen_sizeX, current_screen_sizeY end + -- init management if state.initREQ then osc_init() state.initREQ = false + + -- store initial mouse position + if (state.last_mouseX == nil or state.last_mouseY == nil) and not (mouseX == nil or mouseY == nil) then + state.last_mouseX, state.last_mouseY = mouseX, mouseY + end end - if not(state.anitype == nil) then + -- autohide + if not (state.showtime == nil) and (user_opts.hidetimeout >= 0) and (state.showtime + (user_opts.hidetimeout/1000) < now) and (state.active_element == nil) + and not (mouseX >= osc_param.posX - (osc_param.osc_w / 2) and mouseX <= osc_param.posX + (osc_param.osc_w / 2) + and mouseY >= osc_param.posY - (osc_param.osc_h / 2) and mouseY <= osc_param.posY + (osc_param.osc_h / 2)) then + hide_osc() + end - local now = mp.get_timer() + -- fade animation + if not(state.anitype == nil) then if (state.anistart == nil) then state.anistart = now end - if (now < state.anistart + (user_opts.fadeduration/1000) ) then + if (now < state.anistart + (user_opts.fadeduration/1000)) then if (state.anitype == "in") then --fade in state.osc_visible = true @@ -1074,14 +1087,18 @@ function render() state.anitype = nil end + -- actual rendering local ass = assdraw.ass_new() + -- Messages render_message(ass) + -- actual OSC if state.osc_visible then render_elements(ass) end + -- submit local w, h, aspect = mp.get_screen_size() mp.set_osd_ass(osc_param.playresy * aspect, osc_param.playresy, ass.text) @@ -1089,23 +1106,28 @@ function render() local area_y0, area_y1 if user_opts.valign > 0 then -- deadzone above OSC - area_y0 = get_align(1 - user_opts.deadzonedist, osc_param.posY - (osc_param.osc_h / 2), 0, 0) + area_y0 = get_align(-1 + (2*user_opts.deadzonesize), osc_param.posY - (osc_param.osc_h / 2), 0, 0) area_y1 = osc_param.playresy else -- deadzone below OSC area_y0 = 0 area_y1 = (osc_param.posY + (osc_param.osc_h / 2)) - + get_align(-1 + user_opts.deadzonedist, osc_param.playresy - (osc_param.posY + (osc_param.osc_h / 2)), 0, 0) + + get_align(1 - (2*user_opts.deadzonesize), osc_param.playresy - (osc_param.posY + (osc_param.osc_h / 2)), 0, 0) end --mouse show/hide area mp.set_mouse_area(0, area_y0, osc_param.playresx, area_y1, "showhide") --mouse input area - mp.set_mouse_area( - osc_param.posX - (osc_param.osc_w / 2), osc_param.posY - (osc_param.osc_h / 2), - osc_param.posX + (osc_param.osc_w / 2), osc_param.posY + (osc_param.osc_h / 2), - "input") + if state.osc_visible then -- activate only when OSC is actually visible + mp.set_mouse_area( + osc_param.posX - (osc_param.osc_w / 2), osc_param.posY - (osc_param.osc_h / 2), + osc_param.posX + (osc_param.osc_w / 2), osc_param.posY + (osc_param.osc_h / 2), + "input") + mp.enable_key_bindings("input") + else + mp.disable_key_bindings("input") + end end @@ -1155,7 +1177,16 @@ function process_event(source, what) state.last_seek = nil elseif source == "mouse_move" then - show_osc() + local mouseX, mouseY = mp.get_mouse_pos() + if (user_opts.minmousemove == 0) or + (not ((state.last_mouseX == nil) or (state.last_mouseY == nil)) and + ((math.abs(mouseX - state.last_mouseX) >= user_opts.minmousemove) + or (math.abs(mouseY - state.last_mouseY) >= user_opts.minmousemove) + ) + ) then + show_osc() + end + state.last_mouseX, state.last_mouseY = mouseX, mouseY if not (state.active_element == nil) then @@ -1170,8 +1201,9 @@ function process_event(source, what) end end +-- called by mpv on every frame function tick() - if (mp.property_get("fullscreen") == "yes" and user_opts.showFullscreen) or (mp.property_get("fullscreen") == "no" and user_opts.showWindowed) then + if (mp.property_get("fullscreen") == "yes" and user_opts.showfullscreen) or (mp.property_get("fullscreen") == "no" and user_opts.showwindowed) then render() else mp.set_osd_ass(osc_param.playresy, osc_param.playresy, "") @@ -1192,7 +1224,7 @@ mp.set_key_bindings({ {"mouse_move", function(e) process_event("mouse_move", nil) end}, {"mouse_leave", mouse_leave}, }, "showhide") -mp.enable_key_bindings("showhide", "allow-vo-dragging") +mp.enable_key_bindings("showhide", "allow-vo-dragging|allow-hide-cursor") --mouse input bindings mp.set_key_bindings({ diff --git a/mpvcore/m_config.c b/mpvcore/m_config.c index d01d0ed07c..96c93f7c28 100644 --- a/mpvcore/m_config.c +++ b/mpvcore/m_config.c @@ -180,13 +180,12 @@ static void add_options(struct m_config *config, struct m_config_option *parent, const struct m_option *defs); -static int config_destroy(void *p) +static void config_destroy(void *p) { struct m_config *config = p; m_config_restore_backups(config); for (struct m_config_option *copt = config->opts; copt; copt = copt->next) m_option_free(copt->opt, copt->data); - return 0; } struct m_config *m_config_new(void *talloc_parent, size_t size, @@ -727,10 +726,10 @@ struct m_profile *m_config_add_profile(struct m_config *config, char *name) return p; } -void m_profile_set_desc(struct m_profile *p, char *desc) +void m_profile_set_desc(struct m_profile *p, bstr desc) { talloc_free(p->desc); - p->desc = talloc_strdup(p, desc); + p->desc = bstrdup0(p, desc); } int m_config_set_profile_option(struct m_config *config, struct m_profile *p, diff --git a/mpvcore/m_config.h b/mpvcore/m_config.h index 996d73f26e..871d1a3caf 100644 --- a/mpvcore/m_config.h +++ b/mpvcore/m_config.h @@ -188,7 +188,7 @@ struct m_profile *m_config_add_profile(struct m_config *config, char *name); * \param p The profile object. * \param arg The profile's name. */ -void m_profile_set_desc(struct m_profile *p, char *desc); +void m_profile_set_desc(struct m_profile *p, bstr desc); /* Add an option to a profile. * Used by the config file parser when defining a profile. diff --git a/mpvcore/mp_ring.c b/mpvcore/mp_ring.c index aa62c305be..822825e370 100644 --- a/mpvcore/mp_ring.c +++ b/mpvcore/mp_ring.c @@ -99,9 +99,17 @@ int mp_ring_read_cb(struct mp_ring *buffer, void *ctx, int len, int read_len = FFMIN(len, buffered); int read_ptr = mp_ring_get_rpos(buffer) % size; - func(ctx, buffer->buffer + read_ptr, read_len); + int len1 = FFMIN(size - read_ptr, read_len); + int len2 = read_len - len1; - return mp_ring_drain(buffer, read_len); + func(ctx, buffer->buffer + read_ptr, len1); + if (len2 > 0) + func(ctx, buffer->buffer, len2); + + mp_atomic_add_and_fetch(&buffer->rpos, read_len); + mp_memory_barrier(); + + return read_len; } int mp_ring_write(struct mp_ring *buffer, unsigned char *src, int len) diff --git a/mpvcore/mplayer.c b/mpvcore/mplayer.c index 7de8ff2abf..c0504caf5f 100644 --- a/mpvcore/mplayer.c +++ b/mpvcore/mplayer.c @@ -860,6 +860,17 @@ static const char *backup_properties[] = { 0 }; +// Should follow what parser-cfg.c does/needs +static bool needs_config_quoting(const char *s) +{ + for (int i = 0; s && s[i]; i++) { + unsigned char c = s[i]; + if (!isprint(c) || isspace(c) || c == '#' || c == '\'' || c == '"') + return true; + } + return false; +} + void mp_write_watch_later_conf(struct MPContext *mpctx) { void *tmp = talloc_new(NULL); @@ -889,8 +900,14 @@ void mp_write_watch_later_conf(struct MPContext *mpctx) 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) - fprintf(file, "%s=%s\n", pname, val); + if (r == M_PROPERTY_OK) { + 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); @@ -3377,13 +3394,8 @@ static bool handle_osd_redraw(struct MPContext *mpctx) want_redraw |= mpctx->osd->want_redraw; mpctx->osd->want_redraw = false; if (want_redraw) { - if (redraw_osd(mpctx)) { + if (redraw_osd(mpctx)) return true; - } else if (mpctx->paused) { - // force redrawing OSD by framestepping - add_step_frame(mpctx, 1); - return true; - } } return false; } @@ -4736,9 +4748,9 @@ struct playlist_entry *mp_next_file(struct MPContext *mpctx, int direction, if (mpctx->opts->shuffle) playlist_shuffle(mpctx->playlist); next = mpctx->playlist->first; - if (next && mpctx->opts->loop_times > 0) { + if (next && mpctx->opts->loop_times > 1) { mpctx->opts->loop_times--; - if (mpctx->opts->loop_times == 0) + if (mpctx->opts->loop_times == 1) mpctx->opts->loop_times = -1; } } else { @@ -4827,8 +4839,11 @@ void mp_set_playlist_entry(struct MPContext *mpctx, struct playlist_entry *e) void mp_print_version(int always) { - mp_msg(MSGT_CPLAYER, always ? MSGL_INFO : MSGL_V, + int v = always ? MSGL_INFO : MSGL_V; + mp_msg(MSGT_CPLAYER, v, "%s (C) 2000-2013 mpv/MPlayer/mplayer2 projects\n built on %s\n", mplayer_version, mplayer_builddate); + print_libav_versions(v); + mp_msg(MSGT_CPLAYER, v, "\n"); } static bool handle_help_options(struct MPContext *mpctx) @@ -4955,7 +4970,6 @@ static int mpv_main(int argc, char *argv[]) m_config_preparse_command_line(mpctx->mconfig, argc, argv); mp_print_version(false); - print_libav_versions(); if (!parse_cfgfiles(mpctx, mpctx->mconfig)) exit_player(mpctx, EXIT_ERROR); @@ -5009,6 +5023,9 @@ static int mpv_main(int argc, char *argv[]) #ifdef CONFIG_ASS mpctx->ass_library = mp_ass_init(opts); +#else + mp_msg(MSGT_CPLAYER, MSGL_WARN, "Compiled without libass.\n"); + mp_msg(MSGT_CPLAYER, MSGL_WARN, "There will be no OSD and no text subs.\n"); #endif mpctx->osd = osd_create(opts, mpctx->ass_library); diff --git a/mpvcore/options.c b/mpvcore/options.c index b0988bd6e2..0b5e5fde65 100644 --- a/mpvcore/options.c +++ b/mpvcore/options.c @@ -681,8 +681,8 @@ const m_option_t mp_opts[] = { {"lircconf", &lirc_configfile, CONF_TYPE_STRING, CONF_GLOBAL, 0, 0, NULL}, #endif - OPT_CHOICE_OR_INT("loop", loop_times, M_OPT_GLOBAL, 1, 10000, - ({"no", -1}, {"0", -1}, + OPT_CHOICE_OR_INT("loop", loop_times, M_OPT_GLOBAL, 2, 10000, + ({"no", -1}, {"1", -1}, {"inf", 0})), OPT_FLAG("resume-playback", position_resume, 0), @@ -802,6 +802,7 @@ const struct MPOpts mp_default_opts = { .osd_bar_w = 75.0, .osd_bar_h = 3.125, .osd_scale = 1, + .lua_load_osc = 1, .loop_times = -1, .ordered_chapters = 1, .chapter_merge_threshold = 100, diff --git a/mpvcore/parser-cfg.c b/mpvcore/parser-cfg.c index 763b1b1493..3395a67432 100644 --- a/mpvcore/parser-cfg.c +++ b/mpvcore/parser-cfg.c @@ -173,21 +173,45 @@ int m_config_parse_config_file(m_config_t *config, const char *conffile, } } line_pos++; /* skip the closing " or ' */ - } else { - for (param_pos = 0; isprint(line[line_pos]) - && !isspace(line[line_pos]) - && line[line_pos] != '#'; /* NOTHING */) { - param[param_pos++] = line[line_pos++]; - if (param_pos >= MAX_PARAM_LEN) { + goto param_done; + } + + if (line[line_pos] == '%') { + char *start = &line[line_pos + 1]; + char *end = start; + unsigned long len = strtoul(start, &end, 10); + if (start != end && end[0] == '%') { + if (len >= MAX_PARAM_LEN - 1 || + strlen(end + 1) < len) + { PRINT_LINENUM; - mp_msg(MSGT_CFGPARSER, MSGL_ERR, "too long parameter\n"); + mp_msg(MSGT_CFGPARSER, MSGL_ERR, "bogus %% length\n"); ret = -1; errors++; goto nextline; } + param_pos = snprintf(param, sizeof(param), "%.*s", + (int)len, end + 1); + line_pos += 1 + (end - start) + 1 + len; + goto param_done; } } + for (param_pos = 0; isprint(line[line_pos]) + && !isspace(line[line_pos]) + && line[line_pos] != '#'; /* NOTHING */) { + param[param_pos++] = line[line_pos++]; + if (param_pos >= MAX_PARAM_LEN) { + PRINT_LINENUM; + mp_msg(MSGT_CFGPARSER, MSGL_ERR, "too long parameter\n"); + ret = -1; + errors++; + goto nextline; + } + } + + param_done: + while (isspace(line[line_pos])) ++line_pos; } @@ -204,8 +228,11 @@ int m_config_parse_config_file(m_config_t *config, const char *conffile, bstr bopt = bstr0(opt); bstr bparam = bstr0(param); + if (bopt.len >= 3) + bstr_eatstart0(&bopt, "--"); + if (profile && bstr_equals0(bopt, "profile-desc")) { - m_profile_set_desc(profile, param); + m_profile_set_desc(profile, bparam); goto nextline; } @@ -215,8 +242,8 @@ int m_config_parse_config_file(m_config_t *config, const char *conffile, if (tmp < 0) { PRINT_LINENUM; mp_msg(MSGT_CFGPARSER, MSGL_ERR, - "error parsing option %s=%s: %s\n", - opt, param, m_option_strerror(tmp)); + "error parsing option %.*s=%.*s: %s\n", + BSTR_P(bopt), BSTR_P(bparam), m_option_strerror(tmp)); continue; } @@ -228,7 +255,8 @@ int m_config_parse_config_file(m_config_t *config, const char *conffile, if (tmp < 0) { PRINT_LINENUM; mp_msg(MSGT_CFGPARSER, MSGL_ERR, - "setting option %s='%s' failed.\n", opt, param); + "setting option %.*s='%.*s' failed.\n", + BSTR_P(bopt), BSTR_P(bparam)); continue; /* break */ } diff --git a/mpvcore/playlist_parser.c b/mpvcore/playlist_parser.c index 0b3be14716..7c77760df4 100644 --- a/mpvcore/playlist_parser.c +++ b/mpvcore/playlist_parser.c @@ -648,7 +648,8 @@ struct playlist *playlist_parse_file(const char *file, struct MPOpts *opts) struct playlist *ret = do_parse(stream, true); free_stream(stream); - playlist_add_base_path(ret, mp_dirname(file)); + if (ret) + playlist_add_base_path(ret, mp_dirname(file)); return ret; diff --git a/mpvcore/resolve_quvi9.c b/mpvcore/resolve_quvi9.c index 3fd2b3bd0f..ea96f521e3 100644 --- a/mpvcore/resolve_quvi9.c +++ b/mpvcore/resolve_quvi9.c @@ -17,6 +17,7 @@ #include <stdbool.h> #include <assert.h> +#include <locale.h> #include <quvi.h> @@ -146,5 +147,11 @@ struct mp_resolve_result *mp_resolve_quvi(const char *url, struct MPOpts *opts) talloc_free(res); res = NULL; } + + // libkdecore calls setlocale(LC_ALL, ""), which breaks basic C string + // processing functions. libkdecore can be loaded by libproxy, which is + // used by libquvi9. This is a rather dirty workaround to reset locales. + setlocale(LC_ALL, "C"); + return res; } |