Initial version

This commit is contained in:
Isaac Shoebottom 2024-02-03 15:10:40 -04:00
parent ce2f62dc4b
commit 4ca75c0978
4 changed files with 245 additions and 0 deletions

7
Makefile Normal file
View File

@ -0,0 +1,7 @@
# Export CGO_ENABLED=1
CGO_ENABLED=1
# Export C compiler
CC=gcc
build:
go build -ldflags "-H windowsgui" -o bin/

23
go.mod Normal file
View File

@ -0,0 +1,23 @@
module VolumeFix
go 1.21
require (
github.com/moutend/go-hook v0.1.0
github.com/moutend/go-wca v0.3.0
)
require (
github.com/getlantern/context v0.0.0-20190109183933-c447772a6520 // indirect
github.com/getlantern/errors v0.0.0-20190325191628-abdb3e3e36f7 // indirect
github.com/getlantern/golog v0.0.0-20190830074920-4ef2e798c2d7 // indirect
github.com/getlantern/hex v0.0.0-20190417191902-c6586a6fe0b7 // indirect
github.com/getlantern/hidden v0.0.0-20190325191715-f02dbb02be55 // indirect
github.com/getlantern/ops v0.0.0-20190325191751-d70cb0d6f85f // indirect
github.com/getlantern/systray v1.2.2 // indirect
github.com/go-ole/go-ole v1.3.0 // indirect
github.com/go-stack/stack v1.8.0 // indirect
github.com/micmonay/keybd_event v1.1.2 // indirect
github.com/oxtoacart/bpool v0.0.0-20190530202638-03653db5a59c // indirect
golang.org/x/sys v0.16.0 // indirect
)

44
go.sum Normal file
View File

