Sleep Apple Event not being issued in System Process

xedge

macrumors newbie
Original poster
Oct 25, 2017
4
0
Hi everyone!

I'm developing my first Mac OS X application, and I'm having some problems with an AppleEvent that I want to send to the system.

Firstly, I found an article on how to programmatically shutdown, restart, sleep or logout an apple computer Link, which is the main objective I want to achieve with the application.

Well, I've tested that code and works perfectly fine as it is, but what I need to do is to use it on a GUI and run it on a cycle loop defined by the user so the computer will sleep/wake up or restart (power off/power on) automatically when certain period of time has passed.

This is for testing purposes on certain PCI SSDs, so when the computer can't wake up/restart itself the piece it's considered a failure and it's segregated.

I'm totally new on the Objective C/Swift programming environment, I have read some tutorials, but can't quite understand Objective C completely whereas I do understand Swift.

I adapted the code and bridged the two languages so I can make use of an Objective-C object that has the functions that perform the previous mentioned processes.

The problem here is:

*The code prints a certain line that says that the computer is going to sleep, (which was on the example code previously provided), but now as it interfaces with Swift and the GUI it appears to do nothing but show the date I formatted to be shown on a TextField I declared before.

I really don't know what's going on here, and I'm sorry if I'm being too clumsy on my coding but I will really appreciate any help.

The code of every important file on the project is shown below:

classFunctions.m

Code:
#include <stdio.h>
#include <CoreServices/CoreServices.h>
#include <Carbon/Carbon.h>
#include <Foundation/Foundation.h>
#import "Header.h"

@implementation intOb

OSStatus SendAppleEventToSystemProcess(AEEventID EventToSend);
int executeSleep(void);
int executeRestart(void);
int executeShutDown(void);


- (OSStatus) SendAppleEventToSystemProcess: (AEEventID)EventToSend{
   AEAddressDesc targetDesc;
   static const ProcessSerialNumber kPSNOfSystemProcess = { 0, kSystemProcess };
   AppleEvent eventReply = {typeNull, NULL};
   AppleEvent appleEventToSend = {typeNull, NULL};
   
   OSStatus error = noErr;
   
   error = AECreateDesc(typeProcessSerialNumber, &kPSNOfSystemProcess,
                        sizeof(kPSNOfSystemProcess), &targetDesc);
   
   if (error != noErr)
   {
       return(error);
   }
   
   error = AECreateAppleEvent(kCoreEventClass, EventToSend, &targetDesc, kAutoGenerateReturnID, kAnyTransactionID, &appleEventToSend);
   
   AEDisposeDesc(&targetDesc);
   if (error != noErr)
   {
       return(error);
   }
   
   error = AESend(&appleEventToSend, &eventReply, kAENoReply,
                  kAENormalPriority, kAEDefaultTimeout, NULL, NULL);
   AEDisposeDesc(&appleEventToSend);
   if (error != noErr)
   {
       return(error);
   }
   
   AEDisposeDesc(&eventReply);
   
   return(error);
}


- (int) executeSleep{
   OSStatus error = noErr;
   error = SendAppleEventToSystemProcess(kAESleep);
   if (error == noErr)
   {
       printf("Computer is going to sleep!\n");
       return error;
   }
   else
   {
       printf("Computer wouldn't sleep");
       return error;
   }
}

- (int) executeRestart{
   OSStatus error = noErr;
   error = SendAppleEventToSystemProcess(kAERestart);
   if (error == noErr)
   {
       printf("Computer is going to restart!\n");
       return error;
   }
   else
   {
       printf("Computer wouldn't restart\n");
       return error;
   }
}

- (int) executeShutDown{
   OSStatus error = noErr;
   error = SendAppleEventToSystemProcess(kAEShutDown);
   if (error == noErr)
   {
       printf("Computer is going to shutdown!\n");
       return error;
   }
   else
   {
       printf("Computer wouldn't shutdown\n");
       return error;
   }
}
@end

OSStatus SendAppleEventToSystemProcess(AEEventID EventToSend);

int executeSleep(void);
int executeRestart(void);
int executeShutDown(void);

OSStatus SendAppleEventToSystemProcess(AEEventID EventToSend)
{
   AEAddressDesc targetDesc;
   static const ProcessSerialNumber kPSNOfSystemProcess = { 0, kSystemProcess };
   AppleEvent eventReply = {typeNull, NULL};
   AppleEvent appleEventToSend = {typeNull, NULL};
   
   OSStatus error = noErr;
   
   error = AECreateDesc(typeProcessSerialNumber, &kPSNOfSystemProcess,
                        sizeof(kPSNOfSystemProcess), &targetDesc);
   
   if (error != noErr)
   {
       return(error);
   }
   
   error = AECreateAppleEvent(kCoreEventClass, EventToSend, &targetDesc,
                              kAutoGenerateReturnID, kAnyTransactionID, &appleEventToSend);
   
   AEDisposeDesc(&targetDesc);
   if (error != noErr)
   {
       return(error);
   }
   
   error = AESend(&appleEventToSend, &eventReply, kAENoReply,
                  kAENormalPriority, kAEDefaultTimeout, NULL, NULL);
   AEDisposeDesc(&appleEventToSend);
   if (error != noErr)
   {
       return(error);
   }
   
   AEDisposeDesc(&eventReply);
   
   return(error);
}

