Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

redesign of mpv command input system (make mplayers' slave mode saner) #252

Closed
aktau opened this issue Sep 21, 2013 · 39 comments
Closed

redesign of mpv command input system (make mplayers' slave mode saner) #252

aktau opened this issue Sep 21, 2013 · 39 comments

Comments

@aktau
Copy link

aktau commented Sep 21, 2013

NOTE: this issue is just a proof of concept, and perhaps we could turn it into a wiki page, any input welcome

Yesterday, me and @wm4 were talking about ways to improve on mplayers' slave mode. The current documentation mentions that it's insane, rightly so. Many apps that use mplayer resort to parsing the status line and other assorted messages intended for users to get the necessary information to display in their GUI or respond to mplayer. This is obviously bad: bug ridden, non-backwards and forwards compatible and wastes an unholy amount of CPU cycles. @wm4 says he's been brainstorming about this for some time without reaching a consensus, so I'd like to help. This issue was made to consolidate the possible approaches and finally reach a true consensus. Any comments welcome.

requirements

hard requirements:

  • structured format for developers that want to use mpv
  • backwards and forwards compatible: adding new fields should not disrupt older applications
  • cross platform (UNIX and windows, preferably more)
  • near-binary safe (for chapter information, which can contains values 1-255 for each char)

nice to have:

  • simple text input mode (such that good old echo "loadfile myvideo.mkv" > somefifo can still work). Sending back structured, binary safe information almost forces one to use a TLV-style encoding, but perhaps there are some encodings which provide a fallback (and indeed there are, see the redis topic)

There are 3 separate things here that need to be thought of: communication channel, encoding (format) and protocol. The communication channel is a totally separate layer from the other two, and should be coded this way. The encoding and protocol will most likely be related to and influenced by each other. Though ideally they should be separate.

communication channel

Many types of communication channels can be supported at the same time, perhaps any one of them should be enable-disable-able with a configure switch. This works well with the greedy configure approach currently taken.

A list of some possibilities (some of them already implemented):

  • pipes (present in mpv/mplayer) - posix/windows
  • UNIX fifos (currently present in mpv/mplayer) - mkfifo et al - posix
  • input.conf (currently present in mpv/mplayer) - posix/windows
  • UNIX domain sockets (possibly) - posix
  • nanomsg (possibly) - posix/windows
  • zeromq (possibly) - posix/windows
  • TCP (possibly) - this would enable telnet control, pretty cool - posix/windows
  • COM (possibly) - please god no, but yea, I guess it's a possibility - windows

encoding

JSON

Disadvantages:

  • Not so easy to generate one-liners hand, echo '{ "command": "load", "argument": "/home/shared/videos/coolmovie.mkv"}'' > mpvpipe looks cumbersome.
  • Needs escaping for chapter information

Advantages:

  • JSON is ubiquitous, many languages support it, quite human readable.

Precedents:

  • MongoDB uses it for command submission and even to store its data (well, the BSON equivalent for storage, really). I'm not sure that's a positive point, but that might be because of my terrible experiences with the flakiness of MongoDB.

Libraries:

  • yayl (ISC license, a simpler version of BSD license)
  • jsnm (MIT license)

Another criticism of JSON is that the parsers are bulky and not very performant. And that they fragment the heap with many small allocations. Nobody likes that. Fortunately it appears that this need not be the case. For example jsnm is a lightweight single-file parser that doesn't even require libc, and doesn't require allocations: https://bitbucket.org/zserge/jsmn (the source is easy to read too, about 200 lines of code, have a look).

Bencode

Advantages:

  • Binary safe
  • Simple

Precedents:

  • Used by all bittorrent clients, though not for command submission I think (unsure, didn't research).

Libraries:

  • tbl (ISC license, a simpler version of BSD license) - same interface as yayl

Redis-style messages

Advantages:

  • Binary safe
  • Really simple protocol, could probably code it up by hand over the weekend.
  • Has a simple mode where you can just interact with space separated text-strings, like the old mplayer interface. For an example of this, go here and ctrl-f to inline commands

Disavantages:

  • It's not easy to do nested structures (though it's easy to do lists, I presume chapters will only need a list)

Precedents:

  • Redis uses it for command submission

Libraries:

  • redis-net (BSD license) - I'm not sure if this was meant to be used as a library, but it seems easy enough to rip out the useful parts either from here or redis directly.

How to flesh out a proof of concept

For anyone looking to do some work on it, @wm4 has mentioned that there's mainly 2 important files to look at:

23:26 < wm4> well, most of it is in mpvcore/input/input.c (raw input handling and dispatch, some of the command parser)
23:26 < wm4> and the other half is in mpvcore/command.c
@rossy
Copy link
Member

rossy commented Sep 21, 2013

This looks interesting. It's worth noting that Windows named pipes can be used as an alternative to Unix domain sockets, since unlike anonymous pipes (which are the Windows equivalent of Unix pipes and FIFOs) named pipes are bidirectional, they can be message oriented or stream oriented, they can be read asynchronously, and they have a client/server model.

In Qt, QLocalServer and QLocalSocket use named pipes on Windows and local domain sockets on *nix, so if mpv supported both of these, writing cross platform GUIs wouldn't require much platform specific code.

@aktau
Copy link
Author

aktau commented Sep 21, 2013

named pipes are bidirectional, they can be message oriented or stream oriented, they can be read asynchronously, and they have a client/server model.

Cool, so in essence they're the same as UNIX domain sockets? Are there any differences? It would indeed be a nice way to have a cross-platform local way to talk to mpv.

Though I'm also thinking that TCP in general would be nice, since that would mean easy controlling of mpv over the network. Many UNIX daemons expose a domain socket because it avoids TCP overhead. Redis, MongoDB, postgres, mysql, they all do it. But in the case of mpv, we don't need to send a huge amount of data, so the overhead here is negligible. Since AFAIK the interface to f.ex. TCP sockets and UNIX sockets is exceedingly similar (BSD sockets), I reckon TCP should be implemented first. What do you think?

@ghost
Copy link

ghost commented Sep 21, 2013

My main problem with JSON is that you can't represent byte strings with it. Byte strings can contain invalid UTF-8, for example if the source uses a legacy encoding, instead of UTF-8. This affects things like chapter titles, metadata, and even filenames. With JSON, you'd have to transfer them as char arrays.

TCP is out. It requires lots of platform specific code, which I just removed.

Windows pipes still require some extra code, but it's already there.

I like the idea of supporting a simple protocol; it boils down to allowing the "old" protocol along the new one.

@aktau
Copy link
Author

aktau commented Sep 21, 2013

TCP is out. It requires lots of platform specific code, which I just removed.

Does that mean mpv can no longer read from HTTP streams and things like that? HTTP goes over TCP. It seems contradictory to me, as I thought the libquvi integration was for getting clips from youtube and the likes...

What about the UDP based synchronization that mplayer boasted? I was planning to use that for some cool stuff as well, has that been ripped out?

EDIT: I just tested it with a mpv build from master and streaming from HTTP still works. So I wonder what's different. Is there perhaps some external library like libcurl used for HTTP-only?

@ghost
Copy link

ghost commented Sep 21, 2013

Does that mean mpv can no longer read from HTTP streams and things like that? HTTP goes over TCP. It seems contradictory to me, as I thought the libquvi integration was for getting clips from youtube and the likes...

mpv uses ffmpeg's http implementation. libquvi does its own I/O and uses libcurl.

What about the UDP based synchronization that mplayer boasted? I was planning to use that for some cool stuff as well, has that been ripped out?

This was never merged into mplayer2/mpv in the first place. It looks like this stuff uses sockets manually (rather than layering on mplayer's network code), so it could easily merged... if someone really thinks this is useful.

@aktau
Copy link
Author

aktau commented Sep 21, 2013

This was never merged into mplayer2/mpv in the first place. It looks like this stuff uses sockets manually (rather than layering on mplayer's network code), so it could easily merged... if someone really thinks this is useful.

That's cool. The way I "understood" the concept was that it allow the synced playback of the same video on many different screens, which I could use on an airport project. But that's for later.

To get back on topic:

  • The communication channels is a topic we could discuss later, as it's completely orthogonal to the protocol and encoding chosen. The ones we have for now are fine, and they can be expanded later
  • I see that JSON will not do, according to the information you gave us. Which leaves us with bencode and redis-protocol. There are other contenders, like BSON and msgpack, but they are binary in nature, which would preclude a "simple" protocol. It's very likely I've missed a few here and there, more suggestions?

Byte strings can contain invalid UTF-8, for example if the source uses a legacy encoding, instead of UTF-8. This affects things like chapter titles, metadata, and even filenames. With JSON, you'd have to transfer them as char arrays.

Can't we just convert to UTF-8 here? I mean, otherwise we'd have to specify the encoding in the protocol and it would mean that any client apps would have to deal with any-to-UTF8 encoding, which seems nasty to me. If at all possible I would even suggest a setencoding command, like this: setencoding:utf8, setencoding:ascii. mpv would then do a best-effort conversion if ascii is asked.

@ghost
Copy link

ghost commented Sep 21, 2013

Yes, the main problem is the actual wire protocol. The higher level protocol transports, i.e. what the wire protocol is used for to implement, isn't even interesting; I think it can just wrap the slave commands (those used by input.conf).

There are other contenders, like BSON and msgpack, but they are binary in nature, which would preclude a "simple" protocol.

It should be something that is simple to parse. If the protocol comes with a library, the library should be either ubiquitous, or simple to reimplement by anyone.

Here are some more: the dbus wire protocol (relatively simple), google protobufs, Thrift. See also: http://en.wikipedia.org/wiki/Comparison_of_data_serialization_formats

I guess one additional requirement we have to put is: it should allow coexistence with simple input commands. But this could be realized on the transport layer, so to speak.

@ghost
Copy link

ghost commented Sep 21, 2013

Can't we just convert to UTF-8 here? I mean, otherwise we'd have to specify the encoding in the protocol and it would mean that any client apps would have to deal with any-to-UTF8 encoding, which seems nasty to me.

It is nasty, but you can't detect everything reliably. Usually it's either original data or mojibake, and then I'd prefer to send the original data, and leave the decision what to do with it to the user.

With filenames, you can't actually do much. Filenames come from the disk, and can easily be in a different encoding. This often happens when reading from older disks or when unzipping random files from the internet.

@aktau
Copy link
Author

aktau commented Sep 21, 2013

It is nasty, but you can't detect everything reliably. Usually it's either original data or mojibake, and then I'd prefer to send the original data, and leave the decision what to do with it to the user.

If I understand correctly, the issue is just that the encoding of the characters (I assume chapter information and the likes) is not standard and more importantly, not included in the video. As such, one can only guess at the encoding. (reading up on "mojibake" it seems to be just what happens when you guess the wrong encoding for something, I just had to deal with a lot of double-UTF8 encoded strings in a personal project, for example (which one cannot render correctly)). In that case, I guess it's indeed better to just pass the raw byte array to the application. Which is another notch on the belt of the TLV formats, and it really does disqualify JSON, as JSON only supports UTF-8, 16 and 32.

With filenames, you can't actually do much. Filenames come from the disk, and can easily be in a different encoding. This often happens when reading from older disks or when unzipping random files from the internet.

Yea, not to mention that on UNIX systems no specific encoding is enforced, anyone can set their locale to anything and start filling in weird file names.

I guess passing byte arrays would indeed be the most fitting option.

@ghost
Copy link

ghost commented Sep 22, 2013

Anyway, we just have to choose a protocol, then we can implement it. Currently, I'd tend to bencode, but maybe with custom extensions. I'd like to add a float type, and eliminate the need to sort dictionaries by key. I'd also prefix strings with a type code to make it easier to parse (e.g. s6:string instead of 6:string). But maybe that be worse than standard bencode? But all in all, they'll have to implement the protocol parser anyway, and there's still the "simple" protocol. Your opinion please!

To the higher level layers of the protocols, I wouldn't add much. I'd add sequence numbers to each request and reply (similar as planned for libmpv), and add a way to track property changes.

@aktau
Copy link
Author

aktau commented Sep 22, 2013

I'd also prefix strings with a type code to make it easier to parse (e.g. s6:string instead of 6:string)

I don't think that's really necessary, unless a certain command can return both strings and integers, for example. Which I wouldn't do. If one command can return one type (and accept one fixed types, of course), then that's simpler for everybody. Id est: you know what you're gonna get. Of course there should be a special nil value for when everything goes wrong.

To the higher level layers of the protocols, I wouldn't add much. I'd add sequence numbers to each request and reply (similar as planned for libmpv).

Sequence numbers would indeed be extremely useful, my browser plugin for mplayer just prays that the next response is the good one. Which is not nice at all.

and add a way to track property changes.

> subscribe:playing:886
886:OK
> load:somefile.mkv:887
887:OK
886:event:playing

Something like that?

@ghost
Copy link

ghost commented Sep 22, 2013

I don't think that's really necessary, unless a certain command can return both strings and integers, for example.

Well, bencode already supports distinguishing strings from integers. It's just that when parsing, you had to check whether the first character was between '0' and '9' to know that it's a string, while all other types has a single character to identify it (like 'i' for integers).

Something like that?

Yes. Though with properties I meant properties (which are a separate mechanism, see input.rst), while events are somewhat separate.

@ghost
Copy link

ghost commented Sep 26, 2013

One attempt at defining the lower parts of the protocol (using bencode): http://privatepaste.com/d1f1bec5eb

Another attempt, after I felt that using bencode is too bloated and overengineered: http://privatepaste.com/295754ec5b (but still has the issue that you can't pass structured data)

@aktau
Copy link
Author

aktau commented Sep 26, 2013

Nice exploration of the options, I'm gonna need to mull this over before I give a serious opinion.

@ghost
Copy link

ghost commented Oct 3, 2013

I'll probably implement the second option (http://privatepaste.com/295754ec5b) at some random point, whenever I feel like working on it.

Still not sure what to do about complicated information like chapters, I'll just make something up on the spot that will at least half-work. (This issue has been annoying me from the very start because it's trivial yet I don't know how to solve this. So it's probably still better to solve this via an ad-hoc hack, instead of not at all and holding this back forever.)

@ghost
Copy link

ghost commented Nov 23, 2013

I'll probably implement the second option (http://privatepaste.com/295754ec5b) at some random point, whenever I feel like working on it.

The pastbin died, repost (I hope it's the same): http://sprunge.us/CFJa

I still don't like this option much...

@sebadoom
Copy link

sebadoom commented Dec 2, 2013

I contacted the team privately a while ago asking about slave modes for developing a GUI. The GUI is currently working using the older slave mode (check it out if you want: https://github.com/sebadoom/mpvguihs). I have reached a roadblock as I need more functionality from mpv/slave mode to further advance the GUI (subtitle/audio track lists, chapter lists, etc.). I'm willing to help on this if we can finally define what needs to be done. I tend to favor a simple approach such as JSON + a simple mpv-specific RPC mechanism. Of course something fancier could be in order as well. Regarding binary data (such as chapters and filenames) we could conceivably encode that as uuencode or base64 or something like that (yes, that would result in longer streams of data, but would keep the protocol simple and the use cases dictate it wouldn't be a problem at all, I believe).

IMO, there's no point in developing yet another data format for such a simple use case as this. That problem, as I see it, is already solved, we just need to pick the right tool for it. I also tend to favor zeromq over sockets, but that's just me. Sockets remain simple enough that anyone could use them. Pipes are really cool because we could conceivably send commands from the command-line without external tools, right?

A command could remain as simple as
Client: [{ "cmd": "seek" }, ["relative", "forward", 10, "ms"]]
mpv: ["OK"]

User readable (and writable). Parsers are readily available (no extra dependencies, many could be integrated directly into mpv). Current commands could easily be wrapped in something like this, I guess.

Edit: clarified a couple of points.

@ghost
Copy link

ghost commented Dec 2, 2013

JSON

We could do that. JSON is not that easy to parse though, and there's still this problem that it's hard to put data into JSON without encoding them as byte arrays or without extra mechanism to mangle strings to pretend the data is valid UTF-8.

we could conceivably encode that as uuencode or base64 or something like that

Maybe so. That would require treating all strings specially (except maybe dictionary keys, which are also strings), which would probably be pretty annoying for the user of the protocol. Personally I'd probably prefer URL encoding for strings instead of base64, though. (URL encoding is trivial to implement, even simpler than base64.)

Alternatively, we could do the same thing Python does with filenames that have invalid UTF-8 (basically the same as our problem). Bytes which can't be decoded are escaped as certain reserved code points, details see http://www.python.org/dev/peps/pep-0383/. The problem with this is that the resulting string isn't valid UTF-8 either (and will probably be rejected by most JSON parsers), and it's slow and complicated too.

In general, this doesn't seem to make JSON a good match. Although JSON is relatively simple, it's not the most simple to parse format either.

Parsers are readily available (no extra dependencies, many could be integrated directly into mpv).

The idea of using JSON is not exactly new, and I've looked for parsers myself. I haven't found anything that was light-weight, correct enough, and bullshit-free enough. I'd probably write a parser myself, but that's not the problem. But I'd say that your claim that this problem is already solved is false, unless you pull in a rat-tail of dependencies and correctness issues (such as handling invalid UTF-8, which some people apparently just refuse to acknowledgde that it's a problem that needs proper handling).

I also tend to favor zeromq over sockets

Yes, we could add a zeromq transport. In fact there was someone who did that, but it wasn't merged.

@ghost
Copy link

ghost commented Dec 2, 2013

PS: by URL encoding I mean the percent encoding, that is commonly used to escape URLs, e.g. ['a', 0xc4, 0xe3, 'b'] becomes a%C4%E3b.

@ghost
Copy link

ghost commented Dec 2, 2013

PS 2: of course I don't want to be stuck forever in designing a new slave mode, so if you think JSON + mangling strings is the way to go, we can do that.

@sebadoom
Copy link

sebadoom commented Dec 2, 2013

Hmm, I disagree. I know these ideas are not knew, I've read the ticket.

This (https://bitbucket.org/zserge/jsmn/src/09ad3d4559ea3e5b1b93cd90350e1909534635dd/jsmn.c?at=default) appears to be a JSON parser in less than 300 lines of C89 (no dependencies, not counting headers, MIT licensed). It does not do UTF-8, though. I guess it comes down to how much work you want to put into fixing/integrating an external parser (do we care about other dependencies? do we want to depend on it or integrate it in the code? do we need an industrial-strength implementation? Are we willing to spend time fixing an implementation?).

Additionally, I am not clear as to why all strings would need to be escaped/encoded. You would normally know if there is or could be unsupported data in your stream, so you would only need to encode whatever strings are necessary. Even if you didn't know, it would be trivial to add a check before encoding.

Edit: TBH, I don't really care about the transport as much as the data-format. Whatever transport we pick (files, sockets, pipes, zeromq, shared memory, sysv-ipc, etc) is fine by me.

Edit 2: Actually I'm against shared-memory as a transport.

@sebadoom
Copy link

sebadoom commented Dec 2, 2013

There are also other data formats that are available and work fine. The redis format described above looks like a good compromise. Protocol-buffers are cool too, but I don't really think requiring an IDL would be a good idea for mpv (unless we want a full RPC-like mechanism, then an IDL becomes ideal (since this is C after all)).

@sebadoom
Copy link

sebadoom commented Dec 2, 2013

Hmm, thinking about this other ticket you mentioned (issue #97), you could conceivably combine that with this. You could pick, say, protocol-buffers as an RPC mechanism. Develop the IDL based on the final C API you want. Publish both the IDL and the C API. Clients could use the C library (that is, what I think you want in ticket #97) or protocol-buffers with their language of choice. They would get the exact same functionality. For free.

Edit: and you get binary encoding, too. You'd lose a user readable input command stream, though (a simple command line client could be developed for that).

@ghost
Copy link

ghost commented Dec 2, 2013

This (https://bitbucket.org/zserge/jsmn/src/09ad3d4559ea3e5b1b93cd90350e1909534635dd/jsmn.c?at=default) appears to be a JSON parser in less than 300 lines of C89 (no dependencies, not counting headers, MIT licensed).

Yes, this was the most light-weight one I could find too. Most others get really awkward with trying to define their own dictionary data structures etc. in C.

It does not do UTF-8, though.

It does, but it lacks some other syntax elements, \u escapes at least.

Anyway, this is not really a problem. I'm just saying that just taking some protocol won't actually solve the oustanding issues.

Additionally, I am not clear as to why all strings would need to be escaped/encoded. You would normally know if there is or could be unsupported data in your stream, so you would only need to encode whatever strings are necessary. Even if you didn't know, it would be trivial to add a check before encoding.

How else would you distnguish strings that are passed literal, and strings that have been mangled?

There are also other data formats that are available and work fine. The redis format described above looks like a good compromise.

Well, the most interesting issue is really how nested data like chapter lists etc. should be handled. This is a problem with issue #97 too, but there I'd probably just export these as special cased data structures.

Protocol-buffers are cool too, but I don't really think requiring an IDL would be a good idea for mpv (unless we want a full RPC-like mechanism, then an IDL becomes ideal (since this is C after all)).

Yeah, but I don't really want to deal with code generated from IDL and all that. And protobuf's C generator is third party code too, i.e. not directly supported by protobuf.

You could pick, say, protocol-buffers as an RPC mechanism. Develop the IDL based on the final C API you want. Publish both the IDL and the C API. Clients could use the C library (that is, what I think you want in ticket #97) or protocol-buffers with their language of choice. They would get the exact same functionality. For free.

Also sounds possible, but I think this would be actually more work. For instance, we'd have to finish the C client library first.

Anyway... what should we do now? Send JSON with mangled strings over zeromq? Finish libmpv and bolt a RPC layer using some middleware on top of it? Something else?

You'd lose a user readable input command stream, though

For that, the old input.conf style command processing could still be used. It's still needed for key bindings after all.

By the way, I think in any case it's better to reuse the infrastructure behind input.conf (like commands and properties), instead of writing new command handlers etc., though this is mostly orthogonal to what we're discussing.

@sebadoom
Copy link

sebadoom commented Dec 2, 2013

How else would you distnguish strings that are passed literal, and strings that have been mangled?

I was thinking about perhaps making it clear in the docs for cases where we know that strings are mangled. Or publish a flag along with each potentially dangerous string. Or use a header? (uuencode does that, though it's been criticized precisely for that reason).

Yeah, but I don't really want to deal with code generated from IDL and all that.

I tend to dislike code-generators too. Having worked with RPC mechanisms in C before, though, I have become to appreciate their usefulness in non-reflective languages.

And protobuf's C generator is third party code too, i.e. not directly supported by protobuf.

Just an example. There's Apache Thrift, CORBA (yeah, I know), etc.

Also sounds possible, but I think this would be actually more work. For instance, we'd have to finish the C client library first.

True.

Anyway... what should we do now? Send JSON with mangled strings over zeromq? Finish libmpv and bolt a RPC layer using some middleware on top of it? Something else?

Having little say and experience in mpv development, this is probably up to you and other developers to decide. I'm mainly concerned about how easy it is to use whatever you pick :)
What I don't like about zeromq is depending on it. This is obviously up to you to decide as well, I cannot say whether adding another dependency to mpv is worth it.

@ghost
Copy link

ghost commented Dec 2, 2013

Also, maybe it would actually best if we advance libmpv, and you use it?

Or is there a reason mpv has to be in a separate process?

@sebadoom
Copy link

sebadoom commented Dec 2, 2013

Or is there a reason mpv has to be in a separate process?

Nope, it's OK. It should work either way.

@ghost
Copy link

ghost commented Dec 3, 2013

Good, maybe this makes it simpler.

This brings us to the question how the client API should export things like chapters (or anything else that isn't just a flat string). Maybe we should continue in #97.

@suhr
Copy link

suhr commented Dec 8, 2013

communication channel

Also, there is 9P (http://en.wikipedia.org/wiki/9P) — posix/plan9

@brcha
Copy link

brcha commented Jan 17, 2014

Isn't it simpler to just use D-Bus (http://www.freedesktop.org/wiki/Software/dbus/) like every other application on GNU/Linux, than to reinvent the wheel? It runs fine on OS X and Windows as well and has excellent API support for just about every programming language/framework around.

@ghost
Copy link

ghost commented Jan 17, 2014

I think dbus would make everything much more complicated. It also doesn't run very well on OSX and Windows; and we're already using too many Linux specific libraries that suck on other platforms (like fontconfig).

@ghost
Copy link

ghost commented Feb 10, 2014

There's a client API now (see https://github.com/mpv-player/mpv/blob/master/libmpv/client.h), and a slave protocol could be built on top of it.

@aktau
Copy link
Author

aktau commented Feb 11, 2014

@wm4 it looks very well designed, props!

After reading the comments in the file though, I'm still not entirely sure if it's possible to use this API while having mpv in a separate process.

The thing is: I have a browser plugin that runs a (currently) mplayer instance for every video it encounters, this allows the mplayer process to stay separate and clean up after itself, it works wonderfully. Since this plugin needs to work for months on end (best uptime for a player units is 4 months, up until now), I'm very hesitant to change this setup. Which is why I would like to emulate this with the better, more modern mpv. Therefore I ask: is it possible to spin up an instance of mpv and still somehow use this API?

Or is it such that I will need to make another executable, e.g.: mympv. Which internally embeds the player and communicates with the browser plugin? It seems like a lot of work just to get what mplayer already offers: communication via pipes or stdin/stdout. I'd prefer the real deal: communication via an API.

@ghost
Copy link

ghost commented Feb 11, 2014

I'm still not entirely sure if it's possible to use this API while having mpv in a separate process.

It would still be possible if someone made a library with the same interface that uses a protocol to communicate to a separate mpv process (that is, as soon as there's an actual slave protocol). This would probably work ok for the asynchronous functions, but wouldn't make too much sense with the synchronous ones (too high latency, I suppose). But it still could be implemented.

But first there needs to be a client protocol.

Currently I'm thinking this could be done via JSON. I dabbled with JSON already over a month ago, didn't like it, and abandoned it. I may or may not resume this.

By the way, I'm wondering: if there is a client library that can talk to mpv remotely, it should probably be a separate .so, right? I don't think providing a way to transparently to switch between the two APIs in a driver-callback like way would be useful due to the different performance and latency characteristics. Even if someone wants that, it could be implemented as a third .so (evil).

@aktau
Copy link
Author

aktau commented Feb 11, 2014

It kind of depends on the protocol, a .so sounds nice, but if the protocol is sufficiently simple I would be tempted to do it in a single source file, so it can be included very easily in-tree or in a /deps folder clibs-style.

@ghost
Copy link

ghost commented Feb 11, 2014

Yeah, probably. The hard part is making it work on both win32 and Linux. That will probably require lots of, erm, stuff.

@aktau
Copy link
Author

aktau commented Feb 11, 2014

Yeah, probably. The hard part is making it work on both win32 and Linux. That will probably require lots of, erm, stuff.

Very right, as a matter of fact, for someone demanding cross-platform-ness even between non-POSIX systems, a .so/.dylib/.dll approach would probably be best. One doesn't preclude the other though. In fact, there could be a mpv_comm_posix.h and mpv_comm_win32.h with a mpv_comm.c file to instantiate it all. A makefile could be supplied to build a .so/.dylib/.dll depending on the selected OS (which would select the correct .h file), and projects wanting something more lightweight could just #include the relevant .h file if they so wanted. Or copy/paste the OS-choosing logic from the makefile and just build it with the rest of their project without thinking twice about it. As an intermediate pass, the makefile could also pretty painlessly generate a static library file .a/.lib. Sadly, some kind of cmake or premake like thing would have to be included for those who really really want visual studio in the mix.

@Frenzie
Copy link

Frenzie commented Oct 1, 2014

@wm4

[UDP based synchronization] was never merged into mplayer2/mpv in the first place. It looks like this stuff uses sockets manually (rather than layering on mplayer's network code), so it could easily merged... if someone really thinks this is useful.

If that means the -udp-slave and -udp-master switches, yes, those are useful even on just one computer to get multiple output windows. Doubtless there should be a better (less CPU-wasting) way to get an arbitrary number of output windows, each of which should probably be able to run with arbitrary output drivers, but I suppose that would be a different topic. That way it would only have to be decoded once as long as you were using one computer, like with VLC's clone filter.

@ghost
Copy link

ghost commented Nov 18, 2014

We now have libmpv, and JSON-based IPC on top of it, so this issue is obsolete.

UDP synchronization is discussed in #1272.

This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants