forked from mttrb/antipopd
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathantipopd.m
executable file
·131 lines (99 loc) · 4.21 KB
/
antipopd.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
// antipopd
//
// Copyright (c) Matthew Robinson 2010, 2018
// Email: [email protected]
//
// See banner() below for a description of this program.
//
// This version of antipopd is released, like Robert Tomsick's version, under
// a Creative Commons Attribution Noncommercial Share Alike License 3.0,
// http://creativecommons.org/licenses/by-nc-sa/3.0/us
/*
clang -framework AppKit -framework IOKit -arch i386 -arch x86_64 -o antipopd antipopd.m
*/
#import <CoreFoundation/CoreFoundation.h>
#import <Foundation/Foundation.h>
#import <AppKit/AppKit.h>
#import <IOKit/ps/IOPowerSources.h>
#import <unistd.h>
#define ANTIPOPD_CONFIG "/usr/local/share/antipop/ac_only"
#define BATTERY_STATE CFSTR("State:/IOKit/PowerSources/InternalBattery-0")
#define POWER_SOURCE CFSTR("Power Source State")
#define INTERVAL 5 // seconds
static BOOL runOnACOnly = NO;
void banner() {
printf("antipopd\n\n");
printf("Copyright (c) Matthew Robinson 2010, 2018\n");
printf("Email: [email protected]\n\n");
printf("antipopd is a drop in replacement for Robert Tomsick's antipopd 1.0.2 bash\n");
printf("script which is available at http://www.tomsick.net/projects/antipop\n\n");
printf("antipopd is a utility program which keeps the audio system active to stop\n");
printf("the popping sound that can occur when OS X puts the audio system to sleep.\n");
printf("This is achieved by using the Speech Synthesizer system to speak a space,\n");
printf("which results in no audio output but keeps the audio system awake.\n\n");
printf("The benefit of this compiled version over the bash script is a reduction\n");
printf("in resource overheads. The bash script executes two expensive processes \n");
printf("(pmset and say) every ten seconds (one process if ac_only is set to 0).\n\n");
printf("This version of antipopd is released, like Robert Tomsick's version, under\n");
printf("a Creative Commons Attribution Noncommercial Share Alike License 3.0,\n");
printf("http://creativecommons.org/licenses/by-nc-sa/3.0/us\n\n");
}
NSSpeechSynthesizer *speech = nil;
// Timer callback that actually speaks the space
void speak(CFRunLoopTimerRef timer, void *info) {
if (!speech) {
speech = [[NSSpeechSynthesizer alloc] initWithVoice:nil];
}
// If we are only supposed to run on AC power
if (runOnACOnly) {
// and we don't have unlimited power remaining
if (IOPSGetTimeRemainingEstimate() != kIOPSTimeRemainingUnlimited) {
// then return without speaking
return;
}
}
[speech startSpeakingString:@" "];
}
// Check for the existance of the ac_only file, check the contents
// and set runOnACOnly as appropriate
void loadACOnlyConfig() {
// Try to open the ac_only config file
int fd = open(ANTIPOPD_CONFIG, O_RDONLY);
// If succesful look inside, otherwise proceed with runOnACOnly default
if (fd != -1) {
char buffer;
ssize_t result = read(fd, &buffer, 1);
// ...the first byte of the file is 1
if (result == 1 && buffer == '1') {
runOnACOnly = YES;
}
close(fd);
}
}
int main(int argc, char *argv[]) {
loadACOnlyConfig();
// Put an AutoreleasePool in place in case NSSpeechSynthesizer expects it
@autoreleasepool {
if (argc >= 2) { // if we have any parameter show the banner
banner();
exit(EXIT_SUCCESS);
}
CFRunLoopTimerContext context = {
0, NULL, NULL, NULL, NULL,
};
CFRunLoopTimerRef timer = CFRunLoopTimerCreate(
NULL,
0,
INTERVAL,
0,
0,
speak,
&context
);
CFRunLoopAddTimer(CFRunLoopGetCurrent(), timer, kCFRunLoopDefaultMode);
CFRunLoopRun();
}
// It is unlikely that we will ever get here
// as there is no way to exit the runloop
return(EXIT_SUCCESS);
}