int executeRestart(void){
   OSStatus error = noErr;
   error = SendAppleEventToSystemProcess(kAERestart);
   if (error == noErr)
   {
       printf("Computer is going to restart!\n");
       return error;
   }
   else
   {
       printf("Computer wouldn't restart\n");
       return error;
   }
}

int executeSleep(void){
   OSStatus error = noErr;
   error = SendAppleEventToSystemProcess(kAESleep);
   if (error == noErr)
   {
       printf("Computer is going to sleep!\n");
       return error;
   }
   else
   {
       printf("Computer wouldn't sleep");
       return error;
   }
}

int executeShutDown(void){
   OSStatus error = noErr;
   error = SendAppleEventToSystemProcess(kAEShutDown);
   if (error == noErr)
   {
       printf("Computer is going to shutdown!\n");
       return error;
   }
   else
   {
       printf("Computer wouldn't shutdown\n");
       return error;
   }
}
Header.h

Code:
#import <Foundation/Foundation.h>

@interface intOb : NSObject

//@property (nonatomic, strong) AEEventID *EventToSend;
//@property (nonatomic, strong) NSString *EventToSend;

- (OSStatus) SendAppleEventToSystemProcess: (AEEventID)EventToSend;
- (int) executeSleep;
- (int) executeRestart;
- (int) executeShutDown;

@end
[/B]
FFTest-Bridging-Header.h

Code:
#import "Header.h"
ViewController.swift

Code:
import Cocoa
import CoreServices

class ViewController: NSViewController {
   //MARK: Properties
   
   @IBOutlet weak var workOrderTextField: NSTextField!
   @IBOutlet weak var partNumberTextField: NSTextField!
   @IBOutlet weak var operatorTextField: NSTextField!
   @IBOutlet weak var stationPopUpBtn: NSPopUpButton!
   @IBOutlet weak var confirmBtn: NSButton!
   @IBOutlet weak var serialNumberTextField: NSTextField!
   @IBOutlet weak var validationStatusImage: NSImageView!
   @IBOutlet weak var validationErrorBtn: NSButton!
   @IBOutlet weak var wakeTimeTextField: NSTextField!
   
   @IBOutlet weak var sleepTimeTextField: NSTextField!
   @IBOutlet weak var testLengthTextField: NSTextField!
   @IBOutlet weak var sleepCtDownLabel: NSTextField!
   @IBOutlet weak var sleepCycleCountLabel: NSTextField!
   @IBOutlet weak var sleepTestStartedLabel: NSTextField!
   @IBOutlet weak var lastCycleLabel: NSTextField!
   @IBOutlet weak var totalTimeLabel: NSTextField!
   
   @IBOutlet weak var sleepStatusLabel: NSTextField!
   @IBOutlet weak var sleepResetBtn: NSButton!
   @IBOutlet weak var sleepStopBtn: NSButton!
   @IBOutlet weak var sleepStartBtn: NSButton!
   @IBOutlet weak var countdownTextField: NSTextField!
   @IBOutlet weak var pwrOffLabel: NSTextField!
   @IBOutlet weak var restartCtDownLabel: NSTextField!
   @IBOutlet weak var restartTestStartedLabel: NSTextField!
   @IBOutlet weak var restartCountLabel: NSTextField!
   
   @IBOutlet weak var restartStatusLabel: NSTextField!
   @IBOutlet weak var restartResetBtn: NSButton!
   @IBOutlet weak var restartStartBtn: NSButton!
   let obj: intOb = intOb()
   
   @objc func systemSleep() -> Void{
       obj.executeSleep()
   }
   
   func getDate() -> String{
       let currentDateTime = Date()
       let formatter = DateFormatter()
       formatter.timeStyle = .short
       formatter.dateStyle = .short
       return formatter.string(from: currentDateTime)
   }
   
   override func viewDidLoad() {
       super.viewDidLoad()
       
       // Do any additional setup after loading the view.
   }
   
   override var representedObject: Any? {
       didSet {
           // Update the view, if already loaded.
       }
   }
   
   //MARK: Actions
   
   @IBAction func StartSleep(_ sender: Any) {
   sleepTestStartedLabel.stringValue = getDate()
       obj.executeSleep()
   }
   
}
[/B]
 

0002378

Suspended
May 28, 2017
676
631
Hi, I'm sorry that I don't have a solution to your question, but your thread sparked my interest because my own app needs to do kind of the opposite - it needs to respond to a sleep/wake up event.

Since you seem to know about this kind of thing, can you point me to how I would do that ? (In Swift, preferably)
 

xedge

macrumors newbie
Original poster
Oct 25, 2017
4
0
Hi, I'm sorry that I don't have a solution to your question, but your thread sparked my interest because my own app needs to do kind of the opposite - it needs to respond to a sleep/wake up event.

