Skip to content

Instantly share code, notes, and snippets.

@adamgoose
Created April 27, 2019 07:21
Show Gist options
  • Save adamgoose/bd44dabfebc8f88af3916ba1a50be31b to your computer and use it in GitHub Desktop.
Save adamgoose/bd44dabfebc8f88af3916ba1a50be31b to your computer and use it in GitHub Desktop.
Behringer X Touch One - Control your system volume!
package main
import (
"log"
"math"
"github.com/itchyny/volume-go"
"github.com/rakyll/portmidi"
)
func main() {
k, err := NewKnob(0, 1)
if err != nil {
log.Fatal(err)
}
defer k.Close()
k.Watch()
}
type VolumeKnob struct {
out *portmidi.Stream
in *portmidi.Stream
Volume int
}
func NewKnob(inputID, outputID portmidi.DeviceID) (*VolumeKnob, error) {
out, err := portmidi.NewOutputStream(outputID, 1024, 0)
if err != nil {
return nil, err
}
in, err := portmidi.NewInputStream(inputID, 1024)
if err != nil {
return nil, err
}
v, err := volume.GetVolume()
if err != nil {
return nil, err
}
return &VolumeKnob{
out: out,
in: in,
Volume: v,
}, nil
}
func (k VolumeKnob) Set(v int) {
if v < 0 || v > 100 {
return
}
volume.SetVolume(v)
k.out.WriteShort(144, 111, 127)
k.out.WriteShort(231, 0, intToMidi(v))
k.out.WriteShort(144, 111, 0)
}
func (k VolumeKnob) Close() {
k.out.Close()
k.in.Close()
}
func (k VolumeKnob) Watch() {
ch := k.in.Listen()
for event := range ch {
switch event.Status {
case 144:
// Data1 111
// Data2 on/off
if event.Data2 == 0 {
k.Set(k.Volume)
}
break
case 231:
// Data2 midiLevel
k.Volume = midiToInt(event.Data2)
break
}
}
}
func init() {
portmidi.Initialize()
}
func intToMidi(v int) int64 {
return int64(math.Round(float64(v) * 1.27))
}
func midiToInt(v int64) int {
return int(math.Round(float64(v) / 1.27))
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment