updates
This commit is contained in:
parent
ad58a6fcb9
commit
53c4cee0a5
|
@ -487,6 +487,7 @@ plasma5Packages.qt5ct
|
|||
lxappearance
|
||||
spotdl
|
||||
kdenlive
|
||||
minetest
|
||||
# natron
|
||||
digikam
|
||||
rubberband
|
||||
|
@ -689,6 +690,7 @@ services.emacs = {
|
|||
dired-rainbow
|
||||
diredfl
|
||||
dired-rsync
|
||||
fd-dired
|
||||
ledger-mode
|
||||
org-msg
|
||||
calfw
|
||||
|
|
278
eww/eww.scss
278
eww/eww.scss
|
@ -1,9 +1,9 @@
|
|||
/**
|
||||
Created by saimoom **/
|
||||
*{
|
||||
all: unset;
|
||||
font-family: feather;
|
||||
font-family: VictorMono Nerd Font;
|
||||
all: unset;
|
||||
font-family: feather;
|
||||
font-family: VictorMono Nerd Font;
|
||||
}
|
||||
|
||||
$background: rgba(00, 00, 00, 0.7);
|
||||
|
@ -194,29 +194,29 @@ tooltip label {
|
|||
font-weight: bold;
|
||||
font-size: 24px;
|
||||
margin: 0px 8px 0px 8px;
|
||||
}
|
||||
}
|
||||
|
||||
.launcher_module {
|
||||
background-color: rgba(00, 00, 00, 0.0);
|
||||
}
|
||||
}
|
||||
|
||||
.mem_module {
|
||||
background-color: rgba(00, 00, 00, 0.0);
|
||||
border-radius: 16px;
|
||||
margin: 0px 5px 0px 0px;
|
||||
}
|
||||
}
|
||||
|
||||
.bat_module {
|
||||
background-color: rgba(00, 00, 00, 0.0);
|
||||
border-radius: 16px;
|
||||
margin: 0px 0px 0px 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.cpu_module {
|
||||
background-color: rgba(00, 00, 00, 0.0);
|
||||
border-radius: 16px;
|
||||
margin: 0px 5px 0px 5px;
|
||||
}
|
||||
margin: 0px 10px 0px 5px;
|
||||
}
|
||||
|
||||
.works {
|
||||
font-size: 22px;
|
||||
|
@ -258,43 +258,43 @@ tooltip label {
|
|||
font-weight: normal;
|
||||
border-radius: 25px;
|
||||
|
||||
.cal-in {
|
||||
padding: 10px 10px 10px 10px;
|
||||
color: $white;
|
||||
.cal-in {
|
||||
padding: 10px 10px 10px 10px;
|
||||
color: $white;
|
||||
|
||||
.cal {
|
||||
&.highlight {
|
||||
padding: 20px;
|
||||
}
|
||||
padding: 10px 10px 10px 10px;
|
||||
margin-left: 10px;
|
||||
.cal {
|
||||
&.highlight {
|
||||
padding: 20px;
|
||||
}
|
||||
padding: 10px 10px 10px 10px;
|
||||
margin-left: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
calender {
|
||||
color: $blue;
|
||||
}
|
||||
calendar:selected {
|
||||
color: $blue;
|
||||
color: $blue;
|
||||
}
|
||||
|
||||
calendar.header {
|
||||
color: $blue;
|
||||
font-weight: bold;
|
||||
color: $blue;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
calendar.button {
|
||||
color: $green;
|
||||
color: $green;
|
||||
}
|
||||
|
||||
calendar.highlight {
|
||||
color: $blue;
|
||||
font-weight: bold;
|
||||
color: $blue;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
calendar:indeterminate {
|
||||
color: $black;
|
||||
color: $black;
|
||||
}
|
||||
|
||||
|
||||
|
@ -339,13 +339,13 @@ color: $black;
|
|||
color: $orange;
|
||||
}
|
||||
.sys_bat_box {
|
||||
border-radius: 16px;
|
||||
border-radius: 16px;
|
||||
margin: 15px 10px 10px 20px;
|
||||
}
|
||||
}
|
||||
.sys_mem_box {
|
||||
border-radius: 16px;
|
||||
border-radius: 16px;
|
||||
margin: 10px 10px 15px 20px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.app-name {
|
||||
|
@ -368,7 +368,7 @@ color: $black;
|
|||
}
|
||||
|
||||
.launcher-icon {
|
||||
margin : 9px 0px 10px 15px;
|
||||
margin : 9px 0px 10px 15px;
|
||||
}
|
||||
|
||||
.audio-box {
|
||||
|
@ -386,10 +386,10 @@ color: $black;
|
|||
}
|
||||
|
||||
.speaker_text {
|
||||
color: $base0D;
|
||||
font-size : 26px;
|
||||
font-weight : bold;
|
||||
margin: 20px 0px 0px 0px;
|
||||
color: $base0D;
|
||||
font-size : 26px;
|
||||
font-weight : bold;
|
||||
margin: 20px 0px 0px 0px;
|
||||
}
|
||||
|
||||
.speaker_bar scale trough highlight {
|
||||
|
@ -411,81 +411,81 @@ color: $black;
|
|||
|
||||
|
||||
.mic_icon {
|
||||
background-size: cover;
|
||||
background-size: cover;
|
||||
background-image: url('images/mic.png');
|
||||
background-position: center;
|
||||
min-height: 70px;
|
||||
min-width: 75px;
|
||||
margin: 5px 20px 20px 20px;
|
||||
border-radius: 12px;
|
||||
background-position: center;
|
||||
min-height: 70px;
|
||||
min-width: 75px;
|
||||
margin: 5px 20px 20px 20px;
|
||||
border-radius: 12px;
|
||||
}
|
||||
|
||||
.mic_text {
|
||||
color: $blue;
|
||||
font-size : 26px;
|
||||
font-weight : bold;
|
||||
margin: 0px 0px 0px 0px;
|
||||
color: $blue;
|
||||
font-size : 26px;
|
||||
font-weight : bold;
|
||||
margin: 0px 0px 0px 0px;
|
||||
}
|
||||
|
||||
.mic_bar scale trough highlight {
|
||||
all: unset;
|
||||
all: unset;
|
||||
background-image: linear-gradient(to right, #afcee0 30%, #92B6F4 50%, #77a5bf 100% *50);
|
||||
border-radius: 24px;
|
||||
border-radius: 24px;
|
||||
}
|
||||
.mic_bar scale trough {
|
||||
all: unset;
|
||||
all: unset;
|
||||
box-shadow: 0 6px 5px 2px $shadow;
|
||||
background-color: $widget-background;
|
||||
border-radius: 24px;
|
||||
min-height: 13px;
|
||||
min-width: 120px;
|
||||
margin : 0px 0px 20px 0px;
|
||||
background-color: $widget-background;
|
||||
border-radius: 24px;
|
||||
min-height: 13px;
|
||||
min-width: 120px;
|
||||
margin : 0px 0px 20px 0px;
|
||||
}
|
||||
|
||||
.audio_sep {
|
||||
color: $black;
|
||||
font-size: 18;
|
||||
margin : 0px 0px 0px 0px;
|
||||
margin : 0px 0px 0px 0px;
|
||||
}
|
||||
|
||||
// Music
|
||||
.music-player {
|
||||
all: unset;
|
||||
all: unset;
|
||||
background-color: $widget-background;
|
||||
padding: 0px 25px 0px 17px;
|
||||
border-radius: 12px;
|
||||
padding: 0px 25px 0px 17px;
|
||||
border-radius: 12px;
|
||||
box-shadow: 0px 0px 6px 6px $shadow;}
|
||||
|
||||
.album_art {
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
border-radius: 12px;
|
||||
margin: 2rem 1rem 1.5rem 1rem;
|
||||
padding: 4rem;}
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
border-radius: 12px;
|
||||
margin: 2rem 1rem 1.5rem 1rem;
|
||||
padding: 4rem;}
|
||||
|
||||
.song {
|
||||
font-family: JetBrainsMono Nerd Font Mono;
|
||||
font-weight: bold;
|
||||
color: $white;
|
||||
font-size : 1.2em;
|
||||
font-family: JetBrainsMono Nerd Font Mono;
|
||||
font-weight: bold;
|
||||
color: $white;
|
||||
font-size : 1.2em;
|
||||
}
|
||||
.artist {
|
||||
font-family: JetBrainsMono Nerd Font;
|
||||
font-style: italic;
|
||||
font-size: 1.1em;
|
||||
color: $blue;
|
||||
margin-top: -5px;
|
||||
font-family: JetBrainsMono Nerd Font;
|
||||
font-style: italic;
|
||||
font-size: 1.1em;
|
||||
color: $blue;
|
||||
margin-top: -5px;
|
||||
}
|
||||
.btn_prev, .btn_play, .btn_next {
|
||||
font-family: JetBrainsMono Nerd Font Mono;
|
||||
color: $purple;
|
||||
font-size: 25px;
|
||||
font-family: JetBrainsMono Nerd Font Mono;
|
||||
color: $purple;
|
||||
font-size: 25px;
|
||||
}
|
||||
|
||||
.metric-player scale trough highlight {
|
||||
all: unset;
|
||||
border-radius: 10px;
|
||||
background-color: $blue;
|
||||
all: unset;
|
||||
border-radius: 10px;
|
||||
background-color: $blue;
|
||||
}
|
||||
|
||||
// weather
|
||||
|
@ -498,31 +498,31 @@ font-family: JetBrainsMono Nerd Font Mono;
|
|||
|
||||
.iconweather {
|
||||
font-family: JetBrainsMono Nerd Font;
|
||||
font-size : 44px;
|
||||
font-weight : normal;
|
||||
margin : 0px -5px 0px 20px;
|
||||
font-size : 44px;
|
||||
font-weight : normal;
|
||||
margin : 0px -5px 0px 20px;
|
||||
}
|
||||
|
||||
.label_temp {
|
||||
color : $base0D;
|
||||
font-size : 35px;
|
||||
font-weight : bold;
|
||||
margin : 0px 0px 0px 0px;
|
||||
font-family: Furamono Nerd Font;
|
||||
color : $base0D;
|
||||
font-size : 35px;
|
||||
font-weight : bold;
|
||||
margin : 0px 0px 0px 0px;
|
||||
font-family: Furamono Nerd Font;
|
||||
|
||||
}
|
||||
|
||||
.label_stat {
|
||||
color : $base0D;
|
||||
font-size : 38px;
|
||||
font-weight : bold;
|
||||
color : $base0D;
|
||||
font-size : 38px;
|
||||
font-weight : bold;
|
||||
}
|
||||
|
||||
.label_quote {
|
||||
color : $base0D;
|
||||
font-size : 18px;
|
||||
padding-bottom: 10px;
|
||||
font-weight : normal;
|
||||
color : $base0D;
|
||||
font-size : 18px;
|
||||
padding-bottom: 10px;
|
||||
font-weight : normal;
|
||||
}
|
||||
|
||||
.date {
|
||||
|
@ -551,13 +551,13 @@ font-family: JetBrainsMono Nerd Font Mono;
|
|||
|
||||
|
||||
scale trough {
|
||||
all: unset;
|
||||
background-color: $widget-background;
|
||||
box-shadow: 0 2px 3px 2px $shadow;
|
||||
border-radius: 16px;
|
||||
min-height: 10px;
|
||||
min-width: 70px;
|
||||
margin: 0px 5px 0px 10px;
|
||||
all: unset;
|
||||
background-color: $widget-background;
|
||||
box-shadow: 0 2px 3px 2px $shadow;
|
||||
border-radius: 16px;
|
||||
min-height: 10px;
|
||||
min-width: 70px;
|
||||
margin: 0px 5px 0px 10px;
|
||||
}
|
||||
|
||||
.scale highlight {
|
||||
|
@ -580,28 +580,28 @@ scale trough {
|
|||
box-shadow: 0px 0px 6px 6px rgb(0, 0, 0, .4);}
|
||||
|
||||
.poweroff, .reboot, .firmware, .exit, .restart {
|
||||
margin: 0px 16px 0px 16px;
|
||||
padding: 2px 15px 2px 9px;
|
||||
font-family: mononoki Nerd Font;
|
||||
border-radius: 25px;
|
||||
font-size: 24px;
|
||||
color: $black;
|
||||
margin: 0px 16px 0px 16px;
|
||||
padding: 2px 15px 2px 9px;
|
||||
font-family: mononoki Nerd Font;
|
||||
border-radius: 25px;
|
||||
font-size: 24px;
|
||||
color: $black;
|
||||
}
|
||||
|
||||
.poweroff {
|
||||
background-color: $red;
|
||||
background-color: $red;
|
||||
}
|
||||
.reboot {
|
||||
background-color: $green;
|
||||
background-color: $green;
|
||||
}
|
||||
.firmware {
|
||||
background-color: $orange;
|
||||
background-color: $orange;
|
||||
}
|
||||
.exit {
|
||||
background-color: $purple;
|
||||
background-color: $purple;
|
||||
}
|
||||
.restart {
|
||||
background-color: $blue;
|
||||
background-color: $blue;
|
||||
}
|
||||
|
||||
.fetch {
|
||||
|
@ -613,33 +613,33 @@ scale trough {
|
|||
box-shadow: 0px 0px 6px 6px rgb(0, 0, 0, .4);}
|
||||
|
||||
.wm {
|
||||
font-family: "JetBrainsMono Nerd Font";
|
||||
font-weight: bold;
|
||||
color: $red;
|
||||
font-family: "JetBrainsMono Nerd Font";
|
||||
font-weight: bold;
|
||||
color: $red;
|
||||
}
|
||||
|
||||
.host {
|
||||
font-family: "JetBrainsMono Nerd Font";
|
||||
font-weight: bold;
|
||||
color: $purple;
|
||||
font-family: "JetBrainsMono Nerd Font";
|
||||
font-weight: bold;
|
||||
color: $purple;
|
||||
}
|
||||
|
||||
.uptime {
|
||||
font-family: "JetBrainsMono Nerd Font";
|
||||
font-weight: bold;
|
||||
color: $orange;
|
||||
font-family: "JetBrainsMono Nerd Font";
|
||||
font-weight: bold;
|
||||
color: $orange;
|
||||
}
|
||||
|
||||
.packages {
|
||||
font-family: "JetBrainsMono Nerd Font";
|
||||
font-weight: bold;
|
||||
color: $blue;
|
||||
font-family: "JetBrainsMono Nerd Font";
|
||||
font-weight: bold;
|
||||
color: $blue;
|
||||
}
|
||||
|
||||
.kernal {
|
||||
font-family: "JetBrainsMono Nerd Font";
|
||||
font-weight: bold;
|
||||
color: $green;
|
||||
font-family: "JetBrainsMono Nerd Font";
|
||||
font-weight: bold;
|
||||
color: $green;
|
||||
}
|
||||
|
||||
.notification {
|
||||
|
@ -715,3 +715,31 @@ scale trough {
|
|||
.battery-label {
|
||||
margin: 20px 50px 10px 40px;
|
||||
}
|
||||
|
||||
.volume-container {
|
||||
background-color: $darktransparent;
|
||||
border-radius: 16px;
|
||||
box-shadow: 2px 2px 3px 3px #101010;
|
||||
margin: 8px 18px 13px 18px;
|
||||
}
|
||||
|
||||
.volume-value trough highlight {
|
||||
background-color: $base0B;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
.volume-value {
|
||||
margin-bottom: 0px;
|
||||
margin-right: 0px;
|
||||
min-width: 250px;
|
||||
}
|
||||
|
||||
.volume-label {
|
||||
margin: 10px 20px 10px 5px;
|
||||
}
|
||||
.volume-icon {
|
||||
font-size: 18;
|
||||
color: $base0B;
|
||||
margin: 0px 5px 0px 20px;
|
||||
}
|
||||
|
||||
|
|
|
@ -3,18 +3,19 @@
|
|||
(include "sidebar.yuck")
|
||||
(include "notifications.yuck")
|
||||
(include "battery.yuck")
|
||||
(include "volume.yuck")
|
||||
|
||||
(defpoll clock_time :interval "5s" "date '+\%l:\%M \%p'")
|
||||
(defpoll clock_date :interval "1h" "date '+%b %d, %Y'")
|
||||
(defpoll calendar_day :interval "2h" "date '+%d'")
|
||||
(defpoll calendar_year :interval "2h" "date '+%Y'")
|
||||
(defpoll volume_percent :interval "1s" "~/bin/getvol | cut -c 1-2")
|
||||
(defpoll mic_percent :interval "3s" "pamixer --get-volume --default-source")
|
||||
(defpoll brightness_percent :interval "5s" "scripts/bright")
|
||||
(defpoll COL_WLAN :interval "1m" "scripts/wifi --COL")
|
||||
(defpoll ESSID_WLAN :interval "1m" "scripts/wifi --ESSID")
|
||||
(defpoll WLAN_ICON :interval "1m" "scripts/wifi --ICON")
|
||||
(defpoll HOST :interval "1h" "hostname")
|
||||
(deflisten volume_percent :interval "0.5s" "tail -F /tmp/vol")
|
||||
(deflisten workspace "scripts/workspace")
|
||||
(deflisten appname "scripts/appname")
|
||||
|
||||
|
@ -99,7 +100,7 @@
|
|||
:value volume_percent
|
||||
:orientation "h"
|
||||
:tooltip "${volume_percent}%"
|
||||
:max 100
|
||||
:max 150
|
||||
:min 0
|
||||
:onchange "pamixer --set-volume {}" )
|
||||
(button
|
||||
|
|
32
eww/volume.yuck
Normal file
32
eww/volume.yuck
Normal file
|
@ -0,0 +1,32 @@
|
|||
(defwindow volume
|
||||
:geometry (geometry :x "0px"
|
||||
:y "40px"
|
||||
:anchor "top center")
|
||||
:stacking "fg"
|
||||
:monitor "0"
|
||||
(volshow))
|
||||
|
||||
(defwidget volshow []
|
||||
(box
|
||||
:class "volume-container"
|
||||
:orientation "h"
|
||||
:space-evenly "false"
|
||||
:spacing 5
|
||||
(button
|
||||
:class "volume-icon"
|
||||
:valign "center"
|
||||
:halign "center"
|
||||
:onclick "" "墳")
|
||||
(scale
|
||||
:class "volume-value"
|
||||
:value {volume_percent}
|
||||
:valign "center"
|
||||
:halign "start"
|
||||
:orientation "h"
|
||||
:max 150
|
||||
:min 0)
|
||||
(label
|
||||
:class "volume-label"
|
||||
:halign "start"
|
||||
:valign "center"
|
||||
:text "${volume_percent}%")))
|
|
@ -74,6 +74,7 @@ the close button is positioned to the far right */
|
|||
/* Tab close button */
|
||||
.tab-close-button {
|
||||
opacity: 1 !important;
|
||||
min-width: 10px;
|
||||
}
|
||||
|
||||
#tabs-newtab-button {
|
||||
|
@ -82,23 +83,30 @@ the close button is positioned to the far right */
|
|||
|
||||
#tabbrowser-tabs {
|
||||
max-height: 30px !important;
|
||||
margin-top: 0px !important;
|
||||
margin-bottom: -5px !important;
|
||||
padding-bottom: 0px !important;
|
||||
max-height: 10px !important;
|
||||
}
|
||||
|
||||
#TabsToolbar{
|
||||
margin-top: -0px !important;
|
||||
margin-top: 8px !important;
|
||||
margin-bottom: -1px !important;
|
||||
padding-bottom: opx !important;
|
||||
max-height: 30px;
|
||||
}
|
||||
|
||||
|
||||
.tabbrowser-tab, .tab-background, .tab-stack {
|
||||
margin-top: 0px !important;
|
||||
margin-bottom: 0px !important;
|
||||
max-height: 10px !important;
|
||||
border: none !important;
|
||||
border-radius: 1px !important;
|
||||
}
|
||||
|
||||
.tab-background {
|
||||
margin-top: -5px !important;
|
||||
margin-top: 0px !important;
|
||||
max-height: 10px !important;
|
||||
}
|
||||
|
||||
|
@ -114,6 +122,15 @@ the close button is positioned to the far right */
|
|||
padding: 0px !important;
|
||||
}
|
||||
|
||||
.tab-close-button {
|
||||
margin-top: 5px;
|
||||
min-width: 25px !important;
|
||||
}
|
||||
|
||||
#navigator-toolbox {
|
||||
padding: 0px !important;
|
||||
}
|
||||
|
||||
/* Autohide Navbar */
|
||||
|
||||
#nav-bar:not([customizing="true"]):not([inFullscreen]) {
|
||||
|
@ -146,7 +163,7 @@ the close button is positioned to the far right */
|
|||
|
||||
/* make urlbar rounded */
|
||||
#urlbar{
|
||||
margin-top: 39px !important;
|
||||
margin-top: 17px !important;
|
||||
padding-right: 10px !important;
|
||||
padding-left: 10px !important;
|
||||
}
|
||||
|
@ -172,11 +189,11 @@ the close button is positioned to the far right */
|
|||
}
|
||||
|
||||
#nav-bar-customization-target{
|
||||
margin-top: -22px;
|
||||
margin-top: 0px;
|
||||
}
|
||||
#nav-bar-overflow-button{
|
||||
margin-top: -22px !important;
|
||||
margin-top: 0px !important;
|
||||
}
|
||||
#PanelUI-button{
|
||||
margin-top: -22px !important;
|
||||
margin-top: 0px !important;
|
||||
}
|
||||
|
|
60
flake.lock
60
flake.lock
|
@ -30,11 +30,11 @@
|
|||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1671099536,
|
||||
"narHash": "sha256-e0VCSDEg1NCfqf17A36pccksqYF+m1NCcc0p+cOP89M=",
|
||||
"lastModified": 1672132398,
|
||||
"narHash": "sha256-eiHIeVAv0/RioqX3N8FzMBNiDuj/PhwrxYbJbT+Yuu4=",
|
||||
"owner": "nix-community",
|
||||
"repo": "emacs-overlay",
|
||||
"rev": "0e1a47eadd23dc5669f056f28de606c9d00a1c29",
|
||||
"rev": "ebbb22510930b5153de22357518ebd8ce7ed93b3",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -205,11 +205,11 @@
|
|||
"utils": "utils"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1670970889,
|
||||
"narHash": "sha256-TWJo3/X3Q3r+HeX16QN4FE6ddBpGtAboymSEF+4Nnc0=",
|
||||
"lastModified": 1671966569,
|
||||
"narHash": "sha256-jbLgfSnmLchARBNFRvCic63CFQ9LAyvlXnBpc2kwjQc=",
|
||||
"owner": "nix-community",
|
||||
"repo": "home-manager",
|
||||
"rev": "e412025fffdcd6219ddd21c65d9a1b90005ce508",
|
||||
"rev": "c55fa26ce05fee8e063db22918d05a73d430b2ea",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -229,11 +229,11 @@
|
|||
"xdph": "xdph"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1671043368,
|
||||
"narHash": "sha256-mV63L9g/qQ37eMftY05tTCk2OWcXrkmt7ep9uDClhqI=",
|
||||
"lastModified": 1672057622,
|
||||
"narHash": "sha256-UCA9ObYOGpZh5cZi9HO0p35RJVD1i2DT/Djgyx1dOPM=",
|
||||
"owner": "hyprwm",
|
||||
"repo": "Hyprland",
|
||||
"rev": "b89a07596e9f1caa353caec13cb328a98b39944c",
|
||||
"rev": "545e63d1dd14c76e9faad7839ad255dc9ead4cd8",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -302,11 +302,11 @@
|
|||
"nixpkgs-unstable": "nixpkgs-unstable"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1669646413,
|
||||
"narHash": "sha256-25ZNLtNspU60+HNzuAHgCbkOA4LofC4hS/b8JjED0Wc=",
|
||||
"lastModified": 1671285162,
|
||||
"narHash": "sha256-Qd751zQXNUpMFnk8m9nRDf+stE2KhYUoDmCTbiOtXfw=",
|
||||
"owner": "fort-nix",
|
||||
"repo": "nix-bitcoin",
|
||||
"rev": "5cafafd02777919c10e559b5686237fdefe920c2",
|
||||
"rev": "932e4c93bcc75eddae5259574b7e49a399715df0",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -334,11 +334,11 @@
|
|||
},
|
||||
"nixpkgs-stable": {
|
||||
"locked": {
|
||||
"lastModified": 1670980281,
|
||||
"narHash": "sha256-g0t/SmQca/JBEd+3Ry1qFgDfDK8ME9AM6EP4YUl8/lo=",
|
||||
"lastModified": 1671813978,
|
||||
"narHash": "sha256-oo4we+9IO1D+QS1mOSNh08l9ABDPWLyqvNC0DD0QtZM=",
|
||||
"owner": "nixos",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "5cb48ea3c19ce2e5746a44d6b91847396bd28c1f",
|
||||
"rev": "79e63f30ed2ff36cd0d9c2f7dadae5925c1a65db",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -350,11 +350,11 @@
|
|||
},
|
||||
"nixpkgs-unstable": {
|
||||
"locked": {
|
||||
"lastModified": 1669535121,
|
||||
"narHash": "sha256-koZLM7oWVGrjyHnYDo7/w5qlmUn9UZUKSFNfmIjueE8=",
|
||||
"lastModified": 1670918062,
|
||||
"narHash": "sha256-iOhkyBYUU9Jfkk0lvI4ahpjyrTsLXj9uyJWwmjKg+gg=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "b45ec953794bb07922f0468152ad1ebaf8a084b3",
|
||||
"rev": "84575b0bd882be979516f4fecfe4d7c8de8f6a92",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -382,11 +382,11 @@
|
|||
},
|
||||
"nixpkgs_3": {
|
||||
"locked": {
|
||||
"lastModified": 1669418739,
|
||||
"narHash": "sha256-T86oFvcUIRwHWBWUt7WjaP4BP/3lDGbv5AppQSI1FkI=",
|
||||
"lastModified": 1670700605,
|
||||
"narHash": "sha256-5dlpATkcyITpdtMflhltuD+A3RNpsVI1Mb+dtKkll6Y=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "695b3515251873e0a7e2021add4bba643c56cde3",
|
||||
"rev": "7b9eeb856cbf976482fa8d1cb295ea03fb3e1277",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -398,11 +398,11 @@
|
|||
},
|
||||
"nixpkgs_4": {
|
||||
"locked": {
|
||||
"lastModified": 1670929434,
|
||||
"narHash": "sha256-n5UBO6XBV4h3TB7FYu2yAuNQMEYOrQyKeODUwKe06ow=",
|
||||
"lastModified": 1671983799,
|
||||
"narHash": "sha256-Z2Ro6hFPZHkBqkVXY5/aBUzxi5xizQGvuHQ9+T5B/ks=",
|
||||
"owner": "nixos",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "1710ed1f6f8ceb75cf7d1cf55ee0cc21760e1c7a",
|
||||
"rev": "fad51abd42ca17a60fc1d4cb9382e2d79ae31836",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -492,11 +492,11 @@
|
|||
"flake": false,
|
||||
"locked": {
|
||||
"host": "gitlab.freedesktop.org",
|
||||
"lastModified": 1669925104,
|
||||
"narHash": "sha256-xMHfW+/G9MieN/5tXHUA5/ztE8dkE093cNFTEUgcwxI=",
|
||||
"lastModified": 1671723353,
|
||||
"narHash": "sha256-G1jiI0SA7eiZusO+iJytErMRNbKbwqJJJGL+sNoBNoQ=",
|
||||
"owner": "wlroots",
|
||||
"repo": "wlroots",
|
||||
"rev": "c8eb24d30e18c165728b8788a10716611c3b633d",
|
||||
"rev": "b28a9afd4b0b86e9a66a40f6b44b69f59947b7d6",
|
||||
"type": "gitlab"
|
||||
},
|
||||
"original": {
|
||||
|
@ -515,11 +515,11 @@
|
|||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1670892912,
|
||||
"narHash": "sha256-HC1qHrGXivdzNlWuuWcxX/P7OkNrlLbhzaqLx0mslPA=",
|
||||
"lastModified": 1671837878,
|
||||
"narHash": "sha256-OmFDyktTc/l+3wHboHeFpAQgPt3r7jjqZf8MrwuUGMo=",
|
||||
"owner": "hyprwm",
|
||||
"repo": "xdg-desktop-portal-hyprland",
|
||||
"rev": "9fb4fae94b9bd80395c193dcaf6fdf740550cff1",
|
||||
"rev": "e47f4cec698080768821b271510985ab94a37e91",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
|
28
mpv/script-opts/thumbfast.conf
Normal file
28
mpv/script-opts/thumbfast.conf
Normal file
|
@ -0,0 +1,28 @@
|
|||
# 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
|
||||
|
||||
# Overlay id
|
||||
overlay_id=42
|
||||
|
||||
# Spawn thumbnailer on file load for faster initial thumbnails
|
||||
spawn_first=no
|
||||
|
||||
# Enable on network playback
|
||||
network=no
|
||||
|
||||
# Enable on audio playback
|
||||
audio=no
|
||||
|
||||
# Enable hardware decoding
|
||||
hwdec=no
|
||||
|
||||
# Windows only: use native Windows API to write to pipe (requires LuaJIT)
|
||||
direct_io=no
|
File diff suppressed because it is too large
Load diff
712
mpv/scripts/thumbfast.lua
Normal file
712
mpv/scripts/thumbfast.lua
Normal file
|
@ -0,0 +1,712 @@
|
|||
-- thumbfast.lua
|
||||
--
|
||||
-- High-performance on-the-fly thumbnailer
|
||||
--
|
||||
-- Built for easy integration in third-party UIs.
|
||||
|
||||
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,
|
||||
|
||||
-- Overlay id
|
||||
overlay_id = 42,
|
||||
|
||||
-- Spawn thumbnailer on file load for faster initial thumbnails
|
||||
spawn_first = false,
|
||||
|
||||
-- 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
|
||||
}
|
||||
|
||||
mp.utils = require "mp.utils"
|
||||
mp.options = require "mp.options"
|
||||
mp.options.read_options(options, "thumbfast")
|
||||
|
||||
local pre_0_30_0 = mp.command_native_async == nil
|
||||
|
||||
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 spawned = false
|
||||
local network = false
|
||||
local disabled = false
|
||||
local spawn_waiting = 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 = filters_runtime
|
||||
for k,v in pairs(filters_reset) do filters_all[k] = v end
|
||||
|
||||
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 first_file = false
|
||||
|
||||
local function debounce(func, wait)
|
||||
func = type(func) == "function" and func or function() end
|
||||
wait = type(wait) == "number" and wait / 1000 or 0
|
||||
|
||||
local timer = nil
|
||||
local timer_end = function ()
|
||||
timer:kill()
|
||||
timer = nil
|
||||
func()
|
||||
end
|
||||
|
||||
return function ()
|
||||
if timer then
|
||||
timer:kill()
|
||||
end
|
||||
timer = mp.add_timeout(wait, timer_end)
|
||||
end
|
||||
end
|
||||
|
||||
local client_script = [=[
|
||||
#!/bin/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"] = "Mac",
|
||||
["mac"] = "Mac",
|
||||
["darwin"] = "Mac",
|
||||
|
||||
["^mingw"] = "Windows",
|
||||
["^cygwin"] = "Windows",
|
||||
|
||||
["bsd$"] = "Mac",
|
||||
["sunos"] = "Mac"
|
||||
}
|
||||
|
||||
-- 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 = get_os()
|
||||
|
||||
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 = "mpv"
|
||||
|
||||
if os_name == "Mac" and unique then
|
||||
mpv_path = string.gsub(subprocess({"ps", "-o", "comm=", "-p", tostring(unique)}).stdout, "[\n\r]", "")
|
||||
mpv_path = string.gsub(mpv_path, "/mpv%-bundle$", "/mpv")
|
||||
end
|
||||
|
||||
local function vf_string(filters, full)
|
||||
local vf = ""
|
||||
local vf_table = mp.get_property_native("vf")
|
||||
|
||||
if #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 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 = mp.get_property_number("video-out-params/dw")
|
||||
local height = mp.get_property_number("video-out-params/dh")
|
||||
if not width or not height then return end
|
||||
|
||||
local scale = mp.get_property_number("display-hidpi-scale", 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 = mp.get_property_number("video-out-params/par", 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 display_w, display_h = w, h
|
||||
local rotate = mp.get_property_number("video-params/rotate")
|
||||
|
||||
network = mp.get_property_bool("demuxer-via-network", false)
|
||||
local image = mp.get_property_native("current-tracks/video/image", false)
|
||||
local albumart = image and mp.get_property_native("current-tracks/video/albumart", false)
|
||||
disabled = (w or 0) == 0 or (h or 0) == 0 or
|
||||
has_vid == 0 or
|
||||
(network and not options.network) or
|
||||
(albumart and not options.audio) or
|
||||
(image and not albumart)
|
||||
|
||||
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
|
||||
|
||||
if rotate ~= nil and rotate % 180 == 90 then
|
||||
display_w, display_h = h, w
|
||||
end
|
||||
|
||||
local json, err = mp.utils.format_json({width=display_w, height=display_h, disabled=disabled, available=true, socket=options.socket, thumbnail=options.thumbnail, overlay_id=options.overlay_id})
|
||||
mp.commandv("script-message", "thumbfast-info", json)
|
||||
end
|
||||
|
||||
local function remove_thumbnail_files()
|
||||
os.remove(options.thumbnail)
|
||||
os.remove(options.thumbnail..".bgra")
|
||||
end
|
||||
|
||||
local function spawn(time)
|
||||
if disabled then return end
|
||||
|
||||
local path = mp.get_property("path")
|
||||
if path == nil then return end
|
||||
|
||||
local open_filename = mp.get_property("stream-open-filename")
|
||||
local ytdl = open_filename and network and path ~= open_filename
|
||||
if ytdl then
|
||||
path = open_filename
|
||||
end
|
||||
|
||||
remove_thumbnail_files()
|
||||
|
||||
local vid = mp.get_property_number("vid")
|
||||
has_vid = vid or 0
|
||||
|
||||
local args = {
|
||||
mpv_path, path, "--no-config", "--msg-level=all=no", "--idle", "--pause", "--keep-open=always", "--really-quiet", "--no-terminal",
|
||||
"--edition="..(mp.get_property_number("edition") or "auto"), "--vid="..(vid or "auto"), "--no-sub", "--no-audio",
|
||||
"--start="..time, "--hr-seek=no",
|
||||
"--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 == "Windows" then
|
||||
table.insert(args, "--input-ipc-server="..options.socket)
|
||||
else
|
||||
local client_script_path = options.socket..".run"
|
||||
local file = io.open(client_script_path, "w+")
|
||||
if file == nil then
|
||||
mp.msg.error("client script write failed")
|
||||
return
|
||||
else
|
||||
file:write(string.format(client_script, options.socket))
|
||||
file:close()
|
||||
subprocess({"chmod", "+x", client_script_path}, true)
|
||||
table.insert(args, "--script="..client_script_path)
|
||||
end
|
||||
end
|
||||
|
||||
spawned = true
|
||||
spawn_waiting = true
|
||||
|
||||
subprocess(args, true,
|
||||
function(success, result)
|
||||
if spawn_waiting and (success == false or result.status ~= 0) then
|
||||
mp.msg.error("mpv subprocess create failed")
|
||||
end
|
||||
spawned = false
|
||||
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 file = nil
|
||||
if os_name == "Windows" then
|
||||
file = io.open("\\\\.\\pipe\\"..options.socket, "r+")
|
||||
else
|
||||
file = io.open(options.socket, "r+")
|
||||
end
|
||||
if file ~= nil then
|
||||
file:seek("end")
|
||||
file:write(command.."\n")
|
||||
file:close()
|
||||
end
|
||||
end
|
||||
|
||||
local function draw(w, h, script)
|
||||
if not w or not show_thumbnail then return end
|
||||
local display_w, display_h = w, h
|
||||
if mp.get_property_number("video-params/rotate", 0) % 180 == 90 then
|
||||
display_w, display_h = h, w
|
||||
end
|
||||
|
||||
if x ~= nil then
|
||||
mp.command_native({"overlay-add", options.overlay_id, x, y, options.thumbnail..".bgra", 0, "bgra", display_w, display_h, (4*display_w)})
|
||||
elseif script then
|
||||
local json, err = mp.utils.format_json({width=display_w, height=display_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 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(true)
|
||||
seek_period_counter = 1
|
||||
else
|
||||
if seek_period_counter == 2 then
|
||||
seek_timer:kill()
|
||||
seek()
|
||||
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(true)
|
||||
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
|
||||
if first_file then
|
||||
request_seek()
|
||||
first_file = false
|
||||
end
|
||||
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
|
||||
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 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 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 clear()
|
||||
file_timer:kill()
|
||||
seek_timer:kill()
|
||||
last_seek = 0
|
||||
show_thumbnail = false
|
||||
last_x = nil
|
||||
last_y = nil
|
||||
if script_name then return end
|
||||
mp.command_native({"overlay-remove", options.overlay_id})
|
||||
end
|
||||
|
||||
local function watch_changes()
|
||||
local old_w = effective_w
|
||||
local old_h = effective_h
|
||||
|
||||
calc_dimensions()
|
||||
|
||||
local vf_reset = vf_string(filters_reset)
|
||||
local rotate = mp.get_property_number("video-rotate", 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
|
||||
run("quit")
|
||||
clear()
|
||||
spawned = false
|
||||
spawn(last_seek_time or mp.get_property_number("time-pos", 0))
|
||||
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
|
||||
end
|
||||
|
||||
local watch_changes_debounce = debounce(watch_changes, 500)
|
||||
|
||||
local function sync_changes(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)
|
||||
watch_changes_debounce()
|
||||
end
|
||||
|
||||
local function file_load()
|
||||
clear()
|
||||
real_w, real_h = nil, nil
|
||||
last_real_w, last_real_h = nil, nil
|
||||
last_seek_time = nil
|
||||
if info_timer then
|
||||
info_timer:kill()
|
||||
info_timer = nil
|
||||
end
|
||||
|
||||
calc_dimensions()
|
||||
info(effective_w, effective_h)
|
||||
if disabled then return end
|
||||
|
||||
spawned = false
|
||||
if options.spawn_first then
|
||||
spawn(mp.get_property_number("time-pos", 0))
|
||||
first_file = true
|
||||
end
|
||||
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
|
||||
|
||||
mp.observe_property("display-hidpi-scale", "native", watch_changes)
|
||||
mp.observe_property("video-out-params", "native", watch_changes)
|
||||
mp.observe_property("vf", "native", watch_changes_debounce)
|
||||
mp.observe_property("vid", "native", sync_changes)
|
||||
mp.observe_property("edition", "native", sync_changes)
|
||||
|
||||
mp.register_script_message("thumb", thumb)
|
||||
mp.register_script_message("clear", clear)
|
||||
|
||||
mp.register_event("file-loaded", file_load)
|
||||
mp.register_event("shutdown", shutdown)
|
|
@ -1,7 +1,14 @@
|
|||
#!/bin/sh
|
||||
|
||||
touch /tmp/vol
|
||||
awesome-client "naughty.destroy_all_notifications()"
|
||||
pamixer --allow-boost -d 5
|
||||
pw-play /run/current-system/sw/share/sounds/freedesktop/stereo/audio-volume-change.oga
|
||||
volume=$(pulsemixer --get-volume | awk '{print $1}')
|
||||
notify-send $volume
|
||||
volume=$(pulsemixer --get-volume | awk '{print $1}' | cut -c 1-2)
|
||||
echo $volume >> /tmp/vol
|
||||
|
||||
eww open volume
|
||||
|
||||
sleep 3
|
||||
|
||||
eww close volume
|
||||
|
|
|
@ -1,7 +1,20 @@
|
|||
#!/bin/sh
|
||||
#!/usr/bin/env bash
|
||||
|
||||
awesome-client "naughty.destroy_all_notifications()"
|
||||
touch /tmp/vol
|
||||
touch /tmp/ewwvol
|
||||
echo on > /tmp/ewwvol
|
||||
pamixer --allow-boost -i 5
|
||||
pw-play /run/current-system/sw/share/sounds/freedesktop/stereo/audio-volume-change.oga
|
||||
volume=$(pulsemixer --get-volume | awk '{print $1}')
|
||||
notify-send $volume
|
||||
volume=$(pulsemixer --get-volume | awk '{print $1}' | cut -c 1-2)
|
||||
echo $volume >> /tmp/vol
|
||||
ewwvol=$(cat /tmp/ewwvol)
|
||||
|
||||
eww open volume
|
||||
|
||||
sleep 3
|
||||
|
||||
if [[ ewwvol == "on" ]]; then
|
||||
|
||||
fi
|
||||
|
||||
eww close volume
|
||||
|
|
|
@ -363,6 +363,7 @@
|
|||
lxappearance
|
||||
spotdl
|
||||
kdenlive
|
||||
minetest
|
||||
# natron
|
||||
digikam
|
||||
rubberband
|
||||
|
@ -546,6 +547,7 @@
|
|||
dired-rainbow
|
||||
diredfl
|
||||
dired-rsync
|
||||
fd-dired
|
||||
ledger-mode
|
||||
org-msg
|
||||
calfw
|
||||
|
|
|
@ -382,6 +382,7 @@
|
|||
lxappearance
|
||||
spotdl
|
||||
kdenlive
|
||||
minetest
|
||||
# natron
|
||||
digikam
|
||||
rubberband
|
||||
|
@ -533,6 +534,7 @@
|
|||
dired-rainbow
|
||||
diredfl
|
||||
dired-rsync
|
||||
fd-dired
|
||||
ledger-mode
|
||||
org-msg
|
||||
calfw
|
||||
|
|
|
@ -378,7 +378,6 @@
|
|||
|
||||
home.file.".config/mpv" = {
|
||||
source = ../mpv;
|
||||
recursive = true;
|
||||
};
|
||||
|
||||
home.file.".config/imv" = {
|
||||
|
|
Loading…
Reference in a new issue