Skip to content

Commit

Permalink
Major update and project renamed
Browse files Browse the repository at this point in the history
This PR includes:
- More display methods
- Introduce power methods
- Add audio mute option
- Show popup on error
- Rename screensaver from No Signal to Turn Off
  • Loading branch information
dagwieers committed Apr 12, 2018
1 parent 454fe38 commit 6945ff7
Show file tree
Hide file tree
Showing 6 changed files with 210 additions and 101 deletions.
30 changes: 22 additions & 8 deletions README.adoc
Original file line number Diff line number Diff line change
@@ -1,22 +1,36 @@
= Kodi screensaver to turn off display
= Kodi screensaver that turns your screen off to save power

This Kodi screensaver turns your TV, projector or monitor off, so it can actually "save your screen".

No Signal is a Kodi screensaver that puts your display off when in screen saver mode.

== How does it work ?

It supports the following methods:

Raspberry Pi (vcgencmd)::
The screensaver causes 'no signal' using the vcgencmd utility. This only works on Raspberry Pi.

CEC Standby (internal)::
The screensaver forces the display to go into Standby using internal CEC controls.

Raspberry Pi (vcgencmd)::
The screensaver causes 'no signal' using the vcgencmd utility. This only works on Raspberry Pi.

DPMS (internal)::
The screensaver immediately forces the display off using internal DPMS (Energy Star) controls.

X11 DPMS (xset)::
The screensaver immediately forces the display off using the `xset` utility to set DPMS off state..
DPMS (xset)::
The screensaver immediately forces the display off using the `xset` utility to set DPMS off state.

DPMS (vbetool)::
The screensaver immediately forces the display off using the `vbetool` utility to set DPMS off state.

DPMS (xrandr)::
The screensaver immediately forces the display off using the `xrandr` utility to set DPMS off state.

Android CEC (kernel)::
The screensaver immediately forces the display off using kernel CEC controls and turns off device.


Optionally it also can put your system to sleep or power it off.

Or log off your user or mute audio.

Optionally this screensaver can also log off your user.
One can press the `HOME` key to deactivate the screensaver, depending on the method used and the state of the display it may turn your display back on.
10 changes: 5 additions & 5 deletions addon.xml
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<addon id="screensaver.nosignal" name="No Signal" version="0.8.0" provider-name="Dag Wieers">
<addon id="screensaver.turnoff" name="Turn Off" version="0.8.1" provider-name="Dag Wieers">
<extension point="xbmc.addon.metadata">
<platform>linux</platform>
<platform>all</platform>
<summary lang="en">Screensaver that turns your screen off to save power</summary>
<description lang="en">This is a real screen saver, as it turns the display signal off which makes your TV, beamer or monitor to eventually turn off too.</description>
<source>http://github.com/dagwieers/plugin.screensaver.nosignal</source>
<description lang="en">The Off screensaver turns your TV, projector or monitor off, so it can actually "save your screen".</description>
<source>http://github.com/dagwieers/plugin.screensaver.off</source>
<license>GPL3+</license>
<email>[email protected]</email>
</extension>
<extension point="xbmc.ui.screensaver" library="nosignal.py"/>
<extension point="xbmc.ui.screensaver" library="screensaver.py"/>
<requires><import addon="xbmc.python" version="2.25.0"/></requires>
</addon>
79 changes: 0 additions & 79 deletions nosignal.py

This file was deleted.

33 changes: 26 additions & 7 deletions resources/language/English/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,31 @@
<!-- For the add on itself -->

