diff --git a/resources/rssguard.qrc b/resources/rssguard.qrc index 4e0984fd8..551ec4d09 100644 --- a/resources/rssguard.qrc +++ b/resources/rssguard.qrc @@ -18,6 +18,9 @@ sounds/fanfare2.wav sounds/goodresult.wav + scripts/mpv/mpv.conf + scripts/mpv/input.conf + scripts/adblock/adblock-server.js scripts/readability/readabilize-article.js diff --git a/resources/scripts/mpv/input.conf b/resources/scripts/mpv/input.conf new file mode 100644 index 000000000..655224098 --- /dev/null +++ b/resources/scripts/mpv/input.conf @@ -0,0 +1,431 @@ +# Mouse +MOUSE_BTN0 ignore +MOUSE_BTN0_DBL cycle fullscreen +MOUSE_BTN2 cycle pause +#MOUSE_BTN3 ignore +#MOUSE_BTN4 ignore +#MOUSE_BTN5 ignore +#MOUSE_BTN6 ignore + +# Trackpad +AXIS_UP ignore +AXIS_DOWN ignore +AXIS_LEFT ignore +AXIS_RIGHT ignore + +# Arrow/navigation keys +RIGHT osd-msg-bar seek +5 relative+keyframes +LEFT osd-msg-bar seek -5 relative+keyframes +SHIFT+RIGHT osd-msg-bar seek +1 relative+exact +SHIFT+LEFT osd-msg-bar seek -1 relative+exact +CTRL+RIGHT frame-step ; show-text "Frame: ${estimated-frame-number} / ${estimated-frame-count}" +CTRL+LEFT frame-back-step ; show-text "Frame: ${estimated-frame-number} / ${estimated-frame-count}" + +UP osd-msg-bar seek +30 relative+keyframes +DOWN osd-msg-bar seek -30 relative+keyframes +SHIFT+UP osd-msg-bar seek +120 relative+keyframes +SHIFT+DOWN osd-msg-bar seek -120 relative+keyframes + +PGUP osd-msg-bar seek +600 relative+keyframes +PGDWN osd-msg-bar seek -600 relative+keyframes + +SHIFT+PGUP osd-msg-bar seek +1200 relative+keyframes +SHIFT+PGDWN osd-msg-bar seek +1200 relative+keyframes + +ALT+RIGHT sub-seek +1 ; show-text "Sub Seek +1" +ALT+LEFT sub-seek -1 ; show-text "Sub Seek -1" + +#ALT+RIGHT add video-pan-x -0.01 +#ALT+LEFT add video-pan-x +0.01 +#ALT+UP add video-pan-y +0.01 +#ALT+DOWN add video-pan-y -0.01 + +#META+RIGHT add video-zoom +0.05 +#META+LEFT add video-zoom -0.05 +#META+UP add video-zoom +0.05 +#META+DOWN add video-zoom -0.05 + +# ` [1] [2] [3] [4] [5] [6] [7] [8] [9] [0] - = +# ~ [!] @ # $ % ^ & * ( ) _ + + +1 add contrast -1 ; show-text "ContrastT: ${contrast}" +2 add contrast +1 ; show-text "ContrastT: ${contrast}" +3 add brightness -1 ; show-text "Brightness: ${brightness}" +4 add brightness +1 ; show-text "Brightness: ${brightness}" +5 add gamma -1 ; show-text "Gamma: ${gamma}" +6 add gamma +1 ; show-text "Gamma: ${gamma}" +7 add saturation -1 ; show-text "Saturation: ${saturation}" +8 add saturation +1 ; show-text "Saturation: ${saturation}" + +9 add volume -2 ; show-text "Volume: ${volume}" +0 add volume +2 ; show-text "Volume: ${volume}" + +! cycle ontop + +` ignore +~ ignore +# ignore +$ ignore +% ignore +^ ignore +& ignore +* ignore +§ ignore +± ignore + +# [q] [w] [e] [r] [t] [y] [u] [i] [o] [p] [ ] +# [Q] [W] E R [T] [Y] [U] [I] O [P] { } + +Q quit +# q script-binding auto_save_state/quit-watch-later-conditional + +w script-message osc-playlist +W playlist-shuffle +e playlist-prev ; show-text "${playlist-pos-1}/${playlist-count}" +E ignore + +r playlist-next ; show-text "${playlist-pos-1}/${playlist-count}" +R ignore + +t cycle-values sub-use-margins "yes" "no" +T cycle-values ass-force-margins "yes" "no" # does not work with :blend-subtitles +CTRL+t cycle-values blend-subtitles "yes" "video" "no" + +y cycle-values stretch-image-subs-to-screen "yes" "no" +Y cycle-values stretch-dvd-subs "yes" "no" + +u cycle-values hwdec "auto" "no" +U cycle-values vf "format=colorlevels=full" "format=colorlevels=auto" "format=colorlevels=limited" + +i script-binding stats/display-stats +I script-binding stats/display-stats-toggle +o cycle-values osd-level 3 1 +O ignore +p cycle-values video-rotate 90 180 270 0 +P cycle-values video-aspect "16:9" "4:3" "2.35:1" "16:10" + +[ ignore +] ignore +{ ignore +} ignore + +# [a] [s] [d] [f] [g] [h] [j] [k] [l] +# [A] [S] [D] [F] [G] [H] [J] [K] [L] + +a cycle audio # switch audio streams +A cycle-values af "lavfi=[dynaudnorm=f=200:g=5:r=0.1]" "" # dynamic range compression +CTRL+a script-binding auto_audio_device/toggle-switching # toggle automatic audio device switching + +s cycle sub # cycle through subtitles +S cycle sub-visibility +CTRL+s cycle secondary-sid + +d cycle-values window-scale "1.5" "2.0" "3.0" "0.5" "1.0" ; show-text "Scale: ${window-scale}" +D cycle edition +CTRL+d cycle video + +f cycle fullscreen ; show-text "Scale: ${window-scale}" +F vf clr "" ; show-text "Filters cleared" + +g cycle-values video-sync display-resample audio ; cycle-values interpolation yes no ; show-text "Interpolation: ${interpolation} (${tscale})" +G cycle-values tscale "linear" "catmull_rom" "mitchell" "bicubic" "oversample" ; show-text "Interpolation: ${interpolation} (${tscale})" +CTRL+g cycle-values interpolation no yes ; show-text "Interpolation: ${interpolation} (${tscale})" + +h cycle deinterlace +H script-binding autodeint + +j cycle deband +J vf toggle "lavfi=[hqdn3d=2.0]" + +K ignore + +l cycle-values loop-file yes no ; show-text "${?=loop-file==inf:Looping enabled (file)}${?=loop-file==no:Looping disabled (file)}" +L cycle-values loop-playlist yes no ; show-text "${?=loop-playlist==inf:Looping enabled}${?=loop-playlist==no:Looping disabled}" +CTRL+l ab-loop + +# [z] [x] [c] [v] [b] [n] [m] [,] [.] +# [Z] X C V [B] [N] [M] [<] [>] + +x script-message osc-chapterlist +X ignore +c script-message osc-playlist +C ignore +v script-message osc-tracklist +V ignore + +b add speed +0.05 +B add speed -0.05 +CTRL+b set speed 1.0 + +n add audio-delay +0.10 +N add audio-delay -0.10 +CTRL+n set audio-delay 0 + +m add sub-delay +0.10 +M add sub-delay -0.10 +CTRL+m set sub-delay 0 + +, add sub-scale -0.05 # decrease subtitle font size +< add sub-scale +0.05 # increase subtitle font size +. add sub-pos -1 # move subtitles up +> add sub-pos +1 # move subtitles down + +# Adjust timing so that next/prev subtitle is displayed now +/ sub-step +1 ; show-text "Sub Step +1 (timing adjustment)" +? sub-step -1 ; show-text "Sub Step -1 (timing adjustment)" + +# [esc] [space] [backspace] +# [tab] [enter] + +ESC cycle fullscreen +SPACE cycle pause +IDEOGRAPHIC_SPACE cycle pause +TAB cycle mute +ENTER show-progress + +BS revert-seek +SHIFT+BS set speed 1.0 ; set gamma 0 ; set brightness 0 ; set contrast 0 ; set saturation 0 ; set hue 0 ; show-text "Speed/Gamma/Brightness/Contrast/Saturation/Hue resetted" +ALT+BS set video-pan-x 0 ; set video-pan-y 0 ; show-text "Pan resetted" +META+BS set video-zoom 0 ; show-text "Zoom resetted" + +# [F1] F2 F3 F4 F5 F6 F7 [F8] [F9] [F10] [F11] [F12] + +F1 script-binding console/enable +F8 vf toggle "interpolation=yes,tscale=oversample" ; show-text "Toggled Realtime Motion Interpolation (native) [interpolation=yes,tscale=oversample]" # Soap-opera effect for frame smoothing +F9 apply-profile "upscale-lowres-using-GPU-shaders" ; show-text "Applied GPU upscaler shaders" +F10 cycle-values speed 0.8 0.6 0.4 0.2 1 # Slow speed +F11 cycle-values speed 1.2 1.4 1.6 1.8 2 1 # Faster speed +F12 af toggle "lavfi=[loudnorm=I=-22:TP=-1.5:LRA=2]" # Useful audio normalization for low-audio or whispering scenes (can cause annoying background noise amplification) + +# Numpad + +KP0 ignore +KP1 ignore +KP2 ignore +KP3 ignore +KP4 ignore +KP5 ignore +KP6 ignore +KP7 ignore +KP8 ignore +KP9 ignore +KP_DEC ignore +KP_ENTER ignore + +# Testing at 2023-11-21 09:19:09PM + +# Show Loaded Shaders (for dev testing) +` script-binding sview/shader-view + +# Show progress bar on MOUSE BUTTON 2 double-click +# MOUSE_BTN2_DBL show-progress + +# Seek using mouse wheel +# Quieter alternative for video playback seeking +# (Mechanical keyboard are common these days so this can mindful of other people +# living in the same house) +SHIFT+WHEEL_UP osd-msg-bar seek +120 relative+keyframes +SHIFT+WHEEL_DOWN osd-msg-bar seek -120 relative+keyframes +ALT+WHEEL_UP osd-msg-bar seek +30 relative+keyframes +ALT+WHEEL_DOWN osd-msg-bar seek -30 relative+keyframes +WHEEL_UP osd-msg-bar seek +1 relative+keyframes +WHEEL_DOWN osd-msg-bar seek -1 relative+keyframes +CTRL+WHEEL_UP frame-step +CTRL+WHEEL_DOWN frame-back-step + +# Seek using numbers +CTRL+1 osd-msg-bar seek -1 relative+exact +ALT+1 osd-msg-bar seek +1 relative+exact +CTRL+2 osd-msg-bar seek -2 relative+keyframes +ALT+2 osd-msg-bar seek +2 relative+keyframes +CTRL+3 osd-msg-bar seek -3 relative+keyframes +ALT+3 osd-msg-bar seek +3 relative+keyframes +CTRL+4 osd-msg-bar seek -4 relative+keyframes +ALT+4 osd-msg-bar seek +4 relative+keyframes +CTRL+5 osd-msg-bar seek -5 relative+keyframes +ALT+5 osd-msg-bar seek +5 relative+keyframes +CTRL+6 osd-msg-bar seek -6 relative+keyframes +ALT+6 osd-msg-bar seek +6 relative+keyframes + + +# 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 +#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 +#d cycle deinterlace # toggle 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) \ No newline at end of file diff --git a/resources/scripts/mpv/mpv.conf b/resources/scripts/mpv/mpv.conf new file mode 100644 index 000000000..468a3d755 --- /dev/null +++ b/resources/scripts/mpv/mpv.conf @@ -0,0 +1,3 @@ +volume=50 +osd-color=1.0/0.5/0.25 +hwdec=auto-safe \ No newline at end of file diff --git a/src/librssguard/core/messagefilter.cpp b/src/librssguard/core/messagefilter.cpp index 98ee2fb86..8ac23a0b8 100644 --- a/src/librssguard/core/messagefilter.cpp +++ b/src/librssguard/core/messagefilter.cpp @@ -9,7 +9,7 @@ MessageFilter::MessageFilter(int id, QObject* parent) : QObject(parent), m_id(id) {} MessageObject::FilteringAction MessageFilter::filterMessage(QJSEngine* engine) { - QJSValue filter_func = engine->evaluate(qApp->replaceDataUserDataFolderPlaceholder(m_script)); + QJSValue filter_func = engine->evaluate(qApp->replaceUserDataFolderPlaceholder(m_script)); if (filter_func.isError()) { QJSValue::ErrorType error = filter_func.errorType(); diff --git a/src/librssguard/gui/dialogs/formsettings.cpp b/src/librssguard/gui/dialogs/formsettings.cpp index bed5c7de2..eb9408df6 100644 --- a/src/librssguard/gui/dialogs/formsettings.cpp +++ b/src/librssguard/gui/dialogs/formsettings.cpp @@ -155,7 +155,6 @@ void FormSettings::addSettingsPanel(SettingsPanel* panel) { itm->setText(panel->title()); itm->setIcon(panel->icon()); - // m_ui.m_listSettings->addItem(itm); m_panels.append(panel); QScrollArea* scr = new QScrollArea(m_ui.m_stackedSettings); diff --git a/src/librssguard/gui/mediaplayer/libmpv/libmpvbackend.cpp b/src/librssguard/gui/mediaplayer/libmpv/libmpvbackend.cpp index 1751f04b0..2680b62a6 100644 --- a/src/librssguard/gui/mediaplayer/libmpv/libmpvbackend.cpp +++ b/src/librssguard/gui/mediaplayer/libmpv/libmpvbackend.cpp @@ -6,11 +6,13 @@ #include "definitions/definitions.h" #include "gui/mediaplayer/libmpv/qthelper.h" #include "miscellaneous/settings.h" +#include "miscellaneous/textfactory.h" #include #include #include +#include #include #include #include @@ -28,6 +30,9 @@ #define EVENT_CODE_IDLE 11 #define EVENT_CODE_STOP 12 +#define CONFIG_MAIN_NAME "mpv.conf" +#define CONFIG_INPUT_NAME "input.conf" + static void wakeup(void* ctx) { // This callback is invoked from any mpv thread (but possibly also // recursively from a thread that is calling the mpv API). Just notify @@ -70,34 +75,35 @@ LibMpvBackend::LibMpvBackend(Application* app, QWidget* parent) mpv_set_option(m_mpvHandle, "wid", MPV_FORMAT_INT64, &wid); - mpv_set_option_string(m_mpvHandle, "input-default-bindings", "yes"); mpv_set_option_string(m_mpvHandle, "msg-level", "all=v"); mpv_set_option_string(m_mpvHandle, "config", "yes"); mpv_set_option_string(m_mpvHandle, "hwdec", "auto"); mpv_set_option_string(m_mpvHandle, "osd-playing-msg", "${media-title}"); mpv_set_option_string(m_mpvHandle, "osc", "yes"); mpv_set_option_string(m_mpvHandle, "input-cursor", "yes"); - // mpv_set_option_string(m_mpvHandle, "keep-open", "no"); mpv_set_option_string(m_mpvHandle, "idle", "yes"); mpv_set_option_string(m_mpvHandle, "save-position-on-quit", "no"); mpv_set_option_string(m_mpvHandle, "no-resume-playback", "yes"); -#if !defined(NDEBUG) - mpv_set_option_string(m_mpvHandle, "terminal", "yes"); -#endif - + // + // NOTE: Just random options for testing here. + // + // mpv_set_option_string(m_mpvHandle, "keep-open", "no"); + // mpv_set_option_string(m_mpvHandle, "terminal", "yes"); // mpv_set_option_string(m_mpvHandle, "osd-italic", "yes"); // mpv_set_option_string(m_mpvHandle, "osd-color", "1.0/0.0/0.0"); - - // // mpv_set_option_string(m_mpvHandle, "watch-later-dir", "mpv"); - mpv_set_option_string(m_mpvHandle, "config-dir", "mpv"); // mpv_set_option_string(m_mpvHandle, "input-builtin-bindings", "no"); // mpv_set_option_string(m_mpvHandle, "input-test", "yes"); - // Enable keyboard input on the X11 window. For the messy details, see - // --input-vo-keyboard on the manpage. - // mpv_set_option_string(mpv, "input-vo-keyboard", "yes"); + if (!m_customConfigFolder.isEmpty()) { + QByteArray cfg_folder = QDir::toNativeSeparators(m_customConfigFolder).toLocal8Bit(); + + mpv_set_option_string(m_mpvHandle, "config-dir", cfg_folder.constData()); + } + else { + mpv_set_option_string(m_mpvHandle, "input-default-bindings", "yes"); + } // Observe some properties. mpv_observe_property(m_mpvHandle, EVENT_CODE_FS, "fullscreen", MPV_FORMAT_FLAG); @@ -134,7 +140,16 @@ void LibMpvBackend::destroyHandle() { } } -void LibMpvBackend::loadSettings() {} +void LibMpvBackend::loadSettings() { + if (m_app->settings()->value(GROUP(VideoPlayer), SETTING(VideoPlayer::MpvUseCustomConfigFolder)).toBool()) { + m_customConfigFolder = + m_app->replaceUserDataFolderPlaceholder(m_app->settings() + ->value(GROUP(VideoPlayer), SETTING(VideoPlayer::MpvCustomConfigFolder)) + .toString()); + + installCustomConfig(m_customConfigFolder); + } +} LibMpvBackend::~LibMpvBackend() { destroyHandle(); @@ -198,6 +213,10 @@ double LibMpvBackend::mpvDecodeDouble(void* data) const { return *(double*)data; } +QString LibMpvBackend::mpvEncodeKeyboardButton(int btn) const { + return QString((QChar)btn); +} + QString LibMpvBackend::errorToString(mpv_error error) const { switch (mpv_error(error)) { case mpv_error::MPV_ERROR_EVENT_QUEUE_FULL: @@ -455,16 +474,14 @@ bool LibMpvBackend::eventFilter(QObject* watched, QEvent* event) { mpv_command_async(m_mpvHandle, 0, args); } - if (event->type() == QEvent::Type::KeyPress) { + if (event->type() == QEvent::Type::KeyRelease) { // We catch all keypresses (even from surrounding widgets). QKeyEvent* key_event = dynamic_cast(event); - char txt = (char)key_event->key(); - char str[2]; + QString keys = + QKeySequence(key_event->key() | key_event->modifiers()).toString(QKeySequence::SequenceFormat::PortableText); + QByteArray byte_named_key = keys.toLocal8Bit(); - str[0] = txt; - str[1] = '\0'; - - const char* args[] = {"keypress", str, nullptr}; + const char* args[] = {"keypress", byte_named_key.constData(), nullptr}; mpv_command_async(m_mpvHandle, 0, args); event->accept(); @@ -563,6 +580,22 @@ int LibMpvBackend::duration() const { return out; } +void LibMpvBackend::installCustomConfig(const QString& directory) { + QDir().mkpath(directory); + QDir config_dir(directory); + + for (const QString& cfg_file : QStringList{QSL(CONFIG_MAIN_NAME), QSL(CONFIG_INPUT_NAME)}) { + if (!config_dir.exists(cfg_file)) { + qDebugNN << LOGSEC_MPV << "Copying sample" << QUOTE_W_SPACE(cfg_file) << "to" + << QUOTE_W_SPACE_DOT(config_dir.absolutePath()); + IOFactory::copyFile(QSL(":/scripts/mpv/%1").arg(cfg_file), config_dir.absoluteFilePath(cfg_file)); + } + else { + qDebugNN << LOGSEC_MPV << "Configuration file" << QUOTE_W_SPACE(cfg_file) << "already exists."; + } + } +} + void LibMpvBackend::setMuted(bool muted) { if (m_mpvHandle != nullptr) { const char* mtd = muted ? "yes" : "no"; diff --git a/src/librssguard/gui/mediaplayer/libmpv/libmpvbackend.h b/src/librssguard/gui/mediaplayer/libmpv/libmpvbackend.h index 7af3eabb1..dab226525 100644 --- a/src/librssguard/gui/mediaplayer/libmpv/libmpvbackend.h +++ b/src/librssguard/gui/mediaplayer/libmpv/libmpvbackend.h @@ -21,6 +21,8 @@ class LibMpvBackend : public PlayerBackend { virtual int position() const; virtual int duration() const; + static void installCustomConfig(const QString& directory); + public slots: virtual void setMuted(bool muted); virtual void playUrl(const QUrl& url); @@ -51,12 +53,14 @@ class LibMpvBackend : public PlayerBackend { bool mpvDecodeBool(void* data) const; int mpvDecodeInt(void* data) const; double mpvDecodeDouble(void* data) const; + QString mpvEncodeKeyboardButton(int btn) const; QString errorToString(mpv_error error) const; void destroyHandle(); void loadSettings(); private: + QString m_customConfigFolder; QWidget* m_mpvContainer; mpv_handle* m_mpvHandle; QUrl m_url; diff --git a/src/librssguard/gui/mediaplayer/mediaplayer.ui b/src/librssguard/gui/mediaplayer/mediaplayer.ui index 446eb5f0f..cd6824d9d 100644 --- a/src/librssguard/gui/mediaplayer/mediaplayer.ui +++ b/src/librssguard/gui/mediaplayer/mediaplayer.ui @@ -47,7 +47,7 @@ 9 - 9 + 0 9 diff --git a/src/librssguard/gui/settings/settingsmediaplayer.cpp b/src/librssguard/gui/settings/settingsmediaplayer.cpp index c9f9377b7..5529078ce 100644 --- a/src/librssguard/gui/settings/settingsmediaplayer.cpp +++ b/src/librssguard/gui/settings/settingsmediaplayer.cpp @@ -65,7 +65,9 @@ void SettingsMediaPlayer::saveSettings() { m_ui.m_gbMpvCustomConfigFolder->isChecked()); settings()->setValue(GROUP(VideoPlayer), VideoPlayer::MpvCustomConfigFolder, m_ui.m_txtMpvConfigFolder->text()); - // LibMpvBackend::installCustomConfig() + if (m_ui.m_gbMpvCustomConfigFolder->isChecked()) { + LibMpvBackend::installCustomConfig(m_ui.m_txtMpvConfigFolder->text()); + } #elif defined(ENABLE_MEDIAPLAYER_QTMULTIMEDIA) #else diff --git a/src/librssguard/gui/settings/settingsnodejs.cpp b/src/librssguard/gui/settings/settingsnodejs.cpp index f34aadbff..dfa301ef0 100644 --- a/src/librssguard/gui/settings/settingsnodejs.cpp +++ b/src/librssguard/gui/settings/settingsnodejs.cpp @@ -71,7 +71,7 @@ void SettingsNodejs::changeFileFolder(LineEditWithStatus* tb, bool directory_sel d.setNameFilter(file_filter); } - QString current = qApp->replaceDataUserDataFolderPlaceholder(tb->lineEdit()->text()); + QString current = qApp->replaceUserDataFolderPlaceholder(tb->lineEdit()->text()); d.selectFile(current); @@ -128,7 +128,7 @@ void SettingsNodejs::testNpm() { } void SettingsNodejs::testPackageFolder() { - QString folder = qApp->replaceDataUserDataFolderPlaceholder(m_ui.m_tbPackageFolder->lineEdit()->text()); + QString folder = qApp->replaceUserDataFolderPlaceholder(m_ui.m_tbPackageFolder->lineEdit()->text()); const auto fi = QFileInfo(folder); const auto is_file = fi.isFile() && fi.exists(); diff --git a/src/librssguard/miscellaneous/application.cpp b/src/librssguard/miscellaneous/application.cpp index 7997b706c..a2244926c 100644 --- a/src/librssguard/miscellaneous/application.cpp +++ b/src/librssguard/miscellaneous/application.cpp @@ -539,13 +539,13 @@ QString Application::cacheFolder() { #endif } -QString Application::replaceDataUserDataFolderPlaceholder(QString text) const { +QString Application::replaceUserDataFolderPlaceholder(QString text) const { auto user_data_folder = qApp->userDataFolder(); return text.replace(QSL(USER_DATA_PLACEHOLDER), user_data_folder); } -QStringList Application::replaceDataUserDataFolderPlaceholder(QStringList texts) const { +QStringList Application::replaceUserDataFolderPlaceholder(QStringList texts) const { auto user_data_folder = qApp->userDataFolder(); return texts.replaceInStrings(QSL(USER_DATA_PLACEHOLDER), user_data_folder); diff --git a/src/librssguard/miscellaneous/application.h b/src/librssguard/miscellaneous/application.h index 49c14a07a..a9b275c65 100644 --- a/src/librssguard/miscellaneous/application.h +++ b/src/librssguard/miscellaneous/application.h @@ -155,8 +155,8 @@ class RSSGUARD_DLLSPEC Application : public SingleApplication { int customAdblockPort() const; - QString replaceDataUserDataFolderPlaceholder(QString text) const; - QStringList replaceDataUserDataFolderPlaceholder(QStringList texts) const; + QString replaceUserDataFolderPlaceholder(QString text) const; + QStringList replaceUserDataFolderPlaceholder(QStringList texts) const; void setMainForm(FormMain* main_form); diff --git a/src/librssguard/miscellaneous/nodejs.cpp b/src/librssguard/miscellaneous/nodejs.cpp index e025ffd8a..c6291d54c 100644 --- a/src/librssguard/miscellaneous/nodejs.cpp +++ b/src/librssguard/miscellaneous/nodejs.cpp @@ -53,7 +53,7 @@ QString NodeJs::packageFolder() const { } QString NodeJs::processedPackageFolder() const { - QString path = qApp->replaceDataUserDataFolderPlaceholder(packageFolder()); + QString path = qApp->replaceUserDataFolderPlaceholder(packageFolder()); if (!QDir().mkpath(path)) { qCriticalNN << LOGSEC_NODEJS << "Failed to create package folder structure" << QUOTE_W_SPACE_DOT(path); diff --git a/src/librssguard/miscellaneous/notification.cpp b/src/librssguard/miscellaneous/notification.cpp index d2d0fbd58..052652d00 100644 --- a/src/librssguard/miscellaneous/notification.cpp +++ b/src/librssguard/miscellaneous/notification.cpp @@ -55,7 +55,7 @@ void Notification::playSound(Application* app) const { play ->setSource(QUrl:: fromLocalFile(QDir::toNativeSeparators(app - ->replaceDataUserDataFolderPlaceholder(m_soundPath)))); + ->replaceUserDataFolderPlaceholder(m_soundPath)))); } play->setVolume(fractionalVolume()); @@ -85,7 +85,7 @@ void Notification::playSound(Application* app) const { play ->setSource(QUrl:: fromLocalFile(QDir::toNativeSeparators(app - ->replaceDataUserDataFolderPlaceholder(m_soundPath)))); + ->replaceUserDataFolderPlaceholder(m_soundPath)))); } play->audioOutput()->setVolume(fractionalVolume()); @@ -102,7 +102,7 @@ void Notification::playSound(Application* app) const { } else { play->setMedia(QMediaContent( - QUrl::fromLocalFile(QDir::toNativeSeparators(app->replaceDataUserDataFolderPlaceholder(m_soundPath))))); + QUrl::fromLocalFile(QDir::toNativeSeparators(app->replaceUserDataFolderPlaceholder(m_soundPath))))); } play->setVolume(m_volume); diff --git a/src/librssguard/services/standard/standardfeed.cpp b/src/librssguard/services/standard/standardfeed.cpp index 26d0bcde8..a96c61f96 100644 --- a/src/librssguard/services/standard/standardfeed.cpp +++ b/src/librssguard/services/standard/standardfeed.cpp @@ -403,7 +403,7 @@ void StandardFeed::setEncoding(const QString& encoding) { QStringList StandardFeed::prepareExecutionLine(const QString& execution_line) { auto args = TextFactory::tokenizeProcessArguments(execution_line); - return qApp->replaceDataUserDataFolderPlaceholder(args); + return qApp->replaceUserDataFolderPlaceholder(args); } QByteArray StandardFeed::runScriptProcess(const QStringList& cmd_args,