ctucx.git: nixfiles

ctucx' nixfiles

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, &notifyPortRef, MySleepCallBack, &notifierObject );
        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/
  '';
}