Commit Graph

51 Commits

Author SHA1 Message Date
sfan5 6479646f41 player/scripting: fix use-after-free when loading script folders 2021-04-08 23:47:35 +03:00
wm4 13d354e46d auto_profiles: add this script
This is taken from a somewhat older proof-of-concept script. The basic
idea, and most of the implementation, is still the same. The way the
profiles are actually defined changed.

I still feel bad about this being a Lua script, and running user
expressions as Lua code in a vaguely defined environment, but I guess as
far as balance of effort/maintenance/results goes, this is fine.

It's a bit bloated (the Lua scripting state is at least 150KB or so in
total), so in order to enable this by default, I decided it should
unload itself by default if no auto-profiles are used. (And currently,
it does not actually rescan the profile list if a new config file is
loaded some time later, so the script would do nothing anyway if no auto
profiles were defined.)

This still requires defining inverse profiles for "unapplying" a
profile. Also this is still somewhat racy. Both will probably be
alleviated to some degree in the future.
2020-08-05 22:37:47 +02:00
wm4 adbd28b1db player: fix outdated comment 2020-07-09 12:26:54 +02:00
wm4 5ebb498b7a scripting: make socket FD number for subprocesses dynamic
Before this, we pretty much guaranteed that --mpv-ipc-fd=3 would be
passed. The FD  was hardcoded, so scripts started by this mechanism
didn't need to actually parse the argument. Change this to using a
mostly random FD number instead.

I decided to do this because posix_spawnp() and the current replacement
cannot "guarantee" a FD layout. posix_spawn_file_actions_adddup2() just
runs dup2() calls, so it may be hard to set FD 3/4 if they are already
used by something else. For example imagine trying to map:

    {.fd = 3, .src_fd = 4},
    {.fd = 4, .src_fd = 3},

Then it'd do dup2(4, 3), dup2(3, 4) (reminder: dup2(src, dst)), and the
end result is that FD 4 really maps to the original FD 4.

