Browse Source

Wrapping more addons.

Beoran 6 years ago
parent
commit
162d54a64f
10 changed files with 504 additions and 109 deletions
  1. 41 15
      al/al_test.go
  2. 5 0
      al/audio.go
  3. 12 0
      al/bitmap.go
  4. 19 0
      al/bitmap_io.go
  5. 33 0
      al/font.go
  6. 171 91
      al/native_dialog.go
  7. 3 3
      al/physfs.go
  8. 9 0
      al/primitives.go
  9. 53 0
      al/ttf.go
  10. 158 0
      al/video.go

+ 41 - 15
al/al_test.go

@@ -332,24 +332,13 @@ func TestPrimitives2(t *testing.T) {
     
     bmp := loadBitmap(t, "gin_feather.png")
     blue := CreateColor(0.0, 0.0, 1.0, 1.0)
-    yellow := CreateColor(1.0, 1.0, 0.0, 1.0)
+    bg := CreateColor(1.0, 1.0, 1.0, 1.0)
     ClearToColor(blue)
     v := make([]Vertex, 3)
-    v[0].x = 10
-    v[0].y = 20
-    v[0].color = yellow.toC()
-    v[0].u = 0.0
-    v[0].v = 0.0
     
-    v[1].x = 110
-    v[1].y = 120
-    v[0].u = 1.0
-    v[0].v = 0.0
-
-    v[2].x = 120
-    v[2].y = 210
-    v[0].u = 0.0
-    v[0].v = 1.0
+    v[0].Init(10.0, 20.0, 0.0,  0.0 * bmp.Widthf(), 0.0, bg)
+    v[1].Init(10.0, 120.0, 0.0,  1.0 * bmp.Widthf(), 0.0, bg)
+    v[2].Init(120.0, 120.0, 0.0,  0.0 * bmp.Widthf(), 1.0 * bmp.Heightf(), bg)
     
     DrawPrim(v, bmp, 0, 3, PRIM_TRIANGLE_LIST)
     FlipDisplay()
@@ -357,6 +346,43 @@ func TestPrimitives2(t *testing.T) {
     display.Destroy()
 }
 
+// Test some native dialogs
+func TestDialogs(t *testing.T) {
+    InstallSystem()
+    defer UninstallSystem()
+    InitNativeDialogAddon()
+    defer ShutdownNativeDialogAddon()
+    
+    
+    display := makeDisplay()
+    if display == nil {
+        t.Error("Error creating display.")
+    }
+    
+    fc := CreateNativeFileDialog(".","title","*", FILECHOOSER_FILE_MUST_EXIST | FILECHOOSER_MULTIPLE)
+    fc.Show(display)
+    cn := fc.Count()
+    
+    for i:= 0; i < cn ; i ++ {
+        fn :=  fc.Path(i)
+        t.Logf("File %d of %d selected: %s\n", i + 1, cn, fn)
+    }
+    
+    tl := CreateNativeTextLog("title", TEXTLOG_MONOSPACE)
+    tl.Append("append")
+    
+    res := display.ShowNativeMessageBox("title", "heading", "text", "buttons", MESSAGEBOX_WARN)
+    t.Logf("Dialog result: %d\n", res)
+    
+    
+    FlipDisplay()
+    Rest(1.0)
+    tl.Close()
+    fc.Destroy()
+    display.Destroy()
+}
+
+
 
 // Benchmark basic display function ClearToColor
 func BenchmarkClearToColor(b *testing.B) {

+ 5 - 0
al/audio.go

@@ -919,6 +919,11 @@ func (self *File) Close() {
     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 {

+ 12 - 0
al/bitmap.go

@@ -94,6 +94,18 @@ func (self *Bitmap) Height() int {
     return int(C.al_get_bitmap_height(self.handle))
 }
 
+// Gets the width of the bitmap as a float32.
+func (bmp *Bitmap) Widthf() float32 {
+    return float32(bmp.Width())
+}
+
+// Gets the height of the bitmap as a float32.
+func (bmp *Bitmap) Heightf() float32 {
+    return float32(bmp.Height())
+}
+
+
+
 // Gets the format of the bitmap.
 func (self *Bitmap) Format() int {
     return int(C.al_get_bitmap_format(self.handle))

+ 19 - 0
al/bitmap_io.go

@@ -25,5 +25,24 @@ func (bmp * Bitmap) Save(name string) bool {
     return bool(C.al_save_bitmap(cname, bmp.toC()))
 }
 
+func (file * File) LoadBitmap(ident string) * Bitmap {
+    var cident  *C.char = nil
+    if ident != "" {
+        cident = cstr(ident)
+        defer cstrFree(cident)
+    }
+    
+    return wrapBitmap(C.al_load_bitmap_f(file.toC(), cident))
+}
+
+func (file * File) SaveBitmap(ident string, bmp * Bitmap) bool {
+    var cident  *C.char = nil
+    if ident != "" { 
+        cident = cstr(ident)
+        defer cstrFree(cident)
+    }
+    
+    return bool(C.al_save_bitmap_f(file.toC(), cident, bmp.toC()))
+}
 
 

+ 33 - 0
al/font.go

@@ -320,6 +320,39 @@ func (font * Font) FallbackFont() (* Font) {
     return wrapFontRaw(C.al_get_fallback_font(font.toC()))
 }
 
+// Glyph per glyph drawing 
+
+// Draws an individual glyph from a font
+func (font * Font) DrawGlyph(color Color, x, y float32, codepoint int) {
+    C.al_draw_glyph(font.toC(), color.toC(), C.float(x), C.float(y), C.int(codepoint))
+}
+
+// Gets the width of the glyph for the font
+func (font * Font) GlyphWidth(color Color, codepoint int) int {
+   return int(C.al_get_glyph_width(font.toC(), C.int(codepoint)))
+}
+
+// Gets the advance between two code points for the font
+func (font * Font) GlyphAdvance(color Color, cp1, cp2 int) int {
+   return int(C.al_get_glyph_advance(font.toC(), C.int(cp1), C.int(cp2)))
+}
+
+// Gets the dimensions of the glyph for the font
+func (font * Font) GlyphDimensions(color Color, cp int) (ok bool, bbx, bby, bbw, bbh int) {
+   var cbbx, cbby, cbbw, cbbh C.int
+ 
+   ok = bool(C.al_get_glyph_dimensions(font.toC(), C.int(cp), &cbbx, &cbby, &cbbw, &cbbh))
+ 
+   bbx = int(cbbx)
+   bby = int(cbby)
+   bbw = int(cbbw)
+   bbh = int(cbbh)
+   
+   return ok, bbx, bby, bbw, bbh
+}
+
+
+
 /*
 The fallback is a hassle, might be better to do this in Go.
 ALLEGRO_FONT_FUNC(void, al_do_multiline_text, (const ALLEGRO_FONT *font,

+ 171 - 91
al/native_dialog.go

@@ -11,6 +11,11 @@ package al
 #include <allegro5/allegro.h>
 #include <allegro5/allegro_native_dialog.h>
 #include "helpers.h"
+
+void al_append_native_text_log_wrapper(ALLEGRO_TEXTLOG * tl, const char * text) {
+    al_append_native_text_log(tl, "%s", text);
+}
+
 */
 import "C"
 
@@ -196,6 +201,10 @@ func EndOfMenu(caption string, id int) MenuInfo {
     return MakeMenuInfo(nil, 0, 0, nil)
 }
 
+func (info * MenuInfo) toC() * C.ALLEGRO_MENU_INFO {
+    return (*C.ALLEGRO_MENU_INFO)(info)
+}
+
 // Starts the native dialog addon
 func InitNativeDialogAddon() bool {
     return cb2b(C.al_init_native_dialog_addon())
@@ -207,97 +216,168 @@ func ShutdownNativeDialogAddon() {
 }
 
 // Creates a native file dialog.
-func CreateNativeFileDialogRaw(path, title, patterns string, mode int) *FileChooser {
-    return nil
-    //return wrapFileChooser()
+func CreateNativeFileDialog(path, title, patterns string, mode int) *FileChooser {    
+    cpath    := cstr(path)      ; defer cstrFree(cpath)
+    ctitle   := cstr(title)     ; defer cstrFree(ctitle)
+    cpatterns:= cstr(patterns)  ; defer cstrFree(cpatterns)
+    
+    return wrapFileChooser(C.al_create_native_file_dialog(cpath, ctitle, cpatterns, C.int(mode)))
 }
 
-/*
-TODO:
-ALLEGRO_DIALOG_FUNC(ALLEGRO_FILECHOOSER *, al_create_native_file_dialog, (char const *initial_path,
-   char const *title, char const *patterns, int mode));
-ALLEGRO_DIALOG_FUNC(bool, al_show_native_file_dialog, (ALLEGRO_DISPLAY *display, ALLEGRO_FILECHOOSER *dialog));
-ALLEGRO_DIALOG_FUNC(int, al_get_native_file_dialog_count, (const ALLEGRO_FILECHOOSER *dialog));
-ALLEGRO_DIALOG_FUNC(const char *, al_get_native_file_dialog_path, (const ALLEGRO_FILECHOOSER *dialog,
-   size_t index));
-ALLEGRO_DIALOG_FUNC(void, al_destroy_native_file_dialog, (ALLEGRO_FILECHOOSER *dialog));
-
-ALLEGRO_DIALOG_FUNC(int, al_show_native_message_box, (ALLEGRO_DISPLAY *display, char const *title,
-   char const *heading, char const *text, char const *buttons, int flags));
-
-ALLEGRO_DIALOG_FUNC(ALLEGRO_TEXTLOG *, al_open_native_text_log, (char const *title, int flags));
-ALLEGRO_DIALOG_FUNC(void, al_close_native_text_log, (ALLEGRO_TEXTLOG *textlog));
-ALLEGRO_DIALOG_FUNC(void, al_append_native_text_log, (ALLEGRO_TEXTLOG *textlog, char const *format, ...));
-ALLEGRO_DIALOG_FUNC(ALLEGRO_EVENT_SOURCE *, al_get_native_text_log_event_source, (ALLEGRO_TEXTLOG *textlog));
-
-
-ALLEGRO_DIALOG_FUNC(ALLEGRO_MENU *, al_create_menu, (void));
-ALLEGRO_DIALOG_FUNC(ALLEGRO_MENU *, al_create_popup_menu, (void));
-ALLEGRO_DIALOG_FUNC(ALLEGRO_MENU *, al_build_menu, (ALLEGRO_MENU_INFO *info));
-ALLEGRO_DIALOG_FUNC(int, al_append_menu_item, (ALLEGRO_MENU *parent, char const *title, int id, int flags,
-   ALLEGRO_BITMAP *icon, ALLEGRO_MENU *submenu));
-ALLEGRO_DIALOG_FUNC(int, al_insert_menu_item, (ALLEGRO_MENU *parent, int pos, char const *title, int id,
-   int flags, ALLEGRO_BITMAP *icon, ALLEGRO_MENU *submenu));
-ALLEGRO_DIALOG_FUNC(bool, al_remove_menu_item, (ALLEGRO_MENU *menu, int pos));
-ALLEGRO_DIALOG_FUNC(ALLEGRO_MENU *, al_clone_menu, (ALLEGRO_MENU *menu));
-ALLEGRO_DIALOG_FUNC(ALLEGRO_MENU *, al_clone_menu_for_popup, (ALLEGRO_MENU *menu));
-ALLEGRO_DIALOG_FUNC(void, al_destroy_menu, (ALLEGRO_MENU *menu));
-
-
-ALLEGRO_DIALOG_FUNC(const char *, al_get_menu_item_caption, (ALLEGRO_MENU *menu, int pos));
-ALLEGRO_DIALOG_FUNC(void, al_set_menu_item_caption, (ALLEGRO_MENU *menu, int pos, const char *caption));
-ALLEGRO_DIALOG_FUNC(int, al_get_menu_item_flags, (ALLEGRO_MENU *menu, int pos));
-ALLEGRO_DIALOG_FUNC(void, al_set_menu_item_flags, (ALLEGRO_MENU *menu, int pos, int flags));
-ALLEGRO_DIALOG_FUNC(int, al_toggle_menu_item_flags, (ALLEGRO_MENU *menu, int pos, int flags));
-ALLEGRO_DIALOG_FUNC(ALLEGRO_BITMAP *, al_get_menu_item_icon, (ALLEGRO_MENU *menu, int pos));
-ALLEGRO_DIALOG_FUNC(void, al_set_menu_item_icon, (ALLEGRO_MENU *menu, int pos, ALLEGRO_BITMAP *icon));
-
-ALLEGRO_DIALOG_FUNC(ALLEGRO_MENU *, al_find_menu, (ALLEGRO_MENU *haystack, int id));
-ALLEGRO_DIALOG_FUNC(bool, al_find_menu_item, (ALLEGRO_MENU *haystack, int id, ALLEGRO_MENU **menu, int *index));
-
-ALLEGRO_DIALOG_FUNC(ALLEGRO_EVENT_SOURCE *, al_get_default_menu_event_source, (void));
-ALLEGRO_DIALOG_FUNC(ALLEGRO_EVENT_SOURCE *, al_enable_menu_event_source, (ALLEGRO_MENU *menu));
-ALLEGRO_DIALOG_FUNC(void, al_disable_menu_event_source, (ALLEGRO_MENU *menu));
-
-ALLEGRO_DIALOG_FUNC(ALLEGRO_MENU *, al_get_display_menu, (ALLEGRO_DISPLAY *display));
-ALLEGRO_DIALOG_FUNC(bool, al_set_display_menu, (ALLEGRO_DISPLAY *display, ALLEGRO_MENU *menu));
-ALLEGRO_DIALOG_FUNC(bool, al_popup_menu, (ALLEGRO_MENU *popup, ALLEGRO_DISPLAY *display));
-ALLEGRO_DIALOG_FUNC(ALLEGRO_MENU *, al_remove_display_menu, (ALLEGRO_DISPLAY *display));
-
-ALLEGRO_DIALOG_FUNC(uint32_t, al_get_allegro_native_dialog_version, (void));
-
-enum {
-   ALLEGRO_FILECHOOSER_FILE_MUST_EXIST = 1,
-   ALLEGRO_FILECHOOSER_SAVE            = 2,
-   ALLEGRO_FILECHOOSER_FOLDER          = 4,
-   ALLEGRO_FILECHOOSER_PICTURES        = 8,
-   ALLEGRO_FILECHOOSER_SHOW_HIDDEN     = 16,
-   ALLEGRO_FILECHOOSER_MULTIPLE        = 32
-};
-
-enum {
-   ALLEGRO_MESSAGEBOX_WARN             = 1<<0,
-   ALLEGRO_MESSAGEBOX_ERROR            = 1<<1,
-   ALLEGRO_MESSAGEBOX_OK_CANCEL        = 1<<2,
-   ALLEGRO_MESSAGEBOX_YES_NO           = 1<<3,
-   ALLEGRO_MESSAGEBOX_QUESTION         = 1<<4
-};
-
-enum {
-   ALLEGRO_TEXTLOG_NO_CLOSE            = 1<<0,
-   ALLEGRO_TEXTLOG_MONOSPACE           = 1<<1
-};
-
-enum {
-   ALLEGRO_EVENT_NATIVE_DIALOG_CLOSE   = 600,
-   ALLEGRO_EVENT_MENU_CLICK            = 601
-};
-
-enum {
-   ALLEGRO_MENU_ITEM_ENABLED            = 0,
-   ALLEGRO_MENU_ITEM_CHECKBOX           = 1,
-   ALLEGRO_MENU_ITEM_CHECKED            = 2,
-   ALLEGRO_MENU_ITEM_DISABLED           = 4
-};
+func (dialog * FileChooser) Show(display * Display) bool {
+    return bool(C.al_show_native_file_dialog(display.toC(), dialog.toC()))
+}
+
+func (display * Display) ShowNativeFileDialog(dialog * FileChooser) bool {
+    return bool(C.al_show_native_file_dialog(display.toC(), dialog.toC()))
+}
+
+func (dialog *  FileChooser) Count() int {
+    return int(C.al_get_native_file_dialog_count(dialog.toC()))
+}
+
+func (dialog * FileChooser) Path(index int) string {
+    return C.GoString(C.al_get_native_file_dialog_path(dialog.toC(), C.size_t(index)))
+}
+
+
+func (display * Display) ShowNativeMessageBox(title, heading, text, buttons string, flags int) int {
+    ctitle   := cstr(title)     ; defer cstrFree(ctitle)
+    cheading := cstr(heading)   ; defer cstrFree(cheading)
+    ctext    := cstr(text)      ; defer cstrFree(ctext)
+    cbuttons := cstr(buttons)   ; defer cstrFree(cbuttons)
+    
+    return int(C.al_show_native_message_box(display.toC(), ctitle, cheading, ctext, cbuttons, C.int(flags)))
+}
+
+// Creates a native text log.
+func CreateNativeTextLog(title string, flags int) * TextLog {    
+    ctitle   := cstr(title) ; defer cstrFree(ctitle)
+    
+    return wrapTextLog(C.al_open_native_text_log(ctitle, C.int(flags)))
+}
+
+func (log * TextLog) Append(text string) {
+    ctext    := cstr(text) ; defer cstrFree(ctext)
+    C.al_append_native_text_log_wrapper(log.toC(), ctext)
+}
+
+func (log * TextLog) EventSource() * EventSource {
+    return wrapEventSourceRaw(C.al_get_native_text_log_event_source(log.toC()))
+}
+
+func CreateMenu() * Menu {
+    return wrapMenu(C.al_create_menu())
+}
+
+func CreatePopupMenu() * Menu {
+    return wrapMenu(C.al_create_popup_menu())
+}
+
+func BuildMenu(info * MenuInfo) * Menu {
+    return wrapMenu(C.al_build_menu(info.toC()))
+}
+
+func (menu * Menu) AppendItem(title string, id, flags int, icon * Bitmap, submenu * Menu) int {
+    ctitle   := cstr(title)     ; defer cstrFree(ctitle)
+    return int(C.al_append_menu_item(menu.toC(), ctitle, C.uint16_t(id), C.int(flags), icon.toC(), submenu.toC()))
+}
+
+func (menu * Menu) InsertItem(pos int, title string, id, flags int, icon * Bitmap, submenu * Menu) int {
+    ctitle   := cstr(title)     ; defer cstrFree(ctitle)
+    return int(C.al_insert_menu_item(menu.toC(), C.int(pos), ctitle, C.uint16_t(id), C.int(flags), icon.toC(), submenu.toC()))
+}
+
+func (menu * Menu) RemoveItem(position int) bool {    
+    return bool(C.al_remove_menu_item(menu.toC(), C.int(position)))
+}
+
+func (menu * Menu) Clone() * Menu {
+    return wrapMenu(C.al_clone_menu(menu.toC()))
+}
+
+func (menu * Menu) CloneForPopup() * Menu {
+    return wrapMenu(C.al_clone_menu_for_popup(menu.toC()))
+}
+
+func (menu * Menu) Caption(pos int) string {
+    return C.GoString(C.al_get_menu_item_caption(menu.toC(), C.int(pos)))
+}
+
+func (menu * Menu) SetCaption(pos int, caption string) {
+    ccaption  := cstr(caption)     ; defer cstrFree(ccaption)
+    C.al_set_menu_item_caption(menu.toC(), C.int(pos), ccaption)
+}
+
+func (menu * Menu) Flags(pos int) int {
+    return int(C.al_get_menu_item_flags(menu.toC(), C.int(pos)))
+}
+
+func (menu * Menu) SetFlags(pos int, flags int) {    
+    C.al_set_menu_item_flags(menu.toC(), C.int(pos), C.int(flags))
+}
+
+func (menu * Menu) Icon(pos int) * Bitmap {
+    return wrapBitmapRaw(C.al_get_menu_item_icon(menu.toC(), C.int(pos)))
+}
+
+func (menu * Menu) SetIcon(pos int, icon * Bitmap) {    
+    C.al_set_menu_item_icon(menu.toC(), C.int(pos), icon.toC())
+}
+
+
+func (menu * Menu) Find(id int) * Menu {
+    res     := C.al_find_menu(menu.toC(), C.uint16_t(id))
+    return wrapMenuRaw(res)
+} 
+
+
+func (menu * Menu) FindItem(id int) (ok bool, found * Menu, index int) {
+    var cmenu * C.ALLEGRO_MENU = nil
+    var cindex C.int = -1
+    res     := C.al_find_menu_item(menu.toC(), C.uint16_t(id), &cmenu, &cindex)
+    ok      = bool(res)
+    found   = wrapMenuRaw(cmenu)
+    index   = int(cindex)
+    return ok, menu, index
+}
+
+
+func DefaultMenuEventSource() * EventSource {
+    return wrapEventSourceRaw(C.al_get_default_menu_event_source())
+}
+
+func (menu * Menu) EnableEventSource() * EventSource {
+    return wrapEventSourceRaw(C.al_enable_menu_event_source(menu.toC()))
+}
+
+
+func (menu * Menu) DisableEventSource() {
+    C.al_disable_menu_event_source(menu.toC())
+}
+
+func (disp * Display) Menu() * Menu {
+    return wrapMenuRaw(C.al_get_display_menu(disp.toC()))
+}
+
+func (disp * Display) SetMenu(menu * Menu) bool {
+    return bool(C.al_set_display_menu(disp.toC(), menu.toC()))
+}
+
+func (disp * Display) PopupMenu(menu * Menu) bool {
+    return bool(C.al_popup_menu(menu.toC(), disp.toC()))
+}
+
+func (menu * Menu) Popup(disp * Display) bool {
+    return bool(C.al_popup_menu(menu.toC(), disp.toC()))
+}
+
+
+func (disp * Display) RemoveMenu() * Menu {
+    return wrapMenuRaw(C.al_remove_display_menu(disp.toC()))
+}
+
+func NativeDialogVersion() uint32 {
+    return uint32(C.al_get_allegro_native_dialog_version())
+}
 
-*/

+ 3 - 3
al/physfs.go

@@ -15,9 +15,9 @@ import "C"
 
 // Sets up to use the PHYSFS helper to easily read data in zip file .
 func SetPhysfsFileInterface() {
-	C.al_set_physfs_file_interface()
+    C.al_set_physfs_file_interface()
 }
 
-func GetAllegroPhysfsVersion() uint32 {
-	return uint32(C.al_get_allegro_physfs_version())
+func PhysfsVersion() uint32 {
+    return uint32(C.al_get_allegro_physfs_version())
 }

+ 9 - 0
al/primitives.go

@@ -494,6 +494,15 @@ func DrawFilledPolygon(vertices []float32, join LineJoin,  color Color) {
     C.al_draw_filled_polygon((*C.float)(&vertices[0]), C.int(len(vertices)/2), color.toC())
 }
 
+func (vert * Vertex) Init(x, y, z, u, v float32, color Color) {
+    vert.x      = C.float(x)
+    vert.y      = C.float(y)
+    vert.z      = C.float(z)
+    vert.u      = C.float(u)
+    vert.v      = C.float(v)
+    vert.color  = color.toC()
+}
+
 
 var later = `
 /*

+ 53 - 0
al/ttf.go

@@ -0,0 +1,53 @@
+// TTF extension
+package al
+
+/*
+#cgo pkg-config: allegro_ttf-5
+#cgo CFLAGS: -I/usr/local/include
+#cgo linux LDFLAGS: -lc_nonshared
+#include <stdlib.h>
+#include <allegro5/allegro.h>
+#include <allegro5/allegro_ttf.h>
+#include "helpers.h"
+*/
+import "C"
+
+// import "runtime"
+// import "unsafe"
+const (
+    TTF_NO_KERNING = C.ALLEGRO_TTF_NO_KERNING
+    TTF_MONOCHROME = C.ALLEGRO_TTF_MONOCHROME
+    TTF_NO_AUTOHINT= C.ALLEGRO_TTF_NO_AUTOHINT
+)
+
+func LoadTTFFont(filename string, size, flags int) * Font {
+    cfilename := cstr(filename); defer cstrFree(cfilename)
+    return wrapFont(C.al_load_ttf_font(cfilename, C.int(size), C.int(flags)))
+} 
+
+func (file * File) LoadTTFFont(size, flags int) * Font {
+    return wrapFont(C.al_load_ttf_font_f(file.toC(), nil, C.int(size), C.int(flags)))
+} 
+
+func LoadTTFFontStretch(filename string, w, h, flags int) * Font {
+    cfilename := cstr(filename); defer cstrFree(cfilename)
+    return wrapFont(C.al_load_ttf_font_stretch(cfilename,  C.int(w), C.int(h), C.int(flags)))
+} 
+
+func (file * File) LoadTTFFontStretch(w, h, flags int) * Font {
+    return wrapFont(C.al_load_ttf_font_stretch_f(file.toC(), nil, C.int(w), C.int(h), C.int(flags)))
+} 
+
+
+func InitTTFAddon() bool {
+    return bool(C.al_init_ttf_addon())
+}
+
+func ShutdownTTFAddon() {
+    C.al_shutdown_ttf_addon()
+}
+
+func TTFVersion() uint32 {
+    return uint32(C.al_get_allegro_ttf_version())
+}
+

+ 158 - 0
al/video.go

@@ -0,0 +1,158 @@
+// Video extension
+package al
+
+/*
+#cgo pkg-config: allegro_video-5
+#cgo CFLAGS: -I/usr/local/include
+#cgo linux LDFLAGS: -lc_nonshared
+#include <stdlib.h>
+#include <allegro5/allegro.h>
+#include <allegro5/allegro_video.h>
+#include "helpers.h"
+*/
+import "C"
+
+import "runtime"
+// import "unsafe"
+
+type VideoEventType C.enum_ALLEGRO_VIDEO_EVENT_TYPE
+
+const (
+   EVENT_VIDEO_FRAME_SHOW       = VideoEventType(C.ALLEGRO_EVENT_VIDEO_FRAME_SHOW)
+   EVENT_VIDEO_FRAME_FINISHED   = VideoEventType(C.ALLEGRO_EVENT_VIDEO_FINISHED)
+   eVENT_VIDEO_FRAME_FINISHED   = VideoEventType(C._ALLEGRO_EVENT_VIDEO_SEEK)
+)
+
+type VideoPositionType C.ALLEGRO_VIDEO_POSITION_TYPE
+
+const (
+   VIDEO_POSITION_ACTUAL       = VideoPositionType(C.ALLEGRO_VIDEO_POSITION_ACTUAL)
+   VIDEO_POSITION_VIDEO_DECODE = VideoPositionType(C.ALLEGRO_VIDEO_POSITION_VIDEO_DECODE)
+   VIDEO_POSITION_AUDIO_DECODE = VideoPositionType(C.ALLEGRO_VIDEO_POSITION_AUDIO_DECODE)
+)
+
+type Video struct {
+    handle * C.ALLEGRO_VIDEO
+}
+
+// Converts a video to it's underlying C pointer
+func (self * Video) toC() *C.ALLEGRO_VIDEO {
+    return (*C.ALLEGRO_VIDEO)(self.handle)
+}
+
+// Destroys the video.
+func (self *Video) Destroy() {
+    if self.handle != nil {
+        C.al_close_video(self.toC())
+    }
+    self.handle = nil
+}
+
+// Wraps a C video into a go video
+func wrapVideoRaw(data *C.ALLEGRO_VIDEO) *Video {
+    if data == nil {
+        return nil
+    }
+    return &Video{data}
+}
+
+// Sets up a finalizer for this Video that calls Destroy()
+func (self *Video) SetDestroyFinalizer() *Video {
+    if self != nil {
+        runtime.SetFinalizer(self, func(me *Video) { me.Destroy() })
+    }
+    return self
+}
+
+// Wraps a C video into a go video and sets up a finalizer that calls Destroy()
+func wrapVideo(data *C.ALLEGRO_VIDEO) *Video {
+    self := wrapVideoRaw(data)
+    return self.SetDestroyFinalizer()
+}
+
+
+func OpenVideo(filename string) * Video {
+    cfilename := cstr(filename) ; defer cstrFree(cfilename)
+    return wrapVideo(C.al_open_video(cfilename)) 
+}
+
+func (video * Video) Close() {
+    video.Destroy()
+}
+
+func (video * Video) Start(mixer * Mixer) {
+    C.al_start_video(video.toC(), mixer.toC())
+}
+
+func (video * Video) StartWithVoice(voice * Voice) {
+    C.al_start_video_with_voice(video.toC(), voice.toC())
+}
+
+func (video * Video) EventSource() * EventSource {
+    return wrapEventSourceRaw(C.al_get_video_event_source(video.toC()))
+} 
+
+func (video * Video) SetPlaying(playing bool) {
+    C.al_set_video_playing(video.toC(), C.bool(playing))
+} 
+
+func (video * Video) Playing() bool {
+    return bool(C.al_is_video_playing(video.toC()))
+} 
+
+func (video * Video) AudioRate() float64 {
+    return float64(C.al_get_video_audio_rate(video.toC()))
+}
+
+func (video * Video) FPS() float64 {
+    return float64(C.al_get_video_fps(video.toC()))
+}
+
+func (video * Video) ScaledWidth() float32 {
+    return float32(C.al_get_video_scaled_width(video.toC()))
+} 
+
+func (video * Video) ScaledHeight() float32 {
+    return float32(C.al_get_video_scaled_height(video.toC()))
+}
+
+func (video * Video) Frame() * Bitmap {
+    return wrapBitmapRaw(C.al_get_video_frame(video.toC()))
+}
+
+func (vpt VideoPositionType) toC() C.ALLEGRO_VIDEO_POSITION_TYPE {
+    return C.ALLEGRO_VIDEO_POSITION_TYPE(vpt)
+}
+
+func (video * Video) Position(vpt VideoPositionType) float64 {
+    return float64(C.al_get_video_position(video.toC(), vpt.toC()))    
+}
+
+
+func (video * Video) ActualPosition(vpt VideoPositionType) float64 {
+    return video.Position(VIDEO_POSITION_ACTUAL) 
+}
+
+func (video * Video) AudioDecodePosition(vpt VideoPositionType) float64 {
+    return video.Position(VIDEO_POSITION_AUDIO_DECODE) 
+}
+
+func (video * Video) VideoDecodePosition(vpt VideoPositionType) float64 {
+    return video.Position(VIDEO_POSITION_VIDEO_DECODE) 
+}
+
+func (video * Video) Seek(position_in_seconds float64) bool {
+    return bool(C.al_seek_video(video.toC(), C.double(position_in_seconds)))    
+}
+
+func InitVideoAddon() bool {
+    return bool(C.al_init_video_addon())
+}
+
+func ShutdownVideoAddon() {
+    C.al_shutdown_video_addon()
+}
+
+func VideoVersion() uint32 {
+    return uint32(C.al_get_allegro_video_version())
+}