diff options
| author | Tommaso Negri <me@tommasongr.com> | 2026-08-11 17:50:39 +0200 |
|---|---|---|
| committer | Tommaso Negri <me@tommasongr.com> | 2026-08-11 17:50:39 +0200 |
| commit | a1d62dd085ac70fc90a05095220156897bdd8f82 (patch) | |
| tree | 2af6218e0c9e2a6e399cf5f91e3a0ba05e7c3014 /daemons/volume/volumed.c | |
| parent | 4dcbad96f8dc63c5f48d063606f0384853ac799d (diff) | |
| download | bar-a1d62dd085ac70fc90a05095220156897bdd8f82.tar.gz bar-a1d62dd085ac70fc90a05095220156897bdd8f82.zip | |
refactor daemons + mpd + documentation
Diffstat (limited to 'daemons/volume/volumed.c')
| -rw-r--r-- | daemons/volume/volumed.c | 171 |
1 files changed, 0 insertions, 171 deletions
diff --git a/daemons/volume/volumed.c b/daemons/volume/volumed.c deleted file mode 100644 index 3681b60..0000000 --- a/daemons/volume/volumed.c +++ /dev/null @@ -1,171 +0,0 @@ -// bar-volumed — volume daemon for bar (no permissions needed) -// -// Uses CoreAudio to listen for system volume/mute changes instead of -// a CGEvent tap, so no Accessibility permission is required. -// -// When the volume changes, it posts a Darwin notification that tells -// bar to refresh the "volume" block. -// -// ── Setup ── -// -// 1. Add a volume block to Config (no interval needed): -// Block(name: "volume", placement: .right, command: "<your-volume-script>") -// -// 2. Compile and run the daemon: -// cc -o ~/.local/bin/bar-volumed daemons/volume/volumed.c -framework CoreAudio -// ~/.local/bin/bar-volumed & -// -// 3. Or install as a luanch agent: -// cp daemons/volume/house.panini.bar.volumed.plist ~/Library/LaunchAgents/ -// # Make sure to update the ProgramArguments with the correct path to the program -// launchctl load ~/Library/LaunchAgents/house.panini.bar.volumed.plist -// -// Compile: -// cc -o bar-volumed daemons/volume/volumed.c -framework CoreAudio - -#include <CoreAudio/CoreAudio.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; -} - -// ── Volume change callback ─────────────────────────────────────────── - -static OSStatus volume_changed( - AudioObjectID object, - UInt32 num_addresses, - const AudioObjectPropertyAddress addresses[], - void *context -) { - (void)object; (void)num_addresses; (void)addresses; (void)context; - notify_post("bar.touch.volume"); - return noErr; -} - -// ── Device change callback ─────────────────────────────────────────── -// Re-registers the volume listener when the output device changes -// (e.g. headphones plugged in). - -static AudioDeviceID current_device = kAudioObjectUnknown; -static void register_volume_listener(AudioDeviceID device); - -static OSStatus device_changed( - AudioObjectID object, - UInt32 num_addresses, - const AudioObjectPropertyAddress addresses[], - void *context -) { - (void)object; (void)num_addresses; (void)addresses; (void)context; - - AudioObjectPropertyAddress addr = { - kAudioHardwarePropertyDefaultOutputDevice, - kAudioObjectPropertyScopeGlobal, - kAudioObjectPropertyElementMain - }; - AudioDeviceID new_device = kAudioObjectUnknown; - UInt32 size = sizeof(new_device); - AudioObjectGetPropertyData( - kAudioObjectSystemObject, &addr, 0, NULL, &size, &new_device); - - if (new_device != current_device && new_device != kAudioObjectUnknown) { - register_volume_listener(new_device); - } - return noErr; -} - -// ── Register listener on a device ──────────────────────────────────── - -static void register_volume_listener(AudioDeviceID device) { - // Remove old listener if any - if (current_device != kAudioObjectUnknown) { - AudioObjectPropertyAddress old_addr = { - kAudioDevicePropertyVolumeScalar, - kAudioDevicePropertyScopeOutput, - 1 // channel 1 - }; - AudioObjectRemovePropertyListener( - current_device, &old_addr, volume_changed, NULL); - } - - current_device = device; - - // Get the preferred stereo channel (usually 1) - UInt32 channel = 1; - AudioObjectPropertyAddress chan = { - kAudioDevicePropertyPreferredChannelsForStereo, - kAudioDevicePropertyScopeOutput, - kAudioObjectPropertyElementMain - }; - UInt32 channels[2] = {0, 0}; - UInt32 size = sizeof(channels); - if (AudioObjectGetPropertyData(device, &chan, 0, NULL, &size, &channels) == noErr) { - channel = channels[0]; - } - - // Listen for volume changes on the main output channel - AudioObjectPropertyAddress vol_addr = { - kAudioDevicePropertyVolumeScalar, - kAudioDevicePropertyScopeOutput, - channel - }; - AudioObjectAddPropertyListener(device, &vol_addr, volume_changed, NULL); - - // Also listen for mute changes - AudioObjectPropertyAddress mute_addr = { - kAudioDevicePropertyMute, - kAudioDevicePropertyScopeOutput, - kAudioObjectPropertyElementMain - }; - AudioObjectAddPropertyListener(device, &mute_addr, volume_changed, NULL); -} - -// ── Main ───────────────────────────────────────────────────────────── - -int main(void) { - signal(SIGINT, handle_signal); - signal(SIGTERM, handle_signal); - - // Listen for output device changes - AudioObjectPropertyAddress dev_addr = { - kAudioHardwarePropertyDefaultOutputDevice, - kAudioObjectPropertyScopeGlobal, - kAudioObjectPropertyElementMain - }; - AudioObjectAddPropertyListener( - kAudioObjectSystemObject, &dev_addr, device_changed, NULL); - - // Register on the current device - UInt32 size = sizeof(current_device); - AudioObjectGetPropertyData( - kAudioObjectSystemObject, &dev_addr, 0, NULL, &size, ¤t_device); - - if (current_device != kAudioObjectUnknown) { - register_volume_listener(current_device); - } - - // Run until SIGINT/SIGTERM - while (keep_running) { - pause(); - } - - // Cleanup - if (current_device != kAudioObjectUnknown) { - AudioObjectPropertyAddress vol_addr = { - kAudioDevicePropertyVolumeScalar, - kAudioDevicePropertyScopeOutput, - 1 // channel 1 - }; - AudioObjectRemovePropertyListener( - current_device, &vol_addr, volume_changed, NULL); - } - - return 0; -} |
