Commit 920f0cfe authored by simon's avatar simon
Browse files

when struct and rotate event

parent 8349cff8
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -28,9 +28,9 @@ Example: play a note when pressing button #1. hat position changes frequency, y

	func main() {
		jsevents := Capture(
			Channel{10, State.OnLong}, // events[0] button #10 long pressed
			Channel{1, State.OnClose}, // events[1] button #1 closes
			Channel{1, State.OnMove},  // events[2] hat #1 moves
			Channel{10, Joystick.OnLong}, // events[0] button #10 long pressed
			Channel{1, Joystick.OnClose}, // events[1] button #1 closes
			Channel{1, Joystick.OnMove},  // events[2] hat #1 moves
		)
		var x float32 = .5
		var f time.Duration = time.Second / 440
+3 −3
Original line number Diff line number Diff line
@@ -13,9 +13,9 @@ import . "github.com/splace/sounds"

func main() {
	jsevents := Capture(
		Channel{10, State.OnLong}, // events[0] button #10 long pressed
		Channel{1, State.OnClose}, // events[1] button #1 closes
		Channel{1, State.OnMove},  // events[2] hat #1 moves
		Channel{10, Joystick.OnLong}, // events[0] button #10 long pressed
		Channel{1, Joystick.OnClose}, // events[1] button #1 closes
		Channel{1, Joystick.OnMove},  // events[2] hat #1 moves
	)
	var x float32 = .5
	var f time.Duration = time.Second / 440
+92 −34
Original line number Diff line number Diff line
@@ -2,6 +2,7 @@ package joysticks

import (
	"time"
	"math"
)

type hatAxis struct {
@@ -25,68 +26,104 @@ type Joystick struct {
	buttonCloseEvents     map[uint8]chan event
	buttonOpenEvents      map[uint8]chan event
	buttonLongPressEvents map[uint8]chan event
	hatChangeEvents       map[uint8]chan event
	hatPanXEvents         map[uint8]chan event
	hatPanYEvents         map[uint8]chan event
	hatPositionEvents     map[uint8]chan event
	hatAngleEvents        map[uint8]chan event
}

type event interface {
	Moment() time.Duration
}

type HatChangeEvent struct {
type when struct {
	time time.Duration
	X, Y float32
}

func (b HatChangeEvent) Moment() time.Duration {
func (b when) Moment() time.Duration {
	return b.time
}

type HatPositionEvent struct {
	when
	X, Y float32
}

type ButtonChangeEvent struct {
	time time.Duration
	when
}

func (b ButtonChangeEvent) Moment() time.Duration {
	return b.time
type HatPanXEvent struct {
	when
	V float32
}

type HatPanYEvent struct {
	when
	V float32
}

type HatAngleEvent struct {
	when
	Angle float32
}

// ParcelOutEvents interprets whats on the State.OSEvent channel, then puts the required event(s), on any registered channel(s).
func (js Joystick) ParcelOutEvents() {
	for {
		evt, ok := <-js.OSEvent
		if !ok {
			break
		}
		if evt, ok := <-js.OSEvent; ok {
			switch evt.Type {
			case 1:
				if evt.Value == 0 {
					if c, ok := js.buttonOpenEvents[js.buttons[evt.Index].number]; ok {
					c <- ButtonChangeEvent{toDuration(evt.Time)}
						c <- ButtonChangeEvent{when{toDuration(evt.Time)}}
					}
					if c, ok := js.buttonLongPressEvents[js.buttons[evt.Index].number]; ok {
						if toDuration(evt.Time) > js.buttons[evt.Index].time+time.Second {
						c <- ButtonChangeEvent{toDuration(evt.Time)}
							c <- ButtonChangeEvent{when{toDuration(evt.Time)}}
						}
					}
				}
				if evt.Value == 1 {
					if c, ok := js.buttonCloseEvents[js.buttons[evt.Index].number]; ok {
					c <- ButtonChangeEvent{toDuration(evt.Time)}
						c <- ButtonChangeEvent{when{toDuration(evt.Time)}}
					}
				}
				js.buttons[evt.Index] = button{js.buttons[evt.Index].number, toDuration(evt.Time), evt.Value != 0}
			case 2:
			if c, ok := js.hatChangeEvents[js.hatAxes[evt.Index].number]; ok {
				switch js.hatAxes[evt.Index].axis {
				case 1:
					c <- HatChangeEvent{toDuration(evt.Time), float32(evt.Value) / maxValue, js.hatAxes[evt.Index+1].value}
					if c, ok := js.hatPanXEvents[js.hatAxes[evt.Index].number]; ok {
						c <- HatPanXEvent{when{toDuration(evt.Time)}, float32(evt.Value) / maxValue}
					}
				case 2:
					c <- HatChangeEvent{toDuration(evt.Time), js.hatAxes[evt.Index-1].value, float32(evt.Value) / maxValue}
					if c, ok := js.hatPanYEvents[js.hatAxes[evt.Index].number]; ok {
						c <- HatPanYEvent{when{toDuration(evt.Time)}, float32(evt.Value) / maxValue}
					}
				}
				if c, ok := js.hatPositionEvents[js.hatAxes[evt.Index].number]; ok {
					switch js.hatAxes[evt.Index].axis {
					case 1:
						c <- HatPositionEvent{when{toDuration(evt.Time)}, float32(evt.Value) / maxValue, js.hatAxes[evt.Index+1].value}
					case 2:
						c <- HatPositionEvent{when{toDuration(evt.Time)}, js.hatAxes[evt.Index-1].value, float32(evt.Value) / maxValue}
					}
				}
				if c, ok := js.hatAngleEvents[js.hatAxes[evt.Index].number]; ok {
					switch js.hatAxes[evt.Index].axis {
					case 1:
						c <- HatAngleEvent{when{toDuration(evt.Time)}, float32(math.Atan2(float64(evt.Value),float64(js.hatAxes[evt.Index+1].value)))}
					case 2:
						c <- HatAngleEvent{when{toDuration(evt.Time)}, float32(math.Atan2(float64(js.hatAxes[evt.Index-1].value), float64(evt.Value) / maxValue))}
					}
				}
				js.hatAxes[evt.Index] = hatAxis{js.hatAxes[evt.Index].number, js.hatAxes[evt.Index].axis, toDuration(evt.Time), float32(evt.Value) / maxValue}
			default:
				// log.Println("unknown input type. ",evt.Type & 0x7f)
			}
		} else {
			break
		}
	}
}

@@ -120,7 +157,28 @@ func (js Joystick) OnLong(button uint8) chan event {
// hat moved
func (js Joystick) OnMove(hat uint8) chan event {
	c := make(chan event)
	js.hatChangeEvents[hat] = c
	js.hatPositionEvents[hat] = c
	return c
}

// hat axis-X moved
func (js Joystick) OnPanX(hat uint8) chan event {
	c := make(chan event)
	js.hatPanXEvents[hat] = c
	return c
}

// hat axis-Y moved
func (js Joystick) OnPanY(hat uint8) chan event {
	c := make(chan event)
	js.hatPanYEvents[hat] = c
	return c
}

// hat axis-Y moved
func (js Joystick) OnRotate(hat uint8) chan event {
	c := make(chan event)
	js.hatAngleEvents[hat] = c
	return c
}

+2 −2
Original line number Diff line number Diff line
@@ -44,13 +44,13 @@ var inputPathSlice = []byte("/dev/input/js ")[0:13]
// Connect sets up a go routine that puts a joysticks events onto registered channels.
// 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.)
// then activate using state objects ParcelOutEvents() method.(blocking.)
func Connect(index int) (js *Joystick) {
	r, e := os.OpenFile(string(strconv.AppendUint(inputPathSlice, uint64(index-1), 10)), os.O_RDWR, 0)
	if e != nil {
		return nil
	}
	js = &Joystick{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)}
	js = &Joystick{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()
+16 −10
Original line number Diff line number Diff line
@@ -17,7 +17,8 @@ func TestJoysticksCapture(t *testing.T) {
	events := Capture(
		Channel{10, Joystick.OnLong}, // event[0] button #10 long pressed
		Channel{1, Joystick.OnClose}, // event[1] button #1 closes
		Channel{1, Joystick.OnMove},  // event[2] hat #1 moves
		Channel{1, Joystick.OnRotate},  // event[2] hat #1 rotates
		Channel{2, Joystick.OnRotate},  // event[2] hat #1 rotates
	)
	var x float32 = .5
	var f time.Duration = time.Second / 440
@@ -28,8 +29,10 @@ func TestJoysticksCapture(t *testing.T) {
		case <-events[1]:
			play(NewSound(NewTone(f, float64(x)), time.Second/3))
		case h := <-events[2]:
			x = h.(HatChangeEvent).X/2 + .5
			f = time.Duration(100*math.Pow(2, float64(h.(HatChangeEvent).Y))) * time.Second / 44000
			fmt.Println(h.(HatAngleEvent).Angle)
			x = h.(HatAngleEvent).Angle/6.28 + .5
		case h := <-events[3]:
			f = time.Duration(100*math.Pow(2, float64(h.(HatAngleEvent).Angle)/6.28)) * time.Second / 44000
		}
	}
}
@@ -58,11 +61,11 @@ func TestJoysticksMutipleCapture(t *testing.T) {
		case <-events2[1]:
			play(NewSound(NewTone(f, float64(x)), time.Second/3))
		case h := <-events1[2]:
			x = h.(HatChangeEvent).X/2 + .5
			f = time.Duration(100*math.Pow(2, float64(h.(HatChangeEvent).Y))) * time.Second / 44000
			x = h.(HatPositionEvent).X/2 + .5
			f = time.Duration(100*math.Pow(2, float64(h.(HatPositionEvent).Y))) * time.Second / 44000
		case h := <-events2[2]:
			x = h.(HatChangeEvent).X/2 + .5
			f = time.Duration(100*math.Pow(2, float64(h.(HatChangeEvent).Y))) * time.Second / 44000
			x = h.(HatPositionEvent).X/2 + .5
			f = time.Duration(100*math.Pow(2, float64(h.(HatPositionEvent).Y))) * time.Second / 44000
		}
	}
}
@@ -83,7 +86,8 @@ func TestJoysticksAdvanced(t *testing.T) {
	b4 := js1.OnClose(4)
	quit := js1.OnOpen(10)
	h1 := js1.OnMove(1)
	h2 := js1.OnMove(2)
	h4 := js1.OnPanX(2)
	h5 := js1.OnPanY(2)
	h3 := js1.OnMove(3)
	go js1.ParcelOutEvents()
	time.AfterFunc(time.Second*10, func() { js1.InsertSyntheticEvent(1, 1, 1) }) // value=1 (close),type=1 (button), index=1, so fires b1 after 10 seconds
@@ -102,10 +106,12 @@ func TestJoysticksAdvanced(t *testing.T) {
			play(NewSound(NewTone(time.Second/150, 1), time.Second/3))
		case h := <-h1:
			fmt.Println("hat 1 moved", h)
		case h := <-h2:
			fmt.Println("hat 2 moved", h)
		case h := <-h3:
			fmt.Println("hat 3 moved", h)
		case h := <-h4:
			fmt.Println("hat 2 X moved", h.(HatPanXEvent).V)
		case h := <-h5:
			fmt.Println("hat 2 Y moved", h)
		}
	}
}