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

[mpv] Overrides input-ipc-server set in mpv.conf #529

Closed
ahmubashshir opened this issue May 13, 2022 · 58 comments
Closed

[mpv] Overrides input-ipc-server set in mpv.conf #529

ahmubashshir opened this issue May 13, 2022 · 58 comments

Comments

@ahmubashshir
Copy link

ahmubashshir commented May 13, 2022

Describe the bug
Syncplay overrides input-ipc-server set in mpv.conf thus breaking tools that depends on known input-ipc-server

To Reproduce
Steps to reproduce the behavior:

  1. Set input-ipc-server=/run/user/1000/mpv in mpv.conf
  2. Run mpv with syncplay

Expected behavior
Syncplay should check mpv.conf and use ipc path from mpv.conf if it's set.

Version and platform:

  • OS: Arch Linux
  • Syncplay version and build type: 1.6.9-5 [community/syncplay]
  • Media player and version: mpv 1:0.34.1-4 [community/mpv]

edit: replace outdated option name.

@ahmubashshir ahmubashshir changed the title [mpv] Override input-ipc-path set in mpv.conf [mpv] Overrides input-ipc-path set in mpv.conf May 13, 2022
@Et0h
Copy link
Contributor

Et0h commented May 13, 2022

I hope you can find a solution to this problem, but unfortunately it is not something I can be of much assistance with as it falls outside my knowledge and use case.

Syncplay uses JSON IPC to communicate with mpv, and in my understanding JSON IPC sets input-ipc-server in mpv to allow for this communication. As such, it is possible that the problem / solution lies 'upstream' rather than with Syncplay.

If you can figure out a way for JSON IPC to add itself to input-ipc-server without overriding input-ipc-path then feel free to make a pull request to the appropriate repositories. It's possible that liaising with JSON IPC / mpv devs would be of assistance. If you do so then feel free to include a reference to this issue to provide them with relevant context.

@ahmubashshir
Copy link
Author

ahmubashshir commented May 14, 2022 via email

@daniel-123
Copy link
Contributor

I don't feel that just automatically using ipc file path from config is the optimal approach for two reasons:

  • Primarily the issue is that Syncplay assumes in its design exclusive access to ipc path. Sharing it with another tool runs the risk of either stepping on each others toes. While it's possible that any given tool will work mostly fine, it's seems like a dangerous assumption to base a default behavior on.
  • mpv config can be sourced from a number of places, not just the ~/.config/mpv/mpv.conf. It also differs by platform. I don't think trying to read and parse config files of another piece of software is a good practice.

Because of the above I'd see for example adding a command line switch/config entry to syncplay to allow to customize ipc path as far better option. At very least it doesn't run into the two problems mentioned above.

@Et0h
Copy link
Contributor

Et0h commented May 15, 2022

Because of the above I'd see for example adding a command line switch/config entry to syncplay to allow to customize ipc path as far better option.

Building on this suggestion, Syncplay already has a system for allowing custom player paths. As such if you can figure out a way to tap into that to allow for input-ipc-path to be specified in the player argument for that specific player then that seems like it would be better than adding a new command line switch to Syncplay itself which can't be easily accessed via the GUI.

@Et0h
Copy link
Contributor

Et0h commented May 15, 2022

@ahmubashshir The player arguments show up if you click the 'show more settings' button in the configuration window GUI. Could you please tell me what happens when you add input_ipc_server=PATH to the player arguments for mpv (with PATH being the path of your desired input-ipc-path value)?

@ahmubashshir
Copy link
Author

ahmubashshir commented May 15, 2022 via email

@Et0h
Copy link
Contributor

Et0h commented May 15, 2022

@ahmubashshir Thanks for testing that. What if you change line 248 of python_mpv_jsonipc.py from self._set_default(kwargs, "input_ipc_server", self.ipc_socket) to self._set_default(kwargs, "input-ipc-server", self.ipc_socket) and then specify the path using input-ipc-server=PATH?

@ahmubashshir
Copy link
Author

Same exception happens... btw, why do you vendor dependencies as part of your distribution?

@Et0h
Copy link
Contributor

Et0h commented May 15, 2022

btw, why do you vendor dependencies as part of your distribution?

We use a slightly modified version of the JSON IPC code.

@ahmubashshir
Copy link
Author

Primarily the issue is that Syncplay assumes in its design exclusive access to ipc path.

IMO, if someone set some option in their config, it's better to assume that they knows what they're doing, and we should respect their configs, instead of overriding them, and I don't think anybody would set input-ipc-path in their config without a reason.

@ahmubashshir
Copy link
Author