While this was not a problem in the present code, it's too messy that I
don't want to pretend it can always done this way without an unholy
mess. So my assumption is that FDs 0-2 can be freely assigned because
they're never closed (probably...), while for all other FDs only
pass-through is reasonable.
2020-05-15 16:37:41 +02:00
wm4 1c66e03ae5 scripting: correct passing FDs
For external scripts/processes which use IPC. The mistake didn't really
matter.
2020-05-15 16:37:41 +02:00
wm4 1a72037720 scripting: remove race condition when toggling internal scripts
Scripts such as the OSC can be loaded and unloaded at runtime by
toggling the option that enables them. (It even works, although normally
it's only used to control initial loading.)

Unloading was racy because it used the client name; fix this.

The load-script change is an accidental feature. And probably useless.
2020-03-26 23:59:44 +01:00
wm4 c43fd88f59 scripting: fix racy crash if loading .run files fails
args->client was deallocated if the FDs were closed and nothing
referenced it (IPC socket codes detected the closed sockets and
asynchronously killed the mpv_handle in args->client). The problem was
that args->log depended on it, and was also destroyed.

Fix this by duplicating the mp_log.
2020-02-25 22:41:09 +01:00
wm4 e2ab6b7f35 scripting: add a way to run sub processes as "scripts"
This is just a more convenient way to start IPC client scripts per mpv
instance.

Does not work on Windows, although it could if the subprocess and IPC
parts are implemented (and I guess .exe/.bat suffixes are required).
Also untested whether it builds on Windows. A lot of other things are
untested too, so don't complain.
2020-02-19 22:18:15 +01:00
wm4 c58f9a6579 scripting: give proper name to scripts using a directory
The recently added feature to load scripts from a sub-directory. A
problem was that the script name was still derived from the actual
script source file that was loaded, which was always "main.lua" (or
similar), resulting in "main" as name.

Fix this by using the directory name.

One odd corner case is that you can do "--script=/path/foo////". As by
POSIX semantics, the extra "/" are ignored. However, the newly added
code strips only one separator, so mp_basename() returns "" (as it
should), and the empty name makes mp_new_client() fail in turn. I don't
really care about this, just don't do it. But mp_new_client() failure
was silent (since it normally never happens), so add at least an error
message for that, instead of being entirely silent.
2020-02-06 19:38:22 +01:00
wm4 da38caff9c scripting: load scripts from directories
The intention is to provide a slightly nicer way to distribute scripts.
For example, you could put multiple source files into the directory, and
then import them from the actual script file (this is still
unimplemented).

At first I wanted to require a config file (because you need to know at
least which scripting backend it should use). This wouldn't have been
too hard (could have reused/abused the mpv config file parsing
mechanism, and I already had working code that was just 2 function
calls). But probably better to do this without new config files, because
it might become a pain in the distant future.

So this just probes for "main.lua", "main.js", etc., until an existing
file is found.

Another important change is that this skips all directory entries whose
name starts with ".". This automatically excludes the "." and ".."
special directories, and is probably useful to exclude random crap that
might be lying around in the directory (such as editor temporary files,
or OSX, in its usual hrmful, annoying, and idiotic modus operandi,
sharting all over any directories opened by "Finder").

Although the changelog mentions the docs, they're added only in a later
commit.
2020-02-01 18:09:40 +01:00
wm4 00cdda2ae8 scripting: make player error when attempting to load unknown scripts
It's ridiculous that --script=something.dumb does not cause an error.
Make it error, and extend this behavior to the scripts/ sub-dir in the
mpv config dir.
2020-01-19 19:25:54 +01:00
James Ross-Gowan b3b2cc44fa console.lua: add this script
Merged from mpv-repl git repo commit 5ea2bf64f9c239f0326b02. Some
changes were made on top of it:

- Tabs were converted to 4 spaces indentation (plus some manual
  indentation fixes in some places).
- All user-visible mentions of "repl" were renamed to "console".
- The README was converted to a manpage (with heavy changes, some
  additions taken from stats.rst; rossy converted the key bindings
  table to RST).
- The method to change the default key binding was changed.
- Change minor detail about "font" default value setting (not a
  functional change).
- Integrate into the player as builtin script, including an option to
  prevent loading it.

Above changes and commit message done by wm4.

Signed-off-by: wm4 <wm4@nowhere>
2019-12-08 02:46:44 +01:00
wm4 11c573fda0 scripting: change when/how player waits for scripts being loaded
Fundamentally, scripts are loaded asynchronously, but as a feature,
there was code to wait until a script is loaded (for a certain arbitrary
definition of "loaded"). This was done in scripting.c with the
wait_loaded() function.

This called mp_idle(), and since there are commands to load/unload
scripts, it meant the player core loop could be entered recursively. I
think this is a major complication and has some problems. For example,
if you had a script that does 'os.execute("sleep inf")', then every time
you ran a command to load an instance of the script would add a new
stack frame of mp_idle(). This would lead to some sort of reentrancy
horror that is hard to debug. Also misc/dispatch.c contains a somewhat
tricky mess to support such recursive invocations. There were also some
bugs due to this and due to unforeseen interactions with other messes.

This scripting stuff was the only thing making use of that reentrancy,
and future commands that have "logical" waiting for something should be
implemented differently. So get rid of it.

Change the code to wait only in the player initialization phase: the
only place where it really has to wait is before playback is started,
because scripts might want to set options or hooks that interact with
playback initialization. Unloading of builtin scripts (can happen with
e.g. "set osc no") is left asynchronous; the unloading wasn't too robust
anyway, and this change won't make a difference if someone is trying to
break it intentionally. Note that this is not in mp_initialize(),
because mpv_initialize() uses this by locking the core, which would have
the same problem.

In the future, commands which logically wait should use different
mechanisms. Originally I thought the current approach (that is removed
with this commit) should be used, but it's too much of a mess and can't
even be used in some cases. Examples are:
- "loadfile" should be made blocking (needs to run the normal player
  code and manually unblock the thread issuing the command)
- "add-sub" should not freeze the player until the URL is opened (needs
  to run opening on a separate thread)
Possibly the current scripting behavior could be restored once new
mechanisms exist, and if it turns out that anyone needs it.

With this commit there should be no further instances of recursive
playloop invocations (other than the case in the following commit),
since all mp_idle()/mp_wait_events() calls are done strictly from the
main thread (and not commands/properties or libmpv client API that
"lock" the main thread).
2018-04-18 01:17:41 +03:00
wm4 f60826c3a1
client API: add a first class hook API, and deprecate old API
As it turns out, there are multiple libmpv users who saw a need to
use the hook API. The API is kind of shitty and was never meant to be
actually public (it was mostly a hack for the ytdl script).

Introduce a proper API and deprecate the old one. The old one will
probably continue to work for a few releases, but will be removed
eventually.

There are some slight changes to the old API, but if a user followed
the manual properly, it won't break.

Mostly untested. Appears to work with ytdl_hook.
2018-03-26 23:02:23 -07:00
wm4 03791fae16 all: replace mpv_detach_destroy() with mpv_destroy() 2018-03-15 00:00:04 -07:00
wm4 a7f3cf4737 client API: add mpv_create_weak_client() 2018-03-15 00:00:04 -07:00
wm4 93fb79166b scripting: make a function static 2018-03-08 17:12:32 -08:00
Niklas Haas ba1943ac00 msg: reinterpret a bunch of message levels
I've decided that MP_TRACE means “noisy spam per frame”, whereas
MP_DBG just means “more verbose debugging messages than MSGL_V”.
Basically, MSGL_DBG shouldn't create spam per frame like it currently
does, and MSGL_V should make sense to the end-user and provide mostly
additional informational output.

MP_DBG is basically what I want to make the new default for --log-file,
so the cut-off point for MP_DBG is if we probably want to know if for
debugging purposes but the user most likely doesn't care about on the
terminal.

Also, the debug callbacks for libass and ffmpeg got bumped in their
verbosity levels slightly, because being external components they're a
bit less relevant to mpv debugging, and a bit too over-eager in what
they consider to be relevant information.

I exclusively used the "try it on my machine and remove messages from
MSGL_* until it does what I want it to" approach of refactoring, so
YMMV.
2017-12-15 22:28:47 -08:00
Nicolas F 2e24f5f1b5 scripting: report dlerror() output
dlopen() and dlsym() can fail in various ways, and we can find out
how it failed by calling dlerror(). This is particularly useful if
you typo the filename of a script when explicitly passing it with
--script, and dlopen actually tells you that the file doesn't exist
instead of leading you down a rabbit hole of disassembling your
shared object file to figure out why the thing won't load.
2017-12-01 21:13:48 +01:00
Julian 92a9150cc2 lua: integrate stats.lua script
Signed-off-by: wm4 <wm4@nowhere>

Rename --stats to --load-stats-overlay and add an entry to options.rst
over the original commit.

Signed-off-by: wm4 <wm4@nowhere>
2017-10-09 20:47:33 +02:00
Ricardo Constantino c1f46dbbe9
scripting: add wrapper to load scripts with user paths
Fixes regression since b2f756c80e, which broke load-script command
when used with user paths (ex: ~~/script.lua)
2017-06-30 15:03:10 +01:00
Avi Halachmi (:avih) d223a63bc5 js: add javascript scripting support using MuJS
Implements JS with almost identical API to the Lua support.

Key differences from Lua:
- The global mp, mp.msg and mp.utils are always available.
- Instead of returning x, error, return x and expose mp.last_error().
- Timers are JS standard set/clear Timeout/Interval.
- Supports CommonJS modules/require.
- Added at mp.utils: getenv, read_file, write_file and few more.
- Global print and dump (expand objects) functions.
- mp.options currently not supported.

See DOCS/man/javascript.rst for more details.
2017-06-14 12:29:32 +02:00
Hoyon Mak b2f756c80e scripting: expand --script filename for C plugins 2017-06-09 19:42:12 +02:00
wm4 e91331e683 scripting: don't call dlclose() on C plugins
Can break things quite badly.

Example: reloading a plugin linked against GTK 3.x can cause a segfault
if you call dlclose() on it. According to GTK developers, unloading the
GTK library is unsupported.
2017-01-14 17:14:30 +01:00
wm4 191cdbd31e scripting: minor logging improvements
Give scripting backends a proper name, instead of calling everything
"scripts".

Log client exit directly in client.c, as that is more general (doesn't
change actual output).
2017-01-14 17:13:50 +01:00
wm4 44e06b70d5 player: add experimental C plugin interface
This basically reuses the scripting infrastructure.

Note that this needs to be explicitly enabled at compilation. For one,
enabling export for certain symbols from an executable seems to be quite
toolchain-specific. It might not work outside of Linux and cause random
problems within Linux.

If C plugins actually become commonly used and this approach is starting
to turn out as a problem, we can build mpv CLI as a wrapper for libmpv,
which would remove the requirement that plugins pick up host symbols.

I'm being lazy, so implementation/documentation are parked in existing
files, even if that stuff doesn't necessarily belong there. Sue me, or
better send patches.
2017-01-12 17:45:11 +01:00
wm4 a314b1013f scripting: don't attempt to load builtin scripts twice
During init it will first call mp_load_builtin_scripts(), and then again
via mp_load_scripts().

This was harmless (a second attempt won't load it again if the first one
was successful), but it's unnecessary, and also looks confusing if the
scripts failed to load the first time.
2016-09-26 16:49:35 +02:00
wm4 2ac74977c5 command: add a load-script command
The intention is to give libmpv users as much flexibility to load
scripts as using mpv from CLI, but without restricting libmpv users from
having to decide everything on creation time, or having to go through
hacks like recreating the libmpv context to update state.
2016-09-22 20:57:06 +02:00
wm4 fb67db8b72 player: make --osc/--ytdl settable during playback
Setting the osc or ytdl properties will now load/unload the associated
scripts. (For ytdl this does not mean the currently played URL will be
reloaded.)

Also add a changelog entry for this, which also covers the preceding
work for --terminal.
2016-09-20 01:24:27 +02:00
wm4 03fec24e19 player: litter code with explicit wakeup calls
This does 3 kinds of changes:
- change sleeptime=x to mp_set_timeout()
- change sleeptime=0 to mp_wakeup_core() calls (to be more explicit)
- change commands etc. to call mp_wakeup_core() if they do changes that
  require the playloop to be rerun

This is preparation for the following changes. The goal is to process
client API requests without having to rerun the playloop every time. As
of this commit, the changes should not change behavior. In particular,
the playloop is still implicitly woken up on every command.
2016-09-16 14:39:45 +02:00
wm4 8a9b64329c Relicense some non-MPlayer source files to LGPL 2.1 or later
This covers source files which were added in mplayer2 and mpv times
only, and where all code is covered by LGPL relicensing agreements.

There are probably more files to which this applies, but I'm being
conservative here.

A file named ao_sdl.c exists in MPlayer too, but the mpv one is a
complete rewrite, and was added some time after the original ao_sdl.c
was removed. The same applies to vo_sdl.c, for which the SDL2 API is
radically different in addition (MPlayer supports SDL 1.2 only).

common.c contains only code written by me. But common.h is a strange
case: although it originally was named mp_common.h and exists in MPlayer
too, by now it contains only definitions written by uau and me. The
exceptions are the CONTROL_ defines - thus not changing the license of
common.h yet.

codec_tags.c contained once large tables generated from MPlayer's
codecs.conf, but all of these tables were removed.

From demux_playlist.c I'm removing a code fragment from someone who was
not asked; this probably could be done later (see commit 15dccc37).

misc.c is a bit complicated to reason about (it was split off mplayer.c
and thus contains random functions out of this file), but actually all
functions have been added post-MPlayer. Except get_relative_time(),
which was written by uau, but looks similar to 3 different versions of
something similar in each of the Unix/win32/OSX timer source files. I'm
not sure what that means in regards to copyright, so I've just moved it
into another still-GPL source file for now.

screenshot.c once had some minor parts of MPlayer's vf_screenshot.c, but
they're all gone.
2016-01-19 18:36:06 +01:00
wm4 04c02796bd path: make mp_path_join accept normal C strings
Instead of bstr. Most callers of this function do not need bstr. The
bstr version of this function is now mp_path_join_bstr().
2015-05-09 15:26:47 +02:00
wm4 40997b8ae5 lua: remove deprecated "lua" sub directories
The compatibility code and the deprecation warning were at least in
releases 0.8 and 0.9 - time to get rid of them.
2015-05-09 15:04:05 +02:00
wm4 d01228058b player: properly destroy client context if thread can't be created
Minor leak in an obscure out of memory case.
2015-04-30 21:57:08 +02:00
wm4 fcec3df700 scripting: fix/improve deprecation message
The message was missing a '\n', so it was merged with the next line,
which also typically caused it not to be printed with the colors for
warnings.

Print the full new path in the warning message. (Normally, cfg should
never be NULL, so accounting for this case is just for robustness.)
2014-12-15 06:24:05 +01:00
Avi Halachmi (:avih) 39e04e9294 options: deprecate 'lua' based options/dirs for 'script'
- --lua and --lua-opts change to --script and --script-opts
- 'lua' default script dirs change to 'scripts'
- DOCS updated

- 'lua-settings' dir was _not_ modified

The old lua-based names/dirs still work, but display a warning.

Signed-off-by: wm4 <wm4@nowhere>
2014-12-15 04:39:56 +01:00
wm4 079ecd7f01 player: integrate ytdl_hook.lua 2014-11-19 18:59:38 +01:00
wm4 600221e723 osdep: limit thread names to 16 characters
It turns out the glibc people are very clever and return an error if the
thread name exceeds the maximum supported kernel length, instead of
truncating the name. So everyone has to hardcode the currently allowed
Linux kernel name length limit, even if it gets extended later.

Also the Lua script filenames could get too long; use the client name
instead.

Another strange thing is that on Linux, unrelated threads "inherit" the
name by the thread they were created. This leads to random thread names,
because there's not necessarily a strong relation between these threads
(e.g. script command leads to filter recreation -> the filter's threads
are tagged with the script's thread name). Unfortunate.
2014-10-20 00:17:11 +02:00
wm4 9ba6641879 Set thread name for debugging
Especially with other components (libavcodec, OSX stuff), the thread
list can get quite populated. Setting the thread name helps when
debugging.

Since this is not portable, we check the OS variants in waf configure.
old-configure just gets a special-case for glibc, since doing a full
check here would probably be a waste of effort.
2014-10-19 23:48:40 +02:00
wm4 201a656350 win32: get rid of mp_stat in the normal source code
mp_stat() instead of stat() was used in the normal code (i.e. even
on Unix), because MinGW-w64 has an unbelievable macro-mess in place,
which prevents solving this elegantly.

Add some dirty workarounds to hide mp_stat() from the normal code
properly. This now requires replacing all functions that use the
struct stat type. This includes fstat, lstat, fstatat, and possibly
others. (mpv currently uses stat and fstat only.)
2014-10-17 22:15:19 +02:00
wm4 5fb05940f1 player: open stream and demuxer asynchronously
Run opening the stream and opening the demuxer in a separate thread.
This should remove the last code paths in which the player can normally
get blocked on network.

When the stream is opened, the player will still react to input and so
on. Commands to abort opening can also be handled properly, instead of
using some of the old hacks in input.c. The only thing the user can
really do is aborting loading by navigating the playlist or quitting.
Whether playback abort works depends on the stream implementation; with
normal network, this will depend on what libavformat (via "interrupt"
callback) does.

Some pain is caused by DVD/BD/DVB. These want to reload the demuxer
sometimes. DVB wants it in order to discard old, inactive streams.
DVD/BD for the same reason, and also for reloading stream languages
and similar metadata. This means the stream and the demuxer have to
be loaded separately.

One minor detail is that we now need to copy all global options. This
wasn't really needed before, because the options were accessed on
opening only, but since opening is now on a separate thread, this
obviously becomes a necessity.
2014-10-06 21:49:26 +02:00
wm4 017b3fa9db lua: synchronously wait until scripts are loaded
This makes the player wait until each script is loaded. Do this to give
the script a chance to setup all its event handlers. It might also be
useful to allow a script to change options that matter for playback.

While waiting for a script to be loaded, the player actually accepts
input. This is needed because the scripts can execute player commands
anyway while they are being "loaded". The player won't react to most
commands though: it can't quit or navigate the playlist in this state.

For deciding whether a script is finally loaded, we use a cheap hack: if
mpv_wait_event() is called, it's considered loaded. Let's hope this is
good enough. I think it's better than introducing explicit API for this.
Although I'm sure this will turn out as too simplistic some time in the
future, the same would probably happen with a more explicit API.
2014-09-06 17:02:47 +02:00
wm4 68ff8a0484 Move compat/ and bstr/ directory contents somewhere else
bstr.c doesn't really deserve its own directory, and compat had just
a few files, most of which may as well be in osdep. There isn't really
any justification for these extra directories, so get rid of them.

The compat/libav.h was empty - just delete it. We changed our approach
to API compatibility, and will likely not need it anymore.
2014-08-29 12:31:52 +02:00
Ben Boeckel e023524481 player: don't sort a NULL list
This can occur if the directory does not have any files in it which
causes files to never be non-NULL for qsort.
2014-08-28 12:02:09 +02:00
wm4 f8c2dd1b78 build: include <strings.h> for strcasecmp()
It happens to work without strings.h on glibc or with _GNU_SOURCE, but
the POSIX standard requires including <strings.h>.

Hopefully fixes OSX build.
2014-07-10 08:29:32 +02:00
wm4 07bc199e35 scripting: shorten a line
Also allows it to deal with NULL return values, which currently is not
needed, but may or may not be required at some point in the future (what
if malloc fails).
2014-06-26 19:56:45 +02:00
Kenneth Zhou cb250d490c Basic xdg directory implementation
Search $XDG_CONFIG_HOME and $XDG_CONFIG_DIRS for config files.
This also negates the need to have separate user and global variants of
mp_find_config_file()

Closes #864, #109.

Signed-off-by: wm4 <wm4@nowhere>
2014-06-26 19:37:25 +02:00
wm4 99f5fef0ea Add more const
While I'm not very fond of "const", it's important for declarations
(it decides whether a symbol is emitted in a read-only or read/write
section). Fix all these cases, so we have writeable global data only
when we really need.
2014-06-11 00:39:14 +02:00
wm4 fca608ccb9 client API: rename mpv_destroy() to mpv_detach_destroy()
A bit verbose, but less misleading. In most cases, the API user probably
actually wants mpv_terminate_destroy() instead, so the less-useful
function shouldn't have a simnpler name anyway.
2014-06-07 20:25:48 +02:00
wm4 99e498611e lua: make warning about unknown scripts -v only 2014-06-04 00:33:17 +02:00