Commit 4e429f57 authored by Guillaume Seguin's avatar Guillaume Seguin

Add power management stuff (#284, #480). Needs testing

Heavily untested except on Arch Linux.
parent 499b940a
# This file is part of the Printrun suite.
#
# Printrun is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Printrun is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Printrun. If not, see <http://www.gnu.org/licenses/>.
import platform
import traceback
if platform.system == "Darwin":
from .osx import inhibit_sleep_osx, deinhibit_sleep_osx
inhibit_sleep = inhibit_sleep_osx
deinhibit_sleep = deinhibit_sleep_osx
elif platform.system == "Windows":
import ctypes
ES_CONTINUOUS = 0x80000000
ES_SYSTEM_REQUIRED = 0x00000001
def inhibit_sleep(reason):
mode = ES_CONTINUOUS | ES_SYSTEM_REQUIRED
ctypes.windll.kernel32.SetThreadExecutionState(ctypes.c_int(mode))
def deinhibit_sleep():
ctypes.windll.kernel32.SetThreadExecutionState(ctypes.c_int(ES_CONTINUOUS))
else:
import dbus
def inhibit_sleep(reason):
if inhibit_sleep.handler is None:
bus = dbus.SessionBus()
try:
# GNOME uses the right object path, try it first
service_name = "org.freedesktop.ScreenSaver"
proxy = bus.get_object(service_name,
"/org/freedesktop/ScreenSaver")
inhibit_sleep.handler = dbus.Interface(proxy, service_name)
except dbus.DBusException:
# KDE uses /ScreenSaver object path, let's try it as well
proxy = bus.get_object(service_name,
"/ScreenSaver")
inhibit_sleep.handler = dbus.Interface(proxy, service_name)
inhibit_sleep.token = inhibit_sleep.handler.Inhibit("printrun", reason)
inhibit_sleep.handler = None
def deinhibit_sleep():
if inhibit_sleep.handler is None:
return
inhibit_sleep.handler.UnInhibit(inhibit_sleep.token)
inhibit_sleep.token = None
try:
import psutil
def set_priority():
p = psutil.Process()
p.nice(10 if platform.system != "Windows" else psutil.HIGH_PRIORITY_CLASS)
def reset_priority():
p = psutil.Process()
p.nice(0 if platform.system != "Windows" else psutil.NORMAL_PRIORITY_CLASS)
def powerset_print_start(reason):
set_priority()
inhibit_sleep(reason)
def powerset_print_stop():
reset_priority()
deinhibit_sleep()
except ImportError:
print "psutil unavailable, could not import power utils:"
traceback.print_exc()
def powerset_print_start():
pass
def powerset_print_stop():
pass
# This file is part of the Printrun suite.
#
# Printrun is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Printrun is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Printrun. If not, see <http://www.gnu.org/licenses/>.
#
# Imported from http://www.benden.us/journal/2014/OS-X-Power-Management-No-Sleep-Howto/
# Copyright (c) Joseph Benden 2014
import ctypes
import CoreFoundation
import objc
def SetUpIOFramework():
# load the IOKit library
framework = ctypes.cdll.LoadLibrary(
'/System/Library/Frameworks/IOKit.framework/IOKit')
# declare parameters as described in IOPMLib.h
framework.IOPMAssertionCreateWithName.argtypes = [
ctypes.c_void_p, # CFStringRef
ctypes.c_uint32, # IOPMAssertionLevel
ctypes.c_void_p, # CFStringRef
ctypes.POINTER(ctypes.c_uint32)] # IOPMAssertionID
framework.IOPMAssertionRelease.argtypes = [
ctypes.c_uint32] # IOPMAssertionID
return framework
def StringToCFString(string):
# we'll need to convert our strings before use
encoding = CoreFoundation.kCFStringEncodingASCII
cfstring = CoreFoundation.CFStringCreateWithCString(None, string, encoding)
return objc.pyobjc_id(cfstring.nsstring())
def AssertionCreateWithName(framework, a_type,
a_level, a_reason):
# this method will create an assertion using the IOKit library
# several parameters
a_id = ctypes.c_uint32(0)
a_type = StringToCFString(a_type)
a_reason = StringToCFString(a_reason)
a_error = framework.IOPMAssertionCreateWithName(
a_type, a_level, a_reason, ctypes.byref(a_id))
# we get back a 0 or stderr, along with a unique c_uint
# representing the assertion ID so we can release it later
return a_error, a_id
def AssertionRelease(framework, assertion_id):
# releasing the assertion is easy, and also returns a 0 on
# success, or stderr otherwise
return framework.IOPMAssertionRelease(assertion_id)
def inhibit_sleep_osx(reason):
no_idle = "NoIdleSleepAssertion"
# Initialize IOKit framework
if inhibit_sleep_osx.framework is None:
inhibit_sleep_osx.framework = SetUpIOFramework()
framework = inhibit_sleep_osx.framework
# Start inhibition
ret, a_id = AssertionCreateWithName(framework, no_idle, 255, reason)
inhibit_sleep_osx.assertion_id = a_id
return ret
inhibit_sleep_osx.framework = None
def deinhibit_sleep_osx():
return AssertionRelease(inhibit_sleep_osx.framework,
inhibit_sleep_osx.assertion_id)
...@@ -33,6 +33,7 @@ from printrun.printrun_utils import install_locale, run_command, \ ...@@ -33,6 +33,7 @@ from printrun.printrun_utils import install_locale, run_command, \
format_time, format_duration, RemainingTimeEstimator, \ format_time, format_duration, RemainingTimeEstimator, \
get_home_pos, parse_build_dimensions get_home_pos, parse_build_dimensions
install_locale('pronterface') install_locale('pronterface')
from printrun.power import powerset_print_start, powerset_print_stop
from printrun import gcoder from printrun import gcoder
from functools import wraps from functools import wraps
...@@ -1147,8 +1148,18 @@ class pronsole(cmd.Cmd): ...@@ -1147,8 +1148,18 @@ class pronsole(cmd.Cmd):
else: else:
print _("Print started at: %s") % format_time(self.starttime) print _("Print started at: %s") % format_time(self.starttime)
self.compute_eta = RemainingTimeEstimator(self.fgcode) self.compute_eta = RemainingTimeEstimator(self.fgcode)
try:
powerset_print_start(reason = "Preventing sleep during print")
except:
logging.error(_("Failed to inhibit sleep:"))
traceback.print_exc(file = sys.stdout)
def endcb(self): def endcb(self):
try:
powerset_print_stop()
except:
logging.error(_("Failed to uninhibit sleep:"))
traceback.print_exc(file = sys.stdout)
if self.p.queueindex == 0: if self.p.queueindex == 0:
print_duration = int(time.time() - self.starttime + self.extra_print_time) print_duration = int(time.time() - self.starttime + self.extra_print_time)
print _("Print ended at: %(end_time)s and took %(duration)s") % {"end_time": format_time(time.time()), print _("Print ended at: %(end_time)s and took %(duration)s") % {"end_time": format_time(time.time()),
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment