Loading doc.go +0 −1 Original line number Diff line number Diff line Loading @@ -23,4 +23,3 @@ handle all events directly using the returned HID's OSEvent channel. */ package joysticks joysticks.go +21 −20 Original line number Diff line number Diff line Loading @@ -20,9 +20,9 @@ type button struct { //HID holds the in-coming event channel, mappings, and registered events for a joystick, and has methods to control and adjust behaviour. type HID struct { OSEvent chan osEventRecord buttons map[uint8]button hatAxes map[uint8]hatAxis OSEvents chan osEventRecord Buttons map[uint8]button HatAxes map[uint8]hatAxis buttonCloseEvents map[uint8]chan event buttonOpenEvents map[uint8]chan event buttonLongPressEvents map[uint8]chan event Loading Loading @@ -50,6 +50,7 @@ type HatPositionEvent struct { X, Y float32 } // Button changed event type ButtonChangeEvent struct { when } Loading @@ -75,10 +76,10 @@ type HatAngleEvent struct { // ParcelOutEvents interprets waits on the HID.OSEvent channel (so is blocking), then puts the required event(s), on any registered channel(s). func (d HID) ParcelOutEvents() { for { if evt, ok := <-d.OSEvent; ok { if evt, ok := <-d.OSEvents; ok { switch evt.Type { case 1: b:=d.buttons[evt.Index] b := d.Buttons[evt.Index] if evt.Value == 0 { if c, ok := d.buttonOpenEvents[b.number]; ok { c <- ButtonChangeEvent{when{toDuration(evt.Time)}} Loading @@ -94,9 +95,9 @@ func (d HID) ParcelOutEvents() { c <- ButtonChangeEvent{when{toDuration(evt.Time)}} } } d.buttons[evt.Index] = button{b.number, toDuration(evt.Time), evt.Value != 0} d.Buttons[evt.Index] = button{b.number, toDuration(evt.Time), evt.Value != 0} case 2: h:=d.hatAxes[evt.Index] h := d.HatAxes[evt.Index] v := float32(evt.Value) / maxValue switch h.axis { case 1: Loading @@ -109,22 +110,22 @@ func (d HID) ParcelOutEvents() { } } if c, ok := d.hatPositionEvents[h.number]; ok { switch d.hatAxes[evt.Index].axis { switch d.HatAxes[evt.Index].axis { case 1: c <- HatPositionEvent{when{toDuration(evt.Time)}, v, d.hatAxes[evt.Index+1].value} c <- HatPositionEvent{when{toDuration(evt.Time)}, v, d.HatAxes[evt.Index+1].value} case 2: c <- HatPositionEvent{when{toDuration(evt.Time)}, d.hatAxes[evt.Index-1].value, v} c <- HatPositionEvent{when{toDuration(evt.Time)}, d.HatAxes[evt.Index-1].value, v} } } if c, ok := d.hatAngleEvents[h.number]; ok { switch d.hatAxes[evt.Index].axis { switch d.HatAxes[evt.Index].axis { case 1: c <- HatAngleEvent{when{toDuration(evt.Time)}, float32(math.Atan2(float64(v), float64(d.hatAxes[evt.Index+1].value)))} c <- HatAngleEvent{when{toDuration(evt.Time)}, float32(math.Atan2(float64(v), float64(d.HatAxes[evt.Index+1].value)))} case 2: c <- HatAngleEvent{when{toDuration(evt.Time)}, float32(math.Atan2(float64(d.hatAxes[evt.Index-1].value), float64(v)))} c <- HatAngleEvent{when{toDuration(evt.Time)}, float32(math.Atan2(float64(d.HatAxes[evt.Index-1].value), float64(v)))} } } d.hatAxes[evt.Index] = hatAxis{h.number, h.axis, toDuration(evt.Time), v} d.HatAxes[evt.Index] = hatAxis{h.number, h.axis, toDuration(evt.Time), v} default: // log.Println("unknown input type. ",evt.Type & 0x7f) } Loading Loading @@ -190,7 +191,7 @@ func (d HID) OnRotate(hat uint8) chan event { } func (d HID) ButtonExists(button uint8) (ok bool) { for _, v := range d.buttons { for _, v := range d.Buttons { if v.number == button { return true } Loading @@ -199,7 +200,7 @@ func (d HID) ButtonExists(button uint8) (ok bool) { } func (d HID) HatExists(hat uint8) (ok bool) { for _, v := range d.hatAxes { for _, v := range d.HatAxes { if v.number == hat { return true } Loading @@ -208,5 +209,5 @@ func (d HID) HatExists(hat uint8) (ok bool) { } func (d HID) InsertSyntheticEvent(v int16, t uint8, i uint8) { d.OSEvent <- osEventRecord{Value: v, Type: t, Index: i} d.OSEvents <- osEventRecord{Value: v, Type: t, Index: i} } joysticks_linux.go +17 −18 Original line number Diff line number Diff line Loading @@ -4,9 +4,9 @@ package joysticks import ( "encoding/binary" "strconv" "io" "os" "strconv" "time" ) Loading @@ -24,17 +24,17 @@ const maxValue = 1<<15 - 1 // Finds the first unused joystick, from a max of 4. // Intended for bacic use since doesn't return state object. func Capture(registrees ...Channel) []chan event { js := Connect(1) for i := 2; js == nil && i < 5; i++ { js = Connect(i) d := Connect(1) for i := 2; d == nil && i < 5; i++ { d = Connect(i) } if js == nil { if d == nil { return nil } go js.ParcelOutEvents() go d.ParcelOutEvents() chans := make([]chan event, len(registrees)) for i, fns := range registrees { chans[i] = fns.Method(*js, fns.Number) chans[i] = fns.Method(*d, fns.Number) } return chans } Loading @@ -45,35 +45,35 @@ var inputPathSlice = []byte("/dev/input/js ")[0:13] // register channels by using the returned state object's On<xxx>(index) methods. // Note: only one event, of each type '<xxx>', for each 'index', re-registering stops events going on the old channel. // then activate using state objects ParcelOutEvents() method.(usually in a go routine.) func Connect(index int) (js *HID) { func Connect(index int) (d *HID) { r, e := os.OpenFile(string(strconv.AppendUint(inputPathSlice, uint64(index-1), 10)), os.O_RDWR, 0) if e != nil { return nil } js = &HID{make(chan osEventRecord), make(map[uint8]button), make(map[uint8]hatAxis), make(map[uint8]chan event), make(map[uint8]chan event), make(map[uint8]chan event), make(map[uint8]chan event), make(map[uint8]chan event), make(map[uint8]chan event), make(map[uint8]chan event)} d = &HID{make(chan osEventRecord), make(map[uint8]button), make(map[uint8]hatAxis),make(map[uint8]chan event),make(map[uint8]chan event),make(map[uint8]chan event),make(map[uint8]chan event),make(map[uint8]chan event),make(map[uint8]chan event),make(map[uint8]chan event)} // start thread to read joystick events to the joystick.state osEvent channel go eventPipe(r, js.OSEvent) js.populate() return js go eventPipe(r, d.OSEvents) d.populate() return d } // fill in the joysticks available events from the synthetic state events burst produced initially by the driver. func (d HID) populate() { for buttonNumber, hatNumber, axisNumber := 1, 1, 1; ; { evt := <-d.OSEvent evt := <-d.OSEvents switch evt.Type { case 0x81: d.buttons[evt.Index] = button{uint8(buttonNumber), toDuration(evt.Time), evt.Value != 0} d.Buttons[evt.Index] = button{uint8(buttonNumber), toDuration(evt.Time), evt.Value != 0} buttonNumber += 1 case 0x82: d.hatAxes[evt.Index] = hatAxis{uint8(hatNumber), uint8(axisNumber), toDuration(evt.Time), float32(evt.Value) / maxValue} d.HatAxes[evt.Index] = hatAxis{uint8(hatNumber), uint8(axisNumber), toDuration(evt.Time), float32(evt.Value) / maxValue} axisNumber += 1 if axisNumber > 2 { axisNumber = 1 hatNumber += 1 } default: go func() { d.OSEvent <- evt }() // put the consumed, first, after end of synthetic burst, real event, back on channel. go func() { d.OSEvents <- evt }() // put the consumed, first, after end of synthetic burst, real event, back on channel. return } } Loading @@ -98,4 +98,3 @@ func toDuration(m uint32) time.Duration { joysticks_test.go +2 −3 Original line number Diff line number Diff line Loading @@ -77,8 +77,8 @@ func TestHIDsAdvanced(t *testing.T) { if js1 == nil { panic("no HIDs") } if len(js1.buttons) < 10 || len(js1.hatAxes) < 6 { t.Errorf("HID#1, available buttons %d, Hats %d\n", len(js1.buttons), len(js1.hatAxes)/2) if len(js1.Buttons) < 10 || len(js1.HatAxes) < 6 { t.Errorf("HID#1, available buttons %d, Hats %d\n", len(js1.Buttons), len(js1.HatAxes)/2) } b1 := js1.OnClose(1) Loading Loading @@ -130,4 +130,3 @@ func play(s Sound) { panic(err) } } Loading
doc.go +0 −1 Original line number Diff line number Diff line Loading @@ -23,4 +23,3 @@ handle all events directly using the returned HID's OSEvent channel. */ package joysticks
joysticks.go +21 −20 Original line number Diff line number Diff line Loading @@ -20,9 +20,9 @@ type button struct { //HID holds the in-coming event channel, mappings, and registered events for a joystick, and has methods to control and adjust behaviour. type HID struct { OSEvent chan osEventRecord buttons map[uint8]button hatAxes map[uint8]hatAxis OSEvents chan osEventRecord Buttons map[uint8]button HatAxes map[uint8]hatAxis buttonCloseEvents map[uint8]chan event buttonOpenEvents map[uint8]chan event buttonLongPressEvents map[uint8]chan event Loading Loading @@ -50,6 +50,7 @@ type HatPositionEvent struct { X, Y float32 } // Button changed event type ButtonChangeEvent struct { when } Loading @@ -75,10 +76,10 @@ type HatAngleEvent struct { // ParcelOutEvents interprets waits on the HID.OSEvent channel (so is blocking), then puts the required event(s), on any registered channel(s). func (d HID) ParcelOutEvents() { for { if evt, ok := <-d.OSEvent; ok { if evt, ok := <-d.OSEvents; ok { switch evt.Type { case 1: b:=d.buttons[evt.Index] b := d.Buttons[evt.Index] if evt.Value == 0 { if c, ok := d.buttonOpenEvents[b.number]; ok { c <- ButtonChangeEvent{when{toDuration(evt.Time)}} Loading @@ -94,9 +95,9 @@ func (d HID) ParcelOutEvents() { c <- ButtonChangeEvent{when{toDuration(evt.Time)}} } } d.buttons[evt.Index] = button{b.number, toDuration(evt.Time), evt.Value != 0} d.Buttons[evt.Index] = button{b.number, toDuration(evt.Time), evt.Value != 0} case 2: h:=d.hatAxes[evt.Index] h := d.HatAxes[evt.Index] v := float32(evt.Value) / maxValue switch h.axis { case 1: Loading @@ -109,22 +110,22 @@ func (d HID) ParcelOutEvents() { } } if c, ok := d.hatPositionEvents[h.number]; ok { switch d.hatAxes[evt.Index].axis { switch d.HatAxes[evt.Index].axis { case 1: c <- HatPositionEvent{when{toDuration(evt.Time)}, v, d.hatAxes[evt.Index+1].value} c <- HatPositionEvent{when{toDuration(evt.Time)}, v, d.HatAxes[evt.Index+1].value} case 2: c <- HatPositionEvent{when{toDuration(evt.Time)}, d.hatAxes[evt.Index-1].value, v} c <- HatPositionEvent{when{toDuration(evt.Time)}, d.HatAxes[evt.Index-1].value, v} } } if c, ok := d.hatAngleEvents[h.number]; ok { switch d.hatAxes[evt.Index].axis { switch d.HatAxes[evt.Index].axis { case 1: c <- HatAngleEvent{when{toDuration(evt.Time)}, float32(math.Atan2(float64(v), float64(d.hatAxes[evt.Index+1].value)))} c <- HatAngleEvent{when{toDuration(evt.Time)}, float32(math.Atan2(float64(v), float64(d.HatAxes[evt.Index+1].value)))} case 2: c <- HatAngleEvent{when{toDuration(evt.Time)}, float32(math.Atan2(float64(d.hatAxes[evt.Index-1].value), float64(v)))} c <- HatAngleEvent{when{toDuration(evt.Time)}, float32(math.Atan2(float64(d.HatAxes[evt.Index-1].value), float64(v)))} } } d.hatAxes[evt.Index] = hatAxis{h.number, h.axis, toDuration(evt.Time), v} d.HatAxes[evt.Index] = hatAxis{h.number, h.axis, toDuration(evt.Time), v} default: // log.Println("unknown input type. ",evt.Type & 0x7f) } Loading Loading @@ -190,7 +191,7 @@ func (d HID) OnRotate(hat uint8) chan event { } func (d HID) ButtonExists(button uint8) (ok bool) { for _, v := range d.buttons { for _, v := range d.Buttons { if v.number == button { return true } Loading @@ -199,7 +200,7 @@ func (d HID) ButtonExists(button uint8) (ok bool) { } func (d HID) HatExists(hat uint8) (ok bool) { for _, v := range d.hatAxes { for _, v := range d.HatAxes { if v.number == hat { return true } Loading @@ -208,5 +209,5 @@ func (d HID) HatExists(hat uint8) (ok bool) { } func (d HID) InsertSyntheticEvent(v int16, t uint8, i uint8) { d.OSEvent <- osEventRecord{Value: v, Type: t, Index: i} d.OSEvents <- osEventRecord{Value: v, Type: t, Index: i} }
joysticks_linux.go +17 −18 Original line number Diff line number Diff line Loading @@ -4,9 +4,9 @@ package joysticks import ( "encoding/binary" "strconv" "io" "os" "strconv" "time" ) Loading @@ -24,17 +24,17 @@ const maxValue = 1<<15 - 1 // Finds the first unused joystick, from a max of 4. // Intended for bacic use since doesn't return state object. func Capture(registrees ...Channel) []chan event { js := Connect(1) for i := 2; js == nil && i < 5; i++ { js = Connect(i) d := Connect(1) for i := 2; d == nil && i < 5; i++ { d = Connect(i) } if js == nil { if d == nil { return nil } go js.ParcelOutEvents() go d.ParcelOutEvents() chans := make([]chan event, len(registrees)) for i, fns := range registrees { chans[i] = fns.Method(*js, fns.Number) chans[i] = fns.Method(*d, fns.Number) } return chans } Loading @@ -45,35 +45,35 @@ var inputPathSlice = []byte("/dev/input/js ")[0:13] // register channels by using the returned state object's On<xxx>(index) methods. // Note: only one event, of each type '<xxx>', for each 'index', re-registering stops events going on the old channel. // then activate using state objects ParcelOutEvents() method.(usually in a go routine.) func Connect(index int) (js *HID) { func Connect(index int) (d *HID) { r, e := os.OpenFile(string(strconv.AppendUint(inputPathSlice, uint64(index-1), 10)), os.O_RDWR, 0) if e != nil { return nil } js = &HID{make(chan osEventRecord), make(map[uint8]button), make(map[uint8]hatAxis), make(map[uint8]chan event), make(map[uint8]chan event), make(map[uint8]chan event), make(map[uint8]chan event), make(map[uint8]chan event), make(map[uint8]chan event), make(map[uint8]chan event)} d = &HID{make(chan osEventRecord), make(map[uint8]button), make(map[uint8]hatAxis),make(map[uint8]chan event),make(map[uint8]chan event),make(map[uint8]chan event),make(map[uint8]chan event),make(map[uint8]chan event),make(map[uint8]chan event),make(map[uint8]chan event)} // start thread to read joystick events to the joystick.state osEvent channel go eventPipe(r, js.OSEvent) js.populate() return js go eventPipe(r, d.OSEvents) d.populate() return d } // fill in the joysticks available events from the synthetic state events burst produced initially by the driver. func (d HID) populate() { for buttonNumber, hatNumber, axisNumber := 1, 1, 1; ; { evt := <-d.OSEvent evt := <-d.OSEvents switch evt.Type { case 0x81: d.buttons[evt.Index] = button{uint8(buttonNumber), toDuration(evt.Time), evt.Value != 0} d.Buttons[evt.Index] = button{uint8(buttonNumber), toDuration(evt.Time), evt.Value != 0} buttonNumber += 1 case 0x82: d.hatAxes[evt.Index] = hatAxis{uint8(hatNumber), uint8(axisNumber), toDuration(evt.Time), float32(evt.Value) / maxValue} d.HatAxes[evt.Index] = hatAxis{uint8(hatNumber), uint8(axisNumber), toDuration(evt.Time), float32(evt.Value) / maxValue} axisNumber += 1 if axisNumber > 2 { axisNumber = 1 hatNumber += 1 } default: go func() { d.OSEvent <- evt }() // put the consumed, first, after end of synthetic burst, real event, back on channel. go func() { d.OSEvents <- evt }() // put the consumed, first, after end of synthetic burst, real event, back on channel. return } } Loading @@ -98,4 +98,3 @@ func toDuration(m uint32) time.Duration {
joysticks_test.go +2 −3 Original line number Diff line number Diff line Loading @@ -77,8 +77,8 @@ func TestHIDsAdvanced(t *testing.T) { if js1 == nil { panic("no HIDs") } if len(js1.buttons) < 10 || len(js1.hatAxes) < 6 { t.Errorf("HID#1, available buttons %d, Hats %d\n", len(js1.buttons), len(js1.hatAxes)/2) if len(js1.Buttons) < 10 || len(js1.HatAxes) < 6 { t.Errorf("HID#1, available buttons %d, Hats %d\n", len(js1.Buttons), len(js1.HatAxes)/2) } b1 := js1.OnClose(1) Loading Loading @@ -130,4 +130,3 @@ func play(s Sound) { panic(err) } }