Gentoo Forums
Gentoo Forums
Gentoo Forums
Quick Search: in
HOWTO: Deactivate xscreensaver while watching online videos
View unanswered posts
View posts from last 24 hours

 
Reply to topic    Gentoo Forums Forum Index Documentation, Tips & Tricks
View previous topic :: View next topic  
Author Message
VinzC
Advocate
Advocate


Joined: 17 Apr 2004
Posts: 4862
Location: Dark side of the mood

PostPosted: Sun Jun 26, 2016 9:33 pm    Post subject: HOWTO: Deactivate xscreensaver while watching online videos Reply with quote

Hi all. This is a sequel from a thread I posted a while ago. I came out with this script today and I have just tested it while watching videos on Youtube with Firefox. The script can be updated for use with any browser though.

The background story

I love xscreensaver. But I just hate it when I have to tuck it off while I'm away from the keyboard, watching videos, for instance. On one hand the developers of mplayer have come with a nifty solution: heartbeat-cmd. Unfortunately you can't expect Mozilla to implement the same trick. So we have to do it ourselves, right?...

Prerequisite

As krinn rightfully hints, /proc/pid/io may not always be available. You have to make sure your kernel configuration includes the following:
Kernel config:
Enable extended accounting over taskstats (CONFIG_TASK_XACCT)
* Enable per-task storage I/O accounting (CONFIG_TASK_IO_ACCOUNTING=y)

Note that very same configuration is required if you use iotop.

How does it work

It's best (IMHO) to have the script run on as many distributions as possible instead of relying on extensions or modules, which are browser- or desktop-environment-dependent. Xorg comes with plenty of tools, which used appropriately can get us close to what we want.

Instead of deactivating xscreensaver from within Firefox, we want to a) detect what the active (i.e. currently focused) window is, b) check the process it belongs to, c) if it is busy downloading (a video, whatever...) While a) and b) are easy, c) is less straightforward. How can we detect a browser that pulls down a video from Youtube? Or any video? Check the URL? No, too cumbersome.