ahmubashshir commented Oct 11, 2022 via email

@ahmubashshir
Copy link
Author

ahmubashshir commented Oct 11, 2022 via email

@iamkroot
Copy link

iamkroot commented Jan 1, 2024

IMO, if someone set some option in their config, it's better to assume that they knows what they're doing, and we should respect their configs, instead of overriding them, and I don't think anybody would set input-ipc-path in their config without a reason.

Coming here to echo this sentiment- by setting the config item, the user has explicitly assumed responsibility for any breakage caused by bad actors.

@Et0h It would be nice to get the patch merged

@Et0h
Copy link
Contributor

Et0h commented Jan 1, 2024

@Et0h It would be nice to get the patch merged

I am not aware of any appropriate patch ready to merge.

@iamkroot
Copy link

iamkroot commented Jan 1, 2024

This one seems close enough, no?
#529 (comment)

@ahmubashshir
Copy link
Author

ahmubashshir commented Jan 1, 2024

I am not aware of any appropriate patch ready to merge.

I sent the patch via email here #529 (comment)

edit: Should I fork and send pr?

@Et0h
Copy link
Contributor

Et0h commented Jan 1, 2024

I am not aware of any appropriate patch ready to merge.

I sent the patch via email here #529 (comment)

edit: Should I fork and send pr?

Sorry, I should have been more clear by what I meant by "appropriate patch".

The historic patch you linked to was considered previously and concerns were raised about it by @daniel-123 in #529 (comment) with further relevant thoughts about what might be acceptable set out by myself in #529 (comment)

In response to these comments you said at #529 (comment) that you would send a patch to "for JSON IPC to add itself to input-ipc-server without overriding input-ipc-path" after you studied the source code.

In my understanding you have yet to provide such an updated patch. I'm guessing this is because such a patch is not possible based on mpv's current code, as it wasn't clear to me either how to do such a thing (or else I would have provided such a patch myself). However, I know you previously stated that you were aware of other tools that were successful in working around mpv's limitation of only allowing people to specify one IPC socket per instance of mpv.

If an updated patch along the lines previously discussed is not possible due to limitations of mpv then I would probably consider it an upstream issue for mpv to resolve rather than something that merits a hacky fix for Syncplay that would add to Syncplay's complexity and could cause more problems than it solves.

@iamkroot
Copy link

iamkroot commented Jan 1, 2024

@ahmubashshir quick question- is there a distinction between input-ipc-server and input-ipc-path?

From what I understood, Syncplay already supports specifying --input-ipc-server arg to MPV (via mpv_arguments.get('input-ipc-server')) and it correctly picks up this value instead of a randomly generated one.

EDIT: just verified that this is indeed true. In this case, iamkroot/trakt-scrobbler#266 is a different bug from the current one - will create a separate issue for it.

@iamkroot
Copy link

iamkroot commented Jan 1, 2024

JSON IPC to add itself to input-ipc-server without overriding input-ipc-path

I don't see any input-ipc-path config for MPV. So I'm confused what this sentence means. Could you please clarify @Et0h ?

@Et0h
Copy link
Contributor

Et0h commented Jan 1, 2024

JSON IPC to add itself to input-ipc-server without overriding input-ipc-path

I don't see any input-ipc-path config for MPV. So I'm confused what this sentence means. Could you please clarify @Et0h ?

The term input-ipc-path came from @ahmubashshir rather than myself. I know mpv keeps renaming stuff, so maybe it is synonymous with --input-ipc-server.

Basically what I'm trying to say is that manually reading the configuration file seems hacky, and what we want is a solution that allows both Syncplay and whatever else is using IPC to both work without adding too much complexity and without breaking stuff that currently works.

@ahmubashshir
Copy link
Author

how about using --input-ipc-client on supported platforms?

@ahmubashshir
Copy link
Author

I found another solution... after starting mpv normally, we can set input-ipc-server to another value to start a second ipc server 🙃

@ahmubashshir
Copy link
Author

I'm using this script to start second ipc server when input-ipc-server is different from config

# ~/.config/mpv/scripts/syncplay-fix-ipc.run
#!/bin/bash
[[ "${1%%=*}" == "--mpv-ipc-fd" ]] || exit

MPV_FD="${1#--mpv-ipc-fd=}"
test "$MPV_FD" || exit
test "$MPV_FD" -gt 0 || exit

get_config_from_file() {
	sed -nE '/^'"$1"'=/s/^[^=]+=(.+)$/\1/p' "$2"
}

