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
132
133
134
{ inputs, stdenv, runCommand, writeText, ...}:
let
SpeakerDaemon = writeText "speakerDaemon.c" ''
#include <ctype.h>
#include <stdlib.h>
#include <stdio.h>
#include <mach/mach_port.h>
#include <mach/mach_interface.h>
#include <mach/mach_init.h>
#include <IOKit/pwr_mgt/IOPMLib.h>
#include <IOKit/IOMessage.h>
#include <curl/curl.h>
io_connect_t root_port; // a reference to the Root Power Domain IOService
void MySleepCallBack( void * refCon, io_service_t service, natural_t messageType, void * messageArgument ) {
CURL *curl;
CURLcode res;
FILE *dummy_writer = fopen("/dev/null", "w");
curl_global_init(CURL_GLOBAL_ALL);
switch ( messageType ) {
case kIOMessageCanSystemSleep:
IOAllowPowerChange( root_port, (long)messageArgument );
break;
case kIOMessageSystemWillSleep:
printf("Sleep-Event!\n");
// check if dock is connected
if (system("ioreg -p IOUSB | grep '3-Port USB 2.1 Hub' 1> /dev/null") != 0) break;
curl = curl_easy_init();
if (curl) {
curl_easy_setopt(curl, CURLOPT_WRITEDATA, dummy_writer);
curl_easy_setopt(curl, CURLOPT_URL, "http://10.0.0.1:5000");
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, "{\"accessToken\": \"${inputs.local-secrets.hosts.lollo.smartied.accessToken}\", \"type\": \"SwitchStateAction\", \"deviceName\": \"relay-pc-speakers\", \"state\": false}");
res = curl_easy_perform(curl);
if (res != CURLE_OK) fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
curl_easy_cleanup(curl);
}
IOAllowPowerChange(root_port, (long)messageArgument );
break;
case kIOMessageSystemWillPowerOn:
//System has started the wake up process...
break;
case kIOMessageSystemHasPoweredOn:
printf("WakeUp-Event!\n");
curl = curl_easy_init();
if (curl) {
curl_easy_setopt(curl, CURLOPT_WRITEDATA, dummy_writer);
curl_easy_setopt(curl, CURLOPT_URL, "http://10.0.0.1:5000");
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, "{\"accessToken\": \"${inputs.local-secrets.hosts.lollo.smartied.accessToken}\", \"type\": \"SwitchStateAction\", \"deviceName\": \"relay-pc-speakers\", \"state\": true}");
res = curl_easy_perform(curl);
if (res != CURLE_OK) fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
curl_easy_cleanup(curl);
}
break;
default:
break;
}
curl_global_cleanup();
}
int main( int argc, char **argv ) {
// notification port allocated by IORegisterForSystemPower
IONotificationPortRef notifyPortRef;
// notifier object, used to deregister later
io_object_t notifierObject;
// this parameter is passed to the callback
void* refCon;
// register to receive system sleep notifications
root_port = IORegisterForSystemPower( refCon, ¬ifyPortRef, MySleepCallBack, ¬ifierObject );
if ( root_port == 0 ) {
printf("IORegisterForSystemPower failed\n");
return 1;
}
// add the notification port to the application runloop
CFRunLoopAddSource( CFRunLoopGetCurrent(), IONotificationPortGetRunLoopSource(notifyPortRef), kCFRunLoopCommonModes );
/* Start the run loop to receive sleep notifications. Don't call CFRunLoopRun if this code
is running on the main thread of a Cocoa or Carbon application. Cocoa and Carbon
manage the main thread's run loop for you as part of their event handling
mechanisms.
*/
CFRunLoopRun();
//Not reached, CFRunLoopRun doesn't return in this case.
return (0);
}
'';
buildSymlinks = runCommand "macvim-build-symlinks" {} ''
mkdir -p $out/bin
ln -s /usr/bin/gcc $out/bin
'';
in stdenv.mkDerivation {
name = "SpeakerDaemon";
src = ./.;
nativeBuildInputs = [ buildSymlinks ];
sandboxProfile = ''
(allow file-read* file-write* process-exec mach-lookup)
; block homebrew dependencies
(deny file-read* file-write* process-exec mach-lookup (subpath "/usr/local") (with no-log))
'';
buildPhase = "gcc -framework IOKit -framework Cocoa -lcurl -o SpeakerDaemon ${SpeakerDaemon}";
installPhase = ''
mkdir -p $out/bin
cp SpeakerDaemon $out/bin/
'';
}