zaphyra's git: airpodsctl

Control and monitor your AirPods

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 
package main

import (
	"encoding/json"
	"fmt"
	"os"

	"git.zaphyra.eu/airpodsctl/types"

	"github.com/godbus/dbus/v5"
)

func (state State) monitorCommand() {
	var lines int

	device, err := state.Devices.Get(state.SelectedDevice)
	if err == nil {
		switch state.OutputFormat {
		case types.FormatWaybar:
			fmt.Fprint(os.Stdout, device.FormatWaybarString())
		case types.FormatCLI:
			var output string
			output, lines = device.FormatCLIString()
			fmt.Fprintf(os.Stdout, "\033[?25l%s\033[%dA", output, lines)
		}
	}

	state.RegisterSignals()

	for signal := range state.Signals {
		if signal == nil {
			return
		}

		switch signal.Name {
		case "org.kairpods.manager.DeviceConnected":
			macAddr := signal.Body[0].(string)
			device, _ := state.Devices.Get(macAddr)
			batteryStateBuds := types.StringSlice{}

			if device.Battery.LeftBud.Valid || device.Battery.RightBud.Valid || device.BatteryTTLEstimate.Valid {
				batteryStateBuds.Add("\n<small> 󰁹</small>")

				if device.Battery.LeftBud.Valid {
					var chargeSymbol string
					if device.Battery.LeftBud.Value.Charging {
						chargeSymbol = " <span size=\"smaller\" rise=\"1pt\"></span>"
					}

					batteryStateBuds.Add(fmt.Sprintf("<small>L: %d%%%#s</small>", device.Battery.LeftBud.Value.Level, chargeSymbol))
				}

				if device.Battery.RightBud.Valid {
					var chargeSymbol string
					if device.Battery.RightBud.Value.Charging {
						chargeSymbol = " <span size=\"smaller\" rise=\"1pt\"></span>"
					}

					batteryStateBuds.Add(fmt.Sprintf("<small>R: %d%%%#s</small>", device.Battery.RightBud.Value.Level, chargeSymbol))
				}

				if device.BatteryTTLEstimate.Valid {
					batteryStateBuds.Add(fmt.Sprintf("<small>(󱧦 ~%s remaining)</small>", device.BatteryTTLEstimate))
				}
			}

			state.SendNotify(fmt.Sprintf("Device '%s' connected!%s", device.Name, batteryStateBuds.ConcatString(" ")), 4, "")

		case "org.kairpods.manager.DeviceDisconnected":
			macAddr := signal.Body[0].(string)
			device, _ := state.Devices.Get(macAddr)

			state.SendNotify(fmt.Sprintf("Device '%s' disconnected!", device.Name), 2, "")

		// currently unusable, because there is no event triggered for anc-mode 'adaptive'
		// case "org.kairpods.manager.NoiseControlChanged":
		//	macAddr := signal.Body[0].(string)
		//	ancMode := signal.Body[1].(string)

		//	fmt.Println(ancMode)

		//	state.SendNotify(fmt.Sprintf("Device '%s' switched to ANC-Mode: %s", state.Devices.Get(macAddr).Name, parseANCMode(ancMode).FormatString()), 2)

		case "org.freedesktop.DBus.Properties.PropertiesChanged":
			changedProperties := signal.Body[1].(map[string]dbus.Variant)

			if value, hasKey := changedProperties["Devices"]; hasKey {
				var devicesStr string
				var devices types.Devices

				value.Store(&devicesStr)

				if err := json.Unmarshal([]byte(devicesStr), &devices); err != nil {
					state.PrintDebug(fmt.Sprintf("[monitorCommand] Faild to unmarshal devices-JSON: %s\n", err))
					return
				}

				oldDeviceState, oldDeviceErr := state.Devices.Get(state.SelectedDevice)
				newDeviceState, newDeviceErr := devices.Get(state.SelectedDevice)

				state.Devices = devices

				if newDeviceErr == nil {
					switch state.OutputFormat {
					case types.FormatWaybar:
						fmt.Fprint(os.Stdout, newDeviceState.FormatWaybarString())
					case types.FormatCLI:
						var output string
						output, lines = newDeviceState.FormatCLIString()
						fmt.Fprintf(os.Stdout, "\033[?25l\033[0J%s\033[%dA", output, lines)
					}

					if oldDeviceErr == nil {
						if oldDeviceState.ANCMode != newDeviceState.ANCMode {
							state.SendNotify(fmt.Sprintf("Switched to ANC-Mode: %s", newDeviceState.ANCMode.Value), 2, newDeviceState.Name)
						}
					}
				}
			}

		default:
			state.PrintDebug(fmt.Sprintf("[monitorCommand] Received unknown signal '%s': %+v\n", signal.Name, signal.Body))
		}
	}

	os.Exit(0)
}