@ -0,0 +1,44 @@
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/getlantern/context v0.0.0-20190109183933-c447772a6520 h1:NRUJuo3v3WGC/g5YiyF790gut6oQr5f3FBI88Wv0dx4=
github.com/getlantern/context v0.0.0-20190109183933-c447772a6520/go.mod h1:L+mq6/vvYHKjCX2oez0CgEAJmbq1fbb/oNJIWQkBybY=
github.com/getlantern/errors v0.0.0-20190325191628-abdb3e3e36f7 h1:6uJ+sZ/e03gkbqZ0kUG6mfKoqDb4XMAzMIwlajq19So=
github.com/getlantern/errors v0.0.0-20190325191628-abdb3e3e36f7/go.mod h1:l+xpFBrCtDLpK9qNjxs+cHU6+BAdlBaxHqikB6Lku3A=
github.com/getlantern/golog v0.0.0-20190830074920-4ef2e798c2d7 h1:guBYzEaLz0Vfc/jv0czrr2z7qyzTOGC9hiQ0VC+hKjk=
github.com/getlantern/golog v0.0.0-20190830074920-4ef2e798c2d7/go.mod h1:zx/1xUUeYPy3Pcmet8OSXLbF47l+3y6hIPpyLWoR9oc=
github.com/getlantern/hex v0.0.0-20190417191902-c6586a6fe0b7 h1:micT5vkcr9tOVk1FiH8SWKID8ultN44Z+yzd2y/Vyb0=
github.com/getlantern/hex v0.0.0-20190417191902-c6586a6fe0b7/go.mod h1:dD3CgOrwlzca8ed61CsZouQS5h5jIzkK9ZWrTcf0s+o=
github.com/getlantern/hidden v0.0.0-20190325191715-f02dbb02be55 h1:XYzSdCbkzOC0FDNrgJqGRo8PCMFOBFL9py72DRs7bmc=
github.com/getlantern/hidden v0.0.0-20190325191715-f02dbb02be55/go.mod h1:6mmzY2kW1TOOrVy+r41Za2MxXM+hhqTtY3oBKd2AgFA=
github.com/getlantern/ops v0.0.0-20190325191751-d70cb0d6f85f h1:wrYrQttPS8FHIRSlsrcuKazukx/xqO/PpLZzZXsF+EA=
github.com/getlantern/ops v0.0.0-20190325191751-d70cb0d6f85f/go.mod h1:D5ao98qkA6pxftxoqzibIBBrLSUli+kYnJqrgBf9cIA=
github.com/getlantern/systray v1.2.2 h1:dCEHtfmvkJG7HZ8lS/sLklTH4RKUcIsKrAD9sThoEBE=
github.com/getlantern/systray v1.2.2/go.mod h1:pXFOI1wwqwYXEhLPm9ZGjS2u/vVELeIgNMY5HvhHhcE=
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE=
github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78=
github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/jwfergus/winsystray v0.0.0-20200612115431-12d8dc7aa265 h1:ImfStqG+JS2Uxdymr1LqZAVDFq1BZxQ1mybTM18hnGA=
github.com/jwfergus/winsystray v0.0.0-20200612115431-12d8dc7aa265/go.mod h1:rkjpnJveVtl+m/CY0U4hFgCf2FlG9UcEUOLsUAo0pxE=
github.com/lxn/walk v0.0.0-20210112085537-c389da54e794/go.mod h1:E23UucZGqpuUANJooIbHWCufXvOcT6E7Stq81gU+CSQ=
github.com/lxn/win v0.0.0-20210218163916-a377121e959e/go.mod h1:KxxjdtRkfNoYDCUP5ryK7XJJNTnpC8atvtmTheChOtk=
github.com/micmonay/keybd_event v1.1.2 h1:RpgvPJKOh4Jc+ZYe0OrVzGd2eNMCfuVg3dFTCsuSah4=
github.com/micmonay/keybd_event v1.1.2/go.mod h1:CGMWMDNgsfPljzrAWoybUOSKafQPZpv+rLigt2LzNGI=
github.com/moutend/go-hook v0.1.0 h1:8jGA7zxtcNmiFrHf+KAGpSBbU99fyY9DS1s38MOBJQU=
github.com/moutend/go-hook v0.1.0/go.mod h1:rGHmQESfHpsztJ6jbDoaiCgesGdZttObFlY/ksHIlY4=
github.com/moutend/go-wca v0.3.0 h1:IzhsQ44zBzMdT42xlBjiLSVya9cPYOoKx9E+yXVhFo8=
github.com/moutend/go-wca v0.3.0/go.mod h1:7VrPO512jnjFGJ6rr+zOoCfiYjOHRPNfbttJuxAurcw=
github.com/oxtoacart/bpool v0.0.0-20190530202638-03653db5a59c h1:rp5dCmg/yLR3mgFuSOe4oEnDDmGLROTvMragMUXpTQw=
github.com/oxtoacart/bpool v0.0.0-20190530202638-03653db5a59c/go.mod h1:X07ZCGwUbLaax7L0S3Tw4hpejzu63ZrrQiUe6W0hcy0=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966/go.mod h1:sUM3LWHvSMaG192sy56D9F7CNvL7jUJVXoqM1QKLnog=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200610111108-226ff32320da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201018230417-eeed37f84f13/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.1.0 h1:kunALQeHf1/185U1i0GOB/fy1IPRDDpuoOOqRReG57U=
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU=
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
gopkg.in/Knetic/govaluate.v3 v3.0.0/go.mod h1:csKLBORsPbafmSCGTEh3U7Ozmsuq8ZSIlKk1bcqph0E=

171
main.go Normal file
View File

