9

I am writing a Qt application that does some heavy computations, but on a Mac (potentially also on Windows but I currently have no way of checking this), the execution ceases as soon as the computer goes into sleeping mode.

I would like a way to continue the execution even when the screen goes to screensaver or on blank. Obviously you can ask the user to change his/her energy settings, but that's far from an ideal solution. Is there a proper way of doing this?

Yellow
  • 3,955
  • 6
  • 45
  • 74
  • 1
    Dunno if Qt has an API to do it, but for Mac this should work: http://stackoverflow.com/a/8461182/131930 – Jeremy Friesner May 14 '14 at 02:36
  • It's unclear to me whether with "sleep" you mean screensaver/display turned off (that should have no effect?) or suspend. Unless you're developing an interactive application like a video player, I'd consider it bad style if your application messes with my energy settings. – Frank Osterfeld May 14 '14 at 05:40
  • @FrankOsterfeld if the applications task is to perform a time consuming calculation, then its a viable reason to keep the mac from suspend or at least to have an option to prevent this. – Sebastian Lange May 14 '14 at 07:32
  • @Yellow you are probably stuck with the native api or at least i do not remember having seen a Qt implementation for that. – Sebastian Lange May 14 '14 at 07:33
  • @FrankOsterfeld: I mean the suspend state. Basically, I'm happy with the screen going to screensaver or on blank of course, but I don't want it to go into sleeping/suspend mode, as this would interrupt my calculations. I think that, given the fact that all this application is about is (reasonably) heavy computations that may run overnight, it's fair to expect it to 'mess' with the energy settings. – Yellow May 14 '14 at 08:33
  • Yellow: if I want my computer to not suspend to finish your calculations faster, I change my energy settings. Otherwise, your calculations are simply continued when I resume. I don't see why your program should interfere with what should be under the sovereignty of the system/the user. – Frank Osterfeld May 14 '14 at 18:46
  • 2
    Disagree it's a duplicate; whether/how the multi-platform Qt framework supports it via Qt APIs would be valuable information. – timday May 17 '14 at 09:41

4 Answers4

8

After a thorough search through the Qt 5.2 API, it seems that Qt doesn't offer any functionality to change the energy settings (so neither for Mac, nor any other operating system). I haven't found any indication that it's on their road map either.

A possible solution for Mac OSX using Apple's Objective-C API can be found here (thanks, @Kuba).

On Windows, power settings can be dealt with using the SetThreadExecutionState function (see this question, C#).

Community
  • 1
  • 1
Yellow
  • 3,955
  • 6
  • 45
  • 74
5

There are two aspects of this:

  1. Forced Sleep If the user intends the system to sleep, and you prevent it, your users may well curse you. Forced sleep is also part of energy and thermal management, and is vital to prevent data loss and avoid destruction of hardware and mitigate possible fire risk.

    When I close the lid of my laptop, it better go to sleep and if I find an app that tries to circumvent it, it better be free or else I'm calling my credit card company for a chargeback. It's that simple, and I hope it's easy to understand why it would be so.

  2. Idle Sleep What you want to do is not to prevent the system from going to sleep at all, but to only disable the idle sleep.

Disabling of idle sleep is covered in this answer.

Community
  • 1
  • 1
Kuba hasn't forgotten Monica
  • 95,931
  • 16
  • 151
  • 313
  • 1
    Thanks for the clarification. This sort of made sense in my head but I didn't know the right terms for it. Though the answer you link to is useful for native Mac programming, it is an Objective-C solution rather than a Qt/C++ solution. – Yellow May 17 '14 at 09:16
  • @Yellow There is no Qt/C++ solution. You can freely use Objective-C/C++ from a Qt project. – Kuba hasn't forgotten Monica May 27 '14 at 20:37
2

If you want to avoid the Objective-C API, there's a C-based API underlying it. You can call IOPMAssertionCreateWithDescription() with an assertion type of kIOPMAssertionTypePreventUserIdleSystemSleep. That gives you an assertion ID reference. You cancel the assertion using IOPMAssertionRelease() to match the create call and any IOPMAssertionRetain() calls you may have made.

CFURLRef bundleURL = CFBundleCopyBundleURL(CFBundleGetMainBundle());
CFStringRef bundlePath = CFURLCopyFileSystemPath(bundleURL, kCFURLPOSIXPathStyle);
CFRelease(bundleURL);

IOPMAssertionID assertion;
IOReturn result = IOPMAssertionCreateWithDescription(kIOPMAssertionTypePreventUserIdleSystemSleep,
    CFSTR("A name which makes sense for your app"),
    CFSTR("Some details"), CFSTR("A human-readable reason"),
    bundlePath, 0, NULL, &assertion);
CFRelease(bundlePath);
if (result != kIOReturnSuccess)
    /* handle error */;

// ... do computation ...

IOPMAssertionRelease(assertion);
Ken Thomases
  • 88,520
  • 7
  • 116
  • 154
0

There seems to be a command line utility "caffeinate" that prevents system from going to sleep. Here is an example of using this utility within QT framework:

https://github.com/githublucas420/KDE/blob/4436536a6a2beb1631f89968dfab566963dae073/plugins/screensaver-inhibit/screensaverinhibitplugin-macos.cpp

George Vinokhodov
  • 327
  • 1
  • 4
  • 10