<!-- For the settings -->
<string id="30010">Used method</string>
<string id="30011">Do nothing</string>
<string id="30012">Raspberry Pi (vcgencmd)</string>
<string id="30013">CEC Standby (internal)</string>
<string id="30014">DPMS (internal)</string>
<string id="30015">X11 DPMS (xset)</string>
<string id="30100">Log off user when (activating screensaver)</string>
<string id="30000">Display</string>
<string id="31001">Display method</string>
<string id="31002">Not all 'Display methods' work on every system. Carefully test.</string>
<string id="31100">Do nothing</string>
<string id="31110">CEC Standby (built-in)</string>
<string id="31120">Raspberry Pi (using vcgencmd)</string>
<string id="31130">DPMS (built-in)</string>
<string id="31140">DPMS (using xset)</string>
<string id="31150">DPMS (using vbetool)</string>
<string id="31160">DPMS (using xrandr)</string>
<string id="31170">Android CEC (kernel)</string>
<string id="40000">Power</string>
<string id="41001">Power method</string>
<string id="41002">Don't change this unless you know exactly what you are doing.</string>
<string id="41100">Do nothing</string>
<string id="41110">Suspend (built-in)</string>
<string id="41120">Hibernate (built-in)</string>
<string id="41130">Quit (built-in)</string>
<string id="41140">Shutdown action (built-in)</string>
<string id="41150">Reboot (built-in)</string>
<string id="41260">Powerdown (built-in)</string>
<string id="41170">Android POWER key event (using input)</string>
<string id="80000">Options</string>
<string id="80001">When activating screensaver...</string>
<string id="80500">Log off user</string>
<string id="80600">Mute audio</string>

</strings>
15 changes: 13 additions & 2 deletions resources/settings.xml
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<settings>
<setting label="30010" type="enum" id="method" lvalues="30011|30012|30013|30014|30015" default="1"/>
<setting label="30100" type="bool" id="logoff" default="true"/>
<category id="display" label="30000">
<setting id="display_method" type="enum" label="31001" lvalues="31100|31110|31120|31130|31140|31150|31160|31170" default="1"/>
<setting id="display_label" type="text" label="31002" enable="false" />
</category>
<category id="power" label="40000">
<setting id="power_method" type="enum" label="41001" lvalues="41100|41110|41120|41130|41140|41150|41160|41170" default="0"/>
<setting id="power_label" type="text" label="41002" enable="false" />
</category>
<category id="options" label="80000">
<setting type="lsep" label="80001"/>
<setting id="logoff" type="bool" label="80500" default="false"/>
<setting id="mute" type="bool" label="80600" default="false"/>
</category>
</settings>
144 changes: 144 additions & 0 deletions screensaver.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
import sys
import subprocess

import xbmc
import xbmcaddon
import xbmcgui


def _popup(title='', msg='', delay=5000, image= ''):
xbmc.executebuiltin('XBMC.Notification("%s","%s",%d,"%s")' % (title, msg, delay, image))

def _run_builtin(builtin):
xbmc.log(msg="[%s] Executing builtin '%s'" % (addon_name, builtin), level=xbmc.LOGNOTICE)
try:
xbmc.executebuiltin(builtin)
except Exception as e:
xbmc.log(msg="[%s] Exception executing builtin '%s': %s" % (addon_name, builtin, e), level=xbmc.LOGERROR)
_popup(title='Screensaver failed', msg="[%s] Exception executing builtin '%s': %s" % (addon_name, builtin, e))

def _run_command(command, shell=False):
# TODO: Add options for running using su or sudo
try:
cmd = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=shell)
(out, err) = cmd.communicate()
if cmd.returncode == 0:
xbmc.log(msg="[%s] Running command '%s' returned rc=%s" % (addon_name, ' '.join(command), cmd.returncode), level=xbmc.LOGNOTICE)
else:
xbmc.log(msg="[%s] Running command '%s' failed with rc=%s" % (addon_name, ' '.join(command), cmd.returncode), level=xbmc.LOGERROR)
if err:
xbmc.log(msg="[%s] Command '%s' returned on stderr: %s" % (addon_name, command[0], err), level=xbmc.LOGERROR)
if out:
xbmc.log(msg="[%s] Command '%s' returned on stdout: %s " % (addon_name, command[0], out), level=xbmc.LOGERROR)
_popup(title='Screensaver failed', msg="%s\n%s" % (out, err))
sys.exit(1)
except Exception as e:
xbmc.log(msg="[%s] Exception running '%s': %s" % (addon_name, command[0], e), level=xbmc.LOGERROR)
_popup(title='Screensaver failed', msg="Exception running '%s': %s" % (command[0], e))
sys.exit(2)
# TODO: Show pop-up on failure


class Screensaver(xbmcgui.WindowXMLDialog):

