From fd3f6cc317ad676a2f49fd194bd690b37428f04b Mon Sep 17 00:00:00 2001 From: Jan Meyer Date: Tue, 10 Feb 2026 20:41:34 +0100 Subject: [PATCH] feat(preflight): chekc for makemkv libs --- ripper/preflight.py | 126 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 125 insertions(+), 1 deletion(-) diff --git a/ripper/preflight.py b/ripper/preflight.py index 51fbcc6..98b7d19 100644 --- a/ripper/preflight.py +++ b/ripper/preflight.py @@ -5,9 +5,11 @@ starting a rip, with platform-specific install instructions. """ import importlib +import os import shutil import subprocess import sys +from pathlib import Path def _check_python_version() -> tuple[bool, str]: @@ -55,6 +57,86 @@ def _check_binary(name: str, version_flag: str = "--version") -> tuple[bool, str return True, f"{name} ({path})" +def _check_library(name: str, search_paths: list[str | Path]) -> tuple[bool, str]: + """Check if a shared library exists in any of the given paths.""" + for search_dir in search_paths: + p = Path(search_dir) + if not p.is_dir(): + continue + for f in p.iterdir(): + # Match libmmbd.so, libmmbd.so.0, libmmbd.dylib, mmbd.dll, etc. + if name.lower() in f.name.lower() and f.is_file(): + return True, f"{name} ({f})" + return False, f"{name} — not found" + + +def _check_decryption_libs() -> list[tuple[str, bool, str, bool]]: + """Check for disc decryption libraries (libmmbd, libdvdcss, MakeMKV).""" + results = [] + + # Platform-specific library search paths + if sys.platform == "win32": + lib_paths = [ + Path(os.environ.get("ProgramFiles", "C:/Program Files")) / "MakeMKV", + Path(os.environ.get("ProgramFiles(x86)", "C:/Program Files (x86)")) / "MakeMKV", + Path(os.environ.get("SYSTEMROOT", "C:/Windows")) / "System32", + # HandBrakeCLI directory + ] + hb_path = shutil.which("HandBrakeCLI") + if hb_path: + lib_paths.append(Path(hb_path).parent) + css_name = "libdvdcss" + mmbd_name = "libmmbd" + elif sys.platform == "darwin": + lib_paths = [ + Path("/usr/local/lib"), + Path("/opt/homebrew/lib"), + Path("/usr/lib"), + Path.home() / "lib", + Path("/Applications/MakeMKV.app/Contents/lib"), + ] + css_name = "libdvdcss" + mmbd_name = "libmmbd" + else: + lib_paths = [ + Path("/usr/lib"), + Path("/usr/lib64"), + Path("/usr/local/lib"), + Path("/usr/lib/x86_64-linux-gnu"), + Path("/usr/lib/aarch64-linux-gnu"), + Path.home() / "lib", + Path.home() / ".local" / "lib", + ] + # Also check snap / flatpak MakeMKV paths + snap_lib = Path("/snap/makemkv/current/usr/lib") + if snap_lib.is_dir(): + lib_paths.append(snap_lib) + css_name = "libdvdcss" + mmbd_name = "libmmbd" + + # Check MakeMKV binary + ok, detail = _check_binary("makemkvcon", "--version") + if not ok: + # Also check common non-PATH locations + for candidate in ["/usr/bin/makemkvcon", "/usr/local/bin/makemkvcon", + "/snap/bin/makemkvcon"]: + if Path(candidate).is_file(): + ok = True + detail = f"makemkvcon ({candidate})" + break + results.append(("MakeMKV", ok, detail, False)) + + # Check libmmbd (Blu-ray decryption via MakeMKV) + ok, detail = _check_library(mmbd_name, lib_paths) + results.append(("libmmbd", ok, detail, False)) + + # Check libdvdcss (DVD decryption) + ok, detail = _check_library(css_name, lib_paths) + results.append(("libdvdcss", ok, detail, False)) + + return results + + def _windows_install_hint(tool: str) -> str: """Return a Windows-specific install hint.""" hints = { @@ -68,6 +150,18 @@ def _windows_install_hint(tool: str) -> str: " pip install pymediainfo\n" " Also requires MediaInfo DLL: https://mediaarea.net/en/MediaInfo/Download/Windows" ), + "MakeMKV": ( + " Download from https://www.makemkv.com/download/\n" + " Or: winget install MakeMKV.MakeMKV" + ), + "libmmbd": ( + " Install MakeMKV, then copy libmmbd.dll next to HandBrakeCLI.exe\n" + " Guide: https://www.makemkv.com/forum/viewtopic.php?t=224" + ), + "libdvdcss": ( + " Download from https://www.videolan.org/developers/libdvdcss.html\n" + " Or install VLC (bundles libdvdcss)" + ), } return hints.get(tool, f" pip install {tool}") @@ -88,6 +182,21 @@ def _linux_install_hint(tool: str) -> str: " Also install: sudo apt install libmediainfo0v5 (or equivalent)" ), "eject": " Usually pre-installed. Ubuntu/Debian: sudo apt install eject", + "MakeMKV": ( + " Download from https://www.makemkv.com/download/\n" + " Arch: yay -S makemkv\n" + " Snap: sudo snap install makemkv" + ), + "libmmbd": ( + " Install MakeMKV, then symlink:\n" + " sudo ln -sf /usr/lib/libmmbd.so.0 /usr/lib/libdvdcss.so.2\n" + " Guide: https://www.makemkv.com/forum/viewtopic.php?t=224" + ), + "libdvdcss": ( + " Ubuntu/Debian: sudo apt install libdvdcss2\n" + " Fedora: sudo dnf install libdvdcss\n" + " Arch: sudo pacman -S libdvdcss" + ), } return hints.get(tool, f" pip install {tool}") @@ -104,6 +213,19 @@ def _macos_install_hint(tool: str) -> str: " pip install pymediainfo\n" " Also install: brew install media-info" ), + "MakeMKV": ( + " Download from https://www.makemkv.com/download/\n" + " Or: brew install --cask makemkv" + ), + "libmmbd": ( + " Install MakeMKV, then symlink from the .app bundle:\n" + " sudo ln -sf /Applications/MakeMKV.app/Contents/lib/libmmbd.dylib /usr/local/lib/\n" + " Guide: https://www.makemkv.com/forum/viewtopic.php?t=224" + ), + "libdvdcss": ( + " brew install libdvdcss\n" + " Or: download from https://www.videolan.org/developers/libdvdcss.html" + ), } return hints.get(tool, f" pip install {tool}") @@ -154,7 +276,6 @@ def check_all(verbose: bool = True) -> bool: # Optional binaries (platform-specific) if sys.platform == "win32": - # PowerShell is always available on Windows ok, detail = _check_binary("powershell", "-Command \"echo ok\"") checks.append(("PowerShell", ok, detail, False)) elif sys.platform == "darwin": @@ -164,6 +285,9 @@ def check_all(verbose: bool = True) -> bool: ok, detail = _check_binary("eject", "--version") checks.append(("eject", ok, detail, False)) + # Disc decryption libraries + checks.extend(_check_decryption_libs()) + # Print results all_required_ok = all(ok for _, ok, _, req in checks if req)