[mythtv] screensaver patch

Cliff Draper Cliff.Draper at Sun.COM
Mon Dec 22 17:09:04 EST 2003


I'm attaching the patch for automatic disabling of screensavers
(standard X blanking, DPMS, and xscreensaver).  It adds the following
functions to util.cpp:
  void ScreenSaverOff();
  void ScreenSaverRestore();
  void ResetScreenSaver();

which are called at the right locations when the video player makes a
state transition, when pause is engaged or disengaged, and when
myth_system is called.

Since xscreensaver requires a constant deactivate message, I decided
to write that using a small perl script, rather than add another
thread to mythfrontend.

Here's what I have in my .xsession (which uses xscreensaver and not
the others):
xset s off
xset -dpms
xscreensaver -nosplash &
xscreensaver-keeper &

regards,
Cliff Draper    Sun Microsystems, Forte Tools
My opinions may or may not reflect those of my employer.
---------------------------- food for thought ---------------------------
"The one thing that unites all human beings, regardless of age,
gender, religion, economic status, or ethnic background, is that, deep
down inside, we ALL believe that we are above-average drivers." -Dave Barry
-------------- next part --------------
Index: settings.pro
===================================================================
RCS file: /var/lib/mythcvs/mythtv/settings.pro,v
retrieving revision 1.40
diff -u -r1.40 settings.pro
--- settings.pro	23 Oct 2003 19:57:17 -0000	1.40
+++ settings.pro	22 Dec 2003 21:51:49 -0000
@@ -43,3 +43,6 @@
 # VIA cle266 support
 #CONFIG += using_viahwslice
 #EXTRA_LIBS += -lddmpeg
+
+DEFINES += STANDARD_X_SCREENSAVER
+DEFINES += XSCREENSAVER_KEEPER
Index: libs/libmyth/util.cpp
===================================================================
RCS file: /var/lib/mythcvs/mythtv/libs/libmyth/util.cpp,v
retrieving revision 1.31
diff -u -r1.31 util.cpp
--- libs/libmyth/util.cpp	14 Dec 2003 19:46:51 -0000	1.31
+++ libs/libmyth/util.cpp	22 Dec 2003 21:51:52 -0000
@@ -3,6 +3,7 @@
 #include <unistd.h>
 
 #include <iostream>
+#include <fstream>
 using namespace std;
 
 #include "util.h"
@@ -12,6 +13,26 @@
 extern "C" {
 #include <X11/Xlib.h>
 #include <X11/extensions/Xinerama.h>
+
+#ifdef STANDARD_X_SCREENSAVER
+    /* It would have been better to #include <X11/extensions/dpms.h>, but that didn't work for me; so including them manually. */
+    typedef unsigned short CARD16;
+    extern int XActivateScreenSaver(Display* display);
+    extern int XGetScreenSaver(Display* display, int* timeout_return,
+                               int* interval_return, int* prefer_blanking_return,
+                               int* allow_exposures_return);
+    extern int XSetScreenSaver(Display* display, int timeout,
+                             int interval, int prefer_blanking,
+                             int allow_exposures);
+    extern int XResetScreenSaver(Display* display);
+    extern int DPMSGetTimeouts(Display* display, CARD16* standby,
+                               CARD16* suspend, CARD16* off);
+    extern int DPMSSetTimeouts(Display* display, CARD16 standby,
+                               CARD16 suspend, CARD16 off);
+    extern int DPMSInfo(Display *, CARD16 *, unsigned char *);
+    extern int DPMSEnable(Display *);
+    extern int DPMSDisable(Display *);
+#endif
 }
 #endif
 
@@ -555,7 +576,10 @@
     (void)flags;
 #endif
 
-    return system(command);
+    ScreenSaverOff();
+    int result = system(command);
+    ScreenSaverRestore();
+    return result;
 }
 
 QString cutDownString(QString text, QFont *testFont, int maxwidth)
@@ -584,3 +608,76 @@
     return text;
 }
 
