mirror of
https://github.com/jellyfin/jellyfin-mpv-shim.git
synced 2024-11-27 00:00:37 +00:00
182 lines
5.4 KiB
Python
182 lines
5.4 KiB
Python
from .conf import settings
|
|
from .i18n import _
|
|
|
|
import urllib.request
|
|
import urllib.error
|
|
import logging
|
|
import sys
|
|
import time
|
|
|
|
log = logging.getLogger("svp_integration")
|
|
|
|
from typing import TYPE_CHECKING
|
|
|
|
if TYPE_CHECKING:
|
|
from .menu import OSDMenu as OSDMenu_type
|
|
from .player import PlayerManager as PlayerManager_type
|
|
|
|
|
|
def list_request(path: str):
|
|
try:
|
|
response = urllib.request.urlopen(settings.svp_url + "?" + path)
|
|
return response.read().decode("utf-8").replace("\r\n", "\n").split("\n")
|
|
except urllib.error.URLError:
|
|
log.error("Could not reach SVP API server.", exc_info=True)
|
|
return None
|
|
|
|
|
|
def simple_request(path: str):
|
|
response_list = list_request(path)
|
|
if response_list is None:
|
|
return None
|
|
if len(response_list) != 1 or " = " not in response_list[0]:
|
|
return None
|
|
return response_list[0].split(" = ")[1]
|
|
|
|
|
|
def get_profiles():
|
|
profile_ids = list_request("list=profiles")
|
|
profiles = {}
|
|
for profile_id in profile_ids:
|
|
profile_id = profile_id.replace("profiles.", "")
|
|
if profile_id == "predef":
|
|
continue
|
|
if profile_id == "P10000001_1001_1001_1001_100000000001":
|
|
profile_name = _("Automatic")
|
|
else:
|
|
profile_name = simple_request("profiles.{0}.title".format(profile_id))
|
|
if simple_request("profiles.{0}.on".format(profile_id)) == "false":
|
|
continue
|
|
profile_guid = "{" + profile_id[1:].replace("_", "-") + "}"
|
|
profiles[profile_guid] = profile_name
|
|
return profiles
|
|
|
|
|
|
def get_name_from_guid(profile_id: str):
|
|
profile_id = "P" + profile_id[1:-1].replace("-", "_")
|
|
if profile_id == "P10000001_1001_1001_1001_100000000001":
|
|
return _("Automatic")
|
|
else:
|
|
return simple_request("profiles.{0}.title".format(profile_id))
|
|
|
|
|
|
def get_last_profile():
|
|
return simple_request("rt.playback.last_profile")
|
|
|
|
|
|
def is_svp_alive():
|
|
try:
|
|
response = list_request("")
|
|
return response is not None
|
|
except Exception:
|
|
log.error("Could not reach SVP API server.", exc_info=True)
|
|
return False
|
|
|
|
|
|
def is_svp_enabled():
|
|
return simple_request("rt.disabled") == "false"
|
|
|
|
|
|
def is_svp_active():
|
|
response = simple_request("rt.playback.active")
|
|
if response is None:
|
|
return False
|
|
return response != ""
|
|
|
|
|
|
def set_active_profile(profile_id: str):
|
|
# As far as I know, there is no way to directly set the profile.
|
|
if not is_svp_active():
|
|
return False
|
|
if profile_id == get_last_profile():
|
|
return True
|
|
for i in range(len(list_request("list=profiles"))):
|
|
list_request("!profile_next")
|
|
if get_last_profile() == profile_id:
|
|
return True
|
|
return False
|
|
|
|
|
|
def set_disabled(disabled: bool):
|
|
return (
|
|
simple_request("rt.disabled={0}".format("true" if disabled else "false"))
|
|
== "true"
|
|
)
|
|
|
|
|
|
class SVPManager:
|
|
def __init__(self, menu: "OSDMenu_type", player_manager: "PlayerManager_type"):
|
|
self.menu = menu
|
|
|
|
if settings.svp_enable:
|
|
socket = settings.svp_socket
|
|
if socket is None:
|
|
if sys.platform.startswith("win32") or sys.platform.startswith(
|
|
"cygwin"
|
|
):
|
|
socket = "mpvpipe"
|
|
else:
|
|
socket = "/tmp/mpvsocket"
|
|
|
|
# This actually *adds* another ipc server.
|
|
player_manager.add_ipc(socket)
|
|
|
|
if settings.svp_enable and not is_svp_alive():
|
|
log.error(
|
|
"SVP is not reachable. Please make sure you have the API enabled."
|
|
)
|
|
|
|
@staticmethod
|
|
def is_available():
|
|
if not settings.svp_enable:
|
|
return False
|
|
if not is_svp_alive():
|
|
return False
|
|
return True
|
|
|
|
def menu_set_profile(self):
|
|
profile_id = self.menu.menu_list[self.menu.menu_selection][2]
|
|
if profile_id is None:
|
|
set_disabled(True)
|
|
else:
|
|
set_active_profile(profile_id)
|
|
# Need to re-render menu. SVP has a race condition so we wait a second.
|
|
time.sleep(1)
|
|
self.menu.menu_action("back")
|
|
self.menu_action()
|
|
|
|
def menu_set_enabled(self):
|
|
set_disabled(False)
|
|
|
|
# Need to re-render menu. SVP has a race condition so we wait a second.
|
|
time.sleep(1)
|
|
self.menu.menu_action("back")
|
|
self.menu_action()
|
|
|
|
def menu_action(self):
|
|
if is_svp_active():
|
|
selected = 0
|
|
active_profile = get_last_profile()
|
|
profile_option_list = [(_("Disabled"), self.menu_set_profile, None)]
|
|
for i, (profile_id, profile_name) in enumerate(get_profiles().items()):
|
|
profile_option_list.append(
|
|
(profile_name, self.menu_set_profile, profile_id)
|
|
)
|
|
if profile_id == active_profile:
|
|
selected = i + 1
|
|
self.menu.put_menu(_("Select SVP Profile"), profile_option_list, selected)
|
|
else:
|
|
if is_svp_enabled():
|
|
self.menu.put_menu(
|
|
_("SVP is Not Active"),
|
|
[
|
|
(_("Disable"), self.menu_set_profile, None),
|
|
(_("Retry"), self.menu_set_enabled),
|
|
],
|
|
selected=1,
|
|
)
|
|
else:
|
|
self.menu.put_menu(
|
|
_("SVP is Disabled"), [(_("Enable SVP"), self.menu_set_enabled)]
|
|
)
|