A browser that shows a video is supposed to cause disk activity. In general (and it's true with Youtube) videos aren't downloaded at once (unless they're very short) but slowly enough to not hog up the whole bandwidth. That's the most daring assumption I made. If you check the kernel I/O information for a given process ID you'll see a few hints as to what amount of data a process is pulling off or throwing at the storage. Check write_bytes in /proc/<PID>/io for short.

If the browser doesn't write to the disk for 30 seconds the script exits. Otherwise it sends the deactivate beacon to xscreensaver.

Here's the script.

/usr/local/bin/check-fswindow.sh:
#!/bin/bash

# This script tries to inhibit the screen saver while Firefox (or any other
# browser) is busy showing videos. It is intended to run as a cron job every
# minute or so, i.e. any period shorter than xscreensaver lock time.
#
# Steps:
#
# 1) get the active window (the one which has the focus)
# 2) get the owning process ID
# 3) check write_bytes /proc/<PID>/io
#
# Send the deactivate command whenever "write_bytes" changes.
# Exit if it it's been the same value for 30 seconds.
#
# Note this script uses xprop formatting to output eval compatible assignment
# expressions, such as _NET_ACTIVE_WINDOW and _NET_WM_PID. IF we don't do
# that xprop output contains extraneous spaces that mess things up.

# set -x

check_active_window()
{
   # Get active window ID
   eval $(xprop -root -notype -f _NET_ACTIVE_WINDOW 32x '=$0\n' _NET_ACTIVE_WINDOW)
   [ -n "$_NET_ACTIVE_WINDOW" ] || return 1

   # Get its process ID
   eval $(xprop -id $_NET_ACTIVE_WINDOW -notype -f _NET_WM_PID 32c '=$0\n' _NET_WM_PID)
   [ -n "$_NET_WM_PID" ] || return 1

   # Is it the process which name was passed as an argument?
   grep -Eq "$@" /proc/$_NET_WM_PID/cmdline || return 1
}

# Get display ID from the session manager
if [ -z "$DISPLAY" ]; then
   PID=$(pgrep -u $UID $1)
   [ -n "$PID" ] || exit 0

   eval $(grep -Eoa 'DISPLAY=[:09.]+' /proc/$PID/environ)
   [ -n "$DISPLAY" ] || exit 1

   shift
   export DISPLAY
fi

last_write_bytes=0
count=0
while [ $count -ne 4 ]; do
   # Check active window process
   check_active_window $1 || exit 0

   # Check IO bytes written
   eval $(sed -rn '/^write_bytes/s/:\s+/=/p' /proc/$_NET_WM_PID/io)
   if [ $last_write_bytes -ne $write_bytes ]; then
      [ $last_write_bytes -eq 0 ] || xscreensaver-command -deactivate >/dev/null
      last_write_bytes=$write_bytes
   else
      (( count++ ))
   fi
   sleep 10s
done


EDIT: Bug fixed in the 10s loop; every time the script is executed might prevent the screensaver from running for good since last_write_bytes always starts from 0, which always differs from what's in /proc/$_NET_WM_PID/io on the first iteration.

I successfully ran it from a cron job for a couple of hours while watching videos on Youtube:

crontab -e:
*/5 * * * *     /usr/local/bin/check-fswindow.sh xfce4-session firefox

The script runs with bash. Making it run with dash shouldn't be too difficult. On my machine the screen saver delay is set to 10 minutes. So far it has been enough. The screen saver started as expected after I closed the video tab and left my machine idle for a little more than 10 minutes. Not sure one needs to close the video tab though.

One caveat is that the screen saver will also be deactivated if you leave your browser active, full-screen while downloading anything. Just switch to another window to fix that.

If you want to check, say, seamonkey and firefox, thanks to the grep clause:
crontab -e:
*/5 * * * *     /usr/local/bin/check-fswindow.sh xfce4-session 'seamonkey|firefox'

Hope this helps.
_________________
Gentoo addict: tomorrow I quit, I promise!... Just one more emerge...


Last edited by VinzC on Tue Jun 28, 2016 8:00 pm; edited 3 times in total
Back to top
View user's profile Send private message
krinn
Watchman
Watchman


Joined: 02 May 2003
Posts: 5966

PostPosted: Mon Jun 27, 2016 11:11 am    Post subject: Reply with quote

some notes:
Code:
 sleep 3 && xprop -root -notype -f _NET_ACTIVE_WINDOW 32x '=$0\n' _NET_ACTIVE_WINDOW
(sleep 3 so i have time to click on firefox windows)
_NET_ACTIVE_WINDOW=0x100008e
xprop -id 0x100008e -notype -f _NET_WM_PID 32c '=$0\n' _NET_WM_PID
_NET_WM_PID=5939

Code:
pidof firefox
5939

Code:
LANG=C ls /proc/5939/i*
ls: cannot access '/proc/5939/i*': No such file or directory


- are you sure /proc/pid/io is always there? for my firefox i have none. making the test for write_bytes not that reliable
- i fail to see the fullscreen check. my tests were made with firefox not fullscreen and they pass it well.

edit: in case it help, my "dirty" solve to that problem is: open vlc with a movie, hit pause: vlc disable screen saving (i have no screensaver to disable myself, except the monitors getting off)
Back to top
View user's profile Send private message
VinzC
Advocate
Advocate


Joined: 17 Apr 2004
Posts: 4862
Location: Dark side of the mood

PostPosted: Mon Jun 27, 2016 11:36 am    Post subject: Reply with quote

krinn wrote:
some notes:
...
- are you sure /proc/pid/io is always there? for my firefox i have none. making the test for write_bytes not that reliable
- i fail to see the fullscreen check. my tests were made with firefox not fullscreen and they pass it well.

Dumb me!... I wrote this HOWTO right before going to sleep. Indeed there's no check for _NET_WM_STATE_FULLSCREEN as I later acknowledged any focused web browser window that is using storage continuously must mean to deactivate the screen saver... So the check was there in a first draft of my script, now it's gone. So indeed if you are viewing videos, the screen saver should be deactivated regardless of the full screen state. I'll update my post accordingly.

As for your second point, I can tell it's also present on Manjaro, which runs my laptop. It's filed in your kernel config "Enable per-task storage I/O accounting" (CONFIG_TASK_IO_ACCOUNTING).

krinn wrote:
edit: in case it help, my "dirty" solve to that problem is: open vlc with a movie, hit pause: vlc disable screen saving (i have no screensaver to disable myself, except the monitors getting off)

I don't have VLC on my Gentoo machine and wanted as few dependencies as possible.
_________________
Gentoo addict: tomorrow I quit, I promise!... Just one more emerge...
Back to top
View user's profile Send private message
krinn
Watchman
Watchman


Joined: 02 May 2003
Posts: 5966

PostPosted: Mon Jun 27, 2016 3:00 pm    Post subject: Reply with quote

Code:
grep CONFIG_TASK /usr/src/linux/.config
CONFIG_TASKSTATS=y
CONFIG_TASK_DELAY_ACCT=y
# CONFIG_TASK_XACCT is not set
# CONFIG_TASKS_RCU is not set


Well at least good to note it need a kernel option, but from my kernel, it also mean some minimal kernel version. (i'm using 3.18.30)
Back to top
View user's profile Send private message
VinzC
Advocate
Advocate


Joined: 17 Apr 2004
Posts: 4862
Location: Dark side of the mood

PostPosted: Tue Jun 28, 2016 2:48 pm    Post subject: Reply with quote

krinn wrote:
Code:
grep CONFIG_TASK /usr/src/linux/.config
CONFIG_TASKSTATS=y
CONFIG_TASK_DELAY_ACCT=y
# CONFIG_TASK_XACCT is not set
# CONFIG_TASKS_RCU is not set


Well at least good to note it need a kernel option, but from my kernel, it also mean some minimal kernel version. (i'm using 3.18.30)

You need to enable CONFIG_TASK_XACCT to see CONFIG_TASK_IO_ACCOUNTING. Updating the thread :-) ... Done.
_________________
Gentoo addict: tomorrow I quit, I promise!... Just one more emerge...
Back to top
View user's profile Send private message
Syl20
Guru
Guru


Joined: 04 Aug 2005
Posts: 500
Location: France

PostPosted: Tue Jun 28, 2016 5:29 pm    Post subject: Reply with quote

I'm looking for a solution to this problem, more or less, for years... So I made some tests yesterday, but, unfortunately, Firefox is too much quiet : the "write_bytes" field isn't increased often enough to block the screensaver on my computer. :cry:
My config : amd64 stable, firefox 46, watching Youtube HTML5 videos, xscreensaver configured to blank the screen after five minutes of inactivity, and the script is cronned every two minutes (so there are two executions before the screensaver starting).

That said, this way is interesting, thank you. I'll try to dig a little more, to see if I can find something working on my systems.
Back to top
View user's profile Send private message
VinzC
Advocate
Advocate


Joined: 17 Apr 2004
Posts: 4862
Location: Dark side of the mood

PostPosted: Tue Jun 28, 2016 7:50 pm    Post subject: Reply with quote

Syl20 wrote:
I'm looking for a solution to this problem, more or less, for years... So I made some tests yesterday, but, unfortunately, Firefox is too much quiet : the "write_bytes" field isn't increased often enough to block the screensaver on my computer. :cry:
My config : amd64 stable, firefox 46, watching Youtube HTML5 videos, xscreensaver configured to blank the screen after five minutes of inactivity, and the script is cronned every two minutes (so there are two executions before the screensaver starting).

That said, this way is interesting, thank you. I'll try to dig a little more, to see if I can find something working on my systems.


There are a few ways from here. A couple of options I thought of
  • looking into the window title with xprop
  • monitoring firefox's network traffic — which would maybe require throttling with fast internet connections, in case the download process is too quick
  • find another field from /proc/<pid> to monitor
  • use the fullscreen property alone to deactivate xscreensaver
Maybe also the idle delay you gave xscreensaver is a little too short. I know some applications do restrain from writing to the disk for some period. Don't know if it's the case with firefox but you might want to increase xscreensaver idle delay up to 10 minutes like I did and, why not, increase the number of 10s loops in the script...
_________________
Gentoo addict: tomorrow I quit, I promise!... Just one more emerge...
Back to top
View user's profile Send private message
Syl20
Guru
Guru


Joined: 04 Aug 2005
Posts: 500
Location: France

PostPosted: Thu Jun 30, 2016 10:05 am    Post subject: Reply with quote

I should have some time to spend on this next weekend. Thank you for the tips.
Back to top
View user's profile Send private message
krinn
Watchman
Watchman


Joined: 02 May 2003
Posts: 5966

PostPosted: Thu Jun 30, 2016 3:29 pm    Post subject: Reply with quote

how about netstat -p | firefox
if you get an ESTABLISHED state, it is at work.
Back to top
View user's profile Send private message
frankenputer
n00b
n00b


Joined: 09 Mar 2016
Posts: 26

PostPosted: Thu Jun 30, 2016 3:44 pm    Post subject: Reply with quote

krinn wrote:
how about netstat -p | firefox
if you get an ESTABLISHED state, it is at work.


Code:
netstat -n | gawk '/^tcp/ {state=$NF} END {print state}'
netstat -n | gawk \
  '/^tcp/ {
    st[$NF]++;
  }
  END {
    for (k in st) {
      print k,"\t",st[k];
    }
  }'


Edit:

I think the more correct approach will be to check the CPU load and if it matches certain load to execute xset -dmps and xset s off

Code:
ps -eo pcpu,comm | gawk '{ if ($1 > 20) { print $1,$2 } }'
# 32.4 chrome
Back to top
View user's profile Send private message
VinzC
Advocate
Advocate


Joined: 17 Apr 2004
Posts: 4862
Location: Dark side of the mood

PostPosted: Fri Jul 01, 2016 8:47 pm    Post subject: Reply with quote

krinn wrote:
how about netstat -p | firefox
if you get an ESTABLISHED state, it is at work.

Might be worth trying 8) . I believe keep alive connections/scripts might defeat this test but definitely worth combining with other detection steps.

frankenputer wrote:
I think the more correct approach will be to check the CPU load and if it matches certain load to execute xset -dmps and xset s off

Code:
ps -eo pcpu,comm | gawk '{ if ($1 > 20) { print $1,$2 } }'
# 32.4 chrome

Hmmm... not sure. Web sites with heavy animations might defeat the detection on a "non-accelerated-graphics" (i.e. between old and very, very old) machine, for instance.
_________________
Gentoo addict: tomorrow I quit, I promise!... Just one more emerge...
Back to top
View user's profile Send private message
Syl20
Guru
Guru


Joined: 04 Aug 2005
Posts: 500
Location: France

PostPosted: Mon Jul 04, 2016 3:44 pm    Post subject: Reply with quote

Ok, I've a working script. I decided to deactivate the screensaver only when the browser window has both focused and fullscreen (not maximized) states. That does the job, according to my habits.

Code:
#!/bin/bash
# This script tries to inhibit the screen saver while Firefox (or any other
# browser) is full screen. It is intended to run as a cron job every
# minute or so, i.e. any period shorter than xscreensaver lock time.
#                                                                                                                           
# Note this script uses xprop formatting to output eval compatible assignment
# expressions, such as _NET_ACTIVE_WINDOW and _NET_WM_PID. IF we don't do
# that xprop output contains extraneous spaces that mess things up.
set -uef -o pipefail
                                                                                                                           
[ -z "$@" ] && exit 1
NAV="$1"        # Browser, as it appears in `ps` list

# First, is the browser running ?
PID=$(pgrep --delimiter " " --uid "$UID" "$NAV")
[ -z "$PID" ] && exit 0

# Second, am I focused on it ?
DISPLAYS=""                                                                                                                 
DISPLAY=""                                                                                                                 
for pid in $PID
do
        eval $(grep -Eoa 'DISPLAY=[:09.]+' "/proc/$pid/environ")
        [ -z "$DISPLAY" ] && continue
        DISPLAYS="$DISPLAYS $DISPLAY"
done                                                                                                                       
                                                                                                                           
for DISPLAY in $(echo $DISPLAYS | tr " " "\n" | sort -u)
do
        export DISPLAY

        # Get active window ID
        eval $(xprop -root -notype -f _NET_ACTIVE_WINDOW 32x '=$0\n' _NET_ACTIVE_WINDOW)
        [ -z "$_NET_ACTIVE_WINDOW" ] && exit 1
        # Get its process ID
        eval $(xprop -id "$_NET_ACTIVE_WINDOW" -notype -f _NET_WM_PID 32c '=$0\n' _NET_WM_PID)
        [ -z "$_NET_WM_PID" ] && exit 1
        # Check the process name
        grep -q "$NAV" "/proc/$_NET_WM_PID/cmdline" || continue

        # Third, is the browser window full-screen ?
        xprop -id "$_NET_ACTIVE_WINDOW" -notype "_NET_WM_STATE" | grep -q "_NET_WM_STATE_FULLSCREEN" || continue

        # Ok, all the requirements are met.
        xscreensaver-command -deactivate > /dev/null 2>&1
        xset dpms s reset > /dev/null 2>&1
        exit 0
done


Even if firefox is still mono-processus, I decided to make this script multi-processus compliant. But, most of the times, on a personal computer, there's only one display used at a given time. Rarely two. Splitting the windows properties detections into two different for loops limits the number of executed commands.

I had to add the "xset dpms s reset" command to deactivate all the screen blanking capabilities.

Thank you VinzC for the ideas, the base script, and the motivation to finish this long quest... :lol:
Back to top
View user's profile Send private message
VinzC
Advocate
Advocate


Joined: 17 Apr 2004
Posts: 4862
Location: Dark side of the mood

PostPosted: Thu Jul 07, 2016 5:42 pm    Post subject: Reply with quote

Syl20 wrote:
Thank you VinzC for the ideas, the base script, and the motivation to finish this long quest... :lol:

My pleasure. Glad you found a working solution 8) .
_________________
Gentoo addict: tomorrow I quit, I promise!... Just one more emerge...
Back to top
View user's profile Send private message
Display posts from previous:   
Reply to topic    Gentoo Forums Forum Index Documentation, Tips & Tricks All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum