1
0

themagic.c 3.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. #include <ctype.h>
  2. #include <stdlib.h>
  3. #include <stdio.h>
  4. #include <mach/mach_port.h>
  5. #include <mach/mach_interface.h>
  6. #include <mach/mach_init.h>
  7. #include <IOKit/pwr_mgt/IOPMLib.h>
  8. #include <IOKit/IOMessage.h>
  9. #define WEESLEEP_SUSPENDING "SUSPENDING\n"
  10. #define WEESLEEP_WAKINGUP "WAKINGUP\n"
  11. io_connect_t root_port;
  12. void SleepCallBack(void* refCon, io_service_t service, natural_t messageType, void* messageArgument)
  13. {
  14. char* msg;
  15. switch (messageType) {
  16. case kIOMessageCanSystemSleep:
  17. /* Idle sleep is about to kick in. This message will not be sent for forced sleep.
  18. Applications have a chance to prevent sleep by calling IOCancelPowerChange.
  19. Most applications should not prevent idle sleep.
  20. Power Management waits up to 30 seconds for you to either allow or deny idle
  21. sleep. If you don't acknowledge this power change by calling either
  22. IOAllowPowerChange or IOCancelPowerChange, the system will wait 30
  23. seconds then go to sleep.
  24. */
  25. IOAllowPowerChange(root_port, (long)messageArgument);
  26. break;
  27. case kIOMessageSystemWillSleep:
  28. /* The system WILL go to sleep. If you do not call IOAllowPowerChange or
  29. IOCancelPowerChange to acknowledge this message, sleep will be
  30. delayed by 30 seconds.
  31. NOTE: If you call IOCancelPowerChange to deny sleep it returns
  32. kIOReturnSuccess, however the system WILL still go to sleep.
  33. */
  34. write(1, WEESLEEP_SUSPENDING, strlen(WEESLEEP_SUSPENDING));
  35. IOAllowPowerChange(root_port, (long)messageArgument);
  36. break;
  37. case kIOMessageSystemWillPowerOn:
  38. //System has started the wake up process...
  39. break;
  40. case kIOMessageSystemHasPoweredOn:
  41. write(1, WEESLEEP_WAKINGUP, strlen(WEESLEEP_WAKINGUP));
  42. //System has finished waking up...
  43. break;
  44. default:
  45. break;
  46. }
  47. }
  48. int main(int argc, char** argv)
  49. {
  50. //
  51. // From https://developer.apple.com/library/mac/qa/qa1340/_index.html
  52. // I have basically no idea how this works :)
  53. //
  54. // notification port allocated by IORegisterForSystemPower
  55. IONotificationPortRef notifyPortRef;
  56. // notifier object, used to deregister later
  57. io_object_t notifierObject;
  58. // this parameter is passed to the callback
  59. void* refCon;
  60. // register to receive system sleep notifications
  61. root_port = IORegisterForSystemPower(refCon, &notifyPortRef, SleepCallBack, &notifierObject);
  62. if (root_port == 0) {
  63. printf("IORegisterForSystemPower failed\n");
  64. return 1;
  65. }
  66. // add the notification port to the application runloop
  67. CFRunLoopAddSource(CFRunLoopGetCurrent(), IONotificationPortGetRunLoopSource(notifyPortRef), kCFRunLoopCommonModes);
  68. /* Start the run loop to receive sleep notifications. Don't call CFRunLoopRun if this code
  69. is running on the main thread of a Cocoa or Carbon application. Cocoa and Carbon
  70. manage the main thread's run loop for you as part of their event handling
  71. mechanisms.
  72. */
  73. CFRunLoopRun();
  74. //Not reached, CFRunLoopRun doesn't return in this case.
  75. return 0;
  76. }