package allg5 /* #define ALLEGRO_KCM_AUDIO_SRC #include #include #define USER_EVENT_TYPE ALLEGRO_GET_EVENT_TYPE('u', 's', 'e', 'r') void init_user_event(ALLEGRO_EVENT* e) { e->user.type = USER_EVENT_TYPE; } */ import "C" import ( "errors" "unsafe" ) type EventQueue struct { queue *C.ALLEGRO_EVENT_QUEUE displays map[*C.ALLEGRO_DISPLAY]*Display } type Event interface { Stamp() float64 } type EventBase struct { stamp float64 } func (eb EventBase) Stamp() float64 { return eb.stamp } type DisplayCloseEvent struct { DisplayEvent } type DisplayConnectedEvent struct { DisplayEvent } type DisplayDisconnectedEvent struct { DisplayEvent } type DisplayEvent struct { EventBase Display *Display } type DisplayFoundEvent struct { DisplayEvent } type DisplayHaltDrawingEvent struct { DisplayEvent } type DisplayLostEvent struct { DisplayEvent } type DisplayOrientation int const ( DisplayOrientation0Degrees DisplayOrientation = iota DisplayOrientation90Degrees DisplayOrientation180Degrees DisplayOrientation270Degrees DisplayOrientationFaceUp DisplayOrientationFaceDown ) func toDisplayOrientation(o C.int) DisplayOrientation { switch o { case C.ALLEGRO_DISPLAY_ORIENTATION_0_DEGREES: return DisplayOrientation0Degrees case C.ALLEGRO_DISPLAY_ORIENTATION_90_DEGREES: return DisplayOrientation90Degrees case C.ALLEGRO_DISPLAY_ORIENTATION_180_DEGREES: return DisplayOrientation180Degrees case C.ALLEGRO_DISPLAY_ORIENTATION_270_DEGREES: return DisplayOrientation270Degrees case C.ALLEGRO_DISPLAY_ORIENTATION_FACE_UP: return DisplayOrientationFaceUp case C.ALLEGRO_DISPLAY_ORIENTATION_FACE_DOWN: return DisplayOrientationFaceDown default: panic("not supported") } } type DisplayOrientationEvent struct { DisplayEvent Orientation DisplayOrientation } type DisplayResizeEvent struct { DisplayEvent X, Y int Width int Height int } type DisplayResumeDrawingEvent struct { DisplayEvent } type DisplaySwitchInEvent struct { DisplayEvent } type DisplaySwitchOutEvent struct { DisplayEvent } type KeyEvent struct { EventBase KeyCode Key Display *Display } type KeyCharEvent struct { KeyEvent UnicodeCharacter rune Modifiers KeyMod Repeat bool } type KeyDownEvent struct { KeyEvent } type KeyUpEvent struct { KeyEvent } type MouseButtonDownEvent struct { MouseEvent Button MouseButton Pressure float32 } type MouseButtonUpEvent struct { MouseEvent Button MouseButton Pressure float32 } type MouseEnterEvent struct { MouseEvent } type MouseEvent struct { EventBase X, Y int Z, W int Display *Display } type MouseLeaveEvent struct { MouseEvent } type MouseMoveEvent struct { MouseEvent DeltaX, DeltaY int DeltaZ, DeltaW int Pressure float32 } type RecorderFragmentEvent struct { EventBase Buffer unsafe.Pointer Samples int } type UserEvent struct { EventBase } type UserEventSource struct { source *C.ALLEGRO_EVENT_SOURCE } func NewEventQueue() (*EventQueue, error) { q := C.al_create_event_queue() if q == nil { return nil, errors.New("unable to create event queue") } return &EventQueue{q, map[*C.ALLEGRO_DISPLAY]*Display{}}, nil } func (eq *EventQueue) register(source *C.ALLEGRO_EVENT_SOURCE) { C.al_register_event_source(eq.queue, source) } func (eq *EventQueue) RegisterDisplay(d *Display) { eq.register(C.al_get_display_event_source(d.display)) eq.displays[d.display] = d } func (eq *EventQueue) RegisterMouse() { eq.register(C.al_get_mouse_event_source()) } func (eq *EventQueue) RegisterKeyboard() { eq.register(C.al_get_keyboard_event_source()) } func (eq *EventQueue) RegisterRecorder(rec *Recorder) { eq.register(C.al_get_audio_recorder_event_source(rec.recorder)) } func (eq *EventQueue) RegisterUserEvents(source *UserEventSource) { eq.register(source.source) } func (eq *EventQueue) mapEvent(e *C.ALLEGRO_EVENT) Event { any := (*C.ALLEGRO_ANY_EVENT)(unsafe.Pointer(e)) eb := EventBase{float64(any.timestamp)} switch any._type { case C.ALLEGRO_EVENT_AUDIO_RECORDER_FRAGMENT: recorder := (*C.ALLEGRO_AUDIO_RECORDER_EVENT)(unsafe.Pointer(e)) return &RecorderFragmentEvent{eb, unsafe.Pointer(recorder.buffer), int(recorder.samples)} case C.ALLEGRO_EVENT_DISPLAY_CONNECTED: display := (*C.ALLEGRO_DISPLAY_EVENT)(unsafe.Pointer(e)) return &DisplayConnectedEvent{DisplayEvent{eb, eq.displays[display.source]}} case C.ALLEGRO_EVENT_DISPLAY_CLOSE: display := (*C.ALLEGRO_DISPLAY_EVENT)(unsafe.Pointer(e)) return &DisplayCloseEvent{DisplayEvent{eb, eq.displays[display.source]}} case C.ALLEGRO_EVENT_DISPLAY_DISCONNECTED: display := (*C.ALLEGRO_DISPLAY_EVENT)(unsafe.Pointer(e)) return &DisplayDisconnectedEvent{DisplayEvent{eb, eq.displays[display.source]}} case C.ALLEGRO_EVENT_DISPLAY_FOUND: display := (*C.ALLEGRO_DISPLAY_EVENT)(unsafe.Pointer(e)) return &DisplayFoundEvent{DisplayEvent{eb, eq.displays[display.source]}} case C.ALLEGRO_EVENT_DISPLAY_HALT_DRAWING: display := (*C.ALLEGRO_DISPLAY_EVENT)(unsafe.Pointer(e)) return &DisplayHaltDrawingEvent{DisplayEvent{eb, eq.displays[display.source]}} case C.ALLEGRO_EVENT_DISPLAY_LOST: display := (*C.ALLEGRO_DISPLAY_EVENT)(unsafe.Pointer(e)) return &DisplayLostEvent{DisplayEvent{eb, eq.displays[display.source]}} case C.ALLEGRO_EVENT_DISPLAY_ORIENTATION: display := (*C.ALLEGRO_DISPLAY_EVENT)(unsafe.Pointer(e)) return &DisplayOrientationEvent{DisplayEvent{eb, eq.displays[display.source]}, toDisplayOrientation(display.orientation)} case C.ALLEGRO_EVENT_DISPLAY_RESIZE: display := (*C.ALLEGRO_DISPLAY_EVENT)(unsafe.Pointer(e)) C.al_acknowledge_resize(display.source) return &DisplayResizeEvent{DisplayEvent{eb, eq.displays[display.source]}, int(display.x), int(display.y), int(display.width), int(display.height)} case C.ALLEGRO_EVENT_DISPLAY_RESUME_DRAWING: display := (*C.ALLEGRO_DISPLAY_EVENT)(unsafe.Pointer(e)) return &DisplayResumeDrawingEvent{DisplayEvent{eb, eq.displays[display.source]}} case C.ALLEGRO_EVENT_DISPLAY_SWITCH_IN: display := (*C.ALLEGRO_DISPLAY_EVENT)(unsafe.Pointer(e)) return &DisplaySwitchInEvent{DisplayEvent{eb, eq.displays[display.source]}} case C.ALLEGRO_EVENT_DISPLAY_SWITCH_OUT: display := (*C.ALLEGRO_DISPLAY_EVENT)(unsafe.Pointer(e)) return &DisplaySwitchOutEvent{DisplayEvent{eb, eq.displays[display.source]}} case C.ALLEGRO_EVENT_MOUSE_AXES: mouse := (*C.ALLEGRO_MOUSE_EVENT)(unsafe.Pointer(e)) return &MouseMoveEvent{MouseEvent{eb, int(mouse.x), int(mouse.y), int(mouse.z), int(mouse.w), eq.displays[mouse.display]}, int(mouse.dx), int(mouse.dy), int(mouse.dz), int(mouse.dw), float32(mouse.pressure)} case C.ALLEGRO_EVENT_MOUSE_BUTTON_DOWN: mouse := (*C.ALLEGRO_MOUSE_EVENT)(unsafe.Pointer(e)) return &MouseButtonDownEvent{MouseEvent{eb, int(mouse.x), int(mouse.y), int(mouse.z), int(mouse.w), eq.displays[mouse.display]}, MouseButton(mouse.button), float32(mouse.pressure)} case C.ALLEGRO_EVENT_MOUSE_ENTER_DISPLAY: mouse := (*C.ALLEGRO_MOUSE_EVENT)(unsafe.Pointer(e)) return &MouseEnterEvent{MouseEvent{eb, int(mouse.x), int(mouse.y), int(mouse.z), int(mouse.w), eq.displays[mouse.display]}} case C.ALLEGRO_EVENT_MOUSE_BUTTON_UP: mouse := (*C.ALLEGRO_MOUSE_EVENT)(unsafe.Pointer(e)) return &MouseButtonUpEvent{MouseEvent{eb, int(mouse.x), int(mouse.y), int(mouse.z), int(mouse.w), nil}, MouseButton(mouse.button), float32(mouse.pressure)} case C.ALLEGRO_EVENT_MOUSE_LEAVE_DISPLAY: mouse := (*C.ALLEGRO_MOUSE_EVENT)(unsafe.Pointer(e)) return &MouseLeaveEvent{MouseEvent{eb, int(mouse.x), int(mouse.y), int(mouse.z), int(mouse.w), nil}} case C.ALLEGRO_EVENT_KEY_DOWN: key := (*C.ALLEGRO_KEYBOARD_EVENT)(unsafe.Pointer(e)) return &KeyDownEvent{KeyEvent{eb, Key(key.keycode), nil}} case C.ALLEGRO_EVENT_KEY_UP: key := (*C.ALLEGRO_KEYBOARD_EVENT)(unsafe.Pointer(e)) return &KeyUpEvent{KeyEvent{eb, Key(key.keycode), nil}} case C.ALLEGRO_EVENT_KEY_CHAR: key := (*C.ALLEGRO_KEYBOARD_EVENT)(unsafe.Pointer(e)) return &KeyCharEvent{KeyEvent{eb, Key(key.keycode), nil}, rune(key.unichar), KeyMod(key.modifiers), bool(key.repeat)} case C.USER_EVENT_TYPE: return &UserEvent{eb} } return nil } func (eq *EventQueue) Get() Event { var event C.ALLEGRO_EVENT if !bool(C.al_get_next_event(eq.queue, &event)) { return nil } return eq.mapEvent(&event) } func (eq *EventQueue) GetWait() Event { var event C.ALLEGRO_EVENT C.al_wait_for_event(eq.queue, &event) return eq.mapEvent(&event) } func (eq *EventQueue) Destroy() { C.al_destroy_event_queue(eq.queue) } func (eq *EventQueue) unregister(source *C.ALLEGRO_EVENT_SOURCE) { C.al_unregister_event_source(eq.queue, source) } func (eq *EventQueue) UnregisterDisplay(d *Display) { eq.unregister(C.al_get_display_event_source(d.display)) delete(eq.displays, d.display) } func NewUserEventSource() *UserEventSource { s := (*C.ALLEGRO_EVENT_SOURCE)(C.malloc(C.sizeof_ALLEGRO_EVENT_SOURCE)) source := &UserEventSource{s} C.al_init_user_event_source(s) return source } func (s *UserEventSource) Destroy() { C.al_destroy_user_event_source(s.source) C.free(unsafe.Pointer(s.source)) } func (s *UserEventSource) EmitEvent() bool { e := (*C.ALLEGRO_EVENT)(C.malloc(C.sizeof_ALLEGRO_EVENT)) C.init_user_event(e) return bool(C.al_emit_user_event(s.source, e, nil)) } func GetTime() float64 { return float64(C.al_get_time()) }