views:

502

answers:

4

First time poster, be gentle ;-)

I'm writing an audio app (in C++) which runs as a Windows service, uses WASAPI to take samples from the line in jack, and does some processing on it.

Something I've noticed is that when my app is "recording", Windows won't automatically suspend or hibernate.

I've registered for power event notifications and, if I push the suspend button myself, my service gets the appropriate power events and handles them ok. If I leave the system to suspend on its own, the power events are never received.

If I remove the bits of code where I reference WASAPI, the power events are received as normal on both manual and automatic suspend. So it seems like there's something about using WASAPI that tells Windows to ignore the automatic suspend timer.

Can anyone help explain this behavior, and is there anything I can do to stop it? I don't want my app to be one of those which misbehaves and prevents systems from suspending..

A: 

I believe there's a function in the power management API which allows an app to tell the OS that it doesn't want the system to go into power save mode during some time (I think it's an on/off type function). If something in WASAPI is calling that method, there may be nothing you can do. This would make sense with the hardware button behavior, since the power management service isn't forced to honor the app request depending on how the power mode is activated.

As for work-around, I don't know. One thing I might try is to read the power save timeout information from the power management API, and then suspend recording if the system is nearing the power save threshold; I have no idea how hard that would be though. Good luck. :)

Nick
A: 

One thing I might try is to read the power save timeout information from the power management API, and then suspend recording if the system is nearing the power save threshold;

A good idea - but quite hard I think. The power save timeout should be readable using power management API, but you'd also need to know the current user input idle state, which is not readable from a Windows service.

+4  A: 

Unfortuantely there's no mechanism to do what you want - opening an audio stream prevents power state transitions as does opening a file up over the network and any one of a number of other things.

This is a function of the audio driver (portcls.sys) and not WASAPI and is not a new behavior for Vista - I believe that XP and Win2K had similar behaviors (although power state transitions are much more reliable on Vista than they were on XP and Win2K so users tend to depend on them more).

On Windows 7 you can use the "powercfg -requests" to find if any parts of the system are preventing a machine from entering sleep. More information on that can be found here

Larry Osterman
I didn't know about the -requests switch. Thanks a lot! Big fan here. ;)
macbirdie
+1  A: 

Many thanks to Larry for confirming this behaviour is by design and not me doing something silly.

To work around this issue I used the Win32 CallNtPowerInformation() API to retrieve the system idle timer:

SYSTEM_POWER_INFORMATION spi = {0};
NTSTATUS status = CallNtPowerInformation(SystemPowerInformation, NULL, 0, 
                                         &spi, sizeof(spi));

if (NT_SUCCESS(status) && (spi.TimeRemaining==0))
{
    // should have gone to sleep
}

The spi.TimeRemaining member counts down (in seconds) from the time specified by the user in Control Panel e.g. "System standby after 1 hour", and gets reset whenever CPU usage (as a percentage) rises above spi.MaxIdlenessAllowed.

If spi.TimeRemaining ever reaches zero, the system should have gone to sleep, so I close all my WASAPI handles and let it do so.

snowcrash09