1 #include <cstdlib>
2 #include <sstream>
3 using namespace std;
4
5 #include <sys/time.h>
6 #include <unistd.h>
7
8 #include <CoreFoundation/CoreFoundation.h>
9 #include <CoreServices/CoreServices.h>
10 #include <IOKit/IOKitLib.h>
11
12 #include "config.h"
13
14 #include "keywords.h"
15 #include "Options.h"
16 #include "xpUtil.h"
17
18 #include "TimerMacAqua.h"
19
TimerMacAqua(const int w,const unsigned long h,const unsigned long i)20 TimerMacAqua::TimerMacAqua(const int w, const unsigned long h,
21 const unsigned long i) : Timer(w, h, i)
22 {
23 }
24
~TimerMacAqua()25 TimerMacAqua::~TimerMacAqua()
26 {
27 }
28
29 // returns false if the program should exit after this sleep
30 bool
Sleep()31 TimerMacAqua::Sleep()
32 {
33 // Sleep until the next update
34 gettimeofday(¤tTime_, NULL);
35 if (!SleepForTime(nextUpdate_ - currentTime_.tv_sec))
36 return(false);
37
38 // If the display has not been idle for idlewait_
39 // milliseconds, keep sleeping. Check every second until the
40 // display has been idle for long enough.
41 if (idlewait_ > 0)
42 {
43 unsigned long idle = GetSystemIdleTime();
44 Options *options = Options::getInstance();
45 if (options->Verbosity() > 0)
46 {
47 ostringstream msg;
48 msg << "Idle time is " << idle/1000 << " second";
49 if (idle/1000 != 1) msg << "s";
50 msg << endl;
51 xpMsg(msg.str(), __FILE__, __LINE__);
52 }
53 while (idle < idlewait_)
54 {
55 gettimeofday(¤tTime_, NULL);
56 if (!SleepForTime((idlewait_ - idle) / 1000))
57 return(false);
58 idle = GetSystemIdleTime();
59 }
60 }
61
62 // If the display has been idle for longer than hibernate_
63 // milliseconds, keep sleeping. Check every second until
64 // something happens.
65 if (hibernate_ > 0)
66 {
67 unsigned long idle = GetSystemIdleTime();
68 Options *options = Options::getInstance();
69 if (options->Verbosity() > 0 && idle > hibernate_)
70 xpMsg("Hibernating ...\n", __FILE__, __LINE__);
71
72 while (idle > hibernate_)
73 {
74 if (!SleepForTime(1))
75 return(false);
76 idle = GetSystemIdleTime();
77 }
78 }
79 return(true);
80 }
81
82 // return the system idle time in milliseconds This code is based on
83 // "idler", found at
84 // http://www.macosxlabs.org/tools_and_scripts/script_archive/script_archive.html
85 // Their copyright notice follows:
86
87 /*****************************************
88 * idler.c
89 *
90 * Uses IOKit to figure out the idle time of the system. The idle time
91 * is stored as a property of the IOHIDSystem class; the name is
92 * HIDIdleTime. Stored as a 64-bit int, measured in ns.
93 *
94 * The program itself just prints to stdout the time that the computer has
95 * been idle in seconds.
96 *
97 * Compile with gcc -Wall -framework IOKit -framework Carbon idler.c -o
98 * idler
99 *
100 * Copyright (c) 2003, Stanford University
101 * All rights reserved.
102 *
103 * Redistribution and use in source and binary forms, with or without
104 * modification, are permitted provided that the following conditions are
105 * met:
106 * Redistributions of source code must retain the above copyright notice,
107 * this list of conditions and the following disclaimer.
108 *
109 * Redistributions in binary form must reproduce the above copyright notice,
110 * this list of conditions and the following disclaimer in the documentation
111 * and/or other materials provided with the distribution.
112 *
113 * Neither the name of Stanford University nor the names of its contributors
114 * may be used to endorse or promote products derived from this software
115 * without specific prior written permission.
116 *
117 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
118 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
119 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
120 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
121 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
122 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
123 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
124 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
125 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
126 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
127 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
128 */
129 unsigned long
GetSystemIdleTime()130 TimerMacAqua::GetSystemIdleTime()
131 {
132 unsigned long idle;
133
134 mach_port_t masterPort;
135 io_iterator_t iter;
136 io_registry_entry_t curObj;
137
138 IOMasterPort(MACH_PORT_NULL, &masterPort);
139
140 /* Get IOHIDSystem */
141 IOServiceGetMatchingServices(masterPort,
142 IOServiceMatching("IOHIDSystem"),
143 &iter);
144 if (iter == 0)
145 {
146 xpWarn("Error accessing IOHIDSystem\n", __FILE__, __LINE__);
147 }
148
149 curObj = IOIteratorNext(iter);
150
151 if (curObj == 0)
152 {
153 xpWarn("Iterator's empty!\n", __FILE__, __LINE__);
154 }
155
156 CFMutableDictionaryRef properties = 0;
157 CFTypeRef obj;
158
159 if (IORegistryEntryCreateCFProperties(curObj, &properties,
160 kCFAllocatorDefault, 0)
161 == KERN_SUCCESS && properties != NULL)
162 {
163
164 obj = CFDictionaryGetValue(properties, CFSTR("HIDIdleTime"));
165 CFRetain(obj);
166 }
167 else
168 {
169 xpWarn("Couldn't grab properties of system\n", __FILE__, __LINE__);
170 obj = NULL;
171 }
172
173 if (obj)
174 {
175 uint64_t tHandle;
176
177 CFTypeID type = CFGetTypeID(obj);
178
179 if (type == CFDataGetTypeID())
180 {
181 CFDataGetBytes((CFDataRef) obj,
182 CFRangeMake(0, sizeof(tHandle)),
183 (UInt8*) &tHandle);
184 }
185 else if (type == CFNumberGetTypeID())
186 {
187 CFNumberGetValue((CFNumberRef)obj,
188 kCFNumberSInt64Type,
189 &tHandle);
190 }
191 else
192 {
193 ostringstream errMsg;
194 errMsg << (int) type << ": unsupported type\n";
195 xpWarn(errMsg.str(), __FILE__, __LINE__);
196 }
197
198 CFRelease(obj);
199
200 // tHandle is in nanoseconds, we want milliseconds
201 idle = static_cast<unsigned long> (tHandle / 1e6);
202 }
203 else
204 {
205 xpWarn("Can't find idle time\n", __FILE__, __LINE__);
206 }
207
208 /* Release our resources */
209 IOObjectRelease(curObj);
210 IOObjectRelease(iter);
211 CFRelease((CFTypeRef)properties);
212
213 return(idle);
214 }
215