get_reply_for_command()
{
	local resp
	echo '{ "command": '"$1"' }' >&"$MPV_FD"
	until [[ $resp ]] && [[ $resp =~ "\"data\":" ]]; do
		read -u "$MPV_FD" -r resp
	done
	sed -nE 's/^.+data":"([^"]+)".+$/\1/p' <<< "$resp"
}

read -r cfg < <(get_reply_for_command '["expand-path", "~~home/mpv.conf"]')

read -r cipc < <(get_reply_for_command '["get_property", "input-ipc-server"]')
read -r dipc < <(get_config_from_file input-ipc-server "$cfg")

if [[ $dipc && ! "$cipc" == "$dipc" ]]; then
	echo "set input-ipc-server $dipc" >&"$MPV_FD"
fi

exit 0

@ahmubashshir
Copy link
Author

From 8414e6adb511601b98e1a5d4db26834bbdc9a3e2 Mon Sep 17 00:00:00 2001
Message-ID: <8414e6adb511601b98e1a5d4db26834bbdc9a3e2.1704217301.git.ahmubashshir@gmail.com>
From: Mubashshir <[email protected]>
Date: Tue, 2 Jan 2024 23:36:54 +0600
Subject: [PATCH] mpv: Start second IPC server on user-set path

Currently Syncplay overrides user-set `input-ipc-server` in the config
file when launching mpv.

This patch starts another IPC server on user-set `input-ipc-server` path
so that syncplay can work w/o conflicting with other mpv JSON-IPC
clients.

Closes #529
Signed-off-by: Mubashshir <[email protected]>
---
 requirements.txt        |  1 +
 syncplay/players/mpv.py | 28 ++++++++++++++++++++++++++++
 2 files changed, 29 insertions(+)

diff --git a/requirements.txt b/requirements.txt
index 0d61f2f..bb9cc3b 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,6 +1,7 @@
 certifi>=2018.11.29
 pem>=21.2.0
 twisted[tls]>=16.4.0
+appdirs; sys_platform != 'darwin'
 appnope>=0.1.0; sys_platform == 'darwin'
 pypiwin32>=223; sys_platform == 'win32'
 zope.interface>=4.4.0; sys_platform == 'win32'
diff --git a/syncplay/players/mpv.py b/syncplay/players/mpv.py
index 641a1c0..6403b47 100755
--- a/syncplay/players/mpv.py
+++ b/syncplay/players/mpv.py
@@ -505,6 +505,33 @@ class MpvPlayer(BasePlayer):
             time.time() > (self.lastLoadedTime + constants.MPV_NEWFILE_IGNORE_TIME)
         )
 
+    def _start_default_ipc(self):
+        if not sys.platform == "darwin":
+            import appdirs
+
+        from configparser import ConfigParser, NoOptionError as NoConfigKeyError
+
+        ipc_path = None
+        cfg = os.path.join((
+                os.path.join(os.environ.get('HOME'), '.config', 'mpv')
+                if sys.platform == "darwin"
+                else appdirs.user_config_dir("mpv", roaming=True, appauthor=False)
+            ), 'mpv.conf')
+
+        if not os.path.isfile(cfg):
+            return
+
+        try:
+            config = ConfigParser(allow_no_value=True, strict=False, inline_comment_prefixes="#")
+            with open(cfg, "r") as f:
+                config.read_string(f'[root]\n{f.read()}')
+            ipc_path = config.get("root", "input-ipc-server")
+        except (NoConfigKeyError, KeyError, ValueError):
+            return
+
+        if ipc_path:
+            self._listener.sendLine(["set", "input-ipc-server", ipc_path])
+
 
     def __init__(self, client, playerPath, filePath, args):
         from twisted.internet import reactor
@@ -514,6 +541,7 @@ class MpvPlayer(BasePlayer):
 
         self._playerIPCHandler = MPV
         self._create_listener(playerPath, filePath, args)
+        self._start_default_ipc()
 
     def _set_defaults(self):
         self._paused = None
-- 
2.43.0

mpv-Start-second-IPC-server-on-user-set-path.patch.gz
(use git am to apply the patch)

@Et0h
Copy link
Contributor

Et0h commented Jan 2, 2024

@ahmubashshir Nice work finding that if you set the value it at runtime it creates a second IPC server.

I note @daniel-123's previous comment that "mpv config can be sourced from a number of places, not just the ~/.config/mpv/mpv.conf. It also differs by platform. I don't think trying to read and parse config files of another piece of software is a good practice."

Reading the config from mpv would require a lot of testing due to the numerous platforms and variations, and wouldn't be able to handle complex config scenarios and could therefore exhibit inconsistent behaviour. It would also add an additional dependency (appdirs) which adds to the complexity of Syncplay.

