Browse Source

Wrapping more functionality.

Beoran 6 years ago
parent
commit
8a687f8699
11 changed files with 989 additions and 570 deletions
  1. 1 0
      al/aid.go
  2. 3 452
      al/al.go
  3. 3 64
      al/audio.go
  4. 45 0
      al/config.go
  5. 19 0
      al/cpu.go
  6. 78 54
      al/display.go
  7. 582 0
      al/event.go
  8. 110 0
      al/file.go
  9. 10 0
      al/keyboard.go
  10. 66 0
      al/mode.go
  11. 72 0
      al/touch_input.go

+ 1 - 0
al/aid.go

@@ -131,6 +131,7 @@ func CStrings(args []string) (argc C.int, argv **C.char) {
     for i, s := range args {
         tmpslice[i] = cstr(s)
     }
+    argc = C.int(length)
     return argc, argv
 }
 

+ 3 - 452
al/al.go

@@ -320,458 +320,6 @@ func Rest(seconds float64) {
     C.al_rest(C.double(seconds))
 }
 
-// Event Type, not to avoid complications.
-// type EVENT_TYPE C.ALLEGRO_EVENT_TYPE
-
-// Event Type constants
-const (
-    EVENT_JOYSTICK_AXIS          = C.ALLEGRO_EVENT_JOYSTICK_AXIS
-    EVENT_JOYSTICK_BUTTON_DOWN   = C.ALLEGRO_EVENT_JOYSTICK_BUTTON_DOWN
-    EVENT_JOYSTICK_BUTTON_UP     = C.ALLEGRO_EVENT_JOYSTICK_BUTTON_UP
-    EVENT_JOYSTICK_CONFIGURATION = C.ALLEGRO_EVENT_JOYSTICK_CONFIGURATION
-
-    EVENT_KEY_DOWN = C.ALLEGRO_EVENT_KEY_DOWN
-    EVENT_KEY_CHAR = C.ALLEGRO_EVENT_KEY_CHAR
-    EVENT_KEY_UP   = C.ALLEGRO_EVENT_KEY_UP
-
-    EVENT_MOUSE_AXES          = C.ALLEGRO_EVENT_MOUSE_AXES
-    EVENT_MOUSE_BUTTON_DOWN   = C.ALLEGRO_EVENT_MOUSE_BUTTON_DOWN
-    EVENT_MOUSE_BUTTON_UP     = C.ALLEGRO_EVENT_MOUSE_BUTTON_UP
-    EVENT_MOUSE_ENTER_DISPLAY = C.ALLEGRO_EVENT_MOUSE_ENTER_DISPLAY
-    EVENT_MOUSE_LEAVE_DISPLAY = C.ALLEGRO_EVENT_MOUSE_LEAVE_DISPLAY
-    EVENT_MOUSE_WARPED        = C.ALLEGRO_EVENT_MOUSE_WARPED
-
-    EVENT_TIMER = C.ALLEGRO_EVENT_TIMER
-
-    EVENT_DISPLAY_EXPOSE      = C.ALLEGRO_EVENT_DISPLAY_EXPOSE
-    EVENT_DISPLAY_RESIZE      = C.ALLEGRO_EVENT_DISPLAY_RESIZE
-    EVENT_DISPLAY_CLOSE       = C.ALLEGRO_EVENT_DISPLAY_CLOSE
-    EVENT_DISPLAY_LOST        = C.ALLEGRO_EVENT_DISPLAY_LOST
-    EVENT_DISPLAY_FOUND       = C.ALLEGRO_EVENT_DISPLAY_FOUND
-    EVENT_DISPLAY_SWITCH_IN   = C.ALLEGRO_EVENT_DISPLAY_SWITCH_IN
-    EVENT_DISPLAY_SWITCH_OUT  = C.ALLEGRO_EVENT_DISPLAY_SWITCH_OUT
-    EVENT_DISPLAY_ORIENTATION = C.ALLEGRO_EVENT_DISPLAY_ORIENTATION
-)
-
-func EVENT_TYPE_IS_USER(t int) bool {
-    return ((t) >= 512)
-}
-
-func GET_EVENT_TYPE(a, b, c, d int) int {
-    return AL_ID(a, b, c, d)
-}
-
-func getAnyEvenTimestamp(any *C.ALLEGRO_ANY_EVENT) float64 {
-    return float64(any.timestamp)
-}
-
-// Event sources that emit events.
-type EventSource C.ALLEGRO_EVENT_SOURCE
-
-// Wraps an event source pointer but sets no finalizer (not needed anyway) 
-func wrapEventSourceRaw(ptr *C.ALLEGRO_EVENT_SOURCE) *EventSource {
-    return (*EventSource)(ptr)
-}
-
-// Converts wrapper Event source pointer to C Allegro event pointer
-func (self *EventSource) toC() *C.ALLEGRO_EVENT_SOURCE {
-    return (*C.ALLEGRO_EVENT_SOURCE)(self)
-}
-
-// Events that the event system emits.
-type Event C.ALLEGRO_EVENT
-
-// Converts wrapper Event pointer to C Allegro event pointer
-func (self *Event) toC() *C.ALLEGRO_EVENT {
-    return (*C.ALLEGRO_EVENT)(self)
-}
-
-// Returns an unsafe pointer to the event 
-func (self *Event) toPointer() unsafe.Pointer {
-    return unsafe.Pointer(self.toC())
-}
-
-// Converts wrapper Event pointer to C Allegro any event
-func (self *Event) ANY_EVENT() *C.ALLEGRO_ANY_EVENT {
-    return (*C.ALLEGRO_ANY_EVENT)(self.toPointer())
-}
-
-// Converts wrapper Event pointer to C Allegro display event
-func (self *Event) DISPLAY_EVENT() *C.ALLEGRO_DISPLAY_EVENT {
-    return (*C.ALLEGRO_DISPLAY_EVENT)(self.toPointer())
-}
-
-// Converts wrapper Event pointer to C Allegro joystick event
-func (self *Event) JOYSTICK_EVENT() *C.ALLEGRO_JOYSTICK_EVENT {
-    return (*C.ALLEGRO_JOYSTICK_EVENT)(self.toPointer())
-}
-
-// Converts wrapper Event pointer to C Allegro event
-func (self *Event) KEYBOARD_EVENT() *C.ALLEGRO_KEYBOARD_EVENT {
-    return (*C.ALLEGRO_KEYBOARD_EVENT)(self.toPointer())
-}
-
-// Converts wrapper Event pointer to C Allegro touch event
-func (self *Event) TOUCH_EVENT() *C.ALLEGRO_TOUCH_EVENT {
-    return (*C.ALLEGRO_TOUCH_EVENT)(self.toPointer())
-}
-
-// Converts wrapper Event pointer to C Allegro mouse event
-func (self *Event) MOUSE_EVENT() *C.ALLEGRO_MOUSE_EVENT {
-    return (*C.ALLEGRO_MOUSE_EVENT)(self.toPointer())
-}
-
-// Converts wrapper Event pointer to C Allegro timer event
-func (self *Event) TIMER_EVENT() *C.ALLEGRO_TIMER_EVENT {
-    return (*C.ALLEGRO_TIMER_EVENT)(self.toPointer())
-}
-
-// Converts wrapper Event pointer to C Allegro event
-func (self *Event) USER_EVENT() *C.ALLEGRO_USER_EVENT {
-    return (*C.ALLEGRO_USER_EVENT)(self.toPointer())
-}
-
-// Returns the type of the event.
-func (self *Event) Type() int {
-    return int(self.ANY_EVENT()._type)
-}
-
-// Returns the timestamp of the event.
-func (self *Event) Timestamp() float64 {
-    return float64(self.ANY_EVENT().timestamp)
-}
-
-// Returns the event source of the event
-func (self *Event) EventSource() *EventSource {
-    return (*EventSource)(self.ANY_EVENT().source)
-}
-
-// Returns true if this is a dispay event, false if not.
-func (self *Event) IsDisplay() bool {
-    t := self.Type()
-    return (t >= EVENT_DISPLAY_EXPOSE) && (t <= EVENT_DISPLAY_ORIENTATION)
-}
-
-// Returns true if this is a mouse event, false if not.
-func (self *Event) IsMouse() bool {
-    t := self.Type()
-    return (t >= EVENT_MOUSE_AXES) && (t <= EVENT_MOUSE_WARPED)
-}
-
-// Returns true if this is a Joystick event, false if not.
-func (self *Event) IsJoystick() bool {
-    t := self.Type()
-    return (t >= EVENT_JOYSTICK_AXIS) && (t <= EVENT_JOYSTICK_CONFIGURATION)
-}
-
-// Returns true if this is a keyboard event, false if not.
-func (self *Event) IsKeyboard() bool {
-    t := self.Type()
-    return (t >= EVENT_KEY_DOWN) && (t <= EVENT_KEY_UP)
-}
-
-// Returns true if this is a timer event, false if not.
-func (self *Event) IsTimer() bool {
-    t := self.Type()
-    return (t == EVENT_TIMER)
-}
-
-// Returns true if this is a user event, false if not.
-func (self *Event) IsUser() bool {
-    t := self.Type()
-    return EVENT_TYPE_IS_USER(t)
-}
-
-// Returns the event's source pointer
-func (self *Event) EVENT_SOURCE() *C.ALLEGRO_EVENT_SOURCE {
-    return self.ANY_EVENT().source
-}
-
-// Returns an unsafe pointer to the event's source pointer
-func (self *Event) EVENT_SOURCE_PTR() unsafe.Pointer {
-    return unsafe.Pointer(self.ANY_EVENT())
-}
-
-// Returns the display that has emitted the event. Will return nil if 
-// this is not a display event.
-func (self *Event) DisplayDisplay() *Display {
-    if !(self.IsDisplay()) {
-        return nil
-    }
-    return wrapDisplayRaw((*C.ALLEGRO_DISPLAY)(self.EVENT_SOURCE_PTR()))
-}
-
-// Returns the X position of the display event. Will return garbage 
-// if this is not a display event.
-func (self *Event) DisplayX() int {
-    return int((self.DISPLAY_EVENT()).x)
-}
-
-// Returns the Y position of the display event. Will return garbage 
-// if this is not a display event.
-func (self *Event) DisplayY() int {
-    return int(self.DISPLAY_EVENT().y)
-}
-
-// Returns the width of the display event. Will return garbage 
-// if this is not a display event.
-func (self *Event) DisplayWidth() int {
-    return int(self.DISPLAY_EVENT().width)
-}
-
-// Returns the height of the display event. Will return garbage 
-// if this is not a display event.
-func (self *Event) DisplayHeight() int {
-    return int(self.DISPLAY_EVENT().height)
-}
-
-// Returns the orientation of the display event. Will return garbage 
-// if this is not a display event.
-func (self *Event) DisplayOrientation() int {
-    return int(self.DISPLAY_EVENT().orientation)
-}
-
-// XXX: maybe also wrap the source in a Joystick type? 
-
-// Returns the stick number of the joystick event. Will return garbage 
-// if this is not a joystick event.
-func (self *Event) JoystickStick() int {
-    return int(self.JOYSTICK_EVENT().stick)
-}
-
-// Returns the axis number of the joystick event. Will return garbage 
-// if this is not a joystick event.
-func (self *Event) JoystickAxis() int {
-    return int(self.JOYSTICK_EVENT().axis)
-}
-
-// Returns the button number of the joystick event. Will return garbage 
-// if this is not a joystick event.
-func (self *Event) JoystickButton() int {
-    return int(self.JOYSTICK_EVENT().button)
-}
-
-// Returns the position of the joystick event. Will return garbage 
-// if this is not a joystick event.
-func (self *Event) JoystickPos() float32 {
-    return float32(self.JOYSTICK_EVENT().pos)
-}
-
-/// XXX also wrap Keyboard event source?
-
-// Returns the display that has emitted the keyboard event. Will return nil if 
-// this is not a keyboard event.
-func (self *Event) KeyboardDisplay() *Display {
-    if !(self.IsKeyboard()) {
-        return nil
-    }
-    return wrapDisplayRaw(self.KEYBOARD_EVENT().display)
-}
-
-// Returns the keycode of the keyboard event. Returns garbage 
-// if this is not a keyboard event.
-func (self *Event) KeyboardKeycode() int {
-    return int(self.KEYBOARD_EVENT().keycode)
-}
-
-// Returns the unichar of the keyboard event. Returns garbage 
-// if this is not a keyboard event.
-func (self *Event) KeyboardUnichar() rune {
-    return rune(self.KEYBOARD_EVENT().unichar)
-}
-
-// Returns the modifiers of the keyboard event. Returns garbage 
-// if this is not a keyboard event.
-func (self *Event) KeyboardModifiers() int {
-    return int(self.KEYBOARD_EVENT().modifiers)
-}
-
-// Returns is the keyboard event was autorepeated or not. Returns garbage 
-// if this is not a keyboard event.
-func (self *Event) KeyboardRepeat() bool {
-    return bool(self.KEYBOARD_EVENT().repeat)
-}
-
-// Returns the x postion of the mouse event. Returns garbage 
-// if this is not a mouse event.
-func (self *Event) MouseX() int {
-    return int(self.MOUSE_EVENT().x)
-}
-
-// Returns the y postion of the mouse event. Returns garbage 
-// if this is not a mouse event.
-func (self *Event) MouseY() int {
-    return int(self.MOUSE_EVENT().y)
-}
-
-// Returns the z postion of the mouse event. Returns garbage 
-// if this is not a mouse event.
-func (self *Event) MouseZ() int {
-    return int(self.MOUSE_EVENT().z)
-}
-
-// Returns the w postion of the mouse event. Returns garbage 
-// if this is not a mouse event.
-func (self *Event) MouseW() int {
-    return int(self.MOUSE_EVENT().w)
-}
-
-// Returns the dx of the mouse event. Returns garbage 
-// if this is not a mouse event.
-func (self *Event) MouseDX() int {
-    return int(self.MOUSE_EVENT().dx)
-}
-
-// Returns the dy of the mouse event. Returns garbage 
-// if this is not a mouse event.
-func (self *Event) MouseDY() int {
-    return int(self.MOUSE_EVENT().dy)
-}
-
-// Returns the dz of the mouse event. Returns garbage 
-// if this is not a mouse event.
-func (self *Event) MouseDZ() int {
-    return int(self.MOUSE_EVENT().dz)
-}
-
-// Returns the dw of the mouse event. Returns garbage 
-// if this is not a mouse event.
-func (self *Event) MouseDW() int {
-    return int(self.MOUSE_EVENT().dw)
-}
-
-// Returns the button of the mouse event. Returns garbage 
-// if this is not a mouse event.
-func (self *Event) MouseButton() int {
-    return int(self.MOUSE_EVENT().button)
-}
-
-// Returns the pressure of the mouse event. Returns garbage 
-// if this is not a mouse event.
-func (self *Event) MousePressure() float32 {
-    return float32(self.MOUSE_EVENT().pressure)
-}
-
-// Returns the display that has emitted the mouse event. Will return nil if 
-// this is not a mouse event.
-func (self *Event) MouseDisplay() *Display {
-    if !(self.IsMouse()) {
-        return nil
-    }
-    return wrapDisplayRaw(self.MOUSE_EVENT().display)
-}
-
-// Returns the error of the timer event. Returns garbage 
-// if this is not a timer event.
-func (self *Event) TimerError() float64 {
-    return float64(self.TIMER_EVENT().error)
-}
-
-// Returns the ticks of the timer event. Returns garbage 
-// if this is not a timer event.
-func (self *Event) TimerCount() int64 {
-    return int64(self.TIMER_EVENT().count)
-}
-
-// Wrapping of user event seems not really meaningful in Go so leave that out.
-
-// Event queues.
-type EventQueue struct {
-    handle *C.ALLEGRO_EVENT_QUEUE
-}
-
-// Destroys the event queue.
-func (self *EventQueue) Destroy() {
-    if self.handle != nil {
-        C.al_destroy_event_queue(self.handle)
-    }
-    self.handle = nil
-}
-
-// Wraps an event queue, but does not set a finalizer.
-func wrapEventQueueRaw(handle *C.ALLEGRO_EVENT_QUEUE) *EventQueue {
-    if handle == nil {
-        return nil
-    }
-    return &EventQueue{handle}
-}
-
-// Wraps an event queue and sets a finalizer that calls Destroy
-func wrapEventQueue(handle *C.ALLEGRO_EVENT_QUEUE) *EventQueue {
-    result := wrapEventQueueRaw(handle)
-    if result != nil {
-        runtime.SetFinalizer(result, func(me *EventQueue) { me.Destroy() })
-    }
-    return result
-}
-
-// Create an event queue.
-func CreateEventQueue() *EventQueue {
-    return wrapEventQueue(C.al_create_event_queue())
-}
-
-// Register an event source with self. 
-func (self *EventQueue) RegisterEventSource(src *EventSource) {
-    C.al_register_event_source(self.handle, src.toC())
-}
-
-// Unregister an event source with self. 
-func (self *EventQueue) UnregisterEventSource(src *EventSource) {
-    C.al_unregister_event_source(self.handle, src.toC())
-}
-
-// Returns true if the event queue self is empty, false if not.
-func (self *EventQueue) IsEmpty() bool {
-    return bool(C.al_is_event_queue_empty(self.handle))
-}
-
-// Returns the next event from the event queue as well as a bool
-// to signify if an event was fetched sucessfully or not.
-func (self *EventQueue) GetNextEvent() (event *Event, ok bool) {
-    event = &Event{}
-    ok = bool(C.al_get_next_event(self.handle, event.toC()))
-    return event, ok
-}
-
-// Peeks at the next event in the event queue and returns it as well as a bool
-// to signify if an event was fetched sucessfully or not.
-func (self *EventQueue) PeekNextEvent() (event *Event, ok bool) {
-    event = &Event{}
-    ok = bool(C.al_peek_next_event(self.handle, event.toC()))
-    return event, ok
-}
-
-// Drops the next event from the event queue
-func (self *EventQueue) DropNextEvent() bool {
-    return bool(C.al_drop_next_event(self.handle))
-}
-
-// Flushes the event queue
-func (self *EventQueue) Flush() {
-    C.al_flush_event_queue(self.handle)
-}
-
-// Waits for the next event from the event queue 
-func (self *EventQueue) WaitForEvent() (event *Event) {
-    event = &Event{}
-    C.al_wait_for_event(self.handle, event.toC())
-    return event
-}
-
-// Waits for secs seconds the next event from the event queue 
-func (self *EventQueue) WaitForEventTimed(secs float32) (event *Event, ok bool) {
-    event = &Event{}
-    ok = bool(C.al_wait_for_event_timed(self.handle, event.toC(), C.float(secs)))
-    return event, ok
-}
-
-/*
-// Emitting user events is omitted for now.
-TODO: 
-AL_FUNC(bool, al_wait_for_event_until, (ALLEGRO_EVENT_QUEUE *queue,
-                                        ALLEGRO_EVENT *ret_event,
-                                        ALLEGRO_TIMEOUT *timeout));
-*/
 
 type Timeout = C.ALLEGRO_TIMEOUT
 
