mirror of
https://github.com/ankitects/anki.git
synced 2025-09-18 14:02:21 -04:00
Keep cwd and pass dir to player subprocess instead (#1656)
This commit is contained in:
parent
cc91017bf1
commit
6c8cdc0a0c
4 changed files with 29 additions and 53 deletions
|
@ -245,7 +245,6 @@ class Collection(DeprecatedNamesMixin):
|
||||||
self._clear_caches()
|
self._clear_caches()
|
||||||
self._backend.close_collection(downgrade_to_schema11=downgrade)
|
self._backend.close_collection(downgrade_to_schema11=downgrade)
|
||||||
self.db = None
|
self.db = None
|
||||||
self.media.close()
|
|
||||||
|
|
||||||
def close_for_full_sync(self) -> None:
|
def close_for_full_sync(self) -> None:
|
||||||
# save and cleanup, but backend will take care of collection close
|
# save and cleanup, but backend will take care of collection close
|
||||||
|
@ -253,7 +252,6 @@ class Collection(DeprecatedNamesMixin):
|
||||||
self.save(trx=False)
|
self.save(trx=False)
|
||||||
self._clear_caches()
|
self._clear_caches()
|
||||||
self.db = None
|
self.db = None
|
||||||
self.media.close()
|
|
||||||
|
|
||||||
def rollback(self) -> None:
|
def rollback(self) -> None:
|
||||||
self._clear_caches()
|
self._clear_caches()
|
||||||
|
@ -285,8 +283,6 @@ class Collection(DeprecatedNamesMixin):
|
||||||
media_db_path=media_db,
|
media_db_path=media_db,
|
||||||
log_path=log_path,
|
log_path=log_path,
|
||||||
)
|
)
|
||||||
else:
|
|
||||||
self.media.connect()
|
|
||||||
self.db = DBProxy(weakref.proxy(self._backend))
|
self.db = DBProxy(weakref.proxy(self._backend))
|
||||||
self.db.begin()
|
self.db.begin()
|
||||||
|
|
||||||
|
|
|
@ -29,11 +29,6 @@ def media_paths_from_col_path(col_path: str) -> tuple[str, str]:
|
||||||
CheckMediaResponse = media_pb2.CheckMediaResponse
|
CheckMediaResponse = media_pb2.CheckMediaResponse
|
||||||
|
|
||||||
|
|
||||||
# fixme: look into whether we can drop chdir() below
|
|
||||||
# - need to check aa89d06304fecd3597da4565330a3e55bdbb91fe
|
|
||||||
# - and audio handling code
|
|
||||||
|
|
||||||
|
|
||||||
class MediaManager(DeprecatedNamesMixin):
|
class MediaManager(DeprecatedNamesMixin):
|
||||||
|
|
||||||
sound_regexps = [r"(?i)(\[sound:(?P<fname>[^]]+)\])"]
|
sound_regexps = [r"(?i)(\[sound:(?P<fname>[^]]+)\])"]
|
||||||
|
@ -51,45 +46,19 @@ class MediaManager(DeprecatedNamesMixin):
|
||||||
|
|
||||||
def __init__(self, col: anki.collection.Collection, server: bool) -> None:
|
def __init__(self, col: anki.collection.Collection, server: bool) -> None:
|
||||||
self.col = col.weakref()
|
self.col = col.weakref()
|
||||||
self._dir: str | None = None
|
|
||||||
if server:
|
if server:
|
||||||
return
|
return
|
||||||
# media directory
|
# media directory
|
||||||
self._dir = media_paths_from_col_path(self.col.path)[0]
|
self._dir = media_paths_from_col_path(self.col.path)[0]
|
||||||
if not os.path.exists(self._dir):
|
if not os.path.exists(self._dir):
|
||||||
os.makedirs(self._dir)
|
os.makedirs(self._dir)
|
||||||
try:
|
|
||||||
self._oldcwd = os.getcwd()
|
|
||||||
except OSError:
|
|
||||||
# cwd doesn't exist
|
|
||||||
self._oldcwd = None
|
|
||||||
try:
|
|
||||||
os.chdir(self._dir)
|
|
||||||
except OSError as exc:
|
|
||||||
raise Exception("invalidTempFolder") from exc
|
|
||||||
|
|
||||||
def __repr__(self) -> str:
|
def __repr__(self) -> str:
|
||||||
dict_ = dict(self.__dict__)
|
dict_ = dict(self.__dict__)
|
||||||
del dict_["col"]
|
del dict_["col"]
|
||||||
return f"{super().__repr__()} {pprint.pformat(dict_, width=300)}"
|
return f"{super().__repr__()} {pprint.pformat(dict_, width=300)}"
|
||||||
|
|
||||||
def connect(self) -> None:
|
def dir(self) -> str:
|
||||||
if self.col.server:
|
|
||||||
return
|
|
||||||
os.chdir(self._dir)
|
|
||||||
|
|
||||||
def close(self) -> None:
|
|
||||||
if self.col.server:
|
|
||||||
return
|
|
||||||
# change cwd back to old location
|
|
||||||
if self._oldcwd:
|
|
||||||
try:
|
|
||||||
os.chdir(self._oldcwd)
|
|
||||||
except:
|
|
||||||
# may have been deleted
|
|
||||||
pass
|
|
||||||
|
|
||||||
def dir(self) -> str | None:
|
|
||||||
return self._dir
|
return self._dir
|
||||||
|
|
||||||
def force_resync(self) -> None:
|
def force_resync(self) -> None:
|
||||||
|
|
|
@ -192,7 +192,6 @@ class AnkiQt(QMainWindow):
|
||||||
self.setupKeys()
|
self.setupKeys()
|
||||||
self.setupThreads()
|
self.setupThreads()
|
||||||
self.setupMediaServer()
|
self.setupMediaServer()
|
||||||
self.setupSound()
|
|
||||||
self.setupSpellCheck()
|
self.setupSpellCheck()
|
||||||
self.setupProgress()
|
self.setupProgress()
|
||||||
self.setupStyle()
|
self.setupStyle()
|
||||||
|
@ -449,6 +448,7 @@ class AnkiQt(QMainWindow):
|
||||||
if not self.loadCollection():
|
if not self.loadCollection():
|
||||||
return
|
return
|
||||||
|
|
||||||
|
self.setup_sound()
|
||||||
self.flags = FlagManager(self)
|
self.flags = FlagManager(self)
|
||||||
# show main window
|
# show main window
|
||||||
if self.pm.profile["mainWindowState"]:
|
if self.pm.profile["mainWindowState"]:
|
||||||
|
@ -486,6 +486,7 @@ class AnkiQt(QMainWindow):
|
||||||
self.unloadCollection(callback)
|
self.unloadCollection(callback)
|
||||||
|
|
||||||
def _unloadProfile(self) -> None:
|
def _unloadProfile(self) -> None:
|
||||||
|
self.cleanup_sound()
|
||||||
saveGeom(self, "mainWindow")
|
saveGeom(self, "mainWindow")
|
||||||
saveState(self, "mainWindow")
|
saveState(self, "mainWindow")
|
||||||
self.pm.save()
|
self.pm.save()
|
||||||
|
@ -519,8 +520,11 @@ class AnkiQt(QMainWindow):
|
||||||
# Sound/video
|
# Sound/video
|
||||||
##########################################################################
|
##########################################################################
|
||||||
|
|
||||||
def setupSound(self) -> None:
|
def setup_sound(self) -> None:
|
||||||
aqt.sound.setup_audio(self.taskman, self.pm.base)
|
aqt.sound.setup_audio(self.taskman, self.pm.base, self.col.media.dir())
|
||||||
|
|
||||||
|
def cleanup_sound(self) -> None:
|
||||||
|
aqt.sound.cleanup_audio()
|
||||||
|
|
||||||
def _add_play_buttons(self, text: str) -> str:
|
def _add_play_buttons(self, text: str) -> str:
|
||||||
"Return card text with play buttons added, or stripped."
|
"Return card text with play buttons added, or stripped."
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import atexit
|
|
||||||
import os
|
import os
|
||||||
import platform
|
import platform
|
||||||
import re
|
import re
|
||||||
|
@ -271,8 +270,9 @@ class SimpleProcessPlayer(Player): # pylint: disable=abstract-method
|
||||||
args: list[str] = []
|
args: list[str] = []
|
||||||
env: dict[str, str] | None = None
|
env: dict[str, str] | None = None
|
||||||
|
|
||||||
def __init__(self, taskman: TaskManager) -> None:
|
def __init__(self, taskman: TaskManager, media_folder: str | None = None) -> None:
|
||||||
self._taskman = taskman
|
self._taskman = taskman
|
||||||
|
self._media_folder = media_folder
|
||||||
self._terminate_flag = False
|
self._terminate_flag = False
|
||||||
self._process: subprocess.Popen | None = None
|
self._process: subprocess.Popen | None = None
|
||||||
self._warned_about_missing_player = False
|
self._warned_about_missing_player = False
|
||||||
|
@ -292,6 +292,7 @@ class SimpleProcessPlayer(Player): # pylint: disable=abstract-method
|
||||||
self._process = subprocess.Popen(
|
self._process = subprocess.Popen(
|
||||||
self.args + [tag.filename],
|
self.args + [tag.filename],
|
||||||
env=self.env,
|
env=self.env,
|
||||||
|
cwd=self._media_folder,
|
||||||
stdout=subprocess.DEVNULL,
|
stdout=subprocess.DEVNULL,
|
||||||
stderr=subprocess.DEVNULL,
|
stderr=subprocess.DEVNULL,
|
||||||
)
|
)
|
||||||
|
@ -359,8 +360,10 @@ class SimpleMpvPlayer(SimpleProcessPlayer, VideoPlayer):
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
def __init__(self, taskman: TaskManager, base_folder: str) -> None:
|
def __init__(
|
||||||
super().__init__(taskman)
|
self, taskman: TaskManager, base_folder: str, media_folder: str
|
||||||
|
) -> None:
|
||||||
|
super().__init__(taskman, media_folder)
|
||||||
self.args += [f"--config-dir={base_folder}"]
|
self.args += [f"--config-dir={base_folder}"]
|
||||||
|
|
||||||
|
|
||||||
|
@ -381,7 +384,8 @@ class MpvManager(MPV, SoundOrVideoPlayer):
|
||||||
"--input-media-keys=no",
|
"--input-media-keys=no",
|
||||||
]
|
]
|
||||||
|
|
||||||
def __init__(self, base_path: str) -> None:
|
def __init__(self, base_path: str, media_folder: str) -> None:
|
||||||
|
self.media_folder = media_folder
|
||||||
mpvPath, self.popenEnv = _packagedCmd(["mpv"])
|
mpvPath, self.popenEnv = _packagedCmd(["mpv"])
|
||||||
self.executable = mpvPath[0]
|
self.executable = mpvPath[0]
|
||||||
self._on_done: OnDoneCallback | None = None
|
self._on_done: OnDoneCallback | None = None
|
||||||
|
@ -407,7 +411,7 @@ class MpvManager(MPV, SoundOrVideoPlayer):
|
||||||
assert isinstance(tag, SoundOrVideoTag)
|
assert isinstance(tag, SoundOrVideoTag)
|
||||||
self._on_done = on_done
|
self._on_done = on_done
|
||||||
filename = hooks.media_file_filter(tag.filename)
|
filename = hooks.media_file_filter(tag.filename)
|
||||||
path = os.path.join(os.getcwd(), filename)
|
path = os.path.join(self.media_folder, filename)
|
||||||
|
|
||||||
self.command("loadfile", path, "replace", "pause=no")
|
self.command("loadfile", path, "replace", "pause=no")
|
||||||
gui_hooks.av_player_did_begin_playing(self, tag)
|
gui_hooks.av_player_did_begin_playing(self, tag)
|
||||||
|
@ -446,8 +450,9 @@ class MpvManager(MPV, SoundOrVideoPlayer):
|
||||||
|
|
||||||
|
|
||||||
class SimpleMplayerSlaveModePlayer(SimpleMplayerPlayer):
|
class SimpleMplayerSlaveModePlayer(SimpleMplayerPlayer):
|
||||||
def __init__(self, taskman: TaskManager) -> None:
|
def __init__(self, taskman: TaskManager, media_folder: str) -> None:
|
||||||
super().__init__(taskman)
|
self.media_folder = media_folder
|
||||||
|
super().__init__(taskman, media_folder)
|
||||||
self.args.append("-slave")
|
self.args.append("-slave")
|
||||||
|
|
||||||
def _play(self, tag: AVTag) -> None:
|
def _play(self, tag: AVTag) -> None:
|
||||||
|
@ -458,6 +463,7 @@ class SimpleMplayerSlaveModePlayer(SimpleMplayerPlayer):
|
||||||
self._process = subprocess.Popen(
|
self._process = subprocess.Popen(
|
||||||
self.args + [filename],
|
self.args + [filename],
|
||||||
env=self.env,
|
env=self.env,
|
||||||
|
cwd=self.media_folder,
|
||||||
stdin=subprocess.PIPE,
|
stdin=subprocess.PIPE,
|
||||||
stdout=subprocess.DEVNULL,
|
stdout=subprocess.DEVNULL,
|
||||||
stderr=subprocess.DEVNULL,
|
stderr=subprocess.DEVNULL,
|
||||||
|
@ -819,12 +825,12 @@ def play_clicked_audio(pycmd: str, card: Card) -> None:
|
||||||
##########################################################################
|
##########################################################################
|
||||||
|
|
||||||
|
|
||||||
def setup_audio(taskman: TaskManager, base_folder: str) -> None:
|
def setup_audio(taskman: TaskManager, base_folder: str, media_folder: str) -> None:
|
||||||
# legacy global var
|
# legacy global var
|
||||||
global mpvManager
|
global mpvManager
|
||||||
|
|
||||||
try:
|
try:
|
||||||
mpvManager = MpvManager(base_folder)
|
mpvManager = MpvManager(base_folder, media_folder)
|
||||||
except FileNotFoundError:
|
except FileNotFoundError:
|
||||||
print("mpv not found, reverting to mplayer")
|
print("mpv not found, reverting to mplayer")
|
||||||
except aqt.mpv.MPVProcessError:
|
except aqt.mpv.MPVProcessError:
|
||||||
|
@ -834,10 +840,10 @@ def setup_audio(taskman: TaskManager, base_folder: str) -> None:
|
||||||
av_player.players.append(mpvManager)
|
av_player.players.append(mpvManager)
|
||||||
|
|
||||||
if is_win:
|
if is_win:
|
||||||
mpvPlayer = SimpleMpvPlayer(taskman, base_folder)
|
mpvPlayer = SimpleMpvPlayer(taskman, base_folder, media_folder)
|
||||||
av_player.players.append(mpvPlayer)
|
av_player.players.append(mpvPlayer)
|
||||||
else:
|
else:
|
||||||
mplayer = SimpleMplayerSlaveModePlayer(taskman)
|
mplayer = SimpleMplayerSlaveModePlayer(taskman, media_folder)
|
||||||
av_player.players.append(mplayer)
|
av_player.players.append(mplayer)
|
||||||
|
|
||||||
# tts support
|
# tts support
|
||||||
|
@ -857,5 +863,6 @@ def setup_audio(taskman: TaskManager, base_folder: str) -> None:
|
||||||
if int(platform.version().split(".")[-1]) >= 17763:
|
if int(platform.version().split(".")[-1]) >= 17763:
|
||||||
av_player.players.append(WindowsRTTTSFilePlayer(taskman))
|
av_player.players.append(WindowsRTTTSFilePlayer(taskman))
|
||||||
|
|
||||||
# cleanup at shutdown
|
|
||||||
atexit.register(av_player.shutdown)
|
def cleanup_audio() -> None:
|
||||||
|
av_player.shutdown()
|
||||||
|
|
Loading…
Reference in a new issue