Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Monitoring Screensaver Events in OSX

I want to monitor screensaver and lockscreen events on an OSX box. As a first pass, I'm fine with them just printing to the console.

Following the advice of another's question, I wrote some Objective C to listen for Cocoa Notifications for the com.apple.screensaver.didstart, com.apple.screensaver.didstop, com.apple.screenIsLocked, and com.apple.screenIsUnlocked events.

// ScreenSaverMonitor.h
#import <Foundation/NSObject.h>
#import <Foundation/NSNotification.h>

@interface ScreenSaverMonitor: NSObject {}
-(id) init;
-(void) receive: (NSNotification*) notification;
@end

// ScreenSaverMonitor.m
#import "ScreenSaverMonitor.h"
#import <Foundation/NSString.h>
#import <Foundation/NSDistributedNotificationCenter.h>
#import <Foundation/NSRunLoop.h>
#import <stdio.h>

@implementation ScreenSaverMonitor
-(id) init {
  NSDistributedNotificationCenter * center 
    = [NSDistributedNotificationCenter defaultCenter];

  [center addObserver: self
          selector:    @selector(receive:)
          name:        @"com.apple.screensaver.didstart"
          object:      nil
  ];
  [center addObserver: self
          selector:    @selector(receive:)
          name:        @"com.apple.screensaver.didstop"
          object:      nil
  ];
  [center addObserver: self
          selector:    @selector(receive:)
          name:        @"com.apple.screenIsLocked"
          object:      nil
  ];
  [center addObserver: self
          selector:    @selector(receive:)
          name:        @"com.apple.screenIsUnlocked"
          object:      nil
  ];
  printf("running loop... (^C to quit)");
  [[NSRunLoop currentRunLoop] run];
  printf("...ending loop");
  return self;
}
-(void) receive: (NSNotification*) notification {
  printf("%s\n", [[notification name] UTF8String] );
}
@end

// ScreenSaverMonitorMain.m
#import "ScreenSaverMonitor.h"

int main( int argc, char ** argv) {
  [[ScreenSaverMonitor alloc] init];
  return 0;
}

It compiles fine, but when I run it, I don't seem to observe any screensaver events (despite having the screensaver come on multiple times):

% gcc -Wall ScreenSaverMonitor.m ScreenSaverMonitorMain.m -o ScreenSaverMonitor -lobjc -framework Cocoa
% ./ScreenSaverMonitor
running loop (^C to quit)...
^C
%

My Objective C and Cocoa knowledge is very rusty, so I'm not sure if I'm using the framework wrong, or if I've registered for the wrong events (nor where to look to find out whether those are the right events or not).

So what is it I'm doing wrong?

like image 208
rampion Avatar asked Jun 05 '13 15:06

rampion


1 Answers

You've commented your problem already.

while(1); // busy wait's bad, I know, but easy to implement

The above is almost ALWAYS a bad idea.

NSDistributedNotificationCenter actually requires a running main thread NSRunLoop to operate.

http://developer.apple.com/library/ios/#documentation/cocoa/Conceptual/Notifications/Articles/NotificationCenters.html#//apple_ref/doc/uid/20000216-BAJGDAFC

Creating and spinning a run loop from the main() of a command line application on OS X is a fairly simple thing to do. There are plenty of examples available with a quick search.

like image 99
GoannaGuy Avatar answered Oct 08 '22 08:10

GoannaGuy