summaryrefslogtreecommitdiffstats
path: root/mpvcore
diff options
context:
space:
mode:
Diffstat (limited to 'mpvcore')
-rw-r--r--mpvcore/av_log.c41
-rw-r--r--mpvcore/av_log.h2
-rw-r--r--mpvcore/command.c31
-rw-r--r--mpvcore/lua/osc.lua110
-rw-r--r--mpvcore/m_config.c7
-rw-r--r--mpvcore/m_config.h2
-rw-r--r--mpvcore/mp_ring.c12
-rw-r--r--mpvcore/mplayer.c41
-rw-r--r--mpvcore/options.c5
-rw-r--r--mpvcore/parser-cfg.c50
-rw-r--r--mpvcore/playlist_parser.c3
-rw-r--r--mpvcore/resolve_quvi9.c7
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;
}