Skip to main content

Windows utility to override power requests blocking sleep/hibernate.

Project description

sleeper_service

This is a minimal Windows tray utility that enables (forces) sleep based on the active power plan "Sleep After" parameter.

For a long rant on why this exists, see the Package Rationale.

For the short version of why this exists, if you are looking for something/anything that deals with the "Legacy Kernel Caller" blocking sleep problem, hopefully this will work for you. In particular, if you have issues with Elgato Wave Link killing sleep, this is intended to help.

The v0.9 release provides a tray utility to trigger sleep or hibernate.

Beta: App/program Launch on Resume

v0.10.0 Beta functionality Use with caution. I have added a beta function that can (re-)launch apps/programs when resuming from a suspension triggered by sleeper_service (it does not work when sleep is triggered by the system or the start menu). This capability uses python's subprocess Popen to launch programs.

I've added this functionality because it allows me to manage issues in the Elgato Wave Link 3.0 beta. Specifically there are some people (myself included) who are having problems with Wave Link resuming from sleep properly. In my case, Wave Link either crashes (most of the time), or breaks mixes and/or channel/mix connections. I'm hoping that Elgato will address this issue as part of their beta.

In the interim, I'm using this function to restart Wave Link each time I resume from sleep (my examples in this section are for Wave Link). This is working well enough to allow me to use the beta. The one downside is that Wave Link will always open a foreground desktop window on resume, as the beta does not support opening minimised to the tray. I'm assuming this will be addressed towards the end of the beta. If not, I will tweak the restart functionality when the final version releases.

To set it up, run sleeper_service to create/update the settings file, then exit, and edit the settings so that the [restarts] section of the config.toml file looks like:

[restarts]
"Elgato.Wavelink.exe" = "Popen"

In my case "Elgato.Wavelink.exe" is a system alias for starting the UWP Wave Link 3.0 app. Please replace this with your app name. Currently, "Popen" is the only launch mode suppported, so this is the only valid value. Finally, if you want to start more than one app on resume, just add another line per app.

Using my sample [restarts], Wave Link should restart after every resume triggered by sleeper_service. As noted previously, manual or other automatic resumes will not trigger this restart.

This functionality will work with program or app that:

  • Can be launched with Popen call.
  • Does not require admin privileges.
  • Returns immediately from the Popen call.

