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
135
136
137
138
139
140
141
142
package main
import (
"errors"
"flag"
"fmt"
"os"
"os/signal"
"slices"
"syscall"
"git.zaphyra.eu/airpodsctl/helpers"
"git.zaphyra.eu/airpodsctl/types"
)
func init() {
c := make(chan os.Signal)
signal.Notify(c, os.Interrupt, syscall.SIGTERM)
go func() {
<-c
fmt.Fprint(os.Stdout, "\033[?25h")
os.Exit(0)
}()
}
func main() {
state, errStateInit := InitState()
if errStateInit != nil {
fmt.Fprintln(os.Stderr, "Failed to init state:", errStateInit)
os.Exit(1)
}
defer state.Close()
flag.Usage = func() {
command := "<COMMAND>"
commandHelp := commandHelpStr
if len(flag.Args()) > 1 {
command = flag.Arg(0)
commandHelp = ""
}
fmt.Fprintf(os.Stderr, usageStr, "0.0.0", "2025-08-11", command, commandHelp)
flag.PrintDefaults()
}
flag.StringVar(&state.SelectedDevice, "device", "", "`<macAddress>` of the device that should be used (default: first device found)")
flag.BoolVar(&state.SendNotifications, "notify", false, "Enable notifications")
flag.BoolVar(&state.DebugOutput, "debug", false, "Enable debug-output")
flag.Var(&state.OutputFormat, "format", "`<format>` to use for output (default: cli)\nSupported formats: {cli|waybar}")
flag.BoolFunc("help", "Print this help message", func(str string) error {
flag.Usage()
os.Exit(0)
return nil
})
flag.Parse()
commandArgs := flag.NewFlagSet("", flag.ExitOnError)
commandArgs.Usage = func() {
flag.Usage()
fmt.Fprint(os.Stderr, "\nCOMMAND OPTIONS\n")
commandArgs.PrintDefaults()
fmt.Fprint(os.Stderr, "\n")
}
if len(flag.Args()) < 1 {
fmt.Fprintln(os.Stdout, "No command supplied!\n\nUse --help for a list of available commands.")
os.Exit(0)
}
switch flag.Arg(0) {
case "listDevices":
state.listDevicesCommand()
case "dumpDeviceState":
state.checkSelectedDevice()
state.dumpDeviceStateCommand()
case "toggleAncMode":
var ancMode types.ANCMode
commandArgs.Var(&ancMode, "mode", "`<ancMode>` that should be set\nValid modes: {on|adaptive|transparency|off}")
commandArgs.Parse(flag.Args()[1:])
state.checkSelectedDevice()
state.toggleAncModeCommand(ancMode)
case "toggleFeature":
var feature string
var value types.Bool
commandArgs.Var(&value, "value", "`<value>` that should be set\nValid values: {on|enable|off|disable}")
commandArgs.Func("feature", "`<feature>` that should be modified\n"+featuresHelpStr, func(str string) (err error) {
switch str {
case "":
err = errors.New("No feature supplied!\n")
case "OneBudAnc":
feature = "OneBudANCMode"
case "VolumeSwipe":
feature = "VolumeSwipeConfig"
case "AdaptiveVolume":
feature = "AdaptiveVolumeConfig"
case "ConversationalAwareness":
feature = "ConversationDetectConfig"
case "AllowANCOff":
feature = "AllowANCOffConfig"
default:
err = fmt.Errorf("Unknown Feature: %s\n", str)
}
return
})
commandArgs.Parse(flag.Args()[1:])
state.checkSelectedDevice()
state.toggleFeatureCommand(feature, value)
case "monitor":
state.checkSelectedDevice()
state.monitorCommand()
default:
fmt.Fprintf(os.Stdout, helpers.BoldText("Unknown command: %s")+"\n%s\n", flag.Arg(0), commandHelpStr)
}
}
func (state *State) checkSelectedDevice() {
if state.SelectedDevice == "" {
firstConnectedDevice := slices.IndexFunc(state.Devices, func(device types.Device) bool {
return bool(device.Connected)
})
if firstConnectedDevice != -1 {
state.SelectedDevice = state.Devices[firstConnectedDevice].Address
} else {
fmt.Fprintln(os.Stderr, "Error: No device connected!")
os.Exit(1)
}
}
}