This commit is contained in:
2026-06-28 22:10:55 -07:00
parent d309c3da93
commit c97f3df288
3 changed files with 106 additions and 9 deletions
+40 -1
View File
@@ -15,6 +15,7 @@ from __future__ import annotations
from dataclasses import dataclass, field from dataclasses import dataclass, field
from typing import Any, Dict, List, Optional, Callable, Set, Tuple from typing import Any, Dict, List, Optional, Callable, Set, Tuple
from pathlib import Path from pathlib import Path
from urllib.parse import urlparse
import json import json
import re import re
@@ -2546,6 +2547,44 @@ class ItemDetailView(Table):
return any(_has_renderable_value(item) for item in value) return any(_has_renderable_value(item) for item in value)
return True return True
def _looks_like_http_url(value: Any) -> bool:
text = str(value or "").strip().lower()
return text.startswith("http://") or text.startswith("https://")
def _short_link_label(url_value: str, *, max_len: int = 68) -> str:
text = str(url_value or "").strip()
if not text:
return ""
parsed = urlparse(text)
host = (parsed.netloc or "").strip()
path = (parsed.path or "").strip()
leaf = path.rstrip("/").split("/")[-1] if path else ""
if host and leaf:
label = f"{host}/.../{leaf}"
elif host and path:
label = f"{host}{path}"
elif host:
label = host
else:
label = text
if parsed.query:
label = f"{label}?..."
if len(label) > max_len:
return f"{label[:max_len - 3]}..."
return label
def _render_detail_value(key: str, value: Any) -> Any:
# Keep terminal links compact while preserving full click target.
if str(key or "").strip().lower() in {"path", "url"} and _looks_like_http_url(value):
full_url = str(value).strip()
label = _short_link_label(full_url)
return _rich().Text(label, style=f"underline cyan link {full_url}")
return str(value)
# Canonical display order for metadata; plugin-specific detail views can # Canonical display order for metadata; plugin-specific detail views can
# prepend a preferred order without needing to reimplement rendering. # prepend a preferred order without needing to reimplement rendering.
order: List[str] = [] order: List[str] = []
@@ -2580,7 +2619,7 @@ class ItemDetailView(Table):
val = "\n".join([f"[dim]→[/dim] {r}" for r in val]) val = "\n".join([f"[dim]→[/dim] {r}" for r in val])
if _has_renderable_value(val): if _has_renderable_value(val):
details_table.add_row(f"{key}:", str(val)) details_table.add_row(f"{key}:", _render_detail_value(key, val))
has_details = True has_details = True
# Add any remaining metadata not in the canonical list # Add any remaining metadata not in the canonical list
+51 -5
View File
@@ -4,7 +4,7 @@ local msg = require 'mp.msg'
local M = {} local M = {}
local MEDEIA_LUA_VERSION = '2026-03-23.1' local MEDEIA_LUA_VERSION = '2026-06-25.3'
-- Expose a tiny breadcrumb for debugging which script version is loaded. -- Expose a tiny breadcrumb for debugging which script version is loaded.
pcall(mp.set_property, 'user-data/medeia-lua-version', MEDEIA_LUA_VERSION) pcall(mp.set_property, 'user-data/medeia-lua-version', MEDEIA_LUA_VERSION)
@@ -4164,6 +4164,10 @@ function M._build_web_ytdl_raw_options()
if not lower:find('sub%-langs=', 1) then if not lower:find('sub%-langs=', 1) then
extra[#extra + 1] = 'sub-langs=[en.*,en,-live_chat]' extra[#extra + 1] = 'sub-langs=[en.*,en,-live_chat]'
end end
if not lower:find('sub%-format=', 1) then
-- Prefer chunked subtitle formats over word-by-word JSON tracks.
extra[#extra + 1] = 'sub-format=srt/vtt/best'
end
if #extra == 0 then if #extra == 0 then
return raw ~= '' and raw or nil return raw ~= '' and raw or nil
@@ -4174,15 +4178,43 @@ function M._build_web_ytdl_raw_options()
return table.concat(extra, ',') return table.concat(extra, ',')
end end
function M._apply_web_subtitle_load_defaults(reason) function M._prime_web_subtitle_global_defaults(reason)
local target = trim(tostring(mp.get_property('path') or mp.get_property('stream-open-filename') or '')) local raw = M._build_web_ytdl_raw_options()
if target == '' or not _is_http_url(target) then if not raw or raw == '' then
return false return false
end end
if not _is_ytdlp_url(target) then pcall(mp.set_property, 'options/ytdl-raw-options', raw)
pcall(mp.set_property, 'ytdl-raw-options', raw)
_lua_log('web-subtitles: primed global ytdl defaults reason=' .. tostring(reason or 'startup'))
return true
end
function M._resolve_web_subtitle_target(preferred_target)
local explicit = trim(tostring(preferred_target or ''))
if explicit ~= '' and _is_http_url(explicit) and _is_ytdlp_url(explicit) then
return explicit
end
local path_target = trim(tostring(mp.get_property('path') or mp.get_property('stream-open-filename') or ''))
if path_target ~= '' and _is_http_url(path_target) and _is_ytdlp_url(path_target) then
return path_target
end
local current = _get_current_web_url()
if current and current ~= '' and _is_http_url(current) and _is_ytdlp_url(current) then
return current
end
return nil
end
function M._apply_web_subtitle_load_defaults(reason, preferred_target)
local target = M._resolve_web_subtitle_target(preferred_target)
if not target then
return false return false
end end
_set_current_web_url(target)
M._prepare_ytdl_format_for_web_load(target, reason or 'on-load') M._prepare_ytdl_format_for_web_load(target, reason or 'on-load')
local raw = M._build_web_ytdl_raw_options() local raw = M._build_web_ytdl_raw_options()
@@ -4192,6 +4224,8 @@ function M._apply_web_subtitle_load_defaults(reason)
pcall(mp.set_property, 'file-local-options/sub-visibility', 'yes') pcall(mp.set_property, 'file-local-options/sub-visibility', 'yes')
pcall(mp.set_property, 'file-local-options/sid', 'auto') pcall(mp.set_property, 'file-local-options/sid', 'auto')
pcall(mp.set_property, 'file-local-options/track-auto-selection', 'yes') pcall(mp.set_property, 'file-local-options/track-auto-selection', 'yes')
-- Strip ASS positioning/styling for web subtitles to keep lines anchored naturally.
pcall(mp.set_property, 'file-local-options/sub-ass-override', 'strip')
_lua_log('web-subtitles: prepared load defaults reason=' .. tostring(reason or 'on-load') .. ' target=' .. tostring(target)) _lua_log('web-subtitles: prepared load defaults reason=' .. tostring(reason or 'on-load') .. ' target=' .. tostring(target))
return true return true
end end
@@ -5554,6 +5588,10 @@ local function _apply_ytdl_format_and_reload(url, fmt)
_lua_log('change-format: setting ytdl format=' .. tostring(fmt)) _lua_log('change-format: setting ytdl format=' .. tostring(fmt))
_skip_next_store_check_url = _normalize_url_for_store_lookup(url) _skip_next_store_check_url = _normalize_url_for_store_lookup(url)
_set_current_web_url(url) _set_current_web_url(url)
if _is_ytdlp_url(url) then
M._prime_web_subtitle_global_defaults('change-format')
M._apply_web_subtitle_load_defaults('change-format', url)
end
M._remember_ytdl_download_format(url, fmt) M._remember_ytdl_download_format(url, fmt)
pcall(mp.set_property, 'options/ytdl-format', tostring(fmt)) pcall(mp.set_property, 'options/ytdl-format', tostring(fmt))
pcall(mp.set_property, 'file-local-options/ytdl-format', tostring(fmt)) pcall(mp.set_property, 'file-local-options/ytdl-format', tostring(fmt))
@@ -6559,6 +6597,10 @@ mp.register_script_message('medios-load-url-event', function(json)
_log_all('INFO', 'Load URL started: ' .. url) _log_all('INFO', 'Load URL started: ' .. url)
_lua_log('[LOAD-URL] Starting to load: ' .. url) _lua_log('[LOAD-URL] Starting to load: ' .. url)
_set_current_web_url(url) _set_current_web_url(url)
if _is_ytdlp_url(url) then
M._prime_web_subtitle_global_defaults('load-url')
M._apply_web_subtitle_load_defaults('load-url', url)
end
_pending_format_change = nil _pending_format_change = nil
pcall(mp.set_property, 'options/ytdl-format', '') pcall(mp.set_property, 'options/ytdl-format', '')
pcall(mp.set_property, 'file-local-options/ytdl-format', '') pcall(mp.set_property, 'file-local-options/ytdl-format', '')
@@ -6756,6 +6798,10 @@ end)
mp.add_timeout(0, function() mp.add_timeout(0, function()
pcall(ensure_mpv_ipc_server) pcall(ensure_mpv_ipc_server)
pcall(_lua_log, 'medeia-lua loaded version=' .. MEDEIA_LUA_VERSION) pcall(_lua_log, 'medeia-lua loaded version=' .. MEDEIA_LUA_VERSION)
local ok_subtitle_defaults, subtitle_defaults_err = pcall(M._prime_web_subtitle_global_defaults, 'startup')
if not ok_subtitle_defaults then
_lua_log('web-subtitles: startup defaults failed err=' .. tostring(subtitle_defaults_err))
end
local ok_helper, helper_err = pcall(function() local ok_helper, helper_err = pcall(function()
attempt_start_pipeline_helper_async(function(success) attempt_start_pipeline_helper_async(function(success)
+15 -3
View File
@@ -1790,8 +1790,10 @@ if (Test-Path (Join-Path $repo ".git")) {
$updateText = ($update | Out-String) $updateText = ($update | Out-String)
$repoUpdated = ($updateText -match "Updating|Fast-forward") $repoUpdated = ($updateText -match "Updating|Fast-forward")
$repoUpToDate = ($updateText -match "Already up[\s-]+to[\s-]+date") $repoUpToDate = ($updateText -match "Already up[\s-]+to[\s-]+date")
$skipDepUpdate = $false
if ($gitExit -ne 0) { if ($gitExit -ne 0) {
$skipDepUpdate = $true
Write-Host "[mm] Warning: git update check failed; continuing startup." -ForegroundColor Yellow Write-Host "[mm] Warning: git update check failed; continuing startup." -ForegroundColor Yellow
$gitTail = @($update | Select-Object -Last 3) $gitTail = @($update | Select-Object -Last 3)
foreach ($line in $gitTail) { foreach ($line in $gitTail) {
@@ -1805,7 +1807,9 @@ if (Test-Path (Join-Path $repo ".git")) {
Write-Host "[mm] Repository update check completed." -ForegroundColor DarkGray Write-Host "[mm] Repository update check completed." -ForegroundColor DarkGray
} }
if (-not $env:MM_NO_DEP_UPDATE -and (Test-Path $py) -and (Test-Path $requirements)) { if ($skipDepUpdate) {
Write-Host "[mm] Python module update skipped (network/update check unavailable)." -ForegroundColor DarkGray
} elseif (-not $env:MM_NO_DEP_UPDATE -and (Test-Path $py) -and (Test-Path $requirements)) {
Write-Host "[mm] Checking Python module updates..." -ForegroundColor DarkGray Write-Host "[mm] Checking Python module updates..." -ForegroundColor DarkGray
$depOutput = & $py -m pip install --disable-pip-version-check --upgrade -r $requirements 2>&1 $depOutput = & $py -m pip install --disable-pip-version-check --upgrade -r $requirements 2>&1
$depExit = $LASTEXITCODE $depExit = $LASTEXITCODE
@@ -1905,6 +1909,7 @@ if (Test-Path (Join-Path $repo 'CLI.py')) {
" git -C \"!REPO!\" pull --ff-only >\"!GIT_OUT!\" 2>&1\n" " git -C \"!REPO!\" pull --ff-only >\"!GIT_OUT!\" 2>&1\n"
" set \"GIT_EXIT=!errorlevel!\"\n" " set \"GIT_EXIT=!errorlevel!\"\n"
" set \"REPO_UPDATED=false\"\n" " set \"REPO_UPDATED=false\"\n"
" set \"SKIP_DEP_UPDATE=false\"\n"
" if \"!GIT_EXIT!\" == \"0\" (\n" " if \"!GIT_EXIT!\" == \"0\" (\n"
" findstr /i /c:\"Updating\" /c:\"Fast-forward\" \"!GIT_OUT!\" >nul 2>&1\n" " findstr /i /c:\"Updating\" /c:\"Fast-forward\" \"!GIT_OUT!\" >nul 2>&1\n"
" if !errorlevel! == 0 (\n" " if !errorlevel! == 0 (\n"
@@ -1914,11 +1919,14 @@ if (Test-Path (Join-Path $repo 'CLI.py')) {
" echo [mm] Repository already up to date.\n" " echo [mm] Repository already up to date.\n"
" )\n" " )\n"
" ) else (\n" " ) else (\n"
" set \"SKIP_DEP_UPDATE=true\"\n"
" echo [mm] Warning: git update check failed; continuing startup.\n" " echo [mm] Warning: git update check failed; continuing startup.\n"
" type \"!GIT_OUT!\"\n" " type \"!GIT_OUT!\"\n"
" )\n" " )\n"
" del /q \"!GIT_OUT!\" >nul 2>&1\n" " del /q \"!GIT_OUT!\" >nul 2>&1\n"
" if not defined MM_NO_DEP_UPDATE (\n" " if \"!SKIP_DEP_UPDATE!\" == \"true\" (\n"
" echo [mm] Python module update skipped (network/update check unavailable).\n"
" ) else if not defined MM_NO_DEP_UPDATE (\n"
" if exist \"!PY!\" if exist \"!REQ!\" (\n" " if exist \"!PY!\" if exist \"!REQ!\" (\n"
" echo [mm] Checking Python module updates...\n" " echo [mm] Checking Python module updates...\n"
" set \"PIP_OUT=%TEMP%\\mm_pip_update_!RANDOM!_!RANDOM!.log\"\n" " set \"PIP_OUT=%TEMP%\\mm_pip_update_!RANDOM!_!RANDOM!.log\"\n"
@@ -2127,7 +2135,9 @@ if (Test-Path (Join-Path $repo 'CLI.py')) {
' UPDATE_OUT=$(git -C "$REPO" pull --ff-only 2>&1)\n' ' UPDATE_OUT=$(git -C "$REPO" pull --ff-only 2>&1)\n'
' UPDATE_EXIT=$?\n' ' UPDATE_EXIT=$?\n'
' REPO_UPDATED="false"\n' ' REPO_UPDATED="false"\n'
' SKIP_DEP_UPDATE="false"\n'
' if [ $UPDATE_EXIT -ne 0 ]; then\n' ' if [ $UPDATE_EXIT -ne 0 ]; then\n'
' SKIP_DEP_UPDATE="true"\n'
' echo "[mm] Warning: git update check failed; continuing startup."\n' ' echo "[mm] Warning: git update check failed; continuing startup."\n'
' printf "%s\n" "$UPDATE_OUT" | tail -n 3\n' ' printf "%s\n" "$UPDATE_OUT" | tail -n 3\n'
' elif echo "$UPDATE_OUT" | grep -qiE \'Updating|Fast-forward\'; then\n' ' elif echo "$UPDATE_OUT" | grep -qiE \'Updating|Fast-forward\'; then\n'
@@ -2144,7 +2154,9 @@ if (Test-Path (Join-Path $repo 'CLI.py')) {
' elif [ -x "$VENV/bin/python" ]; then\n' ' elif [ -x "$VENV/bin/python" ]; then\n'
' MM_PY="$VENV/bin/python"\n' ' MM_PY="$VENV/bin/python"\n'
' fi\n' ' fi\n'
' if [ -z "${MM_NO_DEP_UPDATE:-}" ] && [ -n "$MM_PY" ] && [ -f "$REPO/scripts/requirements.txt" ]; then\n' ' if [ "$SKIP_DEP_UPDATE" = "true" ]; then\n'
' echo "[mm] Python module update skipped (network/update check unavailable)."\n'
' elif [ -z "${MM_NO_DEP_UPDATE:-}" ] && [ -n "$MM_PY" ] && [ -f "$REPO/scripts/requirements.txt" ]; then\n'
' echo "[mm] Checking Python module updates..."\n' ' echo "[mm] Checking Python module updates..."\n'
' DEP_OUT=$("$MM_PY" -m pip install --disable-pip-version-check --upgrade -r "$REPO/scripts/requirements.txt" 2>&1)\n' ' DEP_OUT=$("$MM_PY" -m pip install --disable-pip-version-check --upgrade -r "$REPO/scripts/requirements.txt" 2>&1)\n'
' DEP_EXIT=$?\n' ' DEP_EXIT=$?\n'