Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Receiving power notifications (especially shutdown) on Mac OSX

Tags:

c

macos

shutdown

I'm writing an application in C for the Mac (Leopard) that needs to do some work on receipt of power notifications, e.g. sleep, wake-up, shutdown, restart. It runs via launchd as a launchagent on login then begins monitoring for notifications. The code I'm using to do this is as follows:

/* ask for power notifications */
static void StartPowerNotification(void)
{
    static io_connect_t rootPort;   
    IONotificationPortRef notificationPort;
    io_object_t notifier;

    rootPort = IORegisterForSystemPower(&rootPort, &notificationPort, 
                                        PowerCallback, &notifier);
    if (!rootPort) 
        exit (1);

    CFRunLoopAddSource (CFRunLoopGetCurrent(),  
                        IONotificationPortGetRunLoopSource(notificationPort), 
                        kCFRunLoopDefaultMode);
}

/* perform actions on receipt of power notifications */
void PowerCallback (void *rootPort, io_service_t y, 
                    natural_t msgType, void *msgArgument)
{
    switch (msgType) 
    {
        case kIOMessageSystemWillSleep:
            /* perform sleep actions */
            break;

        case kIOMessageSystemHasPoweredOn:
            /* perform wakeup actions */
            break;

        case kIOMessageSystemWillRestart:
            /* perform restart actions */
            break;

        case kIOMessageSystemWillPowerOff:
            /* perform shutdown actions */
            break;
    }
}

However, only the top two for sleep and wake (kIOMessageSystemWillSleep and kIOMessageSystemHasPoweredOn) ever get called. I never get any notifcations for restart or shutdown (kIOMessageSystemWillRestart and kIOMessageSystemWillPowerOff).

Am I doing something wrong? Or is there another API that would give me the restart and shutdown notifications? I'd prefer to keep it as a C program (as thats what I'm familiar with) but am open to any sensible suggestions of alternatives (I've had a look at login/logout hooks but these seem to be deprecated in favour of launchd).

Thanks in advance for any help/tips!

like image 988
binarybob Avatar asked Aug 24 '09 08:08

binarybob


People also ask

How do I turn off System Preferences notifications on Mac?

To change these preferences, choose Apple menu > System Preferences, click Notifications & Focus , then click Notifications. Select an app or website on the left, then view or change settings on the right. The options vary by app. Customize notifications for an app or website.

How do I turn off message banners on Mac?

Manage notifications by conversation In the Messages app on your Mac, select a conversation. Click the Details button in the top-right corner, then select Hide Alerts to stop notifications; to get message notifications again, deselect Hide Alerts.

What is the Notification Center on Mac?

In Notification Center on your Mac, you can catch up on notifications you missed and use widgets to view appointments, birthdays, the weather, top headlines, and more right from the desktop.


2 Answers

I know you can register for the NSWorkspaceWillPowerOffNotification notification from NSWorkspace, which is not a C function but does work.

#import <AppKit/AppKit.h>
#import "WorkspaceResponder.h"

int main (int argc, const char * argv[]) {
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
    NSNotificationCenter *nc = [[NSWorkspace sharedWorkspace] notificationCenter];
    WorkspaceResponder *mainController = [[WorkspaceResponder alloc] init];

    //register for shutdown notications
    [nc addObserver:mainController
selector:@selector(computerWillShutDownNotification:)
          name:NSWorkspaceWillPowerOffNotification object:nil];
    [[NSRunLoop currentRunLoop] run];
    [pool release];
    return 0;
}

Then in WorkspaceResponder.m:

- (void) computerWillShutDownNotification:(NSNotification *)notification {
    NSLog(@"Received Shutdown Notification");
}
like image 100
Rob Keniger Avatar answered Oct 17 '22 12:10

Rob Keniger


Using IORegisterForSystemPower doesn't provide the events you seek. Quoting from function documentation :

/*! @function IORegisterForSystemPower

@abstract Connects the caller to the Root Power Domain IOService for the purpose of receiving sleep & wake notifications for the system.

Does not provide system shutdown and restart notifications.

like image 34
Irad K Avatar answered Oct 17 '22 12:10

Irad K