Since you seem to know about this kind of thing, can you point me to how I would do that ? (In Swift, preferably)
Could you show me relevant parts of your code so I can help you?
 

0002378

Suspended
May 28, 2017
676
631
Could you show me relevant parts of your code so I can help you?
Well, I haven't written the part that responds to such events, so I'm just looking to find out how, in general, one would respond to sleep/wake events.

For instance, do I need to override a method from AppDelegate() ? If so, which method ? Or, what else do I need to do ?

I could share code with you, but it would be of no help to you, because I don't even know where the new code will fit in.

Hope this makes sense.
 

xedge

macrumors newbie
Original poster
Oct 25, 2017
4
0
Well, I haven't written the part that responds to such events, so I'm just looking to find out how, in general, one would respond to sleep/wake events.

For instance, do I need to override a method from AppDelegate() ? If so, which method ? Or, what else do I need to do ?

I could share code with you, but it would be of no help to you, because I don't even know where the new code will fit in.

Hope this makes sense.
I don't quite get the point of what you want to do..., I assume your application may communicate with the user, but how it's supposed to respond to a sleep/wake event? What does it need to do? Should it prompt a message? Fire an alarm clock?

Because maybe you don't really need to fire an AppleEvent, maybe just looking through the logs if certain event happened or something like that.
 

0002378

Suspended
May 28, 2017
676
631
I don't quite get the point of what you want to do..., I assume your application may communicate with the user, but how it's supposed to respond to a sleep/wake event? What does it need to do? Should it prompt a message? Fire an alarm clock?

Because maybe you don't really need to fire an AppleEvent, maybe just looking through the logs if certain event happened or something like that.
Ok, I'll give you some context.

My app is an audio player for MacOS. When the user puts his machine to sleep, I would like to pause or shut down the audio engine (or otherwise release audio-related system resources), and resume the engine upon waking. So, I need to listen for, and respond to, the system going to sleep.

Like when a Macbook/MBP user closes the lid on his laptop, how will I know that that has happened ?

So, I'm not looking to fire such an event. I'm looking to respond to such an event. It's the inverse of firing an event.
 

chown33

Moderator
Staff member
Aug 9, 2009
8,350
4,315
Coruscant antipodal seas
My app is an audio player for MacOS. When the user puts his machine to sleep, I would like to pause or shut down the audio engine (or otherwise release audio-related system resources), and resume the engine upon waking. So, I need to listen for, and respond to, the system going to sleep.
I dont think you have to do anything.

If the system goes to sleep, then audio output should automatically stop. This is a consequence of the system going to sleep. Similarly, when the system wakes up, it should reinit the audio chips and such, so they're back where they were when the system went to sleep. It does this before resuming any apps that were active when the sleep occurred. You don't have to release resources, because the system should turn them off and then turn them back on, without your program doing anything at all.

The easiest way I can think of to illustrate this is to start the 'afplay' command in Terminal. Then shut the lid on your laptop. The audio should stops within several seconds. Leave the lid shut for at least 2 minutes. During this interval, afplay isn't playing audio, nor is it advancing through the samples, or doing anything else, because the system is asleep. Now, open the lid. The audio should recommence at roughly the same place it stopped.

Sleep is rather like swapping. The system does it automatically, and your program isn't usually aware of when it happens, unless it takes some specific measures in order to learn of it happening through other means. Example (in Obj-C, from 2014):
https://developer.apple.com/library/content/qa/qa1340/_index.html
 
  • Like
Reactions: 0002378

0002378

Suspended
May 28, 2017
676
631
I dont think you have to do anything.

If the system goes to sleep, then audio output should automatically stop. This is a consequence of the system going to sleep. Similarly, when the system wakes up, it should reinit the audio chips and such, so they're back where they were when the system went to sleep. It does this before resuming any apps that were active when the sleep occurred. You don't have to release resources, because the system should turn them off and then turn them back on, without your program doing anything at all.

The easiest way I can think of to illustrate this is to start the 'afplay' command in Terminal. Then shut the lid on your laptop. The audio should stops within several seconds. Leave the lid shut for at least 2 minutes. During this interval, afplay isn't playing audio, nor is it advancing through the samples, or doing anything else, because the system is asleep. Now, open the lid. The audio should recommence at roughly the same place it stopped.

Sleep is rather like swapping. The system does it automatically, and your program isn't usually aware of when it happens, unless it takes some specific measures in order to learn of it happening through other means. Example (in Obj-C, from 2014):
https://developer.apple.com/library/content/qa/qa1340/_index.html
Thanks, I know that the audio output should stop (and it does), but sometimes, when the system wakes up from a sleep with my app running, there is no audio output from the entire system. Only killing my app fixes this problem. No other app does this, so I'm convinced that my app is not doing something in response to sleep/wake states, that it should (or doing something it shouldn't).

So, I wanted to see if shutting down and resuming the audio engine in response to sleep/wake would help.