+
+#ifdef XSCREENSAVER_KEEPER
+#define XSCREENSAVER_KEEPER_FILE "/tmp/keep-xscreensaver"
+#define XSCREENSAVER_RESET_FILE "/tmp/reset-xscreensaver"
+#endif
+#ifdef STANDARD_X_SCREENSAVER
+static int screenSaverTimeout, screenSaverInterval, screenSaverPreferBlank, screenSaverAllowExposure;
+static bool reenableDPMSOnRestore;
+#endif
+
+void ResetScreenSaver()
+{
+    //cout << "ResetScreenSaver" << endl;
+#ifdef STANDARD_X_SCREENSAVER
+    XResetScreenSaver(qt_xdisplay());
+#endif
+#ifdef XSCREENSAVER_KEEPER
+    ofstream fout;
+    fout.open(XSCREENSAVER_RESET_FILE);
+    fout.close();
+#endif
+}
+
+void ScreenSaverOff()
+{
+    //cout << "ScreenSaverOff" << endl;
+#ifdef XSCREENSAVER_KEEPER
+    // Need to create the file to turn off xscreensaver
+    ofstream fout;
+    fout.open(XSCREENSAVER_KEEPER_FILE);
+    fout.close();
+#endif
+
+#ifdef STANDARD_X_SCREENSAVER
+    XGetScreenSaver(qt_xdisplay(), &screenSaverTimeout, &screenSaverInterval,
+                    &screenSaverPreferBlank, &screenSaverAllowExposure);
+    //cout << "timeout=" << screenSaverTimeout << " interval=" << screenSaverInterval << endl;
+    //cout << "PreferBlank=" << screenSaverPreferBlank << " allow_exposure=" << screenSaverAllowExposure << endl;
+    XSetScreenSaver(qt_xdisplay(), 0, 0, 0, 0);
+
+    CARD16 power_level;
+    unsigned char state;
+    int result = DPMSInfo(qt_xdisplay(), &power_level, &state);
+    //cout << "DPMSInfo result=" << result << endl;
+    //cout << "power_level " << power_level << " state " << (int) state << endl;
+    if (state != 0) {
+        reenableDPMSOnRestore = true;
+        result = DPMSDisable(qt_xdisplay());
+        //cout << "DPMSDisable result=" << result << endl;
+    } else {
+        reenableDPMSOnRestore = false;
+    }
+#endif
+}
+
+void ScreenSaverRestore()
+{
+    //cout << "ScreenSaverRestore" << endl;
+    // Reset the timer on the screen saver, so that when we restore it, it
+    // doesn't suddenly come on.
+    ResetScreenSaver();
+#ifdef STANDARD_X_SCREENSAVER
+    if (reenableDPMSOnRestore) {
+        int result = DPMSEnable(qt_xdisplay());
+        //cout << "DPMSEnable result=" << result << endl;
+    }
+    XSetScreenSaver(qt_xdisplay(), screenSaverTimeout, screenSaverInterval,
+                    screenSaverPreferBlank, screenSaverAllowExposure);
+#endif
+#ifdef XSCREENSAVER_KEEPER
+    unlink(XSCREENSAVER_KEEPER_FILE);
+#endif
+}
Index: libs/libmyth/util.h
===================================================================
RCS file: /var/lib/mythcvs/mythtv/libs/libmyth/util.h,v
retrieving revision 1.13
diff -u -r1.13 util.h
--- libs/libmyth/util.h	11 Dec 2003 22:48:33 -0000	1.13
+++ libs/libmyth/util.h	22 Dec 2003 21:51:52 -0000
@@ -31,6 +31,10 @@
 long long decodeLongLong(QStringList &list, int offset);
 long long decodeLongLong(QStringList &list, QStringList::iterator &it);
 
+void ScreenSaverOff();
+void ScreenSaverRestore();
+void ResetScreenSaver();
+
 #ifndef QWS
 void GetMythTVGeometry(Display *dpy, int screen_num, int *x, int *y, 
                        int *w, int *h);
Index: libs/libmythtv/tv_play.cpp
===================================================================
RCS file: /var/lib/mythcvs/mythtv/libs/libmythtv/tv_play.cpp,v
retrieving revision 1.135
diff -u -r1.135 tv_play.cpp
--- libs/libmythtv/tv_play.cpp	22 Dec 2003 19:51:20 -0000	1.135
+++ libs/libmythtv/tv_play.cpp	22 Dec 2003 21:51:55 -0000
@@ -500,6 +500,7 @@
 
         recorder->SpawnLiveTV();
 
