Initial version
This commit is contained in:
parent
ce2f62dc4b
commit
4ca75c0978
7
Makefile
Normal file
7
Makefile
Normal 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
23
go.mod
Normal 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
44
go.sum
Normal 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
171
main.go
Normal 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()
|
||||
}
|
Loading…
Reference in New Issue
Block a user