@ -0,0 +1,171 @@
package main
import (
"fmt"
"github.com/getlantern/systray"
"github.com/getlantern/systray/example/icon"
"github.com/go-ole/go-ole"
"github.com/moutend/go-hook/pkg/keyboard"
"github.com/moutend/go-hook/pkg/types"
"github.com/moutend/go-wca/pkg/wca"
"math"
"os"
"os/signal"
)
var (
// DeviceEnumerator Persistent reference to the device enumerator object
DeviceEnumerator *wca.IMMDeviceEnumerator
// IMMDevice Persistent reference to the audio endpoint device
IMMDevice *wca.IMMDevice
// AudioEndpointVolume Persistent reference to the audio endpoint volume object
AudioEndpointVolume *wca.IAudioEndpointVolume
// Volume tracks volume level
Volume float32
)
func main() {
if err := run(); err != nil {
fmt.Println(err)
}
}
func onReady() {
systray.SetIcon(icon.Data)
systray.SetTitle("Volume Fix")
systray.SetTooltip("Volume Fix")
quit := systray.AddMenuItem("Quit", "Quit the whole app")
go func() {
<-quit.ClickedCh
fmt.Println("Quitting")
systray.Quit()
}()
}
func onExit() {
// clean up here
os.Exit(0)
}
func run() error {
// Set up audio endpoint volume
err := setupEndpointVolume()
if err != nil {
return err
}
// Defer teardown of COM objects
defer teardown()
keyboardChan := make(chan types.KeyboardEvent, 3)
if err := keyboard.Install(nil, keyboardChan); err != nil {
return err
}
defer func() {
err := keyboard.Uninstall()
if err != nil {
fmt.Println(err)
}
}()
// Systray, run in a separate goroutine to avoid blocking
go func() {
systray.Run(onReady, onExit)
}()
signalChan := make(chan os.Signal, 1)
signal.Notify(signalChan, os.Interrupt)
fmt.Println("start capturing keyboard input")
for {
select {
case <-signalChan:
fmt.Println("Received shutdown signal")
return nil
case key := <-keyboardChan:
switch key.VKCode {
case types.VK_VOLUME_UP:
// Stop key from being passed to the system
switch key.Message {
case types.WM_KEYDOWN:
fmt.Println("Volume up key pressed")
Volume = getVolume()
case types.WM_KEYUP:
fmt.Println("Volume up key released")
setVolume(Volume + 0.01)
}
case types.VK_VOLUME_DOWN:
switch key.Message {
case types.WM_KEYDOWN:
fmt.Println("Volume down key pressed")
Volume = getVolume()
case types.WM_KEYUP:
fmt.Println("Volume down key released")
setVolume(Volume - 0.01)
}
}
}
}
}
func getVolume() float32 {
var volume float32
err := AudioEndpointVolume.GetMasterVolumeLevelScalar(&volume)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
fmt.Println("Current volume is ", volume)
return volume
}
func setVolume(volume float32) {
precision := float64(volume)
// Clamp volume between 0 and 1
precision = math.Max(0, math.Min(precision, 1))
// Round to 2 decimal places
precision = math.Round(precision*100) / 100
volume = float32(precision)
fmt.Println("Setting volume to ", volume)
err := AudioEndpointVolume.SetMasterVolumeLevelScalar(volume, nil)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
}
func setupEndpointVolume() error {
// Initialize COM library
if err := ole.CoInitializeEx(0, ole.COINIT_APARTMENTTHREADED); err != nil {
return err
}
// Get Device Enumerator
if err := wca.CoCreateInstance(wca.CLSID_MMDeviceEnumerator, 0, wca.CLSCTX_ALL, wca.IID_IMMDeviceEnumerator, &DeviceEnumerator); err != nil {
return err
}
// Get default audio endpoint from the device enumerator
if err := DeviceEnumerator.GetDefaultAudioEndpoint(wca.ERender, wca.EConsole, &IMMDevice); err != nil {
return err
}
// Activate the audio endpoint volume object
if err := IMMDevice.Activate(wca.IID_IAudioEndpointVolume, wca.CLSCTX_ALL, nil, &AudioEndpointVolume); err != nil {
return err
}
return nil
}
func teardown() {
// Release the audio endpoint volume object
if AudioEndpointVolume != nil {
AudioEndpointVolume.Release()
}
// Release the audio endpoint device
if IMMDevice != nil {
IMMDevice.Release()
}
// Release the device enumerator
if DeviceEnumerator != nil {
DeviceEnumerator.Release()
}
// Un-initialize COM library
ole.CoUninitialize()
}