+        ScreenSaverOff();
         StartPlayerAndRecorder(true, true);
     }
     else if (internalState == kState_WatchingLiveTV && 
@@ -509,6 +510,7 @@
         changed = true;
 
         StopPlayerAndRecorder(true, true);
+        ScreenSaverRestore();
     }
     else if (internalState == kState_WatchingRecording &&
              nextState == kState_WatchingPreRecorded)
@@ -521,6 +523,7 @@
              (internalState == kState_None &&
               nextState == kState_WatchingRecording))
     {
+        ScreenSaverOff();
         prbuffer = new RingBuffer(inputFilename, false);
 
         if (nextState == kState_WatchingRecording)
@@ -559,6 +562,7 @@
         changed = true;
 
         StopPlayerAndRecorder(true, false);
+        ScreenSaverRestore();
     }
     else if (internalState == kState_None && 
              nextState == kState_None)
@@ -1507,10 +1511,13 @@
     if (activenvp != nvp)
         return;
 
-    if (paused)
+    if (paused) {
         UpdatePosOSD(time, tr("Paused"));
-    else
+        ScreenSaverRestore();
+    } else {
         osd->EndPause();
+        ScreenSaverOff();
+    }
 }
 
 void TV::DoInfo(void)
Index: programs/mythfrontend/main.cpp
===================================================================
RCS file: /var/lib/mythcvs/mythtv/programs/mythfrontend/main.cpp,v
retrieving revision 1.126
diff -u -r1.126 main.cpp
--- programs/mythfrontend/main.cpp	16 Dec 2003 23:17:28 -0000	1.126
+++ programs/mythfrontend/main.cpp	22 Dec 2003 21:51:57 -0000
@@ -520,6 +520,20 @@
     TV::InitKeys();
 }
 
+#ifdef STANDARD_X_SCREENSAVER
+class MainEventFilter : public QObject {
+public:
+    MainEventFilter() {}
+
+    bool eventFilter(QObject *o, QEvent *event) {
+        if (event->type() == QEvent::KeyPress) {
+            ResetScreenSaver();
+        }
+        return false;
+    }
+};
+#endif
+
 int main(int argc, char **argv)
 {
     QString lcd_host;
@@ -736,6 +750,11 @@
     mainWindow->Init();
     gContext->SetMainWindow(mainWindow);
 
+#ifdef STANDARD_X_SCREENSAVER
+    MainEventFilter *mainEventFilter = new MainEventFilter();
+    a.installEventFilter(mainEventFilter);
+#endif
+
     InitJumpPoints();
 
     MythPluginManager::init();
-------------- next part --------------
#!/usr/bin/perl -w

$keepFile = "/tmp/keep-xscreensaver";
$resetFile = "/tmp/reset-xscreensaver";
$dotXscreensaver = "$ENV{HOME}/.xscreensaver";

$SIG{'HUP'} = 'readDotXscreensaver';

$sleepTime=60;
$sleepTimeWhileSavedScreen = 2;
&readDotXscreensaver;

#$sleepTime=2;   # For testing
printf("Sleep time is $sleepTime\n");

while (1) {
	$deactivate = 0;
	if (-f $resetFile) {
		$deactivate = 1;
		unlink $resetFile;
		#printf("Found $resetFile\n");
	} else {
		if (-f $keepFile) {
			$deactivate = 1;
			# Someone else unlinks the keepFile
			#printf("Found $keepFile\n");
		} else {
			#printf("Did not find it\n");
		}
	}
	if ($deactivate) {
		system "xscreensaver-command -deactivate";
		# Now sleep just enough time to come back again and disable it.
		sleep $sleepTime;
	} else {
		# The screen is currently saved (or will be in a second).
		# Wait only a short amount of time, so that our response time to
		# disabling it is quick.
		sleep $sleepTimeWhileSavedScreen;
	}
}

sub readDotXscreensaver {
	if (open(RC, $dotXscreensaver)) {
		while (defined($line = <RC>)) {
			if ($line =~ /^timeout:\s*(.*)/) {
				$time=$1;
				#printf("Found $time\n");
				($hours, $minutes, $seconds) = split(":", $time);
				$sleepTime = $seconds + 60*$minutes + 3600*$hours - 1;  # subtract 1 so that we can beat the screensaver
			}
		}
		close(RC);
	}
}


More information about the mythtv-dev mailing list