@@ -779,6 +327,9 @@ func (tout * Timeout) Init(seconds float64) {
     C.al_init_timeout(tout, C.double(seconds))
 }
 
+func (tout * Timeout) toC() (* C.ALLEGRO_TIMEOUT) {
+    return (* C.ALLEGRO_TIMEOUT)(tout)
+}
 
 // Precise (?) Timer 
 type Timer struct {

+ 3 - 64
al/audio.go

@@ -23,7 +23,7 @@ const (
 )
 
 // Converts wrapper Event pointer to C Allegro audio recorder event
-func (self *Event) AUDIO_RECORDER_EVENT() *C.ALLEGRO_AUDIO_RECORDER_EVENT {
+func (self *EventUnion) AUDIO_RECORDER_EVENT() *C.ALLEGRO_AUDIO_RECORDER_EVENT {
     return (*C.ALLEGRO_AUDIO_RECORDER_EVENT)(self.toPointer())
 }
 
@@ -906,67 +906,6 @@ func LoadAudioStream(filename string, buffer_count, samples uint) *AudioStream {
     return LoadAudioStreamRaw(filename, buffer_count, samples).SetDestroyFinalizer()
 }
 
-// Allegro's own file for cross platform and physfs reasons.
-type File struct {
-    handle *C.ALLEGRO_FILE
-}
-
-// Closes the Allegro file
-func (self *File) Close() {
-    if self.handle != nil {
-        C.al_fclose(self.handle)
-    }
-    self.handle = nil
-}
-
-// Returns the low level handle of the file 
-func (self *File) toC() * C.ALLEGRO_FILE {
-    return self.handle
-}
-
-// Wraps an ALLEGRO_FILE into a File
-func wrapFileRaw(file *C.ALLEGRO_FILE) *File {
-    if file == nil {
-        return nil
-    }
-    return &File{file}
-}
-
-// Opens an Allegro File
-func openFile(filename, mode string) *C.ALLEGRO_FILE {
-    cfilename := cstr(filename)
-    defer cstrFree(cfilename)
-    cmode := cstr(mode)
-    defer cstrFree(cmode)
-    return C.al_fopen(cfilename, cmode)
-}
-
-// Sets up a finalizer for this File that calls Close()
-func (self *File) SetCloseFinalizer() *File {
-    if self != nil {
-        runtime.SetFinalizer(self, func(me *File) { me.Close() })
-    }
-    return self
-}
-
-// Wraps a file and sets up a finalizer that calls Destroy()
-func wrapFile(data *C.ALLEGRO_FILE) *File {
-    self := wrapFileRaw(data)
-    return self.SetCloseFinalizer()
-}
-
-// Opens a file with no finalizer set
-func OpenFileRaw(filename, mode string) *File {
-    self := openFile(filename, mode)
-    return wrapFileRaw(self)
-}
-
-// Opens a file with a Close finalizer set
-func OpenFile(filename, mode string) *File {
-    self := OpenFileRaw(filename, mode)
-    return self.SetCloseFinalizer()
-}
-
 // Loads a Sample from a File. Filetype is a file extension that identifies the file type 
 // like (.wav, .ogg, etc))
 func (self *File) loadSample(filetype string) *C.ALLEGRO_SAMPLE {
@@ -1093,8 +1032,8 @@ func wrapAudioRecorderEvent(event *C.ALLEGRO_AUDIO_RECORDER_EVENT) *AudioRecorde
     return (*AudioRecorderEvent)(event)
 }
 
-// Converts an event into an allegro recorder event 
-func (self *Event) AudioRecorderEvent() *AudioRecorderEvent {
+// Converts an event unio into an allegro recorder event 
+func (self *EventUnion) AudioRecorderEvent() *AudioRecorderEvent {
     return wrapAudioRecorderEvent(C.al_get_audio_recorder_event(self.toC()))
 }
 

+ 45 - 0
al/config.go

@@ -0,0 +1,45 @@
+// TODO configuration support
+package al
+
+/*
+#include <stdlib.h>
+#include <allegro5/allegro.h>
+#include "helpers.h"
+#include "callbacks.h"
+*/
+import "C"
+
+
+/*
+typedef struct ALLEGRO_CONFIG ALLEGRO_CONFIG;
+
+typedef struct ALLEGRO_CONFIG_SECTION ALLEGRO_CONFIG_SECTION;
+
+typedef struct ALLEGRO_CONFIG_ENTRY ALLEGRO_CONFIG_ENTRY;
+
+AL_FUNC(ALLEGRO_CONFIG *, al_create_config, (void));
+AL_FUNC(void, al_add_config_section, (ALLEGRO_CONFIG *config, const char *name));
+AL_FUNC(void, al_set_config_value, (ALLEGRO_CONFIG *config, const char *section, const char *key, const char *value));
+AL_FUNC(void, al_add_config_comment, (ALLEGRO_CONFIG *config, const char *section, const char *comment));
+AL_FUNC(const char*, al_get_config_value, (const ALLEGRO_CONFIG *config, const char *section, const char *key));
+AL_FUNC(ALLEGRO_CONFIG*, al_load_config_file, (const char *filename));
+AL_FUNC(ALLEGRO_CONFIG*, al_load_config_file_f, (ALLEGRO_FILE *filename));
+AL_FUNC(bool, al_save_config_file, (const char *filename, const ALLEGRO_CONFIG *config));
+AL_FUNC(bool, al_save_config_file_f, (ALLEGRO_FILE *file, const ALLEGRO_CONFIG *config));
+AL_FUNC(void, al_merge_config_into, (ALLEGRO_CONFIG *master, const ALLEGRO_CONFIG *add));
+AL_FUNC(ALLEGRO_CONFIG *, al_merge_config, (const ALLEGRO_CONFIG *cfg1, const ALLEGRO_CONFIG *cfg2));
+AL_FUNC(void, al_destroy_config, (ALLEGRO_CONFIG *config));
+AL_FUNC(bool, al_remove_config_section, (ALLEGRO_CONFIG *config,
+        char const *section));
+AL_FUNC(bool, al_remove_config_key, (ALLEGRO_CONFIG *config,
+        char const *section, char const *key));
+
+AL_FUNC(char const *, al_get_first_config_section, (ALLEGRO_CONFIG const *config, ALLEGRO_CONFIG_SECTION **iterator));
+AL_FUNC(char const *, al_get_next_config_section, (ALLEGRO_CONFIG_SECTION **iterator));
+AL_FUNC(char const *, al_get_first_config_entry, (ALLEGRO_CONFIG const *config, char const *section,
+    ALLEGRO_CONFIG_ENTRY **iterator));
+AL_FUNC(char const *, al_get_next_config_entry, (ALLEGRO_CONFIG_ENTRY **iterator));
+
+*/
+
+

+ 19 - 0
al/cpu.go

@@ -0,0 +1,19 @@
+// TODO configuration support
+package al
+
+/*
+#include <stdlib.h>
+#include <allegro5/allegro.h>
+#include "helpers.h"
+#include "callbacks.h"
+*/
+import "C"
+
+func CPUCount() int {
+    return int(C.al_get_cpu_count())
+}
+
+func RamSize() int { 
+    return int(C.al_get_ram_size())
+}
+

+ 78 - 54
al/display.go

@@ -8,6 +8,7 @@ package al
 import "C"
 
 import "runtime"
+import "unsafe"
 
 // Usful regexp for KATE:  ALLEGRO_([A-Z0-9_]+)(.*) -> \1 = C.ALLEGRO_\1
 
@@ -118,34 +119,6 @@ func wrapDisplay(handle *C.ALLEGRO_DISPLAY) *Display {
     return self
 }
 
-// Display mode info.
-type DisplayMode C.ALLEGRO_DISPLAY_MODE
-
-// Converts display mode to C display mode 
-func (self *DisplayMode) toC() *C.ALLEGRO_DISPLAY_MODE {
-    return (*C.ALLEGRO_DISPLAY_MODE)(self)
-}
-
-// Returns the width of the display mode self.
-func (self *DisplayMode) Width() int {
-    return int(self.width)
-}
-
-// Returns the height of the display mode self.
-func (self *DisplayMode) Height() int {
-    return int(self.height)
-}
-
-// Returns the format of the display mode self.
-func (self *DisplayMode) Format() int {
-    return int(self.format)
-}
-
-// Returns the refresh rate of the display mode self.
-func (self *DisplayMode) RefreshRate() int {
-    return int(self.refresh_rate)
-}
-
 // Monitor info
 type MonitorInfo C.ALLEGRO_MONITOR_INFO
 
@@ -205,6 +178,11 @@ func ClearToColor(color Color) {
     C.al_clear_to_color(color.toC())
 }
 
+// Clears the depth buffer of the active display
+func ClearDepthBuffer(z float32) {
+    C.al_clear_depth_buffer(C.float(z))
+}
+
 // Draws a pixel on the active display at the given location 
 // with the given color
 func DrawPixel(x, y float32, color Color) {
@@ -246,6 +224,11 @@ func (self *Display) DisplayFlags() int {
     return int(C.al_get_display_flags(self.handle))
 }
 
+// Gets the orientation of the display
+func (self *Display) Orientation() int {
+    return int(C.al_get_display_orientation(self.handle))
+}
+
 // Sets a dispay flag on the display
 func (self *Display) SetDisplayFlag(flag int, onoff bool) bool {
     return cb2b(C.al_set_display_flag(self.handle, C.int(flag), b2cb(onoff)))
@@ -286,7 +269,7 @@ func TargetBitmap() *Bitmap {
     return wrapBitmapRaw(C.al_get_target_bitmap())
 }
 
-// Must be called to aknowledge a RESIZE event
+// Must be called to acknowledge a RESIZE event
 func (self *Display) AcknowledgeResize() bool {
     return cb2b(C.al_acknowledge_resize(self.handle))
 }
@@ -296,31 +279,11 @@ func UpdateDisplayRegion(x, y, width, height int) {
     C.al_update_display_region(C.int(x), C.int(y), C.int(width), C.int(height))
 }
 
-// Returns true of the bitmap is compatible with the currebt display, false if not. 
+// Returns true of the bitmap is compatible with the current display, false if not. 
 func (bitmap *Bitmap) IsCompatibleBitmap() bool {
     return cb2b(C.al_is_compatible_bitmap(bitmap.handle))
 }
 
-// Returns the number of display modes available to Allegro
-func NumDisplayModes() int {
-    return int(C.al_get_num_display_modes())
-}
-
-// Returns the index'th display mode. Pass in a DisplayMode struct to store the display
-// mode info in. 
-func (self *DisplayMode) Get(index int) *DisplayMode {
-    return (*DisplayMode)(C.al_get_display_mode(C.int(index), self.toC()))
-}
-
-// Gets display mode info for the index'th display mode
-func GetDisplayMode(index int) *DisplayMode {
-    var mode DisplayMode
-    if (&mode).Get(index) != nil {
-        return &mode
-    }
-    return nil
-}
-
 // Waits for the vertical retrace of the monitor to lessen tearing.
 func WaitForVsync() {
     C.al_wait_for_vsync()
@@ -329,7 +292,7 @@ func WaitForVsync() {
 // Gets the event source of the display to registeron an event queue 
 // with RegisterEventSource.
 func (self *Display) GetEventSource() *EventSource {
-    return (*EventSource)(C.al_get_display_event_source(self.handle))
+    return wrapEventSourceRaw(C.al_get_display_event_source(self.handle))
 }
 
 // Sets the display icon the window manager should use for the display window
@@ -337,6 +300,34 @@ func (self *Display) SetDisplayIcon(bitmap *Bitmap) {
     C.al_set_display_icon(self.handle, bitmap.handle)
 }
 
+
+// Converts an array of Bitmaps to an array of ALLEGRO_BITMAPS  and a length 
+func CBitmaps(bitmaps []*Bitmap) (count C.int, cbitmaps **C.ALLEGRO_BITMAP) {
+    length := len(bitmaps)
+    cbitmaps   = (**C.ALLEGRO_BITMAP)(malloc(length * int(unsafe.Sizeof(*cbitmaps))))
+    tmpslice := (*[1 << 30]*C.ALLEGRO_BITMAP)(unsafe.Pointer(cbitmaps))[:length:length]
+    for i, b := range bitmaps {
+        tmpslice[i] = b.handle
+    }
+    
+    count = C.int(length)
+    return count, cbitmaps 
+}
+
+// frees the data allocated by Cstrings
+func CBitmapsFree(count C.int, cbitmaps **C.ALLEGRO_BITMAP) {
+    free(unsafe.Pointer(cbitmaps))
+}
+
+
+// Sets the display icons the window manager should use for the display window
+func (self *Display) SetDisplayIcons(bitmaps []*Bitmap) {
+    count , cbitmaps := CBitmaps(bitmaps)   
+    defer CBitmapsFree(count, cbitmaps) 
+    C.al_set_display_icons(self.handle, count, cbitmaps)
+}
+
+
 // Gets the number of available video adapters (I.E. grapic cards)
 func NumVideoAdapters() int {
     return int(C.al_get_num_video_adapters())
@@ -395,13 +386,39 @@ func (self *Display) SetWindowPosition(x, y int) {
     C.al_set_window_position(self.handle, C.int(x), C.int(y))
 }
 
+// Constrains the window of a display. The environment might ignore the restraints.
+// 0 means no restraint.
+func (self *Display) SetWindowConstraints(min_w, min_h, max_w, max_h int) {
+    C.al_set_window_constraints(self.handle, C.int(min_w), C.int(min_h), C.int(max_w), C.int(max_h))
+}
+
+// Returns the current constraints of the windowed display
+func (self *Display) WindowContraints() (min_w, min_h, max_w, max_h int) {
+    var cmin_w, cmin_h, cmax_w, c_max_h C.int
+    C.al_get_window_constraints(self.handle, &cmin_w, &cmin_h, &cmax_w, &c_max_h)
+    return int(cmin_w), int(cmin_h), int(cmax_w), int(c_max_h)
+}
+
+
+// Gets the title for displays that will be newly created
+func NewWindowTitle() string {
+    return C.GoString(C.al_get_new_window_title())
+}
+
 // Sets the title of the windowed display
-func (self *Display) SetTitle(str string) {
+func (self *Display) SetWindowTitle(str string) {
     cstr := cstr(str)
     defer cstrFree(cstr)
     C.al_set_window_title(self.handle, cstr)
 }
 
+// Sets the title of newly created windowed displays
+func SetNewWindowTitle(str string) {
+    cstr := cstr(str)
+    defer cstrFree(cstr)
+    C.al_set_new_window_title(cstr)
+}
+
 // Sets a display option to be used when a new display is created
 func SetNewDisplayOption(option, value, importance int) {
     C.al_set_new_display_option(C.int(option), C.int(value), C.int(importance))
@@ -418,12 +435,19 @@ func (self *Display) DisplayOption(option int) int {
 }
 
 // Allows to speed up drawing by holding the display . Only bitmap functions and font 
-// drawing, as well as tranformations shouldbe done until the hold is released
+// drawing, as well as tranformations should be used until the hold is released
 func HoldBitmapDrawing(hold bool) {
     C.al_hold_bitmap_drawing(b2cb(hold))
 }
 
 // Returns whether or not the bitmap drawing was held
 func IsBitmapDrawingHeld() bool {
-    return cb2b(C.al_is_bitmap_drawing_held())
+    return bool(C.al_is_bitmap_drawing_held())
+}
+
+/* UNSTABLE API
+func (disp * Display) BackupDirtyBitmaps() {
+    C.backup_dirty_bitmaps(disp.handle)
 }
+*/
+

+ 582 - 0
al/event.go

@@ -0,0 +1,582 @@
+package al
+
+/*
+#cgo pkg-config: allegro-5
+#cgo CFLAGS: -I/usr/local/include
+#cgo linux LDFLAGS: -lc_nonshared
+#include <stdlib.h>
+#include <allegro5/allegro.h>
+#include <allegro5/events.h>
+#include "helpers.h"
+#include "callbacks.h"
+*/
+import "C"
+
+import "unsafe"
+import "runtime"
+
+
+// EventUnion Type, not to avoid complications.
+// type EVENT_TYPE C.ALLEGRO_EVENT_TYPE
+
+// EventUnion Type constants
+const (
+    EVENT_JOYSTICK_AXIS             = C.ALLEGRO_EVENT_JOYSTICK_AXIS
+    EVENT_JOYSTICK_BUTTON_DOWN      = C.ALLEGRO_EVENT_JOYSTICK_BUTTON_DOWN
+    EVENT_JOYSTICK_BUTTON_UP        = C.ALLEGRO_EVENT_JOYSTICK_BUTTON_UP
+    EVENT_JOYSTICK_CONFIGURATION    = C.ALLEGRO_EVENT_JOYSTICK_CONFIGURATION
+    EVENT_KEY_DOWN                  = C.ALLEGRO_EVENT_KEY_DOWN
+    EVENT_KEY_CHAR                  = C.ALLEGRO_EVENT_KEY_CHAR
+    EVENT_KEY_UP                    = C.ALLEGRO_EVENT_KEY_UP
+    EVENT_MOUSE_AXES                = C.ALLEGRO_EVENT_MOUSE_AXES
+    EVENT_MOUSE_BUTTON_DOWN         = C.ALLEGRO_EVENT_MOUSE_BUTTON_DOWN
+    EVENT_MOUSE_BUTTON_UP           = C.ALLEGRO_EVENT_MOUSE_BUTTON_UP
+    EVENT_MOUSE_ENTER_DISPLAY       = C.ALLEGRO_EVENT_MOUSE_ENTER_DISPLAY
+    EVENT_MOUSE_LEAVE_DISPLAY       = C.ALLEGRO_EVENT_MOUSE_LEAVE_DISPLAY
+    EVENT_MOUSE_WARPED              = C.ALLEGRO_EVENT_MOUSE_WARPED
+    EVENT_TIMER                     = C.ALLEGRO_EVENT_TIMER
+    EVENT_DISPLAY_EXPOSE            = C.ALLEGRO_EVENT_DISPLAY_EXPOSE
+    EVENT_DISPLAY_RESIZE            = C.ALLEGRO_EVENT_DISPLAY_RESIZE
+    EVENT_DISPLAY_CLOSE             = C.ALLEGRO_EVENT_DISPLAY_CLOSE
+    EVENT_DISPLAY_LOST              = C.ALLEGRO_EVENT_DISPLAY_LOST
+    EVENT_DISPLAY_FOUND             = C.ALLEGRO_EVENT_DISPLAY_FOUND
+    EVENT_DISPLAY_SWITCH_IN         = C.ALLEGRO_EVENT_DISPLAY_SWITCH_IN
+    EVENT_DISPLAY_SWITCH_OUT        = C.ALLEGRO_EVENT_DISPLAY_SWITCH_OUT
+    EVENT_DISPLAY_ORIENTATION       = C.ALLEGRO_EVENT_DISPLAY_ORIENTATION
+    EVENT_TOUCH_BEGIN               = C.ALLEGRO_EVENT_TOUCH_BEGIN
+    EVENT_TOUCH_END                 = C.ALLEGRO_EVENT_TOUCH_END
+    EVENT_TOUCH_MOVE                = C.ALLEGRO_EVENT_TOUCH_MOVE
+    EVENT_TOUCH_CANCEL              = C.ALLEGRO_EVENT_TOUCH_CANCEL
+    EVENT_DISPLAY_CONNECTED         = C.ALLEGRO_EVENT_DISPLAY_CONNECTED
+    EVENT_DISPLAY_DISCONNECTED      = C.ALLEGRO_EVENT_DISPLAY_DISCONNECTED
+)
+
+func EVENT_TYPE_IS_USER(t int) bool {
+    return ((t) >= 512)
+}
+
+func GET_EVENT_TYPE(a, b, c, d int) int {
+    return AL_ID(a, b, c, d)
+}
+
+func getAnyEvenTimestamp(any *C.ALLEGRO_ANY_EVENT) float64 {
+    return float64(any.timestamp)
+}
+
+// Wrapper interface for different event sources
+type EventSourcer interface {
+    EventSource() * EventSource
+}
+
+func (disp * Display) EventSource() * EventSource {
+    return (*EventSource)(unsafe.Pointer(disp))
+}
+
+func (joy * Joystick) EventSource() * EventSource {
+    return (*EventSource)(unsafe.Pointer(joy))
+}
+
+func (key * Keyboard) EventSource() * EventSource {
+    return (*EventSource)(unsafe.Pointer(key))
+}
+
+func (mouse * Mouse) EventSource() * EventSource {
+    return (*EventSource)(unsafe.Pointer(mouse))
+}
+
+func (touch * TouchInput) EventSource() * EventSource {
+    return (*EventSource)(unsafe.Pointer(touch))
+}
+
+func (timer * Timer) EventSource() * EventSource {
+    return (*EventSource)(unsafe.Pointer(timer))
+}
+
+func (es * EventSource) EventSource() * EventSource {
+    return es
+}
+
+ 
+// Event sources that emit events.
+type EventSource C.ALLEGRO_EVENT_SOURCE
+
+// Wraps an event source pointer but sets no finalizer (not needed anyway) 
+func wrapEventSourceRaw(ptr *C.ALLEGRO_EVENT_SOURCE) *EventSource {
+    return (*EventSource)(ptr)
+}
+
+// Converts wrapper EventUnion source pointer to C Allegro event source pointer
+func (self *EventSource) toC() *C.ALLEGRO_EVENT_SOURCE {
+    return (*C.ALLEGRO_EVENT_SOURCE)(self)
+}
+
+// Events that the event system emits.
+type EventUnion     C.ALLEGRO_EVENT
+
+// use an EventUnion interface to wrap the 
+// C union's members in
+
+type Event interface {
+    Type() int
+    Source() EventSourcer
+    Timestamp() float64
+}
+
+type AnyEvent       C.ALLEGRO_ANY_EVENT
+type DisplayEvent   C.ALLEGRO_DISPLAY_EVENT
+type JoystickEvent  C.ALLEGRO_JOYSTICK_EVENT
+type KeyboardEvent  C.ALLEGRO_KEYBOARD_EVENT
+type MouseEvent     C.ALLEGRO_MOUSE_EVENT
+type TimerEvent     C.ALLEGRO_TIMER_EVENT
+type TouchEvent     C.ALLEGRO_TOUCH_EVENT
+type UserEvent      C.ALLEGRO_USER_EVENT
+
+
+
+// Converts wrapper EventUnion pointer to C Allegro event pointer
+func (self *EventUnion) toC() *C.ALLEGRO_EVENT {
+    return (*C.ALLEGRO_EVENT)(self)
+}
+
+// Returns an unsafe pointer to the event 
+func (self *EventUnion) toPointer() unsafe.Pointer {
+    return unsafe.Pointer(self.toC())
+}
+
+
+// Converts wrapper EventUnion pointer to an EventUnion interface struct
+func (evun *EventUnion) Event() Event {
+    ae := (*C.ALLEGRO_ANY_EVENT)(evun.toPointer())
+    switch (C.int(ae._type)) {
+        case EVENT_JOYSTICK_AXIS            : fallthrough 
+        case EVENT_JOYSTICK_BUTTON_DOWN     : fallthrough 
+        case EVENT_JOYSTICK_BUTTON_UP       : fallthrough
+        case EVENT_JOYSTICK_CONFIGURATION   : 
+            return (*JoystickEvent)(evun.toPointer())
+        case EVENT_KEY_CHAR                 : fallthrough
+        case EVENT_KEY_DOWN                 : fallthrough
+        case EVENT_KEY_UP                   : 
+            return (*KeyboardEvent)(evun.toPointer())
+
+        case EVENT_MOUSE_AXES               : fallthrough    
+        case EVENT_MOUSE_BUTTON_DOWN        : fallthrough    
+        case EVENT_MOUSE_BUTTON_UP          : fallthrough    
+        case EVENT_MOUSE_ENTER_DISPLAY      : fallthrough    
+        case EVENT_MOUSE_LEAVE_DISPLAY      : fallthrough    
+        case EVENT_MOUSE_WARPED             :
+            return (*MouseEvent)(evun.toPointer())
+            
+        case EVENT_TIMER                    :
+            return (*TimerEvent)(evun.toPointer())
+            
+        case EVENT_DISPLAY_EXPOSE           : fallthrough    
+        case EVENT_DISPLAY_RESIZE           : fallthrough    
+        case EVENT_DISPLAY_CLOSE            : fallthrough    
+        case EVENT_DISPLAY_LOST             : fallthrough    
+        case EVENT_DISPLAY_FOUND            : fallthrough    
+        case EVENT_DISPLAY_SWITCH_IN        : fallthrough    
+        case EVENT_DISPLAY_SWITCH_OUT       : fallthrough    
+        case EVENT_DISPLAY_ORIENTATION      :
+            return (*DisplayEvent)(evun.toPointer())
+        default: break
+    }
+    
+    if EVENT_TYPE_IS_USER(int(ae._type)) {
+            return (*UserEvent)(evun.toPointer())
+    }
+    
+    return (*AnyEvent)(evun.toPointer())
+}
+
+/* These wrappers implement the interface Event for all event types */
+
+
+func (ev AnyEvent     ) Type() int { return int(ev._type); }
+func (ev DisplayEvent ) Type() int { return int(ev._type); }
+func (ev JoystickEvent) Type() int { return int(ev._type); }
+func (ev KeyboardEvent) Type() int { return int(ev._type); }
+func (ev MouseEvent   ) Type() int { return int(ev._type); }
+func (ev TimerEvent   ) Type() int { return int(ev._type); }
+func (ev TouchEvent   ) Type() int { return int(ev._type); }
+func (ev UserEvent    ) Type() int { return int(ev._type); }
+
+func (ev AnyEvent     ) Source() EventSourcer { return wrapEventSourceRaw   (ev.source); }
+func (ev DisplayEvent ) Source() EventSourcer { return wrapDisplayRaw       (ev.source); }
+func (ev JoystickEvent) Source() EventSourcer { return wrapJoystickRaw      (ev.source); }
+func (ev KeyboardEvent) Source() EventSourcer { return wrapKeyboardRaw      (ev.source); }
+func (ev MouseEvent   ) Source() EventSourcer { return wrapMouseRaw         (ev.source); }
+func (ev TimerEvent   ) Source() EventSourcer { return wrapTimerRaw         (ev.source); }
+func (ev TouchEvent   ) Source() EventSourcer { return wrapTouchInputRaw    (ev.source); }
+func (ev UserEvent    ) Source() EventSourcer { return wrapEventSourceRaw   (ev.source); }
+
+func (ev AnyEvent     ) Timestamp() float64 { return float64(ev.timestamp); }
+func (ev DisplayEvent ) Timestamp() float64 { return float64(ev.timestamp); }
+func (ev JoystickEvent) Timestamp() float64 { return float64(ev.timestamp); }
+func (ev KeyboardEvent) Timestamp() float64 { return float64(ev.timestamp); }
+func (ev MouseEvent   ) Timestamp() float64 { return float64(ev.timestamp); }
+func (ev TimerEvent   ) Timestamp() float64 { return float64(ev.timestamp); }
+func (ev TouchEvent   ) Timestamp() float64 { return float64(ev.timestamp); }
+func (ev UserEvent    ) Timestamp() float64 { return float64(ev.timestamp); }
+
+
+func (eu * EventUnion) AnyEvent     () *AnyEvent      {                                                 return (*AnyEvent     )(eu.toPointer());   }
+func (eu * EventUnion) DisplayEvent () *DisplayEvent  { if !eu.IsDisplayEvent () { return nil; } else { return (*DisplayEvent )(eu.toPointer());}; }
+func (eu * EventUnion) JoystickEvent() *JoystickEvent { if !eu.IsJoystickEvent() { return nil; } else { return (*JoystickEvent)(eu.toPointer());}; }
+func (eu * EventUnion) KeyboardEvent() *KeyboardEvent { if !eu.IsKeyboardEvent() { return nil; } else { return (*KeyboardEvent)(eu.toPointer());}; }
+func (eu * EventUnion) MouseEvent   () *MouseEvent    { if !eu.IsMouseEvent   () { return nil; } else { return (*MouseEvent   )(eu.toPointer());}; }
+func (eu * EventUnion) TimerEvent   () *TimerEvent    { if !eu.IsTimerEvent   () { return nil; } else { return (*TimerEvent   )(eu.toPointer());}; }
+func (eu * EventUnion) TouchEvent   () *TouchEvent    { if !eu.IsTouchEvent   () { return nil; } else { return (*TouchEvent   )(eu.toPointer());}; }
+func (eu * EventUnion) UserEvent    () *UserEvent     { if !eu.IsUserEvent    () { return nil; } else { return (*UserEvent    )(eu.toPointer());}; }
+
+// Returns the type of the event.
+func (self *EventUnion) Type() int {
+    return self.AnyEvent().Type()
+}
+
+// Returns the timestamp of the event.
+func (self *EventUnion) Timestamp() float64 {
+    return self.AnyEvent().Timestamp()
+}
+
+// Returns the event source of the event
+func (self *EventUnion) Source() EventSourcer {
+    return self.AnyEvent().Source()
+}
+
+// Returns true if this is a dispay event, false if not.
+func (self *EventUnion) IsDisplayEvent() bool {
+    t := self.Type()
+    return ((t >= EVENT_DISPLAY_EXPOSE) && (t <= EVENT_DISPLAY_ORIENTATION) || ((t>= EVENT_DISPLAY_CONNECTED) && (t<= EVENT_DISPLAY_DISCONNECTED) ))
+}
+
+// Returns true if this is a mouse event, false if not.
+func (self *EventUnion) IsMouseEvent() bool {
+    t := self.Type()
+    return (t >= EVENT_MOUSE_AXES) && (t <= EVENT_MOUSE_WARPED)
+}
+
+// Returns true if this is a Joystick event, false if not.
+func (self *EventUnion) IsJoystickEvent() bool {
+    t := self.Type()
+    return (t >= EVENT_JOYSTICK_AXIS) && (t <= EVENT_JOYSTICK_CONFIGURATION)
+}
+
+// Returns true if this is a keyboard event, false if not.
+func (self *EventUnion) IsKeyboardEvent() bool {
+    t := self.Type()
+    return (t >= EVENT_KEY_DOWN) && (t <= EVENT_KEY_UP)
+}
+
+// Returns true if this is a keyboard event, false if not.
+func (self *EventUnion) IsTouchEvent() bool {
+    t := self.Type()
+    return (t >= EVENT_TOUCH_BEGIN) && (t <= EVENT_TOUCH_CANCEL)
+}
+
+// Returns true if this is a timer event, false if not.
+func (self *EventUnion) IsTimerEvent() bool {
+    t := self.Type()
+    return (t == EVENT_TIMER)
+}
+
+// Returns true if this is a user event, false if not.
+func (self *EventUnion) IsUserEvent() bool {
+    t := self.Type()
+    return EVENT_TYPE_IS_USER(t)
+}
+
+// Returns the X position of the display event.
+func (de DisplayEvent) X() int {
+    return int(de.x)
+}
+
+// Returns the Y position of the display event.
+func (de DisplayEvent) Y() int {
+    return int(de.y)
+}
+
+// Returns the width of the display event.
+func (de DisplayEvent) Width() int {
+    return int(de.width)
+}
+
+// Returns the height of the display event.
+func (de DisplayEvent) Height() int {
+    return int(de.height)
+}
+
+// Returns the orientation of the display event.
+func (de DisplayEvent) Orientation() int {
+    return int(de.orientation)
+}
+
+// Returns the stick number of the joystick event.
+func (je JoystickEvent) Stick() int {
+    return int(je.stick)
+}
+
+// Returns the axis number of the joystick event.
+func (je JoystickEvent) Axis() int {
+    return int(je.axis)
+}
+
+// Returns the button number of the joystick event.
+func (je JoystickEvent) Button() int {
+    return int(je.button)
+}
+
+// Returns the position of the joystick event.
+func (je JoystickEvent) Pos() int {
+    return int(je.pos)
+}
+
+// Returns the display that has emitted the keyboard event.
+func (ke KeyboardEvent) Display() *Display {
+    return wrapDisplayRaw(ke.display)
+}
+
+// Returns the key code of the keyboard event. 
+func (ke KeyboardEvent) Keycode() int {
+    return int(ke.keycode)
+}
+
+// Returns the unicode character of the keyboard event. 
+func (ke KeyboardEvent) Unichar() rune {
+    return rune(ke.unichar)
+}
+
+// Returns the modifiers of the keyboard event. 
+func (ke KeyboardEvent) Modifiers() int {
+    return int(ke.modifiers)
+}
+
+// Returns is the keyboard event was automatically repeated or not.
+func (ke KeyboardEvent) Repeat() bool {
+    return bool(ke.repeat)
+}
+
+// Returns the X position of the mouse event.
+func (me MouseEvent) X() int {
+    return int(me.x)
+}
+
+// Returns the Y position of the mouse event.
+func (me MouseEvent) Y() int {
+    return int(me.y)
+}
+
+// Returns the Z position of the mouse event.
+func (me MouseEvent) Z() int {
+    return int(me.z)
+}
+
+// Returns the W position of the mouse event.
+func (me MouseEvent) W() int {
+    return int(me.w)
+}
+
+// Returns the delta of the X position of the mouse event.
+func (me MouseEvent) DX() int {
+    return int(me.dx)
+}
+
+// Returns the delta of the Y position of the mouse event.
+func (me MouseEvent) DY() int {
+    return int(me.dy)
+}
+
+// Returns the delta of the Z position of the mouse event.
+func (me MouseEvent) DZ() int {
+    return int(me.dz)
+}
+
+// Returns the delta of the W position of the mouse event.
+func (me MouseEvent) DW() int {
+    return int(me.dw)
+}
+
+// Returns the button of the mouse event.
+func (me MouseEvent) Button() int {
+    return int(me.button)
+}
+
+// Returns the pressure of the mouse event.
+func (me MouseEvent) Pressure() float32 {
+    return float32(me.pressure)
+}
+
+// Returns the display that has emitted the mouse event. 
+func (me MouseEvent) Display() *Display {
+    return wrapDisplayRaw(me.display)
+}
+
+
+// Returns the error of the timer event.
+func (te TimerEvent) Error() float64 {
+    return float64(te.error)
+}
+
+// Returns the ticks of the timer event. 
+func (te TimerEvent) Count() int64 {
+    return int64(te.count)
+}
+
+
+// Returns the X position of the touch input event.
+func (te TouchEvent) X() int {
+    return int(te.x)
+}
+
+// Returns the Y position of the touch input event.
+func (te TouchEvent) Y() int {
+    return int(te.y)
+}
+
+// Returns the ID of the touch input event.
+func (te TouchEvent) ID() int {
+    return int(te.id)
+}
+
+// Returns whether the touch input event is primary or not.
+func (te TouchEvent) Primary() bool {
+    return bool(te.primary)
+}
+
+// Returns the delta of the X position of the touch input event.
+func (te TouchEvent) DX() int {
+    return int(te.dx)
+}
+
+// Returns the delta of the Y position of the touch input event.
+func (te TouchEvent) DY() int {
+    return int(te.dy)
+}
+
+/* The safest way to use user events from GO is to use integer handles
+ * as offsets into a GO-allocated map. */
+
+func (ue UserEvent) Data1Pointer() unsafe.Pointer { return unsafe.Pointer(uintptr(ue.data1));}
+func (ue UserEvent) Data1Integer() int64          { return                  int64(ue.data1); }
+func (ue UserEvent) Data2Pointer() unsafe.Pointer { return unsafe.Pointer(uintptr(ue.data2));}
+func (ue UserEvent) Data2Integer() int64          { return                  int64(ue.data2); }
+func (ue UserEvent) Data3Pointer() unsafe.Pointer { return unsafe.Pointer(uintptr(ue.data3));}
+func (ue UserEvent) Data3Integer() int64          { return                  int64(ue.data3); }
+func (ue UserEvent) Data4Pointer() unsafe.Pointer { return unsafe.Pointer(uintptr(ue.data4));}
+func (ue UserEvent) Data4Integer() int64          { return                  int64(ue.data4); }
+
+func (ue UserEvent) SetData1Integer(v int64)      { ue.data1 = C.intptr_t(v); }
+func (ue UserEvent) SetData2Integer(v int64)      { ue.data2 = C.intptr_t(v); }
+func (ue UserEvent) SetData3Integer(v int64)      { ue.data3 = C.intptr_t(v); }
+func (ue UserEvent) SetData4Integer(v int64)      { ue.data4 = C.intptr_t(v); }
+
+
+/*
+The compiler accept this, but it's unlikely to work correctly.
+func (ue UserEvent) Data1() interface{} { return (interface{})(ue.Data1Pointer());}
+func (ue UserEvent) Data2() interface{} { return (interface{})(ue.Data2Pointer());}
+func (ue UserEvent) Data3() interface{} { return (interface{})(ue.Data3Pointer());}
+func (ue UserEvent) Data4() interface{} { return (interface{})(ue.Data4Pointer());}
+*/
+
+
+
+// Event queues.
+type EventQueue struct {
+    handle *C.ALLEGRO_EVENT_QUEUE
+}
+
+// Destroys the event queue.
+func (self *EventQueue) Destroy() {
+    if self.handle != nil {
+        C.al_destroy_event_queue(self.handle)
+    }
+    self.handle = nil
+}
+
+// Wraps an event queue, but does not set a finalizer.
+func wrapEventQueueRaw(handle *C.ALLEGRO_EVENT_QUEUE) *EventQueue {
+    if handle == nil {
+        return nil
+    }
+    return &EventQueue{handle}
+}
+
+func (eq * EventQueue) toC() (handle *C.ALLEGRO_EVENT_QUEUE) {
+    return eq.handle
+}
+
+// Wraps an event queue and sets a finalizer that calls Destroy
+func wrapEventQueue(handle *C.ALLEGRO_EVENT_QUEUE) *EventQueue {
+    result := wrapEventQueueRaw(handle)
+    if result != nil {
+        runtime.SetFinalizer(result, func(me *EventQueue) { me.Destroy() })
+    }
+    return result
+}
+
+// Create an event queue.
+func CreateEventQueue() *EventQueue {
+    return wrapEventQueue(C.al_create_event_queue())
+}
+
+// Register an event source with self. 
+func (self *EventQueue) RegisterEventSource(src *EventSource) {
+    C.al_register_event_source(self.handle, src.toC())
+}
+
+// Unregister an event source with self. 
+func (self *EventQueue) UnregisterEventSource(src *EventSource) {
+    C.al_unregister_event_source(self.handle, src.toC())
+}
+
+// Returns true if the event queue self is empty, false if not.
+func (self *EventQueue) IsEmpty() bool {
+    return bool(C.al_is_event_queue_empty(self.handle))
+}
+
+// Returns the next event from the event queue as well as a bool
+// to signify if an event was fetched sucessfully or not.
+func (self *EventQueue) GetNextEvent() (event *EventUnion, ok bool) {
+    event = &EventUnion{}
+    ok = bool(C.al_get_next_event(self.handle, event.toC()))
+    return event, ok
+}
+
+// Peeks at the next event in the event queue and returns it as well as a bool
+// to signify if an event was fetched sucessfully or not.
+func (self *EventQueue) PeekNextEvent() (event *EventUnion, ok bool) {
+    event = &EventUnion{}
+    ok = bool(C.al_peek_next_event(self.handle, event.toC()))
+    return event, ok
+}
+
+// Drops the next event from the event queue
+func (self *EventQueue) DropNextEvent() bool {
+    return bool(C.al_drop_next_event(self.handle))
+}
+
+// Flushes the event queue
+func (self *EventQueue) Flush() {
+    C.al_flush_event_queue(self.handle)
+}
+
+// Waits for the next event from the event queue 
+func (self *EventQueue) WaitForEvent() (event *EventUnion) {
+    event = &EventUnion{}
+    C.al_wait_for_event(self.handle, event.toC())
+    return event
+}
+
+// Waits for secs seconds the next event from the event queue 
+func (self *EventQueue) WaitForEventTimed(secs float32) (event *EventUnion, ok bool) {
+    event = &EventUnion{}
+    ok = bool(C.al_wait_for_event_timed(self.handle, event.toC(), C.float(secs)))
+    return event, ok
+}
+
+func (queue *EventQueue) WaitForEventUntil(timeout * Timeout) (event *EventUnion, ok bool) {
+    event = &EventUnion{}
+    ok = bool(C.al_wait_for_event_until(queue.toC(), event.toC(), timeout.toC()))
+    return event, ok
+}
+

+ 110 - 0
al/file.go

@@ -0,0 +1,110 @@
+// acodec
+package al
+
+/*
+#cgo pkg-config: allegro-5
+#cgo CFLAGS: -I/usr/local/include
+#cgo linux LDFLAGS: -lc_nonshared
+#include <stdlib.h>
+#include <allegro5/allegro.h>
+#include <allegro5/file.h>
+#include "helpers.h"
+#include "callbacks.h"
+*/
+import "C"
+
+import "errors"
+import "runtime"
+import "unsafe"
+
+// Allegro's own file for cross platform and physfs reasons.
+type File struct {
+    handle *C.ALLEGRO_FILE
+}
+
+// Closes the Allegro file
+func (self *File) Close() {
+    if self.handle != nil {
+        C.al_fclose(self.handle)
+    }
+    self.handle = nil
+}
+
+// Returns the low level handle of the file 
+func (self *File) toC() * C.ALLEGRO_FILE {
+    return self.handle
+}
+
+// Wraps an ALLEGRO_FILE into a File
+func wrapFileRaw(file *C.ALLEGRO_FILE) *File {
+    if file == nil {
+        return nil
+    }
+    return &File{file}
+}
+
+// Opens an Allegro File
+func openFile(filename, mode string) *C.ALLEGRO_FILE {
+    cfilename := cstr(filename)
+    defer cstrFree(cfilename)
+    cmode := cstr(mode)
+    defer cstrFree(cmode)
+    return C.al_fopen(cfilename, cmode)
+}
+
+// Sets up a finalizer for this File that calls Close()
+func (self *File) SetCloseFinalizer() *File {
+    if self != nil {
+        runtime.SetFinalizer(self, func(me *File) { me.Close() })
+    }
+    return self
+}
+
+// Wraps a file and sets up a finalizer that calls Destroy()
+func wrapFile(data *C.ALLEGRO_FILE) *File {
+    self := wrapFileRaw(data)
+    return self.SetCloseFinalizer()
+}
+
+// Opens a file with no finalizer set
+func OpenFileRaw(filename, mode string) *File {
+    self := openFile(filename, mode)
+    return wrapFileRaw(self)
+}
+
+// Opens a file with a Close finalizer set
+func OpenFile(filename, mode string) *File {
+    self := OpenFileRaw(filename, mode)
+    return self.SetCloseFinalizer()
+}
+
+/* File interface is as good as useless in GO, too many
+ * callbacks. */
+
+type Seek C.enum_ALLEGRO_SEEK
+
+const (
+   SEEK_SET = Seek(C.ALLEGRO_SEEK_SET)
+   SEEK_CUR = Seek(C.ALLEGRO_SEEK_CUR)
+   SEEK_END = Seek(C.ALLEGRO_SEEK_END)
+)
+
+func (f * File) Read(p []byte) (n int, err error) {
+    err = nil
+    size := C.al_fread(f.toC(), unsafe.Pointer(&p[0]), C.size_t(len(p)))
+    n = int(size)
+    erri := C.al_ferror(f.toC()) 
+    if erri != 0 {
+        mesg := C.GoString(C.al_ferrmsg(f.toC()))
+        err = errors.New("Could not read file: " + mesg)
+    } 
+    return n, err
+}
+
+/* No Allegro File IO (yet) since that is redundant with Go's std libs. 
+ * Likeswise I'm skipping fixed point math and 
+ * the FS entry.
+ */
+
+
+

+ 10 - 0
al/keyboard.go

@@ -213,3 +213,13 @@ const (
     KEYMOD_ACCENT3    = C.ALLEGRO_KEYMOD_ACCENT3
     KEYMOD_ACCENT4    = C.ALLEGRO_KEYMOD_ACCENT4
 )
+
+type Keyboard struct {
+    handle * C.ALLEGRO_KEYBOARD
+}
+
+func wrapKeyboardRaw(kb * C.ALLEGRO_KEYBOARD) * Keyboard {
+    res := &Keyboard{kb}
+    return res
+}
+

+ 66 - 0
al/mode.go

@@ -0,0 +1,66 @@
+// acodec
+package al
+
+/*
+#cgo pkg-config: allegro-5
+#cgo CFLAGS: -I/usr/local/include
+#cgo linux LDFLAGS: -lc_nonshared
+#include <stdlib.h>
+#include <allegro5/allegro.h>
+#include <allegro5/fullscreen_mode.h>
+#include "helpers.h"
+#include "callbacks.h"
+*/
+import "C"
+import "fmt"
+
+type DisplayMode C.ALLEGRO_DISPLAY_MODE 
+
+func (dm * DisplayMode) toC() * C.ALLEGRO_DISPLAY_MODE {
+    return (*C.ALLEGRO_DISPLAY_MODE)(dm) 
+}
+
+func (dm * DisplayMode) Width() int {
+    return int(dm.width)
+}
+
+func (dm * DisplayMode) Height() int {
+    return int(dm.height)
+}
+
+func (dm * DisplayMode) Format() int {
+    return int(dm.format)
+}
+
+func (dm * DisplayMode) RefreshRate() int {
+    return int(dm.refresh_rate)
+}
+
+func (dm * DisplayMode) String() string {
+    return fmt.Sprintf("(%d %d) %d %d hz", dm.Width(), dm.Height(), dm.Format(), dm.RefreshRate() ) 
+}
+
+func NumDisplayModes() int {
+    return int(C.al_get_num_display_modes())
+}
+
+func GetDisplayMode(index int) (disp * DisplayMode) {
+    disp = &DisplayMode{}
+    if nil == C.al_get_display_mode(C.int(index), disp.toC()) {
+        return nil
+    }
+    return disp
+}
+
+func DisplayModes() (modes [] *DisplayMode) {
+    count := NumDisplayModes()
+    modes = make([]*DisplayMode, count)
+    for i:=0 ; i < count ; i ++ {
+        modes[i] = GetDisplayMode(i)
+    }
+    return modes
+}
+
+
+
+/* vim: set ts=8 sts=3 sw=3 et: */

+ 72 - 0
al/touch_input.go

@@ -0,0 +1,72 @@
+package al
+
+/*
+#include <stdlib.h>
+#include <allegro5/allegro.h>
+#include "helpers.h"
+*/
+import "C"
+
+
+/* Enum: ALLEGRO_TOUCH_INPUT_MAX_TOUCH_COUNT
+ */
+const TOUCH_INPUT_MAX_TOUCH_COUNT = C.ALLEGRO_TOUCH_INPUT_MAX_TOUCH_COUNT
+
+type TouchInput struct {
+    handle * C.ALLEGRO_TOUCH_INPUT
+}
+
+func wrapTouchInputRaw(cti * C.ALLEGRO_TOUCH_INPUT) * TouchInput {
+    res := &TouchInput{cti}
+    return res
+}
+
+type TouchInputState  C.ALLEGRO_TOUCH_INPUT_STATE
+
+func wrapTouchInputStateRaw(cti C.ALLEGRO_TOUCH_INPUT_STATE) TouchInputState {
+    return TouchInputState(cti)
+}
+
+type TouchState C.ALLEGRO_TOUCH_STATE
+
+func wrapTouchStateRaw(ts C.ALLEGRO_TOUCH_STATE) TouchState {
+    return TouchState(ts)
+}
+
+func (ts TouchState) Id() int {
+        return int(ts.id)
+}
+
+func (ts TouchState) X() float32 { return float32(ts.x); }
+func (ts TouchState) Y() float32 { return float32(ts.y); }
+func (ts TouchState) DX() float32 { return float32(ts.dx); }
+func (ts TouchState) DY() float32 { return float32(ts.dy); }
+func (ts TouchState) Primary() bool { return bool(ts.primary); }
+func (ts TouchState) Display() * Display { return wrapDisplayRaw(ts.display); }
+
+func (tsi TouchInputState) Touch(index int) TouchState {
+    return wrapTouchStateRaw(tsi.touches[index])
+} 
+ 
+func IsTouchInputInstalled() bool {
+    return bool(C.al_is_touch_input_installed())
+}
+
+func InstallTouchInput() bool {
+    return bool(C.al_install_touch_input())
+}
+
+func UninstallTouchInput() { 
+    C.al_uninstall_touch_input()
+}
+
+func GetTouchInputState() TouchInputState {
+    cstate := C.struct_ALLEGRO_TOUCH_INPUT_STATE{}
+    C.al_get_touch_input_state(&cstate)
+    return wrapTouchInputStateRaw(cstate)
+}
+
+func GetTouchInputEventSource() * EventSource {
+    return wrapEventSourceRaw(C.al_get_touch_input_event_source())
+}
+