diff options
Diffstat (limited to 'daemons')
| -rw-r--r-- | daemons/batteryd.c | 45 | ||||
| -rw-r--r-- | daemons/brightnessd.c | 75 | ||||
| -rw-r--r-- | daemons/devicesd.c | 75 | ||||
| -rw-r--r-- | daemons/focusd.c | 49 | ||||
| -rw-r--r-- | daemons/networkd.c | 67 | ||||
| -rw-r--r-- | daemons/nowplayingd.c | 55 | ||||
| -rw-r--r-- | daemons/spaced.c | 75 |
7 files changed, 441 insertions, 0 deletions
diff --git a/daemons/batteryd.c b/daemons/batteryd.c new file mode 100644 index 0000000..48e21b3 --- /dev/null +++ b/daemons/batteryd.c @@ -0,0 +1,45 @@ +// batteryd — battery daemon for bar +// +// Uses IOKit to listen for power source changes (battery level, charging +// state, AC plug/unplug) and posts a Darwin notification. +// +// Compile: +// cc -o bar-batteryd daemons/batteryd.c \ +// -framework IOKit -framework CoreFoundation + +#include <IOKit/ps/IOPowerSources.h> +#include <IOKit/ps/IOPSKeys.h> +#include <notify.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +static volatile int keep_running = 1; + +static void handle_signal(int sig) { + (void)sig; + keep_running = 0; +} + +static void power_source_changed(void *context) { + (void)context; + notify_post("bar.touch.<block-name>"); +} + +int main(void) { + signal(SIGINT, handle_signal); + signal(SIGTERM, handle_signal); + + CFRunLoopSourceRef source = IOPSNotificationCreateRunLoopSource(power_source_changed, NULL); + if (source) { + CFRunLoopAddSource(CFRunLoopGetCurrent(), source, kCFRunLoopDefaultMode); + CFRelease(source); + } + + while (keep_running) { + pause(); + } + + return 0; +} diff --git a/daemons/brightnessd.c b/daemons/brightnessd.c new file mode 100644 index 0000000..333dbf4 --- /dev/null +++ b/daemons/brightnessd.c @@ -0,0 +1,75 @@ +// brightnessd — display brightness daemon for bar +// +// Uses IOKit to listen for display brightness changes and posts +// a Darwin notification. +// +// Compile: +// cc -o bar-brightnessd daemons/brightnessd.c \ +// -framework IOKit -framework CoreFoundation + +#include <IOKit/IOKitLib.h> +#include <IOKit/graphics/IOGraphicsLib.h> +#include <notify.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +static volatile int keep_running = 1; +static IONotificationPortRef notifyPort = NULL; + +static void handle_signal(int sig) { + (void)sig; + keep_running = 0; +} + +static void brightness_changed(void *refcon, io_iterator_t iterator) { + (void)refcon; + // Drain the iterator + io_object_t obj; + while ((obj = IOIteratorNext(iterator))) { + IOObjectRelease(obj); + } + notify_post("bar.touch.<block-name>"); +} + +int main(void) { + signal(SIGINT, handle_signal); + signal(SIGTERM, handle_signal); + + notifyPort = IONotificationPortCreate(kIOMasterPortDefault); + CFRunLoopSourceRef source = IONotificationPortGetRunLoopSource(notifyPort); + CFRunLoopAddSource(CFRunLoopGetCurrent(), source, kCFRunLoopDefaultMode); + + // Watch for brightness-related display changes + CFMutableDictionaryRef matching = IOServiceMatching("AppleBacklightDisplay"); + if (!matching) { + // Fallback: try Intel backlight + matching = IOServiceMatching("AppleIntelPanel"); + } + if (!matching) { + matching = IOServiceMatching("IODisplay"); + } + + if (matching) { + io_iterator_t iter; + IOServiceAddMatchingNotification( + notifyPort, kIOFirstMatchNotification, matching, + brightness_changed, NULL, &iter); + brightness_changed(NULL, iter); // drain initial + + // Also watch for termination to catch display disconnect + IOServiceAddMatchingNotification( + notifyPort, kIOTerminatedNotification, matching, + brightness_changed, NULL, &iter); + } + + while (keep_running) { + pause(); + } + + if (notifyPort) { + IONotificationPortDestroy(notifyPort); + } + return 0; +} diff --git a/daemons/devicesd.c b/daemons/devicesd.c new file mode 100644 index 0000000..6b30930 --- /dev/null +++ b/daemons/devicesd.c @@ -0,0 +1,75 @@ +// devicesd — USB device hotplug daemon for bar +// +// Uses IOKit to listen for USB device connect/disconnect events and +// posts a Darwin notification. +// +// Compile: +// cc -o bar-devicesd daemons/devicesd.c \ +// -framework IOKit -framework CoreFoundation + +#include <IOKit/IOKitLib.h> +#include <notify.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +static volatile int keep_running = 1; +static IONotificationPortRef notifyPort = NULL; + +static void handle_signal(int sig) { + (void)sig; + keep_running = 0; +} + +static void device_event(void *refcon, io_iterator_t iterator) { + (void)refcon; + io_object_t obj; + while ((obj = IOIteratorNext(iterator))) { + IOObjectRelease(obj); + } + notify_post("bar.touch.<block-name>"); +} + +int main(void) { + signal(SIGINT, handle_signal); + signal(SIGTERM, handle_signal); + + notifyPort = IONotificationPortCreate(kIOMasterPortDefault); + CFRunLoopSourceRef source = IONotificationPortGetRunLoopSource(notifyPort); + CFRunLoopAddSource(CFRunLoopGetCurrent(), source, kCFRunLoopDefaultMode); + + // Watch for USB devices + CFMutableDictionaryRef matching = IOServiceMatching("IOUSBDevice"); + if (matching) { + io_iterator_t iter; + + IOServiceAddMatchingNotification( + notifyPort, kIOFirstMatchNotification, matching, + device_event, NULL, &iter); + device_event(NULL, iter); // drain initial set + + IOServiceAddMatchingNotification( + notifyPort, kIOTerminatedNotification, matching, + device_event, NULL, &iter); + } + + // Also watch for Bluetooth devices + CFMutableDictionaryRef btMatching = IOServiceMatching("IOBluetoothHCIController"); + if (btMatching) { + io_iterator_t iter; + IOServiceAddMatchingNotification( + notifyPort, kIOFirstMatchNotification, btMatching, + device_event, NULL, &iter); + device_event(NULL, iter); + } + + while (keep_running) { + pause(); + } + + if (notifyPort) { + IONotificationPortDestroy(notifyPort); + } + return 0; +} diff --git a/daemons/focusd.c b/daemons/focusd.c new file mode 100644 index 0000000..9a57564 --- /dev/null +++ b/daemons/focusd.c @@ -0,0 +1,49 @@ +// bar-focusd — Focus / Do Not Disturb daemon for bar +// +// Listens for Focus mode and DND changes via DistributedNotificationCenter +// and posts a Darwin notification. +// +// Compile: +// cc -o bar-focusd daemons/focusd.c -framework CoreFoundation + +#include <CoreFoundation/CoreFoundation.h> +#include <notify.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +static volatile int keep_running = 1; + +static void handle_signal(int sig) { + (void)sig; + keep_running = 0; +} + +static void focus_changed( + CFNotificationCenterRef center, void *observer, + CFStringRef name, const void *object, CFDictionaryRef userInfo +) { + (void)center; (void)observer; (void)name; (void)object; (void)userInfo; + notify_post("bar.touch.<block-name>"); +} + +int main(void) { + signal(SIGINT, handle_signal); + signal(SIGTERM, handle_signal); + + CFNotificationCenterRef center = CFNotificationCenterGetDistributedCenter(); + + // DND / Focus mode changes + CFNotificationCenterAddObserver( + center, NULL, focus_changed, + CFSTR("com.apple.notificationcenter.dndprefs_changed"), + NULL, CFNotificationSuspensionBehaviorDeliverImmediately); + + while (keep_running) { + pause(); + } + + CFNotificationCenterRemoveEveryObserver(center, NULL); + return 0; +} diff --git a/daemons/networkd.c b/daemons/networkd.c new file mode 100644 index 0000000..3fea2c7 --- /dev/null +++ b/daemons/networkd.c @@ -0,0 +1,67 @@ +// bar-networkd — network status daemon for bar +// +// Uses SystemConfiguration to listen for network state changes +// (WiFi connect/disconnect, IP address changes, VPN toggle) and +// posts a Darwin notification. +// +// Compile: +// cc -o bar-networkd daemons/networkd.c \ +// -framework SystemConfiguration -framework CoreFoundation + +#include <SystemConfiguration/SystemConfiguration.h> +#include <notify.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +static volatile int keep_running = 1; + +static void handle_signal(int sig) { + (void)sig; + keep_running = 0; +} + +static void network_changed( + SCDynamicStoreRef store, CFArrayRef changedKeys, void *info +) { + (void)store; (void)changedKeys; (void)info; + notify_post("bar.touch.<block-name>"); +} + +int main(void) { + signal(SIGINT, handle_signal); + signal(SIGTERM, handle_signal); + + SCDynamicStoreContext context = {0, NULL, NULL, NULL, NULL}; + SCDynamicStoreRef store = SCDynamicStoreCreate( + NULL, CFSTR("bar-networkd"), network_changed, &context); + + if (!store) { + fprintf(stderr, "bar-networkd: could not create dynamic store\n"); + return 1; + } + + // Watch for IPv4, IPv6, and WiFi state changes + const void *keys[] = { + CFSTR("State:/Network/Global/IPv4"), + CFSTR("State:/Network/Global/IPv6"), + CFSTR("State:/Network/Interface/en0/AirPort"), + CFSTR("State:/Network/Interface/en1/AirPort"), + }; + CFArrayRef keyArray = CFArrayCreate( + NULL, keys, 4, &kCFTypeArrayCallBacks); + SCDynamicStoreSetNotificationKeys(store, keyArray, NULL); + CFRelease(keyArray); + + CFRunLoopSourceRef source = SCDynamicStoreCreateRunLoopSource(NULL, store, 0); + CFRunLoopAddSource(CFRunLoopGetCurrent(), source, kCFRunLoopDefaultMode); + CFRelease(source); + + while (keep_running) { + pause(); + } + + CFRelease(store); + return 0; +} diff --git a/daemons/nowplayingd.c b/daemons/nowplayingd.c new file mode 100644 index 0000000..fc785b3 --- /dev/null +++ b/daemons/nowplayingd.c @@ -0,0 +1,55 @@ +// nowplayingd — now playing daemon for bar +// +// Listens for track change notifications from Music.app and Spotify +// via DistributedNotificationCenter and posts a Darwin notification. +// +// Compile: +// cc -o bar-nowplayingd daemons/nowplayingd.c -framework CoreFoundation + +#include <CoreFoundation/CoreFoundation.h> +#include <notify.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +static volatile int keep_running = 1; + +static void handle_signal(int sig) { + (void)sig; + keep_running = 0; +} + +static void track_changed( + CFNotificationCenterRef center, void *observer, + CFStringRef name, const void *object, CFDictionaryRef userInfo +) { + (void)center; (void)observer; (void)name; (void)object; (void)userInfo; + notify_post("bar.touch.<block-name>"); +} + +int main(void) { + signal(SIGINT, handle_signal); + signal(SIGTERM, handle_signal); + + CFNotificationCenterRef center = CFNotificationCenterGetDistributedCenter(); + + // Music.app + CFNotificationCenterAddObserver( + center, NULL, track_changed, + CFSTR("com.apple.Music.playerInfo"), + NULL, CFNotificationSuspensionBehaviorDeliverImmediately); + + // Spotify + CFNotificationCenterAddObserver( + center, NULL, track_changed, + CFSTR("com.spotify.client.PlaybackStateChanged"), + NULL, CFNotificationSuspensionBehaviorDeliverImmediately); + + while (keep_running) { + pause(); + } + + CFNotificationCenterRemoveEveryObserver(center, NULL); + return 0; +} diff --git a/daemons/spaced.c b/daemons/spaced.c new file mode 100644 index 0000000..0729266 --- /dev/null +++ b/daemons/spaced.c @@ -0,0 +1,75 @@ +// spaced — desktop space daemon for bar +// +// Monitors the active desktop space and posts a Darwin notification +// when the space changes. Uses a lightweight 0.5s poll of a CoreGraphics +// private API. +// +// Compile: +// cc -o bar-spaced daemons/spaced.c -framework CoreFoundation + +#include <CoreFoundation/CoreFoundation.h> +#include <dlfcn.h> +#include <notify.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +static volatile int keep_running = 1; + +// Private CoreGraphics API +typedef CFStringRef (*CGSCopyActiveMenuBarDisplayIdentifierFunc)(void); + +static CGSCopyActiveMenuBarDisplayIdentifierFunc copyIdentifier = NULL; + +static void handle_signal(int sig) { + (void)sig; + keep_running = 0; +} + +int main(void) { + signal(SIGINT, handle_signal); + signal(SIGTERM, handle_signal); + + // Load the private CGS API at runtime + void *handle = dlopen( + "/System/Library/PrivateFrameworks/CoreGraphics.framework/CoreGraphics", + RTLD_LAZY | RTLD_LOCAL); + + if (!handle) { + fprintf(stderr, "bar-spaced: could not load CoreGraphics framework\n"); + return 1; + } + + copyIdentifier = (CGSCopyActiveMenuBarDisplayIdentifierFunc) + dlsym(handle, "CGSCopyActiveMenuBarDisplayIdentifier"); + + if (!copyIdentifier) { + fprintf(stderr, "bar-spaced: could not find CGS API\n"); + dlclose(handle); + return 1; + } + + CFStringRef last = NULL; + unsigned int pollCount = 0; + + while (keep_running) { + CFStringRef current = copyIdentifier(); + + if (current) { + if (!last || !CFEqual(current, last)) { + notify_post("bar.touch.<block-name>"); + if (last) CFRelease(last); + last = CFStringCreateCopy(NULL, current); + } + CFRelease(current); + } + + usleep(500000); // 0.5 second intervals + pollCount++; + } + + if (last) CFRelease(last); + dlclose(handle); + return 0; +} |