class Monitor(xbmc.Monitor):

def __init__(self, callback):
self._callback = callback

def onScreensaverDeactivated(self):
self._callback()

def onInit(self):
self._monitor = self.Monitor(self.exit)

# Power off system
xbmc.log(msg='[%s] Turn system off using method %s' % (addon_name, power_method), level=xbmc.LOGNOTICE)
if power_method == '1': # Suspend (built-in)
_run_builtin('Suspend')
elif power_method == '2': # ShutDown action (built-in)
_run_builtin('Hibernate')
elif power_method == '3': # ShutDown action (built-in)
_run_builtin('Quit')
elif power_method == '4': # ShutDown action (built-in)
_run_builtin('ShutDown')
elif power_method == '5': # Reboot (built-in)
_run_builtin('Reboot')
elif power_method == '6': # PowerDown (built-in)
_run_builtin('PowerDown')
elif power_method == '7': # Android POWER key event (using input)
_run_command(['su', '-c', 'input keyevent KEYCODE_POWER'], shell=True)

def onAction(self, action):
self.exit()

def exit(self):
# Unmute audio
if mute == 'true':
_run_builtin('Mute')

# Turn on display
xbmc.log(msg='[%s] Turn display signal back on using method %s' % (addon_name, display_method), level=xbmc.LOGNOTICE)
if display_method == '1': # CEC Standby (built-in)
_run_builtin('CECActivateSource')
elif display_method == '2': # Raspberry Pi (using vcgencmd)
_run_command(['vcgencmd', 'display_power', '1'])
elif display_method == '3': # DPMS (built-in)
_run_builtin('ToggleDPMS')
elif display_method == '4': # X11 DPMS (using xset)
_run_command(['xset', 'dpms', 'force', 'on'])
elif display_method == '5': # DPMS (using vbetool)
_run_command(['vbetool', 'dpms', 'on'])
elif display_method == '6': # DPMS (using xrandr)
# NOTE: This needs more outside testing
_run_command(['xrandr', '--output CRT-0', 'on'])
elif display_method == '7': # Android CEC (kernel)
# NOTE: This needs more outside testing
_run_command(['su', '-c', 'echo 1 >/sys/devices/virtual/graphics/fb0/cec'], shell=True)

del self._monitor
self.close()

if __name__ == '__main__':
addon = xbmcaddon.Addon()

addon_name = addon.getAddonInfo('name')
addon_path = addon.getAddonInfo('path')
display_method = addon.getSetting('display_method')
power_method = addon.getSetting('power_method')
logoff = addon.getSetting('logoff')
mute = addon.getSetting('mute')

# Turn off display
xbmc.log(msg='[%s] Turn display signal off using method %s' % (addon_name, display_method), level=xbmc.LOGNOTICE)
if display_method == '1': # CEC Standby (built-in)
_run_builtin('CECStandby')
elif display_method == '2': # Raspberry Pi (using vcgencmd)
_run_command(['vcgencmd', 'display_power', '0'])
elif display_method == '3': # DPMS (built-in)
_run_builtin('ToggleDPMS')
elif display_method == '4': # X11 DPMS (using xset)
_run_command(['xset', 'dpms', 'force', 'off'])
elif display_method == '5': # DPMS (using vbetool)
_run_command(['vbetool', 'dpms', 'off'])
elif display_method == '6': # DPMS (using xrandr)
# NOTE: This needs more outside testing
_run_command(['xrandr', '--output CRT-0', 'off'])
elif display_method == '7': # Android CEC (kernel)
# NOTE: This needs more outside testing
_run_command(['su', '-c', 'echo 0 >/sys/devices/virtual/graphics/fb0/cec'], shell=True)


# FIXME: Screensaver always seems to log off when logged in ?
# Log off user
if logoff == 'true':
_run_builtin('System.Logoff()')

# Mute audio
if mute == 'true':
_run_builtin('Mute')

# Do not start screensaver when command fails
screensaver = Screensaver('screensaver-nosignal.xml', addon_path, 'default')
screensaver.doModal()
del screensaver

0 comments on commit 6945ff7

Please sign in to comment.