In light of these concerns, it might be better for long-term reliability and maintenance if users instead specified input-ipc-server values as a per-player command line argument for mpv/mplayer, and that is then intercepted to be run once mpv has been initialised.

@ahmubashshir
Copy link
Author

ahmubashshir commented Jan 3, 2024

@Et0h

I note @daniel-123's previous comment that "mpv config can be sourced from a number of places, not just the ~/.config/mpv/mpv.conf. It also differs by platform. I don't think trying to read and parse config files of another piece of software is a good practice."

That's why the appdirs module is used... they're doing the heavy lifting of path management.
appdirs module will return platform specific location... like

platform path
windows %APPDATA%/mpv/mpv.conf
linux/*bsd(XDG_CONFIG_HOME unset) ~/.config/mpv/mpv.conf
linux/*bsd(XDG_CONFIG_HOME set) ${XDG_CONFIG_HOME}/mpv/mpv.conf
OSX ~/.config/mpv/mpv.conf

wouldn't be able to handle complex config scenarios

It doesn't need to either, it only needs to read out the specific config key input-ipc-server, nothing else. Even regex could've been used...

it might be better for long-term reliability and maintenance if users instead specified input-ipc-server values as a per-player command line argument for mpv/mplayer.

Shouldn't what the user set in the config file be respected?

I used appdirs module to keep the changes to minimum
(you can get exact config path by sending expand-path ~~home/mpv.conf to the IPC, implementing that seems complex)

@daniel-123

I don't think trying to read and parse config files of another piece of software is a good practice.

If you're integrating with a tool, is ignoring/overriding the user-set config a good practice?

@Et0h
Copy link
Contributor

Et0h commented Feb 1, 2024

  1. mpv.net (too new as the latest version of mpv.net breaks Syncplay if input-ipc-server is specified in config)

I see, I will report this to mpv.net repository.

You don't need to create a new issue as I recently reported it at mpvnet-player/mpv.net#654 but feel free to post on that issue if you can help triangulate or confirm the problem and/or code a solution.

@Et0h
Copy link
Contributor

Et0h commented Feb 2, 2024

I've updated #529 so that if you don't specify a secondary input-ipc-server socket by default it will automatically try to create one as mpvSyncplaySocket. This should hopefully make it easier for finding the socket using trakt-scrobbler, etc.

@soredake
Copy link
Contributor

soredake commented Feb 3, 2024

@Et0h thank you, with this pr all working fine now!

@Et0h
Copy link
Contributor

Et0h commented Feb 3, 2024

That's great to hear @soredake - in that case I can merge the PR. Also, in other good news stax76 has speedily updated mpv.net to fix the issue which would prevent Syncplay from connecting to mpv.net if input-ipc-server is specified in mpv.conf!

Et0h added a commit that referenced this issue Feb 3, 2024
* Pass input-ipc-server player argument to mpv (#529)

* Create secondary mpv IPC Socket "mpvSyncplaySocket" by default
@Et0h Et0h closed this as completed Feb 3, 2024
@Et0h
Copy link
Contributor

Et0h commented Apr 29, 2024

From Syncplay 1.7.3 the user will need to specify the pipe name (e.g. input-ipc-server=\\.\pipe\examplepipe) to connect to an mpv pipe. See #674 and #675 for details.

@soredake
Copy link
Contributor

soredake commented Apr 29, 2024

@Et0h can you please restore creating secondary socket on Windows by default? Otherwise this should be reopened #658, plus even after specifying input-ipc-server=\\.\pipe\mpvsocket in player arguments trakt-scrobbler is not working again. I don't use linux, everything worked fine in previous release on Windows.

@Et0h
Copy link
Contributor

Et0h commented Apr 29, 2024

@Et0h can you please restore creating secondary socket on Windows by default? Otherwise this should be reopened #658, plus even after specifying input-ipc-server=\\.\pipe\mpvsocket in player arguments trakt-scrobbler is not working again. I don't use linux, everything worked fine in previous release on Windows.

I just tried the trakts test for mpv and it worked for me with Syncplay 1.7.3 using both mpv and mpv.net:

c:\Python38>trakts test mpv
Testing connection with mpv.
Please ensure that mpv is playing some media.
 Trying to connect
 Connected

 Waiting for events
 Got info

Playing BigBuckBunny at 13.61%

To get it to work with my version of mpv/mpv.net I had to set input-ipc-server=\\.\pipe\mpvsocket in the mpv.conf file so it knew where it should connect to, and then also put input-ipc-server=\\.\pipe\mpvsocket in the per-player argument for mpv/mpv.net.

In terms of making it a socket/pipe by default, according to @notpeelz it is improper to do it that way. I don't know enough about how sockets/pipes work to be able to judge, so I'm erring on the side of caution and making it an opt-in feature.

@Et0h Et0h reopened this Apr 29, 2024
@notpeelz
Copy link
Contributor

notpeelz commented Apr 30, 2024

I did some investigating.
It turns out mpv doesn't care for multiple --input-ipc-server= options. The last value specified will override the previous ones.

Depending on the order you pass the --input-ipc-server= options, this would either break SyncPlay's ability to communicate with mpv or prevent the creation of the user's socket.

e.g.

$ mpv --player-operation-mode=pseudo-gui --input-ipc-server=/tmp/user-mpv --input-ipc-server=/tmp/syncplay-mpv
# only /tmp/syncplay-mpv is created

Except it doesn't "break" (at least not right away) because SyncPlay extracts the --input-ipc-server=/tmp/user-mpv option from the "Player arguments" field and calls ["set_property", "input-ipc-server", "/tmp/user-mpv"] via its IPC socket.

Now this is where it gets interesting.
When SyncPlay calls set_property input-ipc-server, this bit of code is executed:

if (init || opt_ptr == &opts->ipc_path || opt_ptr == &opts->ipc_client) {
  mp_uninit_ipc(mpctx->ipc_ctx);
  mpctx->ipc_ctx = mp_init_ipc(mpctx->clients, mpctx->global);
}

Essentially, SyncPlay ends up killing its own IPC socket.

You can test this behavior like so:

# in terminal 1:
$ mpv --player-operation-mode=pseudo-gui --input-ipc-server=/tmp/syncplay-mpv

# in terminal 2:
# check that it works
$ echo '{"command": ["get_property", "input-ipc-server"]}' | socat - /tmp/syncplay-mpv
{"data":"/tmp/syncplay-mpv","request_id":0,"error":"success"}

# set the user-defined socket
$ echo '{"command": ["set_property", "input-ipc-server", "/tmp/user-mpv"]}' | socat - /tmp/syncplay-mpv
{"request_id":0,"error":"success"}

# check that the user-defined socket works
$ echo '{"command": ["get_property", "input-ipc-server"]}' | socat - /tmp/user-mpv
{"data":"/tmp/user-mpv","request_id":0,"error":"success"}

# and finally, check if the original socket is still alive (nope)
$ echo '{"command": ["get_property", "input-ipc-server"]}' | socat - /tmp/syncplay-mpv
socat[135918] E GOPEN: /tmp/syncplay-mpv: Connection refused

...except SyncPlay still works???
That's because accepted connections stay open even after the socket is reinitialized! i.e.:

# in terminal 1:
$ mpv --player-operation-mode=pseudo-gui --input-ipc-server=/tmp/syncplay-mpv

# in terminal 2:
# open an interactive REPL with the socket
$ socat - /tmp/syncplay-mpv

# now type the following: {"command": ["get_property", "input-ipc-server"]}<ENTER>
# you should see a response with the expected path.

# now change the the socket path: {"command": ["set_property", "input-ipc-server", "/tmp/user-mpv"]}<ENTER>

# in terminal 3:
# check that the socket is now dead
$ echo '{"command": ["get_property", "input-ipc-server"]}' | socat - /tmp/syncplay-mpv
socat[137175] E GOPEN: /tmp/syncplay-mpv: Connection refused

# now go back to terminal 2 and run the get_property command again: it still works!

I think the real way to fix this would be to ask the mpv devs to support listening on multiple sockets:

config file: input-ipc-server=/tmp/user-mpv
CLI params: --input-ipc-server=/tmp/custom-mpv --input-ipc-server=/tmp/syncplay-mpv
Outcome: input-ipc-server=/tmp/user-mpv:/tmp/custom-mpv:/tmp/syncplay-mpv

Uhh... but what if we want want to override the previous input-ipc-server values?

Option 1:
Using a special syntax to replace the list of sockets (instead of appending by default):

config file: input-ipc-server=/tmp/user-mpv
CLI params: --input-ipc-server=:/tmp/syncplay-mpv
Outcome: input-ipc-server=/tmp/syncplay-mpv

Option 2:
Using a special syntax to append to the list of sockets (instead of replacing by default):

config file: input-ipc-server=/tmp/user-mpv
CLI params: --input-ipc-server=:/tmp/custom-mpv --input-ipc-server=:/tmp/syncplay-mpv
Outcome: input-ipc-server=/tmp/user-mpv:/tmp/custom-mpv:/tmp/syncplay-mpv

Option 3:
Same as option 2, but using mpv's existing property expansion mechanism:

config file: input-ipc-server=/tmp/user-mpv
CLI params: --input-ipc-server=${input-ipc-server}:/tmp/custom-mpv --input-ipc-server=${input-ipc-server}:/tmp/syncplay-mpv
Outcome: input-ipc-server=/tmp/user-mpv:/tmp/custom-mpv:/tmp/syncplay-mpv

Option 1 is bad because it changes existing behavior in a backward-incompatible way.
Option 2 is alright. It's backward-compatible and easier to implement than Option 3.
Option 3 is probably too complex/verbose (also ${} is shell syntax, which would require extra escaping, i.e --input-ipc-server='${input-ipc-server}:/tmp/user-mpv'


Other than that, I don't see a reliable way to "restore" the user-defined input-ipc-server property after the fact.
Also keep in mind that parsing mpv's config file(s) is a bad idea, as @daniel-123 mentioned above. Not only is the config file location unpredictable, but you also have to parse additional config files specified via --include= and include properties.

@soredake
Copy link
Contributor

soredake commented Apr 30, 2024

I just tried the trakts test for mpv and it worked for me with Syncplay 1.7.3 using both mpv and mpv.net:

It doesn't work for me, syncplay works, but trakt-scrobbler saying this:

2024-04-30 09:31:32,334 - ERROR - syncplay@mpv - mpv - Error with command ['get_property', 'path']. Response: {'request_id': 1, 'error': 'property unavailable'}

@notpeelz

Can you please adjust this commit so a secondary socket is still created by default on Windows? I get that you are tried to fix something on linux, but in process you broke functionality that worked in 1.7.2 out of the box, I just needed ipc_path: \\.\pipe\mpvSyncplaySocket in trakt-scrobbler, now I need to set input-ipc-server in mpv.conf and player arguments, and trakt-scrobbler is still not working, and I don't want to spend my time figuring out why because in 1.7.2 release it just worked, and I want it to stay this way on Windows.

@Et0h
Copy link
Contributor

Et0h commented Apr 30, 2024

I just tried the trakts test for mpv and it worked for me with Syncplay 1.7.3 using both mpv and mpv.net:

It doesn't work for me, syncplay works, but trakt-scrobbler saying this:

2024-04-30 09:31:32,334 - ERROR - syncplay@mpv - mpv - Error with command ['get_property', 'path']. Response: {'request_id': 1, 'error': 'property unavailable'}

Did you have a media file playing at the time? That's the error I get if I run the test without a file open.

If you still have issues please provide more detailed instructions on how to replicate, ideally using trakts test.

you broke functionality that worked in 1.7.2 out of the box, I just needed ipc_path: \\.\pipe\mpvSyncplaySocket in trakt-scrobbler, now I need to set input-ipc-server in mpv.conf and player arguments, and trakt-scrobbler is still not working, and I don't want to spend my time figuring out why because in 1.7.2 release it just worked, and I want it to stay this way on Windows.

I think the mpv.conf thing is entirely due to the current trakt-scrobbler code and is nothing to do with recent Syncplay changes. However, it might be due to your attempt to test the latest changes on different media players. The code for getting the per player argument is basically just guesswork if you have more than one player path specified, and only works if you use --input-ipc-server= rather than input-ipc-server=.

As I explain at iamkroot/trakt-scrobbler#266 (comment):

Looking at https://github.com/iamkroot/trakt-scrobbler/blob/7eef02fcfdefb665de6a77dfba403464f024f2ff/trakt_scrobbler/player_monitors/mpv_wrappers.py it looks like some further changes will be required to get it to work reliably via trakt-scrobbler.

Firstly, if there is a Syncplay.ini or .Syncplay folder in the Syncplay folder then Syncplay will use that in preference to the file in the APPDATA folder. This is what distinguishes the installed version of Syncplay from the portable version of Syncplay.

Secondly, someone can have multiple different player entries for perplayerarguments depending on the path of the player. You can get the perplayerargument for the currently selected player by first looking at the value of playerpath and then use that as the key for which which perplayerargument to use.

Thirdly, it can be set as input-ipc-server rather than --input-ipc-server so just looking for --input-ipc-server might not find it.

One option is to just hard-code a pipe/socket name and then instruct people to run input-ipc-server=thatName as a command line argument. This will work UNLESS you end up having two versions of Syncplay running at the same time.

@soredake
Copy link
Contributor

Did you have a media file playing at the time?

Yes, I received this with any media file.

One option is to just hard-code a pipe/socket name and then instruct people to run input-ipc-server=thatName as a command line argument. This will work UNLESS you end up having two versions of Syncplay running at the same time.

Or have option to create secondary socket, that's the best option for me (I only need to set socket in trakt-scrobbler config, and that's all). I'll gladly pay any dev that can make this option.

@notpeelz
Copy link
Contributor

Or have option to create secondary socket

But isn't that already the case? You just need to set the "Player arguments" to --input-ipc-server=\\.\pipe\mpvsocket.
Agreed, the way it's implemented currently is a bit awkward/confusing:

  1. When SyncPlay launches mpv, it appends the user-defined "Player arguments" before its own --input-ipc-server= param. This means that SyncPlay will clobber the user-defined IPC path. At this stage, the user-defined socket doesn't exist yet.
  2. To "restore" the user-defined socket, SyncPlay extracts the value from the --input-ipc-server argument you defined, then calls {"command": ["set_property", "input-ipc-server", "\\\\.\\pipe\\mpvsocket"]} via its own IPC connection. This causes SyncPlay's temporary socket file (or NamedPipe endpoint on windows) to get terminated, however this doesn't terminate the IPC connection already established between mpv and SyncPlay, allowing SyncPlay to keep working.

It doesn't work for me, syncplay works, but trakt-scrobbler saying this: [...]

Works fine for me. Tested in a Windows 10 VM:

image

Steps:

  1. Install Syncplay 1.7.3 (windows installer) and mpv
  2. Install scoop
  3. Install Python 3.8 via scoop (trakt-scrobbler doesn't work with Python 3.12 because it uses deprecated APIs that have since been removed)
scoop bucket add versions
scoop install python38
  1. Install trakt-scrobbler
python38 -m pip install --user pipx
python38 -m pipx ensurepath
pipx install trakt-scrobbler
  1. Configure trakt-scrobbler
trakts auth
trakts config set players.monitored mpv
trakts config set players.mpv.ipc_path \\.\pipe\mpvsocket
trakts start --restart
  1. Launch syncplay and set "Player arguments" to --input-ipc-server=\\.\pipe\mpvsocket
  2. Play big buck bunny
  3. At this point, you should see windows notifications from trakt-scrobbler, informing you of the progress.

I've also tested with this configuration:

trakts config set players.monitored syncplay@mpv
trakts config unset players.mpv.ipc_path
trakts start --restart

...but it appears that trakt-scrobbler doesn't parse SyncPlay's config file correctly.
e.g:
If I set "Player arguments" in the GUI to --input-ipc-server=\\.\pipe\mpvsocket, my %appdata%/syncplay.ini config looks like this:

[client_settings]
perplayerarguments = {'c:\\users\\peelz\\scoop\\apps\\mpv\\current\\mpv.exe': ['--input-ipc-server=\\\\.\\pipe\\mpvsocket']}

trakt-scrobbler logs this (notice how it doesn't parse the escape sequences):

DEBUG - MainThread - monitor - Autoloaded syncplay@mpv ipc_path = \\\\.\\pipe\\mpvsocket

I can make syncplay@mpv work if I edit the config file by hand (while SyncPlay + mpv are still running), i.e.:

[client_settings]
perplayerarguments = {'c:\\users\\peelz\\scoop\\apps\\mpv\\current\\mpv.exe': ['--input-ipc-server=\\.\pipe\mpvsocket']}

then trakt start --restart


IMO trakt-scrobbler's syncplay@mpv shouldn't even exist. Various tools parsing each other's config files is a surefire way to create an unmaintainable, buggy mess of code. My recommendation is to manually configure players.mpv.ipc_path and avoid all of this config-parsing nonsense.

At the risk of repeating myself, the way it works currently is an ugly workaround (see my previous message). The better way to fix this would be for mpv to support listening on multiple sockets simultaneously.

@soredake
Copy link
Contributor

But isn't that already the case?

No, by secondary socket I mean \\.\pipe\mpvSyncplaySocket that was used in 1.7.2 release.

@Et0h
Copy link
Contributor

Et0h commented Apr 30, 2024

But isn't that already the case?

No, by secondary socket I mean \\.\pipe\mpvSyncplaySocket that was used in 1.7.2 release.

Syncplay 1.7.3 allows you to create a second socket called whatever you want by specifying it in the per-player argument within Syncplay. If you want to call it \\.\pipe\mpvSyncplaySocket then you can call it \\.\pipe\mpvSyncplaySocket .

@soredake
Copy link
Contributor

soredake commented Apr 30, 2024

What I've done to receive 'property unavailable' from

  1. Installed scoop

  2. Installed Syncplay 1.7.3 (windows installer) and mpv (from scoop)

  3. Install Python 3.12 via scoop.

  4. Installed master branch of trakt-scrobbler that works with python 3.12 with pipx install --force --pip-args='--force-reinstall' git+https://github.com/iamkroot/trakt-scrobbler.git@master

  5. Setup trakt-scrobbler like this:
    image

  6. Added mpv-git to syncplay.

  7. Added --input-ipc-server=\\.\pipe\mpvsocket to player arguments for mpv-git:
    image

  8. Joined room.

  9. trakts start --restart started trakt-scrobbler

  10. trakts log open opened log.

  11. ERROR - mpv - mpv - Error with command ['get_property', 'time-pos']. Response: {'request_id': 2, 'error': 'property unavailable'}
    In process explorer i see this:
    image

If I understand correctly, --input-ipc-server=\\.\pipe\mpvsocket is just ignored.

@notpeelz
Copy link
Contributor

ERROR - mpv - mpv - Error with command ['get_property', 'time-pos']. Response: {'request_id': 2, 'error': 'property unavailable'}

That's normal, those properties can't be queried if you're not playing a file.
What happens if you load a file after that? trakt-scrobbler was logging those errors too on my end, but it still works.

@Et0h
Copy link
Contributor

Et0h commented Apr 30, 2024

If I understand correctly, --input-ipc-server=\\.\pipe\mpvsocket is just ignored.

It's not ignored so much as set later. Order of events is:

  1. Syncplay launches mpv and keeps trying to connect to its Syncplay socket
  2. mpv is launched and Syncplay connects to its socket
  3. mpv sends <get_syncplayintf_options> to Syncplay
  4. Syncplay runs _sendMpvOptions, and the last part of this is that if a socketPath is defined Syncplay sends to mpv elf._setProperty("input-ipc-server", socketPath)
  5. mpv then closes the Syncplay existing socket but not the connection, and opens a new socket using the socketPath name

Try input-ipc-server instead of --input-ipc-server and see if that helps as that brings your work closer to the example wherenotpelz got it to work. Also, monitor mpv but not syncplay@mpv.

ERROR - mpv - mpv - Error with command ['get_property', 'time-pos']. Response: {'request_id': 2, 'error': 'property unavailable'}

That's normal, those properties can't be queried if you're not playing a file. What happens if you load a file after that? trakt-scrobbler was logging those errors too on my end, but it still works.

Makes sense. If trakts wasn't able to connect to mpv it'd never get that error, which is just the normal message for if no file is playing.

@soredake
Copy link
Contributor

soredake commented Apr 30, 2024

Try input-ipc-server instead of --input-ipc-server and see if that helps as that brings your work closer to the example wherenotpelz got it to work.

Nothing changed unfortunately.

@soredake
Copy link
Contributor

soredake commented May 10, 2024

I found why it was not working for me, I used the same socket for plex-mpv-shim, syncplay and trakt-scrobbler, that caused this ERROR - mpv - mpv - Error with command ['get_property', 'time-pos']. Response: {'request_id': 2, 'error': 'property unavailable'} error, I changed socket to \\.\pipe\mpvSyncplaySocket, and now, it works again, sorry for the noise! I don't know why syncplay and trakt-scrobbler can share the same socket, but plex-mpv-shim and trakt-scrobbler don't.

@Et0h
Copy link
Contributor

Et0h commented May 10, 2024

I found why it was not working for me, I mistakenly used the same socket for plex-mpv-shim and syncplay, that cause this ERROR - mpv - mpv - Error with command ['get_property', 'time-pos']. Response: {'request_id': 2, 'error': 'property unavailable'} error, I changed socket to \\.\pipe\mpvSyncplaySocket, and now, it works again, sorry for the noice!

Glad you got to the bottom of it.

I don't know why syncplay and trakt-scrobbler can share socket, but plex-mpv-shim and trakt-scrobbler don't.

The precise operations and sequencing, perhaps. If I understand correctly mpv opens a socket and Syncplay connects to mpv using that socket and then the socket is closed in mpv but the connection to Syncplay over this socket remains open, and only then is the socket reused for its next purpose which is to allow scrobbler to connect. As Syncplay never disconnects it can still make use of the original connection even after scrobbler connects. It is a bit hacky and probably relies on undocumented functionality but so long as it works consistently I'll take the win.

@notpeelz
Copy link
Contributor

Can this issue be closed now?

@Et0h
Copy link
Contributor

Et0h commented Jun 26, 2024

I'll say yes, and someone can re-open it if necessary.

@Et0h Et0h closed this as completed Jun 26, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants