MythTV  master
mythpowerosx.cpp
Go to the documentation of this file.
1 // MythTV
3 #include "mythlogging.h"
4 #include "mythpowerosx.h"
5 
6 // OSX
7 #include <IOKit/ps/IOPowerSources.h>
8 #include <IOKit/ps/IOPSKeys.h>
9 #include <AvailabilityMacros.h>
10 
11 // kIOMasterPortDefault was deprecated in OS_X 12
12 // kIOMainPortDefault defaults to a main/master port value of 0
13 static constexpr int8_t kMythIOMainPortDefault { 0 };
14 
15 #define LOC QString("PowerOSX: ")
16 
17 static OSStatus SendAppleEventToSystemProcess(AEEventID EventToSend);
18 
25 {
27 }
28 
30 {
32 
33  // deregister power status change notifications
34  CFRunLoopRemoveSource(CFRunLoopGetCurrent(),
35  IONotificationPortGetRunLoopSource(m_powerNotifyPort),
36  kCFRunLoopDefaultMode );
37  IODeregisterForSystemPower(&m_powerNotifier);
38  IOServiceClose(m_rootPowerDomain);
39  IONotificationPortDestroy(m_powerNotifyPort);
40 
41  // deregister power source change notifcations
42  if (m_powerRef)
43  {
44  CFRunLoopRemoveSource(CFRunLoopGetCurrent(), m_powerRef, kCFRunLoopDefaultMode);
45  CFRelease(m_powerRef);
46  }
47 }
48 
50 {
52 
53  // Register for power status updates
54  m_rootPowerDomain = IORegisterForSystemPower(this, &m_powerNotifyPort, PowerCallBack, &m_powerNotifier);
56  {
57  CFRunLoopAddSource(CFRunLoopGetCurrent(),
58  IONotificationPortGetRunLoopSource(m_powerNotifyPort),
59  kCFRunLoopDefaultMode);
60  }
61  else
62  {
63  LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to setup power status callback");
64  }
65 
66  // Is there a battery?
67  CFArrayRef batteryinfo = NULL;
68  if (IOPMCopyBatteryInfo(kMythIOMainPortDefault, &batteryinfo) == kIOReturnSuccess)
69  {
70  CFRelease(batteryinfo);
71 
72  // register for notification of power source changes
73  m_powerRef = IOPSNotificationCreateRunLoopSource(PowerSourceCallBack, this);
74  if (m_powerRef)
75  {
76  CFRunLoopAddSource(CFRunLoopGetCurrent(), m_powerRef, kCFRunLoopDefaultMode);
77  Refresh();
78  }
79  }
80 
81  if (!m_powerRef)
82  LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to setup power source callback");
83 
85  if (IOPMSleepEnabled())
87 
89 }
90 
91 bool MythPowerOSX::DoFeature(bool /*Delayed*/)
92 {
94  return false;
95 
97  AEEventID event = 0;
98  switch (m_scheduledFeature)
99  {
100  case FeatureSuspend: event = kAESleep; break;
101  case FeatureShutdown: event = kAEShutDown; break;
102  case FeatureRestart: event = kAERestart; break;
103  default: return false;
104  }
105  return SendAppleEventToSystemProcess(event) == noErr;
106 }
107 
109 {
110  if (!m_powerRef)
111  return;
112 
113  int newlevel = UnknownPower;
114  CFTypeRef info = IOPSCopyPowerSourcesInfo();
115  CFArrayRef list = IOPSCopyPowerSourcesList(info);
116 
117  for (int i = 0; i < CFArrayGetCount(list); i++)
118  {
119  CFTypeRef source = CFArrayGetValueAtIndex(list, i);
120  CFDictionaryRef description = IOPSGetPowerSourceDescription(info, source);
121 
122  if (static_cast<CFBooleanRef>(CFDictionaryGetValue(description, CFSTR(kIOPSIsPresentKey))) == kCFBooleanFalse)
123  continue;
124 
125  auto type = static_cast<CFStringRef>(CFDictionaryGetValue(description, CFSTR(kIOPSTransportTypeKey)));
126  if (type && CFStringCompare(type, CFSTR(kIOPSInternalType), 0) == kCFCompareEqualTo)
127  {
128  auto state = static_cast<CFStringRef>(CFDictionaryGetValue(description, CFSTR(kIOPSPowerSourceStateKey)));
129  if (state && CFStringCompare(state, CFSTR(kIOPSACPowerValue), 0) == kCFCompareEqualTo)
130  {
131  newlevel = ACPower;
132  }
133  else if (state && CFStringCompare(state, CFSTR(kIOPSBatteryPowerValue), 0) == kCFCompareEqualTo)
134  {
135  int32_t current;
136  int32_t max;
137  auto capacity = static_cast<CFNumberRef>(CFDictionaryGetValue(description, CFSTR(kIOPSCurrentCapacityKey)));
138  CFNumberGetValue(capacity, kCFNumberSInt32Type, &current);
139  capacity = static_cast<CFNumberRef>(CFDictionaryGetValue(description, CFSTR(kIOPSMaxCapacityKey)));
140  CFNumberGetValue(capacity, kCFNumberSInt32Type, &max);
141  newlevel = static_cast<int>(((static_cast<float>(current) /
142  (static_cast<float>(max))) * 100.0F));
143  }
144  else
145  {
146  newlevel = UnknownPower;
147  }
148  }
149  }
150 
151  CFRelease(list);
152  CFRelease(info);
153  PowerLevelChanged(newlevel);
154 }
155 
161 {
163  auto* power = static_cast<MythPowerOSX*>(Reference);
164  if (power)
165  power->Refresh();
166 }
167 
174 void MythPowerOSX::PowerCallBack(void *Reference, io_service_t /*unused*/,
175  natural_t Type, void *Data)
176 {
178  auto* power = static_cast<MythPowerOSX*>(Reference);
179  if (!power)
180  return;
181 
182  switch (Type)
183  {
184  case kIOMessageCanSystemPowerOff:
185  IOAllowPowerChange(power->m_rootPowerDomain, reinterpret_cast<intptr_t>(Data));
186  power->FeatureHappening(FeatureShutdown);
187  break;
188  case kIOMessageCanSystemSleep:
189  IOAllowPowerChange(power->m_rootPowerDomain, reinterpret_cast<intptr_t>(Data));
190  power->FeatureHappening(FeatureSuspend);
191  break;
192  case kIOMessageSystemWillPowerOff:
193  IOAllowPowerChange(power->m_rootPowerDomain, reinterpret_cast<intptr_t>(Data));
194  power->FeatureHappening(FeatureShutdown);
195  break;
196  case kIOMessageSystemWillRestart:
197  IOAllowPowerChange(power->m_rootPowerDomain, reinterpret_cast<intptr_t>(Data));
198  power->FeatureHappening(FeatureRestart);
199  break;
200  case kIOMessageSystemWillSleep:
201  IOAllowPowerChange(power->m_rootPowerDomain, reinterpret_cast<intptr_t>(Data));
202  power->FeatureHappening(FeatureSuspend);
203  break;
204  case kIOMessageSystemHasPoweredOn:
205  power->DidWakeUp();
206  break;
207  }
208 }
209 
210 // see Technical Q&A QA1134
211 OSStatus SendAppleEventToSystemProcess(AEEventID EventToSend)
212 {
213  AEAddressDesc targetDesc;
214  static const ProcessSerialNumber kPSNOfSystemProcess = { 0, kSystemProcess };
215  AppleEvent eventReply = { typeNull, nullptr };
216  AppleEvent appleEventToSend = { typeNull, nullptr };
217 
218  OSStatus error = noErr;
219  error = AECreateDesc(typeProcessSerialNumber, &kPSNOfSystemProcess,
220  sizeof(kPSNOfSystemProcess), &targetDesc);
221  if (error != noErr)
222  return error;
223 
224  error = AECreateAppleEvent(kCoreEventClass, EventToSend, &targetDesc,
225  kAutoGenerateReturnID, kAnyTransactionID, &appleEventToSend);
226  AEDisposeDesc(&targetDesc);
227  if (error != noErr)
228  return error;
229 
230  error = AESendMessage(&appleEventToSend, &eventReply, kAENormalPriority, kAEDefaultTimeout);
231  AEDisposeDesc(&appleEventToSend);
232  if (error != noErr)
233  return error;
234 
235  AEDisposeDesc(&eventReply);
236  return error;
237 }
MythPowerOSX
Definition: mythpowerosx.h:15
MythPower::ACPower
@ ACPower
Definition: mythpower.h:27
MythPowerOSX::MythPowerOSX
MythPowerOSX()
Power management for OSX.
Definition: mythpowerosx.cpp:24
MythPowerOSX::~MythPowerOSX
~MythPowerOSX() override
Definition: mythpowerosx.cpp:29
MythPower::FeatureSuspend
@ FeatureSuspend
Definition: mythpower.h:39
kMythIOMainPortDefault
static constexpr int8_t kMythIOMainPortDefault
Definition: mythpowerosx.cpp:13
error
static void error(const char *str,...)
Definition: vbi.cpp:36
MythPowerOSX::DoFeature
bool DoFeature(bool Delayed=false) override
Definition: mythpowerosx.cpp:91
MythPowerOSX::PowerCallBack
static void PowerCallBack(void *Reference, io_service_t Service, natural_t Type, void *Data)
Receive notification of power status changes.
Definition: mythpowerosx.cpp:174
MythPower::m_scheduledFeature
Feature m_scheduledFeature
Definition: mythpower.h:92
MythPower::UnknownPower
@ UnknownPower
Definition: mythpower.h:31
MythPower::FeatureHappening
virtual void FeatureHappening(Feature Spontaneous=FeatureNone)
Signal to the rest of MythTV that the given feature will happen now.
Definition: mythpower.cpp:298
MythPowerOSX::Init
void Init(void) override
Definition: mythpowerosx.cpp:49
MythPower::FeatureShutdown
@ FeatureShutdown
Definition: mythpower.h:38
mythcocoautils.h
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
SendAppleEventToSystemProcess
static OSStatus SendAppleEventToSystemProcess(AEEventID EventToSend)
Definition: mythpowerosx.cpp:211
MythDate::current
QDateTime current(bool stripped)
Returns current Date and Time in UTC.
Definition: mythdate.cpp:14
MythPowerOSX::m_powerNotifier
io_object_t m_powerNotifier
Definition: mythpowerosx.h:38
mythlogging.h
MythPowerOSX::m_powerRef
CFRunLoopSourceRef m_powerRef
Definition: mythpowerosx.h:36
MythPower::PowerLevelChanged
void PowerLevelChanged(int Level)
Definition: mythpower.cpp:342
mythpowerosx.h
MythPower::m_features
Features m_features
Definition: mythpower.h:91
MythPowerOSX::PowerSourceCallBack
static void PowerSourceCallBack(void *Reference)
Receive notification of changes to the power supply.
Definition: mythpowerosx.cpp:160
MythPowerOSX::Refresh
void Refresh(void) override
Definition: mythpowerosx.cpp:108
MythPowerOSX::m_rootPowerDomain
io_connect_t m_rootPowerDomain
Definition: mythpowerosx.h:37
MythPower::FeatureRestart
@ FeatureRestart
Definition: mythpower.h:41
CocoaAutoReleasePool
Definition: mythcocoautils.h:13
LOC
#define LOC
Definition: mythpowerosx.cpp:15
MythPowerOSX::m_powerNotifyPort
IONotificationPortRef m_powerNotifyPort
Definition: mythpowerosx.h:39
MythPower::Init
virtual void Init(void)
Definition: mythpower.cpp:127