mpv & change wallpaper
This commit is contained in:
15
.scripts/waydroid-reload.sh
Executable file
15
.scripts/waydroid-reload.sh
Executable file
@@ -0,0 +1,15 @@
|
||||
#!/bin/env bash
|
||||
|
||||
function checkReturn {
|
||||
echo "Executing: $@"
|
||||
if ! "$@"; then
|
||||
echo "Error runnning command"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
checkReturn waydroid session stop
|
||||
# checkReturn sudo waydroid upgrade # since I'm not using the default image
|
||||
checkReturn sudo waydroid init -f
|
||||
checkReturn sudo systemctl restart waydroid-container
|
||||
checkReturn waydroid show-full-ui
|
||||
@@ -55,6 +55,7 @@
|
||||
font-family: 'MesloLGM Nerd Font';
|
||||
font-size: 60px;
|
||||
margin-top: 5px;
|
||||
margin-right: 20px;
|
||||
}
|
||||
|
||||
.weather-updatetime {
|
||||
|
||||
@@ -29,19 +29,19 @@ UNITS=metric
|
||||
|
||||
## Make cache dir
|
||||
if [[ ! -d "$cache_dir" ]]; then
|
||||
mkdir -p ${cache_dir}
|
||||
mkdir -p "${cache_dir}"
|
||||
fi
|
||||
|
||||
## Get data
|
||||
get_weather_data() {
|
||||
weather=`curl -sf "http://api.openweathermap.org/data/3.0/onecall?lat=${LAT}&lon=${LON}&exclude=minutely,hourly,daily&appid=${KEY}&units=${UNITS}"`
|
||||
echo ${weather} >&2
|
||||
weather=$(curl -sf "http://api.openweathermap.org/data/3.0/onecall?lat=${LAT}&lon=${LON}&exclude=minutely,hourly,daily&appid=${KEY}&units=${UNITS}")
|
||||
echo "${weather}" >&2
|
||||
weather=$(echo "$weather" | jq -r ".current")
|
||||
|
||||
if [ ! -z "$weather" ]; then
|
||||
weather_temp=`echo "$weather" | jq ".temp" | cut -d "." -f 1`
|
||||
weather_icon_code=`echo "$weather" | jq -r ".weather[].icon" | head -1`
|
||||
weather_description=`echo "$weather" | jq -r ".weather[].description" | head -1 | sed -e "s/\b\(.\)/\u\1/g"`
|
||||
if [ -n "$weather" ]; then
|
||||
weather_temp=$(echo "$weather" | jq ".temp" | cut -d "." -f 1)
|
||||
weather_icon_code=$(echo "$weather" | jq -r ".weather[].icon" | head -1)
|
||||
weather_description=$(echo "$weather" | jq -r ".weather[].description" | head -1 | sed -e "s/\b\(.\)/\u\1/g")
|
||||
|
||||
#Big long if statement of doom
|
||||
if [ "$weather_icon_code" == "50d" ]; then
|
||||
@@ -108,17 +108,17 @@ get_weather_data() {
|
||||
weather_icon=" "
|
||||
weather_hex="#c0caf5"
|
||||
fi
|
||||
echo "$weather_icon" > ${cache_weather_icon}
|
||||
echo "$weather_description" > ${cache_weather_stat}
|
||||
echo "$weather_temp""°C" > ${cache_weather_degree}
|
||||
echo "$weather_hex" > ${cache_weather_hex}
|
||||
date "+%Y-%m-%d %H:%M:%S" | tee ${cache_weather_updatetime} >/dev/null
|
||||
echo "$weather_icon" > "${cache_weather_icon}"
|
||||
echo "$weather_description" > "${cache_weather_stat}"
|
||||
echo "$weather_temp""°C" > "${cache_weather_degree}"
|
||||
echo "$weather_hex" > "${cache_weather_hex}"
|
||||
date "+%Y-%m-%d %H:%M:%S" | tee "${cache_weather_updatetime}" >/dev/null
|
||||
else
|
||||
echo "Weather Unavailable" > ${cache_weather_stat}
|
||||
echo " " > ${cache_weather_icon}
|
||||
echo "-" > ${cache_weather_degree}
|
||||
echo "#adadff" > ${cache_weather_hex}
|
||||
date "+%Y-%m-%d %H:%M:%S" | tee ${cache_weather_updatetime} >/dev/null
|
||||
echo "Weather Unavailable" > "${cache_weather_stat}"
|
||||
echo " " > "${cache_weather_icon}"
|
||||
echo "-" > "${cache_weather_degree}"
|
||||
echo "#adadff" > "${cache_weather_hex}"
|
||||
date "+%Y-%m-%d %H:%M:%S" | tee "${cache_weather_updatetime}" >/dev/null
|
||||
fi
|
||||
}
|
||||
|
||||
@@ -145,13 +145,13 @@ if [[ "$1" == "--getdata" ]]; then
|
||||
get_weather_data
|
||||
fi
|
||||
elif [[ "$1" == "--icon" ]]; then
|
||||
cat ${cache_weather_icon}
|
||||
cat "${cache_weather_icon}"
|
||||
elif [[ "$1" == "--temp" ]]; then
|
||||
cat ${cache_weather_degree}
|
||||
cat "${cache_weather_degree}"
|
||||
elif [[ "$1" == "--hex" ]]; then
|
||||
tail -F ${cache_weather_hex}
|
||||
tail -F "${cache_weather_hex}"
|
||||
elif [[ "$1" == "--stat" ]]; then
|
||||
cat ${cache_weather_stat}
|
||||
cat "${cache_weather_stat}"
|
||||
elif [[ "$1" == "--updatetime" ]]; then
|
||||
cat ${cache_weather_updatetime}
|
||||
cat "${cache_weather_updatetime}"
|
||||
fi
|
||||
@@ -24,4 +24,4 @@ env = NVD_BACKEND,direct
|
||||
env = XCURSOR_SIZE,24
|
||||
env = HYPRCURSOR_SIZE,24
|
||||
env = ELECTRON_OZONE_PLATFORM_HINT,auto
|
||||
env = DISPLAY_DEVICE,nvidia_0 # or nvidia_0
|
||||
env = DISPLAY_DEVICE,intel_backlight # or nvidia_0
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
##! Apps
|
||||
bind = Super, C, exec, code --password-store=gnome-libsecret # Launch VSCode (editor)
|
||||
bind = Super, E, exec, nautilus --new-window # Launch file manager
|
||||
bind = Super, W, exec, firefox --new-window # Launch Firefox
|
||||
bind = Super, W, exec, zen --new-window # Launch Browser
|
||||
bind = Super, X, exec, gnome-text-editor # Launch Text Editor
|
||||
bind = Super, B, exec, killall btop || ghostty -e btop # Launch btop (system monitor)
|
||||
bind = Super, Space, exec, eww open main --toggle # Launch dashboard (eww)
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
preload = /home/kolkas/.config/backgrounds/arona-desks.jpg
|
||||
wallpaper = , /home/kolkas/.config/backgrounds/arona-desks.jpg
|
||||
preload = /home/kolkas/.config/backgrounds/nanami.png
|
||||
wallpaper = , /home/kolkas/.config/backgrounds/nanami.png
|
||||
|
||||
3
mpv/.gitignore
vendored
3
mpv/.gitignore
vendored
@@ -1 +1,2 @@
|
||||
lastopen.json
|
||||
# Shaders cache directory
|
||||
shaders/cache
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2020 Oscar Manglaras
|
||||
Copyright (c) 2021 noelsimbolon
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
121
mpv/README.md
Normal file
121
mpv/README.md
Normal file
@@ -0,0 +1,121 @@
|
||||
# mpv config
|
||||
|
||||

|
||||
|
||||
## Overview
|
||||
|
||||
**mpv** is a free (as in freedom and free beer), open-source, and cross-platform media player. It supports
|
||||
a wide variety of media file formats, audio and video codecs, and subtitle types.
|
||||
|
||||
This repo contains my personal mpv configurations and scripts that I use and are significantly better than default mpv, VLC, and MPC. Before installing, please take your time to read this whole README as common issues can be easily solved by simply reading carefully.
|
||||
|
||||
|
||||
## Preview
|
||||
|
||||
[](https://postimg.cc/VdZnsw2M)
|
||||
|
||||
## Installation
|
||||
|
||||
### Windows
|
||||
|
||||
Here are the steps to install mpv and to use my configuration files on Windows:
|
||||
* Download the latest 64bit mpv Windows build by shinchiro from [mpv.io/installation](https://mpv.io/installation/) or directly from [here](https://sourceforge.net/projects/mpv-player-windows/files/) and extract it wherever you please. This is now your mpv folder
|
||||
* Run `mpv-install.bat`, which is located in `installer` folder, with administrator priviledges by right-clicking and selecting Run as administrator
|
||||
* Download this repository as a ZIP file (or you can clone it using git)
|
||||
* Create a folder named `portable_config` (**this is important**), located at the same directory as `mpv.exe`
|
||||
* Extract or copy the contents of this repository that you have downloaded to the `portable_config` folder
|
||||
* To make some scripts work, you need to modify them from the release a little bit:
|
||||
* In order for the `mpv-gif.lua` script to work, it requires [FFmpeg](https://ffmpeg.org/) with libass enabled and accessible via terminal. See the [installation instructions](https://github.com/Scheliux/mpv-gif-generator#installation) from the script's source repository for further info.
|
||||
* **(Optional)** By default, the `mpv-gif.lua` script saves GIFs to `C:/Program Files/mpv/gifs`. To modify this, open `gif.conf`, which is located in `portable_config/script-opts` folder, with a text editor and specify the `dir`, which is output directory for GIFs, as you please. For example `dir="C:/Users/USERNAME/Pictures/mpv-gifs"`.
|
||||
* **(Optional)** Make your own mpv configuration. You can do that by modifying my configuration files and/or making your own from scratch or modifying others' configurations. Check out the [useful links](#useful-links) section for mpv configuration guides.
|
||||
* You're all set up.
|
||||
|
||||
### Linux
|
||||
|
||||
Here are the steps to install mpv and to use my configuration files on Linux:
|
||||
|
||||
* Install mpv and xclip (clipboard CLI interface) using the package manager that comes with your Linux distribution. xclip is needed for [copy-time.lua](https://github.com/noelsimbolon/mpv-config/blob/linux/scripts/copy-time.lua) and [seek-to.lua](https://github.com/noelsimbolon/mpv-config/blob/linux/scripts/seek-to.lua) scripts to work properly. The package name for mpv and xclip might also vary depending on your Linux distribution. Here, I will make Arch Linux, that comes with `pacman` as its package manager, as an example
|
||||
|
||||
```
|
||||
sudo pacman -S mpv xclip
|
||||
```
|
||||
|
||||
If you, for example, use Fedora Linux, that comes with `dnf` as its package manager, you can install mpv and xclip with the following command instead.
|
||||
```
|
||||
sudo dnf install mpv xclip
|
||||
```
|
||||
|
||||
If you use other Linux distributions, please refer to the documentation of your Linux distribution's package manager on how to install packages.
|
||||
|
||||
* Download this repository as a ZIP file (or you can clone it using git) and extract/copy it to your standard mpv configuration directory which is `~/.config/mpv`
|
||||
* Some things to highlight:
|
||||
* In order for the `mpv-gif.lua` script to work, it requires [FFmpeg](https://ffmpeg.org/) with libass enabled and accessible via terminal. See the [installation instructions](https://github.com/Scheliux/mpv-gif-generator#installation) from the script's source repository for further info.
|
||||
* **(Optional)** By default, the `mpv-gif.lua` script saves GIFs to `~/Videos/mpv-gifs`. To modify this, open `gif.conf`, which is located in `portable_config/script-opts` folder, with a text editor and specify the `dir`, which is output directory for GIFs, as you please. For example `dir="~/Videos"`.
|
||||
* **(Optional)** Make your own mpv configuration. You can do that by modifying my configuration files and/or making your own from scratch or modifying others' configurations. Check out the [useful links](#useful-links) section for mpv configuration guides.
|
||||
* You're all set up.
|
||||
|
||||
## Scripts
|
||||
|
||||
Scripts from external sources:
|
||||
|
||||
* audio-visualizer.lua ([source](https://github.com/mfcc64/mpv-scripts#visualizerlua))\
|
||||
Various audio visualization. It only works if you open audio files.
|
||||
|
||||
* autoload.lua ([source](https://github.com/mpv-player/mpv/blob/master/TOOLS/lua/autoload.lua))\
|
||||
Automatically load playlist entries before and after the currently playing file, by scanning the directory.
|
||||
|
||||
* copy-time.lua ([source](https://github.com/linguisticmind/mpv-scripts/tree/master/copy-time))\
|
||||
Copies current timecode in HH:MM:SS.MS format to clipboard. Cross-platform (Mac, Windows, Linux).
|
||||
|
||||
* cycle-commands.lua ([source](https://github.com/CogentRedTester/mpv-scripts#cycle-commands))\
|
||||
Cycles through a series of commands on a keypress. Each iteration of the cycle can contain as many commands as one wants. Syntax details are at the top of the file.
|
||||
|
||||
* cycle-profile.lua ([source](https://github.com/CogentRedTester/mpv-scripts#cycle-profile))\
|
||||
Cycles through a list of profiles sent via a script message and prints the profile-desc to the OSD. More details at the top of the file.
|
||||
|
||||
* modernz.lua ([source](https://github.com/Samillion/ModernZ))\
|
||||
A modern OSC UI replacement for MPV that retains the functionality of the default OSC.
|
||||
|
||||
* mpv-gif.lua ([source](https://github.com/Scheliux/mpv-gif-generator))\
|
||||
Script to generate GIFs from video playback. Requires FFmpeg with libass enabled. The exporting GIFs with subtitled currently doesn't work properly.
|
||||
|
||||
* playlistmanager.lua ([source](https://github.com/jonniek/mpv-playlistmanager))\
|
||||
Allows you to see and interact with your playlist in an intuitive way.
|
||||
|
||||
* seek-to.lua ([source](https://github.com/dexeonify/mpv-config/blob/main/scripts/seek-to.lua))\
|
||||
Seek to an absolute timestamp specified via keyboard input or pasted from clipboard.
|
||||
|
||||
* sponsorblock-minimal.lua ([source](https://codeberg.org/jouni/mpv_sponsorblock_minimal))\
|
||||
Skip sponsor segments in YouTube videos.
|
||||
|
||||
* thumbfast.lua ([source](https://github.com/po5/thumbfast))\
|
||||
High-performance on-the-fly thumbnailer for mpv. **The script does not display thumbnails on its own**, it is meant to be used alongside a UI script that calls thumbfast.
|
||||
|
||||
Configuration files for these scripts can be found in the `script-opts` folder. I also modified some of these scripts' default keybindings. To see my modifications, look for script keybindings in `input.conf`.
|
||||
|
||||
## Shaders
|
||||
|
||||
The shaders included in the `shaders` folder:
|
||||
|
||||
* ArtCNN_C4F32 ([source](https://github.com/Artoriuz/ArtCNN/blob/main/GLSL/ArtCNN_C4F32.glsl))\
|
||||
Used for luma upscaling.
|
||||
|
||||
* nnedi3-nns128-win8x4 ([source](https://github.com/bjin/mpv-prescalers/tree/master))\
|
||||
Used for luma upscaling.
|
||||
|
||||
Use shaders based on your preference and system capabilities. For more info about shaders, read the resources in the [useful links](#useful-links) section.
|
||||
|
||||
## Useful Links
|
||||
|
||||
* [mpv tutorial](https://thewiki.moe/tutorials/mpv/) by The Wiki
|
||||
* [mpv.conf guide](https://iamscum.wordpress.com/guides/videoplayback-guide/mpv-conf/) by iamscum
|
||||
* [mpv Configuration Guide for Watching Videos](https://kokomins.wordpress.com/2019/10/14/mpv-config-guide/) by Kokomins
|
||||
* [mpv Resampling](https://artoriuz.github.io/blog/mpv_upscaling.html) by João Vitor Chrisóstomo
|
||||
|
||||
## Official Links
|
||||
|
||||
* [mpv homepage](https://mpv.io/)
|
||||
* [mpv wiki](https://github.com/mpv-player/mpv/wiki)
|
||||
* [mpv FAQ](https://github.com/mpv-player/mpv/wiki/FAQ)
|
||||
* [mpv manual](https://mpv.io/manual/stable/)
|
||||
* [mpv User Scripts](https://github.com/mpv-player/mpv/wiki/User-Scripts)
|
||||
BIN
mpv/fonts/Netflix Sans Bold.otf
Normal file
BIN
mpv/fonts/Netflix Sans Bold.otf
Normal file
Binary file not shown.
BIN
mpv/fonts/Netflix Sans Light.otf
Normal file
BIN
mpv/fonts/Netflix Sans Light.otf
Normal file
Binary file not shown.
BIN
mpv/fonts/Netflix Sans Medium.otf
Normal file
BIN
mpv/fonts/Netflix Sans Medium.otf
Normal file
Binary file not shown.
BIN
mpv/fonts/fluent-system-icons.ttf
Normal file
BIN
mpv/fonts/fluent-system-icons.ttf
Normal file
Binary file not shown.
230
mpv/input.conf
230
mpv/input.conf
@@ -1,195 +1,49 @@
|
||||
# vim: syntax=config
|
||||
# Check the following link for mpv's default keybindings:
|
||||
# https://github.com/mpv-player/mpv/blob/master/etc/input.conf
|
||||
|
||||
# 左键单击暂停/双击全屏
|
||||
# MOUSE_BTN0 cycle pause
|
||||
MBTN_LEFT_DBL cycle fullscreen
|
||||
MBTN_LEFT cycle pause
|
||||
# ========== CUSTOM KEYBINDINGS ==========
|
||||
|
||||
# 滚轮控制音量
|
||||
AXIS_UP add volume +2
|
||||
AXIS_DOWN add volume -2
|
||||
# GENERAL
|
||||
k cycle ontop
|
||||
|
||||
# 快进和后退
|
||||
RIGHT osd-msg-bar seek +2 relative+keyframes
|
||||
LEFT osd-msg-bar seek -2 relative+keyframes
|
||||
l osd-msg-bar seek +2 relative+keyframes
|
||||
h osd-msg-bar seek -2 relative+keyframes
|
||||
SHIFT+RIGHT osd-msg-bar seek +10 relative+keyframes
|
||||
SHIFT+LEFT osd-msg-bar seek -10 relative+keyframes
|
||||
L osd-msg-bar seek +10 relative+keyframes
|
||||
H osd-msg-bar seek -10 relative+keyframes
|
||||
# VIDEO
|
||||
d cycle deband
|
||||
D cycle deinterlace
|
||||
n cycle video-unscaled
|
||||
C cycle-values video-aspect-override "16:9" "4:3" "2.35:1" "-1" # cycle the video aspect ratio ("-1" is the container aspect)
|
||||
|
||||
# 音量
|
||||
UP add volume +2
|
||||
# AUDIO
|
||||
a cycle audio
|
||||
A cycle audio down
|
||||
WHEEL_UP add volume 2
|
||||
WHEEL_DOWN add volume -2
|
||||
UP add volume 2
|
||||
DOWN add volume -2
|
||||
k add volume +2
|
||||
j add volume -2
|
||||
SHIFT+UP add volume +10
|
||||
SHIFT+DOWN add volume -10
|
||||
K add volume +10
|
||||
J add volume -10
|
||||
x add audio-delay -0.05
|
||||
X add audio-delay +0.05
|
||||
|
||||
# 亮度
|
||||
. add brightness +1
|
||||
, add brightness -1
|
||||
# SUBTITLES
|
||||
Shift+g add sub-scale +0.05 # increase the subtitle font size
|
||||
Shift+f add sub-scale -0.05 # decrease the subtitle font size
|
||||
E add sub-gauss +0.1 # https://mpv.io/manual/stable/#options-sub-gauss
|
||||
R add sub-gauss -0.1
|
||||
z add sub-delay -0.05 # shift subtitles 50 ms earlier
|
||||
Z add sub-delay +0.05 # shift subtitles 50 ms later
|
||||
u cycle sub-gray # https://mpv.io/manual/stable/#options-sub-gray
|
||||
U cycle blend-subtitles # https://mpv.io/manual/stable/#options-blend-subtitles
|
||||
p cycle sub-fix-timing # https://mpv.io/manual/stable/#options-sub-fix-timing
|
||||
g sub-reload # https://mpv.io/manual/stable/#command-interface-sub-reload
|
||||
l cycle-values sub-ass-override "yes" "force" "no" # https://mpv.io/manual/stable/#options-sub-ass-override
|
||||
|
||||
# 播放下一个/上一个
|
||||
|
||||
ALT+h playlist-prev ; show-text "${playlist-pos-1}/${playlist-count}"
|
||||
PGUP playlist-prev ; show-text "${playlist-pos-1}/${playlist-count}"
|
||||
|
||||
ALT+l playlist-next ; show-text "${playlist-pos-1}/${playlist-count}"
|
||||
PGDWN playlist-next ; show-text "${playlist-pos-1}/${playlist-count}"
|
||||
|
||||
# 显示播放信息
|
||||
CTRL+i script-binding stats/display-stats-toggle
|
||||
|
||||
# 音轨
|
||||
a script_message audio-menu # 打开音轨菜单
|
||||
A cycle audio # 下一个音轨
|
||||
|
||||
# 第一字幕列表选择
|
||||
s script_message subtitle-menu# 打开字幕菜单
|
||||
# # 第一字幕的下一个字幕
|
||||
S cycle sub
|
||||
# # 第二字幕的下一个字幕
|
||||
# ALT+d cycle secondary-sid
|
||||
# # 是否显示字幕 # cycle through subtitles
|
||||
CTRL+s cycle sub-visibility
|
||||
|
||||
|
||||
# 播放速度
|
||||
ALT+b add speed +0.05
|
||||
B add speed -0.05
|
||||
CTRL+b set speed 1.0
|
||||
|
||||
# 音轨延迟
|
||||
ALT+n add audio-delay +0.10
|
||||
N add audio-delay -0.10
|
||||
CTRL+n set sub-delay 0
|
||||
|
||||
# 字幕延迟
|
||||
ALT+m add sub-delay +0.10
|
||||
M add sub-delay -0.10
|
||||
CTRL+m set sub-delay 0
|
||||
|
||||
# 字幕大小和位置
|
||||
t add sub-scale -0.05 # decrease subtitle font size
|
||||
r add sub-scale +0.05 # increase subtitle font size
|
||||
T add sub-pos -1 # move subtitles up
|
||||
R add sub-pos +1 # move subtitles down
|
||||
CTRL+t set sub-scale 1.2
|
||||
CTRL+r set sub-pos 100
|
||||
|
||||
# f 全屏,这个是默认的
|
||||
SPACE cycle pause #暂停
|
||||
IDEOGRAPHIC_SPACE cycle pause
|
||||
m cycle mute #静音
|
||||
CTRL+p show-progress
|
||||
|
||||
|
||||
# 媒体按键
|
||||
MENU show-progress
|
||||
PLAY cycle pause
|
||||
PAUSE cycle pause
|
||||
PLAYPAUSE cycle pause
|
||||
FORWARD osd-msg-bar seek +5 relative keyframes
|
||||
REWIND osd-msg-bar seek -5 relative keyframes
|
||||
VOLUME_UP add volume +2 ; show-text "Volume: ${volume}"
|
||||
VOLUME_DOWN add volume -2 ; show-text "Volume: ${volume}"
|
||||
MUTE cycle mute
|
||||
CLOSE_WIN quit
|
||||
|
||||
# 播放列表
|
||||
# SHIFT+RETURN 打开列表
|
||||
# UP/DOWN移动选择
|
||||
# RETURN 打开
|
||||
# ESC退出
|
||||
SHIFT+ENTER script-binding playlistmanager/showplaylist
|
||||
ALT+k script-binding playlistmanager/moveup
|
||||
ALT+j script-binding playlistmanager/movedown
|
||||
ENTER script-binding playlistmanager/playfile
|
||||
ESC script-binding playlistmanager/hideplaylist
|
||||
|
||||
# 书签
|
||||
# o 打开书签
|
||||
# O 保存当前为书签
|
||||
# ESC :关闭书签菜单
|
||||
# UP/DOWN/j/k/J/K :浏览当前页面上的书签(按住可快速滚动)
|
||||
# LEFT/RIGHT :浏览书签页面(按住可快速滚动)
|
||||
# ENTER :加载当前选择的书签
|
||||
# d/DEL :删除当前选择的书
|
||||
o script_message bookmarker-menu
|
||||
O script_message bookmarker-quick-save
|
||||
d script_message bookmarker-menu
|
||||
|
||||
# 打开上次播放的
|
||||
CTRL+l script_message lastopen
|
||||
|
||||
|
||||
# 文件管理器
|
||||
# ctrl + o 打开文件管理器
|
||||
# alt + o 输入要打开的目录
|
||||
# up/down 移动选择
|
||||
# left/right 进入/离开目录
|
||||
# Return 播放
|
||||
|
||||
#忽略
|
||||
c ignore
|
||||
e ignore
|
||||
g ignore
|
||||
i ignore
|
||||
p ignore
|
||||
q ignore
|
||||
u ignore
|
||||
v ignore
|
||||
w ignore
|
||||
x ignore
|
||||
y ignore
|
||||
z ignore
|
||||
A ignore
|
||||
C ignore
|
||||
D ignore
|
||||
E ignore
|
||||
F ignore
|
||||
G ignore
|
||||
I ignore
|
||||
P ignore
|
||||
Q ignore
|
||||
U ignore
|
||||
V ignore
|
||||
W ignore
|
||||
X ignore
|
||||
Y ignore
|
||||
Z ignore
|
||||
< ignore
|
||||
> ignore
|
||||
? ignore
|
||||
/ ignore
|
||||
[ ignore
|
||||
] ignore
|
||||
{ ignore
|
||||
} ignore
|
||||
\ ignore
|
||||
| ignore
|
||||
0 ignore
|
||||
1 ignore
|
||||
2 ignore
|
||||
3 ignore
|
||||
4 ignore
|
||||
5 ignore
|
||||
6 ignore
|
||||
7 ignore
|
||||
8 ignore
|
||||
9 ignore
|
||||
BS ignore
|
||||
KP0 ignore
|
||||
KP1 ignore
|
||||
KP2 ignore
|
||||
KP3 ignore
|
||||
KP4 ignore
|
||||
KP5 ignore
|
||||
KP6 ignore
|
||||
KP7 ignore
|
||||
KP8 ignore
|
||||
KP9 ignore
|
||||
# SCRIPT KEYBINDINGS
|
||||
~ script-message cycle-commands "apply-profile HDR ; show-text 'HDR profile applied'" "apply-profile HDR restore ; show-text 'HDR profile restored'"
|
||||
# ~ script-message cycle-commands "apply-profile Clip ; show-text 'Clip profile applied'" "apply-profile Mobius ; show-text 'Mobius profile applied'" "apply-profile Reinhard ; show-text 'Reinhard profile applied'" "apply-profile Hable ; show-text 'Hable profile applied'" "apply-profile bt.2390 ; show-text 'bt.2390 profile applied'" "apply-profile Gamma ; show-text 'Gamma profile applied'" "apply-profile Linear ; show-text 'Linear profile applied'"
|
||||
c script-binding cycle-visualizer # cycle audio visualizer (audio-visualizer.lua)
|
||||
b script-binding set_gif_start # set the start timestamp for to make GIF (mpv-gif.lua)
|
||||
B script-binding set_gif_end # set the stop timestamp for to make GIF (mpv-gif.lua)
|
||||
ctrl+b script-binding make_gif # make the GIF using start and stop timestamps (mpv-gif.lua)
|
||||
ctrl+B script-binding make_gif_with_subtitles # make the GIF using start and stop timestamps with subtitles (doesn't seem to work) (mpv-gif.lua)
|
||||
ctrl+c script-binding copy-time # copy current timestamp to clipboard in HH:MM:SS.MS format (copy-time.lua)
|
||||
ctrl+S script-binding toggle-seeker # toggle keyboard input to seek to inputted timestamp (seek-to.lua)
|
||||
ctrl+v script-binding paste-timestamp # automatically seek to pasted timestamp from clipboard (seek-to.lua)
|
||||
alt+b script-binding sponsorblock # toggle sponsorblock on/off (sponsorblock-minimal.lua)
|
||||
|
||||
203
mpv/mpv.conf
203
mpv/mpv.conf
@@ -1,123 +1,130 @@
|
||||
# vim: syntax=config
|
||||
# ========== GENERAL ==========
|
||||
|
||||
profile=high-quality # Allows for higher quality playback on mpv
|
||||
vo=gpu-next # https://mpv.io/manual/stable/#video-output-drivers-gpu
|
||||
|
||||
# gpu-api=vulkan offers better overall performance, but it sometimes breaks playback
|
||||
# For displaying HDR content (not HDR -> SDR) "d3d11" is recommended (Windows only)
|
||||
gpu-api=vulkan # https://mpv.io/manual/stable/#options-gpu-api
|
||||
fullscreen=no # Start in fullscreen
|
||||
force-seekable=yes # If the player thinks that the media is not seekable, force enable seeking
|
||||
keep-open=always # Don't close the player after finishing the video,
|
||||
# and playback will never automatically advance to the next file in the playlist
|
||||
reset-on-next-file=pause # After playing the next file in the playlist,
|
||||
# it will automatically play the file instead of a paused state
|
||||
hwdec=vulkan # https://mpv.io/manual/stable/#options-hwdec
|
||||
dither-depth=8 # This must be set to match your monitor's bit depth
|
||||
scale-antiring=0.6 # https://mpv.io/manual/stable/#options-scale-antiring
|
||||
|
||||
|
||||
###########
|
||||
# General #
|
||||
###########
|
||||
auto-window-resize=no
|
||||
save-position-on-quit
|
||||
input-ipc-server=/tmp/mpvsocket # listen for IPC on this socket
|
||||
load-stats-overlay=no
|
||||
load-auto-profiles=no
|
||||
# ========== SCALERS AND SHADERS ==========
|
||||
|
||||
brightness=-8
|
||||
monitorpixelaspect=1
|
||||
no-border # no window title bar
|
||||
msg-module # prepend module name to log messages
|
||||
msg-color # color log messages on terminal
|
||||
term-osd-bar # display a progress bar on the terminal
|
||||
use-filedir-conf # look for additional config files in the directory of the opened file
|
||||
input-media-keys=no # enable/disable OSX media keys
|
||||
cursor-autohide=1000 # autohide the curser after 1s
|
||||
prefetch-playlist=yes
|
||||
force-seekable=yes
|
||||
scale=ewa_lanczossharp # Luma upscaler
|
||||
dscale=mitchell # Luma downscaler
|
||||
cscale=ewa_lanczossharp # Chroma up&downscaler
|
||||
gpu-shader-cache-dir='~~/shaders/cache' # https://mpv.io/manual/stable/#options-gpu-shader-cache-dir
|
||||
|
||||
screenshot-format=png
|
||||
screenshot-png-compression=8
|
||||
screenshot-template='~/down/%F (%P) %n'
|
||||
watch-later-directory='~/.mpv/watch_later'
|
||||
write-filename-in-watch-later-config
|
||||
watch-later-options-remove=fullscreen
|
||||
|
||||
hls-bitrate=max # use max quality for HLS streams
|
||||
# Only use these if you have high-end hardware
|
||||
# glsl-shader="~~/shaders/nnedi3-nns128-win8x4.hook"
|
||||
# glsl-shader="~~/shaders/ArtCNN_C4F32.glsl"
|
||||
|
||||
|
||||
# ========== DEBANDING ==========
|
||||
|
||||
[default]
|
||||
# Banding is a visual artifact, visual artifacts should never be in a video.
|
||||
# Example of banding: https://imgur.com/32d77H0
|
||||
# Debanding is the process of removing said banding.
|
||||
# 6 minute explanation of what causes banding: https://www.youtube.com/watch?v=h9j89L8eQQk
|
||||
|
||||
deband=no # Turn on only for videos with banding. (Keybind=d)
|
||||
deband-iterations=2 # https://mpv.io/manual/stable/#options-deband-iterations
|
||||
deband-threshold=64 # https://mpv.io/manual/stable/#options-deband-threshold
|
||||
deband-range=17 # https://mpv.io/manual/stable/#options-deband-range
|
||||
deband-grain=12 # https://mpv.io/manual/stable/#options-deband-grain
|
||||
|
||||
|
||||
#########
|
||||
# Cache #
|
||||
#########
|
||||
# ========== ON SCREEN DISPLAY AND ON SCREEN CONTROLLER ==========
|
||||
|
||||
cache=auto
|
||||
osd-bar=no # Don't show a huge volume box on screen when turning the volume up/down
|
||||
osc=no # Allows for custom OSC to be used https://github.com/cyl0/mpv-osc-morden-x
|
||||
border=no # Optional for modern OSC, but recommended
|
||||
cursor-autohide-fs-only=yes # If this option is given, the cursor is always visible in windowed mode
|
||||
# In fullscreen mode, the cursor is shown or hidden according to --cursor-autohide
|
||||
cursor-autohide=300 # Cursor hide in ms
|
||||
osd-level=1 # https://mpv.io/manual/stable/#options-osd-level
|
||||
osd-duration=1000 # Set the duration of the OSD messages in ms
|
||||
hr-seek=yes # Select when to use precise seeks that are not limited to keyframes
|
||||
# https://mpv.io/manual/stable/#options-hr-seek
|
||||
|
||||
osd-font='Verdana'
|
||||
osd-font-size=20
|
||||
osd-color='#FFFFFF' # Hex code for white
|
||||
osd-border-color='#000000' # Hex code for black
|
||||
osd-border-size=0.6 # Size for osd text and progress bar
|
||||
osd-blur=0.2 # Gaussian blur factor. 0 means no blur applied (default)
|
||||
|
||||
|
||||
#############
|
||||
# OSD / OSC #
|
||||
#############
|
||||
osc=no
|
||||
osd-level=1 # enable osd and display --osd-status-msg on interaction
|
||||
osd-duration=2500 # hide the osd after x ms
|
||||
osd-status-msg='${time-pos} / ${duration}${?percent-pos: (${percent-pos}%)}${?frame-drop-count:${!frame-drop-count==0: Dropped: ${frame-drop-count}}}\n${?chapter:Chapter: ${chapter}}'
|
||||
# ========== LANGUAGE PRIORITY ==========
|
||||
|
||||
osd-font='Source Han Sans CN'
|
||||
osd-font-size=32
|
||||
osd-color='#CCFFFFFF' # ARGB format
|
||||
osd-border-color='#DD322640' # ARGB format
|
||||
osd-bar-align-y=0 # progress bar y alignment (-1 top, 0 centered, 1 bottom)
|
||||
osd-border-size=2 # size for osd text and progress bar
|
||||
osd-bar-h=2 # height of osd bar as a fractional percentage of your screen height
|
||||
osd-bar-w=60 # width of " " "
|
||||
alang=ja,jp,jpn,en,eng # Audio language priority
|
||||
slang=en,eng # Subtitle language priority
|
||||
|
||||
|
||||
#############
|
||||
# Subtitles #
|
||||
#############
|
||||
sub-ass
|
||||
# ========== AUDIO ==========
|
||||
|
||||
demuxer-mkv-subtitle-preroll=yes # try to show embedded subs when seeking even when no index information is present
|
||||
demuxer-mkv-subtitle-preroll-secs=2
|
||||
|
||||
sub-auto=fuzzy # external subs don't have to match the file name exactly to autoload
|
||||
sub-file-paths-append=ass # search for external subs in these relative subdirectories
|
||||
sub-file-paths-append=srt
|
||||
sub-file-paths-append=sub
|
||||
sub-file-paths-append=subs
|
||||
sub-file-paths-append=subtitles
|
||||
|
||||
embeddedfonts=yes # use embedded fonts for SSA/ASS subs
|
||||
sub-fix-timing=no # do not try to fix gaps (which might make it worse in some cases)
|
||||
sub-ass-force-style=Kerning=yes # allows you to override style parameters of ASS scripts
|
||||
sub-use-margins
|
||||
sub-ass-force-margins
|
||||
|
||||
# the following options only apply to subtitles without own styling (i.e. not ASS but e.g. SRT)
|
||||
sub-font="Source Han Sans CN"
|
||||
sub-font-size=45
|
||||
sub-color="#FFFFFFFF"
|
||||
sub-border-color="#FF262626"
|
||||
sub-border-size=3.2
|
||||
sub-shadow-offset=1
|
||||
sub-shadow-color="#33000000"
|
||||
sub-scale=1.2
|
||||
volume=100 # default volume, 100 = unchanged
|
||||
audio-file-auto=fuzzy # Load external audio with (almost) the same name as the video
|
||||
volume-max=200 # Max volume of the player
|
||||
audio-pitch-correction=yes # https://mpv.io/manual/stable/#options-audio-pitch-correction
|
||||
|
||||
|
||||
#############
|
||||
# Languages #
|
||||
#############
|
||||
# ========== SUBTITLES ==========
|
||||
|
||||
alang=eng,chi # automatically select these subtitles (decreasing priority)
|
||||
slang=zh,zh-cn,zh-sim # automatically select these audio tracks (decreasing priority)
|
||||
demuxer-mkv-subtitle-preroll=yes # https://mpv.io/manual/stable/#options-demuxer-mkv-subtitle-preroll
|
||||
sub-fix-timing=no # https://mpv.io/manual/stable/#options-sub-fix-timing
|
||||
sub-auto=all # https://mpv.io/manual/stable/#options-sub-auto
|
||||
|
||||
# The following options only apply to subtitles without own styling
|
||||
sub-font='Netflix Sans Medium' # Specify font to use for subtitles that do not themselves specify a particular font
|
||||
sub-font-size=40
|
||||
sub-color='#FFFFFFFF'
|
||||
sub-border-color='#FF000000'
|
||||
sub-border-size=2.0
|
||||
sub-shadow-offset=0
|
||||
sub-spacing=0.0
|
||||
|
||||
|
||||
#########
|
||||
# Audio #
|
||||
#########
|
||||
# ========== SCREENSHOT ==========
|
||||
|
||||
audio-file-auto=fuzzy # external audio doesn't has to match the file name exactly to autoload
|
||||
audio-pitch-correction=yes # automatically insert scaletempo when playing with higher speed
|
||||
volume-max=200 # maximum volume in %, everything above 100 results in amplification
|
||||
volume=80 # default volume, 100 = unchanged
|
||||
screenshot-format=png # Output format of screenshots
|
||||
screenshot-high-bit-depth=yes # Same output bitdepth as the video. Set it "no" if you want to save disc space
|
||||
screenshot-png-compression=1 # Compression of the PNG picture (1-9).
|
||||
# Higher value means better compression, but takes more time
|
||||
screenshot-directory="~/Pictures/mpv-screenshots" # Output directory
|
||||
screenshot-template="%f-%wH.%wM.%wS.%wT-#%#00n" # Name format (filename-hour-minute-second-milisecond-number)
|
||||
|
||||
|
||||
################
|
||||
# Video Output #
|
||||
################
|
||||
profile=fast
|
||||
vo=gpu-next
|
||||
video-rotate=no
|
||||
hwdec=auto
|
||||
gpu-api=opengl
|
||||
# Defaults for all profiles
|
||||
# ========== INTERPOLATION ==========
|
||||
|
||||
# blend-subtitles=yes # Subtitle blending in scenechanges (smoother effect)
|
||||
# video-sync=display-resample # Set the fps as the max of your monitor refresh rate (only useful and needed with "interpolation=yes)
|
||||
# interpolation=yes # Enable interpolation
|
||||
# tscale=oversample # Interpolation method
|
||||
|
||||
|
||||
# ========== CACHE ==========
|
||||
# cache=yes
|
||||
# cache-on-disk=yes
|
||||
# cache-dir="C:\mpv-cache"
|
||||
# demuxer-max-bytes=1000MiB
|
||||
# demuxer-readahead-secs=300
|
||||
# demuxer-max-back-bytes=200MiB
|
||||
|
||||
|
||||
# ========== AUTO PROFILES ==========
|
||||
|
||||
# Auto profile that automatically applies for WEB-DL anime that need some debanding
|
||||
[WEB-DL]
|
||||
profile-desc=WEB-DL Anime (HatSubs, SubsPlease, HorribleSubs, Erai-raws)
|
||||
profile-cond=string.match(p.filename, "HatSubs")~=nil or string.match(p.filename, "SubsPlease")~=nil or string.match(p.filename, "HorribleSubs")~=nil or string.match(p.filename, "Erai%-raws")~=nil
|
||||
deband=yes
|
||||
|
||||
@@ -1,184 +0,0 @@
|
||||
# mpv keybindings
|
||||
#
|
||||
# Location of user-defined bindings: ~/.config/mpv/input.conf
|
||||
#
|
||||
# Lines starting with # are comments. Use SHARP to assign the # key.
|
||||
# Copy this file and uncomment and edit the bindings you want to change.
|
||||
#
|
||||
# List of commands and further details: DOCS/man/input.rst
|
||||
# List of special keys: --input-keylist
|
||||
# Keybindings testing mode: mpv --input-test --force-window --idle
|
||||
#
|
||||
# Use 'ignore' to unbind a key fully (e.g. 'ctrl+a ignore').
|
||||
#
|
||||
# Strings need to be quoted and escaped:
|
||||
# KEY show-text "This is a single backslash: \\ and a quote: \" !"
|
||||
#
|
||||
# You can use modifier-key combinations like Shift+Left or Ctrl+Alt+x with
|
||||
# the modifiers Shift, Ctrl, Alt and Meta (may not work on the terminal).
|
||||
#
|
||||
# The default keybindings are hardcoded into the mpv binary.
|
||||
# You can disable them completely with: --no-input-default-bindings
|
||||
|
||||
# Developer note:
|
||||
# On compilation, this file is baked into the mpv binary, and all lines are
|
||||
# uncommented (unless '#' is followed by a space) - thus this file defines the
|
||||
# default key bindings.
|
||||
|
||||
# If this is enabled, treat all the following bindings as default.
|
||||
#default-bindings start
|
||||
|
||||
#MBTN_LEFT ignore # don't do anything
|
||||
#MBTN_LEFT_DBL cycle fullscreen # toggle fullscreen
|
||||
#MBTN_RIGHT cycle pause # toggle pause/playback mode
|
||||
#MBTN_BACK playlist-prev # skip to the previous file
|
||||
#MBTN_FORWARD playlist-next # skip to the next file
|
||||
|
||||
# Mouse wheels, touchpad or other input devices that have axes
|
||||
# if the input devices supports precise scrolling it will also scale the
|
||||
# numeric value accordingly
|
||||
#WHEEL_UP add volume 2
|
||||
#WHEEL_DOWN add volume -2
|
||||
#WHEEL_LEFT seek -10 # seek 10 seconds backward
|
||||
#WHEEL_RIGHT seek 10 # seek 10 seconds forward
|
||||
|
||||
## Seek units are in seconds, but note that these are limited by keyframes
|
||||
#RIGHT seek 5 # seek 5 seconds forward
|
||||
#LEFT seek -5 # seek 5 seconds backward
|
||||
#UP seek 60 # seek 1 minute forward
|
||||
#DOWN seek -60 # seek 1 minute backward
|
||||
# Do smaller, always exact (non-keyframe-limited), seeks with shift.
|
||||
# Don't show them on the OSD (no-osd).
|
||||
#Shift+RIGHT no-osd seek 1 exact # seek exactly 1 second forward
|
||||
#Shift+LEFT no-osd seek -1 exact # seek exactly 1 second backward
|
||||
#Shift+UP no-osd seek 5 exact # seek exactly 5 seconds forward
|
||||
#Shift+DOWN no-osd seek -5 exact # seek exactly 5 seconds backward
|
||||
#Ctrl+LEFT no-osd sub-seek -1 # seek to the previous subtitle
|
||||
#Ctrl+RIGHT no-osd sub-seek 1 # seek to the next subtitle
|
||||
#Ctrl+Shift+LEFT sub-step -1 # change subtitle timing such that the previous subtitle is displayed
|
||||
#Ctrl+Shift+RIGHT sub-step 1 # change subtitle timing such that the next subtitle is displayed
|
||||
#Alt+left add video-pan-x 0.1 # move the video right
|
||||
#Alt+right add video-pan-x -0.1 # move the video left
|
||||
#Alt+up add video-pan-y 0.1 # move the video down
|
||||
#Alt+down add video-pan-y -0.1 # move the video up
|
||||
#Alt++ add video-zoom 0.1 # zoom in
|
||||
#ZOOMIN add video-zoom 0.1 # zoom in
|
||||
#Alt+- add video-zoom -0.1 # zoom out
|
||||
#ZOOMOUT add video-zoom -0.1 # zoom out
|
||||
#Ctrl+WHEEL_UP add video-zoom 0.1 # zoom in
|
||||
#Ctrl+WHEEL_DOWN add video-zoom -0.1 # zoom out
|
||||
#Alt+BS set video-zoom 0 ; set video-pan-x 0 ; set video-pan-y 0 # reset zoom and pan settings
|
||||
#PGUP add chapter 1 # seek to the next chapter
|
||||
#PGDWN add chapter -1 # seek to the previous chapter
|
||||
#Shift+PGUP seek 600 # seek 10 minutes forward
|
||||
#Shift+PGDWN seek -600 # seek 10 minutes backward
|
||||
#[ multiply speed 1/1.1 # decrease the playback speed
|
||||
#] multiply speed 1.1 # increase the playback speed
|
||||
#{ multiply speed 0.5 # halve the playback speed
|
||||
#} multiply speed 2.0 # double the playback speed
|
||||
#BS set speed 1.0 # reset the speed to normal
|
||||
#Shift+BS revert-seek # undo the previous (or marked) seek
|
||||
#Shift+Ctrl+BS revert-seek mark # mark the position for revert-seek
|
||||
#q quit
|
||||
#Q quit-watch-later # exit and remember the playback position
|
||||
#q {encode} quit 4
|
||||
#ESC set fullscreen no # leave fullscreen
|
||||
#ESC {encode} quit 4
|
||||
#p cycle pause # toggle pause/playback mode
|
||||
#. frame-step # advance one frame and pause
|
||||
#, frame-back-step # go back by one frame and pause
|
||||
#SPACE cycle pause # toggle pause/playback mode
|
||||
#> playlist-next # skip to the next file
|
||||
#ENTER playlist-next # skip to the next file
|
||||
#< playlist-prev # skip to the previous file
|
||||
#O no-osd cycle-values osd-level 3 1 # toggle displaying the OSD on user interaction or always
|
||||
#o show-progress # show playback progress
|
||||
#P show-progress # show playback progress
|
||||
#i script-binding stats/display-stats # display information and statistics
|
||||
#I script-binding stats/display-stats-toggle # toggle displaying information and statistics
|
||||
#` script-binding console/enable # open the console
|
||||
#z add sub-delay -0.1 # shift subtitles 100 ms earlier
|
||||
#Z add sub-delay +0.1 # delay subtitles by 100 ms
|
||||
#x add sub-delay +0.1 # delay subtitles by 100 ms
|
||||
#ctrl++ add audio-delay 0.100 # change audio/video sync by delaying the audio
|
||||
#ctrl+- add audio-delay -0.100 # change audio/video sync by shifting the audio earlier
|
||||
#Shift+g add sub-scale +0.1 # increase the subtitle font size
|
||||
#Shift+f add sub-scale -0.1 # decrease the subtitle font size
|
||||
#9 add volume -2
|
||||
#/ add volume -2
|
||||
#0 add volume 2
|
||||
#* add volume 2
|
||||
#m cycle mute # toggle mute
|
||||
#1 add contrast -1
|
||||
#2 add contrast 1
|
||||
#3 add brightness -1
|
||||
#4 add brightness 1
|
||||
#5 add gamma -1
|
||||
#6 add gamma 1
|
||||
#7 add saturation -1
|
||||
#8 add saturation 1
|
||||
#Alt+0 set current-window-scale 0.5 # halve the window size
|
||||
#Alt+1 set current-window-scale 1.0 # reset the window size
|
||||
#Alt+2 set current-window-scale 2.0 # double the window size
|
||||
#b cycle deband # toggle the debanding filter
|
||||
#d cycle deinterlace # cycle the deinterlacing filter
|
||||
#r add sub-pos -1 # move subtitles up
|
||||
#R add sub-pos +1 # move subtitles down
|
||||
#t add sub-pos +1 # move subtitles down
|
||||
#v cycle sub-visibility # hide or show the subtitles
|
||||
#Alt+v cycle secondary-sub-visibility # hide or show the secondary subtitles
|
||||
#V cycle sub-ass-vsfilter-aspect-compat # toggle stretching SSA/ASS subtitles with anamorphic videos to match the historical renderer
|
||||
#u cycle-values sub-ass-override "force" "yes" # toggle overriding SSA/ASS subtitle styles with the normal styles
|
||||
#j cycle sub # switch subtitle track
|
||||
#J cycle sub down # switch subtitle track backwards
|
||||
#SHARP cycle audio # switch audio track
|
||||
#_ cycle video # switch video track
|
||||
#T cycle ontop # toggle placing the video on top of other windows
|
||||
#f cycle fullscreen # toggle fullscreen
|
||||
#s screenshot # take a screenshot of the video in its original resolution with subtitles
|
||||
#S screenshot video # take a screenshot of the video in its original resolution without subtitles
|
||||
#Ctrl+s screenshot window # take a screenshot of the window with OSD and subtitles
|
||||
#Alt+s screenshot each-frame # automatically screenshot every frame; issue this command again to stop taking screenshots
|
||||
#w add panscan -0.1 # decrease panscan
|
||||
#W add panscan +0.1 # shrink black bars by cropping the video
|
||||
#e add panscan +0.1 # shrink black bars by cropping the video
|
||||
#A cycle-values video-aspect-override "16:9" "4:3" "2.35:1" "-1" # cycle the video aspect ratio ("-1" is the container aspect)
|
||||
#POWER quit
|
||||
#PLAY cycle pause # toggle pause/playback mode
|
||||
#PAUSE cycle pause # toggle pause/playback mode
|
||||
#PLAYPAUSE cycle pause # toggle pause/playback mode
|
||||
#PLAYONLY set pause no # unpause
|
||||
#PAUSEONLY set pause yes # pause
|
||||
#STOP quit
|
||||
#FORWARD seek 60 # seek 1 minute forward
|
||||
#REWIND seek -60 # seek 1 minute backward
|
||||
#NEXT playlist-next # skip to the next file
|
||||
#PREV playlist-prev # skip to the previous file
|
||||
#VOLUME_UP add volume 2
|
||||
#VOLUME_DOWN add volume -2
|
||||
#MUTE cycle mute # toggle mute
|
||||
#CLOSE_WIN quit
|
||||
#CLOSE_WIN {encode} quit 4
|
||||
#ctrl+w quit
|
||||
#E cycle edition # switch edition
|
||||
#l ab-loop # set/clear A-B loop points
|
||||
#L cycle-values loop-file "inf" "no" # toggle infinite looping
|
||||
#ctrl+c quit 4
|
||||
#DEL script-binding osc/visibility # cycle OSC visibility between never, auto (mouse-move) and always
|
||||
#ctrl+h cycle-values hwdec "auto-safe" "no" # toggle hardware decoding
|
||||
#F8 show-text ${playlist} # show the playlist
|
||||
#F9 show-text ${track-list} # show the list of video, audio and sub tracks
|
||||
|
||||
#
|
||||
# Legacy bindings (may or may not be removed in the future)
|
||||
#
|
||||
#! add chapter -1 # seek to the previous chapter
|
||||
#@ add chapter 1 # seek to the next chapter
|
||||
|
||||
#
|
||||
# Not assigned by default
|
||||
# (not an exhaustive list of unbound commands)
|
||||
#
|
||||
|
||||
# ? cycle sub-forced-events-only # display only DVD/PGS forced subtitle events
|
||||
# ? stop # stop playback (quit or enter idle mode)
|
||||
@@ -1,143 +0,0 @@
|
||||
#
|
||||
# Example mpv configuration file
|
||||
#
|
||||
# Warning:
|
||||
#
|
||||
# The commented example options usually do _not_ set the default values. Call
|
||||
# mpv with --list-options to see the default values for most options. There is
|
||||
# no builtin or example mpv.conf with all the defaults.
|
||||
#
|
||||
#
|
||||
# Configuration files are read system-wide from /usr/local/etc/mpv.conf
|
||||
# and per-user from ~/.config/mpv/mpv.conf, where per-user settings override
|
||||
# system-wide settings, all of which are overridden by the command line.
|
||||
#
|
||||
# Configuration file settings and the command line options use the same
|
||||
# underlying mechanisms. Most options can be put into the configuration file
|
||||
# by dropping the preceding '--'. See the man page for a complete list of
|
||||
# options.
|
||||
#
|
||||
# Lines starting with '#' are comments and are ignored.
|
||||
#
|
||||
# See the CONFIGURATION FILES section in the man page
|
||||
# for a detailed description of the syntax.
|
||||
#
|
||||
# Profiles should be placed at the bottom of the configuration file to ensure
|
||||
# that settings wanted as defaults are not restricted to specific profiles.
|
||||
|
||||
##################
|
||||
# video settings #
|
||||
##################
|
||||
|
||||
# Start in fullscreen mode by default.
|
||||
#fs=yes
|
||||
|
||||
# force starting with centered window
|
||||
#geometry=50%:50%
|
||||
|
||||
# don't allow a new window to have a size larger than 90% of the screen size
|
||||
#autofit-larger=90%x90%
|
||||
|
||||
# Do not close the window on exit.
|
||||
#keep-open=yes
|
||||
|
||||
# Do not wait with showing the video window until it has loaded. (This will
|
||||
# resize the window once video is loaded. Also always shows a window with
|
||||
# audio.)
|
||||
#force-window=immediate
|
||||
|
||||
# Disable the On Screen Controller (OSC).
|
||||
#osc=no
|
||||
|
||||
# Keep the player window on top of all other windows.
|
||||
#ontop=yes
|
||||
|
||||
# Specify fast video rendering preset (for --vo=<gpu|gpu-next> only)
|
||||
# Recommended for mobile devices or older hardware with limited processing power
|
||||
#profile=fast
|
||||
|
||||
# Specify high quality video rendering preset (for --vo=<gpu|gpu-next> only)
|
||||
# Offers superior image fidelity and visual quality for an enhanced viewing
|
||||
# experience on capable hardware
|
||||
#profile=high-quality
|
||||
|
||||
# Force video to lock on the display's refresh rate, and change video and audio
|
||||
# speed to some degree to ensure synchronous playback - can cause problems
|
||||
# with some drivers and desktop environments.
|
||||
#video-sync=display-resample
|
||||
|
||||
# Enable hardware decoding if available. Often, this does not work with all
|
||||
# video outputs, but should work well with default settings on most systems.
|
||||
# If performance or energy usage is an issue, forcing the vdpau or vaapi VOs
|
||||
# may or may not help.
|
||||
#hwdec=auto
|
||||
|
||||
##################
|
||||
# audio settings #
|
||||
##################
|
||||
|
||||
# Specify default audio device. You can list devices with: --audio-device=help
|
||||
# The option takes the device string (the stuff between the '...').
|
||||
#audio-device=alsa/default
|
||||
|
||||
# Do not filter audio to keep pitch when changing playback speed.
|
||||
#audio-pitch-correction=no
|
||||
|
||||
# Output 5.1 audio natively, and upmix/downmix audio with a different format.
|
||||
#audio-channels=5.1
|
||||
# Disable any automatic remix, _if_ the audio output accepts the audio format.
|
||||
# of the currently played file. See caveats mentioned in the manpage.
|
||||
# (The default is "auto-safe", see manpage.)
|
||||
#audio-channels=auto
|
||||
|
||||
##################
|
||||
# other settings #
|
||||
##################
|
||||
|
||||
# Pretend to be a web browser. Might fix playback with some streaming sites,
|
||||
# but also will break with shoutcast streams.
|
||||
#user-agent="Mozilla/5.0"
|
||||
|
||||
# cache settings
|
||||
#
|
||||
# Use a large seekable RAM cache even for local input.
|
||||
#cache=yes
|
||||
#
|
||||
# Use extra large RAM cache (needs cache=yes to make it useful).
|
||||
#demuxer-max-bytes=500M
|
||||
#demuxer-max-back-bytes=100M
|
||||
#
|
||||
# Disable the behavior that the player will pause if the cache goes below a
|
||||
# certain fill size.
|
||||
#cache-pause=no
|
||||
#
|
||||
# Store cache payload on the hard disk instead of in RAM. (This may negatively
|
||||
# impact performance unless used for slow input such as network.)
|
||||
#cache-dir=~/.cache/
|
||||
#cache-on-disk=yes
|
||||
|
||||
# Display English subtitles if available.
|
||||
#slang=en
|
||||
|
||||
# Play Finnish audio if available, fall back to English otherwise.
|
||||
#alang=fi,en
|
||||
|
||||
# Change subtitle encoding. For Arabic subtitles use 'cp1256'.
|
||||
# If the file seems to be valid UTF-8, prefer UTF-8.
|
||||
# (You can add '+' in front of the codepage to force it.)
|
||||
#sub-codepage=cp1256
|
||||
|
||||
# You can also include other configuration files.
|
||||
#include=/path/to/the/file/you/want/to/include
|
||||
|
||||
############
|
||||
# Profiles #
|
||||
############
|
||||
|
||||
# The options declared as part of profiles override global default settings,
|
||||
# but only take effect when the profile is active.
|
||||
|
||||
# The following profile can be enabled on the command line with: --profile=eye-cancer
|
||||
|
||||
#[eye-cancer]
|
||||
#sharpen=5
|
||||
@@ -1 +0,0 @@
|
||||
font_size=44
|
||||
@@ -1,175 +0,0 @@
|
||||
#######################################################
|
||||
# This is the default config file for mpv-file-browser
|
||||
# https://github.com/CogentRedTester/mpv-file-browser
|
||||
#######################################################
|
||||
|
||||
# root directories, separated by commas
|
||||
# on linux you will probably want to add `/`,
|
||||
# on windows this should be used to add different drive letters
|
||||
# Examples:
|
||||
# linux: root=~/,/
|
||||
# windows: root=~/,C:/
|
||||
root=~/
|
||||
|
||||
# characters to separate root directories, each character works individually
|
||||
# this is in case one is using directories with strange names
|
||||
root_separators=,;
|
||||
|
||||
# number of entries to show on the screen at once
|
||||
num_entries=20
|
||||
|
||||
# wrap the cursor around the top and bottom of the list
|
||||
wrap=no
|
||||
|
||||
# only show files compatible with mpv in the browser
|
||||
filter_files=yes
|
||||
|
||||
# experimental feature that recurses directories concurrently when appending items to the playlist
|
||||
# this feature has the potential for massive performance improvements when using addons with asynchronous IO
|
||||
concurrent_recursion=no
|
||||
|
||||
# maximum number of recursions that can run concurrently
|
||||
# if this number is too high it risks overflowing the mpv event queue, which will cause some directories to be dropped entirely
|
||||
max_concurrency=16
|
||||
|
||||
# enable custom keybinds
|
||||
# the keybind json file must go in ~~/script-opts
|
||||
custom_keybinds=no
|
||||
|
||||
# file-browser only shows files that are compatible with mpv by default
|
||||
# adding a file extension to this list will add it to the extension whitelist
|
||||
# extensions are separated with the root separators, do not use any spaces
|
||||
extension_whitelist=
|
||||
|
||||
# add file extensions to this list to disable default filetypes
|
||||
# note that this will also override audio/subtitle_extension options below
|
||||
extension_blacklist=
|
||||
|
||||
# files with these extensions will be added as additional audio tracks for the current file instead of appended to the playlist
|
||||
# items on this list are automatically added to the extension whitelist
|
||||
audio_extensions=mka,dts,dtshd,dts-hd,truehd,true-hd
|
||||
|
||||
# files with these extensions will be added as additional subtitle tracks for the current file instead of appended to the playlist
|
||||
# items on this list are automatically added to the extension whitelist
|
||||
subtitle_extensions=etf,etf8,utf-8,idx,sub,srt,rt,ssa,ass,mks,vtt,sup,scc,smi,lrc,pgs
|
||||
|
||||
# filter directories or files starting with a period like .config
|
||||
# for linux systems
|
||||
filter_dot_dirs=no
|
||||
filter_dot_files=no
|
||||
|
||||
# substitude forward slashes for backslashes when appending a local file to the playlist
|
||||
# may be useful on windows systems
|
||||
substitute_backslash=no
|
||||
|
||||
# interpret backslashes `\` in paths as forward slashes `/`
|
||||
# this is useful on Windows, which natively uses backslashes.
|
||||
# As backslashes are valid filename characters in Unix systems this could
|
||||
# cause mangled paths, though such filenames are rare.
|
||||
# Use `yes` and `no` to enable/disable. `auto` tries to use the mpv `platform`
|
||||
# property (mpv v0.36+) to decide. If the property is unavailable it defaults to `yes`.
|
||||
normalise_backslash=auto
|
||||
|
||||
# this option reverses the behaviour of the alt+ENTER keybind
|
||||
# when disabled the keybind is required to enable autoload for the file
|
||||
# when enabled the keybind disables autoload for the file
|
||||
autoload=no
|
||||
|
||||
# if autoload is triggered by selecting the currently playing file, then
|
||||
# the current file will have it's watch-later config saved before being closed and re-opened
|
||||
# essentially the current file will not be restarted
|
||||
autoload_save_current=yes
|
||||
|
||||
# when opening the browser in idle mode prefer the current working directory over the root
|
||||
# note that the working directory is set as the 'current' directory regardless, so `home` will
|
||||
# move the browser there even if this option is set to false
|
||||
default_to_working_directory=no
|
||||
|
||||
# when moving up a directory do not stop on empty protocol schemes like `ftp://`
|
||||
# e.g. moving up from `ftp://localhost/` will move straight to the root instead of `ftp://`
|
||||
skip_protocol_schemes=yes
|
||||
|
||||
# map optical device paths to their respective file paths,
|
||||
# e.g. mapping bd:// to the value of the bluray-device property
|
||||
map_bd_device=yes
|
||||
map_dvd_device=yes
|
||||
map_cdda_device=yes
|
||||
|
||||
# enables addons
|
||||
addons=no
|
||||
addon_directory=~~/script-modules/file-browser-addons
|
||||
|
||||
# directory to load external modules - currently just user-input-module
|
||||
module_directory=~~/script-modules
|
||||
|
||||
# turn the OSC idle screen off and on when opening and closing the browser
|
||||
# this should only be enabled if file-browser is the only thing controlling the idle-screen,
|
||||
# if multiple sources attempt to control the idle-screen at the same time it can cause unexpected behaviour.
|
||||
toggle_idlescreen=no
|
||||
|
||||
# Set the current open status of the browser in the `file_browser/open` field of the `user-data` property.
|
||||
# This property is only available in mpv v0.36+.
|
||||
set_user_data=yes
|
||||
|
||||
# Set the current open status of the browser in the `file_browser-open` field of the `shared-script-properties` property.
|
||||
# This property is deprecated. When it is removed in mpv v0.37 file-browser will automatically disable this option.
|
||||
set_shared_script_properties=no
|
||||
|
||||
####################################
|
||||
######### style settings ###########
|
||||
####################################
|
||||
|
||||
# force file-browser to use a specific text alignment (default: top-left)
|
||||
# uses ass tag alignment numbers: https://aegi.vmoe.info/docs/3.0/ASS_Tags/#index23h3
|
||||
# set to 0 to use the default mpv osd-align options
|
||||
alignment=7
|
||||
|
||||
# The format string used for the header. Uses custom-keybind substitution codes to
|
||||
# dynamically change the contents of the header. See: docs/custom-keybinds.md#codes
|
||||
# e.g. to add file numbers, set this to: {\fnMonospace}[%i/%x]{\fn<font_name_header or blank>} %q\N----------------------------------------------------
|
||||
format_string_header=%q\N----------------------------------------------------
|
||||
|
||||
# The format strings used for the wrappers. Supports custom-keybind substitution codes, and
|
||||
# supports two additional codes: `%<` and `%>` to show the number of items before and after the visible list, respectively.
|
||||
# Setting these options to empty strings will disable the wrappers.
|
||||
format_string_topwrapper=%< item(s) above\N
|
||||
format_string_bottomwrapper=\N%> item(s) remaining
|
||||
|
||||
# allows custom icons be set for the folder and cursor
|
||||
# the `\h` character is a hard space to add padding
|
||||
folder_icon={\p1}m 6.52 0 l 1.63 0 b 0.73 0 0.01 0.73 0.01 1.63 l 0 11.41 b 0 12.32 0.73 13.05 1.63 13.05 l 14.68 13.05 b 15.58 13.05 16.31 12.32 16.31 11.41 l 16.31 3.26 b 16.31 2.36 15.58 1.63 14.68 1.63 l 8.15 1.63{\p0}\h
|
||||
cursor_icon={\p1}m 14.11 6.86 l 0.34 0.02 b 0.25 -0.02 0.13 -0 0.06 0.08 b -0.01 0.16 -0.02 0.28 0.04 0.36 l 3.38 5.55 l 3.38 5.55 3.67 6.15 3.81 6.79 3.79 7.45 3.61 8.08 3.39 8.5l 0.04 13.77 b -0.02 13.86 -0.01 13.98 0.06 14.06 b 0.11 14.11 0.17 14.13 0.24 14.13 b 0.27 14.13 0.31 14.13 0.34 14.11 l 14.11 7.28 b 14.2 7.24 14.25 7.16 14.25 7.07 b 14.25 6.98 14.2 6.9 14.11 6.86{\p0}\h
|
||||
|
||||
# set the opacity of fonts in hexadecimal from 00 (opaque) to FF (transparent)
|
||||
font_opacity_selection_marker=99
|
||||
|
||||
# print the header in bold font
|
||||
font_bold_header=yes
|
||||
|
||||
# scale the size of the browser; 2 would double the size, 0.5 would halve it, etc.
|
||||
# the header and wrapper scaling is relative to the base scaling
|
||||
scaling_factor_base=1
|
||||
scaling_factor_header=1.4
|
||||
scaling_factor_wrappers=0.64
|
||||
|
||||
# set custom font names, blank is the default
|
||||
# setting custom fonts for the folder/cursor can fix broken or missing icons
|
||||
font_name_header=
|
||||
font_name_body=
|
||||
font_name_wrappers=
|
||||
font_name_folder=
|
||||
font_name_cursor=
|
||||
|
||||
# set custom font colours
|
||||
# colours are in hexadecimal format in Blue Green Red order
|
||||
# note that this is the opposite order to most RGB colour codes
|
||||
font_colour_header=00ccff
|
||||
font_colour_body=ffffff
|
||||
font_colour_wrappers=00ccff
|
||||
font_colour_cursor=00ccff
|
||||
|
||||
# these are colours applied to list items in different states
|
||||
font_colour_selected=fce788
|
||||
font_colour_multiselect=fcad88
|
||||
font_colour_playing=33ff66
|
||||
font_colour_playing_multiselected=22b547
|
||||
10
mpv/script-opts/gif.conf
Normal file
10
mpv/script-opts/gif.conf
Normal file
@@ -0,0 +1,10 @@
|
||||
# ========== CONFIGURATION FILE FOR MPV-GIF.LUA ==========
|
||||
|
||||
# Sets the output directory
|
||||
dir="$HOME/Videos/mpv-gifs"
|
||||
|
||||
# Sets the resolution of the output GIFs
|
||||
rez=1920
|
||||
|
||||
# Sets the framerate of the output gifs. Default is 15. Don't go too overboard or the filesize will balloon
|
||||
fps=23.976
|
||||
382
mpv/script-opts/modernz.conf
Normal file
382
mpv/script-opts/modernz.conf
Normal file
@@ -0,0 +1,382 @@
|
||||
# Language and display
|
||||
# set language (for available options, see: https://github.com/Samillion/ModernZ/blob/main/docs/TRANSLATIONS.md)
|
||||
language=en
|
||||
# font for the OSC (default: mpv-osd-symbols or the one set in mpv.conf)
|
||||
font=mpv-osd-symbols
|
||||
|
||||
# show mpv logo when idle
|
||||
idlescreen=yes
|
||||
# show OSC window top bar: "auto", "yes", or "no" (borderless/fullscreen)
|
||||
window_top_bar=auto
|
||||
# show OSC when windowed
|
||||
showwindowed=yes
|
||||
# show OSC when fullscreen
|
||||
showfullscreen=yes
|
||||
# show OSC when paused
|
||||
showonpause=no
|
||||
# disable OSC hide timeout when paused
|
||||
keeponpause=yes
|
||||
# disable Santa hat in December
|
||||
greenandgrumpy=no
|
||||
|
||||
# OSC behaviour and scaling
|
||||
# time (in ms) before OSC hides if no mouse movement
|
||||
hidetimeout=1500
|
||||
# if seeking should reset the hidetimeout
|
||||
seek_resets_hidetimeout=yes
|
||||
# fade-out duration (in ms), set to 0 for no fade
|
||||
fadeduration=200
|
||||
# whether to enable fade-in effect
|
||||
fadein=no
|
||||
# minimum mouse movement (in pixels) required to show OSC
|
||||
minmousemove=0
|
||||
# show OSC only when hovering at the bottom
|
||||
bottomhover=yes
|
||||
# height of hover zone for bottomhover (in pixels)
|
||||
bottomhover_zone=130
|
||||
# show OSC when seeking
|
||||
osc_on_seek=no
|
||||
# show OSC on start of every file
|
||||
osc_on_start=no
|
||||
# pause video while seeking with mouse move (on button hold)
|
||||
mouse_seek_pause=yes
|
||||
# force show seekbar tooltip on mouse drag, even if not hovering seekbar
|
||||
force_seek_tooltip=no
|
||||
|
||||
# scale osc with the video
|
||||
vidscale=auto
|
||||
# osc scale factor when windowed
|
||||
scalewindowed=1.0
|
||||
# osc scale factor when fullscreen
|
||||
scalefullscreen=1.0
|
||||
|
||||
# Elements display
|
||||
# show title in the OSC (above seekbar)
|
||||
show_title=yes
|
||||
# title above seekbar format: "${media-title}" or "${filename}"
|
||||
title=${media-title}
|
||||
# font size of the title text (above seekbar)
|
||||
title_font_size=24
|
||||
# chapter title font size
|
||||
chapter_title_font_size=14
|
||||
# show cached time information
|
||||
cache_info=no
|
||||
# show cache speed per second
|
||||
cache_info_speed=no
|
||||
# font size of the cache information
|
||||
cache_info_font_size=12
|
||||
|
||||
# show chapter title alongside timestamp (below seekbar)
|
||||
show_chapter_title=yes
|
||||
# format for chapter display on seekbar hover (set to "no" to disable)
|
||||
chapter_fmt=%s
|
||||
|
||||
# show total time instead of remaining time
|
||||
timetotal=yes
|
||||
# show timecodes with milliseconds
|
||||
timems=no
|
||||
# use the Unicode minus sign in remaining time
|
||||
unicodeminus=no
|
||||
# "dynamic" or "fixed". dynamic shows MM:SS when possible, fixed always shows HH:MM:SS
|
||||
time_format=dynamic
|
||||
# font size of the time display
|
||||
time_font_size=16
|
||||
# tooltips font size
|
||||
tooltip_font_size=14
|
||||
|
||||
# Title bar settings
|
||||
# show window title in borderless/fullscreen mode
|
||||
window_title=no
|
||||
# show window controls (close, minimize, maximize) in borderless/fullscreen
|
||||
window_controls=yes
|
||||
# same as title but for window_top_bar
|
||||
windowcontrols_title=${media-title}
|
||||
|
||||
# Subtitle display settings
|
||||
# raise subtitles above the OSC when shown
|
||||
raise_subtitles=yes
|
||||
# amount by which subtitles are raised when the OSC is shown (in pixels)
|
||||
raise_subtitle_amount=125
|
||||
|
||||
# Buttons display and functionality
|
||||
# show the jump backward and forward buttons
|
||||
jump_buttons=yes
|
||||
# change the jump amount in seconds
|
||||
jump_amount=10
|
||||
# change the jump amount in seconds when right-clicking jump buttons and shift-clicking chapter skip buttons
|
||||
jump_more_amount=60
|
||||
# show different icon when jump_amount is set to 5, 10, or 30
|
||||
jump_icon_number=yes
|
||||
# seek mode for jump buttons
|
||||
jump_mode=relative
|
||||
# enable continuous jumping when holding down seek buttons
|
||||
jump_softrepeat=yes
|
||||
# show the chapter skip backward and forward buttons
|
||||
chapter_skip_buttons=no
|
||||
# enable continuous skipping when holding down chapter skip buttons
|
||||
chapter_softrepeat=yes
|
||||
# show next/previous playlist track buttons
|
||||
track_nextprev_buttons=yes
|
||||
|
||||
# show mute button and volume slider
|
||||
volume_control=yes
|
||||
# volume scale type: "linear" or "logarithmic"
|
||||
volume_control_type=linear
|
||||
# show playlist button: Left-click for simple playlist, Right-click for interactive playlist
|
||||
playlist_button=yes
|
||||
# hide playlist button when no playlist exists
|
||||
hide_empty_playlist_button=no
|
||||
# gray out the playlist button when no playlist exists
|
||||
gray_empty_playlist_button=no
|
||||
|
||||
# show download button on web videos (requires yt-dlp and ffmpeg)
|
||||
download_button=yes
|
||||
# default download directory for videos (https://mpv.io/manual/master/#paths)
|
||||
download_path=~/Videos/mpv Downloads/
|
||||
# show screenshot button
|
||||
screenshot_button=yes
|
||||
# flag for screenshot button: "subtitles", "video", "window", "each-frame"
|
||||
screenshot_flag=subtitles
|
||||
|
||||
# show window on top button
|
||||
ontop_button=yes
|
||||
# show loop button
|
||||
loop_button=yes
|
||||
# show speed control button
|
||||
speed_button=yes
|
||||
# speed change amount per click
|
||||
speed_button_click=1
|
||||
# speed change amount on scroll
|
||||
speed_button_scroll=0.25
|
||||
# show info button
|
||||
info_button=yes
|
||||
# show fullscreen toggle button
|
||||
fullscreen_button=yes
|
||||
|
||||
# enable looping by right-clicking pause
|
||||
loop_in_pause=yes
|
||||
|
||||
# force buttons to always be active. can add: playlist_prev,playlist_next
|
||||
buttons_always_active=none
|
||||
|
||||
# icon size for the play/pause button
|
||||
playpause_size=28
|
||||
# icon size for the middle buttons
|
||||
midbuttons_size=24
|
||||
# icon size for the side buttons
|
||||
sidebuttons_size=24
|
||||
|
||||
# show zoom controls in image viewer mode
|
||||
zoom_control=yes
|
||||
# maximum zoom in value
|
||||
zoom_in_max=4
|
||||
# minimum zoom out value
|
||||
zoom_out_min=-1
|
||||
|
||||
# Colors and style
|
||||
# accent color of the OSC and title bar
|
||||
osc_color=#000000
|
||||
# color of the title in borderless/fullscreen mode
|
||||
window_title_color=#FFFFFF
|
||||
# color of the window controls (close, minimize, maximize) in borderless/fullscreen mode
|
||||
window_controls_color=#FFFFFF
|
||||
# color of close window control on hover
|
||||
windowcontrols_close_hover=#F45C5B
|
||||
# color of maximize window controls on hover
|
||||
windowcontrols_max_hover=#F8BC3A
|
||||
# color of minimize window controls on hover
|
||||
windowcontrols_min_hover=#43CB44
|
||||
# color of the title (above seekbar)
|
||||
title_color=#FFFFFF
|
||||
# color of the cache information
|
||||
cache_info_color=#FFFFFF
|
||||
# color of the seekbar progress and handle
|
||||
seekbarfg_color=#FB8C00
|
||||
# color of the remaining seekbar
|
||||
seekbarbg_color=#94754F
|
||||
# color of the cache ranges on the seekbar
|
||||
seekbar_cache_color=#918F8E
|
||||
# match volume bar color with seekbar color (ignores side_buttons_color)
|
||||
volumebar_match_seek_color=no
|
||||
# color of the timestamps (below seekbar)
|
||||
time_color=#FFFFFF
|
||||
# color of the chapter title next to timestamp (below seekbar)
|
||||
chapter_title_color=#FFFFFF
|
||||
# color of the side buttons (audio, subtitles, playlist, etc.)
|
||||
side_buttons_color=#FFFFFF
|
||||
# color of the middle buttons (skip, jump, chapter, etc.)
|
||||
middle_buttons_color=#FFFFFF
|
||||
# color of the play/pause button
|
||||
playpause_color=#FFFFFF
|
||||
# color of the element when held down (pressed)
|
||||
held_element_color=#999999
|
||||
# color of a hovered button when hover_effect includes "color"
|
||||
hover_effect_color=#FB8C00
|
||||
# color of the border for thumbnails (with thumbfast)
|
||||
thumbnail_border_color=#111111
|
||||
# color of the border outline for thumbnails
|
||||
thumbnail_border_outline=#404040
|
||||
|
||||
# alpha of the OSC background box
|
||||
fade_alpha=130
|
||||
# blur strength for the OSC alpha fade. caution: high values can take a lot of CPU time to render
|
||||
fade_blur_strength=100
|
||||
# use with "fade_blur_strength=0" to create a transparency box
|
||||
fade_transparency_strength=0
|
||||
# alpha of the window title bar (0 to disable)
|
||||
window_fade_alpha=100
|
||||
# blur strength for the window title bar. caution: high values can take a lot of CPU time to render
|
||||
window_fade_blur_strength=100
|
||||
# use with "window_fade_blur_strength=0" to create a transparency box
|
||||
window_fade_transparency_strength=0
|
||||
# width of the thumbnail border (for thumbfast)
|
||||
thumbnail_border=3
|
||||
# rounded corner radius for thumbnail border (0 to disable)
|
||||
thumbnail_border_radius=3
|
||||
|
||||
# Button hover effects
|
||||
# active button hover effects: "glow", "size", "color"; can use multiple separated by commas
|
||||
hover_effect=size,glow,color
|
||||
# relative size of a hovered button if "size" effect is active
|
||||
hover_button_size=115
|
||||
# glow intensity when "glow" hover effect is active
|
||||
button_glow_amount=5
|
||||
# apply hover size effect to slider handle
|
||||
hover_effect_for_sliders=yes
|
||||
|
||||
# Tooltips and hints
|
||||
# enable tooltips for disabled buttons and elements
|
||||
tooltips_for_disabled_elements=yes
|
||||
# enable text hints for info, loop, ontop, and screenshot buttons
|
||||
tooltip_hints=yes
|
||||
|
||||
# Progress bar settings
|
||||
# size ratio of the seekbar handle (range: 0 ~ 1)
|
||||
seek_handle_size=0.8
|
||||
# show seek range overlay
|
||||
seekrange=yes
|
||||
# transparency of the seek range
|
||||
seekrangealpha=150
|
||||
# update chapter markers on the seekbar when duration changes
|
||||
livemarkers=yes
|
||||
# use keyframes when dragging the seekbar
|
||||
seekbarkeyframes=no
|
||||
# top chapter nibbles above seekbar
|
||||
nibbles_top=yes
|
||||
# bottom chapter nibbles below seekbar
|
||||
nibbles_bottom=yes
|
||||
# chapter nibble style. "triangle", "bar" or "single-bar"
|
||||
nibbles_style=triangle
|
||||
|
||||
# automatically set keyframes for the seekbar based on video length
|
||||
automatickeyframemode=yes
|
||||
# videos longer than this (in seconds) will have keyframes on the seekbar
|
||||
automatickeyframelimit=600
|
||||
|
||||
# always show a small progress line at the bottom of the screen
|
||||
persistentprogress=no
|
||||
# height of the persistent progress bar
|
||||
persistentprogressheight=17
|
||||
# show buffer status on web videos in the persistent progress line
|
||||
persistentbuffer=no
|
||||
|
||||
# Miscellaneous settings
|
||||
# only used at init to set visibility_mode(...)
|
||||
visibility=auto
|
||||
# visibility modes to cycle through, modes are separated by _
|
||||
visibility_modes=never_auto_always
|
||||
# minimum interval between OSC redraws (in seconds)
|
||||
tick_delay=0.03
|
||||
# use display FPS as the minimum redraw interval
|
||||
tick_delay_follow_display_fps=no
|
||||
|
||||
# Elements Position
|
||||
# Useful when adjusting font size or type
|
||||
|
||||
# title height position above seekbar
|
||||
title_height=96
|
||||
# title height position if a chapter title is below it
|
||||
title_with_chapter_height=108
|
||||
# chapter title height position above seekbar
|
||||
chapter_title_height=91
|
||||
# time codes height position
|
||||
time_codes_height=35
|
||||
# time codes height position with portrait window
|
||||
time_codes_centered_height=57
|
||||
# tooltip height position offset
|
||||
tooltip_height_offset=2
|
||||
# if tooltip contains many characters, it is moved to the left by offset
|
||||
tooltip_left_offset=5
|
||||
# portrait window width trigger to move some elements
|
||||
portrait_window_trigger=1000
|
||||
# hide volume bar trigger window width
|
||||
hide_volume_bar_trigger=1150
|
||||
# osc height offset if title above seekbar is disabled
|
||||
notitle_osc_h_offset=25
|
||||
# osc height offset if chapter title is disabled or doesn't exist
|
||||
nochapter_osc_h_offset=10
|
||||
# seek hover timecodes tooltip height position offset
|
||||
seek_hover_tooltip_h_offset=0
|
||||
# osc height without offsets
|
||||
osc_height=132
|
||||
|
||||
## Mouse commands
|
||||
## details: https://github.com/Samillion/ModernZ#mouse-commands-user-options
|
||||
|
||||
# title above seekbar mouse actions
|
||||
title_mbtn_left_command=script-binding stats/display-page-5
|
||||
title_mbtn_mid_command=show-text ${path}
|
||||
title_mbtn_right_command=script-binding select/select-watch-history; script-message-to modernz osc-hide
|
||||
|
||||
# playlist button mouse actions
|
||||
playlist_mbtn_left_command=script-binding select/menu; script-message-to modernz osc-hide
|
||||
playlist_mbtn_right_command=script-binding select/select-playlist; script-message-to modernz osc-hide
|
||||
|
||||
# volume mouse actions
|
||||
vol_ctrl_mbtn_left_command=no-osd cycle mute
|
||||
vol_ctrl_mbtn_right_command=script-binding select/select-audio-device; script-message-to modernz osc-hide
|
||||
vol_ctrl_wheel_down_command=no-osd add volume -5
|
||||
vol_ctrl_wheel_up_command=no-osd add volume 5
|
||||
|
||||
# audio button mouse actions
|
||||
audio_track_mbtn_left_command=script-binding select/select-aid; script-message-to modernz osc-hide
|
||||
audio_track_mbtn_mid_command=cycle audio down
|
||||
audio_track_mbtn_right_command=cycle audio
|
||||
audio_track_wheel_down_command=cycle audio
|
||||
audio_track_wheel_up_command=cycle audio down
|
||||
|
||||
# subtitle button mouse actions
|
||||
sub_track_mbtn_left_command=script-binding select/select-sid; script-message-to modernz osc-hide
|
||||
sub_track_mbtn_mid_command=cycle sub down
|
||||
sub_track_mbtn_right_command=cycle sub
|
||||
sub_track_wheel_down_command=cycle sub
|
||||
sub_track_wheel_up_command=cycle sub down
|
||||
|
||||
# chapter skip buttons mouse actions
|
||||
chapter_prev_mbtn_left_command=add chapter -1
|
||||
chapter_prev_mbtn_mid_command=show-text ${chapter-list} 3000
|
||||
chapter_prev_mbtn_right_command=script-binding select/select-chapter; script-message-to modernz osc-hide
|
||||
|
||||
chapter_next_mbtn_left_command=add chapter 1
|
||||
chapter_next_mbtn_mid_command=show-text ${chapter-list} 3000
|
||||
chapter_next_mbtn_right_command=script-binding select/select-chapter; script-message-to modernz osc-hide
|
||||
|
||||
# chapter title (below seekbar) mouse actions
|
||||
chapter_title_mbtn_left_command=script-binding select/select-chapter; script-message-to modernz osc-hide
|
||||
chapter_title_mbtn_right_command=show-text ${chapter-list} 3000
|
||||
|
||||
# playlist skip buttons mouse actions
|
||||
playlist_prev_mbtn_left_command=playlist-prev
|
||||
playlist_prev_mbtn_mid_command=show-text ${playlist} 3000
|
||||
playlist_prev_mbtn_right_command=script-binding select/select-playlist; script-message-to modernz osc-hide
|
||||
|
||||
playlist_next_mbtn_left_command=playlist-next
|
||||
playlist_next_mbtn_mid_command=show-text ${playlist} 3000
|
||||
playlist_next_mbtn_right_command=script-binding select/select-playlist; script-message-to modernz osc-hide
|
||||
|
||||
# fullscreen button mouse actions
|
||||
fullscreen_mbtn_left_command=cycle fullscreen
|
||||
fullscreen_mbtn_right_command=cycle window-maximized
|
||||
|
||||
# info button mouse actions
|
||||
info_mbtn_left_command=script-binding stats/display-page-1-toggle
|
||||
@@ -1,49 +0,0 @@
|
||||
# Automatically generate the thumbnails on video load, without a keypress
|
||||
autogenerate=no
|
||||
|
||||
# 1 hour, Only automatically thumbnail videos shorter than this (seconds)
|
||||
autogenerate_max_duration=3600
|
||||
|
||||
# SHA1-sum filenames over this length
|
||||
# It's nice to know what files the thumbnails are (hence directory names)
|
||||
# but long URLs may approach filesystem limits.
|
||||
hash_filename_length=128
|
||||
|
||||
# Use mpv to generate thumbnail even if ffmpeg is found in PATH
|
||||
# ffmpeg does not handle ordered chapters (MKVs which rely on other MKVs)!
|
||||
# mpv is a bit slower, but has better support overall (eg. subtitles in the previews)
|
||||
prefer_mpv=yes
|
||||
|
||||
# Disable the built-in keybind ("T") to add your own
|
||||
disable_keybinds=no
|
||||
|
||||
# The thumbnail count target
|
||||
# (This will result in a thumbnail every ~10 seconds for a 25 minute video)
|
||||
thumbnail_count=150
|
||||
|
||||
# The above target count will be adjusted by the minimum and
|
||||
# maximum time difference between thumbnails.
|
||||
# The thumbnail_count will be used to calculate a target separation,
|
||||
# and min/max_delta will be used to constrict it.
|
||||
|
||||
# In other words, thumbnails will be:
|
||||
# at least min_delta seconds apart (limiting the amount)
|
||||
# at most max_delta seconds apart (raising the amount if needed)
|
||||
min_delta=5
|
||||
# 120 seconds aka 2 minutes will add more thumbnails when the video is over 5 hours!
|
||||
max_delta=90
|
||||
|
||||
|
||||
# Overrides for remote urls (you generally want less thumbnails!)
|
||||
# Thumbnailing network paths will be done with mpv
|
||||
|
||||
# Allow thumbnailing network paths (naive check for "://")
|
||||
thumbnail_network=no
|
||||
# Override thumbnail count, min/max delta
|
||||
remote_thumbnail_count=60
|
||||
remote_min_delta=15
|
||||
remote_max_delta=120
|
||||
|
||||
# Try to grab the raw stream and disable ytdl for the mpv subcalls
|
||||
# Much faster than passing the url to ytdl again, but may cause problems with some sites
|
||||
remote_direct_stream=yes
|
||||
@@ -1,22 +0,0 @@
|
||||
# Timestamp
|
||||
# Display total time instead of remaining time
|
||||
timetotal=yes
|
||||
# Display timecodes with milliseconds
|
||||
timems=no
|
||||
|
||||
# Whether to display the chapters/playlist at the OSD when left-clicking the next/previous OSC buttons, respectively.
|
||||
playlist_osd=yes
|
||||
chapters_osd=yes
|
||||
|
||||
# Duration of fade out in ms, 0 = no fade
|
||||
fadeduration=200
|
||||
|
||||
# Minimum amount of pixels the mouse has to move between ticks to make the OSC show up. Default pre-0.21.0 was 3.
|
||||
minmousemove=0
|
||||
|
||||
# auto=hide/show on mouse move
|
||||
# Also supports never and always
|
||||
visibility=auto
|
||||
|
||||
# Use a Unicode minus sign instead of an ASCII hyphen when displaying the remaining playback time.
|
||||
unicodeminus=no
|
||||
@@ -1,169 +0,0 @@
|
||||
#### ------- Mpv-Playlistmanager configuration ------- ####
|
||||
|
||||
#navigation keybindings force override only while playlist is visible
|
||||
#if "no" then you can display the playlist by any of the navigation keys
|
||||
dynamic_binds=yes
|
||||
|
||||
# To bind multiple keys separate them by a space
|
||||
|
||||
# main key to show playlist
|
||||
key_showplaylist=SHIFT+ENTER
|
||||
|
||||
# display playlist while key is held down
|
||||
key_peek_at_playlist=
|
||||
|
||||
# dynamic keys
|
||||
key_moveup=UP
|
||||
key_movedown=DOWN
|
||||
key_movepageup=PGUP
|
||||
key_movepagedown=PGDWN
|
||||
key_movebegin=HOME
|
||||
key_moveend=END
|
||||
key_selectfile=RIGHT LEFT
|
||||
key_unselectfile=
|
||||
key_playfile=ENTER
|
||||
key_removefile=BS
|
||||
key_closeplaylist=ESC SHIFT+ENTER
|
||||
|
||||
# extra functionality keys
|
||||
key_sortplaylist=
|
||||
key_shuffleplaylist=
|
||||
key_reverseplaylist=
|
||||
key_loadfiles=
|
||||
key_saveplaylist=
|
||||
|
||||
#json format for replacing, check .lua for explanation
|
||||
#example json=[{"ext":{"all":true},"rules":[{"_":" "}]},{"ext":{"mp4":true,"mkv":true},"rules":[{"^(.+)%..+$":"%1"},{"%s*[%[%(].-[%]%)]%s*":""},{"(%w)%.(%w)":"%1 %2"}]},{"protocol":{"http":true,"https":true},"rules":[{"^%a+://w*%.?":""}]}]
|
||||
#empty for no replace
|
||||
filename_replace=[{"protocol":{"all":true},"rules":[{"%%(%x%x)":"hex_to_char"}]}]
|
||||
|
||||
#filetypes to search from directory
|
||||
loadfiles_filetypes=["jpg","jpeg","png","tif","tiff","gif","webp","svg","bmp","mp3","wav","ogm","flac","m4a","wma","ogg","opus","mkv","avi","mp4","ogv","webm","rmvb","flv","wmv","mpeg","mpg","m4v","3gp"]
|
||||
|
||||
#loadfiles at startup if 1 or more items in playlist
|
||||
loadfiles_on_start=no
|
||||
#loadfiles from working directory on idle startup
|
||||
loadfiles_on_idle_start=no
|
||||
#always put loaded files after currently playing file
|
||||
loadfiles_always_append=no
|
||||
|
||||
#sort playlist when any files are added to playlist after initial load
|
||||
sortplaylist_on_file_add=no
|
||||
|
||||
#default sorting method, must be one of: "name-asc", "name-desc", "date-asc", "date-desc", "size-asc", "size-desc".
|
||||
default_sort=name-asc
|
||||
|
||||
#linux | windows | auto
|
||||
system=auto
|
||||
|
||||
#Use ~ for home directory. Leave as empty to use mpv/playlists
|
||||
playlist_savepath=
|
||||
|
||||
#constant filename to save playlist as. Note that it will override existing playlist. Leave empty for generated name.
|
||||
playlist_save_filename=
|
||||
|
||||
#save playlist automatically after current file was unloaded
|
||||
save_playlist_on_file_end=no
|
||||
|
||||
#show file title every time a new file is loaded
|
||||
show_title_on_file_load=no
|
||||
#show playlist every time a new file is loaded
|
||||
show_playlist_on_file_load=no
|
||||
#close playlist when selecting file to play
|
||||
close_playlist_on_playfile=no
|
||||
|
||||
#sync cursor when file is loaded from outside reasons(file-ending, playlist-next shortcut etc.)
|
||||
sync_cursor_on_load=yes
|
||||
|
||||
#allow the playlist cursor to loop from end to start and vice versa
|
||||
loop_cursor=yes
|
||||
|
||||
#allow playlistmanager to write watch later config when navigating between files
|
||||
allow_write_watch_later_config=yes
|
||||
|
||||
#reset cursor navigation when closing or opening playlist
|
||||
reset_cursor_on_close=yes
|
||||
reset_cursor_on_open=yes
|
||||
|
||||
#prefer to display titles for following files: "all", "url", "none". Sorting still uses filename
|
||||
prefer_titles=url
|
||||
|
||||
#youtube-dl executable for title resolving if enabled, probably "youtube-dl" or "yt-dlp", can be absolute path
|
||||
youtube_dl_executable=yt-dlp
|
||||
|
||||
#call youtube-dl to resolve the titles of urls in the playlist
|
||||
#if yes, prefer_titles must be set to "url" or "all" for this to work
|
||||
resolve_url_titles=no
|
||||
|
||||
#call ffprobe to resolve the titles of local files in the playlist (if they exist in the metadata)
|
||||
#if yes, prefer_titles must be set to "all" for this to work
|
||||
resolve_local_titles=no
|
||||
|
||||
#timeout in seconds for url title resolving
|
||||
resolve_title_timeout=15
|
||||
|
||||
#how many url titles can be resolved at a time. Higher number might lead to stutters.
|
||||
concurrent_title_resolve_limit=10
|
||||
|
||||
#osd timeout on inactivity in seconds, use 0 for no timeout
|
||||
playlist_display_timeout=0
|
||||
|
||||
#when peeking at playlist, show playlist at the very least for display timeout
|
||||
peek_respect_display_timeout=no
|
||||
|
||||
#the maximum amount of lines playlist will render. -1 will automatically calculate lines.
|
||||
showamount=-1
|
||||
|
||||
#playlist ass style overrides
|
||||
#example {\q2\an7\fnUbuntu\fs10\b0\bord1} equals: line-wrap=no, align=top left, font=Ubuntu, size=10, bold=no, border=1
|
||||
#read http://docs.aegisub.org/3.2/ASS_Tags/ for reference of tags
|
||||
#undeclared tags will use default osd settings
|
||||
#these styles will be used for the whole playlist
|
||||
#\q2 style is recommended since filename wrapping may lead to unexpected rendering
|
||||
#\an7 style is recommended to align to top left, otherwise osd-align-x/y is respected
|
||||
style_ass_tags={\q2\an7}
|
||||
#paddings for left right and top bottom
|
||||
text_padding_x=30
|
||||
text_padding_y=60
|
||||
|
||||
#screen dim when menu is open 0.0 - 1.0 (0 is no dim, 1 is black)
|
||||
curtain_opacity=0.7
|
||||
|
||||
#set title of window with stripped name
|
||||
set_title_stripped=no
|
||||
title_prefix=
|
||||
title_suffix= - mpv
|
||||
|
||||
#slice long filenames, and how many chars to show
|
||||
slice_longfilenames=no
|
||||
slice_longfilenames_amount=70
|
||||
|
||||
#Playing header. One newline will be added after the string.
|
||||
#%mediatitle or %filename = title or name of playing file
|
||||
#%pos = position of playing file
|
||||
#%cursor = position of navigation
|
||||
#%plen = playlist lenght
|
||||
#%N = newline
|
||||
playlist_header=[%cursor/%plen]
|
||||
|
||||
#Playlist file templates
|
||||
#%pos = position of file with leading zeros
|
||||
#%name = title or name of file
|
||||
#%N = newline
|
||||
#you can also use the ass tags mentioned above. For example:
|
||||
# selected_file={\c&HFF00FF&}➔ %name | to add a color for selected file. However, if you
|
||||
# use ass tags you need to reset them for every line (see https://github.com/jonniek/mpv-playlistmanager/issues/20)
|
||||
normal_file={\c&HEEECE8&}○ %name
|
||||
hovered_file={\c&H33FFFF&}● %name
|
||||
selected_file={\c&HFF00FF&}➔ %name
|
||||
playing_file={\c&H91ff4c&}▷ %name
|
||||
playing_hovered_file={\c&H00FF00&}▶ %name
|
||||
playing_selected_file={\c&Hff9ad3&}➤ %name
|
||||
|
||||
#what to show when playlist is truncated
|
||||
playlist_sliced_prefix=...
|
||||
playlist_sliced_suffix=...
|
||||
|
||||
#output visual feedback to OSD when saving, shuffling, reversing playlists
|
||||
display_osd_feedback=yes
|
||||
|
||||
@@ -1,54 +0,0 @@
|
||||
### Config
|
||||
showPictureInPictureButton=yes
|
||||
showSpeedButton=yes
|
||||
# Show name and shortcut of buttons on hover
|
||||
showShortcutTooltip=yes
|
||||
# Show chapter above timestamp in seekbar tooltip
|
||||
showChapterTooltip=yes
|
||||
# skipback/skipfrwd amount in seconds
|
||||
skipBy=5
|
||||
# RightClick skipback/skipfrwd amount in seconds
|
||||
skipByMore=30
|
||||
# "exact" (mordenx default) or "relative+keyframes" (mpv default)
|
||||
skipMode=exact
|
||||
# PictureInPicture 33% screen width, 10px from bottom right
|
||||
pipGeometry=33%+-10+-10
|
||||
# PictureInPicture will show video on all virtual desktops
|
||||
pipAllWorkspaces=yes
|
||||
|
||||
### Sizes
|
||||
# 16:9 video thumbnail = 256x144
|
||||
thumbnailSize=256
|
||||
seekbarHeight=20
|
||||
controlsHeight=64
|
||||
buttonTooltipSize=20
|
||||
windowBarHeight=44
|
||||
windowButtonSize=44
|
||||
windowTitleSize=24
|
||||
cacheTextSize=20
|
||||
timecodeSize=27
|
||||
seekbarTimestampSize=30
|
||||
seekbarTimestampOutline=1
|
||||
chapterTickSize=6
|
||||
windowTitleOutline=1
|
||||
|
||||
### Colors (uses GGBBRR for some reason)
|
||||
### Alpha ranges 0 (opaque) .. 255 (transparent)
|
||||
textColor=FFFFFF
|
||||
buttonColor=CCCCCC
|
||||
buttonHoveredColor=FFFFFF
|
||||
buttonHoveredRectColor=000000
|
||||
# Easily debug button geometry by setting buttonHoveredRectAlpha to 80
|
||||
buttonHoveredRectAlpha=255
|
||||
tooltipColor=CCCCCC
|
||||
windowBarColor=000000
|
||||
# windowBarAlpha (80 is mpv default) (255 morden default)
|
||||
windowBarAlpha=255
|
||||
windowButtonColor=CCCCCC
|
||||
closeButtonHoveredColor=1111DD
|
||||
seekbarHandleColor=FFFFFF
|
||||
seekbarFgColor=483DD7
|
||||
seekbarBgColor=929292
|
||||
seekbarCacheColor=000000
|
||||
seekbarCacheAlpha=128
|
||||
chapterTickColor=CCCCCC
|
||||
17
mpv/script-opts/thumbfast.conf
Normal file
17
mpv/script-opts/thumbfast.conf
Normal file
@@ -0,0 +1,17 @@
|
||||
# This is configuration file for thumbfast.lua
|
||||
# The default options are listed in thumbfast.lua
|
||||
|
||||
# Maximum thumbnail size in pixels (scaled down to fit)
|
||||
# Values are scaled when hidpi is enabled
|
||||
max_height=250
|
||||
max_width=250
|
||||
|
||||
# Spawn thumbnailer on file load for faster initial thumbnails
|
||||
spawn_first=yes
|
||||
|
||||
# Enable on network playback
|
||||
# This allows thumbnailing in videos played over network, e.g. YouTube
|
||||
network=yes
|
||||
|
||||
# Enable hardware decoding
|
||||
hwdec=yes
|
||||
352
mpv/scripts/audio-visualizer.lua
Normal file
352
mpv/scripts/audio-visualizer.lua
Normal file
@@ -0,0 +1,352 @@
|
||||
-- various audio visualization
|
||||
|
||||
local opts = {
|
||||
mode = "novideo",
|
||||
-- off disable visualization
|
||||
-- noalbumart enable visualization when no albumart and no video
|
||||
-- novideo enable visualization when no video
|
||||
-- force always enable visualization
|
||||
|
||||
name = "showcqt",
|
||||
-- off
|
||||
-- showcqt
|
||||
-- avectorscope
|
||||
-- showspectrum
|
||||
-- showcqtbar
|
||||
-- showwaves
|
||||
|
||||
quality = "medium",
|
||||
-- verylow
|
||||
-- low
|
||||
-- medium
|
||||
-- high
|
||||
-- veryhigh
|
||||
|
||||
height = 6,
|
||||
-- [4 .. 12]
|
||||
|
||||
forcewindow = true,
|
||||
-- true (yes) always run visualizer regardless of force-window settings
|
||||
-- false (no) does not run visualizer when force-window is no
|
||||
}
|
||||
|
||||
-- key bindings
|
||||
-- cycle visualizer
|
||||
local cycle_key = "c"
|
||||
|
||||
if not (mp.get_property("options/lavfi-complex", "") == "") then
|
||||
return
|
||||
end
|
||||
|
||||
local visualizer_name_list = {
|
||||
"off",
|
||||
"showcqt",
|
||||
"avectorscope",
|
||||
"showspectrum",
|
||||
"showcqtbar",
|
||||
"showwaves",
|
||||
}
|
||||
|
||||
local axis_0 = "image/png;base64," ..
|
||||
"iVBORw0KGgoAAAANSUhEUgAAB4AAAAAgCAQAAABZEK0tAAAACXBIWXMAAA7EAAAOxAGVKw4bAAASO0lEQVR42u2de2wU1xXGV/IfSJEqVUJCQrIUISFFiiqhSFWkKFKFokpB1TqxHROT8ApueDgEE9u4MW4TSqFA" ..
|
||||
"3TSUQmkSChRwII6BkAQCDSYlBtc1hiSA4/CyMcYGtsZvY3t3vXu719vVPjxzz71zd+wBvnOkdvHZ78w5v7mZmbt7Z9blgsFgMBgMBoPBYDAYDAaDwWAwGAwGg8FgMBgMBoPBYDAYDAaDwWCw+9HYBFbKboe8lE1A" ..
|
||||
"HHHEEUccccQRRxxxxBFHHPEHNe4KBSJWijjiiCOOOOKII4444ogjjjjiD1icwWAwGAwGg8FgMBgM9hAYJsAwGAwGg8FgMBgMBnsozOVyR7zuQOSPdQeif0UcccQRRxxxxBFHHHHEEUcc8QciHn05KaPuwGDHYEfd" ..
|
||||
"gUkZRgkQRxxxxBFHHHHEEUccccQRR/w+jhu9FQ6Hw+FwOBwOh8Ph8AfOx3Zz07LTXpmYzl89McuJOJ6e/czcCWkP7u4Gf/AHf/AHf/AHf/AHf/AHf/B/iPm73D99qaW2u7n7RqI/8lz4LWbxw1tVNjQh7dgH/Z6R" ..
|
||||
"JdjBzmuXKxl7b42sdvqctrORCjqvTc1S3elx9V9vOXNy1+gcP3r+5K6Bu7y8YW/jqZO7PPU5S+Tyx/Fp9lysO/CLV1TqA3/wB3/wB3/wB3/wB3/wB3/wB/8x4e9yL37N+PlYP3o+/BazePVe+c089XL7D4n6qjJZ" ..
|
||||
"dUlhrO7TLWo7wKj+gbvxkGbMv3sl8T3Ht8vlL8hLVPr6dq7Xqw/8wR/8wR/8wR/8wR/8wR/8wR/8k86f/89bK26eYazjSsXGsJ8ui90Bo+MVG7ua1HZAY1VoZj9Utacof8b8DSU15cGAmn5tcfnG/zaE2+tqUtsB" ..
|
||||
"8fXv33T6w8EOxpprYt9xs46xgK9qT0Hes/M2rbr13cgA2SOfP+hnrLacZ68t72sNiYNvrbBWH/iDP/iDP/iDP/iDP/iDP/iDP/jbxD/8f3UVjF2v5q8ef9HlXpQbyjAcuxY7Gp8y8uV1878ZO7lLtsDNv+Ul/e5X" ..
|
||||
"0b9cqlT9JGFypq+XscZTHM3bRaq7IFo/9z+/zZivPxrdsY7Xt35l5N8paV3XGavcLp8/4GMs0t+UrFvf8mESWcKgVh/4gz/4gz/4gz/4gz/4gz/4gz/428Q/vsC1xQFf9b5JGXcvf3/UqIE1bw57az5yuff/uadl" ..
|
||||
"eZ5sefzzh8ZTsX+ZPmfvO5MzVRCWv8tXhz8xi6O5+pXeDqjaw1hvazTaFNqtjV/Hvn/Xho4ruUut7QCXO/vV4DBja95Ur0+Ff+Fy8Ad/8Ad/8Ad/8Ad/8Ad/8Ad/8FfgHy2wt7Wugs+d284aNxCJ36xTbb+7mbGj" ..
|
||||
"76uq4p2vYb9U6XIf3sq/LH/qZfUdwOuvq/juM89F/nnD3ndi6gvt1C+06ovfAaGMN9Q6Bn/wB3/wB3/wB3/wB3/wB3/wB3/b+UcLjFjbOeMGRPFHnpu7yBzKPQ9jkduSH39xweKcJTlLFiz+Sbas3uVe9jrf8soC" ..
|
||||
"rh8eZOzETpXtx9cfvgm7IOb76/6Y+sw8Je3Jl+R3AF/TfrpMXq/LX5yf5k/VR/FX6c8K/4npOUvi61XjT+l1+Yvz0/yp+ij+Kv1Z4f/oC4tyfz7POn9Kr8tfnJ/mT9VH8Vfpz9rxR+0EMPr4Q5+g9I4/Ipc5/oid" ..
|
||||
"Pv7I9wf+9yf/1MxXc/kCQav8Rfpk8DfPL8dfVJ8Mf9n+MP7vv/HPr29/Nts6f0qfjOt/8/xy1/+i+mSu/2X7szb+017JWWK+qJYe/2K9/vgX5ZcZ/+L66PEv35/Djj/RAgfaG6u6Gs0/gTCPry4aaOdtNf/70ReM" ..
|
||||
"NtJ/i7GyUv6qII/ffv1/Cxbly+ld7otH+Kr469Xcvd2M9d+OXSFP60fqv8vVzdWe+oCXsYA3+hV5/23GPvyjGaKfZB/a0nTK211/VH4H3DkfGiQ75PU6/On8Yv4y9Yn4S/dnkX9KWs1HXMEXUZj9epmIv4xehz+d" ..
|
||||
"X8xfpj4Rf+n+LPJPzfz+GOfLWOfVuYvU+cvodfjT+cX8ZeoT8ZfuzyL/sJcU+geHB+ctVucvo9c7/lP5qeM/XZ/4+C/Zn0X+0+cEfGEf9n77qTp/Gb0Ofzq/mL9MfSL+0v1pjP8JabUf8wsvFvzkL1bGP6XXHf/i" ..
|
||||
"/PT4p+qjxr9Ufxb5tzdE9i/3jBxV/jJ6Hf50fjF/mfpE/KX7szz+95R6e3jBd86b/cCLePzTer3xT+Wnxj9dn3j8S/Znmf9rr/e08Pz9HmvnX1qvx5/KT/Gn6xPzl+xP6/pHbQI8+vpHYgLM12i/t4axugMu94aS" ..
|
||||
"tm8W5cY3wON/X8fYuYOJF6D3PN7ek7svf8VYTbnRRtrOMla1m796Zm74t564+e+FPwWg9VOz/AOJj7revEp++4lr0J98qb2BsfYfIv/mzzerrTBDdO4gX/3OmPwEeELaUGeowt/K63X40/nF/Gm9mL9Kf1b4f7mN" ..
|
||||
"sdvnj29vrmbBq1+r85fR6/Cn84v503oxf5X+rPCv2MhYS+2xbRePDA92XlPnL6PX4U/nF/On9WL+Kv1Z4R8m2nmNb9Xst/FE/GX0Ovzp/GL+tF7MX6U/K/yfmcsfqXG58nLlD8e3rlbnL6PX4U/nF/On9WL+Kv1Z" ..
|
||||
"G/+pmfwpop3Xaj769tDqIvXxT+v1xj+Vnxr/lJ4a//L9WeHf3jDQwffu5cq+NsaM17mI+MvodfjT+cX8ab2Yv0p/Vvgvez043Nd6uqzhy4DPU69+/JHR6/Cn84v503oxf5X+rPBPSeu+4R+s3ne6zD8w0G5856yI" ..
|
||||
"v4xehz+dX8yf1ov5q/Rn9fpHbQI8+vpHegLscucuTQnN7fnTvmK/5o7G85alpI2+AA3jaP5PwBt9eHfUa/kK8JsRNFOypmbxXRJ5DDetP7QltLsG+ArysPe2hi45z8hvP3EHuNzb1jLm7Y386/SHoX/1zJgfjU9M" ..
|
||||
"L3931sLI7nq7aGK6ygT4c75O3v/MXHm9Dn86v5g/rRfzV+tPnX/bue7m8OdNjaeGBxO/+aH5y+h1+NP5xfxpvZi/Wn/q/KdmrS0Ovzr/GWPGP4Mu4i+j1+FP5xfzp/Vi/mr9qfPnzu+84ZdXchPgeP4yeh3+dH4x" ..
|
||||
"f1ov5q/Wnzp/PsGjfjJCxF9Gr8Ofzi/mT+vF/NX6szL++c+CfHPI+MgmM/5pvd74p/JT45/SU+NfpT91/sX5kUl1b2t3szp/Gb0Ofzq/mD+tF/NX60+d/4kdjIUnQ98eYsx4kbuIv4xehz+dX8yf1ov5q/Wnzn/m" ..
|
||||
"Lxk7/eFIH+WM7Vinyl9Gr8Ofzi/mT+vF/NX6s3b9ozYBHn39Q0yAfzabPxb79vmi/Ih7vo89QEfjK94YfaftuU+CgfC0k4My+hJ8xnz/YGjG31BakprJPzFYnsefJRbJT+mfnce/+G89G/ls7cmX6vYzFgwW54eH" ..
|
||||
"Ar39+P7eWlGx0VPPF0xE4o/N7LvFv9bfUxr+z6cg785Fxm7GXWKJJnjTsgN+xg5uKsovzt/2+4tHWHD0CnSRXo8/nT+Rf96yWP6UnuKv2p8q/6deDt/dMTG9+8Y9jyz/aHe0Xo8/nV/Mn9JT/FX7szb+p8/ZvGqw" ..
|
||||
"o7NRnT+tT8b4F+WXGf/mernxL9+fOv+nZ/v6Oq9+9Q+zCR7Fn9Lr8qfyU/zFepq/Wn+q/PkEr/1Sc03LmSPvGU8yxPxpvR5/Or+YP6Wn+Kv2p8p/UoZ/sKvx6dkbSqbPkT//RunRej3+dH4xf0pP8Vftz9rxn196" ..
|
||||
"m91XJ3P8F+mTcfwX5Zc5/pvr5Y7/8v2p8t+6mrHPt05Ie2LWnfP3/qvOn9br8afzi/lTeoq/an+q/GctDH8r63Lvfcf4m0oxf1qvx5/OL+ZP6Sn+qv1ZPf6Yu9zxx3QCnLuUPzR6tEVShOLRdeMsGEicmTediszl" ..
|
||||
"d65nrLTEaDOfbuFFcbm3h/9oMbfIwUKsX1v8f2XI+CdtM+aH73fkFl7wTG0/vv6IBXwlhdH3FC739ob/7usN5w8Gd/9BboI4a+Fofo1f/zhddoKqy5+egIr5i/WJ/J+dF+Vf+7Fkf0ngPymj5Qxjxz6Q4990amJ6" ..
|
||||
"4mWKmT45/M3zy/E308vyF/anzX/Lav63oU6jB03I8Bfpk8FflF+Gv7lejj/Rnyb/H44Hg0X5lduNJ3g0f7Fen784P81fpJfhT/anxf+JWSMLxgYHOxJ/rEGOP6XX5U/lp/iL9TR/if60+OcuDV0sXeCXcEG/0ZM9" ..
|
||||
"Kf6UXpc/lZ/iL9bT/CX6S8L51+Wu/djq8UesT8751zy/3PnXTC97/hX2p8mf32Tm7Q0O+/tXvGGFv1ivz1+cn+Yv0svwJ/vT4p+S1tfq69+/6eRufpc9fxKyGn9Kr8ufyk/xF+tp/hL9JeX4Y+ayxx/TCfC07PAt" ..
|
||||
"zGY7ID7e70m8zb/pdOwE9I+/Nt5QacmdC1EQnVc/+lOkRLF+1kK+tG3k8rKLD+/JmXevhHfJ8ODx7TLbT+wvGLznaTr12uuJlxEXDocfZcOt7WxkWSM9wZuW3R3NH/T3tzfsKVWZoOryl5kAi/iL9Yn8J2Uk8lft" ..
|
||||
"zwr/adn8AfDG9wmM5l9WOvo9Ir0+f1F+Gf7mejn+Kv1Z4f/YzENbQtOMQHP16AOLDH+xXp+/KL8Mf3O9HH+V/lT5/6aQBS8cdrnNJngUf1qvx5/KT/EX62n+qv2pj/+y0tKSiekpafVfMBb74C7Z8U/pdce/OD89" ..
|
||||
"/kV6mfGv1p8q/02r+F+aq/f+6e6lYDD26aFy/Gm9Hn8qP8VfrKf5q/Zn7fqHP6rGeIGvzPFfrE/G9Y95frnrHzO97PWPfH+q/FMz275hbLAj4AsGyt9V50/r9fhT+Sn+Yj3NX7U/9fFflD/QMfLX0DVWzT718U/p" ..
|
||||
"dce/OD89/kV6mfGv1p/V44+Zyx5/TCfAuv7NoeBw+AHYfAnygsXm73xs5sqCzauK8uO/xpfX626f8tTMksLNqwryjB6QT00wKdfVJyO/MX/n9GfGf/ZCftdBVZnVvLr6ZOU34++U/kTjn/snf9F7Wp+uXje/aPw7" ..
|
||||
"oT9j/vyjjb62riZ+kmk7a/yMA5Hr6pOX35i/c/qjxn9BHmOf/dV6fl29bn5q/I93f8b8V7zBHzLHX5UUMnZyl2pWXX3y8hvzd05/ovFflK93htHVJyO/aPw7oT9j/l+8z9i2tSlpU7MaqwL+KVmqWXX1yctvzN85" ..
|
||||
"/ZmP/ylZ61fmLj25m2/JSmZdfXLym49/Z/RHnX9tcf0U+zcxtvEt/up6dcCnfgEy3no5fxAmwPdnf+uKfb1BP/9s76mX/75u7PVOr8/u/qK+Yx1j5p/x2q93en329Hf5q86r3PlPvd08o35809U7vT67+5ucGbnX" ..
|
||||
"74M1jO3aMNZ6p9dnd39TsoaHum/wVzlLGPvXP8Za7/T67O4v7GcPitZ32K93en329dfwZdCfOvIAoyN/Y8xskbF9eqfXZ3d/EV/zZsDXdV30qDl79U6vz+7+bPJknAAG2oe6jm///hhjdfvvPz3lxfkXDtcfZay7" ..
|
||||
"pf5obYX02vKk6Z1en739PTuP37PQ1VR/tP6o5yJjks92S5re6fXZ3Z/L3VzdXP351oObqvcNdfv6jX/mwU690+uzu7+wn9jZfinysInx0Du9Pvv662rsaancvn9TzT5vz1D3tOyx1ju9Prv7c7n5mb3hn59u6bjC" ..
|
||||
"TJcY26l3en1298f9nqf7+njqnV6fff2Vv8t/4urEzu8+8/V7e1Izx1rv9Prs7u/xF2srTuy4+q9gYKizcPnY651en9392ezJSLJ+5VAXX4DdenZq1v2oF3vl9uhN1v7+2Id1j43e6fXZ29/shfF3RryQM7Z6p9dn" ..
|
||||
"d38ud/W+yL0Zva3rV4693un12d0f9x+n8x+zZ+yeZ1LGeOidXp+d/ZVv9PaE9293i9kdtnbqnV6f3f3x59u3/Cf84JQv3h8PvdPrs7s/l/uR5/pu6Sxu19U7vT57+6v9OHyG6WuL/tTLWOqdXp+9/WXk8AfMMea5" ..
|
||||
"+ItXxkPv9Prs7s9mT9YpIHepTvvjrYfD4Waempm7tDj/+QVWl7fo6p1en939wcfXH3luweKifLMfmbFf7/T67O6Pe/ary/MefWH89E6vz+7+4OPpU7Pyls38pfXzi67e6fXZ29/kzOV5OrMLXb3T67O7P1sdBxc4" ..
|
||||
"HA6Hw+FwOBwOhz8UDgRwOBwOh8PhcDgcDn8oHAjgcDgcDofD4XA4HP4w+P8AQEuXMXpD8/kAAAAASUVORK5CYII="
|
||||
|
||||
local axis_1 = "image/png;base64," ..
|
||||
"iVBORw0KGgoAAAANSUhEUgAAB4AAAAAwCAQAAABaxq+2AAAACXBIWXMAAA7EAAAOxAGVKw4bAAATVklEQVR42u2df0xUZ7rHJ+EPkiabbGJiYkLSmJg0aTYxTTZNmiYb09ykZjO0QLHY+quy9Qe1YgG5Re62rlev" ..
|
||||
"etluXVevt62rrkq1FLG21epW7FqUZRFtq1LqLxAR1FnkNwIzw8x752V27gzDOe/zvuedA0f5fp9kd+SZ7zPv8zlvz5x35pwzLhcEQRAEQRAEQRAEQRAEQRAEQRAEQRAEQRAEQRAEQRAEQRAEQRAEQRAEQRAEQRAE" ..
|
||||
"QRAEQRAEQRAEQRAEQRAEQRAEQRBkq1gyK2F3Q1HCkpFHHnnkkUceeeSRRx555JFH/lHNu0KJiEqQRx555JFHHnnkkUceeeSRR/4RyzMIgiAIgiAIgiAImgTCAhiCIAiCIAiCIAiaFHK53JGoq4j8sa4i+lfkkUce" ..
|
||||
"eeSRRx555JFHHnnkkX8k8tGHU9PrKgY7BjvqKqamGxVAHnnkkUceeeSRRx555JFHHvmHOG/0VAQCgUAgEAgEAoFAIB65AAIEAoFAIBAIBAKBQEyKAAIEAoFAIBAIBAKBQEyKGN+Xm5mV+tqUNP7oqblOxPHsvOcW" ..
|
||||
"JKc+upsb/MEf/MEf/MEf/MEf/MEf/MF/EvN3uX/5Skttd3P3rfh47IXwU8zyR3eovFBy6omP+j0jN+EKdt64WsnYB+tlvbPmt52PjKDzxoxM1Y0+avw3W86d3ju2xs9ePL134D4f3rC38czpvZ767OVy9UfxafZc" ..
|
||||
"rqv49Wsq4wN/8Ad/8Ad/8Ad/8Ad/8Ad/8Af/ceHvci97w/gXkn72YvgpZvnqA/Iv88yr7T/F+6tKZd3FBbG+z7erbQCj8Q/cHw1p9qL71+Kfc3KXXP383Hinr2/PJr3xgT/4gz/4gz/4gz/4gz/4gz/4g3/C+fP/" ..
|
||||
"eWf17XOMdVwr3xKOs6WxG2BsvnxLV5PaBmisCq3sh6r2F+bNXrS5uKYsGFDzbygq2/LPhnB7XU1qG2D0+A9tPfvxYAdjzTWxz7hdx1jAV7U/P/f5hVvX3vlhZILsl68f9DNWW8ar15b1tYbMwXdWWxsf+IM/+IM/" ..
|
||||
"+IM/+IM/+IM/+IM/+NvEP/x/deWM3azmj5582eVemhOqMBx7LnY0P33ky+vmvzN2eq/sALf9jg/pP/89+pcrlaqfJEzL8PUy1niGo3m3UHUTRMfP44/vMubrj2Z3b+Tj27Qm8u+k1K6bjFXukq8f8DEW6W965p3v" ..
|
||||
"+TSJnMKgNj7wB3/wB3/wB3/wB3/wB3/wB3/wt4n/6AFuKAr4qg9OTb9/9cfjRg2sf3vYW/OJy33ojz0tq3Jlh8c/f2g8E/uXWfMPvDctQwVh2fv87PCn5nI017/R2wBV+xnrbY1mm0KbtfHb2Ofv3dxxLWeFtQ3g" ..
|
||||
"cme9HhxmbP3b6uNT4V+wCvzBH/zBH/zBH/zBH/zBH/zBH/wV+EcH2NtaV87Xzm3njRuI5G/Xqbbf3czY8Q9VXaODn8N+pdLlPrqDf1n+zKvqG4CPv678hy88l/nnDQfeixlfaKN+pTW+0RsgVPGWWsfgD/7gD/7g" ..
|
||||
"D/7gD/7gD/7gD/7gbzv/6AAjartg3IAo/9gLC5aaQ3ngYSxyWfKTLy9elr08e/niZb/IkvW73Cvf5K+8Jp/7hwcZO7VH5fVHjz98EXZ+zPfX/THjM4uk1Kdfkd8A/Jz2s6Xyfl3+4vo0f2p8FH+V/qzwn5KWvXz0" ..
|
||||
"eNX4U35d/uL6NH9qfBR/lf6s8H/8paU5/7bQOn/Kr8tfXJ/mT42P4q/Sn7X9j9obwNj9D/0Gpbf/EYXM/kcc9P5Hvj/wfzj5p2S8nsNPELTKX+RPBH/z+nL8ReOT4S/bH+b/wzf/+fHtr+ZZ50/5E3H8b15f7vhf" ..
|
||||
"ND6Z43/Z/qzN/9TXspebn1RLz3+xX3/+i+rLzH/x+Oj5L9+fw/Y/0QEOtDdWdTWafwJhnl9XONDO22r+++MvGb1I/x3GSkv4o/xcfvn1vxQszJPzu9yXj/Gz4m9W8/B2M9Z/N/YMedo/Mv773N1c7akPeBkLeKNf" ..
|
||||
"kfffZezj35sh+kXWke1NZ7zd9cflN8C9i6FJslver8Ofri/mLzM+EX/p/izyT0qt+YQ7+EkUZr9eJuIv49fhT9cX85cZn4i/dH8W+adk/HiC82Ws8/qCper8Zfw6/On6Yv4y4xPxl+7PIv9wFBf4B4cHFy5T5y/j" ..
|
||||
"19v/U/Wp/T89PvH+X7I/i/xnzQ/4wjHs/f5zdf4yfh3+dH0xf5nxifhL96cx/5NTaz/lB14s+NmfrMx/yq87/8X16flPjY+a/1L9WeTf3hDZvjzSs1X5y/h1+NP1xfxlxifiL92f5fm/v8Tbwwd876LZD7yI5z/t" ..
|
||||
"15v/VH1q/tPjE89/yf4s83/jzZ4WXr/fY+39l/br8afqU/zp8Yn5S/andfyjtgAee/wjsQDm52h/sJ6xugqXe3Nx23dLc0Y3wPN/3sjYhcPxB6APPN7e0/uufsNYTZnRi7SdZ6xqH3/03ILwbz1x+R+EPwWg/TMy" ..
|
||||
"/QPxt7retlb+9ePPQX/6lfYGxtp/ivyb39+sttwM0YXD/Ox3xuQXwMmpQ52hEf5O3q/Dn64v5k/7xfxV+rPC/+udjN29eHJXczULXv9Wnb+MX4c/XV/Mn/aL+av0Z4V/+RbGWmpP7Lx8bHiw84Y6fxm/Dn+6vpg/" ..
|
||||
"7RfzV+nPCv8w0c4b/FXNfhtPxF/Gr8Ofri/mT/vF/FX6s8L/uQX8lhpXK69W/nRyxzp1/jJ+Hf50fTF/2i/mr9KftfmfksHvItp5o+aT74+sK1Sf/7Rfb/5T9an5T/mp+S/fnxX+7Q0DHXzrXq3sa2PM+DwXEX8Z" ..
|
||||
"vw5/ur6YP+0X81fpzwr/lW8Gh/taz5Y2fB3weerV9z8yfh3+dH0xf9ov5q/SnxX+Sandt/yD1QfPlvoHBtqNr5wV8Zfx6/Cn64v5034xf5X+rB7/qC2Axx7/SC+AXe6cFUmhtT2/21fs19zRfO7KpNSxB6BhHM3/" ..
|
||||
"CHijN++ORi0/A/x2BM30zBmZfJNEbsNN+49sD22uAX4GeTh6W0OHnOfkXz9+A7jcOzcw5u2N/Ovsx6F/9cxeFM1PSSt7f+6SyOZ6t3BKmsoC+Et+nrz/uQXyfh3+dH0xf9ov5q/Wnzr/tgvdzeHPmxrPDA/Gf/ND" ..
|
||||
"85fx6/Cn64v5034xf7X+1PnPyNxQFH508QvGjH8GXcRfxq/Dn64v5k/7xfzV+lPnz4NfecMPr+QWwKP5y/h1+NP1xfxpv5i/Wn/q/PkCj/rJCBF/Gb8Of7q+mD/tF/NX68/K/Oc/C/LdEeM9m8z8p/1685+qT81/" ..
|
||||
"yk/Nf5X+1PkX5UUW1b2t3c3q/GX8Ovzp+mL+tF/MX60/df6ndjMWXgx9f4Qx45PcRfxl/Dr86fpi/rRfzF+tP3X+c37D2NmPR/ooY2z3RlX+Mn4d/nR9MX/aL+av1p+14x+1BfDY4x9iAfyrefy22HcvFuZFwvNj" ..
|
||||
"7A46ml/91tgrbS98FgyEl50clNGX4LMX+QdDK/6GkuKUDP6Jwapcfi+xSH3K//xC/sV/6/nIZ2tPv1J3iLFgsCgvPBXo1x/d3zury7d46vkJE5H8E3P67vCv9feXhP/zyc+9d5mx26MOsUQLvJlZAT9jh7cW5hXl" ..
|
||||
"7fyvy8dYcOwZ6CK/Hn+6fjz/3JWx/Ck/xV+1P1X+z7wavrpjSlr3rQceWf7R7mi/Hn+6vpg/5af4q/Znbf7Pmr9t7WBHZ6M6f9qfiPkvqi8z/839cvNfvj91/s/O8/V1Xv/mL2YLPIo/5dflT9Wn+Iv9NH+1/lT5" ..
|
||||
"8wVe+5XmmpZzxz4wXmSI+dN+Pf50fTF/yk/xV+1Plf/UdP9gV+Oz8zYXz5ov//4bpUf79fjT9cX8KT/FX7U/a/t/fuhtdl2dzP5f5E/E/l9UX2b/b+6X2//L96fKf8c6xr7ckZz61Nx7Fx/8U50/7dfjT9cX86f8" ..
|
||||
"FH/V/lT5z10S/lbW5T7wnvE3lWL+tF+PP11fzJ/yU/xV+7O6/zEPuf2P6QI4ZwW/afRYRUqE8tHzxlkwEL8ybzoTWcvv2cRYSbHRy3y+nQ+K2709/EeLuSI7C7F/Q9G/nCHxT9pmLwpf78gVPuGZev3R448o4Csu" ..
|
||||
"iD6nYJW3N/x3X2+4fjC477/lFohzl4zl1/jtz9NkF6i6/OkFqJi/2B/P//mFUf61n0r2lwD+U9NbzjF24iM5/k1npqTFH6aY+RPD37y+HH8zvyx/YX/a/Lev438b6jS60YQMf5E/EfxF9WX4m/vl+BP9afL/6WQw" ..
|
||||
"WJhXuct4gUfzF/v1+Yvr0/xFfhn+ZH9a/J+aO3LC2OBgR/yPNcjxp/y6/Kn6FH+xn+Yv0Z8W/5wVoYOlS/wQLug3urMnxZ/y6/Kn6lP8xX6av0R/CXj/dblrP7W6/xH7E/P+a15f7v3XzC/7/ivsT5M/v8jM2xsc" ..
|
||||
"9vevfssKf7Ffn7+4Ps1f5JfhT/anxT8pta/V139o6+l9/Cp7fidkNf6UX5c/VZ/iL/bT/CX6S8j+xyxk9z+mC+CZWeFLmM02wOh8vyf+Mv+ms7EL0N//h/ELlRTfuxQF0Xn9kz9Ehij2z13CT20bObzs4tN7Wsb9" ..
|
||||
"a+FNMjx4cpfM68f3Fww+8DSdeePN+MOIS0fDt7LhajsfOa2RXuDNzOqO1g/6+9sb9peoLFB1+cssgEX8xf54/lPT4/mr9meF/8wsfgN44+sExvIvLRn7HJFfn7+ovgx/c78cf5X+rPB/Ys6R7aFlRqC5euyORYa/" ..
|
||||
"2K/PX1Rfhr+5X46/Sn+q/H9bwIKXjrrcZgs8ij/t1+NP1af4i/00f9X+1Od/aUlJ8ZS0pNT6rxiLvXGX7Pyn/LrzX1yfnv8iv8z8V+tPlf/WtfwvzdUH/nD/SjAYe/dQOf60X48/VZ/iL/bT/FX7s3b8w29VY3yC" ..
|
||||
"r8z+X+xPxPGPeX254x8zv+zxj3x/qvxTMtq+Y2ywI+ALBsreV+dP+/X4U/Up/mI/zV+1P/X5X5g30DHy19AxVs1B9flP+XXnv7g+Pf9Ffpn5r9af1f2PWcjuf0wXwLrx3ZHgcPgG2PwU5MXLzJ/5xJw1+dvWFuaN" ..
|
||||
"/hpf3q/7+lSkZBQXbFubn2t0g3xqgUmFrj8R9Y35O6c/M/7zlvCrDqpKrdbV9Seqvhl/p/Qnmv88PvuT3t36dP269UXz3wn9GfPnH230tXU18TeZtvPG9zgQha4/cfWN+TunP2r+5+cy9sX/WK+v69etT83/ie7P" ..
|
||||
"mP/qt/hN5vij4gLGTu9VrarrT1x9Y/7O6U80/wvz9N5hdP2JqC+a/07oz5j/Vx8ytnNDUuqMzMaqgH96pmpVXX/i6hvzd05/5vN/euamNTkrTu/jr2Slsq4/MfXN578z+qPef20J/RKHtjK25R3+6GZ1wKd+ADLR" ..
|
||||
"frl4FBbAD2d/G4t8vUE//2zvmVf/vHH8/U4fn939RWP3RsbMP+O13+/08dnT39VvOq/z4D/1dvuc+v5N1+/08dnd37SMyLV+H61nbO/m8fY7fXx29zc9c3io+xZ/lL2csb/9Zbz9Th+f3f2F4/xh0fkd9vudPj77" ..
|
||||
"+mv4OuhPGbmB0bH/ZczsJGP7/E4fn939RWL92wFf103Rrebs9Tt9fHb3Z1Mk4g1goH2o6+SuH08wVnfo4fNTUZR36Wj9cca6W+qP15ZLn1ueML/Tx2dvf88v5NcsdDXVH68/7rnMmOS93RLmd/r47O7P5W6ubq7+" ..
|
||||
"csfhrdUHh7p9/cY/82Cn3+njs7u/cJza034lcrOJifA7fXz29dfV2NNSuevQ1pqD3p6h7plZ4+13+vjs7s/l5u/sDX/9fHvHNWZ6irGdfqePz+7+eDzwdN+cSL/Tx2dff2Xv85+4OrXnhy98/d6elIzx9jt9fHb3" ..
|
||||
"9+TLteWndl//WzAw1Fmwavz9Th+f3f3ZHIkosmnNUBc/Abv1/IzMh9Evjspd0Yus/f2xN+seH7/Tx2dvf/OWjL4y4qXs8fU7fXx29+dyVx+MXJvR27ppzfj7nT4+u/vj8fM0/mP2jD3wTE2fCL/Tx2dnf2VbvD3h" ..
|
||||
"7dvdYnaFrZ1+p4/P7v74/e1b/hG+ccpXH06E3+njs7s/l/uxF/ru6Jzcrut3+vjs7a/20/A7TF9b9KdextPv9PHZ2196Nr/BHGOey79+bSL8Th+f3f3ZHIl6C8hZodP+RPsRCIRZpGTkrCjKe3Gx1dNbdP1OH5/d" ..
|
||||
"/SEmNh57YfGywjyzH5mx3+/08dndH4+s11flPv7SxPmdPj67+0NMZMzIzF055zfW3190/U4fn739TctYlauzutD1O318dvdna2DngkAgEAgEAoFAIBCISRFAgEAgEAgEAoFAIBCISRHRh1PT6yqGOoc66yqMr6NC" ..
|
||||
"HnnkkUceeeSRRx555JFHHvmHOB99WFcRuZGO8b00kUceeeSRRx555JFHHnnkkUf+Ic4zCIIgCIIgCIIgCJoEwgIYgiAIgiAIgiAImhRyRcVK/v+vJS4DIY888sgjjzzyyCOPPPLII4/8o5B3seTQU+6EooQlI488" ..
|
||||
"8sgjjzzyyCOPPPLII4/8o5qHIAiCIAiCIAiCIAiCIAiCIAiCIAiCIAiCIAiCIAiCIAiCIAiCIAiCIAiCIAiCIAiCIAiCIAiCIAiCIAiCIAiCIAiCEqf/A/SNfayCCBqGAAAAAElFTkSuQmCC"
|
||||
|
||||
local options = require 'mp.options'
|
||||
local msg = require 'mp.msg'
|
||||
|
||||
options.read_options(opts)
|
||||
opts.height = math.min(12, math.max(4, opts.height))
|
||||
opts.height = math.floor(opts.height)
|
||||
|
||||
if not opts.forcewindow and mp.get_property('force-window') == "no" then
|
||||
return
|
||||
end
|
||||
|
||||
local function get_visualizer(name, quality, vtrack)
|
||||
local w, h, fps
|
||||
|
||||
if quality == "verylow" then
|
||||
w = 640
|
||||
fps = 30
|
||||
elseif quality == "low" then
|
||||
w = 960
|
||||
fps = 30
|
||||
elseif quality == "medium" then
|
||||
w = 1280
|
||||
fps = 60
|
||||
elseif quality == "high" then
|
||||
w = 1920
|
||||
fps = 60
|
||||
elseif quality == "veryhigh" then
|
||||
w = 2560
|
||||
fps = 60
|
||||
else
|
||||
msg.log("error", "invalid quality")
|
||||
return ""
|
||||
end
|
||||
|
||||
h = w * opts.height / 16
|
||||
|
||||
if name == "showcqt" then
|
||||
local count = math.ceil(w * 180 / 1920 / fps)
|
||||
|
||||
return "[aid1] asplit [ao]," ..
|
||||
"aformat = channel_layouts = stereo," ..
|
||||
"firequalizer =" ..
|
||||
"gain = '1.4884e8 * f*f*f / (f*f + 424.36) / (f*f + 1.4884e8) / sqrt(f*f + 25122.25)':" ..
|
||||
"scale = linlin:" ..
|
||||
"wfunc = tukey:" ..
|
||||
"zero_phase = on:" ..
|
||||
"fft2 = on," ..
|
||||
"showcqt =" ..
|
||||
"fps =" .. fps .. ":" ..
|
||||
"size =" .. w .. "x" .. h .. ":" ..
|
||||
"count =" .. count .. ":" ..
|
||||
"csp = bt709:" ..
|
||||
"bar_g = 2:" ..
|
||||
"sono_g = 4:" ..
|
||||
"bar_v = 9:" ..
|
||||
"sono_v = 17:" ..
|
||||
"axisfile = data\\\\:'" .. axis_0 .. "':" ..
|
||||
"font = 'Nimbus Mono L,Courier New,mono|bold':" ..
|
||||
"fontcolor = 'st(0, (midi(f)-53.5)/12); st(1, 0.5 - 0.5 * cos(PI*ld(0))); r(1-ld(1)) + b(ld(1))':" ..
|
||||
"tc = 0.33:" ..
|
||||
"attack = 0.033:" ..
|
||||
"tlength = 'st(0,0.17); 384*tc / (384 / ld(0) + tc*f /(1-ld(0))) + 384*tc / (tc*f / ld(0) + 384 /(1-ld(0)))'," ..
|
||||
"format = yuv420p [vo]"
|
||||
|
||||
|
||||
elseif name == "avectorscope" then
|
||||
return "[aid1] asplit [ao]," ..
|
||||
"aformat =" ..
|
||||
"sample_rates = 192000," ..
|
||||
"avectorscope =" ..
|
||||
"size =" .. w .. "x" .. h .. ":" ..
|
||||
"r =" .. fps .. "," ..
|
||||
"format = rgb0 [vo]"
|
||||
|
||||
|
||||
elseif name == "showspectrum" then
|
||||
return "[aid1] asplit [ao]," ..
|
||||
"showspectrum =" ..
|
||||
"size =" .. w .. "x" .. h .. ":" ..
|
||||
"win_func = blackman [vo]"
|
||||
|
||||
|
||||
elseif name == "showcqtbar" then
|
||||
local axis_h = math.ceil(w * 12 / 1920) * 4
|
||||
|
||||
return "[aid1] asplit [ao]," ..
|
||||
"aformat = channel_layouts = stereo," ..
|
||||
"firequalizer =" ..
|
||||
"gain = '1.4884e8 * f*f*f / (f*f + 424.36) / (f*f + 1.4884e8) / sqrt(f*f + 25122.25)':" ..
|
||||
"scale = linlin:" ..
|
||||
"wfunc = tukey:" ..
|
||||
"zero_phase = on:" ..
|
||||
"fft2 = on," ..
|
||||
"showcqt =" ..
|
||||
"fps =" .. fps .. ":" ..
|
||||
"size =" .. w .. "x" .. (h + axis_h)/2 .. ":" ..
|
||||
"count = 1:" ..
|
||||
"csp = bt709:" ..
|
||||
"bar_g = 2:" ..
|
||||
"sono_g = 4:" ..
|
||||
"bar_v = 9:" ..
|
||||
"sono_v = 17:" ..
|
||||
"sono_h = 0:" ..
|
||||
"axisfile = data\\\\:'" .. axis_1 .. "':" ..
|
||||
"axis_h =" .. axis_h .. ":" ..
|
||||
"font = 'Nimbus Mono L,Courier New,mono|bold':" ..
|
||||
"fontcolor = 'st(0, (midi(f)-53.5)/12); st(1, 0.5 - 0.5 * cos(PI*ld(0))); r(1-ld(1)) + b(ld(1))':" ..
|
||||
"tc = 0.33:" ..
|
||||
"attack = 0.033:" ..
|
||||
"tlength = 'st(0,0.17); 384*tc / (384 / ld(0) + tc*f /(1-ld(0))) + 384*tc / (tc*f / ld(0) + 384 /(1-ld(0)))'," ..
|
||||
"format = yuv420p," ..
|
||||
"split [v0]," ..
|
||||
"crop =" ..
|
||||
"h =" .. (h - axis_h)/2 .. ":" ..
|
||||
"y = 0," ..
|
||||
"vflip [v1];" ..
|
||||
"[v0][v1] vstack [vo]"
|
||||
|
||||
|
||||
elseif name == "showwaves" then
|
||||
return "[aid1] asplit [ao]," ..
|
||||
"showwaves =" ..
|
||||
"size =" .. w .. "x" .. h .. ":" ..
|
||||
"r =" .. fps .. ":" ..
|
||||
"mode = p2p," ..
|
||||
"format = rgb0 [vo]"
|
||||
elseif name == "off" then
|
||||
local hasvideo = false
|
||||
for id, track in ipairs(mp.get_property_native("track-list")) do
|
||||
if track.type == "video" then
|
||||
hasvideo = true
|
||||
break
|
||||
end
|
||||
end
|
||||
if hasvideo then
|
||||
return "[aid1] asetpts=PTS [ao]; [vid1] setpts=PTS [vo]"
|
||||
else
|
||||
return "[aid1] asetpts=PTS [ao];" ..
|
||||
"color =" ..
|
||||
"c = Black:" ..
|
||||
"s =" .. w .. "x" .. h .. "," ..
|
||||
"format = yuv420p [vo]"
|
||||
end
|
||||
end
|
||||
|
||||
msg.log("error", "invalid visualizer name")
|
||||
return ""
|
||||
end
|
||||
|
||||
local function select_visualizer(vtrack)
|
||||
if opts.mode == "off" then
|
||||
return ""
|
||||
elseif opts.mode == "force" then
|
||||
return get_visualizer(opts.name, opts.quality, vtrack)
|
||||
elseif opts.mode == "noalbumart" then
|
||||
if vtrack == nil then
|
||||
return get_visualizer(opts.name, opts.quality, vtrack)
|
||||
end
|
||||
return ""
|
||||
elseif opts.mode == "novideo" then
|
||||
if vtrack == nil or vtrack.albumart then
|
||||
return get_visualizer(opts.name, opts.quality, vtrack)
|
||||
end
|
||||
return ""
|
||||
end
|
||||
|
||||
msg.log("error", "invalid mode")
|
||||
return ""
|
||||
end
|
||||
|
||||
local function visualizer_hook()
|
||||
local count = mp.get_property_number("track-list/count", -1)
|
||||
if count <= 0 then
|
||||
return
|
||||
end
|
||||
|
||||
local atrack = mp.get_property_native("current-tracks/audio")
|
||||
local vtrack = mp.get_property_native("current-tracks/video")
|
||||
|
||||
--no tracks selected (yet)
|
||||
if atrack == nil and vtrack == nil then
|
||||
for id, track in ipairs(mp.get_property_native("track-list")) do
|
||||
if track.type == "video" and (vtrack == nil or vtrack.albumart == true) and mp.get_property("vid") ~= "no" then
|
||||
vtrack = track
|
||||
elseif track.type == "audio" then
|
||||
atrack = track
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local lavfi = select_visualizer(vtrack)
|
||||
--prevent endless loop
|
||||
if lavfi ~= mp.get_property("options/lavfi-complex", "") then
|
||||
mp.set_property("options/lavfi-complex", lavfi)
|
||||
end
|
||||
end
|
||||
|
||||
mp.add_hook("on_preloaded", 50, visualizer_hook)
|
||||
mp.observe_property("current-tracks/audio", "native", visualizer_hook)
|
||||
mp.observe_property("current-tracks/video", "native", visualizer_hook)
|
||||
|
||||
local function cycle_visualizer()
|
||||
local i, index = 1
|
||||
for i = 1, #visualizer_name_list do
|
||||
if (visualizer_name_list[i] == opts.name) then
|
||||
index = i + 1
|
||||
if index > #visualizer_name_list then
|
||||
index = 1
|
||||
end
|
||||
break
|
||||
end
|
||||
end
|
||||
opts.name = visualizer_name_list[index]
|
||||
visualizer_hook()
|
||||
end
|
||||
|
||||
mp.add_key_binding(cycle_key, "cycle-visualizer", cycle_visualizer)
|
||||
@@ -1,186 +0,0 @@
|
||||
local utils = require 'mp.utils'
|
||||
|
||||
-- 参数设置
|
||||
local audioTracksPerPage = 10
|
||||
local closeAfterLoad = true
|
||||
local rate = 1.5
|
||||
|
||||
-- 全局变量和实用函数
|
||||
local styleOn = mp.get_property("osd-ass-cc/0")
|
||||
local audioTracks = {}
|
||||
local currentSlot = 1
|
||||
local currentPage = 1
|
||||
local maxPage = 1
|
||||
local active = false
|
||||
|
||||
-- 控制列表
|
||||
local audioTrackControls = {
|
||||
ESC = function() abort("") end,
|
||||
e = function() abort("") end,
|
||||
DOWN = function() jumpSlot(1) end,
|
||||
UP = function() jumpSlot(-1) end,
|
||||
j = function() jumpSlot(1) end,
|
||||
k = function() jumpSlot(-1) end,
|
||||
RIGHT = function() jumpPage(1) end,
|
||||
LEFT = function() jumpPage(-1) end,
|
||||
ENTER = function() loadAudioTrack(currentSlot) end,
|
||||
KP_ENTER = function() loadAudioTrack(currentSlot) end
|
||||
}
|
||||
|
||||
local audioTrackFlags = {
|
||||
DOWN = {repeatable = true},
|
||||
UP = {repeatable = true},
|
||||
RIGHT = {repeatable = true},
|
||||
LEFT = {repeatable = true}
|
||||
}
|
||||
|
||||
-- 激活自定义控件
|
||||
function activateControls(name, controls, flags)
|
||||
for key, func in pairs(controls) do
|
||||
mp.add_forced_key_binding(key, name..key, func, flags[key])
|
||||
end
|
||||
end
|
||||
|
||||
-- 取消激活自定义控件
|
||||
function deactivateControls(name, controls)
|
||||
for key, _ in pairs(controls) do
|
||||
mp.remove_key_binding(name..key)
|
||||
end
|
||||
end
|
||||
|
||||
-- 加载音轨列表
|
||||
function listAudioTracks()
|
||||
audioTracks = {}
|
||||
local tracks = mp.get_property_native("track-list")
|
||||
for _, track in ipairs(tracks) do
|
||||
if track.type == "audio" then
|
||||
table.insert(audioTracks, track)
|
||||
end
|
||||
end
|
||||
calcPages()
|
||||
end
|
||||
|
||||
-- 计算当前页和总页数
|
||||
function calcPages()
|
||||
currentPage = math.floor((currentSlot - 1) / audioTracksPerPage) + 1
|
||||
if currentPage == 0 then currentPage = 1 end
|
||||
maxPage = math.floor((#audioTracks - 1) / audioTracksPerPage) + 1
|
||||
if maxPage == 0 then maxPage = 1 end
|
||||
end
|
||||
|
||||
-- 获取指定页的音轨数量
|
||||
function getAmountAudioTracksOnPage(page)
|
||||
local n = audioTracksPerPage
|
||||
if page == maxPage then n = #audioTracks % audioTracksPerPage end
|
||||
if n == 0 then n = audioTracksPerPage end
|
||||
if #audioTracks == 0 then n = 0 end
|
||||
return n
|
||||
end
|
||||
|
||||
-- 获取指定页的第一个音轨索引
|
||||
function getFirstSlotOnPage(page)
|
||||
return (page - 1) * audioTracksPerPage + 1
|
||||
end
|
||||
|
||||
-- 获取指定页的最后一个音轨索引
|
||||
function getLastSlotOnPage(page)
|
||||
local endSlot = getFirstSlotOnPage(page) + getAmountAudioTracksOnPage(page) - 1
|
||||
if endSlot > #audioTracks then endSlot = #audioTracks end
|
||||
return endSlot
|
||||
end
|
||||
|
||||
-- 跳到指定数量的音轨前或后
|
||||
function jumpSlot(i)
|
||||
currentSlot = currentSlot + i
|
||||
local startSlot = getFirstSlotOnPage(currentPage)
|
||||
local endSlot = getLastSlotOnPage(currentPage)
|
||||
|
||||
if currentSlot < startSlot then currentSlot = endSlot end
|
||||
if currentSlot > endSlot then currentSlot = startSlot end
|
||||
|
||||
displayAudioTracks()
|
||||
end
|
||||
|
||||
-- 跳到指定数量的页前或后
|
||||
function jumpPage(i)
|
||||
local oldPos = currentSlot - getFirstSlotOnPage(currentPage) + 1
|
||||
currentPage = currentPage + i
|
||||
if currentPage < 1 then currentPage = maxPage + currentPage end
|
||||
if currentPage > maxPage then currentPage = currentPage - maxPage end
|
||||
|
||||
local audioTracksOnPage = getAmountAudioTracksOnPage(currentPage)
|
||||
if oldPos > audioTracksOnPage then oldPos = audioTracksOnPage end
|
||||
currentSlot = getFirstSlotOnPage(currentPage) + oldPos - 1
|
||||
|
||||
displayAudioTracks()
|
||||
end
|
||||
|
||||
-- 显示当前页的音轨
|
||||
function displayAudioTracks()
|
||||
-- 确定当前页的第一个和最后一个音轨索引
|
||||
local startSlot = getFirstSlotOnPage(currentPage)
|
||||
local endSlot = getLastSlotOnPage(currentPage)
|
||||
|
||||
-- 准备显示的文本并显示
|
||||
local display = styleOn .. "{\\b1}Audio Tracks page " .. currentPage .. "/" .. maxPage .. ":{\\b0}"
|
||||
for i = startSlot, endSlot do
|
||||
local track = audioTracks[i]
|
||||
if (track.title or track.lang or track.src) == nil then
|
||||
goto nextSlot
|
||||
end
|
||||
local selection = ""
|
||||
if i == currentSlot then
|
||||
selection = "{\\b1}{\\c&H00FFFF&}>"
|
||||
end
|
||||
display = display .. "\n" .. selection .. i .. ": " .. (track.title or track.lang or track.src) .. "{\\r}"
|
||||
::nextSlot::
|
||||
end
|
||||
mp.osd_message(display, rate)
|
||||
end
|
||||
|
||||
-- 加载指定的音轨
|
||||
function loadAudioTrack(slot)
|
||||
if slot >= 1 and slot <= #audioTracks then
|
||||
local track = audioTracks[slot]
|
||||
if (track.title or track.lang or track.src) == nil then
|
||||
abort(styleOn.."{\\c&H0000FF&}{\\b1}Can't find the audio track at slot " .. slot)
|
||||
return
|
||||
end
|
||||
mp.set_property_native("aid", track.id)
|
||||
mp.osd_message(string.format("Loaded audio track: %s", track.title or track.lang or track.src), 2)
|
||||
if closeAfterLoad then
|
||||
abort(styleOn.."{\\c&H00FF00&}{\\b1}Successfully loaded audio track:{\\r}\n"..(track.title or track.lang or track.src))
|
||||
end
|
||||
else
|
||||
abort(styleOn.."{\\c&H0000FF&}{\\b1}Can't find the audio track at slot " .. slot)
|
||||
end
|
||||
end
|
||||
|
||||
-- 定时器
|
||||
local timer = mp.add_periodic_timer(rate * 0.95, displayAudioTracks)
|
||||
timer:kill()
|
||||
|
||||
-- 终止程序
|
||||
function abort(message)
|
||||
mode = "none"
|
||||
deactivateControls("audio", audioTrackControls)
|
||||
timer:kill()
|
||||
mp.osd_message(message)
|
||||
active = false
|
||||
end
|
||||
|
||||
-- 处理音轨菜单的状态
|
||||
function handler()
|
||||
if active then
|
||||
abort("")
|
||||
else
|
||||
activateControls("audio", audioTrackControls, audioTrackFlags)
|
||||
listAudioTracks()
|
||||
displayAudioTracks()
|
||||
timer:resume()
|
||||
active = true
|
||||
end
|
||||
end
|
||||
|
||||
-- 注册脚本消息
|
||||
mp.register_script_message("audio-menu", handler)
|
||||
@@ -1,5 +1,5 @@
|
||||
-- This script automatically loads playlist entries before and after the
|
||||
-- currently played file. It does so by scanning the directory a file is
|
||||
-- the currently played file. It does so by scanning the directory a file is
|
||||
-- located in when starting playback. It sorts the directory entries
|
||||
-- alphabetically, and adds entries before and after the current file to
|
||||
-- the internal playlist. (It stops if it would add an already existing
|
||||
@@ -10,201 +10,94 @@
|
||||
To configure this script use file autoload.conf in directory script-opts (the "script-opts"
|
||||
directory must be in the mpv configuration directory, typically ~/.config/mpv/).
|
||||
|
||||
Option `ignore_patterns` is a comma-separated list of patterns (see lua.org/pil/20.2.html).
|
||||
Additionally to the standard lua patterns, you can also escape commas with `%`,
|
||||
for example, the option `bak%,x%,,another` will be resolved as patterns `bak,x,` and `another`.
|
||||
But it does not mean you need to escape all lua patterns twice,
|
||||
so the option `bak%%,%.mp4,` will be resolved as two patterns `bak%%` and `%.mp4`.
|
||||
|
||||
Example configuration would be:
|
||||
|
||||
disabled=no
|
||||
images=no
|
||||
videos=yes
|
||||
audio=yes
|
||||
additional_image_exts=list,of,ext
|
||||
additional_video_exts=list,of,ext
|
||||
additional_audio_exts=list,of,ext
|
||||
ignore_hidden=yes
|
||||
same_type=yes
|
||||
directory_mode=recursive
|
||||
ignore_patterns=^~,^bak-,%.bak$
|
||||
|
||||
--]]
|
||||
|
||||
local MAX_ENTRIES = 5000
|
||||
local MAX_DIR_STACK = 20
|
||||
MAXENTRIES = 5000
|
||||
|
||||
local msg = require 'mp.msg'
|
||||
local options = require 'mp.options'
|
||||
local utils = require 'mp.utils'
|
||||
|
||||
local o = {
|
||||
o = {
|
||||
disabled = false,
|
||||
images = true,
|
||||
videos = true,
|
||||
audio = true,
|
||||
additional_image_exts = "",
|
||||
additional_video_exts = "",
|
||||
additional_audio_exts = "",
|
||||
ignore_hidden = true,
|
||||
same_type = false,
|
||||
directory_mode = "auto",
|
||||
ignore_patterns = ""
|
||||
ignore_hidden = true
|
||||
}
|
||||
options.read_options(o)
|
||||
|
||||
local function Set(t)
|
||||
function Set (t)
|
||||
local set = {}
|
||||
for _, v in pairs(t) do set[v] = true end
|
||||
return set
|
||||
end
|
||||
|
||||
local EXTENSIONS_VIDEO_DEFAULT = Set {
|
||||
function SetUnion (a,b)
|
||||
local res = {}
|
||||
for k in pairs(a) do res[k] = true end
|
||||
for k in pairs(b) do res[k] = true end
|
||||
return res
|
||||
end
|
||||
|
||||
EXTENSIONS_VIDEO = Set {
|
||||
'3g2', '3gp', 'avi', 'flv', 'm2ts', 'm4v', 'mj2', 'mkv', 'mov',
|
||||
'mp4', 'mpeg', 'mpg', 'ogv', 'rmvb', 'webm', 'wmv', 'y4m'
|
||||
}
|
||||
|
||||
local EXTENSIONS_AUDIO_DEFAULT = Set {
|
||||
EXTENSIONS_AUDIO = Set {
|
||||
'aiff', 'ape', 'au', 'flac', 'm4a', 'mka', 'mp3', 'oga', 'ogg',
|
||||
'ogm', 'opus', 'wav', 'wma'
|
||||
}
|
||||
|
||||
local EXTENSIONS_IMAGES_DEFAULT = Set {
|
||||
EXTENSIONS_IMAGES = Set {
|
||||
'avif', 'bmp', 'gif', 'j2k', 'jp2', 'jpeg', 'jpg', 'jxl', 'png',
|
||||
'svg', 'tga', 'tif', 'tiff', 'webp'
|
||||
}
|
||||
|
||||
local EXTENSIONS, EXTENSIONS_VIDEO, EXTENSIONS_AUDIO, EXTENSIONS_IMAGES
|
||||
EXTENSIONS = Set {}
|
||||
if o.videos then EXTENSIONS = SetUnion(EXTENSIONS, EXTENSIONS_VIDEO) end
|
||||
if o.audio then EXTENSIONS = SetUnion(EXTENSIONS, EXTENSIONS_AUDIO) end
|
||||
if o.images then EXTENSIONS = SetUnion(EXTENSIONS, EXTENSIONS_IMAGES) end
|
||||
|
||||
local function SetUnion(a, b)
|
||||
for k in pairs(b) do a[k] = true end
|
||||
return a
|
||||
end
|
||||
|
||||
-- Returns first and last positions in string or past-to-end indices
|
||||
local function FindOrPastTheEnd(string, pattern, start_at)
|
||||
local pos1, pos2 = string:find(pattern, start_at)
|
||||
return pos1 or #string + 1,
|
||||
pos2 or #string + 1
|
||||
end
|
||||
|
||||
local function Split(list)
|
||||
local set = {}
|
||||
|
||||
local item_pos = 1
|
||||
local item = ""
|
||||
|
||||
while item_pos <= #list do
|
||||
local pos1, pos2 = FindOrPastTheEnd(list, "%%*,", item_pos)
|
||||
|
||||
local pattern_length = pos2 - pos1
|
||||
local is_comma_escaped = pattern_length % 2
|
||||
|
||||
local pos_before_escape = pos1 - 1
|
||||
local item_escape_count = pattern_length - is_comma_escaped
|
||||
|
||||
item = item .. string.sub(list, item_pos, pos_before_escape + item_escape_count)
|
||||
|
||||
if is_comma_escaped == 1 then
|
||||
item = item .. ","
|
||||
else
|
||||
set[item] = true
|
||||
item = ""
|
||||
end
|
||||
|
||||
item_pos = pos2 + 1
|
||||
end
|
||||
|
||||
set[item] = true
|
||||
|
||||
-- exclude empty items
|
||||
set[""] = nil
|
||||
|
||||
return set
|
||||
end
|
||||
|
||||
local function split_option_exts(video, audio, image)
|
||||
if video then o.additional_video_exts = Split(o.additional_video_exts) end
|
||||
if audio then o.additional_audio_exts = Split(o.additional_audio_exts) end
|
||||
if image then o.additional_image_exts = Split(o.additional_image_exts) end
|
||||
end
|
||||
|
||||
local function split_patterns()
|
||||
o.ignore_patterns = Split(o.ignore_patterns)
|
||||
end
|
||||
|
||||
local function create_extensions()
|
||||
EXTENSIONS = {}
|
||||
EXTENSIONS_VIDEO = {}
|
||||
EXTENSIONS_AUDIO = {}
|
||||
EXTENSIONS_IMAGES = {}
|
||||
if o.videos then
|
||||
SetUnion(SetUnion(EXTENSIONS_VIDEO, EXTENSIONS_VIDEO_DEFAULT), o.additional_video_exts)
|
||||
SetUnion(EXTENSIONS, EXTENSIONS_VIDEO)
|
||||
end
|
||||
if o.audio then
|
||||
SetUnion(SetUnion(EXTENSIONS_AUDIO, EXTENSIONS_AUDIO_DEFAULT), o.additional_audio_exts)
|
||||
SetUnion(EXTENSIONS, EXTENSIONS_AUDIO)
|
||||
end
|
||||
if o.images then
|
||||
SetUnion(SetUnion(EXTENSIONS_IMAGES, EXTENSIONS_IMAGES_DEFAULT), o.additional_image_exts)
|
||||
SetUnion(EXTENSIONS, EXTENSIONS_IMAGES)
|
||||
end
|
||||
end
|
||||
|
||||
local function validate_directory_mode()
|
||||
if o.directory_mode ~= "recursive" and o.directory_mode ~= "lazy"
|
||||
and o.directory_mode ~= "ignore" then
|
||||
o.directory_mode = nil
|
||||
end
|
||||
end
|
||||
|
||||
options.read_options(o, nil, function(list)
|
||||
split_option_exts(list.additional_video_exts, list.additional_audio_exts,
|
||||
list.additional_image_exts)
|
||||
if list.videos or list.additional_video_exts or
|
||||
list.audio or list.additional_audio_exts or
|
||||
list.images or list.additional_image_exts then
|
||||
create_extensions()
|
||||
end
|
||||
if list.directory_mode then
|
||||
validate_directory_mode()
|
||||
end
|
||||
if list.ignore_patterns then
|
||||
split_patterns()
|
||||
end
|
||||
end)
|
||||
|
||||
split_option_exts(true, true, true)
|
||||
split_patterns()
|
||||
create_extensions()
|
||||
validate_directory_mode()
|
||||
|
||||
local function add_files(files)
|
||||
function add_files_at(index, files)
|
||||
index = index - 1
|
||||
local oldcount = mp.get_property_number("playlist-count", 1)
|
||||
for i = 1, #files do
|
||||
mp.commandv("loadfile", files[i][1], "append")
|
||||
mp.commandv("playlist-move", oldcount + i - 1, files[i][2])
|
||||
mp.commandv("loadfile", files[i], "append")
|
||||
mp.commandv("playlist-move", oldcount + i - 1, index + i - 1)
|
||||
end
|
||||
end
|
||||
|
||||
local function get_extension(path)
|
||||
return path:match("%.([^%.]+)$") or "nomatch"
|
||||
function get_extension(path)
|
||||
match = string.match(path, "%.([^%.]+)$" )
|
||||
if match == nil then
|
||||
return "nomatch"
|
||||
else
|
||||
return match
|
||||
end
|
||||
end
|
||||
|
||||
local function is_ignored(file)
|
||||
for pattern in pairs(o.ignore_patterns) do
|
||||
if file:match(pattern) then
|
||||
return true
|
||||
table.filter = function(t, iter)
|
||||
for i = #t, 1, -1 do
|
||||
if not iter(t[i]) then
|
||||
table.remove(t, i)
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
-- alphanum sorting for humans in Lua
|
||||
-- http://notebook.kulchenko.com/algorithms/alphanumeric-natural-sorting-for-humans-in-lua
|
||||
|
||||
local function alphanumsort(filenames)
|
||||
function alphanumsort(filenames)
|
||||
local function padnum(n, d)
|
||||
return #d > 0 and ("%03d%s%.12f"):format(#n, n, tonumber(d) / (10 ^ #d))
|
||||
or ("%03d%s"):format(#n, n)
|
||||
@@ -221,119 +114,38 @@ local function alphanumsort(filenames)
|
||||
return filenames
|
||||
end
|
||||
|
||||
local autoloaded
|
||||
local added_entries = {}
|
||||
local autoloaded_dir
|
||||
local autoloaded = nil
|
||||
|
||||
local function scan_dir(path, current_file, dir_mode, separator, dir_depth, total_files, extensions)
|
||||
if dir_depth == MAX_DIR_STACK then
|
||||
return
|
||||
end
|
||||
msg.trace("scanning: " .. path)
|
||||
local files = utils.readdir(path, "files") or {}
|
||||
local dirs = dir_mode ~= "ignore" and utils.readdir(path, "dirs") or {}
|
||||
local prefix = path == "." and "" or path
|
||||
|
||||
local function filter(t, iter)
|
||||
for i = #t, 1, -1 do
|
||||
if not iter(t[i]) then
|
||||
table.remove(t, i)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
filter(files, function(v)
|
||||
-- Always accept current file
|
||||
local current = prefix .. v == current_file
|
||||
if current then
|
||||
return true
|
||||
end
|
||||
if o.ignore_hidden and v:match("^%.") then
|
||||
return false
|
||||
end
|
||||
if is_ignored(v) then
|
||||
return false
|
||||
end
|
||||
|
||||
local ext = get_extension(v)
|
||||
return ext and extensions[ext:lower()]
|
||||
end)
|
||||
filter(dirs, function(d)
|
||||
return not (o.ignore_hidden and d:match("^%."))
|
||||
end)
|
||||
alphanumsort(files)
|
||||
alphanumsort(dirs)
|
||||
|
||||
for i, file in ipairs(files) do
|
||||
files[i] = prefix .. file
|
||||
end
|
||||
|
||||
local function append(t1, t2)
|
||||
local t1_size = #t1
|
||||
for i = 1, #t2 do
|
||||
t1[t1_size + i] = t2[i]
|
||||
end
|
||||
end
|
||||
|
||||
append(total_files, files)
|
||||
if dir_mode == "recursive" then
|
||||
for _, dir in ipairs(dirs) do
|
||||
scan_dir(prefix .. dir .. separator, current_file, dir_mode,
|
||||
separator, dir_depth + 1, total_files, extensions)
|
||||
end
|
||||
else
|
||||
for i, dir in ipairs(dirs) do
|
||||
dirs[i] = prefix .. dir
|
||||
end
|
||||
append(total_files, dirs)
|
||||
function get_playlist_filenames()
|
||||
local filenames = {}
|
||||
for n = 0, pl_count - 1, 1 do
|
||||
local filename = mp.get_property('playlist/'..n..'/filename')
|
||||
local _, file = utils.split_path(filename)
|
||||
filenames[file] = true
|
||||
end
|
||||
return filenames
|
||||
end
|
||||
|
||||
local function find_and_add_entries()
|
||||
local aborted = mp.get_property_native("playback-abort")
|
||||
if aborted then
|
||||
msg.debug("stopping: playback aborted")
|
||||
return
|
||||
end
|
||||
|
||||
function find_and_add_entries()
|
||||
local path = mp.get_property("path", "")
|
||||
local dir, filename = utils.split_path(path)
|
||||
msg.trace(("dir: %s, filename: %s"):format(dir, filename))
|
||||
if o.disabled then
|
||||
msg.debug("stopping: autoload disabled")
|
||||
msg.verbose("stopping: autoload disabled")
|
||||
return
|
||||
elseif #dir == 0 then
|
||||
msg.debug("stopping: not a local path")
|
||||
msg.verbose("stopping: not a local path")
|
||||
return
|
||||
end
|
||||
|
||||
local pl_count = mp.get_property_number("playlist-count", 1)
|
||||
local this_ext = get_extension(filename)
|
||||
pl_count = mp.get_property_number("playlist-count", 1)
|
||||
-- check if this is a manually made playlist
|
||||
if pl_count > 1 and autoloaded == nil then
|
||||
msg.debug("stopping: manually made playlist")
|
||||
if (pl_count > 1 and autoloaded == nil) or
|
||||
(pl_count == 1 and EXTENSIONS[string.lower(get_extension(filename))] == nil) then
|
||||
msg.verbose("stopping: manually made playlist")
|
||||
return
|
||||
elseif pl_count == 1 then
|
||||
autoloaded = true
|
||||
autoloaded_dir = dir
|
||||
added_entries = {}
|
||||
end
|
||||
|
||||
local extensions
|
||||
if o.same_type then
|
||||
if EXTENSIONS_VIDEO[this_ext:lower()] then
|
||||
extensions = EXTENSIONS_VIDEO
|
||||
elseif EXTENSIONS_AUDIO[this_ext:lower()] then
|
||||
extensions = EXTENSIONS_AUDIO
|
||||
elseif EXTENSIONS_IMAGES[this_ext:lower()] then
|
||||
extensions = EXTENSIONS_IMAGES
|
||||
end
|
||||
else
|
||||
extensions = EXTENSIONS
|
||||
end
|
||||
if not extensions then
|
||||
msg.debug("stopping: no matched extentions list")
|
||||
return
|
||||
autoloaded = true
|
||||
end
|
||||
|
||||
local pl = mp.get_property_native("playlist", {})
|
||||
@@ -341,75 +153,69 @@ local function find_and_add_entries()
|
||||
msg.trace(("playlist-pos-1: %s, playlist: %s"):format(pl_current,
|
||||
utils.to_string(pl)))
|
||||
|
||||
local files = {}
|
||||
scan_dir(autoloaded_dir, path,
|
||||
o.directory_mode or mp.get_property("directory-mode", "lazy"),
|
||||
mp.get_property_native("platform") == "windows" and "\\" or "/",
|
||||
0, files, extensions)
|
||||
|
||||
if next(files) == nil then
|
||||
msg.debug("no other files or directories in directory")
|
||||
local files = utils.readdir(dir, "files")
|
||||
if files == nil then
|
||||
msg.verbose("no other files in directory")
|
||||
return
|
||||
end
|
||||
table.filter(files, function (v, k)
|
||||
-- The current file could be a hidden file, ignoring it doesn't load other
|
||||
-- files from the current directory.
|
||||
if (o.ignore_hidden and not (v == filename) and string.match(v, "^%.")) then
|
||||
return false
|
||||
end
|
||||
local ext = get_extension(v)
|
||||
if ext == nil then
|
||||
return false
|
||||
end
|
||||
return EXTENSIONS[string.lower(ext)]
|
||||
end)
|
||||
alphanumsort(files)
|
||||
|
||||
if dir == "." then
|
||||
dir = ""
|
||||
end
|
||||
|
||||
-- Find the current pl entry (dir+"/"+filename) in the sorted dir list
|
||||
local current
|
||||
for i = 1, #files do
|
||||
if files[i] == path then
|
||||
if files[i] == filename then
|
||||
current = i
|
||||
break
|
||||
end
|
||||
end
|
||||
if not current then
|
||||
msg.debug("current file not found in directory")
|
||||
if current == nil then
|
||||
return
|
||||
end
|
||||
msg.trace("current file position in files: "..current)
|
||||
|
||||
-- treat already existing playlist entries, independent of how they got added
|
||||
-- as if they got added by autoload
|
||||
for _, entry in ipairs(pl) do
|
||||
added_entries[entry.filename] = true
|
||||
end
|
||||
|
||||
local append = {[-1] = {}, [1] = {}}
|
||||
local filenames = get_playlist_filenames()
|
||||
for direction = -1, 1, 2 do -- 2 iterations, with direction = -1 and +1
|
||||
for i = 1, MAX_ENTRIES do
|
||||
local pos = current + i * direction
|
||||
local file = files[pos]
|
||||
for i = 1, MAXENTRIES do
|
||||
local file = files[current + i * direction]
|
||||
if file == nil or file[1] == "." then
|
||||
break
|
||||
end
|
||||
|
||||
-- skip files that are/were already in the playlist
|
||||
if not added_entries[file] then
|
||||
if direction == -1 then
|
||||
msg.verbose("Prepending " .. file)
|
||||
table.insert(append[-1], 1, {file, pl_current + i * direction + 1})
|
||||
else
|
||||
msg.verbose("Adding " .. file)
|
||||
if pl_count > 1 then
|
||||
table.insert(append[1], {file, pl_current + i * direction - 1})
|
||||
else
|
||||
mp.commandv("loadfile", file, "append")
|
||||
end
|
||||
local filepath = dir .. file
|
||||
-- skip files already in playlist
|
||||
if filenames[file] then break end
|
||||
|
||||
if direction == -1 then
|
||||
if pl_current == 1 then -- never add additional entries in the middle
|
||||
msg.info("Prepending " .. file)
|
||||
table.insert(append[-1], 1, filepath)
|
||||
end
|
||||
added_entries[file] = true
|
||||
else
|
||||
msg.info("Adding " .. file)
|
||||
table.insert(append[1], filepath)
|
||||
end
|
||||
end
|
||||
if pl_count == 1 and direction == -1 and #append[-1] > 0 then
|
||||
local load = append[-1]
|
||||
for i = 1, #load do
|
||||
mp.commandv("loadfile", load[i][1], "append")
|
||||
end
|
||||
mp.commandv("playlist-move", 0, current)
|
||||
end
|
||||
end
|
||||
|
||||
if pl_count > 1 then
|
||||
add_files(append[1])
|
||||
add_files(append[-1])
|
||||
end
|
||||
add_files_at(pl_current + 1, append[1])
|
||||
add_files_at(pl_current, append[-1])
|
||||
end
|
||||
|
||||
mp.register_event("start-file", find_and_add_entries)
|
||||
|
||||
@@ -1,711 +0,0 @@
|
||||
-- // Bookmarker Menu v1.3.1 for mpv \\ --
|
||||
-- See README.md for instructions
|
||||
|
||||
-- Maximum number of characters for bookmark name
|
||||
local maxChar = 100
|
||||
-- Number of bookmarks to be displayed per page
|
||||
local bookmarksPerPage = 10
|
||||
-- Whether to close the Bookmarker menu after loading a bookmark
|
||||
local closeAfterLoad = true
|
||||
-- Whether to close the Bookmarker menu after replacing a bookmark
|
||||
local closeAfterReplace = true
|
||||
-- Whether to ask for confirmation to replace a bookmark (Uses the Typer for confirmation)
|
||||
local confirmReplace = false
|
||||
-- Whether to ask for confirmation to delete a bookmark (Uses the Typer for confirmation)
|
||||
local confirmDelete = false
|
||||
-- The rate (in seconds) at which the bookmarker needs to refresh its interface; lower is more frequent
|
||||
local rate = 1.5
|
||||
-- The filename for the bookmarks file
|
||||
local bookmarkerName = "bookmarker.json"
|
||||
|
||||
-- All the "global" variables and utilities; don't touch these
|
||||
local utils = require 'mp.utils'
|
||||
local styleOn = mp.get_property("osd-ass-cc/0")
|
||||
local styleOff = mp.get_property("osd-ass-cc/1")
|
||||
local bookmarks = {}
|
||||
local currentSlot = 0
|
||||
local currentPage = 1
|
||||
local maxPage = 1
|
||||
local active = false
|
||||
local mode = "none"
|
||||
local bookmarkStore = {}
|
||||
local oldSlot = 0
|
||||
|
||||
-- // Controls \\ --
|
||||
|
||||
-- List of custom controls and their function
|
||||
local bookmarkerControls = {
|
||||
ESC = function() abort("") end,
|
||||
e = function() abort("") end,
|
||||
DOWN = function() jumpSlot(1) end,
|
||||
UP = function() jumpSlot(-1) end,
|
||||
j = function() jumpSlot(1) end,
|
||||
k = function() jumpSlot(-1) end,
|
||||
RIGHT = function() jumpPage(1) end,
|
||||
LEFT = function() jumpPage(-1) end,
|
||||
O = function() addBookmark() end,
|
||||
-- O = function() mode="save" typerStart() end,
|
||||
p = function() mode="replace" typerStart() end,
|
||||
r = function() mode="rename" typerStart() end,
|
||||
f = function() mode="filepath" typerStart() end,
|
||||
m = function() mode="move" moverStart() end,
|
||||
d = function() mode="delete" typerStart() end,
|
||||
DEL = function() mode="delete" typerStart() end,
|
||||
ENTER = function() jumpToBookmark(currentSlot) end,
|
||||
KP_ENTER = function() jumpToBookmark(currentSlot) end
|
||||
}
|
||||
|
||||
local bookmarkerFlags = {
|
||||
DOWN = {repeatable = true},
|
||||
UP = {repeatable = true},
|
||||
RIGHT = {repeatable = true},
|
||||
LEFT = {repeatable = true}
|
||||
}
|
||||
|
||||
-- Activate the custom controls
|
||||
function activateControls(name, controls, flags)
|
||||
for key, func in pairs(controls) do
|
||||
mp.add_forced_key_binding(key, name..key, func, flags[key])
|
||||
end
|
||||
end
|
||||
|
||||
-- Deactivate the custom controls
|
||||
function deactivateControls(name, controls)
|
||||
for key, _ in pairs(controls) do
|
||||
mp.remove_key_binding(name..key)
|
||||
end
|
||||
end
|
||||
|
||||
-- // Typer \\ --
|
||||
|
||||
-- Controls for the Typer
|
||||
local typerControls = {
|
||||
ESC = function() typerExit() end,
|
||||
ENTER = function() typerCommit() end,
|
||||
KP_ENTER = function() typerCommit() end,
|
||||
RIGHT = function() typerCursor(1) end,
|
||||
LEFT = function() typerCursor(-1) end,
|
||||
BS = function() typer("backspace") end,
|
||||
DEL = function() typer("delete") end,
|
||||
SPACE = function() typer(" ") end,
|
||||
SHARP = function() typer("#") end,
|
||||
KP0 = function() typer("0") end,
|
||||
KP1 = function() typer("1") end,
|
||||
KP2 = function() typer("2") end,
|
||||
KP3 = function() typer("3") end,
|
||||
KP4 = function() typer("4") end,
|
||||
KP5 = function() typer("5") end,
|
||||
KP6 = function() typer("6") end,
|
||||
KP7 = function() typer("7") end,
|
||||
KP8 = function() typer("8") end,
|
||||
KP9 = function() typer("9") end,
|
||||
KP_DEC = function() typer(".") end
|
||||
}
|
||||
|
||||
-- All standard keys for the Typer
|
||||
local typerKeys = {"a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z","1","2","3","4","5","6","7","8","9","0","!","@","$","%","^","&","*","(",")","-","_","=","+","[","]","{","}","\\","|",";",":","'","\"",",",".","<",">","/","?","`","~"}
|
||||
-- For some reason, semicolon is not possible, but it's listed there just in case anyway
|
||||
|
||||
local typerText = ""
|
||||
local typerPos = 0
|
||||
local typerActive = false
|
||||
|
||||
-- Function to activate the Typer
|
||||
-- use typerStart() for custom controls around activating the Typer
|
||||
function activateTyper()
|
||||
for key, func in pairs(typerControls) do
|
||||
mp.add_forced_key_binding(key, "typer"..key, func, {repeatable=true})
|
||||
end
|
||||
for i, key in ipairs(typerKeys) do
|
||||
mp.add_forced_key_binding(key, "typer"..key, function() typer(key) end, {repeatable=true})
|
||||
end
|
||||
typerText = ""
|
||||
typerActive = true
|
||||
end
|
||||
|
||||
-- Function to deactivate the Typer
|
||||
-- use typerExit() for custom controls around deactivating the Typer
|
||||
function deactivateTyper()
|
||||
for key, _ in pairs(typerControls) do
|
||||
mp.remove_key_binding("typer"..key)
|
||||
end
|
||||
for i, key in ipairs(typerKeys) do
|
||||
mp.remove_key_binding("typer"..key)
|
||||
end
|
||||
typerActive = false
|
||||
return typerText
|
||||
end
|
||||
|
||||
-- Function to move the cursor of the typer; can wrap around
|
||||
function typerCursor(direction)
|
||||
typerPos = typerPos + direction
|
||||
if typerPos < 0 then typerPos = typerText:len() end
|
||||
if typerPos > typerText:len() then typerPos = 0 end
|
||||
typer("")
|
||||
end
|
||||
|
||||
-- Function for handling the text as it is being typed
|
||||
function typer(s)
|
||||
-- Don't touch this part
|
||||
if s == "backspace" then
|
||||
if typerPos > 0 then
|
||||
typerText = typerText:sub(1, typerPos - 1) .. typerText:sub(typerPos + 1)
|
||||
typerPos = typerPos - 1
|
||||
end
|
||||
elseif s == "delete" then
|
||||
if typerPos < typerText:len() then
|
||||
typerText = typerText:sub(1, typerPos) .. typerText:sub(typerPos + 2)
|
||||
end
|
||||
else
|
||||
if mode == "filepath" or typerText:len() < maxChar then
|
||||
typerText = typerText:sub(1, typerPos) .. s .. typerText:sub(typerPos + 1)
|
||||
typerPos = typerPos + s:len()
|
||||
end
|
||||
end
|
||||
|
||||
-- Enter custom script and display message here
|
||||
local preMessage = "Enter a bookmark name:"
|
||||
if mode == "save" then
|
||||
preMessage = styleOn.."{\\b1}Save a new bookmark with custom name:{\\b0}"..styleOff
|
||||
elseif mode == "replace" then
|
||||
preMessage = styleOn.."{\\b1}Type \"y\" to replace the following bookmark:{\\b0}\n"..displayName(bookmarks[currentSlot]["name"])..styleOff
|
||||
elseif mode == "delete" then
|
||||
preMessage = styleOn.."{\\b1}Type \"y\" to delete the following bookmark:{\\b0}\n"..displayName(bookmarks[currentSlot]["name"])..styleOff
|
||||
elseif mode == "rename" then
|
||||
preMessage = styleOn.."{\\b1}Rename an existing bookmark:{\\b0}"..styleOff
|
||||
elseif mode == "filepath" then
|
||||
preMessage = styleOn.."{\\b1}Change the bookmark's filepath:{\\b0}"..styleOff
|
||||
end
|
||||
|
||||
local postMessage = ""
|
||||
local split = typerPos + math.floor(typerPos / maxChar)
|
||||
local messageLines = math.floor((typerText:len() - 1) / maxChar) + 1
|
||||
for i = 1, messageLines do
|
||||
postMessage = postMessage .. typerText:sub((i-1) * maxChar + 1, i * maxChar) .. "\n"
|
||||
end
|
||||
postMessage = postMessage:sub(1,postMessage:len()-1)
|
||||
|
||||
mp.osd_message(preMessage.."\n"..postMessage:sub(1,split)..styleOn.."{\\c&H00FFFF&}{\\b1}|{\\r}"..styleOff..postMessage:sub(split+1), 9999)
|
||||
end
|
||||
|
||||
-- // Mover \\ --
|
||||
|
||||
-- Controls for the Mover
|
||||
local moverControls = {
|
||||
ESC = function() moverExit() end,
|
||||
DOWN = function() jumpSlot(1) end,
|
||||
UP = function() jumpSlot(-1) end,
|
||||
RIGHT = function() jumpPage(1) end,
|
||||
LEFT = function() jumpPage(-1) end,
|
||||
s = function() addBookmark() end,
|
||||
m = function() moverCommit() end,
|
||||
ENTER = function() moverCommit() end,
|
||||
KP_ENTER = function() moverCommit() end
|
||||
}
|
||||
|
||||
local moverFlags = {
|
||||
DOWN = {repeatable = true},
|
||||
UP = {repeatable = true},
|
||||
RIGHT = {repeatable = true},
|
||||
LEFT = {repeatable = true}
|
||||
}
|
||||
|
||||
-- Function to activate the Mover
|
||||
function moverStart()
|
||||
if bookmarkExists(currentSlot) then
|
||||
deactivateControls("bookmarker", bookmarkerControls)
|
||||
activateControls("mover", moverControls, moverFlags)
|
||||
displayBookmarks()
|
||||
else
|
||||
abort(styleOn.."{\\c&H0000FF&}{\\b1}Can't find the bookmark at slot "..currentSlot)
|
||||
end
|
||||
end
|
||||
|
||||
-- Function to commit the action of the Mover
|
||||
function moverCommit()
|
||||
saveBookmarks()
|
||||
moverExit()
|
||||
end
|
||||
|
||||
-- Function to deactivate the Mover
|
||||
-- If isError is set, then it'll abort
|
||||
function moverExit(isError)
|
||||
deactivateControls("mover", moverControls)
|
||||
mode = "none"
|
||||
if not isError then
|
||||
loadBookmarks()
|
||||
displayBookmarks()
|
||||
activateControls("bookmarker", bookmarkerControls, bookmarkerFlags)
|
||||
end
|
||||
end
|
||||
|
||||
-- // General utilities \\ --
|
||||
|
||||
-- Check if the operating system is Mac OS
|
||||
function isMacOS()
|
||||
local homedir = os.getenv("HOME")
|
||||
return (homedir ~= nil and string.sub(homedir,1,6) == "/Users")
|
||||
end
|
||||
|
||||
-- Check if the operating system is Windows
|
||||
function isWindows()
|
||||
local windir = os.getenv("windir")
|
||||
return (windir~=nil)
|
||||
end
|
||||
|
||||
-- Check whether a certain file exists
|
||||
function fileExists(path)
|
||||
local f = io.open(path,"r")
|
||||
if f~=nil then
|
||||
io.close(f)
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
-- Get the filepath of a file from the mpv config folder
|
||||
function getFilepath(filename)
|
||||
if isWindows() then
|
||||
return os.getenv("APPDATA"):gsub("\\", "/") .. "/mpv/" .. filename
|
||||
else
|
||||
return os.getenv("HOME") .. "/.config/mpv/" .. filename
|
||||
end
|
||||
end
|
||||
|
||||
-- Load a table from a JSON file
|
||||
-- Returns nil if the file can't be found
|
||||
function loadTable(path)
|
||||
local contents = ""
|
||||
local myTable = {}
|
||||
local file = io.open( path, "r" )
|
||||
if file then
|
||||
local contents = file:read( "*a" )
|
||||
myTable = utils.parse_json(contents);
|
||||
io.close(file)
|
||||
return myTable
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
-- Save a table as a JSON file file
|
||||
-- Returns true if successful
|
||||
function saveTable(t, path)
|
||||
local contents = utils.format_json(t)
|
||||
local file = io.open(path .. ".tmp", "wb")
|
||||
file:write(contents)
|
||||
io.close(file)
|
||||
os.remove(path)
|
||||
os.rename(path .. ".tmp", path)
|
||||
return true
|
||||
end
|
||||
|
||||
-- Convert a pos (seconds) to a hh:mm:ss.mmm format
|
||||
function parseTime(pos)
|
||||
local hours = math.floor(pos/3600)
|
||||
local minutes = math.floor((pos % 3600)/60)
|
||||
local seconds = math.floor((pos % 60))
|
||||
local milliseconds = math.floor(pos % 1 * 1000)
|
||||
return string.format("%02d:%02d:%02d.%03d",hours,minutes,seconds,milliseconds)
|
||||
end
|
||||
|
||||
-- // Bookmark functions \\ --
|
||||
|
||||
-- Checks whether the specified bookmark exists
|
||||
function bookmarkExists(slot)
|
||||
return (slot >= 1 and slot <= #bookmarks)
|
||||
end
|
||||
|
||||
-- Calculates the current page and the total number of pages
|
||||
function calcPages()
|
||||
currentPage = math.floor((currentSlot - 1) / bookmarksPerPage) + 1
|
||||
if currentPage == 0 then currentPage = 1 end
|
||||
maxPage = math.floor((#bookmarks - 1) / bookmarksPerPage) + 1
|
||||
if maxPage == 0 then maxPage = 1 end
|
||||
end
|
||||
|
||||
-- Get the amount of bookmarks on the specified page
|
||||
function getAmountBookmarksOnPage(page)
|
||||
local n = bookmarksPerPage
|
||||
if page == maxPage then n = #bookmarks % bookmarksPerPage end
|
||||
if n == 0 then n = bookmarksPerPage end
|
||||
if #bookmarks == 0 then n = 0 end
|
||||
return n
|
||||
end
|
||||
|
||||
-- Get the index of the first slot on the specified page
|
||||
function getFirstSlotOnPage(page)
|
||||
return (page - 1) * bookmarksPerPage + 1
|
||||
end
|
||||
|
||||
-- Get the index of the last slot on the specified page
|
||||
function getLastSlotOnPage(page)
|
||||
local endSlot = getFirstSlotOnPage(page) + getAmountBookmarksOnPage(page) - 1
|
||||
if endSlot > #bookmarks then endSlot = #bookmarks end
|
||||
return endSlot
|
||||
end
|
||||
|
||||
-- Jumps a certain amount of slots forward or backwards in the bookmarks list
|
||||
-- Keeps in mind if the current mode is to move bookmarks
|
||||
function jumpSlot(i)
|
||||
if mode == "move" then
|
||||
oldSlot = currentSlot
|
||||
bookmarkStore = bookmarks[oldSlot]
|
||||
end
|
||||
|
||||
currentSlot = currentSlot + i
|
||||
local startSlot = getFirstSlotOnPage(currentPage)
|
||||
local endSlot = getLastSlotOnPage(currentPage)
|
||||
|
||||
if currentSlot < startSlot then currentSlot = endSlot end
|
||||
if currentSlot > endSlot then currentSlot = startSlot end
|
||||
|
||||
if mode == "move" then
|
||||
table.remove(bookmarks, oldSlot)
|
||||
table.insert(bookmarks, currentSlot, bookmarkStore)
|
||||
end
|
||||
|
||||
displayBookmarks()
|
||||
end
|
||||
|
||||
-- Jumps a certain amount of pages forward or backwards in the bookmarks list
|
||||
-- Keeps in mind if the current mode is to move bookmarks
|
||||
function jumpPage(i)
|
||||
if mode == "move" then
|
||||
oldSlot = currentSlot
|
||||
bookmarkStore = bookmarks[oldSlot]
|
||||
end
|
||||
|
||||
local oldPos = currentSlot - getFirstSlotOnPage(currentPage) + 1
|
||||
currentPage = currentPage + i
|
||||
if currentPage < 1 then currentPage = maxPage + currentPage end
|
||||
if currentPage > maxPage then currentPage = currentPage - maxPage end
|
||||
|
||||
local bookmarksOnPage = getAmountBookmarksOnPage(currentPage)
|
||||
if oldPos > bookmarksOnPage then oldPos = bookmarksOnPage end
|
||||
currentSlot = getFirstSlotOnPage(currentPage) + oldPos - 1
|
||||
|
||||
if mode == "move" then
|
||||
table.remove(bookmarks, oldSlot)
|
||||
table.insert(bookmarks, currentSlot, bookmarkStore)
|
||||
end
|
||||
|
||||
displayBookmarks()
|
||||
end
|
||||
|
||||
-- Parses a bookmark name for storing, also trimming it
|
||||
-- Replaces %t with the timestamp of the bookmark
|
||||
-- Replaces %p with the time position of the bookmark
|
||||
function parseName(name)
|
||||
local pos = 0
|
||||
if mode == "rename" then pos = bookmarks[currentSlot]["pos"] else pos = mp.get_property_number("time-pos") end
|
||||
name, _ = name:gsub("%%t", parseTime(pos))
|
||||
name, _ = name:gsub("%%p", pos)
|
||||
name = trimName(name)
|
||||
return name
|
||||
end
|
||||
|
||||
-- Parses a bookmark name for displaying, also trimming it
|
||||
-- Replaces all { with an escaped { so it won't be interpreted as a tag
|
||||
function displayName(name)
|
||||
name, _ = name:gsub("{", "\\{")
|
||||
name = trimName(name)
|
||||
return name
|
||||
end
|
||||
|
||||
-- Trims a name to the max number of characters
|
||||
function trimName(name)
|
||||
if name:len() > maxChar then name = name:sub(1,maxChar) end
|
||||
return name
|
||||
end
|
||||
|
||||
-- Parses a Windows path with backslashes to one with normal slashes
|
||||
function parsePath(path)
|
||||
if type(path) == "string" then path, _ = path:gsub("\\", "/") end
|
||||
return path
|
||||
end
|
||||
|
||||
-- Loads all the bookmarks in the global table and sets the current page and total number of pages
|
||||
-- Also checks for older versions of bookmarks and "updates" them
|
||||
-- Also checks for bookmarks made by "mpv-bookmarker" and converts them
|
||||
-- Also removes anything it doesn't recognize as a bookmark
|
||||
function loadBookmarks()
|
||||
bookmarks = loadTable(getFilepath(bookmarkerName))
|
||||
if bookmarks == nil then bookmarks = {} end
|
||||
|
||||
local doSave = false
|
||||
local doEject = false
|
||||
local doReplace = false
|
||||
local ejects = {}
|
||||
local newmarks = {}
|
||||
|
||||
for key, bookmark in pairs(bookmarks) do
|
||||
if type(key) == "number" then
|
||||
if bookmark.version == nil or bookmark.version == 1 then
|
||||
if bookmark.name ~= nil and bookmark.path ~= nil and bookmark.pos ~= nil then
|
||||
bookmark.path = parsePath(bookmark.path)
|
||||
bookmark.version = 2
|
||||
doSave = true
|
||||
else
|
||||
table.insert(ejects, key)
|
||||
doEject = true
|
||||
end
|
||||
end
|
||||
else
|
||||
if bookmark.filename ~= nil and bookmark.pos ~= nil and bookmark.filepath ~= nil then
|
||||
local newmark = {
|
||||
name = trimName(""..bookmark.filename.." @ "..parseTime(bookmark.pos)),
|
||||
pos = bookmark.pos,
|
||||
path = parsePath(bookmark.filepath),
|
||||
version = 2
|
||||
}
|
||||
table.insert(newmarks, newmark)
|
||||
end
|
||||
doReplace = true
|
||||
doSave = true
|
||||
end
|
||||
end
|
||||
|
||||
if doEject then
|
||||
for i = #ejects, 1, -1 do table.remove(bookmarks, ejects[i]) end
|
||||
doSave = true
|
||||
end
|
||||
|
||||
if doReplace then bookmarks = newmarks end
|
||||
if doSave then saveBookmarks() end
|
||||
|
||||
if #bookmarks > 0 and currentSlot == 0 then currentSlot = 1 end
|
||||
calcPages()
|
||||
end
|
||||
|
||||
-- Save the globally loaded bookmarks to the JSON file
|
||||
function saveBookmarks()
|
||||
saveTable(bookmarks, getFilepath(bookmarkerName))
|
||||
end
|
||||
|
||||
-- Make a bookmark of the current media file, position and name
|
||||
-- Name can be specified or left blank to automake a name
|
||||
-- Returns the bookmark if successful or nil if it can't make a bookmark
|
||||
function makeBookmark(bname)
|
||||
if mp.get_property("path") ~= nil then
|
||||
if bname == nil then bname = mp.get_property("media-title").." @ %t" end
|
||||
local bookmark = {
|
||||
name = parseName(bname),
|
||||
pos = mp.get_property_number("time-pos"),
|
||||
path = parsePath(mp.get_property("path")),
|
||||
version = 2
|
||||
}
|
||||
return bookmark
|
||||
else
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
-- Add the current position as a bookmark to the global table and then saves it
|
||||
-- Returns the slot of the newly added bookmark
|
||||
-- Returns -1 if there's an error
|
||||
function addBookmark(name)
|
||||
local bookmark = makeBookmark(name)
|
||||
if bookmark == nil then
|
||||
abort(styleOn.."{\\c&H0000FF&}{\\b1}Can't find the media file to create the bookmark for")
|
||||
return -1
|
||||
end
|
||||
table.insert(bookmarks, bookmark)
|
||||
|
||||
if #bookmarks == 1 then currentSlot = 1 end
|
||||
|
||||
calcPages()
|
||||
saveBookmarks()
|
||||
displayBookmarks()
|
||||
return #bookmarks
|
||||
end
|
||||
|
||||
-- Edit a property of a bookmark at the specified slot
|
||||
-- Returns -1 if there's an error
|
||||
function editBookmark(slot, property, value)
|
||||
if bookmarkExists(slot) then
|
||||
if property == "name" then value = parseName(value) end
|
||||
bookmarks[slot][property] = value
|
||||
saveBookmarks()
|
||||
else
|
||||
abort(styleOn.."{\\c&H0000FF&}{\\b1}Can't find the bookmark at slot "..slot)
|
||||
return -1
|
||||
end
|
||||
end
|
||||
|
||||
-- Replaces the bookmark at the specified slot with a provided bookmark
|
||||
-- Keeps the name and its position in the list
|
||||
-- If the slot is not specified, picks the currently selected bookmark to replace
|
||||
-- If a bookmark is not provided, generates a new bookmark
|
||||
function replaceBookmark(slot)
|
||||
if slot == nil then slot = currentSlot end
|
||||
if bookmarkExists(slot) then
|
||||
local bookmark = makeBookmark(bookmarks[slot]["name"])
|
||||
if bookmark == nil then
|
||||
abort(styleOn.."{\\c&H0000FF&}{\\b1}Can't find the media file to create the bookmark for")
|
||||
return -1
|
||||
end
|
||||
bookmarks[slot] = bookmark
|
||||
saveBookmarks()
|
||||
if closeAfterReplace then
|
||||
abort(styleOn.."{\\c&H00FF00&}{\\b1}Successfully replaced bookmark:{\\r}\n"..displayName(bookmark["name"]))
|
||||
return -1
|
||||
end
|
||||
return 1
|
||||
else
|
||||
abort(styleOn.."{\\c&H0000FF&}{\\b1}Can't find the bookmark at slot "..slot)
|
||||
return -1
|
||||
end
|
||||
end
|
||||
|
||||
-- Quickly saves a bookmark without bringing up the menu
|
||||
function quickSave()
|
||||
if not active then
|
||||
loadBookmarks()
|
||||
local slot = addBookmark()
|
||||
if slot > 0 then mp.osd_message("Saved new bookmark at slot " .. slot) end
|
||||
end
|
||||
end
|
||||
|
||||
-- Quickly loads the last bookmark without bringing up the menu
|
||||
function quickLoad()
|
||||
if not active then
|
||||
loadBookmarks()
|
||||
local slot = #bookmarks
|
||||
if slot > 0 then mp.osd_message("Loaded bookmark at slot " .. slot) end
|
||||
jumpToBookmark(slot)
|
||||
end
|
||||
end
|
||||
|
||||
-- Deletes the bookmark in the specified slot from the global table and then saves it
|
||||
function deleteBookmark(slot)
|
||||
table.remove(bookmarks, slot)
|
||||
if currentSlot > #bookmarks then currentSlot = #bookmarks end
|
||||
|
||||
calcPages()
|
||||
saveBookmarks()
|
||||
displayBookmarks()
|
||||
end
|
||||
|
||||
-- Jump to the specified bookmark
|
||||
-- This means loading it, reading it, and jumping to the file + position in the bookmark
|
||||
function jumpToBookmark(slot)
|
||||
if bookmarkExists(slot) then
|
||||
local bookmark = bookmarks[slot]
|
||||
if string.sub(bookmark["path"], 1, 4) == "http" or fileExists(bookmark["path"]) then
|
||||
if parsePath(mp.get_property("path")) == bookmark["path"] then
|
||||
mp.set_property_number("time-pos", bookmark["pos"])
|
||||
else
|
||||
mp.commandv("loadfile", parsePath(bookmark["path"]), "replace", -1, "start="..bookmark["pos"]) end
|
||||
if closeAfterLoad then abort(styleOn.."{\\c&H00FF00&}{\\b1}Successfully found file for bookmark:{\\r}\n"..displayName(bookmark["name"])) end
|
||||
else
|
||||
abort(styleOn.."{\\c&H0000FF&}{\\b1}Can't find file for bookmark:\n" .. displayName(bookmark["name"]))
|
||||
end
|
||||
else
|
||||
abort(styleOn.."{\\c&H0000FF&}{\\b1}Can't find the bookmark at slot " .. slot)
|
||||
end
|
||||
end
|
||||
|
||||
-- Displays the current page of bookmarks
|
||||
function displayBookmarks()
|
||||
-- Determine which slot is the first and last on the current page
|
||||
local startSlot = getFirstSlotOnPage(currentPage)
|
||||
local endSlot = getLastSlotOnPage(currentPage)
|
||||
|
||||
-- Prepare the text to display and display it
|
||||
local display = styleOn .. "{\\b1}Bookmarks page " .. currentPage .. "/" .. maxPage .. ":{\\b0}"
|
||||
for i = startSlot, endSlot do
|
||||
local btext = displayName(bookmarks[i]["name"])
|
||||
local selection = ""
|
||||
if i == currentSlot then
|
||||
selection = "{\\b1}{\\c&H00FFFF&}>"
|
||||
if mode == "move" then btext = "----------------" end
|
||||
btext = btext
|
||||
end
|
||||
display = display .. "\n" .. selection .. i .. ": " .. btext .. "{\\r}"
|
||||
end
|
||||
mp.osd_message(display, rate)
|
||||
end
|
||||
|
||||
local timer = mp.add_periodic_timer(rate * 0.95, displayBookmarks)
|
||||
timer:kill()
|
||||
|
||||
-- Commits the message entered with the Typer with custom scripts preceding it
|
||||
-- Should typically end with typerExit()
|
||||
function typerCommit()
|
||||
local status = 0
|
||||
if mode == "save" then
|
||||
status = addBookmark(typerText)
|
||||
elseif mode == "replace" and typerText == "y" then
|
||||
status = replaceBookmark(currentSlot, makeBookmark(bookmarks[currentSlot]["name"]))
|
||||
elseif mode == "delete" and typerText == "y" then
|
||||
deleteBookmark(currentSlot)
|
||||
elseif mode == "rename" then
|
||||
editBookmark(currentSlot, "name", typerText)
|
||||
elseif mode == "filepath" then
|
||||
editBookmark(currentSlot, "path", typerText)
|
||||
end
|
||||
if status >= 0 then typerExit() end
|
||||
end
|
||||
|
||||
-- Exits the Typer without committing with custom scripts preceding it
|
||||
function typerExit()
|
||||
deactivateTyper()
|
||||
displayBookmarks()
|
||||
timer:resume()
|
||||
mode = "none"
|
||||
activateControls("bookmarker", bookmarkerControls, bookmarkerFlags)
|
||||
end
|
||||
|
||||
-- Starts the Typer with custom scripts preceding it
|
||||
function typerStart()
|
||||
if (mode == "save" or mode=="replace") and mp.get_property("path") == nil then
|
||||
abort(styleOn.."{\\c&H0000FF&}{\\b1}Can't find the media file to create the bookmark for")
|
||||
return -1
|
||||
end
|
||||
if (mode == "replace" or mode == "rename" or mode == "filepath" or mode == "delete") and not bookmarkExists(currentSlot) then
|
||||
abort(styleOn.."{\\c&H0000FF&}{\\b1}Can't find the bookmark at slot "..currentSlot)
|
||||
return -1
|
||||
end
|
||||
if (mode == "replace" and not confirmReplace) or (mode == "delete" and not confirmDelete) then
|
||||
typerText = "y"
|
||||
typerCommit()
|
||||
return
|
||||
end
|
||||
|
||||
deactivateControls("bookmarker", bookmarkerControls)
|
||||
timer:kill()
|
||||
activateTyper()
|
||||
if mode == "rename" then typerText = bookmarks[currentSlot]["name"] end
|
||||
if mode == "filepath" then typerText = bookmarks[currentSlot]["path"] end
|
||||
typerPos = typerText:len()
|
||||
typer("")
|
||||
end
|
||||
|
||||
-- Aborts the program with an optional error message
|
||||
function abort(message)
|
||||
mode = "none"
|
||||
moverExit(true)
|
||||
deactivateTyper()
|
||||
deactivateControls("bookmarker", bookmarkerControls)
|
||||
timer:kill()
|
||||
mp.osd_message(message)
|
||||
active = false
|
||||
end
|
||||
|
||||
-- Handles the state of the bookmarker
|
||||
function handler()
|
||||
if active then
|
||||
abort("")
|
||||
else
|
||||
activateControls("bookmarker", bookmarkerControls, bookmarkerFlags)
|
||||
loadBookmarks()
|
||||
displayBookmarks()
|
||||
timer:resume()
|
||||
active = true
|
||||
end
|
||||
end
|
||||
|
||||
mp.register_script_message("bookmarker-menu", handler)
|
||||
mp.register_script_message("bookmarker-quick-save", quickSave)
|
||||
mp.register_script_message("bookmarker-quick-load", quickLoad)
|
||||
33
mpv/scripts/copy-time.lua
Normal file
33
mpv/scripts/copy-time.lua
Normal file
@@ -0,0 +1,33 @@
|
||||
-- copy-time (Linux version)
|
||||
-- Requires xclip installed
|
||||
|
||||
-- Copies current timecode in HH:MM:SS.MS format to clipboard
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
-- Script adapted by Alex Rogers (https://github.com/linguisticmind)
|
||||
-- Modified from https://github.com/Arieleg/mpv-copyTime
|
||||
-- Released under GNU GPL 3.0
|
||||
|
||||
require "mp"
|
||||
|
||||
local function set_clipboard(text)
|
||||
command = string.format("echo -n %s | xclip -selection clipboard", text)
|
||||
mp.commandv("run", "/bin/bash", "-c", command)
|
||||
end
|
||||
|
||||
function copy_time()
|
||||
local time_pos = mp.get_property_number("time-pos")
|
||||
local time_in_seconds = time_pos
|
||||
local time_seg = time_pos % 60
|
||||
time_pos = time_pos - time_seg
|
||||
local time_hours = math.floor(time_pos / 3600)
|
||||
time_pos = time_pos - (time_hours * 3600)
|
||||
local time_minutes = time_pos/60
|
||||
time_seg,time_ms=string.format("%.03f", time_seg):match"([^.]*).(.*)"
|
||||
time = string.format("%02d:%02d:%02d.%s", time_hours, time_minutes, time_seg, time_ms)
|
||||
set_clipboard(time)
|
||||
mp.osd_message(string.format("Copied to clipboard: %s", time))
|
||||
end
|
||||
|
||||
-- the keybinding here is set to nil on purpose 'cause I modified the keybinding (in input.conf)
|
||||
mp.add_key_binding(nil, "copy-time", copy_time)
|
||||
58
mpv/scripts/cycle-commands.lua
Normal file
58
mpv/scripts/cycle-commands.lua
Normal file
@@ -0,0 +1,58 @@
|
||||
--[=====[
|
||||
script to cycle commands with a keybind, accomplished through script messages
|
||||
available at: https://github.com/CogentRedTester/mpv-scripts
|
||||
|
||||
syntax:
|
||||
script-message cycle-commands "command1" "command2" "command3"
|
||||
|
||||
The syntax of each command is identical to the standard input.conf syntax, but each command must be within
|
||||
a pair of double quotes.
|
||||
|
||||
Commands with mutiword arguments require you to send double quotes just like normal command syntax, however,
|
||||
you will need to escape the quotes with a backslash so that they are sent as part of the string.
|
||||
Semicolons also work exactly like they do normally, so you can easily send multiple commands each cycle.
|
||||
|
||||
Here is an example of a standard input.conf entry:
|
||||
|
||||
script-message cycle-commands "show-text one 1000 ; print-text two" "show-text \"three four\""
|
||||
|
||||
This would, on keypress one, print 'one' to the OSD for 1 second and 'two' to the console,
|
||||
and on keypress two 'three four' would be printed to the OSD.
|
||||
Notice how the quotation marks around 'three four' are escaped using backslashes.
|
||||
All other syntax details should be exactly the same as usual input commands.
|
||||
|
||||
There are no limits to the number of commands, and the script message can be used as often as one wants,
|
||||
the script stores the current iteration for each unique cycle command, so there should be no overlap
|
||||
unless one binds the exact same command string (including spacing)
|
||||
]=====]--
|
||||
|
||||
local mp = require 'mp'
|
||||
local msg = require 'mp.msg'
|
||||
|
||||
--keeps track of the current position for a specific cycle
|
||||
local iterators = {}
|
||||
|
||||
--main function to identify and run the cycles
|
||||
local function main(...)
|
||||
local commands = {...}
|
||||
|
||||
--to identify the specific cycle we'll concatenate all the strings together to use as our table key
|
||||
local str = table.concat(commands, " | ")
|
||||
msg.trace('recieved:', str)
|
||||
|
||||
if iterators[str] == nil then
|
||||
msg.debug('unknown cycle, creating iterator')
|
||||
iterators[str] = 1
|
||||
else
|
||||
iterators[str] = iterators[str] + 1
|
||||
if iterators[str] > #commands then iterators[str] = 1 end
|
||||
end
|
||||
|
||||
--mp.command should run the commands exactly as if they were entered in input.conf.
|
||||
--This should provide universal support for all input.conf command syntax
|
||||
local cmd = commands[ iterators[str] ]
|
||||
msg.verbose('sending command:', cmd)
|
||||
mp.command(cmd)
|
||||
end
|
||||
|
||||
mp.register_script_message('cycle-commands', main)
|
||||
105
mpv/scripts/cycle-profile.lua
Normal file
105
mpv/scripts/cycle-profile.lua
Normal file
@@ -0,0 +1,105 @@
|
||||
--[[
|
||||
script to cycle profiles with a keybind, accomplished through script messages
|
||||
available at: https://github.com/CogentRedTester/mpv-scripts
|
||||
|
||||
syntax:
|
||||
script-message cycle-profiles "profile1;profile2;profile3"
|
||||
|
||||
You must use semicolons to separate the profiles, do not include any spaces that are not part of the profile name.
|
||||
The script will print the profile description to the screen when switching, if there is no profile description, then it just prints the name
|
||||
]]--
|
||||
|
||||
--change this to change what character separates the profile names
|
||||
seperator = ";"
|
||||
|
||||
msg = require 'mp.msg'
|
||||
|
||||
--splits the profiles string into an array of profile names
|
||||
--function taken from: https://stackoverflow.com/questions/1426954/split-string-in-lua/7615129#7615129
|
||||
function mysplit (inputstr, sep)
|
||||
if sep == nil then
|
||||
sep = "%s"
|
||||
end
|
||||
local t={}
|
||||
for str in string.gmatch(inputstr, "([^"..sep.."]+)") do
|
||||
table.insert(t, str)
|
||||
end
|
||||
return t
|
||||
end
|
||||
|
||||
--table of all available profiles and options
|
||||
profileList = mp.get_property_native('profile-list')
|
||||
|
||||
--keeps track of current profile for every unique cycle
|
||||
iterator = {}
|
||||
|
||||
--stores descriptions for profiles
|
||||
--once requested a description is stored here so it does not need to be found again
|
||||
profilesDescs = {}
|
||||
|
||||
--if trying to cycle to an unknown profile this function is run to find a description to print
|
||||
function findDesc(profile)
|
||||
msg.verbose('unknown profile ' .. profile .. ', searching for description')
|
||||
|
||||
for i = 1, #profileList, 1 do
|
||||
if profileList[i]['name'] == profile then
|
||||
msg.verbose('profile found')
|
||||
local desc = profileList[i]['profile-desc']
|
||||
|
||||
if desc ~= nil then
|
||||
msg.verbose('description found')
|
||||
profilesDescs[profile] = desc
|
||||
else
|
||||
msg.verbose('no description, will use name')
|
||||
profilesDescs[profile] = profile
|
||||
end
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
msg.verbose('profile not found')
|
||||
profilesDescs[profile] = "no profile '" .. profile .. "'"
|
||||
end
|
||||
|
||||
--prints the profile description to the OSD
|
||||
--if the profile has not been requested before during the session then it runs findDesc()
|
||||
function printProfileDesc(profile)
|
||||
local desc = profilesDescs[profile]
|
||||
if desc == nil then
|
||||
findDesc(profile)
|
||||
desc = profilesDescs[profile]
|
||||
end
|
||||
|
||||
msg.verbose('profile description: ' .. desc)
|
||||
mp.osd_message(desc)
|
||||
end
|
||||
|
||||
function main(profileStr)
|
||||
--if there is not already an iterator for this cycle then it creates one
|
||||
if iterator[profileStr] == nil then
|
||||
msg.verbose('unknown cycle, creating new iterator')
|
||||
iterator[profileStr] = 1
|
||||
end
|
||||
local i = iterator[profileStr]
|
||||
|
||||
--converts the string into an array of profile names
|
||||
local profiles = mysplit(profileStr, seperator)
|
||||
msg.verbose('cycling ' .. tostring(profiles))
|
||||
msg.verbose("number of profiles: " .. tostring(#profiles))
|
||||
|
||||
--sends the command to apply the profile
|
||||
msg.info("applying profile " .. profiles[i])
|
||||
mp.commandv('apply-profile', profiles[i])
|
||||
|
||||
--prints the profile description to the OSD
|
||||
printProfileDesc(profiles[i])
|
||||
|
||||
--moves the iterator
|
||||
iterator[profileStr] = iterator[profileStr] + 1
|
||||
if iterator[profileStr] > #profiles then
|
||||
msg.verbose('reached end of profiles, wrapping back to start')
|
||||
iterator[profileStr] = 1
|
||||
end
|
||||
end
|
||||
|
||||
mp.register_script_message('cycle-profiles', main)
|
||||
@@ -1,227 +0,0 @@
|
||||
# mpv-file-browser
|
||||
|
||||

|
||||
|
||||
This script allows users to browse and open files and folders entirely from within mpv. The script uses nothing outside the mpv API, so should work identically on all platforms. The browser can move up and down directories, start playing files and folders, or add them to the queue.
|
||||
|
||||
By default only file types compatible with mpv will be shown, but this can be changed in the config file.
|
||||
|
||||
This script requires at least **mpv v0.33**.
|
||||
|
||||
Originally, file-browser worked with versions of mpv going back to
|
||||
v0.31, you can find those older versions of file-browser in the
|
||||
[mpv-v0.31 branch](https://github.com/CogentRedTester/mpv-file-browser/tree/mpv-v0.31).
|
||||
That branch will no longer be receiving any feature updates,
|
||||
but I will try to fix any bugs that are reported on the issue
|
||||
tracker.
|
||||
|
||||
## Installation
|
||||
|
||||
### Basic
|
||||
|
||||
Clone this git repository into the mpv `~~/scripts` directory and
|
||||
change the name of the folder from `mpv-file-browser` to `file-browser`.
|
||||
You can then pull to receive updates.
|
||||
Alternatively, you can download the zip and extract the contents to `~~/scripts/file-browser`.
|
||||
`~~/` is the mpv config directory which is typically `~/.config/mpv/` on linux and `%APPDATA%/mpv/` on windows.
|
||||
|
||||
Create a `file_browser.conf` file in the `~~/script-opts/` directory and customise the [`root` option](#root-directory) for your
|
||||
system. The [`docs/file_browser.conf`](docs/file_browser.conf) file contains the full list of options and their defaults.
|
||||
|
||||
<details>
|
||||
<summary>Expected directory tree:</summary>
|
||||
|
||||
```
|
||||
~~/
|
||||
├── script-opts
|
||||
│ └── file-browser.conf
|
||||
└── scripts
|
||||
└── file-browser
|
||||
├── addons/
|
||||
├── docs/
|
||||
├── modules/
|
||||
├── screenshots/
|
||||
├── LICENSE
|
||||
├── main.lua
|
||||
└── README.md
|
||||
```
|
||||
</details>
|
||||
|
||||
### Advanced
|
||||
|
||||
To setup [custom keybinds](docs/custom-keybinds.md) enable the `custom_keybinds` option in `file_browser.conf` and
|
||||
create a `~~/script-opts/file-browser-keybinds.json` file. Do **not** copy the `file-browser-keybinds.json` file
|
||||
stored in this repository, that file is a collection of random examples, many of which are for completely different
|
||||
operating systems. Use them and the [docs](docs/custom-keybinds.md) to create your own collection of keybinds.
|
||||
|
||||
To setup [addons](addons/README.md) enable the `addons` option in `file_browser.conf` and place the addon files
|
||||
in the `~~/script-modules/file-browser-addons/` directory.
|
||||
|
||||
If you are not going to enable custom keybinds or addons then there is no reason to
|
||||
create `file-browser-keybinds.json` or `script-modules/file-browser-addons/`.
|
||||
|
||||
<details>
|
||||
<summary>Expected directory tree:</summary>
|
||||
|
||||
```
|
||||
~~/
|
||||
├── script-modules
|
||||
│ └── file-browser-addons
|
||||
│ ├── addon1.lua
|
||||
│ ├── addon2.lua
|
||||
│ └── etc.lua
|
||||
├── script-opts
|
||||
│ ├── file_browser.conf
|
||||
│ └── file-browser-keybinds.json
|
||||
└── scripts
|
||||
└── file-browser
|
||||
├── addons/
|
||||
├── docs/
|
||||
├── modules/
|
||||
├── screenshots/
|
||||
├── LICENSE
|
||||
├── main.lua
|
||||
└── README.md
|
||||
```
|
||||
</details>
|
||||
|
||||
## Keybinds
|
||||
|
||||
The following keybinds are set by default
|
||||
|
||||
| Key | Name | Description |
|
||||
|-------------|----------------------------------|-------------------------------------------------------------------------------|
|
||||
| MENU | browse-files | toggles the browser |
|
||||
| Ctrl+o | open-browser | opens the browser |
|
||||
| Alt+o | browse-directory/get-user-input | opens a dialogue box to type in a directory - requires [mpv-user-input](#mpv-user-input) when mpv < v0.38 |
|
||||
|
||||
The following dynamic keybinds are only set while the browser is open:
|
||||
|
||||
| Key | Name | Description |
|
||||
|-------------|---------------|-------------------------------------------------------------------------------|
|
||||
| ESC | close | closes the browser or clears the selection |
|
||||
| ENTER | play | plays the currently selected file or folder |
|
||||
| Shift+ENTER | play_append | appends the current file or folder to the playlist |
|
||||
| Alt+ENTER | play_autoload | loads playlist entries before and after the selected file (like autoload.lua) |
|
||||
| RIGHT | down_dir | enter the currently selected directory |
|
||||
| LEFT | up_dir | move to the parent directory |
|
||||
| DOWN | scroll_down | move selector down the list |
|
||||
| UP | scroll_up | move selector up the list |
|
||||
| PGDWN | page_down | move selector down the list by a page (the num_entries option) |
|
||||
| PGUP | page_up | move selector up the list by a page (the num_entries option) |
|
||||
| Shift+PGDWN | list_bottom | move selector to the bottom of the list |
|
||||
| Shift+PGUP | list_top | move selector to the top of the list |
|
||||
| HOME | goto_current | move to the directory of the currently playing file |
|
||||
| Shift+HOME | goto_root | move to the root directory |
|
||||
| Ctrl+r | reload | reload directory and reset cache |
|
||||
| s | select_mode | toggles multiselect mode |
|
||||
| S | select_item | toggles selection for the current item |
|
||||
| Ctrl+a | select_all | select all items in the current directory |
|
||||
|
||||
When attempting to play or append a subtitle file the script will instead load the subtitle track into the existing video.
|
||||
|
||||
The behaviour of the autoload keybind can be reversed with the `autoload` script-opt.
|
||||
By default the playlist will only be autoloaded if `Alt+ENTER` is used on a single file, however when the option is switched autoload will always be used on single files *unless* `Alt+ENTER` is used. Using autoload on a directory, or while appending an item, will not work.
|
||||
|
||||
## Root Directory
|
||||
|
||||
To accomodate for both windows and linux this script has its own virtual root directory where drives and file folders can be manually added. The root directory can only contain folders.
|
||||
|
||||
The root directory is set using the `root` option, which is a comma separated list of directories. Entries are sent through mpv's `expand-path` command. By default the only root value is the user's home folder:
|
||||
|
||||
`root=~/`
|
||||
|
||||
It is highly recommended that this be customised for the computer being used; [file_browser.conf](file_browser.conf) contains commented out suggestions for generic linux and windows systems. For example, my windows root looks like:
|
||||
|
||||
`root=~/,C:/,D:/,E:/,Z:/`
|
||||
|
||||
## Multi-Select
|
||||
|
||||
By default file-browser only opens/appends the single item that the cursor has selected.
|
||||
However, using the `s` keybinds specified above, it is possible to select multiple items to open all at once. Selected items are shown in a different colour to the cursor.
|
||||
When in multiselect mode the cursor changes colour and scrolling up and down the list will drag the current selection. If the original item was unselected, then dragging will select items, if the original item was selected, then dragging will unselect items.
|
||||
|
||||
When multiple items are selected using the open or append commands all selected files will be added to the playlist in the order they appear on the screen.
|
||||
The currently selected (with the cursor) file will be ignored, instead the first multi-selected item in the folder will follow replace/append behaviour as normal, and following selected items will be appended to the playlist afterwards in the order that they appear on the screen.
|
||||
|
||||
## Custom Keybinds
|
||||
|
||||
File-browser also supports custom keybinds. These keybinds send normal input commands, but the script will substitute characters in the command strings for specific values depending on the currently open directory, and currently selected item.
|
||||
This allows for a wide range of customised behaviour, such as loading additional audio tracks from the browser, or copying the path of the selected item to the clipboard.
|
||||
|
||||
To see how to enable and use custom keybinds, see [custom-keybinds.md](docs/custom-keybinds.md).
|
||||
|
||||
## Add-ons
|
||||
|
||||
Add-ons are ways to add extra features to file-browser, for example adding support for network file servers like ftp, or implementing virtual directories in the root like recently opened files.
|
||||
They can be enabled by setting `addon` script-opt to yes, and placing the addon file into the `~~/script-modules/file-browser-addons/` directory.
|
||||
|
||||
For a list of existing addons see the [wiki](https://github.com/CogentRedTester/mpv-file-browser/wiki/Addon-List).
|
||||
For instructions on writing your own addons see [addons.md](docs/addons.md).
|
||||
|
||||
## Script Messages
|
||||
|
||||
File-browser supports a small number of script messages that allow the user or other scripts to talk with the browser.
|
||||
|
||||
### `browse-directory`
|
||||
|
||||
`script-message browse-directory [directory]`
|
||||
|
||||
Opens the given directory in the browser. If the browser is currently closed it will be opened.
|
||||
|
||||
### `get-directory-contents`
|
||||
|
||||
`script-message get-directory-contents [directory] [response-string]`
|
||||
|
||||
Reads the given directory, and sends the resulting tables to the specified script-message in the format:
|
||||
|
||||
`script-message [response-string] [list] [opts]`
|
||||
|
||||
The [list](docs/addons.md#the-list-array)
|
||||
and [opts](docs/addons.md#the-opts-table)
|
||||
tables are formatted as json strings through the `mp.utils.format_json` function.
|
||||
See [addons.md](docs/addons.md) for how the tables are structured, and what each field means.
|
||||
The API_VERSION field of the `opts` table refers to what version of the addon API file browser is using.
|
||||
The `response-string` refers to an arbitrary script-message that the tables should be sent to.
|
||||
|
||||
This script-message allows other scripts to utilise file-browser's directory parsing capabilities, as well as those of the file-browser addons.
|
||||
|
||||
## Configuration
|
||||
|
||||
See [file_browser.conf](docs/file_browser.conf) for the full list of options and their default values.
|
||||
The file is placed in the `~~/script-opts/` folder.
|
||||
|
||||
## Conditional Auto-Profiles
|
||||
|
||||
file-browser provides a property that can be used with [conditional auto-profiles](https://mpv.io/manual/master/#conditional-auto-profiles)
|
||||
to detect when the browser is open.
|
||||
On mpv v0.36+ you should use the `user-data` property with the `file_browser/open` boolean.
|
||||
|
||||
Here is an example of an auto-profile that hides the OSC logo when using file-browser in an idle window:
|
||||
|
||||
```properties
|
||||
[hide-logo]
|
||||
profile-cond= idle_active and user_data.file_browser.open
|
||||
profile-restore=copy
|
||||
osc=no
|
||||
```
|
||||
|
||||
On older versions of mpv you can use the `file_browser-open` field of the `shared-script-properties` property:
|
||||
|
||||
```properties
|
||||
[hide-logo]
|
||||
profile-cond= idle_active and shared_script_properties["file_browser-open"] == "yes"
|
||||
profile-restore=copy
|
||||
osc=no
|
||||
```
|
||||
|
||||
See [#55](https://github.com/CogentRedTester/mpv-file-browser/issues/55) for more details on this.
|
||||
|
||||
## [mpv-user-input](https://github.com/CogentRedTester/mpv-user-input)
|
||||
|
||||
mpv-user-input is a script that provides an API to request text input from the user over the OSD.
|
||||
It was built using `console.lua` as a base, so supports almost all the same text input commands.
|
||||
If `user-input.lua` is loaded by mpv, and `user-input-module` is in the `~~/script-modules/` directory,
|
||||
then using `Alt+o` will open an input box that can be used to directly enter directories for file-browser to open.
|
||||
|
||||
Mpv v0.38 added the `mp.input` module, which means `mpv-user-input` is no-longer necessary from that version onwards.
|
||||
@@ -1,12 +0,0 @@
|
||||
# addons
|
||||
|
||||
Add-ons are ways to add extra features to file-browser, for example adding support for network file servers like ftp, or implementing virtual directories in the root like recently opened files.
|
||||
They can be enabled by setting `addon` script-opt to yes, and placing the addon file into the `~~/script-modules/file-browser-addons/` directory.
|
||||
|
||||
Browsing filesystems provided by add-ons should feel identical to the normal handling of the script,
|
||||
but they may require extra commandline tools be installed.
|
||||
|
||||
Since addons are loaded programatically from the addon directory it is possible for anyone to write their own addon.
|
||||
Instructions on how to do this are available [here](../docs/addons.md).
|
||||
|
||||
For a list of available addons see the [wiki](https://github.com/CogentRedTester/mpv-file-browser/wiki/Addon-List).
|
||||
@@ -1,89 +0,0 @@
|
||||
--[[
|
||||
An addon for mpv-file-browser which adds support for apache http directory indexes
|
||||
]]--
|
||||
|
||||
local mp = require 'mp'
|
||||
local msg = require 'mp.msg'
|
||||
local utils = require 'mp.utils'
|
||||
local fb = require "file-browser"
|
||||
|
||||
--decodes a URL address
|
||||
--this piece of code was taken from: https://stackoverflow.com/questions/20405985/lua-decodeuri-luvit/20406960#20406960
|
||||
local decodeURI
|
||||
do
|
||||
local char, gsub, tonumber = string.char, string.gsub, tonumber
|
||||
local function _(hex) return char(tonumber(hex, 16)) end
|
||||
|
||||
function decodeURI(s)
|
||||
s = gsub(s, '%%(%x%x)', _)
|
||||
return s
|
||||
end
|
||||
end
|
||||
|
||||
local apache = {
|
||||
priority = 80,
|
||||
api_version = "1.1.0"
|
||||
}
|
||||
|
||||
function apache:can_parse(name)
|
||||
return name:find("^https?://")
|
||||
end
|
||||
|
||||
--send curl errors through the browser empty_text
|
||||
function apache:send_error(str)
|
||||
return {}, {empty_text = "curl error: "..str}
|
||||
end
|
||||
|
||||
local function execute(args)
|
||||
msg.trace(utils.to_string(args))
|
||||
local _, cmd = fb.get_parse_state():yield(
|
||||
mp.command_native_async({
|
||||
name = "subprocess",
|
||||
playback_only = false,
|
||||
capture_stdout = true,
|
||||
capture_stderr = true,
|
||||
args = args
|
||||
}, fb.coroutine.callback())
|
||||
)
|
||||
return cmd
|
||||
end
|
||||
|
||||
function apache:parse(directory)
|
||||
msg.verbose(directory)
|
||||
|
||||
local test = execute({"curl", "-k", "-l", "-I", directory})
|
||||
local response = test.stdout:match("(%d%d%d [^\n\r]+)")
|
||||
if test.stdout:match("Content%-Type: ([^\r\n/]+)") ~= "text" then return nil end
|
||||
if response ~= "200 OK" then return self:send_error(response) end
|
||||
|
||||
local html = execute({"curl", "-k", "-l", directory})
|
||||
if html.status ~= 0 then return self:send_error(tostring(html.status))
|
||||
elseif not html.stdout:find("%[PARENTDIR%]") then return nil end
|
||||
|
||||
html = html.stdout
|
||||
local list = {}
|
||||
for str in string.gmatch(html, "[^\r\n]+") do
|
||||
local valid = true
|
||||
if str:sub(1,4) ~= "<tr>" then valid = false end
|
||||
|
||||
local link = str:match('href="(.-)"')
|
||||
local alt = str:match('alt="%[(.-)%]"')
|
||||
|
||||
if valid and not alt or not link then valid = false end
|
||||
if valid and alt == "PARENTDIR" or alt == "ICO" then valid = false end
|
||||
if valid and link:find("[:?<>|]") then valid = false end
|
||||
|
||||
local is_dir = (alt == "DIR")
|
||||
if valid and is_dir and not self.valid_dir(link) then valid = false end
|
||||
if valid and not is_dir and not self.valid_file(link) then valid = false end
|
||||
|
||||
if valid then
|
||||
msg.trace(alt..": "..link)
|
||||
table.insert(list, { name = link, type = (is_dir and "dir" or "file"), label = decodeURI(link) })
|
||||
end
|
||||
end
|
||||
|
||||
return list, {filtered = true, directory_label = decodeURI(directory)}
|
||||
end
|
||||
|
||||
return apache
|
||||
@@ -1,191 +0,0 @@
|
||||
--[[
|
||||
An addon for mpv-file-browser which adds a Favourites path that can be loaded from the ROOT
|
||||
]]--
|
||||
|
||||
local mp = require "mp"
|
||||
local msg = require "mp.msg"
|
||||
local utils = require "mp.utils"
|
||||
local save_path = mp.command_native({"expand-path", "~~/script-opts/file_browser_favourites.txt"})
|
||||
do
|
||||
local file = io.open(save_path, "a+")
|
||||
if not file then
|
||||
msg.error("cannot access file", ("%q"):format(save_path), "make sure that the directory exists")
|
||||
return {}
|
||||
end
|
||||
file:close()
|
||||
end
|
||||
|
||||
local favourites = nil
|
||||
local favs = {
|
||||
api_version = "1.4.0",
|
||||
priority = 30,
|
||||
cursor = 1
|
||||
}
|
||||
|
||||
local use_virtual_directory = true
|
||||
local full_paths = {}
|
||||
|
||||
local function create_favourite_object(str)
|
||||
local item = {
|
||||
type = str:sub(-1) == "/" and "dir" or "file",
|
||||
path = str,
|
||||
redirect = not use_virtual_directory,
|
||||
name = str:match("([^/]+/?)$")
|
||||
}
|
||||
full_paths[str:match("([^/]+)/?$")] = str
|
||||
return item
|
||||
end
|
||||
|
||||
function favs:setup()
|
||||
self:register_root_item('Favourites/')
|
||||
end
|
||||
|
||||
local function update_favourites()
|
||||
favourites = {}
|
||||
|
||||
local file = io.open(save_path, "r")
|
||||
if not file then return end
|
||||
|
||||
for str in file:lines() do
|
||||
table.insert(favourites, create_favourite_object(str))
|
||||
end
|
||||
file:close()
|
||||
end
|
||||
|
||||
function favs:can_parse(directory)
|
||||
return directory:find("Favourites/") == 1
|
||||
end
|
||||
|
||||
function favs:parse(directory)
|
||||
if not favourites then update_favourites() end
|
||||
if directory == "Favourites/" then
|
||||
local opts = {
|
||||
filtered = true,
|
||||
sorted = true
|
||||
}
|
||||
if self.cursor ~= 1 then opts.selected_index = self.cursor ; self.cursor = 1 end
|
||||
return favourites, opts
|
||||
end
|
||||
|
||||
if use_virtual_directory then
|
||||
-- converts the relative favourite path into a full path
|
||||
local name = directory:match("Favourites/([^/]+)/?")
|
||||
|
||||
local _, finish = directory:find("Favourites/([^/]+/?)")
|
||||
local full_path = (full_paths[name] or "")..directory:sub(finish+1)
|
||||
local list, opts = self:defer(full_path or "")
|
||||
|
||||
if not list then return nil end
|
||||
opts.id = self:get_id()
|
||||
if opts.directory_label then
|
||||
opts.directory_label = opts.directory_label:gsub(full_paths[name], "Favourites/"..name..'/')
|
||||
if opts.directory_label:find("Favourites/") ~= 1 then opts.directory_label = nil end
|
||||
end
|
||||
|
||||
for _, item in ipairs(list) do
|
||||
if not item.path then item.redirect = false end
|
||||
item.path = item.path or full_path..item.name
|
||||
end
|
||||
|
||||
return list, opts
|
||||
end
|
||||
|
||||
local path = full_paths[ directory:match("([^/]+/?)$") or "" ]
|
||||
|
||||
local list, opts = self:defer(path)
|
||||
if not list then return nil end
|
||||
opts.directory = opts.directory or path
|
||||
return list, opts
|
||||
end
|
||||
|
||||
local function get_favourite(path)
|
||||
for index, value in ipairs(favourites) do
|
||||
if value.path == path then return index, value end
|
||||
end
|
||||
end
|
||||
|
||||
--update the browser with new contents of the file
|
||||
local function update_browser()
|
||||
if favs.get_directory():find("[fF]avourites/") then
|
||||
if favs.get_directory():find("[fF]avourites/$") then
|
||||
local cursor = favs.get_selected_index()
|
||||
favs.rescan()
|
||||
favs.set_selected_index(cursor)
|
||||
favs.redraw()
|
||||
else
|
||||
favs.clear_cache()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--write the contents of favourites to the file
|
||||
local function write_to_file()
|
||||
local file = io.open(save_path, "w+")
|
||||
if not file then return msg.error(file, "could not open favourites file") end
|
||||
for _, item in ipairs(favourites) do
|
||||
file:write(string.format("%s\n", item.path))
|
||||
end
|
||||
file:close()
|
||||
end
|
||||
|
||||
local function add_favourite(path)
|
||||
if get_favourite(path) then return end
|
||||
update_favourites()
|
||||
table.insert(favourites, create_favourite_object(path))
|
||||
write_to_file()
|
||||
end
|
||||
|
||||
local function remove_favourite(path)
|
||||
update_favourites()
|
||||
local index = get_favourite(path)
|
||||
if not index then return end
|
||||
table.remove(favourites, index)
|
||||
write_to_file()
|
||||
end
|
||||
|
||||
local function move_favourite(path, direction)
|
||||
update_favourites()
|
||||
local index, item = get_favourite(path)
|
||||
if not index or not favourites[index + direction] then return end
|
||||
|
||||
favourites[index] = favourites[index + direction]
|
||||
favourites[index + direction] = item
|
||||
write_to_file()
|
||||
end
|
||||
|
||||
local function toggle_favourite(cmd, state, co)
|
||||
local path = favs.get_full_path(state.list[state.selected], state.directory)
|
||||
|
||||
if state.directory:find("[fF]avourites/$") then remove_favourite(path)
|
||||
else add_favourite(path) end
|
||||
update_browser()
|
||||
end
|
||||
|
||||
local function move_key(cmd, state, co)
|
||||
if not state.directory:find("[fF]avourites/") then return false end
|
||||
local path = favs.get_full_path(state.list[state.selected], state.directory)
|
||||
|
||||
local cursor = favs.get_selected_index()
|
||||
if cmd.name == favs:get_id().."/move_up" then
|
||||
move_favourite(path, -1)
|
||||
favs.set_selected_index(cursor-1)
|
||||
else
|
||||
move_favourite(path, 1)
|
||||
favs.set_selected_index(cursor+1)
|
||||
end
|
||||
update_browser()
|
||||
end
|
||||
|
||||
update_favourites()
|
||||
mp.register_script_message("favourites/add_favourite", add_favourite)
|
||||
mp.register_script_message("favourites/remove_favourite", remove_favourite)
|
||||
mp.register_script_message("favourites/move_up", function(path) move_favourite(path, -1) end)
|
||||
mp.register_script_message("favourites/move_down", function(path) move_favourite(path, 1) end)
|
||||
|
||||
favs.keybinds = {
|
||||
{ "F", "toggle_favourite", toggle_favourite, {}, },
|
||||
{ "Ctrl+UP", "move_up", move_key, {repeatable = true} },
|
||||
{ "Ctrl+DOWN", "move_down", move_key, {repeatable = true} },
|
||||
}
|
||||
|
||||
return favs
|
||||
@@ -1,104 +0,0 @@
|
||||
--[[
|
||||
An addon for mpv-file-browser for searching the current directory
|
||||
Available at: https://github.com/CogentRedTester/mpv-file-browser/tree/master/addons
|
||||
|
||||
Requires mpv-user-input: https://github.com/CogentRedTester/mpv-user-input
|
||||
|
||||
Keybinds:
|
||||
Ctrl+f open search box
|
||||
Ctrl+F open advanced search box (supports Lua patterns)
|
||||
n cycle to next valid item
|
||||
]]--
|
||||
|
||||
local msg = require "mp.msg"
|
||||
local fb = require "file-browser"
|
||||
local input_loaded, input = pcall(require, "mp.input")
|
||||
local user_input_loaded, user_input = pcall(require, "user-input-module")
|
||||
|
||||
local find = {
|
||||
api_version = "1.3.0"
|
||||
}
|
||||
local latest_coroutine = nil
|
||||
local global_fb_state = getmetatable(fb.get_state()).__original
|
||||
|
||||
local function compare(name, query)
|
||||
if name:find(query) then return true end
|
||||
if name:lower():find(query) then return true end
|
||||
if name:upper():find(query) then return true end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
local function main(key, state, co)
|
||||
if not state.list then return false end
|
||||
|
||||
local text
|
||||
if key.name == "find/find" then text = "Find: enter search string"
|
||||
else text = "Find: enter advanced search string" end
|
||||
|
||||
if input_loaded then
|
||||
input.get({
|
||||
prompt = text .. "\n>",
|
||||
id = "file-browser/find",
|
||||
submit = fb.coroutine.callback(),
|
||||
})
|
||||
elseif user_input_loaded then
|
||||
user_input.get_user_input( fb.coroutine.callback(), { text = text, id = "find", replace = true } )
|
||||
end
|
||||
|
||||
local query, error = coroutine.yield()
|
||||
if input_loaded then input.terminate() end
|
||||
if not query then return msg.debug(error) end
|
||||
|
||||
-- allow the directory to be changed before this point
|
||||
local list = fb.get_list()
|
||||
local parse_id = global_fb_state.co
|
||||
|
||||
if key.name == "find/find" then
|
||||
query = fb.pattern_escape(query)
|
||||
end
|
||||
|
||||
local results = {}
|
||||
|
||||
for index, item in ipairs(list) do
|
||||
if compare(item.label or item.name, query) then
|
||||
table.insert(results, index)
|
||||
end
|
||||
end
|
||||
|
||||
if (#results < 1) then
|
||||
msg.warn("No matching items for '"..query.."'")
|
||||
return
|
||||
end
|
||||
|
||||
--keep cycling through the search results if any are found
|
||||
--putting this into a separate coroutine removes any passthrough ambiguity
|
||||
--the final return statement should return to `step_find` not any other function
|
||||
fb.coroutine.run(function()
|
||||
latest_coroutine = coroutine.running()
|
||||
while (true) do
|
||||
for _, index in ipairs(results) do
|
||||
fb.set_selected_index(index)
|
||||
coroutine.yield(true)
|
||||
|
||||
if parse_id ~= global_fb_state.co then
|
||||
latest_coroutine = nil
|
||||
return false
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
local function step_find()
|
||||
if not latest_coroutine then return false end
|
||||
return fb.coroutine.resume_err(latest_coroutine)
|
||||
end
|
||||
|
||||
find.keybinds = {
|
||||
{"Ctrl+f", "find", main, {}},
|
||||
{"Ctrl+F", "find_advanced", main, {}},
|
||||
{"n", "next", step_find, {}},
|
||||
}
|
||||
|
||||
return find
|
||||
@@ -1,86 +0,0 @@
|
||||
--[[
|
||||
An addon for mpv-file-browser which adds support for ftp servers
|
||||
]]--
|
||||
|
||||
local mp = require 'mp'
|
||||
local msg = require 'mp.msg'
|
||||
local utils = require 'mp.utils'
|
||||
local fb = require 'file-browser'
|
||||
|
||||
local ftp = {
|
||||
priority = 100,
|
||||
api_version = "1.1.0"
|
||||
}
|
||||
|
||||
function ftp:can_parse(directory)
|
||||
return directory:sub(1, 6) == "ftp://"
|
||||
end
|
||||
|
||||
--in my experience curl has been somewhat unreliable when it comes to ftp requests
|
||||
--this fuction retries the request a few times just in case
|
||||
local function execute(args)
|
||||
msg.debug(utils.to_string(args))
|
||||
local _, cmd = fb.get_parse_state():yield(
|
||||
mp.command_native_async({
|
||||
name = "subprocess",
|
||||
playback_only = false,
|
||||
capture_stdout = true,
|
||||
capture_stderr = true,
|
||||
args = args
|
||||
}, fb.coroutine.callback())
|
||||
)
|
||||
return cmd
|
||||
end
|
||||
|
||||
-- encodes special characters using the URL percent encoding format
|
||||
function urlEncode(url)
|
||||
local domain, path = string.match(url, '(ftp://[^/]-/)(.*)')
|
||||
if not path then return url end
|
||||
|
||||
-- these are the unreserved URI characters according to RFC 3986
|
||||
-- https://www.rfc-editor.org/rfc/rfc3986#section-2.3
|
||||
path = string.gsub(path, '[^%w.~_%-]', function(c)
|
||||
return ('%%%x'):format(string.byte(c))
|
||||
end)
|
||||
return domain..path
|
||||
end
|
||||
|
||||
function ftp:parse(directory)
|
||||
msg.verbose(directory)
|
||||
|
||||
local ftp = execute({"curl", "-k", "-g", "--retry", "4", urlEncode(directory)})
|
||||
|
||||
local entries = execute({"curl", "-k", "-g", "-l", "--retry", "4", urlEncode(directory)})
|
||||
|
||||
if entries.status == 28 then
|
||||
msg.error(entries.stderr)
|
||||
elseif entries.status ~= 0 or ftp.status ~= 0 then
|
||||
msg.error(entries.stderr)
|
||||
return
|
||||
end
|
||||
|
||||
local response = {}
|
||||
for str in string.gmatch(ftp.stdout, "[^\r\n]+") do
|
||||
table.insert(response, str)
|
||||
end
|
||||
|
||||
local list = {}
|
||||
local i = 1
|
||||
for str in string.gmatch(entries.stdout, "[^\r\n]+") do
|
||||
if str and response[i] then
|
||||
msg.trace(str .. ' | ' .. response[i])
|
||||
|
||||
if response[i]:sub(1,1) == "d" then
|
||||
table.insert(list, { name = str..'/', type = "dir" })
|
||||
else
|
||||
table.insert(list, { name = str, type = "file" })
|
||||
end
|
||||
|
||||
i = i+1
|
||||
end
|
||||
end
|
||||
|
||||
return list
|
||||
end
|
||||
|
||||
return ftp
|
||||
@@ -1,27 +0,0 @@
|
||||
--[[
|
||||
An addon for mpv-file-browser which displays ~/ for the home directory instead of the full path
|
||||
]]--
|
||||
|
||||
local mp = require "mp"
|
||||
local fb = require "file-browser"
|
||||
|
||||
local home = fb.fix_path(mp.command_native({"expand-path", "~/"}), true)
|
||||
|
||||
local home_label = {
|
||||
priority = 100,
|
||||
api_version = "1.0.0"
|
||||
}
|
||||
|
||||
function home_label:can_parse(directory)
|
||||
return directory:sub(1, home:len()) == home
|
||||
end
|
||||
|
||||
function home_label:parse(directory)
|
||||
local list, opts = self:defer(directory)
|
||||
if (not opts.directory or opts.directory == directory) and not opts.directory_label then
|
||||
opts.directory_label = "~/"..(directory:sub(home:len()+1) or "")
|
||||
end
|
||||
return list, opts
|
||||
end
|
||||
|
||||
return home_label
|
||||
@@ -1,56 +0,0 @@
|
||||
--[[
|
||||
An addon for mpv-file-browser which stores the last opened directory and
|
||||
sets it as the opened directory the next time mpv is opened.
|
||||
|
||||
Available at: https://github.com/CogentRedTester/mpv-file-browser/tree/master/addons
|
||||
]]--
|
||||
|
||||
local mp = require 'mp'
|
||||
local msg = require 'mp.msg'
|
||||
|
||||
local fb = require 'file-browser'
|
||||
|
||||
local state_file = mp.command_native({'expand-path', '~~state/last_opened_directory'})
|
||||
msg.verbose('using', state_file)
|
||||
|
||||
local function write_directory(directory)
|
||||
local file = io.open(state_file, 'w+')
|
||||
|
||||
if not file then return msg.error('could not open', state_file, 'for writing') end
|
||||
|
||||
directory = directory or fb.get_directory()
|
||||
msg.verbose('writing', directory, 'to', state_file)
|
||||
file:write(directory)
|
||||
file:close()
|
||||
end
|
||||
|
||||
|
||||
local addon = {
|
||||
api_version = '1.7.0',
|
||||
priority = 0,
|
||||
}
|
||||
|
||||
function addon:setup()
|
||||
local file = io.open(state_file, "r")
|
||||
if not file then
|
||||
return msg.error('failed to open', state_file, 'for reading')
|
||||
end
|
||||
|
||||
local dir = file:read("*a")
|
||||
msg.verbose('setting default directory to', dir)
|
||||
fb.browse_directory(dir, false)
|
||||
file:close()
|
||||
end
|
||||
|
||||
function addon:can_parse(dir, parse_state)
|
||||
if parse_state.source == 'browser' then write_directory(dir) end
|
||||
return false
|
||||
end
|
||||
|
||||
function addon:parse()
|
||||
return nil
|
||||
end
|
||||
|
||||
mp.register_event('shutdown', function() write_directory() end)
|
||||
|
||||
return addon
|
||||
@@ -1,57 +0,0 @@
|
||||
--[[
|
||||
An addon for mpv-file-browser which uses the Linux ls command to parse native directories
|
||||
This behaves near identically to the native parser, but IO is done asynchronously.
|
||||
|
||||
Available at: https://github.com/CogentRedTester/mpv-file-browser/tree/master/addons
|
||||
]]--
|
||||
|
||||
local mp = require "mp"
|
||||
local msg = require "mp.msg"
|
||||
local fb = require "file-browser"
|
||||
|
||||
local ls = {
|
||||
priority = 109,
|
||||
api_version = "1.1.0",
|
||||
name = "ls",
|
||||
keybind_name = "file"
|
||||
}
|
||||
|
||||
local function command(args, parse_state)
|
||||
local _, cmd = parse_state:yield(
|
||||
mp.command_native_async({
|
||||
name = "subprocess",
|
||||
playback_only = false,
|
||||
capture_stdout = true,
|
||||
capture_stderr = true,
|
||||
args = args
|
||||
}, fb.coroutine.callback())
|
||||
)
|
||||
|
||||
return cmd.status == 0 and cmd.stdout or nil
|
||||
end
|
||||
|
||||
function ls:can_parse(directory)
|
||||
return directory ~= '' and not fb.get_protocol(directory)
|
||||
end
|
||||
|
||||
function ls:parse(directory, parse_state)
|
||||
local list = {}
|
||||
local files = command({"ls", "-1", "-p", "-A", "-N", "--zero", directory}, parse_state)
|
||||
|
||||
if not files then return nil end
|
||||
|
||||
for str in files:gmatch("%Z+") do
|
||||
local is_dir = str:sub(-1) == "/"
|
||||
msg.trace(str)
|
||||
|
||||
if is_dir and fb.valid_dir(str) then
|
||||
table.insert(list, {name = str, type = "dir"})
|
||||
elseif fb.valid_file(str) then
|
||||
table.insert(list, {name = str, type = "file"})
|
||||
end
|
||||
end
|
||||
|
||||
return list, {filtered = true}
|
||||
end
|
||||
|
||||
return ls
|
||||
@@ -1,54 +0,0 @@
|
||||
--[[
|
||||
An addon for mpv-file-browser which adds support for m3u playlists
|
||||
|
||||
If the first entry of a playlist isn't working it is because some playlists are created with random invisible unicode in the first line
|
||||
Vim makes it easy to detect these
|
||||
|
||||
This addon requires that my API mpv-read-file be available in ~~/script-modules/
|
||||
https://github.com/CogentRedTester/mpv-read-file
|
||||
]]--
|
||||
|
||||
local rf = require "read-file"
|
||||
|
||||
local m3u = {
|
||||
priority = 100,
|
||||
api_version = "1.0.0",
|
||||
name = "m3u"
|
||||
}
|
||||
|
||||
local full_paths = {}
|
||||
|
||||
function m3u:setup()
|
||||
self.register_parseable_extension("m3u")
|
||||
self.register_parseable_extension("m3u8")
|
||||
end
|
||||
|
||||
function m3u:can_parse(directory)
|
||||
return directory:find("m3u8?/?$")
|
||||
end
|
||||
|
||||
function m3u:parse(directory)
|
||||
directory = directory:gsub("/$", "")
|
||||
local list = {}
|
||||
|
||||
local path = full_paths[ directory ] or directory
|
||||
local playlist = rf.get_file_handler( path )
|
||||
|
||||
--if we can't read the path then stop here
|
||||
if not playlist then return {}, {sorted = true, filtered = true, empty_text = "Could not read filepath"} end
|
||||
|
||||
local parent = self.fix_path(path:match("^(.+/[^/]+)/"), true)
|
||||
|
||||
local lines = playlist:read("*a")
|
||||
|
||||
for item in lines:gmatch("[^%c]+") do
|
||||
item = self.fix_path(item)
|
||||
local fullpath = self.join_path(parent, item)
|
||||
|
||||
local name = ( self.get_protocol(item) and item or fullpath:match("([^/]+)/?$") )
|
||||
table.insert(list, {name = name, path = fullpath, type = "file"})
|
||||
end
|
||||
return list, {filtered = true, sorted = true}
|
||||
end
|
||||
|
||||
return m3u
|
||||
@@ -1,81 +0,0 @@
|
||||
--[[
|
||||
An addon for mpv-file-browser which uses powershell commands to parse native directories
|
||||
|
||||
This is slower than the default parser for local drives, but faster for network drives
|
||||
The drive_letters array below is used to list the drives to use this parser for
|
||||
]]--
|
||||
|
||||
--list the drive letters to use here (case sensitive)
|
||||
local drive_letters = {
|
||||
"Y", "Z"
|
||||
}
|
||||
|
||||
local mp = require "mp"
|
||||
local msg = require "mp.msg"
|
||||
local fb = require "file-browser"
|
||||
|
||||
local wn = {
|
||||
priority = 109,
|
||||
api_version = "1.1.0",
|
||||
name = "powershell",
|
||||
keybind_name = "file"
|
||||
}
|
||||
|
||||
local drives = {}
|
||||
for _, letter in ipairs(drive_letters) do
|
||||
drives[letter] = true
|
||||
end
|
||||
|
||||
local function command(args, parse_state)
|
||||
local _, cmd = parse_state:yield(
|
||||
mp.command_native_async({
|
||||
name = "subprocess",
|
||||
playback_only = false,
|
||||
capture_stdout = true,
|
||||
capture_stderr = true,
|
||||
args = args
|
||||
}, fb.coroutine.callback())
|
||||
)
|
||||
|
||||
return cmd.status == 0 and cmd.stdout or nil, cmd.stderr
|
||||
end
|
||||
|
||||
function wn:can_parse(directory)
|
||||
return directory ~= '' and not self.get_protocol(directory) and drives[ directory:sub(1,1) ]
|
||||
end
|
||||
|
||||
function wn:parse(directory, parse_state)
|
||||
local list = {}
|
||||
local files, err = command({"powershell", "-noprofile", "-command", [[
|
||||
$dirs = Get-ChildItem -LiteralPath ]]..string.format("%q", directory)..[[ -Directory
|
||||
$files = Get-ChildItem -LiteralPath ]]..string.format("%q", directory)..[[ -File
|
||||
|
||||
foreach ($n in $dirs.Name) {
|
||||
$n += "/"
|
||||
$u8clip = [System.Text.Encoding]::UTF8.GetBytes($n)
|
||||
[Console]::OpenStandardOutput().Write($u8clip, 0, $u8clip.Length)
|
||||
Write-Host ""
|
||||
}
|
||||
|
||||
foreach ($n in $files.Name) {
|
||||
$u8clip = [System.Text.Encoding]::UTF8.GetBytes($n)
|
||||
[Console]::OpenStandardOutput().Write($u8clip, 0, $u8clip.Length)
|
||||
Write-Host ""
|
||||
}
|
||||
]]}, parse_state)
|
||||
|
||||
if not files then msg.debug(err) ; return nil end
|
||||
|
||||
for str in files:gmatch("[^\n\r]+") do
|
||||
local is_dir = str:sub(-1) == "/"
|
||||
if is_dir and self.valid_dir(str) then
|
||||
table.insert(list, {name = str, type = "dir"})
|
||||
elseif self.valid_file(str) then
|
||||
table.insert(list, {name = str, type = "file"})
|
||||
end
|
||||
end
|
||||
|
||||
return self.sort(list), {filtered = true, sorted = true}
|
||||
end
|
||||
|
||||
return wn
|
||||
@@ -1,54 +0,0 @@
|
||||
--[[
|
||||
An addon that loads root items from a `~~/script-opts/file-browser-root.json` file.
|
||||
The contents of this file will override the root script-opt.
|
||||
|
||||
The json file takes the form of a list array as defined by the addon API:
|
||||
https://github.com/CogentRedTester/mpv-file-browser/blob/master/addons/addons.md#the-list-array
|
||||
|
||||
The main purpose of this addon is to allow for users to customise the appearance of their root items
|
||||
using the label or ass fields:
|
||||
|
||||
[
|
||||
{ "name": "Favourites/" },
|
||||
{ "label": "~/", "name": "C:/Users/User/" },
|
||||
{ "label": "1TB HDD", "name": "D:/" },
|
||||
{ "ass": "{\\c&H007700&}Green Text", "name": "E:/" },
|
||||
{ "label": "FTP Server", name: "ftp://user:password@server.com/" }
|
||||
]
|
||||
|
||||
Make sure local directories always end with `/`.
|
||||
`path` and `name` behave the same in the root but either name or label should have a value.
|
||||
ASS styling codes: https://aegi.vmoe.info/docs/3.0/ASS_Tags/
|
||||
]]
|
||||
|
||||
local mp = require 'mp'
|
||||
local msg = require 'mp.msg'
|
||||
local utils = require 'mp.utils'
|
||||
local fb = require 'file-browser'
|
||||
|
||||
-- loads the root json file
|
||||
local config_path = mp.command_native({'expand-path', '~~/script-opts/file-browser-root.json'})
|
||||
|
||||
local file = io.open(config_path, 'r')
|
||||
if not file then
|
||||
msg.error('failed to read file', config_path)
|
||||
return
|
||||
end
|
||||
|
||||
local root_config = utils.parse_json(file:read("*a"))
|
||||
if not root_config then
|
||||
msg.error('failed to parse contents of', config_path, '- Check the syntax is correct.')
|
||||
return
|
||||
end
|
||||
|
||||
local function setup()
|
||||
for i, item in ipairs(root_config) do
|
||||
fb.register_root_item(item, item.priority)
|
||||
end
|
||||
end
|
||||
|
||||
return {
|
||||
api_version = '1.4.0',
|
||||
setup = setup,
|
||||
priority = -1000,
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
--[[
|
||||
An addon for file-browser which decodes URLs so that they are more readable
|
||||
]]
|
||||
|
||||
local urldecode = {
|
||||
priority = 5,
|
||||
api_version = "1.0.0"
|
||||
}
|
||||
|
||||
--decodes a URL address
|
||||
--this piece of code was taken from: https://stackoverflow.com/questions/20405985/lua-decodeuri-luvit/20406960#20406960
|
||||
local decodeURI
|
||||
do
|
||||
local char, gsub, tonumber = string.char, string.gsub, tonumber
|
||||
local function _(hex) return char(tonumber(hex, 16)) end
|
||||
|
||||
function decodeURI(s)
|
||||
s = gsub(s, '%%(%x%x)', _)
|
||||
return s
|
||||
end
|
||||
end
|
||||
|
||||
function urldecode:can_parse(directory)
|
||||
return self.get_protocol(directory)
|
||||
end
|
||||
|
||||
function urldecode:parse(directory)
|
||||
local list, opts = self:defer(directory)
|
||||
if opts.directory and not self.get_protocol(opts.directory) then return list, opts end
|
||||
|
||||
opts.directory_label = decodeURI(opts.directory_label or (opts.directory or directory))
|
||||
return list, opts
|
||||
end
|
||||
|
||||
return urldecode
|
||||
@@ -1,97 +0,0 @@
|
||||
--[[
|
||||
An addon for mpv-file-browser which uses the Windows dir command to parse native directories
|
||||
This behaves near identically to the native parser, but IO is done asynchronously.
|
||||
|
||||
Available at: https://github.com/CogentRedTester/mpv-file-browser/tree/master/addons
|
||||
]]--
|
||||
|
||||
local mp = require "mp"
|
||||
local msg = require "mp.msg"
|
||||
local fb = require "file-browser"
|
||||
|
||||
--this is a LuaJit module this addon will not load if not using LuaJit
|
||||
local ffi = require 'ffi'
|
||||
ffi.cdef([[
|
||||
int __stdcall WideCharToMultiByte(unsigned int CodePage, unsigned int dwFlags, const wchar_t *lpWideCharStr, int cchWideChar, char *lpMultiByteStr, int cbMultiByte, const char *lpDefaultChar, bool *lpUsedDefaultChar);
|
||||
]])
|
||||
|
||||
--converts a UTF16 string to a UTF8 string
|
||||
--this function was adapted from https://github.com/mpv-player/mpv/issues/10139#issuecomment-1117954648
|
||||
local function utf8(WideCharStr)
|
||||
WideCharStr = ffi.cast("wchar_t*", WideCharStr)
|
||||
if not WideCharStr then return nil end
|
||||
|
||||
local utf8_size = ffi.C.WideCharToMultiByte(65001, 0, WideCharStr, -1, nil, 0, nil, nil) --CP_UTF8
|
||||
if utf8_size > 0 then
|
||||
local utf8_path = ffi.new("char[?]", utf8_size)
|
||||
local utf8_size = ffi.C.WideCharToMultiByte(65001, 0, WideCharStr, -1, utf8_path, utf8_size, nil, nil)
|
||||
if utf8_size > 0 then
|
||||
--removes the trailing `\0` character which can break things
|
||||
return ffi.string(utf8_path, utf8_size):sub(1, -2)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local dir = {
|
||||
priority = 109,
|
||||
api_version = "1.1.0",
|
||||
name = "cmd-dir",
|
||||
keybind_name = "file"
|
||||
}
|
||||
|
||||
local function command(args, parse_state)
|
||||
local _, cmd = parse_state:yield(
|
||||
mp.command_native_async({
|
||||
name = "subprocess",
|
||||
playback_only = false,
|
||||
capture_stdout = true,
|
||||
capture_stderr = true,
|
||||
args = args,
|
||||
}, fb.coroutine.callback() )
|
||||
)
|
||||
cmd.stdout = utf8(cmd.stdout)
|
||||
cmd.stderr = utf8(cmd.stderr)
|
||||
|
||||
--dir returns this exact error message if the directory is empty
|
||||
if cmd.status == 1 and cmd.stderr == "File Not Found\r\n" then cmd.status = 0 end
|
||||
|
||||
return cmd.status == 0 and cmd.stdout or nil, cmd.stderr
|
||||
end
|
||||
|
||||
function dir:can_parse(directory)
|
||||
if directory == "" then return end
|
||||
return not fb.get_protocol(directory)
|
||||
end
|
||||
|
||||
function dir:parse(directory, parse_state)
|
||||
local list = {}
|
||||
local files, dirs, err
|
||||
|
||||
-- the dir command expects backslashes for our paths
|
||||
directory = directory:gsub("/", "\\")
|
||||
|
||||
dirs, err = command({ "cmd", "/U", "/c", "dir", "/b", "/ad", directory }, parse_state)
|
||||
if not dirs then return msg.error(err) end
|
||||
|
||||
files, err = command({ "cmd", "/U", "/c", "dir", "/b", "/a-d", directory }, parse_state)
|
||||
if not files then return msg.error(err) end
|
||||
|
||||
for name in dirs:gmatch("[^\n\r]+") do
|
||||
name = name.."/"
|
||||
if fb.valid_dir(name) then
|
||||
table.insert(list, { name = name, type = "dir" })
|
||||
msg.trace(name)
|
||||
end
|
||||
end
|
||||
|
||||
for name in files:gmatch("[^\n\r]+") do
|
||||
if fb.valid_file(name) then
|
||||
table.insert(list, { name = name, type = "file" })
|
||||
msg.trace(name)
|
||||
end
|
||||
end
|
||||
|
||||
return list, { filtered = true }
|
||||
end
|
||||
|
||||
return dir
|
||||
@@ -1,52 +0,0 @@
|
||||
--[[
|
||||
Automatically populates the root with windows drives on startup.
|
||||
Ctrl+r will add new drives mounted since startup.
|
||||
|
||||
Drives will only be added if they are not already present in the root.
|
||||
|
||||
Available at: https://github.com/CogentRedTester/mpv-file-browser/tree/master/addons
|
||||
]]
|
||||
|
||||
local mp = require 'mp'
|
||||
local msg = require 'mp.msg'
|
||||
local fb = require 'file-browser'
|
||||
|
||||
-- returns a list of windows drives
|
||||
local function get_drives()
|
||||
local result = mp.command_native({
|
||||
name = 'subprocess',
|
||||
playback_only = false,
|
||||
capture_stdout = true,
|
||||
args = {'fsutil', 'fsinfo', 'drives'}
|
||||
})
|
||||
if result.status ~= 0 then return msg.error('could not read windows root') end
|
||||
|
||||
local root = {}
|
||||
for drive in result.stdout:gmatch("(%a:)\\") do
|
||||
table.insert(root, drive..'/')
|
||||
end
|
||||
return root
|
||||
end
|
||||
|
||||
-- adds windows drives to the root if they are not already present
|
||||
local function import_drives()
|
||||
local drives = get_drives()
|
||||
|
||||
for _, drive in ipairs(drives) do
|
||||
fb.register_root_item(drive)
|
||||
end
|
||||
end
|
||||
|
||||
local keybind = {
|
||||
key = 'Ctrl+r',
|
||||
name = 'import_root_drives',
|
||||
command = import_drives,
|
||||
parser = 'root',
|
||||
passthrough = true
|
||||
}
|
||||
|
||||
return {
|
||||
api_version = '1.4.0',
|
||||
setup = import_drives,
|
||||
keybinds = { keybind }
|
||||
}
|
||||
@@ -1,958 +0,0 @@
|
||||
# How to Write an Addon - API v1.7.0
|
||||
|
||||
Addons provide ways for file-browser to parse non-native directory structures. This document describes how one can create their own custom addon.
|
||||
|
||||
If you have an independent script but want to use file-browser's parsing capabilities, perhaps to make use of existing addons, then look [here](https://github.com/CogentRedTester/mpv-file-browser#get-directory-contents).
|
||||
|
||||
## Terminology
|
||||
|
||||
For the purpose of this document addons refer to the scripts being loaded while parsers are the objects the scripts return.
|
||||
An addon can return multiple parsers, but when they only returns one the terms are almost synonymous.
|
||||
Additionally, `method` refers to functions called using the `object:funct()` syntax, and hence have access to the self object, whereas `function` is the standard `object.funct()` syntax.
|
||||
|
||||
## API Version
|
||||
|
||||
The API version, shown in the title of this document, allows file-browser to ensure that addons are using the correct
|
||||
version of the API. It follows [semantic versioning](https://semver.org/) conventions of `MAJOR.MINOR.PATCH`.
|
||||
A parser sets its version string with the `version` field, as seen [below](#overview).
|
||||
|
||||
Any change that breaks backwards compatability will cause the major version number to increase.
|
||||
A parser MUST have the same major version number as the API, otherwise an error message will be printed and the parser will
|
||||
not be loaded.
|
||||
|
||||
A minor version number denotes a change to the API that is backwards compatible. This includes additional API functions,
|
||||
or extra fields in tables that were previously unused. It may also include additional arguments to existing functions that
|
||||
add additional behaviour without changing the old behaviour.
|
||||
If the parser's minor version number is greater than the API_VERSION, then a warning is printed to the console.
|
||||
|
||||
Patch numbers denote bug fixes, and are ignored when loading an addon.
|
||||
For this reason addon authors are allowed to leave the patch number out of their version tag and just use `MAJOR.MINOR`.
|
||||
|
||||
## Overview
|
||||
|
||||
File-browser automatically loads any lua files from the `~~/script-modules/file-browser-addons` directory as modules.
|
||||
Each addon must return either a single parser table, or an array of parser tables. Each parser object must contain the following three members:
|
||||
|
||||
| key | type | arguments | returns | description |
|
||||
|-----------|--------|---------------------------|------------------------|--------------------------------------------------------------------------------------------------------------|
|
||||
| priority | number | - | - | a number to determine what order parsers are tested - see [here](#priority-suggestions) for suggested values |
|
||||
| api_version| string | - | - | the API version the parser is using - see [API Version](#api-version) |
|
||||
| can_parse | method | string, parse_state_table | boolean | returns whether or not the given path is compatible with the parser |
|
||||
| parse | method | string, parse_state_table | list_table, opts_table | returns an array of item_tables, and a table of options to control how file_browser handles the list |
|
||||
|
||||
Additionally, each parser can optionally contain:
|
||||
|
||||
| key | type | arguments | returns | description |
|
||||
|--------------|--------|-----------|---------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| name | string | - | - | the name of the parser used for debug messages and to create a unique id - by default uses the filename with `.lua` or `-browser.lua` removed |
|
||||
| keybind_name | string | - | - | the name to use when setting custom keybind filters - uses the value of name by default but can be set manually so that the same keys work with multiple addons |
|
||||
| setup | method | - | - | if it exists this method is automatically run after all parsers are imported and API functions are made available |
|
||||
| keybinds | table | - | - | an array of keybind objects for the browser to set when loading - see [#keybinds] |
|
||||
|
||||
All parsers are given a unique string ID based on their name. If there are collisions then numbers are appended to the end of the name until a free name is found.
|
||||
These IDs are primarily used for debug messages, though they may gain additional functionality in the future.
|
||||
|
||||
Here is an extremely simple example of an addon creating a parser table and returning it to file-browser.
|
||||
|
||||
```lua
|
||||
local parser = {
|
||||
api_version = '1.0.0',
|
||||
priority = 100,
|
||||
name = "example" -- this parser will have the id 'example' or 'example_#' if there are duplicates
|
||||
}
|
||||
|
||||
function parser:can_parse(directory)
|
||||
return directory == "Example/"
|
||||
end
|
||||
|
||||
function parser:parse(directory, state)
|
||||
local list, opts
|
||||
------------------------------
|
||||
--- populate the list here ---
|
||||
------------------------------
|
||||
return list, opts
|
||||
end
|
||||
|
||||
return parser
|
||||
|
||||
```
|
||||
|
||||
## Parsing
|
||||
|
||||
When a directory is loaded file-browser will iterate through the list of parsers from lowest to highest priority.
|
||||
The first parser for which `can_parse` returns true will be selected as the parser for that directory.
|
||||
|
||||
The `parse` method will then be called on the selected parser, which is expected to return either a table of list items, or nil.
|
||||
If an empty table is returned then file-browser will treat the directory as empty, otherwise if the list_table is nil then file-browser will attempt to run `parse` on the next parser for which `can_parse` returns true.
|
||||
This continues until a parser returns a list_table, or until there are no more parsers.
|
||||
|
||||
The entire parse operation is run inside of a coroutine, this allows parsers to pause execution to handle asynchronous operations.
|
||||
Please read [coroutines](#coroutines) for all the details.
|
||||
|
||||
### Parse State Table
|
||||
|
||||
The `parse` and `can_parse` functions are passed a state table as its second argument, this contains the following fields.
|
||||
|
||||
| key | type | description |
|
||||
|----------------------|---------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| source | string | the source of the parse request |
|
||||
| directory | string | the directory of the parse request - for debugging purposes |
|
||||
| already_deferred | boolean | whether or not [defer](#advanced-functions) was called during this parse, if so then file-browser will not try to query any more parsers after receiving the result - set automatically, but can be manually disabled |
|
||||
| yield | method | a wrapper around `coroutine.yield()` - see [coroutines](#coroutines) |
|
||||
| is_coroutine_current | method | returns if the browser is waiting on the current coroutine to populate the list |
|
||||
|
||||
`already_deferred` is an optimisation. If a script uses defer and still returns nil, then that means that none of the remaining parsers will be able to parse the path.
|
||||
Therefore, it is more efficient to just immediately jump to the root.
|
||||
It is up to the addon author to manually disable this if their use of `defer` conflicts with this assumption.
|
||||
|
||||
Source can have the following values:
|
||||
|
||||
| source | description |
|
||||
|----------------|---------------------------------------------------------------------------------------------------------|
|
||||
| browser | triggered by the main browser window |
|
||||
| loadlist | the browser is scanning the directory to append to the playlist |
|
||||
| script-message | triggered by the `get-directory-contents` script-message |
|
||||
| addon | caused by an addon calling the `parse_directory` API function - note that addons can set a custom state |
|
||||
|
||||
Note that all calls to any `parse` function during a specific parse request will be given the same parse_state table.
|
||||
This theoretically allows parsers to communicate with parsers of a lower priority (or modify how they see source information),
|
||||
but no guarantees are made that specific keys will remain unused by the API.
|
||||
|
||||
#### Coroutines
|
||||
|
||||
Any calls to `parse()` (or `can_parse()`, but you should never be yielding inside there) are done in a [Lua coroutine](https://www.lua.org/manual/5.1/manual.html#2.11).
|
||||
This means that you can arbitrarily pause the parse operation if you need to wait for some asynchronous operation to complete,
|
||||
such as waiting for user input, or for a network request to complete.
|
||||
|
||||
Making these operations asynchronous has performance
|
||||
advantages as well, for example recursively opening a network directory tree could cause the browser to freeze
|
||||
for a long period of time. If the network query were asynchronous then the browser would only freeze during actual operations,
|
||||
during network operations it would be free for the user interract with. The browser has even been designed so that
|
||||
a loadfile/loadlist operation saves it's own copy of the current directory, so even if the user hops around like crazy the original
|
||||
open operation will still occur in the correct order (though there's nothing stopping them starting a new operation which will cause
|
||||
random ordering.)
|
||||
|
||||
However, there is one downside to this behaviour. If the parse operation is requested by the browser, then it is
|
||||
possible for the user to change directories while the coroutine is yielded. If you were to resume the coroutine
|
||||
in that situation, then any operations you do are wasted, and unexpected bahaviour could happen.
|
||||
file-browser will automatically detect when it receives a list from an aborted coroutine, so there is no risk
|
||||
of the current list being replaced, but any other logic in your script will continue until `parse` returns.
|
||||
|
||||
To fix this there are two methods available in the state table, the `yield()` method is a wrapper around `coroutine.yield()` that
|
||||
detects when the browser has abandoned the parse, and automatically kills the coroutine by throwing an error.
|
||||
The `is_coroutine_current()` method simply compares if the current coroutine (as returned by `coroutine.running()`) matches the
|
||||
coroutine that the browser is waiting for. Remember this is only a problem when the browser is the source of the request,
|
||||
if the request came from a script-message, or from a loadlist command there are no issues.
|
||||
|
||||
### The List Array
|
||||
|
||||
The list array must be made up of item_tables, which contain details about each item in the directory.
|
||||
Each item has the following members:
|
||||
|
||||
| key | type | required | description |
|
||||
|-------------|-----------------|----------|---------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| name | string | yes | name of the item, and the string to append after the directory when opening a file/folder |
|
||||
| type | string | yes | determines whether the item is a file ("file") or directory ("dir") |
|
||||
| label | string | no | an alternative string to print to the screen instead of name |
|
||||
| ass | string | no | a string to print to the screen without escaping ass styling - overrides label and name |
|
||||
| path | string | no | opening the item uses this full path instead of appending directory and name |
|
||||
| redirect | bool | no | whether `path` should redirect the browser when opening a directory - default yes (nil counts as true) |
|
||||
| mpv_options | string or table | no | a list of options to be sent to mpv when loading the file - can be in the form `opt1=value1,opt2=value2,...` or a table of string keys and values |
|
||||
|
||||
File-browser expects that `type` and `name` will be set for each item, so leaving these out will probably crash the script.
|
||||
File-browser also assumes that all directories end in a `/` when appending name, and that there will be no backslashes.
|
||||
The API function [`fix_path`](#utility-functions) can be used to ensure that paths conform to file-browser rules.
|
||||
|
||||
Here is an example of a static list table being returned by the `parse` method.
|
||||
This would allow one to specify a custom list of items.
|
||||
|
||||
```lua
|
||||
function parser:parse(directory, state)
|
||||
local list = {
|
||||
{ name = "first/", type = "dir" },
|
||||
{ name = "second/", type = "dir" },
|
||||
{ name = "third/", type = "dir" },
|
||||
{ name = "file%01", type = "file", label = "file1" },
|
||||
{ name = "file2", type = "file", path = "https://youtube.com/video" },
|
||||
}
|
||||
|
||||
return list
|
||||
end
|
||||
```
|
||||
|
||||
### The Opts Table
|
||||
|
||||
The options table allows scripts to better control how they are handled by file-browser.
|
||||
None of these values are required, and the opts table can even left as nil when returning.
|
||||
|
||||
| key | type | description |
|
||||
|-----------------|---------|------------------------------------------------------------------------------------------------------------------------------|
|
||||
| filtered | boolean | if true file-browser will not run the standard filter() function on the list |
|
||||
| sorted | boolean | if true file-browser will not sort the list |
|
||||
| directory | string | changes the browser directory to this - used for redirecting to other locations |
|
||||
| directory_label | string | display this label in the header instead of the actual directory - useful to display encoded paths |
|
||||
| empty_text | string | display this text when the list is empty - can be used for error messages |
|
||||
| selected_index | number | the index of the item on the list to select by default - a.k.a. the cursor position |
|
||||
| id | number | id of the parser that successfully returns a list - set automatically, but can be set manually to take ownership (see defer) |
|
||||
|
||||
The previous static example, but modified so that file browser does not try to filter or re-order the list:
|
||||
|
||||
```lua
|
||||
function parser:parse(directory, state)
|
||||
local list = {
|
||||
{ name = "first/", type = "dir" },
|
||||
{ name = "second/", type = "dir" },
|
||||
{ name = "third/", type = "dir" },
|
||||
{ name = "file%01", type = "file", label = "file1" },
|
||||
{ name = "file2", type = "file", path = "https://youtube.com/video" },
|
||||
}
|
||||
|
||||
return list, { sorted = true, filtered = true }
|
||||
end
|
||||
```
|
||||
|
||||
`id` is used to declare ownership of a page. The name of the parser that has ownership is used for custom-keybinds parser filtering.
|
||||
When using `defer` id will be the id of whichever parser first returned a list.
|
||||
This is the only situation when a parser may want to set id manually.
|
||||
|
||||
## Priority Suggestions
|
||||
|
||||
Below is a table of suggested priority ranges:
|
||||
|
||||
| Range | Suggested Use | Example parsers |
|
||||
|---------|------------------------------------------------------------------------------------------------|------------------------------------------------|
|
||||
| 0-20 | parsers that purely modify the results of other parsers | [m3u-fixer](m3u-browser.lua) |
|
||||
| 21-40 | virtual filesystems which need to link to the results of other parsers | [favourites](favourites.lua) |
|
||||
| 41-50 | to support specific sites or systems which can be inferred from the path | |
|
||||
| 51-80 | limitted support for specific protocols which requires complex parsing to verify compatability | [apache](apache-browser.lua) |
|
||||
| 81-90 | parsers that only need to modify the results of full parsers | [home-label](home-label.lua) |
|
||||
| 91-100 | use for parsers which fully support a non-native protocol with absolutely no overlap | [ftp](ftp-browser.lua), [m3u](m3u-browser.lua) |
|
||||
| 101-109 | replacements for the native file parser or fallbacks for the full parsers | [powershell](powershell.lua) |
|
||||
| 110 | priority of the native file parser - don't use | |
|
||||
| 111+ | fallbacks for native parser - potentially alternatives to the default root | |
|
||||
|
||||
## Keybinds
|
||||
|
||||
Addons have the ability to set custom keybinds using the `keybinds` field in the `parser` table. `keybinds` must be an array of tables, each of which may be in two forms.
|
||||
|
||||
Firstly, the keybind_table may be in the form
|
||||
`{ "key", "name", [function], [flags] }`
|
||||
where the table is an array whose four values corresond to the four arguments for the [mp.add_key_binding](https://mpv.io/manual/master/#lua-scripting-[,flags]]\)) API function.
|
||||
|
||||
```lua
|
||||
local function main(keybind, state, co)
|
||||
-- deletes files
|
||||
end
|
||||
|
||||
parser.keybinds = {
|
||||
{ "Alt+DEL", "delete_files", main, {} },
|
||||
}
|
||||
```
|
||||
|
||||
Secondly, the keybind_table may use the same formatting as file-browser's [custom-keybinds](../custom-keybinds.md).
|
||||
Using the array form is equivalent to setting `key`, `name`, `command`, and `flags` of the custom-keybind form, and leaving everything else on the defaults.
|
||||
|
||||
```lua
|
||||
parser.keybinds = {
|
||||
{
|
||||
key = "Alt+DEL",
|
||||
name = "delete_files",
|
||||
command = {"run", "rm", "%F"},
|
||||
filter = "files"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
These keybinds are evaluated only once shortly after the addon is loaded, they cannot be modified dynamically during runtime.
|
||||
Keybinds are applied after the default keybinds, but before the custom keybinds. This means that addons can overwrite the
|
||||
default keybinds, but that users can ovewrite addon keybinds. Among addons, those with higher priority numbers have their keybinds loaded before those
|
||||
with lower priority numbers.
|
||||
Remember that a lower priority value is better, they will overwrite already loaded keybinds.
|
||||
Keybind passthrough works the same way, though there is some custom behaviour when it comes to [raw functions](#keybind-functions).
|
||||
|
||||
### Keybind Names
|
||||
|
||||
In either form the naming of the function is different from custom keybinds. Instead of using the form `file_browser/dynamic/custom/[name]`
|
||||
they use the form `file_browser/dynamic/[parser_ID]/[name]`, where `[parser_id]` is a unique string ID for the parser, which can be retrieved using the
|
||||
`parser:get_id()` method.
|
||||
|
||||
### Native Functions vs Command Tables
|
||||
|
||||
There are two ways of specifying the behaviour of a keybind.
|
||||
It can be in command table form, as done when using custom-keybind syntax, and it can be done in
|
||||
native function form, as done when using the `mp.add_key_binding` syntax.
|
||||
However, these two ways of specifying commands are independant of how the overall keybind is defined.
|
||||
What this means is that the command field of the custom-keybinds syntax can be an array, and the
|
||||
3rd value in the array syntax can be a table of mpv commands.
|
||||
|
||||
```lua
|
||||
local function main(keybind, state, co)
|
||||
-- deletes files
|
||||
end
|
||||
|
||||
-- this is a valid keybind table
|
||||
parser.keybinds = {
|
||||
{ "Alt+DEL", "delete_files", {"run", "rm", "%F"}, {} },
|
||||
|
||||
{
|
||||
key = "Alt+DEL",
|
||||
name = "delete_files",
|
||||
command = main
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
There are some limitations however, not all custom-keybind options are supported when using native functions.
|
||||
The supported options are: `key`, `name`, `condition`, `flags`, `parser`, `passthrough`. The other options can be replicated manually (see below).
|
||||
|
||||
### Keybind Functions
|
||||
|
||||
This section details the use of keybind functions.
|
||||
|
||||
#### Function Call
|
||||
|
||||
If one uses the raw function then the functions are called directly in the form:
|
||||
|
||||
`fn(keybind, state, coroutine)`
|
||||
|
||||
Where `keybind` is the keybind_table of the key being run, `state` is a table of state values at the time of the key press, and `coroutine` is the coroutine object
|
||||
that the keybind is being executed inside.
|
||||
|
||||
The `keybind` table uses the same fields as defined
|
||||
in [custom-keybinds.md](../custom-keybinds.md). Any random extra fields placed in the original
|
||||
`file-browser-keybinds.json` will likely show up as well (this is not guaranteed).
|
||||
Note that even if the array form is used, the `keybind` table will still use the custom-keybind format.
|
||||
|
||||
The entire process of running a keybind is handled with a coroutine, so the addon can safely pause and resume the coroutine at will. The `state` table is provided to
|
||||
allow addons to keep a record of important state values that may be changed during a paused coroutine.
|
||||
|
||||
#### State Table
|
||||
|
||||
The state table contains copies of the following values at the time of the key press.
|
||||
|
||||
| key | description |
|
||||
|-----------------|-------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| directory | the current directory |
|
||||
| directory_label | the current directory_label - can (and often will) be `nil` |
|
||||
| list | the current list_table |
|
||||
| selected | index of the currently selected list item |
|
||||
| selection | table of currently selected items (for multi-select) - in the form { index = true, ... } - always available even if the `multiselect` flag is not set |
|
||||
| parser | a copy of the parser object that provided the current directory |
|
||||
|
||||
The following example shows the implementation of the `delete_files` keybind using the state values:
|
||||
|
||||
```lua
|
||||
local fb = require "file-browser" -- see #api-functions and #utility-functions
|
||||
|
||||
local function main(keybind, state, co)
|
||||
for index, item in state.list do
|
||||
if state.selection[index] and item.type == "file" then
|
||||
os.remove( fb.get_full_path(item, state.directory) )
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
parser.keybinds = {
|
||||
{ "Alt+DEL", "delete_files", main, {} },
|
||||
}
|
||||
```
|
||||
|
||||
#### Passthrough
|
||||
|
||||
If the `passthrough` field of the keybind_table is set to `true` or `false` then file-browser will
|
||||
handle everything. However, if the passthrough field is not set (meaning the bahviour should be automatic)
|
||||
then it is up to the addon to ensure that they are
|
||||
correctly notifying when the operation failed and a passthrough should occur.
|
||||
In order to tell the keybind handler to run the next priority command, the keybind function simply needs to return the value `false`,
|
||||
any other value (including `nil`) will be treated as a successful operation.
|
||||
|
||||
The below example only allows removing files from the `/tmp/` directory and allows other
|
||||
keybinds to run in different directories:
|
||||
|
||||
```lua
|
||||
local fb = require "file-browser" -- see #api-functions and #utility-functions
|
||||
|
||||
local function main(keybind, state, co)
|
||||
if state.directory ~= "/tmp/" then return false end
|
||||
|
||||
for index, item in state.list do
|
||||
if state.selection[index] and item.type == "file" then
|
||||
os.remove( fb.get_full_path(item, state.directory) )
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
parser.keybinds = {
|
||||
{ "Alt+DEL", "delete_files", main, {} },
|
||||
}
|
||||
```
|
||||
|
||||
## The API
|
||||
|
||||
The API is available through a module, which can be loaded with `require "file-browser"`.
|
||||
The API provides a variety of different values and functions for an addon to use
|
||||
in order to make them more powerful.
|
||||
Function definitions are written using Typescript-style type annotations.
|
||||
|
||||
```lua
|
||||
local fb = require "file-browser"
|
||||
|
||||
local parser = {
|
||||
priority = 100,
|
||||
}
|
||||
|
||||
function parser:setup()
|
||||
fb.register_root_item("Example/")
|
||||
end
|
||||
|
||||
return parser
|
||||
```
|
||||
|
||||
### Parser API
|
||||
|
||||
In addition to the standard API there is also an extra parser API that provides
|
||||
several parser specific methods, listed below using `parser:method` instead of `fb.function`.
|
||||
This API is added to the parser object after it is loaded by file-browser,
|
||||
so if a script wants to call them immediately on load they must do so in the `setup` method.
|
||||
All the standard API functions are also available in the parser API.
|
||||
|
||||
```lua
|
||||
local parser = {
|
||||
priority = 100,
|
||||
}
|
||||
|
||||
function parser:setup()
|
||||
-- same operations
|
||||
self.insert_root_item({ name = "Example/", type = "dir" })
|
||||
parser.insert_root_item({ name = "Example/", type = "dir" })
|
||||
end
|
||||
|
||||
-- will not work since the API hasn't been added to the parser yet
|
||||
parser.insert_root_item({ name = "Example/", type = "dir" })
|
||||
|
||||
return parser
|
||||
```
|
||||
|
||||
### General Functions
|
||||
|
||||
#### `fb.API_VERSION: string`
|
||||
|
||||
The current API version in use by file-browser.
|
||||
|
||||
#### `fb.add_default_extension(ext: string): void`
|
||||
|
||||
Adds the given extension to the default extension filter whitelist. Can only be run inside the `setup()` method.
|
||||
|
||||
#### `fb.browse_directory(directory: string, open_browser: bool = true): coroutine`
|
||||
|
||||
Clears the cache and opens the given directory in the browser.
|
||||
If the `open_browser` argument is truthy or `nil` then the browser will be opened
|
||||
if it is currently closed. If `open_browser` is `false` then the directory will
|
||||
be opened in the background.
|
||||
Returns the coroutine of the upcoming parse operation. The parse is queued and run when the script thread next goes idle,
|
||||
allowing one to store this value and use it to identify the triggered parse operation.
|
||||
|
||||
This is the equivalent of calling the `browse-directory` script-message.
|
||||
|
||||
#### `fb.insert_root_item(item: item_table, pos?: number): void`
|
||||
|
||||
Add an item_table to the root list at the specified position. If `pos` is nil then append to the end of the root.
|
||||
`item` must be a valid item_table of `type='dir'`.
|
||||
|
||||
#### `fb.register_directory_mapping(directory: string | nil, mapping: string, pattern?: bool): void`
|
||||
|
||||
Creates a directory mapping for the given directory. A directory mapping is a
|
||||
one-way mapping from an external directory string, to an internal directory
|
||||
within file-browser's directory tree. It allows external paths that may not
|
||||
exist within file-browser's tree to be mapped to a location that is.
|
||||
Internally, this is used by file-browser to map the `bd://`, `dvd://`, and `cdda://`
|
||||
protocol paths to their respective device locations in the filesystem.
|
||||
|
||||
Note that as this is still an experimental feature, the exact situations when mappings
|
||||
are resolved is subject to change. Currently, mapping occurs only when
|
||||
receiving a directory from an external source, such as the mpv `path` property,
|
||||
or the `browse-directory` script message.
|
||||
|
||||
`directory` is a string that represents a location within file-browser's file-system.
|
||||
`mapping` is a string that will be replaced by the `directory` string if found in a path:
|
||||
|
||||
```lua
|
||||
fb.register_directory_mapping('/dev/dvd', 'dvd://')
|
||||
fb.resolve_directory_mapping('dvd://1') -- /dev/dvd/1
|
||||
```
|
||||
|
||||
There can only be one `directory` string associated with each unique `mapping` string,
|
||||
but multiple mappings can point to the same directory.
|
||||
If `directory` is set to `nil` then the existing mapping for `mapping` will be removed.
|
||||
If `pattern` is set to true, then `mapping` will be treated as a Lua
|
||||
pattern. Any part of an input path that matches the pattern will be substituted for
|
||||
the `directory` string.
|
||||
|
||||
```lua
|
||||
fb.register_directory_mapping('/dev/dvd', '^dvd://.*', true)
|
||||
fb.resolve_directory_mapping('dvd://1') -- /dev/dvd
|
||||
```
|
||||
|
||||
When `pattern` is falsy, `mapping` is equivalent to `'^'..fb.pattern_escape(mapping)`.
|
||||
Captures in the pattern may be given extra behaviour in the future.
|
||||
|
||||
#### `fb.register_parseable_extension(ext: string): void`
|
||||
|
||||
Register a file extension that the browser will attempt to open, like a directory - for addons which can parse files such
|
||||
as playlist files.
|
||||
|
||||
#### `fb.register_root_item(item: string | item_table, priority?: number): boolean`
|
||||
|
||||
Registers an item to be added to the root and an optional priority value that determines the position relative to other items (default is 100).
|
||||
A lower priority number is better, meaning they will be placed earlier in the list.
|
||||
Only adds the item if it is not already in the root and returns a boolean that specifies whether or not the item was added.
|
||||
Must be called during or after the `parser:setup()` method is run.
|
||||
|
||||
If `item` is a string then a new item_table is created with the values: `{ type = 'dir', name = item }`.
|
||||
If `item` is an item_table then it must be a valid directory item.
|
||||
Use [`fb.fix_path(name, true)`](#fbfix_pathpath-string-is_directory-boolean-string) to ensure the name field is correct.
|
||||
|
||||
This function should be used over the older `fb.insert_root_item`.
|
||||
|
||||
#### `fb.remove_parseable_extension(ext: string): void`
|
||||
|
||||
Remove a file extension that the browser will attempt to open like a directory.
|
||||
|
||||
#### `fb.parse_directory(directory: string, parse?: parse_state_table): (list_table, opts_table) | nil`
|
||||
|
||||
Starts a new scan for the given directory and returns a list_table and opts_table on success and `nil` on failure.
|
||||
Must be called from inside a [coroutine](#coroutines).
|
||||
|
||||
This function allows addons to request the contents of directories from the loaded parsers. There are no protections
|
||||
against infinite recursion, so be careful about calling this from within another parse.
|
||||
|
||||
Do not use the same `parse` table for multiple parses, state values for the two operations may intefere with each other
|
||||
and cause undefined behaviour. If the `parse.source` field is not set then it will be set to `"addon"`.
|
||||
|
||||
Note that this function is for creating new parse operations, if you wish to create virtual directories or modify
|
||||
the results of other parsers then use [`defer`](#parserdeferdirectory-string-list_table-opts_table--nil).
|
||||
|
||||
Also note that every parse operation is expected to have its own unique coroutine. This acts as a unique
|
||||
ID that can be used internally or by other addons. This means that if multiple `parse_directory` operations
|
||||
are run within a single coroutine then file-browser will automatically create a new coroutine for the scan,
|
||||
which hands execution back to the original coroutine upon completion.
|
||||
|
||||
#### `parser:register_root_item(item: string | item_table, priority?: number): boolean`
|
||||
|
||||
A wrapper around [`fb.register_root_item`](#fbregister_root_itemitem-string--item_table-priority-number-boolean)
|
||||
which uses the parser's priority value if `priority` is undefined.
|
||||
|
||||
#### `fb.remove_all_mappings(directory: string): string[]`
|
||||
|
||||
Removes all [directory mappings](#fbregister_directory_mappingdirectory-string--nil-mapping-string-pattern-bool-void)
|
||||
that resolve to the given `directory`. Returns a list of the `mapping` strings
|
||||
that were removed.
|
||||
|
||||
### Advanced Functions
|
||||
|
||||
#### `fb.clear_cache(): void`
|
||||
|
||||
Clears the directory cache. Use this if you are modifying the contents of directories other
|
||||
than the current one to ensure that their contents will be rescanned when next opened.
|
||||
|
||||
#### `fb.coroutine.assert(err?: string): coroutine`
|
||||
|
||||
Throws an error if it is not called from within a coroutine. Returns the currently running coroutine on success.
|
||||
The string argument can be used to throw a custom error string.
|
||||
|
||||
#### `fb.coroutine.callback(time_limit?: number): function`
|
||||
|
||||
Creates and returns a callback function that resumes the current coroutine.
|
||||
This function is designed to help streamline asynchronous operations. The best way to explain is with an example:
|
||||
|
||||
```lua
|
||||
local function execute(args)
|
||||
mp.command_native_async({
|
||||
name = "subprocess",
|
||||
playback_only = false,
|
||||
capture_stdout = true,
|
||||
capture_stderr = true,
|
||||
args = args
|
||||
}, fb.coroutine.callback())
|
||||
|
||||
local _, cmd = coroutine.yield()
|
||||
|
||||
return cmd.status == 0 and cmd.stdout or nil
|
||||
end
|
||||
```
|
||||
|
||||
This function uses the mpv [subprocess](https://mpv.io/manual/master/#command-interface-subprocess)
|
||||
command to execute some system operation. To prevent the whole script (file-browser and all addons) from freezing
|
||||
it uses the [command_native_async](https://mpv.io/manual/master/#lua-scripting-mp-command-native-async(table-[,fn])) command
|
||||
to execute the operation asynchronously and takes a callback function as its second argument.
|
||||
|
||||
`coroutine.callback())` will automatically create a callback function to resume whatever coroutine ran the `execute` function.
|
||||
Any arguments passed into the callback function (by the async function, not by you) will be passed on to the resume;
|
||||
in this case `command_native_async` passes three values into the callback, of which only the second is of interest to me.
|
||||
|
||||
If `time_limit` is set to a number, then a boolean is passed as the first resume argument to the coroutine.
|
||||
If the callback is not run within `time_limit` seconds then the coroutine will be resumed, and the first
|
||||
argument will be `false`. If the callback is run within the time limit then the first argument will be `true`.
|
||||
|
||||
```lua
|
||||
local function execute(args)
|
||||
local t = mp.command_native_async({
|
||||
name = "subprocess",
|
||||
playback_only = false,
|
||||
capture_stdout = true,
|
||||
capture_stderr = true,
|
||||
args = args
|
||||
}, fb.coroutine.callback(10))
|
||||
|
||||
local success, _, cmd = coroutine.yield()
|
||||
if not success then
|
||||
mp.abort_async_command(t)
|
||||
msg.error("command timed out")
|
||||
return nil
|
||||
end
|
||||
|
||||
return cmd.status == 0 and cmd.stdout or nil
|
||||
end
|
||||
```
|
||||
|
||||
The expectation is that the programmer will yield execution before that callback returns. In this example I
|
||||
yield immediately after running the async command.
|
||||
|
||||
If you are doing this during a parse operation you could also substitute `coroutine.yield()` with `parse_state:yield()` to abort the parse if the user changed
|
||||
browser directories during the asynchronous operation.
|
||||
|
||||
If you have no idea what I've been talking about read the [Lua manual on coroutines](https://www.lua.org/manual/5.1/manual.html#2.11).
|
||||
|
||||
#### `fb.coroutine.resume_catch(co: coroutine, ...): (boolean, ...)`
|
||||
|
||||
Runs `coroutine.resume(co, ...)` with the given coroutine, passing through any additional arguments.
|
||||
If the coroutine throws an error then an error message and stacktrace is printed to the console.
|
||||
All the return values of `coroutine.resume` are caught and returned.
|
||||
|
||||
#### `fb.coroutine.resume_err(co: coroutine, ...): boolean`
|
||||
|
||||
Runs `coroutine.resume(co, ...)` with the given coroutine, passing through any additional arguments.
|
||||
If the coroutine throws an error then an error message and stacktrace is printed to the console.
|
||||
Returns the success boolean returned by `coroutine.resume`, but drops all other return values.
|
||||
|
||||
#### `fb.coroutine.run(fn: function, ...): void`
|
||||
|
||||
Runs the given function in a new coroutine, passing through any additional arguments.
|
||||
|
||||
#### `fb.coroutine.queue(fn: function, ...): coroutine`
|
||||
|
||||
Runs the given function in a coroutine when the script next goes idle, passing through
|
||||
any additional arguments. The (not yet started) coroutine is returned by the function.
|
||||
|
||||
#### `fb.rescan(): coroutine`
|
||||
|
||||
Rescans the current directory. Equivalent to Ctrl+r without the cache refresh for higher level directories.
|
||||
Returns the coroutine of the upcoming parse operation. The parse is queued and run when the script thread next goes idle,
|
||||
allowing one to store this value and use it to identify the triggered parse operation.
|
||||
|
||||
#### `fb.redraw(): void`
|
||||
|
||||
Forces a redraw of the browser UI.
|
||||
|
||||
#### `parser:defer(directory: string): (list_table, opts_table) | nil`
|
||||
|
||||
Forwards the given directory to the next valid parser. For use from within a parse operation.
|
||||
|
||||
The `defer` function is very powerful, and can be used by scripts to create virtual directories, or to modify the results of other parsers.
|
||||
However, due to how much freedom Lua gives coders, it is impossible for file-browser to ensure that parsers are using defer correctly, which can cause unexpected results.
|
||||
The following are a list of recommendations that will increase the compatability with other parsers:
|
||||
|
||||
* Always return the opts table that is returned by defer, this can contain important values for file-browser, as described [above](#the-opts-table).
|
||||
* If required modify values in the existing opts table, don't create a new one.
|
||||
* Respect the `sorted` and `filtered` values in the opts table. This may mean calling `sort` or `filter` manually.
|
||||
* Think about how to handle the `directory_label` field, especially how it might interract with any virtual paths the parser may be maintaining.
|
||||
* Think about what to do if the `directory` field is set.
|
||||
* Think if you want your parser to take full ownership of the results of `defer`, if so consider setting `opts.id = self:get_id()`.
|
||||
* Currently this only affects custom keybind filtering, though it may be changed in the future.
|
||||
|
||||
The [home-label](https://github.com/CogentRedTester/mpv-file-browser/blob/master/addons/home-label.lua)
|
||||
addon provides a good simple example of the safe use of defer. It lets the normal file
|
||||
parser load the home directory, then modifies the directory label.
|
||||
|
||||
```lua
|
||||
local mp = require "mp"
|
||||
local fb = require "file-browser"
|
||||
|
||||
local home = fb.fix_path(mp.command_native({"expand-path", "~/"}), true)
|
||||
|
||||
local home_label = {
|
||||
api_version = '1.0.0',
|
||||
priority = 100
|
||||
}
|
||||
|
||||
function home_label:can_parse(directory)
|
||||
return directory:sub(1, home:len()) == home
|
||||
end
|
||||
|
||||
function home_label:parse(directory, ...)
|
||||
local list, opts = self:defer(directory, ...)
|
||||
|
||||
if (not opts.directory or opts.directory == directory) and not opts.directory_label then
|
||||
opts.directory_label = "~/"..(directory:sub(home:len()+1) or "")
|
||||
end
|
||||
|
||||
return list, opts
|
||||
end
|
||||
|
||||
return home_label
|
||||
```
|
||||
|
||||
### Utility Functions
|
||||
|
||||
#### `fb.ass_escape(str: string, substitute_newline?: true | string): string`
|
||||
|
||||
Returns the `str` string with escaped ass styling codes.
|
||||
The optional 2nd argument allows replacing newlines with the given string, or `'\\n'` if set to `true`.
|
||||
|
||||
#### `fb.copy_table(t: table, depth?: number): table`
|
||||
|
||||
Returns a copy of table `t`.
|
||||
The copy is done recursively to the given `depth`, and any cyclical table references are maintained.
|
||||
Both keys and values are copied. If `depth` is undefined then it defaults to `math.huge` (infinity).
|
||||
Additionally, the original table is stored in the `__original` field of the copy's metatable.
|
||||
The copy behaviour of the metatable itself is subject to change, but currently it is not copied.
|
||||
|
||||
#### `fb.evaluate_string(str: string, chunkname?: string, env?: table, defaults?: bool = true): unknown`
|
||||
|
||||
Loads `str` as a chunk of Lua statement(s) and runs them, returning the result.
|
||||
Errors are propagated to the caller. `chunkname` is used
|
||||
for debug output and error messages.
|
||||
|
||||
Each chunk has a separate global environment table that inherits
|
||||
from the main global table. This means new globals can be created safely,
|
||||
but the default globals can still be accessed. As such, this method
|
||||
cannot and should not be used for security or sandboxing.
|
||||
|
||||
A custom environment table can be provided with the `env` argument.
|
||||
Inheritance from the global table is disabled if `defaults` is `false`.
|
||||
|
||||
Examples:
|
||||
|
||||
```lua
|
||||
fb.evaluate_string('return 5 + 5') -- 10
|
||||
fb.evaluate_string('x = 20 ; return x * x') -- 400
|
||||
|
||||
local code = [[
|
||||
local arr = {1, 2, 3, 4}
|
||||
table.insert(arr, x)
|
||||
return unpack(arr)
|
||||
]]
|
||||
fb.evaluate_string(code, 'test3', {x = 5}) -- 1, 2, 3, 4, 5
|
||||
fb.evaluate_string(code, 'test4', nil, false) -- Lua error: [string "test4"]:2: attempt to index global 'table' (a nil value)
|
||||
|
||||
```
|
||||
|
||||
In an expression the `mp`, `mp.msg`, and `mp.utils` modules are available as `mp`, `msg`, and `utils` respectively.
|
||||
Additionally, in mpv v0.38+ the `mp.input` module is available as `input`.
|
||||
This addon API is available as `fb` and if [mpv-user-input](https://github.com/CogentRedTester/mpv-user-input)
|
||||
is installed then user-input will be available in `user_input`.
|
||||
These modules are all unavailable if `defaults` is `false`.
|
||||
|
||||
#### `fb.filter(list: list_table): list_table`
|
||||
|
||||
Iterates through the given list and removes items that don't pass the user set filters
|
||||
(dot files/directories and valid file extensions).
|
||||
Returns the list but does not create a copy; the `list` table is filtered in-place.
|
||||
|
||||
#### `fb.fix_path(path: string, is_directory?: boolean): string`
|
||||
|
||||
Takes a path and returns a file-browser compatible path string.
|
||||
The optional second argument is a boolean that tells the function to format the path to be a
|
||||
directory.
|
||||
|
||||
#### `fb.get_extension(filename: string, def?: any): string | def`
|
||||
|
||||
Returns the file extension for the string `filename`, or `nil` if there is no extension.
|
||||
If `def` is defined then that is returned instead of `nil`.
|
||||
|
||||
The full stop is not included in the extension, so `test.mkv` will return `mkv`.
|
||||
|
||||
#### `fb.get_full_path(item: item_table, directory?: string): string`
|
||||
|
||||
Takes an item table and returns the item's full path assuming it is in the given directory.
|
||||
Takes into account `item.name`/`item.path` fields, etc.
|
||||
If directory is nil then it uses the currently open directory.
|
||||
|
||||
#### `fb.get_protocol(url: string, def?: any): string | def`
|
||||
|
||||
Returns the protocol scheme for the string `url`, or `nil` if there is no scheme.
|
||||
If `def` is defined then that is returned instead of `nil`.
|
||||
|
||||
The `://` is not included, so `https://example.com/test.mkv` will return `https`.
|
||||
|
||||
#### `fb.iterate_opt(opts: string): iterator`
|
||||
|
||||
Takes an options string consisting of a list of items separated by the `root_separators` defined in `file_browser.conf` and
|
||||
returns an iterator function that can be used to iterate over each item in the list.
|
||||
|
||||
```lua
|
||||
local opt = "a,b,zz z" -- root_separators=,
|
||||
for item in fb.iterate_opt(opt) do
|
||||
print(item) -- prints: 'a', 'b', 'zz z'
|
||||
end
|
||||
```
|
||||
|
||||
#### `fb.join_path(p1: string, p2: string): string`
|
||||
|
||||
A wrapper around [`mp.utils.join_path`](https://mpv.io/manual/master/#lua-scripting-utils-join-path(p1,-p2))
|
||||
which treats paths with network protocols as absolute paths.
|
||||
|
||||
#### `fb.pattern_escape(str: string): string`
|
||||
|
||||
Returns `str` with Lua special pattern characters escaped.
|
||||
|
||||
#### `fb_utils.resolve_directory_mapping(path: string): string`
|
||||
|
||||
Takes a `path` string and resolves any
|
||||
[directory mappings](#fbregister_directory_mappingdirectory-string--nil-mapping-string-pattern-bool-void),
|
||||
replacing any substrings that match a mapping with the associated directory.
|
||||
|
||||
Only the first valid mapping is applied, but this behaviour will likely change in
|
||||
the future. Changes to this behaviour will not consitute a major version bump so should not
|
||||
be relied upon.
|
||||
|
||||
#### `fb.sort(list: list_table): list_table`
|
||||
|
||||
Iterates through the given list and sorts the items using file-browser's sorting algorithm.
|
||||
Returns the list but does not create a copy; the `list` table is sorted in-place.
|
||||
|
||||
#### `fb.valid_file(name: string): boolean`
|
||||
|
||||
Tests if the string `name` passes the user set filters for valid files (extensions/dot files/etc).
|
||||
|
||||
#### `fb.valid_dir(name: string): boolean`
|
||||
|
||||
Tests if the string `name` passes the user set filters for valid directories (dot folders/etc).
|
||||
|
||||
### Getters
|
||||
|
||||
These functions allow addons to safely get information from file-browser.
|
||||
All tables returned by these functions are copies sent through the [`fb.copy_table`](#fbcopy_tablet-table-depth-number-table)
|
||||
function to ensure addons can't accidentally break things.
|
||||
|
||||
#### `fb.get_audio_extensions(): table`
|
||||
|
||||
Returns a set of extensions like [`fb.get_extensions`](#fbget_extensions-table) but for extensions that are opened
|
||||
as additional audio tracks.
|
||||
All of these are included in `fb.get_extensions`.
|
||||
|
||||
#### `fb.get_current_file(): table`
|
||||
|
||||
A table containing the path of the current open file in the form:
|
||||
`{directory = "/home/me/", name = "bunny.mkv", path = "/home/me/bunny.mkv"}`.
|
||||
|
||||
#### `fb.get_current_parser(): string`
|
||||
|
||||
The unique id of the parser that successfully parsed the current directory.
|
||||
|
||||
#### `fb.get_current_parser_keyname(): string`
|
||||
|
||||
The `keybind_name` of the parser that successfully parsed the current directory.
|
||||
Used for custom-keybind filtering.
|
||||
|
||||
#### `fb.get_directory(): string`
|
||||
|
||||
The current directory open in the browser.
|
||||
|
||||
#### `fb.get_dvd_device(): string`
|
||||
|
||||
The current dvd-device as reported by mpv's `dvd-device` property.
|
||||
Formatted to work with file-browser.
|
||||
|
||||
#### `fb.get_extensions(): table`
|
||||
|
||||
Returns the set of valid extensions after applying the user's whitelist/blacklist options.
|
||||
The table is in the form `{ mkv = true, mp3 = true, ... }`.
|
||||
Sub extensions, audio extensions, and parseable extensions are all included in this set.
|
||||
|
||||
#### `fb.get_list(): list_table`
|
||||
|
||||
The list_table currently open in the browser.
|
||||
|
||||
#### `fb.get_open_status(): boolean`
|
||||
|
||||
Returns true if the browser is currently open and false if not.
|
||||
|
||||
#### `fb.get_opt(name: string): string | number | boolean`
|
||||
|
||||
Returns the script-opt with the given name.
|
||||
|
||||
#### `fb.get_parsers(): table`
|
||||
|
||||
Returns a table of all the loaded parsers/addons.
|
||||
The formatting of this table in undefined, but it should
|
||||
always contain an array of the parsers in order of priority.
|
||||
|
||||
#### `fb.get_parse_state(co?: coroutine): parse_state_table`
|
||||
|
||||
Returns the [parse_state table](#parse-state-table) for the given coroutine.
|
||||
If no coroutine is given then it uses the running coroutine.
|
||||
Every parse operation is guaranteed to have a unique coroutine.
|
||||
|
||||
#### `fb.get_parseable_extensions(): table`
|
||||
|
||||
Returns a set of extensions like [`fb.get_extensions`](#fbget_extensions-table) but for extensions that are
|
||||
treated as parseable by the browser.
|
||||
All of these are included in `fb.get_extensions`.
|
||||
|
||||
#### `fb.get_root(): list_table`
|
||||
|
||||
Returns the root table.
|
||||
|
||||
#### `fb.get_script_opts(): table`
|
||||
|
||||
The table of script opts set by the user. This currently does not get
|
||||
changed during runtime, but that is not guaranteed for future minor version increments.
|
||||
|
||||
#### `fb.get_selected_index(): number`
|
||||
|
||||
The current index of the cursor.
|
||||
Note that it is possible for the cursor to be outside the bounds of the list;
|
||||
for example when the list is empty this usually returns 1.
|
||||
|
||||
#### `fb.get_selected_item(): item_table | nil`
|
||||
|
||||
Returns the item_table of the currently selected item.
|
||||
If no item is selected (for example an empty list) then returns nil.
|
||||
|
||||
#### `fb.get_state(): table`
|
||||
|
||||
Returns the current state values of the browser.
|
||||
These are not documented and are subject to change at any time,
|
||||
adding a proper getter for anything is a valid request.
|
||||
|
||||
#### `fb.get_sub_extensions(): table`
|
||||
|
||||
Returns a set of extensions like [`fb.get_extensions`](#fbget_extensions-table) but for extensions that are opened
|
||||
as additional subtitle tracks.
|
||||
All of these are included in `fb.get_extensions`.
|
||||
|
||||
#### `parser:get_id(): string`
|
||||
|
||||
The unique id of the parser. Used for log messages and various internal functions.
|
||||
|
||||
#### `parser:get_index(): number`
|
||||
|
||||
The index of the parser in order of preference (based on the priority value).
|
||||
`defer` uses this internally.
|
||||
|
||||
### Setters
|
||||
|
||||
#### `fb.set_selected_index(pos: number): number | false`
|
||||
|
||||
Sets the cursor position and returns the new index.
|
||||
If the input is not a number return false, if the input is out of bounds move it in bounds.
|
||||
|
||||
## Examples
|
||||
|
||||
For standard addons that add support for non-native filesystems, but otherwise don't do anything fancy, see [ftp-browser](ftp-browser.lua) and [apache-browser](apache-browser.lua).
|
||||
|
||||
For more simple addons that make a few small modifications to how other parsers are displayed, see [home-label](home-label.lua).
|
||||
|
||||
For more complex addons that maintain their own virtual directory structure, see
|
||||
[favourites](favourites.lua).
|
||||
@@ -1,330 +0,0 @@
|
||||
# Custom Keybinds
|
||||
|
||||
File-browser also supports custom keybinds. These keybinds send normal input commands, but the script will substitute characters in the command strings for specific values depending on the currently open directory, and currently selected item.
|
||||
This allows for a wide range of customised behaviour, such as loading additional audio tracks from the browser, or copying the path of the selected item to the clipboard.
|
||||
|
||||
The feature is disabled by default, but is enabled with the `custom_keybinds` script-opt.
|
||||
Keybinds are declared in the `~~/script-opts/file-browser-keybinds.json` file, the config takes the form of an array of json objects, with the following keys:
|
||||
|
||||
| option | required | default | description |
|
||||
|---------------|----------|------------|--------------------------------------------------------------------------------------------|
|
||||
| key | yes | - | the key to bind the command to - same syntax as input.conf |
|
||||
| command | yes | - | json array of commands and arguments |
|
||||
| name | no | numeric id | name of the script-binding - see [modifying default keybinds](#modifying-default-keybinds) |
|
||||
| condition | no | - | a Lua [expression](#expressions) - the keybind will only run if this evaluates to true |
|
||||
| flags | no | - | flags to send to the mpv add_keybind function - see [here](https://mpv.io/manual/master/#lua-scripting-[,flags]]\)) |
|
||||
| filter | no | - | run the command on just a file (`file`) or folder (`dir`) |
|
||||
| parser | no | - | run the command only in directories provided by the specified parser. |
|
||||
| multiselect | no | `false` | command is run on all selected items |
|
||||
| multi-type | no | `repeat` | which multiselect mode to use - `repeat` or `concat` |
|
||||
| delay | no | `0` | time to wait between sending repeated multi commands |
|
||||
| concat-string | no | `' '` (space) | string to insert between items when concatenating multi commands |
|
||||
| passthrough | no | - | force or ban passthrough behaviour - see [passthrough](#passthrough-keybinds) |
|
||||
| api_version | no | - | tie the keybind to a particular [addon API version](./addons.md#api-version), printing warnings and throwing errors if the keybind is used with wrong versions |
|
||||
|
||||
Example:
|
||||
|
||||
```json
|
||||
{
|
||||
"key": "KP1",
|
||||
"command": ["print-text", "example"],
|
||||
}
|
||||
```
|
||||
|
||||
The command can also be an array of arrays, in order to send multiple commands at once:
|
||||
|
||||
```json
|
||||
{
|
||||
"key": "KP2",
|
||||
"command": [
|
||||
["print-text", "example2"],
|
||||
["show-text", "example2"]
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
Filter should not be included unless one wants to limit what types of list entries the command should be run on.
|
||||
To only run the command for directories use `dir`, to only run the command for files use `file`.
|
||||
|
||||
The parser filter is for filtering keybinds to only work inside directories loaded by specific parsers.
|
||||
There are two parsers in the base script, the default parser for native filesystems is called `file`, while the root parser is called `root`.
|
||||
Other parsers can be supplied by addons, and use the addon's filename with `-browser.lua` or just `.lua` stripped unless otherwise stated.
|
||||
For example `ftp-browser.lua` would have a parser called `ftp`.
|
||||
You can set the filter to match multiple parsers by separating the names with spaces.
|
||||
|
||||
```json
|
||||
{
|
||||
"key": "KP2",
|
||||
"command": [ ["print-text", "example3"] ],
|
||||
"parser": "ftp file"
|
||||
}
|
||||
```
|
||||
|
||||
The `flags` field is mostly only useful for addons, but can also be useful if one wants a key to be repeatable.
|
||||
In this case the the keybind would look like the following:
|
||||
|
||||
```json
|
||||
{
|
||||
"key": "p",
|
||||
"command": ["print-text", "spam-text"],
|
||||
"flags": { "repeatable": true }
|
||||
}
|
||||
```
|
||||
|
||||
## Codes
|
||||
|
||||
The script will scan every string in the command for the special substitution strings, they are:
|
||||
|
||||
| code | description |
|
||||
|--------|---------------------------------------------------------------------|
|
||||
| `%%` | escape code for `%` |
|
||||
| `%f` | filepath of the selected item |
|
||||
| `%n` | filename of the selected item |
|
||||
| `%p` | currently open directory |
|
||||
| `%q` | currently open directory but preferring the directory label |
|
||||
| `%d` | name of the current directory (characters between the last two '/') |
|
||||
| `%r` | name of the parser for the currently open directory |
|
||||
| `%x` | number of items in the currently open directory |
|
||||
| `%i` | the 1-based index of the selected item in the list |
|
||||
| `%j` | the 1-based index of the item in a multiselection - returns 1 for single selections |
|
||||
|
||||
Additionally, using the uppercase forms of those codes will send the substituted string through the `string.format("%q", str)` function.
|
||||
This adds double quotes around the string and automatically escapes any characters which would break the string encapsulation.
|
||||
This is not necessary for most mpv commands, but can be very useful when sending commands to the OS with the `run` command,
|
||||
or when passing values into [expressions](#conditional-command-condition-command).
|
||||
|
||||
Example of a command to add an audio track:
|
||||
|
||||
```json
|
||||
{
|
||||
"key": "Ctrl+a",
|
||||
"command": ["audio-add", "%f"],
|
||||
"filter": "file"
|
||||
}
|
||||
```
|
||||
|
||||
Any commands that contain codes representing specific items (`%f`, `%n`, `%i` etc) will
|
||||
not be run if no item is selected (for example in an empty directory).
|
||||
In these cases [passthrough](#passthrough-keybinds) rules will apply.
|
||||
|
||||
## Multiselect Commands
|
||||
|
||||
When multiple items are selected the command can be run for all items in the order they appear on the screen.
|
||||
This can be controlled by the `multiselect` flag, which takes a boolean value.
|
||||
When not set the flag defaults to `false`.
|
||||
|
||||
There are two different multiselect modes, controlled by the `multi-type` option. There are two options:
|
||||
|
||||
### `repeat`
|
||||
|
||||
The default mode that sends the commands once for each item that is selected.
|
||||
If time is needed between running commands of multiple selected items (for example, due to file handlers) then the `delay` option can be used to set a duration (in seconds) between commands.
|
||||
|
||||
### `concat`
|
||||
|
||||
Run a single command, but replace item specific codes with a concatenated string made from each selected item.
|
||||
For example `["print-text", "%n" ]` would print the name of each item selected separated by `' '` (space).
|
||||
The string inserted between each item is determined by the `concat-string` option, but `' '` is the default.
|
||||
|
||||
## Passthrough Keybinds
|
||||
|
||||
When loading keybinds from the json file file-browser will move down the list and overwrite any existing bindings with the same key.
|
||||
This means the lower an item on the list, the higher preference it has.
|
||||
However, file-browser implements a layered passthrough system for its keybinds; if a keybind is blocked from running by user filters, then the next highest preference command will be sent, continuing until a command is sent or there are no more keybinds.
|
||||
The default dynamic keybinds are considered the lowest priority.
|
||||
|
||||
The `filter`, `parser`, and `condition` options can all trigger passthrough, as well as some [codes](#codes).
|
||||
If a multi-select command is run on multiple items then passthrough will occur if any of the selected items fail the filters.
|
||||
|
||||
Passthrough can be forcibly disabled or enabled using the passthrough option.
|
||||
When set to `true` passthrough will always be activate regardless of the state of the filters.
|
||||
|
||||
## Modifying Default Keybinds
|
||||
|
||||
Since the custom keybinds are applied after the default dynamic keybinds they can be used to overwrite the default bindings.
|
||||
Setting new keys for the existing binds can be done with the `script-binding [binding-name]` command, where `binding-name` is the full name of the keybinding.
|
||||
For this script the names of the dynamic keybinds are in the format `file_browser/dynamic/[name]` where `name` is a unique identifier documented in the [keybinds](README.md#keybinds) table.
|
||||
|
||||
For example to change the scroll buttons from the arrows to the scroll wheel:
|
||||
|
||||
```json
|
||||
[
|
||||
{
|
||||
"key": "WHEEL_UP",
|
||||
"command": ["script-binding", "file_browser/dynamic/scroll_up"]
|
||||
},
|
||||
{
|
||||
"key": "WHEEL_DOWN",
|
||||
"command": ["script-binding", "file_browser/dynamic/scroll_down"]
|
||||
},
|
||||
{
|
||||
"key": "UP",
|
||||
"command": ["osd-auto", "add", "volume", "2"]
|
||||
},
|
||||
{
|
||||
"key": "DOWN",
|
||||
"command": ["osd-auto", "add", "volume", "-2"]
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
Custom keybinds can be called using the same method, but users must set the `name` value inside the `file-browser-keybinds.json` file.
|
||||
To avoid conflicts custom keybinds use the format: `file_browser/dynamic/custom/[name]`.
|
||||
|
||||
## Expressions
|
||||
|
||||
Expressions are used to evaluate Lua code into a string that can be used for commands.
|
||||
These behave similarly to those used for [`profile-cond`](https://mpv.io/manual/master/#conditional-auto-profiles)
|
||||
values. In an expression the `mp`, `mp.msg`, and `mp.utils` modules are available as `mp`, `msg`, and `utils` respectively.
|
||||
Additionally, in mpv v0.38+ the `mp.input` module is available as `input`.
|
||||
|
||||
The file-browser [addon API](addons/addons.md#the-api) is available as `fb` and if [mpv-user-input](https://github.com/CogentRedTester/mpv-user-input)
|
||||
is installed then user-input API will be available in `user_input`.
|
||||
|
||||
This example only runs the keybind if the browser is in the Windows C drive or if
|
||||
the selected item is a matroska file:
|
||||
|
||||
```json
|
||||
[
|
||||
{
|
||||
"key": "KP1",
|
||||
"command": ["print-text", "in my C:/ drive!"],
|
||||
"condition": "(%P):find('C:/') == 1"
|
||||
},
|
||||
{
|
||||
"key": "KP2",
|
||||
"command": ["print-text", "Matroska File!"],
|
||||
"condition": "fb.get_extension(%N) == 'mkv'"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
If the `condition` expression contains any item specific codes (`%F`, `%I`, etc) then it will be
|
||||
evaluated on each individual item, otherwise it will evaluated once for the whole keybind.
|
||||
If a code is invalid (for example using `%i` in empty directories) then the expression returns false.
|
||||
|
||||
There are some utility script messages that extend the power of expressions.
|
||||
[`conditional-command`](#conditional-command-condition-command) allows one to specify conditions that
|
||||
can apply to individual items or commands. The tradeoff is that you lose the automated passthrough behaviour.
|
||||
There is also [`evaluate-expressions`](#evaluate-expressions-command) which allows one to evaluate expressions inside commands.
|
||||
|
||||
## Utility Script Messages
|
||||
|
||||
There are a small number of custom script messages defined by file-browser to support custom keybinds.
|
||||
|
||||
### `=> <command...>`
|
||||
|
||||
A basic script message that makes it easier to chain multiple utility script messages together.
|
||||
Any `=>` string will be substituted for `script-message`.
|
||||
|
||||
```json
|
||||
{
|
||||
"key": "KP1",
|
||||
"command": ["script-message", "=>", "delay-command", "%j * 2", "=>", "evaluate-expressions", "print-text", "!{%j * 2}"],
|
||||
"multiselect": true
|
||||
}
|
||||
```
|
||||
|
||||
### `conditional-command [condition] <command...>`
|
||||
|
||||
Runs the following command only if the condition [expression](#expressions) is `true`.
|
||||
|
||||
This example command will only run if the player is currently paused:
|
||||
|
||||
```json
|
||||
{
|
||||
"key": "KP1",
|
||||
"command": ["script-message", "conditional-command", "mp.get_property_bool('pause')", "print-text", "is paused"],
|
||||
}
|
||||
```
|
||||
|
||||
Custom keybind codes are evaluated before the expressions.
|
||||
|
||||
This example only runs if the currently selected item in the browser has a `.mkv` extension:
|
||||
|
||||
```json
|
||||
{
|
||||
"key": "KP1",
|
||||
"command": ["script-message", "conditional-command", "fb.get_extension(%N) == 'mkv'", "print-text", "a matroska file"],
|
||||
}
|
||||
```
|
||||
|
||||
### `delay-command [delay] <command...>`
|
||||
|
||||
Delays the following command by `[delay]` seconds.
|
||||
Delay is an [expression](#expressions).
|
||||
|
||||
The following example will send the `print-text` command after 5 seconds:
|
||||
|
||||
```json
|
||||
{
|
||||
"key": "KP1",
|
||||
"command": ["script-message", "delay-command", "5", "print-text", "example"],
|
||||
}
|
||||
```
|
||||
|
||||
### `evaluate-expressions <command...>`
|
||||
|
||||
Evaluates embedded Lua expressions in the following command.
|
||||
Expressions have the same behaviour as the [`conditional-command`](#conditional-command-condition-command) script-message.
|
||||
Expressions must be surrounded by `!{}` characters.
|
||||
Additional `!` characters can be placed at the start of the expression to
|
||||
escape the evaluation.
|
||||
|
||||
For example the following keybind will print 3 to the console:
|
||||
|
||||
```json
|
||||
{
|
||||
"key": "KP1",
|
||||
"command": ["script-message", "evaluate-expressions", "print-text", "!{1 + 2}"],
|
||||
}
|
||||
```
|
||||
|
||||
This example replaces all `/` characters in the path with `\`
|
||||
(note that the `\` needs to be escaped twice, once for the json file, and once for the string in the lua expression):
|
||||
|
||||
```json
|
||||
{
|
||||
"key": "KP1",
|
||||
"command": ["script-message", "evaluate-expressions", "print-text", "!{ string.gsub(%F, '/', '\\\\') }"],
|
||||
}
|
||||
```
|
||||
|
||||
### `run-statement <statement...>`
|
||||
|
||||
Runs the following string a as a Lua statement. This is similar to an [expression](#expressions),
|
||||
but instead of the code evaluating to a value it must run a series of statements. Basically it allows
|
||||
for function bodies to be embedded into custom keybinds. All the same modules are available.
|
||||
If multiple strings are sent to the script-message then they will be concatenated together with newlines.
|
||||
|
||||
The following keybind will use [mpv-user-input](https://github.com/CogentRedTester/mpv-user-input) to
|
||||
rename items in file-browser:
|
||||
|
||||
```json
|
||||
{
|
||||
"key": "KP1",
|
||||
"command": ["script-message", "run-statement",
|
||||
"assert(user_input, 'install mpv-user-input!')",
|
||||
|
||||
"local line, err = user_input.get_user_input_co({",
|
||||
"id = 'rename-file',",
|
||||
"source = 'custom-keybind',",
|
||||
"request_text = 'rename file:',",
|
||||
"queueable = true,",
|
||||
"default_input = %N,",
|
||||
"cursor_pos = #(%N) - #fb.get_extension(%N, '')",
|
||||
"})",
|
||||
|
||||
"if not line then return end",
|
||||
"os.rename(%F, utils.join_path(%P, line))",
|
||||
|
||||
"fb.rescan()"
|
||||
],
|
||||
"parser": "file",
|
||||
"multiselect": true
|
||||
}
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
||||
See [here](file-browser-keybinds.json).
|
||||
@@ -1,118 +0,0 @@
|
||||
[
|
||||
{
|
||||
"key": "KP1",
|
||||
"command": ["print-text", "file: %f"],
|
||||
"multiselect": true
|
||||
},
|
||||
{
|
||||
"key": "KP2",
|
||||
"command": ["print-text", "name: %n"],
|
||||
"multiselect": true
|
||||
},
|
||||
{
|
||||
"key": "KP3",
|
||||
"command": ["print-text", "open directory: %p"]
|
||||
},
|
||||
{
|
||||
"key": "KP4",
|
||||
"command": ["print-text", "directory name: %d"]
|
||||
},
|
||||
{
|
||||
"key": "KP5",
|
||||
"command": ["print-text", "escape the code: %%f"],
|
||||
"multiselect": true
|
||||
},
|
||||
{
|
||||
"key": "KP6",
|
||||
"command": ["print-text", "full filepath via concatenation: %p%n"],
|
||||
"multiselect": true
|
||||
},
|
||||
{
|
||||
"key": "KP7",
|
||||
"command": ["print-text", "quote/escape filepath: %F"],
|
||||
"multiselect": true
|
||||
},
|
||||
|
||||
|
||||
{
|
||||
"comment": "deletes the currently selected file",
|
||||
"key": "Alt+DEL",
|
||||
"command": ["run", "rm", "%F"],
|
||||
"filter": "file",
|
||||
"multiselect": true,
|
||||
"multi-type": "concat"
|
||||
},
|
||||
{
|
||||
"comment": "opens the currently selected items in a new mpv window",
|
||||
"key": "Ctrl+ENTER",
|
||||
"command": ["run", "mpv", "%F"],
|
||||
"multiselect": true,
|
||||
"multi-type": "concat"
|
||||
},
|
||||
{
|
||||
"key": "Ctrl+c",
|
||||
"command": [
|
||||
["run", "powershell", "-command", "Set-Clipboard", "%F"],
|
||||
["print-text", "copied filepath to clipboard"]
|
||||
],
|
||||
"multiselect": true,
|
||||
"delay": 0.3
|
||||
},
|
||||
{
|
||||
"comment": "Opens the current directory in windows explorer",
|
||||
"key": "Ctrl+o",
|
||||
"command": ["run", "powershell", "-command", "explorer.exe", "(( %P ).TrimEnd('/') -replace '/', '\\' )"],
|
||||
"multiselect": false
|
||||
},
|
||||
{
|
||||
"comment": "Opens the selected directory in windows explorer",
|
||||
"key": "Ctrl+O",
|
||||
"command": ["run", "powershell", "-command", "explorer.exe", "(( %F ).TrimEnd('/') -replace '/', '\\' )"],
|
||||
"filter": "dir",
|
||||
"multiselect": true
|
||||
},
|
||||
{
|
||||
"comment": "Opens the current directory in windows explorer and highlights the currently selected file",
|
||||
"key": "Ctrl+O",
|
||||
"command": ["run", "powershell", "-command", "explorer.exe", "'/select,'", "( %F -replace '/', '\\' )"],
|
||||
"filter": "file",
|
||||
"multiselect": true
|
||||
},
|
||||
{
|
||||
"key": "INS",
|
||||
"command": ["run", "powershell", "-command", "Set-Content", "-LiteralPath", "( %P + '/.ordered-chapters.m3u' )", "-Value", "( %N )"],
|
||||
"multiselect": true,
|
||||
"multi-type": "concat",
|
||||
"concat-string": "+ '\n' +"
|
||||
},
|
||||
|
||||
|
||||
{
|
||||
"key": "WHEEL_UP",
|
||||
"command": ["script-binding", "file_browser/dynamic/scroll_up"]
|
||||
},
|
||||
{
|
||||
"key": "WHEEL_DOWN",
|
||||
"command": ["script-binding", "file_browser/dynamic/scroll_down"]
|
||||
},
|
||||
{
|
||||
"key": "MBTN_LEFT",
|
||||
"command": ["script-binding", "file_browser/dynamic/down_dir"]
|
||||
},
|
||||
{
|
||||
"key": "MBTN_RIGHT",
|
||||
"command": ["script-binding", "file_browser/dynamic/up_dir"]
|
||||
},
|
||||
{
|
||||
"key": "MBTN_MID",
|
||||
"command": ["script-binding", "file_browser/dynamic/play"]
|
||||
},
|
||||
{
|
||||
"key": "UP",
|
||||
"command": ["osd-auto", "add", "volume", "2"]
|
||||
},
|
||||
{
|
||||
"key": "DOWN",
|
||||
"command": ["osd-auto", "add", "volume", "-2"]
|
||||
}
|
||||
]
|
||||
@@ -1,175 +0,0 @@
|
||||
#######################################################
|
||||
# This is the default config file for mpv-file-browser
|
||||
# https://github.com/CogentRedTester/mpv-file-browser
|
||||
#######################################################
|
||||
|
||||
# root directories, separated by commas
|
||||
# on linux you will probably want to add `/`,
|
||||
# on windows this should be used to add different drive letters
|
||||
# Examples:
|
||||
# linux: root=~/,/
|
||||
# windows: root=~/,C:/
|
||||
root=~/
|
||||
|
||||
# characters to separate root directories, each character works individually
|
||||
# this is in case one is using directories with strange names
|
||||
root_separators=,;
|
||||
|
||||
# number of entries to show on the screen at once
|
||||
num_entries=20
|
||||
|
||||
# wrap the cursor around the top and bottom of the list
|
||||
wrap=no
|
||||
|
||||
# only show files compatible with mpv in the browser
|
||||
filter_files=yes
|
||||
|
||||
# experimental feature that recurses directories concurrently when appending items to the playlist
|
||||
# this feature has the potential for massive performance improvements when using addons with asynchronous IO
|
||||
concurrent_recursion=no
|
||||
|
||||
# maximum number of recursions that can run concurrently
|
||||
# if this number is too high it risks overflowing the mpv event queue, which will cause some directories to be dropped entirely
|
||||
max_concurrency=16
|
||||
|
||||
# enable custom keybinds
|
||||
# the keybind json file must go in ~~/script-opts
|
||||
custom_keybinds=no
|
||||
|
||||
# file-browser only shows files that are compatible with mpv by default
|
||||
# adding a file extension to this list will add it to the extension whitelist
|
||||
# extensions are separated with the root separators, do not use any spaces
|
||||
extension_whitelist=
|
||||
|
||||
# add file extensions to this list to disable default filetypes
|
||||
# note that this will also override audio/subtitle_extension options below
|
||||
extension_blacklist=
|
||||
|
||||
# files with these extensions will be added as additional audio tracks for the current file instead of appended to the playlist
|
||||
# items on this list are automatically added to the extension whitelist
|
||||
audio_extensions=mka,dts,dtshd,dts-hd,truehd,true-hd
|
||||
|
||||
# files with these extensions will be added as additional subtitle tracks for the current file instead of appended to the playlist
|
||||
# items on this list are automatically added to the extension whitelist
|
||||
subtitle_extensions=etf,etf8,utf-8,idx,sub,srt,rt,ssa,ass,mks,vtt,sup,scc,smi,lrc,pgs
|
||||
|
||||
# filter directories or files starting with a period like .config
|
||||
# for linux systems
|
||||
filter_dot_dirs=no
|
||||
filter_dot_files=no
|
||||
|
||||
# substitude forward slashes for backslashes when appending a local file to the playlist
|
||||
# may be useful on windows systems
|
||||
substitute_backslash=no
|
||||
|
||||
# interpret backslashes `\` in paths as forward slashes `/`
|
||||
# this is useful on Windows, which natively uses backslashes.
|
||||
# As backslashes are valid filename characters in Unix systems this could
|
||||
# cause mangled paths, though such filenames are rare.
|
||||
# Use `yes` and `no` to enable/disable. `auto` tries to use the mpv `platform`
|
||||
# property (mpv v0.36+) to decide. If the property is unavailable it defaults to `yes`.
|
||||
normalise_backslash=auto
|
||||
|
||||
# this option reverses the behaviour of the alt+ENTER keybind
|
||||
# when disabled the keybind is required to enable autoload for the file
|
||||
# when enabled the keybind disables autoload for the file
|
||||
autoload=no
|
||||
|
||||
# if autoload is triggered by selecting the currently playing file, then
|
||||
# the current file will have it's watch-later config saved before being closed and re-opened
|
||||
# essentially the current file will not be restarted
|
||||
autoload_save_current=yes
|
||||
|
||||
# when opening the browser in idle mode prefer the current working directory over the root
|
||||
# note that the working directory is set as the 'current' directory regardless, so `home` will
|
||||
# move the browser there even if this option is set to false
|
||||
default_to_working_directory=no
|
||||
|
||||
# when moving up a directory do not stop on empty protocol schemes like `ftp://`
|
||||
# e.g. moving up from `ftp://localhost/` will move straight to the root instead of `ftp://`
|
||||
skip_protocol_schemes=yes
|
||||
|
||||
# map optical device paths to their respective file paths,
|
||||
# e.g. mapping bd:// to the value of the bluray-device property
|
||||
map_bd_device=yes
|
||||
map_dvd_device=yes
|
||||
map_cdda_device=yes
|
||||
|
||||
# enables addons
|
||||
addons=no
|
||||
addon_directory=~~/script-modules/file-browser-addons
|
||||
|
||||
# directory to load external modules - currently just user-input-module
|
||||
module_directory=~~/script-modules
|
||||
|
||||
# turn the OSC idle screen off and on when opening and closing the browser
|
||||
# this should only be enabled if file-browser is the only thing controlling the idle-screen,
|
||||
# if multiple sources attempt to control the idle-screen at the same time it can cause unexpected behaviour.
|
||||
toggle_idlescreen=no
|
||||
|
||||
# Set the current open status of the browser in the `file_browser/open` field of the `user-data` property.
|
||||
# This property is only available in mpv v0.36+.
|
||||
set_user_data=yes
|
||||
|
||||
# Set the current open status of the browser in the `file_browser-open` field of the `shared-script-properties` property.
|
||||
# This property is deprecated. When it is removed in mpv v0.37 file-browser will automatically disable this option.
|
||||
set_shared_script_properties=no
|
||||
|
||||
####################################
|
||||
######### style settings ###########
|
||||
####################################
|
||||
|
||||
# force file-browser to use a specific text alignment (default: top-left)
|
||||
# uses ass tag alignment numbers: https://aegi.vmoe.info/docs/3.0/ASS_Tags/#index23h3
|
||||
# set to 0 to use the default mpv osd-align options
|
||||
alignment=7
|
||||
|
||||
# The format string used for the header. Uses custom-keybind substitution codes to
|
||||
# dynamically change the contents of the header. See: docs/custom-keybinds.md#codes
|
||||
# e.g. to add file numbers, set this to: {\fnMonospace}[%i/%x]{\fn<font_name_header or blank>} %q\N----------------------------------------------------
|
||||
format_string_header=%q\N----------------------------------------------------
|
||||
|
||||
# The format strings used for the wrappers. Supports custom-keybind substitution codes, and
|
||||
# supports two additional codes: `%<` and `%>` to show the number of items before and after the visible list, respectively.
|
||||
# Setting these options to empty strings will disable the wrappers.
|
||||
format_string_topwrapper=%< item(s) above\N
|
||||
format_string_bottomwrapper=\N%> item(s) remaining
|
||||
|
||||
# allows custom icons be set for the folder and cursor
|
||||
# the `\h` character is a hard space to add padding
|
||||
folder_icon={\p1}m 6.52 0 l 1.63 0 b 0.73 0 0.01 0.73 0.01 1.63 l 0 11.41 b 0 12.32 0.73 13.05 1.63 13.05 l 14.68 13.05 b 15.58 13.05 16.31 12.32 16.31 11.41 l 16.31 3.26 b 16.31 2.36 15.58 1.63 14.68 1.63 l 8.15 1.63{\p0}\h
|
||||
cursor_icon={\p1}m 14.11 6.86 l 0.34 0.02 b 0.25 -0.02 0.13 -0 0.06 0.08 b -0.01 0.16 -0.02 0.28 0.04 0.36 l 3.38 5.55 l 3.38 5.55 3.67 6.15 3.81 6.79 3.79 7.45 3.61 8.08 3.39 8.5l 0.04 13.77 b -0.02 13.86 -0.01 13.98 0.06 14.06 b 0.11 14.11 0.17 14.13 0.24 14.13 b 0.27 14.13 0.31 14.13 0.34 14.11 l 14.11 7.28 b 14.2 7.24 14.25 7.16 14.25 7.07 b 14.25 6.98 14.2 6.9 14.11 6.86{\p0}\h
|
||||
|
||||
# set the opacity of fonts in hexadecimal from 00 (opaque) to FF (transparent)
|
||||
font_opacity_selection_marker=99
|
||||
|
||||
# print the header in bold font
|
||||
font_bold_header=yes
|
||||
|
||||
# scale the size of the browser; 2 would double the size, 0.5 would halve it, etc.
|
||||
# the header and wrapper scaling is relative to the base scaling
|
||||
scaling_factor_base=1
|
||||
scaling_factor_header=1.4
|
||||
scaling_factor_wrappers=0.64
|
||||
|
||||
# set custom font names, blank is the default
|
||||
# setting custom fonts for the folder/cursor can fix broken or missing icons
|
||||
font_name_header=
|
||||
font_name_body=
|
||||
font_name_wrappers=
|
||||
font_name_folder=
|
||||
font_name_cursor=
|
||||
|
||||
# set custom font colours
|
||||
# colours are in hexadecimal format in Blue Green Red order
|
||||
# note that this is the opposite order to most RGB colour codes
|
||||
font_colour_header=00ccff
|
||||
font_colour_body=ffffff
|
||||
font_colour_wrappers=00ccff
|
||||
font_colour_cursor=00ccff
|
||||
|
||||
# these are colours applied to list items in different states
|
||||
font_colour_selected=fce788
|
||||
font_colour_multiselect=fcad88
|
||||
font_colour_playing=33ff66
|
||||
font_colour_playing_multiselected=22b547
|
||||
@@ -1,73 +0,0 @@
|
||||
--[[
|
||||
mpv-file-browser
|
||||
|
||||
This script allows users to browse and open files and folders entirely from within mpv.
|
||||
The script uses nothing outside the mpv API, so should work identically on all platforms.
|
||||
The browser can move up and down directories, start playing files and folders, or add them to the queue.
|
||||
|
||||
For full documentation see: https://github.com/CogentRedTester/mpv-file-browser
|
||||
]]--
|
||||
|
||||
local mp = require 'mp'
|
||||
|
||||
local o = require 'modules.options'
|
||||
|
||||
-- setting the package paths
|
||||
package.path = mp.command_native({"expand-path", o.module_directory}).."/?.lua;"..package.path
|
||||
|
||||
local addons = require 'modules.addons'
|
||||
local keybinds = require 'modules.keybinds'
|
||||
local setup = require 'modules.setup'
|
||||
local controls = require 'modules.controls'
|
||||
local observers = require 'modules.observers'
|
||||
local script_messages = require 'modules.script-messages'
|
||||
|
||||
local input_loaded, input = pcall(require, "mp.input")
|
||||
local user_input_loaded, user_input = pcall(require, "user-input-module")
|
||||
|
||||
|
||||
-- root and addon setup
|
||||
setup.root()
|
||||
addons.load_internal_parsers()
|
||||
if o.addons then addons.load_external_addons() end
|
||||
|
||||
--these need to be below the addon setup in case any parsers add custom entries
|
||||
setup.extensions_list()
|
||||
keybinds.setup_keybinds()
|
||||
|
||||
-- property observers
|
||||
mp.observe_property('path', 'string', observers.current_directory)
|
||||
if o.map_dvd_device then mp.observe_property('dvd-device', 'string', observers.dvd_device) end
|
||||
if o.map_bd_device then mp.observe_property('bluray-device', 'string', observers.bd_device) end
|
||||
if o.map_cdda_device then mp.observe_property('cdda-device', 'string', observers.cd_device) end
|
||||
|
||||
-- scripts messages
|
||||
mp.register_script_message('=>', script_messages.chain)
|
||||
mp.register_script_message('delay-command', script_messages.delay_command)
|
||||
mp.register_script_message('conditional-command', script_messages.conditional_command)
|
||||
mp.register_script_message('evaluate-expressions', script_messages.evaluate_expressions)
|
||||
mp.register_script_message('run-statement', script_messages.run_statement)
|
||||
|
||||
mp.register_script_message('browse-directory', controls.browse_directory)
|
||||
mp.register_script_message("get-directory-contents", script_messages.get_directory_contents)
|
||||
|
||||
--declares the keybind to open the browser
|
||||
mp.add_key_binding('MENU','browse-files', controls.toggle)
|
||||
mp.add_key_binding('Ctrl+o','open-browser', controls.open)
|
||||
|
||||
if input_loaded then
|
||||
mp.add_key_binding("Alt+o", "browse-directory/get-user-input", function()
|
||||
input.get({
|
||||
prompt = "open directory:",
|
||||
id = "file-browser/browse-directory",
|
||||
submit = function(text)
|
||||
controls.browse_directory(text)
|
||||
input.terminate()
|
||||
end
|
||||
})
|
||||
end)
|
||||
elseif user_input_loaded then
|
||||
mp.add_key_binding("Alt+o", "browse-directory/get-user-input", function()
|
||||
user_input.get_user_input(controls.browse_directory, {request_text = "open directory:"})
|
||||
end)
|
||||
end
|
||||
@@ -1,174 +0,0 @@
|
||||
local mp = require 'mp'
|
||||
local msg = require 'mp.msg'
|
||||
local utils = require 'mp.utils'
|
||||
|
||||
local o = require 'modules.options'
|
||||
local g = require 'modules.globals'
|
||||
local fb = require 'modules.apis.fb'
|
||||
local fb_utils = require 'modules.utils'
|
||||
local parser_API = require 'modules.apis.parser'
|
||||
|
||||
local API_MAJOR, API_MINOR, API_PATCH = g.API_VERSION:match("(%d+)%.(%d+)%.(%d+)")
|
||||
API_MAJOR, API_MINOR, API_PATCH = tonumber(API_MAJOR), tonumber(API_MINOR), tonumber(API_PATCH)
|
||||
|
||||
--checks if the given parser has a valid version number
|
||||
local function check_api_version(parser, id)
|
||||
if parser.version then
|
||||
msg.warn(('%s: use of the `version` field is deprecated - use `api_version` instead'):format(id))
|
||||
parser.api_version = parser.version
|
||||
end
|
||||
|
||||
local version = parser.api_version
|
||||
if type(version) ~= 'string' then return msg.error(("%s: field `api_version` must be a string, got %s"):format(id, tostring(version))) end
|
||||
|
||||
local major, minor = version:match("(%d+)%.(%d+)")
|
||||
major, minor = tonumber(major), tonumber(minor)
|
||||
|
||||
if not major or not minor then
|
||||
return msg.error(("%s: invalid version number, expected v%d.%d.x, got v%s"):format(id, API_MAJOR, API_MINOR, version))
|
||||
elseif major ~= API_MAJOR then
|
||||
return msg.error(("%s has wrong major version number, expected v%d.x.x, got, v%s"):format(id, API_MAJOR, version))
|
||||
elseif minor > API_MINOR then
|
||||
msg.warn(("%s has newer minor version number than API, expected v%d.%d.x, got v%s"):format(id, API_MAJOR, API_MINOR, version))
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
--create a unique id for the given parser
|
||||
local function set_parser_id(parser)
|
||||
local name = parser.name
|
||||
if g.parsers[name] then
|
||||
local n = 2
|
||||
name = parser.name.."_"..n
|
||||
while g.parsers[name] do
|
||||
n = n + 1
|
||||
name = parser.name.."_"..n
|
||||
end
|
||||
end
|
||||
|
||||
g.parsers[name] = parser
|
||||
g.parsers[parser] = { id = name }
|
||||
end
|
||||
|
||||
--runs an addon in a separate environment
|
||||
local function run_addon(path)
|
||||
local name_sqbr = string.format("[%s]", path:match("/([^/]*)%.lua$"))
|
||||
local addon_environment = fb_utils.redirect_table(_G)
|
||||
addon_environment._G = addon_environment
|
||||
|
||||
--gives each addon custom debug messages
|
||||
addon_environment.package = fb_utils.redirect_table(addon_environment.package)
|
||||
addon_environment.package.loaded = fb_utils.redirect_table(addon_environment.package.loaded)
|
||||
local msg_module = {
|
||||
log = function(level, ...) msg.log(level, name_sqbr, ...) end,
|
||||
fatal = function(...) return msg.fatal(name_sqbr, ...) end,
|
||||
error = function(...) return msg.error(name_sqbr, ...) end,
|
||||
warn = function(...) return msg.warn(name_sqbr, ...) end,
|
||||
info = function(...) return msg.info(name_sqbr, ...) end,
|
||||
verbose = function(...) return msg.verbose(name_sqbr, ...) end,
|
||||
debug = function(...) return msg.debug(name_sqbr, ...) end,
|
||||
trace = function(...) return msg.trace(name_sqbr, ...) end,
|
||||
}
|
||||
addon_environment.print = msg_module.info
|
||||
|
||||
addon_environment.require = function(module)
|
||||
if module == "mp.msg" then return msg_module end
|
||||
return require(module)
|
||||
end
|
||||
|
||||
local chunk, err
|
||||
if setfenv then
|
||||
--since I stupidly named a function loadfile I need to specify the global one
|
||||
--I've been using the name too long to want to change it now
|
||||
chunk, err = _G.loadfile(path)
|
||||
if not chunk then return msg.error(err) end
|
||||
setfenv(chunk, addon_environment)
|
||||
else
|
||||
chunk, err = _G.loadfile(path, "bt", addon_environment)
|
||||
if not chunk then return msg.error(err) end
|
||||
end
|
||||
|
||||
local success, result = xpcall(chunk, fb_utils.traceback)
|
||||
return success and result or nil
|
||||
end
|
||||
|
||||
--setup an internal or external parser
|
||||
local function setup_parser(parser, file)
|
||||
parser = setmetatable(parser, { __index = parser_API })
|
||||
parser.name = parser.name or file:gsub("%-browser%.lua$", ""):gsub("%.lua$", "")
|
||||
|
||||
set_parser_id(parser)
|
||||
if not check_api_version(parser, file) then return msg.error("aborting load of parser", parser:get_id(), "from", file) end
|
||||
|
||||
msg.verbose("imported parser", parser:get_id(), "from", file)
|
||||
|
||||
--sets missing functions
|
||||
if not parser.can_parse then
|
||||
if parser.parse then parser.can_parse = function() return true end
|
||||
else parser.can_parse = function() return false end end
|
||||
end
|
||||
|
||||
if parser.priority == nil then parser.priority = 0 end
|
||||
if type(parser.priority) ~= "number" then return msg.error("parser", parser:get_id(), "needs a numeric priority") end
|
||||
|
||||
table.insert(g.parsers, parser)
|
||||
end
|
||||
|
||||
--load an external addon
|
||||
local function setup_addon(file, path)
|
||||
if file:sub(-4) ~= ".lua" then return msg.verbose(path, "is not a lua file - aborting addon setup") end
|
||||
|
||||
local addon_parsers = run_addon(path)
|
||||
if addon_parsers and not next(addon_parsers) then return msg.verbose('addon', path, 'returned empry table - special case, ignoring') end
|
||||
if not addon_parsers or type(addon_parsers) ~= "table" then return msg.error("addon", path, "did not return a table") end
|
||||
|
||||
--if the table contains a priority key then we assume it isn't an array of parsers
|
||||
if not addon_parsers[1] then addon_parsers = {addon_parsers} end
|
||||
|
||||
for _, parser in ipairs(addon_parsers) do
|
||||
setup_parser(parser, file)
|
||||
end
|
||||
end
|
||||
|
||||
--loading external addons
|
||||
local function load_addons(directory)
|
||||
directory = fb_utils.fix_path(directory, true)
|
||||
|
||||
local files = utils.readdir(directory)
|
||||
if not files then error("could not read addon directory") end
|
||||
|
||||
for _, file in ipairs(files) do
|
||||
setup_addon(file, directory..file)
|
||||
end
|
||||
table.sort(g.parsers, function(a, b) return a.priority < b.priority end)
|
||||
|
||||
--we want to store the indexes of the parsers
|
||||
for i = #g.parsers, 1, -1 do g.parsers[ g.parsers[i] ].index = i end
|
||||
|
||||
--we want to run the setup functions for each addon
|
||||
for index, parser in ipairs(g.parsers) do
|
||||
if parser.setup then
|
||||
local success = xpcall(function() parser:setup() end, fb_utils.traceback)
|
||||
if not success then
|
||||
msg.error("parser", parser:get_id(), "threw an error in the setup method - removing from list of parsers")
|
||||
table.remove(g.parsers, index)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function load_internal_parsers()
|
||||
local internal_addon_dir = mp.get_script_directory()..'/modules/parsers/'
|
||||
load_addons(internal_addon_dir)
|
||||
end
|
||||
|
||||
local function load_external_addons()
|
||||
local addon_dir = mp.command_native({"expand-path", o.addon_directory..'/'})
|
||||
load_addons(addon_dir)
|
||||
end
|
||||
|
||||
return {
|
||||
check_api_version = check_api_version,
|
||||
load_internal_parsers = load_internal_parsers,
|
||||
load_external_addons = load_external_addons
|
||||
}
|
||||
@@ -1,136 +0,0 @@
|
||||
local msg = require 'mp.msg'
|
||||
local utils = require 'mp.utils'
|
||||
|
||||
local o = require 'modules.options'
|
||||
local g = require 'modules.globals'
|
||||
local fb_utils = require 'modules.utils'
|
||||
local ass = require 'modules.ass'
|
||||
local directory_movement = require 'modules.navigation.directory-movement'
|
||||
local scanning = require 'modules.navigation.scanning'
|
||||
local cache = require 'modules.cache'
|
||||
local controls = require 'modules.controls'
|
||||
|
||||
local fb = setmetatable({}, { __index = setmetatable({}, { __index = fb_utils }) })
|
||||
package.loaded["file-browser"] = setmetatable({}, { __index = fb })
|
||||
|
||||
--these functions we'll provide as-is
|
||||
fb.redraw = ass.update_ass
|
||||
fb.rescan = scanning.rescan
|
||||
fb.browse_directory = controls.browse_directory
|
||||
|
||||
function fb.clear_cache()
|
||||
cache:clear()
|
||||
end
|
||||
|
||||
--a wrapper around scan_directory for addon API
|
||||
function fb.parse_directory(directory, parse_state)
|
||||
if not parse_state then parse_state = { source = "addon" }
|
||||
elseif not parse_state.source then parse_state.source = "addon" end
|
||||
return scanning.scan_directory(directory, parse_state)
|
||||
end
|
||||
|
||||
--register file extensions which can be opened by the browser
|
||||
function fb.register_parseable_extension(ext)
|
||||
g.parseable_extensions[string.lower(ext)] = true
|
||||
end
|
||||
function fb.remove_parseable_extension(ext)
|
||||
g.parseable_extensions[string.lower(ext)] = nil
|
||||
end
|
||||
|
||||
--add a compatible extension to show through the filter, only applies if run during the setup() method
|
||||
function fb.add_default_extension(ext)
|
||||
table.insert(g.compatible_file_extensions, ext)
|
||||
end
|
||||
|
||||
--add item to root at position pos
|
||||
function fb.insert_root_item(item, pos)
|
||||
msg.debug("adding item to root", item.label or item.name, pos)
|
||||
item.ass = item.ass or fb.ass_escape(item.label or item.name)
|
||||
item.type = "dir"
|
||||
table.insert(g.root, pos or (#g.root + 1), item)
|
||||
end
|
||||
|
||||
-- add a new mapping to the given directory
|
||||
function fb.register_directory_mapping(directory, mapping, pattern)
|
||||
if not pattern then mapping = '^'..fb_utils.pattern_escape(mapping) end
|
||||
g.directory_mappings[mapping] = directory
|
||||
msg.verbose('registering directory alias', mapping, directory)
|
||||
|
||||
directory_movement.set_current_file(g.current_file.original_path)
|
||||
return mapping
|
||||
end
|
||||
|
||||
-- remove all directory mappings that map to the given directory
|
||||
function fb.remove_all_mappings(directory)
|
||||
local removed = {}
|
||||
for mapping, target in pairs(g.directory_mappings) do
|
||||
if target == directory then
|
||||
g.directory_mappings[mapping] = nil
|
||||
table.insert(removed, mapping)
|
||||
end
|
||||
end
|
||||
return removed
|
||||
end
|
||||
|
||||
--a newer API for adding items to the root
|
||||
--only adds the item if the same item does not already exist in the root
|
||||
--the priority variable is a number that specifies the insertion location
|
||||
--a lower priority is placed higher in the list and the default is 100
|
||||
function fb.register_root_item(item, priority)
|
||||
msg.verbose('registering root item:', utils.to_string(item))
|
||||
if type(item) == 'string' then
|
||||
item = {name = item}
|
||||
end
|
||||
|
||||
-- if the item is already in the list then do nothing
|
||||
if fb.list.some(g.root, function(r)
|
||||
return fb.get_full_path(r, '') == fb.get_full_path(item, '')
|
||||
end) then return false end
|
||||
|
||||
item._priority = priority
|
||||
for i, v in ipairs(g.root) do
|
||||
if (v._priority or 100) > (priority or 100) then
|
||||
fb.insert_root_item(item, i)
|
||||
return true
|
||||
end
|
||||
end
|
||||
fb.insert_root_item(item)
|
||||
return true
|
||||
end
|
||||
|
||||
--providing getter and setter functions so that addons can't modify things directly
|
||||
function fb.get_script_opts() return fb.copy_table(o) end
|
||||
function fb.get_opt(key) return o[key] end
|
||||
function fb.get_extensions() return fb.copy_table(g.extensions) end
|
||||
function fb.get_sub_extensions() return fb.copy_table(g.sub_extensions) end
|
||||
function fb.get_audio_extensions() return fb.copy_table(g.audio_extensions) end
|
||||
function fb.get_parseable_extensions() return fb.copy_table(g.parseable_extensions) end
|
||||
function fb.get_state() return fb.copy_table(g.state) end
|
||||
function fb.get_dvd_device() return g.dvd_device end
|
||||
function fb.get_parsers() return fb.copy_table(g.parsers) end
|
||||
function fb.get_root() return fb.copy_table(g.root) end
|
||||
function fb.get_directory() return g.state.directory end
|
||||
function fb.get_list() return fb.copy_table(g.state.list) end
|
||||
function fb.get_current_file() return fb.copy_table(g.current_file) end
|
||||
function fb.get_current_parser() return g.state.parser:get_id() end
|
||||
function fb.get_current_parser_keyname() return g.state.parser.keybind_name or g.state.parser.name end
|
||||
function fb.get_selected_index() return g.state.selected end
|
||||
function fb.get_selected_item() return fb.copy_table(g.state.list[g.state.selected]) end
|
||||
function fb.get_open_status() return not g.state.hidden end
|
||||
function fb.get_parse_state(co) return g.parse_states[co or coroutine.running() or ""] end
|
||||
|
||||
function fb.set_empty_text(str)
|
||||
g.state.empty_text = str
|
||||
fb.redraw()
|
||||
end
|
||||
|
||||
function fb.set_selected_index(index)
|
||||
if type(index) ~= "number" then return false end
|
||||
if index < 1 then index = 1 end
|
||||
if index > #g.state.list then index = #g.state.list end
|
||||
g.state.selected = index
|
||||
fb.redraw()
|
||||
return index
|
||||
end
|
||||
|
||||
return fb
|
||||
@@ -1,32 +0,0 @@
|
||||
|
||||
local msg = require 'mp.msg'
|
||||
|
||||
local g = require 'modules.globals'
|
||||
|
||||
local parse_state_API = {}
|
||||
|
||||
--a wrapper around coroutine.yield that aborts the coroutine if
|
||||
--the parse request was cancelled by the user
|
||||
--the coroutine is
|
||||
function parse_state_API:yield(...)
|
||||
local co = coroutine.running()
|
||||
local is_browser = co == g.state.co
|
||||
if self.source == "browser" and not is_browser then
|
||||
msg.error("current coroutine does not match browser's expected coroutine - did you unsafely yield before this?")
|
||||
error("current coroutine does not match browser's expected coroutine - aborting the parse")
|
||||
end
|
||||
|
||||
local result = table.pack(coroutine.yield(...))
|
||||
if is_browser and co ~= g.state.co then
|
||||
msg.verbose("browser no longer waiting for list - aborting parse for", self.directory)
|
||||
error(g.ABORT_ERROR)
|
||||
end
|
||||
return unpack(result, 1, result.n)
|
||||
end
|
||||
|
||||
--checks if the current coroutine is the one handling the browser's request
|
||||
function parse_state_API:is_coroutine_current()
|
||||
return coroutine.running() == g.state.co
|
||||
end
|
||||
|
||||
return parse_state_API
|
||||
@@ -1,25 +0,0 @@
|
||||
local msg = require 'mp.msg'
|
||||
|
||||
local g = require 'modules.globals'
|
||||
local scanning = require 'modules.navigation.scanning'
|
||||
local fb = require 'modules.apis.fb'
|
||||
|
||||
local parser_api = setmetatable({}, { __index = fb })
|
||||
|
||||
function parser_api:get_index() return g.parsers[self].index end
|
||||
function parser_api:get_id() return g.parsers[self].id end
|
||||
|
||||
--a wrapper that passes the parsers priority value if none other is specified
|
||||
function parser_api:register_root_item(item, priority)
|
||||
return fb.register_root_item(item, priority or g.parsers[self:get_id()].priority)
|
||||
end
|
||||
|
||||
--runs choose_and_parse starting from the next parser
|
||||
function parser_api:defer(directory)
|
||||
msg.trace("deferring to other parsers...")
|
||||
local list, opts = scanning.choose_and_parse(directory, self:get_index() + 1)
|
||||
fb.get_parse_state().already_deferred = true
|
||||
return list, opts
|
||||
end
|
||||
|
||||
return parser_api
|
||||
@@ -1,175 +0,0 @@
|
||||
--------------------------------------------------------------------------------------------------------
|
||||
-----------------------------------------List Formatting------------------------------------------------
|
||||
--------------------------------------------------------------------------------------------------------
|
||||
--------------------------------------------------------------------------------------------------------
|
||||
|
||||
local utils = require 'mp.utils'
|
||||
|
||||
local g = require 'modules.globals'
|
||||
local o = require 'modules.options'
|
||||
local fb_utils = require 'modules.utils'
|
||||
|
||||
local state = g.state
|
||||
local style = g.style
|
||||
local ass = g.ass
|
||||
|
||||
local function draw()
|
||||
ass:update()
|
||||
end
|
||||
|
||||
local function remove()
|
||||
ass:remove()
|
||||
end
|
||||
|
||||
local string_buffer = {}
|
||||
|
||||
--appends the entered text to the overlay
|
||||
local function append(...)
|
||||
for i = 1, select("#", ...) do
|
||||
table.insert(string_buffer, select(i, ...) or '' )
|
||||
end
|
||||
end
|
||||
|
||||
--appends a newline character to the osd
|
||||
local function newline()
|
||||
table.insert(string_buffer, '\\N')
|
||||
end
|
||||
|
||||
local function flush_buffer()
|
||||
ass.data = table.concat(string_buffer, '')
|
||||
string_buffer = {}
|
||||
end
|
||||
|
||||
--detects whether or not to highlight the given entry as being played
|
||||
local function highlight_entry(v)
|
||||
if g.current_file.path == nil then return false end
|
||||
local full_path = fb_utils.get_full_path(v)
|
||||
local alt_path = v.name and g.state.directory..v.name or nil
|
||||
|
||||
if fb_utils.parseable_item(v) then
|
||||
return string.find(g.current_file.directory, full_path, 1, true)
|
||||
or (alt_path and string.find(g.current_file.directory, alt_path, 1, true))
|
||||
else
|
||||
return g.current_file.path == full_path
|
||||
or (alt_path and g.current_file.path == alt_path)
|
||||
end
|
||||
end
|
||||
|
||||
local ass_cache = setmetatable({}, {__mode = 'k'})
|
||||
|
||||
-- escape ass values and replace newlines
|
||||
local function ass_escape(str)
|
||||
if ass_cache[str] then return ass_cache[str] end
|
||||
local escaped = fb_utils.ass_escape(str, true)
|
||||
ass_cache[str] = escaped
|
||||
return escaped
|
||||
end
|
||||
|
||||
--refreshes the ass text using the contents of the list
|
||||
local function update_ass()
|
||||
if state.hidden then state.flag_update = true ; return end
|
||||
|
||||
append(style.global)
|
||||
|
||||
local dir_name = state.directory_label or state.directory
|
||||
if dir_name == "" then dir_name = "ROOT" end
|
||||
append(style.header)
|
||||
append(fb_utils.substitute_codes(o.format_string_header, nil, nil, nil, ass_escape))
|
||||
newline()
|
||||
|
||||
if #state.list < 1 then
|
||||
append(state.empty_text)
|
||||
flush_buffer()
|
||||
draw()
|
||||
return
|
||||
end
|
||||
|
||||
local start = 1
|
||||
local finish = start+o.num_entries-1
|
||||
|
||||
--handling cursor positioning
|
||||
local mid = math.ceil(o.num_entries/2)+1
|
||||
if state.selected+mid > finish then
|
||||
local offset = state.selected - finish + mid
|
||||
|
||||
--if we've overshot the end of the list then undo some of the offset
|
||||
if finish + offset > #state.list then
|
||||
offset = offset - ((finish+offset) - #state.list)
|
||||
end
|
||||
|
||||
start = start + offset
|
||||
finish = finish + offset
|
||||
end
|
||||
|
||||
--making sure that we don't overstep the boundaries
|
||||
if start < 1 then start = 1 end
|
||||
local overflow = finish < #state.list
|
||||
--this is necessary when the number of items in the dir is less than the max
|
||||
if not overflow then finish = #state.list end
|
||||
|
||||
-- these are the number values to place into the wrappers
|
||||
local wrapper_overrides = {['<'] = tostring(start-1), ['>'] = tostring(#state.list-finish)}
|
||||
|
||||
--adding a header to show there are items above in the list
|
||||
if o.format_string_topwrapper ~= '' and start > 1 then
|
||||
append(style.footer_header, fb_utils.substitute_codes(o.format_string_topwrapper, wrapper_overrides, nil, nil, ass_escape))
|
||||
newline()
|
||||
end
|
||||
|
||||
for i=start, finish do
|
||||
local v = state.list[i]
|
||||
local playing_file = highlight_entry(v)
|
||||
append(style.body)
|
||||
|
||||
--handles custom styles for different entries
|
||||
if i == state.selected or i == state.multiselect_start then
|
||||
if not (i == state.selected) then append(style.selection_marker) end
|
||||
|
||||
if not state.multiselect_start then append(style.cursor)
|
||||
else
|
||||
if state.selection[state.multiselect_start] then append(style.cursor_select)
|
||||
else append(style.cursor_deselect) end
|
||||
end
|
||||
append(o.cursor_icon, "\\h", style.body)
|
||||
else
|
||||
append(g.style.indent, o.cursor_icon, "\\h", style.body)
|
||||
end
|
||||
|
||||
--sets the selection colour scheme
|
||||
local multiselected = state.selection[i]
|
||||
|
||||
--sets the colour for the item
|
||||
local function set_colour()
|
||||
if multiselected then append(style.multiselect)
|
||||
elseif i == state.selected then append(style.selected) end
|
||||
|
||||
if playing_file then append( multiselected and style.playing_selected or style.playing) end
|
||||
end
|
||||
set_colour()
|
||||
|
||||
--sets the folder icon
|
||||
if v.type == 'dir' then
|
||||
append(style.folder, o.folder_icon, "\\h", style.body)
|
||||
set_colour()
|
||||
end
|
||||
|
||||
--adds the actual name of the item
|
||||
append(v.ass or ass_escape(v.label or v.name))
|
||||
newline()
|
||||
end
|
||||
|
||||
if o.format_string_bottomwrapper ~= '' and overflow then
|
||||
append(style.footer_header)
|
||||
append(fb_utils.substitute_codes(o.format_string_bottomwrapper, wrapper_overrides, nil, nil, ass_escape))
|
||||
end
|
||||
|
||||
flush_buffer()
|
||||
draw()
|
||||
end
|
||||
|
||||
return {
|
||||
update_ass = update_ass,
|
||||
highlight_entry = highlight_entry,
|
||||
draw = draw,
|
||||
remove = remove,
|
||||
}
|
||||
@@ -1,139 +0,0 @@
|
||||
--------------------------------------------------------------------------------------------------------
|
||||
--------------------------------------Cache Implementation----------------------------------------------
|
||||
--------------------------------------------------------------------------------------------------------
|
||||
--------------------------------------------------------------------------------------------------------
|
||||
|
||||
local msg = require 'mp.msg'
|
||||
local utils = require 'mp.utils'
|
||||
|
||||
local g = require 'modules.globals'
|
||||
local fb_utils = require 'modules.utils'
|
||||
|
||||
local function get_keys(t)
|
||||
local keys = {}
|
||||
for key in pairs(t) do
|
||||
table.insert(keys, key)
|
||||
end
|
||||
return keys
|
||||
end
|
||||
|
||||
local cache = {
|
||||
cache = setmetatable({}, {__mode = 'kv'}),
|
||||
traversal_stack = {},
|
||||
history = {},
|
||||
cached_values = {
|
||||
"directory", "directory_label", "list", "selected", "selection", "parser", "empty_text", "co"
|
||||
},
|
||||
dangling_refs = {},
|
||||
}
|
||||
|
||||
function cache:print_debug_info()
|
||||
local cache_keys = get_keys(self.cache)
|
||||
msg.verbose('Printing cache debug info')
|
||||
msg.verbose('cache size:', #cache_keys)
|
||||
msg.debug(utils.to_string(cache_keys))
|
||||
msg.trace(utils.to_string(self.cache[cache_keys[#cache_keys]]))
|
||||
|
||||
msg.verbose('traversal_stack size:', #self.traversal_stack)
|
||||
msg.debug(utils.to_string(fb_utils.list.map(self.traversal_stack, function(ref) return ref.directory end)))
|
||||
|
||||
msg.verbose('history size:', #self.history)
|
||||
msg.debug(utils.to_string(fb_utils.list.map(self.history, function(ref) return ref.directory end)))
|
||||
end
|
||||
|
||||
function cache:replace_dangling_refs(directory, ref)
|
||||
for _, v in ipairs(self.traversal_stack) do
|
||||
if v.directory == directory then
|
||||
v.ref = ref
|
||||
self.dangling_refs[directory] = nil
|
||||
end
|
||||
end
|
||||
for _, v in ipairs(self.history) do
|
||||
if v.directory == directory then
|
||||
v.ref = ref
|
||||
self.dangling_refs[directory] = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function cache:add_current_state()
|
||||
local directory = g.state.directory
|
||||
if directory == nil then return end
|
||||
|
||||
local t = self.cache[directory] or {}
|
||||
for _, value in ipairs(self.cached_values) do
|
||||
t[value] = g.state[value]
|
||||
end
|
||||
|
||||
self.cache[directory] = t
|
||||
if self.dangling_refs[directory] then
|
||||
self:replace_dangling_refs(directory, t)
|
||||
end
|
||||
end
|
||||
|
||||
-- Creates a reference to the cache of a particular directory to prevent it
|
||||
-- from being garbage collected.
|
||||
function cache:get_cache_ref(directory)
|
||||
return {
|
||||
directory = directory,
|
||||
ref = self.cache[directory],
|
||||
}
|
||||
end
|
||||
|
||||
function cache:append_history()
|
||||
self:add_current_state()
|
||||
local history_size = #self.history
|
||||
|
||||
-- We don't want to have the same directory in the history over and over again.
|
||||
if history_size > 0 and self.history[history_size].directory == g.state.directory then return end
|
||||
|
||||
table.insert(self.history, self:get_cache_ref(g.state.directory))
|
||||
if (history_size + 1) > 100 then table.remove(self.history, 1) end
|
||||
end
|
||||
|
||||
function cache:in_cache(directory)
|
||||
return self.cache[directory] ~= nil
|
||||
end
|
||||
|
||||
function cache:apply(directory)
|
||||
directory = directory or g.state.directory
|
||||
local t = self.cache[directory]
|
||||
if not t then return false end
|
||||
|
||||
msg.verbose('applying cache for', directory)
|
||||
|
||||
for _, value in ipairs(self.cached_values) do
|
||||
msg.debug('setting', value, 'to', t[value])
|
||||
g.state[value] = t[value]
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
function cache:push()
|
||||
local stack_size = #self.traversal_stack
|
||||
if stack_size > 0 and self.traversal_stack[stack_size].directory == g.state.directory then return end
|
||||
table.insert(self.traversal_stack, self:get_cache_ref(g.state.directory))
|
||||
end
|
||||
|
||||
function cache:pop()
|
||||
table.remove(self.traversal_stack)
|
||||
end
|
||||
|
||||
function cache:clear_traversal_stack()
|
||||
self.traversal_stack = {}
|
||||
end
|
||||
|
||||
function cache:clear()
|
||||
self.cache = setmetatable({}, {__mode = 'kv'})
|
||||
for _, v in ipairs(self.traversal_stack) do
|
||||
v.ref = nil
|
||||
self.dangling_refs[v.directory] = true
|
||||
end
|
||||
for _, v in ipairs(self.history) do
|
||||
v.ref = nil
|
||||
self.dangling_refs[v.directory] = true
|
||||
end
|
||||
end
|
||||
|
||||
return cache
|
||||
@@ -1,90 +0,0 @@
|
||||
|
||||
local mp = require 'mp'
|
||||
local msg = require 'mp.msg'
|
||||
local utils = require 'mp.utils'
|
||||
|
||||
local o = require 'modules.options'
|
||||
local g = require 'modules.globals'
|
||||
local fb_utils = require 'modules.utils'
|
||||
local movement = require 'modules.navigation.directory-movement'
|
||||
local ass = require 'modules.ass'
|
||||
local cursor = require 'modules.navigation.cursor'
|
||||
|
||||
local controls = {}
|
||||
|
||||
--opens the browser
|
||||
function controls.open()
|
||||
if not g.state.hidden then return end
|
||||
|
||||
for _,v in ipairs(g.state.keybinds) do
|
||||
mp.add_forced_key_binding(v[1], 'dynamic/'..v[2], v[3], v[4])
|
||||
end
|
||||
|
||||
if o.set_shared_script_properties then utils.shared_script_property_set('file_browser-open', 'yes') end
|
||||
if o.set_user_data then mp.set_property_bool('user-data/file_browser/open', true) end
|
||||
|
||||
if o.toggle_idlescreen then mp.commandv('script-message', 'osc-idlescreen', 'no', 'no_osd') end
|
||||
g.state.hidden = false
|
||||
if g.state.directory == nil then
|
||||
local path = mp.get_property('path')
|
||||
if path or o.default_to_working_directory then movement.goto_current_dir() else movement.goto_root() end
|
||||
return
|
||||
end
|
||||
|
||||
if not g.state.flag_update then ass.draw()
|
||||
else g.state.flag_update = false ; ass.update_ass() end
|
||||
end
|
||||
|
||||
--closes the list and sets the hidden flag
|
||||
function controls.close()
|
||||
if g.state.hidden then return end
|
||||
|
||||
for _,v in ipairs(g.state.keybinds) do
|
||||
mp.remove_key_binding('dynamic/'..v[2])
|
||||
end
|
||||
|
||||
if o.set_shared_script_properties then utils.shared_script_property_set("file_browser-open", "no") end
|
||||
if o.set_user_data then mp.set_property_bool('user-data/file_browser/open', false) end
|
||||
|
||||
if o.toggle_idlescreen then mp.commandv('script-message', 'osc-idlescreen', 'yes', 'no_osd') end
|
||||
g.state.hidden = true
|
||||
ass.remove()
|
||||
end
|
||||
|
||||
--toggles the list
|
||||
function controls.toggle()
|
||||
if g.state.hidden then controls.open()
|
||||
else controls.close() end
|
||||
end
|
||||
|
||||
--run when the escape key is used
|
||||
function controls.escape()
|
||||
--if multiple items are selection cancel the
|
||||
--selection instead of closing the browser
|
||||
if next(g.state.selection) or g.state.multiselect_start then
|
||||
g.state.selection = {}
|
||||
cursor.disable_select_mode()
|
||||
ass.update_ass()
|
||||
return
|
||||
end
|
||||
controls.close()
|
||||
end
|
||||
|
||||
--opens a specific directory
|
||||
function controls.browse_directory(directory, open_browser)
|
||||
if not directory then return end
|
||||
if open_browser == nil then open_browser = true end
|
||||
|
||||
directory = mp.command_native({"expand-path", directory}) or ''
|
||||
-- directory = join_path( mp.get_property("working-directory", ""), directory )
|
||||
|
||||
if directory ~= "" then directory = fb_utils.fix_path(directory, true) end
|
||||
msg.verbose('recieved directory from script message: '..directory)
|
||||
|
||||
directory = fb_utils.resolve_directory_mapping(directory)
|
||||
local co = movement.goto_directory(directory)
|
||||
if open_browser then controls.open() end
|
||||
return co
|
||||
end
|
||||
|
||||
return controls
|
||||
@@ -1,115 +0,0 @@
|
||||
--------------------------------------------------------------------------------------------------------
|
||||
------------------------------------------Variable Setup------------------------------------------------
|
||||
--------------------------------------------------------------------------------------------------------
|
||||
--------------------------------------------------------------------------------------------------------
|
||||
|
||||
local mp = require 'mp'
|
||||
|
||||
local globals = {}
|
||||
local o = require 'modules.options'
|
||||
|
||||
--sets the version for the file-browser API
|
||||
globals.API_VERSION = "1.7.0"
|
||||
|
||||
--gets the current platform (only works in mpv v0.36+)
|
||||
globals.PLATFORM = mp.get_property_native('platform')
|
||||
|
||||
--the osd_overlay API was not added until v0.31. The expand-path command was not added until 0.30
|
||||
assert(mp.create_osd_overlay, "Script requires minimum mpv version 0.33")
|
||||
|
||||
globals.ass = mp.create_osd_overlay("ass-events")
|
||||
globals.ass.res_y = 720 / o.scaling_factor_base
|
||||
|
||||
local BASE_FONT_SIZE = 25
|
||||
|
||||
globals.style = {
|
||||
global = o.alignment == 0 and "" or ([[{\an%d}]]):format(o.alignment),
|
||||
|
||||
-- full line styles
|
||||
header = ([[{\r\q2\b%s\fs%d\fn%s\c&H%s&}]]):format((o.font_bold_header and "1" or "0"), o.scaling_factor_header*BASE_FONT_SIZE, o.font_name_header, o.font_colour_header),
|
||||
body = ([[{\r\q2\fs%d\fn%s\c&H%s&}]]):format(BASE_FONT_SIZE, o.font_name_body, o.font_colour_body),
|
||||
footer_header = ([[{\r\q2\fs%d\fn%s\c&H%s&}]]):format(o.scaling_factor_wrappers*BASE_FONT_SIZE, o.font_name_wrappers, o.font_colour_wrappers),
|
||||
|
||||
--small section styles (for colours)
|
||||
multiselect = ([[{\c&H%s&}]]):format(o.font_colour_multiselect),
|
||||
selected = ([[{\c&H%s&}]]):format(o.font_colour_selected),
|
||||
playing = ([[{\c&H%s&}]]):format(o.font_colour_playing),
|
||||
playing_selected = ([[{\c&H%s&}]]):format(o.font_colour_playing_multiselected),
|
||||
|
||||
--icon styles
|
||||
indent = ([[{\alpha&H%s}]]):format('ff'),
|
||||
cursor = ([[{\fn%s\c&H%s&}]]):format(o.font_name_cursor, o.font_colour_cursor),
|
||||
cursor_select = ([[{\fn%s\c&H%s&}]]):format(o.font_name_cursor, o.font_colour_multiselect),
|
||||
cursor_deselect = ([[{\fn%s\c&H%s&}]]):format(o.font_name_cursor, o.font_colour_selected),
|
||||
folder = ([[{\fn%s}]]):format(o.font_name_folder),
|
||||
selection_marker = ([[{\alpha&H%s}]]):format(o.font_opacity_selection_marker),
|
||||
}
|
||||
|
||||
globals.state = {
|
||||
list = {},
|
||||
selected = 1,
|
||||
hidden = true,
|
||||
flag_update = false,
|
||||
keybinds = nil,
|
||||
|
||||
parser = nil,
|
||||
directory = nil,
|
||||
directory_label = nil,
|
||||
prev_directory = "",
|
||||
co = nil,
|
||||
|
||||
multiselect_start = nil,
|
||||
initial_selection = nil,
|
||||
selection = {}
|
||||
}
|
||||
|
||||
--the parser table actually contains 3 entries for each parser
|
||||
--a numeric entry which represents the priority of the parsers and has the parser object as the value
|
||||
--a string entry representing the id of each parser and with the parser object as the value
|
||||
--and a table entry with the parser itself as the key and a table value in the form { id = %s, index = %d }
|
||||
globals.parsers = {}
|
||||
|
||||
--this table contains the parse_state tables for every parse operation indexed with the coroutine used for the parse
|
||||
--this table has weakly referenced keys, meaning that once the coroutine for a parse is no-longer used by anything that
|
||||
--field in the table will be removed by the garbage collector
|
||||
globals.parse_states = setmetatable({}, { __mode = "k"})
|
||||
|
||||
globals.extensions = {}
|
||||
globals.sub_extensions = {}
|
||||
globals.audio_extensions = {}
|
||||
globals.parseable_extensions = {}
|
||||
|
||||
--This table contains mappings to convert external directories to cannonical
|
||||
--locations within the file-browser file tree. The keys of the table are Lua
|
||||
--patterns used to evaluate external directory paths. The value is the path
|
||||
--that should replace the part of the path than matched the pattern.
|
||||
--These mappings should only applied at the edges where external paths are
|
||||
--ingested by file-browser.
|
||||
globals.directory_mappings = {}
|
||||
|
||||
globals.current_file = {
|
||||
directory = nil,
|
||||
name = nil,
|
||||
path = nil,
|
||||
original_path = nil,
|
||||
}
|
||||
|
||||
globals.root = {}
|
||||
|
||||
--default list of compatible file extensions
|
||||
--adding an item to this list is a valid request on github
|
||||
globals.compatible_file_extensions = {
|
||||
"264","265","3g2","3ga","3ga2","3gp","3gp2","3gpp","3iv","a52","aac","adt","adts","ahn","aif","aifc","aiff","amr","ape","asf","au","avc","avi","awb","ay",
|
||||
"bmp","cue","divx","dts","dtshd","dts-hd","dv","dvr","dvr-ms","eac3","evo","evob","f4a","flac","flc","fli","flic","flv","gbs","gif","gxf","gym",
|
||||
"h264","h265","hdmov","hdv","hes","hevc","jpeg","jpg","kss","lpcm","m1a","m1v","m2a","m2t","m2ts","m2v","m3u","m3u8","m4a","m4v","mk3d","mka","mkv",
|
||||
"mlp","mod","mov","mp1","mp2","mp2v","mp3","mp4","mp4v","mp4v","mpa","mpe","mpeg","mpeg2","mpeg4","mpg","mpg4","mpv","mpv2","mts","mtv","mxf","nsf",
|
||||
"nsfe","nsv","nut","oga","ogg","ogm","ogv","ogx","opus","pcm","pls","png","qt","ra","ram","rm","rmvb","sap","snd","spc","spx","svg","thd","thd+ac3",
|
||||
"tif","tiff","tod","trp","truehd","true-hd","ts","tsa","tsv","tta","tts","vfw","vgm","vgz","vob","vro","wav","weba","webm","webp","wm","wma","wmv","wtv",
|
||||
"wv","x264","x265","xvid","y4m","yuv"
|
||||
}
|
||||
|
||||
globals.ABORT_ERROR = {
|
||||
msg = "browser is no longer waiting for list - aborting parse"
|
||||
}
|
||||
|
||||
return globals
|
||||
@@ -1,308 +0,0 @@
|
||||
------------------------------------------------------------------------------------------
|
||||
----------------------------------Keybind Implementation----------------------------------
|
||||
------------------------------------------------------------------------------------------
|
||||
------------------------------------------------------------------------------------------
|
||||
|
||||
local mp = require 'mp'
|
||||
local msg = require 'mp.msg'
|
||||
local utils = require 'mp.utils'
|
||||
|
||||
local o = require 'modules.options'
|
||||
local g = require 'modules.globals'
|
||||
local fb_utils = require 'modules.utils'
|
||||
local addons = require 'modules.addons'
|
||||
local playlist = require 'modules.playlist'
|
||||
local controls = require 'modules.controls'
|
||||
local movement = require 'modules.navigation.directory-movement'
|
||||
local scanning = require 'modules.navigation.scanning'
|
||||
local cursor = require 'modules.navigation.cursor'
|
||||
local cache = require 'modules.cache'
|
||||
|
||||
g.state.keybinds = {
|
||||
{'ENTER', 'play', function() playlist.add_files('replace', false) end},
|
||||
{'Shift+ENTER', 'play_append', function() playlist.add_files('append-play', false) end},
|
||||
{'Alt+ENTER', 'play_autoload',function() playlist.add_files('replace', true) end},
|
||||
{'ESC', 'close', controls.escape},
|
||||
{'RIGHT', 'down_dir', movement.down_dir},
|
||||
{'LEFT', 'up_dir', movement.up_dir},
|
||||
{'DOWN', 'scroll_down', function() cursor.scroll(1, o.wrap) end, {repeatable = true}},
|
||||
{'UP', 'scroll_up', function() cursor.scroll(-1, o.wrap) end, {repeatable = true}},
|
||||
{'PGDWN', 'page_down', function() cursor.scroll(o.num_entries) end, {repeatable = true}},
|
||||
{'PGUP', 'page_up', function() cursor.scroll(-o.num_entries) end, {repeatable = true}},
|
||||
{'Shift+PGDWN', 'list_bottom', function() cursor.scroll(math.huge) end},
|
||||
{'Shift+PGUP', 'list_top', function() cursor.scroll(-math.huge) end},
|
||||
{'HOME', 'goto_current', movement.goto_current_dir},
|
||||
{'Shift+HOME', 'goto_root', movement.goto_root},
|
||||
{'Ctrl+r', 'reload', function() cache:clear(); scanning.rescan() end},
|
||||
{'s', 'select_mode', cursor.toggle_select_mode},
|
||||
{'S', 'select_item', cursor.toggle_selection},
|
||||
{'Ctrl+a', 'select_all', cursor.select_all}
|
||||
}
|
||||
|
||||
--a map of key-keybinds - only saves the latest keybind if multiple have the same key code
|
||||
local top_level_keys = {}
|
||||
|
||||
--format the item string for either single or multiple items
|
||||
local function create_item_string(base_code_fn, items, state, cmd, quoted)
|
||||
if not items[1] then return end
|
||||
local func = quoted and function(...) return ("%q"):format(base_code_fn(...)) end or base_code_fn
|
||||
|
||||
local out = {}
|
||||
for _, item in ipairs(items) do
|
||||
table.insert(out, func(item, state))
|
||||
end
|
||||
|
||||
return table.concat(out, cmd['concat-string'] or ' ')
|
||||
end
|
||||
|
||||
local KEYBIND_CODE_PATTERN = fb_utils.get_code_pattern(fb_utils.code_fns)
|
||||
local item_specific_codes = 'fnij'
|
||||
|
||||
--substitutes the key codes for the
|
||||
local function substitute_codes(str, cmd, items, state)
|
||||
local overrides = {}
|
||||
|
||||
for code in item_specific_codes:gmatch('.') do
|
||||
overrides[code] = function(_,s) return create_item_string(fb_utils.code_fns[code], items, s, cmd) end
|
||||
overrides[code:upper()] = function(_,s) return create_item_string(fb_utils.code_fns[code], items, s, cmd, true) end
|
||||
end
|
||||
|
||||
return fb_utils.substitute_codes(str, overrides, items[1], state)
|
||||
end
|
||||
|
||||
--iterates through the command table and substitutes special
|
||||
--character codes for the correct strings used for custom functions
|
||||
local function format_command_table(cmd, items, state)
|
||||
local copy = {}
|
||||
for i = 1, #cmd.command do
|
||||
copy[i] = {}
|
||||
|
||||
for j = 1, #cmd.command[i] do
|
||||
copy[i][j] = substitute_codes(cmd.command[i][j], cmd, items, state)
|
||||
end
|
||||
end
|
||||
return copy
|
||||
end
|
||||
|
||||
--runs all of the commands in the command table
|
||||
--key.command must be an array of command tables compatible with mp.command_native
|
||||
--items must be an array of multiple items (when multi-type ~= concat the array will be 1 long)
|
||||
local function run_custom_command(cmd, items, state)
|
||||
local custom_cmds = cmd.codes and format_command_table(cmd, items, state) or cmd.command
|
||||
|
||||
for _, custom_cmd in ipairs(custom_cmds) do
|
||||
msg.debug("running command:", utils.to_string(custom_cmd))
|
||||
mp.command_native(custom_cmd)
|
||||
end
|
||||
end
|
||||
|
||||
--returns true if the given code set has item specific codes (%f, %i, etc)
|
||||
local function has_item_codes(codes)
|
||||
for code in pairs(codes) do
|
||||
if item_specific_codes:find(code:lower(), 1, true) then return true end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
--runs one of the custom commands
|
||||
local function run_custom_keybind(cmd, state, co)
|
||||
--evaluates a condition and passes through the correct values
|
||||
local function evaluate_condition(condition, items)
|
||||
local cond = substitute_codes(condition, cmd, items, state)
|
||||
return fb_utils.evaluate_string('return '..cond) == true
|
||||
end
|
||||
|
||||
-- evaluates the string condition to decide if the keybind should be run
|
||||
local do_item_condition
|
||||
if cmd.condition then
|
||||
if has_item_codes(cmd.condition_codes) then
|
||||
do_item_condition = true
|
||||
elseif not evaluate_condition(cmd.condition, {}) then
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
if cmd.parser then
|
||||
local parser_str = ' '..cmd.parser..' '
|
||||
if not parser_str:find( '%W'..(state.parser.keybind_name or state.parser.name)..'%W' ) then return false end
|
||||
end
|
||||
|
||||
--these are for the default keybinds, or from addons which use direct functions
|
||||
if type(cmd.command) == 'function' then return cmd.command(cmd, cmd.addon and fb_utils.copy_table(state) or state, co) end
|
||||
|
||||
--the function terminates here if we are running the command on a single item
|
||||
if not (cmd.multiselect and next(state.selection)) then
|
||||
if cmd.filter then
|
||||
if not state.list[state.selected] then return false end
|
||||
if state.list[state.selected].type ~= cmd.filter then return false end
|
||||
end
|
||||
|
||||
if cmd.codes then
|
||||
--if the directory is empty, and this command needs to work on an item, then abort and fallback to the next command
|
||||
if not state.list[state.selected] and has_item_codes(cmd.codes) then return false end
|
||||
end
|
||||
|
||||
if do_item_condition and not evaluate_condition(cmd.condition, { state.list[state.selected] }) then
|
||||
return false
|
||||
end
|
||||
run_custom_command(cmd, { state.list[state.selected] }, state)
|
||||
return true
|
||||
end
|
||||
|
||||
--runs the command on all multi-selected items
|
||||
local selection = fb_utils.sort_keys(state.selection, function(item)
|
||||
if do_item_condition and not evaluate_condition(cmd.condition, { item }) then return false end
|
||||
return not cmd.filter or item.type == cmd.filter
|
||||
end)
|
||||
if not next(selection) then return false end
|
||||
|
||||
if cmd["multi-type"] == "concat" then
|
||||
run_custom_command(cmd, selection, state)
|
||||
|
||||
elseif cmd["multi-type"] == "repeat" or cmd["multi-type"] == nil then
|
||||
for i,_ in ipairs(selection) do
|
||||
run_custom_command(cmd, {selection[i]}, state)
|
||||
|
||||
if cmd.delay then
|
||||
mp.add_timeout(cmd.delay, function() fb_utils.coroutine.resume_err(co) end)
|
||||
coroutine.yield()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--we passthrough by default if the command is not run on every selected item
|
||||
if cmd.passthrough ~= nil then return end
|
||||
|
||||
local num_selection = 0
|
||||
for _ in pairs(state.selection) do num_selection = num_selection+1 end
|
||||
return #selection == num_selection
|
||||
end
|
||||
|
||||
--recursively runs the keybind functions, passing down through the chain
|
||||
--of keybinds with the same key value
|
||||
local function run_keybind_recursive(keybind, state, co)
|
||||
msg.trace("Attempting custom command:", utils.to_string(keybind))
|
||||
|
||||
if keybind.passthrough ~= nil then
|
||||
run_custom_keybind(keybind, state, co)
|
||||
if keybind.passthrough == true and keybind.prev_key then
|
||||
run_keybind_recursive(keybind.prev_key, state, co)
|
||||
end
|
||||
else
|
||||
if run_custom_keybind(keybind, state, co) == false and keybind.prev_key then
|
||||
run_keybind_recursive(keybind.prev_key, state, co)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--a wrapper to run a custom keybind as a lua coroutine
|
||||
local function run_keybind_coroutine(key)
|
||||
msg.debug("Received custom keybind "..key.key)
|
||||
local co = coroutine.create(run_keybind_recursive)
|
||||
|
||||
local state_copy = {
|
||||
directory = g.state.directory,
|
||||
directory_label = g.state.directory_label,
|
||||
list = g.state.list, --the list should remain unchanged once it has been saved to the global state, new directories get new tables
|
||||
selected = g.state.selected,
|
||||
selection = fb_utils.copy_table(g.state.selection),
|
||||
parser = g.state.parser,
|
||||
}
|
||||
local success, err = coroutine.resume(co, key, state_copy, co)
|
||||
if not success then
|
||||
msg.error("error running keybind:", utils.to_string(key))
|
||||
fb_utils.traceback(err, co)
|
||||
end
|
||||
end
|
||||
|
||||
--scans the given command table to identify if they contain any custom keybind codes
|
||||
local function scan_for_codes(command_table, codes)
|
||||
if type(command_table) ~= "table" then return codes end
|
||||
for _, value in pairs(command_table) do
|
||||
local type = type(value)
|
||||
if type == "table" then
|
||||
scan_for_codes(value, codes)
|
||||
elseif type == "string" then
|
||||
for code in value:gmatch(KEYBIND_CODE_PATTERN) do
|
||||
codes[code] = true
|
||||
end
|
||||
end
|
||||
end
|
||||
return codes
|
||||
end
|
||||
|
||||
--inserting the custom keybind into the keybind array for declaration when file-browser is opened
|
||||
--custom keybinds with matching names will overwrite eachother
|
||||
local function insert_custom_keybind(keybind)
|
||||
-- api checking for the keybinds is optional, so set to a valid version if it does not exist
|
||||
keybind.api_version = keybind.api_version or '1.0.0'
|
||||
if not addons.check_api_version(keybind, 'keybind '..keybind.name) then return end
|
||||
|
||||
--we'll always save the keybinds as either an array of command arrays or a function
|
||||
if type(keybind.command) == "table" and type(keybind.command[1]) ~= "table" then
|
||||
keybind.command = {keybind.command}
|
||||
end
|
||||
|
||||
keybind.codes = scan_for_codes(keybind.command, {})
|
||||
if not next(keybind.codes) then keybind.codes = nil end
|
||||
keybind.prev_key = top_level_keys[keybind.key]
|
||||
|
||||
if keybind.condition then
|
||||
keybind.condition_codes = {}
|
||||
for code in string.gmatch(keybind.condition, KEYBIND_CODE_PATTERN) do keybind.condition_codes[code] = true end
|
||||
end
|
||||
|
||||
table.insert(g.state.keybinds, {keybind.key, keybind.name, function() run_keybind_coroutine(keybind) end, keybind.flags or {}})
|
||||
top_level_keys[keybind.key] = keybind
|
||||
end
|
||||
|
||||
--loading the custom keybinds
|
||||
--can either load keybinds from the config file, from addons, or from both
|
||||
local function setup_keybinds()
|
||||
if not o.custom_keybinds and not o.addons then return end
|
||||
|
||||
--this is to make the default keybinds compatible with passthrough from custom keybinds
|
||||
for _, keybind in ipairs(g.state.keybinds) do
|
||||
top_level_keys[keybind[1]] = { key = keybind[1], name = keybind[2], command = keybind[3], flags = keybind[4] }
|
||||
end
|
||||
|
||||
--this loads keybinds from addons
|
||||
if o.addons then
|
||||
for i = #g.parsers, 1, -1 do
|
||||
local parser = g.parsers[i]
|
||||
if parser.keybinds then
|
||||
for i, keybind in ipairs(parser.keybinds) do
|
||||
--if addons use the native array command format, then we need to convert them over to the custom command format
|
||||
if not keybind.key then keybind = { key = keybind[1], name = keybind[2], command = keybind[3], flags = keybind[4] }
|
||||
else keybind = fb_utils.copy_table(keybind) end
|
||||
|
||||
keybind.name = g.parsers[parser].id.."/"..(keybind.name or tostring(i))
|
||||
keybind.addon = true
|
||||
insert_custom_keybind(keybind)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--loads custom keybinds from file-browser-keybinds.json
|
||||
if o.custom_keybinds then
|
||||
local path = mp.command_native({"expand-path", "~~/script-opts"}).."/file-browser-keybinds.json"
|
||||
local custom_keybinds, err = io.open( path )
|
||||
if not custom_keybinds then return error(err) end
|
||||
|
||||
local json = custom_keybinds:read("*a")
|
||||
custom_keybinds:close()
|
||||
|
||||
json = utils.parse_json(json)
|
||||
if not json then return error("invalid json syntax for "..path) end
|
||||
|
||||
for i, keybind in ipairs(json) do
|
||||
keybind.name = "custom/"..(keybind.name or tostring(i))
|
||||
insert_custom_keybind(keybind)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return {
|
||||
setup_keybinds = setup_keybinds,
|
||||
}
|
||||
@@ -1,121 +0,0 @@
|
||||
--------------------------------------------------------------------------------------------------------
|
||||
--------------------------------Scroll/Select Implementation--------------------------------------------
|
||||
--------------------------------------------------------------------------------------------------------
|
||||
--------------------------------------------------------------------------------------------------------
|
||||
|
||||
local g = require 'modules.globals'
|
||||
local fb_utils = require 'modules.utils'
|
||||
local ass = require 'modules.ass'
|
||||
|
||||
local cursor = {}
|
||||
|
||||
--disables multiselect
|
||||
function cursor.disable_select_mode()
|
||||
g.state.multiselect_start = nil
|
||||
g.state.initial_selection = nil
|
||||
end
|
||||
|
||||
--enables multiselect
|
||||
function cursor.enable_select_mode()
|
||||
g.state.multiselect_start = g.state.selected
|
||||
g.state.initial_selection = fb_utils.copy_table(g.state.selection)
|
||||
end
|
||||
|
||||
--calculates what drag behaviour is required for that specific movement
|
||||
local function drag_select(original_pos, new_pos)
|
||||
if original_pos == new_pos then return end
|
||||
|
||||
local setting = g.state.selection[g.state.multiselect_start]
|
||||
for i = original_pos, new_pos, (new_pos > original_pos and 1 or -1) do
|
||||
--if we're moving the cursor away from the starting point then set the selection
|
||||
--otherwise restore the original selection
|
||||
if i > g.state.multiselect_start then
|
||||
if new_pos > original_pos then
|
||||
g.state.selection[i] = setting
|
||||
elseif i ~= new_pos then
|
||||
g.state.selection[i] = g.state.initial_selection[i]
|
||||
end
|
||||
elseif i < g.state.multiselect_start then
|
||||
if new_pos < original_pos then
|
||||
g.state.selection[i] = setting
|
||||
elseif i ~= new_pos then
|
||||
g.state.selection[i] = g.state.initial_selection[i]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--moves the selector up and down the list by the entered amount
|
||||
function cursor.scroll(n, wrap)
|
||||
local num_items = #g.state.list
|
||||
if num_items == 0 then return end
|
||||
|
||||
local original_pos = g.state.selected
|
||||
|
||||
if original_pos + n > num_items then
|
||||
g.state.selected = wrap and 1 or num_items
|
||||
elseif original_pos + n < 1 then
|
||||
g.state.selected = wrap and num_items or 1
|
||||
else
|
||||
g.state.selected = original_pos + n
|
||||
end
|
||||
|
||||
if g.state.multiselect_start then drag_select(original_pos, g.state.selected) end
|
||||
ass.update_ass()
|
||||
end
|
||||
|
||||
--selects the first item in the list which is highlighted as playing
|
||||
function cursor.select_playing_item()
|
||||
for i,item in ipairs(g.state.list) do
|
||||
if ass.highlight_entry(item) then
|
||||
g.state.selected = i
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--scans the list for which item to select by default
|
||||
--chooses the folder that the script just moved out of
|
||||
--or, otherwise, the item highlighted as currently playing
|
||||
function cursor.select_prev_directory()
|
||||
if g.state.prev_directory:find(g.state.directory, 1, true) == 1 then
|
||||
local i = 1
|
||||
while (g.state.list[i] and fb_utils.parseable_item(g.state.list[i])) do
|
||||
if g.state.prev_directory:find(fb_utils.get_full_path(g.state.list[i]), 1, true) then
|
||||
g.state.selected = i
|
||||
return
|
||||
end
|
||||
i = i+1
|
||||
end
|
||||
end
|
||||
|
||||
cursor.select_playing_item()
|
||||
end
|
||||
|
||||
--toggles the selection
|
||||
function cursor.toggle_selection()
|
||||
if not g.state.list[g.state.selected] then return end
|
||||
g.state.selection[g.state.selected] = not g.state.selection[g.state.selected] or nil
|
||||
ass.update_ass()
|
||||
end
|
||||
|
||||
--select all items in the list
|
||||
function cursor.select_all()
|
||||
for i,_ in ipairs(g.state.list) do
|
||||
g.state.selection[i] = true
|
||||
end
|
||||
ass.update_ass()
|
||||
end
|
||||
|
||||
--toggles select mode
|
||||
function cursor.toggle_select_mode()
|
||||
if g.state.multiselect_start == nil then
|
||||
cursor.enable_select_mode()
|
||||
cursor.toggle_selection()
|
||||
else
|
||||
cursor.disable_select_mode()
|
||||
ass.update_ass()
|
||||
end
|
||||
end
|
||||
|
||||
return cursor
|
||||
@@ -1,86 +0,0 @@
|
||||
|
||||
local mp = require 'mp'
|
||||
local msg = require 'mp.msg'
|
||||
local utils = require 'mp.utils'
|
||||
|
||||
local o = require 'modules.options'
|
||||
local g = require 'modules.globals'
|
||||
local ass = require 'modules.ass'
|
||||
local cache = require 'modules.cache'
|
||||
local scanning = require 'modules.navigation.scanning'
|
||||
local fb_utils = require 'modules.utils'
|
||||
|
||||
local directory_movement = {}
|
||||
|
||||
function directory_movement.set_current_file(filepath)
|
||||
--if we're in idle mode then we want to open the working directory
|
||||
if filepath == nil then
|
||||
g.current_file.directory = fb_utils.fix_path( mp.get_property("working-directory", ""), true)
|
||||
g.current_file.name = nil
|
||||
g.current_file.path = nil
|
||||
return
|
||||
end
|
||||
|
||||
local absolute_path = fb_utils.absolute_path(filepath)
|
||||
local resolved_path = fb_utils.resolve_directory_mapping(absolute_path)
|
||||
|
||||
g.current_file.directory, g.current_file.name = utils.split_path(resolved_path)
|
||||
g.current_file.original_path = absolute_path
|
||||
g.current_file.path = resolved_path
|
||||
|
||||
if not g.state.hidden then ass.update_ass()
|
||||
else g.state.flag_update = true end
|
||||
end
|
||||
|
||||
--the base function for moving to a directory
|
||||
function directory_movement.goto_directory(directory, moving_adjacent)
|
||||
-- update cache to the lastest state values before changing the current directory
|
||||
cache:add_current_state()
|
||||
|
||||
local current = g.state.list[g.state.selected]
|
||||
g.state.directory = directory
|
||||
|
||||
if g.state.directory_label then
|
||||
if moving_adjacent == 1 then
|
||||
g.state.directory_label = g.state.directory_label..(current.label or current.name)
|
||||
elseif moving_adjacent == -1 then
|
||||
g.state.directory_label = string.match(g.state.directory_label, "^(.-/+)[^/]+/*$")
|
||||
end
|
||||
end
|
||||
|
||||
return scanning.rescan(moving_adjacent or false)
|
||||
end
|
||||
|
||||
--loads the root list
|
||||
function directory_movement.goto_root()
|
||||
msg.verbose('jumping to root')
|
||||
return directory_movement.goto_directory("")
|
||||
end
|
||||
|
||||
--switches to the directory of the currently playing file
|
||||
function directory_movement.goto_current_dir()
|
||||
msg.verbose('jumping to current directory')
|
||||
return directory_movement.goto_directory(g.current_file.directory)
|
||||
end
|
||||
|
||||
--moves up a directory
|
||||
function directory_movement.up_dir()
|
||||
local parent_dir = g.state.directory:match("^(.-/+)[^/]+/*$") or ""
|
||||
|
||||
if o.skip_protocol_schemes and parent_dir:find("^(%a[%w+-.]*)://$") then
|
||||
return directory_movement.goto_root()
|
||||
end
|
||||
|
||||
return directory_movement.goto_directory(parent_dir, -1)
|
||||
end
|
||||
|
||||
--moves down a directory
|
||||
function directory_movement.down_dir()
|
||||
local current = g.state.list[g.state.selected]
|
||||
if not current or not fb_utils.parseable_item(current) then return end
|
||||
|
||||
local directory, redirected = fb_utils.get_new_directory(current, g.state.directory)
|
||||
return directory_movement.goto_directory(directory, not redirected and 1)
|
||||
end
|
||||
|
||||
return directory_movement
|
||||
@@ -1,182 +0,0 @@
|
||||
local mp = require 'mp'
|
||||
local msg = require 'mp.msg'
|
||||
local utils = require 'mp.utils'
|
||||
|
||||
local g = require 'modules.globals'
|
||||
local fb_utils = require 'modules.utils'
|
||||
local cache = require 'modules.cache'
|
||||
local cursor = require 'modules.navigation.cursor'
|
||||
local ass = require 'modules.ass'
|
||||
|
||||
local parse_state_API = require 'modules.apis.parse-state'
|
||||
|
||||
local function clear_non_adjacent_state()
|
||||
g.state.directory_label = nil
|
||||
cache:clear_traversal_stack()
|
||||
end
|
||||
|
||||
--parses the given directory or defers to the next parser if nil is returned
|
||||
local function choose_and_parse(directory, index)
|
||||
msg.debug(("finding parser for %q"):format(directory))
|
||||
local parser, list, opts
|
||||
local parse_state = g.parse_states[coroutine.running() or ""]
|
||||
while list == nil and not parse_state.already_deferred and index <= #g.parsers do
|
||||
parser = g.parsers[index]
|
||||
if parser:can_parse(directory, parse_state) then
|
||||
msg.debug("attempting parser:", parser:get_id())
|
||||
list, opts = parser:parse(directory, parse_state)
|
||||
end
|
||||
index = index + 1
|
||||
end
|
||||
if not list then return nil, {} end
|
||||
|
||||
msg.debug("list returned from:", parser:get_id())
|
||||
opts = opts or {}
|
||||
if list then opts.id = opts.id or parser:get_id() end
|
||||
return list, opts
|
||||
end
|
||||
|
||||
--sets up the parse_state table and runs the parse operation
|
||||
local function run_parse(directory, parse_state)
|
||||
msg.verbose(("scanning files in %q"):format(directory))
|
||||
parse_state.directory = directory
|
||||
|
||||
local co = coroutine.running()
|
||||
g.parse_states[co] = setmetatable(parse_state, { __index = parse_state_API })
|
||||
|
||||
local list, opts = choose_and_parse(directory, 1)
|
||||
|
||||
if list == nil then return msg.debug("no successful parsers found") end
|
||||
opts.parser = g.parsers[opts.id]
|
||||
|
||||
if not opts.filtered then fb_utils.filter(list) end
|
||||
if not opts.sorted then fb_utils.sort(list) end
|
||||
return list, opts
|
||||
end
|
||||
|
||||
--returns the contents of the given directory using the given parse state
|
||||
--if a coroutine has already been used for a parse then create a new coroutine so that
|
||||
--the every parse operation has a unique thread ID
|
||||
local function parse_directory(directory, parse_state)
|
||||
local co = fb_utils.coroutine.assert("scan_directory must be executed from within a coroutine - aborting scan "..utils.to_string(parse_state))
|
||||
if not g.parse_states[co] then return run_parse(directory, parse_state) end
|
||||
|
||||
--if this coroutine is already is use by another parse operation then we create a new
|
||||
--one and hand execution over to that
|
||||
local new_co = coroutine.create(function()
|
||||
fb_utils.coroutine.resume_err(co, run_parse(directory, parse_state))
|
||||
end)
|
||||
|
||||
--queue the new coroutine on the mpv event queue
|
||||
mp.add_timeout(0, function()
|
||||
local success, err = coroutine.resume(new_co)
|
||||
if not success then
|
||||
fb_utils.traceback(err, new_co)
|
||||
fb_utils.coroutine.resume_err(co)
|
||||
end
|
||||
end)
|
||||
return g.parse_states[co]:yield()
|
||||
end
|
||||
|
||||
--sends update requests to the different parsers
|
||||
local function update_list(moving_adjacent)
|
||||
msg.verbose('opening directory: ' .. g.state.directory)
|
||||
|
||||
g.state.selected = 1
|
||||
g.state.selection = {}
|
||||
|
||||
--loads the current directry from the cache to save loading time
|
||||
if cache:in_cache(g.state.directory) then
|
||||
msg.verbose('found directory in cache')
|
||||
cache:apply(g.state.directory)
|
||||
g.state.prev_directory = g.state.directory
|
||||
return
|
||||
end
|
||||
local directory = g.state.directory
|
||||
local list, opts = parse_directory(g.state.directory, { source = "browser" })
|
||||
|
||||
--if the running coroutine isn't the one stored in the state variable, then the user
|
||||
--changed directories while the coroutine was paused, and this operation should be aborted
|
||||
if coroutine.running() ~= g.state.co then
|
||||
msg.verbose(g.ABORT_ERROR.msg)
|
||||
msg.debug("expected:", g.state.directory, "received:", directory)
|
||||
return
|
||||
end
|
||||
|
||||
--apply fallbacks if the scan failed
|
||||
if not list and cache:in_cache(g.state.prev_directory) then
|
||||
--switches settings back to the previously opened directory
|
||||
--to the user it will be like the directory never changed
|
||||
msg.warn("could not read directory", g.state.directory)
|
||||
cache:apply(g.state.prev_directory)
|
||||
return
|
||||
elseif not list then
|
||||
--opens the root instead
|
||||
msg.warn("could not read directory", g.state.directory, "redirecting to root")
|
||||
list, opts = parse_directory("", { source = "browser" })
|
||||
|
||||
-- sets the directory redirect flag
|
||||
opts.directory = ''
|
||||
end
|
||||
|
||||
g.state.list = list
|
||||
g.state.parser = opts.parser
|
||||
|
||||
--setting custom options from parsers
|
||||
g.state.directory_label = opts.directory_label
|
||||
g.state.empty_text = opts.empty_text or g.state.empty_text
|
||||
|
||||
--we assume that directory is only changed when redirecting to a different location
|
||||
--therefore we need to change the `moving_adjacent` flag and clear some state values
|
||||
if opts.directory then
|
||||
g.state.directory = opts.directory
|
||||
moving_adjacent = false
|
||||
clear_non_adjacent_state()
|
||||
end
|
||||
|
||||
if opts.selected_index then
|
||||
g.state.selected = opts.selected_index or g.state.selected
|
||||
if g.state.selected > #g.state.list then g.state.selected = #g.state.list
|
||||
elseif g.state.selected < 1 then g.state.selected = 1 end
|
||||
end
|
||||
|
||||
if moving_adjacent then cursor.select_prev_directory()
|
||||
else cursor.select_playing_item() end
|
||||
g.state.prev_directory = g.state.directory
|
||||
end
|
||||
|
||||
--rescans the folder and updates the list
|
||||
--returns the coroutine for the new parse operation
|
||||
local function rescan(moving_adjacent)
|
||||
if moving_adjacent == nil then moving_adjacent = 0 end
|
||||
|
||||
--we can only make assumptions about the directory label when moving from adjacent directories
|
||||
if not moving_adjacent then clear_non_adjacent_state() end
|
||||
|
||||
g.state.empty_text = "~"
|
||||
g.state.list = {}
|
||||
cursor.disable_select_mode()
|
||||
ass.update_ass()
|
||||
|
||||
--the directory is always handled within a coroutine to allow addons to
|
||||
--pause execution for asynchronous operations
|
||||
g.state.co = fb_utils.coroutine.queue(function()
|
||||
update_list(moving_adjacent)
|
||||
if g.state.empty_text == "~" then g.state.empty_text = "empty directory" end
|
||||
|
||||
cache:append_history()
|
||||
if type(moving_adjacent) == 'number' and moving_adjacent < 0 then cache:pop()
|
||||
else cache:push() end
|
||||
if not cache.traversal_stack[1] then cache:push() end
|
||||
|
||||
ass.update_ass()
|
||||
end)
|
||||
|
||||
return g.state.co
|
||||
end
|
||||
|
||||
return {
|
||||
rescan = rescan,
|
||||
scan_directory = parse_directory,
|
||||
choose_and_parse = choose_and_parse,
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
|
||||
local directory_movement = require 'modules.navigation.directory-movement'
|
||||
local fb = require 'modules.apis.fb'
|
||||
local fb_utils = require 'modules.utils'
|
||||
|
||||
local observers ={}
|
||||
|
||||
--saves the directory and name of the currently playing file
|
||||
function observers.current_directory(_, filepath)
|
||||
directory_movement.set_current_file(filepath)
|
||||
end
|
||||
|
||||
function observers.dvd_device(_, device)
|
||||
if not device or device == "" then device = '/dev/dvd' end
|
||||
fb.register_directory_mapping(fb_utils.absolute_path(device), '^dvd://.*', true)
|
||||
end
|
||||
|
||||
function observers.bd_device(_, device)
|
||||
if not device or device == '' then device = '/dev/bd' end
|
||||
fb.register_directory_mapping(fb_utils.absolute_path(device), '^bd://.*', true)
|
||||
end
|
||||
|
||||
function observers.cd_device(_, device)
|
||||
if not device or device == '' then device = '/dev/cdrom' end
|
||||
fb.register_directory_mapping(fb_utils.absolute_path(device), '^cdda://.*', true)
|
||||
end
|
||||
|
||||
return observers
|
||||
@@ -1,147 +0,0 @@
|
||||
local utils = require 'mp.utils'
|
||||
local opt = require 'mp.options'
|
||||
|
||||
local o = {
|
||||
--root directories
|
||||
root = "~/",
|
||||
|
||||
--characters to use as separators
|
||||
root_separators = ",;",
|
||||
|
||||
--number of entries to show on the screen at once
|
||||
num_entries = 20,
|
||||
|
||||
--wrap the cursor around the top and bottom of the list
|
||||
wrap = false,
|
||||
|
||||
--only show files compatible with mpv
|
||||
filter_files = true,
|
||||
|
||||
--experimental feature that recurses directories concurrently when
|
||||
--appending items to the playlist
|
||||
concurrent_recursion = false,
|
||||
|
||||
--maximum number of recursions that can run concurrently
|
||||
max_concurrency = 16,
|
||||
|
||||
--enable custom keybinds
|
||||
custom_keybinds = false,
|
||||
|
||||
--blacklist compatible files, it's recommended to use this rather than to edit the
|
||||
--compatible list directly. A semicolon separated list of extensions without spaces
|
||||
extension_blacklist = "",
|
||||
|
||||
--add extra file extensions
|
||||
extension_whitelist = "",
|
||||
|
||||
--files with these extensions will be added as additional audio tracks for the current file instead of appended to the playlist
|
||||
audio_extensions = "mka,dts,dtshd,dts-hd,truehd,true-hd",
|
||||
|
||||
--files with these extensions will be added as additional subtitle tracks instead of appended to the playlist
|
||||
subtitle_extensions = "etf,etf8,utf-8,idx,sub,srt,rt,ssa,ass,mks,vtt,sup,scc,smi,lrc,pgs",
|
||||
|
||||
--filter dot directories like .config
|
||||
--most useful on linux systems
|
||||
filter_dot_dirs = false,
|
||||
filter_dot_files = false,
|
||||
|
||||
--substitude forward slashes for backslashes when appending a local file to the playlist
|
||||
--potentially useful on windows systems
|
||||
substitute_backslash = false,
|
||||
|
||||
--interpret backslashes `\` in paths as forward slashes `/`
|
||||
--this is useful on Windows, which natively uses backslashes.
|
||||
--As backslashes are valid filename characters in Unix systems this could
|
||||
--cause mangled paths, though such filenames are rare.
|
||||
--Use `yes` and `no` to enable/disable. `auto` tries to use the mpv `platform`
|
||||
--property (mpv v0.36+) to decide. If the property is unavailable it defaults to `yes`.
|
||||
normalise_backslash = 'auto',
|
||||
|
||||
--this option reverses the behaviour of the alt+ENTER keybind
|
||||
--when disabled the keybind is required to enable autoload for the file
|
||||
--when enabled the keybind disables autoload for the file
|
||||
autoload = false,
|
||||
|
||||
--if autoload is triggered by selecting the currently playing file, then
|
||||
--the current file will have it's watch-later config saved before being closed
|
||||
--essentially the current file will not be restarted
|
||||
autoload_save_current = true,
|
||||
|
||||
--when opening the browser in idle mode prefer the current working directory over the root
|
||||
--note that the working directory is set as the 'current' directory regardless, so `home` will
|
||||
--move the browser there even if this option is set to false
|
||||
default_to_working_directory = false,
|
||||
|
||||
--when moving up a directory do not stop on empty protocol schemes like `ftp://`
|
||||
--e.g. moving up from `ftp://localhost/` will move straight to the root instead of `ftp://`
|
||||
skip_protocol_schemes = true,
|
||||
|
||||
--map optical device paths to their respective file paths,
|
||||
--e.g. mapping bd:// to the value of the bluray-device property
|
||||
map_bd_device = true,
|
||||
map_dvd_device = true,
|
||||
map_cdda_device = true,
|
||||
|
||||
--allows custom icons be set for the folder and cursor
|
||||
--the `\h` character is a hard space to add padding between the symbol and the text
|
||||
folder_icon = [[{\p1}m 6.52 0 l 1.63 0 b 0.73 0 0.01 0.73 0.01 1.63 l 0 11.41 b 0 12.32 0.73 13.05 1.63 13.05 l 14.68 13.05 b 15.58 13.05 16.31 12.32 16.31 11.41 l 16.31 3.26 b 16.31 2.36 15.58 1.63 14.68 1.63 l 8.15 1.63{\p0}\h]],
|
||||
cursor_icon = [[{\p1}m 14.11 6.86 l 0.34 0.02 b 0.25 -0.02 0.13 -0 0.06 0.08 b -0.01 0.16 -0.02 0.28 0.04 0.36 l 3.38 5.55 l 3.38 5.55 3.67 6.15 3.81 6.79 3.79 7.45 3.61 8.08 3.39 8.5l 0.04 13.77 b -0.02 13.86 -0.01 13.98 0.06 14.06 b 0.11 14.11 0.17 14.13 0.24 14.13 b 0.27 14.13 0.31 14.13 0.34 14.11 l 14.11 7.28 b 14.2 7.24 14.25 7.16 14.25 7.07 b 14.25 6.98 14.2 6.9 14.11 6.86{\p0}\h]],
|
||||
|
||||
--enable addons
|
||||
addons = false,
|
||||
addon_directory = "~~/script-modules/file-browser-addons",
|
||||
|
||||
--directory to load external modules - currently just user-input-module
|
||||
module_directory = "~~/script-modules",
|
||||
|
||||
--turn the OSC idle screen off and on when opening and closing the browser
|
||||
toggle_idlescreen = false,
|
||||
|
||||
--Set the current open status of the browser in the `file_browser/open` field of the `user-data` property.
|
||||
--This property is only available in mpv v0.36+.
|
||||
set_user_data = true,
|
||||
|
||||
--Set the current open status of the browser in the `file_browser-open` field of the `shared-script-properties` property.
|
||||
--This property is deprecated. When it is removed in mpv v0.37 file-browser will automatically ignore this option.
|
||||
set_shared_script_properties = false,
|
||||
|
||||
--force file-browser to use a specific text alignment (default: top-left)
|
||||
--uses ass tag alignment numbers: https://aegi.vmoe.info/docs/3.0/ASS_Tags/#index23h3
|
||||
--set to 0 to use the default mpv osd-align options
|
||||
alignment = 7,
|
||||
|
||||
--style settings
|
||||
format_string_header = '%q\\N----------------------------------------------------',
|
||||
format_string_topwrapper = '%< item(s) above\\N',
|
||||
format_string_bottomwrapper = '\\N%> item(s) remaining',
|
||||
|
||||
font_bold_header = true,
|
||||
font_opacity_selection_marker = "99",
|
||||
|
||||
scaling_factor_base = 1,
|
||||
scaling_factor_header = 1.4,
|
||||
scaling_factor_wrappers = 0.64,
|
||||
|
||||
font_name_header = "",
|
||||
font_name_body = "",
|
||||
font_name_wrappers = "",
|
||||
font_name_folder = "",
|
||||
font_name_cursor = "",
|
||||
|
||||
font_colour_header = "00ccff",
|
||||
font_colour_body = "ffffff",
|
||||
font_colour_wrappers = "00ccff",
|
||||
font_colour_cursor = "00ccff",
|
||||
|
||||
font_colour_multiselect = "fcad88",
|
||||
font_colour_selected = "fce788",
|
||||
font_colour_playing = "33ff66",
|
||||
font_colour_playing_multiselected = "22b547"
|
||||
|
||||
}
|
||||
|
||||
opt.read_options(o, 'file_browser')
|
||||
|
||||
o.set_shared_script_properties = o.set_shared_script_properties and utils.shared_script_property_set
|
||||
|
||||
return o
|
||||
@@ -1,44 +0,0 @@
|
||||
-- This file is an internal file-browser addon.
|
||||
-- It should not be imported like a normal module.
|
||||
|
||||
local msg = require 'mp.msg'
|
||||
local utils = require 'mp.utils'
|
||||
|
||||
--parser object for native filesystems
|
||||
local file_parser = {
|
||||
name = "file",
|
||||
priority = 110,
|
||||
api_version = '1.0.0',
|
||||
}
|
||||
|
||||
--try to parse any directory except for the root
|
||||
function file_parser:can_parse(directory)
|
||||
return directory ~= ''
|
||||
end
|
||||
|
||||
--scans the given directory using the mp.utils.readdir function
|
||||
function file_parser:parse(directory)
|
||||
local new_list = {}
|
||||
local list1 = utils.readdir(directory, 'dirs')
|
||||
if list1 == nil then return nil end
|
||||
|
||||
--sorts folders and formats them into the list of directories
|
||||
for i=1, #list1 do
|
||||
local item = list1[i]
|
||||
|
||||
msg.trace(item..'/')
|
||||
table.insert(new_list, {name = item..'/', type = 'dir'})
|
||||
end
|
||||
|
||||
--appends files to the list of directory items
|
||||
local list2 = utils.readdir(directory, 'files')
|
||||
for i=1, #list2 do
|
||||
local item = list2[i]
|
||||
|
||||
msg.trace(item)
|
||||
table.insert(new_list, {name = item, type = 'file'})
|
||||
end
|
||||
return new_list
|
||||
end
|
||||
|
||||
return file_parser
|
||||
@@ -1,25 +0,0 @@
|
||||
|
||||
local g = require 'modules.globals'
|
||||
|
||||
--parser object for the root
|
||||
--not inserted to the parser list as it has special behaviour
|
||||
--it does get added to parsers under its ID to prevent confusing duplicates
|
||||
local root_parser = {
|
||||
name = "root",
|
||||
priority = math.huge,
|
||||
api_version = '1.0.0',
|
||||
}
|
||||
|
||||
function root_parser:can_parse(directory)
|
||||
return directory == ''
|
||||
end
|
||||
|
||||
--we return the root directory exactly as setup
|
||||
function root_parser:parse()
|
||||
return g.root, {
|
||||
sorted = true,
|
||||
filtered = true,
|
||||
}
|
||||
end
|
||||
|
||||
return root_parser
|
||||
@@ -1,292 +0,0 @@
|
||||
------------------------------------------------------------------------------------------
|
||||
---------------------------------File/Playlist Opening------------------------------------
|
||||
------------------------------------------------------------------------------------------
|
||||
------------------------------------------------------------------------------------------
|
||||
|
||||
local mp = require 'mp'
|
||||
local msg = require 'mp.msg'
|
||||
local utils = require 'mp.utils'
|
||||
|
||||
local o = require 'modules.options'
|
||||
local g = require 'modules.globals'
|
||||
local fb_utils = require 'modules.utils'
|
||||
local ass = require 'modules.ass'
|
||||
local cursor = require 'modules.navigation.cursor'
|
||||
local controls = require 'modules.controls'
|
||||
local scanning = require 'modules.navigation.scanning'
|
||||
local movement = require 'modules.navigation.directory-movement'
|
||||
|
||||
local state = g.state
|
||||
|
||||
-- In mpv v0.38 a new index argument was added to the loadfile command.
|
||||
-- For some crazy reason this new argument is placed before the existing options
|
||||
-- argument, breaking any scripts that used it. This function finds the correct index
|
||||
-- for the options argument using the `command-list` property.
|
||||
local function get_loadfile_options_arg_index()
|
||||
local command_list = mp.get_property_native('command-list', {})
|
||||
for _, command in ipairs(command_list) do
|
||||
if command.name == 'loadfile' then
|
||||
for i, arg in ipairs(command.args or {}) do
|
||||
if arg.name == 'options' then
|
||||
return i
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return 3
|
||||
end
|
||||
|
||||
local LEGACY_LOADFILE_SYNTAX = get_loadfile_options_arg_index() == 3
|
||||
|
||||
-- A wrapper around loadfile to handle the syntax changes introduced in mpv v0.38.
|
||||
local function legacy_loadfile_wrapper(file, flag, options)
|
||||
if LEGACY_LOADFILE_SYNTAX then
|
||||
return mp.command_native({"loadfile", file, flag, options})
|
||||
else
|
||||
return mp.command_native({"loadfile", file, flag, -1, options})
|
||||
end
|
||||
end
|
||||
|
||||
--adds a file to the playlist and changes the flag to `append-play` in preparation
|
||||
--for future items
|
||||
local function loadfile(file, opts, mpv_opts)
|
||||
if o.substitute_backslash and not fb_utils.get_protocol(file) then
|
||||
file = file:gsub("/", "\\")
|
||||
end
|
||||
|
||||
if opts.flag == "replace" then msg.verbose("Playling file", file)
|
||||
else msg.verbose("Appending", file, "to the playlist") end
|
||||
|
||||
if mpv_opts then
|
||||
msg.debug('Settings opts on', file, ':', utils.to_string(mpv_opts))
|
||||
end
|
||||
|
||||
if not legacy_loadfile_wrapper(file, opts.flag, mpv_opts) then msg.warn(file) end
|
||||
opts.flag = "append-play"
|
||||
opts.items_appended = opts.items_appended + 1
|
||||
end
|
||||
|
||||
--this function recursively loads directories concurrently in separate coroutines
|
||||
--results are saved in a tree of tables that allows asynchronous access
|
||||
local function concurrent_loadlist_parse(directory, load_opts, prev_dirs, item_t)
|
||||
--prevents infinite recursion from the item.path or opts.directory fields
|
||||
if prev_dirs[directory] then return end
|
||||
prev_dirs[directory] = true
|
||||
|
||||
local list, list_opts = scanning.scan_directory(directory, { source = "loadlist" })
|
||||
if list == g.root then return end
|
||||
|
||||
--if we can't parse the directory then append it and hope mpv fares better
|
||||
if list == nil then
|
||||
msg.warn("Could not parse", directory, "appending to playlist anyway")
|
||||
item_t.type = "file"
|
||||
return
|
||||
end
|
||||
|
||||
directory = list_opts.directory or directory
|
||||
if directory == "" then return end
|
||||
|
||||
--we must declare these before we start loading sublists otherwise the append thread will
|
||||
--need to wait until the whole list is loaded (when synchronous IO is used)
|
||||
item_t._sublist = list or {}
|
||||
list._directory = directory
|
||||
|
||||
--launches new parse operations for directories, each in a different coroutine
|
||||
for _, item in ipairs(list) do
|
||||
if fb_utils.parseable_item(item) then
|
||||
fb_utils.coroutine.run(concurrent_loadlist_wrapper, fb_utils.get_new_directory(item, directory), load_opts, prev_dirs, item)
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
--a wrapper function that ensures the concurrent_loadlist_parse is run correctly
|
||||
function concurrent_loadlist_wrapper(directory, opts, prev_dirs, item)
|
||||
--ensures that only a set number of concurrent parses are operating at any one time.
|
||||
--the mpv event queue is seemingly limited to 1000 items, but only async mpv actions like
|
||||
--command_native_async should use that, events like mp.add_timeout (which coroutine.sleep() uses) should
|
||||
--be handled enturely on the Lua side with a table, which has a significantly larger maximum size.
|
||||
while (opts.concurrency > o.max_concurrency) do
|
||||
fb_utils.coroutine.sleep(0.1)
|
||||
end
|
||||
opts.concurrency = opts.concurrency + 1
|
||||
|
||||
local success = concurrent_loadlist_parse(directory, opts, prev_dirs, item)
|
||||
opts.concurrency = opts.concurrency - 1
|
||||
if not success then item._sublist = {} end
|
||||
if coroutine.status(opts.co) == "suspended" then fb_utils.coroutine.resume_err(opts.co) end
|
||||
end
|
||||
|
||||
--recursively appends items to the playlist, acts as a consumer to the previous functions producer;
|
||||
--if the next directory has not been parsed this function will yield until the parse has completed
|
||||
local function concurrent_loadlist_append(list, load_opts)
|
||||
local directory = list._directory
|
||||
|
||||
for _, item in ipairs(list) do
|
||||
if not g.sub_extensions[ fb_utils.get_extension(item.name, "") ]
|
||||
and not g.audio_extensions[ fb_utils.get_extension(item.name, "") ]
|
||||
then
|
||||
while (not item._sublist and fb_utils.parseable_item(item)) do
|
||||
coroutine.yield()
|
||||
end
|
||||
|
||||
if fb_utils.parseable_item(item) then
|
||||
concurrent_loadlist_append(item._sublist, load_opts)
|
||||
else
|
||||
loadfile(fb_utils.get_full_path(item, directory), load_opts, item.mpv_options)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--recursive function to load directories using the script custom parsers
|
||||
--returns true if any items were appended to the playlist
|
||||
local function custom_loadlist_recursive(directory, load_opts, prev_dirs)
|
||||
--prevents infinite recursion from the item.path or opts.directory fields
|
||||
if prev_dirs[directory] then return end
|
||||
prev_dirs[directory] = true
|
||||
|
||||
local list, opts = scanning.scan_directory(directory, { source = "loadlist" })
|
||||
if list == g.root then return end
|
||||
|
||||
--if we can't parse the directory then append it and hope mpv fares better
|
||||
if list == nil then
|
||||
msg.warn("Could not parse", directory, "appending to playlist anyway")
|
||||
loadfile(directory, load_opts.flag)
|
||||
return true
|
||||
end
|
||||
|
||||
directory = opts.directory or directory
|
||||
if directory == "" then return end
|
||||
|
||||
for _, item in ipairs(list) do
|
||||
if not g.sub_extensions[ fb_utils.get_extension(item.name, "") ]
|
||||
and not g.audio_extensions[ fb_utils.get_extension(item.name, "") ]
|
||||
then
|
||||
if fb_utils.parseable_item(item) then
|
||||
custom_loadlist_recursive( fb_utils.get_new_directory(item, directory) , load_opts, prev_dirs)
|
||||
else
|
||||
local path = fb_utils.get_full_path(item, directory)
|
||||
loadfile(path, load_opts, item.mpv_options)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--a wrapper for the custom_loadlist_recursive function
|
||||
local function loadlist(item, opts)
|
||||
local dir = fb_utils.get_full_path(item, opts.directory)
|
||||
local num_items = opts.items_appended
|
||||
|
||||
if o.concurrent_recursion then
|
||||
item = fb_utils.copy_table(item)
|
||||
opts.co = fb_utils.coroutine.assert()
|
||||
opts.concurrency = 0
|
||||
|
||||
--we need the current coroutine to suspend before we run the first parse operation, so
|
||||
--we schedule the coroutine to run on the mpv event queue
|
||||
mp.add_timeout(0, function()
|
||||
fb_utils.coroutine.run(concurrent_loadlist_wrapper, dir, opts, {}, item)
|
||||
end)
|
||||
concurrent_loadlist_append({item, _directory = opts.directory}, opts)
|
||||
else
|
||||
custom_loadlist_recursive(dir, opts, {})
|
||||
end
|
||||
|
||||
if opts.items_appended == num_items then msg.warn(dir, "contained no valid files") end
|
||||
end
|
||||
|
||||
--load playlist entries before and after the currently playing file
|
||||
local function autoload_dir(path, opts)
|
||||
if o.autoload_save_current and path == g.current_file.path then
|
||||
mp.commandv("write-watch-later-config") end
|
||||
|
||||
--loads the currently selected file, clearing the playlist in the process
|
||||
loadfile(path, opts)
|
||||
|
||||
local pos = 1
|
||||
local file_count = 0
|
||||
for _,item in ipairs(state.list) do
|
||||
if item.type == "file"
|
||||
and not g.sub_extensions[ fb_utils.get_extension(item.name, "") ]
|
||||
and not g.audio_extensions[ fb_utils.get_extension(item.name, "") ]
|
||||
then
|
||||
local p = fb_utils.get_full_path(item)
|
||||
|
||||
if p == path then pos = file_count
|
||||
else loadfile( p, opts, item.mpv_options) end
|
||||
|
||||
file_count = file_count + 1
|
||||
end
|
||||
end
|
||||
mp.commandv("playlist-move", 0, pos+1)
|
||||
end
|
||||
|
||||
--runs the loadfile or loadlist command
|
||||
local function open_item(item, opts)
|
||||
if fb_utils.parseable_item(item) then
|
||||
return loadlist(item, opts)
|
||||
end
|
||||
|
||||
local path = fb_utils.get_full_path(item, opts.directory)
|
||||
if g.sub_extensions[ fb_utils.get_extension(item.name, "") ] then
|
||||
mp.commandv("sub-add", path, opts.flag == "replace" and "select" or "auto")
|
||||
elseif g.audio_extensions[ fb_utils.get_extension(item.name, "") ] then
|
||||
mp.commandv("audio-add", path, opts.flag == "replace" and "select" or "auto")
|
||||
else
|
||||
if opts.autoload then autoload_dir(path, opts)
|
||||
else loadfile(path, opts, item.mpv_options) end
|
||||
end
|
||||
end
|
||||
|
||||
--handles the open options as a coroutine
|
||||
--once loadfile has been run we can no-longer guarantee synchronous execution - the state values may change
|
||||
--therefore, we must ensure that any state values that could be used after a loadfile call are saved beforehand
|
||||
local function open_file_coroutine(opts)
|
||||
if not state.list[state.selected] then return end
|
||||
if opts.flag == 'replace' then controls.close() end
|
||||
|
||||
--we want to set the idle option to yes to ensure that if the first item
|
||||
--fails to load then the player has a chance to attempt to load further items (for async append operations)
|
||||
local idle = mp.get_property("idle", "once")
|
||||
mp.set_property("idle", "yes")
|
||||
|
||||
--handles multi-selection behaviour
|
||||
if next(state.selection) then
|
||||
local selection = fb_utils.sort_keys(state.selection)
|
||||
--reset the selection after
|
||||
state.selection = {}
|
||||
|
||||
cursor.disable_select_mode()
|
||||
ass.update_ass()
|
||||
|
||||
--the currently selected file will be loaded according to the flag
|
||||
--the flag variable will be switched to append once a file is loaded
|
||||
for i=1, #selection do
|
||||
open_item(selection[i], opts)
|
||||
end
|
||||
|
||||
else
|
||||
local item = state.list[state.selected]
|
||||
if opts.flag == "replace" then movement.down_dir() end
|
||||
open_item(item, opts)
|
||||
end
|
||||
|
||||
if mp.get_property("idle") == "yes" then mp.set_property("idle", idle) end
|
||||
end
|
||||
|
||||
--opens the selelected file(s)
|
||||
local function open_file(flag, autoload)
|
||||
fb_utils.coroutine.run(open_file_coroutine, {
|
||||
flag = flag,
|
||||
autoload = (autoload ~= o.autoload and flag == "replace"),
|
||||
directory = state.directory,
|
||||
items_appended = 0
|
||||
})
|
||||
end
|
||||
|
||||
return {
|
||||
add_files = open_file,
|
||||
}
|
||||
@@ -1,93 +0,0 @@
|
||||
local mp = require 'mp'
|
||||
local msg = require 'mp.msg'
|
||||
local utils = require 'mp.utils'
|
||||
|
||||
local o = require 'modules.options'
|
||||
local g = require 'modules.globals'
|
||||
local fb_utils = require 'modules.utils'
|
||||
local scanning = require 'modules.navigation.scanning'
|
||||
|
||||
local script_messages = {}
|
||||
|
||||
--allows other scripts to request directory contents from file-browser
|
||||
function script_messages.get_directory_contents(directory, response_str)
|
||||
fb_utils.coroutine.run(function()
|
||||
if not directory then msg.error("did not receive a directory string"); return end
|
||||
if not response_str then msg.error("did not receive a response string"); return end
|
||||
|
||||
directory = mp.command_native({"expand-path", directory}, "")
|
||||
if directory ~= "" then directory = fb_utils.fix_path(directory, true) end
|
||||
msg.verbose(("recieved %q from 'get-directory-contents' script message - returning result to %q"):format(directory, response_str))
|
||||
|
||||
directory = fb_utils.resolve_directory_mapping(directory)
|
||||
|
||||
local list, opts = scanning.scan_directory(directory, { source = "script-message" } )
|
||||
if opts then opts.API_VERSION = g.API_VERSION end
|
||||
|
||||
local err
|
||||
list, err = fb_utils.format_json_safe(list)
|
||||
if not list then msg.error(err) end
|
||||
|
||||
opts, err = fb_utils.format_json_safe(opts)
|
||||
if not opts then msg.error(err) end
|
||||
|
||||
mp.commandv("script-message", response_str, list or "", opts or "")
|
||||
end)
|
||||
end
|
||||
|
||||
--a helper script message for custom keybinds
|
||||
--substitutes any '=>' arguments for 'script-message'
|
||||
--makes chaining script-messages much easier
|
||||
function script_messages.chain(...)
|
||||
local command = table.pack('script-message', ...)
|
||||
for i, v in ipairs(command) do
|
||||
if v == '=>' then command[i] = 'script-message' end
|
||||
end
|
||||
mp.commandv(table.unpack(command))
|
||||
end
|
||||
|
||||
--a helper script message for custom keybinds
|
||||
--sends a command after the specified delay
|
||||
function script_messages.delay_command(delay, ...)
|
||||
local command = table.pack(...)
|
||||
local success, err = pcall(mp.add_timeout, fb_utils.evaluate_string('return '..delay), function() mp.commandv(table.unpack(command)) end)
|
||||
if not success then return msg.error(err) end
|
||||
end
|
||||
|
||||
--a helper script message for custom keybinds
|
||||
--sends a command only if the given expression returns true
|
||||
function script_messages.conditional_command(condition, ...)
|
||||
local command = table.pack(...)
|
||||
fb_utils.coroutine.run(function()
|
||||
if fb_utils.evaluate_string('return '..condition) == true then mp.commandv(table.unpack(command)) end
|
||||
end)
|
||||
end
|
||||
|
||||
--a helper script message for custom keybinds
|
||||
--extracts lua expressions from the command and evaluates them
|
||||
--expressions must be surrounded by !{}. Another ! before the { will escape the evaluation
|
||||
function script_messages.evaluate_expressions(...)
|
||||
local args = table.pack(...)
|
||||
fb_utils.coroutine.run(function()
|
||||
for i, arg in ipairs(args) do
|
||||
args[i] = arg:gsub('(!+)(%b{})', function(lead, expression)
|
||||
if #lead % 2 == 0 then return string.rep('!', #lead/2)..expression end
|
||||
|
||||
local eval = fb_utils.evaluate_string('return '..expression:sub(2, -2))
|
||||
return type(eval) == "table" and utils.to_string(eval) or tostring(eval)
|
||||
end)
|
||||
end
|
||||
|
||||
mp.commandv(table.unpack(args))
|
||||
end)
|
||||
end
|
||||
|
||||
--a helper function for custom-keybinds
|
||||
--concatenates the command arguments with newlines and runs the
|
||||
--string as a statement of code
|
||||
function script_messages.run_statement(...)
|
||||
local statement = table.concat(table.pack(...), '\n')
|
||||
fb_utils.coroutine.run(fb_utils.evaluate_string, statement)
|
||||
end
|
||||
|
||||
return script_messages
|
||||
@@ -1,52 +0,0 @@
|
||||
local mp = require 'mp'
|
||||
|
||||
local o = require 'modules.options'
|
||||
local g = require 'modules.globals'
|
||||
local fb_utils = require 'modules.utils'
|
||||
|
||||
--sets up the compatible extensions list
|
||||
local function setup_extensions_list()
|
||||
--setting up subtitle extensions
|
||||
for ext in fb_utils.iterate_opt(o.subtitle_extensions:lower()) do
|
||||
g.sub_extensions[ext] = true
|
||||
g.extensions[ext] = true
|
||||
end
|
||||
|
||||
--setting up audio extensions
|
||||
for ext in fb_utils.iterate_opt(o.audio_extensions:lower()) do
|
||||
g.audio_extensions[ext] = true
|
||||
g.extensions[ext] = true
|
||||
end
|
||||
|
||||
--adding file extensions to the set
|
||||
for _, ext in ipairs(g.compatible_file_extensions) do
|
||||
g.extensions[ext] = true
|
||||
end
|
||||
|
||||
--adding extra extensions on the whitelist
|
||||
for str in fb_utils.iterate_opt(o.extension_whitelist:lower()) do
|
||||
g.extensions[str] = true
|
||||
end
|
||||
|
||||
--removing extensions that are in the blacklist
|
||||
for str in fb_utils.iterate_opt(o.extension_blacklist:lower()) do
|
||||
g.extensions[str] = nil
|
||||
end
|
||||
end
|
||||
|
||||
--splits the string into a table on the separators
|
||||
local function setup_root()
|
||||
for str in fb_utils.iterate_opt(o.root) do
|
||||
local path = mp.command_native({'expand-path', str})
|
||||
path = fb_utils.fix_path(path, true)
|
||||
|
||||
local temp = {name = path, type = 'dir', label = str, ass = fb_utils.ass_escape(str, true)}
|
||||
|
||||
g.root[#g.root+1] = temp
|
||||
end
|
||||
end
|
||||
|
||||
return {
|
||||
extensions_list = setup_extensions_list,
|
||||
root = setup_root,
|
||||
}
|
||||
@@ -1,490 +0,0 @@
|
||||
--------------------------------------------------------------------------------------------------------
|
||||
-----------------------------------------Utility Functions----------------------------------------------
|
||||
---------------------------------------Part of the addon API--------------------------------------------
|
||||
--------------------------------------------------------------------------------------------------------
|
||||
|
||||
local mp = require 'mp'
|
||||
local msg = require 'mp.msg'
|
||||
local utils = require 'mp.utils'
|
||||
|
||||
local o = require 'modules.options'
|
||||
local g = require 'modules.globals'
|
||||
|
||||
local input_loaded, input = pcall(require, 'mp.input')
|
||||
local user_input_loaded, user_input = pcall(require, 'user-input-module')
|
||||
|
||||
--creates a table for the API functions
|
||||
--adds one metatable redirect to prevent addon authors from accidentally breaking file-browser
|
||||
local fb_utils = { API_VERSION = g.API_VERSION }
|
||||
|
||||
fb_utils.list = {}
|
||||
fb_utils.coroutine = {}
|
||||
|
||||
--implements table.pack if on lua 5.1
|
||||
if not table.pack then
|
||||
table.unpack = unpack
|
||||
---@diagnostic disable-next-line: duplicate-set-field
|
||||
function table.pack(...)
|
||||
local t = {n = select("#", ...), ...}
|
||||
return t
|
||||
end
|
||||
end
|
||||
|
||||
-- returns the index of the given item in the table
|
||||
-- return -1 if item does not exist
|
||||
function fb_utils.list.indexOf(t, item, from_index)
|
||||
for i = from_index or 1, #t, 1 do
|
||||
if t[i] == item then return i end
|
||||
end
|
||||
return -1
|
||||
end
|
||||
|
||||
--returns whether or not the given table contains an entry that
|
||||
--causes the given function to evaluate to true
|
||||
function fb_utils.list.some(t, fn)
|
||||
for i, v in ipairs(t) do
|
||||
if fn(v, i, t) then return true end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
-- Creates a new table populated with the results of
|
||||
-- calling a provided function on every element in t.
|
||||
function fb_utils.list.map(t, fn)
|
||||
local new_t = {}
|
||||
for i, v in ipairs(t) do
|
||||
new_t[i] = fn(v, i, t)
|
||||
end
|
||||
return new_t
|
||||
end
|
||||
|
||||
--prints an error message and a stack trace
|
||||
--accepts an error object and optionally a coroutine
|
||||
--can be passed directly to xpcall
|
||||
function fb_utils.traceback(errmsg, co)
|
||||
if co then
|
||||
msg.warn(debug.traceback(co))
|
||||
else
|
||||
msg.warn(debug.traceback("", 2))
|
||||
end
|
||||
msg.error(errmsg)
|
||||
end
|
||||
|
||||
--returns a table that stores the given table t as the __index in its metatable
|
||||
--creates a prototypally inherited table
|
||||
function fb_utils.redirect_table(t)
|
||||
return setmetatable({}, { __index = t })
|
||||
end
|
||||
|
||||
function fb_utils.set_prototype(t, proto)
|
||||
return setmetatable(t, { __index = proto })
|
||||
end
|
||||
|
||||
--prints an error if a coroutine returns an error
|
||||
--unlike the next function this one still returns the results of coroutine.resume()
|
||||
function fb_utils.coroutine.resume_catch(...)
|
||||
local returns = table.pack(coroutine.resume(...))
|
||||
if not returns[1] and returns[2] ~= g.ABORT_ERROR then
|
||||
fb_utils.traceback(returns[2], select(1, ...))
|
||||
end
|
||||
return table.unpack(returns, 1, returns.n)
|
||||
end
|
||||
|
||||
--resumes a coroutine and prints an error if it was not sucessful
|
||||
function fb_utils.coroutine.resume_err(...)
|
||||
local success, err = coroutine.resume(...)
|
||||
if not success and err ~= g.ABORT_ERROR then
|
||||
fb_utils.traceback(err, select(1, ...))
|
||||
end
|
||||
return success
|
||||
end
|
||||
|
||||
--in lua 5.1 there is only one return value which will be nil if run from the main thread
|
||||
--in lua 5.2 main will be true if running from the main thread
|
||||
function fb_utils.coroutine.assert(err)
|
||||
local co, main = coroutine.running()
|
||||
assert(not main and co, err or "error - function must be executed from within a coroutine")
|
||||
return co
|
||||
end
|
||||
|
||||
-- Creates a callback function to resume the current coroutine with the given time limit.
|
||||
-- If the time limit expires the coroutine will be resumed. The first return value will be true
|
||||
-- if the callback was resumed within the time limit and false otherwise.
|
||||
-- If time_limit is falsy then there will be no time limit and there will be no additional return value.
|
||||
function fb_utils.coroutine.callback(time_limit)
|
||||
local co = fb_utils.coroutine.assert("cannot create a coroutine callback for the main thread")
|
||||
local timer = time_limit and mp.add_timeout(time_limit, function ()
|
||||
msg.debug("time limit on callback expired")
|
||||
fb_utils.coroutine.resume_err(co, false)
|
||||
end)
|
||||
return function(...)
|
||||
if timer then
|
||||
if not timer:is_enabled() then return
|
||||
else timer:kill() end
|
||||
return fb_utils.coroutine.resume_err(co, true, ...)
|
||||
end
|
||||
return fb_utils.coroutine.resume_err(co, ...)
|
||||
end
|
||||
end
|
||||
|
||||
--puts the current coroutine to sleep for the given number of seconds
|
||||
function fb_utils.coroutine.sleep(n)
|
||||
mp.add_timeout(n, fb_utils.coroutine.callback())
|
||||
coroutine.yield()
|
||||
end
|
||||
|
||||
|
||||
--Runs the given function in a coroutine, passing through any additional arguments.
|
||||
--Does not run the coroutine immediately, instead it ques the coroutine to run when the thread is next idle.
|
||||
--Returns the coroutine object so that the caller can act on it before it is run.
|
||||
function fb_utils.coroutine.queue(fn, ...)
|
||||
local co = coroutine.create(fn)
|
||||
local args = table.pack(...)
|
||||
mp.add_timeout(0, function() fb_utils.coroutine.resume_err(co, table.unpack(args, 1, args.n)) end)
|
||||
return co
|
||||
end
|
||||
|
||||
--runs the given function in a coroutine, passing through any additional arguments
|
||||
--this is for triggering an event in a coroutine
|
||||
function fb_utils.coroutine.run(fn, ...)
|
||||
local co = coroutine.create(fn)
|
||||
fb_utils.coroutine.resume_err(co, ...)
|
||||
end
|
||||
|
||||
--get the full path for the current file
|
||||
function fb_utils.get_full_path(item, dir)
|
||||
if item.path then return item.path end
|
||||
return (dir or g.state.directory)..item.name
|
||||
end
|
||||
|
||||
--gets the path for a new subdirectory, redirects if the path field is set
|
||||
--returns the new directory path and a boolean specifying if a redirect happened
|
||||
function fb_utils.get_new_directory(item, directory)
|
||||
if item.path and item.redirect ~= false then return item.path, true end
|
||||
if directory == "" then return item.name end
|
||||
if string.sub(directory, -1) == "/" then return directory..item.name end
|
||||
return directory.."/"..item.name
|
||||
end
|
||||
|
||||
--returns the file extension of the given file
|
||||
function fb_utils.get_extension(filename, def)
|
||||
return string.lower(filename):match("%.([^%./]+)$") or def
|
||||
end
|
||||
|
||||
--returns the protocol scheme of the given url, or nil if there is none
|
||||
function fb_utils.get_protocol(filename, def)
|
||||
return string.lower(filename):match("^(%a[%w+-.]*)://") or def
|
||||
end
|
||||
|
||||
--formats strings for ass handling
|
||||
--this function is based on a similar function from https://github.com/mpv-player/mpv/blob/master/player/lua/console.lua#L110
|
||||
function fb_utils.ass_escape(str, replace_newline)
|
||||
if replace_newline == true then replace_newline = "\\\239\187\191n" end
|
||||
|
||||
--escape the invalid single characters
|
||||
str = string.gsub(str, '[\\{}\n]', {
|
||||
-- There is no escape for '\' in ASS (I think?) but '\' is used verbatim if
|
||||
-- it isn't followed by a recognised character, so add a zero-width
|
||||
-- non-breaking space
|
||||
['\\'] = '\\\239\187\191',
|
||||
['{'] = '\\{',
|
||||
['}'] = '\\}',
|
||||
-- Precede newlines with a ZWNBSP to prevent ASS's weird collapsing of
|
||||
-- consecutive newlines
|
||||
['\n'] = '\239\187\191\\N',
|
||||
})
|
||||
|
||||
-- Turn leading spaces into hard spaces to prevent ASS from stripping them
|
||||
str = str:gsub('\\N ', '\\N\\h')
|
||||
str = str:gsub('^ ', '\\h')
|
||||
|
||||
if replace_newline then
|
||||
str = str:gsub("\\N", replace_newline)
|
||||
end
|
||||
return str
|
||||
end
|
||||
|
||||
--escape lua pattern characters
|
||||
function fb_utils.pattern_escape(str)
|
||||
return string.gsub(str, "([%^%$%(%)%%%.%[%]%*%+%-])", "%%%1")
|
||||
end
|
||||
|
||||
--standardises filepaths across systems
|
||||
function fb_utils.fix_path(str, is_directory)
|
||||
if str == '' then return str end
|
||||
if o.normalise_backslash == 'yes' or (o.normalise_backslash == 'auto' and g.PLATFORM == 'windows') then
|
||||
str = string.gsub(str, [[\]],[[/]])
|
||||
end
|
||||
str = str:gsub([[/%./]], [[/]])
|
||||
if is_directory and str:sub(-1) ~= '/' then str = str..'/' end
|
||||
return str
|
||||
end
|
||||
|
||||
--wrapper for utils.join_path to handle protocols
|
||||
function fb_utils.join_path(working, relative)
|
||||
return fb_utils.get_protocol(relative) and relative or utils.join_path(working, relative)
|
||||
end
|
||||
|
||||
--converts the given path into an absolute path and normalises it using fb_utils.fix_path
|
||||
function fb_utils.absolute_path(path)
|
||||
local absolute_path = fb_utils.join_path(mp.get_property('working-directory', ''), path)
|
||||
return fb_utils.fix_path(absolute_path)
|
||||
end
|
||||
|
||||
--sorts the table lexicographically ignoring case and accounting for leading/non-leading zeroes
|
||||
--the number format functionality was proposed by github user twophyro, and was presumably taken
|
||||
--from here: http://notebook.kulchenko.com/algorithms/alphanumeric-natural-sorting-for-humans-in-lua
|
||||
function fb_utils.sort(t)
|
||||
local function padnum(n, d)
|
||||
return #d > 0 and ("%03d%s%.12f"):format(#n, n, tonumber(d) / (10 ^ #d))
|
||||
or ("%03d%s"):format(#n, n)
|
||||
end
|
||||
|
||||
--appends the letter d or f to the start of the comparison to sort directories and folders as well
|
||||
local tuples = {}
|
||||
for i, f in ipairs(t) do
|
||||
tuples[i] = {f.type:sub(1, 1) .. (f.label or f.name):lower():gsub("0*(%d+)%.?(%d*)", padnum), f}
|
||||
end
|
||||
table.sort(tuples, function(a, b)
|
||||
return a[1] == b[1] and #b[2] < #a[2] or a[1] < b[1]
|
||||
end)
|
||||
for i, tuple in ipairs(tuples) do t[i] = tuple[2] end
|
||||
return t
|
||||
end
|
||||
|
||||
function fb_utils.valid_dir(dir)
|
||||
if o.filter_dot_dirs and string.sub(dir, 1, 1) == "." then return false end
|
||||
return true
|
||||
end
|
||||
|
||||
function fb_utils.valid_file(file)
|
||||
if o.filter_dot_files and (string.sub(file, 1, 1) == ".") then return false end
|
||||
if o.filter_files and not g.extensions[ fb_utils.get_extension(file, "") ] then return false end
|
||||
return true
|
||||
end
|
||||
|
||||
--returns whether or not the item can be parsed
|
||||
function fb_utils.parseable_item(item)
|
||||
return item.type == "dir" or g.parseable_extensions[fb_utils.get_extension(item.name, "")]
|
||||
end
|
||||
|
||||
-- Takes a directory string and resolves any directory mappings,
|
||||
-- returning the resolved directory.
|
||||
function fb_utils.resolve_directory_mapping(path)
|
||||
if not path then return path end
|
||||
|
||||
for mapping, target in pairs(g.directory_mappings) do
|
||||
local start, finish = string.find(path, mapping)
|
||||
if start then
|
||||
msg.debug('mapping', mapping, 'found for', path, 'changing to', target)
|
||||
|
||||
-- if the mapping is an exact match then return the target as is
|
||||
if finish == #path then return target end
|
||||
|
||||
-- else make sure the path is correctly formatted
|
||||
target = fb_utils.fix_path(target, true)
|
||||
return string.gsub(path, mapping, target)
|
||||
end
|
||||
end
|
||||
|
||||
return path
|
||||
end
|
||||
|
||||
--removes items and folders from the list
|
||||
--this is for addons which can't filter things during their normal processing
|
||||
function fb_utils.filter(t)
|
||||
local max = #t
|
||||
local top = 1
|
||||
for i = 1, max do
|
||||
local temp = t[i]
|
||||
t[i] = nil
|
||||
|
||||
if ( temp.type == "dir" and fb_utils.valid_dir(temp.label or temp.name) ) or
|
||||
( temp.type == "file" and fb_utils.valid_file(temp.label or temp.name) )
|
||||
then
|
||||
t[top] = temp
|
||||
top = top+1
|
||||
end
|
||||
end
|
||||
return t
|
||||
end
|
||||
|
||||
--returns a string iterator that uses the root separators
|
||||
function fb_utils.iterate_opt(str)
|
||||
return string.gmatch(str, "([^"..fb_utils.pattern_escape(o.root_separators).."]+)")
|
||||
end
|
||||
|
||||
--sorts a table into an array of selected items in the correct order
|
||||
--if a predicate function is passed, then the item will only be added to
|
||||
--the table if the function returns true
|
||||
function fb_utils.sort_keys(t, include_item)
|
||||
local keys = {}
|
||||
for k in pairs(t) do
|
||||
local item = g.state.list[k]
|
||||
if not include_item or include_item(item) then
|
||||
item.index = k
|
||||
keys[#keys+1] = item
|
||||
end
|
||||
end
|
||||
|
||||
table.sort(keys, function(a,b) return a.index < b.index end)
|
||||
return keys
|
||||
end
|
||||
|
||||
--Uses a loop to get the length of an array. The `#` operator is undefined if there
|
||||
--are gaps in the array, this ensures there are none as expected by the mpv node function.
|
||||
local function get_length(t)
|
||||
local i = 1
|
||||
while t[i] do i = i+1 end
|
||||
return i - 1
|
||||
end
|
||||
|
||||
--recursively removes elements of the table which would cause
|
||||
--utils.format_json to throw an error
|
||||
local function json_safe_recursive(t)
|
||||
if type(t) ~= "table" then return t end
|
||||
|
||||
local array_length = get_length(t)
|
||||
local isarray = array_length > 0
|
||||
|
||||
for key, value in pairs(t) do
|
||||
local ktype = type(key)
|
||||
local vtype = type(value)
|
||||
|
||||
if vtype ~= "userdata" and vtype ~= "function" and vtype ~= "thread"
|
||||
and (( isarray and ktype == "number" and key <= array_length)
|
||||
or (not isarray and ktype == "string"))
|
||||
then
|
||||
t[key] = json_safe_recursive(t[key])
|
||||
elseif key then
|
||||
t[key] = nil
|
||||
if isarray then array_length = get_length(t) end
|
||||
end
|
||||
end
|
||||
return t
|
||||
end
|
||||
|
||||
--formats a table into a json string but ensures there are no invalid datatypes inside the table first
|
||||
function fb_utils.format_json_safe(t)
|
||||
--operate on a copy of the table to prevent any data loss in the original table
|
||||
t = json_safe_recursive(fb_utils.copy_table(t))
|
||||
local success, result, err = pcall(utils.format_json, t)
|
||||
if success then return result, err
|
||||
else return nil, result end
|
||||
end
|
||||
|
||||
--evaluates and runs the given string in both Lua 5.1 and 5.2
|
||||
--the name argument is used for error reporting
|
||||
--provides the mpv modules and the fb module to the string
|
||||
function fb_utils.evaluate_string(str, chunkname, custom_env, env_defaults)
|
||||
local env
|
||||
if env_defaults ~= false then
|
||||
env = fb_utils.redirect_table(_G)
|
||||
env.mp = fb_utils.redirect_table(mp)
|
||||
env.msg = fb_utils.redirect_table(msg)
|
||||
env.utils = fb_utils.redirect_table(utils)
|
||||
env.fb = fb_utils.redirect_table(fb_utils)
|
||||
env.input = input_loaded and fb_utils.redirect_table(input)
|
||||
env.user_input = user_input_loaded and fb_utils.redirect_table(user_input)
|
||||
env = fb_utils.set_prototype(custom_env or {}, env)
|
||||
else
|
||||
env = custom_env or {}
|
||||
end
|
||||
|
||||
local chunk, err
|
||||
if setfenv then
|
||||
chunk, err = loadstring(str, chunkname)
|
||||
if chunk then setfenv(chunk, env) end
|
||||
else
|
||||
chunk, err = load(str, chunkname, 't', env)
|
||||
end
|
||||
if not chunk then
|
||||
msg.warn('failed to load string:', str)
|
||||
msg.error(err)
|
||||
chunk = function() return nil end
|
||||
end
|
||||
|
||||
return chunk()
|
||||
end
|
||||
|
||||
--copies a table without leaving any references to the original
|
||||
--uses a structured clone algorithm to maintain cyclic references
|
||||
local function copy_table_recursive(t, references, depth)
|
||||
if type(t) ~= "table" or depth == 0 then return t end
|
||||
if references[t] then return references[t] end
|
||||
|
||||
local copy = setmetatable({}, { __original = t })
|
||||
references[t] = copy
|
||||
|
||||
for key, value in pairs(t) do
|
||||
key = copy_table_recursive(key, references, depth - 1)
|
||||
copy[key] = copy_table_recursive(value, references, depth - 1)
|
||||
end
|
||||
return copy
|
||||
end
|
||||
|
||||
--a wrapper around copy_table to provide the reference table
|
||||
function fb_utils.copy_table(t, depth)
|
||||
--this is to handle cyclic table references
|
||||
return copy_table_recursive(t, {}, depth or math.huge)
|
||||
end
|
||||
|
||||
--functions to replace custom-keybind codes
|
||||
fb_utils.code_fns = {
|
||||
["%"] = "%",
|
||||
|
||||
f = function(item, s) return item and fb_utils.get_full_path(item, s.directory) or "" end,
|
||||
n = function(item, s) return item and (item.label or item.name) or "" end,
|
||||
i = function(item, s)
|
||||
local i = fb_utils.list.indexOf(s.list, item)
|
||||
return i ~= -1 and ('%0'..math.ceil(math.log10(#s.list))..'d'):format(i) or 0
|
||||
end,
|
||||
j = function (item, s)
|
||||
return fb_utils.list.indexOf(s.list, item) ~= -1 and math.abs(fb_utils.list.indexOf( fb_utils.sort_keys(s.selection) , item)) or 0
|
||||
end,
|
||||
x = function(_, s) return #s.list or 0 end,
|
||||
p = function(_, s) return s.directory or "" end,
|
||||
q = function(_, s) return s.directory == '' and 'ROOT' or s.directory_label or s.directory or "" end,
|
||||
d = function(_, s) return (s.directory_label or s.directory):match("([^/]+)/?$") or "" end,
|
||||
r = function(_, s) return s.parser.keybind_name or s.parser.name or "" end,
|
||||
}
|
||||
|
||||
-- programatically creates a pattern that matches any key code
|
||||
-- this will result in some duplicates but that shouldn't really matter
|
||||
function fb_utils.get_code_pattern(codes)
|
||||
local CUSTOM_KEYBIND_CODES = ""
|
||||
for key in pairs(codes) do CUSTOM_KEYBIND_CODES = CUSTOM_KEYBIND_CODES..key:lower()..key:upper() end
|
||||
for key in pairs((getmetatable(codes) or {}).__index or {}) do CUSTOM_KEYBIND_CODES = CUSTOM_KEYBIND_CODES..key:lower()..key:upper() end
|
||||
return('%%%%([%s])'):format(fb_utils.pattern_escape(CUSTOM_KEYBIND_CODES))
|
||||
end
|
||||
|
||||
-- substitutes codes in the given string for other substrings
|
||||
-- overrides is a map of characters->strings|functions that determines the replacement string is
|
||||
-- item and state are values passed to functions in the map
|
||||
-- modifier_fn is given the replacement substrings before they are placed in the main string (the return value is the new replacement string)
|
||||
function fb_utils.substitute_codes(str, overrides, item, state, modifier_fn)
|
||||
local replacers = overrides and setmetatable(fb_utils.copy_table(overrides), {__index = fb_utils.code_fns}) or fb_utils.code_fns
|
||||
item = item or g.state.list[g.state.selected]
|
||||
state = state or g.state
|
||||
|
||||
return (string.gsub(str, fb_utils.get_code_pattern(replacers), function(code)
|
||||
local result
|
||||
|
||||
if type(replacers[code]) == "string" then
|
||||
result = replacers[code]
|
||||
--encapsulates the string if using an uppercase code
|
||||
elseif not replacers[code] then
|
||||
local lower_fn = replacers[code:lower()]
|
||||
if not lower_fn then return end
|
||||
result = string.format("%q", lower_fn(item, state))
|
||||
else
|
||||
result = replacers[code](item, state)
|
||||
end
|
||||
|
||||
if modifier_fn then return modifier_fn(result) end
|
||||
return result
|
||||
end))
|
||||
end
|
||||
|
||||
|
||||
return fb_utils
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 2.8 MiB |
Binary file not shown.
|
Before Width: | Height: | Size: 975 KiB |
@@ -1,97 +0,0 @@
|
||||
local utils = require 'mp.utils'
|
||||
local lastopenFileName = "lastopen.json"
|
||||
|
||||
local styleOn = mp.get_property("osd-ass-cc/0")
|
||||
local styleOff = mp.get_property("osd-ass-cc/1")
|
||||
|
||||
|
||||
-- Check if the operating system is Windows
|
||||
function isWindows()
|
||||
local windir = os.getenv("windir")
|
||||
return (windir~=nil)
|
||||
end
|
||||
|
||||
|
||||
-- Get the filepath of a file from the mpv config folder
|
||||
local function getFilepath(filename)
|
||||
if isWindows() then
|
||||
return os.getenv("APPDATA"):gsub("\\", "/") .. "/mpv/" .. filename
|
||||
else
|
||||
return os.getenv("HOME") .. "/.config/mpv/" .. filename
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
local options = {
|
||||
path = getFilepath(lastopenFileName)
|
||||
}
|
||||
|
||||
-- Save a table as a JSON file file
|
||||
-- Returns true if successful
|
||||
function saveTable(t, path)
|
||||
local contents = utils.format_json(t)
|
||||
local file = io.open(path .. ".tmp", "wb")
|
||||
file:write(contents)
|
||||
io.close(file)
|
||||
os.remove(path)
|
||||
os.rename(path .. ".tmp", path)
|
||||
return true
|
||||
end
|
||||
|
||||
function file_exists(path)
|
||||
local file = io.open(path, "r") -- Try to open the file in read mode
|
||||
if file then
|
||||
file:close() -- Close the file if it was successfully opened
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
local function save_data()
|
||||
local data = {
|
||||
path = mp.get_property('path'),
|
||||
time_pos = mp.get_property_number('time-pos')
|
||||
}
|
||||
saveTable(data, options.path)
|
||||
end
|
||||
|
||||
function loadData(path)
|
||||
local contents = ""
|
||||
local myTable = {}
|
||||
local file = io.open( path, "r" )
|
||||
if file then
|
||||
local contents = file:read( "*a" )
|
||||
myTable = utils.parse_json(contents);
|
||||
io.close(file)
|
||||
return myTable
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
-- Parses a Windows path with backslashes to one with normal slashes
|
||||
function parsePath(path)
|
||||
if type(path) == "string" then path, _ = path:gsub("\\", "/") end
|
||||
return path
|
||||
end
|
||||
|
||||
local function load_data()
|
||||
local data = loadData(getFilepath(lastopenFileName))
|
||||
if data then
|
||||
if data.path and file_exists(data.path) then
|
||||
mp.commandv("loadfile", parsePath(data.path), "replace", -1)
|
||||
local message = styleOn.."{\\b1}Last Open load:\n"..data.path.."{\\b0}"..styleOff
|
||||
mp.osd_message(message)
|
||||
elseif not file_exists(data.path) then
|
||||
mp.osd_message('File not found: '..data.path)
|
||||
else
|
||||
mp.osd_message('Failed to parse lastopen.json')
|
||||
end
|
||||
else
|
||||
mp.osd_message('No lastopen.json found')
|
||||
end
|
||||
end
|
||||
|
||||
mp.register_event('start-file', save_data)
|
||||
|
||||
mp.register_script_message("lastopen", load_data)
|
||||
3717
mpv/scripts/modernz.lua
Normal file
3717
mpv/scripts/modernz.lua
Normal file
File diff suppressed because it is too large
Load Diff
191
mpv/scripts/mpv-gif.lua
Normal file
191
mpv/scripts/mpv-gif.lua
Normal file
@@ -0,0 +1,191 @@
|
||||
-- Original by Ruin0x11
|
||||
-- Ported to Windows by Scheliux, Dragoner7
|
||||
|
||||
-- Create animated GIFs with mpv
|
||||
-- Requires ffmpeg.
|
||||
-- Adapted from http://blog.pkh.me/p/21-high-quality-gif-with-ffmpeg.html
|
||||
-- Usage: "b" to set start frame, "B" to set end frame, "Ctrl+b" to create.
|
||||
|
||||
require 'mp.options'
|
||||
local msg = require 'mp.msg'
|
||||
|
||||
local options = {
|
||||
dir = "C:/Program Files/mpv/gifs",
|
||||
rez = 600,
|
||||
fps = 15,
|
||||
}
|
||||
|
||||
read_options(options, "gif")
|
||||
|
||||
|
||||
local fps
|
||||
|
||||
-- Check for invalid fps values
|
||||
-- Can you believe Lua doesn't have a proper ternary operator in the year of our lord 2020?
|
||||
if options.fps ~= nil and options.fps >= 1 and options.fps < 30 then
|
||||
fps = options.fps
|
||||
else
|
||||
fps = 15
|
||||
end
|
||||
|
||||
-- Set this to the filters to pass into ffmpeg's -vf option.
|
||||
-- filters="fps=24,scale=320:-1:flags=spline"
|
||||
filters=string.format("fps=%s,scale='trunc(ih*dar/2)*2:trunc(ih/2)*2',setsar=1/1,scale=%s:-1:flags=spline", fps, options.rez) --change spline to lanczos depending on preference
|
||||
|
||||
-- Setup output directory
|
||||
output_directory=string.gsub(options.dir, '\"', '')
|
||||
|
||||
start_time = -1
|
||||
end_time = -1
|
||||
palette="%TEMP%palette.png"
|
||||
|
||||
-- The roundabout way has to be used due to a some weird
|
||||
-- behavior with %TEMP% on the subtitles= parameter in ffmpeg
|
||||
-- on Windows–it needs to be quadruple backslashed
|
||||
subs = "C:/Users/%USERNAME%/AppData/Local/Temp/subs.srt"
|
||||
|
||||
function make_gif_with_subtitles()
|
||||
make_gif_internal(true)
|
||||
end
|
||||
|
||||
function make_gif()
|
||||
make_gif_internal(false)
|
||||
end
|
||||
|
||||
function table_length(t)
|
||||
local count = 0
|
||||
for _ in pairs(t) do count = count + 1 end
|
||||
return count
|
||||
end
|
||||
|
||||
|
||||
function make_gif_internal(burn_subtitles)
|
||||
local start_time_l = start_time
|
||||
local end_time_l = end_time
|
||||
if start_time_l == -1 or end_time_l == -1 or start_time_l >= end_time_l then
|
||||
mp.osd_message("Invalid start/end time.")
|
||||
return
|
||||
end
|
||||
|
||||
mp.osd_message("Creating GIF.")
|
||||
|
||||
-- shell escape
|
||||
function esc(s)
|
||||
return string.gsub(s, '"', '"\\""')
|
||||
end
|
||||
|
||||
function esc_for_sub(s)
|
||||
s = string.gsub(s, [[\]], [[/]])
|
||||
s = string.gsub(s, '"', '"\\""')
|
||||
s = string.gsub(s, ":", [[\\:]])
|
||||
s = string.gsub(s, "'", [[\\']])
|
||||
return s
|
||||
end
|
||||
|
||||
local pathname = mp.get_property("path", "")
|
||||
local trim_filters = esc(filters)
|
||||
|
||||
local position = start_time_l
|
||||
local duration = end_time_l - start_time_l
|
||||
|
||||
if burn_subtitles then
|
||||
-- Determine currently active sub track
|
||||
|
||||
local i = 0
|
||||
local tracks_count = mp.get_property_number("track-list/count")
|
||||
local subs_array = {}
|
||||
|
||||
-- check for subtitle tracks
|
||||
|
||||
while i < tracks_count do
|
||||
local type = mp.get_property(string.format("track-list/%d/type", i))
|
||||
local selected = mp.get_property(string.format("track-list/%d/selected", i))
|
||||
|
||||
-- if it's a sub track, save it
|
||||
|
||||
if type == "sub" then
|
||||
local length = table_length(subs_array)
|
||||
subs_array[length] = selected == "yes"
|
||||
end
|
||||
i = i + 1
|
||||
end
|
||||
|
||||
if table_length(subs_array) > 0 then
|
||||
|
||||
local correct_track = 0
|
||||
|
||||
-- iterate through saved subtitle tracks until the correct one is found
|
||||
|
||||
for index, is_selected in pairs(subs_array) do
|
||||
if (is_selected) then
|
||||
correct_track = index
|
||||
end
|
||||
end
|
||||
|
||||
trim_filters = trim_filters .. string.format(",subtitles=%s:si=%s", esc_for_sub(pathname), correct_track)
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
-- first, create the palette
|
||||
args = string.format('ffmpeg -v warning -ss %s -t %s -i "%s" -vf "%s,palettegen" -y "%s"', position, duration, esc(pathname), esc(trim_filters), esc(palette))
|
||||
msg.debug(args)
|
||||
os.execute(args)
|
||||
|
||||
-- then, make the gif
|
||||
local filename = mp.get_property("filename/no-ext")
|
||||
local file_path = output_directory .. "/" .. filename
|
||||
|
||||
-- increment filename
|
||||
for i=0,999 do
|
||||
local fn = string.format('%s_%03d.gif',file_path,i)
|
||||
if not file_exists(fn) then
|
||||
gifname = fn
|
||||
break
|
||||
end
|
||||
end
|
||||
if not gifname then
|
||||
mp.osd_message('No available filenames!')
|
||||
return
|
||||
end
|
||||
|
||||
local copyts = ""
|
||||
|
||||
if burn_subtitles then
|
||||
copyts = "-copyts"
|
||||
end
|
||||
|
||||
args = string.format('ffmpeg -v warning -ss %s %s -t %s -i "%s" -i "%s" -lavfi "%s [x]; [x][1:v] paletteuse" -y "%s"', position, copyts, duration, esc(pathname), esc(palette), esc(trim_filters), esc(gifname))
|
||||
os.execute(args)
|
||||
|
||||
local ok, err, code = os.rename(gifname, gifname)
|
||||
if ok then
|
||||
msg.info("GIF created: " .. gifname)
|
||||
mp.osd_message("GIF created: " .. gifname)
|
||||
else
|
||||
mp.osd_message("Error creating file, check CLI for more info.")
|
||||
end
|
||||
end
|
||||
|
||||
function set_gif_start()
|
||||
start_time = mp.get_property_number("time-pos", -1)
|
||||
mp.osd_message("GIF Start: " .. start_time)
|
||||
end
|
||||
|
||||
function set_gif_end()
|
||||
end_time = mp.get_property_number("time-pos", -1)
|
||||
mp.osd_message("GIF End: " .. end_time)
|
||||
end
|
||||
|
||||
function file_exists(name)
|
||||
local f=io.open(name,"r")
|
||||
if f~=nil then io.close(f) return true else return false end
|
||||
end
|
||||
|
||||
-- all keybindings here are set to nil on purpose 'cause I modified the keybindings (in input.conf)
|
||||
mp.add_key_binding(nil, "set_gif_start", set_gif_start)
|
||||
mp.add_key_binding(nil, "set_gif_end", set_gif_end)
|
||||
mp.add_key_binding(nil, "make_gif", make_gif)
|
||||
mp.add_key_binding(nil, "make_gif_with_subtitles", make_gif_with_subtitles) -- making GIFs with subtitles doesn't seem to work
|
||||
@@ -1,736 +0,0 @@
|
||||
--[[
|
||||
Copyright (C) 2017 AMM
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
]]--
|
||||
--[[
|
||||
mpv_thumbnail_script.lua 0.4.3 - commit 682becf (branch master)
|
||||
https://github.com/TheAMM/mpv_thumbnail_script
|
||||
Built on 2020-01-17 00:00:00
|
||||
]]--
|
||||
local assdraw = require 'mp.assdraw'
|
||||
local msg = require 'mp.msg'
|
||||
local opt = require 'mp.options'
|
||||
local utils = require 'mp.utils'
|
||||
|
||||
-- Determine platform --
|
||||
ON_WINDOWS = (package.config:sub(1,1) ~= '/')
|
||||
|
||||
-- Some helper functions needed to parse the options --
|
||||
function isempty(v) return (v == false) or (v == nil) or (v == "") or (v == 0) or (type(v) == "table" and next(v) == nil) end
|
||||
|
||||
function divmod (a, b)
|
||||
return math.floor(a / b), a % b
|
||||
end
|
||||
|
||||
-- Better modulo
|
||||
function bmod( i, N )
|
||||
return (i % N + N) % N
|
||||
end
|
||||
|
||||
function join_paths(...)
|
||||
local sep = ON_WINDOWS and "\\" or "/"
|
||||
local result = "";
|
||||
for i, p in pairs({...}) do
|
||||
if p ~= "" then
|
||||
if is_absolute_path(p) then
|
||||
result = p
|
||||
else
|
||||
result = (result ~= "") and (result:gsub("[\\"..sep.."]*$", "") .. sep .. p) or p
|
||||
end
|
||||
end
|
||||
end
|
||||
return result:gsub("[\\"..sep.."]*$", "")
|
||||
end
|
||||
|
||||
-- /some/path/file.ext -> /some/path, file.ext
|
||||
function split_path( path )
|
||||
local sep = ON_WINDOWS and "\\" or "/"
|
||||
local first_index, last_index = path:find('^.*' .. sep)
|
||||
|
||||
if last_index == nil then
|
||||
return "", path
|
||||
else
|
||||
local dir = path:sub(0, last_index-1)
|
||||
local file = path:sub(last_index+1, -1)
|
||||
|
||||
return dir, file
|
||||
end
|
||||
end
|
||||
|
||||
function is_absolute_path( path )
|
||||
local tmp, is_win = path:gsub("^[A-Z]:\\", "")
|
||||
local tmp, is_unix = path:gsub("^/", "")
|
||||
return (is_win > 0) or (is_unix > 0)
|
||||
end
|
||||
|
||||
function Set(source)
|
||||
local set = {}
|
||||
for _, l in ipairs(source) do set[l] = true end
|
||||
return set
|
||||
end
|
||||
|
||||
---------------------------
|
||||
-- More helper functions --
|
||||
---------------------------
|
||||
|
||||
-- Removes all keys from a table, without destroying the reference to it
|
||||
function clear_table(target)
|
||||
for key, value in pairs(target) do
|
||||
target[key] = nil
|
||||
end
|
||||
end
|
||||
function shallow_copy(target)
|
||||
local copy = {}
|
||||
for k, v in pairs(target) do
|
||||
copy[k] = v
|
||||
end
|
||||
return copy
|
||||
end
|
||||
|
||||
-- Rounds to given decimals. eg. round_dec(3.145, 0) => 3
|
||||
function round_dec(num, idp)
|
||||
local mult = 10^(idp or 0)
|
||||
return math.floor(num * mult + 0.5) / mult
|
||||
end
|
||||
|
||||
function file_exists(name)
|
||||
local f = io.open(name, "rb")
|
||||
if f ~= nil then
|
||||
local ok, err, code = f:read(1)
|
||||
io.close(f)
|
||||
return code == nil
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
function path_exists(name)
|
||||
local f = io.open(name, "rb")
|
||||
if f ~= nil then
|
||||
io.close(f)
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
function create_directories(path)
|
||||
local cmd
|
||||
if ON_WINDOWS then
|
||||
cmd = { args = {"cmd", "/c", "mkdir", path} }
|
||||
else
|
||||
cmd = { args = {"mkdir", "-p", path} }
|
||||
end
|
||||
utils.subprocess(cmd)
|
||||
end
|
||||
|
||||
-- Find an executable in PATH or CWD with the given name
|
||||
function find_executable(name)
|
||||
local delim = ON_WINDOWS and ";" or ":"
|
||||
|
||||
local pwd = os.getenv("PWD") or utils.getcwd()
|
||||
local path = os.getenv("PATH")
|
||||
|
||||
local env_path = pwd .. delim .. path -- Check CWD first
|
||||
|
||||
local result, filename
|
||||
for path_dir in env_path:gmatch("[^"..delim.."]+") do
|
||||
filename = join_paths(path_dir, name)
|
||||
if file_exists(filename) then
|
||||
result = filename
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
return result
|
||||
end
|
||||
|
||||
local ExecutableFinder = { path_cache = {} }
|
||||
-- Searches for an executable and caches the result if any
|
||||
function ExecutableFinder:get_executable_path( name, raw_name )
|
||||
name = ON_WINDOWS and not raw_name and (name .. ".exe") or name
|
||||
|
||||
if self.path_cache[name] == nil then
|
||||
self.path_cache[name] = find_executable(name) or false
|
||||
end
|
||||
return self.path_cache[name]
|
||||
end
|
||||
|
||||
-- Format seconds to HH.MM.SS.sss
|
||||
function format_time(seconds, sep, decimals)
|
||||
decimals = decimals == nil and 3 or decimals
|
||||
sep = sep and sep or "."
|
||||
local s = seconds
|
||||
local h, s = divmod(s, 60*60)
|
||||
local m, s = divmod(s, 60)
|
||||
|
||||
local second_format = string.format("%%0%d.%df", 2+(decimals > 0 and decimals+1 or 0), decimals)
|
||||
|
||||
return string.format("%02d"..sep.."%02d"..sep..second_format, h, m, s)
|
||||
end
|
||||
|
||||
-- Format seconds to 1h 2m 3.4s
|
||||
function format_time_hms(seconds, sep, decimals, force_full)
|
||||
decimals = decimals == nil and 1 or decimals
|
||||
sep = sep ~= nil and sep or " "
|
||||
|
||||
local s = seconds
|
||||
local h, s = divmod(s, 60*60)
|
||||
local m, s = divmod(s, 60)
|
||||
|
||||
if force_full or h > 0 then
|
||||
return string.format("%dh"..sep.."%dm"..sep.."%." .. tostring(decimals) .. "fs", h, m, s)
|
||||
elseif m > 0 then
|
||||
return string.format("%dm"..sep.."%." .. tostring(decimals) .. "fs", m, s)
|
||||
else
|
||||
return string.format("%." .. tostring(decimals) .. "fs", s)
|
||||
end
|
||||
end
|
||||
|
||||
-- Writes text on OSD and console
|
||||
function log_info(txt, timeout)
|
||||
timeout = timeout or 1.5
|
||||
msg.info(txt)
|
||||
mp.osd_message(txt, timeout)
|
||||
end
|
||||
|
||||
-- Join table items, ala ({"a", "b", "c"}, "=", "-", ", ") => "=a-, =b-, =c-"
|
||||
function join_table(source, before, after, sep)
|
||||
before = before or ""
|
||||
after = after or ""
|
||||
sep = sep or ", "
|
||||
local result = ""
|
||||
for i, v in pairs(source) do
|
||||
if not isempty(v) then
|
||||
local part = before .. v .. after
|
||||
if i == 1 then
|
||||
result = part
|
||||
else
|
||||
result = result .. sep .. part
|
||||
end
|
||||
end
|
||||
end
|
||||
return result
|
||||
end
|
||||
|
||||
function wrap(s, char)
|
||||
char = char or "'"
|
||||
return char .. s .. char
|
||||
end
|
||||
-- Wraps given string into 'string' and escapes any 's in it
|
||||
function escape_and_wrap(s, char, replacement)
|
||||
char = char or "'"
|
||||
replacement = replacement or "\\" .. char
|
||||
return wrap(string.gsub(s, char, replacement), char)
|
||||
end
|
||||
-- Escapes single quotes in a string and wraps the input in single quotes
|
||||
function escape_single_bash(s)
|
||||
return escape_and_wrap(s, "'", "'\\''")
|
||||
end
|
||||
|
||||
-- Returns (a .. b) if b is not empty or nil
|
||||
function joined_or_nil(a, b)
|
||||
return not isempty(b) and (a .. b) or nil
|
||||
end
|
||||
|
||||
-- Put items from one table into another
|
||||
function extend_table(target, source)
|
||||
for i, v in pairs(source) do
|
||||
table.insert(target, v)
|
||||
end
|
||||
end
|
||||
|
||||
-- Creates a handle and filename for a temporary random file (in current directory)
|
||||
function create_temporary_file(base, mode, suffix)
|
||||
local handle, filename
|
||||
suffix = suffix or ""
|
||||
while true do
|
||||
filename = base .. tostring(math.random(1, 5000)) .. suffix
|
||||
handle = io.open(filename, "r")
|
||||
if not handle then
|
||||
handle = io.open(filename, mode)
|
||||
break
|
||||
end
|
||||
io.close(handle)
|
||||
end
|
||||
return handle, filename
|
||||
end
|
||||
|
||||
|
||||
function get_processor_count()
|
||||
local proc_count
|
||||
|
||||
if ON_WINDOWS then
|
||||
proc_count = tonumber(os.getenv("NUMBER_OF_PROCESSORS"))
|
||||
else
|
||||
local cpuinfo_handle = io.open("/proc/cpuinfo")
|
||||
if cpuinfo_handle ~= nil then
|
||||
local cpuinfo_contents = cpuinfo_handle:read("*a")
|
||||
local _, replace_count = cpuinfo_contents:gsub('processor', '')
|
||||
proc_count = replace_count
|
||||
end
|
||||
end
|
||||
|
||||
if proc_count and proc_count > 0 then
|
||||
return proc_count
|
||||
else
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
function substitute_values(string, values)
|
||||
local substitutor = function(match)
|
||||
if match == "%" then
|
||||
return "%"
|
||||
else
|
||||
-- nil is discarded by gsub
|
||||
return values[match]
|
||||
end
|
||||
end
|
||||
|
||||
local substituted = string:gsub('%%(.)', substitutor)
|
||||
return substituted
|
||||
end
|
||||
|
||||
-- ASS HELPERS --
|
||||
function round_rect_top( ass, x0, y0, x1, y1, r )
|
||||
local c = 0.551915024494 * r -- circle approximation
|
||||
ass:move_to(x0 + r, y0)
|
||||
ass:line_to(x1 - r, y0) -- top line
|
||||
if r > 0 then
|
||||
ass:bezier_curve(x1 - r + c, y0, x1, y0 + r - c, x1, y0 + r) -- top right corner
|
||||
end
|
||||
ass:line_to(x1, y1) -- right line
|
||||
ass:line_to(x0, y1) -- bottom line
|
||||
ass:line_to(x0, y0 + r) -- left line
|
||||
if r > 0 then
|
||||
ass:bezier_curve(x0, y0 + r - c, x0 + r - c, y0, x0 + r, y0) -- top left corner
|
||||
end
|
||||
end
|
||||
|
||||
function round_rect(ass, x0, y0, x1, y1, rtl, rtr, rbr, rbl)
|
||||
local c = 0.551915024494
|
||||
ass:move_to(x0 + rtl, y0)
|
||||
ass:line_to(x1 - rtr, y0) -- top line
|
||||
if rtr > 0 then
|
||||
ass:bezier_curve(x1 - rtr + rtr*c, y0, x1, y0 + rtr - rtr*c, x1, y0 + rtr) -- top right corner
|
||||
end
|
||||
ass:line_to(x1, y1 - rbr) -- right line
|
||||
if rbr > 0 then
|
||||
ass:bezier_curve(x1, y1 - rbr + rbr*c, x1 - rbr + rbr*c, y1, x1 - rbr, y1) -- bottom right corner
|
||||
end
|
||||
ass:line_to(x0 + rbl, y1) -- bottom line
|
||||
if rbl > 0 then
|
||||
ass:bezier_curve(x0 + rbl - rbl*c, y1, x0, y1 - rbl + rbl*c, x0, y1 - rbl) -- bottom left corner
|
||||
end
|
||||
ass:line_to(x0, y0 + rtl) -- left line
|
||||
if rtl > 0 then
|
||||
ass:bezier_curve(x0, y0 + rtl - rtl*c, x0 + rtl - rtl*c, y0, x0 + rtl, y0) -- top left corner
|
||||
end
|
||||
end
|
||||
local SCRIPT_NAME = "mpv_thumbnail_script"
|
||||
|
||||
local default_cache_base = ON_WINDOWS and os.getenv("TEMP") or "/tmp/"
|
||||
|
||||
local thumbnailer_options = {
|
||||
-- The thumbnail directory
|
||||
cache_directory = join_paths(default_cache_base, "mpv_thumbs_cache"),
|
||||
|
||||
------------------------
|
||||
-- Generation options --
|
||||
------------------------
|
||||
|
||||
-- Automatically generate the thumbnails on video load, without a keypress
|
||||
autogenerate = true,
|
||||
|
||||
-- Only automatically thumbnail videos shorter than this (seconds)
|
||||
autogenerate_max_duration = 3600, -- 1 hour
|
||||
|
||||
-- SHA1-sum filenames over this length
|
||||
-- It's nice to know what files the thumbnails are (hence directory names)
|
||||
-- but long URLs may approach filesystem limits.
|
||||
hash_filename_length = 128,
|
||||
|
||||
-- Use mpv to generate thumbnail even if ffmpeg is found in PATH
|
||||
-- ffmpeg does not handle ordered chapters (MKVs which rely on other MKVs)!
|
||||
-- mpv is a bit slower, but has better support overall (eg. subtitles in the previews)
|
||||
prefer_mpv = true,
|
||||
|
||||
-- Explicitly disable subtitles on the mpv sub-calls
|
||||
mpv_no_sub = false,
|
||||
-- Add a "--no-config" to the mpv sub-call arguments
|
||||
mpv_no_config = false,
|
||||
-- Add a "--profile=<mpv_profile>" to the mpv sub-call arguments
|
||||
-- Use "" to disable
|
||||
mpv_profile = "",
|
||||
-- Output debug logs to <thumbnail_path>.log, ala <cache_directory>/<video_filename>/000000.bgra.log
|
||||
-- The logs are removed after successful encodes, unless you set mpv_keep_logs below
|
||||
mpv_logs = true,
|
||||
-- Keep all mpv logs, even the succesfull ones
|
||||
mpv_keep_logs = false,
|
||||
|
||||
-- Disable the built-in keybind ("T") to add your own
|
||||
disable_keybinds = false,
|
||||
|
||||
---------------------
|
||||
-- Display options --
|
||||
---------------------
|
||||
|
||||
-- Move the thumbnail up or down
|
||||
-- For example:
|
||||
-- topbar/bottombar: 24
|
||||
-- rest: 0
|
||||
vertical_offset = 24,
|
||||
|
||||
-- Adjust background padding
|
||||
-- Examples:
|
||||
-- topbar: 0, 10, 10, 10
|
||||
-- bottombar: 10, 0, 10, 10
|
||||
-- slimbox/box: 10, 10, 10, 10
|
||||
pad_top = 10,
|
||||
pad_bot = 0,
|
||||
pad_left = 10,
|
||||
pad_right = 10,
|
||||
|
||||
-- If true, pad values are screen-pixels. If false, video-pixels.
|
||||
pad_in_screenspace = true,
|
||||
-- Calculate pad into the offset
|
||||
offset_by_pad = true,
|
||||
|
||||
-- Background color in BBGGRR
|
||||
background_color = "000000",
|
||||
-- Alpha: 0 - fully opaque, 255 - transparent
|
||||
background_alpha = 80,
|
||||
|
||||
-- Keep thumbnail on the screen near left or right side
|
||||
constrain_to_screen = true,
|
||||
|
||||
-- Do not display the thumbnailing progress
|
||||
hide_progress = false,
|
||||
|
||||
-----------------------
|
||||
-- Thumbnail options --
|
||||
-----------------------
|
||||
|
||||
-- The maximum dimensions of the thumbnails (pixels)
|
||||
thumbnail_width = 200,
|
||||
thumbnail_height = 200,
|
||||
|
||||
-- The thumbnail count target
|
||||
-- (This will result in a thumbnail every ~10 seconds for a 25 minute video)
|
||||
thumbnail_count = 150,
|
||||
|
||||
-- The above target count will be adjusted by the minimum and
|
||||
-- maximum time difference between thumbnails.
|
||||
-- The thumbnail_count will be used to calculate a target separation,
|
||||
-- and min/max_delta will be used to constrict it.
|
||||
|
||||
-- In other words, thumbnails will be:
|
||||
-- at least min_delta seconds apart (limiting the amount)
|
||||
-- at most max_delta seconds apart (raising the amount if needed)
|
||||
min_delta = 5,
|
||||
-- 120 seconds aka 2 minutes will add more thumbnails when the video is over 5 hours!
|
||||
max_delta = 90,
|
||||
|
||||
|
||||
-- Overrides for remote urls (you generally want less thumbnails!)
|
||||
-- Thumbnailing network paths will be done with mpv
|
||||
|
||||
-- Allow thumbnailing network paths (naive check for "://")
|
||||
thumbnail_network = false,
|
||||
-- Override thumbnail count, min/max delta
|
||||
remote_thumbnail_count = 60,
|
||||
remote_min_delta = 15,
|
||||
remote_max_delta = 120,
|
||||
|
||||
-- Try to grab the raw stream and disable ytdl for the mpv subcalls
|
||||
-- Much faster than passing the url to ytdl again, but may cause problems with some sites
|
||||
remote_direct_stream = true,
|
||||
}
|
||||
|
||||
read_options(thumbnailer_options, SCRIPT_NAME)
|
||||
function skip_nil(tbl)
|
||||
local n = {}
|
||||
for k, v in pairs(tbl) do
|
||||
table.insert(n, v)
|
||||
end
|
||||
return n
|
||||
end
|
||||
|
||||
function create_thumbnail_mpv(file_path, timestamp, size, output_path, options)
|
||||
options = options or {}
|
||||
|
||||
local ytdl_disabled = not options.enable_ytdl and (mp.get_property_native("ytdl") == false
|
||||
or thumbnailer_options.remote_direct_stream)
|
||||
|
||||
local header_fields_arg = nil
|
||||
local header_fields = mp.get_property_native("http-header-fields")
|
||||
if #header_fields > 0 then
|
||||
-- We can't escape the headers, mpv won't parse "--http-header-fields='Name: value'" properly
|
||||
header_fields_arg = "--http-header-fields=" .. table.concat(header_fields, ",")
|
||||
end
|
||||
|
||||
local profile_arg = nil
|
||||
if thumbnailer_options.mpv_profile ~= "" then
|
||||
profile_arg = "--profile=" .. thumbnailer_options.mpv_profile
|
||||
end
|
||||
|
||||
local log_arg = "--log-file=" .. output_path .. ".log"
|
||||
|
||||
local mpv_command = skip_nil({
|
||||
"mpv",
|
||||
-- Hide console output
|
||||
"--msg-level=all=no",
|
||||
|
||||
-- Disable ytdl
|
||||
(ytdl_disabled and "--no-ytdl" or nil),
|
||||
-- Pass HTTP headers from current instance
|
||||
header_fields_arg,
|
||||
-- Pass User-Agent and Referer - should do no harm even with ytdl active
|
||||
"--user-agent=" .. mp.get_property_native("user-agent"),
|
||||
"--referrer=" .. mp.get_property_native("referrer"),
|
||||
-- Disable hardware decoding
|
||||
"--hwdec=no",
|
||||
|
||||
-- Insert --no-config, --profile=... and --log-file if enabled
|
||||
(thumbnailer_options.mpv_no_config and "--no-config" or nil),
|
||||
profile_arg,
|
||||
(thumbnailer_options.mpv_logs and log_arg or nil),
|
||||
|
||||
file_path,
|
||||
|
||||
"--start=" .. tostring(timestamp),
|
||||
"--frames=1",
|
||||
"--hr-seek=yes",
|
||||
"--no-audio",
|
||||
-- Optionally disable subtitles
|
||||
(thumbnailer_options.mpv_no_sub and "--no-sub" or nil),
|
||||
|
||||
("--vf=scale=%d:%d"):format(size.w, size.h),
|
||||
"--vf-add=format=bgra",
|
||||
"--of=rawvideo",
|
||||
"--ovc=rawvideo",
|
||||
"--o=" .. output_path
|
||||
})
|
||||
return utils.subprocess({args=mpv_command})
|
||||
end
|
||||
|
||||
|
||||
function create_thumbnail_ffmpeg(file_path, timestamp, size, output_path)
|
||||
local ffmpeg_command = {
|
||||
"ffmpeg",
|
||||
"-loglevel", "quiet",
|
||||
"-noaccurate_seek",
|
||||
"-ss", format_time(timestamp, ":"),
|
||||
"-i", file_path,
|
||||
|
||||
"-frames:v", "1",
|
||||
"-an",
|
||||
|
||||
"-vf", ("scale=%d:%d"):format(size.w, size.h),
|
||||
"-c:v", "rawvideo",
|
||||
"-pix_fmt", "bgra",
|
||||
"-f", "rawvideo",
|
||||
|
||||
"-y", output_path
|
||||
}
|
||||
return utils.subprocess({args=ffmpeg_command})
|
||||
end
|
||||
|
||||
|
||||
function check_output(ret, output_path, is_mpv)
|
||||
local log_path = output_path .. ".log"
|
||||
local success = true
|
||||
|
||||
if ret.killed_by_us then
|
||||
return nil
|
||||
else
|
||||
if ret.error or ret.status ~= 0 then
|
||||
msg.error("Thumbnailing command failed!")
|
||||
msg.error("mpv process error:", ret.error)
|
||||
msg.error("Process stdout:", ret.stdout)
|
||||
if is_mpv then
|
||||
msg.error("Debug log:", log_path)
|
||||
end
|
||||
|
||||
success = false
|
||||
end
|
||||
|
||||
if not file_exists(output_path) then
|
||||
msg.error("Output file missing!", output_path)
|
||||
success = false
|
||||
end
|
||||
end
|
||||
|
||||
if is_mpv and not thumbnailer_options.mpv_keep_logs then
|
||||
-- Remove successful debug logs
|
||||
if success and file_exists(log_path) then
|
||||
os.remove(log_path)
|
||||
end
|
||||
end
|
||||
|
||||
return success
|
||||
end
|
||||
|
||||
|
||||
function do_worker_job(state_json_string, frames_json_string)
|
||||
msg.debug("Handling given job")
|
||||
local thumb_state, err = utils.parse_json(state_json_string)
|
||||
if err then
|
||||
msg.error("Failed to parse state JSON")
|
||||
return
|
||||
end
|
||||
|
||||
local thumbnail_indexes, err = utils.parse_json(frames_json_string)
|
||||
if err then
|
||||
msg.error("Failed to parse thumbnail frame indexes")
|
||||
return
|
||||
end
|
||||
|
||||
local thumbnail_func = create_thumbnail_mpv
|
||||
if not thumbnailer_options.prefer_mpv then
|
||||
if ExecutableFinder:get_executable_path("ffmpeg") then
|
||||
thumbnail_func = create_thumbnail_ffmpeg
|
||||
else
|
||||
msg.warn("Could not find ffmpeg in PATH! Falling back on mpv.")
|
||||
end
|
||||
end
|
||||
|
||||
local file_duration = mp.get_property_native("duration")
|
||||
local file_path = thumb_state.worker_input_path
|
||||
|
||||
if thumb_state.is_remote then
|
||||
if (thumbnail_func == create_thumbnail_ffmpeg) then
|
||||
msg.warn("Thumbnailing remote path, falling back on mpv.")
|
||||
end
|
||||
thumbnail_func = create_thumbnail_mpv
|
||||
end
|
||||
|
||||
local generate_thumbnail_for_index = function(thumbnail_index)
|
||||
-- Given a 1-based thumbnail index, generate a thumbnail for it based on the thumbnailer state
|
||||
local thumb_idx = thumbnail_index - 1
|
||||
msg.debug("Starting work on thumbnail", thumb_idx)
|
||||
|
||||
local thumbnail_path = thumb_state.thumbnail_template:format(thumb_idx)
|
||||
-- Grab the "middle" of the thumbnail duration instead of the very start, and leave some margin in the end
|
||||
local timestamp = math.min(file_duration - 0.25, (thumb_idx + 0.5) * thumb_state.thumbnail_delta)
|
||||
|
||||
mp.commandv("script-message", "mpv_thumbnail_script-progress", tostring(thumbnail_index))
|
||||
|
||||
-- The expected size (raw BGRA image)
|
||||
local thumbnail_raw_size = (thumb_state.thumbnail_size.w * thumb_state.thumbnail_size.h * 4)
|
||||
|
||||
local need_thumbnail_generation = false
|
||||
|
||||
-- Check if the thumbnail already exists and is the correct size
|
||||
local thumbnail_file = io.open(thumbnail_path, "rb")
|
||||
if thumbnail_file == nil then
|
||||
need_thumbnail_generation = true
|
||||
else
|
||||
local existing_thumbnail_filesize = thumbnail_file:seek("end")
|
||||
if existing_thumbnail_filesize ~= thumbnail_raw_size then
|
||||
-- Size doesn't match, so (re)generate
|
||||
msg.warn("Thumbnail", thumb_idx, "did not match expected size, regenerating")
|
||||
need_thumbnail_generation = true
|
||||
end
|
||||
thumbnail_file:close()
|
||||
end
|
||||
|
||||
if need_thumbnail_generation then
|
||||
local ret = thumbnail_func(file_path, timestamp, thumb_state.thumbnail_size, thumbnail_path, thumb_state.worker_extra)
|
||||
local success = check_output(ret, thumbnail_path, thumbnail_func == create_thumbnail_mpv)
|
||||
|
||||
if success == nil then
|
||||
-- Killed by us, changing files, ignore
|
||||
msg.debug("Changing files, subprocess killed")
|
||||
return true
|
||||
elseif not success then
|
||||
-- Real failure
|
||||
mp.osd_message("Thumbnailing failed, check console for details", 3.5)
|
||||
return true
|
||||
end
|
||||
else
|
||||
msg.debug("Thumbnail", thumb_idx, "already done!")
|
||||
end
|
||||
|
||||
-- Verify thumbnail size
|
||||
-- Sometimes ffmpeg will output an empty file when seeking to a "bad" section (usually the end)
|
||||
thumbnail_file = io.open(thumbnail_path, "rb")
|
||||
|
||||
-- Bail if we can't read the file (it should really exist by now, we checked this in check_output!)
|
||||
if thumbnail_file == nil then
|
||||
msg.error("Thumbnail suddenly disappeared!")
|
||||
return true
|
||||
end
|
||||
|
||||
-- Check the size of the generated file
|
||||
local thumbnail_file_size = thumbnail_file:seek("end")
|
||||
thumbnail_file:close()
|
||||
|
||||
-- Check if the file is big enough
|
||||
local missing_bytes = math.max(0, thumbnail_raw_size - thumbnail_file_size)
|
||||
if missing_bytes > 0 then
|
||||
msg.warn(("Thumbnail missing %d bytes (expected %d, had %d), padding %s"):format(
|
||||
missing_bytes, thumbnail_raw_size, thumbnail_file_size, thumbnail_path
|
||||
))
|
||||
-- Pad the file if it's missing content (eg. ffmpeg seek to file end)
|
||||
thumbnail_file = io.open(thumbnail_path, "ab")
|
||||
thumbnail_file:write(string.rep(string.char(0), missing_bytes))
|
||||
thumbnail_file:close()
|
||||
end
|
||||
|
||||
msg.debug("Finished work on thumbnail", thumb_idx)
|
||||
mp.commandv("script-message", "mpv_thumbnail_script-ready", tostring(thumbnail_index), thumbnail_path)
|
||||
end
|
||||
|
||||
msg.debug(("Generating %d thumbnails @ %dx%d for %q"):format(
|
||||
#thumbnail_indexes,
|
||||
thumb_state.thumbnail_size.w,
|
||||
thumb_state.thumbnail_size.h,
|
||||
file_path))
|
||||
|
||||
for i, thumbnail_index in ipairs(thumbnail_indexes) do
|
||||
local bail = generate_thumbnail_for_index(thumbnail_index)
|
||||
if bail then return end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
-- Set up listeners and keybinds
|
||||
|
||||
-- Job listener
|
||||
mp.register_script_message("mpv_thumbnail_script-job", do_worker_job)
|
||||
|
||||
|
||||
-- Register this worker with the master script
|
||||
local register_timer = nil
|
||||
local register_timeout = mp.get_time() + 1.5
|
||||
|
||||
local register_function = function()
|
||||
if mp.get_time() > register_timeout and register_timer then
|
||||
msg.error("Thumbnail worker registering timed out")
|
||||
register_timer:stop()
|
||||
else
|
||||
msg.debug("Announcing self to master...")
|
||||
mp.commandv("script-message", "mpv_thumbnail_script-worker", mp.get_script_name())
|
||||
end
|
||||
end
|
||||
|
||||
register_timer = mp.add_periodic_timer(0.1, register_function)
|
||||
|
||||
mp.register_script_message("mpv_thumbnail_script-slaved", function()
|
||||
msg.debug("Successfully registered with master")
|
||||
register_timer:stop()
|
||||
end)
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,7 @@
|
||||
local settings = {
|
||||
|
||||
-- #### FUNCTIONALITY SETTINGS
|
||||
|
||||
--navigation keybindings force override only while playlist is visible
|
||||
--if "no" then you can display the playlist by any of the navigation keys
|
||||
dynamic_binds = true,
|
||||
@@ -111,12 +114,11 @@ local settings = {
|
||||
save_playlist_on_file_end = false,
|
||||
|
||||
|
||||
--show file title every time a new file is loaded
|
||||
show_title_on_file_load = false,
|
||||
--show playlist every time a new file is loaded
|
||||
show_playlist_on_file_load = false,
|
||||
--close playlist when selecting file to play
|
||||
close_playlist_on_playfile = false,
|
||||
--show playlist or filename every time a new file is loaded
|
||||
--2 shows playlist, 1 shows current file(filename strip applied) as osd text, 0 shows nothing
|
||||
--instead of using this you can also call script-message playlistmanager show playlist/filename
|
||||
--ex. KEY playlist-next ; script-message playlistmanager show playlist
|
||||
show_playlist_on_fileload = 0,
|
||||
|
||||
--sync cursor when file is loaded from outside reasons(file-ending, playlist-next shortcut etc.)
|
||||
--has the sideeffect of moving cursor if file happens to change when navigating
|
||||
@@ -126,6 +128,8 @@ local settings = {
|
||||
--allow the playlist cursor to loop from end to start and vice versa
|
||||
loop_cursor = true,
|
||||
|
||||
--youtube-dl executable for title resolving if enabled, probably "youtube-dl" or "yt-dlp", can be absolute path
|
||||
youtube_dl_executable = "youtube-dl",
|
||||
|
||||
-- allow playlistmanager to write watch later config when navigating between files
|
||||
allow_write_watch_later_config = true,
|
||||
@@ -134,12 +138,11 @@ local settings = {
|
||||
reset_cursor_on_close = true,
|
||||
reset_cursor_on_open = true,
|
||||
|
||||
--#### VISUAL SETTINGS
|
||||
|
||||
--prefer to display titles for following files: "all", "url", "none". Sorting still uses filename.
|
||||
prefer_titles = "url",
|
||||
|
||||
--youtube-dl executable for title resolving if enabled, probably "youtube-dl" or "yt-dlp", can be absolute path
|
||||
youtube_dl_executable = "yt-dlp",
|
||||
|
||||
--call youtube-dl to resolve the titles of urls in the playlist
|
||||
resolve_url_titles = false,
|
||||
|
||||
@@ -158,23 +161,23 @@ local settings = {
|
||||
-- when peeking at playlist, show playlist at the very least for display timeout
|
||||
peek_respect_display_timeout = false,
|
||||
|
||||
-- the maximum amount of lines playlist will render. -1 will automatically calculate lines.
|
||||
showamount = -1,
|
||||
-- the maximum amount of lines playlist will render. Optimal value depends on font/video size etc.
|
||||
showamount = 9,
|
||||
|
||||
--font size scales by window, if false requires larger font and padding sizes
|
||||
scale_playlist_by_window=true,
|
||||
--playlist ass style overrides inside curly brackets, \keyvalue is one field, extra \ for escape in lua
|
||||
--example {\\q2\\an7\\fnUbuntu\\fs10\\b0\\bord1} equals: line-wrap=no, align=top left, font=Ubuntu, size=10, bold=no, border=1
|
||||
--example {\\fnUbuntu\\fs10\\b0\\bord1} equals: font=Ubuntu, size=10, bold=no, border=1
|
||||
--read http://docs.aegisub.org/3.2/ASS_Tags/ for reference of tags
|
||||
--undeclared tags will use default osd settings
|
||||
--these styles will be used for the whole playlist
|
||||
--\\q2 style is recommended since filename wrapping may lead to unexpected rendering
|
||||
--\\an7 style is recommended to align to top left otherwise, osd-align-x/y is respected
|
||||
style_ass_tags = "{\\q2\\an7}",
|
||||
--paddings for left right and top bottom
|
||||
text_padding_x = 30,
|
||||
text_padding_y = 60,
|
||||
style_ass_tags = "{}",
|
||||
--paddings from top left corner
|
||||
text_padding_x = 10,
|
||||
text_padding_y = 30,
|
||||
|
||||
--screen dim when menu is open 0.0 - 1.0 (0 is no dim, 1 is black)
|
||||
curtain_opacity=0.0,
|
||||
curtain_opacity=0,
|
||||
|
||||
--set title of window with stripped name
|
||||
set_title_stripped = false,
|
||||
@@ -222,17 +225,6 @@ local utils = require("mp.utils")
|
||||
local msg = require("mp.msg")
|
||||
local assdraw = require("mp.assdraw")
|
||||
|
||||
local alignment_table = {
|
||||
[1] = { ["x"] = "left", ["y"] = "bottom" },
|
||||
[2] = { ["x"] = "center", ["y"] = "bottom" },
|
||||
[3] = { ["x"] = "right", ["y"] = "bottom" },
|
||||
[4] = { ["x"] = "left", ["y"] = "center" },
|
||||
[5] = { ["x"] = "center", ["y"] = "center" },
|
||||
[6] = { ["x"] = "right", ["y"] = "center" },
|
||||
[7] = { ["x"] = "left", ["y"] = "top" },
|
||||
[8] = { ["x"] = "center", ["y"] = "top" },
|
||||
[9] = { ["x"] = "right", ["y"] = "top" },
|
||||
}
|
||||
|
||||
--check os
|
||||
if settings.system=="auto" then
|
||||
@@ -244,47 +236,7 @@ if settings.system=="auto" then
|
||||
end
|
||||
end
|
||||
|
||||
-- auto calculate showamount
|
||||
if settings.showamount == -1 then
|
||||
-- same as draw_playlist() height
|
||||
local h = 720
|
||||
|
||||
local playlist_h = h
|
||||
-- both top and bottom with same padding
|
||||
playlist_h = playlist_h - settings.text_padding_y * 2
|
||||
|
||||
-- osd-font-size is based on 720p height
|
||||
-- see https://mpv.io/manual/stable/#options-osd-font-size
|
||||
-- details in https://mpv.io/manual/stable/#options-sub-font-size
|
||||
-- draw_playlist() is based on 720p, need some conversion
|
||||
local fs = mp.get_property_native('osd-font-size') * h / 720
|
||||
-- get the ass font size
|
||||
if settings.style_ass_tags ~= nil then
|
||||
local ass_fs_tag = settings.style_ass_tags:match('\\fs%d+')
|
||||
if ass_fs_tag ~= nil then
|
||||
fs = tonumber(ass_fs_tag:match('%d+'))
|
||||
end
|
||||
end
|
||||
|
||||
settings.showamount = math.floor(playlist_h / fs)
|
||||
|
||||
-- exclude the header line
|
||||
if settings.playlist_header ~= "" then
|
||||
settings.showamount = settings.showamount - 1
|
||||
-- probably some newlines (%N or \N) in the header
|
||||
for _ in settings.playlist_header:gmatch('%%N') do
|
||||
settings.showamount = settings.showamount - 1
|
||||
end
|
||||
for _ in settings.playlist_header:gmatch('\\N') do
|
||||
settings.showamount = settings.showamount - 1
|
||||
end
|
||||
end
|
||||
|
||||
msg.info('auto showamount: ' .. settings.showamount)
|
||||
end
|
||||
|
||||
--global variables
|
||||
local playlist_overlay = mp.create_osd_overlay("ass-events")
|
||||
local playlist_visible = false
|
||||
local strippedname = nil
|
||||
local path = nil
|
||||
@@ -300,13 +252,6 @@ local requested_titles = {}
|
||||
|
||||
local filetype_lookup = {}
|
||||
|
||||
function refresh_UI()
|
||||
if not playlist_visible then return end
|
||||
refresh_globals()
|
||||
if plen == 0 then return end
|
||||
draw_playlist()
|
||||
end
|
||||
|
||||
function update_opts(changelog)
|
||||
msg.verbose('updating options')
|
||||
|
||||
@@ -343,56 +288,16 @@ function update_opts(changelog)
|
||||
keybindstimer:kill()
|
||||
end
|
||||
|
||||
refresh_UI()
|
||||
if playlist_visible then showplaylist() end
|
||||
end
|
||||
|
||||
update_opts({filename_replace = true, loadfiles_filetypes = true})
|
||||
|
||||
----- winapi start -----
|
||||
-- in windows system, we can use the sorting function provided by the win32 API
|
||||
-- see https://learn.microsoft.com/en-us/windows/win32/api/shlwapi/nf-shlwapi-strcmplogicalw
|
||||
local winapisort = nil
|
||||
if settings.system == "windows" then
|
||||
-- ffiok is false usually means the mpv builds without luajit
|
||||
local ffiok, ffi = pcall(require, "ffi")
|
||||
if ffiok then
|
||||
ffi.cdef[[
|
||||
int MultiByteToWideChar(unsigned int CodePage, unsigned long dwFlags, const char *lpMultiByteStr, int cbMultiByte, wchar_t *lpWideCharStr, int cchWideChar);
|
||||
int StrCmpLogicalW(const wchar_t * psz1, const wchar_t * psz2);
|
||||
]]
|
||||
|
||||
local shlwapi = ffi.load("shlwapi.dll")
|
||||
|
||||
function MultiByteToWideChar(MultiByteStr)
|
||||
local UTF8_CODEPAGE = 65001
|
||||
if MultiByteStr then
|
||||
local utf16_len = ffi.C.MultiByteToWideChar(UTF8_CODEPAGE, 0, MultiByteStr, -1, nil, 0)
|
||||
if utf16_len > 0 then
|
||||
local utf16_str = ffi.new("wchar_t[?]", utf16_len)
|
||||
if ffi.C.MultiByteToWideChar(UTF8_CODEPAGE, 0, MultiByteStr, -1, utf16_str, utf16_len) > 0 then
|
||||
return utf16_str
|
||||
end
|
||||
end
|
||||
end
|
||||
return ""
|
||||
end
|
||||
|
||||
winapisort = function (a, b)
|
||||
return shlwapi.StrCmpLogicalW(MultiByteToWideChar(a), MultiByteToWideChar(b)) < 0
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
----- winapi end -----
|
||||
|
||||
local sort_modes = {
|
||||
{
|
||||
id="name-asc",
|
||||
title="name ascending",
|
||||
sort_fn=function (a, b, playlist)
|
||||
if winapisort ~= nil then
|
||||
return winapisort(playlist[a].string, playlist[b].string)
|
||||
end
|
||||
return alphanumsort(playlist[a].string, playlist[b].string)
|
||||
end,
|
||||
},
|
||||
@@ -400,9 +305,6 @@ local sort_modes = {
|
||||
id="name-desc",
|
||||
title="name descending",
|
||||
sort_fn=function (a, b, playlist)
|
||||
if winapisort ~= nil then
|
||||
return winapisort(playlist[b].string, playlist[a].string)
|
||||
end
|
||||
return alphanumsort(playlist[b].string, playlist[a].string)
|
||||
end,
|
||||
},
|
||||
@@ -449,9 +351,6 @@ end
|
||||
|
||||
function on_file_loaded()
|
||||
refresh_globals()
|
||||
if settings.sync_cursor_on_load then cursor=pos end
|
||||
refresh_UI() -- refresh only after moving cursor
|
||||
|
||||
filename = mp.get_property("filename")
|
||||
path = mp.get_property('path')
|
||||
local media_title = mp.get_property("media-title")
|
||||
@@ -459,12 +358,17 @@ function on_file_loaded()
|
||||
title_table[path] = media_title
|
||||
end
|
||||
|
||||
strippedname = stripfilename(mp.get_property('media-title'))
|
||||
if settings.show_title_on_file_load then
|
||||
mp.commandv('show-text', strippedname)
|
||||
if settings.sync_cursor_on_load then
|
||||
cursor=pos
|
||||
--refresh playlist if cursor moved
|
||||
if playlist_visible then draw_playlist() end
|
||||
end
|
||||
if settings.show_playlist_on_file_load then
|
||||
|
||||
strippedname = stripfilename(mp.get_property('media-title'))
|
||||
if settings.show_playlist_on_fileload == 2 then
|
||||
showplaylist()
|
||||
elseif settings.show_playlist_on_fileload == 1 then
|
||||
mp.commandv('show-text', strippedname)
|
||||
end
|
||||
if settings.set_title_stripped then
|
||||
mp.set_property("title", settings.title_prefix..strippedname..settings.title_suffix)
|
||||
@@ -499,6 +403,7 @@ function on_end_file()
|
||||
path = nil
|
||||
directory = nil
|
||||
filename = nil
|
||||
if playlist_visible then showplaylist() end
|
||||
end
|
||||
|
||||
function refresh_globals()
|
||||
@@ -522,28 +427,6 @@ local filename_replace_functions = {
|
||||
hex_to_char = function(x) return string.char(tonumber(x, 16)) end
|
||||
}
|
||||
|
||||
-- from http://lua-users.org/wiki/LuaUnicode
|
||||
local UTF8_PATTERN = '[%z\1-\127\194-\244][\128-\191]*'
|
||||
|
||||
-- return a substring based on utf8 characters
|
||||
-- like string.sub, but negative index is not supported
|
||||
local function utf8_sub(s, i, j)
|
||||
if i > j then
|
||||
return s
|
||||
end
|
||||
|
||||
local t = {}
|
||||
local idx = 1
|
||||
for char in s:gmatch(UTF8_PATTERN) do
|
||||
if i <= idx and idx <= j then
|
||||
local width = #char > 2 and 2 or 1
|
||||
idx = idx + width
|
||||
t[#t + 1] = char
|
||||
end
|
||||
end
|
||||
return table.concat(t)
|
||||
end
|
||||
|
||||
--strip a filename based on its extension or protocol according to rules in settings
|
||||
function stripfilename(pathfile, media_title)
|
||||
if pathfile == nil then return '' end
|
||||
@@ -563,9 +446,8 @@ function stripfilename(pathfile, media_title)
|
||||
end
|
||||
end
|
||||
end
|
||||
local tmp_clip = utf8_sub(tmp, 1, settings.slice_longfilenames_amount)
|
||||
if settings.slice_longfilenames and tmp ~= tmp_clip then
|
||||
tmp = tmp_clip .. "..."
|
||||
if settings.slice_longfilenames and tmp:len()>settings.slice_longfilenames_amount+5 then
|
||||
tmp = tmp:sub(1, settings.slice_longfilenames_amount).." ..."
|
||||
end
|
||||
return tmp
|
||||
end
|
||||
@@ -592,10 +474,17 @@ function get_name_from_index(i, notitle)
|
||||
local name = mp.get_property('playlist/'..i..'/filename')
|
||||
|
||||
local should_use_title = settings.prefer_titles == 'all' or is_protocol(name) and settings.prefer_titles == 'url'
|
||||
|
||||
--check if file has a media title stored
|
||||
if not title and should_use_title and title_table[name] then
|
||||
title = title_table[name]
|
||||
--check if file has a media title stored or as property
|
||||
if not title and should_use_title then
|
||||
local mtitle = mp.get_property('media-title')
|
||||
if i == pos and mp.get_property('filename') ~= mtitle then
|
||||
if not title_table[name] then
|
||||
title_table[name] = mtitle
|
||||
end
|
||||
title = mtitle
|
||||
elseif title_table[name] then
|
||||
title = title_table[name]
|
||||
end
|
||||
end
|
||||
|
||||
--if we have media title use a more conservative strip
|
||||
@@ -616,8 +505,6 @@ function parse_header(string)
|
||||
local esc_title = stripfilename(mp.get_property("media-title"), true):gsub("%%", "%%%%")
|
||||
local esc_file = stripfilename(mp.get_property("filename")):gsub("%%", "%%%%")
|
||||
return string:gsub("%%N", "\\N")
|
||||
-- add a blank character at the end of each '\N' to ensure that the height of the empty line is the same as the non empty line
|
||||
:gsub("\\N", "\\N ")
|
||||
:gsub("%%pos", mp.get_property_number("playlist-pos",0)+1)
|
||||
:gsub("%%plen", mp.get_property("playlist-count"))
|
||||
:gsub("%%cursor", cursor+1)
|
||||
@@ -664,21 +551,16 @@ function parse_filename_by_index(index)
|
||||
return parse_filename(template, get_name_from_index(index), index)
|
||||
end
|
||||
|
||||
function is_terminal_mode()
|
||||
local width, height, aspect_ratio = mp.get_osd_size()
|
||||
return width == 0 and height == 0 and aspect_ratio == 0
|
||||
end
|
||||
|
||||
function draw_playlist()
|
||||
refresh_globals()
|
||||
local ass = assdraw.ass_new()
|
||||
local terminaloutput = ""
|
||||
|
||||
local _, _, a = mp.get_osd_size()
|
||||
local h = 720
|
||||
local w = math.ceil(h * a)
|
||||
local h = 360
|
||||
local w = h * a
|
||||
|
||||
if settings.curtain_opacity ~= nil and settings.curtain_opacity ~= 0 and settings.curtain_opacity <= 1.0 then
|
||||
if settings.curtain_opacity ~= nil and settings.curtain_opacity ~= 0 and settings.curtain_opacity < 1.0 then
|
||||
-- curtain dim from https://github.com/christoph-heinrich/mpv-quality-menu/blob/501794bfbef468ee6a61e54fc8821fe5cd72c4ed/quality-menu.lua#L699-L707
|
||||
local alpha = 255 - math.ceil(255 * settings.curtain_opacity)
|
||||
ass.text = string.format('{\\pos(0,0)\\rDefault\\an7\\1c&H000000&\\alpha&H%X&}', alpha)
|
||||
@@ -690,53 +572,13 @@ function draw_playlist()
|
||||
|
||||
ass:append(settings.style_ass_tags)
|
||||
|
||||
-- add \clip style
|
||||
-- make both left and right follow text_padding_x
|
||||
-- both top and bottom follow text_padding_y
|
||||
local border_size = mp.get_property_number('osd-border-size')
|
||||
if settings.style_ass_tags ~= nil then
|
||||
local bord = tonumber(settings.style_ass_tags:match('\\bord(%d+%.?%d*)'))
|
||||
if bord ~= nil then border_size = bord end
|
||||
-- TODO: padding should work even on different osd alignments
|
||||
if mp.get_property("osd-align-x") == "left" and mp.get_property("osd-align-y") == "top" then
|
||||
ass:pos(settings.text_padding_x, settings.text_padding_y)
|
||||
end
|
||||
ass:append(string.format('{\\clip(%f,%f,%f,%f)}',
|
||||
settings.text_padding_x - border_size, settings.text_padding_y - border_size,
|
||||
w - 1 - settings.text_padding_x + border_size, h - 1 - settings.text_padding_y + border_size))
|
||||
|
||||
-- align from mpv.conf
|
||||
local align_x = mp.get_property("osd-align-x")
|
||||
local align_y = mp.get_property("osd-align-y")
|
||||
-- align from style_ass_tags
|
||||
if settings.style_ass_tags ~= nil then
|
||||
local an = tonumber(settings.style_ass_tags:match('\\an(%d)'))
|
||||
if an ~= nil and alignment_table[an] ~= nil then
|
||||
align_x = alignment_table[an]["x"]
|
||||
align_y = alignment_table[an]["y"]
|
||||
end
|
||||
end
|
||||
-- range of x [0, w-1]
|
||||
local pos_x
|
||||
if align_x == 'left' then
|
||||
pos_x = settings.text_padding_x
|
||||
elseif align_x == 'right' then
|
||||
pos_x = w - 1 - settings.text_padding_x
|
||||
else
|
||||
pos_x = math.floor((w - 1) / 2)
|
||||
end
|
||||
-- range of y [0, h-1]
|
||||
local pos_y
|
||||
if align_y == 'top' then
|
||||
pos_y = settings.text_padding_y
|
||||
elseif align_y == 'bottom' then
|
||||
pos_y = h - 1 - settings.text_padding_y
|
||||
else
|
||||
pos_y = math.floor((h - 1) / 2)
|
||||
end
|
||||
ass:pos(pos_x, pos_y)
|
||||
|
||||
if settings.playlist_header ~= "" then
|
||||
local header = parse_header(settings.playlist_header)
|
||||
ass:append(header.."\\N")
|
||||
terminaloutput = terminaloutput..header.."\n"
|
||||
ass:append(parse_header(settings.playlist_header).."\\N")
|
||||
end
|
||||
|
||||
-- (visible index, playlist index) pairs of playlist entries that should be rendered
|
||||
@@ -770,28 +612,16 @@ function draw_playlist()
|
||||
for display_index, playlist_index in pairs(visible_indices) do
|
||||
if display_index == 1 and playlist_index ~= 1 then
|
||||
ass:append(settings.playlist_sliced_prefix.."\\N")
|
||||
terminaloutput = terminaloutput..settings.playlist_sliced_prefix.."\n"
|
||||
elseif display_index == settings.showamount and playlist_index ~= plen then
|
||||
ass:append(settings.playlist_sliced_suffix)
|
||||
terminaloutput = terminaloutput..settings.playlist_sliced_suffix.."\n"
|
||||
else
|
||||
-- parse_filename_by_index expects 0 based index
|
||||
local fname = parse_filename_by_index(playlist_index - 1)
|
||||
ass:append(fname.."\\N")
|
||||
terminaloutput = terminaloutput..fname.."\n"
|
||||
ass:append(parse_filename_by_index(playlist_index - 1).."\\N")
|
||||
end
|
||||
end
|
||||
|
||||
if is_terminal_mode() then
|
||||
local timeout_setting = settings.playlist_display_timeout
|
||||
local timeout = timeout_setting == 0 and 2147483 or timeout_setting
|
||||
-- TODO: probably have to strip ass tags from terminal output
|
||||
-- would maybe be possible to use terminal color output instead
|
||||
mp.osd_message(terminaloutput, timeout)
|
||||
else
|
||||
playlist_overlay.data = ass.text
|
||||
playlist_overlay:update()
|
||||
end
|
||||
if settings.scale_playlist_by_window then w,h = 0, 0 end
|
||||
mp.set_osd_ass(w, h, ass.text)
|
||||
end
|
||||
|
||||
local peek_display_timer = nil
|
||||
@@ -863,7 +693,7 @@ function showplaylist(duration)
|
||||
draw_playlist()
|
||||
keybindstimer:kill()
|
||||
|
||||
local dur = tonumber(duration) or settings.playlist_display_timeout
|
||||
local dur = duration or settings.playlist_display_timeout
|
||||
if dur > 0 then
|
||||
keybindstimer = mp.add_periodic_timer(dur, remove_keybinds)
|
||||
end
|
||||
@@ -879,7 +709,7 @@ function showplaylist_non_interactive(duration)
|
||||
draw_playlist()
|
||||
keybindstimer:kill()
|
||||
|
||||
local dur = tonumber(duration) or settings.playlist_display_timeout
|
||||
local dur = duration or settings.playlist_display_timeout
|
||||
if dur > 0 then
|
||||
keybindstimer = mp.add_periodic_timer(dur, remove_keybinds)
|
||||
end
|
||||
@@ -947,44 +777,26 @@ function movedown()
|
||||
showplaylist()
|
||||
end
|
||||
|
||||
|
||||
function movepageup()
|
||||
refresh_globals()
|
||||
if plen == 0 or cursor == 0 then return end
|
||||
local offset = settings.showamount % 2 == 0 and 1 or 0
|
||||
local last_file_that_doesnt_scroll = math.ceil(settings.showamount / 2)
|
||||
local reverse_cursor = plen - cursor
|
||||
local files_to_jump = math.max(last_file_that_doesnt_scroll + offset - reverse_cursor, 0) + settings.showamount - 2
|
||||
local prev_cursor = cursor
|
||||
cursor = cursor - files_to_jump
|
||||
if cursor < last_file_that_doesnt_scroll then
|
||||
cursor = 0
|
||||
end
|
||||
if selection then
|
||||
mp.commandv("playlist-move", prev_cursor, cursor)
|
||||
end
|
||||
cursor = cursor - settings.showamount
|
||||
if cursor < 0 then cursor = 0 end
|
||||
if selection then mp.commandv("playlist-move", prev_cursor, cursor) end
|
||||
showplaylist()
|
||||
end
|
||||
|
||||
function movepagedown()
|
||||
refresh_globals()
|
||||
if plen == 0 or cursor == plen - 1 then return end
|
||||
local last_file_that_doesnt_scroll = math.ceil(settings.showamount / 2) - 1
|
||||
local files_to_jump = math.max(last_file_that_doesnt_scroll - cursor, 0) + settings.showamount - 2
|
||||
if plen == 0 or cursor == plen-1 then return end
|
||||
local prev_cursor = cursor
|
||||
cursor = cursor + files_to_jump
|
||||
|
||||
local cursor_on_last_page = plen - (settings.showamount - 3)
|
||||
if cursor > cursor_on_last_page then
|
||||
cursor = plen - 1
|
||||
end
|
||||
if selection then
|
||||
mp.commandv("playlist-move", prev_cursor, cursor + 1)
|
||||
end
|
||||
cursor = cursor + settings.showamount
|
||||
if cursor >= plen then cursor = plen-1 end
|
||||
if selection then mp.commandv("playlist-move", prev_cursor, cursor+1) end
|
||||
showplaylist()
|
||||
end
|
||||
|
||||
|
||||
function movebegin()
|
||||
refresh_globals()
|
||||
if plen == 0 or cursor == 0 then return end
|
||||
@@ -1011,37 +823,14 @@ function write_watch_later(force_write)
|
||||
end
|
||||
end
|
||||
|
||||
function playlist_next()
|
||||
write_watch_later(true)
|
||||
function playlist_next(force_write)
|
||||
write_watch_later(force_write)
|
||||
mp.commandv("playlist-next", "weak")
|
||||
if settings.close_playlist_on_playfile then
|
||||
remove_keybinds()
|
||||
end
|
||||
refresh_UI()
|
||||
end
|
||||
|
||||
function playlist_prev()
|
||||
write_watch_later(true)
|
||||
function playlist_prev(force_write)
|
||||
write_watch_later(force_write)
|
||||
mp.commandv("playlist-prev", "weak")
|
||||
if settings.close_playlist_on_playfile then
|
||||
remove_keybinds()
|
||||
end
|
||||
refresh_UI()
|
||||
end
|
||||
|
||||
function playlist_random()
|
||||
write_watch_later()
|
||||
refresh_globals()
|
||||
if plen < 2 then return end
|
||||
math.randomseed(os.time())
|
||||
local random = pos
|
||||
while random == pos do
|
||||
random = math.random(0, plen-1)
|
||||
end
|
||||
mp.set_property("playlist-pos", random)
|
||||
if settings.close_playlist_on_playfile then
|
||||
remove_keybinds()
|
||||
end
|
||||
end
|
||||
|
||||
function playfile()
|
||||
@@ -1059,10 +848,8 @@ function playfile()
|
||||
write_watch_later()
|
||||
mp.commandv("playlist-next", "weak")
|
||||
end
|
||||
if settings.close_playlist_on_playfile then
|
||||
if settings.show_playlist_on_fileload ~= 2 then
|
||||
remove_keybinds()
|
||||
elseif playlist_visible then
|
||||
showplaylist()
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1105,13 +892,8 @@ function playlist(force_dir)
|
||||
if force_dir then dir = force_dir end
|
||||
|
||||
local files = file_filter(utils.readdir(dir, "files"))
|
||||
if winapisort ~= nil then
|
||||
table.sort(files, winapisort)
|
||||
else
|
||||
table.sort(files, alphanumsort)
|
||||
end
|
||||
|
||||
|
||||
table.sort(files, alphanumsort)
|
||||
|
||||
if files == nil then
|
||||
msg.verbose("no files in directory")
|
||||
return
|
||||
@@ -1159,8 +941,7 @@ function playlist(force_dir)
|
||||
refresh_globals()
|
||||
if playlist_visible then
|
||||
showplaylist()
|
||||
end
|
||||
if settings.display_osd_feedback then
|
||||
elseif settings.display_osd_feedback then
|
||||
if c2 > 0 or c>0 then
|
||||
mp.osd_message("Added "..c + c2.." files to playlist")
|
||||
else
|
||||
@@ -1334,8 +1115,7 @@ function reverseplaylist()
|
||||
end
|
||||
if playlist_visible then
|
||||
showplaylist()
|
||||
end
|
||||
if settings.display_osd_feedback then
|
||||
elseif settings.display_osd_feedback then
|
||||
mp.osd_message("Playlist reversed")
|
||||
end
|
||||
end
|
||||
@@ -1361,8 +1141,7 @@ function shuffleplaylist()
|
||||
refresh_globals()
|
||||
if playlist_visible then
|
||||
showplaylist()
|
||||
end
|
||||
if settings.display_osd_feedback then
|
||||
elseif settings.display_osd_feedback then
|
||||
mp.osd_message("Playlist shuffled")
|
||||
end
|
||||
end
|
||||
@@ -1424,11 +1203,7 @@ function remove_keybinds()
|
||||
keybindstimer:kill()
|
||||
keybindstimer = mp.add_periodic_timer(settings.playlist_display_timeout, remove_keybinds)
|
||||
keybindstimer:kill()
|
||||
playlist_overlay.data = ""
|
||||
playlist_overlay:remove()
|
||||
if is_terminal_mode() then
|
||||
mp.osd_message("")
|
||||
end
|
||||
mp.set_osd_ass(0, 0, "")
|
||||
playlist_visible = false
|
||||
if settings.reset_cursor_on_close then
|
||||
resetcursor()
|
||||
@@ -1466,10 +1241,9 @@ mp.observe_property('playlist-count', "number", function(_, plcount)
|
||||
refresh_globals()
|
||||
sortplaylist()
|
||||
end
|
||||
refresh_UI()
|
||||
if playlist_visible then showplaylist() end
|
||||
resolve_titles()
|
||||
end)
|
||||
mp.observe_property('osd-dimensions', 'native', refresh_UI)
|
||||
|
||||
|
||||
url_request_queue = {}
|
||||
@@ -1540,10 +1314,10 @@ function resolve_titles()
|
||||
and not requested_titles[filename]
|
||||
then
|
||||
requested_titles[filename] = true
|
||||
if filename:match('^https?://') and settings.resolve_url_titles then
|
||||
if filename:match('^https?://') then
|
||||
url_titles_to_fetch.push(filename)
|
||||
added_urls = true
|
||||
elseif settings.prefer_titles == "all" and settings.resolve_local_titles then
|
||||
elseif settings.prefer_titles == "all" then
|
||||
local_titles_to_fetch.push(filename)
|
||||
added_local = true
|
||||
end
|
||||
@@ -1586,8 +1360,8 @@ function resolve_ytdl_title(filename)
|
||||
local title = (is_playlist and '[playlist]: ' or '') .. json['title']
|
||||
msg.verbose(filename .. " resolved to '" .. title .. "'")
|
||||
title_table[filename] = title
|
||||
mp.set_property_native('user-data/playlistmanager/titles', title_table)
|
||||
refresh_UI()
|
||||
refresh_globals()
|
||||
if playlist_visible then showplaylist() end
|
||||
else
|
||||
msg.error("Failed parsing json, reason: "..(err or "unknown"))
|
||||
end
|
||||
@@ -1627,8 +1401,8 @@ function resolve_ffprobe_title(filename)
|
||||
if title then
|
||||
msg.verbose(filename .. " resolved to '" .. title .. "'")
|
||||
title_table[filename] = title
|
||||
mp.set_property_native('user-data/playlistmanager/titles', title_table)
|
||||
refresh_UI()
|
||||
refresh_globals()
|
||||
if playlist_visible then showplaylist() end
|
||||
end
|
||||
else
|
||||
msg.error("Failed to resolve local title "..filename.." Error: "..(res.error or "unknown"))
|
||||
@@ -1668,9 +1442,8 @@ function handlemessage(msg, value, value2)
|
||||
if msg == "reverse" then reverseplaylist() ; return end
|
||||
if msg == "loadfiles" then playlist(value) ; return end
|
||||
if msg == "save" then save_playlist(value) ; return end
|
||||
if msg == "playlist-next" then playlist_next() ; return end
|
||||
if msg == "playlist-prev" then playlist_prev() ; return end
|
||||
if msg == "playlist-next-random" then playlist_random() ; return end
|
||||
if msg == "playlist-next" then playlist_next(true) ; return end
|
||||
if msg == "playlist-prev" then playlist_prev(true) ; return end
|
||||
if msg == "enable-interactive-save" then interactive_save = true end
|
||||
if msg == "close" then remove_keybinds() end
|
||||
end
|
||||
|
||||
192
mpv/scripts/seek-to.lua
Normal file
192
mpv/scripts/seek-to.lua
Normal file
@@ -0,0 +1,192 @@
|
||||
-- Original script from https://github.com/occivink/mpv-scripts/blob/master/scripts/seek-to.lua
|
||||
-- prerequisite: xclip (clipboard CLI interface) installed
|
||||
|
||||
local assdraw = require 'mp.assdraw'
|
||||
local utils = require 'mp.utils'
|
||||
local msg = require 'mp.msg'
|
||||
local active = false
|
||||
local cursor_position = 1
|
||||
local time_scale = {60*60*10, 60*60, 60*10, 60, 10, 1, 0.1, 0.01, 0.001}
|
||||
|
||||
local ass_begin = mp.get_property("osd-ass-cc/0")
|
||||
local ass_end = mp.get_property("osd-ass-cc/1")
|
||||
|
||||
local history = { {} }
|
||||
for i = 1, 9 do
|
||||
history[1][i] = 0
|
||||
end
|
||||
local history_position = 1
|
||||
|
||||
-- timer to redraw periodically the message
|
||||
-- to avoid leaving bindings when the seeker disappears for whatever reason
|
||||
-- pretty hacky tbh
|
||||
local timer = nil
|
||||
local timer_duration = 3
|
||||
|
||||
function show_seeker()
|
||||
local prepend_char = {'','',':','',':','','.','',''}
|
||||
local str = ''
|
||||
for i = 1, 9 do
|
||||
str = str .. prepend_char[i]
|
||||
if i == cursor_position then
|
||||
str = str .. '{\\b1}' .. history[history_position][i] .. '{\\r}'
|
||||
else
|
||||
str = str .. history[history_position][i]
|
||||
end
|
||||
end
|
||||
mp.osd_message("Seek to: " .. ass_begin .. str .. ass_end, timer_duration)
|
||||
end
|
||||
|
||||
function copy_history_to_last()
|
||||
if history_position ~= #history then
|
||||
for i = 1, 9 do
|
||||
history[#history][i] = history[history_position][i]
|
||||
end
|
||||
history_position = #history
|
||||
end
|
||||
end
|
||||
|
||||
function change_number(i)
|
||||
-- can't set above 60 minutes or seconds
|
||||
if (cursor_position == 3 or cursor_position == 5) and i >= 6 then
|
||||
return
|
||||
end
|
||||
if history[history_position][cursor_position] ~= i then
|
||||
copy_history_to_last()
|
||||
history[#history][cursor_position] = i
|
||||
end
|
||||
shift_cursor(false)
|
||||
end
|
||||
|
||||
function shift_cursor(left)
|
||||
if left then
|
||||
cursor_position = math.max(1, cursor_position - 1)
|
||||
else
|
||||
cursor_position = math.min(cursor_position + 1, 9)
|
||||
end
|
||||
end
|
||||
|
||||
function current_time_as_sec(time)
|
||||
local sec = 0
|
||||
for i = 1, 9 do
|
||||
sec = sec + time_scale[i] * time[i]
|
||||
end
|
||||
return sec
|
||||
end
|
||||
|
||||
function time_equal(lhs, rhs)
|
||||
for i = 1, 9 do
|
||||
if lhs[i] ~= rhs[i] then
|
||||
return false
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
function seek_to()
|
||||
copy_history_to_last()
|
||||
mp.commandv("osd-bar", "seek", current_time_as_sec(history[history_position]), "absolute")
|
||||
--deduplicate consecutive timestamps
|
||||
if #history == 1 or not time_equal(history[history_position], history[#history - 1]) then
|
||||
history[#history + 1] = {}
|
||||
history_position = #history
|
||||
end
|
||||
for i = 1, 9 do
|
||||
history[#history][i] = 0
|
||||
end
|
||||
end
|
||||
|
||||
function backspace()
|
||||
if history[history_position][cursor_position] ~= 0 then
|
||||
copy_history_to_last()
|
||||
history[#history][cursor_position] = 0
|
||||
end
|
||||
shift_cursor(true)
|
||||
end
|
||||
|
||||
function history_move(up)
|
||||
if up then
|
||||
history_position = math.max(1, history_position - 1)
|
||||
else
|
||||
history_position = math.min(history_position + 1, #history)
|
||||
end
|
||||
end
|
||||
|
||||
local key_mappings = {
|
||||
LEFT = function() shift_cursor(true) show_seeker() end,
|
||||
RIGHT = function() shift_cursor(false) show_seeker() end,
|
||||
UP = function() history_move(true) show_seeker() end,
|
||||
DOWN = function() history_move(false) show_seeker() end,
|
||||
BS = function() backspace() show_seeker() end,
|
||||
ESC = function() set_inactive() end,
|
||||
ENTER = function() seek_to() set_inactive() end
|
||||
}
|
||||
for i = 0, 9 do
|
||||
local func = function() change_number(i) show_seeker() end
|
||||
key_mappings[string.format("KP%d", i)] = func
|
||||
key_mappings[string.format("%d", i)] = func
|
||||
end
|
||||
|
||||
function set_active()
|
||||
if not mp.get_property("seekable") then return end
|
||||
-- find duration of the video and set cursor position accordingly
|
||||
local duration = mp.get_property_number("duration")
|
||||
if duration ~= nil then
|
||||
for i = 1, 9 do
|
||||
if duration > time_scale[i] then
|
||||
cursor_position = i
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
for key, func in pairs(key_mappings) do
|
||||
mp.add_forced_key_binding(key, "seek-to-"..key, func)
|
||||
end
|
||||
show_seeker()
|
||||
timer = mp.add_periodic_timer(timer_duration, show_seeker)
|
||||
active = true
|
||||
end
|
||||
|
||||
function set_inactive()
|
||||
mp.osd_message("")
|
||||
for key, _ in pairs(key_mappings) do
|
||||
mp.remove_key_binding("seek-to-"..key)
|
||||
end
|
||||
timer:kill()
|
||||
active = false
|
||||
end
|
||||
|
||||
function paste_timestamp()
|
||||
-- get clipboard data
|
||||
local clipboard = utils.subprocess({
|
||||
args = { "xclip", "-selection", "clipboard", "-o" },
|
||||
playback_only = false,
|
||||
capture_stdout = true,
|
||||
capture_stderr = true
|
||||
})
|
||||
|
||||
-- error handling
|
||||
if not clipboard.error then
|
||||
timestamp = clipboard.stdout
|
||||
else
|
||||
msg.error("Error getting data from clipboard:")
|
||||
msg.error(" stderr: " .. clipboard.stderr)
|
||||
msg.error(" stdout: " .. clipboard.stdout)
|
||||
return
|
||||
end
|
||||
|
||||
-- find timestamp from clipboard
|
||||
match = timestamp:match("%d?%d?:?%d%d:%d%d%.?%d*")
|
||||
|
||||
-- paste and seek to timestamp
|
||||
if match ~= nil then
|
||||
mp.osd_message("Timestamp pasted: " .. match)
|
||||
mp.commandv("osd-bar", "seek", match, "absolute")
|
||||
else
|
||||
msg.warn("No pastable timestamp found!")
|
||||
end
|
||||
end
|
||||
|
||||
-- keybindings are set in input.conf
|
||||
mp.add_key_binding(nil, "toggle-seeker", function() if active then set_inactive() else set_active() end end)
|
||||
mp.add_key_binding(nil, "paste-timestamp", paste_timestamp)
|
||||
147
mpv/scripts/sponsorblock-minimal.lua
Normal file
147
mpv/scripts/sponsorblock-minimal.lua
Normal file
@@ -0,0 +1,147 @@
|
||||
-- sponsorblock-minimal.lua
|
||||
-- source: https://codeberg.org/jouni/mpv_sponsorblock_minimal
|
||||
--
|
||||
-- This script skips sponsored segments of YouTube videos
|
||||
-- using data from https://github.com/ajayyy/SponsorBlock
|
||||
|
||||
local opt = require 'mp.options'
|
||||
local utils = require 'mp.utils'
|
||||
|
||||
local ON = false
|
||||
local ranges = nil
|
||||
|
||||
local options = {
|
||||
server = "https://sponsor.ajay.app/api/skipSegments",
|
||||
|
||||
-- Categories to fetch and skip
|
||||
categories = '"sponsor"',
|
||||
|
||||
-- Set this to "true" to use sha256HashPrefix instead of videoID
|
||||
hash = ""
|
||||
}
|
||||
|
||||
opt.read_options(options)
|
||||
|
||||
function get_ranges(youtube_id, url)
|
||||
local luacurl_available, cURL = pcall(require,'cURL')
|
||||
|
||||
local res = nil
|
||||
if not(luacurl_available) then -- if Lua-cURL is not available on this system
|
||||
local sponsors = mp.command_native{
|
||||
name = "subprocess",
|
||||
capture_stdout = true,
|
||||
playback_only = false,
|
||||
args = {"curl", "-L", "-s", "-g", url}
|
||||
}
|
||||
res = sponsors.stdout
|
||||
else -- otherwise use Lua-cURL (binding to libcurl)
|
||||
local buf={}
|
||||
local c = cURL.easy_init()
|
||||
c:setopt_followlocation(1)
|
||||
c:setopt_url(url)
|
||||
c:setopt_writefunction(function(chunk) table.insert(buf,chunk); return true; end)
|
||||
c:perform()
|
||||
res = table.concat(buf)
|
||||
end
|
||||
|
||||
if res then
|
||||
local json = utils.parse_json(res)
|
||||
if type(json) == "table" then
|
||||
if options.hash == "true" then
|
||||
for _, i in pairs(json) do
|
||||
if i.videoID == youtube_id then
|
||||
return i.segments
|
||||
end
|
||||
end
|
||||
else
|
||||
return json
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
function skip_ads(name,pos)
|
||||
if pos then
|
||||
for _, i in pairs(ranges) do
|
||||
v = i.segment[2]
|
||||
if i.segment[1] <= pos and v > pos then
|
||||
--this message may sometimes be wrong
|
||||
--it only seems to be a visual thing though
|
||||
mp.osd_message(("[sponsorblock] skipping forward %ds"):format(math.floor(v-mp.get_property("time-pos"))))
|
||||
--need to do the +0.01 otherwise mpv will start spamming skip sometimes
|
||||
--example: https://www.youtube.com/watch?v=4ypMJzeNooo
|
||||
mp.set_property("time-pos",v+0.01)
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function file_loaded()
|
||||
local video_path = mp.get_property("path", "")
|
||||
local video_referer = string.match(mp.get_property("http-header-fields", ""), "Referer:([^,]+)") or ""
|
||||
|
||||
local urls = {
|
||||
"ytdl://youtu%.be/([%w-_]+).*",
|
||||
"ytdl://w?w?w?%.?youtube%.com/v/([%w-_]+).*",
|
||||
"https?://youtu%.be/([%w-_]+).*",
|
||||
"https?://w?w?w?%.?youtube%.com/v/([%w-_]+).*",
|
||||
"/watch.*[?&]v=([%w-_]+).*",
|
||||
"/embed/([%w-_]+).*",
|
||||
"^ytdl://([%w-_]+)$",
|
||||
"-([%w-_]+)%."
|
||||
}
|
||||
local youtube_id = nil
|
||||
local purl = mp.get_property("metadata/by-key/PURL", "")
|
||||
for i,url in ipairs(urls) do
|
||||
youtube_id = youtube_id or string.match(video_path, url) or string.match(video_referer, url) or string.match(purl, url)
|
||||
if youtube_id then break end
|
||||
end
|
||||
|
||||
if not youtube_id or string.len(youtube_id) < 11 then return end
|
||||
youtube_id = string.sub(youtube_id, 1, 11)
|
||||
|
||||
local url = ""
|
||||
if options.hash == "true" then
|
||||
local sha = mp.command_native{
|
||||
name = "subprocess",
|
||||
capture_stdout = true,
|
||||
args = {"sha256sum"},
|
||||
stdin_data = youtube_id
|
||||
}
|
||||
url = ("%s/%s?categories=[%s]"):format(options.server, string.sub(sha.stdout, 0, 4), options.categories)
|
||||
else
|
||||
url = ("%s?videoID=%s&categories=[%s]"):format(options.server, youtube_id, options.categories)
|
||||
end
|
||||
|
||||
ranges = get_ranges(youtube_id, url)
|
||||
if ranges then
|
||||
ON = true
|
||||
mp.add_key_binding("b","sponsorblock",toggle)
|
||||
mp.observe_property("time-pos", "native", skip_ads)
|
||||
end
|
||||
end
|
||||
|
||||
function end_file()
|
||||
if not ON then return end
|
||||
mp.unobserve_property(skip_ads)
|
||||
ranges = nil
|
||||
ON = false
|
||||
end
|
||||
|
||||
function toggle()
|
||||
if ON then
|
||||
mp.unobserve_property(skip_ads)
|
||||
mp.osd_message("[sponsorblock] off")
|
||||
ON = false
|
||||
else
|
||||
mp.observe_property("time-pos", "native", skip_ads)
|
||||
mp.osd_message("[sponsorblock] on")
|
||||
ON = true
|
||||
end
|
||||
end
|
||||
|
||||
mp.register_event("file-loaded", file_loaded)
|
||||
mp.register_event("end-file", end_file)
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,190 +0,0 @@
|
||||
local utils = require 'mp.utils'
|
||||
|
||||
-- 参数设置
|
||||
local subtitlesPerPage = 10
|
||||
local closeAfterLoad = true
|
||||
local rate = 1.5
|
||||
|
||||
-- 全局变量和实用函数
|
||||
local styleOn = mp.get_property("osd-ass-cc/0")
|
||||
local subtitles = {}
|
||||
local currentSlot = 1
|
||||
local currentPage = 1
|
||||
local maxPage = 1
|
||||
local active = false
|
||||
|
||||
-- 控制列表
|
||||
local subtitleControls = {
|
||||
ESC = function() abort("") end,
|
||||
e = function() abort("") end,
|
||||
DOWN = function() jumpSlot(1) end,
|
||||
UP = function() jumpSlot(-1) end,
|
||||
j = function() jumpSlot(1) end,
|
||||
k = function() jumpSlot(-1) end,
|
||||
RIGHT = function() jumpPage(1) end,
|
||||
LEFT = function() jumpPage(-1) end,
|
||||
ENTER = function() loadSubtitle(currentSlot) end,
|
||||
KP_ENTER = function() loadSubtitle(currentSlot) end
|
||||
}
|
||||
|
||||
local subtitleFlags = {
|
||||
DOWN = {repeatable = true},
|
||||
UP = {repeatable = true},
|
||||
RIGHT = {repeatable = true},
|
||||
LEFT = {repeatable = true}
|
||||
}
|
||||
|
||||
-- 激活自定义控件
|
||||
function activateControls(name, controls, flags)
|
||||
for key, func in pairs(controls) do
|
||||
mp.add_forced_key_binding(key, name..key, func, flags[key])
|
||||
end
|
||||
end
|
||||
|
||||
-- 取消激活自定义控件
|
||||
function deactivateControls(name, controls)
|
||||
for key, _ in pairs(controls) do
|
||||
mp.remove_key_binding(name..key)
|
||||
end
|
||||
end
|
||||
|
||||
-- 实用函数
|
||||
function fileExists(path)
|
||||
local f = io.open(path, "r")
|
||||
if f ~= nil then
|
||||
io.close(f)
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
-- 加载字幕列表
|
||||
function listSubtitles()
|
||||
subtitles = {}
|
||||
local tracks = mp.get_property_native("track-list")
|
||||
for _, track in ipairs(tracks) do
|
||||
if track.type == "sub" then
|
||||
table.insert(subtitles, track)
|
||||
end
|
||||
end
|
||||
calcPages()
|
||||
end
|
||||
|
||||
-- 计算当前页和总页数
|
||||
function calcPages()
|
||||
currentPage = math.floor((currentSlot - 1) / subtitlesPerPage) + 1
|
||||
if currentPage == 0 then currentPage = 1 end
|
||||
maxPage = math.floor((#subtitles - 1) / subtitlesPerPage) + 1
|
||||
if maxPage == 0 then maxPage = 1 end
|
||||
end
|
||||
|
||||
-- 获取指定页的字幕数量
|
||||
function getAmountSubtitlesOnPage(page)
|
||||
local n = subtitlesPerPage
|
||||
if page == maxPage then n = #subtitles % subtitlesPerPage end
|
||||
if n == 0 then n = subtitlesPerPage end
|
||||
if #subtitles == 0 then n = 0 end
|
||||
return n
|
||||
end
|
||||
|
||||
-- 获取指定页的第一个字幕索引
|
||||
function getFirstSlotOnPage(page)
|
||||
return (page - 1) * subtitlesPerPage + 1
|
||||
end
|
||||
|
||||
-- 获取指定页的最后一个字幕索引
|
||||
function getLastSlotOnPage(page)
|
||||
local endSlot = getFirstSlotOnPage(page) + getAmountSubtitlesOnPage(page) - 1
|
||||
if endSlot > #subtitles then endSlot = #subtitles end
|
||||
return endSlot
|
||||
end
|
||||
|
||||
-- 跳到指定数量的字幕前或后
|
||||
function jumpSlot(i)
|
||||
currentSlot = currentSlot + i
|
||||
local startSlot = getFirstSlotOnPage(currentPage)
|
||||
local endSlot = getLastSlotOnPage(currentPage)
|
||||
|
||||
if currentSlot < startSlot then currentSlot = endSlot end
|
||||
if currentSlot > endSlot then currentSlot = startSlot end
|
||||
|
||||
displaySubtitles()
|
||||
end
|
||||
|
||||
-- 跳到指定数量的页前或后
|
||||
function jumpPage(i)
|
||||
local oldPos = currentSlot - getFirstSlotOnPage(currentPage) + 1
|
||||
currentPage = currentPage + i
|
||||
if currentPage < 1 then currentPage = maxPage + currentPage end
|
||||
if currentPage > maxPage then currentPage = currentPage - maxPage end
|
||||
|
||||
local subtitlesOnPage = getAmountSubtitlesOnPage(currentPage)
|
||||
if oldPos > subtitlesOnPage then oldPos = subtitlesOnPage end
|
||||
currentSlot = getFirstSlotOnPage(currentPage) + oldPos - 1
|
||||
|
||||
displaySubtitles()
|
||||
end
|
||||
|
||||
-- 显示当前页的字幕
|
||||
function displaySubtitles()
|
||||
-- 确定当前页的第一个和最后一个字幕索引
|
||||
local startSlot = getFirstSlotOnPage(currentPage)
|
||||
local endSlot = getLastSlotOnPage(currentPage)
|
||||
|
||||
-- 准备显示的文本并显示
|
||||
local display = styleOn .. "{\\b1}Subtitles page " .. currentPage .. "/" .. maxPage .. ":{\\b0}"
|
||||
for i = startSlot, endSlot do
|
||||
local sub = subtitles[i]
|
||||
local selection = ""
|
||||
if i == currentSlot then
|
||||
selection = "{\\b1}{\\c&H00FFFF&}>"
|
||||
end
|
||||
display = display .. "\n" .. selection .. i .. ": " .. (sub.title or sub.lang or sub.src) .. "{\\r}"
|
||||
end
|
||||
mp.osd_message(display, rate)
|
||||
end
|
||||
|
||||
-- 加载指定的字幕
|
||||
function loadSubtitle(slot)
|
||||
if slot >= 1 and slot <= #subtitles then
|
||||
local sub = subtitles[slot]
|
||||
mp.set_property_native("sid", sub.id)
|
||||
mp.osd_message(string.format("Loaded subtitle: %s", sub.title or sub.lang or sub.src), 2)
|
||||
if closeAfterLoad then
|
||||
abort(styleOn.."{\\c&H00FF00&}{\\b1}Successfully loaded subtitle:{\\r}\n"..(sub.title or sub.lang or sub.src))
|
||||
end
|
||||
else
|
||||
abort(styleOn.."{\\c&H0000FF&}{\\b1}Can't find the subtitle at slot " .. slot)
|
||||
end
|
||||
end
|
||||
|
||||
-- 定时器
|
||||
local timer = mp.add_periodic_timer(rate * 0.95, displaySubtitles)
|
||||
timer:kill()
|
||||
|
||||
|
||||
-- 终止程序
|
||||
function abort(message)
|
||||
mode = "none"
|
||||
deactivateControls("subtitle", subtitleControls)
|
||||
timer:kill()
|
||||
mp.osd_message(message)
|
||||
active = false
|
||||
end
|
||||
|
||||
-- 处理字幕菜单的状态
|
||||
function handler()
|
||||
if active then
|
||||
abort("")
|
||||
else
|
||||
activateControls("subtitle", subtitleControls, subtitleFlags)
|
||||
listSubtitles()
|
||||
displaySubtitles()
|
||||
timer:resume()
|
||||
active = true
|
||||
end
|
||||
end
|
||||
|
||||
-- 注册脚本消息
|
||||
mp.register_script_message("subtitle-menu", handler)
|
||||
926
mpv/scripts/thumbfast.lua
Normal file
926
mpv/scripts/thumbfast.lua
Normal file
@@ -0,0 +1,926 @@
|
||||
-- thumbfast.lua
|
||||
--
|
||||
-- High-performance on-the-fly thumbnailer
|
||||
--
|
||||
-- Built for easy integration in third-party UIs.
|
||||
|
||||
--[[
|
||||
This Source Code Form is subject to the terms of the Mozilla Public
|
||||
License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
]]
|
||||
|
||||
local options = {
|
||||
-- Socket path (leave empty for auto)
|
||||
socket = "",
|
||||
|
||||
-- Thumbnail path (leave empty for auto)
|
||||
thumbnail = "",
|
||||
|
||||
-- Maximum thumbnail size in pixels (scaled down to fit)
|
||||
-- Values are scaled when hidpi is enabled
|
||||
max_height = 200,
|
||||
max_width = 200,
|
||||
|
||||
-- Apply tone-mapping, no to disable
|
||||
tone_mapping = "auto",
|
||||
|
||||
-- Overlay id
|
||||
overlay_id = 42,
|
||||
|
||||
-- Spawn thumbnailer on file load for faster initial thumbnails
|
||||
spawn_first = false,
|
||||
|
||||
-- Close thumbnailer process after an inactivity period in seconds, 0 to disable
|
||||
quit_after_inactivity = 0,
|
||||
|
||||
-- Enable on network playback
|
||||
network = false,
|
||||
|
||||
-- Enable on audio playback
|
||||
audio = false,
|
||||
|
||||
-- Enable hardware decoding
|
||||
hwdec = false,
|
||||
|
||||
-- Windows only: use native Windows API to write to pipe (requires LuaJIT)
|
||||
direct_io = false,
|
||||
|
||||
-- Custom path to the mpv executable
|
||||
mpv_path = "mpv"
|
||||
}
|
||||
|
||||
mp.utils = require "mp.utils"
|
||||
mp.options = require "mp.options"
|
||||
mp.options.read_options(options, "thumbfast")
|
||||
|
||||
local properties = {}
|
||||
local pre_0_30_0 = mp.command_native_async == nil
|
||||
local pre_0_33_0 = true
|
||||
|
||||
function subprocess(args, async, callback)
|
||||
callback = callback or function() end
|
||||
|
||||
if not pre_0_30_0 then
|
||||
if async then
|
||||
return mp.command_native_async({name = "subprocess", playback_only = true, args = args}, callback)
|
||||
else
|
||||
return mp.command_native({name = "subprocess", playback_only = false, capture_stdout = true, args = args})
|
||||
end
|
||||
else
|
||||
if async then
|
||||
return mp.utils.subprocess_detached({args = args}, callback)
|
||||
else
|
||||
return mp.utils.subprocess({args = args})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local winapi = {}
|
||||
if options.direct_io then
|
||||
local ffi_loaded, ffi = pcall(require, "ffi")
|
||||
if ffi_loaded then
|
||||
winapi = {
|
||||
ffi = ffi,
|
||||
C = ffi.C,
|
||||
bit = require("bit"),
|
||||
socket_wc = "",
|
||||
|
||||
-- WinAPI constants
|
||||
CP_UTF8 = 65001,
|
||||
GENERIC_WRITE = 0x40000000,
|
||||
OPEN_EXISTING = 3,
|
||||
FILE_FLAG_WRITE_THROUGH = 0x80000000,
|
||||
FILE_FLAG_NO_BUFFERING = 0x20000000,
|
||||
PIPE_NOWAIT = ffi.new("unsigned long[1]", 0x00000001),
|
||||
|
||||
INVALID_HANDLE_VALUE = ffi.cast("void*", -1),
|
||||
|
||||
-- don't care about how many bytes WriteFile wrote, so allocate something to store the result once
|
||||
_lpNumberOfBytesWritten = ffi.new("unsigned long[1]"),
|
||||
}
|
||||
-- cache flags used in run() to avoid bor() call
|
||||
winapi._createfile_pipe_flags = winapi.bit.bor(winapi.FILE_FLAG_WRITE_THROUGH, winapi.FILE_FLAG_NO_BUFFERING)
|
||||
|
||||
ffi.cdef[[
|
||||
void* __stdcall CreateFileW(const wchar_t *lpFileName, unsigned long dwDesiredAccess, unsigned long dwShareMode, void *lpSecurityAttributes, unsigned long dwCreationDisposition, unsigned long dwFlagsAndAttributes, void *hTemplateFile);
|
||||
bool __stdcall WriteFile(void *hFile, const void *lpBuffer, unsigned long nNumberOfBytesToWrite, unsigned long *lpNumberOfBytesWritten, void *lpOverlapped);
|
||||
bool __stdcall CloseHandle(void *hObject);
|
||||
bool __stdcall SetNamedPipeHandleState(void *hNamedPipe, unsigned long *lpMode, unsigned long *lpMaxCollectionCount, unsigned long *lpCollectDataTimeout);
|
||||
int __stdcall MultiByteToWideChar(unsigned int CodePage, unsigned long dwFlags, const char *lpMultiByteStr, int cbMultiByte, wchar_t *lpWideCharStr, int cchWideChar);
|
||||
]]
|
||||
|
||||
winapi.MultiByteToWideChar = function(MultiByteStr)
|
||||
if MultiByteStr then
|
||||
local utf16_len = winapi.C.MultiByteToWideChar(winapi.CP_UTF8, 0, MultiByteStr, -1, nil, 0)
|
||||
if utf16_len > 0 then
|
||||
local utf16_str = winapi.ffi.new("wchar_t[?]", utf16_len)
|
||||
if winapi.C.MultiByteToWideChar(winapi.CP_UTF8, 0, MultiByteStr, -1, utf16_str, utf16_len) > 0 then
|
||||
return utf16_str
|
||||
end
|
||||
end
|
||||
end
|
||||
return ""
|
||||
end
|
||||
|
||||
else
|
||||
options.direct_io = false
|
||||
end
|
||||
end
|
||||
|
||||
local file = nil
|
||||
local file_bytes = 0
|
||||
local spawned = false
|
||||
local disabled = false
|
||||
local force_disabled = false
|
||||
local spawn_waiting = false
|
||||
local spawn_working = false
|
||||
local script_written = false
|
||||
|
||||
local dirty = false
|
||||
|
||||
local x = nil
|
||||
local y = nil
|
||||
local last_x = x
|
||||
local last_y = y
|
||||
|
||||
local last_seek_time = nil
|
||||
|
||||
local effective_w = options.max_width
|
||||
local effective_h = options.max_height
|
||||
local real_w = nil
|
||||
local real_h = nil
|
||||
local last_real_w = nil
|
||||
local last_real_h = nil
|
||||
|
||||
local script_name = nil
|
||||
|
||||
local show_thumbnail = false
|
||||
|
||||
local filters_reset = {["lavfi-crop"]=true, ["crop"]=true}
|
||||
local filters_runtime = {["hflip"]=true, ["vflip"]=true}
|
||||
local filters_all = {["hflip"]=true, ["vflip"]=true, ["lavfi-crop"]=true, ["crop"]=true}
|
||||
|
||||
local tone_mappings = {["none"]=true, ["clip"]=true, ["linear"]=true, ["gamma"]=true, ["reinhard"]=true, ["hable"]=true, ["mobius"]=true}
|
||||
local last_tone_mapping = nil
|
||||
|
||||
local last_vf_reset = ""
|
||||
local last_vf_runtime = ""
|
||||
|
||||
local last_rotate = 0
|
||||
|
||||
local par = ""
|
||||
local last_par = ""
|
||||
|
||||
local last_has_vid = 0
|
||||
local has_vid = 0
|
||||
|
||||
local file_timer = nil
|
||||
local file_check_period = 1/60
|
||||
|
||||
local allow_fast_seek = true
|
||||
|
||||
local client_script = [=[
|
||||
#!/usr/bin/env bash
|
||||
MPV_IPC_FD=0; MPV_IPC_PATH="%s"
|
||||
trap "kill 0" EXIT
|
||||
while [[ $# -ne 0 ]]; do case $1 in --mpv-ipc-fd=*) MPV_IPC_FD=${1/--mpv-ipc-fd=/} ;; esac; shift; done
|
||||
if echo "print-text thumbfast" >&"$MPV_IPC_FD"; then echo -n > "$MPV_IPC_PATH"; tail -f "$MPV_IPC_PATH" >&"$MPV_IPC_FD" & while read -r -u "$MPV_IPC_FD" 2>/dev/null; do :; done; fi
|
||||
]=]
|
||||
|
||||
local function get_os()
|
||||
local raw_os_name = ""
|
||||
|
||||
if jit and jit.os and jit.arch then
|
||||
raw_os_name = jit.os
|
||||
else
|
||||
if package.config:sub(1,1) == "\\" then
|
||||
-- Windows
|
||||
local env_OS = os.getenv("OS")
|
||||
if env_OS then
|
||||
raw_os_name = env_OS
|
||||
end
|
||||
else
|
||||
raw_os_name = subprocess({"uname", "-s"}).stdout
|
||||
end
|
||||
end
|
||||
|
||||
raw_os_name = (raw_os_name):lower()
|
||||
|
||||
local os_patterns = {
|
||||
["windows"] = "windows",
|
||||
["linux"] = "linux",
|
||||
|
||||
["osx"] = "darwin",
|
||||
["mac"] = "darwin",
|
||||
["darwin"] = "darwin",
|
||||
|
||||
["^mingw"] = "windows",
|
||||
["^cygwin"] = "windows",
|
||||
|
||||
["bsd$"] = "darwin",
|
||||
["sunos"] = "darwin"
|
||||
}
|
||||
|
||||
-- Default to linux
|
||||
local str_os_name = "linux"
|
||||
|
||||
for pattern, name in pairs(os_patterns) do
|
||||
if raw_os_name:match(pattern) then
|
||||
str_os_name = name
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
return str_os_name
|
||||
end
|
||||
|
||||
local os_name = mp.get_property("platform") or get_os()
|
||||
|
||||
local path_separator = os_name == "windows" and "\\" or "/"
|
||||
|
||||
if options.socket == "" then
|
||||
if os_name == "windows" then
|
||||
options.socket = "thumbfast"
|
||||
else
|
||||
options.socket = "/tmp/thumbfast"
|
||||
end
|
||||
end
|
||||
|
||||
if options.thumbnail == "" then
|
||||
if os_name == "windows" then
|
||||
options.thumbnail = os.getenv("TEMP").."\\thumbfast.out"
|
||||
else
|
||||
options.thumbnail = "/tmp/thumbfast.out"
|
||||
end
|
||||
end
|
||||
|
||||
local unique = mp.utils.getpid()
|
||||
|
||||
options.socket = options.socket .. unique
|
||||
options.thumbnail = options.thumbnail .. unique
|
||||
|
||||
if options.direct_io then
|
||||
if os_name == "windows" then
|
||||
winapi.socket_wc = winapi.MultiByteToWideChar("\\\\.\\pipe\\" .. options.socket)
|
||||
end
|
||||
|
||||
if winapi.socket_wc == "" then
|
||||
options.direct_io = false
|
||||
end
|
||||
end
|
||||
|
||||
local mpv_path = options.mpv_path
|
||||
|
||||
if mpv_path == "mpv" and os_name == "darwin" and unique then
|
||||
-- TODO: look into ~~osxbundle/
|
||||
mpv_path = string.gsub(subprocess({"ps", "-o", "comm=", "-p", tostring(unique)}).stdout, "[\n\r]", "")
|
||||
if mpv_path ~= "mpv" then
|
||||
mpv_path = string.gsub(mpv_path, "/mpv%-bundle$", "/mpv")
|
||||
local mpv_bin = mp.utils.file_info("/usr/local/mpv")
|
||||
if mpv_bin and mpv_bin.is_file then
|
||||
mpv_path = "/usr/local/mpv"
|
||||
else
|
||||
local mpv_app = mp.utils.file_info("/Applications/mpv.app/Contents/MacOS/mpv")
|
||||
if mpv_app and mpv_app.is_file then
|
||||
mp.msg.warn("symlink mpv to fix Dock icons: `sudo ln -s /Applications/mpv.app/Contents/MacOS/mpv /usr/local/mpv`")
|
||||
else
|
||||
mp.msg.warn("drag to your Applications folder and symlink mpv to fix Dock icons: `sudo ln -s /Applications/mpv.app/Contents/MacOS/mpv /usr/local/mpv`")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function vo_tone_mapping()
|
||||
local passes = mp.get_property_native("vo-passes")
|
||||
if passes and passes["fresh"] then
|
||||
for k, v in pairs(passes["fresh"]) do
|
||||
for k2, v2 in pairs(v) do
|
||||
if k2 == "desc" and v2 then
|
||||
local tone_mapping = string.match(v2, "([0-9a-z.-]+) tone map")
|
||||
if tone_mapping then
|
||||
return tone_mapping
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function vf_string(filters, full)
|
||||
local vf = ""
|
||||
local vf_table = properties["vf"]
|
||||
|
||||
if vf_table and #vf_table > 0 then
|
||||
for i = #vf_table, 1, -1 do
|
||||
if filters[vf_table[i].name] then
|
||||
local args = ""
|
||||
for key, value in pairs(vf_table[i].params) do
|
||||
if args ~= "" then
|
||||
args = args .. ":"
|
||||
end
|
||||
args = args .. key .. "=" .. value
|
||||
end
|
||||
vf = vf .. vf_table[i].name .. "=" .. args .. ","
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if (full and options.tone_mapping ~= "no") or options.tone_mapping == "auto" then
|
||||
if properties["video-params"] and properties["video-params"]["primaries"] == "bt.2020" then
|
||||
local tone_mapping = options.tone_mapping
|
||||
if tone_mapping == "auto" then
|
||||
tone_mapping = last_tone_mapping or properties["tone-mapping"]
|
||||
if tone_mapping == "auto" and properties["current-vo"] == "gpu-next" then
|
||||
tone_mapping = vo_tone_mapping()
|
||||
end
|
||||
end
|
||||
if not tone_mappings[tone_mapping] then
|
||||
tone_mapping = "hable"
|
||||
end
|
||||
last_tone_mapping = tone_mapping
|
||||
vf = vf .. "zscale=transfer=linear,format=gbrpf32le,tonemap="..tone_mapping..",zscale=transfer=bt709,"
|
||||
end
|
||||
end
|
||||
|
||||
if full then
|
||||
vf = vf.."scale=w="..effective_w..":h="..effective_h..par..",pad=w="..effective_w..":h="..effective_h..":x=-1:y=-1,format=bgra"
|
||||
end
|
||||
|
||||
return vf
|
||||
end
|
||||
|
||||
local function calc_dimensions()
|
||||
local width = properties["video-out-params"] and properties["video-out-params"]["dw"]
|
||||
local height = properties["video-out-params"] and properties["video-out-params"]["dh"]
|
||||
if not width or not height then return end
|
||||
|
||||
local scale = properties["display-hidpi-scale"] or 1
|
||||
|
||||
if width / height > options.max_width / options.max_height then
|
||||
effective_w = math.floor(options.max_width * scale + 0.5)
|
||||
effective_h = math.floor(height / width * effective_w + 0.5)
|
||||
else
|
||||
effective_h = math.floor(options.max_height * scale + 0.5)
|
||||
effective_w = math.floor(width / height * effective_h + 0.5)
|
||||
end
|
||||
|
||||
local v_par = properties["video-out-params"] and properties["video-out-params"]["par"] or 1
|
||||
if v_par == 1 then
|
||||
par = ":force_original_aspect_ratio=decrease"
|
||||
else
|
||||
par = ""
|
||||
end
|
||||
end
|
||||
|
||||
local info_timer = nil
|
||||
|
||||
local function info(w, h)
|
||||
local rotate = properties["video-params"] and properties["video-params"]["rotate"]
|
||||
local image = properties["current-tracks/video"] and properties["current-tracks/video"]["image"]
|
||||
local albumart = image and properties["current-tracks/video"]["albumart"]
|
||||
|
||||
disabled = (w or 0) == 0 or (h or 0) == 0 or
|
||||
has_vid == 0 or
|
||||
(properties["demuxer-via-network"] and not options.network) or
|
||||
(albumart and not options.audio) or
|
||||
(image and not albumart) or
|
||||
force_disabled
|
||||
|
||||
if info_timer then
|
||||
info_timer:kill()
|
||||
info_timer = nil
|
||||
elseif has_vid == 0 or (rotate == nil and not disabled) then
|
||||
info_timer = mp.add_timeout(0.05, function() info(w, h) end)
|
||||
end
|
||||
|
||||
local json, err = mp.utils.format_json({width=w, height=h, disabled=disabled, available=true, socket=options.socket, thumbnail=options.thumbnail, overlay_id=options.overlay_id})
|
||||
if pre_0_30_0 then
|
||||
mp.command_native({"script-message", "thumbfast-info", json})
|
||||
else
|
||||
mp.command_native_async({"script-message", "thumbfast-info", json}, function() end)
|
||||
end
|
||||
end
|
||||
|
||||
local function remove_thumbnail_files()
|
||||
if file then
|
||||
file:close()
|
||||
file = nil
|
||||
file_bytes = 0
|
||||
end
|
||||
os.remove(options.thumbnail)
|
||||
os.remove(options.thumbnail..".bgra")
|
||||
end
|
||||
|
||||
local activity_timer
|
||||
|
||||
local function spawn(time)
|
||||
if disabled then return end
|
||||
|
||||
local path = properties["path"]
|
||||
if path == nil then return end
|
||||
|
||||
if options.quit_after_inactivity > 0 then
|
||||
if show_thumbnail or activity_timer:is_enabled() then
|
||||
activity_timer:kill()
|
||||
end
|
||||
activity_timer:resume()
|
||||
end
|
||||
|
||||
local open_filename = properties["stream-open-filename"]
|
||||
local ytdl = open_filename and properties["demuxer-via-network"] and path ~= open_filename
|
||||
if ytdl then
|
||||
path = open_filename
|
||||
end
|
||||
|
||||
remove_thumbnail_files()
|
||||
|
||||
local vid = properties["vid"]
|
||||
has_vid = vid or 0
|
||||
|
||||
local args = {
|
||||
mpv_path, "--no-config", "--msg-level=all=no", "--idle", "--pause", "--keep-open=always", "--really-quiet", "--no-terminal",
|
||||
"--load-scripts=no", "--osc=no", "--ytdl=no", "--load-stats-overlay=no", "--load-osd-console=no", "--load-auto-profiles=no",
|
||||
"--edition="..(properties["edition"] or "auto"), "--vid="..(vid or "auto"), "--no-sub", "--no-audio",
|
||||
"--start="..time, allow_fast_seek and "--hr-seek=no" or "--hr-seek=yes",
|
||||
"--ytdl-format=worst", "--demuxer-readahead-secs=0", "--demuxer-max-bytes=128KiB",
|
||||
"--vd-lavc-skiploopfilter=all", "--vd-lavc-software-fallback=1", "--vd-lavc-fast", "--vd-lavc-threads=2", "--hwdec="..(options.hwdec and "auto" or "no"),
|
||||
"--vf="..vf_string(filters_all, true),
|
||||
"--sws-scaler=fast-bilinear",
|
||||
"--video-rotate="..last_rotate,
|
||||
"--ovc=rawvideo", "--of=image2", "--ofopts=update=1", "--o="..options.thumbnail
|
||||
}
|
||||
|
||||
if not pre_0_30_0 then
|
||||
table.insert(args, "--sws-allow-zimg=no")
|
||||
end
|
||||
|
||||
if os_name == "darwin" and properties["macos-app-activation-policy"] then
|
||||
table.insert(args, "--macos-app-activation-policy=accessory")
|
||||
end
|
||||
|
||||
if os_name == "windows" or pre_0_33_0 then
|
||||
table.insert(args, "--input-ipc-server="..options.socket)
|
||||
elseif not script_written then
|
||||
local client_script_path = options.socket..".run"
|
||||
local script = io.open(client_script_path, "w+")
|
||||
if script == nil then
|
||||
mp.msg.error("client script write failed")
|
||||
return
|
||||
else
|
||||
script_written = true
|
||||
script:write(string.format(client_script, options.socket))
|
||||
script:close()
|
||||
subprocess({"chmod", "+x", client_script_path}, true)
|
||||
table.insert(args, "--scripts="..client_script_path)
|
||||
end
|
||||
else
|
||||
local client_script_path = options.socket..".run"
|
||||
table.insert(args, "--scripts="..client_script_path)
|
||||
end
|
||||
|
||||
table.insert(args, "--")
|
||||
table.insert(args, path)
|
||||
|
||||
spawned = true
|
||||
spawn_waiting = true
|
||||
|
||||
subprocess(args, true,
|
||||
function(success, result)
|
||||
if spawn_waiting and (success == false or (result.status ~= 0 and result.status ~= -2)) then
|
||||
spawned = false
|
||||
spawn_waiting = false
|
||||
options.tone_mapping = "no"
|
||||
mp.msg.error("mpv subprocess create failed")
|
||||
if not spawn_working then -- notify users of required configuration
|
||||
if options.mpv_path == "mpv" then
|
||||
if properties["current-vo"] == "libmpv" then
|
||||
if options.mpv_path == mpv_path then -- attempt to locate ImPlay
|
||||
mpv_path = "ImPlay"
|
||||
spawn(time)
|
||||
else -- ImPlay not in path
|
||||
if os_name ~= "darwin" then
|
||||
force_disabled = true
|
||||
info(real_w or effective_w, real_h or effective_h)
|
||||
end
|
||||
mp.commandv("show-text", "thumbfast: ERROR! cannot create mpv subprocess", 5000)
|
||||
mp.commandv("script-message-to", "implay", "show-message", "thumbfast initial setup", "Set mpv_path=PATH_TO_ImPlay in thumbfast config:\n" .. string.gsub(mp.command_native({"expand-path", "~~/script-opts/thumbfast.conf"}), "[/\\]", path_separator).."\nand restart ImPlay")
|
||||
end
|
||||
else
|
||||
mp.commandv("show-text", "thumbfast: ERROR! cannot create mpv subprocess", 5000)
|
||||
if os_name == "windows" then
|
||||
mp.commandv("script-message-to", "mpvnet", "show-text", "thumbfast: ERROR! install standalone mpv, see README", 5000, 20)
|
||||
mp.commandv("script-message", "mpv.net", "show-text", "thumbfast: ERROR! install standalone mpv, see README", 5000, 20)
|
||||
end
|
||||
end
|
||||
else
|
||||
mp.commandv("show-text", "thumbfast: ERROR! cannot create mpv subprocess", 5000)
|
||||
-- found ImPlay but not defined in config
|
||||
mp.commandv("script-message-to", "implay", "show-message", "thumbfast", "Set mpv_path=PATH_TO_ImPlay in thumbfast config:\n" .. string.gsub(mp.command_native({"expand-path", "~~/script-opts/thumbfast.conf"}), "[/\\]", path_separator).."\nand restart ImPlay")
|
||||
end
|
||||
end
|
||||
elseif success == true and (result.status == 0 or result.status == -2) then
|
||||
if not spawn_working and properties["current-vo"] == "libmpv" and options.mpv_path ~= mpv_path then
|
||||
mp.commandv("script-message-to", "implay", "show-message", "thumbfast initial setup", "Set mpv_path=ImPlay in thumbfast config:\n" .. string.gsub(mp.command_native({"expand-path", "~~/script-opts/thumbfast.conf"}), "[/\\]", path_separator).."\nand restart ImPlay")
|
||||
end
|
||||
spawn_working = true
|
||||
spawn_waiting = false
|
||||
end
|
||||
end
|
||||
)
|
||||
end
|
||||
|
||||
local function run(command)
|
||||
if not spawned then return end
|
||||
|
||||
if options.direct_io then
|
||||
local hPipe = winapi.C.CreateFileW(winapi.socket_wc, winapi.GENERIC_WRITE, 0, nil, winapi.OPEN_EXISTING, winapi._createfile_pipe_flags, nil)
|
||||
if hPipe ~= winapi.INVALID_HANDLE_VALUE then
|
||||
local buf = command .. "\n"
|
||||
winapi.C.SetNamedPipeHandleState(hPipe, winapi.PIPE_NOWAIT, nil, nil)
|
||||
winapi.C.WriteFile(hPipe, buf, #buf + 1, winapi._lpNumberOfBytesWritten, nil)
|
||||
winapi.C.CloseHandle(hPipe)
|
||||
end
|
||||
|
||||
return
|
||||
end
|
||||
|
||||
local command_n = command.."\n"
|
||||
|
||||
if os_name == "windows" then
|
||||
if file and file_bytes + #command_n >= 4096 then
|
||||
file:close()
|
||||
file = nil
|
||||
file_bytes = 0
|
||||
end
|
||||
if not file then
|
||||
file = io.open("\\\\.\\pipe\\"..options.socket, "r+b")
|
||||
end
|
||||
elseif pre_0_33_0 then
|
||||
subprocess({"/usr/bin/env", "sh", "-c", "echo '" .. command .. "' | socat - " .. options.socket})
|
||||
return
|
||||
elseif not file then
|
||||
file = io.open(options.socket, "r+")
|
||||
end
|
||||
if file then
|
||||
file_bytes = file:seek("end")
|
||||
file:write(command_n)
|
||||
file:flush()
|
||||
end
|
||||
end
|
||||
|
||||
local function draw(w, h, script)
|
||||
if not w or not show_thumbnail then return end
|
||||
if x ~= nil then
|
||||
if pre_0_30_0 then
|
||||
mp.command_native({"overlay-add", options.overlay_id, x, y, options.thumbnail..".bgra", 0, "bgra", w, h, (4*w)})
|
||||
else
|
||||
mp.command_native_async({"overlay-add", options.overlay_id, x, y, options.thumbnail..".bgra", 0, "bgra", w, h, (4*w)}, function() end)
|
||||
end
|
||||
elseif script then
|
||||
local json, err = mp.utils.format_json({width=w, height=h, x=x, y=y, socket=options.socket, thumbnail=options.thumbnail, overlay_id=options.overlay_id})
|
||||
mp.commandv("script-message-to", script, "thumbfast-render", json)
|
||||
end
|
||||
end
|
||||
|
||||
local function real_res(req_w, req_h, filesize)
|
||||
local count = filesize / 4
|
||||
local diff = (req_w * req_h) - count
|
||||
|
||||
if (properties["video-params"] and properties["video-params"]["rotate"] or 0) % 180 == 90 then
|
||||
req_w, req_h = req_h, req_w
|
||||
end
|
||||
|
||||
if diff == 0 then
|
||||
return req_w, req_h
|
||||
else
|
||||
local threshold = 5 -- throw out results that change too much
|
||||
local long_side, short_side = req_w, req_h
|
||||
if req_h > req_w then
|
||||
long_side, short_side = req_h, req_w
|
||||
end
|
||||
for a = short_side, short_side - threshold, -1 do
|
||||
if count % a == 0 then
|
||||
local b = count / a
|
||||
if long_side - b < threshold then
|
||||
if req_h < req_w then return b, a else return a, b end
|
||||
end
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
local function move_file(from, to)
|
||||
if os_name == "windows" then
|
||||
os.remove(to)
|
||||
end
|
||||
-- move the file because it can get overwritten while overlay-add is reading it, and crash the player
|
||||
os.rename(from, to)
|
||||
end
|
||||
|
||||
local function seek(fast)
|
||||
if last_seek_time then
|
||||
run("async seek " .. last_seek_time .. (fast and " absolute+keyframes" or " absolute+exact"))
|
||||
end
|
||||
end
|
||||
|
||||
local seek_period = 3/60
|
||||
local seek_period_counter = 0
|
||||
local seek_timer
|
||||
seek_timer = mp.add_periodic_timer(seek_period, function()
|
||||
if seek_period_counter == 0 then
|
||||
seek(allow_fast_seek)
|
||||
seek_period_counter = 1
|
||||
else
|
||||
if seek_period_counter == 2 then
|
||||
if allow_fast_seek then
|
||||
seek_timer:kill()
|
||||
seek()
|
||||
end
|
||||
else seek_period_counter = seek_period_counter + 1 end
|
||||
end
|
||||
end)
|
||||
seek_timer:kill()
|
||||
|
||||
local function request_seek()
|
||||
if seek_timer:is_enabled() then
|
||||
seek_period_counter = 0
|
||||
else
|
||||
seek_timer:resume()
|
||||
seek(allow_fast_seek)
|
||||
seek_period_counter = 1
|
||||
end
|
||||
end
|
||||
|
||||
local function check_new_thumb()
|
||||
-- the slave might start writing to the file after checking existance and
|
||||
-- validity but before actually moving the file, so move to a temporary
|
||||
-- location before validity check to make sure everything stays consistant
|
||||
-- and valid thumbnails don't get overwritten by invalid ones
|
||||
local tmp = options.thumbnail..".tmp"
|
||||
move_file(options.thumbnail, tmp)
|
||||
local finfo = mp.utils.file_info(tmp)
|
||||
if not finfo then return false end
|
||||
spawn_waiting = false
|
||||
local w, h = real_res(effective_w, effective_h, finfo.size)
|
||||
if w then -- only accept valid thumbnails
|
||||
move_file(tmp, options.thumbnail..".bgra")
|
||||
|
||||
real_w, real_h = w, h
|
||||
if real_w and (real_w ~= last_real_w or real_h ~= last_real_h) then
|
||||
last_real_w, last_real_h = real_w, real_h
|
||||
info(real_w, real_h)
|
||||
end
|
||||
if not show_thumbnail then
|
||||
file_timer:kill()
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
file_timer = mp.add_periodic_timer(file_check_period, function()
|
||||
if check_new_thumb() then
|
||||
draw(real_w, real_h, script_name)
|
||||
end
|
||||
end)
|
||||
file_timer:kill()
|
||||
|
||||
local function clear()
|
||||
file_timer:kill()
|
||||
seek_timer:kill()
|
||||
if options.quit_after_inactivity > 0 then
|
||||
if show_thumbnail or activity_timer:is_enabled() then
|
||||
activity_timer:kill()
|
||||
end
|
||||
activity_timer:resume()
|
||||
end
|
||||
last_seek_time = nil
|
||||
show_thumbnail = false
|
||||
last_x = nil
|
||||
last_y = nil
|
||||
if script_name then return end
|
||||
if pre_0_30_0 then
|
||||
mp.command_native({"overlay-remove", options.overlay_id})
|
||||
else
|
||||
mp.command_native_async({"overlay-remove", options.overlay_id}, function() end)
|
||||
end
|
||||
end
|
||||
|
||||
local function quit()
|
||||
activity_timer:kill()
|
||||
if show_thumbnail then
|
||||
activity_timer:resume()
|
||||
return
|
||||
end
|
||||
run("quit")
|
||||
spawned = false
|
||||
real_w, real_h = nil, nil
|
||||
clear()
|
||||
end
|
||||
|
||||
activity_timer = mp.add_timeout(options.quit_after_inactivity, quit)
|
||||
activity_timer:kill()
|
||||
|
||||
local function thumb(time, r_x, r_y, script)
|
||||
if disabled then return end
|
||||
|
||||
time = tonumber(time)
|
||||
if time == nil then return end
|
||||
|
||||
if r_x == "" or r_y == "" then
|
||||
x, y = nil, nil
|
||||
else
|
||||
x, y = math.floor(r_x + 0.5), math.floor(r_y + 0.5)
|
||||
end
|
||||
|
||||
script_name = script
|
||||
if last_x ~= x or last_y ~= y or not show_thumbnail then
|
||||
show_thumbnail = true
|
||||
last_x = x
|
||||
last_y = y
|
||||
draw(real_w, real_h, script)
|
||||
end
|
||||
|
||||
if options.quit_after_inactivity > 0 then
|
||||
if show_thumbnail or activity_timer:is_enabled() then
|
||||
activity_timer:kill()
|
||||
end
|
||||
activity_timer:resume()
|
||||
end
|
||||
|
||||
if time == last_seek_time then return end
|
||||
last_seek_time = time
|
||||
if not spawned then spawn(time) end
|
||||
request_seek()
|
||||
if not file_timer:is_enabled() then file_timer:resume() end
|
||||
end
|
||||
|
||||
local function watch_changes()
|
||||
if not dirty or not properties["video-out-params"] then return end
|
||||
dirty = false
|
||||
|
||||
local old_w = effective_w
|
||||
local old_h = effective_h
|
||||
|
||||
calc_dimensions()
|
||||
|
||||
local vf_reset = vf_string(filters_reset)
|
||||
local rotate = properties["video-rotate"] or 0
|
||||
|
||||
local resized = old_w ~= effective_w or
|
||||
old_h ~= effective_h or
|
||||
last_vf_reset ~= vf_reset or
|
||||
(last_rotate % 180) ~= (rotate % 180) or
|
||||
par ~= last_par
|
||||
|
||||
if resized then
|
||||
last_rotate = rotate
|
||||
info(effective_w, effective_h)
|
||||
elseif last_has_vid ~= has_vid and has_vid ~= 0 then
|
||||
info(effective_w, effective_h)
|
||||
end
|
||||
|
||||
if spawned then
|
||||
if resized then
|
||||
-- mpv doesn't allow us to change output size
|
||||
local seek_time = last_seek_time
|
||||
run("quit")
|
||||
clear()
|
||||
spawned = false
|
||||
spawn(seek_time or mp.get_property_number("time-pos", 0))
|
||||
file_timer:resume()
|
||||
else
|
||||
if rotate ~= last_rotate then
|
||||
run("set video-rotate "..rotate)
|
||||
end
|
||||
local vf_runtime = vf_string(filters_runtime)
|
||||
if vf_runtime ~= last_vf_runtime then
|
||||
run("vf set "..vf_string(filters_all, true))
|
||||
last_vf_runtime = vf_runtime
|
||||
end
|
||||
end
|
||||
else
|
||||
last_vf_runtime = vf_string(filters_runtime)
|
||||
end
|
||||
|
||||
last_vf_reset = vf_reset
|
||||
last_rotate = rotate
|
||||
last_par = par
|
||||
last_has_vid = has_vid
|
||||
|
||||
if not spawned and not disabled and options.spawn_first and resized then
|
||||
spawn(mp.get_property_number("time-pos", 0))
|
||||
file_timer:resume()
|
||||
end
|
||||
end
|
||||
|
||||
local function update_property(name, value)
|
||||
properties[name] = value
|
||||
end
|
||||
|
||||
local function update_property_dirty(name, value)
|
||||
properties[name] = value
|
||||
dirty = true
|
||||
if name == "tone-mapping" then
|
||||
last_tone_mapping = nil
|
||||
end
|
||||
end
|
||||
|
||||
local function update_tracklist(name, value)
|
||||
-- current-tracks shim
|
||||
for _, track in ipairs(value) do
|
||||
if track.type == "video" and track.selected then
|
||||
properties["current-tracks/video"] = track
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function sync_changes(prop, val)
|
||||
update_property(prop, val)
|
||||
if val == nil then return end
|
||||
|
||||
if type(val) == "boolean" then
|
||||
if prop == "vid" then
|
||||
has_vid = 0
|
||||
last_has_vid = 0
|
||||
info(effective_w, effective_h)
|
||||
clear()
|
||||
return
|
||||
end
|
||||
val = val and "yes" or "no"
|
||||
end
|
||||
|
||||
if prop == "vid" then
|
||||
has_vid = 1
|
||||
end
|
||||
|
||||
if not spawned then return end
|
||||
|
||||
run("set "..prop.." "..val)
|
||||
dirty = true
|
||||
end
|
||||
|
||||
local function file_load()
|
||||
clear()
|
||||
spawned = false
|
||||
real_w, real_h = nil, nil
|
||||
last_real_w, last_real_h = nil, nil
|
||||
last_tone_mapping = nil
|
||||
last_seek_time = nil
|
||||
if info_timer then
|
||||
info_timer:kill()
|
||||
info_timer = nil
|
||||
end
|
||||
|
||||
calc_dimensions()
|
||||
info(effective_w, effective_h)
|
||||
end
|
||||
|
||||
local function shutdown()
|
||||
run("quit")
|
||||
remove_thumbnail_files()
|
||||
if os_name ~= "windows" then
|
||||
os.remove(options.socket)
|
||||
os.remove(options.socket..".run")
|
||||
end
|
||||
end
|
||||
|
||||
local function on_duration(prop, val)
|
||||
allow_fast_seek = (val or 30) >= 30
|
||||
end
|
||||
|
||||
mp.observe_property("current-tracks/video", "native", function(name, value)
|
||||
if pre_0_33_0 then
|
||||
mp.unobserve_property(update_tracklist)
|
||||
pre_0_33_0 = false
|
||||
end
|
||||
update_property(name, value)
|
||||
end)
|
||||
|
||||
mp.observe_property("track-list", "native", update_tracklist)
|
||||
mp.observe_property("display-hidpi-scale", "native", update_property_dirty)
|
||||
mp.observe_property("video-out-params", "native", update_property_dirty)
|
||||
mp.observe_property("video-params", "native", update_property_dirty)
|
||||
mp.observe_property("vf", "native", update_property_dirty)
|
||||
mp.observe_property("tone-mapping", "native", update_property_dirty)
|
||||
mp.observe_property("demuxer-via-network", "native", update_property)
|
||||
mp.observe_property("stream-open-filename", "native", update_property)
|
||||
mp.observe_property("macos-app-activation-policy", "native", update_property)
|
||||
mp.observe_property("current-vo", "native", update_property)
|
||||
mp.observe_property("video-rotate", "native", update_property)
|
||||
mp.observe_property("path", "native", update_property)
|
||||
mp.observe_property("vid", "native", sync_changes)
|
||||
mp.observe_property("edition", "native", sync_changes)
|
||||
mp.observe_property("duration", "native", on_duration)
|
||||
|
||||
mp.register_script_message("thumb", thumb)
|
||||
mp.register_script_message("clear", clear)
|
||||
|
||||
mp.register_event("file-loaded", file_load)
|
||||
mp.register_event("shutdown", shutdown)
|
||||
|
||||
mp.register_idle(watch_changes)
|
||||
3927
mpv/shaders/ArtCNN_C4F32.glsl
Normal file
3927
mpv/shaders/ArtCNN_C4F32.glsl
Normal file
File diff suppressed because it is too large
Load Diff
418
mpv/shaders/nnedi3-nns128-win8x4.hook
Normal file
418
mpv/shaders/nnedi3-nns128-win8x4.hook
Normal file
@@ -0,0 +1,418 @@
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//!DESC NNEDI3 (double_y, nns128, win8x4)
|
||||
//!HOOK LUMA
|
||||
//!BIND HOOKED
|
||||
//!SAVE nnedi3_int
|
||||
//!WHEN HOOKED.h OUTPUT.h / 0.707106 <
|
||||
float nnedi3(vec4 samples[8]) {
|
||||
float sum = 0.0, sumsq = 0.0;
|
||||
for (int i = 0; i < 8; i++) {
|
||||
sum += dot(samples[i], vec4(1.0));
|
||||
sumsq += dot(samples[i], samples[i]);
|
||||
}
|
||||
float mstd0 = sum / 32.0;
|
||||
float mstd1 = sumsq / 32.0 - mstd0 * mstd0;
|
||||
float mstd2 = mix(0.0, inversesqrt(mstd1), mstd1 >= 1.192092896e-7);
|
||||
mstd1 *= mstd2;
|
||||
float vsum = 0.0, wsum = 0.0, sum1, sum2;
|
||||
#define T(x) intBitsToFloat(x)
|
||||
#define W(i,w0,w1,w2,w3) dot(samples[i],vec4(T(w0),T(w1),T(w2),T(w3)))
|
||||
#define WS(w0,w1) sum1 = exp(sum1 * mstd2 + T(w0)); sum2 = sum2 * mstd2 + T(w1); wsum += sum1; vsum += sum1*(sum2/(1.0+abs(sum2)));
|
||||
sum1=W(0,-1106336704,-1104338237,1041734649,-1112016931)+W(1,-1134422686,-1108550970,-1135080854,-1117701445)+W(2,-1097058997,1036063029,1053379177,-1099451832)+W(3,-1096794255,1068454954,1068510503,-1092648385)+W(4,-1096428577,1045547931,-1114733521,-1101312270)+W(5,-1108910446,-1102009308,-1146436468,-1118387353)+W(6,-1110459731,-1122481515,-1107441476,-1118789516)+W(7,-1101174078,1017740065,-1113618698,-1107281979);sum2=W(0,-1107960738,1034572820,-1105088633,-1147785184)+W(1,1022891960,1003346080,-1103397515,1035529310)+W(2,-1112828174,-1096749055,1056062200,-1105585021)+W(3,-1099542471,1067566060,-1127174872,1034766166)+W(4,1028527356,-1090311143,1048792675,-1117109292)+W(5,-1124169384,1028295012,-1106700271,-1116900804)+W(6,1003609248,-1101382023,1033154740,-1121486356)+W(7,1019646072,-1102277943,1037356874,-1114899026);WS(-1075683047,-1087125913);
|
||||
sum1=W(0,1042687663,1052977914,-1087267578,1041384601)+W(1,1034752002,1046022844,-1097639380,1034807969)+W(2,1020877136,1051043629,-1087388173,1037740431)+W(3,1043598702,1049374510,-1095656786,1044538321)+W(4,1032834596,1044576234,-1108370107,-1113942663)+W(5,1049059763,-1108783446,-1101488315,1043415765)+W(6,1041786741,-1105784362,-1111228387,1011031587)+W(7,1050972591,-1089957133,-1108747496,1034104676);sum2=W(0,-1129327146,-1112916736,-1109246006,-1168639863)+W(1,-1149557934,-1120018795,1012425107,-1122303521)+W(2,1027469999,-1105442406,1044505132,-1114911422)+W(3,-1116270499,1056936993,1054092693,-1109477794)+W(4,-1107094547,1036431709,1015080154,-1122292075)+W(5,-1114668504,1029410453,-1102188513,1038663029)+W(6,-1136313139,-1126491682,-1123974759,-1124857486)+W(7,-1115408970,-1112281372,-1115235380,1004657207);WS(1042212664,-1102203684);
|
||||
sum1=W(0,-1140902818,1040147851,1035472140,-1111794429)+W(1,1019874102,-1104962202,1045102086,1033944684)+W(2,-1138465404,-1102798136,1044852023,-1122108180)+W(3,1041713132,-1085739950,1052255697,1042129278)+W(4,1031911135,-1090423514,1050093153,1026181805)+W(5,1032244040,-1096835716,-1114874577,1045351411)+W(6,-1122713961,1015091005,-1125530488,1045226448)+W(7,1032066151,-1100137137,1025859399,1037723887);sum2=W(0,1025219442,-1109152196,1026944460,-1136900198)+W(1,-1119436548,-1122141349,1040314652,-1112897189)+W(2,1041363772,1032935700,-1124096755,-1144192892)+W(3,1026037858,-1095545125,-1132954458,1046665648)+W(4,-1106963956,1029288712,1063106013,-1112667488)+W(5,-1148187164,1048235476,1044093468,-1091150222)+W(6,-1115265228,1017807431,-1119277141,-1098670428)+W(7,1027834104,-1124373883,-1115291573,-1099776205);WS(-1106435384,1038338229);
|
||||
sum1=W(0,1040095954,1057302312,-1085504617,1038469973)+W(1,1019822615,1048464174,-1109673285,1008999077)+W(2,1037825128,1048602738,-1088007186,1047759857)+W(3,1041126536,1046177110,-1089584127,1042217259)+W(4,1042659628,-1113571175,-1112427435,-1122205838)+W(5,1046281616,1010729037,-1099904421,1042535855)+W(6,1025627498,-1116720143,985851280,1020820192)+W(7,1052688116,-1090676327,-1109333660,1034203799);sum2=W(0,1016257202,1059204215,1078138204,1045786159)+W(1,1025056091,1059357388,1057901024,-1115583727)+W(2,-1123344133,-1096239491,-1075026282,1040463834)+W(3,-1117490597,-1080318626,-1073900782,1043123901)+W(4,-1139226916,-1097775023,1041808545,1021989454)+W(5,-1121712633,-1121076469,1040778731,-1105966927)+W(6,1032149092,-1108589001,1040543247,1015040126)+W(7,1018740994,1042934709,1013253724,-1147555881);WS(-1079558823,-1098708322);
|
||||
sum1=W(0,-1107155318,-1102044491,-1157836704,1018716763)+W(1,1025234303,-1098872409,1050456336,1032647774)+W(2,1015859078,-1087610848,1055919296,1043448582)+W(3,1036194249,-1086405173,1051086989,1041211303)+W(4,-1109510417,1049149960,1049231261,1032229161)+W(5,-1106597869,-1113006787,1047976577,-1113988824)+W(6,-1106784003,1034815041,1037659280,-1114873522)+W(7,-1107821257,-1109243348,1045770027,-1115826050);sum2=W(0,-1115121954,1038073794,-1128914993,-1116577465)+W(1,1012713185,-1114116718,1041575276,-1124395325)+W(2,-1120959275,1048906430,1074552079,1055266270)+W(3,979525395,-1089285214,-1076455267,1060162115)+W(4,1031308048,1044939824,-1081125046,-1098098687)+W(5,1023425822,960279117,-1109266711,1021768571)+W(6,1008898041,-1114246838,1028966618,-1124862202)+W(7,1015643115,-1116674868,-1116558128,1013382601);WS(1045132600,-1120782135);
|
||||
sum1=W(0,-1105751784,1057393815,-1105555137,-1117651397)+W(1,-1105178898,1048859946,-1097544977,1030868229)+W(2,-1104184899,1059464001,-1093321826,-1113548192)+W(3,-1114219853,1046945589,-1096850414,-1114482291)+W(4,-1110381909,-1115358437,1045680426,-1100710867)+W(5,1038688878,-1101266388,1054674458,-1101910270)+W(6,-1129240105,1006928425,1040711722,-1109195062)+W(7,1028338913,1001553277,1051440502,-1106616547);sum2=W(0,1017265392,1041015042,-1100279165,1015388608)+W(1,-1109811903,1031690548,-1110095441,-1118750728)+W(2,1023756444,1041543835,-1121800962,1018680528)+W(3,-1113627340,1061785433,1052269299,-1143924414)+W(4,1014378799,-1112539854,1027655784,-1099334823)+W(5,-1145950526,1033767962,-1103181542,1020584168)+W(6,-1129429444,-1111764061,-1110834939,-1108053853)+W(7,1013677319,-1098545742,-1106577514,1036964648);WS(1052573852,-1122511817);
|
||||
sum1=W(0,-1122539822,-1107197216,-1123108403,1051517474)+W(1,1036520122,-1104137920,1038549849,1023654291)+W(2,-1150669710,-1095755763,1032946604,1039184399)+W(3,-1131456914,-1089160552,1050538028,1041388597)+W(4,1027717464,-1090293588,1052989852,-1168884669)+W(5,1032118773,-1090056564,1057974832,1033029075)+W(6,1021054902,-1092174087,1053464075,1028526105)+W(7,1030809195,-1086001910,1057808582,1041880934);sum2=W(0,-1085894681,-1108201039,1070882268,-1081052443)+W(1,1038192816,-1090848333,-1093216289,-1102549623)+W(2,-1098445483,1052221636,1067999858,-1087793608)+W(3,-1102898046,1071505414,1073865984,-1090403840)+W(4,1008806191,-1098981857,1058878464,-1095780376)+W(5,1050638036,-1086351349,-1083525828,1055133376)+W(6,-1102617523,-1096799400,-1107159037,-1096503933)+W(7,1057325981,-1088620184,-1083206959,1053790412);WS(-1073219892,-1080326418);
|
||||
sum1=W(0,-1114077580,-1101602915,1057495924,-1151047116)+W(1,-1142635506,-1103425331,1053716920,-1114784094)+W(2,-1142955026,-1090278522,1055741332,-1111276924)+W(3,-1123237842,-1092662145,1051447237,-1121668701)+W(4,1038107057,-1091646784,1052494629,1000704387)+W(5,-1103324917,-1114692451,1049044089,-1109204280)+W(6,1026598572,-1101848592,1043005848,1010568075)+W(7,-1095875035,1038718196,1047828379,-1156952092);sum2=W(0,-1121663397,-1095443331,-1067370736,1005231721)+W(1,-1116542136,1050195534,-1071776975,974104521)+W(2,1042431779,-1123573301,1068672794,-1111985184)+W(3,1037730633,-1100504352,1077012119,1047585075)+W(4,1010053773,1043186658,1070664889,1016528922)+W(5,-1137348615,-1102861372,1045361006,-1109020232)+W(6,1028087910,-1110454800,-1123945395,1037668055)+W(7,-1119025600,1040229501,1027642294,-1117277443);WS(-1130027456,1047744266);
|
||||
sum1=W(0,1030328637,-1103440100,1050534604,-1130350917)+W(1,-1100312969,1043447132,1038395889,-1105733872)+W(2,1036569044,-1096543805,1037345619,1043114871)+W(3,1044449278,-1093151398,-1106526388,1022399622)+W(4,-1106699970,1024264999,-1115006287,1020228332)+W(5,1046212150,-1115860524,1035372917,1024836117)+W(6,-1104762293,1041344218,980910400,-1123108872)+W(7,-1124975021,1032410566,1044066628,-1112803412);sum2=W(0,1029880722,1033391383,-1137819024,-1114516031)+W(1,-1098453144,1041649400,-1137377888,1025620716)+W(2,1029103498,-1095624145,1040796761,1035240799)+W(3,1067660000,-1082091368,-1080643124,1066795978)+W(4,-1094604015,1056223691,-1102259819,-1098376459)+W(5,1046293202,1027973488,-1121978412,1036814117)+W(6,-1104816365,1034193475,-1148596400,-1107858514)+W(7,-1117927817,1034286113,1041009105,-1114981924);WS(1049012636,1037011386);
|
||||
sum1=W(0,-1108102978,-1097922903,1049818257,1041216474)+W(1,1042768739,-1089977373,1052134241,-1106782690)+W(2,1036457352,-1083790961,1059747641,-1120768141)+W(3,-1105146600,1050515995,1062551839,975424142)+W(4,-1100621772,1053649082,-1088576433,1042971413)+W(5,-1100160944,1044221701,-1093385002,1047421135)+W(6,-1149100234,1020595485,-1108848982,-1142399358)+W(7,-1116535239,-1110188826,-1147628986,1034144007);sum2=W(0,-1130376652,-1109271051,-1098570547,1029552052)+W(1,-1109307779,1040605589,-1097221185,-1097745138)+W(2,998991648,-1117670218,-1087670872,-1101762859)+W(3,-1105231849,1068278024,1068017963,-1100990121)+W(4,-1124853008,-1099193318,-1103240593,-1094879980)+W(5,-1110904873,1035466738,1049832589,-1119653306)+W(6,1033926100,-1111928806,1018913792,-1099498770)+W(7,1012787248,1025845624,1035573068,1046656503);WS(-1099128120,1074104605);
|
||||
sum1=W(0,1001695642,1031876531,-1106225286,1039516460)+W(1,-1114738061,1036082771,-1127447088,1037331996)+W(2,-1137881464,1049670772,-1114090766,1048871226)+W(3,1035838167,1045634202,-1084335000,1024672505)+W(4,1036976671,1039176783,-1092101927,-1111706306)+W(5,1043227732,1044499416,-1106295064,1040216275)+W(6,1024532056,-1115296143,-1108352670,1018355325)+W(7,1041576607,1036111714,-1103209586,-1129216251);sum2=W(0,-1125983803,1057121124,-1097673861,-1097055530)+W(1,1026289226,1048908439,-1081617292,-1105528539)+W(2,1003361806,1042597022,-1083990029,-1094090339)+W(3,1036989304,-1101738899,1066557847,1060807350)+W(4,-1121376018,-1101518001,1050089807,1045798092)+W(5,-1127516251,-1114490175,1021212715,1007168711)+W(6,999276462,1032222895,-1107462587,1021142275)+W(7,1020382491,-1111061815,1048167829,1024157832);WS(1043392312,-1114334171);
|
||||
sum1=W(0,1041086874,1046571639,-1101297859,-1108043111)+W(1,1027676176,1051603231,-1100311555,1031499310)+W(2,1029494548,-1114765098,-1090719068,-1123479337)+W(3,1038182418,1063881062,-1092551191,1047470620)+W(4,1033375641,1036439434,-1093343060,1029157954)+W(5,1014428948,1039261900,-1095549099,-1113522785)+W(6,1016176348,1049353410,-1102133676,1032866554)+W(7,1036956537,1039119196,-1097401399,-1108903402);sum2=W(0,1032922039,-1110774431,1024080221,-1111786600)+W(1,1034144522,1041464609,1024001520,1038622987)+W(2,1035186417,-1089347840,-1102975683,-1098326560)+W(3,-1106146153,1063858171,1062496232,-1094555153)+W(4,995983013,-1103182741,-1104694448,-1110476474)+W(5,1014708981,-1105498679,1034761930,-1107944280)+W(6,-1118508182,1046443094,-1113235807,1045574278)+W(7,-1122673776,-1107403517,-1126790312,-1119406695);WS(1055141020,1060902337);
|
||||
sum1=W(0,1034435725,1057965143,-1123568702,-1104499136)+W(1,-1133288704,1052483105,-1121795134,1006999415)+W(2,1026181508,1052696320,-1094115828,-1153162900)+W(3,1033934442,-1122504460,-1084201687,1029709087)+W(4,1030709219,1052884304,-1093347107,1036285529)+W(5,-1118188821,1049027177,-1096042081,-1155692311)+W(6,1027652318,1046782257,-1098441692,1013713298)+W(7,1035419593,1045790650,-1101051195,-1111952258);sum2=W(0,1043194323,-1070666261,-1098866335,-1101126135)+W(1,1017945729,-1075189642,-1106608294,1010301074)+W(2,992756489,1068575013,1051129947,-1107911121)+W(3,-1117717167,1076566585,1049134123,1046700061)+W(4,1023440269,1056539999,1047751107,1020103457)+W(5,-1108161809,-1098049115,-1097073139,1026363561)+W(6,1034607052,1036076910,1011007330,1035420194)+W(7,-1115924363,-1112346970,1016205049,-1137869730);WS(-1090579868,1070279725);
|
||||
sum1=W(0,1032329895,1048430680,-1101560157,-1129281319)+W(1,-1102328821,1050349544,-1091335294,1012204235)+W(2,-1113203900,1052980239,1039656780,1033674783)+W(3,-1098061089,1057014372,-1084573078,-1115372202)+W(4,-1105344998,1057962188,-1103450436,-1108117804)+W(5,1034205973,1038273502,1043587871,-1111454739)+W(6,-1106552005,1046276062,-1098888483,-1115265901)+W(7,1041435478,1049777060,1002064136,-1109943484);sum2=W(0,987673807,1027892228,-1103141235,1005138532)+W(1,1036995374,-1102736131,1049007178,1028221332)+W(2,-1095509641,1034852634,-1090760003,-1123669832)+W(3,-1094252408,1059241808,1060311666,-1128511149)+W(4,-1119095571,-1103859919,-1129798465,1032914452)+W(5,-1103179232,1043446486,-1100012675,1006285508)+W(6,1040985329,-1109795439,1051746582,-1122773902)+W(7,-1114181285,1004807604,-1113144024,987177167);WS(1058381774,-1086956646);
|
||||
sum1=W(0,1005434106,-1096145742,1046241393,1026532260)+W(1,-1149835360,-1100460324,1039571170,-1120107684)+W(2,1034370117,-1096424577,1054608457,-1107524072)+W(3,1036055789,1033532617,-1110152984,-1123297125)+W(4,1007595428,1049990129,-1100950084,1032832748)+W(5,-1173712576,1042033667,-1103984787,1041584782)+W(6,-1122685332,-1147483724,-1122634471,-1111048693)+W(7,-1119060568,1021597150,1016207588,1023439817);sum2=W(0,1073050559,1049113865,1048373410,-1123382260)+W(1,1069067455,1035642194,-1101089925,1035361564)+W(2,-1096535796,-1105600932,1050248373,-1105239942)+W(3,-1073893027,-1114871718,-1113393188,1000972215)+W(4,-1077684470,-1104998692,1015693919,-1112223483)+W(5,1038335059,1034875990,1032989733,987872957)+W(6,994568047,1004288083,1024635942,1016564448)+W(7,-1109196141,1019116562,1041247426,1019016937);WS(1051792028,1027146209);
|
||||
sum1=W(0,-1173418992,-1096555104,1048715847,1037767898)+W(1,1031492470,-1099279313,1043543405,1032372106)+W(2,1030866682,-1102472206,1045948678,1031937048)+W(3,-1111745573,-1086728512,1048944276,1030986133)+W(4,1037975597,-1098029143,1053562136,1035090980)+W(5,1032231158,-1099704976,1041023999,1038793940)+W(6,1021051177,-1107704157,1031959404,1031982829)+W(7,1029296729,-1088435526,1046674105,1043937550);sum2=W(0,1076285256,-1071495861,-1089164092,1024798548)+W(1,1067013205,-1080654015,1044446905,-1130255717)+W(2,1054912747,-1092768710,-1089831336,-1111620633)+W(3,-1103468782,1053690657,1049463752,-1129289568)+W(4,-1082179927,1062196550,-1116071286,1022374674)+W(5,-1086354611,1059230433,1055604285,-1147177200)+W(6,-1086555076,1065208788,-1102169042,1008723412)+W(7,-1077304359,1069826015,1049830695,990531682);WS(-1116843232,1041538044);
|
||||
sum1=W(0,1038718416,1050813118,-1091780513,-1107356403)+W(1,1041393778,1048646402,-1107072481,1032833522)+W(2,1023355030,1043671731,-1097953353,-1126022145)+W(3,1040958951,1037057641,-1088265503,-1185162751)+W(4,1040537034,1050123337,-1105750724,1038008293)+W(5,-1112360254,1052799074,-1091053114,-1123581176)+W(6,1043346413,1037436293,-1121572392,1033129910)+W(7,1047211822,1042212684,-1091261766,-1116284746);sum2=W(0,-1127892588,-1090048491,-1076486023,1071993665)+W(1,1025248710,-1124324076,-1080184847,1067215194)+W(2,-1127740272,-1092974499,-1080442855,1068762214)+W(3,-1114879615,1047668544,1048567939,1014309155)+W(4,-1125515678,1042122418,1066323214,-1079656754)+W(5,-1135605467,1052455522,1068938556,-1077318729)+W(6,1015277154,-1102075660,1066205534,-1083078137)+W(7,-1118452308,1052515578,1058048535,-1086246531);WS(1045082936,1047750074);
|
||||
sum1=W(0,1017867382,1038967959,-1107005280,-1117189504)+W(1,-1105827232,1036533543,-1101431328,1000061951)+W(2,-1139557912,1048524561,1044741561,1034808454)+W(3,-1098507795,1057427781,-1099209723,-1102176472)+W(4,-1112138258,1057555836,-1103886606,-1102736460)+W(5,-1113781499,1044700722,-1117912777,-1102956733)+W(6,-1117154624,1037485187,-1108908881,-1113728179)+W(7,1024003356,1046059755,1024367918,-1108156515);sum2=W(0,1003184961,1024857236,-1114215978,1037587704)+W(1,971431442,-1109323954,1030818718,-1121823736)+W(2,-1131894760,1026446282,1031262679,1045339410)+W(3,-1133283297,-1105665514,1056963612,-1107079097)+W(4,984723076,-1116186208,1055283667,-1090072253)+W(5,1031831407,1024492508,975724297,-1102678968)+W(6,-1125590160,-1121629964,-1116339968,-1103014356)+W(7,1031681833,-1148808497,1026784592,-1123463096);WS(1059869006,1015916977);
|
||||
sum1=W(0,-1111801867,-1103727218,1051877295,-1115491581)+W(1,1039164638,-1102716146,1051739903,-1106752078)+W(2,1023424768,-1089648586,1057614174,-1104830517)+W(3,-1118862224,-1092420393,1055627629,-1112797325)+W(4,-1114194639,1049092536,-1096079006,1038662167)+W(5,-1099094340,1052180160,1008315659,1030088557)+W(6,-1118811114,1032231232,-1121275805,-1131680577)+W(7,-1096321008,1046058153,1039975892,-1175801754);sum2=W(0,-1113427160,-1090644207,1034414883,1038986783)+W(1,-1104433368,-1091764889,-1120815960,-1135559136)+W(2,-1104169884,-1109333336,995253792,1033390214)+W(3,-1117600576,1065407690,1059846520,-1120264784)+W(4,-1102319880,-1098732665,1048874179,-1104270640)+W(5,1039627671,-1109931470,1008884504,1019376128)+W(6,-1097619580,1043714297,1021072320,-1111461786)+W(7,1047721667,1041133481,-1103318888,-1142244432);WS(1054131356,-1077482588);
|
||||
sum1=W(0,-1100136045,-1101215881,1045307006,1047064142)+W(1,989703980,-1100083265,1039854844,-1120855287)+W(2,-1114161471,-1091699940,1051542530,1042850313)+W(3,-1117800461,-1088812180,1056393300,-1122501592)+W(4,1013262449,-1095974704,1053327664,-1118254671)+W(5,-1112319975,1033042241,1059113280,-1111473941)+W(6,1027862775,-1095224480,1049428707,-1119385054)+W(7,-1103330903,-1102789769,1055440053,-1109190398);sum2=W(0,-1098032416,1063396296,1043414797,-1093635160)+W(1,1055692800,1024719031,1032661901,1049215120)+W(2,-1101668743,1065491656,1058961916,-1090478816)+W(3,-1100435053,1073645059,1063424749,1050905898)+W(4,-1089098280,1060161647,-1096580753,-1135528507)+W(5,-1094416925,-1074198531,-1098776178,1042380471)+W(6,-1099202751,-1081296593,-1115458644,1032695397)+W(7,-1104551065,-1083400329,-1092624053,1054277265);WS(-1082679118,-1072338335);
|
||||
sum1=W(0,-1126832308,-1092407662,1041636256,1032452512)+W(1,998650886,-1099976035,1035459839,-1118647007)+W(2,1029713605,-1098757312,1053507448,-1113994637)+W(3,1045660229,1049242330,-1097348797,1019901759)+W(4,-1125245511,1052609817,-1097111418,1026546307)+W(5,1001090478,1049104969,-1099322690,1041545965)+W(6,-1126242526,958956607,-1116731426,-1113342195)+W(7,-1128346278,-1170516592,1009511091,1027607012);sum2=W(0,-1069228184,-1099529380,-1112044089,-1144476451)+W(1,-1073602631,1043301860,1041147606,-1112019052)+W(2,1021776922,1054858487,-1119872164,1036271953)+W(3,1076866983,1044685536,-1106846135,1018899191)+W(4,1069809281,1062109344,1042271976,-1114284680)+W(5,-1101499289,-1097491140,1035368326,-1126672913)+W(6,1013617559,-1149319294,1025827813,-1112053703)+W(7,1036050969,-1113127688,-1115137330,-1146921887);WS(-1125906880,1029353026);
|
||||
sum1=W(0,1052620124,-1082830235,1044570800,1033131793)+W(1,1040928385,-1087911853,1048894344,1031982257)+W(2,1053619569,-1088553290,1054767249,-1118254573)+W(3,1034478636,-1115166792,1052323270,1037418321)+W(4,-1149501032,-1104403058,-1096342700,1045103465)+W(5,1027228408,1046902211,-1092690897,1053685367)+W(6,1033816441,-1140598044,-1112660402,1032758420)+W(7,-1143379631,-1115398454,-1089842615,1056771243);sum2=W(0,1052242091,-1123374674,-1088438592,-1109756837)+W(1,-1105901664,1032004261,-1109896025,-1117902306)+W(2,1041713460,1057464262,-1106721416,-1106560728)+W(3,-1098081544,1055897675,1057898227,-1101499608)+W(4,-1101414896,-1108453649,1044097375,-1114554169)+W(5,-1140318759,-1099401944,1041656473,1042131382)+W(6,-1123485994,1039811869,1042751001,-1104786072)+W(7,-1108472633,-1092934450,1033994653,1048148308);WS(-1080878567,1068324028);
|
||||
sum1=W(0,-1115471279,-1095139206,1057833304,1032811018)+W(1,1019310859,-1103458412,1049561152,-1118469827)+W(2,-1121098697,-1090917913,1058273109,-1107876783)+W(3,-1115193805,-1094785898,1054221326,-1109399058)+W(4,-1153442440,-1100131090,1050583410,-1121957752)+W(5,-1104713039,-1118370765,1048985266,-1109945243)+W(6,1023975060,-1102569730,1041261354,-1125987028)+W(7,-1094675607,1044057356,1045920684,-1144681671);sum2=W(0,-1122597644,1052263517,1084267296,1037076324)+W(1,1032420914,-1132353885,1077171750,1017945885)+W(2,-1109997244,-1113437764,-1076080701,1045994672)+W(3,1029919127,-1086124512,-1066836895,-1105598049)+W(4,-1129031901,-1134522929,-1073829589,-1115453382)+W(5,1025876905,-1137529969,-1128728545,1027437378)+W(6,-1121404056,1041285329,-1128683125,-1112127416)+W(7,1025649559,-1111439550,-1109934248,1032857588);WS(-1106960696,-1099012034);
|
||||
sum1=W(0,-1114528403,-1099071342,1055554285,-1109121109)+W(1,-1119077260,-1099370430,1049964157,-1115766890)+W(2,-1143558020,-1089278443,1061104081,-1114965299)+W(3,-1119877760,-1086538844,1056629915,-1120868875)+W(4,-1109244232,1010994112,1049997315,1034547527)+W(5,-1096650748,1041376829,1042073805,-1114495407)+W(6,-1112604445,1042854492,1031563405,-1139584324)+W(7,-1100402892,1049345155,-1123516568,-1118254096);sum2=W(0,-1116593925,1027806287,1032648371,1024756439)+W(1,1028908115,-1136470458,1006654490,-1116529299)+W(2,999050165,1039840949,1052059722,-1107372324)+W(3,1037914955,-1122048333,1057985079,-1128153177)+W(4,-1106109711,1057135276,-1090440242,-1142966917)+W(5,-1105957739,-1105275062,-1131926605,-1123338691)+W(6,-1123834115,-1096566133,1018741845,1013415162)+W(7,-1113783754,-1105721601,-1124260101,1018182189);WS(-1103089976,1059868827);
|
||||
sum1=W(0,1026631887,-1091300264,1056895190,1031003956)+W(1,1033737723,-1096562704,1050565142,-1140469197)+W(2,1034000797,-1087537316,1059766350,-1108911023)+W(3,-1130496915,-1094386976,1053939124,1032926090)+W(4,-1106694966,1044429902,-1108577640,-1120892680)+W(5,-1105866475,1045093007,-1109922270,1034482579)+W(6,-1106727101,1040636078,-1122075862,-1136817768)+W(7,-1098705919,1044615672,-1100982776,1045052014);sum2=W(0,-1114832682,1044376552,1052671036,-1084839384)+W(1,1038307608,-1101986459,-1094811671,-1076225566)+W(2,-1109268272,1025272345,-1106762472,-1074779618)+W(3,1031259614,-1112738770,1052706603,-1088390497)+W(4,-1136199018,1014008179,1040752903,1066038403)+W(5,-1118450441,1042085570,-1100877636,1071357616)+W(6,1025376385,-1110075404,1051973899,1068318141)+W(7,-1125957173,1027010884,1036345951,1050587817);WS(-1089897038,998399462);
|
||||
sum1=W(0,-1100326508,-1114312802,1049930251,-1141222070)+W(1,-1099771006,-1109889234,1047140918,-1114407115)+W(2,-1103969415,-1092992143,1060325312,-1106384368)+W(3,1030998252,-1098209637,1062808044,1017922927)+W(4,-1111096702,-1116385180,-1128865717,1023432554)+W(5,-1129527451,-1096464604,1048691588,-1125954964)+W(6,-1115021151,-1111889198,-1137813989,-1121716413)+W(7,-1124899748,-1109224641,1043572929,1020452535);sum2=W(0,-1094975511,-1113696880,1023473326,1029862812)+W(1,-1089233591,1032844980,1036803698,-1117299445)+W(2,-1089977002,1066397244,-1129026618,1025970568)+W(3,1033778332,1037917830,-1104280508,1031377784)+W(4,1006981461,1039504138,1024702770,-1122944997)+W(5,-1137053176,1032622380,-1121975322,1022461928)+W(6,-1125132764,1021506052,974010432,-1130740686)+W(7,979684320,-1119563165,-1138205260,1024270227);WS(-1096120220,-1099720911);
|
||||
sum1=W(0,1052677544,-1105594052,-1101878153,990296621)+W(1,1027883172,1050583742,-1120505890,1026529890)+W(2,1046184634,1030711656,-1094174707,1039246623)+W(3,1036941212,1050761182,-1087347673,1031039363)+W(4,1037786724,1044997418,-1091299260,1038193547)+W(5,1039372749,1051859318,-1092171165,1036921611)+W(6,992842790,1041579690,-1105854769,-1115076484)+W(7,1040590154,1052858474,-1087724293,1007468831);sum2=W(0,1040381409,1023777345,-1110031849,1022623295)+W(1,-1131846701,-1095435966,-1146822820,-1096899181)+W(2,1030695069,-1111411494,-1089001391,1049343346)+W(3,1015259161,-1085163747,-1074171332,-1107180310)+W(4,1026868853,-1100600319,-1078760233,1043071461)+W(5,-1164136976,1052695808,1048168469,1020495459)+W(6,-1121164685,1041440525,1074132102,1017314953)+W(7,-1109936403,1051545155,1072577306,1050115198);WS(-1080112807,-1111145054);
|
||||
sum1=W(0,-1103297132,1049824404,-1133975251,1026400021)+W(1,-1106341774,1049617192,-1122989109,1042898005)+W(2,-1098278655,1059552348,-1086286580,1041608840)+W(3,1024154699,1031972225,-1137351813,-1145221295)+W(4,1037514093,-1085661228,1056970252,-1102084285)+W(5,1034961350,-1097823136,992708574,1041904442)+W(6,-1125780682,-1114326813,1021582000,1038246926)+W(7,-1109009483,-1119831648,1040424089,1042525799);sum2=W(0,1041258750,989910477,-1134607603,-1109794979)+W(1,-1109734283,-1100922013,1016064722,1041809078)+W(2,-1123542769,-1096844113,1041392492,-1126381362)+W(3,-1113561957,1051742866,1057819912,982123162)+W(4,-1110564237,-1100235579,1047439582,-1119465765)+W(5,1026811493,-1105813951,-1113868277,1026735929)+W(6,-1130694514,-1151284621,-1118083589,1019553626)+W(7,1024057869,-1136706867,-1114600003,-1114678252);WS(1043409720,-1105036943);
|
||||
sum1=W(0,1040191749,-1096303173,-1115184605,1041655059)+W(1,1033970558,-1095924673,1041748910,1041917006)+W(2,1042494496,-1093807736,1044442592,-1160531625)+W(3,1046767380,-1092831585,1042876074,1039311757)+W(4,972615552,-1096756208,-1140612185,1020654492)+W(5,1032778168,-1126846855,1018241414,1043700571)+W(6,1032217109,-1115229280,1027878365,1034107952)+W(7,1032356247,-1098580285,1034858676,1036396440);sum2=W(0,1027808259,-1139047739,986751832,-1095774205)+W(1,1010119787,1043340308,1026247831,-1093511024)+W(2,-1111510504,-1106790738,1065364148,-1089533357)+W(3,-1113418759,-1096910874,1040723354,1053173071)+W(4,1032132185,1040059331,1038861011,-1106558855)+W(5,-1121052855,-1115460243,-1113647147,1027584935)+W(6,1014515195,1017581734,1041604470,-1121443175)+W(7,1010692603,-1120741339,-1135975307,1014681515);WS(1035857520,1029952289);
|
||||
sum1=W(0,-1143077795,1037051011,-1110400621,-1121149466)+W(1,-1105351783,1029971495,-1106469910,1043652126)+W(2,-1113811952,1049064844,-1094483622,1027875988)+W(3,-1106526780,1035603988,1058276716,1035104701)+W(4,1035289215,-1083894414,1056346487,-1114346217)+W(5,999420801,-1098557596,1050633420,-1123554317)+W(6,-1129002434,-1111645039,1042325343,-1130799743)+W(7,-1113970285,-1130790920,1026109447,1025377311);sum2=W(0,-1118517607,1026484093,1039465846,1008581907)+W(1,-1101077931,1046485772,1030900361,-1114630284)+W(2,1029148161,-1098019518,1048118782,-1106945018)+W(3,-1087996420,1071267691,1064954318,-1097625455)+W(4,1047526016,-1082674625,-1084489705,-1156379726)+W(5,-1108756119,1032470282,-1118487613,1024110641)+W(6,1038718292,-1106613565,-1112021711,1020048570)+W(7,1024464693,-1113199029,-1120012731,1036291722);WS(1058189134,1034857672);
|
||||
sum1=W(0,-1171748679,1031241360,-1100969760,987174985)+W(1,-1105475825,1044072484,-1094075536,1045893176)+W(2,-1097172873,1057114388,-1082247827,1042860595)+W(3,-1108837708,1051374554,1060030327,1031954257)+W(4,1038034707,-1083662360,1058651386,-1120638978)+W(5,-1131134898,-1099379283,1046921459,-1137288661)+W(6,-1113151849,-1121036423,1041721673,1037681908)+W(7,-1119273967,1018101850,1036514264,1029972391);sum2=W(0,1003810984,1020569783,-1128982694,1043745048)+W(1,1036204547,-1114489126,-1099380876,-1104004872)+W(2,-1101998989,-1121260135,-1101918458,-1104165612)+W(3,1041029203,1052640914,1059611184,-1121067579)+W(4,-1098215637,1059150102,1040381797,-1100369008)+W(5,1044393168,-1098121773,-1094102036,1032515174)+W(6,-1110527635,1037147118,1028175839,-1114899975)+W(7,1027560485,-1110248773,-1113935142,1000033398);WS(-1107450480,1040804833);
|
||||
sum1=W(0,1040192716,1040473489,-1095196747,-1124855402)+W(1,1022226221,1047969017,-1098407451,1020416041)+W(2,1002013395,1044185574,-1087290490,-1160070647)+W(3,-1117682794,1060667554,-1089168888,1045737613)+W(4,1001040843,1057909434,-1111951852,-1101676720)+W(5,1000424795,1049088596,-1119291421,-1103624738)+W(6,-1120982404,1038016429,1031577591,-1104451167)+W(7,1025306833,1042416864,-1112956481,-1115902938);sum2=W(0,1014727333,-1124633329,1026257754,-1111611661)+W(1,-1117243126,-1107065949,-1111801245,-1136702760)+W(2,1029406572,1041729284,-1084100906,-1103677442)+W(3,1027900147,-1094200388,1052541581,1050798725)+W(4,-1112527674,-1104959017,1070744988,-1105828213)+W(5,-1114664521,1040214496,-1111707080,-1111536822)+W(6,-1111634336,1005029260,-1127513012,-1106506739)+W(7,-1107116047,1049039902,-1107038609,-1140667375);WS(-1113867888,1064515135);
|
||||
sum1=W(0,-1113562537,1048061265,1011269086,-1105945126)+W(1,-1107046062,1043460993,-1098944190,-1148623547)+W(2,-1103978495,1060048584,-1107431310,-1111558073)+W(3,-1098739202,1062873548,1045822761,-1114838028)+W(4,-1122423580,-1119786749,1025265092,-1101841139)+W(5,1019693149,1023528257,-1112998912,-1117915947)+W(6,-1116789880,-1106657727,-1142662356,-1106868487)+W(7,1020558520,-1137576074,-1104660585,-1122252061);sum2=W(0,-1145158406,1022878354,-1111624996,1010204019)+W(1,1012385731,-1129472106,1015658802,-1123973089)+W(2,1016118130,1044961455,1040055751,-1157676569)+W(3,1024197601,1049544336,1057430996,1022031298)+W(4,-1112179804,1030346877,-1114498280,-1124728962)+W(5,-1119519161,-1131221354,1020564842,1023003938)+W(6,-1127326042,-1095482557,-1112131584,-1121117277)+W(7,-1113792718,-1093377057,1019749938,-1141925830);WS(1051333020,-1087054195);
|
||||
sum1=W(0,-1112042433,-1104387605,1052246829,-1113527444)+W(1,1019002067,-1096771599,1048899277,-1098301717)+W(2,-1115058903,-1102529947,1054136106,-1095193948)+W(3,1046618143,-1093976551,1044227957,1044013586)+W(4,-1107874438,-1089735051,1060328029,-1107288943)+W(5,-1148774132,-1129150690,1046377228,1038700845)+W(6,1036768028,-1101876091,1045160291,1024370318)+W(7,-1154881470,-1098135714,1045432325,1019966234);sum2=W(0,-1114066012,1041392892,1044719218,-1097547793)+W(1,1029900262,-1112610934,1046575198,-1095644935)+W(2,-1114806697,1041587346,1050162797,-1102972970)+W(3,-1110038644,1025557898,1055420600,-1095936036)+W(4,1036646832,1055783298,-1099287148,1028020818)+W(5,-1110070018,-1102485451,-1100701871,-1113902766)+W(6,1020625547,988088600,1033323822,-1135974783)+W(7,987867800,1039502616,-1119304428,1018696751);WS(-1120103648,-1090070191);
|
||||
sum1=W(0,-1117418940,1049030490,-1112262737,-1114427969)+W(1,1024592611,1050801054,-1094705236,1032013281)+W(2,1040968250,-1111205267,1042055990,-1110419822)+W(3,1049918615,-1116228463,-1085341341,1047944497)+W(4,1034410595,1050512309,-1106227665,-1132367051)+W(5,1035134604,-1102511675,1036298997,1025392341)+W(6,-1119948353,1034763283,-1138448657,-1111046724)+W(7,-1144523437,1039656998,-1110564136,-1120201127);sum2=W(0,-1122606938,1046354401,-1124762815,-1118515993)+W(1,-1141997982,1040228902,-1102583710,1036845124)+W(2,1027805544,-1143835982,1052785838,-1106443071)+W(3,-1120462650,1061896257,1059397472,1043676745)+W(4,-1100560083,-1080731069,-1120768779,995709275)+W(5,-1105726471,-1098049024,-1126645315,-1128858827)+W(6,1025575588,1026943708,1011421951,-1112152255)+W(7,-1113668318,1032253740,-1122685018,-1127110207);WS(1060158670,1068766623);
|
||||
sum1=W(0,-1116432453,1056712636,-1087151539,1040295867)+W(1,-1131098839,1049784895,-1102593034,1033948341)+W(2,-1099753724,1057908127,-1089291740,1031077093)+W(3,1034945056,1044163070,-1094800699,1027113355)+W(4,-1122123599,1028198895,1036808107,-1132674679)+W(5,1040823512,-1122504371,-1120242995,-1117547229)+W(6,1040184285,-1123329903,-1127465369,1040274980)+W(7,1050332416,-1096645803,-1132187055,-1137741501);sum2=W(0,1036379663,-1098232449,-1128107780,-1120677803)+W(1,-1108907739,1058983203,1035811659,-1120240179)+W(2,1070189048,1016986873,1040144345,1029686139)+W(3,1073213180,1047923452,-1105399966,-1109097268)+W(4,1065321765,1033582270,-1110681209,1041308319)+W(5,-1076673488,1031365639,1039880527,-1109042515)+W(6,-1079893128,1038048757,-1116001167,1034493417)+W(7,-1072585926,-1107019906,1018297481,-1131123922);WS(-1112459888,1031046963);
|
||||
sum1=W(0,-1112719265,-1128634346,1043326546,-1115081924)+W(1,-1129483154,-1120462421,-1103778738,-1114915140)+W(2,-1103727283,-1112785958,1050524372,-1104237825)+W(3,-1091575740,1056781779,1067939282,-1096588493)+W(4,-1104335643,-1153409228,1048587330,-1108534894)+W(5,-1155155940,-1108013960,-1132710977,-1114726045)+W(6,-1114094348,-1118230989,-1109505653,991235804)+W(7,-1105426861,1027667442,1036777787,-1111746006);sum2=W(0,-1119086167,1037241732,-1114652243,-1131518324)+W(1,1013020612,-1129818230,1028260797,-1115730540)+W(2,-1141008560,1029187991,-1112264831,1036245214)+W(3,-1108719150,-1074141953,1072760747,1034705438)+W(4,1023891147,1019083994,1042535682,-1119172530)+W(5,-1145112744,-1124211508,-1131878972,-1133917220)+W(6,1018251990,-1122886966,1037493286,-1114007324)+W(7,-1116478859,1027168441,-1129254230,1018465006);WS(-1086783566,-1086791567);
|
||||
sum1=W(0,-1115195632,-1095708330,-1123676804,1041725033)+W(1,-1153026662,-1093442522,1018199561,-1121101892)+W(2,-1134496297,-1098161001,1037878573,1034570216)+W(3,-1108787789,1044632085,1064261167,-1103584185)+W(4,-1119803561,-1091375169,1057417647,-1108866704)+W(5,-1145121243,-1107384199,1052226946,-1122033784)+W(6,-1131708777,-1100078210,1046948682,-1117964907)+W(7,-1110064394,-1104664012,1047330733,1022321300);sum2=W(0,1031515378,-1077397139,-1134939312,-1112896962)+W(1,-1121810184,-1079753374,-1097085111,1035985281)+W(2,1010081392,1044674665,1052841311,-1105060263)+W(3,-1119765868,1073378801,1007836336,1031953140)+W(4,1035546479,1056367001,1044809025,1022446080)+W(5,-1106495935,-1109376902,-1118570548,1031289566)+W(6,1028378344,1035615024,992033726,1032016077)+W(7,1003402623,-1118889676,1010750288,-1150317246);WS(-1096711324,-1080143969);
|
||||
sum1=W(0,-1135181951,-1095339398,1050582337,1026786373)+W(1,1025399430,-1094144146,1049483953,-1123204644)+W(2,1033906501,-1093853897,1045129706,1006467326)+W(3,1041786535,-1089314149,1046728732,1031608549)+W(4,-1133559462,-1089126233,1045641984,-1135165794)+W(5,1003671004,-1110956839,1051092970,1017185520)+W(6,-1123695637,-1129083412,1049638101,996324016)+W(7,-1105366874,-1113909272,1057307443,1009923752);sum2=W(0,1023911567,-1108118447,1044892126,-1112738860)+W(1,1004932796,-1134375038,-1138359022,1020475455)+W(2,-1119124867,1035251904,1063133445,-1102926770)+W(3,1022775023,1037995724,1074655410,1047698054)+W(4,1011639102,1050162042,1070062472,-1113839430)+W(5,1036397588,1037707684,-1083132698,-1117927031)+W(6,999444348,-1111062570,-1073510095,1017195567)+W(7,-1106309084,-1101285996,-1073687480,1041743674);WS(-1089880270,1068594400);
|
||||
sum1=W(0,-1114467040,-1104513741,1050219169,-1118490053)+W(1,1023170830,-1091458130,1042545281,-1120682309)+W(2,1036273894,1034367029,1048674674,1031296832)+W(3,-1107800974,-1100997781,1042739212,-1110241363)+W(4,1029867434,-1095286649,1053624831,1034289100)+W(5,-1106779367,1047811540,1034908007,-1107012174)+W(6,1024593089,-1096228817,1034674708,1021221591)+W(7,-1110449433,-1109179032,1049808694,-1126204757);sum2=W(0,1030004067,-1133064657,1024174065,-1119836251)+W(1,-1117028113,-1134091777,-1113615539,1025775761)+W(2,-1105887481,1045929484,1032698350,-1118489229)+W(3,-1066126465,1081917443,-1097201480,1041573100)+W(4,-1104777348,1043726141,1033613382,-1124268877)+W(5,-1122550707,1028310407,-1107697461,1030764051)+W(6,-1130918117,1016764395,1029778305,-1116797441)+W(7,1023720579,-1116064873,1018371831,1018350967);WS(1067475431,-1126058166);
|
||||
sum1=W(0,-1108052732,-1097851361,1049362324,1040199303)+W(1,1043040440,-1108210069,1048929252,-1109622414)+W(2,1048922396,-1084429932,1054104112,1041203782)+W(3,-1097574342,1055911149,1047147106,-1104274751)+W(4,-1119673025,1041902328,-1085779789,1047880876)+W(5,-1101774749,1035827603,1049622021,-1116198608)+W(6,1019400344,-1115594513,1019477630,-1107876353)+W(7,1007801026,-1107003538,1037086373,1036701569);sum2=W(0,1013753738,1020731454,-1120697178,1009873360)+W(1,-1113150555,1046742995,1034035253,-1099358283)+W(2,1015248850,1045156685,-1094710566,1039470065)+W(3,1042650722,-1104352239,-1128318417,1046693145)+W(4,1040818978,-1089864705,1045040370,1036008061)+W(5,-1105652199,1045331461,1025091411,1030627793)+W(6,1033430289,-1109224259,-1106535436,1017876415)+W(7,-1120377801,1016214593,1019751894,-1132110931);WS(1060496974,-1099362699);
|
||||
sum1=W(0,1054706808,-1109706041,-1098091909,-1129324363)+W(1,1036662868,1041317773,-1123237413,1015757258)+W(2,1045895019,1051554925,-1091928498,1021341985)+W(3,1033303646,1049334366,-1083798889,-1112852963)+W(4,1044095763,1051166813,-1095315343,1041804248)+W(5,-1130190200,1053590462,-1087007295,-1127492145)+W(6,1035564779,1049285205,-1097088265,1039262630)+W(7,1040746168,1055551482,-1094550458,-1114905285);sum2=W(0,-1073385920,1077926840,1032559783,-1094451238)+W(1,-1084887580,1058818874,-1089669880,-1121878040)+W(2,-1083140914,1060159151,1045764296,-1173171215)+W(3,-1081800202,1074845707,1059775011,-1120435570)+W(4,-1085954594,1061906872,-1103860568,-1115590029)+W(5,1037413129,-1084431515,-1094536545,1053315192)+W(6,-1096433065,-1126824848,-1133232881,-1107838893)+W(7,1054210787,-1087315344,-1099186518,1052978812);WS(-1078369703,1041267413);
|
||||
sum1=W(0,1024386586,1041630887,-1102607056,1016693023)+W(1,-1098405416,-1112635974,1051293608,1018393854)+W(2,1044040033,-1132435208,-1094040968,1046099151)+W(3,-1098286219,1041292515,1052507157,-1095618428)+W(4,-1130684104,-1091497929,1056853585,1018959206)+W(5,1045750173,1016159377,-1105775474,-1117949682)+W(6,-1098338270,-1139597330,1049412460,-1118540325)+W(7,1041584973,-1101611546,1026100205,1040982949);sum2=W(0,1035615459,-1097925659,1043665288,1020457849)+W(1,1028814353,1038714809,1033337220,-1103657321)+W(2,1062855981,-1077657685,1051048913,-1109823715)+W(3,1052250964,-1101970047,-1113114333,1058024935)+W(4,1056109526,-1098468896,-1085664062,1056999181)+W(5,-1106019250,-1114182260,1040975429,-1105846491)+W(6,1048995011,-1104046747,-1109605260,1042595027)+W(7,-1115640692,-1130122971,1034778788,-1112374505);WS(1049151900,-1114127847);
|
||||
sum1=W(0,1050216581,1044969414,-1106856243,-1099359923)+W(1,1000015204,1047621718,-1112471205,-1148711507)+W(2,-1136218178,1057314961,-1091938023,-1133921207)+W(3,1023136961,1055877843,-1092033343,-1112054390)+W(4,-1130455775,1054358666,-1099719178,1034273823)+W(5,-1133465094,1052966059,-1089783713,-1122838974)+W(6,-1160090192,1045850836,-1099053307,1019980258)+W(7,1035991733,1052491071,-1087984664,-1112322824);sum2=W(0,-1105478410,1011113448,1068049752,-1082501551)+W(1,1039552519,1050864081,-1103020148,1059003564)+W(2,-1131405058,-1125310098,1066695202,-1098156272)+W(3,-1099466970,1043215106,1074596924,1039344435)+W(4,1049027924,1034334973,1067601936,-1099880092)+W(5,-1115050596,-1095883745,-1084539788,-1107282542)+W(6,-1129231446,1036178144,-1075514015,-1097076855)+W(7,1049583286,-1088635155,-1074115054,1042018058);WS(-1081332839,-1093454830);
|
||||
sum1=W(0,-1109709318,1035356975,1039420520,-1111308088)+W(1,-1104916884,1037116623,-1122158672,1014687039)+W(2,-1108177419,-1125155242,1053028347,-1112931654)+W(3,-1117212646,1030327966,-1104761999,1020526050)+W(4,-1119705461,1050241163,1032136206,-1119448076)+W(5,1032417267,-1103907222,-1115200780,-1112611266)+W(6,-1118748528,1046095669,-1115609017,-1136487898)+W(7,987327371,1033262333,1029855614,-1104533373);sum2=W(0,1013207527,-1118344664,-1124997045,1036829905)+W(1,-1127355075,1028266047,-1117884424,1016171285)+W(2,-1103159789,1043690369,-1116887196,1024917624)+W(3,1040955478,1051132935,1047094008,1041601336)+W(4,1008876024,-1108842627,1057384051,-1127506713)+W(5,-1116686760,1041402295,-1100609336,1033786361)+W(6,1035764738,-1105537330,-1098518151,-1114313206)+W(7,-1154118338,-1128237045,-1089828796,-1102385561);WS(1063446990,1030048893);
|
||||
sum1=W(0,-1131562670,1043069042,-1108681470,-1108650254)+W(1,-1099483503,1049571969,-1106599551,-1106453175)+W(2,-1106193120,1061428532,-1097709592,1008661917)+W(3,-1102405700,1053095529,1046689338,-1102088711)+W(4,1021119810,-1115069793,1029025472,-1123233168)+W(5,-1113568905,-1119868742,1006738196,-1104754348)+W(6,1009340592,1027160065,-1120287391,-1136963210)+W(7,1030255032,1043118346,-1111789333,-1114502129);sum2=W(0,1012371361,1017109065,-1110016822,-1103671135)+W(1,-1149491589,-1115161102,-1109821790,-1097972516)+W(2,1023756477,1012418345,1060485172,-1094449842)+W(3,-1165255819,-1111308586,1031379047,1049769129)+W(4,-1111467932,1015942947,1046805034,999148403)+W(5,1019335917,-1106016138,-1114576028,1022790203)+W(6,-1140694601,1015823021,1024897044,1032463998)+W(7,1010513313,1026481588,-1114618076,-1146831635);WS(1060385486,1040268319);
|
||||
sum1=W(0,-1115333181,-1105770459,1048230464,1022495614)+W(1,-1113839600,-1104706211,-1122113023,-1115044751)+W(2,1026945989,-1085502934,1051932092,997701279)+W(3,1041834949,-1112644646,1065603891,1044329112)+W(4,-1100015113,-1102865873,-1105250533,1038196649)+W(5,1010458454,-1112283012,1054415097,-1113673817)+W(6,-1113704543,-1108020290,-1122402466,-1105082025)+W(7,-1110169699,-1115522389,1046973419,-1115640050);sum2=W(0,-1115664423,1041813775,-1142717933,-1120925434)+W(1,-1122287706,1041645390,-1094011677,-1119842210)+W(2,1044568139,-1087138046,-1124627987,-1120985148)+W(3,-1099350461,1067461852,1027339570,-1113918825)+W(4,-1102715015,-1116572542,1045144111,-1100833175)+W(5,1042022920,-1109622665,1054026149,-1101147879)+W(6,1031291077,-1113357449,-1122353792,-1112018489)+W(7,1032474264,-1110133469,1047364150,-1109170005);WS(1049043868,1050086952);
|
||||
sum1=W(0,-1127858130,-1091279607,1054362490,1028884238)+W(1,1025810768,-1101354119,1044465651,1022883995)+W(2,1034666762,-1089232423,1050465752,1032068165)+W(3,989092984,-1092016019,1058690160,1005443958)+W(4,-1115481017,-1089729669,1053482909,1007092039)+W(5,-1119959429,-1104525366,1051092259,-1149438996)+W(6,1012364567,-1121438163,1019953121,-1137072337)+W(7,-1097661520,-1160888088,1051219071,1017307814);sum2=W(0,1030282550,-1099759289,1070065566,-1078832473)+W(1,1012065197,1050936278,1068820850,-1076346523)+W(2,1049708534,1018991152,1068572253,-1075628240)+W(3,-1101566471,1050588571,1075164582,-1072955990)+W(4,1043525707,-1112383125,1046261639,-1093459475)+W(5,1038111746,-1121285468,1053555382,-1088795804)+W(6,1040589253,1039884984,1040055978,-1099780818)+W(7,-1106531005,-1113841779,1058828770,-1090423367);WS(-1083655502,1074535575);
|
||||
sum1=W(0,973651072,-1100106921,1049212555,-1122472503)+W(1,1028862937,-1096173461,1052529147,996549482)+W(2,1029517469,-1088250868,1057957824,-1111380529)+W(3,-1111330742,-1101351113,1060855844,-1125410415)+W(4,1043404639,-1092528244,1050267538,-1109626381)+W(5,-1105397947,1034877328,-1104065896,-1122247818)+W(6,-1129726574,-1113904430,1041335934,-1108333759)+W(7,-1099887737,-1118418050,1047916353,1037233742);sum2=W(0,1037582341,-1116649305,-1107051108,1040538112)+W(1,1032149251,-1112916551,1041643977,-1112067691)+W(2,-1135487115,1044443302,1030763641,1036263743)+W(3,-1107247151,-1117703407,1053360182,-1115814520)+W(4,1053968825,1049963138,-1087331905,1035849297)+W(5,-1096732175,1042101117,-1089009482,-1104153316)+W(6,1034930229,1046616621,-1110671517,-1104877620)+W(7,-1094249638,-1127010106,1059951262,-1116847106);WS(-1132786560,1056578758);
|
||||
sum1=W(0,1031072232,1043718831,-1098888378,-1123786893)+W(1,1019453021,1050053971,-1104586611,1030360908)+W(2,-1112153353,1057505465,-1090760605,-1123598824)+W(3,-1127115205,1049535379,-1081773448,1035671447)+W(4,-1153314582,1052394474,-1106021324,1044649456)+W(5,-1105591705,1045418390,-1120283669,-1105554848)+W(6,986346381,1044283028,1036365944,1033186457)+W(7,1024604121,1048806335,-1103287167,-1108912601);sum2=W(0,1040658557,1011638864,1041865287,-1109113498)+W(1,-1106354313,1020064744,-1103147627,1033931950)+W(2,1027144364,1049840877,1026998340,-1120927100)+W(3,-1103628435,1050147177,1053587315,-1102211113)+W(4,-1123462592,-1117174472,-1118058864,1033328738)+W(5,-1130705048,-1105120318,1036775410,-1101351534)+W(6,-1126068784,-1113970774,-1104140895,1028877580)+W(7,1016031184,-1135769248,1030416564,-1112076066);WS(1062711758,-1109562142);
|
||||
sum1=W(0,-1107075140,-1100622401,1053288051,1017596397)+W(1,-1125545776,-1104747337,1049612355,1007433175)+W(2,-1121788380,-1103229831,1059638178,-1120034657)+W(3,-1112684886,-1083301774,1048337697,-1098025711)+W(4,-1128625782,1050510715,1052952654,-1112854653)+W(5,-1102890883,-1097610180,1051307580,-1108240645)+W(6,-1129119788,-1109077454,1041285742,1022176121)+W(7,-1102110160,1030737729,1049115768,1020667959);sum2=W(0,1022257834,977550902,-1113927342,1036504102)+W(1,1033804876,-1105772859,1042844173,-1107093105)+W(2,1033963400,-1098748483,-1096777339,1028160469)+W(3,-1113268759,1063293804,1059312088,-1089861840)+W(4,-1123922685,-1090033704,-1134320563,-1101525036)+W(5,1029999681,1051039483,1037687330,1017532722)+W(6,1015463858,-1104977553,1024487701,-1122996995)+W(7,-1125618402,1022914778,1004875175,-1116068477);WS(1046002488,-1083997249);
|
||||
sum1=W(0,-1116203964,-1099156844,1050076828,1025075217)+W(1,1044431961,1028498222,1049400252,1035032656)+W(2,1041235242,-1096363997,1050263757,1032516798)+W(3,1046371486,-1079124621,1020370202,1050189128)+W(4,-1106267745,-1088685662,1048790666,1042510329)+W(5,-1117705943,-1103556299,1053355933,1039724554)+W(6,-1122870401,999993136,1034829570,1027729159)+W(7,-1109240562,-1106798659,1037276039,1037249299);sum2=W(0,-1094982381,1041875660,1017839086,1045890174)+W(1,1024745423,-1091311273,1044409386,-1107764806)+W(2,-1097113645,1042706326,974632891,1048260200)+W(3,1017043870,-1148119319,1061393923,-1118443235)+W(4,1052555320,-1098101314,1043955676,-1097368628)+W(5,-1107563793,1010824956,-1098402228,1041238578)+W(6,1049262968,-1094774489,1042935118,-1116185663)+W(7,-1118735987,1030619863,-1094515595,1042214090);WS(-1083255246,-1075588436);
|
||||
sum1=W(0,-1154522904,1026375684,-1099839750,1037990411)+W(1,-1106371438,1036249778,-1113752075,-1119606102)+W(2,-1105464695,1056687627,-1092436626,1043935324)+W(3,1036086422,-1097055709,1050924256,1036476796)+W(4,1023783355,-1088556578,1056650964,-1111337285)+W(5,-1127243930,-1108055408,1045926824,-1110940389)+W(6,1030176790,-1105944807,1039385437,-1124332025)+W(7,1031412139,-1123388097,1041066449,1021333175);sum2=W(0,-1117330831,1032531181,1043756688,1060766869)+W(1,1023708058,-1114369361,1031926890,1067300065)+W(2,-1133288218,1017487862,-1104593512,-1105945514)+W(3,-1122435213,1047518334,1043258354,-1075696003)+W(4,-1139180683,-1122916014,-1096895795,-1102393264)+W(5,1020252429,1027012545,1049767697,-1106946489)+W(6,1025188082,-1103557501,1019544307,1020047431)+W(7,-1109968059,1046855474,-1112657711,-1113285900);WS(1056055196,1023945849);
|
||||
sum1=W(0,-1104545849,1036175954,1032040419,-1111539988)+W(1,-1139517988,-1138851412,1009002268,1026875367)+W(2,-1101013315,1048468083,1040659763,-1104005681)+W(3,-1136100212,-1097789539,1059870683,-1112873620)+W(4,-1148373856,-1096999890,1039368714,-1135793772)+W(5,1013350648,-1097071058,1053644410,-1132670698)+W(6,-1120654743,995622088,-1122818538,1028030253)+W(7,-1108930702,-1128233700,1033002810,-1133516850);sum2=W(0,1033182461,-1110992702,1011638125,-1116812221)+W(1,-1135790885,1041801313,976542168,-1135785781)+W(2,1036058972,-1115959119,-1106760241,1013579453)+W(3,-1145806187,-1083556559,-1068720208,1034110873)+W(4,1026470367,1047402951,1080067579,1048786168)+W(5,-1125994579,1026458945,1043021822,-1124564059)+W(6,-1123856921,1021989349,-1118809257,-1115658442)+W(7,-1152817846,1029289545,1027196491,-1110636256);WS(1047050040,1036867972);
|
||||
sum1=W(0,1031952202,1041031945,-1098508279,-1117663192)+W(1,1040033213,1050476745,-1097704487,1033331580)+W(2,1049413776,1016870010,-1091275871,1012948685)+W(3,1052329098,1054273441,-1087382286,1043041286)+W(4,-1134253939,1041748879,-1095309386,-1131302504)+W(5,1023712847,1035493153,-1117526273,-1125396951)+W(6,-1129317744,1041656495,-1112254893,-1153578470)+W(7,1023414180,1041394937,-1108492595,-1112644847);sum2=W(0,-1120609508,-1138324119,-1110367912,1021280635)+W(1,-1098653081,1042859622,1038385587,1026624912)+W(2,-1074671298,1072071026,1026263792,1026288466)+W(3,-1081276780,1068070176,-1107049493,-1122098825)+W(4,-1097107702,1044485226,1024907208,1040255596)+W(5,-1110118090,1040658983,-1122488627,-1152233050)+W(6,-1137118351,-1118978815,1038809437,-1126727249)+W(7,-1119823807,1035453187,-1111098449,1006813455);WS(1047287096,1059538103);
|
||||
sum1=W(0,1030804480,1034749929,-1102474905,1013951379)+W(1,-1111595219,1051408038,-1094490621,1039425378)+W(2,-1123153834,1049213285,-1099609086,-1112788128)+W(3,-1098057279,1057344539,1048597242,-1098419769)+W(4,1007980582,1048793645,-1094890059,-1118093753)+W(5,1018775223,-1106759404,1046324795,-1108341356)+W(6,1036089754,-1115115061,1003815995,-1120388747)+W(7,1030691489,1033654600,-1126686757,-1135294247);sum2=W(0,-1112864979,1024004698,1034996841,1004307827)+W(1,1034721747,-1109416755,1041661735,-1116757818)+W(2,-1108077379,988806988,1041642045,1037366938)+W(3,1023366533,1058238498,1008174217,-1107547239)+W(4,1021246669,-1115279539,-1122858630,-1108868659)+W(5,1032508120,1041332549,-1089151778,-1128614293)+W(6,-1113986367,1033457886,-1130797677,-1130732717)+W(7,-1153257254,1018109285,-1111548255,-1122125438);WS(1066216871,-1084582294);
|
||||
sum1=W(0,1009745022,-1095963722,1050775177,1027534757)+W(1,1023325836,-1096473834,1046303345,-1126933960)+W(2,1034246149,-1087129751,1057767679,-1118146623)+W(3,-1103455511,-1142570129,1064400323,-1103828265)+W(4,1025953385,-1094684497,1038452388,1018950609)+W(5,-1105242559,-1107829831,992534739,1030437560)+W(6,988118663,-1107520037,1025316967,1020674901)+W(7,-1107601837,-1117719279,1044853309,1033139589);sum2=W(0,-1127013105,1031626404,1029958550,1017794797)+W(1,1018526115,-1117975133,-1113082476,1023300847)+W(2,-1123587641,1062148372,1035325186,-1145491637)+W(3,1052346460,1074624908,-1130733653,1041942663)+W(4,-1098654594,-1090512380,1046581721,-1113152926)+W(5,1029804743,-1070854231,-1113725416,-1139181075)+W(6,-1118240305,-1095518794,1031776819,-1120299385)+W(7,1030491706,1041467716,-1115594754,-1142763637);WS(1033725552,-1082653885);
|
||||
sum1=W(0,1027658456,-1091894661,1054730080,1024810077)+W(1,1033791775,-1094613753,1052727904,1020875129)+W(2,1038169633,-1085886368,1060322284,-1114253244)+W(3,-1130834725,-1094605577,1054915405,1021660859)+W(4,-1105755912,1049096200,-1115316932,1010914050)+W(5,-1107114253,1038006563,-1113871235,1032412472)+W(6,-1106878767,1040399888,-1114082704,1016596422)+W(7,-1102176852,1038046228,-1098681477,1044096992);sum2=W(0,-1126607908,-1109006144,-1093467963,1059727060)+W(1,-1111819446,1050929158,1063076656,1073053378)+W(2,1032709615,1025316173,1048889614,1073749745)+W(3,-1119610542,-1107176811,-1090320472,1058093447)+W(4,1027594385,-1123863107,1046933317,-1079533534)+W(5,1029384695,-1122531221,1051206364,-1073154062)+W(6,-1115269200,1026796828,997945380,-1075936158)+W(7,1032209203,-1115616555,-1109796884,-1088004581);WS(-1087442510,1045166814);
|
||||
sum1=W(0,-1106921670,1032009478,1041337656,-1110338367)+W(1,1032907600,-1127325529,-1100890040,1042108264)+W(2,-1111070674,-1106321881,1060092296,-1105899594)+W(3,1047421629,-1085655355,1044767811,1027442111)+W(4,-1094092352,1057239638,1040377247,-1105935775)+W(5,1031075349,-1098381173,1037296628,1037469097)+W(6,-1136240762,-1128650952,-1131454723,1027139781)+W(7,-1129052086,-1107389381,1037463686,991481919);sum2=W(0,-1119426781,1040351141,-1104019881,1015410156)+W(1,-1109786529,1043540747,-1106797782,1043466418)+W(2,1041819143,-1105926532,-1098594115,1048709183)+W(3,1018220925,-1133247980,1066013053,-1092013542)+W(4,-1103055916,-1096724541,-1136157126,-1109288787)+W(5,-1124599508,1038612076,-1097021086,1027934232)+W(6,986571056,1019567362,1025702119,-1140871148)+W(7,1024618671,-1143357456,1008181894,1027080058);WS(1059279054,1041683061);
|
||||
sum1=W(0,1028823114,-1096417644,1041071884,1040139175)+W(1,1033060856,-1095251776,1051348966,-1133443258)+W(2,-1136683218,-1096755466,-1106154521,1027763154)+W(3,1041097809,-1095420880,1062896338,1037083176)+W(4,-1108712682,-1087904547,1057053635,-1109247178)+W(5,-1099515041,-1117180600,1050313119,-1169250436)+W(6,-1114499693,-1113115866,1041134484,1007514196)+W(7,-1105525449,-1121084634,1043053335,1031868218);sum2=W(0,-1104031080,1039900182,1028023758,-1125301559)+W(1,-1113246189,1044206765,-1122555834,1027754708)+W(2,-1124792744,1043086617,1041018096,-1129842792)+W(3,-1107688308,1057123143,-1100462314,1022410763)+W(4,-1084040655,1066602722,-1123151815,1034604384)+W(5,-1089958554,1037219700,1032289221,1029558442)+W(6,-1098618924,-1111210157,1028867168,-1139711519)+W(7,-1098033920,1036938090,-1143651414,-1122704124);WS(-1093886876,-1092780259);
|
||||
sum1=W(0,1031521076,1034696971,-1098366291,991412379)+W(1,1040859655,1027092583,-1107551117,1023411481)+W(2,-1123954783,1057011018,-1084481759,1037665034)+W(3,-1115369432,1055452141,-1086775792,1037775165)+W(4,1027325374,1055461116,1050583573,-1102735091)+W(5,-1130075936,1043845385,-1098824964,-1106471523)+W(6,1017430099,1041326696,1032795870,-1113156096)+W(7,1005655277,1045628689,-1110858724,-1108701199);sum2=W(0,-1099549152,-1115620025,1042476476,-1128057356)+W(1,-1101982776,-1110046443,-1138118945,-1104607948)+W(2,1039636960,1067650764,1056117723,-1129519972)+W(3,1065032135,-1096892917,-1084935200,1039009532)+W(4,1046191187,-1084058149,1043334912,1042222420)+W(5,-1112740199,-1089814493,-1116550886,-1114781123)+W(6,-1120755726,1022618460,1030169574,1023299940)+W(7,-1138571865,-1106519005,-1123579094,1029490149);WS(-1103384376,1050555318);
|
||||
sum1=W(0,990997212,1056616014,-1113359817,-1104278389)+W(1,-1104723373,1049493908,-1101985253,-1112669305)+W(2,-1102560870,1060440249,-1095607555,-1117918862)+W(3,-1110645588,1063537686,-1091747296,-1124628967)+W(4,-1114771100,1049398171,-1098384586,-1120789735)+W(5,1006886950,-1123261404,-1094355067,1020875660)+W(6,1011892746,1042753094,-1098733239,1029891897)+W(7,1041403778,1041297647,-1099641616,-1143354303);sum2=W(0,-1097904627,1056762738,1033294591,-1113205081)+W(1,-1102268820,998260703,-1102966386,-1105114179)+W(2,-1101696600,1049156882,1040206209,1028552759)+W(3,-1102083058,1055125136,1048772561,1023069474)+W(4,-1100977750,1040009482,1004029807,-1108173489)+W(5,1022682138,-1099421122,1040485303,1040370279)+W(6,-1105396681,-1114104451,-1118051402,-1109779069)+W(7,1035758392,-1112582051,1040482786,-1135668672);WS(1042369848,-1095650924);
|
||||
sum1=W(0,1032801852,1060985291,-1088222536,-1154392525)+W(1,-1124780413,1056066249,-1093287088,1017158008)+W(2,-1142443027,1059062488,-1089766974,1041310978)+W(3,1031124370,1046815795,-1084610255,-1111535759)+W(4,1024489633,1051554984,-1096293908,-1118760812)+W(5,1037041722,1026983110,1035048291,-1118618480)+W(6,-1157391942,1037131073,-1113190096,1032589425)+W(7,1048283534,1028118439,-1107690581,-1101944856);sum2=W(0,1056251107,-1084477192,-1077785336,1053829707)+W(1,-1118435725,1041984407,-1086371528,-1113013425)+W(2,-1111043713,-1093515412,-1093010832,1046411943)+W(3,-1090037466,1073185178,1074151927,-1090694669)+W(4,-1129656805,1051712939,1054463958,-1095714333)+W(5,-1093926860,1053076395,-1094829660,-1103046632)+W(6,1052716525,-1096065312,-1090812268,1035367276)+W(7,-1083761792,1066458198,1063500158,-1087950464);WS(-1081634407,-1072784825);
|
||||
sum1=W(0,-1102740818,1024862651,1056867014,1016622683)+W(1,-1115394775,1046040367,1027952685,-1112643478)+W(2,-1101924733,-1109613465,1058509811,-1096240139)+W(3,-1100839185,-1115978107,1050187219,-1101581667)+W(4,-1123768914,1049722038,-1098437541,1008822020)+W(5,-1140848016,-1098661743,1033615035,1023463264)+W(6,-1118249725,-1138059466,-1143195264,-1116668435)+W(7,-1116477425,1025943000,-1132571500,1036595961);sum2=W(0,-1139809909,1046126277,-1119940899,1040903120)+W(1,-1126178115,-1111752353,1055245806,-1104413152)+W(2,1032546581,1034216546,-1088954301,1019748625)+W(3,-1097752958,1042101074,1058677046,-1089277711)+W(4,1042272246,1043290796,-1087007443,1028591970)+W(5,-1118367610,-1112722386,1048637958,-1139620757)+W(6,-1138081685,1034532478,-1140548675,1017306737)+W(7,1017774855,1030093406,1029648824,1033828758);WS(1050645916,1033550915);
|
||||
sum1=W(0,-1118556120,-1107219907,1039060494,1030703933)+W(1,-1108262319,1043545243,-1145250020,-1110184190)+W(2,1043230361,-1086762442,1059123936,-1110311564)+W(3,-1094947334,-1104041435,1057758321,-1100512367)+W(4,-1103841584,1058293794,-1096913490,1044416908)+W(5,1018079143,-1097977901,1039599795,-1132472896)+W(6,1032598742,1041130248,-1151122424,-1147952664)+W(7,1008731683,-1123331655,-1123961290,1022228292);sum2=W(0,1040267615,-1112791644,1010515766,1024308395)+W(1,1048409433,-1110540665,1032365064,1041630361)+W(2,-1107165984,-1088877638,-1090038325,1040244783)+W(3,-1086251247,1053330884,1049266570,1037513285)+W(4,-1113957324,1057377190,1028890653,-1098504745)+W(5,-1107976602,1057673067,-1103454662,1039941233)+W(6,-1122078587,1024512949,1041725883,-1103661415)+W(7,-1111525785,1042772014,-1143554104,1024552651);WS(1051978908,-1102077462);
|
||||
sum1=W(0,-1132165009,1045761591,1013540534,-1106078467)+W(1,-1117187439,1051430047,-1096198150,1014010165)+W(2,-1108837850,1060286099,-1130717861,-1121999817)+W(3,1037183202,1046972447,-1085387922,1030141582)+W(4,1028473682,-1128782822,-1105434962,1008925446)+W(5,1045655273,1028047735,-1101497054,1018887490)+W(6,1025240990,-1178179968,-1110960744,-1122721428)+W(7,1033734537,1035331372,-1102517015,1026996307);sum2=W(0,1023072493,974611657,-1101792417,-1112121991)+W(1,-1125531833,1047662948,1051899312,1037288067)+W(2,1030396885,1035351326,1080526024,1042102238)+W(3,-1118880502,-1090109833,-1069022098,-1113214479)+W(4,1027419877,-1110942359,-1087739606,1032127295)+W(5,-1161271853,1033315833,1036440530,-1143368203)+W(6,1019485964,1010290822,-1124554651,-1132377096)+W(7,1028708277,-1156901930,-1114394737,-1141169667);WS(1058455886,-1096183470);
|
||||
sum1=W(0,-1105360672,-1112611850,1060616064,-1104075433)+W(1,-1112035684,1032735242,1033545283,-1111940643)+W(2,-1105059667,1048808633,1051085625,-1115570744)+W(3,-1103063975,1042817013,-1097442806,-1097216429)+W(4,-1112638549,1058906409,-1102188695,-1107200030)+W(5,-1104182327,1047248804,-1103229812,-1108265532)+W(6,-1106250503,1047193699,-1106970890,-1119499692)+W(7,-1103319623,1057710235,-1109193562,-1106901731);sum2=W(0,-1135393651,-1114274101,-1117767149,-1110403581)+W(1,-1131009665,1016197705,-1130986601,-1136444051)+W(2,1004138181,-1143366053,1026922589,-1112183743)+W(3,-1111055824,1051632163,1048764370,-1121253595)+W(4,-1134829555,-1111579981,1036257166,1009689523)+W(5,-1127256265,1038147066,-1112945554,989872074)+W(6,-1113946573,1025185617,-1143942149,-1123668797)+W(7,1010148467,-1137859715,-1123068365,-1123716033);WS(-1103618872,1023577831);
|
||||
sum1=W(0,1041702149,1057806109,-1091063799,1022049043)+W(1,1032268701,997904496,-1106010126,-1102660926)+W(2,1021026046,1057675340,-1090884608,1046995709)+W(3,1032012647,-1129702414,-1094077941,-1100395542)+W(4,1023662430,1056283152,-1094732237,1050214494)+W(5,-1111766616,1039716321,-1100869456,-1096243374)+W(6,-1112590149,1049875952,-1105996279,1047647816)+W(7,1042231991,1054291708,-1098425069,-1100607928);sum2=W(0,1073849383,-1072987051,1040644897,1022236877)+W(1,1069429154,-1080077361,-1098556311,-1128073567)+W(2,1070121938,-1076996297,-1124122091,-1118780260)+W(3,1066905653,-1086754234,-1095882058,1027638421)+W(4,-1087755842,1060194671,-1096747545,1012182550)+W(5,-1080359597,1067521081,1048551041,-1129108935)+W(6,-1073496568,1074652354,-1092793409,-1130588931)+W(7,-1070245916,1075883836,1058695504,1001812541);WS(1010873216,-1100304815);
|
||||
sum1=W(0,-1154187044,1045945805,-1102222630,-1113759340)+W(1,1028741017,1051026373,-1103217414,1022415534)+W(2,-1114247598,1058185854,-1097780567,-1105383733)+W(3,-1099084427,1059904750,-1091550752,-1111624796)+W(4,-1104966895,1052860588,-1108718914,-1114326870)+W(5,994968800,1038231664,-1110664976,-1110217221)+W(6,-1113228468,1040557287,1017403508,-1108875519)+W(7,1028263947,1032103905,1017865354,-1109350878);sum2=W(0,-1114639192,-1100331344,1035901690,1012858414)+W(1,1039210963,1069298433,1043940791,-1126620651)+W(2,1047528380,1080352854,1030733380,1036529177)+W(3,-1099502544,-1067747068,-1084572959,-1099630936)+W(4,1041344628,-1080996124,1003800555,1043527822)+W(5,-1108972702,1032407437,1045939813,-1119860547)+W(6,1021595805,-1121090437,-1121287047,-1145664907)+W(7,-1116883371,1016604711,-1122259179,1034105585);WS(1044302648,-1104457270);
|
||||
sum1=W(0,-1115179413,1029190781,-1108944696,-1115207128)+W(1,-1101763748,1045938783,-1102720380,1013266237)+W(2,999269803,1034810490,1038235218,1025157307)+W(3,-1106420033,1055724168,-1101615303,-1105407492)+W(4,1041707045,1053359959,-1094303566,1045691477)+W(5,-1128885581,-1100033022,1043259278,-1113033137)+W(6,-1110751840,1037908026,1011056201,-1114066571)+W(7,1029110244,1035419021,-1123807773,-1113282394);sum2=W(0,-1117238549,-1109414288,-1115125848,1023475415)+W(1,-1115295266,-1128441429,-1121954754,1024122972)+W(2,1033754662,-1104877135,1018153798,1002646200)+W(3,-1095438097,1053172955,1038786210,-1106263750)+W(4,-1106855439,1056926069,-1104082080,1034246226)+W(5,1011060498,-1108715476,1043675119,1025499367)+W(6,-1117460606,1036225840,1008366234,-1107090094)+W(7,1032653312,-1114450934,1018894269,1013321052);WS(1068015911,1043072951);
|
||||
sum1=W(0,-1127841379,-1101991257,1041159238,1035382295)+W(1,1035792844,-1091973141,1040826438,-1098419575)+W(2,-1155603908,-1110119406,1052691071,1043898844)+W(3,1018341976,-1095315357,1053842800,1030324599)+W(4,-1111053022,-1107228151,1042506601,-1108241413)+W(5,1044403491,-1111437840,1050221764,1043481954)+W(6,-1112313859,-1097295811,1030249017,-1098652336)+W(7,1005208661,-1103670736,1046985745,1032196534);sum2=W(0,-1134315530,-1125722365,-1135384490,-1118933131)+W(1,1033824390,1019923991,998580556,1027495017)+W(2,-1112867968,1039464885,-1093291922,1045077367)+W(3,1039862799,-1087456726,-1061395777,1087627027)+W(4,1005143468,-1119378177,-1106942114,1034637079)+W(5,-1114969920,1042059959,-1121281813,-1148550692)+W(6,1030354102,-1113780490,1034179020,-1118611519)+W(7,-1131720457,1009971850,1032010553,-1117397469);WS(1060186318,-1131602669);
|
||||
sum1=W(0,1022422466,1050205114,-1099402401,-1112848707)+W(1,-1102049002,1052887138,-1102238785,-1106285089)+W(2,1050775273,1052456073,-1100510367,1039607513)+W(3,-1097141731,1049038746,-1088759247,-1098786589)+W(4,1056872997,1040490435,-1122526498,1048305743)+W(5,-1099566807,1039690728,-1099089908,-1104192622)+W(6,1025667942,1043457059,-1102859210,1032266998)+W(7,1032894309,1045856748,-1106963501,-1118572779);sum2=W(0,989650422,-1120410947,1047633630,-1081060940)+W(1,-1108234271,1050158699,1066272871,-1074101109)+W(2,-1120122674,-1092804082,1075424781,-1079387458)+W(3,1045260201,1024838498,1061734347,1050344942)+W(4,-1114112879,-1125280065,-1091697647,1043540897)+W(5,1037831837,-1119936776,1003481288,1039609275)+W(6,-1117501250,-1114421818,1011848513,-1131708367)+W(7,1024132690,1035095434,-1106020023,1026462111);WS(1057810382,986287880);
|
||||
sum1=W(0,-1105255365,-1110142276,1041191503,1050176972)+W(1,1027767677,-1106138450,1031406779,-1130243957)+W(2,1037147968,-1092238936,1027980992,1041310918)+W(3,1038550632,-1090210593,1049547413,1041377527)+W(4,-1136315263,-1089134184,1052451129,-1115128119)+W(5,1035749561,-1093055129,1057536820,1033537239)+W(6,-1115075413,-1097497096,1050343212,-1127231554)+W(7,1028257967,-1089420006,1058108487,1031965752);sum2=W(0,-1099824579,1070708271,1075074245,-1097074436)+W(1,-1113793286,-1104040400,-1084124078,1023561426)+W(2,1053512844,-1091831853,-1082668198,1039380165)+W(3,-1112943238,-1072548459,-1072503695,1009216489)+W(4,1041834894,-1093778092,1056090411,1043969626)+W(5,-1099992002,1057576575,1053907302,-1107563771)+W(6,-1120789532,1064181862,1058602971,1034348623)+W(7,1024916046,1051972140,1054786345,-1106961801);WS(-1075707047,1038147646);
|
||||
sum1=W(0,1038492938,1050722763,-1095596015,1040870942)+W(1,-1115961531,1026800423,-1103730686,-1122935577)+W(2,1036899040,1055626176,-1091210886,1047700685)+W(3,1041066756,1052178217,-1090286882,1036539085)+W(4,1038870159,1027667391,-1094135001,-1102625947)+W(5,1045702796,1053246416,-1095582752,1048523811)+W(6,1022987667,-1100305296,-1109653838,-1105859960)+W(7,1044017707,1049962981,-1093296229,-1117734303);sum2=W(0,-1145353723,1027969677,-1115030411,1052090154)+W(1,-1113260796,-1095928859,1031463199,-1110261785)+W(2,-1112198364,1052169305,-1108227013,1041877601)+W(3,-1113367096,1052353113,1051016428,-1099630700)+W(4,1007958125,-1129450520,1041462653,-1087173862)+W(5,1047146251,1051473061,1045242344,-1102681887)+W(6,-1122974002,-1091037095,1032341221,-1095485390)+W(7,1021064313,1050393555,1020102815,-1111896409);WS(-1102302520,1068562064);
|
||||
sum1=W(0,-1130894152,-1101486038,1044130034,1031789673)+W(1,1029216267,-1094978851,1029251017,-1102217970)+W(2,1029150351,-1104755260,1053252560,1042516209)+W(3,1029804895,-1093484995,1050941559,1040658618)+W(4,-1108054071,-1110271975,1036880709,-1113036417)+W(5,1046304488,-1106599349,1050863202,1041743615)+W(6,-1107326720,-1102131284,-1128083416,-1102226940)+W(7,1018120580,-1102274525,1047248574,1032422999);sum2=W(0,1019111797,1022527979,-1131519898,1029130971)+W(1,-1123809812,-1111065998,1023737355,-1117143513)+W(2,1006739898,1031759809,1045357020,-1106220344)+W(3,1041109085,-1095097056,1082939698,-1064938697)+W(4,-1126211453,1034613952,1027342607,-1122955245)+W(5,1028972357,-1107360163,1033832936,-1112280546)+W(6,-1118372569,1033659253,-1112248823,1032152906)+W(7,1025713585,-1118642675,-1118824157,1028082979);WS(1066566439,-1125753148);
|
||||
sum1=W(0,1020091828,-1096367972,1038767583,1030663671)+W(1,1041951168,-1098758994,1048997640,1025331919)+W(2,-1130301450,-1093467737,-1130818632,-1108818909)+W(3,1052053147,-1089881409,1064063659,1044746920)+W(4,-1131231944,-1092544881,-1116991019,1022962726)+W(5,1033588155,-1098181717,1042770882,1041997189)+W(6,1009411772,-1110070786,1046860728,1018371147)+W(7,-1116682291,-1096392077,1027361773,1038578846);sum2=W(0,-1105507764,1019815533,-1136431769,1024962860)+W(1,-1149004498,1047279899,-1121679526,1041000955)+W(2,-1098298748,-1106660204,-1096656341,-1107413740)+W(3,-1115729482,1058550934,1058580319,1027135608)+W(4,-1094576030,1031191852,-1098228632,-1101441076)+W(5,-1111478010,1032716298,1041490224,1035067556)+W(6,-1129010369,-1117054989,1047791827,-1123460834)+W(7,1018600957,1019851909,-1106522387,1005788722);WS(1050996380,1066787661);
|
||||
sum1=W(0,1042843177,-1109518091,-1098674409,-1112832565)+W(1,-1120310187,1043911830,-1097687209,-1133582755)+W(2,1033453959,1059519229,-1096304487,-1116528532)+W(3,-1107450543,1061971625,-1098011863,-1105396874)+W(4,1017862620,1051823058,-1095767039,1033796902)+W(5,-1134072575,1046601317,-1095249970,999923683)+W(6,1025308393,1042112788,-1098354285,1030029487)+W(7,1033769739,1046863997,-1098417599,-1109771063);sum2=W(0,-1103321099,-1087654445,-1098379129,1013739975)+W(1,1033376724,-1114493691,-1096458683,1015354012)+W(2,-1108916223,1049058628,1036368268,-1121134774)+W(3,1033194077,1065240604,1054396447,-1115257551)+W(4,1038197771,-1128335788,1049730119,-1129699908)+W(5,1032881798,-1094150295,-1108472207,1021079748)+W(6,1017830932,1006224046,1031462702,-1117224382)+W(7,-1138730935,-1112103411,-1102017203,1038189385);WS(1027314912,-1081149641);
|
||||
sum1=W(0,-1109480125,1051429188,-1118844062,-1097611416)+W(1,-1114947760,1053252314,-1094077252,1034118735)+W(2,-1101195017,1058130398,-1113091794,-1104617542)+W(3,-1132100201,1061393767,-1085308129,1035982720)+W(4,-1103759537,1057940398,-1102037735,-1114189097)+W(5,1044342469,-1104522586,-1094497965,1036294793)+W(6,-1111893319,1055491172,-1103334896,-1128796810)+W(7,1051194426,-1120202825,-1094870250,1030785028);sum2=W(0,-1131039707,-1098833779,-1147567565,1035790053)+W(1,1024995350,-1124760267,1057070390,995065627)+W(2,-1104486127,-1078713050,-1091843304,1037354874)+W(3,1015537291,-1065942779,-1081156610,-1154356731)+W(4,1053996441,1047686732,-1094140189,-1107145709)+W(5,-1103676904,1084085461,1060423478,1026796886)+W(6,1047124046,1064521940,1046849692,-1108476011)+W(7,-1111129691,-1093915430,1018309905,1038591472);WS(-1081542375,1044780323);
|
||||
sum1=W(0,1026864081,1046719985,-1098857847,-1114219435)+W(1,-1100303790,1054288460,-1108679899,-1104586877)+W(2,1048337215,1054459103,-1098101851,1041408644)+W(3,-1098110473,1048901488,-1093175556,-1098306531)+W(4,1054474587,1041639871,-1104037973,1046672715)+W(5,-1099969099,1034589376,-1107626335,-1104199322)+W(6,1023999910,1043694031,-1101510966,1022681657)+W(7,1028627178,1046235480,-1106600025,-1126646775);sum2=W(0,1017985090,1024212320,-1099849981,1067245211)+W(1,1027847194,-1098721130,-1081468176,1074345814)+W(2,1036519222,1050387030,-1070464929,1070597407)+W(3,-1113167123,-1094712479,-1096550174,-1088417301)+W(4,1037009826,-1100822056,1057690620,-1104880956)+W(5,-1113380621,1028269032,1042714784,-1102737214)+W(6,1031131596,1009055356,-1145638655,1000105719)+W(7,-1115360802,-1113841920,1046010973,-1112342255);WS(1059294542,1020616832);
|
||||
sum1=W(0,-1157534552,-1096856701,1050532499,-1112831597)+W(1,1039080142,1044861738,1041652423,1046540791)+W(2,-1097783100,-1089052876,1057029426,-1098369827)+W(3,1031217968,-1085780263,1047119538,1040272239)+W(4,-1164216296,1044573672,1039715347,1024931118)+W(5,-1138897989,-1097342660,1043073721,-1103025619)+W(6,1026686634,1041475528,1040308239,1045404192)+W(7,-1105498094,-1105558033,1048391538,-1114523696);sum2=W(0,-1106291706,1040318024,-1114208076,-1142193319)+W(1,1001372950,-1105705183,-1116263519,-1145917455)+W(2,-1099590495,1045484852,-1108179199,1036599633)+W(3,-1093748925,1061316313,1049891427,-1108356360)+W(4,1015225205,-1098311584,1040668388,-1148092276)+W(5,-1105937891,1041085521,-1111581107,1032743264)+W(6,-1112612361,1028378294,-1115787941,1021281994)+W(7,995169980,1035732349,-1113959318,1024794158);WS(1059376718,-1137270291);
|
||||
sum1=W(0,-1118257199,1043258576,-1114290826,-1112002778)+W(1,1037392427,-1106073464,-1124279079,1022160871)+W(2,-1097794403,1054680411,-1115190716,1045843716)+W(3,1035766677,-1099046488,1052189312,1011458515)+W(4,1026067385,-1088020070,1054691490,-1110958220)+W(5,1032186693,1041392887,-1097245116,1046761570)+W(6,-1108679762,-1113652045,1025610423,-1117145658)+W(7,-1139304576,-1111666975,-1123561026,1032305501);sum2=W(0,1025244035,1033595807,1016573022,1002397687)+W(1,-1122852568,-1087687504,1048825911,-1104089806)+W(2,-1092220395,1066421651,1058107887,-1130145014)+W(3,1038019467,1047700223,-1089540205,-1111655831)+W(4,1048072683,-1084925862,1045215493,1032935415)+W(5,-1113553750,1050883425,-1098430697,1015641098)+W(6,-1119930901,-1105555859,1041208433,1001885951)+W(7,-1139793711,-1146566911,-1124843514,-1131703250);WS(1058596686,1013962118);
|
||||
sum1=W(0,1000024554,1052551424,-1088298614,1039656505)+W(1,-1127551432,1049056438,-1098656348,1034731345)+W(2,-1100000762,1057499982,-1090756927,1019232187)+W(3,1035333436,1036076760,-1097067922,1033429441)+W(4,-1122612871,-1127972943,1040213184,-1125045580)+W(5,1044766998,-1116046252,1015197910,-1113717771)+W(6,1041477861,-1118015335,-1123679237,1037833508)+W(7,1051562743,-1099275107,-1122278672,-1122272135);sum2=W(0,-1104434141,1048601996,1033271157,1004930429)+W(1,1029025211,-1091369704,-1119340081,1028438774)+W(2,-1078497608,1052827694,1025214064,-1106316897)+W(3,-1079110377,-1106615386,-1109539756,1034989376)+W(4,-1085502108,-1115334546,1050957039,-1108631008)+W(5,1066279808,1037382016,-1106594885,1023198169)+W(6,1062913146,-1122817088,1036274829,-1134348613)+W(7,1068620036,1048688798,-1118139306,-1139733884);WS(1044771128,1023341948);
|
||||
sum1=W(0,-1156220044,-1092336191,1051560294,1036528391)+W(1,1034545464,-1098819215,1044146859,1029114797)+W(2,1033488922,-1096491302,1051910286,1022761170)+W(3,-1111313058,-1086850728,1045449190,1029767950)+W(4,1038420969,-1102939421,1053458817,1041877300)+W(5,1008511890,-1100928894,1038883707,1034675856)+W(6,1013986230,-1115524377,1012126018,1037411178)+W(7,1011084871,-1089482302,1046748951,1043196317);sum2=W(0,-1071004894,1076503146,1057610169,-1122913984)+W(1,-1080574884,1066884159,-1107351326,-1130255370)+W(2,-1089987082,1058011283,1054000347,1038970611)+W(3,1049506323,-1098882467,-1090234844,1014162118)+W(4,1065282653,-1084978169,1030898490,-1114000490)+W(5,1062249589,-1088626314,-1090230279,1022492087)+W(6,1060165079,-1082249713,1044380003,-1131621088)+W(7,1070844945,-1077734377,-1096516163,1013009282);WS(-1111817840,-1134998409);
|
||||
sum1=W(0,1022731056,-1102901203,1029699069,1021112442)+W(1,1045262352,-1094315057,1052915216,-1107194439)+W(2,1044888721,-1085070720,1058770140,-1097785743)+W(3,1029818259,-1111793509,1057078063,-1117717150)+W(4,-1105915720,1055206544,-1095183540,1040740592)+W(5,-1114660906,1046806370,-1097451385,1036425016)+W(6,1027479949,-1123039746,-1112670352,1005586201)+W(7,991785104,-1136267423,-1114500629,1016465988);sum2=W(0,-1129690332,-1113356803,997943457,1015499837)+W(1,1030842707,1026318374,-1119512995,-1180561029)+W(2,-1123486113,1041923626,1037525758,-1144014736)+W(3,1054087898,-1089332833,-1088292904,1037328869)+W(4,-1105176966,1068558125,1040210770,-1107365912)+W(5,-1097205966,-1141184456,1050151959,-1114055561)+W(6,-1098021434,-1107728348,1018682892,1009592392)+W(7,-1106929221,-1104288342,1006954668,1013301204);WS(-1100650808,1043653943);
|
||||
sum1=W(0,1038392637,1044290651,-1095199164,1033771919)+W(1,1032036848,1040683515,-1115398639,1038316223)+W(2,-1120772452,-1106266873,-1094097345,1042896310)+W(3,1043637149,-1090111931,-1097393337,1045751664)+W(4,1040259489,-1133467790,-1104941765,-1159203906)+W(5,1047398869,1044787930,-1101572298,1015063331)+W(6,1038054351,1023591523,1016760834,1030908740)+W(7,1050576478,1037223428,-1102689443,-1125005703);sum2=W(0,1018053796,1046306039,-1101305605,1031448374)+W(1,1000548496,1043541862,1029064982,-1112893849)+W(2,1049079603,1010667960,-1116813778,1021972628)+W(3,1039189619,1064529690,1038487223,-1105518867)+W(4,-1128574308,1047996002,-1100258391,1037842238)+W(5,-1118597354,-1087406141,1048794746,1033382833)+W(6,-1106984497,-1095617964,-1114392997,1021089548)+W(7,-1104543855,-1086946593,1045938007,-1140458600);WS(-1121537248,1047151836);
|
||||
sum1=W(0,-1096325448,1052654400,1000450324,-1116556387)+W(1,-1113135282,1035132488,-1110395025,1023519458)+W(2,-1098188693,1046868890,-1139200797,-1111260975)+W(3,-1112146268,-1134150082,1049727010,-1110207458)+W(4,-1108791588,-1129891280,1041189572,-1104838938)+W(5,-1117696601,-1098847494,1056884317,-1098805187)+W(6,-1123869651,1032919412,1041128337,-1146298440)+W(7,-1114157115,-1107856679,1058220805,-1103148146);sum2=W(0,-1142864271,1043572739,-1125571574,-1107989855)+W(1,1021304865,1026011378,1028667063,-1140649559)+W(2,1043366966,-1102859954,1022196210,1020722946)+W(3,-1107584343,-1080136051,-1072538638,-1132367054)+W(4,1014758407,-1103597159,-1076945816,1041979768)+W(5,-1130465374,-1115654645,1048815254,-1126224006)+W(6,-1120740451,1046511165,1072551214,1027667511)+W(7,1000478551,1053224660,1074776028,1048839210);WS(-1086568910,969651201);
|
||||
sum1=W(0,-1128189323,-1096064919,1047521403,1043461231)+W(1,1044154939,-1089612648,1054908701,-1099266659)+W(2,1043534732,-1084798775,1056987371,-1113308531)+W(3,-1114366976,1053159863,1057685165,-1152040120)+W(4,-1098469330,1053431542,-1089249613,1042761408)+W(5,-1101372520,1050787607,-1090701774,1049635020)+W(6,-1123038043,1036747448,-1105030179,1010635844)+W(7,-1132910587,-1116020373,1027268120,1018344000);sum2=W(0,1042932965,-1103892922,-1104364155,-1139842168)+W(1,-1103428495,1060495074,1060109323,-1118896922)+W(2,1039997403,1052448567,1064108701,991756114)+W(3,-1093583228,-1075640666,-1073056297,-1097481656)+W(4,1044856824,1057723154,1055665788,1040659602)+W(5,-1121819542,1057002090,1060503917,-1099984054)+W(6,-1177180368,-1112150955,-1116550688,1034919451)+W(7,1028413178,-1118134166,-1110515035,1041069777);WS(-1084093518,-1116656412);
|
||||
sum1=W(0,1002008836,1058416208,-1096672513,-1112390467)+W(1,959481663,1026388179,-1109778819,1023428581)+W(2,-1104590931,1059097973,-1088144465,-1112632704)+W(3,1050696243,1042079029,-1096264126,1040470858)+W(4,-1106608235,1041679827,-1101432288,-1102954054)+W(5,1047962207,1049127990,-1100480244,1047012782)+W(6,1030562773,1031439243,-1113594772,-1112144502)+W(7,1015783795,1042535660,-1093923750,-1145396437);sum2=W(0,1007960967,1027407916,-1129957403,-1132155403)+W(1,-1110192070,1010716935,1018303319,-1121935910)+W(2,1049899326,-1097456083,1037417999,-1137993343)+W(3,1056650247,-1070859565,-1094713389,-1142796285)+W(4,1078512141,-1068241064,-1096379657,1039214170)+W(5,1081472440,-1079514242,1043613542,-1111213656)+W(6,1058404171,-1094427160,1025537830,1032528613)+W(7,999915485,1030657127,-1116925932,1024356221);WS(1052225948,1018668194);
|
||||
sum1=W(0,-1120453498,1051775516,-1117579103,-1107074656)+W(1,-1123160289,1048325451,-1111291056,-1112742544)+W(2,-1108654867,1058214550,-1093397513,-1147977428)+W(3,-1104839613,1064670427,-1091445969,-1119335936)+W(4,1041378113,-1126638409,-1092047898,-1109154218)+W(5,1036965515,1049967085,-1099225050,1034167881)+W(6,1044186084,-1096299613,-1112850625,-1138567959)+W(7,1034438594,-1128237844,-1112057991,1019177609);sum2=W(0,-1121001958,-1117606942,-1103097305,-1130038396)+W(1,-1148685985,-1111847761,1021935234,-1112487949)+W(2,1018483434,-1120566718,1049895592,1038078839)+W(3,1021815720,-1076982600,-1081972918,-1125812992)+W(4,1049361594,1074852012,1051964198,-1152546434)+W(5,-1108634723,1048076514,1040925857,-1104919092)+W(6,-1132118692,-1102180777,1017568960,1026180028)+W(7,-1105580672,-1116866514,1040155911,-1123068468);WS(-1096382876,-1091051652);
|
||||
sum1=W(0,-1116126267,1057278592,-1096000788,-1116910752)+W(1,-1113197617,1048826126,-1097274020,-1140807037)+W(2,-1112424211,1058810754,-1088739494,1039925053)+W(3,-1124324715,1056304110,-1091311905,-1132679170)+W(4,-1136579346,1041995897,-1114916522,-1107191661)+W(5,1040875430,1016295122,1038826452,-1119450067)+W(6,-1113905512,1024916389,-1128507781,1023437062)+W(7,1017323784,1042534003,1017648027,-1098370349);sum2=W(0,-1120311657,1025682064,1036682152,-1108273289)+W(1,1036113080,-1107470193,-1108061877,1012612647)+W(2,-1109045199,1035621932,1051542033,-1101063214)+W(3,1029662296,-1118009189,-1101792442,-1076098595)+W(4,-1122358251,1045290388,-1093646778,-1080861029)+W(5,-1114085873,1009830751,1056395710,1039398973)+W(6,1016737279,1035169596,-1091719234,1065137390)+W(7,-1115835645,1030264440,1052430993,1072502688);WS(1040082544,-1114755812);
|
||||
sum1=W(0,1017784372,-1110974758,1040296296,1024480479)+W(1,1037505264,-1108514902,1041424680,-1104471944)+W(2,1045745417,-1095324708,1054913780,-1106439461)+W(3,1019379817,1052579502,-1106396419,-1115066496)+W(4,-1109308706,1058051822,-1087512533,1040857799)+W(5,-1124056118,1046163210,-1093666877,1001482384)+W(6,1025470519,1038459986,-1106674096,995688529)+W(7,1039469090,998280780,-1109356390,-1108404770);sum2=W(0,-1162396366,1045315846,1034748092,1035646876)+W(1,-1117720653,-1118054954,1034773210,-1100298043)+W(2,-1104226850,1057942904,1043388435,-1097646834)+W(3,-1105580348,1059476362,1067689202,-1093789486)+W(4,-1105643813,-1090022037,-1083232471,1040357620)+W(5,1031813906,1045409162,-1101262587,-1113573448)+W(6,1011045214,-1106412098,-1124577575,1012935222)+W(7,1018164327,1023977529,-1102021751,1024454049);WS(1036525168,-1082462584);
|
||||
sum1=W(0,-1116308971,-1085123800,1057675329,1019612704)+W(1,1037298441,-1087372070,1051660338,1027541711)+W(2,1027885589,-1086414101,1059597873,-1109257541)+W(3,-1122874917,-1096064460,1059581688,1041073820)+W(4,-1154089797,-1099879381,1052784510,1028059367)+W(5,-1108384819,-1104319094,-1117339864,1045372305)+W(6,1028179743,-1127380522,1039251609,1031554934)+W(7,1003463273,-1096394215,-1110971807,1053758651);sum2=W(0,1060691160,-1081285622,-1080809247,1052276353)+W(1,-1103295177,-1090050073,1050684042,-1106187369)+W(2,1035985281,-1102851017,-1087522637,1048638013)+W(3,-1085964582,1072728426,1060852217,-1090587145)+W(4,-1105398566,1060511611,1058511518,1029176048)+W(5,-1107551093,1033954581,1041242888,-1094879840)+W(6,1049030608,-1086630634,1028348456,1046256182)+W(7,-1090293163,1058069039,1062481845,-1087039462);WS(-1074352935,1040600857);
|
||||
sum1=W(0,1042034194,1057627204,-1090157751,1024364622)+W(1,1028652336,1025049468,-1105875707,-1105990299)+W(2,1024054004,1057567995,-1088931067,1048022018)+W(3,1030695172,1022098295,-1095088235,-1100928004)+W(4,1029627411,1052602222,-1094832321,1049957878)+W(5,-1117605317,1039437212,-1104356174,-1095846092)+W(6,-1114002447,1049556590,-1107260676,1047165477)+W(7,1041624512,1053416947,-1101255271,-1098759166);sum2=W(0,-1075440350,1073165865,-1112383192,-1148975848)+W(1,-1079714919,1065983198,1048707236,-1115591486)+W(2,-1079134350,1068716226,-1135853868,1038054064)+W(3,-1081735031,1066499710,-1098543278,-1125971282)+W(4,1055569671,-1095308006,1021808504,1040311395)+W(5,1066585571,-1080754250,-1108920844,-1110109816)+W(6,1071644179,-1074800849,1050977418,1035370814)+W(7,1075476470,-1073191304,-1090378667,-1120408347);WS(1041022776,1033480094);
|
||||
sum1=W(0,-1132576057,1026327841,-1110434490,-1119031508)+W(1,-1123321429,1042302896,-1109312954,1021323174)+W(2,1028959481,1052457903,-1089918670,1029242558)+W(3,-1104176578,1063677500,1025377120,-1118638740)+W(4,1046472198,-1097607903,-1090934974,1013298461)+W(5,-1121060138,-1123802109,1046523967,-1106699146)+W(6,1027556403,-1118671609,-1112257611,1030036314)+W(7,-1115611836,1039698959,1000531209,-1116635705);sum2=W(0,-1106027239,1049930690,-1110218398,1034564779)+W(1,-1122286155,-1127267122,-1108798456,1018367610)+W(2,-1102546078,1041115945,1058786995,-1095860458)+W(3,1055155948,-1091935564,1075372513,1043590800)+W(4,-1096754888,1052250618,-1071163371,-1112711414)+W(5,1032068992,-1103388917,-1123143101,-1119323979)+W(6,-1121774513,1038737216,-1121707895,1016553114)+W(7,1036170969,-1108790214,1032355550,1017858173);WS(1055618972,-1117202987);
|
||||
sum1=W(0,1030962480,1039894129,-1101932469,1031993659)+W(1,-1101414710,1053882576,-1089999221,1048656807)+W(2,-1098100923,1057347458,-1085784352,1043352452)+W(3,-1111740150,1049814740,1051098296,1031031542)+W(4,1036980413,-1090053902,1056052448,-1104607674)+W(5,1041005827,-1088233382,1051763396,-1119077705)+W(6,1021681163,-1105970903,1044301630,1022017143)+W(7,-1112834597,-1117339136,1032801282,1039235901);sum2=W(0,-1114659327,-1101541229,-1107338771,1039378885)+W(1,-1123577690,1043634319,1057974128,-1111523166)+W(2,1042921002,1066882360,1050113378,1040130625)+W(3,-1105097716,-1077668162,-1080704784,-1104122760)+W(4,1042773509,1037629509,1051155360,1012227066)+W(5,-1093975266,1058638399,1052705661,-1110420726)+W(6,1032061179,-1108208741,1008396554,-1125218199)+W(7,1000405669,-1131856909,-1111189711,1025207949);WS(-1091387548,-1116324289);
|
||||
sum1=W(0,1026642697,-1112220622,1049897926,1027958127)+W(1,1044682252,-1093973688,1047211372,-1098544270)+W(2,1041967213,1046046637,1050365286,-1112662293)+W(3,1032214050,-1086442024,-1112122925,-1106755108)+W(4,-1131062694,-1099996941,1046223135,-1116559746)+W(5,1015214154,1053177927,-1132096750,1034258897)+W(6,-1137069945,-1098783494,1024489425,-1111108842)+W(7,-1110158325,1037567917,1042021623,1031638516);sum2=W(0,-1108095393,1011776651,-1101257730,1019145070)+W(1,1016776222,1024100809,-1105403134,1032882678)+W(2,977935538,-1097248934,-1101986254,-1124027994)+W(3,-1122468710,1057627889,1060632600,-1103033100)+W(4,1019959206,1042194141,-1090719303,1039533068)+W(5,1030099429,-1117226417,1037412790,-1110127978)+W(6,-1104930054,1051928720,-1109292621,-1125661478)+W(7,1002749526,1041814459,-1115385474,-1108291818);WS(1057965518,-1118811194);
|
||||
sum1=W(0,-1104352985,-1106566686,1052732873,-1107147458)+W(1,1038892389,-1112643723,1003767366,-1114250980)+W(2,-1105058276,1026830542,1060358287,-1096574819)+W(3,1042490232,-1091938531,1019887594,1048844541)+W(4,-1121521774,1058056073,-1118338013,1024329053)+W(5,-1099594944,-1101314965,1042464324,-1107780158)+W(6,1033536020,-1098044778,1024562028,1032778872)+W(7,-1095161930,1039936570,1046000094,-1107207172);sum2=W(0,-1116205334,993944814,1032713731,-1106373772)+W(1,1042905425,-1113078065,-1104977559,1039619019)+W(2,-1109155755,1044406596,1048672381,-1115343154)+W(3,1044205280,1040105843,-1104277422,1048332350)+W(4,1035597621,1043112037,-1103087244,999501191)+W(5,1008636092,-1123380436,-1153474446,-1106439836)+W(6,1036458751,-1105268129,1015784078,1021528398)+W(7,-1092853308,1005260887,1036094123,-1106473413);WS(1053420700,1049909457);
|
||||
sum1=W(0,-1115258034,-1106165874,1050401361,-1113250117)+W(1,1034071238,-1089903413,1041332866,1023742249)+W(2,1027276239,1036166247,1049384898,-1130552842)+W(3,-1115686559,-1100423414,1037380859,-1120158506)+W(4,1041096236,-1093491554,1052388787,1037333727)+W(5,-1102788144,1049835542,1034784425,-1103514783)+W(6,1034068157,-1095323722,1031952854,1037170040)+W(7,-1107460367,-1110396954,1050882791,-1114330639);sum2=W(0,-1112500393,1024557142,-1136367764,1020782048)+W(1,1028289272,-1165623582,1035333264,-1122738507)+W(2,1049127312,-1095250820,-1114028070,1025362120)+W(3,1086771603,-1062269001,-1087155359,1034731082)+W(4,1048088739,-1095068995,1022077560,-1125007838)+W(5,1020087240,999933935,1034746908,-1120796207)+W(6,1014851096,-1135945992,-1120864651,1026594640)+W(7,-1146529543,1025716258,-1127622484,-1128255426);WS(1063806286,1027083983);
|
||||
sum1=W(0,-1114823180,1045480194,-1118427516,-1109705966)+W(1,1030313470,1039206373,-1106496703,1020453816)+W(2,-1111791457,1061885616,1010686340,-1103432478)+W(3,-1111977289,1050451993,-1083830979,1039658735)+W(4,-1108043857,1057912708,-1099420545,-1114670584)+W(5,1019729830,1036575619,-1105267089,-1109909656)+W(6,-1114640622,1039765761,-1131920190,-1113587473)+W(7,1033983240,1034424532,-1125840468,-1112770081);sum2=W(0,1033978022,-1122290634,1016780797,-1164938552)+W(1,-1100194899,-1091664523,-1103111994,1002490582)+W(2,1033701105,-1071413373,1047766898,-1105595809)+W(3,1050426550,1075108998,-1096749849,1051489664)+W(4,-1104028404,1062092502,1027350687,-1108336227)+W(5,1034191613,-1103668501,-1131589290,1021076655)+W(6,-1141130302,1034149895,-1131724600,-1149103768)+W(7,1010895851,-1140709165,1027888251,-1131210373);WS(1058288590,1045994186);
|
||||
sum1=W(0,1018135640,-1093342072,1052167946,1038262801)+W(1,-1123855059,-1096797372,1041780692,1015346466)+W(2,1040223430,-1086390197,1052872019,-1132654257)+W(3,-1112801779,-1105293320,1059840396,-1134794696)+W(4,1036317947,-1091216419,1051866430,-1117665797)+W(5,-1098800665,-1117054299,1050341107,1012611090)+W(6,1034707665,-1096209979,1048652350,-1139713758)+W(7,-1096517871,1023470716,1050625648,1010858330);sum2=W(0,1041114210,-1099008397,-1123917868,-1125418381)+W(1,-1099284356,1047276236,-1111523652,-1120564910)+W(2,1038292116,-1081084758,1037708884,1020505319)+W(3,-1092208278,-1071665325,-1086778305,-1100128811)+W(4,1054381469,1054365119,-1101037019,1024474915)+W(5,-1104534119,1081581342,1026238413,-1125603475)+W(6,1025804573,1062322644,-1134916894,1025011807)+W(7,1033400256,-1093538640,1052085127,-1103707544);WS(-1088887374,1070119449);
|
||||
sum1=W(0,1040460421,1052058645,-1090595183,-1105506686)+W(1,1041554590,1048371361,-1115426747,1029097335)+W(2,1013850612,1048732808,-1094790815,-1129317061)+W(3,1038262022,1042754705,-1087902678,1001782464)+W(4,1042710919,1047384127,-1106656361,1038072126)+W(5,-1106869091,1054439312,-1090477876,-1131475029)+W(6,1044864290,1032508990,-1122940954,1028935005)+W(7,1046057615,1042772520,-1091795237,-1119515740);sum2=W(0,1024604999,1056461606,1071685965,-1075212110)+W(1,-1112923336,1030035123,1066713447,-1080779344)+W(2,1027433809,1050727550,1068313262,-1078194918)+W(3,1025504127,-1090534096,1028028856,-1153515923)+W(4,1007245204,-1105339223,-1081367671,1068056044)+W(5,-1144581942,-1095507508,-1078816510,1069903211)+W(6,-1129047399,1043793174,-1081156501,1064173276)+W(7,1021294865,-1095638178,-1090770344,1060536751);WS(1040470840,1011790950);
|
||||
sum1=W(0,1015095158,1043725275,-1105535856,-1108386992)+W(1,-1120734562,1051465082,-1108441440,1030149375)+W(2,-1116691398,1058372660,-1095343471,-1112701741)+W(3,-1118217942,1055309890,-1081260869,1026499745)+W(4,1019898057,1046636817,1047492563,1032201014)+W(5,-1123629847,1044874098,-1093096561,-1115283258)+W(6,1034607368,1043010193,-1105294873,1028457510)+W(7,1041822001,1040878843,-1106259483,-1112399171);sum2=W(0,1022830461,-1117997331,1037270083,1023767946)+W(1,1021246145,-1110014342,-1125616185,-1130403951)+W(2,1015115055,-1111993293,1044158772,1025796328)+W(3,-1114703004,1036613835,1073620398,1050812248)+W(4,-1120910531,1023720090,-1076883688,-1112499600)+W(5,1015720307,-1117604953,-1087890801,1028283916)+W(6,983370825,-1120463052,1025754476,-1104874229)+W(7,-1123770073,1036937497,-1113287589,1033737696);WS(1058309838,-1101980246);
|
||||
sum1=W(0,-1118965337,-1110907254,1038642111,1028903966)+W(1,-1098779704,1049643561,1038999679,-1108240479)+W(2,1049071256,-1081904943,1054751182,1040887994)+W(3,-1113399754,1042163763,1056093093,-1118832415)+W(4,1026571427,1052138696,-1083956910,1046797612)+W(5,-1110569018,-1106220306,1050507993,-1104697276)+W(6,-1131332475,1025191299,-1146247429,-1123883748)+W(7,-1128371676,-1129449041,1030864044,1017502086);sum2=W(0,-1137655511,-1111106723,1035105104,-1112318930)+W(1,1043191716,1033166752,-1112822728,1027572041)+W(2,-1121349336,1033268708,-1104857525,1035699332)+W(3,-1097517035,1052576386,1055574555,-1097542777)+W(4,1046822141,-1107318253,-1114990789,-1110157019)+W(5,-1129223371,-1102887232,-1121581721,1031007843)+W(6,-1116759551,1040601750,-1152414880,-1157281192)+W(7,-1124684976,993535634,-1107957817,1025775603);WS(1063710542,-1111213649);
|
||||
sum1=W(0,1039559517,1052251350,-1101160384,-1113889808)+W(1,-1110192145,1049489370,-1097695264,1031901152)+W(2,-1107309859,1058328276,-1093740712,-1104513406)+W(3,-1118762901,1061120005,-1096321197,-1097003636)+W(4,-1108199122,1049656673,-1097289639,-1112381384)+W(5,1037245627,1033876357,-1114972772,-1176476024)+W(6,-1139769966,1041987905,-1102516745,1022802380)+W(7,1035326852,1045428971,-1103522251,-1115185874);sum2=W(0,1026803387,-1115186477,999853755,-1112425236)+W(1,1021750253,1031459540,1031446318,-1106593609)+W(2,1040812059,-1116326399,1058720440,-1086524651)+W(3,-1107480079,1040651083,1071698983,-1075753828)+W(4,1041131835,1020594503,1051128601,-1096266051)+W(5,-1115082464,1033768858,1034660038,-1108942599)+W(6,1006187407,-1132516997,1027131696,-1123360193)+W(7,1001155939,1015478283,1041372466,-1104453127);WS(1039772272,-1082982873);
|
||||
sum1=W(0,1039127452,1049032497,-1098139952,-1155633625)+W(1,-1106264016,1053169593,-1088020664,1043520647)+W(2,-1104546353,1060522592,-1087153807,1040400554)+W(3,-1145518233,1056693961,1038834197,-1139907193)+W(4,1041713673,-1095982984,1053429837,-1104883452)+W(5,1044410893,-1088607916,1048228018,-1103034636)+W(6,1039725795,-1099512929,1030077856,-1134131855)+W(7,1007790526,-1120546088,-1130616150,1012687882);sum2=W(0,1032987173,-1092902636,1027660911,1032111389)+W(1,-1102803435,1037122437,1039508875,-1101516234)+W(2,-1097110538,-1083842457,-1115097563,1001644292)+W(3,-1101871105,1067610414,1067552095,-1104358647)+W(4,-1101555589,1033006847,-1096151174,-1145661076)+W(5,-1123533577,1041814167,1026567371,-1104681426)+W(6,-1098769512,1045724867,-1107225085,1020958965)+W(7,1048796624,999019252,-1105667947,1028203943);WS(-1101412664,1073047832);
|
||||
sum1=W(0,-1113880945,1059007377,-1091904865,-1133362719)+W(1,-1123950537,1047579477,-1097814305,-1131741454)+W(2,-1109995975,1060416389,-1087199740,1032803377)+W(3,-1123565085,1056063051,-1092124214,-1113780884)+W(4,-1123728428,1046383171,-1099567891,-1113889390)+W(5,1035385983,1040643140,1038341800,-1126485237)+W(6,-1115318676,1033389702,-1119557930,1012558775)+W(7,1010675502,1041003725,1042882861,-1096461162);sum2=W(0,1013686761,1030949359,-1109223248,-1132915573)+W(1,-1123503757,1039110679,1035635962,996209923)+W(2,1035262859,-1105775253,-1106751414,1029135163)+W(3,-1115490710,1027204409,1057425426,1070858778)+W(4,1025861040,1019519396,1043312829,1067133266)+W(5,980681483,-1111394964,-1098000154,-1098902818)+W(6,-1125276038,1024413043,1051287795,-1083268694)+W(7,-1129892230,-1126757058,-1103421662,-1073095921);WS(-1103532344,-1105840701);
|
||||
sum1=W(0,-1106756472,-1105825052,1050195304,1044840709)+W(1,-1106322913,1053932942,1007328528,-1104890465)+W(2,1029810954,-1086676361,1057202097,-1144507642)+W(3,-1096389739,-1098358914,1054492326,-1098185309)+W(4,-1116067305,1054020609,-1093369370,1032208700)+W(5,1035916925,-1096691570,1012599092,1048715303)+W(6,-1105566449,1051257001,1027855335,-1100267787)+W(7,1034505108,1026552303,-1101687900,1050640157);sum2=W(0,-1111707317,-1101137684,-1116414033,-1103752872)+W(1,-1119262447,-1109186725,-1107841286,1034593530)+W(2,1037989791,1049211868,1056722210,-1110917586)+W(3,1056036881,-1099242284,-1094543747,1049861706)+W(4,-1105645897,1038198606,1053421235,1030171051)+W(5,1006194414,-1118866635,-1104714858,-1103907620)+W(6,-1146663095,-1109483964,-1120693058,1032413269)+W(7,-1129479912,-1114787638,-1115357885,1029169157);WS(1045178680,-1115117954);
|
||||
sum1=W(0,-1102680211,1048681528,1019008549,1008490315)+W(1,-1123018420,-1113607536,1040296293,1012835273)+W(2,-1116849368,-1092105355,1035615004,1027033246)+W(3,1024407336,-1093530556,1061339424,-1128145511)+W(4,-1107241006,-1096193779,1057711678,-1103222073)+W(5,1026392201,-1102060551,1055864515,-1110547491)+W(6,-1107918421,-1102337510,1045891981,-1110097884)+W(7,-1123314455,-1095199752,1052562824,1020395952);sum2=W(0,-1108321996,-1096948503,-1112108000,1026091852)+W(1,-1115537892,-1104693583,-1112710060,1022753169)+W(2,-1106228104,1047339287,-1126080161,-1120501740)+W(3,998645667,1055675007,1051246853,-1105262859)+W(4,-1112292909,1049114511,1041989299,-1123292948)+W(5,1035781218,-1100682049,1025978716,-1139782977)+W(6,-1111036660,1032758858,1034053890,-1111667328)+W(7,1018530825,-1113969306,-1113712936,1033000622);WS(1044590904,1058699692);
|
||||
sum1=W(0,985175380,-1092606720,1051210502,1009220799)+W(1,1034192409,-1090621088,1050384326,-1109361592)+W(2,1020554347,-1093618783,1055009987,-1117059707)+W(3,1024014533,-1113905855,1062574818,-1128567457)+W(4,-1115433194,-1096920415,1054554325,1015981863)+W(5,-1128687821,-1112503613,1031218808,1039114097)+W(6,1008304190,-1100279725,-1105751509,-1127205548)+W(7,-1115445028,-1101027255,-1144235755,1035507338);sum2=W(0,1036009101,-1108619644,1010492213,-1131279719)+W(1,-1117283755,1041337919,-1100684466,1035041542)+W(2,1033667347,1012813669,1015579759,-1124020763)+W(3,-1107239966,1053310286,1056064408,1025470531)+W(4,1034685217,-1103814148,1050883237,1032198922)+W(5,-1128406639,1029066827,-1113069964,-1104788458)+W(6,-1123321687,-1109499964,-1098878001,1024066141)+W(7,-1125402335,-1123197815,-1096911819,-1108347132);WS(1044030776,-1089132931);
|
||||
sum1=W(0,1034269487,-1093699058,1045160768,1040395197)+W(1,1032883970,-1097458090,1050995424,-1135242887)+W(2,1042439154,-1086092656,1057188990,1040422743)+W(3,1044751430,-1078975458,-1096290982,1048952172)+W(4,1019707982,1035194756,1032938655,1042217766)+W(5,1041434446,1038040390,1043682915,1043586045)+W(6,-1133288904,-1131544335,1022768458,1029073256)+W(7,-1128708109,-1101499019,1043305900,1044718778);sum2=W(0,1043294282,-1107262777,-1132728616,-1112978295)+W(1,-1127265324,-1107127922,-1133435576,-1101649503)+W(2,1035036911,1048700262,-1115280193,-1142433873)+W(3,1051203976,-1114081637,1060204569,-1138065032)+W(4,-1092441683,1027047222,-1096051714,1049542158)+W(5,1037063919,-1087538045,1059699424,1027406094)+W(6,-1095318743,1043898666,-1091030613,1036599707)+W(7,-1096741875,-1114635611,1057805441,-1117298502);WS(-1083489614,-1078579141);
|
||||
sum1=W(0,-1113694287,-1091060438,1048678744,1022130309)+W(1,1048897616,-1104759380,1055607032,1045345264)+W(2,-1104500498,-1089217572,1025763911,-1098656951)+W(3,1029397720,-1096433234,1056656214,1045280313)+W(4,1039983475,-1090900481,1055730826,1003335600)+W(5,-1099529286,-1103761763,1039576037,-1104729181)+W(6,1047818144,-1126261903,1050842685,1045845834)+W(7,-1100400745,-1098862766,1044462332,-1124798927);sum2=W(0,1034867092,-1113896283,-1089397746,1053130734)+W(1,1036831152,1008734783,-1143881728,1048547317)+W(2,-1155378720,-1107821706,-1090933436,1050664536)+W(3,1050005016,1036439980,1067046868,-1081990202)+W(4,-1109019109,-1105188391,1074023168,-1073616958)+W(5,-1107857756,-1103852014,1073004488,-1073650181)+W(6,1025727369,-1113326142,1071596064,-1078582463)+W(7,-1105627363,1036502992,1068047188,-1079035066);WS(-1123566816,-1118788492);
|
||||
sum1=W(0,1034266605,-1131696345,-1102436480,1029920799)+W(1,-1136553988,1054570946,-1101485920,1027694719)+W(2,1032767842,1043367745,-1093672570,1029228634)+W(3,-1119057557,1057910725,-1081257723,1038070160)+W(4,1032596498,1051309065,-1104247863,1041012541)+W(5,-1138237144,1050053561,-1097237249,-1104490509)+W(6,1034235800,1044754161,-1100737384,1036672371)+W(7,1038972738,1047609962,-1118734125,-1101643609);sum2=W(0,1001205015,-1108935456,-1123729961,-1151981614)+W(1,1006355343,1048575251,1037564428,-1123825361)+W(2,1030505158,-1114918170,-1096130861,1015236500)+W(3,-1119701641,-1088419213,-1068662368,-1095410362)+W(4,1039794598,1032736312,1076967646,1049774729)+W(5,-1107202062,1045905661,1068403675,-1105335733)+W(6,1026836118,-1116946341,-1104305708,1050153445)+W(7,-1115440174,1003805295,-1124006983,-1103176791);WS(-1103567160,1051728620);
|
||||
sum1=W(0,1022317012,1037463598,-1094952698,1033922872)+W(1,-1105517764,1027268637,-1107670055,1024776175)+W(2,-1109296554,1052072875,-1103880757,1038888053)+W(3,1030946149,-1094107172,1052944567,1043766492)+W(4,1032988986,-1087396213,1057943536,-1110506946)+W(5,-1117957958,-1098739651,1052382091,-1108829569)+W(6,1025729823,-1104965205,1036164793,-1132271979)+W(7,1009731405,1017302004,1041821631,1015545129);sum2=W(0,1031290011,-1127050317,-1113481669,-1080536402)+W(1,-1114551402,1026829489,1042490649,-1076466135)+W(2,-1137203270,1032334734,1043198364,1038797044)+W(3,1025723227,-1098446681,-1127701979,1074254195)+W(4,1020823723,1041359246,1057793899,1035340712)+W(5,-1107112701,1041376772,-1100591458,-1118262367)+W(6,-1156747895,1034398482,-1114292550,1013380262)+W(7,-1140368490,-1104694439,1037536680,1032104302);WS(-1106439480,1029090439);
|
||||
sum1=W(0,1034559195,1042655458,-1102396839,1026400220)+W(1,-1151887836,1030625962,-1115609614,1035325646)+W(2,1020849475,1059377738,-1089162129,1042909598)+W(3,1042053132,-1084013087,-1083731653,1039293086)+W(4,1043127920,-1107145304,1052971191,1029716960)+W(5,1043814293,1032281331,-1107154457,1024778063)+W(6,1037260390,1040913704,-1113717087,1028666946)+W(7,1043715864,1033172451,1017680531,-1130742978);sum2=W(0,-1129107524,1021999108,1022835844,-1129901940)+W(1,-1123636938,-1148550480,1016982596,-1140398984)+W(2,-1116921954,-1104180688,1016773924,1030858450)+W(3,1035143287,1058583951,1054454385,-1117386658)+W(4,1036996009,-1112895549,-1097314323,-1108156993)+W(5,1026655402,-1116180274,-1099699990,-1118751234)+W(6,-1117010042,-1131502740,-1132536424,1016259828)+W(7,-1126794884,-1138164712,-1129763396,-1117013506);WS(1048151864,1059242544);
|
||||
sum1=W(0,-1122367849,-1097114939,1043794348,1026875087)+W(1,-1121466768,-1097911384,1033810391,1014185912)+W(2,1042165293,-1085899247,1063564267,-1106211614)+W(3,-1116044868,1042506911,1042284551,-1111561384)+W(4,-1105437493,1056857214,-1089674786,1040868541)+W(5,1037358179,-1105063934,1049648847,1028107682)+W(6,-1125163356,-1123578292,1021855394,-1111395274)+W(7,-1111398955,-1106114902,1045389303,1010402126);sum2=W(0,-1139648101,-1110557326,-1106733442,1039330638)+W(1,-1108856547,1041627874,-1106727608,987619817)+W(2,1015236663,1032833232,1048813377,1025349119)+W(3,-1095822659,1054902128,1055403310,-1095503796)+W(4,-1137977893,-1098765424,-1097123375,1050144719)+W(5,1038373686,-1121592121,1045561320,-1108448514)+W(6,1015865663,-1106594443,-1106386080,1041979856)+W(7,1025690243,-1117564251,1017823319,-1105901385);WS(1058511566,1043187024);
|
||||
sum1=W(0,1042620242,1041476871,-1106861387,1043942651)+W(1,1027981614,1044640335,-1120607404,1040914531)+W(2,1037513401,1039039385,-1101062960,1040902562)+W(3,1050564856,-1085132912,-1089194338,1048598306)+W(4,1040390932,-1095196494,1032203084,1019897185)+W(5,1044188393,-1116362934,-1134658518,1032634704)+W(6,1032851398,-1107832665,1026497359,1027555603)+W(7,1043046140,-1105825814,-1105488567,1032742569);sum2=W(0,-1094808435,-1083260450,1041967320,1026111290)+W(1,-1132385524,-1089624726,-1102801635,1034887813)+W(2,-1110994277,-1098133391,1050258559,-1123786474)+W(3,1039748829,1063143581,1037743779,1033106845)+W(4,1038866141,1043371703,1048943341,-1110363077)+W(5,1012861192,1040218148,-1112998265,-1121754906)+W(6,1030487914,1012758152,1031702418,1012203560)+W(7,-1132742376,1052570990,-1105604919,-1111765769);WS(-1087236686,1061665912);
|
||||
sum1=W(0,-1115274057,1023071688,-1107980923,-1119301463)+W(1,-1116162424,1030200068,-1101866270,-1128116268)+W(2,-1104461343,1054050807,-1092884195,-1109238785)+W(3,-1093387666,1067462106,1056570668,-1095571507)+W(4,-1113556238,1050597447,1044256537,-1103733247)+W(5,-1115159031,1031104576,-1106234576,-1111522325)+W(6,-1126942285,-1121547516,-1128835891,-1111458030)+W(7,-1121543315,1042315272,-1114796114,-1109780718);sum2=W(0,-1127633710,1024134807,-1114424195,-1109129714)+W(1,1024854732,1020748524,-1098546148,1025355297)+W(2,-1123781128,-1117094752,-1079772750,-1102118069)+W(3,1040493279,1065417820,1059484680,-1114766469)+W(4,-1105896535,1047826025,-1107504040,1033237727)+W(5,1033983514,-1102101577,1049649199,-1154145757)+W(6,-1122459292,1040101538,-1105983778,1012710689)+W(7,-1120616672,-1124130304,1041220419,-1123999628);WS(-1092106140,-1084163121);
|
||||
sum1=W(0,1036347305,1049849489,-1101083230,-1106738110)+W(1,1016904817,1040213041,-1152694122,-1115216475)+W(2,1034414494,1056746079,-1083169173,1039797369)+W(3,1040590819,1048812489,-1107117385,1022569263)+W(4,1047670567,-1084779712,1051667767,-1112982247)+W(5,1030378702,1040726752,-1109066592,-1125038036)+W(6,-1114654031,1033236350,1024925978,1025136605)+W(7,1037868673,1034988241,-1107106473,-1146668256);sum2=W(0,-1144361879,-1111008682,-1092072719,1021883158)+W(1,-1128843246,-1134810723,-1121102479,-1116668390)+W(2,1005924247,1041181160,1045581242,-1109114373)+W(3,-1104940693,1054697191,1046555600,-1113715104)+W(4,-1123234701,1052731012,-1103970223,-1128555074)+W(5,1030348431,1042931729,-1104348933,1032936433)+W(6,1032437115,-1112071203,-1113690885,-1136719027)+W(7,1024671661,-1111460488,-1129885552,-1114960949);WS(1058637774,-1109876822);
|
||||
sum1=W(0,-1123254812,1042623060,-1126486401,-1112485473)+W(1,1041301297,-1105094644,-1111052512,1037949088)+W(2,-1108082435,1059472952,-1094910408,1016105496)+W(3,-1113241451,1043969956,-1094009726,1038892497)+W(4,-1110973875,-1113269955,1058531737,-1093047519)+W(5,1027216056,1026816394,-1100061186,1032398170)+W(6,1014894339,-1130602892,1032486130,-1128303438)+W(7,1019588394,1026167148,-1117291247,1021704844);sum2=W(0,1019183838,-1103677237,1041385745,-1115238116)+W(1,1031923668,1026573624,1025625867,1024201143)+W(2,1049015983,-1101357077,-1095136476,1024442030)+W(3,-1096362417,1060010174,-1096248497,-1122837727)+W(4,1005830618,-1122620605,-1115221092,1034369966)+W(5,1036998273,-1106684685,1049273019,1031554545)+W(6,-1119396253,1023743335,-1112424814,1004099770)+W(7,-1125844722,970656667,1011280453,1010302645);WS(1068382951,-1145853862);
|
||||
sum1=W(0,-1109092968,-1104283584,-1126224104,-1142984099)+W(1,-1120835030,-1104742016,1048835390,1035504970)+W(2,1015957108,-1087137628,1060142968,1044651720)+W(3,1033165317,-1082841532,1050512116,1036256010)+W(4,1015780402,1048723479,1050625794,1040271692)+W(5,-1098982451,-1119342334,1046183055,-1112268532)+W(6,-1106789039,1037068029,1033167819,-1115364877)+W(7,-1105810191,998682871,1042826568,-1113754717);sum2=W(0,1042289605,-1105845074,-1105090355,1041479887)+W(1,-1123754179,1032442894,-1106552079,1028813354)+W(2,1040865617,-1090127653,-1075116096,-1087510643)+W(3,1025996190,1055606718,1073431719,-1084272058)+W(4,-1100913998,-1104101067,1067916428,1045036562)+W(5,-1118459936,1026136504,1042119939,-1131666845)+W(6,-1114401734,1031986833,-1112990087,1021173748)+W(7,-1118182115,1045409779,1031635830,-1131440550);WS(-1115823328,-1115141930);
|
||||
sum1=W(0,994860217,-1096937968,1034643656,1022968545)+W(1,1043355533,-1093401724,1045563268,-1100277972)+W(2,1046651158,-1082957735,1056739037,-1106135459)+W(3,1031967699,1057829358,1053028032,-1113373017)+W(4,-1112906011,1054780763,-1085595451,1036473238)+W(5,-1139800861,1049387203,-1100812438,1042166401)+W(6,1032268536,1029694230,-1112691098,-1109328859)+W(7,1021673189,1032667294,-1163065290,1026417494);sum2=W(0,1041009418,1006794492,1023178506,-1126244586)+W(1,-1106230161,1034312638,-1120362931,1021996758)+W(2,-1113994011,-1108126219,-1105213924,-1131146954)+W(3,-1100787264,1060460225,1054015707,997147503)+W(4,-1102450993,-1119222967,1053508358,-1107185372)+W(5,-1114680808,-1097084093,-1133314452,-1126416406)+W(6,1031764893,-1125377404,-1141774536,-1126617106)+W(7,-1145068408,-1105852265,-1120752408,-1131039214);WS(1044911928,1063248560);
|
||||
sum1=W(0,-1117210934,-1089987573,1050931427,-1154913199)+W(1,1045807559,1006551364,1049202419,1049427019)+W(2,-1116245664,-1085623154,1044690392,-1098224261)+W(3,-1122601008,-1098705597,1056494849,1043742399)+W(4,1041679280,-1089608778,1054654497,1009817082)+W(5,-1102494868,-1098692501,1047881833,-1102952115)+W(6,1044187563,1040126000,1043119951,1048685800)+W(7,-1101059428,-1100421777,1043071666,-1132265536);sum2=W(0,-1110897864,1031814971,1060526454,-1090228093)+W(1,-1104703066,-1126406622,1034850394,-1097166620)+W(2,1039476246,-1112535334,1060516426,-1091926928)+W(3,-1102025112,-1088994686,-1088701567,1063814816)+W(4,1041770976,1050082866,-1072347435,1074296249)+W(5,1044782005,1038057456,-1075073775,1073862535)+W(6,-1112640404,1029663347,-1077197270,1067261757)+W(7,1045848501,-1098794387,-1081012351,1067785227);WS(-1105546040,1026157880);
|
||||
sum1=W(0,1040950836,1040614249,-1102499357,1036650571)+W(1,1036866652,1043435937,1032157499,1032871003)+W(2,1045419231,1048836647,-1088963702,1035867609)+W(3,1057171433,-1092874056,-1078642173,1040635958)+W(4,1039696013,1049109967,-1094603626,1039966133)+W(5,1040737235,1037560064,999044599,1035782037)+W(6,1031337694,1039556030,-1107844556,1034875342)+W(7,1043417390,1020658754,-1101965321,1029450491);sum2=W(0,999804672,1033414560,-1131242272,-1111239120)+W(1,965076992,-1142972544,-1152459008,-1114613368)+W(2,1017997216,-1117537424,1043660652,1024438240)+W(3,-1113573416,-1080122522,1068973644,1009242816)+W(4,1015814944,-1116987776,-1113471168,1026341216)+W(5,1013150208,1009041344,1023678672,-1111376032)+W(6,1004325632,1030258512,-1115573696,-1124670336)+W(7,-1116017408,-1123867424,1025739248,1011147520);WS(-1081027239,1060388068);
|
||||
sum1=W(0,1040945153,1049191505,-1103567931,-1142725077)+W(1,1018532824,1052335227,-1106690587,-1126830164)+W(2,1048158700,1053224518,-1098210230,1044049241)+W(3,1050078256,-1089652372,-1079677805,1037048166)+W(4,1043330564,1050009062,-1090769236,1037549983)+W(5,1045983912,1019623144,-1102526621,-1124021470)+W(6,1034126717,1043374892,-1113976903,1031972104)+W(7,1042366848,1037373643,-1106920486,1000910717);sum2=W(0,1029289565,-1119356133,-1126159585,-1119814653)+W(1,1023484285,1031916514,-1111485988,-1133461586)+W(2,1041097307,-1120749829,-1121314077,-1112201820)+W(3,1044843621,1057057740,1024531885,1001931237)+W(4,-1101664529,1055633817,-1102656055,1035253182)+W(5,-1108647964,-1098024997,1016983721,1019582313)+W(6,-1111945130,1038083406,-1105960100,1011319026)+W(7,-1129898257,-1101101054,1022769465,-1110859200);WS(-1121436896,-1083449266);
|
||||
sum1=W(0,-1131437006,1057845458,-1096100393,-1112818966)+W(1,-1126965659,1026072602,-1106937331,1025271436)+W(2,-1106898372,1058188821,-1089458543,-1120770471)+W(3,1049661628,1047051462,-1093909527,1039868950)+W(4,-1110051320,1036301673,-1105302990,-1101852248)+W(5,1048826500,1049513187,-1097831955,1048680544)+W(6,1018834023,1026266705,-1115312055,-1111779257)+W(7,1030351624,1043516478,-1094725407,-1137214404);sum2=W(0,1025140224,-1118806788,-1126785121,1031495588)+W(1,1016993788,1030590564,-1118559458,991152164)+W(2,-1106156741,1042721449,-1106137914,1038491925)+W(3,-1085967118,1078987048,-1100137345,1040984057)+W(4,-1070014283,1078555235,1044823121,-1111978905)+W(5,-1066270592,1069325982,-1105174392,1030579932)+W(6,-1089828448,1051485796,-1121082393,-1113499951)+W(7,-1115300709,1026006822,1011662011,-1120641633);WS(1060473294,-1125032523);
|
||||
sum1=W(0,-1118381578,1043924207,1028842287,-1103983036)+W(1,-1131528546,1048790648,-1094915206,1032416951)+W(2,-1103035725,1057928103,1048586166,-1131359957)+W(3,1044891665,-1096003632,-1089668066,1041536420)+W(4,1017562024,-1104437021,1048997587,-1119623443)+W(5,1038728371,-1127678449,-1106021950,1026802338)+W(6,1013193724,-1138265298,1016196772,-1112764523)+W(7,1017619335,1019650740,-1112334062,1028850580);sum2=W(0,-1124013145,1023871771,1041717973,1027246941)+W(1,-1154979909,-1104183315,-1104961174,-1105906795)+W(2,-1113455493,1024353365,-1071159846,-1114760758)+W(3,1042673063,-1099433949,1075222357,1048045634)+W(4,1009341589,1037029004,1061754151,-1101645527)+W(5,-1131887235,-1106752952,-1106459992,1027783079)+W(6,-1126494367,-1136822537,1037905746,-1130069351)+W(7,-1120394460,-1135604889,1020599743,1023779471);WS(1063175758,1049951270);
|
||||
sum1=W(0,1051934199,-1084051495,1040719576,1028219745)+W(1,1041620825,-1091045702,1046456792,1028165760)+W(2,1053157077,-1089200998,1054477181,-1110307566)+W(3,1019501037,-1103613676,1050464826,1037889601)+W(4,-1121035141,-1103906809,-1098419444,1045652053)+W(5,1024394007,1042850683,-1097805325,1054554722)+W(6,1034798936,-1117239270,1011564046,1031152711)+W(7,999909159,-1106705027,-1091232034,1056053333);sum2=W(0,-1091471926,1062079447,1055700238,1015596856)+W(1,1042259987,-1095572989,1041645665,1033532620)+W(2,-1103057728,-1089203271,1037140407,1035045090)+W(3,1049412228,-1092861102,-1093629070,1042934527)+W(4,1044973062,1034556296,-1095940003,1032040702)+W(5,-1116401558,1047552828,-1106623325,-1106239816)+W(6,1011000463,-1110031497,-1107294450,1033073048)+W(7,-1130123924,1051271629,1053844390,-1095799213);WS(-1085388366,-1090694979);
|
||||
sum1=W(0,-1123787314,1044273497,-1108110651,-1115475932)+W(1,-1119481145,-1130943626,1041576542,-1117135031)+W(2,1032777214,1047368143,-1087220302,1040347561)+W(3,-1112850502,1059845268,1027588771,-1101064470)+W(4,1041751591,-1095680144,1036323946,1037523789)+W(5,-1125429276,1039407200,-1111657568,-1126225621)+W(6,-1140788444,990533574,1021334836,-1134357621)+W(7,-1113892940,1032644049,-1143449895,-1109271006);sum2=W(0,-1107190004,1037736456,-1125693587,-1120404934)+W(1,1013881877,-1105376838,1040619572,-1122228614)+W(2,-1118295314,-1123416196,-1082924015,1051908042)+W(3,-1121103222,1042717593,1068021664,-1087341114)+W(4,-1127822751,-1115549939,1016978358,1042189807)+W(5,-1115317828,1043660085,-1108863865,-1125959243)+W(6,-1126179247,-1126402007,-1136349779,1038966556)+W(7,-1114801766,1040920849,-1107267301,1023515477);WS(1065904679,-1122628785);
|
||||
return clamp(mstd0 + 5.0 * vsum / wsum * mstd1, 0.0, 1.0);
|
||||
} // nnedi3
|
||||
vec4 hook() {
|
||||
vec4 ret = vec4(0.0);
|
||||
vec4 samples[8];
|
||||
samples[0][0] = HOOKED_texOff(vec2(-3.0, -1.0)).x;
|
||||
samples[0][1] = HOOKED_texOff(vec2(-3.0, 0.0)).x;
|
||||
samples[0][2] = HOOKED_texOff(vec2(-3.0, 1.0)).x;
|
||||
samples[0][3] = HOOKED_texOff(vec2(-3.0, 2.0)).x;
|
||||
samples[1][0] = HOOKED_texOff(vec2(-2.0, -1.0)).x;
|
||||
samples[1][1] = HOOKED_texOff(vec2(-2.0, 0.0)).x;
|
||||
samples[1][2] = HOOKED_texOff(vec2(-2.0, 1.0)).x;
|
||||
samples[1][3] = HOOKED_texOff(vec2(-2.0, 2.0)).x;
|
||||
samples[2][0] = HOOKED_texOff(vec2(-1.0, -1.0)).x;
|
||||
samples[2][1] = HOOKED_texOff(vec2(-1.0, 0.0)).x;
|
||||
samples[2][2] = HOOKED_texOff(vec2(-1.0, 1.0)).x;
|
||||
samples[2][3] = HOOKED_texOff(vec2(-1.0, 2.0)).x;
|
||||
samples[3][0] = HOOKED_texOff(vec2(0.0, -1.0)).x;
|
||||
samples[3][1] = HOOKED_texOff(vec2(0.0, 0.0)).x;
|
||||
samples[3][2] = HOOKED_texOff(vec2(0.0, 1.0)).x;
|
||||
samples[3][3] = HOOKED_texOff(vec2(0.0, 2.0)).x;
|
||||
samples[4][0] = HOOKED_texOff(vec2(1.0, -1.0)).x;
|
||||
samples[4][1] = HOOKED_texOff(vec2(1.0, 0.0)).x;
|
||||
samples[4][2] = HOOKED_texOff(vec2(1.0, 1.0)).x;
|
||||
samples[4][3] = HOOKED_texOff(vec2(1.0, 2.0)).x;
|
||||
samples[5][0] = HOOKED_texOff(vec2(2.0, -1.0)).x;
|
||||
samples[5][1] = HOOKED_texOff(vec2(2.0, 0.0)).x;
|
||||
samples[5][2] = HOOKED_texOff(vec2(2.0, 1.0)).x;
|
||||
samples[5][3] = HOOKED_texOff(vec2(2.0, 2.0)).x;
|
||||
samples[6][0] = HOOKED_texOff(vec2(3.0, -1.0)).x;
|
||||
samples[6][1] = HOOKED_texOff(vec2(3.0, 0.0)).x;
|
||||
samples[6][2] = HOOKED_texOff(vec2(3.0, 1.0)).x;
|
||||
samples[6][3] = HOOKED_texOff(vec2(3.0, 2.0)).x;
|
||||
samples[7][0] = HOOKED_texOff(vec2(4.0, -1.0)).x;
|
||||
samples[7][1] = HOOKED_texOff(vec2(4.0, 0.0)).x;
|
||||
samples[7][2] = HOOKED_texOff(vec2(4.0, 1.0)).x;
|
||||
samples[7][3] = HOOKED_texOff(vec2(4.0, 2.0)).x;
|
||||
ret[0] = nnedi3(samples);
|
||||
return ret;
|
||||
} // hook
|
||||
//!DESC NNEDI3 (combine_y, nns128, win8x4)
|
||||
//!HOOK LUMA
|
||||
//!BIND HOOKED
|
||||
//!BIND nnedi3_int
|
||||
//!HEIGHT 2 HOOKED.h *
|
||||
//!OFFSET 0.000000 -0.500000
|
||||
//!WHEN HOOKED.h OUTPUT.h / 0.707106 <
|
||||
vec4 hook() {
|
||||
vec2 dir = fract(HOOKED_pos * HOOKED_size) - 0.5;
|
||||
if (dir.y < 0.0) {
|
||||
return HOOKED_texOff(-dir);
|
||||
} else {
|
||||
return nnedi3_int_texOff(-dir);
|
||||
}
|
||||
}
|
||||
//!DESC NNEDI3 (double_x, nns128, win8x4)
|
||||
//!HOOK LUMA
|
||||
//!BIND HOOKED
|
||||
//!SAVE nnedi3_int
|
||||
//!WHEN HOOKED.w OUTPUT.w / 0.707106 <
|
||||
float nnedi3(vec4 samples[8]) {
|
||||
float sum = 0.0, sumsq = 0.0;
|
||||
for (int i = 0; i < 8; i++) {
|
||||
sum += dot(samples[i], vec4(1.0));
|
||||
sumsq += dot(samples[i], samples[i]);
|
||||
}
|
||||
float mstd0 = sum / 32.0;
|
||||
float mstd1 = sumsq / 32.0 - mstd0 * mstd0;
|
||||
float mstd2 = mix(0.0, inversesqrt(mstd1), mstd1 >= 1.192092896e-7);
|
||||
mstd1 *= mstd2;
|
||||
float vsum = 0.0, wsum = 0.0, sum1, sum2;
|
||||
#define T(x) intBitsToFloat(x)
|
||||
#define W(i,w0,w1,w2,w3) dot(samples[i],vec4(T(w0),T(w1),T(w2),T(w3)))
|
||||
#define WS(w0,w1) sum1 = exp(sum1 * mstd2 + T(w0)); sum2 = sum2 * mstd2 + T(w1); wsum += sum1; vsum += sum1*(sum2/(1.0+abs(sum2)));
|
||||
sum1=W(0,-1106336704,-1134422686,-1097058997,-1096794255)+W(1,-1096428577,-1108910446,-1110459731,-1101174078)+W(2,-1104338237,-1108550970,1036063029,1068454954)+W(3,1045547931,-1102009308,-1122481515,1017740065)+W(4,1041734649,-1135080854,1053379177,1068510503)+W(5,-1114733521,-1146436468,-1107441476,-1113618698)+W(6,-1112016931,-1117701445,-1099451832,-1092648385)+W(7,-1101312270,-1118387353,-1118789516,-1107281979);sum2=W(0,-1107960738,1022891960,-1112828174,-1099542471)+W(1,1028527356,-1124169384,1003609248,1019646072)+W(2,1034572820,1003346080,-1096749055,1067566060)+W(3,-1090311143,1028295012,-1101382023,-1102277943)+W(4,-1105088633,-1103397515,1056062200,-1127174872)+W(5,1048792675,-1106700271,1033154740,1037356874)+W(6,-1147785184,1035529310,-1105585021,1034766166)+W(7,-1117109292,-1116900804,-1121486356,-1114899026);WS(-1075683047,-1087125913);
|
||||
sum1=W(0,1042687663,1034752002,1020877136,1043598702)+W(1,1032834596,1049059763,1041786741,1050972591)+W(2,1052977914,1046022844,1051043629,1049374510)+W(3,1044576234,-1108783446,-1105784362,-1089957133)+W(4,-1087267578,-1097639380,-1087388173,-1095656786)+W(5,-1108370107,-1101488315,-1111228387,-1108747496)+W(6,1041384601,1034807969,1037740431,1044538321)+W(7,-1113942663,1043415765,1011031587,1034104676);sum2=W(0,-1129327146,-1149557934,1027469999,-1116270499)+W(1,-1107094547,-1114668504,-1136313139,-1115408970)+W(2,-1112916736,-1120018795,-1105442406,1056936993)+W(3,1036431709,1029410453,-1126491682,-1112281372)+W(4,-1109246006,1012425107,1044505132,1054092693)+W(5,1015080154,-1102188513,-1123974759,-1115235380)+W(6,-1168639863,-1122303521,-1114911422,-1109477794)+W(7,-1122292075,1038663029,-1124857486,1004657207);WS(1042212664,-1102203684);
|
||||
sum1=W(0,-1140902818,1019874102,-1138465404,1041713132)+W(1,1031911135,1032244040,-1122713961,1032066151)+W(2,1040147851,-1104962202,-1102798136,-1085739950)+W(3,-1090423514,-1096835716,1015091005,-1100137137)+W(4,1035472140,1045102086,1044852023,1052255697)+W(5,1050093153,-1114874577,-1125530488,1025859399)+W(6,-1111794429,1033944684,-1122108180,1042129278)+W(7,1026181805,1045351411,1045226448,1037723887);sum2=W(0,1025219442,-1119436548,1041363772,1026037858)+W(1,-1106963956,-1148187164,-1115265228,1027834104)+W(2,-1109152196,-1122141349,1032935700,-1095545125)+W(3,1029288712,1048235476,1017807431,-1124373883)+W(4,1026944460,1040314652,-1124096755,-1132954458)+W(5,1063106013,1044093468,-1119277141,-1115291573)+W(6,-1136900198,-1112897189,-1144192892,1046665648)+W(7,-1112667488,-1091150222,-1098670428,-1099776205);WS(-1106435384,1038338229);
|
||||
sum1=W(0,1040095954,1019822615,1037825128,1041126536)+W(1,1042659628,1046281616,1025627498,1052688116)+W(2,1057302312,1048464174,1048602738,1046177110)+W(3,-1113571175,1010729037,-1116720143,-1090676327)+W(4,-1085504617,-1109673285,-1088007186,-1089584127)+W(5,-1112427435,-1099904421,985851280,-1109333660)+W(6,1038469973,1008999077,1047759857,1042217259)+W(7,-1122205838,1042535855,1020820192,1034203799);sum2=W(0,1016257202,1025056091,-1123344133,-1117490597)+W(1,-1139226916,-1121712633,1032149092,1018740994)+W(2,1059204215,1059357388,-1096239491,-1080318626)+W(3,-1097775023,-1121076469,-1108589001,1042934709)+W(4,1078138204,1057901024,-1075026282,-1073900782)+W(5,1041808545,1040778731,1040543247,1013253724)+W(6,1045786159,-1115583727,1040463834,1043123901)+W(7,1021989454,-1105966927,1015040126,-1147555881);WS(-1079558823,-1098708322);
|
||||
sum1=W(0,-1107155318,1025234303,1015859078,1036194249)+W(1,-1109510417,-1106597869,-1106784003,-1107821257)+W(2,-1102044491,-1098872409,-1087610848,-1086405173)+W(3,1049149960,-1113006787,1034815041,-1109243348)+W(4,-1157836704,1050456336,1055919296,1051086989)+W(5,1049231261,1047976577,1037659280,1045770027)+W(6,1018716763,1032647774,1043448582,1041211303)+W(7,1032229161,-1113988824,-1114873522,-1115826050);sum2=W(0,-1115121954,1012713185,-1120959275,979525395)+W(1,1031308048,1023425822,1008898041,1015643115)+W(2,1038073794,-1114116718,1048906430,-1089285214)+W(3,1044939824,960279117,-1114246838,-1116674868)+W(4,-1128914993,1041575276,1074552079,-1076455267)+W(5,-1081125046,-1109266711,1028966618,-1116558128)+W(6,-1116577465,-1124395325,1055266270,1060162115)+W(7,-1098098687,1021768571,-1124862202,1013382601);WS(1045132600,-1120782135);
|
||||
sum1=W(0,-1105751784,-1105178898,-1104184899,-1114219853)+W(1,-1110381909,1038688878,-1129240105,1028338913)+W(2,1057393815,1048859946,1059464001,1046945589)+W(3,-1115358437,-1101266388,1006928425,1001553277)+W(4,-1105555137,-1097544977,-1093321826,-1096850414)+W(5,1045680426,1054674458,1040711722,1051440502)+W(6,-1117651397,1030868229,-1113548192,-1114482291)+W(7,-1100710867,-1101910270,-1109195062,-1106616547);sum2=W(0,1017265392,-1109811903,1023756444,-1113627340)+W(1,1014378799,-1145950526,-1129429444,1013677319)+W(2,1041015042,1031690548,1041543835,1061785433)+W(3,-1112539854,1033767962,-1111764061,-1098545742)+W(4,-1100279165,-1110095441,-1121800962,1052269299)+W(5,1027655784,-1103181542,-1110834939,-1106577514)+W(6,1015388608,-1118750728,1018680528,-1143924414)+W(7,-1099334823,1020584168,-1108053853,1036964648);WS(1052573852,-1122511817);
|
||||
sum1=W(0,-1122539822,1036520122,-1150669710,-1131456914)+W(1,1027717464,1032118773,1021054902,1030809195)+W(2,-1107197216,-1104137920,-1095755763,-1089160552)+W(3,-1090293588,-1090056564,-1092174087,-1086001910)+W(4,-1123108403,1038549849,1032946604,1050538028)+W(5,1052989852,1057974832,1053464075,1057808582)+W(6,1051517474,1023654291,1039184399,1041388597)+W(7,-1168884669,1033029075,1028526105,1041880934);sum2=W(0,-1085894681,1038192816,-1098445483,-1102898046)+W(1,1008806191,1050638036,-1102617523,1057325981)+W(2,-1108201039,-1090848333,1052221636,1071505414)+W(3,-1098981857,-1086351349,-1096799400,-1088620184)+W(4,1070882268,-1093216289,1067999858,1073865984)+W(5,1058878464,-1083525828,-1107159037,-1083206959)+W(6,-1081052443,-1102549623,-1087793608,-1090403840)+W(7,-1095780376,1055133376,-1096503933,1053790412);WS(-1073219892,-1080326418);
|
||||
sum1=W(0,-1114077580,-1142635506,-1142955026,-1123237842)+W(1,1038107057,-1103324917,1026598572,-1095875035)+W(2,-1101602915,-1103425331,-1090278522,-1092662145)+W(3,-1091646784,-1114692451,-1101848592,1038718196)+W(4,1057495924,1053716920,1055741332,1051447237)+W(5,1052494629,1049044089,1043005848,1047828379)+W(6,-1151047116,-1114784094,-1111276924,-1121668701)+W(7,1000704387,-1109204280,1010568075,-1156952092);sum2=W(0,-1121663397,-1116542136,1042431779,1037730633)+W(1,1010053773,-1137348615,1028087910,-1119025600)+W(2,-1095443331,1050195534,-1123573301,-1100504352)+W(3,1043186658,-1102861372,-1110454800,1040229501)+W(4,-1067370736,-1071776975,1068672794,1077012119)+W(5,1070664889,1045361006,-1123945395,1027642294)+W(6,1005231721,974104521,-1111985184,1047585075)+W(7,1016528922,-1109020232,1037668055,-1117277443);WS(-1130027456,1047744266);
|
||||
sum1=W(0,1030328637,-1100312969,1036569044,1044449278)+W(1,-1106699970,1046212150,-1104762293,-1124975021)+W(2,-1103440100,1043447132,-1096543805,-1093151398)+W(3,1024264999,-1115860524,1041344218,1032410566)+W(4,1050534604,1038395889,1037345619,-1106526388)+W(5,-1115006287,1035372917,980910400,1044066628)+W(6,-1130350917,-1105733872,1043114871,1022399622)+W(7,1020228332,1024836117,-1123108872,-1112803412);sum2=W(0,1029880722,-1098453144,1029103498,1067660000)+W(1,-1094604015,1046293202,-1104816365,-1117927817)+W(2,1033391383,1041649400,-1095624145,-1082091368)+W(3,1056223691,1027973488,1034193475,1034286113)+W(4,-1137819024,-1137377888,1040796761,-1080643124)+W(5,-1102259819,-1121978412,-1148596400,1041009105)+W(6,-1114516031,1025620716,1035240799,1066795978)+W(7,-1098376459,1036814117,-1107858514,-1114981924);WS(1049012636,1037011386);
|
||||
sum1=W(0,-1108102978,1042768739,1036457352,-1105146600)+W(1,-1100621772,-1100160944,-1149100234,-1116535239)+W(2,-1097922903,-1089977373,-1083790961,1050515995)+W(3,1053649082,1044221701,1020595485,-1110188826)+W(4,1049818257,1052134241,1059747641,1062551839)+W(5,-1088576433,-1093385002,-1108848982,-1147628986)+W(6,1041216474,-1106782690,-1120768141,975424142)+W(7,1042971413,1047421135,-1142399358,1034144007);sum2=W(0,-1130376652,-1109307779,998991648,-1105231849)+W(1,-1124853008,-1110904873,1033926100,1012787248)+W(2,-1109271051,1040605589,-1117670218,1068278024)+W(3,-1099193318,1035466738,-1111928806,1025845624)+W(4,-1098570547,-1097221185,-1087670872,1068017963)+W(5,-1103240593,1049832589,1018913792,1035573068)+W(6,1029552052,-1097745138,-1101762859,-1100990121)+W(7,-1094879980,-1119653306,-1099498770,1046656503);WS(-1099128120,1074104605);
|
||||
sum1=W(0,1001695642,-1114738061,-1137881464,1035838167)+W(1,1036976671,1043227732,1024532056,1041576607)+W(2,1031876531,1036082771,1049670772,1045634202)+W(3,1039176783,1044499416,-1115296143,1036111714)+W(4,-1106225286,-1127447088,-1114090766,-1084335000)+W(5,-1092101927,-1106295064,-1108352670,-1103209586)+W(6,1039516460,1037331996,1048871226,1024672505)+W(7,-1111706306,1040216275,1018355325,-1129216251);sum2=W(0,-1125983803,1026289226,1003361806,1036989304)+W(1,-1121376018,-1127516251,999276462,1020382491)+W(2,1057121124,1048908439,1042597022,-1101738899)+W(3,-1101518001,-1114490175,1032222895,-1111061815)+W(4,-1097673861,-1081617292,-1083990029,1066557847)+W(5,1050089807,1021212715,-1107462587,1048167829)+W(6,-1097055530,-1105528539,-1094090339,1060807350)+W(7,1045798092,1007168711,1021142275,1024157832);WS(1043392312,-1114334171);
|
||||
sum1=W(0,1041086874,1027676176,1029494548,1038182418)+W(1,1033375641,1014428948,1016176348,1036956537)+W(2,1046571639,1051603231,-1114765098,1063881062)+W(3,1036439434,1039261900,1049353410,1039119196)+W(4,-1101297859,-1100311555,-1090719068,-1092551191)+W(5,-1093343060,-1095549099,-1102133676,-1097401399)+W(6,-1108043111,1031499310,-1123479337,1047470620)+W(7,1029157954,-1113522785,1032866554,-1108903402);sum2=W(0,1032922039,1034144522,1035186417,-1106146153)+W(1,995983013,1014708981,-1118508182,-1122673776)+W(2,-1110774431,1041464609,-1089347840,1063858171)+W(3,-1103182741,-1105498679,1046443094,-1107403517)+W(4,1024080221,1024001520,-1102975683,1062496232)+W(5,-1104694448,1034761930,-1113235807,-1126790312)+W(6,-1111786600,1038622987,-1098326560,-1094555153)+W(7,-1110476474,-1107944280,1045574278,-1119406695);WS(1055141020,1060902337);
|
||||
sum1=W(0,1034435725,-1133288704,1026181508,1033934442)+W(1,1030709219,-1118188821,1027652318,1035419593)+W(2,1057965143,1052483105,1052696320,-1122504460)+W(3,1052884304,1049027177,1046782257,1045790650)+W(4,-1123568702,-1121795134,-1094115828,-1084201687)+W(5,-1093347107,-1096042081,-1098441692,-1101051195)+W(6,-1104499136,1006999415,-1153162900,1029709087)+W(7,1036285529,-1155692311,1013713298,-1111952258);sum2=W(0,1043194323,1017945729,992756489,-1117717167)+W(1,1023440269,-1108161809,1034607052,-1115924363)+W(2,-1070666261,-1075189642,1068575013,1076566585)+W(3,1056539999,-1098049115,1036076910,-1112346970)+W(4,-1098866335,-1106608294,1051129947,1049134123)+W(5,1047751107,-1097073139,1011007330,1016205049)+W(6,-1101126135,1010301074,-1107911121,1046700061)+W(7,1020103457,1026363561,1035420194,-1137869730);WS(-1090579868,1070279725);
|
||||
sum1=W(0,1032329895,-1102328821,-1113203900,-1098061089)+W(1,-1105344998,1034205973,-1106552005,1041435478)+W(2,1048430680,1050349544,1052980239,1057014372)+W(3,1057962188,1038273502,1046276062,1049777060)+W(4,-1101560157,-1091335294,1039656780,-1084573078)+W(5,-1103450436,1043587871,-1098888483,1002064136)+W(6,-1129281319,1012204235,1033674783,-1115372202)+W(7,-1108117804,-1111454739,-1115265901,-1109943484);sum2=W(0,987673807,1036995374,-1095509641,-1094252408)+W(1,-1119095571,-1103179232,1040985329,-1114181285)+W(2,1027892228,-1102736131,1034852634,1059241808)+W(3,-1103859919,1043446486,-1109795439,1004807604)+W(4,-1103141235,1049007178,-1090760003,1060311666)+W(5,-1129798465,-1100012675,1051746582,-1113144024)+W(6,1005138532,1028221332,-1123669832,-1128511149)+W(7,1032914452,1006285508,-1122773902,987177167);WS(1058381774,-1086956646);
|
||||
sum1=W(0,1005434106,-1149835360,1034370117,1036055789)+W(1,1007595428,-1173712576,-1122685332,-1119060568)+W(2,-1096145742,-1100460324,-1096424577,1033532617)+W(3,1049990129,1042033667,-1147483724,1021597150)+W(4,1046241393,1039571170,1054608457,-1110152984)+W(5,-1100950084,-1103984787,-1122634471,1016207588)+W(6,1026532260,-1120107684,-1107524072,-1123297125)+W(7,1032832748,1041584782,-1111048693,1023439817);sum2=W(0,1073050559,1069067455,-1096535796,-1073893027)+W(1,-1077684470,1038335059,994568047,-1109196141)+W(2,1049113865,1035642194,-1105600932,-1114871718)+W(3,-1104998692,1034875990,1004288083,1019116562)+W(4,1048373410,-1101089925,1050248373,-1113393188)+W(5,1015693919,1032989733,1024635942,1041247426)+W(6,-1123382260,1035361564,-1105239942,1000972215)+W(7,-1112223483,987872957,1016564448,1019016937);WS(1051792028,1027146209);
|
||||
sum1=W(0,-1173418992,1031492470,1030866682,-1111745573)+W(1,1037975597,1032231158,1021051177,1029296729)+W(2,-1096555104,-1099279313,-1102472206,-1086728512)+W(3,-1098029143,-1099704976,-1107704157,-1088435526)+W(4,1048715847,1043543405,1045948678,1048944276)+W(5,1053562136,1041023999,1031959404,1046674105)+W(6,1037767898,1032372106,1031937048,1030986133)+W(7,1035090980,1038793940,1031982829,1043937550);sum2=W(0,1076285256,1067013205,1054912747,-1103468782)+W(1,-1082179927,-1086354611,-1086555076,-1077304359)+W(2,-1071495861,-1080654015,-1092768710,1053690657)+W(3,1062196550,1059230433,1065208788,1069826015)+W(4,-1089164092,1044446905,-1089831336,1049463752)+W(5,-1116071286,1055604285,-1102169042,1049830695)+W(6,1024798548,-1130255717,-1111620633,-1129289568)+W(7,1022374674,-1147177200,1008723412,990531682);WS(-1116843232,1041538044);
|
||||
sum1=W(0,1038718416,1041393778,1023355030,1040958951)+W(1,1040537034,-1112360254,1043346413,1047211822)+W(2,1050813118,1048646402,1043671731,1037057641)+W(3,1050123337,1052799074,1037436293,1042212684)+W(4,-1091780513,-1107072481,-1097953353,-1088265503)+W(5,-1105750724,-1091053114,-1121572392,-1091261766)+W(6,-1107356403,1032833522,-1126022145,-1185162751)+W(7,1038008293,-1123581176,1033129910,-1116284746);sum2=W(0,-1127892588,1025248710,-1127740272,-1114879615)+W(1,-1125515678,-1135605467,1015277154,-1118452308)+W(2,-1090048491,-1124324076,-1092974499,1047668544)+W(3,1042122418,1052455522,-1102075660,1052515578)+W(4,-1076486023,-1080184847,-1080442855,1048567939)+W(5,1066323214,1068938556,1066205534,1058048535)+W(6,1071993665,1067215194,1068762214,1014309155)+W(7,-1079656754,-1077318729,-1083078137,-1086246531);WS(1045082936,1047750074);
|
||||
sum1=W(0,1017867382,-1105827232,-1139557912,-1098507795)+W(1,-1112138258,-1113781499,-1117154624,1024003356)+W(2,1038967959,1036533543,1048524561,1057427781)+W(3,1057555836,1044700722,1037485187,1046059755)+W(4,-1107005280,-1101431328,1044741561,-1099209723)+W(5,-1103886606,-1117912777,-1108908881,1024367918)+W(6,-1117189504,1000061951,1034808454,-1102176472)+W(7,-1102736460,-1102956733,-1113728179,-1108156515);sum2=W(0,1003184961,971431442,-1131894760,-1133283297)+W(1,984723076,1031831407,-1125590160,1031681833)+W(2,1024857236,-1109323954,1026446282,-1105665514)+W(3,-1116186208,1024492508,-1121629964,-1148808497)+W(4,-1114215978,1030818718,1031262679,1056963612)+W(5,1055283667,975724297,-1116339968,1026784592)+W(6,1037587704,-1121823736,1045339410,-1107079097)+W(7,-1090072253,-1102678968,-1103014356,-1123463096);WS(1059869006,1015916977);
|
||||
sum1=W(0,-1111801867,1039164638,1023424768,-1118862224)+W(1,-1114194639,-1099094340,-1118811114,-1096321008)+W(2,-1103727218,-1102716146,-1089648586,-1092420393)+W(3,1049092536,1052180160,1032231232,1046058153)+W(4,1051877295,1051739903,1057614174,1055627629)+W(5,-1096079006,1008315659,-1121275805,1039975892)+W(6,-1115491581,-1106752078,-1104830517,-1112797325)+W(7,1038662167,1030088557,-1131680577,-1175801754);sum2=W(0,-1113427160,-1104433368,-1104169884,-1117600576)+W(1,-1102319880,1039627671,-1097619580,1047721667)+W(2,-1090644207,-1091764889,-1109333336,1065407690)+W(3,-1098732665,-1109931470,1043714297,1041133481)+W(4,1034414883,-1120815960,995253792,1059846520)+W(5,1048874179,1008884504,1021072320,-1103318888)+W(6,1038986783,-1135559136,1033390214,-1120264784)+W(7,-1104270640,1019376128,-1111461786,-1142244432);WS(1054131356,-1077482588);
|
||||
sum1=W(0,-1100136045,989703980,-1114161471,-1117800461)+W(1,1013262449,-1112319975,1027862775,-1103330903)+W(2,-1101215881,-1100083265,-1091699940,-1088812180)+W(3,-1095974704,1033042241,-1095224480,-1102789769)+W(4,1045307006,1039854844,1051542530,1056393300)+W(5,1053327664,1059113280,1049428707,1055440053)+W(6,1047064142,-1120855287,1042850313,-1122501592)+W(7,-1118254671,-1111473941,-1119385054,-1109190398);sum2=W(0,-1098032416,1055692800,-1101668743,-1100435053)+W(1,-1089098280,-1094416925,-1099202751,-1104551065)+W(2,1063396296,1024719031,1065491656,1073645059)+W(3,1060161647,-1074198531,-1081296593,-1083400329)+W(4,1043414797,1032661901,1058961916,1063424749)+W(5,-1096580753,-1098776178,-1115458644,-1092624053)+W(6,-1093635160,1049215120,-1090478816,1050905898)+W(7,-1135528507,1042380471,1032695397,1054277265);WS(-1082679118,-1072338335);
|
||||
sum1=W(0,-1126832308,998650886,1029713605,1045660229)+W(1,-1125245511,1001090478,-1126242526,-1128346278)+W(2,-1092407662,-1099976035,-1098757312,1049242330)+W(3,1052609817,1049104969,958956607,-1170516592)+W(4,1041636256,1035459839,1053507448,-1097348797)+W(5,-1097111418,-1099322690,-1116731426,1009511091)+W(6,1032452512,-1118647007,-1113994637,1019901759)+W(7,1026546307,1041545965,-1113342195,1027607012);sum2=W(0,-1069228184,-1073602631,1021776922,1076866983)+W(1,1069809281,-1101499289,1013617559,1036050969)+W(2,-1099529380,1043301860,1054858487,1044685536)+W(3,1062109344,-1097491140,-1149319294,-1113127688)+W(4,-1112044089,1041147606,-1119872164,-1106846135)+W(5,1042271976,1035368326,1025827813,-1115137330)+W(6,-1144476451,-1112019052,1036271953,1018899191)+W(7,-1114284680,-1126672913,-1112053703,-1146921887);WS(-1125906880,1029353026);
|
||||
sum1=W(0,1052620124,1040928385,1053619569,1034478636)+W(1,-1149501032,1027228408,1033816441,-1143379631)+W(2,-1082830235,-1087911853,-1088553290,-1115166792)+W(3,-1104403058,1046902211,-1140598044,-1115398454)+W(4,1044570800,1048894344,1054767249,1052323270)+W(5,-1096342700,-1092690897,-1112660402,-1089842615)+W(6,1033131793,1031982257,-1118254573,1037418321)+W(7,1045103465,1053685367,1032758420,1056771243);sum2=W(0,1052242091,-1105901664,1041713460,-1098081544)+W(1,-1101414896,-1140318759,-1123485994,-1108472633)+W(2,-1123374674,1032004261,1057464262,1055897675)+W(3,-1108453649,-1099401944,1039811869,-1092934450)+W(4,-1088438592,-1109896025,-1106721416,1057898227)+W(5,1044097375,1041656473,1042751001,1033994653)+W(6,-1109756837,-1117902306,-1106560728,-1101499608)+W(7,-1114554169,1042131382,-1104786072,1048148308);WS(-1080878567,1068324028);
|
||||
sum1=W(0,-1115471279,1019310859,-1121098697,-1115193805)+W(1,-1153442440,-1104713039,1023975060,-1094675607)+W(2,-1095139206,-1103458412,-1090917913,-1094785898)+W(3,-1100131090,-1118370765,-1102569730,1044057356)+W(4,1057833304,1049561152,1058273109,1054221326)+W(5,1050583410,1048985266,1041261354,1045920684)+W(6,1032811018,-1118469827,-1107876783,-1109399058)+W(7,-1121957752,-1109945243,-1125987028,-1144681671);sum2=W(0,-1122597644,1032420914,-1109997244,1029919127)+W(1,-1129031901,1025876905,-1121404056,1025649559)+W(2,1052263517,-1132353885,-1113437764,-1086124512)+W(3,-1134522929,-1137529969,1041285329,-1111439550)+W(4,1084267296,1077171750,-1076080701,-1066836895)+W(5,-1073829589,-1128728545,-1128683125,-1109934248)+W(6,1037076324,1017945885,1045994672,-1105598049)+W(7,-1115453382,1027437378,-1112127416,1032857588);WS(-1106960696,-1099012034);
|
||||
sum1=W(0,-1114528403,-1119077260,-1143558020,-1119877760)+W(1,-1109244232,-1096650748,-1112604445,-1100402892)+W(2,-1099071342,-1099370430,-1089278443,-1086538844)+W(3,1010994112,1041376829,1042854492,1049345155)+W(4,1055554285,1049964157,1061104081,1056629915)+W(5,1049997315,1042073805,1031563405,-1123516568)+W(6,-1109121109,-1115766890,-1114965299,-1120868875)+W(7,1034547527,-1114495407,-1139584324,-1118254096);sum2=W(0,-1116593925,1028908115,999050165,1037914955)+W(1,-1106109711,-1105957739,-1123834115,-1113783754)+W(2,1027806287,-1136470458,1039840949,-1122048333)+W(3,1057135276,-1105275062,-1096566133,-1105721601)+W(4,1032648371,1006654490,1052059722,1057985079)+W(5,-1090440242,-1131926605,1018741845,-1124260101)+W(6,1024756439,-1116529299,-1107372324,-1128153177)+W(7,-1142966917,-1123338691,1013415162,1018182189);WS(-1103089976,1059868827);
|
||||
sum1=W(0,1026631887,1033737723,1034000797,-1130496915)+W(1,-1106694966,-1105866475,-1106727101,-1098705919)+W(2,-1091300264,-1096562704,-1087537316,-1094386976)+W(3,1044429902,1045093007,1040636078,1044615672)+W(4,1056895190,1050565142,1059766350,1053939124)+W(5,-1108577640,-1109922270,-1122075862,-1100982776)+W(6,1031003956,-1140469197,-1108911023,1032926090)+W(7,-1120892680,1034482579,-1136817768,1045052014);sum2=W(0,-1114832682,1038307608,-1109268272,1031259614)+W(1,-1136199018,-1118450441,1025376385,-1125957173)+W(2,1044376552,-1101986459,1025272345,-1112738770)+W(3,1014008179,1042085570,-1110075404,1027010884)+W(4,1052671036,-1094811671,-1106762472,1052706603)+W(5,1040752903,-1100877636,1051973899,1036345951)+W(6,-1084839384,-1076225566,-1074779618,-1088390497)+W(7,1066038403,1071357616,1068318141,1050587817);WS(-1089897038,998399462);
|
||||
sum1=W(0,-1100326508,-1099771006,-1103969415,1030998252)+W(1,-1111096702,-1129527451,-1115021151,-1124899748)+W(2,-1114312802,-1109889234,-1092992143,-1098209637)+W(3,-1116385180,-1096464604,-1111889198,-1109224641)+W(4,1049930251,1047140918,1060325312,1062808044)+W(5,-1128865717,1048691588,-1137813989,1043572929)+W(6,-1141222070,-1114407115,-1106384368,1017922927)+W(7,1023432554,-1125954964,-1121716413,1020452535);sum2=W(0,-1094975511,-1089233591,-1089977002,1033778332)+W(1,1006981461,-1137053176,-1125132764,979684320)+W(2,-1113696880,1032844980,1066397244,1037917830)+W(3,1039504138,1032622380,1021506052,-1119563165)+W(4,1023473326,1036803698,-1129026618,-1104280508)+W(5,1024702770,-1121975322,974010432,-1138205260)+W(6,1029862812,-1117299445,1025970568,1031377784)+W(7,-1122944997,1022461928,-1130740686,1024270227);WS(-1096120220,-1099720911);
|
||||
sum1=W(0,1052677544,1027883172,1046184634,1036941212)+W(1,1037786724,1039372749,992842790,1040590154)+W(2,-1105594052,1050583742,1030711656,1050761182)+W(3,1044997418,1051859318,1041579690,1052858474)+W(4,-1101878153,-1120505890,-1094174707,-1087347673)+W(5,-1091299260,-1092171165,-1105854769,-1087724293)+W(6,990296621,1026529890,1039246623,1031039363)+W(7,1038193547,1036921611,-1115076484,1007468831);sum2=W(0,1040381409,-1131846701,1030695069,1015259161)+W(1,1026868853,-1164136976,-1121164685,-1109936403)+W(2,1023777345,-1095435966,-1111411494,-1085163747)+W(3,-1100600319,1052695808,1041440525,1051545155)+W(4,-1110031849,-1146822820,-1089001391,-1074171332)+W(5,-1078760233,1048168469,1074132102,1072577306)+W(6,1022623295,-1096899181,1049343346,-1107180310)+W(7,1043071461,1020495459,1017314953,1050115198);WS(-1080112807,-1111145054);
|
||||
sum1=W(0,-1103297132,-1106341774,-1098278655,1024154699)+W(1,1037514093,1034961350,-1125780682,-1109009483)+W(2,1049824404,1049617192,1059552348,1031972225)+W(3,-1085661228,-1097823136,-1114326813,-1119831648)+W(4,-1133975251,-1122989109,-1086286580,-1137351813)+W(5,1056970252,992708574,1021582000,1040424089)+W(6,1026400021,1042898005,1041608840,-1145221295)+W(7,-1102084285,1041904442,1038246926,1042525799);sum2=W(0,1041258750,-1109734283,-1123542769,-1113561957)+W(1,-1110564237,1026811493,-1130694514,1024057869)+W(2,989910477,-1100922013,-1096844113,1051742866)+W(3,-1100235579,-1105813951,-1151284621,-1136706867)+W(4,-1134607603,1016064722,1041392492,1057819912)+W(5,1047439582,-1113868277,-1118083589,-1114600003)+W(6,-1109794979,1041809078,-1126381362,982123162)+W(7,-1119465765,1026735929,1019553626,-1114678252);WS(1043409720,-1105036943);
|
||||
sum1=W(0,1040191749,1033970558,1042494496,1046767380)+W(1,972615552,1032778168,1032217109,1032356247)+W(2,-1096303173,-1095924673,-1093807736,-1092831585)+W(3,-1096756208,-1126846855,-1115229280,-1098580285)+W(4,-1115184605,1041748910,1044442592,1042876074)+W(5,-1140612185,1018241414,1027878365,1034858676)+W(6,1041655059,1041917006,-1160531625,1039311757)+W(7,1020654492,1043700571,1034107952,1036396440);sum2=W(0,1027808259,1010119787,-1111510504,-1113418759)+W(1,1032132185,-1121052855,1014515195,1010692603)+W(2,-1139047739,1043340308,-1106790738,-1096910874)+W(3,1040059331,-1115460243,1017581734,-1120741339)+W(4,986751832,1026247831,1065364148,1040723354)+W(5,1038861011,-1113647147,1041604470,-1135975307)+W(6,-1095774205,-1093511024,-1089533357,1053173071)+W(7,-1106558855,1027584935,-1121443175,1014681515);WS(1035857520,1029952289);
|
||||
sum1=W(0,-1143077795,-1105351783,-1113811952,-1106526780)+W(1,1035289215,999420801,-1129002434,-1113970285)+W(2,1037051011,1029971495,1049064844,1035603988)+W(3,-1083894414,-1098557596,-1111645039,-1130790920)+W(4,-1110400621,-1106469910,-1094483622,1058276716)+W(5,1056346487,1050633420,1042325343,1026109447)+W(6,-1121149466,1043652126,1027875988,1035104701)+W(7,-1114346217,-1123554317,-1130799743,1025377311);sum2=W(0,-1118517607,-1101077931,1029148161,-1087996420)+W(1,1047526016,-1108756119,1038718292,1024464693)+W(2,1026484093,1046485772,-1098019518,1071267691)+W(3,-1082674625,1032470282,-1106613565,-1113199029)+W(4,1039465846,1030900361,1048118782,1064954318)+W(5,-1084489705,-1118487613,-1112021711,-1120012731)+W(6,1008581907,-1114630284,-1106945018,-1097625455)+W(7,-1156379726,1024110641,1020048570,1036291722);WS(1058189134,1034857672);
|
||||
sum1=W(0,-1171748679,-1105475825,-1097172873,-1108837708)+W(1,1038034707,-1131134898,-1113151849,-1119273967)+W(2,1031241360,1044072484,1057114388,1051374554)+W(3,-1083662360,-1099379283,-1121036423,1018101850)+W(4,-1100969760,-1094075536,-1082247827,1060030327)+W(5,1058651386,1046921459,1041721673,1036514264)+W(6,987174985,1045893176,1042860595,1031954257)+W(7,-1120638978,-1137288661,1037681908,1029972391);sum2=W(0,1003810984,1036204547,-1101998989,1041029203)+W(1,-1098215637,1044393168,-1110527635,1027560485)+W(2,1020569783,-1114489126,-1121260135,1052640914)+W(3,1059150102,-1098121773,1037147118,-1110248773)+W(4,-1128982694,-1099380876,-1101918458,1059611184)+W(5,1040381797,-1094102036,1028175839,-1113935142)+W(6,1043745048,-1104004872,-1104165612,-1121067579)+W(7,-1100369008,1032515174,-1114899975,1000033398);WS(-1107450480,1040804833);
|
||||
sum1=W(0,1040192716,1022226221,1002013395,-1117682794)+W(1,1001040843,1000424795,-1120982404,1025306833)+W(2,1040473489,1047969017,1044185574,1060667554)+W(3,1057909434,1049088596,1038016429,1042416864)+W(4,-1095196747,-1098407451,-1087290490,-1089168888)+W(5,-1111951852,-1119291421,1031577591,-1112956481)+W(6,-1124855402,1020416041,-1160070647,1045737613)+W(7,-1101676720,-1103624738,-1104451167,-1115902938);sum2=W(0,1014727333,-1117243126,1029406572,1027900147)+W(1,-1112527674,-1114664521,-1111634336,-1107116047)+W(2,-1124633329,-1107065949,1041729284,-1094200388)+W(3,-1104959017,1040214496,1005029260,1049039902)+W(4,1026257754,-1111801245,-1084100906,1052541581)+W(5,1070744988,-1111707080,-1127513012,-1107038609)+W(6,-1111611661,-1136702760,-1103677442,1050798725)+W(7,-1105828213,-1111536822,-1106506739,-1140667375);WS(-1113867888,1064515135);
|
||||
sum1=W(0,-1113562537,-1107046062,-1103978495,-1098739202)+W(1,-1122423580,1019693149,-1116789880,1020558520)+W(2,1048061265,1043460993,1060048584,1062873548)+W(3,-1119786749,1023528257,-1106657727,-1137576074)+W(4,1011269086,-1098944190,-1107431310,1045822761)+W(5,1025265092,-1112998912,-1142662356,-1104660585)+W(6,-1105945126,-1148623547,-1111558073,-1114838028)+W(7,-1101841139,-1117915947,-1106868487,-1122252061);sum2=W(0,-1145158406,1012385731,1016118130,1024197601)+W(1,-1112179804,-1119519161,-1127326042,-1113792718)+W(2,1022878354,-1129472106,1044961455,1049544336)+W(3,1030346877,-1131221354,-1095482557,-1093377057)+W(4,-1111624996,1015658802,1040055751,1057430996)+W(5,-1114498280,1020564842,-1112131584,1019749938)+W(6,1010204019,-1123973089,-1157676569,1022031298)+W(7,-1124728962,1023003938,-1121117277,-1141925830);WS(1051333020,-1087054195);
|
||||
sum1=W(0,-1112042433,1019002067,-1115058903,1046618143)+W(1,-1107874438,-1148774132,1036768028,-1154881470)+W(2,-1104387605,-1096771599,-1102529947,-1093976551)+W(3,-1089735051,-1129150690,-1101876091,-1098135714)+W(4,1052246829,1048899277,1054136106,1044227957)+W(5,1060328029,1046377228,1045160291,1045432325)+W(6,-1113527444,-1098301717,-1095193948,1044013586)+W(7,-1107288943,1038700845,1024370318,1019966234);sum2=W(0,-1114066012,1029900262,-1114806697,-1110038644)+W(1,1036646832,-1110070018,1020625547,987867800)+W(2,1041392892,-1112610934,1041587346,1025557898)+W(3,1055783298,-1102485451,988088600,1039502616)+W(4,1044719218,1046575198,1050162797,1055420600)+W(5,-1099287148,-1100701871,1033323822,-1119304428)+W(6,-1097547793,-1095644935,-1102972970,-1095936036)+W(7,1028020818,-1113902766,-1135974783,1018696751);WS(-1120103648,-1090070191);
|
||||
sum1=W(0,-1117418940,1024592611,1040968250,1049918615)+W(1,1034410595,1035134604,-1119948353,-1144523437)+W(2,1049030490,1050801054,-1111205267,-1116228463)+W(3,1050512309,-1102511675,1034763283,1039656998)+W(4,-1112262737,-1094705236,1042055990,-1085341341)+W(5,-1106227665,1036298997,-1138448657,-1110564136)+W(6,-1114427969,1032013281,-1110419822,1047944497)+W(7,-1132367051,1025392341,-1111046724,-1120201127);sum2=W(0,-1122606938,-1141997982,1027805544,-1120462650)+W(1,-1100560083,-1105726471,1025575588,-1113668318)+W(2,1046354401,1040228902,-1143835982,1061896257)+W(3,-1080731069,-1098049024,1026943708,1032253740)+W(4,-1124762815,-1102583710,1052785838,1059397472)+W(5,-1120768779,-1126645315,1011421951,-1122685018)+W(6,-1118515993,1036845124,-1106443071,1043676745)+W(7,995709275,-1128858827,-1112152255,-1127110207);WS(1060158670,1068766623);
|
||||
sum1=W(0,-1116432453,-1131098839,-1099753724,1034945056)+W(1,-1122123599,1040823512,1040184285,1050332416)+W(2,1056712636,1049784895,1057908127,1044163070)+W(3,1028198895,-1122504371,-1123329903,-1096645803)+W(4,-1087151539,-1102593034,-1089291740,-1094800699)+W(5,1036808107,-1120242995,-1127465369,-1132187055)+W(6,1040295867,1033948341,1031077093,1027113355)+W(7,-1132674679,-1117547229,1040274980,-1137741501);sum2=W(0,1036379663,-1108907739,1070189048,1073213180)+W(1,1065321765,-1076673488,-1079893128,-1072585926)+W(2,-1098232449,1058983203,1016986873,1047923452)+W(3,1033582270,1031365639,1038048757,-1107019906)+W(4,-1128107780,1035811659,1040144345,-1105399966)+W(5,-1110681209,1039880527,-1116001167,1018297481)+W(6,-1120677803,-1120240179,1029686139,-1109097268)+W(7,1041308319,-1109042515,1034493417,-1131123922);WS(-1112459888,1031046963);
|
||||
sum1=W(0,-1112719265,-1129483154,-1103727283,-1091575740)+W(1,-1104335643,-1155155940,-1114094348,-1105426861)+W(2,-1128634346,-1120462421,-1112785958,1056781779)+W(3,-1153409228,-1108013960,-1118230989,1027667442)+W(4,1043326546,-1103778738,1050524372,1067939282)+W(5,1048587330,-1132710977,-1109505653,1036777787)+W(6,-1115081924,-1114915140,-1104237825,-1096588493)+W(7,-1108534894,-1114726045,991235804,-1111746006);sum2=W(0,-1119086167,1013020612,-1141008560,-1108719150)+W(1,1023891147,-1145112744,1018251990,-1116478859)+W(2,1037241732,-1129818230,1029187991,-1074141953)+W(3,1019083994,-1124211508,-1122886966,1027168441)+W(4,-1114652243,1028260797,-1112264831,1072760747)+W(5,1042535682,-1131878972,1037493286,-1129254230)+W(6,-1131518324,-1115730540,1036245214,1034705438)+W(7,-1119172530,-1133917220,-1114007324,1018465006);WS(-1086783566,-1086791567);
|
||||
sum1=W(0,-1115195632,-1153026662,-1134496297,-1108787789)+W(1,-1119803561,-1145121243,-1131708777,-1110064394)+W(2,-1095708330,-1093442522,-1098161001,1044632085)+W(3,-1091375169,-1107384199,-1100078210,-1104664012)+W(4,-1123676804,1018199561,1037878573,1064261167)+W(5,1057417647,1052226946,1046948682,1047330733)+W(6,1041725033,-1121101892,1034570216,-1103584185)+W(7,-1108866704,-1122033784,-1117964907,1022321300);sum2=W(0,1031515378,-1121810184,1010081392,-1119765868)+W(1,1035546479,-1106495935,1028378344,1003402623)+W(2,-1077397139,-1079753374,1044674665,1073378801)+W(3,1056367001,-1109376902,1035615024,-1118889676)+W(4,-1134939312,-1097085111,1052841311,1007836336)+W(5,1044809025,-1118570548,992033726,1010750288)+W(6,-1112896962,1035985281,-1105060263,1031953140)+W(7,1022446080,1031289566,1032016077,-1150317246);WS(-1096711324,-1080143969);
|
||||
sum1=W(0,-1135181951,1025399430,1033906501,1041786535)+W(1,-1133559462,1003671004,-1123695637,-1105366874)+W(2,-1095339398,-1094144146,-1093853897,-1089314149)+W(3,-1089126233,-1110956839,-1129083412,-1113909272)+W(4,1050582337,1049483953,1045129706,1046728732)+W(5,1045641984,1051092970,1049638101,1057307443)+W(6,1026786373,-1123204644,1006467326,1031608549)+W(7,-1135165794,1017185520,996324016,1009923752);sum2=W(0,1023911567,1004932796,-1119124867,1022775023)+W(1,1011639102,1036397588,999444348,-1106309084)+W(2,-1108118447,-1134375038,1035251904,1037995724)+W(3,1050162042,1037707684,-1111062570,-1101285996)+W(4,1044892126,-1138359022,1063133445,1074655410)+W(5,1070062472,-1083132698,-1073510095,-1073687480)+W(6,-1112738860,1020475455,-1102926770,1047698054)+W(7,-1113839430,-1117927031,1017195567,1041743674);WS(-1089880270,1068594400);
|
||||
sum1=W(0,-1114467040,1023170830,1036273894,-1107800974)+W(1,1029867434,-1106779367,1024593089,-1110449433)+W(2,-1104513741,-1091458130,1034367029,-1100997781)+W(3,-1095286649,1047811540,-1096228817,-1109179032)+W(4,1050219169,1042545281,1048674674,1042739212)+W(5,1053624831,1034908007,1034674708,1049808694)+W(6,-1118490053,-1120682309,1031296832,-1110241363)+W(7,1034289100,-1107012174,1021221591,-1126204757);sum2=W(0,1030004067,-1117028113,-1105887481,-1066126465)+W(1,-1104777348,-1122550707,-1130918117,1023720579)+W(2,-1133064657,-1134091777,1045929484,1081917443)+W(3,1043726141,1028310407,1016764395,-1116064873)+W(4,1024174065,-1113615539,1032698350,-1097201480)+W(5,1033613382,-1107697461,1029778305,1018371831)+W(6,-1119836251,1025775761,-1118489229,1041573100)+W(7,-1124268877,1030764051,-1116797441,1018350967);WS(1067475431,-1126058166);
|
||||
sum1=W(0,-1108052732,1043040440,1048922396,-1097574342)+W(1,-1119673025,-1101774749,1019400344,1007801026)+W(2,-1097851361,-1108210069,-1084429932,1055911149)+W(3,1041902328,1035827603,-1115594513,-1107003538)+W(4,1049362324,1048929252,1054104112,1047147106)+W(5,-1085779789,1049622021,1019477630,1037086373)+W(6,1040199303,-1109622414,1041203782,-1104274751)+W(7,1047880876,-1116198608,-1107876353,1036701569);sum2=W(0,1013753738,-1113150555,1015248850,1042650722)+W(1,1040818978,-1105652199,1033430289,-1120377801)+W(2,1020731454,1046742995,1045156685,-1104352239)+W(3,-1089864705,1045331461,-1109224259,1016214593)+W(4,-1120697178,1034035253,-1094710566,-1128318417)+W(5,1045040370,1025091411,-1106535436,1019751894)+W(6,1009873360,-1099358283,1039470065,1046693145)+W(7,1036008061,1030627793,1017876415,-1132110931);WS(1060496974,-1099362699);
|
||||
sum1=W(0,1054706808,1036662868,1045895019,1033303646)+W(1,1044095763,-1130190200,1035564779,1040746168)+W(2,-1109706041,1041317773,1051554925,1049334366)+W(3,1051166813,1053590462,1049285205,1055551482)+W(4,-1098091909,-1123237413,-1091928498,-1083798889)+W(5,-1095315343,-1087007295,-1097088265,-1094550458)+W(6,-1129324363,1015757258,1021341985,-1112852963)+W(7,1041804248,-1127492145,1039262630,-1114905285);sum2=W(0,-1073385920,-1084887580,-1083140914,-1081800202)+W(1,-1085954594,1037413129,-1096433065,1054210787)+W(2,1077926840,1058818874,1060159151,1074845707)+W(3,1061906872,-1084431515,-1126824848,-1087315344)+W(4,1032559783,-1089669880,1045764296,1059775011)+W(5,-1103860568,-1094536545,-1133232881,-1099186518)+W(6,-1094451238,-1121878040,-1173171215,-1120435570)+W(7,-1115590029,1053315192,-1107838893,1052978812);WS(-1078369703,1041267413);
|
||||
sum1=W(0,1024386586,-1098405416,1044040033,-1098286219)+W(1,-1130684104,1045750173,-1098338270,1041584973)+W(2,1041630887,-1112635974,-1132435208,1041292515)+W(3,-1091497929,1016159377,-1139597330,-1101611546)+W(4,-1102607056,1051293608,-1094040968,1052507157)+W(5,1056853585,-1105775474,1049412460,1026100205)+W(6,1016693023,1018393854,1046099151,-1095618428)+W(7,1018959206,-1117949682,-1118540325,1040982949);sum2=W(0,1035615459,1028814353,1062855981,1052250964)+W(1,1056109526,-1106019250,1048995011,-1115640692)+W(2,-1097925659,1038714809,-1077657685,-1101970047)+W(3,-1098468896,-1114182260,-1104046747,-1130122971)+W(4,1043665288,1033337220,1051048913,-1113114333)+W(5,-1085664062,1040975429,-1109605260,1034778788)+W(6,1020457849,-1103657321,-1109823715,1058024935)+W(7,1056999181,-1105846491,1042595027,-1112374505);WS(1049151900,-1114127847);
|
||||
sum1=W(0,1050216581,1000015204,-1136218178,1023136961)+W(1,-1130455775,-1133465094,-1160090192,1035991733)+W(2,1044969414,1047621718,1057314961,1055877843)+W(3,1054358666,1052966059,1045850836,1052491071)+W(4,-1106856243,-1112471205,-1091938023,-1092033343)+W(5,-1099719178,-1089783713,-1099053307,-1087984664)+W(6,-1099359923,-1148711507,-1133921207,-1112054390)+W(7,1034273823,-1122838974,1019980258,-1112322824);sum2=W(0,-1105478410,1039552519,-1131405058,-1099466970)+W(1,1049027924,-1115050596,-1129231446,1049583286)+W(2,1011113448,1050864081,-1125310098,1043215106)+W(3,1034334973,-1095883745,1036178144,-1088635155)+W(4,1068049752,-1103020148,1066695202,1074596924)+W(5,1067601936,-1084539788,-1075514015,-1074115054)+W(6,-1082501551,1059003564,-1098156272,1039344435)+W(7,-1099880092,-1107282542,-1097076855,1042018058);WS(-1081332839,-1093454830);
|
||||
sum1=W(0,-1109709318,-1104916884,-1108177419,-1117212646)+W(1,-1119705461,1032417267,-1118748528,987327371)+W(2,1035356975,1037116623,-1125155242,1030327966)+W(3,1050241163,-1103907222,1046095669,1033262333)+W(4,1039420520,-1122158672,1053028347,-1104761999)+W(5,1032136206,-1115200780,-1115609017,1029855614)+W(6,-1111308088,1014687039,-1112931654,1020526050)+W(7,-1119448076,-1112611266,-1136487898,-1104533373);sum2=W(0,1013207527,-1127355075,-1103159789,1040955478)+W(1,1008876024,-1116686760,1035764738,-1154118338)+W(2,-1118344664,1028266047,1043690369,1051132935)+W(3,-1108842627,1041402295,-1105537330,-1128237045)+W(4,-1124997045,-1117884424,-1116887196,1047094008)+W(5,1057384051,-1100609336,-1098518151,-1089828796)+W(6,1036829905,1016171285,1024917624,1041601336)+W(7,-1127506713,1033786361,-1114313206,-1102385561);WS(1063446990,1030048893);
|
||||
sum1=W(0,-1131562670,-1099483503,-1106193120,-1102405700)+W(1,1021119810,-1113568905,1009340592,1030255032)+W(2,1043069042,1049571969,1061428532,1053095529)+W(3,-1115069793,-1119868742,1027160065,1043118346)+W(4,-1108681470,-1106599551,-1097709592,1046689338)+W(5,1029025472,1006738196,-1120287391,-1111789333)+W(6,-1108650254,-1106453175,1008661917,-1102088711)+W(7,-1123233168,-1104754348,-1136963210,-1114502129);sum2=W(0,1012371361,-1149491589,1023756477,-1165255819)+W(1,-1111467932,1019335917,-1140694601,1010513313)+W(2,1017109065,-1115161102,1012418345,-1111308586)+W(3,1015942947,-1106016138,1015823021,1026481588)+W(4,-1110016822,-1109821790,1060485172,1031379047)+W(5,1046805034,-1114576028,1024897044,-1114618076)+W(6,-1103671135,-1097972516,-1094449842,1049769129)+W(7,999148403,1022790203,1032463998,-1146831635);WS(1060385486,1040268319);
|
||||
sum1=W(0,-1115333181,-1113839600,1026945989,1041834949)+W(1,-1100015113,1010458454,-1113704543,-1110169699)+W(2,-1105770459,-1104706211,-1085502934,-1112644646)+W(3,-1102865873,-1112283012,-1108020290,-1115522389)+W(4,1048230464,-1122113023,1051932092,1065603891)+W(5,-1105250533,1054415097,-1122402466,1046973419)+W(6,1022495614,-1115044751,997701279,1044329112)+W(7,1038196649,-1113673817,-1105082025,-1115640050);sum2=W(0,-1115664423,-1122287706,1044568139,-1099350461)+W(1,-1102715015,1042022920,1031291077,1032474264)+W(2,1041813775,1041645390,-1087138046,1067461852)+W(3,-1116572542,-1109622665,-1113357449,-1110133469)+W(4,-1142717933,-1094011677,-1124627987,1027339570)+W(5,1045144111,1054026149,-1122353792,1047364150)+W(6,-1120925434,-1119842210,-1120985148,-1113918825)+W(7,-1100833175,-1101147879,-1112018489,-1109170005);WS(1049043868,1050086952);
|
||||
sum1=W(0,-1127858130,1025810768,1034666762,989092984)+W(1,-1115481017,-1119959429,1012364567,-1097661520)+W(2,-1091279607,-1101354119,-1089232423,-1092016019)+W(3,-1089729669,-1104525366,-1121438163,-1160888088)+W(4,1054362490,1044465651,1050465752,1058690160)+W(5,1053482909,1051092259,1019953121,1051219071)+W(6,1028884238,1022883995,1032068165,1005443958)+W(7,1007092039,-1149438996,-1137072337,1017307814);sum2=W(0,1030282550,1012065197,1049708534,-1101566471)+W(1,1043525707,1038111746,1040589253,-1106531005)+W(2,-1099759289,1050936278,1018991152,1050588571)+W(3,-1112383125,-1121285468,1039884984,-1113841779)+W(4,1070065566,1068820850,1068572253,1075164582)+W(5,1046261639,1053555382,1040055978,1058828770)+W(6,-1078832473,-1076346523,-1075628240,-1072955990)+W(7,-1093459475,-1088795804,-1099780818,-1090423367);WS(-1083655502,1074535575);
|
||||
sum1=W(0,973651072,1028862937,1029517469,-1111330742)+W(1,1043404639,-1105397947,-1129726574,-1099887737)+W(2,-1100106921,-1096173461,-1088250868,-1101351113)+W(3,-1092528244,1034877328,-1113904430,-1118418050)+W(4,1049212555,1052529147,1057957824,1060855844)+W(5,1050267538,-1104065896,1041335934,1047916353)+W(6,-1122472503,996549482,-1111380529,-1125410415)+W(7,-1109626381,-1122247818,-1108333759,1037233742);sum2=W(0,1037582341,1032149251,-1135487115,-1107247151)+W(1,1053968825,-1096732175,1034930229,-1094249638)+W(2,-1116649305,-1112916551,1044443302,-1117703407)+W(3,1049963138,1042101117,1046616621,-1127010106)+W(4,-1107051108,1041643977,1030763641,1053360182)+W(5,-1087331905,-1089009482,-1110671517,1059951262)+W(6,1040538112,-1112067691,1036263743,-1115814520)+W(7,1035849297,-1104153316,-1104877620,-1116847106);WS(-1132786560,1056578758);
|
||||
sum1=W(0,1031072232,1019453021,-1112153353,-1127115205)+W(1,-1153314582,-1105591705,986346381,1024604121)+W(2,1043718831,1050053971,1057505465,1049535379)+W(3,1052394474,1045418390,1044283028,1048806335)+W(4,-1098888378,-1104586611,-1090760605,-1081773448)+W(5,-1106021324,-1120283669,1036365944,-1103287167)+W(6,-1123786893,1030360908,-1123598824,1035671447)+W(7,1044649456,-1105554848,1033186457,-1108912601);sum2=W(0,1040658557,-1106354313,1027144364,-1103628435)+W(1,-1123462592,-1130705048,-1126068784,1016031184)+W(2,1011638864,1020064744,1049840877,1050147177)+W(3,-1117174472,-1105120318,-1113970774,-1135769248)+W(4,1041865287,-1103147627,1026998340,1053587315)+W(5,-1118058864,1036775410,-1104140895,1030416564)+W(6,-1109113498,1033931950,-1120927100,-1102211113)+W(7,1033328738,-1101351534,1028877580,-1112076066);WS(1062711758,-1109562142);
|
||||
sum1=W(0,-1107075140,-1125545776,-1121788380,-1112684886)+W(1,-1128625782,-1102890883,-1129119788,-1102110160)+W(2,-1100622401,-1104747337,-1103229831,-1083301774)+W(3,1050510715,-1097610180,-1109077454,1030737729)+W(4,1053288051,1049612355,1059638178,1048337697)+W(5,1052952654,1051307580,1041285742,1049115768)+W(6,1017596397,1007433175,-1120034657,-1098025711)+W(7,-1112854653,-1108240645,1022176121,1020667959);sum2=W(0,1022257834,1033804876,1033963400,-1113268759)+W(1,-1123922685,1029999681,1015463858,-1125618402)+W(2,977550902,-1105772859,-1098748483,1063293804)+W(3,-1090033704,1051039483,-1104977553,1022914778)+W(4,-1113927342,1042844173,-1096777339,1059312088)+W(5,-1134320563,1037687330,1024487701,1004875175)+W(6,1036504102,-1107093105,1028160469,-1089861840)+W(7,-1101525036,1017532722,-1122996995,-1116068477);WS(1046002488,-1083997249);
|
||||
sum1=W(0,-1116203964,1044431961,1041235242,1046371486)+W(1,-1106267745,-1117705943,-1122870401,-1109240562)+W(2,-1099156844,1028498222,-1096363997,-1079124621)+W(3,-1088685662,-1103556299,999993136,-1106798659)+W(4,1050076828,1049400252,1050263757,1020370202)+W(5,1048790666,1053355933,1034829570,1037276039)+W(6,1025075217,1035032656,1032516798,1050189128)+W(7,1042510329,1039724554,1027729159,1037249299);sum2=W(0,-1094982381,1024745423,-1097113645,1017043870)+W(1,1052555320,-1107563793,1049262968,-1118735987)+W(2,1041875660,-1091311273,1042706326,-1148119319)+W(3,-1098101314,1010824956,-1094774489,1030619863)+W(4,1017839086,1044409386,974632891,1061393923)+W(5,1043955676,-1098402228,1042935118,-1094515595)+W(6,1045890174,-1107764806,1048260200,-1118443235)+W(7,-1097368628,1041238578,-1116185663,1042214090);WS(-1083255246,-1075588436);
|
||||
sum1=W(0,-1154522904,-1106371438,-1105464695,1036086422)+W(1,1023783355,-1127243930,1030176790,1031412139)+W(2,1026375684,1036249778,1056687627,-1097055709)+W(3,-1088556578,-1108055408,-1105944807,-1123388097)+W(4,-1099839750,-1113752075,-1092436626,1050924256)+W(5,1056650964,1045926824,1039385437,1041066449)+W(6,1037990411,-1119606102,1043935324,1036476796)+W(7,-1111337285,-1110940389,-1124332025,1021333175);sum2=W(0,-1117330831,1023708058,-1133288218,-1122435213)+W(1,-1139180683,1020252429,1025188082,-1109968059)+W(2,1032531181,-1114369361,1017487862,1047518334)+W(3,-1122916014,1027012545,-1103557501,1046855474)+W(4,1043756688,1031926890,-1104593512,1043258354)+W(5,-1096895795,1049767697,1019544307,-1112657711)+W(6,1060766869,1067300065,-1105945514,-1075696003)+W(7,-1102393264,-1106946489,1020047431,-1113285900);WS(1056055196,1023945849);
|
||||
sum1=W(0,-1104545849,-1139517988,-1101013315,-1136100212)+W(1,-1148373856,1013350648,-1120654743,-1108930702)+W(2,1036175954,-1138851412,1048468083,-1097789539)+W(3,-1096999890,-1097071058,995622088,-1128233700)+W(4,1032040419,1009002268,1040659763,1059870683)+W(5,1039368714,1053644410,-1122818538,1033002810)+W(6,-1111539988,1026875367,-1104005681,-1112873620)+W(7,-1135793772,-1132670698,1028030253,-1133516850);sum2=W(0,1033182461,-1135790885,1036058972,-1145806187)+W(1,1026470367,-1125994579,-1123856921,-1152817846)+W(2,-1110992702,1041801313,-1115959119,-1083556559)+W(3,1047402951,1026458945,1021989349,1029289545)+W(4,1011638125,976542168,-1106760241,-1068720208)+W(5,1080067579,1043021822,-1118809257,1027196491)+W(6,-1116812221,-1135785781,1013579453,1034110873)+W(7,1048786168,-1124564059,-1115658442,-1110636256);WS(1047050040,1036867972);
|
||||
sum1=W(0,1031952202,1040033213,1049413776,1052329098)+W(1,-1134253939,1023712847,-1129317744,1023414180)+W(2,1041031945,1050476745,1016870010,1054273441)+W(3,1041748879,1035493153,1041656495,1041394937)+W(4,-1098508279,-1097704487,-1091275871,-1087382286)+W(5,-1095309386,-1117526273,-1112254893,-1108492595)+W(6,-1117663192,1033331580,1012948685,1043041286)+W(7,-1131302504,-1125396951,-1153578470,-1112644847);sum2=W(0,-1120609508,-1098653081,-1074671298,-1081276780)+W(1,-1097107702,-1110118090,-1137118351,-1119823807)+W(2,-1138324119,1042859622,1072071026,1068070176)+W(3,1044485226,1040658983,-1118978815,1035453187)+W(4,-1110367912,1038385587,1026263792,-1107049493)+W(5,1024907208,-1122488627,1038809437,-1111098449)+W(6,1021280635,1026624912,1026288466,-1122098825)+W(7,1040255596,-1152233050,-1126727249,1006813455);WS(1047287096,1059538103);
|
||||
sum1=W(0,1030804480,-1111595219,-1123153834,-1098057279)+W(1,1007980582,1018775223,1036089754,1030691489)+W(2,1034749929,1051408038,1049213285,1057344539)+W(3,1048793645,-1106759404,-1115115061,1033654600)+W(4,-1102474905,-1094490621,-1099609086,1048597242)+W(5,-1094890059,1046324795,1003815995,-1126686757)+W(6,1013951379,1039425378,-1112788128,-1098419769)+W(7,-1118093753,-1108341356,-1120388747,-1135294247);sum2=W(0,-1112864979,1034721747,-1108077379,1023366533)+W(1,1021246669,1032508120,-1113986367,-1153257254)+W(2,1024004698,-1109416755,988806988,1058238498)+W(3,-1115279539,1041332549,1033457886,1018109285)+W(4,1034996841,1041661735,1041642045,1008174217)+W(5,-1122858630,-1089151778,-1130797677,-1111548255)+W(6,1004307827,-1116757818,1037366938,-1107547239)+W(7,-1108868659,-1128614293,-1130732717,-1122125438);WS(1066216871,-1084582294);
|
||||
sum1=W(0,1009745022,1023325836,1034246149,-1103455511)+W(1,1025953385,-1105242559,988118663,-1107601837)+W(2,-1095963722,-1096473834,-1087129751,-1142570129)+W(3,-1094684497,-1107829831,-1107520037,-1117719279)+W(4,1050775177,1046303345,1057767679,1064400323)+W(5,1038452388,992534739,1025316967,1044853309)+W(6,1027534757,-1126933960,-1118146623,-1103828265)+W(7,1018950609,1030437560,1020674901,1033139589);sum2=W(0,-1127013105,1018526115,-1123587641,1052346460)+W(1,-1098654594,1029804743,-1118240305,1030491706)+W(2,1031626404,-1117975133,1062148372,1074624908)+W(3,-1090512380,-1070854231,-1095518794,1041467716)+W(4,1029958550,-1113082476,1035325186,-1130733653)+W(5,1046581721,-1113725416,1031776819,-1115594754)+W(6,1017794797,1023300847,-1145491637,1041942663)+W(7,-1113152926,-1139181075,-1120299385,-1142763637);WS(1033725552,-1082653885);
|
||||
sum1=W(0,1027658456,1033791775,1038169633,-1130834725)+W(1,-1105755912,-1107114253,-1106878767,-1102176852)+W(2,-1091894661,-1094613753,-1085886368,-1094605577)+W(3,1049096200,1038006563,1040399888,1038046228)+W(4,1054730080,1052727904,1060322284,1054915405)+W(5,-1115316932,-1113871235,-1114082704,-1098681477)+W(6,1024810077,1020875129,-1114253244,1021660859)+W(7,1010914050,1032412472,1016596422,1044096992);sum2=W(0,-1126607908,-1111819446,1032709615,-1119610542)+W(1,1027594385,1029384695,-1115269200,1032209203)+W(2,-1109006144,1050929158,1025316173,-1107176811)+W(3,-1123863107,-1122531221,1026796828,-1115616555)+W(4,-1093467963,1063076656,1048889614,-1090320472)+W(5,1046933317,1051206364,997945380,-1109796884)+W(6,1059727060,1073053378,1073749745,1058093447)+W(7,-1079533534,-1073154062,-1075936158,-1088004581);WS(-1087442510,1045166814);
|
||||
sum1=W(0,-1106921670,1032907600,-1111070674,1047421629)+W(1,-1094092352,1031075349,-1136240762,-1129052086)+W(2,1032009478,-1127325529,-1106321881,-1085655355)+W(3,1057239638,-1098381173,-1128650952,-1107389381)+W(4,1041337656,-1100890040,1060092296,1044767811)+W(5,1040377247,1037296628,-1131454723,1037463686)+W(6,-1110338367,1042108264,-1105899594,1027442111)+W(7,-1105935775,1037469097,1027139781,991481919);sum2=W(0,-1119426781,-1109786529,1041819143,1018220925)+W(1,-1103055916,-1124599508,986571056,1024618671)+W(2,1040351141,1043540747,-1105926532,-1133247980)+W(3,-1096724541,1038612076,1019567362,-1143357456)+W(4,-1104019881,-1106797782,-1098594115,1066013053)+W(5,-1136157126,-1097021086,1025702119,1008181894)+W(6,1015410156,1043466418,1048709183,-1092013542)+W(7,-1109288787,1027934232,-1140871148,1027080058);WS(1059279054,1041683061);
|
||||
sum1=W(0,1028823114,1033060856,-1136683218,1041097809)+W(1,-1108712682,-1099515041,-1114499693,-1105525449)+W(2,-1096417644,-1095251776,-1096755466,-1095420880)+W(3,-1087904547,-1117180600,-1113115866,-1121084634)+W(4,1041071884,1051348966,-1106154521,1062896338)+W(5,1057053635,1050313119,1041134484,1043053335)+W(6,1040139175,-1133443258,1027763154,1037083176)+W(7,-1109247178,-1169250436,1007514196,1031868218);sum2=W(0,-1104031080,-1113246189,-1124792744,-1107688308)+W(1,-1084040655,-1089958554,-1098618924,-1098033920)+W(2,1039900182,1044206765,1043086617,1057123143)+W(3,1066602722,1037219700,-1111210157,1036938090)+W(4,1028023758,-1122555834,1041018096,-1100462314)+W(5,-1123151815,1032289221,1028867168,-1143651414)+W(6,-1125301559,1027754708,-1129842792,1022410763)+W(7,1034604384,1029558442,-1139711519,-1122704124);WS(-1093886876,-1092780259);
|
||||
sum1=W(0,1031521076,1040859655,-1123954783,-1115369432)+W(1,1027325374,-1130075936,1017430099,1005655277)+W(2,1034696971,1027092583,1057011018,1055452141)+W(3,1055461116,1043845385,1041326696,1045628689)+W(4,-1098366291,-1107551117,-1084481759,-1086775792)+W(5,1050583573,-1098824964,1032795870,-1110858724)+W(6,991412379,1023411481,1037665034,1037775165)+W(7,-1102735091,-1106471523,-1113156096,-1108701199);sum2=W(0,-1099549152,-1101982776,1039636960,1065032135)+W(1,1046191187,-1112740199,-1120755726,-1138571865)+W(2,-1115620025,-1110046443,1067650764,-1096892917)+W(3,-1084058149,-1089814493,1022618460,-1106519005)+W(4,1042476476,-1138118945,1056117723,-1084935200)+W(5,1043334912,-1116550886,1030169574,-1123579094)+W(6,-1128057356,-1104607948,-1129519972,1039009532)+W(7,1042222420,-1114781123,1023299940,1029490149);WS(-1103384376,1050555318);
|
||||
sum1=W(0,990997212,-1104723373,-1102560870,-1110645588)+W(1,-1114771100,1006886950,1011892746,1041403778)+W(2,1056616014,1049493908,1060440249,1063537686)+W(3,1049398171,-1123261404,1042753094,1041297647)+W(4,-1113359817,-1101985253,-1095607555,-1091747296)+W(5,-1098384586,-1094355067,-1098733239,-1099641616)+W(6,-1104278389,-1112669305,-1117918862,-1124628967)+W(7,-1120789735,1020875660,1029891897,-1143354303);sum2=W(0,-1097904627,-1102268820,-1101696600,-1102083058)+W(1,-1100977750,1022682138,-1105396681,1035758392)+W(2,1056762738,998260703,1049156882,1055125136)+W(3,1040009482,-1099421122,-1114104451,-1112582051)+W(4,1033294591,-1102966386,1040206209,1048772561)+W(5,1004029807,1040485303,-1118051402,1040482786)+W(6,-1113205081,-1105114179,1028552759,1023069474)+W(7,-1108173489,1040370279,-1109779069,-1135668672);WS(1042369848,-1095650924);
|
||||
sum1=W(0,1032801852,-1124780413,-1142443027,1031124370)+W(1,1024489633,1037041722,-1157391942,1048283534)+W(2,1060985291,1056066249,1059062488,1046815795)+W(3,1051554984,1026983110,1037131073,1028118439)+W(4,-1088222536,-1093287088,-1089766974,-1084610255)+W(5,-1096293908,1035048291,-1113190096,-1107690581)+W(6,-1154392525,1017158008,1041310978,-1111535759)+W(7,-1118760812,-1118618480,1032589425,-1101944856);sum2=W(0,1056251107,-1118435725,-1111043713,-1090037466)+W(1,-1129656805,-1093926860,1052716525,-1083761792)+W(2,-1084477192,1041984407,-1093515412,1073185178)+W(3,1051712939,1053076395,-1096065312,1066458198)+W(4,-1077785336,-1086371528,-1093010832,1074151927)+W(5,1054463958,-1094829660,-1090812268,1063500158)+W(6,1053829707,-1113013425,1046411943,-1090694669)+W(7,-1095714333,-1103046632,1035367276,-1087950464);WS(-1081634407,-1072784825);
|
||||
sum1=W(0,-1102740818,-1115394775,-1101924733,-1100839185)+W(1,-1123768914,-1140848016,-1118249725,-1116477425)+W(2,1024862651,1046040367,-1109613465,-1115978107)+W(3,1049722038,-1098661743,-1138059466,1025943000)+W(4,1056867014,1027952685,1058509811,1050187219)+W(5,-1098437541,1033615035,-1143195264,-1132571500)+W(6,1016622683,-1112643478,-1096240139,-1101581667)+W(7,1008822020,1023463264,-1116668435,1036595961);sum2=W(0,-1139809909,-1126178115,1032546581,-1097752958)+W(1,1042272246,-1118367610,-1138081685,1017774855)+W(2,1046126277,-1111752353,1034216546,1042101074)+W(3,1043290796,-1112722386,1034532478,1030093406)+W(4,-1119940899,1055245806,-1088954301,1058677046)+W(5,-1087007443,1048637958,-1140548675,1029648824)+W(6,1040903120,-1104413152,1019748625,-1089277711)+W(7,1028591970,-1139620757,1017306737,1033828758);WS(1050645916,1033550915);
|
||||
sum1=W(0,-1118556120,-1108262319,1043230361,-1094947334)+W(1,-1103841584,1018079143,1032598742,1008731683)+W(2,-1107219907,1043545243,-1086762442,-1104041435)+W(3,1058293794,-1097977901,1041130248,-1123331655)+W(4,1039060494,-1145250020,1059123936,1057758321)+W(5,-1096913490,1039599795,-1151122424,-1123961290)+W(6,1030703933,-1110184190,-1110311564,-1100512367)+W(7,1044416908,-1132472896,-1147952664,1022228292);sum2=W(0,1040267615,1048409433,-1107165984,-1086251247)+W(1,-1113957324,-1107976602,-1122078587,-1111525785)+W(2,-1112791644,-1110540665,-1088877638,1053330884)+W(3,1057377190,1057673067,1024512949,1042772014)+W(4,1010515766,1032365064,-1090038325,1049266570)+W(5,1028890653,-1103454662,1041725883,-1143554104)+W(6,1024308395,1041630361,1040244783,1037513285)+W(7,-1098504745,1039941233,-1103661415,1024552651);WS(1051978908,-1102077462);
|
||||
sum1=W(0,-1132165009,-1117187439,-1108837850,1037183202)+W(1,1028473682,1045655273,1025240990,1033734537)+W(2,1045761591,1051430047,1060286099,1046972447)+W(3,-1128782822,1028047735,-1178179968,1035331372)+W(4,1013540534,-1096198150,-1130717861,-1085387922)+W(5,-1105434962,-1101497054,-1110960744,-1102517015)+W(6,-1106078467,1014010165,-1121999817,1030141582)+W(7,1008925446,1018887490,-1122721428,1026996307);sum2=W(0,1023072493,-1125531833,1030396885,-1118880502)+W(1,1027419877,-1161271853,1019485964,1028708277)+W(2,974611657,1047662948,1035351326,-1090109833)+W(3,-1110942359,1033315833,1010290822,-1156901930)+W(4,-1101792417,1051899312,1080526024,-1069022098)+W(5,-1087739606,1036440530,-1124554651,-1114394737)+W(6,-1112121991,1037288067,1042102238,-1113214479)+W(7,1032127295,-1143368203,-1132377096,-1141169667);WS(1058455886,-1096183470);
|
||||
sum1=W(0,-1105360672,-1112035684,-1105059667,-1103063975)+W(1,-1112638549,-1104182327,-1106250503,-1103319623)+W(2,-1112611850,1032735242,1048808633,1042817013)+W(3,1058906409,1047248804,1047193699,1057710235)+W(4,1060616064,1033545283,1051085625,-1097442806)+W(5,-1102188695,-1103229812,-1106970890,-1109193562)+W(6,-1104075433,-1111940643,-1115570744,-1097216429)+W(7,-1107200030,-1108265532,-1119499692,-1106901731);sum2=W(0,-1135393651,-1131009665,1004138181,-1111055824)+W(1,-1134829555,-1127256265,-1113946573,1010148467)+W(2,-1114274101,1016197705,-1143366053,1051632163)+W(3,-1111579981,1038147066,1025185617,-1137859715)+W(4,-1117767149,-1130986601,1026922589,1048764370)+W(5,1036257166,-1112945554,-1143942149,-1123068365)+W(6,-1110403581,-1136444051,-1112183743,-1121253595)+W(7,1009689523,989872074,-1123668797,-1123716033);WS(-1103618872,1023577831);
|
||||
sum1=W(0,1041702149,1032268701,1021026046,1032012647)+W(1,1023662430,-1111766616,-1112590149,1042231991)+W(2,1057806109,997904496,1057675340,-1129702414)+W(3,1056283152,1039716321,1049875952,1054291708)+W(4,-1091063799,-1106010126,-1090884608,-1094077941)+W(5,-1094732237,-1100869456,-1105996279,-1098425069)+W(6,1022049043,-1102660926,1046995709,-1100395542)+W(7,1050214494,-1096243374,1047647816,-1100607928);sum2=W(0,1073849383,1069429154,1070121938,1066905653)+W(1,-1087755842,-1080359597,-1073496568,-1070245916)+W(2,-1072987051,-1080077361,-1076996297,-1086754234)+W(3,1060194671,1067521081,1074652354,1075883836)+W(4,1040644897,-1098556311,-1124122091,-1095882058)+W(5,-1096747545,1048551041,-1092793409,1058695504)+W(6,1022236877,-1128073567,-1118780260,1027638421)+W(7,1012182550,-1129108935,-1130588931,1001812541);WS(1010873216,-1100304815);
|
||||
sum1=W(0,-1154187044,1028741017,-1114247598,-1099084427)+W(1,-1104966895,994968800,-1113228468,1028263947)+W(2,1045945805,1051026373,1058185854,1059904750)+W(3,1052860588,1038231664,1040557287,1032103905)+W(4,-1102222630,-1103217414,-1097780567,-1091550752)+W(5,-1108718914,-1110664976,1017403508,1017865354)+W(6,-1113759340,1022415534,-1105383733,-1111624796)+W(7,-1114326870,-1110217221,-1108875519,-1109350878);sum2=W(0,-1114639192,1039210963,1047528380,-1099502544)+W(1,1041344628,-1108972702,1021595805,-1116883371)+W(2,-1100331344,1069298433,1080352854,-1067747068)+W(3,-1080996124,1032407437,-1121090437,1016604711)+W(4,1035901690,1043940791,1030733380,-1084572959)+W(5,1003800555,1045939813,-1121287047,-1122259179)+W(6,1012858414,-1126620651,1036529177,-1099630936)+W(7,1043527822,-1119860547,-1145664907,1034105585);WS(1044302648,-1104457270);
|
||||
sum1=W(0,-1115179413,-1101763748,999269803,-1106420033)+W(1,1041707045,-1128885581,-1110751840,1029110244)+W(2,1029190781,1045938783,1034810490,1055724168)+W(3,1053359959,-1100033022,1037908026,1035419021)+W(4,-1108944696,-1102720380,1038235218,-1101615303)+W(5,-1094303566,1043259278,1011056201,-1123807773)+W(6,-1115207128,1013266237,1025157307,-1105407492)+W(7,1045691477,-1113033137,-1114066571,-1113282394);sum2=W(0,-1117238549,-1115295266,1033754662,-1095438097)+W(1,-1106855439,1011060498,-1117460606,1032653312)+W(2,-1109414288,-1128441429,-1104877135,1053172955)+W(3,1056926069,-1108715476,1036225840,-1114450934)+W(4,-1115125848,-1121954754,1018153798,1038786210)+W(5,-1104082080,1043675119,1008366234,1018894269)+W(6,1023475415,1024122972,1002646200,-1106263750)+W(7,1034246226,1025499367,-1107090094,1013321052);WS(1068015911,1043072951);
|
||||
sum1=W(0,-1127841379,1035792844,-1155603908,1018341976)+W(1,-1111053022,1044403491,-1112313859,1005208661)+W(2,-1101991257,-1091973141,-1110119406,-1095315357)+W(3,-1107228151,-1111437840,-1097295811,-1103670736)+W(4,1041159238,1040826438,1052691071,1053842800)+W(5,1042506601,1050221764,1030249017,1046985745)+W(6,1035382295,-1098419575,1043898844,1030324599)+W(7,-1108241413,1043481954,-1098652336,1032196534);sum2=W(0,-1134315530,1033824390,-1112867968,1039862799)+W(1,1005143468,-1114969920,1030354102,-1131720457)+W(2,-1125722365,1019923991,1039464885,-1087456726)+W(3,-1119378177,1042059959,-1113780490,1009971850)+W(4,-1135384490,998580556,-1093291922,-1061395777)+W(5,-1106942114,-1121281813,1034179020,1032010553)+W(6,-1118933131,1027495017,1045077367,1087627027)+W(7,1034637079,-1148550692,-1118611519,-1117397469);WS(1060186318,-1131602669);
|
||||
sum1=W(0,1022422466,-1102049002,1050775273,-1097141731)+W(1,1056872997,-1099566807,1025667942,1032894309)+W(2,1050205114,1052887138,1052456073,1049038746)+W(3,1040490435,1039690728,1043457059,1045856748)+W(4,-1099402401,-1102238785,-1100510367,-1088759247)+W(5,-1122526498,-1099089908,-1102859210,-1106963501)+W(6,-1112848707,-1106285089,1039607513,-1098786589)+W(7,1048305743,-1104192622,1032266998,-1118572779);sum2=W(0,989650422,-1108234271,-1120122674,1045260201)+W(1,-1114112879,1037831837,-1117501250,1024132690)+W(2,-1120410947,1050158699,-1092804082,1024838498)+W(3,-1125280065,-1119936776,-1114421818,1035095434)+W(4,1047633630,1066272871,1075424781,1061734347)+W(5,-1091697647,1003481288,1011848513,-1106020023)+W(6,-1081060940,-1074101109,-1079387458,1050344942)+W(7,1043540897,1039609275,-1131708367,1026462111);WS(1057810382,986287880);
|
||||
sum1=W(0,-1105255365,1027767677,1037147968,1038550632)+W(1,-1136315263,1035749561,-1115075413,1028257967)+W(2,-1110142276,-1106138450,-1092238936,-1090210593)+W(3,-1089134184,-1093055129,-1097497096,-1089420006)+W(4,1041191503,1031406779,1027980992,1049547413)+W(5,1052451129,1057536820,1050343212,1058108487)+W(6,1050176972,-1130243957,1041310918,1041377527)+W(7,-1115128119,1033537239,-1127231554,1031965752);sum2=W(0,-1099824579,-1113793286,1053512844,-1112943238)+W(1,1041834894,-1099992002,-1120789532,1024916046)+W(2,1070708271,-1104040400,-1091831853,-1072548459)+W(3,-1093778092,1057576575,1064181862,1051972140)+W(4,1075074245,-1084124078,-1082668198,-1072503695)+W(5,1056090411,1053907302,1058602971,1054786345)+W(6,-1097074436,1023561426,1039380165,1009216489)+W(7,1043969626,-1107563771,1034348623,-1106961801);WS(-1075707047,1038147646);
|
||||
sum1=W(0,1038492938,-1115961531,1036899040,1041066756)+W(1,1038870159,1045702796,1022987667,1044017707)+W(2,1050722763,1026800423,1055626176,1052178217)+W(3,1027667391,1053246416,-1100305296,1049962981)+W(4,-1095596015,-1103730686,-1091210886,-1090286882)+W(5,-1094135001,-1095582752,-1109653838,-1093296229)+W(6,1040870942,-1122935577,1047700685,1036539085)+W(7,-1102625947,1048523811,-1105859960,-1117734303);sum2=W(0,-1145353723,-1113260796,-1112198364,-1113367096)+W(1,1007958125,1047146251,-1122974002,1021064313)+W(2,1027969677,-1095928859,1052169305,1052353113)+W(3,-1129450520,1051473061,-1091037095,1050393555)+W(4,-1115030411,1031463199,-1108227013,1051016428)+W(5,1041462653,1045242344,1032341221,1020102815)+W(6,1052090154,-1110261785,1041877601,-1099630700)+W(7,-1087173862,-1102681887,-1095485390,-1111896409);WS(-1102302520,1068562064);
|
||||
sum1=W(0,-1130894152,1029216267,1029150351,1029804895)+W(1,-1108054071,1046304488,-1107326720,1018120580)+W(2,-1101486038,-1094978851,-1104755260,-1093484995)+W(3,-1110271975,-1106599349,-1102131284,-1102274525)+W(4,1044130034,1029251017,1053252560,1050941559)+W(5,1036880709,1050863202,-1128083416,1047248574)+W(6,1031789673,-1102217970,1042516209,1040658618)+W(7,-1113036417,1041743615,-1102226940,1032422999);sum2=W(0,1019111797,-1123809812,1006739898,1041109085)+W(1,-1126211453,1028972357,-1118372569,1025713585)+W(2,1022527979,-1111065998,1031759809,-1095097056)+W(3,1034613952,-1107360163,1033659253,-1118642675)+W(4,-1131519898,1023737355,1045357020,1082939698)+W(5,1027342607,1033832936,-1112248823,-1118824157)+W(6,1029130971,-1117143513,-1106220344,-1064938697)+W(7,-1122955245,-1112280546,1032152906,1028082979);WS(1066566439,-1125753148);
|
||||
sum1=W(0,1020091828,1041951168,-1130301450,1052053147)+W(1,-1131231944,1033588155,1009411772,-1116682291)+W(2,-1096367972,-1098758994,-1093467737,-1089881409)+W(3,-1092544881,-1098181717,-1110070786,-1096392077)+W(4,1038767583,1048997640,-1130818632,1064063659)+W(5,-1116991019,1042770882,1046860728,1027361773)+W(6,1030663671,1025331919,-1108818909,1044746920)+W(7,1022962726,1041997189,1018371147,1038578846);sum2=W(0,-1105507764,-1149004498,-1098298748,-1115729482)+W(1,-1094576030,-1111478010,-1129010369,1018600957)+W(2,1019815533,1047279899,-1106660204,1058550934)+W(3,1031191852,1032716298,-1117054989,1019851909)+W(4,-1136431769,-1121679526,-1096656341,1058580319)+W(5,-1098228632,1041490224,1047791827,-1106522387)+W(6,1024962860,1041000955,-1107413740,1027135608)+W(7,-1101441076,1035067556,-1123460834,1005788722);WS(1050996380,1066787661);
|
||||
sum1=W(0,1042843177,-1120310187,1033453959,-1107450543)+W(1,1017862620,-1134072575,1025308393,1033769739)+W(2,-1109518091,1043911830,1059519229,1061971625)+W(3,1051823058,1046601317,1042112788,1046863997)+W(4,-1098674409,-1097687209,-1096304487,-1098011863)+W(5,-1095767039,-1095249970,-1098354285,-1098417599)+W(6,-1112832565,-1133582755,-1116528532,-1105396874)+W(7,1033796902,999923683,1030029487,-1109771063);sum2=W(0,-1103321099,1033376724,-1108916223,1033194077)+W(1,1038197771,1032881798,1017830932,-1138730935)+W(2,-1087654445,-1114493691,1049058628,1065240604)+W(3,-1128335788,-1094150295,1006224046,-1112103411)+W(4,-1098379129,-1096458683,1036368268,1054396447)+W(5,1049730119,-1108472207,1031462702,-1102017203)+W(6,1013739975,1015354012,-1121134774,-1115257551)+W(7,-1129699908,1021079748,-1117224382,1038189385);WS(1027314912,-1081149641);
|
||||
sum1=W(0,-1109480125,-1114947760,-1101195017,-1132100201)+W(1,-1103759537,1044342469,-1111893319,1051194426)+W(2,1051429188,1053252314,1058130398,1061393767)+W(3,1057940398,-1104522586,1055491172,-1120202825)+W(4,-1118844062,-1094077252,-1113091794,-1085308129)+W(5,-1102037735,-1094497965,-1103334896,-1094870250)+W(6,-1097611416,1034118735,-1104617542,1035982720)+W(7,-1114189097,1036294793,-1128796810,1030785028);sum2=W(0,-1131039707,1024995350,-1104486127,1015537291)+W(1,1053996441,-1103676904,1047124046,-1111129691)+W(2,-1098833779,-1124760267,-1078713050,-1065942779)+W(3,1047686732,1084085461,1064521940,-1093915430)+W(4,-1147567565,1057070390,-1091843304,-1081156610)+W(5,-1094140189,1060423478,1046849692,1018309905)+W(6,1035790053,995065627,1037354874,-1154356731)+W(7,-1107145709,1026796886,-1108476011,1038591472);WS(-1081542375,1044780323);
|
||||
sum1=W(0,1026864081,-1100303790,1048337215,-1098110473)+W(1,1054474587,-1099969099,1023999910,1028627178)+W(2,1046719985,1054288460,1054459103,1048901488)+W(3,1041639871,1034589376,1043694031,1046235480)+W(4,-1098857847,-1108679899,-1098101851,-1093175556)+W(5,-1104037973,-1107626335,-1101510966,-1106600025)+W(6,-1114219435,-1104586877,1041408644,-1098306531)+W(7,1046672715,-1104199322,1022681657,-1126646775);sum2=W(0,1017985090,1027847194,1036519222,-1113167123)+W(1,1037009826,-1113380621,1031131596,-1115360802)+W(2,1024212320,-1098721130,1050387030,-1094712479)+W(3,-1100822056,1028269032,1009055356,-1113841920)+W(4,-1099849981,-1081468176,-1070464929,-1096550174)+W(5,1057690620,1042714784,-1145638655,1046010973)+W(6,1067245211,1074345814,1070597407,-1088417301)+W(7,-1104880956,-1102737214,1000105719,-1112342255);WS(1059294542,1020616832);
|
||||
sum1=W(0,-1157534552,1039080142,-1097783100,1031217968)+W(1,-1164216296,-1138897989,1026686634,-1105498094)+W(2,-1096856701,1044861738,-1089052876,-1085780263)+W(3,1044573672,-1097342660,1041475528,-1105558033)+W(4,1050532499,1041652423,1057029426,1047119538)+W(5,1039715347,1043073721,1040308239,1048391538)+W(6,-1112831597,1046540791,-1098369827,1040272239)+W(7,1024931118,-1103025619,1045404192,-1114523696);sum2=W(0,-1106291706,1001372950,-1099590495,-1093748925)+W(1,1015225205,-1105937891,-1112612361,995169980)+W(2,1040318024,-1105705183,1045484852,1061316313)+W(3,-1098311584,1041085521,1028378294,1035732349)+W(4,-1114208076,-1116263519,-1108179199,1049891427)+W(5,1040668388,-1111581107,-1115787941,-1113959318)+W(6,-1142193319,-1145917455,1036599633,-1108356360)+W(7,-1148092276,1032743264,1021281994,1024794158);WS(1059376718,-1137270291);
|
||||
sum1=W(0,-1118257199,1037392427,-1097794403,1035766677)+W(1,1026067385,1032186693,-1108679762,-1139304576)+W(2,1043258576,-1106073464,1054680411,-1099046488)+W(3,-1088020070,1041392887,-1113652045,-1111666975)+W(4,-1114290826,-1124279079,-1115190716,1052189312)+W(5,1054691490,-1097245116,1025610423,-1123561026)+W(6,-1112002778,1022160871,1045843716,1011458515)+W(7,-1110958220,1046761570,-1117145658,1032305501);sum2=W(0,1025244035,-1122852568,-1092220395,1038019467)+W(1,1048072683,-1113553750,-1119930901,-1139793711)+W(2,1033595807,-1087687504,1066421651,1047700223)+W(3,-1084925862,1050883425,-1105555859,-1146566911)+W(4,1016573022,1048825911,1058107887,-1089540205)+W(5,1045215493,-1098430697,1041208433,-1124843514)+W(6,1002397687,-1104089806,-1130145014,-1111655831)+W(7,1032935415,1015641098,1001885951,-1131703250);WS(1058596686,1013962118);
|
||||
sum1=W(0,1000024554,-1127551432,-1100000762,1035333436)+W(1,-1122612871,1044766998,1041477861,1051562743)+W(2,1052551424,1049056438,1057499982,1036076760)+W(3,-1127972943,-1116046252,-1118015335,-1099275107)+W(4,-1088298614,-1098656348,-1090756927,-1097067922)+W(5,1040213184,1015197910,-1123679237,-1122278672)+W(6,1039656505,1034731345,1019232187,1033429441)+W(7,-1125045580,-1113717771,1037833508,-1122272135);sum2=W(0,-1104434141,1029025211,-1078497608,-1079110377)+W(1,-1085502108,1066279808,1062913146,1068620036)+W(2,1048601996,-1091369704,1052827694,-1106615386)+W(3,-1115334546,1037382016,-1122817088,1048688798)+W(4,1033271157,-1119340081,1025214064,-1109539756)+W(5,1050957039,-1106594885,1036274829,-1118139306)+W(6,1004930429,1028438774,-1106316897,1034989376)+W(7,-1108631008,1023198169,-1134348613,-1139733884);WS(1044771128,1023341948);
|
||||
sum1=W(0,-1156220044,1034545464,1033488922,-1111313058)+W(1,1038420969,1008511890,1013986230,1011084871)+W(2,-1092336191,-1098819215,-1096491302,-1086850728)+W(3,-1102939421,-1100928894,-1115524377,-1089482302)+W(4,1051560294,1044146859,1051910286,1045449190)+W(5,1053458817,1038883707,1012126018,1046748951)+W(6,1036528391,1029114797,1022761170,1029767950)+W(7,1041877300,1034675856,1037411178,1043196317);sum2=W(0,-1071004894,-1080574884,-1089987082,1049506323)+W(1,1065282653,1062249589,1060165079,1070844945)+W(2,1076503146,1066884159,1058011283,-1098882467)+W(3,-1084978169,-1088626314,-1082249713,-1077734377)+W(4,1057610169,-1107351326,1054000347,-1090234844)+W(5,1030898490,-1090230279,1044380003,-1096516163)+W(6,-1122913984,-1130255370,1038970611,1014162118)+W(7,-1114000490,1022492087,-1131621088,1013009282);WS(-1111817840,-1134998409);
|
||||
sum1=W(0,1022731056,1045262352,1044888721,1029818259)+W(1,-1105915720,-1114660906,1027479949,991785104)+W(2,-1102901203,-1094315057,-1085070720,-1111793509)+W(3,1055206544,1046806370,-1123039746,-1136267423)+W(4,1029699069,1052915216,1058770140,1057078063)+W(5,-1095183540,-1097451385,-1112670352,-1114500629)+W(6,1021112442,-1107194439,-1097785743,-1117717150)+W(7,1040740592,1036425016,1005586201,1016465988);sum2=W(0,-1129690332,1030842707,-1123486113,1054087898)+W(1,-1105176966,-1097205966,-1098021434,-1106929221)+W(2,-1113356803,1026318374,1041923626,-1089332833)+W(3,1068558125,-1141184456,-1107728348,-1104288342)+W(4,997943457,-1119512995,1037525758,-1088292904)+W(5,1040210770,1050151959,1018682892,1006954668)+W(6,1015499837,-1180561029,-1144014736,1037328869)+W(7,-1107365912,-1114055561,1009592392,1013301204);WS(-1100650808,1043653943);
|
||||
sum1=W(0,1038392637,1032036848,-1120772452,1043637149)+W(1,1040259489,1047398869,1038054351,1050576478)+W(2,1044290651,1040683515,-1106266873,-1090111931)+W(3,-1133467790,1044787930,1023591523,1037223428)+W(4,-1095199164,-1115398639,-1094097345,-1097393337)+W(5,-1104941765,-1101572298,1016760834,-1102689443)+W(6,1033771919,1038316223,1042896310,1045751664)+W(7,-1159203906,1015063331,1030908740,-1125005703);sum2=W(0,1018053796,1000548496,1049079603,1039189619)+W(1,-1128574308,-1118597354,-1106984497,-1104543855)+W(2,1046306039,1043541862,1010667960,1064529690)+W(3,1047996002,-1087406141,-1095617964,-1086946593)+W(4,-1101305605,1029064982,-1116813778,1038487223)+W(5,-1100258391,1048794746,-1114392997,1045938007)+W(6,1031448374,-1112893849,1021972628,-1105518867)+W(7,1037842238,1033382833,1021089548,-1140458600);WS(-1121537248,1047151836);
|
||||
sum1=W(0,-1096325448,-1113135282,-1098188693,-1112146268)+W(1,-1108791588,-1117696601,-1123869651,-1114157115)+W(2,1052654400,1035132488,1046868890,-1134150082)+W(3,-1129891280,-1098847494,1032919412,-1107856679)+W(4,1000450324,-1110395025,-1139200797,1049727010)+W(5,1041189572,1056884317,1041128337,1058220805)+W(6,-1116556387,1023519458,-1111260975,-1110207458)+W(7,-1104838938,-1098805187,-1146298440,-1103148146);sum2=W(0,-1142864271,1021304865,1043366966,-1107584343)+W(1,1014758407,-1130465374,-1120740451,1000478551)+W(2,1043572739,1026011378,-1102859954,-1080136051)+W(3,-1103597159,-1115654645,1046511165,1053224660)+W(4,-1125571574,1028667063,1022196210,-1072538638)+W(5,-1076945816,1048815254,1072551214,1074776028)+W(6,-1107989855,-1140649559,1020722946,-1132367054)+W(7,1041979768,-1126224006,1027667511,1048839210);WS(-1086568910,969651201);
|
||||
sum1=W(0,-1128189323,1044154939,1043534732,-1114366976)+W(1,-1098469330,-1101372520,-1123038043,-1132910587)+W(2,-1096064919,-1089612648,-1084798775,1053159863)+W(3,1053431542,1050787607,1036747448,-1116020373)+W(4,1047521403,1054908701,1056987371,1057685165)+W(5,-1089249613,-1090701774,-1105030179,1027268120)+W(6,1043461231,-1099266659,-1113308531,-1152040120)+W(7,1042761408,1049635020,1010635844,1018344000);sum2=W(0,1042932965,-1103428495,1039997403,-1093583228)+W(1,1044856824,-1121819542,-1177180368,1028413178)+W(2,-1103892922,1060495074,1052448567,-1075640666)+W(3,1057723154,1057002090,-1112150955,-1118134166)+W(4,-1104364155,1060109323,1064108701,-1073056297)+W(5,1055665788,1060503917,-1116550688,-1110515035)+W(6,-1139842168,-1118896922,991756114,-1097481656)+W(7,1040659602,-1099984054,1034919451,1041069777);WS(-1084093518,-1116656412);
|
||||
sum1=W(0,1002008836,959481663,-1104590931,1050696243)+W(1,-1106608235,1047962207,1030562773,1015783795)+W(2,1058416208,1026388179,1059097973,1042079029)+W(3,1041679827,1049127990,1031439243,1042535660)+W(4,-1096672513,-1109778819,-1088144465,-1096264126)+W(5,-1101432288,-1100480244,-1113594772,-1093923750)+W(6,-1112390467,1023428581,-1112632704,1040470858)+W(7,-1102954054,1047012782,-1112144502,-1145396437);sum2=W(0,1007960967,-1110192070,1049899326,1056650247)+W(1,1078512141,1081472440,1058404171,999915485)+W(2,1027407916,1010716935,-1097456083,-1070859565)+W(3,-1068241064,-1079514242,-1094427160,1030657127)+W(4,-1129957403,1018303319,1037417999,-1094713389)+W(5,-1096379657,1043613542,1025537830,-1116925932)+W(6,-1132155403,-1121935910,-1137993343,-1142796285)+W(7,1039214170,-1111213656,1032528613,1024356221);WS(1052225948,1018668194);
|
||||
sum1=W(0,-1120453498,-1123160289,-1108654867,-1104839613)+W(1,1041378113,1036965515,1044186084,1034438594)+W(2,1051775516,1048325451,1058214550,1064670427)+W(3,-1126638409,1049967085,-1096299613,-1128237844)+W(4,-1117579103,-1111291056,-1093397513,-1091445969)+W(5,-1092047898,-1099225050,-1112850625,-1112057991)+W(6,-1107074656,-1112742544,-1147977428,-1119335936)+W(7,-1109154218,1034167881,-1138567959,1019177609);sum2=W(0,-1121001958,-1148685985,1018483434,1021815720)+W(1,1049361594,-1108634723,-1132118692,-1105580672)+W(2,-1117606942,-1111847761,-1120566718,-1076982600)+W(3,1074852012,1048076514,-1102180777,-1116866514)+W(4,-1103097305,1021935234,1049895592,-1081972918)+W(5,1051964198,1040925857,1017568960,1040155911)+W(6,-1130038396,-1112487949,1038078839,-1125812992)+W(7,-1152546434,-1104919092,1026180028,-1123068468);WS(-1096382876,-1091051652);
|
||||
sum1=W(0,-1116126267,-1113197617,-1112424211,-1124324715)+W(1,-1136579346,1040875430,-1113905512,1017323784)+W(2,1057278592,1048826126,1058810754,1056304110)+W(3,1041995897,1016295122,1024916389,1042534003)+W(4,-1096000788,-1097274020,-1088739494,-1091311905)+W(5,-1114916522,1038826452,-1128507781,1017648027)+W(6,-1116910752,-1140807037,1039925053,-1132679170)+W(7,-1107191661,-1119450067,1023437062,-1098370349);sum2=W(0,-1120311657,1036113080,-1109045199,1029662296)+W(1,-1122358251,-1114085873,1016737279,-1115835645)+W(2,1025682064,-1107470193,1035621932,-1118009189)+W(3,1045290388,1009830751,1035169596,1030264440)+W(4,1036682152,-1108061877,1051542033,-1101792442)+W(5,-1093646778,1056395710,-1091719234,1052430993)+W(6,-1108273289,1012612647,-1101063214,-1076098595)+W(7,-1080861029,1039398973,1065137390,1072502688);WS(1040082544,-1114755812);
|
||||
sum1=W(0,1017784372,1037505264,1045745417,1019379817)+W(1,-1109308706,-1124056118,1025470519,1039469090)+W(2,-1110974758,-1108514902,-1095324708,1052579502)+W(3,1058051822,1046163210,1038459986,998280780)+W(4,1040296296,1041424680,1054913780,-1106396419)+W(5,-1087512533,-1093666877,-1106674096,-1109356390)+W(6,1024480479,-1104471944,-1106439461,-1115066496)+W(7,1040857799,1001482384,995688529,-1108404770);sum2=W(0,-1162396366,-1117720653,-1104226850,-1105580348)+W(1,-1105643813,1031813906,1011045214,1018164327)+W(2,1045315846,-1118054954,1057942904,1059476362)+W(3,-1090022037,1045409162,-1106412098,1023977529)+W(4,1034748092,1034773210,1043388435,1067689202)+W(5,-1083232471,-1101262587,-1124577575,-1102021751)+W(6,1035646876,-1100298043,-1097646834,-1093789486)+W(7,1040357620,-1113573448,1012935222,1024454049);WS(1036525168,-1082462584);
|
||||
sum1=W(0,-1116308971,1037298441,1027885589,-1122874917)+W(1,-1154089797,-1108384819,1028179743,1003463273)+W(2,-1085123800,-1087372070,-1086414101,-1096064460)+W(3,-1099879381,-1104319094,-1127380522,-1096394215)+W(4,1057675329,1051660338,1059597873,1059581688)+W(5,1052784510,-1117339864,1039251609,-1110971807)+W(6,1019612704,1027541711,-1109257541,1041073820)+W(7,1028059367,1045372305,1031554934,1053758651);sum2=W(0,1060691160,-1103295177,1035985281,-1085964582)+W(1,-1105398566,-1107551093,1049030608,-1090293163)+W(2,-1081285622,-1090050073,-1102851017,1072728426)+W(3,1060511611,1033954581,-1086630634,1058069039)+W(4,-1080809247,1050684042,-1087522637,1060852217)+W(5,1058511518,1041242888,1028348456,1062481845)+W(6,1052276353,-1106187369,1048638013,-1090587145)+W(7,1029176048,-1094879840,1046256182,-1087039462);WS(-1074352935,1040600857);
|
||||
sum1=W(0,1042034194,1028652336,1024054004,1030695172)+W(1,1029627411,-1117605317,-1114002447,1041624512)+W(2,1057627204,1025049468,1057567995,1022098295)+W(3,1052602222,1039437212,1049556590,1053416947)+W(4,-1090157751,-1105875707,-1088931067,-1095088235)+W(5,-1094832321,-1104356174,-1107260676,-1101255271)+W(6,1024364622,-1105990299,1048022018,-1100928004)+W(7,1049957878,-1095846092,1047165477,-1098759166);sum2=W(0,-1075440350,-1079714919,-1079134350,-1081735031)+W(1,1055569671,1066585571,1071644179,1075476470)+W(2,1073165865,1065983198,1068716226,1066499710)+W(3,-1095308006,-1080754250,-1074800849,-1073191304)+W(4,-1112383192,1048707236,-1135853868,-1098543278)+W(5,1021808504,-1108920844,1050977418,-1090378667)+W(6,-1148975848,-1115591486,1038054064,-1125971282)+W(7,1040311395,-1110109816,1035370814,-1120408347);WS(1041022776,1033480094);
|
||||
sum1=W(0,-1132576057,-1123321429,1028959481,-1104176578)+W(1,1046472198,-1121060138,1027556403,-1115611836)+W(2,1026327841,1042302896,1052457903,1063677500)+W(3,-1097607903,-1123802109,-1118671609,1039698959)+W(4,-1110434490,-1109312954,-1089918670,1025377120)+W(5,-1090934974,1046523967,-1112257611,1000531209)+W(6,-1119031508,1021323174,1029242558,-1118638740)+W(7,1013298461,-1106699146,1030036314,-1116635705);sum2=W(0,-1106027239,-1122286155,-1102546078,1055155948)+W(1,-1096754888,1032068992,-1121774513,1036170969)+W(2,1049930690,-1127267122,1041115945,-1091935564)+W(3,1052250618,-1103388917,1038737216,-1108790214)+W(4,-1110218398,-1108798456,1058786995,1075372513)+W(5,-1071163371,-1123143101,-1121707895,1032355550)+W(6,1034564779,1018367610,-1095860458,1043590800)+W(7,-1112711414,-1119323979,1016553114,1017858173);WS(1055618972,-1117202987);
|
||||
sum1=W(0,1030962480,-1101414710,-1098100923,-1111740150)+W(1,1036980413,1041005827,1021681163,-1112834597)+W(2,1039894129,1053882576,1057347458,1049814740)+W(3,-1090053902,-1088233382,-1105970903,-1117339136)+W(4,-1101932469,-1089999221,-1085784352,1051098296)+W(5,1056052448,1051763396,1044301630,1032801282)+W(6,1031993659,1048656807,1043352452,1031031542)+W(7,-1104607674,-1119077705,1022017143,1039235901);sum2=W(0,-1114659327,-1123577690,1042921002,-1105097716)+W(1,1042773509,-1093975266,1032061179,1000405669)+W(2,-1101541229,1043634319,1066882360,-1077668162)+W(3,1037629509,1058638399,-1108208741,-1131856909)+W(4,-1107338771,1057974128,1050113378,-1080704784)+W(5,1051155360,1052705661,1008396554,-1111189711)+W(6,1039378885,-1111523166,1040130625,-1104122760)+W(7,1012227066,-1110420726,-1125218199,1025207949);WS(-1091387548,-1116324289);
|
||||
sum1=W(0,1026642697,1044682252,1041967213,1032214050)+W(1,-1131062694,1015214154,-1137069945,-1110158325)+W(2,-1112220622,-1093973688,1046046637,-1086442024)+W(3,-1099996941,1053177927,-1098783494,1037567917)+W(4,1049897926,1047211372,1050365286,-1112122925)+W(5,1046223135,-1132096750,1024489425,1042021623)+W(6,1027958127,-1098544270,-1112662293,-1106755108)+W(7,-1116559746,1034258897,-1111108842,1031638516);sum2=W(0,-1108095393,1016776222,977935538,-1122468710)+W(1,1019959206,1030099429,-1104930054,1002749526)+W(2,1011776651,1024100809,-1097248934,1057627889)+W(3,1042194141,-1117226417,1051928720,1041814459)+W(4,-1101257730,-1105403134,-1101986254,1060632600)+W(5,-1090719303,1037412790,-1109292621,-1115385474)+W(6,1019145070,1032882678,-1124027994,-1103033100)+W(7,1039533068,-1110127978,-1125661478,-1108291818);WS(1057965518,-1118811194);
|
||||
sum1=W(0,-1104352985,1038892389,-1105058276,1042490232)+W(1,-1121521774,-1099594944,1033536020,-1095161930)+W(2,-1106566686,-1112643723,1026830542,-1091938531)+W(3,1058056073,-1101314965,-1098044778,1039936570)+W(4,1052732873,1003767366,1060358287,1019887594)+W(5,-1118338013,1042464324,1024562028,1046000094)+W(6,-1107147458,-1114250980,-1096574819,1048844541)+W(7,1024329053,-1107780158,1032778872,-1107207172);sum2=W(0,-1116205334,1042905425,-1109155755,1044205280)+W(1,1035597621,1008636092,1036458751,-1092853308)+W(2,993944814,-1113078065,1044406596,1040105843)+W(3,1043112037,-1123380436,-1105268129,1005260887)+W(4,1032713731,-1104977559,1048672381,-1104277422)+W(5,-1103087244,-1153474446,1015784078,1036094123)+W(6,-1106373772,1039619019,-1115343154,1048332350)+W(7,999501191,-1106439836,1021528398,-1106473413);WS(1053420700,1049909457);
|
||||
sum1=W(0,-1115258034,1034071238,1027276239,-1115686559)+W(1,1041096236,-1102788144,1034068157,-1107460367)+W(2,-1106165874,-1089903413,1036166247,-1100423414)+W(3,-1093491554,1049835542,-1095323722,-1110396954)+W(4,1050401361,1041332866,1049384898,1037380859)+W(5,1052388787,1034784425,1031952854,1050882791)+W(6,-1113250117,1023742249,-1130552842,-1120158506)+W(7,1037333727,-1103514783,1037170040,-1114330639);sum2=W(0,-1112500393,1028289272,1049127312,1086771603)+W(1,1048088739,1020087240,1014851096,-1146529543)+W(2,1024557142,-1165623582,-1095250820,-1062269001)+W(3,-1095068995,999933935,-1135945992,1025716258)+W(4,-1136367764,1035333264,-1114028070,-1087155359)+W(5,1022077560,1034746908,-1120864651,-1127622484)+W(6,1020782048,-1122738507,1025362120,1034731082)+W(7,-1125007838,-1120796207,1026594640,-1128255426);WS(1063806286,1027083983);
|
||||
sum1=W(0,-1114823180,1030313470,-1111791457,-1111977289)+W(1,-1108043857,1019729830,-1114640622,1033983240)+W(2,1045480194,1039206373,1061885616,1050451993)+W(3,1057912708,1036575619,1039765761,1034424532)+W(4,-1118427516,-1106496703,1010686340,-1083830979)+W(5,-1099420545,-1105267089,-1131920190,-1125840468)+W(6,-1109705966,1020453816,-1103432478,1039658735)+W(7,-1114670584,-1109909656,-1113587473,-1112770081);sum2=W(0,1033978022,-1100194899,1033701105,1050426550)+W(1,-1104028404,1034191613,-1141130302,1010895851)+W(2,-1122290634,-1091664523,-1071413373,1075108998)+W(3,1062092502,-1103668501,1034149895,-1140709165)+W(4,1016780797,-1103111994,1047766898,-1096749849)+W(5,1027350687,-1131589290,-1131724600,1027888251)+W(6,-1164938552,1002490582,-1105595809,1051489664)+W(7,-1108336227,1021076655,-1149103768,-1131210373);WS(1058288590,1045994186);
|
||||
sum1=W(0,1018135640,-1123855059,1040223430,-1112801779)+W(1,1036317947,-1098800665,1034707665,-1096517871)+W(2,-1093342072,-1096797372,-1086390197,-1105293320)+W(3,-1091216419,-1117054299,-1096209979,1023470716)+W(4,1052167946,1041780692,1052872019,1059840396)+W(5,1051866430,1050341107,1048652350,1050625648)+W(6,1038262801,1015346466,-1132654257,-1134794696)+W(7,-1117665797,1012611090,-1139713758,1010858330);sum2=W(0,1041114210,-1099284356,1038292116,-1092208278)+W(1,1054381469,-1104534119,1025804573,1033400256)+W(2,-1099008397,1047276236,-1081084758,-1071665325)+W(3,1054365119,1081581342,1062322644,-1093538640)+W(4,-1123917868,-1111523652,1037708884,-1086778305)+W(5,-1101037019,1026238413,-1134916894,1052085127)+W(6,-1125418381,-1120564910,1020505319,-1100128811)+W(7,1024474915,-1125603475,1025011807,-1103707544);WS(-1088887374,1070119449);
|
||||
sum1=W(0,1040460421,1041554590,1013850612,1038262022)+W(1,1042710919,-1106869091,1044864290,1046057615)+W(2,1052058645,1048371361,1048732808,1042754705)+W(3,1047384127,1054439312,1032508990,1042772520)+W(4,-1090595183,-1115426747,-1094790815,-1087902678)+W(5,-1106656361,-1090477876,-1122940954,-1091795237)+W(6,-1105506686,1029097335,-1129317061,1001782464)+W(7,1038072126,-1131475029,1028935005,-1119515740);sum2=W(0,1024604999,-1112923336,1027433809,1025504127)+W(1,1007245204,-1144581942,-1129047399,1021294865)+W(2,1056461606,1030035123,1050727550,-1090534096)+W(3,-1105339223,-1095507508,1043793174,-1095638178)+W(4,1071685965,1066713447,1068313262,1028028856)+W(5,-1081367671,-1078816510,-1081156501,-1090770344)+W(6,-1075212110,-1080779344,-1078194918,-1153515923)+W(7,1068056044,1069903211,1064173276,1060536751);WS(1040470840,1011790950);
|
||||
sum1=W(0,1015095158,-1120734562,-1116691398,-1118217942)+W(1,1019898057,-1123629847,1034607368,1041822001)+W(2,1043725275,1051465082,1058372660,1055309890)+W(3,1046636817,1044874098,1043010193,1040878843)+W(4,-1105535856,-1108441440,-1095343471,-1081260869)+W(5,1047492563,-1093096561,-1105294873,-1106259483)+W(6,-1108386992,1030149375,-1112701741,1026499745)+W(7,1032201014,-1115283258,1028457510,-1112399171);sum2=W(0,1022830461,1021246145,1015115055,-1114703004)+W(1,-1120910531,1015720307,983370825,-1123770073)+W(2,-1117997331,-1110014342,-1111993293,1036613835)+W(3,1023720090,-1117604953,-1120463052,1036937497)+W(4,1037270083,-1125616185,1044158772,1073620398)+W(5,-1076883688,-1087890801,1025754476,-1113287589)+W(6,1023767946,-1130403951,1025796328,1050812248)+W(7,-1112499600,1028283916,-1104874229,1033737696);WS(1058309838,-1101980246);
|
||||
sum1=W(0,-1118965337,-1098779704,1049071256,-1113399754)+W(1,1026571427,-1110569018,-1131332475,-1128371676)+W(2,-1110907254,1049643561,-1081904943,1042163763)+W(3,1052138696,-1106220306,1025191299,-1129449041)+W(4,1038642111,1038999679,1054751182,1056093093)+W(5,-1083956910,1050507993,-1146247429,1030864044)+W(6,1028903966,-1108240479,1040887994,-1118832415)+W(7,1046797612,-1104697276,-1123883748,1017502086);sum2=W(0,-1137655511,1043191716,-1121349336,-1097517035)+W(1,1046822141,-1129223371,-1116759551,-1124684976)+W(2,-1111106723,1033166752,1033268708,1052576386)+W(3,-1107318253,-1102887232,1040601750,993535634)+W(4,1035105104,-1112822728,-1104857525,1055574555)+W(5,-1114990789,-1121581721,-1152414880,-1107957817)+W(6,-1112318930,1027572041,1035699332,-1097542777)+W(7,-1110157019,1031007843,-1157281192,1025775603);WS(1063710542,-1111213649);
|
||||
sum1=W(0,1039559517,-1110192145,-1107309859,-1118762901)+W(1,-1108199122,1037245627,-1139769966,1035326852)+W(2,1052251350,1049489370,1058328276,1061120005)+W(3,1049656673,1033876357,1041987905,1045428971)+W(4,-1101160384,-1097695264,-1093740712,-1096321197)+W(5,-1097289639,-1114972772,-1102516745,-1103522251)+W(6,-1113889808,1031901152,-1104513406,-1097003636)+W(7,-1112381384,-1176476024,1022802380,-1115185874);sum2=W(0,1026803387,1021750253,1040812059,-1107480079)+W(1,1041131835,-1115082464,1006187407,1001155939)+W(2,-1115186477,1031459540,-1116326399,1040651083)+W(3,1020594503,1033768858,-1132516997,1015478283)+W(4,999853755,1031446318,1058720440,1071698983)+W(5,1051128601,1034660038,1027131696,1041372466)+W(6,-1112425236,-1106593609,-1086524651,-1075753828)+W(7,-1096266051,-1108942599,-1123360193,-1104453127);WS(1039772272,-1082982873);
|
||||
sum1=W(0,1039127452,-1106264016,-1104546353,-1145518233)+W(1,1041713673,1044410893,1039725795,1007790526)+W(2,1049032497,1053169593,1060522592,1056693961)+W(3,-1095982984,-1088607916,-1099512929,-1120546088)+W(4,-1098139952,-1088020664,-1087153807,1038834197)+W(5,1053429837,1048228018,1030077856,-1130616150)+W(6,-1155633625,1043520647,1040400554,-1139907193)+W(7,-1104883452,-1103034636,-1134131855,1012687882);sum2=W(0,1032987173,-1102803435,-1097110538,-1101871105)+W(1,-1101555589,-1123533577,-1098769512,1048796624)+W(2,-1092902636,1037122437,-1083842457,1067610414)+W(3,1033006847,1041814167,1045724867,999019252)+W(4,1027660911,1039508875,-1115097563,1067552095)+W(5,-1096151174,1026567371,-1107225085,-1105667947)+W(6,1032111389,-1101516234,1001644292,-1104358647)+W(7,-1145661076,-1104681426,1020958965,1028203943);WS(-1101412664,1073047832);
|
||||
sum1=W(0,-1113880945,-1123950537,-1109995975,-1123565085)+W(1,-1123728428,1035385983,-1115318676,1010675502)+W(2,1059007377,1047579477,1060416389,1056063051)+W(3,1046383171,1040643140,1033389702,1041003725)+W(4,-1091904865,-1097814305,-1087199740,-1092124214)+W(5,-1099567891,1038341800,-1119557930,1042882861)+W(6,-1133362719,-1131741454,1032803377,-1113780884)+W(7,-1113889390,-1126485237,1012558775,-1096461162);sum2=W(0,1013686761,-1123503757,1035262859,-1115490710)+W(1,1025861040,980681483,-1125276038,-1129892230)+W(2,1030949359,1039110679,-1105775253,1027204409)+W(3,1019519396,-1111394964,1024413043,-1126757058)+W(4,-1109223248,1035635962,-1106751414,1057425426)+W(5,1043312829,-1098000154,1051287795,-1103421662)+W(6,-1132915573,996209923,1029135163,1070858778)+W(7,1067133266,-1098902818,-1083268694,-1073095921);WS(-1103532344,-1105840701);
|
||||
sum1=W(0,-1106756472,-1106322913,1029810954,-1096389739)+W(1,-1116067305,1035916925,-1105566449,1034505108)+W(2,-1105825052,1053932942,-1086676361,-1098358914)+W(3,1054020609,-1096691570,1051257001,1026552303)+W(4,1050195304,1007328528,1057202097,1054492326)+W(5,-1093369370,1012599092,1027855335,-1101687900)+W(6,1044840709,-1104890465,-1144507642,-1098185309)+W(7,1032208700,1048715303,-1100267787,1050640157);sum2=W(0,-1111707317,-1119262447,1037989791,1056036881)+W(1,-1105645897,1006194414,-1146663095,-1129479912)+W(2,-1101137684,-1109186725,1049211868,-1099242284)+W(3,1038198606,-1118866635,-1109483964,-1114787638)+W(4,-1116414033,-1107841286,1056722210,-1094543747)+W(5,1053421235,-1104714858,-1120693058,-1115357885)+W(6,-1103752872,1034593530,-1110917586,1049861706)+W(7,1030171051,-1103907620,1032413269,1029169157);WS(1045178680,-1115117954);
|
||||
sum1=W(0,-1102680211,-1123018420,-1116849368,1024407336)+W(1,-1107241006,1026392201,-1107918421,-1123314455)+W(2,1048681528,-1113607536,-1092105355,-1093530556)+W(3,-1096193779,-1102060551,-1102337510,-1095199752)+W(4,1019008549,1040296293,1035615004,1061339424)+W(5,1057711678,1055864515,1045891981,1052562824)+W(6,1008490315,1012835273,1027033246,-1128145511)+W(7,-1103222073,-1110547491,-1110097884,1020395952);sum2=W(0,-1108321996,-1115537892,-1106228104,998645667)+W(1,-1112292909,1035781218,-1111036660,1018530825)+W(2,-1096948503,-1104693583,1047339287,1055675007)+W(3,1049114511,-1100682049,1032758858,-1113969306)+W(4,-1112108000,-1112710060,-1126080161,1051246853)+W(5,1041989299,1025978716,1034053890,-1113712936)+W(6,1026091852,1022753169,-1120501740,-1105262859)+W(7,-1123292948,-1139782977,-1111667328,1033000622);WS(1044590904,1058699692);
|
||||
sum1=W(0,985175380,1034192409,1020554347,1024014533)+W(1,-1115433194,-1128687821,1008304190,-1115445028)+W(2,-1092606720,-1090621088,-1093618783,-1113905855)+W(3,-1096920415,-1112503613,-1100279725,-1101027255)+W(4,1051210502,1050384326,1055009987,1062574818)+W(5,1054554325,1031218808,-1105751509,-1144235755)+W(6,1009220799,-1109361592,-1117059707,-1128567457)+W(7,1015981863,1039114097,-1127205548,1035507338);sum2=W(0,1036009101,-1117283755,1033667347,-1107239966)+W(1,1034685217,-1128406639,-1123321687,-1125402335)+W(2,-1108619644,1041337919,1012813669,1053310286)+W(3,-1103814148,1029066827,-1109499964,-1123197815)+W(4,1010492213,-1100684466,1015579759,1056064408)+W(5,1050883237,-1113069964,-1098878001,-1096911819)+W(6,-1131279719,1035041542,-1124020763,1025470531)+W(7,1032198922,-1104788458,1024066141,-1108347132);WS(1044030776,-1089132931);
|
||||
sum1=W(0,1034269487,1032883970,1042439154,1044751430)+W(1,1019707982,1041434446,-1133288904,-1128708109)+W(2,-1093699058,-1097458090,-1086092656,-1078975458)+W(3,1035194756,1038040390,-1131544335,-1101499019)+W(4,1045160768,1050995424,1057188990,-1096290982)+W(5,1032938655,1043682915,1022768458,1043305900)+W(6,1040395197,-1135242887,1040422743,1048952172)+W(7,1042217766,1043586045,1029073256,1044718778);sum2=W(0,1043294282,-1127265324,1035036911,1051203976)+W(1,-1092441683,1037063919,-1095318743,-1096741875)+W(2,-1107262777,-1107127922,1048700262,-1114081637)+W(3,1027047222,-1087538045,1043898666,-1114635611)+W(4,-1132728616,-1133435576,-1115280193,1060204569)+W(5,-1096051714,1059699424,-1091030613,1057805441)+W(6,-1112978295,-1101649503,-1142433873,-1138065032)+W(7,1049542158,1027406094,1036599707,-1117298502);WS(-1083489614,-1078579141);
|
||||
sum1=W(0,-1113694287,1048897616,-1104500498,1029397720)+W(1,1039983475,-1099529286,1047818144,-1100400745)+W(2,-1091060438,-1104759380,-1089217572,-1096433234)+W(3,-1090900481,-1103761763,-1126261903,-1098862766)+W(4,1048678744,1055607032,1025763911,1056656214)+W(5,1055730826,1039576037,1050842685,1044462332)+W(6,1022130309,1045345264,-1098656951,1045280313)+W(7,1003335600,-1104729181,1045845834,-1124798927);sum2=W(0,1034867092,1036831152,-1155378720,1050005016)+W(1,-1109019109,-1107857756,1025727369,-1105627363)+W(2,-1113896283,1008734783,-1107821706,1036439980)+W(3,-1105188391,-1103852014,-1113326142,1036502992)+W(4,-1089397746,-1143881728,-1090933436,1067046868)+W(5,1074023168,1073004488,1071596064,1068047188)+W(6,1053130734,1048547317,1050664536,-1081990202)+W(7,-1073616958,-1073650181,-1078582463,-1079035066);WS(-1123566816,-1118788492);
|
||||
sum1=W(0,1034266605,-1136553988,1032767842,-1119057557)+W(1,1032596498,-1138237144,1034235800,1038972738)+W(2,-1131696345,1054570946,1043367745,1057910725)+W(3,1051309065,1050053561,1044754161,1047609962)+W(4,-1102436480,-1101485920,-1093672570,-1081257723)+W(5,-1104247863,-1097237249,-1100737384,-1118734125)+W(6,1029920799,1027694719,1029228634,1038070160)+W(7,1041012541,-1104490509,1036672371,-1101643609);sum2=W(0,1001205015,1006355343,1030505158,-1119701641)+W(1,1039794598,-1107202062,1026836118,-1115440174)+W(2,-1108935456,1048575251,-1114918170,-1088419213)+W(3,1032736312,1045905661,-1116946341,1003805295)+W(4,-1123729961,1037564428,-1096130861,-1068662368)+W(5,1076967646,1068403675,-1104305708,-1124006983)+W(6,-1151981614,-1123825361,1015236500,-1095410362)+W(7,1049774729,-1105335733,1050153445,-1103176791);WS(-1103567160,1051728620);
|
||||
sum1=W(0,1022317012,-1105517764,-1109296554,1030946149)+W(1,1032988986,-1117957958,1025729823,1009731405)+W(2,1037463598,1027268637,1052072875,-1094107172)+W(3,-1087396213,-1098739651,-1104965205,1017302004)+W(4,-1094952698,-1107670055,-1103880757,1052944567)+W(5,1057943536,1052382091,1036164793,1041821631)+W(6,1033922872,1024776175,1038888053,1043766492)+W(7,-1110506946,-1108829569,-1132271979,1015545129);sum2=W(0,1031290011,-1114551402,-1137203270,1025723227)+W(1,1020823723,-1107112701,-1156747895,-1140368490)+W(2,-1127050317,1026829489,1032334734,-1098446681)+W(3,1041359246,1041376772,1034398482,-1104694439)+W(4,-1113481669,1042490649,1043198364,-1127701979)+W(5,1057793899,-1100591458,-1114292550,1037536680)+W(6,-1080536402,-1076466135,1038797044,1074254195)+W(7,1035340712,-1118262367,1013380262,1032104302);WS(-1106439480,1029090439);
|
||||
sum1=W(0,1034559195,-1151887836,1020849475,1042053132)+W(1,1043127920,1043814293,1037260390,1043715864)+W(2,1042655458,1030625962,1059377738,-1084013087)+W(3,-1107145304,1032281331,1040913704,1033172451)+W(4,-1102396839,-1115609614,-1089162129,-1083731653)+W(5,1052971191,-1107154457,-1113717087,1017680531)+W(6,1026400220,1035325646,1042909598,1039293086)+W(7,1029716960,1024778063,1028666946,-1130742978);sum2=W(0,-1129107524,-1123636938,-1116921954,1035143287)+W(1,1036996009,1026655402,-1117010042,-1126794884)+W(2,1021999108,-1148550480,-1104180688,1058583951)+W(3,-1112895549,-1116180274,-1131502740,-1138164712)+W(4,1022835844,1016982596,1016773924,1054454385)+W(5,-1097314323,-1099699990,-1132536424,-1129763396)+W(6,-1129901940,-1140398984,1030858450,-1117386658)+W(7,-1108156993,-1118751234,1016259828,-1117013506);WS(1048151864,1059242544);
|
||||
sum1=W(0,-1122367849,-1121466768,1042165293,-1116044868)+W(1,-1105437493,1037358179,-1125163356,-1111398955)+W(2,-1097114939,-1097911384,-1085899247,1042506911)+W(3,1056857214,-1105063934,-1123578292,-1106114902)+W(4,1043794348,1033810391,1063564267,1042284551)+W(5,-1089674786,1049648847,1021855394,1045389303)+W(6,1026875087,1014185912,-1106211614,-1111561384)+W(7,1040868541,1028107682,-1111395274,1010402126);sum2=W(0,-1139648101,-1108856547,1015236663,-1095822659)+W(1,-1137977893,1038373686,1015865663,1025690243)+W(2,-1110557326,1041627874,1032833232,1054902128)+W(3,-1098765424,-1121592121,-1106594443,-1117564251)+W(4,-1106733442,-1106727608,1048813377,1055403310)+W(5,-1097123375,1045561320,-1106386080,1017823319)+W(6,1039330638,987619817,1025349119,-1095503796)+W(7,1050144719,-1108448514,1041979856,-1105901385);WS(1058511566,1043187024);
|
||||
sum1=W(0,1042620242,1027981614,1037513401,1050564856)+W(1,1040390932,1044188393,1032851398,1043046140)+W(2,1041476871,1044640335,1039039385,-1085132912)+W(3,-1095196494,-1116362934,-1107832665,-1105825814)+W(4,-1106861387,-1120607404,-1101062960,-1089194338)+W(5,1032203084,-1134658518,1026497359,-1105488567)+W(6,1043942651,1040914531,1040902562,1048598306)+W(7,1019897185,1032634704,1027555603,1032742569);sum2=W(0,-1094808435,-1132385524,-1110994277,1039748829)+W(1,1038866141,1012861192,1030487914,-1132742376)+W(2,-1083260450,-1089624726,-1098133391,1063143581)+W(3,1043371703,1040218148,1012758152,1052570990)+W(4,1041967320,-1102801635,1050258559,1037743779)+W(5,1048943341,-1112998265,1031702418,-1105604919)+W(6,1026111290,1034887813,-1123786474,1033106845)+W(7,-1110363077,-1121754906,1012203560,-1111765769);WS(-1087236686,1061665912);
|
||||
sum1=W(0,-1115274057,-1116162424,-1104461343,-1093387666)+W(1,-1113556238,-1115159031,-1126942285,-1121543315)+W(2,1023071688,1030200068,1054050807,1067462106)+W(3,1050597447,1031104576,-1121547516,1042315272)+W(4,-1107980923,-1101866270,-1092884195,1056570668)+W(5,1044256537,-1106234576,-1128835891,-1114796114)+W(6,-1119301463,-1128116268,-1109238785,-1095571507)+W(7,-1103733247,-1111522325,-1111458030,-1109780718);sum2=W(0,-1127633710,1024854732,-1123781128,1040493279)+W(1,-1105896535,1033983514,-1122459292,-1120616672)+W(2,1024134807,1020748524,-1117094752,1065417820)+W(3,1047826025,-1102101577,1040101538,-1124130304)+W(4,-1114424195,-1098546148,-1079772750,1059484680)+W(5,-1107504040,1049649199,-1105983778,1041220419)+W(6,-1109129714,1025355297,-1102118069,-1114766469)+W(7,1033237727,-1154145757,1012710689,-1123999628);WS(-1092106140,-1084163121);
|
||||
sum1=W(0,1036347305,1016904817,1034414494,1040590819)+W(1,1047670567,1030378702,-1114654031,1037868673)+W(2,1049849489,1040213041,1056746079,1048812489)+W(3,-1084779712,1040726752,1033236350,1034988241)+W(4,-1101083230,-1152694122,-1083169173,-1107117385)+W(5,1051667767,-1109066592,1024925978,-1107106473)+W(6,-1106738110,-1115216475,1039797369,1022569263)+W(7,-1112982247,-1125038036,1025136605,-1146668256);sum2=W(0,-1144361879,-1128843246,1005924247,-1104940693)+W(1,-1123234701,1030348431,1032437115,1024671661)+W(2,-1111008682,-1134810723,1041181160,1054697191)+W(3,1052731012,1042931729,-1112071203,-1111460488)+W(4,-1092072719,-1121102479,1045581242,1046555600)+W(5,-1103970223,-1104348933,-1113690885,-1129885552)+W(6,1021883158,-1116668390,-1109114373,-1113715104)+W(7,-1128555074,1032936433,-1136719027,-1114960949);WS(1058637774,-1109876822);
|
||||
sum1=W(0,-1123254812,1041301297,-1108082435,-1113241451)+W(1,-1110973875,1027216056,1014894339,1019588394)+W(2,1042623060,-1105094644,1059472952,1043969956)+W(3,-1113269955,1026816394,-1130602892,1026167148)+W(4,-1126486401,-1111052512,-1094910408,-1094009726)+W(5,1058531737,-1100061186,1032486130,-1117291247)+W(6,-1112485473,1037949088,1016105496,1038892497)+W(7,-1093047519,1032398170,-1128303438,1021704844);sum2=W(0,1019183838,1031923668,1049015983,-1096362417)+W(1,1005830618,1036998273,-1119396253,-1125844722)+W(2,-1103677237,1026573624,-1101357077,1060010174)+W(3,-1122620605,-1106684685,1023743335,970656667)+W(4,1041385745,1025625867,-1095136476,-1096248497)+W(5,-1115221092,1049273019,-1112424814,1011280453)+W(6,-1115238116,1024201143,1024442030,-1122837727)+W(7,1034369966,1031554545,1004099770,1010302645);WS(1068382951,-1145853862);
|
||||
sum1=W(0,-1109092968,-1120835030,1015957108,1033165317)+W(1,1015780402,-1098982451,-1106789039,-1105810191)+W(2,-1104283584,-1104742016,-1087137628,-1082841532)+W(3,1048723479,-1119342334,1037068029,998682871)+W(4,-1126224104,1048835390,1060142968,1050512116)+W(5,1050625794,1046183055,1033167819,1042826568)+W(6,-1142984099,1035504970,1044651720,1036256010)+W(7,1040271692,-1112268532,-1115364877,-1113754717);sum2=W(0,1042289605,-1123754179,1040865617,1025996190)+W(1,-1100913998,-1118459936,-1114401734,-1118182115)+W(2,-1105845074,1032442894,-1090127653,1055606718)+W(3,-1104101067,1026136504,1031986833,1045409779)+W(4,-1105090355,-1106552079,-1075116096,1073431719)+W(5,1067916428,1042119939,-1112990087,1031635830)+W(6,1041479887,1028813354,-1087510643,-1084272058)+W(7,1045036562,-1131666845,1021173748,-1131440550);WS(-1115823328,-1115141930);
|
||||
sum1=W(0,994860217,1043355533,1046651158,1031967699)+W(1,-1112906011,-1139800861,1032268536,1021673189)+W(2,-1096937968,-1093401724,-1082957735,1057829358)+W(3,1054780763,1049387203,1029694230,1032667294)+W(4,1034643656,1045563268,1056739037,1053028032)+W(5,-1085595451,-1100812438,-1112691098,-1163065290)+W(6,1022968545,-1100277972,-1106135459,-1113373017)+W(7,1036473238,1042166401,-1109328859,1026417494);sum2=W(0,1041009418,-1106230161,-1113994011,-1100787264)+W(1,-1102450993,-1114680808,1031764893,-1145068408)+W(2,1006794492,1034312638,-1108126219,1060460225)+W(3,-1119222967,-1097084093,-1125377404,-1105852265)+W(4,1023178506,-1120362931,-1105213924,1054015707)+W(5,1053508358,-1133314452,-1141774536,-1120752408)+W(6,-1126244586,1021996758,-1131146954,997147503)+W(7,-1107185372,-1126416406,-1126617106,-1131039214);WS(1044911928,1063248560);
|
||||
sum1=W(0,-1117210934,1045807559,-1116245664,-1122601008)+W(1,1041679280,-1102494868,1044187563,-1101059428)+W(2,-1089987573,1006551364,-1085623154,-1098705597)+W(3,-1089608778,-1098692501,1040126000,-1100421777)+W(4,1050931427,1049202419,1044690392,1056494849)+W(5,1054654497,1047881833,1043119951,1043071666)+W(6,-1154913199,1049427019,-1098224261,1043742399)+W(7,1009817082,-1102952115,1048685800,-1132265536);sum2=W(0,-1110897864,-1104703066,1039476246,-1102025112)+W(1,1041770976,1044782005,-1112640404,1045848501)+W(2,1031814971,-1126406622,-1112535334,-1088994686)+W(3,1050082866,1038057456,1029663347,-1098794387)+W(4,1060526454,1034850394,1060516426,-1088701567)+W(5,-1072347435,-1075073775,-1077197270,-1081012351)+W(6,-1090228093,-1097166620,-1091926928,1063814816)+W(7,1074296249,1073862535,1067261757,1067785227);WS(-1105546040,1026157880);
|
||||
sum1=W(0,1040950836,1036866652,1045419231,1057171433)+W(1,1039696013,1040737235,1031337694,1043417390)+W(2,1040614249,1043435937,1048836647,-1092874056)+W(3,1049109967,1037560064,1039556030,1020658754)+W(4,-1102499357,1032157499,-1088963702,-1078642173)+W(5,-1094603626,999044599,-1107844556,-1101965321)+W(6,1036650571,1032871003,1035867609,1040635958)+W(7,1039966133,1035782037,1034875342,1029450491);sum2=W(0,999804672,965076992,1017997216,-1113573416)+W(1,1015814944,1013150208,1004325632,-1116017408)+W(2,1033414560,-1142972544,-1117537424,-1080122522)+W(3,-1116987776,1009041344,1030258512,-1123867424)+W(4,-1131242272,-1152459008,1043660652,1068973644)+W(5,-1113471168,1023678672,-1115573696,1025739248)+W(6,-1111239120,-1114613368,1024438240,1009242816)+W(7,1026341216,-1111376032,-1124670336,1011147520);WS(-1081027239,1060388068);
|
||||
sum1=W(0,1040945153,1018532824,1048158700,1050078256)+W(1,1043330564,1045983912,1034126717,1042366848)+W(2,1049191505,1052335227,1053224518,-1089652372)+W(3,1050009062,1019623144,1043374892,1037373643)+W(4,-1103567931,-1106690587,-1098210230,-1079677805)+W(5,-1090769236,-1102526621,-1113976903,-1106920486)+W(6,-1142725077,-1126830164,1044049241,1037048166)+W(7,1037549983,-1124021470,1031972104,1000910717);sum2=W(0,1029289565,1023484285,1041097307,1044843621)+W(1,-1101664529,-1108647964,-1111945130,-1129898257)+W(2,-1119356133,1031916514,-1120749829,1057057740)+W(3,1055633817,-1098024997,1038083406,-1101101054)+W(4,-1126159585,-1111485988,-1121314077,1024531885)+W(5,-1102656055,1016983721,-1105960100,1022769465)+W(6,-1119814653,-1133461586,-1112201820,1001931237)+W(7,1035253182,1019582313,1011319026,-1110859200);WS(-1121436896,-1083449266);
|
||||
sum1=W(0,-1131437006,-1126965659,-1106898372,1049661628)+W(1,-1110051320,1048826500,1018834023,1030351624)+W(2,1057845458,1026072602,1058188821,1047051462)+W(3,1036301673,1049513187,1026266705,1043516478)+W(4,-1096100393,-1106937331,-1089458543,-1093909527)+W(5,-1105302990,-1097831955,-1115312055,-1094725407)+W(6,-1112818966,1025271436,-1120770471,1039868950)+W(7,-1101852248,1048680544,-1111779257,-1137214404);sum2=W(0,1025140224,1016993788,-1106156741,-1085967118)+W(1,-1070014283,-1066270592,-1089828448,-1115300709)+W(2,-1118806788,1030590564,1042721449,1078987048)+W(3,1078555235,1069325982,1051485796,1026006822)+W(4,-1126785121,-1118559458,-1106137914,-1100137345)+W(5,1044823121,-1105174392,-1121082393,1011662011)+W(6,1031495588,991152164,1038491925,1040984057)+W(7,-1111978905,1030579932,-1113499951,-1120641633);WS(1060473294,-1125032523);
|
||||
sum1=W(0,-1118381578,-1131528546,-1103035725,1044891665)+W(1,1017562024,1038728371,1013193724,1017619335)+W(2,1043924207,1048790648,1057928103,-1096003632)+W(3,-1104437021,-1127678449,-1138265298,1019650740)+W(4,1028842287,-1094915206,1048586166,-1089668066)+W(5,1048997587,-1106021950,1016196772,-1112334062)+W(6,-1103983036,1032416951,-1131359957,1041536420)+W(7,-1119623443,1026802338,-1112764523,1028850580);sum2=W(0,-1124013145,-1154979909,-1113455493,1042673063)+W(1,1009341589,-1131887235,-1126494367,-1120394460)+W(2,1023871771,-1104183315,1024353365,-1099433949)+W(3,1037029004,-1106752952,-1136822537,-1135604889)+W(4,1041717973,-1104961174,-1071159846,1075222357)+W(5,1061754151,-1106459992,1037905746,1020599743)+W(6,1027246941,-1105906795,-1114760758,1048045634)+W(7,-1101645527,1027783079,-1130069351,1023779471);WS(1063175758,1049951270);
|
||||
sum1=W(0,1051934199,1041620825,1053157077,1019501037)+W(1,-1121035141,1024394007,1034798936,999909159)+W(2,-1084051495,-1091045702,-1089200998,-1103613676)+W(3,-1103906809,1042850683,-1117239270,-1106705027)+W(4,1040719576,1046456792,1054477181,1050464826)+W(5,-1098419444,-1097805325,1011564046,-1091232034)+W(6,1028219745,1028165760,-1110307566,1037889601)+W(7,1045652053,1054554722,1031152711,1056053333);sum2=W(0,-1091471926,1042259987,-1103057728,1049412228)+W(1,1044973062,-1116401558,1011000463,-1130123924)+W(2,1062079447,-1095572989,-1089203271,-1092861102)+W(3,1034556296,1047552828,-1110031497,1051271629)+W(4,1055700238,1041645665,1037140407,-1093629070)+W(5,-1095940003,-1106623325,-1107294450,1053844390)+W(6,1015596856,1033532620,1035045090,1042934527)+W(7,1032040702,-1106239816,1033073048,-1095799213);WS(-1085388366,-1090694979);
|
||||
sum1=W(0,-1123787314,-1119481145,1032777214,-1112850502)+W(1,1041751591,-1125429276,-1140788444,-1113892940)+W(2,1044273497,-1130943626,1047368143,1059845268)+W(3,-1095680144,1039407200,990533574,1032644049)+W(4,-1108110651,1041576542,-1087220302,1027588771)+W(5,1036323946,-1111657568,1021334836,-1143449895)+W(6,-1115475932,-1117135031,1040347561,-1101064470)+W(7,1037523789,-1126225621,-1134357621,-1109271006);sum2=W(0,-1107190004,1013881877,-1118295314,-1121103222)+W(1,-1127822751,-1115317828,-1126179247,-1114801766)+W(2,1037736456,-1105376838,-1123416196,1042717593)+W(3,-1115549939,1043660085,-1126402007,1040920849)+W(4,-1125693587,1040619572,-1082924015,1068021664)+W(5,1016978358,-1108863865,-1136349779,-1107267301)+W(6,-1120404934,-1122228614,1051908042,-1087341114)+W(7,1042189807,-1125959243,1038966556,1023515477);WS(1065904679,-1122628785);
|
||||
return clamp(mstd0 + 5.0 * vsum / wsum * mstd1, 0.0, 1.0);
|
||||
} // nnedi3
|
||||
vec4 hook() {
|
||||
vec4 ret = vec4(0.0);
|
||||
vec4 samples[8];
|
||||
samples[0][0] = HOOKED_texOff(vec2(-1.0, -3.0)).x;
|
||||
samples[0][1] = HOOKED_texOff(vec2(-1.0, -2.0)).x;
|
||||
samples[0][2] = HOOKED_texOff(vec2(-1.0, -1.0)).x;
|
||||
samples[0][3] = HOOKED_texOff(vec2(-1.0, 0.0)).x;
|
||||
samples[1][0] = HOOKED_texOff(vec2(-1.0, 1.0)).x;
|
||||
samples[1][1] = HOOKED_texOff(vec2(-1.0, 2.0)).x;
|
||||
samples[1][2] = HOOKED_texOff(vec2(-1.0, 3.0)).x;
|
||||
samples[1][3] = HOOKED_texOff(vec2(-1.0, 4.0)).x;
|
||||
samples[2][0] = HOOKED_texOff(vec2(0.0, -3.0)).x;
|
||||
samples[2][1] = HOOKED_texOff(vec2(0.0, -2.0)).x;
|
||||
samples[2][2] = HOOKED_texOff(vec2(0.0, -1.0)).x;
|
||||
samples[2][3] = HOOKED_texOff(vec2(0.0, 0.0)).x;
|
||||
samples[3][0] = HOOKED_texOff(vec2(0.0, 1.0)).x;
|
||||
samples[3][1] = HOOKED_texOff(vec2(0.0, 2.0)).x;
|
||||
samples[3][2] = HOOKED_texOff(vec2(0.0, 3.0)).x;
|
||||
samples[3][3] = HOOKED_texOff(vec2(0.0, 4.0)).x;
|
||||
samples[4][0] = HOOKED_texOff(vec2(1.0, -3.0)).x;
|
||||
samples[4][1] = HOOKED_texOff(vec2(1.0, -2.0)).x;
|
||||
samples[4][2] = HOOKED_texOff(vec2(1.0, -1.0)).x;
|
||||
samples[4][3] = HOOKED_texOff(vec2(1.0, 0.0)).x;
|
||||
samples[5][0] = HOOKED_texOff(vec2(1.0, 1.0)).x;
|
||||
samples[5][1] = HOOKED_texOff(vec2(1.0, 2.0)).x;
|
||||
samples[5][2] = HOOKED_texOff(vec2(1.0, 3.0)).x;
|
||||
samples[5][3] = HOOKED_texOff(vec2(1.0, 4.0)).x;
|
||||
samples[6][0] = HOOKED_texOff(vec2(2.0, -3.0)).x;
|
||||
samples[6][1] = HOOKED_texOff(vec2(2.0, -2.0)).x;
|
||||
samples[6][2] = HOOKED_texOff(vec2(2.0, -1.0)).x;
|
||||
samples[6][3] = HOOKED_texOff(vec2(2.0, 0.0)).x;
|
||||
samples[7][0] = HOOKED_texOff(vec2(2.0, 1.0)).x;
|
||||
samples[7][1] = HOOKED_texOff(vec2(2.0, 2.0)).x;
|
||||
samples[7][2] = HOOKED_texOff(vec2(2.0, 3.0)).x;
|
||||
samples[7][3] = HOOKED_texOff(vec2(2.0, 4.0)).x;
|
||||
ret[0] = nnedi3(samples);
|
||||
return ret;
|
||||
} // hook
|
||||
//!DESC NNEDI3 (combine_x, nns128, win8x4)
|
||||
//!HOOK LUMA
|
||||
//!BIND HOOKED
|
||||
//!BIND nnedi3_int
|
||||
//!WIDTH 2 HOOKED.w *
|
||||
//!OFFSET -0.500000 0.000000
|
||||
//!WHEN HOOKED.w OUTPUT.w / 0.707106 <
|
||||
vec4 hook() {
|
||||
vec2 dir = fract(HOOKED_pos * HOOKED_size) - 0.5;
|
||||
if (dir.x < 0.0) {
|
||||
return HOOKED_texOff(-dir);
|
||||
} else {
|
||||
return nnedi3_int_texOff(-dir);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user