This may be useful for other audio control apps that cause the "Legacy Kernel Caller" problem - e.g. Voicemeeter or SteelSeries Sonar (I haven't tested either of these, but I know it was an issue for older versions of Voicemeeter, and may still be?). If you do test this successfully with apps other than Wave Link, can you please add a comment to the end of this issue so that I can update the list of programs known to restart correctly.

If you have a program that you can't get to work with [restarts], please raise an issue so that we can address the problem.

We do have a live issue which may affect some programs/apps - any program/app restarted after sleep will have the same Windows "Current Directory" as the sleeper_service. This could be a problem if it relies on finding configuration or data files in the current directory. I'm treating this as a lower priority enhancement for a future release. If this is affecting you, please add a comment on this issue so that I know to make it a higher priority.

Change Log

  • v0.11.0 Added an option to add a "Suspend now!" button to the tray menu for testing. This can only be enabled by editing the config.toml settings.
  • V0.10.0 Converted to .pyw app, added beta function to enable restarting Wave Link on resume from sleep.
  • v0.9.0 Tray manager interface, core sleep functions implemented.
  • v0.0.2 Functional beta. Still requires pystray wrapper.
  • v0.0.1 Proof of concept.

Installation and Usage

sleeper_service is a system tray application for Windows. I'd recommend downloading the zip file from the Release page, unzipping and adding the executable to your start programs. However, if you prefer, you can install via pip (pip install sleeper_service) and either create your own pyinstaller bundle or run it from a local python installation or virtual environment.

Right click on the sleeper_service icon to see the interface:

Interface

Clicking on Enabled will enable/disable the service. You can also enable/disable by left clicking on the sleeper_service icon. The icon will have a red cross when disabled.

You can also switch between using the system timers and a manual timer specification. The Suspend: and After: lines are information only to tell you what the suspend action is and when it will be triggered.

There are a few other configuration parameters, but these only be changed by editing the configuration file - exit the service before editing.

(I'm assuming most of the parameters will be changed infrequently, so not worth including in the tray interface - Please raise an issue if you would prefer more parameters in the UI.)

Configuration file

The config.toml file provides manual configuration for sleeper_service. The location of the file is determined in the following priority order.

  • If the command line option --config <file path> specifies a file, e service will use the named file.
  • If the command line option --config <folder path> specifies a folder, the service will look for config.toml in the specified folder path.
  • If the service is run from the pyinstaller bundle, it will look for config.toml in the same folder as the service executable.
  • If the service is run as a normal python routine, it will look for the ficonfig.toml in the current working directory.

If the file does not exist, it will be created.

The configuration file options are:

  • enabled: true or false. Enable or disable the sleeper service. Switchable from the system tray interface. Useful if you want to turn it off for a while.
  • user_system_timer: true or false. If true, the suspend timer and suspend state are read from the users Windows Power plan (Sleep after and Hibernate after values, with the shorter timer assumed to apply). If false, manually specified values are taken from the configuration file. . Switchable from the system tray interface.
  • manual_suspend_after: time in minutes to activate suspend if use_system_timer is false.
  • manual_suspend_state: The suspend state to apply if use_system_timer is false. Allowable case sensitive values are: "sleep", "hibernate" or "disabled".
  • check_interval: time in minutes that sleeper_service will sleep between checks that the idle time has expired (I'm assuming most people will be happy checking once a minute at most).
  • suspend_button: when true, the tray menu includes a "Suspend now!" button that will immediately enable the suspend state. (Great for testing!)

The default configuration file is:

enabled = true
use_system_timer = true
manual_suspend_after = 10
manual_suspend_state = "sleep"
check_interval = 1

Package Rationale

This utility deals with the brain dead Windows implementation that allows an audio stream to block sleep. (Truly. It's genuinely stupid.)

Typical symptoms of this problem are:

  • A call to powercfg /requests will include the lines:
    [SYSTEM]
    An audio stream is currently in use.
    [DRIVER] Legacy Kernel Caller
    
  • Windows ignores sleep settings in the power plan (yeah, it's really this stupid).
  • There are no easy fixes or overrides to address the problem.

I've run into this problem with Elgato's Wave Link software (which is the trigger for writing this utility), and it has been a problem with Voicemeeter in the past (not sure if this has been resolved in more recent versions), and plenty of other software that creates an audio stream.

A quick search brings a vast range of complaints about Microsoft's bone headed implementation, but little in the way of effective, simple solutions to the problem. In particular:

  • Using powercfg /requestsoverride should allow users to prevent the Legacy Kernel Caller from blocking sleep. This flat out doesn't work. (Even if it did, Microsoft has decreed that this particular powercfg call requires elevated privileges. For a user space problem. Did I mention bone headed?).
  • There are various solutions using AutoHotKey, Visual Basic Scripts, and the Windows task manager. All are a bit opaque.

So this is yet another solution to the problem which is hopefully be relatively fire and forget, and also easy to suspend for the times you actually do want an audio stream to block sleep (rarely in my experience).

Development/testing

This section is a collection of information that may be useful in developing/testing future functionality.

Powercfg Options

Some of these commands may require an elevated shell:

  • powercfg /hibernate on/off to enable or disable hibernate.
  • powercfg /a lists available sleep states for system (and also sleep states that are not available/enabled).

Sleep and Requests

Forcing sleep from the Windows menu or programmatically will clear sleep blocking requests (powercfg /requests). Restarting audio streams seems to repair this when required, so I'm not going to worry about this. (Ideally, Microsoft would fix the underlying problem that audio streams should not have special privileges that block sleep states).

PyInstaller Builds

If you are building your own binary, I suggest starting with a clean environment and install only sleeper_service and pyinstaller to minimise by-catch in the pyinstaller bundle.

TODO/In Progress

This section contains informal notes on pending implementation details and possible future fixes/extensions.

Implementation:

  • Update module docs as development progresses.
  • Maybe add option too keep awake if audio stream detected on specific devices.
  • Make/ask for help with better icon. Best described as a bit rubbish at the moment.

Right now, wave link breaks things badly on resume from sleep. If Elgato don't fix this, each time we resume, we may need to:

  • (best case) restart wave link. Currently in beta for the beta. Not ideal, as Wave Link does not restart minimised.
  • check if wave link is active, kill and restart.

For finding and restarting Wave Link:

  • Can get more info with get-appxpackage -Name Elgato.Wavelink and get-startapps
  • If the final release doesn't fix problems in the beta, may need to kill the wave link process and restart - kill+psutils or taskkill?
  • Finally, restart wave link with either qualified app name. subprocess.run("explorer shell:appsfolder\Elgato.WaveLink_g54w8ztgkx496!App")
  • Or, even better: Wave Link has an app execution alias: "Elgato.WaveLink.exe", so no need to find UWP name if this is active!
    • So far, it looks like the easiest method to start this is with: subprocess.Popen("Elgato.Wavelink.exe")

Other:

  • Look into using pycaw to enable/disable microphones/inputs as a way to kill sleep blocking by powercfg requests. Specifically, using privacy & security setting for microphone. Maybe disabling device works as well. Neither sound like good solutions though.
  • Assuming Elgato fix the resume problem, it may be enough to simply pause/play to reset audio. Or maybe trigger a Streamdeck call to enable/disable channel/mix connections?

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

sleeper_service-0.11.0.tar.gz (19.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

sleeper_service-0.11.0-py3-none-any.whl (15.3 kB view details)

Uploaded Python 3

File details

Details for the file sleeper_service-0.11.0.tar.gz.

File metadata

  • Download URL: sleeper_service-0.11.0.tar.gz
  • Upload date:
  • Size: 19.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.2

File hashes

Hashes for sleeper_service-0.11.0.tar.gz
Algorithm Hash digest
SHA256 757a5f04f5633e79a242213a7b91494725316ed06f9fd82d5caa2ee26aa99520
MD5 54a3a1322e90197421178c278ef67663
BLAKE2b-256 b7696cd0418adf7412c67b513050892c888284f315a5326086a6964e027626cb

See more details on using hashes here.

File details

Details for the file sleeper_service-0.11.0-py3-none-any.whl.

File metadata

File hashes

Hashes for sleeper_service-0.11.0-py3-none-any.whl
Algorithm Hash digest
SHA256 361b086bc2d58e8d662f922be763f1abd70571dda175e2f8d5ec5a142a61ec2a
MD5 189103a334a322dcd6f538a368bc3758
BLAKE2b-256 3f6e1c7400e44a45c6876e4f0b4db2ee0d688a5538b617ca2d395be0695bcab8

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page